comparison m68k_to_x86.c @ 151:6b593ea0ed90

Implement MULU/MULS and DIVU/DIVS
author Mike Pavone <pavone@retrodev.com>
date Thu, 03 Jan 2013 22:07:40 -0800
parents 3e68e517cc01
children 79958b95526f
comparison
equal deleted inserted replaced
150:3e68e517cc01 151:6b593ea0ed90
24 uint8_t mode; 24 uint8_t mode;
25 uint8_t base; 25 uint8_t base;
26 uint8_t index; 26 uint8_t index;
27 uint8_t cycles; 27 uint8_t cycles;
28 } x86_ea; 28 } x86_ea;
29
30 char disasm_buf[1024];
29 31
30 void handle_cycle_limit_int(); 32 void handle_cycle_limit_int();
31 void m68k_read_word_scratch1(); 33 void m68k_read_word_scratch1();
32 void m68k_read_long_scratch1(); 34 void m68k_read_long_scratch1();
33 void m68k_read_byte_scratch1(); 35 void m68k_read_byte_scratch1();
341 } 343 }
342 ea->mode = MODE_IMMED; 344 ea->mode = MODE_IMMED;
343 ea->disp = inst->src.params.immed; 345 ea->disp = inst->src.params.immed;
344 break; 346 break;
345 default: 347 default:
346 printf("address mode %d not implemented (src)\n", inst->src.addr_mode); 348 m68k_disasm(inst, disasm_buf);
349 printf("%s\naddress mode %d not implemented (src)\n", disasm_buf, inst->src.addr_mode);
347 exit(1); 350 exit(1);
348 } 351 }
349 return out; 352 return out;
350 } 353 }
351 354
606 } 609 }
607 ea->mode = MODE_REG_DIRECT; 610 ea->mode = MODE_REG_DIRECT;
608 ea->base = SCRATCH1; 611 ea->base = SCRATCH1;
609 break; 612 break;
610 default: 613 default:
611 printf("address mode %d not implemented (dst)\n", inst->dst.addr_mode); 614 m68k_disasm(inst, disasm_buf);
615 printf("%s\naddress mode %d not implemented (dst)\n", disasm_buf, inst->dst.addr_mode);
612 exit(1); 616 exit(1);
613 } 617 }
614 return out; 618 return out;
615 } 619 }
616 620
953 dst = call(dst, (char *)m68k_write_long_highfirst); 957 dst = call(dst, (char *)m68k_write_long_highfirst);
954 break; 958 break;
955 } 959 }
956 break; 960 break;
957 default: 961 default:
958 printf("address mode %d not implemented (move dst)\n", inst->dst.addr_mode); 962 m68k_disasm(inst, disasm_buf);
963 printf("%s\naddress mode %d not implemented (move dst)\n", disasm_buf, inst->dst.addr_mode);
959 exit(1); 964 exit(1);
960 } 965 }
961 966
962 //add cycles for prefetch 967 //add cycles for prefetch
963 dst = cycles(dst, BUS); 968 dst = cycles(dst, BUS);
993 case MODE_ABSOLUTE_SHORT: 998 case MODE_ABSOLUTE_SHORT:
994 early_cycles += 4; 999 early_cycles += 4;
995 dst = mov_ir(dst, inst->dst.params.immed, SCRATCH2, SZ_D); 1000 dst = mov_ir(dst, inst->dst.params.immed, SCRATCH2, SZ_D);
996 break; 1001 break;
997 default: 1002 default:
998 printf("address mode %d not implemented (movem dst)\n", inst->dst.addr_mode); 1003 m68k_disasm(inst, disasm_buf);
1004 printf("%s\naddress mode %d not implemented (movem dst)\n", disasm_buf, inst->dst.addr_mode);
999 exit(1); 1005 exit(1);
1000 } 1006 }
1001 dst = cycles(dst, early_cycles); 1007 dst = cycles(dst, early_cycles);
1002 for(bit=0; reg < 16 && reg >= 0; reg += dir, bit++) { 1008 for(bit=0; reg < 16 && reg >= 0; reg += dir, bit++) {
1003 if (inst->src.params.immed & (1 << bit)) { 1009 if (inst->src.params.immed & (1 << bit)) {
1054 case MODE_ABSOLUTE_SHORT: 1060 case MODE_ABSOLUTE_SHORT:
1055 early_cycles += 4; 1061 early_cycles += 4;
1056 dst = mov_ir(dst, inst->src.params.immed, SCRATCH1, SZ_D); 1062 dst = mov_ir(dst, inst->src.params.immed, SCRATCH1, SZ_D);
1057 break; 1063 break;
1058 default: 1064 default:
1059 printf("address mode %d not implemented (movem src)\n", inst->src.addr_mode); 1065 m68k_disasm(inst, disasm_buf);
1066 printf("%s\naddress mode %d not implemented (movem src)\n", disasm_buf, inst->src.addr_mode);
1060 exit(1); 1067 exit(1);
1061 } 1068 }
1062 dst = cycles(dst, early_cycles); 1069 dst = cycles(dst, early_cycles);
1063 for(reg = 0; reg < 16; reg ++) { 1070 for(reg = 0; reg < 16; reg ++) {
1064 if (inst->dst.params.immed & (1 << reg)) { 1071 if (inst->dst.params.immed & (1 << reg)) {
1290 } else { 1297 } else {
1291 dst = mov_irdisp8(dst, inst->src.params.immed, CONTEXT, reg_offset(&(inst->dst)), SZ_D); 1298 dst = mov_irdisp8(dst, inst->src.params.immed, CONTEXT, reg_offset(&(inst->dst)), SZ_D);
1292 } 1299 }
1293 break; 1300 break;
1294 default: 1301 default:
1295 printf("address mode %d not implemented (lea src)\n", inst->src.addr_mode); 1302 m68k_disasm(inst, disasm_buf);
1303 printf("%s\naddress mode %d not implemented (lea src)\n", disasm_buf, inst->src.addr_mode);
1296 exit(1); 1304 exit(1);
1297 } 1305 }
1298 return dst; 1306 return dst;
1299 } 1307 }
1300 1308
1370 case MODE_ABSOLUTE_SHORT: 1378 case MODE_ABSOLUTE_SHORT:
1371 dst = cycles(dst, (inst->src.addr_mode == MODE_ABSOLUTE) ? BUS * 3 : BUS * 2); 1379 dst = cycles(dst, (inst->src.addr_mode == MODE_ABSOLUTE) ? BUS * 3 : BUS * 2);
1372 dst = mov_ir(dst, inst->src.params.immed, SCRATCH1, SZ_D); 1380 dst = mov_ir(dst, inst->src.params.immed, SCRATCH1, SZ_D);
1373 break; 1381 break;
1374 default: 1382 default:
1375 printf("address mode %d not implemented (lea src)\n", inst->src.addr_mode); 1383 m68k_disasm(inst, disasm_buf);
1384 printf("%s\naddress mode %d not implemented (lea src)\n", disasm_buf, inst->src.addr_mode);
1376 exit(1); 1385 exit(1);
1377 } 1386 }
1378 dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); 1387 dst = sub_ir(dst, 4, opts->aregs[7], SZ_D);
1379 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); 1388 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D);
1380 dst = call(dst, (uint8_t *)m68k_write_long_lowfirst); 1389 dst = call(dst, (uint8_t *)m68k_write_long_lowfirst);
1696 dst = call(dst, (uint8_t *)m68k_native_addr); 1705 dst = call(dst, (uint8_t *)m68k_native_addr);
1697 dst = jmp_r(dst, SCRATCH1); 1706 dst = jmp_r(dst, SCRATCH1);
1698 } 1707 }
1699 break; 1708 break;
1700 default: 1709 default:
1701 printf("address mode %d not yet supported (jmp)\n", inst->src.addr_mode); 1710 m68k_disasm(inst, disasm_buf);
1711 printf("%s\naddress mode %d not yet supported (jmp)\n", disasm_buf, inst->src.addr_mode);
1702 exit(1); 1712 exit(1);
1703 } 1713 }
1704 return dst; 1714 return dst;
1705 } 1715 }
1706 1716
1876 } 1886 }
1877 //would add_ir(dst, 8, RSP, SZ_Q) be faster here? 1887 //would add_ir(dst, 8, RSP, SZ_Q) be faster here?
1878 dst = pop_r(dst, SCRATCH1); 1888 dst = pop_r(dst, SCRATCH1);
1879 break; 1889 break;
1880 default: 1890 default:
1881 printf("address mode %d not yet supported (jsr)\n", inst->src.addr_mode); 1891 m68k_disasm(inst, disasm_buf);
1892 printf("%s\naddress mode %d not yet supported (jsr)\n", disasm_buf, inst->src.addr_mode);
1882 exit(1); 1893 exit(1);
1883 } 1894 }
1884 return dst; 1895 return dst;
1885 } 1896 }
1886 1897
2105 #define BIT_SUPERVISOR 5 2116 #define BIT_SUPERVISOR 5
2106 2117
2107 uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) 2118 uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
2108 { 2119 {
2109 uint8_t * end_off, *zero_off, *norm_off; 2120 uint8_t * end_off, *zero_off, *norm_off;
2121 uint8_t dst_reg;
2110 map_native_address(opts->native_code_map, inst->address, dst); 2122 map_native_address(opts->native_code_map, inst->address, dst);
2111 dst = check_cycles_int(dst, inst->address); 2123 dst = check_cycles_int(dst, inst->address);
2112 if (inst->op == M68K_MOVE) { 2124 if (inst->op == M68K_MOVE) {
2113 return translate_m68k_move(dst, inst, opts); 2125 return translate_m68k_move(dst, inst, opts);
2114 } else if(inst->op == M68K_LEA) { 2126 } else if(inst->op == M68K_LEA) {
2366 dst = setcc_r(dst, CC_C, FLAG_C); 2378 dst = setcc_r(dst, CC_C, FLAG_C);
2367 dst = setcc_r(dst, CC_Z, FLAG_Z); 2379 dst = setcc_r(dst, CC_Z, FLAG_Z);
2368 dst = setcc_r(dst, CC_S, FLAG_N); 2380 dst = setcc_r(dst, CC_S, FLAG_N);
2369 dst = setcc_r(dst, CC_O, FLAG_V); 2381 dst = setcc_r(dst, CC_O, FLAG_V);
2370 break; 2382 break;
2371 /*case M68K_DIVS: 2383 case M68K_DIVS:
2372 case M68K_DIVU: 2384 case M68K_DIVU:
2373 break;*/ 2385 //TODO: Trap on division by zero
2386 dst = cycles(dst, inst->op == M68K_DIVS ? 158 : 140);
2387 dst = push_r(dst, RDX);
2388 dst = push_r(dst, RAX);
2389 if (dst_op.mode == MODE_REG_DIRECT) {
2390 dst = mov_rr(dst, dst_op.base, RAX, SZ_D);
2391 } else {
2392 dst = mov_rdisp8r(dst, dst_op.base, dst_op.disp, RAX, SZ_D);
2393 }
2394 if (src_op.mode == MODE_IMMED) {
2395 dst = mov_ir(dst, src_op.disp, SCRATCH2, SZ_D);
2396 } else if (src_op.mode == MODE_REG_DIRECT) {
2397 if (inst->op == M68K_DIVS) {
2398 dst = movsx_rr(dst, src_op.base, SCRATCH2, SZ_W, SZ_D);
2399 } else {
2400 dst = movzx_rr(dst, src_op.base, SCRATCH2, SZ_W, SZ_D);
2401 }
2402 } else if (src_op.mode == MODE_REG_DISPLACE8) {
2403 if (inst->op == M68K_DIVS) {
2404 dst = movsx_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH2, SZ_W, SZ_D);
2405 } else {
2406 dst = movzx_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH2, SZ_W, SZ_D);
2407 }
2408 }
2409 if (inst->op == M68K_DIVS) {
2410 dst = cdq(dst);
2411 } else {
2412 dst = xor_rr(dst, RDX, RDX, SZ_D);
2413 }
2414 if (inst->op == M68K_DIVS) {
2415 dst = idiv_r(dst, SCRATCH2, SZ_D);
2416 } else {
2417 dst = div_r(dst, SCRATCH2, SZ_D);
2418 }
2419 dst = cmp_ir(dst, 0x10000, RAX, SZ_D);
2420 norm_off = dst+1;
2421 dst = jcc(dst, CC_NC, dst+2);
2422 if (dst_op.mode == MODE_REG_DIRECT) {
2423 dst = mov_rr(dst, RDX, dst_op.base, SZ_W);
2424 dst = shl_ir(dst, 16, dst_op.base, SZ_D);
2425 dst = mov_rr(dst, RAX, dst_op.base, SZ_W);
2426 } else {
2427 dst = mov_rrdisp8(dst, RDX, dst_op.base, dst_op.disp, SZ_W);
2428 dst = shl_irdisp8(dst, 16, dst_op.base, dst_op.disp, SZ_D);
2429 dst = mov_rrdisp8(dst, RAX, dst_op.base, dst_op.disp, SZ_W);
2430 }
2431 dst = pop_r(dst, RAX);
2432 dst = pop_r(dst, RDX);
2433 dst = mov_ir(dst, 0, FLAG_V, SZ_B);
2434 dst = cmp_ir(dst, 0, RAX, SZ_W);
2435 dst = setcc_r(dst, CC_Z, FLAG_Z);
2436 dst = setcc_r(dst, CC_S, FLAG_N);
2437 end_off = dst+1;
2438 dst = jmp(dst, dst+2);
2439 *norm_off = dst - (norm_off + 1);
2440 dst = pop_r(dst, RAX);
2441 dst = pop_r(dst, RDX);
2442 dst = mov_ir(dst, 1, FLAG_V, SZ_B);
2443 *end_off = dst - (end_off + 1);
2444 dst = mov_ir(dst, 0, FLAG_C, SZ_B);
2445 break;
2374 case M68K_EOR: 2446 case M68K_EOR:
2375 dst = cycles(dst, BUS); 2447 dst = cycles(dst, BUS);
2376 if (src_op.mode == MODE_REG_DIRECT) { 2448 if (src_op.mode == MODE_REG_DIRECT) {
2377 if (dst_op.mode == MODE_REG_DIRECT) { 2449 if (dst_op.mode == MODE_REG_DIRECT) {
2378 dst = xor_rr(dst, src_op.base, dst_op.base, inst->extra.size); 2450 dst = xor_rr(dst, src_op.base, dst_op.base, inst->extra.size);
2485 dst = mov_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH1, SZ_D); 2557 dst = mov_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH1, SZ_D);
2486 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); 2558 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D);
2487 } 2559 }
2488 } 2560 }
2489 break; 2561 break;
2490 /*case M68K_MOVEP: 2562 //case M68K_MOVEP:
2491 case M68K_MULS: 2563 case M68K_MULS:
2492 case M68K_MULU: 2564 case M68K_MULU:
2493 case M68K_NBCD:*/ 2565 dst = cycles(dst, 70); //TODO: Calculate the actual value based on the value of the <ea> parameter
2566 if (src_op.mode == MODE_IMMED) {
2567 //immediate value should already be sign extended to 32-bits
2568 dst = mov_ir(dst, inst->op == M68K_MULU ? (src_op.disp & 0xFFFF) : src_op.disp, SCRATCH1, SZ_D);
2569 } else if (src_op.mode == MODE_REG_DIRECT) {
2570 if (inst->op == M68K_MULS) {
2571 dst = movsx_rr(dst, src_op.base, SCRATCH1, SZ_W, SZ_D);
2572 } else {
2573 dst = movzx_rr(dst, src_op.base, SCRATCH1, SZ_W, SZ_D);
2574 }
2575 } else {
2576 if (inst->op == M68K_MULS) {
2577 dst = movsx_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH1, SZ_W, SZ_D);
2578 } else {
2579 dst = movzx_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH1, SZ_W, SZ_D);
2580 }
2581 }
2582 if (dst_op.mode == MODE_REG_DIRECT) {
2583 dst_reg = dst_op.base;
2584 if (inst->op == M68K_MULS) {
2585 dst = movsx_rr(dst, dst_reg, dst_reg, SZ_W, SZ_D);
2586 } else {
2587 dst = movzx_rr(dst, dst_reg, dst_reg, SZ_W, SZ_D);
2588 }
2589 } else {
2590 dst_reg = SCRATCH2;
2591 if (inst->op == M68K_MULS) {
2592 dst = movsx_rdisp8r(dst, dst_op.base, dst_op.disp, SCRATCH2, SZ_W, SZ_D);
2593 } else {
2594 dst = movzx_rdisp8r(dst, dst_op.base, dst_op.disp, SCRATCH2, SZ_W, SZ_D);
2595 }
2596 }
2597 dst = imul_rr(dst, SCRATCH1, dst_reg, SZ_D);
2598 if (dst_op.mode == MODE_REG_DISPLACE8) {
2599 dst = mov_rrdisp8(dst, dst_reg, dst_op.base, dst_op.disp, SZ_D);
2600 }
2601 dst = mov_ir(dst, 0, FLAG_V, SZ_B);
2602 dst = mov_ir(dst, 0, FLAG_C, SZ_B);
2603 dst = cmp_ir(dst, 0, dst_reg, SZ_D);
2604 dst = setcc_r(dst, CC_Z, FLAG_Z);
2605 dst = setcc_r(dst, CC_S, FLAG_N);
2606 break;
2607 //case M68K_NBCD:
2494 case M68K_NEG: 2608 case M68K_NEG:
2495 if (dst_op.mode == MODE_REG_DIRECT) { 2609 if (dst_op.mode == MODE_REG_DIRECT) {
2496 dst = neg_r(dst, dst_op.base, inst->extra.size); 2610 dst = neg_r(dst, dst_op.base, inst->extra.size);
2497 } else { 2611 } else {
2498 dst = not_rdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size); 2612 dst = not_rdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size);
2885 dst = add_ir(dst, 4, opts->aregs[7], SZ_D); 2999 dst = add_ir(dst, 4, opts->aregs[7], SZ_D);
2886 break; 3000 break;
2887 /*case M68K_INVALID: 3001 /*case M68K_INVALID:
2888 break;*/ 3002 break;*/
2889 default: 3003 default:
2890 printf("instruction %d not yet implemented\n", inst->op); 3004 m68k_disasm(inst, disasm_buf);
3005 printf("%X: %s\ninstruction %d not yet implemented\n", inst->address, disasm_buf, inst->op);
2891 exit(1); 3006 exit(1);
2892 } 3007 }
2893 return dst; 3008 return dst;
2894 } 3009 }
2895 3010