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

528 lines
17 KiB
OpenEdge ABL

; do *NOT* use register4 to register7 during time slicing
mathX EQU register8
mathY EQU register9
mathSum EQU register12
mathRem EQU register12
mathMask EQU register13
mathSign EQU register14
mathQuot EQU register15
mathShift EQU register15
mathBase EQU register10
mathPow EQU register11
mathResult EQU register14
%SUB sign
sign LDW mathX
BLE sign_le
LDI 1
RET
sign_le BLT sign_lt
LDI 0
RET
sign_lt LDWI 0xFFFF
RET
%ENDS
%SUB absolute
absolute LDW mathX
BGE abs_exit
LDI 0
SUBW mathX
abs_exit RET
%ENDS
%SUB power16bit
; accumulator = mathX ** mathY, (result 16bit)
power16bit LDW mathX
BNE power16_cont0
LDI 0
RET
power16_cont0 SUBI 1
BNE power16_cont1
LDI 1
RET
power16_cont1 LDW mathY
BNE power16_cont2
LDI 1
RET
power16_cont2 SUBI 1
BNE power16_cont3
LDW mathX ; return mathX
RET
power16_cont3 LDWI SYS_LSRW1_48
STW giga_sysFn ; setup right shift
LDW mathX
STW mathBase
LDW mathY
STW mathPow
LDI 1
STW mathResult
PUSH
LDWI power16bitExt
CALL giga_vAC
POP
RET
%ENDS
%SUB power16bitExt
power16bitExt PUSH
LDW mathPow
power16E_loop ANDI 1
BEQ power16E_skip
LDW mathBase
STW mathX
LDW mathResult
STW mathY
LDWI multiply16bit
CALL giga_vAC
STW mathResult ; mathResult = mathBase * mathResult
power16E_skip LDW mathBase
STW mathX
STW mathY
LDWI multiply16bit
CALL giga_vAC
STW mathBase ; mathBase = mathBase * mathBase
LDW mathPow
SYS 48
STW mathPow ; mathPow = mathPow / 2
BNE power16E_loop ; while mathPow > 0
POP
LDW mathResult
RET
%ENDS
%SUB multiply16bit
; accumulator = mathX * mathY, (result 16bit)
multiply16bit LDI 0
STW mathSum
LDW mathX
BEQ multiply16_exit ; if x=0 then return 0
LDWI SYS_LSRW1_48
STW giga_sysFn
LDW mathY
multiply16_loop BEQ multiply16_exit ; if y=0 then return
ANDI 1
BEQ multiply16_skip
LDW mathSum
ADDW mathX
STW mathSum ; mathSum += mathX
multiply16_skip LDW mathX
LSLW
STW mathX ; mathX = mathX <<1
LDW mathY
SYS 48
STW mathY ; mathY = mathY >>1
BRA multiply16_loop
%if TIME_SLICING
multiply16_exit PUSH
CALL realTimeStubAddr
POP
LDW mathSum
%else
multiply16_exit LDW mathSum
%endif
RET
%ENDS
%SUB multiply16bit_1
; accumulator = mathX * mathY, (result 16bit)
multiply16bit_1 LDI 0
STW mathSum
LDI 1
multiply161_loop STW mathMask
ANDW mathY
BEQ multiply161_skip
LDW mathSum
ADDW mathX
STW mathSum
multiply161_skip LDW mathX
ADDW mathX
STW mathX
LDW mathMask
ADDW mathMask
BNE multiply161_loop
%if TIME_SLICING
PUSH
CALL realTimeStubAddr
POP
%endif
LDW mathSum
RET
%ENDS
%SUB divide16bit
; accumulator:mathRem = mathX / mathY, (results 16bit)
divide16bit LDW mathX
XORW mathY
STW mathSign
LDW mathX
BGE divide16_pos0
LDI 0
SUBW mathX
STW mathX
divide16_pos0 LDW mathY
BGE divide16_pos1
LDI 0
SUBW mathY
STW mathY
divide16_pos1 LDI 0
STW mathRem
LDI 1
divide16_loop STW mathMask
LDW mathRem
LSLW
STW mathRem
LDW mathX
BGE divide16_incr
INC mathRem
divide16_incr LDW mathX
LSLW
STW mathX
LDW mathRem
SUBW mathY
BLT divide16_incx
STW mathRem
INC mathX
divide16_incx LDW mathMask
LSLW
BNE divide16_loop
%if TIME_SLICING
PUSH
CALL realTimeStubAddr
POP
%endif
LDW mathSign
BGE divide16_exit
LDI 0
SUBW mathX
RET
divide16_exit LDW mathX
RET
%ENDS
%SUB divide16bit_1
; accumulator:mathRem = mathX / mathY, (results 16bit)
divide16bit_1 LDI 0
STW mathQuot
STW mathRem
LDWI SYS_LSRW1_48
STW giga_sysFn
LDW mathX
XORW mathY
STW mathSign
LDW mathX
BGE divide161_pos0
LDI 0
SUBW mathX
STW mathX
divide161_pos0 LDW mathY
BGE divide161_pos1
LDI 0
SUBW mathY
STW mathY
divide161_pos1 LDWI 0x8000
divide161_loop STW mathMask
BEQ divide161_exit
LDW mathRem
LSLW
STW mathRem
LDW mathX
ANDW mathMask
BEQ divide161_skip1
INC mathRem
divide161_skip1 LDW mathRem
SUBW mathY
BLT divide161_skip2
STW mathRem
LDW mathQuot
ORW mathMask
STW mathQuot
divide161_skip2 LDW mathMask
SYS 48
BRA divide161_loop
%if TIME_SLICING
divide161_exit PUSH
CALL realTimeStubAddr
POP
LDW mathSign
%else
divide161_exit LDW mathSign
%endif
BLT divide161_sgn
LDW mathQuot
RET
divide161_sgn LDI 0
SUBW mathQuot
RET
%ENDS
%SUB rand16bit
rand16bit LDWI SYS_Random_34
STW giga_sysFn
SYS 34
RET
%ENDS
%SUB randMod16bit
randMod16bit PUSH
LDWI SYS_Random_34
STW giga_sysFn
SYS 34
STW mathX
LDWI divide16bit
CALL giga_vAC
LDW mathRem
POP
RET
%ENDS
%SUB shiftLeft4bit
shiftLeft4bit LDWI SYS_LSLW4_46
STW giga_sysFn
LDW mathShift
SYS 46
RET
%ENDS
%SUB shiftLeft8bit
shiftLeft8bit LDWI SYS_LSLW8_24
STW giga_sysFn
LDW mathShift
SYS 28
RET
%ENDS
%SUB shiftRight1bit
shiftRight1bit LDWI SYS_LSRW1_48
STW giga_sysFn
LDW mathShift
SYS 48
RET
%ENDS
%SUB shiftRight2bit
shiftRight2bit LDWI SYS_LSRW2_52
STW giga_sysFn
LDW mathShift
SYS 52
RET
%ENDS
%SUB shiftRight3bit
shiftRight3bit LDWI SYS_LSRW3_52
STW giga_sysFn
LDW mathShift
SYS 52
RET
%ENDS
%SUB shiftRight4bit
shiftRight4bit LDWI SYS_LSRW4_50
STW giga_sysFn
LDW mathShift
SYS 50
RET
%ENDS
%SUB shiftRight5bit
shiftRight5bit LDWI SYS_LSRW5_50
STW giga_sysFn
LDW mathShift
SYS 50
RET
%ENDS
%SUB shiftRight6bit
shiftRight6bit LDWI SYS_LSRW6_48
STW giga_sysFn
LDW mathShift
SYS 48
RET
%ENDS
%SUB shiftRight7bit
shiftRight7bit LDWI SYS_LSRW7_30
STW giga_sysFn
LDW mathShift
SYS 30
RET
%ENDS
%SUB shiftRight8bit
shiftRight8bit LDWI SYS_LSRW8_24
STW giga_sysFn
LDW mathShift
SYS 28
RET
%ENDS
%SUB shiftRightSgn1bit
shiftRightSgn1bit LDWI SYS_LSRW1_48
STW giga_sysFn
LDWI 0x8000
STW mathSign
ANDW mathShift
BEQ shiftRS1_pos ; check sign
LDW mathShift
SYS 48 ; shift right 1
ORW mathSign ; fix sign
RET
shiftRS1_pos LDW mathShift ; positive number
SYS 48
RET
%ENDS
%SUB shiftRightSgn2bit
shiftRightSgn2bit LDWI SYS_LSRW2_52
STW giga_sysFn
LD mathShift + 1
ANDI 0x80
BEQ shiftRS2_pos ; check sign
LDWI 0xC000
STW mathSign
LDW mathShift
SYS 52 ; shift right 2
ORW mathSign ; fix sign
RET
shiftRS2_pos LDW mathShift ; positive number
SYS 52
RET
%ENDS
%SUB shiftRightSgn3bit
shiftRightSgn3bit LDWI SYS_LSRW3_52
STW giga_sysFn
LD mathShift + 1
ANDI 0x80
BEQ shiftRS3_pos ; check sign
LDWI 0xE000
STW mathSign
LDW mathShift
SYS 52 ; shift right 3
ORW mathSign ; fix sign
RET
shiftRS3_pos LDW mathShift ; positive number
SYS 52
RET
%ENDS
%SUB shiftRightSgn4bit
shiftRightSgn4bit LDWI SYS_LSRW4_50
STW giga_sysFn
LD mathShift + 1
ANDI 0x80
BEQ shiftRS4_pos ; check sign
LDWI 0xF000
STW mathSign
LDW mathShift
SYS 50 ; shift right 4
ORW mathSign ; fix sign
RET
shiftRS4_pos LDW mathShift ; positive number
SYS 50
RET
%ENDS
%SUB shiftRightSgn5bit
shiftRightSgn5bit LDWI SYS_LSRW5_50
STW giga_sysFn
LD mathShift + 1
ANDI 0x80
BEQ shiftRS5_pos ; check sign
LDWI 0xF800
STW mathSign
LDW mathShift
SYS 50 ; shift right 5
ORW mathSign ; fix sign
RET
shiftRS5_pos LDW mathShift ; positive number
SYS 50
RET
%ENDS
%SUB shiftRightSgn6bit
shiftRightSgn6bit LDWI SYS_LSRW6_48
STW giga_sysFn
LD mathShift + 1
ANDI 0x80
BEQ shiftRS6_pos ; check sign
LDWI 0xFC00
STW mathSign
LDW mathShift
SYS 48 ; shift right 6
ORW mathSign ; fix sign
RET
shiftRS6_pos LDW mathShift ; positive number
SYS 48
RET
%ENDS
%SUB shiftRightSgn7bit
shiftRightSgn7bit LDWI SYS_LSRW7_30
STW giga_sysFn
LD mathShift + 1
ANDI 0x80
BEQ shiftRS7_pos ; check sign
LDWI 0xFE00
STW mathSign
LDW mathShift
SYS 30 ; shift right 7
ORW mathSign ; fix sign
RET
shiftRS7_pos LDW mathShift ; positive number
SYS 30
RET
%ENDS
%SUB shiftRightSgn8bit
shiftRightSgn8bit LDWI SYS_LSRW8_24
STW giga_sysFn
LD mathShift + 1
ANDI 0x80
BEQ shiftRS8_pos ; check sign
LDWI 0xFF00
STW mathSign
LDW mathShift
SYS 28 ; shift right 8
ORW mathSign ; fix sign
RET
shiftRS8_pos LDW mathShift ; positive number
SYS 28
RET
%ENDS