📄 bbu_library.s
字号:
; This subroutine performs an unsigned 32 bit divide. Users are encouraged to
; use the BBU_U32Divide routine in the BBU_Math.s file in place of this one for
; all new code. This older routine may be eliminated in the future.
;
; PARAMETER PASSING:
;
; INPUT - r0 contains the dividend - (destroyed!)
; INPUT - r1 contains the divisor - (destroyed!)
;
; OUTPUT - r0 will contain the result
; OUTPUT - r1 will contain the remainder
;
BBU_U32Div FUNCTION
stmfd sp!, {r2-r7, lr} ; Save r2-r7, & link reg on stack
mov r6, r0 ; Copy dividend ro r6
mov r7, r1 ; Copy divisor to r7
mov r0, #0 ; Clear result
mov r1, #0 ; Clear remainder
mov r5, #32 ; load r5 with loop count
mrs r4, CPSR ; Get CPSR
bic r4, r4, #0x20000000 ; Clear carry bit
;
; Main division loop begins here
;
10 msr CPSR_f, r4 ; write flags back
adcs r0, r0, r0 ; Shift C bit into result
adcs r6, r6, r6 ; Rotate r6 left 1 bit through C bit
adcs r1, r1, r1 ; Rotate data left, into remainder
subs r1, r1, r7 ; Subtract dividend
blt %F12 ; Branch if negative
mrs r4, CPSR ; Get CPSR
orr r4, r4, #0x20000000 ; Set carry bit
b %F14 ; Check loop count
12 add r1, r1, r7 ; Restore remainder
mrs r4, CPSR ; Get CPSR
bic r4, r4, #0x20000000 ; Clear carry bit
14 subs r5, r5, #1 ; decrement loop count
bne %B10 ; Loop until done
;
; Shift the last bit into the result and return to caller
;
msr CPSR_f, r4 ; write flags back
adcs r0, r0, r0 ; Shift C bit into result
adcs r6, r6, r6 ; Rotate r6 left 1 bit through C bit
ldmfd sp!, {r2-r7, pc} ; Restore r2-r7 and return to caller
ENDFUNC
;
;*********************************************************************************
;
; **************
; * *
; * BBU_getnum * Subroutine "BBU Get Number"
; * *
; **************
;
; Last Update: 27-Jun-2006
;
; This subroutine searches the BBU input buffer (BBU_ibuf) for a valid hex or
; decimal value. The values are unsigned.
;
; The hex value can range from 0x0 to 0xFFFFFFFF
; The decimal value can range 0 to 4294967295
; Note: A leading decimal point for a decimal number is optional (legacy code)
;
; PARAMETER PASSING:
;
; INPUT: r0 = Address of the first digit of the number
;
; OUTPUT: r0 = Address of next byte (following the number)
; r1 = Number detected in binary format
; r2 = Decoded number status
; bit 0 - 0=No error, 1=Syntax error
; bit 1 - 0=No error, 1= Number too big
; bit 2 - reserved - returned as 0
; bit 3 - reserved - returned as 0
; bit 4 - 0=Decimal input, 1=Hex input
;
BBU_getnum FUNCTION
stmfd sp!, {r3-r4, lr} ; Save used registers, & link reg on stack
mov r1, #0 ; Set returned number to zero for now
mov r2, #0 ; Clear return code - No error
;
; The first byte should be pointing to the first digit before this routine
; is called.
;
ldrb r3, [r0], #1 ; Get the first byte
cmp r3, #'0' ; Is this byte a <zero>?
beq %F10 ; Yes - check for "0X" (Hex number) input
;
; If the byte is in the range 1-9, Assume a decimal number is being entered
;
cmp r3, #'1' ; Compare byte to ASCII '1'
blt %F30 ; Syntax Error if .LT. ASCII 1
cmp r3, #'9' ; Compare byte to ASCII '9'
bgt %F30 ; Syntax Error if .GT. ASCII 9
sub r0, r0, #1 ; In decimal range - reset pointer (back up 1 byte)
b %F20 ; Decode as a decimal number
;
; A <zero> was found - If the next byte is an "X", assume the user is
; inputting a hex value. If not, check the byte preceding the zero to
; see that it is either a space or the start of the input buffer.
;
10 ldrb r3, [r0], #1 ; Get the next byte in the buffer
cmp r3, #'X' ; is this byte an "X"?
beq %F15 ; Yes - assume it is a hex number
sub r0, r0, #2 ; No - back up two bytes (points to ASCII zero byte)
b %F20 ; No - assume it's a decimal number
;
; A "0X" (zero, X) sequence was found - try to decode the following
; bytes as if a hex number being entered.
;
15 bic r2, r2, #8 ; Indicate possible hex number found
mov r4, #0 ; Zero out a byte counter
16 ldrb r3, [r0], #1 ; Get next byte in the buffer
cmp r3, #0 ; Is this a NULL byte?
beq %F35 ; Yes - return to caller
cmp r3, #',' ; Is this byte a comma?
beq %F35 ; Yes - return to caller
cmp r3, #' ' ; Is this byte a <space>?
beq %F35 ; Yes - return to caller
cmp r3, #'/' ; Is this byte a <forward slash>?
beq %F35 ; Yes - return to caller
cmp r3, #'0' ; Compare to ASCII <zero>
blt %F30 ; Lower - Syntax error!
cmp r3, #'F' ; Compare to ASCII "F"
bgt %F30 ; Higher - Syntax error!
;
; ASCII value is between ASCII<zero> and ASCII<F> but the code still
; needs to weed out anything above ASCII<9> and below ASCII<A>
;
cmp r3, #0x3A ; If less than this value, byte is 0-9
sublt r3, r3, #'0' ; subtract ASCII<zero> if byte is in the 0-9 range...
blt %F17 ; ...and add to r1
cmp r3, #0x40 ; If greater than this value, byte is A-F
subgt r3, r3, #0x37 ; Subtract 0x37 to make byte binary...
bgt %F17 ; ...and add to r1
b %F30 ; Otherwise - Syntax error!
17 mov r1, r1, LSL #4 ; Shift r1 left one nibble
orr r1, r1, r3 ; Add in data in r3
add r4, r4, #1 ; Increment byte count
cmp r4, #9 ; 9th digit?
orreq r2, r2, #2 ; Set "number too large" bit
beq %F36 ; ...and exit
b %B16 ; Size is OK - Get next byte
;
; Code picks up here if a decimal number was detected.
; Start looking for numeric (0-9) digits to follow
;
20 ldrb r3, [r0], #1 ; Get the next byte
cmp r3, #0 ; Is this a NULL byte?
beq %F35 ; Yes - return to caller
cmp r3, #' ' ; Is this a <space>?
beq %F35 ; YES - return to caller
cmp r3, #',' ; Is this byte a comma?
beq %F35 ; Yes - return to caller
cmp r3, #'/' ; Is this byte a <forward slash>?
beq %F35 ; Yes - return to caller
cmp r3, #'0' ; Compare to ASCII <zero>
blt %F30 ; Lower - Syntax error!
cmp r3, #'9' ; Compare to ASCII "9"
bgt %F30 ; Higher - Syntax error!
;
; Valid Digit entered - add it to the value in r6
;
ldr r4, =0x19999999 ; Number can't be higher than this...
cmp r1, r4 ; ...before the multiply by 10
orrgt r2, r2, #2 ; Set "number too large" (to multiply by 10)
bgt %F36 ; ...and exit
mov r4, #10 ; If OK - Set up multiplier
muls r1, r1, r4 ; Multiply r6 by 10
sub r3, r3, #'0' ; Turn byte into binary...
adds r1, r1, r3 ; ...and add it to r1
orrcs r2, r2, #2 ; Set "number too large" bit if carry is set
bcs %F36 ; ...and exit
b %B20 ; OK so far - Get another byte
;
; Syntax error detected in numeric input
;
30 orr r2, r2, #1 ; Set Syntax error bit
mov r1, #0 ; Clear returned number
;
; Subroutine return path
;
35 sub r0, r0, #1 ; Point to next byte AFTER the number
36 ldmfd sp!, {r3-r4, pc} ; Restore r2-r4, & return to caller
ENDFUNC
;
;*********************************************************************************
;
; **************
; * *
; * BBU_ENCODE * Encodes a 32 bit binary value into an decimal ASCII string
; * * ***** Use only for BBU TIME command *****
; ************** ***** Use BBU_UDecToAscii routine for all other cases! *****
;
; Last Update: 3-Aug-1004
;
; PARAMETER PASSING:
;
; INPUT - r0 contains number to encode (destroyed)
; r1 contains address where output is to be written (updated)
; r2 contains formatting information as follows: (preserved)
; bits 3:0 = number of digits (1->16)
; bits 5:4 = 0-> left pad with NULLs
; 1-> left pad with zeros
; 2-> left pad with spaces
;
;
; OUTPUT - NONE
;
BBU_ENCODE FUNCTION
stmfd sp!, {r3, r4, r5, lr}; Save r3-r5, & link reg on stack
mov r3, r1 ; Save a copy of the pointer
and r4, r2, #0xF ; Number of digits in r4
mov r2, r2, LSR #4 ; Shift r2 right 4 bits
and r2, r2, #3 ; Save bits 1:0
mov r5, #0 ; Zero out a work register
;
; Get 1,000,000,000s digit
;
ldr r1, =1000000000 ; Load divisor
bl BBU_U32Div ; Perform unsigned 32 bit divide
cmp r4, #10 ; Display 10 digits or more?
blt %F41 ; No - don't output this digit
bl BBU_FMTDIG ; Yes - Format output byte
;
; Get 100,000,000s digit
;
41 mov r0, r1 ; Copy remainder to r0
ldr r1, =100000000 ; Load divisor
bl BBU_U32Div ; Perform unsigned 32 bit divide
cmp r4, #9 ; Display 9 digits or more?
blt %F42 ; No - don't output this digit
bl BBU_FMTDIG ; Yes - Format output byte
;
; Get 10,000,000s digit
;
42 mov r0, r1 ; Copy remainder to r0
ldr r1, =10000000 ; Load divisor
bl BBU_U32Div ; Perform unsigned 32 bit divide
cmp r4, #8 ; Display 8 digits or more?
blt %F43 ; No - don't output this digit
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -