⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c64.h64

📁 SEED的VPM642测试程序-板级支持库
💻 H64
📖 第 1 页 / 共 3 页
字号:

	.else
	    .emsg "Bad register name in C64_set - :reg:"
	.endif

	.endloop

ab_mask	.set abmask
c_mask	.set cmask

	.endm

;
;# ======== C64_disableIER ========
;
;  Disable interrupts using mask
;  IEMASK	- Interrupt Enable mask
;  REG0, REG1	- temporary registers used to set IER
;
;#
;# Preconditions:
;#	none
;#
;# Postconditions:
;#	none
;#
;
C64_disableIER	.macro	IEMASK, REG0, REG1
	.if ($symlen(":IEMASK:") == 0)
	    .emsg  "C64_disableIER: IEMASK, REG0, and REG1 operands missing."
        .elseif ($symlen(":REG0:") == 0)
	    .emsg  "C64_disableIER: REG0 and REG1 operands missing."
	.elseif ($symlen(":REG1:") == 0)
	    .emsg  "C64_disableIER: REG1 operand missing."
	.else
	    b       disableIER_label?		; Protect IER from interrupt
||          mvkl    :IEMASK:, :REG1:
            mvc     ier, :REG0:
            mvkh    :IEMASK:, :REG1:
            xor     -1, :REG1:, :REG1:
            and     :REG1:, :REG0:, :REG0:
            mvc     :REG0:, ier		
disableIER_label?:
	.endif
	.endm

;
;# ======== C64_enableIER ========
;
;  Enable interrupts using mask
;  IEMASK	- Interrupt Enable mask
;  REG0, REG1	- temporary registers used to set IER
;
;#
;# Preconditions:
;#	none
;#
;# Postconditions:
;#	none
;#
;
C64_enableIER	.macro	IEMASK, REG0, REG1
	.if ($symlen(":IEMASK:") == 0)
	    .emsg  "C64_enableIER: IEMASK, REG0, and REG1 operands missing."
        .elseif ($symlen(":REG0:") == 0)
	    .emsg  "C64_enableIER: REG0 and REG1 operands missing."
	.elseif ($symlen(":REG1:") == 0)
	    .emsg  "C64_enableIER: REG1 operand missing."
	.else
	    b       enableIER_label?		; Protect IER from interrupt
            mvc     ier, :REG0:
            mvkl    :IEMASK:, :REG1:
            mvkh    :IEMASK:, :REG1:
            or      :REG1:, :REG0:, :REG0:
            mvc     :REG0:, ier		
enableIER_label?:
	.endif
	.endm

;
;# ======== FIRST_BIT_NUM ========
;  Returns the bit number of the lowest 1 bit in 32-bit register.
;  Returns 32 if none set.
;
;#
;# Preconditions:
;#	none
;#
;# Postconditions:
;#	none
;#
;
FIRST_BIT_NUM	.macro	MASK, BITNUM
	.asg	0, BITNUM
	.eval	MASK, regmask
	.loop	32
	    .if	(regmask & 1)
		.break
	    .endif
	    .eval	regmask >> 1, regmask
	    .eval	BITNUM + 1, BITNUM
	.endloop
	.endm

;
;# ======== NUM_BITS ========
;  Returns the number of 1 bits in a 32-bit register.
;
;#
;# Preconditions:
;#	none
;#
;# Postconditions:
;#	none
;#
;
NUM_BITS	.macro	MASK, BITCOUNT
	.asg	0, BITCOUNT
	.eval	MASK, regmask
	.loop	32
	    .if	(regmask & 1)
		.eval	BITCOUNT + 1, BITCOUNT
	    .endif
	    .eval	regmask >> 1, regmask
	.endloop
	.endm

;
;# ======== BIT_NUM_2_CREG ========
;  Maps the control register bitmask assignments to names.
;
;#
;# Preconditions:
;#	none
;#
;# Postconditions:
;#	none
;#
;
BIT_NUM_2_CREG	.macro	BITNUM, CREG
	.if ((1 << BITNUM) = C64_AMR)
	    .asg	amr, CREG
	.elseif ((1 << BITNUM) = C64_CSR)
	    .asg	csr, CREG
	.elseif ((1 << BITNUM) = C64_IER)
	    .asg	ier, CREG
	.elseif ((1 << BITNUM) = C64_IST)
	    .asg	istp, CREG
	.elseif ((1 << BITNUM) = C64_IRP)
	    .asg	irp, CREG
	.elseif ((1 << BITNUM) = C64_NRP)
	    .asg	nrp, CREG
	.else
	    .emsg	"Bad bit in C64_CMASK"
	    .break
	.endif
	.endm

;
;# ======== C64_restore ========
;
;  This macro conditionally restores registers from the stack, depending
;  on AMASK, BMASK and CMASK. Typically, use of this macro balances use of the 
;  C64_save macro with the same mask values.
;
;  C64_restore AMASK, BMASK, CMASK
;
;  AMASK - Mask of A registers to restore
;  BMASK - Mask of B registers to restore
;  CMASK - Mask of control registers to restore
;
; Currently, this macro is largely complicated by the fact that you
; can't have an assembly construct like the following:
;	.if	(bitcount > 1)
; ||	mv	A4, B0
;	.endif
; The assembler complains about an illegal mnemonic.  Without the
; ability to generate code as above, many places in this macro are
; greatly more complicated since they must now look ahead.
;
; We need to maintain 8-byte stack alignment.
; The method chosen is to count the number of bits in the masks,
; thereby giving you the number of registers to restore.  This is
; then rounded up to the nearest even number, and the SP is
; adjusted once at the end, with all previous "loads" being
; offset into that frame.  Since the pre-processor is doing all
; the counting, this turns out to be equally efficient to the
; C6x method involving "pops".
;
; Uses two lowest numbered A registers in AMASK for an A-side stack
; frame pointer and a temporary A register.  If no A registers specified
; in AMASK, registers A0 & A1 are used.  If only register A0 is specified,
; register A1 is also used.  If a register other than A0 is specified,
; register A0 and that one are used.
;
; For the B-side, the lowest numbered B register in BMASK is used as a
; temporary B register, and if no B register is specified, register B0
; is used.
;
;#
;# Preconditions:
;#	none
;#
;# Postconditions:
;#	none
;#
;
C64_restore .macro AMASK, BMASK, CMASK, SPFLAG
	.sslist
	.asg	0, mask
	.asg	0, bitn_a
	.asg	0, bitn_b
	.asg	-1, bitn_c
	.asg	0, bitn_0
	.asg	0, bitn_1
	.asg	0, bitn_next
	.asg	0, bitcount
	.asg	0, a_bitcount
	.asg	0, b_bitcount
	.asg	0, c_bitcount
	.asg	0, creg0
	.asg	0, creg1
	.asg	-1, cr0_offset
	.asg	-1, cr1_offset
	.asg	0, nop_count

	.eval	AMASK, amask
	.eval	BMASK, bmask
	.eval	bmask & ~(C64_B15), bmask		; don't restore B15
	.eval	CMASK, cmask

	.eval	0, C64_spoffset

	;
	; .mexit was causing errors since the rest of the macro
	; was getting expanded even though it wasn't used.  Instead
	; of .mexit, turn the 'if' test around to control inclusion
	; of the rest of the macro.
	;
	.if	!((amask = 0) & (bmask = 0) & (cmask = 0))

	;
	; Count 1 bits in masks
	;
	NUM_BITS	amask, a_bitcount
	NUM_BITS	bmask, b_bitcount
	NUM_BITS	cmask, c_bitcount
	
	; make sure at least two A registers are specified
	NUM_BITS	amask, a_bitcount
	.if	(a_bitcount = 0)
	    .eval	C64_A0 | C64_A1, amask
	    .eval	a_bitcount + 2, a_bitcount
	.elseif	(a_bitcount = 1)
	    .if	(amask & C64_A0)
		.eval	amask | C64_A1, amask
	    .eval	a_bitcount + 1, a_bitcount
	    .else
		.eval	amask | C64_A0, amask
	    .eval	a_bitcount + 1, a_bitcount
	    .endif
	.endif

	; make sure at least one B register is specified
	.if	(bmask = 0)
	    .eval	(C64_B0) , bmask
	    .eval	b_bitcount + 1, b_bitcount
	.endif

	.eval	a_bitcount + b_bitcount + c_bitcount, ones
	.eval	a_bitcount + b_bitcount, ab_count	; if ab_count is even
							; behavior differ
	.eval	ones + 1, tmp_ones			; align to even
	.eval	tmp_ones & 0xfffffffe, even_ones	;   number of words
	.eval	even_ones * 4, words
	.eval	even_ones / 2, half		; split the frames in half
	.eval   half, boffset			; use as B frame Offset
	.eval   boffset - 1, aoffset		; use as A frame Offset
						; -1 for SPA

	; assign A-side stack frame pointer and temp A register
	FIRST_BIT_NUM	amask, bitn_a
	.eval	amask & ~(1 << bitn_a), amask
	.asg	a:bitn_a:, SPA
	FIRST_BIT_NUM	amask, bitn_a
	.eval	amask & ~(1 << bitn_a), amask
	.asg	a:bitn_a:, TMPA
	.eval	a_bitcount - 2, a_bitcount

	; assign B-side stack frame pointer and temp B register
	FIRST_BIT_NUM	bmask, bitn_b
	.eval	bmask & ~(1 << bitn_b), bmask
	.asg	b:bitn_b:, TMPB
	.asg	SP, SPB
	.eval	b_bitcount - 1, b_bitcount

	; C64_save saves the B temp register before the A temp register
	.eval	boffset, tmpb_offset
	.eval	boffset -1, boffset
	.eval	aoffset, tmpa_offset
	.eval	aoffset -1, aoffset

	mv	SP, SPA						; CODE
	addaw	SPA, half, SPA		; move SP into SPA then add half to SPA

	;
	; Try to set up some advanced loads for control registers
	; to reduce load latency
	;
	.eval	a_bitcount + b_bitcount, bitcount
	.if	(c_bitcount > 1)
	    .if (ab_count & 0xfffffffe)
	    	.eval	aoffset+boffset - bitcount - 1, cr0_offset
	    	.eval	cr0_offset, cr1_offset
	    	.eval	4 - bitcount, nop_count
	    	ldw	*+SPB[cr0_offset+half], TMPB		; CODE
||	    	ldw	*+SPA[cr1_offset-half], TMPA		; CODE
	    .else 
	    	.eval	aoffset+boffset - bitcount + 1, cr0_offset
	    	.eval	cr0_offset - 1, cr1_offset
	    	.eval	4 - bitcount, nop_count
	    	ldw	*+SPB[cr0_offset], TMPB				; CODE
||	    	ldw	*+SPA[cr1_offset], TMPA				; CODE
	    .endif
	.elseif	(c_bitcount = 1)
	    .if (ab_count & 0xfffffffe)
	    	.eval	aoffset+boffset - bitcount, cr0_offset
	    	.eval	4 - bitcount, nop_count
	        ldw	*+SPB[cr0_offset+half], TMPB		; CODE
	    .else	
	    	.eval	aoffset+boffset - bitcount+1, cr0_offset
	    	.eval	4 - bitcount, nop_count
	        ldw	*+SPB[cr0_offset], TMPB				; CODE
	    .endif
	.endif

	;
	; This loop handles when both A and B registers need restoring
	;
	.loop
	    .if		(a_bitcount > 0) & (b_bitcount > 0)
		FIRST_BIT_NUM	amask, bitn_a
		FIRST_BIT_NUM	bmask, bitn_b
		.eval	amask & ~(1 << bitn_a), amask
		.eval	bmask & ~(1 << bitn_b), bmask

		ldw	*+SPB[boffset], b:bitn_b:		; CODE
||		ldw	*+SPA[aoffset], a:bitn_a:		; CODE

		.eval	boffset - 1, boffset
		.eval	aoffset - 1, aoffset
		.eval	a_bitcount - 1, a_bitcount
		.eval	b_bitcount - 1, b_bitcount
	    .else
		.break
	    .endif
	.endloop

	.if	(a_bitcount > 0)
	    .asg	amask, mask
	    .asg	A, reg
	.elseif	(b_bitcount > 0)
	    .asg	bmask, mask
	    .asg	B, reg
	.endif

	;
	; we enter this loop when there are only registers from either
	; A or B remaining (but not both).
	;
	NUM_BITS	mask, bitcount
	.loop
	    .if	(bitcount > 0)
		FIRST_BIT_NUM	mask, bitn_next
		.eval	mask & ~(1 << bitn_next), mask
		.eval	bitcount - 1, bitcount

		.if (aoffset >= boffset)
		    ldw	*+SP[aoffset+half], :reg::bitn_next: ; CODE
		    .eval	aoffset - 1, aoffset
		.else
		    ldw	*+SP[boffset], :reg::bitn_next:		  ; CODE
		    .eval	boffset - 1, boffset
		.endif
	    .else
		.break
	    .endif
	.endloop

	;
	; Restore the control registers
	;
	.if	(cr0_offset != -1)
	    FIRST_BIT_NUM	cmask, bitn_0
	    BIT_NUM_2_CREG	bitn_0, creg0
	    .eval	cmask & ~(1 << bitn_0), cmask

	    .if	(nop_count > 0)

	 	nop	:nop_count:				; CODE

	    .endif
	    .if	(cr1_offset = -1)

		mvc	TMPB, creg0				; CODE

		.eval	c_bitcount - 1, c_bitcount

		; if even then it must live in a ptr so decrement aoffset
		; if odd then it must exist in b ptr so decrement boffset
		.if (ab_count & 0xfffffffe)
		    .eval	aoffset - 1, aoffset
		.else 
		    .eval	boffset - 1, boffset
		.endif
	    .else
		; already set up first register immediately above
		FIRST_BIT_NUM	cmask, bitn_1
		BIT_NUM_2_CREG	bitn_1, creg1
		.eval	cmask & ~(1 << bitn_1), cmask

		mvc	TMPB, creg0				; CODE
||		mv	TMPA, TMPB				; CODE
		mvc	TMPB, creg1				; CODE

		.eval	c_bitcount - 2, c_bitcount
		; if even then it must live in a ptr so decrement aoffset
		; if odd then it must exist in b ptr so decrement boffset
		.if (ab_count & 0xfffffffe)
		    .eval	aoffset - 1, aoffset
		.else 
		    .eval	boffset - 1, boffset
		.endif
	    .endif
	.endif

	.loop
	    .if	(c_bitcount > 1)
		FIRST_BIT_NUM	cmask, bitn_0
		BIT_NUM_2_CREG	bitn_0, creg0
		.eval	cmask & ~(1 << bitn_0), cmask
		FIRST_BIT_NUM	cmask, bitn_1
		BIT_NUM_2_CREG	bitn_1, creg1
		.eval	cmask & ~(1 << bitn_1), cmask
		.eval	c_bitcount - 2, c_bitcount

		ldw	*+SPB[boffset], TMPB			; CODE
||		ldw	*+SPA[aoffset], TMPA			; CODE
		nop	4					; CODE
		mvc	TMPB, creg0				; CODE
||		mv	TMPA, TMPB				; CODE
		mvc	TMPB, creg1				; CODE

		.eval	aoffset - 1, aoffset
		.eval	boffset - 1, boffset
	    .elseif	(c_bitcount = 1)
		FIRST_BIT_NUM	cmask, bitn_c

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -