gigatron/rom/Contrib/at67/gbas/runtime/numeric_ROMv5a.i
2025-01-28 19:17:01 +03:00

274 lines
9.4 KiB
OpenEdge ABL

; do *NOT* use register4 to register7 during time slicing
intSrcA EQU register0
intSrcB EQU register1
intSrcX EQU register2
intSwap EQU register3
intSrcAddr EQU register8
intDigit EQU register9
intResult EQU register10
intNegative EQU register11
bcdLength EQU register8
bcdSrcAddr EQU register9
bcdDstAddr EQU register10
bcdSrcData EQU register11
bcdDstData EQU register11 ; alias to make code less confusing
bcdCarry EQU register12
bcdBorrow EQU register12 ; alias to make code less confusing
bcdValue EQU register0
bcdDigit EQU register1
bcdMult EQU register2
%SUB integerMin
integerMin STW intSrcB
LDW intSrcA
SUBW intSrcB
BLE integerMi_A
LDW intSrcB
RET
integerMi_A LDW intSrcA
RET
%ENDS
%SUB integerMax
integerMax STW intSrcB
LDW intSrcA
SUBW intSrcB
BGE integerMa_A
LDW intSrcB
RET
integerMa_A LDW intSrcA
RET
%ENDS
%SUB integerClamp
integerClamp STW intSrcB
LDW intSrcX
SUBW intSrcA
BGE integerCl_X
BRA integerCl_A0
integerCl_X LDW intSrcX
STW intSrcA
integerCl_A0 LDW intSrcA
SUBW intSrcB
BLE integerCl_A1
LDW intSrcB
RET
integerCl_A1 LDW intSrcA
RET
%ENDS
%SUB integerStr
; converts a string to a +/- integer, assumes string pointer is pointing to first char and not the string length, (no overflow or underflow checks)
integerStr LDI 0
ST intNegative
STW intResult
LDW intSrcAddr
PEEK
SUBI 45 ; -ve
BNE integerS_loop
LDI 1
ST intNegative
INC intSrcAddr ; skip -ve
integerS_loop LDW intSrcAddr
PEEK
SUBI 48 ; str[i] - '0'
BLT integerS_neg
STW intDigit
SUBI 9
BGT integerS_neg
LDW intResult
LSLW
LSLW
ADDW intResult
LSLW
ADDW intDigit
STW intResult ; result = result*10 + digit
INC intSrcAddr
BRA integerS_loop
integerS_neg LD intNegative
BEQ integerS_exit
LDI 0
SUBW intResult ; result *= -1
RET
integerS_exit LDW intResult
RET
%ENDS
; bcd values are stored unpacked lsd to msd
%SUB bcdAdd
bcdAdd ST bcdLength
LDI 0
STW bcdCarry
bcdA_loop LDW bcdDstAddr
PEEK ; expects unpacked byte values 0 to 9
STW bcdDstData
LDW bcdSrcAddr
PEEK ; expects unpacked byte values 0 to 9
ADDW bcdDstData
ADDW bcdCarry
STW bcdDstData
SUBI 10 ; no handling of values > 9
BLT bcdA_nc
STW bcdDstData
LDI 1
BRA bcdA_cont
bcdA_nc LDI 0
bcdA_cont STW bcdCarry
LDW bcdDstData
POKE bcdDstAddr ; modifies dst bcd value
INC bcdDstAddr
INC bcdSrcAddr
LD bcdLength
SUBI 1
ST bcdLength ; expects src and dst lengths to be equal
BGT bcdA_loop
RET
%ENDS
; bcd values are stored unpacked lsd to msd
%SUB bcdSub
bcdSub ST bcdLength
LDI 0
STW bcdBorrow
bcdS_loop LDW bcdSrcAddr
PEEK ; expects unpacked byte values 0 to 9
STW bcdSrcData
LDW bcdDstAddr
PEEK ; expects unpacked byte values 0 to 9
SUBW bcdSrcData
SUBW bcdBorrow
STW bcdDstData
BGE bcdS_nb
ADDI 10
STW bcdDstData
LDI 1
BRA bcdS_cont
bcdS_nb LDI 0
bcdS_cont STW bcdBorrow
LDW bcdDstData
POKE bcdDstAddr ; modifies dst bcd value
INC bcdDstAddr
INC bcdSrcAddr
LD bcdLength
SUBI 1
ST bcdLength ; expects src and dst lengths to be equal
BGT bcdS_loop
RET
%ENDS
%SUB bcdDigits
bcdDigits STW bcdMult
LDW bcdValue
bcdD_index SUBW bcdMult
BLT bcdD_cont
STW bcdValue
INC bcdDigit ; calculate digit
BRA bcdD_index
bcdD_cont LD bcdDigit
POKE bcdDstAddr ; store digit
LDW bcdDstAddr
SUBI 1
STW bcdDstAddr
LDI 0
ST bcdDigit ; reset digit
bcdD_exit RET
%ENDS
%SUB bcdInt
; create a bcd value from a +ve int, (max 42767)
bcdInt STW bcdValue
PUSH
LDW bcdDstAddr
ADDI 4
STW bcdDstAddr ; bcdDstAddr must point to >= 5 digit bcd value
LDI 0
STW bcdDigit
LDWI 10000
CALLI bcdDigits
LDWI 1000
CALLI bcdDigits
LDI 100
CALLI bcdDigits
LDI 10
CALLI bcdDigits
LD bcdValue
POKE bcdDstAddr
POP
RET
%ENDS
; bcd values are stored unpacked lsd to msd
; cmp expects addrs to be pointing to msd!
%SUB bcdCmp
bcdCmp ST bcdLength
bcdCmp_loop LDW bcdDstAddr
PEEK ; expects unpacked byte values 0 to 9
STW bcdDstData
LDW bcdSrcAddr
PEEK ; expects unpacked byte values 0 to 9
SUBW bcdDstData
BGT bcdC_gt
BLT bcdC_lt
PUSH
CALLI bcdCmpExt
POP
BGT bcdCmp_loop
LDI 0
RET
bcdC_gt LDI 1
RET
bcdC_lt LDWI -1
RET
%ENDS
%SUB bcdCmpExt
bcdCmpExt LDW bcdDstAddr
SUBI 1
STW bcdDstAddr
LDW bcdSrcAddr
SUBI 1
STW bcdSrcAddr
LD bcdLength
SUBI 1
ST bcdLength ; expects src and dst lengths to be equal
RET
%ENDS
%SUB bcdCpy
bcdCpy ST bcdLength
bcdCpy_loop LDW bcdSrcAddr
PEEK
POKE bcdDstAddr
INC bcdSrcAddr
INC bcdDstAddr
LD bcdLength
SUBI 1
ST bcdLength ; expects src and dst lengths to be equal
BGT bcdCpy_loop
RET
%ENDS