Mercurial > repos > blastem
comparison z80_to_x86.c @ 250:5f1b68cecfc7
Implemented basic interrupt support in Z80 core.
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Mon, 29 Apr 2013 00:59:50 -0700 |
parents | 9c7a3db7bcd0 |
children | 63b9a500a00b |
comparison
equal
deleted
inserted
replaced
249:d94e6cd5a8a5 | 250:5f1b68cecfc7 |
---|---|
8 #include <string.h> | 8 #include <string.h> |
9 | 9 |
10 #define MODE_UNUSED (MODE_IMMED-1) | 10 #define MODE_UNUSED (MODE_IMMED-1) |
11 | 11 |
12 #define ZCYCLES RBP | 12 #define ZCYCLES RBP |
13 #define ZLIMIT RDI | |
13 #define SCRATCH1 R13 | 14 #define SCRATCH1 R13 |
14 #define SCRATCH2 R14 | 15 #define SCRATCH2 R14 |
15 #define CONTEXT RSI | 16 #define CONTEXT RSI |
16 | 17 |
17 //TODO: Find out the actual value for this | 18 //TODO: Find out the actual value for this |
22 void z80_write_byte(); | 23 void z80_write_byte(); |
23 void z80_write_word_highfirst(); | 24 void z80_write_word_highfirst(); |
24 void z80_write_word_lowfirst(); | 25 void z80_write_word_lowfirst(); |
25 void z80_save_context(); | 26 void z80_save_context(); |
26 void z80_native_addr(); | 27 void z80_native_addr(); |
28 void z80_do_sync(); | |
29 void z80_handle_cycle_limit_int(); | |
27 | 30 |
28 uint8_t z80_size(z80inst * inst) | 31 uint8_t z80_size(z80inst * inst) |
29 { | 32 { |
30 uint8_t reg = (inst->reg & 0x1F); | 33 uint8_t reg = (inst->reg & 0x1F); |
31 if (reg != Z80_UNUSED && reg != Z80_USE_IMMED) { | 34 if (reg != Z80_UNUSED && reg != Z80_USE_IMMED) { |
62 uint8_t * zcycles(uint8_t * dst, uint32_t num_cycles) | 65 uint8_t * zcycles(uint8_t * dst, uint32_t num_cycles) |
63 { | 66 { |
64 return add_ir(dst, num_cycles, ZCYCLES, SZ_D); | 67 return add_ir(dst, num_cycles, ZCYCLES, SZ_D); |
65 } | 68 } |
66 | 69 |
70 uint8_t * z80_check_cycles_int(uint8_t * dst, uint16_t address) | |
71 { | |
72 dst = cmp_rr(dst, ZCYCLES, ZLIMIT, SZ_D); | |
73 uint8_t * jmp_off = dst+1; | |
74 dst = jcc(dst, CC_NC, dst + 7); | |
75 dst = mov_ir(dst, address, SCRATCH2, SZ_W); | |
76 dst = call(dst, (uint8_t *)z80_handle_cycle_limit_int); | |
77 *jmp_off = dst - (jmp_off+1); | |
78 return dst; | |
79 } | |
80 | |
67 uint8_t * translate_z80_reg(z80inst * inst, x86_ea * ea, uint8_t * dst, x86_z80_options * opts) | 81 uint8_t * translate_z80_reg(z80inst * inst, x86_ea * ea, uint8_t * dst, x86_z80_options * opts) |
68 { | 82 { |
69 if (inst->reg == Z80_USE_IMMED) { | 83 if (inst->reg == Z80_USE_IMMED) { |
70 ea->mode = MODE_IMMED; | 84 ea->mode = MODE_IMMED; |
71 ea->disp = inst->immed; | 85 ea->disp = inst->immed; |
242 { | 256 { |
243 uint32_t cycles; | 257 uint32_t cycles; |
244 x86_ea src_op, dst_op; | 258 x86_ea src_op, dst_op; |
245 uint8_t size; | 259 uint8_t size; |
246 x86_z80_options *opts = context->options; | 260 x86_z80_options *opts = context->options; |
261 dst = z80_check_cycles_int(dst, address); | |
247 switch(inst->op) | 262 switch(inst->op) |
248 { | 263 { |
249 case Z80_LD: | 264 case Z80_LD: |
250 size = z80_size(inst); | 265 size = z80_size(inst); |
251 switch (inst->addr_mode & 0x1F) | 266 switch (inst->addr_mode & 0x1F) |
695 //case Z80_HALT: | 710 //case Z80_HALT: |
696 case Z80_DI: | 711 case Z80_DI: |
697 dst = zcycles(dst, 4); | 712 dst = zcycles(dst, 4); |
698 dst = mov_irdisp8(dst, 0, CONTEXT, offsetof(z80_context, iff1), SZ_B); | 713 dst = mov_irdisp8(dst, 0, CONTEXT, offsetof(z80_context, iff1), SZ_B); |
699 dst = mov_irdisp8(dst, 0, CONTEXT, offsetof(z80_context, iff2), SZ_B); | 714 dst = mov_irdisp8(dst, 0, CONTEXT, offsetof(z80_context, iff2), SZ_B); |
715 dst = mov_rdisp8r(dst, CONTEXT, offsetof(z80_context, sync_cycle), ZLIMIT, SZ_D); | |
700 break; | 716 break; |
701 case Z80_EI: | 717 case Z80_EI: |
702 //TODO: Implement interrupt enable latency of 1 instruction afer EI | 718 //TODO: Implement interrupt enable latency of 1 instruction afer EI |
703 dst = zcycles(dst, 4); | 719 dst = zcycles(dst, 4); |
704 dst = mov_irdisp8(dst, 1, CONTEXT, offsetof(z80_context, iff1), SZ_B); | 720 dst = mov_irdisp8(dst, 1, CONTEXT, offsetof(z80_context, iff1), SZ_B); |
705 dst = mov_irdisp8(dst, 1, CONTEXT, offsetof(z80_context, iff2), SZ_B); | 721 dst = mov_irdisp8(dst, 1, CONTEXT, offsetof(z80_context, iff2), SZ_B); |
722 dst = call(dst, (uint8_t *)z80_do_sync); | |
706 break; | 723 break; |
707 case Z80_IM: | 724 case Z80_IM: |
708 dst = zcycles(dst, 4); | 725 dst = zcycles(dst, 4); |
709 dst = mov_irdisp8(dst, inst->immed, CONTEXT, offsetof(z80_context, im), SZ_B); | 726 dst = mov_irdisp8(dst, inst->immed, CONTEXT, offsetof(z80_context, im), SZ_B); |
710 break; | 727 break; |
1187 { | 1204 { |
1188 uint8_t * addr = z80_get_native_address(context, address); | 1205 uint8_t * addr = z80_get_native_address(context, address); |
1189 if (!addr) { | 1206 if (!addr) { |
1190 translate_z80_stream(context, address); | 1207 translate_z80_stream(context, address); |
1191 addr = z80_get_native_address(context, address); | 1208 addr = z80_get_native_address(context, address); |
1209 if (!addr) { | |
1210 printf("Failed to translate %X to native code\n", address); | |
1211 } | |
1192 } | 1212 } |
1193 return addr; | 1213 return addr; |
1194 } | 1214 } |
1195 | 1215 |
1196 //uint32_t max_size = 0; | 1216 //uint32_t max_size = 0; |