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

📄 fpp04.s43

📁 MSP430浮点库
💻 S43
📖 第 1 页 / 共 2 页
字号:
     ELSE                             ; End of software multiplication loop
;
; Hardware Multiplication sequences:
;
;			       31		 0
;			      +----+----+----+----+
;			      |    mid1 x lsb2	  |
;			      +----+----+----+----+
;			      +----+----+----+----+
;			      |    lsb1 x mid2	  |
;		     47       +----+----+----+----+
;		    +----+----+----+----+
;		    | 00 | msb1 x lsb2	|
;		    +----+----+----+----+
;		    +----+----+----+----+
;		    | 00 | lsb1 x msb2	|
;		    +----+----+----+----+
;		    +----+----+----+----+
;		    |	 mid1 x mid2	|
;	   63	    +----+----+----+----+
;	  +----+----+----+----+
;	  | 00 | msb1 x mid2  |
;	  +----+----+----+----+
;	  +----+----+----+----+
;	  | 00 | mid1 x msb2  |
;	  +----+----+----+----+
;	  +----+----+
;	  |msb1xmsb2|
;	  +----+----+
; ----------------------------------------------------
;	  +----+----+----+----+----+----+
;	  |   MSB   |	MID   |   LSB	| RESULT_xxx
;	  +----+----+----+----+----+----+
;
     IF DOUBLE = 1                      ; .DOUBLE MPY sequence
	MPY	ARG2_LSB,ARG1_MID	;	      XXXX XXXX
	MAC	ARG1_LSB,ARG2_MID	;	    c XXXX XXXX
	ADD	&ResHi,RESULT_LSB	;
	ADDC	&SumExt,RESULT_MID	;
	MPY	ARG1_MSB,ARG2_LSB	;	 00XX XXXX
	MAC	ARG1_LSB,ARG2_MSB	;	 0XXX XXXX
	MAC	ARG1_MID,ARG2_MID	;      c XXXX XXXX
	ADD	&ResLo,RESULT_LSB	;
	ADDC	&ResHi,RESULT_MID	;
	ADDC	&SumExt,RESULT_MSB	;
	MPY	ARG1_MSB,ARG2_MID	;   00XX XXXX
	MAC	ARG2_MSB,ARG1_MID	;   0XXX XXXX
	ADD	&ResLo,RESULT_MID	;
	ADDC	&ResHi,RESULT_MSB	;
	MPY	ARG1_MSB,ARG2_MSB     ;0000 XXXX
	ADD	&ResLo,RESULT_MSB	;    MSB  MID  LSB  ---
;
     ELSE                               ; .FLOAT MPY sequence
;
;		     31 	       0
;		    +----+----+----+----+
;		    |	 lsb1 x lsb2	|
;	   47	    +----+----+----+----+
;	  +----+----+----+----+
;	  | 00 | lsb1 x msb2  |
;	  +----+----+----+----+
;	  +----+----+----+----+
;	  | 00 | msb1 x lsb2  |
;	  +----+----+----+----+
;	  +----+----+
;	  |msb1xmsb2|
;	  +----+----+
; ------------------------------------------
;	  +----+----+----+----+
;	  |   MSB   |	LSB   | RESULT_xxx
;	  +----+----+----+----+
;
; NOTE: The  MPY   ARG1_LSB,ARG2_MSB  is replaced by a
;	     MOV   ARG2_MSB,&0138h    due to speed reasons
;
	MPY	ARG1_LSB,ARG2_LSB	;	      XXXX XXXX
	MOV	&ResHi,RESULT_LSB	;
	MOV	ARG2_MSB,&0138h 	;!!	 00XX XXXX
	MAC	ARG2_LSB,ARG1_MSB	;	 0XXX XXXX
	ADD	&ResLo,RESULT_LSB	;
	ADDC	&ResHi,RESULT_MSB	;
	MPY	ARG1_MSB,ARG2_MSB	;   0000 XXXX
	ADD	&ResLo,RESULT_MSB	;	  MSB  LSB  ---
     ENDIF
;
; The hardware multiplier result is located falsely:
; Shift right result 8 bits to get FPP mantissa format (shown for .DOUBLE):
; .FLOAT   1234 5678	  -> 0012 3456 xx__
; .DOUBLE  1234 5678 9ABC -> 0012 3456 789A xx__   (xx in HELP for rounding)
;
	SWPB	RESULT_LSB		; 9ABC -> BC9A
	MOV	RESULT_LSB,HELP 	; BC9A (contains LSB-1, LSB-2)
	MOV.B	RESULT_LSB,RESULT_LSB	; 009A
     IF DOUBLE = 1
	MOV.B	RESULT_MID,COUNTER	; 0078 -> COUNTER
	SWPB	COUNTER 		; 7800
	ADD	COUNTER,RESULT_LSB	; 789A -> RESULT_LSB
	SWPB	RESULT_MID		; 7856
	MOV.B	RESULT_MID,RESULT_MID	; 0056
	MOV.B	RESULT_MSB,COUNTER	; 0034 -> COUNTER
	SWPB	COUNTER 		; 3400
	ADD	COUNTER,RESULT_MID	; 3456 -> RESULT_MID
     ELSE
	MOV.B	RESULT_MSB,COUNTER	;
	SWPB	COUNTER 		;
	ADD	COUNTER,RESULT_LSB	;
     ENDIF
	SWPB	RESULT_MSB		; 3412
	MOV.B	RESULT_MSB,RESULT_MSB	; 0012 -> RESULT_MSB
     ENDIF                              ; End of hardware MPY sequence
;
; Common completion part:
; Result in RESULT: 40 0000 to FF FFFE (40 0000 0000 to FF FFFF FFFE
; Normalization is made to get MSB = 1 and rounding with LSB-1
;
	TST.B	RESULT_MSB	; If hidden Bit is not set
	JGE	FM5		; then jump
	INC.B	3(SP)		; New RESULT-exponent: hidden bit = 1
	JNC	FM6
	JMP	DBL_OVERFLOW	; Exponent-overflow (FF to 00)
FM5	RLC	HELP		; LSB-1 of RESULT to carry
	RLC	RESULT_LSB	; to format the mantissa
     IF DOUBLE=1
	RLC	RESULT_MID
     ENDIF
	RLC.B	RESULT_MSB

; round with LSB-1 resp. LSB-2

FM6	RLC	HELP		; Next LSB-1 to CARRY
	JMP	NORMLZ		; Go to common completion part
;=============================================================================
; Floating Point Division       Result on TOS = @RPRES/@RPARG

; Check if dividend is zero: result is zero
; Check if divisor  is zero: result is signed max. number (overflow error)

FLT_DIV CALL	#INIMD		; Read arguments, zero test, sign prep.
;	MOV.B	HELP,2(SP)	; Sign of result in HELP.7
	BIT	#1,COUNTER	; If argument1 is zero:
	JNZ	EXIT		; Result is zero
	BIT	#2,COUNTER	; If argument2 is zero:
	JNZ	DIV_BY_ZERO	; signed overflow

; Calculate the exponent of the result by subtraction of the exponents
; of argument1 and argument2

	MOV	ARG1_MSB,HELP	; Fetch exponent of argument 1
	BIS	#0FFh,HELP	; Avoid influence from mantissa
	SUB	ARG2_MSB,HELP	; argument 1 - argument 2 -> HELP
	JC	FD1		;
	ADD	#8000h,HELP	; Toggle sign bit of exponent
	JC	FD2		;
	JMP	DBL_UNDERFLOW	; Underflow: result = 0
FD1	ADD	#8000h,HELP	; Toggle sign bit of exponent
	JC	DBL_OVERFLOW	; Overflow: largest signed number
FD2	SWPB	HELP		;
	MOV.B	HELP,3(SP)	; Save exponent of result

; Division-loop for mantissa calculation
;
	BIS.B	#80h,ARG2_MSB	      ; Set hidden bit argument 2
	BIS.B	#80h,ARG1_MSB	      ; Set hidden bit argument 2
	MOV.B	#ML,COUNTER	      ; Mantissa length to COUNTER

FD4	SUB	ARG2_LSB,ARG1_LSB     ; ARG1 - ARG2
     IF DOUBLE=1
	SUBC	ARG2_MID,ARG1_MID     ;
     ENDIF
	SUBC	ARG2_MSB,ARG1_MSB     ;
	JC	FD3		      ; ARG1 >= ARG2
	ADD	ARG2_LSB,ARG1_LSB     ; ARG1 < ARG2: restore ARG1
     IF DOUBLE=1
	ADDC	ARG2_MID,ARG1_MID     ;
     ENDIF
	ADDC	ARG2_MSB,ARG1_MSB     ;
	CLRC			      ;
FD3	RLC	RESULT_LSB	      ; Carry to result
     IF DOUBLE=1
	RLC	RESULT_MID
     ENDIF
	RLC	RESULT_MSB
	RLA	ARG1_LSB	      ;
     IF DOUBLE=1
	RLC	ARG1_MID	      ;
     ENDIF
	RLC	ARG1_MSB	      ;
	DEC.B	COUNTER 	      ; If division is not finished:
	JNZ	FD4		      ; continue loop

	TST.B	RESULT_MSB	      ; Hidden bit set (normalized)?
	JN	FD5		      ; Yes
	INC.B	COUNTER 	      ; No, go through loop once more
	DEC.B	3(SP)		      ; Correct exponent
	JHS	FD4		      ;
	JMP	DBL_UNDERFLOW	      ; Underflow: result = 0
;
; Result in RESULT: 80 0000 to FF FFFE (80 0000 0000 to FF FFFF FFFE)
; Rounding is made with LSB-1
;
FD5	SUBC	ARG2_LSB,ARG1_LSB     ; Calculate LSB-1
     IF DOUBLE=1
	SUBC	ARG2_MID,ARG1_MID     ;
     ENDIF
	SUBC	ARG2_MSB,ARG1_MSB     ; Rounding info in Carry
;==============================================================================
; Common completion part: Mantissa in RESULT_xxx
;			Sign	 in 2(SP) MSB	(hidden bit)
;			Exponent in 3(SP)
;			LSB-1	 in Carry for rounding
;
; Rounding info in carry, no error, sign and exponent get inserted
;
NORMLZ	ADC	RESULT_LSB	      ; Round mantissa with LSB-1
     IF DOUBLE=1
	ADC	RESULT_MID
     ENDIF
	ADC.B	RESULT_MSB
	ADC.B	3(SP)		      ; Round exponent with Carry
	JC	DBL_OVERFLOW	      ; Exponent overflow 0FFh to 00h
;
; No rounding, no error, sign and exponent get inserted
;
DDRNZ	BIC.B	#80h,RESULT_MSB       ; Clear hidden Bit (and higher byte)
	BIS	2(SP),RESULT_MSB      ; Insert exponent and sign bit
;
; All done, result is placed on top of stack (TOS)
;
EXIT	CLR	HELP		      ; N=0, no error
EXITE	MOV	RESULT_MSB,2(SP)      ; Result (RESULT) to Stack
     IF DOUBLE=1
	MOV	RESULT_MID,4(SP)      ;
	MOV	RESULT_LSB,6(SP)      ;
     ELSE
	MOV	RESULT_LSB,4(SP)      ;
     ENDIF
;
; Termination subroutine: error code in HELP (0 = no error)
; Subroutine can be used by user written FP subroutines
;
FLT_END MOV	SP,RPRES	      ; Result pointer to result
	ADD	#2,RPRES	      ; Correction (SP points to return addr.)
	MOV	RPRES,RPARG	      ; Argument pointer to result
	BIC	#FN+FZ+FC,SR	      ; Clear N,Z and C in SR
	BIS	HELP,SR 	      ; Set SR according to error status
	RET			      ; Stored in HELP
;==============================================================================
; Floating Point Error Handling: underflow, overflow, division by zero
;
;  +--------------------+-------------------+------------------------+
;  | Error		|    Statusregister |	 Result 	     |
;  +--------------------+-------------------+------------------------+
;  | No error		|    N=0, C=x, Z=x  |	 xxxx xxxx xxxx      |
;  | Overflow positive	|    N=1, C=1, Z=1  |	 FF7F FFFF FFFF      |
;  | Overflow negative	|    N=1, C=1, Z=0  |	 FFFF FFFF FFFF      |
;  | Underflow		|    N=1, C=0, Z=0  |	 0000 0000 0000      |
;  | Division by zero	|    N=1, C=0, Z=1  |	 FF7F FFFF FFFF or   |
;  |			|		    |	 FFFF FFFF FFFF      |
;  +--------------------+-------------------+------------------------+
;
DBL_UNDERFLOW			; Underflow: Result = 0
     IF SW_UFLOW=1              ; Error only if SW_UFLOW = 1
	MOV	#FN,HELP	; Error code N=1, C=0, Z=0
	JMP	RES01
     ENDIF
RES0	CLR	HELP		; Result is 0: N = 0 (No error)
RES01	CLR	RESULT_MSB	; Errorfree zero result
     IF DOUBLE=1
	CLR	RESULT_MID
     ENDIF
	CLR	RESULT_LSB
	JMP	EXITE		; To normal completion

DBL_OVERFLOW			; Overflow: Insert largest signed number
	MOV	#FN+FC,HELP	; Error code N=1, C=1, Z=Sign
	TST.B	2(SP)		; Sign of result is stored here
	JN	L$1		; Neg. sign: Z=0
	BIS	#FZ,HELP	; Pos. sign: Z=1
L$1	MOV	#0FF7Fh,RESULT_MSB
	BIS	2(SP),RESULT_MSB      ; Insert sign
     IF DOUBLE=1
	MOV	#0FFFFh,RESULT_MID    ;
     ENDIF
	MOV	#0FFFFh,RESULT_LSB    ;
	JMP	EXITE		      ;

DIV_BY_ZERO                  ; Division by 0: Insert largest signed number
        MOV     #FN+FZ,HELP  ; Error code N=1, C=0, Z=1
        JMP     L$1          ; Result like overflow

;=============================================================================
; Floating Point Comparison
;
;  Call of the Comparison:
;
;     MOV     #ARG1,RPRES     ; Pointer to Argument 1 MSBs
;     MOV     #ARG2,RPARG     ; Pointer to Argument 2 MSBs
;     CALL    #FLT_CMP	      ; Comparison call
;     JEQ     EQUAL	      ; If arg1 = arg2
;     JHS     A1_GT_A2	      ; If arg1 > arg2
;     ...     ...	      ; If arg1 < arg2
;
;  The result of the compare is written to the status register SR and HELP
; RPARG and RPRES point with SP to actual result area (normal return)
;
;  +--------------------------+------------------------------+
;  | Condition		      |    Statusregister	     |
;  +--------------------------+------------------------------+
;  | Argument 1 =  Argument 2 | ZERO = 1, CARRY = 1, NEG = 0 |
;  | Argument 1 <  Argument 2 | ZERO = 0, CARRY = 0, NEG = 0 |
;  | Argument 1 >  Argument 2 | ZERO = 0, CARRY = 1, NEG = 0 |
;  +--------------------------+------------------------------+
;
FLT_CMP EQU     $
        IF     DOUBLE=1
        MOV     @R5+,ARG2_MSB           ; Copy argument 2 to regs
        MOV     @R5+,ARG2_MID
        MOV     @R5+,ARG2_LSB
        MOV     @R11+,ARG1_MSB          ; Copy argument 1 to regs
        MOV     @R11+,ARG1_MID
        MOV     @R11+,ARG1_LSB
        ELSE
        MOV     @R5+,ARG2_MSB           ; Copy argument 2 to regs
        MOV     @R5+,ARG2_LSB
        MOV     @R9+,ARG1_MSB           ; Copy argument 1 to regs
        MOV     @R9+,ARG1_LSB
        ENDIF
;
	TST.B	ARG2_MSB		; Arg1, Arg2: check signs
	JN	FC2			; Arg2 = neg.
	TST.B	ARG1_MSB		; Arg2 = pos.
	JN	A1LTA2			; Arg2 = +, Arg1 = -: A1 < A2
	CMP	ARG2_MSB,ARG1_MSB	; Arg1 = +, Arg2 = +
	JNE	FC4			; Check values
        IF     DOUBLE=1
	CMP	ARG2_MID,ARG1_MID
	JNE	FC4
        ENDIF
	CMP	ARG2_LSB,ARG1_LSB
	JEQ	A1EQA2			; Arg1 = Arg2
FC4	JLO	A1LTA2			; Arg1 < Arg2
A1GTA2	MOV	#FC,HELP		; Carry = 1, Zero = 0
	JMP	FLT_END 		; To completion part
;
FC2	TST.B	ARG1_MSB		; Arg2 = -
	JGE	A1GTA2			; Arg1 = +: A1 > A2
	CMP	ARG2_MSB,ARG1_MSB	; Arg1 = -, Arg2 = -
	JNE	FC5			; Check values
        IF     DOUBLE=1
	CMP	ARG2_MID,ARG1_MID
	JNE	FC5
        ENDIF
	CMP	ARG2_LSB,ARG1_LSB
	JEQ	A1EQA2			; Arg1 = Arg2
FC5	JLO	A1GTA2			; Arg1 > Arg2
A1LTA2	CLR	HELP			; Carry = 0, Zero = 0
	JMP	FLT_END 		; Modify SR with HELP
A1EQA2	MOV	#FZ+FC,HELP		; Arg1 = Arg2: Z = C = 1
	JMP	FLT_END 		; To completion part
;=============================================================================
; Floating Point Subroutines
;
; INIMD creates the sign of the result for MPY and DIV in HELP.7
; INIAS is used too

INIMD   EQU     $
        IF      DOUBLE=1
        MOV.B   @R11,HELP       ; Calculate sign of result:
        ELSE
        MOV.B   @R9,HELP
        ENDIF
        XOR.B   @R5,HELP        ; Sign arg2 .xor. sign arg1
	AND.B	#080h,HELP	; Leave only the calculated sign

; INIAS  loads the arguments to ARG1_xxx and ARG2_xxx
;      clears the variables RESULT_xxx
;      tests the arguments to zero and stores the result in
;      COUNTER - if argument1 is zero: COUNTER.0 is 1
;		 if argument2 is zero: COUNTER.1 is 1
;		 else COUNTER is 0

INIAS   EQU     $
        IF      DOUBLE=1
        MOV     @R5+,ARG2_MSB   ; Copy argument 2 to regs
        MOV     @R5+,ARG2_MID
        MOV     @R5,ARG2_LSB
        MOV     @R11+,ARG1_MSB  ; Copy argument 1 to regs
        MOV     @R11+,ARG1_MID
        MOV     @R11,ARG1_LSB
        ELSE
        MOV     @R5+,ARG2_MSB   ; Copy argument 2 to regs
        MOV     @R5,ARG2_LSB
        MOV     @R9+,ARG1_MSB   ; Copy argument 1 to regs
        MOV     @R9,ARG1_LSB
        ENDIF
        MOV.B   HELP,4(SP)      ; Insert sign
	CLR	RESULT_MSB	; Clear RESULT
     IF DOUBLE=1
	CLR	RESULT_MID	;
     ENDIF
	CLR	RESULT_LSB	;
;
	CLR	COUNTER 	; Clear COUNTER
	TST	ARG1_MSB	; If ARG1 = 0:
	JNZ	FNZ1		; set LSB of COUNTER
     IF DOUBLE=1
	TST	ARG1_MID	;
	JNZ	FNZ1		;
     ENDIF
	TST	ARG1_LSB	;
	JNZ	FNZ1		;
	BIS	#1,COUNTER	; ARG1 = 0
;
FNZ1	TST	ARG2_MSB	; If ARG2 = 0:
	JNZ	FNZ2		; set LSB+1 of COUNTER
     IF DOUBLE=1
	TST	ARG2_MID	;
	JNZ	FNZ2		;
     ENDIF
	TST	ARG2_LSB	;
	JNZ	FNZ2		;
	BIS	#2,COUNTER	; ARG2 = 0
FNZ2	RET			; Zero info in COUNTER, sign in HELP
;
;  END OF THE FLOATING POINT BASIC ARITHMETIC OPERATIONS

⌨️ 快捷键说明

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