Mercurial > repos > blastem
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 |