Mercurial > repos > blastem
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 |