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