comparison m68k_to_x86.c @ 92:c3d034e076ee

Fix some bugs in emulation of CLR
author Mike Pavone <pavone@retrodev.com>
date Thu, 27 Dec 2012 10:40:03 -0800
parents 60b5c9e2f4e0
children f63b0e58e2d5
comparison
equal deleted inserted replaced
91:8c446fc19cc0 92:c3d034e076ee
316 exit(1); 316 exit(1);
317 } 317 }
318 return out; 318 return out;
319 } 319 }
320 320
321 uint8_t * translate_m68k_dst(m68kinst * inst, x86_ea * ea, uint8_t * out, x86_68k_options * opts) 321 uint8_t * translate_m68k_dst(m68kinst * inst, x86_ea * ea, uint8_t * out, x86_68k_options * opts, uint8_t fake_read)
322 { 322 {
323 int8_t reg = native_reg(&(inst->dst), opts); 323 int8_t reg = native_reg(&(inst->dst), opts);
324 int32_t dec_amount, inc_amount; 324 int32_t dec_amount, inc_amount;
325 if (reg >= 0) { 325 if (reg >= 0) {
326 ea->mode = MODE_REG_DIRECT; 326 ea->mode = MODE_REG_DIRECT;
342 } else { 342 } else {
343 out = sub_irdisp8(out, dec_amount, CONTEXT, reg_offset(&(inst->dst)), SZ_D); 343 out = sub_irdisp8(out, dec_amount, CONTEXT, reg_offset(&(inst->dst)), SZ_D);
344 } 344 }
345 case MODE_AREG_INDIRECT: 345 case MODE_AREG_INDIRECT:
346 case MODE_AREG_POSTINC: 346 case MODE_AREG_POSTINC:
347 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { 347 if (fake_read) {
348 out = mov_rr(out, opts->aregs[inst->dst.params.regs.pri], SCRATCH1, SZ_D); 348 out = cycles(out, inst->extra.size == OPSIZE_LONG ? 8 : 4);
349 } else { 349 } else {
350 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->dst)), SCRATCH1, SZ_D); 350 if (opts->aregs[inst->dst.params.regs.pri] >= 0) {
351 } 351 out = mov_rr(out, opts->aregs[inst->dst.params.regs.pri], SCRATCH1, SZ_D);
352 switch (inst->extra.size) 352 } else {
353 { 353 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->dst)), SCRATCH1, SZ_D);
354 case OPSIZE_BYTE: 354 }
355 out = call(out, (char *)m68k_read_byte_scratch1); 355 switch (inst->extra.size)
356 break; 356 {
357 case OPSIZE_WORD: 357 case OPSIZE_BYTE:
358 out = call(out, (char *)m68k_read_word_scratch1); 358 out = call(out, (char *)m68k_read_byte_scratch1);
359 break; 359 break;
360 case OPSIZE_LONG: 360 case OPSIZE_WORD:
361 out = call(out, (char *)m68k_read_long_scratch1); 361 out = call(out, (char *)m68k_read_word_scratch1);
362 break; 362 break;
363 case OPSIZE_LONG:
364 out = call(out, (char *)m68k_read_long_scratch1);
365 break;
366 }
363 } 367 }
364 //save reg value in SCRATCH2 so we can use it to save the result in memory later 368 //save reg value in SCRATCH2 so we can use it to save the result in memory later
365 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { 369 if (opts->aregs[inst->dst.params.regs.pri] >= 0) {
366 out = mov_rr(out, opts->aregs[inst->dst.params.regs.pri], SCRATCH2, SZ_D); 370 out = mov_rr(out, opts->aregs[inst->dst.params.regs.pri], SCRATCH2, SZ_D);
367 } else { 371 } else {
378 } 382 }
379 ea->mode = MODE_REG_DIRECT; 383 ea->mode = MODE_REG_DIRECT;
380 ea->base = SCRATCH1; 384 ea->base = SCRATCH1;
381 break; 385 break;
382 case MODE_AREG_DISPLACE: 386 case MODE_AREG_DISPLACE:
383 out = cycles(out, BUS); 387 out = cycles(out, fake_read ? BUS+(inst->extra.size == OPSIZE_LONG ? BUS*2 : BUS) : BUS);
388 reg = fake_read ? SCRATCH2 : SCRATCH1;
384 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { 389 if (opts->aregs[inst->dst.params.regs.pri] >= 0) {
385 out = mov_rr(out, opts->aregs[inst->dst.params.regs.pri], SCRATCH1, SZ_D); 390 out = mov_rr(out, opts->aregs[inst->dst.params.regs.pri], reg, SZ_D);
386 } else { 391 } else {
387 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->dst)), SCRATCH1, SZ_D); 392 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->dst)), reg, SZ_D);
388 } 393 }
389 out = add_ir(out, inst->dst.params.regs.displacement, SCRATCH1, SZ_D); 394 out = add_ir(out, inst->dst.params.regs.displacement, reg, SZ_D);
390 out = push_r(out, SCRATCH1); 395 if (!fake_read) {
391 switch (inst->extra.size) 396 out = push_r(out, SCRATCH1);
392 { 397 switch (inst->extra.size)
393 case OPSIZE_BYTE: 398 {
394 out = call(out, (char *)m68k_read_byte_scratch1); 399 case OPSIZE_BYTE:
395 break; 400 out = call(out, (char *)m68k_read_byte_scratch1);
396 case OPSIZE_WORD: 401 break;
397 out = call(out, (char *)m68k_read_word_scratch1); 402 case OPSIZE_WORD:
398 break; 403 out = call(out, (char *)m68k_read_word_scratch1);
399 case OPSIZE_LONG: 404 break;
400 out = call(out, (char *)m68k_read_long_scratch1); 405 case OPSIZE_LONG:
401 break; 406 out = call(out, (char *)m68k_read_long_scratch1);
402 } 407 break;
403 out = pop_r(out, SCRATCH2); 408 }
409 out = pop_r(out, SCRATCH2);
410 }
404 ea->mode = MODE_REG_DIRECT; 411 ea->mode = MODE_REG_DIRECT;
405 ea->base = SCRATCH1; 412 ea->base = SCRATCH1;
406 break; 413 break;
407 case MODE_PC_DISPLACE: 414 case MODE_PC_DISPLACE:
408 out = cycles(out, BUS); 415 out = cycles(out, fake_read ? BUS+(inst->extra.size == OPSIZE_LONG ? BUS*2 : BUS) : BUS);
409 out = mov_ir(out, inst->dst.params.regs.displacement + inst->address+2, SCRATCH1, SZ_D); 416 out = mov_ir(out, inst->dst.params.regs.displacement + inst->address+2, fake_read ? SCRATCH2 : SCRATCH1, SZ_D);
410 out = push_r(out, SCRATCH1); 417 if (!fake_read) {
411 switch (inst->extra.size) 418 out = push_r(out, SCRATCH1);
412 { 419 switch (inst->extra.size)
413 case OPSIZE_BYTE: 420 {
414 out = call(out, (char *)m68k_read_byte_scratch1); 421 case OPSIZE_BYTE:
415 break; 422 out = call(out, (char *)m68k_read_byte_scratch1);
416 case OPSIZE_WORD: 423 break;
417 out = call(out, (char *)m68k_read_word_scratch1); 424 case OPSIZE_WORD:
418 break; 425 out = call(out, (char *)m68k_read_word_scratch1);
419 case OPSIZE_LONG: 426 break;
420 out = call(out, (char *)m68k_read_long_scratch1); 427 case OPSIZE_LONG:
421 break; 428 out = call(out, (char *)m68k_read_long_scratch1);
422 } 429 break;
423 out = pop_r(out, SCRATCH2); 430 }
431 out = pop_r(out, SCRATCH2);
432 }
424 ea->mode = MODE_REG_DIRECT; 433 ea->mode = MODE_REG_DIRECT;
425 ea->base = SCRATCH1; 434 ea->base = SCRATCH1;
426 break; 435 break;
427 case MODE_ABSOLUTE: 436 case MODE_ABSOLUTE:
428 case MODE_ABSOLUTE_SHORT: 437 case MODE_ABSOLUTE_SHORT:
429 //Add cycles for reading address from instruction stream 438 //Add cycles for reading address from instruction stream
430 if (inst->dst.addr_mode == MODE_ABSOLUTE) { 439 out = cycles(out, (inst->dst.addr_mode == MODE_ABSOLUTE ? BUS*2 : BUS) + (fake_read ? (inst->extra.size == OPSIZE_LONG ? BUS*2 : BUS) : 0));
431 out = cycles(out, BUS*2); 440 out = mov_ir(out, inst->dst.params.immed, fake_read ? SCRATCH2 : SCRATCH1, SZ_D);
432 } else { 441 if (!fake_read) {
433 out = cycles(out, BUS); 442 out = push_r(out, SCRATCH1);
434 } 443 switch (inst->extra.size)
435 out = mov_ir(out, inst->dst.params.immed, SCRATCH1, SZ_D); 444 {
436 out = push_r(out, SCRATCH1); 445 case OPSIZE_BYTE:
437 switch (inst->extra.size) 446 out = call(out, (char *)m68k_read_byte_scratch1);
438 { 447 break;
439 case OPSIZE_BYTE: 448 case OPSIZE_WORD:
440 out = call(out, (char *)m68k_read_byte_scratch1); 449 out = call(out, (char *)m68k_read_word_scratch1);
441 break; 450 break;
442 case OPSIZE_WORD: 451 case OPSIZE_LONG:
443 out = call(out, (char *)m68k_read_word_scratch1); 452 out = call(out, (char *)m68k_read_long_scratch1);
444 break; 453 break;
445 case OPSIZE_LONG: 454 }
446 out = call(out, (char *)m68k_read_long_scratch1); 455 out = pop_r(out, SCRATCH2);
447 break; 456 }
448 }
449 out = pop_r(out, SCRATCH2);
450 ea->mode = MODE_REG_DIRECT; 457 ea->mode = MODE_REG_DIRECT;
451 ea->base = SCRATCH1; 458 ea->base = SCRATCH1;
452 break; 459 break;
453 default: 460 default:
454 printf("address mode %d not implemented (dst)\n", inst->dst.addr_mode); 461 printf("address mode %d not implemented (dst)\n", inst->dst.addr_mode);
876 { 883 {
877 dst = mov_ir(dst, 0, FLAG_N, SZ_B); 884 dst = mov_ir(dst, 0, FLAG_N, SZ_B);
878 dst = mov_ir(dst, 0, FLAG_V, SZ_B); 885 dst = mov_ir(dst, 0, FLAG_V, SZ_B);
879 dst = mov_ir(dst, 0, FLAG_C, SZ_B); 886 dst = mov_ir(dst, 0, FLAG_C, SZ_B);
880 dst = mov_ir(dst, 1, FLAG_Z, SZ_B); 887 dst = mov_ir(dst, 1, FLAG_Z, SZ_B);
881 uint8_t reg = native_reg(&(inst->dst), opts); 888 int8_t reg = native_reg(&(inst->dst), opts);
882 if (reg >= 0) { 889 if (reg >= 0) {
883 dst = cycles(dst, (inst->extra.size == OPSIZE_LONG ? 6 : 4)); 890 dst = cycles(dst, (inst->extra.size == OPSIZE_LONG ? 6 : 4));
884 return xor_rr(dst, reg, reg, inst->extra.size); 891 return xor_rr(dst, reg, reg, inst->extra.size);
885 } 892 }
886 int32_t dec_amount,inc_amount; 893 x86_ea dst_op;
887 switch (inst->dst.addr_mode) 894 dst = translate_m68k_dst(inst, &dst_op, dst, opts, 1);
888 { 895 if (dst_op.mode == MODE_REG_DIRECT) {
889 case MODE_REG: 896 dst = xor_rr(dst, dst_op.base, dst_op.base, inst->extra.size);
890 case MODE_AREG: 897 } else {
891 dst = cycles(dst, (inst->extra.size == OPSIZE_LONG ? 6 : 4)); 898 dst = mov_irdisp8(dst, 0, dst_op.base, dst_op.disp, inst->extra.size);
892 dst = mov_irdisp8(dst, 0, CONTEXT, reg_offset(&(inst->dst)), inst->extra.size); 899 }
893 break; 900 dst = m68k_save_result(inst, dst, opts);
894 case MODE_AREG_PREDEC:
895 dst = cycles(dst, PREDEC_PENALTY);
896 dec_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : 1);
897 if (opts->aregs[inst->dst.params.regs.pri] >= 0) {
898 dst = sub_ir(dst, dec_amount, opts->aregs[inst->dst.params.regs.pri], SZ_D);
899 } else {
900 dst = sub_irdisp8(dst, dec_amount, CONTEXT, reg_offset(&(inst->dst)), SZ_D);
901 }
902 case MODE_AREG_INDIRECT:
903 case MODE_AREG_POSTINC:
904 //add cycles for prefetch and wasted read
905 dst = cycles(dst, (inst->extra.size == OPSIZE_LONG ? 12 : 8));
906 if (opts->aregs[inst->dst.params.regs.pri] >= 0) {
907 dst = mov_rr(dst, opts->aregs[inst->dst.params.regs.pri], SCRATCH2, SZ_D);
908 } else {
909 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->dst)), SCRATCH2, SZ_D);
910 }
911 dst = xor_rr(dst, SCRATCH1, SCRATCH1, SZ_D);
912 switch (inst->extra.size)
913 {
914 case OPSIZE_BYTE:
915 dst = call(dst, (char *)m68k_write_byte);
916 break;
917 case OPSIZE_WORD:
918 dst = call(dst, (char *)m68k_write_word);
919 break;
920 case OPSIZE_LONG:
921 dst = call(dst, (char *)m68k_write_long_highfirst);
922 break;
923 }
924 if (inst->dst.addr_mode == MODE_AREG_POSTINC) {
925 inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : 1);
926 if (opts->aregs[inst->dst.params.regs.pri] >= 0) {
927 dst = add_ir(dst, inc_amount, opts->aregs[inst->dst.params.regs.pri], SZ_D);
928 } else {
929 dst = add_irdisp8(dst, inc_amount, CONTEXT, reg_offset(&(inst->dst)), SZ_D);
930 }
931 }
932 break;
933 default:
934 printf("address mode %d not implemented (clr dst)\n", inst->dst.addr_mode);
935 exit(1);
936 }
937 return dst; 901 return dst;
938 } 902 }
939 903
940 uint8_t * translate_m68k_lea(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) 904 uint8_t * translate_m68k_lea(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
941 { 905 {
1450 x86_ea src_op, dst_op; 1414 x86_ea src_op, dst_op;
1451 if (inst->src.addr_mode != MODE_UNUSED) { 1415 if (inst->src.addr_mode != MODE_UNUSED) {
1452 dst = translate_m68k_src(inst, &src_op, dst, opts); 1416 dst = translate_m68k_src(inst, &src_op, dst, opts);
1453 } 1417 }
1454 if (inst->dst.addr_mode != MODE_UNUSED) { 1418 if (inst->dst.addr_mode != MODE_UNUSED) {
1455 dst = translate_m68k_dst(inst, &dst_op, dst, opts); 1419 dst = translate_m68k_dst(inst, &dst_op, dst, opts, 0);
1456 } 1420 }
1457 switch(inst->op) 1421 switch(inst->op)
1458 { 1422 {
1459 //case M68K_ABCD: 1423 //case M68K_ABCD:
1460 // break; 1424 // break;