Mercurial > repos > blastem
comparison m68k_to_x86.c @ 567:8e395210f50f
Refactor gen_x86 to use an interface more like gen_arm and to remove the need for the caller to decide whether an 8-bit or 32-bit displacement is needed in the rdisp functions. Update m68k_to_x86 to use the new version of the gen_x86 functions and do some minor refactoring there in the process
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 02 Mar 2014 14:45:36 -0800 |
parents | dc9f178085a0 |
children | 9b7fcf748be0 |
comparison
equal
deleted
inserted
replaced
566:624dd5106060 | 567:8e395210f50f |
---|---|
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 code_ptr cycles(code_ptr dst, uint32_t num) | 46 |
47 { | 47 void set_flag(x86_68k_options * opts, uint8_t val, uint8_t flag) |
48 dst = add_ir(dst, num, CYCLES, SZ_D); | |
49 return dst; | |
50 } | |
51 | |
52 code_ptr check_cycles_int(code_ptr dst, uint32_t address, x86_68k_options * opts) | |
53 { | |
54 dst = cmp_rr(dst, CYCLES, LIMIT, SZ_D); | |
55 code_ptr jmp_off = dst+1; | |
56 dst = jcc(dst, CC_NC, dst + 7); | |
57 dst = mov_ir(dst, address, SCRATCH1, SZ_D); | |
58 dst = call(dst, opts->gen.handle_cycle_limit_int); | |
59 *jmp_off = dst - (jmp_off+1); | |
60 return dst; | |
61 } | |
62 | |
63 code_ptr check_cycles(code_ptr dst, cpu_options * opts) | |
64 { | |
65 dst = cmp_rr(dst, CYCLES, LIMIT, SZ_D); | |
66 code_ptr jmp_off = dst+1; | |
67 dst = jcc(dst, CC_NC, dst + 7); | |
68 dst = call(dst, opts->handle_cycle_limit); | |
69 *jmp_off = dst - (jmp_off+1); | |
70 return dst; | |
71 } | |
72 | |
73 code_ptr set_flag(code_ptr dst, uint8_t val, uint8_t flag, x86_68k_options * opts) | |
74 { | 48 { |
75 if (opts->flag_regs[flag] >= 0) { | 49 if (opts->flag_regs[flag] >= 0) { |
76 dst = mov_ir(dst, val, opts->flag_regs[flag], SZ_B); | 50 mov_ir(&opts->gen.code, val, opts->flag_regs[flag], SZ_B); |
77 } else { | 51 } else { |
78 int8_t offset = offsetof(m68k_context, flags) + flag; | 52 int8_t offset = offsetof(m68k_context, flags) + flag; |
79 if (offset) { | 53 if (offset) { |
80 dst = mov_irdisp8(dst, val, CONTEXT, offset, SZ_B); | 54 mov_irdisp(&opts->gen.code, val, opts->gen.context_reg, offset, SZ_B); |
81 } else { | 55 } else { |
82 dst = mov_irind(dst, val, CONTEXT, SZ_B); | 56 mov_irind(&opts->gen.code, val, opts->gen.context_reg, SZ_B); |
83 } | 57 } |
84 } | 58 } |
85 | 59 } |
86 return dst; | 60 |
87 } | 61 void set_flag_cond(x86_68k_options *opts, uint8_t cond, uint8_t flag) |
88 | |
89 code_ptr set_flag_cond(code_ptr dst, uint8_t cond, uint8_t flag, x86_68k_options *opts) | |
90 { | 62 { |
91 if (opts->flag_regs[flag] >= 0) { | 63 if (opts->flag_regs[flag] >= 0) { |
92 dst = setcc_r(dst, cond, opts->flag_regs[flag]); | 64 setcc_r(&opts->gen.code, cond, opts->flag_regs[flag]); |
93 } else { | 65 } else { |
94 int8_t offset = offsetof(m68k_context, flags) + flag; | 66 int8_t offset = offsetof(m68k_context, flags) + flag; |
95 if (offset) { | 67 if (offset) { |
96 dst = setcc_rdisp8(dst, cond, CONTEXT, offset); | 68 setcc_rdisp(&opts->gen.code, cond, opts->gen.context_reg, offset); |
97 } else { | 69 } else { |
98 dst = setcc_rind(dst, cond, CONTEXT); | 70 setcc_rind(&opts->gen.code, cond, opts->gen.context_reg); |
99 } | 71 } |
100 } | 72 } |
101 | 73 } |
102 return dst; | 74 |
103 } | 75 void check_flag(x86_68k_options *opts, uint8_t flag) |
104 | |
105 code_ptr check_flag(code_ptr dst, uint8_t flag, x86_68k_options *opts) | |
106 { | 76 { |
107 if (opts->flag_regs[flag] >= 0) { | 77 if (opts->flag_regs[flag] >= 0) { |
108 dst = cmp_ir(dst, 0, opts->flag_regs[flag], SZ_B); | 78 cmp_ir(&opts->gen.code, 0, opts->flag_regs[flag], SZ_B); |
109 } else { | 79 } else { |
110 dst = cmp_irdisp8(dst, 0, CONTEXT, offsetof(m68k_context, flags) + flag, SZ_B); | 80 cmp_irdisp(&opts->gen.code, 0, opts->gen.context_reg, offsetof(m68k_context, flags) + flag, SZ_B); |
111 } | 81 } |
112 return dst; | 82 } |
113 } | 83 |
114 | 84 void flag_to_reg(x86_68k_options *opts, uint8_t flag, uint8_t reg) |
115 code_ptr flag_to_reg(code_ptr dst, uint8_t flag, uint8_t reg, x86_68k_options *opts) | |
116 { | 85 { |
117 if (opts->flag_regs[flag] >= 0) { | 86 if (opts->flag_regs[flag] >= 0) { |
118 dst = mov_rr(dst, opts->flag_regs[flag], reg, SZ_B); | 87 mov_rr(&opts->gen.code, opts->flag_regs[flag], reg, SZ_B); |
119 } else { | 88 } else { |
120 int8_t offset = offsetof(m68k_context, flags) + flag; | 89 int8_t offset = offsetof(m68k_context, flags) + flag; |
121 if (offset) { | 90 if (offset) { |
122 dst = mov_rdisp8r(dst, CONTEXT, offset, reg, SZ_B); | 91 mov_rdispr(&opts->gen.code, opts->gen.context_reg, offset, reg, SZ_B); |
123 } else { | 92 } else { |
124 dst = mov_rindr(dst, CONTEXT, reg, SZ_B); | 93 mov_rindr(&opts->gen.code, opts->gen.context_reg, reg, SZ_B); |
125 } | 94 } |
126 } | 95 } |
127 return dst; | 96 } |
128 } | 97 |
129 | 98 void reg_to_flag(x86_68k_options *opts, uint8_t reg, uint8_t flag) |
130 code_ptr reg_to_flag(code_ptr dst, uint8_t flag, uint8_t reg, x86_68k_options *opts) | |
131 { | 99 { |
132 if (opts->flag_regs[flag] >= 0) { | 100 if (opts->flag_regs[flag] >= 0) { |
133 dst = mov_rr(dst, reg, opts->flag_regs[flag], SZ_B); | 101 mov_rr(&opts->gen.code, reg, opts->flag_regs[flag], SZ_B); |
134 } else { | 102 } else { |
135 int8_t offset = offsetof(m68k_context, flags) + flag; | 103 int8_t offset = offsetof(m68k_context, flags) + flag; |
136 if (offset) { | 104 if (offset) { |
137 dst = mov_rrdisp8(dst, reg, CONTEXT, offset, SZ_B); | 105 mov_rrdisp(&opts->gen.code, reg, opts->gen.context_reg, offset, SZ_B); |
138 } else { | 106 } else { |
139 dst = mov_rrind(dst, reg, CONTEXT, SZ_B); | 107 mov_rrind(&opts->gen.code, reg, opts->gen.context_reg, SZ_B); |
140 } | 108 } |
141 } | 109 } |
142 return dst; | 110 } |
143 } | 111 |
144 | 112 void flag_to_flag(x86_68k_options *opts, uint8_t flag1, uint8_t flag2) |
145 code_ptr flag_to_flag(code_ptr dst, uint8_t flag1, uint8_t flag2, x86_68k_options *opts) | 113 { |
146 { | 114 code_info *code = &opts->gen.code; |
147 if (opts->flag_regs[flag1] >= 0 && opts->flag_regs[flag2] >= 0) { | 115 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); | 116 mov_rr(code, opts->flag_regs[flag1], opts->flag_regs[flag2], SZ_B); |
149 } else if(opts->flag_regs[flag1] >= 0) { | 117 } else if(opts->flag_regs[flag1] >= 0) { |
150 dst = mov_rrdisp8(dst, opts->flag_regs[flag1], CONTEXT, offsetof(m68k_context, flags) + flag2, SZ_B); | 118 mov_rrdisp(code, opts->flag_regs[flag1], opts->gen.context_reg, offsetof(m68k_context, flags) + flag2, SZ_B); |
151 } else if (opts->flag_regs[flag2] >= 0) { | 119 } else if (opts->flag_regs[flag2] >= 0) { |
152 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, flags) + flag1, opts->flag_regs[flag2], SZ_B); | 120 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, flags) + flag1, opts->flag_regs[flag2], SZ_B); |
153 } else { | 121 } else { |
154 dst = push_r(dst, SCRATCH1); | 122 push_r(code, opts->gen.scratch1); |
155 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, flags) + flag1, SCRATCH1, SZ_B); | 123 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, flags) + flag1, opts->gen.scratch1, SZ_B); |
156 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, flags) + flag2, SZ_B); | 124 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, flags) + flag2, SZ_B); |
157 dst = pop_r(dst, SCRATCH1); | 125 pop_r(code, opts->gen.scratch1); |
158 } | 126 } |
159 return dst; | 127 } |
160 } | 128 |
161 | 129 void flag_to_carry(x86_68k_options * opts, uint8_t flag) |
162 code_ptr flag_to_carry(code_ptr dst, uint8_t flag, x86_68k_options * opts) | |
163 { | 130 { |
164 if (opts->flag_regs[flag] >= 0) { | 131 if (opts->flag_regs[flag] >= 0) { |
165 dst = bt_ir(dst, 0, opts->flag_regs[flag], SZ_B); | 132 bt_ir(&opts->gen.code, 0, opts->flag_regs[flag], SZ_B); |
166 } else { | 133 } else { |
167 dst = bt_irdisp8(dst, 0, CONTEXT, offsetof(m68k_context, flags) + flag, SZ_B); | 134 bt_irdisp(&opts->gen.code, 0, opts->gen.context_reg, offsetof(m68k_context, flags) + flag, SZ_B); |
168 } | 135 } |
169 return dst; | 136 } |
170 } | 137 |
171 | 138 void or_flag_to_reg(x86_68k_options *opts, uint8_t flag, uint8_t reg) |
172 code_ptr or_flag_to_reg(code_ptr dst, uint8_t flag, uint8_t reg, x86_68k_options *opts) | |
173 { | 139 { |
174 if (opts->flag_regs[flag] >= 0) { | 140 if (opts->flag_regs[flag] >= 0) { |
175 dst = or_rr(dst, opts->flag_regs[flag], reg, SZ_B); | 141 or_rr(&opts->gen.code, opts->flag_regs[flag], reg, SZ_B); |
176 } else { | 142 } else { |
177 dst = or_rdisp8r(dst, CONTEXT, offsetof(m68k_context, flags) + flag, reg, SZ_B); | 143 or_rdispr(&opts->gen.code, opts->gen.context_reg, offsetof(m68k_context, flags) + flag, reg, SZ_B); |
178 } | 144 } |
179 return dst; | 145 } |
180 } | 146 |
181 | 147 void xor_flag_to_reg(x86_68k_options *opts, uint8_t flag, uint8_t reg) |
182 code_ptr xor_flag_to_reg(code_ptr dst, uint8_t flag, uint8_t reg, x86_68k_options *opts) | |
183 { | 148 { |
184 if (opts->flag_regs[flag] >= 0) { | 149 if (opts->flag_regs[flag] >= 0) { |
185 dst = xor_rr(dst, opts->flag_regs[flag], reg, SZ_B); | 150 xor_rr(&opts->gen.code, opts->flag_regs[flag], reg, SZ_B); |
186 } else { | 151 } else { |
187 dst = xor_rdisp8r(dst, CONTEXT, offsetof(m68k_context, flags) + flag, reg, SZ_B); | 152 xor_rdispr(&opts->gen.code, opts->gen.context_reg, offsetof(m68k_context, flags) + flag, reg, SZ_B); |
188 } | 153 } |
189 return dst; | 154 } |
190 } | 155 |
191 | 156 void xor_flag(x86_68k_options *opts, uint8_t val, uint8_t flag) |
192 code_ptr xor_flag(code_ptr dst, uint8_t val, uint8_t flag, x86_68k_options *opts) | |
193 { | 157 { |
194 if (opts->flag_regs[flag] >= 0) { | 158 if (opts->flag_regs[flag] >= 0) { |
195 dst = xor_ir(dst, val, opts->flag_regs[flag], SZ_B); | 159 xor_ir(&opts->gen.code, val, opts->flag_regs[flag], SZ_B); |
196 } else { | 160 } else { |
197 dst = xor_irdisp8(dst, val, CONTEXT, offsetof(m68k_context, flags) + flag, SZ_B); | 161 xor_irdisp(&opts->gen.code, val, opts->gen.context_reg, offsetof(m68k_context, flags) + flag, SZ_B); |
198 } | 162 } |
199 return dst; | 163 } |
200 } | 164 |
201 | 165 void cmp_flags(x86_68k_options *opts, uint8_t flag1, uint8_t flag2) |
202 code_ptr cmp_flags(code_ptr dst, uint8_t flag1, uint8_t flag2, x86_68k_options *opts) | 166 { |
203 { | 167 code_info *code = &opts->gen.code; |
204 if (opts->flag_regs[flag1] >= 0 && opts->flag_regs[flag2] >= 0) { | 168 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); | 169 cmp_rr(code, opts->flag_regs[flag1], opts->flag_regs[flag2], SZ_B); |
206 } else if(opts->flag_regs[flag1] >= 0 || opts->flag_regs[flag2] >= 0) { | 170 } else if(opts->flag_regs[flag1] >= 0 || opts->flag_regs[flag2] >= 0) { |
207 if (opts->flag_regs[flag2] >= 0) { | 171 if (opts->flag_regs[flag2] >= 0) { |
208 uint8_t tmp = flag1; | 172 uint8_t tmp = flag1; |
209 flag1 = flag2; | 173 flag1 = flag2; |
210 flag2 = tmp; | 174 flag2 = tmp; |
211 } | 175 } |
212 dst = cmp_rrdisp8(dst, opts->flag_regs[flag1], CONTEXT, offsetof(m68k_context, flags) + flag2, SZ_B); | 176 cmp_rrdisp(code, opts->flag_regs[flag1], opts->gen.context_reg, offsetof(m68k_context, flags) + flag2, SZ_B); |
213 } else { | 177 } else { |
214 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, flags) + flag1, SCRATCH1, SZ_B); | 178 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, flags) + flag1, opts->gen.scratch1, SZ_B); |
215 dst = cmp_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, flags) + flag2, SZ_B); | 179 cmp_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, flags) + flag2, SZ_B); |
216 } | 180 } |
217 return dst; | |
218 } | 181 } |
219 | 182 |
220 int8_t native_reg(m68k_op_info * op, x86_68k_options * opts) | 183 int8_t native_reg(m68k_op_info * op, x86_68k_options * opts) |
221 { | 184 { |
222 if (op->addr_mode == MODE_REG) { | 185 if (op->addr_mode == MODE_REG) { |
247 printf("a%d: %X\n", i, context->aregs[i]); | 210 printf("a%d: %X\n", i, context->aregs[i]); |
248 } | 211 } |
249 exit(0); | 212 exit(0); |
250 } | 213 } |
251 | 214 |
252 code_ptr translate_m68k_src(m68kinst * inst, x86_ea * ea, code_ptr out, x86_68k_options * opts) | 215 void m68k_read_size(x86_68k_options *opts, uint8_t size) |
253 { | 216 { |
217 switch (size) | |
218 { | |
219 case OPSIZE_BYTE: | |
220 call(&opts->gen.code, opts->read_8); | |
221 break; | |
222 case OPSIZE_WORD: | |
223 call(&opts->gen.code, opts->read_16); | |
224 break; | |
225 case OPSIZE_LONG: | |
226 call(&opts->gen.code, opts->read_32); | |
227 break; | |
228 } | |
229 } | |
230 | |
231 void m68k_write_size(x86_68k_options *opts, uint8_t size) | |
232 { | |
233 switch (size) | |
234 { | |
235 case OPSIZE_BYTE: | |
236 call(&opts->gen.code, opts->write_8); | |
237 break; | |
238 case OPSIZE_WORD: | |
239 call(&opts->gen.code, opts->write_16); | |
240 break; | |
241 case OPSIZE_LONG: | |
242 call(&opts->gen.code, opts->write_32_highfirst); | |
243 break; | |
244 } | |
245 } | |
246 | |
247 void translate_m68k_src(m68kinst * inst, x86_ea * ea, x86_68k_options * opts) | |
248 { | |
249 code_info *code = &opts->gen.code; | |
254 int8_t reg = native_reg(&(inst->src), opts); | 250 int8_t reg = native_reg(&(inst->src), opts); |
255 uint8_t sec_reg; | 251 uint8_t sec_reg; |
256 int32_t dec_amount,inc_amount; | 252 int32_t dec_amount,inc_amount; |
257 if (reg >= 0) { | 253 if (reg >= 0) { |
258 ea->mode = MODE_REG_DIRECT; | 254 ea->mode = MODE_REG_DIRECT; |
259 if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) { | 255 if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) { |
260 out = movsx_rr(out, reg, SCRATCH1, SZ_W, SZ_D); | 256 movsx_rr(code, reg, opts->gen.scratch1, SZ_W, SZ_D); |
261 ea->base = SCRATCH1; | 257 ea->base = opts->gen.scratch1; |
262 } else { | 258 } else { |
263 ea->base = reg; | 259 ea->base = reg; |
264 } | 260 } |
265 return out; | 261 return; |
266 } | 262 } |
267 switch (inst->src.addr_mode) | 263 switch (inst->src.addr_mode) |
268 { | 264 { |
269 case MODE_REG: | 265 case MODE_REG: |
270 case MODE_AREG: | 266 case MODE_AREG: |
273 reg = native_reg(&(inst->dst), opts); | 269 reg = native_reg(&(inst->dst), opts); |
274 if (reg >= 0 || inst->dst.addr_mode == MODE_UNUSED || !(inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG) | 270 if (reg >= 0 || inst->dst.addr_mode == MODE_UNUSED || !(inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG) |
275 || inst->op == M68K_EXG) { | 271 || inst->op == M68K_EXG) { |
276 | 272 |
277 ea->mode = MODE_REG_DISPLACE8; | 273 ea->mode = MODE_REG_DISPLACE8; |
278 ea->base = CONTEXT; | 274 ea->base = opts->gen.context_reg; |
279 ea->disp = reg_offset(&(inst->src)); | 275 ea->disp = reg_offset(&(inst->src)); |
280 } else { | 276 } else { |
281 if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) { | 277 if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) { |
282 out = movsx_rdisp8r(out, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, SZ_W, SZ_D); | 278 movsx_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_W, SZ_D); |
283 } else { | 279 } else { |
284 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, inst->extra.size); | 280 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, inst->extra.size); |
285 } | 281 } |
286 ea->mode = MODE_REG_DIRECT; | 282 ea->mode = MODE_REG_DIRECT; |
287 ea->base = SCRATCH1; | 283 ea->base = opts->gen.scratch1; |
288 //we're explicitly handling the areg dest here, so we exit immediately | 284 //we're explicitly handling the areg dest here, so we exit immediately |
289 return out; | 285 return; |
290 } | 286 } |
291 break; | 287 break; |
292 case MODE_AREG_PREDEC: | 288 case MODE_AREG_PREDEC: |
293 dec_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->src.params.regs.pri == 7 ? 2 :1)); | 289 dec_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->src.params.regs.pri == 7 ? 2 :1)); |
294 out = cycles(out, PREDEC_PENALTY); | 290 cycles(&opts->gen, PREDEC_PENALTY); |
295 if (opts->aregs[inst->src.params.regs.pri] >= 0) { | 291 if (opts->aregs[inst->src.params.regs.pri] >= 0) { |
296 out = sub_ir(out, dec_amount, opts->aregs[inst->src.params.regs.pri], SZ_D); | 292 sub_ir(code, dec_amount, opts->aregs[inst->src.params.regs.pri], SZ_D); |
297 } else { | 293 } else { |
298 out = sub_irdisp8(out, dec_amount, CONTEXT, reg_offset(&(inst->src)), SZ_D); | 294 sub_irdisp(code, dec_amount, opts->gen.context_reg, reg_offset(&(inst->src)), SZ_D); |
299 } | 295 } |
300 case MODE_AREG_INDIRECT: | 296 case MODE_AREG_INDIRECT: |
301 case MODE_AREG_POSTINC: | 297 case MODE_AREG_POSTINC: |
302 if (opts->aregs[inst->src.params.regs.pri] >= 0) { | 298 if (opts->aregs[inst->src.params.regs.pri] >= 0) { |
303 out = mov_rr(out, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); | 299 mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); |
304 } else { | 300 } else { |
305 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, SZ_D); | 301 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_D); |
306 } | 302 } |
307 switch (inst->extra.size) | 303 m68k_read_size(opts, inst->extra.size); |
308 { | |
309 case OPSIZE_BYTE: | |
310 out = call(out, opts->read_8); | |
311 break; | |
312 case OPSIZE_WORD: | |
313 out = call(out, opts->read_16); | |
314 break; | |
315 case OPSIZE_LONG: | |
316 out = call(out, opts->read_32); | |
317 break; | |
318 } | |
319 | 304 |
320 if (inst->src.addr_mode == MODE_AREG_POSTINC) { | 305 if (inst->src.addr_mode == MODE_AREG_POSTINC) { |
321 inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->src.params.regs.pri == 7 ? 2 : 1)); | 306 inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->src.params.regs.pri == 7 ? 2 : 1)); |
322 if (opts->aregs[inst->src.params.regs.pri] >= 0) { | 307 if (opts->aregs[inst->src.params.regs.pri] >= 0) { |
323 out = add_ir(out, inc_amount, opts->aregs[inst->src.params.regs.pri], SZ_D); | 308 add_ir(code, inc_amount, opts->aregs[inst->src.params.regs.pri], SZ_D); |
324 } else { | 309 } else { |
325 out = add_irdisp8(out, inc_amount, CONTEXT, reg_offset(&(inst->src)), SZ_D); | 310 add_irdisp(code, inc_amount, opts->gen.context_reg, reg_offset(&(inst->src)), SZ_D); |
326 } | 311 } |
327 } | 312 } |
328 ea->mode = MODE_REG_DIRECT; | 313 ea->mode = MODE_REG_DIRECT; |
329 ea->base = (inst->dst.addr_mode == MODE_AREG_PREDEC && inst->op != M68K_MOVE) ? SCRATCH2 : SCRATCH1; | 314 ea->base = (inst->dst.addr_mode == MODE_AREG_PREDEC && inst->op != M68K_MOVE) ? opts->gen.scratch2 : opts->gen.scratch1; |
330 break; | 315 break; |
331 case MODE_AREG_DISPLACE: | 316 case MODE_AREG_DISPLACE: |
332 out = cycles(out, BUS); | 317 cycles(&opts->gen, BUS); |
333 if (opts->aregs[inst->src.params.regs.pri] >= 0) { | 318 if (opts->aregs[inst->src.params.regs.pri] >= 0) { |
334 out = mov_rr(out, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); | 319 mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); |
335 } else { | 320 } else { |
336 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, SZ_D); | 321 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_D); |
337 } | 322 } |
338 out = add_ir(out, inst->src.params.regs.displacement, SCRATCH1, SZ_D); | 323 add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); |
339 switch (inst->extra.size) | 324 m68k_read_size(opts, inst->extra.size); |
340 { | 325 |
341 case OPSIZE_BYTE: | |
342 out = call(out, opts->read_8); | |
343 break; | |
344 case OPSIZE_WORD: | |
345 out = call(out, opts->read_16); | |
346 break; | |
347 case OPSIZE_LONG: | |
348 out = call(out, opts->read_32); | |
349 break; | |
350 } | |
351 ea->mode = MODE_REG_DIRECT; | 326 ea->mode = MODE_REG_DIRECT; |
352 ea->base = SCRATCH1; | 327 ea->base = opts->gen.scratch1; |
353 break; | 328 break; |
354 case MODE_AREG_INDEX_DISP8: | 329 case MODE_AREG_INDEX_DISP8: |
355 out = cycles(out, 6); | 330 cycles(&opts->gen, 6); |
356 if (opts->aregs[inst->src.params.regs.pri] >= 0) { | 331 if (opts->aregs[inst->src.params.regs.pri] >= 0) { |
357 out = mov_rr(out, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); | 332 mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); |
358 } else { | 333 } else { |
359 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, SZ_D); | 334 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_D); |
360 } | 335 } |
361 sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; | 336 sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; |
362 if (inst->src.params.regs.sec & 1) { | 337 if (inst->src.params.regs.sec & 1) { |
363 if (inst->src.params.regs.sec & 0x10) { | 338 if (inst->src.params.regs.sec & 0x10) { |
364 if (opts->aregs[sec_reg] >= 0) { | 339 if (opts->aregs[sec_reg] >= 0) { |
365 out = add_rr(out, opts->aregs[sec_reg], SCRATCH1, SZ_D); | 340 add_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_D); |
366 } else { | 341 } else { |
367 out = add_rdisp8r(out, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D); | 342 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); |
368 } | 343 } |
369 } else { | 344 } else { |
370 if (opts->dregs[sec_reg] >= 0) { | 345 if (opts->dregs[sec_reg] >= 0) { |
371 out = add_rr(out, opts->dregs[sec_reg], SCRATCH1, SZ_D); | 346 add_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_D); |
372 } else { | 347 } else { |
373 out = add_rdisp8r(out, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D); | 348 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); |
374 } | 349 } |
375 } | 350 } |
376 } else { | 351 } else { |
377 if (inst->src.params.regs.sec & 0x10) { | 352 if (inst->src.params.regs.sec & 0x10) { |
378 if (opts->aregs[sec_reg] >= 0) { | 353 if (opts->aregs[sec_reg] >= 0) { |
379 out = movsx_rr(out, opts->aregs[sec_reg], SCRATCH2, SZ_W, SZ_D); | 354 movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); |
380 } else { | 355 } else { |
381 out = movsx_rdisp8r(out, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D); | 356 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); |
382 } | 357 } |
383 } else { | 358 } else { |
384 if (opts->dregs[sec_reg] >= 0) { | 359 if (opts->dregs[sec_reg] >= 0) { |
385 out = movsx_rr(out, opts->dregs[sec_reg], SCRATCH2, SZ_W, SZ_D); | 360 movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); |
386 } else { | 361 } else { |
387 out = movsx_rdisp8r(out, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D); | 362 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); |
388 } | 363 } |
389 } | 364 } |
390 out = add_rr(out, SCRATCH2, SCRATCH1, SZ_D); | 365 add_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D); |
391 } | 366 } |
392 if (inst->src.params.regs.displacement) { | 367 if (inst->src.params.regs.displacement) { |
393 out = add_ir(out, inst->src.params.regs.displacement, SCRATCH1, SZ_D); | 368 add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); |
394 } | 369 } |
395 switch (inst->extra.size) | 370 m68k_read_size(opts, inst->extra.size); |
396 { | 371 |
397 case OPSIZE_BYTE: | |
398 out = call(out, opts->read_8); | |
399 break; | |
400 case OPSIZE_WORD: | |
401 out = call(out, opts->read_16); | |
402 break; | |
403 case OPSIZE_LONG: | |
404 out = call(out, opts->read_32); | |
405 break; | |
406 } | |
407 ea->mode = MODE_REG_DIRECT; | 372 ea->mode = MODE_REG_DIRECT; |
408 ea->base = SCRATCH1; | 373 ea->base = opts->gen.scratch1; |
409 break; | 374 break; |
410 case MODE_PC_DISPLACE: | 375 case MODE_PC_DISPLACE: |
411 out = cycles(out, BUS); | 376 cycles(&opts->gen, BUS); |
412 out = mov_ir(out, inst->src.params.regs.displacement + inst->address+2, SCRATCH1, SZ_D); | 377 mov_ir(code, inst->src.params.regs.displacement + inst->address+2, opts->gen.scratch1, SZ_D); |
413 switch (inst->extra.size) | 378 m68k_read_size(opts, inst->extra.size); |
414 { | 379 |
415 case OPSIZE_BYTE: | |
416 out = call(out, opts->read_8); | |
417 break; | |
418 case OPSIZE_WORD: | |
419 out = call(out, opts->read_16); | |
420 break; | |
421 case OPSIZE_LONG: | |
422 out = call(out, opts->read_32); | |
423 break; | |
424 } | |
425 ea->mode = MODE_REG_DIRECT; | 380 ea->mode = MODE_REG_DIRECT; |
426 ea->base = SCRATCH1; | 381 ea->base = opts->gen.scratch1; |
427 break; | 382 break; |
428 case MODE_PC_INDEX_DISP8: | 383 case MODE_PC_INDEX_DISP8: |
429 out = cycles(out, 6); | 384 cycles(&opts->gen, 6); |
430 out = mov_ir(out, inst->address+2, SCRATCH1, SZ_D); | 385 mov_ir(code, inst->address+2, opts->gen.scratch1, SZ_D); |
431 sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; | 386 sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; |
432 if (inst->src.params.regs.sec & 1) { | 387 if (inst->src.params.regs.sec & 1) { |
433 if (inst->src.params.regs.sec & 0x10) { | 388 if (inst->src.params.regs.sec & 0x10) { |
434 if (opts->aregs[sec_reg] >= 0) { | 389 if (opts->aregs[sec_reg] >= 0) { |
435 out = add_rr(out, opts->aregs[sec_reg], SCRATCH1, SZ_D); | 390 add_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_D); |
436 } else { | 391 } else { |
437 out = add_rdisp8r(out, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D); | 392 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); |
438 } | 393 } |
439 } else { | 394 } else { |
440 if (opts->dregs[sec_reg] >= 0) { | 395 if (opts->dregs[sec_reg] >= 0) { |
441 out = add_rr(out, opts->dregs[sec_reg], SCRATCH1, SZ_D); | 396 add_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_D); |
442 } else { | 397 } else { |
443 out = add_rdisp8r(out, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D); | 398 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); |
444 } | 399 } |
445 } | 400 } |
446 } else { | 401 } else { |
447 if (inst->src.params.regs.sec & 0x10) { | 402 if (inst->src.params.regs.sec & 0x10) { |
448 if (opts->aregs[sec_reg] >= 0) { | 403 if (opts->aregs[sec_reg] >= 0) { |
449 out = movsx_rr(out, opts->aregs[sec_reg], SCRATCH2, SZ_W, SZ_D); | 404 movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); |
450 } else { | 405 } else { |
451 out = movsx_rdisp8r(out, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D); | 406 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); |
452 } | 407 } |
453 } else { | 408 } else { |
454 if (opts->dregs[sec_reg] >= 0) { | 409 if (opts->dregs[sec_reg] >= 0) { |
455 out = movsx_rr(out, opts->dregs[sec_reg], SCRATCH2, SZ_W, SZ_D); | 410 movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); |
456 } else { | 411 } else { |
457 out = movsx_rdisp8r(out, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D); | 412 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); |
458 } | 413 } |
459 } | 414 } |
460 out = add_rr(out, SCRATCH2, SCRATCH1, SZ_D); | 415 add_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D); |
461 } | 416 } |
462 if (inst->src.params.regs.displacement) { | 417 if (inst->src.params.regs.displacement) { |
463 out = add_ir(out, inst->src.params.regs.displacement, SCRATCH1, SZ_D); | 418 add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); |
464 } | 419 } |
465 switch (inst->extra.size) | 420 m68k_read_size(opts, inst->extra.size); |
466 { | 421 |
467 case OPSIZE_BYTE: | |
468 out = call(out, opts->read_8); | |
469 break; | |
470 case OPSIZE_WORD: | |
471 out = call(out, opts->read_16); | |
472 break; | |
473 case OPSIZE_LONG: | |
474 out = call(out, opts->read_32); | |
475 break; | |
476 } | |
477 ea->mode = MODE_REG_DIRECT; | 422 ea->mode = MODE_REG_DIRECT; |
478 ea->base = SCRATCH1; | 423 ea->base = opts->gen.scratch1; |
479 break; | 424 break; |
480 case MODE_ABSOLUTE: | 425 case MODE_ABSOLUTE: |
481 case MODE_ABSOLUTE_SHORT: | 426 case MODE_ABSOLUTE_SHORT: |
482 if (inst->src.addr_mode == MODE_ABSOLUTE) { | 427 cycles(&opts->gen, inst->src.addr_mode == MODE_ABSOLUTE ? BUS*2 : BUS); |
483 out = cycles(out, BUS*2); | 428 mov_ir(code, inst->src.params.immed, opts->gen.scratch1, SZ_D); |
484 } else { | 429 m68k_read_size(opts, inst->extra.size); |
485 out = cycles(out, BUS); | 430 |
486 } | |
487 out = mov_ir(out, inst->src.params.immed, SCRATCH1, SZ_D); | |
488 switch (inst->extra.size) | |
489 { | |
490 case OPSIZE_BYTE: | |
491 out = call(out, opts->read_8); | |
492 break; | |
493 case OPSIZE_WORD: | |
494 out = call(out, opts->read_16); | |
495 break; | |
496 case OPSIZE_LONG: | |
497 out = call(out, opts->read_32); | |
498 break; | |
499 } | |
500 ea->mode = MODE_REG_DIRECT; | 431 ea->mode = MODE_REG_DIRECT; |
501 ea->base = SCRATCH1; | 432 ea->base = opts->gen.scratch1; |
502 break; | 433 break; |
503 case MODE_IMMEDIATE: | 434 case MODE_IMMEDIATE: |
504 case MODE_IMMEDIATE_WORD: | 435 case MODE_IMMEDIATE_WORD: |
505 if (inst->variant != VAR_QUICK) { | 436 if (inst->variant != VAR_QUICK) { |
506 out = cycles(out, (inst->extra.size == OPSIZE_LONG && inst->src.addr_mode == MODE_IMMEDIATE) ? BUS*2 : BUS); | 437 cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG && inst->src.addr_mode == MODE_IMMEDIATE) ? BUS*2 : BUS); |
507 } | 438 } |
508 ea->mode = MODE_IMMED; | 439 ea->mode = MODE_IMMED; |
509 ea->disp = inst->src.params.immed; | 440 ea->disp = inst->src.params.immed; |
510 if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD && ea->disp & 0x8000) { | 441 if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD && ea->disp & 0x8000) { |
511 ea->disp |= 0xFFFF0000; | 442 ea->disp |= 0xFFFF0000; |
512 } | 443 } |
513 return out; | 444 return; |
514 default: | 445 default: |
515 m68k_disasm(inst, disasm_buf); | 446 m68k_disasm(inst, disasm_buf); |
516 printf("%X: %s\naddress mode %d not implemented (src)\n", inst->address, disasm_buf, inst->src.addr_mode); | 447 printf("%X: %s\naddress mode %d not implemented (src)\n", inst->address, disasm_buf, inst->src.addr_mode); |
517 exit(1); | 448 exit(1); |
518 } | 449 } |
519 if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) { | 450 if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) { |
520 if (ea->mode == MODE_REG_DIRECT) { | 451 if (ea->mode == MODE_REG_DIRECT) { |
521 out = movsx_rr(out, ea->base, SCRATCH1, SZ_W, SZ_D); | 452 movsx_rr(code, ea->base, opts->gen.scratch1, SZ_W, SZ_D); |
522 } else { | 453 } else { |
523 out = movsx_rdisp8r(out, ea->base, ea->disp, SCRATCH1, SZ_W, SZ_D); | 454 movsx_rdispr(code, ea->base, ea->disp, opts->gen.scratch1, SZ_W, SZ_D); |
524 ea->mode = MODE_REG_DIRECT; | 455 ea->mode = MODE_REG_DIRECT; |
525 } | 456 } |
526 ea->base = SCRATCH1; | 457 ea->base = opts->gen.scratch1; |
527 } | 458 } |
528 return out; | 459 } |
529 } | 460 |
530 | 461 void translate_m68k_dst(m68kinst * inst, x86_ea * ea, 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) | 462 { |
532 { | 463 code_info *code = &opts->gen.code; |
533 int8_t reg = native_reg(&(inst->dst), opts), sec_reg; | 464 int8_t reg = native_reg(&(inst->dst), opts), sec_reg; |
534 int32_t dec_amount, inc_amount; | 465 int32_t dec_amount, inc_amount; |
535 if (reg >= 0) { | 466 if (reg >= 0) { |
536 ea->mode = MODE_REG_DIRECT; | 467 ea->mode = MODE_REG_DIRECT; |
537 ea->base = reg; | 468 ea->base = reg; |
538 return out; | 469 return; |
539 } | 470 } |
540 switch (inst->dst.addr_mode) | 471 switch (inst->dst.addr_mode) |
541 { | 472 { |
542 case MODE_REG: | 473 case MODE_REG: |
543 case MODE_AREG: | 474 case MODE_AREG: |
544 ea->mode = MODE_REG_DISPLACE8; | 475 ea->mode = MODE_REG_DISPLACE8; |
545 ea->base = CONTEXT; | 476 ea->base = opts->gen.context_reg; |
546 ea->disp = reg_offset(&(inst->dst)); | 477 ea->disp = reg_offset(&(inst->dst)); |
547 break; | 478 break; |
548 case MODE_AREG_PREDEC: | 479 case MODE_AREG_PREDEC: |
549 if (inst->src.addr_mode == MODE_AREG_PREDEC) { | 480 if (inst->src.addr_mode == MODE_AREG_PREDEC) { |
550 out = push_r(out, SCRATCH1); | 481 push_r(code, opts->gen.scratch1); |
551 } | 482 } |
552 dec_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1)); | 483 dec_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1)); |
553 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | 484 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { |
554 out = sub_ir(out, dec_amount, opts->aregs[inst->dst.params.regs.pri], SZ_D); | 485 sub_ir(code, dec_amount, opts->aregs[inst->dst.params.regs.pri], SZ_D); |
555 } else { | 486 } else { |
556 out = sub_irdisp8(out, dec_amount, CONTEXT, reg_offset(&(inst->dst)), SZ_D); | 487 sub_irdisp(code, dec_amount, opts->gen.context_reg, reg_offset(&(inst->dst)), SZ_D); |
557 } | 488 } |
558 case MODE_AREG_INDIRECT: | 489 case MODE_AREG_INDIRECT: |
559 case MODE_AREG_POSTINC: | 490 case MODE_AREG_POSTINC: |
560 if (fake_read) { | 491 if (fake_read) { |
561 out = cycles(out, inst->extra.size == OPSIZE_LONG ? 8 : 4); | 492 cycles(&opts->gen, inst->extra.size == OPSIZE_LONG ? 8 : 4); |
562 } else { | 493 } else { |
563 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | 494 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { |
564 out = mov_rr(out, opts->aregs[inst->dst.params.regs.pri], SCRATCH1, SZ_D); | 495 mov_rr(code, opts->aregs[inst->dst.params.regs.pri], opts->gen.scratch1, SZ_D); |
565 } else { | 496 } else { |
566 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->dst)), SCRATCH1, SZ_D); | 497 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->dst)), opts->gen.scratch1, SZ_D); |
567 } | 498 } |
568 switch (inst->extra.size) | 499 m68k_read_size(opts, inst->extra.size); |
569 { | |
570 case OPSIZE_BYTE: | |
571 out = call(out, opts->read_8); | |
572 break; | |
573 case OPSIZE_WORD: | |
574 out = call(out, opts->read_16); | |
575 break; | |
576 case OPSIZE_LONG: | |
577 out = call(out, opts->read_32); | |
578 break; | |
579 } | |
580 } | 500 } |
581 if (inst->src.addr_mode == MODE_AREG_PREDEC) { | 501 if (inst->src.addr_mode == MODE_AREG_PREDEC) { |
582 //restore src operand to SCRATCH2 | 502 //restore src operand to opts->gen.scratch2 |
583 out =pop_r(out, SCRATCH2); | 503 pop_r(code, opts->gen.scratch2); |
584 } else { | 504 } else { |
585 //save reg value in SCRATCH2 so we can use it to save the result in memory later | 505 //save reg value in opts->gen.scratch2 so we can use it to save the result in memory later |
586 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | 506 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { |
587 out = mov_rr(out, opts->aregs[inst->dst.params.regs.pri], SCRATCH2, SZ_D); | 507 mov_rr(code, opts->aregs[inst->dst.params.regs.pri], opts->gen.scratch2, SZ_D); |
588 } else { | 508 } else { |
589 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->dst)), SCRATCH2, SZ_D); | 509 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->dst)), opts->gen.scratch2, SZ_D); |
590 } | 510 } |
591 } | 511 } |
592 | 512 |
593 if (inst->dst.addr_mode == MODE_AREG_POSTINC) { | 513 if (inst->dst.addr_mode == MODE_AREG_POSTINC) { |
594 inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1)); | 514 inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1)); |
595 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | 515 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { |
596 out = add_ir(out, inc_amount, opts->aregs[inst->dst.params.regs.pri], SZ_D); | 516 add_ir(code, inc_amount, opts->aregs[inst->dst.params.regs.pri], SZ_D); |
597 } else { | 517 } else { |
598 out = add_irdisp8(out, inc_amount, CONTEXT, reg_offset(&(inst->dst)), SZ_D); | 518 add_irdisp(code, inc_amount, opts->gen.context_reg, reg_offset(&(inst->dst)), SZ_D); |
599 } | 519 } |
600 } | 520 } |
601 ea->mode = MODE_REG_DIRECT; | 521 ea->mode = MODE_REG_DIRECT; |
602 ea->base = SCRATCH1; | 522 ea->base = opts->gen.scratch1; |
603 break; | 523 break; |
604 case MODE_AREG_DISPLACE: | 524 case MODE_AREG_DISPLACE: |
605 out = cycles(out, fake_read ? BUS+(inst->extra.size == OPSIZE_LONG ? BUS*2 : BUS) : BUS); | 525 cycles(&opts->gen, fake_read ? BUS+(inst->extra.size == OPSIZE_LONG ? BUS*2 : BUS) : BUS); |
606 reg = fake_read ? SCRATCH2 : SCRATCH1; | 526 reg = fake_read ? opts->gen.scratch2 : opts->gen.scratch1; |
607 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | 527 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { |
608 out = mov_rr(out, opts->aregs[inst->dst.params.regs.pri], reg, SZ_D); | 528 mov_rr(code, opts->aregs[inst->dst.params.regs.pri], reg, SZ_D); |
609 } else { | 529 } else { |
610 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->dst)), reg, SZ_D); | 530 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->dst)), reg, SZ_D); |
611 } | 531 } |
612 out = add_ir(out, inst->dst.params.regs.displacement, reg, SZ_D); | 532 add_ir(code, inst->dst.params.regs.displacement, reg, SZ_D); |
613 if (!fake_read) { | 533 if (!fake_read) { |
614 out = push_r(out, SCRATCH1); | 534 push_r(code, opts->gen.scratch1); |
615 switch (inst->extra.size) | 535 m68k_read_size(opts, inst->extra.size); |
616 { | 536 pop_r(code, opts->gen.scratch2); |
617 case OPSIZE_BYTE: | |
618 out = call(out, opts->read_8); | |
619 break; | |
620 case OPSIZE_WORD: | |
621 out = call(out, opts->read_16); | |
622 break; | |
623 case OPSIZE_LONG: | |
624 out = call(out, opts->read_32); | |
625 break; | |
626 } | |
627 out = pop_r(out, SCRATCH2); | |
628 } | 537 } |
629 ea->mode = MODE_REG_DIRECT; | 538 ea->mode = MODE_REG_DIRECT; |
630 ea->base = SCRATCH1; | 539 ea->base = opts->gen.scratch1; |
631 break; | 540 break; |
632 case MODE_AREG_INDEX_DISP8: | 541 case MODE_AREG_INDEX_DISP8: |
633 out = cycles(out, fake_read ? (6 + inst->extra.size == OPSIZE_LONG ? 8 : 4) : 6); | 542 cycles(&opts->gen, fake_read ? (6 + inst->extra.size == OPSIZE_LONG ? 8 : 4) : 6); |
634 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | 543 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { |
635 out = mov_rr(out, opts->aregs[inst->dst.params.regs.pri], SCRATCH1, SZ_D); | 544 mov_rr(code, opts->aregs[inst->dst.params.regs.pri], opts->gen.scratch1, SZ_D); |
636 } else { | 545 } else { |
637 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->dst)), SCRATCH1, SZ_D); | 546 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->dst)), opts->gen.scratch1, SZ_D); |
638 } | 547 } |
639 sec_reg = (inst->dst.params.regs.sec >> 1) & 0x7; | 548 sec_reg = (inst->dst.params.regs.sec >> 1) & 0x7; |
640 if (inst->dst.params.regs.sec & 1) { | 549 if (inst->dst.params.regs.sec & 1) { |
641 if (inst->dst.params.regs.sec & 0x10) { | 550 if (inst->dst.params.regs.sec & 0x10) { |
642 if (opts->aregs[sec_reg] >= 0) { | 551 if (opts->aregs[sec_reg] >= 0) { |
643 out = add_rr(out, opts->aregs[sec_reg], SCRATCH1, SZ_D); | 552 add_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_D); |
644 } else { | 553 } else { |
645 out = add_rdisp8r(out, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D); | 554 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); |
646 } | 555 } |
647 } else { | 556 } else { |
648 if (opts->dregs[sec_reg] >= 0) { | 557 if (opts->dregs[sec_reg] >= 0) { |
649 out = add_rr(out, opts->dregs[sec_reg], SCRATCH1, SZ_D); | 558 add_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_D); |
650 } else { | 559 } else { |
651 out = add_rdisp8r(out, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D); | 560 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); |
652 } | 561 } |
653 } | 562 } |
654 } else { | 563 } else { |
655 if (inst->dst.params.regs.sec & 0x10) { | 564 if (inst->dst.params.regs.sec & 0x10) { |
656 if (opts->aregs[sec_reg] >= 0) { | 565 if (opts->aregs[sec_reg] >= 0) { |
657 out = movsx_rr(out, opts->aregs[sec_reg], SCRATCH2, SZ_W, SZ_D); | 566 movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); |
658 } else { | 567 } else { |
659 out = movsx_rdisp8r(out, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D); | 568 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); |
660 } | 569 } |
661 } else { | 570 } else { |
662 if (opts->dregs[sec_reg] >= 0) { | 571 if (opts->dregs[sec_reg] >= 0) { |
663 out = movsx_rr(out, opts->dregs[sec_reg], SCRATCH2, SZ_W, SZ_D); | 572 movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); |
664 } else { | 573 } else { |
665 out = movsx_rdisp8r(out, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D); | 574 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); |
666 } | 575 } |
667 } | 576 } |
668 out = add_rr(out, SCRATCH2, SCRATCH1, SZ_D); | 577 add_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D); |
669 } | 578 } |
670 if (inst->dst.params.regs.displacement) { | 579 if (inst->dst.params.regs.displacement) { |
671 out = add_ir(out, inst->dst.params.regs.displacement, SCRATCH1, SZ_D); | 580 add_ir(code, inst->dst.params.regs.displacement, opts->gen.scratch1, SZ_D); |
672 } | 581 } |
673 if (fake_read) { | 582 if (fake_read) { |
674 out = mov_rr(out, SCRATCH1, SCRATCH2, SZ_D); | 583 mov_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_D); |
675 } else { | 584 } else { |
676 out = push_r(out, SCRATCH1); | 585 push_r(code, opts->gen.scratch1); |
677 switch (inst->extra.size) | 586 m68k_read_size(opts, inst->extra.size); |
678 { | 587 pop_r(code, opts->gen.scratch2); |
679 case OPSIZE_BYTE: | |
680 out = call(out, opts->read_8); | |
681 break; | |
682 case OPSIZE_WORD: | |
683 out = call(out, opts->read_16); | |
684 break; | |
685 case OPSIZE_LONG: | |
686 out = call(out, opts->read_32); | |
687 break; | |
688 } | |
689 out = pop_r(out, SCRATCH2); | |
690 } | 588 } |
691 ea->mode = MODE_REG_DIRECT; | 589 ea->mode = MODE_REG_DIRECT; |
692 ea->base = SCRATCH1; | 590 ea->base = opts->gen.scratch1; |
693 break; | 591 break; |
694 case MODE_PC_DISPLACE: | 592 case MODE_PC_DISPLACE: |
695 out = cycles(out, fake_read ? BUS+(inst->extra.size == OPSIZE_LONG ? BUS*2 : BUS) : BUS); | 593 cycles(&opts->gen, fake_read ? BUS+(inst->extra.size == OPSIZE_LONG ? BUS*2 : BUS) : BUS); |
696 out = mov_ir(out, inst->dst.params.regs.displacement + inst->address+2, fake_read ? SCRATCH2 : SCRATCH1, SZ_D); | 594 mov_ir(code, inst->dst.params.regs.displacement + inst->address+2, fake_read ? opts->gen.scratch2 : opts->gen.scratch1, SZ_D); |
697 if (!fake_read) { | 595 if (!fake_read) { |
698 out = push_r(out, SCRATCH1); | 596 push_r(code, opts->gen.scratch1); |
699 switch (inst->extra.size) | 597 m68k_read_size(opts, inst->extra.size); |
700 { | 598 pop_r(code, opts->gen.scratch2); |
701 case OPSIZE_BYTE: | |
702 out = call(out, opts->read_8); | |
703 break; | |
704 case OPSIZE_WORD: | |
705 out = call(out, opts->read_16); | |
706 break; | |
707 case OPSIZE_LONG: | |
708 out = call(out, opts->read_32); | |
709 break; | |
710 } | |
711 out = pop_r(out, SCRATCH2); | |
712 } | 599 } |
713 ea->mode = MODE_REG_DIRECT; | 600 ea->mode = MODE_REG_DIRECT; |
714 ea->base = SCRATCH1; | 601 ea->base = opts->gen.scratch1; |
715 break; | 602 break; |
716 case MODE_PC_INDEX_DISP8: | 603 case MODE_PC_INDEX_DISP8: |
717 out = cycles(out, fake_read ? (6 + inst->extra.size == OPSIZE_LONG ? 8 : 4) : 6); | 604 cycles(&opts->gen, fake_read ? (6 + inst->extra.size == OPSIZE_LONG ? 8 : 4) : 6); |
718 out = mov_ir(out, inst->address+2, SCRATCH1, SZ_D); | 605 mov_ir(code, inst->address+2, opts->gen.scratch1, SZ_D); |
719 sec_reg = (inst->dst.params.regs.sec >> 1) & 0x7; | 606 sec_reg = (inst->dst.params.regs.sec >> 1) & 0x7; |
720 if (inst->dst.params.regs.sec & 1) { | 607 if (inst->dst.params.regs.sec & 1) { |
721 if (inst->dst.params.regs.sec & 0x10) { | 608 if (inst->dst.params.regs.sec & 0x10) { |
722 if (opts->aregs[sec_reg] >= 0) { | 609 if (opts->aregs[sec_reg] >= 0) { |
723 out = add_rr(out, opts->aregs[sec_reg], SCRATCH1, SZ_D); | 610 add_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_D); |
724 } else { | 611 } else { |
725 out = add_rdisp8r(out, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D); | 612 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); |
726 } | 613 } |
727 } else { | 614 } else { |
728 if (opts->dregs[sec_reg] >= 0) { | 615 if (opts->dregs[sec_reg] >= 0) { |
729 out = add_rr(out, opts->dregs[sec_reg], SCRATCH1, SZ_D); | 616 add_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_D); |
730 } else { | 617 } else { |
731 out = add_rdisp8r(out, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D); | 618 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); |
732 } | 619 } |
733 } | 620 } |
734 } else { | 621 } else { |
735 if (inst->dst.params.regs.sec & 0x10) { | 622 if (inst->dst.params.regs.sec & 0x10) { |
736 if (opts->aregs[sec_reg] >= 0) { | 623 if (opts->aregs[sec_reg] >= 0) { |
737 out = movsx_rr(out, opts->aregs[sec_reg], SCRATCH2, SZ_W, SZ_D); | 624 movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); |
738 } else { | 625 } else { |
739 out = movsx_rdisp8r(out, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D); | 626 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); |
740 } | 627 } |
741 } else { | 628 } else { |
742 if (opts->dregs[sec_reg] >= 0) { | 629 if (opts->dregs[sec_reg] >= 0) { |
743 out = movsx_rr(out, opts->dregs[sec_reg], SCRATCH2, SZ_W, SZ_D); | 630 movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); |
744 } else { | 631 } else { |
745 out = movsx_rdisp8r(out, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D); | 632 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); |
746 } | 633 } |
747 } | 634 } |
748 out = add_rr(out, SCRATCH2, SCRATCH1, SZ_D); | 635 add_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D); |
749 } | 636 } |
750 if (inst->dst.params.regs.displacement) { | 637 if (inst->dst.params.regs.displacement) { |
751 out = add_ir(out, inst->dst.params.regs.displacement, SCRATCH1, SZ_D); | 638 add_ir(code, inst->dst.params.regs.displacement, opts->gen.scratch1, SZ_D); |
752 } | 639 } |
753 if (fake_read) { | 640 if (fake_read) { |
754 out = mov_rr(out, SCRATCH1, SCRATCH2, SZ_D); | 641 mov_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_D); |
755 } else { | 642 } else { |
756 out = push_r(out, SCRATCH1); | 643 push_r(code, opts->gen.scratch1); |
757 switch (inst->extra.size) | 644 m68k_read_size(opts, inst->extra.size); |
758 { | 645 pop_r(code, opts->gen.scratch2); |
759 case OPSIZE_BYTE: | |
760 out = call(out, opts->read_8); | |
761 break; | |
762 case OPSIZE_WORD: | |
763 out = call(out, opts->read_16); | |
764 break; | |
765 case OPSIZE_LONG: | |
766 out = call(out, opts->read_32); | |
767 break; | |
768 } | |
769 out = pop_r(out, SCRATCH2); | |
770 } | 646 } |
771 ea->mode = MODE_REG_DIRECT; | 647 ea->mode = MODE_REG_DIRECT; |
772 ea->base = SCRATCH1; | 648 ea->base = opts->gen.scratch1; |
773 break; | 649 break; |
774 case MODE_ABSOLUTE: | 650 case MODE_ABSOLUTE: |
775 case MODE_ABSOLUTE_SHORT: | 651 case MODE_ABSOLUTE_SHORT: |
776 //Add cycles for reading address from instruction stream | 652 //Add cycles for reading address from instruction stream |
777 out = cycles(out, (inst->dst.addr_mode == MODE_ABSOLUTE ? BUS*2 : BUS) + (fake_read ? (inst->extra.size == OPSIZE_LONG ? BUS*2 : BUS) : 0)); | 653 cycles(&opts->gen, (inst->dst.addr_mode == MODE_ABSOLUTE ? BUS*2 : BUS) + (fake_read ? (inst->extra.size == OPSIZE_LONG ? BUS*2 : BUS) : 0)); |
778 out = mov_ir(out, inst->dst.params.immed, fake_read ? SCRATCH2 : SCRATCH1, SZ_D); | 654 mov_ir(code, inst->dst.params.immed, fake_read ? opts->gen.scratch2 : opts->gen.scratch1, SZ_D); |
779 if (!fake_read) { | 655 if (!fake_read) { |
780 out = push_r(out, SCRATCH1); | 656 push_r(code, opts->gen.scratch1); |
781 switch (inst->extra.size) | 657 m68k_read_size(opts, inst->extra.size); |
782 { | 658 pop_r(code, opts->gen.scratch2); |
783 case OPSIZE_BYTE: | |
784 out = call(out, opts->read_8); | |
785 break; | |
786 case OPSIZE_WORD: | |
787 out = call(out, opts->read_16); | |
788 break; | |
789 case OPSIZE_LONG: | |
790 out = call(out, opts->read_32); | |
791 break; | |
792 } | |
793 out = pop_r(out, SCRATCH2); | |
794 } | 659 } |
795 ea->mode = MODE_REG_DIRECT; | 660 ea->mode = MODE_REG_DIRECT; |
796 ea->base = SCRATCH1; | 661 ea->base = opts->gen.scratch1; |
797 break; | 662 break; |
798 default: | 663 default: |
799 m68k_disasm(inst, disasm_buf); | 664 m68k_disasm(inst, disasm_buf); |
800 printf("%X: %s\naddress mode %d not implemented (dst)\n", inst->address, disasm_buf, inst->dst.addr_mode); | 665 printf("%X: %s\naddress mode %d not implemented (dst)\n", inst->address, disasm_buf, inst->dst.addr_mode); |
801 exit(1); | 666 exit(1); |
802 } | 667 } |
803 return out; | 668 } |
804 } | 669 |
805 | 670 void m68k_save_result(m68kinst * inst, x86_68k_options * opts) |
806 code_ptr m68k_save_result(m68kinst * inst, code_ptr out, x86_68k_options * opts) | 671 { |
807 { | 672 code_info *code = &opts->gen.code; |
808 if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG) { | 673 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) { | 674 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) { | 675 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { |
811 out = mov_rr(out, opts->aregs[inst->dst.params.regs.pri], SCRATCH2, SZ_D); | 676 mov_rr(code, opts->aregs[inst->dst.params.regs.pri], opts->gen.scratch2, SZ_D); |
812 } else { | 677 } else { |
813 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->dst)), SCRATCH2, SZ_D); | 678 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->dst)), opts->gen.scratch2, SZ_D); |
814 } | 679 } |
815 } | 680 } |
816 switch (inst->extra.size) | 681 switch (inst->extra.size) |
817 { | 682 { |
818 case OPSIZE_BYTE: | 683 case OPSIZE_BYTE: |
819 out = call(out, opts->write_8); | 684 call(code, opts->write_8); |
820 break; | 685 break; |
821 case OPSIZE_WORD: | 686 case OPSIZE_WORD: |
822 out = call(out, opts->write_16); | 687 call(code, opts->write_16); |
823 break; | 688 break; |
824 case OPSIZE_LONG: | 689 case OPSIZE_LONG: |
825 out = call(out, opts->write_32_lowfirst); | 690 call(code, opts->write_32_lowfirst); |
826 break; | 691 break; |
827 } | 692 } |
828 } | 693 } |
829 return out; | |
830 } | 694 } |
831 | 695 |
832 code_ptr get_native_address(native_map_slot * native_code_map, uint32_t address) | 696 code_ptr get_native_address(native_map_slot * native_code_map, uint32_t address) |
833 { | 697 { |
834 address &= 0xFFFFFF; | 698 address &= 0xFFFFFF; |
913 } | 777 } |
914 uint32_t slot = (address & 0xFFFF)/1024; | 778 uint32_t slot = (address & 0xFFFF)/1024; |
915 return opts->gen.ram_inst_sizes[slot][((address & 0xFFFF)/2)%512]; | 779 return opts->gen.ram_inst_sizes[slot][((address & 0xFFFF)/2)%512]; |
916 } | 780 } |
917 | 781 |
918 code_ptr translate_m68k_move(code_ptr dst, m68kinst * inst, x86_68k_options * opts) | 782 void translate_m68k_move(x86_68k_options * opts, m68kinst * inst) |
919 { | 783 { |
784 code_info *code = &opts->gen.code; | |
920 int8_t reg, flags_reg, sec_reg; | 785 int8_t reg, flags_reg, sec_reg; |
921 uint8_t dir = 0; | 786 uint8_t dir = 0; |
922 int32_t offset; | 787 int32_t offset; |
923 int32_t inc_amount, dec_amount; | 788 int32_t inc_amount, dec_amount; |
924 x86_ea src; | 789 x86_ea src; |
925 dst = translate_m68k_src(inst, &src, dst, opts); | 790 translate_m68k_src(inst, &src, opts); |
926 reg = native_reg(&(inst->dst), opts); | 791 reg = native_reg(&(inst->dst), opts); |
927 if (inst->dst.addr_mode != MODE_AREG) { | 792 if (inst->dst.addr_mode != MODE_AREG) { |
928 //update statically set flags | 793 //update statically set flags |
929 dst = set_flag(dst, 0, FLAG_V, opts); | 794 set_flag(opts, 0, FLAG_V); |
930 dst = set_flag(dst, 0, FLAG_C, opts); | 795 set_flag(opts, 0, FLAG_C); |
931 } | 796 } |
932 | 797 |
933 if (inst->dst.addr_mode != MODE_AREG) { | 798 if (inst->dst.addr_mode != MODE_AREG) { |
934 if (src.mode == MODE_REG_DIRECT) { | 799 if (src.mode == MODE_REG_DIRECT) { |
935 flags_reg = src.base; | 800 flags_reg = src.base; |
936 } else { | 801 } else { |
937 if (reg >= 0) { | 802 if (reg >= 0) { |
938 flags_reg = reg; | 803 flags_reg = reg; |
939 } else { | 804 } else { |
940 if(src.mode == MODE_REG_DISPLACE8) { | 805 if(src.mode == MODE_REG_DISPLACE8) { |
941 dst = mov_rdisp8r(dst, src.base, src.disp, SCRATCH1, inst->extra.size); | 806 mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size); |
942 } else { | 807 } else { |
943 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size); | 808 mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size); |
944 } | 809 } |
945 src.mode = MODE_REG_DIRECT; | 810 src.mode = MODE_REG_DIRECT; |
946 flags_reg = src.base = SCRATCH1; | 811 flags_reg = src.base = opts->gen.scratch1; |
947 } | 812 } |
948 } | 813 } |
949 } | 814 } |
950 uint8_t size = inst->extra.size; | 815 uint8_t size = inst->extra.size; |
951 switch(inst->dst.addr_mode) | 816 switch(inst->dst.addr_mode) |
953 case MODE_AREG: | 818 case MODE_AREG: |
954 size = OPSIZE_LONG; | 819 size = OPSIZE_LONG; |
955 case MODE_REG: | 820 case MODE_REG: |
956 if (reg >= 0) { | 821 if (reg >= 0) { |
957 if (src.mode == MODE_REG_DIRECT) { | 822 if (src.mode == MODE_REG_DIRECT) { |
958 dst = mov_rr(dst, src.base, reg, size); | 823 mov_rr(code, src.base, reg, size); |
959 } else if (src.mode == MODE_REG_DISPLACE8) { | 824 } else if (src.mode == MODE_REG_DISPLACE8) { |
960 dst = mov_rdisp8r(dst, src.base, src.disp, reg, size); | 825 mov_rdispr(code, src.base, src.disp, reg, size); |
961 } else { | 826 } else { |
962 dst = mov_ir(dst, src.disp, reg, size); | 827 mov_ir(code, src.disp, reg, size); |
963 } | 828 } |
964 } else if(src.mode == MODE_REG_DIRECT) { | 829 } else if(src.mode == MODE_REG_DIRECT) { |
965 dst = mov_rrdisp8(dst, src.base, CONTEXT, reg_offset(&(inst->dst)), size); | 830 mov_rrdisp(code, src.base, opts->gen.context_reg, reg_offset(&(inst->dst)), size); |
966 } else { | 831 } else { |
967 dst = mov_irdisp8(dst, src.disp, CONTEXT, reg_offset(&(inst->dst)), size); | 832 mov_irdisp(code, src.disp, opts->gen.context_reg, reg_offset(&(inst->dst)), size); |
968 } | 833 } |
969 if (inst->dst.addr_mode != MODE_AREG) { | 834 if (inst->dst.addr_mode != MODE_AREG) { |
970 dst = cmp_ir(dst, 0, flags_reg, size); | 835 cmp_ir(code, 0, flags_reg, size); |
971 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 836 set_flag_cond(opts, CC_Z, FLAG_Z); |
972 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 837 set_flag_cond(opts, CC_S, FLAG_N); |
973 } | 838 } |
974 break; | 839 break; |
975 case MODE_AREG_PREDEC: | 840 case MODE_AREG_PREDEC: |
976 dec_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1)); | 841 dec_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1)); |
977 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | 842 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { |
978 dst = sub_ir(dst, dec_amount, opts->aregs[inst->dst.params.regs.pri], SZ_D); | 843 sub_ir(code, dec_amount, opts->aregs[inst->dst.params.regs.pri], SZ_D); |
979 } else { | 844 } else { |
980 dst = sub_irdisp8(dst, dec_amount, CONTEXT, reg_offset(&(inst->dst)), SZ_D); | 845 sub_irdisp(code, dec_amount, opts->gen.context_reg, reg_offset(&(inst->dst)), SZ_D); |
981 } | 846 } |
982 case MODE_AREG_INDIRECT: | 847 case MODE_AREG_INDIRECT: |
983 case MODE_AREG_POSTINC: | 848 case MODE_AREG_POSTINC: |
984 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | 849 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { |
985 dst = mov_rr(dst, opts->aregs[inst->dst.params.regs.pri], SCRATCH2, SZ_D); | 850 mov_rr(code, opts->aregs[inst->dst.params.regs.pri], opts->gen.scratch2, SZ_D); |
986 } else { | 851 } else { |
987 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->dst)), SCRATCH2, SZ_D); | 852 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->dst)), opts->gen.scratch2, SZ_D); |
988 } | 853 } |
989 if (src.mode == MODE_REG_DIRECT) { | 854 if (src.mode == MODE_REG_DIRECT) { |
990 if (src.base != SCRATCH1) { | 855 if (src.base != opts->gen.scratch1) { |
991 dst = mov_rr(dst, src.base, SCRATCH1, inst->extra.size); | 856 mov_rr(code, src.base, opts->gen.scratch1, inst->extra.size); |
992 } | 857 } |
993 } else if (src.mode == MODE_REG_DISPLACE8) { | 858 } else if (src.mode == MODE_REG_DISPLACE8) { |
994 dst = mov_rdisp8r(dst, src.base, src.disp, SCRATCH1, inst->extra.size); | 859 mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size); |
995 } else { | 860 } else { |
996 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size); | 861 mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size); |
997 } | 862 } |
998 if (inst->dst.addr_mode != MODE_AREG) { | 863 if (inst->dst.addr_mode != MODE_AREG) { |
999 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); | 864 cmp_ir(code, 0, flags_reg, inst->extra.size); |
1000 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 865 set_flag_cond(opts, CC_Z, FLAG_Z); |
1001 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 866 set_flag_cond(opts, CC_S, FLAG_N); |
1002 } | 867 } |
1003 switch (inst->extra.size) | 868 m68k_write_size(opts, inst->extra.size); |
1004 { | 869 |
1005 case OPSIZE_BYTE: | |
1006 dst = call(dst, opts->write_8); | |
1007 break; | |
1008 case OPSIZE_WORD: | |
1009 dst = call(dst, opts->write_16); | |
1010 break; | |
1011 case OPSIZE_LONG: | |
1012 dst = call(dst, opts->write_32_highfirst); | |
1013 break; | |
1014 } | |
1015 if (inst->dst.addr_mode == MODE_AREG_POSTINC) { | 870 if (inst->dst.addr_mode == MODE_AREG_POSTINC) { |
1016 inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1)); | 871 inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1)); |
1017 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | 872 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { |
1018 dst = add_ir(dst, inc_amount, opts->aregs[inst->dst.params.regs.pri], SZ_D); | 873 add_ir(code, inc_amount, opts->aregs[inst->dst.params.regs.pri], SZ_D); |
1019 } else { | 874 } else { |
1020 dst = add_irdisp8(dst, inc_amount, CONTEXT, reg_offset(&(inst->dst)), SZ_D); | 875 add_irdisp(code, inc_amount, opts->gen.context_reg, reg_offset(&(inst->dst)), SZ_D); |
1021 } | 876 } |
1022 } | 877 } |
1023 break; | 878 break; |
1024 case MODE_AREG_DISPLACE: | 879 case MODE_AREG_DISPLACE: |
1025 dst = cycles(dst, BUS); | 880 cycles(&opts->gen, BUS); |
1026 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | 881 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { |
1027 dst = mov_rr(dst, opts->aregs[inst->dst.params.regs.pri], SCRATCH2, SZ_D); | 882 mov_rr(code, opts->aregs[inst->dst.params.regs.pri], opts->gen.scratch2, SZ_D); |
1028 } else { | 883 } else { |
1029 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->dst)), SCRATCH2, SZ_D); | 884 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->dst)), opts->gen.scratch2, SZ_D); |
1030 } | 885 } |
1031 dst = add_ir(dst, inst->dst.params.regs.displacement, SCRATCH2, SZ_D); | 886 add_ir(code, inst->dst.params.regs.displacement, opts->gen.scratch2, SZ_D); |
1032 if (src.mode == MODE_REG_DIRECT) { | 887 if (src.mode == MODE_REG_DIRECT) { |
1033 if (src.base != SCRATCH1) { | 888 if (src.base != opts->gen.scratch1) { |
1034 dst = mov_rr(dst, src.base, SCRATCH1, inst->extra.size); | 889 mov_rr(code, src.base, opts->gen.scratch1, inst->extra.size); |
1035 } | 890 } |
1036 } else if (src.mode == MODE_REG_DISPLACE8) { | 891 } else if (src.mode == MODE_REG_DISPLACE8) { |
1037 dst = mov_rdisp8r(dst, src.base, src.disp, SCRATCH1, inst->extra.size); | 892 mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size); |
1038 } else { | 893 } else { |
1039 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size); | 894 mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size); |
1040 } | 895 } |
1041 if (inst->dst.addr_mode != MODE_AREG) { | 896 if (inst->dst.addr_mode != MODE_AREG) { |
1042 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); | 897 cmp_ir(code, 0, flags_reg, inst->extra.size); |
1043 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 898 set_flag_cond(opts, CC_Z, FLAG_Z); |
1044 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 899 set_flag_cond(opts, CC_S, FLAG_N); |
1045 } | 900 } |
1046 switch (inst->extra.size) | 901 m68k_write_size(opts, inst->extra.size); |
1047 { | |
1048 case OPSIZE_BYTE: | |
1049 dst = call(dst, opts->write_8); | |
1050 break; | |
1051 case OPSIZE_WORD: | |
1052 dst = call(dst, opts->write_16); | |
1053 break; | |
1054 case OPSIZE_LONG: | |
1055 dst = call(dst, opts->write_32_highfirst); | |
1056 break; | |
1057 } | |
1058 break; | 902 break; |
1059 case MODE_AREG_INDEX_DISP8: | 903 case MODE_AREG_INDEX_DISP8: |
1060 dst = cycles(dst, 6);//TODO: Check to make sure this is correct | 904 cycles(&opts->gen, 6);//TODO: Check to make sure this is correct |
1061 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | 905 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { |
1062 dst = mov_rr(dst, opts->aregs[inst->dst.params.regs.pri], SCRATCH2, SZ_D); | 906 mov_rr(code, opts->aregs[inst->dst.params.regs.pri], opts->gen.scratch2, SZ_D); |
1063 } else { | 907 } else { |
1064 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->dst)), SCRATCH2, SZ_D); | 908 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->dst)), opts->gen.scratch2, SZ_D); |
1065 } | 909 } |
1066 sec_reg = (inst->dst.params.regs.sec >> 1) & 0x7; | 910 sec_reg = (inst->dst.params.regs.sec >> 1) & 0x7; |
1067 if (inst->dst.params.regs.sec & 1) { | 911 if (inst->dst.params.regs.sec & 1) { |
1068 if (inst->dst.params.regs.sec & 0x10) { | 912 if (inst->dst.params.regs.sec & 0x10) { |
1069 if (opts->aregs[sec_reg] >= 0) { | 913 if (opts->aregs[sec_reg] >= 0) { |
1070 dst = add_rr(dst, opts->aregs[sec_reg], SCRATCH2, SZ_D); | 914 add_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_D); |
1071 } else { | 915 } else { |
1072 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_D); | 916 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_D); |
1073 } | 917 } |
1074 } else { | 918 } else { |
1075 if (opts->dregs[sec_reg] >= 0) { | 919 if (opts->dregs[sec_reg] >= 0) { |
1076 dst = add_rr(dst, opts->dregs[sec_reg], SCRATCH2, SZ_D); | 920 add_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_D); |
1077 } else { | 921 } else { |
1078 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_D); | 922 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_D); |
1079 } | 923 } |
1080 } | 924 } |
1081 } else { | 925 } else { |
1082 if (src.base == SCRATCH1) { | 926 if (src.base == opts->gen.scratch1) { |
1083 dst = push_r(dst, SCRATCH1); | 927 push_r(code, opts->gen.scratch1); |
1084 } | 928 } |
1085 if (inst->dst.params.regs.sec & 0x10) { | 929 if (inst->dst.params.regs.sec & 0x10) { |
1086 if (opts->aregs[sec_reg] >= 0) { | 930 if (opts->aregs[sec_reg] >= 0) { |
1087 dst = movsx_rr(dst, opts->aregs[sec_reg], SCRATCH1, SZ_W, SZ_D); | 931 movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_W, SZ_D); |
1088 } else { | 932 } else { |
1089 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_W, SZ_D); | 933 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_W, SZ_D); |
1090 } | 934 } |
1091 } else { | 935 } else { |
1092 if (opts->dregs[sec_reg] >= 0) { | 936 if (opts->dregs[sec_reg] >= 0) { |
1093 dst = movsx_rr(dst, opts->dregs[sec_reg], SCRATCH1, SZ_W, SZ_D); | 937 movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_W, SZ_D); |
1094 } else { | 938 } else { |
1095 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_W, SZ_D); | 939 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_W, SZ_D); |
1096 } | 940 } |
1097 } | 941 } |
1098 dst = add_rr(dst, SCRATCH1, SCRATCH2, SZ_D); | 942 add_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_D); |
1099 if (src.base == SCRATCH1) { | 943 if (src.base == opts->gen.scratch1) { |
1100 dst = pop_r(dst, SCRATCH1); | 944 pop_r(code, opts->gen.scratch1); |
1101 } | 945 } |
1102 } | 946 } |
1103 if (inst->dst.params.regs.displacement) { | 947 if (inst->dst.params.regs.displacement) { |
1104 dst = add_ir(dst, inst->dst.params.regs.displacement, SCRATCH2, SZ_D); | 948 add_ir(code, inst->dst.params.regs.displacement, opts->gen.scratch2, SZ_D); |
1105 } | 949 } |
1106 if (src.mode == MODE_REG_DIRECT) { | 950 if (src.mode == MODE_REG_DIRECT) { |
1107 if (src.base != SCRATCH1) { | 951 if (src.base != opts->gen.scratch1) { |
1108 dst = mov_rr(dst, src.base, SCRATCH1, inst->extra.size); | 952 mov_rr(code, src.base, opts->gen.scratch1, inst->extra.size); |
1109 } | 953 } |
1110 } else if (src.mode == MODE_REG_DISPLACE8) { | 954 } else if (src.mode == MODE_REG_DISPLACE8) { |
1111 dst = mov_rdisp8r(dst, src.base, src.disp, SCRATCH1, inst->extra.size); | 955 mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size); |
1112 } else { | 956 } else { |
1113 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size); | 957 mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size); |
1114 } | 958 } |
1115 if (inst->dst.addr_mode != MODE_AREG) { | 959 if (inst->dst.addr_mode != MODE_AREG) { |
1116 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); | 960 cmp_ir(code, 0, flags_reg, inst->extra.size); |
1117 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 961 set_flag_cond(opts, CC_Z, FLAG_Z); |
1118 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 962 set_flag_cond(opts, CC_S, FLAG_N); |
1119 } | 963 } |
1120 switch (inst->extra.size) | 964 m68k_write_size(opts, inst->extra.size); |
1121 { | |
1122 case OPSIZE_BYTE: | |
1123 dst = call(dst, opts->write_8); | |
1124 break; | |
1125 case OPSIZE_WORD: | |
1126 dst = call(dst, opts->write_16); | |
1127 break; | |
1128 case OPSIZE_LONG: | |
1129 dst = call(dst, opts->write_32_highfirst); | |
1130 break; | |
1131 } | |
1132 break; | 965 break; |
1133 case MODE_PC_DISPLACE: | 966 case MODE_PC_DISPLACE: |
1134 dst = cycles(dst, BUS); | 967 cycles(&opts->gen, BUS); |
1135 dst = mov_ir(dst, inst->dst.params.regs.displacement + inst->address+2, SCRATCH2, SZ_D); | 968 mov_ir(code, inst->dst.params.regs.displacement + inst->address+2, opts->gen.scratch2, SZ_D); |
1136 if (src.mode == MODE_REG_DIRECT) { | 969 if (src.mode == MODE_REG_DIRECT) { |
1137 if (src.base != SCRATCH1) { | 970 if (src.base != opts->gen.scratch1) { |
1138 dst = mov_rr(dst, src.base, SCRATCH1, inst->extra.size); | 971 mov_rr(code, src.base, opts->gen.scratch1, inst->extra.size); |
1139 } | 972 } |
1140 } else if (src.mode == MODE_REG_DISPLACE8) { | 973 } else if (src.mode == MODE_REG_DISPLACE8) { |
1141 dst = mov_rdisp8r(dst, src.base, src.disp, SCRATCH1, inst->extra.size); | 974 mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size); |
1142 } else { | 975 } else { |
1143 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size); | 976 mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size); |
1144 } | 977 } |
1145 if (inst->dst.addr_mode != MODE_AREG) { | 978 if (inst->dst.addr_mode != MODE_AREG) { |
1146 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); | 979 cmp_ir(code, 0, flags_reg, inst->extra.size); |
1147 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 980 set_flag_cond(opts, CC_Z, FLAG_Z); |
1148 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 981 set_flag_cond(opts, CC_S, FLAG_N); |
1149 } | 982 } |
1150 switch (inst->extra.size) | 983 m68k_write_size(opts, inst->extra.size); |
1151 { | |
1152 case OPSIZE_BYTE: | |
1153 dst = call(dst, opts->write_8); | |
1154 break; | |
1155 case OPSIZE_WORD: | |
1156 dst = call(dst, opts->write_16); | |
1157 break; | |
1158 case OPSIZE_LONG: | |
1159 dst = call(dst, opts->write_32_highfirst); | |
1160 break; | |
1161 } | |
1162 break; | 984 break; |
1163 case MODE_PC_INDEX_DISP8: | 985 case MODE_PC_INDEX_DISP8: |
1164 dst = cycles(dst, 6);//TODO: Check to make sure this is correct | 986 cycles(&opts->gen, 6);//TODO: Check to make sure this is correct |
1165 dst = mov_ir(dst, inst->address, SCRATCH2, SZ_D); | 987 mov_ir(code, inst->address, opts->gen.scratch2, SZ_D); |
1166 sec_reg = (inst->dst.params.regs.sec >> 1) & 0x7; | 988 sec_reg = (inst->dst.params.regs.sec >> 1) & 0x7; |
1167 if (inst->dst.params.regs.sec & 1) { | 989 if (inst->dst.params.regs.sec & 1) { |
1168 if (inst->dst.params.regs.sec & 0x10) { | 990 if (inst->dst.params.regs.sec & 0x10) { |
1169 if (opts->aregs[sec_reg] >= 0) { | 991 if (opts->aregs[sec_reg] >= 0) { |
1170 dst = add_rr(dst, opts->aregs[sec_reg], SCRATCH2, SZ_D); | 992 add_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_D); |
1171 } else { | 993 } else { |
1172 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_D); | 994 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_D); |
1173 } | 995 } |
1174 } else { | 996 } else { |
1175 if (opts->dregs[sec_reg] >= 0) { | 997 if (opts->dregs[sec_reg] >= 0) { |
1176 dst = add_rr(dst, opts->dregs[sec_reg], SCRATCH2, SZ_D); | 998 add_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_D); |
1177 } else { | 999 } else { |
1178 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_D); | 1000 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_D); |
1179 } | 1001 } |
1180 } | 1002 } |
1181 } else { | 1003 } else { |
1182 if (src.base == SCRATCH1) { | 1004 if (src.base == opts->gen.scratch1) { |
1183 dst = push_r(dst, SCRATCH1); | 1005 push_r(code, opts->gen.scratch1); |
1184 } | 1006 } |
1185 if (inst->dst.params.regs.sec & 0x10) { | 1007 if (inst->dst.params.regs.sec & 0x10) { |
1186 if (opts->aregs[sec_reg] >= 0) { | 1008 if (opts->aregs[sec_reg] >= 0) { |
1187 dst = movsx_rr(dst, opts->aregs[sec_reg], SCRATCH1, SZ_W, SZ_D); | 1009 movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_W, SZ_D); |
1188 } else { | 1010 } else { |
1189 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_W, SZ_D); | 1011 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_W, SZ_D); |
1190 } | 1012 } |
1191 } else { | 1013 } else { |
1192 if (opts->dregs[sec_reg] >= 0) { | 1014 if (opts->dregs[sec_reg] >= 0) { |
1193 dst = movsx_rr(dst, opts->dregs[sec_reg], SCRATCH1, SZ_W, SZ_D); | 1015 movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_W, SZ_D); |
1194 } else { | 1016 } else { |
1195 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_W, SZ_D); | 1017 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_W, SZ_D); |
1196 } | 1018 } |
1197 } | 1019 } |
1198 dst = add_rr(dst, SCRATCH1, SCRATCH2, SZ_D); | 1020 add_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_D); |
1199 if (src.base == SCRATCH1) { | 1021 if (src.base == opts->gen.scratch1) { |
1200 dst = pop_r(dst, SCRATCH1); | 1022 pop_r(code, opts->gen.scratch1); |
1201 } | 1023 } |
1202 } | 1024 } |
1203 if (inst->dst.params.regs.displacement) { | 1025 if (inst->dst.params.regs.displacement) { |
1204 dst = add_ir(dst, inst->dst.params.regs.displacement, SCRATCH2, SZ_D); | 1026 add_ir(code, inst->dst.params.regs.displacement, opts->gen.scratch2, SZ_D); |
1205 } | 1027 } |
1206 if (src.mode == MODE_REG_DIRECT) { | 1028 if (src.mode == MODE_REG_DIRECT) { |
1207 if (src.base != SCRATCH1) { | 1029 if (src.base != opts->gen.scratch1) { |
1208 dst = mov_rr(dst, src.base, SCRATCH1, inst->extra.size); | 1030 mov_rr(code, src.base, opts->gen.scratch1, inst->extra.size); |
1209 } | 1031 } |
1210 } else if (src.mode == MODE_REG_DISPLACE8) { | 1032 } else if (src.mode == MODE_REG_DISPLACE8) { |
1211 dst = mov_rdisp8r(dst, src.base, src.disp, SCRATCH1, inst->extra.size); | 1033 mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size); |
1212 } else { | 1034 } else { |
1213 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size); | 1035 mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size); |
1214 } | 1036 } |
1215 if (inst->dst.addr_mode != MODE_AREG) { | 1037 if (inst->dst.addr_mode != MODE_AREG) { |
1216 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); | 1038 cmp_ir(code, 0, flags_reg, inst->extra.size); |
1217 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 1039 set_flag_cond(opts, CC_Z, FLAG_Z); |
1218 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 1040 set_flag_cond(opts, CC_S, FLAG_N); |
1219 } | 1041 } |
1220 switch (inst->extra.size) | 1042 m68k_write_size(opts, inst->extra.size); |
1221 { | |
1222 case OPSIZE_BYTE: | |
1223 dst = call(dst, opts->write_8); | |
1224 break; | |
1225 case OPSIZE_WORD: | |
1226 dst = call(dst, opts->write_16); | |
1227 break; | |
1228 case OPSIZE_LONG: | |
1229 dst = call(dst, opts->write_32_highfirst); | |
1230 break; | |
1231 } | |
1232 break; | 1043 break; |
1233 case MODE_ABSOLUTE: | 1044 case MODE_ABSOLUTE: |
1234 case MODE_ABSOLUTE_SHORT: | 1045 case MODE_ABSOLUTE_SHORT: |
1235 if (src.mode == MODE_REG_DIRECT) { | 1046 if (src.mode == MODE_REG_DIRECT) { |
1236 if (src.base != SCRATCH1) { | 1047 if (src.base != opts->gen.scratch1) { |
1237 dst = mov_rr(dst, src.base, SCRATCH1, inst->extra.size); | 1048 mov_rr(code, src.base, opts->gen.scratch1, inst->extra.size); |
1238 } | 1049 } |
1239 } else if (src.mode == MODE_REG_DISPLACE8) { | 1050 } else if (src.mode == MODE_REG_DISPLACE8) { |
1240 dst = mov_rdisp8r(dst, src.base, src.disp, SCRATCH1, inst->extra.size); | 1051 mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size); |
1241 } else { | 1052 } else { |
1242 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size); | 1053 mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size); |
1243 } | 1054 } |
1244 if (inst->dst.addr_mode == MODE_ABSOLUTE) { | 1055 if (inst->dst.addr_mode == MODE_ABSOLUTE) { |
1245 dst = cycles(dst, BUS*2); | 1056 cycles(&opts->gen, BUS*2); |
1246 } else { | 1057 } else { |
1247 dst = cycles(dst, BUS); | 1058 cycles(&opts->gen, BUS); |
1248 } | 1059 } |
1249 dst = mov_ir(dst, inst->dst.params.immed, SCRATCH2, SZ_D); | 1060 mov_ir(code, inst->dst.params.immed, opts->gen.scratch2, SZ_D); |
1250 if (inst->dst.addr_mode != MODE_AREG) { | 1061 if (inst->dst.addr_mode != MODE_AREG) { |
1251 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); | 1062 cmp_ir(code, 0, flags_reg, inst->extra.size); |
1252 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 1063 set_flag_cond(opts, CC_Z, FLAG_Z); |
1253 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 1064 set_flag_cond(opts, CC_S, FLAG_N); |
1254 } | 1065 } |
1255 switch (inst->extra.size) | 1066 m68k_write_size(opts, inst->extra.size); |
1256 { | |
1257 case OPSIZE_BYTE: | |
1258 dst = call(dst, opts->write_8); | |
1259 break; | |
1260 case OPSIZE_WORD: | |
1261 dst = call(dst, opts->write_16); | |
1262 break; | |
1263 case OPSIZE_LONG: | |
1264 dst = call(dst, opts->write_32_highfirst); | |
1265 break; | |
1266 } | |
1267 break; | 1067 break; |
1268 default: | 1068 default: |
1269 m68k_disasm(inst, disasm_buf); | 1069 m68k_disasm(inst, disasm_buf); |
1270 printf("%X: %s\naddress mode %d not implemented (move dst)\n", inst->address, disasm_buf, inst->dst.addr_mode); | 1070 printf("%X: %s\naddress mode %d not implemented (move dst)\n", inst->address, disasm_buf, inst->dst.addr_mode); |
1271 exit(1); | 1071 exit(1); |
1272 } | 1072 } |
1273 | 1073 |
1274 //add cycles for prefetch | 1074 //add cycles for prefetch |
1275 dst = cycles(dst, BUS); | 1075 cycles(&opts->gen, BUS); |
1276 return dst; | 1076 } |
1277 } | 1077 |
1278 | 1078 void translate_m68k_movem(x86_68k_options * opts, m68kinst * inst) |
1279 code_ptr translate_m68k_movem(code_ptr dst, m68kinst * inst, x86_68k_options * opts) | 1079 { |
1280 { | 1080 code_info *code = &opts->gen.code; |
1281 int8_t bit,reg,sec_reg; | 1081 int8_t bit,reg,sec_reg; |
1282 uint8_t early_cycles; | 1082 uint8_t early_cycles; |
1283 if(inst->src.addr_mode == MODE_REG) { | 1083 if(inst->src.addr_mode == MODE_REG) { |
1284 //reg to mem | 1084 //reg to mem |
1285 early_cycles = 8; | 1085 early_cycles = 8; |
1287 switch (inst->dst.addr_mode) | 1087 switch (inst->dst.addr_mode) |
1288 { | 1088 { |
1289 case MODE_AREG_INDIRECT: | 1089 case MODE_AREG_INDIRECT: |
1290 case MODE_AREG_PREDEC: | 1090 case MODE_AREG_PREDEC: |
1291 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | 1091 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { |
1292 dst = mov_rr(dst, opts->aregs[inst->dst.params.regs.pri], SCRATCH2, SZ_D); | 1092 mov_rr(code, opts->aregs[inst->dst.params.regs.pri], opts->gen.scratch2, SZ_D); |
1293 } else { | 1093 } else { |
1294 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->dst)), SCRATCH2, SZ_D); | 1094 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->dst)), opts->gen.scratch2, SZ_D); |
1295 } | 1095 } |
1296 break; | 1096 break; |
1297 case MODE_AREG_DISPLACE: | 1097 case MODE_AREG_DISPLACE: |
1298 early_cycles += BUS; | 1098 early_cycles += BUS; |
1299 reg = SCRATCH2; | 1099 reg = opts->gen.scratch2; |
1300 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | 1100 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { |
1301 dst = mov_rr(dst, opts->aregs[inst->dst.params.regs.pri], SCRATCH2, SZ_D); | 1101 mov_rr(code, opts->aregs[inst->dst.params.regs.pri], opts->gen.scratch2, SZ_D); |
1302 } else { | 1102 } else { |
1303 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->dst)), SCRATCH2, SZ_D); | 1103 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->dst)), opts->gen.scratch2, SZ_D); |
1304 } | 1104 } |
1305 dst = add_ir(dst, inst->dst.params.regs.displacement, SCRATCH2, SZ_D); | 1105 add_ir(code, inst->dst.params.regs.displacement, opts->gen.scratch2, SZ_D); |
1306 break; | 1106 break; |
1307 case MODE_AREG_INDEX_DISP8: | 1107 case MODE_AREG_INDEX_DISP8: |
1308 early_cycles += 6; | 1108 early_cycles += 6; |
1309 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | 1109 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { |
1310 dst = mov_rr(dst, opts->aregs[inst->dst.params.regs.pri], SCRATCH2, SZ_D); | 1110 mov_rr(code, opts->aregs[inst->dst.params.regs.pri], opts->gen.scratch2, SZ_D); |
1311 } else { | 1111 } else { |
1312 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->dst)), SCRATCH2, SZ_D); | 1112 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->dst)), opts->gen.scratch2, SZ_D); |
1313 } | 1113 } |
1314 sec_reg = (inst->dst.params.regs.sec >> 1) & 0x7; | 1114 sec_reg = (inst->dst.params.regs.sec >> 1) & 0x7; |
1315 if (inst->dst.params.regs.sec & 1) { | 1115 if (inst->dst.params.regs.sec & 1) { |
1316 if (inst->dst.params.regs.sec & 0x10) { | 1116 if (inst->dst.params.regs.sec & 0x10) { |
1317 if (opts->aregs[sec_reg] >= 0) { | 1117 if (opts->aregs[sec_reg] >= 0) { |
1318 dst = add_rr(dst, opts->aregs[sec_reg], SCRATCH2, SZ_D); | 1118 add_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_D); |
1319 } else { | 1119 } else { |
1320 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_D); | 1120 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_D); |
1321 } | 1121 } |
1322 } else { | 1122 } else { |
1323 if (opts->dregs[sec_reg] >= 0) { | 1123 if (opts->dregs[sec_reg] >= 0) { |
1324 dst = add_rr(dst, opts->dregs[sec_reg], SCRATCH2, SZ_D); | 1124 add_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_D); |
1325 } else { | 1125 } else { |
1326 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_D); | 1126 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_D); |
1327 } | 1127 } |
1328 } | 1128 } |
1329 } else { | 1129 } else { |
1330 if (inst->dst.params.regs.sec & 0x10) { | 1130 if (inst->dst.params.regs.sec & 0x10) { |
1331 if (opts->aregs[sec_reg] >= 0) { | 1131 if (opts->aregs[sec_reg] >= 0) { |
1332 dst = movsx_rr(dst, opts->aregs[sec_reg], SCRATCH1, SZ_W, SZ_D); | 1132 movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_W, SZ_D); |
1333 } else { | 1133 } else { |
1334 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_W, SZ_D); | 1134 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_W, SZ_D); |
1335 } | 1135 } |
1336 } else { | 1136 } else { |
1337 if (opts->dregs[sec_reg] >= 0) { | 1137 if (opts->dregs[sec_reg] >= 0) { |
1338 dst = movsx_rr(dst, opts->dregs[sec_reg], SCRATCH1, SZ_W, SZ_D); | 1138 movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_W, SZ_D); |
1339 } else { | 1139 } else { |
1340 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_W, SZ_D); | 1140 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_W, SZ_D); |
1341 } | 1141 } |
1342 } | 1142 } |
1343 dst = add_rr(dst, SCRATCH1, SCRATCH2, SZ_D); | 1143 add_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_D); |
1344 } | 1144 } |
1345 if (inst->dst.params.regs.displacement) { | 1145 if (inst->dst.params.regs.displacement) { |
1346 dst = add_ir(dst, inst->dst.params.regs.displacement, SCRATCH2, SZ_D); | 1146 add_ir(code, inst->dst.params.regs.displacement, opts->gen.scratch2, SZ_D); |
1347 } | 1147 } |
1348 break; | 1148 break; |
1349 case MODE_PC_DISPLACE: | 1149 case MODE_PC_DISPLACE: |
1350 early_cycles += BUS; | 1150 early_cycles += BUS; |
1351 dst = mov_ir(dst, inst->dst.params.regs.displacement + inst->address+2, SCRATCH2, SZ_D); | 1151 mov_ir(code, inst->dst.params.regs.displacement + inst->address+2, opts->gen.scratch2, SZ_D); |
1352 break; | 1152 break; |
1353 case MODE_PC_INDEX_DISP8: | 1153 case MODE_PC_INDEX_DISP8: |
1354 early_cycles += 6; | 1154 early_cycles += 6; |
1355 dst = mov_ir(dst, inst->address+2, SCRATCH2, SZ_D); | 1155 mov_ir(code, inst->address+2, opts->gen.scratch2, SZ_D); |
1356 sec_reg = (inst->dst.params.regs.sec >> 1) & 0x7; | 1156 sec_reg = (inst->dst.params.regs.sec >> 1) & 0x7; |
1357 if (inst->dst.params.regs.sec & 1) { | 1157 if (inst->dst.params.regs.sec & 1) { |
1358 if (inst->dst.params.regs.sec & 0x10) { | 1158 if (inst->dst.params.regs.sec & 0x10) { |
1359 if (opts->aregs[sec_reg] >= 0) { | 1159 if (opts->aregs[sec_reg] >= 0) { |
1360 dst = add_rr(dst, opts->aregs[sec_reg], SCRATCH2, SZ_D); | 1160 add_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_D); |
1361 } else { | 1161 } else { |
1362 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_D); | 1162 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_D); |
1363 } | 1163 } |
1364 } else { | 1164 } else { |
1365 if (opts->dregs[sec_reg] >= 0) { | 1165 if (opts->dregs[sec_reg] >= 0) { |
1366 dst = add_rr(dst, opts->dregs[sec_reg], SCRATCH2, SZ_D); | 1166 add_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_D); |
1367 } else { | 1167 } else { |
1368 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_D); | 1168 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_D); |
1369 } | 1169 } |
1370 } | 1170 } |
1371 } else { | 1171 } else { |
1372 if (inst->dst.params.regs.sec & 0x10) { | 1172 if (inst->dst.params.regs.sec & 0x10) { |
1373 if (opts->aregs[sec_reg] >= 0) { | 1173 if (opts->aregs[sec_reg] >= 0) { |
1374 dst = movsx_rr(dst, opts->aregs[sec_reg], SCRATCH1, SZ_W, SZ_D); | 1174 movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_W, SZ_D); |
1375 } else { | 1175 } else { |
1376 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_W, SZ_D); | 1176 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_W, SZ_D); |
1377 } | 1177 } |
1378 } else { | 1178 } else { |
1379 if (opts->dregs[sec_reg] >= 0) { | 1179 if (opts->dregs[sec_reg] >= 0) { |
1380 dst = movsx_rr(dst, opts->dregs[sec_reg], SCRATCH1, SZ_W, SZ_D); | 1180 movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_W, SZ_D); |
1381 } else { | 1181 } else { |
1382 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_W, SZ_D); | 1182 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_W, SZ_D); |
1383 } | 1183 } |
1384 } | 1184 } |
1385 dst = add_rr(dst, SCRATCH1, SCRATCH2, SZ_D); | 1185 add_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_D); |
1386 } | 1186 } |
1387 if (inst->dst.params.regs.displacement) { | 1187 if (inst->dst.params.regs.displacement) { |
1388 dst = add_ir(dst, inst->dst.params.regs.displacement, SCRATCH2, SZ_D); | 1188 add_ir(code, inst->dst.params.regs.displacement, opts->gen.scratch2, SZ_D); |
1389 } | 1189 } |
1390 break; | 1190 break; |
1391 case MODE_ABSOLUTE: | 1191 case MODE_ABSOLUTE: |
1392 early_cycles += 4; | 1192 early_cycles += 4; |
1393 case MODE_ABSOLUTE_SHORT: | 1193 case MODE_ABSOLUTE_SHORT: |
1394 early_cycles += 4; | 1194 early_cycles += 4; |
1395 dst = mov_ir(dst, inst->dst.params.immed, SCRATCH2, SZ_D); | 1195 mov_ir(code, inst->dst.params.immed, opts->gen.scratch2, SZ_D); |
1396 break; | 1196 break; |
1397 default: | 1197 default: |
1398 m68k_disasm(inst, disasm_buf); | 1198 m68k_disasm(inst, disasm_buf); |
1399 printf("%X: %s\naddress mode %d not implemented (movem dst)\n", inst->address, disasm_buf, inst->dst.addr_mode); | 1199 printf("%X: %s\naddress mode %d not implemented (movem dst)\n", inst->address, disasm_buf, inst->dst.addr_mode); |
1400 exit(1); | 1200 exit(1); |
1404 dir = -1; | 1204 dir = -1; |
1405 } else { | 1205 } else { |
1406 reg = 0; | 1206 reg = 0; |
1407 dir = 1; | 1207 dir = 1; |
1408 } | 1208 } |
1409 dst = cycles(dst, early_cycles); | 1209 cycles(&opts->gen, early_cycles); |
1410 for(bit=0; reg < 16 && reg >= 0; reg += dir, bit++) { | 1210 for(bit=0; reg < 16 && reg >= 0; reg += dir, bit++) { |
1411 if (inst->src.params.immed & (1 << bit)) { | 1211 if (inst->src.params.immed & (1 << bit)) { |
1412 if (inst->dst.addr_mode == MODE_AREG_PREDEC) { | 1212 if (inst->dst.addr_mode == MODE_AREG_PREDEC) { |
1413 dst = sub_ir(dst, (inst->extra.size == OPSIZE_LONG) ? 4 : 2, SCRATCH2, SZ_D); | 1213 sub_ir(code, (inst->extra.size == OPSIZE_LONG) ? 4 : 2, opts->gen.scratch2, SZ_D); |
1414 } | 1214 } |
1415 dst = push_r(dst, SCRATCH2); | 1215 push_r(code, opts->gen.scratch2); |
1416 if (reg > 7) { | 1216 if (reg > 7) { |
1417 if (opts->aregs[reg-8] >= 0) { | 1217 if (opts->aregs[reg-8] >= 0) { |
1418 dst = mov_rr(dst, opts->aregs[reg-8], SCRATCH1, inst->extra.size); | 1218 mov_rr(code, opts->aregs[reg-8], opts->gen.scratch1, inst->extra.size); |
1419 } else { | 1219 } else { |
1420 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * (reg-8), SCRATCH1, inst->extra.size); | 1220 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * (reg-8), opts->gen.scratch1, inst->extra.size); |
1421 } | 1221 } |
1422 } else { | 1222 } else { |
1423 if (opts->dregs[reg] >= 0) { | 1223 if (opts->dregs[reg] >= 0) { |
1424 dst = mov_rr(dst, opts->dregs[reg], SCRATCH1, inst->extra.size); | 1224 mov_rr(code, opts->dregs[reg], opts->gen.scratch1, inst->extra.size); |
1425 } else { | 1225 } else { |
1426 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t) * (reg), SCRATCH1, inst->extra.size); | 1226 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t) * (reg), opts->gen.scratch1, inst->extra.size); |
1427 } | 1227 } |
1428 } | 1228 } |
1429 if (inst->extra.size == OPSIZE_LONG) { | 1229 if (inst->extra.size == OPSIZE_LONG) { |
1430 dst = call(dst, opts->write_32_lowfirst); | 1230 call(code, opts->write_32_lowfirst); |
1431 } else { | 1231 } else { |
1432 dst = call(dst, opts->write_16); | 1232 call(code, opts->write_16); |
1433 } | 1233 } |
1434 dst = pop_r(dst, SCRATCH2); | 1234 pop_r(code, opts->gen.scratch2); |
1435 if (inst->dst.addr_mode != MODE_AREG_PREDEC) { | 1235 if (inst->dst.addr_mode != MODE_AREG_PREDEC) { |
1436 dst = add_ir(dst, (inst->extra.size == OPSIZE_LONG) ? 4 : 2, SCRATCH2, SZ_D); | 1236 add_ir(code, (inst->extra.size == OPSIZE_LONG) ? 4 : 2, opts->gen.scratch2, SZ_D); |
1437 } | 1237 } |
1438 } | 1238 } |
1439 } | 1239 } |
1440 if (inst->dst.addr_mode == MODE_AREG_PREDEC) { | 1240 if (inst->dst.addr_mode == MODE_AREG_PREDEC) { |
1441 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | 1241 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { |
1442 dst = mov_rr(dst, SCRATCH2, opts->aregs[inst->dst.params.regs.pri], SZ_D); | 1242 mov_rr(code, opts->gen.scratch2, opts->aregs[inst->dst.params.regs.pri], SZ_D); |
1443 } else { | 1243 } else { |
1444 dst = mov_rrdisp8(dst, SCRATCH2, CONTEXT, reg_offset(&(inst->dst)), SZ_D); | 1244 mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, reg_offset(&(inst->dst)), SZ_D); |
1445 } | 1245 } |
1446 } | 1246 } |
1447 } else { | 1247 } else { |
1448 //mem to reg | 1248 //mem to reg |
1449 early_cycles = 4; | 1249 early_cycles = 4; |
1450 switch (inst->src.addr_mode) | 1250 switch (inst->src.addr_mode) |
1451 { | 1251 { |
1452 case MODE_AREG_INDIRECT: | 1252 case MODE_AREG_INDIRECT: |
1453 case MODE_AREG_POSTINC: | 1253 case MODE_AREG_POSTINC: |
1454 if (opts->aregs[inst->src.params.regs.pri] >= 0) { | 1254 if (opts->aregs[inst->src.params.regs.pri] >= 0) { |
1455 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); | 1255 mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); |
1456 } else { | 1256 } else { |
1457 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, SZ_D); | 1257 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_D); |
1458 } | 1258 } |
1459 break; | 1259 break; |
1460 case MODE_AREG_DISPLACE: | 1260 case MODE_AREG_DISPLACE: |
1461 early_cycles += BUS; | 1261 early_cycles += BUS; |
1462 reg = SCRATCH2; | 1262 reg = opts->gen.scratch2; |
1463 if (opts->aregs[inst->src.params.regs.pri] >= 0) { | 1263 if (opts->aregs[inst->src.params.regs.pri] >= 0) { |
1464 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); | 1264 mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); |
1465 } else { | 1265 } else { |
1466 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, SZ_D); | 1266 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_D); |
1467 } | 1267 } |
1468 dst = add_ir(dst, inst->src.params.regs.displacement, SCRATCH1, SZ_D); | 1268 add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); |
1469 break; | 1269 break; |
1470 case MODE_AREG_INDEX_DISP8: | 1270 case MODE_AREG_INDEX_DISP8: |
1471 early_cycles += 6; | 1271 early_cycles += 6; |
1472 if (opts->aregs[inst->src.params.regs.pri] >= 0) { | 1272 if (opts->aregs[inst->src.params.regs.pri] >= 0) { |
1473 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); | 1273 mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); |
1474 } else { | 1274 } else { |
1475 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, SZ_D); | 1275 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_D); |
1476 } | 1276 } |
1477 sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; | 1277 sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; |
1478 if (inst->src.params.regs.sec & 1) { | 1278 if (inst->src.params.regs.sec & 1) { |
1479 if (inst->src.params.regs.sec & 0x10) { | 1279 if (inst->src.params.regs.sec & 0x10) { |
1480 if (opts->aregs[sec_reg] >= 0) { | 1280 if (opts->aregs[sec_reg] >= 0) { |
1481 dst = add_rr(dst, opts->aregs[sec_reg], SCRATCH1, SZ_D); | 1281 add_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_D); |
1482 } else { | 1282 } else { |
1483 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D); | 1283 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); |
1484 } | 1284 } |
1485 } else { | 1285 } else { |
1486 if (opts->dregs[sec_reg] >= 0) { | 1286 if (opts->dregs[sec_reg] >= 0) { |
1487 dst = add_rr(dst, opts->dregs[sec_reg], SCRATCH1, SZ_D); | 1287 add_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_D); |
1488 } else { | 1288 } else { |
1489 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D); | 1289 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); |
1490 } | 1290 } |
1491 } | 1291 } |
1492 } else { | 1292 } else { |
1493 if (inst->src.params.regs.sec & 0x10) { | 1293 if (inst->src.params.regs.sec & 0x10) { |
1494 if (opts->aregs[sec_reg] >= 0) { | 1294 if (opts->aregs[sec_reg] >= 0) { |
1495 dst = movsx_rr(dst, opts->aregs[sec_reg], SCRATCH2, SZ_W, SZ_D); | 1295 movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); |
1496 } else { | 1296 } else { |
1497 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D); | 1297 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); |
1498 } | 1298 } |
1499 } else { | 1299 } else { |
1500 if (opts->dregs[sec_reg] >= 0) { | 1300 if (opts->dregs[sec_reg] >= 0) { |
1501 dst = movsx_rr(dst, opts->dregs[sec_reg], SCRATCH2, SZ_W, SZ_D); | 1301 movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); |
1502 } else { | 1302 } else { |
1503 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D); | 1303 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); |
1504 } | 1304 } |
1505 } | 1305 } |
1506 dst = add_rr(dst, SCRATCH2, SCRATCH1, SZ_D); | 1306 add_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D); |
1507 } | 1307 } |
1508 if (inst->src.params.regs.displacement) { | 1308 if (inst->src.params.regs.displacement) { |
1509 dst = add_ir(dst, inst->src.params.regs.displacement, SCRATCH1, SZ_D); | 1309 add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); |
1510 } | 1310 } |
1511 break; | 1311 break; |
1512 case MODE_PC_DISPLACE: | 1312 case MODE_PC_DISPLACE: |
1513 early_cycles += BUS; | 1313 early_cycles += BUS; |
1514 dst = mov_ir(dst, inst->src.params.regs.displacement + inst->address+2, SCRATCH1, SZ_D); | 1314 mov_ir(code, inst->src.params.regs.displacement + inst->address+2, opts->gen.scratch1, SZ_D); |
1515 break; | 1315 break; |
1516 case MODE_PC_INDEX_DISP8: | 1316 case MODE_PC_INDEX_DISP8: |
1517 early_cycles += 6; | 1317 early_cycles += 6; |
1518 dst = mov_ir(dst, inst->address+2, SCRATCH1, SZ_D); | 1318 mov_ir(code, inst->address+2, opts->gen.scratch1, SZ_D); |
1519 sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; | 1319 sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; |
1520 if (inst->src.params.regs.sec & 1) { | 1320 if (inst->src.params.regs.sec & 1) { |
1521 if (inst->src.params.regs.sec & 0x10) { | 1321 if (inst->src.params.regs.sec & 0x10) { |
1522 if (opts->aregs[sec_reg] >= 0) { | 1322 if (opts->aregs[sec_reg] >= 0) { |
1523 dst = add_rr(dst, opts->aregs[sec_reg], SCRATCH1, SZ_D); | 1323 add_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_D); |
1524 } else { | 1324 } else { |
1525 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D); | 1325 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); |
1526 } | 1326 } |
1527 } else { | 1327 } else { |
1528 if (opts->dregs[sec_reg] >= 0) { | 1328 if (opts->dregs[sec_reg] >= 0) { |
1529 dst = add_rr(dst, opts->dregs[sec_reg], SCRATCH1, SZ_D); | 1329 add_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_D); |
1530 } else { | 1330 } else { |
1531 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D); | 1331 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); |
1532 } | 1332 } |
1533 } | 1333 } |
1534 } else { | 1334 } else { |
1535 if (inst->src.params.regs.sec & 0x10) { | 1335 if (inst->src.params.regs.sec & 0x10) { |
1536 if (opts->aregs[sec_reg] >= 0) { | 1336 if (opts->aregs[sec_reg] >= 0) { |
1537 dst = movsx_rr(dst, opts->aregs[sec_reg], SCRATCH2, SZ_W, SZ_D); | 1337 movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); |
1538 } else { | 1338 } else { |
1539 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D); | 1339 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); |
1540 } | 1340 } |
1541 } else { | 1341 } else { |
1542 if (opts->dregs[sec_reg] >= 0) { | 1342 if (opts->dregs[sec_reg] >= 0) { |
1543 dst = movsx_rr(dst, opts->dregs[sec_reg], SCRATCH2, SZ_W, SZ_D); | 1343 movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); |
1544 } else { | 1344 } else { |
1545 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D); | 1345 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); |
1546 } | 1346 } |
1547 } | 1347 } |
1548 dst = add_rr(dst, SCRATCH2, SCRATCH1, SZ_D); | 1348 add_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D); |
1549 } | 1349 } |
1550 if (inst->src.params.regs.displacement) { | 1350 if (inst->src.params.regs.displacement) { |
1551 dst = add_ir(dst, inst->src.params.regs.displacement, SCRATCH1, SZ_D); | 1351 add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); |
1552 } | 1352 } |
1553 break; | 1353 break; |
1554 case MODE_ABSOLUTE: | 1354 case MODE_ABSOLUTE: |
1555 early_cycles += 4; | 1355 early_cycles += 4; |
1556 case MODE_ABSOLUTE_SHORT: | 1356 case MODE_ABSOLUTE_SHORT: |
1557 early_cycles += 4; | 1357 early_cycles += 4; |
1558 dst = mov_ir(dst, inst->src.params.immed, SCRATCH1, SZ_D); | 1358 mov_ir(code, inst->src.params.immed, opts->gen.scratch1, SZ_D); |
1559 break; | 1359 break; |
1560 default: | 1360 default: |
1561 m68k_disasm(inst, disasm_buf); | 1361 m68k_disasm(inst, disasm_buf); |
1562 printf("%X: %s\naddress mode %d not implemented (movem src)\n", inst->address, disasm_buf, inst->src.addr_mode); | 1362 printf("%X: %s\naddress mode %d not implemented (movem src)\n", inst->address, disasm_buf, inst->src.addr_mode); |
1563 exit(1); | 1363 exit(1); |
1564 } | 1364 } |
1565 dst = cycles(dst, early_cycles); | 1365 cycles(&opts->gen, early_cycles); |
1566 for(reg = 0; reg < 16; reg ++) { | 1366 for(reg = 0; reg < 16; reg ++) { |
1567 if (inst->dst.params.immed & (1 << reg)) { | 1367 if (inst->dst.params.immed & (1 << reg)) { |
1568 dst = push_r(dst, SCRATCH1); | 1368 push_r(code, opts->gen.scratch1); |
1569 if (inst->extra.size == OPSIZE_LONG) { | 1369 if (inst->extra.size == OPSIZE_LONG) { |
1570 dst = call(dst, opts->read_32); | 1370 call(code, opts->read_32); |
1571 } else { | 1371 } else { |
1572 dst = call(dst, opts->read_16); | 1372 call(code, opts->read_16); |
1573 } | 1373 } |
1574 if (inst->extra.size == OPSIZE_WORD) { | 1374 if (inst->extra.size == OPSIZE_WORD) { |
1575 dst = movsx_rr(dst, SCRATCH1, SCRATCH1, SZ_W, SZ_D); | 1375 movsx_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_W, SZ_D); |
1576 } | 1376 } |
1577 if (reg > 7) { | 1377 if (reg > 7) { |
1578 if (opts->aregs[reg-8] >= 0) { | 1378 if (opts->aregs[reg-8] >= 0) { |
1579 dst = mov_rr(dst, SCRATCH1, opts->aregs[reg-8], SZ_D); | 1379 mov_rr(code, opts->gen.scratch1, opts->aregs[reg-8], SZ_D); |
1580 } else { | 1380 } else { |
1581 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * (reg-8), SZ_D); | 1381 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * (reg-8), SZ_D); |
1582 } | 1382 } |
1583 } else { | 1383 } else { |
1584 if (opts->dregs[reg] >= 0) { | 1384 if (opts->dregs[reg] >= 0) { |
1585 dst = mov_rr(dst, SCRATCH1, opts->dregs[reg], SZ_D); | 1385 mov_rr(code, opts->gen.scratch1, opts->dregs[reg], SZ_D); |
1586 } else { | 1386 } else { |
1587 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t) * (reg), SZ_D); | 1387 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t) * (reg), SZ_D); |
1588 } | 1388 } |
1589 } | 1389 } |
1590 dst = pop_r(dst, SCRATCH1); | 1390 pop_r(code, opts->gen.scratch1); |
1591 dst = add_ir(dst, (inst->extra.size == OPSIZE_LONG) ? 4 : 2, SCRATCH1, SZ_D); | 1391 add_ir(code, (inst->extra.size == OPSIZE_LONG) ? 4 : 2, opts->gen.scratch1, SZ_D); |
1592 } | 1392 } |
1593 } | 1393 } |
1594 if (inst->src.addr_mode == MODE_AREG_POSTINC) { | 1394 if (inst->src.addr_mode == MODE_AREG_POSTINC) { |
1595 if (opts->aregs[inst->src.params.regs.pri] >= 0) { | 1395 if (opts->aregs[inst->src.params.regs.pri] >= 0) { |
1596 dst = mov_rr(dst, SCRATCH1, opts->aregs[inst->src.params.regs.pri], SZ_D); | 1396 mov_rr(code, opts->gen.scratch1, opts->aregs[inst->src.params.regs.pri], SZ_D); |
1597 } else { | 1397 } else { |
1598 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, reg_offset(&(inst->src)), SZ_D); | 1398 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, reg_offset(&(inst->src)), SZ_D); |
1599 } | 1399 } |
1600 } | 1400 } |
1601 } | 1401 } |
1602 //prefetch | 1402 //prefetch |
1603 dst = cycles(dst, 4); | 1403 cycles(&opts->gen, 4); |
1604 return dst; | 1404 } |
1605 } | 1405 |
1606 | 1406 void translate_m68k_clr(x86_68k_options * opts, m68kinst * inst) |
1607 code_ptr translate_m68k_clr(code_ptr dst, m68kinst * inst, x86_68k_options * opts) | 1407 { |
1608 { | 1408 code_info *code = &opts->gen.code; |
1609 dst = set_flag(dst, 0, FLAG_N, opts); | 1409 set_flag(opts, 0, FLAG_N); |
1610 dst = set_flag(dst, 0, FLAG_V, opts); | 1410 set_flag(opts, 0, FLAG_V); |
1611 dst = set_flag(dst, 0, FLAG_C, opts); | 1411 set_flag(opts, 0, FLAG_C); |
1612 dst = set_flag(dst, 1, FLAG_Z, opts); | 1412 set_flag(opts, 1, FLAG_Z); |
1613 int8_t reg = native_reg(&(inst->dst), opts); | 1413 int8_t reg = native_reg(&(inst->dst), opts); |
1614 if (reg >= 0) { | 1414 if (reg >= 0) { |
1615 dst = cycles(dst, (inst->extra.size == OPSIZE_LONG ? 6 : 4)); | 1415 cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG ? 6 : 4)); |
1616 return xor_rr(dst, reg, reg, inst->extra.size); | 1416 xor_rr(code, reg, reg, inst->extra.size); |
1417 return; | |
1617 } | 1418 } |
1618 x86_ea dst_op; | 1419 x86_ea dst_op; |
1619 dst = translate_m68k_dst(inst, &dst_op, dst, opts, 1); | 1420 translate_m68k_dst(inst, &dst_op, opts, 1); |
1620 if (dst_op.mode == MODE_REG_DIRECT) { | 1421 if (dst_op.mode == MODE_REG_DIRECT) { |
1621 dst = xor_rr(dst, dst_op.base, dst_op.base, inst->extra.size); | 1422 xor_rr(code, dst_op.base, dst_op.base, inst->extra.size); |
1622 } else { | 1423 } else { |
1623 dst = mov_irdisp8(dst, 0, dst_op.base, dst_op.disp, inst->extra.size); | 1424 mov_irdisp(code, 0, dst_op.base, dst_op.disp, inst->extra.size); |
1624 } | 1425 } |
1625 dst = m68k_save_result(inst, dst, opts); | 1426 m68k_save_result(inst, opts); |
1626 return dst; | 1427 } |
1627 } | 1428 |
1628 | 1429 void translate_m68k_ext(x86_68k_options * opts, m68kinst * inst) |
1629 code_ptr translate_m68k_ext(code_ptr dst, m68kinst * inst, x86_68k_options * opts) | 1430 { |
1630 { | 1431 code_info *code = &opts->gen.code; |
1631 x86_ea dst_op; | 1432 x86_ea dst_op; |
1632 uint8_t dst_size = inst->extra.size; | 1433 uint8_t dst_size = inst->extra.size; |
1633 inst->extra.size--; | 1434 inst->extra.size--; |
1634 dst = translate_m68k_dst(inst, &dst_op, dst, opts, 0); | 1435 translate_m68k_dst(inst, &dst_op, opts, 0); |
1635 if (dst_op.mode == MODE_REG_DIRECT) { | 1436 if (dst_op.mode == MODE_REG_DIRECT) { |
1636 dst = movsx_rr(dst, dst_op.base, dst_op.base, inst->extra.size, dst_size); | 1437 movsx_rr(code, dst_op.base, dst_op.base, inst->extra.size, dst_size); |
1637 dst = cmp_ir(dst, 0, dst_op.base, dst_size); | 1438 cmp_ir(code, 0, dst_op.base, dst_size); |
1638 } else { | 1439 } else { |
1639 dst = movsx_rdisp8r(dst, dst_op.base, dst_op.disp, SCRATCH1, inst->extra.size, dst_size); | 1440 movsx_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, inst->extra.size, dst_size); |
1640 dst = cmp_ir(dst, 0, SCRATCH1, dst_size); | 1441 cmp_ir(code, 0, opts->gen.scratch1, dst_size); |
1641 dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, dst_size); | 1442 mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, dst_size); |
1642 } | 1443 } |
1643 inst->extra.size = dst_size; | 1444 inst->extra.size = dst_size; |
1644 dst = set_flag(dst, 0, FLAG_V, opts); | 1445 set_flag(opts, 0, FLAG_V); |
1645 dst = set_flag(dst, 0, FLAG_C, opts); | 1446 set_flag(opts, 0, FLAG_C); |
1646 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 1447 set_flag_cond(opts, CC_Z, FLAG_Z); |
1647 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 1448 set_flag_cond(opts, CC_S, FLAG_N); |
1648 //M68K EXT only operates on registers so no need for a call to save result here | 1449 //M68K EXT only operates on registers so no need for a call to save result here |
1649 return dst; | 1450 } |
1650 } | 1451 |
1651 | 1452 void translate_m68k_lea(x86_68k_options * opts, m68kinst * inst) |
1652 code_ptr translate_m68k_lea(code_ptr dst, m68kinst * inst, x86_68k_options * opts) | 1453 { |
1653 { | 1454 code_info *code = &opts->gen.code; |
1654 int8_t dst_reg = native_reg(&(inst->dst), opts), sec_reg; | 1455 int8_t dst_reg = native_reg(&(inst->dst), opts), sec_reg; |
1655 switch(inst->src.addr_mode) | 1456 switch(inst->src.addr_mode) |
1656 { | 1457 { |
1657 case MODE_AREG_INDIRECT: | 1458 case MODE_AREG_INDIRECT: |
1658 dst = cycles(dst, BUS); | 1459 cycles(&opts->gen, BUS); |
1659 if (opts->aregs[inst->src.params.regs.pri] >= 0) { | 1460 if (opts->aregs[inst->src.params.regs.pri] >= 0) { |
1660 if (dst_reg >= 0) { | 1461 if (dst_reg >= 0) { |
1661 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], dst_reg, SZ_D); | 1462 mov_rr(code, opts->aregs[inst->src.params.regs.pri], dst_reg, SZ_D); |
1662 } else { | 1463 } else { |
1663 dst = mov_rrdisp8(dst, opts->aregs[inst->src.params.regs.pri], CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->dst.params.regs.pri, SZ_D); | 1464 mov_rrdisp(code, opts->aregs[inst->src.params.regs.pri], opts->gen.context_reg, offsetof(m68k_context, aregs) + 4 * inst->dst.params.regs.pri, SZ_D); |
1664 } | 1465 } |
1665 } else { | 1466 } else { |
1666 if (dst_reg >= 0) { | 1467 if (dst_reg >= 0) { |
1667 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, dst_reg, SZ_D); | 1468 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, dst_reg, SZ_D); |
1668 } else { | 1469 } else { |
1669 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, SCRATCH1, SZ_D); | 1470 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, opts->gen.scratch1, SZ_D); |
1670 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->dst.params.regs.pri, SZ_D); | 1471 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, aregs) + 4 * inst->dst.params.regs.pri, SZ_D); |
1671 } | 1472 } |
1672 } | 1473 } |
1673 break; | 1474 break; |
1674 case MODE_AREG_DISPLACE: | 1475 case MODE_AREG_DISPLACE: |
1675 dst = cycles(dst, 8); | 1476 cycles(&opts->gen, 8); |
1676 if (dst_reg >= 0) { | 1477 if (dst_reg >= 0) { |
1677 if (inst->src.params.regs.pri != inst->dst.params.regs.pri) { | 1478 if (inst->src.params.regs.pri != inst->dst.params.regs.pri) { |
1678 if (opts->aregs[inst->src.params.regs.pri] >= 0) { | 1479 if (opts->aregs[inst->src.params.regs.pri] >= 0) { |
1679 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], dst_reg, SZ_D); | 1480 mov_rr(code, opts->aregs[inst->src.params.regs.pri], dst_reg, SZ_D); |
1680 } else { | 1481 } else { |
1681 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src)), dst_reg, SZ_D); | 1482 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), dst_reg, SZ_D); |
1682 } | 1483 } |
1683 } | 1484 } |
1684 dst = add_ir(dst, inst->src.params.regs.displacement, dst_reg, SZ_D); | 1485 add_ir(code, inst->src.params.regs.displacement, dst_reg, SZ_D); |
1685 } else { | 1486 } else { |
1686 if (inst->src.params.regs.pri != inst->dst.params.regs.pri) { | 1487 if (inst->src.params.regs.pri != inst->dst.params.regs.pri) { |
1687 if (opts->aregs[inst->src.params.regs.pri] >= 0) { | 1488 if (opts->aregs[inst->src.params.regs.pri] >= 0) { |
1688 dst = mov_rrdisp8(dst, opts->aregs[inst->src.params.regs.pri], CONTEXT, reg_offset(&(inst->dst)), SZ_D); | 1489 mov_rrdisp(code, opts->aregs[inst->src.params.regs.pri], opts->gen.context_reg, reg_offset(&(inst->dst)), SZ_D); |
1689 } else { | 1490 } else { |
1690 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, SZ_D); | 1491 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_D); |
1691 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, reg_offset(&(inst->dst)), SZ_D); | 1492 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, reg_offset(&(inst->dst)), SZ_D); |
1692 } | 1493 } |
1693 } | 1494 } |
1694 dst = add_irdisp8(dst, inst->src.params.regs.displacement, CONTEXT, reg_offset(&(inst->dst)), SZ_D); | 1495 add_irdisp(code, inst->src.params.regs.displacement, opts->gen.context_reg, reg_offset(&(inst->dst)), SZ_D); |
1695 } | 1496 } |
1696 break; | 1497 break; |
1697 case MODE_AREG_INDEX_DISP8: | 1498 case MODE_AREG_INDEX_DISP8: |
1698 dst = cycles(dst, 12); | 1499 cycles(&opts->gen, 12); |
1699 if (opts->aregs[inst->src.params.regs.pri] >= 0) { | 1500 if (opts->aregs[inst->src.params.regs.pri] >= 0) { |
1700 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH2, SZ_D); | 1501 mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch2, SZ_D); |
1701 } else { | 1502 } else { |
1702 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src)), SCRATCH2, SZ_D); | 1503 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch2, SZ_D); |
1703 } | 1504 } |
1704 sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; | 1505 sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; |
1705 if (inst->src.params.regs.sec & 1) { | 1506 if (inst->src.params.regs.sec & 1) { |
1706 if (inst->src.params.regs.sec & 0x10) { | 1507 if (inst->src.params.regs.sec & 0x10) { |
1707 if (opts->aregs[sec_reg] >= 0) { | 1508 if (opts->aregs[sec_reg] >= 0) { |
1708 dst = add_rr(dst, opts->aregs[sec_reg], SCRATCH2, SZ_D); | 1509 add_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_D); |
1709 } else { | 1510 } else { |
1710 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_D); | 1511 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_D); |
1711 } | 1512 } |
1712 } else { | 1513 } else { |
1713 if (opts->dregs[sec_reg] >= 0) { | 1514 if (opts->dregs[sec_reg] >= 0) { |
1714 dst = add_rr(dst, opts->dregs[sec_reg], SCRATCH2, SZ_D); | 1515 add_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_D); |
1715 } else { | 1516 } else { |
1716 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_D); | 1517 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_D); |
1717 } | 1518 } |
1718 } | 1519 } |
1719 } else { | 1520 } else { |
1720 if (inst->src.params.regs.sec & 0x10) { | 1521 if (inst->src.params.regs.sec & 0x10) { |
1721 if (opts->aregs[sec_reg] >= 0) { | 1522 if (opts->aregs[sec_reg] >= 0) { |
1722 dst = movsx_rr(dst, opts->aregs[sec_reg], SCRATCH1, SZ_W, SZ_D); | 1523 movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_W, SZ_D); |
1723 } else { | 1524 } else { |
1724 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_W, SZ_D); | 1525 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_W, SZ_D); |
1725 } | 1526 } |
1726 } else { | 1527 } else { |
1727 if (opts->dregs[sec_reg] >= 0) { | 1528 if (opts->dregs[sec_reg] >= 0) { |
1728 dst = movsx_rr(dst, opts->dregs[sec_reg], SCRATCH1, SZ_W, SZ_D); | 1529 movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_W, SZ_D); |
1729 } else { | 1530 } else { |
1730 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_W, SZ_D); | 1531 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_W, SZ_D); |
1731 } | 1532 } |
1732 } | 1533 } |
1733 dst = add_rr(dst, SCRATCH1, SCRATCH2, SZ_D); | 1534 add_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_D); |
1734 } | 1535 } |
1735 if (inst->src.params.regs.displacement) { | 1536 if (inst->src.params.regs.displacement) { |
1736 dst = add_ir(dst, inst->src.params.regs.displacement, SCRATCH2, SZ_D); | 1537 add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch2, SZ_D); |
1737 } | 1538 } |
1738 if (dst_reg >= 0) { | 1539 if (dst_reg >= 0) { |
1739 dst = mov_rr(dst, SCRATCH2, dst_reg, SZ_D); | 1540 mov_rr(code, opts->gen.scratch2, dst_reg, SZ_D); |
1740 } else { | 1541 } else { |
1741 dst = mov_rrdisp8(dst, SCRATCH2, CONTEXT, reg_offset(&(inst->dst)), SZ_D); | 1542 mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, reg_offset(&(inst->dst)), SZ_D); |
1742 } | 1543 } |
1743 break; | 1544 break; |
1744 case MODE_PC_DISPLACE: | 1545 case MODE_PC_DISPLACE: |
1745 dst = cycles(dst, 8); | 1546 cycles(&opts->gen, 8); |
1746 if (dst_reg >= 0) { | 1547 if (dst_reg >= 0) { |
1747 dst = mov_ir(dst, inst->src.params.regs.displacement + inst->address+2, dst_reg, SZ_D); | 1548 mov_ir(code, inst->src.params.regs.displacement + inst->address+2, dst_reg, SZ_D); |
1748 } else { | 1549 } else { |
1749 dst = mov_irdisp8(dst, inst->src.params.regs.displacement + inst->address+2, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->dst.params.regs.pri, SZ_D); | 1550 mov_irdisp(code, inst->src.params.regs.displacement + inst->address+2, opts->gen.context_reg, offsetof(m68k_context, aregs) + 4 * inst->dst.params.regs.pri, SZ_D); |
1750 } | 1551 } |
1751 break; | 1552 break; |
1752 case MODE_PC_INDEX_DISP8: | 1553 case MODE_PC_INDEX_DISP8: |
1753 dst = cycles(dst, BUS*3); | 1554 cycles(&opts->gen, BUS*3); |
1754 dst = mov_ir(dst, inst->address+2, SCRATCH1, SZ_D); | 1555 mov_ir(code, inst->address+2, opts->gen.scratch1, SZ_D); |
1755 sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; | 1556 sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; |
1756 if (inst->src.params.regs.sec & 1) { | 1557 if (inst->src.params.regs.sec & 1) { |
1757 if (inst->src.params.regs.sec & 0x10) { | 1558 if (inst->src.params.regs.sec & 0x10) { |
1758 if (opts->aregs[sec_reg] >= 0) { | 1559 if (opts->aregs[sec_reg] >= 0) { |
1759 dst = add_rr(dst, opts->aregs[sec_reg], SCRATCH1, SZ_D); | 1560 add_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_D); |
1760 } else { | 1561 } else { |
1761 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D); | 1562 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); |
1762 } | 1563 } |
1763 } else { | 1564 } else { |
1764 if (opts->dregs[sec_reg] >= 0) { | 1565 if (opts->dregs[sec_reg] >= 0) { |
1765 dst = add_rr(dst, opts->dregs[sec_reg], SCRATCH1, SZ_D); | 1566 add_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_D); |
1766 } else { | 1567 } else { |
1767 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D); | 1568 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); |
1768 } | 1569 } |
1769 } | 1570 } |
1770 } else { | 1571 } else { |
1771 if (inst->src.params.regs.sec & 0x10) { | 1572 if (inst->src.params.regs.sec & 0x10) { |
1772 if (opts->aregs[sec_reg] >= 0) { | 1573 if (opts->aregs[sec_reg] >= 0) { |
1773 dst = movsx_rr(dst, opts->aregs[sec_reg], SCRATCH2, SZ_W, SZ_D); | 1574 movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); |
1774 } else { | 1575 } else { |
1775 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D); | 1576 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); |
1776 } | 1577 } |
1777 } else { | 1578 } else { |
1778 if (opts->dregs[sec_reg] >= 0) { | 1579 if (opts->dregs[sec_reg] >= 0) { |
1779 dst = movsx_rr(dst, opts->dregs[sec_reg], SCRATCH2, SZ_W, SZ_D); | 1580 movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); |
1780 } else { | 1581 } else { |
1781 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D); | 1582 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); |
1782 } | 1583 } |
1783 } | 1584 } |
1784 dst = add_rr(dst, SCRATCH2, SCRATCH1, SZ_D); | 1585 add_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D); |
1785 } | 1586 } |
1786 if (inst->src.params.regs.displacement) { | 1587 if (inst->src.params.regs.displacement) { |
1787 dst = add_ir(dst, inst->src.params.regs.displacement, SCRATCH1, SZ_D); | 1588 add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); |
1788 } | 1589 } |
1789 if (dst_reg >= 0) { | 1590 if (dst_reg >= 0) { |
1790 dst = mov_rr(dst, SCRATCH1, dst_reg, SZ_D); | 1591 mov_rr(code, opts->gen.scratch1, dst_reg, SZ_D); |
1791 } else { | 1592 } else { |
1792 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, reg_offset(&(inst->dst)), SZ_D); | 1593 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, reg_offset(&(inst->dst)), SZ_D); |
1793 } | 1594 } |
1794 break; | 1595 break; |
1795 case MODE_ABSOLUTE: | 1596 case MODE_ABSOLUTE: |
1796 case MODE_ABSOLUTE_SHORT: | 1597 case MODE_ABSOLUTE_SHORT: |
1797 dst = cycles(dst, (inst->src.addr_mode == MODE_ABSOLUTE) ? BUS * 3 : BUS * 2); | 1598 cycles(&opts->gen, (inst->src.addr_mode == MODE_ABSOLUTE) ? BUS * 3 : BUS * 2); |
1798 if (dst_reg >= 0) { | 1599 if (dst_reg >= 0) { |
1799 dst = mov_ir(dst, inst->src.params.immed, dst_reg, SZ_D); | 1600 mov_ir(code, inst->src.params.immed, dst_reg, SZ_D); |
1800 } else { | 1601 } else { |
1801 dst = mov_irdisp8(dst, inst->src.params.immed, CONTEXT, reg_offset(&(inst->dst)), SZ_D); | 1602 mov_irdisp(code, inst->src.params.immed, opts->gen.context_reg, reg_offset(&(inst->dst)), SZ_D); |
1802 } | 1603 } |
1803 break; | 1604 break; |
1804 default: | 1605 default: |
1805 m68k_disasm(inst, disasm_buf); | 1606 m68k_disasm(inst, disasm_buf); |
1806 printf("%X: %s\naddress mode %d not implemented (lea src)\n", inst->address, disasm_buf, inst->src.addr_mode); | 1607 printf("%X: %s\naddress mode %d not implemented (lea src)\n", inst->address, disasm_buf, inst->src.addr_mode); |
1807 exit(1); | 1608 exit(1); |
1808 } | 1609 } |
1809 return dst; | 1610 } |
1810 } | 1611 |
1811 | 1612 void translate_m68k_pea(x86_68k_options * opts, m68kinst * inst) |
1812 code_ptr translate_m68k_pea(code_ptr dst, m68kinst * inst, x86_68k_options * opts) | 1613 { |
1813 { | 1614 code_info *code = &opts->gen.code; |
1814 uint8_t sec_reg; | 1615 uint8_t sec_reg; |
1815 switch(inst->src.addr_mode) | 1616 switch(inst->src.addr_mode) |
1816 { | 1617 { |
1817 case MODE_AREG_INDIRECT: | 1618 case MODE_AREG_INDIRECT: |
1818 dst = cycles(dst, BUS); | 1619 cycles(&opts->gen, BUS); |
1819 if (opts->aregs[inst->src.params.regs.pri] >= 0) { | 1620 if (opts->aregs[inst->src.params.regs.pri] >= 0) { |
1820 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); | 1621 mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); |
1821 } else { | 1622 } else { |
1822 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, SCRATCH1, SZ_D); | 1623 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, opts->gen.scratch1, SZ_D); |
1823 } | 1624 } |
1824 break; | 1625 break; |
1825 case MODE_AREG_DISPLACE: | 1626 case MODE_AREG_DISPLACE: |
1826 dst = cycles(dst, 8); | 1627 cycles(&opts->gen, 8); |
1827 if (opts->aregs[inst->src.params.regs.pri] >= 0) { | 1628 if (opts->aregs[inst->src.params.regs.pri] >= 0) { |
1828 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); | 1629 mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); |
1829 } else { | 1630 } else { |
1830 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, SZ_D); | 1631 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_D); |
1831 } | 1632 } |
1832 dst = add_ir(dst, inst->src.params.regs.displacement, SCRATCH1, SZ_D); | 1633 add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); |
1833 break; | 1634 break; |
1834 case MODE_AREG_INDEX_DISP8: | 1635 case MODE_AREG_INDEX_DISP8: |
1835 dst = cycles(dst, 6);//TODO: Check to make sure this is correct | 1636 cycles(&opts->gen, 6);//TODO: Check to make sure this is correct |
1836 if (opts->aregs[inst->src.params.regs.pri] >= 0) { | 1637 if (opts->aregs[inst->src.params.regs.pri] >= 0) { |
1837 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); | 1638 mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); |
1838 } else { | 1639 } else { |
1839 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, SZ_D); | 1640 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_D); |
1840 } | 1641 } |
1841 sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; | 1642 sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; |
1842 if (inst->src.params.regs.sec & 1) { | 1643 if (inst->src.params.regs.sec & 1) { |
1843 if (inst->src.params.regs.sec & 0x10) { | 1644 if (inst->src.params.regs.sec & 0x10) { |
1844 if (opts->aregs[sec_reg] >= 0) { | 1645 if (opts->aregs[sec_reg] >= 0) { |
1845 dst = add_rr(dst, opts->aregs[sec_reg], SCRATCH1, SZ_D); | 1646 add_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_D); |
1846 } else { | 1647 } else { |
1847 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D); | 1648 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); |
1848 } | 1649 } |
1849 } else { | 1650 } else { |
1850 if (opts->dregs[sec_reg] >= 0) { | 1651 if (opts->dregs[sec_reg] >= 0) { |
1851 dst = add_rr(dst, opts->dregs[sec_reg], SCRATCH1, SZ_D); | 1652 add_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_D); |
1852 } else { | 1653 } else { |
1853 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D); | 1654 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); |
1854 } | 1655 } |
1855 } | 1656 } |
1856 } else { | 1657 } else { |
1857 if (inst->src.params.regs.sec & 0x10) { | 1658 if (inst->src.params.regs.sec & 0x10) { |
1858 if (opts->aregs[sec_reg] >= 0) { | 1659 if (opts->aregs[sec_reg] >= 0) { |
1859 dst = movsx_rr(dst, opts->aregs[sec_reg], SCRATCH2, SZ_W, SZ_D); | 1660 movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); |
1860 } else { | 1661 } else { |
1861 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D); | 1662 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); |
1862 } | 1663 } |
1863 } else { | 1664 } else { |
1864 if (opts->dregs[sec_reg] >= 0) { | 1665 if (opts->dregs[sec_reg] >= 0) { |
1865 dst = movsx_rr(dst, opts->dregs[sec_reg], SCRATCH2, SZ_W, SZ_D); | 1666 movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); |
1866 } else { | 1667 } else { |
1867 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D); | 1668 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); |
1868 } | 1669 } |
1869 } | 1670 } |
1870 dst = add_rr(dst, SCRATCH2, SCRATCH1, SZ_D); | 1671 add_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D); |
1871 } | 1672 } |
1872 if (inst->src.params.regs.displacement) { | 1673 if (inst->src.params.regs.displacement) { |
1873 dst = add_ir(dst, inst->src.params.regs.displacement, SCRATCH1, SZ_D); | 1674 add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); |
1874 } | 1675 } |
1875 break; | 1676 break; |
1876 case MODE_PC_DISPLACE: | 1677 case MODE_PC_DISPLACE: |
1877 dst = cycles(dst, 8); | 1678 cycles(&opts->gen, 8); |
1878 dst = mov_ir(dst, inst->src.params.regs.displacement + inst->address+2, SCRATCH1, SZ_D); | 1679 mov_ir(code, inst->src.params.regs.displacement + inst->address+2, opts->gen.scratch1, SZ_D); |
1879 break; | 1680 break; |
1880 case MODE_ABSOLUTE: | 1681 case MODE_ABSOLUTE: |
1881 case MODE_ABSOLUTE_SHORT: | 1682 case MODE_ABSOLUTE_SHORT: |
1882 dst = cycles(dst, (inst->src.addr_mode == MODE_ABSOLUTE) ? BUS * 3 : BUS * 2); | 1683 cycles(&opts->gen, (inst->src.addr_mode == MODE_ABSOLUTE) ? BUS * 3 : BUS * 2); |
1883 dst = mov_ir(dst, inst->src.params.immed, SCRATCH1, SZ_D); | 1684 mov_ir(code, inst->src.params.immed, opts->gen.scratch1, SZ_D); |
1884 break; | 1685 break; |
1885 default: | 1686 default: |
1886 m68k_disasm(inst, disasm_buf); | 1687 m68k_disasm(inst, disasm_buf); |
1887 printf("%X: %s\naddress mode %d not implemented (lea src)\n", inst->address, disasm_buf, inst->src.addr_mode); | 1688 printf("%X: %s\naddress mode %d not implemented (lea src)\n", inst->address, disasm_buf, inst->src.addr_mode); |
1888 exit(1); | 1689 exit(1); |
1889 } | 1690 } |
1890 dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); | 1691 sub_ir(code, 4, opts->aregs[7], SZ_D); |
1891 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); | 1692 mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); |
1892 dst = call(dst, opts->write_32_lowfirst); | 1693 call(code, opts->write_32_lowfirst); |
1893 return dst; | 1694 } |
1894 } | 1695 |
1895 | 1696 void translate_m68k_bsr(x86_68k_options * opts, m68kinst * inst) |
1896 code_ptr translate_m68k_bsr(code_ptr dst, m68kinst * inst, x86_68k_options * opts) | 1697 { |
1897 { | 1698 code_info *code = &opts->gen.code; |
1898 int32_t disp = inst->src.params.immed; | 1699 int32_t disp = inst->src.params.immed; |
1899 uint32_t after = inst->address + (inst->variant == VAR_BYTE ? 2 : 4); | 1700 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 | 1701 //TODO: Add cycles in the right place relative to pushing the return address on the stack |
1901 dst = cycles(dst, 10); | 1702 cycles(&opts->gen, 10); |
1902 dst = mov_ir(dst, after, SCRATCH1, SZ_D); | 1703 mov_ir(code, after, opts->gen.scratch1, SZ_D); |
1903 dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); | 1704 sub_ir(code, 4, opts->aregs[7], SZ_D); |
1904 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); | 1705 mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); |
1905 dst = call(dst, opts->write_32_highfirst); | 1706 call(code, opts->write_32_highfirst); |
1906 code_ptr dest_addr = get_native_address(opts->gen.native_code_map, (inst->address+2) + disp); | 1707 code_ptr dest_addr = get_native_address(opts->gen.native_code_map, (inst->address+2) + disp); |
1907 if (!dest_addr) { | 1708 if (!dest_addr) { |
1908 opts->gen.deferred = defer_address(opts->gen.deferred, (inst->address+2) + disp, dst + 1); | 1709 opts->gen.deferred = defer_address(opts->gen.deferred, (inst->address+2) + disp, code->cur + 1); |
1909 //dummy address to be replaced later | 1710 //dummy address to be replaced later |
1910 dest_addr = dst + 256; | 1711 dest_addr = code->cur + 256; |
1911 } | 1712 } |
1912 dst = jmp(dst, (char *)dest_addr); | 1713 jmp(code, dest_addr); |
1913 return dst; | 1714 } |
1914 } | 1715 |
1915 | 1716 uint8_t m68k_eval_cond(x86_68k_options * opts, uint8_t cc) |
1916 code_ptr translate_m68k_bcc(code_ptr dst, m68kinst * inst, x86_68k_options * opts) | 1717 { |
1917 { | 1718 uint8_t cond = CC_NZ; |
1918 dst = cycles(dst, 10);//TODO: Adjust this for branch not taken case | 1719 switch (cc) |
1720 { | |
1721 case COND_HIGH: | |
1722 cond = CC_Z; | |
1723 case COND_LOW_SAME: | |
1724 flag_to_reg(opts, FLAG_Z, opts->gen.scratch1); | |
1725 or_flag_to_reg(opts, FLAG_C, opts->gen.scratch1); | |
1726 break; | |
1727 case COND_CARRY_CLR: | |
1728 cond = CC_Z; | |
1729 case COND_CARRY_SET: | |
1730 check_flag(opts, FLAG_C); | |
1731 break; | |
1732 case COND_NOT_EQ: | |
1733 cond = CC_Z; | |
1734 case COND_EQ: | |
1735 check_flag(opts, FLAG_Z); | |
1736 break; | |
1737 case COND_OVERF_CLR: | |
1738 cond = CC_Z; | |
1739 case COND_OVERF_SET: | |
1740 check_flag(opts, FLAG_V); | |
1741 break; | |
1742 case COND_PLUS: | |
1743 cond = CC_Z; | |
1744 case COND_MINUS: | |
1745 check_flag(opts, FLAG_N); | |
1746 break; | |
1747 case COND_GREATER_EQ: | |
1748 cond = CC_Z; | |
1749 case COND_LESS: | |
1750 cmp_flags(opts, FLAG_N, FLAG_V); | |
1751 break; | |
1752 case COND_GREATER: | |
1753 cond = CC_Z; | |
1754 case COND_LESS_EQ: | |
1755 flag_to_reg(opts, FLAG_V, opts->gen.scratch1); | |
1756 xor_flag_to_reg(opts, FLAG_N, opts->gen.scratch1); | |
1757 or_flag_to_reg(opts, FLAG_Z, opts->gen.scratch1); | |
1758 break; | |
1759 } | |
1760 return cond; | |
1761 } | |
1762 | |
1763 void translate_m68k_bcc(x86_68k_options * opts, m68kinst * inst) | |
1764 { | |
1765 code_info *code = &opts->gen.code; | |
1766 cycles(&opts->gen, 10);//TODO: Adjust this for branch not taken case | |
1919 int32_t disp = inst->src.params.immed; | 1767 int32_t disp = inst->src.params.immed; |
1920 uint32_t after = inst->address + 2; | 1768 uint32_t after = inst->address + 2; |
1921 code_ptr dest_addr = get_native_address(opts->gen.native_code_map, after + disp); | 1769 code_ptr dest_addr = get_native_address(opts->gen.native_code_map, after + disp); |
1922 if (inst->extra.cond == COND_TRUE) { | 1770 if (inst->extra.cond == COND_TRUE) { |
1923 if (!dest_addr) { | 1771 if (!dest_addr) { |
1924 opts->gen.deferred = defer_address(opts->gen.deferred, after + disp, dst + 1); | 1772 opts->gen.deferred = defer_address(opts->gen.deferred, after + disp, code->cur + 1); |
1925 //dummy address to be replaced later, make sure it generates a 4-byte displacement | 1773 //dummy address to be replaced later, make sure it generates a 4-byte displacement |
1926 dest_addr = dst + 256; | 1774 dest_addr = code->cur + 256; |
1927 } | 1775 } |
1928 dst = jmp(dst, dest_addr); | 1776 jmp(code, dest_addr); |
1929 } else { | 1777 } else { |
1930 uint8_t cond = CC_NZ; | 1778 uint8_t cond = m68k_eval_cond(opts, inst->extra.cond); |
1931 switch (inst->extra.cond) | |
1932 { | |
1933 case COND_HIGH: | |
1934 cond = CC_Z; | |
1935 case COND_LOW_SAME: | |
1936 dst = flag_to_reg(dst, FLAG_Z, SCRATCH1, opts); | |
1937 dst = or_flag_to_reg(dst, FLAG_C, SCRATCH1, opts); | |
1938 break; | |
1939 case COND_CARRY_CLR: | |
1940 cond = CC_Z; | |
1941 case COND_CARRY_SET: | |
1942 dst = check_flag(dst, FLAG_C, opts); | |
1943 break; | |
1944 case COND_NOT_EQ: | |
1945 cond = CC_Z; | |
1946 case COND_EQ: | |
1947 dst = check_flag(dst, FLAG_Z, opts); | |
1948 break; | |
1949 case COND_OVERF_CLR: | |
1950 cond = CC_Z; | |
1951 case COND_OVERF_SET: | |
1952 dst = check_flag(dst, FLAG_V, opts); | |
1953 break; | |
1954 case COND_PLUS: | |
1955 cond = CC_Z; | |
1956 case COND_MINUS: | |
1957 dst = check_flag(dst, FLAG_N, opts); | |
1958 break; | |
1959 case COND_GREATER_EQ: | |
1960 cond = CC_Z; | |
1961 case COND_LESS: | |
1962 dst = cmp_flags(dst, FLAG_N, FLAG_V, opts); | |
1963 break; | |
1964 case COND_GREATER: | |
1965 cond = CC_Z; | |
1966 case COND_LESS_EQ: | |
1967 dst = flag_to_reg(dst, FLAG_V, SCRATCH1, opts); | |
1968 dst = xor_flag_to_reg(dst, FLAG_N, SCRATCH1, opts); | |
1969 dst = or_flag_to_reg(dst, FLAG_Z, SCRATCH1, opts); | |
1970 break; | |
1971 } | |
1972 if (!dest_addr) { | 1779 if (!dest_addr) { |
1973 opts->gen.deferred = defer_address(opts->gen.deferred, after + disp, dst + 2); | 1780 opts->gen.deferred = defer_address(opts->gen.deferred, after + disp, code->cur + 2); |
1974 //dummy address to be replaced later, make sure it generates a 4-byte displacement | 1781 //dummy address to be replaced later, make sure it generates a 4-byte displacement |
1975 dest_addr = dst + 256; | 1782 dest_addr = code->cur + 256; |
1976 } | 1783 } |
1977 dst = jcc(dst, cond, dest_addr); | 1784 jcc(code, cond, dest_addr); |
1978 } | 1785 } |
1979 return dst; | 1786 } |
1980 } | 1787 |
1981 | 1788 void translate_m68k_scc(x86_68k_options * opts, m68kinst * inst) |
1982 code_ptr translate_m68k_scc(code_ptr dst, m68kinst * inst, x86_68k_options * opts) | 1789 { |
1983 { | 1790 code_info *code = &opts->gen.code; |
1984 uint8_t cond = inst->extra.cond; | 1791 uint8_t cond = inst->extra.cond; |
1985 x86_ea dst_op; | 1792 x86_ea dst_op; |
1986 inst->extra.size = OPSIZE_BYTE; | 1793 inst->extra.size = OPSIZE_BYTE; |
1987 dst = translate_m68k_dst(inst, &dst_op, dst, opts, 1); | 1794 translate_m68k_dst(inst, &dst_op, opts, 1); |
1988 if (cond == COND_TRUE || cond == COND_FALSE) { | 1795 if (cond == COND_TRUE || cond == COND_FALSE) { |
1989 if ((inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG) && inst->extra.cond == COND_TRUE) { | 1796 if ((inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG) && inst->extra.cond == COND_TRUE) { |
1990 dst = cycles(dst, 6); | 1797 cycles(&opts->gen, 6); |
1991 } else { | 1798 } else { |
1992 dst = cycles(dst, BUS); | 1799 cycles(&opts->gen, BUS); |
1993 } | 1800 } |
1994 if (dst_op.mode == MODE_REG_DIRECT) { | 1801 if (dst_op.mode == MODE_REG_DIRECT) { |
1995 dst = mov_ir(dst, cond == COND_TRUE ? 0xFF : 0, dst_op.base, SZ_B); | 1802 mov_ir(code, cond == COND_TRUE ? 0xFF : 0, dst_op.base, SZ_B); |
1996 } else { | 1803 } else { |
1997 dst = mov_irdisp8(dst, cond == COND_TRUE ? 0xFF : 0, dst_op.base, dst_op.disp, SZ_B); | 1804 mov_irdisp(code, cond == COND_TRUE ? 0xFF : 0, dst_op.base, dst_op.disp, SZ_B); |
1998 } | 1805 } |
1999 } else { | 1806 } else { |
2000 uint8_t cc = CC_NZ; | 1807 uint8_t cc = m68k_eval_cond(opts, cond); |
2001 switch (cond) | 1808 check_alloc_code(code, 6*MAX_INST_LEN); |
2002 { | 1809 code_ptr true_off = code->cur + 1; |
2003 case COND_HIGH: | 1810 jcc(code, cc, code->cur+2); |
2004 cc = CC_Z; | 1811 cycles(&opts->gen, BUS); |
2005 case COND_LOW_SAME: | |
2006 dst = flag_to_reg(dst, FLAG_Z, SCRATCH1, opts); | |
2007 dst = or_flag_to_reg(dst, FLAG_C, SCRATCH1, opts); | |
2008 break; | |
2009 case COND_CARRY_CLR: | |
2010 cc = CC_Z; | |
2011 case COND_CARRY_SET: | |
2012 dst = check_flag(dst, FLAG_C, opts); | |
2013 break; | |
2014 case COND_NOT_EQ: | |
2015 cc = CC_Z; | |
2016 case COND_EQ: | |
2017 dst = check_flag(dst, FLAG_Z, opts); | |
2018 break; | |
2019 case COND_OVERF_CLR: | |
2020 cc = CC_Z; | |
2021 case COND_OVERF_SET: | |
2022 dst = check_flag(dst, FLAG_V, opts); | |
2023 break; | |
2024 case COND_PLUS: | |
2025 cc = CC_Z; | |
2026 case COND_MINUS: | |
2027 dst = check_flag(dst, FLAG_N, opts); | |
2028 break; | |
2029 case COND_GREATER_EQ: | |
2030 cc = CC_Z; | |
2031 case COND_LESS: | |
2032 dst = cmp_flags(dst, FLAG_N, FLAG_V, opts); | |
2033 break; | |
2034 case COND_GREATER: | |
2035 cc = CC_Z; | |
2036 case COND_LESS_EQ: | |
2037 dst = flag_to_reg(dst, FLAG_V, SCRATCH1, opts); | |
2038 dst = xor_flag_to_reg(dst, FLAG_N, SCRATCH1, opts); | |
2039 dst = or_flag_to_reg(dst, FLAG_Z, SCRATCH1, opts); | |
2040 break; | |
2041 } | |
2042 code_ptr true_off = dst + 1; | |
2043 dst = jcc(dst, cc, dst+2); | |
2044 dst = cycles(dst, BUS); | |
2045 if (dst_op.mode == MODE_REG_DIRECT) { | 1812 if (dst_op.mode == MODE_REG_DIRECT) { |
2046 dst = mov_ir(dst, 0, dst_op.base, SZ_B); | 1813 mov_ir(code, 0, dst_op.base, SZ_B); |
2047 } else { | 1814 } else { |
2048 dst = mov_irdisp8(dst, 0, dst_op.base, dst_op.disp, SZ_B); | 1815 mov_irdisp(code, 0, dst_op.base, dst_op.disp, SZ_B); |
2049 } | 1816 } |
2050 code_ptr end_off = dst+1; | 1817 code_ptr end_off = code->cur+1; |
2051 dst = jmp(dst, dst+2); | 1818 jmp(code, code->cur+2); |
2052 *true_off = dst - (true_off+1); | 1819 *true_off = code->cur - (true_off+1); |
2053 dst = cycles(dst, 6); | 1820 cycles(&opts->gen, 6); |
2054 if (dst_op.mode == MODE_REG_DIRECT) { | 1821 if (dst_op.mode == MODE_REG_DIRECT) { |
2055 dst = mov_ir(dst, 0xFF, dst_op.base, SZ_B); | 1822 mov_ir(code, 0xFF, dst_op.base, SZ_B); |
2056 } else { | 1823 } else { |
2057 dst = mov_irdisp8(dst, 0xFF, dst_op.base, dst_op.disp, SZ_B); | 1824 mov_irdisp(code, 0xFF, dst_op.base, dst_op.disp, SZ_B); |
2058 } | 1825 } |
2059 *end_off = dst - (end_off+1); | 1826 *end_off = code->cur - (end_off+1); |
2060 } | 1827 } |
2061 dst = m68k_save_result(inst, dst, opts); | 1828 m68k_save_result(inst, opts); |
2062 return dst; | 1829 } |
2063 } | 1830 |
2064 | 1831 void translate_m68k_jmp_jsr(x86_68k_options * opts, m68kinst * inst) |
2065 code_ptr translate_m68k_jmp(code_ptr dst, m68kinst * inst, x86_68k_options * opts) | 1832 { |
2066 { | 1833 uint8_t is_jsr = inst->op == M68K_JSR; |
2067 code_ptr dest_addr; | 1834 code_info *code = &opts->gen.code; |
2068 uint8_t sec_reg; | |
2069 uint32_t m68k_addr; | |
2070 switch(inst->src.addr_mode) | |
2071 { | |
2072 case MODE_AREG_INDIRECT: | |
2073 dst = cycles(dst, BUS*2); | |
2074 if (opts->aregs[inst->src.params.regs.pri] >= 0) { | |
2075 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); | |
2076 } else { | |
2077 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, SCRATCH1, SZ_D); | |
2078 } | |
2079 dst = call(dst, opts->native_addr); | |
2080 dst = jmp_r(dst, SCRATCH1); | |
2081 break; | |
2082 case MODE_AREG_INDEX_DISP8: | |
2083 dst = cycles(dst, BUS*3);//TODO: CHeck that this is correct | |
2084 if (opts->aregs[inst->src.params.regs.pri] >= 0) { | |
2085 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); | |
2086 } else { | |
2087 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, SZ_D); | |
2088 } | |
2089 sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; | |
2090 if (inst->src.params.regs.sec & 1) { | |
2091 //32-bit index register | |
2092 if (inst->src.params.regs.sec & 0x10) { | |
2093 if (opts->aregs[sec_reg] >= 0) { | |
2094 dst = add_rr(dst, opts->aregs[sec_reg], SCRATCH1, SZ_D); | |
2095 } else { | |
2096 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D); | |
2097 } | |
2098 } else { | |
2099 if (opts->dregs[sec_reg] >= 0) { | |
2100 dst = add_rr(dst, opts->dregs[sec_reg], SCRATCH1, SZ_D); | |
2101 } else { | |
2102 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D); | |
2103 } | |
2104 } | |
2105 } else { | |
2106 //16-bit index register | |
2107 if (inst->src.params.regs.sec & 0x10) { | |
2108 if (opts->aregs[sec_reg] >= 0) { | |
2109 dst = movsx_rr(dst, opts->aregs[sec_reg], SCRATCH2, SZ_W, SZ_D); | |
2110 } else { | |
2111 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D); | |
2112 } | |
2113 } else { | |
2114 if (opts->dregs[sec_reg] >= 0) { | |
2115 dst = movsx_rr(dst, opts->dregs[sec_reg], SCRATCH2, SZ_W, SZ_D); | |
2116 } else { | |
2117 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D); | |
2118 } | |
2119 } | |
2120 dst = add_rr(dst, SCRATCH2, SCRATCH1, SZ_D); | |
2121 } | |
2122 if (inst->src.params.regs.displacement) { | |
2123 dst = add_ir(dst, inst->src.params.regs.displacement, SCRATCH1, SZ_D); | |
2124 } | |
2125 dst = call(dst, opts->native_addr); | |
2126 dst = jmp_r(dst, SCRATCH1); | |
2127 break; | |
2128 case MODE_PC_DISPLACE: | |
2129 dst = cycles(dst, 10); | |
2130 m68k_addr = inst->src.params.regs.displacement + inst->address + 2; | |
2131 if ((m68k_addr & 0xFFFFFF) < 0x400000) { | |
2132 dest_addr = get_native_address(opts->gen.native_code_map, m68k_addr); | |
2133 if (!dest_addr) { | |
2134 opts->gen.deferred = defer_address(opts->gen.deferred, m68k_addr, dst + 1); | |
2135 //dummy address to be replaced later, make sure it generates a 4-byte displacement | |
2136 dest_addr = dst + 256; | |
2137 } | |
2138 dst = jmp(dst, dest_addr); | |
2139 } else { | |
2140 dst = mov_ir(dst, m68k_addr, SCRATCH1, SZ_D); | |
2141 dst = call(dst, opts->native_addr); | |
2142 dst = jmp_r(dst, SCRATCH1); | |
2143 } | |
2144 break; | |
2145 case MODE_PC_INDEX_DISP8: | |
2146 dst = cycles(dst, BUS*3);//TODO: CHeck that this is correct | |
2147 dst = mov_ir(dst, inst->address+2, SCRATCH1, SZ_D); | |
2148 sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; | |
2149 if (inst->src.params.regs.sec & 1) { | |
2150 if (inst->src.params.regs.sec & 0x10) { | |
2151 if (opts->aregs[sec_reg] >= 0) { | |
2152 dst = add_rr(dst, opts->aregs[sec_reg], SCRATCH1, SZ_D); | |
2153 } else { | |
2154 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D); | |
2155 } | |
2156 } else { | |
2157 if (opts->dregs[sec_reg] >= 0) { | |
2158 dst = add_rr(dst, opts->dregs[sec_reg], SCRATCH1, SZ_D); | |
2159 } else { | |
2160 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D); | |
2161 } | |
2162 } | |
2163 } else { | |
2164 if (inst->src.params.regs.sec & 0x10) { | |
2165 if (opts->aregs[sec_reg] >= 0) { | |
2166 dst = movsx_rr(dst, opts->aregs[sec_reg], SCRATCH2, SZ_W, SZ_D); | |
2167 } else { | |
2168 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D); | |
2169 } | |
2170 } else { | |
2171 if (opts->dregs[sec_reg] >= 0) { | |
2172 dst = movsx_rr(dst, opts->dregs[sec_reg], SCRATCH2, SZ_W, SZ_D); | |
2173 } else { | |
2174 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D); | |
2175 } | |
2176 } | |
2177 dst = add_rr(dst, SCRATCH2, SCRATCH1, SZ_D); | |
2178 } | |
2179 if (inst->src.params.regs.displacement) { | |
2180 dst = add_ir(dst, inst->src.params.regs.displacement, SCRATCH1, SZ_D); | |
2181 } | |
2182 dst = call(dst, opts->native_addr); | |
2183 dst = jmp_r(dst, SCRATCH1); | |
2184 break; | |
2185 case MODE_ABSOLUTE: | |
2186 case MODE_ABSOLUTE_SHORT: | |
2187 dst = cycles(dst, inst->src.addr_mode == MODE_ABSOLUTE ? 12 : 10); | |
2188 m68k_addr = inst->src.params.immed; | |
2189 if ((m68k_addr & 0xFFFFFF) < 0x400000) { | |
2190 dest_addr = get_native_address(opts->gen.native_code_map, m68k_addr); | |
2191 if (!dest_addr) { | |
2192 opts->gen.deferred = defer_address(opts->gen.deferred, m68k_addr, dst + 1); | |
2193 //dummy address to be replaced later, make sure it generates a 4-byte displacement | |
2194 dest_addr = dst + 256; | |
2195 } | |
2196 dst = jmp(dst, dest_addr); | |
2197 } else { | |
2198 dst = mov_ir(dst, m68k_addr, SCRATCH1, SZ_D); | |
2199 dst = call(dst, opts->native_addr); | |
2200 dst = jmp_r(dst, SCRATCH1); | |
2201 } | |
2202 break; | |
2203 default: | |
2204 m68k_disasm(inst, disasm_buf); | |
2205 printf("%s\naddress mode %d not yet supported (jmp)\n", disasm_buf, inst->src.addr_mode); | |
2206 exit(1); | |
2207 } | |
2208 return dst; | |
2209 } | |
2210 | |
2211 code_ptr translate_m68k_jsr(code_ptr dst, m68kinst * inst, x86_68k_options * opts) | |
2212 { | |
2213 code_ptr dest_addr; | 1835 code_ptr dest_addr; |
2214 uint8_t sec_reg; | 1836 uint8_t sec_reg; |
2215 uint32_t after; | 1837 uint32_t after; |
2216 uint32_t m68k_addr; | 1838 uint32_t m68k_addr; |
2217 switch(inst->src.addr_mode) | 1839 switch(inst->src.addr_mode) |
2218 { | 1840 { |
2219 case MODE_AREG_INDIRECT: | 1841 case MODE_AREG_INDIRECT: |
2220 dst = cycles(dst, BUS*2); | 1842 cycles(&opts->gen, BUS*2); |
2221 dst = mov_ir(dst, inst->address + 2, SCRATCH1, SZ_D); | 1843 if (is_jsr) { |
2222 dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); | 1844 mov_ir(code, inst->address + 2, opts->gen.scratch1, SZ_D); |
2223 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); | 1845 sub_ir(code, 4, opts->aregs[7], SZ_D); |
2224 dst = call(dst, opts->write_32_highfirst); | 1846 mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); |
1847 call(code, opts->write_32_highfirst); | |
1848 } | |
2225 if (opts->aregs[inst->src.params.regs.pri] >= 0) { | 1849 if (opts->aregs[inst->src.params.regs.pri] >= 0) { |
2226 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); | 1850 mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); |
2227 } else { | 1851 } else { |
2228 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, SCRATCH1, SZ_D); | 1852 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, opts->gen.scratch1, SZ_D); |
2229 } | 1853 } |
2230 dst = call(dst, opts->native_addr); | 1854 call(code, opts->native_addr); |
2231 dst = jmp_r(dst, SCRATCH1); | 1855 jmp_r(code, opts->gen.scratch1); |
2232 break; | 1856 break; |
2233 case MODE_AREG_DISPLACE: | 1857 case MODE_AREG_DISPLACE: |
2234 dst = cycles(dst, BUS*2); | 1858 cycles(&opts->gen, BUS*2); |
2235 dst = mov_ir(dst, inst->address + 4, SCRATCH1, SZ_D); | 1859 if (is_jsr) { |
2236 dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); | 1860 mov_ir(code, inst->address + 4, opts->gen.scratch1, SZ_D); |
2237 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); | 1861 sub_ir(code, 4, opts->aregs[7], SZ_D); |
2238 dst = call(dst, opts->write_32_highfirst); | 1862 mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); |
1863 call(code, opts->write_32_highfirst); | |
1864 } | |
2239 if (opts->aregs[inst->src.params.regs.pri] >= 0) { | 1865 if (opts->aregs[inst->src.params.regs.pri] >= 0) { |
2240 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); | 1866 mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); |
2241 } else { | 1867 } else { |
2242 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, SCRATCH1, SZ_D); | 1868 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, opts->gen.scratch1, SZ_D); |
2243 } | 1869 } |
2244 dst = add_ir(dst, inst->src.params.regs.displacement, SCRATCH1, SZ_D); | 1870 add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); |
2245 dst = call(dst, opts->native_addr); | 1871 call(code, opts->native_addr); |
2246 dst = jmp_r(dst, SCRATCH1); | 1872 jmp_r(code, opts->gen.scratch1); |
2247 break; | 1873 break; |
2248 case MODE_AREG_INDEX_DISP8: | 1874 case MODE_AREG_INDEX_DISP8: |
2249 dst = cycles(dst, BUS*3);//TODO: CHeck that this is correct | 1875 cycles(&opts->gen, BUS*3);//TODO: CHeck that this is correct |
2250 dst = mov_ir(dst, inst->address + 4, SCRATCH1, SZ_D); | 1876 if (is_jsr) { |
2251 dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); | 1877 mov_ir(code, inst->address + 4, opts->gen.scratch1, SZ_D); |
2252 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); | 1878 sub_ir(code, 4, opts->aregs[7], SZ_D); |
2253 dst = call(dst, opts->write_32_highfirst); | 1879 mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); |
1880 call(code, opts->write_32_highfirst); | |
1881 } | |
2254 if (opts->aregs[inst->src.params.regs.pri] >= 0) { | 1882 if (opts->aregs[inst->src.params.regs.pri] >= 0) { |
2255 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); | 1883 mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); |
2256 } else { | 1884 } else { |
2257 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, SZ_D); | 1885 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_D); |
2258 } | 1886 } |
1887 sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; | |
1888 if (inst->src.params.regs.sec & 1) { | |
1889 //32-bit index register | |
1890 if (inst->src.params.regs.sec & 0x10) { | |
1891 if (opts->aregs[sec_reg] >= 0) { | |
1892 add_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_D); | |
1893 } else { | |
1894 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); | |
1895 } | |
1896 } else { | |
1897 if (opts->dregs[sec_reg] >= 0) { | |
1898 add_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_D); | |
1899 } else { | |
1900 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); | |
1901 } | |
1902 } | |
1903 } else { | |
1904 //16-bit index register | |
1905 if (inst->src.params.regs.sec & 0x10) { | |
1906 if (opts->aregs[sec_reg] >= 0) { | |
1907 movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); | |
1908 } else { | |
1909 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); | |
1910 } | |
1911 } else { | |
1912 if (opts->dregs[sec_reg] >= 0) { | |
1913 movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); | |
1914 } else { | |
1915 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); | |
1916 } | |
1917 } | |
1918 add_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D); | |
1919 } | |
1920 if (inst->src.params.regs.displacement) { | |
1921 add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); | |
1922 } | |
1923 call(code, opts->native_addr); | |
1924 jmp_r(code, opts->gen.scratch1); | |
1925 break; | |
1926 case MODE_PC_DISPLACE: | |
1927 //TODO: Add cycles in the right place relative to pushing the return address on the stack | |
1928 cycles(&opts->gen, 10); | |
1929 if (is_jsr) { | |
1930 mov_ir(code, inst->address + 4, opts->gen.scratch1, SZ_D); | |
1931 sub_ir(code, 4, opts->aregs[7], SZ_D); | |
1932 mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); | |
1933 call(code, opts->write_32_highfirst); | |
1934 } | |
1935 m68k_addr = inst->src.params.regs.displacement + inst->address + 2; | |
1936 if ((m68k_addr & 0xFFFFFF) < 0x400000) { | |
1937 dest_addr = get_native_address(opts->gen.native_code_map, m68k_addr); | |
1938 if (!dest_addr) { | |
1939 opts->gen.deferred = defer_address(opts->gen.deferred, m68k_addr, code->cur + 1); | |
1940 //dummy address to be replaced later, make sure it generates a 4-byte displacement | |
1941 dest_addr = code->cur + 256; | |
1942 } | |
1943 jmp(code, dest_addr); | |
1944 } else { | |
1945 mov_ir(code, m68k_addr, opts->gen.scratch1, SZ_D); | |
1946 call(code, opts->native_addr); | |
1947 jmp_r(code, opts->gen.scratch1); | |
1948 } | |
1949 break; | |
1950 case MODE_PC_INDEX_DISP8: | |
1951 cycles(&opts->gen, BUS*3);//TODO: CHeck that this is correct | |
1952 if (is_jsr) { | |
1953 mov_ir(code, inst->address + 4, opts->gen.scratch1, SZ_D); | |
1954 sub_ir(code, 4, opts->aregs[7], SZ_D); | |
1955 mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); | |
1956 call(code, opts->write_32_highfirst); | |
1957 } | |
1958 mov_ir(code, inst->address+2, opts->gen.scratch1, SZ_D); | |
2259 sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; | 1959 sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; |
2260 if (inst->src.params.regs.sec & 1) { | 1960 if (inst->src.params.regs.sec & 1) { |
2261 if (inst->src.params.regs.sec & 0x10) { | 1961 if (inst->src.params.regs.sec & 0x10) { |
2262 if (opts->aregs[sec_reg] >= 0) { | 1962 if (opts->aregs[sec_reg] >= 0) { |
2263 dst = add_rr(dst, opts->aregs[sec_reg], SCRATCH1, SZ_D); | 1963 add_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_D); |
2264 } else { | 1964 } else { |
2265 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D); | 1965 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); |
2266 } | 1966 } |
2267 } else { | 1967 } else { |
2268 if (opts->dregs[sec_reg] >= 0) { | 1968 if (opts->dregs[sec_reg] >= 0) { |
2269 dst = add_rr(dst, opts->dregs[sec_reg], SCRATCH1, SZ_D); | 1969 add_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_D); |
2270 } else { | 1970 } else { |
2271 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D); | 1971 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); |
2272 } | 1972 } |
2273 } | 1973 } |
2274 } else { | 1974 } else { |
2275 if (inst->src.params.regs.sec & 0x10) { | 1975 if (inst->src.params.regs.sec & 0x10) { |
2276 if (opts->aregs[sec_reg] >= 0) { | 1976 if (opts->aregs[sec_reg] >= 0) { |
2277 dst = movsx_rr(dst, opts->aregs[sec_reg], SCRATCH2, SZ_W, SZ_D); | 1977 movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); |
2278 } else { | 1978 } else { |
2279 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D); | 1979 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); |
2280 } | 1980 } |
2281 } else { | 1981 } else { |
2282 if (opts->dregs[sec_reg] >= 0) { | 1982 if (opts->dregs[sec_reg] >= 0) { |
2283 dst = movsx_rr(dst, opts->dregs[sec_reg], SCRATCH2, SZ_W, SZ_D); | 1983 movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); |
2284 } else { | 1984 } else { |
2285 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D); | 1985 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); |
2286 } | 1986 } |
2287 } | 1987 } |
2288 dst = add_rr(dst, SCRATCH2, SCRATCH1, SZ_D); | 1988 add_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D); |
2289 } | 1989 } |
2290 if (inst->src.params.regs.displacement) { | 1990 if (inst->src.params.regs.displacement) { |
2291 dst = add_ir(dst, inst->src.params.regs.displacement, SCRATCH1, SZ_D); | 1991 add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); |
2292 } | 1992 } |
2293 dst = call(dst, opts->native_addr); | 1993 call(code, opts->native_addr); |
2294 dst = jmp_r(dst, SCRATCH1); | 1994 jmp_r(code, opts->gen.scratch1); |
2295 break; | |
2296 case MODE_PC_DISPLACE: | |
2297 //TODO: Add cycles in the right place relative to pushing the return address on the stack | |
2298 dst = cycles(dst, 10); | |
2299 dst = mov_ir(dst, inst->address + 4, SCRATCH1, SZ_D); | |
2300 dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); | |
2301 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); | |
2302 dst = call(dst, opts->write_32_highfirst); | |
2303 m68k_addr = inst->src.params.regs.displacement + inst->address + 2; | |
2304 if ((m68k_addr & 0xFFFFFF) < 0x400000) { | |
2305 dest_addr = get_native_address(opts->gen.native_code_map, m68k_addr); | |
2306 if (!dest_addr) { | |
2307 opts->gen.deferred = defer_address(opts->gen.deferred, m68k_addr, dst + 1); | |
2308 //dummy address to be replaced later, make sure it generates a 4-byte displacement | |
2309 dest_addr = dst + 256; | |
2310 } | |
2311 dst = jmp(dst, dest_addr); | |
2312 } else { | |
2313 dst = mov_ir(dst, m68k_addr, SCRATCH1, SZ_D); | |
2314 dst = call(dst, opts->native_addr); | |
2315 dst = jmp_r(dst, SCRATCH1); | |
2316 } | |
2317 break; | |
2318 case MODE_PC_INDEX_DISP8: | |
2319 dst = cycles(dst, BUS*3);//TODO: CHeck that this is correct | |
2320 dst = mov_ir(dst, inst->address + 4, SCRATCH1, SZ_D); | |
2321 dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); | |
2322 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); | |
2323 dst = call(dst, opts->write_32_highfirst); | |
2324 dst = mov_ir(dst, inst->address+2, SCRATCH1, SZ_D); | |
2325 sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; | |
2326 if (inst->src.params.regs.sec & 1) { | |
2327 if (inst->src.params.regs.sec & 0x10) { | |
2328 if (opts->aregs[sec_reg] >= 0) { | |
2329 dst = add_rr(dst, opts->aregs[sec_reg], SCRATCH1, SZ_D); | |
2330 } else { | |
2331 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D); | |
2332 } | |
2333 } else { | |
2334 if (opts->dregs[sec_reg] >= 0) { | |
2335 dst = add_rr(dst, opts->dregs[sec_reg], SCRATCH1, SZ_D); | |
2336 } else { | |
2337 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D); | |
2338 } | |
2339 } | |
2340 } else { | |
2341 if (inst->src.params.regs.sec & 0x10) { | |
2342 if (opts->aregs[sec_reg] >= 0) { | |
2343 dst = movsx_rr(dst, opts->aregs[sec_reg], SCRATCH2, SZ_W, SZ_D); | |
2344 } else { | |
2345 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D); | |
2346 } | |
2347 } else { | |
2348 if (opts->dregs[sec_reg] >= 0) { | |
2349 dst = movsx_rr(dst, opts->dregs[sec_reg], SCRATCH2, SZ_W, SZ_D); | |
2350 } else { | |
2351 dst = movsx_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D); | |
2352 } | |
2353 } | |
2354 dst = add_rr(dst, SCRATCH2, SCRATCH1, SZ_D); | |
2355 } | |
2356 if (inst->src.params.regs.displacement) { | |
2357 dst = add_ir(dst, inst->src.params.regs.displacement, SCRATCH1, SZ_D); | |
2358 } | |
2359 dst = call(dst, opts->native_addr); | |
2360 dst = jmp_r(dst, SCRATCH1); | |
2361 break; | 1995 break; |
2362 case MODE_ABSOLUTE: | 1996 case MODE_ABSOLUTE: |
2363 case MODE_ABSOLUTE_SHORT: | 1997 case MODE_ABSOLUTE_SHORT: |
2364 //TODO: Add cycles in the right place relative to pushing the return address on the stack | 1998 //TODO: Add cycles in the right place relative to pushing the return address on the stack |
2365 dst = cycles(dst, inst->src.addr_mode == MODE_ABSOLUTE ? 12 : 10); | 1999 cycles(&opts->gen, inst->src.addr_mode == MODE_ABSOLUTE ? 12 : 10); |
2366 dst = mov_ir(dst, inst->address + (inst->src.addr_mode == MODE_ABSOLUTE ? 6 : 4), SCRATCH1, SZ_D); | 2000 if (is_jsr) { |
2367 dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); | 2001 mov_ir(code, inst->address + (inst->src.addr_mode == MODE_ABSOLUTE ? 6 : 4), opts->gen.scratch1, SZ_D); |
2368 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); | 2002 sub_ir(code, 4, opts->aregs[7], SZ_D); |
2369 dst = call(dst, opts->write_32_highfirst); | 2003 mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); |
2004 call(code, opts->write_32_highfirst); | |
2005 } | |
2370 m68k_addr = inst->src.params.immed; | 2006 m68k_addr = inst->src.params.immed; |
2371 if ((m68k_addr & 0xFFFFFF) < 0x400000) { | 2007 if ((m68k_addr & 0xFFFFFF) < 0x400000) { |
2372 dest_addr = get_native_address(opts->gen.native_code_map, m68k_addr); | 2008 dest_addr = get_native_address(opts->gen.native_code_map, m68k_addr); |
2373 if (!dest_addr) { | 2009 if (!dest_addr) { |
2374 opts->gen.deferred = defer_address(opts->gen.deferred, m68k_addr, dst + 1); | 2010 opts->gen.deferred = defer_address(opts->gen.deferred, m68k_addr, code->cur + 1); |
2375 //dummy address to be replaced later, make sure it generates a 4-byte displacement | 2011 //dummy address to be replaced later, make sure it generates a 4-byte displacement |
2376 dest_addr = dst + 256; | 2012 dest_addr = code->cur + 256; |
2377 } | 2013 } |
2378 dst = jmp(dst, dest_addr); | 2014 jmp(code, dest_addr); |
2379 } else { | 2015 } else { |
2380 dst = mov_ir(dst, m68k_addr, SCRATCH1, SZ_D); | 2016 mov_ir(code, m68k_addr, opts->gen.scratch1, SZ_D); |
2381 dst = call(dst, opts->native_addr); | 2017 call(code, opts->native_addr); |
2382 dst = jmp_r(dst, SCRATCH1); | 2018 jmp_r(code, opts->gen.scratch1); |
2383 } | 2019 } |
2384 break; | 2020 break; |
2385 default: | 2021 default: |
2386 m68k_disasm(inst, disasm_buf); | 2022 m68k_disasm(inst, disasm_buf); |
2387 printf("%s\naddress mode %d not yet supported (jsr)\n", disasm_buf, inst->src.addr_mode); | 2023 printf("%s\naddress mode %d not yet supported (%s)\n", disasm_buf, inst->src.addr_mode, is_jsr ? "jsr" : "jmp"); |
2388 exit(1); | 2024 exit(1); |
2389 } | 2025 } |
2390 return dst; | 2026 } |
2391 } | 2027 |
2392 | 2028 void translate_m68k_rts(x86_68k_options * opts, m68kinst * inst) |
2393 code_ptr translate_m68k_rts(code_ptr dst, m68kinst * inst, x86_68k_options * opts) | 2029 { |
2394 { | 2030 code_info *code = &opts->gen.code; |
2395 //TODO: Add cycles | 2031 //TODO: Add cycles |
2396 dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); | 2032 mov_rr(code, opts->aregs[7], opts->gen.scratch1, SZ_D); |
2397 dst = add_ir(dst, 4, opts->aregs[7], SZ_D); | 2033 add_ir(code, 4, opts->aregs[7], SZ_D); |
2398 dst = call(dst, opts->read_32); | 2034 call(code, opts->read_32); |
2399 dst = call(dst, opts->native_addr); | 2035 call(code, opts->native_addr); |
2400 dst = jmp_r(dst, SCRATCH1); | 2036 jmp_r(code, opts->gen.scratch1); |
2401 return dst; | 2037 } |
2402 } | 2038 |
2403 | 2039 void translate_m68k_dbcc(x86_68k_options * opts, m68kinst * inst) |
2404 code_ptr translate_m68k_dbcc(code_ptr dst, m68kinst * inst, x86_68k_options * opts) | 2040 { |
2405 { | 2041 code_info *code = &opts->gen.code; |
2406 //best case duration | 2042 //best case duration |
2407 dst = cycles(dst, 10); | 2043 cycles(&opts->gen, 10); |
2408 code_ptr skip_loc = NULL; | 2044 code_ptr skip_loc = NULL; |
2409 //TODO: Check if COND_TRUE technically valid here even though | 2045 //TODO: Check if COND_TRUE technically valid here even though |
2410 //it's basically a slow NOP | 2046 //it's basically a slow NOP |
2411 if (inst->extra.cond != COND_FALSE) { | 2047 if (inst->extra.cond != COND_FALSE) { |
2412 uint8_t cond = CC_NZ; | 2048 uint8_t cond = m68k_eval_cond(opts, inst->extra.cond); |
2413 switch (inst->extra.cond) | 2049 check_alloc_code(code, 6*MAX_INST_LEN); |
2414 { | 2050 skip_loc = code->cur + 1; |
2415 case COND_HIGH: | 2051 jcc(code, cond, code->cur + 2); |
2416 cond = CC_Z; | |
2417 case COND_LOW_SAME: | |
2418 dst = flag_to_reg(dst, FLAG_Z, SCRATCH1, opts); | |
2419 dst = or_flag_to_reg(dst, FLAG_C, SCRATCH1, opts); | |
2420 break; | |
2421 case COND_CARRY_CLR: | |
2422 cond = CC_Z; | |
2423 case COND_CARRY_SET: | |
2424 dst = check_flag(dst, FLAG_C, opts); | |
2425 break; | |
2426 case COND_NOT_EQ: | |
2427 cond = CC_Z; | |
2428 case COND_EQ: | |
2429 dst = check_flag(dst, FLAG_Z, opts); | |
2430 break; | |
2431 case COND_OVERF_CLR: | |
2432 cond = CC_Z; | |
2433 case COND_OVERF_SET: | |
2434 dst = check_flag(dst, FLAG_V, opts); | |
2435 break; | |
2436 case COND_PLUS: | |
2437 cond = CC_Z; | |
2438 case COND_MINUS: | |
2439 dst = check_flag(dst, FLAG_N, opts); | |
2440 break; | |
2441 case COND_GREATER_EQ: | |
2442 cond = CC_Z; | |
2443 case COND_LESS: | |
2444 dst = cmp_flags(dst, FLAG_N, FLAG_V, opts); | |
2445 break; | |
2446 case COND_GREATER: | |
2447 cond = CC_Z; | |
2448 case COND_LESS_EQ: | |
2449 dst = flag_to_reg(dst, FLAG_V, SCRATCH1, opts); | |
2450 dst = xor_flag_to_reg(dst, FLAG_N, SCRATCH1, opts); | |
2451 dst = or_flag_to_reg(dst, FLAG_Z, SCRATCH1, opts); | |
2452 break; | |
2453 } | |
2454 skip_loc = dst + 1; | |
2455 dst = jcc(dst, cond, dst + 2); | |
2456 } | 2052 } |
2457 if (opts->dregs[inst->dst.params.regs.pri] >= 0) { | 2053 if (opts->dregs[inst->dst.params.regs.pri] >= 0) { |
2458 dst = sub_ir(dst, 1, opts->dregs[inst->dst.params.regs.pri], SZ_W); | 2054 sub_ir(code, 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); | 2055 cmp_ir(code, -1, opts->dregs[inst->dst.params.regs.pri], SZ_W); |
2460 } else { | 2056 } else { |
2461 dst = sub_irdisp8(dst, 1, CONTEXT, offsetof(m68k_context, dregs) + 4 * inst->dst.params.regs.pri, SZ_W); | 2057 sub_irdisp(code, 1, opts->gen.context_reg, 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); | 2058 cmp_irdisp(code, -1, opts->gen.context_reg, offsetof(m68k_context, dregs) + 4 * inst->dst.params.regs.pri, SZ_W); |
2463 } | 2059 } |
2464 code_ptr loop_end_loc = dst+1; | 2060 code_ptr loop_end_loc = code->cur + 1; |
2465 dst = jcc(dst, CC_Z, dst+2); | 2061 jcc(code, CC_Z, code->cur + 2); |
2466 uint32_t after = inst->address + 2; | 2062 uint32_t after = inst->address + 2; |
2467 code_ptr dest_addr = get_native_address(opts->gen.native_code_map, after + inst->src.params.immed); | 2063 code_ptr dest_addr = get_native_address(opts->gen.native_code_map, after + inst->src.params.immed); |
2468 if (!dest_addr) { | 2064 if (!dest_addr) { |
2469 opts->gen.deferred = defer_address(opts->gen.deferred, after + inst->src.params.immed, dst + 1); | 2065 opts->gen.deferred = defer_address(opts->gen.deferred, after + inst->src.params.immed, code->cur + 1); |
2470 //dummy address to be replaced later, make sure it generates a 4-byte displacement | 2066 //dummy address to be replaced later, make sure it generates a 4-byte displacement |
2471 dest_addr = dst + 256; | 2067 dest_addr = code->cur + 256; |
2472 } | 2068 } |
2473 dst = jmp(dst, dest_addr); | 2069 jmp(code, dest_addr); |
2474 *loop_end_loc = dst - (loop_end_loc+1); | 2070 *loop_end_loc = code->cur - (loop_end_loc+1); |
2475 if (skip_loc) { | 2071 if (skip_loc) { |
2476 dst = cycles(dst, 2); | 2072 cycles(&opts->gen, 2); |
2477 *skip_loc = dst - (skip_loc+1); | 2073 *skip_loc = code->cur - (skip_loc+1); |
2478 dst = cycles(dst, 2); | 2074 cycles(&opts->gen, 2); |
2479 } else { | 2075 } else { |
2480 dst = cycles(dst, 4); | 2076 cycles(&opts->gen, 4); |
2481 } | 2077 } |
2482 return dst; | 2078 } |
2483 } | 2079 |
2484 | 2080 void translate_m68k_link(x86_68k_options * opts, m68kinst * inst) |
2485 code_ptr translate_m68k_link(code_ptr dst, m68kinst * inst, x86_68k_options * opts) | 2081 { |
2486 { | 2082 code_info *code = &opts->gen.code; |
2487 int8_t reg = native_reg(&(inst->src), opts); | 2083 int8_t reg = native_reg(&(inst->src), opts); |
2488 //compensate for displacement word | 2084 //compensate for displacement word |
2489 dst = cycles(dst, BUS); | 2085 cycles(&opts->gen, BUS); |
2490 dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); | 2086 sub_ir(code, 4, opts->aregs[7], SZ_D); |
2491 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); | 2087 mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); |
2492 if (reg >= 0) { | 2088 if (reg >= 0) { |
2493 dst = mov_rr(dst, reg, SCRATCH1, SZ_D); | 2089 mov_rr(code, reg, opts->gen.scratch1, SZ_D); |
2494 } else { | 2090 } else { |
2495 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, SZ_D); | 2091 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_D); |
2496 } | 2092 } |
2497 dst = call(dst, opts->write_32_highfirst); | 2093 call(code, opts->write_32_highfirst); |
2498 if (reg >= 0) { | 2094 if (reg >= 0) { |
2499 dst = mov_rr(dst, opts->aregs[7], reg, SZ_D); | 2095 mov_rr(code, opts->aregs[7], reg, SZ_D); |
2500 } else { | 2096 } else { |
2501 dst = mov_rrdisp8(dst, opts->aregs[7], CONTEXT, reg_offset(&(inst->src)), SZ_D); | 2097 mov_rrdisp(code, opts->aregs[7], opts->gen.context_reg, reg_offset(&(inst->src)), SZ_D); |
2502 } | 2098 } |
2503 dst = add_ir(dst, inst->dst.params.immed, opts->aregs[7], SZ_D); | 2099 add_ir(code, inst->dst.params.immed, opts->aregs[7], SZ_D); |
2504 //prefetch | 2100 //prefetch |
2505 dst = cycles(dst, BUS); | 2101 cycles(&opts->gen, BUS); |
2506 return dst; | 2102 } |
2507 } | 2103 |
2508 | 2104 void translate_m68k_movep(x86_68k_options * opts, m68kinst * inst) |
2509 code_ptr translate_m68k_movep(code_ptr dst, m68kinst * inst, x86_68k_options * opts) | 2105 { |
2510 { | 2106 code_info *code = &opts->gen.code; |
2511 int8_t reg; | 2107 int8_t reg; |
2512 dst = cycles(dst, BUS*2); | 2108 cycles(&opts->gen, BUS*2); |
2513 if (inst->src.addr_mode == MODE_REG) { | 2109 if (inst->src.addr_mode == MODE_REG) { |
2514 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | 2110 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { |
2515 dst = mov_rr(dst, opts->aregs[inst->dst.params.regs.pri], SCRATCH2, SZ_D); | 2111 mov_rr(code, opts->aregs[inst->dst.params.regs.pri], opts->gen.scratch2, SZ_D); |
2516 } else { | 2112 } else { |
2517 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->dst)), SCRATCH2, SZ_D); | 2113 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->dst)), opts->gen.scratch2, SZ_D); |
2518 } | 2114 } |
2519 if (inst->dst.params.regs.displacement) { | 2115 if (inst->dst.params.regs.displacement) { |
2520 dst = add_ir(dst, inst->dst.params.regs.displacement, SCRATCH2, SZ_D); | 2116 add_ir(code, inst->dst.params.regs.displacement, opts->gen.scratch2, SZ_D); |
2521 } | 2117 } |
2522 reg = native_reg(&(inst->src), opts); | 2118 reg = native_reg(&(inst->src), opts); |
2523 if (inst->extra.size == OPSIZE_LONG) { | 2119 if (inst->extra.size == OPSIZE_LONG) { |
2524 if (reg >= 0) { | 2120 if (reg >= 0) { |
2525 dst = mov_rr(dst, reg, SCRATCH1, SZ_D); | 2121 mov_rr(code, reg, opts->gen.scratch1, SZ_D); |
2526 dst = shr_ir(dst, 24, SCRATCH1, SZ_D); | 2122 shr_ir(code, 24, opts->gen.scratch1, SZ_D); |
2527 dst = push_r(dst, SCRATCH2); | 2123 push_r(code, opts->gen.scratch2); |
2528 dst = call(dst, opts->write_8); | 2124 call(code, opts->write_8); |
2529 dst = pop_r(dst, SCRATCH2); | 2125 pop_r(code, opts->gen.scratch2); |
2530 dst = mov_rr(dst, reg, SCRATCH1, SZ_D); | 2126 mov_rr(code, reg, opts->gen.scratch1, SZ_D); |
2531 dst = shr_ir(dst, 16, SCRATCH1, SZ_D); | 2127 shr_ir(code, 16, opts->gen.scratch1, SZ_D); |
2532 | 2128 |
2533 } else { | 2129 } else { |
2534 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src))+3, SCRATCH1, SZ_B); | 2130 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src))+3, opts->gen.scratch1, SZ_B); |
2535 dst = push_r(dst, SCRATCH2); | 2131 push_r(code, opts->gen.scratch2); |
2536 dst = call(dst, opts->write_8); | 2132 call(code, opts->write_8); |
2537 dst = pop_r(dst, SCRATCH2); | 2133 pop_r(code, opts->gen.scratch2); |
2538 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src))+2, SCRATCH1, SZ_B); | 2134 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src))+2, opts->gen.scratch1, SZ_B); |
2539 } | 2135 } |
2540 dst = add_ir(dst, 2, SCRATCH2, SZ_D); | 2136 add_ir(code, 2, opts->gen.scratch2, SZ_D); |
2541 dst = push_r(dst, SCRATCH2); | 2137 push_r(code, opts->gen.scratch2); |
2542 dst = call(dst, opts->write_8); | 2138 call(code, opts->write_8); |
2543 dst = pop_r(dst, SCRATCH2); | 2139 pop_r(code, opts->gen.scratch2); |
2544 dst = add_ir(dst, 2, SCRATCH2, SZ_D); | 2140 add_ir(code, 2, opts->gen.scratch2, SZ_D); |
2545 } | 2141 } |
2546 if (reg >= 0) { | 2142 if (reg >= 0) { |
2547 dst = mov_rr(dst, reg, SCRATCH1, SZ_W); | 2143 mov_rr(code, reg, opts->gen.scratch1, SZ_W); |
2548 dst = shr_ir(dst, 8, SCRATCH1, SZ_W); | 2144 shr_ir(code, 8, opts->gen.scratch1, SZ_W); |
2549 dst = push_r(dst, SCRATCH2); | 2145 push_r(code, opts->gen.scratch2); |
2550 dst = call(dst, opts->write_8); | 2146 call(code, opts->write_8); |
2551 dst = pop_r(dst, SCRATCH2); | 2147 pop_r(code, opts->gen.scratch2); |
2552 dst = mov_rr(dst, reg, SCRATCH1, SZ_W); | 2148 mov_rr(code, reg, opts->gen.scratch1, SZ_W); |
2553 } else { | 2149 } else { |
2554 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src))+1, SCRATCH1, SZ_B); | 2150 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src))+1, opts->gen.scratch1, SZ_B); |
2555 dst = push_r(dst, SCRATCH2); | 2151 push_r(code, opts->gen.scratch2); |
2556 dst = call(dst, opts->write_8); | 2152 call(code, opts->write_8); |
2557 dst = pop_r(dst, SCRATCH2); | 2153 pop_r(code, opts->gen.scratch2); |
2558 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, SZ_B); | 2154 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_B); |
2559 } | 2155 } |
2560 dst = add_ir(dst, 2, SCRATCH2, SZ_D); | 2156 add_ir(code, 2, opts->gen.scratch2, SZ_D); |
2561 dst = call(dst, opts->write_8); | 2157 call(code, opts->write_8); |
2562 } else { | 2158 } else { |
2563 if (opts->aregs[inst->src.params.regs.pri] >= 0) { | 2159 if (opts->aregs[inst->src.params.regs.pri] >= 0) { |
2564 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); | 2160 mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); |
2565 } else { | 2161 } else { |
2566 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, SZ_D); | 2162 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_D); |
2567 } | 2163 } |
2568 if (inst->src.params.regs.displacement) { | 2164 if (inst->src.params.regs.displacement) { |
2569 dst = add_ir(dst, inst->src.params.regs.displacement, SCRATCH1, SZ_D); | 2165 add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); |
2570 } | 2166 } |
2571 reg = native_reg(&(inst->dst), opts); | 2167 reg = native_reg(&(inst->dst), opts); |
2572 if (inst->extra.size == OPSIZE_LONG) { | 2168 if (inst->extra.size == OPSIZE_LONG) { |
2573 if (reg >= 0) { | 2169 if (reg >= 0) { |
2574 dst = push_r(dst, SCRATCH1); | 2170 push_r(code, opts->gen.scratch1); |
2575 dst = call(dst, opts->read_8); | 2171 call(code, opts->read_8); |
2576 dst = shl_ir(dst, 24, SCRATCH1, SZ_D); | 2172 shl_ir(code, 24, opts->gen.scratch1, SZ_D); |
2577 dst = mov_rr(dst, SCRATCH1, reg, SZ_D); | 2173 mov_rr(code, opts->gen.scratch1, reg, SZ_D); |
2578 dst = pop_r(dst, SCRATCH1); | 2174 pop_r(code, opts->gen.scratch1); |
2579 dst = add_ir(dst, 2, SCRATCH1, SZ_D); | 2175 add_ir(code, 2, opts->gen.scratch1, SZ_D); |
2580 dst = push_r(dst, SCRATCH1); | 2176 push_r(code, opts->gen.scratch1); |
2581 dst = call(dst, opts->read_8); | 2177 call(code, opts->read_8); |
2582 dst = shl_ir(dst, 16, SCRATCH1, SZ_D); | 2178 shl_ir(code, 16, opts->gen.scratch1, SZ_D); |
2583 dst = or_rr(dst, SCRATCH1, reg, SZ_D); | 2179 or_rr(code, opts->gen.scratch1, reg, SZ_D); |
2584 } else { | 2180 } else { |
2585 dst = push_r(dst, SCRATCH1); | 2181 push_r(code, opts->gen.scratch1); |
2586 dst = call(dst, opts->read_8); | 2182 call(code, opts->read_8); |
2587 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, reg_offset(&(inst->dst))+3, SZ_B); | 2183 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, reg_offset(&(inst->dst))+3, SZ_B); |
2588 dst = pop_r(dst, SCRATCH1); | 2184 pop_r(code, opts->gen.scratch1); |
2589 dst = add_ir(dst, 2, SCRATCH1, SZ_D); | 2185 add_ir(code, 2, opts->gen.scratch1, SZ_D); |
2590 dst = push_r(dst, SCRATCH1); | 2186 push_r(code, opts->gen.scratch1); |
2591 dst = call(dst, opts->read_8); | 2187 call(code, opts->read_8); |
2592 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, reg_offset(&(inst->dst))+2, SZ_B); | 2188 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, reg_offset(&(inst->dst))+2, SZ_B); |
2593 } | 2189 } |
2594 dst = pop_r(dst, SCRATCH1); | 2190 pop_r(code, opts->gen.scratch1); |
2595 dst = add_ir(dst, 2, SCRATCH1, SZ_D); | 2191 add_ir(code, 2, opts->gen.scratch1, SZ_D); |
2596 } | 2192 } |
2597 dst = push_r(dst, SCRATCH1); | 2193 push_r(code, opts->gen.scratch1); |
2598 dst = call(dst, opts->read_8); | 2194 call(code, opts->read_8); |
2599 if (reg >= 0) { | 2195 if (reg >= 0) { |
2600 | 2196 |
2601 dst = shl_ir(dst, 8, SCRATCH1, SZ_W); | 2197 shl_ir(code, 8, opts->gen.scratch1, SZ_W); |
2602 dst = mov_rr(dst, SCRATCH1, reg, SZ_W); | 2198 mov_rr(code, opts->gen.scratch1, reg, SZ_W); |
2603 dst = pop_r(dst, SCRATCH1); | 2199 pop_r(code, opts->gen.scratch1); |
2604 dst = add_ir(dst, 2, SCRATCH1, SZ_D); | 2200 add_ir(code, 2, opts->gen.scratch1, SZ_D); |
2605 dst = call(dst, opts->read_8); | 2201 call(code, opts->read_8); |
2606 dst = mov_rr(dst, SCRATCH1, reg, SZ_B); | 2202 mov_rr(code, opts->gen.scratch1, reg, SZ_B); |
2607 } else { | 2203 } else { |
2608 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, reg_offset(&(inst->dst))+1, SZ_B); | 2204 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, reg_offset(&(inst->dst))+1, SZ_B); |
2609 dst = pop_r(dst, SCRATCH1); | 2205 pop_r(code, opts->gen.scratch1); |
2610 dst = add_ir(dst, 2, SCRATCH1, SZ_D); | 2206 add_ir(code, 2, opts->gen.scratch1, SZ_D); |
2611 dst = call(dst, opts->read_8); | 2207 call(code, opts->read_8); |
2612 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, reg_offset(&(inst->dst)), SZ_B); | 2208 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, reg_offset(&(inst->dst)), SZ_B); |
2613 } | 2209 } |
2614 } | 2210 } |
2615 return dst; | 2211 } |
2616 } | 2212 |
2617 | 2213 void translate_m68k_cmp(x86_68k_options * opts, m68kinst * inst) |
2618 code_ptr translate_m68k_cmp(code_ptr dst, m68kinst * inst, x86_68k_options * opts) | 2214 { |
2619 { | 2215 code_info *code = &opts->gen.code; |
2620 uint8_t size = inst->extra.size; | 2216 uint8_t size = inst->extra.size; |
2621 x86_ea src_op, dst_op; | 2217 x86_ea src_op, dst_op; |
2622 dst = translate_m68k_src(inst, &src_op, dst, opts); | 2218 translate_m68k_src(inst, &src_op, opts); |
2623 if (inst->dst.addr_mode == MODE_AREG_POSTINC) { | 2219 if (inst->dst.addr_mode == MODE_AREG_POSTINC) { |
2624 dst = push_r(dst, SCRATCH1); | 2220 push_r(code, opts->gen.scratch1); |
2625 dst = translate_m68k_dst(inst, &dst_op, dst, opts, 0); | 2221 translate_m68k_dst(inst, &dst_op, opts, 0); |
2626 dst = pop_r(dst, SCRATCH2); | 2222 pop_r(code, opts->gen.scratch2); |
2627 src_op.base = SCRATCH2; | 2223 src_op.base = opts->gen.scratch2; |
2628 } else { | 2224 } else { |
2629 dst = translate_m68k_dst(inst, &dst_op, dst, opts, 0); | 2225 translate_m68k_dst(inst, &dst_op, opts, 0); |
2630 if (inst->dst.addr_mode == MODE_AREG && size == OPSIZE_WORD) { | 2226 if (inst->dst.addr_mode == MODE_AREG && size == OPSIZE_WORD) { |
2631 size = OPSIZE_LONG; | 2227 size = OPSIZE_LONG; |
2632 } | 2228 } |
2633 } | 2229 } |
2634 dst = cycles(dst, BUS); | 2230 cycles(&opts->gen, BUS); |
2635 if (src_op.mode == MODE_REG_DIRECT) { | 2231 if (src_op.mode == MODE_REG_DIRECT) { |
2636 if (dst_op.mode == MODE_REG_DIRECT) { | 2232 if (dst_op.mode == MODE_REG_DIRECT) { |
2637 dst = cmp_rr(dst, src_op.base, dst_op.base, size); | 2233 cmp_rr(code, src_op.base, dst_op.base, size); |
2638 } else { | 2234 } else { |
2639 dst = cmp_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, size); | 2235 cmp_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, size); |
2640 } | 2236 } |
2641 } else if (src_op.mode == MODE_REG_DISPLACE8) { | 2237 } else if (src_op.mode == MODE_REG_DISPLACE8) { |
2642 dst = cmp_rdisp8r(dst, src_op.base, src_op.disp, dst_op.base, size); | 2238 cmp_rdispr(code, src_op.base, src_op.disp, dst_op.base, size); |
2643 } else { | 2239 } else { |
2644 if (dst_op.mode == MODE_REG_DIRECT) { | 2240 if (dst_op.mode == MODE_REG_DIRECT) { |
2645 dst = cmp_ir(dst, src_op.disp, dst_op.base, size); | 2241 cmp_ir(code, src_op.disp, dst_op.base, size); |
2646 } else { | 2242 } else { |
2647 dst = cmp_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, size); | 2243 cmp_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, size); |
2648 } | 2244 } |
2649 } | 2245 } |
2650 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); | 2246 set_flag_cond(opts, CC_C, FLAG_C); |
2651 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 2247 set_flag_cond(opts, CC_Z, FLAG_Z); |
2652 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 2248 set_flag_cond(opts, CC_S, FLAG_N); |
2653 dst = set_flag_cond(dst, CC_O, FLAG_V, opts); | 2249 set_flag_cond(opts, CC_O, FLAG_V); |
2654 return dst; | 2250 } |
2655 } | 2251 |
2656 | 2252 typedef void (*shift_ir_t)(code_info *code, 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); | 2253 typedef void (*shift_irdisp_t)(code_info *code, uint8_t val, uint8_t dst_base, int32_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); | 2254 typedef void (*shift_clr_t)(code_info *code, uint8_t dst, uint8_t size); |
2659 typedef code_ptr (*shift_clr_t)(code_ptr out, uint8_t dst, uint8_t size); | 2255 typedef void (*shift_clrdisp_t)(code_info *code, uint8_t dst_base, int32_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); | 2256 |
2661 | 2257 void translate_shift(x86_68k_options * opts, m68kinst * inst, x86_ea *src_op, x86_ea * dst_op, shift_ir_t shift_ir, shift_irdisp_t shift_irdisp, shift_clr_t shift_clr, shift_clrdisp_t shift_clrdisp, shift_ir_t special, shift_irdisp_t special_disp) |
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) | 2258 { |
2663 { | 2259 code_info *code = &opts->gen.code; |
2664 code_ptr end_off = NULL; | 2260 code_ptr end_off = NULL; |
2665 code_ptr nz_off = NULL; | 2261 code_ptr nz_off = NULL; |
2666 code_ptr z_off = NULL; | 2262 code_ptr z_off = NULL; |
2667 if (inst->src.addr_mode == MODE_UNUSED) { | 2263 if (inst->src.addr_mode == MODE_UNUSED) { |
2668 dst = cycles(dst, BUS); | 2264 cycles(&opts->gen, BUS); |
2669 //Memory shift | 2265 //Memory shift |
2670 dst = shift_ir(dst, 1, dst_op->base, SZ_W); | 2266 shift_ir(code, 1, dst_op->base, SZ_W); |
2671 } else { | 2267 } else { |
2672 dst = cycles(dst, inst->extra.size == OPSIZE_LONG ? 8 : 6); | 2268 cycles(&opts->gen, inst->extra.size == OPSIZE_LONG ? 8 : 6); |
2673 if (src_op->mode == MODE_IMMED) { | 2269 if (src_op->mode == MODE_IMMED) { |
2674 if (src_op->disp != 1 && inst->op == M68K_ASL) { | 2270 if (src_op->disp != 1 && inst->op == M68K_ASL) { |
2675 dst = set_flag(dst, 0, FLAG_V, opts); | 2271 set_flag(opts, 0, FLAG_V); |
2676 for (int i = 0; i < src_op->disp; i++) { | 2272 for (int i = 0; i < src_op->disp; i++) { |
2677 if (dst_op->mode == MODE_REG_DIRECT) { | 2273 if (dst_op->mode == MODE_REG_DIRECT) { |
2678 dst = shift_ir(dst, 1, dst_op->base, inst->extra.size); | 2274 shift_ir(code, 1, dst_op->base, inst->extra.size); |
2679 } else { | 2275 } else { |
2680 dst = shift_irdisp8(dst, 1, dst_op->base, dst_op->disp, inst->extra.size); | 2276 shift_irdisp(code, 1, dst_op->base, dst_op->disp, inst->extra.size); |
2681 } | 2277 } |
2682 //dst = setcc_r(dst, CC_O, FLAG_V); | 2278 check_alloc_code(code, 2*MAX_INST_LEN); |
2683 code_ptr after_flag_set = dst+1; | 2279 code_ptr after_flag_set = code->cur + 1; |
2684 dst = jcc(dst, CC_NO, dst+2); | 2280 jcc(code, CC_NO, code->cur + 2); |
2685 dst = set_flag(dst, 1, FLAG_V, opts); | 2281 set_flag(opts, 1, FLAG_V); |
2686 *after_flag_set = dst - (after_flag_set+1); | 2282 *after_flag_set = code->cur - (after_flag_set+1); |
2687 } | 2283 } |
2688 } else { | 2284 } else { |
2689 if (dst_op->mode == MODE_REG_DIRECT) { | 2285 if (dst_op->mode == MODE_REG_DIRECT) { |
2690 dst = shift_ir(dst, src_op->disp, dst_op->base, inst->extra.size); | 2286 shift_ir(code, src_op->disp, dst_op->base, inst->extra.size); |
2691 } else { | 2287 } else { |
2692 dst = shift_irdisp8(dst, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size); | 2288 shift_irdisp(code, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size); |
2693 } | 2289 } |
2694 dst = set_flag_cond(dst, CC_O, FLAG_V, opts); | 2290 set_flag_cond(opts, CC_O, FLAG_V); |
2695 } | 2291 } |
2696 } else { | 2292 } else { |
2697 if (src_op->base != RCX) { | 2293 if (src_op->base != RCX) { |
2698 if (src_op->mode == MODE_REG_DIRECT) { | 2294 if (src_op->mode == MODE_REG_DIRECT) { |
2699 dst = mov_rr(dst, src_op->base, RCX, SZ_B); | 2295 mov_rr(code, src_op->base, RCX, SZ_B); |
2700 } else { | 2296 } else { |
2701 dst = mov_rdisp8r(dst, src_op->base, src_op->disp, RCX, SZ_B); | 2297 mov_rdispr(code, src_op->base, src_op->disp, RCX, SZ_B); |
2702 } | 2298 } |
2703 | 2299 |
2704 } | 2300 } |
2705 dst = and_ir(dst, 63, RCX, SZ_D); | 2301 and_ir(code, 63, RCX, SZ_D); |
2706 nz_off = dst+1; | 2302 check_alloc_code(code, 7*MAX_INST_LEN); |
2707 dst = jcc(dst, CC_NZ, dst+2); | 2303 nz_off = code->cur + 1; |
2304 jcc(code, CC_NZ, code->cur + 2); | |
2708 //Flag behavior for shift count of 0 is different for x86 than 68K | 2305 //Flag behavior for shift count of 0 is different for x86 than 68K |
2709 if (dst_op->mode == MODE_REG_DIRECT) { | 2306 if (dst_op->mode == MODE_REG_DIRECT) { |
2710 dst = cmp_ir(dst, 0, dst_op->base, inst->extra.size); | 2307 cmp_ir(code, 0, dst_op->base, inst->extra.size); |
2711 } else { | 2308 } else { |
2712 dst = cmp_irdisp8(dst, 0, dst_op->base, dst_op->disp, inst->extra.size); | 2309 cmp_irdisp(code, 0, dst_op->base, dst_op->disp, inst->extra.size); |
2713 } | 2310 } |
2714 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 2311 set_flag_cond(opts, CC_Z, FLAG_Z); |
2715 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 2312 set_flag_cond(opts, CC_S, FLAG_N); |
2716 dst = set_flag(dst, 0, FLAG_C, opts); | 2313 set_flag(opts, 0, FLAG_C); |
2717 //For other instructions, this flag will be set below | 2314 //For other instructions, this flag will be set below |
2718 if (inst->op == M68K_ASL) { | 2315 if (inst->op == M68K_ASL) { |
2719 dst = set_flag(dst, 0, FLAG_V, opts); | 2316 set_flag(opts, 0, FLAG_V); |
2720 } | 2317 } |
2721 z_off = dst+1; | 2318 z_off = code->cur + 1; |
2722 dst = jmp(dst, dst+2); | 2319 jmp(code, code->cur + 2); |
2723 *nz_off = dst - (nz_off + 1); | 2320 *nz_off = code->cur - (nz_off + 1); |
2724 //add 2 cycles for every bit shifted | 2321 //add 2 cycles for every bit shifted |
2725 dst = add_rr(dst, RCX, CYCLES, SZ_D); | 2322 add_rr(code, RCX, CYCLES, SZ_D); |
2726 dst = add_rr(dst, RCX, CYCLES, SZ_D); | 2323 add_rr(code, RCX, CYCLES, SZ_D); |
2727 if (inst->op == M68K_ASL) { | 2324 if (inst->op == M68K_ASL) { |
2728 //ASL has Overflow flag behavior that depends on all of the bits shifted through the MSB | 2325 //ASL has Overflow flag behavior that depends on all of the bits shifted through the MSB |
2729 //Easiest way to deal with this is to shift one bit at a time | 2326 //Easiest way to deal with this is to shift one bit at a time |
2730 dst = set_flag(dst, 0, FLAG_V, opts); | 2327 set_flag(opts, 0, FLAG_V); |
2731 code_ptr loop_start = dst; | 2328 check_alloc_code(code, 5*MAX_INST_LEN); |
2329 code_ptr loop_start = code->cur; | |
2732 if (dst_op->mode == MODE_REG_DIRECT) { | 2330 if (dst_op->mode == MODE_REG_DIRECT) { |
2733 dst = shift_ir(dst, 1, dst_op->base, inst->extra.size); | 2331 shift_ir(code, 1, dst_op->base, inst->extra.size); |
2734 } else { | 2332 } else { |
2735 dst = shift_irdisp8(dst, 1, dst_op->base, dst_op->disp, inst->extra.size); | 2333 shift_irdisp(code, 1, dst_op->base, dst_op->disp, inst->extra.size); |
2736 } | 2334 } |
2737 //dst = setcc_r(dst, CC_O, FLAG_V); | 2335 code_ptr after_flag_set = code->cur + 1; |
2738 code_ptr after_flag_set = dst+1; | 2336 jcc(code, CC_NO, code->cur + 2); |
2739 dst = jcc(dst, CC_NO, dst+2); | 2337 set_flag(opts, 1, FLAG_V); |
2740 dst = set_flag(dst, 1, FLAG_V, opts); | 2338 *after_flag_set = code->cur - (after_flag_set+1); |
2741 *after_flag_set = dst - (after_flag_set+1); | 2339 loop(code, loop_start); |
2742 dst = loop(dst, loop_start); | |
2743 } else { | 2340 } else { |
2744 //x86 shifts modulo 32 for operand sizes less than 64-bits | 2341 //x86 shifts modulo 32 for operand sizes less than 64-bits |
2745 //but M68K shifts modulo 64, so we need to check for large shifts here | 2342 //but M68K shifts modulo 64, so we need to check for large shifts here |
2746 dst = cmp_ir(dst, 32, RCX, SZ_B); | 2343 cmp_ir(code, 32, RCX, SZ_B); |
2747 code_ptr norm_shift_off = dst + 1; | 2344 check_alloc_code(code, 14*MAX_INST_LEN); |
2748 dst = jcc(dst, CC_L, dst+2); | 2345 code_ptr norm_shift_off = code->cur + 1; |
2346 jcc(code, CC_L, code->cur + 2); | |
2749 if (special) { | 2347 if (special) { |
2750 code_ptr after_flag_set = NULL; | 2348 code_ptr after_flag_set = NULL; |
2751 if (inst->extra.size == OPSIZE_LONG) { | 2349 if (inst->extra.size == OPSIZE_LONG) { |
2752 code_ptr neq_32_off = dst + 1; | 2350 code_ptr neq_32_off = code->cur + 1; |
2753 dst = jcc(dst, CC_NZ, dst+2); | 2351 jcc(code, CC_NZ, code->cur + 2); |
2754 | 2352 |
2755 //set the carry bit to the lsb | 2353 //set the carry bit to the lsb |
2756 if (dst_op->mode == MODE_REG_DIRECT) { | 2354 if (dst_op->mode == MODE_REG_DIRECT) { |
2757 dst = special(dst, 1, dst_op->base, SZ_D); | 2355 special(code, 1, dst_op->base, SZ_D); |
2758 } else { | 2356 } else { |
2759 dst = special_disp8(dst, 1, dst_op->base, dst_op->disp, SZ_D); | 2357 special_disp(code, 1, dst_op->base, dst_op->disp, SZ_D); |
2760 } | 2358 } |
2761 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); | 2359 set_flag_cond(opts, CC_C, FLAG_C); |
2762 after_flag_set = dst+1; | 2360 after_flag_set = code->cur + 1; |
2763 dst = jmp(dst, dst+2); | 2361 jmp(code, code->cur + 2); |
2764 *neq_32_off = dst - (neq_32_off+1); | 2362 *neq_32_off = code->cur - (neq_32_off+1); |
2765 } | 2363 } |
2766 dst = set_flag(dst, 0, FLAG_C, opts); | 2364 set_flag(opts, 0, FLAG_C); |
2767 if (after_flag_set) { | 2365 if (after_flag_set) { |
2768 *after_flag_set = dst - (after_flag_set+1); | 2366 *after_flag_set = code->cur - (after_flag_set+1); |
2769 } | 2367 } |
2770 dst = set_flag(dst, 1, FLAG_Z, opts); | 2368 set_flag(opts, 1, FLAG_Z); |
2771 dst = set_flag(dst, 0, FLAG_N, opts); | 2369 set_flag(opts, 0, FLAG_N); |
2772 if (dst_op->mode == MODE_REG_DIRECT) { | 2370 if (dst_op->mode == MODE_REG_DIRECT) { |
2773 dst = xor_rr(dst, dst_op->base, dst_op->base, inst->extra.size); | 2371 xor_rr(code, dst_op->base, dst_op->base, inst->extra.size); |
2774 } else { | 2372 } else { |
2775 dst = mov_irdisp8(dst, 0, dst_op->base, dst_op->disp, inst->extra.size); | 2373 mov_irdisp(code, 0, dst_op->base, dst_op->disp, inst->extra.size); |
2776 } | 2374 } |
2777 } else { | 2375 } else { |
2778 if (dst_op->mode == MODE_REG_DIRECT) { | 2376 if (dst_op->mode == MODE_REG_DIRECT) { |
2779 dst = shift_ir(dst, 31, dst_op->base, inst->extra.size); | 2377 shift_ir(code, 31, dst_op->base, inst->extra.size); |
2780 dst = shift_ir(dst, 1, dst_op->base, inst->extra.size); | 2378 shift_ir(code, 1, dst_op->base, inst->extra.size); |
2781 } else { | 2379 } else { |
2782 dst = shift_irdisp8(dst, 31, dst_op->base, dst_op->disp, inst->extra.size); | 2380 shift_irdisp(code, 31, dst_op->base, dst_op->disp, inst->extra.size); |
2783 dst = shift_irdisp8(dst, 1, dst_op->base, dst_op->disp, inst->extra.size); | 2381 shift_irdisp(code, 1, dst_op->base, dst_op->disp, inst->extra.size); |
2784 } | 2382 } |
2785 | 2383 |
2786 } | 2384 } |
2787 end_off = dst+1; | 2385 end_off = code->cur + 1; |
2788 dst = jmp(dst, dst+2); | 2386 jmp(code, code->cur + 2); |
2789 *norm_shift_off = dst - (norm_shift_off+1); | 2387 *norm_shift_off = code->cur - (norm_shift_off+1); |
2790 if (dst_op->mode == MODE_REG_DIRECT) { | 2388 if (dst_op->mode == MODE_REG_DIRECT) { |
2791 dst = shift_clr(dst, dst_op->base, inst->extra.size); | 2389 shift_clr(code, dst_op->base, inst->extra.size); |
2792 } else { | 2390 } else { |
2793 dst = shift_clrdisp8(dst, dst_op->base, dst_op->disp, inst->extra.size); | 2391 shift_clrdisp(code, dst_op->base, dst_op->disp, inst->extra.size); |
2794 } | 2392 } |
2795 } | 2393 } |
2796 } | 2394 } |
2797 | 2395 |
2798 } | 2396 } |
2799 if (!special && end_off) { | 2397 if (!special && end_off) { |
2800 *end_off = dst - (end_off + 1); | 2398 *end_off = code->cur - (end_off + 1); |
2801 } | 2399 } |
2802 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); | 2400 set_flag_cond(opts, CC_C, FLAG_C); |
2803 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 2401 set_flag_cond(opts, CC_Z, FLAG_Z); |
2804 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 2402 set_flag_cond(opts, CC_S, FLAG_N); |
2805 if (special && end_off) { | 2403 if (special && end_off) { |
2806 *end_off = dst - (end_off + 1); | 2404 *end_off = code->cur - (end_off + 1); |
2807 } | 2405 } |
2808 //set X flag to same as C flag | 2406 //set X flag to same as C flag |
2809 if (opts->flag_regs[FLAG_C] >= 0) { | 2407 if (opts->flag_regs[FLAG_C] >= 0) { |
2810 dst = flag_to_flag(dst, FLAG_C, FLAG_X, opts); | 2408 flag_to_flag(opts, FLAG_C, FLAG_X); |
2811 } else { | 2409 } else { |
2812 dst = set_flag_cond(dst, CC_C, FLAG_X, opts); | 2410 set_flag_cond(opts, CC_C, FLAG_X); |
2813 } | 2411 } |
2814 if (z_off) { | 2412 if (z_off) { |
2815 *z_off = dst - (z_off + 1); | 2413 *z_off = code->cur - (z_off + 1); |
2816 } | 2414 } |
2817 if (inst->op != M68K_ASL) { | 2415 if (inst->op != M68K_ASL) { |
2818 dst = set_flag(dst, 0, FLAG_V, opts); | 2416 set_flag(opts, 0, FLAG_V); |
2819 } | 2417 } |
2820 if (inst->src.addr_mode == MODE_UNUSED) { | 2418 if (inst->src.addr_mode == MODE_UNUSED) { |
2821 dst = m68k_save_result(inst, dst, opts); | 2419 m68k_save_result(inst, opts); |
2822 } | 2420 } |
2823 return dst; | |
2824 } | 2421 } |
2825 | 2422 |
2826 #define BIT_SUPERVISOR 5 | 2423 #define BIT_SUPERVISOR 5 |
2827 | 2424 |
2828 code_ptr translate_m68k(code_ptr dst, m68kinst * inst, x86_68k_options * opts) | 2425 void translate_m68k(x86_68k_options * opts, m68kinst * inst) |
2829 { | 2426 { |
2830 code_ptr end_off, zero_off, norm_off; | 2427 code_ptr end_off, zero_off, norm_off; |
2831 uint8_t dst_reg; | 2428 uint8_t dst_reg; |
2832 dst = check_cycles_int(dst, inst->address, opts); | 2429 code_info *code = &opts->gen.code; |
2430 check_cycles_int(&opts->gen, inst->address); | |
2833 if (inst->op == M68K_MOVE) { | 2431 if (inst->op == M68K_MOVE) { |
2834 return translate_m68k_move(dst, inst, opts); | 2432 return translate_m68k_move(opts, inst); |
2835 } else if(inst->op == M68K_LEA) { | 2433 } else if(inst->op == M68K_LEA) { |
2836 return translate_m68k_lea(dst, inst, opts); | 2434 return translate_m68k_lea(opts, inst); |
2837 } else if(inst->op == M68K_PEA) { | 2435 } else if(inst->op == M68K_PEA) { |
2838 return translate_m68k_pea(dst, inst, opts); | 2436 return translate_m68k_pea(opts, inst); |
2839 } else if(inst->op == M68K_BSR) { | 2437 } else if(inst->op == M68K_BSR) { |
2840 return translate_m68k_bsr(dst, inst, opts); | 2438 return translate_m68k_bsr(opts, inst); |
2841 } else if(inst->op == M68K_BCC) { | 2439 } else if(inst->op == M68K_BCC) { |
2842 return translate_m68k_bcc(dst, inst, opts); | 2440 return translate_m68k_bcc(opts, inst); |
2843 } else if(inst->op == M68K_JMP) { | 2441 } else if(inst->op == M68K_JMP) { |
2844 return translate_m68k_jmp(dst, inst, opts); | 2442 return translate_m68k_jmp_jsr(opts, inst); |
2845 } else if(inst->op == M68K_JSR) { | 2443 } else if(inst->op == M68K_JSR) { |
2846 return translate_m68k_jsr(dst, inst, opts); | 2444 return translate_m68k_jmp_jsr(opts, inst); |
2847 } else if(inst->op == M68K_RTS) { | 2445 } else if(inst->op == M68K_RTS) { |
2848 return translate_m68k_rts(dst, inst, opts); | 2446 return translate_m68k_rts(opts, inst); |
2849 } else if(inst->op == M68K_DBCC) { | 2447 } else if(inst->op == M68K_DBCC) { |
2850 return translate_m68k_dbcc(dst, inst, opts); | 2448 return translate_m68k_dbcc(opts, inst); |
2851 } else if(inst->op == M68K_CLR) { | 2449 } else if(inst->op == M68K_CLR) { |
2852 return translate_m68k_clr(dst, inst, opts); | 2450 return translate_m68k_clr(opts, inst); |
2853 } else if(inst->op == M68K_MOVEM) { | 2451 } else if(inst->op == M68K_MOVEM) { |
2854 return translate_m68k_movem(dst, inst, opts); | 2452 return translate_m68k_movem(opts, inst); |
2855 } else if(inst->op == M68K_LINK) { | 2453 } else if(inst->op == M68K_LINK) { |
2856 return translate_m68k_link(dst, inst, opts); | 2454 return translate_m68k_link(opts, inst); |
2857 } else if(inst->op == M68K_EXT) { | 2455 } else if(inst->op == M68K_EXT) { |
2858 return translate_m68k_ext(dst, inst, opts); | 2456 return translate_m68k_ext(opts, inst); |
2859 } else if(inst->op == M68K_SCC) { | 2457 } else if(inst->op == M68K_SCC) { |
2860 return translate_m68k_scc(dst, inst, opts); | 2458 return translate_m68k_scc(opts, inst); |
2861 } else if(inst->op == M68K_MOVEP) { | 2459 } else if(inst->op == M68K_MOVEP) { |
2862 return translate_m68k_movep(dst, inst, opts); | 2460 return translate_m68k_movep(opts, inst); |
2863 } else if(inst->op == M68K_INVALID) { | 2461 } else if(inst->op == M68K_INVALID) { |
2864 if (inst->src.params.immed == 0x7100) { | 2462 if (inst->src.params.immed == 0x7100) { |
2865 return retn(dst); | 2463 return retn(code); |
2866 } | 2464 } |
2867 dst = mov_ir(dst, inst->address, SCRATCH1, SZ_D); | 2465 mov_ir(code, inst->address, opts->gen.scratch1, SZ_D); |
2868 return call(dst, (code_ptr)m68k_invalid); | 2466 return call(code, (code_ptr)m68k_invalid); |
2869 } else if(inst->op == M68K_CMP) { | 2467 } else if(inst->op == M68K_CMP) { |
2870 return translate_m68k_cmp(dst, inst, opts); | 2468 return translate_m68k_cmp(opts, inst); |
2871 } | 2469 } |
2872 x86_ea src_op, dst_op; | 2470 x86_ea src_op, dst_op; |
2873 if (inst->src.addr_mode != MODE_UNUSED) { | 2471 if (inst->src.addr_mode != MODE_UNUSED) { |
2874 dst = translate_m68k_src(inst, &src_op, dst, opts); | 2472 translate_m68k_src(inst, &src_op, opts); |
2875 } | 2473 } |
2876 if (inst->dst.addr_mode != MODE_UNUSED) { | 2474 if (inst->dst.addr_mode != MODE_UNUSED) { |
2877 dst = translate_m68k_dst(inst, &dst_op, dst, opts, 0); | 2475 translate_m68k_dst(inst, &dst_op, opts, 0); |
2878 } | 2476 } |
2879 uint8_t size; | 2477 uint8_t size; |
2880 switch(inst->op) | 2478 switch(inst->op) |
2881 { | 2479 { |
2882 case M68K_ABCD: | 2480 case M68K_ABCD: |
2883 if (src_op.base != SCRATCH2) { | 2481 if (src_op.base != opts->gen.scratch2) { |
2884 if (src_op.mode == MODE_REG_DIRECT) { | 2482 if (src_op.mode == MODE_REG_DIRECT) { |
2885 dst = mov_rr(dst, src_op.base, SCRATCH2, SZ_B); | 2483 mov_rr(code, src_op.base, opts->gen.scratch2, SZ_B); |
2886 } else { | 2484 } else { |
2887 dst = mov_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH2, SZ_B); | 2485 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, SZ_B); |
2888 } | 2486 } |
2889 } | 2487 } |
2890 if (dst_op.base != SCRATCH1) { | 2488 if (dst_op.base != opts->gen.scratch1) { |
2891 if (dst_op.mode == MODE_REG_DIRECT) { | 2489 if (dst_op.mode == MODE_REG_DIRECT) { |
2892 dst = mov_rr(dst, dst_op.base, SCRATCH1, SZ_B); | 2490 mov_rr(code, dst_op.base, opts->gen.scratch1, SZ_B); |
2893 } else { | 2491 } else { |
2894 dst = mov_rdisp8r(dst, dst_op.base, dst_op.disp, SCRATCH1, SZ_B); | 2492 mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, SZ_B); |
2895 } | 2493 } |
2896 } | 2494 } |
2897 dst = flag_to_carry(dst, FLAG_X, opts); | 2495 flag_to_carry(opts, FLAG_X); |
2898 dst = jcc(dst, CC_NC, dst+5); | 2496 jcc(code, CC_NC, code->cur + 5); |
2899 dst = add_ir(dst, 1, SCRATCH1, SZ_B); | 2497 add_ir(code, 1, opts->gen.scratch1, SZ_B); |
2900 dst = call(dst, (code_ptr)bcd_add); | 2498 call(code, (code_ptr)bcd_add); |
2901 dst = reg_to_flag(dst, CH, FLAG_C, opts); | 2499 reg_to_flag(opts, CH, FLAG_C); |
2902 dst = reg_to_flag(dst, CH, FLAG_X, opts); | 2500 reg_to_flag(opts, CH, FLAG_X); |
2903 dst = cmp_ir(dst, 0, SCRATCH1, SZ_B); | 2501 cmp_ir(code, 0, opts->gen.scratch1, SZ_B); |
2904 dst = jcc(dst, CC_Z, dst+4); | 2502 jcc(code, CC_Z, code->cur + 4); |
2905 dst = set_flag(dst, 0, FLAG_Z, opts); | 2503 set_flag(opts, 0, FLAG_Z); |
2906 if (dst_op.base != SCRATCH1) { | 2504 if (dst_op.base != opts->gen.scratch1) { |
2907 if (dst_op.mode == MODE_REG_DIRECT) { | 2505 if (dst_op.mode == MODE_REG_DIRECT) { |
2908 dst = mov_rr(dst, SCRATCH1, dst_op.base, SZ_B); | 2506 mov_rr(code, opts->gen.scratch1, dst_op.base, SZ_B); |
2909 } else { | 2507 } else { |
2910 dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, SZ_B); | 2508 mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, SZ_B); |
2911 } | 2509 } |
2912 } | 2510 } |
2913 dst = m68k_save_result(inst, dst, opts); | 2511 m68k_save_result(inst, opts); |
2914 break; | 2512 break; |
2915 case M68K_ADD: | 2513 case M68K_ADD: |
2916 dst = cycles(dst, BUS); | 2514 cycles(&opts->gen, BUS); |
2917 size = inst->dst.addr_mode == MODE_AREG ? OPSIZE_LONG : inst->extra.size; | 2515 size = inst->dst.addr_mode == MODE_AREG ? OPSIZE_LONG : inst->extra.size; |
2918 if (src_op.mode == MODE_REG_DIRECT) { | 2516 if (src_op.mode == MODE_REG_DIRECT) { |
2919 if (dst_op.mode == MODE_REG_DIRECT) { | 2517 if (dst_op.mode == MODE_REG_DIRECT) { |
2920 dst = add_rr(dst, src_op.base, dst_op.base, size); | 2518 add_rr(code, src_op.base, dst_op.base, size); |
2921 } else { | 2519 } else { |
2922 dst = add_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, size); | 2520 add_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, size); |
2923 } | 2521 } |
2924 } else if (src_op.mode == MODE_REG_DISPLACE8) { | 2522 } else if (src_op.mode == MODE_REG_DISPLACE8) { |
2925 dst = add_rdisp8r(dst, src_op.base, src_op.disp, dst_op.base, size); | 2523 add_rdispr(code, src_op.base, src_op.disp, dst_op.base, size); |
2926 } else { | 2524 } else { |
2927 if (dst_op.mode == MODE_REG_DIRECT) { | 2525 if (dst_op.mode == MODE_REG_DIRECT) { |
2928 dst = add_ir(dst, src_op.disp, dst_op.base, size); | 2526 add_ir(code, src_op.disp, dst_op.base, size); |
2929 } else { | 2527 } else { |
2930 dst = add_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, size); | 2528 add_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, size); |
2931 } | 2529 } |
2932 } | 2530 } |
2933 if (inst->dst.addr_mode != MODE_AREG) { | 2531 if (inst->dst.addr_mode != MODE_AREG) { |
2934 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); | 2532 set_flag_cond(opts, CC_C, FLAG_C); |
2935 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 2533 set_flag_cond(opts, CC_Z, FLAG_Z); |
2936 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 2534 set_flag_cond(opts, CC_S, FLAG_N); |
2937 dst = set_flag_cond(dst, CC_O, FLAG_V, opts); | 2535 set_flag_cond(opts, CC_O, FLAG_V); |
2938 if (opts->flag_regs[FLAG_C] >= 0) { | 2536 if (opts->flag_regs[FLAG_C] >= 0) { |
2939 dst = flag_to_flag(dst, FLAG_C, FLAG_X, opts); | 2537 flag_to_flag(opts, FLAG_C, FLAG_X); |
2940 } else { | 2538 } else { |
2941 dst = set_flag_cond(dst, CC_C, FLAG_X, opts); | 2539 set_flag_cond(opts, CC_C, FLAG_X); |
2942 } | 2540 } |
2943 } | 2541 } |
2944 dst = m68k_save_result(inst, dst, opts); | 2542 m68k_save_result(inst, opts); |
2945 break; | 2543 break; |
2946 case M68K_ADDX: { | 2544 case M68K_ADDX: { |
2947 dst = cycles(dst, BUS); | 2545 cycles(&opts->gen, BUS); |
2948 dst = flag_to_carry(dst, FLAG_X, opts); | 2546 flag_to_carry(opts, FLAG_X); |
2949 if (src_op.mode == MODE_REG_DIRECT) { | 2547 if (src_op.mode == MODE_REG_DIRECT) { |
2950 if (dst_op.mode == MODE_REG_DIRECT) { | 2548 if (dst_op.mode == MODE_REG_DIRECT) { |
2951 dst = adc_rr(dst, src_op.base, dst_op.base, inst->extra.size); | 2549 adc_rr(code, src_op.base, dst_op.base, inst->extra.size); |
2952 } else { | 2550 } else { |
2953 dst = adc_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, inst->extra.size); | 2551 adc_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, inst->extra.size); |
2954 } | 2552 } |
2955 } else if (src_op.mode == MODE_REG_DISPLACE8) { | 2553 } else if (src_op.mode == MODE_REG_DISPLACE8) { |
2956 dst = adc_rdisp8r(dst, src_op.base, src_op.disp, dst_op.base, inst->extra.size); | 2554 adc_rdispr(code, src_op.base, src_op.disp, dst_op.base, inst->extra.size); |
2957 } else { | 2555 } else { |
2958 if (dst_op.mode == MODE_REG_DIRECT) { | 2556 if (dst_op.mode == MODE_REG_DIRECT) { |
2959 dst = adc_ir(dst, src_op.disp, dst_op.base, inst->extra.size); | 2557 adc_ir(code, src_op.disp, dst_op.base, inst->extra.size); |
2960 } else { | 2558 } else { |
2961 dst = adc_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 2559 adc_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
2962 } | 2560 } |
2963 } | 2561 } |
2964 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); | 2562 set_flag_cond(opts, CC_C, FLAG_C); |
2965 | 2563 |
2966 code_ptr after_flag_set = dst+1; | 2564 check_alloc_code(code, 2*MAX_INST_LEN); |
2967 dst = jcc(dst, CC_Z, dst+2); | 2565 code_ptr after_flag_set = code->cur + 1; |
2968 dst = set_flag(dst, 0, FLAG_Z, opts); | 2566 jcc(code, CC_Z, code->cur + 2); |
2969 *after_flag_set = dst - (after_flag_set+1); | 2567 set_flag(opts, 0, FLAG_Z); |
2970 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 2568 *after_flag_set = code->cur - (after_flag_set+1); |
2971 dst = set_flag_cond(dst, CC_O, FLAG_V, opts); | 2569 set_flag_cond(opts, CC_S, FLAG_N); |
2570 set_flag_cond(opts, CC_O, FLAG_V); | |
2972 if (opts->flag_regs[FLAG_C] >= 0) { | 2571 if (opts->flag_regs[FLAG_C] >= 0) { |
2973 dst = flag_to_flag(dst, FLAG_C, FLAG_X, opts); | 2572 flag_to_flag(opts, FLAG_C, FLAG_X); |
2974 } else { | 2573 } else { |
2975 dst = set_flag_cond(dst, CC_C, FLAG_X, opts); | 2574 set_flag_cond(opts, CC_C, FLAG_X); |
2976 } | 2575 } |
2977 dst = m68k_save_result(inst, dst, opts); | 2576 m68k_save_result(inst, opts); |
2978 break; | 2577 break; |
2979 } | 2578 } |
2980 case M68K_AND: | 2579 case M68K_AND: |
2981 dst = cycles(dst, BUS); | 2580 cycles(&opts->gen, BUS); |
2982 if (src_op.mode == MODE_REG_DIRECT) { | 2581 if (src_op.mode == MODE_REG_DIRECT) { |
2983 if (dst_op.mode == MODE_REG_DIRECT) { | 2582 if (dst_op.mode == MODE_REG_DIRECT) { |
2984 dst = and_rr(dst, src_op.base, dst_op.base, inst->extra.size); | 2583 and_rr(code, src_op.base, dst_op.base, inst->extra.size); |
2985 } else { | 2584 } else { |
2986 dst = and_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, inst->extra.size); | 2585 and_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, inst->extra.size); |
2987 } | 2586 } |
2988 } else if (src_op.mode == MODE_REG_DISPLACE8) { | 2587 } else if (src_op.mode == MODE_REG_DISPLACE8) { |
2989 dst = and_rdisp8r(dst, src_op.base, src_op.disp, dst_op.base, inst->extra.size); | 2588 and_rdispr(code, src_op.base, src_op.disp, dst_op.base, inst->extra.size); |
2990 } else { | 2589 } else { |
2991 if (dst_op.mode == MODE_REG_DIRECT) { | 2590 if (dst_op.mode == MODE_REG_DIRECT) { |
2992 dst = and_ir(dst, src_op.disp, dst_op.base, inst->extra.size); | 2591 and_ir(code, src_op.disp, dst_op.base, inst->extra.size); |
2993 } else { | 2592 } else { |
2994 dst = and_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 2593 and_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
2995 } | 2594 } |
2996 } | 2595 } |
2997 dst = set_flag(dst, 0, FLAG_C, opts); | 2596 set_flag(opts, 0, FLAG_C); |
2998 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 2597 set_flag_cond(opts, CC_Z, FLAG_Z); |
2999 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 2598 set_flag_cond(opts, CC_S, FLAG_N); |
3000 dst = set_flag(dst, 0, FLAG_V, opts); | 2599 set_flag(opts, 0, FLAG_V); |
3001 dst = m68k_save_result(inst, dst, opts); | 2600 m68k_save_result(inst, opts); |
3002 break; | 2601 break; |
3003 case M68K_ANDI_CCR: | 2602 case M68K_ANDI_CCR: |
3004 case M68K_ANDI_SR: | 2603 case M68K_ANDI_SR: |
3005 dst = cycles(dst, 20); | 2604 cycles(&opts->gen, 20); |
3006 //TODO: If ANDI to SR, trap if not in supervisor mode | 2605 //TODO: If ANDI to SR, trap if not in supervisor mode |
3007 if (!(inst->src.params.immed & 0x1)) { | 2606 if (!(inst->src.params.immed & 0x1)) { |
3008 dst = set_flag(dst, 0, FLAG_C, opts); | 2607 set_flag(opts, 0, FLAG_C); |
3009 } | 2608 } |
3010 if (!(inst->src.params.immed & 0x2)) { | 2609 if (!(inst->src.params.immed & 0x2)) { |
3011 dst = set_flag(dst, 0, FLAG_V, opts); | 2610 set_flag(opts, 0, FLAG_V); |
3012 } | 2611 } |
3013 if (!(inst->src.params.immed & 0x4)) { | 2612 if (!(inst->src.params.immed & 0x4)) { |
3014 dst = set_flag(dst, 0, FLAG_Z, opts); | 2613 set_flag(opts, 0, FLAG_Z); |
3015 } | 2614 } |
3016 if (!(inst->src.params.immed & 0x8)) { | 2615 if (!(inst->src.params.immed & 0x8)) { |
3017 dst = set_flag(dst, 0, FLAG_N, opts); | 2616 set_flag(opts, 0, FLAG_N); |
3018 } | 2617 } |
3019 if (!(inst->src.params.immed & 0x10)) { | 2618 if (!(inst->src.params.immed & 0x10)) { |
3020 dst = set_flag(dst, 0, FLAG_X, opts); | 2619 set_flag(opts, 0, FLAG_X); |
3021 } | 2620 } |
3022 if (inst->op == M68K_ANDI_SR) { | 2621 if (inst->op == M68K_ANDI_SR) { |
3023 dst = and_irdisp8(dst, inst->src.params.immed >> 8, CONTEXT, offsetof(m68k_context, status), SZ_B); | 2622 and_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
3024 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { | 2623 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { |
3025 //leave supervisor mode | 2624 //leave supervisor mode |
3026 dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_B); | 2625 mov_rr(code, opts->aregs[7], opts->gen.scratch1, SZ_B); |
3027 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->aregs[7], SZ_B); | 2626 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->aregs[7], SZ_B); |
3028 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_B); | 2627 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_B); |
3029 } | 2628 } |
3030 if (inst->src.params.immed & 0x700) { | 2629 if (inst->src.params.immed & 0x700) { |
3031 dst = call(dst, opts->do_sync); | 2630 call(code, opts->do_sync); |
3032 } | 2631 } |
3033 } | 2632 } |
3034 break; | 2633 break; |
3035 case M68K_ASL: | 2634 case M68K_ASL: |
3036 case M68K_LSL: | 2635 case M68K_LSL: |
3037 dst = translate_shift(dst, inst, &src_op, &dst_op, opts, shl_ir, shl_irdisp8, shl_clr, shl_clrdisp8, shr_ir, shr_irdisp8); | 2636 translate_shift(opts, inst, &src_op, &dst_op, shl_ir, shl_irdisp, shl_clr, shl_clrdisp, shr_ir, shr_irdisp); |
3038 break; | 2637 break; |
3039 case M68K_ASR: | 2638 case M68K_ASR: |
3040 dst = translate_shift(dst, inst, &src_op, &dst_op, opts, sar_ir, sar_irdisp8, sar_clr, sar_clrdisp8, NULL, NULL); | 2639 translate_shift(opts, inst, &src_op, &dst_op, sar_ir, sar_irdisp, sar_clr, sar_clrdisp, NULL, NULL); |
3041 break; | 2640 break; |
3042 case M68K_LSR: | 2641 case M68K_LSR: |
3043 dst = translate_shift(dst, inst, &src_op, &dst_op, opts, shr_ir, shr_irdisp8, shr_clr, shr_clrdisp8, shl_ir, shl_irdisp8); | 2642 translate_shift(opts, inst, &src_op, &dst_op, shr_ir, shr_irdisp, shr_clr, shr_clrdisp, shl_ir, shl_irdisp); |
3044 break; | 2643 break; |
3045 case M68K_BCHG: | 2644 case M68K_BCHG: |
3046 case M68K_BCLR: | 2645 case M68K_BCLR: |
3047 case M68K_BSET: | 2646 case M68K_BSET: |
3048 case M68K_BTST: | 2647 case M68K_BTST: |
3049 dst = cycles(dst, inst->extra.size == OPSIZE_BYTE ? 4 : ( | 2648 cycles(&opts->gen, inst->extra.size == OPSIZE_BYTE ? 4 : ( |
3050 inst->op == M68K_BTST ? 6 : (inst->op == M68K_BCLR ? 10 : 8)) | 2649 inst->op == M68K_BTST ? 6 : (inst->op == M68K_BCLR ? 10 : 8)) |
3051 ); | 2650 ); |
3052 if (src_op.mode == MODE_IMMED) { | 2651 if (src_op.mode == MODE_IMMED) { |
3053 if (inst->extra.size == OPSIZE_BYTE) { | 2652 if (inst->extra.size == OPSIZE_BYTE) { |
3054 src_op.disp &= 0x7; | 2653 src_op.disp &= 0x7; |
3055 } | 2654 } |
3056 if (inst->op == M68K_BTST) { | 2655 if (inst->op == M68K_BTST) { |
3057 if (dst_op.mode == MODE_REG_DIRECT) { | 2656 if (dst_op.mode == MODE_REG_DIRECT) { |
3058 dst = bt_ir(dst, src_op.disp, dst_op.base, inst->extra.size); | 2657 bt_ir(code, src_op.disp, dst_op.base, inst->extra.size); |
3059 } else { | 2658 } else { |
3060 dst = bt_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 2659 bt_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
3061 } | 2660 } |
3062 } else if (inst->op == M68K_BSET) { | 2661 } else if (inst->op == M68K_BSET) { |
3063 if (dst_op.mode == MODE_REG_DIRECT) { | 2662 if (dst_op.mode == MODE_REG_DIRECT) { |
3064 dst = bts_ir(dst, src_op.disp, dst_op.base, inst->extra.size); | 2663 bts_ir(code, src_op.disp, dst_op.base, inst->extra.size); |
3065 } else { | 2664 } else { |
3066 dst = bts_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 2665 bts_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
3067 } | 2666 } |
3068 } else if (inst->op == M68K_BCLR) { | 2667 } else if (inst->op == M68K_BCLR) { |
3069 if (dst_op.mode == MODE_REG_DIRECT) { | 2668 if (dst_op.mode == MODE_REG_DIRECT) { |
3070 dst = btr_ir(dst, src_op.disp, dst_op.base, inst->extra.size); | 2669 btr_ir(code, src_op.disp, dst_op.base, inst->extra.size); |
3071 } else { | 2670 } else { |
3072 dst = btr_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 2671 btr_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
3073 } | 2672 } |
3074 } else { | 2673 } else { |
3075 if (dst_op.mode == MODE_REG_DIRECT) { | 2674 if (dst_op.mode == MODE_REG_DIRECT) { |
3076 dst = btc_ir(dst, src_op.disp, dst_op.base, inst->extra.size); | 2675 btc_ir(code, src_op.disp, dst_op.base, inst->extra.size); |
3077 } else { | 2676 } else { |
3078 dst = btc_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 2677 btc_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
3079 } | 2678 } |
3080 } | 2679 } |
3081 } else { | 2680 } else { |
3082 if (src_op.mode == MODE_REG_DISPLACE8 || (inst->dst.addr_mode != MODE_REG && src_op.base != SCRATCH1 && src_op.base != SCRATCH2)) { | 2681 if (src_op.mode == MODE_REG_DISPLACE8 || (inst->dst.addr_mode != MODE_REG && src_op.base != opts->gen.scratch1 && src_op.base != opts->gen.scratch2)) { |
3083 if (dst_op.base == SCRATCH1) { | 2682 if (dst_op.base == opts->gen.scratch1) { |
3084 dst = push_r(dst, SCRATCH2); | 2683 push_r(code, opts->gen.scratch2); |
3085 if (src_op.mode == MODE_REG_DIRECT) { | 2684 if (src_op.mode == MODE_REG_DIRECT) { |
3086 dst = mov_rr(dst, src_op.base, SCRATCH2, SZ_B); | 2685 mov_rr(code, src_op.base, opts->gen.scratch2, SZ_B); |
3087 } else { | 2686 } else { |
3088 dst = mov_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH2, SZ_B); | 2687 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, SZ_B); |
3089 } | 2688 } |
3090 src_op.base = SCRATCH2; | 2689 src_op.base = opts->gen.scratch2; |
3091 } else { | 2690 } else { |
3092 if (src_op.mode == MODE_REG_DIRECT) { | 2691 if (src_op.mode == MODE_REG_DIRECT) { |
3093 dst = mov_rr(dst, src_op.base, SCRATCH1, SZ_B); | 2692 mov_rr(code, src_op.base, opts->gen.scratch1, SZ_B); |
3094 } else { | 2693 } else { |
3095 dst = mov_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH1, SZ_B); | 2694 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_B); |
3096 } | 2695 } |
3097 src_op.base = SCRATCH1; | 2696 src_op.base = opts->gen.scratch1; |
3098 } | 2697 } |
3099 } | 2698 } |
3100 uint8_t size = inst->extra.size; | 2699 uint8_t size = inst->extra.size; |
3101 if (dst_op.mode == MODE_REG_DISPLACE8) { | 2700 if (dst_op.mode == MODE_REG_DISPLACE8) { |
3102 if (src_op.base != SCRATCH1 && src_op.base != SCRATCH2) { | 2701 if (src_op.base != opts->gen.scratch1 && src_op.base != opts->gen.scratch2) { |
3103 if (src_op.mode == MODE_REG_DIRECT) { | 2702 if (src_op.mode == MODE_REG_DIRECT) { |
3104 dst = mov_rr(dst, src_op.base, SCRATCH1, SZ_D); | 2703 mov_rr(code, src_op.base, opts->gen.scratch1, SZ_D); |
3105 } else { | 2704 } else { |
3106 dst = mov_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH1, SZ_D); | 2705 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_D); |
3107 src_op.mode = MODE_REG_DIRECT; | 2706 src_op.mode = MODE_REG_DIRECT; |
3108 } | 2707 } |
3109 src_op.base = SCRATCH1; | 2708 src_op.base = opts->gen.scratch1; |
3110 } | 2709 } |
3111 //b### with register destination is modulo 32 | 2710 //b### with register destination is modulo 32 |
3112 //x86 with a memory destination isn't modulo anything | 2711 //x86 with a memory destination isn't modulo anything |
3113 //so use an and here to force the value to be modulo 32 | 2712 //so use an and here to force the value to be modulo 32 |
3114 dst = and_ir(dst, 31, SCRATCH1, SZ_D); | 2713 and_ir(code, 31, opts->gen.scratch1, SZ_D); |
3115 } else if(inst->dst.addr_mode != MODE_REG) { | 2714 } else if(inst->dst.addr_mode != MODE_REG) { |
3116 //b### with memory destination is modulo 8 | 2715 //b### with memory destination is modulo 8 |
3117 //x86-64 doesn't support 8-bit bit operations | 2716 //x86-64 doesn't support 8-bit bit operations |
3118 //so we fake it by forcing the bit number to be modulo 8 | 2717 //so we fake it by forcing the bit number to be modulo 8 |
3119 dst = and_ir(dst, 7, src_op.base, SZ_D); | 2718 and_ir(code, 7, src_op.base, SZ_D); |
3120 size = SZ_D; | 2719 size = SZ_D; |
3121 } | 2720 } |
3122 if (inst->op == M68K_BTST) { | 2721 if (inst->op == M68K_BTST) { |
3123 if (dst_op.mode == MODE_REG_DIRECT) { | 2722 if (dst_op.mode == MODE_REG_DIRECT) { |
3124 dst = bt_rr(dst, src_op.base, dst_op.base, size); | 2723 bt_rr(code, src_op.base, dst_op.base, size); |
3125 } else { | 2724 } else { |
3126 dst = bt_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, size); | 2725 bt_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, size); |
3127 } | 2726 } |
3128 } else if (inst->op == M68K_BSET) { | 2727 } else if (inst->op == M68K_BSET) { |
3129 if (dst_op.mode == MODE_REG_DIRECT) { | 2728 if (dst_op.mode == MODE_REG_DIRECT) { |
3130 dst = bts_rr(dst, src_op.base, dst_op.base, size); | 2729 bts_rr(code, src_op.base, dst_op.base, size); |
3131 } else { | 2730 } else { |
3132 dst = bts_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, size); | 2731 bts_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, size); |
3133 } | 2732 } |
3134 } else if (inst->op == M68K_BCLR) { | 2733 } else if (inst->op == M68K_BCLR) { |
3135 if (dst_op.mode == MODE_REG_DIRECT) { | 2734 if (dst_op.mode == MODE_REG_DIRECT) { |
3136 dst = btr_rr(dst, src_op.base, dst_op.base, size); | 2735 btr_rr(code, src_op.base, dst_op.base, size); |
3137 } else { | 2736 } else { |
3138 dst = btr_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, size); | 2737 btr_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, size); |
3139 } | 2738 } |
3140 } else { | 2739 } else { |
3141 if (dst_op.mode == MODE_REG_DIRECT) { | 2740 if (dst_op.mode == MODE_REG_DIRECT) { |
3142 dst = btc_rr(dst, src_op.base, dst_op.base, size); | 2741 btc_rr(code, src_op.base, dst_op.base, size); |
3143 } else { | 2742 } else { |
3144 dst = btc_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, size); | 2743 btc_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, size); |
3145 } | 2744 } |
3146 } | 2745 } |
3147 if (src_op.base == SCRATCH2) { | 2746 if (src_op.base == opts->gen.scratch2) { |
3148 dst = pop_r(dst, SCRATCH2); | 2747 pop_r(code, opts->gen.scratch2); |
3149 } | 2748 } |
3150 } | 2749 } |
3151 //x86 sets the carry flag to the value of the bit tested | 2750 //x86 sets the carry flag to the value of the bit tested |
3152 //68K sets the zero flag to the complement of the bit tested | 2751 //68K sets the zero flag to the complement of the bit tested |
3153 dst = set_flag_cond(dst, CC_NC, FLAG_Z, opts); | 2752 set_flag_cond(opts, CC_NC, FLAG_Z); |
3154 if (inst->op != M68K_BTST) { | 2753 if (inst->op != M68K_BTST) { |
3155 dst = m68k_save_result(inst, dst, opts); | 2754 m68k_save_result(inst, opts); |
3156 } | 2755 } |
3157 break; | 2756 break; |
3158 case M68K_CHK: | 2757 case M68K_CHK: |
3159 { | 2758 { |
3160 dst = cycles(dst, 6); | 2759 cycles(&opts->gen, 6); |
3161 if (dst_op.mode == MODE_REG_DIRECT) { | 2760 if (dst_op.mode == MODE_REG_DIRECT) { |
3162 dst = cmp_ir(dst, 0, dst_op.base, inst->extra.size); | 2761 cmp_ir(code, 0, dst_op.base, inst->extra.size); |
3163 } else { | 2762 } else { |
3164 dst = cmp_irdisp8(dst, 0, dst_op.base, dst_op.disp, inst->extra.size); | 2763 cmp_irdisp(code, 0, dst_op.base, dst_op.disp, inst->extra.size); |
3165 } | 2764 } |
3166 uint32_t isize; | 2765 uint32_t isize; |
3167 switch(inst->src.addr_mode) | 2766 switch(inst->src.addr_mode) |
3168 { | 2767 { |
3169 case MODE_AREG_DISPLACE: | 2768 case MODE_AREG_DISPLACE: |
3178 isize = 6; | 2777 isize = 6; |
3179 break; | 2778 break; |
3180 default: | 2779 default: |
3181 isize = 2; | 2780 isize = 2; |
3182 } | 2781 } |
3183 code_ptr passed = dst+1; | 2782 //make sure we won't start a new chunk in the middle of these branches |
3184 dst = jcc(dst, CC_GE, dst+2); | 2783 check_alloc_code(code, MAX_INST_LEN * 11); |
3185 dst = set_flag(dst, 1, FLAG_N, opts); | 2784 code_ptr passed = code->cur + 1; |
3186 dst = mov_ir(dst, VECTOR_CHK, SCRATCH2, SZ_D); | 2785 jcc(code, CC_GE, code->cur + 2); |
3187 dst = mov_ir(dst, inst->address+isize, SCRATCH1, SZ_D); | 2786 set_flag(opts, 1, FLAG_N); |
3188 dst = jmp(dst, opts->trap); | 2787 mov_ir(code, VECTOR_CHK, opts->gen.scratch2, SZ_D); |
3189 *passed = dst - (passed+1); | 2788 mov_ir(code, inst->address+isize, opts->gen.scratch1, SZ_D); |
2789 jmp(code, opts->trap); | |
2790 *passed = code->cur - (passed+1); | |
3190 if (dst_op.mode == MODE_REG_DIRECT) { | 2791 if (dst_op.mode == MODE_REG_DIRECT) { |
3191 if (src_op.mode == MODE_REG_DIRECT) { | 2792 if (src_op.mode == MODE_REG_DIRECT) { |
3192 dst = cmp_rr(dst, src_op.base, dst_op.base, inst->extra.size); | 2793 cmp_rr(code, src_op.base, dst_op.base, inst->extra.size); |
3193 } else if(src_op.mode == MODE_REG_DISPLACE8) { | 2794 } else if(src_op.mode == MODE_REG_DISPLACE8) { |
3194 dst = cmp_rdisp8r(dst, src_op.base, src_op.disp, dst_op.base, inst->extra.size); | 2795 cmp_rdispr(code, src_op.base, src_op.disp, dst_op.base, inst->extra.size); |
3195 } else { | 2796 } else { |
3196 dst = cmp_ir(dst, src_op.disp, dst_op.base, inst->extra.size); | 2797 cmp_ir(code, src_op.disp, dst_op.base, inst->extra.size); |
3197 } | 2798 } |
3198 } else if(dst_op.mode == MODE_REG_DISPLACE8) { | 2799 } else if(dst_op.mode == MODE_REG_DISPLACE8) { |
3199 if (src_op.mode == MODE_REG_DIRECT) { | 2800 if (src_op.mode == MODE_REG_DIRECT) { |
3200 dst = cmp_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, inst->extra.size); | 2801 cmp_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, inst->extra.size); |
3201 } else { | 2802 } else { |
3202 dst = cmp_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 2803 cmp_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
3203 } | 2804 } |
3204 } | 2805 } |
3205 passed = dst+1; | 2806 passed = code->cur + 1; |
3206 dst = jcc(dst, CC_LE, dst+2); | 2807 jcc(code, CC_LE, code->cur + 2); |
3207 dst = set_flag(dst, 0, FLAG_N, opts); | 2808 set_flag(opts, 0, FLAG_N); |
3208 dst = mov_ir(dst, VECTOR_CHK, SCRATCH2, SZ_D); | 2809 mov_ir(code, VECTOR_CHK, opts->gen.scratch2, SZ_D); |
3209 dst = mov_ir(dst, inst->address+isize, SCRATCH1, SZ_D); | 2810 mov_ir(code, inst->address+isize, opts->gen.scratch1, SZ_D); |
3210 dst = jmp(dst, opts->trap); | 2811 jmp(code, opts->trap); |
3211 *passed = dst - (passed+1); | 2812 *passed = code->cur - (passed+1); |
3212 dst = cycles(dst, 4); | 2813 cycles(&opts->gen, 4); |
3213 break; | 2814 break; |
3214 } | 2815 } |
3215 case M68K_DIVS: | 2816 case M68K_DIVS: |
3216 case M68K_DIVU: | 2817 case M68K_DIVU: |
3217 { | 2818 { |
2819 check_alloc_code(code, MAX_NATIVE_SIZE); | |
3218 //TODO: cycle exact division | 2820 //TODO: cycle exact division |
3219 dst = cycles(dst, inst->op == M68K_DIVS ? 158 : 140); | 2821 cycles(&opts->gen, inst->op == M68K_DIVS ? 158 : 140); |
3220 dst = set_flag(dst, 0, FLAG_C, opts); | 2822 set_flag(opts, 0, FLAG_C); |
3221 dst = push_r(dst, RDX); | 2823 push_r(code, RDX); |
3222 dst = push_r(dst, RAX); | 2824 push_r(code, RAX); |
3223 if (dst_op.mode == MODE_REG_DIRECT) { | 2825 if (dst_op.mode == MODE_REG_DIRECT) { |
3224 dst = mov_rr(dst, dst_op.base, RAX, SZ_D); | 2826 mov_rr(code, dst_op.base, RAX, SZ_D); |
3225 } else { | 2827 } else { |
3226 dst = mov_rdisp8r(dst, dst_op.base, dst_op.disp, RAX, SZ_D); | 2828 mov_rdispr(code, dst_op.base, dst_op.disp, RAX, SZ_D); |
3227 } | 2829 } |
3228 if (src_op.mode == MODE_IMMED) { | 2830 if (src_op.mode == MODE_IMMED) { |
3229 dst = mov_ir(dst, (src_op.disp & 0x8000) && inst->op == M68K_DIVS ? src_op.disp | 0xFFFF0000 : src_op.disp, SCRATCH2, SZ_D); | 2831 mov_ir(code, (src_op.disp & 0x8000) && inst->op == M68K_DIVS ? src_op.disp | 0xFFFF0000 : src_op.disp, opts->gen.scratch2, SZ_D); |
3230 } else if (src_op.mode == MODE_REG_DIRECT) { | 2832 } else if (src_op.mode == MODE_REG_DIRECT) { |
3231 if (inst->op == M68K_DIVS) { | 2833 if (inst->op == M68K_DIVS) { |
3232 dst = movsx_rr(dst, src_op.base, SCRATCH2, SZ_W, SZ_D); | 2834 movsx_rr(code, src_op.base, opts->gen.scratch2, SZ_W, SZ_D); |
3233 } else { | 2835 } else { |
3234 dst = movzx_rr(dst, src_op.base, SCRATCH2, SZ_W, SZ_D); | 2836 movzx_rr(code, src_op.base, opts->gen.scratch2, SZ_W, SZ_D); |
3235 } | 2837 } |
3236 } else if (src_op.mode == MODE_REG_DISPLACE8) { | 2838 } else if (src_op.mode == MODE_REG_DISPLACE8) { |
3237 if (inst->op == M68K_DIVS) { | 2839 if (inst->op == M68K_DIVS) { |
3238 dst = movsx_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH2, SZ_W, SZ_D); | 2840 movsx_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, SZ_W, SZ_D); |
3239 } else { | 2841 } else { |
3240 dst = movzx_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH2, SZ_W, SZ_D); | 2842 movzx_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, SZ_W, SZ_D); |
3241 } | 2843 } |
3242 } | 2844 } |
3243 dst = cmp_ir(dst, 0, SCRATCH2, SZ_D); | 2845 cmp_ir(code, 0, opts->gen.scratch2, SZ_D); |
3244 code_ptr not_zero = dst+1; | 2846 check_alloc_code(code, 6*MAX_INST_LEN); |
3245 dst = jcc(dst, CC_NZ, dst+2); | 2847 code_ptr not_zero = code->cur + 1; |
3246 dst = pop_r(dst, RAX); | 2848 jcc(code, CC_NZ, code->cur + 2); |
3247 dst = pop_r(dst, RDX); | 2849 pop_r(code, RAX); |
3248 dst = mov_ir(dst, VECTOR_INT_DIV_ZERO, SCRATCH2, SZ_D); | 2850 pop_r(code, RDX); |
3249 dst = mov_ir(dst, inst->address+2, SCRATCH1, SZ_D); | 2851 mov_ir(code, VECTOR_INT_DIV_ZERO, opts->gen.scratch2, SZ_D); |
3250 dst = jmp(dst, opts->trap); | 2852 mov_ir(code, inst->address+2, opts->gen.scratch1, SZ_D); |
3251 *not_zero = dst - (not_zero+1); | 2853 jmp(code, opts->trap); |
2854 *not_zero = code->cur - (not_zero+1); | |
3252 if (inst->op == M68K_DIVS) { | 2855 if (inst->op == M68K_DIVS) { |
3253 dst = cdq(dst); | 2856 cdq(code); |
3254 } else { | 2857 } else { |
3255 dst = xor_rr(dst, RDX, RDX, SZ_D); | 2858 xor_rr(code, RDX, RDX, SZ_D); |
3256 } | 2859 } |
3257 if (inst->op == M68K_DIVS) { | 2860 if (inst->op == M68K_DIVS) { |
3258 dst = idiv_r(dst, SCRATCH2, SZ_D); | 2861 idiv_r(code, opts->gen.scratch2, SZ_D); |
3259 } else { | 2862 } else { |
3260 dst = div_r(dst, SCRATCH2, SZ_D); | 2863 div_r(code, opts->gen.scratch2, SZ_D); |
3261 } | 2864 } |
3262 code_ptr skip_sec_check; | 2865 code_ptr skip_sec_check; |
3263 if (inst->op == M68K_DIVS) { | 2866 if (inst->op == M68K_DIVS) { |
3264 dst = cmp_ir(dst, 0x8000, RAX, SZ_D); | 2867 cmp_ir(code, 0x8000, RAX, SZ_D); |
3265 skip_sec_check = dst + 1; | 2868 skip_sec_check = code->cur + 1; |
3266 dst = jcc(dst, CC_GE, dst+2); | 2869 jcc(code, CC_GE, code->cur + 2); |
3267 dst = cmp_ir(dst, -0x8000, RAX, SZ_D); | 2870 cmp_ir(code, -0x8000, RAX, SZ_D); |
3268 norm_off = dst+1; | 2871 norm_off = code->cur + 1; |
3269 dst = jcc(dst, CC_L, dst+2); | 2872 jcc(code, CC_L, code->cur + 2); |
3270 } else { | 2873 } else { |
3271 dst = cmp_ir(dst, 0x10000, RAX, SZ_D); | 2874 cmp_ir(code, 0x10000, RAX, SZ_D); |
3272 norm_off = dst+1; | 2875 norm_off = code->cur + 1; |
3273 dst = jcc(dst, CC_NC, dst+2); | 2876 jcc(code, CC_NC, code->cur + 2); |
3274 } | 2877 } |
3275 if (dst_op.mode == MODE_REG_DIRECT) { | 2878 if (dst_op.mode == MODE_REG_DIRECT) { |
3276 dst = mov_rr(dst, RDX, dst_op.base, SZ_W); | 2879 mov_rr(code, RDX, dst_op.base, SZ_W); |
3277 dst = shl_ir(dst, 16, dst_op.base, SZ_D); | 2880 shl_ir(code, 16, dst_op.base, SZ_D); |
3278 dst = mov_rr(dst, RAX, dst_op.base, SZ_W); | 2881 mov_rr(code, RAX, dst_op.base, SZ_W); |
3279 } else { | 2882 } else { |
3280 dst = mov_rrdisp8(dst, RDX, dst_op.base, dst_op.disp, SZ_W); | 2883 mov_rrdisp(code, RDX, dst_op.base, dst_op.disp, SZ_W); |
3281 dst = shl_irdisp8(dst, 16, dst_op.base, dst_op.disp, SZ_D); | 2884 shl_irdisp(code, 16, dst_op.base, dst_op.disp, SZ_D); |
3282 dst = mov_rrdisp8(dst, RAX, dst_op.base, dst_op.disp, SZ_W); | 2885 mov_rrdisp(code, RAX, dst_op.base, dst_op.disp, SZ_W); |
3283 } | 2886 } |
3284 dst = cmp_ir(dst, 0, RAX, SZ_W); | 2887 cmp_ir(code, 0, RAX, SZ_W); |
3285 dst = pop_r(dst, RAX); | 2888 pop_r(code, RAX); |
3286 dst = pop_r(dst, RDX); | 2889 pop_r(code, RDX); |
3287 dst = set_flag(dst, 0, FLAG_V, opts); | 2890 set_flag(opts, 0, FLAG_V); |
3288 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 2891 set_flag_cond(opts, CC_Z, FLAG_Z); |
3289 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 2892 set_flag_cond(opts, CC_S, FLAG_N); |
3290 end_off = dst+1; | 2893 end_off = code->cur + 1; |
3291 dst = jmp(dst, dst+2); | 2894 jmp(code, code->cur + 2); |
3292 *norm_off = dst - (norm_off + 1); | 2895 *norm_off = code->cur - (norm_off + 1); |
3293 if (inst->op == M68K_DIVS) { | 2896 if (inst->op == M68K_DIVS) { |
3294 *skip_sec_check = dst - (skip_sec_check+1); | 2897 *skip_sec_check = code->cur - (skip_sec_check+1); |
3295 } | 2898 } |
3296 dst = pop_r(dst, RAX); | 2899 pop_r(code, RAX); |
3297 dst = pop_r(dst, RDX); | 2900 pop_r(code, RDX); |
3298 dst = set_flag(dst, 1, FLAG_V, opts); | 2901 set_flag(opts, 1, FLAG_V); |
3299 *end_off = dst - (end_off + 1); | 2902 *end_off = code->cur - (end_off + 1); |
3300 break; | 2903 break; |
3301 } | 2904 } |
3302 case M68K_EOR: | 2905 case M68K_EOR: |
3303 dst = cycles(dst, BUS); | 2906 cycles(&opts->gen, BUS); |
3304 if (src_op.mode == MODE_REG_DIRECT) { | 2907 if (src_op.mode == MODE_REG_DIRECT) { |
3305 if (dst_op.mode == MODE_REG_DIRECT) { | 2908 if (dst_op.mode == MODE_REG_DIRECT) { |
3306 dst = xor_rr(dst, src_op.base, dst_op.base, inst->extra.size); | 2909 xor_rr(code, src_op.base, dst_op.base, inst->extra.size); |
3307 } else { | 2910 } else { |
3308 dst = xor_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, inst->extra.size); | 2911 xor_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, inst->extra.size); |
3309 } | 2912 } |
3310 } else if (src_op.mode == MODE_REG_DISPLACE8) { | 2913 } else if (src_op.mode == MODE_REG_DISPLACE8) { |
3311 dst = xor_rdisp8r(dst, src_op.base, src_op.disp, dst_op.base, inst->extra.size); | 2914 xor_rdispr(code, src_op.base, src_op.disp, dst_op.base, inst->extra.size); |
3312 } else { | 2915 } else { |
3313 if (dst_op.mode == MODE_REG_DIRECT) { | 2916 if (dst_op.mode == MODE_REG_DIRECT) { |
3314 dst = xor_ir(dst, src_op.disp, dst_op.base, inst->extra.size); | 2917 xor_ir(code, src_op.disp, dst_op.base, inst->extra.size); |
3315 } else { | 2918 } else { |
3316 dst = xor_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 2919 xor_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
3317 } | 2920 } |
3318 } | 2921 } |
3319 dst = set_flag(dst, 0, FLAG_C, opts); | 2922 set_flag(opts, 0, FLAG_C); |
3320 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 2923 set_flag_cond(opts, CC_Z, FLAG_Z); |
3321 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 2924 set_flag_cond(opts, CC_S, FLAG_N); |
3322 dst = set_flag(dst, 0, FLAG_V, opts); | 2925 set_flag(opts, 0, FLAG_V); |
3323 dst = m68k_save_result(inst, dst, opts); | 2926 m68k_save_result(inst, opts); |
3324 break; | 2927 break; |
3325 case M68K_EORI_CCR: | 2928 case M68K_EORI_CCR: |
3326 case M68K_EORI_SR: | 2929 case M68K_EORI_SR: |
3327 dst = cycles(dst, 20); | 2930 cycles(&opts->gen, 20); |
3328 //TODO: If ANDI to SR, trap if not in supervisor mode | 2931 //TODO: If ANDI to SR, trap if not in supervisor mode |
3329 if (inst->src.params.immed & 0x1) { | 2932 if (inst->src.params.immed & 0x1) { |
3330 dst = xor_flag(dst, 1, FLAG_C, opts); | 2933 xor_flag(opts, 1, FLAG_C); |
3331 } | 2934 } |
3332 if (inst->src.params.immed & 0x2) { | 2935 if (inst->src.params.immed & 0x2) { |
3333 dst = xor_flag(dst, 1, FLAG_V, opts); | 2936 xor_flag(opts, 1, FLAG_V); |
3334 } | 2937 } |
3335 if (inst->src.params.immed & 0x4) { | 2938 if (inst->src.params.immed & 0x4) { |
3336 dst = xor_flag(dst, 1, FLAG_Z, opts); | 2939 xor_flag(opts, 1, FLAG_Z); |
3337 } | 2940 } |
3338 if (inst->src.params.immed & 0x8) { | 2941 if (inst->src.params.immed & 0x8) { |
3339 dst = xor_flag(dst, 1, FLAG_N, opts); | 2942 xor_flag(opts, 1, FLAG_N); |
3340 } | 2943 } |
3341 if (inst->src.params.immed & 0x10) { | 2944 if (inst->src.params.immed & 0x10) { |
3342 dst = xor_flag(dst, 1, FLAG_X, opts); | 2945 xor_flag(opts, 1, FLAG_X); |
3343 } | 2946 } |
3344 if (inst->op == M68K_ORI_SR) { | 2947 if (inst->op == M68K_ORI_SR) { |
3345 dst = xor_irdisp8(dst, inst->src.params.immed >> 8, CONTEXT, offsetof(m68k_context, status), SZ_B); | 2948 xor_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
3346 if (inst->src.params.immed & 0x700) { | 2949 if (inst->src.params.immed & 0x700) { |
3347 dst = call(dst, opts->do_sync); | 2950 call(code, opts->do_sync); |
3348 } | 2951 } |
3349 } | 2952 } |
3350 break; | 2953 break; |
3351 case M68K_EXG: | 2954 case M68K_EXG: |
3352 dst = cycles(dst, 6); | 2955 cycles(&opts->gen, 6); |
3353 if (dst_op.mode == MODE_REG_DIRECT) { | 2956 if (dst_op.mode == MODE_REG_DIRECT) { |
3354 dst = mov_rr(dst, dst_op.base, SCRATCH2, SZ_D); | 2957 mov_rr(code, dst_op.base, opts->gen.scratch2, SZ_D); |
3355 if (src_op.mode == MODE_REG_DIRECT) { | 2958 if (src_op.mode == MODE_REG_DIRECT) { |
3356 dst = mov_rr(dst, src_op.base, dst_op.base, SZ_D); | 2959 mov_rr(code, src_op.base, dst_op.base, SZ_D); |
3357 dst = mov_rr(dst, SCRATCH2, src_op.base, SZ_D); | 2960 mov_rr(code, opts->gen.scratch2, src_op.base, SZ_D); |
3358 } else { | 2961 } else { |
3359 dst = mov_rdisp8r(dst, src_op.base, src_op.disp, dst_op.base, SZ_D); | 2962 mov_rdispr(code, src_op.base, src_op.disp, dst_op.base, SZ_D); |
3360 dst = mov_rrdisp8(dst, SCRATCH2, src_op.base, src_op.disp, SZ_D); | 2963 mov_rrdisp(code, opts->gen.scratch2, src_op.base, src_op.disp, SZ_D); |
3361 } | 2964 } |
3362 } else { | 2965 } else { |
3363 dst = mov_rdisp8r(dst, dst_op.base, dst_op.disp, SCRATCH2, SZ_D); | 2966 mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, SZ_D); |
3364 if (src_op.mode == MODE_REG_DIRECT) { | 2967 if (src_op.mode == MODE_REG_DIRECT) { |
3365 dst = mov_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, SZ_D); | 2968 mov_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, SZ_D); |
3366 dst = mov_rr(dst, SCRATCH2, src_op.base, SZ_D); | 2969 mov_rr(code, opts->gen.scratch2, src_op.base, SZ_D); |
3367 } else { | 2970 } else { |
3368 dst = mov_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH1, SZ_D); | 2971 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_D); |
3369 dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, SZ_D); | 2972 mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, SZ_D); |
3370 dst = mov_rrdisp8(dst, SCRATCH2, src_op.base, src_op.disp, SZ_D); | 2973 mov_rrdisp(code, opts->gen.scratch2, src_op.base, src_op.disp, SZ_D); |
3371 } | 2974 } |
3372 } | 2975 } |
3373 break; | 2976 break; |
3374 case M68K_ILLEGAL: | 2977 case M68K_ILLEGAL: |
3375 dst = call(dst, opts->gen.save_context); | 2978 call(code, opts->gen.save_context); |
3376 #ifdef X86_64 | 2979 #ifdef X86_64 |
3377 dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); | 2980 mov_rr(code, opts->gen.context_reg, RDI, SZ_PTR); |
3378 #else | 2981 #else |
3379 dst = push_r(dst, CONTEXT); | 2982 push_r(code, opts->gen.context_reg); |
3380 #endif | 2983 #endif |
3381 dst = call(dst, (code_ptr)print_regs_exit); | 2984 call(code, (code_ptr)print_regs_exit); |
3382 break; | 2985 break; |
3383 case M68K_MOVE_FROM_SR: | 2986 case M68K_MOVE_FROM_SR: |
3384 //TODO: Trap if not in system mode | 2987 //TODO: Trap if not in system mode |
3385 dst = call(dst, opts->get_sr); | 2988 call(code, opts->get_sr); |
3386 if (dst_op.mode == MODE_REG_DIRECT) { | 2989 if (dst_op.mode == MODE_REG_DIRECT) { |
3387 dst = mov_rr(dst, SCRATCH1, dst_op.base, SZ_W); | 2990 mov_rr(code, opts->gen.scratch1, dst_op.base, SZ_W); |
3388 } else { | 2991 } else { |
3389 dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, SZ_W); | 2992 mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, SZ_W); |
3390 } | 2993 } |
3391 dst = m68k_save_result(inst, dst, opts); | 2994 m68k_save_result(inst, opts); |
3392 break; | 2995 break; |
3393 case M68K_MOVE_CCR: | 2996 case M68K_MOVE_CCR: |
3394 case M68K_MOVE_SR: | 2997 case M68K_MOVE_SR: |
3395 //TODO: Privilege check for MOVE to SR | 2998 //TODO: Privilege check for MOVE to SR |
3396 if (src_op.mode == MODE_IMMED) { | 2999 if (src_op.mode == MODE_IMMED) { |
3397 dst = set_flag(dst, src_op.disp & 0x1, FLAG_C, opts); | 3000 set_flag(opts, src_op.disp & 0x1, FLAG_C); |
3398 dst = set_flag(dst, (src_op.disp >> 1) & 0x1, FLAG_V, opts); | 3001 set_flag(opts, (src_op.disp >> 1) & 0x1, FLAG_V); |
3399 dst = set_flag(dst, (src_op.disp >> 2) & 0x1, FLAG_Z, opts); | 3002 set_flag(opts, (src_op.disp >> 2) & 0x1, FLAG_Z); |
3400 dst = set_flag(dst, (src_op.disp >> 3) & 0x1, FLAG_N, opts); | 3003 set_flag(opts, (src_op.disp >> 3) & 0x1, FLAG_N); |
3401 dst = set_flag(dst, (src_op.disp >> 4) & 0x1, FLAG_X, opts); | 3004 set_flag(opts, (src_op.disp >> 4) & 0x1, FLAG_X); |
3402 if (inst->op == M68K_MOVE_SR) { | 3005 if (inst->op == M68K_MOVE_SR) { |
3403 dst = mov_irdisp8(dst, (src_op.disp >> 8), CONTEXT, offsetof(m68k_context, status), SZ_B); | 3006 mov_irdisp(code, (src_op.disp >> 8), opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
3404 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { | 3007 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { |
3405 //leave supervisor mode | 3008 //leave supervisor mode |
3406 dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); | 3009 mov_rr(code, opts->aregs[7], opts->gen.scratch1, SZ_D); |
3407 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->aregs[7], SZ_D); | 3010 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->aregs[7], SZ_D); |
3408 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); | 3011 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); |
3409 } | 3012 } |
3410 dst = call(dst, opts->do_sync); | 3013 call(code, opts->do_sync); |
3411 } | 3014 } |
3412 dst = cycles(dst, 12); | 3015 cycles(&opts->gen, 12); |
3413 } else { | 3016 } else { |
3414 if (src_op.base != SCRATCH1) { | 3017 if (src_op.base != opts->gen.scratch1) { |
3415 if (src_op.mode == MODE_REG_DIRECT) { | 3018 if (src_op.mode == MODE_REG_DIRECT) { |
3416 dst = mov_rr(dst, src_op.base, SCRATCH1, SZ_W); | 3019 mov_rr(code, src_op.base, opts->gen.scratch1, SZ_W); |
3417 } else { | 3020 } else { |
3418 dst = mov_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH1, SZ_W); | 3021 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_W); |
3419 } | 3022 } |
3420 } | 3023 } |
3421 dst = call(dst, inst->op == M68K_MOVE_SR ? opts->set_sr : opts->set_ccr); | 3024 call(code, inst->op == M68K_MOVE_SR ? opts->set_sr : opts->set_ccr); |
3422 dst = cycles(dst, 12); | 3025 cycles(&opts->gen, 12); |
3423 | 3026 |
3424 } | 3027 } |
3425 break; | 3028 break; |
3426 case M68K_MOVE_USP: | 3029 case M68K_MOVE_USP: |
3427 dst = cycles(dst, BUS); | 3030 cycles(&opts->gen, BUS); |
3428 //TODO: Trap if not in supervisor mode | 3031 //TODO: Trap if not in supervisor mode |
3429 //dst = bt_irdisp8(dst, BIT_SUPERVISOR, CONTEXT, offsetof(m68k_context, status), SZ_B); | 3032 //bt_irdisp(code, BIT_SUPERVISOR, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
3430 if (inst->src.addr_mode == MODE_UNUSED) { | 3033 if (inst->src.addr_mode == MODE_UNUSED) { |
3431 if (dst_op.mode == MODE_REG_DIRECT) { | 3034 if (dst_op.mode == MODE_REG_DIRECT) { |
3432 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, dst_op.base, SZ_D); | 3035 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, dst_op.base, SZ_D); |
3433 } else { | 3036 } else { |
3434 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SCRATCH1, SZ_D); | 3037 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->gen.scratch1, SZ_D); |
3435 dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, SZ_D); | 3038 mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, SZ_D); |
3436 } | 3039 } |
3437 } else { | 3040 } else { |
3438 if (src_op.mode == MODE_REG_DIRECT) { | 3041 if (src_op.mode == MODE_REG_DIRECT) { |
3439 dst = mov_rrdisp8(dst, src_op.base, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); | 3042 mov_rrdisp(code, src_op.base, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); |
3440 } else { | 3043 } else { |
3441 dst = mov_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH1, SZ_D); | 3044 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_D); |
3442 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); | 3045 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); |
3443 } | 3046 } |
3444 } | 3047 } |
3445 break; | 3048 break; |
3446 //case M68K_MOVEP: | 3049 //case M68K_MOVEP: |
3447 case M68K_MULS: | 3050 case M68K_MULS: |
3448 case M68K_MULU: | 3051 case M68K_MULU: |
3449 dst = cycles(dst, 70); //TODO: Calculate the actual value based on the value of the <ea> parameter | 3052 cycles(&opts->gen, 70); //TODO: Calculate the actual value based on the value of the <ea> parameter |
3450 if (src_op.mode == MODE_IMMED) { | 3053 if (src_op.mode == MODE_IMMED) { |
3451 dst = mov_ir(dst, inst->op == M68K_MULU ? (src_op.disp & 0xFFFF) : ((src_op.disp & 0x8000) ? src_op.disp | 0xFFFF0000 : src_op.disp), SCRATCH1, SZ_D); | 3054 mov_ir(code, inst->op == M68K_MULU ? (src_op.disp & 0xFFFF) : ((src_op.disp & 0x8000) ? src_op.disp | 0xFFFF0000 : src_op.disp), opts->gen.scratch1, SZ_D); |
3452 } else if (src_op.mode == MODE_REG_DIRECT) { | 3055 } else if (src_op.mode == MODE_REG_DIRECT) { |
3453 if (inst->op == M68K_MULS) { | 3056 if (inst->op == M68K_MULS) { |
3454 dst = movsx_rr(dst, src_op.base, SCRATCH1, SZ_W, SZ_D); | 3057 movsx_rr(code, src_op.base, opts->gen.scratch1, SZ_W, SZ_D); |
3455 } else { | 3058 } else { |
3456 dst = movzx_rr(dst, src_op.base, SCRATCH1, SZ_W, SZ_D); | 3059 movzx_rr(code, src_op.base, opts->gen.scratch1, SZ_W, SZ_D); |
3457 } | 3060 } |
3458 } else { | 3061 } else { |
3459 if (inst->op == M68K_MULS) { | 3062 if (inst->op == M68K_MULS) { |
3460 dst = movsx_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH1, SZ_W, SZ_D); | 3063 movsx_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_W, SZ_D); |
3461 } else { | 3064 } else { |
3462 dst = movzx_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH1, SZ_W, SZ_D); | 3065 movzx_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_W, SZ_D); |
3463 } | 3066 } |
3464 } | 3067 } |
3465 if (dst_op.mode == MODE_REG_DIRECT) { | 3068 if (dst_op.mode == MODE_REG_DIRECT) { |
3466 dst_reg = dst_op.base; | 3069 dst_reg = dst_op.base; |
3467 if (inst->op == M68K_MULS) { | 3070 if (inst->op == M68K_MULS) { |
3468 dst = movsx_rr(dst, dst_reg, dst_reg, SZ_W, SZ_D); | 3071 movsx_rr(code, dst_reg, dst_reg, SZ_W, SZ_D); |
3469 } else { | 3072 } else { |
3470 dst = movzx_rr(dst, dst_reg, dst_reg, SZ_W, SZ_D); | 3073 movzx_rr(code, dst_reg, dst_reg, SZ_W, SZ_D); |
3471 } | 3074 } |
3472 } else { | 3075 } else { |
3473 dst_reg = SCRATCH2; | 3076 dst_reg = opts->gen.scratch2; |
3474 if (inst->op == M68K_MULS) { | 3077 if (inst->op == M68K_MULS) { |
3475 dst = movsx_rdisp8r(dst, dst_op.base, dst_op.disp, SCRATCH2, SZ_W, SZ_D); | 3078 movsx_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, SZ_W, SZ_D); |
3476 } else { | 3079 } else { |
3477 dst = movzx_rdisp8r(dst, dst_op.base, dst_op.disp, SCRATCH2, SZ_W, SZ_D); | 3080 movzx_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, SZ_W, SZ_D); |
3478 } | 3081 } |
3479 } | 3082 } |
3480 dst = imul_rr(dst, SCRATCH1, dst_reg, SZ_D); | 3083 imul_rr(code, opts->gen.scratch1, dst_reg, SZ_D); |
3481 if (dst_op.mode == MODE_REG_DISPLACE8) { | 3084 if (dst_op.mode == MODE_REG_DISPLACE8) { |
3482 dst = mov_rrdisp8(dst, dst_reg, dst_op.base, dst_op.disp, SZ_D); | 3085 mov_rrdisp(code, dst_reg, dst_op.base, dst_op.disp, SZ_D); |
3483 } | 3086 } |
3484 dst = set_flag(dst, 0, FLAG_V, opts); | 3087 set_flag(opts, 0, FLAG_V); |
3485 dst = set_flag(dst, 0, FLAG_C, opts); | 3088 set_flag(opts, 0, FLAG_C); |
3486 dst = cmp_ir(dst, 0, dst_reg, SZ_D); | 3089 cmp_ir(code, 0, dst_reg, SZ_D); |
3487 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 3090 set_flag_cond(opts, CC_Z, FLAG_Z); |
3488 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 3091 set_flag_cond(opts, CC_S, FLAG_N); |
3489 break; | 3092 break; |
3490 //case M68K_NBCD: | 3093 //case M68K_NBCD: |
3491 case M68K_NEG: | 3094 case M68K_NEG: |
3492 dst = cycles(dst, BUS); | 3095 cycles(&opts->gen, BUS); |
3493 if (dst_op.mode == MODE_REG_DIRECT) { | 3096 if (dst_op.mode == MODE_REG_DIRECT) { |
3494 dst = neg_r(dst, dst_op.base, inst->extra.size); | 3097 neg_r(code, dst_op.base, inst->extra.size); |
3495 } else { | 3098 } else { |
3496 dst = neg_rdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size); | 3099 neg_rdisp(code, dst_op.base, dst_op.disp, inst->extra.size); |
3497 } | 3100 } |
3498 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); | 3101 set_flag_cond(opts, CC_C, FLAG_C); |
3499 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 3102 set_flag_cond(opts, CC_Z, FLAG_Z); |
3500 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 3103 set_flag_cond(opts, CC_S, FLAG_N); |
3501 dst = set_flag_cond(dst, CC_O, FLAG_V, opts); | 3104 set_flag_cond(opts, CC_O, FLAG_V); |
3502 if (opts->flag_regs[FLAG_C] >= 0) { | 3105 if (opts->flag_regs[FLAG_C] >= 0) { |
3503 dst = flag_to_flag(dst, FLAG_C, FLAG_X, opts); | 3106 flag_to_flag(opts, FLAG_C, FLAG_X); |
3504 } else { | 3107 } else { |
3505 dst = set_flag_cond(dst, CC_C, FLAG_X, opts); | 3108 set_flag_cond(opts, CC_C, FLAG_X); |
3506 } | 3109 } |
3507 dst = m68k_save_result(inst, dst, opts); | 3110 m68k_save_result(inst, opts); |
3508 break; | 3111 break; |
3509 case M68K_NEGX: { | 3112 case M68K_NEGX: { |
3510 dst = cycles(dst, BUS); | 3113 cycles(&opts->gen, BUS); |
3511 if (dst_op.mode == MODE_REG_DIRECT) { | 3114 if (dst_op.mode == MODE_REG_DIRECT) { |
3512 if (dst_op.base == SCRATCH1) { | 3115 if (dst_op.base == opts->gen.scratch1) { |
3513 dst = push_r(dst, SCRATCH2); | 3116 push_r(code, opts->gen.scratch2); |
3514 dst = xor_rr(dst, SCRATCH2, SCRATCH2, inst->extra.size); | 3117 xor_rr(code, opts->gen.scratch2, opts->gen.scratch2, inst->extra.size); |
3515 dst = flag_to_carry(dst, FLAG_X, opts); | 3118 flag_to_carry(opts, FLAG_X); |
3516 dst = sbb_rr(dst, dst_op.base, SCRATCH2, inst->extra.size); | 3119 sbb_rr(code, dst_op.base, opts->gen.scratch2, inst->extra.size); |
3517 dst = mov_rr(dst, SCRATCH2, dst_op.base, inst->extra.size); | 3120 mov_rr(code, opts->gen.scratch2, dst_op.base, inst->extra.size); |
3518 dst = pop_r(dst, SCRATCH2); | 3121 pop_r(code, opts->gen.scratch2); |
3519 } else { | 3122 } else { |
3520 dst = xor_rr(dst, SCRATCH1, SCRATCH1, inst->extra.size); | 3123 xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, inst->extra.size); |
3521 dst = flag_to_carry(dst, FLAG_X, opts); | 3124 flag_to_carry(opts, FLAG_X); |
3522 dst = sbb_rr(dst, dst_op.base, SCRATCH1, inst->extra.size); | 3125 sbb_rr(code, dst_op.base, opts->gen.scratch1, inst->extra.size); |
3523 dst = mov_rr(dst, SCRATCH1, dst_op.base, inst->extra.size); | 3126 mov_rr(code, opts->gen.scratch1, dst_op.base, inst->extra.size); |
3524 } | 3127 } |
3525 } else { | 3128 } else { |
3526 dst = xor_rr(dst, SCRATCH1, SCRATCH1, inst->extra.size); | 3129 xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, inst->extra.size); |
3527 dst = flag_to_carry(dst, FLAG_X, opts); | 3130 flag_to_carry(opts, FLAG_X); |
3528 dst = sbb_rdisp8r(dst, dst_op.base, dst_op.disp, SCRATCH1, inst->extra.size); | 3131 sbb_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, inst->extra.size); |
3529 dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, inst->extra.size); | 3132 mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, inst->extra.size); |
3530 } | 3133 } |
3531 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); | 3134 set_flag_cond(opts, CC_C, FLAG_C); |
3532 code_ptr after_flag_set = dst+1; | 3135 code_ptr after_flag_set = code->cur + 1; |
3533 dst = jcc(dst, CC_Z, dst+2); | 3136 jcc(code, CC_Z, code->cur + 2); |
3534 dst = set_flag(dst, 0, FLAG_Z, opts); | 3137 set_flag(opts, 0, FLAG_Z); |
3535 *after_flag_set = dst - (after_flag_set+1); | 3138 *after_flag_set = code->cur - (after_flag_set+1); |
3536 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 3139 set_flag_cond(opts, CC_S, FLAG_N); |
3537 dst = set_flag_cond(dst, CC_O, FLAG_V, opts); | 3140 set_flag_cond(opts, CC_O, FLAG_V); |
3538 if (opts->flag_regs[FLAG_C] >= 0) { | 3141 if (opts->flag_regs[FLAG_C] >= 0) { |
3539 dst = flag_to_flag(dst, FLAG_C, FLAG_X, opts); | 3142 flag_to_flag(opts, FLAG_C, FLAG_X); |
3540 } else { | 3143 } else { |
3541 dst = set_flag_cond(dst, CC_C, FLAG_X, opts); | 3144 set_flag_cond(opts, CC_C, FLAG_X); |
3542 } | 3145 } |
3543 dst = m68k_save_result(inst, dst, opts); | 3146 m68k_save_result(inst, opts); |
3544 break; | 3147 break; |
3545 } | 3148 } |
3546 case M68K_NOP: | 3149 case M68K_NOP: |
3547 dst = cycles(dst, BUS); | 3150 cycles(&opts->gen, BUS); |
3548 break; | 3151 break; |
3549 case M68K_NOT: | 3152 case M68K_NOT: |
3550 if (dst_op.mode == MODE_REG_DIRECT) { | 3153 if (dst_op.mode == MODE_REG_DIRECT) { |
3551 dst = not_r(dst, dst_op.base, inst->extra.size); | 3154 not_r(code, dst_op.base, inst->extra.size); |
3552 dst = cmp_ir(dst, 0, dst_op.base, inst->extra.size); | 3155 cmp_ir(code, 0, dst_op.base, inst->extra.size); |
3553 } else { | 3156 } else { |
3554 dst = not_rdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size); | 3157 not_rdisp(code, dst_op.base, dst_op.disp, inst->extra.size); |
3555 dst = cmp_irdisp8(dst, 0, dst_op.base, dst_op.disp, inst->extra.size); | 3158 cmp_irdisp(code, 0, dst_op.base, dst_op.disp, inst->extra.size); |
3556 } | 3159 } |
3557 | 3160 |
3558 dst = set_flag(dst, 0, FLAG_C, opts); | 3161 set_flag(opts, 0, FLAG_C); |
3559 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 3162 set_flag_cond(opts, CC_Z, FLAG_Z); |
3560 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 3163 set_flag_cond(opts, CC_S, FLAG_N); |
3561 dst = set_flag(dst, 0, FLAG_V, opts); | 3164 set_flag(opts, 0, FLAG_V); |
3562 dst = m68k_save_result(inst, dst, opts); | 3165 m68k_save_result(inst, opts); |
3563 break; | 3166 break; |
3564 case M68K_OR: | 3167 case M68K_OR: |
3565 dst = cycles(dst, BUS); | 3168 cycles(&opts->gen, BUS); |
3566 if (src_op.mode == MODE_REG_DIRECT) { | 3169 if (src_op.mode == MODE_REG_DIRECT) { |
3567 if (dst_op.mode == MODE_REG_DIRECT) { | 3170 if (dst_op.mode == MODE_REG_DIRECT) { |
3568 dst = or_rr(dst, src_op.base, dst_op.base, inst->extra.size); | 3171 or_rr(code, src_op.base, dst_op.base, inst->extra.size); |
3569 } else { | 3172 } else { |
3570 dst = or_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, inst->extra.size); | 3173 or_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, inst->extra.size); |
3571 } | 3174 } |
3572 } else if (src_op.mode == MODE_REG_DISPLACE8) { | 3175 } else if (src_op.mode == MODE_REG_DISPLACE8) { |
3573 dst = or_rdisp8r(dst, src_op.base, src_op.disp, dst_op.base, inst->extra.size); | 3176 or_rdispr(code, src_op.base, src_op.disp, dst_op.base, inst->extra.size); |
3574 } else { | 3177 } else { |
3575 if (dst_op.mode == MODE_REG_DIRECT) { | 3178 if (dst_op.mode == MODE_REG_DIRECT) { |
3576 dst = or_ir(dst, src_op.disp, dst_op.base, inst->extra.size); | 3179 or_ir(code, src_op.disp, dst_op.base, inst->extra.size); |
3577 } else { | 3180 } else { |
3578 dst = or_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 3181 or_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
3579 } | 3182 } |
3580 } | 3183 } |
3581 dst = set_flag(dst, 0, FLAG_C, opts); | 3184 set_flag(opts, 0, FLAG_C); |
3582 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 3185 set_flag_cond(opts, CC_Z, FLAG_Z); |
3583 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 3186 set_flag_cond(opts, CC_S, FLAG_N); |
3584 dst = set_flag(dst, 0, FLAG_V, opts); | 3187 set_flag(opts, 0, FLAG_V); |
3585 dst = m68k_save_result(inst, dst, opts); | 3188 m68k_save_result(inst, opts); |
3586 break; | 3189 break; |
3587 case M68K_ORI_CCR: | 3190 case M68K_ORI_CCR: |
3588 case M68K_ORI_SR: | 3191 case M68K_ORI_SR: |
3589 dst = cycles(dst, 20); | 3192 cycles(&opts->gen, 20); |
3590 //TODO: If ANDI to SR, trap if not in supervisor mode | 3193 //TODO: If ANDI to SR, trap if not in supervisor mode |
3591 if (inst->src.params.immed & 0x1) { | 3194 if (inst->src.params.immed & 0x1) { |
3592 dst = set_flag(dst, 1, FLAG_C, opts); | 3195 set_flag(opts, 1, FLAG_C); |
3593 } | 3196 } |
3594 if (inst->src.params.immed & 0x2) { | 3197 if (inst->src.params.immed & 0x2) { |
3595 dst = set_flag(dst, 1, FLAG_V, opts); | 3198 set_flag(opts, 1, FLAG_V); |
3596 } | 3199 } |
3597 if (inst->src.params.immed & 0x4) { | 3200 if (inst->src.params.immed & 0x4) { |
3598 dst = set_flag(dst, 1, FLAG_Z, opts); | 3201 set_flag(opts, 1, FLAG_Z); |
3599 } | 3202 } |
3600 if (inst->src.params.immed & 0x8) { | 3203 if (inst->src.params.immed & 0x8) { |
3601 dst = set_flag(dst, 1, FLAG_N, opts); | 3204 set_flag(opts, 1, FLAG_N); |
3602 } | 3205 } |
3603 if (inst->src.params.immed & 0x10) { | 3206 if (inst->src.params.immed & 0x10) { |
3604 dst = set_flag(dst, 1, FLAG_X, opts); | 3207 set_flag(opts, 1, FLAG_X); |
3605 } | 3208 } |
3606 if (inst->op == M68K_ORI_SR) { | 3209 if (inst->op == M68K_ORI_SR) { |
3607 dst = or_irdisp8(dst, inst->src.params.immed >> 8, CONTEXT, offsetof(m68k_context, status), SZ_B); | 3210 or_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
3608 if (inst->src.params.immed & 0x700) { | 3211 if (inst->src.params.immed & 0x700) { |
3609 dst = call(dst, opts->do_sync); | 3212 call(code, opts->do_sync); |
3610 } | 3213 } |
3611 } | 3214 } |
3612 break; | 3215 break; |
3613 case M68K_RESET: | 3216 case M68K_RESET: |
3614 dst = call(dst, opts->gen.save_context); | 3217 call(code, opts->gen.save_context); |
3615 #ifdef X86_64 | 3218 #ifdef X86_64 |
3616 dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); | 3219 mov_rr(code, opts->gen.context_reg, RDI, SZ_PTR); |
3617 #else | 3220 #else |
3618 dst = push_r(dst, CONTEXT); | 3221 push_r(code, opts->gen.context_reg); |
3619 #endif | 3222 #endif |
3620 dst = call(dst, (code_ptr)print_regs_exit); | 3223 call(code, (code_ptr)print_regs_exit); |
3621 break; | 3224 break; |
3622 case M68K_ROL: | 3225 case M68K_ROL: |
3623 case M68K_ROR: | 3226 case M68K_ROR: |
3624 dst = set_flag(dst, 0, FLAG_V, opts); | 3227 set_flag(opts, 0, FLAG_V); |
3625 if (inst->src.addr_mode == MODE_UNUSED) { | 3228 if (inst->src.addr_mode == MODE_UNUSED) { |
3626 dst = cycles(dst, BUS); | 3229 cycles(&opts->gen, BUS); |
3627 //Memory rotate | 3230 //Memory rotate |
3628 if (inst->op == M68K_ROL) { | 3231 if (inst->op == M68K_ROL) { |
3629 dst = rol_ir(dst, 1, dst_op.base, inst->extra.size); | 3232 rol_ir(code, 1, dst_op.base, inst->extra.size); |
3630 } else { | 3233 } else { |
3631 dst = ror_ir(dst, 1, dst_op.base, inst->extra.size); | 3234 ror_ir(code, 1, dst_op.base, inst->extra.size); |
3632 } | 3235 } |
3633 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); | 3236 set_flag_cond(opts, CC_C, FLAG_C); |
3634 dst = cmp_ir(dst, 0, dst_op.base, inst->extra.size); | 3237 cmp_ir(code, 0, dst_op.base, inst->extra.size); |
3635 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 3238 set_flag_cond(opts, CC_Z, FLAG_Z); |
3636 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 3239 set_flag_cond(opts, CC_S, FLAG_N); |
3637 dst = m68k_save_result(inst, dst, opts); | 3240 m68k_save_result(inst, opts); |
3638 } else { | 3241 } else { |
3639 if (src_op.mode == MODE_IMMED) { | 3242 if (src_op.mode == MODE_IMMED) { |
3640 dst = cycles(dst, (inst->extra.size == OPSIZE_LONG ? 8 : 6) + src_op.disp*2); | 3243 cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG ? 8 : 6) + src_op.disp*2); |
3641 if (dst_op.mode == MODE_REG_DIRECT) { | 3244 if (dst_op.mode == MODE_REG_DIRECT) { |
3642 if (inst->op == M68K_ROL) { | 3245 if (inst->op == M68K_ROL) { |
3643 dst = rol_ir(dst, src_op.disp, dst_op.base, inst->extra.size); | 3246 rol_ir(code, src_op.disp, dst_op.base, inst->extra.size); |
3644 } else { | 3247 } else { |
3645 dst = ror_ir(dst, src_op.disp, dst_op.base, inst->extra.size); | 3248 ror_ir(code, src_op.disp, dst_op.base, inst->extra.size); |
3646 } | 3249 } |
3647 } else { | 3250 } else { |
3648 if (inst->op == M68K_ROL) { | 3251 if (inst->op == M68K_ROL) { |
3649 dst = rol_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 3252 rol_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
3650 } else { | 3253 } else { |
3651 dst = ror_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 3254 ror_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
3652 } | 3255 } |
3653 } | 3256 } |
3654 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); | 3257 set_flag_cond(opts, CC_C, FLAG_C); |
3655 } else { | 3258 } else { |
3656 if (src_op.mode == MODE_REG_DIRECT) { | 3259 if (src_op.mode == MODE_REG_DIRECT) { |
3657 if (src_op.base != SCRATCH1) { | 3260 if (src_op.base != opts->gen.scratch1) { |
3658 dst = mov_rr(dst, src_op.base, SCRATCH1, SZ_B); | 3261 mov_rr(code, src_op.base, opts->gen.scratch1, SZ_B); |
3659 } | 3262 } |
3660 } else { | 3263 } else { |
3661 dst = mov_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH1, SZ_B); | 3264 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_B); |
3662 } | 3265 } |
3663 dst = and_ir(dst, 63, SCRATCH1, SZ_D); | 3266 and_ir(code, 63, opts->gen.scratch1, SZ_D); |
3664 zero_off = dst+1; | 3267 zero_off = code->cur + 1; |
3665 dst = jcc(dst, CC_Z, dst+2); | 3268 jcc(code, CC_Z, code->cur + 2); |
3666 dst = add_rr(dst, SCRATCH1, CYCLES, SZ_D); | 3269 add_rr(code, opts->gen.scratch1, CYCLES, SZ_D); |
3667 dst = add_rr(dst, SCRATCH1, CYCLES, SZ_D); | 3270 add_rr(code, opts->gen.scratch1, CYCLES, SZ_D); |
3668 dst = cmp_ir(dst, 32, SCRATCH1, SZ_B); | 3271 cmp_ir(code, 32, opts->gen.scratch1, SZ_B); |
3669 norm_off = dst+1; | 3272 norm_off = code->cur + 1; |
3670 dst = jcc(dst, CC_L, dst+2); | 3273 jcc(code, CC_L, code->cur + 2); |
3671 dst = sub_ir(dst, 32, SCRATCH1, SZ_B); | 3274 sub_ir(code, 32, opts->gen.scratch1, SZ_B); |
3672 if (dst_op.mode == MODE_REG_DIRECT) { | 3275 if (dst_op.mode == MODE_REG_DIRECT) { |
3673 if (inst->op == M68K_ROL) { | 3276 if (inst->op == M68K_ROL) { |
3674 dst = rol_ir(dst, 31, dst_op.base, inst->extra.size); | 3277 rol_ir(code, 31, dst_op.base, inst->extra.size); |
3675 dst = rol_ir(dst, 1, dst_op.base, inst->extra.size); | 3278 rol_ir(code, 1, dst_op.base, inst->extra.size); |
3676 } else { | 3279 } else { |
3677 dst = ror_ir(dst, 31, dst_op.base, inst->extra.size); | 3280 ror_ir(code, 31, dst_op.base, inst->extra.size); |
3678 dst = ror_ir(dst, 1, dst_op.base, inst->extra.size); | 3281 ror_ir(code, 1, dst_op.base, inst->extra.size); |
3679 } | 3282 } |
3680 } else { | 3283 } else { |
3681 if (inst->op == M68K_ROL) { | 3284 if (inst->op == M68K_ROL) { |
3682 dst = rol_irdisp8(dst, 31, dst_op.base, dst_op.disp, inst->extra.size); | 3285 rol_irdisp(code, 31, dst_op.base, dst_op.disp, inst->extra.size); |
3683 dst = rol_irdisp8(dst, 1, dst_op.base, dst_op.disp, inst->extra.size); | 3286 rol_irdisp(code, 1, dst_op.base, dst_op.disp, inst->extra.size); |
3684 } else { | 3287 } else { |
3685 dst = ror_irdisp8(dst, 31, dst_op.base, dst_op.disp, inst->extra.size); | 3288 ror_irdisp(code, 31, dst_op.base, dst_op.disp, inst->extra.size); |
3686 dst = ror_irdisp8(dst, 1, dst_op.base, dst_op.disp, inst->extra.size); | 3289 ror_irdisp(code, 1, dst_op.base, dst_op.disp, inst->extra.size); |
3687 } | 3290 } |
3688 } | 3291 } |
3689 *norm_off = dst - (norm_off+1); | 3292 *norm_off = code->cur - (norm_off+1); |
3690 if (dst_op.mode == MODE_REG_DIRECT) { | 3293 if (dst_op.mode == MODE_REG_DIRECT) { |
3691 if (inst->op == M68K_ROL) { | 3294 if (inst->op == M68K_ROL) { |
3692 dst = rol_clr(dst, dst_op.base, inst->extra.size); | 3295 rol_clr(code, dst_op.base, inst->extra.size); |
3693 } else { | 3296 } else { |
3694 dst = ror_clr(dst, dst_op.base, inst->extra.size); | 3297 ror_clr(code, dst_op.base, inst->extra.size); |
3695 } | 3298 } |
3696 } else { | 3299 } else { |
3697 if (inst->op == M68K_ROL) { | 3300 if (inst->op == M68K_ROL) { |
3698 dst = rol_clrdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size); | 3301 rol_clrdisp(code, dst_op.base, dst_op.disp, inst->extra.size); |
3699 } else { | 3302 } else { |
3700 dst = ror_clrdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size); | 3303 ror_clrdisp(code, dst_op.base, dst_op.disp, inst->extra.size); |
3701 } | 3304 } |
3702 } | 3305 } |
3703 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); | 3306 set_flag_cond(opts, CC_C, FLAG_C); |
3704 end_off = dst + 1; | 3307 end_off = code->cur + 1; |
3705 dst = jmp(dst, dst+2); | 3308 jmp(code, code->cur + 2); |
3706 *zero_off = dst - (zero_off+1); | 3309 *zero_off = code->cur - (zero_off+1); |
3707 dst = set_flag(dst, 0, FLAG_C, opts); | 3310 set_flag(opts, 0, FLAG_C); |
3708 *end_off = dst - (end_off+1); | 3311 *end_off = code->cur - (end_off+1); |
3709 } | 3312 } |
3710 if (dst_op.mode == MODE_REG_DIRECT) { | 3313 if (dst_op.mode == MODE_REG_DIRECT) { |
3711 dst = cmp_ir(dst, 0, dst_op.base, inst->extra.size); | 3314 cmp_ir(code, 0, dst_op.base, inst->extra.size); |
3712 } else { | 3315 } else { |
3713 dst = cmp_irdisp8(dst, 0, dst_op.base, dst_op.disp, inst->extra.size); | 3316 cmp_irdisp(code, 0, dst_op.base, dst_op.disp, inst->extra.size); |
3714 } | 3317 } |
3715 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 3318 set_flag_cond(opts, CC_Z, FLAG_Z); |
3716 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 3319 set_flag_cond(opts, CC_S, FLAG_N); |
3717 } | 3320 } |
3718 break; | 3321 break; |
3719 case M68K_ROXL: | 3322 case M68K_ROXL: |
3720 case M68K_ROXR: | 3323 case M68K_ROXR: |
3721 dst = set_flag(dst, 0, FLAG_V, opts); | 3324 set_flag(opts, 0, FLAG_V); |
3722 if (inst->src.addr_mode == MODE_UNUSED) { | 3325 if (inst->src.addr_mode == MODE_UNUSED) { |
3723 dst = cycles(dst, BUS); | 3326 cycles(&opts->gen, BUS); |
3724 //Memory rotate | 3327 //Memory rotate |
3725 dst = flag_to_carry(dst, FLAG_X, opts); | 3328 flag_to_carry(opts, FLAG_X); |
3726 if (inst->op == M68K_ROXL) { | 3329 if (inst->op == M68K_ROXL) { |
3727 dst = rcl_ir(dst, 1, dst_op.base, inst->extra.size); | 3330 rcl_ir(code, 1, dst_op.base, inst->extra.size); |
3728 } else { | 3331 } else { |
3729 dst = rcr_ir(dst, 1, dst_op.base, inst->extra.size); | 3332 rcr_ir(code, 1, dst_op.base, inst->extra.size); |
3730 } | 3333 } |
3731 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); | 3334 set_flag_cond(opts, CC_C, FLAG_C); |
3732 if (opts->flag_regs[FLAG_C] < 0) { | 3335 if (opts->flag_regs[FLAG_C] < 0) { |
3733 dst = set_flag_cond(dst, CC_C, FLAG_X, opts); | 3336 set_flag_cond(opts, CC_C, FLAG_X); |
3734 } | 3337 } |
3735 dst = cmp_ir(dst, 0, dst_op.base, inst->extra.size); | 3338 cmp_ir(code, 0, dst_op.base, inst->extra.size); |
3736 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 3339 set_flag_cond(opts, CC_Z, FLAG_Z); |
3737 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 3340 set_flag_cond(opts, CC_S, FLAG_N); |
3738 if (opts->flag_regs[FLAG_C] >= 0) { | 3341 if (opts->flag_regs[FLAG_C] >= 0) { |
3739 dst = flag_to_flag(dst, FLAG_C, FLAG_X, opts); | 3342 flag_to_flag(opts, FLAG_C, FLAG_X); |
3740 } | 3343 } |
3741 dst = m68k_save_result(inst, dst, opts); | 3344 m68k_save_result(inst, opts); |
3742 } else { | 3345 } else { |
3743 if (src_op.mode == MODE_IMMED) { | 3346 if (src_op.mode == MODE_IMMED) { |
3744 dst = cycles(dst, (inst->extra.size == OPSIZE_LONG ? 8 : 6) + src_op.disp*2); | 3347 cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG ? 8 : 6) + src_op.disp*2); |
3745 dst = flag_to_carry(dst, FLAG_X, opts); | 3348 flag_to_carry(opts, FLAG_X); |
3746 if (dst_op.mode == MODE_REG_DIRECT) { | 3349 if (dst_op.mode == MODE_REG_DIRECT) { |
3747 if (inst->op == M68K_ROXL) { | 3350 if (inst->op == M68K_ROXL) { |
3748 dst = rcl_ir(dst, src_op.disp, dst_op.base, inst->extra.size); | 3351 rcl_ir(code, src_op.disp, dst_op.base, inst->extra.size); |
3749 } else { | 3352 } else { |
3750 dst = rcr_ir(dst, src_op.disp, dst_op.base, inst->extra.size); | 3353 rcr_ir(code, src_op.disp, dst_op.base, inst->extra.size); |
3751 } | 3354 } |
3752 } else { | 3355 } else { |
3753 if (inst->op == M68K_ROXL) { | 3356 if (inst->op == M68K_ROXL) { |
3754 dst = rcl_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 3357 rcl_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
3755 } else { | 3358 } else { |
3756 dst = rcr_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 3359 rcr_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
3757 } | 3360 } |
3758 } | 3361 } |
3759 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); | 3362 set_flag_cond(opts, CC_C, FLAG_C); |
3760 if (opts->flag_regs[FLAG_C] >= 0) { | 3363 if (opts->flag_regs[FLAG_C] >= 0) { |
3761 dst = flag_to_flag(dst, FLAG_C, FLAG_X, opts); | 3364 flag_to_flag(opts, FLAG_C, FLAG_X); |
3762 } else { | 3365 } else { |
3763 dst = set_flag_cond(dst, CC_C, FLAG_X, opts); | 3366 set_flag_cond(opts, CC_C, FLAG_X); |
3764 } | 3367 } |
3765 } else { | 3368 } else { |
3766 if (src_op.mode == MODE_REG_DIRECT) { | 3369 if (src_op.mode == MODE_REG_DIRECT) { |
3767 if (src_op.base != SCRATCH1) { | 3370 if (src_op.base != opts->gen.scratch1) { |
3768 dst = mov_rr(dst, src_op.base, SCRATCH1, SZ_B); | 3371 mov_rr(code, src_op.base, opts->gen.scratch1, SZ_B); |
3769 } | 3372 } |
3770 } else { | 3373 } else { |
3771 dst = mov_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH1, SZ_B); | 3374 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_B); |
3772 } | 3375 } |
3773 dst = and_ir(dst, 63, SCRATCH1, SZ_D); | 3376 and_ir(code, 63, opts->gen.scratch1, SZ_D); |
3774 zero_off = dst+1; | 3377 zero_off = code->cur + 1; |
3775 dst = jcc(dst, CC_Z, dst+2); | 3378 jcc(code, CC_Z, code->cur + 2); |
3776 dst = add_rr(dst, SCRATCH1, CYCLES, SZ_D); | 3379 add_rr(code, opts->gen.scratch1, CYCLES, SZ_D); |
3777 dst = add_rr(dst, SCRATCH1, CYCLES, SZ_D); | 3380 add_rr(code, opts->gen.scratch1, CYCLES, SZ_D); |
3778 dst = cmp_ir(dst, 32, SCRATCH1, SZ_B); | 3381 cmp_ir(code, 32, opts->gen.scratch1, SZ_B); |
3779 norm_off = dst+1; | 3382 norm_off = code->cur + 1; |
3780 dst = jcc(dst, CC_L, dst+2); | 3383 jcc(code, CC_L, code->cur + 2); |
3781 dst = flag_to_carry(dst, FLAG_X, opts); | 3384 flag_to_carry(opts, FLAG_X); |
3782 if (dst_op.mode == MODE_REG_DIRECT) { | 3385 if (dst_op.mode == MODE_REG_DIRECT) { |
3783 if (inst->op == M68K_ROXL) { | 3386 if (inst->op == M68K_ROXL) { |
3784 dst = rcl_ir(dst, 31, dst_op.base, inst->extra.size); | 3387 rcl_ir(code, 31, dst_op.base, inst->extra.size); |
3785 dst = rcl_ir(dst, 1, dst_op.base, inst->extra.size); | 3388 rcl_ir(code, 1, dst_op.base, inst->extra.size); |
3786 } else { | 3389 } else { |
3787 dst = rcr_ir(dst, 31, dst_op.base, inst->extra.size); | 3390 rcr_ir(code, 31, dst_op.base, inst->extra.size); |
3788 dst = rcr_ir(dst, 1, dst_op.base, inst->extra.size); | 3391 rcr_ir(code, 1, dst_op.base, inst->extra.size); |
3789 } | 3392 } |
3790 } else { | 3393 } else { |
3791 if (inst->op == M68K_ROXL) { | 3394 if (inst->op == M68K_ROXL) { |
3792 dst = rcl_irdisp8(dst, 31, dst_op.base, dst_op.disp, inst->extra.size); | 3395 rcl_irdisp(code, 31, dst_op.base, dst_op.disp, inst->extra.size); |
3793 dst = rcl_irdisp8(dst, 1, dst_op.base, dst_op.disp, inst->extra.size); | 3396 rcl_irdisp(code, 1, dst_op.base, dst_op.disp, inst->extra.size); |
3794 } else { | 3397 } else { |
3795 dst = rcr_irdisp8(dst, 31, dst_op.base, dst_op.disp, inst->extra.size); | 3398 rcr_irdisp(code, 31, dst_op.base, dst_op.disp, inst->extra.size); |
3796 dst = rcr_irdisp8(dst, 1, dst_op.base, dst_op.disp, inst->extra.size); | 3399 rcr_irdisp(code, 1, dst_op.base, dst_op.disp, inst->extra.size); |
3797 } | 3400 } |
3798 } | 3401 } |
3799 dst = set_flag_cond(dst, CC_C, FLAG_X, opts); | 3402 set_flag_cond(opts, CC_C, FLAG_X); |
3800 dst = sub_ir(dst, 32, SCRATCH1, SZ_B); | 3403 sub_ir(code, 32, opts->gen.scratch1, SZ_B); |
3801 *norm_off = dst - (norm_off+1); | 3404 *norm_off = code->cur - (norm_off+1); |
3802 dst = flag_to_carry(dst, FLAG_X, opts); | 3405 flag_to_carry(opts, FLAG_X); |
3803 if (dst_op.mode == MODE_REG_DIRECT) { | 3406 if (dst_op.mode == MODE_REG_DIRECT) { |
3804 if (inst->op == M68K_ROXL) { | 3407 if (inst->op == M68K_ROXL) { |
3805 dst = rcl_clr(dst, dst_op.base, inst->extra.size); | 3408 rcl_clr(code, dst_op.base, inst->extra.size); |
3806 } else { | 3409 } else { |
3807 dst = rcr_clr(dst, dst_op.base, inst->extra.size); | 3410 rcr_clr(code, dst_op.base, inst->extra.size); |
3808 } | 3411 } |
3809 } else { | 3412 } else { |
3810 if (inst->op == M68K_ROXL) { | 3413 if (inst->op == M68K_ROXL) { |
3811 dst = rcl_clrdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size); | 3414 rcl_clrdisp(code, dst_op.base, dst_op.disp, inst->extra.size); |
3812 } else { | 3415 } else { |
3813 dst = rcr_clrdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size); | 3416 rcr_clrdisp(code, dst_op.base, dst_op.disp, inst->extra.size); |
3814 } | 3417 } |
3815 } | 3418 } |
3816 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); | 3419 set_flag_cond(opts, CC_C, FLAG_C); |
3817 if (opts->flag_regs[FLAG_C] >= 0) { | 3420 if (opts->flag_regs[FLAG_C] >= 0) { |
3818 dst = flag_to_flag(dst, FLAG_C, FLAG_X, opts); | 3421 flag_to_flag(opts, FLAG_C, FLAG_X); |
3819 } else { | 3422 } else { |
3820 dst = set_flag_cond(dst, CC_C, FLAG_X, opts); | 3423 set_flag_cond(opts, CC_C, FLAG_X); |
3821 } | 3424 } |
3822 end_off = dst + 1; | 3425 end_off = code->cur + 1; |
3823 dst = jmp(dst, dst+2); | 3426 jmp(code, code->cur + 2); |
3824 *zero_off = dst - (zero_off+1); | 3427 *zero_off = code->cur - (zero_off+1); |
3825 //Carry flag is set to X flag when count is 0, this is different from ROR/ROL | 3428 //Carry flag is set to X flag when count is 0, this is different from ROR/ROL |
3826 dst = flag_to_flag(dst, FLAG_X, FLAG_C, opts); | 3429 flag_to_flag(opts, FLAG_X, FLAG_C); |
3827 *end_off = dst - (end_off+1); | 3430 *end_off = code->cur - (end_off+1); |
3828 } | 3431 } |
3829 if (dst_op.mode == MODE_REG_DIRECT) { | 3432 if (dst_op.mode == MODE_REG_DIRECT) { |
3830 dst = cmp_ir(dst, 0, dst_op.base, inst->extra.size); | 3433 cmp_ir(code, 0, dst_op.base, inst->extra.size); |
3831 } else { | 3434 } else { |
3832 dst = cmp_irdisp8(dst, 0, dst_op.base, dst_op.disp, inst->extra.size); | 3435 cmp_irdisp(code, 0, dst_op.base, dst_op.disp, inst->extra.size); |
3833 } | 3436 } |
3834 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 3437 set_flag_cond(opts, CC_Z, FLAG_Z); |
3835 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 3438 set_flag_cond(opts, CC_S, FLAG_N); |
3836 } | 3439 } |
3837 break; | 3440 break; |
3838 case M68K_RTE: | 3441 case M68K_RTE: |
3839 //TODO: Trap if not in system mode | 3442 //TODO: Trap if not in system mode |
3840 //Read saved SR | 3443 //Read saved SR |
3841 dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); | 3444 mov_rr(code, opts->aregs[7], opts->gen.scratch1, SZ_D); |
3842 dst = call(dst, opts->read_16); | 3445 call(code, opts->read_16); |
3843 dst = add_ir(dst, 2, opts->aregs[7], SZ_D); | 3446 add_ir(code, 2, opts->aregs[7], SZ_D); |
3844 dst = call(dst, opts->set_sr); | 3447 call(code, opts->set_sr); |
3845 //Read saved PC | 3448 //Read saved PC |
3846 dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); | 3449 mov_rr(code, opts->aregs[7], opts->gen.scratch1, SZ_D); |
3847 dst = call(dst, opts->read_32); | 3450 call(code, opts->read_32); |
3848 dst = add_ir(dst, 4, opts->aregs[7], SZ_D); | 3451 add_ir(code, 4, opts->aregs[7], SZ_D); |
3849 //Check if we've switched to user mode and swap stack pointers if needed | 3452 //Check if we've switched to user mode and swap stack pointers if needed |
3850 dst = bt_irdisp8(dst, 5, CONTEXT, offsetof(m68k_context, status), SZ_B); | 3453 bt_irdisp(code, 5, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
3851 end_off = dst+1; | 3454 end_off = code->cur + 1; |
3852 dst = jcc(dst, CC_C, dst+2); | 3455 jcc(code, CC_C, code->cur + 2); |
3853 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); | 3456 mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); |
3854 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->aregs[7], SZ_D); | 3457 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->aregs[7], SZ_D); |
3855 dst = mov_rrdisp8(dst, SCRATCH2, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); | 3458 mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); |
3856 *end_off = dst - (end_off+1); | 3459 *end_off = code->cur - (end_off+1); |
3857 //Get native address, sync components, recalculate integer points and jump to returned address | 3460 //Get native address, sync components, recalculate integer points and jump to returned address |
3858 dst = call(dst, opts->native_addr_and_sync); | 3461 call(code, opts->native_addr_and_sync); |
3859 dst = jmp_r(dst, SCRATCH1); | 3462 jmp_r(code, opts->gen.scratch1); |
3860 break; | 3463 break; |
3861 case M68K_RTR: | 3464 case M68K_RTR: |
3862 //Read saved CCR | 3465 //Read saved CCR |
3863 dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); | 3466 mov_rr(code, opts->aregs[7], opts->gen.scratch1, SZ_D); |
3864 dst = call(dst, opts->read_16); | 3467 call(code, opts->read_16); |
3865 dst = add_ir(dst, 2, opts->aregs[7], SZ_D); | 3468 add_ir(code, 2, opts->aregs[7], SZ_D); |
3866 dst = call(dst, opts->set_ccr); | 3469 call(code, opts->set_ccr); |
3867 //Read saved PC | 3470 //Read saved PC |
3868 dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); | 3471 mov_rr(code, opts->aregs[7], opts->gen.scratch1, SZ_D); |
3869 dst = call(dst, opts->read_32); | 3472 call(code, opts->read_32); |
3870 dst = add_ir(dst, 4, opts->aregs[7], SZ_D); | 3473 add_ir(code, 4, opts->aregs[7], SZ_D); |
3871 //Get native address and jump to it | 3474 //Get native address and jump to it |
3872 dst = call(dst, opts->native_addr); | 3475 call(code, opts->native_addr); |
3873 dst = jmp_r(dst, SCRATCH1); | 3476 jmp_r(code, opts->gen.scratch1); |
3874 break; | 3477 break; |
3875 case M68K_SBCD: { | 3478 case M68K_SBCD: { |
3876 if (src_op.base != SCRATCH2) { | 3479 if (src_op.base != opts->gen.scratch2) { |
3877 if (src_op.mode == MODE_REG_DIRECT) { | 3480 if (src_op.mode == MODE_REG_DIRECT) { |
3878 dst = mov_rr(dst, src_op.base, SCRATCH2, SZ_B); | 3481 mov_rr(code, src_op.base, opts->gen.scratch2, SZ_B); |
3879 } else { | 3482 } else { |
3880 dst = mov_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH2, SZ_B); | 3483 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, SZ_B); |
3881 } | 3484 } |
3882 } | 3485 } |
3883 if (dst_op.base != SCRATCH1) { | 3486 if (dst_op.base != opts->gen.scratch1) { |
3884 if (dst_op.mode == MODE_REG_DIRECT) { | 3487 if (dst_op.mode == MODE_REG_DIRECT) { |
3885 dst = mov_rr(dst, dst_op.base, SCRATCH1, SZ_B); | 3488 mov_rr(code, dst_op.base, opts->gen.scratch1, SZ_B); |
3886 } else { | 3489 } else { |
3887 dst = mov_rdisp8r(dst, dst_op.base, dst_op.disp, SCRATCH1, SZ_B); | 3490 mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, SZ_B); |
3888 } | 3491 } |
3889 } | 3492 } |
3890 dst = flag_to_carry(dst, FLAG_X, opts); | 3493 flag_to_carry(opts, FLAG_X); |
3891 dst = jcc(dst, CC_NC, dst+5); | 3494 jcc(code, CC_NC, code->cur + 5); |
3892 dst = sub_ir(dst, 1, SCRATCH1, SZ_B); | 3495 sub_ir(code, 1, opts->gen.scratch1, SZ_B); |
3893 dst = call(dst, (code_ptr)bcd_sub); | 3496 call(code, (code_ptr)bcd_sub); |
3894 dst = reg_to_flag(dst, CH, FLAG_C, opts); | 3497 reg_to_flag(opts, CH, FLAG_C); |
3895 dst = reg_to_flag(dst, CH, FLAG_X, opts); | 3498 reg_to_flag(opts, CH, FLAG_X); |
3896 dst = cmp_ir(dst, 0, SCRATCH1, SZ_B); | 3499 cmp_ir(code, 0, opts->gen.scratch1, SZ_B); |
3897 code_ptr after_flag_set = dst+1; | 3500 code_ptr after_flag_set = code->cur+1; |
3898 dst = jcc(dst, CC_Z, dst+2); | 3501 jcc(code, CC_Z, code->cur + 2); |
3899 dst = set_flag(dst, 0, FLAG_Z, opts); | 3502 set_flag(opts, 0, FLAG_Z); |
3900 *after_flag_set = dst - (after_flag_set+1); | 3503 *after_flag_set = code->cur - (after_flag_set+1); |
3901 if (dst_op.base != SCRATCH1) { | 3504 if (dst_op.base != opts->gen.scratch1) { |
3902 if (dst_op.mode == MODE_REG_DIRECT) { | 3505 if (dst_op.mode == MODE_REG_DIRECT) { |
3903 dst = mov_rr(dst, SCRATCH1, dst_op.base, SZ_B); | 3506 mov_rr(code, opts->gen.scratch1, dst_op.base, SZ_B); |
3904 } else { | 3507 } else { |
3905 dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, SZ_B); | 3508 mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, SZ_B); |
3906 } | 3509 } |
3907 } | 3510 } |
3908 dst = m68k_save_result(inst, dst, opts); | 3511 m68k_save_result(inst, opts); |
3909 break; | 3512 break; |
3910 } | 3513 } |
3911 case M68K_STOP: { | 3514 case M68K_STOP: { |
3912 //TODO: Trap if not in system mode | 3515 //TODO: Trap if not in system mode |
3913 //manual says 4 cycles, but it has to be at least 8 since it's a 2-word instruction | 3516 //manual says 4 cycles, but it has to be at least 8 since it's a 2-word instruction |
3914 //possibly even 12 since that's how long MOVE to SR takes | 3517 //possibly even 12 since that's how long MOVE to SR takes |
3915 dst = cycles(dst, BUS*2); | 3518 cycles(&opts->gen, BUS*2); |
3916 dst = set_flag(dst, src_op.disp & 0x1, FLAG_C, opts); | 3519 set_flag(opts, src_op.disp & 0x1, FLAG_C); |
3917 dst = set_flag(dst, (src_op.disp >> 1) & 0x1, FLAG_V, opts); | 3520 set_flag(opts, (src_op.disp >> 1) & 0x1, FLAG_V); |
3918 dst = set_flag(dst, (src_op.disp >> 2) & 0x1, FLAG_Z, opts); | 3521 set_flag(opts, (src_op.disp >> 2) & 0x1, FLAG_Z); |
3919 dst = set_flag(dst, (src_op.disp >> 3) & 0x1, FLAG_N, opts); | 3522 set_flag(opts, (src_op.disp >> 3) & 0x1, FLAG_N); |
3920 dst = set_flag(dst, (src_op.disp >> 4) & 0x1, FLAG_X, opts); | 3523 set_flag(opts, (src_op.disp >> 4) & 0x1, FLAG_X); |
3921 dst = mov_irdisp8(dst, (src_op.disp >> 8), CONTEXT, offsetof(m68k_context, status), SZ_B); | 3524 mov_irdisp(code, (src_op.disp >> 8), opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
3922 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { | 3525 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { |
3923 //leave supervisor mode | 3526 //leave supervisor mode |
3924 dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); | 3527 mov_rr(code, opts->aregs[7], opts->gen.scratch1, SZ_D); |
3925 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->aregs[7], SZ_D); | 3528 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->aregs[7], SZ_D); |
3926 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); | 3529 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); |
3927 } | 3530 } |
3928 code_ptr loop_top = dst; | 3531 code_ptr loop_top = code->cur; |
3929 dst = call(dst, opts->do_sync); | 3532 call(code, opts->do_sync); |
3930 dst = cmp_rr(dst, LIMIT, CYCLES, SZ_D); | 3533 cmp_rr(code, opts->gen.limit, opts->gen.cycles, SZ_D); |
3931 code_ptr normal_cycle_up = dst + 1; | 3534 code_ptr normal_cycle_up = code->cur + 1; |
3932 dst = jcc(dst, CC_A, dst+2); | 3535 jcc(code, CC_A, code->cur + 2); |
3933 dst = cycles(dst, BUS); | 3536 cycles(&opts->gen, BUS); |
3934 code_ptr after_cycle_up = dst + 1; | 3537 code_ptr after_cycle_up = code->cur + 1; |
3935 dst = jmp(dst, dst+2); | 3538 jmp(code, code->cur + 2); |
3936 *normal_cycle_up = dst - (normal_cycle_up + 1); | 3539 *normal_cycle_up = code->cur - (normal_cycle_up + 1); |
3937 dst = mov_rr(dst, LIMIT, CYCLES, SZ_D); | 3540 mov_rr(code, opts->gen.limit, opts->gen.cycles, SZ_D); |
3938 *after_cycle_up = dst - (after_cycle_up+1); | 3541 *after_cycle_up = code->cur - (after_cycle_up+1); |
3939 dst = cmp_rdisp8r(dst, CONTEXT, offsetof(m68k_context, int_cycle), CYCLES, SZ_D); | 3542 cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_cycle), opts->gen.cycles, SZ_D); |
3940 dst = jcc(dst, CC_C, loop_top); | 3543 jcc(code, CC_C, loop_top); |
3941 break; | 3544 break; |
3942 } | 3545 } |
3943 case M68K_SUB: | 3546 case M68K_SUB: |
3944 size = inst->dst.addr_mode == MODE_AREG ? OPSIZE_LONG : inst->extra.size; | 3547 size = inst->dst.addr_mode == MODE_AREG ? OPSIZE_LONG : inst->extra.size; |
3945 dst = cycles(dst, BUS); | 3548 cycles(&opts->gen, BUS); |
3946 if (src_op.mode == MODE_REG_DIRECT) { | 3549 if (src_op.mode == MODE_REG_DIRECT) { |
3947 if (dst_op.mode == MODE_REG_DIRECT) { | 3550 if (dst_op.mode == MODE_REG_DIRECT) { |
3948 dst = sub_rr(dst, src_op.base, dst_op.base, size); | 3551 sub_rr(code, src_op.base, dst_op.base, size); |
3949 } else { | 3552 } else { |
3950 dst = sub_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, size); | 3553 sub_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, size); |
3951 } | 3554 } |
3952 } else if (src_op.mode == MODE_REG_DISPLACE8) { | 3555 } else if (src_op.mode == MODE_REG_DISPLACE8) { |
3953 dst = sub_rdisp8r(dst, src_op.base, src_op.disp, dst_op.base, size); | 3556 sub_rdispr(code, src_op.base, src_op.disp, dst_op.base, size); |
3954 } else { | 3557 } else { |
3955 if (dst_op.mode == MODE_REG_DIRECT) { | 3558 if (dst_op.mode == MODE_REG_DIRECT) { |
3956 dst = sub_ir(dst, src_op.disp, dst_op.base, size); | 3559 sub_ir(code, src_op.disp, dst_op.base, size); |
3957 } else { | 3560 } else { |
3958 dst = sub_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, size); | 3561 sub_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, size); |
3959 } | 3562 } |
3960 } | 3563 } |
3961 if (inst->dst.addr_mode != MODE_AREG) { | 3564 if (inst->dst.addr_mode != MODE_AREG) { |
3962 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); | 3565 set_flag_cond(opts, CC_C, FLAG_C); |
3963 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 3566 set_flag_cond(opts, CC_Z, FLAG_Z); |
3964 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 3567 set_flag_cond(opts, CC_S, FLAG_N); |
3965 dst = set_flag_cond(dst, CC_O, FLAG_V, opts); | 3568 set_flag_cond(opts, CC_O, FLAG_V); |
3966 if (opts->flag_regs[FLAG_C] >= 0) { | 3569 if (opts->flag_regs[FLAG_C] >= 0) { |
3967 dst = flag_to_flag(dst, FLAG_C, FLAG_X, opts); | 3570 flag_to_flag(opts, FLAG_C, FLAG_X); |
3968 } else { | 3571 } else { |
3969 dst = set_flag_cond(dst, CC_C, FLAG_X, opts); | 3572 set_flag_cond(opts, CC_C, FLAG_X); |
3970 } | 3573 } |
3971 } | 3574 } |
3972 dst = m68k_save_result(inst, dst, opts); | 3575 m68k_save_result(inst, opts); |
3973 break; | 3576 break; |
3974 case M68K_SUBX: { | 3577 case M68K_SUBX: { |
3975 dst = cycles(dst, BUS); | 3578 cycles(&opts->gen, BUS); |
3976 dst = flag_to_carry(dst, FLAG_X, opts); | 3579 flag_to_carry(opts, FLAG_X); |
3977 if (src_op.mode == MODE_REG_DIRECT) { | 3580 if (src_op.mode == MODE_REG_DIRECT) { |
3978 if (dst_op.mode == MODE_REG_DIRECT) { | 3581 if (dst_op.mode == MODE_REG_DIRECT) { |
3979 dst = sbb_rr(dst, src_op.base, dst_op.base, inst->extra.size); | 3582 sbb_rr(code, src_op.base, dst_op.base, inst->extra.size); |
3980 } else { | 3583 } else { |
3981 dst = sbb_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, inst->extra.size); | 3584 sbb_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, inst->extra.size); |
3982 } | 3585 } |
3983 } else if (src_op.mode == MODE_REG_DISPLACE8) { | 3586 } else if (src_op.mode == MODE_REG_DISPLACE8) { |
3984 dst = sbb_rdisp8r(dst, src_op.base, src_op.disp, dst_op.base, inst->extra.size); | 3587 sbb_rdispr(code, src_op.base, src_op.disp, dst_op.base, inst->extra.size); |
3985 } else { | 3588 } else { |
3986 if (dst_op.mode == MODE_REG_DIRECT) { | 3589 if (dst_op.mode == MODE_REG_DIRECT) { |
3987 dst = sbb_ir(dst, src_op.disp, dst_op.base, inst->extra.size); | 3590 sbb_ir(code, src_op.disp, dst_op.base, inst->extra.size); |
3988 } else { | 3591 } else { |
3989 dst = sbb_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 3592 sbb_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
3990 } | 3593 } |
3991 } | 3594 } |
3992 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); | 3595 set_flag_cond(opts, CC_C, FLAG_C); |
3993 if (opts->flag_regs[FLAG_C] < 0) { | 3596 if (opts->flag_regs[FLAG_C] < 0) { |
3994 dst = set_flag_cond(dst, CC_C, FLAG_X, opts); | 3597 set_flag_cond(opts, CC_C, FLAG_X); |
3995 } | 3598 } |
3996 code_ptr after_flag_set = dst+1; | 3599 code_ptr after_flag_set = code->cur + 1; |
3997 dst = jcc(dst, CC_Z, dst+2); | 3600 jcc(code, CC_Z, code->cur + 2); |
3998 dst = set_flag(dst, 0, FLAG_Z, opts); | 3601 set_flag(opts, 0, FLAG_Z); |
3999 *after_flag_set = dst - (after_flag_set+1); | 3602 *after_flag_set = code->cur - (after_flag_set+1); |
4000 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 3603 set_flag_cond(opts, CC_S, FLAG_N); |
4001 dst = set_flag_cond(dst, CC_O, FLAG_V, opts); | 3604 set_flag_cond(opts, CC_O, FLAG_V); |
4002 if (opts->flag_regs[FLAG_C] >= 0) { | 3605 if (opts->flag_regs[FLAG_C] >= 0) { |
4003 dst = flag_to_flag(dst, FLAG_C, FLAG_X, opts); | 3606 flag_to_flag(opts, FLAG_C, FLAG_X); |
4004 } | 3607 } |
4005 dst = m68k_save_result(inst, dst, opts); | 3608 m68k_save_result(inst, opts); |
4006 break; | 3609 break; |
4007 } | 3610 } |
4008 case M68K_SWAP: | 3611 case M68K_SWAP: |
4009 dst = cycles(dst, BUS); | 3612 cycles(&opts->gen, BUS); |
4010 if (src_op.mode == MODE_REG_DIRECT) { | 3613 if (src_op.mode == MODE_REG_DIRECT) { |
4011 dst = rol_ir(dst, 16, src_op.base, SZ_D); | 3614 rol_ir(code, 16, src_op.base, SZ_D); |
4012 dst = cmp_ir(dst, 0, src_op.base, SZ_D); | 3615 cmp_ir(code, 0, src_op.base, SZ_D); |
4013 } else{ | 3616 } else{ |
4014 dst = rol_irdisp8(dst, 16, src_op.base, src_op.disp, SZ_D); | 3617 rol_irdisp(code, 16, src_op.base, src_op.disp, SZ_D); |
4015 dst = cmp_irdisp8(dst, 0, src_op.base, src_op.disp, SZ_D); | 3618 cmp_irdisp(code, 0, src_op.base, src_op.disp, SZ_D); |
4016 } | 3619 } |
4017 | 3620 |
4018 dst = set_flag(dst, 0, FLAG_C, opts); | 3621 set_flag(opts, 0, FLAG_C); |
4019 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 3622 set_flag_cond(opts, CC_Z, FLAG_Z); |
4020 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 3623 set_flag_cond(opts, CC_S, FLAG_N); |
4021 dst = set_flag(dst, 0, FLAG_V, opts); | 3624 set_flag(opts, 0, FLAG_V); |
4022 break; | 3625 break; |
4023 //case M68K_TAS: | 3626 //case M68K_TAS: |
4024 case M68K_TRAP: | 3627 case M68K_TRAP: |
4025 dst = mov_ir(dst, src_op.disp + VECTOR_TRAP_0, SCRATCH2, SZ_D); | 3628 mov_ir(code, src_op.disp + VECTOR_TRAP_0, opts->gen.scratch2, SZ_D); |
4026 dst = mov_ir(dst, inst->address+2, SCRATCH1, SZ_D); | 3629 mov_ir(code, inst->address+2, opts->gen.scratch1, SZ_D); |
4027 dst = jmp(dst, opts->trap); | 3630 jmp(code, opts->trap); |
4028 break; | 3631 break; |
4029 //case M68K_TRAPV: | 3632 //case M68K_TRAPV: |
4030 case M68K_TST: | 3633 case M68K_TST: |
4031 dst = cycles(dst, BUS); | 3634 cycles(&opts->gen, BUS); |
4032 if (src_op.mode == MODE_REG_DIRECT) { | 3635 if (src_op.mode == MODE_REG_DIRECT) { |
4033 dst = cmp_ir(dst, 0, src_op.base, inst->extra.size); | 3636 cmp_ir(code, 0, src_op.base, inst->extra.size); |
4034 } else { //M68000 doesn't support immedate operand for tst, so this must be MODE_REG_DISPLACE8 | 3637 } else { //M68000 doesn't support immedate operand for tst, so this must be MODE_REG_DISPLACE8 |
4035 dst = cmp_irdisp8(dst, 0, src_op.base, src_op.disp, inst->extra.size); | 3638 cmp_irdisp(code, 0, src_op.base, src_op.disp, inst->extra.size); |
4036 } | 3639 } |
4037 dst = set_flag(dst, 0, FLAG_C, opts); | 3640 set_flag(opts, 0, FLAG_C); |
4038 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); | 3641 set_flag_cond(opts, CC_Z, FLAG_Z); |
4039 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | 3642 set_flag_cond(opts, CC_S, FLAG_N); |
4040 dst = set_flag(dst, 0, FLAG_V, opts); | 3643 set_flag(opts, 0, FLAG_V); |
4041 break; | 3644 break; |
4042 case M68K_UNLK: | 3645 case M68K_UNLK: |
4043 dst = cycles(dst, BUS); | 3646 cycles(&opts->gen, BUS); |
4044 if (dst_op.mode == MODE_REG_DIRECT) { | 3647 if (dst_op.mode == MODE_REG_DIRECT) { |
4045 dst = mov_rr(dst, dst_op.base, opts->aregs[7], SZ_D); | 3648 mov_rr(code, dst_op.base, opts->aregs[7], SZ_D); |
4046 } else { | 3649 } else { |
4047 dst = mov_rdisp8r(dst, dst_op.base, dst_op.disp, opts->aregs[7], SZ_D); | 3650 mov_rdispr(code, dst_op.base, dst_op.disp, opts->aregs[7], SZ_D); |
4048 } | 3651 } |
4049 dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); | 3652 mov_rr(code, opts->aregs[7], opts->gen.scratch1, SZ_D); |
4050 dst = call(dst, opts->read_32); | 3653 call(code, opts->read_32); |
4051 if (dst_op.mode == MODE_REG_DIRECT) { | 3654 if (dst_op.mode == MODE_REG_DIRECT) { |
4052 dst = mov_rr(dst, SCRATCH1, dst_op.base, SZ_D); | 3655 mov_rr(code, opts->gen.scratch1, dst_op.base, SZ_D); |
4053 } else { | 3656 } else { |
4054 dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, SZ_D); | 3657 mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, SZ_D); |
4055 } | 3658 } |
4056 dst = add_ir(dst, 4, opts->aregs[7], SZ_D); | 3659 add_ir(code, 4, opts->aregs[7], SZ_D); |
4057 break; | 3660 break; |
4058 default: | 3661 default: |
4059 m68k_disasm(inst, disasm_buf); | 3662 m68k_disasm(inst, disasm_buf); |
4060 printf("%X: %s\ninstruction %d not yet implemented\n", inst->address, disasm_buf, inst->op); | 3663 printf("%X: %s\ninstruction %d not yet implemented\n", inst->address, disasm_buf, inst->op); |
4061 exit(1); | 3664 exit(1); |
4062 } | 3665 } |
4063 return dst; | |
4064 } | 3666 } |
4065 | 3667 |
4066 uint8_t m68k_is_terminal(m68kinst * inst) | 3668 uint8_t m68k_is_terminal(m68kinst * inst) |
4067 { | 3669 { |
4068 return inst->op == M68K_RTS || inst->op == M68K_RTE || inst->op == M68K_RTR || inst->op == M68K_JMP | 3670 return inst->op == M68K_RTS || inst->op == M68K_RTE || inst->op == M68K_RTR || inst->op == M68K_JMP |
4077 if (opts->gen.deferred) { | 3679 if (opts->gen.deferred) { |
4078 translate_m68k_stream(opts->gen.deferred->address, context); | 3680 translate_m68k_stream(opts->gen.deferred->address, context); |
4079 } | 3681 } |
4080 } | 3682 } |
4081 | 3683 |
4082 code_ptr translate_m68k_stream(uint32_t address, m68k_context * context) | 3684 void translate_m68k_stream(uint32_t address, m68k_context * context) |
4083 { | 3685 { |
4084 m68kinst instbuf; | 3686 m68kinst instbuf; |
4085 x86_68k_options * opts = context->options; | 3687 x86_68k_options * opts = context->options; |
4086 code_ptr dst = opts->gen.cur_code; | 3688 code_info *code = &opts->gen.code; |
4087 code_ptr dst_end = opts->gen.code_end; | |
4088 address &= 0xFFFFFF; | 3689 address &= 0xFFFFFF; |
4089 if(get_native_address(opts->gen.native_code_map, address)) { | 3690 if(get_native_address(opts->gen.native_code_map, address)) { |
4090 return dst; | 3691 return; |
4091 } | 3692 } |
4092 char disbuf[1024]; | 3693 char disbuf[1024]; |
4093 uint16_t *encoded, *next; | 3694 uint16_t *encoded, *next; |
4094 if ((address & 0xFFFFFF) < 0x400000) { | 3695 if ((address & 0xFFFFFF) < 0x400000) { |
4095 encoded = context->mem_pointers[0] + (address & 0xFFFFFF)/2; | 3696 encoded = context->mem_pointers[0] + (address & 0xFFFFFF)/2; |
4102 do { | 3703 do { |
4103 if (opts->address_log) { | 3704 if (opts->address_log) { |
4104 fprintf(opts->address_log, "%X\n", address); | 3705 fprintf(opts->address_log, "%X\n", address); |
4105 } | 3706 } |
4106 do { | 3707 do { |
4107 if (dst_end-dst < MAX_NATIVE_SIZE) { | |
4108 if (dst_end-dst < 5) { | |
4109 puts("out of code memory, not enough space for jmp to next chunk"); | |
4110 exit(1); | |
4111 } | |
4112 size_t size = 1024*1024; | |
4113 opts->gen.cur_code = alloc_code(&size); | |
4114 opts->gen.code_end = opts->gen.cur_code + size; | |
4115 jmp(dst, opts->gen.cur_code); | |
4116 dst = opts->gen.cur_code; | |
4117 dst_end = opts->gen.code_end; | |
4118 } | |
4119 if (address >= 0x400000 && address < 0xE00000) { | 3708 if (address >= 0x400000 && address < 0xE00000) { |
4120 dst = xor_rr(dst, RDI, RDI, SZ_D); | 3709 xor_rr(code, RDI, RDI, SZ_D); |
4121 #ifdef X86_32 | 3710 #ifdef X86_32 |
4122 dst = push_r(dst, RDI); | 3711 push_r(code, RDI); |
4123 #endif | 3712 #endif |
4124 dst = call(dst, (code_ptr)exit); | 3713 call(code, (code_ptr)exit); |
4125 break; | 3714 break; |
4126 } | 3715 } |
4127 code_ptr existing = get_native_address(opts->gen.native_code_map, address); | 3716 code_ptr existing = get_native_address(opts->gen.native_code_map, address); |
4128 if (existing) { | 3717 if (existing) { |
4129 dst = jmp(dst, existing); | 3718 jmp(code, existing); |
4130 break; | 3719 break; |
4131 } | 3720 } |
4132 next = m68k_decode(encoded, &instbuf, address); | 3721 next = m68k_decode(encoded, &instbuf, address); |
4133 if (instbuf.op == M68K_INVALID) { | 3722 if (instbuf.op == M68K_INVALID) { |
4134 instbuf.src.params.immed = *encoded; | 3723 instbuf.src.params.immed = *encoded; |
4136 uint16_t m68k_size = (next-encoded)*2; | 3725 uint16_t m68k_size = (next-encoded)*2; |
4137 address += m68k_size; | 3726 address += m68k_size; |
4138 encoded = next; | 3727 encoded = next; |
4139 //m68k_disasm(&instbuf, disbuf); | 3728 //m68k_disasm(&instbuf, disbuf); |
4140 //printf("%X: %s\n", instbuf.address, disbuf); | 3729 //printf("%X: %s\n", instbuf.address, disbuf); |
4141 code_ptr after = translate_m68k(dst, &instbuf, opts); | 3730 |
4142 map_native_address(context, instbuf.address, dst, m68k_size, after-dst); | 3731 //make sure the beginning of the code for an instruction is contiguous |
4143 dst = after; | 3732 check_alloc_code(code, MAX_INST_LEN*4); |
3733 code_ptr start = code->cur; | |
3734 translate_m68k(opts, &instbuf); | |
3735 code_ptr after = code->cur; | |
3736 map_native_address(context, instbuf.address, start, m68k_size, after-start); | |
3737 after; | |
4144 } while(!m68k_is_terminal(&instbuf)); | 3738 } while(!m68k_is_terminal(&instbuf)); |
4145 process_deferred(&opts->gen.deferred, context, (native_addr_func)get_native_from_context); | 3739 process_deferred(&opts->gen.deferred, context, (native_addr_func)get_native_from_context); |
4146 if (opts->gen.deferred) { | 3740 if (opts->gen.deferred) { |
4147 address = opts->gen.deferred->address; | 3741 address = opts->gen.deferred->address; |
4148 if ((address & 0xFFFFFF) < 0x400000) { | 3742 if ((address & 0xFFFFFF) < 0x400000) { |
4155 } | 3749 } |
4156 } else { | 3750 } else { |
4157 encoded = NULL; | 3751 encoded = NULL; |
4158 } | 3752 } |
4159 } while(encoded != NULL); | 3753 } while(encoded != NULL); |
4160 opts->gen.cur_code = dst; | |
4161 return dst; | |
4162 } | 3754 } |
4163 | 3755 |
4164 code_ptr get_native_address_trans(m68k_context * context, uint32_t address) | 3756 code_ptr get_native_address_trans(m68k_context * context, uint32_t address) |
4165 { | 3757 { |
4166 address &= 0xFFFFFF; | 3758 address &= 0xFFFFFF; |
4173 } | 3765 } |
4174 | 3766 |
4175 void * m68k_retranslate_inst(uint32_t address, m68k_context * context) | 3767 void * m68k_retranslate_inst(uint32_t address, m68k_context * context) |
4176 { | 3768 { |
4177 x86_68k_options * opts = context->options; | 3769 x86_68k_options * opts = context->options; |
3770 code_info *code = &opts->gen.code; | |
4178 uint8_t orig_size = get_native_inst_size(opts, address); | 3771 uint8_t orig_size = get_native_inst_size(opts, address); |
4179 code_ptr orig_start = get_native_address(context->native_code_map, address); | 3772 code_ptr orig_start = get_native_address(context->native_code_map, address); |
4180 uint32_t orig = address; | 3773 uint32_t orig = address; |
3774 code_info orig_code; | |
3775 orig_code.cur = orig_start; | |
3776 orig_code.last = orig_start + orig_size + 5; | |
4181 address &= 0xFFFF; | 3777 address &= 0xFFFF; |
4182 code_ptr dst = opts->gen.cur_code; | |
4183 code_ptr dst_end = opts->gen.code_end; | |
4184 uint16_t *after, *inst = context->mem_pointers[1] + address/2; | 3778 uint16_t *after, *inst = context->mem_pointers[1] + address/2; |
4185 m68kinst instbuf; | 3779 m68kinst instbuf; |
4186 after = m68k_decode(inst, &instbuf, orig); | 3780 after = m68k_decode(inst, &instbuf, orig); |
4187 if (orig_size != MAX_NATIVE_SIZE) { | 3781 if (orig_size != MAX_NATIVE_SIZE) { |
4188 if (dst_end - dst < 128) { | |
4189 size_t size = 1024*1024; | |
4190 dst = alloc_code(&size); | |
4191 opts->gen.code_end = dst_end = dst + size; | |
4192 opts->gen.cur_code = dst; | |
4193 } | |
4194 deferred_addr * orig_deferred = opts->gen.deferred; | 3782 deferred_addr * orig_deferred = opts->gen.deferred; |
4195 code_ptr native_end = translate_m68k(dst, &instbuf, opts); | 3783 |
3784 //make sure the beginning of the code for an instruction is contiguous | |
3785 check_alloc_code(code, MAX_INST_LEN*4); | |
3786 code_ptr native_start = code->cur; | |
3787 translate_m68k(opts, &instbuf); | |
3788 code_ptr native_end = code->cur; | |
4196 uint8_t is_terminal = m68k_is_terminal(&instbuf); | 3789 uint8_t is_terminal = m68k_is_terminal(&instbuf); |
4197 if ((native_end - dst) <= orig_size) { | 3790 if ((native_end - native_start) <= orig_size) { |
4198 code_ptr native_next; | 3791 code_ptr native_next; |
4199 if (!is_terminal) { | 3792 if (!is_terminal) { |
4200 native_next = get_native_address(context->native_code_map, orig + (after-inst)*2); | 3793 native_next = get_native_address(context->native_code_map, orig + (after-inst)*2); |
4201 } | 3794 } |
4202 if (is_terminal || (native_next && ((native_next == orig_start + orig_size) || (orig_size - (native_end - dst)) > 5))) { | 3795 if (is_terminal || (native_next && ((native_next == orig_start + orig_size) || (orig_size - (native_end - native_start)) > 5))) { |
4203 remove_deferred_until(&opts->gen.deferred, orig_deferred); | 3796 remove_deferred_until(&opts->gen.deferred, orig_deferred); |
4204 native_end = translate_m68k(orig_start, &instbuf, opts); | 3797 code_info tmp; |
3798 tmp.cur = code->cur; | |
3799 tmp.last = code->last; | |
3800 code->cur = orig_code.cur; | |
3801 code->last = orig_code.last; | |
3802 translate_m68k(opts, &instbuf); | |
3803 native_end = orig_code.cur = code->cur; | |
3804 code->cur = tmp.cur; | |
3805 code->last = tmp.last; | |
4205 if (!is_terminal) { | 3806 if (!is_terminal) { |
4206 if (native_next == orig_start + orig_size && (native_next-native_end) < 2) { | 3807 if (native_next == orig_start + orig_size && (native_next-native_end) < 2) { |
4207 while (native_end < orig_start + orig_size) { | 3808 while (orig_code.cur < orig_start + orig_size) { |
4208 *(native_end++) = 0x90; //NOP | 3809 *(orig_code.cur++) = 0x90; //NOP |
4209 } | 3810 } |
4210 } else { | 3811 } else { |
4211 jmp(native_end, native_next); | 3812 jmp(&orig_code, native_next); |
4212 } | 3813 } |
4213 } | 3814 } |
4214 m68k_handle_deferred(context); | 3815 m68k_handle_deferred(context); |
4215 return orig_start; | 3816 return orig_start; |
4216 } | 3817 } |
4217 } | 3818 } |
4218 | 3819 |
4219 map_native_address(context, instbuf.address, dst, (after-inst)*2, MAX_NATIVE_SIZE); | 3820 map_native_address(context, instbuf.address, native_start, (after-inst)*2, MAX_NATIVE_SIZE); |
4220 opts->gen.cur_code = dst+MAX_NATIVE_SIZE; | 3821 |
4221 jmp(orig_start, dst); | 3822 jmp(&orig_code, native_start); |
4222 if (!m68k_is_terminal(&instbuf)) { | 3823 if (!m68k_is_terminal(&instbuf)) { |
4223 jmp(native_end, get_native_address_trans(context, orig + (after-inst)*2)); | 3824 code_ptr native_end = code->cur; |
3825 code->cur = native_start + MAX_NATIVE_SIZE; | |
3826 code_ptr rest = get_native_address_trans(context, orig + (after-inst)*2); | |
3827 code_ptr tmp = code->cur; | |
3828 code->cur = native_end; | |
3829 jmp(code, rest); | |
3830 code->cur = tmp; | |
3831 } else { | |
3832 code->cur = native_start + MAX_NATIVE_SIZE; | |
4224 } | 3833 } |
4225 m68k_handle_deferred(context); | 3834 m68k_handle_deferred(context); |
4226 return dst; | 3835 return native_start; |
4227 } else { | 3836 } else { |
4228 dst = translate_m68k(orig_start, &instbuf, opts); | 3837 code_info tmp; |
3838 tmp.cur = code->cur; | |
3839 tmp.last = code->last; | |
3840 code->cur = orig_code.cur; | |
3841 code->last = orig_code.last; | |
3842 translate_m68k(opts, &instbuf); | |
4229 if (!m68k_is_terminal(&instbuf)) { | 3843 if (!m68k_is_terminal(&instbuf)) { |
4230 dst = jmp(dst, get_native_address_trans(context, orig + (after-inst)*2)); | 3844 jmp(code, get_native_address_trans(context, orig + (after-inst)*2)); |
4231 } | 3845 } |
3846 code->cur = tmp.cur; | |
3847 code->last = tmp.last; | |
4232 m68k_handle_deferred(context); | 3848 m68k_handle_deferred(context); |
4233 return orig_start; | 3849 return orig_start; |
4234 } | 3850 } |
4235 } | 3851 } |
4236 | 3852 |
4237 m68k_context * m68k_handle_code_write(uint32_t address, m68k_context * context) | 3853 m68k_context * m68k_handle_code_write(uint32_t address, m68k_context * context) |
4238 { | 3854 { |
4239 uint32_t inst_start = get_instruction_start(context->native_code_map, address | 0xFF0000); | 3855 uint32_t inst_start = get_instruction_start(context->native_code_map, address | 0xFF0000); |
4240 if (inst_start) { | 3856 if (inst_start) { |
3857 x86_68k_options * options = context->options; | |
3858 code_info *code = &options->gen.code; | |
4241 code_ptr dst = get_native_address(context->native_code_map, inst_start); | 3859 code_ptr dst = get_native_address(context->native_code_map, inst_start); |
4242 dst = mov_ir(dst, inst_start, SCRATCH2, SZ_D); | 3860 code_info orig; |
4243 x86_68k_options * options = context->options; | 3861 orig.cur = dst; |
3862 orig.last = dst + 128; | |
3863 mov_ir(&orig, inst_start, options->gen.scratch2, SZ_D); | |
3864 | |
4244 if (!options->retrans_stub) { | 3865 if (!options->retrans_stub) { |
4245 if (options->gen.code_end - options->gen.cur_code < 32) { | 3866 options->retrans_stub = code->cur; |
4246 size_t size = 1024*1024; | 3867 call(code, options->gen.save_context); |
4247 options->gen.cur_code = alloc_code(&size); | 3868 push_r(code, options->gen.context_reg); |
4248 options->gen.code_end = options->gen.cur_code + size; | |
4249 } | |
4250 code_ptr rdst = options->retrans_stub = options->gen.cur_code; | |
4251 rdst = call(rdst, options->gen.save_context); | |
4252 rdst = push_r(rdst, CONTEXT); | |
4253 #ifdef X86_32 | 3869 #ifdef X86_32 |
4254 rdst = push_r(rdst, CONTEXT); | 3870 push_r(code, options->gen.context_reg); |
4255 rdst = push_r(rdst, SCRATCH2); | 3871 push_r(code, options->gen.scratch2); |
4256 #endif | 3872 #endif |
4257 rdst = call(rdst, (code_ptr)m68k_retranslate_inst); | 3873 call(code, (code_ptr)m68k_retranslate_inst); |
4258 #ifdef X86_32 | 3874 #ifdef X86_32 |
4259 rdst = add_ir(rdst, 8, RSP, SZ_D); | 3875 add_ir(code, 8, RSP, SZ_D); |
4260 #endif | 3876 #endif |
4261 rdst = pop_r(rdst, CONTEXT); | 3877 pop_r(code, options->gen.context_reg); |
4262 rdst = mov_rr(rdst, RAX, SCRATCH1, SZ_PTR); | 3878 mov_rr(code, RAX, options->gen.scratch1, SZ_PTR); |
4263 rdst = call(rdst, options->gen.load_context); | 3879 call(code, options->gen.load_context); |
4264 rdst = jmp_r(rdst, SCRATCH1); | 3880 jmp_r(code, options->gen.scratch1); |
4265 options->gen.cur_code = rdst; | 3881 } |
4266 } | 3882 jmp(&orig, options->retrans_stub); |
4267 dst = jmp(dst, options->retrans_stub); | |
4268 } | 3883 } |
4269 return context; | 3884 return context; |
4270 } | 3885 } |
4271 | 3886 |
4272 void insert_breakpoint(m68k_context * context, uint32_t address, code_ptr bp_handler) | 3887 void insert_breakpoint(m68k_context * context, uint32_t address, code_ptr bp_handler) |
4273 { | 3888 { |
4274 static code_ptr bp_stub = NULL; | 3889 static code_ptr bp_stub = NULL; |
4275 code_ptr native = get_native_address_trans(context, address); | 3890 x86_68k_options * opts = context->options; |
4276 code_ptr start_native = native; | 3891 code_info native; |
4277 native = mov_ir(native, address, SCRATCH1, SZ_D); | 3892 native.cur = get_native_address_trans(context, address); |
3893 native.last = native.cur + 128; | |
3894 code_ptr start_native = native.cur; | |
3895 mov_ir(&native, address, opts->gen.scratch1, SZ_D); | |
4278 if (!bp_stub) { | 3896 if (!bp_stub) { |
4279 x86_68k_options * opts = context->options; | 3897 code_info *code = &opts->gen.code; |
4280 code_ptr dst = opts->gen.cur_code; | 3898 check_alloc_code(code, 5); |
4281 code_ptr dst_end = opts->gen.code_end; | 3899 bp_stub = code->cur; |
4282 if (dst_end - dst < 128) { | 3900 call(&native, bp_stub); |
4283 size_t size = 1024*1024; | |
4284 dst = alloc_code(&size); | |
4285 opts->gen.code_end = dst_end = dst + size; | |
4286 } | |
4287 bp_stub = dst; | |
4288 native = call(native, bp_stub); | |
4289 | 3901 |
4290 //Calculate length of prologue | 3902 //Calculate length of prologue |
4291 dst = check_cycles_int(dst, address, opts); | 3903 check_cycles_int(&opts->gen, address); |
4292 int check_int_size = dst-bp_stub; | 3904 int check_int_size = code->cur-bp_stub; |
4293 dst = bp_stub; | 3905 code->cur = bp_stub; |
4294 | 3906 |
4295 //Save context and call breakpoint handler | 3907 //Save context and call breakpoint handler |
4296 dst = call(dst, opts->gen.save_context); | 3908 call(code, opts->gen.save_context); |
4297 dst = push_r(dst, SCRATCH1); | 3909 push_r(code, opts->gen.scratch1); |
4298 #ifdef X86_64 | 3910 #ifdef X86_64 |
4299 dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); | 3911 mov_rr(code, opts->gen.context_reg, RDI, SZ_PTR); |
4300 dst = mov_rr(dst, SCRATCH1, RSI, SZ_D); | 3912 mov_rr(code, opts->gen.scratch1, RSI, SZ_D); |
4301 #else | 3913 #else |
4302 dst = push_r(dst, SCRATCH1); | 3914 push_r(code, opts->gen.scratch1); |
4303 dst = push_r(dst, CONTEXT); | 3915 push_r(code, opts->gen.context_reg); |
4304 #endif | 3916 #endif |
4305 dst = call(dst, bp_handler); | 3917 call(code, bp_handler); |
4306 #ifdef X86_32 | 3918 #ifdef X86_32 |
4307 dst = add_ir(dst, 8, RSP, SZ_D); | 3919 add_ir(code, 8, RSP, SZ_D); |
4308 #endif | 3920 #endif |
4309 dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR); | 3921 mov_rr(code, RAX, opts->gen.context_reg, SZ_PTR); |
4310 //Restore context | 3922 //Restore context |
4311 dst = call(dst, opts->gen.load_context); | 3923 call(code, opts->gen.load_context); |
4312 dst = pop_r(dst, SCRATCH1); | 3924 pop_r(code, opts->gen.scratch1); |
4313 //do prologue stuff | 3925 //do prologue stuff |
4314 dst = cmp_rr(dst, CYCLES, LIMIT, SZ_D); | 3926 cmp_rr(code, opts->gen.cycles, opts->gen.limit, SZ_D); |
4315 code_ptr jmp_off = dst+1; | 3927 code_ptr jmp_off = code->cur + 1; |
4316 dst = jcc(dst, CC_NC, dst + 7); | 3928 jcc(code, CC_NC, code->cur + 7); |
4317 dst = call(dst, opts->gen.handle_cycle_limit_int); | 3929 call(code, opts->gen.handle_cycle_limit_int); |
4318 *jmp_off = dst - (jmp_off+1); | 3930 *jmp_off = code->cur - (jmp_off+1); |
4319 //jump back to body of translated instruction | 3931 //jump back to body of translated instruction |
4320 dst = pop_r(dst, SCRATCH1); | 3932 pop_r(code, opts->gen.scratch1); |
4321 dst = add_ir(dst, check_int_size - (native-start_native), SCRATCH1, SZ_PTR); | 3933 add_ir(code, check_int_size - (native.cur-start_native), opts->gen.scratch1, SZ_PTR); |
4322 dst = jmp_r(dst, SCRATCH1); | 3934 jmp_r(code, opts->gen.scratch1); |
4323 opts->gen.cur_code = dst; | |
4324 } else { | 3935 } else { |
4325 native = call(native, bp_stub); | 3936 call(&native, bp_stub); |
4326 } | 3937 } |
4327 } | 3938 } |
4328 | 3939 |
4329 void remove_breakpoint(m68k_context * context, uint32_t address) | 3940 void remove_breakpoint(m68k_context * context, uint32_t address) |
4330 { | 3941 { |
4331 code_ptr native = get_native_address(context->native_code_map, address); | 3942 code_ptr native = get_native_address(context->native_code_map, address); |
4332 check_cycles_int(native, address, context->options); | 3943 check_cycles_int(context->options, address); |
4333 } | 3944 } |
4334 | 3945 |
4335 void start_68k_context(m68k_context * context, uint32_t address) | 3946 void start_68k_context(m68k_context * context, uint32_t address) |
4336 { | 3947 { |
4337 code_ptr addr = get_native_address_trans(context, address); | 3948 code_ptr addr = get_native_address_trans(context, address); |
4347 start_68k_context(context, address); | 3958 start_68k_context(context, address); |
4348 } | 3959 } |
4349 | 3960 |
4350 code_ptr gen_mem_fun(cpu_options * opts, memmap_chunk * memmap, uint32_t num_chunks, ftype fun_type) | 3961 code_ptr gen_mem_fun(cpu_options * opts, memmap_chunk * memmap, uint32_t num_chunks, ftype fun_type) |
4351 { | 3962 { |
4352 code_ptr dst = opts->cur_code; | 3963 code_info *code = &opts->code; |
4353 code_ptr start = dst; | 3964 code_ptr start = code->cur; |
4354 dst = check_cycles(dst, opts); | 3965 check_cycles(opts); |
4355 dst = cycles(dst, BUS); | 3966 cycles(opts, BUS); |
4356 dst = and_ir(dst, 0xFFFFFF, SCRATCH1, SZ_D); | 3967 and_ir(code, 0xFFFFFF, opts->scratch1, SZ_D); |
4357 code_ptr lb_jcc = NULL, ub_jcc = NULL; | 3968 code_ptr lb_jcc = NULL, ub_jcc = NULL; |
4358 uint8_t is_write = fun_type == WRITE_16 || fun_type == WRITE_8; | 3969 uint8_t is_write = fun_type == WRITE_16 || fun_type == WRITE_8; |
4359 uint8_t adr_reg = is_write ? SCRATCH2 : SCRATCH1; | 3970 uint8_t adr_reg = is_write ? opts->scratch2 : opts->scratch1; |
4360 uint16_t access_flag = is_write ? MMAP_WRITE : MMAP_READ; | 3971 uint16_t access_flag = is_write ? MMAP_WRITE : MMAP_READ; |
4361 uint8_t size = (fun_type == READ_16 || fun_type == WRITE_16) ? SZ_W : SZ_B; | 3972 uint8_t size = (fun_type == READ_16 || fun_type == WRITE_16) ? SZ_W : SZ_B; |
4362 for (uint32_t chunk = 0; chunk < num_chunks; chunk++) | 3973 for (uint32_t chunk = 0; chunk < num_chunks; chunk++) |
4363 { | 3974 { |
4364 if (memmap[chunk].start > 0) { | 3975 if (memmap[chunk].start > 0) { |
4365 dst = cmp_ir(dst, memmap[chunk].start, adr_reg, SZ_D); | 3976 cmp_ir(code, memmap[chunk].start, adr_reg, SZ_D); |
4366 lb_jcc = dst + 1; | 3977 lb_jcc = code->cur + 1; |
4367 dst = jcc(dst, CC_C, dst+2); | 3978 jcc(code, CC_C, code->cur + 2); |
4368 } | 3979 } |
4369 if (memmap[chunk].end < 0x1000000) { | 3980 if (memmap[chunk].end < 0x1000000) { |
4370 dst = cmp_ir(dst, memmap[chunk].end, adr_reg, SZ_D); | 3981 cmp_ir(code, memmap[chunk].end, adr_reg, SZ_D); |
4371 ub_jcc = dst + 1; | 3982 ub_jcc = code->cur + 1; |
4372 dst = jcc(dst, CC_NC, dst+2); | 3983 jcc(code, CC_NC, code->cur + 2); |
4373 } | 3984 } |
4374 | 3985 |
4375 if (memmap[chunk].mask != 0xFFFFFF) { | 3986 if (memmap[chunk].mask != 0xFFFFFF) { |
4376 dst = and_ir(dst, memmap[chunk].mask, adr_reg, SZ_D); | 3987 and_ir(code, memmap[chunk].mask, adr_reg, SZ_D); |
4377 } | 3988 } |
4378 void * cfun; | 3989 void * cfun; |
4379 switch (fun_type) | 3990 switch (fun_type) |
4380 { | 3991 { |
4381 case READ_16: | 3992 case READ_16: |
4394 cfun = NULL; | 4005 cfun = NULL; |
4395 } | 4006 } |
4396 if(memmap[chunk].buffer && memmap[chunk].flags & access_flag) { | 4007 if(memmap[chunk].buffer && memmap[chunk].flags & access_flag) { |
4397 if (memmap[chunk].flags & MMAP_PTR_IDX) { | 4008 if (memmap[chunk].flags & MMAP_PTR_IDX) { |
4398 if (memmap[chunk].flags & MMAP_FUNC_NULL) { | 4009 if (memmap[chunk].flags & MMAP_FUNC_NULL) { |
4399 dst = cmp_irdisp8(dst, 0, CONTEXT, offsetof(m68k_context, mem_pointers) + sizeof(void*) * memmap[chunk].ptr_index, SZ_PTR); | 4010 cmp_irdisp(code, 0, opts->context_reg, offsetof(m68k_context, mem_pointers) + sizeof(void*) * memmap[chunk].ptr_index, SZ_PTR); |
4400 code_ptr not_null = dst+1; | 4011 code_ptr not_null = code->cur + 1; |
4401 dst = jcc(dst, CC_NZ, dst+2); | 4012 jcc(code, CC_NZ, code->cur + 2); |
4402 dst = call(dst, opts->save_context); | 4013 call(code, opts->save_context); |
4403 #ifdef X86_64 | 4014 #ifdef X86_64 |
4404 if (is_write) { | 4015 if (is_write) { |
4405 if (SCRATCH2 != RDI) { | 4016 if (opts->scratch2 != RDI) { |
4406 dst = mov_rr(dst, SCRATCH2, RDI, SZ_D); | 4017 mov_rr(code, opts->scratch2, RDI, SZ_D); |
4407 } | 4018 } |
4408 dst = mov_rr(dst, SCRATCH1, RDX, size); | 4019 mov_rr(code, opts->scratch1, RDX, size); |
4409 } else { | 4020 } else { |
4410 dst = push_r(dst, CONTEXT); | 4021 push_r(code, opts->context_reg); |
4411 dst = mov_rr(dst, SCRATCH1, RDI, SZ_D); | 4022 mov_rr(code, opts->scratch1, RDI, SZ_D); |
4412 } | 4023 } |
4413 dst = test_ir(dst, 8, RSP, SZ_D); | 4024 test_ir(code, 8, RSP, SZ_D); |
4414 code_ptr adjust_rsp = dst+1; | 4025 code_ptr adjust_rsp = code->cur + 1; |
4415 dst = jcc(dst, CC_NZ, dst+2); | 4026 jcc(code, CC_NZ, code->cur + 2); |
4416 dst = call(dst, cfun); | 4027 call(code, cfun); |
4417 code_ptr no_adjust = dst+1; | 4028 code_ptr no_adjust = code->cur + 1; |
4418 dst = jmp(dst, dst+2); | 4029 jmp(code, code->cur + 2); |
4419 *adjust_rsp = dst - (adjust_rsp + 1); | 4030 *adjust_rsp = code->cur - (adjust_rsp + 1); |
4420 dst = sub_ir(dst, 8, RSP, SZ_PTR); | 4031 sub_ir(code, 8, RSP, SZ_PTR); |
4421 dst = call(dst, cfun); | 4032 call(code, cfun); |
4422 dst = add_ir(dst, 8, RSP, SZ_PTR); | 4033 add_ir(code, 8, RSP, SZ_PTR); |
4423 *no_adjust = dst - (no_adjust + 1); | 4034 *no_adjust = code->cur - (no_adjust + 1); |
4424 #else | 4035 #else |
4425 if (is_write) { | 4036 if (is_write) { |
4426 dst = push_r(dst, SCRATCH1); | 4037 push_r(code, opts->scratch1); |
4427 } else { | 4038 } else { |
4428 dst = push_r(dst, CONTEXT);//save CONTEXT for later | 4039 push_r(code, opts->context_reg);//save opts->context_reg for later |
4429 } | 4040 } |
4430 dst = push_r(dst, CONTEXT); | 4041 push_r(code, opts->context_reg); |
4431 dst = push_r(dst, is_write ? SCRATCH2 : SCRATCH1); | 4042 push_r(code, is_write ? opts->scratch2 : opts->scratch1); |
4432 dst = call(dst, cfun); | 4043 call(code, cfun); |
4433 dst = add_ir(dst, is_write ? 12 : 8, RSP, SZ_D); | 4044 add_ir(code, is_write ? 12 : 8, RSP, SZ_D); |
4434 #endif | 4045 #endif |
4435 if (is_write) { | 4046 if (is_write) { |
4436 dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR); | 4047 mov_rr(code, RAX, opts->context_reg, SZ_PTR); |
4437 } else { | 4048 } else { |
4438 dst = pop_r(dst, CONTEXT); | 4049 pop_r(code, opts->context_reg); |
4439 dst = mov_rr(dst, RAX, SCRATCH1, size); | 4050 mov_rr(code, RAX, opts->scratch1, size); |
4440 } | 4051 } |
4441 dst = jmp(dst, opts->load_context); | 4052 jmp(code, opts->load_context); |
4442 | 4053 |
4443 *not_null = dst - (not_null + 1); | 4054 *not_null = code->cur - (not_null + 1); |
4444 } | 4055 } |
4445 if (size == SZ_B) { | 4056 if (size == SZ_B) { |
4446 dst = xor_ir(dst, 1, adr_reg, SZ_D); | 4057 xor_ir(code, 1, adr_reg, SZ_D); |
4447 } | 4058 } |
4448 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, mem_pointers) + sizeof(void*) * memmap[chunk].ptr_index, adr_reg, SZ_PTR); | 4059 add_rdispr(code, opts->context_reg, offsetof(m68k_context, mem_pointers) + sizeof(void*) * memmap[chunk].ptr_index, adr_reg, SZ_PTR); |
4449 if (is_write) { | 4060 if (is_write) { |
4450 dst = mov_rrind(dst, SCRATCH1, SCRATCH2, size); | 4061 mov_rrind(code, opts->scratch1, opts->scratch2, size); |
4451 | 4062 |
4452 } else { | 4063 } else { |
4453 dst = mov_rindr(dst, SCRATCH1, SCRATCH1, size); | 4064 mov_rindr(code, opts->scratch1, opts->scratch1, size); |
4454 } | 4065 } |
4455 } else { | 4066 } else { |
4456 uint8_t tmp_size = size; | 4067 uint8_t tmp_size = size; |
4457 if (size == SZ_B) { | 4068 if (size == SZ_B) { |
4458 if ((memmap[chunk].flags & MMAP_ONLY_ODD) || (memmap[chunk].flags & MMAP_ONLY_EVEN)) { | 4069 if ((memmap[chunk].flags & MMAP_ONLY_ODD) || (memmap[chunk].flags & MMAP_ONLY_EVEN)) { |
4459 dst = bt_ir(dst, 0, adr_reg, SZ_D); | 4070 bt_ir(code, 0, adr_reg, SZ_D); |
4460 code_ptr good_addr = dst + 1; | 4071 code_ptr good_addr = code->cur + 1; |
4461 dst = jcc(dst, (memmap[chunk].flags & MMAP_ONLY_ODD) ? CC_C : CC_NC, dst+2); | 4072 jcc(code, (memmap[chunk].flags & MMAP_ONLY_ODD) ? CC_C : CC_NC, code->cur + 2); |
4462 if (!is_write) { | 4073 if (!is_write) { |
4463 dst = mov_ir(dst, 0xFF, SCRATCH1, SZ_B); | 4074 mov_ir(code, 0xFF, opts->scratch1, SZ_B); |
4464 } | 4075 } |
4465 dst = retn(dst); | 4076 retn(code); |
4466 *good_addr = dst - (good_addr + 1); | 4077 *good_addr = code->cur - (good_addr + 1); |
4467 dst = shr_ir(dst, 1, adr_reg, SZ_D); | 4078 shr_ir(code, 1, adr_reg, SZ_D); |
4468 } else { | 4079 } else { |
4469 dst = xor_ir(dst, 1, adr_reg, SZ_D); | 4080 xor_ir(code, 1, adr_reg, SZ_D); |
4470 } | 4081 } |
4471 } else if ((memmap[chunk].flags & MMAP_ONLY_ODD) || (memmap[chunk].flags & MMAP_ONLY_EVEN)) { | 4082 } else if ((memmap[chunk].flags & MMAP_ONLY_ODD) || (memmap[chunk].flags & MMAP_ONLY_EVEN)) { |
4472 tmp_size = SZ_B; | 4083 tmp_size = SZ_B; |
4473 dst = shr_ir(dst, 1, adr_reg, SZ_D); | 4084 shr_ir(code, 1, adr_reg, SZ_D); |
4474 if ((memmap[chunk].flags & MMAP_ONLY_EVEN) && is_write) { | 4085 if ((memmap[chunk].flags & MMAP_ONLY_EVEN) && is_write) { |
4475 dst = shr_ir(dst, 8, SCRATCH1, SZ_W); | 4086 shr_ir(code, 8, opts->scratch1, SZ_W); |
4476 } | 4087 } |
4477 } | 4088 } |
4478 if ((intptr_t)memmap[chunk].buffer <= 0x7FFFFFFF && (intptr_t)memmap[chunk].buffer >= -2147483648) { | 4089 if ((intptr_t)memmap[chunk].buffer <= 0x7FFFFFFF && (intptr_t)memmap[chunk].buffer >= -2147483648) { |
4479 if (is_write) { | 4090 if (is_write) { |
4480 dst = mov_rrdisp32(dst, SCRATCH1, SCRATCH2, (intptr_t)memmap[chunk].buffer, tmp_size); | 4091 mov_rrdisp(code, opts->scratch1, opts->scratch2, (intptr_t)memmap[chunk].buffer, tmp_size); |
4481 } else { | 4092 } else { |
4482 dst = mov_rdisp32r(dst, SCRATCH1, (intptr_t)memmap[chunk].buffer, SCRATCH1, tmp_size); | 4093 mov_rdispr(code, opts->scratch1, (intptr_t)memmap[chunk].buffer, opts->scratch1, tmp_size); |
4483 } | 4094 } |
4484 } else { | 4095 } else { |
4485 if (is_write) { | 4096 if (is_write) { |
4486 dst = push_r(dst, SCRATCH1); | 4097 push_r(code, opts->scratch1); |
4487 dst = mov_ir(dst, (intptr_t)memmap[chunk].buffer, SCRATCH1, SZ_PTR); | 4098 mov_ir(code, (intptr_t)memmap[chunk].buffer, opts->scratch1, SZ_PTR); |
4488 dst = add_rr(dst, SCRATCH1, SCRATCH2, SZ_PTR); | 4099 add_rr(code, opts->scratch1, opts->scratch2, SZ_PTR); |
4489 dst = pop_r(dst, SCRATCH1); | 4100 pop_r(code, opts->scratch1); |
4490 dst = mov_rrind(dst, SCRATCH1, SCRATCH2, tmp_size); | 4101 mov_rrind(code, opts->scratch1, opts->scratch2, tmp_size); |
4491 } else { | 4102 } else { |
4492 dst = mov_ir(dst, (intptr_t)memmap[chunk].buffer, SCRATCH2, SZ_PTR); | 4103 mov_ir(code, (intptr_t)memmap[chunk].buffer, opts->scratch2, SZ_PTR); |
4493 dst = mov_rindexr(dst, SCRATCH2, SCRATCH1, 1, SCRATCH1, tmp_size); | 4104 mov_rindexr(code, opts->scratch2, opts->scratch1, 1, opts->scratch1, tmp_size); |
4494 } | 4105 } |
4495 } | 4106 } |
4496 if (size != tmp_size && !is_write) { | 4107 if (size != tmp_size && !is_write) { |
4497 if (memmap[chunk].flags & MMAP_ONLY_EVEN) { | 4108 if (memmap[chunk].flags & MMAP_ONLY_EVEN) { |
4498 dst = shl_ir(dst, 8, SCRATCH1, SZ_W); | 4109 shl_ir(code, 8, opts->scratch1, SZ_W); |
4499 dst = mov_ir(dst, 0xFF, SCRATCH1, SZ_B); | 4110 mov_ir(code, 0xFF, opts->scratch1, SZ_B); |
4500 } else { | 4111 } else { |
4501 dst = or_ir(dst, 0xFF00, SCRATCH1, SZ_W); | 4112 or_ir(code, 0xFF00, opts->scratch1, SZ_W); |
4502 } | 4113 } |
4503 } | 4114 } |
4504 } | 4115 } |
4505 if (is_write && (memmap[chunk].flags & MMAP_CODE)) { | 4116 if (is_write && (memmap[chunk].flags & MMAP_CODE)) { |
4506 dst = mov_rr(dst, SCRATCH2, SCRATCH1, SZ_D); | 4117 mov_rr(code, opts->scratch2, opts->scratch1, SZ_D); |
4507 dst = shr_ir(dst, 11, SCRATCH1, SZ_D); | 4118 shr_ir(code, 11, opts->scratch1, SZ_D); |
4508 dst = bt_rrdisp32(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, ram_code_flags), SZ_D); | 4119 bt_rrdisp(code, opts->scratch1, opts->context_reg, offsetof(m68k_context, ram_code_flags), SZ_D); |
4509 code_ptr not_code = dst+1; | 4120 code_ptr not_code = code->cur + 1; |
4510 dst = jcc(dst, CC_NC, dst+2); | 4121 jcc(code, CC_NC, code->cur + 2); |
4511 dst = call(dst, opts->save_context); | 4122 call(code, opts->save_context); |
4512 #ifdef X86_32 | 4123 #ifdef X86_32 |
4513 dst = push_r(dst, CONTEXT); | 4124 push_r(code, opts->context_reg); |
4514 dst = push_r(dst, SCRATCH2); | 4125 push_r(code, opts->scratch2); |
4515 #endif | 4126 #endif |
4516 dst = call(dst, (code_ptr)m68k_handle_code_write); | 4127 call(code, (code_ptr)m68k_handle_code_write); |
4517 #ifdef X86_32 | 4128 #ifdef X86_32 |
4518 dst = add_ir(dst, 8, RSP, SZ_D); | 4129 add_ir(code, 8, RSP, SZ_D); |
4519 #endif | 4130 #endif |
4520 dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR); | 4131 mov_rr(code, RAX, opts->context_reg, SZ_PTR); |
4521 dst = call(dst, opts->load_context); | 4132 call(code, opts->load_context); |
4522 *not_code = dst - (not_code+1); | 4133 *not_code = code->cur - (not_code+1); |
4523 } | 4134 } |
4524 dst = retn(dst); | 4135 retn(code); |
4525 } else if (cfun) { | 4136 } else if (cfun) { |
4526 dst = call(dst, opts->save_context); | 4137 call(code, opts->save_context); |
4527 #ifdef X86_64 | 4138 #ifdef X86_64 |
4528 if (is_write) { | 4139 if (is_write) { |
4529 if (SCRATCH2 != RDI) { | 4140 if (opts->scratch2 != RDI) { |
4530 dst = mov_rr(dst, SCRATCH2, RDI, SZ_D); | 4141 mov_rr(code, opts->scratch2, RDI, SZ_D); |
4531 } | 4142 } |
4532 dst = mov_rr(dst, SCRATCH1, RDX, size); | 4143 mov_rr(code, opts->scratch1, RDX, size); |
4533 } else { | 4144 } else { |
4534 dst = push_r(dst, CONTEXT); | 4145 push_r(code, opts->context_reg); |
4535 dst = mov_rr(dst, SCRATCH1, RDI, SZ_D); | 4146 mov_rr(code, opts->scratch1, RDI, SZ_D); |
4536 } | 4147 } |
4537 dst = test_ir(dst, 8, RSP, SZ_D); | 4148 test_ir(code, 8, RSP, SZ_D); |
4538 code_ptr adjust_rsp = dst+1; | 4149 code_ptr adjust_rsp = code->cur + 1; |
4539 dst = jcc(dst, CC_NZ, dst+2); | 4150 jcc(code, CC_NZ, code->cur + 2); |
4540 dst = call(dst, cfun); | 4151 call(code, cfun); |
4541 code_ptr no_adjust = dst+1; | 4152 code_ptr no_adjust = code->cur + 1; |
4542 dst = jmp(dst, dst+2); | 4153 jmp(code, code->cur + 2); |
4543 *adjust_rsp = dst - (adjust_rsp + 1); | 4154 *adjust_rsp = code->cur - (adjust_rsp + 1); |
4544 dst = sub_ir(dst, 8, RSP, SZ_PTR); | 4155 sub_ir(code, 8, RSP, SZ_PTR); |
4545 dst = call(dst, cfun); | 4156 call(code, cfun); |
4546 dst = add_ir(dst, 8, RSP, SZ_PTR); | 4157 add_ir(code, 8, RSP, SZ_PTR); |
4547 *no_adjust = dst - (no_adjust+1); | 4158 *no_adjust = code->cur - (no_adjust+1); |
4548 #else | 4159 #else |
4549 if (is_write) { | 4160 if (is_write) { |
4550 dst = push_r(dst, SCRATCH1); | 4161 push_r(code, opts->scratch1); |
4551 } else { | 4162 } else { |
4552 dst = push_r(dst, CONTEXT);//save CONTEXT for later | 4163 push_r(code, opts->context_reg);//save opts->context_reg for later |
4553 } | 4164 } |
4554 dst = push_r(dst, CONTEXT); | 4165 push_r(code, opts->context_reg); |
4555 dst = push_r(dst, is_write ? SCRATCH2 : SCRATCH1); | 4166 push_r(code, is_write ? opts->scratch2 : opts->scratch1); |
4556 dst = call(dst, cfun); | 4167 call(code, cfun); |
4557 dst = add_ir(dst, is_write ? 12 : 8, RSP, SZ_D); | 4168 add_ir(code, is_write ? 12 : 8, RSP, SZ_D); |
4558 #endif | 4169 #endif |
4559 if (is_write) { | 4170 if (is_write) { |
4560 dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR); | 4171 mov_rr(code, RAX, opts->context_reg, SZ_PTR); |
4561 } else { | 4172 } else { |
4562 dst = pop_r(dst, CONTEXT); | 4173 pop_r(code, opts->context_reg); |
4563 dst = mov_rr(dst, RAX, SCRATCH1, size); | 4174 mov_rr(code, RAX, opts->scratch1, size); |
4564 } | 4175 } |
4565 dst = jmp(dst, opts->load_context); | 4176 jmp(code, opts->load_context); |
4566 } else { | 4177 } else { |
4567 //Not sure the best course of action here | 4178 //Not sure the best course of action here |
4568 if (!is_write) { | 4179 if (!is_write) { |
4569 dst = mov_ir(dst, size == SZ_B ? 0xFF : 0xFFFF, SCRATCH1, size); | 4180 mov_ir(code, size == SZ_B ? 0xFF : 0xFFFF, opts->scratch1, size); |
4570 } | 4181 } |
4571 dst = retn(dst); | 4182 retn(code); |
4572 } | 4183 } |
4573 if (lb_jcc) { | 4184 if (lb_jcc) { |
4574 *lb_jcc = dst - (lb_jcc+1); | 4185 *lb_jcc = code->cur - (lb_jcc+1); |
4575 lb_jcc = NULL; | 4186 lb_jcc = NULL; |
4576 } | 4187 } |
4577 if (ub_jcc) { | 4188 if (ub_jcc) { |
4578 *ub_jcc = dst - (ub_jcc+1); | 4189 *ub_jcc = code->cur - (ub_jcc+1); |
4579 ub_jcc = NULL; | 4190 ub_jcc = NULL; |
4580 } | 4191 } |
4581 } | 4192 } |
4582 if (!is_write) { | 4193 if (!is_write) { |
4583 dst = mov_ir(dst, size == SZ_B ? 0xFF : 0xFFFF, SCRATCH1, size); | 4194 mov_ir(code, size == SZ_B ? 0xFF : 0xFFFF, opts->scratch1, size); |
4584 } | 4195 } |
4585 dst = retn(dst); | 4196 retn(code); |
4586 opts->cur_code = dst; | |
4587 return start; | 4197 return start; |
4588 } | 4198 } |
4589 | 4199 |
4590 void init_x86_68k_opts(x86_68k_options * opts, memmap_chunk * memmap, uint32_t num_chunks) | 4200 void init_x86_68k_opts(x86_68k_options * opts, memmap_chunk * memmap, uint32_t num_chunks) |
4591 { | 4201 { |
4592 memset(opts, 0, sizeof(*opts)); | 4202 memset(opts, 0, sizeof(*opts)); |
4593 for (int i = 0; i < 8; i++) | 4203 for (int i = 0; i < 8; i++) |
4204 { | |
4594 opts->dregs[i] = opts->aregs[i] = -1; | 4205 opts->dregs[i] = opts->aregs[i] = -1; |
4206 } | |
4595 #ifdef X86_64 | 4207 #ifdef X86_64 |
4596 opts->dregs[0] = R10; | 4208 opts->dregs[0] = R10; |
4597 opts->dregs[1] = R11; | 4209 opts->dregs[1] = R11; |
4598 opts->dregs[2] = R12; | 4210 opts->dregs[2] = R12; |
4599 opts->dregs[3] = R8; | 4211 opts->dregs[3] = R8; |
4605 opts->flag_regs[0] = -1; | 4217 opts->flag_regs[0] = -1; |
4606 opts->flag_regs[1] = RBX; | 4218 opts->flag_regs[1] = RBX; |
4607 opts->flag_regs[2] = RDX; | 4219 opts->flag_regs[2] = RDX; |
4608 opts->flag_regs[3] = BH; | 4220 opts->flag_regs[3] = BH; |
4609 opts->flag_regs[4] = DH; | 4221 opts->flag_regs[4] = DH; |
4222 | |
4223 opts->gen.scratch2 = RDI; | |
4610 #else | 4224 #else |
4611 opts->dregs[0] = RDX; | 4225 opts->dregs[0] = RDX; |
4612 opts->aregs[7] = RDI; | 4226 opts->aregs[7] = RDI; |
4613 | 4227 |
4614 for (int i = 0; i < 5; i++) | 4228 for (int i = 0; i < 5; i++) |
4229 { | |
4615 opts->flag_regs[i] = -1; | 4230 opts->flag_regs[i] = -1; |
4231 } | |
4232 opts->gen.scratch2 = RBX; | |
4616 #endif | 4233 #endif |
4234 opts->gen.context_reg = RSI; | |
4235 opts->gen.cycles = RAX; | |
4236 opts->gen.limit = RBP; | |
4237 opts->gen.scratch1 = RCX; | |
4617 | 4238 |
4618 | 4239 |
4619 opts->gen.native_code_map = malloc(sizeof(native_map_slot) * NATIVE_MAP_CHUNKS); | 4240 opts->gen.native_code_map = malloc(sizeof(native_map_slot) * NATIVE_MAP_CHUNKS); |
4620 memset(opts->gen.native_code_map, 0, sizeof(native_map_slot) * NATIVE_MAP_CHUNKS); | 4241 memset(opts->gen.native_code_map, 0, sizeof(native_map_slot) * NATIVE_MAP_CHUNKS); |
4621 opts->gen.deferred = NULL; | 4242 opts->gen.deferred = NULL; |
4622 size_t size = 1024 * 1024; | 4243 opts->gen.ram_inst_sizes = malloc(sizeof(uint8_t *) * 64); |
4623 opts->gen.cur_code = alloc_code(&size); | 4244 memset(opts->gen.ram_inst_sizes, 0, sizeof(uint8_t *) * 64); |
4624 opts->gen.code_end = opts->gen.cur_code + size; | 4245 |
4625 opts->gen.ram_inst_sizes = malloc(sizeof(code_ptr) * 64); | 4246 code_info *code = &opts->gen.code; |
4626 memset(opts->gen.ram_inst_sizes, 0, sizeof(code_ptr) * 64); | 4247 init_code_info(code); |
4627 | 4248 |
4628 code_ptr dst = opts->gen.cur_code; | 4249 opts->gen.save_context = code->cur; |
4629 | |
4630 opts->gen.save_context = dst; | |
4631 for (int i = 0; i < 5; i++) | 4250 for (int i = 0; i < 5; i++) |
4632 if (opts->flag_regs[i] >= 0) { | 4251 if (opts->flag_regs[i] >= 0) { |
4633 dst = mov_rrdisp8(dst, opts->flag_regs[i], CONTEXT, offsetof(m68k_context, flags) + i, SZ_B); | 4252 mov_rrdisp(code, opts->flag_regs[i], opts->gen.context_reg, offsetof(m68k_context, flags) + i, SZ_B); |
4634 } | 4253 } |
4635 for (int i = 0; i < 8; i++) | 4254 for (int i = 0; i < 8; i++) |
4636 { | 4255 { |
4637 if (opts->dregs[i] >= 0) { | 4256 if (opts->dregs[i] >= 0) { |
4638 dst = mov_rrdisp8(dst, opts->dregs[i], CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t) * i, SZ_D); | 4257 mov_rrdisp(code, opts->dregs[i], opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t) * i, SZ_D); |
4639 } | 4258 } |
4640 if (opts->aregs[i] >= 0) { | 4259 if (opts->aregs[i] >= 0) { |
4641 dst = mov_rrdisp8(dst, opts->aregs[i], CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * i, SZ_D); | 4260 mov_rrdisp(code, opts->aregs[i], opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * i, SZ_D); |
4642 } | 4261 } |
4643 } | 4262 } |
4644 dst = mov_rrdisp8(dst, CYCLES, CONTEXT, offsetof(m68k_context, current_cycle), SZ_D); | 4263 mov_rrdisp(code, opts->gen.cycles, opts->gen.context_reg, offsetof(m68k_context, current_cycle), SZ_D); |
4645 dst = retn(dst); | 4264 retn(code); |
4646 | 4265 |
4647 opts->gen.load_context = dst; | 4266 opts->gen.load_context = code->cur; |
4648 for (int i = 0; i < 5; i++) | 4267 for (int i = 0; i < 5; i++) |
4649 if (opts->flag_regs[i] >= 0) { | 4268 if (opts->flag_regs[i] >= 0) { |
4650 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, flags) + i, opts->flag_regs[i], SZ_B); | 4269 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, flags) + i, opts->flag_regs[i], SZ_B); |
4651 } | 4270 } |
4652 for (int i = 0; i < 8; i++) | 4271 for (int i = 0; i < 8; i++) |
4653 { | 4272 { |
4654 if (opts->dregs[i] >= 0) { | 4273 if (opts->dregs[i] >= 0) { |
4655 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t) * i, opts->dregs[i], SZ_D); | 4274 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t) * i, opts->dregs[i], SZ_D); |
4656 } | 4275 } |
4657 if (opts->aregs[i] >= 0) { | 4276 if (opts->aregs[i] >= 0) { |
4658 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * i, opts->aregs[i], SZ_D); | 4277 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * i, opts->aregs[i], SZ_D); |
4659 } | 4278 } |
4660 } | 4279 } |
4661 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, current_cycle), CYCLES, SZ_D); | 4280 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, current_cycle), CYCLES, SZ_D); |
4662 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, target_cycle), LIMIT, SZ_D); | 4281 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, target_cycle), LIMIT, SZ_D); |
4663 dst = retn(dst); | 4282 retn(code); |
4664 | 4283 |
4665 opts->start_context = (start_fun)dst; | 4284 opts->start_context = (start_fun)code->cur; |
4666 #ifdef X86_64 | 4285 #ifdef X86_64 |
4667 if (SCRATCH2 != RDI) { | 4286 if (opts->gen.scratch2 != RDI) { |
4668 dst = mov_rr(dst, RDI, SCRATCH2, SZ_PTR); | 4287 mov_rr(code, RDI, opts->gen.scratch2, SZ_PTR); |
4669 } | 4288 } |
4670 //save callee save registers | 4289 //save callee save registers |
4671 dst = push_r(dst, RBP); | 4290 push_r(code, RBP); |
4672 dst = push_r(dst, R12); | 4291 push_r(code, R12); |
4673 dst = push_r(dst, R13); | 4292 push_r(code, R13); |
4674 dst = push_r(dst, R14); | 4293 push_r(code, R14); |
4675 dst = push_r(dst, R15); | 4294 push_r(code, R15); |
4676 #else | 4295 #else |
4677 //save callee save registers | 4296 //save callee save registers |
4678 dst = push_r(dst, RBP); | 4297 push_r(code, RBP); |
4679 dst = push_r(dst, RBX); | 4298 push_r(code, RBX); |
4680 dst = push_r(dst, RSI); | 4299 push_r(code, RSI); |
4681 dst = push_r(dst, RDI); | 4300 push_r(code, RDI); |
4682 | 4301 |
4683 dst = mov_rdisp8r(dst, RSP, 20, SCRATCH2, SZ_D); | 4302 mov_rdispr(code, RSP, 20, opts->gen.scratch2, SZ_D); |
4684 dst = mov_rdisp8r(dst, RSP, 24, CONTEXT, SZ_D); | 4303 mov_rdispr(code, RSP, 24, opts->gen.context_reg, SZ_D); |
4685 #endif | 4304 #endif |
4686 dst = call(dst, opts->gen.load_context); | 4305 call(code, opts->gen.load_context); |
4687 dst = call_r(dst, SCRATCH2); | 4306 call_r(code, opts->gen.scratch2); |
4688 dst = call(dst, opts->gen.save_context); | 4307 call(code, opts->gen.save_context); |
4689 #ifdef X86_64 | 4308 #ifdef X86_64 |
4690 //restore callee save registers | 4309 //restore callee save registers |
4691 dst = pop_r(dst, R15); | 4310 pop_r(code, R15); |
4692 dst = pop_r(dst, R14); | 4311 pop_r(code, R14); |
4693 dst = pop_r(dst, R13); | 4312 pop_r(code, R13); |
4694 dst = pop_r(dst, R12); | 4313 pop_r(code, R12); |
4695 dst = pop_r(dst, RBP); | 4314 pop_r(code, RBP); |
4696 #else | 4315 #else |
4697 dst = pop_r(dst, RDI); | 4316 pop_r(code, RDI); |
4698 dst = pop_r(dst, RSI); | 4317 pop_r(code, RSI); |
4699 dst = pop_r(dst, RBX); | 4318 pop_r(code, RBX); |
4700 dst = pop_r(dst, RBP); | 4319 pop_r(code, RBP); |
4701 #endif | 4320 #endif |
4702 dst = retn(dst); | 4321 retn(code); |
4703 | 4322 |
4704 opts->native_addr = dst; | 4323 opts->native_addr = code->cur; |
4705 dst = call(dst, opts->gen.save_context); | 4324 call(code, opts->gen.save_context); |
4706 dst = push_r(dst, CONTEXT); | 4325 push_r(code, opts->gen.context_reg); |
4707 #ifdef X86_64 | 4326 #ifdef X86_64 |
4708 dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); //move context to 1st arg reg | 4327 mov_rr(code, opts->gen.context_reg, RDI, SZ_PTR); //move context to 1st arg reg |
4709 dst = mov_rr(dst, SCRATCH1, RSI, SZ_D); //move address to 2nd arg reg | 4328 mov_rr(code, opts->gen.scratch1, RSI, SZ_D); //move address to 2nd arg reg |
4710 #else | 4329 #else |
4711 dst = push_r(dst, SCRATCH1); | 4330 push_r(code, opts->gen.scratch1); |
4712 dst = push_r(dst, CONTEXT); | 4331 push_r(code, opts->gen.context_reg); |
4713 #endif | 4332 #endif |
4714 dst = call(dst, (code_ptr)get_native_address_trans); | 4333 call(code, (code_ptr)get_native_address_trans); |
4715 #ifdef X86_32 | 4334 #ifdef X86_32 |
4716 dst = add_ir(dst, 8, RSP, SZ_D); | 4335 add_ir(code, 8, RSP, SZ_D); |
4717 #endif | 4336 #endif |
4718 dst = mov_rr(dst, RAX, SCRATCH1, SZ_PTR); //move result to scratch reg | 4337 mov_rr(code, RAX, opts->gen.scratch1, SZ_PTR); //move result to scratch reg |
4719 dst = pop_r(dst, CONTEXT); | 4338 pop_r(code, opts->gen.context_reg); |
4720 dst = call(dst, opts->gen.load_context); | 4339 call(code, opts->gen.load_context); |
4721 dst = retn(dst); | 4340 retn(code); |
4722 | 4341 |
4723 opts->native_addr_and_sync = dst; | 4342 opts->native_addr_and_sync = code->cur; |
4724 dst = call(dst, opts->gen.save_context); | 4343 call(code, opts->gen.save_context); |
4725 dst = push_r(dst, SCRATCH1); | 4344 push_r(code, opts->gen.scratch1); |
4726 #ifdef X86_64 | 4345 #ifdef X86_64 |
4727 dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); | 4346 mov_rr(code, opts->gen.context_reg, RDI, SZ_PTR); |
4728 dst = xor_rr(dst, RSI, RSI, SZ_D); | 4347 xor_rr(code, RSI, RSI, SZ_D); |
4729 dst = test_ir(dst, 8, RSP, SZ_PTR); //check stack alignment | 4348 test_ir(code, 8, RSP, SZ_PTR); //check stack alignment |
4730 code_ptr do_adjust_rsp = dst+1; | 4349 code_ptr do_adjust_rsp = code->cur + 1; |
4731 dst = jcc(dst, CC_NZ, dst+2); | 4350 jcc(code, CC_NZ, code->cur + 2); |
4732 dst = call(dst, (code_ptr)sync_components); | 4351 call(code, (code_ptr)sync_components); |
4733 code_ptr no_adjust_rsp = dst+1; | 4352 code_ptr no_adjust_rsp = code->cur + 1; |
4734 dst = jmp(dst, dst+2); | 4353 jmp(code, code->cur + 2); |
4735 *do_adjust_rsp = dst - (do_adjust_rsp+1); | 4354 *do_adjust_rsp = code->cur - (do_adjust_rsp+1); |
4736 dst = sub_ir(dst, 8, RSP, SZ_PTR); | 4355 sub_ir(code, 8, RSP, SZ_PTR); |
4737 dst = call(dst, (code_ptr)sync_components); | 4356 call(code, (code_ptr)sync_components); |
4738 dst = add_ir(dst, 8, RSP, SZ_PTR); | 4357 add_ir(code, 8, RSP, SZ_PTR); |
4739 *no_adjust_rsp = dst - (no_adjust_rsp+1); | 4358 *no_adjust_rsp = code->cur - (no_adjust_rsp+1); |
4740 dst = pop_r(dst, RSI); | 4359 pop_r(code, RSI); |
4741 dst = push_r(dst, RAX); | 4360 push_r(code, RAX); |
4742 dst = mov_rr(dst, RAX, RDI, SZ_PTR); | 4361 mov_rr(code, RAX, RDI, SZ_PTR); |
4743 dst = call(dst, (code_ptr)get_native_address_trans); | 4362 call(code, (code_ptr)get_native_address_trans); |
4744 #else | 4363 #else |
4745 //TODO: Add support for pushing a constant in gen_x86 | 4364 //TODO: Add support for pushing a constant in gen_x86 |
4746 dst = xor_rr(dst, RAX, RAX, SZ_D); | 4365 xor_rr(code, RAX, RAX, SZ_D); |
4747 dst = push_r(dst, RAX); | 4366 push_r(code, RAX); |
4748 dst = push_r(dst, CONTEXT); | 4367 push_r(code, opts->gen.context_reg); |
4749 dst = call(dst, (code_ptr)sync_components); | 4368 call(code, (code_ptr)sync_components); |
4750 dst = add_ir(dst, 8, RSP, SZ_D); | 4369 add_ir(code, 8, RSP, SZ_D); |
4751 dst = pop_r(dst, RSI); //restore saved address from SCRATCH1 | 4370 pop_r(code, RSI); //restore saved address from opts->gen.scratch1 |
4752 dst = push_r(dst, RAX); //save context pointer for later | 4371 push_r(code, RAX); //save context pointer for later |
4753 dst = push_r(dst, RSI); //2nd arg -- address | 4372 push_r(code, RSI); //2nd arg -- address |
4754 dst = push_r(dst, RAX); //1st arg -- context pointer | 4373 push_r(code, RAX); //1st arg -- context pointer |
4755 dst = call(dst, (code_ptr)get_native_address_trans); | 4374 call(code, (code_ptr)get_native_address_trans); |
4756 dst = add_ir(dst, 8, RSP, SZ_D); | 4375 add_ir(code, 8, RSP, SZ_D); |
4757 #endif | 4376 #endif |
4758 | 4377 |
4759 dst = mov_rr(dst, RAX, SCRATCH1, SZ_PTR); //move result to scratch reg | 4378 mov_rr(code, RAX, opts->gen.scratch1, SZ_PTR); //move result to scratch reg |
4760 dst = pop_r(dst, CONTEXT); | 4379 pop_r(code, opts->gen.context_reg); |
4761 dst = call(dst, opts->gen.load_context); | 4380 call(code, opts->gen.load_context); |
4762 dst = retn(dst); | 4381 retn(code); |
4763 | 4382 |
4764 opts->gen.handle_cycle_limit = dst; | 4383 opts->gen.handle_cycle_limit = code->cur; |
4765 dst = cmp_rdisp8r(dst, CONTEXT, offsetof(m68k_context, sync_cycle), CYCLES, SZ_D); | 4384 cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, sync_cycle), CYCLES, SZ_D); |
4766 code_ptr skip_sync = dst+1; | 4385 code_ptr skip_sync = code->cur + 1; |
4767 dst = jcc(dst, CC_C, dst+2); | 4386 jcc(code, CC_C, code->cur + 2); |
4768 opts->do_sync = dst; | 4387 opts->do_sync = code->cur; |
4769 dst = push_r(dst, SCRATCH1); | 4388 push_r(code, opts->gen.scratch1); |
4770 dst = push_r(dst, SCRATCH2); | 4389 push_r(code, opts->gen.scratch2); |
4771 dst = call(dst, opts->gen.save_context); | 4390 call(code, opts->gen.save_context); |
4772 #ifdef X86_64 | 4391 #ifdef X86_64 |
4773 dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); | 4392 mov_rr(code, opts->gen.context_reg, RDI, SZ_PTR); |
4774 dst = xor_rr(dst, RSI, RSI, SZ_D); | 4393 xor_rr(code, RSI, RSI, SZ_D); |
4775 dst = test_ir(dst, 8, RSP, SZ_D); | 4394 test_ir(code, 8, RSP, SZ_D); |
4776 code_ptr adjust_rsp = dst+1; | 4395 code_ptr adjust_rsp = code->cur + 1; |
4777 dst = jcc(dst, CC_NZ, dst+2); | 4396 jcc(code, CC_NZ, code->cur + 2); |
4778 dst = call(dst, (code_ptr)sync_components); | 4397 call(code, (code_ptr)sync_components); |
4779 code_ptr no_adjust = dst+1; | 4398 code_ptr no_adjust = code->cur + 1; |
4780 dst = jmp(dst, dst+2); | 4399 jmp(code, code->cur + 2); |
4781 *adjust_rsp = dst - (adjust_rsp + 1); | 4400 *adjust_rsp = code->cur - (adjust_rsp + 1); |
4782 dst = sub_ir(dst, 8, RSP, SZ_PTR); | 4401 sub_ir(code, 8, RSP, SZ_PTR); |
4783 dst = call(dst, (code_ptr)sync_components); | 4402 call(code, (code_ptr)sync_components); |
4784 dst = add_ir(dst, 8, RSP, SZ_PTR); | 4403 add_ir(code, 8, RSP, SZ_PTR); |
4785 *no_adjust = dst - (no_adjust+1); | 4404 *no_adjust = code->cur - (no_adjust+1); |
4786 #else | 4405 #else |
4787 //TODO: Add support for pushing a constant in gen_x86 | 4406 //TODO: Add support for pushing a constant in gen_x86 |
4788 dst = xor_rr(dst, RAX, RAX, SZ_D); | 4407 xor_rr(code, RAX, RAX, SZ_D); |
4789 dst = push_r(dst, RAX); | 4408 push_r(code, RAX); |
4790 dst = push_r(dst, CONTEXT); | 4409 push_r(code, opts->gen.context_reg); |
4791 dst = call(dst, (code_ptr)sync_components); | 4410 call(code, (code_ptr)sync_components); |
4792 dst = add_ir(dst, 8, RSP, SZ_D); | 4411 add_ir(code, 8, RSP, SZ_D); |
4793 #endif | 4412 #endif |
4794 dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR); | 4413 mov_rr(code, RAX, opts->gen.context_reg, SZ_PTR); |
4795 dst = call(dst, opts->gen.load_context); | 4414 call(code, opts->gen.load_context); |
4796 dst = pop_r(dst, SCRATCH2); | 4415 pop_r(code, opts->gen.scratch2); |
4797 dst = pop_r(dst, SCRATCH1); | 4416 pop_r(code, opts->gen.scratch1); |
4798 *skip_sync = dst - (skip_sync+1); | 4417 *skip_sync = code->cur - (skip_sync+1); |
4799 dst = retn(dst); | 4418 retn(code); |
4800 | |
4801 opts->gen.cur_code = dst; | |
4802 | 4419 |
4803 opts->read_16 = gen_mem_fun(&opts->gen, memmap, num_chunks, READ_16); | 4420 opts->read_16 = gen_mem_fun(&opts->gen, memmap, num_chunks, READ_16); |
4804 opts->read_8 = gen_mem_fun(&opts->gen, memmap, num_chunks, READ_8); | 4421 opts->read_8 = gen_mem_fun(&opts->gen, memmap, num_chunks, READ_8); |
4805 opts->write_16 = gen_mem_fun(&opts->gen, memmap, num_chunks, WRITE_16); | 4422 opts->write_16 = gen_mem_fun(&opts->gen, memmap, num_chunks, WRITE_16); |
4806 opts->write_8 = gen_mem_fun(&opts->gen, memmap, num_chunks, WRITE_8); | 4423 opts->write_8 = gen_mem_fun(&opts->gen, memmap, num_chunks, WRITE_8); |
4807 | 4424 |
4808 dst = opts->gen.cur_code; | 4425 opts->read_32 = code->cur; |
4809 | 4426 push_r(code, opts->gen.scratch1); |
4810 opts->read_32 = dst; | 4427 call(code, opts->read_16); |
4811 dst = push_r(dst, SCRATCH1); | 4428 mov_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_W); |
4812 dst = call(dst, opts->read_16); | 4429 pop_r(code, opts->gen.scratch1); |
4813 dst = mov_rr(dst, SCRATCH1, SCRATCH2, SZ_W); | 4430 push_r(code, opts->gen.scratch2); |
4814 dst = pop_r(dst, SCRATCH1); | 4431 add_ir(code, 2, opts->gen.scratch1, SZ_D); |
4815 dst = push_r(dst, SCRATCH2); | 4432 call(code, opts->read_16); |
4816 dst = add_ir(dst, 2, SCRATCH1, SZ_D); | 4433 pop_r(code, opts->gen.scratch2); |
4817 dst = call(dst, opts->read_16); | 4434 movzx_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_W, SZ_D); |
4818 dst = pop_r(dst, SCRATCH2); | 4435 shl_ir(code, 16, opts->gen.scratch2, SZ_D); |
4819 dst = movzx_rr(dst, SCRATCH1, SCRATCH1, SZ_W, SZ_D); | 4436 or_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D); |
4820 dst = shl_ir(dst, 16, SCRATCH2, SZ_D); | 4437 retn(code); |
4821 dst = or_rr(dst, SCRATCH2, SCRATCH1, SZ_D); | 4438 |
4822 dst = retn(dst); | 4439 opts->write_32_lowfirst = code->cur; |
4823 | 4440 push_r(code, opts->gen.scratch2); |
4824 opts->write_32_lowfirst = dst; | 4441 push_r(code, opts->gen.scratch1); |
4825 dst = push_r(dst, SCRATCH2); | 4442 add_ir(code, 2, opts->gen.scratch2, SZ_D); |
4826 dst = push_r(dst, SCRATCH1); | 4443 call(code, opts->write_16); |
4827 dst = add_ir(dst, 2, SCRATCH2, SZ_D); | 4444 pop_r(code, opts->gen.scratch1); |
4828 dst = call(dst, opts->write_16); | 4445 pop_r(code, opts->gen.scratch2); |
4829 dst = pop_r(dst, SCRATCH1); | 4446 shr_ir(code, 16, opts->gen.scratch1, SZ_D); |
4830 dst = pop_r(dst, SCRATCH2); | 4447 jmp(code, opts->write_16); |
4831 dst = shr_ir(dst, 16, SCRATCH1, SZ_D); | 4448 |
4832 dst = jmp(dst, opts->write_16); | 4449 opts->write_32_highfirst = code->cur; |
4833 | 4450 push_r(code, opts->gen.scratch1); |
4834 opts->write_32_highfirst = dst; | 4451 push_r(code, opts->gen.scratch2); |
4835 dst = push_r(dst, SCRATCH1); | 4452 shr_ir(code, 16, opts->gen.scratch1, SZ_D); |
4836 dst = push_r(dst, SCRATCH2); | 4453 call(code, opts->write_16); |
4837 dst = shr_ir(dst, 16, SCRATCH1, SZ_D); | 4454 pop_r(code, opts->gen.scratch2); |
4838 dst = call(dst, opts->write_16); | 4455 pop_r(code, opts->gen.scratch1); |
4839 dst = pop_r(dst, SCRATCH2); | 4456 add_ir(code, 2, opts->gen.scratch2, SZ_D); |
4840 dst = pop_r(dst, SCRATCH1); | 4457 jmp(code, opts->write_16); |
4841 dst = add_ir(dst, 2, SCRATCH2, SZ_D); | 4458 |
4842 dst = jmp(dst, opts->write_16); | 4459 opts->get_sr = code->cur; |
4843 | 4460 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, status), opts->gen.scratch1, SZ_B); |
4844 opts->get_sr = dst; | 4461 shl_ir(code, 8, opts->gen.scratch1, SZ_W); |
4845 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, status), SCRATCH1, SZ_B); | |
4846 dst = shl_ir(dst, 8, SCRATCH1, SZ_W); | |
4847 if (opts->flag_regs[FLAG_X] >= 0) { | 4462 if (opts->flag_regs[FLAG_X] >= 0) { |
4848 dst = mov_rr(dst, opts->flag_regs[FLAG_X], SCRATCH1, SZ_B); | 4463 mov_rr(code, opts->flag_regs[FLAG_X], opts->gen.scratch1, SZ_B); |
4849 } else { | 4464 } else { |
4850 int8_t offset = offsetof(m68k_context, flags); | 4465 int8_t offset = offsetof(m68k_context, flags); |
4851 if (offset) { | 4466 if (offset) { |
4852 dst = mov_rdisp8r(dst, CONTEXT, offset, SCRATCH1, SZ_B); | 4467 mov_rdispr(code, opts->gen.context_reg, offset, opts->gen.scratch1, SZ_B); |
4853 } else { | 4468 } else { |
4854 dst = mov_rindr(dst, CONTEXT, SCRATCH1, SZ_B); | 4469 mov_rindr(code, opts->gen.context_reg, opts->gen.scratch1, SZ_B); |
4855 } | 4470 } |
4856 } | 4471 } |
4857 for (int flag = FLAG_N; flag <= FLAG_C; flag++) | 4472 for (int flag = FLAG_N; flag <= FLAG_C; flag++) |
4858 { | 4473 { |
4859 dst = shl_ir(dst, 1, SCRATCH1, SZ_B); | 4474 shl_ir(code, 1, opts->gen.scratch1, SZ_B); |
4860 if (opts->flag_regs[flag] >= 0) { | 4475 if (opts->flag_regs[flag] >= 0) { |
4861 dst = or_rr(dst, opts->flag_regs[flag], SCRATCH1, SZ_B); | 4476 or_rr(code, opts->flag_regs[flag], opts->gen.scratch1, SZ_B); |
4862 } else { | 4477 } else { |
4863 dst = or_rdisp8r(dst, CONTEXT, offsetof(m68k_context, flags) + flag, SCRATCH1, SZ_B); | 4478 or_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, flags) + flag, opts->gen.scratch1, SZ_B); |
4864 } | 4479 } |
4865 } | 4480 } |
4866 dst = retn(dst); | 4481 retn(code); |
4867 | 4482 |
4868 opts->set_sr = dst; | 4483 opts->set_sr = code->cur; |
4869 for (int flag = FLAG_C; flag >= FLAG_X; flag--) | 4484 for (int flag = FLAG_C; flag >= FLAG_X; flag--) |
4870 { | 4485 { |
4871 dst = rcr_ir(dst, 1, SCRATCH1, SZ_B); | 4486 rcr_ir(code, 1, opts->gen.scratch1, SZ_B); |
4872 if (opts->flag_regs[flag] >= 0) { | 4487 if (opts->flag_regs[flag] >= 0) { |
4873 dst = setcc_r(dst, CC_C, opts->flag_regs[flag]); | 4488 setcc_r(code, CC_C, opts->flag_regs[flag]); |
4874 } else { | 4489 } else { |
4875 int8_t offset = offsetof(m68k_context, flags) + flag; | 4490 int8_t offset = offsetof(m68k_context, flags) + flag; |
4876 if (offset) { | 4491 if (offset) { |
4877 dst = setcc_rdisp8(dst, CC_C, CONTEXT, offset); | 4492 setcc_rdisp(code, CC_C, opts->gen.context_reg, offset); |
4878 } else { | 4493 } else { |
4879 dst = setcc_rind(dst, CC_C, CONTEXT); | 4494 setcc_rind(code, CC_C, opts->gen.context_reg); |
4880 } | 4495 } |
4881 } | 4496 } |
4882 } | 4497 } |
4883 dst = shr_ir(dst, 8, SCRATCH1, SZ_W); | 4498 shr_ir(code, 8, opts->gen.scratch1, SZ_W); |
4884 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, status), SZ_B); | 4499 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
4885 dst = retn(dst); | 4500 retn(code); |
4886 | 4501 |
4887 opts->set_ccr = dst; | 4502 opts->set_ccr = code->cur; |
4888 for (int flag = FLAG_C; flag >= FLAG_X; flag--) | 4503 for (int flag = FLAG_C; flag >= FLAG_X; flag--) |
4889 { | 4504 { |
4890 dst = rcr_ir(dst, 1, SCRATCH1, SZ_B); | 4505 rcr_ir(code, 1, opts->gen.scratch1, SZ_B); |
4891 if (opts->flag_regs[flag] >= 0) { | 4506 if (opts->flag_regs[flag] >= 0) { |
4892 dst = setcc_r(dst, CC_C, opts->flag_regs[flag]); | 4507 setcc_r(code, CC_C, opts->flag_regs[flag]); |
4893 } else { | 4508 } else { |
4894 int8_t offset = offsetof(m68k_context, flags) + flag; | 4509 int8_t offset = offsetof(m68k_context, flags) + flag; |
4895 if (offset) { | 4510 if (offset) { |
4896 dst = setcc_rdisp8(dst, CC_C, CONTEXT, offset); | 4511 setcc_rdisp(code, CC_C, opts->gen.context_reg, offset); |
4897 } else { | 4512 } else { |
4898 dst = setcc_rind(dst, CC_C, CONTEXT); | 4513 setcc_rind(code, CC_C, opts->gen.context_reg); |
4899 } | 4514 } |
4900 } | 4515 } |
4901 } | 4516 } |
4902 dst = retn(dst); | 4517 retn(code); |
4903 | 4518 |
4904 opts->gen.handle_cycle_limit_int = dst; | 4519 opts->gen.handle_cycle_limit_int = code->cur; |
4905 dst = cmp_rdisp8r(dst, CONTEXT, offsetof(m68k_context, int_cycle), CYCLES, SZ_D); | 4520 cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_cycle), CYCLES, SZ_D); |
4906 code_ptr do_int = dst+1; | 4521 code_ptr do_int = code->cur + 1; |
4907 dst = jcc(dst, CC_NC, dst+2); | 4522 jcc(code, CC_NC, code->cur + 2); |
4908 dst = cmp_rdisp8r(dst, CONTEXT, offsetof(m68k_context, sync_cycle), CYCLES, SZ_D); | 4523 cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, sync_cycle), CYCLES, SZ_D); |
4909 skip_sync = dst+1; | 4524 skip_sync = code->cur + 1; |
4910 dst = jcc(dst, CC_C, dst+2); | 4525 jcc(code, CC_C, code->cur + 2); |
4911 dst = call(dst, opts->gen.save_context); | 4526 call(code, opts->gen.save_context); |
4912 #ifdef X86_64 | 4527 #ifdef X86_64 |
4913 dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); | 4528 mov_rr(code, opts->gen.context_reg, RDI, SZ_PTR); |
4914 dst = mov_rr(dst, SCRATCH1, RSI, SZ_D); | 4529 mov_rr(code, opts->gen.scratch1, RSI, SZ_D); |
4915 dst = test_ir(dst, 8, RSP, SZ_D); | 4530 test_ir(code, 8, RSP, SZ_D); |
4916 adjust_rsp = dst+1; | 4531 adjust_rsp = code->cur + 1; |
4917 dst = jcc(dst, CC_NZ, dst+2); | 4532 jcc(code, CC_NZ, code->cur + 2); |
4918 dst = call(dst, (code_ptr)sync_components); | 4533 call(code, (code_ptr)sync_components); |
4919 no_adjust = dst+1; | 4534 no_adjust = code->cur + 1; |
4920 dst = jmp(dst, dst+2); | 4535 jmp(code, code->cur + 2); |
4921 *adjust_rsp = dst - (adjust_rsp + 1); | 4536 *adjust_rsp = code->cur - (adjust_rsp + 1); |
4922 dst = sub_ir(dst, 8, RSP, SZ_PTR); | 4537 sub_ir(code, 8, RSP, SZ_PTR); |
4923 dst = call(dst, (code_ptr)sync_components); | 4538 call(code, (code_ptr)sync_components); |
4924 dst = add_ir(dst, 8, RSP, SZ_PTR); | 4539 add_ir(code, 8, RSP, SZ_PTR); |
4925 *no_adjust = dst - (no_adjust+1); | 4540 *no_adjust = code->cur - (no_adjust+1); |
4926 #else | 4541 #else |
4927 dst = push_r(dst, SCRATCH1); | 4542 push_r(code, opts->gen.scratch1); |
4928 dst = push_r(dst, CONTEXT); | 4543 push_r(code, opts->gen.context_reg); |
4929 dst = call(dst, (code_ptr)sync_components); | 4544 call(code, (code_ptr)sync_components); |
4930 dst = add_ir(dst, 8, RSP, SZ_D); | 4545 add_ir(code, 8, RSP, SZ_D); |
4931 #endif | 4546 #endif |
4932 dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR); | 4547 mov_rr(code, RAX, opts->gen.context_reg, SZ_PTR); |
4933 dst = jmp(dst, opts->gen.load_context); | 4548 jmp(code, opts->gen.load_context); |
4934 *skip_sync = dst - (skip_sync+1); | 4549 *skip_sync = code->cur - (skip_sync+1); |
4935 dst = retn(dst); | 4550 retn(code); |
4936 *do_int = dst - (do_int+1); | 4551 *do_int = code->cur - (do_int+1); |
4937 //set target cycle to sync cycle | 4552 //set target cycle to sync cycle |
4938 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, sync_cycle), LIMIT, SZ_D); | 4553 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, sync_cycle), LIMIT, SZ_D); |
4939 //swap USP and SSP if not already in supervisor mode | 4554 //swap USP and SSP if not already in supervisor mode |
4940 dst = bt_irdisp8(dst, 5, CONTEXT, offsetof(m68k_context, status), SZ_B); | 4555 bt_irdisp(code, 5, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
4941 code_ptr already_supervisor = dst+1; | 4556 code_ptr already_supervisor = code->cur + 1; |
4942 dst = jcc(dst, CC_C, dst+2); | 4557 jcc(code, CC_C, code->cur + 2); |
4943 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SCRATCH2, SZ_D); | 4558 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->gen.scratch2, SZ_D); |
4944 dst = mov_rrdisp8(dst, opts->aregs[7], CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); | 4559 mov_rrdisp(code, opts->aregs[7], opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); |
4945 dst = mov_rr(dst, SCRATCH2, opts->aregs[7], SZ_D); | 4560 mov_rr(code, opts->gen.scratch2, opts->aregs[7], SZ_D); |
4946 *already_supervisor = dst - (already_supervisor+1); | 4561 *already_supervisor = code->cur - (already_supervisor+1); |
4947 //save PC | 4562 //save PC |
4948 dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); | 4563 sub_ir(code, 4, opts->aregs[7], SZ_D); |
4949 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); | 4564 mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); |
4950 dst = call(dst, opts->write_32_lowfirst); | 4565 call(code, opts->write_32_lowfirst); |
4951 //save status register | 4566 //save status register |
4952 dst = sub_ir(dst, 2, opts->aregs[7], SZ_D); | 4567 sub_ir(code, 2, opts->aregs[7], SZ_D); |
4953 dst = call(dst, opts->get_sr); | 4568 call(code, opts->get_sr); |
4954 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); | 4569 mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); |
4955 dst = call(dst, opts->write_16); | 4570 call(code, opts->write_16); |
4956 //update status register | 4571 //update status register |
4957 dst = and_irdisp8(dst, 0xF8, CONTEXT, offsetof(m68k_context, status), SZ_B); | 4572 and_irdisp(code, 0xF8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
4958 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, int_num), SCRATCH1, SZ_B); | 4573 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_num), opts->gen.scratch1, SZ_B); |
4959 dst = or_ir(dst, 0x20, SCRATCH1, SZ_B); | 4574 or_ir(code, 0x20, opts->gen.scratch1, SZ_B); |
4960 dst = or_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, status), SZ_B); | 4575 or_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
4961 //calculate interrupt vector address | 4576 //calculate interrupt vector address |
4962 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, int_num), SCRATCH1, SZ_D); | 4577 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_num), opts->gen.scratch1, SZ_D); |
4963 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, int_ack), SZ_W); | 4578 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, int_ack), SZ_W); |
4964 dst = shl_ir(dst, 2, SCRATCH1, SZ_D); | 4579 shl_ir(code, 2, opts->gen.scratch1, SZ_D); |
4965 dst = add_ir(dst, 0x60, SCRATCH1, SZ_D); | 4580 add_ir(code, 0x60, opts->gen.scratch1, SZ_D); |
4966 dst = call(dst, opts->read_32); | 4581 call(code, opts->read_32); |
4967 dst = call(dst, opts->native_addr_and_sync); | 4582 call(code, opts->native_addr_and_sync); |
4968 dst = cycles(dst, 24); | 4583 cycles(&opts->gen, 24); |
4969 //discard function return address | 4584 //discard function return address |
4970 dst = pop_r(dst, SCRATCH2); | 4585 pop_r(code, opts->gen.scratch2); |
4971 dst = jmp_r(dst, SCRATCH1); | 4586 jmp_r(code, opts->gen.scratch1); |
4972 | 4587 |
4973 opts->trap = dst; | 4588 opts->trap = code->cur; |
4974 dst = push_r(dst, SCRATCH2); | 4589 push_r(code, opts->gen.scratch2); |
4975 //swap USP and SSP if not already in supervisor mode | 4590 //swap USP and SSP if not already in supervisor mode |
4976 dst = bt_irdisp8(dst, 5, CONTEXT, offsetof(m68k_context, status), SZ_B); | 4591 bt_irdisp(code, 5, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
4977 already_supervisor = dst+1; | 4592 already_supervisor = code->cur + 1; |
4978 dst = jcc(dst, CC_C, dst+2); | 4593 jcc(code, CC_C, code->cur + 2); |
4979 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SCRATCH2, SZ_D); | 4594 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->gen.scratch2, SZ_D); |
4980 dst = mov_rrdisp8(dst, opts->aregs[7], CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); | 4595 mov_rrdisp(code, opts->aregs[7], opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); |
4981 dst = mov_rr(dst, SCRATCH2, opts->aregs[7], SZ_D); | 4596 mov_rr(code, opts->gen.scratch2, opts->aregs[7], SZ_D); |
4982 *already_supervisor = dst - (already_supervisor+1); | 4597 *already_supervisor = code->cur - (already_supervisor+1); |
4983 //save PC | 4598 //save PC |
4984 dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); | 4599 sub_ir(code, 4, opts->aregs[7], SZ_D); |
4985 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); | 4600 mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); |
4986 dst = call(dst, opts->write_32_lowfirst); | 4601 call(code, opts->write_32_lowfirst); |
4987 //save status register | 4602 //save status register |
4988 dst = sub_ir(dst, 2, opts->aregs[7], SZ_D); | 4603 sub_ir(code, 2, opts->aregs[7], SZ_D); |
4989 dst = call(dst, opts->get_sr); | 4604 call(code, opts->get_sr); |
4990 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); | 4605 mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); |
4991 dst = call(dst, opts->write_16); | 4606 call(code, opts->write_16); |
4992 //set supervisor bit | 4607 //set supervisor bit |
4993 dst = or_irdisp8(dst, 0x20, CONTEXT, offsetof(m68k_context, status), SZ_B); | 4608 or_irdisp(code, 0x20, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
4994 //calculate vector address | 4609 //calculate vector address |
4995 dst = pop_r(dst, SCRATCH1); | 4610 pop_r(code, opts->gen.scratch1); |
4996 dst = shl_ir(dst, 2, SCRATCH1, SZ_D); | 4611 shl_ir(code, 2, opts->gen.scratch1, SZ_D); |
4997 dst = call(dst, opts->read_32); | 4612 call(code, opts->read_32); |
4998 dst = call(dst, opts->native_addr_and_sync); | 4613 call(code, opts->native_addr_and_sync); |
4999 dst = cycles(dst, 18); | 4614 cycles(&opts->gen, 18); |
5000 dst = jmp_r(dst, SCRATCH1); | 4615 jmp_r(code, opts->gen.scratch1); |
5001 | |
5002 opts->gen.cur_code = dst; | |
5003 } | 4616 } |
5004 | 4617 |
5005 void init_68k_context(m68k_context * context, native_map_slot * native_code_map, void * opts) | 4618 void init_68k_context(m68k_context * context, native_map_slot * native_code_map, void * opts) |
5006 { | 4619 { |
5007 memset(context, 0, sizeof(m68k_context)); | 4620 memset(context, 0, sizeof(m68k_context)); |