Mercurial > repos > blastem
comparison z80_to_x86.c @ 267:1788e3f29c28
Don't mix *H regs with the REX prefix
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 02 May 2013 00:10:24 -0700 |
parents | 376df762ddf5 |
children | 6c2d7e003a55 |
comparison
equal
deleted
inserted
replaced
266:376df762ddf5 | 267:1788e3f29c28 |
---|---|
58 default: | 58 default: |
59 return Z80_UNUSED; | 59 return Z80_UNUSED; |
60 } | 60 } |
61 } | 61 } |
62 | 62 |
63 uint8_t z80_low_reg(uint8_t reg) | |
64 { | |
65 switch(reg) | |
66 { | |
67 case Z80_B: | |
68 case Z80_BC: | |
69 return Z80_C; | |
70 case Z80_D: | |
71 case Z80_DE: | |
72 return Z80_E; | |
73 case Z80_H: | |
74 case Z80_HL: | |
75 return Z80_L; | |
76 case Z80_IXH: | |
77 case Z80_IX: | |
78 return Z80_IXL; | |
79 case Z80_IYH: | |
80 case Z80_IY: | |
81 return Z80_IYL; | |
82 default: | |
83 return Z80_UNUSED; | |
84 } | |
85 } | |
86 | |
63 uint8_t * zcycles(uint8_t * dst, uint32_t num_cycles) | 87 uint8_t * zcycles(uint8_t * dst, uint32_t num_cycles) |
64 { | 88 { |
65 return add_ir(dst, num_cycles, ZCYCLES, SZ_D); | 89 return add_ir(dst, num_cycles, ZCYCLES, SZ_D); |
66 } | 90 } |
67 | 91 |
88 if (inst->reg == Z80_IYH) { | 112 if (inst->reg == Z80_IYH) { |
89 ea->base = opts->regs[Z80_IYL]; | 113 ea->base = opts->regs[Z80_IYL]; |
90 dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W); | 114 dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W); |
91 } else if(opts->regs[inst->reg] >= 0) { | 115 } else if(opts->regs[inst->reg] >= 0) { |
92 ea->base = opts->regs[inst->reg]; | 116 ea->base = opts->regs[inst->reg]; |
117 if (ea->base >= AH && ea->base <= BH && (inst->addr_mode & 0x1F) == Z80_REG) { | |
118 uint8_t other_reg = opts->regs[inst->ea_reg]; | |
119 if (other_reg > R8 || (other_reg >= RSP && other_reg <= RDI)) { | |
120 //we can't mix an *H reg with a register that requires the REX prefix | |
121 ea->base = opts->regs[z80_low_reg(inst->reg)]; | |
122 dst = ror_ir(dst, 8, ea->base, SZ_W); | |
123 } | |
124 } | |
93 } else { | 125 } else { |
94 ea->mode = MODE_REG_DISPLACE8; | 126 ea->mode = MODE_REG_DISPLACE8; |
95 ea->base = CONTEXT; | 127 ea->base = CONTEXT; |
96 ea->disp = offsetof(z80_context, regs) + inst->reg; | 128 ea->disp = offsetof(z80_context, regs) + inst->reg; |
97 } | 129 } |
101 | 133 |
102 uint8_t * z80_save_reg(uint8_t * dst, z80inst * inst, x86_z80_options * opts) | 134 uint8_t * z80_save_reg(uint8_t * dst, z80inst * inst, x86_z80_options * opts) |
103 { | 135 { |
104 if (inst->reg == Z80_IYH) { | 136 if (inst->reg == Z80_IYH) { |
105 dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W); | 137 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) { | |
139 uint8_t other_reg = opts->regs[inst->ea_reg]; | |
140 if (other_reg > R8 || (other_reg >= RSP && other_reg <= RDI)) { | |
141 //we can't mix an *H reg with a register that requires the REX prefix | |
142 dst = ror_ir(dst, 8, opts->regs[z80_low_reg(inst->reg)], SZ_W); | |
143 } | |
106 } | 144 } |
107 return dst; | 145 return dst; |
108 } | 146 } |
109 | 147 |
110 uint8_t * translate_z80_ea(z80inst * inst, x86_ea * ea, uint8_t * dst, x86_z80_options * opts, uint8_t read, uint8_t modify) | 148 uint8_t * translate_z80_ea(z80inst * inst, x86_ea * ea, uint8_t * dst, x86_z80_options * opts, uint8_t read, uint8_t modify) |
118 if (inst->ea_reg == Z80_IYH) { | 156 if (inst->ea_reg == Z80_IYH) { |
119 ea->base = opts->regs[Z80_IYL]; | 157 ea->base = opts->regs[Z80_IYL]; |
120 dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W); | 158 dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W); |
121 } else { | 159 } else { |
122 ea->base = opts->regs[inst->ea_reg]; | 160 ea->base = opts->regs[inst->ea_reg]; |
161 if (ea->base >= AH && ea->base <= BH && inst->reg != Z80_UNUSED && inst->reg != Z80_USE_IMMED) { | |
162 uint8_t other_reg = opts->regs[inst->reg]; | |
163 if (other_reg > R8 || (other_reg >= RSP && other_reg <= RDI)) { | |
164 //we can't mix an *H reg with a register that requires the REX prefix | |
165 ea->base = opts->regs[z80_low_reg(inst->ea_reg)]; | |
166 dst = ror_ir(dst, 8, ea->base, SZ_W); | |
167 } | |
168 } | |
123 } | 169 } |
124 break; | 170 break; |
125 case Z80_REG_INDIRECT: | 171 case Z80_REG_INDIRECT: |
126 dst = mov_rr(dst, opts->regs[inst->ea_reg], areg, SZ_W); | 172 dst = mov_rr(dst, opts->regs[inst->ea_reg], areg, SZ_W); |
127 size = z80_size(inst); | 173 size = z80_size(inst); |
192 return dst; | 238 return dst; |
193 } | 239 } |
194 | 240 |
195 uint8_t * z80_save_ea(uint8_t * dst, z80inst * inst, x86_z80_options * opts) | 241 uint8_t * z80_save_ea(uint8_t * dst, z80inst * inst, x86_z80_options * opts) |
196 { | 242 { |
197 if (inst->addr_mode == Z80_REG && inst->ea_reg == Z80_IYH) { | 243 if ((inst->addr_mode & 0x1F) == Z80_REG) { |
198 dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W); | 244 if (inst->ea_reg == Z80_IYH) { |
245 dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W); | |
246 } else if (inst->reg != Z80_UNUSED && inst->reg != Z80_USE_IMMED && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) { | |
247 uint8_t other_reg = opts->regs[inst->reg]; | |
248 if (other_reg > R8 || (other_reg >= RSP && other_reg <= RDI)) { | |
249 //we can't mix an *H reg with a register that requires the REX prefix | |
250 dst = ror_ir(dst, 8, opts->regs[z80_low_reg(inst->ea_reg)], SZ_W); | |
251 } | |
252 } | |
199 } | 253 } |
200 return dst; | 254 return dst; |
201 } | 255 } |
202 | 256 |
203 uint8_t * z80_save_result(uint8_t * dst, z80inst * inst) | 257 uint8_t * z80_save_result(uint8_t * dst, z80inst * inst) |
1216 map = context->static_code_map; | 1270 map = context->static_code_map; |
1217 } else if (address >= 0x8000) { | 1271 } else if (address >= 0x8000) { |
1218 address &= 0x7FFF; | 1272 address &= 0x7FFF; |
1219 map = context->banked_code_map + (context->bank_reg << 15); | 1273 map = context->banked_code_map + (context->bank_reg << 15); |
1220 } else { | 1274 } else { |
1275 printf("z80_get_native_address: %X NULL\n", address); | |
1221 return NULL; | 1276 return NULL; |
1222 } | 1277 } |
1223 if (!map->base || !map->offsets || map->offsets[address] == INVALID_OFFSET) { | 1278 if (!map->base || !map->offsets || map->offsets[address] == INVALID_OFFSET) { |
1279 printf("z80_get_native_address: %X NULL\n", address); | |
1224 return NULL; | 1280 return NULL; |
1225 } | 1281 } |
1226 //printf("z80_get_native_address: %X %p\n", address, map->base + map->offsets[address]); | 1282 printf("z80_get_native_address: %X %p\n", address, map->base + map->offsets[address]); |
1227 return map->base + map->offsets[address]; | 1283 return map->base + map->offsets[address]; |
1228 } | 1284 } |
1229 | 1285 |
1230 uint8_t z80_get_native_inst_size(x86_z80_options * opts, uint32_t address) | 1286 uint8_t z80_get_native_inst_size(x86_z80_options * opts, uint32_t address) |
1231 { | 1287 { |
1300 z80_context * z80_handle_code_write(uint32_t address, z80_context * context) | 1356 z80_context * z80_handle_code_write(uint32_t address, z80_context * context) |
1301 { | 1357 { |
1302 uint32_t inst_start = z80_get_instruction_start(context->static_code_map, address); | 1358 uint32_t inst_start = z80_get_instruction_start(context->static_code_map, address); |
1303 if (inst_start != INVALID_INSTRUCTION_START) { | 1359 if (inst_start != INVALID_INSTRUCTION_START) { |
1304 uint8_t * dst = z80_get_native_address(context, inst_start); | 1360 uint8_t * dst = z80_get_native_address(context, inst_start); |
1305 //printf("patching code at %p for Z80 instruction at %X due to write to %X\n", dst, inst_start, address); | 1361 printf("patching code at %p for Z80 instruction at %X due to write to %X\n", dst, inst_start, address); |
1306 dst = mov_ir(dst, inst_start, SCRATCH1, SZ_D); | 1362 dst = mov_ir(dst, inst_start, SCRATCH1, SZ_D); |
1307 dst = jmp(dst, (uint8_t *)z80_retrans_stub); | 1363 dst = jmp(dst, (uint8_t *)z80_retrans_stub); |
1308 } | 1364 } |
1309 return context; | 1365 return context; |
1310 } | 1366 } |
1341 address &= 0x1FFF; | 1397 address &= 0x1FFF; |
1342 uint8_t * dst = opts->cur_code; | 1398 uint8_t * dst = opts->cur_code; |
1343 uint8_t * dst_end = opts->code_end; | 1399 uint8_t * dst_end = opts->code_end; |
1344 uint8_t *after, *inst = context->mem_pointers[0] + address; | 1400 uint8_t *after, *inst = context->mem_pointers[0] + address; |
1345 z80inst instbuf; | 1401 z80inst instbuf; |
1346 //printf("Retranslating code at Z80 address %X, native address %p\n", address, orig_start); | 1402 printf("Retranslating code at Z80 address %X, native address %p\n", address, orig_start); |
1347 after = z80_decode(inst, &instbuf); | 1403 after = z80_decode(inst, &instbuf); |
1348 /*z80_disasm(&instbuf, disbuf); | 1404 z80_disasm(&instbuf, disbuf); |
1349 if (instbuf.op == Z80_NOP) { | 1405 if (instbuf.op == Z80_NOP) { |
1350 printf("%X\t%s(%d)\n", address, disbuf, instbuf.immed); | 1406 printf("%X\t%s(%d)\n", address, disbuf, instbuf.immed); |
1351 } else { | 1407 } else { |
1352 printf("%X\t%s\n", address, disbuf); | 1408 printf("%X\t%s\n", address, disbuf); |
1353 }*/ | 1409 } |
1354 if (orig_size != ZMAX_NATIVE_SIZE) { | 1410 if (orig_size != ZMAX_NATIVE_SIZE) { |
1355 if (dst_end - dst < ZMAX_NATIVE_SIZE) { | 1411 if (dst_end - dst < ZMAX_NATIVE_SIZE) { |
1356 size_t size = 1024*1024; | 1412 size_t size = 1024*1024; |
1357 dst = alloc_code(&size); | 1413 dst = alloc_code(&size); |
1358 opts->code_end = dst_end = dst + size; | 1414 opts->code_end = dst_end = dst + size; |
1406 encoded = context->mem_pointers[1] + (address & 0x7FFF); | 1462 encoded = context->mem_pointers[1] + (address & 0x7FFF); |
1407 } | 1463 } |
1408 while (encoded != NULL) | 1464 while (encoded != NULL) |
1409 { | 1465 { |
1410 z80inst inst; | 1466 z80inst inst; |
1411 //printf("translating Z80 code at address %X\n", address); | 1467 printf("translating Z80 code at address %X\n", address); |
1412 do { | 1468 do { |
1413 if (opts->code_end-opts->cur_code < ZMAX_NATIVE_SIZE) { | 1469 if (opts->code_end-opts->cur_code < ZMAX_NATIVE_SIZE) { |
1414 if (opts->code_end-opts->cur_code < 5) { | 1470 if (opts->code_end-opts->cur_code < 5) { |
1415 puts("out of code memory, not enough space for jmp to next chunk"); | 1471 puts("out of code memory, not enough space for jmp to next chunk"); |
1416 exit(1); | 1472 exit(1); |