main z80_to_x86.c
   1/*
   2 Copyright 2013 Michael Pavone
   3 This file is part of BlastEm.
   4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
   5*/
   6#include "z80inst.h"
   7#include "z80_to_x86.h"
   8#include "gen_x86.h"
   9#include "mem.h"
  10#include "util.h"
  11#include <stdio.h>
  12#include <stdlib.h>
  13#include <stddef.h>
  14#include <string.h>
  15
  16#define MODE_UNUSED (MODE_IMMED-1)
  17#define MAX_MCYCLE_LENGTH 6
  18#define NATIVE_CHUNK_SIZE 1024
  19#define NATIVE_MAP_CHUNKS (0x10000 / NATIVE_CHUNK_SIZE)
  20
  21//#define DO_DEBUG_PRINT
  22
  23#ifdef DO_DEBUG_PRINT
  24#define dprintf printf
  25#else
  26#define dprintf
  27#endif
  28
  29uint32_t zbreakpoint_patch(z80_context * context, uint16_t address, code_ptr dst);
  30void z80_handle_deferred(z80_context * context);
  31
  32uint8_t z80_size(z80inst * inst)
  33{
  34	uint8_t reg = (inst->reg & 0x1F);
  35	if (reg != Z80_UNUSED && reg != Z80_USE_IMMED) {
  36		return reg < Z80_BC ? SZ_B : SZ_W;
  37	}
  38	//TODO: Handle any necessary special cases
  39	return SZ_B;
  40}
  41
  42uint8_t zf_off(uint8_t flag)
  43{
  44	return offsetof(z80_context, flags) + flag;
  45}
  46
  47uint8_t zaf_off(uint8_t flag)
  48{
  49	return offsetof(z80_context, alt_flags) + flag;
  50}
  51
  52uint8_t zr_off(uint8_t reg)
  53{
  54	if (reg > Z80_A) {
  55		reg = z80_low_reg(reg);
  56	}
  57	return offsetof(z80_context, regs) + reg;
  58}
  59
  60uint8_t zar_off(uint8_t reg)
  61{
  62	if (reg > Z80_A) {
  63		reg = z80_low_reg(reg);
  64	}
  65	return offsetof(z80_context, alt_regs) + reg;
  66}
  67
  68void zreg_to_native(z80_options *opts, uint8_t reg, uint8_t native_reg)
  69{
  70	if (opts->regs[reg] >= 0) {
  71		mov_rr(&opts->gen.code, opts->regs[reg], native_reg, reg > Z80_A ? SZ_W : SZ_B);
  72	} else {
  73		mov_rdispr(&opts->gen.code, opts->gen.context_reg, zr_off(reg), native_reg, reg > Z80_A ? SZ_W : SZ_B);
  74	}
  75}
  76
  77void native_to_zreg(z80_options *opts, uint8_t native_reg, uint8_t reg)
  78{
  79	if (opts->regs[reg] >= 0) {
  80		mov_rr(&opts->gen.code, native_reg, opts->regs[reg], reg > Z80_A ? SZ_W : SZ_B);
  81	} else {
  82		mov_rrdisp(&opts->gen.code, native_reg, opts->gen.context_reg, zr_off(reg), reg > Z80_A ? SZ_W : SZ_B);
  83	}
  84}
  85
  86void translate_z80_reg(z80inst * inst, host_ea * ea, z80_options * opts)
  87{
  88	code_info *code = &opts->gen.code;
  89	if (inst->reg == Z80_USE_IMMED) {
  90		ea->mode = MODE_IMMED;
  91		ea->disp = inst->immed;
  92	} else if ((inst->reg & 0x1F) == Z80_UNUSED) {
  93		ea->mode = MODE_UNUSED;
  94	} else {
  95		ea->mode = MODE_REG_DIRECT;
  96		if (inst->reg == Z80_IYH && opts->regs[Z80_IYL] >= 0) {
  97			if ((inst->addr_mode & 0x1F) == Z80_REG && inst->ea_reg == Z80_IYL) {
  98				mov_rr(code, opts->regs[Z80_IY], opts->gen.scratch1, SZ_W);
  99				ror_ir(code, 8, opts->gen.scratch1, SZ_W);
 100				ea->base = opts->gen.scratch1;
 101			} else {
 102				ea->base = opts->regs[Z80_IYL];
 103				ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
 104			}
 105		} else if(opts->regs[inst->reg] >= 0) {
 106			ea->base = opts->regs[inst->reg];
 107			if (ea->base >= AH && ea->base <= BH) {
 108				if ((inst->addr_mode & 0x1F) == Z80_REG) {
 109					uint8_t other_reg = opts->regs[inst->ea_reg];
 110					if (other_reg >= R8 || (other_reg >= RSP && other_reg <= RDI)) {
 111						//we can't mix an *H reg with a register that requires the REX prefix
 112						ea->base = opts->regs[z80_low_reg(inst->reg)];
 113						ror_ir(code, 8, ea->base, SZ_W);
 114					}
 115				} else if((inst->addr_mode & 0x1F) != Z80_UNUSED && (inst->addr_mode & 0x1F) != Z80_IMMED) {
 116					//temp regs require REX prefix too
 117					ea->base = opts->regs[z80_low_reg(inst->reg)];
 118					ror_ir(code, 8, ea->base, SZ_W);
 119				}
 120			}
 121		} else {
 122			ea->mode = MODE_REG_DISPLACE8;
 123			ea->base = opts->gen.context_reg;
 124			ea->disp = zr_off(inst->reg);
 125		}
 126	}
 127}
 128
 129void z80_save_reg(z80inst * inst, z80_options * opts)
 130{
 131	code_info *code = &opts->gen.code;
 132	if (inst->reg == Z80_USE_IMMED || inst->reg == Z80_UNUSED) {
 133		return;
 134	}
 135	if (inst->reg == Z80_IYH && opts->regs[Z80_IYL] >= 0) {
 136		if ((inst->addr_mode & 0x1F) == Z80_REG && inst->ea_reg == Z80_IYL) {
 137			ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
 138			mov_rr(code, opts->gen.scratch1, opts->regs[Z80_IYL], SZ_B);
 139			ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
 140		} else {
 141			ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
 142		}
 143	} else if (opts->regs[inst->reg] >= AH && opts->regs[inst->reg] <= BH) {
 144		if ((inst->addr_mode & 0x1F) == Z80_REG) {
 145			uint8_t other_reg = opts->regs[inst->ea_reg];
 146			if (other_reg >= R8 || (other_reg >= RSP && other_reg <= RDI)) {
 147				//we can't mix an *H reg with a register that requires the REX prefix
 148				ror_ir(code, 8, opts->regs[z80_low_reg(inst->reg)], SZ_W);
 149			}
 150		} else if((inst->addr_mode & 0x1F) != Z80_UNUSED && (inst->addr_mode & 0x1F) != Z80_IMMED) {
 151			//temp regs require REX prefix too
 152			ror_ir(code, 8, opts->regs[z80_low_reg(inst->reg)], SZ_W);
 153		}
 154	}
 155}
 156
 157void translate_z80_ea(z80inst * inst, host_ea * ea, z80_options * opts, uint8_t read, uint8_t modify)
 158{
 159	code_info *code = &opts->gen.code;
 160	uint8_t size, areg;
 161	int8_t reg;
 162	ea->mode = MODE_REG_DIRECT;
 163	areg = read ? opts->gen.scratch1 : opts->gen.scratch2;
 164	switch(inst->addr_mode & 0x1F)
 165	{
 166	case Z80_REG:
 167		if (inst->ea_reg == Z80_IYH && opts->regs[Z80_IYL] >= 0) {
 168			if (inst->reg == Z80_IYL) {
 169				mov_rr(code, opts->regs[Z80_IY], opts->gen.scratch1, SZ_W);
 170				ror_ir(code, 8, opts->gen.scratch1, SZ_W);
 171				ea->base = opts->gen.scratch1;
 172			} else {
 173				ea->base = opts->regs[Z80_IYL];
 174				ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
 175			}
 176		} else if(opts->regs[inst->ea_reg] >= 0) {
 177			ea->base = opts->regs[inst->ea_reg];
 178			if (ea->base >= AH && ea->base <= BH && inst->reg != Z80_UNUSED && inst->reg != Z80_USE_IMMED) {
 179				uint8_t other_reg = opts->regs[inst->reg];
 180#ifdef X86_64
 181				if (other_reg >= R8 || (other_reg >= RSP && other_reg <= RDI)) {
 182					//we can't mix an *H reg with a register that requires the REX prefix
 183					ea->base = opts->regs[z80_low_reg(inst->ea_reg)];
 184					ror_ir(code, 8, ea->base, SZ_W);
 185				}
 186#endif
 187			}
 188		} else {
 189			ea->mode = MODE_REG_DISPLACE8;
 190			ea->base = opts->gen.context_reg;
 191			ea->disp = zr_off(inst->ea_reg);
 192		}
 193		break;
 194	case Z80_REG_INDIRECT:
 195		zreg_to_native(opts, inst->ea_reg, areg);
 196		size = z80_size(inst);
 197		if (read) {
 198			if (modify) {
 199				//push_r(code, opts->gen.scratch1);
 200				mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_W);
 201			}
 202			if (size == SZ_B) {
 203				call(code, opts->read_8);
 204			} else {
 205				call(code, opts->read_16);
 206			}
 207		}
 208		ea->base = opts->gen.scratch1;
 209		break;
 210	case Z80_IMMED:
 211		ea->mode = MODE_IMMED;
 212		ea->disp = inst->immed;
 213		break;
 214	case Z80_IMMED_INDIRECT:
 215		mov_ir(code, inst->immed, areg, SZ_W);
 216		size = z80_size(inst);
 217		if (read) {
 218			/*if (modify) {
 219				push_r(code, opts->gen.scratch1);
 220			}*/
 221			if (size == SZ_B) {
 222				call(code, opts->read_8);
 223			} else {
 224				call(code, opts->read_16);
 225			}
 226		}
 227		ea->base = opts->gen.scratch1;
 228		break;
 229	case Z80_IX_DISPLACE:
 230	case Z80_IY_DISPLACE:
 231		zreg_to_native(opts, (inst->addr_mode & 0x1F) == Z80_IX_DISPLACE ? Z80_IX : Z80_IY, areg);
 232		add_ir(code, inst->ea_reg & 0x80 ? inst->ea_reg - 256 : inst->ea_reg, areg, SZ_W);
 233		size = z80_size(inst);
 234		if (read) {
 235			if (modify) {
 236				//push_r(code, opts->gen.scratch1);
 237				mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_W);
 238			}
 239			if (size == SZ_B) {
 240				call(code, opts->read_8);
 241			} else {
 242				call(code, opts->read_16);
 243			}
 244		}
 245		ea->base = opts->gen.scratch1;
 246		break;
 247	case Z80_UNUSED:
 248		ea->mode = MODE_UNUSED;
 249		break;
 250	default:
 251		fatal_error("Unrecognized Z80 addressing mode %d\n", inst->addr_mode & 0x1F);
 252	}
 253}
 254
 255void z80_save_ea(code_info *code, z80inst * inst, z80_options * opts)
 256{
 257	if ((inst->addr_mode & 0x1F) == Z80_REG) {
 258		if (inst->ea_reg == Z80_IYH && opts->regs[Z80_IYL] >= 0) {
 259			if (inst->reg == Z80_IYL) {
 260				ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
 261				mov_rr(code, opts->gen.scratch1, opts->regs[Z80_IYL], SZ_B);
 262				ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
 263			} else {
 264				ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
 265			}
 266		} else if (inst->reg != Z80_UNUSED && inst->reg != Z80_USE_IMMED && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) {
 267			uint8_t other_reg = opts->regs[inst->reg];
 268#ifdef X86_64
 269			if (other_reg >= R8 || (other_reg >= RSP && other_reg <= RDI)) {
 270				//we can't mix an *H reg with a register that requires the REX prefix
 271				ror_ir(code, 8, opts->regs[z80_low_reg(inst->ea_reg)], SZ_W);
 272			}
 273#endif
 274		}
 275	}
 276}
 277
 278void z80_save_result(z80_options *opts, z80inst * inst)
 279{
 280	switch(inst->addr_mode & 0x1f)
 281	{
 282	case Z80_REG_INDIRECT:
 283	case Z80_IMMED_INDIRECT:
 284	case Z80_IX_DISPLACE:
 285	case Z80_IY_DISPLACE:
 286		if (inst->op != Z80_LD) {
 287			mov_rdispr(&opts->gen.code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch2, SZ_W);
 288		}
 289		if (z80_size(inst) == SZ_B) {
 290			call(&opts->gen.code, opts->write_8);
 291		} else {
 292			call(&opts->gen.code, opts->write_16_lowfirst);
 293		}
 294	}
 295}
 296
 297enum {
 298	DONT_READ=0,
 299	READ
 300};
 301
 302enum {
 303	DONT_MODIFY=0,
 304	MODIFY
 305};
 306
 307void z80_print_regs_exit(z80_context * context)
 308{
 309	printf("A: %X\nB: %X\nC: %X\nD: %X\nE: %X\nHL: %X\nIX: %X\nIY: %X\nSP: %X\n\nIM: %d, IFF1: %d, IFF2: %d\n",
 310		context->regs[Z80_A], context->regs[Z80_B], context->regs[Z80_C],
 311		context->regs[Z80_D], context->regs[Z80_E],
 312		(context->regs[Z80_H] << 8) | context->regs[Z80_L],
 313		(context->regs[Z80_IXH] << 8) | context->regs[Z80_IXL],
 314		(context->regs[Z80_IYH] << 8) | context->regs[Z80_IYL],
 315		context->sp, context->im, context->iff1, context->iff2);
 316	puts("--Alternate Regs--");
 317	printf("A: %X\nB: %X\nC: %X\nD: %X\nE: %X\nHL: %X\nIX: %X\nIY: %X\n",
 318		context->alt_regs[Z80_A], context->alt_regs[Z80_B], context->alt_regs[Z80_C],
 319		context->alt_regs[Z80_D], context->alt_regs[Z80_E],
 320		(context->alt_regs[Z80_H] << 8) | context->alt_regs[Z80_L],
 321		(context->alt_regs[Z80_IXH] << 8) | context->alt_regs[Z80_IXL],
 322		(context->alt_regs[Z80_IYH] << 8) | context->alt_regs[Z80_IYL]);
 323	exit(0);
 324}
 325
 326void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address, uint8_t interp)
 327{
 328	uint32_t num_cycles;
 329	host_ea src_op, dst_op;
 330	uint8_t size;
 331	z80_options *opts = context->options;
 332	uint8_t * start = opts->gen.code.cur;
 333	code_info *code = &opts->gen.code;
 334	if (!interp) {
 335		check_cycles_int(&opts->gen, address);
 336		if (context->breakpoint_flags[address / 8] & (1 << (address % 8))) {
 337			zbreakpoint_patch(context, address, start);
 338		}
 339		num_cycles = 4 * inst->opcode_bytes;
 340		add_ir(code, inst->opcode_bytes > 1 ? 2 : 1, opts->regs[Z80_R], SZ_B);
 341#ifdef Z80_LOG_ADDRESS
 342		log_address(&opts->gen, address, "Z80: %X @ %d\n");
 343#endif
 344	}
 345	switch(inst->op)
 346	{
 347	case Z80_LD:
 348		size = z80_size(inst);
 349		switch (inst->addr_mode & 0x1F)
 350		{
 351		case Z80_REG:
 352		case Z80_REG_INDIRECT:
 353			if (size != SZ_B) {
 354				num_cycles += 2;
 355			}
 356			if (inst->reg == Z80_I || inst->ea_reg == Z80_I || inst->reg == Z80_R || inst->ea_reg == Z80_R) {
 357				num_cycles += 1;
 358			} else if (inst->reg == Z80_USE_IMMED) {
 359				num_cycles += 3;
 360			}
 361			break;
 362		case Z80_IMMED:
 363			num_cycles += size == SZ_B ? 3 : 6;
 364			break;
 365		case Z80_IMMED_INDIRECT:
 366			num_cycles += 6;
 367			break;
 368		case Z80_IX_DISPLACE:
 369		case Z80_IY_DISPLACE:
 370			num_cycles += 8; //3 for displacement, 5 for address addition
 371			break;
 372		}
 373		cycles(&opts->gen, num_cycles);
 374		if (inst->addr_mode & Z80_DIR) {
 375			translate_z80_ea(inst, &dst_op, opts, DONT_READ, MODIFY);
 376			translate_z80_reg(inst, &src_op, opts);
 377		} else {
 378			translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
 379			translate_z80_reg(inst, &dst_op, opts);
 380		}
 381		if (inst->reg == Z80_R) {
 382			mov_rr(code, opts->regs[Z80_A], opts->gen.scratch1, SZ_B);
 383			mov_rr(code, opts->regs[Z80_A], opts->regs[Z80_R], SZ_B);
 384			and_ir(code, 0x80, opts->gen.scratch1, SZ_B);
 385			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zr_off(Z80_R), SZ_B);
 386		} else if (inst->ea_reg == Z80_R && inst->addr_mode == Z80_REG) {
 387			mov_rr(code, opts->regs[Z80_R], opts->regs[Z80_A], SZ_B);
 388			and_ir(code, 0x7F, opts->regs[Z80_A], SZ_B);
 389			or_rdispr(code, opts->gen.context_reg, zr_off(Z80_R), opts->regs[Z80_A], SZ_B);
 390		} else if (src_op.mode == MODE_REG_DIRECT) {
 391			if(dst_op.mode == MODE_REG_DISPLACE8) {
 392				mov_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, size);
 393			} else {
 394				mov_rr(code, src_op.base, dst_op.base, size);
 395			}
 396		} else if(src_op.mode == MODE_IMMED) {
 397			if(dst_op.mode == MODE_REG_DISPLACE8) {
 398				mov_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, size);
 399			} else {
 400				mov_ir(code, src_op.disp, dst_op.base, size);
 401			}
 402		} else {
 403			if(dst_op.mode == MODE_REG_DISPLACE8) {
 404				mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, size);
 405				mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, size);
 406			} else {
 407				mov_rdispr(code, src_op.base, src_op.disp, dst_op.base, size);
 408			}
 409		}
 410		if ((inst->ea_reg == Z80_I || inst->ea_reg == Z80_R) && inst->addr_mode == Z80_REG) {
 411			//ld a, i and ld a, r sets some flags
 412			cmp_ir(code, 0, dst_op.base, SZ_B);
 413			setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
 414			setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
 415			mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);;
 416			mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);;
 417			mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, iff2), opts->gen.scratch1, SZ_B);
 418			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
 419		}
 420		z80_save_reg(inst, opts);
 421		z80_save_ea(code, inst, opts);
 422		if (inst->addr_mode & Z80_DIR) {
 423			z80_save_result(opts, inst);
 424		}
 425		break;
 426	case Z80_PUSH:
 427		cycles(&opts->gen, num_cycles + 1);
 428		sub_ir(code, 2, opts->regs[Z80_SP], SZ_W);
 429		if (inst->reg == Z80_AF) {
 430			zreg_to_native(opts, Z80_A, opts->gen.scratch1);
 431			shl_ir(code, 8, opts->gen.scratch1, SZ_W);
 432			mov_rdispr(code, opts->gen.context_reg, zf_off(ZF_XY), opts->gen.scratch1, SZ_B);
 433			and_ir(code, 0x28, opts->gen.scratch1, SZ_B);
 434			or_rdispr(code, opts->gen.context_reg, zf_off(ZF_C), opts->gen.scratch1, SZ_B);
 435			ror_ir(code, 1, opts->gen.scratch1, SZ_B);
 436			or_rdispr(code, opts->gen.context_reg, zf_off(ZF_N), opts->gen.scratch1, SZ_B);
 437			ror_ir(code, 1, opts->gen.scratch1, SZ_B);
 438			or_rdispr(code, opts->gen.context_reg, zf_off(ZF_PV), opts->gen.scratch1, SZ_B);
 439			ror_ir(code, 2, opts->gen.scratch1, SZ_B);
 440			or_rdispr(code, opts->gen.context_reg, zf_off(ZF_H), opts->gen.scratch1, SZ_B);
 441			ror_ir(code, 2, opts->gen.scratch1, SZ_B);
 442			or_rdispr(code, opts->gen.context_reg, zf_off(ZF_Z), opts->gen.scratch1, SZ_B);
 443			ror_ir(code, 1, opts->gen.scratch1, SZ_B);
 444			or_rdispr(code, opts->gen.context_reg, zf_off(ZF_S), opts->gen.scratch1, SZ_B);
 445			ror_ir(code, 1, opts->gen.scratch1, SZ_B);
 446		} else {
 447			zreg_to_native(opts, inst->reg, opts->gen.scratch1);
 448		}
 449		mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
 450		call(code, opts->write_16_highfirst);
 451		//no call to save_z80_reg needed since there's no chance we'll use the only
 452		//the upper half of a register pair
 453		break;
 454	case Z80_POP:
 455		cycles(&opts->gen, num_cycles);
 456		mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
 457		call(code, opts->read_16);
 458		add_ir(code, 2, opts->regs[Z80_SP], SZ_W);
 459		if (inst->reg == Z80_AF) {
 460
 461			bt_ir(code, 0, opts->gen.scratch1, SZ_W);
 462			setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
 463			bt_ir(code, 1, opts->gen.scratch1, SZ_W);
 464			setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_N));
 465			bt_ir(code, 2, opts->gen.scratch1, SZ_W);
 466			setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_PV));
 467			bt_ir(code, 4, opts->gen.scratch1, SZ_W);
 468			setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
 469			bt_ir(code, 6, opts->gen.scratch1, SZ_W);
 470			setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_Z));
 471			bt_ir(code, 7, opts->gen.scratch1, SZ_W);
 472			setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_S));
 473			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 474			shr_ir(code, 8, opts->gen.scratch1, SZ_W);
 475			native_to_zreg(opts, opts->gen.scratch1, Z80_A);
 476		} else {
 477			native_to_zreg(opts, opts->gen.scratch1, inst->reg);
 478		}
 479		//no call to save_z80_reg needed since there's no chance we'll use the only
 480		//the upper half of a register pair
 481		break;
 482	case Z80_EX:
 483		cycles(&opts->gen, num_cycles);
 484		if (inst->addr_mode == Z80_REG) {
 485			if(inst->reg == Z80_AF) {
 486				zreg_to_native(opts, Z80_A, opts->gen.scratch1);
 487				mov_rdispr(code, opts->gen.context_reg, zar_off(Z80_A), opts->gen.scratch2, SZ_B);
 488				mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zar_off(Z80_A), SZ_B);
 489				native_to_zreg(opts, opts->gen.scratch2, Z80_A);
 490
 491				//Flags are currently word aligned, so we can move
 492				//them efficiently a word at a time
 493				for (int f = ZF_C; f < ZF_NUM; f+=2) {
 494					mov_rdispr(code, opts->gen.context_reg, zf_off(f), opts->gen.scratch1, SZ_W);
 495					mov_rdispr(code, opts->gen.context_reg, zaf_off(f), opts->gen.scratch2, SZ_W);
 496					mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zaf_off(f), SZ_W);
 497					mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(f), SZ_W);
 498				}
 499			} else {
 500				if (opts->regs[Z80_DE] >= 0 && opts->regs[Z80_HL] >= 0) {
 501					xchg_rr(code, opts->regs[Z80_DE], opts->regs[Z80_HL], SZ_W);
 502				} else {
 503					zreg_to_native(opts, Z80_DE, opts->gen.scratch1);
 504					zreg_to_native(opts, Z80_HL, opts->gen.scratch2);
 505					native_to_zreg(opts, opts->gen.scratch1, Z80_HL);
 506					native_to_zreg(opts, opts->gen.scratch2, Z80_DE);
 507				}
 508			}
 509		} else {
 510			mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
 511			call(code, opts->read_8);
 512			if (opts->regs[inst->reg] >= 0) {
 513				xchg_rr(code, opts->regs[inst->reg], opts->gen.scratch1, SZ_B);
 514			} else {
 515				zreg_to_native(opts, inst->reg, opts->gen.scratch2);
 516				xchg_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 517				native_to_zreg(opts, opts->gen.scratch2, inst->reg);
 518			}
 519			mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
 520			call(code, opts->write_8);
 521			cycles(&opts->gen, 1);
 522			uint8_t high_reg = z80_high_reg(inst->reg);
 523			mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
 524			add_ir(code, 1, opts->gen.scratch1, SZ_W);
 525			call(code, opts->read_8);
 526			if (opts->regs[inst->reg] >= 0) {
 527				//even though some of the upper halves can be used directly
 528				//the limitations on mixing *H regs with the REX prefix
 529				//prevent us from taking advantage of it
 530				uint8_t use_reg = opts->regs[inst->reg];
 531				ror_ir(code, 8, use_reg, SZ_W);
 532				xchg_rr(code, use_reg, opts->gen.scratch1, SZ_B);
 533				//restore reg to normal rotation
 534				ror_ir(code, 8, use_reg, SZ_W);
 535			} else {
 536				zreg_to_native(opts, high_reg, opts->gen.scratch2);
 537				xchg_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 538				native_to_zreg(opts, opts->gen.scratch2, high_reg);
 539			}
 540			mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
 541			add_ir(code, 1, opts->gen.scratch2, SZ_W);
 542			call(code, opts->write_8);
 543			cycles(&opts->gen, 2);
 544		}
 545		break;
 546	case Z80_EXX:
 547		cycles(&opts->gen, num_cycles);
 548		zreg_to_native(opts, Z80_BC, opts->gen.scratch1);
 549		mov_rdispr(code, opts->gen.context_reg, zar_off(Z80_BC), opts->gen.scratch2, SZ_W);
 550		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zar_off(Z80_BC), SZ_W);
 551		native_to_zreg(opts, opts->gen.scratch2, Z80_BC);
 552
 553		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
 554		mov_rdispr(code, opts->gen.context_reg, zar_off(Z80_HL), opts->gen.scratch2, SZ_W);
 555		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zar_off(Z80_HL), SZ_W);
 556		native_to_zreg(opts, opts->gen.scratch2, Z80_HL);
 557
 558		zreg_to_native(opts, Z80_DE, opts->gen.scratch1);
 559		mov_rdispr(code, opts->gen.context_reg, zar_off(Z80_DE), opts->gen.scratch2, SZ_W);
 560		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zar_off(Z80_DE), SZ_W);
 561		native_to_zreg(opts, opts->gen.scratch2, Z80_DE);
 562		break;
 563	case Z80_LDI: {
 564		cycles(&opts->gen, num_cycles);
 565		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
 566		call(code, opts->read_8);
 567		zreg_to_native(opts, Z80_DE, opts->gen.scratch2);
 568		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 569		call(code, opts->write_8);
 570		mov_rdispr(code, opts->gen.context_reg, zf_off(ZF_XY), opts->gen.scratch1, SZ_B);
 571		add_rr(code, opts->regs[Z80_A], opts->gen.scratch1, SZ_B);
 572		mov_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 573		and_ir(code, 0x8, opts->gen.scratch1, SZ_B);
 574		shl_ir(code, 4, opts->gen.scratch2, SZ_B);
 575		or_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 576		mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 577		cycles(&opts->gen, 2);
 578		if (opts->regs[Z80_DE] >= 0) {
 579			add_ir(code, 1, opts->regs[Z80_DE], SZ_W);
 580		} else {
 581			add_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_DE), SZ_W);
 582		}
 583		if (opts->regs[Z80_HL] >= 0) {
 584			add_ir(code, 1, opts->regs[Z80_HL], SZ_W);
 585		} else {
 586			add_irdisp(code, 1, opts->gen.context_reg,  zr_off(Z80_HL), SZ_W);
 587		}
 588		if (opts->regs[Z80_BC] >= 0) {
 589			sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
 590		} else {
 591			sub_irdisp(code, 1, opts->gen.context_reg,  zr_off(Z80_BC), SZ_W);
 592		}
 593		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
 594		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
 595		setcc_rdisp(code, CC_NZ, opts->gen.context_reg, zf_off(ZF_PV));
 596		break;
 597	}
 598	case Z80_LDIR: {
 599		cycles(&opts->gen, num_cycles);
 600		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
 601		call(code, opts->read_8);
 602		zreg_to_native(opts, Z80_DE, opts->gen.scratch2);
 603		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 604		call(code, opts->write_8);
 605		mov_rdispr(code, opts->gen.context_reg, zf_off(ZF_XY), opts->gen.scratch1, SZ_B);
 606		add_rr(code, opts->regs[Z80_A], opts->gen.scratch1, SZ_B);
 607		mov_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 608		and_ir(code, 0x8, opts->gen.scratch1, SZ_B);
 609		shl_ir(code, 4, opts->gen.scratch2, SZ_B);
 610		or_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 611		mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 612		if (opts->regs[Z80_DE] >= 0) {
 613			add_ir(code, 1, opts->regs[Z80_DE], SZ_W);
 614		} else {
 615			add_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_DE), SZ_W);
 616		}
 617		if (opts->regs[Z80_HL] >= 0) {
 618			add_ir(code, 1, opts->regs[Z80_HL], SZ_W);
 619		} else {
 620			add_irdisp(code, 1, opts->gen.context_reg,  zr_off(Z80_HL), SZ_W);
 621		}
 622		if (opts->regs[Z80_BC] >= 0) {
 623			sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
 624		} else {
 625			sub_irdisp(code, 1, opts->gen.context_reg,  zr_off(Z80_BC), SZ_W);
 626		}
 627		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
 628		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
 629		uint8_t * cont = code->cur+1;
 630		jcc(code, CC_Z, code->cur+2);
 631		cycles(&opts->gen, 7);
 632		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
 633		jmp(code, start);
 634		*cont = code->cur - (cont + 1);
 635		cycles(&opts->gen, 2);
 636		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
 637		break;
 638	}
 639	case Z80_LDD: {
 640		cycles(&opts->gen, num_cycles);
 641		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
 642		call(code, opts->read_8);
 643		zreg_to_native(opts, Z80_DE, opts->gen.scratch2);
 644		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 645		call(code, opts->write_8);
 646		mov_rdispr(code, opts->gen.context_reg, zf_off(ZF_XY), opts->gen.scratch1, SZ_B);
 647		add_rr(code, opts->regs[Z80_A], opts->gen.scratch1, SZ_B);
 648		mov_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 649		and_ir(code, 0x8, opts->gen.scratch1, SZ_B);
 650		shl_ir(code, 4, opts->gen.scratch2, SZ_B);
 651		or_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 652		mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 653		cycles(&opts->gen, 2);
 654		if (opts->regs[Z80_DE] >= 0) {
 655			sub_ir(code, 1, opts->regs[Z80_DE], SZ_W);
 656		} else {
 657			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_DE), SZ_W);
 658		}
 659		if (opts->regs[Z80_HL] >= 0) {
 660			sub_ir(code, 1, opts->regs[Z80_HL], SZ_W);
 661		} else {
 662			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_W);
 663		}
 664		if (opts->regs[Z80_BC] >= 0) {
 665			sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
 666		} else {
 667			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_BC), SZ_W);
 668		}
 669		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
 670		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
 671		setcc_rdisp(code, CC_NZ, opts->gen.context_reg, zf_off(ZF_PV));
 672		break;
 673	}
 674	case Z80_LDDR: {
 675		cycles(&opts->gen, num_cycles);
 676		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
 677		call(code, opts->read_8);
 678		zreg_to_native(opts, Z80_DE, opts->gen.scratch2);
 679		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 680		call(code, opts->write_8);
 681		mov_rdispr(code, opts->gen.context_reg, zf_off(ZF_XY), opts->gen.scratch1, SZ_B);
 682		add_rr(code, opts->regs[Z80_A], opts->gen.scratch1, SZ_B);
 683		mov_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 684		and_ir(code, 0x8, opts->gen.scratch1, SZ_B);
 685		shl_ir(code, 4, opts->gen.scratch2, SZ_B);
 686		or_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 687		mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 688		if (opts->regs[Z80_DE] >= 0) {
 689			sub_ir(code, 1, opts->regs[Z80_DE], SZ_W);
 690		} else {
 691			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_DE), SZ_W);
 692		}
 693		if (opts->regs[Z80_HL] >= 0) {
 694			sub_ir(code, 1, opts->regs[Z80_HL], SZ_W);
 695		} else {
 696			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_W);
 697		}
 698		if (opts->regs[Z80_BC] >= 0) {
 699			sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
 700		} else {
 701			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_BC), SZ_W);
 702		}
 703		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
 704		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
 705		uint8_t * cont = code->cur+1;
 706		jcc(code, CC_Z, code->cur+2);
 707		cycles(&opts->gen, 7);
 708		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
 709		jmp(code, start);
 710		*cont = code->cur - (cont + 1);
 711		cycles(&opts->gen, 2);
 712		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
 713		break;
 714	}
 715	case Z80_CPI:
 716		cycles(&opts->gen, num_cycles);//T-States 4,4
 717		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
 718		call(code, opts->read_8);//T-States 3
 719		mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
 720		sub_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 721		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
 722		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
 723		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
 724		xor_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
 725		xor_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 726		bt_ir(code, 4, opts->gen.scratch2, SZ_B);
 727		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
 728		cycles(&opts->gen, 5);//T-States 5
 729		if (opts->regs[Z80_HL] >= 0) {
 730			add_ir(code, 1, opts->regs[Z80_HL], SZ_W);
 731		} else {
 732			add_irdisp(code, 1, opts->gen.context_reg,  zr_off(Z80_HL), SZ_W);
 733		}
 734		if (opts->regs[Z80_BC] >= 0) {
 735			sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
 736		} else {
 737			sub_irdisp(code, 1, opts->gen.context_reg,  zr_off(Z80_BC), SZ_W);
 738		}
 739		setcc_rdisp(code, CC_NZ, opts->gen.context_reg, zf_off(ZF_PV));
 740		mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
 741		sub_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 742		sub_rdispr(code, opts->gen.context_reg, zf_off(ZF_H), opts->gen.scratch2, SZ_B);
 743		mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 744		shl_ir(code, 4, opts->gen.scratch2, SZ_B);
 745		and_irdisp(code, 0x8, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 746		and_ir(code, 0x20, opts->gen.scratch2, SZ_B);
 747		or_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 748		break;
 749	case Z80_CPIR: {
 750		cycles(&opts->gen, num_cycles);//T-States 4,4
 751		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
 752		call(code, opts->read_8);//T-States 3
 753		mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
 754		sub_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 755		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
 756		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
 757		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
 758		xor_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
 759		xor_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 760		bt_ir(code, 4, opts->gen.scratch2, SZ_B);
 761		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
 762		cycles(&opts->gen, 5);//T-States 5
 763		if (opts->regs[Z80_HL] >= 0) {
 764			add_ir(code, 1, opts->regs[Z80_HL], SZ_W);
 765		} else {
 766			add_irdisp(code, 1, opts->gen.context_reg,  zr_off(Z80_HL), SZ_W);
 767		}
 768		mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
 769		sub_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 770		sub_rdispr(code, opts->gen.context_reg, zf_off(ZF_H), opts->gen.scratch2, SZ_B);
 771		mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 772		shl_ir(code, 4, opts->gen.scratch2, SZ_B);
 773		and_irdisp(code, 0x8, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 774		and_ir(code, 0x20, opts->gen.scratch2, SZ_B);
 775		or_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 776		if (opts->regs[Z80_BC] >= 0) {
 777			sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
 778		} else {
 779			sub_irdisp(code, 1, opts->gen.context_reg,  zr_off(Z80_BC), SZ_W);
 780		}
 781		setcc_rdisp(code, CC_NZ, opts->gen.context_reg, zf_off(ZF_PV));
 782		uint8_t * cont = code->cur+1;
 783		jcc(code, CC_Z, code->cur+2);
 784		cmp_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B);
 785		uint8_t * cont2 = code->cur+1;
 786		jcc(code, CC_Z, code->cur+2);
 787		//repeat case
 788		cycles(&opts->gen, 5);//T-States 5
 789		jmp(code, start);
 790		*cont = code->cur - (cont + 1);
 791		*cont2 = code->cur - (cont2 + 1);
 792		break;
 793	}
 794	case Z80_CPD:
 795		cycles(&opts->gen, num_cycles);//T-States 4,4
 796		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
 797		call(code, opts->read_8);//T-States 3
 798		mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
 799		sub_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 800		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
 801		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
 802		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
 803		xor_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
 804		xor_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 805		bt_ir(code, 4, opts->gen.scratch2, SZ_B);
 806		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
 807		cycles(&opts->gen, 5);//T-States 5
 808		if (opts->regs[Z80_HL] >= 0) {
 809			sub_ir(code, 1, opts->regs[Z80_HL], SZ_W);
 810		} else {
 811			sub_irdisp(code, 1, opts->gen.context_reg,  zr_off(Z80_HL), SZ_W);
 812		}
 813		if (opts->regs[Z80_BC] >= 0) {
 814			sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
 815		} else {
 816			sub_irdisp(code, 1, opts->gen.context_reg,  zr_off(Z80_BC), SZ_W);
 817		}
 818		setcc_rdisp(code, CC_NZ, opts->gen.context_reg, zf_off(ZF_PV));
 819		mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
 820		sub_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 821		sub_rdispr(code, opts->gen.context_reg, zf_off(ZF_H), opts->gen.scratch2, SZ_B);
 822		mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 823		shl_ir(code, 4, opts->gen.scratch2, SZ_B);
 824		and_irdisp(code, 0x8, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 825		and_ir(code, 0x20, opts->gen.scratch2, SZ_B);
 826		or_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 827		break;
 828	case Z80_CPDR: {
 829		cycles(&opts->gen, num_cycles);//T-States 4,4
 830		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
 831		call(code, opts->read_8);//T-States 3
 832		mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
 833		sub_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 834		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
 835		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
 836		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
 837		xor_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
 838		xor_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 839		bt_ir(code, 4, opts->gen.scratch2, SZ_B);
 840		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
 841		cycles(&opts->gen, 5);//T-States 5
 842		if (opts->regs[Z80_HL] >= 0) {
 843			sub_ir(code, 1, opts->regs[Z80_HL], SZ_W);
 844		} else {
 845			sub_irdisp(code, 1, opts->gen.context_reg,  zr_off(Z80_HL), SZ_W);
 846		}
 847		mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
 848		sub_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 849		sub_rdispr(code, opts->gen.context_reg, zf_off(ZF_H), opts->gen.scratch2, SZ_B);
 850		mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 851		shl_ir(code, 4, opts->gen.scratch2, SZ_B);
 852		and_irdisp(code, 0x8, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 853		and_ir(code, 0x20, opts->gen.scratch2, SZ_B);
 854		or_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 855		if (opts->regs[Z80_BC] >= 0) {
 856			sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
 857		} else {
 858			sub_irdisp(code, 1, opts->gen.context_reg,  zr_off(Z80_BC), SZ_W);
 859		}
 860		setcc_rdisp(code, CC_NZ, opts->gen.context_reg, zf_off(ZF_PV));
 861		uint8_t * cont = code->cur+1;
 862		jcc(code, CC_Z, code->cur+2);
 863		cmp_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B);
 864		uint8_t * cont2 = code->cur+1;
 865		jcc(code, CC_Z, code->cur+2);
 866		//repeat case
 867		cycles(&opts->gen, 5);//T-States 5
 868		jmp(code, start);
 869		*cont = code->cur - (cont + 1);
 870		*cont2 = code->cur - (cont2 + 1);
 871		break;
 872	}
 873	case Z80_ADD:
 874		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
 875			num_cycles += 8;
 876		} else if(inst->addr_mode == Z80_IMMED) {
 877			num_cycles += 3;
 878		} else if(z80_size(inst) == SZ_W) {
 879			num_cycles += 7;
 880		}
 881		cycles(&opts->gen, num_cycles);
 882		translate_z80_reg(inst, &dst_op, opts);
 883		translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
 884		if (dst_op.mode == MODE_REG_DIRECT) {
 885			mov_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
 886		} else {
 887			mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, z80_size(inst));
 888		}
 889		if (src_op.mode == MODE_REG_DIRECT) {
 890			xor_rr(code, src_op.base, opts->gen.scratch2, z80_size(inst));
 891		} else if (src_op.mode == MODE_IMMED) {
 892			xor_ir(code, src_op.disp, opts->gen.scratch2, z80_size(inst));
 893		} else {
 894			xor_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, z80_size(inst));
 895		}
 896		if (dst_op.mode == MODE_REG_DIRECT) {
 897			if (src_op.mode == MODE_REG_DIRECT) {
 898				add_rr(code, src_op.base, dst_op.base, z80_size(inst));
 899			} else if (src_op.mode == MODE_IMMED) {
 900				add_ir(code, src_op.disp, dst_op.base, z80_size(inst));
 901			} else {
 902				add_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst));
 903			}
 904			if (z80_size(inst) == SZ_B) {
 905				mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 906			}
 907		} else {
 908			if (src_op.mode == MODE_REG_DIRECT) {
 909				add_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, z80_size(inst));
 910			} else if (src_op.mode == MODE_IMMED) {
 911				add_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, z80_size(inst));
 912			} else {
 913				mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, z80_size(inst));
 914				add_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, z80_size(inst));
 915			}
 916			mov_rdispr(code, dst_op.base, dst_op.disp + (z80_size(inst) == SZ_B ? 0 : 1), opts->gen.scratch1, SZ_B);
 917			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 918		}
 919		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
 920		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
 921		if (z80_size(inst) == SZ_B) {
 922			setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
 923			setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
 924			setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
 925		}
 926		if (dst_op.mode == MODE_REG_DIRECT) {
 927			xor_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
 928		} else {
 929			xor_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, z80_size(inst));
 930		}
 931		bt_ir(code, z80_size(inst) == SZ_B ? 4 : 12, opts->gen.scratch2, z80_size(inst));
 932		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
 933		if (z80_size(inst) == SZ_W & dst_op.mode == MODE_REG_DIRECT) {
 934			mov_rr(code, dst_op.base, opts->gen.scratch2, SZ_W);
 935			shr_ir(code, 8, opts->gen.scratch2, SZ_W);
 936			mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 937		}
 938		z80_save_reg(inst, opts);
 939		z80_save_ea(code, inst, opts);
 940		break;
 941	case Z80_ADC:
 942		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
 943			num_cycles += 8;
 944		} else if(inst->addr_mode == Z80_IMMED) {
 945			num_cycles += 3;
 946		} else if(z80_size(inst) == SZ_W) {
 947			num_cycles += 7;
 948		}
 949		cycles(&opts->gen, num_cycles);
 950		translate_z80_reg(inst, &dst_op, opts);
 951		translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
 952		if (dst_op.mode == MODE_REG_DIRECT) {
 953			mov_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
 954		} else {
 955			mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, z80_size(inst));
 956		}
 957		if (src_op.mode == MODE_REG_DIRECT) {
 958			xor_rr(code, src_op.base, opts->gen.scratch2, z80_size(inst));
 959		} else if (src_op.mode == MODE_IMMED) {
 960			xor_ir(code, src_op.disp, opts->gen.scratch2, z80_size(inst));
 961		} else {
 962			xor_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, z80_size(inst));
 963		}
 964		bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
 965		if (dst_op.mode == MODE_REG_DIRECT) {
 966			if (src_op.mode == MODE_REG_DIRECT) {
 967				adc_rr(code, src_op.base, dst_op.base, z80_size(inst));
 968			} else if (src_op.mode == MODE_IMMED) {
 969				adc_ir(code, src_op.disp, dst_op.base, z80_size(inst));
 970			} else {
 971				adc_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst));
 972			}
 973			if (z80_size(inst) == SZ_B) {
 974				mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 975			}
 976		} else {
 977			if (src_op.mode == MODE_REG_DIRECT) {
 978				adc_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, z80_size(inst));
 979			} else if (src_op.mode == MODE_IMMED) {
 980				adc_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, z80_size(inst));
 981			} else {
 982				mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, z80_size(inst));
 983				adc_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, z80_size(inst));
 984			}
 985			mov_rdispr(code, dst_op.base, dst_op.disp + z80_size(inst) == SZ_B ? 0 : 8, opts->gen.scratch1, SZ_B);
 986			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 987		}
 988		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
 989		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
 990		setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
 991		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
 992		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
 993		if (dst_op.mode == MODE_REG_DIRECT) {
 994			xor_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
 995		} else {
 996			xor_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, z80_size(inst));
 997		}
 998		bt_ir(code, z80_size(inst) == SZ_B ? 4 : 12, opts->gen.scratch2, z80_size(inst));
 999		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
1000		if (z80_size(inst) == SZ_W & dst_op.mode == MODE_REG_DIRECT) {
1001			mov_rr(code, dst_op.base, opts->gen.scratch2, SZ_W);
1002			shr_ir(code, 8, opts->gen.scratch2, SZ_W);
1003			mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1004		}
1005		z80_save_reg(inst, opts);
1006		z80_save_ea(code, inst, opts);
1007		break;
1008	case Z80_SUB:
1009		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1010			num_cycles += 8;
1011		} else if(inst->addr_mode == Z80_IMMED) {
1012			num_cycles += 3;
1013		}
1014		cycles(&opts->gen, num_cycles);
1015		translate_z80_reg(inst, &dst_op, opts);
1016		translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
1017		if (dst_op.mode == MODE_REG_DIRECT) {
1018			mov_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
1019		} else {
1020			mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, z80_size(inst));
1021		}
1022		if (src_op.mode == MODE_REG_DIRECT) {
1023			xor_rr(code, src_op.base, opts->gen.scratch2, z80_size(inst));
1024		} else if (src_op.mode == MODE_IMMED) {
1025			xor_ir(code, src_op.disp, opts->gen.scratch2, z80_size(inst));
1026		} else {
1027			xor_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, z80_size(inst));
1028		}
1029		if (dst_op.mode == MODE_REG_DIRECT) {
1030			if (src_op.mode == MODE_REG_DIRECT) {
1031				sub_rr(code, src_op.base, dst_op.base, z80_size(inst));
1032			} else if (src_op.mode == MODE_IMMED) {
1033				sub_ir(code, src_op.disp, dst_op.base, z80_size(inst));
1034			} else {
1035				sub_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst));
1036			}
1037			if (z80_size(inst) == SZ_B) {
1038				mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1039			}
1040		} else {
1041			if (src_op.mode == MODE_REG_DIRECT) {
1042				sub_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, z80_size(inst));
1043			} else if (src_op.mode == MODE_IMMED) {
1044				sub_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, z80_size(inst));
1045			} else {
1046				mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, z80_size(inst));
1047				sub_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, z80_size(inst));
1048			}
1049			mov_rdispr(code, dst_op.base, dst_op.disp + z80_size(inst) == SZ_B ? 0 : 8, opts->gen.scratch1, SZ_B);
1050			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1051		}
1052		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1053		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1054		setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
1055		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1056		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1057		if (dst_op.mode == MODE_REG_DIRECT) {
1058			xor_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
1059		} else {
1060			xor_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, z80_size(inst));
1061		}
1062		bt_ir(code, z80_size(inst) == SZ_B ? 4 : 12, opts->gen.scratch2, z80_size(inst));
1063		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
1064		if (z80_size(inst) == SZ_W & dst_op.mode == MODE_REG_DIRECT) {
1065			mov_rr(code, dst_op.base, opts->gen.scratch2, SZ_W);
1066			shr_ir(code, 8, opts->gen.scratch2, SZ_W);
1067			mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1068		}
1069		z80_save_reg(inst, opts);
1070		z80_save_ea(code, inst, opts);
1071		break;
1072	case Z80_SBC:
1073		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1074			num_cycles += 8;
1075		} else if(inst->addr_mode == Z80_IMMED) {
1076			num_cycles += 3;
1077		} else if(z80_size(inst) == SZ_W) {
1078			num_cycles += 7;
1079		}
1080		cycles(&opts->gen, num_cycles);
1081		translate_z80_reg(inst, &dst_op, opts);
1082		translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
1083		if (dst_op.mode == MODE_REG_DIRECT) {
1084			mov_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
1085		} else {
1086			mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, z80_size(inst));
1087		}
1088		if (src_op.mode == MODE_REG_DIRECT) {
1089			xor_rr(code, src_op.base, opts->gen.scratch2, z80_size(inst));
1090		} else if (src_op.mode == MODE_IMMED) {
1091			xor_ir(code, src_op.disp, opts->gen.scratch2, z80_size(inst));
1092		} else {
1093			xor_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, z80_size(inst));
1094		}
1095		bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1096		if (dst_op.mode == MODE_REG_DIRECT) {
1097			if (src_op.mode == MODE_REG_DIRECT) {
1098				sbb_rr(code, src_op.base, dst_op.base, z80_size(inst));
1099			} else if (src_op.mode == MODE_IMMED) {
1100				sbb_ir(code, src_op.disp, dst_op.base, z80_size(inst));
1101			} else {
1102				sbb_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst));
1103			}
1104			if (z80_size(inst) == SZ_B) {
1105				mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1106			}
1107		} else {
1108			if (src_op.mode == MODE_REG_DIRECT) {
1109				sbb_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, z80_size(inst));
1110			} else if (src_op.mode == MODE_IMMED) {
1111				sbb_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, z80_size(inst));
1112			} else {
1113				mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, z80_size(inst));
1114				sbb_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, z80_size(inst));
1115			}
1116			mov_rdispr(code, dst_op.base, dst_op.disp + z80_size(inst) == SZ_B ? 0 : 8, opts->gen.scratch1, SZ_B);
1117			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1118		}
1119		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1120		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1121		setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
1122		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1123		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1124		if (dst_op.mode == MODE_REG_DIRECT) {
1125			xor_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
1126		} else {
1127			xor_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, z80_size(inst));
1128		}
1129		bt_ir(code, z80_size(inst) == SZ_B ? 4 : 12, opts->gen.scratch2, z80_size(inst));
1130		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
1131		if (z80_size(inst) == SZ_W & dst_op.mode == MODE_REG_DIRECT) {
1132			mov_rr(code, dst_op.base, opts->gen.scratch2, SZ_W);
1133			shr_ir(code, 8, opts->gen.scratch2, SZ_W);
1134			mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1135		}
1136		z80_save_reg(inst, opts);
1137		z80_save_ea(code, inst, opts);
1138		break;
1139	case Z80_AND:
1140		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1141			num_cycles += 8;
1142		} else if(inst->addr_mode == Z80_IMMED) {
1143			num_cycles += 3;
1144		} else if(z80_size(inst) == SZ_W) {
1145			num_cycles += 4;
1146		}
1147		cycles(&opts->gen, num_cycles);
1148		translate_z80_reg(inst, &dst_op, opts);
1149		translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
1150		if (src_op.mode == MODE_REG_DIRECT) {
1151			and_rr(code, src_op.base, dst_op.base, z80_size(inst));
1152		} else if (src_op.mode == MODE_IMMED) {
1153			and_ir(code, src_op.disp, dst_op.base, z80_size(inst));
1154		} else {
1155			and_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst));
1156		}
1157		mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1158		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1159		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1160		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1161		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1162		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1163		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1164		z80_save_reg(inst, opts);
1165		z80_save_ea(code, inst, opts);
1166		break;
1167	case Z80_OR:
1168		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1169			num_cycles += 8;
1170		} else if(inst->addr_mode == Z80_IMMED) {
1171			num_cycles += 3;
1172		} else if(z80_size(inst) == SZ_W) {
1173			num_cycles += 4;
1174		}
1175		cycles(&opts->gen, num_cycles);
1176		translate_z80_reg(inst, &dst_op, opts);
1177		translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
1178		if (src_op.mode == MODE_REG_DIRECT) {
1179			or_rr(code, src_op.base, dst_op.base, z80_size(inst));
1180		} else if (src_op.mode == MODE_IMMED) {
1181			or_ir(code, src_op.disp, dst_op.base, z80_size(inst));
1182		} else {
1183			or_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst));
1184		}
1185		mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1186		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1187		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1188		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1189		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1190		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1191		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1192		z80_save_reg(inst, opts);
1193		z80_save_ea(code, inst, opts);
1194		break;
1195	case Z80_XOR:
1196		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1197			num_cycles += 8;
1198		} else if(inst->addr_mode == Z80_IMMED) {
1199			num_cycles += 3;
1200		} else if(z80_size(inst) == SZ_W) {
1201			num_cycles += 4;
1202		}
1203		cycles(&opts->gen, num_cycles);
1204		translate_z80_reg(inst, &dst_op, opts);
1205		translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
1206		if (src_op.mode == MODE_REG_DIRECT) {
1207			xor_rr(code, src_op.base, dst_op.base, z80_size(inst));
1208		} else if (src_op.mode == MODE_IMMED) {
1209			xor_ir(code, src_op.disp, dst_op.base, z80_size(inst));
1210		} else {
1211			xor_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst));
1212		}
1213		mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1214		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1215		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1216		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1217		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1218		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1219		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1220		z80_save_reg(inst, opts);
1221		z80_save_ea(code, inst, opts);
1222		break;
1223	case Z80_CP:
1224		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1225			num_cycles += 8;
1226		} else if(inst->addr_mode == Z80_IMMED) {
1227			num_cycles += 3;
1228		}
1229		cycles(&opts->gen, num_cycles);
1230		translate_z80_reg(inst, &dst_op, opts);
1231		translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
1232		mov_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
1233		if (src_op.mode == MODE_REG_DIRECT) {
1234			sub_rr(code, src_op.base, opts->gen.scratch2, z80_size(inst));
1235			mov_rrdisp(code, src_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1236		} else if (src_op.mode == MODE_IMMED) {
1237			sub_ir(code, src_op.disp, opts->gen.scratch2, z80_size(inst));
1238			mov_irdisp(code, src_op.disp, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1239		} else {
1240			sub_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, z80_size(inst));
1241			mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_B);
1242			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1243		}
1244		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1245		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1246		setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
1247		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1248		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1249		xor_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
1250		if (src_op.mode == MODE_REG_DIRECT) {
1251			xor_rr(code, src_op.base, opts->gen.scratch2, z80_size(inst));
1252		} else if (src_op.mode == MODE_IMMED) {
1253			xor_ir(code, src_op.disp, opts->gen.scratch2, z80_size(inst));
1254		} else {
1255			xor_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, z80_size(inst));
1256		}
1257		bt_ir(code, 4, opts->gen.scratch2, SZ_B);
1258		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
1259		z80_save_reg(inst, opts);
1260		z80_save_ea(code, inst, opts);
1261		break;
1262	case Z80_INC:
1263	case Z80_DEC:
1264		if(z80_size(inst) == SZ_W) {
1265			num_cycles += 2;
1266		} else if (inst->addr_mode == Z80_REG_INDIRECT) {
1267			num_cycles += 1;
1268		} else if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1269			num_cycles += 9;
1270		}
1271		cycles(&opts->gen, num_cycles);
1272		translate_z80_reg(inst, &dst_op, opts);
1273		if (dst_op.mode == MODE_UNUSED) {
1274			translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
1275		}
1276		if (z80_size(inst) == SZ_B) {
1277			if (dst_op.mode == MODE_REG_DIRECT) {
1278				if (dst_op.base >= AH && dst_op.base <= BH) {
1279					mov_rr(code, dst_op.base - AH, opts->gen.scratch2, SZ_W);
1280				} else {
1281					mov_rr(code, dst_op.base, opts->gen.scratch2, SZ_B);
1282				}
1283			} else {
1284				mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, SZ_B);
1285			}
1286		}
1287		if (inst->op == Z80_INC) {
1288			if (dst_op.mode == MODE_REG_DIRECT) {
1289				add_ir(code, 1, dst_op.base, z80_size(inst));
1290			} else {
1291				add_irdisp(code, 1, dst_op.base, dst_op.disp, z80_size(inst));
1292			}
1293		} else {
1294			if (dst_op.mode == MODE_REG_DIRECT) {
1295				sub_ir(code, 1, dst_op.base, z80_size(inst));
1296			} else {
1297				sub_irdisp(code, 1, dst_op.base, dst_op.disp, z80_size(inst));
1298			}
1299		}
1300		if (z80_size(inst) == SZ_B) {
1301			mov_irdisp(code, inst->op == Z80_DEC, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1302			setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
1303			setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1304			setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1305			int bit = 4;
1306			if (dst_op.mode == MODE_REG_DIRECT) {
1307				mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1308				if (dst_op.base >= AH && dst_op.base <= BH) {
1309					bit = 12;
1310					xor_rr(code, dst_op.base - AH, opts->gen.scratch2, SZ_W);
1311				} else {
1312					xor_rr(code, dst_op.base, opts->gen.scratch2, SZ_B);
1313				}
1314			} else {
1315				mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, SZ_B);
1316				xor_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, SZ_B);
1317				mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1318			}
1319			bt_ir(code, bit, opts->gen.scratch2, SZ_W);
1320			setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
1321		}
1322		z80_save_reg(inst, opts);
1323		z80_save_ea(code, inst, opts);
1324		z80_save_result(opts, inst);
1325		break;
1326	case Z80_DAA: {
1327		cycles(&opts->gen, num_cycles);
1328		xor_rr(code, opts->gen.scratch2, opts->gen.scratch2, SZ_B);
1329		zreg_to_native(opts, Z80_A, opts->gen.scratch1);
1330		and_ir(code, 0xF, opts->gen.scratch1, SZ_B);
1331		cmp_ir(code, 0xA, opts->gen.scratch1, SZ_B);
1332		mov_ir(code, 0xA0, opts->gen.scratch1, SZ_B);
1333		code_ptr corf_low_range = code->cur + 1;
1334		jcc(code, CC_NC, code->cur+2);
1335		cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1336		code_ptr corf_low = code->cur + 1;
1337		jcc(code, CC_NZ, code->cur+2);
1338		code_ptr no_corf_low = code->cur + 1;
1339		jmp(code, code->cur + 2);
1340		
1341		*corf_low_range = code->cur - (corf_low_range + 1);
1342		mov_ir(code, 0x90, opts->gen.scratch1, SZ_B);
1343		*corf_low = code->cur - (corf_low + 1);
1344		mov_ir(code, 0x06, opts->gen.scratch2, SZ_B);
1345		
1346		*no_corf_low = code->cur - (no_corf_low + 1);
1347		cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1348		code_ptr corf_high = code->cur+1;
1349		jcc(code, CC_NZ, code->cur+2);
1350		cmp_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B);
1351		code_ptr no_corf_high = code->cur+1;
1352		jcc(code, CC_C, code->cur+2);
1353		*corf_high = code->cur - (corf_high + 1);
1354		or_ir(code, 0x60, opts->gen.scratch2, SZ_B);
1355		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1356		*no_corf_high = code->cur - (no_corf_high + 1);
1357		
1358		mov_rr(code, opts->regs[Z80_A], opts->gen.scratch1, SZ_B);
1359		xor_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_B);
1360		
1361		cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1362		code_ptr not_sub = code->cur+1;
1363		jcc(code, CC_Z, code->cur+2);
1364		neg_r(code, opts->gen.scratch2, SZ_B);
1365		*not_sub = code->cur - (not_sub + 1);
1366		
1367		add_rr(code, opts->gen.scratch2, opts->regs[Z80_A], SZ_B);
1368		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1369		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1370		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1371		xor_rr(code, opts->regs[Z80_A], opts->gen.scratch1, SZ_B);
1372		bt_ir(code, 4, opts->gen.scratch1, SZ_B);
1373		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
1374		mov_rrdisp(code, opts->regs[Z80_A], opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1375		break;
1376	}
1377	case Z80_CPL:
1378		cycles(&opts->gen, num_cycles);
1379		not_r(code, opts->regs[Z80_A], SZ_B);
1380		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1381		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1382		mov_rrdisp(code, opts->regs[Z80_A], opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1383		break;
1384	case Z80_NEG:
1385		cycles(&opts->gen, num_cycles);
1386		mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
1387		neg_r(code, opts->regs[Z80_A], SZ_B);
1388		mov_rrdisp(code, opts->regs[Z80_A], opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1389		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1390		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1391		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1392		setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
1393		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1394		xor_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
1395		bt_ir(code, 4, opts->gen.scratch2, SZ_B);
1396		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
1397		break;
1398	case Z80_CCF:
1399		cycles(&opts->gen, num_cycles);
1400		mov_rdispr(code, opts->gen.context_reg, zf_off(ZF_C), opts->gen.scratch1, SZ_B);
1401		xor_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1402		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1403		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1404		mov_rrdisp(code, opts->regs[Z80_A], opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1405		break;
1406	case Z80_SCF:
1407		cycles(&opts->gen, num_cycles);
1408		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1409		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1410		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1411		mov_rrdisp(code, opts->regs[Z80_A], opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1412		break;
1413	case Z80_NOP:
1414		cycles(&opts->gen, num_cycles);
1415		break;
1416	case Z80_HALT: {
1417		code_ptr loop_top = code->cur;
1418		//this isn't terribly efficient, but it's good enough for now
1419		cycles(&opts->gen, num_cycles);
1420		check_cycles_int(&opts->gen, address+1);
1421		jmp(code, loop_top);
1422		break;
1423	}
1424	case Z80_DI:
1425		cycles(&opts->gen, num_cycles);
1426		mov_irdisp(code, 0, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B);
1427		mov_irdisp(code, 0, opts->gen.context_reg, offsetof(z80_context, iff2), SZ_B);
1428		//turn cycles remaining into current cycle
1429		neg_r(code, opts->gen.cycles, SZ_D);
1430		add_rdispr(code, opts->gen.context_reg, offsetof(z80_context, target_cycle), opts->gen.cycles, SZ_D);
1431		//set interrupt cycle to never and fetch the new target cycle from sync_cycle
1432		mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, sync_cycle), opts->gen.scratch1, SZ_D);
1433		mov_irdisp(code, 0xFFFFFFFF, opts->gen.context_reg, offsetof(z80_context, int_cycle), SZ_D);
1434		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, target_cycle), SZ_D);
1435		//turn current cycle back into cycles remaining
1436		neg_r(code, opts->gen.cycles, SZ_D);
1437		add_rr(code, opts->gen.scratch1, opts->gen.cycles, SZ_D);
1438		break;
1439	case Z80_EI:
1440		cycles(&opts->gen, num_cycles);
1441		neg_r(code, opts->gen.cycles, SZ_D);
1442		add_rdispr(code, opts->gen.context_reg, offsetof(z80_context, target_cycle), opts->gen.cycles, SZ_D);
1443		mov_rrdisp(code, opts->gen.cycles, opts->gen.context_reg, offsetof(z80_context, int_enable_cycle), SZ_D);
1444		neg_r(code, opts->gen.cycles, SZ_D);
1445		add_rdispr(code, opts->gen.context_reg, offsetof(z80_context, target_cycle), opts->gen.cycles, SZ_D);
1446		mov_irdisp(code, 1, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B);
1447		mov_irdisp(code, 1, opts->gen.context_reg, offsetof(z80_context, iff2), SZ_B);
1448		//interrupt enable has a one-instruction latency, minimum instruction duration is 4 cycles
1449		add_irdisp(code, 4*opts->gen.clock_divider, opts->gen.context_reg, offsetof(z80_context, int_enable_cycle), SZ_D);
1450		call(code, opts->do_sync);
1451		break;
1452	case Z80_IM:
1453		cycles(&opts->gen, num_cycles);
1454		mov_irdisp(code, inst->immed, opts->gen.context_reg, offsetof(z80_context, im), SZ_B);
1455		break;
1456	case Z80_RLC:
1457		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1458			num_cycles += 8;
1459		}
1460		cycles(&opts->gen, num_cycles);
1461		if (inst->addr_mode != Z80_UNUSED) {
1462			translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
1463			translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
1464			cycles(&opts->gen, 1);
1465		} else {
1466			src_op.mode = MODE_UNUSED;
1467			translate_z80_reg(inst, &dst_op, opts);
1468		}
1469		if (dst_op.mode == MODE_REG_DIRECT) {
1470			rol_ir(code, 1, dst_op.base, SZ_B);
1471			mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1472		} else {
1473			rol_irdisp(code, 1, dst_op.base, dst_op.disp, SZ_B);
1474			mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, SZ_B);
1475			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1476		}
1477		if (src_op.mode == MODE_REG_DIRECT) {
1478			mov_rr(code, dst_op.base, src_op.base, SZ_B);
1479		} else if(src_op.mode == MODE_REG_DISPLACE8) {
1480			mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B);
1481		}
1482		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1483		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1484		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1485		if (inst->immed) {
1486			//rlca does not set these flags
1487			if (dst_op.mode == MODE_REG_DIRECT) {
1488				cmp_ir(code, 0, dst_op.base, SZ_B);
1489			} else {
1490				cmp_irdisp(code, 0, dst_op.base, dst_op.disp, SZ_B);
1491			}
1492			setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1493			setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1494			setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1495		}
1496		if (inst->addr_mode != Z80_UNUSED) {
1497			z80_save_result(opts, inst);
1498			if (src_op.mode != MODE_UNUSED) {
1499				z80_save_reg(inst, opts);
1500			}
1501		} else {
1502			z80_save_reg(inst, opts);
1503		}
1504		break;
1505	case Z80_RL:
1506		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1507			num_cycles += 8;
1508		}
1509		cycles(&opts->gen, num_cycles);
1510		if (inst->addr_mode != Z80_UNUSED) {
1511			translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
1512			translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
1513			cycles(&opts->gen, 1);
1514		} else {
1515			src_op.mode = MODE_UNUSED;
1516			translate_z80_reg(inst, &dst_op, opts);
1517		}
1518		bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1519		if (dst_op.mode == MODE_REG_DIRECT) {
1520			rcl_ir(code, 1, dst_op.base, SZ_B);
1521			mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1522		} else {
1523			rcl_irdisp(code, 1, dst_op.base, dst_op.disp, SZ_B);
1524			mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, SZ_B);
1525			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1526		}
1527		if (src_op.mode == MODE_REG_DIRECT) {
1528			mov_rr(code, dst_op.base, src_op.base, SZ_B);
1529		} else if(src_op.mode == MODE_REG_DISPLACE8) {
1530			mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B);
1531		}
1532		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1533		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1534		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1535		if (inst->immed) {
1536			//rla does not set these flags
1537			if (dst_op.mode == MODE_REG_DIRECT) {
1538				cmp_ir(code, 0, dst_op.base, SZ_B);
1539			} else {
1540				cmp_irdisp(code, 0, dst_op.base, dst_op.disp, SZ_B);
1541			}
1542			setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1543			setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1544			setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1545		}
1546		if (inst->addr_mode != Z80_UNUSED) {
1547			z80_save_result(opts, inst);
1548			if (src_op.mode != MODE_UNUSED) {
1549				z80_save_reg(inst, opts);
1550			}
1551		} else {
1552			z80_save_reg(inst, opts);
1553		}
1554		break;
1555	case Z80_RRC:
1556		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1557			num_cycles += 8;
1558		}
1559		cycles(&opts->gen, num_cycles);
1560		if (inst->addr_mode != Z80_UNUSED) {
1561			translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
1562			translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
1563			cycles(&opts->gen, 1);
1564		} else {
1565			src_op.mode = MODE_UNUSED;
1566			translate_z80_reg(inst, &dst_op, opts);
1567		}
1568		if (dst_op.mode == MODE_REG_DIRECT) {
1569			ror_ir(code, 1, dst_op.base, SZ_B);
1570			mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1571		} else {
1572			ror_irdisp(code, 1, dst_op.base, dst_op.disp, SZ_B);
1573			mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, SZ_B);
1574			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1575		}
1576		if (src_op.mode == MODE_REG_DIRECT) {
1577			mov_rr(code, dst_op.base, src_op.base, SZ_B);
1578		} else if(src_op.mode == MODE_REG_DISPLACE8) {
1579			mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B);
1580		}
1581		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1582		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1583		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1584		if (inst->immed) {
1585			//rrca does not set these flags
1586			if (dst_op.mode == MODE_REG_DIRECT) {
1587				cmp_ir(code, 0, dst_op.base, SZ_B);
1588			} else {
1589				cmp_irdisp(code, 0, dst_op.base, dst_op.disp, SZ_B);
1590			}
1591			setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1592			setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1593			setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1594		}
1595		if (inst->addr_mode != Z80_UNUSED) {
1596			z80_save_result(opts, inst);
1597			if (src_op.mode != MODE_UNUSED) {
1598				z80_save_reg(inst, opts);
1599			}
1600		} else {
1601			z80_save_reg(inst, opts);
1602		}
1603		break;
1604	case Z80_RR:
1605		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1606			num_cycles += 8;
1607		}
1608		cycles(&opts->gen, num_cycles);
1609		if (inst->addr_mode != Z80_UNUSED) {
1610			translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
1611			translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
1612			cycles(&opts->gen, 1);
1613		} else {
1614			src_op.mode = MODE_UNUSED;
1615			translate_z80_reg(inst, &dst_op, opts);
1616		}
1617		bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1618		if (dst_op.mode == MODE_REG_DIRECT) {
1619			rcr_ir(code, 1, dst_op.base, SZ_B);
1620			mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1621		} else {
1622			rcr_irdisp(code, 1, dst_op.base, dst_op.disp, SZ_B);
1623			mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, SZ_B);
1624			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1625		}
1626		if (src_op.mode == MODE_REG_DIRECT) {
1627			mov_rr(code, dst_op.base, src_op.base, SZ_B);
1628		} else if(src_op.mode == MODE_REG_DISPLACE8) {
1629			mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B);
1630		}
1631		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1632		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1633		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1634		if (inst->immed) {
1635			//rra does not set these flags
1636			if (dst_op.mode == MODE_REG_DIRECT) {
1637				cmp_ir(code, 0, dst_op.base, SZ_B);
1638			} else {
1639				cmp_irdisp(code, 0, dst_op.base, dst_op.disp, SZ_B);
1640			}
1641			setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1642			setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1643			setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1644		}
1645		if (inst->addr_mode != Z80_UNUSED) {
1646			z80_save_result(opts, inst);
1647			if (src_op.mode != MODE_UNUSED) {
1648				z80_save_reg(inst, opts);
1649			}
1650		} else {
1651			z80_save_reg(inst, opts);
1652		}
1653		break;
1654	case Z80_SLA:
1655	case Z80_SLL:
1656		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1657			num_cycles += 8;
1658		}
1659		cycles(&opts->gen, num_cycles);
1660		if (inst->addr_mode != Z80_UNUSED) {
1661			translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
1662			translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
1663			cycles(&opts->gen, 1);
1664		} else {
1665			src_op.mode = MODE_UNUSED;
1666			translate_z80_reg(inst, &dst_op, opts);
1667		}
1668		if (dst_op.mode == MODE_REG_DIRECT) {
1669			shl_ir(code, 1, dst_op.base, SZ_B);
1670		} else {
1671			shl_irdisp(code, 1, dst_op.base, dst_op.disp, SZ_B);
1672		}
1673		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1674		if (inst->op == Z80_SLL) {
1675			if (dst_op.mode == MODE_REG_DIRECT) {
1676				or_ir(code, 1, dst_op.base, SZ_B);
1677			} else {
1678				or_irdisp(code, 1, dst_op.base, dst_op.disp, SZ_B);
1679			}
1680		}
1681		if (src_op.mode == MODE_REG_DIRECT) {
1682			mov_rr(code, dst_op.base, src_op.base, SZ_B);
1683		} else if(src_op.mode == MODE_REG_DISPLACE8) {
1684			mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B);
1685		}
1686		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1687		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1688		if (dst_op.mode == MODE_REG_DIRECT) {
1689			mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1690			cmp_ir(code, 0, dst_op.base, SZ_B);
1691		} else {
1692			mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, SZ_B);
1693			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1694			cmp_irdisp(code, 0, dst_op.base, dst_op.disp, SZ_B);
1695		}
1696		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1697		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1698		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1699		if (inst->addr_mode != Z80_UNUSED) {
1700			z80_save_result(opts, inst);
1701			if (src_op.mode != MODE_UNUSED) {
1702				z80_save_reg(inst, opts);
1703			}
1704		} else {
1705			z80_save_reg(inst, opts);
1706		}
1707		break;
1708	case Z80_SRA:
1709		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1710			num_cycles += 8;
1711		}
1712		cycles(&opts->gen, num_cycles);
1713		if (inst->addr_mode != Z80_UNUSED) {
1714			translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
1715			translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
1716			cycles(&opts->gen, 1);
1717		} else {
1718			src_op.mode = MODE_UNUSED;
1719			translate_z80_reg(inst, &dst_op, opts);
1720		}
1721		if (dst_op.mode == MODE_REG_DIRECT) {
1722			sar_ir(code, 1, dst_op.base, SZ_B);
1723		} else {
1724			sar_irdisp(code, 1, dst_op.base, dst_op.disp, SZ_B);
1725		}
1726		if (src_op.mode == MODE_REG_DIRECT) {
1727			mov_rr(code, dst_op.base, src_op.base, SZ_B);
1728		} else if(src_op.mode == MODE_REG_DISPLACE8) {
1729			mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B);
1730		}
1731		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1732		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1733		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1734		if (dst_op.mode == MODE_REG_DIRECT) {
1735			mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1736			cmp_ir(code, 0, dst_op.base, SZ_B);
1737		} else {
1738			mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, SZ_B);
1739			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1740			cmp_irdisp(code, 0, dst_op.base, dst_op.disp, SZ_B);
1741		}
1742		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1743		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1744		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1745		if (inst->addr_mode != Z80_UNUSED) {
1746			z80_save_result(opts, inst);
1747			if (src_op.mode != MODE_UNUSED) {
1748				z80_save_reg(inst, opts);
1749			}
1750		} else {
1751			z80_save_reg(inst, opts);
1752		}
1753		break;
1754	case Z80_SRL:
1755		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1756			num_cycles += 8;
1757		}
1758		cycles(&opts->gen, num_cycles);
1759		if (inst->addr_mode != Z80_UNUSED) {
1760			translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
1761			translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
1762			cycles(&opts->gen, 1);
1763		} else {
1764			src_op.mode = MODE_UNUSED;
1765			translate_z80_reg(inst, &dst_op, opts);
1766		}
1767		if (dst_op.mode == MODE_REG_DIRECT) {
1768			shr_ir(code, 1, dst_op.base, SZ_B);
1769		} else {
1770			shr_irdisp(code, 1, dst_op.base, dst_op.disp, SZ_B);
1771		}
1772		if (src_op.mode == MODE_REG_DIRECT) {
1773			mov_rr(code, dst_op.base, src_op.base, SZ_B);
1774		} else if(src_op.mode == MODE_REG_DISPLACE8) {
1775			mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B);
1776		}
1777		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1778		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1779		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1780		if (dst_op.mode == MODE_REG_DIRECT) {
1781			mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1782			cmp_ir(code, 0, dst_op.base, SZ_B);
1783		} else {
1784			mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, SZ_B);
1785			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1786			cmp_irdisp(code, 0, dst_op.base, dst_op.disp, SZ_B);
1787		}
1788		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1789		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1790		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1791		if (inst->addr_mode != Z80_UNUSED) {
1792			z80_save_result(opts, inst);
1793			if (src_op.mode != MODE_UNUSED) {
1794				z80_save_reg(inst, opts);
1795			}
1796		} else {
1797			z80_save_reg(inst, opts);
1798		}
1799		break;
1800	case Z80_RLD:
1801		cycles(&opts->gen, num_cycles);
1802		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
1803		call(code, opts->read_8);
1804		//Before: (HL) = 0x12, A = 0x34
1805		//After: (HL) = 0x24, A = 0x31
1806		zreg_to_native(opts, Z80_A, opts->gen.scratch2);
1807		shl_ir(code, 4, opts->gen.scratch1, SZ_W);
1808		and_ir(code, 0xF, opts->gen.scratch2, SZ_W);
1809		and_ir(code, 0xFFF, opts->gen.scratch1, SZ_W);
1810		and_ir(code, 0xF0, opts->regs[Z80_A], SZ_B);
1811		or_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_W);
1812		//opts->gen.scratch1 = 0x0124
1813		ror_ir(code, 8, opts->gen.scratch1, SZ_W);
1814		cycles(&opts->gen, 4);
1815		or_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B);
1816		//set flags
1817		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1818		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1819		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1820		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1821		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1822		mov_rrdisp(code, opts->regs[Z80_A], opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1823
1824		zreg_to_native(opts, Z80_HL, opts->gen.scratch2);
1825		ror_ir(code, 8, opts->gen.scratch1, SZ_W);
1826		call(code, opts->write_8);
1827		break;
1828	case Z80_RRD:
1829		cycles(&opts->gen, num_cycles);
1830		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
1831		call(code, opts->read_8);
1832		//Before: (HL) = 0x12, A = 0x34
1833		//After: (HL) = 0x41, A = 0x32
1834		zreg_to_native(opts, Z80_A, opts->gen.scratch2);
1835		ror_ir(code, 4, opts->gen.scratch1, SZ_W);
1836		shl_ir(code, 4, opts->gen.scratch2, SZ_W);
1837		and_ir(code, 0xF00F, opts->gen.scratch1, SZ_W);
1838		and_ir(code, 0xF0, opts->regs[Z80_A], SZ_B);
1839		and_ir(code, 0xF0, opts->gen.scratch2, SZ_W);
1840		//opts->gen.scratch1 = 0x2001
1841		//opts->gen.scratch2 = 0x0040
1842		or_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_W);
1843		//opts->gen.scratch1 = 0x2041
1844		ror_ir(code, 8, opts->gen.scratch1, SZ_W);
1845		cycles(&opts->gen, 4);
1846		shr_ir(code, 4, opts->gen.scratch1, SZ_B);
1847		or_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B);
1848		//set flags
1849		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1850		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1851		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1852		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1853		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1854		mov_rrdisp(code, opts->regs[Z80_A], opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1855
1856		zreg_to_native(opts, Z80_HL, opts->gen.scratch2);
1857		ror_ir(code, 8, opts->gen.scratch1, SZ_W);
1858		call(code, opts->write_8);
1859		break;
1860	case Z80_BIT: {
1861		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1862			num_cycles += 4;
1863		}
1864		cycles(&opts->gen, num_cycles);
1865		uint8_t bit;
1866		if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) {
1867			src_op.base = opts->regs[z80_word_reg(inst->ea_reg)];
1868			src_op.mode = MODE_REG_DIRECT;
1869			size = SZ_W;
1870			bit = inst->immed + 8;
1871		} else {
1872			size = SZ_B;
1873			bit = inst->immed;
1874			translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
1875		}
1876		if (inst->addr_mode != Z80_REG) {
1877			//Reads normally take 3 cycles, but the read at the end of a bit instruction takes 4
1878			cycles(&opts->gen, 1);
1879		}
1880		if (src_op.mode == MODE_REG_DIRECT) {
1881			bt_ir(code, bit, src_op.base, size);
1882		} else {
1883			bt_irdisp(code, bit, src_op.base, src_op.disp, size);
1884		}
1885		setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_Z));
1886		setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_PV));
1887		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1888		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1889		if (inst->immed == 7) {
1890			if (src_op.mode == MODE_REG_DIRECT) {
1891				cmp_ir(code, 0, src_op.base, size);
1892			} else {
1893				cmp_irdisp(code, 0, src_op.base, src_op.disp, size);
1894			}
1895			setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1896		} else {
1897			mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_S), SZ_B);
1898		}
1899		
1900		if ((inst->addr_mode & 0x1F) == Z80_REG) {
1901			if (src_op.mode == MODE_REG_DIRECT) {
1902				if (size == SZ_W) {
1903					mov_rr(code, src_op.base, opts->gen.scratch1, SZ_W);
1904					shr_ir(code, 8, opts->gen.scratch1, SZ_W);
1905					mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1906				} else {
1907					mov_rrdisp(code, src_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1908				}
1909			} else {
1910				mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_B);
1911				mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1912			}
1913		} else if((inst->addr_mode & 0x1F) != Z80_REG_INDIRECT) {
1914			zreg_to_native(opts, (inst->addr_mode & 0x1F) == Z80_IX_DISPLACE ? Z80_IX : Z80_IY, opts->gen.scratch2);
1915			add_ir(code, inst->ea_reg & 0x80 ? inst->ea_reg - 256 : inst->ea_reg, opts->gen.scratch2, SZ_W);
1916			shr_ir(code, 8, opts->gen.scratch2, SZ_W);
1917			mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1918		}
1919		break;
1920	}
1921	case Z80_SET: {
1922		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1923			num_cycles += 4;
1924		}
1925		cycles(&opts->gen, num_cycles);
1926		uint8_t bit;
1927		if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) {
1928			src_op.base = opts->regs[z80_word_reg(inst->ea_reg)];
1929			src_op.mode = MODE_REG_DIRECT;
1930			size = SZ_W;
1931			bit = inst->immed + 8;
1932		} else {
1933			size = SZ_B;
1934			bit = inst->immed;
1935			translate_z80_ea(inst, &src_op, opts, READ, MODIFY);
1936		}
1937		if (inst->reg != Z80_USE_IMMED) {
1938			translate_z80_reg(inst, &dst_op, opts);
1939		}
1940		if (inst->addr_mode != Z80_REG) {
1941			//Reads normally take 3 cycles, but the read in the middle of a set instruction takes 4
1942			cycles(&opts->gen, 1);
1943		}
1944		if (src_op.mode == MODE_REG_DIRECT) {
1945			bts_ir(code, bit, src_op.base, size);
1946		} else {
1947			bts_irdisp(code, bit, src_op.base, src_op.disp, size);
1948		}
1949		if (inst->reg != Z80_USE_IMMED) {
1950			if (size == SZ_W) {
1951#ifdef X86_64
1952				if (dst_op.base >= R8) {
1953					ror_ir(code, 8, src_op.base, SZ_W);
1954					mov_rr(code, opts->regs[z80_low_reg(inst->ea_reg)], dst_op.base, SZ_B);
1955					ror_ir(code, 8, src_op.base, SZ_W);
1956				} else {
1957#endif
1958					if (dst_op.mode == MODE_REG_DIRECT) {
1959						zreg_to_native(opts, inst->ea_reg, dst_op.base);
1960					} else {
1961						zreg_to_native(opts, inst->ea_reg, opts->gen.scratch1);
1962						mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, SZ_B);
1963					}
1964#ifdef X86_64
1965				}
1966#endif
1967			} else {
1968				if (dst_op.mode == MODE_REG_DIRECT) {
1969					if (src_op.mode == MODE_REG_DIRECT) {
1970						mov_rr(code, src_op.base, dst_op.base, SZ_B);
1971					} else {
1972						mov_rdispr(code, src_op.base, src_op.disp, dst_op.base, SZ_B);
1973					}
1974				} else if (src_op.mode == MODE_REG_DIRECT) {
1975					mov_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, SZ_B);
1976				} else {
1977					mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_B);
1978					mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, SZ_B);
1979				}
1980			}
1981		}
1982		if ((inst->addr_mode & 0x1F) != Z80_REG) {
1983			z80_save_result(opts, inst);
1984			if (inst->reg != Z80_USE_IMMED) {
1985				z80_save_reg(inst, opts);
1986			}
1987		}
1988		break;
1989	}
1990	case Z80_RES: {
1991		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1992			num_cycles += 4;
1993		}
1994		cycles(&opts->gen, num_cycles);
1995		uint8_t bit;
1996		if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) {
1997			src_op.base = opts->regs[z80_word_reg(inst->ea_reg)];
1998			src_op.mode = MODE_REG_DIRECT;
1999			size = SZ_W;
2000			bit = inst->immed + 8;
2001		} else {
2002			size = SZ_B;
2003			bit = inst->immed;
2004			translate_z80_ea(inst, &src_op, opts, READ, MODIFY);
2005		}
2006		if (inst->reg != Z80_USE_IMMED) {
2007			translate_z80_reg(inst, &dst_op, opts);
2008		}
2009		if (inst->addr_mode != Z80_REG) {
2010			//Reads normally take 3 cycles, but the read in the middle of a set instruction takes 4
2011			cycles(&opts->gen, 1);
2012		}
2013		if (src_op.mode == MODE_REG_DIRECT) {
2014			btr_ir(code, bit, src_op.base, size);
2015		} else {
2016			btr_irdisp(code, bit, src_op.base, src_op.disp, size);
2017		}
2018		if (inst->reg != Z80_USE_IMMED) {
2019			if (size == SZ_W) {
2020#ifdef X86_64
2021				if (dst_op.base >= R8) {
2022					ror_ir(code, 8, src_op.base, SZ_W);
2023					mov_rr(code, opts->regs[z80_low_reg(inst->ea_reg)], dst_op.base, SZ_B);
2024					ror_ir(code, 8, src_op.base, SZ_W);
2025				} else {
2026#endif
2027					if (dst_op.mode == MODE_REG_DIRECT) {
2028						zreg_to_native(opts, inst->ea_reg, dst_op.base);
2029					} else {
2030						zreg_to_native(opts, inst->ea_reg, opts->gen.scratch1);
2031						mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, SZ_B);
2032					}
2033#ifdef X86_64
2034				}
2035#endif
2036			} else {
2037				if (dst_op.mode == MODE_REG_DIRECT) {
2038					if (src_op.mode == MODE_REG_DIRECT) {
2039						mov_rr(code, src_op.base, dst_op.base, SZ_B);
2040					} else {
2041						mov_rdispr(code, src_op.base, src_op.disp, dst_op.base, SZ_B);
2042					}
2043				} else if (src_op.mode == MODE_REG_DIRECT) {
2044					mov_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, SZ_B);
2045				} else {
2046					mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_B);
2047					mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, SZ_B);
2048				}
2049			}
2050		}
2051		if (inst->addr_mode != Z80_REG) {
2052			z80_save_result(opts, inst);
2053			if (inst->reg != Z80_USE_IMMED) {
2054				z80_save_reg(inst, opts);
2055			}
2056		}
2057		break;
2058	}
2059	case Z80_JP: {
2060		if (inst->addr_mode != Z80_REG_INDIRECT) {
2061			num_cycles += 6;
2062		}
2063		cycles(&opts->gen, num_cycles);
2064		if (inst->addr_mode != Z80_REG_INDIRECT) {
2065			code_ptr call_dst = z80_get_native_address(context, inst->immed);
2066			if (!call_dst) {
2067				opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
2068				//fake address to force large displacement
2069				call_dst = code->cur + 256;
2070			}
2071			jmp(code, call_dst);
2072		} else {
2073			if (inst->addr_mode == Z80_REG_INDIRECT) {
2074				zreg_to_native(opts, inst->ea_reg, opts->gen.scratch1);
2075			} else {
2076				mov_ir(code, inst->immed, opts->gen.scratch1, SZ_W);
2077			}
2078			call(code, opts->native_addr);
2079			jmp_r(code, opts->gen.scratch1);
2080		}
2081		break;
2082	}
2083	case Z80_JPCC: {
2084		cycles(&opts->gen, num_cycles + 6);//T States: 4,3,3
2085		uint8_t cond = CC_Z;
2086		switch (inst->reg)
2087		{
2088		case Z80_CC_NZ:
2089			cond = CC_NZ;
2090		case Z80_CC_Z:
2091			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_Z), SZ_B);
2092			break;
2093		case Z80_CC_NC:
2094			cond = CC_NZ;
2095		case Z80_CC_C:
2096			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
2097			break;
2098		case Z80_CC_PO:
2099			cond = CC_NZ;
2100		case Z80_CC_PE:
2101			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
2102			break;
2103		case Z80_CC_P:
2104			cond = CC_NZ;
2105		case Z80_CC_M:
2106			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_S), SZ_B);
2107			break;
2108		}
2109		uint8_t *no_jump_off = code->cur+1;
2110		jcc(code, cond, code->cur+2);
2111		uint16_t dest_addr = inst->immed;
2112		code_ptr call_dst = z80_get_native_address(context, dest_addr);
2113			if (!call_dst) {
2114			opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
2115				//fake address to force large displacement
2116			call_dst = code->cur + 256;
2117			}
2118		jmp(code, call_dst);
2119		*no_jump_off = code->cur - (no_jump_off+1);
2120		break;
2121	}
2122	case Z80_JR: {
2123		cycles(&opts->gen, num_cycles + 8);//T States: 4,3,5
2124		uint16_t dest_addr = address + inst->immed + 2;
2125		code_ptr call_dst = z80_get_native_address(context, dest_addr);
2126			if (!call_dst) {
2127			opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
2128				//fake address to force large displacement
2129			call_dst = code->cur + 256;
2130			}
2131		jmp(code, call_dst);
2132		break;
2133	}
2134	case Z80_JRCC: {
2135		cycles(&opts->gen, num_cycles + 3);//T States: 4,3
2136		uint8_t cond = CC_Z;
2137		switch (inst->reg)
2138		{
2139		case Z80_CC_NZ:
2140			cond = CC_NZ;
2141		case Z80_CC_Z:
2142			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_Z), SZ_B);
2143			break;
2144		case Z80_CC_NC:
2145			cond = CC_NZ;
2146		case Z80_CC_C:
2147			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
2148			break;
2149		}
2150		uint8_t *no_jump_off = code->cur+1;
2151		jcc(code, cond, code->cur+2);
2152		cycles(&opts->gen, 5);//T States: 5
2153		uint16_t dest_addr = address + inst->immed + 2;
2154		code_ptr call_dst = z80_get_native_address(context, dest_addr);
2155			if (!call_dst) {
2156			opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
2157				//fake address to force large displacement
2158			call_dst = code->cur + 256;
2159			}
2160		jmp(code, call_dst);
2161		*no_jump_off = code->cur - (no_jump_off+1);
2162		break;
2163	}
2164	case Z80_DJNZ: {
2165		cycles(&opts->gen, num_cycles + 4);//T States: 5,3
2166		if (opts->regs[Z80_B] >= 0) {
2167			sub_ir(code, 1, opts->regs[Z80_B], SZ_B);
2168		} else {
2169			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2170		}
2171		uint8_t *no_jump_off = code->cur+1;
2172		jcc(code, CC_Z, code->cur+2);
2173		cycles(&opts->gen, 5);//T States: 5
2174		uint16_t dest_addr = address + inst->immed + 2;
2175		code_ptr call_dst = z80_get_native_address(context, dest_addr);
2176			if (!call_dst) {
2177			opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
2178				//fake address to force large displacement
2179			call_dst = code->cur + 256;
2180			}
2181		jmp(code, call_dst);
2182		*no_jump_off = code->cur - (no_jump_off+1);
2183		break;
2184		}
2185	case Z80_CALL: {
2186		cycles(&opts->gen, num_cycles + 7);//T States: 4,3,4
2187		sub_ir(code, 2, opts->regs[Z80_SP], SZ_W);
2188		mov_ir(code, address + 3, opts->gen.scratch1, SZ_W);
2189		mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
2190		call(code, opts->write_16_highfirst);//T States: 3, 3
2191		code_ptr call_dst = z80_get_native_address(context, inst->immed);
2192			if (!call_dst) {
2193			opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
2194				//fake address to force large displacement
2195			call_dst = code->cur + 256;
2196			}
2197		jmp(code, call_dst);
2198		break;
2199	}
2200	case Z80_CALLCC: {
2201		cycles(&opts->gen, num_cycles + 6);//T States: 4,3,3 (false case)
2202		uint8_t cond = CC_Z;
2203		switch (inst->reg)
2204		{
2205		case Z80_CC_NZ:
2206			cond = CC_NZ;
2207		case Z80_CC_Z:
2208			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_Z), SZ_B);
2209			break;
2210		case Z80_CC_NC:
2211			cond = CC_NZ;
2212		case Z80_CC_C:
2213			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
2214			break;
2215		case Z80_CC_PO:
2216			cond = CC_NZ;
2217		case Z80_CC_PE:
2218			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
2219			break;
2220		case Z80_CC_P:
2221			cond = CC_NZ;
2222		case Z80_CC_M:
2223			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_S), SZ_B);
2224			break;
2225		}
2226		uint8_t *no_call_off = code->cur+1;
2227		jcc(code, cond, code->cur+2);
2228		cycles(&opts->gen, 1);//Last of the above T states takes an extra cycle in the true case
2229		sub_ir(code, 2, opts->regs[Z80_SP], SZ_W);
2230		mov_ir(code, address + 3, opts->gen.scratch1, SZ_W);
2231		mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
2232		call(code, opts->write_16_highfirst);//T States: 3, 3
2233		code_ptr call_dst = z80_get_native_address(context, inst->immed);
2234			if (!call_dst) {
2235			opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
2236				//fake address to force large displacement
2237			call_dst = code->cur + 256;
2238			}
2239		jmp(code, call_dst);
2240		*no_call_off = code->cur - (no_call_off+1);
2241		break;
2242		}
2243	case Z80_RET:
2244		cycles(&opts->gen, num_cycles);//T States: 4
2245		mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
2246		call(code, opts->read_16);//T STates: 3, 3
2247		add_ir(code, 2, opts->regs[Z80_SP], SZ_W);
2248		call(code, opts->native_addr);
2249		jmp_r(code, opts->gen.scratch1);
2250		break;
2251	case Z80_RETCC: {
2252		cycles(&opts->gen, num_cycles + 1);//T States: 5
2253		uint8_t cond = CC_Z;
2254		switch (inst->reg)
2255		{
2256		case Z80_CC_NZ:
2257			cond = CC_NZ;
2258		case Z80_CC_Z:
2259			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_Z), SZ_B);
2260			break;
2261		case Z80_CC_NC:
2262			cond = CC_NZ;
2263		case Z80_CC_C:
2264			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
2265			break;
2266		case Z80_CC_PO:
2267			cond = CC_NZ;
2268		case Z80_CC_PE:
2269			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
2270			break;
2271		case Z80_CC_P:
2272			cond = CC_NZ;
2273		case Z80_CC_M:
2274			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_S), SZ_B);
2275			break;
2276		}
2277		uint8_t *no_call_off = code->cur+1;
2278		jcc(code, cond, code->cur+2);
2279		mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
2280		call(code, opts->read_16);//T STates: 3, 3
2281		add_ir(code, 2, opts->regs[Z80_SP], SZ_W);
2282		call(code, opts->native_addr);
2283		jmp_r(code, opts->gen.scratch1);
2284		*no_call_off = code->cur - (no_call_off+1);
2285		break;
2286	}
2287	case Z80_RETI:
2288		//For some systems, this may need a callback for signalling interrupt routine completion
2289		cycles(&opts->gen, num_cycles);//T States: 4, 4
2290		mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
2291		call(code, opts->read_16);//T STates: 3, 3
2292		add_ir(code, 2, opts->regs[Z80_SP], SZ_W);
2293		call(code, opts->native_addr);
2294		jmp_r(code, opts->gen.scratch1);
2295		break;
2296	case Z80_RETN:
2297		cycles(&opts->gen, num_cycles);//T States: 4, 4
2298		mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, iff2), opts->gen.scratch2, SZ_B);
2299		mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
2300		mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B);
2301		call(code, opts->read_16);//T STates: 3, 3
2302		add_ir(code, 2, opts->regs[Z80_SP], SZ_W);
2303		call(code, opts->native_addr);
2304		jmp_r(code, opts->gen.scratch1);
2305		break;
2306	case Z80_RST: {
2307		//RST is basically CALL to an address in page 0
2308		cycles(&opts->gen, num_cycles + 1);//T States: 5
2309		sub_ir(code, 2, opts->regs[Z80_SP], SZ_W);
2310		mov_ir(code, address + 1, opts->gen.scratch1, SZ_W);
2311		mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
2312		call(code, opts->write_16_highfirst);//T States: 3, 3
2313		code_ptr call_dst = z80_get_native_address(context, inst->immed);
2314		if (!call_dst) {
2315			opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
2316			//fake address to force large displacement
2317			call_dst = code->cur + 256;
2318		}
2319		jmp(code, call_dst);
2320		break;
2321	}
2322	case Z80_IN:
2323		if (inst->addr_mode == Z80_IMMED_INDIRECT) {
2324			num_cycles += 3;
2325		}
2326		cycles(&opts->gen, num_cycles);//T States: 4 3/4
2327		if (inst->addr_mode == Z80_IMMED_INDIRECT) {
2328			mov_ir(code, inst->immed, opts->gen.scratch1, SZ_B);
2329		} else {
2330			zreg_to_native(opts, Z80_C, opts->gen.scratch2);
2331		}
2332		call(code, opts->read_io);
2333		if (inst->addr_mode != Z80_IMMED_INDIRECT) {
2334			or_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_B);
2335			mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
2336			mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
2337			setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
2338			setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
2339			setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
2340		}
2341		if (inst->reg != Z80_UNUSED) {
2342			translate_z80_reg(inst, &dst_op, opts);
2343			if (dst_op.mode == MODE_REG_DIRECT) {
2344				mov_rr(code, opts->gen.scratch1, dst_op.base, SZ_B);
2345			} else {
2346				mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, SZ_B);
2347			}
2348		}
2349		z80_save_reg(inst, opts);
2350		break;
2351	case Z80_INI:
2352		cycles(&opts->gen, num_cycles + 1);//T States: 4, 5
2353		//read from IO (C)
2354		zreg_to_native(opts, Z80_BC, opts->gen.scratch1);
2355		call(code, opts->read_io);//T states 3
2356		
2357		//undocumented N flag behavior
2358		//flag set on bit 7 of value written
2359		bt_ir(code, 7, opts->gen.scratch1, SZ_B);
2360		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_N));
2361		//save value to be written for flag calculation, as the write func does not
2362		//guarantee that it's preserved across the call
2363		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_B);
2364		
2365		//write to (HL)
2366		zreg_to_native(opts, Z80_HL, opts->gen.scratch2);
2367		call(code, opts->write_8);//T states 4
2368		cycles(&opts->gen, 1);
2369		
2370		//increment HL
2371		if (opts->regs[Z80_HL] >= 0) {
2372			add_ir(code, 1, opts->regs[Z80_HL], SZ_W);
2373		} else {
2374			add_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B);
2375		}
2376		mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch1, SZ_B);
2377		if (opts->regs[Z80_C] >= 0) {
2378			add_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
2379		} else {
2380			add_rdispr(code, opts->gen.context_reg, zr_off(Z80_C), opts->gen.scratch1, SZ_B);
2381		}
2382		add_ir(code, 1, opts->gen.scratch1, SZ_B);
2383		//undocumented C and H flag behavior
2384		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
2385		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
2386		//decrement B
2387		if (opts->regs[Z80_B] >= 0) {
2388			sub_ir(code, 1, opts->regs[Z80_B], SZ_B);
2389			mov_rrdisp(code, opts->regs[Z80_B], opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
2390		} else {
2391			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2392		}
2393		//undocumented Z and S flag behavior, set based on decrement of B
2394		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
2395		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
2396		//crazy undocumented P/V flag behavior
2397		and_ir(code, 7, opts->gen.scratch1, SZ_B);
2398		if (opts->regs[Z80_B] >= 0) {
2399			//deal with silly x86-64 restrictions on *H registers
2400			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2401			xor_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
2402			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2403		} else {
2404			xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B);
2405		}
2406		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
2407		break;
2408	case Z80_INIR: {
2409		cycles(&opts->gen, num_cycles + 1);//T States: 4, 5
2410		//read from IO (C)
2411		zreg_to_native(opts, Z80_BC, opts->gen.scratch1);
2412		call(code, opts->read_io);//T states 3
2413		
2414		//undocumented N flag behavior
2415		//flag set on bit 7 of value written
2416		bt_ir(code, 7, opts->gen.scratch1, SZ_B);
2417		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_N));
2418		//save value to be written for flag calculation, as the write func does not
2419		//guarantee that it's preserved across the call
2420		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_B);
2421		
2422		//write to (HL)
2423		zreg_to_native(opts, Z80_HL, opts->gen.scratch2);
2424		call(code, opts->write_8);//T states 4
2425		cycles(&opts->gen, 1);
2426		
2427		//increment HL
2428		if (opts->regs[Z80_HL] >= 0) {
2429			add_ir(code, 1, opts->regs[Z80_HL], SZ_W);
2430		} else {
2431			add_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B);
2432		}
2433		mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch1, SZ_B);
2434		if (opts->regs[Z80_C] >= 0) {
2435			add_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
2436		} else {
2437			add_rdispr(code, opts->gen.context_reg, zr_off(Z80_C), opts->gen.scratch1, SZ_B);
2438		}
2439		add_ir(code, 1, opts->gen.scratch1, SZ_B);
2440		//undocumented C and H flag behavior
2441		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
2442		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
2443		//decrement B
2444		if (opts->regs[Z80_B] >= 0) {
2445			sub_ir(code, 1, opts->regs[Z80_B], SZ_B);
2446			mov_rrdisp(code, opts->regs[Z80_B], opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
2447		} else {
2448			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2449		}
2450		//undocumented Z and S flag behavior, set based on decrement of B
2451		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
2452		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
2453		//crazy undocumented P/V flag behavior
2454		and_ir(code, 7, opts->gen.scratch1, SZ_B);
2455		if (opts->regs[Z80_B] >= 0) {
2456			//deal with silly x86-64 restrictions on *H registers
2457			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2458			xor_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
2459			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2460		} else {
2461			xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B);
2462		}
2463		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
2464		if (opts->regs[Z80_B] >= 0) {
2465			cmp_ir(code, 0, opts->regs[Z80_B], SZ_B);
2466		} else {
2467			cmp_irdisp(code, 0, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2468		}
2469		code_ptr done = code->cur+1;
2470		jcc(code, CC_Z, code->cur+2);
2471		cycles(&opts->gen, 5);
2472		jmp(code, start);
2473		*done = code->cur - (done + 1);
2474		break;
2475	}
2476	case Z80_IND:
2477		cycles(&opts->gen, num_cycles + 1);//T States: 4, 5
2478		//read from IO (C)
2479		zreg_to_native(opts, Z80_BC, opts->gen.scratch1);
2480		call(code, opts->read_io);//T states 3
2481		
2482		//undocumented N flag behavior
2483		//flag set on bit 7 of value written
2484		bt_ir(code, 7, opts->gen.scratch1, SZ_B);
2485		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_N));
2486		//save value to be written for flag calculation, as the write func does not
2487		//guarantee that it's preserved across the call
2488		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_B);
2489		
2490		//write to (HL)
2491		zreg_to_native(opts, Z80_HL, opts->gen.scratch2);
2492		call(code, opts->write_8);//T states 4
2493		cycles(&opts->gen, 1);
2494		
2495		//decrement HL
2496		if (opts->regs[Z80_HL] >= 0) {
2497			sub_ir(code, 1, opts->regs[Z80_HL], SZ_W);
2498		} else {
2499			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B);
2500		}
2501		mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch1, SZ_B);
2502		if (opts->regs[Z80_C] >= 0) {
2503			add_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
2504		} else {
2505			add_rdispr(code, opts->gen.context_reg, zr_off(Z80_C), opts->gen.scratch1, SZ_B);
2506		}
2507		add_ir(code, 1, opts->gen.scratch1, SZ_B);
2508		//undocumented C and H flag behavior
2509		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
2510		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
2511		//decrement B
2512		if (opts->regs[Z80_B] >= 0) {
2513			sub_ir(code, 1, opts->regs[Z80_B], SZ_B);
2514			mov_rrdisp(code, opts->regs[Z80_B], opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
2515		} else {
2516			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2517		}
2518		//undocumented Z and S flag behavior, set based on decrement of B
2519		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
2520		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
2521		//crazy undocumented P/V flag behavior
2522		and_ir(code, 7, opts->gen.scratch1, SZ_B);
2523		if (opts->regs[Z80_B] >= 0) {
2524			//deal with silly x86-64 restrictions on *H registers
2525			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2526			xor_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
2527			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2528		} else {
2529			xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B);
2530		}
2531		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
2532		break;
2533	case Z80_INDR: {
2534		cycles(&opts->gen, num_cycles + 1);//T States: 4, 5
2535		//read from IO (C)
2536		zreg_to_native(opts, Z80_BC, opts->gen.scratch1);
2537		call(code, opts->read_io);//T states 3
2538		
2539		//undocumented N flag behavior
2540		//flag set on bit 7 of value written
2541		bt_ir(code, 7, opts->gen.scratch1, SZ_B);
2542		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_N));
2543		//save value to be written for flag calculation, as the write func does not
2544		//guarantee that it's preserved across the call
2545		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_B);
2546		
2547		//write to (HL)
2548		zreg_to_native(opts, Z80_HL, opts->gen.scratch2);
2549		call(code, opts->write_8);//T states 4
2550		cycles(&opts->gen, 1);
2551		
2552		//decrement HL
2553		if (opts->regs[Z80_HL] >= 0) {
2554			sub_ir(code, 1, opts->regs[Z80_HL], SZ_W);
2555		} else {
2556			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B);
2557		}
2558		mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch1, SZ_B);
2559		if (opts->regs[Z80_C] >= 0) {
2560			add_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
2561		} else {
2562			add_rdispr(code, opts->gen.context_reg, zr_off(Z80_C), opts->gen.scratch1, SZ_B);
2563		}
2564		add_ir(code, 1, opts->gen.scratch1, SZ_B);
2565		//undocumented C and H flag behavior
2566		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
2567		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
2568		//decrement B
2569		if (opts->regs[Z80_B] >= 0) {
2570			sub_ir(code, 1, opts->regs[Z80_B], SZ_B);
2571			mov_rrdisp(code, opts->regs[Z80_B], opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
2572		} else {
2573			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2574		}
2575		//undocumented Z and S flag behavior, set based on decrement of B
2576		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
2577		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
2578		//crazy undocumented P/V flag behavior
2579		and_ir(code, 7, opts->gen.scratch1, SZ_B);
2580		if (opts->regs[Z80_B] >= 0) {
2581			//deal with silly x86-64 restrictions on *H registers
2582			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2583			xor_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
2584			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2585		} else {
2586			xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B);
2587		}
2588		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
2589		if (opts->regs[Z80_B] >= 0) {
2590			cmp_ir(code, 0, opts->regs[Z80_B], SZ_B);
2591		} else {
2592			cmp_irdisp(code, 0, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2593		}
2594		code_ptr done = code->cur+1;
2595		jcc(code, CC_Z, code->cur+2);
2596		cycles(&opts->gen, 5);
2597		jmp(code, start);
2598		*done = code->cur - (done + 1);
2599		break;
2600	}
2601	case Z80_OUT:
2602		if (inst->addr_mode == Z80_IMMED_INDIRECT) {
2603			num_cycles += 3;
2604		}
2605		cycles(&opts->gen, num_cycles);//T States: 4 3/4
2606		if ((inst->addr_mode & 0x1F) == Z80_IMMED_INDIRECT) {
2607			mov_ir(code, inst->immed, opts->gen.scratch2, SZ_B);
2608		} else {
2609			zreg_to_native(opts, Z80_C, opts->gen.scratch2);
2610		}
2611		translate_z80_reg(inst, &src_op, opts);
2612		if (src_op.mode == MODE_REG_DIRECT) {
2613			mov_rr(code, src_op.base, opts->gen.scratch1, SZ_B);
2614		} else if (src_op.mode == MODE_IMMED) {
2615			mov_ir(code, src_op.disp, opts->gen.scratch1, SZ_B);
2616		} else {
2617			mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_B);
2618		}
2619		call(code, opts->write_io);
2620		z80_save_reg(inst, opts);
2621		break;
2622	case Z80_OUTI:
2623		cycles(&opts->gen, num_cycles + 1);//T States: 4, 5
2624		//read from (HL)
2625		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
2626		call(code, opts->read_8);//T states 3
2627		//undocumented N flag behavior
2628		//flag set on bit 7 of value written
2629		bt_ir(code, 7, opts->gen.scratch1, SZ_B);
2630		setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_N)); 
2631		//write to IO (C)
2632		zreg_to_native(opts, Z80_C, opts->gen.scratch2);
2633		call(code, opts->write_io);//T states 4
2634		//increment HL
2635		if (opts->regs[Z80_HL] >= 0) {
2636			add_ir(code, 1, opts->regs[Z80_HL], SZ_W);
2637			add_rr(code, opts->regs[Z80_L], opts->gen.scratch1, SZ_B);
2638		} else {
2639			add_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B);
2640			add_rdispr(code, opts->gen.context_reg, zr_off(Z80_L), opts->gen.scratch1, SZ_B);
2641		}
2642		//undocumented C and H flag behavior
2643		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
2644		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
2645		//decrement B
2646		if (opts->regs[Z80_B] >= 0) {
2647			sub_ir(code, 1, opts->regs[Z80_B], SZ_B);
2648		} else {
2649			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2650		}
2651		//undocumented Z and S flag behavior, set based on decrement of B
2652		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
2653		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
2654		//crazy undocumented P/V flag behavior
2655		and_ir(code, 7, opts->gen.scratch1, SZ_B);
2656		if (opts->regs[Z80_B] >= 0) {
2657			//deal with silly x86-64 restrictions on *H registers
2658			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2659			xor_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
2660			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2661		} else {
2662			xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B);
2663		}
2664		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
2665		break;
2666	case Z80_OTIR: {
2667		cycles(&opts->gen, num_cycles + 1);//T States: 4, 5
2668		//read from (HL)
2669		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
2670		call(code, opts->read_8);//T states 3
2671		//undocumented N flag behavior
2672		//flag set on bit 7 of value written
2673		bt_ir(code, 7, opts->gen.scratch1, SZ_B);
2674		setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_N)); 
2675		//write to IO (C)
2676		zreg_to_native(opts, Z80_C, opts->gen.scratch2);
2677		call(code, opts->write_io);//T states 4
2678		//increment HL
2679		if (opts->regs[Z80_HL] >= 0) {
2680			add_ir(code, 1, opts->regs[Z80_HL], SZ_W);
2681			add_rr(code, opts->regs[Z80_L], opts->gen.scratch1, SZ_B);
2682		} else {
2683			add_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B);
2684			add_rdispr(code, opts->gen.context_reg, zr_off(Z80_L), opts->gen.scratch1, SZ_B);
2685		}
2686		//undocumented C and H flag behavior
2687		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
2688		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
2689		//decrement B
2690		if (opts->regs[Z80_B] >= 0) {
2691			sub_ir(code, 1, opts->regs[Z80_B], SZ_B);
2692		} else {
2693			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2694		}
2695		//undocumented Z and S flag behavior, set based on decrement of B
2696		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
2697		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
2698		//crazy undocumented P/V flag behavior
2699		and_ir(code, 7, opts->gen.scratch1, SZ_B);
2700		if (opts->regs[Z80_B] >= 0) {
2701			//deal with silly x86-64 restrictions on *H registers
2702			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2703			xor_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
2704			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2705		} else {
2706			xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B);
2707		}
2708		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
2709		if (opts->regs[Z80_B] >= 0) {
2710			cmp_ir(code, 0, opts->regs[Z80_B], SZ_B);
2711		} else {
2712			cmp_irdisp(code, 0, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2713		}
2714		code_ptr done = code->cur+1;
2715		jcc(code, CC_Z, code->cur+2);
2716		cycles(&opts->gen, 5);
2717		jmp(code, start);
2718		*done = code->cur - (done + 1);
2719		break;
2720	}
2721	case Z80_OUTD:
2722		cycles(&opts->gen, num_cycles + 1);//T States: 4, 5
2723		//read from (HL)
2724		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
2725		call(code, opts->read_8);//T states 3
2726		//undocumented N flag behavior
2727		//flag set on bit 7 of value written
2728		bt_ir(code, 7, opts->gen.scratch1, SZ_B);
2729		setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_N)); 
2730		//write to IO (C)
2731		zreg_to_native(opts, Z80_C, opts->gen.scratch2);
2732		call(code, opts->write_io);//T states 4
2733		//decrement HL
2734		if (opts->regs[Z80_HL] >= 0) {
2735			sub_ir(code, 1, opts->regs[Z80_HL], SZ_W);
2736			add_rr(code, opts->regs[Z80_L], opts->gen.scratch1, SZ_B);
2737		} else {
2738			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B);
2739			add_rdispr(code, opts->gen.context_reg, zr_off(Z80_L), opts->gen.scratch1, SZ_B);
2740		}
2741		//undocumented C and H flag behavior
2742		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
2743		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
2744		//decrement B
2745		if (opts->regs[Z80_B] >= 0) {
2746			sub_ir(code, 1, opts->regs[Z80_B], SZ_B);
2747		} else {
2748			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2749		}
2750		//undocumented Z and S flag behavior, set based on decrement of B
2751		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
2752		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
2753		//crazy undocumented P/V flag behavior
2754		and_ir(code, 7, opts->gen.scratch1, SZ_B);
2755		if (opts->regs[Z80_B] >= 0) {
2756			//deal with silly x86-64 restrictions on *H registers
2757			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2758			xor_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
2759			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2760		} else {
2761			xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B);
2762		}
2763		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
2764		break;
2765	case Z80_OTDR: {
2766		cycles(&opts->gen, num_cycles + 1);//T States: 4, 5
2767		//read from (HL)
2768		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
2769		call(code, opts->read_8);//T states 3
2770		//undocumented N flag behavior
2771		//flag set on bit 7 of value written
2772		bt_ir(code, 7, opts->gen.scratch1, SZ_B);
2773		setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_N)); 
2774		//write to IO (C)
2775		zreg_to_native(opts, Z80_C, opts->gen.scratch2);
2776		call(code, opts->write_io);//T states 4
2777		//increment HL
2778		if (opts->regs[Z80_HL] >= 0) {
2779			sub_ir(code, 1, opts->regs[Z80_HL], SZ_W);
2780			add_rr(code, opts->regs[Z80_L], opts->gen.scratch1, SZ_B);
2781		} else {
2782			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B);
2783			add_rdispr(code, opts->gen.context_reg, zr_off(Z80_L), opts->gen.scratch1, SZ_B);
2784		}
2785		//undocumented C and H flag behavior
2786		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
2787		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
2788		//decrement B
2789		if (opts->regs[Z80_B] >= 0) {
2790			sub_ir(code, 1, opts->regs[Z80_B], SZ_B);
2791		} else {
2792			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2793		}
2794		//undocumented Z and S flag behavior, set based on decrement of B
2795		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
2796		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
2797		//crazy undocumented P/V flag behavior
2798		and_ir(code, 7, opts->gen.scratch1, SZ_B);
2799		if (opts->regs[Z80_B] >= 0) {
2800			//deal with silly x86-64 restrictions on *H registers
2801			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2802			xor_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
2803			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2804		} else {
2805			xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B);
2806		}
2807		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
2808		if (opts->regs[Z80_B] >= 0) {
2809			cmp_ir(code, 0, opts->regs[Z80_B], SZ_B);
2810		} else {
2811			cmp_irdisp(code, 0, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2812		}
2813		code_ptr done = code->cur+1;
2814		jcc(code, CC_Z, code->cur+2);
2815		cycles(&opts->gen, 5);
2816		jmp(code, start);
2817		*done = code->cur - (done + 1);
2818		break;
2819	}
2820	default: {
2821		char disbuf[80];
2822		z80_disasm(inst, disbuf, address);
2823		FILE * f = fopen("zram.bin", "wb");
2824		fwrite(context->mem_pointers[0], 1, 8 * 1024, f);
2825		fclose(f);
2826		fatal_error("unimplemented Z80 instruction: %s at %X\nZ80 RAM has been saved to zram.bin for debugging", disbuf, address);
2827	}
2828	}
2829}
2830
2831uint8_t * z80_interp_handler(uint8_t opcode, z80_context * context)
2832{
2833	if (!context->interp_code[opcode]) {
2834		if (opcode == 0xCB || (opcode >= 0xDD && (opcode & 0xF) == 0xD)) {
2835			fatal_error("Encountered prefix byte %X at address %X. Z80 interpeter doesn't support those yet.", opcode, context->pc);
2836		}
2837		uint8_t codebuf[8];
2838		memset(codebuf, 0, sizeof(codebuf));
2839		codebuf[0] = opcode;
2840		z80inst inst;
2841		uint8_t * after = z80_decode(codebuf, &inst);
2842		if (after - codebuf > 1) {
2843			fatal_error("Encountered multi-byte Z80 instruction at %X. Z80 interpeter doesn't support those yet.", context->pc);
2844		}
2845
2846		z80_options * opts = context->options;
2847		code_info *code = &opts->gen.code;
2848		check_alloc_code(code, ZMAX_NATIVE_SIZE);
2849		context->interp_code[opcode] = code->cur;
2850		translate_z80inst(&inst, context, 0, 1);
2851		mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, pc), opts->gen.scratch1, SZ_W);
2852		add_ir(code, after - codebuf, opts->gen.scratch1, SZ_W);
2853		call(code, opts->native_addr);
2854		jmp_r(code, opts->gen.scratch1);
2855		z80_handle_deferred(context);
2856	}
2857	return context->interp_code[opcode];
2858}
2859
2860code_info z80_make_interp_stub(z80_context * context, uint16_t address)
2861{
2862	z80_options *opts = context->options;
2863	code_info * code = &opts->gen.code;
2864	check_alloc_code(code, 32);
2865	code_info stub = {code->cur, NULL};
2866	//TODO: make this play well with the breakpoint code
2867	mov_ir(code, address, opts->gen.scratch1, SZ_W);
2868	call(code, opts->read_8);
2869	//opcode fetch M-cycles have one extra T-state
2870	cycles(&opts->gen, 1);
2871	//TODO: increment R
2872	check_cycles_int(&opts->gen, address);
2873	call(code, opts->gen.save_context);
2874	mov_irdisp(code, address, opts->gen.context_reg, offsetof(z80_context, pc), SZ_W);
2875	push_r(code, opts->gen.context_reg);
2876	call_args(code, (code_ptr)z80_interp_handler, 2, opts->gen.scratch1, opts->gen.context_reg);
2877	mov_rr(code, RAX, opts->gen.scratch1, SZ_PTR);
2878	pop_r(code, opts->gen.context_reg);
2879	call(code, opts->gen.load_context);
2880	jmp_r(code, opts->gen.scratch1);
2881	stub.last = code->cur;
2882	return stub;
2883}
2884
2885
2886uint8_t * z80_get_native_address(z80_context * context, uint32_t address)
2887{
2888	z80_options *opts = context->options;
2889	native_map_slot * native_code_map = opts->gen.native_code_map;
2890	
2891	memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, 0, NULL);
2892	if (mem_chunk) {
2893		//calculate the lowest alias for this address
2894		address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask);
2895	}
2896	uint32_t chunk = address / NATIVE_CHUNK_SIZE;
2897	if (!native_code_map[chunk].base) {
2898		return NULL;
2899	}
2900	uint32_t offset = address % NATIVE_CHUNK_SIZE;
2901	if (native_code_map[chunk].offsets[offset] == INVALID_OFFSET || native_code_map[chunk].offsets[offset] == EXTENSION_WORD) {
2902		return NULL;
2903	}
2904	return native_code_map[chunk].base + native_code_map[chunk].offsets[offset];
2905}
2906
2907uint8_t z80_get_native_inst_size(z80_options * opts, uint32_t address)
2908{
2909	uint32_t meta_off;
2910	memmap_chunk const *chunk = find_map_chunk(address, &opts->gen, MMAP_CODE, &meta_off);
2911	if (chunk) {
2912		meta_off += (address - chunk->start) & chunk->mask;
2913	}
2914	uint32_t slot = meta_off/1024;
2915	return opts->gen.ram_inst_sizes[slot][meta_off%1024];
2916}
2917
2918void z80_map_native_address(z80_context * context, uint32_t address, uint8_t * native_address, uint8_t size, uint8_t native_size)
2919{
2920	z80_options * opts = context->options;
2921	uint32_t meta_off;
2922	memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, MMAP_CODE, &meta_off);
2923	if (mem_chunk) {
2924		if (mem_chunk->flags & MMAP_CODE) {
2925			uint32_t masked = (address & mem_chunk->mask);
2926			uint32_t final_off = masked + meta_off;
2927			uint32_t ram_flags_off = final_off >> (opts->gen.ram_flags_shift + 3);
2928			context->ram_code_flags[ram_flags_off] |= 1 << ((final_off >> opts->gen.ram_flags_shift) & 7);
2929
2930			uint32_t slot = final_off / 1024;
2931			if (!opts->gen.ram_inst_sizes[slot]) {
2932				opts->gen.ram_inst_sizes[slot] = malloc(sizeof(uint8_t) * 1024);
2933			}
2934			opts->gen.ram_inst_sizes[slot][final_off % 1024] = native_size;
2935
2936			//TODO: Deal with case in which end of instruction is in a different memory chunk
2937			masked = (address + size - 1) & mem_chunk->mask;
2938			final_off = masked + meta_off;
2939			ram_flags_off = final_off >> (opts->gen.ram_flags_shift + 3);
2940			context->ram_code_flags[ram_flags_off] |= 1 << ((final_off >> opts->gen.ram_flags_shift) & 7);
2941		}
2942		//calculate the lowest alias for this address
2943		address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask);
2944	} else {
2945		address &= opts->gen.address_mask;
2946	}
2947	
2948	native_map_slot *map = opts->gen.native_code_map + address / NATIVE_CHUNK_SIZE;
2949	if (!map->base) {
2950		map->base = native_address;
2951		map->offsets = malloc(sizeof(int32_t) * NATIVE_CHUNK_SIZE);
2952		memset(map->offsets, 0xFF, sizeof(int32_t) * NATIVE_CHUNK_SIZE);
2953	}
2954	map->offsets[address % NATIVE_CHUNK_SIZE] = native_address - map->base;
2955	for(--size, address++; size; --size, address++) {
2956		address &= opts->gen.address_mask;
2957		map = opts->gen.native_code_map + address / NATIVE_CHUNK_SIZE;
2958		if (!map->base) {
2959			map->base = native_address;
2960			map->offsets = malloc(sizeof(int32_t) * NATIVE_CHUNK_SIZE);
2961			memset(map->offsets, 0xFF, sizeof(int32_t) * NATIVE_CHUNK_SIZE);
2962		}
2963	
2964		if (map->offsets[address % NATIVE_CHUNK_SIZE] == INVALID_OFFSET) {
2965			//TODO: better handling of potentially overlapping instructions
2966			map->offsets[address % NATIVE_CHUNK_SIZE] = EXTENSION_WORD;
2967		}
2968	}
2969}
2970
2971#define INVALID_INSTRUCTION_START 0xFEEDFEED
2972
2973uint32_t z80_get_instruction_start(z80_context *context, uint32_t address)
2974{	
2975	z80_options *opts = context->options;
2976	native_map_slot * native_code_map = opts->gen.native_code_map;
2977	memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, 0, NULL);
2978	if (mem_chunk) {
2979		//calculate the lowest alias for this address
2980		address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask);
2981	}
2982	
2983	uint32_t chunk = address / NATIVE_CHUNK_SIZE;
2984	if (!native_code_map[chunk].base) {
2985		return INVALID_INSTRUCTION_START;
2986	}
2987	uint32_t offset = address % NATIVE_CHUNK_SIZE;
2988	if (native_code_map[chunk].offsets[offset] == INVALID_OFFSET) {
2989		return INVALID_INSTRUCTION_START;
2990	}
2991	while (native_code_map[chunk].offsets[offset] == EXTENSION_WORD)
2992	{
2993		--address;
2994		chunk = address / NATIVE_CHUNK_SIZE;
2995		offset = address % NATIVE_CHUNK_SIZE;
2996	}
2997	return address;
2998}
2999
3000//Technically unbounded due to redundant prefixes, but this is the max useful size
3001#define Z80_MAX_INST_SIZE 4
3002
3003z80_context * z80_handle_code_write(uint32_t address, z80_context * context)
3004{
3005	uint32_t inst_start = z80_get_instruction_start(context, address);
3006	while (inst_start != INVALID_INSTRUCTION_START && (address - inst_start) < Z80_MAX_INST_SIZE) {
3007		code_ptr dst = z80_get_native_address(context, inst_start);
3008		code_info code = {dst, dst+32, 0};
3009		z80_options * opts = context->options;
3010		dprintf("patching code at %p for Z80 instruction at %X due to write to %X\n", code.cur, inst_start, address);
3011		mov_ir(&code, inst_start, opts->gen.scratch1, SZ_D);
3012		call(&code, opts->retrans_stub);
3013		inst_start = z80_get_instruction_start(context, inst_start - 1);
3014	}
3015	return context;
3016}
3017
3018void z80_invalidate_code_range(z80_context *context, uint32_t start, uint32_t end)
3019{
3020	z80_options *opts = context->options;
3021	native_map_slot * native_code_map = opts->gen.native_code_map;
3022	memmap_chunk const *mem_chunk = find_map_chunk(start, &opts->gen, 0, NULL);
3023	if (mem_chunk) {
3024		//calculate the lowest alias for this address
3025		start = mem_chunk->start + ((start - mem_chunk->start) & mem_chunk->mask);
3026	}
3027	mem_chunk = find_map_chunk(end, &opts->gen, 0, NULL);
3028	if (mem_chunk) {
3029		//calculate the lowest alias for this address
3030		end = mem_chunk->start + ((end - mem_chunk->start) & mem_chunk->mask);
3031	}
3032	uint32_t start_chunk = start / NATIVE_CHUNK_SIZE, end_chunk = end / NATIVE_CHUNK_SIZE;
3033	for (uint32_t chunk = start_chunk; chunk <= end_chunk; chunk++)
3034	{
3035		if (native_code_map[chunk].base) {
3036			uint32_t start_offset = chunk == start_chunk ? start % NATIVE_CHUNK_SIZE : 0;
3037			uint32_t end_offset = chunk == end_chunk ? end % NATIVE_CHUNK_SIZE : NATIVE_CHUNK_SIZE;
3038			for (uint32_t offset = start_offset; offset < end_offset; offset++)
3039			{
3040				if (native_code_map[chunk].offsets[offset] != INVALID_OFFSET && native_code_map[chunk].offsets[offset] != EXTENSION_WORD) {
3041					code_info code;
3042					code.cur = native_code_map[chunk].base + native_code_map[chunk].offsets[offset];
3043					code.last = code.cur + 32;
3044					code.stack_off = 0;
3045					mov_ir(&code, chunk * NATIVE_CHUNK_SIZE + offset, opts->gen.scratch1, SZ_D);
3046					call(&code, opts->retrans_stub);
3047				}
3048			}
3049		}
3050	}
3051}
3052
3053uint8_t * z80_get_native_address_trans(z80_context * context, uint32_t address)
3054{
3055	uint8_t * addr = z80_get_native_address(context, address);
3056	if (!addr) {
3057		translate_z80_stream(context, address);
3058		addr = z80_get_native_address(context, address);
3059		if (!addr) {
3060			printf("Failed to translate %X to native code\n", address);
3061		}
3062	}
3063	return addr;
3064}
3065
3066void z80_handle_deferred(z80_context * context)
3067{
3068	z80_options * opts = context->options;
3069	process_deferred(&opts->gen.deferred, context, (native_addr_func)z80_get_native_address);
3070	if (opts->gen.deferred) {
3071		translate_z80_stream(context, opts->gen.deferred->address);
3072	}
3073}
3074
3075extern void * z80_retranslate_inst(uint32_t address, z80_context * context, uint8_t * orig_start) asm("z80_retranslate_inst");
3076void * z80_retranslate_inst(uint32_t address, z80_context * context, uint8_t * orig_start)
3077{
3078	char disbuf[80];
3079	z80_options * opts = context->options;
3080	uint8_t orig_size = z80_get_native_inst_size(opts, address);
3081	code_info *code = &opts->gen.code;
3082	uint8_t *after, *inst = get_native_pointer(address, (void **)context->mem_pointers, &opts->gen);
3083	z80inst instbuf;
3084	dprintf("Retranslating code at Z80 address %X, native address %p\n", address, orig_start);
3085	after = z80_decode(inst, &instbuf);
3086	#ifdef DO_DEBUG_PRINT
3087	z80_disasm(&instbuf, disbuf, address);
3088	if (instbuf.op == Z80_NOP) {
3089		printf("%X\t%s(%d)\n", address, disbuf, instbuf.immed);
3090	} else {
3091		printf("%X\t%s\n", address, disbuf);
3092	}
3093	#endif
3094	if (orig_size != ZMAX_NATIVE_SIZE) {
3095		check_alloc_code(code, ZMAX_NATIVE_SIZE);
3096		code_ptr start = code->cur;
3097		deferred_addr * orig_deferred = opts->gen.deferred;
3098		translate_z80inst(&instbuf, context, address, 0);
3099		/*
3100		if ((native_end - dst) <= orig_size) {
3101			uint8_t * native_next = z80_get_native_address(context, address + after-inst);
3102			if (native_next && ((native_next == orig_start + orig_size) || (orig_size - (native_end - dst)) > 5)) {
3103				remove_deferred_until(&opts->gen.deferred, orig_deferred);
3104				native_end = translate_z80inst(&instbuf, orig_start, context, address, 0);
3105				if (native_next == orig_start + orig_size && (native_next-native_end) < 2) {
3106					while (native_end < orig_start + orig_size) {
3107						*(native_end++) = 0x90; //NOP
3108					}
3109				} else {
3110					jmp(native_end, native_next);
3111				}
3112				z80_handle_deferred(context);
3113				return orig_start;
3114			}
3115		}*/
3116		z80_map_native_address(context, address, start, after-inst, ZMAX_NATIVE_SIZE);
3117		code_info tmp_code = {orig_start, orig_start + 16};
3118		jmp(&tmp_code, start);
3119		tmp_code = *code;
3120		code->cur = start + ZMAX_NATIVE_SIZE;
3121		if (!z80_is_terminal(&instbuf)) {
3122			jmp(&tmp_code, z80_get_native_address_trans(context, address + after-inst));
3123		}
3124		z80_handle_deferred(context);
3125		return start;
3126	} else {
3127		code_info tmp_code = *code;
3128		code->cur = orig_start;
3129		code->last = orig_start + ZMAX_NATIVE_SIZE;
3130		translate_z80inst(&instbuf, context, address, 0);
3131		code_info tmp2 = *code;
3132		*code = tmp_code;
3133		if (!z80_is_terminal(&instbuf)) {
3134
3135			jmp(&tmp2, z80_get_native_address_trans(context, address + after-inst));
3136		}
3137		z80_handle_deferred(context);
3138		return orig_start;
3139	}
3140}
3141
3142void translate_z80_stream(z80_context * context, uint32_t address)
3143{
3144	char disbuf[80];
3145	if (z80_get_native_address(context, address)) {
3146		return;
3147	}
3148	z80_options * opts = context->options;
3149	uint32_t start_address = address;
3150
3151	do
3152	{
3153		z80inst inst;
3154		dprintf("translating Z80 code at address %X\n", address);
3155		do {
3156			uint8_t * existing = z80_get_native_address(context, address);
3157			if (existing) {
3158				jmp(&opts->gen.code, existing);
3159				break;
3160			}
3161			uint8_t * encoded, *next;
3162			encoded = get_native_pointer(address, (void **)context->mem_pointers, &opts->gen);
3163			if (!encoded) {
3164				code_info stub = z80_make_interp_stub(context, address);
3165				z80_map_native_address(context, address, stub.cur, 1, stub.last - stub.cur);
3166				break;
3167			}
3168			//make sure prologue is in a contiguous chunk of code
3169			check_code_prologue(&opts->gen.code);
3170			next = z80_decode(encoded, &inst);
3171			#ifdef DO_DEBUG_PRINT
3172			z80_disasm(&inst, disbuf, address);
3173			if (inst.op == Z80_NOP) {
3174				printf("%X\t%s(%d)\n", address, disbuf, inst.immed);
3175			} else {
3176				printf("%X\t%s\n", address, disbuf);
3177			}
3178			#endif
3179			code_ptr start = opts->gen.code.cur;
3180			translate_z80inst(&inst, context, address, 0);
3181			z80_map_native_address(context, address, start, next-encoded, opts->gen.code.cur - start);
3182			address += next-encoded;
3183				address &= 0xFFFF;
3184		} while (!z80_is_terminal(&inst));
3185		process_deferred(&opts->gen.deferred, context, (native_addr_func)z80_get_native_address);
3186		if (opts->gen.deferred) {
3187			address = opts->gen.deferred->address;
3188			dprintf("defferred address: %X\n", address);
3189		}
3190	} while (opts->gen.deferred);
3191}
3192
3193void init_z80_opts(z80_options * options, memmap_chunk const * chunks, uint32_t num_chunks, memmap_chunk const * io_chunks, uint32_t num_io_chunks, uint32_t clock_divider, uint32_t io_address_mask)
3194{
3195	memset(options, 0, sizeof(*options));
3196
3197	options->gen.memmap = chunks;
3198	options->gen.memmap_chunks = num_chunks;
3199	options->gen.address_size = SZ_W;
3200	options->gen.address_mask = 0xFFFF;
3201	options->gen.max_address = 0x10000;
3202	options->gen.bus_cycles = 3;
3203	options->gen.clock_divider = clock_divider;
3204	options->gen.mem_ptr_off = offsetof(z80_context, mem_pointers);
3205	options->gen.ram_flags_off = offsetof(z80_context, ram_code_flags);
3206	options->gen.ram_flags_shift = 7;
3207
3208	options->flags = 0;
3209#ifdef X86_64
3210	options->regs[Z80_B] = BH;
3211	options->regs[Z80_C] = RBX;
3212	options->regs[Z80_D] = CH;
3213	options->regs[Z80_E] = RCX;
3214	options->regs[Z80_H] = AH;
3215	options->regs[Z80_L] = RAX;
3216	options->regs[Z80_IXH] = DH;
3217	options->regs[Z80_IXL] = RDX;
3218	options->regs[Z80_IYH] = -1;
3219	options->regs[Z80_IYL] = R8;
3220	options->regs[Z80_I] = -1;
3221	options->regs[Z80_R] = RDI;
3222	options->regs[Z80_A] = R10;
3223	options->regs[Z80_BC] = RBX;
3224	options->regs[Z80_DE] = RCX;
3225	options->regs[Z80_HL] = RAX;
3226	options->regs[Z80_SP] = R9;
3227	options->regs[Z80_AF] = -1;
3228	options->regs[Z80_IX] = RDX;
3229	options->regs[Z80_IY] = R8;
3230
3231	options->gen.scratch1 = R13;
3232	options->gen.scratch2 = R14;
3233#else
3234	memset(options->regs, -1, sizeof(options->regs));
3235	options->regs[Z80_A] = RAX;
3236	options->regs[Z80_R] = AH;
3237	options->regs[Z80_H] = BH;
3238	options->regs[Z80_L] = RBX;
3239	options->regs[Z80_HL] = RBX;
3240	
3241	options->regs[Z80_SP] = RDI;
3242
3243	options->gen.scratch1 = RCX;
3244	options->gen.scratch2 = RDX;
3245#endif
3246
3247	options->gen.context_reg = RSI;
3248	options->gen.cycles = RBP;
3249	options->gen.limit = -1;
3250
3251	options->gen.native_code_map = malloc(sizeof(native_map_slot) * NATIVE_MAP_CHUNKS);
3252	memset(options->gen.native_code_map, 0, sizeof(native_map_slot) * NATIVE_MAP_CHUNKS);
3253	options->gen.deferred = NULL;
3254	uint32_t inst_size_size = sizeof(uint8_t *) * ram_size(&options->gen) / 1024;
3255	options->gen.ram_inst_sizes = malloc(inst_size_size);
3256	memset(options->gen.ram_inst_sizes, 0, inst_size_size);
3257
3258	code_info *code = &options->gen.code;
3259	init_code_info(code);
3260
3261	options->save_context_scratch = code->cur;
3262	mov_rrdisp(code, options->gen.scratch1, options->gen.context_reg, offsetof(z80_context, scratch1), SZ_W);
3263	mov_rrdisp(code, options->gen.scratch2, options->gen.context_reg, offsetof(z80_context, scratch2), SZ_W);
3264
3265	options->gen.save_context = code->cur;
3266	for (int i = 0; i <= Z80_A; i++)
3267	{
3268		int reg;
3269		uint8_t size;
3270		if (i < Z80_I) {
3271			reg = i /2 + Z80_BC + (i > Z80_H ? 2 : 0);
3272			size = SZ_W;
3273		} else {
3274			reg = i;
3275			size = SZ_B;
3276		}
3277		if (reg == Z80_R) {
3278			and_ir(code, 0x7F, options->regs[Z80_R], SZ_B);
3279			or_rrdisp(code, options->regs[Z80_R], options->gen.context_reg, zr_off(Z80_R), SZ_B);
3280		} else if (options->regs[reg] >= 0) {
3281			mov_rrdisp(code, options->regs[reg], options->gen.context_reg, zr_off(reg), size);
3282		}
3283		if (size == SZ_W) {
3284			i++;
3285		}
3286	}
3287	if (options->regs[Z80_SP] >= 0) {
3288		mov_rrdisp(code, options->regs[Z80_SP], options->gen.context_reg, offsetof(z80_context, sp), SZ_W);
3289	}
3290	neg_r(code, options->gen.cycles, SZ_D);
3291	add_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.cycles, SZ_D);
3292	mov_rrdisp(code, options->gen.cycles, options->gen.context_reg, offsetof(z80_context, current_cycle), SZ_D);
3293	retn(code);
3294
3295	options->load_context_scratch = code->cur;
3296	mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, scratch1), options->gen.scratch1, SZ_W);
3297	mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, scratch2), options->gen.scratch2, SZ_W);
3298	options->gen.load_context = code->cur;
3299	for (int i = 0; i <= Z80_A; i++)
3300	{
3301		int reg;
3302		uint8_t size;
3303		if (i < Z80_I) {
3304			reg = i /2 + Z80_BC + (i > Z80_H ? 2 : 0);
3305			size = SZ_W;
3306		} else {
3307			reg = i;
3308			size = SZ_B;
3309		}
3310		if (options->regs[reg] >= 0) {
3311			mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, regs) + i, options->regs[reg], size);
3312			if (reg == Z80_R) {
3313				and_irdisp(code, 0x80, options->gen.context_reg, zr_off(reg), SZ_B);
3314			}
3315		}
3316		if (size == SZ_W) {
3317			i++;
3318		}
3319	}
3320	if (options->regs[Z80_SP] >= 0) {
3321		mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, sp), options->regs[Z80_SP], SZ_W);
3322	}
3323	mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.cycles, SZ_D);
3324	sub_rdispr(code, options->gen.context_reg, offsetof(z80_context, current_cycle), options->gen.cycles, SZ_D);
3325	retn(code);
3326
3327	options->native_addr = code->cur;
3328	call(code, options->gen.save_context);
3329	push_r(code, options->gen.context_reg);
3330	movzx_rr(code, options->gen.scratch1, options->gen.scratch1, SZ_W, SZ_D);
3331	call_args(code, (code_ptr)z80_get_native_address_trans, 2, options->gen.context_reg, options->gen.scratch1);
3332	mov_rr(code, RAX, options->gen.scratch1, SZ_PTR);
3333	pop_r(code, options->gen.context_reg);
3334	call(code, options->gen.load_context);
3335	retn(code);
3336
3337	uint32_t tmp_stack_off;
3338
3339	options->gen.handle_cycle_limit = code->cur;
3340	//calculate call/stack adjust size
3341	sub_ir(code, 16-sizeof(void *), RSP, SZ_PTR);
3342	call_noalign(code, options->gen.handle_cycle_limit);
3343	uint32_t call_adjust_size = code->cur - options->gen.handle_cycle_limit;
3344	code->cur = options->gen.handle_cycle_limit;
3345	
3346	neg_r(code, options->gen.cycles, SZ_D);
3347	add_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.cycles, SZ_D);
3348	cmp_rdispr(code, options->gen.context_reg, offsetof(z80_context, sync_cycle), options->gen.cycles, SZ_D);
3349	code_ptr no_sync = code->cur+1;
3350	jcc(code, CC_B, no_sync);
3351	neg_r(code, options->gen.cycles, SZ_D);
3352	add_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.cycles, SZ_D);
3353	mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, pc), SZ_W);
3354	call(code, options->save_context_scratch);
3355	tmp_stack_off = code->stack_off;
3356	pop_r(code, RAX); //return address in read/write func
3357	add_ir(code, 16-sizeof(void *), RSP, SZ_PTR);
3358	pop_r(code, RBX); //return address in translated code
3359	add_ir(code, 16-sizeof(void *), RSP, SZ_PTR);
3360	sub_ir(code, call_adjust_size, RAX, SZ_PTR); //adjust return address to point to the call + stack adjust that got us here
3361	mov_rrdisp(code, RBX, options->gen.context_reg, offsetof(z80_context, extra_pc), SZ_PTR);
3362	mov_rrind(code, RAX, options->gen.context_reg, SZ_PTR);
3363	restore_callee_save_regs(code);
3364	//return to caller of z80_run
3365	retn(code);
3366	
3367	*no_sync = code->cur - (no_sync + 1);
3368	neg_r(code, options->gen.cycles, SZ_D);
3369	add_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.cycles, SZ_D);
3370	retn(code);
3371	code->stack_off = tmp_stack_off;
3372
3373	options->gen.handle_code_write = (code_ptr)z80_handle_code_write;
3374
3375	options->read_8 = gen_mem_fun(&options->gen, chunks, num_chunks, READ_8, &options->read_8_noinc);
3376	options->write_8 = gen_mem_fun(&options->gen, chunks, num_chunks, WRITE_8, &options->write_8_noinc);
3377
3378	code_ptr skip_int = code->cur;
3379	//calculate adjust size
3380	add_ir(code, 16-sizeof(void *), RSP, SZ_PTR);
3381	uint32_t adjust_size = code->cur - skip_int;
3382	code->cur = skip_int;
3383	
3384	cmp_rdispr(code, options->gen.context_reg, offsetof(z80_context, sync_cycle), options->gen.cycles, SZ_D);
3385	code_ptr skip_sync = code->cur + 1;
3386	jcc(code, CC_B, skip_sync);
3387	neg_r(code, options->gen.cycles, SZ_D);
3388	add_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.cycles, SZ_D);
3389	//save PC
3390	mov_rrdisp(code, options->gen.scratch1, options->gen.context_reg, offsetof(z80_context, pc), SZ_D);
3391	options->do_sync = code->cur;
3392	call(code, options->gen.save_context);
3393	tmp_stack_off = code->stack_off;
3394	//pop return address off the stack and save for resume later
3395	//pop_rind(code, options->gen.context_reg);
3396	pop_r(code, RAX);
3397	add_ir(code, adjust_size, RAX, SZ_PTR);
3398	add_ir(code, 16-sizeof(void *), RSP, SZ_PTR);
3399	mov_rrind(code, RAX, options->gen.context_reg, SZ_PTR);
3400	
3401	//restore callee saved registers
3402	restore_callee_save_regs(code);
3403	//return to caller of z80_run
3404	retn(code);
3405	*skip_sync = code->cur - (skip_sync+1);
3406	neg_r(code, options->gen.cycles, SZ_D);
3407	add_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.cycles, SZ_D);
3408	retn(code);
3409	code->stack_off = tmp_stack_off;
3410
3411	options->gen.handle_cycle_limit_int = code->cur;
3412	neg_r(code, options->gen.cycles, SZ_D);
3413	add_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.cycles, SZ_D);
3414	cmp_rdispr(code, options->gen.context_reg, offsetof(z80_context, int_cycle), options->gen.cycles, SZ_D);
3415	jcc(code, CC_B, skip_int);
3416	//set limit to the cycle limit
3417	mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, sync_cycle), options->gen.scratch2, SZ_D);
3418	mov_rrdisp(code, options->gen.scratch2, options->gen.context_reg, offsetof(z80_context, target_cycle), SZ_D);
3419	neg_r(code, options->gen.cycles, SZ_D);
3420	add_rr(code, options->gen.scratch2, options->gen.cycles, SZ_D);
3421	//disable interrupts
3422	cmp_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, int_is_nmi), SZ_B);
3423	code_ptr is_nmi = code->cur + 1;
3424	jcc(code, CC_NZ, is_nmi);
3425	mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff1), SZ_B);
3426	mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff2), SZ_B);
3427	cycles(&options->gen, 6); //interupt ack cycle
3428	code_ptr after_int_disable = code->cur + 1;
3429	jmp(code, after_int_disable);
3430	*is_nmi = code->cur - (is_nmi + 1);
3431	mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, iff1), options->gen.scratch2, SZ_B);
3432	mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff1), SZ_B);
3433	mov_rrdisp(code, options->gen.scratch2, options->gen.context_reg, offsetof(z80_context, iff2), SZ_B);
3434	cycles(&options->gen, 5); //NMI processing cycles
3435	*after_int_disable = code->cur - (after_int_disable + 1);
3436	//save return address (in scratch1) to Z80 stack
3437	sub_ir(code, 2, options->regs[Z80_SP], SZ_W);
3438	mov_rr(code, options->regs[Z80_SP], options->gen.scratch2, SZ_W);
3439	//we need to do check_cycles and cycles outside of the write_8 call
3440	//so that the stack has the correct depth if we need to return to C
3441	//for a synchronization
3442	check_cycles(&options->gen);
3443	cycles(&options->gen, 3);
3444	//save word to write before call to write_8_noinc
3445	push_r(code, options->gen.scratch1);
3446	call(code, options->write_8_noinc);
3447	//restore word to write
3448	pop_r(code, options->gen.scratch1);
3449	//write high byte to SP+1
3450	mov_rr(code, options->regs[Z80_SP], options->gen.scratch2, SZ_W);
3451	add_ir(code, 1, options->gen.scratch2, SZ_W);
3452	shr_ir(code, 8, options->gen.scratch1, SZ_W);
3453	check_cycles(&options->gen);
3454	cycles(&options->gen, 3);
3455	call(code, options->write_8_noinc);
3456	//dispose of return address as we'll be jumping somewhere else
3457	add_ir(code, 16, RSP, SZ_PTR);
3458	cmp_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, int_is_nmi), SZ_B);
3459	is_nmi = code->cur + 1;
3460	jcc(code, CC_NZ, is_nmi);
3461	//TODO: Support interrupt mode 0, not needed for Genesis sit it seems to read $FF during intack
3462	//which is conveniently rst $38, i.e. the same thing that im 1 does
3463	//check interrupt mode
3464	cmp_irdisp(code, 2, options->gen.context_reg, offsetof(z80_context, im), SZ_B);
3465	code_ptr im2 = code->cur + 1;
3466	jcc(code, CC_Z, im2);
3467	mov_ir(code, 0x38, options->gen.scratch1, SZ_W);
3468	cycles(&options->gen, 1); //total time for mode 0/1 is 13 t-states
3469	code_ptr after_int_dest = code->cur + 1;
3470	jmp(code, after_int_dest);
3471	*im2 = code->cur - (im2 + 1);
3472	//read vector address from I << 8 | vector
3473	mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, regs) + Z80_I, options->gen.scratch1, SZ_B);
3474	shl_ir(code, 8, options->gen.scratch1, SZ_W);
3475	movzx_rdispr(code, options->gen.context_reg, offsetof(z80_context, im2_vector), options->gen.scratch2, SZ_B, SZ_W);
3476	or_rr(code, options->gen.scratch2, options->gen.scratch1, SZ_W);
3477	push_r(code, options->gen.scratch1);
3478	cycles(&options->gen, 3);
3479	call(code, options->read_8_noinc);
3480	pop_r(code, options->gen.scratch2);
3481	push_r(code, options->gen.scratch1);
3482	mov_rr(code, options->gen.scratch2, options->gen.scratch1, SZ_W);
3483	add_ir(code, 1, options->gen.scratch1, SZ_W);
3484	cycles(&options->gen, 3);
3485	call(code, options->read_8_noinc);
3486	pop_r(code, options->gen.scratch2);
3487	shl_ir(code, 8, options->gen.scratch1, SZ_W);
3488	movzx_rr(code, options->gen.scratch2, options->gen.scratch2, SZ_B, SZ_W);
3489	or_rr(code, options->gen.scratch2, options->gen.scratch1, SZ_W);
3490	code_ptr after_int_dest2 = code->cur + 1;
3491	jmp(code, after_int_dest2);
3492	*is_nmi = code->cur - (is_nmi + 1);
3493	mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, int_is_nmi), SZ_B);
3494	mov_irdisp(code, CYCLE_NEVER, options->gen.context_reg, offsetof(z80_context, nmi_start), SZ_D);
3495	mov_ir(code, 0x66, options->gen.scratch1, SZ_W);
3496	*after_int_dest = code->cur - (after_int_dest + 1);
3497	*after_int_dest2 = code->cur - (after_int_dest2 + 1);
3498	call(code, options->native_addr);
3499	mov_rrind(code, options->gen.scratch1, options->gen.context_reg, SZ_PTR);
3500	tmp_stack_off = code->stack_off;
3501	restore_callee_save_regs(code);
3502	//return to caller of z80_run to sync
3503	retn(code);
3504	code->stack_off = tmp_stack_off;
3505
3506	//HACK
3507	options->gen.address_size = SZ_D;
3508	options->gen.address_mask = io_address_mask;
3509	options->gen.bus_cycles = 4;
3510	options->read_io = gen_mem_fun(&options->gen, io_chunks, num_io_chunks, READ_8, NULL);
3511	options->write_io = gen_mem_fun(&options->gen, io_chunks, num_io_chunks, WRITE_8, NULL);
3512	options->gen.address_size = SZ_W;
3513	options->gen.address_mask = 0xFFFF;
3514	options->gen.bus_cycles = 3;
3515
3516	options->read_16 = code->cur;
3517	cycles(&options->gen, 3);
3518	check_cycles(&options->gen);
3519	//TODO: figure out how to handle the extra wait state for word reads to bank area
3520	//may also need special handling to avoid too much stack depth when access is blocked
3521	push_r(code, options->gen.scratch1);
3522	call(code, options->read_8_noinc);
3523	mov_rr(code, options->gen.scratch1, options->gen.scratch2, SZ_B);
3524#ifndef X86_64
3525	//scratch 2 is a caller save register in 32-bit builds and may be clobbered by something called from the read8 fun
3526	mov_rrdisp(code, options->gen.scratch1, options->gen.context_reg, offsetof(z80_context, scratch2), SZ_B);
3527#endif
3528	pop_r(code, options->gen.scratch1);
3529	add_ir(code, 1, options->gen.scratch1, SZ_W);
3530	cycles(&options->gen, 3);
3531	check_cycles(&options->gen);
3532	call(code, options->read_8_noinc);
3533	shl_ir(code, 8, options->gen.scratch1, SZ_W);
3534#ifdef X86_64
3535	mov_rr(code, options->gen.scratch2, options->gen.scratch1, SZ_B);
3536#else
3537	mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, scratch2), options->gen.scratch1, SZ_B);
3538#endif
3539	retn(code);
3540
3541	options->write_16_highfirst = code->cur;
3542	cycles(&options->gen, 3);
3543	check_cycles(&options->gen);
3544	push_r(code, options->gen.scratch2);
3545	push_r(code, options->gen.scratch1);
3546	add_ir(code, 1, options->gen.scratch2, SZ_W);
3547	shr_ir(code, 8, options->gen.scratch1, SZ_W);
3548	call(code, options->write_8_noinc);
3549	pop_r(code, options->gen.scratch1);
3550	pop_r(code, options->gen.scratch2);
3551	cycles(&options->gen, 3);
3552	check_cycles(&options->gen);
3553	//TODO: Check if we can get away with TCO here
3554	call(code, options->write_8_noinc);
3555	retn(code);
3556
3557	options->write_16_lowfirst = code->cur;
3558	cycles(&options->gen, 3);
3559	check_cycles(&options->gen);
3560	push_r(code, options->gen.scratch2);
3561	push_r(code, options->gen.scratch1);
3562	call(code, options->write_8_noinc);
3563	pop_r(code, options->gen.scratch1);
3564	pop_r(code, options->gen.scratch2);
3565	add_ir(code, 1, options->gen.scratch2, SZ_W);
3566	shr_ir(code, 8, options->gen.scratch1, SZ_W);
3567	cycles(&options->gen, 3);
3568	check_cycles(&options->gen);
3569	//TODO: Check if we can get away with TCO here
3570	call(code, options->write_8_noinc);
3571	retn(code);
3572
3573	options->retrans_stub = code->cur;
3574	tmp_stack_off = code->stack_off;
3575	//calculate size of patch
3576	mov_ir(code, 0x7FFF, options->gen.scratch1, SZ_D);
3577	code->stack_off += sizeof(void *);
3578	if (code->stack_off & 0xF) {
3579		sub_ir(code, 16 - (code->stack_off & 0xF), RSP, SZ_PTR);
3580	}
3581	call_noalign(code, options->retrans_stub);
3582	uint32_t patch_size = code->cur - options->retrans_stub;
3583	code->cur = options->retrans_stub;
3584	code->stack_off = tmp_stack_off;
3585	
3586	//pop return address
3587	pop_r(code, options->gen.scratch2);
3588	add_ir(code, 16-sizeof(void*), RSP, SZ_PTR);
3589	code->stack_off = tmp_stack_off;
3590	call(code, options->gen.save_context);
3591	//adjust pointer before move and call instructions that got us here
3592	sub_ir(code, patch_size, options->gen.scratch2, SZ_PTR);
3593	push_r(code, options->gen.context_reg);
3594	call_args(code, (code_ptr)z80_retranslate_inst, 3, options->gen.scratch1, options->gen.context_reg, options->gen.scratch2);
3595	pop_r(code, options->gen.context_reg);
3596	mov_rr(code, RAX, options->gen.scratch1, SZ_PTR);
3597	call(code, options->gen.load_context);
3598	jmp_r(code, options->gen.scratch1);
3599
3600	options->run = (z80_ctx_fun)code->cur;
3601	tmp_stack_off = code->stack_off;
3602	save_callee_save_regs(code);
3603#ifdef X86_64
3604	mov_rr(code, RDI, options->gen.context_reg, SZ_PTR);
3605#else
3606	mov_rdispr(code, RSP, 5 * sizeof(int32_t), options->gen.context_reg, SZ_PTR);
3607#endif
3608	call(code, options->load_context_scratch);
3609	cmp_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, extra_pc), SZ_PTR);
3610	code_ptr no_extra = code->cur+1;
3611	jcc(code, CC_Z, no_extra);
3612	sub_ir(code, 16-sizeof(void *), RSP, SZ_PTR);	
3613	push_rdisp(code, options->gen.context_reg, offsetof(z80_context, extra_pc));
3614	mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, extra_pc), SZ_PTR);
3615	*no_extra = code->cur - (no_extra + 1);
3616	jmp_rind(code, options->gen.context_reg);
3617	code->stack_off = tmp_stack_off;
3618}
3619
3620z80_context *init_z80_context(z80_options * options)
3621{
3622	size_t ctx_size = sizeof(z80_context) + ram_size(&options->gen) / (1 << options->gen.ram_flags_shift) / 8;
3623	z80_context *context = calloc(1, ctx_size);
3624	context->options = options;
3625	context->int_cycle = CYCLE_NEVER;
3626	context->int_pulse_start = CYCLE_NEVER;
3627	context->int_pulse_end = CYCLE_NEVER;
3628	context->nmi_start = CYCLE_NEVER;
3629	
3630	return context;
3631}
3632
3633static void check_nmi(z80_context *context)
3634{
3635	if (context->nmi_start < context->int_cycle) {
3636		context->int_cycle = context->nmi_start;
3637		context->int_is_nmi = 1;
3638	}
3639}
3640
3641void z80_run(z80_context * context, uint32_t target_cycle)
3642{
3643	if (context->reset || context->busack) {
3644		context->current_cycle = target_cycle;
3645	} else {
3646		if (context->current_cycle < target_cycle) {
3647			//busreq is sampled at the end of an m-cycle
3648			//we can approximate that by running for a single m-cycle after a bus request
3649			context->sync_cycle = context->busreq ? context->current_cycle + 3*context->options->gen.clock_divider : target_cycle;
3650			if (!context->native_pc) {
3651				context->native_pc = z80_get_native_address_trans(context, context->pc);
3652			}
3653			while (context->current_cycle < context->sync_cycle)
3654			{
3655				if (context->next_int_pulse && (context->int_pulse_end < context->current_cycle || context->int_pulse_end == CYCLE_NEVER)) {
3656					context->next_int_pulse(context);
3657				}
3658				if (context->iff1) {
3659					context->int_cycle = context->int_pulse_start < context->int_enable_cycle ? context->int_enable_cycle : context->int_pulse_start;
3660					context->int_is_nmi = 0;
3661				} else {
3662					context->int_cycle = CYCLE_NEVER;
3663				}
3664				check_nmi(context);
3665				
3666				context->target_cycle = context->sync_cycle < context->int_cycle ? context->sync_cycle : context->int_cycle;
3667				dprintf("Running Z80 from cycle %d to cycle %d. Int cycle: %d (%d - %d)\n", context->current_cycle, context->sync_cycle, context->int_cycle, context->int_pulse_start, context->int_pulse_end);
3668				context->options->run(context);
3669				dprintf("Z80 ran to cycle %d\n", context->current_cycle);
3670			}
3671			if (context->busreq) {
3672				context->busack = 1;
3673				context->current_cycle = target_cycle;
3674			}
3675		}
3676	}
3677}
3678
3679void z80_options_free(z80_options *opts)
3680{
3681	for (uint32_t address = 0; address < opts->gen.address_mask; address += NATIVE_CHUNK_SIZE)
3682	{
3683		uint32_t chunk = address / NATIVE_CHUNK_SIZE;
3684		if (opts->gen.native_code_map[chunk].base) {
3685			free(opts->gen.native_code_map[chunk].offsets);
3686		}
3687	}
3688	free(opts->gen.native_code_map);
3689	uint32_t ram_inst_slots = ram_size(&opts->gen) / 1024;
3690	for (uint32_t i = 0; i < ram_inst_slots; i++)
3691	{
3692		free(opts->gen.ram_inst_sizes[i]);
3693	}
3694	free(opts->gen.ram_inst_sizes);
3695	free(opts);
3696}
3697
3698void z80_assert_reset(z80_context * context, uint32_t cycle)
3699{
3700	z80_run(context, cycle);
3701	context->reset = 1;
3702}
3703
3704void z80_clear_reset(z80_context * context, uint32_t cycle)
3705{
3706	z80_run(context, cycle);
3707	if (context->reset) {
3708		//TODO: Handle case where reset is not asserted long enough
3709		context->im = 0;
3710		context->iff1 = context->iff2 = 0;
3711		context->native_pc = NULL;
3712		context->extra_pc = NULL;
3713		context->pc = 0;
3714		context->reset = 0;
3715		if (context->busreq) {
3716			//TODO: Figure out appropriate delay
3717			context->busack = 1;
3718		}
3719	}
3720}
3721
3722void z80_assert_busreq(z80_context * context, uint32_t cycle)
3723{
3724	z80_run(context, cycle);
3725	context->busreq = 1;
3726	//this is an imperfect aproximation since most M-cycles take less tstates than the max
3727	//and a short 3-tstate m-cycle can take an unbounded number due to wait states
3728	if (context->current_cycle - cycle > MAX_MCYCLE_LENGTH * context->options->gen.clock_divider) {
3729		context->busack = 1;
3730	}
3731}
3732
3733void z80_clear_busreq(z80_context * context, uint32_t cycle)
3734{
3735	z80_run(context, cycle);
3736	context->busreq = 0;
3737	context->busack = 0;
3738	//there appears to be at least a 1 Z80 cycle delay between busreq
3739	//being released and resumption of execution
3740	context->current_cycle += context->options->gen.clock_divider;
3741}
3742
3743uint8_t z80_get_busack(z80_context * context, uint32_t cycle)
3744{
3745	z80_run(context, cycle);
3746	return context->busack;
3747}
3748
3749void z80_assert_nmi(z80_context *context, uint32_t cycle)
3750{
3751	context->nmi_start = cycle;
3752	check_nmi(context);
3753}
3754
3755void z80_adjust_cycles(z80_context * context, uint32_t deduction)
3756{
3757	if (context->current_cycle < deduction) {
3758		fprintf(stderr, "WARNING: Deduction of %u cycles when Z80 cycle counter is only %u\n", deduction, context->current_cycle);
3759		context->current_cycle = 0;
3760	} else {
3761		context->current_cycle -= deduction;
3762	}
3763	if (context->int_enable_cycle != CYCLE_NEVER) {
3764		if (context->int_enable_cycle < deduction) {
3765			context->int_enable_cycle = 0;
3766		} else {
3767			context->int_enable_cycle -= deduction;
3768		}
3769	}
3770	if (context->int_pulse_start != CYCLE_NEVER) {
3771		if (context->int_pulse_end < deduction) {
3772			context->int_pulse_start = context->int_pulse_end = CYCLE_NEVER;
3773		} else {
3774			if (context->int_pulse_end != CYCLE_NEVER) {
3775				context->int_pulse_end -= deduction;
3776			}
3777			if (context->int_pulse_start < deduction) {
3778				context->int_pulse_start = 0;
3779			} else {
3780				context->int_pulse_start -= deduction;
3781			}
3782		}
3783	}
3784}
3785
3786uint32_t zbreakpoint_patch(z80_context * context, uint16_t address, code_ptr dst)
3787{
3788	code_info code = {
3789		dst, 
3790		dst+32,
3791#ifdef X86_64
3792		8
3793#else
3794		0
3795#endif
3796	};
3797	mov_ir(&code, address, context->options->gen.scratch1, SZ_W);
3798	call(&code, context->bp_stub);
3799	return code.cur-dst;
3800}
3801
3802void zcreate_stub(z80_context * context)
3803{
3804	//FIXME: Stack offset stuff is probably broken on 32-bit
3805	z80_options * opts = context->options;
3806	code_info *code = &opts->gen.code;
3807	uint32_t start_stack_off = code->stack_off;
3808	check_code_prologue(code);
3809	context->bp_stub = code->cur;
3810
3811	//Calculate length of prologue
3812	check_cycles_int(&opts->gen, 0);
3813	int check_int_size = code->cur-context->bp_stub;
3814	code->cur = context->bp_stub;
3815
3816	//Calculate length of patch
3817	int patch_size = zbreakpoint_patch(context, 0, code->cur);
3818
3819#ifdef X86_64
3820	code->stack_off = 8;
3821#endif
3822	//Save context and call breakpoint handler
3823	call(code, opts->gen.save_context);
3824	push_r(code, opts->gen.scratch1);
3825	call_args_abi(code, context->bp_handler, 2, opts->gen.context_reg, opts->gen.scratch1);
3826	mov_rr(code, RAX, opts->gen.context_reg, SZ_PTR);
3827		//Restore context
3828	call(code, opts->gen.load_context);
3829	pop_r(code, opts->gen.scratch1);
3830		//do prologue stuff
3831	cmp_ir(code, 1, opts->gen.cycles, SZ_D);
3832	uint8_t * jmp_off = code->cur+1;
3833	jcc(code, CC_NS, code->cur + 7);
3834	pop_r(code, opts->gen.scratch1);
3835	add_ir(code, check_int_size - patch_size, opts->gen.scratch1, SZ_PTR);
3836#ifdef X86_64
3837	sub_ir(code, 8, RSP, SZ_PTR);
3838#endif
3839	push_r(code, opts->gen.scratch1);
3840	jmp(code, opts->gen.handle_cycle_limit_int);
3841	*jmp_off = code->cur - (jmp_off+1);
3842		//jump back to body of translated instruction
3843	pop_r(code, opts->gen.scratch1);
3844	add_ir(code, check_int_size - patch_size, opts->gen.scratch1, SZ_PTR);
3845	jmp_r(code, opts->gen.scratch1);
3846	code->stack_off = start_stack_off;
3847}
3848
3849void zinsert_breakpoint(z80_context * context, uint16_t address, uint8_t * bp_handler)
3850{
3851	context->bp_handler = bp_handler;
3852	uint8_t bit = 1 << (address % 8);
3853	if (!(bit & context->breakpoint_flags[address / 8])) {
3854		context->breakpoint_flags[address / 8] |= bit;
3855		if (!context->bp_stub) {
3856			zcreate_stub(context);
3857		}
3858		uint8_t * native = z80_get_native_address(context, address);
3859		if (native) {
3860			zbreakpoint_patch(context, address, native);
3861		}
3862	}
3863}
3864
3865void zremove_breakpoint(z80_context * context, uint16_t address)
3866{
3867	context->breakpoint_flags[address / 8] &= ~(1 << (address % 8));
3868	uint8_t * native = z80_get_native_address(context, address);
3869	if (native) {
3870		z80_options * opts = context->options;
3871		code_info tmp_code = opts->gen.code;
3872		opts->gen.code.cur = native;
3873		opts->gen.code.last = native + 128;
3874		check_cycles_int(&opts->gen, address);
3875		opts->gen.code = tmp_code;
3876	}
3877}
3878
3879void z80_serialize(z80_context *context, serialize_buffer *buf)
3880{
3881	for (int i = 0; i <= Z80_A; i++)
3882	{
3883		save_int8(buf, context->regs[i]);
3884	}
3885	uint8_t f = context->flags[ZF_S];
3886	f <<= 1;
3887	f |= context->flags[ZF_Z] ;
3888	f <<= 2;
3889	f |= context->flags[ZF_H];
3890	f <<= 2;
3891	f |= context->flags[ZF_PV];
3892	f <<= 1;
3893	f |= context->flags[ZF_N];
3894	f <<= 1;
3895	f |= context->flags[ZF_C];
3896	f |= context->flags[ZF_XY] & 0x28;
3897	save_int8(buf, f);
3898	for (int i = 0; i <= Z80_A; i++)
3899	{
3900		save_int8(buf, context->alt_regs[i]);
3901	}
3902	f = context->alt_flags[ZF_S];
3903	f <<= 1;
3904	f |= context->alt_flags[ZF_Z] ;
3905	f <<= 2;
3906	f |= context->alt_flags[ZF_H];
3907	f <<= 2;
3908	f |= context->alt_flags[ZF_PV];
3909	f <<= 1;
3910	f |= context->alt_flags[ZF_N];
3911	f <<= 1;
3912	f |= context->alt_flags[ZF_C];
3913	f |= context->flags[ZF_XY] & 0x28;
3914	save_int8(buf, f);
3915	save_int16(buf, context->pc);
3916	save_int16(buf, context->sp);
3917	save_int8(buf, context->im);
3918	save_int8(buf, context->iff1);
3919	save_int8(buf, context->iff2);
3920	save_int8(buf, context->int_is_nmi);
3921	save_int8(buf, context->busack);
3922	save_int32(buf, context->current_cycle);
3923	save_int32(buf, context->int_cycle);
3924	save_int32(buf, context->int_enable_cycle);
3925	save_int32(buf, context->int_pulse_start);
3926	save_int32(buf, context->int_pulse_end);
3927	save_int32(buf, context->nmi_start);
3928}
3929
3930void z80_deserialize(deserialize_buffer *buf, void *vcontext)
3931{
3932	z80_context *context = vcontext;
3933	for (int i = 0; i <= Z80_A; i++)
3934	{
3935		context->regs[i] = load_int8(buf);
3936	}
3937	uint8_t f = load_int8(buf);
3938	context->flags[ZF_XY] = f & 0x28;
3939	context->flags[ZF_C] = f & 1;
3940	f >>= 1;
3941	context->flags[ZF_N] = f & 1;
3942	f >>= 1;
3943	context->flags[ZF_PV] = f & 1;
3944	f >>= 2;
3945	context->flags[ZF_H] = f & 1;
3946	f >>= 2;
3947	context->flags[ZF_Z] = f & 1;
3948	f >>= 1;
3949	context->flags[ZF_S] = f;
3950	for (int i = 0; i <= Z80_A; i++)
3951	{
3952		context->alt_regs[i] = load_int8(buf);
3953	}
3954	f = load_int8(buf);
3955	context->alt_flags[ZF_XY] = f & 0x28;
3956	context->alt_flags[ZF_C] = f & 1;
3957	f >>= 1;
3958	context->alt_flags[ZF_N] = f & 1;
3959	f >>= 1;
3960	context->alt_flags[ZF_PV] = f & 1;
3961	f >>= 2;
3962	context->alt_flags[ZF_H] = f & 1;
3963	f >>= 2;
3964	context->alt_flags[ZF_Z] = f & 1;
3965	f >>= 1;
3966	context->alt_flags[ZF_S] = f;
3967	context->pc = load_int16(buf);
3968	context->sp = load_int16(buf);
3969	context->im = load_int8(buf);
3970	context->iff1 = load_int8(buf);
3971	context->iff2 = load_int8(buf);
3972	context->int_is_nmi = load_int8(buf);
3973	context->busack = load_int8(buf);
3974	context->current_cycle = load_int32(buf);
3975	context->int_cycle = load_int32(buf);
3976	context->int_enable_cycle = load_int32(buf);
3977	context->int_pulse_start = load_int32(buf);
3978	context->int_pulse_end = load_int32(buf);
3979	context->nmi_start = load_int32(buf);
3980	context->native_pc = context->extra_pc = NULL;
3981}
3982