2021-08-02 23:49:18 +00:00
;; Standard Library
2021-01-02 05:08:37 +00:00
2021-08-03 14:10:51 +00:00
;; These registers are used within virtual functions as temporary holders
.constant std_SCRATCH_0 MGMT_SCRATCH_0
.constant std_SCRATCH_1 MGMT_SCRATCH_1
2021-01-02 09:30:32 +00:00
2021-08-02 23:49:18 +00:00
;; Also used as single return value
2021-08-03 14:10:51 +00:00
.reserve std_RETURN_VALUE 0x1E0
.reserve std_RETURN_VALUE_EXTRA 0x1E1
.reserve std_PARAMETER_0 0x1E2
.reserve std_PARAMETER_1 0x1E3
2021-08-05 22:04:44 +00:00
;; Used for offset pointer access
.constant std_THIS % 0
2021-08-03 14:10:51 +00:00
2021-08-02 23:49:18 +00:00
.constant RRET std_RETURN_VALUE ;;Alias
.constant RRET_X std_RETURN_VALUE_EXTRA ;;Alias
2021-01-02 09:30:32 +00:00
.constant P0 std_PARAMETER_0
.constant P1 std_PARAMETER_1
2021-08-03 15:52:42 +00:00
.constant S0 std_SCRATCH_0
.constant S1 std_SCRATCH_1
2021-01-02 05:08:37 +00:00
2021-08-02 23:49:18 +00:00
;; These are offset registers to be called with <OP>~2 to access stack frame parameters
.constant P2 % 0 , + 1 ;; Equivalent to same address in GET <Reg>, 1
.constant P3 % 0 , + 2 ;; Equivalent to same address in GET <Reg>, 2
.constant P4 % 0 , + 3 ;; Equivalent to same address in GET <Reg>, 3
.constant P5 % 0 , + 4 ;; Equivalent to same address in GET <Reg>, 4
.constant P6 % 0 , + 5 ;; Equivalent to same address in GET <Reg>, 5
.constant P7 % 0 , + 6 ;; Equivalent to same address in GET <Reg>, 6
.constant P8 % 0 , + 7 ;; Equivalent to same address in GET <Reg>, 7
.constant P9 % 0 , + 8 ;; Equivalent to same address in GET <Reg>, 8
.constant P10 % 0 , + 9 ;; Equivalent to same address in GET <Reg>, 9
.constant P11 % 0 , + 10 ;; Equivalent to same address in GET <Reg>, 10
.constant P12 % 0 , + 11 ;; Equivalent to same address in GET <Reg>, 11
.constant P13 % 0 , + 12 ;; Equivalent to same address in GET <Reg>, 12
.constant P14 % 0 , + 13 ;; Equivalent to same address in GET <Reg>, 13
.constant P15 % 0 , + 14 ;; Equivalent to same address in GET <Reg>, 14
.constant P16 % 0 , + 15 ;; Equivalent to same address in GET <Reg>, 15
2021-01-03 03:54:30 +00:00
2021-08-03 00:25:54 +00:00
;; These are parameter registers to be called with GET to access stack frame parameters
.constant GET_P2 1
.constant GET_P3 2
.constant GET_P4 3
.constant GET_P5 4
.constant GET_P6 5
.constant GET_P7 6
.constant GET_P8 7
.constant GET_P9 8
.constant GET_P10 9
.constant GET_P11 10
.constant GET_P12 11
.constant GET_P13 12
.constant GET_P14 13
.constant GET_P15 14
.constant GET_P16 15
2021-08-02 23:49:18 +00:00
;; Ephemeral registers to be used within functions. These values may not be kept when calling other functions. They can be used when returning values if necessary.
;; Some std functions might restore these values.
2021-08-03 14:10:51 +00:00
.reserve std_EPHEMERAL_REGISTER_0 0x1F0
2021-08-05 22:04:44 +00:00
.reserve std_EPHEMERAL_REGISTER_1 0x1F1
2021-08-03 14:10:51 +00:00
.reserve std_EPHEMERAL_REGISTER_2 0x1F2
.reserve std_EPHEMERAL_REGISTER_3 0x1F3
.reserve std_EPHEMERAL_REGISTER_4 0x1F4
.reserve std_EPHEMERAL_REGISTER_5 0x1F5
.reserve std_EPHEMERAL_REGISTER_6 0x1F6
.reserve std_EPHEMERAL_REGISTER_7 0x1F7
.reserve std_EPHEMERAL_REGISTER_8 0x1F8
.reserve std_EPHEMERAL_REGISTER_9 0x1F9
.reserve std_EPHEMERAL_REGISTER_10 0x1FA
.reserve std_EPHEMERAL_REGISTER_11 0x1FB
.reserve std_EPHEMERAL_REGISTER_12 0x1FC
.reserve std_EPHEMERAL_REGISTER_13 0x1FD
.reserve std_EPHEMERAL_REGISTER_14 0x1FE
.reserve std_EPHEMERAL_REGISTER_15 0x1FF
2021-08-02 23:49:18 +00:00
;; Abbreviations
2021-01-02 05:08:37 +00:00
.constant R0 std_EPHEMERAL_REGISTER_0
.constant R1 std_EPHEMERAL_REGISTER_1
.constant R2 std_EPHEMERAL_REGISTER_2
.constant R3 std_EPHEMERAL_REGISTER_3
.constant R4 std_EPHEMERAL_REGISTER_4
.constant R5 std_EPHEMERAL_REGISTER_5
.constant R6 std_EPHEMERAL_REGISTER_6
.constant R7 std_EPHEMERAL_REGISTER_7
.constant R8 std_EPHEMERAL_REGISTER_8
.constant R9 std_EPHEMERAL_REGISTER_9
2021-08-02 22:02:49 +00:00
.constant R10 std_EPHEMERAL_REGISTER_10
.constant R11 std_EPHEMERAL_REGISTER_11
.constant R12 std_EPHEMERAL_REGISTER_12
.constant R13 std_EPHEMERAL_REGISTER_13
.constant R14 std_EPHEMERAL_REGISTER_14
.constant R15 std_EPHEMERAL_REGISTER_15
2021-01-02 05:08:37 +00:00
2021-08-03 13:48:52 +00:00
; FASTCALL uint std_multiply(uint A, uint B). Return value on RRET
2021-08-03 16:20:08 +00:00
; Uses shift + add multiplication
2021-01-02 05:08:37 +00:00
.constant std_mul @ std_multiply
.constant std_multiply @ std_multiply
std_multiply:
2021-08-03 16:20:08 +00:00
MOV S0 , P0 ; S0 = A
MOV S1 , P1 ; S1 = B
MOV RRET , 0 ; result = 0
2021-01-02 05:08:37 +00:00
.multiply:
2021-08-03 16:20:08 +00:00
BEQ S0 , 0 , 0xFFFFFFFF , @ .return ; continue if S0 != 0
BNE S0 , 1 , 0x1 , @ .skipBit ; If the lowest order bit is set in A?
ADD RRET , RRET , S1 ; result = result + b
.skipBit:
SHR S0 , S0 , 1 ; a = a >> 1, no sign copy
ADD S1 , S1 , S1 ; b = b + b
JUMP @ .multiply
.return: RET ; Return, no need to get rid of stack as fastcall passed them on registers
2021-08-03 13:48:52 +00:00
; FASTCALL uint std_divide(uint dividend, uint divisor). Return quotient on RRET, remainder on RRET_X
; Uses shift + add division
; TODO: check validity
.constant std_div @ std_divide
.constant std_divide @ std_divide
std_divide:
BNE P1 , 0 , 0xffffffff , @ .normal_division ; Handle divisor = 0
WRITE RRET , 0xffffffff , 0xffffffff ; Return both values 0xffffffff
JUMP @ .return
.normal_division:
PUSH BSM_COUNTER_0 ; Save old value of counter
MOV BSM_COUNTER_0 , 32 ; Move bits left to counter (8 * 4)
MOV RRET , P0 ; Move dividend to RRET (quotient)
MOV RRET_X , 0 ; Move remainder to RRET_X
2021-08-05 22:04:44 +00:00
MOV S0 , 0
2021-08-03 13:48:52 +00:00
.divide:
2021-08-05 22:04:44 +00:00
MOV S0 , RRET ; Move quotient to temp S0
2021-08-03 13:48:52 +00:00
ADD RRET , RRET , RRET ; quotient = quotient + quotient
ADD RRET_X , RRET_X , RRET_X ; remainder = remainder + remainder + ...
2021-08-05 22:04:44 +00:00
SHL S0 , RRET , S0 ; quot << S0
ADD RRET_X , RRET_X , S0 ; remainder = ... + (quot << S0)
2021-08-03 13:48:52 +00:00
2021-08-05 22:04:44 +00:00
SUB S0 , RRET_X , P1 ; compare rem >= divisor
BNE S0 , 0 , 1 < 31 , @ .no_reduce
2021-08-03 13:48:52 +00:00
SUB RRET_X , RRET_X , P1 ; remainder = remainder - divisor
ADD RRET , RRET , 1 ; quotient = quotient + 1
.no_reduce:
LOOP @ .divide ; Check if 0, if not, decrease bits left and go back. Use COUNTER[0]
POP BSM_COUNTER_0 ; Restore old value of counter
.return: RET ; Return, no need to get rid of stack as fastcall passed them on registers
2021-01-02 05:08:37 +00:00
2021-08-02 22:02:49 +00:00
2021-08-02 23:49:18 +00:00
;; x86-like definitions
2021-08-02 22:02:49 +00:00
.constant ebp , rrcc_FRAME_POINTER
.constant esp , rrcc_STACK_POINTER
.constant eax , RRET