view m68k.cpu @ 2493:b62336ceb626 default tip

Kinda hacky fix to make sure Nuklear has the right GL context
author Michael Pavone <pavone@retrodev.com>
date Wed, 17 Apr 2024 22:18:45 -0700
parents f0645adddf0d
children
line wrap: on
line source

info
	prefix m68k_
	opcode_size 16
	body m68k_run_op
	header m68k.h
	interrupt m68k_interrupt
	include m68k_util.c
	sync_cycle m68k_sync_cycle
	
declare
	typedef m68k_context *(*sync_fun)(m68k_context * context, uint32_t address);
	typedef m68k_context *(*int_ack_fun)(m68k_context * context);
	typedef m68k_context *(*m68k_reset_handler)(m68k_context *context);
	void init_m68k_opts(m68k_options *opts, memmap_chunk * memmap, uint32_t num_chunks, uint32_t clock_divider, sync_fun sync_components, int_ack_fun int_ack);
	m68k_context *init_68k_context(m68k_options * opts, m68k_reset_handler reset_handler);
	void m68k_reset(m68k_context *context);
	void m68k_print_regs(m68k_context *context);

regs
	dregs 32 d0 d1 d2 d3 d4 d5 d6 d7
	aregs 32 a0 a1 a2 a3 a4 a5 a6 a7
	pc 32
	other_sp 32
	scratch1 32
	scratch2 32
	int_cycle 32
	prefetch 16
	int_priority 8
	int_num 8
	int_pending 8
	int_pending_num 8
	int_ack 8
	status 8
	ccr 8
	xflag 8
	nflag 8
	zflag 8
	vflag 8
	cflag 8
	reset_handler ptrvoid
	mem_pointers ptrvoid 8
	
flags
	register ccr
	X 4 carry xflag
	N 3 sign nflag
	Z 2 zero zflag
	V 1 overflow vflag
	C 0 carry cflag

m68k_prefetch
	if dynarec
	
	ccall m68k_read16_noinc context pc
	mov result prefetch
	
	end
	
	if interp
	
	mov pc scratch1
	ocall read_16
	mov scratch1 prefetch
	
	end
	
	add 2 pc pc
	
check_user_mode_swap_ssp_usp
	local tmp 8
	and 0x20 status tmp
	if tmp
	else
		xchg other_sp a7
	end
	
m68k_get_sr
	lsl status 8 scratch1
	or ccr scratch1 scratch1
	
m68k_write32_lowfirst
	arg value 32
	add 2 scratch2 scratch2
	mov value scratch1
	ocall write_16
	
	sub 2 scratch2 scratch2
	lsr value 16 scratch1
	ocall write_16

m68k_write32
	arg value 32
	local tmp 32
	mov value tmp
	lsr value 16 scratch1
	ocall write_16
	
	add 2 scratch2 scratch2
	mov tmp scratch1
	ocall write_16
	
m68k_read32
	local tmp 32
	add 2 scratch1 tmp
	ocall read_16
	xchg scratch1 tmp
	ocall read_16
	lsl tmp 16 tmp
	or tmp scratch1 scratch1
	
m68k_interrupt
	cmp int_cycle cycles
	if >=U
	
	#INT_PENDING_NONE
	cmp 255 int_pending
	if =
	
	mov int_priority int_pending
	mov int_num int_pending_num
	
	else
	
	#INT_PENDING_SR_CHANGE
	cmp 254 int_pending
	if =
	
	mov int_priority int_pending
	mov int_num int_pending_num
	
	else
	
	check_user_mode_swap_ssp_usp
	
	cycles 6
	#save status reg
	sub 6 a7 a7
	m68k_get_sr
	mov a7 scratch2
	ocall write_16
	
	#update status register
	and 0x78 status status
	or int_priority status status
	or 0x20 status status
	
	#Interrupt ack cycle
	mov int_pending int_ack
	if int_pending_num
	cycles 4
	else
	#TODO: do the whole E clock variable latency nonsense
	cycles 13
	add 24 int_pending int_pending_num
	end
	
	#save pc
	add 2 a7 scratch2
	m68k_write32_lowfirst pc
	
	lsl int_pending_num 2 scratch1
	m68k_read32
	mov scratch1 pc
	update_sync
	end
	
m68k_run_op
	dispatch prefetch

m68k_mem_src
	arg address 32
	arg size 16
	arg isdst 8
	mov address scratch1
	if isdst
	mov address scratch2
	meta ismem 1
	end
	switch size
	
	case 0
	ocall read_8
	
	case 1
	ocall read_16
	
	case 2
	m68k_read32
	
	end
	meta op scratch1

m68k_write_size
	arg size 16
	arg lowfirst 8
	switch size
	case 0
	ocall write_8
	
	case 1
	ocall write_16
	
	case 2
	if lowfirst
	m68k_write32_lowfirst scratch1
	else
	m68k_write32 scratch1
	end
	end
	
m68k_index_word
	m68k_prefetch
	local disp 32
	and prefetch 255 disp
	sext 16 disp disp
	sext 32 disp disp
	local index 16
	lsr prefetch 12 index
	local isareg 16
	and index 8 isareg
	and index 7 index
	local islong 16
	and prefetch 2048 islong
	
	switch isareg
	case 0
		switch islong
		case 0
		sext 32 dregs.index scratch1
		case 2048
		mov dregs.index scratch1
		end
	case 8
		switch islong
		case 0
		sext 32 aregs.index scratch1
		case 2048
		mov aregs.index scratch1
		end
	end
	add disp scratch1 scratch1

m68k_fetch_op_ea
	arg mode 16
	arg reg 16
	arg Z 16
	arg isdst 8
	switch mode
	
	case 0
	#data reg direct
	meta op dregs.reg
	if isdst
	meta ismem 0
	end
	
	case 1
	#address reg direct
	meta op aregs.reg
	if isdst
	meta ismem 0
	end
	
	case 2
	#address reg indirect
	m68k_mem_src aregs.reg Z isdst
	
	case 3
	#postincrement
	m68k_mem_src aregs.reg Z isdst
	switch reg
	case 7
		if Z
			addsize Z aregs.reg aregs.reg
		else
			addsize 1 aregs.reg aregs.reg
		end
	default
		addsize Z aregs.reg aregs.reg
	end
	
	case 4
	#predecrement
	switch reg
	case 7
		if Z
			decsize Z aregs.reg aregs.reg
		else
			decsize 1 aregs.reg aregs.reg
		end
	default
		decsize Z aregs.reg aregs.reg
	end
	cycles 2
	m68k_mem_src aregs.reg Z isdst
	
	case 5
	#displacement
	m68k_prefetch
	sext 32 prefetch scratch1
	add scratch1 aregs.reg scratch1
	m68k_mem_src scratch1 Z isdst
	
	case 6
	#indexed
	m68k_index_word
	cycles 2
	add aregs.reg scratch1 scratch1
	
	m68k_mem_src scratch1 Z isdst
	case 7
	#pc-relative and absolute modes
	
	switch reg
	case 0
	#absolute short
	m68k_prefetch
	sext 32 prefetch scratch1
	m68k_mem_src scratch1 Z isdst
	
	case 1
	#absolute long
	local address 32
	m68k_prefetch
	lsl prefetch 16 address
	m68k_prefetch
	or prefetch address scratch1
	m68k_mem_src scratch1 Z isdst
	
	case 2
	#pc displaceent
	m68k_prefetch
	sext 32 prefetch scratch1
	add scratch1 pc scratch1
	sub 2 scratch1 scratch1
	m68k_mem_src scratch1 Z isdst
	
	case 3
	#pc indexed
	m68k_index_word
	cycles 2
	add pc scratch1 scratch1
	sub 2 scratch1 scratch1
	m68k_mem_src scratch1 Z isdst
	
	case 4
	#immediate
	switch Z
	case 2
		local tmp32 32
		m68k_prefetch
		lsl prefetch 16 tmp32
		m68k_prefetch
		or prefetch tmp32 scratch1
		
	default
		m68k_prefetch
		mov prefetch scratch1
	end
	meta op scratch1
	
	end
	
	end

m68k_fetch_src_ea
	arg mode 16
	arg reg 16
	arg Z 16
	m68k_fetch_op_ea mode reg Z 0
	meta src op
	switch mode
	case 0
		meta src_is_mem 0
	case 1
		meta src_is_mem 0
	default
		meta src_is_mem 1
	end

m68k_fetch_dst_ea
	arg mode 16
	arg reg 16
	arg Z 16
	m68k_fetch_op_ea mode reg Z 1
	meta dst op
	
m68k_save_dst
	arg Z 16
	if ismem
	m68k_write_size Z 0
	end

1101DDD0ZZMMMRRR add_ea_dn
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	invalid Z 3
	m68k_fetch_src_ea M R Z
	
	add src dregs.D dregs.D Z
	update_flags XNZVC
	m68k_prefetch
	
1101DDD1ZZMMMRRR add_dn_ea
	invalid M 0
	invalid M 1
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	invalid Z 3
	m68k_fetch_dst_ea M R Z
	
	add dregs.D dst dst Z
	update_flags XNZVC
	m68k_save_dst Z
	m68k_prefetch

1101AAAZ11MMMRRR adda
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	local size 16
	local ext_src 32
	#TODO: ensure "penalty" cycles are in the right place
	if Z
		size = 2
		switch M
		case 0
			#dreg src
			cycles 4
		case 1
			#areg src
			cycles 4
		case 7
			if R = 4
				#immediate
				cycles 4
			else
				cycles 2
			end
		default
			cycles 2
		end
	else
		size = 1
		cycles 4
	end
	m68k_fetch_src_ea M R size
	switch size
	case 1
	sext 32 src ext_src
	meta src ext_src
	end
	
	add src aregs.A aregs.A
	m68k_prefetch

00000110ZZMMMRRR addi
	local immed 32
	invalid Z 3
	invalid M 1
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	#fetch immediate operand
	m68k_prefetch
	switch Z
	case 2
		lsl prefetch 16 immed
		m68k_prefetch
		or prefetch immed immed
		if M = 0
			cycles 4
		end
	default
		mov prefetch immed
	end
	#fetch dst EA
	m68k_fetch_dst_ea M R Z
	
	add immed dst dst Z
	update_flags XNZVC
	m68k_save_dst Z
	m68k_prefetch
	
0101III0ZZMMMRRR addq
	invalid Z 3
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	local src 32
	switch I
	case 0
	mov 8 src
	default
	mov I src
	end
	
	m68k_fetch_dst_ea M R Z
	switch M
	case 1
		cycles 4
		add src dst dst Z
	default
		add src dst dst Z
		update_flags XNZVC
	end
	m68k_save_dst Z
	m68k_prefetch

1101DDD1ZZ000SSS addx_dy_dx
	invalid Z 3
	adc dregs.S dregs.D dregs.D Z
	update_flags XNVC
	switch Z
	case 0
		local tmp8 8
		mov dregs.D tmp8
		if tmp8
			update_flags Z0
		end
	case 1
		local tmp16 16
		mov dregs.D tmp16
		if tmp16
			update_flags Z0
		end
	case 2
		cycles 4
		if dregs.D
			update_flags Z0
		end
	end
	m68k_prefetch

1101DDD1ZZ001SSS addx_ay_ax
	invalid Z 3
	if Z
		decsize Z aregs.S aregs.S
	else
		switch S
		case 7
			sub 2 aregs.S aregs.S
		default
			decsize Z aregs.S aregs.S
		end
	end
	#predec penalty on src only
	cycles 2
	mov aregs.S scratch1
	switch Z
	case 0
	ocall read_8
	case 1
	ocall read_16
	case 2
	m68k_read32
	end
	mov scratch1 scratch2
	if Z
		decsize Z aregs.D aregs.D
	else
		switch D
		case 7
			sub 2 aregs.D aregs.D
		default
			decsize Z aregs.D aregs.D
		end
	end
	mov aregs.D scratch1
	switch Z
	case 0
	ocall read_8
	case 1
	ocall read_16
	case 2
	m68k_read32
	end
	adc scratch2 scratch1 scratch1 Z
	update_flags XNVC
	switch Z
	case 0
	local tmp8 8
	mov dregs.D tmp8
	if tmp8
		update_flags Z0
	end
	case 1
	local tmp16 16
	mov dregs.D tmp16
	if tmp16
		update_flags Z0
	end
	case 2
	if dregs.D
		update_flags Z0
	end
	end
	mov aregs.D scratch2
	m68k_write_size Z 0
	m68k_prefetch

1100DDD0ZZMMMRRR and_ea_dn
	invalid M 1
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	invalid Z 3
	m68k_fetch_src_ea M R Z
	
	and src dregs.D dregs.D Z
	update_flags NZV0C0
	m68k_prefetch
	
1100DDD1ZZMMMRRR and_dn_ea
	invalid M 0
	invalid M 1
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	invalid Z 3
	m68k_fetch_dst_ea M R Z
	
	and dregs.D dst dst Z
	update_flags NZV0C0
	m68k_save_dst Z
	m68k_prefetch
	
00000010ZZMMMRRR andi
	local immed 32
	invalid Z 3
	invalid M 1
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	#fetch immediate operand
	m68k_prefetch
	switch Z
	case 2
		lsl prefetch 16 immed
		m68k_prefetch
		or prefetch immed immed
		if M = 0
			cycles 4
		end
	default
		mov prefetch immed
	end
	#fetch dst EA
	m68k_fetch_dst_ea M R Z
	
	and immed dst dst Z
	update_flags NZV0C0
	m68k_save_dst Z
	m68k_prefetch

0000001000111100 andi_to_ccr
	#fetch immediate operand
	m68k_prefetch
	and prefetch ccr ccr
	m68k_prefetch
	
1011DDD1ZZMMMRRR eor_dn_ea
	invalid M 1
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	invalid Z 3
	m68k_fetch_dst_ea M R Z

	if Z = 2
		if M = 0
			cycles 4
		end
	end

	xor dregs.D dst dst Z
	update_flags NZV0C0
	m68k_save_dst Z
	m68k_prefetch

00001010ZZMMMRRR eori
	local immed 32
	invalid Z 3
	invalid M 1
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	#fetch immediate operand
	m68k_prefetch
	switch Z
	case 2
		lsl prefetch 16 immed
		m68k_prefetch
		or prefetch immed immed
		if M = 0
			cycles 4
		end
	default
		mov prefetch immed
	end
	#fetch dst EA
	m68k_fetch_dst_ea M R Z
	
	xor immed dst dst Z
	update_flags NZV0C0
	m68k_save_dst Z
	m68k_prefetch
	
0000001000111100 eori_to_ccr
	#fetch immediate operand
	m68k_prefetch
	xor prefetch ccr ccr
	m68k_prefetch
	
1000DDD0ZZMMMRRR or_ea_dn
	invalid M 1
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	invalid Z 3
	m68k_fetch_src_ea M R Z

	if Z = 2
		switch M
		case 0
			#dreg
			cycles 4
		case 7
			if R = 4
				#immediate
				cycles 4
			else
				cycles 2
			end
		default
			cycles 2
		end
	end

	or src dregs.D dregs.D Z
	update_flags NZV0C0
	m68k_prefetch
	
1000DDD1ZZMMMRRR or_dn_ea
	invalid M 0
	invalid M 1
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	invalid Z 3
	m68k_fetch_dst_ea M R Z
	
	or dregs.D dst dst Z
	update_flags NZV0C0
	m68k_save_dst Z
	m68k_prefetch
	
00000000ZZMMMRRR ori
	local immed 32
	invalid Z 3
	invalid M 1
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	#fetch immediate operand
	m68k_prefetch
	switch Z
	case 2
		lsl prefetch 16 immed
		m68k_prefetch
		or prefetch immed immed
		if M = 0
			cycles 4
		end
	default
		mov prefetch immed
	end
	#fetch dst EA
	m68k_fetch_dst_ea M R Z
	
	or immed dst dst Z
	update_flags NZV0C0
	m68k_save_dst Z
	m68k_prefetch

0000000000111100 ori_to_ccr
	#fetch immediate operand
	m68k_prefetch
	or prefetch ccr ccr
	m68k_prefetch
	
1001DDD0ZZMMMRRR sub_ea_dn
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	invalid Z 3
	m68k_fetch_src_ea M R Z
	
	sub src dregs.D dregs.D Z
	update_flags XNZVC
	m68k_prefetch
	
1001DDD1ZZMMMRRR sub_dn_ea
	invalid M 0
	invalid M 1
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	invalid Z 3
	m68k_fetch_dst_ea M R Z
	
	sub dregs.D dst dst Z
	update_flags XNZVC
	m68k_save_dst Z
	m68k_prefetch

1001AAAZ11MMMRRR suba
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	local size 16
	local ext_src 32
	if Z
		size = 2
		switch M
		case 0
			#dreg src
			cycles 4
		case 1
			#areg src
			cycles 4
		case 7
			if R = 4
				#immediate
				cycles 4
			else
				cycles 2
			end
		default
			cycles 2
		end
	else
		size = 1
		cycles 4
	end
	m68k_fetch_src_ea M R size
	switch size
	case 1
	sext 32 src ext_src
	meta src ext_src
	end
	
	sub src aregs.A aregs.A
	m68k_prefetch

00000100ZZMMMRRR subi
	local immed 32
	invalid Z 3
	invalid M 1
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	#fetch immediate operand
	m68k_prefetch
	switch Z
	case 2
		lsl prefetch 16 immed
		m68k_prefetch
		or prefetch immed immed
		if M = 0
			cycles 4
		end
	default
		mov prefetch immed
	end
	#fetch dst EA
	m68k_fetch_dst_ea M R Z
	
	sub immed dst dst Z
	update_flags XNZVC
	m68k_save_dst Z
	m68k_prefetch
	
0101III1ZZMMMRRR subq
	invalid Z 3
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	local src 32
	switch I
	case 0
	mov 8 src
	default
	mov I src
	end
	
	m68k_fetch_dst_ea M R Z
	switch M
	case 1
		sub src dst dst Z
	default
		sub src dst dst Z
		update_flags XNZVC
	end
	m68k_save_dst Z
	m68k_prefetch
	
1110CCC0ZZ001RRR lsri
	invalid Z 3
	switch C
	case 0
		meta shift 8
	default
		meta shift C
	end
	lsr dregs.R shift dregs.R Z
	update_flags XNZV0C
	local cyc 32
	cyc = shift + shift
	switch Z
	case 2
		cyc += 4
	default
		cyc += 2
	end
	cycles cyc
	#TODO: should this happen before or after the majority of the shift?
	m68k_prefetch
	
1110CCC0ZZ101RRR lsr_dn
	invalid Z 3
	local shift 8
	and dregs.C 63 shift
	lsr dregs.R shift dregs.R Z
	update_flags XNZV0C
	add shift shift shift
	switch Z
	case 2
		add 4 shift shift
	default
		add 2 shift shift
	end
	cycles shift
	#TODO: should this happen before or after the majority of the shift?
	m68k_prefetch
	
1110001011MMMRRR lsr_ea
	invalid M 0
	invalid M 1
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	
	m68k_fetch_dst_ea M R 0
	lsr dst 1 dst
	update_flags XNZV0C
	m68k_save_dst 0
	m68k_prefetch
	
1110CCC1ZZ001RRR lsli
	invalid Z 3
	switch C
	case 0
		meta shift 8
	default
		meta shift C
	end
	lsl dregs.R shift dregs.R Z
	update_flags XNZV0C
	local cyc 32
	cyc = shift + shift
	switch Z
	case 2
		cyc += 4
	default
		cyc += 2
	end
	cycles cyc
	#TODO: should this happen before or after the majority of the shift?
	m68k_prefetch
	
1110CCC1ZZ101RRR lsl_dn
	invalid Z 3
	local shift 8
	and dregs.C 63 shift
	lsl dregs.R shift dregs.R Z
	update_flags XNZV0C
	add shift shift shift
	switch Z
	case 2
		add 4 shift shift
	default
		add 2 shift shift
	end
	cycles shift
	#TODO: should this happen before or after the majority of the shift?
	m68k_prefetch
	
1110001111MMMRRR lsl_ea
	invalid M 0
	invalid M 1
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	
	m68k_fetch_dst_ea M R 0
	lsl dst 1 dst
	update_flags XNZV0C
	m68k_save_dst 0
	m68k_prefetch

00ZZRRRMMMEEESSS move
	invalid Z 0
	invalid M 1
	invalid M 7 #not actually invalid, but will be handled separately due to DSL limitations
	invalid E 7 S 5
	invalid E 7 S 6
	invalid E 7 S 7
	local size 8
	local memsrc 32
	#move uses a different size format than most instructions
	switch Z
		case 1
			mov 0 size
		case 2
			mov 2 size
		case 3
			mov 1 size
	end
	m68k_fetch_src_ea E S size
	
	if src_is_mem
		#avoid clobbering src if we need scratch1
		mov src memsrc
		meta src memsrc
	end
	
	cmp 0 src size
	update_flags NZV0C0
	
	switch M
		case 0
		mov src dregs.R size
		
		case 2
		mov aregs.R scratch2
		mov src scratch1
		m68k_write_size size 0
		
		case 3
		mov aregs.R scratch2
		mov src scratch1
		switch R
			case 7
				if size
					addsize size aregs.R aregs.R
				else
					addsize 1 aregs.R aregs.R
				end
			default
				addsize size aregs.R aregs.R
		end
		m68k_write_size size 0
		
		case 4
		mov src scratch1
		switch R
			case 7
				if size
					decsize size aregs.R aregs.R
				else
					decsize 1 aregs.R aregs.R
				end
			default
				decsize size aregs.R aregs.R
		end
		mov aregs.R scratch2
		m68k_write_size size 1
		
		case 5
		m68k_prefetch
		sext 32 prefetch scratch2
		add aregs.R scratch2 scratch2
		mov src scratch1
		m68k_write_size size 0
		
		case 6
		m68k_index_word
		add aregs.R scratch1 scratch2
		mov src scratch1
		m68k_write_size size 0
	end
	m68k_prefetch


00ZZ00M111EEESSS move_abs
	invalid E 7 S 5
	invalid E 7 S 6
	invalid E 7 S 7
	invalid Z 0
	local size 8
	local memsrc 32
	#move uses a different size format than most instructions
	switch Z
	case 1
		mov 0 size
	case 2
		mov 2 size
	case 3
		mov 1 size
	end
	m68k_fetch_src_ea E S size
	
	if src_is_mem
		#avoid clobbering src if we need scratch1
		mov src memsrc
		meta src memsrc
	end
	
	cmp 0 src size
	update_flags NZV0C0
	
	switch M
	case 0
	m68k_prefetch
	sext 32 prefetch scratch2
	
	case 1
	m68k_prefetch
	lsl prefetch 16 scratch2
	m68k_prefetch
	or prefetch scratch2 scratch2
	end
	mov src scratch1
	m68k_write_size size 0
	m68k_prefetch
	
00ZZRRR001EEESSS movea
	local size 8
	invalid Z 0
	invalid Z 1
	invalid E 7 S 5
	invalid E 7 S 6
	invalid E 7 S 7
	switch Z
	case 2
		mov 2 size
	case 3
		mov 1 size
	end
	m68k_fetch_src_ea E S size
	switch Z
	case 2
		mov src aregs.R
	case 3
		sext 32 src aregs.R
	end
	m68k_prefetch
	
0100010011MMMRRR move_to_ccr
	invalid M 1
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	m68k_fetch_src_ea M R 1
	mov scratch1 ccr
	cycles 8
	m68k_prefetch

0100011011MMMRRR move_to_sr
	invalid M 1
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	#TODO: privilege violation exception if in user mode
	m68k_fetch_src_ea M R 1
	mov scratch1 ccr
	lsr scratch1 8 status
	update_sync
	cycles 8
	m68k_prefetch

0100000011MMMRRR move_from_sr
	invalid M 1
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	m68k_fetch_dst_ea M R 1
	lsl status 8 scratch1
	or ccr scratch1 scratch1
	mov scratch1 dst
	if M
		cycles 4
	else
		cycles 2
	end
	m68k_save_dst 1
	m68k_prefetch

01000000ZZMMMRRR negx
	invalid M 1
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	m68k_fetch_dst_ea M R Z
	sbc dst 0 dst Z
	update_flags XNZVC
	if Z = 2
		if M = 0
			cycles 2
		end
	end
	m68k_save_dst Z
	m68k_prefetch

01000010ZZMMMRRR clr
	invalid M 1
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	invalid Z 3
	m68k_fetch_dst_ea M R Z
	if Z = 2
		if M = 0
			#register clears have 2 cycle penalty for longword size
			cycles 2
		end
	end
	dst:Z = 0
	update_flags N0Z1V0C0
	m68k_save_dst Z
	m68k_prefetch

00001100ZZMMMRRR cmpi
	local immed 32
	invalid Z 3
	invalid M 1
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	#fetch immediate operand
	m68k_prefetch
	switch Z
	case 2
		immed = prefetch << 16
		m68k_prefetch
		immed |= prefetch
		if M = 0
			cycles 2
		end
	default
		immed = prefetch
	end
	#fetch dst EA
	m68k_fetch_dst_ea M R Z
	
	cmp immed dst Z
	update_flags NZVC
	m68k_prefetch

1011DDD1ZZ001SSS cmpm
	invalid Z 3
	scratch1 = aregs.S 
	switch Z
	case 0
		ocall read_8
	case 1
		ocall read_16
	case 2
		m68k_read32
	end
	scratch2 = scratch1
	if Z
		addsize Z aregs.S aregs.S
	else
		if S = 7
			aregs.S += 2
		else
			aregs.S += 1
		end
	end
	scratch1 = aregs.D
	switch Z
	case 0
		ocall read_8
	case 1
		ocall read_16
	case 2
		m68k_read32
	end
	if Z
		addsize Z aregs.D aregs.D
	else
		if D = 7
			aregs.D += 2
		else
			aregs.D += 1
		end
	end
	cmp scratch2 scratch1 Z
	update_flags NZVC
	m68k_prefetch

1011DDD0ZZMMMRRR cmp
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	invalid Z 3
	m68k_fetch_src_ea M R Z
	
	if Z = 2
		cycles 2
	end
	
	cmp src dregs.D Z
	update_flags NZVC
	m68k_prefetch

1011DDDZ11MMMRRR cmpa
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	local size 16
	local ext_src 32
	if Z
		size = 2
	else
		size = 1
	end
	m68k_fetch_src_ea M R size
	cycles 2
	if size = 1
		sext 32 src ext_src
		meta src ext_src
	end
	cmp src aregs.D
	update_flags NZVC
	m68k_prefetch

0000100000MMMRRR btsti
	invalid M 1
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7

	local tmp 32
	m68k_prefetch
	if M
		tmp = scratch1 & 7
		meta size 0
	else
		cycles 2
		tmp = scratch1 & 31
		meta size 2
	end
	tmp = 1 << tmp
	m68k_fetch_src_ea M R size
	tmp &= src
	update_flags Z
	m68k_prefetch

0000100001MMMRRR bchgi
	invalid M 1
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7

	local tmp 32
	local tmp2 32
	m68k_prefetch
	if M
		tmp = scratch1 & 7
		meta size 0
	else
		tmp = scratch1 & 31
		meta size 2
		if tmp >=U 16
			cycles 4
		else
			cycles 2
		end
	end
	tmp = 1 << tmp
	m68k_fetch_dst_ea M R size
	tmp2 = tmp & dst
	update_flags Z
	dst ^= tmp
	m68k_save_dst size
	m68k_prefetch

0000100010MMMRRR bclri
	invalid M 1
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7

	local tmp 32
	local tmp2 32
	m68k_prefetch
	if M
		tmp = scratch1 & 7
		meta size 0
	else
		tmp = scratch1 & 31
		meta size 2
		if tmp >=U 16
			cycles 6
		else
			cycles 4
		end
	end
	tmp = 1 << tmp
	m68k_fetch_dst_ea M R size
	tmp2 = tmp & dst
	update_flags Z
	tmp = ~tmp
	dst &= tmp
	m68k_save_dst size
	m68k_prefetch

0000100011MMMRRR bseti
	invalid M 1
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7

	local tmp 32
	local tmp2 32
	m68k_prefetch
	if M
		tmp = scratch1 & 7
		meta size 0
	else
		tmp = scratch1 & 31
		meta size 2
		if tmp >=U 16
			cycles 4
		else
			cycles 2
		end
	end
	tmp = 1 << tmp
	m68k_fetch_dst_ea M R size
	tmp2 = tmp & dst
	update_flags Z
	dst |= tmp
	m68k_save_dst size
	m68k_prefetch

0000SSS100MMMRRR btst_dn
	invalid M 1
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7

	local tmp 32
	if M
		tmp = dregs.S & 7
		meta size 0
	else
		tmp = dregs.S & 31
		meta size 2
		cycles 2
	end
	tmp = 1 << tmp
	m68k_fetch_src_ea M R size
	tmp &= src
	update_flags Z
	m68k_prefetch

0000SSS101MMMRRR bchg_dn
	invalid M 1
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7

	local tmp 32
	local tmp2 32
	if M
		tmp = dregs.S & 7
		meta size 0
	else
		tmp = dregs.S & 31
		meta size 2
		if tmp >=U 16
			cycles 4
		else
			cycles 2
		end
	end
	tmp = 1 << tmp
	m68k_fetch_dst_ea M R size
	tmp2 = tmp & dst
	update_flags Z
	dst ^= tmp
	m68k_save_dst size
	m68k_prefetch

0000SSS110MMMRRR bclr_dn
	invalid M 1
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7

	local tmp 32
	local tmp2 32
	if M
		tmp = dregs.S & 7
		meta size 0
	else
		tmp = dregs.S & 31
		meta size 2
		if tmp >=U 16
			cycles 6
		else
			cycles 4
		end
	end
	tmp = 1 << tmp
	m68k_fetch_dst_ea M R size
	tmp2 = tmp & dst
	update_flags Z
	tmp = ~tmp
	dst &= tmp
	m68k_save_dst size
	m68k_prefetch

0000SSS111MMMRRR bset_dn
	invalid M 1
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7

	local tmp 32
	local tmp2 32
	if M
		tmp = dregs.S & 7
		meta size 0
	else
		tmp = dregs.S & 31
		meta size 2
		if tmp >=U 16
			cycles 4
		else
			cycles 2
		end
	end
	tmp = 1 << tmp
	m68k_fetch_dst_ea M R size
	tmp2 = tmp & dst
	update_flags Z
	dst |= tmp
	m68k_save_dst size
	m68k_prefetch

0000DDD10Z001AAA movep_ay_dx
	local address 32
	m68k_prefetch
	scratch1 += aregs.A
	address = scratch1 + 2
	ocall read_8
	dregs.D:1 = scratch1 << 8
	scratch1 = address
	ocall read_8
	dregs.D:0 = scratch1
	if Z
		address += 2
		scratch1 = address
		dregs.D <<= 16
		ocall read_8
		dregs.D:1 = scratch1 << 8
		scratch1 = address + 2
		ocall read_8
		dregs.D:0 = scratch1
	end
	m68k_prefetch

0000DDD11Z001AAA movep_dx_ay
	m68k_prefetch
	scratch2 = scratch1 + aregs.A
	if Z
		scratch1 = dregs.D >> 24
		ocall write_8
		scratch2 += 2
		scratch1 = dregs.D >> 16
		ocall write_8
		scratch2 += 2
	end
	scratch1 = dregs.D >> 8
	ocall write_8
	scratch2 += 2
	scratch1 = dregs.D
	ocall write_8
	m68k_prefetch

01000100ZZMMMRRR neg
	invalid Z 3
	invalid M 1
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	
	m68k_fetch_dst_ea M R Z
	dst:Z = -dst
	update_flags XNZVC
	if Z = 2
		if M = 0
			cycles 2
		end
	end
	m68k_save_dst Z
	m68k_prefetch

01000110ZZMMMRRR not
	invalid Z 3
	invalid M 1
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	
	m68k_fetch_dst_ea M R Z
	dst:Z = ~dst
	update_flags NZV0C0
	if Z = 2
		if M = 0
			cycles 2
		end
	end
	m68k_save_dst Z
	m68k_prefetch

01001000ZZ000RRR ext
	invalid Z 0
	invalid Z 1
	if Z = 3
		meta bits 32
	else
		meta bits 16
	end
	sext bits dregs.R dregs.R
	update_flags NZV0C0
	m68k_prefetch

0100111001010RRR link
	a7 -= 4
	scratch2 = a7
	#TODO: confirm order of fetch and write
	m68k_write32 aregs.R
	m68k_prefetch
	aregs.R = a7
	sext 32 scratch1 scratch1
	a7 += scratch1
	m68k_prefetch

0100111001011RRR unlk
	a7 = aregs.R
	scratch1 = a7
	m68k_read32
	a7 += 4
	aregs.R = scratch1
	m68k_prefetch

0100100001000RRR swap
	ror dregs.R 16 dregs.R
	update_flags NZV0C0
	m68k_prefetch
	
m68k_calc_ea
	arg mode 16
	arg reg 16
	
	switch mode
	case 2
		#address reg indirect
		meta ea aregs.reg
	case 5
		#displacement
		m68k_prefetch
		sext 32 prefetch scratch1
		scratch1 += aregs.reg
		meta ea scratch1
	case 6
		#index
		m68k_index_word
		cycles 4
		scratch1 += aregs.reg
		meta ea scratch1
	case 7
		switch reg
		case 0
			#absolute short
			m68k_prefetch
			sext 32 prefetch scratch1
		case 1
			#absoltue long
			m68k_prefetch
			scratch2 = prefetch << 16
			m68k_prefetch
			scratch1 = scratch2 | prefetch
		case 2
			#pc displacement
			m68k_prefetch
			sext 32 prefetch scratch1
			scratch1 += pc
			scratch1 -= 2
		case 3
			#pc indexed
			m68k_index_word
			cycles 4
			scratch1 += pc
			scratch1 -= 2
		end
		meta ea scratch1
	end

0100100001MMMRRR pea
	invalid M 0
	invalid M 1
	invalid M 3
	invalid M 4
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	
	m68k_calc_ea M R
	scratch2 = a7 - 4
	m68k_write32_lowfirst ea
	a7 -= 4
	
	m68k_prefetch

0100DDD111MMMRRR lea
	invalid M 0
	invalid M 1
	invalid M 3
	invalid M 4
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	
	m68k_calc_ea M R
	aregs.D = ea
	
	m68k_prefetch

01001010ZZMMMRRR tst
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	
	m68k_fetch_dst_ea M R Z
	
	cmp 0 dst Z
	update_flags NZV0C0
	m68k_prefetch

0100111001110000 reset
	if reset_handler
	pcall reset_handler m68k_reset_handler context
	end
	cycles 128
	m68k_prefetch

0100111001110001 nop
	m68k_prefetch

0100111001110011 rte
	#TODO: privilege violation exception if in user mode
	#Read saved SR
	scratch1 = a7
	ocall read_16
	a7 += 2
	ccr = scratch1
	status = scratch1 >> 8
	#Read saved PC
	scratch1 = a7
	m68k_read32
	a7 += 4
	pc = scratch1
	
	check_user_mode_swap_ssp_usp
	cycles 4
	update_sync
	m68k_prefetch

0100111001110101 m68k_rts
	scratch1 = a7
	m68k_read32
	a7 += 4
	pc = scratch1
	
	cycles 4
	m68k_prefetch

0100111001110111 rtr
	#Read saved CCR
	scratch1 = a7
	ocall read_16
	a7 += 2
	ccr = scratch1
	#Read saved PC
	scratch1 = a7
	m68k_read32
	a7 += 4
	pc = scratch1
	
	cycles 4
	m68k_prefetch

0100111010MMMRRR jsr
	invalid M 0
	invalid M 1
	invalid M 3
	invalid M 4
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	
	a7 -= 4
	scratch1 = a7
	m68k_write32 pc
	
	m68k_calc_ea M R
	pc = ea
	
	cycles 4
	m68k_prefetch

0100111010MMMRRR jmp
	invalid M 0
	invalid M 1
	invalid M 3
	invalid M 4
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	
	m68k_calc_ea M R
	pc = ea
	
	cycles 4
	m68k_prefetch

010010001ZMMMRRR movem_reg_to_mem
	invalid M 0
	invalid M 1
	invalid M 3
	invalid M 7 R 2
	invalid M 7 R 3
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	local reglist 16
	
	m68k_prefetch
	reglist = scratch1
	
010011001ZMMMRRR movem_mem_to_reg
	invalid M 0
	invalid M 1
	invalid M 4
	invalid M 7 R 4
	invalid M 7 R 5
	invalid M 7 R 6
	invalid M 7 R 7
	local reglist 16
	
	m68k_prefetch
	reglist = scratch1