comparison z80_to_x86.c @ 591:966b46c68942

Get Z80 core back into compileable state
author Michael Pavone <pavone@retrodev.com>
date Wed, 17 Dec 2014 09:53:51 -0800
parents ea80559c67cb
children 4ff7bbb3943b
comparison
equal deleted inserted replaced
590:ea80559c67cb 591:966b46c68942
52 } 52 }
53 //TODO: Handle any necessary special cases 53 //TODO: Handle any necessary special cases
54 return SZ_B; 54 return SZ_B;
55 } 55 }
56 56
57 void translate_z80_reg(z80inst * inst, x86_ea * ea, z80_options * opts) 57 void translate_z80_reg(z80inst * inst, host_ea * ea, z80_options * opts)
58 { 58 {
59 code_info *code = &opts->gen.code; 59 code_info *code = &opts->gen.code;
60 if (inst->reg == Z80_USE_IMMED) { 60 if (inst->reg == Z80_USE_IMMED) {
61 ea->mode = MODE_IMMED; 61 ea->mode = MODE_IMMED;
62 ea->disp = inst->immed; 62 ea->disp = inst->immed;
120 ror_ir(code, 8, opts->regs[z80_low_reg(inst->reg)], SZ_W); 120 ror_ir(code, 8, opts->regs[z80_low_reg(inst->reg)], SZ_W);
121 } 121 }
122 } 122 }
123 } 123 }
124 124
125 void translate_z80_ea(z80inst * inst, x86_ea * ea, z80_options * opts, uint8_t read, uint8_t modify) 125 void translate_z80_ea(z80inst * inst, host_ea * ea, z80_options * opts, uint8_t read, uint8_t modify)
126 { 126 {
127 code_info *code = &opts->gen.code; 127 code_info *code = &opts->gen.code;
128 uint8_t size, reg, areg; 128 uint8_t size, reg, areg;
129 ea->mode = MODE_REG_DIRECT; 129 ea->mode = MODE_REG_DIRECT;
130 areg = read ? opts->gen.scratch1 : opts->gen.scratch2; 130 areg = read ? opts->gen.scratch1 : opts->gen.scratch2;
156 mov_rr(code, opts->regs[inst->ea_reg], areg, SZ_W); 156 mov_rr(code, opts->regs[inst->ea_reg], areg, SZ_W);
157 size = z80_size(inst); 157 size = z80_size(inst);
158 if (read) { 158 if (read) {
159 if (modify) { 159 if (modify) {
160 //push_r(code, opts->gen.scratch1); 160 //push_r(code, opts->gen.scratch1);
161 mov_rrdisp8(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_W); 161 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_W);
162 } 162 }
163 if (size == SZ_B) { 163 if (size == SZ_B) {
164 call(code, opts->read_8); 164 call(code, opts->read_8);
165 } else { 165 } else {
166 dst = call(dst, opts->read_16); 166 call(code, opts->read_16);
167 } 167 }
168 if (modify) { 168 if (modify) {
169 //pop_r(code, opts->gen.scratch2); 169 //pop_r(code, opts->gen.scratch2);
170 mov_rdisp8r(code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch2, SZ_W); 170 mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch2, SZ_W);
171 } 171 }
172 } 172 }
173 ea->base = opts->gen.scratch1; 173 ea->base = opts->gen.scratch1;
174 break; 174 break;
175 case Z80_IMMED: 175 case Z80_IMMED:
176 ea->mode = MODE_IMMED; 176 ea->mode = MODE_IMMED;
177 ea->disp = inst->immed; 177 ea->disp = inst->immed;
178 break; 178 break;
179 case Z80_IMMED_INDIRECT: 179 case Z80_IMMED_INDIRECT:
180 dst = mov_ir(dst, inst->immed, areg, SZ_W); 180 mov_ir(code, inst->immed, areg, SZ_W);
181 size = z80_size(inst); 181 size = z80_size(inst);
182 if (read) { 182 if (read) {
183 /*if (modify) { 183 /*if (modify) {
184 dst = push_r(dst, opts->gen.scratch1); 184 push_r(code, opts->gen.scratch1);
185 }*/ 185 }*/
186 if (size == SZ_B) { 186 if (size == SZ_B) {
187 dst = call(dst, (uint8_t *)z80_read_byte); 187 call(code, (uint8_t *)z80_read_byte);
188 } else { 188 } else {
189 dst = call(dst, (uint8_t *)z80_read_word); 189 call(code, (uint8_t *)z80_read_word);
190 } 190 }
191 if (modify) { 191 if (modify) {
192 //dst = pop_r(dst, opts->gen.scratch2); 192 //pop_r(code, opts->gen.scratch2);
193 dst = mov_ir(dst, inst->immed, opts->gen.scratch2, SZ_W); 193 mov_ir(code, inst->immed, opts->gen.scratch2, SZ_W);
194 } 194 }
195 } 195 }
196 ea->base = opts->gen.scratch1; 196 ea->base = opts->gen.scratch1;
197 break; 197 break;
198 case Z80_IX_DISPLACE: 198 case Z80_IX_DISPLACE:
199 case Z80_IY_DISPLACE: 199 case Z80_IY_DISPLACE:
200 reg = opts->regs[(inst->addr_mode & 0x1F) == Z80_IX_DISPLACE ? Z80_IX : Z80_IY]; 200 reg = opts->regs[(inst->addr_mode & 0x1F) == Z80_IX_DISPLACE ? Z80_IX : Z80_IY];
201 dst = mov_rr(dst, reg, areg, SZ_W); 201 mov_rr(code, reg, areg, SZ_W);
202 dst = add_ir(dst, inst->ea_reg & 0x80 ? inst->ea_reg - 256 : inst->ea_reg, areg, SZ_W); 202 add_ir(code, inst->ea_reg & 0x80 ? inst->ea_reg - 256 : inst->ea_reg, areg, SZ_W);
203 size = z80_size(inst); 203 size = z80_size(inst);
204 if (read) { 204 if (read) {
205 if (modify) { 205 if (modify) {
206 //dst = push_r(dst, opts->gen.scratch1); 206 //push_r(code, opts->gen.scratch1);
207 dst = mov_rrdisp8(dst, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_W); 207 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_W);
208 } 208 }
209 if (size == SZ_B) { 209 if (size == SZ_B) {
210 dst = call(dst, (uint8_t *)z80_read_byte); 210 call(code, (uint8_t *)z80_read_byte);
211 } else { 211 } else {
212 dst = call(dst, (uint8_t *)z80_read_word); 212 call(code, (uint8_t *)z80_read_word);
213 } 213 }
214 if (modify) { 214 if (modify) {
215 //dst = pop_r(dst, opts->gen.scratch2); 215 //pop_r(code, opts->gen.scratch2);
216 dst = mov_rdisp8r(dst, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch2, SZ_W); 216 mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch2, SZ_W);
217 } 217 }
218 } 218 }
219 ea->base = opts->gen.scratch1; 219 ea->base = opts->gen.scratch1;
220 break; 220 break;
221 case Z80_UNUSED: 221 case Z80_UNUSED:
223 break; 223 break;
224 default: 224 default:
225 fprintf(stderr, "Unrecognized Z80 addressing mode %d\n", inst->addr_mode & 0x1F); 225 fprintf(stderr, "Unrecognized Z80 addressing mode %d\n", inst->addr_mode & 0x1F);
226 exit(1); 226 exit(1);
227 } 227 }
228 return dst; 228 }
229 } 229
230 230 void z80_save_ea(code_info *code, z80inst * inst, z80_options * opts)
231 uint8_t * z80_save_ea(uint8_t * dst, z80inst * inst, z80_options * opts)
232 { 231 {
233 if ((inst->addr_mode & 0x1F) == Z80_REG) { 232 if ((inst->addr_mode & 0x1F) == Z80_REG) {
234 if (inst->ea_reg == Z80_IYH) { 233 if (inst->ea_reg == Z80_IYH) {
235 if (inst->reg == Z80_IYL) { 234 if (inst->reg == Z80_IYL) {
236 dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W); 235 ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
237 dst = mov_rr(dst, opts->gen.scratch1, opts->regs[Z80_IYL], SZ_B); 236 mov_rr(code, opts->gen.scratch1, opts->regs[Z80_IYL], SZ_B);
238 dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W); 237 ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
239 } else { 238 } else {
240 dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W); 239 ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
241 } 240 }
242 } else if (inst->reg != Z80_UNUSED && inst->reg != Z80_USE_IMMED && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) { 241 } else if (inst->reg != Z80_UNUSED && inst->reg != Z80_USE_IMMED && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) {
243 uint8_t other_reg = opts->regs[inst->reg]; 242 uint8_t other_reg = opts->regs[inst->reg];
244 if (other_reg >= R8 || (other_reg >= RSP && other_reg <= RDI)) { 243 if (other_reg >= R8 || (other_reg >= RSP && other_reg <= RDI)) {
245 //we can't mix an *H reg with a register that requires the REX prefix 244 //we can't mix an *H reg with a register that requires the REX prefix
246 dst = ror_ir(dst, 8, opts->regs[z80_low_reg(inst->ea_reg)], SZ_W); 245 ror_ir(code, 8, opts->regs[z80_low_reg(inst->ea_reg)], SZ_W);
247 } 246 }
248 } 247 }
249 } 248 }
250 return dst; 249 }
251 } 250
252 251 void z80_save_result(code_info *code, z80inst * inst)
253 uint8_t * z80_save_result(uint8_t * dst, z80inst * inst)
254 { 252 {
255 switch(inst->addr_mode & 0x1f) 253 switch(inst->addr_mode & 0x1f)
256 { 254 {
257 case Z80_REG_INDIRECT: 255 case Z80_REG_INDIRECT:
258 case Z80_IMMED_INDIRECT: 256 case Z80_IMMED_INDIRECT:
259 case Z80_IX_DISPLACE: 257 case Z80_IX_DISPLACE:
260 case Z80_IY_DISPLACE: 258 case Z80_IY_DISPLACE:
261 if (z80_size(inst) == SZ_B) { 259 if (z80_size(inst) == SZ_B) {
262 dst = call(dst, (uint8_t *)z80_write_byte); 260 call(code, (uint8_t *)z80_write_byte);
263 } else { 261 } else {
264 dst = call(dst, (uint8_t *)z80_write_word_lowfirst); 262 call(code, (uint8_t *)z80_write_word_lowfirst);
265 } 263 }
266 } 264 }
267 return dst;
268 } 265 }
269 266
270 enum { 267 enum {
271 DONT_READ=0, 268 DONT_READ=0,
272 READ 269 READ
309 (context->alt_regs[Z80_IXH] << 8) | context->alt_regs[Z80_IXL], 306 (context->alt_regs[Z80_IXH] << 8) | context->alt_regs[Z80_IXL],
310 (context->alt_regs[Z80_IYH] << 8) | context->alt_regs[Z80_IYL]); 307 (context->alt_regs[Z80_IYH] << 8) | context->alt_regs[Z80_IYL]);
311 exit(0); 308 exit(0);
312 } 309 }
313 310
314 uint8_t * translate_z80inst(z80inst * inst, z80_context * context, uint16_t address) 311 void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address)
315 { 312 {
316 uint32_t cycles; 313 uint32_t num_cycles;
317 x86_ea src_op, dst_op; 314 host_ea src_op, dst_op;
318 uint8_t size; 315 uint8_t size;
319 z80_options *opts = context->options; 316 z80_options *opts = context->options;
320 uint8_t * start = opts->code.cur; 317 uint8_t * start = opts->gen.code.cur;
318 code_info *code = &opts->gen.code;
321 check_cycles_int(&opts->gen, address); 319 check_cycles_int(&opts->gen, address);
322 switch(inst->op) 320 switch(inst->op)
323 { 321 {
324 case Z80_LD: 322 case Z80_LD:
325 size = z80_size(inst); 323 size = z80_size(inst);
326 switch (inst->addr_mode & 0x1F) 324 switch (inst->addr_mode & 0x1F)
327 { 325 {
328 case Z80_REG: 326 case Z80_REG:
329 case Z80_REG_INDIRECT: 327 case Z80_REG_INDIRECT:
330 cycles = size == SZ_B ? 4 : 6; 328 num_cycles = size == SZ_B ? 4 : 6;
331 if (inst->ea_reg == Z80_IX || inst->ea_reg == Z80_IY) { 329 if (inst->ea_reg == Z80_IX || inst->ea_reg == Z80_IY) {
332 cycles += 4; 330 num_cycles += 4;
333 } 331 }
334 if (inst->reg == Z80_I || inst->ea_reg == Z80_I) { 332 if (inst->reg == Z80_I || inst->ea_reg == Z80_I) {
335 cycles += 5; 333 num_cycles += 5;
336 } 334 }
337 break; 335 break;
338 case Z80_IMMED: 336 case Z80_IMMED:
339 cycles = size == SZ_B ? 7 : 10; 337 num_cycles = size == SZ_B ? 7 : 10;
340 break; 338 break;
341 case Z80_IMMED_INDIRECT: 339 case Z80_IMMED_INDIRECT:
342 cycles = 10; 340 num_cycles = 10;
343 break; 341 break;
344 case Z80_IX_DISPLACE: 342 case Z80_IX_DISPLACE:
345 case Z80_IY_DISPLACE: 343 case Z80_IY_DISPLACE:
346 cycles = 16; 344 num_cycles = 16;
347 break; 345 break;
348 } 346 }
349 if ((inst->reg >= Z80_IXL && inst->reg <= Z80_IYH) || inst->reg == Z80_IX || inst->reg == Z80_IY) { 347 if ((inst->reg >= Z80_IXL && inst->reg <= Z80_IYH) || inst->reg == Z80_IX || inst->reg == Z80_IY) {
350 cycles += 4; 348 num_cycles += 4;
351 } 349 }
352 dst = cycles(&opts->gen, cycles); 350 cycles(&opts->gen, num_cycles);
353 if (inst->addr_mode & Z80_DIR) { 351 if (inst->addr_mode & Z80_DIR) {
354 dst = translate_z80_ea(inst, &dst_op, dst, opts, DONT_READ, MODIFY); 352 translate_z80_ea(inst, &dst_op, opts, DONT_READ, MODIFY);
355 dst = translate_z80_reg(inst, &src_op, dst, opts); 353 translate_z80_reg(inst, &src_op, opts);
356 } else { 354 } else {
357 dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); 355 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
358 dst = translate_z80_reg(inst, &dst_op, dst, opts); 356 translate_z80_reg(inst, &dst_op, opts);
359 } 357 }
360 if (src_op.mode == MODE_REG_DIRECT) { 358 if (src_op.mode == MODE_REG_DIRECT) {
361 if(dst_op.mode == MODE_REG_DISPLACE8) { 359 if(dst_op.mode == MODE_REG_DISPLACE8) {
362 dst = mov_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, size); 360 mov_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, size);
363 } else { 361 } else {
364 dst = mov_rr(dst, src_op.base, dst_op.base, size); 362 mov_rr(code, src_op.base, dst_op.base, size);
365 } 363 }
366 } else if(src_op.mode == MODE_IMMED) { 364 } else if(src_op.mode == MODE_IMMED) {
367 dst = mov_ir(dst, src_op.disp, dst_op.base, size); 365 mov_ir(code, src_op.disp, dst_op.base, size);
368 } else { 366 } else {
369 dst = mov_rdisp8r(dst, src_op.base, src_op.disp, dst_op.base, size); 367 mov_rdispr(code, src_op.base, src_op.disp, dst_op.base, size);
370 } 368 }
371 dst = z80_save_reg(dst, inst, opts); 369 z80_save_reg(inst, opts);
372 dst = z80_save_ea(dst, inst, opts); 370 z80_save_ea(code, inst, opts);
373 if (inst->addr_mode & Z80_DIR) { 371 if (inst->addr_mode & Z80_DIR) {
374 dst = z80_save_result(dst, inst); 372 z80_save_result(code, inst);
375 } 373 }
376 break; 374 break;
377 case Z80_PUSH: 375 case Z80_PUSH:
378 dst = cycles(&opts->gen, (inst->reg == Z80_IX || inst->reg == Z80_IY) ? 9 : 5); 376 cycles(&opts->gen, (inst->reg == Z80_IX || inst->reg == Z80_IY) ? 9 : 5);
379 dst = sub_ir(dst, 2, opts->regs[Z80_SP], SZ_W); 377 sub_ir(code, 2, opts->regs[Z80_SP], SZ_W);
380 if (inst->reg == Z80_AF) { 378 if (inst->reg == Z80_AF) {
381 dst = mov_rr(dst, opts->regs[Z80_A], opts->gen.scratch1, SZ_B); 379 mov_rr(code, opts->regs[Z80_A], opts->gen.scratch1, SZ_B);
382 dst = shl_ir(dst, 8, opts->gen.scratch1, SZ_W); 380 shl_ir(code, 8, opts->gen.scratch1, SZ_W);
383 dst = mov_rdisp8r(dst, opts->gen.context_reg, zf_off(ZF_S), opts->gen.scratch1, SZ_B); 381 mov_rdispr(code, opts->gen.context_reg, zf_off(ZF_S), opts->gen.scratch1, SZ_B);
384 dst = shl_ir(dst, 1, opts->gen.scratch1, SZ_B); 382 shl_ir(code, 1, opts->gen.scratch1, SZ_B);
385 dst = or_rdisp8r(dst, opts->gen.context_reg, zf_off(ZF_Z), opts->gen.scratch1, SZ_B); 383 or_rdispr(code, opts->gen.context_reg, zf_off(ZF_Z), opts->gen.scratch1, SZ_B);
386 dst = shl_ir(dst, 2, opts->gen.scratch1, SZ_B); 384 shl_ir(code, 2, opts->gen.scratch1, SZ_B);
387 dst = or_rdisp8r(dst, opts->gen.context_reg, zf_off(ZF_H), opts->gen.scratch1, SZ_B); 385 or_rdispr(code, opts->gen.context_reg, zf_off(ZF_H), opts->gen.scratch1, SZ_B);
388 dst = shl_ir(dst, 2, opts->gen.scratch1, SZ_B); 386 shl_ir(code, 2, opts->gen.scratch1, SZ_B);
389 dst = or_rdisp8r(dst, opts->gen.context_reg, zf_off(ZF_PV), opts->gen.scratch1, SZ_B); 387 or_rdispr(code, opts->gen.context_reg, zf_off(ZF_PV), opts->gen.scratch1, SZ_B);
390 dst = shl_ir(dst, 1, opts->gen.scratch1, SZ_B); 388 shl_ir(code, 1, opts->gen.scratch1, SZ_B);
391 dst = or_rdisp8r(dst, opts->gen.context_reg, zf_off(ZF_N), opts->gen.scratch1, SZ_B); 389 or_rdispr(code, opts->gen.context_reg, zf_off(ZF_N), opts->gen.scratch1, SZ_B);
392 dst = shl_ir(dst, 1, opts->gen.scratch1, SZ_B); 390 shl_ir(code, 1, opts->gen.scratch1, SZ_B);
393 dst = or_rdisp8r(dst, opts->gen.context_reg, zf_off(ZF_C), opts->gen.scratch1, SZ_B); 391 or_rdispr(code, opts->gen.context_reg, zf_off(ZF_C), opts->gen.scratch1, SZ_B);
394 } else { 392 } else {
395 dst = translate_z80_reg(inst, &src_op, dst, opts); 393 translate_z80_reg(inst, &src_op, opts);
396 dst = mov_rr(dst, src_op.base, opts->gen.scratch1, SZ_W); 394 mov_rr(code, src_op.base, opts->gen.scratch1, SZ_W);
397 } 395 }
398 dst = mov_rr(dst, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); 396 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
399 dst = call(dst, (uint8_t *)z80_write_word_highfirst); 397 call(code, (uint8_t *)z80_write_word_highfirst);
400 //no call to save_z80_reg needed since there's no chance we'll use the only 398 //no call to save_z80_reg needed since there's no chance we'll use the only
401 //the upper half of a register pair 399 //the upper half of a register pair
402 break; 400 break;
403 case Z80_POP: 401 case Z80_POP:
404 dst = cycles(&opts->gen, (inst->reg == Z80_IX || inst->reg == Z80_IY) ? 8 : 4); 402 cycles(&opts->gen, (inst->reg == Z80_IX || inst->reg == Z80_IY) ? 8 : 4);
405 dst = mov_rr(dst, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); 403 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
406 dst = call(dst, (uint8_t *)z80_read_word); 404 call(code, (uint8_t *)z80_read_word);
407 dst = add_ir(dst, 2, opts->regs[Z80_SP], SZ_W); 405 add_ir(code, 2, opts->regs[Z80_SP], SZ_W);
408 if (inst->reg == Z80_AF) { 406 if (inst->reg == Z80_AF) {
409 407
410 dst = bt_ir(dst, 0, opts->gen.scratch1, SZ_W); 408 bt_ir(code, 0, opts->gen.scratch1, SZ_W);
411 dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); 409 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
412 dst = bt_ir(dst, 1, opts->gen.scratch1, SZ_W); 410 bt_ir(code, 1, opts->gen.scratch1, SZ_W);
413 dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_N)); 411 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_N));
414 dst = bt_ir(dst, 2, opts->gen.scratch1, SZ_W); 412 bt_ir(code, 2, opts->gen.scratch1, SZ_W);
415 dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_PV)); 413 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_PV));
416 dst = bt_ir(dst, 4, opts->gen.scratch1, SZ_W); 414 bt_ir(code, 4, opts->gen.scratch1, SZ_W);
417 dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_H)); 415 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
418 dst = bt_ir(dst, 6, opts->gen.scratch1, SZ_W); 416 bt_ir(code, 6, opts->gen.scratch1, SZ_W);
419 dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_Z)); 417 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_Z));
420 dst = bt_ir(dst, 7, opts->gen.scratch1, SZ_W); 418 bt_ir(code, 7, opts->gen.scratch1, SZ_W);
421 dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_S)); 419 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_S));
422 dst = shr_ir(dst, 8, opts->gen.scratch1, SZ_W); 420 shr_ir(code, 8, opts->gen.scratch1, SZ_W);
423 dst = mov_rr(dst, opts->gen.scratch1, opts->regs[Z80_A], SZ_B); 421 mov_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B);
424 } else { 422 } else {
425 dst = translate_z80_reg(inst, &src_op, dst, opts); 423 translate_z80_reg(inst, &src_op, opts);
426 dst = mov_rr(dst, opts->gen.scratch1, src_op.base, SZ_W); 424 mov_rr(code, opts->gen.scratch1, src_op.base, SZ_W);
427 } 425 }
428 //no call to save_z80_reg needed since there's no chance we'll use the only 426 //no call to save_z80_reg needed since there's no chance we'll use the only
429 //the upper half of a register pair 427 //the upper half of a register pair
430 break; 428 break;
431 case Z80_EX: 429 case Z80_EX:
432 if (inst->addr_mode == Z80_REG || inst->reg == Z80_HL) { 430 if (inst->addr_mode == Z80_REG || inst->reg == Z80_HL) {
433 cycles = 4; 431 num_cycles = 4;
434 } else { 432 } else {
435 cycles = 8; 433 num_cycles = 8;
436 } 434 }
437 dst = cycles(&opts->gen, cycles); 435 cycles(&opts->gen, num_cycles);
438 if (inst->addr_mode == Z80_REG) { 436 if (inst->addr_mode == Z80_REG) {
439 if(inst->reg == Z80_AF) { 437 if(inst->reg == Z80_AF) {
440 dst = mov_rr(dst, opts->regs[Z80_A], opts->gen.scratch1, SZ_B); 438 mov_rr(code, opts->regs[Z80_A], opts->gen.scratch1, SZ_B);
441 dst = mov_rdisp8r(dst, opts->gen.context_reg, zar_off(Z80_A), opts->regs[Z80_A], SZ_B); 439 mov_rdispr(code, opts->gen.context_reg, zar_off(Z80_A), opts->regs[Z80_A], SZ_B);
442 dst = mov_rrdisp8(dst, opts->gen.scratch1, opts->gen.context_reg, zar_off(Z80_A), SZ_B); 440 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zar_off(Z80_A), SZ_B);
443 441
444 //Flags are currently word aligned, so we can move 442 //Flags are currently word aligned, so we can move
445 //them efficiently a word at a time 443 //them efficiently a word at a time
446 for (int f = ZF_C; f < ZF_NUM; f+=2) { 444 for (int f = ZF_C; f < ZF_NUM; f+=2) {
447 dst = mov_rdisp8r(dst, opts->gen.context_reg, zf_off(f), opts->gen.scratch1, SZ_W); 445 mov_rdispr(code, opts->gen.context_reg, zf_off(f), opts->gen.scratch1, SZ_W);
448 dst = mov_rdisp8r(dst, opts->gen.context_reg, zaf_off(f), opts->gen.scratch2, SZ_W); 446 mov_rdispr(code, opts->gen.context_reg, zaf_off(f), opts->gen.scratch2, SZ_W);
449 dst = mov_rrdisp8(dst, opts->gen.scratch1, opts->gen.context_reg, zaf_off(f), SZ_W); 447 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zaf_off(f), SZ_W);
450 dst = mov_rrdisp8(dst, opts->gen.scratch2, opts->gen.context_reg, zf_off(f), SZ_W); 448 mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(f), SZ_W);
451 } 449 }
452 } else { 450 } else {
453 dst = xchg_rr(dst, opts->regs[Z80_DE], opts->regs[Z80_HL], SZ_W); 451 xchg_rr(code, opts->regs[Z80_DE], opts->regs[Z80_HL], SZ_W);
454 } 452 }
455 } else { 453 } else {
456 dst = mov_rr(dst, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); 454 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
457 dst = call(dst, (uint8_t *)z80_read_byte); 455 call(code, (uint8_t *)z80_read_byte);
458 dst = xchg_rr(dst, opts->regs[inst->reg], opts->gen.scratch1, SZ_B); 456 xchg_rr(code, opts->regs[inst->reg], opts->gen.scratch1, SZ_B);
459 dst = mov_rr(dst, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); 457 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
460 dst = call(dst, (uint8_t *)z80_write_byte); 458 call(code, (uint8_t *)z80_write_byte);
461 dst = cycles(&opts->gen, 1); 459 cycles(&opts->gen, 1);
462 uint8_t high_reg = z80_high_reg(inst->reg); 460 uint8_t high_reg = z80_high_reg(inst->reg);
463 uint8_t use_reg; 461 uint8_t use_reg;
464 //even though some of the upper halves can be used directly 462 //even though some of the upper halves can be used directly
465 //the limitations on mixing *H regs with the REX prefix 463 //the limitations on mixing *H regs with the REX prefix
466 //prevent us from taking advantage of it 464 //prevent us from taking advantage of it
467 use_reg = opts->regs[inst->reg]; 465 use_reg = opts->regs[inst->reg];
468 dst = ror_ir(dst, 8, use_reg, SZ_W); 466 ror_ir(code, 8, use_reg, SZ_W);
469 dst = mov_rr(dst, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); 467 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
470 dst = add_ir(dst, 1, opts->gen.scratch1, SZ_W); 468 add_ir(code, 1, opts->gen.scratch1, SZ_W);
471 dst = call(dst, (uint8_t *)z80_read_byte); 469 call(code, (uint8_t *)z80_read_byte);
472 dst = xchg_rr(dst, use_reg, opts->gen.scratch1, SZ_B); 470 xchg_rr(code, use_reg, opts->gen.scratch1, SZ_B);
473 dst = mov_rr(dst, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); 471 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
474 dst = add_ir(dst, 1, opts->gen.scratch2, SZ_W); 472 add_ir(code, 1, opts->gen.scratch2, SZ_W);
475 dst = call(dst, (uint8_t *)z80_write_byte); 473 call(code, (uint8_t *)z80_write_byte);
476 //restore reg to normal rotation 474 //restore reg to normal rotation
477 dst = ror_ir(dst, 8, use_reg, SZ_W); 475 ror_ir(code, 8, use_reg, SZ_W);
478 dst = cycles(&opts->gen, 2); 476 cycles(&opts->gen, 2);
479 } 477 }
480 break; 478 break;
481 case Z80_EXX: 479 case Z80_EXX:
482 dst = cycles(&opts->gen, 4); 480 cycles(&opts->gen, 4);
483 dst = mov_rr(dst, opts->regs[Z80_BC], opts->gen.scratch1, SZ_W); 481 mov_rr(code, opts->regs[Z80_BC], opts->gen.scratch1, SZ_W);
484 dst = mov_rr(dst, opts->regs[Z80_HL], opts->gen.scratch2, SZ_W); 482 mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch2, SZ_W);
485 dst = mov_rdisp8r(dst, opts->gen.context_reg, zar_off(Z80_C), opts->regs[Z80_BC], SZ_W); 483 mov_rdispr(code, opts->gen.context_reg, zar_off(Z80_C), opts->regs[Z80_BC], SZ_W);
486 dst = mov_rdisp8r(dst, opts->gen.context_reg, zar_off(Z80_L), opts->regs[Z80_HL], SZ_W); 484 mov_rdispr(code, opts->gen.context_reg, zar_off(Z80_L), opts->regs[Z80_HL], SZ_W);
487 dst = mov_rrdisp8(dst, opts->gen.scratch1, opts->gen.context_reg, zar_off(Z80_C), SZ_W); 485 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zar_off(Z80_C), SZ_W);
488 dst = mov_rrdisp8(dst, opts->gen.scratch2, opts->gen.context_reg, zar_off(Z80_L), SZ_W); 486 mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zar_off(Z80_L), SZ_W);
489 dst = mov_rr(dst, opts->regs[Z80_DE], opts->gen.scratch1, SZ_W); 487 mov_rr(code, opts->regs[Z80_DE], opts->gen.scratch1, SZ_W);
490 dst = mov_rdisp8r(dst, opts->gen.context_reg, zar_off(Z80_E), opts->regs[Z80_DE], SZ_W); 488 mov_rdispr(code, opts->gen.context_reg, zar_off(Z80_E), opts->regs[Z80_DE], SZ_W);
491 dst = mov_rrdisp8(dst, opts->gen.scratch1, opts->gen.context_reg, zar_off(Z80_E), SZ_W); 489 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zar_off(Z80_E), SZ_W);
492 break; 490 break;
493 case Z80_LDI: { 491 case Z80_LDI: {
494 dst = cycles(&opts->gen, 8); 492 cycles(&opts->gen, 8);
495 dst = mov_rr(dst, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W); 493 mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W);
496 dst = call(dst, (uint8_t *)z80_read_byte); 494 call(code, (uint8_t *)z80_read_byte);
497 dst = mov_rr(dst, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W); 495 mov_rr(code, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W);
498 dst = call(dst, (uint8_t *)z80_write_byte); 496 call(code, (uint8_t *)z80_write_byte);
499 dst = cycles(&opts->gen, 2); 497 cycles(&opts->gen, 2);
500 dst = add_ir(dst, 1, opts->regs[Z80_DE], SZ_W); 498 add_ir(code, 1, opts->regs[Z80_DE], SZ_W);
501 dst = add_ir(dst, 1, opts->regs[Z80_HL], SZ_W); 499 add_ir(code, 1, opts->regs[Z80_HL], SZ_W);
502 dst = sub_ir(dst, 1, opts->regs[Z80_BC], SZ_W); 500 sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
503 //TODO: Implement half-carry 501 //TODO: Implement half-carry
504 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 502 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
505 dst = setcc_rdisp8(dst, CC_NZ, opts->gen.context_reg, zf_off(ZF_PV)); 503 setcc_rdisp(code, CC_NZ, opts->gen.context_reg, zf_off(ZF_PV));
506 break; 504 break;
507 } 505 }
508 case Z80_LDIR: { 506 case Z80_LDIR: {
509 dst = cycles(&opts->gen, 8); 507 cycles(&opts->gen, 8);
510 dst = mov_rr(dst, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W); 508 mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W);
511 dst = call(dst, (uint8_t *)z80_read_byte); 509 call(code, (uint8_t *)z80_read_byte);
512 dst = mov_rr(dst, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W); 510 mov_rr(code, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W);
513 dst = call(dst, (uint8_t *)z80_write_byte); 511 call(code, (uint8_t *)z80_write_byte);
514 dst = add_ir(dst, 1, opts->regs[Z80_DE], SZ_W); 512 add_ir(code, 1, opts->regs[Z80_DE], SZ_W);
515 dst = add_ir(dst, 1, opts->regs[Z80_HL], SZ_W); 513 add_ir(code, 1, opts->regs[Z80_HL], SZ_W);
516 514
517 dst = sub_ir(dst, 1, opts->regs[Z80_BC], SZ_W); 515 sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
518 uint8_t * cont = dst+1; 516 uint8_t * cont = code->cur+1;
519 dst = jcc(dst, CC_Z, dst+2); 517 jcc(code, CC_Z, code->cur+2);
520 dst = cycles(&opts->gen, 7); 518 cycles(&opts->gen, 7);
521 //TODO: Figure out what the flag state should be here 519 //TODO: Figure out what the flag state should be here
522 //TODO: Figure out whether an interrupt can interrupt this 520 //TODO: Figure out whether an interrupt can interrupt this
523 dst = jmp(dst, start); 521 jmp(code, start);
524 *cont = dst - (cont + 1); 522 *cont = code->cur - (cont + 1);
525 dst = cycles(&opts->gen, 2); 523 cycles(&opts->gen, 2);
526 //TODO: Implement half-carry 524 //TODO: Implement half-carry
527 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 525 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
528 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B); 526 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
529 break; 527 break;
530 } 528 }
531 case Z80_LDD: { 529 case Z80_LDD: {
532 dst = cycles(&opts->gen, 8); 530 cycles(&opts->gen, 8);
533 dst = mov_rr(dst, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W); 531 mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W);
534 dst = call(dst, (uint8_t *)z80_read_byte); 532 call(code, (uint8_t *)z80_read_byte);
535 dst = mov_rr(dst, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W); 533 mov_rr(code, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W);
536 dst = call(dst, (uint8_t *)z80_write_byte); 534 call(code, (uint8_t *)z80_write_byte);
537 dst = cycles(&opts->gen, 2); 535 cycles(&opts->gen, 2);
538 dst = sub_ir(dst, 1, opts->regs[Z80_DE], SZ_W); 536 sub_ir(code, 1, opts->regs[Z80_DE], SZ_W);
539 dst = sub_ir(dst, 1, opts->regs[Z80_HL], SZ_W); 537 sub_ir(code, 1, opts->regs[Z80_HL], SZ_W);
540 dst = sub_ir(dst, 1, opts->regs[Z80_BC], SZ_W); 538 sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
541 //TODO: Implement half-carry 539 //TODO: Implement half-carry
542 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 540 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
543 dst = setcc_rdisp8(dst, CC_NZ, opts->gen.context_reg, zf_off(ZF_PV)); 541 setcc_rdisp(code, CC_NZ, opts->gen.context_reg, zf_off(ZF_PV));
544 break; 542 break;
545 } 543 }
546 case Z80_LDDR: { 544 case Z80_LDDR: {
547 dst = cycles(&opts->gen, 8); 545 cycles(&opts->gen, 8);
548 dst = mov_rr(dst, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W); 546 mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W);
549 dst = call(dst, (uint8_t *)z80_read_byte); 547 call(code, (uint8_t *)z80_read_byte);
550 dst = mov_rr(dst, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W); 548 mov_rr(code, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W);
551 dst = call(dst, (uint8_t *)z80_write_byte); 549 call(code, (uint8_t *)z80_write_byte);
552 dst = sub_ir(dst, 1, opts->regs[Z80_DE], SZ_W); 550 sub_ir(code, 1, opts->regs[Z80_DE], SZ_W);
553 dst = sub_ir(dst, 1, opts->regs[Z80_HL], SZ_W); 551 sub_ir(code, 1, opts->regs[Z80_HL], SZ_W);
554 552
555 dst = sub_ir(dst, 1, opts->regs[Z80_BC], SZ_W); 553 sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
556 uint8_t * cont = dst+1; 554 uint8_t * cont = code->cur+1;
557 dst = jcc(dst, CC_Z, dst+2); 555 jcc(code, CC_Z, code->cur+2);
558 dst = cycles(&opts->gen, 7); 556 cycles(&opts->gen, 7);
559 //TODO: Figure out what the flag state should be here 557 //TODO: Figure out what the flag state should be here
560 //TODO: Figure out whether an interrupt can interrupt this 558 //TODO: Figure out whether an interrupt can interrupt this
561 dst = jmp(dst, start); 559 jmp(code, start);
562 *cont = dst - (cont + 1); 560 *cont = code->cur - (cont + 1);
563 dst = cycles(&opts->gen, 2); 561 cycles(&opts->gen, 2);
564 //TODO: Implement half-carry 562 //TODO: Implement half-carry
565 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 563 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
566 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B); 564 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
567 break; 565 break;
568 } 566 }
569 /*case Z80_CPI: 567 /*case Z80_CPI:
570 case Z80_CPIR: 568 case Z80_CPIR:
571 case Z80_CPD: 569 case Z80_CPD:
572 case Z80_CPDR: 570 case Z80_CPDR:
573 break;*/ 571 break;*/
574 case Z80_ADD: 572 case Z80_ADD:
575 cycles = 4; 573 num_cycles = 4;
576 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { 574 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
577 cycles += 12; 575 num_cycles += 12;
578 } else if(inst->addr_mode == Z80_IMMED) { 576 } else if(inst->addr_mode == Z80_IMMED) {
579 cycles += 3; 577 num_cycles += 3;
580 } else if(z80_size(inst) == SZ_W) { 578 } else if(z80_size(inst) == SZ_W) {
581 cycles += 4; 579 num_cycles += 4;
582 } 580 }
583 dst = cycles(&opts->gen, cycles); 581 cycles(&opts->gen, num_cycles);
584 dst = translate_z80_reg(inst, &dst_op, dst, opts); 582 translate_z80_reg(inst, &dst_op, opts);
585 dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); 583 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
586 if (src_op.mode == MODE_REG_DIRECT) { 584 if (src_op.mode == MODE_REG_DIRECT) {
587 dst = add_rr(dst, src_op.base, dst_op.base, z80_size(inst)); 585 add_rr(code, src_op.base, dst_op.base, z80_size(inst));
588 } else { 586 } else {
589 dst = add_ir(dst, src_op.disp, dst_op.base, z80_size(inst)); 587 add_ir(code, src_op.disp, dst_op.base, z80_size(inst));
590 } 588 }
591 dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); 589 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
592 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 590 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
593 //TODO: Implement half-carry flag 591 //TODO: Implement half-carry flag
594 if (z80_size(inst) == SZ_B) { 592 if (z80_size(inst) == SZ_B) {
595 dst = setcc_rdisp8(dst, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); 593 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
596 dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 594 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
597 dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 595 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
598 } 596 }
599 dst = z80_save_reg(dst, inst, opts); 597 z80_save_reg(inst, opts);
600 dst = z80_save_ea(dst, inst, opts); 598 z80_save_ea(code, inst, opts);
601 break; 599 break;
602 case Z80_ADC: 600 case Z80_ADC:
603 cycles = 4; 601 num_cycles = 4;
604 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { 602 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
605 cycles += 12; 603 num_cycles += 12;
606 } else if(inst->addr_mode == Z80_IMMED) { 604 } else if(inst->addr_mode == Z80_IMMED) {
607 cycles += 3; 605 num_cycles += 3;
608 } else if(z80_size(inst) == SZ_W) { 606 } else if(z80_size(inst) == SZ_W) {
609 cycles += 4; 607 num_cycles += 4;
610 } 608 }
611 dst = cycles(&opts->gen, cycles); 609 cycles(&opts->gen, num_cycles);
612 dst = translate_z80_reg(inst, &dst_op, dst, opts); 610 translate_z80_reg(inst, &dst_op, opts);
613 dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); 611 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
614 dst = bt_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); 612 bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
615 if (src_op.mode == MODE_REG_DIRECT) { 613 if (src_op.mode == MODE_REG_DIRECT) {
616 dst = adc_rr(dst, src_op.base, dst_op.base, z80_size(inst)); 614 adc_rr(code, src_op.base, dst_op.base, z80_size(inst));
617 } else { 615 } else {
618 dst = adc_ir(dst, src_op.disp, dst_op.base, z80_size(inst)); 616 adc_ir(code, src_op.disp, dst_op.base, z80_size(inst));
619 } 617 }
620 dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); 618 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
621 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 619 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
622 //TODO: Implement half-carry flag 620 //TODO: Implement half-carry flag
623 dst = setcc_rdisp8(dst, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); 621 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
624 dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 622 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
625 dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 623 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
626 dst = z80_save_reg(dst, inst, opts); 624 z80_save_reg(inst, opts);
627 dst = z80_save_ea(dst, inst, opts); 625 z80_save_ea(code, inst, opts);
628 break; 626 break;
629 case Z80_SUB: 627 case Z80_SUB:
630 cycles = 4; 628 num_cycles = 4;
631 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { 629 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
632 cycles += 12; 630 num_cycles += 12;
633 } else if(inst->addr_mode == Z80_IMMED) { 631 } else if(inst->addr_mode == Z80_IMMED) {
634 cycles += 3; 632 num_cycles += 3;
635 } 633 }
636 dst = cycles(&opts->gen, cycles); 634 cycles(&opts->gen, num_cycles);
637 dst = translate_z80_reg(inst, &dst_op, dst, opts); 635 translate_z80_reg(inst, &dst_op, opts);
638 dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); 636 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
639 if (src_op.mode == MODE_REG_DIRECT) { 637 if (src_op.mode == MODE_REG_DIRECT) {
640 dst = sub_rr(dst, src_op.base, dst_op.base, z80_size(inst)); 638 sub_rr(code, src_op.base, dst_op.base, z80_size(inst));
641 } else { 639 } else {
642 dst = sub_ir(dst, src_op.disp, dst_op.base, z80_size(inst)); 640 sub_ir(code, src_op.disp, dst_op.base, z80_size(inst));
643 } 641 }
644 dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); 642 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
645 dst = mov_irdisp8(dst, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 643 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
646 dst = setcc_rdisp8(dst, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); 644 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
647 //TODO: Implement half-carry flag 645 //TODO: Implement half-carry flag
648 dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 646 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
649 dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 647 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
650 dst = z80_save_reg(dst, inst, opts); 648 z80_save_reg(inst, opts);
651 dst = z80_save_ea(dst, inst, opts); 649 z80_save_ea(code, inst, opts);
652 break; 650 break;
653 case Z80_SBC: 651 case Z80_SBC:
654 cycles = 4; 652 num_cycles = 4;
655 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { 653 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
656 cycles += 12; 654 num_cycles += 12;
657 } else if(inst->addr_mode == Z80_IMMED) { 655 } else if(inst->addr_mode == Z80_IMMED) {
658 cycles += 3; 656 num_cycles += 3;
659 } else if(z80_size(inst) == SZ_W) { 657 } else if(z80_size(inst) == SZ_W) {
660 cycles += 4; 658 num_cycles += 4;
661 } 659 }
662 dst = cycles(&opts->gen, cycles); 660 cycles(&opts->gen, num_cycles);
663 dst = translate_z80_reg(inst, &dst_op, dst, opts); 661 translate_z80_reg(inst, &dst_op, opts);
664 dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); 662 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
665 dst = bt_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); 663 bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
666 if (src_op.mode == MODE_REG_DIRECT) { 664 if (src_op.mode == MODE_REG_DIRECT) {
667 dst = sbb_rr(dst, src_op.base, dst_op.base, z80_size(inst)); 665 sbb_rr(code, src_op.base, dst_op.base, z80_size(inst));
668 } else { 666 } else {
669 dst = sbb_ir(dst, src_op.disp, dst_op.base, z80_size(inst)); 667 sbb_ir(code, src_op.disp, dst_op.base, z80_size(inst));
670 } 668 }
671 dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); 669 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
672 dst = mov_irdisp8(dst, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 670 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
673 //TODO: Implement half-carry flag 671 //TODO: Implement half-carry flag
674 dst = setcc_rdisp8(dst, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); 672 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
675 dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 673 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
676 dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 674 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
677 dst = z80_save_reg(dst, inst, opts); 675 z80_save_reg(inst, opts);
678 dst = z80_save_ea(dst, inst, opts); 676 z80_save_ea(code, inst, opts);
679 break; 677 break;
680 case Z80_AND: 678 case Z80_AND:
681 cycles = 4; 679 num_cycles = 4;
682 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { 680 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
683 cycles += 12; 681 num_cycles += 12;
684 } else if(inst->addr_mode == Z80_IMMED) { 682 } else if(inst->addr_mode == Z80_IMMED) {
685 cycles += 3; 683 num_cycles += 3;
686 } else if(z80_size(inst) == SZ_W) { 684 } else if(z80_size(inst) == SZ_W) {
687 cycles += 4; 685 num_cycles += 4;
688 } 686 }
689 dst = cycles(&opts->gen, cycles); 687 cycles(&opts->gen, num_cycles);
690 dst = translate_z80_reg(inst, &dst_op, dst, opts); 688 translate_z80_reg(inst, &dst_op, opts);
691 dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); 689 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
692 if (src_op.mode == MODE_REG_DIRECT) { 690 if (src_op.mode == MODE_REG_DIRECT) {
693 dst = and_rr(dst, src_op.base, dst_op.base, z80_size(inst)); 691 and_rr(code, src_op.base, dst_op.base, z80_size(inst));
694 } else { 692 } else {
695 dst = and_ir(dst, src_op.disp, dst_op.base, z80_size(inst)); 693 and_ir(code, src_op.disp, dst_op.base, z80_size(inst));
696 } 694 }
697 //TODO: Cleanup flags 695 //TODO: Cleanup flags
698 dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); 696 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
699 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 697 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
700 //TODO: Implement half-carry flag 698 //TODO: Implement half-carry flag
701 if (z80_size(inst) == SZ_B) { 699 if (z80_size(inst) == SZ_B) {
702 dst = setcc_rdisp8(dst, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); 700 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
703 dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 701 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
704 dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 702 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
705 } 703 }
706 dst = z80_save_reg(dst, inst, opts); 704 z80_save_reg(inst, opts);
707 dst = z80_save_ea(dst, inst, opts); 705 z80_save_ea(code, inst, opts);
708 break; 706 break;
709 case Z80_OR: 707 case Z80_OR:
710 cycles = 4; 708 num_cycles = 4;
711 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { 709 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
712 cycles += 12; 710 num_cycles += 12;
713 } else if(inst->addr_mode == Z80_IMMED) { 711 } else if(inst->addr_mode == Z80_IMMED) {
714 cycles += 3; 712 num_cycles += 3;
715 } else if(z80_size(inst) == SZ_W) { 713 } else if(z80_size(inst) == SZ_W) {
716 cycles += 4; 714 num_cycles += 4;
717 } 715 }
718 dst = cycles(&opts->gen, cycles); 716 cycles(&opts->gen, num_cycles);
719 dst = translate_z80_reg(inst, &dst_op, dst, opts); 717 translate_z80_reg(inst, &dst_op, opts);
720 dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); 718 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
721 if (src_op.mode == MODE_REG_DIRECT) { 719 if (src_op.mode == MODE_REG_DIRECT) {
722 dst = or_rr(dst, src_op.base, dst_op.base, z80_size(inst)); 720 or_rr(code, src_op.base, dst_op.base, z80_size(inst));
723 } else { 721 } else {
724 dst = or_ir(dst, src_op.disp, dst_op.base, z80_size(inst)); 722 or_ir(code, src_op.disp, dst_op.base, z80_size(inst));
725 } 723 }
726 //TODO: Cleanup flags 724 //TODO: Cleanup flags
727 dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); 725 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
728 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 726 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
729 //TODO: Implement half-carry flag 727 //TODO: Implement half-carry flag
730 if (z80_size(inst) == SZ_B) { 728 if (z80_size(inst) == SZ_B) {
731 dst = setcc_rdisp8(dst, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); 729 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
732 dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 730 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
733 dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 731 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
734 } 732 }
735 dst = z80_save_reg(dst, inst, opts); 733 z80_save_reg(inst, opts);
736 dst = z80_save_ea(dst, inst, opts); 734 z80_save_ea(code, inst, opts);
737 break; 735 break;
738 case Z80_XOR: 736 case Z80_XOR:
739 cycles = 4; 737 num_cycles = 4;
740 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { 738 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
741 cycles += 12; 739 num_cycles += 12;
742 } else if(inst->addr_mode == Z80_IMMED) { 740 } else if(inst->addr_mode == Z80_IMMED) {
743 cycles += 3; 741 num_cycles += 3;
744 } else if(z80_size(inst) == SZ_W) { 742 } else if(z80_size(inst) == SZ_W) {
745 cycles += 4; 743 num_cycles += 4;
746 } 744 }
747 dst = cycles(&opts->gen, cycles); 745 cycles(&opts->gen, num_cycles);
748 dst = translate_z80_reg(inst, &dst_op, dst, opts); 746 translate_z80_reg(inst, &dst_op, opts);
749 dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); 747 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
750 if (src_op.mode == MODE_REG_DIRECT) { 748 if (src_op.mode == MODE_REG_DIRECT) {
751 dst = xor_rr(dst, src_op.base, dst_op.base, z80_size(inst)); 749 xor_rr(code, src_op.base, dst_op.base, z80_size(inst));
752 } else { 750 } else {
753 dst = xor_ir(dst, src_op.disp, dst_op.base, z80_size(inst)); 751 xor_ir(code, src_op.disp, dst_op.base, z80_size(inst));
754 } 752 }
755 //TODO: Cleanup flags 753 //TODO: Cleanup flags
756 dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); 754 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
757 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 755 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
758 //TODO: Implement half-carry flag 756 //TODO: Implement half-carry flag
759 if (z80_size(inst) == SZ_B) { 757 if (z80_size(inst) == SZ_B) {
760 dst = setcc_rdisp8(dst, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); 758 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
761 dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 759 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
762 dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 760 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
763 } 761 }
764 dst = z80_save_reg(dst, inst, opts); 762 z80_save_reg(inst, opts);
765 dst = z80_save_ea(dst, inst, opts); 763 z80_save_ea(code, inst, opts);
766 break; 764 break;
767 case Z80_CP: 765 case Z80_CP:
768 cycles = 4; 766 num_cycles = 4;
769 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { 767 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
770 cycles += 12; 768 num_cycles += 12;
771 } else if(inst->addr_mode == Z80_IMMED) { 769 } else if(inst->addr_mode == Z80_IMMED) {
772 cycles += 3; 770 num_cycles += 3;
773 } 771 }
774 dst = cycles(&opts->gen, cycles); 772 cycles(&opts->gen, num_cycles);
775 dst = translate_z80_reg(inst, &dst_op, dst, opts); 773 translate_z80_reg(inst, &dst_op, opts);
776 dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); 774 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
777 if (src_op.mode == MODE_REG_DIRECT) { 775 if (src_op.mode == MODE_REG_DIRECT) {
778 dst = cmp_rr(dst, src_op.base, dst_op.base, z80_size(inst)); 776 cmp_rr(code, src_op.base, dst_op.base, z80_size(inst));
779 } else { 777 } else {
780 dst = cmp_ir(dst, src_op.disp, dst_op.base, z80_size(inst)); 778 cmp_ir(code, src_op.disp, dst_op.base, z80_size(inst));
781 } 779 }
782 dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); 780 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
783 dst = mov_irdisp8(dst, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 781 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
784 dst = setcc_rdisp8(dst, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); 782 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
785 //TODO: Implement half-carry flag 783 //TODO: Implement half-carry flag
786 dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 784 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
787 dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 785 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
788 dst = z80_save_reg(dst, inst, opts); 786 z80_save_reg(inst, opts);
789 dst = z80_save_ea(dst, inst, opts); 787 z80_save_ea(code, inst, opts);
790 break; 788 break;
791 case Z80_INC: 789 case Z80_INC:
792 cycles = 4; 790 num_cycles = 4;
793 if (inst->reg == Z80_IX || inst->reg == Z80_IY) { 791 if (inst->reg == Z80_IX || inst->reg == Z80_IY) {
794 cycles += 6; 792 num_cycles += 6;
795 } else if(z80_size(inst) == SZ_W) { 793 } else if(z80_size(inst) == SZ_W) {
796 cycles += 2; 794 num_cycles += 2;
797 } else if(inst->reg == Z80_IXH || inst->reg == Z80_IXL || inst->reg == Z80_IYH || inst->reg == Z80_IYL || inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { 795 } else if(inst->reg == Z80_IXH || inst->reg == Z80_IXL || inst->reg == Z80_IYH || inst->reg == Z80_IYL || inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
798 cycles += 4; 796 num_cycles += 4;
799 } 797 }
800 dst = cycles(&opts->gen, cycles); 798 cycles(&opts->gen, num_cycles);
801 dst = translate_z80_reg(inst, &dst_op, dst, opts); 799 translate_z80_reg(inst, &dst_op, opts);
802 if (dst_op.mode == MODE_UNUSED) { 800 if (dst_op.mode == MODE_UNUSED) {
803 dst = translate_z80_ea(inst, &dst_op, dst, opts, READ, MODIFY); 801 translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
804 } 802 }
805 dst = add_ir(dst, 1, dst_op.base, z80_size(inst)); 803 add_ir(code, 1, dst_op.base, z80_size(inst));
806 if (z80_size(inst) == SZ_B) { 804 if (z80_size(inst) == SZ_B) {
807 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 805 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
808 //TODO: Implement half-carry flag 806 //TODO: Implement half-carry flag
809 dst = setcc_rdisp8(dst, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); 807 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
810 dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 808 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
811 dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 809 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
812 } 810 }
813 dst = z80_save_reg(dst, inst, opts); 811 z80_save_reg(inst, opts);
814 dst = z80_save_ea(dst, inst, opts); 812 z80_save_ea(code, inst, opts);
815 dst = z80_save_result(dst, inst); 813 z80_save_result(code, inst);
816 break; 814 break;
817 case Z80_DEC: 815 case Z80_DEC:
818 cycles = 4; 816 num_cycles = 4;
819 if (inst->reg == Z80_IX || inst->reg == Z80_IY) { 817 if (inst->reg == Z80_IX || inst->reg == Z80_IY) {
820 cycles += 6; 818 num_cycles += 6;
821 } else if(z80_size(inst) == SZ_W) { 819 } else if(z80_size(inst) == SZ_W) {
822 cycles += 2; 820 num_cycles += 2;
823 } else if(inst->reg == Z80_IXH || inst->reg == Z80_IXL || inst->reg == Z80_IYH || inst->reg == Z80_IYL || inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { 821 } else if(inst->reg == Z80_IXH || inst->reg == Z80_IXL || inst->reg == Z80_IYH || inst->reg == Z80_IYL || inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
824 cycles += 4; 822 num_cycles += 4;
825 } 823 }
826 dst = cycles(&opts->gen, cycles); 824 cycles(&opts->gen, num_cycles);
827 dst = translate_z80_reg(inst, &dst_op, dst, opts); 825 translate_z80_reg(inst, &dst_op, opts);
828 if (dst_op.mode == MODE_UNUSED) { 826 if (dst_op.mode == MODE_UNUSED) {
829 dst = translate_z80_ea(inst, &dst_op, dst, opts, READ, MODIFY); 827 translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
830 } 828 }
831 dst = sub_ir(dst, 1, dst_op.base, z80_size(inst)); 829 sub_ir(code, 1, dst_op.base, z80_size(inst));
832 if (z80_size(inst) == SZ_B) { 830 if (z80_size(inst) == SZ_B) {
833 dst = mov_irdisp8(dst, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 831 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
834 //TODO: Implement half-carry flag 832 //TODO: Implement half-carry flag
835 dst = setcc_rdisp8(dst, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); 833 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
836 dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 834 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
837 dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 835 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
838 } 836 }
839 dst = z80_save_reg(dst, inst, opts); 837 z80_save_reg(inst, opts);
840 dst = z80_save_ea(dst, inst, opts); 838 z80_save_ea(code, inst, opts);
841 dst = z80_save_result(dst, inst); 839 z80_save_result(code, inst);
842 break; 840 break;
843 //case Z80_DAA: 841 //case Z80_DAA:
844 case Z80_CPL: 842 case Z80_CPL:
845 dst = cycles(&opts->gen, 4); 843 cycles(&opts->gen, 4);
846 dst = not_r(dst, opts->regs[Z80_A], SZ_B); 844 not_r(code, opts->regs[Z80_A], SZ_B);
847 //TODO: Implement half-carry flag 845 //TODO: Implement half-carry flag
848 dst = mov_irdisp8(dst, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 846 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
849 break; 847 break;
850 case Z80_NEG: 848 case Z80_NEG:
851 dst = cycles(&opts->gen, 8); 849 cycles(&opts->gen, 8);
852 dst = neg_r(dst, opts->regs[Z80_A], SZ_B); 850 neg_r(code, opts->regs[Z80_A], SZ_B);
853 //TODO: Implement half-carry flag 851 //TODO: Implement half-carry flag
854 dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 852 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
855 dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 853 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
856 dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); 854 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
857 dst = setcc_rdisp8(dst, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); 855 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
858 dst = mov_irdisp8(dst, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 856 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
859 break; 857 break;
860 case Z80_CCF: 858 case Z80_CCF:
861 dst = cycles(&opts->gen, 4); 859 cycles(&opts->gen, 4);
862 dst = xor_irdisp8(dst, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B); 860 xor_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
863 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 861 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
864 //TODO: Implement half-carry flag 862 //TODO: Implement half-carry flag
865 break; 863 break;
866 case Z80_SCF: 864 case Z80_SCF:
867 dst = cycles(&opts->gen, 4); 865 cycles(&opts->gen, 4);
868 dst = mov_irdisp8(dst, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B); 866 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
869 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 867 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
870 //TODO: Implement half-carry flag 868 //TODO: Implement half-carry flag
871 break; 869 break;
872 case Z80_NOP: 870 case Z80_NOP:
873 if (inst->immed == 42) { 871 if (inst->immed == 42) {
874 dst = call(dst, (uint8_t *)z80_save_context); 872 call(code, (uint8_t *)z80_save_context);
875 dst = mov_rr(dst, opts->gen.context_reg, RDI, SZ_Q); 873 mov_rr(code, opts->gen.context_reg, RDI, SZ_Q);
876 dst = jmp(dst, (uint8_t *)z80_print_regs_exit); 874 jmp(code, (uint8_t *)z80_print_regs_exit);
877 } else { 875 } else {
878 dst = cycles(&opts->gen, 4 * inst->immed); 876 cycles(&opts->gen, 4 * inst->immed);
879 } 877 }
880 break; 878 break;
881 case Z80_HALT: 879 case Z80_HALT:
882 dst = cycles(&opts->gen, 4); 880 cycles(&opts->gen, 4);
883 dst = mov_ir(dst, address, opts->gen.scratch1, SZ_W); 881 mov_ir(code, address, opts->gen.scratch1, SZ_W);
884 uint8_t * call_inst = dst; 882 uint8_t * call_inst = code->cur;
885 dst = call(dst, (uint8_t *)z80_halt); 883 call(code, (uint8_t *)z80_halt);
886 dst = jmp(dst, call_inst); 884 jmp(code, call_inst);
887 break; 885 break;
888 case Z80_DI: 886 case Z80_DI:
889 dst = cycles(&opts->gen, 4); 887 cycles(&opts->gen, 4);
890 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B); 888 mov_irdisp(code, 0, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B);
891 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, offsetof(z80_context, iff2), SZ_B); 889 mov_irdisp(code, 0, opts->gen.context_reg, offsetof(z80_context, iff2), SZ_B);
892 dst = mov_rdisp8r(dst, opts->gen.context_reg, offsetof(z80_context, sync_cycle), opts->gen.limit, SZ_D); 890 mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, sync_cycle), opts->gen.limit, SZ_D);
893 dst = mov_irdisp8(dst, 0xFFFFFFFF, opts->gen.context_reg, offsetof(z80_context, int_cycle), SZ_D); 891 mov_irdisp(code, 0xFFFFFFFF, opts->gen.context_reg, offsetof(z80_context, int_cycle), SZ_D);
894 break; 892 break;
895 case Z80_EI: 893 case Z80_EI:
896 dst = cycles(&opts->gen, 4); 894 cycles(&opts->gen, 4);
897 dst = mov_rrdisp32(dst, opts->gen.cycles, opts->gen.context_reg, offsetof(z80_context, int_enable_cycle), SZ_D); 895 mov_rrdisp(code, opts->gen.cycles, opts->gen.context_reg, offsetof(z80_context, int_enable_cycle), SZ_D);
898 dst = mov_irdisp8(dst, 1, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B); 896 mov_irdisp(code, 1, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B);
899 dst = mov_irdisp8(dst, 1, opts->gen.context_reg, offsetof(z80_context, iff2), SZ_B); 897 mov_irdisp(code, 1, opts->gen.context_reg, offsetof(z80_context, iff2), SZ_B);
900 //interrupt enable has a one-instruction latency, minimum instruction duration is 4 cycles 898 //interrupt enable has a one-instruction latency, minimum instruction duration is 4 cycles
901 dst = add_irdisp32(dst, 4, opts->gen.context_reg, offsetof(z80_context, int_enable_cycle), SZ_D); 899 add_irdisp(code, 4, opts->gen.context_reg, offsetof(z80_context, int_enable_cycle), SZ_D);
902 dst = call(dst, (uint8_t *)z80_do_sync); 900 call(code, (uint8_t *)z80_do_sync);
903 break; 901 break;
904 case Z80_IM: 902 case Z80_IM:
905 dst = cycles(&opts->gen, 4); 903 cycles(&opts->gen, 4);
906 dst = mov_irdisp8(dst, inst->immed, opts->gen.context_reg, offsetof(z80_context, im), SZ_B); 904 mov_irdisp(code, inst->immed, opts->gen.context_reg, offsetof(z80_context, im), SZ_B);
907 break; 905 break;
908 case Z80_RLC: 906 case Z80_RLC:
909 cycles = inst->immed == 0 ? 4 : (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8); 907 num_cycles = inst->immed == 0 ? 4 : (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8);
910 dst = cycles(&opts->gen, cycles); 908 cycles(&opts->gen, num_cycles);
911 if (inst->addr_mode != Z80_UNUSED) { 909 if (inst->addr_mode != Z80_UNUSED) {
912 dst = translate_z80_ea(inst, &dst_op, dst, opts, READ, MODIFY); 910 translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
913 dst = translate_z80_reg(inst, &src_op, dst, opts); //For IX/IY variants that also write to a register 911 translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
914 dst = cycles(&opts->gen, 1); 912 cycles(&opts->gen, 1);
915 } else { 913 } else {
916 src_op.mode = MODE_UNUSED; 914 src_op.mode = MODE_UNUSED;
917 dst = translate_z80_reg(inst, &dst_op, dst, opts); 915 translate_z80_reg(inst, &dst_op, opts);
918 } 916 }
919 dst = rol_ir(dst, 1, dst_op.base, SZ_B); 917 rol_ir(code, 1, dst_op.base, SZ_B);
920 if (src_op.mode != MODE_UNUSED) { 918 if (src_op.mode != MODE_UNUSED) {
921 dst = mov_rr(dst, dst_op.base, src_op.base, SZ_B); 919 mov_rr(code, dst_op.base, src_op.base, SZ_B);
922 } 920 }
923 dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); 921 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
924 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 922 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
925 //TODO: Implement half-carry flag 923 //TODO: Implement half-carry flag
926 dst = cmp_ir(dst, 0, dst_op.base, SZ_B); 924 cmp_ir(code, 0, dst_op.base, SZ_B);
927 dst = setcc_rdisp8(dst, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); 925 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
928 dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 926 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
929 dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 927 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
930 if (inst->addr_mode != Z80_UNUSED) { 928 if (inst->addr_mode != Z80_UNUSED) {
931 dst = z80_save_result(dst, inst); 929 z80_save_result(code, inst);
932 if (src_op.mode != MODE_UNUSED) { 930 if (src_op.mode != MODE_UNUSED) {
933 dst = z80_save_reg(dst, inst, opts); 931 z80_save_reg(inst, opts);
934 } 932 }
935 } else { 933 } else {
936 dst = z80_save_reg(dst, inst, opts); 934 z80_save_reg(inst, opts);
937 } 935 }
938 break; 936 break;
939 case Z80_RL: 937 case Z80_RL:
940 cycles = inst->immed == 0 ? 4 : (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8); 938 num_cycles = inst->immed == 0 ? 4 : (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8);
941 dst = cycles(&opts->gen, cycles); 939 cycles(&opts->gen, num_cycles);
942 if (inst->addr_mode != Z80_UNUSED) { 940 if (inst->addr_mode != Z80_UNUSED) {
943 dst = translate_z80_ea(inst, &dst_op, dst, opts, READ, MODIFY); 941 translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
944 dst = translate_z80_reg(inst, &src_op, dst, opts); //For IX/IY variants that also write to a register 942 translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
945 dst = cycles(&opts->gen, 1); 943 cycles(&opts->gen, 1);
946 } else { 944 } else {
947 src_op.mode = MODE_UNUSED; 945 src_op.mode = MODE_UNUSED;
948 dst = translate_z80_reg(inst, &dst_op, dst, opts); 946 translate_z80_reg(inst, &dst_op, opts);
949 } 947 }
950 dst = bt_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); 948 bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
951 dst = rcl_ir(dst, 1, dst_op.base, SZ_B); 949 rcl_ir(code, 1, dst_op.base, SZ_B);
952 if (src_op.mode != MODE_UNUSED) { 950 if (src_op.mode != MODE_UNUSED) {
953 dst = mov_rr(dst, dst_op.base, src_op.base, SZ_B); 951 mov_rr(code, dst_op.base, src_op.base, SZ_B);
954 } 952 }
955 dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); 953 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
956 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 954 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
957 //TODO: Implement half-carry flag 955 //TODO: Implement half-carry flag
958 dst = cmp_ir(dst, 0, dst_op.base, SZ_B); 956 cmp_ir(code, 0, dst_op.base, SZ_B);
959 dst = setcc_rdisp8(dst, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); 957 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
960 dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 958 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
961 dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 959 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
962 if (inst->addr_mode != Z80_UNUSED) { 960 if (inst->addr_mode != Z80_UNUSED) {
963 dst = z80_save_result(dst, inst); 961 z80_save_result(code, inst);
964 if (src_op.mode != MODE_UNUSED) { 962 if (src_op.mode != MODE_UNUSED) {
965 dst = z80_save_reg(dst, inst, opts); 963 z80_save_reg(inst, opts);
966 } 964 }
967 } else { 965 } else {
968 dst = z80_save_reg(dst, inst, opts); 966 z80_save_reg(inst, opts);
969 } 967 }
970 break; 968 break;
971 case Z80_RRC: 969 case Z80_RRC:
972 cycles = inst->immed == 0 ? 4 : (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8); 970 num_cycles = inst->immed == 0 ? 4 : (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8);
973 dst = cycles(&opts->gen, cycles); 971 cycles(&opts->gen, num_cycles);
974 if (inst->addr_mode != Z80_UNUSED) { 972 if (inst->addr_mode != Z80_UNUSED) {
975 dst = translate_z80_ea(inst, &dst_op, dst, opts, READ, MODIFY); 973 translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
976 dst = translate_z80_reg(inst, &src_op, dst, opts); //For IX/IY variants that also write to a register 974 translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
977 dst = cycles(&opts->gen, 1); 975 cycles(&opts->gen, 1);
978 } else { 976 } else {
979 src_op.mode = MODE_UNUSED; 977 src_op.mode = MODE_UNUSED;
980 dst = translate_z80_reg(inst, &dst_op, dst, opts); 978 translate_z80_reg(inst, &dst_op, opts);
981 } 979 }
982 dst = ror_ir(dst, 1, dst_op.base, SZ_B); 980 ror_ir(code, 1, dst_op.base, SZ_B);
983 if (src_op.mode != MODE_UNUSED) { 981 if (src_op.mode != MODE_UNUSED) {
984 dst = mov_rr(dst, dst_op.base, src_op.base, SZ_B); 982 mov_rr(code, dst_op.base, src_op.base, SZ_B);
985 } 983 }
986 dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); 984 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
987 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 985 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
988 //TODO: Implement half-carry flag 986 //TODO: Implement half-carry flag
989 dst = cmp_ir(dst, 0, dst_op.base, SZ_B); 987 cmp_ir(code, 0, dst_op.base, SZ_B);
990 dst = setcc_rdisp8(dst, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); 988 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
991 dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 989 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
992 dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 990 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
993 if (inst->addr_mode != Z80_UNUSED) { 991 if (inst->addr_mode != Z80_UNUSED) {
994 dst = z80_save_result(dst, inst); 992 z80_save_result(code, inst);
995 if (src_op.mode != MODE_UNUSED) { 993 if (src_op.mode != MODE_UNUSED) {
996 dst = z80_save_reg(dst, inst, opts); 994 z80_save_reg(inst, opts);
997 } 995 }
998 } else { 996 } else {
999 dst = z80_save_reg(dst, inst, opts); 997 z80_save_reg(inst, opts);
1000 } 998 }
1001 break; 999 break;
1002 case Z80_RR: 1000 case Z80_RR:
1003 cycles = inst->immed == 0 ? 4 : (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8); 1001 num_cycles = inst->immed == 0 ? 4 : (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8);
1004 dst = cycles(&opts->gen, cycles); 1002 cycles(&opts->gen, num_cycles);
1005 if (inst->addr_mode != Z80_UNUSED) { 1003 if (inst->addr_mode != Z80_UNUSED) {
1006 dst = translate_z80_ea(inst, &dst_op, dst, opts, READ, MODIFY); 1004 translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
1007 dst = translate_z80_reg(inst, &src_op, dst, opts); //For IX/IY variants that also write to a register 1005 translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
1008 dst = cycles(&opts->gen, 1); 1006 cycles(&opts->gen, 1);
1009 } else { 1007 } else {
1010 src_op.mode = MODE_UNUSED; 1008 src_op.mode = MODE_UNUSED;
1011 dst = translate_z80_reg(inst, &dst_op, dst, opts); 1009 translate_z80_reg(inst, &dst_op, opts);
1012 } 1010 }
1013 dst = bt_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); 1011 bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1014 dst = rcr_ir(dst, 1, dst_op.base, SZ_B); 1012 rcr_ir(code, 1, dst_op.base, SZ_B);
1015 if (src_op.mode != MODE_UNUSED) { 1013 if (src_op.mode != MODE_UNUSED) {
1016 dst = mov_rr(dst, dst_op.base, src_op.base, SZ_B); 1014 mov_rr(code, dst_op.base, src_op.base, SZ_B);
1017 } 1015 }
1018 dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); 1016 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1019 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 1017 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1020 //TODO: Implement half-carry flag 1018 //TODO: Implement half-carry flag
1021 dst = cmp_ir(dst, 0, dst_op.base, SZ_B); 1019 cmp_ir(code, 0, dst_op.base, SZ_B);
1022 dst = setcc_rdisp8(dst, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); 1020 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1023 dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 1021 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1024 dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 1022 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1025 if (inst->addr_mode != Z80_UNUSED) { 1023 if (inst->addr_mode != Z80_UNUSED) {
1026 dst = z80_save_result(dst, inst); 1024 z80_save_result(code, inst);
1027 if (src_op.mode != MODE_UNUSED) { 1025 if (src_op.mode != MODE_UNUSED) {
1028 dst = z80_save_reg(dst, inst, opts); 1026 z80_save_reg(inst, opts);
1029 } 1027 }
1030 } else { 1028 } else {
1031 dst = z80_save_reg(dst, inst, opts); 1029 z80_save_reg(inst, opts);
1032 } 1030 }
1033 break; 1031 break;
1034 case Z80_SLA: 1032 case Z80_SLA:
1035 case Z80_SLL: 1033 case Z80_SLL:
1036 cycles = inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8; 1034 num_cycles = inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8;
1037 dst = cycles(&opts->gen, cycles); 1035 cycles(&opts->gen, num_cycles);
1038 if (inst->addr_mode != Z80_UNUSED) { 1036 if (inst->addr_mode != Z80_UNUSED) {
1039 dst = translate_z80_ea(inst, &dst_op, dst, opts, READ, MODIFY); 1037 translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
1040 dst = translate_z80_reg(inst, &src_op, dst, opts); //For IX/IY variants that also write to a register 1038 translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
1041 dst = cycles(&opts->gen, 1); 1039 cycles(&opts->gen, 1);
1042 } else { 1040 } else {
1043 src_op.mode = MODE_UNUSED; 1041 src_op.mode = MODE_UNUSED;
1044 dst = translate_z80_reg(inst, &dst_op, dst, opts); 1042 translate_z80_reg(inst, &dst_op, opts);
1045 } 1043 }
1046 dst = shl_ir(dst, 1, dst_op.base, SZ_B); 1044 shl_ir(code, 1, dst_op.base, SZ_B);
1047 dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); 1045 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1048 if (inst->op == Z80_SLL) { 1046 if (inst->op == Z80_SLL) {
1049 dst = or_ir(dst, 1, dst_op.base, SZ_B); 1047 or_ir(code, 1, dst_op.base, SZ_B);
1050 } 1048 }
1051 if (src_op.mode != MODE_UNUSED) { 1049 if (src_op.mode != MODE_UNUSED) {
1052 dst = mov_rr(dst, dst_op.base, src_op.base, SZ_B); 1050 mov_rr(code, dst_op.base, src_op.base, SZ_B);
1053 } 1051 }
1054 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 1052 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1055 //TODO: Implement half-carry flag 1053 //TODO: Implement half-carry flag
1056 dst = cmp_ir(dst, 0, dst_op.base, SZ_B); 1054 cmp_ir(code, 0, dst_op.base, SZ_B);
1057 dst = setcc_rdisp8(dst, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); 1055 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1058 dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 1056 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1059 dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 1057 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1060 if (inst->addr_mode != Z80_UNUSED) { 1058 if (inst->addr_mode != Z80_UNUSED) {
1061 dst = z80_save_result(dst, inst); 1059 z80_save_result(code, inst);
1062 if (src_op.mode != MODE_UNUSED) { 1060 if (src_op.mode != MODE_UNUSED) {
1063 dst = z80_save_reg(dst, inst, opts); 1061 z80_save_reg(inst, opts);
1064 } 1062 }
1065 } else { 1063 } else {
1066 dst = z80_save_reg(dst, inst, opts); 1064 z80_save_reg(inst, opts);
1067 } 1065 }
1068 break; 1066 break;
1069 case Z80_SRA: 1067 case Z80_SRA:
1070 cycles = inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8; 1068 num_cycles = inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8;
1071 dst = cycles(&opts->gen, cycles); 1069 cycles(&opts->gen, num_cycles);
1072 if (inst->addr_mode != Z80_UNUSED) { 1070 if (inst->addr_mode != Z80_UNUSED) {
1073 dst = translate_z80_ea(inst, &dst_op, dst, opts, READ, MODIFY); 1071 translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
1074 dst = translate_z80_reg(inst, &src_op, dst, opts); //For IX/IY variants that also write to a register 1072 translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
1075 dst = cycles(&opts->gen, 1); 1073 cycles(&opts->gen, 1);
1076 } else { 1074 } else {
1077 src_op.mode = MODE_UNUSED; 1075 src_op.mode = MODE_UNUSED;
1078 dst = translate_z80_reg(inst, &dst_op, dst, opts); 1076 translate_z80_reg(inst, &dst_op, opts);
1079 } 1077 }
1080 dst = sar_ir(dst, 1, dst_op.base, SZ_B); 1078 sar_ir(code, 1, dst_op.base, SZ_B);
1081 if (src_op.mode != MODE_UNUSED) { 1079 if (src_op.mode != MODE_UNUSED) {
1082 dst = mov_rr(dst, dst_op.base, src_op.base, SZ_B); 1080 mov_rr(code, dst_op.base, src_op.base, SZ_B);
1083 } 1081 }
1084 dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); 1082 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1085 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 1083 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1086 //TODO: Implement half-carry flag 1084 //TODO: Implement half-carry flag
1087 dst = cmp_ir(dst, 0, dst_op.base, SZ_B); 1085 cmp_ir(code, 0, dst_op.base, SZ_B);
1088 dst = setcc_rdisp8(dst, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); 1086 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1089 dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 1087 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1090 dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 1088 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1091 if (inst->addr_mode != Z80_UNUSED) { 1089 if (inst->addr_mode != Z80_UNUSED) {
1092 dst = z80_save_result(dst, inst); 1090 z80_save_result(code, inst);
1093 if (src_op.mode != MODE_UNUSED) { 1091 if (src_op.mode != MODE_UNUSED) {
1094 dst = z80_save_reg(dst, inst, opts); 1092 z80_save_reg(inst, opts);
1095 } 1093 }
1096 } else { 1094 } else {
1097 dst = z80_save_reg(dst, inst, opts); 1095 z80_save_reg(inst, opts);
1098 } 1096 }
1099 break; 1097 break;
1100 case Z80_SRL: 1098 case Z80_SRL:
1101 cycles = inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8; 1099 num_cycles = inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8;
1102 dst = cycles(&opts->gen, cycles); 1100 cycles(&opts->gen, num_cycles);
1103 if (inst->addr_mode != Z80_UNUSED) { 1101 if (inst->addr_mode != Z80_UNUSED) {
1104 dst = translate_z80_ea(inst, &dst_op, dst, opts, READ, MODIFY); 1102 translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
1105 dst = translate_z80_reg(inst, &src_op, dst, opts); //For IX/IY variants that also write to a register 1103 translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
1106 dst = cycles(&opts->gen, 1); 1104 cycles(&opts->gen, 1);
1107 } else { 1105 } else {
1108 src_op.mode = MODE_UNUSED; 1106 src_op.mode = MODE_UNUSED;
1109 dst = translate_z80_reg(inst, &dst_op, dst, opts); 1107 translate_z80_reg(inst, &dst_op, opts);
1110 } 1108 }
1111 dst = shr_ir(dst, 1, dst_op.base, SZ_B); 1109 shr_ir(code, 1, dst_op.base, SZ_B);
1112 if (src_op.mode != MODE_UNUSED) { 1110 if (src_op.mode != MODE_UNUSED) {
1113 dst = mov_rr(dst, dst_op.base, src_op.base, SZ_B); 1111 mov_rr(code, dst_op.base, src_op.base, SZ_B);
1114 } 1112 }
1115 dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); 1113 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1116 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 1114 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1117 //TODO: Implement half-carry flag 1115 //TODO: Implement half-carry flag
1118 dst = cmp_ir(dst, 0, dst_op.base, SZ_B); 1116 cmp_ir(code, 0, dst_op.base, SZ_B);
1119 dst = setcc_rdisp8(dst, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); 1117 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1120 dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 1118 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1121 dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 1119 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1122 if (inst->addr_mode != Z80_UNUSED) { 1120 if (inst->addr_mode != Z80_UNUSED) {
1123 dst = z80_save_result(dst, inst); 1121 z80_save_result(code, inst);
1124 if (src_op.mode != MODE_UNUSED) { 1122 if (src_op.mode != MODE_UNUSED) {
1125 dst = z80_save_reg(dst, inst, opts); 1123 z80_save_reg(inst, opts);
1126 } 1124 }
1127 } else { 1125 } else {
1128 dst = z80_save_reg(dst, inst, opts); 1126 z80_save_reg(inst, opts);
1129 } 1127 }
1130 break; 1128 break;
1131 case Z80_RLD: 1129 case Z80_RLD:
1132 dst = cycles(&opts->gen, 8); 1130 cycles(&opts->gen, 8);
1133 dst = mov_rr(dst, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W); 1131 mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W);
1134 dst = call(dst, (uint8_t *)z80_read_byte); 1132 call(code, (uint8_t *)z80_read_byte);
1135 //Before: (HL) = 0x12, A = 0x34 1133 //Before: (HL) = 0x12, A = 0x34
1136 //After: (HL) = 0x24, A = 0x31 1134 //After: (HL) = 0x24, A = 0x31
1137 dst = mov_rr(dst, opts->regs[Z80_A], opts->gen.scratch2, SZ_B); 1135 mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
1138 dst = shl_ir(dst, 4, opts->gen.scratch1, SZ_W); 1136 shl_ir(code, 4, opts->gen.scratch1, SZ_W);
1139 dst = and_ir(dst, 0xF, opts->gen.scratch2, SZ_W); 1137 and_ir(code, 0xF, opts->gen.scratch2, SZ_W);
1140 dst = and_ir(dst, 0xFFF, opts->gen.scratch1, SZ_W); 1138 and_ir(code, 0xFFF, opts->gen.scratch1, SZ_W);
1141 dst = and_ir(dst, 0xF0, opts->regs[Z80_A], SZ_B); 1139 and_ir(code, 0xF0, opts->regs[Z80_A], SZ_B);
1142 dst = or_rr(dst, opts->gen.scratch2, opts->gen.scratch1, SZ_W); 1140 or_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_W);
1143 //opts->gen.scratch1 = 0x0124 1141 //opts->gen.scratch1 = 0x0124
1144 dst = ror_ir(dst, 8, opts->gen.scratch1, SZ_W); 1142 ror_ir(code, 8, opts->gen.scratch1, SZ_W);
1145 dst = cycles(&opts->gen, 4); 1143 cycles(&opts->gen, 4);
1146 dst = or_rr(dst, opts->gen.scratch1, opts->regs[Z80_A], SZ_B); 1144 or_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B);
1147 //set flags 1145 //set flags
1148 //TODO: Implement half-carry flag 1146 //TODO: Implement half-carry flag
1149 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 1147 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1150 dst = setcc_rdisp8(dst, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); 1148 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1151 dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 1149 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1152 dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 1150 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1153 1151
1154 dst = mov_rr(dst, opts->regs[Z80_HL], opts->gen.scratch2, SZ_W); 1152 mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch2, SZ_W);
1155 dst = ror_ir(dst, 8, opts->gen.scratch1, SZ_W); 1153 ror_ir(code, 8, opts->gen.scratch1, SZ_W);
1156 dst = call(dst, (uint8_t *)z80_write_byte); 1154 call(code, (uint8_t *)z80_write_byte);
1157 break; 1155 break;
1158 case Z80_RRD: 1156 case Z80_RRD:
1159 dst = cycles(&opts->gen, 8); 1157 cycles(&opts->gen, 8);
1160 dst = mov_rr(dst, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W); 1158 mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W);
1161 dst = call(dst, (uint8_t *)z80_read_byte); 1159 call(code, (uint8_t *)z80_read_byte);
1162 //Before: (HL) = 0x12, A = 0x34 1160 //Before: (HL) = 0x12, A = 0x34
1163 //After: (HL) = 0x41, A = 0x32 1161 //After: (HL) = 0x41, A = 0x32
1164 dst = movzx_rr(dst, opts->regs[Z80_A], opts->gen.scratch2, SZ_B, SZ_W); 1162 movzx_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B, SZ_W);
1165 dst = ror_ir(dst, 4, opts->gen.scratch1, SZ_W); 1163 ror_ir(code, 4, opts->gen.scratch1, SZ_W);
1166 dst = shl_ir(dst, 4, opts->gen.scratch2, SZ_W); 1164 shl_ir(code, 4, opts->gen.scratch2, SZ_W);
1167 dst = and_ir(dst, 0xF00F, opts->gen.scratch1, SZ_W); 1165 and_ir(code, 0xF00F, opts->gen.scratch1, SZ_W);
1168 dst = and_ir(dst, 0xF0, opts->regs[Z80_A], SZ_B); 1166 and_ir(code, 0xF0, opts->regs[Z80_A], SZ_B);
1169 //opts->gen.scratch1 = 0x2001 1167 //opts->gen.scratch1 = 0x2001
1170 //opts->gen.scratch2 = 0x0040 1168 //opts->gen.scratch2 = 0x0040
1171 dst = or_rr(dst, opts->gen.scratch2, opts->gen.scratch1, SZ_W); 1169 or_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_W);
1172 //opts->gen.scratch1 = 0x2041 1170 //opts->gen.scratch1 = 0x2041
1173 dst = ror_ir(dst, 8, opts->gen.scratch1, SZ_W); 1171 ror_ir(code, 8, opts->gen.scratch1, SZ_W);
1174 dst = cycles(&opts->gen, 4); 1172 cycles(&opts->gen, 4);
1175 dst = shr_ir(dst, 4, opts->gen.scratch1, SZ_B); 1173 shr_ir(code, 4, opts->gen.scratch1, SZ_B);
1176 dst = or_rr(dst, opts->gen.scratch1, opts->regs[Z80_A], SZ_B); 1174 or_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B);
1177 //set flags 1175 //set flags
1178 //TODO: Implement half-carry flag 1176 //TODO: Implement half-carry flag
1179 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 1177 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1180 dst = setcc_rdisp8(dst, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); 1178 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1181 dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 1179 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1182 dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 1180 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1183 1181
1184 dst = mov_rr(dst, opts->regs[Z80_HL], opts->gen.scratch2, SZ_W); 1182 mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch2, SZ_W);
1185 dst = ror_ir(dst, 8, opts->gen.scratch1, SZ_W); 1183 ror_ir(code, 8, opts->gen.scratch1, SZ_W);
1186 dst = call(dst, (uint8_t *)z80_write_byte); 1184 call(code, (uint8_t *)z80_write_byte);
1187 break; 1185 break;
1188 case Z80_BIT: { 1186 case Z80_BIT: {
1189 cycles = (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) ? 8 : 16; 1187 num_cycles = (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) ? 8 : 16;
1190 dst = cycles(&opts->gen, cycles); 1188 cycles(&opts->gen, num_cycles);
1191 uint8_t bit; 1189 uint8_t bit;
1192 if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) { 1190 if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) {
1193 src_op.base = opts->regs[z80_word_reg(inst->ea_reg)]; 1191 src_op.base = opts->regs[z80_word_reg(inst->ea_reg)];
1194 size = SZ_W; 1192 size = SZ_W;
1195 bit = inst->immed + 8; 1193 bit = inst->immed + 8;
1196 } else { 1194 } else {
1197 size = SZ_B; 1195 size = SZ_B;
1198 bit = inst->immed; 1196 bit = inst->immed;
1199 dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); 1197 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
1200 } 1198 }
1201 if (inst->addr_mode != Z80_REG) { 1199 if (inst->addr_mode != Z80_REG) {
1202 //Reads normally take 3 cycles, but the read at the end of a bit instruction takes 4 1200 //Reads normally take 3 cycles, but the read at the end of a bit instruction takes 4
1203 dst = cycles(&opts->gen, 1); 1201 cycles(&opts->gen, 1);
1204 } 1202 }
1205 dst = bt_ir(dst, bit, src_op.base, size); 1203 bt_ir(code, bit, src_op.base, size);
1206 dst = setcc_rdisp8(dst, CC_NC, opts->gen.context_reg, zf_off(ZF_Z)); 1204 setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_Z));
1207 dst = setcc_rdisp8(dst, CC_NC, opts->gen.context_reg, zf_off(ZF_PV)); 1205 setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_PV));
1208 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 1206 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1209 if (inst->immed == 7) { 1207 if (inst->immed == 7) {
1210 dst = cmp_ir(dst, 0, src_op.base, size); 1208 cmp_ir(code, 0, src_op.base, size);
1211 dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 1209 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1212 } else { 1210 } else {
1213 dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_S), SZ_B); 1211 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_S), SZ_B);
1214 } 1212 }
1215 break; 1213 break;
1216 } 1214 }
1217 case Z80_SET: { 1215 case Z80_SET: {
1218 cycles = (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) ? 8 : 16; 1216 num_cycles = (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) ? 8 : 16;
1219 dst = cycles(&opts->gen, cycles); 1217 cycles(&opts->gen, num_cycles);
1220 uint8_t bit; 1218 uint8_t bit;
1221 if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) { 1219 if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) {
1222 src_op.base = opts->regs[z80_word_reg(inst->ea_reg)]; 1220 src_op.base = opts->regs[z80_word_reg(inst->ea_reg)];
1223 size = SZ_W; 1221 size = SZ_W;
1224 bit = inst->immed + 8; 1222 bit = inst->immed + 8;
1225 } else { 1223 } else {
1226 size = SZ_B; 1224 size = SZ_B;
1227 bit = inst->immed; 1225 bit = inst->immed;
1228 dst = translate_z80_ea(inst, &src_op, dst, opts, READ, MODIFY); 1226 translate_z80_ea(inst, &src_op, opts, READ, MODIFY);
1229 } 1227 }
1230 if (inst->reg != Z80_USE_IMMED) { 1228 if (inst->reg != Z80_USE_IMMED) {
1231 dst = translate_z80_reg(inst, &dst_op, dst, opts); 1229 translate_z80_reg(inst, &dst_op, opts);
1232 } 1230 }
1233 if (inst->addr_mode != Z80_REG) { 1231 if (inst->addr_mode != Z80_REG) {
1234 //Reads normally take 3 cycles, but the read in the middle of a set instruction takes 4 1232 //Reads normally take 3 cycles, but the read in the middle of a set instruction takes 4
1235 dst = cycles(&opts->gen, 1); 1233 cycles(&opts->gen, 1);
1236 } 1234 }
1237 dst = bts_ir(dst, bit, src_op.base, size); 1235 bts_ir(code, bit, src_op.base, size);
1238 if (inst->reg != Z80_USE_IMMED) { 1236 if (inst->reg != Z80_USE_IMMED) {
1239 if (size == SZ_W) { 1237 if (size == SZ_W) {
1240 if (dst_op.base >= R8) { 1238 if (dst_op.base >= R8) {
1241 dst = ror_ir(dst, 8, src_op.base, SZ_W); 1239 ror_ir(code, 8, src_op.base, SZ_W);
1242 dst = mov_rr(dst, opts->regs[z80_low_reg(inst->ea_reg)], dst_op.base, SZ_B); 1240 mov_rr(code, opts->regs[z80_low_reg(inst->ea_reg)], dst_op.base, SZ_B);
1243 dst = ror_ir(dst, 8, src_op.base, SZ_W); 1241 ror_ir(code, 8, src_op.base, SZ_W);
1244 } else { 1242 } else {
1245 dst = mov_rr(dst, opts->regs[inst->ea_reg], dst_op.base, SZ_B); 1243 mov_rr(code, opts->regs[inst->ea_reg], dst_op.base, SZ_B);
1246 } 1244 }
1247 } else { 1245 } else {
1248 dst = mov_rr(dst, src_op.base, dst_op.base, SZ_B); 1246 mov_rr(code, src_op.base, dst_op.base, SZ_B);
1249 } 1247 }
1250 } 1248 }
1251 if ((inst->addr_mode & 0x1F) != Z80_REG) { 1249 if ((inst->addr_mode & 0x1F) != Z80_REG) {
1252 dst = z80_save_result(dst, inst); 1250 z80_save_result(code, inst);
1253 if (inst->reg != Z80_USE_IMMED) { 1251 if (inst->reg != Z80_USE_IMMED) {
1254 dst = z80_save_reg(dst, inst, opts); 1252 z80_save_reg(inst, opts);
1255 } 1253 }
1256 } 1254 }
1257 break; 1255 break;
1258 } 1256 }
1259 case Z80_RES: { 1257 case Z80_RES: {
1260 cycles = (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) ? 8 : 16; 1258 num_cycles = (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) ? 8 : 16;
1261 dst = cycles(&opts->gen, cycles); 1259 cycles(&opts->gen, num_cycles);
1262 uint8_t bit; 1260 uint8_t bit;
1263 if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) { 1261 if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) {
1264 src_op.base = opts->regs[z80_word_reg(inst->ea_reg)]; 1262 src_op.base = opts->regs[z80_word_reg(inst->ea_reg)];
1265 size = SZ_W; 1263 size = SZ_W;
1266 bit = inst->immed + 8; 1264 bit = inst->immed + 8;
1267 } else { 1265 } else {
1268 size = SZ_B; 1266 size = SZ_B;
1269 bit = inst->immed; 1267 bit = inst->immed;
1270 dst = translate_z80_ea(inst, &src_op, dst, opts, READ, MODIFY); 1268 translate_z80_ea(inst, &src_op, opts, READ, MODIFY);
1271 } 1269 }
1272 if (inst->reg != Z80_USE_IMMED) { 1270 if (inst->reg != Z80_USE_IMMED) {
1273 dst = translate_z80_reg(inst, &dst_op, dst, opts); 1271 translate_z80_reg(inst, &dst_op, opts);
1274 } 1272 }
1275 if (inst->addr_mode != Z80_REG) { 1273 if (inst->addr_mode != Z80_REG) {
1276 //Reads normally take 3 cycles, but the read in the middle of a set instruction takes 4 1274 //Reads normally take 3 cycles, but the read in the middle of a set instruction takes 4
1277 dst = cycles(&opts->gen, 1); 1275 cycles(&opts->gen, 1);
1278 } 1276 }
1279 dst = btr_ir(dst, bit, src_op.base, size); 1277 btr_ir(code, bit, src_op.base, size);
1280 if (inst->reg != Z80_USE_IMMED) { 1278 if (inst->reg != Z80_USE_IMMED) {
1281 if (size == SZ_W) { 1279 if (size == SZ_W) {
1282 if (dst_op.base >= R8) { 1280 if (dst_op.base >= R8) {
1283 dst = ror_ir(dst, 8, src_op.base, SZ_W); 1281 ror_ir(code, 8, src_op.base, SZ_W);
1284 dst = mov_rr(dst, opts->regs[z80_low_reg(inst->ea_reg)], dst_op.base, SZ_B); 1282 mov_rr(code, opts->regs[z80_low_reg(inst->ea_reg)], dst_op.base, SZ_B);
1285 dst = ror_ir(dst, 8, src_op.base, SZ_W); 1283 ror_ir(code, 8, src_op.base, SZ_W);
1286 } else { 1284 } else {
1287 dst = mov_rr(dst, opts->regs[inst->ea_reg], dst_op.base, SZ_B); 1285 mov_rr(code, opts->regs[inst->ea_reg], dst_op.base, SZ_B);
1288 } 1286 }
1289 } else { 1287 } else {
1290 dst = mov_rr(dst, src_op.base, dst_op.base, SZ_B); 1288 mov_rr(code, src_op.base, dst_op.base, SZ_B);
1291 } 1289 }
1292 } 1290 }
1293 if (inst->addr_mode != Z80_REG) { 1291 if (inst->addr_mode != Z80_REG) {
1294 dst = z80_save_result(dst, inst); 1292 z80_save_result(code, inst);
1295 if (inst->reg != Z80_USE_IMMED) { 1293 if (inst->reg != Z80_USE_IMMED) {
1296 dst = z80_save_reg(dst, inst, opts); 1294 z80_save_reg(inst, opts);
1297 } 1295 }
1298 } 1296 }
1299 break; 1297 break;
1300 } 1298 }
1301 case Z80_JP: { 1299 case Z80_JP: {
1302 cycles = 4; 1300 num_cycles = 4;
1303 if (inst->addr_mode != Z80_REG_INDIRECT) { 1301 if (inst->addr_mode != Z80_REG_INDIRECT) {
1304 cycles += 6; 1302 num_cycles += 6;
1305 } else if(inst->ea_reg == Z80_IX || inst->ea_reg == Z80_IY) { 1303 } else if(inst->ea_reg == Z80_IX || inst->ea_reg == Z80_IY) {
1306 cycles += 4; 1304 num_cycles += 4;
1307 } 1305 }
1308 dst = cycles(&opts->gen, cycles); 1306 cycles(&opts->gen, num_cycles);
1309 if (inst->addr_mode != Z80_REG_INDIRECT && inst->immed < 0x4000) { 1307 if (inst->addr_mode != Z80_REG_INDIRECT && inst->immed < 0x4000) {
1310 uint8_t * call_dst = z80_get_native_address(context, inst->immed); 1308 code_ptr call_dst = z80_get_native_address(context, inst->immed);
1311 if (!call_dst) { 1309 if (!call_dst) {
1312 opts->deferred = defer_address(opts->deferred, inst->immed, dst + 1); 1310 opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
1313 //fake address to force large displacement 1311 //fake address to force large displacement
1314 call_dst = dst + 256; 1312 call_dst + 256;
1315 } 1313 }
1316 dst = jmp(dst, call_dst); 1314 jmp(code, call_dst);
1317 } else { 1315 } else {
1318 if (inst->addr_mode == Z80_REG_INDIRECT) { 1316 if (inst->addr_mode == Z80_REG_INDIRECT) {
1319 dst = mov_rr(dst, opts->regs[inst->ea_reg], opts->gen.scratch1, SZ_W); 1317 mov_rr(code, opts->regs[inst->ea_reg], opts->gen.scratch1, SZ_W);
1320 } else { 1318 } else {
1321 dst = mov_ir(dst, inst->immed, opts->gen.scratch1, SZ_W); 1319 mov_ir(code, inst->immed, opts->gen.scratch1, SZ_W);
1322 } 1320 }
1323 dst = call(dst, (uint8_t *)z80_native_addr); 1321 call(code, (uint8_t *)z80_native_addr);
1324 dst = jmp_r(dst, opts->gen.scratch1); 1322 jmp_r(code, opts->gen.scratch1);
1325 } 1323 }
1326 break; 1324 break;
1327 } 1325 }
1328 case Z80_JPCC: { 1326 case Z80_JPCC: {
1329 dst = cycles(&opts->gen, 7);//T States: 4,3 1327 cycles(&opts->gen, 7);//T States: 4,3
1330 uint8_t cond = CC_Z; 1328 uint8_t cond = CC_Z;
1331 switch (inst->reg) 1329 switch (inst->reg)
1332 { 1330 {
1333 case Z80_CC_NZ: 1331 case Z80_CC_NZ:
1334 cond = CC_NZ; 1332 cond = CC_NZ;
1335 case Z80_CC_Z: 1333 case Z80_CC_Z:
1336 dst = cmp_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_Z), SZ_B); 1334 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_Z), SZ_B);
1337 break; 1335 break;
1338 case Z80_CC_NC: 1336 case Z80_CC_NC:
1339 cond = CC_NZ; 1337 cond = CC_NZ;
1340 case Z80_CC_C: 1338 case Z80_CC_C:
1341 dst = cmp_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); 1339 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1342 break; 1340 break;
1343 case Z80_CC_PO: 1341 case Z80_CC_PO:
1344 cond = CC_NZ; 1342 cond = CC_NZ;
1345 case Z80_CC_PE: 1343 case Z80_CC_PE:
1346 dst = cmp_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B); 1344 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
1347 break; 1345 break;
1348 case Z80_CC_P: 1346 case Z80_CC_P:
1349 cond = CC_NZ; 1347 cond = CC_NZ;
1350 case Z80_CC_M: 1348 case Z80_CC_M:
1351 dst = cmp_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_S), SZ_B); 1349 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_S), SZ_B);
1352 break; 1350 break;
1353 } 1351 }
1354 uint8_t *no_jump_off = dst+1; 1352 uint8_t *no_jump_off = code->cur+1;
1355 dst = jcc(dst, cond, dst+2); 1353 jcc(code, cond, code->cur+2);
1356 dst = cycles(&opts->gen, 5);//T States: 5 1354 cycles(&opts->gen, 5);//T States: 5
1357 uint16_t dest_addr = inst->immed; 1355 uint16_t dest_addr = inst->immed;
1358 if (dest_addr < 0x4000) { 1356 if (dest_addr < 0x4000) {
1359 uint8_t * call_dst = z80_get_native_address(context, dest_addr); 1357 code_ptr call_dst = z80_get_native_address(context, dest_addr);
1360 if (!call_dst) { 1358 if (!call_dst) {
1361 opts->deferred = defer_address(opts->deferred, dest_addr, dst + 1); 1359 opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
1362 //fake address to force large displacement 1360 //fake address to force large displacement
1363 call_dst = dst + 256; 1361 call_dst + 256;
1364 } 1362 }
1365 dst = jmp(dst, call_dst); 1363 jmp(code, call_dst);
1366 } else { 1364 } else {
1367 dst = mov_ir(dst, dest_addr, opts->gen.scratch1, SZ_W); 1365 mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W);
1368 dst = call(dst, (uint8_t *)z80_native_addr); 1366 call(code, (uint8_t *)z80_native_addr);
1369 dst = jmp_r(dst, opts->gen.scratch1); 1367 jmp_r(code, opts->gen.scratch1);
1370 } 1368 }
1371 *no_jump_off = dst - (no_jump_off+1); 1369 *no_jump_off = code->cur - (no_jump_off+1);
1372 break; 1370 break;
1373 } 1371 }
1374 case Z80_JR: { 1372 case Z80_JR: {
1375 dst = cycles(&opts->gen, 12);//T States: 4,3,5 1373 cycles(&opts->gen, 12);//T States: 4,3,5
1376 uint16_t dest_addr = address + inst->immed + 2; 1374 uint16_t dest_addr = address + inst->immed + 2;
1377 if (dest_addr < 0x4000) { 1375 if (dest_addr < 0x4000) {
1378 uint8_t * call_dst = z80_get_native_address(context, dest_addr); 1376 code_ptr call_dst = z80_get_native_address(context, dest_addr);
1379 if (!call_dst) { 1377 if (!call_dst) {
1380 opts->deferred = defer_address(opts->deferred, dest_addr, dst + 1); 1378 opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
1381 //fake address to force large displacement 1379 //fake address to force large displacement
1382 call_dst = dst + 256; 1380 call_dst + 256;
1383 } 1381 }
1384 dst = jmp(dst, call_dst); 1382 jmp(code, call_dst);
1385 } else { 1383 } else {
1386 dst = mov_ir(dst, dest_addr, opts->gen.scratch1, SZ_W); 1384 mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W);
1387 dst = call(dst, (uint8_t *)z80_native_addr); 1385 call(code, (uint8_t *)z80_native_addr);
1388 dst = jmp_r(dst, opts->gen.scratch1); 1386 jmp_r(code, opts->gen.scratch1);
1389 } 1387 }
1390 break; 1388 break;
1391 } 1389 }
1392 case Z80_JRCC: { 1390 case Z80_JRCC: {
1393 dst = cycles(&opts->gen, 7);//T States: 4,3 1391 cycles(&opts->gen, 7);//T States: 4,3
1394 uint8_t cond = CC_Z; 1392 uint8_t cond = CC_Z;
1395 switch (inst->reg) 1393 switch (inst->reg)
1396 { 1394 {
1397 case Z80_CC_NZ: 1395 case Z80_CC_NZ:
1398 cond = CC_NZ; 1396 cond = CC_NZ;
1399 case Z80_CC_Z: 1397 case Z80_CC_Z:
1400 dst = cmp_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_Z), SZ_B); 1398 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_Z), SZ_B);
1401 break; 1399 break;
1402 case Z80_CC_NC: 1400 case Z80_CC_NC:
1403 cond = CC_NZ; 1401 cond = CC_NZ;
1404 case Z80_CC_C: 1402 case Z80_CC_C:
1405 dst = cmp_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); 1403 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1406 break; 1404 break;
1407 } 1405 }
1408 uint8_t *no_jump_off = dst+1; 1406 uint8_t *no_jump_off = code->cur+1;
1409 dst = jcc(dst, cond, dst+2); 1407 jcc(code, cond, code->cur+2);
1410 dst = cycles(&opts->gen, 5);//T States: 5 1408 cycles(&opts->gen, 5);//T States: 5
1411 uint16_t dest_addr = address + inst->immed + 2; 1409 uint16_t dest_addr = address + inst->immed + 2;
1412 if (dest_addr < 0x4000) { 1410 if (dest_addr < 0x4000) {
1413 uint8_t * call_dst = z80_get_native_address(context, dest_addr); 1411 code_ptr call_dst = z80_get_native_address(context, dest_addr);
1414 if (!call_dst) { 1412 if (!call_dst) {
1415 opts->deferred = defer_address(opts->deferred, dest_addr, dst + 1); 1413 opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
1416 //fake address to force large displacement 1414 //fake address to force large displacement
1417 call_dst = dst + 256; 1415 call_dst + 256;
1418 } 1416 }
1419 dst = jmp(dst, call_dst); 1417 jmp(code, call_dst);
1420 } else { 1418 } else {
1421 dst = mov_ir(dst, dest_addr, opts->gen.scratch1, SZ_W); 1419 mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W);
1422 dst = call(dst, (uint8_t *)z80_native_addr); 1420 call(code, (uint8_t *)z80_native_addr);
1423 dst = jmp_r(dst, opts->gen.scratch1); 1421 jmp_r(code, opts->gen.scratch1);
1424 } 1422 }
1425 *no_jump_off = dst - (no_jump_off+1); 1423 *no_jump_off = code->cur - (no_jump_off+1);
1426 break; 1424 break;
1427 } 1425 }
1428 case Z80_DJNZ: 1426 case Z80_DJNZ:
1429 dst = cycles(&opts->gen, 8);//T States: 5,3 1427 cycles(&opts->gen, 8);//T States: 5,3
1430 dst = sub_ir(dst, 1, opts->regs[Z80_B], SZ_B); 1428 sub_ir(code, 1, opts->regs[Z80_B], SZ_B);
1431 uint8_t *no_jump_off = dst+1; 1429 uint8_t *no_jump_off = code->cur+1;
1432 dst = jcc(dst, CC_Z, dst+2); 1430 jcc(code, CC_Z, code->cur+2);
1433 dst = cycles(&opts->gen, 5);//T States: 5 1431 cycles(&opts->gen, 5);//T States: 5
1434 uint16_t dest_addr = address + inst->immed + 2; 1432 uint16_t dest_addr = address + inst->immed + 2;
1435 if (dest_addr < 0x4000) { 1433 if (dest_addr < 0x4000) {
1436 uint8_t * call_dst = z80_get_native_address(context, dest_addr); 1434 code_ptr call_dst = z80_get_native_address(context, dest_addr);
1437 if (!call_dst) { 1435 if (!call_dst) {
1438 opts->deferred = defer_address(opts->deferred, dest_addr, dst + 1); 1436 opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
1439 //fake address to force large displacement 1437 //fake address to force large displacement
1440 call_dst = dst + 256; 1438 call_dst + 256;
1441 } 1439 }
1442 dst = jmp(dst, call_dst); 1440 jmp(code, call_dst);
1443 } else { 1441 } else {
1444 dst = mov_ir(dst, dest_addr, opts->gen.scratch1, SZ_W); 1442 mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W);
1445 dst = call(dst, (uint8_t *)z80_native_addr); 1443 call(code, (uint8_t *)z80_native_addr);
1446 dst = jmp_r(dst, opts->gen.scratch1); 1444 jmp_r(code, opts->gen.scratch1);
1447 } 1445 }
1448 *no_jump_off = dst - (no_jump_off+1); 1446 *no_jump_off = code->cur - (no_jump_off+1);
1449 break; 1447 break;
1450 case Z80_CALL: { 1448 case Z80_CALL: {
1451 dst = cycles(&opts->gen, 11);//T States: 4,3,4 1449 cycles(&opts->gen, 11);//T States: 4,3,4
1452 dst = sub_ir(dst, 2, opts->regs[Z80_SP], SZ_W); 1450 sub_ir(code, 2, opts->regs[Z80_SP], SZ_W);
1453 dst = mov_ir(dst, address + 3, opts->gen.scratch1, SZ_W); 1451 mov_ir(code, address + 3, opts->gen.scratch1, SZ_W);
1454 dst = mov_rr(dst, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); 1452 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
1455 dst = call(dst, (uint8_t *)z80_write_word_highfirst);//T States: 3, 3 1453 call(code, (uint8_t *)z80_write_word_highfirst);//T States: 3, 3
1456 if (inst->immed < 0x4000) { 1454 if (inst->immed < 0x4000) {
1457 uint8_t * call_dst = z80_get_native_address(context, inst->immed); 1455 code_ptr call_dst = z80_get_native_address(context, inst->immed);
1458 if (!call_dst) { 1456 if (!call_dst) {
1459 opts->deferred = defer_address(opts->deferred, inst->immed, dst + 1); 1457 opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
1460 //fake address to force large displacement 1458 //fake address to force large displacement
1461 call_dst = dst + 256; 1459 call_dst + 256;
1462 } 1460 }
1463 dst = jmp(dst, call_dst); 1461 jmp(code, call_dst);
1464 } else { 1462 } else {
1465 dst = mov_ir(dst, inst->immed, opts->gen.scratch1, SZ_W); 1463 mov_ir(code, inst->immed, opts->gen.scratch1, SZ_W);
1466 dst = call(dst, (uint8_t *)z80_native_addr); 1464 call(code, (uint8_t *)z80_native_addr);
1467 dst = jmp_r(dst, opts->gen.scratch1); 1465 jmp_r(code, opts->gen.scratch1);
1468 } 1466 }
1469 break; 1467 break;
1470 } 1468 }
1471 case Z80_CALLCC: 1469 case Z80_CALLCC:
1472 dst = cycles(&opts->gen, 10);//T States: 4,3,3 (false case) 1470 cycles(&opts->gen, 10);//T States: 4,3,3 (false case)
1473 uint8_t cond = CC_Z; 1471 uint8_t cond = CC_Z;
1474 switch (inst->reg) 1472 switch (inst->reg)
1475 { 1473 {
1476 case Z80_CC_NZ: 1474 case Z80_CC_NZ:
1477 cond = CC_NZ; 1475 cond = CC_NZ;
1478 case Z80_CC_Z: 1476 case Z80_CC_Z:
1479 dst = cmp_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_Z), SZ_B); 1477 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_Z), SZ_B);
1480 break; 1478 break;
1481 case Z80_CC_NC: 1479 case Z80_CC_NC:
1482 cond = CC_NZ; 1480 cond = CC_NZ;
1483 case Z80_CC_C: 1481 case Z80_CC_C:
1484 dst = cmp_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); 1482 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1485 break; 1483 break;
1486 case Z80_CC_PO: 1484 case Z80_CC_PO:
1487 cond = CC_NZ; 1485 cond = CC_NZ;
1488 case Z80_CC_PE: 1486 case Z80_CC_PE:
1489 dst = cmp_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B); 1487 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
1490 break; 1488 break;
1491 case Z80_CC_P: 1489 case Z80_CC_P:
1492 cond = CC_NZ; 1490 cond = CC_NZ;
1493 case Z80_CC_M: 1491 case Z80_CC_M:
1494 dst = cmp_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_S), SZ_B); 1492 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_S), SZ_B);
1495 break; 1493 break;
1496 } 1494 }
1497 uint8_t *no_call_off = dst+1; 1495 uint8_t *no_call_off = code->cur+1;
1498 dst = jcc(dst, cond, dst+2); 1496 jcc(code, cond, code->cur+2);
1499 dst = cycles(&opts->gen, 1);//Last of the above T states takes an extra cycle in the true case 1497 cycles(&opts->gen, 1);//Last of the above T states takes an extra cycle in the true case
1500 dst = sub_ir(dst, 2, opts->regs[Z80_SP], SZ_W); 1498 sub_ir(code, 2, opts->regs[Z80_SP], SZ_W);
1501 dst = mov_ir(dst, address + 3, opts->gen.scratch1, SZ_W); 1499 mov_ir(code, address + 3, opts->gen.scratch1, SZ_W);
1502 dst = mov_rr(dst, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); 1500 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
1503 dst = call(dst, (uint8_t *)z80_write_word_highfirst);//T States: 3, 3 1501 call(code, (uint8_t *)z80_write_word_highfirst);//T States: 3, 3
1504 if (inst->immed < 0x4000) { 1502 if (inst->immed < 0x4000) {
1505 uint8_t * call_dst = z80_get_native_address(context, inst->immed); 1503 code_ptr call_dst = z80_get_native_address(context, inst->immed);
1506 if (!call_dst) { 1504 if (!call_dst) {
1507 opts->deferred = defer_address(opts->deferred, inst->immed, dst + 1); 1505 opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
1508 //fake address to force large displacement 1506 //fake address to force large displacement
1509 call_dst = dst + 256; 1507 call_dst + 256;
1510 } 1508 }
1511 dst = jmp(dst, call_dst); 1509 jmp(code, call_dst);
1512 } else { 1510 } else {
1513 dst = mov_ir(dst, inst->immed, opts->gen.scratch1, SZ_W); 1511 mov_ir(code, inst->immed, opts->gen.scratch1, SZ_W);
1514 dst = call(dst, (uint8_t *)z80_native_addr); 1512 call(code, (uint8_t *)z80_native_addr);
1515 dst = jmp_r(dst, opts->gen.scratch1); 1513 jmp_r(code, opts->gen.scratch1);
1516 } 1514 }
1517 *no_call_off = dst - (no_call_off+1); 1515 *no_call_off = code->cur - (no_call_off+1);
1518 break; 1516 break;
1519 case Z80_RET: 1517 case Z80_RET:
1520 dst = cycles(&opts->gen, 4);//T States: 4 1518 cycles(&opts->gen, 4);//T States: 4
1521 dst = mov_rr(dst, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); 1519 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
1522 dst = call(dst, (uint8_t *)z80_read_word);//T STates: 3, 3 1520 call(code, (uint8_t *)z80_read_word);//T STates: 3, 3
1523 dst = add_ir(dst, 2, opts->regs[Z80_SP], SZ_W); 1521 add_ir(code, 2, opts->regs[Z80_SP], SZ_W);
1524 dst = call(dst, (uint8_t *)z80_native_addr); 1522 call(code, (uint8_t *)z80_native_addr);
1525 dst = jmp_r(dst, opts->gen.scratch1); 1523 jmp_r(code, opts->gen.scratch1);
1526 break; 1524 break;
1527 case Z80_RETCC: { 1525 case Z80_RETCC: {
1528 dst = cycles(&opts->gen, 5);//T States: 5 1526 cycles(&opts->gen, 5);//T States: 5
1529 uint8_t cond = CC_Z; 1527 uint8_t cond = CC_Z;
1530 switch (inst->reg) 1528 switch (inst->reg)
1531 { 1529 {
1532 case Z80_CC_NZ: 1530 case Z80_CC_NZ:
1533 cond = CC_NZ; 1531 cond = CC_NZ;
1534 case Z80_CC_Z: 1532 case Z80_CC_Z:
1535 dst = cmp_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_Z), SZ_B); 1533 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_Z), SZ_B);
1536 break; 1534 break;
1537 case Z80_CC_NC: 1535 case Z80_CC_NC:
1538 cond = CC_NZ; 1536 cond = CC_NZ;
1539 case Z80_CC_C: 1537 case Z80_CC_C:
1540 dst = cmp_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); 1538 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1541 break; 1539 break;
1542 case Z80_CC_PO: 1540 case Z80_CC_PO:
1543 cond = CC_NZ; 1541 cond = CC_NZ;
1544 case Z80_CC_PE: 1542 case Z80_CC_PE:
1545 dst = cmp_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B); 1543 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
1546 break; 1544 break;
1547 case Z80_CC_P: 1545 case Z80_CC_P:
1548 cond = CC_NZ; 1546 cond = CC_NZ;
1549 case Z80_CC_M: 1547 case Z80_CC_M:
1550 dst = cmp_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_S), SZ_B); 1548 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_S), SZ_B);
1551 break; 1549 break;
1552 } 1550 }
1553 uint8_t *no_call_off = dst+1; 1551 uint8_t *no_call_off = code->cur+1;
1554 dst = jcc(dst, cond, dst+2); 1552 jcc(code, cond, code->cur+2);
1555 dst = mov_rr(dst, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); 1553 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
1556 dst = call(dst, (uint8_t *)z80_read_word);//T STates: 3, 3 1554 call(code, (uint8_t *)z80_read_word);//T STates: 3, 3
1557 dst = add_ir(dst, 2, opts->regs[Z80_SP], SZ_W); 1555 add_ir(code, 2, opts->regs[Z80_SP], SZ_W);
1558 dst = call(dst, (uint8_t *)z80_native_addr); 1556 call(code, (uint8_t *)z80_native_addr);
1559 dst = jmp_r(dst, opts->gen.scratch1); 1557 jmp_r(code, opts->gen.scratch1);
1560 *no_call_off = dst - (no_call_off+1); 1558 *no_call_off = code->cur - (no_call_off+1);
1561 break; 1559 break;
1562 } 1560 }
1563 case Z80_RETI: 1561 case Z80_RETI:
1564 //For some systems, this may need a callback for signalling interrupt routine completion 1562 //For some systems, this may need a callback for signalling interrupt routine completion
1565 dst = cycles(&opts->gen, 8);//T States: 4, 4 1563 cycles(&opts->gen, 8);//T States: 4, 4
1566 dst = mov_rr(dst, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); 1564 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
1567 dst = call(dst, (uint8_t *)z80_read_word);//T STates: 3, 3 1565 call(code, (uint8_t *)z80_read_word);//T STates: 3, 3
1568 dst = add_ir(dst, 2, opts->regs[Z80_SP], SZ_W); 1566 add_ir(code, 2, opts->regs[Z80_SP], SZ_W);
1569 dst = call(dst, (uint8_t *)z80_native_addr); 1567 call(code, (uint8_t *)z80_native_addr);
1570 dst = jmp_r(dst, opts->gen.scratch1); 1568 jmp_r(code, opts->gen.scratch1);
1571 break; 1569 break;
1572 case Z80_RETN: 1570 case Z80_RETN:
1573 dst = cycles(&opts->gen, 8);//T States: 4, 4 1571 cycles(&opts->gen, 8);//T States: 4, 4
1574 dst = mov_rdisp8r(dst, opts->gen.context_reg, offsetof(z80_context, iff2), opts->gen.scratch2, SZ_B); 1572 mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, iff2), opts->gen.scratch2, SZ_B);
1575 dst = mov_rr(dst, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); 1573 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
1576 dst = mov_rrdisp8(dst, opts->gen.scratch2, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B); 1574 mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B);
1577 dst = call(dst, (uint8_t *)z80_read_word);//T STates: 3, 3 1575 call(code, (uint8_t *)z80_read_word);//T STates: 3, 3
1578 dst = add_ir(dst, 2, opts->regs[Z80_SP], SZ_W); 1576 add_ir(code, 2, opts->regs[Z80_SP], SZ_W);
1579 dst = call(dst, (uint8_t *)z80_native_addr); 1577 call(code, (uint8_t *)z80_native_addr);
1580 dst = jmp_r(dst, opts->gen.scratch1); 1578 jmp_r(code, opts->gen.scratch1);
1581 break; 1579 break;
1582 case Z80_RST: { 1580 case Z80_RST: {
1583 //RST is basically CALL to an address in page 0 1581 //RST is basically CALL to an address in page 0
1584 dst = cycles(&opts->gen, 5);//T States: 5 1582 cycles(&opts->gen, 5);//T States: 5
1585 dst = sub_ir(dst, 2, opts->regs[Z80_SP], SZ_W); 1583 sub_ir(code, 2, opts->regs[Z80_SP], SZ_W);
1586 dst = mov_ir(dst, address + 1, opts->gen.scratch1, SZ_W); 1584 mov_ir(code, address + 1, opts->gen.scratch1, SZ_W);
1587 dst = mov_rr(dst, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); 1585 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
1588 dst = call(dst, (uint8_t *)z80_write_word_highfirst);//T States: 3, 3 1586 call(code, (uint8_t *)z80_write_word_highfirst);//T States: 3, 3
1589 uint8_t * call_dst = z80_get_native_address(context, inst->immed); 1587 code_ptr call_dst = z80_get_native_address(context, inst->immed);
1590 if (!call_dst) { 1588 if (!call_dst) {
1591 opts->deferred = defer_address(opts->deferred, inst->immed, dst + 1); 1589 opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
1592 //fake address to force large displacement 1590 //fake address to force large displacement
1593 call_dst = dst + 256; 1591 call_dst + 256;
1594 } 1592 }
1595 dst = jmp(dst, call_dst); 1593 jmp(code, call_dst);
1596 break; 1594 break;
1597 } 1595 }
1598 case Z80_IN: 1596 case Z80_IN:
1599 dst = cycles(&opts->gen, inst->reg == Z80_A ? 7 : 8);//T States: 4 3/4 1597 cycles(&opts->gen, inst->reg == Z80_A ? 7 : 8);//T States: 4 3/4
1600 if (inst->addr_mode == Z80_IMMED_INDIRECT) { 1598 if (inst->addr_mode == Z80_IMMED_INDIRECT) {
1601 dst = mov_ir(dst, inst->immed, opts->gen.scratch1, SZ_B); 1599 mov_ir(code, inst->immed, opts->gen.scratch1, SZ_B);
1602 } else { 1600 } else {
1603 dst = mov_rr(dst, opts->regs[Z80_C], opts->gen.scratch1, SZ_B); 1601 mov_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
1604 } 1602 }
1605 dst = call(dst, (uint8_t *)z80_io_read); 1603 call(code, (uint8_t *)z80_io_read);
1606 translate_z80_reg(inst, &dst_op, dst, opts); 1604 translate_z80_reg(inst, &dst_op, opts);
1607 dst = mov_rr(dst, opts->gen.scratch1, dst_op.base, SZ_B); 1605 mov_rr(code, opts->gen.scratch1, dst_op.base, SZ_B);
1608 dst = z80_save_reg(dst, inst, opts); 1606 z80_save_reg(inst, opts);
1609 break; 1607 break;
1610 /*case Z80_INI: 1608 /*case Z80_INI:
1611 case Z80_INIR: 1609 case Z80_INIR:
1612 case Z80_IND: 1610 case Z80_IND:
1613 case Z80_INDR:*/ 1611 case Z80_INDR:*/
1614 case Z80_OUT: 1612 case Z80_OUT:
1615 dst = cycles(&opts->gen, inst->reg == Z80_A ? 7 : 8);//T States: 4 3/4 1613 cycles(&opts->gen, inst->reg == Z80_A ? 7 : 8);//T States: 4 3/4
1616 if ((inst->addr_mode & 0x1F) == Z80_IMMED_INDIRECT) { 1614 if ((inst->addr_mode & 0x1F) == Z80_IMMED_INDIRECT) {
1617 dst = mov_ir(dst, inst->immed, opts->gen.scratch2, SZ_B); 1615 mov_ir(code, inst->immed, opts->gen.scratch2, SZ_B);
1618 } else { 1616 } else {
1619 dst = mov_rr(dst, opts->regs[Z80_C], opts->gen.scratch2, SZ_B); 1617 mov_rr(code, opts->regs[Z80_C], opts->gen.scratch2, SZ_B);
1620 } 1618 }
1621 translate_z80_reg(inst, &src_op, dst, opts); 1619 translate_z80_reg(inst, &src_op, opts);
1622 dst = mov_rr(dst, dst_op.base, opts->gen.scratch1, SZ_B); 1620 mov_rr(code, dst_op.base, opts->gen.scratch1, SZ_B);
1623 dst = call(dst, (uint8_t *)z80_io_write); 1621 call(code, (uint8_t *)z80_io_write);
1624 dst = z80_save_reg(dst, inst, opts); 1622 z80_save_reg(inst, opts);
1625 break; 1623 break;
1626 /*case Z80_OUTI: 1624 /*case Z80_OUTI:
1627 case Z80_OTIR: 1625 case Z80_OTIR:
1628 case Z80_OUTD: 1626 case Z80_OUTD:
1629 case Z80_OTDR:*/ 1627 case Z80_OTDR:*/
1635 fwrite(context->mem_pointers[0], 1, 8 * 1024, f); 1633 fwrite(context->mem_pointers[0], 1, 8 * 1024, f);
1636 fclose(f); 1634 fclose(f);
1637 exit(1); 1635 exit(1);
1638 } 1636 }
1639 } 1637 }
1640 return dst;
1641 } 1638 }
1642 1639
1643 uint8_t * z80_get_native_address(z80_context * context, uint32_t address) 1640 uint8_t * z80_get_native_address(z80_context * context, uint32_t address)
1644 { 1641 {
1645 native_map_slot *map; 1642 native_map_slot *map;
1664 uint8_t z80_get_native_inst_size(z80_options * opts, uint32_t address) 1661 uint8_t z80_get_native_inst_size(z80_options * opts, uint32_t address)
1665 { 1662 {
1666 if (address >= 0x4000) { 1663 if (address >= 0x4000) {
1667 return 0; 1664 return 0;
1668 } 1665 }
1669 return opts->ram_inst_sizes[address & 0x1FFF]; 1666 return opts->gen.ram_inst_sizes[0][address & 0x1FFF];
1670 } 1667 }
1671 1668
1672 void z80_map_native_address(z80_context * context, uint32_t address, uint8_t * native_address, uint8_t size, uint8_t native_size) 1669 void z80_map_native_address(z80_context * context, uint32_t address, uint8_t * native_address, uint8_t size, uint8_t native_size)
1673 { 1670 {
1674 uint32_t orig_address = address; 1671 uint32_t orig_address = address;
1675 native_map_slot *map; 1672 native_map_slot *map;
1676 z80_options * opts = context->options; 1673 z80_options * opts = context->options;
1677 if (address < 0x4000) { 1674 if (address < 0x4000) {
1678 address &= 0x1FFF; 1675 address &= 0x1FFF;
1679 map = context->static_code_map; 1676 map = context->static_code_map;
1680 opts->ram_inst_sizes[address] = native_size; 1677 opts->gen.ram_inst_sizes[0][address] = native_size;
1681 context->ram_code_flags[(address & 0x1C00) >> 10] |= 1 << ((address & 0x380) >> 7); 1678 context->ram_code_flags[(address & 0x1C00) >> 10] |= 1 << ((address & 0x380) >> 7);
1682 context->ram_code_flags[((address + size) & 0x1C00) >> 10] |= 1 << (((address + size) & 0x380) >> 7); 1679 context->ram_code_flags[((address + size) & 0x1C00) >> 10] |= 1 << (((address + size) & 0x380) >> 7);
1683 } else if (address >= 0x8000) { 1680 } else if (address >= 0x8000) {
1684 address &= 0x7FFF; 1681 address &= 0x7FFF;
1685 map = context->banked_code_map + context->bank_reg; 1682 map = context->banked_code_map + context->bank_reg;
1733 1730
1734 z80_context * z80_handle_code_write(uint32_t address, z80_context * context) 1731 z80_context * z80_handle_code_write(uint32_t address, z80_context * context)
1735 { 1732 {
1736 uint32_t inst_start = z80_get_instruction_start(context->static_code_map, address); 1733 uint32_t inst_start = z80_get_instruction_start(context->static_code_map, address);
1737 if (inst_start != INVALID_INSTRUCTION_START) { 1734 if (inst_start != INVALID_INSTRUCTION_START) {
1738 uint8_t * dst = z80_get_native_address(context, inst_start); 1735 code_ptr dst = z80_get_native_address(context, inst_start);
1739 dprintf("patching code at %p for Z80 instruction at %X due to write to %X\n", dst, inst_start, address); 1736 code_info code = {dst, dst+16};
1740 dst = mov_ir(dst, inst_start, opts->gen.scratch1, SZ_D); 1737 z80_options * opts = context->options;
1741 dst = call(dst, (uint8_t *)z80_retrans_stub); 1738 dprintf("patching code at %p for Z80 instruction at %X due to write to %X\n", code, inst_start, address);
1739 mov_ir(&code, inst_start, opts->gen.scratch1, SZ_D);
1740 call(&code, (uint8_t *)z80_retrans_stub);
1742 } 1741 }
1743 return context; 1742 return context;
1744 } 1743 }
1745 1744
1746 uint8_t * z80_get_native_address_trans(z80_context * context, uint32_t address) 1745 uint8_t * z80_get_native_address_trans(z80_context * context, uint32_t address)
1757 } 1756 }
1758 1757
1759 void z80_handle_deferred(z80_context * context) 1758 void z80_handle_deferred(z80_context * context)
1760 { 1759 {
1761 z80_options * opts = context->options; 1760 z80_options * opts = context->options;
1762 process_deferred(&opts->deferred, context, (native_addr_func)z80_get_native_address); 1761 process_deferred(&opts->gen.deferred, context, (native_addr_func)z80_get_native_address);
1763 if (opts->deferred) { 1762 if (opts->gen.deferred) {
1764 translate_z80_stream(context, opts->deferred->address); 1763 translate_z80_stream(context, opts->gen.deferred->address);
1765 } 1764 }
1766 } 1765 }
1767 1766
1768 void * z80_retranslate_inst(uint32_t address, z80_context * context, uint8_t * orig_start) 1767 void * z80_retranslate_inst(uint32_t address, z80_context * context, uint8_t * orig_start)
1769 { 1768 {
1770 char disbuf[80]; 1769 char disbuf[80];
1771 z80_options * opts = context->options; 1770 z80_options * opts = context->options;
1772 uint8_t orig_size = z80_get_native_inst_size(opts, address); 1771 uint8_t orig_size = z80_get_native_inst_size(opts, address);
1773 uint32_t orig = address; 1772 uint32_t orig = address;
1774 address &= 0x1FFF; 1773 address &= 0x1FFF;
1775 uint8_t * dst = opts->cur_code; 1774 code_info *code = &opts->gen.code;
1776 uint8_t * dst_end = opts->code_end;
1777 uint8_t *after, *inst = context->mem_pointers[0] + address; 1775 uint8_t *after, *inst = context->mem_pointers[0] + address;
1778 z80inst instbuf; 1776 z80inst instbuf;
1779 dprintf("Retranslating code at Z80 address %X, native address %p\n", address, orig_start); 1777 dprintf("Retranslating code at Z80 address %X, native address %p\n", address, orig_start);
1780 after = z80_decode(inst, &instbuf); 1778 after = z80_decode(inst, &instbuf);
1781 #ifdef DO_DEBUG_PRINT 1779 #ifdef DO_DEBUG_PRINT
1785 } else { 1783 } else {
1786 printf("%X\t%s\n", address, disbuf); 1784 printf("%X\t%s\n", address, disbuf);
1787 } 1785 }
1788 #endif 1786 #endif
1789 if (orig_size != ZMAX_NATIVE_SIZE) { 1787 if (orig_size != ZMAX_NATIVE_SIZE) {
1790 if (dst_end - dst < ZMAX_NATIVE_SIZE) { 1788 code_ptr start = code->cur;
1791 size_t size = 1024*1024; 1789 deferred_addr * orig_deferred = opts->gen.deferred;
1792 dst = alloc_code(&size); 1790 translate_z80inst(&instbuf, context, address);
1793 opts->code_end = dst_end = dst + size; 1791 /*
1794 opts->cur_code = dst;
1795 }
1796 deferred_addr * orig_deferred = opts->deferred;
1797 uint8_t * native_end = translate_z80inst(&instbuf, dst, context, address);
1798 if ((native_end - dst) <= orig_size) { 1792 if ((native_end - dst) <= orig_size) {
1799 uint8_t * native_next = z80_get_native_address(context, address + after-inst); 1793 uint8_t * native_next = z80_get_native_address(context, address + after-inst);
1800 if (native_next && ((native_next == orig_start + orig_size) || (orig_size - (native_end - dst)) > 5)) { 1794 if (native_next && ((native_next == orig_start + orig_size) || (orig_size - (native_end - dst)) > 5)) {
1801 remove_deferred_until(&opts->deferred, orig_deferred); 1795 remove_deferred_until(&opts->gen.deferred, orig_deferred);
1802 native_end = translate_z80inst(&instbuf, orig_start, context, address); 1796 native_end = translate_z80inst(&instbuf, orig_start, context, address);
1803 if (native_next == orig_start + orig_size && (native_next-native_end) < 2) { 1797 if (native_next == orig_start + orig_size && (native_next-native_end) < 2) {
1804 while (native_end < orig_start + orig_size) { 1798 while (native_end < orig_start + orig_size) {
1805 *(native_end++) = 0x90; //NOP 1799 *(native_end++) = 0x90; //NOP
1806 } 1800 }
1808 jmp(native_end, native_next); 1802 jmp(native_end, native_next);
1809 } 1803 }
1810 z80_handle_deferred(context); 1804 z80_handle_deferred(context);
1811 return orig_start; 1805 return orig_start;
1812 } 1806 }
1813 } 1807 }*/
1814 z80_map_native_address(context, address, dst, after-inst, ZMAX_NATIVE_SIZE); 1808 z80_map_native_address(context, address, start, after-inst, ZMAX_NATIVE_SIZE);
1815 opts->cur_code = dst+ZMAX_NATIVE_SIZE; 1809 code_info tmp_code = {orig_start, orig_start + 16};
1816 jmp(orig_start, dst); 1810 jmp(&tmp_code, start);
1817 if (!z80_is_terminal(&instbuf)) { 1811 if (!z80_is_terminal(&instbuf)) {
1818 jmp(native_end, z80_get_native_address_trans(context, address + after-inst)); 1812 jmp(code, z80_get_native_address_trans(context, address + after-inst));
1819 } 1813 }
1814 code->cur = start + ZMAX_NATIVE_SIZE;
1820 z80_handle_deferred(context); 1815 z80_handle_deferred(context);
1821 return dst; 1816 return start;
1822 } else { 1817 } else {
1823 dst = translate_z80inst(&instbuf, orig_start, context, address); 1818 code_info tmp_code = *code;
1819 code->cur = orig_start;
1820 code->last = orig_start + ZMAX_NATIVE_SIZE;
1821 translate_z80inst(&instbuf, context, address);
1824 if (!z80_is_terminal(&instbuf)) { 1822 if (!z80_is_terminal(&instbuf)) {
1825 dst = jmp(dst, z80_get_native_address_trans(context, address + after-inst)); 1823 jmp(code, z80_get_native_address_trans(context, address + after-inst));
1826 } 1824 }
1825 *code = tmp_code;
1827 z80_handle_deferred(context); 1826 z80_handle_deferred(context);
1828 return orig_start; 1827 return orig_start;
1829 } 1828 }
1830 } 1829 }
1831 1830
1848 while (encoded != NULL) 1847 while (encoded != NULL)
1849 { 1848 {
1850 z80inst inst; 1849 z80inst inst;
1851 dprintf("translating Z80 code at address %X\n", address); 1850 dprintf("translating Z80 code at address %X\n", address);
1852 do { 1851 do {
1853 if (opts->code_end-opts->cur_code < ZMAX_NATIVE_SIZE) {
1854 if (opts->code_end-opts->cur_code < 5) {
1855 puts("out of code memory, not enough space for jmp to next chunk");
1856 exit(1);
1857 }
1858 size_t size = 1024*1024;
1859 opts->cur_code = alloc_code(&size);
1860 opts->code_end = opts->cur_code + size;
1861 jmp(opts->cur_code, opts->cur_code);
1862 }
1863 if (address > 0x4000 && address < 0x8000) { 1852 if (address > 0x4000 && address < 0x8000) {
1864 opts->cur_code = xor_rr(opts->cur_code, RDI, RDI, SZ_D); 1853 xor_rr(&opts->gen.code, RDI, RDI, SZ_D);
1865 opts->cur_code = call(opts->cur_code, (uint8_t *)exit); 1854 call(&opts->gen.code, (uint8_t *)exit);
1866 break; 1855 break;
1867 } 1856 }
1868 uint8_t * existing = z80_get_native_address(context, address); 1857 uint8_t * existing = z80_get_native_address(context, address);
1869 if (existing) { 1858 if (existing) {
1870 opts->cur_code = jmp(opts->cur_code, existing); 1859 jmp(&opts->gen.code, existing);
1871 break; 1860 break;
1872 } 1861 }
1873 next = z80_decode(encoded, &inst); 1862 next = z80_decode(encoded, &inst);
1874 #ifdef DO_DEBUG_PRINT 1863 #ifdef DO_DEBUG_PRINT
1875 z80_disasm(&inst, disbuf, address); 1864 z80_disasm(&inst, disbuf, address);
1877 printf("%X\t%s(%d)\n", address, disbuf, inst.immed); 1866 printf("%X\t%s(%d)\n", address, disbuf, inst.immed);
1878 } else { 1867 } else {
1879 printf("%X\t%s\n", address, disbuf); 1868 printf("%X\t%s\n", address, disbuf);
1880 } 1869 }
1881 #endif 1870 #endif
1882 uint8_t *after = translate_z80inst(&inst, opts->cur_code, context, address); 1871 code_ptr start = opts->gen.code.cur;
1883 z80_map_native_address(context, address, opts->cur_code, next-encoded, after - opts->cur_code); 1872 translate_z80inst(&inst, context, address);
1884 opts->cur_code = after; 1873 z80_map_native_address(context, address, start, next-encoded, opts->gen.code.cur - start);
1885 address += next-encoded; 1874 address += next-encoded;
1886 if (address > 0xFFFF) { 1875 if (address > 0xFFFF) {
1887 address &= 0xFFFF; 1876 address &= 0xFFFF;
1888 1877
1889 } else { 1878 } else {
1890 encoded = next; 1879 encoded = next;
1891 } 1880 }
1892 } while (!z80_is_terminal(&inst)); 1881 } while (!z80_is_terminal(&inst));
1893 process_deferred(&opts->deferred, context, (native_addr_func)z80_get_native_address); 1882 process_deferred(&opts->gen.deferred, context, (native_addr_func)z80_get_native_address);
1894 if (opts->deferred) { 1883 if (opts->gen.deferred) {
1895 address = opts->deferred->address; 1884 address = opts->gen.deferred->address;
1896 dprintf("defferred address: %X\n", address); 1885 dprintf("defferred address: %X\n", address);
1897 if (address < 0x4000) { 1886 if (address < 0x4000) {
1898 encoded = context->mem_pointers[0] + (address & 0x1FFF); 1887 encoded = context->mem_pointers[0] + (address & 0x1FFF);
1899 } else if (address > 0x8000 && context->mem_pointers[1]) { 1888 } else if (address > 0x8000 && context->mem_pointers[1]) {
1900 encoded = context->mem_pointers[1] + (address & 0x7FFF); 1889 encoded = context->mem_pointers[1] + (address & 0x7FFF);
1951 options->gen.scratch2 = R14; 1940 options->gen.scratch2 = R14;
1952 1941
1953 options->gen.native_code_map = malloc(sizeof(native_map_slot)); 1942 options->gen.native_code_map = malloc(sizeof(native_map_slot));
1954 memset(options->gen.native_code_map, 0, sizeof(native_map_slot)); 1943 memset(options->gen.native_code_map, 0, sizeof(native_map_slot));
1955 options->gen.deferred = NULL; 1944 options->gen.deferred = NULL;
1956 options->gen.ram_inst_sizes = malloc(sizeof(uint8_t) * 0x2000); 1945 options->gen.ram_inst_sizes = malloc(sizeof(uint8_t) * 0x2000 + sizeof(uint8_t *));
1957 memset(options->ram_inst_sizes, 0, sizeof(uint8_t) * 0x2000); 1946 options->gen.ram_inst_sizes[0] = (uint8_t *)(options->gen.ram_inst_sizes + 1);
1947 memset(options->gen.ram_inst_sizes[0], 0, sizeof(uint8_t) * 0x2000);
1958 1948
1959 code_info *code = &options->gen.code; 1949 code_info *code = &options->gen.code;
1960 init_code_info(code); 1950 init_code_info(code);
1961 1951
1962 options->save_context_scratch = code->cur; 1952 options->save_context_scratch = code->cur;
2026 pop_r(code, RBX); //return address in translated code 2016 pop_r(code, RBX); //return address in translated code
2027 sub_ir(code, 5, RAX, SZ_PTR); //adjust return address to point to the call that got us here 2017 sub_ir(code, 5, RAX, SZ_PTR); //adjust return address to point to the call that got us here
2028 mov_rrdisp(code, RBX, options->gen.context_reg, offsetof(z80_context, extra_pc), SZ_PTR); 2018 mov_rrdisp(code, RBX, options->gen.context_reg, offsetof(z80_context, extra_pc), SZ_PTR);
2029 mov_rrind(code, RAX, options->gen.context_reg, SZ_PTR); 2019 mov_rrind(code, RAX, options->gen.context_reg, SZ_PTR);
2030 //restore callee saved registers 2020 //restore callee saved registers
2031 pop_r(code, R15) 2021 pop_r(code, R15);
2032 pop_r(code, R14) 2022 pop_r(code, R14);
2033 pop_r(code, R13) 2023 pop_r(code, R13);
2034 pop_r(code, R12) 2024 pop_r(code, R12);
2035 pop_r(code, RBP) 2025 pop_r(code, RBP);
2036 pop_r(code, RBX) 2026 pop_r(code, RBX);
2037 *no_sync = code->cur - no_sync; 2027 *no_sync = code->cur - no_sync;
2038 //return to caller of z80_run 2028 //return to caller of z80_run
2039 retn(code); 2029 retn(code);
2040 2030
2041 options->gen.read_8 = gen_mem_fun(&options->gen, chunks, num_chunks, READ_8, NULL); 2031 options->read_8 = gen_mem_fun(&options->gen, chunks, num_chunks, READ_8, NULL);
2042 options->gen.write_8 = gen_mem_fun(&options->gen, chunks, num_chunks, WRITE_8, &options->write_8_noinc); 2032 options->write_8 = gen_mem_fun(&options->gen, chunks, num_chunks, WRITE_8, &options->write_8_noinc);
2043 2033
2044 options->gen.handle_cycle_limit_int = code->cur; 2034 options->gen.handle_cycle_limit_int = code->cur;
2045 cmp_rdispr(code, options->gen.context_reg, offsetof(z80_context, int_cycle), options->gen.cycles, SZ_D); 2035 cmp_rdispr(code, options->gen.context_reg, offsetof(z80_context, int_cycle), options->gen.cycles, SZ_D);
2046 code_ptr skip_int = code->cur+1; 2036 code_ptr skip_int = code->cur+1;
2047 jcc(code, CC_B, skip_int); 2037 jcc(code, CC_B, skip_int);
2048 //set limit to the cycle limit 2038 //set limit to the cycle limit
2049 mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, sync_cycle), options->gen.limit, SZ_D); 2039 mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, sync_cycle), options->gen.limit, SZ_D);
2050 //disable interrupts 2040 //disable interrupts
2051 move_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff1), SZ_B); 2041 mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff1), SZ_B);
2052 move_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff2), SZ_B); 2042 mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff2), SZ_B);
2053 cycles(&options->gen, 7); 2043 cycles(&options->gen, 7);
2054 //save return address (in scratch1) to Z80 stack 2044 //save return address (in scratch1) to Z80 stack
2055 sub_ir(code, 2, options->regs[Z80_SP], SZ_W); 2045 sub_ir(code, 2, options->regs[Z80_SP], SZ_W);
2056 mov_rr(code, options->regs[Z80_SP], options->gen.scratch2, SZ_W); 2046 mov_rr(code, options->regs[Z80_SP], options->gen.scratch2, SZ_W);
2057 //we need to do check_cycles and cycles outside of the write_8 call 2047 //we need to do check_cycles and cycles outside of the write_8 call
2070 shr_ir(code, 8, options->gen.scratch1, SZ_W); 2060 shr_ir(code, 8, options->gen.scratch1, SZ_W);
2071 check_cycles(&options->gen); 2061 check_cycles(&options->gen);
2072 cycles(&options->gen, 3); 2062 cycles(&options->gen, 3);
2073 call(code, options->write_8_noinc); 2063 call(code, options->write_8_noinc);
2074 //dispose of return address as we'll be jumping somewhere else 2064 //dispose of return address as we'll be jumping somewhere else
2075 pop_r(options->gen.scratch2); 2065 pop_r(code, options->gen.scratch2);
2076 //TODO: Support interrupt mode 0 and 2 2066 //TODO: Support interrupt mode 0 and 2
2077 mov_ir(code, 0x38, options->gen.scratch1, SZ_W); 2067 mov_ir(code, 0x38, options->gen.scratch1, SZ_W);
2078 call(code, (code_ptr)z80_native_addr); 2068 call(code, (code_ptr)z80_native_addr);
2079 jmp_r(code, options->gen.scratch1); 2069 jmp_r(code, options->gen.scratch1);
2080 } 2070 }
2100 } 2090 }
2101 2091
2102 void zinsert_breakpoint(z80_context * context, uint16_t address, uint8_t * bp_handler) 2092 void zinsert_breakpoint(z80_context * context, uint16_t address, uint8_t * bp_handler)
2103 { 2093 {
2104 static uint8_t * bp_stub = NULL; 2094 static uint8_t * bp_stub = NULL;
2095 z80_options * opts = context->options;
2105 uint8_t * native = z80_get_native_address_trans(context, address); 2096 uint8_t * native = z80_get_native_address_trans(context, address);
2106 uint8_t * start_native = native; 2097 code_info tmp_code = {native, native+16};
2107 native = mov_ir(native, address, opts->gen.scratch1, SZ_W); 2098 mov_ir(&tmp_code, address, opts->gen.scratch1, SZ_W);
2108 if (!bp_stub) { 2099 if (!bp_stub) {
2109 z80_options * opts = context->options; 2100 code_info *code = &opts->gen.code;
2110 uint8_t * dst = opts->cur_code; 2101 //TODO: do an alloc check here to make sure the prologue length calc works
2111 uint8_t * dst_end = opts->code_end; 2102 bp_stub = code->cur;
2112 if (dst_end - dst < 128) { 2103 call(&tmp_code, bp_stub);
2113 size_t size = 1024*1024;
2114 dst = alloc_code(&size);
2115 opts->code_end = dst_end = dst + size;
2116 }
2117 bp_stub = dst;
2118 native = call(native, bp_stub);
2119 2104
2120 //Calculate length of prologue 2105 //Calculate length of prologue
2121 dst = z80_check_cycles_int(dst, address); 2106 check_cycles_int(&opts->gen, address);
2122 int check_int_size = dst-bp_stub; 2107 int check_int_size = code->cur-bp_stub;
2123 dst = bp_stub; 2108 code->cur = bp_stub;
2124 2109
2125 //Save context and call breakpoint handler 2110 //Save context and call breakpoint handler
2126 dst = call(dst, (uint8_t *)z80_save_context); 2111 call(code, (uint8_t *)z80_save_context);
2127 dst = push_r(dst, opts->gen.scratch1); 2112 push_r(code, opts->gen.scratch1);
2128 dst = mov_rr(dst, opts->gen.context_reg, RDI, SZ_Q); 2113 mov_rr(code, opts->gen.context_reg, RDI, SZ_Q);
2129 dst = mov_rr(dst, opts->gen.scratch1, RSI, SZ_W); 2114 mov_rr(code, opts->gen.scratch1, RSI, SZ_W);
2130 dst = call(dst, bp_handler); 2115 call(code, bp_handler);
2131 dst = mov_rr(dst, RAX, opts->gen.context_reg, SZ_Q); 2116 mov_rr(code, RAX, opts->gen.context_reg, SZ_Q);
2132 //Restore context 2117 //Restore context
2133 dst = call(dst, (uint8_t *)z80_load_context); 2118 call(code, (uint8_t *)z80_load_context);
2134 dst = pop_r(dst, opts->gen.scratch1); 2119 pop_r(code, opts->gen.scratch1);
2135 //do prologue stuff 2120 //do prologue stuff
2136 dst = cmp_rr(dst, opts->gen.cycles, opts->gen.limit, SZ_D); 2121 cmp_rr(code, opts->gen.cycles, opts->gen.limit, SZ_D);
2137 uint8_t * jmp_off = dst+1; 2122 uint8_t * jmp_off = code->cur+1;
2138 dst = jcc(dst, CC_NC, dst + 7); 2123 jcc(code, CC_NC, code->cur + 7);
2139 dst = pop_r(dst, opts->gen.scratch1); 2124 pop_r(code, opts->gen.scratch1);
2140 dst = add_ir(dst, check_int_size - (native-start_native), opts->gen.scratch1, SZ_Q); 2125 add_ir(code, check_int_size - (code->cur-native), opts->gen.scratch1, SZ_Q);
2141 dst = push_r(dst, opts->gen.scratch1); 2126 push_r(code, opts->gen.scratch1);
2142 dst = jmp(dst, (uint8_t *)z80_handle_cycle_limit_int); 2127 jmp(code, (uint8_t *)z80_handle_cycle_limit_int);
2143 *jmp_off = dst - (jmp_off+1); 2128 *jmp_off = code->cur - (jmp_off+1);
2144 //jump back to body of translated instruction 2129 //jump back to body of translated instruction
2145 dst = pop_r(dst, opts->gen.scratch1); 2130 pop_r(code, opts->gen.scratch1);
2146 dst = add_ir(dst, check_int_size - (native-start_native), opts->gen.scratch1, SZ_Q); 2131 add_ir(code, check_int_size - (code->cur-native), opts->gen.scratch1, SZ_Q);
2147 dst = jmp_r(dst, opts->gen.scratch1); 2132 jmp_r(code, opts->gen.scratch1);
2148 opts->cur_code = dst;
2149 } else { 2133 } else {
2150 native = call(native, bp_stub); 2134 call(&tmp_code, bp_stub);
2151 } 2135 }
2152 } 2136 }
2153 2137
2154 void zremove_breakpoint(z80_context * context, uint16_t address) 2138 void zremove_breakpoint(z80_context * context, uint16_t address)
2155 { 2139 {
2156 uint8_t * native = z80_get_native_address(context, address); 2140 uint8_t * native = z80_get_native_address(context, address);
2157 z80_check_cycles_int(native, address); 2141 z80_options * opts = context->options;
2158 } 2142 code_info tmp_code = opts->gen.code;
2159 2143 opts->gen.code.cur = native;
2160 2144 opts->gen.code.last = native + 16;
2145 check_cycles_int(&opts->gen, address);
2146 opts->gen.code = tmp_code;
2147 }
2148
2149