main m68k_core_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 "gen_x86.h"
   7#include "m68k_core.h"
   8#include "m68k_internal.h"
   9#include "68kinst.h"
  10#include "mem.h"
  11#include "backend.h"
  12#include "util.h"
  13#include <stdio.h>
  14#include <stddef.h>
  15#include <stdlib.h>
  16#include <string.h>
  17
  18enum {
  19	FLAG_X,
  20	FLAG_N,
  21	FLAG_Z,
  22	FLAG_V,
  23	FLAG_C
  24};
  25
  26void set_flag(m68k_options * opts, uint8_t val, uint8_t flag)
  27{
  28	if (opts->flag_regs[flag] >= 0) {
  29		mov_ir(&opts->gen.code, val, opts->flag_regs[flag], SZ_B);
  30	} else {
  31		int8_t offset = offsetof(m68k_context, flags) + flag;
  32		if (offset) {
  33			mov_irdisp(&opts->gen.code, val, opts->gen.context_reg, offset, SZ_B);
  34		} else {
  35			mov_irind(&opts->gen.code, val, opts->gen.context_reg, SZ_B);
  36		}
  37	}
  38}
  39
  40void set_flag_cond(m68k_options *opts, uint8_t cond, uint8_t flag)
  41{
  42	if (opts->flag_regs[flag] >= 0) {
  43		setcc_r(&opts->gen.code, cond, opts->flag_regs[flag]);
  44	} else {
  45		int8_t offset = offsetof(m68k_context, flags) + flag;
  46		if (offset) {
  47			setcc_rdisp(&opts->gen.code, cond, opts->gen.context_reg, offset);
  48		} else {
  49			setcc_rind(&opts->gen.code, cond, opts->gen.context_reg);
  50		}
  51	}
  52}
  53
  54void check_flag(m68k_options *opts, uint8_t flag)
  55{
  56	if (opts->flag_regs[flag] >= 0) {
  57		cmp_ir(&opts->gen.code, 0, opts->flag_regs[flag], SZ_B);
  58	} else {
  59		cmp_irdisp(&opts->gen.code, 0, opts->gen.context_reg, offsetof(m68k_context, flags) + flag, SZ_B);
  60	}
  61}
  62
  63void flag_to_reg(m68k_options *opts, uint8_t flag, uint8_t reg)
  64{
  65	if (opts->flag_regs[flag] >= 0) {
  66		mov_rr(&opts->gen.code, opts->flag_regs[flag], reg, SZ_B);
  67	} else {
  68		int8_t offset = offsetof(m68k_context, flags) + flag;
  69		if (offset) {
  70			mov_rdispr(&opts->gen.code, opts->gen.context_reg, offset, reg, SZ_B);
  71		} else {
  72			mov_rindr(&opts->gen.code, opts->gen.context_reg, reg, SZ_B);
  73		}
  74	}
  75}
  76
  77void reg_to_flag(m68k_options *opts, uint8_t reg, uint8_t flag)
  78{
  79	if (opts->flag_regs[flag] >= 0) {
  80		mov_rr(&opts->gen.code, reg, opts->flag_regs[flag], SZ_B);
  81	} else {
  82		int8_t offset = offsetof(m68k_context, flags) + flag;
  83		if (offset) {
  84			mov_rrdisp(&opts->gen.code, reg, opts->gen.context_reg, offset, SZ_B);
  85		} else {
  86			mov_rrind(&opts->gen.code, reg, opts->gen.context_reg, SZ_B);
  87		}
  88	}
  89}
  90
  91void flag_to_flag(m68k_options *opts, uint8_t flag1, uint8_t flag2)
  92{
  93	code_info *code = &opts->gen.code;
  94	if (opts->flag_regs[flag1] >= 0 && opts->flag_regs[flag2] >= 0) {
  95		mov_rr(code, opts->flag_regs[flag1], opts->flag_regs[flag2], SZ_B);
  96	} else if(opts->flag_regs[flag1] >= 0) {
  97		mov_rrdisp(code, opts->flag_regs[flag1], opts->gen.context_reg, offsetof(m68k_context, flags) + flag2, SZ_B);
  98	} else if (opts->flag_regs[flag2] >= 0) {
  99		mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, flags) + flag1, opts->flag_regs[flag2], SZ_B);
 100	} else {
 101		push_r(code, opts->gen.scratch1);
 102		mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, flags) + flag1, opts->gen.scratch1, SZ_B);
 103		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, flags) + flag2, SZ_B);
 104		pop_r(code, opts->gen.scratch1);
 105	}
 106}
 107
 108void update_flags(m68k_options *opts, uint32_t update_mask)
 109{
 110	uint8_t native_flags[] = {0, CC_S, CC_Z, CC_O, CC_C};
 111	for (int8_t flag = FLAG_C; flag >= FLAG_X; --flag)
 112	{
 113		if (update_mask & X0 << (flag*3)) {
 114			set_flag(opts, 0, flag);
 115		} else if(update_mask & X1 << (flag*3)) {
 116			set_flag(opts, 1, flag);
 117		} else if(update_mask & X << (flag*3)) {
 118			if (flag == FLAG_X) {
 119				if (opts->flag_regs[FLAG_C] >= 0 || !(update_mask & (C0|C1|C))) {
 120					flag_to_flag(opts, FLAG_C, FLAG_X);
 121				} else if(update_mask & C0) {
 122					set_flag(opts, 0, flag);
 123				} else if(update_mask & C1) {
 124					set_flag(opts, 1, flag);
 125				} else {
 126					set_flag_cond(opts, CC_C, flag);
 127				}
 128			} else {
 129				set_flag_cond(opts, native_flags[flag], flag);
 130			}
 131		}
 132	}
 133}
 134
 135void flag_to_carry(m68k_options * opts, uint8_t flag)
 136{
 137	if (opts->flag_regs[flag] >= 0) {
 138		bt_ir(&opts->gen.code, 0, opts->flag_regs[flag], SZ_B);
 139	} else {
 140		bt_irdisp(&opts->gen.code, 0, opts->gen.context_reg, offsetof(m68k_context, flags) + flag, SZ_B);
 141	}
 142}
 143
 144void or_flag_to_reg(m68k_options *opts, uint8_t flag, uint8_t reg)
 145{
 146	if (opts->flag_regs[flag] >= 0) {
 147		or_rr(&opts->gen.code, opts->flag_regs[flag], reg, SZ_B);
 148	} else {
 149		or_rdispr(&opts->gen.code, opts->gen.context_reg, offsetof(m68k_context, flags) + flag, reg, SZ_B);
 150	}
 151}
 152
 153void xor_flag_to_reg(m68k_options *opts, uint8_t flag, uint8_t reg)
 154{
 155	if (opts->flag_regs[flag] >= 0) {
 156		xor_rr(&opts->gen.code, opts->flag_regs[flag], reg, SZ_B);
 157	} else {
 158		xor_rdispr(&opts->gen.code, opts->gen.context_reg, offsetof(m68k_context, flags) + flag, reg, SZ_B);
 159	}
 160}
 161
 162void xor_flag(m68k_options *opts, uint8_t val, uint8_t flag)
 163{
 164	if (opts->flag_regs[flag] >= 0) {
 165		xor_ir(&opts->gen.code, val, opts->flag_regs[flag], SZ_B);
 166	} else {
 167		xor_irdisp(&opts->gen.code, val, opts->gen.context_reg, offsetof(m68k_context, flags) + flag, SZ_B);
 168	}
 169}
 170
 171void cmp_flags(m68k_options *opts, uint8_t flag1, uint8_t flag2)
 172{
 173	code_info *code = &opts->gen.code;
 174	if (opts->flag_regs[flag1] >= 0 && opts->flag_regs[flag2] >= 0) {
 175		cmp_rr(code, opts->flag_regs[flag1], opts->flag_regs[flag2], SZ_B);
 176	} else if(opts->flag_regs[flag1] >= 0 || opts->flag_regs[flag2] >= 0) {
 177		if (opts->flag_regs[flag2] >= 0) {
 178			uint8_t tmp = flag1;
 179			flag1 = flag2;
 180			flag2 = tmp;
 181		}
 182		cmp_rrdisp(code, opts->flag_regs[flag1], opts->gen.context_reg, offsetof(m68k_context, flags) + flag2, SZ_B);
 183	} else {
 184		mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, flags) + flag1, opts->gen.scratch1, SZ_B);
 185		cmp_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, flags) + flag2, SZ_B);
 186	}
 187}
 188
 189void areg_to_native(m68k_options *opts, uint8_t reg, uint8_t native_reg)
 190{
 191	if (opts->aregs[reg] >= 0) {
 192		mov_rr(&opts->gen.code, opts->aregs[reg], native_reg, SZ_D);
 193	} else {
 194		mov_rdispr(&opts->gen.code, opts->gen.context_reg,  areg_offset(reg), native_reg, SZ_D);
 195	}
 196}
 197
 198void dreg_to_native(m68k_options *opts, uint8_t reg, uint8_t native_reg)
 199{
 200	if (opts->dregs[reg] >= 0) {
 201		mov_rr(&opts->gen.code, opts->dregs[reg], native_reg, SZ_D);
 202	} else {
 203		mov_rdispr(&opts->gen.code, opts->gen.context_reg,  dreg_offset(reg), native_reg, SZ_D);
 204	}
 205}
 206
 207void areg_to_native_sx(m68k_options *opts, uint8_t reg, uint8_t native_reg)
 208{
 209	if (opts->aregs[reg] >= 0) {
 210		movsx_rr(&opts->gen.code, opts->aregs[reg], native_reg, SZ_W, SZ_D);
 211	} else {
 212		movsx_rdispr(&opts->gen.code, opts->gen.context_reg,  areg_offset(reg), native_reg, SZ_W, SZ_D);
 213	}
 214}
 215
 216void dreg_to_native_sx(m68k_options *opts, uint8_t reg, uint8_t native_reg)
 217{
 218	if (opts->dregs[reg] >= 0) {
 219		movsx_rr(&opts->gen.code, opts->dregs[reg], native_reg, SZ_W, SZ_D);
 220	} else {
 221		movsx_rdispr(&opts->gen.code, opts->gen.context_reg,  dreg_offset(reg), native_reg, SZ_W, SZ_D);
 222	}
 223}
 224
 225void native_to_areg(m68k_options *opts, uint8_t native_reg, uint8_t reg)
 226	{
 227	if (opts->aregs[reg] >= 0) {
 228		mov_rr(&opts->gen.code, native_reg, opts->aregs[reg], SZ_D);
 229	} else {
 230		mov_rrdisp(&opts->gen.code, native_reg, opts->gen.context_reg, areg_offset(reg), SZ_D);
 231	}
 232}
 233
 234void native_to_dreg(m68k_options *opts, uint8_t native_reg, uint8_t reg)
 235{
 236	if (opts->dregs[reg] >= 0) {
 237		mov_rr(&opts->gen.code, native_reg, opts->dregs[reg], SZ_D);
 238	} else {
 239		mov_rrdisp(&opts->gen.code, native_reg, opts->gen.context_reg, dreg_offset(reg), SZ_D);
 240	}
 241}
 242
 243void ldi_areg(m68k_options *opts, int32_t value, uint8_t reg)
 244{
 245	if (opts->aregs[reg] >= 0) {
 246		mov_ir(&opts->gen.code, value, opts->aregs[reg], SZ_D);
 247	} else {
 248		mov_irdisp(&opts->gen.code, value, opts->gen.context_reg, areg_offset(reg), SZ_D);
 249	}
 250}
 251
 252void ldi_native(m68k_options *opts, int32_t value, uint8_t reg)
 253{
 254	mov_ir(&opts->gen.code, value, reg, SZ_D);
 255}
 256
 257void addi_native(m68k_options *opts, int32_t value, uint8_t reg)
 258{
 259	add_ir(&opts->gen.code, value, reg, SZ_D);
 260			}
 261
 262void subi_native(m68k_options *opts, int32_t value, uint8_t reg)
 263{
 264	sub_ir(&opts->gen.code, value, reg, SZ_D);
 265}
 266
 267void push_native(m68k_options *opts, uint8_t reg)
 268{
 269	push_r(&opts->gen.code, reg);
 270}
 271
 272void pop_native(m68k_options *opts, uint8_t reg)
 273{
 274	pop_r(&opts->gen.code, reg);
 275}
 276
 277void sign_extend16_native(m68k_options *opts, uint8_t reg)
 278{
 279	movsx_rr(&opts->gen.code, reg, reg, SZ_W, SZ_D);
 280}
 281
 282void addi_areg(m68k_options *opts, int32_t val, uint8_t reg)
 283{
 284	if (opts->aregs[reg] >= 0) {
 285		add_ir(&opts->gen.code, val, opts->aregs[reg], SZ_D);
 286	} else {
 287		add_irdisp(&opts->gen.code, val, opts->gen.context_reg, areg_offset(reg), SZ_D);
 288	}
 289}
 290
 291void subi_areg(m68k_options *opts, int32_t val, uint8_t reg)
 292{
 293	if (opts->aregs[reg] >= 0) {
 294		sub_ir(&opts->gen.code, val, opts->aregs[reg], SZ_D);
 295	} else {
 296		sub_irdisp(&opts->gen.code, val, opts->gen.context_reg, areg_offset(reg), SZ_D);
 297	}
 298}
 299
 300void add_areg_native(m68k_options *opts, uint8_t reg, uint8_t native_reg)
 301{
 302	if (opts->aregs[reg] >= 0) {
 303		add_rr(&opts->gen.code, opts->aregs[reg], native_reg, SZ_D);
 304	} else {
 305		add_rdispr(&opts->gen.code, opts->gen.context_reg, areg_offset(reg), native_reg, SZ_D);
 306	}
 307}
 308
 309void add_dreg_native(m68k_options *opts, uint8_t reg, uint8_t native_reg)
 310{
 311	if (opts->dregs[reg] >= 0) {
 312		add_rr(&opts->gen.code, opts->dregs[reg], native_reg, SZ_D);
 313	} else {
 314		add_rdispr(&opts->gen.code, opts->gen.context_reg, dreg_offset(reg), native_reg, SZ_D);
 315	}
 316}
 317
 318void calc_areg_displace(m68k_options *opts, m68k_op_info *op, uint8_t native_reg)
 319{
 320	areg_to_native(opts, op->params.regs.pri, native_reg);
 321	add_ir(&opts->gen.code, op->params.regs.displacement & 0x8000 ? op->params.regs.displacement | 0xFFFF0000 : op->params.regs.displacement, native_reg, SZ_D);
 322}
 323
 324void calc_index_disp8(m68k_options *opts, m68k_op_info *op, uint8_t native_reg)
 325{
 326	uint8_t sec_reg = (op->params.regs.sec >> 1) & 0x7;
 327	if (op->params.regs.sec & 1) {
 328		if (op->params.regs.sec & 0x10) {
 329			add_areg_native(opts, sec_reg, native_reg);
 330		} else {
 331			add_dreg_native(opts, sec_reg, native_reg);
 332		}
 333	} else {
 334		uint8_t other_reg = native_reg == opts->gen.scratch1 ? opts->gen.scratch2 : opts->gen.scratch1;
 335		if (op->params.regs.sec & 0x10) {
 336			areg_to_native_sx(opts, sec_reg, other_reg);
 337		} else {
 338			dreg_to_native_sx(opts, sec_reg, other_reg);
 339		}
 340		add_rr(&opts->gen.code, other_reg, native_reg, SZ_D);
 341	}
 342	if (op->params.regs.displacement) {
 343		add_ir(&opts->gen.code, op->params.regs.displacement, native_reg, SZ_D);
 344	}
 345}
 346
 347void calc_areg_index_disp8(m68k_options *opts, m68k_op_info *op, uint8_t native_reg)
 348{
 349	areg_to_native(opts, op->params.regs.pri, native_reg);
 350	calc_index_disp8(opts, op, native_reg);
 351}
 352
 353void m68k_check_cycles_int_latch(m68k_options *opts)
 354{
 355	code_info *code = &opts->gen.code;
 356	check_alloc_code(code, 3*MAX_INST_LEN);
 357	uint8_t cc;
 358	if (opts->gen.limit < 0) {
 359		cmp_ir(code, 1, opts->gen.cycles, SZ_D);
 360		cc = CC_NS;
 361	} else {
 362		cmp_rr(code, opts->gen.cycles, opts->gen.limit, SZ_D);
 363		cc = CC_A;
 364	}
 365	code_ptr jmp_off = code->cur+1;
 366	jcc(code, cc, jmp_off+1);
 367	call(code, opts->handle_int_latch);
 368	*jmp_off = code->cur - (jmp_off+1);
 369}
 370
 371uint8_t translate_m68k_op(m68kinst * inst, host_ea * ea, m68k_options * opts, uint8_t dst)
 372{
 373	code_info *code = &opts->gen.code;
 374	m68k_op_info *op = dst ? &inst->dst : &inst->src;
 375	int8_t reg = native_reg(op, opts);
 376	uint8_t sec_reg;
 377	uint8_t ret = 1;
 378	int32_t dec_amount, inc_amount;
 379	if (reg >= 0) {
 380		ea->mode = MODE_REG_DIRECT;
 381		if (!dst && inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) {
 382			movsx_rr(code, reg, opts->gen.scratch1, SZ_W, SZ_D);
 383			ea->base = opts->gen.scratch1;
 384#ifdef X86_32
 385		} else if (reg > RBX && inst->extra.size == OPSIZE_BYTE) {
 386			mov_rr(code, reg, opts->gen.scratch1, SZ_D);
 387			ea->base = opts->gen.scratch1;
 388#endif
 389		} else {
 390			ea->base = reg;
 391		}
 392		return 0;
 393	}
 394	switch (op->addr_mode)
 395	{
 396	case MODE_REG:
 397	case MODE_AREG:
 398		//We only get one memory parameter, so if the dst operand is a register in memory,
 399		//we need to copy this to a temp register first if we're translating the src operand
 400		if (dst || native_reg(&(inst->dst), opts) >= 0 || inst->dst.addr_mode == MODE_UNUSED || !(inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG)
 401		    || inst->op == M68K_EXG) {
 402
 403			ea->mode = MODE_REG_DISPLACE8;
 404			ea->base = opts->gen.context_reg;
 405			ea->disp = reg_offset(op);
 406		} else {
 407			if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) {
 408				movsx_rdispr(code, opts->gen.context_reg, reg_offset(op), opts->gen.scratch1, SZ_W, SZ_D);
 409			} else {
 410				mov_rdispr(code, opts->gen.context_reg, reg_offset(op), opts->gen.scratch1, inst->extra.size);
 411			}
 412			ea->mode = MODE_REG_DIRECT;
 413			ea->base = opts->gen.scratch1;
 414			//we're explicitly handling the areg dest here, so we exit immediately
 415			return 0;
 416		}
 417		ret = 0;
 418		break;
 419	case MODE_AREG_PREDEC:
 420		if (dst && inst->src.addr_mode == MODE_AREG_PREDEC) {
 421			push_r(code, opts->gen.scratch1);
 422		}
 423		dec_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (op->params.regs.pri == 7 ? 2 :1));
 424		if (!dst) {
 425			cycles(&opts->gen, PREDEC_PENALTY);
 426		}
 427		subi_areg(opts, dec_amount, op->params.regs.pri);
 428	case MODE_AREG_INDIRECT:
 429	case MODE_AREG_POSTINC:
 430		areg_to_native(opts, op->params.regs.pri, opts->gen.scratch1);
 431		m68k_read_size(opts, inst->extra.size);
 432
 433		if (dst) {
 434			if (inst->src.addr_mode == MODE_AREG_PREDEC) {
 435				//restore src operand to opts->gen.scratch2
 436				pop_r(code, opts->gen.scratch2);
 437			} else {
 438				//save reg value in opts->gen.scratch2 so we can use it to save the result in memory later
 439				areg_to_native(opts, op->params.regs.pri, opts->gen.scratch2);
 440			}
 441		}
 442
 443		if (op->addr_mode == MODE_AREG_POSTINC) {
 444			inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (op->params.regs.pri == 7 ? 2 : 1));
 445			addi_areg(opts, inc_amount, op->params.regs.pri);
 446		}
 447		ea->mode = MODE_REG_DIRECT;
 448		ea->base = (!dst && inst->dst.addr_mode == MODE_AREG_PREDEC && inst->op != M68K_MOVE) ? opts->gen.scratch2 : opts->gen.scratch1;
 449		break;
 450	case MODE_AREG_DISPLACE:
 451		cycles(&opts->gen, BUS);
 452		calc_areg_displace(opts, op, opts->gen.scratch1);
 453		if (dst) {
 454			push_r(code, opts->gen.scratch1);
 455		}
 456		m68k_read_size(opts, inst->extra.size);
 457		if (dst) {
 458			pop_r(code, opts->gen.scratch2);
 459		}
 460
 461		ea->mode = MODE_REG_DIRECT;
 462		ea->base = opts->gen.scratch1;
 463		break;
 464	case MODE_AREG_INDEX_DISP8:
 465		cycles(&opts->gen, 6);
 466		calc_areg_index_disp8(opts, op, opts->gen.scratch1);
 467		if (dst) {
 468			push_r(code, opts->gen.scratch1);
 469		}
 470		m68k_read_size(opts, inst->extra.size);
 471		if (dst) {
 472			pop_r(code, opts->gen.scratch2);
 473		}
 474
 475		ea->mode = MODE_REG_DIRECT;
 476		ea->base = opts->gen.scratch1;
 477		break;
 478	case MODE_PC_DISPLACE:
 479		cycles(&opts->gen, BUS);
 480		mov_ir(code, op->params.regs.displacement + inst->address+2, opts->gen.scratch1, SZ_D);
 481		if (dst) {
 482			push_r(code, opts->gen.scratch1);
 483		}
 484		m68k_read_size(opts, inst->extra.size);
 485		if (dst) {
 486			pop_r(code, opts->gen.scratch2);
 487		}
 488
 489		ea->mode = MODE_REG_DIRECT;
 490		ea->base = opts->gen.scratch1;
 491		break;
 492	case MODE_PC_INDEX_DISP8:
 493		cycles(&opts->gen, 6);
 494		mov_ir(code, inst->address+2, opts->gen.scratch1, SZ_D);
 495		calc_index_disp8(opts, op, opts->gen.scratch1);
 496		if (dst) {
 497			push_r(code, opts->gen.scratch1);
 498		}
 499		m68k_read_size(opts, inst->extra.size);
 500		if (dst) {
 501			pop_r(code, opts->gen.scratch2);
 502		}
 503
 504		ea->mode = MODE_REG_DIRECT;
 505		ea->base = opts->gen.scratch1;
 506		break;
 507	case MODE_ABSOLUTE:
 508	case MODE_ABSOLUTE_SHORT:
 509		cycles(&opts->gen, op->addr_mode == MODE_ABSOLUTE ? BUS*2 : BUS);
 510		mov_ir(code, op->params.immed, opts->gen.scratch1, SZ_D);
 511		if (dst) {
 512			push_r(code, opts->gen.scratch1);
 513		}
 514		m68k_read_size(opts, inst->extra.size);
 515		if (dst) {
 516			pop_r(code, opts->gen.scratch2);
 517		}
 518
 519		ea->mode = MODE_REG_DIRECT;
 520		ea->base = opts->gen.scratch1;
 521		break;
 522	case MODE_IMMEDIATE:
 523	case MODE_IMMEDIATE_WORD:
 524		if (inst->variant != VAR_QUICK) {
 525			cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG && op->addr_mode == MODE_IMMEDIATE) ? BUS*2 : BUS);
 526		}
 527		ea->mode = MODE_IMMED;
 528		ea->disp = op->params.immed;
 529		//sign extend value when the destination is an address register
 530		if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD && ea->disp & 0x8000) {
 531			ea->disp |= 0xFFFF0000;
 532		}
 533		return inst->variant != VAR_QUICK;
 534	default:
 535		m68k_disasm(inst, disasm_buf);
 536		fatal_error("%X: %s\naddress mode %d not implemented (%s)\n", inst->address, disasm_buf, op->addr_mode, dst ? "dst" : "src");
 537	}
 538	if (!dst && inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) {
 539		if (ea->mode == MODE_REG_DIRECT) {
 540			movsx_rr(code, ea->base, opts->gen.scratch1, SZ_W, SZ_D);
 541		} else {
 542			movsx_rdispr(code, ea->base, ea->disp, opts->gen.scratch1, SZ_W, SZ_D);
 543			ea->mode = MODE_REG_DIRECT;
 544		}
 545		ea->base = opts->gen.scratch1;
 546	}
 547	return ret;
 548}
 549
 550void check_user_mode_swap_ssp_usp(m68k_options *opts)
 551{
 552	code_info * code = &opts->gen.code;
 553	//Check if we've switched to user mode and swap stack pointers if needed
 554	bt_irdisp(code, 5, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
 555	code_ptr end_off = code->cur + 1;
 556	jcc(code, CC_C, code->cur + 2);
 557	swap_ssp_usp(opts);
 558	*end_off = code->cur - (end_off + 1);
 559}
 560
 561void translate_m68k_move(m68k_options * opts, m68kinst * inst)
 562{
 563	code_info *code = &opts->gen.code;
 564	int8_t reg, flags_reg, sec_reg;
 565	uint8_t dir = 0;
 566	int32_t offset;
 567	int32_t inc_amount, dec_amount;
 568	host_ea src;
 569	uint8_t needs_int_latch = translate_m68k_op(inst, &src, opts, 0);
 570	reg = native_reg(&(inst->dst), opts);
 571
 572	if (inst->dst.addr_mode != MODE_AREG) {
 573		if (src.mode == MODE_REG_DIRECT) {
 574			flags_reg = src.base;
 575		} else {
 576			if (reg >= 0) {
 577				flags_reg = reg;
 578			} else {
 579				if(src.mode == MODE_REG_DISPLACE8) {
 580					mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size);
 581				} else {
 582					mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size);
 583				}
 584				src.mode = MODE_REG_DIRECT;
 585				flags_reg = src.base = opts->gen.scratch1;
 586			}
 587		}
 588	}
 589	uint8_t size = inst->extra.size;
 590	switch(inst->dst.addr_mode)
 591	{
 592	case MODE_AREG:
 593		size = OPSIZE_LONG;
 594	case MODE_REG:
 595		if (reg >= 0) {
 596			if (src.mode == MODE_REG_DIRECT) {
 597				mov_rr(code, src.base, reg, size);
 598			} else if (src.mode == MODE_REG_DISPLACE8) {
 599				mov_rdispr(code, src.base, src.disp, reg, size);
 600			} else {
 601				mov_ir(code, src.disp, reg, size);
 602			}
 603		} else if(src.mode == MODE_REG_DIRECT) {
 604			mov_rrdisp(code, src.base, opts->gen.context_reg, reg_offset(&(inst->dst)), size);
 605		} else {
 606			mov_irdisp(code, src.disp, opts->gen.context_reg, reg_offset(&(inst->dst)), size);
 607		}
 608		break;
 609	case MODE_AREG_PREDEC:
 610		dec_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1));
 611	case MODE_AREG_INDIRECT:
 612	case MODE_AREG_POSTINC:
 613		if (src.mode == MODE_REG_DIRECT) {
 614			if (src.base != opts->gen.scratch1) {
 615				mov_rr(code, src.base, opts->gen.scratch1, inst->extra.size);
 616			}
 617		} else if (src.mode == MODE_REG_DISPLACE8) {
 618			mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size);
 619		} else {
 620			mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size);
 621		}
 622		if (inst->dst.addr_mode == MODE_AREG_PREDEC) {
 623			subi_areg(opts, dec_amount, inst->dst.params.regs.pri);
 624		}
 625		areg_to_native(opts, inst->dst.params.regs.pri, opts->gen.scratch2);
 626		break;
 627	case MODE_AREG_DISPLACE:
 628		cycles(&opts->gen, BUS);
 629		calc_areg_displace(opts, &inst->dst, opts->gen.scratch2);
 630		if (src.mode == MODE_REG_DIRECT) {
 631			if (src.base != opts->gen.scratch1) {
 632				mov_rr(code, src.base, opts->gen.scratch1, inst->extra.size);
 633			}
 634		} else if (src.mode == MODE_REG_DISPLACE8) {
 635			mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size);
 636		} else {
 637			mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size);
 638		}
 639		break;
 640	case MODE_AREG_INDEX_DISP8:
 641		cycles(&opts->gen, 6);//TODO: Check to make sure this is correct
 642		//calc_areg_index_disp8 will clober scratch1 when a 16-bit index is used
 643		if (src.base == opts->gen.scratch1 && !(inst->dst.params.regs.sec & 1)) {
 644			push_r(code, opts->gen.scratch1);
 645		}
 646		calc_areg_index_disp8(opts, &inst->dst, opts->gen.scratch2);
 647		if (src.base == opts->gen.scratch1 && !(inst->dst.params.regs.sec & 1)) {
 648			pop_r(code, opts->gen.scratch1);
 649		}
 650		if (src.mode == MODE_REG_DIRECT) {
 651			if (src.base != opts->gen.scratch1) {
 652				mov_rr(code, src.base, opts->gen.scratch1, inst->extra.size);
 653			}
 654		} else if (src.mode == MODE_REG_DISPLACE8) {
 655			mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size);
 656		} else {
 657			mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size);
 658		}
 659		break;
 660	case MODE_PC_DISPLACE:
 661		cycles(&opts->gen, BUS);
 662		mov_ir(code, inst->dst.params.regs.displacement + inst->address+2, opts->gen.scratch2, SZ_D);
 663		if (src.mode == MODE_REG_DIRECT) {
 664			if (src.base != opts->gen.scratch1) {
 665				mov_rr(code, src.base, opts->gen.scratch1, inst->extra.size);
 666			}
 667		} else if (src.mode == MODE_REG_DISPLACE8) {
 668			mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size);
 669		} else {
 670			mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size);
 671		}
 672		break;
 673	case MODE_PC_INDEX_DISP8:
 674		cycles(&opts->gen, 6);//TODO: Check to make sure this is correct
 675		mov_ir(code, inst->address, opts->gen.scratch2, SZ_D);
 676		if (src.base == opts->gen.scratch1 && !(inst->dst.params.regs.sec & 1)) {
 677			push_r(code, opts->gen.scratch1);
 678		}
 679		calc_index_disp8(opts, &inst->dst, opts->gen.scratch2);
 680		if (src.base == opts->gen.scratch1 && !(inst->dst.params.regs.sec & 1)) {
 681			pop_r(code, opts->gen.scratch1);
 682		}
 683		if (src.mode == MODE_REG_DIRECT) {
 684			if (src.base != opts->gen.scratch1) {
 685				mov_rr(code, src.base, opts->gen.scratch1, inst->extra.size);
 686			}
 687		} else if (src.mode == MODE_REG_DISPLACE8) {
 688			mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size);
 689		} else {
 690			mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size);
 691		}
 692		break;
 693	case MODE_ABSOLUTE:
 694	case MODE_ABSOLUTE_SHORT:
 695		if (src.mode == MODE_REG_DIRECT) {
 696			if (src.base != opts->gen.scratch1) {
 697				mov_rr(code, src.base, opts->gen.scratch1, inst->extra.size);
 698			}
 699		} else if (src.mode == MODE_REG_DISPLACE8) {
 700			mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size);
 701		} else {
 702			mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size);
 703		}
 704		if (inst->dst.addr_mode == MODE_ABSOLUTE) {
 705			cycles(&opts->gen, BUS*2);
 706		} else {
 707			cycles(&opts->gen, BUS);
 708		}
 709		mov_ir(code, inst->dst.params.immed, opts->gen.scratch2, SZ_D);
 710		break;
 711	default:
 712		m68k_disasm(inst, disasm_buf);
 713		fatal_error("%X: %s\naddress mode %d not implemented (move dst)\n", inst->address, disasm_buf, inst->dst.addr_mode);
 714	}
 715
 716	if (inst->dst.addr_mode != MODE_AREG) {
 717		cmp_ir(code, 0, flags_reg, inst->extra.size);
 718		update_flags(opts, N|Z|V0|C0);
 719	}
 720	if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG) {
 721		if (inst->extra.size == OPSIZE_LONG) {
 722			//We want the int latch to occur between the two writes,
 723			//but that's a pain to do without refactoring how 32-bit writes work
 724			//workaround it by temporarily increasing the cycle count before the check
 725			cycles(&opts->gen, BUS);
 726		}
 727		m68k_check_cycles_int_latch(opts);
 728		if (inst->extra.size == OPSIZE_LONG) {
 729			//and then backing out that extra increment here before the write happens
 730			cycles(&opts->gen, -BUS);
 731		}
 732		m68k_write_size(opts, inst->extra.size, inst->dst.addr_mode == MODE_AREG_PREDEC);
 733		if (inst->dst.addr_mode == MODE_AREG_POSTINC) {
 734			inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1));
 735			addi_areg(opts, inc_amount, inst->dst.params.regs.pri);
 736		}
 737	} else if (needs_int_latch) {
 738		m68k_check_cycles_int_latch(opts);
 739	}
 740
 741	//add cycles for prefetch
 742	cycles(&opts->gen, BUS);
 743}
 744
 745void translate_m68k_ext(m68k_options * opts, m68kinst * inst)
 746{
 747	code_info *code = &opts->gen.code;
 748	host_ea dst_op;
 749	uint8_t dst_size = inst->extra.size;
 750	inst->extra.size--;
 751	translate_m68k_op(inst, &dst_op, opts, 1);
 752	if (dst_op.mode == MODE_REG_DIRECT) {
 753		movsx_rr(code, dst_op.base, dst_op.base, inst->extra.size, dst_size);
 754		cmp_ir(code, 0, dst_op.base, dst_size);
 755	} else {
 756		movsx_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, inst->extra.size, dst_size);
 757		cmp_ir(code, 0, opts->gen.scratch1, dst_size);
 758		mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, dst_size);
 759	}
 760	inst->extra.size = dst_size;
 761	update_flags(opts, N|V0|C0|Z);
 762	cycles(&opts->gen, BUS);
 763	//M68K EXT only operates on registers so no need for a call to save result here
 764}
 765
 766uint8_t m68k_eval_cond(m68k_options * opts, uint8_t cc)
 767{
 768	uint8_t cond = CC_NZ;
 769	switch (cc)
 770	{
 771	case COND_HIGH:
 772		cond = CC_Z;
 773	case COND_LOW_SAME:
 774		flag_to_reg(opts, FLAG_Z, opts->gen.scratch1);
 775		or_flag_to_reg(opts, FLAG_C, opts->gen.scratch1);
 776		break;
 777	case COND_CARRY_CLR:
 778		cond = CC_Z;
 779	case COND_CARRY_SET:
 780		check_flag(opts, FLAG_C);
 781		break;
 782	case COND_NOT_EQ:
 783		cond = CC_Z;
 784	case COND_EQ:
 785		check_flag(opts, FLAG_Z);
 786		break;
 787	case COND_OVERF_CLR:
 788		cond = CC_Z;
 789	case COND_OVERF_SET:
 790		check_flag(opts, FLAG_V);
 791		break;
 792	case COND_PLUS:
 793		cond = CC_Z;
 794	case COND_MINUS:
 795		check_flag(opts, FLAG_N);
 796		break;
 797	case COND_GREATER_EQ:
 798		cond = CC_Z;
 799	case COND_LESS:
 800		cmp_flags(opts, FLAG_N, FLAG_V);
 801		break;
 802	case COND_GREATER:
 803		cond = CC_Z;
 804	case COND_LESS_EQ:
 805		flag_to_reg(opts, FLAG_V, opts->gen.scratch1);
 806		xor_flag_to_reg(opts, FLAG_N, opts->gen.scratch1);
 807		or_flag_to_reg(opts, FLAG_Z, opts->gen.scratch1);
 808		break;
 809	}
 810	return cond;
 811}
 812
 813void translate_m68k_bcc(m68k_options * opts, m68kinst * inst)
 814{
 815	code_info *code = &opts->gen.code;
 816	
 817	int32_t disp = inst->src.params.immed;
 818	uint32_t after = inst->address + 2;
 819	if (inst->extra.cond == COND_TRUE) {
 820		cycles(&opts->gen, 10);
 821		jump_m68k_abs(opts, after + disp);
 822	} else {
 823		uint8_t cond = m68k_eval_cond(opts, inst->extra.cond);
 824		code_ptr do_branch = code->cur + 1;
 825		jcc(code, cond, do_branch);
 826		
 827		cycles(&opts->gen, inst->variant == VAR_BYTE ? 8 : 12);
 828		code_ptr done = code->cur + 1;
 829		jmp(code, done);
 830		
 831		*do_branch = code->cur - (do_branch + 1);
 832		cycles(&opts->gen, 10);
 833		code_ptr dest_addr = get_native_address(opts, after + disp);
 834		if (!dest_addr) {
 835			opts->gen.deferred = defer_address(opts->gen.deferred, after + disp, code->cur + 1);
 836			//dummy address to be replaced later, make sure it generates a 4-byte displacement
 837			dest_addr = code->cur + 256;
 838		}
 839		jmp(code, dest_addr);
 840		
 841		*done = code->cur - (done + 1);
 842	}
 843}
 844
 845void translate_m68k_scc(m68k_options * opts, m68kinst * inst)
 846{
 847	code_info *code = &opts->gen.code;
 848	uint8_t cond = inst->extra.cond;
 849	host_ea dst_op;
 850	inst->extra.size = OPSIZE_BYTE;
 851	translate_m68k_op(inst, &dst_op, opts, 1);
 852	if (cond == COND_TRUE || cond == COND_FALSE) {
 853		if ((inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG) && inst->extra.cond == COND_TRUE) {
 854			cycles(&opts->gen, 6);
 855		} else {
 856			cycles(&opts->gen, BUS);
 857		}
 858		if (dst_op.mode == MODE_REG_DIRECT) {
 859			mov_ir(code, cond == COND_TRUE ? 0xFF : 0, dst_op.base, SZ_B);
 860		} else {
 861			mov_irdisp(code, cond == COND_TRUE ? 0xFF : 0, dst_op.base, dst_op.disp, SZ_B);
 862		}
 863	} else {
 864		uint8_t cc = m68k_eval_cond(opts, cond);
 865		check_alloc_code(code, 6*MAX_INST_LEN);
 866		code_ptr true_off = code->cur + 1;
 867		jcc(code, cc, code->cur+2);
 868		cycles(&opts->gen, BUS);
 869		if (dst_op.mode == MODE_REG_DIRECT) {
 870			mov_ir(code, 0, dst_op.base, SZ_B);
 871		} else {
 872			mov_irdisp(code, 0, dst_op.base, dst_op.disp, SZ_B);
 873		}
 874		code_ptr end_off = code->cur+1;
 875		jmp(code, code->cur+2);
 876		*true_off = code->cur - (true_off+1);
 877		cycles(&opts->gen, 6);
 878		if (dst_op.mode == MODE_REG_DIRECT) {
 879			mov_ir(code, 0xFF, dst_op.base, SZ_B);
 880		} else {
 881			mov_irdisp(code, 0xFF, dst_op.base, dst_op.disp, SZ_B);
 882		}
 883		*end_off = code->cur - (end_off+1);
 884	}
 885	m68k_save_result(inst, opts);
 886}
 887
 888void translate_m68k_dbcc(m68k_options * opts, m68kinst * inst)
 889{
 890	code_info *code = &opts->gen.code;
 891	//best case duration
 892	cycles(&opts->gen, 10);
 893	code_ptr skip_loc = NULL;
 894	//TODO: Check if COND_TRUE technically valid here even though
 895	//it's basically a slow NOP
 896	if (inst->extra.cond != COND_FALSE) {
 897		uint8_t cond = m68k_eval_cond(opts, inst->extra.cond);
 898		check_alloc_code(code, 6*MAX_INST_LEN);
 899		skip_loc = code->cur + 1;
 900		jcc(code, cond, code->cur + 2);
 901	}
 902	if (opts->dregs[inst->dst.params.regs.pri] >= 0) {
 903		sub_ir(code, 1, opts->dregs[inst->dst.params.regs.pri], SZ_W);
 904		cmp_ir(code, -1, opts->dregs[inst->dst.params.regs.pri], SZ_W);
 905	} else {
 906		sub_irdisp(code, 1, opts->gen.context_reg, offsetof(m68k_context, dregs) + 4 * inst->dst.params.regs.pri, SZ_W);
 907		cmp_irdisp(code, -1, opts->gen.context_reg, offsetof(m68k_context, dregs) + 4 * inst->dst.params.regs.pri, SZ_W);
 908	}
 909	code_ptr loop_end_loc = code->cur + 1;
 910	jcc(code, CC_Z, code->cur + 2);
 911	uint32_t after = inst->address + 2;
 912	jump_m68k_abs(opts, after + inst->src.params.immed);
 913	*loop_end_loc = code->cur - (loop_end_loc+1);
 914	if (skip_loc) {
 915		cycles(&opts->gen, 2);
 916		*skip_loc = code->cur - (skip_loc+1);
 917		cycles(&opts->gen, 2);
 918	} else {
 919		cycles(&opts->gen, 4);
 920	}
 921}
 922
 923void translate_m68k_movep(m68k_options * opts, m68kinst * inst)
 924{
 925	code_info *code = &opts->gen.code;
 926	int8_t reg;
 927	cycles(&opts->gen, BUS*2);
 928	if (inst->src.addr_mode == MODE_REG) {
 929		calc_areg_displace(opts, &inst->dst, opts->gen.scratch2);
 930		reg = native_reg(&(inst->src), opts);
 931		if (inst->extra.size == OPSIZE_LONG) {
 932			if (reg >= 0) {
 933				mov_rr(code, reg, opts->gen.scratch1, SZ_D);
 934				shr_ir(code, 24, opts->gen.scratch1, SZ_D);
 935				push_r(code, opts->gen.scratch2);
 936				call(code, opts->write_8);
 937				pop_r(code, opts->gen.scratch2);
 938				mov_rr(code, reg, opts->gen.scratch1, SZ_D);
 939				shr_ir(code, 16, opts->gen.scratch1, SZ_D);
 940
 941			} else {
 942				mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src))+3, opts->gen.scratch1, SZ_B);
 943				push_r(code, opts->gen.scratch2);
 944				call(code, opts->write_8);
 945				pop_r(code, opts->gen.scratch2);
 946				mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src))+2, opts->gen.scratch1, SZ_B);
 947			}
 948			add_ir(code, 2, opts->gen.scratch2, SZ_D);
 949			push_r(code, opts->gen.scratch2);
 950			call(code, opts->write_8);
 951			pop_r(code, opts->gen.scratch2);
 952			add_ir(code, 2, opts->gen.scratch2, SZ_D);
 953		}
 954		if (reg >= 0) {
 955			mov_rr(code, reg, opts->gen.scratch1, SZ_W);
 956			shr_ir(code, 8, opts->gen.scratch1, SZ_W);
 957			push_r(code, opts->gen.scratch2);
 958			call(code, opts->write_8);
 959			pop_r(code, opts->gen.scratch2);
 960			mov_rr(code, reg, opts->gen.scratch1, SZ_W);
 961		} else {
 962			mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src))+1, opts->gen.scratch1, SZ_B);
 963			push_r(code, opts->gen.scratch2);
 964			call(code, opts->write_8);
 965			pop_r(code, opts->gen.scratch2);
 966			mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_B);
 967		}
 968		add_ir(code, 2, opts->gen.scratch2, SZ_D);
 969		call(code, opts->write_8);
 970	} else {
 971		calc_areg_displace(opts, &inst->src, opts->gen.scratch1);
 972		reg = native_reg(&(inst->dst), opts);
 973		if (inst->extra.size == OPSIZE_LONG) {
 974			if (reg >= 0) {
 975				push_r(code, opts->gen.scratch1);
 976				call(code, opts->read_8);
 977				shl_ir(code, 24, opts->gen.scratch1, SZ_D);
 978				mov_rr(code, opts->gen.scratch1, reg, SZ_D);
 979				pop_r(code, opts->gen.scratch1);
 980				add_ir(code, 2, opts->gen.scratch1, SZ_D);
 981				push_r(code, opts->gen.scratch1);
 982				call(code, opts->read_8);
 983				movzx_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_B, SZ_W);
 984				shl_ir(code, 16, opts->gen.scratch1, SZ_D);
 985				or_rr(code, opts->gen.scratch1, reg, SZ_D);
 986			} else {
 987				push_r(code, opts->gen.scratch1);
 988				call(code, opts->read_8);
 989				mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, reg_offset(&(inst->dst))+3, SZ_B);
 990				pop_r(code, opts->gen.scratch1);
 991				add_ir(code, 2, opts->gen.scratch1, SZ_D);
 992				push_r(code, opts->gen.scratch1);
 993				call(code, opts->read_8);
 994				mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, reg_offset(&(inst->dst))+2, SZ_B);
 995			}
 996			pop_r(code, opts->gen.scratch1);
 997			add_ir(code, 2, opts->gen.scratch1, SZ_D);
 998		}
 999		push_r(code, opts->gen.scratch1);
1000		call(code, opts->read_8);
1001		if (reg >= 0) {
1002
1003			shl_ir(code, 8, opts->gen.scratch1, SZ_W);
1004			mov_rr(code, opts->gen.scratch1, reg, SZ_W);
1005			pop_r(code, opts->gen.scratch1);
1006			add_ir(code, 2, opts->gen.scratch1, SZ_D);
1007			call(code, opts->read_8);
1008			mov_rr(code, opts->gen.scratch1, reg, SZ_B);
1009		} else {
1010			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, reg_offset(&(inst->dst))+1, SZ_B);
1011			pop_r(code, opts->gen.scratch1);
1012			add_ir(code, 2, opts->gen.scratch1, SZ_D);
1013			call(code, opts->read_8);
1014			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, reg_offset(&(inst->dst)), SZ_B);
1015		}
1016	}
1017}
1018
1019typedef void (*shift_ir_t)(code_info *code, uint8_t val, uint8_t dst, uint8_t size);
1020typedef void (*shift_irdisp_t)(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size);
1021typedef void (*shift_clr_t)(code_info *code, uint8_t dst, uint8_t size);
1022typedef void (*shift_clrdisp_t)(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size);
1023
1024void translate_shift(m68k_options * opts, m68kinst * inst, host_ea *src_op, host_ea * dst_op, shift_ir_t shift_ir, shift_irdisp_t shift_irdisp, shift_clr_t shift_clr, shift_clrdisp_t shift_clrdisp, shift_ir_t special, shift_irdisp_t special_disp)
1025{
1026	code_info *code = &opts->gen.code;
1027	code_ptr end_off = NULL;
1028	code_ptr nz_off = NULL;
1029	code_ptr z_off = NULL;
1030	if (inst->src.addr_mode == MODE_UNUSED) {
1031		cycles(&opts->gen, BUS);
1032		//Memory shift
1033		shift_ir(code, 1, dst_op->base, SZ_W);
1034	} else {
1035		if (src_op->mode == MODE_IMMED) {
1036			cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG ? 8 : 6) + 2 * src_op->disp);
1037			if (src_op->disp != 1 && inst->op == M68K_ASL) {
1038				set_flag(opts, 0, FLAG_V);
1039				for (int i = 0; i < src_op->disp; i++) {
1040					if (dst_op->mode == MODE_REG_DIRECT) {
1041						shift_ir(code, 1, dst_op->base, inst->extra.size);
1042					} else {
1043						shift_irdisp(code, 1, dst_op->base, dst_op->disp, inst->extra.size);
1044					}
1045					check_alloc_code(code, 2*MAX_INST_LEN);
1046					code_ptr after_flag_set = code->cur + 1;
1047					jcc(code, CC_NO, code->cur + 2);
1048					set_flag(opts, 1, FLAG_V);
1049					*after_flag_set = code->cur - (after_flag_set+1);
1050				}
1051			} else {
1052				if (dst_op->mode == MODE_REG_DIRECT) {
1053					shift_ir(code, src_op->disp, dst_op->base, inst->extra.size);
1054				} else {
1055					shift_irdisp(code, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size);
1056				}
1057				set_flag_cond(opts, CC_O, FLAG_V);
1058			}
1059		} else {
1060			cycles(&opts->gen, inst->extra.size == OPSIZE_LONG ? 8 : 6);
1061			if (src_op->base != RCX) {
1062				if (src_op->mode == MODE_REG_DIRECT) {
1063					mov_rr(code, src_op->base, RCX, SZ_B);
1064				} else {
1065					mov_rdispr(code, src_op->base, src_op->disp, RCX, SZ_B);
1066				}
1067
1068			}
1069			and_ir(code, 63, RCX, SZ_D);
1070			check_alloc_code(code, 7*MAX_INST_LEN);
1071			nz_off = code->cur + 1;
1072			jcc(code, CC_NZ, code->cur + 2);
1073			//Flag behavior for shift count of 0 is different for x86 than 68K
1074			if (dst_op->mode == MODE_REG_DIRECT) {
1075				cmp_ir(code, 0, dst_op->base, inst->extra.size);
1076			} else {
1077				cmp_irdisp(code, 0, dst_op->base, dst_op->disp, inst->extra.size);
1078			}
1079			set_flag_cond(opts, CC_Z, FLAG_Z);
1080			set_flag_cond(opts, CC_S, FLAG_N);
1081			set_flag(opts, 0, FLAG_C);
1082			//For other instructions, this flag will be set below
1083			if (inst->op == M68K_ASL) {
1084				set_flag(opts, 0, FLAG_V);
1085			}
1086			z_off = code->cur + 1;
1087			jmp(code, code->cur + 2);
1088			*nz_off = code->cur - (nz_off + 1);
1089			//add 2 cycles for every bit shifted
1090			mov_ir(code, 2 * opts->gen.clock_divider, opts->gen.scratch2, SZ_D);
1091			imul_rr(code, RCX, opts->gen.scratch2, SZ_D);
1092			add_rr(code, opts->gen.scratch2, opts->gen.cycles, SZ_D);
1093			if (inst->op == M68K_ASL) {
1094				//ASL has Overflow flag behavior that depends on all of the bits shifted through the MSB
1095				//Easiest way to deal with this is to shift one bit at a time
1096				set_flag(opts, 0, FLAG_V);
1097				check_alloc_code(code, 5*MAX_INST_LEN);
1098				code_ptr loop_start = code->cur;
1099				if (dst_op->mode == MODE_REG_DIRECT) {
1100					shift_ir(code, 1, dst_op->base, inst->extra.size);
1101				} else {
1102					shift_irdisp(code, 1, dst_op->base, dst_op->disp, inst->extra.size);
1103				}
1104				code_ptr after_flag_set = code->cur + 1;
1105				jcc(code, CC_NO, code->cur + 2);
1106				set_flag(opts, 1, FLAG_V);
1107				*after_flag_set = code->cur - (after_flag_set+1);
1108				loop(code, loop_start);
1109			} else {
1110				//x86 shifts modulo 32 for operand sizes less than 64-bits
1111				//but M68K shifts modulo 64, so we need to check for large shifts here
1112				cmp_ir(code, 32, RCX, SZ_B);
1113				check_alloc_code(code, 14*MAX_INST_LEN);
1114				code_ptr norm_shift_off = code->cur + 1;
1115				jcc(code, CC_L, code->cur + 2);
1116				if (special) {
1117					code_ptr after_flag_set = NULL;
1118					if (inst->extra.size == OPSIZE_LONG) {
1119						code_ptr neq_32_off = code->cur + 1;
1120						jcc(code, CC_NZ, code->cur + 2);
1121
1122						//set the carry bit to the lsb
1123						if (dst_op->mode == MODE_REG_DIRECT) {
1124							special(code, 1, dst_op->base, SZ_D);
1125						} else {
1126							special_disp(code, 1, dst_op->base, dst_op->disp, SZ_D);
1127						}
1128						set_flag_cond(opts, CC_C, FLAG_C);
1129						after_flag_set = code->cur + 1;
1130						jmp(code, code->cur + 2);
1131						*neq_32_off = code->cur - (neq_32_off+1);
1132					}
1133					set_flag(opts, 0, FLAG_C);
1134					if (after_flag_set) {
1135						*after_flag_set = code->cur - (after_flag_set+1);
1136					}
1137					set_flag(opts, 1, FLAG_Z);
1138					set_flag(opts, 0, FLAG_N);
1139					if (dst_op->mode == MODE_REG_DIRECT) {
1140						xor_rr(code, dst_op->base, dst_op->base, inst->extra.size);
1141					} else {
1142						mov_irdisp(code, 0, dst_op->base, dst_op->disp, inst->extra.size);
1143					}
1144				} else {
1145					if (dst_op->mode == MODE_REG_DIRECT) {
1146						shift_ir(code, 31, dst_op->base, inst->extra.size);
1147						shift_ir(code, 1, dst_op->base, inst->extra.size);
1148					} else {
1149						shift_irdisp(code, 31, dst_op->base, dst_op->disp, inst->extra.size);
1150						shift_irdisp(code, 1, dst_op->base, dst_op->disp, inst->extra.size);
1151					}
1152
1153				}
1154				end_off = code->cur + 1;
1155				jmp(code, code->cur + 2);
1156				*norm_shift_off = code->cur - (norm_shift_off+1);
1157				if (dst_op->mode == MODE_REG_DIRECT) {
1158					shift_clr(code, dst_op->base, inst->extra.size);
1159				} else {
1160					shift_clrdisp(code, dst_op->base, dst_op->disp, inst->extra.size);
1161				}
1162			}
1163		}
1164
1165	}
1166	if (!special && end_off) {
1167		*end_off = code->cur - (end_off + 1);
1168	}
1169	update_flags(opts, C|Z|N);
1170	if (special && end_off) {
1171		*end_off = code->cur - (end_off + 1);
1172	}
1173	//set X flag to same as C flag
1174	if (opts->flag_regs[FLAG_C] >= 0) {
1175		flag_to_flag(opts, FLAG_C, FLAG_X);
1176	} else {
1177		set_flag_cond(opts, CC_C, FLAG_X);
1178	}
1179	if (z_off) {
1180		*z_off = code->cur - (z_off + 1);
1181	}
1182	if (inst->op != M68K_ASL) {
1183		set_flag(opts, 0, FLAG_V);
1184	}
1185	if (inst->src.addr_mode == MODE_UNUSED) {
1186		m68k_save_result(inst, opts);
1187	}
1188}
1189
1190void translate_m68k_reset(m68k_options *opts, m68kinst *inst)
1191{
1192	code_info *code = &opts->gen.code;
1193	//RESET instructions take a long time to give peripherals time to reset themselves
1194	cycles(&opts->gen, 132);
1195	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, reset_handler), opts->gen.scratch1, SZ_PTR);
1196	cmp_ir(code, 0, opts->gen.scratch1, SZ_PTR);
1197	code_ptr no_reset_handler = code->cur + 1;
1198	jcc(code, CC_Z, code->cur+2);
1199	call(code, opts->gen.save_context);
1200	call_args_r(code, opts->gen.scratch1, 1, opts->gen.context_reg);
1201	mov_rr(code, RAX, opts->gen.context_reg, SZ_PTR);
1202	call(code, opts->gen.load_context);
1203	*no_reset_handler = code->cur - (no_reset_handler + 1);
1204}
1205
1206void op_ir(code_info *code, m68kinst *inst, int32_t val, uint8_t dst, uint8_t size)
1207{
1208	switch (inst->op)
1209	{
1210	case M68K_ADD:  add_ir(code, val, dst, size); break;
1211	case M68K_ADDX: adc_ir(code, val, dst, size); break;
1212	case M68K_AND:  and_ir(code, val, dst, size); break;
1213	case M68K_BTST: bt_ir(code, val, dst, size); break;
1214	case M68K_BSET: bts_ir(code, val, dst, size); break;
1215	case M68K_BCLR: btr_ir(code, val, dst, size); break;
1216	case M68K_BCHG: btc_ir(code, val, dst, size); break;
1217	case M68K_CMP:  cmp_ir(code, val, dst, size); break;
1218	case M68K_EOR:  xor_ir(code, val, dst, size); break;
1219	case M68K_OR:   or_ir(code, val, dst, size); break;
1220	case M68K_ROL:  rol_ir(code, val, dst, size); break;
1221	case M68K_ROR:  ror_ir(code, val, dst, size); break;
1222	case M68K_ROXL: rcl_ir(code, val, dst, size); break;
1223	case M68K_ROXR: rcr_ir(code, val, dst, size); break;
1224	case M68K_SUB:  sub_ir(code, val, dst, size); break;
1225	case M68K_SUBX: sbb_ir(code, val, dst, size); break;
1226	}
1227}
1228
1229void op_irdisp(code_info *code, m68kinst *inst, int32_t val, uint8_t dst, int32_t disp, uint8_t size)
1230{
1231	switch (inst->op)
1232	{
1233	case M68K_ADD:  add_irdisp(code, val, dst, disp, size); break;
1234	case M68K_ADDX: adc_irdisp(code, val, dst, disp, size); break;
1235	case M68K_AND:  and_irdisp(code, val, dst, disp, size); break;
1236	case M68K_BTST: bt_irdisp(code, val, dst, disp, size); break;
1237	case M68K_BSET: bts_irdisp(code, val, dst, disp, size); break;
1238	case M68K_BCLR: btr_irdisp(code, val, dst, disp, size); break;
1239	case M68K_BCHG: btc_irdisp(code, val, dst, disp, size); break;
1240	case M68K_CMP:  cmp_irdisp(code, val, dst, disp, size); break;
1241	case M68K_EOR:  xor_irdisp(code, val, dst, disp, size); break;
1242	case M68K_OR:   or_irdisp(code, val, dst, disp, size); break;
1243	case M68K_ROL:  rol_irdisp(code, val, dst, disp, size); break;
1244	case M68K_ROR:  ror_irdisp(code, val, dst, disp, size); break;
1245	case M68K_ROXL: rcl_irdisp(code, val, dst, disp, size); break;
1246	case M68K_ROXR: rcr_irdisp(code, val, dst, disp, size); break;
1247	case M68K_SUB:  sub_irdisp(code, val, dst, disp, size); break;
1248	case M68K_SUBX: sbb_irdisp(code, val, dst, disp, size); break;
1249	}
1250}
1251
1252void op_rr(code_info *code, m68kinst *inst, uint8_t src, uint8_t dst, uint8_t size)
1253{
1254	switch (inst->op)
1255	{
1256	case M68K_ADD:  add_rr(code, src, dst, size); break;
1257	case M68K_ADDX: adc_rr(code, src, dst, size); break;
1258	case M68K_AND:  and_rr(code, src, dst, size); break;
1259	case M68K_BTST: bt_rr(code, src, dst, size); break;
1260	case M68K_BSET: bts_rr(code, src, dst, size); break;
1261	case M68K_BCLR: btr_rr(code, src, dst, size); break;
1262	case M68K_BCHG: btc_rr(code, src, dst, size); break;
1263	case M68K_CMP:  cmp_rr(code, src, dst, size); break;
1264	case M68K_EOR:  xor_rr(code, src, dst, size); break;
1265	case M68K_OR:   or_rr(code, src, dst, size); break;
1266	case M68K_SUB:  sub_rr(code, src, dst, size); break;
1267	case M68K_SUBX: sbb_rr(code, src, dst, size); break;
1268	}
1269}
1270
1271void op_rrdisp(code_info *code, m68kinst *inst, uint8_t src, uint8_t dst, int32_t disp, uint8_t size)
1272{
1273	switch(inst->op)
1274	{
1275	case M68K_ADD:  add_rrdisp(code, src, dst, disp, size); break;
1276	case M68K_ADDX: adc_rrdisp(code, src, dst, disp, size); break;
1277	case M68K_AND:  and_rrdisp(code, src, dst, disp, size); break;
1278	case M68K_BTST: bt_rrdisp(code, src, dst, disp, size); break;
1279	case M68K_BSET: bts_rrdisp(code, src, dst, disp, size); break;
1280	case M68K_BCLR: btr_rrdisp(code, src, dst, disp, size); break;
1281	case M68K_BCHG: btc_rrdisp(code, src, dst, disp, size); break;
1282	case M68K_CMP:  cmp_rrdisp(code, src, dst, disp, size); break;
1283	case M68K_EOR:  xor_rrdisp(code, src, dst, disp, size); break;
1284	case M68K_OR:   or_rrdisp(code, src, dst, disp, size); break;
1285	case M68K_SUB:  sub_rrdisp(code, src, dst, disp, size); break;
1286	case M68K_SUBX: sbb_rrdisp(code, src, dst, disp, size); break;
1287	}
1288}
1289
1290void op_rdispr(code_info *code, m68kinst *inst, uint8_t src, int32_t disp, uint8_t dst, uint8_t size)
1291{
1292	switch (inst->op)
1293	{
1294	case M68K_ADD:  add_rdispr(code, src, disp, dst, size); break;
1295	case M68K_ADDX: adc_rdispr(code, src, disp, dst, size); break;
1296	case M68K_AND:  and_rdispr(code, src, disp, dst, size); break;
1297	case M68K_CMP:  cmp_rdispr(code, src, disp, dst, size); break;
1298	case M68K_EOR:  xor_rdispr(code, src, disp, dst, size); break;
1299	case M68K_OR:   or_rdispr(code, src, disp, dst, size); break;
1300	case M68K_SUB:  sub_rdispr(code, src, disp, dst, size); break;
1301	case M68K_SUBX: sbb_rdispr(code, src, disp, dst, size); break;
1302	}
1303}
1304
1305void translate_m68k_arith(m68k_options *opts, m68kinst * inst, uint32_t flag_mask, host_ea *src_op, host_ea *dst_op)
1306{
1307	code_info *code = &opts->gen.code;
1308	uint8_t size = inst->dst.addr_mode == MODE_AREG ? OPSIZE_LONG : inst->extra.size;
1309	
1310	uint32_t numcycles;
1311	if ((inst->op == M68K_ADDX || inst->op == M68K_SUBX) && inst->src.addr_mode != MODE_REG) {
1312		numcycles = 6;
1313	} else if (size == OPSIZE_LONG) {
1314		if (inst->op == M68K_CMP) {
1315			numcycles = 6;
1316		} else if (inst->op == M68K_AND && inst->variant == VAR_IMMEDIATE) {
1317			numcycles = 6;
1318		} else if (inst->op == M68K_ADD && inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD && inst->variant == VAR_QUICK) {
1319			numcycles = 4;
1320		} else if (inst->dst.addr_mode <= MODE_AREG) {
1321			numcycles = inst->src.addr_mode <= MODE_AREG || inst->src.addr_mode == MODE_IMMEDIATE ? 8 : 6;
1322		} else {
1323			numcycles = 4;
1324		}
1325	} else {
1326		numcycles = 4;
1327	}
1328	cycles(&opts->gen, numcycles);
1329	
1330	if (inst->op == M68K_ADDX || inst->op == M68K_SUBX) {
1331		flag_to_carry(opts, FLAG_X);
1332	}
1333	
1334	if (src_op->mode == MODE_REG_DIRECT) {
1335		if (dst_op->mode == MODE_REG_DIRECT) {
1336			op_rr(code, inst, src_op->base, dst_op->base, size);
1337		} else {
1338			op_rrdisp(code, inst, src_op->base, dst_op->base, dst_op->disp, size);
1339		}
1340	} else if (src_op->mode == MODE_REG_DISPLACE8) {
1341		op_rdispr(code, inst, src_op->base, src_op->disp, dst_op->base, size);
1342	} else {
1343		if (dst_op->mode == MODE_REG_DIRECT) {
1344			op_ir(code, inst, src_op->disp, dst_op->base, size);
1345		} else {
1346			op_irdisp(code, inst, src_op->disp, dst_op->base, dst_op->disp, size);
1347		}
1348	}
1349	if (inst->dst.addr_mode != MODE_AREG || inst->op == M68K_CMP) {
1350		update_flags(opts, flag_mask);
1351		if (inst->op == M68K_ADDX || inst->op == M68K_SUBX) {
1352			check_alloc_code(code, 2*MAX_INST_LEN);
1353			code_ptr after_flag_set = code->cur + 1;
1354			jcc(code, CC_Z, code->cur + 2);
1355			set_flag(opts, 0, FLAG_Z);
1356			*after_flag_set = code->cur - (after_flag_set+1);
1357		}
1358	}
1359	if (inst->op != M68K_CMP) {
1360		m68k_save_result(inst, opts);
1361	}
1362}
1363
1364void translate_m68k_cmp(m68k_options * opts, m68kinst * inst)
1365{
1366	code_info *code = &opts->gen.code;
1367	uint8_t size = inst->extra.size;
1368	host_ea src_op, dst_op;
1369	translate_m68k_op(inst, &src_op, opts, 0);
1370	if (inst->dst.addr_mode == MODE_AREG_POSTINC) {
1371		push_r(code, opts->gen.scratch1);
1372		translate_m68k_op(inst, &dst_op, opts, 1);
1373		pop_r(code, opts->gen.scratch2);
1374		src_op.base = opts->gen.scratch2;
1375	} else {
1376		translate_m68k_op(inst, &dst_op, opts, 1);
1377		if (inst->dst.addr_mode == MODE_AREG && size == OPSIZE_WORD) {
1378			size = OPSIZE_LONG;
1379		}
1380	}
1381	translate_m68k_arith(opts, inst, N|Z|V|C, &src_op, &dst_op);
1382}
1383
1384void translate_m68k_tas(m68k_options *opts, m68kinst *inst)
1385{
1386	code_info *code = &opts->gen.code;
1387	host_ea op;
1388	translate_m68k_op(inst, &op, opts, 1);
1389	if (op.mode == MODE_REG_DIRECT) {
1390		cmp_ir(code, 0, op.base, SZ_B);
1391	} else {
1392		cmp_irdisp(code, 0, op.base, op.disp, SZ_B);
1393	}
1394	update_flags(opts, N|Z|V0|C0);
1395	if (inst->dst.addr_mode == MODE_REG) {
1396		cycles(&opts->gen, BUS);
1397		if (op.mode == MODE_REG_DIRECT) {
1398			bts_ir(code, 7, op.base, SZ_B);
1399		} else {
1400			bts_irdisp(code, 7, op.base, op.disp, SZ_B);
1401		}
1402	} else {
1403		if (opts->gen.flags & M68K_OPT_BROKEN_READ_MODIFY) {
1404			//2 cycles for processing
1405			//4 for failed writeback
1406			//4 for prefetch
1407			cycles(&opts->gen, BUS * 2 + 2);
1408		} else {
1409			cycles(&opts->gen, 2);
1410			bts_ir(code, 7, op.base, SZ_B);
1411			m68k_save_result(inst, opts);
1412			cycles(&opts->gen, BUS);
1413		}
1414	}
1415}
1416
1417void op_r(code_info *code, m68kinst *inst, uint8_t dst, uint8_t size)
1418{
1419	switch(inst->op)
1420	{
1421	case M68K_CLR:   xor_rr(code, dst, dst, size); break;
1422	case M68K_NEG:   neg_r(code, dst, size); break;
1423	case M68K_NOT:   not_r(code, dst, size); cmp_ir(code, 0, dst, size); break;
1424	case M68K_ROL:   rol_clr(code, dst, size); break;
1425	case M68K_ROR:   ror_clr(code, dst, size); break;
1426	case M68K_ROXL:  rcl_clr(code, dst, size); break;
1427	case M68K_ROXR:  rcr_clr(code, dst, size); break;
1428	case M68K_SWAP:  rol_ir(code, 16, dst, SZ_D); cmp_ir(code, 0, dst, SZ_D); break;
1429	case M68K_TST:   cmp_ir(code, 0, dst, size); break;
1430	}
1431}
1432
1433void op_rdisp(code_info *code, m68kinst *inst, uint8_t dst, int32_t disp, uint8_t size)
1434{
1435	switch(inst->op)
1436	{
1437	case M68K_CLR:   mov_irdisp(code, 0, dst, disp, size); break;
1438	case M68K_NEG:   neg_rdisp(code, dst, disp, size); break;
1439	case M68K_NOT:   not_rdisp(code, dst, disp, size); cmp_irdisp(code, 0, dst, disp, size); break;
1440	case M68K_ROL:   rol_clrdisp(code, dst, disp, size); break;
1441	case M68K_ROR:   ror_clrdisp(code, dst, disp, size); break;
1442	case M68K_ROXL:  rcl_clrdisp(code, dst, disp, size); break;
1443	case M68K_ROXR:  rcr_clrdisp(code, dst, disp, size); break;
1444	case M68K_SWAP:  rol_irdisp(code, 16, dst, disp, SZ_D); cmp_irdisp(code, 0, dst, disp, SZ_D); break;
1445	case M68K_TST:   cmp_irdisp(code, 0, dst, disp, size); break;
1446	}
1447}
1448
1449void translate_m68k_unary(m68k_options *opts, m68kinst *inst, uint32_t flag_mask, host_ea *dst_op)
1450{
1451	code_info *code = &opts->gen.code;
1452	uint32_t num_cycles = BUS;
1453	if (inst->extra.size == OPSIZE_LONG && (inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG)) {
1454		num_cycles += 2;
1455	}
1456	cycles(&opts->gen, num_cycles);
1457	if (dst_op->mode == MODE_REG_DIRECT) {
1458		op_r(code, inst, dst_op->base, inst->extra.size);
1459	} else {
1460		op_rdisp(code, inst, dst_op->base, dst_op->disp, inst->extra.size);
1461	}
1462	update_flags(opts, flag_mask);
1463	m68k_save_result(inst, opts);
1464}
1465
1466void translate_m68k_abcd_sbcd(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1467{
1468	code_info *code = &opts->gen.code;
1469	if (inst->op == M68K_NBCD) {
1470		if (dst_op->base != opts->gen.scratch2) {
1471			if (dst_op->mode == MODE_REG_DIRECT) {
1472				mov_rr(code, dst_op->base, opts->gen.scratch2, SZ_B);
1473			} else {
1474				mov_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch2, SZ_B);
1475			}
1476		}
1477		xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_B);
1478	} else {
1479		if (src_op->base != opts->gen.scratch2) {
1480			if (src_op->mode == MODE_REG_DIRECT) {
1481				mov_rr(code, src_op->base, opts->gen.scratch2, SZ_B);
1482			} else {
1483				mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch2, SZ_B);
1484			}
1485		}
1486		if (dst_op->base != opts->gen.scratch1) {
1487			if (dst_op->mode == MODE_REG_DIRECT) {
1488				mov_rr(code, dst_op->base, opts->gen.scratch1, SZ_B);
1489			} else {
1490				mov_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch1, SZ_B);
1491			}
1492		}
1493	}
1494	if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG && inst->dst.addr_mode != MODE_AREG_PREDEC) {
1495		//destination is in memory so we need to preserve scratch2 for the write at the end
1496		push_r(code, opts->gen.scratch2);
1497	}
1498	//MC68000 User's Manual suggests NBCD hides the 2 cycle penalty during the write cycle somehow
1499	cycles(&opts->gen, inst->op == M68K_NBCD && inst->dst.addr_mode != MODE_REG_DIRECT ? BUS : BUS + 2);
1500	uint8_t other_reg;
1501	//WARNING: This may need adjustment if register assignments change
1502	if (opts->gen.scratch2 > RBX) {
1503		other_reg = RAX;
1504		xchg_rr(code, opts->gen.scratch2, RAX, SZ_D);
1505	} else {
1506		other_reg = opts->gen.scratch2;
1507	}
1508	mov_rr(code, opts->gen.scratch1, opts->gen.scratch1 + (AH-RAX), SZ_B);
1509	mov_rr(code, other_reg, other_reg + (AH-RAX), SZ_B);
1510	and_ir(code, 0xF, opts->gen.scratch1 + (AH-RAX), SZ_B);
1511	and_ir(code, 0xF, other_reg + (AH-RAX), SZ_B);
1512	//do op on low nibble so we can determine if an adjustment is necessary
1513	flag_to_carry(opts, FLAG_X);
1514	if (inst->op == M68K_ABCD) {
1515		adc_rr(code, other_reg + (AH-RAX), opts->gen.scratch1 + (AH-RAX), SZ_B);
1516	} else {
1517		sbb_rr(code, other_reg + (AH-RAX), opts->gen.scratch1 + (AH-RAX), SZ_B);
1518	}
1519	cmp_ir(code, inst->op == M68K_SBCD ? 0x10 : 0xA, opts->gen.scratch1 + (AH-RAX), SZ_B);
1520	mov_ir(code, 0xA0, other_reg + (AH-RAX), SZ_B);
1521	code_ptr no_adjust = code->cur+1;
1522	//add correction factor if necessary
1523	jcc(code, CC_B, no_adjust);
1524	mov_ir(code, 6, opts->gen.scratch1 + (AH-RAX), SZ_B);
1525	mov_ir(code, inst->op == M68K_ABCD ? 0x9A : 0xA6, other_reg + (AH-RAX), SZ_B);
1526	code_ptr after_adjust = code->cur+1;
1527	jmp(code, after_adjust);
1528
1529	*no_adjust = code->cur - (no_adjust+1);
1530	xor_rr(code, opts->gen.scratch1 + (AH-RAX), opts->gen.scratch1 + (AH-RAX), SZ_B);
1531	*after_adjust = code->cur - (after_adjust+1);
1532
1533	//do op on full byte
1534	flag_to_carry(opts, FLAG_X);
1535	if (inst->op == M68K_ABCD) {
1536		adc_rr(code, other_reg, opts->gen.scratch1, SZ_B);
1537	} else {
1538		sbb_rr(code, other_reg, opts->gen.scratch1, SZ_B);
1539	}
1540	set_flag(opts, 0, FLAG_C);
1541	//determine if we need a correction on the upper nibble
1542	code_ptr def_adjust = code->cur+1;
1543	jcc(code, CC_C, def_adjust);
1544	if (inst->op == M68K_SBCD) {
1545		no_adjust = code->cur+1;
1546		jmp(code, no_adjust);
1547	} else {
1548		cmp_rr(code, other_reg + (AH-RAX), opts->gen.scratch1, SZ_B);
1549		no_adjust = code->cur+1;
1550		jcc(code, CC_B, no_adjust);
1551	}
1552	*def_adjust = code->cur - (def_adjust + 1);
1553	set_flag(opts, 1, FLAG_C);
1554	or_ir(code, 0x60, opts->gen.scratch1 + (AH-RAX), SZ_B);
1555	*no_adjust = code->cur - (no_adjust+1);
1556	if (inst->op == M68K_ABCD) {
1557		add_rr(code, opts->gen.scratch1 + (AH-RAX), opts->gen.scratch1, SZ_B);
1558	} else {
1559		sub_rr(code, opts->gen.scratch1 + (AH-RAX), opts->gen.scratch1, SZ_B);
1560	}
1561	code_ptr no_ensure_carry = code->cur+1;
1562	jcc(code, CC_NC, no_ensure_carry);
1563	set_flag(opts, 1, FLAG_C);
1564	*no_ensure_carry = code->cur - (no_ensure_carry+1);
1565	//restore RAX if necessary
1566	if (opts->gen.scratch2 > RBX) {
1567		mov_rr(code, opts->gen.scratch2, RAX, SZ_D);
1568	}
1569	//V flag is set based on the result of the addition/subtraction of the
1570	//result and the correction factor
1571	set_flag_cond(opts, CC_O, FLAG_V);
1572
1573	flag_to_flag(opts, FLAG_C, FLAG_X);
1574
1575	cmp_ir(code, 0, opts->gen.scratch1, SZ_B);
1576	set_flag_cond(opts, CC_S, FLAG_N);
1577	code_ptr no_setz = code->cur+1;
1578	jcc(code, CC_Z, no_setz);
1579	set_flag(opts, 0, FLAG_Z);
1580	*no_setz = code->cur - (no_setz + 1);
1581	if (dst_op->base != opts->gen.scratch1) {
1582		if (dst_op->mode == MODE_REG_DIRECT) {
1583			mov_rr(code, opts->gen.scratch1, dst_op->base, SZ_B);
1584		} else {
1585			mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, SZ_B);
1586		}
1587	}
1588	if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG && inst->dst.addr_mode != MODE_AREG_PREDEC) {
1589		//destination is in memory so we need to restore scratch2 for the write at the end
1590		pop_r(code, opts->gen.scratch2);
1591	}
1592	m68k_save_result(inst, opts);
1593}
1594
1595void translate_m68k_sl(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1596{
1597	translate_shift(opts, inst, src_op, dst_op, shl_ir, shl_irdisp, shl_clr, shl_clrdisp, shr_ir, shr_irdisp);
1598}
1599
1600void translate_m68k_asr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1601{
1602	translate_shift(opts, inst, src_op, dst_op, sar_ir, sar_irdisp, sar_clr, sar_clrdisp, NULL, NULL);
1603}
1604
1605void translate_m68k_lsr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1606{
1607	translate_shift(opts, inst, src_op, dst_op, shr_ir, shr_irdisp, shr_clr, shr_clrdisp, shl_ir, shl_irdisp);
1608}
1609
1610void translate_m68k_bit(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1611{
1612	code_info *code = &opts->gen.code;
1613	cycles(&opts->gen, inst->extra.size == OPSIZE_BYTE ? 4 : (
1614			inst->op == M68K_BTST ? 6 : (inst->op == M68K_BCLR ? 10 : 8))
1615	);
1616	if (src_op->mode == MODE_IMMED) {
1617		if (inst->extra.size == OPSIZE_BYTE) {
1618			src_op->disp &= 0x7;
1619		}
1620		if (dst_op->mode == MODE_REG_DIRECT) {
1621			op_ir(code, inst, src_op->disp, dst_op->base, inst->extra.size);
1622		} else {
1623			op_irdisp(code, inst, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size);
1624		}
1625	} else {
1626		if (src_op->mode == MODE_REG_DISPLACE8 || (inst->dst.addr_mode != MODE_REG && src_op->base != opts->gen.scratch1 && src_op->base != opts->gen.scratch2)) {
1627			if (dst_op->base == opts->gen.scratch1) {
1628				push_r(code, opts->gen.scratch2);
1629				if (src_op->mode == MODE_REG_DIRECT) {
1630					mov_rr(code, src_op->base, opts->gen.scratch2, SZ_B);
1631				} else {
1632					mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch2, SZ_B);
1633				}
1634				src_op->base = opts->gen.scratch2;
1635			} else {
1636				if (src_op->mode == MODE_REG_DIRECT) {
1637					mov_rr(code, src_op->base, opts->gen.scratch1, SZ_B);
1638				} else {
1639					mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_B);
1640				}
1641				src_op->base = opts->gen.scratch1;
1642				}
1643			}
1644			uint8_t size = inst->extra.size;
1645		if (dst_op->mode == MODE_REG_DISPLACE8) {
1646			if (src_op->base != opts->gen.scratch1 && src_op->base != opts->gen.scratch2) {
1647				if (src_op->mode == MODE_REG_DIRECT) {
1648					mov_rr(code, src_op->base, opts->gen.scratch1, SZ_D);
1649				} else {
1650					mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_D);
1651					src_op->mode = MODE_REG_DIRECT;
1652				}
1653				src_op->base = opts->gen.scratch1;
1654			}
1655			//b### with register destination is modulo 32
1656			//x86 with a memory destination isn't modulo anything
1657			//so use an and here to force the value to be modulo 32
1658			and_ir(code, 31, opts->gen.scratch1, SZ_D);
1659		} else if(inst->dst.addr_mode != MODE_REG) {
1660			//b### with memory destination is modulo 8
1661			//x86-64 doesn't support 8-bit bit operations
1662			//so we fake it by forcing the bit number to be modulo 8
1663			and_ir(code, 7, src_op->base, SZ_D);
1664			size = SZ_D;
1665		}
1666		if (dst_op->mode == MODE_IMMED) {
1667			dst_op->base = src_op->base == opts->gen.scratch1 ? opts->gen.scratch2 : opts->gen.scratch1;
1668			mov_ir(code, dst_op->disp, dst_op->base, SZ_B);
1669			dst_op->mode = MODE_REG_DIRECT;
1670		}
1671		if (dst_op->mode == MODE_REG_DIRECT) {
1672			op_rr(code, inst, src_op->base, dst_op->base, size);
1673		} else {
1674			op_rrdisp(code, inst, src_op->base, dst_op->base, dst_op->disp, size);
1675		}
1676		if (src_op->base == opts->gen.scratch2) {
1677			pop_r(code, opts->gen.scratch2);
1678		}
1679	}
1680	//x86 sets the carry flag to the value of the bit tested
1681	//68K sets the zero flag to the complement of the bit tested
1682	set_flag_cond(opts, CC_NC, FLAG_Z);
1683	if (inst->op != M68K_BTST) {
1684		m68k_save_result(inst, opts);
1685	}
1686}
1687
1688void translate_m68k_chk(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1689	{
1690	code_info *code = &opts->gen.code;
1691	cycles(&opts->gen, 6);
1692	if (dst_op->mode == MODE_REG_DIRECT) {
1693		cmp_ir(code, 0, dst_op->base, inst->extra.size);
1694	} else {
1695		cmp_irdisp(code, 0, dst_op->base, dst_op->disp, inst->extra.size);
1696	}
1697	uint32_t isize;
1698	switch(inst->src.addr_mode)
1699	{
1700	case MODE_AREG_DISPLACE:
1701	case MODE_AREG_INDEX_DISP8:
1702	case MODE_ABSOLUTE_SHORT:
1703	case MODE_PC_INDEX_DISP8:
1704	case MODE_PC_DISPLACE:
1705	case MODE_IMMEDIATE:
1706		isize = 4;
1707		break;
1708	case MODE_ABSOLUTE:
1709		isize = 6;
1710		break;
1711	default:
1712		isize = 2;
1713	}
1714	//make sure we won't start a new chunk in the middle of these branches
1715	check_alloc_code(code, MAX_INST_LEN * 11);
1716	code_ptr passed = code->cur + 1;
1717	jcc(code, CC_GE, code->cur + 2);
1718	set_flag(opts, 1, FLAG_N);
1719	mov_ir(code, VECTOR_CHK, opts->gen.scratch2, SZ_D);
1720	mov_ir(code, inst->address+isize, opts->gen.scratch1, SZ_D);
1721	jmp(code, opts->trap);
1722	*passed = code->cur - (passed+1);
1723	if (dst_op->mode == MODE_REG_DIRECT) {
1724		if (src_op->mode == MODE_REG_DIRECT) {
1725			cmp_rr(code, src_op->base, dst_op->base, inst->extra.size);
1726		} else if(src_op->mode == MODE_REG_DISPLACE8) {
1727			cmp_rdispr(code, src_op->base, src_op->disp, dst_op->base, inst->extra.size);
1728		} else {
1729			cmp_ir(code, src_op->disp, dst_op->base, inst->extra.size);
1730		}
1731	} else if(dst_op->mode == MODE_REG_DISPLACE8) {
1732		if (src_op->mode == MODE_REG_DIRECT) {
1733			cmp_rrdisp(code, src_op->base, dst_op->base, dst_op->disp, inst->extra.size);
1734		} else {
1735			cmp_irdisp(code, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size);
1736		}
1737	}
1738	passed = code->cur + 1;
1739	jcc(code, CC_LE, code->cur + 2);
1740	set_flag(opts, 0, FLAG_N);
1741	mov_ir(code, VECTOR_CHK, opts->gen.scratch2, SZ_D);
1742	mov_ir(code, inst->address+isize, opts->gen.scratch1, SZ_D);
1743	jmp(code, opts->trap);
1744	*passed = code->cur - (passed+1);
1745	cycles(&opts->gen, 4);
1746}
1747
1748static uint32_t divu(uint32_t dividend, m68k_context *context, uint32_t divisor_shift)
1749{
1750	uint16_t quotient = 0;
1751	uint8_t force = 0;
1752	uint16_t bit = 0;
1753	uint32_t cycles = 6;
1754	for (int i = 0; i < 16; i++)
1755	{
1756		force = dividend >> 31;
1757		quotient = quotient << 1 | bit;
1758		dividend = dividend << 1;
1759		
1760		if (force || dividend >= divisor_shift) {
1761			dividend -= divisor_shift;
1762			cycles += force ? 4 : 6;
1763			bit = 1;
1764		} else {
1765			bit = 0;
1766			cycles += 8;
1767		}
1768	}
1769	cycles += force ? 6 : bit ? 4 : 2;
1770	context->current_cycle += cycles * context->options->gen.clock_divider;
1771	quotient = quotient << 1 | bit;
1772	return dividend | quotient;
1773}
1774
1775static uint32_t divs(uint32_t dividend, m68k_context *context, uint32_t divisor_shift)
1776{
1777	uint32_t orig_divisor = divisor_shift, orig_dividend = dividend;
1778	if (divisor_shift & 0x80000000) {
1779		divisor_shift = 0 - divisor_shift;
1780	}
1781	
1782	uint32_t cycles = 12;
1783	if (dividend & 0x80000000) {
1784		//dvs10
1785		dividend = 0 - dividend;
1786		cycles += 2;
1787	}
1788	if (divisor_shift <= dividend) {
1789		context->flags[FLAG_V] = 1;
1790		context->flags[FLAG_N] = 1;
1791		context->flags[FLAG_Z] = 0;
1792		cycles += 2;
1793		context->current_cycle += cycles * context->options->gen.clock_divider;
1794		return orig_dividend;
1795	}
1796	uint16_t quotient = 0;
1797	uint16_t bit = 0;
1798	for (int i = 0; i < 15; i++)
1799	{
1800		quotient = quotient << 1 | bit;
1801		dividend = dividend << 1;
1802		
1803		if (dividend >= divisor_shift) {
1804			dividend -= divisor_shift;
1805			cycles += 6;
1806			bit = 1;
1807		} else {
1808			bit = 0;
1809			cycles += 8;
1810		}
1811	}
1812	quotient = quotient << 1 | bit;
1813	dividend = dividend << 1;
1814	if (dividend >= divisor_shift) {
1815		dividend -= divisor_shift;
1816		quotient = quotient << 1 | 1;
1817	} else {
1818		quotient = quotient << 1;
1819	}
1820	cycles += 4;
1821	
1822	context->flags[FLAG_V] = 0;
1823	if (orig_divisor & 0x80000000) {
1824		cycles += 16; //was 10
1825		if (orig_dividend & 0x80000000) {
1826			if (quotient & 0x8000) {
1827				context->flags[FLAG_V] = 1;
1828				context->flags[FLAG_N] = 1;
1829				context->flags[FLAG_Z] = 0;
1830				context->current_cycle += cycles * context->options->gen.clock_divider;
1831				return orig_dividend;
1832			} else {
1833				dividend = -dividend;
1834			}
1835		} else {
1836			quotient = -quotient;
1837			if (quotient && !(quotient & 0x8000)) {
1838				context->flags[FLAG_V] = 1;
1839			}
1840		}
1841	} else if (orig_dividend & 0x80000000) {
1842		cycles += 18; // was 12
1843		quotient = -quotient;
1844		if (quotient && !(quotient & 0x8000)) {
1845			context->flags[FLAG_V] = 1;
1846		} else {
1847			dividend = -dividend;
1848		}
1849	} else {
1850		cycles += 14; //was 10
1851		if (quotient & 0x8000) {
1852			context->flags[FLAG_V] = 1;
1853		}
1854	}
1855	if (context->flags[FLAG_V]) {
1856		context->flags[FLAG_N] = 1;
1857		context->flags[FLAG_Z] = 0;
1858		context->current_cycle += cycles * context->options->gen.clock_divider;
1859		return orig_dividend;
1860	}
1861	context->flags[FLAG_N] = (quotient & 0x8000) ? 1 : 0;
1862	context->flags[FLAG_Z] = quotient == 0;
1863	//V was cleared above, C is cleared by the generated machine code
1864	context->current_cycle += cycles * context->options->gen.clock_divider;
1865	return dividend | quotient;
1866}
1867
1868void translate_m68k_div(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1869{
1870	code_info *code = &opts->gen.code;
1871	check_alloc_code(code, MAX_NATIVE_SIZE);
1872	set_flag(opts, 0, FLAG_C);
1873	if (dst_op->mode == MODE_REG_DIRECT) {
1874		mov_rr(code, dst_op->base, opts->gen.scratch2, SZ_D);
1875	} else {
1876		mov_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch2, SZ_D);
1877	}
1878	if (src_op->mode == MODE_IMMED) {
1879		mov_ir(code, src_op->disp << 16, opts->gen.scratch1, SZ_D);
1880	} else {
1881		if (src_op->mode == MODE_REG_DISPLACE8) {
1882			movzx_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_W, SZ_D);
1883		} else if (src_op->base != opts->gen.scratch1) {
1884			movzx_rr(code, src_op->base, opts->gen.scratch1, SZ_W, SZ_D);
1885		}
1886		shl_ir(code, 16, opts->gen.scratch1, SZ_D);
1887	}
1888	cmp_ir(code, 0, opts->gen.scratch1, SZ_D);
1889	code_ptr not_zero = code->cur+1;
1890	jcc(code, CC_NZ, not_zero);
1891	
1892	//TODO: Check that opts->trap includes the cycles conumed by the first trap0 microinstruction
1893	cycles(&opts->gen, 4);
1894	uint32_t isize = 2;
1895	switch(inst->src.addr_mode)
1896	{
1897	case MODE_AREG_DISPLACE:
1898	case MODE_AREG_INDEX_DISP8:
1899	case MODE_ABSOLUTE_SHORT:
1900	case MODE_PC_DISPLACE:
1901	case MODE_PC_INDEX_DISP8:
1902	case MODE_IMMEDIATE:
1903		isize = 4;
1904		break;
1905	case MODE_ABSOLUTE:
1906		isize = 6;
1907		break;
1908	}
1909	//zero seems to clear all flags
1910	update_flags(opts, N0|Z0|V0);
1911	mov_ir(code, VECTOR_INT_DIV_ZERO, opts->gen.scratch2, SZ_D);
1912	mov_ir(code, inst->address+isize, opts->gen.scratch1, SZ_D);
1913	jmp(code, opts->trap);
1914	
1915	*not_zero = code->cur - (not_zero + 1);
1916	code_ptr end = NULL;
1917	if (inst->op == M68K_DIVU) {
1918		//initial overflow check needs to be done in the C code for divs
1919		//but can be done before dumping state to mem in divu as an optimization
1920		cmp_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_D);
1921		code_ptr not_overflow = code->cur+1;
1922		jcc(code, CC_C, not_overflow);
1923		
1924		//overflow seems to always set the N and clear Z
1925		update_flags(opts, N1|Z0|V1);
1926		cycles(&opts->gen, 10);
1927		end = code->cur+1;
1928		jmp(code, end);
1929		
1930		*not_overflow = code->cur - (not_overflow + 1);
1931	}
1932	call(code, opts->gen.save_context);
1933	push_r(code, opts->gen.context_reg);
1934	//TODO: inline the functionality of divudivs/ so we don't need to dump context to memory
1935	call_args(code, (code_ptr)(inst->op == M68K_DIVU ? divu : divs), 3, opts->gen.scratch2, opts->gen.context_reg, opts->gen.scratch1);
1936	pop_r(code, opts->gen.context_reg);
1937	mov_rr(code, RAX, opts->gen.scratch1, SZ_D);
1938	
1939	call(code, opts->gen.load_context);
1940	
1941	if (inst->op == M68K_DIVU) {
1942		cmp_ir(code, 0, opts->gen.scratch1, SZ_W);
1943		update_flags(opts, V0|Z|N);
1944	}
1945	
1946	if (dst_op->mode == MODE_REG_DIRECT) {
1947		mov_rr(code, opts->gen.scratch1, dst_op->base, SZ_D);
1948	} else {
1949		mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, SZ_D);
1950	}
1951	if (end) {
1952		*end = code->cur - (end + 1);
1953	}
1954}
1955
1956void translate_m68k_exg(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1957{
1958	code_info *code = &opts->gen.code;
1959	cycles(&opts->gen, 6);
1960	if (dst_op->mode == MODE_REG_DIRECT) {
1961		mov_rr(code, dst_op->base, opts->gen.scratch2, SZ_D);
1962		if (src_op->mode == MODE_REG_DIRECT) {
1963			mov_rr(code, src_op->base, dst_op->base, SZ_D);
1964			mov_rr(code, opts->gen.scratch2, src_op->base, SZ_D);
1965		} else {
1966			mov_rdispr(code, src_op->base, src_op->disp, dst_op->base, SZ_D);
1967			mov_rrdisp(code, opts->gen.scratch2, src_op->base, src_op->disp, SZ_D);
1968		}
1969	} else {
1970		mov_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch2, SZ_D);
1971		if (src_op->mode == MODE_REG_DIRECT) {
1972			mov_rrdisp(code, src_op->base, dst_op->base, dst_op->disp, SZ_D);
1973			mov_rr(code, opts->gen.scratch2, src_op->base, SZ_D);
1974		} else {
1975			mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_D);
1976			mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, SZ_D);
1977			mov_rrdisp(code, opts->gen.scratch2, src_op->base, src_op->disp, SZ_D);
1978		}
1979	}
1980}
1981
1982
1983
1984static uint32_t mulu_cycles(uint16_t value)
1985{
1986	//4 for prefetch, 2-cycles per bit x 16, 2 for cleanup
1987	uint32_t cycles = 38;
1988	uint16_t a = (value & 0b1010101010101010) >> 1;
1989	uint16_t b = value & 0b0101010101010101;
1990	value = a + b;
1991	a = (value & 0b1100110011001100) >> 2;
1992	b = value & 0b0011001100110011;
1993	value = a + b;
1994	a = (value & 0b1111000011110000) >> 4;
1995	b = value & 0b0000111100001111;
1996	value = a + b;
1997	a = (value & 0b1111111100000000) >> 8;
1998	b = value & 0b0000000011111111;
1999	value = a + b;
2000	return cycles + 2*value;
2001}
2002
2003static uint32_t muls_cycles(uint16_t value)
2004{
2005	//muls timing is essentially the same as muls, but it's based on the number of 0/1
2006	//transitions rather than the number of 1 bits. xoring the value with itself shifted
2007	//by one effectively sets one bit for every transition
2008	return mulu_cycles((value << 1) ^ value);
2009}
2010
2011void translate_m68k_mul(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
2012{
2013	code_info *code = &opts->gen.code;
2014	if (src_op->mode == MODE_IMMED) {
2015		cycles(&opts->gen, inst->op == M68K_MULU ? mulu_cycles(src_op->disp) : muls_cycles(src_op->disp));
2016		mov_ir(code, inst->op == M68K_MULU ? (src_op->disp & 0xFFFF) : ((src_op->disp & 0x8000) ? src_op->disp | 0xFFFF0000 : src_op->disp), opts->gen.scratch1, SZ_D);
2017	} else if (src_op->mode == MODE_REG_DIRECT) {
2018		if (inst->op == M68K_MULS) {
2019			movsx_rr(code, src_op->base, opts->gen.scratch1, SZ_W, SZ_D);
2020		} else {
2021			movzx_rr(code, src_op->base, opts->gen.scratch1, SZ_W, SZ_D);
2022		}
2023	} else {
2024		if (inst->op == M68K_MULS) {
2025			movsx_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_W, SZ_D);
2026		} else {
2027			movzx_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_W, SZ_D);
2028		}
2029	}
2030	if (src_op->mode != MODE_IMMED) {
2031		//TODO: Inline cycle calculation so we don't need to save/restore a bunch of registers
2032		//save context to memory and call the relevant C function for calculating the cycle count
2033		call(code, opts->gen.save_context);
2034		push_r(code, opts->gen.scratch1);
2035		push_r(code, opts->gen.context_reg);
2036		call_args(code, (code_ptr)(inst->op == M68K_MULS ? muls_cycles : mulu_cycles), 1, opts->gen.scratch1);
2037		pop_r(code, opts->gen.context_reg);
2038		//turn 68K cycles into master clock cycles and add to the current cycle count
2039		imul_irr(code, opts->gen.clock_divider, RAX, RAX, SZ_D);
2040		add_rrdisp(code, RAX, opts->gen.context_reg, offsetof(m68k_context, current_cycle), SZ_D);
2041		//restore context and scratch1
2042		call(code, opts->gen.load_context);
2043		pop_r(code, opts->gen.scratch1);
2044	}
2045	
2046	uint8_t dst_reg;
2047	if (dst_op->mode == MODE_REG_DIRECT) {
2048		dst_reg = dst_op->base;
2049		if (inst->op == M68K_MULS) {
2050			movsx_rr(code, dst_reg, dst_reg, SZ_W, SZ_D);
2051		} else {
2052			movzx_rr(code, dst_reg, dst_reg, SZ_W, SZ_D);
2053		}
2054	} else {
2055		dst_reg = opts->gen.scratch2;
2056		if (inst->op == M68K_MULS) {
2057			movsx_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch2, SZ_W, SZ_D);
2058		} else {
2059			movzx_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch2, SZ_W, SZ_D);
2060		}
2061	}
2062	imul_rr(code, opts->gen.scratch1, dst_reg, SZ_D);
2063	if (dst_op->mode == MODE_REG_DISPLACE8) {
2064		mov_rrdisp(code, dst_reg, dst_op->base, dst_op->disp, SZ_D);
2065	}
2066	cmp_ir(code, 0, dst_reg, SZ_D);
2067	update_flags(opts, N|Z|V0|C0);
2068}
2069
2070void translate_m68k_negx(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
2071{
2072	code_info *code = &opts->gen.code;
2073	cycles(&opts->gen, BUS);
2074	if (dst_op->mode == MODE_REG_DIRECT) {
2075		if (dst_op->base == opts->gen.scratch1) {
2076			push_r(code, opts->gen.scratch2);
2077			xor_rr(code, opts->gen.scratch2, opts->gen.scratch2, inst->extra.size);
2078			flag_to_carry(opts, FLAG_X);
2079			sbb_rr(code, dst_op->base, opts->gen.scratch2, inst->extra.size);
2080			mov_rr(code, opts->gen.scratch2, dst_op->base, inst->extra.size);
2081			pop_r(code, opts->gen.scratch2);
2082		} else {
2083			xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, inst->extra.size);
2084			flag_to_carry(opts, FLAG_X);
2085			sbb_rr(code, dst_op->base, opts->gen.scratch1, inst->extra.size);
2086			mov_rr(code, opts->gen.scratch1, dst_op->base, inst->extra.size);
2087		}
2088	} else {
2089		xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, inst->extra.size);
2090		flag_to_carry(opts, FLAG_X);
2091		sbb_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch1, inst->extra.size);
2092		mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, inst->extra.size);
2093	}
2094	set_flag_cond(opts, CC_C, FLAG_C);
2095	code_ptr after_flag_set = code->cur + 1;
2096	jcc(code, CC_Z, code->cur + 2);
2097	set_flag(opts, 0, FLAG_Z);
2098	*after_flag_set = code->cur - (after_flag_set+1);
2099	set_flag_cond(opts, CC_S, FLAG_N);
2100	set_flag_cond(opts, CC_O, FLAG_V);
2101	if (opts->flag_regs[FLAG_C] >= 0) {
2102		flag_to_flag(opts, FLAG_C, FLAG_X);
2103	} else {
2104		set_flag_cond(opts, CC_C, FLAG_X);
2105	}
2106	m68k_save_result(inst, opts);
2107}
2108
2109void translate_m68k_rot(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
2110{
2111	code_info *code = &opts->gen.code;
2112	int32_t init_flags = C|V0;
2113	if (inst->src.addr_mode == MODE_UNUSED) {
2114		cycles(&opts->gen, BUS);
2115		//Memory rotate
2116		if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) {
2117			flag_to_carry(opts, FLAG_X);
2118			init_flags |= X;
2119		}
2120		op_ir(code, inst, 1, dst_op->base, inst->extra.size);
2121		update_flags(opts, init_flags);
2122		cmp_ir(code, 0, dst_op->base, inst->extra.size);
2123		update_flags(opts, Z|N);
2124		m68k_save_result(inst, opts);
2125	} else {
2126		if (src_op->mode == MODE_IMMED) {
2127			cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG ? 8 : 6) + src_op->disp*2);
2128			if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) {
2129				flag_to_carry(opts, FLAG_X);
2130				init_flags |= X;
2131			}
2132			if (dst_op->mode == MODE_REG_DIRECT) {
2133				op_ir(code, inst, src_op->disp, dst_op->base, inst->extra.size);
2134			} else {
2135				op_irdisp(code, inst, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size);
2136			}
2137			update_flags(opts, init_flags);
2138		} else {
2139			if (src_op->mode == MODE_REG_DIRECT) {
2140				if (src_op->base != opts->gen.scratch1) {
2141					mov_rr(code, src_op->base, opts->gen.scratch1, SZ_B);
2142				}
2143			} else {
2144				mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_B);
2145			}
2146			and_ir(code, 63, opts->gen.scratch1, SZ_D);
2147			code_ptr zero_off = code->cur + 1;
2148			jcc(code, CC_Z, code->cur + 2);
2149			//add 2 cycles for every bit shifted
2150			mov_ir(code, 2 * opts->gen.clock_divider, opts->gen.scratch2, SZ_D);
2151			imul_rr(code, RCX, opts->gen.scratch2, SZ_D);
2152			add_rr(code, opts->gen.scratch2, opts->gen.cycles, SZ_D);
2153			cmp_ir(code, 32, opts->gen.scratch1, SZ_B);
2154			code_ptr norm_off = code->cur + 1;
2155			jcc(code, CC_L, code->cur + 2);
2156			if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) {
2157				flag_to_carry(opts, FLAG_X);
2158				init_flags |= X;
2159			} else {
2160				sub_ir(code, 32, opts->gen.scratch1, SZ_B);
2161			}
2162			if (dst_op->mode == MODE_REG_DIRECT) {
2163				op_ir(code, inst, 31, dst_op->base, inst->extra.size);
2164				op_ir(code, inst, 1, dst_op->base, inst->extra.size);
2165			} else {
2166				op_irdisp(code, inst, 31, dst_op->base, dst_op->disp, inst->extra.size);
2167				op_irdisp(code, inst, 1, dst_op->base, dst_op->disp, inst->extra.size);
2168			}
2169
2170			if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) {
2171				set_flag_cond(opts, CC_C, FLAG_X);
2172				sub_ir(code, 32, opts->gen.scratch1, SZ_B);
2173				*norm_off = code->cur - (norm_off+1);
2174				flag_to_carry(opts, FLAG_X);
2175			} else {
2176				*norm_off = code->cur - (norm_off+1);
2177			}
2178			if (dst_op->mode == MODE_REG_DIRECT) {
2179				op_r(code, inst, dst_op->base, inst->extra.size);
2180			} else {
2181				op_rdisp(code, inst, dst_op->base, dst_op->disp, inst->extra.size);
2182			}
2183			update_flags(opts, init_flags);
2184			code_ptr end_off = code->cur + 1;
2185			jmp(code, code->cur + 2);
2186			*zero_off = code->cur - (zero_off+1);
2187			if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) {
2188				//Carry flag is set to X flag when count is 0, this is different from ROR/ROL
2189				flag_to_flag(opts, FLAG_X, FLAG_C);
2190			} else {
2191				set_flag(opts, 0, FLAG_C);
2192			}
2193			*end_off = code->cur - (end_off+1);
2194		}
2195		if (dst_op->mode == MODE_REG_DIRECT) {
2196			cmp_ir(code, 0, dst_op->base, inst->extra.size);
2197		} else {
2198			cmp_irdisp(code, 0, dst_op->base, dst_op->disp, inst->extra.size);
2199		}
2200		update_flags(opts, Z|N);
2201	}
2202}
2203
2204#define BIT_SUPERVISOR 5
2205
2206void m68k_trap_if_not_supervisor(m68k_options *opts, m68kinst *inst)
2207{
2208	code_info *code = &opts->gen.code;
2209	//check supervisor bit in SR and trap if not in supervisor mode
2210	bt_irdisp(code, BIT_SUPERVISOR, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2211	code_ptr in_sup_mode = code->cur + 1;
2212	jcc(code, CC_C, code->cur + 2);
2213	
2214	ldi_native(opts, VECTOR_PRIV_VIOLATION, opts->gen.scratch2);
2215	ldi_native(opts, inst->address, opts->gen.scratch1);
2216	jmp(code, opts->trap);
2217	
2218	*in_sup_mode = code->cur - (in_sup_mode + 1);
2219}
2220
2221void translate_m68k_andi_ori_ccr_sr(m68k_options *opts, m68kinst *inst)
2222{
2223	code_info *code = &opts->gen.code;
2224	if (inst->op == M68K_ANDI_SR || inst->op == M68K_ORI_SR) {
2225		m68k_trap_if_not_supervisor(opts, inst);
2226	}
2227	cycles(&opts->gen, 20);
2228	uint32_t flag_mask = 0;
2229	uint32_t base_flag = inst->op == M68K_ANDI_SR || inst->op == M68K_ANDI_CCR ? X0 : X1;
2230	for (int i = 0; i < 5; i++)
2231	{
2232		if ((base_flag == X0) ^ ((inst->src.params.immed & 1 << i) > 0))
2233		{
2234			flag_mask |= base_flag << ((4 - i) * 3);
2235		}
2236	}
2237	update_flags(opts, flag_mask);
2238	if (inst->op == M68K_ANDI_SR || inst->op == M68K_ORI_SR) {
2239		if (inst->op == M68K_ANDI_SR) {
2240			and_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2241		} else {
2242			or_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2243		}
2244		if (inst->op == M68K_ANDI_SR && !(inst->src.params.immed & (1 << (BIT_SUPERVISOR + 8)))) {
2245			//leave supervisor mode
2246			swap_ssp_usp(opts);
2247		}
2248		if ((inst->op == M68K_ANDI_SR && (inst->src.params.immed  & 0x700) != 0x700)
2249		    || (inst->op == M68K_ORI_SR && inst->src.params.immed & 0x8700)) {
2250			if (inst->op == M68K_ANDI_SR) {
2251				//set int pending flag in case we trigger an interrupt as a result of the mask change
2252				mov_irdisp(code, INT_PENDING_SR_CHANGE, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
2253			}
2254			call(code, opts->do_sync);
2255		}
2256	}
2257}
2258
2259void translate_m68k_eori_ccr_sr(m68k_options *opts, m68kinst *inst)
2260{
2261	code_info *code = &opts->gen.code;
2262	if (inst->op == M68K_EORI_SR) {
2263		m68k_trap_if_not_supervisor(opts, inst);
2264	}
2265	cycles(&opts->gen, 20);
2266	if (inst->src.params.immed & 0x1) {
2267		xor_flag(opts, 1, FLAG_C);
2268	}
2269	if (inst->src.params.immed & 0x2) {
2270		xor_flag(opts, 1, FLAG_V);
2271	}
2272	if (inst->src.params.immed & 0x4) {
2273		xor_flag(opts, 1, FLAG_Z);
2274	}
2275	if (inst->src.params.immed & 0x8) {
2276		xor_flag(opts, 1, FLAG_N);
2277	}
2278	if (inst->src.params.immed & 0x10) {
2279		xor_flag(opts, 1, FLAG_X);
2280	}
2281	if (inst->op == M68K_EORI_SR) {
2282		xor_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2283		if (inst->src.params.immed & 0x8700) {
2284			//set int pending flag in case we trigger an interrupt as a result of the mask change
2285			mov_irdisp(code, INT_PENDING_SR_CHANGE, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
2286			call(code, opts->do_sync);
2287		}
2288	}
2289}
2290
2291void set_all_flags(m68k_options *opts, uint8_t flags)
2292{
2293	uint32_t flag_mask = flags & 0x10 ? X1 : X0;
2294	flag_mask |= flags & 0x8 ? N1 : N0;
2295	flag_mask |= flags & 0x4 ? Z1 : Z0;
2296	flag_mask |= flags & 0x2 ? V1 : V0;
2297	flag_mask |= flags & 0x1 ? C1 : C0;
2298	update_flags(opts, flag_mask);
2299}
2300
2301void translate_m68k_move_ccr_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
2302{
2303	code_info *code = &opts->gen.code;
2304	if (inst->op == M68K_MOVE_SR) {
2305		m68k_trap_if_not_supervisor(opts, inst);
2306	}
2307	if (src_op->mode == MODE_IMMED) {
2308		set_all_flags(opts, src_op->disp);
2309		if (inst->op == M68K_MOVE_SR) {
2310			mov_irdisp(code, (src_op->disp >> 8), opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2311			if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) {
2312				//leave supervisor mode
2313				swap_ssp_usp(opts);
2314			}
2315			if (((src_op->disp >> 8) & 7) < 7) {
2316				//set int pending flag in case we trigger an interrupt as a result of the mask change
2317				mov_irdisp(code, INT_PENDING_SR_CHANGE, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
2318			}
2319			call(code, opts->do_sync);
2320		}
2321		cycles(&opts->gen, 12);
2322	} else {
2323		if (src_op->base != opts->gen.scratch1) {
2324			if (src_op->mode == MODE_REG_DIRECT) {
2325				mov_rr(code, src_op->base, opts->gen.scratch1, SZ_W);
2326			} else {
2327				mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_W);
2328			}
2329		}
2330		if (inst->op == M68K_MOVE_SR) {
2331			call(code, opts->set_sr);
2332			call(code, opts->do_sync);
2333		} else {
2334			call(code, opts->set_ccr);
2335		}
2336		cycles(&opts->gen, 12);
2337	}
2338}
2339
2340void translate_m68k_stop(m68k_options *opts, m68kinst *inst)
2341{
2342	m68k_trap_if_not_supervisor(opts, inst);
2343	//manual says 4 cycles, but it has to be at least 8 since it's a 2-word instruction
2344	//possibly even 12 since that's how long MOVE to SR takes
2345	//On further thought prefetch + the fact that this stops the CPU may make
2346	//Motorola's accounting make sense here
2347	code_info *code = &opts->gen.code;
2348	cycles(&opts->gen, BUS*2);
2349	set_all_flags(opts,  inst->src.params.immed);
2350	mov_irdisp(code, (inst->src.params.immed >> 8), opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2351	if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) {
2352		//leave supervisor mode
2353		swap_ssp_usp(opts);
2354	}
2355	code_ptr loop_top = code->cur;
2356		call(code, opts->do_sync);
2357		cmp_rr(code, opts->gen.cycles, opts->gen.limit, SZ_D);
2358		code_ptr normal_cycle_up = code->cur + 1;
2359		jcc(code, CC_A, code->cur + 2);
2360			cycles(&opts->gen, BUS);
2361			code_ptr after_cycle_up = code->cur + 1;
2362			jmp(code, code->cur + 2);
2363		*normal_cycle_up = code->cur - (normal_cycle_up + 1);
2364			mov_rr(code, opts->gen.limit, opts->gen.cycles, SZ_D);
2365		*after_cycle_up = code->cur - (after_cycle_up+1);
2366		cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_cycle), opts->gen.cycles, SZ_D);
2367	jcc(code, CC_C, loop_top);
2368	//set int pending flag so interrupt fires immediately after stop is done
2369	mov_irdisp(code, INT_PENDING_SR_CHANGE, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
2370}
2371
2372void translate_m68k_trapv(m68k_options *opts, m68kinst *inst)
2373{
2374	code_info *code = &opts->gen.code;
2375	cycles(&opts->gen, BUS);
2376	flag_to_carry(opts, FLAG_V);
2377	code_ptr no_trap = code->cur + 1;
2378	jcc(code, CC_NC, no_trap);
2379	ldi_native(opts, VECTOR_TRAPV, opts->gen.scratch2);
2380	ldi_native(opts, inst->address+2, opts->gen.scratch1);
2381	jmp(code, opts->trap);
2382	*no_trap = code->cur - (no_trap + 1);
2383}
2384
2385void translate_m68k_odd(m68k_options *opts, m68kinst *inst)
2386{
2387	code_info *code = &opts->gen.code;
2388	//swap USP and SSP if not already in supervisor mode
2389	check_user_mode_swap_ssp_usp(opts);
2390	//save PC
2391	subi_areg(opts, 4, 7);
2392	areg_to_native(opts, 7, opts->gen.scratch2);
2393	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, last_prefetch_address), opts->gen.scratch1, SZ_D);
2394	call(code, opts->write_32_lowfirst);
2395	//save status register
2396	subi_areg(opts, 2, 7);
2397	call(code, opts->get_sr);
2398	areg_to_native(opts, 7, opts->gen.scratch2);
2399	call(code, opts->write_16);
2400	//save instruction register
2401	subi_areg(opts, 2, 7);
2402	//calculate IR
2403	push_r(code, opts->gen.context_reg);
2404	call(code, opts->gen.save_context);
2405	call_args_abi(code, (code_ptr)m68k_get_ir, 1, opts->gen.context_reg);
2406	mov_rr(code, RAX, opts->gen.scratch1, SZ_W);
2407	pop_r(code, opts->gen.context_reg);
2408	push_r(code, RAX); //save it for use in the "info" word
2409	call(code, opts->gen.load_context);
2410	//write it to the stack
2411	areg_to_native(opts, 7, opts->gen.scratch2);
2412	call(code, opts->write_16);
2413	//save access address
2414	subi_areg(opts, 4, 7);
2415	mov_ir(code, inst->address, opts->gen.scratch1, SZ_D);
2416	areg_to_native(opts, 7, opts->gen.scratch2);
2417	call(code, opts->write_32_lowfirst);
2418	//save FC, I/N and R/W word'
2419	xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_W);
2420	//FC3 is basically the same as the supervisor bit
2421	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, status), opts->gen.scratch1, SZ_B);
2422	shr_ir(code, 3, opts->gen.scratch1, SZ_B);
2423	and_ir(code, 4, opts->gen.scratch1, SZ_B);
2424	//set FC1 to one to indicate instruction fetch, and R/W to indicate read
2425	or_ir(code, 0x12, opts->gen.scratch1, SZ_B);
2426	//set undefined bits to IR value
2427	pop_r(code, opts->gen.scratch2);
2428	and_ir(code, 0xFFE0, opts->gen.scratch2, SZ_W);
2429	or_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_W);
2430	subi_areg(opts, 2, 7);
2431	areg_to_native(opts, 7, opts->gen.scratch2);
2432	call(code, opts->write_16);
2433	//set supervisor bit
2434	or_irdisp(code, 0x20, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2435	//load vector address
2436	mov_ir(code, 4 * VECTOR_ADDRESS_ERROR, opts->gen.scratch1, SZ_D);
2437	call(code, opts->read_32);
2438	call(code, opts->native_addr_and_sync);
2439	cycles(&opts->gen, 18);
2440	jmp_r(code, opts->gen.scratch1);
2441}
2442
2443void translate_m68k_move_from_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
2444{
2445	code_info *code = &opts->gen.code;
2446	cycles(&opts->gen, inst->dst.addr_mode == MODE_REG_DIRECT ? BUS+2 : BUS);
2447	call(code, opts->get_sr);
2448	if (dst_op->mode == MODE_REG_DIRECT) {
2449		mov_rr(code, opts->gen.scratch1, dst_op->base, SZ_W);
2450	} else {
2451		mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, SZ_W);
2452	}
2453	m68k_save_result(inst, opts);
2454}
2455
2456void m68k_out_of_bounds_execution(uint32_t address)
2457{
2458	fatal_error("M68K attempted to execute code at unmapped or I/O address %X\n", address);
2459}
2460
2461void translate_out_of_bounds(m68k_options *opts, uint32_t address)
2462{
2463	code_info *code = &opts->gen.code;
2464	check_cycles_int(&opts->gen, address);
2465	mov_ir(code, address, opts->gen.scratch1, SZ_D);
2466	call_args(code, (code_ptr)m68k_out_of_bounds_execution, 1, opts->gen.scratch1);
2467}
2468
2469void m68k_set_last_prefetch(m68k_options *opts, uint32_t address)
2470{
2471	mov_irdisp(&opts->gen.code, address, opts->gen.context_reg, offsetof(m68k_context, last_prefetch_address), SZ_D);
2472}
2473
2474void nop_fill_or_jmp_next(code_info *code, code_ptr old_end, code_ptr next_inst)
2475{
2476	if (next_inst == old_end && next_inst - code->cur < 2) {
2477		while (code->cur < old_end) {
2478			*(code->cur++) = 0x90; //NOP
2479		}
2480	} else {
2481		jmp(code, next_inst);
2482	}
2483}
2484
2485#define M68K_MAX_INST_SIZE (2*(1+2+2))
2486
2487m68k_context * m68k_handle_code_write(uint32_t address, m68k_context * context)
2488{
2489	m68k_options * options = context->options;
2490	uint32_t inst_start = get_instruction_start(options, address);
2491	while (inst_start && (address - inst_start) < M68K_MAX_INST_SIZE) {
2492		code_ptr dst = get_native_address(context->options, inst_start);
2493		patch_for_retranslate(&options->gen, dst, options->retrans_stub);
2494		inst_start = get_instruction_start(options, inst_start - 2);
2495	}
2496	return context;
2497}
2498
2499void m68k_invalidate_code_range(m68k_context *context, uint32_t start, uint32_t end)
2500{
2501	m68k_options *opts = context->options;
2502	native_map_slot *native_code_map = opts->gen.native_code_map;
2503	memmap_chunk const *mem_chunk = find_map_chunk(start, &opts->gen, 0, NULL);
2504	if (mem_chunk) {
2505		//calculate the lowest alias for this address
2506		start = mem_chunk->start + ((start - mem_chunk->start) & mem_chunk->mask);
2507	}
2508	mem_chunk = find_map_chunk(end, &opts->gen, 0, NULL);
2509	if (mem_chunk) {
2510		//calculate the lowest alias for this address
2511		end = mem_chunk->start + ((end - mem_chunk->start) & mem_chunk->mask);
2512	}
2513	uint32_t start_chunk = start / NATIVE_CHUNK_SIZE, end_chunk = end / NATIVE_CHUNK_SIZE;
2514	for (uint32_t chunk = start_chunk; chunk <= end_chunk; chunk++)
2515	{
2516		if (native_code_map[chunk].base) {
2517			uint32_t start_offset = chunk == start_chunk ? start % NATIVE_CHUNK_SIZE : 0;
2518			uint32_t end_offset = chunk == end_chunk ? end % NATIVE_CHUNK_SIZE : NATIVE_CHUNK_SIZE;
2519			for (uint32_t offset = start_offset; offset < end_offset; offset++)
2520			{
2521				if (native_code_map[chunk].offsets[offset] != INVALID_OFFSET && native_code_map[chunk].offsets[offset] != EXTENSION_WORD) {
2522					patch_for_retranslate(&opts->gen, native_code_map[chunk].base + native_code_map[chunk].offsets[offset], opts->retrans_stub);
2523					/*code_info code;
2524					code.cur = native_code_map[chunk].base + native_code_map[chunk].offsets[offset];
2525					code.last = code.cur + 32;
2526					code.stack_off = 0;
2527					mov_ir(&code, chunk * NATIVE_CHUNK_SIZE + offset, opts->gen.scratch2, SZ_D);
2528					jmp(&code, opts->retrans_stub);*/
2529				}
2530			}
2531		}
2532	}
2533}
2534
2535void m68k_breakpoint_patch(m68k_context *context, uint32_t address, m68k_debug_handler bp_handler, code_ptr native_addr)
2536{
2537	m68k_options * opts = context->options;
2538	code_info native;
2539	native.cur = native_addr ? native_addr : get_native_address(context->options, address);
2540	
2541	if (!native.cur) {
2542		return;
2543	}
2544	
2545	if (*native.cur != opts->prologue_start) {
2546		//instruction has already been patched, probably for retranslation
2547		return;
2548	}
2549	native.last = native.cur + 128;
2550	native.stack_off = 0;
2551	code_ptr start_native = native.cur;
2552	mov_ir(&native, address, opts->gen.scratch1, SZ_D);
2553	
2554	
2555	call(&native, opts->bp_stub);
2556}
2557
2558void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chunks, uint32_t clock_divider)
2559{
2560	memset(opts, 0, sizeof(*opts));
2561	opts->gen.memmap = memmap;
2562	opts->gen.memmap_chunks = num_chunks;
2563	opts->gen.address_size = SZ_D;
2564	opts->gen.address_mask = 0xFFFFFF;
2565	opts->gen.byte_swap = 1;
2566	opts->gen.max_address = 0x1000000;
2567	opts->gen.bus_cycles = BUS;
2568	opts->gen.clock_divider = clock_divider;
2569	opts->gen.mem_ptr_off = offsetof(m68k_context, mem_pointers);
2570	opts->gen.ram_flags_off = offsetof(m68k_context, ram_code_flags);
2571	opts->gen.ram_flags_shift = 11;
2572	for (int i = 0; i < 8; i++)
2573	{
2574		opts->dregs[i] = opts->aregs[i] = -1;
2575	}
2576#ifdef X86_64
2577	opts->dregs[0] = R10;
2578	opts->dregs[1] = R11;
2579	opts->dregs[2] = R12;
2580	opts->dregs[3] = R8;
2581	opts->aregs[0] = R13;
2582	opts->aregs[1] = R14;
2583	opts->aregs[2] = R9;
2584	opts->aregs[7] = R15;
2585
2586	opts->flag_regs[0] = -1;
2587	opts->flag_regs[1] = RBX;
2588	opts->flag_regs[2] = RDX;
2589	opts->flag_regs[3] = BH;
2590	opts->flag_regs[4] = DH;
2591
2592	opts->gen.scratch2 = RDI;
2593#else
2594	opts->dregs[0] = RDX;
2595	opts->aregs[7] = RDI;
2596
2597	for (int i = 0; i < 5; i++)
2598	{
2599		opts->flag_regs[i] = -1;
2600	}
2601	opts->gen.scratch2 = RBX;
2602#endif
2603	opts->gen.context_reg = RSI;
2604	opts->gen.cycles = RAX;
2605	opts->gen.limit = RBP;
2606	opts->gen.scratch1 = RCX;
2607	opts->gen.align_error_mask = 1;
2608
2609
2610	opts->gen.native_code_map = malloc(sizeof(native_map_slot) * NATIVE_MAP_CHUNKS);
2611	memset(opts->gen.native_code_map, 0, sizeof(native_map_slot) * NATIVE_MAP_CHUNKS);
2612	opts->gen.deferred = NULL;
2613
2614	uint32_t inst_size_size = sizeof(uint8_t *) * ram_size(&opts->gen) / 1024;
2615	opts->gen.ram_inst_sizes = malloc(inst_size_size);
2616	memset(opts->gen.ram_inst_sizes, 0, inst_size_size);
2617
2618	code_info *code = &opts->gen.code;
2619	init_code_info(code);
2620
2621	opts->gen.save_context = code->cur;
2622	for (int i = 0; i < 5; i++)
2623		if (opts->flag_regs[i] >= 0) {
2624			mov_rrdisp(code, opts->flag_regs[i], opts->gen.context_reg, offsetof(m68k_context, flags) + i, SZ_B);
2625		}
2626	for (int i = 0; i < 8; i++)
2627	{
2628		if (opts->dregs[i] >= 0) {
2629			mov_rrdisp(code, opts->dregs[i], opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t) * i, SZ_D);
2630		}
2631		if (opts->aregs[i] >= 0) {
2632			mov_rrdisp(code, opts->aregs[i], opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * i, SZ_D);
2633		}
2634	}
2635	mov_rrdisp(code, opts->gen.cycles, opts->gen.context_reg, offsetof(m68k_context, current_cycle), SZ_D);
2636	retn(code);
2637
2638	opts->gen.load_context = code->cur;
2639	for (int i = 0; i < 5; i++)
2640	{
2641		if (opts->flag_regs[i] >= 0) {
2642			mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, flags) + i, opts->flag_regs[i], SZ_B);
2643		}
2644	}
2645	for (int i = 0; i < 8; i++)
2646	{
2647		if (opts->dregs[i] >= 0) {
2648			mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t) * i, opts->dregs[i], SZ_D);
2649		}
2650		if (opts->aregs[i] >= 0) {
2651			mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * i, opts->aregs[i], SZ_D);
2652		}
2653	}
2654	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, current_cycle), opts->gen.cycles, SZ_D);
2655	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, target_cycle), opts->gen.limit, SZ_D);
2656	retn(code);
2657
2658	opts->start_context = (start_fun)code->cur;
2659	save_callee_save_regs(code);
2660#ifdef X86_64
2661	if (opts->gen.scratch2 != RDI) {
2662		mov_rr(code, RDI, opts->gen.scratch2, SZ_PTR);
2663	}
2664#else
2665	mov_rdispr(code, RSP, 20, opts->gen.scratch2, SZ_D);
2666	mov_rdispr(code, RSP, 24, opts->gen.context_reg, SZ_D);
2667#endif
2668	call(code, opts->gen.load_context);
2669	call_r(code, opts->gen.scratch2);
2670	call(code, opts->gen.save_context);
2671	restore_callee_save_regs(code);
2672	retn(code);
2673
2674	opts->native_addr = code->cur;
2675	call(code, opts->gen.save_context);
2676	push_r(code, opts->gen.context_reg);
2677	call_args(code, (code_ptr)get_native_address_trans, 2, opts->gen.context_reg, opts->gen.scratch1);
2678	mov_rr(code, RAX, opts->gen.scratch1, SZ_PTR); //move result to scratch reg
2679	pop_r(code, opts->gen.context_reg);
2680	call(code, opts->gen.load_context);
2681	retn(code);
2682
2683	opts->native_addr_and_sync = code->cur;
2684	call(code, opts->gen.save_context);
2685	push_r(code, opts->gen.scratch1);
2686
2687	xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_D);
2688	call_args_abi(code, (code_ptr)sync_components, 2, opts->gen.context_reg, opts->gen.scratch1);
2689	pop_r(code, RSI); //restore saved address from opts->gen.scratch1
2690	push_r(code, RAX); //save context pointer for later
2691	call_args(code, (code_ptr)get_native_address_trans, 2, RAX, RSI);
2692	mov_rr(code, RAX, opts->gen.scratch1, SZ_PTR); //move result to scratch reg
2693	pop_r(code, opts->gen.context_reg);
2694	call(code, opts->gen.load_context);
2695	retn(code);
2696
2697	opts->gen.handle_cycle_limit = code->cur;
2698	cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, sync_cycle), opts->gen.cycles, SZ_D);
2699	code_ptr skip_sync = code->cur + 1;
2700	jcc(code, CC_C, code->cur + 2);
2701	opts->do_sync = code->cur;
2702	push_r(code, opts->gen.scratch1);
2703	push_r(code, opts->gen.scratch2);
2704	call(code, opts->gen.save_context);
2705	xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_D);
2706	call_args_abi(code, (code_ptr)sync_components, 2, opts->gen.context_reg, opts->gen.scratch1);
2707	mov_rr(code, RAX, opts->gen.context_reg, SZ_PTR);
2708	call(code, opts->gen.load_context);
2709	pop_r(code, opts->gen.scratch2);
2710	pop_r(code, opts->gen.scratch1);
2711	*skip_sync = code->cur - (skip_sync+1);
2712	retn(code);
2713
2714	opts->gen.handle_code_write = (code_ptr)m68k_handle_code_write;
2715	
2716	check_alloc_code(code, 256);
2717	opts->gen.handle_align_error_write = code->cur;
2718	code->cur += 256;
2719	check_alloc_code(code, 256);
2720	opts->gen.handle_align_error_read = code->cur;
2721	code->cur += 256;
2722	
2723	opts->read_16 = gen_mem_fun(&opts->gen, memmap, num_chunks, READ_16, NULL);
2724	opts->read_8 = gen_mem_fun(&opts->gen, memmap, num_chunks, READ_8, NULL);
2725	opts->write_16 = gen_mem_fun(&opts->gen, memmap, num_chunks, WRITE_16, NULL);
2726	opts->write_8 = gen_mem_fun(&opts->gen, memmap, num_chunks, WRITE_8, NULL);
2727
2728	opts->read_32 = code->cur;
2729	push_r(code, opts->gen.scratch1);
2730	call(code, opts->read_16);
2731	mov_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_W);
2732	pop_r(code, opts->gen.scratch1);
2733	push_r(code, opts->gen.scratch2);
2734	add_ir(code, 2, opts->gen.scratch1, SZ_D);
2735	call(code, opts->read_16);
2736	pop_r(code, opts->gen.scratch2);
2737	movzx_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_W, SZ_D);
2738	shl_ir(code, 16, opts->gen.scratch2, SZ_D);
2739	or_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D);
2740	retn(code);
2741
2742	opts->write_32_lowfirst = code->cur;
2743	push_r(code, opts->gen.scratch2);
2744	push_r(code, opts->gen.scratch1);
2745	add_ir(code, 2, opts->gen.scratch2, SZ_D);
2746	call(code, opts->write_16);
2747	pop_r(code, opts->gen.scratch1);
2748	pop_r(code, opts->gen.scratch2);
2749	shr_ir(code, 16, opts->gen.scratch1, SZ_D);
2750	jmp(code, opts->write_16);
2751
2752	opts->write_32_highfirst = code->cur;
2753	push_r(code, opts->gen.scratch1);
2754	push_r(code, opts->gen.scratch2);
2755	shr_ir(code, 16, opts->gen.scratch1, SZ_D);
2756	call(code, opts->write_16);
2757	pop_r(code, opts->gen.scratch2);
2758	pop_r(code, opts->gen.scratch1);
2759	add_ir(code, 2, opts->gen.scratch2, SZ_D);
2760	jmp(code, opts->write_16);
2761
2762	opts->get_sr = code->cur;
2763	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, status), opts->gen.scratch1, SZ_B);
2764	shl_ir(code, 8, opts->gen.scratch1, SZ_W);
2765	if (opts->flag_regs[FLAG_X] >= 0) {
2766		mov_rr(code, opts->flag_regs[FLAG_X], opts->gen.scratch1, SZ_B);
2767	} else {
2768		int8_t offset = offsetof(m68k_context, flags);
2769		if (offset) {
2770			mov_rdispr(code, opts->gen.context_reg, offset, opts->gen.scratch1, SZ_B);
2771		} else {
2772			mov_rindr(code, opts->gen.context_reg, opts->gen.scratch1, SZ_B);
2773		}
2774	}
2775	for (int flag = FLAG_N; flag <= FLAG_C; flag++)
2776	{
2777		shl_ir(code, 1, opts->gen.scratch1, SZ_B);
2778		if (opts->flag_regs[flag] >= 0) {
2779			or_rr(code, opts->flag_regs[flag], opts->gen.scratch1, SZ_B);
2780		} else {
2781			or_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, flags) + flag, opts->gen.scratch1, SZ_B);
2782		}
2783	}
2784	retn(code);
2785
2786	opts->set_sr = code->cur;
2787	for (int flag = FLAG_C; flag >= FLAG_X; flag--)
2788	{
2789		rcr_ir(code, 1, opts->gen.scratch1, SZ_B);
2790		if (opts->flag_regs[flag] >= 0) {
2791			setcc_r(code, CC_C, opts->flag_regs[flag]);
2792		} else {
2793			int8_t offset = offsetof(m68k_context, flags) + flag;
2794			if (offset) {
2795				setcc_rdisp(code, CC_C, opts->gen.context_reg, offset);
2796			} else {
2797				setcc_rind(code, CC_C, opts->gen.context_reg);
2798			}
2799		}
2800	}
2801	shr_ir(code, 8, opts->gen.scratch1, SZ_W);
2802	mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2803	//set int pending flag in case we trigger an interrupt as a result of the mask change
2804	mov_irdisp(code, INT_PENDING_SR_CHANGE, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
2805	retn(code);
2806
2807	opts->set_ccr = code->cur;
2808	for (int flag = FLAG_C; flag >= FLAG_X; flag--)
2809	{
2810		rcr_ir(code, 1, opts->gen.scratch1, SZ_B);
2811		if (opts->flag_regs[flag] >= 0) {
2812			setcc_r(code, CC_C, opts->flag_regs[flag]);
2813		} else {
2814			int8_t offset = offsetof(m68k_context, flags) + flag;
2815			if (offset) {
2816				setcc_rdisp(code, CC_C, opts->gen.context_reg, offset);
2817			} else {
2818				setcc_rind(code, CC_C, opts->gen.context_reg);
2819			}
2820		}
2821	}
2822	retn(code);
2823	
2824	code_info tmp_code = *code;
2825	code->cur = opts->gen.handle_align_error_write;
2826	code->last = code->cur + 256;
2827	//unwind the stack one functinon call
2828	add_ir(code, 16, RSP, SZ_PTR);
2829	//save address that triggered error so we can write it to the 68K stack at the appropriate place
2830	push_r(code, opts->gen.scratch2);
2831	//swap USP and SSP if not already in supervisor mode
2832	check_user_mode_swap_ssp_usp(opts);
2833	//save PC
2834	subi_areg(opts, 4, 7);
2835	areg_to_native(opts, 7, opts->gen.scratch2);
2836	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, last_prefetch_address), opts->gen.scratch1, SZ_D);
2837	call(code, opts->write_32_lowfirst);
2838	//save status register
2839	subi_areg(opts, 2, 7);
2840	call(code, opts->get_sr);
2841	areg_to_native(opts, 7, opts->gen.scratch2);
2842	call(code, opts->write_16);
2843	//save instruction register
2844	subi_areg(opts, 2, 7);
2845	//calculate IR
2846	push_r(code, opts->gen.context_reg);
2847	call(code, opts->gen.save_context);
2848	call_args_abi(code, (code_ptr)m68k_get_ir, 1, opts->gen.context_reg);
2849	mov_rr(code, RAX, opts->gen.scratch1, SZ_W);
2850	pop_r(code, opts->gen.context_reg);
2851	pop_r(code, opts->gen.scratch2); //access address
2852	push_r(code, RAX); //save it for use in the "info" word
2853	push_r(code, opts->gen.scratch2); //access address
2854	call(code, opts->gen.load_context);
2855	//write it to the stack
2856	areg_to_native(opts, 7, opts->gen.scratch2);
2857	call(code, opts->write_16);
2858	//save access address
2859	subi_areg(opts, 4, 7);
2860	pop_r(code, opts->gen.scratch1);
2861	areg_to_native(opts, 7, opts->gen.scratch2);
2862	call(code, opts->write_32_lowfirst);
2863	//save FC, I/N and R/W word'
2864	xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_W);
2865	//FC3 is basically the same as the supervisor bit
2866	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, status), opts->gen.scratch1, SZ_B);
2867	shr_ir(code, 3, opts->gen.scratch1, SZ_B);
2868	and_ir(code, 4, opts->gen.scratch1, SZ_B);
2869	//set FC0 to one to indicate data access
2870	or_ir(code, 1, opts->gen.scratch1, SZ_B);
2871	//set undefined bits to IR value
2872	pop_r(code, opts->gen.scratch2);
2873	and_ir(code, 0xFFE0, opts->gen.scratch2, SZ_W);
2874	or_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_W);
2875	subi_areg(opts, 2, 7);
2876	areg_to_native(opts, 7, opts->gen.scratch2);
2877	call(code, opts->write_16);
2878	//set supervisor bit
2879	or_irdisp(code, 0x20, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2880	//load vector address
2881	mov_ir(code, 4 * VECTOR_ADDRESS_ERROR, opts->gen.scratch1, SZ_D);
2882	call(code, opts->read_32);
2883	call(code, opts->native_addr_and_sync);
2884	cycles(&opts->gen, 18);
2885	jmp_r(code, opts->gen.scratch1);
2886	
2887	code->cur = opts->gen.handle_align_error_read;
2888	code->last = code->cur + 256;
2889	//unwind the stack one functinon call
2890	add_ir(code, 16, RSP, SZ_PTR);
2891	//save address that triggered error so we can write it to the 68K stack at the appropriate place
2892	push_r(code, opts->gen.scratch1);
2893	//swap USP and SSP if not already in supervisor mode
2894	check_user_mode_swap_ssp_usp(opts);
2895	//save PC
2896	subi_areg(opts, 4, 7);
2897	areg_to_native(opts, 7, opts->gen.scratch2);
2898	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, last_prefetch_address), opts->gen.scratch1, SZ_D);
2899	call(code, opts->write_32_lowfirst);
2900	//save status register
2901	subi_areg(opts, 2, 7);
2902	call(code, opts->get_sr);
2903	areg_to_native(opts, 7, opts->gen.scratch2);
2904	call(code, opts->write_16);
2905	//save instruction register
2906	subi_areg(opts, 2, 7);
2907	//calculate IR
2908	push_r(code, opts->gen.context_reg);
2909	call(code, opts->gen.save_context);
2910	call_args_abi(code, (code_ptr)m68k_get_ir, 1, opts->gen.context_reg);
2911	mov_rr(code, RAX, opts->gen.scratch1, SZ_W);
2912	pop_r(code, opts->gen.context_reg);
2913	pop_r(code, opts->gen.scratch2); //access address
2914	push_r(code, RAX); //save it for use in the "info" word
2915	push_r(code, opts->gen.scratch2); //access address
2916	call(code, opts->gen.load_context);
2917	//write it to the stack
2918	areg_to_native(opts, 7, opts->gen.scratch2);
2919	call(code, opts->write_16);
2920	//save access address
2921	subi_areg(opts, 4, 7);
2922	pop_r(code, opts->gen.scratch1);
2923	areg_to_native(opts, 7, opts->gen.scratch2);
2924	call(code, opts->write_32_lowfirst);
2925	//save FC, I/N and R/W word'
2926	xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_W);
2927	//FC3 is basically the same as the supervisor bit
2928	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, status), opts->gen.scratch1, SZ_B);
2929	shr_ir(code, 3, opts->gen.scratch1, SZ_B);
2930	and_ir(code, 4, opts->gen.scratch1, SZ_B);
2931	//set FC0 to one to indicate data access, and R/W to indicate read
2932	or_ir(code, 0x11, opts->gen.scratch1, SZ_B);
2933	//set undefined bits to IR value
2934	pop_r(code, opts->gen.scratch2);
2935	and_ir(code, 0xFFE0, opts->gen.scratch2, SZ_W);
2936	or_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_W);
2937	subi_areg(opts, 2, 7);
2938	areg_to_native(opts, 7, opts->gen.scratch2);
2939	call(code, opts->write_16);
2940	//set supervisor bit
2941	or_irdisp(code, 0x20, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2942	//load vector address
2943	mov_ir(code, 4 * VECTOR_ADDRESS_ERROR, opts->gen.scratch1, SZ_D);
2944	call(code, opts->read_32);
2945	call(code, opts->native_addr_and_sync);
2946	cycles(&opts->gen, 18);
2947	jmp_r(code, opts->gen.scratch1);
2948	
2949	*code = tmp_code;
2950
2951	opts->gen.handle_cycle_limit_int = code->cur;
2952	//calculate stack adjust size
2953	add_ir(code, 16-sizeof(void*), RSP, SZ_PTR);
2954	uint32_t adjust_size = code->cur - opts->gen.handle_cycle_limit_int;
2955	code->cur = opts->gen.handle_cycle_limit_int;
2956	//handle trace mode
2957	cmp_irdisp(code, 0, opts->gen.context_reg, offsetof(m68k_context, trace_pending), SZ_B);
2958	code_ptr do_trace = code->cur + 1;
2959	jcc(code, CC_NZ, do_trace);
2960	bt_irdisp(code, 7, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2961	code_ptr no_trace = code->cur + 1;
2962	jcc(code, CC_NC, no_trace);
2963	mov_irdisp(code, 1, opts->gen.context_reg, offsetof(m68k_context, trace_pending), SZ_B);
2964	*no_trace = code->cur - (no_trace + 1);
2965	//handle interrupts
2966	cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_cycle), opts->gen.cycles, SZ_D);
2967	code_ptr do_int = code->cur + 2; 
2968	jcc(code, CC_NC, do_int+512);//force 32-bit displacement
2969	//handle component synchronization
2970	cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, sync_cycle), opts->gen.cycles, SZ_D);
2971	skip_sync = code->cur + 1;
2972	jcc(code, CC_C, code->cur + 2);
2973	call(code, opts->gen.save_context);
2974	call_args_abi(code, (code_ptr)sync_components, 2, opts->gen.context_reg, opts->gen.scratch1);
2975	mov_rr(code, RAX, opts->gen.context_reg, SZ_PTR);
2976	jmp(code, opts->gen.load_context);
2977	*skip_sync = code->cur - (skip_sync+1);
2978	cmp_irdisp(code, 0, opts->gen.context_reg, offsetof(m68k_context, should_return), SZ_B);
2979	code_ptr do_ret = code->cur + 1;
2980	jcc(code, CC_NZ, do_ret);
2981	retn(code);
2982	*do_ret = code->cur - (do_ret+1);
2983	uint32_t tmp_stack_off = code->stack_off;
2984	//fetch return address and adjust RSP
2985	pop_r(code, opts->gen.scratch1);
2986	add_ir(code, 16-sizeof(void *), RSP, SZ_PTR);
2987	add_ir(code, adjust_size, opts->gen.scratch1, SZ_PTR);
2988	//save return address for restoring later
2989	mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, resume_pc), SZ_PTR);
2990	retn(code);
2991	code->stack_off = tmp_stack_off;
2992	*do_trace = code->cur - (do_trace + 1);
2993	//clear out trace pending flag
2994	mov_irdisp(code, 0, opts->gen.context_reg, offsetof(m68k_context, trace_pending), SZ_B);
2995	//save PC as stored in scratch1 for later
2996	push_r(code, opts->gen.scratch1);
2997	//swap USP and SSP if not already in supervisor mode
2998	check_user_mode_swap_ssp_usp(opts);
2999	//save status register
3000	subi_areg(opts, 6, 7);
3001	call(code, opts->get_sr);
3002	cycles(&opts->gen, 6);
3003	//save SR to stack
3004	areg_to_native(opts, 7, opts->gen.scratch2);
3005	call(code, opts->write_16);
3006	//update the status register
3007	and_irdisp(code, 0x7F, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
3008	or_irdisp(code, 0x20, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
3009	//save PC
3010	areg_to_native(opts, 7, opts->gen.scratch2);
3011	add_ir(code, 2, opts->gen.scratch2, SZ_D);
3012	pop_r(code, opts->gen.scratch1);
3013	call(code, opts->write_32_lowfirst);
3014	//read vector
3015	mov_ir(code, 0x24, opts->gen.scratch1, SZ_D);
3016	call(code, opts->read_32);
3017	call(code, opts->native_addr_and_sync);
3018	//2 prefetch bus operations + 2 idle bus cycles
3019	cycles(&opts->gen, 10);
3020	//discard function return address
3021	pop_r(code, opts->gen.scratch2);
3022	add_ir(code, 16-sizeof(void *), RSP, SZ_PTR);
3023	jmp_r(code, opts->gen.scratch1);
3024	
3025	code->stack_off = tmp_stack_off;
3026	
3027	*((uint32_t *)do_int) = code->cur - (do_int+4);
3028	//implement 1 instruction latency
3029	cmp_irdisp(code, INT_PENDING_NONE, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
3030	do_int = code->cur + 1;
3031	jcc(code, CC_NZ, do_int);
3032	//store current interrupt number so it doesn't change before we start processing the vector
3033	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_num), opts->gen.scratch1, SZ_B);
3034	mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
3035	retn(code);
3036	*do_int = code->cur - (do_int + 1);
3037	//Check if int_pending has an actual interrupt priority in it
3038	cmp_irdisp(code, INT_PENDING_SR_CHANGE, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
3039	code_ptr already_int_num = code->cur + 1;
3040	jcc(code, CC_NZ, already_int_num);
3041	
3042	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_num), opts->gen.scratch2, SZ_B);
3043	mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
3044	
3045	*already_int_num = code->cur - (already_int_num + 1);
3046	//save PC as stored in scratch1 for later
3047	push_r(code, opts->gen.scratch1);
3048	//set target cycle to sync cycle
3049	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, sync_cycle), opts->gen.limit, SZ_D);
3050	//swap USP and SSP if not already in supervisor mode
3051	check_user_mode_swap_ssp_usp(opts);
3052	//save status register
3053	subi_areg(opts, 6, 7);
3054	call(code, opts->get_sr);
3055	//6 cycles before SR gets saved
3056	cycles(&opts->gen, 6);
3057	//save SR to stack
3058	areg_to_native(opts, 7, opts->gen.scratch2);
3059	call(code, opts->write_16);
3060	//interrupt ack cycle
3061	//the Genesis responds to these exclusively with !VPA which means its a slow
3062	//6800 operation. documentation says these can take between 10 and 19 cycles.
3063	//actual results measurements seem to suggest it's actually between 9 and 18
3064	//WARNING: this code might break with register assignment changes
3065	//save RDX
3066	push_r(code, RDX);
3067	//save cycle count
3068	mov_rr(code, RAX, opts->gen.scratch1, SZ_D);
3069	//clear top doubleword of dividend
3070	xor_rr(code, RDX, RDX, SZ_D);
3071	//set divisor to clock divider
3072	mov_ir(code, opts->gen.clock_divider, opts->gen.scratch2, SZ_D);
3073	div_r(code, opts->gen.scratch2, SZ_D);
3074	//discard remainder
3075	xor_rr(code, RDX, RDX, SZ_D);
3076	//set divisor to 10, the period of E
3077	mov_ir(code, 10, opts->gen.scratch2, SZ_D);
3078	div_r(code, opts->gen.scratch2, SZ_D);
3079	//delay will be (9 + 4 + the remainder) * clock_divider
3080	//the extra 4 is to cover the idle bus period after the ack
3081	add_ir(code, 9 + 4, RDX, SZ_D);
3082	mov_ir(code, opts->gen.clock_divider, RAX, SZ_D);
3083	mul_r(code, RDX, SZ_D);
3084	pop_r(code, RDX);
3085	//add saved cycle count to result
3086	add_rr(code, opts->gen.scratch1, RAX, SZ_D);
3087
3088	//update status register
3089	and_irdisp(code, 0x78, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
3090	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_num), opts->gen.scratch1, SZ_B);
3091	//clear trace pending flag
3092	mov_irdisp(code, 0, opts->gen.context_reg, offsetof(m68k_context, trace_pending), SZ_B);
3093	//need to separate int priority and interrupt vector, but for now mask out large interrupt numbers
3094	and_ir(code, 0x7, opts->gen.scratch1, SZ_B);
3095	or_ir(code, 0x20, opts->gen.scratch1, SZ_B);
3096	or_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
3097
3098	pop_r(code, opts->gen.scratch1);
3099
3100	//save PC
3101	areg_to_native(opts, 7, opts->gen.scratch2);
3102	add_ir(code, 2, opts->gen.scratch2, SZ_D);
3103	call(code, opts->write_32_lowfirst);
3104
3105	//grab saved interrupt number
3106	xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_D);
3107	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_pending), opts->gen.scratch1, SZ_B);
3108	//ack the interrupt (happens earlier on hardware, but shouldn't be an observable difference)
3109	mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, int_ack), SZ_W);
3110	//calculate the vector address
3111	shl_ir(code, 2, opts->gen.scratch1, SZ_D);
3112	add_ir(code, 0x60, opts->gen.scratch1, SZ_D);
3113	//clear out pending flag
3114	mov_irdisp(code, INT_PENDING_NONE, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
3115	//read vector
3116	call(code, opts->read_32);
3117	call(code, opts->native_addr_and_sync);
3118	//2 prefetch bus operations + 2 idle bus cycles
3119	cycles(&opts->gen, 10);
3120	tmp_stack_off = code->stack_off;
3121	//discard function return address
3122	pop_r(code, opts->gen.scratch2);
3123	add_ir(code, 16-sizeof(void *), RSP, SZ_PTR);
3124	jmp_r(code, opts->gen.scratch1);
3125	code->stack_off = tmp_stack_off;
3126	
3127	opts->handle_int_latch = code->cur;
3128	cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_cycle), opts->gen.cycles, SZ_D);
3129	code_ptr do_latch = code->cur + 1; 
3130	jcc(code, CC_NC, do_latch);
3131	retn(code);
3132	*do_latch = code->cur - (do_latch + 1);
3133	cmp_irdisp(code, INT_PENDING_NONE, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
3134	do_latch = code->cur + 1;
3135	jcc(code, CC_Z, do_latch);
3136	retn(code);
3137	*do_latch = code->cur - (do_latch + 1);
3138	//store current interrupt number so it doesn't change before we start processing the vector
3139	push_r(code, opts->gen.scratch1);
3140	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_num), opts->gen.scratch1, SZ_B);
3141	mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
3142	pop_r(code, opts->gen.scratch1);
3143	retn(code);
3144
3145	opts->trap = code->cur;
3146	push_r(code, opts->gen.scratch2);
3147	//swap USP and SSP if not already in supervisor mode
3148	check_user_mode_swap_ssp_usp(opts);
3149	//save PC
3150	subi_areg(opts, 4, 7);
3151	areg_to_native(opts, 7, opts->gen.scratch2);
3152	call(code, opts->write_32_lowfirst);
3153	//save status register
3154	subi_areg(opts, 2, 7);
3155	call(code, opts->get_sr);
3156	areg_to_native(opts, 7, opts->gen.scratch2);
3157	call(code, opts->write_16);
3158	//set supervisor bit
3159	or_irdisp(code, 0x20, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
3160	//clear trace bit
3161	and_irdisp(code, 0x7F, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
3162	mov_irdisp(code, 0, opts->gen.context_reg, offsetof(m68k_context, trace_pending), SZ_B);
3163	//calculate vector address
3164	pop_r(code, opts->gen.scratch1);
3165	shl_ir(code, 2, opts->gen.scratch1, SZ_D);
3166	call(code, opts->read_32);
3167	call(code, opts->native_addr_and_sync);
3168	cycles(&opts->gen, 18);
3169	jmp_r(code, opts->gen.scratch1);
3170	
3171	opts->retrans_stub = code->cur;
3172	call(code, opts->gen.save_context);
3173	push_r(code, opts->gen.context_reg);
3174	call_args(code,(code_ptr)m68k_retranslate_inst, 2, opts->gen.scratch1, opts->gen.context_reg);
3175	pop_r(code, opts->gen.context_reg);
3176	mov_rr(code, RAX, opts->gen.scratch1, SZ_PTR);
3177	call(code, opts->gen.load_context);
3178	jmp_r(code, opts->gen.scratch1);
3179	
3180	
3181	check_code_prologue(code);
3182	opts->bp_stub = code->cur;
3183
3184	tmp_stack_off = code->stack_off;
3185	//Calculate length of prologue
3186	check_cycles_int(&opts->gen, 0x1234);
3187	int check_int_size = code->cur-opts->bp_stub;
3188	code->cur = opts->bp_stub;
3189	code->stack_off = tmp_stack_off;
3190	opts->prologue_start = *opts->bp_stub;
3191	//Calculate length of patch
3192	mov_ir(code, 0x1234, opts->gen.scratch1, SZ_D);
3193	call(code, opts->bp_stub);
3194	int patch_size = code->cur - opts->bp_stub;
3195	code->cur = opts->bp_stub;
3196	code->stack_off = tmp_stack_off;
3197
3198	//Save context and call breakpoint handler
3199	call(code, opts->gen.save_context);
3200	push_r(code, opts->gen.scratch1);
3201	call_args_abi(code, (code_ptr)m68k_bp_dispatcher, 2, opts->gen.context_reg, opts->gen.scratch1);
3202	mov_rr(code, RAX, opts->gen.context_reg, SZ_PTR);
3203	//Restore context
3204	call(code, opts->gen.load_context);
3205	pop_r(code, opts->gen.scratch1);
3206	//do prologue stuff
3207	cmp_rr(code, opts->gen.cycles, opts->gen.limit, SZ_D);
3208	code_ptr jmp_off = code->cur + 1;
3209	jcc(code, CC_NC, code->cur + 7);
3210	call(code, opts->gen.handle_cycle_limit_int);
3211	*jmp_off = code->cur - (jmp_off+1);
3212	//jump back to body of translated instruction
3213	pop_r(code, opts->gen.scratch1);
3214	add_ir(code, check_int_size - patch_size, opts->gen.scratch1, SZ_PTR);
3215	jmp_r(code, opts->gen.scratch1);
3216	code->stack_off = tmp_stack_off;
3217	
3218	retranslate_calc(&opts->gen);
3219}