c62.h62

来自「SEED的VPM642测试程序-板级支持库」· H62 代码 · 共 1,248 行 · 第 1/3 页

H62
1,248
字号
;#
;# Postconditions:
;#	none
;#
;
C62_disableIER	.macro	IEMASK, REG0, REG1
	.if ($symlen(":IEMASK:") == 0)
	    .emsg  "C62_disableIER: IEMASK, REG0, and REG1 operands missing."
        .elseif ($symlen(":REG0:") == 0)
	    .emsg  "C62_disableIER: REG0 and REG1 operands missing."
	.elseif ($symlen(":REG1:") == 0)
	    .emsg  "C62_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

;
;# ======== C62_enableIER ========
;
;  Enable interrupts using mask
;  IEMASK	- Interrupt Enable mask
;  REG0, REG1	- temporary registers used to set IER
;
;#
;# Preconditions:
;#	none
;#
;# Postconditions:
;#	none
;#
;
C62_enableIER	.macro	IEMASK, REG0, REG1
	.if ($symlen(":IEMASK:") == 0)
	    .emsg  "C62_enableIER: IEMASK, REG0, and REG1 operands missing."
        .elseif ($symlen(":REG0:") == 0)
	    .emsg  "C62_enableIER: REG0 and REG1 operands missing."
	.elseif ($symlen(":REG1:") == 0)
	    .emsg  "C62_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) = C62_AMR)
	    .asg	amr, CREG
	.elseif ((1 << BITNUM) = C62_CSR)
	    .asg	csr, CREG
	.elseif ((1 << BITNUM) = C62_IER)
	    .asg	ier, CREG
	.elseif ((1 << BITNUM) = C62_IST)
	    .asg	istp, CREG
	.elseif ((1 << BITNUM) = C62_IRP)
	    .asg	irp, CREG
	.elseif ((1 << BITNUM) = C62_NRP)
	    .asg	nrp, CREG
	.else
	    .emsg	"Bad bit in C62_CMASK"
	    .break
	.endif
	.endm

;
;# ======== C62_restore ========
;
;  This macro conditionally restores registers from the stack, depending
;  on ABMASK and CMASK. Typically, use of this macro balances use of the 
;  C62_save macro with the same mask values.
;
;  C62_restore ABMASK, CMASK
;
;  ABMASK - Mask of A and 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 ABMASK for an A-side stack
; frame pointer and a temporary A register.  If no A registers specified
; in ABMASK, 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 ABMASK is used as a
; temporary B register, and if no B register is specified, register B0
; is used.
;
;#
;# Preconditions:
;#	none
;#
;# Postconditions:
;#	none
;#
;

C62_restore .macro ABMASK, CMASK, SPFLAG
	.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	ABMASK & 0x0000ffff, amask
	.eval	(ABMASK >> 16) & 0xffff, bmask
	.eval	bmask & ~(C62_B15 >> 16), bmask		; don't restore B15
	.eval	CMASK, cmask

	.eval	0, C62_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	C62_A0 | C62_A1, amask
	    .eval	a_bitcount + 2, a_bitcount
	.elseif	(a_bitcount = 1)
	    .if	(amask & C62_A0)
		.eval	amask | C62_A1, amask
	    .eval	a_bitcount + 1, a_bitcount
	    .else
		.eval	amask | C62_A0, amask
	    .eval	a_bitcount + 1, a_bitcount
	    .endif
	.endif

	; make sure at least one B register is specified
	.if	(bmask = 0)
	    .eval	(C62_B0 >> 16) & 0xffff, bmask
	    .eval	b_bitcount + 1, b_bitcount
	.endif

	.eval	a_bitcount + b_bitcount + c_bitcount, ones

	.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 - 1, offset

	; 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

	; C62_save saves the B temp register before the A temp register
	.eval	offset, tmpb_offset
	.eval	offset - 1, offset
	.eval	offset, tmpa_offset
	.eval	offset - 1, offset

	mv	SP, SPA						; CODE

	;
	; Try to set up some advanced loads for control registers
	; to reduce load latency
	;
	.eval	a_bitcount + b_bitcount, bitcount
	.if	(c_bitcount > 1)
	    .eval	offset - bitcount, 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

	.elseif	(c_bitcount = 1)
	    .eval	offset - bitcount, cr0_offset
	    .eval	4 - bitcount, nop_count

	    ldw	*+SPB[cr0_offset], TMPB				; CODE

	.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[offset], b:bitn_b:		; CODE
||		ldw	*+SPA[offset - 1], a:bitn_a:		; CODE

		.eval	offset - 2, offset
		.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

		ldw	*+SP[offset], :reg::bitn_next:		; CODE

		.eval	offset - 1, offset
	    .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
		.eval	offset - 1, offset
	    .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
		.eval	offset - 2, offset
	    .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[offset], TMPB			; CODE
||		ldw	*+SPA[offset - 1], TMPA			; CODE
		nop	4					; CODE
		mvc	TMPB, creg0				; CODE
||		mv	TMPA, TMPB				; CODE
		mvc	TMPB, creg1				; CODE

		.eval	offset - 2, offset
	    .elseif	(c_bitcount = 1)
		FIRST_BIT_NUM	cmask, bitn_c
		BIT_NUM_2_CREG	bitn_c, creg0
		.eval	cmask & ~(1 << bitn_c), cmask
		.eval	c_bitcount - 1, c_bitcount

		ldw	*+SPB[offset], TMPB			; CODE
		nop	4					; CODE
		mvc	TMPB, creg0				; CODE

		.eval	offset - 1, offset
	    .else
		.break
	    .endif
	.endloop

	ldw	*+SPA[tmpa_offset], TMPA			; CODE
||	ldw	*+SPB[tmpb_offset], TMPB			; CODE

⌨️ 快捷键说明

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