view m68k.cpu @ 1941:9eec86183aae

Implement 68K or and sub instructions in new core
author Michael Pavone <pavone@retrodev.com>
date Fri, 24 Apr 2020 09:23:43 -0700
parents 048442b0cb62
children 7d4df6b74263
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 *(*m68k_reset_handler)(m68k_context *context);
	void init_m68k_opts(m68k_options *opts, memmap_chunk * memmap, uint32_t num_chunks, uint32_t clock_divider);
	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
	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
	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
	if Z
	mov 2 size
	else
	mov 1 size
	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
	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
		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
	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
	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
	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
	
	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
	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
	
	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
	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
	mov 2 size
	else
	mov 1 size
	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
	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

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
	m68k_prefetch

0100011011MMMRRR move_to_sr
	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
	lsr scratch1 8 status
	update_sync
	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
	m68k_save_dst 1
	m68k_prefetch

0100111001110000 reset
	cycles 124
	if reset_handler
	pcall reset_handler m68k_reset_handler context
	end