Browse code

update for C++17 compliance, update to latest 2sf, add WINE cross-compile makefiles

Adam Higerd authored on 2021/02/11 15:36:17
Showing 1 changed files
... ...
@@ -34,7 +34,7 @@
34 34
 #include "instruction_attributes.h"
35 35
 #include "MMU.h"
36 36
 #include "MMU_timing.h"
37
-#include "utils/AsmJit/asmjit.h"
37
+#include "utils/AsmJit/AsmJit.h"
38 38
 #include "arm_jit.h"
39 39
 #include "bios.h"
40 40
 
... ...
@@ -56,14 +56,14 @@ using namespace asmjit;
56 56
 	GpVar txt = c.newGpVar(kVarTypeIntPtr); \
57 57
 	GpVar data = c.newGpVar(kVarTypeIntPtr); \
58 58
 	GpVar io = c.newGpVar(kVarTypeInt32); \
59
-	c.lea(io, x86::dword_ptr_abs(stdout)); \
59
+	c.lea(io, x86::dword_ptr_abs(stderr)); \
60 60
 	c.lea(txt, x86::dword_ptr_abs(&buf)); \
61 61
 	c.mov(data, *reinterpret_cast<GpVar *>(&val)); \
62
-	auto prn = c.addCall(imm_ptr(fprintf), ASMJIT_CALL_CONV, FuncBuilder3<void, void *, void *, uint32_t>()); \
62
+	auto prn = c.addCall(imm_ptr(fprintf), ASMJIT_STDLIB_CALL_CONV, FuncBuilder3<void, void *, void *, uint32_t>()); \
63 63
 	prn->setArg(0, io); \
64 64
 	prn->setArg(1, txt); \
65 65
 	prn->setArg(2, data); \
66
-	auto prn_flush = c.addCall(imm_ptr(fflush), ASMJIT_CALL_CONV, FuncBuilder1<void, void *>()); \
66
+	auto prn_flush = c.addCall(imm_ptr(fflush), ASMJIT_STDLIB_CALL_CONV, FuncBuilder1<void, void *>()); \
67 67
 	prn_flush->setArg(0, io); \
68 68
 }
69 69
 #else
... ...
@@ -194,9 +194,9 @@ static uint8_t recompile_counts[(1 << 26) / 16];
194 194
 DS_ALIGN(4096) static uint8_t scratchpad[1 << 25];
195 195
 static uint8_t *scratchptr;
196 196
 
197
-struct ASMJIT_API StaticCodeGenerator : public Context
197
+struct StaticCodeSetup
198 198
 {
199
-	StaticCodeGenerator()
199
+	StaticCodeSetup()
200 200
 	{
201 201
 		scratchptr = scratchpad;
202 202
 		int align = reinterpret_cast<uintptr_t>(scratchpad) & (sysconf(_SC_PAGESIZE) - 1);
... ...
@@ -207,32 +207,10 @@ struct ASMJIT_API StaticCodeGenerator : public Context
207 207
 			abort();
208 208
 		}
209 209
 	}
210
-
211
-	uint32_t generate(void **dest, Assembler *assembler)
212
-	{
213
-		uintptr_t size = assembler->getCodeSize();
214
-		if (!size)
215
-		{
216
-			*dest = nullptr;
217
-			return kErrorNoFunction;
218
-		}
219
-		if (size > reinterpret_cast<uintptr_t>(scratchpad + sizeof(scratchpad) - scratchptr))
220
-		{
221
-			fprintf(stderr, "Out of memory for asmjit. Clearing code cache.\n");
222
-			arm_jit_reset(true);
223
-			// If arm_jit_reset didn't involve recompiling op_cmp, we could keep the current function.
224
-			*dest = nullptr;
225
-			return kErrorOk;
226
-		}
227
-		void *p = scratchptr;
228
-		size = assembler->relocCode(p);
229
-		scratchptr += size;
230
-		*dest = p;
231
-		return kErrorOk;
232
-	}
233 210
 };
234 211
 
235
-static StaticCodeGenerator codegen;
212
+static StaticCodeSetup setup;
213
+static StaticRuntime codegen(scratchpad, sizeof(scratchpad));
236 214
 static X86Compiler c(&codegen);
237 215
 #else
238 216
 static JitRuntime runtime;
... ...
@@ -280,7 +258,7 @@ static inline uint32_t _REG_NUM(uint32_t i, uint32_t n) { return (i >> n) & 0x7;
280 258
 // sequencer.reschedule = true;
281 259
 #define changeCPSR \
282 260
 { \
283
-	auto ctxCPSR = c.addCall(imm_ptr(NDS_Reschedule), ASMJIT_CALL_CONV, FuncBuilder0<void>()); \
261
+	auto ctxCPSR = c.addCall(imm_ptr(NDS_Reschedule), ASMJIT_STDLIB_CALL_CONV, FuncBuilder0<void>()); \
284 262
 }
285 263
 
286 264
 #if PROFILER_JIT_LEVEL > 0
... ...
@@ -417,7 +395,7 @@ static GpVar bb_profiler_entry;
417 395
 	c.mov(SPSR, cpu_ptr(SPSR.val)); \
418 396
 	c.mov(tmp, SPSR); \
419 397
 	c.and_(tmp, 0x1F); \
420
-	auto ctx = c.addCall(imm_ptr(armcpu_switchMode), ASMJIT_CALL_CONV, FuncBuilder2<void, void *, uint8_t>()); \
398
+	auto ctx = c.addCall(imm_ptr(armcpu_switchMode), ASMJIT_STDLIB_CALL_CONV, FuncBuilder2<void, void *, uint8_t>()); \
421 399
 	ctx->setArg(0, bb_cpu); \
422 400
 	ctx->setArg(1, tmp); \
423 401
 	c.mov(cpu_ptr(CPSR.val), SPSR); \
... ...
@@ -1187,10 +1165,10 @@ static int OP_MVN_S_IMM_VAL(uint32_t i) { OP_MOV_S(S_IMM_VAL; rhs = ~rhs); }
1187 1165
 //   QADD / QDADD / QSUB / QDSUB
1188 1166
 // -----------------------------------------------------------------------------
1189 1167
 // TODO
1190
-static int OP_QADD(uint32_t i) { printf("JIT: unimplemented OP_QADD\n"); return 0; }
1191
-static int OP_QSUB(uint32_t i) { printf("JIT: unimplemented OP_QSUB\n"); return 0; }
1192
-static int OP_QDADD(uint32_t i) { printf("JIT: unimplemented OP_QDADD\n"); return 0; }
1193
-static int OP_QDSUB(uint32_t i) { printf("JIT: unimplemented OP_QDSUB\n"); return 0; }
1168
+static int OP_QADD(uint32_t i) { fprintf(stderr, "JIT: unimplemented OP_QADD\n"); return 0; }
1169
+static int OP_QSUB(uint32_t i) { fprintf(stderr, "JIT: unimplemented OP_QSUB\n"); return 0; }
1170
+static int OP_QDADD(uint32_t i) { fprintf(stderr, "JIT: unimplemented OP_QDADD\n"); return 0; }
1171
+static int OP_QDSUB(uint32_t i) { fprintf(stderr, "JIT: unimplemented OP_QDSUB\n"); return 0; }
1194 1172
 
1195 1173
 // -----------------------------------------------------------------------------
1196 1174
 //   MUL
... ...
@@ -1423,7 +1401,7 @@ static int OP_MRS_SPSR(uint32_t i)
1423 1401
 			{ \
1424 1402
 				c.mov(mode, rhs); \
1425 1403
 				c.and_(mode, 0x1F); \
1426
-				auto ctx = c.addCall(imm_ptr(armcpu_switchMode), ASMJIT_CALL_CONV, \
1404
+				auto ctx = c.addCall(imm_ptr(armcpu_switchMode), ASMJIT_STDLIB_CALL_CONV, \
1427 1405
 					FuncBuilder2<void, void *, uint8_t>()); \
1428 1406
 				ctx->setArg(0, bb_cpu); \
1429 1407
 				ctx->setArg(1, mode); \
... ...
@@ -1492,7 +1470,7 @@ static int OP_MRS_SPSR(uint32_t i)
1492 1470
 		/* armcpu_switchMode */ \
1493 1471
 		c.mov(mode, rhs); \
1494 1472
 		c.and_(mode, 0x1F); \
1495
-		auto ctx = c.addCall(imm_ptr(armcpu_switchMode), ASMJIT_CALL_CONV, \
1473
+		auto ctx = c.addCall(imm_ptr(armcpu_switchMode), ASMJIT_STDLIB_CALL_CONV, \
1496 1474
 			FuncBuilder2<void, void *, uint8_t>()); \
1497 1475
 		ctx->setArg(0, bb_cpu); \
1498 1476
 		ctx->setArg(1, mode); \
... ...
@@ -1925,12 +1903,12 @@ static int OP_LDRD_STRD_POST_INDEX(uint32_t i)
1925 1903
 
1926 1904
 	if (Rd_num == 14)
1927 1905
 	{
1928
-		printf("OP_LDRD_STRD_POST_INDEX: use R14!!!!\n");
1906
+		fprintf(stderr, "OP_LDRD_STRD_POST_INDEX: use R14!!!!\n");
1929 1907
 		return 0; // TODO: exception
1930 1908
 	}
1931 1909
 	if (Rd_num & 0x1)
1932 1910
 	{
1933
-		printf("OP_LDRD_STRD_POST_INDEX: ERROR!!!!\n");
1911
+		fprintf(stderr, "OP_LDRD_STRD_POST_INDEX: ERROR!!!!\n");
1934 1912
 		return 0; // TODO: exception
1935 1913
 	}
1936 1914
 	GpVar Rd = c.newGpVar(kVarTypeInt32);
... ...
@@ -1966,12 +1944,12 @@ static int OP_LDRD_STRD_OFFSET_PRE_INDEX(uint32_t i)
1966 1944
 
1967 1945
 	if (Rd_num == 14)
1968 1946
 	{
1969
-		printf("OP_LDRD_STRD_OFFSET_PRE_INDEX: use R14!!!!\n");
1947
+		fprintf(stderr, "OP_LDRD_STRD_OFFSET_PRE_INDEX: use R14!!!!\n");
1970 1948
 		return 0; // TODO: exception
1971 1949
 	}
1972 1950
 	if (Rd_num & 0x1)
1973 1951
 	{
1974
-		printf("OP_LDRD_STRD_OFFSET_PRE_INDEX: ERROR!!!!\n");
1952
+		fprintf(stderr, "OP_LDRD_STRD_OFFSET_PRE_INDEX: ERROR!!!!\n");
1975 1953
 		return 0; // TODO: exception
1976 1954
 	}
1977 1955
 	GpVar Rd = c.newGpVar(kVarTypeInt32);
... ...
@@ -2089,7 +2067,7 @@ static uint64_t get_reg_list(uint32_t reg_mask, int dir)
2089 2067
 #define LDM_INLINE inline
2090 2068
 #endif
2091 2069
 
2092
-template<int PROCNUM, bool store, int dir> static LDM_INLINE FASTCALL uint32_t OP_LDM_STM_generic(uint32_t adr, uint64_t regs, int n)
2070
+template<int PROCNUM, bool store, int dir> static LDM_INLINE LDM_FASTCALL uint32_t OP_LDM_STM_generic(uint32_t adr, uint64_t regs, int n)
2093 2071
 {
2094 2072
 	uint32_t cycles = 0;
2095 2073
 	adr &= ~3;
... ...
@@ -2112,7 +2090,7 @@ template<int PROCNUM, bool store, int dir> static LDM_INLINE FASTCALL uint32_t O
2112 2090
 #define ADV_CYCLES
2113 2091
 #endif
2114 2092
 
2115
-template<int PROCNUM, bool store, int dir> static LDM_INLINE FASTCALL uint32_t OP_LDM_STM_other(uint32_t adr, uint64_t regs, int n)
2093
+template<int PROCNUM, bool store, int dir> static LDM_INLINE LDM_FASTCALL uint32_t OP_LDM_STM_other(uint32_t adr, uint64_t regs, int n)
2116 2094
 {
2117 2095
 	uint32_t cycles = 0;
2118 2096
 	adr &= ~3;
... ...
@@ -2142,7 +2120,7 @@ template<int PROCNUM, bool store, int dir> static LDM_INLINE FASTCALL uint32_t O
2142 2120
 	return cycles;
2143 2121
 }
2144 2122
 
2145
-template<int PROCNUM, bool store, int dir, bool null_compiled> static FORCEINLINE FASTCALL uint32_t OP_LDM_STM_main(uint32_t adr, uint64_t regs, int n, uint8_t *ptr, uint32_t cycles)
2123
+template<int PROCNUM, bool store, int dir, bool null_compiled> static FORCEINLINE LDM_FASTCALL uint32_t OP_LDM_STM_main(uint32_t adr, uint64_t regs, int n, uint8_t *ptr, uint32_t cycles)
2146 2124
 {
2147 2125
 #ifdef ENABLE_ADVANCED_TIMING
2148 2126
 	cycles = 0;
... ...
@@ -2188,7 +2166,7 @@ template<int PROCNUM, bool store, int dir, bool null_compiled> static FORCEINLIN
2188 2166
 #undef ADV_CYCLES
2189 2167
 }
2190 2168
 
2191
-template<int PROCNUM, bool store, int dir> static uint32_t FASTCALL OP_LDM_STM(uint32_t adr, uint64_t regs, int n)
2169
+template<int PROCNUM, bool store, int dir> static uint32_t LDM_FASTCALL OP_LDM_STM(uint32_t adr, uint64_t regs, int n)
2192 2170
 {
2193 2171
 	// TODO use classify_adr?
2194 2172
 	uint32_t cycles;
... ...
@@ -2227,7 +2205,8 @@ template<int PROCNUM, bool store, int dir> static uint32_t FASTCALL OP_LDM_STM(u
2227 2205
 	return OP_LDM_STM_main<PROCNUM, store, dir, store>(adr, regs, n, ptr, cycles);
2228 2206
 }
2229 2207
 
2230
-typedef uint32_t FASTCALL (*LDMOpFunc)(uint32_t, uint64_t, int);
2208
+typedef uint32_t LDM_FASTCALL (*LDMOpFunc)(uint32_t, uint64_t, int);
2209
+
2231 2210
 static const LDMOpFunc op_ldm_stm_tab[2][2][2] =
2232 2211
 {
2233 2212
 	{
... ...
@@ -2260,7 +2239,7 @@ static void call_ldm_stm(GpVar adr, uint32_t bitmask, bool store, int dir)
2260 2239
 		GpVar regs_hi = c.newGpVar(kVarTypeInt32);
2261 2240
 		c.mov(regs_lo, get_reg_list(bitmask, dir) & 0xFFFFFFFF);
2262 2241
 		c.mov(regs_hi, get_reg_list(bitmask, dir) >> 32);
2263
-		auto ctx = c.addCall(imm_ptr(op_ldm_stm_tab[PROCNUM][store][dir > 0]), ASMJIT_CALL_CONV,
2242
+		auto ctx = c.addCall(imm_ptr(op_ldm_stm_tab[PROCNUM][store][dir > 0]), ASMJIT_STDLIB_CALL_CONV,
2264 2243
 			FuncBuilder4<uint32_t, uint32_t, uint32_t, uint32_t, int>());
2265 2244
 		ctx->setArg(0, adr);
2266 2245
 		ctx->setArg(1, regs_lo);
... ...
@@ -2339,7 +2318,7 @@ static int op_ldm_stm2(uint32_t i, bool store, int dir, bool before, bool writeb
2339 2318
 	uint32_t pop = popcount(bitmask);
2340 2319
 	bool bit15 = !!BIT15(i);
2341 2320
 
2342
-	//printf("ARM%c: %s R%d:%08X, bitmask %02X\n", PROCNUM?'7':'9', (store?"STM":"LDM"), REG_POS(i, 16), cpu->R[REG_POS(i, 16)], bitmask);
2321
+	//fprintf(stderr, "ARM%c: %s R%d:%08X, bitmask %02X\n", PROCNUM?'7':'9', (store?"STM":"LDM"), REG_POS(i, 16), cpu->R[REG_POS(i, 16)], bitmask);
2343 2322
 	uint32_t adr_first = cpu->R[REG_POS(i, 16)];
2344 2323
 
2345 2324
 	GpVar adr = c.newGpVar(kVarTypeInt32);
... ...
@@ -2351,10 +2330,10 @@ static int op_ldm_stm2(uint32_t i, bool store, int dir, bool before, bool writeb
2351 2330
 
2352 2331
 	if (!bit15 || store)
2353 2332
 	{
2354
-		//if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; }
2333
+		//if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { fprintf(stderr, "ERROR1\n"); return 1; }
2355 2334
 		//oldmode = armcpu_switchMode(cpu, SYS);
2356 2335
 		c.mov(oldmode, SYS);
2357
-		auto ctx = c.addCall(imm_ptr(armcpu_switchMode), ASMJIT_CALL_CONV,
2336
+		auto ctx = c.addCall(imm_ptr(armcpu_switchMode), ASMJIT_STDLIB_CALL_CONV,
2358 2337
 			FuncBuilder2<uint32_t, uint8_t *, uint8_t>());
2359 2338
 		ctx->setArg(0, bb_cpu);
2360 2339
 		ctx->setArg(1, oldmode);
... ...
@@ -2366,7 +2345,7 @@ static int op_ldm_stm2(uint32_t i, bool store, int dir, bool before, bool writeb
2366 2345
 	if (!bit15 || store)
2367 2346
 	{
2368 2347
 		//armcpu_switchMode(cpu, oldmode);
2369
-		auto ctx = c.addCall(imm_ptr(armcpu_switchMode), ASMJIT_CALL_CONV,
2348
+		auto ctx = c.addCall(imm_ptr(armcpu_switchMode), ASMJIT_STDLIB_CALL_CONV,
2370 2349
 			FuncBuilder2<void, uint8_t *, uint8_t>());
2371 2350
 		ctx->setArg(0, bb_cpu);
2372 2351
 		ctx->setArg(1, oldmode);
... ...
@@ -2487,7 +2466,7 @@ static int OP_CLZ(uint32_t i)
2487 2466
 // -----------------------------------------------------------------------------
2488 2467
 #define maskPrecalc \
2489 2468
 { \
2490
-	auto ctxM = c.addCall(imm_ptr(maskPrecalc), ASMJIT_CALL_CONV, FuncBuilder0<void>()); \
2469
+	auto ctxM = c.addCall(imm_ptr(maskPrecalc), ASMJIT_STDLIB_CALL_CONV, FuncBuilder0<void>()); \
2491 2470
 }
2492 2471
 static int OP_MCR(uint32_t i)
2493 2472
 {
... ...
@@ -2498,12 +2477,12 @@ static int OP_MCR(uint32_t i)
2498 2477
 	if (cpnum != 15)
2499 2478
 	{
2500 2479
 		// TODO - exception?
2501
-		printf("JIT: MCR P%i, 0, R%i, C%i, C%i, %i, %i (don't allocated coprocessor)\n", cpnum, REG_POS(i, 12), REG_POS(i, 16), REG_POS(i, 0), (i >> 21) & 0x7, (i >> 5) & 0x7);
2480
+		fprintf(stderr, "JIT: MCR P%i, 0, R%i, C%i, C%i, %i, %i (don't allocated coprocessor)\n", cpnum, REG_POS(i, 12), REG_POS(i, 16), REG_POS(i, 0), (i >> 21) & 0x7, (i >> 5) & 0x7);
2502 2481
 		return 2;
2503 2482
 	}
2504 2483
 	if (REG_POS(i, 12) == 15)
2505 2484
 	{
2506
-		printf("JIT: MCR Rd=R15\n");
2485
+		fprintf(stderr, "JIT: MCR Rd=R15\n");
2507 2486
 		return 2;
2508 2487
 	}
2509 2488
 
... ...
@@ -2723,7 +2702,7 @@ static int OP_MCR(uint32_t i)
2723 2702
 
2724 2703
 	if (bUnknown)
2725 2704
 	{
2726
-		//printf("Unknown MCR command: MRC P15, 0, R%i, C%i, C%i, %i, %i\n", REG_POS(i, 12), CRn, CRm, opcode1, opcode2);
2705
+		//fprintf(stderr, "Unknown MCR command: MRC P15, 0, R%i, C%i, C%i, %i, %i\n", REG_POS(i, 12), CRn, CRm, opcode1, opcode2);
2727 2706
 		return 1;
2728 2707
 	}
2729 2708
 
... ...
@@ -2738,7 +2717,7 @@ static int OP_MRC(uint32_t i)
2738 2717
 	uint32_t cpnum = REG_POS(i, 8);
2739 2718
 	if (cpnum != 15)
2740 2719
 	{
2741
-		printf("MRC P%i, 0, R%i, C%i, C%i, %i, %i (don't allocated coprocessor)\n", cpnum, REG_POS(i, 12), REG_POS(i, 16), REG_POS(i, 0), (i>>21)&0x7, (i>>5)&0x7);
2720
+		fprintf(stderr, "MRC P%i, 0, R%i, C%i, C%i, %i, %i (don't allocated coprocessor)\n", cpnum, REG_POS(i, 12), REG_POS(i, 16), REG_POS(i, 0), (i>>21)&0x7, (i>>5)&0x7);
2742 2721
 		return 2;
2743 2722
 	}
2744 2723
 
... ...
@@ -2928,7 +2907,7 @@ static int OP_MRC(uint32_t i)
2928 2907
 
2929 2908
 	if (bUnknown)
2930 2909
 	{
2931
-		//printf("Unknown MRC command: MRC P15, 0, R%i, C%i, C%i, %i, %i\n", REG_POS(i, 12), CRn, CRm, opcode1, opcode2);
2910
+		//fprintf(stderr, "Unknown MRC command: MRC P15, 0, R%i, C%i, C%i, %i, %i\n", REG_POS(i, 12), CRn, CRm, opcode1, opcode2);
2932 2911
 		return 1;
2933 2912
 	}
2934 2913
 
... ...
@@ -2956,7 +2935,7 @@ uint32_t op_swi(uint8_t swinum)
2956 2935
 		// TODO:
2957 2936
 		return 0;
2958 2937
 #else
2959
-		auto ctx = c.addCall(imm_ptr(ARM_swi_tab[PROCNUM][swinum]), ASMJIT_CALL_CONV, FuncBuilder0<uint32_t>());
2938
+		auto ctx = c.addCall(imm_ptr(ARM_swi_tab[PROCNUM][swinum]), ASMJIT_STDLIB_CALL_CONV, FuncBuilder0<uint32_t>());
2960 2939
 		ctx->setRet(0, bb_cycles);
2961 2940
 		c.add(bb_cycles, 3);
2962 2941
 		return 1;
... ...
@@ -2970,7 +2949,7 @@ uint32_t op_swi(uint8_t swinum)
2970 2949
 	c.mov(oldCPSR, CPSR);
2971 2950
 	JIT_COMMENT("enter SVC mode");
2972 2951
 	c.mov(mode, imm(SVC));
2973
-	auto ctx = c.addCall(imm_ptr(armcpu_switchMode), ASMJIT_CALL_CONV, FuncBuilder2<void, void *, uint8_t>());
2952
+	auto ctx = c.addCall(imm_ptr(armcpu_switchMode), ASMJIT_STDLIB_CALL_CONV, FuncBuilder2<void, void *, uint8_t>());
2974 2953
 	ctx->setArg(0, bb_cpu);
2975 2954
 	ctx->setArg(1, mode);
2976 2955
 	c.unuse(mode);
... ...
@@ -2996,7 +2975,7 @@ static int OP_SWI(uint32_t i) { return op_swi((i >> 16) & 0x1F); }
2996 2975
 // -----------------------------------------------------------------------------
2997 2976
 //   BKPT
2998 2977
 // -----------------------------------------------------------------------------
2999
-static int OP_BKPT(uint32_t i) { printf("JIT: unimplemented OP_BKPT\n"); return 0; }
2978
+static int OP_BKPT(uint32_t i) { fprintf(stderr, "JIT: unimplemented OP_BKPT\n"); return 0; }
3000 2979
 
3001 2980
 // -----------------------------------------------------------------------------
3002 2981
 //   THUMB
... ...
@@ -3625,7 +3604,7 @@ static int op_ldm_stm_thumb(uint32_t i, bool store)
3625 3604
 	uint32_t pop = popcount(bitmask);
3626 3605
 
3627 3606
 	//if (BIT_N(i, _REG_NUM(i, 8)))
3628
-	//	printf("WARNING - %sIA with Rb in Rlist (THUMB)\n", store?"STM":"LDM");
3607
+	//	fprintf(stderr, "WARNING - %sIA with Rb in Rlist (THUMB)\n", store?"STM":"LDM");
3629 3608
 
3630 3609
 	GpVar adr = c.newGpVar(kVarTypeInt32);
3631 3610
 	c.mov(adr, reg_pos_thumb(8));
... ...
@@ -4025,7 +4004,7 @@ template<int PROCNUM> static uint32_t compile_basicblock()
4025 4004
 
4026 4005
 	if (!JIT_MAPPED(start_adr & 0x0FFFFFFF, PROCNUM))
4027 4006
 	{
4028
-		printf("JIT: use unmapped memory address %08X\n", start_adr);
4007
+		fprintf(stderr, "JIT: use unmapped memory address %08X\n", start_adr);
4029 4008
 		execute = false;
4030 4009
 		return 1;
4031 4010
 	}
... ...
@@ -4156,7 +4135,7 @@ template<int PROCNUM> static uint32_t compile_basicblock()
4156 4135
 #endif
4157 4136
 	c.endFunc();
4158 4137
 
4159
-	ArmOpCompiled f = static_cast<ArmOpCompiled>(c.make());
4138
+	ArmOpCompiled f = (ArmOpCompiled)(c.make());
4160 4139
 	if (c.getError())
4161 4140
 	{
4162 4141
 		fprintf(stderr, "JIT error: %s\n", ErrorUtil::asString(c.getError()));
... ...
@@ -4205,13 +4184,14 @@ void arm_jit_reset(bool enable)
4205 4184
 #ifdef HAVE_STATIC_CODE_BUFFER
4206 4185
 	scratchptr = scratchpad;
4207 4186
 #endif
4208
-	printf("CPU mode: %s\n", enable ? "JIT" : "Interpreter");
4187
+	fprintf(stderr, "CPU mode: %s\n", enable ? "JIT" : "Interpreter");
4209 4188
 
4210 4189
 	if (enable)
4211 4190
 	{
4212
-		printf("JIT max block size %d instruction(s)\n", CommonSettings.jit_max_block_size);
4191
+		fprintf(stderr, "JIT max block size %d instruction(s)\n", CommonSettings.jit_max_block_size);
4213 4192
 #ifdef MAPPED_JIT_FUNCS
4214 4193
 		// these pointers are allocated by asmjit and need freeing
4194
+#ifndef HAVE_STATIC_CODE_BUFFER
4215 4195
 		#define JITFREE(x)  for (size_t iii = 0; iii < ARRAY_SIZE((x)); ++iii) if ((x)[iii]) runtime.getMemMgr()->release(reinterpret_cast<void *>((x)[iii])); memset((x), 0, sizeof((x)));
4216 4196
 			JITFREE(JIT.MAIN_MEM);
4217 4197
 			JITFREE(JIT.SWIRAM);
... ...
@@ -4223,6 +4203,7 @@ void arm_jit_reset(bool enable)
4223 4203
 			JITFREE(JIT.ARM7_WIRAM);
4224 4204
 			JITFREE(JIT.ARM7_WRAM);
4225 4205
 		#undef JITFREE
4206
+#endif
4226 4207
 
4227 4208
 		memset(recompile_counts, 0, sizeof(recompile_counts));
4228 4209
 		init_jit_mem();
... ...
@@ -4268,7 +4249,7 @@ static int pcmp_entry(PROFILER_ENTRY *info1, PROFILER_ENTRY *info2)
4268 4249
 void arm_jit_close()
4269 4250
 {
4270 4251
 #if PROFILER_JIT_LEVEL > 0
4271
-	printf("Generating profile report...");
4252
+	fprintf(stderr, "Generating profile report...");
4272 4253
 
4273 4254
 	for (uint8_t proc = 0; proc < 2; ++proc)
4274 4255
 	{
... ...
@@ -4393,7 +4374,7 @@ void arm_jit_close()
4393 4374
 		}
4394 4375
 #endif
4395 4376
 	}
4396
-	printf(" done.\n");
4377
+	fprintf(stderr, " done.\n");
4397 4378
 #endif
4398 4379
 }
4399 4380
 #endif // HAVE_JIT
Browse code

* Fixes for gcc and clang (while they can compile the code, the DLLs made aren't functional, but oh well).

* [2SF] Used more up-to-date asmjit, despite the ugly looking code.

Naram Qashat authored on 2014/09/17 19:51:45
Showing 1 changed files
... ...
@@ -34,7 +34,7 @@
34 34
 #include "instruction_attributes.h"
35 35
 #include "MMU.h"
36 36
 #include "MMU_timing.h"
37
-#include "utils/AsmJit/AsmJit.h"
37
+#include "utils/AsmJit/asmjit.h"
38 38
 #include "arm_jit.h"
39 39
 #include "bios.h"
40 40
 
... ...
@@ -42,10 +42,10 @@
42 42
 #define PROFILER_JIT_LEVEL 0
43 43
 
44 44
 #if PROFILER_JIT_LEVEL > 0
45
-#include <algorithm>
45
+# include <algorithm>
46 46
 #endif
47 47
 
48
-using namespace AsmJit;
48
+using namespace asmjit;
49 49
 
50 50
 #if LOG_JIT_LEVEL > 0
51 51
 #define LOG_JIT 1
... ...
@@ -53,20 +53,18 @@ using namespace AsmJit;
53 53
 #define printJIT(buf, val) \
54 54
 { \
55 55
 	JIT_COMMENT("printJIT(\""##buf"\", val);"); \
56
-	GpVar txt = c.newGpVar(kX86VarTypeGpz); \
57
-	GpVar data = c.newGpVar(kX86VarTypeGpz); \
58
-	GpVar io = c.newGpVar(kX86VarTypeGpd); \
59
-	c.lea(io, dword_ptr_abs(stdout)); \
60
-	c.lea(txt, dword_ptr_abs(&buf)); \
56
+	GpVar txt = c.newGpVar(kVarTypeIntPtr); \
57
+	GpVar data = c.newGpVar(kVarTypeIntPtr); \
58
+	GpVar io = c.newGpVar(kVarTypeInt32); \
59
+	c.lea(io, x86::dword_ptr_abs(stdout)); \
60
+	c.lea(txt, x86::dword_ptr_abs(&buf)); \
61 61
 	c.mov(data, *reinterpret_cast<GpVar *>(&val)); \
62
-	X86CompilerFuncCall* prn = c.call(reinterpret_cast<uintptr_t>(fprintf)); \
63
-	prn->setPrototype(ASMJIT_CALL_CONV, FuncBuilder3<void, void *, void *, uint32_t>()); \
64
-	prn->setArgument(0, io); \
65
-	prn->setArgument(1, txt); \
66
-	prn->setArgument(2, data); \
67
-	X86CompilerFuncCall *prn_flush = c.call(reinterpret_cast<uintptr_t>(fflush)); \
68
-	prn_flush->setPrototype(ASMJIT_CALL_CONV, FuncBuilder1<void, void *>()); \
69
-	prn_flush->setArgument(0, io); \
62
+	auto prn = c.addCall(imm_ptr(fprintf), ASMJIT_CALL_CONV, FuncBuilder3<void, void *, void *, uint32_t>()); \
63
+	prn->setArg(0, io); \
64
+	prn->setArg(1, txt); \
65
+	prn->setArg(2, data); \
66
+	auto prn_flush = c.addCall(imm_ptr(fflush), ASMJIT_CALL_CONV, FuncBuilder1<void, void *>()); \
67
+	prn_flush->setArg(0, io); \
70 68
 }
71 69
 #else
72 70
 #define LOG_JIT 0
... ...
@@ -237,7 +235,8 @@ struct ASMJIT_API StaticCodeGenerator : public Context
237 235
 static StaticCodeGenerator codegen;
238 236
 static X86Compiler c(&codegen);
239 237
 #else
240
-static X86Compiler c;
238
+static JitRuntime runtime;
239
+static X86Compiler c(&runtime);
241 240
 #endif
242 241
 
243 242
 static void emit_branch(int cond, Label to);
... ...
@@ -259,19 +258,19 @@ static uint32_t bb_constant_cycles;
259 258
 #define bb_next_instruction (bb_adr + bb_opcodesize)
260 259
 #define bb_r15 (bb_adr + 2 * bb_opcodesize)
261 260
 
262
-#define cpu_ptr(x) dword_ptr(bb_cpu, offsetof(armcpu_t, x))
263
-#define cpu_ptr_byte(x, y) byte_ptr(bb_cpu, offsetof(armcpu_t, x) + y)
261
+#define cpu_ptr(x) x86::dword_ptr(bb_cpu, offsetof(armcpu_t, x))
262
+#define cpu_ptr_byte(x, y) x86::byte_ptr(bb_cpu, offsetof(armcpu_t, x) + y)
264 263
 #define flags_ptr cpu_ptr_byte(CPSR.val, 3)
265
-#define reg_ptr(x) dword_ptr(bb_cpu, offsetof(armcpu_t, R) + 4 * (x))
266
-#define reg_pos_ptr(x) dword_ptr(bb_cpu, offsetof(armcpu_t, R) + 4 * REG_POS(i, (x)))
267
-#define reg_pos_ptrL(x) word_ptr(bb_cpu, offsetof(armcpu_t, R) + 4 * REG_POS(i, (x)))
268
-#define reg_pos_ptrH(x) word_ptr(bb_cpu, offsetof(armcpu_t, R) + 4 * REG_POS(i, (x)) + 2)
269
-#define reg_pos_ptrB(x) byte_ptr(bb_cpu, offsetof(armcpu_t, R) + 4 * REG_POS(i, (x)))
270
-#define reg_pos_thumb(x) dword_ptr(bb_cpu, offsetof(armcpu_t, R) + 4 * ((i >> (x)) & 0x7))
271
-#define reg_pos_thumbB(x) byte_ptr(bb_cpu, offsetof(armcpu_t, R) + 4 * ((i >> (x)) & 0x7))
272
-#define cp15_ptr(x) dword_ptr(bb_cp15, offsetof(armcp15_t, x))
273
-#define mmu_ptr(x) dword_ptr(bb_mmu, offsetof(MMU_struct, x))
274
-#define mmu_ptr_byte(x) byte_ptr(bb_mmu, offsetof(MMU_struct, x))
264
+#define reg_ptr(x) x86::dword_ptr(bb_cpu, offsetof(armcpu_t, R) + 4 * (x))
265
+#define reg_pos_ptr(x) x86::dword_ptr(bb_cpu, offsetof(armcpu_t, R) + 4 * REG_POS(i, (x)))
266
+#define reg_pos_ptrL(x) x86::word_ptr(bb_cpu, offsetof(armcpu_t, R) + 4 * REG_POS(i, (x)))
267
+#define reg_pos_ptrH(x) x86::word_ptr(bb_cpu, offsetof(armcpu_t, R) + 4 * REG_POS(i, (x)) + 2)
268
+#define reg_pos_ptrB(x) x86::byte_ptr(bb_cpu, offsetof(armcpu_t, R) + 4 * REG_POS(i, (x)))
269
+#define reg_pos_thumb(x) x86::dword_ptr(bb_cpu, offsetof(armcpu_t, R) + 4 * ((i >> (x)) & 0x7))
270
+#define reg_pos_thumbB(x) x86::byte_ptr(bb_cpu, offsetof(armcpu_t, R) + 4 * ((i >> (x)) & 0x7))
271
+#define cp15_ptr(x) x86::dword_ptr(bb_cp15, offsetof(armcp15_t, x))
272
+#define mmu_ptr(x) x86::dword_ptr(bb_mmu, offsetof(MMU_struct, x))
273
+#define mmu_ptr_byte(x) x86::byte_ptr(bb_mmu, offsetof(MMU_struct, x))
275 274
 static inline uint32_t _REG_NUM(uint32_t i, uint32_t n) { return (i >> n) & 0x7; }
276 275
 
277 276
 #ifndef ASMJIT_X64
... ...
@@ -281,8 +280,7 @@ static inline uint32_t _REG_NUM(uint32_t i, uint32_t n) { return (i >> n) & 0x7;
281 280
 // sequencer.reschedule = true;
282 281
 #define changeCPSR \
283 282
 { \
284
-	X86CompilerFuncCall *ctxCPSR = c.call(reinterpret_cast<void *>(NDS_Reschedule)); \
285
-	ctxCPSR->setPrototype(ASMJIT_CALL_CONV, FuncBuilder0<void>()); \
283
+	auto ctxCPSR = c.addCall(imm_ptr(NDS_Reschedule), ASMJIT_CALL_CONV, FuncBuilder0<void>()); \
286 284
 }
287 285
 
288 286
 #if PROFILER_JIT_LEVEL > 0
... ...
@@ -306,8 +304,8 @@ struct JIT_PROFILER
306 304
 
307 305
 static GpVar bb_profiler;
308 306
 
309
-#define profiler_counter_arm(opcode) qword_ptr(bb_profiler, offsetof(JIT_PROFILER, arm_count[INSTRUCTION_INDEX(opcode)]))
310
-#define profiler_counter_thumb(opcode) qword_ptr(bb_profiler, offsetof(JIT_PROFILER, thumb_count[opcode>>6]))
307
+#define profiler_counter_arm(opcode) x86::qword_ptr(bb_profiler, offsetof(JIT_PROFILER, arm_count[INSTRUCTION_INDEX(opcode)]))
308
+#define profiler_counter_thumb(opcode) x86::qword_ptr(bb_profiler, offsetof(JIT_PROFILER, thumb_count[opcode>>6]))
311 309
 
312 310
 #if PROFILER_JIT_LEVEL > 1
313 311
 struct PROFILER_ENTRY
... ...
@@ -327,18 +325,18 @@ static GpVar bb_profiler_entry;
327 325
 #define SET_NZCV(sign) \
328 326
 { \
329 327
 	JIT_COMMENT("SET_NZCV"); \
330
-	GpVar x = c.newGpVar(kX86VarTypeGpd); \
331
-	GpVar y = c.newGpVar(kX86VarTypeGpd); \
328
+	GpVar x = c.newGpVar(kVarTypeInt32); \
329
+	GpVar y = c.newGpVar(kVarTypeInt32); \
332 330
 	c.sets(x.r8Lo()); \
333 331
 	c.setz(y.r8Lo()); \
334
-	c.lea(x, ptr(y.r64(), x.r64(), kScale2Times)); \
332
+	c.lea(x, x86::ptr(y.r64(), x.r64(), 1)); \
335 333
 	if (sign) \
336 334
 		c.setnc(y.r8Lo()); \
337 335
 	else \
338 336
 		c.setc(y.r8Lo()); \
339
-	c.lea(x, ptr(y.r64(), x.r64(), kScale2Times)); \
337
+	c.lea(x, x86::ptr(y.r64(), x.r64(), 1)); \
340 338
 	c.seto(y.r8Lo()); \
341
-	c.lea(x, ptr(y.r64(), x.r64(), kScale2Times)); \
339
+	c.lea(x, x86::ptr(y.r64(), x.r64(), 1)); \
342 340
 	c.movzx(y, flags_ptr); \
343 341
 	c.shl(x, 4); \
344 342
 	c.and_(y, 0xF); \
... ...
@@ -352,14 +350,14 @@ static GpVar bb_profiler_entry;
352 350
 #define SET_NZC \
353 351
 { \
354 352
 	JIT_COMMENT("SET_NZC"); \
355
-	GpVar x = c.newGpVar(kX86VarTypeGpd); \
356
-	GpVar y = c.newGpVar(kX86VarTypeGpd); \
353
+	GpVar x = c.newGpVar(kVarTypeInt32); \
354
+	GpVar y = c.newGpVar(kVarTypeInt32); \
357 355
 	c.sets(x.r8Lo()); \
358 356
 	c.setz(y.r8Lo()); \
359
-	c.lea(x, ptr(y.r64(), x.r64(), kScale2Times)); \
357
+	c.lea(x, x86::ptr(y.r64(), x.r64(), 1)); \
360 358
 	if (cf_change) \
361 359
 	{ \
362
-		c.lea(x, ptr(rcf.r64(), x.r64(), kScale2Times)); \
360
+		c.lea(x, x86::ptr(rcf.r64(), x.r64(), 1)); \
363 361
 		c.unuse(rcf); \
364 362
 	} \
365 363
 	c.movzx(y, flags_ptr); \
... ...
@@ -388,11 +386,11 @@ static GpVar bb_profiler_entry;
388 386
 #define SET_NZ(clear_cv) \
389 387
 { \
390 388
 	JIT_COMMENT("SET_NZ"); \
391
-	GpVar x = c.newGpVar(kX86VarTypeGpz); \
392
-	GpVar y = c.newGpVar(kX86VarTypeGpz); \
389
+	GpVar x = c.newGpVar(kVarTypeIntPtr); \
390
+	GpVar y = c.newGpVar(kVarTypeIntPtr); \
393 391
 	c.sets(x.r8Lo()); \
394 392
 	c.setz(y.r8Lo()); \
395
-	c.lea(x, ptr(y.r64(), x.r64(), kScale2Times)); \
393
+	c.lea(x, x86::ptr(y.r64(), x.r64(), 1)); \
396 394
 	c.movzx(y, flags_ptr); \
397 395
 	c.and_(y, clear_cv?0x0F:0x3F); \
398 396
 	c.shl(x, 6); \
... ...
@@ -404,7 +402,7 @@ static GpVar bb_profiler_entry;
404 402
 #define SET_Q \
405 403
 { \
406 404
 	JIT_COMMENT("SET_Q"); \
407
-	GpVar x = c.newGpVar(kX86VarTypeGpz); \
405
+	GpVar x = c.newGpVar(kVarTypeIntPtr); \
408 406
 	c.seto(x.r8Lo()); \
409 407
 	c.shl(x, 3); \
410 408
 	c.or_(flags_ptr, x.r8Lo()); \
... ...
@@ -414,19 +412,18 @@ static GpVar bb_profiler_entry;
414 412
 #define S_DST_R15 \
415 413
 { \
416 414
 	JIT_COMMENT("S_DST_R15"); \
417
-	GpVar SPSR = c.newGpVar(kX86VarTypeGpd); \
418
-	GpVar tmp = c.newGpVar(kX86VarTypeGpd); \
415
+	GpVar SPSR = c.newGpVar(kVarTypeInt32); \
416
+	GpVar tmp = c.newGpVar(kVarTypeInt32); \
419 417
 	c.mov(SPSR, cpu_ptr(SPSR.val)); \
420 418
 	c.mov(tmp, SPSR); \
421 419
 	c.and_(tmp, 0x1F); \
422
-	X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(armcpu_switchMode)); \
423
-	ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<void, void *, uint8_t>()); \
424
-	ctx->setArgument(0, bb_cpu); \
425
-	ctx->setArgument(1, tmp); \
420
+	auto ctx = c.addCall(imm_ptr(armcpu_switchMode), ASMJIT_CALL_CONV, FuncBuilder2<void, void *, uint8_t>()); \
421
+	ctx->setArg(0, bb_cpu); \
422
+	ctx->setArg(1, tmp); \
426 423
 	c.mov(cpu_ptr(CPSR.val), SPSR); \
427 424
 	c.and_(SPSR, 1 << 5); \
428 425
 	c.shr(SPSR, 5); \
429
-	c.lea(tmp, ptr_abs(reinterpret_cast<void *>(0xFFFFFFFC), SPSR.r64(), kScale2Times)); \
426
+	c.lea(tmp, x86::ptr_abs(0xFFFFFFFC, SPSR.r64(), 1)); \
430 427
 	c.and_(tmp, reg_ptr(15)); \
431 428
 	c.mov(cpu_ptr(next_instruction), tmp); \
432 429
 	c.unuse(tmp); \
... ...
@@ -438,7 +435,7 @@ static GpVar bb_profiler_entry;
438 435
 	JIT_COMMENT("LSL_IMM"); \
439 436
 	bool rhs_is_imm = false; \
440 437
 	uint32_t imm = (i >> 7) & 0x1F; \
441
-	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
438
+	GpVar rhs = c.newGpVar(kVarTypeInt32); \
442 439
 	c.mov(rhs, reg_pos_ptr(0)); \
443 440
 	if (imm) \
444 441
 		c.shl(rhs, imm); \
... ...
@@ -449,14 +446,14 @@ static GpVar bb_profiler_entry;
449 446
 	bool rhs_is_imm = false; \
450 447
 	uint8_t cf_change = 0; \
451 448
 	GpVar rcf; \
452
-	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
449
+	GpVar rhs = c.newGpVar(kVarTypeInt32); \
453 450
 	uint32_t imm = (i >> 7)&0x1F; \
454 451
 	c.mov(rhs, reg_pos_ptr(0)); \
455 452
 	if (imm)  \
456 453
 	{ \
457 454
 		cf_change = 1; \
458 455
 		c.shl(rhs, imm); \
459
-		rcf = c.newGpVar(kX86VarTypeGpd); \
456
+		rcf = c.newGpVar(kVarTypeInt32); \
460 457
 		c.setc(rcf.r8Lo()); \
461 458
 	}
462 459
 
... ...
@@ -464,7 +461,7 @@ static GpVar bb_profiler_entry;
464 461
 	JIT_COMMENT("LSR_IMM"); \
465 462
 	bool rhs_is_imm = false; \
466 463
 	uint32_t imm = (i >> 7) & 0x1F; \
467
-	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
464
+	GpVar rhs = c.newGpVar(kVarTypeInt32); \
468 465
 	if (imm) \
469 466
 	{ \
470 467
 		c.mov(rhs, reg_pos_ptr(0)); \
... ...
@@ -478,8 +475,8 @@ static GpVar bb_profiler_entry;
478 475
 	JIT_COMMENT("S_LSR_IMM"); \
479 476
 	bool rhs_is_imm = false; \
480 477
 	uint8_t cf_change = 1; \
481
-	GpVar rcf = c.newGpVar(kX86VarTypeGpd); \
482
-	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
478
+	GpVar rcf = c.newGpVar(kVarTypeInt32); \
479
+	GpVar rhs = c.newGpVar(kVarTypeInt32); \
483 480
 	uint32_t imm = (i >> 7) & 0x1F; \
484 481
 	c.mov(rhs, reg_pos_ptr(0)); \
485 482
 	if (!imm) \
... ...
@@ -498,7 +495,7 @@ static GpVar bb_profiler_entry;
498 495
 	JIT_COMMENT("ASR_IMM"); \
499 496
 	bool rhs_is_imm = false; \
500 497
 	uint32_t imm = (i >> 7) & 0x1F; \
501
-	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
498
+	GpVar rhs = c.newGpVar(kVarTypeInt32); \
502 499
 	c.mov(rhs, reg_pos_ptr(0)); \
503 500
 	if (!imm) \
504 501
 		imm = 31; \
... ...
@@ -509,8 +506,8 @@ static GpVar bb_profiler_entry;
509 506
 	JIT_COMMENT("S_ASR_IMM"); \
510 507
 	bool rhs_is_imm = false; \
511 508
 	uint8_t cf_change = 1; \
512
-	GpVar rcf = c.newGpVar(kX86VarTypeGpd); \
513
-	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
509
+	GpVar rcf = c.newGpVar(kVarTypeInt32); \
510
+	GpVar rhs = c.newGpVar(kVarTypeInt32); \
514 511
 	uint32_t imm = (i >> 7) & 0x1F; \
515 512
 	c.mov(rhs, reg_pos_ptr(0)); \
516 513
 	if (!imm) \
... ...
@@ -522,7 +519,7 @@ static GpVar bb_profiler_entry;
522 519
 	JIT_COMMENT("ROR_IMM"); \
523 520
 	bool rhs_is_imm = false; \
524 521
 	uint32_t imm = (i >> 7) & 0x1F; \
525
-	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
522
+	GpVar rhs = c.newGpVar(kVarTypeInt32); \
526 523
 	c.mov(rhs, reg_pos_ptr(0)); \
527 524
 	if (!imm) \
528 525
 	{ \
... ...
@@ -537,8 +534,8 @@ static GpVar bb_profiler_entry;
537 534
 	JIT_COMMENT("S_ROR_IMM"); \
538 535
 	bool rhs_is_imm = false; \
539 536
 	uint8_t cf_change = 1; \
540
-	GpVar rcf = c.newGpVar(kX86VarTypeGpd); \
541
-	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
537
+	GpVar rcf = c.newGpVar(kVarTypeInt32); \
538
+	GpVar rhs = c.newGpVar(kVarTypeInt32); \
542 539
 	uint32_t imm = (i >> 7) & 0x1F; \
543 540
 	c.mov(rhs, reg_pos_ptr(0)); \
544 541
 	if (!imm) \
... ...
@@ -571,7 +568,7 @@ static GpVar bb_profiler_entry;
571 568
 	if ((i >> 8) & 0xF) \
572 569
 	{ \
573 570
 		cf_change = 1; \
574
-		rcf = c.newGpVar(kX86VarTypeGpd); \
571
+		rcf = c.newGpVar(kVarTypeInt32); \
575 572
 		c.mov(rcf, BIT31(rhs)); \
576 573
 	} \
577 574
 	uint32_t rhs_first = rhs;
... ...
@@ -592,9 +589,9 @@ static GpVar bb_profiler_entry;
592 589
 #define LSX_REG(name, x86inst, sign) \
593 590
 	JIT_COMMENT(#name); \
594 591
 	bool rhs_is_imm = false; \
595
-	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
596
-	GpVar imm = c.newGpVar(kX86VarTypeGpz); \
597
-	GpVar tmp = c.newGpVar(kX86VarTypeGpz); \
592
+	GpVar rhs = c.newGpVar(kVarTypeInt32); \
593
+	GpVar imm = c.newGpVar(kVarTypeIntPtr); \
594
+	GpVar tmp = c.newGpVar(kVarTypeIntPtr); \
598 595
 	if (sign) \
599 596
 		c.mov(tmp, 31); \
600 597
 	else \
... ...
@@ -613,9 +610,9 @@ static GpVar bb_profiler_entry;
613 610
 	JIT_COMMENT(#name); \
614 611
 	bool rhs_is_imm = false; \
615 612
 	uint8_t cf_change = 1; \
616
-	GpVar rcf = c.newGpVar(kX86VarTypeGpd); \
617
-	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
618
-	GpVar imm = c.newGpVar(kX86VarTypeGpz); \
613
+	GpVar rcf = c.newGpVar(kVarTypeInt32); \
614
+	GpVar rhs = c.newGpVar(kVarTypeInt32); \
615
+	GpVar imm = c.newGpVar(kVarTypeIntPtr); \
619 616
 	Label __zero = c.newLabel(); \
620 617
 	Label __lt32 = c.newLabel(); \
621 618
 	Label __done = c.newLabel(); \
... ...
@@ -662,8 +659,8 @@ static GpVar bb_profiler_entry;
662 659
 #define ROR_REG \
663 660
 	JIT_COMMENT("ROR_REG"); \
664 661
 	bool rhs_is_imm = false; \
665
-	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
666
-	GpVar imm = c.newGpVar(kX86VarTypeGpz); \
662
+	GpVar rhs = c.newGpVar(kVarTypeInt32); \
663
+	GpVar imm = c.newGpVar(kVarTypeIntPtr); \
667 664
 	c.mov(rhs, reg_pos_ptr(0)); \
668 665
 	c.mov(imm, reg_pos_ptrB(8)); \
669 666
 	c.ror(rhs, imm.r8Lo());
... ...
@@ -672,9 +669,9 @@ static GpVar bb_profiler_entry;
672 669
 	JIT_COMMENT("S_ROR_REG"); \
673 670
 	bool rhs_is_imm = false; \
674 671
 	bool cf_change = 1; \
675
-	GpVar rcf = c.newGpVar(kX86VarTypeGpd); \
676
-	GpVar imm = c.newGpVar(kX86VarTypeGpz); \
677
-	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
672
+	GpVar rcf = c.newGpVar(kVarTypeInt32); \
673
+	GpVar imm = c.newGpVar(kVarTypeIntPtr); \
674
+	GpVar rhs = c.newGpVar(kVarTypeInt32); \
678 675
 	Label __zero = c.newLabel(); \
679 676
 	Label __zero_1F = c.newLabel(); \
680 677
 	Label __done = c.newLabel(); \
... ...
@@ -707,7 +704,7 @@ static void emit_MMU_aluMemCycles(int alu_cycles, GpVar mem_cycles, int populati
707 704
 	{
708 705
 		if (population < alu_cycles)
709 706
 		{
710
-			GpVar x = c.newGpVar(kX86VarTypeGpd);
707
+			GpVar x = c.newGpVar(kVarTypeInt32);
711 708
 			c.mov(x, alu_cycles);
712 709
 			c.cmp(mem_cycles, alu_cycles);
713 710
 			c.cmovl(mem_cycles, x);
... ...
@@ -722,7 +719,7 @@ static void emit_MMU_aluMemCycles(int alu_cycles, GpVar mem_cycles, int populati
722 719
 // -----------------------------------------------------------------------------
723 720
 #define OP_ARITHMETIC(arg, x86inst, symmetric, flags) \
724 721
 	arg; \
725
-	GpVar lhs = c.newGpVar(kX86VarTypeGpd); \
722
+	GpVar lhs = c.newGpVar(kVarTypeInt32); \
726 723
 	if (REG_POS(i, 12) == REG_POS(i, 16)) \
727 724
 		c.x86inst(reg_pos_ptr(12), rhs); \
728 725
 	else if (symmetric && !rhs_is_imm) \
... ...
@@ -750,7 +747,7 @@ static void emit_MMU_aluMemCycles(int alu_cycles, GpVar mem_cycles, int populati
750 747
 	{ \
751 748
 		if (REG_POS(i, 12) == 15) \
752 749
 		{ \
753
-			GpVar tmp = c.newGpVar(kX86VarTypeGpd); \
750
+			GpVar tmp = c.newGpVar(kVarTypeInt32); \
754 751
 			c.mov(tmp, reg_ptr(15)); \
755 752
 			c.mov(cpu_ptr(next_instruction), tmp); \
756 753
 			bb_constant_cycles += 2; \
... ...
@@ -760,7 +757,7 @@ static void emit_MMU_aluMemCycles(int alu_cycles, GpVar mem_cycles, int populati
760 757
 
761 758
 #define OP_ARITHMETIC_R(arg, x86inst, flags) \
762 759
 	arg; \
763
-	GpVar lhs = c.newGpVar(kX86VarTypeGpd); \
760
+	GpVar lhs = c.newGpVar(kVarTypeInt32); \
764 761
 	c.mov(lhs, rhs); \
765 762
 	c.x86inst(lhs, reg_pos_ptr(16)); \
766 763
 	c.mov(reg_pos_ptr(12), lhs); \
... ...
@@ -778,7 +775,7 @@ static void emit_MMU_aluMemCycles(int alu_cycles, GpVar mem_cycles, int populati
778 775
 	{ \
779 776
 		if (REG_POS(i, 12) == 15) \
780 777
 		{ \
781
-			GpVar tmp = c.newGpVar(kX86VarTypeGpd); \
778
+			GpVar tmp = c.newGpVar(kVarTypeInt32); \
782 779
 			c.mov(cpu_ptr(next_instruction), lhs); \
783 780
 			bb_constant_cycles += 2; \
784 781
 		} \
... ...
@@ -796,7 +793,7 @@ static void emit_MMU_aluMemCycles(int alu_cycles, GpVar mem_cycles, int populati
796 793
 	} \
797 794
 	else \
798 795
 	{ \
799
-		GpVar lhs = c.newGpVar(kX86VarTypeGpd); \
796
+		GpVar lhs = c.newGpVar(kVarTypeInt32); \
800 797
 		c.mov(lhs, reg_pos_ptr(16)); \
801 798
 		c.x86inst(lhs, rhs); \
802 799
 		c.mov(reg_pos_ptr(12), lhs); \
... ...
@@ -1046,7 +1043,7 @@ static int OP_TST_IMM_VAL(uint32_t i) { OP_TST_(S_IMM_VAL); }
1046 1043
 		c.xor_(*reinterpret_cast<GpVar *>(&rhs), reg_pos_ptr(16)); \
1047 1044
 	else \
1048 1045
 	{ \
1049
-		GpVar x = c.newGpVar(kX86VarTypeGpd); \
1046
+		GpVar x = c.newGpVar(kVarTypeInt32); \
1050 1047
 		c.mov(x, rhs); \
1051 1048
 		c.xor_(x, reg_pos_ptr(16)); \
1052 1049
 	} \
... ...
@@ -1095,7 +1092,7 @@ static int OP_CMP_IMM_VAL(uint32_t i) { OP_CMP(IMM_VAL); }
1095 1092
 		c.cmp(reg_pos_ptr(16), -rhs_imm); \
1096 1093
 	else \
1097 1094
 	{ \
1098
-		GpVar lhs = c.newGpVar(kX86VarTypeGpd); \
1095
+		GpVar lhs = c.newGpVar(kVarTypeInt32); \
1099 1096
 		c.mov(lhs, reg_pos_ptr(16)); \
1100 1097
 		c.add(lhs, rhs); \
1101 1098
 	} \
... ...
@@ -1202,7 +1199,7 @@ static void MUL_Mxx_END(GpVar x, bool sign, int cycles)
1202 1199
 {
1203 1200
 	if (sign)
1204 1201
 	{
1205
-		GpVar y = c.newGpVar(kX86VarTypeGpd);
1202
+		GpVar y = c.newGpVar(kVarTypeInt32);
1206 1203
 		c.mov(y, x);
1207 1204
 		c.sar(x, 31);
1208 1205
 		c.xor_(x, y);
... ...
@@ -1214,12 +1211,12 @@ static void MUL_Mxx_END(GpVar x, bool sign, int cycles)
1214 1211
 }
1215 1212
 
1216 1213
 #define OP_MUL_(op, width, sign, accum, flags) \
1217
-	GpVar lhs = c.newGpVar(kX86VarTypeGpd); \
1218
-	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
1214
+	GpVar lhs = c.newGpVar(kVarTypeInt32); \
1215
+	GpVar rhs = c.newGpVar(kVarTypeInt32); \
1219 1216
 	GpVar hi; \
1220 1217
 	if (width) \
1221 1218
 	{ \
1222
-		hi = c.newGpVar(kX86VarTypeGpd); \
1219
+		hi = c.newGpVar(kVarTypeInt32); \
1223 1220
 		c.xor_(hi, hi); \
1224 1221
 	} \
1225 1222
 	c.mov(lhs, reg_pos_ptr(0)); \
... ...
@@ -1281,13 +1278,13 @@ static int OP_SMULL_S(uint32_t i) { OP_MUL_(c.imul(hi,lhs,rhs), 1, 1, 0, 1); }
1281 1278
 static int OP_SMLAL_S(uint32_t i) { OP_MUL_(c.imul(hi,lhs,rhs), 1, 1, 1, 1); }
1282 1279
 
1283 1280
 #define OP_MULxy_(op, x, y, width, accum, flags) \
1284
-	GpVar lhs = c.newGpVar(kX86VarTypeGpd); \
1285
-	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
1281
+	GpVar lhs = c.newGpVar(kVarTypeInt32); \
1282
+	GpVar rhs = c.newGpVar(kVarTypeInt32); \
1286 1283
 	GpVar hi; \
1287 1284
 	c.movsx(lhs, reg_pos_ptr##x(0)); \
1288 1285
 	c.movsx(rhs, reg_pos_ptr##y(8)); \
1289 1286
 	if (width) \
1290
-		hi = c.newGpVar(kX86VarTypeGpd); \
1287
+		hi = c.newGpVar(kVarTypeInt32); \
1291 1288
 	op; \
1292 1289
 	if (width && accum) \
1293 1290
 	{ \
... ...
@@ -1352,8 +1349,8 @@ static int OP_SMLAL_T_T(uint32_t i) { OP_MULxy_(c.imul(hi,lhs,rhs), H, H, 1, 1,
1352 1349
 // -----------------------------------------------------------------------------
1353 1350
 #ifdef ASMJIT_X64
1354 1351
 #define OP_SMxxW_(x, accum, flags) \
1355
-	GpVar lhs = c.newGpVar(kX86VarTypeGpz); \
1356
-	GpVar rhs = c.newGpVar(kX86VarTypeGpz); \
1352
+	GpVar lhs = c.newGpVar(kVarTypeIntPtr); \
1353
+	GpVar rhs = c.newGpVar(kVarTypeIntPtr); \
1357 1354
 	c.movsx(lhs, reg_pos_ptr##x(8)); \
1358 1355
 	c.movsxd(rhs, reg_pos_ptr(0)); \
1359 1356
 	c.imul(lhs, rhs);  \
... ...
@@ -1366,9 +1363,9 @@ static int OP_SMLAL_T_T(uint32_t i) { OP_MULxy_(c.imul(hi,lhs,rhs), H, H, 1, 1,
1366 1363
 	return 1;
1367 1364
 #else
1368 1365
 #define OP_SMxxW_(x, accum, flags) \
1369
-	GpVar lhs = c.newGpVar(kX86VarTypeGpd); \
1370
-	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
1371
-	GpVar hi = c.newGpVar(kX86VarTypeGpd); \
1366
+	GpVar lhs = c.newGpVar(kVarTypeInt32); \
1367
+	GpVar rhs = c.newGpVar(kVarTypeInt32); \
1368
+	GpVar hi = c.newGpVar(kVarTypeInt32); \
1372 1369
 	c.movsx(lhs, reg_pos_ptr##x(8)); \
1373 1370
 	c.mov(rhs, reg_pos_ptr(0)); \
1374 1371
 	c.imul(hi, lhs, rhs);  \
... ...
@@ -1393,7 +1390,7 @@ static int OP_SMLAW_T(uint32_t i) { OP_SMxxW_(H, 1, 1); }
1393 1390
 // -----------------------------------------------------------------------------
1394 1391
 static int OP_MRS_CPSR(uint32_t i)
1395 1392
 {
1396
-	GpVar x = c.newGpVar(kX86VarTypeGpd);
1393
+	GpVar x = c.newGpVar(kVarTypeInt32);
1397 1394
 	c.mov(x, cpu_ptr(CPSR));
1398 1395
 	c.mov(reg_pos_ptr(12), x);
1399 1396
 	return 1;
... ...
@@ -1401,7 +1398,7 @@ static int OP_MRS_CPSR(uint32_t i)
1401 1398
 
1402 1399
 static int OP_MRS_SPSR(uint32_t i)
1403 1400
 {
1404
-	GpVar x = c.newGpVar(kX86VarTypeGpd);
1401
+	GpVar x = c.newGpVar(kVarTypeInt32);
1405 1402
 	c.mov(x, cpu_ptr(SPSR));
1406 1403
 	c.mov(reg_pos_ptr(12), x);
1407 1404
 	return 1;
... ...
@@ -1409,14 +1406,14 @@ static int OP_MRS_SPSR(uint32_t i)
1409 1406
 
1410 1407
 // TODO: SPSR: if(cpu->CPSR.bits.mode == USR || cpu->CPSR.bits.mode == SYS) return 1;
1411 1408
 #define OP_MSR_(reg, args, sw) \
1412
-	GpVar operand = c.newGpVar(kX86VarTypeGpd); \
1409
+	GpVar operand = c.newGpVar(kVarTypeInt32); \
1413 1410
 	args; \
1414 1411
 	c.mov(operand, rhs); \
1415 1412
 	switch ((i >> 16) & 0xF) \
1416 1413
 	{ \
1417 1414
 		case 0x1: /* bit 16 */ \
1418 1415
 		{ \
1419
-			GpVar mode = c.newGpVar(kX86VarTypeGpd); \
1416
+			GpVar mode = c.newGpVar(kVarTypeInt32); \
1420 1417
 			Label __skip = c.newLabel(); \
1421 1418
 			c.mov(mode, cpu_ptr(CPSR)); \
1422 1419
 			c.and_(mode, 0x1F); \
... ...
@@ -1426,10 +1423,10 @@ static int OP_MRS_SPSR(uint32_t i)
1426 1423
 			{ \
1427 1424
 				c.mov(mode, rhs); \
1428 1425
 				c.and_(mode, 0x1F); \
1429
-				X86CompilerFuncCall* ctx = c.call(reinterpret_cast<void *>(armcpu_switchMode)); \
1430
-				ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<void, void *, uint8_t>()); \
1431
-				ctx->setArgument(0, bb_cpu); \
1432
-				ctx->setArgument(1, mode); \
1426
+				auto ctx = c.addCall(imm_ptr(armcpu_switchMode), ASMJIT_CALL_CONV, \
1427
+					FuncBuilder2<void, void *, uint8_t>()); \
1428
+				ctx->setArg(0, bb_cpu); \
1429
+				ctx->setArg(1, mode); \
1433 1430
 			} \
1434 1431
 			Mem xPSR_memB = cpu_ptr_byte(reg, 0); \
1435 1432
 			c.mov(xPSR_memB, operand.r8Lo()); \
... ...
@@ -1439,7 +1436,7 @@ static int OP_MRS_SPSR(uint32_t i)
1439 1436
 		} \
1440 1437
 		case 0x2: /* bit 17 */ \
1441 1438
 		{ \
1442
-			GpVar mode = c.newGpVar(kX86VarTypeGpd); \
1439
+			GpVar mode = c.newGpVar(kVarTypeInt32); \
1443 1440
 			Label __skip = c.newLabel(); \
1444 1441
 			c.mov(mode, cpu_ptr(CPSR)); \
1445 1442
 			c.and_(mode, 0x1F); \
... ...
@@ -1454,7 +1451,7 @@ static int OP_MRS_SPSR(uint32_t i)
1454 1451
 		} \
1455 1452
 		case 0x4: /* bit 18 */ \
1456 1453
 		{ \
1457
-			GpVar mode = c.newGpVar(kX86VarTypeGpd); \
1454
+			GpVar mode = c.newGpVar(kVarTypeInt32); \
1458 1455
 			Label __skip = c.newLabel(); \
1459 1456
 			c.mov(mode, cpu_ptr(CPSR)); \
1460 1457
 			c.and_(mode, 0x1F); \
... ...
@@ -1481,8 +1478,8 @@ static int OP_MRS_SPSR(uint32_t i)
1481 1478
 	static uint32_t byte_mask_USR = BIT19(i) ? 0xFF000000 : 0x00000000; \
1482 1479
 \
1483 1480
 	Mem xPSR_mem = cpu_ptr(reg.val); \
1484
-	GpVar xPSR = c.newGpVar(kX86VarTypeGpd); \
1485
-	GpVar mode = c.newGpVar(kX86VarTypeGpd); \
1481
+	GpVar xPSR = c.newGpVar(kVarTypeInt32); \
1482
+	GpVar mode = c.newGpVar(kVarTypeInt32); \
1486 1483
 	Label __USR = c.newLabel(); \
1487 1484
 	Label __done = c.newLabel(); \
1488 1485
 	c.mov(mode, cpu_ptr(CPSR.val)); \
... ...
@@ -1495,10 +1492,10 @@ static int OP_MRS_SPSR(uint32_t i)
1495 1492
 		/* armcpu_switchMode */ \
1496 1493
 		c.mov(mode, rhs); \
1497 1494
 		c.and_(mode, 0x1F); \
1498
-		X86CompilerFuncCall* ctx = c.call(reinterpret_cast<void *>(armcpu_switchMode)); \
1499
-		ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<void, void *, uint8_t>()); \
1500
-		ctx->setArgument(0, bb_cpu); \
1501
-		ctx->setArgument(1, mode); \
1495
+		auto ctx = c.addCall(imm_ptr(armcpu_switchMode), ASMJIT_CALL_CONV, \
1496
+			FuncBuilder2<void, void *, uint8_t>()); \
1497
+		ctx->setArg(0, bb_cpu); \
1498
+		ctx->setArg(1, mode); \
1502 1499
 	} \
1503 1500
 	/* cpu->CPSR.val = (cpu->CPSR.val & ~byte_mask) | (operand & byte_mask); */ \
1504 1501
 	c.mov(xPSR, xPSR_mem); \
... ...
@@ -1602,8 +1599,8 @@ static uint32_t add(uint32_t lhs, uint32_t rhs) { return lhs + rhs; }
1602 1599
 static uint32_t sub(uint32_t lhs, uint32_t rhs) { return lhs - rhs; }
1603 1600
 
1604 1601
 #define OP_LDR_(mem_op, arg, sign_op, writeback) \
1605
-	GpVar adr = c.newGpVar(kX86VarTypeGpd); \
1606
-	GpVar dst = c.newGpVar(kX86VarTypeGpz); \
1602
+	GpVar adr = c.newGpVar(kVarTypeInt32); \
1603
+	GpVar dst = c.newGpVar(kVarTypeIntPtr); \
1607 1604
 	c.mov(adr, reg_pos_ptr(16)); \
1608 1605
 	c.lea(dst, reg_pos_ptr(12)); \
1609 1606
 	arg; \
... ...
@@ -1618,25 +1615,25 @@ static uint32_t sub(uint32_t lhs, uint32_t rhs) { return lhs - rhs; }
1618 1615
 		} \
1619 1616
 		else if (writeback > 0) \
1620 1617
 		{ \
1621
-			GpVar tmp_reg = c.newGpVar(kX86VarTypeGpd); \
1618
+			GpVar tmp_reg = c.newGpVar(kVarTypeInt32); \
1622 1619
 			c.mov(tmp_reg, adr); \
1623 1620
 			c.sign_op(tmp_reg, rhs); \
1624 1621
 			c.mov(reg_pos_ptr(16), tmp_reg); \
1625 1622
 		} \
1626 1623
 	} \
1627
-	uint32_t adr_first = sign_op(cpu->R[REG_POS(i,16)], rhs_first); \
1628
-	X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(mem_op##_tab[PROCNUM][classify_adr(adr_first, 0)])); \
1629
-	ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<uint32_t, uint32_t, uint32_t *>()); \
1630
-	ctx->setArgument(0, adr); \
1631
-	ctx->setArgument(1, dst); \
1632
-	ctx->setReturn(bb_cycles); \
1624
+	uint32_t adr_first = sign_op(cpu->R[REG_POS(i, 16)], rhs_first); \
1625
+	auto ctx = c.addCall(imm_ptr(mem_op##_tab[PROCNUM][classify_adr(adr_first, 0)]), ASMJIT_CALL_CONV, \
1626
+		FuncBuilder2<uint32_t, uint32_t, uint32_t *>()); \
1627
+	ctx->setArg(0, adr); \
1628
+	ctx->setArg(1, dst); \
1629
+	ctx->setRet(0, bb_cycles); \
1633 1630
 	if (REG_POS(i, 12) == 15) \
1634 1631
 	{ \
1635
-		GpVar tmp = c.newGpVar(kX86VarTypeGpd); \
1632
+		GpVar tmp = c.newGpVar(kVarTypeInt32); \
1636 1633
 		c.mov(tmp, reg_ptr(15)); \
1637 1634
 		if (!PROCNUM) \
1638 1635
 		{ \
1639
-			GpVar thumb = c.newGpVar(kX86VarTypeGpz); \
1636
+			GpVar thumb = c.newGpVar(kVarTypeIntPtr); \
1640 1637
 			c.movzx(thumb, reg_pos_ptrB(16)); \
1641 1638
 			c.and_(thumb, 1); \
1642 1639
 			c.shl(thumb, 5); \
... ...
@@ -1789,8 +1786,8 @@ static const OpSTR STRB_tab[2][3] = { T(OP_STRB) };
1789 1786
 #undef T
1790 1787
 
1791 1788
 #define OP_STR_(mem_op, arg, sign_op, writeback) \
1792
-	GpVar adr = c.newGpVar(kX86VarTypeGpd); \
1793
-	GpVar data = c.newGpVar(kX86VarTypeGpd); \
1789
+	GpVar adr = c.newGpVar(kVarTypeInt32); \
1790
+	GpVar data = c.newGpVar(kVarTypeInt32); \
1794 1791
 	c.mov(adr, reg_pos_ptr(16)); \
1795 1792
 	c.mov(data, reg_pos_ptr(12)); \
1796 1793
 	arg; \
... ...
@@ -1805,18 +1802,18 @@ static const OpSTR STRB_tab[2][3] = { T(OP_STRB) };
1805 1802
 		} \
1806 1803
 		else if (writeback > 0) \
1807 1804
 		{ \
1808
-			GpVar tmp_reg = c.newGpVar(kX86VarTypeGpd); \
1805
+			GpVar tmp_reg = c.newGpVar(kVarTypeInt32); \
1809 1806
 			c.mov(tmp_reg, adr); \
1810 1807
 			c.sign_op(tmp_reg, rhs); \
1811 1808
 			c.mov(reg_pos_ptr(16), tmp_reg); \
1812 1809
 		} \
1813 1810
 	} \
1814 1811
 	uint32_t adr_first = sign_op(cpu->R[REG_POS(i,16)], rhs_first); \
1815
-	X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(mem_op##_tab[PROCNUM][classify_adr(adr_first, 1)])); \
1816
-	ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<uint32_t, uint32_t, uint32_t>()); \
1817
-	ctx->setArgument(0, adr); \
1818
-	ctx->setArgument(1, data); \
1819
-	ctx->setReturn(bb_cycles); \
1812
+	auto ctx = c.addCall(imm_ptr(mem_op##_tab[PROCNUM][classify_adr(adr_first, 1)]), ASMJIT_CALL_CONV, \
1813
+		FuncBuilder2<uint32_t, uint32_t, uint32_t>()); \
1814
+	ctx->setArg(0, adr); \
1815
+	ctx->setArg(1, data); \
1816
+	ctx->setRet(0, bb_cycles); \
1820 1817
 	return 1;
1821 1818
 
1822 1819
 static int OP_STR_P_IMM_OFF(uint32_t i) { OP_STR_(STR, IMM_OFF_12, add, 0); }
... ...
@@ -1925,7 +1922,7 @@ static const LDRD_STRD_REG op_strd_tab[2][16] = { { T(OP_STRD_REG, 0) }, { T(OP_
1925 1922
 static int OP_LDRD_STRD_POST_INDEX(uint32_t i)
1926 1923
 {
1927 1924
 	uint8_t Rd_num = REG_POS(i, 12);
1928
-	
1925
+
1929 1926
 	if (Rd_num == 14)
1930 1927
 	{
1931 1928
 		printf("OP_LDRD_STRD_POST_INDEX: use R14!!!!\n");
... ...
@@ -1936,8 +1933,8 @@ static int OP_LDRD_STRD_POST_INDEX(uint32_t i)
1936 1933
 		printf("OP_LDRD_STRD_POST_INDEX: ERROR!!!!\n");
1937 1934
 		return 0; // TODO: exception
1938 1935
 	}
1939
-	GpVar Rd = c.newGpVar(kX86VarTypeGpd);
1940
-	GpVar addr = c.newGpVar(kX86VarTypeGpd);
1936
+	GpVar Rd = c.newGpVar(kVarTypeInt32);
1937
+	GpVar addr = c.newGpVar(kVarTypeInt32);
1941 1938
 
1942 1939
 	c.mov(Rd, reg_pos_ptr(16));
1943 1940
 	c.mov(addr, reg_pos_ptr(16));
... ...
@@ -1950,15 +1947,15 @@ static int OP_LDRD_STRD_POST_INDEX(uint32_t i)
1950 1947
 	}
1951 1948
 	else
1952 1949
 	{
1953
-		GpVar idx = c.newGpVar(kX86VarTypeGpd);
1950
+		GpVar idx = c.newGpVar(kVarTypeInt32);
1954 1951
 		c.mov(idx, reg_pos_ptr(0));
1955 1952
 		BIT23(i) ? c.add(reg_pos_ptr(16), idx) : c.sub(reg_pos_ptr(16), idx);
1956 1953
 	}
1957 1954
 
1958
-	X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(BIT5(i) ? op_strd_tab[PROCNUM][Rd_num] : op_ldrd_tab[PROCNUM][Rd_num]));
1959
-	ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder1<uint32_t, uint32_t>());
1960
-	ctx->setArgument(0, addr);
1961
-	ctx->setReturn(bb_cycles);
1955
+	auto ctx = c.addCall(imm_ptr(BIT5(i) ? op_strd_tab[PROCNUM][Rd_num] : op_ldrd_tab[PROCNUM][Rd_num]),
1956
+		ASMJIT_CALL_CONV, FuncBuilder1<uint32_t, uint32_t>());
1957
+	ctx->setArg(0, addr);
1958
+	ctx->setRet(0, bb_cycles);
1962 1959
 	emit_MMU_aluMemCycles(3, bb_cycles, 0);
1963 1960
 	return 1;
1964 1961
 }
... ...
@@ -1966,7 +1963,7 @@ static int OP_LDRD_STRD_POST_INDEX(uint32_t i)
1966 1963
 static int OP_LDRD_STRD_OFFSET_PRE_INDEX(uint32_t i)
1967 1964
 {
1968 1965
 	uint8_t Rd_num = REG_POS(i, 12);
1969
-	
1966
+
1970 1967
 	if (Rd_num == 14)
1971 1968
 	{
1972 1969
 		printf("OP_LDRD_STRD_OFFSET_PRE_INDEX: use R14!!!!\n");
... ...
@@ -1977,8 +1974,8 @@ static int OP_LDRD_STRD_OFFSET_PRE_INDEX(uint32_t i)
1977 1974
 		printf("OP_LDRD_STRD_OFFSET_PRE_INDEX: ERROR!!!!\n");
1978 1975
 		return 0; // TODO: exception
1979 1976
 	}
1980
-	GpVar Rd = c.newGpVar(kX86VarTypeGpd);
1981
-	GpVar addr = c.newGpVar(kX86VarTypeGpd);
1977
+	GpVar Rd = c.newGpVar(kVarTypeInt32);
1978
+	GpVar addr = c.newGpVar(kVarTypeInt32);
1982 1979
 
1983 1980
 	c.mov(Rd, reg_pos_ptr(16));
1984 1981
 	c.mov(addr, reg_pos_ptr(16));
... ...
@@ -1994,10 +1991,10 @@ static int OP_LDRD_STRD_OFFSET_PRE_INDEX(uint32_t i)
1994 1991
 
1995 1992
 	if (BIT5(i)) // Store
1996 1993
 	{
1997
-		X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(op_strd_tab[PROCNUM][Rd_num]));
1998
-		ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder1<uint32_t, uint32_t>());
1999
-		ctx->setArgument(0, addr);
2000
-		ctx->setReturn(bb_cycles);
1994
+		auto ctx = c.addCall(imm_ptr(op_strd_tab[PROCNUM][Rd_num]), ASMJIT_CALL_CONV,
1995
+			FuncBuilder1<uint32_t, uint32_t>());
1996
+		ctx->setArg(0, addr);
1997
+		ctx->setRet(0, bb_cycles);
2001 1998
 		if (BIT21(i)) // W bit - writeback
2002 1999
 			c.mov(reg_pos_ptr(16), addr);
2003 2000
 		emit_MMU_aluMemCycles(3, bb_cycles, 0);
... ...
@@ -2006,10 +2003,10 @@ static int OP_LDRD_STRD_OFFSET_PRE_INDEX(uint32_t i)
2006 2003
 	{
2007 2004
 		if (BIT21(i)) // W bit - writeback
2008 2005
 			c.mov(reg_pos_ptr(16), addr);
2009
-		X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(op_ldrd_tab[PROCNUM][Rd_num]));
2010
-		ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder1<uint32_t, uint32_t>());
2011
-		ctx->setArgument(0, addr);
2012
-		ctx->setReturn(bb_cycles);
2006
+		auto ctx = c.addCall(imm_ptr(op_ldrd_tab[PROCNUM][Rd_num]), ASMJIT_CALL_CONV,
2007
+			FuncBuilder1<uint32_t, uint32_t>());
2008
+		ctx->setArg(0, addr);
2009
+		ctx->setRet(0, bb_cycles);
2013 2010
 		emit_MMU_aluMemCycles(3, bb_cycles, 0);
2014 2011
 	}
2015 2012
 	return 1;
... ...
@@ -2039,21 +2036,21 @@ static const OP_SWP_SWPB op_swp_tab[2][2] = { { op_swp<0>, op_swp<1> }, { op_swp
2039 2036
 
2040 2037
 static int op_swp_(uint32_t i, int b)
2041 2038
 {
2042
-	GpVar addr = c.newGpVar(kX86VarTypeGpd);
2043
-	GpVar Rd = c.newGpVar(kX86VarTypeGpz);
2044
-	GpVar Rs = c.newGpVar(kX86VarTypeGpd);
2039
+	GpVar addr = c.newGpVar(kVarTypeInt32);
2040
+	GpVar Rd = c.newGpVar(kVarTypeIntPtr);
2041
+	GpVar Rs = c.newGpVar(kVarTypeInt32);
2045 2042
 	c.mov(addr, reg_pos_ptr(16));
2046 2043
 	c.lea(Rd, reg_pos_ptr(12));
2047 2044
 	if (b)
2048 2045
 		c.movzx(Rs, reg_pos_ptrB(0));
2049 2046
 	else
2050 2047
 		c.mov(Rs, reg_pos_ptr(0));
2051
-	X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(op_swp_tab[b][PROCNUM]));
2052
-	ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder3<uint32_t, uint32_t, uint32_t *, uint32_t>());
2053
-	ctx->setArgument(0, addr);
2054
-	ctx->setArgument(1, Rd);
2055
-	ctx->setArgument(2, Rs);
2056
-	ctx->setReturn(bb_cycles);
2048
+	auto ctx = c.addCall(imm_ptr(op_swp_tab[b][PROCNUM]), ASMJIT_CALL_CONV,
2049
+		FuncBuilder3<uint32_t, uint32_t, uint32_t *, uint32_t>());
2050
+	ctx->setArg(0, addr);
2051
+	ctx->setArg(1, Rd);
2052
+	ctx->setArg(2, Rs);
2053
+	ctx->setRet(0, bb_cycles);
2057 2054
 	emit_MMU_aluMemCycles(4, bb_cycles, 0);
2058 2055
 	return 1;
2059 2056
 }
... ...
@@ -2247,30 +2244,30 @@ static void call_ldm_stm(GpVar adr, uint32_t bitmask, bool store, int dir)
2247 2244
 {
2248 2245
 	if (bitmask)
2249 2246
 	{
2250
-		GpVar n = c.newGpVar(kX86VarTypeGpd);
2247
+		GpVar n = c.newGpVar(kVarTypeInt32);
2251 2248
 		c.mov(n, popcount(bitmask));
2252 2249
 #ifdef ASMJIT_X64
2253
-		GpVar regs = c.newGpVar(kX86VarTypeGpz);
2250
+		GpVar regs = c.newGpVar(kVarTypeIntPtr);
2254 2251
 		c.mov(regs, get_reg_list(bitmask, dir));
2255
-		X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(op_ldm_stm_tab[PROCNUM][store][dir > 0]));
2256
-		ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder3<uint32_t, uint32_t, uint64_t, int>());
2257
-		ctx->setArgument(0, adr);
2258
-		ctx->setArgument(1, regs);
2259
-		ctx->setArgument(2, n);
2252
+		auto ctx = c.addCall(imm_ptr(op_ldm_stm_tab[PROCNUM][store][dir > 0]), ASMJIT_CALL_CONV,
2253
+			FuncBuilder3<uint32_t, uint32_t, uint64_t, int>());
2254
+		ctx->setArg(0, adr);
2255
+		ctx->setArg(1, regs);
2256
+		ctx->setArg(2, n);
2260 2257
 #else
2261 2258
 		// same prototype, but we have to handle splitting of a u64 arg manually
2262
-		GpVar regs_lo = c.newGpVar(kX86VarTypeGpd);
2263
-		GpVar regs_hi = c.newGpVar(kX86VarTypeGpd);
2259
+		GpVar regs_lo = c.newGpVar(kVarTypeInt32);
2260
+		GpVar regs_hi = c.newGpVar(kVarTypeInt32);
2264 2261
 		c.mov(regs_lo, get_reg_list(bitmask, dir) & 0xFFFFFFFF);
2265 2262
 		c.mov(regs_hi, get_reg_list(bitmask, dir) >> 32);
2266
-		X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(op_ldm_stm_tab[PROCNUM][store][dir > 0]));
2267
-		ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder4<uint32_t, uint32_t, uint32_t, uint32_t, int>());
2268
-		ctx->setArgument(0, adr);
2269
-		ctx->setArgument(1, regs_lo);
2270
-		ctx->setArgument(2, regs_hi);
2271
-		ctx->setArgument(3, n);
2263
+		auto ctx = c.addCall(imm_ptr(op_ldm_stm_tab[PROCNUM][store][dir > 0]), ASMJIT_CALL_CONV,
2264
+			FuncBuilder4<uint32_t, uint32_t, uint32_t, uint32_t, int>());
2265
+		ctx->setArg(0, adr);
2266
+		ctx->setArg(1, regs_lo);
2267
+		ctx->setArg(2, regs_hi);
2268
+		ctx->setArg(3, n);
2272 2269
 #endif
2273
-		ctx->setReturn(bb_cycles);
2270
+		ctx->setRet(0, bb_cycles);
2274 2271
 	}
2275 2272
 	else
2276 2273
 		++bb_constant_cycles;
... ...
@@ -2284,7 +2281,7 @@ static int op_ldm_stm(uint32_t i, bool store, int dir, bool before, bool writeba
2284 2281
 	uint32_t bitmask = i & 0xFFFF;
2285 2282
 	uint32_t pop = popcount(bitmask);
2286 2283
 
2287
-	GpVar adr = c.newGpVar(kX86VarTypeGpd);
2284
+	GpVar adr = c.newGpVar(kVarTypeInt32);
2288 2285
 	c.mov(adr, reg_pos_ptr(16));
2289 2286
 	if (before)
2290 2287
 		c.add(adr, 4*dir);
... ...
@@ -2296,7 +2293,7 @@ static int op_ldm_stm(uint32_t i, bool store, int dir, bool before, bool writeba
2296 2293
 
2297 2294
 	if (writeback)
2298 2295
 	{
2299
-		
2296
+
2300 2297
 		if (store || !(i & (1 << REG_POS(i, 16))))
2301 2298
 		{
2302 2299
 			JIT_COMMENT("--- writeback");
... ...
@@ -2345,8 +2342,8 @@ static int op_ldm_stm2(uint32_t i, bool store, int dir, bool before, bool writeb
2345 2342
 	//printf("ARM%c: %s R%d:%08X, bitmask %02X\n", PROCNUM?'7':'9', (store?"STM":"LDM"), REG_POS(i, 16), cpu->R[REG_POS(i, 16)], bitmask);
2346 2343
 	uint32_t adr_first = cpu->R[REG_POS(i, 16)];
2347 2344
 
2348
-	GpVar adr = c.newGpVar(kX86VarTypeGpd);
2349
-	GpVar oldmode = c.newGpVar(kX86VarTypeGpd);
2345
+	GpVar adr = c.newGpVar(kVarTypeInt32);
2346
+	GpVar oldmode = c.newGpVar(kVarTypeInt32);
2350 2347
 
2351 2348
 	c.mov(adr, reg_pos_ptr(16));
2352 2349
 	if (before)
... ...
@@ -2357,11 +2354,11 @@ static int op_ldm_stm2(uint32_t i, bool store, int dir, bool before, bool writeb
2357 2354
 		//if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; }
2358 2355
 		//oldmode = armcpu_switchMode(cpu, SYS);
2359 2356
 		c.mov(oldmode, SYS);
2360
-		X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(armcpu_switchMode));
2361
-		ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<uint32_t, uint8_t *, uint8_t>());
2362
-		ctx->setArgument(0, bb_cpu);
2363
-		ctx->setArgument(1, oldmode);
2364
-		ctx->setReturn(oldmode);
2357
+		auto ctx = c.addCall(imm_ptr(armcpu_switchMode), ASMJIT_CALL_CONV,
2358
+			FuncBuilder2<uint32_t, uint8_t *, uint8_t>());
2359
+		ctx->setArg(0, bb_cpu);
2360
+		ctx->setArg(1, oldmode);
2361
+		ctx->setRet(0, oldmode);
2365 2362
 	}
2366 2363
 
2367 2364
 	call_ldm_stm(adr, bitmask, store, dir);
... ...
@@ -2369,10 +2366,10 @@ static int op_ldm_stm2(uint32_t i, bool store, int dir, bool before, bool writeb
2369 2366
 	if (!bit15 || store)
2370 2367
 	{
2371 2368
 		//armcpu_switchMode(cpu, oldmode);
2372
-		X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(armcpu_switchMode));
2373
-		ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<void, uint8_t *, uint8_t>());
2374
-		ctx->setArgument(0, bb_cpu);
2375
-		ctx->setArgument(1, oldmode);
2369
+		auto ctx = c.addCall(imm_ptr(armcpu_switchMode), ASMJIT_CALL_CONV,
2370
+			FuncBuilder2<void, uint8_t *, uint8_t>());
2371
+		ctx->setArg(0, bb_cpu);
2372
+		ctx->setArg(1, oldmode);
2376 2373
 	}
2377 2374
 	else
2378 2375
 		S_DST_R15;
... ...
@@ -2443,17 +2440,17 @@ static int OP_BL(uint32_t i) { return op_b(i, 1); }
2443 2440
 
2444 2441
 static int op_bx(Mem srcreg, bool blx, bool test_thumb)
2445 2442
 {
2446
-	GpVar dst = c.newGpVar(kX86VarTypeGpd);
2443
+	GpVar dst = c.newGpVar(kVarTypeInt32);
2447 2444
 	c.mov(dst, srcreg);
2448 2445
 
2449 2446
 	if (test_thumb)
2450 2447
 	{
2451
-		GpVar mask = c.newGpVar(kX86VarTypeGpd);
2448
+		GpVar mask = c.newGpVar(kVarTypeInt32);
2452 2449
 		GpVar thumb = dst;
2453
-		dst = c.newGpVar(kX86VarTypeGpd);
2450
+		dst = c.newGpVar(kVarTypeInt32);
2454 2451
 		c.mov(dst, thumb);
2455 2452
 		c.and_(thumb, 1);
2456
-		c.lea(mask, ptr_abs(reinterpret_cast<void *>(0xFFFFFFFC), thumb.r64(), kScale2Times));
2453
+		c.lea(mask, x86::ptr_abs(0xFFFFFFFC, thumb.r64(), 1));
2457 2454
 		c.shl(thumb, 5);
2458 2455
 		c.or_(cpu_ptr_byte(CPSR, 0), thumb.r8Lo());
2459 2456
 		c.and_(dst, mask);
... ...
@@ -2476,12 +2473,12 @@ static int OP_BLX_REG(uint32_t i) { return op_bx(reg_pos_ptr(0), 1, 1); }
2476 2473
 // -----------------------------------------------------------------------------
2477 2474
 static int OP_CLZ(uint32_t i)
2478 2475
 {
2479
-	GpVar res = c.newGpVar(kX86VarTypeGpd);
2476
+	GpVar res = c.newGpVar(kVarTypeInt32);
2480 2477
 	c.mov(res, 0x3F);
2481 2478
 	c.bsr(res, reg_pos_ptr(0));
2482 2479
 	c.xor_(res, 0x1F);
2483 2480
 	c.mov(reg_pos_ptr(12), res);
2484
-	
2481
+
2485 2482
 	return 1;
2486 2483
 }
2487 2484
 
... ...
@@ -2490,8 +2487,7 @@ static int OP_CLZ(uint32_t i)
2490 2487
 // -----------------------------------------------------------------------------
2491 2488
 #define maskPrecalc \
2492 2489
 { \
2493
-	X86CompilerFuncCall *ctxM = c.call(reinterpret_cast<void *>(maskPrecalc)); \
2494
-	ctxM->setPrototype(ASMJIT_CALL_CONV, FuncBuilder0<void>()); \
2490
+	auto ctxM = c.addCall(imm_ptr(maskPrecalc), ASMJIT_CALL_CONV, FuncBuilder0<void>()); \
2495 2491
 }
2496 2492
 static int OP_MCR(uint32_t i)
2497 2493
 {
... ...
@@ -2516,8 +2512,8 @@ static int OP_MCR(uint32_t i)
2516 2512
 	uint8_t opcode1 = (i >> 21) & 0x7; // opcode1
2517 2513
 	uint8_t opcode2 = (i >> 5) & 0x7; // opcode2
2518 2514
 
2519
-	GpVar bb_cp15 = c.newGpVar(kX86VarTypeGpz);
2520
-	GpVar data = c.newGpVar(kX86VarTypeGpd);
2515
+	GpVar bb_cp15 = c.newGpVar(kVarTypeIntPtr);
2516
+	GpVar data = c.newGpVar(kVarTypeInt32);
2521 2517
 	c.mov(data, reg_pos_ptr(12));
2522 2518
 	c.mov(bb_cp15, reinterpret_cast<uintptr_t>(&cp15));
2523 2519
 
... ...
@@ -2527,17 +2523,17 @@ static int OP_MCR(uint32_t i)
2527 2523
 		case 1:
2528 2524
 			if (!opcode1 && !opcode2 && !CRm)
2529 2525
 			{
2530
-				GpVar tmp = c.newGpVar(kX86VarTypeGpd);
2526
+				GpVar tmp = c.newGpVar(kVarTypeInt32);
2531 2527
 				// On the NDS bit0,2,7,12..19 are R/W, Bit3..6 are always set, all other bits are always zero.
2532 2528
 				//MMU.ARM9_RW_MODE = BIT7(val);
2533
-				GpVar bb_mmu = c.newGpVar(kX86VarTypeGpz);
2529
+				GpVar bb_mmu = c.newGpVar(kVarTypeIntPtr);
2534 2530
 				c.mov(bb_mmu, reinterpret_cast<uintptr_t>(&MMU));
2535 2531
 				Mem rwmode = mmu_ptr_byte(ARM9_RW_MODE);
2536 2532
 				Mem ldtbit = cpu_ptr_byte(LDTBit, 0);
2537 2533
 				c.test(data, 1 << 7);
2538 2534
 				c.setnz(rwmode);
2539 2535
 				//cpu->intVector = 0xFFFF0000 * (BIT13(val));
2540
-				GpVar vec = c.newGpVar(kX86VarTypeGpd);
2536
+				GpVar vec = c.newGpVar(kVarTypeInt32);
2541 2537
 				c.mov(tmp, 0xFFFF0000);
2542 2538
 				c.xor_(vec, vec);
2543 2539
 				c.test(data, 1 << 13);
... ...
@@ -2696,7 +2692,7 @@ static int OP_MCR(uint32_t i)
2696 2692
 							{
2697 2693
 								//MMU.DTCMRegion = DTCMRegion = val & 0x0FFFF000;
2698 2694
 								c.and_(data, 0x0FFFF000);
2699
-								GpVar bb_mmu = c.newGpVar(kX86VarTypeGpz);
2695
+								GpVar bb_mmu = c.newGpVar(kVarTypeIntPtr);
2700 2696
 								c.mov(bb_mmu, reinterpret_cast<uintptr_t>(&MMU));
2701 2697
 								c.mov(mmu_ptr(DTCMRegion), data);
2702 2698
 								c.mov(cp15_ptr(DTCMRegion), data);
... ...
@@ -2706,7 +2702,7 @@ static int OP_MCR(uint32_t i)
2706 2702
 							{
2707 2703
 								//ITCMRegion = val;
2708 2704
 								//ITCM base is not writeable!
2709
-								GpVar bb_mmu = c.newGpVar(kX86VarTypeGpz);
2705
+								GpVar bb_mmu = c.newGpVar(kVarTypeIntPtr);
2710 2706
 								c.mov(bb_mmu, reinterpret_cast<uintptr_t>(&MMU));
2711 2707
 								c.mov(mmu_ptr(ITCMRegion), 0);
2712 2708
 								c.mov(cp15_ptr(ITCMRegion), data);
... ...
@@ -2751,11 +2747,11 @@ static int OP_MRC(uint32_t i)
2751 2747
 	uint8_t opcode1 = (i >> 21) & 0x7; // opcode1
2752 2748
 	uint8_t opcode2 = (i >> 5) & 0x7; // opcode2
2753 2749
 
2754
-	GpVar bb_cp15 = c.newGpVar(kX86VarTypeGpz);
2755
-	GpVar data = c.newGpVar(kX86VarTypeGpd);
2750
+	GpVar bb_cp15 = c.newGpVar(kVarTypeIntPtr);
2751
+	GpVar data = c.newGpVar(kVarTypeInt32);
2756 2752
 
2757 2753
 	c.mov(bb_cp15, (uintptr_t)&cp15);
2758
-	
2754
+
2759 2755
 	bool bUnknown = false;
2760 2756
 	switch (CRn)
2761 2757
 	{
... ...
@@ -2960,32 +2956,30 @@ uint32_t op_swi(uint8_t swinum)
2960 2956
 		// TODO:
2961 2957
 		return 0;
2962 2958
 #else
2963
-		X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(ARM_swi_tab[PROCNUM][swinum]));
2964
-		ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder0<uint32_t>());
2965
-		ctx->setReturn(bb_cycles);
2959
+		auto ctx = c.addCall(imm_ptr(ARM_swi_tab[PROCNUM][swinum]), ASMJIT_CALL_CONV, FuncBuilder0<uint32_t>());
2960
+		ctx->setRet(0, bb_cycles);
2966 2961
 		c.add(bb_cycles, 3);
2967 2962
 		return 1;
2968 2963
 #endif
2969 2964
 	}
2970 2965
 
2971
-	GpVar oldCPSR = c.newGpVar(kX86VarTypeGpd);
2972
-	GpVar mode = c.newGpVar(kX86VarTypeGpd);
2966
+	GpVar oldCPSR = c.newGpVar(kVarTypeInt32);
2967
+	GpVar mode = c.newGpVar(kVarTypeInt32);
2973 2968
 	Mem CPSR = cpu_ptr(CPSR.val);
2974 2969
 	JIT_COMMENT("store CPSR to x86 stack");
2975 2970
 	c.mov(oldCPSR, CPSR);
2976 2971
 	JIT_COMMENT("enter SVC mode");
2977 2972
 	c.mov(mode, imm(SVC));
2978
-	X86CompilerFuncCall* ctx = c.call(reinterpret_cast<void *>(armcpu_switchMode));
2979
-	ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<void, void *, uint8_t>());
2980
-	ctx->setArgument(0, bb_cpu);
2981
-	ctx->setArgument(1, mode);
2973
+	auto ctx = c.addCall(imm_ptr(armcpu_switchMode), ASMJIT_CALL_CONV, FuncBuilder2<void, void *, uint8_t>());
2974
+	ctx->setArg(0, bb_cpu);
2975
+	ctx->setArg(1, mode);
2982 2976
 	c.unuse(mode);
2983 2977
 	JIT_COMMENT("store next instruction address to R14");
2984 2978
 	c.mov(reg_ptr(14), bb_next_instruction);
2985 2979
 	JIT_COMMENT("save old CPSR as new SPSR");
2986 2980
 	c.mov(cpu_ptr(SPSR.val), oldCPSR);
2987 2981
 	JIT_COMMENT("CPSR: clear T, set I");
2988
-	GpVar _cpsr = c.newGpVar(kX86VarTypeGpd);
2982
+	GpVar _cpsr = c.newGpVar(kVarTypeInt32);
2989 2983
 	c.mov(_cpsr, CPSR);
2990 2984
 	c.and_(_cpsr, ~(1 << 5)); /* clear T */
2991 2985
 	c.or_(_cpsr, 1 << 7); /* set I */
... ...
@@ -2993,7 +2987,7 @@ uint32_t op_swi(uint8_t swinum)
2993 2987
 	c.unuse(_cpsr);
2994 2988
 	JIT_COMMENT("set next instruction");
2995 2989
 	c.mov(cpu_ptr(next_instruction), imm(cpu->intVector + 0x08));
2996
-	
2990
+
2997 2991
 	return 1;
2998 2992
 }
2999 2993
 
... ...
@@ -3008,14 +3002,14 @@ static int OP_BKPT(uint32_t i) { printf("JIT: unimplemented OP_BKPT\n"); return
3008 3002
 //   THUMB
3009 3003
 // -----------------------------------------------------------------------------
3010 3004
 #define OP_SHIFTS_IMM(x86inst) \
3011
-	GpVar rcf = c.newGpVar(kX86VarTypeGpd); \
3005
+	GpVar rcf = c.newGpVar(kVarTypeInt32); \
3012 3006
 	uint8_t cf_change = 1; \
3013 3007
 	uint32_t rhs = (i >> 6) & 0x1F; \
3014 3008
 	if (_REG_NUM(i, 0) == _REG_NUM(i, 3)) \
3015 3009
 		c.x86inst(reg_pos_thumb(0), rhs); \
3016 3010
 	else \
3017 3011
 	{ \
3018
-		GpVar lhs = c.newGpVar(kX86VarTypeGpd); \
3012
+		GpVar lhs = c.newGpVar(kVarTypeInt32); \
3019 3013
 		c.mov(lhs, reg_pos_thumb(3)); \
3020 3014
 		c.x86inst(lhs, rhs); \
3021 3015
 		c.mov(reg_pos_thumb(0), lhs); \
... ...
@@ -3027,8 +3021,8 @@ static int OP_BKPT(uint32_t i) { printf("JIT: unimplemented OP_BKPT\n"); return
3027 3021
 
3028 3022
 #define OP_SHIFTS_REG(x86inst, bit) \
3029 3023
 	uint8_t cf_change = 1; \
3030
-	GpVar imm = c.newGpVar(kX86VarTypeGpz); \
3031
-	GpVar rcf = c.newGpVar(kX86VarTypeGpd); \
3024
+	GpVar imm = c.newGpVar(kVarTypeIntPtr); \
3025
+	GpVar rcf = c.newGpVar(kVarTypeInt32); \
3032 3026
 	Label __eq32 = c.newLabel(); \
3033 3027
 	Label __ls32 = c.newLabel(); \
3034 3028
 	Label __zero = c.newLabel(); \
... ...
@@ -3065,7 +3059,7 @@ static int OP_BKPT(uint32_t i) { printf("JIT: unimplemented OP_BKPT\n"); return
3065 3059
 	return 1;
3066 3060
 
3067 3061
 #define OP_LOGIC(x86inst, _conv) \
3068
-	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
3062
+	GpVar rhs = c.newGpVar(kVarTypeInt32); \
3069 3063
 	c.mov(rhs, reg_pos_thumb(3)); \
3070 3064
 	if (_conv == 1) \
3071 3065
 		c.not_(rhs); \
... ...
@@ -3082,7 +3076,7 @@ static int OP_LSL_0(uint32_t i)
3082 3076
 		c.cmp(reg_pos_thumb(0), 0);
3083 3077
 	else
3084 3078
 	{
3085
-		GpVar rhs = c.newGpVar(kX86VarTypeGpd);
3079
+		GpVar rhs = c.newGpVar(kVarTypeInt32);
3086 3080
 		c.mov(rhs, reg_pos_thumb(3));
3087 3081
 		c.mov(reg_pos_thumb(0), rhs);
3088 3082
 		c.cmp(rhs, 0);
... ...
@@ -3094,7 +3088,7 @@ static int OP_LSL(uint32_t i) { OP_SHIFTS_IMM(shl); }
3094 3088
 static int OP_LSL_REG(uint32_t i) { OP_SHIFTS_REG(shl, 0); }
3095 3089
 static int OP_LSR_0(uint32_t i)
3096 3090
 {
3097
-	GpVar rcf = c.newGpVar(kX86VarTypeGpd);
3091
+	GpVar rcf = c.newGpVar(kVarTypeInt32);
3098 3092
 	c.test(reg_pos_thumb(3), 1 << 31);
3099 3093
 	c.setnz(rcf.r8Lo());
3100 3094
 	SET_NZC_SHIFTS_ZERO(1);
... ...
@@ -3106,8 +3100,8 @@ static int OP_LSR_REG(uint32_t i) { OP_SHIFTS_REG(shr, 31); }
3106 3100
 static int OP_ASR_0(uint32_t i)
3107 3101
 {
3108 3102
 	uint8_t cf_change = 1;
3109
-	GpVar rcf = c.newGpVar(kX86VarTypeGpd);
3110
-	GpVar rhs = c.newGpVar(kX86VarTypeGpd);
3103
+	GpVar rcf = c.newGpVar(kVarTypeInt32);
3104
+	GpVar rhs = c.newGpVar(kVarTypeInt32);
3111 3105
 	if (_REG_NUM(i, 0) == _REG_NUM(i, 3))
3112 3106
 		c.sar(reg_pos_thumb(0), 31);
3113 3107
 	else
... ...
@@ -3121,15 +3115,15 @@ static int OP_ASR_0(uint32_t i)
3121 3115
 	return 1;
3122 3116
 }
3123 3117
 static int OP_ASR(uint32_t i) { OP_SHIFTS_IMM(sar); }
3124
-static int OP_ASR_REG(uint32_t i) 
3118
+static int OP_ASR_REG(uint32_t i)
3125 3119
 {
3126 3120
 	uint8_t cf_change = 1;
3127 3121
 	Label __gr0 = c.newLabel();
3128 3122
 	Label __lt32 = c.newLabel();
3129 3123
 	Label __done = c.newLabel();
3130 3124
 	Label __setFlags = c.newLabel();
3131
-	GpVar imm = c.newGpVar(kX86VarTypeGpz);
3132
-	GpVar rcf = c.newGpVar(kX86VarTypeGpd);
3125
+	GpVar imm = c.newGpVar(kVarTypeIntPtr);
3126
+	GpVar rcf = c.newGpVar(kVarTypeInt32);
3133 3127
 	c.mov(imm, reg_pos_thumb(3));
3134 3128
 	c.and_(imm, 0xFF);
3135 3129
 	c.jnz(__gr0);
... ...
@@ -3161,8 +3155,8 @@ static int OP_ASR_REG(uint32_t i)
3161 3155
 static int OP_ROR_REG(uint32_t i)
3162 3156
 {
3163 3157
 	uint8_t cf_change = 1;
3164
-	GpVar imm = c.newGpVar(kX86VarTypeGpz);
3165
-	GpVar rcf = c.newGpVar(kX86VarTypeGpd);
3158
+	GpVar imm = c.newGpVar(kVarTypeIntPtr);
3159
+	GpVar rcf = c.newGpVar(kVarTypeInt32);
3166 3160
 	Label __zero = c.newLabel();
3167 3161
 	Label __zero_1F = c.newLabel();
3168 3162
 	Label __done = c.newLabel();
... ...
@@ -3208,7 +3202,7 @@ static int OP_NEG(uint32_t i)
3208 3202
 		c.neg(reg_pos_thumb(0));
3209 3203
 	else
3210 3204
 	{
3211
-		GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3205
+		GpVar tmp = c.newGpVar(kVarTypeInt32);
3212 3206
 		c.mov(tmp, reg_pos_thumb(3));
3213 3207
 		c.neg(tmp);
3214 3208
 		c.mov(reg_pos_thumb(0), tmp);
... ...
@@ -3220,13 +3214,13 @@ static int OP_NEG(uint32_t i)
3220 3214
 //-----------------------------------------------------------------------------
3221 3215
 //   ADD
3222 3216
 //-----------------------------------------------------------------------------
3223
-static int OP_ADD_IMM3(uint32_t i) 
3217
+static int OP_ADD_IMM3(uint32_t i)
3224 3218
 {
3225 3219
 	uint32_t imm3 = (i >> 6) & 0x07;
3226 3220
 
3227 3221
 	if (!imm3) // mov 2
3228 3222
 	{
3229
-		GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3223
+		GpVar tmp = c.newGpVar(kVarTypeInt32);
3230 3224
 		c.mov(tmp, reg_pos_thumb(3));
3231 3225
 		c.mov(reg_pos_thumb(0), tmp);
3232 3226
 		c.cmp(tmp, 0);
... ...
@@ -3237,7 +3231,7 @@ static int OP_ADD_IMM3(uint32_t i)
3237 3231
 		c.add(reg_pos_thumb(0), imm3);
3238 3232
 	else
3239 3233
 	{
3240
-		GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3234
+		GpVar tmp = c.newGpVar(kVarTypeInt32);
3241 3235
 		c.mov(tmp, reg_pos_thumb(3));
3242 3236
 		c.add(tmp, imm3);
3243 3237
 		c.mov(reg_pos_thumb(0), tmp);
... ...
@@ -3250,14 +3244,14 @@ static int OP_ADD_IMM8(uint32_t i)
3250 3244
 	c.add(reg_pos_thumb(8), (i & 0xFF));
3251 3245
 	SET_NZCV(0);
3252 3246
 
3253
-	return 1; 
3247
+	return 1;
3254 3248
 }
3255
-static int OP_ADD_REG(uint32_t i) 
3249
+static int OP_ADD_REG(uint32_t i)
3256 3250
 {
3257 3251
 	//cpu->R[REG_NUM(i, 0)] = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
3258 3252
 	if (_REG_NUM(i, 0) == _REG_NUM(i, 3))
3259 3253
 	{
3260
-		GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3254
+		GpVar tmp = c.newGpVar(kVarTypeInt32);
3261 3255
 		c.mov(tmp, reg_pos_thumb(6));
3262 3256
 		c.add(reg_pos_thumb(0), tmp);
3263 3257
 	}
... ...
@@ -3265,26 +3259,26 @@ static int OP_ADD_REG(uint32_t i)
3265 3259
 	{
3266 3260
 		if (_REG_NUM(i, 0) == _REG_NUM(i, 6))
3267 3261
 		{
3268
-			GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3262
+			GpVar tmp = c.newGpVar(kVarTypeInt32);
3269 3263
 			c.mov(tmp, reg_pos_thumb(3));
3270 3264
 			c.add(reg_pos_thumb(0), tmp);
3271 3265
 		}
3272 3266
 		else
3273 3267
 		{
3274
-			GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3268
+			GpVar tmp = c.newGpVar(kVarTypeInt32);
3275 3269
 			c.mov(tmp, reg_pos_thumb(3));
3276 3270
 			c.add(tmp, reg_pos_thumb(6));
3277 3271
 			c.mov(reg_pos_thumb(0), tmp);
3278 3272
 		}
3279 3273
 	}
3280 3274
 	SET_NZCV(0);
3281
-	return 1; 
3275
+	return 1;
3282 3276
 }
3283 3277
 static int OP_ADD_SPE(uint32_t i)
3284 3278
 {
3285 3279
 	uint32_t Rd = _REG_NUM(i, 0) | ((i >> 4) & 8);
3286 3280
 	//cpu->R[Rd] += cpu->R[REG_POS(i, 3)];
3287
-	GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3281
+	GpVar tmp = c.newGpVar(kVarTypeInt32);
3288 3282
 	c.mov(tmp, reg_ptr(Rd));
3289 3283
 	c.add(tmp, reg_pos_ptr(3));
3290 3284
 	c.mov(reg_ptr(Rd), tmp);
... ...
@@ -3306,7 +3300,7 @@ static int OP_ADD_2SP(uint32_t i)
3306 3300
 {
3307 3301
 	uint32_t imm = (i & 0xFF) << 2;
3308 3302
 	//cpu->R[REG_NUM(i, 8)] = cpu->R[13] + ((i&0xFF)<<2);
3309
-	GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3303
+	GpVar tmp = c.newGpVar(kVarTypeInt32);
3310 3304
 	c.mov(tmp, reg_ptr(13));
3311 3305
 	if (imm)
3312 3306
 		c.add(tmp, imm);
... ...
@@ -3327,7 +3321,7 @@ static int OP_SUB_IMM3(uint32_t i)
3327 3321
 		c.sub(reg_pos_thumb(0), imm3);
3328 3322
 	else
3329 3323
 	{
3330
-		GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3324
+		GpVar tmp = c.newGpVar(kVarTypeInt32);
3331 3325
 		c.mov(tmp, reg_pos_thumb(3));
3332 3326
 		c.sub(tmp, imm3);
3333 3327
 		c.mov(reg_pos_thumb(0), tmp);
... ...
@@ -3340,26 +3334,26 @@ static int OP_SUB_IMM8(uint32_t i)
3340 3334
 	//cpu->R[REG_NUM(i, 8)] -= imm8;
3341 3335
 	c.sub(reg_pos_thumb(8), i & 0xFF);
3342 3336
 	SET_NZCV(1);
3343
-	return 1; 
3337
+	return 1;
3344 3338
 }
3345 3339
 static int OP_SUB_REG(uint32_t i)
3346 3340
 {
3347
-	// cpu->R[REG_NUM(i, 0)] = cpu->R[REG_NUM(i, 3)] - cpu->R[REG_NUM(i, 6)];
3341
+	//cpu->R[REG_NUM(i, 0)] = cpu->R[REG_NUM(i, 3)] - cpu->R[REG_NUM(i, 6)];
3348 3342
 	if (_REG_NUM(i, 0) == _REG_NUM(i, 3))
3349 3343
 	{
3350
-		GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3344
+		GpVar tmp = c.newGpVar(kVarTypeInt32);
3351 3345
 		c.mov(tmp, reg_pos_thumb(6));
3352 3346
 		c.sub(reg_pos_thumb(0), tmp);
3353 3347
 	}
3354 3348
 	else
3355 3349
 	{
3356
-		GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3350
+		GpVar tmp = c.newGpVar(kVarTypeInt32);
3357 3351
 		c.mov(tmp, reg_pos_thumb(3));
3358 3352
 		c.sub(tmp, reg_pos_thumb(6));
3359 3353
 		c.mov(reg_pos_thumb(0), tmp);
3360 3354
 	}
3361 3355
 	SET_NZCV(1);
3362
-	return 1; 
3356
+	return 1;
3363 3357
 }
3364 3358
 
3365 3359
 // -----------------------------------------------------------------------------
... ...
@@ -3367,7 +3361,7 @@ static int OP_SUB_REG(uint32_t i)
3367 3361
 // -----------------------------------------------------------------------------
3368 3362
 static int OP_ADC_REG(uint32_t i)
3369 3363
 {
3370
-	GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3364
+	GpVar tmp = c.newGpVar(kVarTypeInt32);
3371 3365
 	c.mov(tmp, reg_pos_thumb(3));
3372 3366
 	GET_CARRY(0);
3373 3367
 	c.adc(reg_pos_thumb(0), tmp);
... ...
@@ -3380,7 +3374,7 @@ static int OP_ADC_REG(uint32_t i)
3380 3374
 // -----------------------------------------------------------------------------
3381 3375
 static int OP_SBC_REG(uint32_t i)
3382 3376
 {
3383
-	GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3377
+	GpVar tmp = c.newGpVar(kVarTypeInt32);
3384 3378
 	c.mov(tmp, reg_pos_thumb(3));
3385 3379
 	GET_CARRY(1);
3386 3380
 	c.sbb(reg_pos_thumb(0), tmp);
... ...
@@ -3403,7 +3397,7 @@ static int OP_MOV_SPE(uint32_t i)
3403 3397
 {
3404 3398
 	uint32_t Rd = _REG_NUM(i, 0) | ((i >> 4) & 8);
3405 3399
 	//cpu->R[Rd] = cpu->R[REG_POS(i, 3)];
3406
-	GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3400
+	GpVar tmp = c.newGpVar(kVarTypeInt32);
3407 3401
 	c.mov(tmp, reg_pos_ptr(3));
3408 3402
 	c.mov(reg_ptr(Rd), tmp);
3409 3403
 	if (Rd == 15)
... ...
@@ -3411,13 +3405,13 @@ static int OP_MOV_SPE(uint32_t i)
3411 3405
 		c.mov(cpu_ptr(next_instruction), tmp);
3412 3406
 		bb_constant_cycles += 2;
3413 3407
 	}
3414
-	
3408
+
3415 3409
 	return 1;
3416 3410
 }
3417 3411
 
3418 3412
 static int OP_MVN(uint32_t i)
3419 3413
 {
3420
-	GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3414
+	GpVar tmp = c.newGpVar(kVarTypeInt32);
3421 3415
 	c.mov(tmp, reg_pos_thumb(3));
3422 3416
 	c.not_(tmp);
3423 3417
 	c.cmp(tmp, 0);
... ...
@@ -3431,7 +3425,7 @@ static int OP_MVN(uint32_t i)
3431 3425
 // -----------------------------------------------------------------------------
3432 3426
 static int OP_MUL_REG(uint32_t i)
3433 3427
 {
3434
-	GpVar lhs = c.newGpVar(kX86VarTypeGpd);
3428
+	GpVar lhs = c.newGpVar(kVarTypeInt32);
3435 3429
 	c.mov(lhs, reg_pos_thumb(0));
3436 3430
 	c.imul(lhs, reg_pos_thumb(3));
3437 3431
 	c.cmp(lhs, 0);
... ...
@@ -3456,7 +3450,7 @@ static int OP_CMP_IMM8(uint32_t i)
3456 3450
 
3457 3451
 static int OP_CMP(uint32_t i)
3458 3452
 {
3459
-	GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3453
+	GpVar tmp = c.newGpVar(kVarTypeInt32);
3460 3454
 	c.mov(tmp, reg_pos_thumb(3));
3461 3455
 	c.cmp(reg_pos_thumb(0), tmp);
3462 3456
 	SET_NZCV(1);
... ...
@@ -3466,7 +3460,7 @@ static int OP_CMP(uint32_t i)
3466 3460
 static int OP_CMP_SPE(uint32_t i)
3467 3461
 {
3468 3462
 	uint32_t Rn = (i & 7) | ((i >> 4) & 8);
3469
-	GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3463
+	GpVar tmp = c.newGpVar(kVarTypeInt32);
3470 3464
 	c.mov(tmp, reg_pos_ptr(3));
3471 3465
 	c.cmp(reg_ptr(Rn), tmp);
3472 3466
 	SET_NZCV(1);
... ...
@@ -3475,7 +3469,7 @@ static int OP_CMP_SPE(uint32_t i)
3475 3469
 
3476 3470
 static int OP_CMN(uint32_t i)
3477 3471
 {
3478
-	GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3472
+	GpVar tmp = c.newGpVar(kVarTypeInt32);
3479 3473
 	c.mov(tmp, reg_pos_thumb(0));
3480 3474
 	c.add(tmp, reg_pos_thumb(3));
3481 3475
 	SET_NZCV(0);
... ...
@@ -3487,7 +3481,7 @@ static int OP_CMN(uint32_t i)
3487 3481
 // -----------------------------------------------------------------------------
3488 3482
 static int OP_TST(uint32_t i)
3489 3483
 {
3490
-	GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3484
+	GpVar tmp = c.newGpVar(kVarTypeInt32);
3491 3485
 	c.mov(tmp, reg_pos_thumb(3));
3492 3486
 	c.test(reg_pos_thumb(0), tmp);
3493 3487
 	SET_NZ(0);
... ...
@@ -3498,8 +3492,8 @@ static int OP_TST(uint32_t i)
3498 3492
 //   STR / LDR / STRB / LDRB
3499 3493
 // -----------------------------------------------------------------------------
3500 3494
 #define STR_THUMB(mem_op, offset) \
3501
-	GpVar addr = c.newGpVar(kX86VarTypeGpd); \
3502
-	GpVar data = c.newGpVar(kX86VarTypeGpd); \
3495
+	GpVar addr = c.newGpVar(kVarTypeInt32); \
3496
+	GpVar data = c.newGpVar(kVarTypeInt32); \
3503 3497
 	uint32_t adr_first = cpu->R[_REG_NUM(i, 3)]; \
3504 3498
 \
3505 3499
 	c.mov(addr, reg_pos_thumb(3)); \
... ...
@@ -3517,16 +3511,16 @@ static int OP_TST(uint32_t i)
3517 3511
 		adr_first += cpu->R[_REG_NUM(i, 6)]; \
3518 3512
 	} \
3519 3513
 	c.mov(data, reg_pos_thumb(0)); \
3520
-	X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(mem_op##_tab[PROCNUM][classify_adr(adr_first, 1)])); \
3521
-	ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<void, uint32_t, uint32_t>()); \
3522
-	ctx->setArgument(0, addr); \
3523
-	ctx->setArgument(1, data); \
3524
-	ctx->setReturn(bb_cycles); \
3514
+	auto ctx = c.addCall(imm_ptr(mem_op##_tab[PROCNUM][classify_adr(adr_first, 1)]), ASMJIT_CALL_CONV, \
3515
+		FuncBuilder2<void, uint32_t, uint32_t>()); \
3516
+	ctx->setArg(0, addr); \
3517
+	ctx->setArg(1, data); \
3518
+	ctx->setRet(0, bb_cycles); \
3525 3519
 	return 1;
3526 3520
 
3527 3521
 #define LDR_THUMB(mem_op, offset) \
3528
-	GpVar addr = c.newGpVar(kX86VarTypeGpd); \
3529
-	GpVar data = c.newGpVar(kX86VarTypeGpz); \
3522
+	GpVar addr = c.newGpVar(kVarTypeInt32); \
3523
+	GpVar data = c.newGpVar(kVarTypeIntPtr); \
3530 3524
 	uint32_t adr_first = cpu->R[_REG_NUM(i, 3)]; \
3531 3525
 \
3532 3526
 	c.mov(addr, reg_pos_thumb(3)); \
... ...
@@ -3544,16 +3538,16 @@ static int OP_TST(uint32_t i)
3544 3538
 		adr_first += cpu->R[_REG_NUM(i, 6)]; \
3545 3539
 	} \
3546 3540
 	c.lea(data, reg_pos_thumb(0)); \
3547
-	X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(mem_op##_tab[PROCNUM][classify_adr(adr_first, 0)])); \
3548
-	ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<void, uint32_t, uint32_t *>()); \
3549
-	ctx->setArgument(0, addr); \
3550
-	ctx->setArgument(1, data); \
3551
-	ctx->setReturn(bb_cycles); \
3541
+	auto ctx = c.addCall(imm_ptr(mem_op##_tab[PROCNUM][classify_adr(adr_first, 0)]), ASMJIT_CALL_CONV, \
3542
+		FuncBuilder2<void, uint32_t, uint32_t *>()); \
3543
+	ctx->setArg(0, addr); \
3544
+	ctx->setArg(1, data); \
3545
+	ctx->setRet(0, bb_cycles); \
3552 3546
 	return 1;
3553 3547
 
3554 3548
 static int OP_STRB_IMM_OFF(uint32_t i) { STR_THUMB(STRB, (i >> 6) & 0x1F); }
3555 3549
 static int OP_LDRB_IMM_OFF(uint32_t i) { LDR_THUMB(LDRB, (i >> 6) & 0x1F); }
3556
-static int OP_STRB_REG_OFF(uint32_t i) { STR_THUMB(STRB, -1); } 
3550
+static int OP_STRB_REG_OFF(uint32_t i) { STR_THUMB(STRB, -1); }
3557 3551
 static int OP_LDRB_REG_OFF(uint32_t i) { LDR_THUMB(LDRB, -1); }
3558 3552
 static int OP_LDRSB_REG_OFF(uint32_t i) { LDR_THUMB(LDRSB, -1); }
3559 3553
 
... ...
@@ -3573,17 +3567,17 @@ static int OP_STR_SPREL(uint32_t i)
3573 3567
 	uint32_t imm = (i & 0xFF) << 2;
3574 3568
 	uint32_t adr_first = cpu->R[13] + imm;
3575 3569
 
3576
-	GpVar addr = c.newGpVar(kX86VarTypeGpd);
3570
+	GpVar addr = c.newGpVar(kVarTypeInt32);
3577 3571
 	c.mov(addr, reg_ptr(13));
3578 3572
 	if (imm)
3579 3573
 		c.add(addr, imm);
3580
-	GpVar data = c.newGpVar(kX86VarTypeGpd);
3574
+	GpVar data = c.newGpVar(kVarTypeInt32);
3581 3575
 	c.mov(data, reg_pos_thumb(8));
3582
-	X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(STR_tab[PROCNUM][classify_adr(adr_first, 1)]));
3583
-	ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<void, uint32_t, uint32_t>());
3584
-	ctx->setArgument(0, addr);
3585
-	ctx->setArgument(1, data);
3586
-	ctx->setReturn(bb_cycles);
3576
+	auto ctx = c.addCall(imm_ptr(STR_tab[PROCNUM][classify_adr(adr_first, 1)]), ASMJIT_CALL_CONV,
3577
+		FuncBuilder2<void, uint32_t, uint32_t>());
3578
+	ctx->setArg(0, addr);
3579
+	ctx->setArg(1, data);
3580
+	ctx->setRet(0, bb_cycles);
3587 3581
 	return 1;
3588 3582
 }
3589 3583
 
... ...
@@ -3591,18 +3585,18 @@ static int OP_LDR_SPREL(uint32_t i)
3591 3585
 {
3592 3586
 	uint32_t imm = (i & 0xFF) << 2;
3593 3587
 	uint32_t adr_first = cpu->R[13] + imm;
3594
-	
3595
-	GpVar addr = c.newGpVar(kX86VarTypeGpd);
3588
+
3589
+	GpVar addr = c.newGpVar(kVarTypeInt32);
3596 3590
 	c.mov(addr, reg_ptr(13));
3597 3591
 	if (imm)
3598 3592
 		c.add(addr, imm);
3599
-	GpVar data = c.newGpVar(kX86VarTypeGpz);
3593
+	GpVar data = c.newGpVar(kVarTypeIntPtr);
3600 3594
 	c.lea(data, reg_pos_thumb(8));
3601
-	X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(LDR_tab[PROCNUM][classify_adr(adr_first, 0)]));
3602
-	ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<void, uint32_t, uint32_t *>());
3603
-	ctx->setArgument(0, addr);
3604
-	ctx->setArgument(1, data);
3605
-	ctx->setReturn(bb_cycles);
3595
+	auto ctx = c.addCall(imm_ptr(LDR_tab[PROCNUM][classify_adr(adr_first, 0)]), ASMJIT_CALL_CONV,
3596
+		FuncBuilder2<void, uint32_t, uint32_t *>());
3597
+	ctx->setArg(0, addr);
3598
+	ctx->setArg(1, data);
3599
+	ctx->setRet(0, bb_cycles);
3606 3600
 	return 1;
3607 3601
 }
3608 3602
 
... ...
@@ -3610,15 +3604,15 @@ static int OP_LDR_PCREL(uint32_t i)
3610 3604
 {
3611 3605
 	uint32_t imm = (i & 0xFF) << 2;
3612 3606
 	uint32_t adr_first = (bb_r15 & 0xFFFFFFFC) + imm;
3613
-	GpVar addr = c.newGpVar(kX86VarTypeGpd);
3614
-	GpVar data = c.newGpVar(kX86VarTypeGpz);
3607
+	GpVar addr = c.newGpVar(kVarTypeInt32);
3608
+	GpVar data = c.newGpVar(kVarTypeIntPtr);
3615 3609
 	c.mov(addr, adr_first);
3616 3610
 	c.lea(data, reg_pos_thumb(8));
3617
-	X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(LDR_tab[PROCNUM][classify_adr(adr_first, 0)]));
3618
-	ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<void, uint32_t, uint32_t *>());
3619
-	ctx->setArgument(0, addr);
3620
-	ctx->setArgument(1, data);
3621
-	ctx->setReturn(bb_cycles);
3611
+	auto ctx = c.addCall(imm_ptr(LDR_tab[PROCNUM][classify_adr(adr_first, 0)]), ASMJIT_CALL_CONV,
3612
+		FuncBuilder2<void, uint32_t, uint32_t *>());
3613
+	ctx->setArg(0, addr);
3614
+	ctx->setArg(1, data);
3615
+	ctx->setRet(0, bb_cycles);
3622 3616
 	return 1;
3623 3617
 }
3624 3618
 
... ...
@@ -3633,7 +3627,7 @@ static int op_ldm_stm_thumb(uint32_t i, bool store)
3633 3627
 	//if (BIT_N(i, _REG_NUM(i, 8)))
3634 3628
 	//	printf("WARNING - %sIA with Rb in Rlist (THUMB)\n", store?"STM":"LDM");
3635 3629
 
3636
-	GpVar adr = c.newGpVar(kX86VarTypeGpd);
3630
+	GpVar adr = c.newGpVar(kVarTypeInt32);
3637 3631
 	c.mov(adr, reg_pos_thumb(8));
3638 3632
 
3639 3633
 	call_ldm_stm(adr, bitmask, store, 1);
... ...
@@ -3672,7 +3666,7 @@ static int op_push_pop(uint32_t i, bool store, bool pc_lr)
3672 3666
 	uint32_t pop = popcount(bitmask);
3673 3667
 	int dir = store ? -1 : 1;
3674 3668
 
3675
-	GpVar adr = c.newGpVar(kX86VarTypeGpd);
3669
+	GpVar adr = c.newGpVar(kVarTypeInt32);
3676 3670
 	c.mov(adr, reg_ptr(13));
3677 3671
 	if (store)
3678 3672
 		c.sub(adr, 4);
... ...
@@ -3720,7 +3714,7 @@ static int OP_B_UNCOND(uint32_t i)
3720 3714
 
3721 3715
 static int OP_BLX(uint32_t i)
3722 3716
 {
3723
-	GpVar dst = c.newGpVar(kX86VarTypeGpd);
3717
+	GpVar dst = c.newGpVar(kVarTypeInt32);
3724 3718
 	c.mov(dst, reg_ptr(14));
3725 3719
 	c.add(dst, (i & 0x7FF) << 1);
3726 3720
 	c.and_(dst, 0xFFFFFFFC);
... ...
@@ -3738,9 +3732,9 @@ static int OP_BL_10( uint32_t i)
3738 3732
 	return 1;
3739 3733
 }
3740 3734
 
3741
-static int OP_BL_11(uint32_t i) 
3735
+static int OP_BL_11(uint32_t i)
3742 3736
 {
3743
-	GpVar dst = c.newGpVar(kX86VarTypeGpd);
3737
+	GpVar dst = c.newGpVar(kVarTypeInt32);
3744 3738
 	c.mov(dst, reg_ptr(14));
3745 3739
 	c.add(dst, (i & 0x7FF) << 1);
3746 3740
 	c.mov(cpu_ptr(instruct_adr), dst);
... ...
@@ -3750,8 +3744,8 @@ static int OP_BL_11(uint32_t i)
3750 3744
 
3751 3745
 static int op_bx_thumb(Mem srcreg, bool blx, bool test_thumb)
3752 3746
 {
3753
-	GpVar dst = c.newGpVar(kX86VarTypeGpd);
3754
-	GpVar thumb = c.newGpVar(kX86VarTypeGpd);
3747
+	GpVar dst = c.newGpVar(kVarTypeInt32);
3748
+	GpVar thumb = c.newGpVar(kVarTypeInt32);
3755 3749
 	c.mov(dst, srcreg);
3756 3750
 	c.mov(thumb, dst); // * cpu->CPSR.bits.T = BIT0(Rm);
3757 3751
 	c.and_(thumb, 1); // *
... ...
@@ -3759,14 +3753,14 @@ static int op_bx_thumb(Mem srcreg, bool blx, bool test_thumb)
3759 3753
 		c.mov(reg_ptr(14), bb_next_instruction | 1);
3760 3754
 	if (test_thumb)
3761 3755
 	{
3762
-		GpVar mask = c.newGpVar(kX86VarTypeGpd);
3763
-		c.lea(mask, ptr_abs(reinterpret_cast<void *>(0xFFFFFFFC), thumb.r64(), kScale2Times));
3756
+		GpVar mask = c.newGpVar(kVarTypeInt32);
3757
+		c.lea(mask, x86::ptr_abs(0xFFFFFFFC, thumb.r64(), 1));
3764 3758
 		c.and_(dst, mask);
3765 3759
 	}
3766 3760
 	else
3767 3761
 		c.and_(dst, 0xFFFFFFFE);
3768
-	
3769
-	GpVar tmp = c.newGpVar(kX86VarTypeGpd); // *
3762
+
3763
+	GpVar tmp = c.newGpVar(kVarTypeInt32); // *
3770 3764
 	c.mov(tmp, cpu_ptr_byte(CPSR, 0)); // *
3771 3765
 	c.and_(tmp, ~(1 << 5)); // *
3772 3766
 	c.shl(thumb, 5); // *
... ...
@@ -3892,7 +3886,7 @@ static bool instr_is_conditional(uint32_t opcode)
3892 3886
 {
3893 3887
 	if (bb_thumb)
3894 3888
 		return false;
3895
-	
3889
+
3896 3890
 	return !(CONDITION(opcode) == 0xE || (CONDITION(opcode) == 0xF && CODE(opcode) == 5));
3897 3891
 }
3898 3892
 
... ...
@@ -3904,7 +3898,7 @@ static int instr_cycles(uint32_t opcode)
3904 3898
 	{
3905 3899
 		if ((x & BRANCH_SWI) && !cpu->swi_tab)
3906 3900
 			return 3;
3907
-		
3901
+
3908 3902
 		return 0;
3909 3903
 	}
3910 3904
 	if (instr_is_branch(opcode) && !(instr_attributes(opcode) & (BRANCH_ALWAYS | BRANCH_LDM)))
... ...
@@ -3968,14 +3962,14 @@ static void emit_branch(int cond, Label to)
3968 3962
 	}
3969 3963
 	else
3970 3964
 	{
3971
-		GpVar x = c.newGpVar(kX86VarTypeGpz);
3965
+		GpVar x = c.newGpVar(kVarTypeIntPtr);
3972 3966
 		c.movzx(x, flags_ptr);
3973 3967
 		c.and_(x, 0xF0);
3974 3968
 #if defined(_M_X64) || defined(__x86_64__)
3975 3969
 		c.add(x, offsetof(armcpu_t,cond_table) + cond);
3976
-		c.test(byte_ptr(bb_cpu, x), 1);
3970
+		c.test(x86::byte_ptr(bb_cpu, x), 1);
3977 3971
 #else
3978
-		c.test(byte_ptr_abs((void *)(arm_cond_table + cond), x, kScaleNone), 1);
3972
+		c.test(x86::byte_ptr_abs(reinterpret_cast<Ptr>(&arm_cond_table[0]) + cond, x, 0), 1);
3979 3973
 #endif
3980 3974
 		c.unuse(x);
3981 3975
 		c.jz(to);
... ...
@@ -3989,13 +3983,12 @@ static void emit_armop_call(uint32_t opcode)
3989 3983
 		return;
3990 3984
 
3991 3985
 	JIT_COMMENT("call interpreter");
3992
-	GpVar arg = c.newGpVar(kX86VarTypeGpd);
3986
+	GpVar arg = c.newGpVar(kVarTypeInt32);
3993 3987
 	c.mov(arg, opcode);
3994 3988
 	OpFunc f = bb_thumb ? thumb_instructions_set[PROCNUM][opcode >> 6] : arm_instructions_set[PROCNUM][INSTRUCTION_INDEX(opcode)];
3995
-	X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(f));
3996
-	ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder1<uint32_t, uint32_t>());
3997
-	ctx->setArgument(0, arg);
3998
-	ctx->setReturn(bb_cycles);
3989
+	auto ctx = c.addCall(imm_ptr(f), ASMJIT_CALL_CONV, FuncBuilder1<uint32_t, uint32_t>());
3990
+	ctx->setArg(0, arg);
3991
+	ctx->setRet(0, bb_cycles);
3999 3992
 }
4000 3993
 
4001 3994
 static void _armlog(uint8_t proc, uint32_t addr, uint32_t opcode)
... ...
@@ -4003,7 +3996,7 @@ static void _armlog(uint8_t proc, uint32_t addr, uint32_t opcode)
4003 3996
 #if 0
4004 3997
 #if 0
4005 3998
 	fprintf(stderr, "\t\t;R0:%08X R1:%08X R2:%08X R3:%08X R4:%08X R5:%08X R6:%08X R7:%08X R8:%08X R9:%08X\n\t\t;R10:%08X R11:%08X R12:%08X R13:%08X R14:%08X R15:%08X| next %08X, N:%i Z:%i C:%i V:%i\n",
4006
-		cpu->R[0],  cpu->R[1],  cpu->R[2],  cpu->R[3],  cpu->R[4],  cpu->R[5],  cpu->R[6],  cpu->R[7], 
3999
+		cpu->R[0],  cpu->R[1],  cpu->R[2],  cpu->R[3],  cpu->R[4],  cpu->R[5],  cpu->R[6],  cpu->R[7],
4007 4000
 		cpu->R[8],  cpu->R[9],  cpu->R[10],  cpu->R[11],  cpu->R[12],  cpu->R[13],  cpu->R[14],  cpu->R[15],
4008 4001
 		cpu->next_instruction, cpu->CPSR.bits.N, cpu->CPSR.bits.Z, cpu->CPSR.bits.C, cpu->CPSR.bits.V);
4009 4002
 #endif
... ...
@@ -4014,7 +4007,7 @@ static void _armlog(uint8_t proc, uint32_t addr, uint32_t opcode)
4014 4007
 	else
4015 4008
 		des_arm_instructions_set[INDEX22(opcode)](addr, opcode, dasmbuf);
4016 4009
 	#undef INDEX22
4017
-	fprintf(stderr, "%s%c %08X\t%08X \t%s\n", cpu->CPSR.bits.T?"THUMB":"ARM", proc?'7':'9', addr, opcode, dasmbuf); 
4010
+	fprintf(stderr, "%s%c %08X\t%08X \t%s\n", cpu->CPSR.bits.T?"THUMB":"ARM", proc?'7':'9', addr, opcode, dasmbuf);
4018 4011
 #endif
4019 4012
 }
4020 4013
 
... ...
@@ -4026,7 +4019,7 @@ template<int PROCNUM> static uint32_t compile_basicblock()
4026 4019
 	uint32_t interpreted_cycles = 0;
4027 4020
 	uint32_t start_adr = cpu->instruct_adr;
4028 4021
 	uint32_t opcode = 0;
4029
-	
4022
+
4030 4023
 	bb_thumb = cpu->CPSR.bits.T;
4031 4024
 	bb_opcodesize = bb_thumb ? 2 : 4;
4032 4025
 
... ...
@@ -4041,22 +4034,22 @@ template<int PROCNUM> static uint32_t compile_basicblock()
4041 4034
 	fprintf(stderr, "adr %08Xh %s%c\n", start_adr, ARMPROC.CPSR.bits.T ? "THUMB":"ARM", PROCNUM?'7':'9');
4042 4035
 #endif
4043 4036
 
4044
-	c.clear();
4045
-	c.newFunc(ASMJIT_CALL_CONV, FuncBuilder0<int>());
4037
+	c.reset();
4038
+	c.addFunc(ASMJIT_CALL_CONV, FuncBuilder0<int>());
4046 4039
 	c.getFunc()->setHint(kFuncHintNaked, true);
4047 4040
 	c.getFunc()->setHint(kX86FuncHintPushPop, true);
4048
-	
4041
+
4049 4042
 	JIT_COMMENT("CPU ptr");
4050
-	bb_cpu = c.newGpVar(kX86VarTypeGpz);
4043
+	bb_cpu = c.newGpVar(kVarTypeIntPtr);
4051 4044
 	c.mov(bb_cpu, (uintptr_t)&ARMPROC);
4052 4045
 
4053 4046
 	JIT_COMMENT("reset bb_total_cycles");
4054
-	bb_total_cycles = c.newGpVar(kX86VarTypeGpz);
4047
+	bb_total_cycles = c.newGpVar(kVarTypeIntPtr);
4055 4048
 	c.mov(bb_total_cycles, 0);
4056 4049
 
4057
-#if (PROFILER_JIT_LEVEL > 0)
4050
+#if PROFILER_JIT_LEVEL > 0
4058 4051
 	JIT_COMMENT("Profiler ptr");
4059
-	bb_profiler = c.newGpVar(kX86VarTypeGpz);
4052
+	bb_profiler = c.newGpVar(kVarTypeIntPtr);
4060 4053
 	c.mov(bb_profiler, reinterpret_cast<uintptr_t>(&profiler_counter[PROCNUM]));
4061 4054
 #endif
4062 4055
 
... ...
@@ -4081,12 +4074,12 @@ template<int PROCNUM> static uint32_t compile_basicblock()
4081 4074
 		uint32_t cycles = instr_cycles(opcode);
4082 4075
 
4083 4076
 		bEndBlock = i >= CommonSettings.jit_max_block_size - 1 || instr_is_branch(opcode);
4084
-		
4077
+
4085 4078
 #if LOG_JIT
4086 4079
 		if (instr_is_conditional(opcode) && cycles > 1 || !cycles)
4087 4080
 			has_variable_cycles = true;
4088 4081
 #endif
4089
-		bb_cycles = c.newGpVar(kX86VarTypeGpz);
4082
+		bb_cycles = c.newGpVar(kVarTypeIntPtr);
4090 4083
 
4091 4084
 		bb_constant_cycles += instr_is_conditional(opcode) ? 1 : cycles;
4092 4085
 
... ...
@@ -4111,11 +4104,11 @@ template<int PROCNUM> static uint32_t compile_basicblock()
4111 4104
 			if (!bEndBlock)
4112 4105
 				sync_r15(opcode, 0, 0);
4113 4106
 			emit_armop_call(opcode);
4114
-			
4107
+
4115 4108
 			if (!cycles)
4116 4109
 			{
4117 4110
 				JIT_COMMENT("variable cycles");
4118
-				c.lea(bb_total_cycles, ptr(bb_total_cycles.r64(), bb_cycles.r64(), kScaleNone));
4111
+				c.lea(bb_total_cycles, x86::ptr(bb_total_cycles.r64(), bb_cycles.r64(), 0));
4119 4112
 			}
4120 4113
 			c.bind(skip);
4121 4114
 		}
... ...
@@ -4126,16 +4119,16 @@ template<int PROCNUM> static uint32_t compile_basicblock()
4126 4119
 			if (!cycles)
4127 4120
 			{
4128 4121
 				JIT_COMMENT("variable cycles");
4129
-				c.lea(bb_total_cycles, ptr(bb_total_cycles.r64(), bb_cycles.r64(), kScaleNone));
4122
+				c.lea(bb_total_cycles, x86::ptr(bb_total_cycles.r64(), bb_cycles.r64(), 0));
4130 4123
 			}
4131 4124
 		}
4132 4125
 		interpreted_cycles += op_decode[PROCNUM][bb_thumb]();
4133 4126
 	}
4134
-	
4127
+
4135 4128
 	if (!instr_does_prefetch(opcode))
4136 4129
 	{
4137 4130
 		JIT_COMMENT("!instr_does_prefetch: copy next_instruction (%08X) to instruct_adr (%08X)", cpu->next_instruction, cpu->instruct_adr);
4138
-		GpVar x = c.newGpVar(kX86VarTypeGpd);
4131
+		GpVar x = c.newGpVar(kVarTypeInt32);
4139 4132
 		c.mov(x, cpu_ptr(next_instruction));
4140 4133
 		c.mov(cpu_ptr(instruct_adr), x);
4141 4134
 		c.unuse(x);
... ...
@@ -4151,9 +4144,9 @@ template<int PROCNUM> static uint32_t compile_basicblock()
4151 4144
 #if PROFILER_JIT_LEVEL > 1
4152 4145
 	JIT_COMMENT("*** profiler - cycles");
4153 4146
 	uint32_t padr = (start_adr & 0x07FFFFFE) >> 1;
4154
-	bb_profiler_entry = c.newGpVar(kX86VarTypeGpz);
4147
+	bb_profiler_entry = c.newGpVar(kVarTypeIntPtr);
4155 4148
 	c.mov(bb_profiler_entry, reinterpret_cast<uintptr_t>(&profiler_entry[PROCNUM][padr]));
4156
-	c.add(dword_ptr(bb_profiler_entry, offsetof(PROFILER_ENTRY, cycles)), bb_total_cycles);
4149
+	c.add(X86Mem(bb_profiler_entry, offsetof(PROFILER_ENTRY, cycles), 4), bb_total_cycles);
4157 4150
 	profiler_entry[PROCNUM][padr].addr = start_adr;
4158 4151
 #endif
4159 4152
 
... ...
@@ -4164,9 +4157,9 @@ template<int PROCNUM> static uint32_t compile_basicblock()
4164 4157
 	c.endFunc();
4165 4158
 
4166 4159
 	ArmOpCompiled f = static_cast<ArmOpCompiled>(c.make());
4167
-	if(c.getError())
4160
+	if (c.getError())
4168 4161
 	{
4169
-		fprintf(stderr, "JIT error: %s\n", getErrorString(c.getError()));
4162
+		fprintf(stderr, "JIT error: %s\n", ErrorUtil::asString(c.getError()));
4170 4163
 		f = op_decode[PROCNUM][bb_thumb];
4171 4164
 	}
4172 4165
 #if LOG_JIT
... ...
@@ -4174,7 +4167,7 @@ template<int PROCNUM> static uint32_t compile_basicblock()
4174 4167
 	fprintf(stderr, "Block address %08lX\n\n", baddr);
4175 4168
 	fflush(stderr);
4176 4169
 #endif
4177
-	
4170
+
4178 4171
 	JIT_COMPILED_FUNC(start_adr, PROCNUM) = reinterpret_cast<uintptr_t>(f);
4179 4172
 	return interpreted_cycles;
4180 4173
 }
... ...
@@ -4219,7 +4212,7 @@ void arm_jit_reset(bool enable)
4219 4212
 		printf("JIT max block size %d instruction(s)\n", CommonSettings.jit_max_block_size);
4220 4213
 #ifdef MAPPED_JIT_FUNCS
4221 4214
 		// these pointers are allocated by asmjit and need freeing
4222
-		#define JITFREE(x)  for (size_t iii = 0; iii < ARRAY_SIZE((x)); ++iii) if ((x)[iii]) AsmJit::MemoryManager::getGlobal()->free(reinterpret_cast<void *>((x)[iii])); memset((x), 0, sizeof((x)));
4215
+		#define JITFREE(x)  for (size_t iii = 0; iii < ARRAY_SIZE((x)); ++iii) if ((x)[iii]) runtime.getMemMgr()->release(reinterpret_cast<void *>((x)[iii])); memset((x), 0, sizeof((x)));
4223 4216
 			JITFREE(JIT.MAIN_MEM);
4224 4217
 			JITFREE(JIT.SWIRAM);
4225 4218
 			JITFREE(JIT.ARM9_ITCM);
... ...
@@ -4243,7 +4236,7 @@ void arm_jit_reset(bool enable)
4243 4236
 #endif
4244 4237
 	}
4245 4238
 
4246
-	c.clear();
4239
+	c.reset();
4247 4240
 
4248 4241
 #if PROFILER_JIT_LEVEL > 0
4249 4242
 	reconstruct(&profiler_counter[0]);
... ...
@@ -4284,8 +4277,8 @@ void arm_jit_close()
4284 4277
 
4285 4278
 		auto arm_info = std::unique_ptr<PROFILER_COUNTER_INFO[]>(new PROFILER_COUNTER_INFO[4096]);
4286 4279
 		auto thumb_info = std::unique_ptr<PROFILER_COUNTER_INFO[]>(new PROFILER_COUNTER_INFO[1024]);
4287
-		memset(arm_info, 0, sizeof(PROFILER_COUNTER_INFO) * 4096);
4288
-		memset(thumb_info, 0, sizeof(PROFILER_COUNTER_INFO) * 1024);
4280
+		memset(&arm_info[0], 0, sizeof(PROFILER_COUNTER_INFO) * 4096);
4281
+		memset(&thumb_info[0], 0, sizeof(PROFILER_COUNTER_INFO) * 1024);
4289 4282
 
4290 4283
 		// ARM
4291 4284
 		last[0] = 0;
... ...
@@ -4331,8 +4324,8 @@ void arm_jit_close()
4331 4324
 			}
4332 4325
 		}
4333 4326
 
4334
-		std::qsort(arm_info, last[0], sizeof(PROFILER_COUNTER_INFO), (int (*)(const void *, const void *))pcmp);
4335
-		std::qsort(thumb_info, last[1], sizeof(PROFILER_COUNTER_INFO), (int (*)(const void *, const void *))pcmp);
4327
+		std::qsort(&arm_info[0], last[0], sizeof(PROFILER_COUNTER_INFO), (int (*)(const void *, const void *))pcmp);
4328
+		std::qsort(&thumb_info[0], last[1], sizeof(PROFILER_COUNTER_INFO), (int (*)(const void *, const void *))pcmp);
4336 4329
 
4337 4330
 		char buf[MAX_PATH] = { 0 };
4338 4331
 		sprintf(buf, "\\desmume_jit%c_counter.profiler", !proc ? '9' : '7');
... ...
@@ -4355,7 +4348,7 @@ void arm_jit_close()
4355 4348
 					fprintf(fp, "%30s: %20ld\n", arm_info[i].name, arm_info[i].count);
4356 4349
 				fprintf(fp, "\n");
4357 4350
 			}
4358
-			
4351
+
4359 4352
 			if (last[1])
4360 4353
 			{
4361 4354
 				fprintf(fp, "========================================== THUMB ==========================================\n");
Browse code

Updated to latest DeSmuME SVN.

Naram Qashat authored on 2013/04/19 13:01:50
Showing 1 changed files
... ...
@@ -50,9 +50,28 @@ using namespace AsmJit;
50 50
 #if LOG_JIT_LEVEL > 0
51 51
 #define LOG_JIT 1
52 52
 #define JIT_COMMENT(...) c.comment(__VA_ARGS__)
53
+#define printJIT(buf, val) \
54
+{ \
55
+	JIT_COMMENT("printJIT(\""##buf"\", val);"); \
56
+	GpVar txt = c.newGpVar(kX86VarTypeGpz); \
57
+	GpVar data = c.newGpVar(kX86VarTypeGpz); \
58
+	GpVar io = c.newGpVar(kX86VarTypeGpd); \
59
+	c.lea(io, dword_ptr_abs(stdout)); \
60
+	c.lea(txt, dword_ptr_abs(&buf)); \
61
+	c.mov(data, *reinterpret_cast<GpVar *>(&val)); \
62
+	X86CompilerFuncCall* prn = c.call(reinterpret_cast<uintptr_t>(fprintf)); \
63
+	prn->setPrototype(ASMJIT_CALL_CONV, FuncBuilder3<void, void *, void *, uint32_t>()); \
64
+	prn->setArgument(0, io); \
65
+	prn->setArgument(1, txt); \
66
+	prn->setArgument(2, data); \
67
+	X86CompilerFuncCall *prn_flush = c.call(reinterpret_cast<uintptr_t>(fflush)); \
68
+	prn_flush->setPrototype(ASMJIT_CALL_CONV, FuncBuilder1<void, void *>()); \
69
+	prn_flush->setArgument(0, io); \
70
+}
53 71
 #else
54 72
 #define LOG_JIT 0
55 73
 #define JIT_COMMENT(...)
74
+#define printJIT(buf, val)
56 75
 #endif
57 76
 
58 77
 #ifdef MAPPED_JIT_FUNCS
... ...
@@ -1392,6 +1411,7 @@ static int OP_MRS_SPSR(uint32_t i)
1392 1411
 #define OP_MSR_(reg, args, sw) \
1393 1412
 	GpVar operand = c.newGpVar(kX86VarTypeGpd); \
1394 1413
 	args; \
1414
+	c.mov(operand, rhs); \
1395 1415
 	switch ((i >> 16) & 0xF) \
1396 1416
 	{ \
1397 1417
 		case 0x1: /* bit 16 */ \
... ...
@@ -1411,7 +1431,6 @@ static int OP_MRS_SPSR(uint32_t i)
1411 1431
 				ctx->setArgument(0, bb_cpu); \
1412 1432
 				ctx->setArgument(1, mode); \
1413 1433
 			} \
1414
-			c.mov(operand, rhs); \
1415 1434
 			Mem xPSR_memB = cpu_ptr_byte(reg, 0); \
1416 1435
 			c.mov(xPSR_memB, operand.r8Lo()); \
1417 1436
 			changeCPSR; \
... ...
@@ -1426,7 +1445,6 @@ static int OP_MRS_SPSR(uint32_t i)
1426 1445
 			c.and_(mode, 0x1F); \
1427 1446
 			c.cmp(mode, USR); \
1428 1447
 			c.je(__skip); \
1429
-			c.mov(operand, rhs); \
1430 1448
 			Mem xPSR_memB = cpu_ptr_byte(reg, 1); \
1431 1449
 			c.shr(operand, 8); \
1432 1450
 			c.mov(xPSR_memB, operand.r8Lo()); \
... ...
@@ -1442,7 +1460,6 @@ static int OP_MRS_SPSR(uint32_t i)
1442 1460
 			c.and_(mode, 0x1F); \
1443 1461
 			c.cmp(mode, USR); \
1444 1462
 			c.je(__skip); \
1445
-			c.mov(operand, rhs); \
1446 1463
 			Mem xPSR_memB = cpu_ptr_byte(reg, 2); \
1447 1464
 			c.shr(operand, 16); \
1448 1465
 			c.mov(xPSR_memB, operand.r8Lo()); \
... ...
@@ -1452,7 +1469,6 @@ static int OP_MRS_SPSR(uint32_t i)
1452 1469
 		} \
1453 1470
 		case 0x8: /* bit 19 */ \
1454 1471
 		{ \
1455
-			c.mov(operand, rhs); \
1456 1472
 			Mem xPSR_memB = cpu_ptr_byte(reg, 3); \
1457 1473
 			c.shr(operand, 24); \
1458 1474
 			c.mov(xPSR_memB, operand.r8Lo()); \
... ...
@@ -1485,7 +1501,6 @@ static int OP_MRS_SPSR(uint32_t i)
1485 1501
 		ctx->setArgument(1, mode); \
1486 1502
 	} \
1487 1503
 	/* cpu->CPSR.val = (cpu->CPSR.val & ~byte_mask) | (operand & byte_mask); */ \
1488
-	c.mov(operand, rhs); \
1489 1504
 	c.mov(xPSR, xPSR_mem); \
1490 1505
 	c.and_(operand, byte_mask); \
1491 1506
 	c.and_(xPSR, ~byte_mask); \
... ...
@@ -1494,7 +1509,6 @@ static int OP_MRS_SPSR(uint32_t i)
1494 1509
 	c.jmp(__done); \
1495 1510
 	/* mode == USR */ \
1496 1511
 	c.bind(__USR); \
1497
-	c.mov(operand, rhs); \
1498 1512
 	c.mov(xPSR, xPSR_mem); \
1499 1513
 	c.and_(operand, byte_mask_USR); \
1500 1514
 	c.and_(xPSR, ~byte_mask_USR); \
... ...
@@ -4199,10 +4213,10 @@ void arm_jit_reset(bool enable)
4199 4213
 	scratchptr = scratchpad;
4200 4214
 #endif
4201 4215
 	printf("CPU mode: %s\n", enable ? "JIT" : "Interpreter");
4202
-	printf("JIT max block size %d instruction(s)\n", CommonSettings.jit_max_block_size);
4203 4216
 
4204 4217
 	if (enable)
4205 4218
 	{
4219
+		printf("JIT max block size %d instruction(s)\n", CommonSettings.jit_max_block_size);
4206 4220
 #ifdef MAPPED_JIT_FUNCS
4207 4221
 		// these pointers are allocated by asmjit and need freeing
4208 4222
 		#define JITFREE(x)  for (size_t iii = 0; iii < ARRAY_SIZE((x)); ++iii) if ((x)[iii]) AsmJit::MemoryManager::getGlobal()->free(reinterpret_cast<void *>((x)[iii])); memset((x), 0, sizeof((x)));
Browse code

Removed a bunch of casts, they seem to be fine without them in most cases.

Naram Qashat authored on 2013/04/18 23:22:54
Showing 1 changed files
... ...
@@ -484,7 +484,7 @@ static GpVar bb_profiler_entry;
484 484
 	if (!imm) \
485 485
 		imm = 31; \
486 486
 	c.sar(rhs, imm); \
487
-	uint32_t rhs_first = static_cast<int32_t>(cpu->R[REG_POS(i, 0)]) >> imm;
487
+	uint32_t rhs_first = cpu->R[REG_POS(i, 0)] >> imm;
488 488
 
489 489
 #define S_ASR_IMM \
490 490
 	JIT_COMMENT("S_ASR_IMM"); \
... ...
@@ -512,7 +512,7 @@ static GpVar bb_profiler_entry;
512 512
 	} \
513 513
 	else \
514 514
 		c.ror(rhs, imm); \
515
-	uint32_t rhs_first = imm ? ROR(cpu->R[REG_POS(i, 0)], imm) : (static_cast<uint32_t>(cpu->CPSR.bits.C) << 31) | (cpu->R[REG_POS(i, 0)] >> 1);
515
+	uint32_t rhs_first = imm ? ROR(cpu->R[REG_POS(i, 0)], imm) : (cpu->CPSR.bits.C << 31) | (cpu->R[REG_POS(i, 0)] >> 1);
516 516
 
517 517
 #define S_ROR_IMM \
518 518
 	JIT_COMMENT("S_ROR_IMM"); \
... ...
@@ -2136,7 +2136,7 @@ template<int PROCNUM, bool store, int dir, bool null_compiled> static FORCEINLIN
2136 2136
 #ifdef ENABLE_ADVANCED_TIMING
2137 2137
 	cycles = 0;
2138 2138
 #endif
2139
-	uintptr_t *func = reinterpret_cast<uintptr_t *>(&JIT_COMPILED_FUNC(adr, PROCNUM));
2139
+	uintptr_t *func = &JIT_COMPILED_FUNC(adr, PROCNUM);
2140 2140
 
2141 2141
 #define OP(j) \
2142 2142
 { \
... ...
@@ -2247,7 +2247,7 @@ static void call_ldm_stm(GpVar adr, uint32_t bitmask, bool store, int dir)
2247 2247
 		// same prototype, but we have to handle splitting of a u64 arg manually
2248 2248
 		GpVar regs_lo = c.newGpVar(kX86VarTypeGpd);
2249 2249
 		GpVar regs_hi = c.newGpVar(kX86VarTypeGpd);
2250
-		c.mov(regs_lo, static_cast<uint32_t>(get_reg_list(bitmask, dir)));
2250
+		c.mov(regs_lo, get_reg_list(bitmask, dir) & 0xFFFFFFFF);
2251 2251
 		c.mov(regs_hi, get_reg_list(bitmask, dir) >> 32);
2252 2252
 		X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(op_ldm_stm_tab[PROCNUM][store][dir > 0]));
2253 2253
 		ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder4<uint32_t, uint32_t, uint32_t, uint32_t, int>());
... ...
@@ -3685,7 +3685,7 @@ static int OP_B_COND(uint32_t i)
3685 3685
 {
3686 3686
 	Label skip = c.newLabel();
3687 3687
 
3688
-	uint32_t dst = bb_r15 + (static_cast<uint32_t>(static_cast<int8_t>(i & 0xFF)) << 1);
3688
+	uint32_t dst = bb_r15 + ((i & 0xFF) << 1);
3689 3689
 
3690 3690
 	c.mov(cpu_ptr(instruct_adr), bb_next_instruction);
3691 3691
 
... ...
@@ -4149,7 +4149,7 @@ template<int PROCNUM> static uint32_t compile_basicblock()
4149 4149
 #endif
4150 4150
 	c.endFunc();
4151 4151
 
4152
-	ArmOpCompiled f = reinterpret_cast<ArmOpCompiled>(c.make());
4152
+	ArmOpCompiled f = static_cast<ArmOpCompiled>(c.make());
4153 4153
 	if(c.getError())
4154 4154
 	{
4155 4155
 		fprintf(stderr, "JIT error: %s\n", getErrorString(c.getError()));
... ...
@@ -4247,13 +4247,13 @@ void arm_jit_reset(bool enable)
4247 4247
 #if PROFILER_JIT_LEVEL > 0
4248 4248
 static int pcmp(PROFILER_COUNTER_INFO *info1, PROFILER_COUNTER_INFO *info2)
4249 4249
 {
4250
-	return static_cast<int>(info2->count - info1->count);
4250
+	return info2->count - info1->count;
4251 4251
 }
4252 4252
 
4253 4253
 #if PROFILER_JIT_LEVEL > 1
4254 4254
 static int pcmp_entry(PROFILER_ENTRY *info1, PROFILER_ENTRY *info2)
4255 4255
 {
4256
-	return static_cast<int>(info1->cycles - info2->cycles);
4256
+	return info1->cycles - info2->cycles;
4257 4257
 }
4258 4258
 #endif
4259 4259
 #endif
Browse code

Updating in_2sf to use a newish version of DeSmuME, 0.9.9 from SVN. Somewhat cleaned up as well, but not everything because it's a pain in the ass.

Naram Qashat authored on 2013/04/18 17:22:55
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,4392 @@
1
+/*	Copyright (C) 2006 yopyop
2
+	Copyright (C) 2011 Loren Merritt
3
+	Copyright (C) 2012 DeSmuME team
4
+
5
+	This file is free software: you can redistribute it and/or modify
6
+	it under the terms of the GNU General Public License as published by
7
+	the Free Software Foundation, either version 3 of the License, or
8
+	(at your option) any later version.
9
+
10
+	This file is distributed in the hope that it will be useful,
11
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
+	GNU General Public License for more details.
14
+
15
+	You should have received a copy of the GNU General Public License
16
+	along with the this software.  If not, see <http://www.gnu.org/licenses/>.
17
+*/
18
+
19
+#include "types.h"
20
+#ifdef HAVE_JIT
21
+#if !defined(__x86_64__) && !defined(__LP64) && !defined(__IA64__) && !defined(_M_X64) && !defined(_WIN64) && !defined(_M_IX86) && !defined(__INTEL__) && !defined(__i386__)
22
+#error "ERROR: JIT compiler - unsupported target platform"
23
+#endif
24
+#ifdef _WINDOWS
25
+// **** Windows port
26
+#else
27
+# include <sys/mman.h>
28
+# include <errno.h>
29
+# include <unistd.h>
30
+# include <stddef.h>
31
+# define HAVE_STATIC_CODE_BUFFER
32
+#endif
33
+#include "instructions.h"
34
+#include "instruction_attributes.h"
35
+#include "MMU.h"
36
+#include "MMU_timing.h"
37
+#include "utils/AsmJit/AsmJit.h"
38
+#include "arm_jit.h"
39
+#include "bios.h"
40
+
41
+#define LOG_JIT_LEVEL 0
42
+#define PROFILER_JIT_LEVEL 0
43
+
44
+#if PROFILER_JIT_LEVEL > 0
45
+#include <algorithm>
46
+#endif
47
+
48
+using namespace AsmJit;
49
+
50
+#if LOG_JIT_LEVEL > 0
51
+#define LOG_JIT 1
52
+#define JIT_COMMENT(...) c.comment(__VA_ARGS__)
53
+#else
54
+#define LOG_JIT 0
55
+#define JIT_COMMENT(...)
56
+#endif
57
+
58
+#ifdef MAPPED_JIT_FUNCS
59
+CACHE_ALIGN JIT_struct JIT;
60
+
61
+uintptr_t *JIT_struct::JIT_MEM[2][0x4000] = { { 0 }, { 0 } };
62
+
63
+static uintptr_t *JIT_MEM[][32] =
64
+{
65
+	//arm9
66
+	{
67
+		/* 0X*/	DUP2(JIT.ARM9_ITCM),
68
+		/* 1X*/	DUP2(JIT.ARM9_ITCM), // mirror
69
+		/* 2X*/	DUP2(JIT.MAIN_MEM),
70
+		/* 3X*/	DUP2(JIT.SWIRAM),
71
+		/* 4X*/	DUP2(nullptr),
72
+		/* 5X*/	DUP2(nullptr),
73
+		/* 6X*/	nullptr,
74
+				JIT.ARM9_LCDC, // Plain ARM9-CPU Access (LCDC mode) (max 656KB)
75
+		/* 7X*/	DUP2(nullptr),
76
+		/* 8X*/	DUP2(nullptr),
77
+		/* 9X*/	DUP2(nullptr),
78
+		/* AX*/	DUP2(nullptr),
79
+		/* BX*/	DUP2(nullptr),
80
+		/* CX*/	DUP2(nullptr),
81
+		/* DX*/	DUP2(nullptr),
82
+		/* EX*/	DUP2(nullptr),
83
+		/* FX*/	DUP2(JIT.ARM9_BIOS)
84
+	},
85
+	//arm7
86
+	{
87
+		/* 0X*/	DUP2(JIT.ARM7_BIOS),
88
+		/* 1X*/	DUP2(nullptr),
89
+		/* 2X*/	DUP2(JIT.MAIN_MEM),
90
+		/* 3X*/	JIT.SWIRAM,
91
+				JIT.ARM7_ERAM,
92
+		/* 4X*/	nullptr,
93
+				JIT.ARM7_WIRAM,
94
+		/* 5X*/	DUP2(nullptr),
95
+		/* 6X*/	JIT.ARM7_WRAM,		// VRAM allocated as Work RAM to ARM7 (max. 256K)
96
+				nullptr,
97
+		/* 7X*/	DUP2(nullptr),
98
+		/* 8X*/	DUP2(nullptr),
99
+		/* 9X*/	DUP2(nullptr),
100
+		/* AX*/	DUP2(nullptr),
101
+		/* BX*/	DUP2(nullptr),
102
+		/* CX*/	DUP2(nullptr),
103
+		/* DX*/	DUP2(nullptr),
104
+		/* EX*/	DUP2(nullptr),
105
+		/* FX*/	DUP2(nullptr)
106
+	}
107
+};
108
+
109
+static uint32_t JIT_MASK[][32] =
110
+{
111
+	//arm9
112
+	{
113
+		/* 0X*/	DUP2(0x00007FFF),
114
+		/* 1X*/	DUP2(0x00007FFF),
115
+		/* 2X*/	DUP2(0x003FFFFF), // FIXME _MMU_MAIN_MEM_MASK
116
+		/* 3X*/	DUP2(0x00007FFF),
117
+		/* 4X*/	DUP2(0x00000000),
118
+		/* 5X*/	DUP2(0x00000000),
119
+		/* 6X*/	0x00000000,
120
+				0x000FFFFF,
121
+		/* 7X*/	DUP2(0x00000000),
122
+		/* 8X*/	DUP2(0x00000000),
123
+		/* 9X*/	DUP2(0x00000000),
124
+		/* AX*/	DUP2(0x00000000),
125
+		/* BX*/	DUP2(0x00000000),
126
+		/* CX*/	DUP2(0x00000000),
127
+		/* DX*/	DUP2(0x00000000),
128
+		/* EX*/	DUP2(0x00000000),
129
+		/* FX*/	DUP2(0x00007FFF)
130
+	},
131
+	//arm7
132
+	{
133
+		/* 0X*/	DUP2(0x00003FFF),
134
+		/* 1X*/	DUP2(0x00000000),
135
+		/* 2X*/	DUP2(0x003FFFFF),
136
+		/* 3X*/	0x00007FFF,
137
+				0x0000FFFF,
138
+		/* 4X*/	0x00000000,
139
+				0x0000FFFF,
140
+		/* 5X*/	DUP2(0x00000000),
141
+		/* 6X*/	0x0003FFFF,
142
+				0x00000000,
143
+		/* 7X*/	DUP2(0x00000000),
144
+		/* 8X*/	DUP2(0x00000000),
145
+		/* 9X*/	DUP2(0x00000000),
146
+		/* AX*/	DUP2(0x00000000),
147
+		/* BX*/	DUP2(0x00000000),
148
+		/* CX*/	DUP2(0x00000000),
149
+		/* DX*/	DUP2(0x00000000),
150
+		/* EX*/	DUP2(0x00000000),
151
+		/* FX*/	DUP2(0x00000000)
152
+	}
153
+};
154
+
155
+static void init_jit_mem()
156
+{
157
+	static bool inited = false;
158
+	if (inited)
159
+		return;
160
+	inited = true;
161
+	for (int proc = 0; proc < 2; ++proc)
162
+		for (int i = 0; i < 0x4000; ++i)
163
+			JIT.JIT_MEM[proc][i] = JIT_MEM[proc][i >> 9] + (((i << 14) & JIT_MASK[proc][i >> 9]) >> 1);
164
+}
165
+#else
166
+DS_ALIGN(4096) uintptr_t compiled_funcs[1 << 26] = {0};
167
+#endif
168
+
169
+static uint8_t recompile_counts[(1 << 26) / 16];
170
+
171
+#ifdef HAVE_STATIC_CODE_BUFFER
172
+// On x86_64, allocate jitted code from a static buffer to ensure that it's within 2GB of .text
173
+// Allows call instructions to use pcrel offsets, as opposed to slower indirect calls.
174
+// Reduces memory needed for function pointers.
175
+// FIXME win64 needs this too, x86_32 doesn't
176
+
177
+DS_ALIGN(4096) static uint8_t scratchpad[1 << 25];
178
+static uint8_t *scratchptr;
179
+
180
+struct ASMJIT_API StaticCodeGenerator : public Context
181
+{
182
+	StaticCodeGenerator()
183
+	{
184
+		scratchptr = scratchpad;
185
+		int align = reinterpret_cast<uintptr_t>(scratchpad) & (sysconf(_SC_PAGESIZE) - 1);
186
+		int err = mprotect(scratchpad - align, sizeof(scratchpad) + align, PROT_READ | PROT_WRITE | PROT_EXEC);
187
+		if (err)
188
+		{
189
+			fprintf(stderr, "mprotect failed: %s\n", strerror(errno));
190
+			abort();
191
+		}
192
+	}
193
+
194
+	uint32_t generate(void **dest, Assembler *assembler)
195
+	{
196
+		uintptr_t size = assembler->getCodeSize();
197
+		if (!size)
198
+		{
199
+			*dest = nullptr;
200
+			return kErrorNoFunction;
201
+		}
202
+		if (size > reinterpret_cast<uintptr_t>(scratchpad + sizeof(scratchpad) - scratchptr))
203
+		{
204
+			fprintf(stderr, "Out of memory for asmjit. Clearing code cache.\n");
205
+			arm_jit_reset(true);
206
+			// If arm_jit_reset didn't involve recompiling op_cmp, we could keep the current function.
207
+			*dest = nullptr;
208
+			return kErrorOk;
209
+		}
210
+		void *p = scratchptr;
211
+		size = assembler->relocCode(p);
212
+		scratchptr += size;
213
+		*dest = p;
214
+		return kErrorOk;
215
+	}
216
+};
217
+
218
+static StaticCodeGenerator codegen;
219
+static X86Compiler c(&codegen);
220
+#else
221
+static X86Compiler c;
222
+#endif
223
+
224
+static void emit_branch(int cond, Label to);
225
+static void _armlog(uint8_t proc, uint32_t addr, uint32_t opcode);
226
+
227
+static FileLogger logger(stderr);
228
+
229
+static int PROCNUM;
230
+static int *PROCNUM_ptr = &PROCNUM;
231
+static int bb_opcodesize;
232
+static int bb_adr;
233
+static bool bb_thumb;
234
+static GpVar bb_cpu;
235
+static GpVar bb_cycles;
236
+static GpVar bb_total_cycles;
237
+static uint32_t bb_constant_cycles;
238
+
239
+#define cpu (&ARMPROC)
240
+#define bb_next_instruction (bb_adr + bb_opcodesize)
241
+#define bb_r15 (bb_adr + 2 * bb_opcodesize)
242
+
243
+#define cpu_ptr(x) dword_ptr(bb_cpu, offsetof(armcpu_t, x))
244
+#define cpu_ptr_byte(x, y) byte_ptr(bb_cpu, offsetof(armcpu_t, x) + y)
245
+#define flags_ptr cpu_ptr_byte(CPSR.val, 3)
246
+#define reg_ptr(x) dword_ptr(bb_cpu, offsetof(armcpu_t, R) + 4 * (x))
247
+#define reg_pos_ptr(x) dword_ptr(bb_cpu, offsetof(armcpu_t, R) + 4 * REG_POS(i, (x)))
248
+#define reg_pos_ptrL(x) word_ptr(bb_cpu, offsetof(armcpu_t, R) + 4 * REG_POS(i, (x)))
249
+#define reg_pos_ptrH(x) word_ptr(bb_cpu, offsetof(armcpu_t, R) + 4 * REG_POS(i, (x)) + 2)
250
+#define reg_pos_ptrB(x) byte_ptr(bb_cpu, offsetof(armcpu_t, R) + 4 * REG_POS(i, (x)))
251
+#define reg_pos_thumb(x) dword_ptr(bb_cpu, offsetof(armcpu_t, R) + 4 * ((i >> (x)) & 0x7))
252
+#define reg_pos_thumbB(x) byte_ptr(bb_cpu, offsetof(armcpu_t, R) + 4 * ((i >> (x)) & 0x7))
253
+#define cp15_ptr(x) dword_ptr(bb_cp15, offsetof(armcp15_t, x))
254
+#define mmu_ptr(x) dword_ptr(bb_mmu, offsetof(MMU_struct, x))
255
+#define mmu_ptr_byte(x) byte_ptr(bb_mmu, offsetof(MMU_struct, x))
256
+static inline uint32_t _REG_NUM(uint32_t i, uint32_t n) { return (i >> n) & 0x7; }
257
+
258
+#ifndef ASMJIT_X64
259
+#define r64 r32
260
+#endif
261
+
262
+// sequencer.reschedule = true;
263
+#define changeCPSR \
264
+{ \
265
+	X86CompilerFuncCall *ctxCPSR = c.call(reinterpret_cast<void *>(NDS_Reschedule)); \
266
+	ctxCPSR->setPrototype(ASMJIT_CALL_CONV, FuncBuilder0<void>()); \
267
+}
268
+
269
+#if PROFILER_JIT_LEVEL > 0
270
+struct PROFILER_COUNTER_INFO
271
+{
272
+	uint64_t count;
273
+	char name[64];
274
+};
275
+
276
+struct JIT_PROFILER
277
+{
278
+	JIT_PROFILER::JIT_PROFILER()
279
+	{
280
+		memset(&this->arm_count[0], 0, sizeof(this->arm_count));
281
+		memset(&this->thumb_count[0], 0, sizeof(this->thumb_count));
282
+	}
283
+
284
+	uint64_t arm_count[4096];
285
+	uint64_t thumb_count[1024];
286
+} profiler_counter[2];
287
+
288
+static GpVar bb_profiler;
289
+
290
+#define profiler_counter_arm(opcode) qword_ptr(bb_profiler, offsetof(JIT_PROFILER, arm_count[INSTRUCTION_INDEX(opcode)]))
291
+#define profiler_counter_thumb(opcode) qword_ptr(bb_profiler, offsetof(JIT_PROFILER, thumb_count[opcode>>6]))
292
+
293
+#if PROFILER_JIT_LEVEL > 1
294
+struct PROFILER_ENTRY
295
+{
296
+	uint32_t addr;
297
+	uint32_t cycles;
298
+} profiler_entry[2][1<<26];
299
+
300
+static GpVar bb_profiler_entry;
301
+#endif
302
+
303
+#endif
304
+
305
+// -----------------------------------------------------------------------------
306
+//   Shifting macros
307
+// -----------------------------------------------------------------------------
308
+#define SET_NZCV(sign) \
309
+{ \
310
+	JIT_COMMENT("SET_NZCV"); \
311
+	GpVar x = c.newGpVar(kX86VarTypeGpd); \
312
+	GpVar y = c.newGpVar(kX86VarTypeGpd); \
313
+	c.sets(x.r8Lo()); \
314
+	c.setz(y.r8Lo()); \
315
+	c.lea(x, ptr(y.r64(), x.r64(), kScale2Times)); \
316
+	if (sign) \
317
+		c.setnc(y.r8Lo()); \
318
+	else \
319
+		c.setc(y.r8Lo()); \
320
+	c.lea(x, ptr(y.r64(), x.r64(), kScale2Times)); \
321
+	c.seto(y.r8Lo()); \
322
+	c.lea(x, ptr(y.r64(), x.r64(), kScale2Times)); \
323
+	c.movzx(y, flags_ptr); \
324
+	c.shl(x, 4); \
325
+	c.and_(y, 0xF); \
326
+	c.or_(x, y); \
327
+	c.mov(flags_ptr, x.r8Lo()); \
328
+	c.unuse(x); \
329
+	c.unuse(y); \
330
+	JIT_COMMENT("end SET_NZCV"); \
331
+}
332
+
333
+#define SET_NZC \
334
+{ \
335
+	JIT_COMMENT("SET_NZC"); \
336
+	GpVar x = c.newGpVar(kX86VarTypeGpd); \
337
+	GpVar y = c.newGpVar(kX86VarTypeGpd); \
338
+	c.sets(x.r8Lo()); \
339
+	c.setz(y.r8Lo()); \
340
+	c.lea(x, ptr(y.r64(), x.r64(), kScale2Times)); \
341
+	if (cf_change) \
342
+	{ \
343
+		c.lea(x, ptr(rcf.r64(), x.r64(), kScale2Times)); \
344
+		c.unuse(rcf); \
345
+	} \
346
+	c.movzx(y, flags_ptr); \
347
+	c.shl(x, 6 - cf_change); \
348
+	c.and_(y, cf_change?0x1F:0x3F); \
349
+	c.or_(x, y); \
350
+	c.mov(flags_ptr, x.r8Lo()); \
351
+	JIT_COMMENT("end SET_NZC"); \
352
+}
353
+
354
+#define SET_NZC_SHIFTS_ZERO(cf) \
355
+{ \
356
+	JIT_COMMENT("SET_NZC_SHIFTS_ZERO"); \
357
+	c.and_(flags_ptr, 0x1F); \
358
+	if (cf) \
359
+	{ \
360
+		c.shl(rcf, 5); \
361
+		c.or_(rcf, 1 << 6); \
362
+		c.or_(flags_ptr, rcf.r8Lo()); \
363
+	} \
364
+	else \
365
+		c.or_(flags_ptr, 1 << 6); \
366
+	JIT_COMMENT("end SET_NZC_SHIFTS_ZERO"); \
367
+}
368
+
369
+#define SET_NZ(clear_cv) \
370
+{ \
371
+	JIT_COMMENT("SET_NZ"); \
372
+	GpVar x = c.newGpVar(kX86VarTypeGpz); \
373
+	GpVar y = c.newGpVar(kX86VarTypeGpz); \
374
+	c.sets(x.r8Lo()); \
375
+	c.setz(y.r8Lo()); \
376
+	c.lea(x, ptr(y.r64(), x.r64(), kScale2Times)); \
377
+	c.movzx(y, flags_ptr); \
378
+	c.and_(y, clear_cv?0x0F:0x3F); \
379
+	c.shl(x, 6); \
380
+	c.or_(x, y); \
381
+	c.mov(flags_ptr, x.r8Lo()); \
382
+	JIT_COMMENT("end SET_NZ"); \
383
+}
384
+
385
+#define SET_Q \
386
+{ \
387
+	JIT_COMMENT("SET_Q"); \
388
+	GpVar x = c.newGpVar(kX86VarTypeGpz); \
389
+	c.seto(x.r8Lo()); \
390
+	c.shl(x, 3); \
391
+	c.or_(flags_ptr, x.r8Lo()); \
392
+	JIT_COMMENT("end SET_Q"); \
393
+}
394
+
395
+#define S_DST_R15 \
396
+{ \
397
+	JIT_COMMENT("S_DST_R15"); \
398
+	GpVar SPSR = c.newGpVar(kX86VarTypeGpd); \
399
+	GpVar tmp = c.newGpVar(kX86VarTypeGpd); \
400
+	c.mov(SPSR, cpu_ptr(SPSR.val)); \
401
+	c.mov(tmp, SPSR); \
402
+	c.and_(tmp, 0x1F); \
403
+	X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(armcpu_switchMode)); \
404
+	ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<void, void *, uint8_t>()); \
405
+	ctx->setArgument(0, bb_cpu); \
406
+	ctx->setArgument(1, tmp); \
407
+	c.mov(cpu_ptr(CPSR.val), SPSR); \
408
+	c.and_(SPSR, 1 << 5); \
409
+	c.shr(SPSR, 5); \
410
+	c.lea(tmp, ptr_abs(reinterpret_cast<void *>(0xFFFFFFFC), SPSR.r64(), kScale2Times)); \
411
+	c.and_(tmp, reg_ptr(15)); \
412
+	c.mov(cpu_ptr(next_instruction), tmp); \
413
+	c.unuse(tmp); \
414
+	JIT_COMMENT("end S_DST_R15"); \
415
+}
416
+
417
+// ============================================================================================= IMM
418
+#define LSL_IMM \
419
+	JIT_COMMENT("LSL_IMM"); \
420
+	bool rhs_is_imm = false; \
421
+	uint32_t imm = (i >> 7) & 0x1F; \
422
+	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
423
+	c.mov(rhs, reg_pos_ptr(0)); \
424
+	if (imm) \
425
+		c.shl(rhs, imm); \
426
+	uint32_t rhs_first = cpu->R[REG_POS(i, 0)] << imm;
427
+
428
+#define S_LSL_IMM \
429
+	JIT_COMMENT("S_LSL_IMM"); \
430
+	bool rhs_is_imm = false; \
431
+	uint8_t cf_change = 0; \
432
+	GpVar rcf; \
433
+	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
434
+	uint32_t imm = (i >> 7)&0x1F; \
435
+	c.mov(rhs, reg_pos_ptr(0)); \
436
+	if (imm)  \
437
+	{ \
438
+		cf_change = 1; \
439
+		c.shl(rhs, imm); \
440
+		rcf = c.newGpVar(kX86VarTypeGpd); \
441
+		c.setc(rcf.r8Lo()); \
442
+	}
443
+
444
+#define LSR_IMM \
445
+	JIT_COMMENT("LSR_IMM"); \
446
+	bool rhs_is_imm = false; \
447
+	uint32_t imm = (i >> 7) & 0x1F; \
448
+	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
449
+	if (imm) \
450
+	{ \
451
+		c.mov(rhs, reg_pos_ptr(0)); \
452
+		c.shr(rhs, imm); \
453
+	} \
454
+	else \
455
+		c.mov(rhs, 0); \
456
+	uint32_t rhs_first = imm ? cpu->R[REG_POS(i, 0)] >> imm : 0;
457
+
458
+#define S_LSR_IMM \
459
+	JIT_COMMENT("S_LSR_IMM"); \
460
+	bool rhs_is_imm = false; \
461
+	uint8_t cf_change = 1; \
462
+	GpVar rcf = c.newGpVar(kX86VarTypeGpd); \
463
+	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
464
+	uint32_t imm = (i >> 7) & 0x1F; \
465
+	c.mov(rhs, reg_pos_ptr(0)); \
466
+	if (!imm) \
467
+	{ \
468
+		c.test(rhs, 1 << 31); \
469
+		c.setnz(rcf.r8Lo()); \
470
+		c.xor_(rhs, rhs); \
471
+	} \
472
+	else \
473
+	{ \
474
+		c.shr(rhs, imm); \
475
+		c.setc(rcf.r8Lo()); \
476
+	}
477
+
478
+#define ASR_IMM \
479
+	JIT_COMMENT("ASR_IMM"); \
480
+	bool rhs_is_imm = false; \
481
+	uint32_t imm = (i >> 7) & 0x1F; \
482
+	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
483
+	c.mov(rhs, reg_pos_ptr(0)); \
484
+	if (!imm) \
485
+		imm = 31; \
486
+	c.sar(rhs, imm); \
487
+	uint32_t rhs_first = static_cast<int32_t>(cpu->R[REG_POS(i, 0)]) >> imm;
488
+
489
+#define S_ASR_IMM \
490
+	JIT_COMMENT("S_ASR_IMM"); \
491
+	bool rhs_is_imm = false; \
492
+	uint8_t cf_change = 1; \
493
+	GpVar rcf = c.newGpVar(kX86VarTypeGpd); \
494
+	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
495
+	uint32_t imm = (i >> 7) & 0x1F; \
496
+	c.mov(rhs, reg_pos_ptr(0)); \
497
+	if (!imm) \
498
+		imm = 31; \
499
+	c.sar(rhs, imm); \
500
+	imm == 31 ? c.sets(rcf.r8Lo()) : c.setc(rcf.r8Lo());
501
+
502
+#define ROR_IMM \
503
+	JIT_COMMENT("ROR_IMM"); \
504
+	bool rhs_is_imm = false; \
505
+	uint32_t imm = (i >> 7) & 0x1F; \
506
+	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
507
+	c.mov(rhs, reg_pos_ptr(0)); \
508
+	if (!imm) \
509
+	{ \
510
+		c.bt(flags_ptr, 5); \
511
+		c.rcr(rhs, 1); \
512
+	} \
513
+	else \
514
+		c.ror(rhs, imm); \
515
+	uint32_t rhs_first = imm ? ROR(cpu->R[REG_POS(i, 0)], imm) : (static_cast<uint32_t>(cpu->CPSR.bits.C) << 31) | (cpu->R[REG_POS(i, 0)] >> 1);
516
+
517
+#define S_ROR_IMM \
518
+	JIT_COMMENT("S_ROR_IMM"); \
519
+	bool rhs_is_imm = false; \
520
+	uint8_t cf_change = 1; \
521
+	GpVar rcf = c.newGpVar(kX86VarTypeGpd); \
522
+	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
523
+	uint32_t imm = (i >> 7) & 0x1F; \
524
+	c.mov(rhs, reg_pos_ptr(0)); \
525
+	if (!imm) \
526
+	{ \
527
+		c.bt(flags_ptr, 5); \
528
+		c.rcr(rhs, 1); \
529
+	} \
530
+	else \
531
+		c.ror(rhs, imm); \
532
+	c.setc(rcf.r8Lo());
533
+
534
+#define REG_OFF \
535
+	JIT_COMMENT("REG_OFF"); \
536
+	bool rhs_is_imm = false; \
537
+	Mem rhs = reg_pos_ptr(0); \
538
+	uint32_t rhs_first = cpu->R[REG_POS(i, 0)];
539
+
540
+#define IMM_VAL \
541
+	JIT_COMMENT("IMM_VAL"); \
542
+	bool rhs_is_imm = true; \
543
+	uint32_t rhs = ROR(i & 0xFF, (i >> 7) & 0x1E); \
544
+	uint32_t rhs_first = rhs;
545
+
546
+#define S_IMM_VAL \
547
+	JIT_COMMENT("S_IMM_VAL"); \
548
+	bool rhs_is_imm = true; \
549
+	uint8_t cf_change = 0; \
550
+	GpVar rcf; \
551
+	uint32_t rhs = ROR(i & 0xFF, (i >> 7) & 0x1E); \
552
+	if ((i >> 8) & 0xF) \
553
+	{ \
554
+		cf_change = 1; \
555
+		rcf = c.newGpVar(kX86VarTypeGpd); \
556
+		c.mov(rcf, BIT31(rhs)); \
557
+	} \
558
+	uint32_t rhs_first = rhs;
559
+
560
+#define IMM_OFF \
561
+	JIT_COMMENT("IMM_OFF"); \
562
+	bool rhs_is_imm = true; \
563
+	uint32_t rhs = ((i >> 4) & 0xF0) + (i & 0xF); \
564
+	uint32_t rhs_first = rhs;
565
+
566
+#define IMM_OFF_12 \
567
+	JIT_COMMENT("IMM_OFF_12"); \
568
+	bool rhs_is_imm = true; \
569
+	uint32_t rhs = i & 0xFFF; \
570
+	uint32_t rhs_first = rhs;
571
+
572
+// ============================================================================================= REG
573
+#define LSX_REG(name, x86inst, sign) \
574
+	JIT_COMMENT(#name); \
575
+	bool rhs_is_imm = false; \
576
+	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
577
+	GpVar imm = c.newGpVar(kX86VarTypeGpz); \
578
+	GpVar tmp = c.newGpVar(kX86VarTypeGpz); \
579
+	if (sign) \
580
+		c.mov(tmp, 31); \
581
+	else \
582
+		c.mov(tmp, 0); \
583
+	c.movzx(imm, reg_pos_ptrB(8)); \
584
+	c.mov(rhs, reg_pos_ptr(0)); \
585
+	c.cmp(imm, 31); \
586
+	if (sign) \
587
+		c.cmovg(imm, tmp); \
588
+	else \
589
+		c.cmovg(rhs, tmp); \
590
+	c.x86inst(rhs, imm); \
591
+	c.unuse(tmp);
592
+
593
+#define S_LSX_REG(name, x86inst, sign) \
594
+	JIT_COMMENT(#name); \
595
+	bool rhs_is_imm = false; \
596
+	uint8_t cf_change = 1; \
597
+	GpVar rcf = c.newGpVar(kX86VarTypeGpd); \
598
+	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
599
+	GpVar imm = c.newGpVar(kX86VarTypeGpz); \
600
+	Label __zero = c.newLabel(); \
601
+	Label __lt32 = c.newLabel(); \
602
+	Label __done = c.newLabel(); \
603
+	c.mov(imm, reg_pos_ptr(8)); \
604
+	c.mov(rhs, reg_pos_ptr(0)); \
605
+	c.and_(imm, 0xFF); \
606
+	c.jz(__zero); \
607
+	c.cmp(imm, 32); \
608
+	c.jl(__lt32); \
609
+	if (!sign) \
610
+	{ \
611
+		Label __eq32 = c.newLabel(); \
612
+		c.je(__eq32); \
613
+		/* imm > 32 */ \
614
+		c.mov(rhs, 0); \
615
+		c.mov(rcf, 0); \
616
+		c.jmp(__done); \
617
+		/* imm == 32 */ \
618
+		c.bind(__eq32); \
619
+	} \
620
+	c.x86inst(rhs, 31); \
621
+	c.x86inst(rhs, 1); \
622
+	c.setc(rcf.r8Lo()); \
623
+	c.jmp(__done); \
624
+	/* imm == 0 */ \
625
+	c.bind(__zero); \
626
+	c.test(flags_ptr, 1 << 5); \
627
+	c.setnz(rcf.r8Lo()); \
628
+	c.jmp(__done); \
629
+	/* imm < 32 */ \
630
+	c.bind(__lt32); \
631
+	c.x86inst(rhs, imm); \
632
+	c.setc(rcf.r8Lo()); \
633
+	/* done */ \
634
+	c.bind(__done);
635
+
636
+#define LSL_REG LSX_REG(LSL_REG, shl, 0)
637
+#define LSR_REG LSX_REG(LSR_REG, shr, 0)
638
+#define ASR_REG LSX_REG(ASR_REG, sar, 1)
639
+#define S_LSL_REG S_LSX_REG(S_LSL_REG, shl, 0)
640
+#define S_LSR_REG S_LSX_REG(S_LSR_REG, shr, 0)
641
+#define S_ASR_REG S_LSX_REG(S_ASR_REG, sar, 1)
642
+
643
+#define ROR_REG \
644
+	JIT_COMMENT("ROR_REG"); \
645
+	bool rhs_is_imm = false; \
646
+	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
647
+	GpVar imm = c.newGpVar(kX86VarTypeGpz); \
648
+	c.mov(rhs, reg_pos_ptr(0)); \
649
+	c.mov(imm, reg_pos_ptrB(8)); \
650
+	c.ror(rhs, imm.r8Lo());
651
+
652
+#define S_ROR_REG \
653
+	JIT_COMMENT("S_ROR_REG"); \
654
+	bool rhs_is_imm = false; \
655
+	bool cf_change = 1; \
656
+	GpVar rcf = c.newGpVar(kX86VarTypeGpd); \
657
+	GpVar imm = c.newGpVar(kX86VarTypeGpz); \
658
+	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
659
+	Label __zero = c.newLabel(); \
660
+	Label __zero_1F = c.newLabel(); \
661
+	Label __done = c.newLabel(); \
662
+	c.mov(imm, reg_pos_ptr(8)); \
663
+	c.mov(rhs, reg_pos_ptr(0)); \
664
+	c.and_(imm, 0xFF); \
665
+	c.jz(__zero);\
666
+	c.and_(imm, 0x1F); \
667
+	c.jz(__zero_1F);\
668
+	/* imm&0x1F != 0 */ \
669
+	c.ror(rhs, imm); \
670
+	c.setc(rcf.r8Lo()); \
671
+	c.jmp(__done); \
672
+	/* imm&0x1F == 0 */ \
673
+	c.bind(__zero_1F); \
674
+	c.test(rhs, 1 << 31); \
675
+	c.setnz(rcf.r8Lo()); \
676
+	c.jmp(__done); \
677
+	/* imm == 0 */ \
678
+	c.bind(__zero); \
679
+	c.test(flags_ptr, 1 << 5); \
680
+	c.setnz(rcf.r8Lo()); \
681
+	/* done */ \
682
+	c.bind(__done);
683
+
684
+// ==================================================================== common funcs
685
+static void emit_MMU_aluMemCycles(int alu_cycles, GpVar mem_cycles, int population)
686
+{
687
+	if (PROCNUM == ARMCPU_ARM9)
688
+	{
689
+		if (population < alu_cycles)
690
+		{
691
+			GpVar x = c.newGpVar(kX86VarTypeGpd);
692
+			c.mov(x, alu_cycles);
693
+			c.cmp(mem_cycles, alu_cycles);
694
+			c.cmovl(mem_cycles, x);
695
+		}
696
+	}
697
+	else
698
+		c.add(mem_cycles, alu_cycles);
699
+}
700
+
701
+// -----------------------------------------------------------------------------
702
+//   OPs
703
+// -----------------------------------------------------------------------------
704
+#define OP_ARITHMETIC(arg, x86inst, symmetric, flags) \
705
+	arg; \
706
+	GpVar lhs = c.newGpVar(kX86VarTypeGpd); \
707
+	if (REG_POS(i, 12) == REG_POS(i, 16)) \
708
+		c.x86inst(reg_pos_ptr(12), rhs); \
709
+	else if (symmetric && !rhs_is_imm) \
710
+	{ \
711
+		c.x86inst(*reinterpret_cast<GpVar *>(&rhs), reg_pos_ptr(16)); \
712
+		c.mov(reg_pos_ptr(12), rhs); \
713
+	} \
714
+	else \
715
+	{ \
716
+		c.mov(lhs, reg_pos_ptr(16)); \
717
+		c.x86inst(lhs, rhs); \
718
+		c.mov(reg_pos_ptr(12), lhs); \
719
+	} \
720
+	if (flags) \
721
+	{ \
722
+		if (REG_POS(i, 12) == 15) \
723
+		{ \
724
+			S_DST_R15; \
725
+			bb_constant_cycles += 2; \
726
+			return 1; \
727
+		} \
728
+		SET_NZCV(!symmetric); \
729
+	} \
730
+	else \
731
+	{ \
732
+		if (REG_POS(i, 12) == 15) \
733
+		{ \
734
+			GpVar tmp = c.newGpVar(kX86VarTypeGpd); \
735
+			c.mov(tmp, reg_ptr(15)); \
736
+			c.mov(cpu_ptr(next_instruction), tmp); \
737
+			bb_constant_cycles += 2; \
738
+		} \
739
+	} \
740
+	return 1;
741
+
742
+#define OP_ARITHMETIC_R(arg, x86inst, flags) \
743
+	arg; \
744
+	GpVar lhs = c.newGpVar(kX86VarTypeGpd); \
745
+	c.mov(lhs, rhs); \
746
+	c.x86inst(lhs, reg_pos_ptr(16)); \
747
+	c.mov(reg_pos_ptr(12), lhs); \
748
+	if (flags) \
749
+	{ \
750
+		if (REG_POS(i, 12) == 15) \
751
+		{ \
752
+			S_DST_R15; \
753
+			bb_constant_cycles += 2; \
754
+			return 1; \
755
+		} \
756
+		SET_NZCV(1); \
757
+	} \
758
+	else \
759
+	{ \
760
+		if (REG_POS(i, 12) == 15) \
761
+		{ \
762
+			GpVar tmp = c.newGpVar(kX86VarTypeGpd); \
763
+			c.mov(cpu_ptr(next_instruction), lhs); \
764
+			bb_constant_cycles += 2; \
765
+		} \
766
+	} \
767
+	return 1;
768
+
769
+#define OP_ARITHMETIC_S(arg, x86inst, symmetric) \
770
+	arg; \
771
+	if (REG_POS(i, 12) == REG_POS(i, 16)) \
772
+		c.x86inst(reg_pos_ptr(12), rhs); \
773
+	else if (symmetric && !rhs_is_imm) \
774
+	{ \
775
+		c.x86inst(*reinterpret_cast<GpVar *>(&rhs), reg_pos_ptr(16)); \
776
+		c.mov(reg_pos_ptr(12), rhs); \
777
+	} \
778
+	else \
779
+	{ \
780
+		GpVar lhs = c.newGpVar(kX86VarTypeGpd); \
781
+		c.mov(lhs, reg_pos_ptr(16)); \
782
+		c.x86inst(lhs, rhs); \
783
+		c.mov(reg_pos_ptr(12), lhs); \
784
+	} \
785
+	if (REG_POS(i, 12) == 15) \
786
+	{ \
787
+		S_DST_R15; \
788
+		bb_constant_cycles += 2; \
789
+		return 1; \
790
+	} \
791
+	SET_NZC; \
792
+	return 1;
793
+
794
+#define GET_CARRY(invert) \
795
+{ \
796
+	c.bt(flags_ptr, 5); \
797
+	if (invert) \
798
+		c.cmc(); \
799
+}
800
+
801
+static int OP_AND_LSL_IMM(uint32_t i) { OP_ARITHMETIC(LSL_IMM, and_, 1, 0); }
802
+static int OP_AND_LSL_REG(uint32_t i) { OP_ARITHMETIC(LSL_REG, and_, 1, 0); }
803
+static int OP_AND_LSR_IMM(uint32_t i) { OP_ARITHMETIC(LSR_IMM, and_, 1, 0); }
804
+static int OP_AND_LSR_REG(uint32_t i) { OP_ARITHMETIC(LSR_REG, and_, 1, 0); }
805
+static int OP_AND_ASR_IMM(uint32_t i) { OP_ARITHMETIC(ASR_IMM, and_, 1, 0); }
806
+static int OP_AND_ASR_REG(uint32_t i) { OP_ARITHMETIC(ASR_REG, and_, 1, 0); }
807
+static int OP_AND_ROR_IMM(uint32_t i) { OP_ARITHMETIC(ROR_IMM, and_, 1, 0); }
808
+static int OP_AND_ROR_REG(uint32_t i) { OP_ARITHMETIC(ROR_REG, and_, 1, 0); }
809
+static int OP_AND_IMM_VAL(uint32_t i) { OP_ARITHMETIC(IMM_VAL, and_, 1, 0); }
810
+
811
+static int OP_EOR_LSL_IMM(uint32_t i) { OP_ARITHMETIC(LSL_IMM, xor_, 1, 0); }
812
+static int OP_EOR_LSL_REG(uint32_t i) { OP_ARITHMETIC(LSL_REG, xor_, 1, 0); }
813
+static int OP_EOR_LSR_IMM(uint32_t i) { OP_ARITHMETIC(LSR_IMM, xor_, 1, 0); }
814
+static int OP_EOR_LSR_REG(uint32_t i) { OP_ARITHMETIC(LSR_REG, xor_, 1, 0); }
815
+static int OP_EOR_ASR_IMM(uint32_t i) { OP_ARITHMETIC(ASR_IMM, xor_, 1, 0); }
816
+static int OP_EOR_ASR_REG(uint32_t i) { OP_ARITHMETIC(ASR_REG, xor_, 1, 0); }
817
+static int OP_EOR_ROR_IMM(uint32_t i) { OP_ARITHMETIC(ROR_IMM, xor_, 1, 0); }
818
+static int OP_EOR_ROR_REG(uint32_t i) { OP_ARITHMETIC(ROR_REG, xor_, 1, 0); }
819
+static int OP_EOR_IMM_VAL(uint32_t i) { OP_ARITHMETIC(IMM_VAL, xor_, 1, 0); }
820
+
821
+static int OP_ORR_LSL_IMM(uint32_t i) { OP_ARITHMETIC(LSL_IMM, or_, 1, 0); }
822
+static int OP_ORR_LSL_REG(uint32_t i) { OP_ARITHMETIC(LSL_REG, or_, 1, 0); }
823
+static int OP_ORR_LSR_IMM(uint32_t i) { OP_ARITHMETIC(LSR_IMM, or_, 1, 0); }
824
+static int OP_ORR_LSR_REG(uint32_t i) { OP_ARITHMETIC(LSR_REG, or_, 1, 0); }
825
+static int OP_ORR_ASR_IMM(uint32_t i) { OP_ARITHMETIC(ASR_IMM, or_, 1, 0); }
826
+static int OP_ORR_ASR_REG(uint32_t i) { OP_ARITHMETIC(ASR_REG, or_, 1, 0); }
827
+static int OP_ORR_ROR_IMM(uint32_t i) { OP_ARITHMETIC(ROR_IMM, or_, 1, 0); }
828
+static int OP_ORR_ROR_REG(uint32_t i) { OP_ARITHMETIC(ROR_REG, or_, 1, 0); }
829
+static int OP_ORR_IMM_VAL(uint32_t i) { OP_ARITHMETIC(IMM_VAL, or_, 1, 0); }
830
+
831
+static int OP_ADD_LSL_IMM(uint32_t i) { OP_ARITHMETIC(LSL_IMM, add, 1, 0); }
832
+static int OP_ADD_LSL_REG(uint32_t i) { OP_ARITHMETIC(LSL_REG, add, 1, 0); }
833
+static int OP_ADD_LSR_IMM(uint32_t i) { OP_ARITHMETIC(LSR_IMM, add, 1, 0); }
834
+static int OP_ADD_LSR_REG(uint32_t i) { OP_ARITHMETIC(LSR_REG, add, 1, 0); }
835
+static int OP_ADD_ASR_IMM(uint32_t i) { OP_ARITHMETIC(ASR_IMM, add, 1, 0); }
836
+static int OP_ADD_ASR_REG(uint32_t i) { OP_ARITHMETIC(ASR_REG, add, 1, 0); }
837
+static int OP_ADD_ROR_IMM(uint32_t i) { OP_ARITHMETIC(ROR_IMM, add, 1, 0); }
838
+static int OP_ADD_ROR_REG(uint32_t i) { OP_ARITHMETIC(ROR_REG, add, 1, 0); }
839
+static int OP_ADD_IMM_VAL(uint32_t i) { OP_ARITHMETIC(IMM_VAL, add, 1, 0); }
840
+
841
+static int OP_SUB_LSL_IMM(uint32_t i) { OP_ARITHMETIC(LSL_IMM, sub, 0, 0); }
842
+static int OP_SUB_LSL_REG(uint32_t i) { OP_ARITHMETIC(LSL_REG, sub, 0, 0); }
843
+static int OP_SUB_LSR_IMM(uint32_t i) { OP_ARITHMETIC(LSR_IMM, sub, 0, 0); }
844
+static int OP_SUB_LSR_REG(uint32_t i) { OP_ARITHMETIC(LSR_REG, sub, 0, 0); }
845
+static int OP_SUB_ASR_IMM(uint32_t i) { OP_ARITHMETIC(ASR_IMM, sub, 0, 0); }
846
+static int OP_SUB_ASR_REG(uint32_t i) { OP_ARITHMETIC(ASR_REG, sub, 0, 0); }
847
+static int OP_SUB_ROR_IMM(uint32_t i) { OP_ARITHMETIC(ROR_IMM, sub, 0, 0); }
848
+static int OP_SUB_ROR_REG(uint32_t i) { OP_ARITHMETIC(ROR_REG, sub, 0, 0); }
849
+static int OP_SUB_IMM_VAL(uint32_t i) { OP_ARITHMETIC(IMM_VAL, sub, 0, 0); }
850
+
851
+static int OP_RSB_LSL_IMM(uint32_t i) { OP_ARITHMETIC_R(LSL_IMM, sub, 0); }
852
+static int OP_RSB_LSL_REG(uint32_t i) { OP_ARITHMETIC_R(LSL_REG, sub, 0); }
853
+static int OP_RSB_LSR_IMM(uint32_t i) { OP_ARITHMETIC_R(LSR_IMM, sub, 0); }
854
+static int OP_RSB_LSR_REG(uint32_t i) { OP_ARITHMETIC_R(LSR_REG, sub, 0); }
855
+static int OP_RSB_ASR_IMM(uint32_t i) { OP_ARITHMETIC_R(ASR_IMM, sub, 0); }
856
+static int OP_RSB_ASR_REG(uint32_t i) { OP_ARITHMETIC_R(ASR_REG, sub, 0); }
857
+static int OP_RSB_ROR_IMM(uint32_t i) { OP_ARITHMETIC_R(ROR_IMM, sub, 0); }
858
+static int OP_RSB_ROR_REG(uint32_t i) { OP_ARITHMETIC_R(ROR_REG, sub, 0); }
859
+static int OP_RSB_IMM_VAL(uint32_t i) { OP_ARITHMETIC_R(IMM_VAL, sub, 0); }
860
+
861
+// ================================ S instructions
862
+static int OP_AND_S_LSL_IMM(uint32_t i) { OP_ARITHMETIC_S(S_LSL_IMM, and_, 1); }
863
+static int OP_AND_S_LSL_REG(uint32_t i) { OP_ARITHMETIC_S(S_LSL_REG, and_, 1); }
864
+static int OP_AND_S_LSR_IMM(uint32_t i) { OP_ARITHMETIC_S(S_LSR_IMM, and_, 1); }
865
+static int OP_AND_S_LSR_REG(uint32_t i) { OP_ARITHMETIC_S(S_LSR_REG, and_, 1); }
866
+static int OP_AND_S_ASR_IMM(uint32_t i) { OP_ARITHMETIC_S(S_ASR_IMM, and_, 1); }
867
+static int OP_AND_S_ASR_REG(uint32_t i) { OP_ARITHMETIC_S(S_ASR_REG, and_, 1); }
868
+static int OP_AND_S_ROR_IMM(uint32_t i) { OP_ARITHMETIC_S(S_ROR_IMM, and_, 1); }
869
+static int OP_AND_S_ROR_REG(uint32_t i) { OP_ARITHMETIC_S(S_ROR_REG, and_, 1); }
870
+static int OP_AND_S_IMM_VAL(uint32_t i) { OP_ARITHMETIC_S(S_IMM_VAL, and_, 1); }
871
+
872
+static int OP_EOR_S_LSL_IMM(uint32_t i) { OP_ARITHMETIC_S(S_LSL_IMM, xor_, 1); }
873
+static int OP_EOR_S_LSL_REG(uint32_t i) { OP_ARITHMETIC_S(S_LSL_REG, xor_, 1); }
874
+static int OP_EOR_S_LSR_IMM(uint32_t i) { OP_ARITHMETIC_S(S_LSR_IMM, xor_, 1); }
875
+static int OP_EOR_S_LSR_REG(uint32_t i) { OP_ARITHMETIC_S(S_LSR_REG, xor_, 1); }
876
+static int OP_EOR_S_ASR_IMM(uint32_t i) { OP_ARITHMETIC_S(S_ASR_IMM, xor_, 1); }
877
+static int OP_EOR_S_ASR_REG(uint32_t i) { OP_ARITHMETIC_S(S_ASR_REG, xor_, 1); }
878
+static int OP_EOR_S_ROR_IMM(uint32_t i) { OP_ARITHMETIC_S(S_ROR_IMM, xor_, 1); }
879
+static int OP_EOR_S_ROR_REG(uint32_t i) { OP_ARITHMETIC_S(S_ROR_REG, xor_, 1); }
880
+static int OP_EOR_S_IMM_VAL(uint32_t i) { OP_ARITHMETIC_S(S_IMM_VAL, xor_, 1); }
881
+
882
+static int OP_ORR_S_LSL_IMM(uint32_t i) { OP_ARITHMETIC_S(S_LSL_IMM, or_, 1); }
883
+static int OP_ORR_S_LSL_REG(uint32_t i) { OP_ARITHMETIC_S(S_LSL_REG, or_, 1); }
884
+static int OP_ORR_S_LSR_IMM(uint32_t i) { OP_ARITHMETIC_S(S_LSR_IMM, or_, 1); }
885
+static int OP_ORR_S_LSR_REG(uint32_t i) { OP_ARITHMETIC_S(S_LSR_REG, or_, 1); }
886
+static int OP_ORR_S_ASR_IMM(uint32_t i) { OP_ARITHMETIC_S(S_ASR_IMM, or_, 1); }
887
+static int OP_ORR_S_ASR_REG(uint32_t i) { OP_ARITHMETIC_S(S_ASR_REG, or_, 1); }
888
+static int OP_ORR_S_ROR_IMM(uint32_t i) { OP_ARITHMETIC_S(S_ROR_IMM, or_, 1); }
889
+static int OP_ORR_S_ROR_REG(uint32_t i) { OP_ARITHMETIC_S(S_ROR_REG, or_, 1); }
890
+static int OP_ORR_S_IMM_VAL(uint32_t i) { OP_ARITHMETIC_S(S_IMM_VAL, or_, 1); }
891
+
892
+static int OP_ADD_S_LSL_IMM(uint32_t i) { OP_ARITHMETIC(LSL_IMM, add, 1, 1); }
893
+static int OP_ADD_S_LSL_REG(uint32_t i) { OP_ARITHMETIC(LSL_REG, add, 1, 1); }
894
+static int OP_ADD_S_LSR_IMM(uint32_t i) { OP_ARITHMETIC(LSR_IMM, add, 1, 1); }
895
+static int OP_ADD_S_LSR_REG(uint32_t i) { OP_ARITHMETIC(LSR_REG, add, 1, 1); }
896
+static int OP_ADD_S_ASR_IMM(uint32_t i) { OP_ARITHMETIC(ASR_IMM, add, 1, 1); }
897
+static int OP_ADD_S_ASR_REG(uint32_t i) { OP_ARITHMETIC(ASR_REG, add, 1, 1); }
898
+static int OP_ADD_S_ROR_IMM(uint32_t i) { OP_ARITHMETIC(ROR_IMM, add, 1, 1); }
899
+static int OP_ADD_S_ROR_REG(uint32_t i) { OP_ARITHMETIC(ROR_REG, add, 1, 1); }
900
+static int OP_ADD_S_IMM_VAL(uint32_t i) { OP_ARITHMETIC(IMM_VAL, add, 1, 1); }
901
+
902
+static int OP_SUB_S_LSL_IMM(uint32_t i) { OP_ARITHMETIC(LSL_IMM, sub, 0, 1); }
903
+static int OP_SUB_S_LSL_REG(uint32_t i) { OP_ARITHMETIC(LSL_REG, sub, 0, 1); }
904
+static int OP_SUB_S_LSR_IMM(uint32_t i) { OP_ARITHMETIC(LSR_IMM, sub, 0, 1); }
905
+static int OP_SUB_S_LSR_REG(uint32_t i) { OP_ARITHMETIC(LSR_REG, sub, 0, 1); }
906
+static int OP_SUB_S_ASR_IMM(uint32_t i) { OP_ARITHMETIC(ASR_IMM, sub, 0, 1); }
907
+static int OP_SUB_S_ASR_REG(uint32_t i) { OP_ARITHMETIC(ASR_REG, sub, 0, 1); }
908
+static int OP_SUB_S_ROR_IMM(uint32_t i) { OP_ARITHMETIC(ROR_IMM, sub, 0, 1); }
909
+static int OP_SUB_S_ROR_REG(uint32_t i) { OP_ARITHMETIC(ROR_REG, sub, 0, 1); }
910
+static int OP_SUB_S_IMM_VAL(uint32_t i) { OP_ARITHMETIC(IMM_VAL, sub, 0, 1); }
911
+
912
+static int OP_RSB_S_LSL_IMM(uint32_t i) { OP_ARITHMETIC_R(LSL_IMM, sub, 1); }
913
+static int OP_RSB_S_LSL_REG(uint32_t i) { OP_ARITHMETIC_R(LSL_REG, sub, 1); }
914
+static int OP_RSB_S_LSR_IMM(uint32_t i) { OP_ARITHMETIC_R(LSR_IMM, sub, 1); }
915
+static int OP_RSB_S_LSR_REG(uint32_t i) { OP_ARITHMETIC_R(LSR_REG, sub, 1); }
916
+static int OP_RSB_S_ASR_IMM(uint32_t i) { OP_ARITHMETIC_R(ASR_IMM, sub, 1); }
917
+static int OP_RSB_S_ASR_REG(uint32_t i) { OP_ARITHMETIC_R(ASR_REG, sub, 1); }
918
+static int OP_RSB_S_ROR_IMM(uint32_t i) { OP_ARITHMETIC_R(ROR_IMM, sub, 1); }
919
+static int OP_RSB_S_ROR_REG(uint32_t i) { OP_ARITHMETIC_R(ROR_REG, sub, 1); }
920
+static int OP_RSB_S_IMM_VAL(uint32_t i) { OP_ARITHMETIC_R(IMM_VAL, sub, 1); }
921
+
922
+static int OP_ADC_LSL_IMM(uint32_t i) { OP_ARITHMETIC(LSL_IMM; GET_CARRY(0), adc, 1, 0); }
923
+static int OP_ADC_LSL_REG(uint32_t i) { OP_ARITHMETIC(LSL_REG; GET_CARRY(0), adc, 1, 0); }
924
+static int OP_ADC_LSR_IMM(uint32_t i) { OP_ARITHMETIC(LSR_IMM; GET_CARRY(0), adc, 1, 0); }
925
+static int OP_ADC_LSR_REG(uint32_t i) { OP_ARITHMETIC(LSR_REG; GET_CARRY(0), adc, 1, 0); }
926
+static int OP_ADC_ASR_IMM(uint32_t i) { OP_ARITHMETIC(ASR_IMM; GET_CARRY(0), adc, 1, 0); }
927
+static int OP_ADC_ASR_REG(uint32_t i) { OP_ARITHMETIC(ASR_REG; GET_CARRY(0), adc, 1, 0); }
928
+static int OP_ADC_ROR_IMM(uint32_t i) { OP_ARITHMETIC(ROR_IMM; GET_CARRY(0), adc, 1, 0); }
929
+static int OP_ADC_ROR_REG(uint32_t i) { OP_ARITHMETIC(ROR_REG; GET_CARRY(0), adc, 1, 0); }
930
+static int OP_ADC_IMM_VAL(uint32_t i) { OP_ARITHMETIC(IMM_VAL; GET_CARRY(0), adc, 1, 0); }
931
+
932
+static int OP_ADC_S_LSL_IMM(uint32_t i) { OP_ARITHMETIC(LSL_IMM; GET_CARRY(0), adc, 1, 1); }
933
+static int OP_ADC_S_LSL_REG(uint32_t i) { OP_ARITHMETIC(LSL_REG; GET_CARRY(0), adc, 1, 1); }
934
+static int OP_ADC_S_LSR_IMM(uint32_t i) { OP_ARITHMETIC(LSR_IMM; GET_CARRY(0), adc, 1, 1); }
935
+static int OP_ADC_S_LSR_REG(uint32_t i) { OP_ARITHMETIC(LSR_REG; GET_CARRY(0), adc, 1, 1); }
936
+static int OP_ADC_S_ASR_IMM(uint32_t i) { OP_ARITHMETIC(ASR_IMM; GET_CARRY(0), adc, 1, 1); }
937
+static int OP_ADC_S_ASR_REG(uint32_t i) { OP_ARITHMETIC(ASR_REG; GET_CARRY(0), adc, 1, 1); }
938
+static int OP_ADC_S_ROR_IMM(uint32_t i) { OP_ARITHMETIC(ROR_IMM; GET_CARRY(0), adc, 1, 1); }
939
+static int OP_ADC_S_ROR_REG(uint32_t i) { OP_ARITHMETIC(ROR_REG; GET_CARRY(0), adc, 1, 1); }
940
+static int OP_ADC_S_IMM_VAL(uint32_t i) { OP_ARITHMETIC(IMM_VAL; GET_CARRY(0), adc, 1, 1); }
941
+
942
+static int OP_SBC_LSL_IMM(uint32_t i) { OP_ARITHMETIC(LSL_IMM; GET_CARRY(1), sbb, 0, 0); }
943
+static int OP_SBC_LSL_REG(uint32_t i) { OP_ARITHMETIC(LSL_REG; GET_CARRY(1), sbb, 0, 0); }
944
+static int OP_SBC_LSR_IMM(uint32_t i) { OP_ARITHMETIC(LSR_IMM; GET_CARRY(1), sbb, 0, 0); }
945
+static int OP_SBC_LSR_REG(uint32_t i) { OP_ARITHMETIC(LSR_REG; GET_CARRY(1), sbb, 0, 0); }
946
+static int OP_SBC_ASR_IMM(uint32_t i) { OP_ARITHMETIC(ASR_IMM; GET_CARRY(1), sbb, 0, 0); }
947
+static int OP_SBC_ASR_REG(uint32_t i) { OP_ARITHMETIC(ASR_REG; GET_CARRY(1), sbb, 0, 0); }
948
+static int OP_SBC_ROR_IMM(uint32_t i) { OP_ARITHMETIC(ROR_IMM; GET_CARRY(1), sbb, 0, 0); }
949
+static int OP_SBC_ROR_REG(uint32_t i) { OP_ARITHMETIC(ROR_REG; GET_CARRY(1), sbb, 0, 0); }
950
+static int OP_SBC_IMM_VAL(uint32_t i) { OP_ARITHMETIC(IMM_VAL; GET_CARRY(1), sbb, 0, 0); }
951
+
952
+static int OP_SBC_S_LSL_IMM(uint32_t i) { OP_ARITHMETIC(LSL_IMM; GET_CARRY(1), sbb, 0, 1); }
953
+static int OP_SBC_S_LSL_REG(uint32_t i) { OP_ARITHMETIC(LSL_REG; GET_CARRY(1), sbb, 0, 1); }
954
+static int OP_SBC_S_LSR_IMM(uint32_t i) { OP_ARITHMETIC(LSR_IMM; GET_CARRY(1), sbb, 0, 1); }
955
+static int OP_SBC_S_LSR_REG(uint32_t i) { OP_ARITHMETIC(LSR_REG; GET_CARRY(1), sbb, 0, 1); }
956
+static int OP_SBC_S_ASR_IMM(uint32_t i) { OP_ARITHMETIC(ASR_IMM; GET_CARRY(1), sbb, 0, 1); }
957
+static int OP_SBC_S_ASR_REG(uint32_t i) { OP_ARITHMETIC(ASR_REG; GET_CARRY(1), sbb, 0, 1); }
958
+static int OP_SBC_S_ROR_IMM(uint32_t i) { OP_ARITHMETIC(ROR_IMM; GET_CARRY(1), sbb, 0, 1); }
959
+static int OP_SBC_S_ROR_REG(uint32_t i) { OP_ARITHMETIC(ROR_REG; GET_CARRY(1), sbb, 0, 1); }
960
+static int OP_SBC_S_IMM_VAL(uint32_t i) { OP_ARITHMETIC(IMM_VAL; GET_CARRY(1), sbb, 0, 1); }
961
+
962
+static int OP_RSC_LSL_IMM(uint32_t i) { OP_ARITHMETIC_R(LSL_IMM; GET_CARRY(1), sbb, 0); }
963
+static int OP_RSC_LSL_REG(uint32_t i) { OP_ARITHMETIC_R(LSL_REG; GET_CARRY(1), sbb, 0); }
964
+static int OP_RSC_LSR_IMM(uint32_t i) { OP_ARITHMETIC_R(LSR_IMM; GET_CARRY(1), sbb, 0); }
965
+static int OP_RSC_LSR_REG(uint32_t i) { OP_ARITHMETIC_R(LSR_REG; GET_CARRY(1), sbb, 0); }
966
+static int OP_RSC_ASR_IMM(uint32_t i) { OP_ARITHMETIC_R(ASR_IMM; GET_CARRY(1), sbb, 0); }
967
+static int OP_RSC_ASR_REG(uint32_t i) { OP_ARITHMETIC_R(ASR_REG; GET_CARRY(1), sbb, 0); }
968
+static int OP_RSC_ROR_IMM(uint32_t i) { OP_ARITHMETIC_R(ROR_IMM; GET_CARRY(1), sbb, 0); }
969
+static int OP_RSC_ROR_REG(uint32_t i) { OP_ARITHMETIC_R(ROR_REG; GET_CARRY(1), sbb, 0); }
970
+static int OP_RSC_IMM_VAL(uint32_t i) { OP_ARITHMETIC_R(IMM_VAL; GET_CARRY(1), sbb, 0); }
971
+
972
+static int OP_RSC_S_LSL_IMM(uint32_t i) { OP_ARITHMETIC_R(LSL_IMM; GET_CARRY(1), sbb, 1); }
973
+static int OP_RSC_S_LSL_REG(uint32_t i) { OP_ARITHMETIC_R(LSL_REG; GET_CARRY(1), sbb, 1); }
974
+static int OP_RSC_S_LSR_IMM(uint32_t i) { OP_ARITHMETIC_R(LSR_IMM; GET_CARRY(1), sbb, 1); }
975
+static int OP_RSC_S_LSR_REG(uint32_t i) { OP_ARITHMETIC_R(LSR_REG; GET_CARRY(1), sbb, 1); }
976
+static int OP_RSC_S_ASR_IMM(uint32_t i) { OP_ARITHMETIC_R(ASR_IMM; GET_CARRY(1), sbb, 1); }
977
+static int OP_RSC_S_ASR_REG(uint32_t i) { OP_ARITHMETIC_R(ASR_REG; GET_CARRY(1), sbb, 1); }
978
+static int OP_RSC_S_ROR_IMM(uint32_t i) { OP_ARITHMETIC_R(ROR_IMM; GET_CARRY(1), sbb, 1); }
979
+static int OP_RSC_S_ROR_REG(uint32_t i) { OP_ARITHMETIC_R(ROR_REG; GET_CARRY(1), sbb, 1); }
980
+static int OP_RSC_S_IMM_VAL(uint32_t i) { OP_ARITHMETIC_R(IMM_VAL; GET_CARRY(1), sbb, 1); }
981
+
982
+static int OP_BIC_LSL_IMM(uint32_t i) { OP_ARITHMETIC(LSL_IMM; c.not_(rhs), and_, 1, 0); }
983
+static int OP_BIC_LSL_REG(uint32_t i) { OP_ARITHMETIC(LSL_REG; c.not_(rhs), and_, 1, 0); }
984
+static int OP_BIC_LSR_IMM(uint32_t i) { OP_ARITHMETIC(LSR_IMM; c.not_(rhs), and_, 1, 0); }
985
+static int OP_BIC_LSR_REG(uint32_t i) { OP_ARITHMETIC(LSR_REG; c.not_(rhs), and_, 1, 0); }
986
+static int OP_BIC_ASR_IMM(uint32_t i) { OP_ARITHMETIC(ASR_IMM; c.not_(rhs), and_, 1, 0); }
987
+static int OP_BIC_ASR_REG(uint32_t i) { OP_ARITHMETIC(ASR_REG; c.not_(rhs), and_, 1, 0); }
988
+static int OP_BIC_ROR_IMM(uint32_t i) { OP_ARITHMETIC(ROR_IMM; c.not_(rhs), and_, 1, 0); }
989
+static int OP_BIC_ROR_REG(uint32_t i) { OP_ARITHMETIC(ROR_REG; c.not_(rhs), and_, 1, 0); }
990
+static int OP_BIC_IMM_VAL(uint32_t i) { OP_ARITHMETIC(IMM_VAL; rhs = ~rhs,  and_, 1, 0); }
991
+
992
+static int OP_BIC_S_LSL_IMM(uint32_t i) { OP_ARITHMETIC_S(S_LSL_IMM; c.not_(rhs), and_, 1); }
993
+static int OP_BIC_S_LSL_REG(uint32_t i) { OP_ARITHMETIC_S(S_LSL_REG; c.not_(rhs), and_, 1); }
994
+static int OP_BIC_S_LSR_IMM(uint32_t i) { OP_ARITHMETIC_S(S_LSR_IMM; c.not_(rhs), and_, 1); }
995
+static int OP_BIC_S_LSR_REG(uint32_t i) { OP_ARITHMETIC_S(S_LSR_REG; c.not_(rhs), and_, 1); }
996
+static int OP_BIC_S_ASR_IMM(uint32_t i) { OP_ARITHMETIC_S(S_ASR_IMM; c.not_(rhs), and_, 1); }
997
+static int OP_BIC_S_ASR_REG(uint32_t i) { OP_ARITHMETIC_S(S_ASR_REG; c.not_(rhs), and_, 1); }
998
+static int OP_BIC_S_ROR_IMM(uint32_t i) { OP_ARITHMETIC_S(S_ROR_IMM; c.not_(rhs), and_, 1); }
999
+static int OP_BIC_S_ROR_REG(uint32_t i) { OP_ARITHMETIC_S(S_ROR_REG; c.not_(rhs), and_, 1); }
1000
+static int OP_BIC_S_IMM_VAL(uint32_t i) { OP_ARITHMETIC_S(S_IMM_VAL; rhs = ~rhs,  and_, 1); }
1001
+
1002
+// -----------------------------------------------------------------------------
1003
+//   TST
1004
+// -----------------------------------------------------------------------------
1005
+#define OP_TST_(arg) \
1006
+	arg; \
1007
+	c.test(reg_pos_ptr(16), rhs); \
1008
+	SET_NZC; \
1009
+	return 1;
1010
+
1011
+static int OP_TST_LSL_IMM(uint32_t i) { OP_TST_(S_LSL_IMM); }
1012
+static int OP_TST_LSL_REG(uint32_t i) { OP_TST_(S_LSL_REG); }
1013
+static int OP_TST_LSR_IMM(uint32_t i) { OP_TST_(S_LSR_IMM); }
1014
+static int OP_TST_LSR_REG(uint32_t i) { OP_TST_(S_LSR_REG); }
1015
+static int OP_TST_ASR_IMM(uint32_t i) { OP_TST_(S_ASR_IMM); }
1016
+static int OP_TST_ASR_REG(uint32_t i) { OP_TST_(S_ASR_REG); }
1017
+static int OP_TST_ROR_IMM(uint32_t i) { OP_TST_(S_ROR_IMM); }
1018
+static int OP_TST_ROR_REG(uint32_t i) { OP_TST_(S_ROR_REG); }
1019
+static int OP_TST_IMM_VAL(uint32_t i) { OP_TST_(S_IMM_VAL); }
1020
+
1021
+// -----------------------------------------------------------------------------
1022
+//   TEQ
1023
+// -----------------------------------------------------------------------------
1024
+#define OP_TEQ_(arg) \
1025
+	arg; \
1026
+	if (!rhs_is_imm) \
1027
+		c.xor_(*reinterpret_cast<GpVar *>(&rhs), reg_pos_ptr(16)); \
1028
+	else \
1029
+	{ \
1030
+		GpVar x = c.newGpVar(kX86VarTypeGpd); \
1031
+		c.mov(x, rhs); \
1032
+		c.xor_(x, reg_pos_ptr(16)); \
1033
+	} \
1034
+	SET_NZC; \
1035
+	return 1;
1036
+
1037
+static int OP_TEQ_LSL_IMM(uint32_t i) { OP_TEQ_(S_LSL_IMM); }
1038
+static int OP_TEQ_LSL_REG(uint32_t i) { OP_TEQ_(S_LSL_REG); }
1039
+static int OP_TEQ_LSR_IMM(uint32_t i) { OP_TEQ_(S_LSR_IMM); }
1040
+static int OP_TEQ_LSR_REG(uint32_t i) { OP_TEQ_(S_LSR_REG); }
1041
+static int OP_TEQ_ASR_IMM(uint32_t i) { OP_TEQ_(S_ASR_IMM); }
1042
+static int OP_TEQ_ASR_REG(uint32_t i) { OP_TEQ_(S_ASR_REG); }
1043
+static int OP_TEQ_ROR_IMM(uint32_t i) { OP_TEQ_(S_ROR_IMM); }
1044
+static int OP_TEQ_ROR_REG(uint32_t i) { OP_TEQ_(S_ROR_REG); }
1045
+static int OP_TEQ_IMM_VAL(uint32_t i) { OP_TEQ_(S_IMM_VAL); }
1046
+
1047
+// -----------------------------------------------------------------------------
1048
+//   CMP
1049
+// -----------------------------------------------------------------------------
1050
+#define OP_CMP(arg) \
1051
+	arg; \
1052
+	c.cmp(reg_pos_ptr(16), rhs); \
1053
+	SET_NZCV(1); \
1054
+	return 1;
1055
+
1056
+static int OP_CMP_LSL_IMM(uint32_t i) { OP_CMP(LSL_IMM); }
1057
+static int OP_CMP_LSL_REG(uint32_t i) { OP_CMP(LSL_REG); }
1058
+static int OP_CMP_LSR_IMM(uint32_t i) { OP_CMP(LSR_IMM); }
1059
+static int OP_CMP_LSR_REG(uint32_t i) { OP_CMP(LSR_REG); }
1060
+static int OP_CMP_ASR_IMM(uint32_t i) { OP_CMP(ASR_IMM); }
1061
+static int OP_CMP_ASR_REG(uint32_t i) { OP_CMP(ASR_REG); }
1062
+static int OP_CMP_ROR_IMM(uint32_t i) { OP_CMP(ROR_IMM); }
1063
+static int OP_CMP_ROR_REG(uint32_t i) { OP_CMP(ROR_REG); }
1064
+static int OP_CMP_IMM_VAL(uint32_t i) { OP_CMP(IMM_VAL); }
1065
+
1066
+#undef OP_CMP
1067
+
1068
+// -----------------------------------------------------------------------------
1069
+//   CMN
1070
+// -----------------------------------------------------------------------------
1071
+#define OP_CMN(arg) \
1072
+	arg; \
1073
+	uint32_t rhs_imm = *reinterpret_cast<uint32_t *>(&rhs); \
1074
+	int sign = rhs_is_imm && (rhs_imm != -rhs_imm); \
1075
+	if (sign) \
1076
+		c.cmp(reg_pos_ptr(16), -rhs_imm); \
1077
+	else \
1078
+	{ \
1079
+		GpVar lhs = c.newGpVar(kX86VarTypeGpd); \
1080
+		c.mov(lhs, reg_pos_ptr(16)); \
1081
+		c.add(lhs, rhs); \
1082
+	} \
1083
+	SET_NZCV(sign); \
1084
+	return 1;
1085
+
1086
+static int OP_CMN_LSL_IMM(uint32_t i) { OP_CMN(LSL_IMM); }
1087
+static int OP_CMN_LSL_REG(uint32_t i) { OP_CMN(LSL_REG); }
1088
+static int OP_CMN_LSR_IMM(uint32_t i) { OP_CMN(LSR_IMM); }
1089
+static int OP_CMN_LSR_REG(uint32_t i) { OP_CMN(LSR_REG); }
1090
+static int OP_CMN_ASR_IMM(uint32_t i) { OP_CMN(ASR_IMM); }
1091
+static int OP_CMN_ASR_REG(uint32_t i) { OP_CMN(ASR_REG); }
1092
+static int OP_CMN_ROR_IMM(uint32_t i) { OP_CMN(ROR_IMM); }
1093
+static int OP_CMN_ROR_REG(uint32_t i) { OP_CMN(ROR_REG); }
1094
+static int OP_CMN_IMM_VAL(uint32_t i) { OP_CMN(IMM_VAL); }
1095
+
1096
+#undef OP_CMN
1097
+
1098
+// -----------------------------------------------------------------------------
1099
+//   MOV
1100
+// -----------------------------------------------------------------------------
1101
+#define OP_MOV(arg) \
1102
+	arg; \
1103
+	c.mov(reg_pos_ptr(12), rhs); \
1104
+	if (REG_POS(i, 12) == 15) \
1105
+	{ \
1106
+		c.mov(cpu_ptr(next_instruction), rhs); \
1107
+		return 1; \
1108
+	} \
1109
+	return 1;
1110
+
1111
+static int OP_MOV_LSL_IMM(uint32_t i) { if (i == 0xE1A00000) { /* nop */ JIT_COMMENT("nop"); return 1; } OP_MOV(LSL_IMM); }
1112
+static int OP_MOV_LSL_REG(uint32_t i) { OP_MOV(LSL_REG; if (REG_POS(i, 0) == 15) c.add(rhs, 4);); }
1113
+static int OP_MOV_LSR_IMM(uint32_t i) { OP_MOV(LSR_IMM); }
1114
+static int OP_MOV_LSR_REG(uint32_t i) { OP_MOV(LSR_REG; if (REG_POS(i, 0) == 15) c.add(rhs, 4);); }
1115
+static int OP_MOV_ASR_IMM(uint32_t i) { OP_MOV(ASR_IMM); }
1116
+static int OP_MOV_ASR_REG(uint32_t i) { OP_MOV(ASR_REG); }
1117
+static int OP_MOV_ROR_IMM(uint32_t i) { OP_MOV(ROR_IMM); }
1118
+static int OP_MOV_ROR_REG(uint32_t i) { OP_MOV(ROR_REG); }
1119
+static int OP_MOV_IMM_VAL(uint32_t i) { OP_MOV(IMM_VAL); }
1120
+
1121
+#define OP_MOV_S(arg) \
1122
+	arg; \
1123
+	c.mov(reg_pos_ptr(12), rhs); \
1124
+	if (REG_POS(i, 12) == 15) \
1125
+	{ \
1126
+		S_DST_R15; \
1127
+		bb_constant_cycles += 2; \
1128
+		return 1; \
1129
+	} \
1130
+	if (!rhs_is_imm) \
1131
+		c.cmp(*reinterpret_cast<GpVar *>(&rhs), 0); \
1132
+	else \
1133
+		c.cmp(reg_pos_ptr(12), 0); \
1134
+	SET_NZC; \
1135
+	return 1;
1136
+
1137
+static int OP_MOV_S_LSL_IMM(uint32_t i) { OP_MOV_S(S_LSL_IMM); }
1138
+static int OP_MOV_S_LSL_REG(uint32_t i) { OP_MOV_S(S_LSL_REG; if (REG_POS(i, 0) == 15) c.add(rhs, 4);); }
1139
+static int OP_MOV_S_LSR_IMM(uint32_t i) { OP_MOV_S(S_LSR_IMM); }
1140
+static int OP_MOV_S_LSR_REG(uint32_t i) { OP_MOV_S(S_LSR_REG; if (REG_POS(i, 0) == 15) c.add(rhs, 4);); }
1141
+static int OP_MOV_S_ASR_IMM(uint32_t i) { OP_MOV_S(S_ASR_IMM); }
1142
+static int OP_MOV_S_ASR_REG(uint32_t i) { OP_MOV_S(S_ASR_REG); }
1143
+static int OP_MOV_S_ROR_IMM(uint32_t i) { OP_MOV_S(S_ROR_IMM); }
1144
+static int OP_MOV_S_ROR_REG(uint32_t i) { OP_MOV_S(S_ROR_REG); }
1145
+static int OP_MOV_S_IMM_VAL(uint32_t i) { OP_MOV_S(S_IMM_VAL); }
1146
+
1147
+// -----------------------------------------------------------------------------
1148
+//   MVN
1149
+// -----------------------------------------------------------------------------
1150
+static int OP_MVN_LSL_IMM(uint32_t i) { OP_MOV(LSL_IMM; c.not_(rhs)); }
1151
+static int OP_MVN_LSL_REG(uint32_t i) { OP_MOV(LSL_REG; c.not_(rhs)); }
1152
+static int OP_MVN_LSR_IMM(uint32_t i) { OP_MOV(LSR_IMM; c.not_(rhs)); }
1153
+static int OP_MVN_LSR_REG(uint32_t i) { OP_MOV(LSR_REG; c.not_(rhs)); }
1154
+static int OP_MVN_ASR_IMM(uint32_t i) { OP_MOV(ASR_IMM; c.not_(rhs)); }
1155
+static int OP_MVN_ASR_REG(uint32_t i) { OP_MOV(ASR_REG; c.not_(rhs)); }
1156
+static int OP_MVN_ROR_IMM(uint32_t i) { OP_MOV(ROR_IMM; c.not_(rhs)); }
1157
+static int OP_MVN_ROR_REG(uint32_t i) { OP_MOV(ROR_REG; c.not_(rhs)); }
1158
+static int OP_MVN_IMM_VAL(uint32_t i) { OP_MOV(IMM_VAL; rhs = ~rhs); }
1159
+
1160
+static int OP_MVN_S_LSL_IMM(uint32_t i) { OP_MOV_S(S_LSL_IMM; c.not_(rhs)); }
1161
+static int OP_MVN_S_LSL_REG(uint32_t i) { OP_MOV_S(S_LSL_REG; c.not_(rhs)); }
1162
+static int OP_MVN_S_LSR_IMM(uint32_t i) { OP_MOV_S(S_LSR_IMM; c.not_(rhs)); }
1163
+static int OP_MVN_S_LSR_REG(uint32_t i) { OP_MOV_S(S_LSR_REG; c.not_(rhs)); }
1164
+static int OP_MVN_S_ASR_IMM(uint32_t i) { OP_MOV_S(S_ASR_IMM; c.not_(rhs)); }
1165
+static int OP_MVN_S_ASR_REG(uint32_t i) { OP_MOV_S(S_ASR_REG; c.not_(rhs)); }
1166
+static int OP_MVN_S_ROR_IMM(uint32_t i) { OP_MOV_S(S_ROR_IMM; c.not_(rhs)); }
1167
+static int OP_MVN_S_ROR_REG(uint32_t i) { OP_MOV_S(S_ROR_REG; c.not_(rhs)); }
1168
+static int OP_MVN_S_IMM_VAL(uint32_t i) { OP_MOV_S(S_IMM_VAL; rhs = ~rhs); }
1169
+
1170
+//- ----------------------------------------------------------------------------
1171
+//   QADD / QDADD / QSUB / QDSUB
1172
+// -----------------------------------------------------------------------------
1173
+// TODO
1174
+static int OP_QADD(uint32_t i) { printf("JIT: unimplemented OP_QADD\n"); return 0; }
1175
+static int OP_QSUB(uint32_t i) { printf("JIT: unimplemented OP_QSUB\n"); return 0; }
1176
+static int OP_QDADD(uint32_t i) { printf("JIT: unimplemented OP_QDADD\n"); return 0; }
1177
+static int OP_QDSUB(uint32_t i) { printf("JIT: unimplemented OP_QDSUB\n"); return 0; }
1178
+
1179
+// -----------------------------------------------------------------------------
1180
+//   MUL
1181
+// -----------------------------------------------------------------------------
1182
+static void MUL_Mxx_END(GpVar x, bool sign, int cycles)
1183
+{
1184
+	if (sign)
1185
+	{
1186
+		GpVar y = c.newGpVar(kX86VarTypeGpd);
1187
+		c.mov(y, x);
1188
+		c.sar(x, 31);
1189
+		c.xor_(x, y);
1190
+	}
1191
+	c.or_(x, 1);
1192
+	c.bsr(bb_cycles, x);
1193
+	c.shr(bb_cycles, 3);
1194
+	c.add(bb_cycles, cycles + 1);
1195
+}
1196
+
1197
+#define OP_MUL_(op, width, sign, accum, flags) \
1198
+	GpVar lhs = c.newGpVar(kX86VarTypeGpd); \
1199
+	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
1200
+	GpVar hi; \
1201
+	if (width) \
1202
+	{ \
1203
+		hi = c.newGpVar(kX86VarTypeGpd); \
1204
+		c.xor_(hi, hi); \
1205
+	} \
1206
+	c.mov(lhs, reg_pos_ptr(0)); \
1207
+	c.mov(rhs, reg_pos_ptr(8)); \
1208
+	op; \
1209
+	if (width && accum) \
1210
+	{ \
1211
+		if (flags) \
1212
+		{ \
1213
+			c.add(lhs, reg_pos_ptr(12)); \
1214
+			c.adc(hi, reg_pos_ptr(16)); \
1215
+			c.mov(reg_pos_ptr(12), lhs); \
1216
+			c.mov(reg_pos_ptr(16), hi); \
1217
+			c.cmp(hi, lhs); \
1218
+			SET_NZ(0); \
1219
+		} \
1220
+		else \
1221
+		{ \
1222
+			c.add(reg_pos_ptr(12), lhs); \
1223
+			c.adc(reg_pos_ptr(16), hi); \
1224
+		} \
1225
+	} \
1226
+	else if (width) \
1227
+	{ \
1228
+		c.mov(reg_pos_ptr(12), lhs); \
1229
+		c.mov(reg_pos_ptr(16), hi); \
1230
+		if (flags) \
1231
+		{ \
1232
+			c.cmp(hi, lhs); \
1233
+			SET_NZ(0); \
1234
+		} \
1235
+	} \
1236
+	else \
1237
+	{ \
1238
+		if (accum) \
1239
+			c.add(lhs, reg_pos_ptr(12)); \
1240
+		c.mov(reg_pos_ptr(16), lhs); \
1241
+		if (flags) \
1242
+		{ \
1243
+			c.cmp(lhs, 0); \
1244
+			SET_NZ(0); \
1245
+		} \
1246
+	} \
1247
+	MUL_Mxx_END(rhs, sign, 1 + width + accum); \
1248
+	return 1;
1249
+
1250
+static int OP_MUL(uint32_t i) { OP_MUL_(c.imul(lhs,rhs), 0, 1, 0, 0); }
1251
+static int OP_MLA(uint32_t i) { OP_MUL_(c.imul(lhs,rhs), 0, 1, 1, 0); }
1252
+static int OP_UMULL(uint32_t i) { OP_MUL_(c.mul(hi,lhs,rhs), 1, 0, 0, 0); }
1253
+static int OP_UMLAL(uint32_t i) { OP_MUL_(c.mul(hi,lhs,rhs), 1, 0, 1, 0); }
1254
+static int OP_SMULL(uint32_t i) { OP_MUL_(c.imul(hi,lhs,rhs), 1, 1, 0, 0); }
1255
+static int OP_SMLAL(uint32_t i) { OP_MUL_(c.imul(hi,lhs,rhs), 1, 1, 1, 0); }
1256
+
1257
+static int OP_MUL_S(uint32_t i) { OP_MUL_(c.imul(lhs,rhs), 0, 1, 0, 1); }
1258
+static int OP_MLA_S(uint32_t i) { OP_MUL_(c.imul(lhs,rhs), 0, 1, 1, 1); }
1259
+static int OP_UMULL_S(uint32_t i) { OP_MUL_(c.mul(hi,lhs,rhs), 1, 0, 0, 1); }
1260
+static int OP_UMLAL_S(uint32_t i) { OP_MUL_(c.mul(hi,lhs,rhs), 1, 0, 1, 1); }
1261
+static int OP_SMULL_S(uint32_t i) { OP_MUL_(c.imul(hi,lhs,rhs), 1, 1, 0, 1); }
1262
+static int OP_SMLAL_S(uint32_t i) { OP_MUL_(c.imul(hi,lhs,rhs), 1, 1, 1, 1); }
1263
+
1264
+#define OP_MULxy_(op, x, y, width, accum, flags) \
1265
+	GpVar lhs = c.newGpVar(kX86VarTypeGpd); \
1266
+	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
1267
+	GpVar hi; \
1268
+	c.movsx(lhs, reg_pos_ptr##x(0)); \
1269
+	c.movsx(rhs, reg_pos_ptr##y(8)); \
1270
+	if (width) \
1271
+		hi = c.newGpVar(kX86VarTypeGpd); \
1272
+	op; \
1273
+	if (width && accum) \
1274
+	{ \
1275
+		if (flags) \
1276
+		{ \
1277
+			c.add(lhs, reg_pos_ptr(12)); \
1278
+			c.adc(hi, reg_pos_ptr(16)); \
1279
+			c.mov(reg_pos_ptr(12), lhs); \
1280
+			c.mov(reg_pos_ptr(16), hi); \
1281
+			SET_Q; \
1282
+		} \
1283
+		else \
1284
+		{ \
1285
+			c.add(reg_pos_ptr(12), lhs); \
1286
+			c.adc(reg_pos_ptr(16), hi); \
1287
+		} \
1288
+	} \
1289
+	else if (width) \
1290
+	{ \
1291
+		c.mov(reg_pos_ptr(12), lhs); \
1292
+		c.mov(reg_pos_ptr(16), hi); \
1293
+		if (flags) \
1294
+			SET_Q; \
1295
+	} \
1296
+	else \
1297
+	{ \
1298
+		if (accum) \
1299
+			c.add(lhs, reg_pos_ptr(12));  \
1300
+		c.mov(reg_pos_ptr(16), lhs); \
1301
+		if (flags) \
1302
+			SET_Q; \
1303
+	} \
1304
+	return 1;
1305
+
1306
+
1307
+// -----------------------------------------------------------------------------
1308
+//   SMUL
1309
+// -----------------------------------------------------------------------------
1310
+static int OP_SMUL_B_B(uint32_t i) { OP_MULxy_(c.imul(lhs, rhs), L, L, 0, 0, 0); }
1311
+static int OP_SMUL_B_T(uint32_t i) { OP_MULxy_(c.imul(lhs, rhs), L, H, 0, 0, 0); }
1312
+static int OP_SMUL_T_B(uint32_t i) { OP_MULxy_(c.imul(lhs, rhs), H, L, 0, 0, 0); }
1313
+static int OP_SMUL_T_T(uint32_t i) { OP_MULxy_(c.imul(lhs, rhs), H, H, 0, 0, 0); }
1314
+
1315
+// -----------------------------------------------------------------------------
1316
+//   SMLA
1317
+// -----------------------------------------------------------------------------
1318
+static int OP_SMLA_B_B(uint32_t i) { OP_MULxy_(c.imul(lhs, rhs), L, L, 0, 1, 1); }
1319
+static int OP_SMLA_B_T(uint32_t i) { OP_MULxy_(c.imul(lhs, rhs), L, H, 0, 1, 1); }
1320
+static int OP_SMLA_T_B(uint32_t i) { OP_MULxy_(c.imul(lhs, rhs), H, L, 0, 1, 1); }
1321
+static int OP_SMLA_T_T(uint32_t i) { OP_MULxy_(c.imul(lhs, rhs), H, H, 0, 1, 1); }
1322
+
1323
+// -----------------------------------------------------------------------------
1324
+//   SMLAL
1325
+// -----------------------------------------------------------------------------
1326
+static int OP_SMLAL_B_B(uint32_t i) { OP_MULxy_(c.imul(hi,lhs,rhs), L, L, 1, 1, 1); }
1327
+static int OP_SMLAL_B_T(uint32_t i) { OP_MULxy_(c.imul(hi,lhs,rhs), L, H, 1, 1, 1); }
1328
+static int OP_SMLAL_T_B(uint32_t i) { OP_MULxy_(c.imul(hi,lhs,rhs), H, L, 1, 1, 1); }
1329
+static int OP_SMLAL_T_T(uint32_t i) { OP_MULxy_(c.imul(hi,lhs,rhs), H, H, 1, 1, 1); }
1330
+
1331
+// -----------------------------------------------------------------------------
1332
+//   SMULW / SMLAW
1333
+// -----------------------------------------------------------------------------
1334
+#ifdef ASMJIT_X64
1335
+#define OP_SMxxW_(x, accum, flags) \
1336
+	GpVar lhs = c.newGpVar(kX86VarTypeGpz); \
1337
+	GpVar rhs = c.newGpVar(kX86VarTypeGpz); \
1338
+	c.movsx(lhs, reg_pos_ptr##x(8)); \
1339
+	c.movsxd(rhs, reg_pos_ptr(0)); \
1340
+	c.imul(lhs, rhs);  \
1341
+	c.sar(lhs, 16); \
1342
+	if (accum) \
1343
+		c.add(lhs, reg_pos_ptr(12)); \
1344
+	c.mov(reg_pos_ptr(16), lhs.r32()); \
1345
+	if (flags) \
1346
+		SET_Q; \
1347
+	return 1;
1348
+#else
1349
+#define OP_SMxxW_(x, accum, flags) \
1350
+	GpVar lhs = c.newGpVar(kX86VarTypeGpd); \
1351
+	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
1352
+	GpVar hi = c.newGpVar(kX86VarTypeGpd); \
1353
+	c.movsx(lhs, reg_pos_ptr##x(8)); \
1354
+	c.mov(rhs, reg_pos_ptr(0)); \
1355
+	c.imul(hi, lhs, rhs);  \
1356
+	c.shr(lhs, 16); \
1357
+	c.shl(hi, 16); \
1358
+	c.or_(lhs, hi); \
1359
+	if (accum) \
1360
+		c.add(lhs, reg_pos_ptr(12)); \
1361
+	c.mov(reg_pos_ptr(16), lhs); \
1362
+	if (flags) \
1363
+		SET_Q; \
1364
+	return 1;
1365
+#endif
1366
+
1367
+static int OP_SMULW_B(uint32_t i) { OP_SMxxW_(L, 0, 0); }
1368
+static int OP_SMULW_T(uint32_t i) { OP_SMxxW_(H, 0, 0); }
1369
+static int OP_SMLAW_B(uint32_t i) { OP_SMxxW_(L, 1, 1); }
1370
+static int OP_SMLAW_T(uint32_t i) { OP_SMxxW_(H, 1, 1); }
1371
+
1372
+// -----------------------------------------------------------------------------
1373
+//   MRS / MSR
1374
+// -----------------------------------------------------------------------------
1375
+static int OP_MRS_CPSR(uint32_t i)
1376
+{
1377
+	GpVar x = c.newGpVar(kX86VarTypeGpd);
1378
+	c.mov(x, cpu_ptr(CPSR));
1379
+	c.mov(reg_pos_ptr(12), x);
1380
+	return 1;
1381
+}
1382
+
1383
+static int OP_MRS_SPSR(uint32_t i)
1384
+{
1385
+	GpVar x = c.newGpVar(kX86VarTypeGpd);
1386
+	c.mov(x, cpu_ptr(SPSR));
1387
+	c.mov(reg_pos_ptr(12), x);
1388
+	return 1;
1389
+}
1390
+
1391
+// TODO: SPSR: if(cpu->CPSR.bits.mode == USR || cpu->CPSR.bits.mode == SYS) return 1;
1392
+#define OP_MSR_(reg, args, sw) \
1393
+	GpVar operand = c.newGpVar(kX86VarTypeGpd); \
1394
+	args; \
1395
+	switch ((i >> 16) & 0xF) \
1396
+	{ \
1397
+		case 0x1: /* bit 16 */ \
1398
+		{ \
1399
+			GpVar mode = c.newGpVar(kX86VarTypeGpd); \
1400
+			Label __skip = c.newLabel(); \
1401
+			c.mov(mode, cpu_ptr(CPSR)); \
1402
+			c.and_(mode, 0x1F); \
1403
+			c.cmp(mode, USR); \
1404
+			c.je(__skip); \
1405
+			if (sw) \
1406
+			{ \
1407
+				c.mov(mode, rhs); \
1408
+				c.and_(mode, 0x1F); \
1409
+				X86CompilerFuncCall* ctx = c.call(reinterpret_cast<void *>(armcpu_switchMode)); \
1410
+				ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<void, void *, uint8_t>()); \
1411
+				ctx->setArgument(0, bb_cpu); \
1412
+				ctx->setArgument(1, mode); \
1413
+			} \
1414
+			c.mov(operand, rhs); \
1415
+			Mem xPSR_memB = cpu_ptr_byte(reg, 0); \
1416
+			c.mov(xPSR_memB, operand.r8Lo()); \
1417
+			changeCPSR; \
1418
+			c.bind(__skip); \
1419
+			return 1; \
1420
+		} \
1421
+		case 0x2: /* bit 17 */ \
1422
+		{ \
1423
+			GpVar mode = c.newGpVar(kX86VarTypeGpd); \
1424
+			Label __skip = c.newLabel(); \
1425
+			c.mov(mode, cpu_ptr(CPSR)); \
1426
+			c.and_(mode, 0x1F); \
1427
+			c.cmp(mode, USR); \
1428
+			c.je(__skip); \
1429
+			c.mov(operand, rhs); \
1430
+			Mem xPSR_memB = cpu_ptr_byte(reg, 1); \
1431
+			c.shr(operand, 8); \
1432
+			c.mov(xPSR_memB, operand.r8Lo()); \
1433
+			changeCPSR; \
1434
+			c.bind(__skip); \
1435
+			return 1; \
1436
+		} \
1437
+		case 0x4: /* bit 18 */ \
1438
+		{ \
1439
+			GpVar mode = c.newGpVar(kX86VarTypeGpd); \
1440
+			Label __skip = c.newLabel(); \
1441
+			c.mov(mode, cpu_ptr(CPSR)); \
1442
+			c.and_(mode, 0x1F); \
1443
+			c.cmp(mode, USR); \
1444
+			c.je(__skip); \
1445
+			c.mov(operand, rhs); \
1446
+			Mem xPSR_memB = cpu_ptr_byte(reg, 2); \
1447
+			c.shr(operand, 16); \
1448
+			c.mov(xPSR_memB, operand.r8Lo()); \
1449
+			changeCPSR; \
1450
+			c.bind(__skip); \
1451
+			return 1; \
1452
+		} \
1453
+		case 0x8: /* bit 19 */ \
1454
+		{ \
1455
+			c.mov(operand, rhs); \
1456
+			Mem xPSR_memB = cpu_ptr_byte(reg, 3); \
1457
+			c.shr(operand, 24); \
1458
+			c.mov(xPSR_memB, operand.r8Lo()); \
1459
+			changeCPSR; \
1460
+			return 1; \
1461
+		} \
1462
+	} \
1463
+\
1464
+	static uint32_t byte_mask = (BIT16(i) ? 0x000000FF : 0x00000000) | (BIT17(i) ? 0x0000FF00 : 0x00000000) | (BIT18(i) ? 0x00FF0000 : 0x00000000) | (BIT19(i) ? 0xFF000000 : 0x00000000); \
1465
+	static uint32_t byte_mask_USR = BIT19(i) ? 0xFF000000 : 0x00000000; \
1466
+\
1467
+	Mem xPSR_mem = cpu_ptr(reg.val); \
1468
+	GpVar xPSR = c.newGpVar(kX86VarTypeGpd); \
1469
+	GpVar mode = c.newGpVar(kX86VarTypeGpd); \
1470
+	Label __USR = c.newLabel(); \
1471
+	Label __done = c.newLabel(); \
1472
+	c.mov(mode, cpu_ptr(CPSR.val)); \
1473
+	c.and_(mode, 0x1F); \
1474
+	c.cmp(mode, USR); \
1475
+	c.je(__USR); \
1476
+	/* mode != USR */ \
1477
+	if (sw && BIT16(i)) \
1478
+	{ \
1479
+		/* armcpu_switchMode */ \
1480
+		c.mov(mode, rhs); \
1481
+		c.and_(mode, 0x1F); \
1482
+		X86CompilerFuncCall* ctx = c.call(reinterpret_cast<void *>(armcpu_switchMode)); \
1483
+		ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<void, void *, uint8_t>()); \
1484
+		ctx->setArgument(0, bb_cpu); \
1485
+		ctx->setArgument(1, mode); \
1486
+	} \
1487
+	/* cpu->CPSR.val = (cpu->CPSR.val & ~byte_mask) | (operand & byte_mask); */ \
1488
+	c.mov(operand, rhs); \
1489
+	c.mov(xPSR, xPSR_mem); \
1490
+	c.and_(operand, byte_mask); \
1491
+	c.and_(xPSR, ~byte_mask); \
1492
+	c.or_(xPSR, operand); \
1493
+	c.mov(xPSR_mem, xPSR); \
1494
+	c.jmp(__done); \
1495
+	/* mode == USR */ \
1496
+	c.bind(__USR); \
1497
+	c.mov(operand, rhs); \
1498
+	c.mov(xPSR, xPSR_mem); \
1499
+	c.and_(operand, byte_mask_USR); \
1500
+	c.and_(xPSR, ~byte_mask_USR); \
1501
+	c.or_(xPSR, operand); \
1502
+	c.mov(xPSR_mem, xPSR); \
1503
+	c.bind(__done); \
1504
+	changeCPSR; \
1505
+	return 1;
1506
+
1507
+static int OP_MSR_CPSR(uint32_t i) { OP_MSR_(CPSR, REG_OFF, 1); }
1508
+static int OP_MSR_SPSR(uint32_t i) { OP_MSR_(SPSR, REG_OFF, 0); }
1509
+static int OP_MSR_CPSR_IMM_VAL(uint32_t i) { OP_MSR_(CPSR, IMM_VAL, 1); }
1510
+static int OP_MSR_SPSR_IMM_VAL(uint32_t i) { OP_MSR_(SPSR, IMM_VAL, 0); }
1511
+
1512
+// -----------------------------------------------------------------------------
1513
+//   LDR
1514
+// -----------------------------------------------------------------------------
1515
+typedef uint32_t (FASTCALL *OpLDR)(uint32_t, uint32_t *);
1516
+
1517
+// 98% of all memory accesses land in the same region as the first execution of
1518
+// that instruction, so keep multiple copies with different fastpaths.
1519
+// The copies don't need to differ in any way; the point is merely to cooperate
1520
+// with x86 branch prediction.
1521
+
1522
+enum
1523
+{
1524
+	MEMTYPE_GENERIC, // no assumptions
1525
+	MEMTYPE_MAIN,
1526
+	MEMTYPE_DTCM,
1527
+	MEMTYPE_ERAM,
1528
+	MEMTYPE_SWIRAM,
1529
+	MEMTYPE_OTHER // memory that is known to not be MAIN, DTCM, ERAM, or SWIRAM
1530
+};
1531
+
1532
+static uint32_t classify_adr(uint32_t adr, bool store)
1533
+{
1534
+	if (PROCNUM == ARMCPU_ARM9 && (adr & ~0x3FFF) == MMU.DTCMRegion)
1535
+		return MEMTYPE_DTCM;
1536
+	else if ((adr & 0x0F000000) == 0x02000000)
1537
+		return MEMTYPE_MAIN;
1538
+	else if (PROCNUM == ARMCPU_ARM7 && !store && (adr & 0xFF800000) == 0x03800000)
1539
+		return MEMTYPE_ERAM;
1540
+	else if (PROCNUM == ARMCPU_ARM7 && !store && (adr & 0xFF800000) == 0x03000000)
1541
+		return MEMTYPE_SWIRAM;
1542
+	else
1543
+		return MEMTYPE_GENERIC;
1544
+}
1545
+
1546
+template<int PROCNUM, int memtype> static uint32_t FASTCALL OP_LDR(uint32_t adr, uint32_t *dstreg)
1547
+{
1548
+	uint32_t data = READ32(cpu->mem_if->data, adr);
1549
+	if (adr & 3)
1550
+		data = ROR(data, 8 * (adr & 3));
1551
+	*dstreg = data;
1552
+	return MMU_aluMemAccessCycles<PROCNUM, 32, MMU_AD_READ>(3, adr);
1553
+}
1554
+
1555
+template<int PROCNUM, int memtype> static uint32_t FASTCALL OP_LDRH(uint32_t adr, uint32_t *dstreg)
1556
+{
1557
+	*dstreg = READ16(cpu->mem_if->data, adr);
1558
+	return MMU_aluMemAccessCycles<PROCNUM, 16, MMU_AD_READ>(3, adr);
1559
+}
1560
+
1561
+template<int PROCNUM, int memtype> static uint32_t FASTCALL OP_LDRSH(uint32_t adr, uint32_t *dstreg)
1562
+{
1563
+	*dstreg = static_cast<int16_t>(READ16(cpu->mem_if->data, adr));
1564
+	return MMU_aluMemAccessCycles<PROCNUM, 16, MMU_AD_READ>(3, adr);
1565
+}
1566
+
1567
+template<int PROCNUM, int memtype> static uint32_t FASTCALL OP_LDRB(uint32_t adr, uint32_t *dstreg)
1568
+{
1569
+	*dstreg = READ8(cpu->mem_if->data, adr);
1570
+	return MMU_aluMemAccessCycles<PROCNUM, 8, MMU_AD_READ>(3, adr);
1571
+}
1572
+
1573
+template<int PROCNUM, int memtype> static uint32_t FASTCALL OP_LDRSB(uint32_t adr, uint32_t *dstreg)
1574
+{
1575
+	*dstreg = static_cast<int8_t>(READ8(cpu->mem_if->data, adr));
1576
+	return MMU_aluMemAccessCycles<PROCNUM, 8, MMU_AD_READ>(3, adr);
1577
+}
1578
+
1579
+#define T(op) op<0, 0>, op<0, 1>, op<0, 2>, nullptr, nullptr, op<1, 0>, op<1, 1>, nullptr, op<1, 3>, op<1, 4>
1580
+static const OpLDR LDR_tab[2][5] = { T(OP_LDR) };
1581
+static const OpLDR LDRH_tab[2][5] = { T(OP_LDRH) };
1582
+static const OpLDR LDRSH_tab[2][5] = { T(OP_LDRSH) };
1583
+static const OpLDR LDRB_tab[2][5] = { T(OP_LDRB) };
1584
+static const OpLDR LDRSB_tab[2][5] = { T(OP_LDRSB) };
1585
+#undef T
1586
+
1587
+static uint32_t add(uint32_t lhs, uint32_t rhs) { return lhs + rhs; }
1588
+static uint32_t sub(uint32_t lhs, uint32_t rhs) { return lhs - rhs; }
1589
+
1590
+#define OP_LDR_(mem_op, arg, sign_op, writeback) \
1591
+	GpVar adr = c.newGpVar(kX86VarTypeGpd); \
1592
+	GpVar dst = c.newGpVar(kX86VarTypeGpz); \
1593
+	c.mov(adr, reg_pos_ptr(16)); \
1594
+	c.lea(dst, reg_pos_ptr(12)); \
1595
+	arg; \
1596
+	if (!rhs_is_imm || *reinterpret_cast<uint32_t *>(&rhs)) \
1597
+	{ \
1598
+		if (!writeback) \
1599
+			c.sign_op(adr, rhs); \
1600
+		else if (writeback < 0) \
1601
+		{ \
1602
+			c.sign_op(adr, rhs); \
1603
+			c.mov(reg_pos_ptr(16), adr); \
1604
+		} \
1605
+		else if (writeback > 0) \
1606
+		{ \
1607
+			GpVar tmp_reg = c.newGpVar(kX86VarTypeGpd); \
1608
+			c.mov(tmp_reg, adr); \
1609
+			c.sign_op(tmp_reg, rhs); \
1610
+			c.mov(reg_pos_ptr(16), tmp_reg); \
1611
+		} \
1612
+	} \
1613
+	uint32_t adr_first = sign_op(cpu->R[REG_POS(i,16)], rhs_first); \
1614
+	X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(mem_op##_tab[PROCNUM][classify_adr(adr_first, 0)])); \
1615
+	ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<uint32_t, uint32_t, uint32_t *>()); \
1616
+	ctx->setArgument(0, adr); \
1617
+	ctx->setArgument(1, dst); \
1618
+	ctx->setReturn(bb_cycles); \
1619
+	if (REG_POS(i, 12) == 15) \
1620
+	{ \
1621
+		GpVar tmp = c.newGpVar(kX86VarTypeGpd); \
1622
+		c.mov(tmp, reg_ptr(15)); \
1623
+		if (!PROCNUM) \
1624
+		{ \
1625
+			GpVar thumb = c.newGpVar(kX86VarTypeGpz); \
1626
+			c.movzx(thumb, reg_pos_ptrB(16)); \
1627
+			c.and_(thumb, 1); \
1628
+			c.shl(thumb, 5); \
1629
+			c.or_(cpu_ptr(CPSR), thumb.r64()); \
1630
+			c.and_(tmp, 0xFFFFFFFE); \
1631
+		} \
1632
+		else \
1633
+			c.and_(tmp, 0xFFFFFFFC); \
1634
+		c.mov(cpu_ptr(next_instruction), tmp); \
1635
+	} \
1636
+	return 1;
1637
+
1638
+// LDR
1639
+static int OP_LDR_P_IMM_OFF(uint32_t i) { OP_LDR_(LDR, IMM_OFF_12, add, 0); }
1640
+static int OP_LDR_M_IMM_OFF(uint32_t i) { OP_LDR_(LDR, IMM_OFF_12, sub, 0); }
1641
+static int OP_LDR_P_LSL_IMM_OFF(uint32_t i) { OP_LDR_(LDR, LSL_IMM, add, 0); }
1642
+static int OP_LDR_M_LSL_IMM_OFF(uint32_t i) { OP_LDR_(LDR, LSL_IMM, sub, 0); }
1643
+static int OP_LDR_P_LSR_IMM_OFF(uint32_t i) { OP_LDR_(LDR, LSR_IMM, add, 0); }
1644
+static int OP_LDR_M_LSR_IMM_OFF(uint32_t i) { OP_LDR_(LDR, LSR_IMM, sub, 0); }
1645
+static int OP_LDR_P_ASR_IMM_OFF(uint32_t i) { OP_LDR_(LDR, ASR_IMM, add, 0); }
1646
+static int OP_LDR_M_ASR_IMM_OFF(uint32_t i) { OP_LDR_(LDR, ASR_IMM, sub, 0); }
1647
+static int OP_LDR_P_ROR_IMM_OFF(uint32_t i) { OP_LDR_(LDR, ROR_IMM, add, 0); }
1648
+static int OP_LDR_M_ROR_IMM_OFF(uint32_t i) { OP_LDR_(LDR, ROR_IMM, sub, 0); }
1649
+
1650
+static int OP_LDR_P_IMM_OFF_PREIND(uint32_t i) { OP_LDR_(LDR, IMM_OFF_12, add, -1); }
1651
+static int OP_LDR_M_IMM_OFF_PREIND(uint32_t i) { OP_LDR_(LDR, IMM_OFF_12, sub, -1); }
1652
+static int OP_LDR_P_LSL_IMM_OFF_PREIND(uint32_t i) { OP_LDR_(LDR, LSL_IMM, add, -1); }
1653
+static int OP_LDR_M_LSL_IMM_OFF_PREIND(uint32_t i) { OP_LDR_(LDR, LSL_IMM, sub, -1); }
1654
+static int OP_LDR_P_LSR_IMM_OFF_PREIND(uint32_t i) { OP_LDR_(LDR, LSR_IMM, add, -1); }
1655
+static int OP_LDR_M_LSR_IMM_OFF_PREIND(uint32_t i) { OP_LDR_(LDR, LSR_IMM, sub, -1); }
1656
+static int OP_LDR_P_ASR_IMM_OFF_PREIND(uint32_t i) { OP_LDR_(LDR, ASR_IMM, add, -1); }
1657
+static int OP_LDR_M_ASR_IMM_OFF_PREIND(uint32_t i) { OP_LDR_(LDR, ASR_IMM, sub, -1); }
1658
+static int OP_LDR_P_ROR_IMM_OFF_PREIND(uint32_t i) { OP_LDR_(LDR, ROR_IMM, add, -1); }
1659
+static int OP_LDR_M_ROR_IMM_OFF_PREIND(uint32_t i) { OP_LDR_(LDR, ROR_IMM, sub, -1); }
1660
+static int OP_LDR_P_IMM_OFF_POSTIND(uint32_t i) { OP_LDR_(LDR, IMM_OFF_12, add, 1); }
1661
+static int OP_LDR_M_IMM_OFF_POSTIND(uint32_t i) { OP_LDR_(LDR, IMM_OFF_12, sub, 1); }
1662
+static int OP_LDR_P_LSL_IMM_OFF_POSTIND(uint32_t i) { OP_LDR_(LDR, LSL_IMM, add, 1); }
1663
+static int OP_LDR_M_LSL_IMM_OFF_POSTIND(uint32_t i) { OP_LDR_(LDR, LSL_IMM, sub, 1); }
1664
+static int OP_LDR_P_LSR_IMM_OFF_POSTIND(uint32_t i) { OP_LDR_(LDR, LSR_IMM, add, 1); }
1665
+static int OP_LDR_M_LSR_IMM_OFF_POSTIND(uint32_t i) { OP_LDR_(LDR, LSR_IMM, sub, 1); }
1666
+static int OP_LDR_P_ASR_IMM_OFF_POSTIND(uint32_t i) { OP_LDR_(LDR, ASR_IMM, add, 1); }
1667
+static int OP_LDR_M_ASR_IMM_OFF_POSTIND(uint32_t i) { OP_LDR_(LDR, ASR_IMM, sub, 1); }
1668
+static int OP_LDR_P_ROR_IMM_OFF_POSTIND(uint32_t i) { OP_LDR_(LDR, ROR_IMM, add, 1); }
1669
+static int OP_LDR_M_ROR_IMM_OFF_POSTIND(uint32_t i) { OP_LDR_(LDR, ROR_IMM, sub, 1); }
1670
+
1671
+// LDRH
1672
+static int OP_LDRH_P_IMM_OFF(uint32_t i) { OP_LDR_(LDRH, IMM_OFF, add, 0); }
1673
+static int OP_LDRH_M_IMM_OFF(uint32_t i) { OP_LDR_(LDRH, IMM_OFF, sub, 0); }
1674
+static int OP_LDRH_P_REG_OFF(uint32_t i) { OP_LDR_(LDRH, REG_OFF, add, 0); }
1675
+static int OP_LDRH_M_REG_OFF(uint32_t i) { OP_LDR_(LDRH, REG_OFF, sub, 0); }
1676
+
1677
+static int OP_LDRH_PRE_INDE_P_IMM_OFF(uint32_t i) { OP_LDR_(LDRH, IMM_OFF, add, -1); }
1678
+static int OP_LDRH_PRE_INDE_M_IMM_OFF(uint32_t i) { OP_LDR_(LDRH, IMM_OFF, sub, -1); }
1679
+static int OP_LDRH_PRE_INDE_P_REG_OFF(uint32_t i) { OP_LDR_(LDRH, REG_OFF, add, -1); }
1680
+static int OP_LDRH_PRE_INDE_M_REG_OFF(uint32_t i) { OP_LDR_(LDRH, REG_OFF, sub, -1); }
1681
+static int OP_LDRH_POS_INDE_P_IMM_OFF(uint32_t i) { OP_LDR_(LDRH, IMM_OFF, add, 1); }
1682
+static int OP_LDRH_POS_INDE_M_IMM_OFF(uint32_t i) { OP_LDR_(LDRH, IMM_OFF, sub, 1); }
1683
+static int OP_LDRH_POS_INDE_P_REG_OFF(uint32_t i) { OP_LDR_(LDRH, REG_OFF, add, 1); }
1684
+static int OP_LDRH_POS_INDE_M_REG_OFF(uint32_t i) { OP_LDR_(LDRH, REG_OFF, sub, 1); }
1685
+
1686
+// LDRSH
1687
+static int OP_LDRSH_P_IMM_OFF(uint32_t i) { OP_LDR_(LDRSH, IMM_OFF, add, 0); }
1688
+static int OP_LDRSH_M_IMM_OFF(uint32_t i) { OP_LDR_(LDRSH, IMM_OFF, sub, 0); }
1689
+static int OP_LDRSH_P_REG_OFF(uint32_t i) { OP_LDR_(LDRSH, REG_OFF, add, 0); }
1690
+static int OP_LDRSH_M_REG_OFF(uint32_t i) { OP_LDR_(LDRSH, REG_OFF, sub, 0); }
1691
+
1692
+static int OP_LDRSH_PRE_INDE_P_IMM_OFF(uint32_t i) { OP_LDR_(LDRSH, IMM_OFF, add, -1); }
1693
+static int OP_LDRSH_PRE_INDE_M_IMM_OFF(uint32_t i) { OP_LDR_(LDRSH, IMM_OFF, sub, -1); }
1694
+static int OP_LDRSH_PRE_INDE_P_REG_OFF(uint32_t i) { OP_LDR_(LDRSH, REG_OFF, add, -1); }
1695
+static int OP_LDRSH_PRE_INDE_M_REG_OFF(uint32_t i) { OP_LDR_(LDRSH, REG_OFF, sub, -1); }
1696
+static int OP_LDRSH_POS_INDE_P_IMM_OFF(uint32_t i) { OP_LDR_(LDRSH, IMM_OFF, add, 1); }
1697
+static int OP_LDRSH_POS_INDE_M_IMM_OFF(uint32_t i) { OP_LDR_(LDRSH, IMM_OFF, sub, 1); }
1698
+static int OP_LDRSH_POS_INDE_P_REG_OFF(uint32_t i) { OP_LDR_(LDRSH, REG_OFF, add, 1); }
1699
+static int OP_LDRSH_POS_INDE_M_REG_OFF(uint32_t i) { OP_LDR_(LDRSH, REG_OFF, sub, 1); }
1700
+
1701
+// LDRB
1702
+static int OP_LDRB_P_IMM_OFF(uint32_t i) { OP_LDR_(LDRB, IMM_OFF_12, add, 0); }
1703
+static int OP_LDRB_M_IMM_OFF(uint32_t i) { OP_LDR_(LDRB, IMM_OFF_12, sub, 0); }
1704
+static int OP_LDRB_P_LSL_IMM_OFF(uint32_t i) { OP_LDR_(LDRB, LSL_IMM, add, 0); }
1705
+static int OP_LDRB_M_LSL_IMM_OFF(uint32_t i) { OP_LDR_(LDRB, LSL_IMM, sub, 0); }
1706
+static int OP_LDRB_P_LSR_IMM_OFF(uint32_t i) { OP_LDR_(LDRB, LSR_IMM, add, 0); }
1707
+static int OP_LDRB_M_LSR_IMM_OFF(uint32_t i) { OP_LDR_(LDRB, LSR_IMM, sub, 0); }
1708
+static int OP_LDRB_P_ASR_IMM_OFF(uint32_t i) { OP_LDR_(LDRB, ASR_IMM, add, 0); }
1709
+static int OP_LDRB_M_ASR_IMM_OFF(uint32_t i) { OP_LDR_(LDRB, ASR_IMM, sub, 0); }
1710
+static int OP_LDRB_P_ROR_IMM_OFF(uint32_t i) { OP_LDR_(LDRB, ROR_IMM, add, 0); }
1711
+static int OP_LDRB_M_ROR_IMM_OFF(uint32_t i) { OP_LDR_(LDRB, ROR_IMM, sub, 0); }
1712
+
1713
+static int OP_LDRB_P_IMM_OFF_PREIND(uint32_t i) { OP_LDR_(LDRB, IMM_OFF_12, add, -1); }
1714
+static int OP_LDRB_M_IMM_OFF_PREIND(uint32_t i) { OP_LDR_(LDRB, IMM_OFF_12, sub, -1); }
1715
+static int OP_LDRB_P_LSL_IMM_OFF_PREIND(uint32_t i) { OP_LDR_(LDRB, LSL_IMM, add, -1); }
1716
+static int OP_LDRB_M_LSL_IMM_OFF_PREIND(uint32_t i) { OP_LDR_(LDRB, LSL_IMM, sub, -1); }
1717
+static int OP_LDRB_P_LSR_IMM_OFF_PREIND(uint32_t i) { OP_LDR_(LDRB, LSR_IMM, add, -1); }
1718
+static int OP_LDRB_M_LSR_IMM_OFF_PREIND(uint32_t i) { OP_LDR_(LDRB, LSR_IMM, sub, -1); }
1719
+static int OP_LDRB_P_ASR_IMM_OFF_PREIND(uint32_t i) { OP_LDR_(LDRB, ASR_IMM, add, -1); }
1720
+static int OP_LDRB_M_ASR_IMM_OFF_PREIND(uint32_t i) { OP_LDR_(LDRB, ASR_IMM, sub, -1); }
1721
+static int OP_LDRB_P_ROR_IMM_OFF_PREIND(uint32_t i) { OP_LDR_(LDRB, ROR_IMM, add, -1); }
1722
+static int OP_LDRB_M_ROR_IMM_OFF_PREIND(uint32_t i) { OP_LDR_(LDRB, ROR_IMM, sub, -1); }
1723
+static int OP_LDRB_P_IMM_OFF_POSTIND(uint32_t i) { OP_LDR_(LDRB, IMM_OFF_12, add, 1); }
1724
+static int OP_LDRB_M_IMM_OFF_POSTIND(uint32_t i) { OP_LDR_(LDRB, IMM_OFF_12, sub, 1); }
1725
+static int OP_LDRB_P_LSL_IMM_OFF_POSTIND(uint32_t i) { OP_LDR_(LDRB, LSL_IMM, add, 1); }
1726
+static int OP_LDRB_M_LSL_IMM_OFF_POSTIND(uint32_t i) { OP_LDR_(LDRB, LSL_IMM, sub, 1); }
1727
+static int OP_LDRB_P_LSR_IMM_OFF_POSTIND(uint32_t i) { OP_LDR_(LDRB, LSR_IMM, add, 1); }
1728
+static int OP_LDRB_M_LSR_IMM_OFF_POSTIND(uint32_t i) { OP_LDR_(LDRB, LSR_IMM, sub, 1); }
1729
+static int OP_LDRB_P_ASR_IMM_OFF_POSTIND(uint32_t i) { OP_LDR_(LDRB, ASR_IMM, add, 1); }
1730
+static int OP_LDRB_M_ASR_IMM_OFF_POSTIND(uint32_t i) { OP_LDR_(LDRB, ASR_IMM, sub, 1); }
1731
+static int OP_LDRB_P_ROR_IMM_OFF_POSTIND(uint32_t i) { OP_LDR_(LDRB, ROR_IMM, add, 1); }
1732
+static int OP_LDRB_M_ROR_IMM_OFF_POSTIND(uint32_t i) { OP_LDR_(LDRB, ROR_IMM, sub, 1); }
1733
+
1734
+// LDRSB
1735
+static int OP_LDRSB_P_IMM_OFF(uint32_t i) { OP_LDR_(LDRSB, IMM_OFF, add, 0); }
1736
+static int OP_LDRSB_M_IMM_OFF(uint32_t i) { OP_LDR_(LDRSB, IMM_OFF, sub, 0); }
1737
+static int OP_LDRSB_P_REG_OFF(uint32_t i) { OP_LDR_(LDRSB, REG_OFF, add, 0); }
1738
+static int OP_LDRSB_M_REG_OFF(uint32_t i) { OP_LDR_(LDRSB, REG_OFF, sub, 0); }
1739
+
1740
+static int OP_LDRSB_PRE_INDE_P_IMM_OFF(uint32_t i) { OP_LDR_(LDRSB, IMM_OFF, add, -1); }
1741
+static int OP_LDRSB_PRE_INDE_M_IMM_OFF(uint32_t i) { OP_LDR_(LDRSB, IMM_OFF, sub, -1); }
1742
+static int OP_LDRSB_PRE_INDE_P_REG_OFF(uint32_t i) { OP_LDR_(LDRSB, REG_OFF, add, -1); }
1743
+static int OP_LDRSB_PRE_INDE_M_REG_OFF(uint32_t i) { OP_LDR_(LDRSB, REG_OFF, sub, -1); }
1744
+static int OP_LDRSB_POS_INDE_P_IMM_OFF(uint32_t i) { OP_LDR_(LDRSB, IMM_OFF, add, 1); }
1745
+static int OP_LDRSB_POS_INDE_M_IMM_OFF(uint32_t i) { OP_LDR_(LDRSB, IMM_OFF, sub, 1); }
1746
+static int OP_LDRSB_POS_INDE_P_REG_OFF(uint32_t i) { OP_LDR_(LDRSB, REG_OFF, add, 1); }
1747
+static int OP_LDRSB_POS_INDE_M_REG_OFF(uint32_t i) { OP_LDR_(LDRSB, REG_OFF, sub, 1); }
1748
+
1749
+// -----------------------------------------------------------------------------
1750
+//   STR
1751
+// -----------------------------------------------------------------------------
1752
+template<int PROCNUM, int memtype> static uint32_t FASTCALL OP_STR(uint32_t adr, uint32_t data)
1753
+{
1754
+	WRITE32(cpu->mem_if->data, adr, data);
1755
+	return MMU_aluMemAccessCycles<PROCNUM, 32, MMU_AD_WRITE>(2, adr);
1756
+}
1757
+
1758
+template<int PROCNUM, int memtype> static uint32_t FASTCALL OP_STRH(uint32_t adr, uint32_t data)
1759
+{
1760
+	WRITE16(cpu->mem_if->data, adr, data);
1761
+	return MMU_aluMemAccessCycles<PROCNUM, 16, MMU_AD_WRITE>(2, adr);
1762
+}
1763
+
1764
+template<int PROCNUM, int memtype> static uint32_t FASTCALL OP_STRB(uint32_t adr, uint32_t data)
1765
+{
1766
+	WRITE8(cpu->mem_if->data, adr, data);
1767
+	return MMU_aluMemAccessCycles<PROCNUM, 8, MMU_AD_WRITE>(2, adr);
1768
+}
1769
+
1770
+typedef uint32_t (FASTCALL *OpSTR)(uint32_t, uint32_t);
1771
+#define T(op) op<0, 0>, op<0, 1>, op<0, 2>, op<1, 0>, op<1, 1>, nullptr
1772
+static const OpSTR STR_tab[2][3] = { T(OP_STR) };
1773
+static const OpSTR STRH_tab[2][3] = { T(OP_STRH) };
1774
+static const OpSTR STRB_tab[2][3] = { T(OP_STRB) };
1775
+#undef T
1776
+
1777
+#define OP_STR_(mem_op, arg, sign_op, writeback) \
1778
+	GpVar adr = c.newGpVar(kX86VarTypeGpd); \
1779
+	GpVar data = c.newGpVar(kX86VarTypeGpd); \
1780
+	c.mov(adr, reg_pos_ptr(16)); \
1781
+	c.mov(data, reg_pos_ptr(12)); \
1782
+	arg; \
1783
+	if (!rhs_is_imm || *reinterpret_cast<uint32_t *>(&rhs)) \
1784
+	{ \
1785
+		if (!writeback) \
1786
+			c.sign_op(adr, rhs); \
1787
+		else if (writeback < 0) \
1788
+		{ \
1789
+			c.sign_op(adr, rhs); \
1790
+			c.mov(reg_pos_ptr(16), adr); \
1791
+		} \
1792
+		else if (writeback > 0) \
1793
+		{ \
1794
+			GpVar tmp_reg = c.newGpVar(kX86VarTypeGpd); \
1795
+			c.mov(tmp_reg, adr); \
1796
+			c.sign_op(tmp_reg, rhs); \
1797
+			c.mov(reg_pos_ptr(16), tmp_reg); \
1798
+		} \
1799
+	} \
1800
+	uint32_t adr_first = sign_op(cpu->R[REG_POS(i,16)], rhs_first); \
1801
+	X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(mem_op##_tab[PROCNUM][classify_adr(adr_first, 1)])); \
1802
+	ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<uint32_t, uint32_t, uint32_t>()); \
1803
+	ctx->setArgument(0, adr); \
1804
+	ctx->setArgument(1, data); \
1805
+	ctx->setReturn(bb_cycles); \
1806
+	return 1;
1807
+
1808
+static int OP_STR_P_IMM_OFF(uint32_t i) { OP_STR_(STR, IMM_OFF_12, add, 0); }
1809
+static int OP_STR_M_IMM_OFF(uint32_t i) { OP_STR_(STR, IMM_OFF_12, sub, 0); }
1810
+static int OP_STR_P_LSL_IMM_OFF(uint32_t i) { OP_STR_(STR, LSL_IMM, add, 0); }
1811
+static int OP_STR_M_LSL_IMM_OFF(uint32_t i) { OP_STR_(STR, LSL_IMM, sub, 0); }
1812
+static int OP_STR_P_LSR_IMM_OFF(uint32_t i) { OP_STR_(STR, LSR_IMM, add, 0); }
1813
+static int OP_STR_M_LSR_IMM_OFF(uint32_t i) { OP_STR_(STR, LSR_IMM, sub, 0); }
1814
+static int OP_STR_P_ASR_IMM_OFF(uint32_t i) { OP_STR_(STR, ASR_IMM, add, 0); }
1815
+static int OP_STR_M_ASR_IMM_OFF(uint32_t i) { OP_STR_(STR, ASR_IMM, sub, 0); }
1816
+static int OP_STR_P_ROR_IMM_OFF(uint32_t i) { OP_STR_(STR, ROR_IMM, add, 0); }
1817
+static int OP_STR_M_ROR_IMM_OFF(uint32_t i) { OP_STR_(STR, ROR_IMM, sub, 0); }
1818
+
1819
+static int OP_STR_P_IMM_OFF_PREIND(uint32_t i) { OP_STR_(STR, IMM_OFF_12, add, -1); }
1820
+static int OP_STR_M_IMM_OFF_PREIND(uint32_t i) { OP_STR_(STR, IMM_OFF_12, sub, -1); }
1821
+static int OP_STR_P_LSL_IMM_OFF_PREIND(uint32_t i) { OP_STR_(STR, LSL_IMM, add, -1); }
1822
+static int OP_STR_M_LSL_IMM_OFF_PREIND(uint32_t i) { OP_STR_(STR, LSL_IMM, sub, -1); }
1823
+static int OP_STR_P_LSR_IMM_OFF_PREIND(uint32_t i) { OP_STR_(STR, LSR_IMM, add, -1); }
1824
+static int OP_STR_M_LSR_IMM_OFF_PREIND(uint32_t i) { OP_STR_(STR, LSR_IMM, sub, -1); }
1825
+static int OP_STR_P_ASR_IMM_OFF_PREIND(uint32_t i) { OP_STR_(STR, ASR_IMM, add, -1); }
1826
+static int OP_STR_M_ASR_IMM_OFF_PREIND(uint32_t i) { OP_STR_(STR, ASR_IMM, sub, -1); }
1827
+static int OP_STR_P_ROR_IMM_OFF_PREIND(uint32_t i) { OP_STR_(STR, ROR_IMM, add, -1); }
1828
+static int OP_STR_M_ROR_IMM_OFF_PREIND(uint32_t i) { OP_STR_(STR, ROR_IMM, sub, -1); }
1829
+static int OP_STR_P_IMM_OFF_POSTIND(uint32_t i) { OP_STR_(STR, IMM_OFF_12, add, 1); }
1830
+static int OP_STR_M_IMM_OFF_POSTIND(uint32_t i) { OP_STR_(STR, IMM_OFF_12, sub, 1); }
1831
+static int OP_STR_P_LSL_IMM_OFF_POSTIND(uint32_t i) { OP_STR_(STR, LSL_IMM, add, 1); }
1832
+static int OP_STR_M_LSL_IMM_OFF_POSTIND(uint32_t i) { OP_STR_(STR, LSL_IMM, sub, 1); }
1833
+static int OP_STR_P_LSR_IMM_OFF_POSTIND(uint32_t i) { OP_STR_(STR, LSR_IMM, add, 1); }
1834
+static int OP_STR_M_LSR_IMM_OFF_POSTIND(uint32_t i) { OP_STR_(STR, LSR_IMM, sub, 1); }
1835
+static int OP_STR_P_ASR_IMM_OFF_POSTIND(uint32_t i) { OP_STR_(STR, ASR_IMM, add, 1); }
1836
+static int OP_STR_M_ASR_IMM_OFF_POSTIND(uint32_t i) { OP_STR_(STR, ASR_IMM, sub, 1); }
1837
+static int OP_STR_P_ROR_IMM_OFF_POSTIND(uint32_t i) { OP_STR_(STR, ROR_IMM, add, 1); }
1838
+static int OP_STR_M_ROR_IMM_OFF_POSTIND(uint32_t i) { OP_STR_(STR, ROR_IMM, sub, 1); }
1839
+
1840
+static int OP_STRH_P_IMM_OFF(uint32_t i) { OP_STR_(STRH, IMM_OFF, add, 0); }
1841
+static int OP_STRH_M_IMM_OFF(uint32_t i) { OP_STR_(STRH, IMM_OFF, sub, 0); }
1842
+static int OP_STRH_P_REG_OFF(uint32_t i) { OP_STR_(STRH, REG_OFF, add, 0); }
1843
+static int OP_STRH_M_REG_OFF(uint32_t i) { OP_STR_(STRH, REG_OFF, sub, 0); }
1844
+
1845
+static int OP_STRH_PRE_INDE_P_IMM_OFF(uint32_t i) { OP_STR_(STRH, IMM_OFF, add, -1); }
1846
+static int OP_STRH_PRE_INDE_M_IMM_OFF(uint32_t i) { OP_STR_(STRH, IMM_OFF, sub, -1); }
1847
+static int OP_STRH_PRE_INDE_P_REG_OFF(uint32_t i) { OP_STR_(STRH, REG_OFF, add, -1); }
1848
+static int OP_STRH_PRE_INDE_M_REG_OFF(uint32_t i) { OP_STR_(STRH, REG_OFF, sub, -1); }
1849
+static int OP_STRH_POS_INDE_P_IMM_OFF(uint32_t i) { OP_STR_(STRH, IMM_OFF, add, 1); }
1850
+static int OP_STRH_POS_INDE_M_IMM_OFF(uint32_t i) { OP_STR_(STRH, IMM_OFF, sub, 1); }
1851
+static int OP_STRH_POS_INDE_P_REG_OFF(uint32_t i) { OP_STR_(STRH, REG_OFF, add, 1); }
1852
+static int OP_STRH_POS_INDE_M_REG_OFF(uint32_t i) { OP_STR_(STRH, REG_OFF, sub, 1); }
1853
+
1854
+static int OP_STRB_P_IMM_OFF(uint32_t i) { OP_STR_(STRB, IMM_OFF_12, add, 0); }
1855
+static int OP_STRB_M_IMM_OFF(uint32_t i) { OP_STR_(STRB, IMM_OFF_12, sub, 0); }
1856
+static int OP_STRB_P_LSL_IMM_OFF(uint32_t i) { OP_STR_(STRB, LSL_IMM, add, 0); }
1857
+static int OP_STRB_M_LSL_IMM_OFF(uint32_t i) { OP_STR_(STRB, LSL_IMM, sub, 0); }
1858
+static int OP_STRB_P_LSR_IMM_OFF(uint32_t i) { OP_STR_(STRB, LSR_IMM, add, 0); }
1859
+static int OP_STRB_M_LSR_IMM_OFF(uint32_t i) { OP_STR_(STRB, LSR_IMM, sub, 0); }
1860
+static int OP_STRB_P_ASR_IMM_OFF(uint32_t i) { OP_STR_(STRB, ASR_IMM, add, 0); }
1861
+static int OP_STRB_M_ASR_IMM_OFF(uint32_t i) { OP_STR_(STRB, ASR_IMM, sub, 0); }
1862
+static int OP_STRB_P_ROR_IMM_OFF(uint32_t i) { OP_STR_(STRB, ROR_IMM, add, 0); }
1863
+static int OP_STRB_M_ROR_IMM_OFF(uint32_t i) { OP_STR_(STRB, ROR_IMM, sub, 0); }
1864
+
1865
+static int OP_STRB_P_IMM_OFF_PREIND(uint32_t i) { OP_STR_(STRB, IMM_OFF_12, add, -1); }
1866
+static int OP_STRB_M_IMM_OFF_PREIND(uint32_t i) { OP_STR_(STRB, IMM_OFF_12, sub, -1); }
1867
+static int OP_STRB_P_LSL_IMM_OFF_PREIND(uint32_t i) { OP_STR_(STRB, LSL_IMM, add, -1); }
1868
+static int OP_STRB_M_LSL_IMM_OFF_PREIND(uint32_t i) { OP_STR_(STRB, LSL_IMM, sub, -1); }
1869
+static int OP_STRB_P_LSR_IMM_OFF_PREIND(uint32_t i) { OP_STR_(STRB, LSR_IMM, add, -1); }
1870
+static int OP_STRB_M_LSR_IMM_OFF_PREIND(uint32_t i) { OP_STR_(STRB, LSR_IMM, sub, -1); }
1871
+static int OP_STRB_P_ASR_IMM_OFF_PREIND(uint32_t i) { OP_STR_(STRB, ASR_IMM, add, -1); }
1872
+static int OP_STRB_M_ASR_IMM_OFF_PREIND(uint32_t i) { OP_STR_(STRB, ASR_IMM, sub, -1); }
1873
+static int OP_STRB_P_ROR_IMM_OFF_PREIND(uint32_t i) { OP_STR_(STRB, ROR_IMM, add, -1); }
1874
+static int OP_STRB_M_ROR_IMM_OFF_PREIND(uint32_t i) { OP_STR_(STRB, ROR_IMM, sub, -1); }
1875
+static int OP_STRB_P_IMM_OFF_POSTIND(uint32_t i) { OP_STR_(STRB, IMM_OFF_12, add, 1); }
1876
+static int OP_STRB_M_IMM_OFF_POSTIND(uint32_t i) { OP_STR_(STRB, IMM_OFF_12, sub, 1); }
1877
+static int OP_STRB_P_LSL_IMM_OFF_POSTIND(uint32_t i) { OP_STR_(STRB, LSL_IMM, add, 1); }
1878
+static int OP_STRB_M_LSL_IMM_OFF_POSTIND(uint32_t i) { OP_STR_(STRB, LSL_IMM, sub, 1); }
1879
+static int OP_STRB_P_LSR_IMM_OFF_POSTIND(uint32_t i) { OP_STR_(STRB, LSR_IMM, add, 1); }
1880
+static int OP_STRB_M_LSR_IMM_OFF_POSTIND(uint32_t i) { OP_STR_(STRB, LSR_IMM, sub, 1); }
1881
+static int OP_STRB_P_ASR_IMM_OFF_POSTIND(uint32_t i) { OP_STR_(STRB, ASR_IMM, add, 1); }
1882
+static int OP_STRB_M_ASR_IMM_OFF_POSTIND(uint32_t i) { OP_STR_(STRB, ASR_IMM, sub, 1); }
1883
+static int OP_STRB_P_ROR_IMM_OFF_POSTIND(uint32_t i) { OP_STR_(STRB, ROR_IMM, add, 1); }
1884
+static int OP_STRB_M_ROR_IMM_OFF_POSTIND(uint32_t i) { OP_STR_(STRB, ROR_IMM, sub, 1); }
1885
+
1886
+// -----------------------------------------------------------------------------
1887
+//   LDRD / STRD
1888
+// -----------------------------------------------------------------------------
1889
+typedef uint32_t FASTCALL (*LDRD_STRD_REG)(uint32_t);
1890
+
1891
+template<int PROCNUM, uint8_t Rnum> static uint32_t FASTCALL OP_LDRD_REG(uint32_t adr)
1892
+{
1893
+	cpu->R[Rnum] = READ32(cpu->mem_if->data, adr);
1894
+	cpu->R[Rnum + 1] = READ32(cpu->mem_if->data, adr + 4);
1895
+	return MMU_memAccessCycles<PROCNUM, 32, MMU_AD_READ>(adr) + MMU_memAccessCycles<PROCNUM, 32, MMU_AD_READ>(adr + 4);
1896
+}
1897
+
1898
+template<int PROCNUM, uint8_t Rnum> static uint32_t FASTCALL OP_STRD_REG(uint32_t adr)
1899
+{
1900
+	WRITE32(cpu->mem_if->data, adr, cpu->R[Rnum]);
1901
+	WRITE32(cpu->mem_if->data, adr + 4, cpu->R[Rnum + 1]);
1902
+	return MMU_memAccessCycles<PROCNUM, 32, MMU_AD_WRITE>(adr) + MMU_memAccessCycles<PROCNUM, 32, MMU_AD_WRITE>(adr + 4);
1903
+}
1904
+
1905
+#define T(op, proc) op<proc, 0>, op<proc, 1>, op<proc, 2>, op<proc, 3>, op<proc, 4>, op<proc, 5>, op<proc, 6>, op<proc, 7>, \
1906
+	op<proc, 8>, op<proc, 9>, op<proc, 10>, op<proc, 11>, op<proc, 12>, op<proc, 13>, op<proc, 14>, op<proc, 15>
1907
+static const LDRD_STRD_REG op_ldrd_tab[2][16] = { { T(OP_LDRD_REG, 0) }, { T(OP_LDRD_REG, 1) } };
1908
+static const LDRD_STRD_REG op_strd_tab[2][16] = { { T(OP_STRD_REG, 0) }, { T(OP_STRD_REG, 1) } };
1909
+#undef T
1910
+
1911
+static int OP_LDRD_STRD_POST_INDEX(uint32_t i)
1912
+{
1913
+	uint8_t Rd_num = REG_POS(i, 12);
1914
+	
1915
+	if (Rd_num == 14)
1916
+	{
1917
+		printf("OP_LDRD_STRD_POST_INDEX: use R14!!!!\n");
1918
+		return 0; // TODO: exception
1919
+	}
1920
+	if (Rd_num & 0x1)
1921
+	{
1922
+		printf("OP_LDRD_STRD_POST_INDEX: ERROR!!!!\n");
1923
+		return 0; // TODO: exception
1924
+	}
1925
+	GpVar Rd = c.newGpVar(kX86VarTypeGpd);
1926
+	GpVar addr = c.newGpVar(kX86VarTypeGpd);
1927
+
1928
+	c.mov(Rd, reg_pos_ptr(16));
1929
+	c.mov(addr, reg_pos_ptr(16));
1930
+
1931
+	// I bit - immediate or register
1932
+	if (BIT22(i))
1933
+	{
1934
+		IMM_OFF;
1935
+		BIT23(i) ? c.add(reg_pos_ptr(16), rhs) : c.sub(reg_pos_ptr(16), rhs);
1936
+	}
1937
+	else
1938
+	{
1939
+		GpVar idx = c.newGpVar(kX86VarTypeGpd);
1940
+		c.mov(idx, reg_pos_ptr(0));
1941
+		BIT23(i) ? c.add(reg_pos_ptr(16), idx) : c.sub(reg_pos_ptr(16), idx);
1942
+	}
1943
+
1944
+	X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(BIT5(i) ? op_strd_tab[PROCNUM][Rd_num] : op_ldrd_tab[PROCNUM][Rd_num]));
1945
+	ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder1<uint32_t, uint32_t>());
1946
+	ctx->setArgument(0, addr);
1947
+	ctx->setReturn(bb_cycles);
1948
+	emit_MMU_aluMemCycles(3, bb_cycles, 0);
1949
+	return 1;
1950
+}
1951
+
1952
+static int OP_LDRD_STRD_OFFSET_PRE_INDEX(uint32_t i)
1953
+{
1954
+	uint8_t Rd_num = REG_POS(i, 12);
1955
+	
1956
+	if (Rd_num == 14)
1957
+	{
1958
+		printf("OP_LDRD_STRD_OFFSET_PRE_INDEX: use R14!!!!\n");
1959
+		return 0; // TODO: exception
1960
+	}
1961
+	if (Rd_num & 0x1)
1962
+	{
1963
+		printf("OP_LDRD_STRD_OFFSET_PRE_INDEX: ERROR!!!!\n");
1964
+		return 0; // TODO: exception
1965
+	}
1966
+	GpVar Rd = c.newGpVar(kX86VarTypeGpd);
1967
+	GpVar addr = c.newGpVar(kX86VarTypeGpd);
1968
+
1969
+	c.mov(Rd, reg_pos_ptr(16));
1970
+	c.mov(addr, reg_pos_ptr(16));
1971
+
1972
+	// I bit - immediate or register
1973
+	if (BIT22(i))
1974
+	{
1975
+		IMM_OFF;
1976
+		BIT23(i) ? c.add(addr, rhs) : c.sub(addr, rhs);
1977
+	}
1978
+	else
1979
+		BIT23(i) ? c.add(addr, reg_pos_ptr(0)) : c.sub(addr, reg_pos_ptr(0));
1980
+
1981
+	if (BIT5(i)) // Store
1982
+	{
1983
+		X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(op_strd_tab[PROCNUM][Rd_num]));
1984
+		ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder1<uint32_t, uint32_t>());
1985
+		ctx->setArgument(0, addr);
1986
+		ctx->setReturn(bb_cycles);
1987
+		if (BIT21(i)) // W bit - writeback
1988
+			c.mov(reg_pos_ptr(16), addr);
1989
+		emit_MMU_aluMemCycles(3, bb_cycles, 0);
1990
+	}
1991
+	else // Load
1992
+	{
1993
+		if (BIT21(i)) // W bit - writeback
1994
+			c.mov(reg_pos_ptr(16), addr);
1995
+		X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(op_ldrd_tab[PROCNUM][Rd_num]));
1996
+		ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder1<uint32_t, uint32_t>());
1997
+		ctx->setArgument(0, addr);
1998
+		ctx->setReturn(bb_cycles);
1999
+		emit_MMU_aluMemCycles(3, bb_cycles, 0);
2000
+	}
2001
+	return 1;
2002
+}
2003
+
2004
+// -----------------------------------------------------------------------------
2005
+//   SWP/SWPB
2006
+// -----------------------------------------------------------------------------
2007
+template<int PROCNUM> static uint32_t FASTCALL op_swp(uint32_t adr, uint32_t *Rd, uint32_t Rs)
2008
+{
2009
+	uint32_t tmp = ROR(READ32(cpu->mem_if->data, adr), (adr & 3) << 3);
2010
+	WRITE32(cpu->mem_if->data, adr, Rs);
2011
+	*Rd = tmp;
2012
+	return MMU_memAccessCycles<PROCNUM, 32, MMU_AD_READ>(adr) + MMU_memAccessCycles<PROCNUM, 32, MMU_AD_WRITE>(adr);
2013
+}
2014
+
2015
+template<int PROCNUM> static uint32_t FASTCALL op_swpb(uint32_t adr, uint32_t *Rd, uint32_t Rs)
2016
+{
2017
+	uint32_t tmp = READ8(cpu->mem_if->data, adr);
2018
+	WRITE8(cpu->mem_if->data, adr, Rs);
2019
+	*Rd = tmp;
2020
+	return MMU_memAccessCycles<PROCNUM, 8, MMU_AD_READ>(adr) + MMU_memAccessCycles<PROCNUM, 8, MMU_AD_WRITE>(adr);
2021
+}
2022
+
2023
+typedef uint32_t FASTCALL (*OP_SWP_SWPB)(uint32_t, uint32_t *, uint32_t);
2024
+static const OP_SWP_SWPB op_swp_tab[2][2] = { { op_swp<0>, op_swp<1> }, { op_swpb<0>, op_swpb<1> } };
2025
+
2026
+static int op_swp_(uint32_t i, int b)
2027
+{
2028
+	GpVar addr = c.newGpVar(kX86VarTypeGpd);
2029
+	GpVar Rd = c.newGpVar(kX86VarTypeGpz);
2030
+	GpVar Rs = c.newGpVar(kX86VarTypeGpd);
2031
+	c.mov(addr, reg_pos_ptr(16));
2032
+	c.lea(Rd, reg_pos_ptr(12));
2033
+	if (b)
2034
+		c.movzx(Rs, reg_pos_ptrB(0));
2035
+	else
2036
+		c.mov(Rs, reg_pos_ptr(0));
2037
+	X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(op_swp_tab[b][PROCNUM]));
2038
+	ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder3<uint32_t, uint32_t, uint32_t *, uint32_t>());
2039
+	ctx->setArgument(0, addr);
2040
+	ctx->setArgument(1, Rd);
2041
+	ctx->setArgument(2, Rs);
2042
+	ctx->setReturn(bb_cycles);
2043
+	emit_MMU_aluMemCycles(4, bb_cycles, 0);
2044
+	return 1;
2045
+}
2046
+
2047
+static int OP_SWP(uint32_t i) { return op_swp_(i, 0); }
2048
+static int OP_SWPB(uint32_t i) { return op_swp_(i, 1); }
2049
+
2050
+// -----------------------------------------------------------------------------
2051
+//   LDMIA / LDMIB / LDMDA / LDMDB / STMIA / STMIB / STMDA / STMDB
2052
+// -----------------------------------------------------------------------------
2053
+static uint32_t popcount(uint32_t x)
2054
+{
2055
+	uint32_t pop = 0;
2056
+	for (; x; x >>= 1)
2057
+		pop += x & 1;
2058
+	return pop;
2059
+}
2060
+
2061
+static uint64_t get_reg_list(uint32_t reg_mask, int dir)
2062
+{
2063
+	uint64_t regs = 0;
2064
+	for (int j = 0; j < 16; ++j)
2065
+	{
2066
+		int k = dir < 0 ? j : 15 - j;
2067
+		if (BIT_N(reg_mask, k))
2068
+			regs = (regs << 4) | k;
2069
+	}
2070
+	return regs;
2071
+}
2072
+
2073
+#ifdef ASMJIT_X64
2074
+// generic needs to spill regs and main doesn't; if it's inlined gcc isn't smart enough to keep the spills out of the common case.
2075
+#define LDM_INLINE
2076
+#else
2077
+// spills either way, and we might as well save codesize by not having separate functions
2078
+#define LDM_INLINE inline
2079
+#endif
2080
+
2081
+template<int PROCNUM, bool store, int dir> static LDM_INLINE FASTCALL uint32_t OP_LDM_STM_generic(uint32_t adr, uint64_t regs, int n)
2082
+{
2083
+	uint32_t cycles = 0;
2084
+	adr &= ~3;
2085
+	do
2086
+	{
2087
+		if (store)
2088
+			_MMU_write32<PROCNUM>(adr, cpu->R[regs & 0xF]);
2089
+		else
2090
+			cpu->R[regs & 0xF] = _MMU_read32<PROCNUM>(adr);
2091
+		cycles += MMU_memAccessCycles<PROCNUM, 32, store ? MMU_AD_WRITE : MMU_AD_READ>(adr);
2092
+		adr += 4 * dir;
2093
+		regs >>= 4;
2094
+	} while (--n > 0);
2095
+	return cycles;
2096
+}
2097
+
2098
+#ifdef ENABLE_ADVANCED_TIMING
2099
+#define ADV_CYCLES cycles += MMU_memAccessCycles<PROCNUM, 32, store ? MMU_AD_WRITE : MMU_AD_READ>(adr);
2100
+#else
2101
+#define ADV_CYCLES
2102
+#endif
2103
+
2104
+template<int PROCNUM, bool store, int dir> static LDM_INLINE FASTCALL uint32_t OP_LDM_STM_other(uint32_t adr, uint64_t regs, int n)
2105
+{
2106
+	uint32_t cycles = 0;
2107
+	adr &= ~3;
2108
+#ifndef ENABLE_ADVANCED_TIMING
2109
+	cycles = n * MMU_memAccessCycles<PROCNUM, 32, store ? MMU_AD_WRITE : MMU_AD_READ>(adr);
2110
+#endif
2111
+	do
2112
+	{
2113
+		if (PROCNUM == ARMCPU_ARM9)
2114
+		{
2115
+			if (store)
2116
+				_MMU_ARM9_write32(adr, cpu->R[regs & 0xF]);
2117
+			else
2118
+				cpu->R[regs & 0xF] = _MMU_ARM9_read32(adr);
2119
+		}
2120
+		else
2121
+		{
2122
+			if (store)
2123
+				_MMU_ARM7_write32(adr, cpu->R[regs & 0xF]);
2124
+			else
2125
+				cpu->R[regs & 0xF] = _MMU_ARM7_read32(adr);
2126
+		}
2127
+		ADV_CYCLES;
2128
+		adr += 4 * dir;
2129
+		regs >>= 4;
2130
+	} while (--n > 0);
2131
+	return cycles;
2132
+}
2133
+
2134
+template<int PROCNUM, bool store, int dir, bool null_compiled> static FORCEINLINE FASTCALL uint32_t OP_LDM_STM_main(uint32_t adr, uint64_t regs, int n, uint8_t *ptr, uint32_t cycles)
2135
+{
2136
+#ifdef ENABLE_ADVANCED_TIMING
2137
+	cycles = 0;
2138
+#endif
2139
+	uintptr_t *func = reinterpret_cast<uintptr_t *>(&JIT_COMPILED_FUNC(adr, PROCNUM));
2140
+
2141
+#define OP(j) \
2142
+{ \
2143
+	/* no need to zero functions in DTCM, since we can't execute from it */ \
2144
+	if (null_compiled && store) \
2145
+	{ \
2146
+		*func = 0; \
2147
+		*(func + 1) = 0; \
2148
+	} \
2149
+	int Rd = (static_cast<uintptr_t>(regs) >> (j * 4)) & 0xF; \
2150
+	if (store) \
2151
+		*reinterpret_cast<uint32_t *>(ptr) = cpu->R[Rd]; \
2152
+	else \
2153
+		cpu->R[Rd] = *reinterpret_cast<uint32_t *>(ptr); \
2154
+	ADV_CYCLES; \
2155
+	func += 2 * dir; \
2156
+	adr += 4 * dir; \
2157
+	ptr += 4 * dir; \
2158
+}
2159
+
2160
+	do
2161
+	{
2162
+		OP(0);
2163
+		if (n == 1)
2164
+			break;
2165
+		OP(1);
2166
+		if (n == 2)
2167
+			break;
2168
+		OP(2);
2169
+		if (n == 3)
2170
+			break;
2171
+		OP(3);
2172
+		regs >>= 16;
2173
+		n -= 4;
2174
+	} while (n > 0);
2175
+	return cycles;
2176
+#undef OP
2177
+#undef ADV_CYCLES
2178
+}
2179
+
2180
+template<int PROCNUM, bool store, int dir> static uint32_t FASTCALL OP_LDM_STM(uint32_t adr, uint64_t regs, int n)
2181
+{
2182
+	// TODO use classify_adr?
2183
+	uint32_t cycles;
2184
+	uint8_t *ptr;
2185
+
2186
+	if ((adr ^ (adr + (dir > 0 ? (n - 1) * 4 : -15 * 4))) & ~0x3FFF) // a little conservative, but we don't want to run too many comparisons
2187
+		// the memory region spans a page boundary, so we can't factor the address translation out of the loop
2188
+		return OP_LDM_STM_generic<PROCNUM, store, dir>(adr, regs, n);
2189
+	else if (PROCNUM == ARMCPU_ARM9 && (adr & ~0x3FFF) == MMU.DTCMRegion)
2190
+	{
2191
+		// don't special-case DTCM cycles, even though that would be both faster and more accurate,
2192
+		// because that wouldn't match the non-jitted version with !ACCOUNT_FOR_DATA_TCM_SPEED
2193
+		ptr = MMU.ARM9_DTCM + (adr & 0x3FFC);
2194
+		cycles = n * MMU_memAccessCycles<PROCNUM, 32, store ? MMU_AD_WRITE : MMU_AD_READ>(adr);
2195
+		if (store)
2196
+			return OP_LDM_STM_main<PROCNUM, store, dir, 0>(adr, regs, n, ptr, cycles);
2197
+	}
2198
+	else if ((adr & 0x0F000000) == 0x02000000)
2199
+	{
2200
+		ptr = MMU.MAIN_MEM + (adr & _MMU_MAIN_MEM_MASK32);
2201
+		cycles = n * (PROCNUM == ARMCPU_ARM9 ? 4 : 2);
2202
+	}
2203
+	else if (PROCNUM == ARMCPU_ARM7 && !store && (adr & 0xFF800000) == 0x03800000)
2204
+	{
2205
+		ptr = MMU.ARM7_ERAM + (adr & 0xFFFC);
2206
+		cycles = n;
2207
+	}
2208
+	else if (PROCNUM == ARMCPU_ARM7 && !store && (adr & 0xFF800000) == 0x03000000)
2209
+	{
2210
+		ptr = MMU.SWIRAM + (adr & 0x7FFC);
2211
+		cycles = n;
2212
+	}
2213
+	else
2214
+		return OP_LDM_STM_other<PROCNUM, store, dir>(adr, regs, n);
2215
+
2216
+	return OP_LDM_STM_main<PROCNUM, store, dir, store>(adr, regs, n, ptr, cycles);
2217
+}
2218
+
2219
+typedef uint32_t FASTCALL (*LDMOpFunc)(uint32_t, uint64_t, int);
2220
+static const LDMOpFunc op_ldm_stm_tab[2][2][2] =
2221
+{
2222
+	{
2223
+		{ OP_LDM_STM<0, 0, -1>, OP_LDM_STM<0, 0, 1> },
2224
+		{ OP_LDM_STM<0, 1, -1>, OP_LDM_STM<0, 1, 1> },
2225
+	},
2226
+	{
2227
+		{ OP_LDM_STM<1, 0, -1>, OP_LDM_STM<1, 0, 1> },
2228
+		{ OP_LDM_STM<1, 1, -1>, OP_LDM_STM<1, 1, 1> },
2229
+	}
2230
+};
2231
+
2232
+static void call_ldm_stm(GpVar adr, uint32_t bitmask, bool store, int dir)
2233
+{
2234
+	if (bitmask)
2235
+	{
2236
+		GpVar n = c.newGpVar(kX86VarTypeGpd);
2237
+		c.mov(n, popcount(bitmask));
2238
+#ifdef ASMJIT_X64
2239
+		GpVar regs = c.newGpVar(kX86VarTypeGpz);
2240
+		c.mov(regs, get_reg_list(bitmask, dir));
2241
+		X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(op_ldm_stm_tab[PROCNUM][store][dir > 0]));
2242
+		ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder3<uint32_t, uint32_t, uint64_t, int>());
2243
+		ctx->setArgument(0, adr);
2244
+		ctx->setArgument(1, regs);
2245
+		ctx->setArgument(2, n);
2246
+#else
2247
+		// same prototype, but we have to handle splitting of a u64 arg manually
2248
+		GpVar regs_lo = c.newGpVar(kX86VarTypeGpd);
2249
+		GpVar regs_hi = c.newGpVar(kX86VarTypeGpd);
2250
+		c.mov(regs_lo, static_cast<uint32_t>(get_reg_list(bitmask, dir)));
2251
+		c.mov(regs_hi, get_reg_list(bitmask, dir) >> 32);
2252
+		X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(op_ldm_stm_tab[PROCNUM][store][dir > 0]));
2253
+		ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder4<uint32_t, uint32_t, uint32_t, uint32_t, int>());
2254
+		ctx->setArgument(0, adr);
2255
+		ctx->setArgument(1, regs_lo);
2256
+		ctx->setArgument(2, regs_hi);
2257
+		ctx->setArgument(3, n);
2258
+#endif
2259
+		ctx->setReturn(bb_cycles);
2260
+	}
2261
+	else
2262
+		++bb_constant_cycles;
2263
+}
2264
+
2265
+static int op_bx(Mem srcreg, bool blx, bool test_thumb);
2266
+static int op_bx_thumb(Mem srcreg, bool blx, bool test_thumb);
2267
+
2268
+static int op_ldm_stm(uint32_t i, bool store, int dir, bool before, bool writeback)
2269
+{
2270
+	uint32_t bitmask = i & 0xFFFF;
2271
+	uint32_t pop = popcount(bitmask);
2272
+
2273
+	GpVar adr = c.newGpVar(kX86VarTypeGpd);
2274
+	c.mov(adr, reg_pos_ptr(16));
2275
+	if (before)
2276
+		c.add(adr, 4*dir);
2277
+
2278
+	call_ldm_stm(adr, bitmask, store, dir);
2279
+
2280
+	if (BIT15(i) && !store)
2281
+		op_bx(reg_ptr(15), 0, PROCNUM == ARMCPU_ARM9);
2282
+
2283
+	if (writeback)
2284
+	{
2285
+		
2286
+		if (store || !(i & (1 << REG_POS(i, 16))))
2287
+		{
2288
+			JIT_COMMENT("--- writeback");
2289
+			c.add(reg_pos_ptr(16), 4 * dir * pop);
2290
+		}
2291
+		else
2292
+		{
2293
+			uint32_t bitlist = (~((2 << REG_POS(i, 16)) - 1)) & 0xFFFF;
2294
+			if (i & bitlist)
2295
+			{
2296
+				JIT_COMMENT("--- writeback");
2297
+				c.add(adr, 4 * dir * (pop - before));
2298
+				c.mov(reg_pos_ptr(16), adr);
2299
+			}
2300
+		}
2301
+	}
2302
+
2303
+	emit_MMU_aluMemCycles(store ? 1 : 2, bb_cycles, pop);
2304
+	return 1;
2305
+}
2306
+
2307
+static int OP_LDMIA(uint32_t i) { return op_ldm_stm(i, 0, +1, 0, 0); }
2308
+static int OP_LDMIB(uint32_t i) { return op_ldm_stm(i, 0, +1, 1, 0); }
2309
+static int OP_LDMDA(uint32_t i) { return op_ldm_stm(i, 0, -1, 0, 0); }
2310
+static int OP_LDMDB(uint32_t i) { return op_ldm_stm(i, 0, -1, 1, 0); }
2311
+static int OP_LDMIA_W(uint32_t i) { return op_ldm_stm(i, 0, +1, 0, 1); }
2312
+static int OP_LDMIB_W(uint32_t i) { return op_ldm_stm(i, 0, +1, 1, 1); }
2313
+static int OP_LDMDA_W(uint32_t i) { return op_ldm_stm(i, 0, -1, 0, 1); }
2314
+static int OP_LDMDB_W(uint32_t i) { return op_ldm_stm(i, 0, -1, 1, 1); }
2315
+
2316
+static int OP_STMIA(uint32_t i) { return op_ldm_stm(i, 1, +1, 0, 0); }
2317
+static int OP_STMIB(uint32_t i) { return op_ldm_stm(i, 1, +1, 1, 0); }
2318
+static int OP_STMDA(uint32_t i) { return op_ldm_stm(i, 1, -1, 0, 0); }
2319
+static int OP_STMDB(uint32_t i) { return op_ldm_stm(i, 1, -1, 1, 0); }
2320
+static int OP_STMIA_W(uint32_t i) { return op_ldm_stm(i, 1, +1, 0, 1); }
2321
+static int OP_STMIB_W(uint32_t i) { return op_ldm_stm(i, 1, +1, 1, 1); }
2322
+static int OP_STMDA_W(uint32_t i) { return op_ldm_stm(i, 1, -1, 0, 1); }
2323
+static int OP_STMDB_W(uint32_t i) { return op_ldm_stm(i, 1, -1, 1, 1); }
2324
+
2325
+static int op_ldm_stm2(uint32_t i, bool store, int dir, bool before, bool writeback)
2326
+{
2327
+	uint32_t bitmask = i & 0xFFFF;
2328
+	uint32_t pop = popcount(bitmask);
2329
+	bool bit15 = !!BIT15(i);
2330
+
2331
+	//printf("ARM%c: %s R%d:%08X, bitmask %02X\n", PROCNUM?'7':'9', (store?"STM":"LDM"), REG_POS(i, 16), cpu->R[REG_POS(i, 16)], bitmask);
2332
+	uint32_t adr_first = cpu->R[REG_POS(i, 16)];
2333
+
2334
+	GpVar adr = c.newGpVar(kX86VarTypeGpd);
2335
+	GpVar oldmode = c.newGpVar(kX86VarTypeGpd);
2336
+
2337
+	c.mov(adr, reg_pos_ptr(16));
2338
+	if (before)
2339
+		c.add(adr, 4*dir);
2340
+
2341
+	if (!bit15 || store)
2342
+	{
2343
+		//if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; }
2344
+		//oldmode = armcpu_switchMode(cpu, SYS);
2345
+		c.mov(oldmode, SYS);
2346
+		X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(armcpu_switchMode));
2347
+		ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<uint32_t, uint8_t *, uint8_t>());
2348
+		ctx->setArgument(0, bb_cpu);
2349
+		ctx->setArgument(1, oldmode);
2350
+		ctx->setReturn(oldmode);
2351
+	}
2352
+
2353
+	call_ldm_stm(adr, bitmask, store, dir);
2354
+
2355
+	if (!bit15 || store)
2356
+	{
2357
+		//armcpu_switchMode(cpu, oldmode);
2358
+		X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(armcpu_switchMode));
2359
+		ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<void, uint8_t *, uint8_t>());
2360
+		ctx->setArgument(0, bb_cpu);
2361
+		ctx->setArgument(1, oldmode);
2362
+	}
2363
+	else
2364
+		S_DST_R15;
2365
+
2366
+	// FIXME
2367
+	if (writeback)
2368
+	{
2369
+		if (store || !(i & (1 << REG_POS(i, 16))))
2370
+			c.add(reg_pos_ptr(16), 4 * dir * pop);
2371
+		else
2372
+		{
2373
+			uint32_t bitlist = (~((2 << REG_POS(i, 16)) - 1)) & 0xFFFF;
2374
+			if (i & bitlist)
2375
+			{
2376
+				c.add(adr, 4 * dir * (pop - before));
2377
+				c.mov(reg_pos_ptr(16), adr);
2378
+			}
2379
+		}
2380
+	}
2381
+
2382
+	emit_MMU_aluMemCycles(store ? 1 : 2, bb_cycles, pop);
2383
+	return 1;
2384
+}
2385
+
2386
+static int OP_LDMIA2(uint32_t i) { return op_ldm_stm2(i, 0, +1, 0, 0); }
2387
+static int OP_LDMIB2(uint32_t i) { return op_ldm_stm2(i, 0, +1, 1, 0); }
2388
+static int OP_LDMDA2(uint32_t i) { return op_ldm_stm2(i, 0, -1, 0, 0); }
2389
+static int OP_LDMDB2(uint32_t i) { return op_ldm_stm2(i, 0, -1, 1, 0); }
2390
+static int OP_LDMIA2_W(uint32_t i) { return op_ldm_stm2(i, 0, +1, 0, 1); }
2391
+static int OP_LDMIB2_W(uint32_t i) { return op_ldm_stm2(i, 0, +1, 1, 1); }
2392
+static int OP_LDMDA2_W(uint32_t i) { return op_ldm_stm2(i, 0, -1, 0, 1); }
2393
+static int OP_LDMDB2_W(uint32_t i) { return op_ldm_stm2(i, 0, -1, 1, 1); }
2394
+
2395
+static int OP_STMIA2(uint32_t i) { return op_ldm_stm2(i, 1, +1, 0, 0); }
2396
+static int OP_STMIB2(uint32_t i) { return op_ldm_stm2(i, 1, +1, 1, 0); }
2397
+static int OP_STMDA2(uint32_t i) { return op_ldm_stm2(i, 1, -1, 0, 0); }
2398
+static int OP_STMDB2(uint32_t i) { return op_ldm_stm2(i, 1, -1, 1, 0); }
2399
+static int OP_STMIA2_W(uint32_t i) { return op_ldm_stm2(i, 1, +1, 0, 1); }
2400
+static int OP_STMIB2_W(uint32_t i) { return op_ldm_stm2(i, 1, +1, 1, 1); }
2401
+static int OP_STMDA2_W(uint32_t i) { return op_ldm_stm2(i, 1, -1, 0, 1); }
2402
+static int OP_STMDB2_W(uint32_t i) { return op_ldm_stm2(i, 1, -1, 1, 1); }
2403
+
2404
+// -----------------------------------------------------------------------------
2405
+//   Branch
2406
+// -----------------------------------------------------------------------------
2407
+
2408
+static inline uint32_t SIGNEXTEND_11(uint32_t i) { return static_cast<uint32_t>((static_cast<int32_t>(i) << 21) >> 21); }
2409
+static inline uint32_t SIGNEXTEND_24(uint32_t i) { return static_cast<uint32_t>((static_cast<int32_t>(i) << 8) >> 8); }
2410
+
2411
+static int op_b(uint32_t i, bool bl)
2412
+{
2413
+	uint32_t dst = bb_r15 + (SIGNEXTEND_24(i) << 2);
2414
+	if (CONDITION(i) == 0xF)
2415
+	{
2416
+		if (bl)
2417
+			dst += 2;
2418
+		c.or_(cpu_ptr_byte(CPSR, 0), 1 << 5);
2419
+	}
2420
+	if (bl || CONDITION(i) == 0xF)
2421
+		c.mov(reg_ptr(14), bb_next_instruction);
2422
+
2423
+	c.mov(cpu_ptr(instruct_adr), dst);
2424
+	return 1;
2425
+}
2426
+
2427
+static int OP_B(uint32_t i) { return op_b(i, 0); }
2428
+static int OP_BL(uint32_t i) { return op_b(i, 1); }
2429
+
2430
+static int op_bx(Mem srcreg, bool blx, bool test_thumb)
2431
+{
2432
+	GpVar dst = c.newGpVar(kX86VarTypeGpd);
2433
+	c.mov(dst, srcreg);
2434
+
2435
+	if (test_thumb)
2436
+	{
2437
+		GpVar mask = c.newGpVar(kX86VarTypeGpd);
2438
+		GpVar thumb = dst;
2439
+		dst = c.newGpVar(kX86VarTypeGpd);
2440
+		c.mov(dst, thumb);
2441
+		c.and_(thumb, 1);
2442
+		c.lea(mask, ptr_abs(reinterpret_cast<void *>(0xFFFFFFFC), thumb.r64(), kScale2Times));
2443
+		c.shl(thumb, 5);
2444
+		c.or_(cpu_ptr_byte(CPSR, 0), thumb.r8Lo());
2445
+		c.and_(dst, mask);
2446
+	}
2447
+	else
2448
+		c.and_(dst, 0xFFFFFFFC);
2449
+
2450
+	if (blx)
2451
+		c.mov(reg_ptr(14), bb_next_instruction);
2452
+	c.mov(cpu_ptr(instruct_adr), dst);
2453
+	return 1;
2454
+}
2455
+
2456
+// TODO: exeption when Rm=PC
2457
+static int OP_BX(uint32_t i) { return op_bx(reg_pos_ptr(0), 0, 1); }
2458
+static int OP_BLX_REG(uint32_t i) { return op_bx(reg_pos_ptr(0), 1, 1); }
2459
+
2460
+// -----------------------------------------------------------------------------
2461
+//   CLZ
2462
+// -----------------------------------------------------------------------------
2463
+static int OP_CLZ(uint32_t i)
2464
+{
2465
+	GpVar res = c.newGpVar(kX86VarTypeGpd);
2466
+	c.mov(res, 0x3F);
2467
+	c.bsr(res, reg_pos_ptr(0));
2468
+	c.xor_(res, 0x1F);
2469
+	c.mov(reg_pos_ptr(12), res);
2470
+	
2471
+	return 1;
2472
+}
2473
+
2474
+// -----------------------------------------------------------------------------
2475
+//   MCR / MRC
2476
+// -----------------------------------------------------------------------------
2477
+#define maskPrecalc \
2478
+{ \
2479
+	X86CompilerFuncCall *ctxM = c.call(reinterpret_cast<void *>(maskPrecalc)); \
2480
+	ctxM->setPrototype(ASMJIT_CALL_CONV, FuncBuilder0<void>()); \
2481
+}
2482
+static int OP_MCR(uint32_t i)
2483
+{
2484
+	if (PROCNUM == ARMCPU_ARM7)
2485
+		return 0;
2486
+
2487
+	uint32_t cpnum = REG_POS(i, 8);
2488
+	if (cpnum != 15)
2489
+	{
2490
+		// TODO - exception?
2491
+		printf("JIT: MCR P%i, 0, R%i, C%i, C%i, %i, %i (don't allocated coprocessor)\n", cpnum, REG_POS(i, 12), REG_POS(i, 16), REG_POS(i, 0), (i >> 21) & 0x7, (i >> 5) & 0x7);
2492
+		return 2;
2493
+	}
2494
+	if (REG_POS(i, 12) == 15)
2495
+	{
2496
+		printf("JIT: MCR Rd=R15\n");
2497
+		return 2;
2498
+	}
2499
+
2500
+	uint8_t CRn =  REG_POS(i, 16); // Cn
2501
+	uint8_t CRm =  REG_POS(i, 0); // Cm
2502
+	uint8_t opcode1 = (i >> 21) & 0x7; // opcode1
2503
+	uint8_t opcode2 = (i >> 5) & 0x7; // opcode2
2504
+
2505
+	GpVar bb_cp15 = c.newGpVar(kX86VarTypeGpz);
2506
+	GpVar data = c.newGpVar(kX86VarTypeGpd);
2507
+	c.mov(data, reg_pos_ptr(12));
2508
+	c.mov(bb_cp15, reinterpret_cast<uintptr_t>(&cp15));
2509
+
2510
+	bool bUnknown = false;
2511
+	switch (CRn)
2512
+	{
2513
+		case 1:
2514
+			if (!opcode1 && !opcode2 && !CRm)
2515
+			{
2516
+				GpVar tmp = c.newGpVar(kX86VarTypeGpd);
2517
+				// On the NDS bit0,2,7,12..19 are R/W, Bit3..6 are always set, all other bits are always zero.
2518
+				//MMU.ARM9_RW_MODE = BIT7(val);
2519
+				GpVar bb_mmu = c.newGpVar(kX86VarTypeGpz);
2520
+				c.mov(bb_mmu, reinterpret_cast<uintptr_t>(&MMU));
2521
+				Mem rwmode = mmu_ptr_byte(ARM9_RW_MODE);
2522
+				Mem ldtbit = cpu_ptr_byte(LDTBit, 0);
2523
+				c.test(data, 1 << 7);
2524
+				c.setnz(rwmode);
2525
+				//cpu->intVector = 0xFFFF0000 * (BIT13(val));
2526
+				GpVar vec = c.newGpVar(kX86VarTypeGpd);
2527
+				c.mov(tmp, 0xFFFF0000);
2528
+				c.xor_(vec, vec);
2529
+				c.test(data, 1 << 13);
2530
+				c.cmovnz(vec, tmp);
2531
+				c.mov(cpu_ptr(intVector), vec);
2532
+				//cpu->LDTBit = !BIT15(val); //TBit
2533
+				c.test(data, 1 << 15);
2534
+				c.setz(ldtbit);
2535
+				//ctrl = (val & 0x000FF085) | 0x00000078;
2536
+				c.and_(data, 0x000FF085);
2537
+				c.or_(data, 0x00000078);
2538
+				c.mov(cp15_ptr(ctrl), data);
2539
+				break;
2540
+			}
2541
+			bUnknown = true;
2542
+			break;
2543
+		case 2:
2544
+			if (!opcode1 && !CRm)
2545
+			{
2546
+				switch (opcode2)
2547
+				{
2548
+					case 0:
2549
+						// DCConfig = val;
2550
+						c.mov(cp15_ptr(DCConfig), data);
2551
+						break;
2552
+					case 1:
2553
+						// ICConfig = val;
2554
+						c.mov(cp15_ptr(ICConfig), data);
2555
+						break;
2556
+					default:
2557
+						bUnknown = true;
2558
+						break;
2559
+				}
2560
+				break;
2561
+			}
2562
+			bUnknown = true;
2563
+			break;
2564
+		case 3:
2565
+			if (!opcode1 && !opcode2 && !CRm)
2566
+			{
2567
+				//writeBuffCtrl = val;
2568
+				c.mov(cp15_ptr(writeBuffCtrl), data);
2569
+				break;
2570
+			}
2571
+			bUnknown = true;
2572
+			break;
2573
+		case 5:
2574
+			if (!opcode1 && !CRm)
2575
+			{
2576
+				switch (opcode2)
2577
+				{
2578
+					case 2:
2579
+						//DaccessPerm = val;
2580
+						c.mov(cp15_ptr(DaccessPerm), data);
2581
+						maskPrecalc;
2582
+						break;
2583
+					case 3:
2584
+						//IaccessPerm = val;
2585
+						c.mov(cp15_ptr(IaccessPerm), data);
2586
+						maskPrecalc;
2587
+						break;
2588
+					default:
2589
+						bUnknown = true;
2590
+						break;
2591
+				}
2592
+			}
2593
+			bUnknown = true;
2594
+			break;
2595
+		case 6:
2596
+			if (!opcode1 && !opcode2)
2597
+			{
2598
+				switch (CRm)
2599
+				{
2600
+					case 0:
2601
+						//protectBaseSize0 = val;
2602
+						c.mov(cp15_ptr(protectBaseSize0), data);
2603
+						maskPrecalc;
2604
+						break;
2605
+					case 1:
2606
+						//protectBaseSize1 = val;
2607
+						c.mov(cp15_ptr(protectBaseSize1), data);
2608
+						maskPrecalc;
2609
+						break;
2610
+					case 2:
2611
+						//protectBaseSize2 = val;
2612
+						c.mov(cp15_ptr(protectBaseSize2), data);
2613
+						maskPrecalc;
2614
+						break;
2615
+					case 3:
2616
+						//protectBaseSize3 = val;
2617
+						c.mov(cp15_ptr(protectBaseSize3), data);
2618
+						maskPrecalc;
2619
+						break;
2620
+					case 4:
2621
+						//protectBaseSize4 = val;
2622
+						c.mov(cp15_ptr(protectBaseSize4), data);
2623
+						maskPrecalc;
2624
+						break;
2625
+					case 5:
2626
+						//protectBaseSize5 = val;
2627
+						c.mov(cp15_ptr(protectBaseSize5), data);
2628
+						maskPrecalc;
2629
+						break;
2630
+					case 6:
2631
+						//protectBaseSize6 = val;
2632
+						c.mov(cp15_ptr(protectBaseSize6), data);
2633
+						maskPrecalc;
2634
+						break;
2635
+					case 7:
2636
+						//protectBaseSize7 = val;
2637
+						c.mov(cp15_ptr(protectBaseSize7), data);
2638
+						maskPrecalc;
2639
+						break;
2640
+					default:
2641
+						bUnknown = true;
2642
+						break;
2643
+				}
2644
+			}
2645
+			bUnknown = true;
2646
+			break;
2647
+		case 7:
2648
+			if (!CRm && !opcode1 && opcode2 == 4)
2649
+			{
2650
+				//CP15wait4IRQ;
2651
+				c.mov(cpu_ptr(waitIRQ), true);
2652
+				c.mov(cpu_ptr(halt_IE_and_IF), true);
2653
+				//IME set deliberately omitted: only SWI sets IME to 1
2654
+				break;
2655
+			}
2656
+			bUnknown = true;
2657
+			break;
2658
+		case 9:
2659
+			if (!opcode1)
2660
+			{
2661
+				switch (CRm)
2662
+				{
2663
+					case 0:
2664
+						switch (opcode2)
2665
+						{
2666
+							case 0:
2667
+								//DcacheLock = val;
2668
+								c.mov(cp15_ptr(DcacheLock), data);
2669
+								break;
2670
+							case 1:
2671
+								//IcacheLock = val;
2672
+								c.mov(cp15_ptr(IcacheLock), data);
2673
+								break;
2674
+							default:
2675
+								bUnknown = true;
2676
+								break;
2677
+						}
2678
+					case 1:
2679
+						switch (opcode2)
2680
+						{
2681
+							case 0:
2682
+							{
2683
+								//MMU.DTCMRegion = DTCMRegion = val & 0x0FFFF000;
2684
+								c.and_(data, 0x0FFFF000);
2685
+								GpVar bb_mmu = c.newGpVar(kX86VarTypeGpz);
2686
+								c.mov(bb_mmu, reinterpret_cast<uintptr_t>(&MMU));
2687
+								c.mov(mmu_ptr(DTCMRegion), data);
2688
+								c.mov(cp15_ptr(DTCMRegion), data);
2689
+								break;
2690
+							}
2691
+							case 1:
2692
+							{
2693
+								//ITCMRegion = val;
2694
+								//ITCM base is not writeable!
2695
+								GpVar bb_mmu = c.newGpVar(kX86VarTypeGpz);
2696
+								c.mov(bb_mmu, reinterpret_cast<uintptr_t>(&MMU));
2697
+								c.mov(mmu_ptr(ITCMRegion), 0);
2698
+								c.mov(cp15_ptr(ITCMRegion), data);
2699
+								break;
2700
+							}
2701
+							default:
2702
+								bUnknown = true;
2703
+								break;
2704
+						}
2705
+				}
2706
+				break;
2707
+			}
2708
+			bUnknown = true;
2709
+			break;
2710
+		default:
2711
+			bUnknown = true;
2712
+	}
2713
+
2714
+	if (bUnknown)
2715
+	{
2716
+		//printf("Unknown MCR command: MRC P15, 0, R%i, C%i, C%i, %i, %i\n", REG_POS(i, 12), CRn, CRm, opcode1, opcode2);
2717
+		return 1;
2718
+	}
2719
+
2720
+	return 1;
2721
+}
2722
+
2723
+static int OP_MRC(uint32_t i)
2724
+{
2725
+	if (PROCNUM == ARMCPU_ARM7)
2726
+		return 0;
2727
+
2728
+	uint32_t cpnum = REG_POS(i, 8);
2729
+	if (cpnum != 15)
2730
+	{
2731
+		printf("MRC P%i, 0, R%i, C%i, C%i, %i, %i (don't allocated coprocessor)\n", cpnum, REG_POS(i, 12), REG_POS(i, 16), REG_POS(i, 0), (i>>21)&0x7, (i>>5)&0x7);
2732
+		return 2;
2733
+	}
2734
+
2735
+	uint8_t CRn =  REG_POS(i, 16); // Cn
2736
+	uint8_t CRm =  REG_POS(i, 0); // Cm
2737
+	uint8_t opcode1 = (i >> 21) & 0x7; // opcode1
2738
+	uint8_t opcode2 = (i >> 5) & 0x7; // opcode2
2739
+
2740
+	GpVar bb_cp15 = c.newGpVar(kX86VarTypeGpz);
2741
+	GpVar data = c.newGpVar(kX86VarTypeGpd);
2742
+
2743
+	c.mov(bb_cp15, (uintptr_t)&cp15);
2744
+	
2745
+	bool bUnknown = false;
2746
+	switch (CRn)
2747
+	{
2748
+		case 0:
2749
+			if (!opcode1 && !CRm)
2750
+			{
2751
+				switch (opcode2)
2752
+				{
2753
+					case 1:
2754
+						// *R = cacheType;
2755
+						c.mov(data, cp15_ptr(cacheType));
2756
+						break;
2757
+					case 2:
2758
+						// *R = TCMSize;
2759
+						c.mov(data, cp15_ptr(TCMSize));
2760
+						break;
2761
+					default:		// FIXME
2762
+						// *R = IDCode;
2763
+						c.mov(data, cp15_ptr(IDCode));
2764
+						break;
2765
+				}
2766
+				break;
2767
+			}
2768
+			bUnknown = true;
2769
+			break;
2770
+		case 1:
2771
+			if (!opcode1 && !opcode2 && !CRm)
2772
+			{
2773
+				// *R = ctrl;
2774
+				c.mov(data, cp15_ptr(ctrl));
2775
+				break;
2776
+			}
2777
+			bUnknown = true;
2778
+			break;
2779
+		case 2:
2780
+			if (!opcode1 && !CRm)
2781
+			{
2782
+				switch (opcode2)
2783
+				{
2784
+					case 0:
2785
+						// *R = DCConfig;
2786
+						c.mov(data, cp15_ptr(DCConfig));
2787
+						break;
2788
+					case 1:
2789
+						// *R = ICConfig;
2790
+						c.mov(data, cp15_ptr(ICConfig));
2791
+						break;
2792
+					default:
2793
+						bUnknown = true;
2794
+						break;
2795
+				}
2796
+				break;
2797
+			}
2798
+			bUnknown = true;
2799
+			break;
2800
+		case 3:
2801
+			if (!opcode1 && !opcode2 && !CRm)
2802
+			{
2803
+				// *R = writeBuffCtrl;
2804
+				c.mov(data, cp15_ptr(writeBuffCtrl));
2805
+				break;
2806
+			}
2807
+			bUnknown = true;
2808
+			break;
2809
+		case 5:
2810
+			if (!opcode1 && !CRm)
2811
+			{
2812
+				switch (opcode2)
2813
+				{
2814
+					case 2:
2815
+						// *R = DaccessPerm;
2816
+						c.mov(data, cp15_ptr(DaccessPerm));
2817
+						break;
2818
+					case 3:
2819
+						// *R = IaccessPerm;
2820
+						c.mov(data, cp15_ptr(IaccessPerm));
2821
+						break;
2822
+					default:
2823
+						bUnknown = true;
2824
+						break;
2825
+				}
2826
+				break;
2827
+			}
2828
+			bUnknown = true;
2829
+			break;
2830
+		case 6:
2831
+			if (!opcode1 && !opcode2)
2832
+			{
2833
+				switch(CRm)
2834
+				{
2835
+					case 0:
2836
+						// *R = protectBaseSize0;
2837
+						c.mov(data, cp15_ptr(protectBaseSize0));
2838
+						break;
2839
+					case 1:
2840
+						// *R = protectBaseSize1;
2841
+						c.mov(data, cp15_ptr(protectBaseSize1));
2842
+						break;
2843
+					case 2:
2844
+						// *R = protectBaseSize2;
2845
+						c.mov(data, cp15_ptr(protectBaseSize2));
2846
+						break;
2847
+					case 3:
2848
+						// *R = protectBaseSize3;
2849
+						c.mov(data, cp15_ptr(protectBaseSize3));
2850
+						break;
2851
+					case 4:
2852
+						// *R = protectBaseSize4;
2853
+						c.mov(data, cp15_ptr(protectBaseSize4));
2854
+						break;
2855
+					case 5:
2856
+						// *R = protectBaseSize5;
2857
+						c.mov(data, cp15_ptr(protectBaseSize5));
2858
+						break;
2859
+					case 6:
2860
+						// *R = protectBaseSize6;
2861
+						c.mov(data, cp15_ptr(protectBaseSize6));
2862
+						break;
2863
+					case 7:
2864
+						// *R = protectBaseSize7;
2865
+						c.mov(data, cp15_ptr(protectBaseSize7));
2866
+						break;
2867
+					default:
2868
+						bUnknown = true;
2869
+						break;
2870
+				}
2871
+				break;
2872
+			}
2873
+			bUnknown = true;
2874
+			break;
2875
+		case 9:
2876
+			if (!opcode1)
2877
+			{
2878
+				switch (CRm)
2879
+				{
2880
+					case 0:
2881
+						switch (opcode2)
2882
+						{
2883
+							case 0:
2884
+								//*R = DcacheLock;
2885
+								c.mov(data, cp15_ptr(DcacheLock));
2886
+								break;
2887
+							case 1:
2888
+								//*R = IcacheLock;
2889
+								c.mov(data, cp15_ptr(IcacheLock));
2890
+								break;
2891
+							default:
2892
+								bUnknown = true;
2893
+								break;
2894
+						}
2895
+					case 1:
2896
+						switch (opcode2)
2897
+						{
2898
+							case 0:
2899
+								//*R = DTCMRegion;
2900
+								c.mov(data, cp15_ptr(DTCMRegion));
2901
+								break;
2902
+							case 1:
2903
+								//*R = ITCMRegion;
2904
+								c.mov(data, cp15_ptr(ITCMRegion));
2905
+								break;
2906
+							default:
2907
+								bUnknown = true;
2908
+								break;
2909
+						}
2910
+				}
2911
+				break;
2912
+			}
2913
+			bUnknown = true;
2914
+			break;
2915
+		default:
2916
+			bUnknown = true;
2917
+	}
2918
+
2919
+	if (bUnknown)
2920
+	{
2921
+		//printf("Unknown MRC command: MRC P15, 0, R%i, C%i, C%i, %i, %i\n", REG_POS(i, 12), CRn, CRm, opcode1, opcode2);
2922
+		return 1;
2923
+	}
2924
+
2925
+	if (REG_POS(i, 12) == 15) // set NZCV
2926
+	{
2927
+		//CPSR.bits.N = BIT31(data);
2928
+		//CPSR.bits.Z = BIT30(data);
2929
+		//CPSR.bits.C = BIT29(data);
2930
+		//CPSR.bits.V = BIT28(data);
2931
+		c.and_(data, 0xF0000000);
2932
+		c.and_(cpu_ptr(CPSR), 0x0FFFFFFF);
2933
+		c.or_(cpu_ptr(CPSR), data);
2934
+	}
2935
+	else
2936
+		c.mov(reg_pos_ptr(12), data);
2937
+
2938
+	return 1;
2939
+}
2940
+
2941
+uint32_t op_swi(uint8_t swinum)
2942
+{
2943
+	if (cpu->swi_tab)
2944
+	{
2945
+#if defined(_M_X64) || defined(__x86_64__)
2946
+		// TODO:
2947
+		return 0;
2948
+#else
2949
+		X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(ARM_swi_tab[PROCNUM][swinum]));
2950
+		ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder0<uint32_t>());
2951
+		ctx->setReturn(bb_cycles);
2952
+		c.add(bb_cycles, 3);
2953
+		return 1;
2954
+#endif
2955
+	}
2956
+
2957
+	GpVar oldCPSR = c.newGpVar(kX86VarTypeGpd);
2958
+	GpVar mode = c.newGpVar(kX86VarTypeGpd);
2959
+	Mem CPSR = cpu_ptr(CPSR.val);
2960
+	JIT_COMMENT("store CPSR to x86 stack");
2961
+	c.mov(oldCPSR, CPSR);
2962
+	JIT_COMMENT("enter SVC mode");
2963
+	c.mov(mode, imm(SVC));
2964
+	X86CompilerFuncCall* ctx = c.call(reinterpret_cast<void *>(armcpu_switchMode));
2965
+	ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<void, void *, uint8_t>());
2966
+	ctx->setArgument(0, bb_cpu);
2967
+	ctx->setArgument(1, mode);
2968
+	c.unuse(mode);
2969
+	JIT_COMMENT("store next instruction address to R14");
2970
+	c.mov(reg_ptr(14), bb_next_instruction);
2971
+	JIT_COMMENT("save old CPSR as new SPSR");
2972
+	c.mov(cpu_ptr(SPSR.val), oldCPSR);
2973
+	JIT_COMMENT("CPSR: clear T, set I");
2974
+	GpVar _cpsr = c.newGpVar(kX86VarTypeGpd);
2975
+	c.mov(_cpsr, CPSR);
2976
+	c.and_(_cpsr, ~(1 << 5)); /* clear T */
2977
+	c.or_(_cpsr, 1 << 7); /* set I */
2978
+	c.mov(CPSR, _cpsr);
2979
+	c.unuse(_cpsr);
2980
+	JIT_COMMENT("set next instruction");
2981
+	c.mov(cpu_ptr(next_instruction), imm(cpu->intVector + 0x08));
2982
+	
2983
+	return 1;
2984
+}
2985
+
2986
+static int OP_SWI(uint32_t i) { return op_swi((i >> 16) & 0x1F); }
2987
+
2988
+// -----------------------------------------------------------------------------
2989
+//   BKPT
2990
+// -----------------------------------------------------------------------------
2991
+static int OP_BKPT(uint32_t i) { printf("JIT: unimplemented OP_BKPT\n"); return 0; }
2992
+
2993
+// -----------------------------------------------------------------------------
2994
+//   THUMB
2995
+// -----------------------------------------------------------------------------
2996
+#define OP_SHIFTS_IMM(x86inst) \
2997
+	GpVar rcf = c.newGpVar(kX86VarTypeGpd); \
2998
+	uint8_t cf_change = 1; \
2999
+	uint32_t rhs = (i >> 6) & 0x1F; \
3000
+	if (_REG_NUM(i, 0) == _REG_NUM(i, 3)) \
3001
+		c.x86inst(reg_pos_thumb(0), rhs); \
3002
+	else \
3003
+	{ \
3004
+		GpVar lhs = c.newGpVar(kX86VarTypeGpd); \
3005
+		c.mov(lhs, reg_pos_thumb(3)); \
3006
+		c.x86inst(lhs, rhs); \
3007
+		c.mov(reg_pos_thumb(0), lhs); \
3008
+		c.unuse(lhs); \
3009
+	} \
3010
+	c.setc(rcf.r8Lo()); \
3011
+	SET_NZC; \
3012
+	return 1;
3013
+
3014
+#define OP_SHIFTS_REG(x86inst, bit) \
3015
+	uint8_t cf_change = 1; \
3016
+	GpVar imm = c.newGpVar(kX86VarTypeGpz); \
3017
+	GpVar rcf = c.newGpVar(kX86VarTypeGpd); \
3018
+	Label __eq32 = c.newLabel(); \
3019
+	Label __ls32 = c.newLabel(); \
3020
+	Label __zero = c.newLabel(); \
3021
+	Label __done = c.newLabel(); \
3022
+\
3023
+	c.mov(imm, reg_pos_thumb(3)); \
3024
+	c.and_(imm, 0xFF); \
3025
+	c.jz(__zero); \
3026
+	c.cmp(imm, 32); \
3027
+	c.jl(__ls32); \
3028
+	c.je(__eq32); \
3029
+	/* imm > 32 */ \
3030
+	c.mov(reg_pos_thumb(0), 0); \
3031
+	SET_NZC_SHIFTS_ZERO(0); \
3032
+	c.jmp(__done); \
3033
+	/* imm == 32 */ \
3034
+	c.bind(__eq32); \
3035
+	c.test(reg_pos_thumb(0), 1 << bit); \
3036
+	c.setnz(rcf.r8Lo()); \
3037
+	c.mov(reg_pos_thumb(0), 0); \
3038
+	SET_NZC_SHIFTS_ZERO(1); \
3039
+	c.jmp(__done); \
3040
+	/* imm == 0 */ \
3041
+	c.bind(__zero); \
3042
+	c.cmp(reg_pos_thumb(0), 0); \
3043
+	SET_NZ(0); \
3044
+	c.jmp(__done); \
3045
+	/* imm < 32 */ \
3046
+	c.bind(__ls32); \
3047
+	c.x86inst(reg_pos_thumb(0), imm); \
3048
+	c.setc(rcf.r8Lo()); \
3049
+	SET_NZC; \
3050
+	c.bind(__done); \
3051
+	return 1;
3052
+
3053
+#define OP_LOGIC(x86inst, _conv) \
3054
+	GpVar rhs = c.newGpVar(kX86VarTypeGpd); \
3055
+	c.mov(rhs, reg_pos_thumb(3)); \
3056
+	if (_conv == 1) \
3057
+		c.not_(rhs); \
3058
+	c.x86inst(reg_pos_thumb(0), rhs); \
3059
+	SET_NZ(0); \
3060
+	return 1;
3061
+
3062
+// -----------------------------------------------------------------------------
3063
+//   LSL / LSR / ASR / ROR
3064
+// -----------------------------------------------------------------------------
3065
+static int OP_LSL_0(uint32_t i)
3066
+{
3067
+	if (_REG_NUM(i, 0) == _REG_NUM(i, 3))
3068
+		c.cmp(reg_pos_thumb(0), 0);
3069
+	else
3070
+	{
3071
+		GpVar rhs = c.newGpVar(kX86VarTypeGpd);
3072
+		c.mov(rhs, reg_pos_thumb(3));
3073
+		c.mov(reg_pos_thumb(0), rhs);
3074
+		c.cmp(rhs, 0);
3075
+	}
3076
+	SET_NZ(0);
3077
+	return 1;
3078
+}
3079
+static int OP_LSL(uint32_t i) { OP_SHIFTS_IMM(shl); }
3080
+static int OP_LSL_REG(uint32_t i) { OP_SHIFTS_REG(shl, 0); }
3081
+static int OP_LSR_0(uint32_t i)
3082
+{
3083
+	GpVar rcf = c.newGpVar(kX86VarTypeGpd);
3084
+	c.test(reg_pos_thumb(3), 1 << 31);
3085
+	c.setnz(rcf.r8Lo());
3086
+	SET_NZC_SHIFTS_ZERO(1);
3087
+	c.mov(reg_pos_thumb(0), 0);
3088
+	return 1;
3089
+}
3090
+static int OP_LSR(uint32_t i) { OP_SHIFTS_IMM(shr); }
3091
+static int OP_LSR_REG(uint32_t i) { OP_SHIFTS_REG(shr, 31); }
3092
+static int OP_ASR_0(uint32_t i)
3093
+{
3094
+	uint8_t cf_change = 1;
3095
+	GpVar rcf = c.newGpVar(kX86VarTypeGpd);
3096
+	GpVar rhs = c.newGpVar(kX86VarTypeGpd);
3097
+	if (_REG_NUM(i, 0) == _REG_NUM(i, 3))
3098
+		c.sar(reg_pos_thumb(0), 31);
3099
+	else
3100
+	{
3101
+		c.mov(rhs, reg_pos_thumb(3));
3102
+		c.sar(rhs, 31);
3103
+		c.mov(reg_pos_thumb(0), rhs);
3104
+	}
3105
+	c.sets(rcf.r8Lo());
3106
+	SET_NZC;
3107
+	return 1;
3108
+}
3109
+static int OP_ASR(uint32_t i) { OP_SHIFTS_IMM(sar); }
3110
+static int OP_ASR_REG(uint32_t i) 
3111
+{
3112
+	uint8_t cf_change = 1;
3113
+	Label __gr0 = c.newLabel();
3114
+	Label __lt32 = c.newLabel();
3115
+	Label __done = c.newLabel();
3116
+	Label __setFlags = c.newLabel();
3117
+	GpVar imm = c.newGpVar(kX86VarTypeGpz);
3118
+	GpVar rcf = c.newGpVar(kX86VarTypeGpd);
3119
+	c.mov(imm, reg_pos_thumb(3));
3120
+	c.and_(imm, 0xFF);
3121
+	c.jnz(__gr0);
3122
+	/* imm == 0 */
3123
+	c.cmp(reg_pos_thumb(0), 0);
3124
+	SET_NZ(0);
3125
+	c.jmp(__done);
3126
+	/* imm > 0 */
3127
+	c.bind(__gr0);
3128
+	c.cmp(imm, 32);
3129
+	c.jl(__lt32);
3130
+	/* imm > 31 */
3131
+	c.sar(reg_pos_thumb(0), 31);
3132
+	c.sets(rcf.r8Lo());
3133
+	c.jmp(__setFlags);
3134
+	/* imm < 32 */
3135
+	c.bind(__lt32);
3136
+	c.sar(reg_pos_thumb(0), imm);
3137
+	c.setc(rcf.r8Lo());
3138
+	c.bind(__setFlags);
3139
+	SET_NZC;
3140
+	c.bind(__done);
3141
+	return 1;
3142
+}
3143
+
3144
+// -----------------------------------------------------------------------------
3145
+//   ROR
3146
+// -----------------------------------------------------------------------------
3147
+static int OP_ROR_REG(uint32_t i)
3148
+{
3149
+	uint8_t cf_change = 1;
3150
+	GpVar imm = c.newGpVar(kX86VarTypeGpz);
3151
+	GpVar rcf = c.newGpVar(kX86VarTypeGpd);
3152
+	Label __zero = c.newLabel();
3153
+	Label __zero_1F = c.newLabel();
3154
+	Label __done = c.newLabel();
3155
+
3156
+	c.mov(imm, reg_pos_thumb(3));
3157
+	c.and_(imm, 0xFF);
3158
+	c.jz(__zero);
3159
+	c.and_(imm, 0x1F);
3160
+	c.jz(__zero_1F);
3161
+	c.ror(reg_pos_thumb(0), imm);
3162
+	c.setc(rcf.r8Lo());
3163
+	SET_NZC;
3164
+	c.jmp(__done);
3165
+	/* imm & 0x1F == 0 */
3166
+	c.bind(__zero_1F);
3167
+	c.cmp(reg_pos_thumb(0), 0);
3168
+	c.sets(rcf.r8Lo());
3169
+	SET_NZC;
3170
+	c.jmp(__done);
3171
+	/* imm == 0 */
3172
+	c.bind(__zero);
3173
+	c.cmp(reg_pos_thumb(0), 0);
3174
+	SET_NZ(0);
3175
+	c.bind(__done);
3176
+
3177
+	return 1;
3178
+}
3179
+
3180
+// -----------------------------------------------------------------------------
3181
+//   AND / ORR / EOR / BIC
3182
+// -----------------------------------------------------------------------------
3183
+static int OP_AND(uint32_t i) { OP_LOGIC(and_, 0); }
3184
+static int OP_ORR(uint32_t i) { OP_LOGIC(or_,  0); }
3185
+static int OP_EOR(uint32_t i) { OP_LOGIC(xor_, 0); }
3186
+static int OP_BIC(uint32_t i) { OP_LOGIC(and_, 1); }
3187
+
3188
+// -----------------------------------------------------------------------------
3189
+//   NEG
3190
+// -----------------------------------------------------------------------------
3191
+static int OP_NEG(uint32_t i)
3192
+{
3193
+	if (_REG_NUM(i, 0) == _REG_NUM(i, 3))
3194
+		c.neg(reg_pos_thumb(0));
3195
+	else
3196
+	{
3197
+		GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3198
+		c.mov(tmp, reg_pos_thumb(3));
3199
+		c.neg(tmp);
3200
+		c.mov(reg_pos_thumb(0), tmp);
3201
+	}
3202
+	SET_NZCV(1);
3203
+	return 1;
3204
+}
3205
+
3206
+//-----------------------------------------------------------------------------
3207
+//   ADD
3208
+//-----------------------------------------------------------------------------
3209
+static int OP_ADD_IMM3(uint32_t i) 
3210
+{
3211
+	uint32_t imm3 = (i >> 6) & 0x07;
3212
+
3213
+	if (!imm3) // mov 2
3214
+	{
3215
+		GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3216
+		c.mov(tmp, reg_pos_thumb(3));
3217
+		c.mov(reg_pos_thumb(0), tmp);
3218
+		c.cmp(tmp, 0);
3219
+		SET_NZ(1);
3220
+		return 1;
3221
+	}
3222
+	if (_REG_NUM(i, 0) == _REG_NUM(i, 3))
3223
+		c.add(reg_pos_thumb(0), imm3);
3224
+	else
3225
+	{
3226
+		GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3227
+		c.mov(tmp, reg_pos_thumb(3));
3228
+		c.add(tmp, imm3);
3229
+		c.mov(reg_pos_thumb(0), tmp);
3230
+	}
3231
+	SET_NZCV(0);
3232
+	return 1;
3233
+}
3234
+static int OP_ADD_IMM8(uint32_t i)
3235
+{
3236
+	c.add(reg_pos_thumb(8), (i & 0xFF));
3237
+	SET_NZCV(0);
3238
+
3239
+	return 1; 
3240
+}
3241
+static int OP_ADD_REG(uint32_t i) 
3242
+{
3243
+	//cpu->R[REG_NUM(i, 0)] = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
3244
+	if (_REG_NUM(i, 0) == _REG_NUM(i, 3))
3245
+	{
3246
+		GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3247
+		c.mov(tmp, reg_pos_thumb(6));
3248
+		c.add(reg_pos_thumb(0), tmp);
3249
+	}
3250
+	else
3251
+	{
3252
+		if (_REG_NUM(i, 0) == _REG_NUM(i, 6))
3253
+		{
3254
+			GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3255
+			c.mov(tmp, reg_pos_thumb(3));
3256
+			c.add(reg_pos_thumb(0), tmp);
3257
+		}
3258
+		else
3259
+		{
3260
+			GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3261
+			c.mov(tmp, reg_pos_thumb(3));
3262
+			c.add(tmp, reg_pos_thumb(6));
3263
+			c.mov(reg_pos_thumb(0), tmp);
3264
+		}
3265
+	}
3266
+	SET_NZCV(0);
3267
+	return 1; 
3268
+}
3269
+static int OP_ADD_SPE(uint32_t i)
3270
+{
3271
+	uint32_t Rd = _REG_NUM(i, 0) | ((i >> 4) & 8);
3272
+	//cpu->R[Rd] += cpu->R[REG_POS(i, 3)];
3273
+	GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3274
+	c.mov(tmp, reg_ptr(Rd));
3275
+	c.add(tmp, reg_pos_ptr(3));
3276
+	c.mov(reg_ptr(Rd), tmp);
3277
+
3278
+	if (Rd == 15)
3279
+		c.mov(cpu_ptr(next_instruction), tmp);
3280
+
3281
+	return 1;
3282
+}
3283
+
3284
+static int OP_ADD_2PC(uint32_t i)
3285
+{
3286
+	uint32_t imm = (i & 0xFF) << 2;
3287
+	c.mov(reg_pos_thumb(8), (bb_r15 & 0xFFFFFFFC) + imm);
3288
+	return 1;
3289
+}
3290
+
3291
+static int OP_ADD_2SP(uint32_t i)
3292
+{
3293
+	uint32_t imm = (i & 0xFF) << 2;
3294
+	//cpu->R[REG_NUM(i, 8)] = cpu->R[13] + ((i&0xFF)<<2);
3295
+	GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3296
+	c.mov(tmp, reg_ptr(13));
3297
+	if (imm)
3298
+		c.add(tmp, imm);
3299
+	c.mov(reg_pos_thumb(8), tmp);
3300
+
3301
+	return 1;
3302
+}
3303
+
3304
+// -----------------------------------------------------------------------------
3305
+//   SUB
3306
+// -----------------------------------------------------------------------------
3307
+static int OP_SUB_IMM3(uint32_t i)
3308
+{
3309
+	uint32_t imm3 = (i >> 6) & 0x07;
3310
+
3311
+	// cpu->R[REG_NUM(i, 0)] = cpu->R[REG_NUM(i, 3)] - imm3;
3312
+	if (_REG_NUM(i, 0) == _REG_NUM(i, 3))
3313
+		c.sub(reg_pos_thumb(0), imm3);
3314
+	else
3315
+	{
3316
+		GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3317
+		c.mov(tmp, reg_pos_thumb(3));
3318
+		c.sub(tmp, imm3);
3319
+		c.mov(reg_pos_thumb(0), tmp);
3320
+	}
3321
+	SET_NZCV(1);
3322
+	return 1;
3323
+}
3324
+static int OP_SUB_IMM8(uint32_t i)
3325
+{
3326
+	//cpu->R[REG_NUM(i, 8)] -= imm8;
3327
+	c.sub(reg_pos_thumb(8), i & 0xFF);
3328
+	SET_NZCV(1);
3329
+	return 1; 
3330
+}
3331
+static int OP_SUB_REG(uint32_t i)
3332
+{
3333
+	// cpu->R[REG_NUM(i, 0)] = cpu->R[REG_NUM(i, 3)] - cpu->R[REG_NUM(i, 6)];
3334
+	if (_REG_NUM(i, 0) == _REG_NUM(i, 3))
3335
+	{
3336
+		GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3337
+		c.mov(tmp, reg_pos_thumb(6));
3338
+		c.sub(reg_pos_thumb(0), tmp);
3339
+	}
3340
+	else
3341
+	{
3342
+		GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3343
+		c.mov(tmp, reg_pos_thumb(3));
3344
+		c.sub(tmp, reg_pos_thumb(6));
3345
+		c.mov(reg_pos_thumb(0), tmp);
3346
+	}
3347
+	SET_NZCV(1);
3348
+	return 1; 
3349
+}
3350
+
3351
+// -----------------------------------------------------------------------------
3352
+//   ADC
3353
+// -----------------------------------------------------------------------------
3354
+static int OP_ADC_REG(uint32_t i)
3355
+{
3356
+	GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3357
+	c.mov(tmp, reg_pos_thumb(3));
3358
+	GET_CARRY(0);
3359
+	c.adc(reg_pos_thumb(0), tmp);
3360
+	SET_NZCV(0);
3361
+	return 1;
3362
+}
3363
+
3364
+// -----------------------------------------------------------------------------
3365
+//   SBC
3366
+// -----------------------------------------------------------------------------
3367
+static int OP_SBC_REG(uint32_t i)
3368
+{
3369
+	GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3370
+	c.mov(tmp, reg_pos_thumb(3));
3371
+	GET_CARRY(1);
3372
+	c.sbb(reg_pos_thumb(0), tmp);
3373
+	SET_NZCV(1);
3374
+	return 1;
3375
+}
3376
+
3377
+// -----------------------------------------------------------------------------
3378
+//   MOV / MVN
3379
+// -----------------------------------------------------------------------------
3380
+static int OP_MOV_IMM8(uint32_t i)
3381
+{
3382
+	c.mov(reg_pos_thumb(8), i & 0xFF);
3383
+	c.cmp(reg_pos_thumb(8), 0);
3384
+	SET_NZ(0);
3385
+	return 1;
3386
+}
3387
+
3388
+static int OP_MOV_SPE(uint32_t i)
3389
+{
3390
+	uint32_t Rd = _REG_NUM(i, 0) | ((i >> 4) & 8);
3391
+	//cpu->R[Rd] = cpu->R[REG_POS(i, 3)];
3392
+	GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3393
+	c.mov(tmp, reg_pos_ptr(3));
3394
+	c.mov(reg_ptr(Rd), tmp);
3395
+	if (Rd == 15)
3396
+	{
3397
+		c.mov(cpu_ptr(next_instruction), tmp);
3398
+		bb_constant_cycles += 2;
3399
+	}
3400
+	
3401
+	return 1;
3402
+}
3403
+
3404
+static int OP_MVN(uint32_t i)
3405
+{
3406
+	GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3407
+	c.mov(tmp, reg_pos_thumb(3));
3408
+	c.not_(tmp);
3409
+	c.cmp(tmp, 0);
3410
+	c.mov(reg_pos_thumb(0), tmp);
3411
+	SET_NZ(0);
3412
+	return 1;
3413
+}
3414
+
3415
+// -----------------------------------------------------------------------------
3416
+//   MUL
3417
+// -----------------------------------------------------------------------------
3418
+static int OP_MUL_REG(uint32_t i)
3419
+{
3420
+	GpVar lhs = c.newGpVar(kX86VarTypeGpd);
3421
+	c.mov(lhs, reg_pos_thumb(0));
3422
+	c.imul(lhs, reg_pos_thumb(3));
3423
+	c.cmp(lhs, 0);
3424
+	c.mov(reg_pos_thumb(0), lhs);
3425
+	SET_NZ(0);
3426
+	if (PROCNUM == ARMCPU_ARM7)
3427
+		c.mov(bb_cycles, 4);
3428
+	else
3429
+		MUL_Mxx_END(lhs, 0, 1);
3430
+	return 1;
3431
+}
3432
+
3433
+// -----------------------------------------------------------------------------
3434
+//   CMP / CMN
3435
+// -----------------------------------------------------------------------------
3436
+static int OP_CMP_IMM8(uint32_t i)
3437
+{
3438
+	c.cmp(reg_pos_thumb(8), i & 0xFF);
3439
+	SET_NZCV(1);
3440
+	return 1;
3441
+}
3442
+
3443
+static int OP_CMP(uint32_t i)
3444
+{
3445
+	GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3446
+	c.mov(tmp, reg_pos_thumb(3));
3447
+	c.cmp(reg_pos_thumb(0), tmp);
3448
+	SET_NZCV(1);
3449
+	return 1;
3450
+}
3451
+
3452
+static int OP_CMP_SPE(uint32_t i)
3453
+{
3454
+	uint32_t Rn = (i & 7) | ((i >> 4) & 8);
3455
+	GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3456
+	c.mov(tmp, reg_pos_ptr(3));
3457
+	c.cmp(reg_ptr(Rn), tmp);
3458
+	SET_NZCV(1);
3459
+	return 1;
3460
+}
3461
+
3462
+static int OP_CMN(uint32_t i)
3463
+{
3464
+	GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3465
+	c.mov(tmp, reg_pos_thumb(0));
3466
+	c.add(tmp, reg_pos_thumb(3));
3467
+	SET_NZCV(0);
3468
+	return 1;
3469
+}
3470
+
3471
+// -----------------------------------------------------------------------------
3472
+//   TST
3473
+// -----------------------------------------------------------------------------
3474
+static int OP_TST(uint32_t i)
3475
+{
3476
+	GpVar tmp = c.newGpVar(kX86VarTypeGpd);
3477
+	c.mov(tmp, reg_pos_thumb(3));
3478
+	c.test(reg_pos_thumb(0), tmp);
3479
+	SET_NZ(0);
3480
+	return 1;
3481
+}
3482
+
3483
+// -----------------------------------------------------------------------------
3484
+//   STR / LDR / STRB / LDRB
3485
+// -----------------------------------------------------------------------------
3486
+#define STR_THUMB(mem_op, offset) \
3487
+	GpVar addr = c.newGpVar(kX86VarTypeGpd); \
3488
+	GpVar data = c.newGpVar(kX86VarTypeGpd); \
3489
+	uint32_t adr_first = cpu->R[_REG_NUM(i, 3)]; \
3490
+\
3491
+	c.mov(addr, reg_pos_thumb(3)); \
3492
+	if ((offset) != -1) \
3493
+	{ \
3494
+		if ((offset)) \
3495
+		{ \
3496
+			c.add(addr, static_cast<uint32_t>((offset))); \
3497
+			adr_first += static_cast<uint32_t>((offset)); \
3498
+		} \
3499
+	} \
3500
+	else \
3501
+	{ \
3502
+		c.add(addr, reg_pos_thumb(6)); \
3503
+		adr_first += cpu->R[_REG_NUM(i, 6)]; \
3504
+	} \
3505
+	c.mov(data, reg_pos_thumb(0)); \
3506
+	X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(mem_op##_tab[PROCNUM][classify_adr(adr_first, 1)])); \
3507
+	ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<void, uint32_t, uint32_t>()); \
3508
+	ctx->setArgument(0, addr); \
3509
+	ctx->setArgument(1, data); \
3510
+	ctx->setReturn(bb_cycles); \
3511
+	return 1;
3512
+
3513
+#define LDR_THUMB(mem_op, offset) \
3514
+	GpVar addr = c.newGpVar(kX86VarTypeGpd); \
3515
+	GpVar data = c.newGpVar(kX86VarTypeGpz); \
3516
+	uint32_t adr_first = cpu->R[_REG_NUM(i, 3)]; \
3517
+\
3518
+	c.mov(addr, reg_pos_thumb(3)); \
3519
+	if ((offset) != -1) \
3520
+	{ \
3521
+		if ((offset)) \
3522
+		{ \
3523
+			c.add(addr, static_cast<uint32_t>((offset))); \
3524
+			adr_first += static_cast<uint32_t>((offset)); \
3525
+		} \
3526
+	} \
3527
+	else \
3528
+	{ \
3529
+		c.add(addr, reg_pos_thumb(6)); \
3530
+		adr_first += cpu->R[_REG_NUM(i, 6)]; \
3531
+	} \
3532
+	c.lea(data, reg_pos_thumb(0)); \
3533
+	X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(mem_op##_tab[PROCNUM][classify_adr(adr_first, 0)])); \
3534
+	ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<void, uint32_t, uint32_t *>()); \
3535
+	ctx->setArgument(0, addr); \
3536
+	ctx->setArgument(1, data); \
3537
+	ctx->setReturn(bb_cycles); \
3538
+	return 1;
3539
+
3540
+static int OP_STRB_IMM_OFF(uint32_t i) { STR_THUMB(STRB, (i >> 6) & 0x1F); }
3541
+static int OP_LDRB_IMM_OFF(uint32_t i) { LDR_THUMB(LDRB, (i >> 6) & 0x1F); }
3542
+static int OP_STRB_REG_OFF(uint32_t i) { STR_THUMB(STRB, -1); } 
3543
+static int OP_LDRB_REG_OFF(uint32_t i) { LDR_THUMB(LDRB, -1); }
3544
+static int OP_LDRSB_REG_OFF(uint32_t i) { LDR_THUMB(LDRSB, -1); }
3545
+
3546
+static int OP_STRH_IMM_OFF(uint32_t i) { STR_THUMB(STRH, (i >> 5) & 0x3E); }
3547
+static int OP_LDRH_IMM_OFF(uint32_t i) { LDR_THUMB(LDRH, (i >> 5) & 0x3E); }
3548
+static int OP_STRH_REG_OFF(uint32_t i) { STR_THUMB(STRH, -1); }
3549
+static int OP_LDRH_REG_OFF(uint32_t i) { LDR_THUMB(LDRH, -1); }
3550
+static int OP_LDRSH_REG_OFF(uint32_t i) { LDR_THUMB(LDRSH, -1); }
3551
+
3552
+static int OP_STR_IMM_OFF(uint32_t i) { STR_THUMB(STR, (i >> 4) & 0x7C); }
3553
+static int OP_LDR_IMM_OFF(uint32_t i) { LDR_THUMB(LDR, (i >> 4) & 0x7C); } // FIXME: tempValue = (tempValue>>adr) | (tempValue<<(32-adr));
3554
+static int OP_STR_REG_OFF(uint32_t i) { STR_THUMB(STR, -1); }
3555
+static int OP_LDR_REG_OFF(uint32_t i) { LDR_THUMB(LDR, -1); }
3556
+
3557
+static int OP_STR_SPREL(uint32_t i)
3558
+{
3559
+	uint32_t imm = (i & 0xFF) << 2;
3560
+	uint32_t adr_first = cpu->R[13] + imm;
3561
+
3562
+	GpVar addr = c.newGpVar(kX86VarTypeGpd);
3563
+	c.mov(addr, reg_ptr(13));
3564
+	if (imm)
3565
+		c.add(addr, imm);
3566
+	GpVar data = c.newGpVar(kX86VarTypeGpd);
3567
+	c.mov(data, reg_pos_thumb(8));
3568
+	X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(STR_tab[PROCNUM][classify_adr(adr_first, 1)]));
3569
+	ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<void, uint32_t, uint32_t>());
3570
+	ctx->setArgument(0, addr);
3571
+	ctx->setArgument(1, data);
3572
+	ctx->setReturn(bb_cycles);
3573
+	return 1;
3574
+}
3575
+
3576
+static int OP_LDR_SPREL(uint32_t i)
3577
+{
3578
+	uint32_t imm = (i & 0xFF) << 2;
3579
+	uint32_t adr_first = cpu->R[13] + imm;
3580
+	
3581
+	GpVar addr = c.newGpVar(kX86VarTypeGpd);
3582
+	c.mov(addr, reg_ptr(13));
3583
+	if (imm)
3584
+		c.add(addr, imm);
3585
+	GpVar data = c.newGpVar(kX86VarTypeGpz);
3586
+	c.lea(data, reg_pos_thumb(8));
3587
+	X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(LDR_tab[PROCNUM][classify_adr(adr_first, 0)]));
3588
+	ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<void, uint32_t, uint32_t *>());
3589
+	ctx->setArgument(0, addr);
3590
+	ctx->setArgument(1, data);
3591
+	ctx->setReturn(bb_cycles);
3592
+	return 1;
3593
+}
3594
+
3595
+static int OP_LDR_PCREL(uint32_t i)
3596
+{
3597
+	uint32_t imm = (i & 0xFF) << 2;
3598
+	uint32_t adr_first = (bb_r15 & 0xFFFFFFFC) + imm;
3599
+	GpVar addr = c.newGpVar(kX86VarTypeGpd);
3600
+	GpVar data = c.newGpVar(kX86VarTypeGpz);
3601
+	c.mov(addr, adr_first);
3602
+	c.lea(data, reg_pos_thumb(8));
3603
+	X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(LDR_tab[PROCNUM][classify_adr(adr_first, 0)]));
3604
+	ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2<void, uint32_t, uint32_t *>());
3605
+	ctx->setArgument(0, addr);
3606
+	ctx->setArgument(1, data);
3607
+	ctx->setReturn(bb_cycles);
3608
+	return 1;
3609
+}
3610
+
3611
+// -----------------------------------------------------------------------------
3612
+//   STMIA / LDMIA
3613
+// -----------------------------------------------------------------------------
3614
+static int op_ldm_stm_thumb(uint32_t i, bool store)
3615
+{
3616
+	uint32_t bitmask = i & 0xFF;
3617
+	uint32_t pop = popcount(bitmask);
3618
+
3619
+	//if (BIT_N(i, _REG_NUM(i, 8)))
3620
+	//	printf("WARNING - %sIA with Rb in Rlist (THUMB)\n", store?"STM":"LDM");
3621
+
3622
+	GpVar adr = c.newGpVar(kX86VarTypeGpd);
3623
+	c.mov(adr, reg_pos_thumb(8));
3624
+
3625
+	call_ldm_stm(adr, bitmask, store, 1);
3626
+
3627
+	// ARM_REF:	THUMB: Causes base register write-back, and is not optional
3628
+	// ARM_REF:	If the base register <Rn> is specified in <registers>, the final value of <Rn> is the loaded value
3629
+	//			(not the written-back value).
3630
+	if (store)
3631
+		c.add(reg_pos_thumb(8), 4 * pop);
3632
+	else
3633
+	{
3634
+		if (!BIT_N(i, _REG_NUM(i, 8)))
3635
+			c.add(reg_pos_thumb(8), 4 * pop);
3636
+	}
3637
+
3638
+	emit_MMU_aluMemCycles(store ? 2 : 3, bb_cycles, pop);
3639
+	return 1;
3640
+}
3641
+
3642
+static int OP_LDMIA_THUMB(uint32_t i) { return op_ldm_stm_thumb(i, 0); }
3643
+static int OP_STMIA_THUMB(uint32_t i) { return op_ldm_stm_thumb(i, 1); }
3644
+
3645
+// -----------------------------------------------------------------------------
3646
+//   Adjust SP
3647
+// -----------------------------------------------------------------------------
3648
+static int OP_ADJUST_P_SP(uint32_t i) { c.add(reg_ptr(13), (i & 0x7F) << 2); return 1; }
3649
+static int OP_ADJUST_M_SP(uint32_t i) { c.sub(reg_ptr(13), (i & 0x7F) << 2); return 1; }
3650
+
3651
+// -----------------------------------------------------------------------------
3652
+//   PUSH / POP
3653
+// -----------------------------------------------------------------------------
3654
+static int op_push_pop(uint32_t i, bool store, bool pc_lr)
3655
+{
3656
+	uint32_t bitmask = i & 0xFF;
3657
+	bitmask |= pc_lr << (store ? 14 : 15);
3658
+	uint32_t pop = popcount(bitmask);
3659
+	int dir = store ? -1 : 1;
3660
+
3661
+	GpVar adr = c.newGpVar(kX86VarTypeGpd);
3662
+	c.mov(adr, reg_ptr(13));
3663
+	if (store)
3664
+		c.sub(adr, 4);
3665
+
3666
+	call_ldm_stm(adr, bitmask, store, dir);
3667
+
3668
+	if (pc_lr && !store)
3669
+		op_bx_thumb(reg_ptr(15), 0, PROCNUM == ARMCPU_ARM9);
3670
+	c.add(reg_ptr(13), 4 * dir * pop);
3671
+
3672
+	emit_MMU_aluMemCycles(store ? (pc_lr ? 4 : 3) : (pc_lr ? 5 : 2), bb_cycles, pop);
3673
+	return 1;
3674
+}
3675
+
3676
+static int OP_PUSH(uint32_t i) { return op_push_pop(i, 1, 0); }
3677
+static int OP_PUSH_LR(uint32_t i) { return op_push_pop(i, 1, 1); }
3678
+static int OP_POP(uint32_t i) { return op_push_pop(i, 0, 0); }
3679
+static int OP_POP_PC(uint32_t i)  { return op_push_pop(i, 0, 1); }
3680
+
3681
+// -----------------------------------------------------------------------------
3682
+//   Branch
3683
+// -----------------------------------------------------------------------------
3684
+static int OP_B_COND(uint32_t i)
3685
+{
3686
+	Label skip = c.newLabel();
3687
+
3688
+	uint32_t dst = bb_r15 + (static_cast<uint32_t>(static_cast<int8_t>(i & 0xFF)) << 1);
3689
+
3690
+	c.mov(cpu_ptr(instruct_adr), bb_next_instruction);
3691
+
3692
+	emit_branch((i >> 8) & 0xF, skip);
3693
+	c.mov(cpu_ptr(instruct_adr), dst);
3694
+	c.add(bb_total_cycles, 2);
3695
+	c.bind(skip);
3696
+
3697
+	return 1;
3698
+}
3699
+
3700
+static int OP_B_UNCOND(uint32_t i)
3701
+{
3702
+	uint32_t dst = bb_r15 + (SIGNEXTEND_11(i) << 1);
3703
+	c.mov(cpu_ptr(instruct_adr), dst);
3704
+	return 1;
3705
+}
3706
+
3707
+static int OP_BLX(uint32_t i)
3708
+{
3709
+	GpVar dst = c.newGpVar(kX86VarTypeGpd);
3710
+	c.mov(dst, reg_ptr(14));
3711
+	c.add(dst, (i & 0x7FF) << 1);
3712
+	c.and_(dst, 0xFFFFFFFC);
3713
+	c.mov(cpu_ptr(instruct_adr), dst);
3714
+	c.mov(reg_ptr(14), bb_next_instruction | 1);
3715
+	// reset T bit
3716
+	c.and_(cpu_ptr_byte(CPSR, 0), ~(1 << 5));
3717
+	return 1;
3718
+}
3719
+
3720
+static int OP_BL_10( uint32_t i)
3721
+{
3722
+	uint32_t dst = bb_r15 + (SIGNEXTEND_11(i) << 12);
3723
+	c.mov(reg_ptr(14), dst);
3724
+	return 1;
3725
+}
3726
+
3727
+static int OP_BL_11(uint32_t i) 
3728
+{
3729
+	GpVar dst = c.newGpVar(kX86VarTypeGpd);
3730
+	c.mov(dst, reg_ptr(14));
3731
+	c.add(dst, (i & 0x7FF) << 1);
3732
+	c.mov(cpu_ptr(instruct_adr), dst);
3733
+	c.mov(reg_ptr(14), bb_next_instruction | 1);
3734
+	return 1;
3735
+}
3736
+
3737
+static int op_bx_thumb(Mem srcreg, bool blx, bool test_thumb)
3738
+{
3739
+	GpVar dst = c.newGpVar(kX86VarTypeGpd);
3740
+	GpVar thumb = c.newGpVar(kX86VarTypeGpd);
3741
+	c.mov(dst, srcreg);
3742
+	c.mov(thumb, dst); // * cpu->CPSR.bits.T = BIT0(Rm);
3743
+	c.and_(thumb, 1); // *
3744
+	if (blx)
3745
+		c.mov(reg_ptr(14), bb_next_instruction | 1);
3746
+	if (test_thumb)
3747
+	{
3748
+		GpVar mask = c.newGpVar(kX86VarTypeGpd);
3749
+		c.lea(mask, ptr_abs(reinterpret_cast<void *>(0xFFFFFFFC), thumb.r64(), kScale2Times));
3750
+		c.and_(dst, mask);
3751
+	}
3752
+	else
3753
+		c.and_(dst, 0xFFFFFFFE);
3754
+	
3755
+	GpVar tmp = c.newGpVar(kX86VarTypeGpd); // *
3756
+	c.mov(tmp, cpu_ptr_byte(CPSR, 0)); // *
3757
+	c.and_(tmp, ~(1 << 5)); // *
3758
+	c.shl(thumb, 5); // *
3759
+	c.or_(tmp, thumb); // *
3760
+	c.mov(cpu_ptr_byte(CPSR, 0), tmp.r8Lo()); // ******************************
3761
+
3762
+	c.mov(cpu_ptr(instruct_adr), dst);
3763
+	return 1;
3764
+}
3765
+
3766
+static int OP_BX_THUMB(uint32_t i) { if (REG_POS(i, 3) == 15) c.mov(reg_ptr(15), bb_r15); return op_bx_thumb(reg_pos_ptr(3), 0, 0); }
3767
+static int OP_BLX_THUMB(uint32_t i) { return op_bx_thumb(reg_pos_ptr(3), 1, 1); }
3768
+
3769
+static int OP_SWI_THUMB(uint32_t i) { return op_swi(i & 0x1F); }
3770
+
3771
+// -----------------------------------------------------------------------------
3772
+//   Unimplemented; fall back to the C versions
3773
+// -----------------------------------------------------------------------------
3774
+
3775
+#define OP_UND           nullptr
3776
+#define OP_LDREX         nullptr
3777
+#define OP_STREX         nullptr
3778
+#define OP_LDC_P_IMM_OFF nullptr
3779
+#define OP_LDC_M_IMM_OFF nullptr
3780
+#define OP_LDC_P_PREIND  nullptr
3781
+#define OP_LDC_M_PREIND  nullptr
3782
+#define OP_LDC_P_POSTIND nullptr
3783
+#define OP_LDC_M_POSTIND nullptr
3784
+#define OP_LDC_OPTION    nullptr
3785
+#define OP_STC_P_IMM_OFF nullptr
3786
+#define OP_STC_M_IMM_OFF nullptr
3787
+#define OP_STC_P_PREIND  nullptr
3788
+#define OP_STC_M_PREIND  nullptr
3789
+#define OP_STC_P_POSTIND nullptr
3790
+#define OP_STC_M_POSTIND nullptr
3791
+#define OP_STC_OPTION    nullptr
3792
+#define OP_CDP           nullptr
3793
+
3794
+#define OP_UND_THUMB     nullptr
3795
+#define OP_BKPT_THUMB    nullptr
3796
+
3797
+// -----------------------------------------------------------------------------
3798
+//   Dispatch table
3799
+// -----------------------------------------------------------------------------
3800
+
3801
+typedef int (*ArmOpCompiler)(uint32_t);
3802
+static const ArmOpCompiler arm_instruction_compilers[4096] =
3803
+{
3804
+#define TABDECL(x) x
3805
+#include "instruction_tabdef.inc"
3806
+#undef TABDECL
3807
+};
3808
+
3809
+static const ArmOpCompiler thumb_instruction_compilers[1024] =
3810
+{
3811
+#define TABDECL(x) x
3812
+#include "thumb_tabdef.inc"
3813
+#undef TABDECL
3814
+};
3815
+
3816
+//-----------------------------------------------------------------------------
3817
+//   Generic instruction wrapper
3818
+//-----------------------------------------------------------------------------
3819
+
3820
+template<int PROCNUM, int thumb> static uint32_t FASTCALL OP_DECODE()
3821
+{
3822
+	uint32_t cycles;
3823
+	uint32_t adr = cpu->instruct_adr;
3824
+	if (thumb)
3825
+	{
3826
+		cpu->next_instruction = adr + 2;
3827
+		cpu->R[15] = adr + 4;
3828
+		uint32_t opcode = _MMU_read16<PROCNUM, MMU_AT_CODE>(adr);
3829
+		_armlog(PROCNUM, adr, opcode);
3830
+		cycles = thumb_instructions_set[PROCNUM][opcode >> 6](opcode);
3831
+	}
3832
+	else
3833
+	{
3834
+		cpu->next_instruction = adr + 4;
3835
+		cpu->R[15] = adr + 8;
3836
+		uint32_t opcode = _MMU_read32<PROCNUM, MMU_AT_CODE>(adr);
3837
+		_armlog(PROCNUM, adr, opcode);
3838
+		if (CONDITION(opcode) == 0xE || TEST_COND(CONDITION(opcode), CODE(opcode), cpu->CPSR))
3839
+			cycles = arm_instructions_set[PROCNUM][INSTRUCTION_INDEX(opcode)](opcode);
3840
+		else
3841
+			cycles = 1;
3842
+	}
3843
+	cpu->instruct_adr = cpu->next_instruction;
3844
+	return cycles;
3845
+}
3846
+
3847
+static const ArmOpCompiled op_decode[][2] = { { OP_DECODE<0, 0>, OP_DECODE<0, 1> }, { OP_DECODE<1, 0>, OP_DECODE<1, 1> } };
3848
+
3849
+// -----------------------------------------------------------------------------
3850
+//   Compiler
3851
+// -----------------------------------------------------------------------------
3852
+
3853
+static uint32_t instr_attributes(uint32_t opcode)
3854
+{
3855
+	return bb_thumb ? thumb_attributes[opcode >> 6] : instruction_attributes[INSTRUCTION_INDEX(opcode)];
3856
+}
3857
+
3858
+static bool instr_is_branch(uint32_t opcode)
3859
+{
3860
+	uint32_t x = instr_attributes(opcode);
3861
+	if (bb_thumb)
3862
+		return (x & BRANCH_ALWAYS) || ((x & BRANCH_POS0) && ((opcode & 7) | ((opcode >> 4) & 8)) == 15) || (x & BRANCH_SWI) || (x & JIT_BYPASS);
3863
+	else
3864
+		return (x & BRANCH_ALWAYS) || ((x & BRANCH_POS12) && REG_POS(opcode, 12) == 15) || ((x & BRANCH_LDM) && BIT15(opcode)) || (x & BRANCH_SWI) || (x & JIT_BYPASS);
3865
+}
3866
+
3867
+static bool instr_uses_r15(uint32_t opcode)
3868
+{
3869
+	uint32_t x = instr_attributes(opcode);
3870
+	if (bb_thumb)
3871
+		return ((x & SRCREG_POS0) && ((opcode & 7) | ((opcode >> 4) & 8)) == 15) || ((x & SRCREG_POS3) && REG_POS(opcode, 3) == 15) || (x & JIT_BYPASS);
3872
+	else
3873
+		return ((x & SRCREG_POS0) && REG_POS(opcode, 0) == 15) || ((x & SRCREG_POS8) && REG_POS(opcode, 8) == 15) || ((x & SRCREG_POS12) && REG_POS(opcode, 12) == 15) ||
3874
+			((x & SRCREG_POS16) && REG_POS(opcode, 16) == 15) || ((x & SRCREG_STM) && BIT15(opcode)) || (x & JIT_BYPASS);
3875
+}
3876
+
3877
+static bool instr_is_conditional(uint32_t opcode)
3878
+{
3879
+	if (bb_thumb)
3880
+		return false;
3881
+	
3882
+	return !(CONDITION(opcode) == 0xE || (CONDITION(opcode) == 0xF && CODE(opcode) == 5));
3883
+}
3884
+
3885
+static int instr_cycles(uint32_t opcode)
3886
+{
3887
+	uint32_t x = instr_attributes(opcode);
3888
+	uint32_t c = x & INSTR_CYCLES_MASK;
3889
+	if (c == INSTR_CYCLES_VARIABLE)
3890
+	{
3891
+		if ((x & BRANCH_SWI) && !cpu->swi_tab)
3892
+			return 3;
3893
+		
3894
+		return 0;
3895
+	}
3896
+	if (instr_is_branch(opcode) && !(instr_attributes(opcode) & (BRANCH_ALWAYS | BRANCH_LDM)))
3897
+		c += 2;
3898
+	return c;
3899
+}
3900
+
3901
+static bool instr_does_prefetch(uint32_t opcode)
3902
+{
3903
+	uint32_t x = instr_attributes(opcode);
3904
+	if(bb_thumb)
3905
+		return thumb_instruction_compilers[opcode >> 6] && (x & BRANCH_ALWAYS);
3906
+	else
3907
+		return instr_is_branch(opcode) && arm_instruction_compilers[INSTRUCTION_INDEX(opcode)] && ((x & BRANCH_ALWAYS) || (x & BRANCH_LDM));
3908
+}
3909
+
3910
+static void sync_r15(uint32_t opcode, bool is_last, bool force)
3911
+{
3912
+	if (instr_does_prefetch(opcode))
3913
+	{
3914
+		assert(!instr_uses_r15(opcode));
3915
+		if (force)
3916
+		{
3917
+			JIT_COMMENT("sync_r15: force instruct_adr %08Xh (PREFETCH)", bb_adr);
3918
+			c.mov(cpu_ptr(instruct_adr), bb_next_instruction);
3919
+		}
3920
+	}
3921
+	else
3922
+	{
3923
+		if (force || (instr_attributes(opcode) & JIT_BYPASS) || (instr_attributes(opcode) & BRANCH_SWI) || (is_last && !instr_is_branch(opcode)))
3924
+		{
3925
+			JIT_COMMENT("sync_r15: next_instruction %08Xh - %s%s%s%s", bb_next_instruction,
3926
+				force ? " FORCE" : "",
3927
+				(instr_attributes(opcode) & JIT_BYPASS) ? " BYPASS" : "",
3928
+				(instr_attributes(opcode) & BRANCH_SWI) ? " SWI" : "",
3929
+				is_last && !instr_is_branch(opcode) ? " LAST" : ""
3930
+			);
3931
+			c.mov(cpu_ptr(next_instruction), bb_next_instruction);
3932
+		}
3933
+		if (instr_uses_r15(opcode))
3934
+		{
3935
+			JIT_COMMENT("sync_r15: R15 %08Xh (USES R15)", bb_r15);
3936
+			c.mov(reg_ptr(15), bb_r15);
3937
+		}
3938
+		if (instr_attributes(opcode) & JIT_BYPASS)
3939
+		{
3940
+			JIT_COMMENT("sync_r15: instruct_adr %08Xh (JIT_BYPASS)", bb_adr);
3941
+			c.mov(cpu_ptr(instruct_adr), bb_adr);
3942
+		}
3943
+	}
3944
+}
3945
+
3946
+static void emit_branch(int cond, Label to)
3947
+{
3948
+	JIT_COMMENT("emit_branch cond %02X", cond);
3949
+	static const uint8_t cond_bit[] = { 0x40, 0x40, 0x20, 0x20, 0x80, 0x80, 0x10, 0x10 };
3950
+	if (cond < 8)
3951
+	{
3952
+		c.test(flags_ptr, cond_bit[cond]);
3953
+		(cond & 1) ? c.jnz(to) : c.jz(to);
3954
+	}
3955
+	else
3956
+	{
3957
+		GpVar x = c.newGpVar(kX86VarTypeGpz);
3958
+		c.movzx(x, flags_ptr);
3959
+		c.and_(x, 0xF0);
3960
+#if defined(_M_X64) || defined(__x86_64__)
3961
+		c.add(x, offsetof(armcpu_t,cond_table) + cond);
3962
+		c.test(byte_ptr(bb_cpu, x), 1);
3963
+#else
3964
+		c.test(byte_ptr_abs((void *)(arm_cond_table + cond), x, kScaleNone), 1);
3965
+#endif
3966
+		c.unuse(x);
3967
+		c.jz(to);
3968
+	}
3969
+}
3970
+
3971
+static void emit_armop_call(uint32_t opcode)
3972
+{
3973
+	ArmOpCompiler fc = bb_thumb ? thumb_instruction_compilers[opcode >> 6] : arm_instruction_compilers[INSTRUCTION_INDEX(opcode)];
3974
+	if (fc && fc(opcode))
3975
+		return;
3976
+
3977
+	JIT_COMMENT("call interpreter");
3978
+	GpVar arg = c.newGpVar(kX86VarTypeGpd);
3979
+	c.mov(arg, opcode);
3980
+	OpFunc f = bb_thumb ? thumb_instructions_set[PROCNUM][opcode >> 6] : arm_instructions_set[PROCNUM][INSTRUCTION_INDEX(opcode)];
3981
+	X86CompilerFuncCall *ctx = c.call(reinterpret_cast<void *>(f));
3982
+	ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder1<uint32_t, uint32_t>());
3983
+	ctx->setArgument(0, arg);
3984
+	ctx->setReturn(bb_cycles);
3985
+}
3986
+
3987
+static void _armlog(uint8_t proc, uint32_t addr, uint32_t opcode)
3988
+{
3989
+#if 0
3990
+#if 0
3991
+	fprintf(stderr, "\t\t;R0:%08X R1:%08X R2:%08X R3:%08X R4:%08X R5:%08X R6:%08X R7:%08X R8:%08X R9:%08X\n\t\t;R10:%08X R11:%08X R12:%08X R13:%08X R14:%08X R15:%08X| next %08X, N:%i Z:%i C:%i V:%i\n",
3992
+		cpu->R[0],  cpu->R[1],  cpu->R[2],  cpu->R[3],  cpu->R[4],  cpu->R[5],  cpu->R[6],  cpu->R[7], 
3993
+		cpu->R[8],  cpu->R[9],  cpu->R[10],  cpu->R[11],  cpu->R[12],  cpu->R[13],  cpu->R[14],  cpu->R[15],
3994
+		cpu->next_instruction, cpu->CPSR.bits.N, cpu->CPSR.bits.Z, cpu->CPSR.bits.C, cpu->CPSR.bits.V);
3995
+#endif
3996
+	#define INDEX22(i) ((((i)>>16)&0xFF0)|(((i)>>4)&0xF))
3997
+	char dasmbuf[4096];
3998
+	if(cpu->CPSR.bits.T)
3999
+		des_thumb_instructions_set[((opcode)>>6)&1023](addr, opcode, dasmbuf);
4000
+	else
4001
+		des_arm_instructions_set[INDEX22(opcode)](addr, opcode, dasmbuf);
4002
+	#undef INDEX22
4003
+	fprintf(stderr, "%s%c %08X\t%08X \t%s\n", cpu->CPSR.bits.T?"THUMB":"ARM", proc?'7':'9', addr, opcode, dasmbuf); 
4004
+#endif
4005
+}
4006
+
4007
+template<int PROCNUM> static uint32_t compile_basicblock()
4008
+{
4009
+#if LOG_JIT
4010
+	bool has_variable_cycles = false;
4011
+#endif
4012
+	uint32_t interpreted_cycles = 0;
4013
+	uint32_t start_adr = cpu->instruct_adr;
4014
+	uint32_t opcode = 0;
4015
+	
4016
+	bb_thumb = cpu->CPSR.bits.T;
4017
+	bb_opcodesize = bb_thumb ? 2 : 4;
4018
+
4019
+	if (!JIT_MAPPED(start_adr & 0x0FFFFFFF, PROCNUM))
4020
+	{
4021
+		printf("JIT: use unmapped memory address %08X\n", start_adr);
4022
+		execute = false;
4023
+		return 1;
4024
+	}
4025
+
4026
+#if LOG_JIT
4027
+	fprintf(stderr, "adr %08Xh %s%c\n", start_adr, ARMPROC.CPSR.bits.T ? "THUMB":"ARM", PROCNUM?'7':'9');
4028
+#endif
4029
+
4030
+	c.clear();
4031
+	c.newFunc(ASMJIT_CALL_CONV, FuncBuilder0<int>());
4032
+	c.getFunc()->setHint(kFuncHintNaked, true);
4033
+	c.getFunc()->setHint(kX86FuncHintPushPop, true);
4034
+	
4035
+	JIT_COMMENT("CPU ptr");
4036
+	bb_cpu = c.newGpVar(kX86VarTypeGpz);
4037
+	c.mov(bb_cpu, (uintptr_t)&ARMPROC);
4038
+
4039
+	JIT_COMMENT("reset bb_total_cycles");
4040
+	bb_total_cycles = c.newGpVar(kX86VarTypeGpz);
4041
+	c.mov(bb_total_cycles, 0);
4042
+
4043
+#if (PROFILER_JIT_LEVEL > 0)
4044
+	JIT_COMMENT("Profiler ptr");
4045
+	bb_profiler = c.newGpVar(kX86VarTypeGpz);
4046
+	c.mov(bb_profiler, reinterpret_cast<uintptr_t>(&profiler_counter[PROCNUM]));
4047
+#endif
4048
+
4049
+	bb_constant_cycles = 0;
4050
+	for (uint32_t i = 0, bEndBlock = 0; !bEndBlock; ++i)
4051
+	{
4052
+		bb_adr = start_adr + (i * bb_opcodesize);
4053
+		if (bb_thumb)
4054
+			opcode = _MMU_read16<PROCNUM, MMU_AT_CODE>(bb_adr);
4055
+		else
4056
+			opcode = _MMU_read32<PROCNUM, MMU_AT_CODE>(bb_adr);
4057
+
4058
+#if LOG_JIT
4059
+		char dasmbuf[1024] = {0};
4060
+		if (bb_thumb)
4061
+			des_thumb_instructions_set[opcode >> 6](bb_adr, opcode, dasmbuf);
4062
+		else
4063
+			des_arm_instructions_set[INSTRUCTION_INDEX(opcode)](bb_adr, opcode, dasmbuf);
4064
+		fprintf(stderr, "%08X\t%s\t\t; %s \n", bb_adr, dasmbuf, disassemble(opcode));
4065
+#endif
4066
+
4067
+		uint32_t cycles = instr_cycles(opcode);
4068
+
4069
+		bEndBlock = i >= CommonSettings.jit_max_block_size - 1 || instr_is_branch(opcode);
4070
+		
4071
+#if LOG_JIT
4072
+		if (instr_is_conditional(opcode) && cycles > 1 || !cycles)
4073
+			has_variable_cycles = true;
4074
+#endif
4075
+		bb_cycles = c.newGpVar(kX86VarTypeGpz);
4076
+
4077
+		bb_constant_cycles += instr_is_conditional(opcode) ? 1 : cycles;
4078
+
4079
+		JIT_COMMENT("%s (PC:%08X)", disassemble(opcode), bb_adr);
4080
+
4081
+#if PROFILER_JIT_LEVEL > 0
4082
+		JIT_COMMENT("*** profiler - counter");
4083
+		if (bb_thumb)
4084
+			c.add(profiler_counter_thumb(opcode), 1);
4085
+		else
4086
+			c.add(profiler_counter_arm(opcode), 1);
4087
+#endif
4088
+		if (instr_is_conditional(opcode))
4089
+		{
4090
+			// 25% of conditional instructions are immediately followed by
4091
+			// another with the same condition, but merging them into a
4092
+			// single branch has negligible effect on speed.
4093
+			if (bEndBlock)
4094
+				sync_r15(opcode, 1, 1);
4095
+			Label skip = c.newLabel();
4096
+			emit_branch(CONDITION(opcode), skip);
4097
+			if (!bEndBlock)
4098
+				sync_r15(opcode, 0, 0);
4099
+			emit_armop_call(opcode);
4100
+			
4101
+			if (!cycles)
4102
+			{
4103
+				JIT_COMMENT("variable cycles");
4104
+				c.lea(bb_total_cycles, ptr(bb_total_cycles.r64(), bb_cycles.r64(), kScaleNone));
4105
+			}
4106
+			c.bind(skip);
4107
+		}
4108
+		else
4109
+		{
4110
+			sync_r15(opcode, !!bEndBlock, false);
4111
+			emit_armop_call(opcode);
4112
+			if (!cycles)
4113
+			{
4114
+				JIT_COMMENT("variable cycles");
4115
+				c.lea(bb_total_cycles, ptr(bb_total_cycles.r64(), bb_cycles.r64(), kScaleNone));
4116
+			}
4117
+		}
4118
+		interpreted_cycles += op_decode[PROCNUM][bb_thumb]();
4119
+	}
4120
+	
4121
+	if (!instr_does_prefetch(opcode))
4122
+	{
4123
+		JIT_COMMENT("!instr_does_prefetch: copy next_instruction (%08X) to instruct_adr (%08X)", cpu->next_instruction, cpu->instruct_adr);
4124
+		GpVar x = c.newGpVar(kX86VarTypeGpd);
4125
+		c.mov(x, cpu_ptr(next_instruction));
4126
+		c.mov(cpu_ptr(instruct_adr), x);
4127
+		c.unuse(x);
4128
+		//c.mov(cpu_ptr(instruct_adr), bb_adr);
4129
+		//c.mov(cpu_ptr(instruct_adr), bb_next_instruction);
4130
+	}
4131
+
4132
+	JIT_COMMENT("total cycles (block)");
4133
+
4134
+	if (bb_constant_cycles > 0)
4135
+		c.add(bb_total_cycles, bb_constant_cycles);
4136
+
4137
+#if PROFILER_JIT_LEVEL > 1
4138
+	JIT_COMMENT("*** profiler - cycles");
4139
+	uint32_t padr = (start_adr & 0x07FFFFFE) >> 1;
4140
+	bb_profiler_entry = c.newGpVar(kX86VarTypeGpz);
4141
+	c.mov(bb_profiler_entry, reinterpret_cast<uintptr_t>(&profiler_entry[PROCNUM][padr]));
4142
+	c.add(dword_ptr(bb_profiler_entry, offsetof(PROFILER_ENTRY, cycles)), bb_total_cycles);
4143
+	profiler_entry[PROCNUM][padr].addr = start_adr;
4144
+#endif
4145
+
4146
+	c.ret(bb_total_cycles);
4147
+#if LOG_JIT
4148
+	fprintf(stderr, "cycles %d%s\n", bb_constant_cycles, has_variable_cycles ? " + variable" : "");
4149
+#endif
4150
+	c.endFunc();
4151
+
4152
+	ArmOpCompiled f = reinterpret_cast<ArmOpCompiled>(c.make());
4153
+	if(c.getError())
4154
+	{
4155
+		fprintf(stderr, "JIT error: %s\n", getErrorString(c.getError()));
4156
+		f = op_decode[PROCNUM][bb_thumb];
4157
+	}
4158
+#if LOG_JIT
4159
+	uintptr_t baddr = reinterpret_cast<uintptr_t>(f);
4160
+	fprintf(stderr, "Block address %08lX\n\n", baddr);
4161
+	fflush(stderr);
4162
+#endif
4163
+	
4164
+	JIT_COMPILED_FUNC(start_adr, PROCNUM) = reinterpret_cast<uintptr_t>(f);
4165
+	return interpreted_cycles;
4166
+}
4167
+
4168
+template<int PROCNUM> uint32_t arm_jit_compile()
4169
+{
4170
+	*PROCNUM_ptr = PROCNUM;
4171
+
4172
+	// prevent endless recompilation of self-modifying code, which would be a memleak since we only free code all at once.
4173
+	// also allows us to clear compiled_funcs[] while leaving it sparsely allocated, if the OS does memory overcommit.
4174
+	uint32_t adr = cpu->instruct_adr;
4175
+	uint32_t mask_adr = (adr & 0x07FFFFFE) >> 4;
4176
+	if (((recompile_counts[mask_adr >> 1] >> 4 * (mask_adr & 1)) & 0xF) > 8)
4177
+	{
4178
+		ArmOpCompiled f = op_decode[PROCNUM][cpu->CPSR.bits.T];
4179
+		JIT_COMPILED_FUNC(adr, PROCNUM) = reinterpret_cast<uintptr_t>(f);
4180
+		return f();
4181
+	}
4182
+	recompile_counts[mask_adr >> 1] += 1 << 4 * (mask_adr & 1);
4183
+
4184
+	return compile_basicblock<PROCNUM>();
4185
+}
4186
+
4187
+template uint32_t arm_jit_compile<0>();
4188
+template uint32_t arm_jit_compile<1>();
4189
+
4190
+void arm_jit_reset(bool enable)
4191
+{
4192
+#if LOG_JIT
4193
+	c.setLogger(&logger);
4194
+#ifdef _WINDOWS
4195
+	freopen("\\desmume_jit.log", "w", stderr);
4196
+#endif
4197
+#endif
4198
+#ifdef HAVE_STATIC_CODE_BUFFER
4199
+	scratchptr = scratchpad;
4200
+#endif
4201
+	printf("CPU mode: %s\n", enable ? "JIT" : "Interpreter");
4202
+	printf("JIT max block size %d instruction(s)\n", CommonSettings.jit_max_block_size);
4203
+
4204
+	if (enable)
4205
+	{
4206
+#ifdef MAPPED_JIT_FUNCS
4207
+		// these pointers are allocated by asmjit and need freeing
4208
+		#define JITFREE(x)  for (size_t iii = 0; iii < ARRAY_SIZE((x)); ++iii) if ((x)[iii]) AsmJit::MemoryManager::getGlobal()->free(reinterpret_cast<void *>((x)[iii])); memset((x), 0, sizeof((x)));
4209
+			JITFREE(JIT.MAIN_MEM);
4210
+			JITFREE(JIT.SWIRAM);
4211
+			JITFREE(JIT.ARM9_ITCM);
4212
+			JITFREE(JIT.ARM9_LCDC);
4213
+			JITFREE(JIT.ARM9_BIOS);
4214
+			JITFREE(JIT.ARM7_BIOS);
4215
+			JITFREE(JIT.ARM7_ERAM);
4216
+			JITFREE(JIT.ARM7_WIRAM);
4217
+			JITFREE(JIT.ARM7_WRAM);
4218
+		#undef JITFREE
4219
+
4220
+		memset(recompile_counts, 0, sizeof(recompile_counts));
4221
+		init_jit_mem();
4222
+#else
4223
+		for (int i = 0; i < sizeof(recompile_counts) / 8; ++i)
4224
+			if (reinterpret_cast<uint64_t *>(recompile_counts)[i])
4225
+			{
4226
+				reinterpret_cast<uint64_t *>(recompile_counts)[i] = nullptr;
4227
+				memset(compiled_funcs + 128 * i, 0, 128 * sizeof(*compiled_funcs));
4228
+			}
4229
+#endif
4230
+	}
4231
+
4232
+	c.clear();
4233
+
4234
+#if PROFILER_JIT_LEVEL > 0
4235
+	reconstruct(&profiler_counter[0]);
4236
+	reconstruct(&profiler_counter[1]);
4237
+#if PROFILER_JIT_LEVEL > 1
4238
+	for (uint8_t t = 0; t < 2; ++t)
4239
+	{
4240
+		for (uint32_t i = 0; i < (1 << 26); ++i)
4241
+			memset(&profiler_entry[t][i], 0, sizeof(PROFILER_ENTRY));
4242
+	}
4243
+#endif
4244
+#endif
4245
+}
4246
+
4247
+#if PROFILER_JIT_LEVEL > 0
4248
+static int pcmp(PROFILER_COUNTER_INFO *info1, PROFILER_COUNTER_INFO *info2)
4249
+{
4250
+	return static_cast<int>(info2->count - info1->count);
4251
+}
4252
+
4253
+#if PROFILER_JIT_LEVEL > 1
4254
+static int pcmp_entry(PROFILER_ENTRY *info1, PROFILER_ENTRY *info2)
4255
+{
4256
+	return static_cast<int>(info1->cycles - info2->cycles);
4257
+}
4258
+#endif
4259
+#endif
4260
+
4261
+void arm_jit_close()
4262
+{
4263
+#if PROFILER_JIT_LEVEL > 0
4264
+	printf("Generating profile report...");
4265
+
4266
+	for (uint8_t proc = 0; proc < 2; ++proc)
4267
+	{
4268
+		extern GameInfo gameInfo;
4269
+		uint16_t last[2] = { 0 };
4270
+
4271
+		auto arm_info = std::unique_ptr<PROFILER_COUNTER_INFO[]>(new PROFILER_COUNTER_INFO[4096]);
4272
+		auto thumb_info = std::unique_ptr<PROFILER_COUNTER_INFO[]>(new PROFILER_COUNTER_INFO[1024]);
4273
+		memset(arm_info, 0, sizeof(PROFILER_COUNTER_INFO) * 4096);
4274
+		memset(thumb_info, 0, sizeof(PROFILER_COUNTER_INFO) * 1024);
4275
+
4276
+		// ARM
4277
+		last[0] = 0;
4278
+		for (uint16_t i = 0; i < 4096; ++i)
4279
+		{
4280
+			uint16_t t = 0;
4281
+			if (!profiler_counter[proc].arm_count[i])
4282
+				continue;
4283
+
4284
+			for (t = 0; t < last[0]; ++t)
4285
+			{
4286
+				if (!strcmp(arm_instruction_names[i], arm_info[t].name))
4287
+				{
4288
+					arm_info[t].count += profiler_counter[proc].arm_count[i];
4289
+					break;
4290
+				}
4291
+			}
4292
+			if (t == last[0])
4293
+			{
4294
+				strcpy(arm_info[last[0]++].name, arm_instruction_names[i]);
4295
+				arm_info[t].count = profiler_counter[proc].arm_count[i];
4296
+			}
4297
+		}
4298
+
4299
+		// THUMB
4300
+		last[1] = 0;
4301
+		for (uint16_t i = 0; i < 1024; ++i)
4302
+		{
4303
+			uint16_t t = 0;
4304
+			if (!profiler_counter[proc].thumb_count[i])
4305
+				continue;
4306
+
4307
+			for (t = 0; t < last[1]; ++t)
4308
+				if (!strcmp(thumb_instruction_names[i], thumb_info[t].name))
4309
+				{
4310
+					thumb_info[t].count += profiler_counter[proc].thumb_count[i];
4311
+					break;
4312
+				}
4313
+			if (t == last[1])
4314
+			{
4315
+				strcpy(thumb_info[last[1]++].name, thumb_instruction_names[i]);
4316
+				thumb_info[t].count = profiler_counter[proc].thumb_count[i];
4317
+			}
4318
+		}
4319
+
4320
+		std::qsort(arm_info, last[0], sizeof(PROFILER_COUNTER_INFO), (int (*)(const void *, const void *))pcmp);
4321
+		std::qsort(thumb_info, last[1], sizeof(PROFILER_COUNTER_INFO), (int (*)(const void *, const void *))pcmp);
4322
+
4323
+		char buf[MAX_PATH] = { 0 };
4324
+		sprintf(buf, "\\desmume_jit%c_counter.profiler", !proc ? '9' : '7');
4325
+		FILE *fp = fopen(buf, "w");
4326
+		if (fp)
4327
+		{
4328
+			if (!gameInfo.isHomebrew)
4329
+			{
4330
+				fprintf(fp, "Name:   %s\n", gameInfo.ROMname);
4331
+				fprintf(fp, "Serial: %s\n", gameInfo.ROMserial);
4332
+			}
4333
+			else
4334
+				fprintf(fp, "Homebrew\n");
4335
+			fprintf(fp, "CPU: ARM%c\n\n", !proc ? '9' : '7');
4336
+
4337
+			if (last[0])
4338
+			{
4339
+				fprintf(fp, "========================================== ARM ==========================================\n");
4340
+				for (int i = 0; i < last[0]; ++i)
4341
+					fprintf(fp, "%30s: %20ld\n", arm_info[i].name, arm_info[i].count);
4342
+				fprintf(fp, "\n");
4343
+			}
4344
+			
4345
+			if (last[1])
4346
+			{
4347
+				fprintf(fp, "========================================== THUMB ==========================================\n");
4348
+				for (int i = 0; i < last[1]; ++i)
4349
+					fprintf(fp, "%30s: %20ld\n", thumb_info[i].name, thumb_info[i].count);
4350
+				fprintf(fp, "\n");
4351
+			}
4352
+
4353
+			fclose(fp);
4354
+		}
4355
+
4356
+#if PROFILER_JIT_LEVEL > 1
4357
+		sprintf(buf, "\\desmume_jit%c_entry.profiler", !proc ? '9' : '7');
4358
+		fp = fopen(buf, "w");
4359
+		if (fp)
4360
+		{
4361
+			uint32_t count = 0;
4362
+
4363
+			fprintf(fp, "Entrypoints (cycles):\n");
4364
+			auto tmp = std::unique_ptr<PROFILER_ENTRY[]>(new PROFILER_ENTRY[1 << 26]);
4365
+			memset(tmp, 0, sizeof(PROFILER_ENTRY) * (1 << 26));
4366
+			for (uint32_t i = 0; i < (1 << 26); ++i)
4367
+			{
4368
+				if (!profiler_entry[proc][i].cycles)
4369
+					continue;
4370
+				memcpy(&tmp[count++], &profiler_entry[proc][i], sizeof(PROFILER_ENTRY));
4371
+			}
4372
+			std::qsort(tmp, count, sizeof(PROFILER_ENTRY), (int (*)(const void *, const void *))pcmp_entry);
4373
+			if (!gameInfo.isHomebrew)
4374
+			{
4375
+				fprintf(fp, "Name:   %s\n", gameInfo.ROMname);
4376
+				fprintf(fp, "Serial: %s\n", gameInfo.ROMserial);
4377
+			}
4378
+			else
4379
+				fprintf(fp, "Homebrew\n");
4380
+			fprintf(fp, "CPU: ARM%c\n\n", !proc ? '9' : '7');
4381
+
4382
+			while (count-- > 0)
4383
+				fprintf(fp, "%08X: %20ld\n", tmp[count].addr, tmp[count].cycles);
4384
+
4385
+			fclose(fp);
4386
+		}
4387
+#endif
4388
+	}
4389
+	printf(" done.\n");
4390
+#endif
4391
+}
4392
+#endif // HAVE_JIT