32x drc functional on ARM, random adjustments
[picodrive.git] / cpu / drc / emit_x86.c
1 #include <stdarg.h>
2
3 enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI };
4
5 #define CONTEXT_REG xBP
6
7 #define EMIT_PTR(ptr, val, type) \
8         *(type *)(ptr) = val
9
10 #define EMIT(val, type) { \
11         EMIT_PTR(tcache_ptr, val, type); \
12         tcache_ptr += sizeof(type); \
13 }
14
15 #define EMIT_OP(op) { \
16         COUNT_OP; \
17         EMIT(op, u8); \
18 }
19
20 #define EMIT_MODRM(mod,r,rm) \
21         EMIT(((mod)<<6) | ((r)<<3) | (rm), u8)
22
23 #define EMIT_OP_MODRM(op,mod,r,rm) { \
24         EMIT_OP(op); \
25         EMIT_MODRM(mod, r, rm); \
26 }
27
28 #define emith_move_r_r(dst, src) \
29         EMIT_OP_MODRM(0x8b, 3, dst, src)
30
31 #define emith_move_r_imm(r, imm) { \
32         EMIT_OP(0xb8 + (r)); \
33         EMIT(imm, u32); \
34 }
35
36 #define emith_add_r_imm(r, imm) { \
37         EMIT_OP_MODRM(0x81, 3, 0, r); \
38         EMIT(imm, u32); \
39 }
40
41 #define emith_sub_r_imm(r, imm) { \
42         EMIT_OP_MODRM(0x81, 3, 5, r); \
43         EMIT(imm, u32); \
44 }
45
46 // XXX: offs is 8bit only
47 #define emith_ctx_read(r, offs) { \
48         EMIT_OP_MODRM(0x8b, 1, r, xBP); \
49         EMIT(offs, u8);         /* mov tmp, [ebp+#offs] */ \
50 }
51
52 #define emith_ctx_write(r, offs) { \
53         EMIT_OP_MODRM(0x89, 1, r, xBP); \
54         EMIT(offs, u8);         /* mov [ebp+#offs], tmp */ \
55 }
56
57 #define emith_ctx_sub(val, offs) { \
58         EMIT_OP_MODRM(0x81, 1, 5, xBP); \
59         EMIT(offs, u8); \
60         EMIT(val, u32);         /* sub [ebp+#offs], dword val */ \
61 }
62
63 #define emith_jump(ptr) { \
64         u32 disp = (u32)ptr - ((u32)tcache_ptr + 5); \
65         EMIT_OP(0xe9); \
66         EMIT(disp, u32); \
67 }
68
69 #define emith_call(ptr) { \
70         u32 disp = (u32)ptr - ((u32)tcache_ptr + 5); \
71         EMIT_OP(0xe8); \
72         EMIT(disp, u32); \
73 }
74
75 #define EMITH_CONDITIONAL(code, is_nonzero) { \
76         u8 *ptr = tcache_ptr; \
77         tcache_ptr = tcache_ptr + 2; \
78         code; \
79         EMIT_PTR(ptr, ((is_nonzero) ? 0x75 : 0x74), u8); \
80         EMIT_PTR(ptr + 1, (tcache_ptr - (ptr + 2)), u8); \
81 }
82
83 #define arg2reg(rd, arg) \
84         switch (arg) { \
85         case 0: rd = xAX; break; \
86         case 1: rd = xDX; break; \
87         case 2: rd = xCX; break; \
88         }
89
90 #define emith_pass_arg_r(arg, reg) { \
91         int rd = 7; \
92         arg2reg(rd, arg); \
93         emith_move_r_r(rd, reg); \
94 }
95
96 #define emith_pass_arg_imm(arg, imm) { \
97         int rd = 7; \
98         arg2reg(rd, arg); \
99         emith_move_r_imm(rd, imm); \
100 }
101
102 /* SH2 drc specific */
103 #define emith_test_t() { \
104         if (reg_map_g2h[SHR_SR] == -1) { \
105                 EMIT_OP_MODRM(0xf6, 1, 0, 5); \
106                 EMIT(SHR_SR * 4, u8); \
107                 EMIT(0x01, u8); /* test [ebp+SHR_SR], byte 1 */ \
108         } else { \
109                 EMIT_OP_MODRM(0xf7, 3, 0, reg_map_g2h[SHR_SR]); \
110                 EMIT(0x01, u16); /* test <reg>, word 1 */ \
111         } \
112 }
113