;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; Microsoft Research Singularity ;;; ;;; Copyright (c) Microsoft Corporation. All rights reserved. ;;; ;;; This file contains ARM-specific assembly code. ;;; ; ;div64.s - perform __int64 right shift operation ; OPT 2 ; disable listing INCLUDE kxarm.inc OPT 1 ; reenable listing IMPORT __rt_div0 TEXTAREA ;****************************************************************************** NESTED_ENTRY __rt_udivrem64by64 stmdb sp!, {r4 - r6, r10, r11, lr} PROLOG_END orrs r11, r2, r3 ; check to see if y is 0 bne |YIsNotZero| ; ; Divide by zero has occurred. Raise an exception ; call RaiseException(STATUS_INTEGER_DIVIDE_BY_ZERO, 0, 0, NULL) ; bl __rt_div0 ; __rt_div0 just calls RaiseException with above args. mvn r0, #0 mvn r1, #0 mvn r2, #0 mvn r3, #0 b |ReturnQAndMod| |YIsNotZero| mov r5, #0 ; r5 and r6 hold __int64 q; mov r6, #0 cmp r3, r1 ; Is y>x ? bhi |ReturnQAndMod| bcc |YLTEQX_A| cmp r2, r0 bhi |ReturnQAndMod| |YLTEQX_A| ands r11, r3, #2, 2 ; check if y's high bit is set bpl |HighBitNotSetForY| mov r5, #1 ; r6 already stores 0, q=1 subs r0, r0, r2 ; subcract y from x, x = x % y sbc r1, r1, r3 ; b |ReturnQAndMod| |HighBitNotSetForY| mov r10, #1 ; r10 and r4 hold __int64 mod; mov r4, #0 |YLTEQX_B| mov r3, r3, lsl #1 ; y <<= 1; mov r11, r4, lsl #1 ; mask <<= 1; orr r3, r3, r2, lsr #31 orr r4, r11, r10, lsr #31 mov r10, r10, lsl #1 mov r2, r2, lsl #1 movs r11, r3, lsr #31 bne |HighBitYisSet| ;y is as big as possible cmp r3, r1 bcc |YLTEQX_B| ; loop if yhi-xhi < 0 bhi |ShiftYAndMask|; break if yhi-xhi > 0 cmp r2, r0 bls |YLTEQX_B| ; loop ylo - xlo <= 0 b |ShiftYAndMask| |YGTX_A| adds r5, r10, r5 ; q+=mask adc r6, r4, r6 subs r0, r0, r2 ; x-=y sbc r1, r1, r3 |ShiftYAndMask| mov r11, r3, lsl #31 ; y>>=1 mask>>=1 orr r2, r11, r2, lsr #1 mov r11, r4, lsl #31 orr r10, r11, r10, lsr #1 mov r4, r4, lsr #1 mov r3, r3, lsr #1 |HighBitYisSet| orrs r11, r10, r4 ; Is mask 0? beq |ReturnQAndMod| cmp r3, r1 bcc |YGTX_A| ; loop if r1 > r3 or x >= y bhi |ShiftYAndMask| cmp r2, r0 bls |YGTX_A| ; loop y <= x b |ShiftYAndMask| |ReturnQAndMod| mov r2, r0 ; move the remainder to r2 and r3 mov r3, r1 mov r0, r5 ; put the quotient in r0, r1 mov r1, r6 ldmia sp!, {r4 - r6, r10, r11, lr} ; ldmfd IF Interworking BX lr ELSE MOV pc, lr ENDIF ENTRY_END ;****************************************************************************** NESTED_ENTRY __rt_divrem64by64 stmdb sp!, {r10, r11, lr} PROLOG_END ands r10, r1, #2, 2 ; check if x's sign bit is set bpl |CompareY| rsbs r0, r0, #0 ; x=-x; rsc r1, r1, #0 |CompareY| ands r11, r3, #2, 2 ; check if y's sign bit is set bpl |DoUDiv| rsbs r2, r2, #0 ; y=-y; rsc r3, r3, #0 |DoUDiv| bl |__rt_udivrem64by64|; cmp r10, #0 beq |NumeratorPos| rsbs r2, r2, #0 ; modulus has same sign as numerator rsc r3, r3, #0 |NumeratorPos| cmp r10, r11 beq |QPos| rsbs r0, r0, #0 ; Quotient sign reveral rsc r1, r1, #0 |QPos| ldmia sp!, {r10, r11, lr} IF Interworking BX lr ELSE MOV pc, lr ENDIF ENTRY_END ;****************************************************************************** NESTED_ENTRY __rt_udiv64by64 stmdb sp!, {lr} PROLOG_END bl __rt_udivrem64by64 ldmia sp!, {lr} IF Interworking BX lr ELSE MOV pc, lr ENDIF ENTRY_END ;****************************************************************************** NESTED_ENTRY __rt_urem64by64 stmdb sp!, {lr} PROLOG_END bl __rt_udivrem64by64 mov r0,r2 mov r1,r3 ldmia sp!, {lr} IF Interworking BX lr ELSE MOV pc, lr ENDIF ENTRY_END ;****************************************************************************** NESTED_ENTRY __rt_sdiv64by64 stmdb sp!, {lr} PROLOG_END bl __rt_divrem64by64 ldmia sp!, {lr} IF Interworking BX lr ELSE MOV pc, lr ENDIF ENTRY_END ;****************************************************************************** NESTED_ENTRY __rt_srem64by64 stmdb sp!, {lr} PROLOG_END bl __rt_divrem64by64 mov r0,r2 mov r1,r3 ldmia sp!, {lr} IF Interworking BX lr ELSE MOV pc, lr ENDIF ENTRY_END END