Mercurial > repos > blastem
comparison z80_to_x86.c @ 264:8fd6652e56f8
Fix a crash bug in instruction retranslation
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Wed, 01 May 2013 20:09:53 -0700 |
parents | d97c9eca49f4 |
children | 376df762ddf5 |
comparison
equal
deleted
inserted
replaced
263:2989ed7b8608 | 264:8fd6652e56f8 |
---|---|
1221 return NULL; | 1221 return NULL; |
1222 } | 1222 } |
1223 if (!map->base || !map->offsets || map->offsets[address] == INVALID_OFFSET) { | 1223 if (!map->base || !map->offsets || map->offsets[address] == INVALID_OFFSET) { |
1224 return NULL; | 1224 return NULL; |
1225 } | 1225 } |
1226 //printf("z80_get_native_address: %X %p\n", address, map->base + map->offsets[address]); | |
1226 return map->base + map->offsets[address]; | 1227 return map->base + map->offsets[address]; |
1227 } | 1228 } |
1228 | 1229 |
1229 uint8_t z80_get_native_inst_size(x86_z80_options * opts, uint32_t address) | 1230 uint8_t z80_get_native_inst_size(x86_z80_options * opts, uint32_t address) |
1230 { | 1231 { |
1299 z80_context * z80_handle_code_write(uint32_t address, z80_context * context) | 1300 z80_context * z80_handle_code_write(uint32_t address, z80_context * context) |
1300 { | 1301 { |
1301 uint32_t inst_start = z80_get_instruction_start(context->static_code_map, address); | 1302 uint32_t inst_start = z80_get_instruction_start(context->static_code_map, address); |
1302 if (inst_start != INVALID_INSTRUCTION_START) { | 1303 if (inst_start != INVALID_INSTRUCTION_START) { |
1303 uint8_t * dst = z80_get_native_address(context, inst_start); | 1304 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); | |
1304 dst = mov_ir(dst, inst_start, SCRATCH1, SZ_D); | 1306 dst = mov_ir(dst, inst_start, SCRATCH1, SZ_D); |
1305 dst = jmp(dst, (uint8_t *)z80_retrans_stub); | 1307 dst = jmp(dst, (uint8_t *)z80_retrans_stub); |
1306 } | 1308 } |
1307 return context; | 1309 return context; |
1310 } | |
1311 | |
1312 uint8_t * z80_get_native_address_trans(z80_context * context, uint32_t address) | |
1313 { | |
1314 uint8_t * addr = z80_get_native_address(context, address); | |
1315 if (!addr) { | |
1316 translate_z80_stream(context, address); | |
1317 addr = z80_get_native_address(context, address); | |
1318 if (!addr) { | |
1319 printf("Failed to translate %X to native code\n", address); | |
1320 } | |
1321 } | |
1322 return addr; | |
1308 } | 1323 } |
1309 | 1324 |
1310 void * z80_retranslate_inst(uint32_t address, z80_context * context) | 1325 void * z80_retranslate_inst(uint32_t address, z80_context * context) |
1311 { | 1326 { |
1312 x86_z80_options * opts = context->options; | 1327 x86_z80_options * opts = context->options; |
1326 opts->code_end = dst_end = dst + size; | 1341 opts->code_end = dst_end = dst + size; |
1327 opts->cur_code = dst; | 1342 opts->cur_code = dst; |
1328 } | 1343 } |
1329 uint8_t * native_end = translate_z80inst(&instbuf, dst, context, address); | 1344 uint8_t * native_end = translate_z80inst(&instbuf, dst, context, address); |
1330 if ((native_end - dst) <= orig_size) { | 1345 if ((native_end - dst) <= orig_size) { |
1331 native_end = translate_z80inst(&instbuf, orig_start, context, address); | 1346 uint8_t * native_next = z80_get_native_address(context, address + after-inst); |
1332 while (native_end < orig_start + orig_size) { | 1347 if (native_next && ((native_next == orig_start + orig_size) || (orig_size - (native_end - dst)) > 5)) { |
1333 *(native_end++) = 0x90; //NOP | 1348 native_end = translate_z80inst(&instbuf, orig_start, context, address); |
1334 } | 1349 if (native_next == orig_start + orig_size) { |
1335 return orig_start; | 1350 while (native_end < orig_start + orig_size) { |
1336 } else { | 1351 *(native_end++) = 0x90; //NOP |
1337 z80_map_native_address(context, address, dst, after-inst, ZMAX_NATIVE_SIZE); | 1352 } |
1338 opts->code_end = dst+ZMAX_NATIVE_SIZE; | 1353 } else { |
1339 if(!(instbuf.op == Z80_RET || instbuf.op == Z80_RETI || instbuf.op == Z80_RETN || instbuf.op == Z80_JP || (instbuf.op == Z80_NOP && instbuf.immed == 42))) { | 1354 jmp(native_end, native_next); |
1340 jmp(native_end, z80_get_native_address(context, address + after-inst)); | 1355 } |
1341 } | 1356 return orig_start; |
1342 return dst; | 1357 } |
1343 } | 1358 } |
1359 z80_map_native_address(context, address, dst, after-inst, ZMAX_NATIVE_SIZE); | |
1360 opts->code_end = dst+ZMAX_NATIVE_SIZE; | |
1361 if(!(instbuf.op == Z80_RET || instbuf.op == Z80_RETI || instbuf.op == Z80_RETN || instbuf.op == Z80_JP || (instbuf.op == Z80_NOP && instbuf.immed == 42))) { | |
1362 jmp(native_end, z80_get_native_address_trans(context, address + after-inst)); | |
1363 } | |
1364 return dst; | |
1344 } else { | 1365 } else { |
1345 dst = translate_z80inst(&instbuf, orig_start, context, address); | 1366 dst = translate_z80inst(&instbuf, orig_start, context, address); |
1346 if(!(instbuf.op == Z80_RET || instbuf.op == Z80_RETI || instbuf.op == Z80_RETN || instbuf.op == Z80_JP || (instbuf.op == Z80_NOP && instbuf.immed == 42))) { | 1367 if(!(instbuf.op == Z80_RET || instbuf.op == Z80_RETI || instbuf.op == Z80_RETN || instbuf.op == Z80_JP || (instbuf.op == Z80_NOP && instbuf.immed == 42))) { |
1347 dst = jmp(dst, z80_get_native_address(context, address + after-inst)); | 1368 dst = jmp(dst, z80_get_native_address_trans(context, address + after-inst)); |
1348 } | 1369 } |
1349 return orig_start; | 1370 return orig_start; |
1350 } | 1371 } |
1351 } | |
1352 | |
1353 uint8_t * z80_get_native_address_trans(z80_context * context, uint32_t address) | |
1354 { | |
1355 uint8_t * addr = z80_get_native_address(context, address); | |
1356 if (!addr) { | |
1357 translate_z80_stream(context, address); | |
1358 addr = z80_get_native_address(context, address); | |
1359 if (!addr) { | |
1360 printf("Failed to translate %X to native code\n", address); | |
1361 } | |
1362 } | |
1363 return addr; | |
1364 } | 1372 } |
1365 | 1373 |
1366 void translate_z80_stream(z80_context * context, uint32_t address) | 1374 void translate_z80_stream(z80_context * context, uint32_t address) |
1367 { | 1375 { |
1368 char disbuf[80]; | 1376 char disbuf[80]; |
1377 encoded = context->mem_pointers[1] + (address & 0x7FFF); | 1385 encoded = context->mem_pointers[1] + (address & 0x7FFF); |
1378 } | 1386 } |
1379 while (encoded != NULL) | 1387 while (encoded != NULL) |
1380 { | 1388 { |
1381 z80inst inst; | 1389 z80inst inst; |
1382 printf("translating Z80 code at address %X\n", address); | 1390 //printf("translating Z80 code at address %X\n", address); |
1383 do { | 1391 do { |
1384 if (opts->code_end-opts->cur_code < ZMAX_NATIVE_SIZE) { | 1392 if (opts->code_end-opts->cur_code < ZMAX_NATIVE_SIZE) { |
1385 if (opts->code_end-opts->cur_code < 5) { | 1393 if (opts->code_end-opts->cur_code < 5) { |
1386 puts("out of code memory, not enough space for jmp to next chunk"); | 1394 puts("out of code memory, not enough space for jmp to next chunk"); |
1387 exit(1); | 1395 exit(1); |