diff --git a/Ryujinx.Tests.Unicorn/Native/Arm32Register.cs b/Ryujinx.Tests.Unicorn/Native/Arm32Register.cs deleted file mode 100644 index 419f8e4d9..000000000 --- a/Ryujinx.Tests.Unicorn/Native/Arm32Register.cs +++ /dev/null @@ -1,135 +0,0 @@ -namespace Ryujinx.Tests.Unicorn.Native -{ - public enum Arm32Register - { - INVALID = 0, - - APSR, - APSR_NZCV, - CPSR, - FPEXC, - FPINST, - FPSCR, - FPSCR_NZCV, - FPSID, - ITSTATE, - LR, - PC, - SP, - SPSR, - D0, - D1, - D2, - D3, - D4, - D5, - D6, - D7, - D8, - D9, - D10, - D11, - D12, - D13, - D14, - D15, - D16, - D17, - D18, - D19, - D20, - D21, - D22, - D23, - D24, - D25, - D26, - D27, - D28, - D29, - D30, - D31, - FPINST2, - MVFR0, - MVFR1, - MVFR2, - Q0, - Q1, - Q2, - Q3, - Q4, - Q5, - Q6, - Q7, - Q8, - Q9, - Q10, - Q11, - Q12, - Q13, - Q14, - Q15, - R0, - R1, - R2, - R3, - R4, - R5, - R6, - R7, - R8, - R9, - R10, - R11, - R12, - S0, - S1, - S2, - S3, - S4, - S5, - S6, - S7, - S8, - S9, - S10, - S11, - S12, - S13, - S14, - S15, - S16, - S17, - S18, - S19, - S20, - S21, - S22, - S23, - S24, - S25, - S26, - S27, - S28, - S29, - S30, - S31, - C1_C0_2, - C13_C0_2, - C13_C0_3, - IPSR, - MSP, - PSP, - CONTROL, - ENDING, - - // Alias registers. - R13 = SP, - R14 = LR, - R15 = PC, - SB = R9, - SL = R10, - FP = R11, - IP = R12, - } -} diff --git a/Ryujinx.Tests.Unicorn/Native/ArmRegister.cs b/Ryujinx.Tests.Unicorn/Native/ArmRegister.cs deleted file mode 100644 index af331bd1c..000000000 --- a/Ryujinx.Tests.Unicorn/Native/ArmRegister.cs +++ /dev/null @@ -1,295 +0,0 @@ -// ReSharper disable InconsistentNaming -namespace Ryujinx.Tests.Unicorn.Native -{ - public enum ArmRegister - { - INVALID = 0, - - X29, - X30, - NZCV, - SP, - WSP, - WZR, - XZR, - B0, - B1, - B2, - B3, - B4, - B5, - B6, - B7, - B8, - B9, - B10, - B11, - B12, - B13, - B14, - B15, - B16, - B17, - B18, - B19, - B20, - B21, - B22, - B23, - B24, - B25, - B26, - B27, - B28, - B29, - B30, - B31, - D0, - D1, - D2, - D3, - D4, - D5, - D6, - D7, - D8, - D9, - D10, - D11, - D12, - D13, - D14, - D15, - D16, - D17, - D18, - D19, - D20, - D21, - D22, - D23, - D24, - D25, - D26, - D27, - D28, - D29, - D30, - D31, - H0, - H1, - H2, - H3, - H4, - H5, - H6, - H7, - H8, - H9, - H10, - H11, - H12, - H13, - H14, - H15, - H16, - H17, - H18, - H19, - H20, - H21, - H22, - H23, - H24, - H25, - H26, - H27, - H28, - H29, - H30, - H31, - Q0, - Q1, - Q2, - Q3, - Q4, - Q5, - Q6, - Q7, - Q8, - Q9, - Q10, - Q11, - Q12, - Q13, - Q14, - Q15, - Q16, - Q17, - Q18, - Q19, - Q20, - Q21, - Q22, - Q23, - Q24, - Q25, - Q26, - Q27, - Q28, - Q29, - Q30, - Q31, - S0, - S1, - S2, - S3, - S4, - S5, - S6, - S7, - S8, - S9, - S10, - S11, - S12, - S13, - S14, - S15, - S16, - S17, - S18, - S19, - S20, - S21, - S22, - S23, - S24, - S25, - S26, - S27, - S28, - S29, - S30, - S31, - W0, - W1, - W2, - W3, - W4, - W5, - W6, - W7, - W8, - W9, - W10, - W11, - W12, - W13, - W14, - W15, - W16, - W17, - W18, - W19, - W20, - W21, - W22, - W23, - W24, - W25, - W26, - W27, - W28, - W29, - W30, - X0, - X1, - X2, - X3, - X4, - X5, - X6, - X7, - X8, - X9, - X10, - X11, - X12, - X13, - X14, - X15, - X16, - X17, - X18, - X19, - X20, - X21, - X22, - X23, - X24, - X25, - X26, - X27, - X28, - - V0, - V1, - V2, - V3, - V4, - V5, - V6, - V7, - V8, - V9, - V10, - V11, - V12, - V13, - V14, - V15, - V16, - V17, - V18, - V19, - V20, - V21, - V22, - V23, - V24, - V25, - V26, - V27, - V28, - V29, - V30, - V31, - - // > pseudo registers - PC, // program counter register - - CPACR_EL1, - ESR, - - // > thread registers - TPIDR_EL0, - TPIDRRO_EL0, - TPIDR_EL1, - - PSTATE, // PSTATE pseudoregister - - // > floating point control and status registers - FPCR, - FPSR, - - ENDING, // <-- mark the end of the list of registers - - // > alias registers - - IP0 = X16, - IP1 = X17, - FP = X29, - LR = X30, - } -} diff --git a/Ryujinx.Tests.Unicorn/Native/Const/Arch.cs b/Ryujinx.Tests.Unicorn/Native/Const/Arch.cs new file mode 100644 index 000000000..f614d091b --- /dev/null +++ b/Ryujinx.Tests.Unicorn/Native/Const/Arch.cs @@ -0,0 +1,20 @@ +// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT + +// ReSharper disable InconsistentNaming +namespace Ryujinx.Tests.Unicorn.Native.Const +{ + public enum Arch + { + ARM = 1, + ARM64 = 2, + MIPS = 3, + X86 = 4, + PPC = 5, + SPARC = 6, + M68K = 7, + RISCV = 8, + S390X = 9, + TRICORE = 10, + MAX = 11, + } +} diff --git a/Ryujinx.Tests.Unicorn/Native/Const/Arm.cs b/Ryujinx.Tests.Unicorn/Native/Const/Arm.cs new file mode 100644 index 000000000..4b7b3d6f3 --- /dev/null +++ b/Ryujinx.Tests.Unicorn/Native/Const/Arm.cs @@ -0,0 +1,200 @@ +// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT + +// ReSharper disable InconsistentNaming +namespace Ryujinx.Tests.Unicorn.Native.Const +{ + public enum Arm + { + + // ARM CPU + + CPU_ARM_926 = 0, + CPU_ARM_946 = 1, + CPU_ARM_1026 = 2, + CPU_ARM_1136_R2 = 3, + CPU_ARM_1136 = 4, + CPU_ARM_1176 = 5, + CPU_ARM_11MPCORE = 6, + CPU_ARM_CORTEX_M0 = 7, + CPU_ARM_CORTEX_M3 = 8, + CPU_ARM_CORTEX_M4 = 9, + CPU_ARM_CORTEX_M7 = 10, + CPU_ARM_CORTEX_M33 = 11, + CPU_ARM_CORTEX_R5 = 12, + CPU_ARM_CORTEX_R5F = 13, + CPU_ARM_CORTEX_A7 = 14, + CPU_ARM_CORTEX_A8 = 15, + CPU_ARM_CORTEX_A9 = 16, + CPU_ARM_CORTEX_A15 = 17, + CPU_ARM_TI925T = 18, + CPU_ARM_SA1100 = 19, + CPU_ARM_SA1110 = 20, + CPU_ARM_PXA250 = 21, + CPU_ARM_PXA255 = 22, + CPU_ARM_PXA260 = 23, + CPU_ARM_PXA261 = 24, + CPU_ARM_PXA262 = 25, + CPU_ARM_PXA270 = 26, + CPU_ARM_PXA270A0 = 27, + CPU_ARM_PXA270A1 = 28, + CPU_ARM_PXA270B0 = 29, + CPU_ARM_PXA270B1 = 30, + CPU_ARM_PXA270C0 = 31, + CPU_ARM_PXA270C5 = 32, + CPU_ARM_MAX = 33, + CPU_ARM_ENDING = 34, + + // ARM registers + + REG_INVALID = 0, + REG_APSR = 1, + REG_APSR_NZCV = 2, + REG_CPSR = 3, + REG_FPEXC = 4, + REG_FPINST = 5, + REG_FPSCR = 6, + REG_FPSCR_NZCV = 7, + REG_FPSID = 8, + REG_ITSTATE = 9, + REG_LR = 10, + REG_PC = 11, + REG_SP = 12, + REG_SPSR = 13, + REG_D0 = 14, + REG_D1 = 15, + REG_D2 = 16, + REG_D3 = 17, + REG_D4 = 18, + REG_D5 = 19, + REG_D6 = 20, + REG_D7 = 21, + REG_D8 = 22, + REG_D9 = 23, + REG_D10 = 24, + REG_D11 = 25, + REG_D12 = 26, + REG_D13 = 27, + REG_D14 = 28, + REG_D15 = 29, + REG_D16 = 30, + REG_D17 = 31, + REG_D18 = 32, + REG_D19 = 33, + REG_D20 = 34, + REG_D21 = 35, + REG_D22 = 36, + REG_D23 = 37, + REG_D24 = 38, + REG_D25 = 39, + REG_D26 = 40, + REG_D27 = 41, + REG_D28 = 42, + REG_D29 = 43, + REG_D30 = 44, + REG_D31 = 45, + REG_FPINST2 = 46, + REG_MVFR0 = 47, + REG_MVFR1 = 48, + REG_MVFR2 = 49, + REG_Q0 = 50, + REG_Q1 = 51, + REG_Q2 = 52, + REG_Q3 = 53, + REG_Q4 = 54, + REG_Q5 = 55, + REG_Q6 = 56, + REG_Q7 = 57, + REG_Q8 = 58, + REG_Q9 = 59, + REG_Q10 = 60, + REG_Q11 = 61, + REG_Q12 = 62, + REG_Q13 = 63, + REG_Q14 = 64, + REG_Q15 = 65, + REG_R0 = 66, + REG_R1 = 67, + REG_R2 = 68, + REG_R3 = 69, + REG_R4 = 70, + REG_R5 = 71, + REG_R6 = 72, + REG_R7 = 73, + REG_R8 = 74, + REG_R9 = 75, + REG_R10 = 76, + REG_R11 = 77, + REG_R12 = 78, + REG_S0 = 79, + REG_S1 = 80, + REG_S2 = 81, + REG_S3 = 82, + REG_S4 = 83, + REG_S5 = 84, + REG_S6 = 85, + REG_S7 = 86, + REG_S8 = 87, + REG_S9 = 88, + REG_S10 = 89, + REG_S11 = 90, + REG_S12 = 91, + REG_S13 = 92, + REG_S14 = 93, + REG_S15 = 94, + REG_S16 = 95, + REG_S17 = 96, + REG_S18 = 97, + REG_S19 = 98, + REG_S20 = 99, + REG_S21 = 100, + REG_S22 = 101, + REG_S23 = 102, + REG_S24 = 103, + REG_S25 = 104, + REG_S26 = 105, + REG_S27 = 106, + REG_S28 = 107, + REG_S29 = 108, + REG_S30 = 109, + REG_S31 = 110, + REG_C1_C0_2 = 111, + REG_C13_C0_2 = 112, + REG_C13_C0_3 = 113, + REG_IPSR = 114, + REG_MSP = 115, + REG_PSP = 116, + REG_CONTROL = 117, + REG_IAPSR = 118, + REG_EAPSR = 119, + REG_XPSR = 120, + REG_EPSR = 121, + REG_IEPSR = 122, + REG_PRIMASK = 123, + REG_BASEPRI = 124, + REG_BASEPRI_MAX = 125, + REG_FAULTMASK = 126, + REG_APSR_NZCVQ = 127, + REG_APSR_G = 128, + REG_APSR_NZCVQG = 129, + REG_IAPSR_NZCVQ = 130, + REG_IAPSR_G = 131, + REG_IAPSR_NZCVQG = 132, + REG_EAPSR_NZCVQ = 133, + REG_EAPSR_G = 134, + REG_EAPSR_NZCVQG = 135, + REG_XPSR_NZCVQ = 136, + REG_XPSR_G = 137, + REG_XPSR_NZCVQG = 138, + REG_CP_REG = 139, + REG_ENDING = 140, + + // alias registers + REG_R13 = 12, + REG_R14 = 10, + REG_R15 = 11, + REG_SB = 75, + REG_SL = 76, + REG_FP = 77, + REG_IP = 78, + } +} diff --git a/Ryujinx.Tests.Unicorn/Native/Const/Arm64.cs b/Ryujinx.Tests.Unicorn/Native/Const/Arm64.cs new file mode 100644 index 000000000..11344557b --- /dev/null +++ b/Ryujinx.Tests.Unicorn/Native/Const/Arm64.cs @@ -0,0 +1,341 @@ +// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT + +// ReSharper disable InconsistentNaming +namespace Ryujinx.Tests.Unicorn.Native.Const +{ + public enum Arm64 + { + + // ARM64 CPU + + CPU_ARM64_A57 = 0, + CPU_ARM64_A53 = 1, + CPU_ARM64_A72 = 2, + CPU_ARM64_MAX = 3, + CPU_ARM64_ENDING = 4, + + // ARM64 registers + + REG_INVALID = 0, + REG_X29 = 1, + REG_X30 = 2, + REG_NZCV = 3, + REG_SP = 4, + REG_WSP = 5, + REG_WZR = 6, + REG_XZR = 7, + REG_B0 = 8, + REG_B1 = 9, + REG_B2 = 10, + REG_B3 = 11, + REG_B4 = 12, + REG_B5 = 13, + REG_B6 = 14, + REG_B7 = 15, + REG_B8 = 16, + REG_B9 = 17, + REG_B10 = 18, + REG_B11 = 19, + REG_B12 = 20, + REG_B13 = 21, + REG_B14 = 22, + REG_B15 = 23, + REG_B16 = 24, + REG_B17 = 25, + REG_B18 = 26, + REG_B19 = 27, + REG_B20 = 28, + REG_B21 = 29, + REG_B22 = 30, + REG_B23 = 31, + REG_B24 = 32, + REG_B25 = 33, + REG_B26 = 34, + REG_B27 = 35, + REG_B28 = 36, + REG_B29 = 37, + REG_B30 = 38, + REG_B31 = 39, + REG_D0 = 40, + REG_D1 = 41, + REG_D2 = 42, + REG_D3 = 43, + REG_D4 = 44, + REG_D5 = 45, + REG_D6 = 46, + REG_D7 = 47, + REG_D8 = 48, + REG_D9 = 49, + REG_D10 = 50, + REG_D11 = 51, + REG_D12 = 52, + REG_D13 = 53, + REG_D14 = 54, + REG_D15 = 55, + REG_D16 = 56, + REG_D17 = 57, + REG_D18 = 58, + REG_D19 = 59, + REG_D20 = 60, + REG_D21 = 61, + REG_D22 = 62, + REG_D23 = 63, + REG_D24 = 64, + REG_D25 = 65, + REG_D26 = 66, + REG_D27 = 67, + REG_D28 = 68, + REG_D29 = 69, + REG_D30 = 70, + REG_D31 = 71, + REG_H0 = 72, + REG_H1 = 73, + REG_H2 = 74, + REG_H3 = 75, + REG_H4 = 76, + REG_H5 = 77, + REG_H6 = 78, + REG_H7 = 79, + REG_H8 = 80, + REG_H9 = 81, + REG_H10 = 82, + REG_H11 = 83, + REG_H12 = 84, + REG_H13 = 85, + REG_H14 = 86, + REG_H15 = 87, + REG_H16 = 88, + REG_H17 = 89, + REG_H18 = 90, + REG_H19 = 91, + REG_H20 = 92, + REG_H21 = 93, + REG_H22 = 94, + REG_H23 = 95, + REG_H24 = 96, + REG_H25 = 97, + REG_H26 = 98, + REG_H27 = 99, + REG_H28 = 100, + REG_H29 = 101, + REG_H30 = 102, + REG_H31 = 103, + REG_Q0 = 104, + REG_Q1 = 105, + REG_Q2 = 106, + REG_Q3 = 107, + REG_Q4 = 108, + REG_Q5 = 109, + REG_Q6 = 110, + REG_Q7 = 111, + REG_Q8 = 112, + REG_Q9 = 113, + REG_Q10 = 114, + REG_Q11 = 115, + REG_Q12 = 116, + REG_Q13 = 117, + REG_Q14 = 118, + REG_Q15 = 119, + REG_Q16 = 120, + REG_Q17 = 121, + REG_Q18 = 122, + REG_Q19 = 123, + REG_Q20 = 124, + REG_Q21 = 125, + REG_Q22 = 126, + REG_Q23 = 127, + REG_Q24 = 128, + REG_Q25 = 129, + REG_Q26 = 130, + REG_Q27 = 131, + REG_Q28 = 132, + REG_Q29 = 133, + REG_Q30 = 134, + REG_Q31 = 135, + REG_S0 = 136, + REG_S1 = 137, + REG_S2 = 138, + REG_S3 = 139, + REG_S4 = 140, + REG_S5 = 141, + REG_S6 = 142, + REG_S7 = 143, + REG_S8 = 144, + REG_S9 = 145, + REG_S10 = 146, + REG_S11 = 147, + REG_S12 = 148, + REG_S13 = 149, + REG_S14 = 150, + REG_S15 = 151, + REG_S16 = 152, + REG_S17 = 153, + REG_S18 = 154, + REG_S19 = 155, + REG_S20 = 156, + REG_S21 = 157, + REG_S22 = 158, + REG_S23 = 159, + REG_S24 = 160, + REG_S25 = 161, + REG_S26 = 162, + REG_S27 = 163, + REG_S28 = 164, + REG_S29 = 165, + REG_S30 = 166, + REG_S31 = 167, + REG_W0 = 168, + REG_W1 = 169, + REG_W2 = 170, + REG_W3 = 171, + REG_W4 = 172, + REG_W5 = 173, + REG_W6 = 174, + REG_W7 = 175, + REG_W8 = 176, + REG_W9 = 177, + REG_W10 = 178, + REG_W11 = 179, + REG_W12 = 180, + REG_W13 = 181, + REG_W14 = 182, + REG_W15 = 183, + REG_W16 = 184, + REG_W17 = 185, + REG_W18 = 186, + REG_W19 = 187, + REG_W20 = 188, + REG_W21 = 189, + REG_W22 = 190, + REG_W23 = 191, + REG_W24 = 192, + REG_W25 = 193, + REG_W26 = 194, + REG_W27 = 195, + REG_W28 = 196, + REG_W29 = 197, + REG_W30 = 198, + REG_X0 = 199, + REG_X1 = 200, + REG_X2 = 201, + REG_X3 = 202, + REG_X4 = 203, + REG_X5 = 204, + REG_X6 = 205, + REG_X7 = 206, + REG_X8 = 207, + REG_X9 = 208, + REG_X10 = 209, + REG_X11 = 210, + REG_X12 = 211, + REG_X13 = 212, + REG_X14 = 213, + REG_X15 = 214, + REG_X16 = 215, + REG_X17 = 216, + REG_X18 = 217, + REG_X19 = 218, + REG_X20 = 219, + REG_X21 = 220, + REG_X22 = 221, + REG_X23 = 222, + REG_X24 = 223, + REG_X25 = 224, + REG_X26 = 225, + REG_X27 = 226, + REG_X28 = 227, + REG_V0 = 228, + REG_V1 = 229, + REG_V2 = 230, + REG_V3 = 231, + REG_V4 = 232, + REG_V5 = 233, + REG_V6 = 234, + REG_V7 = 235, + REG_V8 = 236, + REG_V9 = 237, + REG_V10 = 238, + REG_V11 = 239, + REG_V12 = 240, + REG_V13 = 241, + REG_V14 = 242, + REG_V15 = 243, + REG_V16 = 244, + REG_V17 = 245, + REG_V18 = 246, + REG_V19 = 247, + REG_V20 = 248, + REG_V21 = 249, + REG_V22 = 250, + REG_V23 = 251, + REG_V24 = 252, + REG_V25 = 253, + REG_V26 = 254, + REG_V27 = 255, + REG_V28 = 256, + REG_V29 = 257, + REG_V30 = 258, + REG_V31 = 259, + + // pseudo registers + REG_PC = 260, + REG_CPACR_EL1 = 261, + + // thread registers, depreciated, use UC_ARM64_REG_CP_REG instead + REG_TPIDR_EL0 = 262, + REG_TPIDRRO_EL0 = 263, + REG_TPIDR_EL1 = 264, + REG_PSTATE = 265, + + // exception link registers, depreciated, use UC_ARM64_REG_CP_REG instead + REG_ELR_EL0 = 266, + REG_ELR_EL1 = 267, + REG_ELR_EL2 = 268, + REG_ELR_EL3 = 269, + + // stack pointers registers, depreciated, use UC_ARM64_REG_CP_REG instead + REG_SP_EL0 = 270, + REG_SP_EL1 = 271, + REG_SP_EL2 = 272, + REG_SP_EL3 = 273, + + // other CP15 registers, depreciated, use UC_ARM64_REG_CP_REG instead + REG_TTBR0_EL1 = 274, + REG_TTBR1_EL1 = 275, + REG_ESR_EL0 = 276, + REG_ESR_EL1 = 277, + REG_ESR_EL2 = 278, + REG_ESR_EL3 = 279, + REG_FAR_EL0 = 280, + REG_FAR_EL1 = 281, + REG_FAR_EL2 = 282, + REG_FAR_EL3 = 283, + REG_PAR_EL1 = 284, + REG_MAIR_EL1 = 285, + REG_VBAR_EL0 = 286, + REG_VBAR_EL1 = 287, + REG_VBAR_EL2 = 288, + REG_VBAR_EL3 = 289, + REG_CP_REG = 290, + + // floating point control and status registers + REG_FPCR = 291, + REG_FPSR = 292, + REG_ENDING = 293, + + // alias registers + REG_IP0 = 215, + REG_IP1 = 216, + REG_FP = 1, + REG_LR = 2, + + // ARM64 instructions + + INS_INVALID = 0, + INS_MRS = 1, + INS_MSR = 2, + INS_SYS = 3, + INS_SYSL = 4, + INS_ENDING = 5, + } +} diff --git a/Ryujinx.Tests.Unicorn/Native/Const/Common.cs b/Ryujinx.Tests.Unicorn/Native/Const/Common.cs new file mode 100644 index 000000000..e4b59a489 --- /dev/null +++ b/Ryujinx.Tests.Unicorn/Native/Const/Common.cs @@ -0,0 +1,44 @@ +// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT + +// ReSharper disable InconsistentNaming +namespace Ryujinx.Tests.Unicorn.Native.Const +{ + public enum Common + { + API_MAJOR = 2, + + API_MINOR = 0, + + API_PATCH = 0, + API_EXTRA = 255, + VERSION_MAJOR = 2, + + VERSION_MINOR = 0, + + VERSION_PATCH = 0, + VERSION_EXTRA = 255, + SECOND_SCALE = 1000000, + MILISECOND_SCALE = 1000, + QUERY_MODE = 1, + QUERY_PAGE_SIZE = 2, + QUERY_ARCH = 3, + QUERY_TIMEOUT = 4, + + CTL_IO_NONE = 0, + CTL_IO_WRITE = 1, + CTL_IO_READ = 2, + CTL_IO_READ_WRITE = 3, + + CTL_UC_MODE = 0, + CTL_UC_PAGE_SIZE = 1, + CTL_UC_ARCH = 2, + CTL_UC_TIMEOUT = 3, + CTL_UC_USE_EXITS = 4, + CTL_UC_EXITS_CNT = 5, + CTL_UC_EXITS = 6, + CTL_CPU_MODEL = 7, + CTL_TB_REQUEST_CACHE = 8, + CTL_TB_REMOVE_CACHE = 9, + CTL_TB_FLUSH = 10, + } +} diff --git a/Ryujinx.Tests.Unicorn/Native/Const/Error.cs b/Ryujinx.Tests.Unicorn/Native/Const/Error.cs new file mode 100644 index 000000000..9cedb0fcc --- /dev/null +++ b/Ryujinx.Tests.Unicorn/Native/Const/Error.cs @@ -0,0 +1,31 @@ +// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT + +// ReSharper disable InconsistentNaming +namespace Ryujinx.Tests.Unicorn.Native.Const +{ + public enum Error + { + OK = 0, + NOMEM = 1, + ARCH = 2, + HANDLE = 3, + MODE = 4, + VERSION = 5, + READ_UNMAPPED = 6, + WRITE_UNMAPPED = 7, + FETCH_UNMAPPED = 8, + HOOK = 9, + INSN_INVALID = 10, + MAP = 11, + WRITE_PROT = 12, + READ_PROT = 13, + FETCH_PROT = 14, + ARG = 15, + READ_UNALIGNED = 16, + WRITE_UNALIGNED = 17, + FETCH_UNALIGNED = 18, + HOOK_EXIST = 19, + RESOURCE = 20, + EXCEPTION = 21, + } +} diff --git a/Ryujinx.Tests.Unicorn/Native/Const/Hook.cs b/Ryujinx.Tests.Unicorn/Native/Const/Hook.cs new file mode 100644 index 000000000..a6b9dca6e --- /dev/null +++ b/Ryujinx.Tests.Unicorn/Native/Const/Hook.cs @@ -0,0 +1,33 @@ +// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT + +// ReSharper disable InconsistentNaming +namespace Ryujinx.Tests.Unicorn.Native.Const +{ + public enum Hook + { + INTR = 1, + INSN = 2, + CODE = 4, + BLOCK = 8, + MEM_READ_UNMAPPED = 16, + MEM_WRITE_UNMAPPED = 32, + MEM_FETCH_UNMAPPED = 64, + MEM_READ_PROT = 128, + MEM_WRITE_PROT = 256, + MEM_FETCH_PROT = 512, + MEM_READ = 1024, + MEM_WRITE = 2048, + MEM_FETCH = 4096, + MEM_READ_AFTER = 8192, + INSN_INVALID = 16384, + EDGE_GENERATED = 32768, + TCG_OPCODE = 65536, + MEM_UNMAPPED = 112, + MEM_PROT = 896, + MEM_READ_INVALID = 144, + MEM_WRITE_INVALID = 288, + MEM_FETCH_INVALID = 576, + MEM_INVALID = 1008, + MEM_VALID = 7168, + } +} diff --git a/Ryujinx.Tests.Unicorn/Native/Const/Memory.cs b/Ryujinx.Tests.Unicorn/Native/Const/Memory.cs new file mode 100644 index 000000000..a7d60e611 --- /dev/null +++ b/Ryujinx.Tests.Unicorn/Native/Const/Memory.cs @@ -0,0 +1,19 @@ +// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT + +// ReSharper disable InconsistentNaming +namespace Ryujinx.Tests.Unicorn.Native.Const +{ + public enum Memory + { + READ = 16, + WRITE = 17, + FETCH = 18, + READ_UNMAPPED = 19, + WRITE_UNMAPPED = 20, + FETCH_UNMAPPED = 21, + WRITE_PROT = 22, + READ_PROT = 23, + FETCH_PROT = 24, + READ_AFTER = 25, + } +} diff --git a/Ryujinx.Tests.Unicorn/Native/Const/Mode.cs b/Ryujinx.Tests.Unicorn/Native/Const/Mode.cs new file mode 100644 index 000000000..804d01a97 --- /dev/null +++ b/Ryujinx.Tests.Unicorn/Native/Const/Mode.cs @@ -0,0 +1,35 @@ +// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT + +// ReSharper disable InconsistentNaming +namespace Ryujinx.Tests.Unicorn.Native.Const +{ + public enum Mode + { + LITTLE_ENDIAN = 0, + BIG_ENDIAN = 1073741824, + ARM = 0, + THUMB = 16, + MCLASS = 32, + V8 = 64, + ARMBE8 = 1024, + ARM926 = 128, + ARM946 = 256, + ARM1176 = 512, + MICRO = 16, + MIPS3 = 32, + MIPS32R6 = 64, + MIPS32 = 4, + MIPS64 = 8, + MODE_16 = 2, + MODE_32 = 4, + MODE_64 = 8, + PPC32 = 4, + PPC64 = 8, + QPX = 16, + SPARC32 = 4, + SPARC64 = 8, + V9 = 16, + RISCV32 = 4, + RISCV64 = 8, + } +} diff --git a/Ryujinx.Tests.Unicorn/Native/Const/Permission.cs b/Ryujinx.Tests.Unicorn/Native/Const/Permission.cs new file mode 100644 index 000000000..19ddc4f27 --- /dev/null +++ b/Ryujinx.Tests.Unicorn/Native/Const/Permission.cs @@ -0,0 +1,14 @@ +// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT + +// ReSharper disable InconsistentNaming +namespace Ryujinx.Tests.Unicorn.Native.Const +{ + public enum Permission + { + NONE = 0, + READ = 1, + WRITE = 2, + EXEC = 4, + ALL = 7, + } +} diff --git a/Ryujinx.Tests.Unicorn/Native/Const/TCG.cs b/Ryujinx.Tests.Unicorn/Native/Const/TCG.cs new file mode 100644 index 000000000..f38785db7 --- /dev/null +++ b/Ryujinx.Tests.Unicorn/Native/Const/TCG.cs @@ -0,0 +1,12 @@ +// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT + +// ReSharper disable InconsistentNaming +namespace Ryujinx.Tests.Unicorn.Native.Const +{ + public enum TCG + { + OP_SUB = 0, + OP_FLAG_CMP = 1, + OP_FLAG_DIRECT = 2, + } +} diff --git a/Ryujinx.Tests.Unicorn/Native/Interface.cs b/Ryujinx.Tests.Unicorn/Native/Interface.cs index 59b1da079..0ecda22ea 100644 --- a/Ryujinx.Tests.Unicorn/Native/Interface.cs +++ b/Ryujinx.Tests.Unicorn/Native/Interface.cs @@ -1,13 +1,43 @@ +using Ryujinx.Tests.Unicorn.Native.Const; using System; +using System.IO; +using System.Reflection; using System.Runtime.InteropServices; namespace Ryujinx.Tests.Unicorn.Native { - public class Interface + public static class Interface { - public static void Checked(UnicornError error) + public static bool IsUnicornAvailable { get; private set; } = true; + + private static IntPtr ImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath) { - if (error != UnicornError.UC_ERR_OK) + if (libraryName == "unicorn") + { + string loadPath = $"{Path.GetDirectoryName(assembly.Location)}/"; + loadPath += OperatingSystem.IsWindows() ? $"{libraryName}.dll" : $"lib{libraryName}.so"; + + if (!NativeLibrary.TryLoad(loadPath, out IntPtr libraryPtr)) + { + IsUnicornAvailable = false; + Console.Error.WriteLine($"ERROR: Could not find unicorn at: {loadPath}"); + } + + return libraryPtr; + } + + // Otherwise, fallback to default import resolver. + return IntPtr.Zero; + } + + static Interface() + { + NativeLibrary.SetDllImportResolver(Assembly.GetExecutingAssembly(), ImportResolver); + } + + public static void Checked(Error error) + { + if (error != Error.OK) { throw new UnicornException(error); } @@ -31,39 +61,39 @@ namespace Ryujinx.Tests.Unicorn.Native public static extern uint uc_version(out uint major, out uint minor); [DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)] - public static extern UnicornError uc_open(UnicornArch arch, UnicornMode mode, out IntPtr uc); + public static extern Error uc_open(Arch arch, Mode mode, out IntPtr uc); [DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)] - public static extern UnicornError uc_close(IntPtr uc); + public static extern Error uc_close(IntPtr uc); [DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)] - public static extern IntPtr uc_strerror(UnicornError err); + public static extern IntPtr uc_strerror(Error err); [DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)] - public static extern UnicornError uc_reg_write(IntPtr uc, int regid, byte[] value); + public static extern Error uc_reg_write(IntPtr uc, int regid, byte[] value); [DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)] - public static extern UnicornError uc_reg_read(IntPtr uc, int regid, byte[] value); + public static extern Error uc_reg_read(IntPtr uc, int regid, byte[] value); [DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)] - public static extern UnicornError uc_mem_write(IntPtr uc, ulong address, byte[] bytes, ulong size); + public static extern Error uc_mem_write(IntPtr uc, ulong address, byte[] bytes, ulong size); [DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)] - public static extern UnicornError uc_mem_read(IntPtr uc, ulong address, byte[] bytes, ulong size); + public static extern Error uc_mem_read(IntPtr uc, ulong address, byte[] bytes, ulong size); [DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)] - public static extern UnicornError uc_emu_start(IntPtr uc, ulong begin, ulong until, ulong timeout, ulong count); + public static extern Error uc_emu_start(IntPtr uc, ulong begin, ulong until, ulong timeout, ulong count); [DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)] - public static extern UnicornError uc_mem_map(IntPtr uc, ulong address, ulong size, uint perms); + public static extern Error uc_mem_map(IntPtr uc, ulong address, ulong size, uint perms); [DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)] - public static extern UnicornError uc_mem_unmap(IntPtr uc, ulong address, ulong size); + public static extern Error uc_mem_unmap(IntPtr uc, ulong address, ulong size); [DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)] - public static extern UnicornError uc_mem_protect(IntPtr uc, ulong address, ulong size, uint perms); + public static extern Error uc_mem_protect(IntPtr uc, ulong address, ulong size, uint perms); [DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)] - public static extern UnicornError uc_mem_regions(IntPtr uc, out IntPtr regions, out uint count); + public static extern Error uc_mem_regions(IntPtr uc, out IntPtr regions, out uint count); } -} +} \ No newline at end of file diff --git a/Ryujinx.Tests.Unicorn/Native/UnicornArch.cs b/Ryujinx.Tests.Unicorn/Native/UnicornArch.cs deleted file mode 100644 index ff633293e..000000000 --- a/Ryujinx.Tests.Unicorn/Native/UnicornArch.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Ryujinx.Tests.Unicorn.Native -{ - public enum UnicornArch : uint - { - UC_ARCH_ARM = 1, // ARM architecture (including Thumb, Thumb-2) - UC_ARCH_ARM64, // ARM-64, also called AArch64 - UC_ARCH_MIPS, // Mips architecture - UC_ARCH_X86, // X86 architecture (including x86 & x86-64) - UC_ARCH_PPC, // PowerPC architecture (currently unsupported) - UC_ARCH_SPARC, // Sparc architecture - UC_ARCH_M68K, // M68K architecture - UC_ARCH_MAX, - } -} diff --git a/Ryujinx.Tests.Unicorn/Native/UnicornMode.cs b/Ryujinx.Tests.Unicorn/Native/UnicornMode.cs deleted file mode 100644 index 8045f2dac..000000000 --- a/Ryujinx.Tests.Unicorn/Native/UnicornMode.cs +++ /dev/null @@ -1,33 +0,0 @@ -// ReSharper disable InconsistentNaming -namespace Ryujinx.Tests.Unicorn.Native -{ - public enum UnicornMode : uint - { - UC_MODE_LITTLE_ENDIAN = 0, // little-endian mode (default mode) - UC_MODE_BIG_ENDIAN = 1 << 30, // big-endian mode - // arm / arm64 - UC_MODE_ARM = 0, // ARM mode - UC_MODE_THUMB = 1 << 4, // THUMB mode (including Thumb-2) - UC_MODE_MCLASS = 1 << 5, // ARM's Cortex-M series (currently unsupported) - UC_MODE_V8 = 1 << 6, // ARMv8 A32 encodings for ARM (currently unsupported) - // mips - UC_MODE_MICRO = 1 << 4, // MicroMips mode (currently unsupported) - UC_MODE_MIPS3 = 1 << 5, // Mips III ISA (currently unsupported) - UC_MODE_MIPS32R6 = 1 << 6, // Mips32r6 ISA (currently unsupported) - UC_MODE_MIPS32 = 1 << 2, // Mips32 ISA - UC_MODE_MIPS64 = 1 << 3, // Mips64 ISA - // x86 / x64 - UC_MODE_16 = 1 << 1, // 16-bit mode - UC_MODE_32 = 1 << 2, // 32-bit mode - UC_MODE_64 = 1 << 3, // 64-bit mode - // ppc - UC_MODE_PPC32 = 1 << 2, // 32-bit mode (currently unsupported) - UC_MODE_PPC64 = 1 << 3, // 64-bit mode (currently unsupported) - UC_MODE_QPX = 1 << 4, // Quad Processing eXtensions mode (currently unsupported) - // sparc - UC_MODE_SPARC32 = 1 << 2, // 32-bit mode - UC_MODE_SPARC64 = 1 << 3, // 64-bit mode - UC_MODE_V9 = 1 << 4, // SparcV9 mode (currently unsupported) - // m68k - } -} diff --git a/Ryujinx.Tests.Unicorn/UnicornAArch32.cs b/Ryujinx.Tests.Unicorn/UnicornAArch32.cs index e634e0d2a..8b3e79b69 100644 --- a/Ryujinx.Tests.Unicorn/UnicornAArch32.cs +++ b/Ryujinx.Tests.Unicorn/UnicornAArch32.cs @@ -1,4 +1,5 @@ using Ryujinx.Tests.Unicorn.Native; +using Ryujinx.Tests.Unicorn.Native.Const; using System; namespace Ryujinx.Tests.Unicorn @@ -30,32 +31,32 @@ namespace Ryujinx.Tests.Unicorn public uint LR { - get => GetRegister(Arm32Register.LR); - set => SetRegister(Arm32Register.LR, value); + get => GetRegister(Arm.REG_LR); + set => SetRegister(Arm.REG_LR, value); } public uint SP { - get => GetRegister(Arm32Register.SP); - set => SetRegister(Arm32Register.SP, value); + get => GetRegister(Arm.REG_SP); + set => SetRegister(Arm.REG_SP, value); } public uint PC { - get => GetRegister(Arm32Register.PC) & 0xfffffffeu; - set => SetRegister(Arm32Register.PC, (value & 0xfffffffeu) | (ThumbFlag ? 1u : 0u)); + get => GetRegister(Arm.REG_PC) & 0xfffffffeu; + set => SetRegister(Arm.REG_PC, (value & 0xfffffffeu) | (ThumbFlag ? 1u : 0u)); } public uint CPSR { - get => (uint)GetRegister(Arm32Register.CPSR); - set => SetRegister(Arm32Register.CPSR, (uint)value); + get => GetRegister(Arm.REG_CPSR); + set => SetRegister(Arm.REG_CPSR, value); } public int Fpscr { - get => (int)GetRegister(Arm32Register.FPSCR) | ((int)GetRegister(Arm32Register.FPSCR_NZCV)); - set => SetRegister(Arm32Register.FPSCR, (uint)value); + get => (int)GetRegister(Arm.REG_FPSCR) | ((int)GetRegister(Arm.REG_FPSCR_NZCV)); + set => SetRegister(Arm.REG_FPSCR, (uint)value); } public bool QFlag @@ -94,16 +95,16 @@ namespace Ryujinx.Tests.Unicorn set { CPSR = (CPSR & ~0x00000020u) | (value ? 0x00000020u : 0u); - SetRegister(Arm32Register.PC, (GetRegister(Arm32Register.PC) & 0xfffffffeu) | (value ? 1u : 0u)); + SetRegister(Arm.REG_PC, (GetRegister(Arm.REG_PC) & 0xfffffffeu) | (value ? 1u : 0u)); } } public UnicornAArch32() { - Interface.Checked(Interface.uc_open(UnicornArch.UC_ARCH_ARM, UnicornMode.UC_MODE_LITTLE_ENDIAN, out uc)); + Interface.Checked(Interface.uc_open(Arch.ARM, Mode.LITTLE_ENDIAN, out uc)); - SetRegister(Arm32Register.C1_C0_2, GetRegister(Arm32Register.C1_C0_2) | 0xf00000); - SetRegister(Arm32Register.FPEXC, 0x40000000); + SetRegister(Arm.REG_C1_C0_2, GetRegister(Arm.REG_C1_C0_2) | 0xf00000); + SetRegister(Arm.REG_FPEXC, 0x40000000); } ~UnicornAArch32() @@ -136,44 +137,44 @@ namespace Ryujinx.Tests.Unicorn RunForCount(1); } - private static Arm32Register[] XRegisters = new Arm32Register[16] + private static Arm[] XRegisters = new Arm[16] { - Arm32Register.R0, - Arm32Register.R1, - Arm32Register.R2, - Arm32Register.R3, - Arm32Register.R4, - Arm32Register.R5, - Arm32Register.R6, - Arm32Register.R7, - Arm32Register.R8, - Arm32Register.R9, - Arm32Register.R10, - Arm32Register.R11, - Arm32Register.R12, - Arm32Register.R13, - Arm32Register.R14, - Arm32Register.R15, + Arm.REG_R0, + Arm.REG_R1, + Arm.REG_R2, + Arm.REG_R3, + Arm.REG_R4, + Arm.REG_R5, + Arm.REG_R6, + Arm.REG_R7, + Arm.REG_R8, + Arm.REG_R9, + Arm.REG_R10, + Arm.REG_R11, + Arm.REG_R12, + Arm.REG_R13, + Arm.REG_R14, + Arm.REG_R15, }; - private static Arm32Register[] QRegisters = new Arm32Register[16] + private static Arm[] QRegisters = new Arm[16] { - Arm32Register.Q0, - Arm32Register.Q1, - Arm32Register.Q2, - Arm32Register.Q3, - Arm32Register.Q4, - Arm32Register.Q5, - Arm32Register.Q6, - Arm32Register.Q7, - Arm32Register.Q8, - Arm32Register.Q9, - Arm32Register.Q10, - Arm32Register.Q11, - Arm32Register.Q12, - Arm32Register.Q13, - Arm32Register.Q14, - Arm32Register.Q15 + Arm.REG_Q0, + Arm.REG_Q1, + Arm.REG_Q2, + Arm.REG_Q3, + Arm.REG_Q4, + Arm.REG_Q5, + Arm.REG_Q6, + Arm.REG_Q7, + Arm.REG_Q8, + Arm.REG_Q9, + Arm.REG_Q10, + Arm.REG_Q11, + Arm.REG_Q12, + Arm.REG_Q13, + Arm.REG_Q14, + Arm.REG_Q15 }; public uint GetX(int index) @@ -204,7 +205,7 @@ namespace Ryujinx.Tests.Unicorn } // Getting quadword registers from Unicorn A32 seems to be broken, so we combine its 2 doubleword registers instead. - return GetVector((Arm32Register)((int)Arm32Register.D0 + index * 2)); + return GetVector((Arm)((int)Arm.REG_D0 + index * 2)); } public void SetQ(int index, SimdValue value) @@ -214,10 +215,10 @@ namespace Ryujinx.Tests.Unicorn throw new ArgumentOutOfRangeException(nameof(index)); } - SetVector((Arm32Register)((int)Arm32Register.D0 + index * 2), value); + SetVector((Arm)((int)Arm.REG_D0 + index * 2), value); } - public uint GetRegister(Arm32Register register) + public uint GetRegister(Arm register) { byte[] data = new byte[4]; @@ -226,14 +227,14 @@ namespace Ryujinx.Tests.Unicorn return (uint)BitConverter.ToInt32(data, 0); } - public void SetRegister(Arm32Register register, uint value) + public void SetRegister(Arm register, uint value) { byte[] data = BitConverter.GetBytes(value); Interface.Checked(Interface.uc_reg_write(uc, (int)register, data)); } - public SimdValue GetVector(Arm32Register register) + public SimdValue GetVector(Arm register) { byte[] data = new byte[8]; @@ -245,7 +246,7 @@ namespace Ryujinx.Tests.Unicorn return new SimdValue(lo, hi); } - private void SetVector(Arm32Register register, SimdValue value) + private void SetVector(Arm register, SimdValue value) { byte[] data = BitConverter.GetBytes(value.GetUInt64(0)); Interface.Checked(Interface.uc_reg_write(uc, (int)register, data)); @@ -300,13 +301,10 @@ namespace Ryujinx.Tests.Unicorn try { Interface.uc_version(out _, out _); + } + catch (DllNotFoundException) { } - return true; - } - catch (DllNotFoundException) - { - return false; - } + return Interface.IsUnicornAvailable; } } -} +} \ No newline at end of file diff --git a/Ryujinx.Tests.Unicorn/UnicornAArch64.cs b/Ryujinx.Tests.Unicorn/UnicornAArch64.cs index c5d5540b1..5cd5f88cb 100644 --- a/Ryujinx.Tests.Unicorn/UnicornAArch64.cs +++ b/Ryujinx.Tests.Unicorn/UnicornAArch64.cs @@ -1,4 +1,5 @@ using Ryujinx.Tests.Unicorn.Native; +using Ryujinx.Tests.Unicorn.Native.Const; using System; namespace Ryujinx.Tests.Unicorn @@ -30,38 +31,38 @@ namespace Ryujinx.Tests.Unicorn public ulong LR { - get => GetRegister(ArmRegister.LR); - set => SetRegister(ArmRegister.LR, value); + get => GetRegister(Arm64.REG_LR); + set => SetRegister(Arm64.REG_LR, value); } public ulong SP { - get => GetRegister(ArmRegister.SP); - set => SetRegister(ArmRegister.SP, value); + get => GetRegister(Arm64.REG_SP); + set => SetRegister(Arm64.REG_SP, value); } public ulong PC { - get => GetRegister(ArmRegister.PC); - set => SetRegister(ArmRegister.PC, value); + get => GetRegister(Arm64.REG_PC); + set => SetRegister(Arm64.REG_PC, value); } public uint Pstate { - get => (uint)GetRegister(ArmRegister.PSTATE); - set => SetRegister(ArmRegister.PSTATE, (uint)value); + get => (uint)GetRegister(Arm64.REG_PSTATE); + set => SetRegister(Arm64.REG_PSTATE, (uint)value); } public int Fpcr { - get => (int)GetRegister(ArmRegister.FPCR); - set => SetRegister(ArmRegister.FPCR, (uint)value); + get => (int)GetRegister(Arm64.REG_FPCR); + set => SetRegister(Arm64.REG_FPCR, (uint)value); } public int Fpsr { - get => (int)GetRegister(ArmRegister.FPSR); - set => SetRegister(ArmRegister.FPSR, (uint)value); + get => (int)GetRegister(Arm64.REG_FPSR); + set => SetRegister(Arm64.REG_FPSR, (uint)value); } public bool OverflowFlag @@ -90,9 +91,9 @@ namespace Ryujinx.Tests.Unicorn public UnicornAArch64() { - Interface.Checked(Interface.uc_open(UnicornArch.UC_ARCH_ARM64, UnicornMode.UC_MODE_LITTLE_ENDIAN, out uc)); + Interface.Checked(Interface.uc_open(Arch.ARM64, Mode.LITTLE_ENDIAN, out uc)); - SetRegister(ArmRegister.CPACR_EL1, 0x00300000); + SetRegister(Arm64.REG_CPACR_EL1, 0x00300000); } ~UnicornAArch64() @@ -125,75 +126,75 @@ namespace Ryujinx.Tests.Unicorn RunForCount(1); } - private static ArmRegister[] XRegisters = new ArmRegister[31] + private static Arm64[] XRegisters = new Arm64[31] { - ArmRegister.X0, - ArmRegister.X1, - ArmRegister.X2, - ArmRegister.X3, - ArmRegister.X4, - ArmRegister.X5, - ArmRegister.X6, - ArmRegister.X7, - ArmRegister.X8, - ArmRegister.X9, - ArmRegister.X10, - ArmRegister.X11, - ArmRegister.X12, - ArmRegister.X13, - ArmRegister.X14, - ArmRegister.X15, - ArmRegister.X16, - ArmRegister.X17, - ArmRegister.X18, - ArmRegister.X19, - ArmRegister.X20, - ArmRegister.X21, - ArmRegister.X22, - ArmRegister.X23, - ArmRegister.X24, - ArmRegister.X25, - ArmRegister.X26, - ArmRegister.X27, - ArmRegister.X28, - ArmRegister.X29, - ArmRegister.X30, + Arm64.REG_X0, + Arm64.REG_X1, + Arm64.REG_X2, + Arm64.REG_X3, + Arm64.REG_X4, + Arm64.REG_X5, + Arm64.REG_X6, + Arm64.REG_X7, + Arm64.REG_X8, + Arm64.REG_X9, + Arm64.REG_X10, + Arm64.REG_X11, + Arm64.REG_X12, + Arm64.REG_X13, + Arm64.REG_X14, + Arm64.REG_X15, + Arm64.REG_X16, + Arm64.REG_X17, + Arm64.REG_X18, + Arm64.REG_X19, + Arm64.REG_X20, + Arm64.REG_X21, + Arm64.REG_X22, + Arm64.REG_X23, + Arm64.REG_X24, + Arm64.REG_X25, + Arm64.REG_X26, + Arm64.REG_X27, + Arm64.REG_X28, + Arm64.REG_X29, + Arm64.REG_X30, }; - private static ArmRegister[] QRegisters = new ArmRegister[32] + private static Arm64[] QRegisters = new Arm64[32] { - ArmRegister.Q0, - ArmRegister.Q1, - ArmRegister.Q2, - ArmRegister.Q3, - ArmRegister.Q4, - ArmRegister.Q5, - ArmRegister.Q6, - ArmRegister.Q7, - ArmRegister.Q8, - ArmRegister.Q9, - ArmRegister.Q10, - ArmRegister.Q11, - ArmRegister.Q12, - ArmRegister.Q13, - ArmRegister.Q14, - ArmRegister.Q15, - ArmRegister.Q16, - ArmRegister.Q17, - ArmRegister.Q18, - ArmRegister.Q19, - ArmRegister.Q20, - ArmRegister.Q21, - ArmRegister.Q22, - ArmRegister.Q23, - ArmRegister.Q24, - ArmRegister.Q25, - ArmRegister.Q26, - ArmRegister.Q27, - ArmRegister.Q28, - ArmRegister.Q29, - ArmRegister.Q30, - ArmRegister.Q31, + Arm64.REG_Q0, + Arm64.REG_Q1, + Arm64.REG_Q2, + Arm64.REG_Q3, + Arm64.REG_Q4, + Arm64.REG_Q5, + Arm64.REG_Q6, + Arm64.REG_Q7, + Arm64.REG_Q8, + Arm64.REG_Q9, + Arm64.REG_Q10, + Arm64.REG_Q11, + Arm64.REG_Q12, + Arm64.REG_Q13, + Arm64.REG_Q14, + Arm64.REG_Q15, + Arm64.REG_Q16, + Arm64.REG_Q17, + Arm64.REG_Q18, + Arm64.REG_Q19, + Arm64.REG_Q20, + Arm64.REG_Q21, + Arm64.REG_Q22, + Arm64.REG_Q23, + Arm64.REG_Q24, + Arm64.REG_Q25, + Arm64.REG_Q26, + Arm64.REG_Q27, + Arm64.REG_Q28, + Arm64.REG_Q29, + Arm64.REG_Q30, + Arm64.REG_Q31, }; public ulong GetX(int index) @@ -236,7 +237,7 @@ namespace Ryujinx.Tests.Unicorn SetVector(QRegisters[index], value); } - private ulong GetRegister(ArmRegister register) + private ulong GetRegister(Arm64 register) { byte[] data = new byte[8]; @@ -245,14 +246,14 @@ namespace Ryujinx.Tests.Unicorn return (ulong)BitConverter.ToInt64(data, 0); } - private void SetRegister(ArmRegister register, ulong value) + private void SetRegister(Arm64 register, ulong value) { byte[] data = BitConverter.GetBytes(value); Interface.Checked(Interface.uc_reg_write(uc, (int)register, data)); } - private SimdValue GetVector(ArmRegister register) + private SimdValue GetVector(Arm64 register) { byte[] data = new byte[16]; @@ -261,7 +262,7 @@ namespace Ryujinx.Tests.Unicorn return new SimdValue(data); } - private void SetVector(ArmRegister register, SimdValue value) + private void SetVector(Arm64 register, SimdValue value) { byte[] data = value.ToArray(); @@ -315,13 +316,10 @@ namespace Ryujinx.Tests.Unicorn try { Interface.uc_version(out _, out _); + } + catch (DllNotFoundException) { } - return true; - } - catch (DllNotFoundException) - { - return false; - } + return Interface.IsUnicornAvailable; } } } \ No newline at end of file diff --git a/Ryujinx.Tests.Unicorn/UnicornError.cs b/Ryujinx.Tests.Unicorn/UnicornError.cs deleted file mode 100644 index ac324089c..000000000 --- a/Ryujinx.Tests.Unicorn/UnicornError.cs +++ /dev/null @@ -1,29 +0,0 @@ -// ReSharper disable InconsistentNaming -namespace Ryujinx.Tests.Unicorn -{ - public enum UnicornError - { - UC_ERR_OK = 0, // No error: everything was fine - UC_ERR_NOMEM, // Out-Of-Memory error: uc_open(), uc_emulate() - UC_ERR_ARCH, // Unsupported architecture: uc_open() - UC_ERR_HANDLE, // Invalid handle - UC_ERR_MODE, // Invalid/unsupported mode: uc_open() - UC_ERR_VERSION, // Unsupported version (bindings) - UC_ERR_READ_UNMAPPED, // Quit emulation due to READ on unmapped memory: uc_emu_start() - UC_ERR_WRITE_UNMAPPED, // Quit emulation due to WRITE on unmapped memory: uc_emu_start() - UC_ERR_FETCH_UNMAPPED, // Quit emulation due to FETCH on unmapped memory: uc_emu_start() - UC_ERR_HOOK, // Invalid hook type: uc_hook_add() - UC_ERR_INSN_INVALID, // Quit emulation due to invalid instruction: uc_emu_start() - UC_ERR_MAP, // Invalid memory mapping: uc_mem_map() - UC_ERR_WRITE_PROT, // Quit emulation due to UC_MEM_WRITE_PROT violation: uc_emu_start() - UC_ERR_READ_PROT, // Quit emulation due to UC_MEM_READ_PROT violation: uc_emu_start() - UC_ERR_FETCH_PROT, // Quit emulation due to UC_MEM_FETCH_PROT violation: uc_emu_start() - UC_ERR_ARG, // Invalid argument provided to uc_xxx function (See specific function API) - UC_ERR_READ_UNALIGNED, // Unaligned read - UC_ERR_WRITE_UNALIGNED, // Unaligned write - UC_ERR_FETCH_UNALIGNED, // Unaligned fetch - UC_ERR_HOOK_EXIST, // hook for this event already existed - UC_ERR_RESOURCE, // Insufficient resource: uc_emu_start() - UC_ERR_EXCEPTION // Unhandled CPU exception - } -} diff --git a/Ryujinx.Tests.Unicorn/UnicornException.cs b/Ryujinx.Tests.Unicorn/UnicornException.cs index 3cb693703..b5c5f980e 100644 --- a/Ryujinx.Tests.Unicorn/UnicornException.cs +++ b/Ryujinx.Tests.Unicorn/UnicornException.cs @@ -1,3 +1,4 @@ +using Ryujinx.Tests.Unicorn.Native.Const; using System; using System.Runtime.InteropServices; @@ -5,9 +6,9 @@ namespace Ryujinx.Tests.Unicorn { public class UnicornException : Exception { - public readonly UnicornError Error; + public readonly Error Error; - internal UnicornException(UnicornError error) + internal UnicornException(Error error) { Error = error; } @@ -20,4 +21,4 @@ namespace Ryujinx.Tests.Unicorn } } } -} +} \ No newline at end of file diff --git a/Ryujinx.Tests.Unicorn/libs/README.md b/Ryujinx.Tests.Unicorn/libs/README.md index 427044f90..d05291e5c 100644 --- a/Ryujinx.Tests.Unicorn/libs/README.md +++ b/Ryujinx.Tests.Unicorn/libs/README.md @@ -9,14 +9,12 @@ CPU simulator, Armeilleure. On Windows, Unicorn is shipped as a pre-compiled dynamic library (`.dll`), licenced under the GPLv2. -The source code for `windows/unicorn.dll` is available at: https://github.com/MerryMage/UnicornDotNet/tree/299451c02d9c810d2feca51f5e9cb6d8b2f38960 +The source code for `windows/unicorn.dll` is available at: https://github.com/unicorn-engine/unicorn/tree/df3aa0fccbce9e1420e82110cbae5951755a0698 ## Linux -On Linux, you will first need to download Unicorn from https://github.com/unicorn-engine/unicorn. +On Windows, Unicorn is shipped as a pre-compiled shared object (`.so`), licenced under the GPLv2. -Then you need to patch it to expose the FSPCR register by applying `linux/unicorn_fspcr.patch` - -Then, compile Unicorn from source with its `make.sh` script. +The source code for `linux/unicorn.so` is available at: https://github.com/unicorn-engine/unicorn/tree/df3aa0fccbce9e1420e82110cbae5951755a0698 See https://github.com/Ryujinx/Ryujinx/pull/1433 for details. diff --git a/Ryujinx.Tests.Unicorn/libs/linux/libunicorn.so b/Ryujinx.Tests.Unicorn/libs/linux/libunicorn.so new file mode 100644 index 000000000..8d0948af9 Binary files /dev/null and b/Ryujinx.Tests.Unicorn/libs/linux/libunicorn.so differ diff --git a/Ryujinx.Tests.Unicorn/libs/linux/unicorn_fspcr.patch b/Ryujinx.Tests.Unicorn/libs/linux/unicorn_fspcr.patch deleted file mode 100644 index 391c2fb62..000000000 --- a/Ryujinx.Tests.Unicorn/libs/linux/unicorn_fspcr.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/qemu/target-arm/unicorn_arm.c b/qemu/target-arm/unicorn_arm.c -index 5ff9ebb..d4953f4 100644 ---- a/qemu/target-arm/unicorn_arm.c -+++ b/qemu/target-arm/unicorn_arm.c -@@ -101,6 +101,9 @@ int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int coun - case UC_ARM_REG_FPEXC: - *(int32_t *)value = ARM_CPU(uc, mycpu)->env.vfp.xregs[ARM_VFP_FPEXC]; - break; -+ case UC_ARM_REG_FPSCR: -+ *(int32_t *)value = vfp_get_fpscr(&ARM_CPU(uc, mycpu)->env); -+ break; - case UC_ARM_REG_IPSR: - *(uint32_t *)value = xpsr_read(&ARM_CPU(uc, mycpu)->env) & 0x1ff; - break; -@@ -175,6 +178,9 @@ int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, i - case UC_ARM_REG_FPEXC: - ARM_CPU(uc, mycpu)->env.vfp.xregs[ARM_VFP_FPEXC] = *(int32_t *)value; - break; -+ case UC_ARM_REG_FPSCR: -+ vfp_set_fpscr(&ARM_CPU(uc, mycpu)->env, *(uint32_t *)value); -+ break; - case UC_ARM_REG_IPSR: - xpsr_write(&ARM_CPU(uc, mycpu)->env, *(uint32_t *)value, 0x1ff); - break; diff --git a/Ryujinx.Tests.Unicorn/libs/windows/unicorn.dll b/Ryujinx.Tests.Unicorn/libs/windows/unicorn.dll index 146628e14..1c84586e4 100644 Binary files a/Ryujinx.Tests.Unicorn/libs/windows/unicorn.dll and b/Ryujinx.Tests.Unicorn/libs/windows/unicorn.dll differ diff --git a/Ryujinx.Tests.Unicorn/unicorn_const_generator.py b/Ryujinx.Tests.Unicorn/unicorn_const_generator.py new file mode 100644 index 000000000..813485fd2 --- /dev/null +++ b/Ryujinx.Tests.Unicorn/unicorn_const_generator.py @@ -0,0 +1,199 @@ +#!/usr/bin/env python3 +# Unicorn Engine +# By Dang Hoang Vu, 2013 +# Modified for Ryujinx from: https://github.com/unicorn-engine/unicorn/blob/6c1cbef6ac505d355033aef1176b684d02e1eb3a/bindings/const_generator.py +from __future__ import print_function +import sys, re, os + +include = [ 'arm.h', 'arm64.h', 'unicorn.h' ] +split_common = [ 'ARCH', 'MODE', 'ERR', 'MEM', 'TCG', 'HOOK', 'PROT' ] + +template = { + 'dotnet': { + 'header': "// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT\n\n// ReSharper disable InconsistentNaming\nnamespace Ryujinx.Tests.Unicorn.Native.Const\n{\n public enum %s\n {\n", + 'footer': " }\n}\n", + 'line_format': ' %s = %s,\n', + 'out_file': os.path.join(os.path.dirname(__file__), 'Native', 'Const', '%s.cs'), + # prefixes for constant filenames of all archs - case sensitive + 'arm.h': 'Arm', + 'arm64.h': 'Arm64', + 'unicorn.h': 'Common', + # prefixes for filenames of split_common values - case sensitive + 'ARCH': 'Arch', + 'MODE': 'Mode', + 'ERR': 'Error', + 'MEM': 'Memory', + 'TCG': 'TCG', + 'HOOK': 'Hook', + 'PROT': 'Permission', + 'comment_open': ' //', + 'comment_close': '', + } +} + +# markup for comments to be added to autogen files +MARKUP = '//>' + +def gen(unicorn_repo_path): + global include + include_dir = os.path.join(unicorn_repo_path, 'include', 'unicorn') + templ = template["dotnet"] + for target in include: + prefix = templ[target] + outfile = open(templ['out_file'] %(prefix), 'wb') # open as binary prevents windows newlines + outfile.write((templ['header'] % (prefix)).encode("utf-8")) + if target == 'unicorn.h': + prefix = '' + for cat in split_common: + with open(templ['out_file'] %(templ[cat]), 'wb') as file: + file.write((templ['header'] %(templ[cat])).encode("utf-8")) + with open(os.path.join(include_dir, target)) as f: + lines = f.readlines() + + previous = {} + count = 0 + skip = 0 + in_comment = False + + for lno, line in enumerate(lines): + if "/*" in line: + in_comment = True + if "*/" in line: + in_comment = False + if in_comment: + continue + if skip > 0: + # Due to clang-format, values may come up in the next line + skip -= 1 + continue + line = line.strip() + + if line.startswith(MARKUP): # markup for comments + outfile.write(("\n%s%s%s\n" %(templ['comment_open'], \ + line.replace(MARKUP, ''), templ['comment_close'])).encode("utf-8")) + continue + + if line == '' or line.startswith('//'): + continue + + tmp = line.strip().split(',') + if len(tmp) >= 2 and tmp[0] != "#define" and not tmp[0].startswith("UC_"): + continue + for t in tmp: + t = t.strip() + if not t or t.startswith('//'): continue + f = re.split('\s+', t) + + # parse #define UC_TARGET (num) + define = False + if f[0] == '#define' and len(f) >= 3: + define = True + f.pop(0) + f.insert(1, '=') + if f[0].startswith("UC_" + prefix.upper()) or f[0].startswith("UC_CPU"): + if len(f) > 1 and f[1] not in ('//', '='): + print("WARNING: Unable to convert %s" % f) + print(" Line =", line) + continue + elif len(f) > 1 and f[1] == '=': + # Like: + # UC_A = + # (1 << 2) + # #define UC_B \ + # (UC_A | UC_C) + # Let's search the next line + if len(f) == 2: + if lno == len(lines) - 1: + print("WARNING: Unable to convert %s" % f) + print(" Line =", line) + continue + skip += 1 + next_line = lines[lno + 1] + next_line_tmp = next_line.strip().split(",") + rhs = next_line_tmp[0] + elif f[-1] == "\\": + idx = 0 + rhs = "" + while True: + idx += 1 + if lno + idx == len(lines): + print("WARNING: Unable to convert %s" % f) + print(" Line =", line) + continue + skip += 1 + next_line = lines[lno + idx] + next_line_f = re.split('\s+', next_line.strip()) + if next_line_f[-1] == "\\": + rhs += "".join(next_line_f[:-1]) + else: + rhs += next_line.strip() + break + else: + rhs = ''.join(f[2:]) + else: + rhs = str(count) + + + lhs = f[0].strip() + #print(f'lhs: {lhs} rhs: {rhs} f:{f}') + # evaluate bitshifts in constants e.g. "UC_X86 = 1 << 1" + match = re.match(r'(?P\s*\d+\s*<<\s*\d+\s*)', rhs) + if match: + rhs = str(eval(match.group(1))) + else: + # evaluate references to other constants e.g. "UC_ARM_REG_X = UC_ARM_REG_SP" + match = re.match(r'^([^\d]\w+)$', rhs) + if match: + rhs = previous[match.group(1)] + + if not rhs.isdigit(): + for k, v in previous.items(): + rhs = re.sub(r'\b%s\b' % k, v, rhs) + rhs = str(eval(rhs)) + + lhs_strip = re.sub(r'^UC_', '', lhs) + count = int(rhs) + 1 + + if target == "unicorn.h": + matched_cat = False + for cat in split_common: + if lhs_strip.startswith(f"{cat}_"): + with open(templ['out_file'] %(templ[cat]), 'ab') as cat_file: + cat_lhs_strip = lhs_strip + if not lhs_strip.lstrip(f"{cat}_").isnumeric(): + cat_lhs_strip = lhs_strip.replace(f"{cat}_", "", 1) + cat_file.write( + (templ['line_format'] % (cat_lhs_strip, rhs)).encode("utf-8")) + matched_cat = True + break + if matched_cat: + previous[lhs] = str(rhs) + continue + + if (count == 1): + outfile.write(("\n").encode("utf-8")) + + if lhs_strip.startswith(f"{prefix.upper()}_") and not lhs_strip.replace(f"{prefix.upper()}_", "", 1).isnumeric(): + lhs_strip = lhs_strip.replace(f"{prefix.upper()}_", "", 1) + + outfile.write((templ['line_format'] % (lhs_strip, rhs)).encode("utf-8")) + previous[lhs] = str(rhs) + + outfile.write((templ['footer']).encode("utf-8")) + outfile.close() + + if target == "unicorn.h": + for cat in split_common: + with open(templ['out_file'] %(templ[cat]), 'ab') as cat_file: + cat_file.write(templ['footer'].encode('utf-8')) + +if __name__ == "__main__": + if len(sys.argv) < 2: + print("Usage:", sys.argv[0], " ") + sys.exit(1) + unicorn_repo_path = sys.argv[1] + if os.path.isdir(unicorn_repo_path): + print("Generating constants for dotnet") + gen(unicorn_repo_path) + else: + print("Couldn't find unicorn repo at:", unicorn_repo_path) diff --git a/Ryujinx.Tests/Cpu/CpuTest.cs b/Ryujinx.Tests/Cpu/CpuTest.cs index f983a03fb..cafed37da 100644 --- a/Ryujinx.Tests/Cpu/CpuTest.cs +++ b/Ryujinx.Tests/Cpu/CpuTest.cs @@ -38,14 +38,11 @@ namespace Ryujinx.Tests.Cpu private bool _usingMemory; - static CpuTest() + [OneTimeSetUp] + public void OneTimeSetup() { _unicornAvailable = UnicornAArch64.IsAvailable(); - - if (!_unicornAvailable) - { - Console.WriteLine("WARNING: Could not find Unicorn."); - } + Assume.That(_unicornAvailable, "Unicorn is not available"); } [SetUp] @@ -610,4 +607,4 @@ namespace Ryujinx.Tests.Cpu return rnd & 0x800FFFFFFFFFFFFFul; } } -} +} \ No newline at end of file diff --git a/Ryujinx.Tests/Cpu/CpuTest32.cs b/Ryujinx.Tests/Cpu/CpuTest32.cs index 2c36396f9..53fea943d 100644 --- a/Ryujinx.Tests/Cpu/CpuTest32.cs +++ b/Ryujinx.Tests/Cpu/CpuTest32.cs @@ -33,14 +33,11 @@ namespace Ryujinx.Tests.Cpu private bool _usingMemory; - static CpuTest32() + [OneTimeSetUp] + public void OneTimeSetup() { _unicornAvailable = UnicornAArch32.IsAvailable(); - - if (!_unicornAvailable) - { - Console.WriteLine("WARNING: Could not find Unicorn."); - } + Assume.That(_unicornAvailable, "Unicorn is not available"); } [SetUp] diff --git a/Ryujinx.Tests/Ryujinx.Tests.csproj b/Ryujinx.Tests/Ryujinx.Tests.csproj index 6ab2fa6b1..b56929dc9 100644 --- a/Ryujinx.Tests/Ryujinx.Tests.csproj +++ b/Ryujinx.Tests/Ryujinx.Tests.csproj @@ -34,7 +34,17 @@ - + + + + + + + + + + +