Mercurial > repos > blastem
comparison z80_to_x86.c @ 268:6c2d7e003a55
Sync Z80 on writes to busreq/reset ports. NULL out extra_pc on z80 reset
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 02 May 2013 21:54:04 -0700 |
parents | 1788e3f29c28 |
children | 3c054d977175 |
comparison
equal
deleted
inserted
replaced
267:1788e3f29c28 | 268:6c2d7e003a55 |
---|---|
12 #define ZCYCLES RBP | 12 #define ZCYCLES RBP |
13 #define ZLIMIT RDI | 13 #define ZLIMIT RDI |
14 #define SCRATCH1 R13 | 14 #define SCRATCH1 R13 |
15 #define SCRATCH2 R14 | 15 #define SCRATCH2 R14 |
16 #define CONTEXT RSI | 16 #define CONTEXT RSI |
17 | |
18 #ifdef DO_DEBUG_PRINT | |
19 #define dprintf printf | |
20 #else | |
21 #define dprintf | |
22 #endif | |
17 | 23 |
18 void z80_read_byte(); | 24 void z80_read_byte(); |
19 void z80_read_word(); | 25 void z80_read_word(); |
20 void z80_write_byte(); | 26 void z80_write_byte(); |
21 void z80_write_word_highfirst(); | 27 void z80_write_word_highfirst(); |
112 if (inst->reg == Z80_IYH) { | 118 if (inst->reg == Z80_IYH) { |
113 ea->base = opts->regs[Z80_IYL]; | 119 ea->base = opts->regs[Z80_IYL]; |
114 dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W); | 120 dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W); |
115 } else if(opts->regs[inst->reg] >= 0) { | 121 } else if(opts->regs[inst->reg] >= 0) { |
116 ea->base = opts->regs[inst->reg]; | 122 ea->base = opts->regs[inst->reg]; |
117 if (ea->base >= AH && ea->base <= BH && (inst->addr_mode & 0x1F) == Z80_REG) { | 123 if (ea->base >= AH && ea->base <= BH) { |
118 uint8_t other_reg = opts->regs[inst->ea_reg]; | 124 if ((inst->addr_mode & 0x1F) == Z80_REG) { |
119 if (other_reg > R8 || (other_reg >= RSP && other_reg <= RDI)) { | 125 uint8_t other_reg = opts->regs[inst->ea_reg]; |
120 //we can't mix an *H reg with a register that requires the REX prefix | 126 if (other_reg > R8 || (other_reg >= RSP && other_reg <= RDI)) { |
127 //we can't mix an *H reg with a register that requires the REX prefix | |
128 ea->base = opts->regs[z80_low_reg(inst->reg)]; | |
129 dst = ror_ir(dst, 8, ea->base, SZ_W); | |
130 } | |
131 } else if((inst->addr_mode & 0x1F) != Z80_UNUSED && (inst->addr_mode & 0x1F) != Z80_IMMED) { | |
132 //temp regs require REX prefix too | |
121 ea->base = opts->regs[z80_low_reg(inst->reg)]; | 133 ea->base = opts->regs[z80_low_reg(inst->reg)]; |
122 dst = ror_ir(dst, 8, ea->base, SZ_W); | 134 dst = ror_ir(dst, 8, ea->base, SZ_W); |
123 } | 135 } |
124 } | 136 } |
125 } else { | 137 } else { |
133 | 145 |
134 uint8_t * z80_save_reg(uint8_t * dst, z80inst * inst, x86_z80_options * opts) | 146 uint8_t * z80_save_reg(uint8_t * dst, z80inst * inst, x86_z80_options * opts) |
135 { | 147 { |
136 if (inst->reg == Z80_IYH) { | 148 if (inst->reg == Z80_IYH) { |
137 dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W); | 149 dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W); |
138 } else if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->reg] >= AH && opts->regs[inst->reg] <= BH) { | 150 } else if (opts->regs[inst->reg] >= AH && opts->regs[inst->reg] <= BH) { |
139 uint8_t other_reg = opts->regs[inst->ea_reg]; | 151 if ((inst->addr_mode & 0x1F) == Z80_REG) { |
140 if (other_reg > R8 || (other_reg >= RSP && other_reg <= RDI)) { | 152 uint8_t other_reg = opts->regs[inst->ea_reg]; |
141 //we can't mix an *H reg with a register that requires the REX prefix | 153 if (other_reg > R8 || (other_reg >= RSP && other_reg <= RDI)) { |
154 //we can't mix an *H reg with a register that requires the REX prefix | |
155 dst = ror_ir(dst, 8, opts->regs[z80_low_reg(inst->reg)], SZ_W); | |
156 } | |
157 } else if((inst->addr_mode & 0x1F) != Z80_UNUSED && (inst->addr_mode & 0x1F) != Z80_IMMED) { | |
158 //temp regs require REX prefix too | |
142 dst = ror_ir(dst, 8, opts->regs[z80_low_reg(inst->reg)], SZ_W); | 159 dst = ror_ir(dst, 8, opts->regs[z80_low_reg(inst->reg)], SZ_W); |
143 } | 160 } |
144 } | 161 } |
145 return dst; | 162 return dst; |
146 } | 163 } |
1270 map = context->static_code_map; | 1287 map = context->static_code_map; |
1271 } else if (address >= 0x8000) { | 1288 } else if (address >= 0x8000) { |
1272 address &= 0x7FFF; | 1289 address &= 0x7FFF; |
1273 map = context->banked_code_map + (context->bank_reg << 15); | 1290 map = context->banked_code_map + (context->bank_reg << 15); |
1274 } else { | 1291 } else { |
1275 printf("z80_get_native_address: %X NULL\n", address); | 1292 dprintf("z80_get_native_address: %X NULL\n", address); |
1276 return NULL; | 1293 return NULL; |
1277 } | 1294 } |
1278 if (!map->base || !map->offsets || map->offsets[address] == INVALID_OFFSET) { | 1295 if (!map->base || !map->offsets || map->offsets[address] == INVALID_OFFSET || map->offsets[address] == EXTENSION_WORD) { |
1279 printf("z80_get_native_address: %X NULL\n", address); | 1296 dprintf("z80_get_native_address: %X NULL\n", address); |
1280 return NULL; | 1297 return NULL; |
1281 } | 1298 } |
1282 printf("z80_get_native_address: %X %p\n", address, map->base + map->offsets[address]); | 1299 dprintf("z80_get_native_address: %X %p\n", address, map->base + map->offsets[address]); |
1283 return map->base + map->offsets[address]; | 1300 return map->base + map->offsets[address]; |
1284 } | 1301 } |
1285 | 1302 |
1286 uint8_t z80_get_native_inst_size(x86_z80_options * opts, uint32_t address) | 1303 uint8_t z80_get_native_inst_size(x86_z80_options * opts, uint32_t address) |
1287 { | 1304 { |
1356 z80_context * z80_handle_code_write(uint32_t address, z80_context * context) | 1373 z80_context * z80_handle_code_write(uint32_t address, z80_context * context) |
1357 { | 1374 { |
1358 uint32_t inst_start = z80_get_instruction_start(context->static_code_map, address); | 1375 uint32_t inst_start = z80_get_instruction_start(context->static_code_map, address); |
1359 if (inst_start != INVALID_INSTRUCTION_START) { | 1376 if (inst_start != INVALID_INSTRUCTION_START) { |
1360 uint8_t * dst = z80_get_native_address(context, inst_start); | 1377 uint8_t * dst = z80_get_native_address(context, inst_start); |
1361 printf("patching code at %p for Z80 instruction at %X due to write to %X\n", dst, inst_start, address); | 1378 dprintf("patching code at %p for Z80 instruction at %X due to write to %X\n", dst, inst_start, address); |
1362 dst = mov_ir(dst, inst_start, SCRATCH1, SZ_D); | 1379 dst = mov_ir(dst, inst_start, SCRATCH1, SZ_D); |
1363 dst = jmp(dst, (uint8_t *)z80_retrans_stub); | 1380 dst = jmp(dst, (uint8_t *)z80_retrans_stub); |
1364 } | 1381 } |
1365 return context; | 1382 return context; |
1366 } | 1383 } |
1397 address &= 0x1FFF; | 1414 address &= 0x1FFF; |
1398 uint8_t * dst = opts->cur_code; | 1415 uint8_t * dst = opts->cur_code; |
1399 uint8_t * dst_end = opts->code_end; | 1416 uint8_t * dst_end = opts->code_end; |
1400 uint8_t *after, *inst = context->mem_pointers[0] + address; | 1417 uint8_t *after, *inst = context->mem_pointers[0] + address; |
1401 z80inst instbuf; | 1418 z80inst instbuf; |
1402 printf("Retranslating code at Z80 address %X, native address %p\n", address, orig_start); | 1419 dprintf("Retranslating code at Z80 address %X, native address %p\n", address, orig_start); |
1403 after = z80_decode(inst, &instbuf); | 1420 after = z80_decode(inst, &instbuf); |
1421 #ifdef DO_DEBUG_PRINT | |
1404 z80_disasm(&instbuf, disbuf); | 1422 z80_disasm(&instbuf, disbuf); |
1405 if (instbuf.op == Z80_NOP) { | 1423 if (instbuf.op == Z80_NOP) { |
1406 printf("%X\t%s(%d)\n", address, disbuf, instbuf.immed); | 1424 printf("%X\t%s(%d)\n", address, disbuf, instbuf.immed); |
1407 } else { | 1425 } else { |
1408 printf("%X\t%s\n", address, disbuf); | 1426 printf("%X\t%s\n", address, disbuf); |
1409 } | 1427 } |
1428 #endif | |
1410 if (orig_size != ZMAX_NATIVE_SIZE) { | 1429 if (orig_size != ZMAX_NATIVE_SIZE) { |
1411 if (dst_end - dst < ZMAX_NATIVE_SIZE) { | 1430 if (dst_end - dst < ZMAX_NATIVE_SIZE) { |
1412 size_t size = 1024*1024; | 1431 size_t size = 1024*1024; |
1413 dst = alloc_code(&size); | 1432 dst = alloc_code(&size); |
1414 opts->code_end = dst_end = dst + size; | 1433 opts->code_end = dst_end = dst + size; |
1462 encoded = context->mem_pointers[1] + (address & 0x7FFF); | 1481 encoded = context->mem_pointers[1] + (address & 0x7FFF); |
1463 } | 1482 } |
1464 while (encoded != NULL) | 1483 while (encoded != NULL) |
1465 { | 1484 { |
1466 z80inst inst; | 1485 z80inst inst; |
1467 printf("translating Z80 code at address %X\n", address); | 1486 dprintf("translating Z80 code at address %X\n", address); |
1468 do { | 1487 do { |
1469 if (opts->code_end-opts->cur_code < ZMAX_NATIVE_SIZE) { | 1488 if (opts->code_end-opts->cur_code < ZMAX_NATIVE_SIZE) { |
1470 if (opts->code_end-opts->cur_code < 5) { | 1489 if (opts->code_end-opts->cur_code < 5) { |
1471 puts("out of code memory, not enough space for jmp to next chunk"); | 1490 puts("out of code memory, not enough space for jmp to next chunk"); |
1472 exit(1); | 1491 exit(1); |
1485 if (existing) { | 1504 if (existing) { |
1486 opts->cur_code = jmp(opts->cur_code, existing); | 1505 opts->cur_code = jmp(opts->cur_code, existing); |
1487 break; | 1506 break; |
1488 } | 1507 } |
1489 next = z80_decode(encoded, &inst); | 1508 next = z80_decode(encoded, &inst); |
1509 #ifdef DO_DEBUG_PRINT | |
1490 z80_disasm(&inst, disbuf); | 1510 z80_disasm(&inst, disbuf); |
1491 if (inst.op == Z80_NOP) { | 1511 if (inst.op == Z80_NOP) { |
1492 printf("%X\t%s(%d)\n", address, disbuf, inst.immed); | 1512 printf("%X\t%s(%d)\n", address, disbuf, inst.immed); |
1493 } else { | 1513 } else { |
1494 printf("%X\t%s\n", address, disbuf); | 1514 printf("%X\t%s\n", address, disbuf); |
1495 } | 1515 } |
1516 #endif | |
1496 uint8_t *after = translate_z80inst(&inst, opts->cur_code, context, address); | 1517 uint8_t *after = translate_z80inst(&inst, opts->cur_code, context, address); |
1497 z80_map_native_address(context, address, opts->cur_code, next-encoded, after - opts->cur_code); | 1518 z80_map_native_address(context, address, opts->cur_code, next-encoded, after - opts->cur_code); |
1498 opts->cur_code = after; | 1519 opts->cur_code = after; |
1499 address += next-encoded; | 1520 address += next-encoded; |
1500 if (address > 0xFFFF) { | 1521 if (address > 0xFFFF) { |
1505 } | 1526 } |
1506 } while (!(inst.op == Z80_RET || inst.op == Z80_RETI || inst.op == Z80_RETN || inst.op == Z80_JP || (inst.op == Z80_NOP && inst.immed == 42))); | 1527 } while (!(inst.op == Z80_RET || inst.op == Z80_RETI || inst.op == Z80_RETN || inst.op == Z80_JP || (inst.op == Z80_NOP && inst.immed == 42))); |
1507 process_deferred(&opts->deferred, context, (native_addr_func)z80_get_native_address); | 1528 process_deferred(&opts->deferred, context, (native_addr_func)z80_get_native_address); |
1508 if (opts->deferred) { | 1529 if (opts->deferred) { |
1509 address = opts->deferred->address; | 1530 address = opts->deferred->address; |
1510 printf("defferred address: %X\n", address); | 1531 dprintf("defferred address: %X\n", address); |
1511 if (address < 0x4000) { | 1532 if (address < 0x4000) { |
1512 encoded = context->mem_pointers[0] + (address & 0x1FFF); | 1533 encoded = context->mem_pointers[0] + (address & 0x1FFF); |
1513 } else if (address > 0x8000 && context->mem_pointers[1]) { | 1534 } else if (address > 0x8000 && context->mem_pointers[1]) { |
1514 encoded = context->mem_pointers[1] + (address & 0x7FFF); | 1535 encoded = context->mem_pointers[1] + (address & 0x7FFF); |
1515 } else { | 1536 } else { |
1568 void z80_reset(z80_context * context) | 1589 void z80_reset(z80_context * context) |
1569 { | 1590 { |
1570 context->im = 0; | 1591 context->im = 0; |
1571 context->iff1 = context->iff2 = 0; | 1592 context->iff1 = context->iff2 = 0; |
1572 context->native_pc = z80_get_native_address_trans(context, 0); | 1593 context->native_pc = z80_get_native_address_trans(context, 0); |
1573 } | 1594 context->extra_pc = NULL; |
1574 | 1595 } |
1575 | 1596 |
1597 |