32x: drc: dynamicregister allocator
[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_jump(ptr) { \
58         u32 disp = (u32)ptr - ((u32)tcache_ptr + 5); \
59         EMIT_OP(0xe9); \
60         EMIT(disp, u32); \
61 }
62
63 #define emith_call(ptr) { \
64         u32 disp = (u32)ptr - ((u32)tcache_ptr + 5); \
65         EMIT_OP(0xe8); \
66         EMIT(disp, u32); \
67 }
68
69 #define EMITH_CONDITIONAL(code, is_nonzero) { \
70         u8 *ptr = tcache_ptr; \
71         tcache_ptr = tcache_ptr + 2; \
72         code; \
73         EMIT_PTR(ptr, ((is_nonzero) ? 0x75 : 0x74), u8); \
74         EMIT_PTR(ptr + 1, (tcache_ptr - (ptr + 2)), u8); \
75 }
76
77 #define arg2reg(rd, arg) \
78         switch (arg) { \
79         case 0: rd = xAX; break; \
80         case 1: rd = xDX; break; \
81         case 2: rd = xCX; break; \
82         }
83
84 #define emith_pass_arg_r(arg, reg) { \
85         int rd = 7; \
86         arg2reg(rd, arg); \
87         emith_move_r_r(rd, reg); \
88 }
89
90 #define emith_pass_arg_imm(arg, imm) { \
91         int rd = 7; \
92         arg2reg(rd, arg); \
93         emith_move_r_imm(rd, imm); \
94 }
95
96 /* SH2 drc specific */
97 #define emith_test_t() { \
98         if (reg_map_g2h[SHR_SR] == -1) { \
99                 EMIT_OP_MODRM(0xf6, 1, 0, 5); \
100                 EMIT(SHR_SR * 4, u8); \
101                 EMIT(0x01, u8); /* test [ebp+SHR_SR], byte 1 */ \
102         } else { \
103                 EMIT_OP_MODRM(0xf7, 3, 0, reg_map_g2h[SHR_SR]); \
104                 EMIT(0x01, u16); /* test <reg>, word 1 */ \
105         } \
106 }
107