; Copyright 1996 Acorn Computers Ltd
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
;     http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
; Things that compiled C needs when included as AAsm source.
; Must appear before any included C output.

; Branches out of this code go to: dividebyzero.

; --------------------------------------------------------------------------
; Arrange to ignore spurious ObjAsm directives
        MACRO
        IMPORT  $a
        MEND
        MACRO
        AREA    $a,$b,$c
        MEND
        MACRO
        EXPORT  $a
        MEND

; Arrange to ignore spurious stack overflow warnings.
; sl register contains garbage, so ignore stack overflow.
; Just hope we have enough stack - we don't use much, so should be OK.
|x$stack_overflow|
|x$stack_overflow_1|
|__main|
        MOVS    PC,LR
; We also define __main to allow for the spurious B to it at
; the front of the compiled code.

; These are the C register usages - the other ones are already
; defined. They're reproduced here because some code (eg. the divide
; routine) uses them. They must be deleted in some way from the
; assembler that the C compiler generates.
a1 RN 0
a2 RN 1
a3 RN 2
a4 RN 3
v1 RN 4
v2 RN 5
v3 RN 6
v4 RN 7
v5 RN 8
v6 RN 9
;sl RN 10
;fp RN 11
;ip RN 12
;sp RN 13
;lr RN 14
;pc RN 15

; --------------------------------------------------------------------------
; Signed divide, extracted directly from AppSource.RISC_OSLib.kernel.s.k_body,
; where it's called _kernel_sdiv. I use this rather than the conventional
; assembler version because I know it's precisely what C code expects.

;      [ debug
; Only used in printing numbers, in the code as it is at the moment!
; No, JPEG stuff ends up using it a little.

|x$divide|
;v5 of C compiler uses new name for _kernel_sdiv. __rt_sdiv
|__rt_sdiv|
|_kernel_sdiv|
; Signed divide of a2 by a1: returns quotient in a1, remainder in a2
; Quotient is truncated (rounded towards zero).
; Sign of remainder = sign of dividend.
; Destroys a3, a4 and ip
; Negates dividend and divisor, then does an unsigned divide; signs
; get sorted out again at the end.
; Code mostly as for udiv, except that the justification part is slightly
; simplified by knowledge that the dividend is in the range [0..#x80000000]
; (one register may be gained thereby).

        MOVS    ip, a1
        BEQ     dividebyzero
        RSBMI   a1, a1, #0              ; absolute value of divisor
        EOR     ip, ip, a2
        ANDS    a4, a2, #&80000000
        ORR     ip, a4, ip, LSR #1
        ; ip bit 31  sign of dividend (= sign of remainder)
        ;    bit 30  sign of dividend EOR sign of divisor (= sign of quotient)
        RSBNE   a2, a2, #0              ; absolute value of dividend

        MOV     a3, a1
        MOV     a4, #0
s_loop
        CMP     a2, a3, ASL #0
        BLS     s_shifted0mod8
        CMP     a2, a3, ASL #1
        BLS     s_shifted1mod8
        CMP     a2, a3, ASL #2
        BLS     s_shifted2mod8
        CMP     a2, a3, ASL #3
        BLS     s_shifted3mod8
        CMP     a2, a3, ASL #4
        BLS     s_shifted4mod8
        CMP     a2, a3, ASL #5
        BLS     s_shifted5mod8
        CMP     a2, a3, ASL #6
        BLS     s_shifted6mod8
        CMP     a2, a3, ASL #7
        MOVHI   a3, a3, ASL #8
        BHI     s_loop
s_loop2
        CMP     a2, a3, ASL #7
        ADC     a4, a4, a4
        SUBHS   a2, a2, a3, ASL #7
        CMP     a2, a3, ASL #6
s_shifted6mod8
        ADC     a4, a4, a4
        SUBHS   a2, a2, a3, ASL #6
        CMP     a2, a3, ASL #5
s_shifted5mod8
        ADC     a4, a4, a4
        SUBHS   a2, a2, a3, ASL #5
        CMP     a2, a3, ASL #4
s_shifted4mod8
        ADC     a4, a4, a4
        SUBHS   a2, a2, a3, ASL #4
        CMP     a2, a3, ASL #3
s_shifted3mod8
        ADC     a4, a4, a4
        SUBHS   a2, a2, a3, ASL #3
        CMP     a2, a3, ASL #2
s_shifted2mod8
        ADC     a4, a4, a4
        SUBHS   a2, a2, a3, ASL #2
        CMP     a2, a3, ASL #1
s_shifted1mod8
        ADC     a4, a4, a4
        SUBHS   a2, a2, a3, ASL #1
        CMP     a2, a3, ASL #0
s_shifted0mod8
        ADC     a4, a4, a4
        SUBHS   a2, a2, a3, ASL #0
        CMP     a1, a3, LSR #1
        MOVLS   a3, a3, LSR #8
        BLS     s_loop2
        MOV     a1, a4
        TST     ip, #&40000000
        RSBNE   a1, a1, #0
        TST     ip, #&80000000
        RSBNE   a2, a2, #0
        MOVS    pc, r14

; Signed remainder of a2 by a1: returns remainder in a1

|_kernel_srem|
        STMFD   sp!, {r14}
        BL      |_kernel_sdiv|
        MOV     a1, a2
        LDMFD   sp!, {pc}^

        END