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);