; 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