Mercurial > repos > blastem
comparison m68k_to_x86.c @ 558:dc9f178085a0
Use a typedef code_ptr in place of uint8_t * in 68K core to better support host instruction sets with different instruction word sizes. Make x86_68k_options contain a cpu_options so that gen_mem_fun can eventually be shared with the Z80 core.
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Mon, 24 Feb 2014 01:30:16 -0800 |
parents | acec5464fa1e |
children | 6b248602ab84 8e395210f50f |
comparison
equal
deleted
inserted
replaced
557:acec5464fa1e | 558:dc9f178085a0 |
---|---|
41 | 41 |
42 void m68k_invalid(); | 42 void m68k_invalid(); |
43 void bcd_add(); | 43 void bcd_add(); |
44 void bcd_sub(); | 44 void bcd_sub(); |
45 | 45 |
46 uint8_t * cycles(uint8_t * dst, uint32_t num) | 46 code_ptr cycles(code_ptr dst, uint32_t num) |
47 { | 47 { |
48 dst = add_ir(dst, num, CYCLES, SZ_D); | 48 dst = add_ir(dst, num, CYCLES, SZ_D); |
49 return dst; | 49 return dst; |
50 } | 50 } |
51 | 51 |
52 uint8_t * check_cycles_int(uint8_t * dst, uint32_t address, x86_68k_options * opts) | 52 code_ptr check_cycles_int(code_ptr dst, uint32_t address, x86_68k_options * opts) |
53 { | 53 { |
54 dst = cmp_rr(dst, CYCLES, LIMIT, SZ_D); | 54 dst = cmp_rr(dst, CYCLES, LIMIT, SZ_D); |
55 uint8_t * jmp_off = dst+1; | 55 code_ptr jmp_off = dst+1; |
56 dst = jcc(dst, CC_NC, dst + 7); | 56 dst = jcc(dst, CC_NC, dst + 7); |
57 dst = mov_ir(dst, address, SCRATCH1, SZ_D); | 57 dst = mov_ir(dst, address, SCRATCH1, SZ_D); |
58 dst = call(dst, opts->handle_cycle_limit_int); | 58 dst = call(dst, opts->gen.handle_cycle_limit_int); |
59 *jmp_off = dst - (jmp_off+1); | 59 *jmp_off = dst - (jmp_off+1); |
60 return dst; | 60 return dst; |
61 } | 61 } |
62 | 62 |
63 uint8_t * check_cycles(uint8_t * dst, x86_68k_options * opts) | 63 code_ptr check_cycles(code_ptr dst, cpu_options * opts) |
64 { | 64 { |
65 dst = cmp_rr(dst, CYCLES, LIMIT, SZ_D); | 65 dst = cmp_rr(dst, CYCLES, LIMIT, SZ_D); |
66 uint8_t * jmp_off = dst+1; | 66 code_ptr jmp_off = dst+1; |
67 dst = jcc(dst, CC_NC, dst + 7); | 67 dst = jcc(dst, CC_NC, dst + 7); |
68 dst = call(dst, opts->handle_cycle_limit); | 68 dst = call(dst, opts->handle_cycle_limit); |
69 *jmp_off = dst - (jmp_off+1); | 69 *jmp_off = dst - (jmp_off+1); |
70 return dst; | 70 return dst; |
71 } | 71 } |
72 | 72 |
73 uint8_t * set_flag(uint8_t * dst, uint8_t val, uint8_t flag, x86_68k_options * opts) | 73 code_ptr set_flag(code_ptr dst, uint8_t val, uint8_t flag, x86_68k_options * opts) |
74 { | 74 { |
75 if (opts->flag_regs[flag] >= 0) { | 75 if (opts->flag_regs[flag] >= 0) { |
76 dst = mov_ir(dst, val, opts->flag_regs[flag], SZ_B); | 76 dst = mov_ir(dst, val, opts->flag_regs[flag], SZ_B); |
77 } else { | 77 } else { |
78 int8_t offset = offsetof(m68k_context, flags) + flag; | 78 int8_t offset = offsetof(m68k_context, flags) + flag; |
84 } | 84 } |
85 | 85 |
86 return dst; | 86 return dst; |
87 } | 87 } |
88 | 88 |
89 uint8_t * set_flag_cond(uint8_t * dst, uint8_t cond, uint8_t flag, x86_68k_options *opts) | 89 code_ptr set_flag_cond(code_ptr dst, uint8_t cond, uint8_t flag, x86_68k_options *opts) |
90 { | 90 { |
91 if (opts->flag_regs[flag] >= 0) { | 91 if (opts->flag_regs[flag] >= 0) { |
92 dst = setcc_r(dst, cond, opts->flag_regs[flag]); | 92 dst = setcc_r(dst, cond, opts->flag_regs[flag]); |
93 } else { | 93 } else { |
94 int8_t offset = offsetof(m68k_context, flags) + flag; | 94 int8_t offset = offsetof(m68k_context, flags) + flag; |
100 } | 100 } |
101 | 101 |
102 return dst; | 102 return dst; |
103 } | 103 } |
104 | 104 |
105 uint8_t * check_flag(uint8_t *dst, uint8_t flag, x86_68k_options *opts) | 105 code_ptr check_flag(code_ptr dst, uint8_t flag, x86_68k_options *opts) |
106 { | 106 { |
107 if (opts->flag_regs[flag] >= 0) { | 107 if (opts->flag_regs[flag] >= 0) { |
108 dst = cmp_ir(dst, 0, opts->flag_regs[flag], SZ_B); | 108 dst = cmp_ir(dst, 0, opts->flag_regs[flag], SZ_B); |
109 } else { | 109 } else { |
110 dst = cmp_irdisp8(dst, 0, CONTEXT, offsetof(m68k_context, flags) + flag, SZ_B); | 110 dst = cmp_irdisp8(dst, 0, CONTEXT, offsetof(m68k_context, flags) + flag, SZ_B); |
111 } | 111 } |
112 return dst; | 112 return dst; |
113 } | 113 } |
114 | 114 |
115 uint8_t * flag_to_reg(uint8_t *dst, uint8_t flag, uint8_t reg, x86_68k_options *opts) | 115 code_ptr flag_to_reg(code_ptr dst, uint8_t flag, uint8_t reg, x86_68k_options *opts) |
116 { | 116 { |
117 if (opts->flag_regs[flag] >= 0) { | 117 if (opts->flag_regs[flag] >= 0) { |
118 dst = mov_rr(dst, opts->flag_regs[flag], reg, SZ_B); | 118 dst = mov_rr(dst, opts->flag_regs[flag], reg, SZ_B); |
119 } else { | 119 } else { |
120 int8_t offset = offsetof(m68k_context, flags) + flag; | 120 int8_t offset = offsetof(m68k_context, flags) + flag; |
125 } | 125 } |
126 } | 126 } |
127 return dst; | 127 return dst; |
128 } | 128 } |
129 | 129 |
130 uint8_t * reg_to_flag(uint8_t *dst, uint8_t flag, uint8_t reg, x86_68k_options *opts) | 130 code_ptr reg_to_flag(code_ptr dst, uint8_t flag, uint8_t reg, x86_68k_options *opts) |
131 { | 131 { |
132 if (opts->flag_regs[flag] >= 0) { | 132 if (opts->flag_regs[flag] >= 0) { |
133 dst = mov_rr(dst, reg, opts->flag_regs[flag], SZ_B); | 133 dst = mov_rr(dst, reg, opts->flag_regs[flag], SZ_B); |
134 } else { | 134 } else { |
135 int8_t offset = offsetof(m68k_context, flags) + flag; | 135 int8_t offset = offsetof(m68k_context, flags) + flag; |
140 } | 140 } |
141 } | 141 } |
142 return dst; | 142 return dst; |
143 } | 143 } |
144 | 144 |
145 uint8_t * flag_to_flag(uint8_t *dst, uint8_t flag1, uint8_t flag2, x86_68k_options *opts) | 145 code_ptr flag_to_flag(code_ptr dst, uint8_t flag1, uint8_t flag2, x86_68k_options *opts) |
146 { | 146 { |
147 if (opts->flag_regs[flag1] >= 0 && opts->flag_regs[flag2] >= 0) { | 147 if (opts->flag_regs[flag1] >= 0 && opts->flag_regs[flag2] >= 0) { |
148 dst = mov_rr(dst, opts->flag_regs[flag1], opts->flag_regs[flag2], SZ_B); | 148 dst = mov_rr(dst, opts->flag_regs[flag1], opts->flag_regs[flag2], SZ_B); |
149 } else if(opts->flag_regs[flag1] >= 0) { | 149 } else if(opts->flag_regs[flag1] >= 0) { |
150 dst = mov_rrdisp8(dst, opts->flag_regs[flag1], CONTEXT, offsetof(m68k_context, flags) + flag2, SZ_B); | 150 dst = mov_rrdisp8(dst, opts->flag_regs[flag1], CONTEXT, offsetof(m68k_context, flags) + flag2, SZ_B); |
157 dst = pop_r(dst, SCRATCH1); | 157 dst = pop_r(dst, SCRATCH1); |
158 } | 158 } |
159 return dst; | 159 return dst; |
160 } | 160 } |
161 | 161 |
162 uint8_t * flag_to_carry(uint8_t *dst, uint8_t flag, x86_68k_options * opts) | 162 code_ptr flag_to_carry(code_ptr dst, uint8_t flag, x86_68k_options * opts) |
163 { | 163 { |
164 if (opts->flag_regs[flag] >= 0) { | 164 if (opts->flag_regs[flag] >= 0) { |
165 dst = bt_ir(dst, 0, opts->flag_regs[flag], SZ_B); | 165 dst = bt_ir(dst, 0, opts->flag_regs[flag], SZ_B); |
166 } else { | 166 } else { |
167 dst = bt_irdisp8(dst, 0, CONTEXT, offsetof(m68k_context, flags) + flag, SZ_B); | 167 dst = bt_irdisp8(dst, 0, CONTEXT, offsetof(m68k_context, flags) + flag, SZ_B); |
168 } | 168 } |
169 return dst; | 169 return dst; |
170 } | 170 } |
171 | 171 |
172 uint8_t * or_flag_to_reg(uint8_t *dst, uint8_t flag, uint8_t reg, x86_68k_options *opts) | 172 code_ptr or_flag_to_reg(code_ptr dst, uint8_t flag, uint8_t reg, x86_68k_options *opts) |
173 { | 173 { |
174 if (opts->flag_regs[flag] >= 0) { | 174 if (opts->flag_regs[flag] >= 0) { |
175 dst = or_rr(dst, opts->flag_regs[flag], reg, SZ_B); | 175 dst = or_rr(dst, opts->flag_regs[flag], reg, SZ_B); |
176 } else { | 176 } else { |
177 dst = or_rdisp8r(dst, CONTEXT, offsetof(m68k_context, flags) + flag, reg, SZ_B); | 177 dst = or_rdisp8r(dst, CONTEXT, offsetof(m68k_context, flags) + flag, reg, SZ_B); |
178 } | 178 } |
179 return dst; | 179 return dst; |
180 } | 180 } |
181 | 181 |
182 uint8_t * xor_flag_to_reg(uint8_t *dst, uint8_t flag, uint8_t reg, x86_68k_options *opts) | 182 code_ptr xor_flag_to_reg(code_ptr dst, uint8_t flag, uint8_t reg, x86_68k_options *opts) |
183 { | 183 { |
184 if (opts->flag_regs[flag] >= 0) { | 184 if (opts->flag_regs[flag] >= 0) { |
185 dst = xor_rr(dst, opts->flag_regs[flag], reg, SZ_B); | 185 dst = xor_rr(dst, opts->flag_regs[flag], reg, SZ_B); |
186 } else { | 186 } else { |
187 dst = xor_rdisp8r(dst, CONTEXT, offsetof(m68k_context, flags) + flag, reg, SZ_B); | 187 dst = xor_rdisp8r(dst, CONTEXT, offsetof(m68k_context, flags) + flag, reg, SZ_B); |
188 } | 188 } |
189 return dst; | 189 return dst; |
190 } | 190 } |
191 | 191 |
192 uint8_t * xor_flag(uint8_t *dst, uint8_t val, uint8_t flag, x86_68k_options *opts) | 192 code_ptr xor_flag(code_ptr dst, uint8_t val, uint8_t flag, x86_68k_options *opts) |
193 { | 193 { |
194 if (opts->flag_regs[flag] >= 0) { | 194 if (opts->flag_regs[flag] >= 0) { |
195 dst = xor_ir(dst, val, opts->flag_regs[flag], SZ_B); | 195 dst = xor_ir(dst, val, opts->flag_regs[flag], SZ_B); |
196 } else { | 196 } else { |
197 dst = xor_irdisp8(dst, val, CONTEXT, offsetof(m68k_context, flags) + flag, SZ_B); | 197 dst = xor_irdisp8(dst, val, CONTEXT, offsetof(m68k_context, flags) + flag, SZ_B); |
198 } | 198 } |
199 return dst; | 199 return dst; |
200 } | 200 } |
201 | 201 |
202 uint8_t * cmp_flags(uint8_t *dst, uint8_t flag1, uint8_t flag2, x86_68k_options *opts) | 202 code_ptr cmp_flags(code_ptr dst, uint8_t flag1, uint8_t flag2, x86_68k_options *opts) |
203 { | 203 { |
204 if (opts->flag_regs[flag1] >= 0 && opts->flag_regs[flag2] >= 0) { | 204 if (opts->flag_regs[flag1] >= 0 && opts->flag_regs[flag2] >= 0) { |
205 dst = cmp_rr(dst, opts->flag_regs[flag1], opts->flag_regs[flag2], SZ_B); | 205 dst = cmp_rr(dst, opts->flag_regs[flag1], opts->flag_regs[flag2], SZ_B); |
206 } else if(opts->flag_regs[flag1] >= 0 || opts->flag_regs[flag2] >= 0) { | 206 } else if(opts->flag_regs[flag1] >= 0 || opts->flag_regs[flag2] >= 0) { |
207 if (opts->flag_regs[flag2] >= 0) { | 207 if (opts->flag_regs[flag2] >= 0) { |
247 printf("a%d: %X\n", i, context->aregs[i]); | 247 printf("a%d: %X\n", i, context->aregs[i]); |
248 } | 248 } |
249 exit(0); | 249 exit(0); |
250 } | 250 } |
251 | 251 |
252 uint8_t * translate_m68k_src(m68kinst * inst, x86_ea * ea, uint8_t * out, x86_68k_options * opts) | 252 code_ptr translate_m68k_src(m68kinst * inst, x86_ea * ea, code_ptr out, x86_68k_options * opts) |
253 { | 253 { |
254 int8_t reg = native_reg(&(inst->src), opts); | 254 int8_t reg = native_reg(&(inst->src), opts); |
255 uint8_t sec_reg; | 255 uint8_t sec_reg; |
256 int32_t dec_amount,inc_amount; | 256 int32_t dec_amount,inc_amount; |
257 if (reg >= 0) { | 257 if (reg >= 0) { |
526 ea->base = SCRATCH1; | 526 ea->base = SCRATCH1; |
527 } | 527 } |
528 return out; | 528 return out; |
529 } | 529 } |
530 | 530 |
531 uint8_t * translate_m68k_dst(m68kinst * inst, x86_ea * ea, uint8_t * out, x86_68k_options * opts, uint8_t fake_read) | 531 code_ptr translate_m68k_dst(m68kinst * inst, x86_ea * ea, code_ptr out, x86_68k_options * opts, uint8_t fake_read) |
532 { | 532 { |
533 int8_t reg = native_reg(&(inst->dst), opts), sec_reg; | 533 int8_t reg = native_reg(&(inst->dst), opts), sec_reg; |
534 int32_t dec_amount, inc_amount; | 534 int32_t dec_amount, inc_amount; |
535 if (reg >= 0) { | 535 if (reg >= 0) { |
536 ea->mode = MODE_REG_DIRECT; | 536 ea->mode = MODE_REG_DIRECT; |
801 exit(1); | 801 exit(1); |
802 } | 802 } |
803 return out; | 803 return out; |
804 } | 804 } |
805 | 805 |
806 uint8_t * m68k_save_result(m68kinst * inst, uint8_t * out, x86_68k_options * opts) | 806 code_ptr m68k_save_result(m68kinst * inst, code_ptr out, x86_68k_options * opts) |
807 { | 807 { |
808 if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG) { | 808 if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG) { |
809 if (inst->dst.addr_mode == MODE_AREG_PREDEC && inst->src.addr_mode == MODE_AREG_PREDEC && inst->op != M68K_MOVE) { | 809 if (inst->dst.addr_mode == MODE_AREG_PREDEC && inst->src.addr_mode == MODE_AREG_PREDEC && inst->op != M68K_MOVE) { |
810 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | 810 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { |
811 out = mov_rr(out, opts->aregs[inst->dst.params.regs.pri], SCRATCH2, SZ_D); | 811 out = mov_rr(out, opts->aregs[inst->dst.params.regs.pri], SCRATCH2, SZ_D); |
827 } | 827 } |
828 } | 828 } |
829 return out; | 829 return out; |
830 } | 830 } |
831 | 831 |
832 uint8_t * get_native_address(native_map_slot * native_code_map, uint32_t address) | 832 code_ptr get_native_address(native_map_slot * native_code_map, uint32_t address) |
833 { | 833 { |
834 address &= 0xFFFFFF; | 834 address &= 0xFFFFFF; |
835 address /= 2; | 835 address /= 2; |
836 uint32_t chunk = address / NATIVE_CHUNK_SIZE; | 836 uint32_t chunk = address / NATIVE_CHUNK_SIZE; |
837 if (!native_code_map[chunk].base) { | 837 if (!native_code_map[chunk].base) { |
842 return NULL; | 842 return NULL; |
843 } | 843 } |
844 return native_code_map[chunk].base + native_code_map[chunk].offsets[offset]; | 844 return native_code_map[chunk].base + native_code_map[chunk].offsets[offset]; |
845 } | 845 } |
846 | 846 |
847 uint8_t * get_native_from_context(m68k_context * context, uint32_t address) | 847 code_ptr get_native_from_context(m68k_context * context, uint32_t address) |
848 { | 848 { |
849 return get_native_address(context->native_code_map, address); | 849 return get_native_address(context->native_code_map, address); |
850 } | 850 } |
851 | 851 |
852 uint32_t get_instruction_start(native_map_slot * native_code_map, uint32_t address) | 852 uint32_t get_instruction_start(native_map_slot * native_code_map, uint32_t address) |
867 offset = address % NATIVE_CHUNK_SIZE; | 867 offset = address % NATIVE_CHUNK_SIZE; |
868 } | 868 } |
869 return address*2; | 869 return address*2; |
870 } | 870 } |
871 | 871 |
872 void map_native_address(m68k_context * context, uint32_t address, uint8_t * native_addr, uint8_t size, uint8_t native_size) | 872 void map_native_address(m68k_context * context, uint32_t address, code_ptr native_addr, uint8_t size, uint8_t native_size) |
873 { | 873 { |
874 native_map_slot * native_code_map = context->native_code_map; | 874 native_map_slot * native_code_map = context->native_code_map; |
875 x86_68k_options * opts = context->options; | 875 x86_68k_options * opts = context->options; |
876 address &= 0xFFFFFF; | 876 address &= 0xFFFFFF; |
877 if (address > 0xE00000) { | 877 if (address > 0xE00000) { |
878 context->ram_code_flags[(address & 0xC000) >> 14] |= 1 << ((address & 0x3800) >> 11); | 878 context->ram_code_flags[(address & 0xC000) >> 14] |= 1 << ((address & 0x3800) >> 11); |
879 if (((address & 0x3FFF) + size) & 0xC000) { | 879 if (((address & 0x3FFF) + size) & 0xC000) { |
880 context->ram_code_flags[((address+size) & 0xC000) >> 14] |= 1 << (((address+size) & 0x3800) >> 11); | 880 context->ram_code_flags[((address+size) & 0xC000) >> 14] |= 1 << (((address+size) & 0x3800) >> 11); |
881 } | 881 } |
882 uint32_t slot = (address & 0xFFFF)/1024; | 882 uint32_t slot = (address & 0xFFFF)/1024; |
883 if (!opts->ram_inst_sizes[slot]) { | 883 if (!opts->gen.ram_inst_sizes[slot]) { |
884 opts->ram_inst_sizes[slot] = malloc(sizeof(uint8_t) * 512); | 884 opts->gen.ram_inst_sizes[slot] = malloc(sizeof(uint8_t) * 512); |
885 } | 885 } |
886 opts->ram_inst_sizes[slot][((address & 0xFFFF)/2)%512] = native_size; | 886 opts->gen.ram_inst_sizes[slot][((address & 0xFFFF)/2)%512] = native_size; |
887 } | 887 } |
888 address/= 2; | 888 address/= 2; |
889 uint32_t chunk = address / NATIVE_CHUNK_SIZE; | 889 uint32_t chunk = address / NATIVE_CHUNK_SIZE; |
890 if (!native_code_map[chunk].base) { | 890 if (!native_code_map[chunk].base) { |
891 native_code_map[chunk].base = native_addr; | 891 native_code_map[chunk].base = native_addr; |
910 { | 910 { |
911 if (address < 0xE00000) { | 911 if (address < 0xE00000) { |
912 return 0; | 912 return 0; |
913 } | 913 } |
914 uint32_t slot = (address & 0xFFFF)/1024; | 914 uint32_t slot = (address & 0xFFFF)/1024; |
915 return opts->ram_inst_sizes[slot][((address & 0xFFFF)/2)%512]; | 915 return opts->gen.ram_inst_sizes[slot][((address & 0xFFFF)/2)%512]; |
916 } | 916 } |
917 | 917 |
918 uint8_t * translate_m68k_move(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) | 918 code_ptr translate_m68k_move(code_ptr dst, m68kinst * inst, x86_68k_options * opts) |
919 { | 919 { |
920 int8_t reg, flags_reg, sec_reg; | 920 int8_t reg, flags_reg, sec_reg; |
921 uint8_t dir = 0; | 921 uint8_t dir = 0; |
922 int32_t offset; | 922 int32_t offset; |
923 int32_t inc_amount, dec_amount; | 923 int32_t inc_amount, dec_amount; |
1274 //add cycles for prefetch | 1274 //add cycles for prefetch |
1275 dst = cycles(dst, BUS); | 1275 dst = cycles(dst, BUS); |
1276 return dst; | 1276 return dst; |
1277 } | 1277 } |
1278 | 1278 |
1279 uint8_t * translate_m68k_movem(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) | 1279 code_ptr translate_m68k_movem(code_ptr dst, m68kinst * inst, x86_68k_options * opts) |
1280 { | 1280 { |
1281 int8_t bit,reg,sec_reg; | 1281 int8_t bit,reg,sec_reg; |
1282 uint8_t early_cycles; | 1282 uint8_t early_cycles; |
1283 if(inst->src.addr_mode == MODE_REG) { | 1283 if(inst->src.addr_mode == MODE_REG) { |
1284 //reg to mem | 1284 //reg to mem |
1602 //prefetch | 1602 //prefetch |
1603 dst = cycles(dst, 4); | 1603 dst = cycles(dst, 4); |
1604 return dst; | 1604 return dst; |
1605 } | 1605 } |
1606 | 1606 |
1607 uint8_t * translate_m68k_clr(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) | 1607 code_ptr translate_m68k_clr(code_ptr dst, m68kinst * inst, x86_68k_options * opts) |
1608 { | 1608 { |
1609 dst = set_flag(dst, 0, FLAG_N, opts); | 1609 dst = set_flag(dst, 0, FLAG_N, opts); |
1610 dst = set_flag(dst, 0, FLAG_V, opts); | 1610 dst = set_flag(dst, 0, FLAG_V, opts); |
1611 dst = set_flag(dst, 0, FLAG_C, opts); | 1611 dst = set_flag(dst, 0, FLAG_C, opts); |
1612 dst = set_flag(dst, 1, FLAG_Z, opts); | 1612 dst = set_flag(dst, 1, FLAG_Z, opts); |
1624 } | 1624 } |
1625 dst = m68k_save_result(inst, dst, opts); | 1625 dst = m68k_save_result(inst, dst, opts); |
1626 return dst; | 1626 return dst; |
1627 } | 1627 } |
1628 | 1628 |
1629 uint8_t * translate_m68k_ext(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) | 1629 code_ptr translate_m68k_ext(code_ptr dst, m68kinst * inst, x86_68k_options * opts) |
1630 { | 1630 { |
1631 x86_ea dst_op; | 1631 x86_ea dst_op; |
1632 uint8_t dst_size = inst->extra.size; | 1632 uint8_t dst_size = inst->extra.size; |
1633 inst->extra.size--; | 1633 inst->extra.size--; |
1634 dst = translate_m68k_dst(inst, &dst_op, dst, opts, 0); | 1634 dst = translate_m68k_dst(inst, &dst_op, dst, opts, 0); |
1647 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 1647 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
1648 //M68K EXT only operates on registers so no need for a call to save result here | 1648 //M68K EXT only operates on registers so no need for a call to save result here |
1649 return dst; | 1649 return dst; |
1650 } | 1650 } |
1651 | 1651 |
1652 uint8_t * translate_m68k_lea(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) | 1652 code_ptr translate_m68k_lea(code_ptr dst, m68kinst * inst, x86_68k_options * opts) |
1653 { | 1653 { |
1654 int8_t dst_reg = native_reg(&(inst->dst), opts), sec_reg; | 1654 int8_t dst_reg = native_reg(&(inst->dst), opts), sec_reg; |
1655 switch(inst->src.addr_mode) | 1655 switch(inst->src.addr_mode) |
1656 { | 1656 { |
1657 case MODE_AREG_INDIRECT: | 1657 case MODE_AREG_INDIRECT: |
1807 exit(1); | 1807 exit(1); |
1808 } | 1808 } |
1809 return dst; | 1809 return dst; |
1810 } | 1810 } |
1811 | 1811 |
1812 uint8_t * translate_m68k_pea(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) | 1812 code_ptr translate_m68k_pea(code_ptr dst, m68kinst * inst, x86_68k_options * opts) |
1813 { | 1813 { |
1814 uint8_t sec_reg; | 1814 uint8_t sec_reg; |
1815 switch(inst->src.addr_mode) | 1815 switch(inst->src.addr_mode) |
1816 { | 1816 { |
1817 case MODE_AREG_INDIRECT: | 1817 case MODE_AREG_INDIRECT: |
1891 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); | 1891 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); |
1892 dst = call(dst, opts->write_32_lowfirst); | 1892 dst = call(dst, opts->write_32_lowfirst); |
1893 return dst; | 1893 return dst; |
1894 } | 1894 } |
1895 | 1895 |
1896 uint8_t * translate_m68k_bsr(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) | 1896 code_ptr translate_m68k_bsr(code_ptr dst, m68kinst * inst, x86_68k_options * opts) |
1897 { | 1897 { |
1898 int32_t disp = inst->src.params.immed; | 1898 int32_t disp = inst->src.params.immed; |
1899 uint32_t after = inst->address + (inst->variant == VAR_BYTE ? 2 : 4); | 1899 uint32_t after = inst->address + (inst->variant == VAR_BYTE ? 2 : 4); |
1900 //TODO: Add cycles in the right place relative to pushing the return address on the stack | 1900 //TODO: Add cycles in the right place relative to pushing the return address on the stack |
1901 dst = cycles(dst, 10); | 1901 dst = cycles(dst, 10); |
1902 dst = mov_ir(dst, after, SCRATCH1, SZ_D); | 1902 dst = mov_ir(dst, after, SCRATCH1, SZ_D); |
1903 dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); | 1903 dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); |
1904 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); | 1904 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); |
1905 dst = call(dst, opts->write_32_highfirst); | 1905 dst = call(dst, opts->write_32_highfirst); |
1906 uint8_t * dest_addr = get_native_address(opts->native_code_map, (inst->address+2) + disp); | 1906 code_ptr dest_addr = get_native_address(opts->gen.native_code_map, (inst->address+2) + disp); |
1907 if (!dest_addr) { | 1907 if (!dest_addr) { |
1908 opts->deferred = defer_address(opts->deferred, (inst->address+2) + disp, dst + 1); | 1908 opts->gen.deferred = defer_address(opts->gen.deferred, (inst->address+2) + disp, dst + 1); |
1909 //dummy address to be replaced later | 1909 //dummy address to be replaced later |
1910 dest_addr = dst + 256; | 1910 dest_addr = dst + 256; |
1911 } | 1911 } |
1912 dst = jmp(dst, (char *)dest_addr); | 1912 dst = jmp(dst, (char *)dest_addr); |
1913 return dst; | 1913 return dst; |
1914 } | 1914 } |
1915 | 1915 |
1916 uint8_t * translate_m68k_bcc(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) | 1916 code_ptr translate_m68k_bcc(code_ptr dst, m68kinst * inst, x86_68k_options * opts) |
1917 { | 1917 { |
1918 dst = cycles(dst, 10);//TODO: Adjust this for branch not taken case | 1918 dst = cycles(dst, 10);//TODO: Adjust this for branch not taken case |
1919 int32_t disp = inst->src.params.immed; | 1919 int32_t disp = inst->src.params.immed; |
1920 uint32_t after = inst->address + 2; | 1920 uint32_t after = inst->address + 2; |
1921 uint8_t * dest_addr = get_native_address(opts->native_code_map, after + disp); | 1921 code_ptr dest_addr = get_native_address(opts->gen.native_code_map, after + disp); |
1922 if (inst->extra.cond == COND_TRUE) { | 1922 if (inst->extra.cond == COND_TRUE) { |
1923 if (!dest_addr) { | 1923 if (!dest_addr) { |
1924 opts->deferred = defer_address(opts->deferred, after + disp, dst + 1); | 1924 opts->gen.deferred = defer_address(opts->gen.deferred, after + disp, dst + 1); |
1925 //dummy address to be replaced later, make sure it generates a 4-byte displacement | 1925 //dummy address to be replaced later, make sure it generates a 4-byte displacement |
1926 dest_addr = dst + 256; | 1926 dest_addr = dst + 256; |
1927 } | 1927 } |
1928 dst = jmp(dst, dest_addr); | 1928 dst = jmp(dst, dest_addr); |
1929 } else { | 1929 } else { |
1968 dst = xor_flag_to_reg(dst, FLAG_N, SCRATCH1, opts); | 1968 dst = xor_flag_to_reg(dst, FLAG_N, SCRATCH1, opts); |
1969 dst = or_flag_to_reg(dst, FLAG_Z, SCRATCH1, opts); | 1969 dst = or_flag_to_reg(dst, FLAG_Z, SCRATCH1, opts); |
1970 break; | 1970 break; |
1971 } | 1971 } |
1972 if (!dest_addr) { | 1972 if (!dest_addr) { |
1973 opts->deferred = defer_address(opts->deferred, after + disp, dst + 2); | 1973 opts->gen.deferred = defer_address(opts->gen.deferred, after + disp, dst + 2); |
1974 //dummy address to be replaced later, make sure it generates a 4-byte displacement | 1974 //dummy address to be replaced later, make sure it generates a 4-byte displacement |
1975 dest_addr = dst + 256; | 1975 dest_addr = dst + 256; |
1976 } | 1976 } |
1977 dst = jcc(dst, cond, dest_addr); | 1977 dst = jcc(dst, cond, dest_addr); |
1978 } | 1978 } |
1979 return dst; | 1979 return dst; |
1980 } | 1980 } |
1981 | 1981 |
1982 uint8_t * translate_m68k_scc(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) | 1982 code_ptr translate_m68k_scc(code_ptr dst, m68kinst * inst, x86_68k_options * opts) |
1983 { | 1983 { |
1984 uint8_t cond = inst->extra.cond; | 1984 uint8_t cond = inst->extra.cond; |
1985 x86_ea dst_op; | 1985 x86_ea dst_op; |
1986 inst->extra.size = OPSIZE_BYTE; | 1986 inst->extra.size = OPSIZE_BYTE; |
1987 dst = translate_m68k_dst(inst, &dst_op, dst, opts, 1); | 1987 dst = translate_m68k_dst(inst, &dst_op, dst, opts, 1); |
2037 dst = flag_to_reg(dst, FLAG_V, SCRATCH1, opts); | 2037 dst = flag_to_reg(dst, FLAG_V, SCRATCH1, opts); |
2038 dst = xor_flag_to_reg(dst, FLAG_N, SCRATCH1, opts); | 2038 dst = xor_flag_to_reg(dst, FLAG_N, SCRATCH1, opts); |
2039 dst = or_flag_to_reg(dst, FLAG_Z, SCRATCH1, opts); | 2039 dst = or_flag_to_reg(dst, FLAG_Z, SCRATCH1, opts); |
2040 break; | 2040 break; |
2041 } | 2041 } |
2042 uint8_t *true_off = dst + 1; | 2042 code_ptr true_off = dst + 1; |
2043 dst = jcc(dst, cc, dst+2); | 2043 dst = jcc(dst, cc, dst+2); |
2044 dst = cycles(dst, BUS); | 2044 dst = cycles(dst, BUS); |
2045 if (dst_op.mode == MODE_REG_DIRECT) { | 2045 if (dst_op.mode == MODE_REG_DIRECT) { |
2046 dst = mov_ir(dst, 0, dst_op.base, SZ_B); | 2046 dst = mov_ir(dst, 0, dst_op.base, SZ_B); |
2047 } else { | 2047 } else { |
2048 dst = mov_irdisp8(dst, 0, dst_op.base, dst_op.disp, SZ_B); | 2048 dst = mov_irdisp8(dst, 0, dst_op.base, dst_op.disp, SZ_B); |
2049 } | 2049 } |
2050 uint8_t *end_off = dst+1; | 2050 code_ptr end_off = dst+1; |
2051 dst = jmp(dst, dst+2); | 2051 dst = jmp(dst, dst+2); |
2052 *true_off = dst - (true_off+1); | 2052 *true_off = dst - (true_off+1); |
2053 dst = cycles(dst, 6); | 2053 dst = cycles(dst, 6); |
2054 if (dst_op.mode == MODE_REG_DIRECT) { | 2054 if (dst_op.mode == MODE_REG_DIRECT) { |
2055 dst = mov_ir(dst, 0xFF, dst_op.base, SZ_B); | 2055 dst = mov_ir(dst, 0xFF, dst_op.base, SZ_B); |
2060 } | 2060 } |
2061 dst = m68k_save_result(inst, dst, opts); | 2061 dst = m68k_save_result(inst, dst, opts); |
2062 return dst; | 2062 return dst; |
2063 } | 2063 } |
2064 | 2064 |
2065 uint8_t * translate_m68k_jmp(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) | 2065 code_ptr translate_m68k_jmp(code_ptr dst, m68kinst * inst, x86_68k_options * opts) |
2066 { | 2066 { |
2067 uint8_t * dest_addr, sec_reg; | 2067 code_ptr dest_addr; |
2068 uint8_t sec_reg; | |
2068 uint32_t m68k_addr; | 2069 uint32_t m68k_addr; |
2069 switch(inst->src.addr_mode) | 2070 switch(inst->src.addr_mode) |
2070 { | 2071 { |
2071 case MODE_AREG_INDIRECT: | 2072 case MODE_AREG_INDIRECT: |
2072 dst = cycles(dst, BUS*2); | 2073 dst = cycles(dst, BUS*2); |
2126 break; | 2127 break; |
2127 case MODE_PC_DISPLACE: | 2128 case MODE_PC_DISPLACE: |
2128 dst = cycles(dst, 10); | 2129 dst = cycles(dst, 10); |
2129 m68k_addr = inst->src.params.regs.displacement + inst->address + 2; | 2130 m68k_addr = inst->src.params.regs.displacement + inst->address + 2; |
2130 if ((m68k_addr & 0xFFFFFF) < 0x400000) { | 2131 if ((m68k_addr & 0xFFFFFF) < 0x400000) { |
2131 dest_addr = get_native_address(opts->native_code_map, m68k_addr); | 2132 dest_addr = get_native_address(opts->gen.native_code_map, m68k_addr); |
2132 if (!dest_addr) { | 2133 if (!dest_addr) { |
2133 opts->deferred = defer_address(opts->deferred, m68k_addr, dst + 1); | 2134 opts->gen.deferred = defer_address(opts->gen.deferred, m68k_addr, dst + 1); |
2134 //dummy address to be replaced later, make sure it generates a 4-byte displacement | 2135 //dummy address to be replaced later, make sure it generates a 4-byte displacement |
2135 dest_addr = dst + 256; | 2136 dest_addr = dst + 256; |
2136 } | 2137 } |
2137 dst = jmp(dst, dest_addr); | 2138 dst = jmp(dst, dest_addr); |
2138 } else { | 2139 } else { |
2184 case MODE_ABSOLUTE: | 2185 case MODE_ABSOLUTE: |
2185 case MODE_ABSOLUTE_SHORT: | 2186 case MODE_ABSOLUTE_SHORT: |
2186 dst = cycles(dst, inst->src.addr_mode == MODE_ABSOLUTE ? 12 : 10); | 2187 dst = cycles(dst, inst->src.addr_mode == MODE_ABSOLUTE ? 12 : 10); |
2187 m68k_addr = inst->src.params.immed; | 2188 m68k_addr = inst->src.params.immed; |
2188 if ((m68k_addr & 0xFFFFFF) < 0x400000) { | 2189 if ((m68k_addr & 0xFFFFFF) < 0x400000) { |
2189 dest_addr = get_native_address(opts->native_code_map, m68k_addr); | 2190 dest_addr = get_native_address(opts->gen.native_code_map, m68k_addr); |
2190 if (!dest_addr) { | 2191 if (!dest_addr) { |
2191 opts->deferred = defer_address(opts->deferred, m68k_addr, dst + 1); | 2192 opts->gen.deferred = defer_address(opts->gen.deferred, m68k_addr, dst + 1); |
2192 //dummy address to be replaced later, make sure it generates a 4-byte displacement | 2193 //dummy address to be replaced later, make sure it generates a 4-byte displacement |
2193 dest_addr = dst + 256; | 2194 dest_addr = dst + 256; |
2194 } | 2195 } |
2195 dst = jmp(dst, dest_addr); | 2196 dst = jmp(dst, dest_addr); |
2196 } else { | 2197 } else { |
2205 exit(1); | 2206 exit(1); |
2206 } | 2207 } |
2207 return dst; | 2208 return dst; |
2208 } | 2209 } |
2209 | 2210 |
2210 uint8_t * translate_m68k_jsr(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) | 2211 code_ptr translate_m68k_jsr(code_ptr dst, m68kinst * inst, x86_68k_options * opts) |
2211 { | 2212 { |
2212 uint8_t * dest_addr, sec_reg; | 2213 code_ptr dest_addr; |
2214 uint8_t sec_reg; | |
2213 uint32_t after; | 2215 uint32_t after; |
2214 uint32_t m68k_addr; | 2216 uint32_t m68k_addr; |
2215 switch(inst->src.addr_mode) | 2217 switch(inst->src.addr_mode) |
2216 { | 2218 { |
2217 case MODE_AREG_INDIRECT: | 2219 case MODE_AREG_INDIRECT: |
2298 dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); | 2300 dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); |
2299 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); | 2301 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); |
2300 dst = call(dst, opts->write_32_highfirst); | 2302 dst = call(dst, opts->write_32_highfirst); |
2301 m68k_addr = inst->src.params.regs.displacement + inst->address + 2; | 2303 m68k_addr = inst->src.params.regs.displacement + inst->address + 2; |
2302 if ((m68k_addr & 0xFFFFFF) < 0x400000) { | 2304 if ((m68k_addr & 0xFFFFFF) < 0x400000) { |
2303 dest_addr = get_native_address(opts->native_code_map, m68k_addr); | 2305 dest_addr = get_native_address(opts->gen.native_code_map, m68k_addr); |
2304 if (!dest_addr) { | 2306 if (!dest_addr) { |
2305 opts->deferred = defer_address(opts->deferred, m68k_addr, dst + 1); | 2307 opts->gen.deferred = defer_address(opts->gen.deferred, m68k_addr, dst + 1); |
2306 //dummy address to be replaced later, make sure it generates a 4-byte displacement | 2308 //dummy address to be replaced later, make sure it generates a 4-byte displacement |
2307 dest_addr = dst + 256; | 2309 dest_addr = dst + 256; |
2308 } | 2310 } |
2309 dst = jmp(dst, dest_addr); | 2311 dst = jmp(dst, dest_addr); |
2310 } else { | 2312 } else { |
2365 dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); | 2367 dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); |
2366 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); | 2368 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); |
2367 dst = call(dst, opts->write_32_highfirst); | 2369 dst = call(dst, opts->write_32_highfirst); |
2368 m68k_addr = inst->src.params.immed; | 2370 m68k_addr = inst->src.params.immed; |
2369 if ((m68k_addr & 0xFFFFFF) < 0x400000) { | 2371 if ((m68k_addr & 0xFFFFFF) < 0x400000) { |
2370 dest_addr = get_native_address(opts->native_code_map, m68k_addr); | 2372 dest_addr = get_native_address(opts->gen.native_code_map, m68k_addr); |
2371 if (!dest_addr) { | 2373 if (!dest_addr) { |
2372 opts->deferred = defer_address(opts->deferred, m68k_addr, dst + 1); | 2374 opts->gen.deferred = defer_address(opts->gen.deferred, m68k_addr, dst + 1); |
2373 //dummy address to be replaced later, make sure it generates a 4-byte displacement | 2375 //dummy address to be replaced later, make sure it generates a 4-byte displacement |
2374 dest_addr = dst + 256; | 2376 dest_addr = dst + 256; |
2375 } | 2377 } |
2376 dst = jmp(dst, dest_addr); | 2378 dst = jmp(dst, dest_addr); |
2377 } else { | 2379 } else { |
2386 exit(1); | 2388 exit(1); |
2387 } | 2389 } |
2388 return dst; | 2390 return dst; |
2389 } | 2391 } |
2390 | 2392 |
2391 uint8_t * translate_m68k_rts(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) | 2393 code_ptr translate_m68k_rts(code_ptr dst, m68kinst * inst, x86_68k_options * opts) |
2392 { | 2394 { |
2393 //TODO: Add cycles | 2395 //TODO: Add cycles |
2394 dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); | 2396 dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); |
2395 dst = add_ir(dst, 4, opts->aregs[7], SZ_D); | 2397 dst = add_ir(dst, 4, opts->aregs[7], SZ_D); |
2396 dst = call(dst, opts->read_32); | 2398 dst = call(dst, opts->read_32); |
2397 dst = call(dst, opts->native_addr); | 2399 dst = call(dst, opts->native_addr); |
2398 dst = jmp_r(dst, SCRATCH1); | 2400 dst = jmp_r(dst, SCRATCH1); |
2399 return dst; | 2401 return dst; |
2400 } | 2402 } |
2401 | 2403 |
2402 uint8_t * translate_m68k_dbcc(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) | 2404 code_ptr translate_m68k_dbcc(code_ptr dst, m68kinst * inst, x86_68k_options * opts) |
2403 { | 2405 { |
2404 //best case duration | 2406 //best case duration |
2405 dst = cycles(dst, 10); | 2407 dst = cycles(dst, 10); |
2406 uint8_t * skip_loc = NULL; | 2408 code_ptr skip_loc = NULL; |
2407 //TODO: Check if COND_TRUE technically valid here even though | 2409 //TODO: Check if COND_TRUE technically valid here even though |
2408 //it's basically a slow NOP | 2410 //it's basically a slow NOP |
2409 if (inst->extra.cond != COND_FALSE) { | 2411 if (inst->extra.cond != COND_FALSE) { |
2410 uint8_t cond = CC_NZ; | 2412 uint8_t cond = CC_NZ; |
2411 switch (inst->extra.cond) | 2413 switch (inst->extra.cond) |
2457 dst = cmp_ir(dst, -1, opts->dregs[inst->dst.params.regs.pri], SZ_W); | 2459 dst = cmp_ir(dst, -1, opts->dregs[inst->dst.params.regs.pri], SZ_W); |
2458 } else { | 2460 } else { |
2459 dst = sub_irdisp8(dst, 1, CONTEXT, offsetof(m68k_context, dregs) + 4 * inst->dst.params.regs.pri, SZ_W); | 2461 dst = sub_irdisp8(dst, 1, CONTEXT, offsetof(m68k_context, dregs) + 4 * inst->dst.params.regs.pri, SZ_W); |
2460 dst = cmp_irdisp8(dst, -1, CONTEXT, offsetof(m68k_context, dregs) + 4 * inst->dst.params.regs.pri, SZ_W); | 2462 dst = cmp_irdisp8(dst, -1, CONTEXT, offsetof(m68k_context, dregs) + 4 * inst->dst.params.regs.pri, SZ_W); |
2461 } | 2463 } |
2462 uint8_t *loop_end_loc = dst+1; | 2464 code_ptr loop_end_loc = dst+1; |
2463 dst = jcc(dst, CC_Z, dst+2); | 2465 dst = jcc(dst, CC_Z, dst+2); |
2464 uint32_t after = inst->address + 2; | 2466 uint32_t after = inst->address + 2; |
2465 uint8_t * dest_addr = get_native_address(opts->native_code_map, after + inst->src.params.immed); | 2467 code_ptr dest_addr = get_native_address(opts->gen.native_code_map, after + inst->src.params.immed); |
2466 if (!dest_addr) { | 2468 if (!dest_addr) { |
2467 opts->deferred = defer_address(opts->deferred, after + inst->src.params.immed, dst + 1); | 2469 opts->gen.deferred = defer_address(opts->gen.deferred, after + inst->src.params.immed, dst + 1); |
2468 //dummy address to be replaced later, make sure it generates a 4-byte displacement | 2470 //dummy address to be replaced later, make sure it generates a 4-byte displacement |
2469 dest_addr = dst + 256; | 2471 dest_addr = dst + 256; |
2470 } | 2472 } |
2471 dst = jmp(dst, dest_addr); | 2473 dst = jmp(dst, dest_addr); |
2472 *loop_end_loc = dst - (loop_end_loc+1); | 2474 *loop_end_loc = dst - (loop_end_loc+1); |
2478 dst = cycles(dst, 4); | 2480 dst = cycles(dst, 4); |
2479 } | 2481 } |
2480 return dst; | 2482 return dst; |
2481 } | 2483 } |
2482 | 2484 |
2483 uint8_t * translate_m68k_link(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) | 2485 code_ptr translate_m68k_link(code_ptr dst, m68kinst * inst, x86_68k_options * opts) |
2484 { | 2486 { |
2485 int8_t reg = native_reg(&(inst->src), opts); | 2487 int8_t reg = native_reg(&(inst->src), opts); |
2486 //compensate for displacement word | 2488 //compensate for displacement word |
2487 dst = cycles(dst, BUS); | 2489 dst = cycles(dst, BUS); |
2488 dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); | 2490 dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); |
2502 //prefetch | 2504 //prefetch |
2503 dst = cycles(dst, BUS); | 2505 dst = cycles(dst, BUS); |
2504 return dst; | 2506 return dst; |
2505 } | 2507 } |
2506 | 2508 |
2507 uint8_t * translate_m68k_movep(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) | 2509 code_ptr translate_m68k_movep(code_ptr dst, m68kinst * inst, x86_68k_options * opts) |
2508 { | 2510 { |
2509 int8_t reg; | 2511 int8_t reg; |
2510 dst = cycles(dst, BUS*2); | 2512 dst = cycles(dst, BUS*2); |
2511 if (inst->src.addr_mode == MODE_REG) { | 2513 if (inst->src.addr_mode == MODE_REG) { |
2512 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | 2514 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { |
2611 } | 2613 } |
2612 } | 2614 } |
2613 return dst; | 2615 return dst; |
2614 } | 2616 } |
2615 | 2617 |
2616 uint8_t * translate_m68k_cmp(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) | 2618 code_ptr translate_m68k_cmp(code_ptr dst, m68kinst * inst, x86_68k_options * opts) |
2617 { | 2619 { |
2618 uint8_t size = inst->extra.size; | 2620 uint8_t size = inst->extra.size; |
2619 x86_ea src_op, dst_op; | 2621 x86_ea src_op, dst_op; |
2620 dst = translate_m68k_src(inst, &src_op, dst, opts); | 2622 dst = translate_m68k_src(inst, &src_op, dst, opts); |
2621 if (inst->dst.addr_mode == MODE_AREG_POSTINC) { | 2623 if (inst->dst.addr_mode == MODE_AREG_POSTINC) { |
2650 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 2652 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
2651 dst = set_flag_cond(dst, CC_O, FLAG_V, opts); | 2653 dst = set_flag_cond(dst, CC_O, FLAG_V, opts); |
2652 return dst; | 2654 return dst; |
2653 } | 2655 } |
2654 | 2656 |
2655 typedef uint8_t * (*shift_ir_t)(uint8_t * out, uint8_t val, uint8_t dst, uint8_t size); | 2657 typedef code_ptr (*shift_ir_t)(code_ptr out, uint8_t val, uint8_t dst, uint8_t size); |
2656 typedef uint8_t * (*shift_irdisp8_t)(uint8_t * out, uint8_t val, uint8_t dst_base, int8_t disp, uint8_t size); | 2658 typedef code_ptr (*shift_irdisp8_t)(code_ptr out, uint8_t val, uint8_t dst_base, int8_t disp, uint8_t size); |
2657 typedef uint8_t * (*shift_clr_t)(uint8_t * out, uint8_t dst, uint8_t size); | 2659 typedef code_ptr (*shift_clr_t)(code_ptr out, uint8_t dst, uint8_t size); |
2658 typedef uint8_t * (*shift_clrdisp8_t)(uint8_t * out, uint8_t dst_base, int8_t disp, uint8_t size); | 2660 typedef code_ptr (*shift_clrdisp8_t)(code_ptr out, uint8_t dst_base, int8_t disp, uint8_t size); |
2659 | 2661 |
2660 uint8_t * translate_shift(uint8_t * dst, m68kinst * inst, x86_ea *src_op, x86_ea * dst_op, x86_68k_options * opts, shift_ir_t shift_ir, shift_irdisp8_t shift_irdisp8, shift_clr_t shift_clr, shift_clrdisp8_t shift_clrdisp8, shift_ir_t special, shift_irdisp8_t special_disp8) | 2662 code_ptr translate_shift(code_ptr dst, m68kinst * inst, x86_ea *src_op, x86_ea * dst_op, x86_68k_options * opts, shift_ir_t shift_ir, shift_irdisp8_t shift_irdisp8, shift_clr_t shift_clr, shift_clrdisp8_t shift_clrdisp8, shift_ir_t special, shift_irdisp8_t special_disp8) |
2661 { | 2663 { |
2662 uint8_t * end_off = NULL; | 2664 code_ptr end_off = NULL; |
2663 uint8_t * nz_off = NULL; | 2665 code_ptr nz_off = NULL; |
2664 uint8_t * z_off = NULL; | 2666 code_ptr z_off = NULL; |
2665 if (inst->src.addr_mode == MODE_UNUSED) { | 2667 if (inst->src.addr_mode == MODE_UNUSED) { |
2666 dst = cycles(dst, BUS); | 2668 dst = cycles(dst, BUS); |
2667 //Memory shift | 2669 //Memory shift |
2668 dst = shift_ir(dst, 1, dst_op->base, SZ_W); | 2670 dst = shift_ir(dst, 1, dst_op->base, SZ_W); |
2669 } else { | 2671 } else { |
2676 dst = shift_ir(dst, 1, dst_op->base, inst->extra.size); | 2678 dst = shift_ir(dst, 1, dst_op->base, inst->extra.size); |
2677 } else { | 2679 } else { |
2678 dst = shift_irdisp8(dst, 1, dst_op->base, dst_op->disp, inst->extra.size); | 2680 dst = shift_irdisp8(dst, 1, dst_op->base, dst_op->disp, inst->extra.size); |
2679 } | 2681 } |
2680 //dst = setcc_r(dst, CC_O, FLAG_V); | 2682 //dst = setcc_r(dst, CC_O, FLAG_V); |
2681 uint8_t *after_flag_set = dst+1; | 2683 code_ptr after_flag_set = dst+1; |
2682 dst = jcc(dst, CC_NO, dst+2); | 2684 dst = jcc(dst, CC_NO, dst+2); |
2683 dst = set_flag(dst, 1, FLAG_V, opts); | 2685 dst = set_flag(dst, 1, FLAG_V, opts); |
2684 *after_flag_set = dst - (after_flag_set+1); | 2686 *after_flag_set = dst - (after_flag_set+1); |
2685 } | 2687 } |
2686 } else { | 2688 } else { |
2724 dst = add_rr(dst, RCX, CYCLES, SZ_D); | 2726 dst = add_rr(dst, RCX, CYCLES, SZ_D); |
2725 if (inst->op == M68K_ASL) { | 2727 if (inst->op == M68K_ASL) { |
2726 //ASL has Overflow flag behavior that depends on all of the bits shifted through the MSB | 2728 //ASL has Overflow flag behavior that depends on all of the bits shifted through the MSB |
2727 //Easiest way to deal with this is to shift one bit at a time | 2729 //Easiest way to deal with this is to shift one bit at a time |
2728 dst = set_flag(dst, 0, FLAG_V, opts); | 2730 dst = set_flag(dst, 0, FLAG_V, opts); |
2729 uint8_t * loop_start = dst; | 2731 code_ptr loop_start = dst; |
2730 if (dst_op->mode == MODE_REG_DIRECT) { | 2732 if (dst_op->mode == MODE_REG_DIRECT) { |
2731 dst = shift_ir(dst, 1, dst_op->base, inst->extra.size); | 2733 dst = shift_ir(dst, 1, dst_op->base, inst->extra.size); |
2732 } else { | 2734 } else { |
2733 dst = shift_irdisp8(dst, 1, dst_op->base, dst_op->disp, inst->extra.size); | 2735 dst = shift_irdisp8(dst, 1, dst_op->base, dst_op->disp, inst->extra.size); |
2734 } | 2736 } |
2735 //dst = setcc_r(dst, CC_O, FLAG_V); | 2737 //dst = setcc_r(dst, CC_O, FLAG_V); |
2736 uint8_t *after_flag_set = dst+1; | 2738 code_ptr after_flag_set = dst+1; |
2737 dst = jcc(dst, CC_NO, dst+2); | 2739 dst = jcc(dst, CC_NO, dst+2); |
2738 dst = set_flag(dst, 1, FLAG_V, opts); | 2740 dst = set_flag(dst, 1, FLAG_V, opts); |
2739 *after_flag_set = dst - (after_flag_set+1); | 2741 *after_flag_set = dst - (after_flag_set+1); |
2740 dst = loop(dst, loop_start); | 2742 dst = loop(dst, loop_start); |
2741 } else { | 2743 } else { |
2742 //x86 shifts modulo 32 for operand sizes less than 64-bits | 2744 //x86 shifts modulo 32 for operand sizes less than 64-bits |
2743 //but M68K shifts modulo 64, so we need to check for large shifts here | 2745 //but M68K shifts modulo 64, so we need to check for large shifts here |
2744 dst = cmp_ir(dst, 32, RCX, SZ_B); | 2746 dst = cmp_ir(dst, 32, RCX, SZ_B); |
2745 uint8_t * norm_shift_off = dst + 1; | 2747 code_ptr norm_shift_off = dst + 1; |
2746 dst = jcc(dst, CC_L, dst+2); | 2748 dst = jcc(dst, CC_L, dst+2); |
2747 if (special) { | 2749 if (special) { |
2748 uint8_t *after_flag_set = NULL; | 2750 code_ptr after_flag_set = NULL; |
2749 if (inst->extra.size == OPSIZE_LONG) { | 2751 if (inst->extra.size == OPSIZE_LONG) { |
2750 uint8_t * neq_32_off = dst + 1; | 2752 code_ptr neq_32_off = dst + 1; |
2751 dst = jcc(dst, CC_NZ, dst+2); | 2753 dst = jcc(dst, CC_NZ, dst+2); |
2752 | 2754 |
2753 //set the carry bit to the lsb | 2755 //set the carry bit to the lsb |
2754 if (dst_op->mode == MODE_REG_DIRECT) { | 2756 if (dst_op->mode == MODE_REG_DIRECT) { |
2755 dst = special(dst, 1, dst_op->base, SZ_D); | 2757 dst = special(dst, 1, dst_op->base, SZ_D); |
2821 return dst; | 2823 return dst; |
2822 } | 2824 } |
2823 | 2825 |
2824 #define BIT_SUPERVISOR 5 | 2826 #define BIT_SUPERVISOR 5 |
2825 | 2827 |
2826 uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) | 2828 code_ptr translate_m68k(code_ptr dst, m68kinst * inst, x86_68k_options * opts) |
2827 { | 2829 { |
2828 uint8_t * end_off, *zero_off, *norm_off; | 2830 code_ptr end_off, zero_off, norm_off; |
2829 uint8_t dst_reg; | 2831 uint8_t dst_reg; |
2830 dst = check_cycles_int(dst, inst->address, opts); | 2832 dst = check_cycles_int(dst, inst->address, opts); |
2831 if (inst->op == M68K_MOVE) { | 2833 if (inst->op == M68K_MOVE) { |
2832 return translate_m68k_move(dst, inst, opts); | 2834 return translate_m68k_move(dst, inst, opts); |
2833 } else if(inst->op == M68K_LEA) { | 2835 } else if(inst->op == M68K_LEA) { |
2861 } else if(inst->op == M68K_INVALID) { | 2863 } else if(inst->op == M68K_INVALID) { |
2862 if (inst->src.params.immed == 0x7100) { | 2864 if (inst->src.params.immed == 0x7100) { |
2863 return retn(dst); | 2865 return retn(dst); |
2864 } | 2866 } |
2865 dst = mov_ir(dst, inst->address, SCRATCH1, SZ_D); | 2867 dst = mov_ir(dst, inst->address, SCRATCH1, SZ_D); |
2866 return call(dst, (uint8_t *)m68k_invalid); | 2868 return call(dst, (code_ptr)m68k_invalid); |
2867 } else if(inst->op == M68K_CMP) { | 2869 } else if(inst->op == M68K_CMP) { |
2868 return translate_m68k_cmp(dst, inst, opts); | 2870 return translate_m68k_cmp(dst, inst, opts); |
2869 } | 2871 } |
2870 x86_ea src_op, dst_op; | 2872 x86_ea src_op, dst_op; |
2871 if (inst->src.addr_mode != MODE_UNUSED) { | 2873 if (inst->src.addr_mode != MODE_UNUSED) { |
2893 } | 2895 } |
2894 } | 2896 } |
2895 dst = flag_to_carry(dst, FLAG_X, opts); | 2897 dst = flag_to_carry(dst, FLAG_X, opts); |
2896 dst = jcc(dst, CC_NC, dst+5); | 2898 dst = jcc(dst, CC_NC, dst+5); |
2897 dst = add_ir(dst, 1, SCRATCH1, SZ_B); | 2899 dst = add_ir(dst, 1, SCRATCH1, SZ_B); |
2898 dst = call(dst, (uint8_t *)bcd_add); | 2900 dst = call(dst, (code_ptr)bcd_add); |
2899 dst = reg_to_flag(dst, CH, FLAG_C, opts); | 2901 dst = reg_to_flag(dst, CH, FLAG_C, opts); |
2900 dst = reg_to_flag(dst, CH, FLAG_X, opts); | 2902 dst = reg_to_flag(dst, CH, FLAG_X, opts); |
2901 dst = cmp_ir(dst, 0, SCRATCH1, SZ_B); | 2903 dst = cmp_ir(dst, 0, SCRATCH1, SZ_B); |
2902 dst = jcc(dst, CC_Z, dst+4); | 2904 dst = jcc(dst, CC_Z, dst+4); |
2903 dst = set_flag(dst, 0, FLAG_Z, opts); | 2905 dst = set_flag(dst, 0, FLAG_Z, opts); |
2959 dst = adc_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 2961 dst = adc_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
2960 } | 2962 } |
2961 } | 2963 } |
2962 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); | 2964 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); |
2963 | 2965 |
2964 uint8_t *after_flag_set = dst+1; | 2966 code_ptr after_flag_set = dst+1; |
2965 dst = jcc(dst, CC_Z, dst+2); | 2967 dst = jcc(dst, CC_Z, dst+2); |
2966 dst = set_flag(dst, 0, FLAG_Z, opts); | 2968 dst = set_flag(dst, 0, FLAG_Z, opts); |
2967 *after_flag_set = dst - (after_flag_set+1); | 2969 *after_flag_set = dst - (after_flag_set+1); |
2968 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 2970 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
2969 dst = set_flag_cond(dst, CC_O, FLAG_V, opts); | 2971 dst = set_flag_cond(dst, CC_O, FLAG_V, opts); |
3176 isize = 6; | 3178 isize = 6; |
3177 break; | 3179 break; |
3178 default: | 3180 default: |
3179 isize = 2; | 3181 isize = 2; |
3180 } | 3182 } |
3181 uint8_t * passed = dst+1; | 3183 code_ptr passed = dst+1; |
3182 dst = jcc(dst, CC_GE, dst+2); | 3184 dst = jcc(dst, CC_GE, dst+2); |
3183 dst = set_flag(dst, 1, FLAG_N, opts); | 3185 dst = set_flag(dst, 1, FLAG_N, opts); |
3184 dst = mov_ir(dst, VECTOR_CHK, SCRATCH2, SZ_D); | 3186 dst = mov_ir(dst, VECTOR_CHK, SCRATCH2, SZ_D); |
3185 dst = mov_ir(dst, inst->address+isize, SCRATCH1, SZ_D); | 3187 dst = mov_ir(dst, inst->address+isize, SCRATCH1, SZ_D); |
3186 dst = jmp(dst, opts->trap); | 3188 dst = jmp(dst, opts->trap); |
3237 } else { | 3239 } else { |
3238 dst = movzx_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH2, SZ_W, SZ_D); | 3240 dst = movzx_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH2, SZ_W, SZ_D); |
3239 } | 3241 } |
3240 } | 3242 } |
3241 dst = cmp_ir(dst, 0, SCRATCH2, SZ_D); | 3243 dst = cmp_ir(dst, 0, SCRATCH2, SZ_D); |
3242 uint8_t * not_zero = dst+1; | 3244 code_ptr not_zero = dst+1; |
3243 dst = jcc(dst, CC_NZ, dst+2); | 3245 dst = jcc(dst, CC_NZ, dst+2); |
3244 dst = pop_r(dst, RAX); | 3246 dst = pop_r(dst, RAX); |
3245 dst = pop_r(dst, RDX); | 3247 dst = pop_r(dst, RDX); |
3246 dst = mov_ir(dst, VECTOR_INT_DIV_ZERO, SCRATCH2, SZ_D); | 3248 dst = mov_ir(dst, VECTOR_INT_DIV_ZERO, SCRATCH2, SZ_D); |
3247 dst = mov_ir(dst, inst->address+2, SCRATCH1, SZ_D); | 3249 dst = mov_ir(dst, inst->address+2, SCRATCH1, SZ_D); |
3255 if (inst->op == M68K_DIVS) { | 3257 if (inst->op == M68K_DIVS) { |
3256 dst = idiv_r(dst, SCRATCH2, SZ_D); | 3258 dst = idiv_r(dst, SCRATCH2, SZ_D); |
3257 } else { | 3259 } else { |
3258 dst = div_r(dst, SCRATCH2, SZ_D); | 3260 dst = div_r(dst, SCRATCH2, SZ_D); |
3259 } | 3261 } |
3260 uint8_t * skip_sec_check; | 3262 code_ptr skip_sec_check; |
3261 if (inst->op == M68K_DIVS) { | 3263 if (inst->op == M68K_DIVS) { |
3262 dst = cmp_ir(dst, 0x8000, RAX, SZ_D); | 3264 dst = cmp_ir(dst, 0x8000, RAX, SZ_D); |
3263 skip_sec_check = dst + 1; | 3265 skip_sec_check = dst + 1; |
3264 dst = jcc(dst, CC_GE, dst+2); | 3266 dst = jcc(dst, CC_GE, dst+2); |
3265 dst = cmp_ir(dst, -0x8000, RAX, SZ_D); | 3267 dst = cmp_ir(dst, -0x8000, RAX, SZ_D); |
3368 dst = mov_rrdisp8(dst, SCRATCH2, src_op.base, src_op.disp, SZ_D); | 3370 dst = mov_rrdisp8(dst, SCRATCH2, src_op.base, src_op.disp, SZ_D); |
3369 } | 3371 } |
3370 } | 3372 } |
3371 break; | 3373 break; |
3372 case M68K_ILLEGAL: | 3374 case M68K_ILLEGAL: |
3373 dst = call(dst, opts->save_context); | 3375 dst = call(dst, opts->gen.save_context); |
3374 #ifdef X86_64 | 3376 #ifdef X86_64 |
3375 dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); | 3377 dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); |
3376 #else | 3378 #else |
3377 dst = push_r(dst, CONTEXT); | 3379 dst = push_r(dst, CONTEXT); |
3378 #endif | 3380 #endif |
3379 dst = call(dst, (uint8_t *)print_regs_exit); | 3381 dst = call(dst, (code_ptr)print_regs_exit); |
3380 break; | 3382 break; |
3381 case M68K_MOVE_FROM_SR: | 3383 case M68K_MOVE_FROM_SR: |
3382 //TODO: Trap if not in system mode | 3384 //TODO: Trap if not in system mode |
3383 dst = call(dst, opts->get_sr); | 3385 dst = call(dst, opts->get_sr); |
3384 if (dst_op.mode == MODE_REG_DIRECT) { | 3386 if (dst_op.mode == MODE_REG_DIRECT) { |
3525 dst = flag_to_carry(dst, FLAG_X, opts); | 3527 dst = flag_to_carry(dst, FLAG_X, opts); |
3526 dst = sbb_rdisp8r(dst, dst_op.base, dst_op.disp, SCRATCH1, inst->extra.size); | 3528 dst = sbb_rdisp8r(dst, dst_op.base, dst_op.disp, SCRATCH1, inst->extra.size); |
3527 dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, inst->extra.size); | 3529 dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, inst->extra.size); |
3528 } | 3530 } |
3529 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); | 3531 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); |
3530 uint8_t *after_flag_set = dst+1; | 3532 code_ptr after_flag_set = dst+1; |
3531 dst = jcc(dst, CC_Z, dst+2); | 3533 dst = jcc(dst, CC_Z, dst+2); |
3532 dst = set_flag(dst, 0, FLAG_Z, opts); | 3534 dst = set_flag(dst, 0, FLAG_Z, opts); |
3533 *after_flag_set = dst - (after_flag_set+1); | 3535 *after_flag_set = dst - (after_flag_set+1); |
3534 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 3536 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
3535 dst = set_flag_cond(dst, CC_O, FLAG_V, opts); | 3537 dst = set_flag_cond(dst, CC_O, FLAG_V, opts); |
3607 dst = call(dst, opts->do_sync); | 3609 dst = call(dst, opts->do_sync); |
3608 } | 3610 } |
3609 } | 3611 } |
3610 break; | 3612 break; |
3611 case M68K_RESET: | 3613 case M68K_RESET: |
3612 dst = call(dst, opts->save_context); | 3614 dst = call(dst, opts->gen.save_context); |
3613 #ifdef X86_64 | 3615 #ifdef X86_64 |
3614 dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); | 3616 dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); |
3615 #else | 3617 #else |
3616 dst = push_r(dst, CONTEXT); | 3618 dst = push_r(dst, CONTEXT); |
3617 #endif | 3619 #endif |
3618 dst = call(dst, (uint8_t *)print_regs_exit); | 3620 dst = call(dst, (code_ptr)print_regs_exit); |
3619 break; | 3621 break; |
3620 case M68K_ROL: | 3622 case M68K_ROL: |
3621 case M68K_ROR: | 3623 case M68K_ROR: |
3622 dst = set_flag(dst, 0, FLAG_V, opts); | 3624 dst = set_flag(dst, 0, FLAG_V, opts); |
3623 if (inst->src.addr_mode == MODE_UNUSED) { | 3625 if (inst->src.addr_mode == MODE_UNUSED) { |
3886 } | 3888 } |
3887 } | 3889 } |
3888 dst = flag_to_carry(dst, FLAG_X, opts); | 3890 dst = flag_to_carry(dst, FLAG_X, opts); |
3889 dst = jcc(dst, CC_NC, dst+5); | 3891 dst = jcc(dst, CC_NC, dst+5); |
3890 dst = sub_ir(dst, 1, SCRATCH1, SZ_B); | 3892 dst = sub_ir(dst, 1, SCRATCH1, SZ_B); |
3891 dst = call(dst, (uint8_t *)bcd_sub); | 3893 dst = call(dst, (code_ptr)bcd_sub); |
3892 dst = reg_to_flag(dst, CH, FLAG_C, opts); | 3894 dst = reg_to_flag(dst, CH, FLAG_C, opts); |
3893 dst = reg_to_flag(dst, CH, FLAG_X, opts); | 3895 dst = reg_to_flag(dst, CH, FLAG_X, opts); |
3894 dst = cmp_ir(dst, 0, SCRATCH1, SZ_B); | 3896 dst = cmp_ir(dst, 0, SCRATCH1, SZ_B); |
3895 uint8_t *after_flag_set = dst+1; | 3897 code_ptr after_flag_set = dst+1; |
3896 dst = jcc(dst, CC_Z, dst+2); | 3898 dst = jcc(dst, CC_Z, dst+2); |
3897 dst = set_flag(dst, 0, FLAG_Z, opts); | 3899 dst = set_flag(dst, 0, FLAG_Z, opts); |
3898 *after_flag_set = dst - (after_flag_set+1); | 3900 *after_flag_set = dst - (after_flag_set+1); |
3899 if (dst_op.base != SCRATCH1) { | 3901 if (dst_op.base != SCRATCH1) { |
3900 if (dst_op.mode == MODE_REG_DIRECT) { | 3902 if (dst_op.mode == MODE_REG_DIRECT) { |
3921 //leave supervisor mode | 3923 //leave supervisor mode |
3922 dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); | 3924 dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); |
3923 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->aregs[7], SZ_D); | 3925 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->aregs[7], SZ_D); |
3924 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); | 3926 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); |
3925 } | 3927 } |
3926 uint8_t * loop_top = dst; | 3928 code_ptr loop_top = dst; |
3927 dst = call(dst, opts->do_sync); | 3929 dst = call(dst, opts->do_sync); |
3928 dst = cmp_rr(dst, LIMIT, CYCLES, SZ_D); | 3930 dst = cmp_rr(dst, LIMIT, CYCLES, SZ_D); |
3929 uint8_t * normal_cycle_up = dst + 1; | 3931 code_ptr normal_cycle_up = dst + 1; |
3930 dst = jcc(dst, CC_A, dst+2); | 3932 dst = jcc(dst, CC_A, dst+2); |
3931 dst = cycles(dst, BUS); | 3933 dst = cycles(dst, BUS); |
3932 uint8_t * after_cycle_up = dst + 1; | 3934 code_ptr after_cycle_up = dst + 1; |
3933 dst = jmp(dst, dst+2); | 3935 dst = jmp(dst, dst+2); |
3934 *normal_cycle_up = dst - (normal_cycle_up + 1); | 3936 *normal_cycle_up = dst - (normal_cycle_up + 1); |
3935 dst = mov_rr(dst, LIMIT, CYCLES, SZ_D); | 3937 dst = mov_rr(dst, LIMIT, CYCLES, SZ_D); |
3936 *after_cycle_up = dst - (after_cycle_up+1); | 3938 *after_cycle_up = dst - (after_cycle_up+1); |
3937 dst = cmp_rdisp8r(dst, CONTEXT, offsetof(m68k_context, int_cycle), CYCLES, SZ_D); | 3939 dst = cmp_rdisp8r(dst, CONTEXT, offsetof(m68k_context, int_cycle), CYCLES, SZ_D); |
3989 } | 3991 } |
3990 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); | 3992 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); |
3991 if (opts->flag_regs[FLAG_C] < 0) { | 3993 if (opts->flag_regs[FLAG_C] < 0) { |
3992 dst = set_flag_cond(dst, CC_C, FLAG_X, opts); | 3994 dst = set_flag_cond(dst, CC_C, FLAG_X, opts); |
3993 } | 3995 } |
3994 uint8_t *after_flag_set = dst+1; | 3996 code_ptr after_flag_set = dst+1; |
3995 dst = jcc(dst, CC_Z, dst+2); | 3997 dst = jcc(dst, CC_Z, dst+2); |
3996 dst = set_flag(dst, 0, FLAG_Z, opts); | 3998 dst = set_flag(dst, 0, FLAG_Z, opts); |
3997 *after_flag_set = dst - (after_flag_set+1); | 3999 *after_flag_set = dst - (after_flag_set+1); |
3998 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 4000 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
3999 dst = set_flag_cond(dst, CC_O, FLAG_V, opts); | 4001 dst = set_flag_cond(dst, CC_O, FLAG_V, opts); |
4069 } | 4071 } |
4070 | 4072 |
4071 void m68k_handle_deferred(m68k_context * context) | 4073 void m68k_handle_deferred(m68k_context * context) |
4072 { | 4074 { |
4073 x86_68k_options * opts = context->options; | 4075 x86_68k_options * opts = context->options; |
4074 process_deferred(&opts->deferred, context, (native_addr_func)get_native_from_context); | 4076 process_deferred(&opts->gen.deferred, context, (native_addr_func)get_native_from_context); |
4075 if (opts->deferred) { | 4077 if (opts->gen.deferred) { |
4076 translate_m68k_stream(opts->deferred->address, context); | 4078 translate_m68k_stream(opts->gen.deferred->address, context); |
4077 } | 4079 } |
4078 } | 4080 } |
4079 | 4081 |
4080 uint8_t * translate_m68k_stream(uint32_t address, m68k_context * context) | 4082 code_ptr translate_m68k_stream(uint32_t address, m68k_context * context) |
4081 { | 4083 { |
4082 m68kinst instbuf; | 4084 m68kinst instbuf; |
4083 x86_68k_options * opts = context->options; | 4085 x86_68k_options * opts = context->options; |
4084 uint8_t * dst = opts->cur_code; | 4086 code_ptr dst = opts->gen.cur_code; |
4085 uint8_t * dst_end = opts->code_end; | 4087 code_ptr dst_end = opts->gen.code_end; |
4086 address &= 0xFFFFFF; | 4088 address &= 0xFFFFFF; |
4087 if(get_native_address(opts->native_code_map, address)) { | 4089 if(get_native_address(opts->gen.native_code_map, address)) { |
4088 return dst; | 4090 return dst; |
4089 } | 4091 } |
4090 char disbuf[1024]; | 4092 char disbuf[1024]; |
4091 uint16_t *encoded, *next; | 4093 uint16_t *encoded, *next; |
4092 if ((address & 0xFFFFFF) < 0x400000) { | 4094 if ((address & 0xFFFFFF) < 0x400000) { |
4106 if (dst_end-dst < 5) { | 4108 if (dst_end-dst < 5) { |
4107 puts("out of code memory, not enough space for jmp to next chunk"); | 4109 puts("out of code memory, not enough space for jmp to next chunk"); |
4108 exit(1); | 4110 exit(1); |
4109 } | 4111 } |
4110 size_t size = 1024*1024; | 4112 size_t size = 1024*1024; |
4111 opts->cur_code = alloc_code(&size); | 4113 opts->gen.cur_code = alloc_code(&size); |
4112 opts->code_end = opts->cur_code + size; | 4114 opts->gen.code_end = opts->gen.cur_code + size; |
4113 jmp(dst, opts->cur_code); | 4115 jmp(dst, opts->gen.cur_code); |
4114 dst = opts->cur_code; | 4116 dst = opts->gen.cur_code; |
4115 dst_end = opts->code_end; | 4117 dst_end = opts->gen.code_end; |
4116 } | 4118 } |
4117 if (address >= 0x400000 && address < 0xE00000) { | 4119 if (address >= 0x400000 && address < 0xE00000) { |
4118 dst = xor_rr(dst, RDI, RDI, SZ_D); | 4120 dst = xor_rr(dst, RDI, RDI, SZ_D); |
4119 #ifdef X86_32 | 4121 #ifdef X86_32 |
4120 dst = push_r(dst, RDI); | 4122 dst = push_r(dst, RDI); |
4121 #endif | 4123 #endif |
4122 dst = call(dst, (uint8_t *)exit); | 4124 dst = call(dst, (code_ptr)exit); |
4123 break; | 4125 break; |
4124 } | 4126 } |
4125 uint8_t * existing = get_native_address(opts->native_code_map, address); | 4127 code_ptr existing = get_native_address(opts->gen.native_code_map, address); |
4126 if (existing) { | 4128 if (existing) { |
4127 dst = jmp(dst, existing); | 4129 dst = jmp(dst, existing); |
4128 break; | 4130 break; |
4129 } | 4131 } |
4130 next = m68k_decode(encoded, &instbuf, address); | 4132 next = m68k_decode(encoded, &instbuf, address); |
4134 uint16_t m68k_size = (next-encoded)*2; | 4136 uint16_t m68k_size = (next-encoded)*2; |
4135 address += m68k_size; | 4137 address += m68k_size; |
4136 encoded = next; | 4138 encoded = next; |
4137 //m68k_disasm(&instbuf, disbuf); | 4139 //m68k_disasm(&instbuf, disbuf); |
4138 //printf("%X: %s\n", instbuf.address, disbuf); | 4140 //printf("%X: %s\n", instbuf.address, disbuf); |
4139 uint8_t * after = translate_m68k(dst, &instbuf, opts); | 4141 code_ptr after = translate_m68k(dst, &instbuf, opts); |
4140 map_native_address(context, instbuf.address, dst, m68k_size, after-dst); | 4142 map_native_address(context, instbuf.address, dst, m68k_size, after-dst); |
4141 dst = after; | 4143 dst = after; |
4142 } while(!m68k_is_terminal(&instbuf)); | 4144 } while(!m68k_is_terminal(&instbuf)); |
4143 process_deferred(&opts->deferred, context, (native_addr_func)get_native_from_context); | 4145 process_deferred(&opts->gen.deferred, context, (native_addr_func)get_native_from_context); |
4144 if (opts->deferred) { | 4146 if (opts->gen.deferred) { |
4145 address = opts->deferred->address; | 4147 address = opts->gen.deferred->address; |
4146 if ((address & 0xFFFFFF) < 0x400000) { | 4148 if ((address & 0xFFFFFF) < 0x400000) { |
4147 encoded = context->mem_pointers[0] + (address & 0xFFFFFF)/2; | 4149 encoded = context->mem_pointers[0] + (address & 0xFFFFFF)/2; |
4148 } else if ((address & 0xFFFFFF) > 0xE00000) { | 4150 } else if ((address & 0xFFFFFF) > 0xE00000) { |
4149 encoded = context->mem_pointers[1] + (address & 0xFFFF)/2; | 4151 encoded = context->mem_pointers[1] + (address & 0xFFFF)/2; |
4150 } else { | 4152 } else { |
4153 } | 4155 } |
4154 } else { | 4156 } else { |
4155 encoded = NULL; | 4157 encoded = NULL; |
4156 } | 4158 } |
4157 } while(encoded != NULL); | 4159 } while(encoded != NULL); |
4158 opts->cur_code = dst; | 4160 opts->gen.cur_code = dst; |
4159 return dst; | 4161 return dst; |
4160 } | 4162 } |
4161 | 4163 |
4162 uint8_t * get_native_address_trans(m68k_context * context, uint32_t address) | 4164 code_ptr get_native_address_trans(m68k_context * context, uint32_t address) |
4163 { | 4165 { |
4164 address &= 0xFFFFFF; | 4166 address &= 0xFFFFFF; |
4165 uint8_t * ret = get_native_address(context->native_code_map, address); | 4167 code_ptr ret = get_native_address(context->native_code_map, address); |
4166 if (!ret) { | 4168 if (!ret) { |
4167 translate_m68k_stream(address, context); | 4169 translate_m68k_stream(address, context); |
4168 ret = get_native_address(context->native_code_map, address); | 4170 ret = get_native_address(context->native_code_map, address); |
4169 } | 4171 } |
4170 return ret; | 4172 return ret; |
4172 | 4174 |
4173 void * m68k_retranslate_inst(uint32_t address, m68k_context * context) | 4175 void * m68k_retranslate_inst(uint32_t address, m68k_context * context) |
4174 { | 4176 { |
4175 x86_68k_options * opts = context->options; | 4177 x86_68k_options * opts = context->options; |
4176 uint8_t orig_size = get_native_inst_size(opts, address); | 4178 uint8_t orig_size = get_native_inst_size(opts, address); |
4177 uint8_t * orig_start = get_native_address(context->native_code_map, address); | 4179 code_ptr orig_start = get_native_address(context->native_code_map, address); |
4178 uint32_t orig = address; | 4180 uint32_t orig = address; |
4179 address &= 0xFFFF; | 4181 address &= 0xFFFF; |
4180 uint8_t * dst = opts->cur_code; | 4182 code_ptr dst = opts->gen.cur_code; |
4181 uint8_t * dst_end = opts->code_end; | 4183 code_ptr dst_end = opts->gen.code_end; |
4182 uint16_t *after, *inst = context->mem_pointers[1] + address/2; | 4184 uint16_t *after, *inst = context->mem_pointers[1] + address/2; |
4183 m68kinst instbuf; | 4185 m68kinst instbuf; |
4184 after = m68k_decode(inst, &instbuf, orig); | 4186 after = m68k_decode(inst, &instbuf, orig); |
4185 if (orig_size != MAX_NATIVE_SIZE) { | 4187 if (orig_size != MAX_NATIVE_SIZE) { |
4186 if (dst_end - dst < 128) { | 4188 if (dst_end - dst < 128) { |
4187 size_t size = 1024*1024; | 4189 size_t size = 1024*1024; |
4188 dst = alloc_code(&size); | 4190 dst = alloc_code(&size); |
4189 opts->code_end = dst_end = dst + size; | 4191 opts->gen.code_end = dst_end = dst + size; |
4190 opts->cur_code = dst; | 4192 opts->gen.cur_code = dst; |
4191 } | 4193 } |
4192 deferred_addr * orig_deferred = opts->deferred; | 4194 deferred_addr * orig_deferred = opts->gen.deferred; |
4193 uint8_t * native_end = translate_m68k(dst, &instbuf, opts); | 4195 code_ptr native_end = translate_m68k(dst, &instbuf, opts); |
4194 uint8_t is_terminal = m68k_is_terminal(&instbuf); | 4196 uint8_t is_terminal = m68k_is_terminal(&instbuf); |
4195 if ((native_end - dst) <= orig_size) { | 4197 if ((native_end - dst) <= orig_size) { |
4196 uint8_t * native_next; | 4198 code_ptr native_next; |
4197 if (!is_terminal) { | 4199 if (!is_terminal) { |
4198 native_next = get_native_address(context->native_code_map, orig + (after-inst)*2); | 4200 native_next = get_native_address(context->native_code_map, orig + (after-inst)*2); |
4199 } | 4201 } |
4200 if (is_terminal || (native_next && ((native_next == orig_start + orig_size) || (orig_size - (native_end - dst)) > 5))) { | 4202 if (is_terminal || (native_next && ((native_next == orig_start + orig_size) || (orig_size - (native_end - dst)) > 5))) { |
4201 remove_deferred_until(&opts->deferred, orig_deferred); | 4203 remove_deferred_until(&opts->gen.deferred, orig_deferred); |
4202 native_end = translate_m68k(orig_start, &instbuf, opts); | 4204 native_end = translate_m68k(orig_start, &instbuf, opts); |
4203 if (!is_terminal) { | 4205 if (!is_terminal) { |
4204 if (native_next == orig_start + orig_size && (native_next-native_end) < 2) { | 4206 if (native_next == orig_start + orig_size && (native_next-native_end) < 2) { |
4205 while (native_end < orig_start + orig_size) { | 4207 while (native_end < orig_start + orig_size) { |
4206 *(native_end++) = 0x90; //NOP | 4208 *(native_end++) = 0x90; //NOP |
4213 return orig_start; | 4215 return orig_start; |
4214 } | 4216 } |
4215 } | 4217 } |
4216 | 4218 |
4217 map_native_address(context, instbuf.address, dst, (after-inst)*2, MAX_NATIVE_SIZE); | 4219 map_native_address(context, instbuf.address, dst, (after-inst)*2, MAX_NATIVE_SIZE); |
4218 opts->cur_code = dst+MAX_NATIVE_SIZE; | 4220 opts->gen.cur_code = dst+MAX_NATIVE_SIZE; |
4219 jmp(orig_start, dst); | 4221 jmp(orig_start, dst); |
4220 if (!m68k_is_terminal(&instbuf)) { | 4222 if (!m68k_is_terminal(&instbuf)) { |
4221 jmp(native_end, get_native_address_trans(context, orig + (after-inst)*2)); | 4223 jmp(native_end, get_native_address_trans(context, orig + (after-inst)*2)); |
4222 } | 4224 } |
4223 m68k_handle_deferred(context); | 4225 m68k_handle_deferred(context); |
4234 | 4236 |
4235 m68k_context * m68k_handle_code_write(uint32_t address, m68k_context * context) | 4237 m68k_context * m68k_handle_code_write(uint32_t address, m68k_context * context) |
4236 { | 4238 { |
4237 uint32_t inst_start = get_instruction_start(context->native_code_map, address | 0xFF0000); | 4239 uint32_t inst_start = get_instruction_start(context->native_code_map, address | 0xFF0000); |
4238 if (inst_start) { | 4240 if (inst_start) { |
4239 uint8_t * dst = get_native_address(context->native_code_map, inst_start); | 4241 code_ptr dst = get_native_address(context->native_code_map, inst_start); |
4240 dst = mov_ir(dst, inst_start, SCRATCH2, SZ_D); | 4242 dst = mov_ir(dst, inst_start, SCRATCH2, SZ_D); |
4241 x86_68k_options * options = context->options; | 4243 x86_68k_options * options = context->options; |
4242 if (!options->retrans_stub) { | 4244 if (!options->retrans_stub) { |
4243 if (options->code_end - options->cur_code < 32) { | 4245 if (options->gen.code_end - options->gen.cur_code < 32) { |
4244 size_t size = 1024*1024; | 4246 size_t size = 1024*1024; |
4245 options->cur_code = alloc_code(&size); | 4247 options->gen.cur_code = alloc_code(&size); |
4246 options->code_end = options->cur_code + size; | 4248 options->gen.code_end = options->gen.cur_code + size; |
4247 } | 4249 } |
4248 uint8_t * rdst = options->retrans_stub = options->cur_code; | 4250 code_ptr rdst = options->retrans_stub = options->gen.cur_code; |
4249 rdst = call(rdst, options->save_context); | 4251 rdst = call(rdst, options->gen.save_context); |
4250 rdst = push_r(rdst, CONTEXT); | 4252 rdst = push_r(rdst, CONTEXT); |
4251 #ifdef X86_32 | 4253 #ifdef X86_32 |
4252 rdst = push_r(rdst, CONTEXT); | 4254 rdst = push_r(rdst, CONTEXT); |
4253 rdst = push_r(rdst, SCRATCH2); | 4255 rdst = push_r(rdst, SCRATCH2); |
4254 #endif | 4256 #endif |
4255 rdst = call(rdst, (uint8_t *)m68k_retranslate_inst); | 4257 rdst = call(rdst, (code_ptr)m68k_retranslate_inst); |
4256 #ifdef X86_32 | 4258 #ifdef X86_32 |
4257 rdst = add_ir(rdst, 8, RSP, SZ_D); | 4259 rdst = add_ir(rdst, 8, RSP, SZ_D); |
4258 #endif | 4260 #endif |
4259 rdst = pop_r(rdst, CONTEXT); | 4261 rdst = pop_r(rdst, CONTEXT); |
4260 rdst = mov_rr(rdst, RAX, SCRATCH1, SZ_PTR); | 4262 rdst = mov_rr(rdst, RAX, SCRATCH1, SZ_PTR); |
4261 rdst = call(rdst, options->load_context); | 4263 rdst = call(rdst, options->gen.load_context); |
4262 rdst = jmp_r(rdst, SCRATCH1); | 4264 rdst = jmp_r(rdst, SCRATCH1); |
4263 options->cur_code = rdst; | 4265 options->gen.cur_code = rdst; |
4264 } | 4266 } |
4265 dst = jmp(dst, options->retrans_stub); | 4267 dst = jmp(dst, options->retrans_stub); |
4266 } | 4268 } |
4267 return context; | 4269 return context; |
4268 } | 4270 } |
4269 | 4271 |
4270 void insert_breakpoint(m68k_context * context, uint32_t address, uint8_t * bp_handler) | 4272 void insert_breakpoint(m68k_context * context, uint32_t address, code_ptr bp_handler) |
4271 { | 4273 { |
4272 static uint8_t * bp_stub = NULL; | 4274 static code_ptr bp_stub = NULL; |
4273 uint8_t * native = get_native_address_trans(context, address); | 4275 code_ptr native = get_native_address_trans(context, address); |
4274 uint8_t * start_native = native; | 4276 code_ptr start_native = native; |
4275 native = mov_ir(native, address, SCRATCH1, SZ_D); | 4277 native = mov_ir(native, address, SCRATCH1, SZ_D); |
4276 if (!bp_stub) { | 4278 if (!bp_stub) { |
4277 x86_68k_options * opts = context->options; | 4279 x86_68k_options * opts = context->options; |
4278 uint8_t * dst = opts->cur_code; | 4280 code_ptr dst = opts->gen.cur_code; |
4279 uint8_t * dst_end = opts->code_end; | 4281 code_ptr dst_end = opts->gen.code_end; |
4280 if (dst_end - dst < 128) { | 4282 if (dst_end - dst < 128) { |
4281 size_t size = 1024*1024; | 4283 size_t size = 1024*1024; |
4282 dst = alloc_code(&size); | 4284 dst = alloc_code(&size); |
4283 opts->code_end = dst_end = dst + size; | 4285 opts->gen.code_end = dst_end = dst + size; |
4284 } | 4286 } |
4285 bp_stub = dst; | 4287 bp_stub = dst; |
4286 native = call(native, bp_stub); | 4288 native = call(native, bp_stub); |
4287 | 4289 |
4288 //Calculate length of prologue | 4290 //Calculate length of prologue |
4289 dst = check_cycles_int(dst, address, opts); | 4291 dst = check_cycles_int(dst, address, opts); |
4290 int check_int_size = dst-bp_stub; | 4292 int check_int_size = dst-bp_stub; |
4291 dst = bp_stub; | 4293 dst = bp_stub; |
4292 | 4294 |
4293 //Save context and call breakpoint handler | 4295 //Save context and call breakpoint handler |
4294 dst = call(dst, opts->save_context); | 4296 dst = call(dst, opts->gen.save_context); |
4295 dst = push_r(dst, SCRATCH1); | 4297 dst = push_r(dst, SCRATCH1); |
4296 #ifdef X86_64 | 4298 #ifdef X86_64 |
4297 dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); | 4299 dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); |
4298 dst = mov_rr(dst, SCRATCH1, RSI, SZ_D); | 4300 dst = mov_rr(dst, SCRATCH1, RSI, SZ_D); |
4299 #else | 4301 #else |
4304 #ifdef X86_32 | 4306 #ifdef X86_32 |
4305 dst = add_ir(dst, 8, RSP, SZ_D); | 4307 dst = add_ir(dst, 8, RSP, SZ_D); |
4306 #endif | 4308 #endif |
4307 dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR); | 4309 dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR); |
4308 //Restore context | 4310 //Restore context |
4309 dst = call(dst, opts->load_context); | 4311 dst = call(dst, opts->gen.load_context); |
4310 dst = pop_r(dst, SCRATCH1); | 4312 dst = pop_r(dst, SCRATCH1); |
4311 //do prologue stuff | 4313 //do prologue stuff |
4312 dst = cmp_rr(dst, CYCLES, LIMIT, SZ_D); | 4314 dst = cmp_rr(dst, CYCLES, LIMIT, SZ_D); |
4313 uint8_t * jmp_off = dst+1; | 4315 code_ptr jmp_off = dst+1; |
4314 dst = jcc(dst, CC_NC, dst + 7); | 4316 dst = jcc(dst, CC_NC, dst + 7); |
4315 dst = call(dst, opts->handle_cycle_limit_int); | 4317 dst = call(dst, opts->gen.handle_cycle_limit_int); |
4316 *jmp_off = dst - (jmp_off+1); | 4318 *jmp_off = dst - (jmp_off+1); |
4317 //jump back to body of translated instruction | 4319 //jump back to body of translated instruction |
4318 dst = pop_r(dst, SCRATCH1); | 4320 dst = pop_r(dst, SCRATCH1); |
4319 dst = add_ir(dst, check_int_size - (native-start_native), SCRATCH1, SZ_PTR); | 4321 dst = add_ir(dst, check_int_size - (native-start_native), SCRATCH1, SZ_PTR); |
4320 dst = jmp_r(dst, SCRATCH1); | 4322 dst = jmp_r(dst, SCRATCH1); |
4321 opts->cur_code = dst; | 4323 opts->gen.cur_code = dst; |
4322 } else { | 4324 } else { |
4323 native = call(native, bp_stub); | 4325 native = call(native, bp_stub); |
4324 } | 4326 } |
4325 } | 4327 } |
4326 | 4328 |
4327 void remove_breakpoint(m68k_context * context, uint32_t address) | 4329 void remove_breakpoint(m68k_context * context, uint32_t address) |
4328 { | 4330 { |
4329 uint8_t * native = get_native_address(context->native_code_map, address); | 4331 code_ptr native = get_native_address(context->native_code_map, address); |
4330 check_cycles_int(native, address, context->options); | 4332 check_cycles_int(native, address, context->options); |
4331 } | 4333 } |
4332 | 4334 |
4333 void start_68k_context(m68k_context * context, uint32_t address) | 4335 void start_68k_context(m68k_context * context, uint32_t address) |
4334 { | 4336 { |
4335 uint8_t * addr = get_native_address_trans(context, address); | 4337 code_ptr addr = get_native_address_trans(context, address); |
4336 x86_68k_options * options = context->options; | 4338 x86_68k_options * options = context->options; |
4337 options->start_context(addr, context); | 4339 options->start_context(addr, context); |
4338 } | 4340 } |
4339 | 4341 |
4340 void m68k_reset(m68k_context * context) | 4342 void m68k_reset(m68k_context * context) |
4343 context->aregs[7] = context->mem_pointers[0][0] << 16 | context->mem_pointers[0][1]; | 4345 context->aregs[7] = context->mem_pointers[0][0] << 16 | context->mem_pointers[0][1]; |
4344 uint32_t address = context->mem_pointers[0][2] << 16 | context->mem_pointers[0][3]; | 4346 uint32_t address = context->mem_pointers[0][2] << 16 | context->mem_pointers[0][3]; |
4345 start_68k_context(context, address); | 4347 start_68k_context(context, address); |
4346 } | 4348 } |
4347 | 4349 |
4348 uint8_t * gen_mem_fun(x86_68k_options * opts, memmap_chunk * memmap, uint32_t num_chunks, ftype fun_type) | 4350 code_ptr gen_mem_fun(cpu_options * opts, memmap_chunk * memmap, uint32_t num_chunks, ftype fun_type) |
4349 { | 4351 { |
4350 uint8_t * dst = opts->cur_code; | 4352 code_ptr dst = opts->cur_code; |
4351 uint8_t * start = dst; | 4353 code_ptr start = dst; |
4352 dst = check_cycles(dst, opts); | 4354 dst = check_cycles(dst, opts); |
4353 dst = cycles(dst, BUS); | 4355 dst = cycles(dst, BUS); |
4354 dst = and_ir(dst, 0xFFFFFF, SCRATCH1, SZ_D); | 4356 dst = and_ir(dst, 0xFFFFFF, SCRATCH1, SZ_D); |
4355 uint8_t *lb_jcc = NULL, *ub_jcc = NULL; | 4357 code_ptr lb_jcc = NULL, ub_jcc = NULL; |
4356 uint8_t is_write = fun_type == WRITE_16 || fun_type == WRITE_8; | 4358 uint8_t is_write = fun_type == WRITE_16 || fun_type == WRITE_8; |
4357 uint8_t adr_reg = is_write ? SCRATCH2 : SCRATCH1; | 4359 uint8_t adr_reg = is_write ? SCRATCH2 : SCRATCH1; |
4358 uint16_t access_flag = is_write ? MMAP_WRITE : MMAP_READ; | 4360 uint16_t access_flag = is_write ? MMAP_WRITE : MMAP_READ; |
4359 uint8_t size = (fun_type == READ_16 || fun_type == WRITE_16) ? SZ_W : SZ_B; | 4361 uint8_t size = (fun_type == READ_16 || fun_type == WRITE_16) ? SZ_W : SZ_B; |
4360 for (uint32_t chunk = 0; chunk < num_chunks; chunk++) | 4362 for (uint32_t chunk = 0; chunk < num_chunks; chunk++) |
4393 } | 4395 } |
4394 if(memmap[chunk].buffer && memmap[chunk].flags & access_flag) { | 4396 if(memmap[chunk].buffer && memmap[chunk].flags & access_flag) { |
4395 if (memmap[chunk].flags & MMAP_PTR_IDX) { | 4397 if (memmap[chunk].flags & MMAP_PTR_IDX) { |
4396 if (memmap[chunk].flags & MMAP_FUNC_NULL) { | 4398 if (memmap[chunk].flags & MMAP_FUNC_NULL) { |
4397 dst = cmp_irdisp8(dst, 0, CONTEXT, offsetof(m68k_context, mem_pointers) + sizeof(void*) * memmap[chunk].ptr_index, SZ_PTR); | 4399 dst = cmp_irdisp8(dst, 0, CONTEXT, offsetof(m68k_context, mem_pointers) + sizeof(void*) * memmap[chunk].ptr_index, SZ_PTR); |
4398 uint8_t * not_null = dst+1; | 4400 code_ptr not_null = dst+1; |
4399 dst = jcc(dst, CC_NZ, dst+2); | 4401 dst = jcc(dst, CC_NZ, dst+2); |
4400 dst = call(dst, opts->save_context); | 4402 dst = call(dst, opts->save_context); |
4401 #ifdef X86_64 | 4403 #ifdef X86_64 |
4402 if (is_write) { | 4404 if (is_write) { |
4403 if (SCRATCH2 != RDI) { | 4405 if (SCRATCH2 != RDI) { |
4407 } else { | 4409 } else { |
4408 dst = push_r(dst, CONTEXT); | 4410 dst = push_r(dst, CONTEXT); |
4409 dst = mov_rr(dst, SCRATCH1, RDI, SZ_D); | 4411 dst = mov_rr(dst, SCRATCH1, RDI, SZ_D); |
4410 } | 4412 } |
4411 dst = test_ir(dst, 8, RSP, SZ_D); | 4413 dst = test_ir(dst, 8, RSP, SZ_D); |
4412 uint8_t *adjust_rsp = dst+1; | 4414 code_ptr adjust_rsp = dst+1; |
4413 dst = jcc(dst, CC_NZ, dst+2); | 4415 dst = jcc(dst, CC_NZ, dst+2); |
4414 dst = call(dst, cfun); | 4416 dst = call(dst, cfun); |
4415 uint8_t *no_adjust = dst+1; | 4417 code_ptr no_adjust = dst+1; |
4416 dst = jmp(dst, dst+2); | 4418 dst = jmp(dst, dst+2); |
4417 *adjust_rsp = dst - (adjust_rsp + 1); | 4419 *adjust_rsp = dst - (adjust_rsp + 1); |
4418 dst = sub_ir(dst, 8, RSP, SZ_PTR); | 4420 dst = sub_ir(dst, 8, RSP, SZ_PTR); |
4419 dst = call(dst, cfun); | 4421 dst = call(dst, cfun); |
4420 dst = add_ir(dst, 8, RSP, SZ_PTR); | 4422 dst = add_ir(dst, 8, RSP, SZ_PTR); |
4453 } else { | 4455 } else { |
4454 uint8_t tmp_size = size; | 4456 uint8_t tmp_size = size; |
4455 if (size == SZ_B) { | 4457 if (size == SZ_B) { |
4456 if ((memmap[chunk].flags & MMAP_ONLY_ODD) || (memmap[chunk].flags & MMAP_ONLY_EVEN)) { | 4458 if ((memmap[chunk].flags & MMAP_ONLY_ODD) || (memmap[chunk].flags & MMAP_ONLY_EVEN)) { |
4457 dst = bt_ir(dst, 0, adr_reg, SZ_D); | 4459 dst = bt_ir(dst, 0, adr_reg, SZ_D); |
4458 uint8_t * good_addr = dst + 1; | 4460 code_ptr good_addr = dst + 1; |
4459 dst = jcc(dst, (memmap[chunk].flags & MMAP_ONLY_ODD) ? CC_C : CC_NC, dst+2); | 4461 dst = jcc(dst, (memmap[chunk].flags & MMAP_ONLY_ODD) ? CC_C : CC_NC, dst+2); |
4460 if (!is_write) { | 4462 if (!is_write) { |
4461 dst = mov_ir(dst, 0xFF, SCRATCH1, SZ_B); | 4463 dst = mov_ir(dst, 0xFF, SCRATCH1, SZ_B); |
4462 } | 4464 } |
4463 dst = retn(dst); | 4465 dst = retn(dst); |
4502 } | 4504 } |
4503 if (is_write && (memmap[chunk].flags & MMAP_CODE)) { | 4505 if (is_write && (memmap[chunk].flags & MMAP_CODE)) { |
4504 dst = mov_rr(dst, SCRATCH2, SCRATCH1, SZ_D); | 4506 dst = mov_rr(dst, SCRATCH2, SCRATCH1, SZ_D); |
4505 dst = shr_ir(dst, 11, SCRATCH1, SZ_D); | 4507 dst = shr_ir(dst, 11, SCRATCH1, SZ_D); |
4506 dst = bt_rrdisp32(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, ram_code_flags), SZ_D); | 4508 dst = bt_rrdisp32(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, ram_code_flags), SZ_D); |
4507 uint8_t * not_code = dst+1; | 4509 code_ptr not_code = dst+1; |
4508 dst = jcc(dst, CC_NC, dst+2); | 4510 dst = jcc(dst, CC_NC, dst+2); |
4509 dst = call(dst, opts->save_context); | 4511 dst = call(dst, opts->save_context); |
4510 #ifdef X86_32 | 4512 #ifdef X86_32 |
4511 dst = push_r(dst, CONTEXT); | 4513 dst = push_r(dst, CONTEXT); |
4512 dst = push_r(dst, SCRATCH2); | 4514 dst = push_r(dst, SCRATCH2); |
4513 #endif | 4515 #endif |
4514 dst = call(dst, (uint8_t *)m68k_handle_code_write); | 4516 dst = call(dst, (code_ptr)m68k_handle_code_write); |
4515 #ifdef X86_32 | 4517 #ifdef X86_32 |
4516 dst = add_ir(dst, 8, RSP, SZ_D); | 4518 dst = add_ir(dst, 8, RSP, SZ_D); |
4517 #endif | 4519 #endif |
4518 dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR); | 4520 dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR); |
4519 dst = call(dst, opts->load_context); | 4521 dst = call(dst, opts->load_context); |
4531 } else { | 4533 } else { |
4532 dst = push_r(dst, CONTEXT); | 4534 dst = push_r(dst, CONTEXT); |
4533 dst = mov_rr(dst, SCRATCH1, RDI, SZ_D); | 4535 dst = mov_rr(dst, SCRATCH1, RDI, SZ_D); |
4534 } | 4536 } |
4535 dst = test_ir(dst, 8, RSP, SZ_D); | 4537 dst = test_ir(dst, 8, RSP, SZ_D); |
4536 uint8_t *adjust_rsp = dst+1; | 4538 code_ptr adjust_rsp = dst+1; |
4537 dst = jcc(dst, CC_NZ, dst+2); | 4539 dst = jcc(dst, CC_NZ, dst+2); |
4538 dst = call(dst, cfun); | 4540 dst = call(dst, cfun); |
4539 uint8_t *no_adjust = dst+1; | 4541 code_ptr no_adjust = dst+1; |
4540 dst = jmp(dst, dst+2); | 4542 dst = jmp(dst, dst+2); |
4541 *adjust_rsp = dst - (adjust_rsp + 1); | 4543 *adjust_rsp = dst - (adjust_rsp + 1); |
4542 dst = sub_ir(dst, 8, RSP, SZ_PTR); | 4544 dst = sub_ir(dst, 8, RSP, SZ_PTR); |
4543 dst = call(dst, cfun); | 4545 dst = call(dst, cfun); |
4544 dst = add_ir(dst, 8, RSP, SZ_PTR); | 4546 dst = add_ir(dst, 8, RSP, SZ_PTR); |
4612 for (int i = 0; i < 5; i++) | 4614 for (int i = 0; i < 5; i++) |
4613 opts->flag_regs[i] = -1; | 4615 opts->flag_regs[i] = -1; |
4614 #endif | 4616 #endif |
4615 | 4617 |
4616 | 4618 |
4617 opts->native_code_map = malloc(sizeof(native_map_slot) * NATIVE_MAP_CHUNKS); | 4619 opts->gen.native_code_map = malloc(sizeof(native_map_slot) * NATIVE_MAP_CHUNKS); |
4618 memset(opts->native_code_map, 0, sizeof(native_map_slot) * NATIVE_MAP_CHUNKS); | 4620 memset(opts->gen.native_code_map, 0, sizeof(native_map_slot) * NATIVE_MAP_CHUNKS); |
4619 opts->deferred = NULL; | 4621 opts->gen.deferred = NULL; |
4620 size_t size = 1024 * 1024; | 4622 size_t size = 1024 * 1024; |
4621 opts->cur_code = alloc_code(&size); | 4623 opts->gen.cur_code = alloc_code(&size); |
4622 opts->code_end = opts->cur_code + size; | 4624 opts->gen.code_end = opts->gen.cur_code + size; |
4623 opts->ram_inst_sizes = malloc(sizeof(uint8_t *) * 64); | 4625 opts->gen.ram_inst_sizes = malloc(sizeof(code_ptr) * 64); |
4624 memset(opts->ram_inst_sizes, 0, sizeof(uint8_t *) * 64); | 4626 memset(opts->gen.ram_inst_sizes, 0, sizeof(code_ptr) * 64); |
4625 | 4627 |
4626 uint8_t * dst = opts->cur_code; | 4628 code_ptr dst = opts->gen.cur_code; |
4627 | 4629 |
4628 opts->save_context = dst; | 4630 opts->gen.save_context = dst; |
4629 for (int i = 0; i < 5; i++) | 4631 for (int i = 0; i < 5; i++) |
4630 if (opts->flag_regs[i] >= 0) { | 4632 if (opts->flag_regs[i] >= 0) { |
4631 dst = mov_rrdisp8(dst, opts->flag_regs[i], CONTEXT, offsetof(m68k_context, flags) + i, SZ_B); | 4633 dst = mov_rrdisp8(dst, opts->flag_regs[i], CONTEXT, offsetof(m68k_context, flags) + i, SZ_B); |
4632 } | 4634 } |
4633 for (int i = 0; i < 8; i++) | 4635 for (int i = 0; i < 8; i++) |
4640 } | 4642 } |
4641 } | 4643 } |
4642 dst = mov_rrdisp8(dst, CYCLES, CONTEXT, offsetof(m68k_context, current_cycle), SZ_D); | 4644 dst = mov_rrdisp8(dst, CYCLES, CONTEXT, offsetof(m68k_context, current_cycle), SZ_D); |
4643 dst = retn(dst); | 4645 dst = retn(dst); |
4644 | 4646 |
4645 opts->load_context = dst; | 4647 opts->gen.load_context = dst; |
4646 for (int i = 0; i < 5; i++) | 4648 for (int i = 0; i < 5; i++) |
4647 if (opts->flag_regs[i] >= 0) { | 4649 if (opts->flag_regs[i] >= 0) { |
4648 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, flags) + i, opts->flag_regs[i], SZ_B); | 4650 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, flags) + i, opts->flag_regs[i], SZ_B); |
4649 } | 4651 } |
4650 for (int i = 0; i < 8; i++) | 4652 for (int i = 0; i < 8; i++) |
4679 dst = push_r(dst, RDI); | 4681 dst = push_r(dst, RDI); |
4680 | 4682 |
4681 dst = mov_rdisp8r(dst, RSP, 20, SCRATCH2, SZ_D); | 4683 dst = mov_rdisp8r(dst, RSP, 20, SCRATCH2, SZ_D); |
4682 dst = mov_rdisp8r(dst, RSP, 24, CONTEXT, SZ_D); | 4684 dst = mov_rdisp8r(dst, RSP, 24, CONTEXT, SZ_D); |
4683 #endif | 4685 #endif |
4684 dst = call(dst, opts->load_context); | 4686 dst = call(dst, opts->gen.load_context); |
4685 dst = call_r(dst, SCRATCH2); | 4687 dst = call_r(dst, SCRATCH2); |
4686 dst = call(dst, opts->save_context); | 4688 dst = call(dst, opts->gen.save_context); |
4687 #ifdef X86_64 | 4689 #ifdef X86_64 |
4688 //restore callee save registers | 4690 //restore callee save registers |
4689 dst = pop_r(dst, R15); | 4691 dst = pop_r(dst, R15); |
4690 dst = pop_r(dst, R14); | 4692 dst = pop_r(dst, R14); |
4691 dst = pop_r(dst, R13); | 4693 dst = pop_r(dst, R13); |
4698 dst = pop_r(dst, RBP); | 4700 dst = pop_r(dst, RBP); |
4699 #endif | 4701 #endif |
4700 dst = retn(dst); | 4702 dst = retn(dst); |
4701 | 4703 |
4702 opts->native_addr = dst; | 4704 opts->native_addr = dst; |
4703 dst = call(dst, opts->save_context); | 4705 dst = call(dst, opts->gen.save_context); |
4704 dst = push_r(dst, CONTEXT); | 4706 dst = push_r(dst, CONTEXT); |
4705 #ifdef X86_64 | 4707 #ifdef X86_64 |
4706 dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); //move context to 1st arg reg | 4708 dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); //move context to 1st arg reg |
4707 dst = mov_rr(dst, SCRATCH1, RSI, SZ_D); //move address to 2nd arg reg | 4709 dst = mov_rr(dst, SCRATCH1, RSI, SZ_D); //move address to 2nd arg reg |
4708 #else | 4710 #else |
4709 dst = push_r(dst, SCRATCH1); | 4711 dst = push_r(dst, SCRATCH1); |
4710 dst = push_r(dst, CONTEXT); | 4712 dst = push_r(dst, CONTEXT); |
4711 #endif | 4713 #endif |
4712 dst = call(dst, (uint8_t *)get_native_address_trans); | 4714 dst = call(dst, (code_ptr)get_native_address_trans); |
4713 #ifdef X86_32 | 4715 #ifdef X86_32 |
4714 dst = add_ir(dst, 8, RSP, SZ_D); | 4716 dst = add_ir(dst, 8, RSP, SZ_D); |
4715 #endif | 4717 #endif |
4716 dst = mov_rr(dst, RAX, SCRATCH1, SZ_PTR); //move result to scratch reg | 4718 dst = mov_rr(dst, RAX, SCRATCH1, SZ_PTR); //move result to scratch reg |
4717 dst = pop_r(dst, CONTEXT); | 4719 dst = pop_r(dst, CONTEXT); |
4718 dst = call(dst, opts->load_context); | 4720 dst = call(dst, opts->gen.load_context); |
4719 dst = retn(dst); | 4721 dst = retn(dst); |
4720 | 4722 |
4721 opts->native_addr_and_sync = dst; | 4723 opts->native_addr_and_sync = dst; |
4722 dst = call(dst, opts->save_context); | 4724 dst = call(dst, opts->gen.save_context); |
4723 dst = push_r(dst, SCRATCH1); | 4725 dst = push_r(dst, SCRATCH1); |
4724 #ifdef X86_64 | 4726 #ifdef X86_64 |
4725 dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); | 4727 dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); |
4726 dst = xor_rr(dst, RSI, RSI, SZ_D); | 4728 dst = xor_rr(dst, RSI, RSI, SZ_D); |
4727 dst = test_ir(dst, 8, RSP, SZ_PTR); //check stack alignment | 4729 dst = test_ir(dst, 8, RSP, SZ_PTR); //check stack alignment |
4728 uint8_t * do_adjust_rsp = dst+1; | 4730 code_ptr do_adjust_rsp = dst+1; |
4729 dst = jcc(dst, CC_NZ, dst+2); | 4731 dst = jcc(dst, CC_NZ, dst+2); |
4730 dst = call(dst, (uint8_t *)sync_components); | 4732 dst = call(dst, (code_ptr)sync_components); |
4731 uint8_t * no_adjust_rsp = dst+1; | 4733 code_ptr no_adjust_rsp = dst+1; |
4732 dst = jmp(dst, dst+2); | 4734 dst = jmp(dst, dst+2); |
4733 *do_adjust_rsp = dst - (do_adjust_rsp+1); | 4735 *do_adjust_rsp = dst - (do_adjust_rsp+1); |
4734 dst = sub_ir(dst, 8, RSP, SZ_PTR); | 4736 dst = sub_ir(dst, 8, RSP, SZ_PTR); |
4735 dst = call(dst, (uint8_t *)sync_components); | 4737 dst = call(dst, (code_ptr)sync_components); |
4736 dst = add_ir(dst, 8, RSP, SZ_PTR); | 4738 dst = add_ir(dst, 8, RSP, SZ_PTR); |
4737 *no_adjust_rsp = dst - (no_adjust_rsp+1); | 4739 *no_adjust_rsp = dst - (no_adjust_rsp+1); |
4738 dst = pop_r(dst, RSI); | 4740 dst = pop_r(dst, RSI); |
4739 dst = push_r(dst, RAX); | 4741 dst = push_r(dst, RAX); |
4740 dst = mov_rr(dst, RAX, RDI, SZ_PTR); | 4742 dst = mov_rr(dst, RAX, RDI, SZ_PTR); |
4741 dst = call(dst, (uint8_t *)get_native_address_trans); | 4743 dst = call(dst, (code_ptr)get_native_address_trans); |
4742 #else | 4744 #else |
4743 //TODO: Add support for pushing a constant in gen_x86 | 4745 //TODO: Add support for pushing a constant in gen_x86 |
4744 dst = xor_rr(dst, RAX, RAX, SZ_D); | 4746 dst = xor_rr(dst, RAX, RAX, SZ_D); |
4745 dst = push_r(dst, RAX); | 4747 dst = push_r(dst, RAX); |
4746 dst = push_r(dst, CONTEXT); | 4748 dst = push_r(dst, CONTEXT); |
4747 dst = call(dst, (uint8_t *)sync_components); | 4749 dst = call(dst, (code_ptr)sync_components); |
4748 dst = add_ir(dst, 8, RSP, SZ_D); | 4750 dst = add_ir(dst, 8, RSP, SZ_D); |
4749 dst = pop_r(dst, RSI); //restore saved address from SCRATCH1 | 4751 dst = pop_r(dst, RSI); //restore saved address from SCRATCH1 |
4750 dst = push_r(dst, RAX); //save context pointer for later | 4752 dst = push_r(dst, RAX); //save context pointer for later |
4751 dst = push_r(dst, RSI); //2nd arg -- address | 4753 dst = push_r(dst, RSI); //2nd arg -- address |
4752 dst = push_r(dst, RAX); //1st arg -- context pointer | 4754 dst = push_r(dst, RAX); //1st arg -- context pointer |
4753 dst = call(dst, (uint8_t *)get_native_address_trans); | 4755 dst = call(dst, (code_ptr)get_native_address_trans); |
4754 dst = add_ir(dst, 8, RSP, SZ_D); | 4756 dst = add_ir(dst, 8, RSP, SZ_D); |
4755 #endif | 4757 #endif |
4756 | 4758 |
4757 dst = mov_rr(dst, RAX, SCRATCH1, SZ_PTR); //move result to scratch reg | 4759 dst = mov_rr(dst, RAX, SCRATCH1, SZ_PTR); //move result to scratch reg |
4758 dst = pop_r(dst, CONTEXT); | 4760 dst = pop_r(dst, CONTEXT); |
4759 dst = call(dst, opts->load_context); | 4761 dst = call(dst, opts->gen.load_context); |
4760 dst = retn(dst); | 4762 dst = retn(dst); |
4761 | 4763 |
4762 opts->handle_cycle_limit = dst; | 4764 opts->gen.handle_cycle_limit = dst; |
4763 dst = cmp_rdisp8r(dst, CONTEXT, offsetof(m68k_context, sync_cycle), CYCLES, SZ_D); | 4765 dst = cmp_rdisp8r(dst, CONTEXT, offsetof(m68k_context, sync_cycle), CYCLES, SZ_D); |
4764 uint8_t * skip_sync = dst+1; | 4766 code_ptr skip_sync = dst+1; |
4765 dst = jcc(dst, CC_C, dst+2); | 4767 dst = jcc(dst, CC_C, dst+2); |
4766 opts->do_sync = dst; | 4768 opts->do_sync = dst; |
4767 dst = push_r(dst, SCRATCH1); | 4769 dst = push_r(dst, SCRATCH1); |
4768 dst = push_r(dst, SCRATCH2); | 4770 dst = push_r(dst, SCRATCH2); |
4769 dst = call(dst, opts->save_context); | 4771 dst = call(dst, opts->gen.save_context); |
4770 #ifdef X86_64 | 4772 #ifdef X86_64 |
4771 dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); | 4773 dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); |
4772 dst = xor_rr(dst, RSI, RSI, SZ_D); | 4774 dst = xor_rr(dst, RSI, RSI, SZ_D); |
4773 dst = test_ir(dst, 8, RSP, SZ_D); | 4775 dst = test_ir(dst, 8, RSP, SZ_D); |
4774 uint8_t *adjust_rsp = dst+1; | 4776 code_ptr adjust_rsp = dst+1; |
4775 dst = jcc(dst, CC_NZ, dst+2); | 4777 dst = jcc(dst, CC_NZ, dst+2); |
4776 dst = call(dst, (uint8_t *)sync_components); | 4778 dst = call(dst, (code_ptr)sync_components); |
4777 uint8_t *no_adjust = dst+1; | 4779 code_ptr no_adjust = dst+1; |
4778 dst = jmp(dst, dst+2); | 4780 dst = jmp(dst, dst+2); |
4779 *adjust_rsp = dst - (adjust_rsp + 1); | 4781 *adjust_rsp = dst - (adjust_rsp + 1); |
4780 dst = sub_ir(dst, 8, RSP, SZ_PTR); | 4782 dst = sub_ir(dst, 8, RSP, SZ_PTR); |
4781 dst = call(dst, (uint8_t *)sync_components); | 4783 dst = call(dst, (code_ptr)sync_components); |
4782 dst = add_ir(dst, 8, RSP, SZ_PTR); | 4784 dst = add_ir(dst, 8, RSP, SZ_PTR); |
4783 *no_adjust = dst - (no_adjust+1); | 4785 *no_adjust = dst - (no_adjust+1); |
4784 #else | 4786 #else |
4785 //TODO: Add support for pushing a constant in gen_x86 | 4787 //TODO: Add support for pushing a constant in gen_x86 |
4786 dst = xor_rr(dst, RAX, RAX, SZ_D); | 4788 dst = xor_rr(dst, RAX, RAX, SZ_D); |
4787 dst = push_r(dst, RAX); | 4789 dst = push_r(dst, RAX); |
4788 dst = push_r(dst, CONTEXT); | 4790 dst = push_r(dst, CONTEXT); |
4789 dst = call(dst, (uint8_t *)sync_components); | 4791 dst = call(dst, (code_ptr)sync_components); |
4790 dst = add_ir(dst, 8, RSP, SZ_D); | 4792 dst = add_ir(dst, 8, RSP, SZ_D); |
4791 #endif | 4793 #endif |
4792 dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR); | 4794 dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR); |
4793 dst = call(dst, opts->load_context); | 4795 dst = call(dst, opts->gen.load_context); |
4794 dst = pop_r(dst, SCRATCH2); | 4796 dst = pop_r(dst, SCRATCH2); |
4795 dst = pop_r(dst, SCRATCH1); | 4797 dst = pop_r(dst, SCRATCH1); |
4796 *skip_sync = dst - (skip_sync+1); | 4798 *skip_sync = dst - (skip_sync+1); |
4797 dst = retn(dst); | 4799 dst = retn(dst); |
4798 | 4800 |
4799 opts->cur_code = dst; | 4801 opts->gen.cur_code = dst; |
4800 | 4802 |
4801 opts->read_16 = gen_mem_fun(opts, memmap, num_chunks, READ_16); | 4803 opts->read_16 = gen_mem_fun(&opts->gen, memmap, num_chunks, READ_16); |
4802 opts->read_8 = gen_mem_fun(opts, memmap, num_chunks, READ_8); | 4804 opts->read_8 = gen_mem_fun(&opts->gen, memmap, num_chunks, READ_8); |
4803 opts->write_16 = gen_mem_fun(opts, memmap, num_chunks, WRITE_16); | 4805 opts->write_16 = gen_mem_fun(&opts->gen, memmap, num_chunks, WRITE_16); |
4804 opts->write_8 = gen_mem_fun(opts, memmap, num_chunks, WRITE_8); | 4806 opts->write_8 = gen_mem_fun(&opts->gen, memmap, num_chunks, WRITE_8); |
4805 | 4807 |
4806 dst = opts->cur_code; | 4808 dst = opts->gen.cur_code; |
4807 | 4809 |
4808 opts->read_32 = dst; | 4810 opts->read_32 = dst; |
4809 dst = push_r(dst, SCRATCH1); | 4811 dst = push_r(dst, SCRATCH1); |
4810 dst = call(dst, opts->read_16); | 4812 dst = call(dst, opts->read_16); |
4811 dst = mov_rr(dst, SCRATCH1, SCRATCH2, SZ_W); | 4813 dst = mov_rr(dst, SCRATCH1, SCRATCH2, SZ_W); |
4897 } | 4899 } |
4898 } | 4900 } |
4899 } | 4901 } |
4900 dst = retn(dst); | 4902 dst = retn(dst); |
4901 | 4903 |
4902 opts->handle_cycle_limit_int = dst; | 4904 opts->gen.handle_cycle_limit_int = dst; |
4903 dst = cmp_rdisp8r(dst, CONTEXT, offsetof(m68k_context, int_cycle), CYCLES, SZ_D); | 4905 dst = cmp_rdisp8r(dst, CONTEXT, offsetof(m68k_context, int_cycle), CYCLES, SZ_D); |
4904 uint8_t * do_int = dst+1; | 4906 code_ptr do_int = dst+1; |
4905 dst = jcc(dst, CC_NC, dst+2); | 4907 dst = jcc(dst, CC_NC, dst+2); |
4906 dst = cmp_rdisp8r(dst, CONTEXT, offsetof(m68k_context, sync_cycle), CYCLES, SZ_D); | 4908 dst = cmp_rdisp8r(dst, CONTEXT, offsetof(m68k_context, sync_cycle), CYCLES, SZ_D); |
4907 skip_sync = dst+1; | 4909 skip_sync = dst+1; |
4908 dst = jcc(dst, CC_C, dst+2); | 4910 dst = jcc(dst, CC_C, dst+2); |
4909 dst = call(dst, opts->save_context); | 4911 dst = call(dst, opts->gen.save_context); |
4910 #ifdef X86_64 | 4912 #ifdef X86_64 |
4911 dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); | 4913 dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); |
4912 dst = mov_rr(dst, SCRATCH1, RSI, SZ_D); | 4914 dst = mov_rr(dst, SCRATCH1, RSI, SZ_D); |
4913 dst = test_ir(dst, 8, RSP, SZ_D); | 4915 dst = test_ir(dst, 8, RSP, SZ_D); |
4914 adjust_rsp = dst+1; | 4916 adjust_rsp = dst+1; |
4915 dst = jcc(dst, CC_NZ, dst+2); | 4917 dst = jcc(dst, CC_NZ, dst+2); |
4916 dst = call(dst, (uint8_t *)sync_components); | 4918 dst = call(dst, (code_ptr)sync_components); |
4917 no_adjust = dst+1; | 4919 no_adjust = dst+1; |
4918 dst = jmp(dst, dst+2); | 4920 dst = jmp(dst, dst+2); |
4919 *adjust_rsp = dst - (adjust_rsp + 1); | 4921 *adjust_rsp = dst - (adjust_rsp + 1); |
4920 dst = sub_ir(dst, 8, RSP, SZ_PTR); | 4922 dst = sub_ir(dst, 8, RSP, SZ_PTR); |
4921 dst = call(dst, (uint8_t *)sync_components); | 4923 dst = call(dst, (code_ptr)sync_components); |
4922 dst = add_ir(dst, 8, RSP, SZ_PTR); | 4924 dst = add_ir(dst, 8, RSP, SZ_PTR); |
4923 *no_adjust = dst - (no_adjust+1); | 4925 *no_adjust = dst - (no_adjust+1); |
4924 #else | 4926 #else |
4925 dst = push_r(dst, SCRATCH1); | 4927 dst = push_r(dst, SCRATCH1); |
4926 dst = push_r(dst, CONTEXT); | 4928 dst = push_r(dst, CONTEXT); |
4927 dst = call(dst, (uint8_t *)sync_components); | 4929 dst = call(dst, (code_ptr)sync_components); |
4928 dst = add_ir(dst, 8, RSP, SZ_D); | 4930 dst = add_ir(dst, 8, RSP, SZ_D); |
4929 #endif | 4931 #endif |
4930 dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR); | 4932 dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR); |
4931 dst = jmp(dst, opts->load_context); | 4933 dst = jmp(dst, opts->gen.load_context); |
4932 *skip_sync = dst - (skip_sync+1); | 4934 *skip_sync = dst - (skip_sync+1); |
4933 dst = retn(dst); | 4935 dst = retn(dst); |
4934 *do_int = dst - (do_int+1); | 4936 *do_int = dst - (do_int+1); |
4935 //set target cycle to sync cycle | 4937 //set target cycle to sync cycle |
4936 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, sync_cycle), LIMIT, SZ_D); | 4938 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, sync_cycle), LIMIT, SZ_D); |
4937 //swap USP and SSP if not already in supervisor mode | 4939 //swap USP and SSP if not already in supervisor mode |
4938 dst = bt_irdisp8(dst, 5, CONTEXT, offsetof(m68k_context, status), SZ_B); | 4940 dst = bt_irdisp8(dst, 5, CONTEXT, offsetof(m68k_context, status), SZ_B); |
4939 uint8_t *already_supervisor = dst+1; | 4941 code_ptr already_supervisor = dst+1; |
4940 dst = jcc(dst, CC_C, dst+2); | 4942 dst = jcc(dst, CC_C, dst+2); |
4941 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SCRATCH2, SZ_D); | 4943 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SCRATCH2, SZ_D); |
4942 dst = mov_rrdisp8(dst, opts->aregs[7], CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); | 4944 dst = mov_rrdisp8(dst, opts->aregs[7], CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); |
4943 dst = mov_rr(dst, SCRATCH2, opts->aregs[7], SZ_D); | 4945 dst = mov_rr(dst, SCRATCH2, opts->aregs[7], SZ_D); |
4944 *already_supervisor = dst - (already_supervisor+1); | 4946 *already_supervisor = dst - (already_supervisor+1); |
4995 dst = call(dst, opts->read_32); | 4997 dst = call(dst, opts->read_32); |
4996 dst = call(dst, opts->native_addr_and_sync); | 4998 dst = call(dst, opts->native_addr_and_sync); |
4997 dst = cycles(dst, 18); | 4999 dst = cycles(dst, 18); |
4998 dst = jmp_r(dst, SCRATCH1); | 5000 dst = jmp_r(dst, SCRATCH1); |
4999 | 5001 |
5000 opts->cur_code = dst; | 5002 opts->gen.cur_code = dst; |
5001 } | 5003 } |
5002 | 5004 |
5003 void init_68k_context(m68k_context * context, native_map_slot * native_code_map, void * opts) | 5005 void init_68k_context(m68k_context * context, native_map_slot * native_code_map, void * opts) |
5004 { | 5006 { |
5005 memset(context, 0, sizeof(m68k_context)); | 5007 memset(context, 0, sizeof(m68k_context)); |