comparison m68k_core_x86.c @ 571:c90fc522e7e3

Refactor translat_m68k_src and translate_m68k_dst into a single function
author Michael Pavone <pavone@retrodev.com>
date Sun, 02 Mar 2014 17:53:32 -0800
parents 76bba9ffe351
children 1594525e2157
comparison
equal deleted inserted replaced
570:76bba9ffe351 571:c90fc522e7e3
179 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, flags) + flag1, opts->gen.scratch1, SZ_B); 179 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, flags) + flag1, opts->gen.scratch1, SZ_B);
180 cmp_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, flags) + flag2, SZ_B); 180 cmp_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, flags) + flag2, SZ_B);
181 } 181 }
182 } 182 }
183 183
184 void translate_m68k_src(m68kinst * inst, x86_ea * ea, m68k_options * opts) 184 void translate_m68k_op(m68kinst * inst, x86_ea * ea, m68k_options * opts, uint8_t dst)
185 { 185 {
186 code_info *code = &opts->gen.code; 186 code_info *code = &opts->gen.code;
187 int8_t reg = native_reg(&(inst->src), opts); 187 m68k_op_info *op = dst ? &inst->dst : &inst->src;
188 int8_t reg = native_reg(op, opts);
188 uint8_t sec_reg; 189 uint8_t sec_reg;
189 int32_t dec_amount,inc_amount; 190 int32_t dec_amount,inc_amount;
190 if (reg >= 0) { 191 if (reg >= 0) {
191 ea->mode = MODE_REG_DIRECT; 192 ea->mode = MODE_REG_DIRECT;
192 if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) { 193 if (!dst && inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) {
193 movsx_rr(code, reg, opts->gen.scratch1, SZ_W, SZ_D); 194 movsx_rr(code, reg, opts->gen.scratch1, SZ_W, SZ_D);
194 ea->base = opts->gen.scratch1; 195 ea->base = opts->gen.scratch1;
195 } else { 196 } else {
196 ea->base = reg; 197 ea->base = reg;
197 } 198 }
198 return; 199 return;
199 } 200 }
200 switch (inst->src.addr_mode) 201 switch (op->addr_mode)
201 { 202 {
202 case MODE_REG: 203 case MODE_REG:
203 case MODE_AREG: 204 case MODE_AREG:
204 //We only get one memory parameter, so if the dst operand is a register in memory, 205 //We only get one memory parameter, so if the dst operand is a register in memory,
205 //we need to copy this to a temp register first 206 //we need to copy this to a temp register first if we're translating the src operand
206 reg = native_reg(&(inst->dst), opts); 207 if (dst || native_reg(&(inst->dst), opts) >= 0 || inst->dst.addr_mode == MODE_UNUSED || !(inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG)
207 if (reg >= 0 || inst->dst.addr_mode == MODE_UNUSED || !(inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG)
208 || inst->op == M68K_EXG) { 208 || inst->op == M68K_EXG) {
209 209
210 ea->mode = MODE_REG_DISPLACE8; 210 ea->mode = MODE_REG_DISPLACE8;
211 ea->base = opts->gen.context_reg; 211 ea->base = opts->gen.context_reg;
212 ea->disp = reg_offset(&(inst->src)); 212 ea->disp = reg_offset(op);
213 } else { 213 } else {
214 if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) { 214 if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) {
215 movsx_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_W, SZ_D); 215 movsx_rdispr(code, opts->gen.context_reg, reg_offset(op), opts->gen.scratch1, SZ_W, SZ_D);
216 } else { 216 } else {
217 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, inst->extra.size); 217 mov_rdispr(code, opts->gen.context_reg, reg_offset(op), opts->gen.scratch1, inst->extra.size);
218 } 218 }
219 ea->mode = MODE_REG_DIRECT; 219 ea->mode = MODE_REG_DIRECT;
220 ea->base = opts->gen.scratch1; 220 ea->base = opts->gen.scratch1;
221 //we're explicitly handling the areg dest here, so we exit immediately 221 //we're explicitly handling the areg dest here, so we exit immediately
222 return; 222 return;
223 } 223 }
224 break; 224 break;
225 case MODE_AREG_PREDEC: 225 case MODE_AREG_PREDEC:
226 dec_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->src.params.regs.pri == 7 ? 2 :1)); 226 if (dst && inst->src.addr_mode == MODE_AREG_PREDEC) {
227 cycles(&opts->gen, PREDEC_PENALTY); 227 push_r(code, opts->gen.scratch1);
228 if (opts->aregs[inst->src.params.regs.pri] >= 0) { 228 }
229 sub_ir(code, dec_amount, opts->aregs[inst->src.params.regs.pri], SZ_D); 229 dec_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (op->params.regs.pri == 7 ? 2 :1));
230 } else { 230 if (!dst) {
231 sub_irdisp(code, dec_amount, opts->gen.context_reg, reg_offset(&(inst->src)), SZ_D); 231 cycles(&opts->gen, PREDEC_PENALTY);
232 }
233 if (opts->aregs[op->params.regs.pri] >= 0) {
234 sub_ir(code, dec_amount, opts->aregs[op->params.regs.pri], SZ_D);
235 } else {
236 sub_irdisp(code, dec_amount, opts->gen.context_reg, reg_offset(op), SZ_D);
232 } 237 }
233 case MODE_AREG_INDIRECT: 238 case MODE_AREG_INDIRECT:
234 case MODE_AREG_POSTINC: 239 case MODE_AREG_POSTINC:
235 if (opts->aregs[inst->src.params.regs.pri] >= 0) { 240 if (opts->aregs[op->params.regs.pri] >= 0) {
236 mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); 241 mov_rr(code, opts->aregs[op->params.regs.pri], opts->gen.scratch1, SZ_D);
237 } else { 242 } else {
238 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_D); 243 mov_rdispr(code, opts->gen.context_reg, reg_offset(op), opts->gen.scratch1, SZ_D);
239 } 244 }
240 m68k_read_size(opts, inst->extra.size); 245 m68k_read_size(opts, inst->extra.size);
241 246
242 if (inst->src.addr_mode == MODE_AREG_POSTINC) { 247 if (dst) {
243 inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->src.params.regs.pri == 7 ? 2 : 1)); 248 if (inst->src.addr_mode == MODE_AREG_PREDEC) {
244 if (opts->aregs[inst->src.params.regs.pri] >= 0) { 249 //restore src operand to opts->gen.scratch2
245 add_ir(code, inc_amount, opts->aregs[inst->src.params.regs.pri], SZ_D); 250 pop_r(code, opts->gen.scratch2);
246 } else { 251 } else {
247 add_irdisp(code, inc_amount, opts->gen.context_reg, reg_offset(&(inst->src)), SZ_D); 252 //save reg value in opts->gen.scratch2 so we can use it to save the result in memory later
253 if (opts->aregs[op->params.regs.pri] >= 0) {
254 mov_rr(code, opts->aregs[op->params.regs.pri], opts->gen.scratch2, SZ_D);
255 } else {
256 mov_rdispr(code, opts->gen.context_reg, reg_offset(op), opts->gen.scratch2, SZ_D);
257 }
258 }
259 }
260
261 if (op->addr_mode == MODE_AREG_POSTINC) {
262 inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (op->params.regs.pri == 7 ? 2 : 1));
263 if (opts->aregs[op->params.regs.pri] >= 0) {
264 add_ir(code, inc_amount, opts->aregs[op->params.regs.pri], SZ_D);
265 } else {
266 add_irdisp(code, inc_amount, opts->gen.context_reg, reg_offset(op), SZ_D);
248 } 267 }
249 } 268 }
250 ea->mode = MODE_REG_DIRECT; 269 ea->mode = MODE_REG_DIRECT;
251 ea->base = (inst->dst.addr_mode == MODE_AREG_PREDEC && inst->op != M68K_MOVE) ? opts->gen.scratch2 : opts->gen.scratch1; 270 ea->base = (!dst && inst->dst.addr_mode == MODE_AREG_PREDEC && inst->op != M68K_MOVE) ? opts->gen.scratch2 : opts->gen.scratch1;
252 break; 271 break;
253 case MODE_AREG_DISPLACE: 272 case MODE_AREG_DISPLACE:
254 cycles(&opts->gen, BUS); 273 cycles(&opts->gen, BUS);
255 if (opts->aregs[inst->src.params.regs.pri] >= 0) { 274 if (opts->aregs[op->params.regs.pri] >= 0) {
256 mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); 275 mov_rr(code, opts->aregs[op->params.regs.pri], opts->gen.scratch1, SZ_D);
257 } else { 276 } else {
258 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_D); 277 mov_rdispr(code, opts->gen.context_reg, reg_offset(op), opts->gen.scratch1, SZ_D);
259 } 278 }
260 add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); 279 add_ir(code, op->params.regs.displacement, opts->gen.scratch1, SZ_D);
280 if (dst) {
281 push_r(code, opts->gen.scratch1);
282 }
261 m68k_read_size(opts, inst->extra.size); 283 m68k_read_size(opts, inst->extra.size);
284 if (dst) {
285 pop_r(code, opts->gen.scratch2);
286 }
262 287
263 ea->mode = MODE_REG_DIRECT; 288 ea->mode = MODE_REG_DIRECT;
264 ea->base = opts->gen.scratch1; 289 ea->base = opts->gen.scratch1;
265 break; 290 break;
266 case MODE_AREG_INDEX_DISP8: 291 case MODE_AREG_INDEX_DISP8:
267 cycles(&opts->gen, 6); 292 cycles(&opts->gen, 6);
268 if (opts->aregs[inst->src.params.regs.pri] >= 0) { 293 if (opts->aregs[op->params.regs.pri] >= 0) {
269 mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); 294 mov_rr(code, opts->aregs[op->params.regs.pri], opts->gen.scratch1, SZ_D);
270 } else { 295 } else {
271 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_D); 296 mov_rdispr(code, opts->gen.context_reg, reg_offset(op), opts->gen.scratch1, SZ_D);
272 } 297 }
273 sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; 298 sec_reg = (op->params.regs.sec >> 1) & 0x7;
274 if (inst->src.params.regs.sec & 1) { 299 if (op->params.regs.sec & 1) {
275 if (inst->src.params.regs.sec & 0x10) { 300 if (op->params.regs.sec & 0x10) {
276 if (opts->aregs[sec_reg] >= 0) { 301 if (opts->aregs[sec_reg] >= 0) {
277 add_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_D); 302 add_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_D);
278 } else { 303 } else {
279 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); 304 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D);
280 } 305 }
284 } else { 309 } else {
285 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); 310 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D);
286 } 311 }
287 } 312 }
288 } else { 313 } else {
289 if (inst->src.params.regs.sec & 0x10) { 314 if (op->params.regs.sec & 0x10) {
290 if (opts->aregs[sec_reg] >= 0) { 315 if (opts->aregs[sec_reg] >= 0) {
291 movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); 316 movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D);
292 } else { 317 } else {
293 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); 318 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D);
294 } 319 }
299 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); 324 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D);
300 } 325 }
301 } 326 }
302 add_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D); 327 add_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D);
303 } 328 }
304 if (inst->src.params.regs.displacement) { 329 if (op->params.regs.displacement) {
305 add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); 330 add_ir(code, op->params.regs.displacement, opts->gen.scratch1, SZ_D);
331 }
332 if (dst) {
333 push_r(code, opts->gen.scratch1);
306 } 334 }
307 m68k_read_size(opts, inst->extra.size); 335 m68k_read_size(opts, inst->extra.size);
336 if (dst) {
337 pop_r(code, opts->gen.scratch2);
338 }
308 339
309 ea->mode = MODE_REG_DIRECT; 340 ea->mode = MODE_REG_DIRECT;
310 ea->base = opts->gen.scratch1; 341 ea->base = opts->gen.scratch1;
311 break; 342 break;
312 case MODE_PC_DISPLACE: 343 case MODE_PC_DISPLACE:
313 cycles(&opts->gen, BUS); 344 cycles(&opts->gen, BUS);
314 mov_ir(code, inst->src.params.regs.displacement + inst->address+2, opts->gen.scratch1, SZ_D); 345 mov_ir(code, op->params.regs.displacement + inst->address+2, opts->gen.scratch1, SZ_D);
346 if (dst) {
347 push_r(code, opts->gen.scratch1);
348 }
315 m68k_read_size(opts, inst->extra.size); 349 m68k_read_size(opts, inst->extra.size);
350 if (dst) {
351 pop_r(code, opts->gen.scratch2);
352 }
316 353
317 ea->mode = MODE_REG_DIRECT; 354 ea->mode = MODE_REG_DIRECT;
318 ea->base = opts->gen.scratch1; 355 ea->base = opts->gen.scratch1;
319 break; 356 break;
320 case MODE_PC_INDEX_DISP8: 357 case MODE_PC_INDEX_DISP8:
321 cycles(&opts->gen, 6); 358 cycles(&opts->gen, 6);
322 mov_ir(code, inst->address+2, opts->gen.scratch1, SZ_D); 359 mov_ir(code, inst->address+2, opts->gen.scratch1, SZ_D);
323 sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; 360 sec_reg = (op->params.regs.sec >> 1) & 0x7;
324 if (inst->src.params.regs.sec & 1) { 361 if (op->params.regs.sec & 1) {
325 if (inst->src.params.regs.sec & 0x10) { 362 if (op->params.regs.sec & 0x10) {
326 if (opts->aregs[sec_reg] >= 0) { 363 if (opts->aregs[sec_reg] >= 0) {
327 add_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_D); 364 add_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_D);
328 } else { 365 } else {
329 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); 366 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D);
330 } 367 }
334 } else { 371 } else {
335 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); 372 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D);
336 } 373 }
337 } 374 }
338 } else { 375 } else {
339 if (inst->src.params.regs.sec & 0x10) { 376 if (op->params.regs.sec & 0x10) {
340 if (opts->aregs[sec_reg] >= 0) { 377 if (opts->aregs[sec_reg] >= 0) {
341 movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); 378 movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D);
342 } else { 379 } else {
343 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); 380 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D);
344 } 381 }
349 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); 386 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D);
350 } 387 }
351 } 388 }
352 add_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D); 389 add_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D);
353 } 390 }
354 if (inst->src.params.regs.displacement) { 391 if (op->params.regs.displacement) {
355 add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); 392 add_ir(code, op->params.regs.displacement, opts->gen.scratch1, SZ_D);
393 }
394 if (dst) {
395 push_r(code, opts->gen.scratch1);
356 } 396 }
357 m68k_read_size(opts, inst->extra.size); 397 m68k_read_size(opts, inst->extra.size);
398 if (dst) {
399 pop_r(code, opts->gen.scratch2);
400 }
358 401
359 ea->mode = MODE_REG_DIRECT; 402 ea->mode = MODE_REG_DIRECT;
360 ea->base = opts->gen.scratch1; 403 ea->base = opts->gen.scratch1;
361 break; 404 break;
362 case MODE_ABSOLUTE: 405 case MODE_ABSOLUTE:
363 case MODE_ABSOLUTE_SHORT: 406 case MODE_ABSOLUTE_SHORT:
364 cycles(&opts->gen, inst->src.addr_mode == MODE_ABSOLUTE ? BUS*2 : BUS); 407 cycles(&opts->gen, op->addr_mode == MODE_ABSOLUTE ? BUS*2 : BUS);
365 mov_ir(code, inst->src.params.immed, opts->gen.scratch1, SZ_D); 408 mov_ir(code, op->params.immed, opts->gen.scratch1, SZ_D);
409 if (dst) {
410 push_r(code, opts->gen.scratch1);
411 }
366 m68k_read_size(opts, inst->extra.size); 412 m68k_read_size(opts, inst->extra.size);
413 if (dst) {
414 pop_r(code, opts->gen.scratch2);
415 }
367 416
368 ea->mode = MODE_REG_DIRECT; 417 ea->mode = MODE_REG_DIRECT;
369 ea->base = opts->gen.scratch1; 418 ea->base = opts->gen.scratch1;
370 break; 419 break;
371 case MODE_IMMEDIATE: 420 case MODE_IMMEDIATE:
372 case MODE_IMMEDIATE_WORD: 421 case MODE_IMMEDIATE_WORD:
373 if (inst->variant != VAR_QUICK) { 422 if (inst->variant != VAR_QUICK) {
374 cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG && inst->src.addr_mode == MODE_IMMEDIATE) ? BUS*2 : BUS); 423 cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG && op->addr_mode == MODE_IMMEDIATE) ? BUS*2 : BUS);
375 } 424 }
376 ea->mode = MODE_IMMED; 425 ea->mode = MODE_IMMED;
377 ea->disp = inst->src.params.immed; 426 ea->disp = op->params.immed;
427 //sign extend value when the destination is an address register
378 if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD && ea->disp & 0x8000) { 428 if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD && ea->disp & 0x8000) {
379 ea->disp |= 0xFFFF0000; 429 ea->disp |= 0xFFFF0000;
380 } 430 }
381 return; 431 return;
382 default: 432 default:
383 m68k_disasm(inst, disasm_buf); 433 m68k_disasm(inst, disasm_buf);
384 printf("%X: %s\naddress mode %d not implemented (src)\n", inst->address, disasm_buf, inst->src.addr_mode); 434 printf("%X: %s\naddress mode %d not implemented (%s)\n", inst->address, disasm_buf, op->addr_mode, dst ? "dst" : "src");
385 exit(1); 435 exit(1);
386 } 436 }
387 if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) { 437 if (!dst && inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) {
388 if (ea->mode == MODE_REG_DIRECT) { 438 if (ea->mode == MODE_REG_DIRECT) {
389 movsx_rr(code, ea->base, opts->gen.scratch1, SZ_W, SZ_D); 439 movsx_rr(code, ea->base, opts->gen.scratch1, SZ_W, SZ_D);
390 } else { 440 } else {
391 movsx_rdispr(code, ea->base, ea->disp, opts->gen.scratch1, SZ_W, SZ_D); 441 movsx_rdispr(code, ea->base, ea->disp, opts->gen.scratch1, SZ_W, SZ_D);
392 ea->mode = MODE_REG_DIRECT; 442 ea->mode = MODE_REG_DIRECT;
393 } 443 }
394 ea->base = opts->gen.scratch1; 444 ea->base = opts->gen.scratch1;
395 }
396 }
397
398 void translate_m68k_dst(m68kinst * inst, x86_ea * ea, m68k_options * opts, uint8_t fake_read)
399 {
400 code_info *code = &opts->gen.code;
401 int8_t reg = native_reg(&(inst->dst), opts), sec_reg;
402 int32_t dec_amount, inc_amount;
403 if (reg >= 0) {
404 ea->mode = MODE_REG_DIRECT;
405 ea->base = reg;
406 return;
407 }
408 switch (inst->dst.addr_mode)
409 {
410 case MODE_REG:
411 case MODE_AREG:
412 ea->mode = MODE_REG_DISPLACE8;
413 ea->base = opts->gen.context_reg;
414 ea->disp = reg_offset(&(inst->dst));
415 break;
416 case MODE_AREG_PREDEC:
417 if (inst->src.addr_mode == MODE_AREG_PREDEC) {
418 push_r(code, opts->gen.scratch1);
419 }
420 dec_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1));
421 if (opts->aregs[inst->dst.params.regs.pri] >= 0) {
422 sub_ir(code, dec_amount, opts->aregs[inst->dst.params.regs.pri], SZ_D);
423 } else {
424 sub_irdisp(code, dec_amount, opts->gen.context_reg, reg_offset(&(inst->dst)), SZ_D);
425 }
426 case MODE_AREG_INDIRECT:
427 case MODE_AREG_POSTINC:
428 if (fake_read) {
429 cycles(&opts->gen, inst->extra.size == OPSIZE_LONG ? 8 : 4);
430 } else {
431 if (opts->aregs[inst->dst.params.regs.pri] >= 0) {
432 mov_rr(code, opts->aregs[inst->dst.params.regs.pri], opts->gen.scratch1, SZ_D);
433 } else {
434 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->dst)), opts->gen.scratch1, SZ_D);
435 }
436 m68k_read_size(opts, inst->extra.size);
437 }
438 if (inst->src.addr_mode == MODE_AREG_PREDEC) {
439 //restore src operand to opts->gen.scratch2
440 pop_r(code, opts->gen.scratch2);
441 } else {
442 //save reg value in opts->gen.scratch2 so we can use it to save the result in memory later
443 if (opts->aregs[inst->dst.params.regs.pri] >= 0) {
444 mov_rr(code, opts->aregs[inst->dst.params.regs.pri], opts->gen.scratch2, SZ_D);
445 } else {
446 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->dst)), opts->gen.scratch2, SZ_D);
447 }
448 }
449
450 if (inst->dst.addr_mode == MODE_AREG_POSTINC) {
451 inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1));
452 if (opts->aregs[inst->dst.params.regs.pri] >= 0) {
453 add_ir(code, inc_amount, opts->aregs[inst->dst.params.regs.pri], SZ_D);
454 } else {
455 add_irdisp(code, inc_amount, opts->gen.context_reg, reg_offset(&(inst->dst)), SZ_D);
456 }
457 }
458 ea->mode = MODE_REG_DIRECT;
459 ea->base = opts->gen.scratch1;
460 break;
461 case MODE_AREG_DISPLACE:
462 cycles(&opts->gen, fake_read ? BUS+(inst->extra.size == OPSIZE_LONG ? BUS*2 : BUS) : BUS);
463 reg = fake_read ? opts->gen.scratch2 : opts->gen.scratch1;
464 if (opts->aregs[inst->dst.params.regs.pri] >= 0) {
465 mov_rr(code, opts->aregs[inst->dst.params.regs.pri], reg, SZ_D);
466 } else {
467 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->dst)), reg, SZ_D);
468 }
469 add_ir(code, inst->dst.params.regs.displacement, reg, SZ_D);
470 if (!fake_read) {
471 push_r(code, opts->gen.scratch1);
472 m68k_read_size(opts, inst->extra.size);
473 pop_r(code, opts->gen.scratch2);
474 }
475 ea->mode = MODE_REG_DIRECT;
476 ea->base = opts->gen.scratch1;
477 break;
478 case MODE_AREG_INDEX_DISP8:
479 cycles(&opts->gen, fake_read ? (6 + inst->extra.size == OPSIZE_LONG ? 8 : 4) : 6);
480 if (opts->aregs[inst->dst.params.regs.pri] >= 0) {
481 mov_rr(code, opts->aregs[inst->dst.params.regs.pri], opts->gen.scratch1, SZ_D);
482 } else {
483 mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->dst)), opts->gen.scratch1, SZ_D);
484 }
485 sec_reg = (inst->dst.params.regs.sec >> 1) & 0x7;
486 if (inst->dst.params.regs.sec & 1) {
487 if (inst->dst.params.regs.sec & 0x10) {
488 if (opts->aregs[sec_reg] >= 0) {
489 add_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_D);
490 } else {
491 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D);
492 }
493 } else {
494 if (opts->dregs[sec_reg] >= 0) {
495 add_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_D);
496 } else {
497 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D);
498 }
499 }
500 } else {
501 if (inst->dst.params.regs.sec & 0x10) {
502 if (opts->aregs[sec_reg] >= 0) {
503 movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D);
504 } else {
505 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D);
506 }
507 } else {
508 if (opts->dregs[sec_reg] >= 0) {
509 movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D);
510 } else {
511 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D);
512 }
513 }
514 add_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D);
515 }
516 if (inst->dst.params.regs.displacement) {
517 add_ir(code, inst->dst.params.regs.displacement, opts->gen.scratch1, SZ_D);
518 }
519 if (fake_read) {
520 mov_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_D);
521 } else {
522 push_r(code, opts->gen.scratch1);
523 m68k_read_size(opts, inst->extra.size);
524 pop_r(code, opts->gen.scratch2);
525 }
526 ea->mode = MODE_REG_DIRECT;
527 ea->base = opts->gen.scratch1;
528 break;
529 case MODE_PC_DISPLACE:
530 cycles(&opts->gen, fake_read ? BUS+(inst->extra.size == OPSIZE_LONG ? BUS*2 : BUS) : BUS);
531 mov_ir(code, inst->dst.params.regs.displacement + inst->address+2, fake_read ? opts->gen.scratch2 : opts->gen.scratch1, SZ_D);
532 if (!fake_read) {
533 push_r(code, opts->gen.scratch1);
534 m68k_read_size(opts, inst->extra.size);
535 pop_r(code, opts->gen.scratch2);
536 }
537 ea->mode = MODE_REG_DIRECT;
538 ea->base = opts->gen.scratch1;
539 break;
540 case MODE_PC_INDEX_DISP8:
541 cycles(&opts->gen, fake_read ? (6 + inst->extra.size == OPSIZE_LONG ? 8 : 4) : 6);
542 mov_ir(code, inst->address+2, opts->gen.scratch1, SZ_D);
543 sec_reg = (inst->dst.params.regs.sec >> 1) & 0x7;
544 if (inst->dst.params.regs.sec & 1) {
545 if (inst->dst.params.regs.sec & 0x10) {
546 if (opts->aregs[sec_reg] >= 0) {
547 add_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_D);
548 } else {
549 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D);
550 }
551 } else {
552 if (opts->dregs[sec_reg] >= 0) {
553 add_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_D);
554 } else {
555 add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D);
556 }
557 }
558 } else {
559 if (inst->dst.params.regs.sec & 0x10) {
560 if (opts->aregs[sec_reg] >= 0) {
561 movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D);
562 } else {
563 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D);
564 }
565 } else {
566 if (opts->dregs[sec_reg] >= 0) {
567 movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D);
568 } else {
569 movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D);
570 }
571 }
572 add_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D);
573 }
574 if (inst->dst.params.regs.displacement) {
575 add_ir(code, inst->dst.params.regs.displacement, opts->gen.scratch1, SZ_D);
576 }
577 if (fake_read) {
578 mov_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_D);
579 } else {
580 push_r(code, opts->gen.scratch1);
581 m68k_read_size(opts, inst->extra.size);
582 pop_r(code, opts->gen.scratch2);
583 }
584 ea->mode = MODE_REG_DIRECT;
585 ea->base = opts->gen.scratch1;
586 break;
587 case MODE_ABSOLUTE:
588 case MODE_ABSOLUTE_SHORT:
589 //Add cycles for reading address from instruction stream
590 cycles(&opts->gen, (inst->dst.addr_mode == MODE_ABSOLUTE ? BUS*2 : BUS) + (fake_read ? (inst->extra.size == OPSIZE_LONG ? BUS*2 : BUS) : 0));
591 mov_ir(code, inst->dst.params.immed, fake_read ? opts->gen.scratch2 : opts->gen.scratch1, SZ_D);
592 if (!fake_read) {
593 push_r(code, opts->gen.scratch1);
594 m68k_read_size(opts, inst->extra.size);
595 pop_r(code, opts->gen.scratch2);
596 }
597 ea->mode = MODE_REG_DIRECT;
598 ea->base = opts->gen.scratch1;
599 break;
600 default:
601 m68k_disasm(inst, disasm_buf);
602 printf("%X: %s\naddress mode %d not implemented (dst)\n", inst->address, disasm_buf, inst->dst.addr_mode);
603 exit(1);
604 } 445 }
605 } 446 }
606 447
607 void m68k_save_result(m68kinst * inst, m68k_options * opts) 448 void m68k_save_result(m68kinst * inst, m68k_options * opts)
608 { 449 {
636 int8_t reg, flags_reg, sec_reg; 477 int8_t reg, flags_reg, sec_reg;
637 uint8_t dir = 0; 478 uint8_t dir = 0;
638 int32_t offset; 479 int32_t offset;
639 int32_t inc_amount, dec_amount; 480 int32_t inc_amount, dec_amount;
640 x86_ea src; 481 x86_ea src;
641 translate_m68k_src(inst, &src, opts); 482 translate_m68k_op(inst, &src, opts, 0);
642 reg = native_reg(&(inst->dst), opts); 483 reg = native_reg(&(inst->dst), opts);
643 if (inst->dst.addr_mode != MODE_AREG) { 484 if (inst->dst.addr_mode != MODE_AREG) {
644 //update statically set flags 485 //update statically set flags
645 set_flag(opts, 0, FLAG_V); 486 set_flag(opts, 0, FLAG_V);
646 set_flag(opts, 0, FLAG_C); 487 set_flag(opts, 0, FLAG_C);
1266 cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG ? 6 : 4)); 1107 cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG ? 6 : 4));
1267 xor_rr(code, reg, reg, inst->extra.size); 1108 xor_rr(code, reg, reg, inst->extra.size);
1268 return; 1109 return;
1269 } 1110 }
1270 x86_ea dst_op; 1111 x86_ea dst_op;
1271 translate_m68k_dst(inst, &dst_op, opts, 1); 1112 translate_m68k_op(inst, &dst_op, opts, 1);
1272 if (dst_op.mode == MODE_REG_DIRECT) { 1113 if (dst_op.mode == MODE_REG_DIRECT) {
1273 xor_rr(code, dst_op.base, dst_op.base, inst->extra.size); 1114 xor_rr(code, dst_op.base, dst_op.base, inst->extra.size);
1274 } else { 1115 } else {
1275 mov_irdisp(code, 0, dst_op.base, dst_op.disp, inst->extra.size); 1116 mov_irdisp(code, 0, dst_op.base, dst_op.disp, inst->extra.size);
1276 } 1117 }
1281 { 1122 {
1282 code_info *code = &opts->gen.code; 1123 code_info *code = &opts->gen.code;
1283 x86_ea dst_op; 1124 x86_ea dst_op;
1284 uint8_t dst_size = inst->extra.size; 1125 uint8_t dst_size = inst->extra.size;
1285 inst->extra.size--; 1126 inst->extra.size--;
1286 translate_m68k_dst(inst, &dst_op, opts, 0); 1127 translate_m68k_op(inst, &dst_op, opts, 1);
1287 if (dst_op.mode == MODE_REG_DIRECT) { 1128 if (dst_op.mode == MODE_REG_DIRECT) {
1288 movsx_rr(code, dst_op.base, dst_op.base, inst->extra.size, dst_size); 1129 movsx_rr(code, dst_op.base, dst_op.base, inst->extra.size, dst_size);
1289 cmp_ir(code, 0, dst_op.base, dst_size); 1130 cmp_ir(code, 0, dst_op.base, dst_size);
1290 } else { 1131 } else {
1291 movsx_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, inst->extra.size, dst_size); 1132 movsx_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, inst->extra.size, dst_size);
1640 { 1481 {
1641 code_info *code = &opts->gen.code; 1482 code_info *code = &opts->gen.code;
1642 uint8_t cond = inst->extra.cond; 1483 uint8_t cond = inst->extra.cond;
1643 x86_ea dst_op; 1484 x86_ea dst_op;
1644 inst->extra.size = OPSIZE_BYTE; 1485 inst->extra.size = OPSIZE_BYTE;
1645 translate_m68k_dst(inst, &dst_op, opts, 1); 1486 translate_m68k_op(inst, &dst_op, opts, 1);
1646 if (cond == COND_TRUE || cond == COND_FALSE) { 1487 if (cond == COND_TRUE || cond == COND_FALSE) {
1647 if ((inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG) && inst->extra.cond == COND_TRUE) { 1488 if ((inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG) && inst->extra.cond == COND_TRUE) {
1648 cycles(&opts->gen, 6); 1489 cycles(&opts->gen, 6);
1649 } else { 1490 } else {
1650 cycles(&opts->gen, BUS); 1491 cycles(&opts->gen, BUS);
2064 void translate_m68k_cmp(m68k_options * opts, m68kinst * inst) 1905 void translate_m68k_cmp(m68k_options * opts, m68kinst * inst)
2065 { 1906 {
2066 code_info *code = &opts->gen.code; 1907 code_info *code = &opts->gen.code;
2067 uint8_t size = inst->extra.size; 1908 uint8_t size = inst->extra.size;
2068 x86_ea src_op, dst_op; 1909 x86_ea src_op, dst_op;
2069 translate_m68k_src(inst, &src_op, opts); 1910 translate_m68k_op(inst, &src_op, opts, 0);
2070 if (inst->dst.addr_mode == MODE_AREG_POSTINC) { 1911 if (inst->dst.addr_mode == MODE_AREG_POSTINC) {
2071 push_r(code, opts->gen.scratch1); 1912 push_r(code, opts->gen.scratch1);
2072 translate_m68k_dst(inst, &dst_op, opts, 0); 1913 translate_m68k_op(inst, &dst_op, opts, 1);
2073 pop_r(code, opts->gen.scratch2); 1914 pop_r(code, opts->gen.scratch2);
2074 src_op.base = opts->gen.scratch2; 1915 src_op.base = opts->gen.scratch2;
2075 } else { 1916 } else {
2076 translate_m68k_dst(inst, &dst_op, opts, 0); 1917 translate_m68k_op(inst, &dst_op, opts, 1);
2077 if (inst->dst.addr_mode == MODE_AREG && size == OPSIZE_WORD) { 1918 if (inst->dst.addr_mode == MODE_AREG && size == OPSIZE_WORD) {
2078 size = OPSIZE_LONG; 1919 size = OPSIZE_LONG;
2079 } 1920 }
2080 } 1921 }
2081 cycles(&opts->gen, BUS); 1922 cycles(&opts->gen, BUS);
2318 } else if(inst->op == M68K_CMP) { 2159 } else if(inst->op == M68K_CMP) {
2319 return translate_m68k_cmp(opts, inst); 2160 return translate_m68k_cmp(opts, inst);
2320 } 2161 }
2321 x86_ea src_op, dst_op; 2162 x86_ea src_op, dst_op;
2322 if (inst->src.addr_mode != MODE_UNUSED) { 2163 if (inst->src.addr_mode != MODE_UNUSED) {
2323 translate_m68k_src(inst, &src_op, opts); 2164 translate_m68k_op(inst, &src_op, opts, 0);
2324 } 2165 }
2325 if (inst->dst.addr_mode != MODE_UNUSED) { 2166 if (inst->dst.addr_mode != MODE_UNUSED) {
2326 translate_m68k_dst(inst, &dst_op, opts, 0); 2167 translate_m68k_op(inst, &dst_op, opts, 1);
2327 } 2168 }
2328 uint8_t size; 2169 uint8_t size;
2329 switch(inst->op) 2170 switch(inst->op)
2330 { 2171 {
2331 case M68K_ABCD: 2172 case M68K_ABCD: