110d565efSmrg@ libgcc routines for ARM cpu. 210d565efSmrg@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk) 310d565efSmrg 4*ec02198aSmrg/* Copyright (C) 1995-2020 Free Software Foundation, Inc. 510d565efSmrg 610d565efSmrgThis file is free software; you can redistribute it and/or modify it 710d565efSmrgunder the terms of the GNU General Public License as published by the 810d565efSmrgFree Software Foundation; either version 3, or (at your option) any 910d565efSmrglater version. 1010d565efSmrg 1110d565efSmrgThis file is distributed in the hope that it will be useful, but 1210d565efSmrgWITHOUT ANY WARRANTY; without even the implied warranty of 1310d565efSmrgMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1410d565efSmrgGeneral Public License for more details. 1510d565efSmrg 1610d565efSmrgUnder Section 7 of GPL version 3, you are granted additional 1710d565efSmrgpermissions described in the GCC Runtime Library Exception, version 1810d565efSmrg3.1, as published by the Free Software Foundation. 1910d565efSmrg 2010d565efSmrgYou should have received a copy of the GNU General Public License and 2110d565efSmrga copy of the GCC Runtime Library Exception along with this program; 2210d565efSmrgsee the files COPYING3 and COPYING.RUNTIME respectively. If not, see 2310d565efSmrg<http://www.gnu.org/licenses/>. */ 2410d565efSmrg 25*ec02198aSmrg/* Everything in this file should now use unified syntax. */ 26*ec02198aSmrg 27*ec02198aSmrg .syntax unified 28*ec02198aSmrg 2910d565efSmrg/* An executable stack is *not* required for these functions. */ 3010d565efSmrg#if defined(__ELF__) && defined(__linux__) 3110d565efSmrg.section .note.GNU-stack,"",%progbits 3210d565efSmrg.previous 3310d565efSmrg#endif /* __ELF__ and __linux__ */ 3410d565efSmrg 3510d565efSmrg#ifdef __ARM_EABI__ 3610d565efSmrg/* Some attributes that are common to all routines in this file. */ 3710d565efSmrg /* Tag_ABI_align_needed: This code does not require 8-byte 3810d565efSmrg alignment from the caller. */ 3910d565efSmrg /* .eabi_attribute 24, 0 -- default setting. */ 4010d565efSmrg /* Tag_ABI_align_preserved: This code preserves 8-byte 4110d565efSmrg alignment in any callee. */ 4210d565efSmrg .eabi_attribute 25, 1 4310d565efSmrg#endif /* __ARM_EABI__ */ 4410d565efSmrg/* ------------------------------------------------------------------------ */ 4510d565efSmrg 4610d565efSmrg/* We need to know what prefix to add to function names. */ 4710d565efSmrg 4810d565efSmrg#ifndef __USER_LABEL_PREFIX__ 4910d565efSmrg#error __USER_LABEL_PREFIX__ not defined 5010d565efSmrg#endif 5110d565efSmrg 5210d565efSmrg/* ANSI concatenation macros. */ 5310d565efSmrg 5410d565efSmrg#define CONCAT1(a, b) CONCAT2(a, b) 5510d565efSmrg#define CONCAT2(a, b) a ## b 5610d565efSmrg 5710d565efSmrg/* Use the right prefix for global labels. */ 5810d565efSmrg 5910d565efSmrg#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) 6010d565efSmrg 6110d565efSmrg#ifdef __ELF__ 6210d565efSmrg#ifdef __thumb__ 6310d565efSmrg#define __PLT__ /* Not supported in Thumb assembler (for now). */ 6410d565efSmrg#elif defined __vxworks && !defined __PIC__ 6510d565efSmrg#define __PLT__ /* Not supported by the kernel loader. */ 6610d565efSmrg#else 6710d565efSmrg#define __PLT__ (PLT) 6810d565efSmrg#endif 6910d565efSmrg#define TYPE(x) .type SYM(x),function 7010d565efSmrg#define SIZE(x) .size SYM(x), . - SYM(x) 7110d565efSmrg#define LSYM(x) .x 7210d565efSmrg#else 7310d565efSmrg#define __PLT__ 7410d565efSmrg#define TYPE(x) 7510d565efSmrg#define SIZE(x) 7610d565efSmrg#define LSYM(x) x 7710d565efSmrg#endif 7810d565efSmrg 7910d565efSmrg/* Function end macros. Variants for interworking. */ 8010d565efSmrg 8110d565efSmrg/* There are times when we might prefer Thumb1 code even if ARM code is 8210d565efSmrg permitted, for example, the code might be smaller, or there might be 8310d565efSmrg interworking problems with switching to ARM state if interworking is 8410d565efSmrg disabled. */ 8510d565efSmrg#if (defined(__thumb__) \ 8610d565efSmrg && !defined(__thumb2__) \ 8710d565efSmrg && (!defined(__THUMB_INTERWORK__) \ 8810d565efSmrg || defined (__OPTIMIZE_SIZE__) \ 8910d565efSmrg || !__ARM_ARCH_ISA_ARM)) 9010d565efSmrg# define __prefer_thumb__ 9110d565efSmrg#endif 9210d565efSmrg 9310d565efSmrg#if !__ARM_ARCH_ISA_ARM && __ARM_ARCH_ISA_THUMB == 1 9410d565efSmrg#define NOT_ISA_TARGET_32BIT 1 9510d565efSmrg#endif 9610d565efSmrg 9710d565efSmrg/* How to return from a function call depends on the architecture variant. */ 9810d565efSmrg 990fc04c29Smrg#if (__ARM_ARCH > 4) || defined(__ARM_ARCH_4T__) 10010d565efSmrg 10110d565efSmrg# define RET bx lr 10210d565efSmrg# define RETc(x) bx##x lr 10310d565efSmrg 10410d565efSmrg/* Special precautions for interworking on armv4t. */ 1050fc04c29Smrg# if (__ARM_ARCH == 4) 10610d565efSmrg 10710d565efSmrg/* Always use bx, not ldr pc. */ 10810d565efSmrg# if (defined(__thumb__) || defined(__THUMB_INTERWORK__)) 10910d565efSmrg# define __INTERWORKING__ 11010d565efSmrg# endif /* __THUMB__ || __THUMB_INTERWORK__ */ 11110d565efSmrg 11210d565efSmrg/* Include thumb stub before arm mode code. */ 11310d565efSmrg# if defined(__thumb__) && !defined(__THUMB_INTERWORK__) 11410d565efSmrg# define __INTERWORKING_STUBS__ 11510d565efSmrg# endif /* __thumb__ && !__THUMB_INTERWORK__ */ 11610d565efSmrg 11710d565efSmrg#endif /* __ARM_ARCH == 4 */ 11810d565efSmrg 11910d565efSmrg#else 12010d565efSmrg 12110d565efSmrg# define RET mov pc, lr 12210d565efSmrg# define RETc(x) mov##x pc, lr 12310d565efSmrg 12410d565efSmrg#endif 12510d565efSmrg 12610d565efSmrg.macro cfi_pop advance, reg, cfa_offset 12710d565efSmrg#ifdef __ELF__ 12810d565efSmrg .pushsection .debug_frame 12910d565efSmrg .byte 0x4 /* DW_CFA_advance_loc4 */ 13010d565efSmrg .4byte \advance 13110d565efSmrg .byte (0xc0 | \reg) /* DW_CFA_restore */ 13210d565efSmrg .byte 0xe /* DW_CFA_def_cfa_offset */ 13310d565efSmrg .uleb128 \cfa_offset 13410d565efSmrg .popsection 13510d565efSmrg#endif 13610d565efSmrg.endm 13710d565efSmrg.macro cfi_push advance, reg, offset, cfa_offset 13810d565efSmrg#ifdef __ELF__ 13910d565efSmrg .pushsection .debug_frame 14010d565efSmrg .byte 0x4 /* DW_CFA_advance_loc4 */ 14110d565efSmrg .4byte \advance 14210d565efSmrg .byte (0x80 | \reg) /* DW_CFA_offset */ 14310d565efSmrg .uleb128 (\offset / -4) 14410d565efSmrg .byte 0xe /* DW_CFA_def_cfa_offset */ 14510d565efSmrg .uleb128 \cfa_offset 14610d565efSmrg .popsection 14710d565efSmrg#endif 14810d565efSmrg.endm 14910d565efSmrg.macro cfi_start start_label, end_label 15010d565efSmrg#ifdef __ELF__ 15110d565efSmrg .pushsection .debug_frame 15210d565efSmrgLSYM(Lstart_frame): 15310d565efSmrg .4byte LSYM(Lend_cie) - LSYM(Lstart_cie) @ Length of CIE 15410d565efSmrgLSYM(Lstart_cie): 15510d565efSmrg .4byte 0xffffffff @ CIE Identifier Tag 15610d565efSmrg .byte 0x1 @ CIE Version 15710d565efSmrg .ascii "\0" @ CIE Augmentation 15810d565efSmrg .uleb128 0x1 @ CIE Code Alignment Factor 15910d565efSmrg .sleb128 -4 @ CIE Data Alignment Factor 16010d565efSmrg .byte 0xe @ CIE RA Column 16110d565efSmrg .byte 0xc @ DW_CFA_def_cfa 16210d565efSmrg .uleb128 0xd 16310d565efSmrg .uleb128 0x0 16410d565efSmrg 16510d565efSmrg .align 2 16610d565efSmrgLSYM(Lend_cie): 16710d565efSmrg .4byte LSYM(Lend_fde)-LSYM(Lstart_fde) @ FDE Length 16810d565efSmrgLSYM(Lstart_fde): 16910d565efSmrg .4byte LSYM(Lstart_frame) @ FDE CIE offset 17010d565efSmrg .4byte \start_label @ FDE initial location 17110d565efSmrg .4byte \end_label-\start_label @ FDE address range 17210d565efSmrg .popsection 17310d565efSmrg#endif 17410d565efSmrg.endm 17510d565efSmrg.macro cfi_end end_label 17610d565efSmrg#ifdef __ELF__ 17710d565efSmrg .pushsection .debug_frame 17810d565efSmrg .align 2 17910d565efSmrgLSYM(Lend_fde): 18010d565efSmrg .popsection 18110d565efSmrg\end_label: 18210d565efSmrg#endif 18310d565efSmrg.endm 18410d565efSmrg 18510d565efSmrg/* Don't pass dirn, it's there just to get token pasting right. */ 18610d565efSmrg 18710d565efSmrg.macro RETLDM regs=, cond=, unwind=, dirn=ia 18810d565efSmrg#if defined (__INTERWORKING__) 18910d565efSmrg .ifc "\regs","" 19010d565efSmrg ldr\cond lr, [sp], #8 19110d565efSmrg .else 19210d565efSmrg# if defined(__thumb2__) 19310d565efSmrg pop\cond {\regs, lr} 19410d565efSmrg# else 19510d565efSmrg ldm\cond\dirn sp!, {\regs, lr} 19610d565efSmrg# endif 19710d565efSmrg .endif 19810d565efSmrg .ifnc "\unwind", "" 19910d565efSmrg /* Mark LR as restored. */ 20010d565efSmrg97: cfi_pop 97b - \unwind, 0xe, 0x0 20110d565efSmrg .endif 20210d565efSmrg bx\cond lr 20310d565efSmrg#else 20410d565efSmrg /* Caller is responsible for providing IT instruction. */ 20510d565efSmrg .ifc "\regs","" 20610d565efSmrg ldr\cond pc, [sp], #8 20710d565efSmrg .else 20810d565efSmrg# if defined(__thumb2__) 20910d565efSmrg pop\cond {\regs, pc} 21010d565efSmrg# else 21110d565efSmrg ldm\cond\dirn sp!, {\regs, pc} 21210d565efSmrg# endif 21310d565efSmrg .endif 21410d565efSmrg#endif 21510d565efSmrg.endm 21610d565efSmrg 21710d565efSmrg/* The Unified assembly syntax allows the same code to be assembled for both 21810d565efSmrg ARM and Thumb-2. However this is only supported by recent gas, so define 21910d565efSmrg a set of macros to allow ARM code on older assemblers. */ 22010d565efSmrg#if defined(__thumb2__) 22110d565efSmrg.macro do_it cond, suffix="" 22210d565efSmrg it\suffix \cond 22310d565efSmrg.endm 22410d565efSmrg.macro shift1 op, arg0, arg1, arg2 22510d565efSmrg \op \arg0, \arg1, \arg2 22610d565efSmrg.endm 22710d565efSmrg#define do_push push 22810d565efSmrg#define do_pop pop 22910d565efSmrg/* Perform an arithmetic operation with a variable shift operand. This 23010d565efSmrg requires two instructions and a scratch register on Thumb-2. */ 23110d565efSmrg.macro shiftop name, dest, src1, src2, shiftop, shiftreg, tmp 23210d565efSmrg \shiftop \tmp, \src2, \shiftreg 23310d565efSmrg \name \dest, \src1, \tmp 23410d565efSmrg.endm 23510d565efSmrg#else 23610d565efSmrg.macro do_it cond, suffix="" 23710d565efSmrg.endm 23810d565efSmrg.macro shift1 op, arg0, arg1, arg2 23910d565efSmrg mov \arg0, \arg1, \op \arg2 24010d565efSmrg.endm 24110d565efSmrg#define do_push stmfd sp!, 24210d565efSmrg#define do_pop ldmfd sp!, 24310d565efSmrg.macro shiftop name, dest, src1, src2, shiftop, shiftreg, tmp 24410d565efSmrg \name \dest, \src1, \src2, \shiftop \shiftreg 24510d565efSmrg.endm 24610d565efSmrg#endif 24710d565efSmrg 248*ec02198aSmrg#define COND(op1, op2, cond) op1 ## op2 ## cond 249*ec02198aSmrg 25010d565efSmrg#ifdef __ARM_EABI__ 25110d565efSmrg.macro ARM_LDIV0 name signed 25210d565efSmrg cmp r0, #0 25310d565efSmrg .ifc \signed, unsigned 25410d565efSmrg movne r0, #0xffffffff 25510d565efSmrg .else 25610d565efSmrg movgt r0, #0x7fffffff 25710d565efSmrg movlt r0, #0x80000000 25810d565efSmrg .endif 25910d565efSmrg b SYM (__aeabi_idiv0) __PLT__ 26010d565efSmrg.endm 26110d565efSmrg#else 26210d565efSmrg.macro ARM_LDIV0 name signed 26310d565efSmrg str lr, [sp, #-8]! 26410d565efSmrg98: cfi_push 98b - __\name, 0xe, -0x8, 0x8 26510d565efSmrg bl SYM (__div0) __PLT__ 26610d565efSmrg mov r0, #0 @ About as wrong as it could be. 26710d565efSmrg RETLDM unwind=98b 26810d565efSmrg.endm 26910d565efSmrg#endif 27010d565efSmrg 27110d565efSmrg 27210d565efSmrg#ifdef __ARM_EABI__ 27310d565efSmrg.macro THUMB_LDIV0 name signed 27410d565efSmrg#ifdef NOT_ISA_TARGET_32BIT 27510d565efSmrg 27610d565efSmrg push {r0, lr} 277*ec02198aSmrg movs r0, #0 27810d565efSmrg bl SYM(__aeabi_idiv0) 27910d565efSmrg @ We know we are not on armv4t, so pop pc is safe. 28010d565efSmrg pop {r1, pc} 28110d565efSmrg 28210d565efSmrg#elif defined(__thumb2__) 28310d565efSmrg .syntax unified 28410d565efSmrg .ifc \signed, unsigned 28510d565efSmrg cbz r0, 1f 28610d565efSmrg mov r0, #0xffffffff 28710d565efSmrg1: 28810d565efSmrg .else 28910d565efSmrg cmp r0, #0 29010d565efSmrg do_it gt 29110d565efSmrg movgt r0, #0x7fffffff 29210d565efSmrg do_it lt 29310d565efSmrg movlt r0, #0x80000000 29410d565efSmrg .endif 29510d565efSmrg b.w SYM(__aeabi_idiv0) __PLT__ 29610d565efSmrg#else 29710d565efSmrg .align 2 29810d565efSmrg bx pc 29910d565efSmrg nop 30010d565efSmrg .arm 30110d565efSmrg cmp r0, #0 30210d565efSmrg .ifc \signed, unsigned 30310d565efSmrg movne r0, #0xffffffff 30410d565efSmrg .else 30510d565efSmrg movgt r0, #0x7fffffff 30610d565efSmrg movlt r0, #0x80000000 30710d565efSmrg .endif 30810d565efSmrg b SYM(__aeabi_idiv0) __PLT__ 30910d565efSmrg .thumb 31010d565efSmrg#endif 31110d565efSmrg.endm 31210d565efSmrg#else 31310d565efSmrg.macro THUMB_LDIV0 name signed 31410d565efSmrg push { r1, lr } 31510d565efSmrg98: cfi_push 98b - __\name, 0xe, -0x4, 0x8 31610d565efSmrg bl SYM (__div0) 317*ec02198aSmrg movs r0, #0 @ About as wrong as it could be. 31810d565efSmrg#if defined (__INTERWORKING__) 31910d565efSmrg pop { r1, r2 } 32010d565efSmrg bx r2 32110d565efSmrg#else 32210d565efSmrg pop { r1, pc } 32310d565efSmrg#endif 32410d565efSmrg.endm 32510d565efSmrg#endif 32610d565efSmrg 32710d565efSmrg.macro FUNC_END name 32810d565efSmrg SIZE (__\name) 32910d565efSmrg.endm 33010d565efSmrg 33110d565efSmrg.macro DIV_FUNC_END name signed 33210d565efSmrg cfi_start __\name, LSYM(Lend_div0) 33310d565efSmrgLSYM(Ldiv0): 33410d565efSmrg#ifdef __thumb__ 33510d565efSmrg THUMB_LDIV0 \name \signed 33610d565efSmrg#else 33710d565efSmrg ARM_LDIV0 \name \signed 33810d565efSmrg#endif 33910d565efSmrg cfi_end LSYM(Lend_div0) 34010d565efSmrg FUNC_END \name 34110d565efSmrg.endm 34210d565efSmrg 34310d565efSmrg.macro THUMB_FUNC_START name 34410d565efSmrg .globl SYM (\name) 34510d565efSmrg TYPE (\name) 34610d565efSmrg .thumb_func 34710d565efSmrgSYM (\name): 34810d565efSmrg.endm 34910d565efSmrg 35010d565efSmrg/* Function start macros. Variants for ARM and Thumb. */ 35110d565efSmrg 35210d565efSmrg#ifdef __thumb__ 35310d565efSmrg#define THUMB_FUNC .thumb_func 35410d565efSmrg#define THUMB_CODE .force_thumb 35510d565efSmrg# if defined(__thumb2__) 356*ec02198aSmrg#define THUMB_SYNTAX 35710d565efSmrg# else 35810d565efSmrg#define THUMB_SYNTAX 35910d565efSmrg# endif 36010d565efSmrg#else 36110d565efSmrg#define THUMB_FUNC 36210d565efSmrg#define THUMB_CODE 36310d565efSmrg#define THUMB_SYNTAX 36410d565efSmrg#endif 36510d565efSmrg 3660fc04c29Smrg.macro FUNC_START name 36710d565efSmrg .text 36810d565efSmrg .globl SYM (__\name) 36910d565efSmrg TYPE (__\name) 37010d565efSmrg .align 0 37110d565efSmrg THUMB_CODE 37210d565efSmrg THUMB_FUNC 37310d565efSmrg THUMB_SYNTAX 37410d565efSmrgSYM (__\name): 37510d565efSmrg.endm 37610d565efSmrg 37710d565efSmrg.macro ARM_SYM_START name 37810d565efSmrg TYPE (\name) 37910d565efSmrg .align 0 38010d565efSmrgSYM (\name): 38110d565efSmrg.endm 38210d565efSmrg 38310d565efSmrg.macro SYM_END name 38410d565efSmrg SIZE (\name) 38510d565efSmrg.endm 38610d565efSmrg 38710d565efSmrg/* Special function that will always be coded in ARM assembly, even if 38810d565efSmrg in Thumb-only compilation. */ 38910d565efSmrg 39010d565efSmrg#if defined(__thumb2__) 39110d565efSmrg 39210d565efSmrg/* For Thumb-2 we build everything in thumb mode. */ 3930fc04c29Smrg.macro ARM_FUNC_START name 3940fc04c29Smrg FUNC_START \name 39510d565efSmrg .syntax unified 39610d565efSmrg.endm 39710d565efSmrg#define EQUIV .thumb_set 39810d565efSmrg.macro ARM_CALL name 39910d565efSmrg bl __\name 40010d565efSmrg.endm 40110d565efSmrg 40210d565efSmrg#elif defined(__INTERWORKING_STUBS__) 40310d565efSmrg 40410d565efSmrg.macro ARM_FUNC_START name 40510d565efSmrg FUNC_START \name 40610d565efSmrg bx pc 40710d565efSmrg nop 40810d565efSmrg .arm 40910d565efSmrg/* A hook to tell gdb that we've switched to ARM mode. Also used to call 41010d565efSmrg directly from other local arm routines. */ 41110d565efSmrg_L__\name: 41210d565efSmrg.endm 41310d565efSmrg#define EQUIV .thumb_set 41410d565efSmrg/* Branch directly to a function declared with ARM_FUNC_START. 41510d565efSmrg Must be called in arm mode. */ 41610d565efSmrg.macro ARM_CALL name 41710d565efSmrg bl _L__\name 41810d565efSmrg.endm 41910d565efSmrg 42010d565efSmrg#else /* !(__INTERWORKING_STUBS__ || __thumb2__) */ 42110d565efSmrg 42210d565efSmrg#ifdef NOT_ISA_TARGET_32BIT 42310d565efSmrg#define EQUIV .thumb_set 42410d565efSmrg#else 4250fc04c29Smrg.macro ARM_FUNC_START name 42610d565efSmrg .text 42710d565efSmrg .globl SYM (__\name) 42810d565efSmrg TYPE (__\name) 42910d565efSmrg .align 0 43010d565efSmrg .arm 43110d565efSmrgSYM (__\name): 43210d565efSmrg.endm 43310d565efSmrg#define EQUIV .set 43410d565efSmrg.macro ARM_CALL name 43510d565efSmrg bl __\name 43610d565efSmrg.endm 43710d565efSmrg#endif 43810d565efSmrg 43910d565efSmrg#endif 44010d565efSmrg 44110d565efSmrg.macro FUNC_ALIAS new old 44210d565efSmrg .globl SYM (__\new) 44310d565efSmrg#if defined (__thumb__) 44410d565efSmrg .thumb_set SYM (__\new), SYM (__\old) 44510d565efSmrg#else 44610d565efSmrg .set SYM (__\new), SYM (__\old) 44710d565efSmrg#endif 44810d565efSmrg.endm 44910d565efSmrg 45010d565efSmrg#ifndef NOT_ISA_TARGET_32BIT 45110d565efSmrg.macro ARM_FUNC_ALIAS new old 45210d565efSmrg .globl SYM (__\new) 45310d565efSmrg EQUIV SYM (__\new), SYM (__\old) 45410d565efSmrg#if defined(__INTERWORKING_STUBS__) 45510d565efSmrg .set SYM (_L__\new), SYM (_L__\old) 45610d565efSmrg#endif 45710d565efSmrg.endm 45810d565efSmrg#endif 45910d565efSmrg 46010d565efSmrg#ifdef __ARMEB__ 46110d565efSmrg#define xxh r0 46210d565efSmrg#define xxl r1 46310d565efSmrg#define yyh r2 46410d565efSmrg#define yyl r3 46510d565efSmrg#else 46610d565efSmrg#define xxh r1 46710d565efSmrg#define xxl r0 46810d565efSmrg#define yyh r3 46910d565efSmrg#define yyl r2 47010d565efSmrg#endif 47110d565efSmrg 47210d565efSmrg#ifdef __ARM_EABI__ 47310d565efSmrg.macro WEAK name 47410d565efSmrg .weak SYM (__\name) 47510d565efSmrg.endm 47610d565efSmrg#endif 47710d565efSmrg 47810d565efSmrg#ifdef __thumb__ 47910d565efSmrg/* Register aliases. */ 48010d565efSmrg 48110d565efSmrgwork .req r4 @ XXXX is this safe ? 48210d565efSmrgdividend .req r0 48310d565efSmrgdivisor .req r1 48410d565efSmrgoverdone .req r2 48510d565efSmrgresult .req r2 48610d565efSmrgcurbit .req r3 48710d565efSmrg#endif 48810d565efSmrg#if 0 48910d565efSmrgip .req r12 49010d565efSmrgsp .req r13 49110d565efSmrglr .req r14 49210d565efSmrgpc .req r15 49310d565efSmrg#endif 49410d565efSmrg 49510d565efSmrg/* ------------------------------------------------------------------------ */ 49610d565efSmrg/* Bodies of the division and modulo routines. */ 49710d565efSmrg/* ------------------------------------------------------------------------ */ 498*ec02198aSmrg 49910d565efSmrg.macro ARM_DIV_BODY dividend, divisor, result, curbit 50010d565efSmrg 5010fc04c29Smrg#if defined (__ARM_FEATURE_CLZ) && ! defined (__OPTIMIZE_SIZE__) 50210d565efSmrg 50310d565efSmrg#if defined (__thumb2__) 50410d565efSmrg clz \curbit, \dividend 50510d565efSmrg clz \result, \divisor 50610d565efSmrg sub \curbit, \result, \curbit 50710d565efSmrg rsb \curbit, \curbit, #31 50810d565efSmrg adr \result, 1f 50910d565efSmrg add \curbit, \result, \curbit, lsl #4 51010d565efSmrg mov \result, #0 51110d565efSmrg mov pc, \curbit 51210d565efSmrg.p2align 3 51310d565efSmrg1: 51410d565efSmrg .set shift, 32 51510d565efSmrg .rept 32 51610d565efSmrg .set shift, shift - 1 51710d565efSmrg cmp.w \dividend, \divisor, lsl #shift 51810d565efSmrg nop.n 51910d565efSmrg adc.w \result, \result, \result 52010d565efSmrg it cs 52110d565efSmrg subcs.w \dividend, \dividend, \divisor, lsl #shift 52210d565efSmrg .endr 52310d565efSmrg#else 52410d565efSmrg clz \curbit, \dividend 52510d565efSmrg clz \result, \divisor 52610d565efSmrg sub \curbit, \result, \curbit 52710d565efSmrg rsbs \curbit, \curbit, #31 52810d565efSmrg addne \curbit, \curbit, \curbit, lsl #1 52910d565efSmrg mov \result, #0 53010d565efSmrg addne pc, pc, \curbit, lsl #2 53110d565efSmrg nop 53210d565efSmrg .set shift, 32 53310d565efSmrg .rept 32 53410d565efSmrg .set shift, shift - 1 53510d565efSmrg cmp \dividend, \divisor, lsl #shift 53610d565efSmrg adc \result, \result, \result 53710d565efSmrg subcs \dividend, \dividend, \divisor, lsl #shift 53810d565efSmrg .endr 53910d565efSmrg#endif 54010d565efSmrg 5410fc04c29Smrg#else /* !defined (__ARM_FEATURE_CLZ) || defined (__OPTIMIZE_SIZE__) */ 5420fc04c29Smrg#if defined (__ARM_FEATURE_CLZ) 54310d565efSmrg 54410d565efSmrg clz \curbit, \divisor 54510d565efSmrg clz \result, \dividend 54610d565efSmrg sub \result, \curbit, \result 54710d565efSmrg mov \curbit, #1 54810d565efSmrg mov \divisor, \divisor, lsl \result 54910d565efSmrg mov \curbit, \curbit, lsl \result 55010d565efSmrg mov \result, #0 55110d565efSmrg 5520fc04c29Smrg#else /* !defined (__ARM_FEATURE_CLZ) */ 55310d565efSmrg 55410d565efSmrg @ Initially shift the divisor left 3 bits if possible, 55510d565efSmrg @ set curbit accordingly. This allows for curbit to be located 55610d565efSmrg @ at the left end of each 4-bit nibbles in the division loop 55710d565efSmrg @ to save one loop in most cases. 55810d565efSmrg tst \divisor, #0xe0000000 55910d565efSmrg moveq \divisor, \divisor, lsl #3 56010d565efSmrg moveq \curbit, #8 56110d565efSmrg movne \curbit, #1 56210d565efSmrg 56310d565efSmrg @ Unless the divisor is very big, shift it up in multiples of 56410d565efSmrg @ four bits, since this is the amount of unwinding in the main 56510d565efSmrg @ division loop. Continue shifting until the divisor is 56610d565efSmrg @ larger than the dividend. 56710d565efSmrg1: cmp \divisor, #0x10000000 56810d565efSmrg cmplo \divisor, \dividend 56910d565efSmrg movlo \divisor, \divisor, lsl #4 57010d565efSmrg movlo \curbit, \curbit, lsl #4 57110d565efSmrg blo 1b 57210d565efSmrg 57310d565efSmrg @ For very big divisors, we must shift it a bit at a time, or 57410d565efSmrg @ we will be in danger of overflowing. 57510d565efSmrg1: cmp \divisor, #0x80000000 57610d565efSmrg cmplo \divisor, \dividend 57710d565efSmrg movlo \divisor, \divisor, lsl #1 57810d565efSmrg movlo \curbit, \curbit, lsl #1 57910d565efSmrg blo 1b 58010d565efSmrg 58110d565efSmrg mov \result, #0 58210d565efSmrg 5830fc04c29Smrg#endif /* !defined (__ARM_FEATURE_CLZ) */ 58410d565efSmrg 58510d565efSmrg @ Division loop 58610d565efSmrg1: cmp \dividend, \divisor 58710d565efSmrg do_it hs, t 58810d565efSmrg subhs \dividend, \dividend, \divisor 58910d565efSmrg orrhs \result, \result, \curbit 59010d565efSmrg cmp \dividend, \divisor, lsr #1 59110d565efSmrg do_it hs, t 59210d565efSmrg subhs \dividend, \dividend, \divisor, lsr #1 59310d565efSmrg orrhs \result, \result, \curbit, lsr #1 59410d565efSmrg cmp \dividend, \divisor, lsr #2 59510d565efSmrg do_it hs, t 59610d565efSmrg subhs \dividend, \dividend, \divisor, lsr #2 59710d565efSmrg orrhs \result, \result, \curbit, lsr #2 59810d565efSmrg cmp \dividend, \divisor, lsr #3 59910d565efSmrg do_it hs, t 60010d565efSmrg subhs \dividend, \dividend, \divisor, lsr #3 60110d565efSmrg orrhs \result, \result, \curbit, lsr #3 60210d565efSmrg cmp \dividend, #0 @ Early termination? 60310d565efSmrg do_it ne, t 60410d565efSmrg movnes \curbit, \curbit, lsr #4 @ No, any more bits to do? 60510d565efSmrg movne \divisor, \divisor, lsr #4 60610d565efSmrg bne 1b 60710d565efSmrg 6080fc04c29Smrg#endif /* !defined (__ARM_FEATURE_CLZ) || defined (__OPTIMIZE_SIZE__) */ 60910d565efSmrg 61010d565efSmrg.endm 61110d565efSmrg/* ------------------------------------------------------------------------ */ 61210d565efSmrg.macro ARM_DIV2_ORDER divisor, order 61310d565efSmrg 6140fc04c29Smrg#if defined (__ARM_FEATURE_CLZ) 61510d565efSmrg 61610d565efSmrg clz \order, \divisor 61710d565efSmrg rsb \order, \order, #31 61810d565efSmrg 61910d565efSmrg#else 62010d565efSmrg 62110d565efSmrg cmp \divisor, #(1 << 16) 62210d565efSmrg movhs \divisor, \divisor, lsr #16 62310d565efSmrg movhs \order, #16 62410d565efSmrg movlo \order, #0 62510d565efSmrg 62610d565efSmrg cmp \divisor, #(1 << 8) 62710d565efSmrg movhs \divisor, \divisor, lsr #8 62810d565efSmrg addhs \order, \order, #8 62910d565efSmrg 63010d565efSmrg cmp \divisor, #(1 << 4) 63110d565efSmrg movhs \divisor, \divisor, lsr #4 63210d565efSmrg addhs \order, \order, #4 63310d565efSmrg 63410d565efSmrg cmp \divisor, #(1 << 2) 63510d565efSmrg addhi \order, \order, #3 63610d565efSmrg addls \order, \order, \divisor, lsr #1 63710d565efSmrg 63810d565efSmrg#endif 63910d565efSmrg 64010d565efSmrg.endm 64110d565efSmrg/* ------------------------------------------------------------------------ */ 64210d565efSmrg.macro ARM_MOD_BODY dividend, divisor, order, spare 64310d565efSmrg 6440fc04c29Smrg#if defined(__ARM_FEATURE_CLZ) && ! defined (__OPTIMIZE_SIZE__) 64510d565efSmrg 64610d565efSmrg clz \order, \divisor 64710d565efSmrg clz \spare, \dividend 64810d565efSmrg sub \order, \order, \spare 64910d565efSmrg rsbs \order, \order, #31 65010d565efSmrg addne pc, pc, \order, lsl #3 65110d565efSmrg nop 65210d565efSmrg .set shift, 32 65310d565efSmrg .rept 32 65410d565efSmrg .set shift, shift - 1 65510d565efSmrg cmp \dividend, \divisor, lsl #shift 65610d565efSmrg subcs \dividend, \dividend, \divisor, lsl #shift 65710d565efSmrg .endr 65810d565efSmrg 6590fc04c29Smrg#else /* !defined (__ARM_FEATURE_CLZ) || defined (__OPTIMIZE_SIZE__) */ 6600fc04c29Smrg#if defined (__ARM_FEATURE_CLZ) 66110d565efSmrg 66210d565efSmrg clz \order, \divisor 66310d565efSmrg clz \spare, \dividend 66410d565efSmrg sub \order, \order, \spare 66510d565efSmrg mov \divisor, \divisor, lsl \order 66610d565efSmrg 6670fc04c29Smrg#else /* !defined (__ARM_FEATURE_CLZ) */ 66810d565efSmrg 66910d565efSmrg mov \order, #0 67010d565efSmrg 67110d565efSmrg @ Unless the divisor is very big, shift it up in multiples of 67210d565efSmrg @ four bits, since this is the amount of unwinding in the main 67310d565efSmrg @ division loop. Continue shifting until the divisor is 67410d565efSmrg @ larger than the dividend. 67510d565efSmrg1: cmp \divisor, #0x10000000 67610d565efSmrg cmplo \divisor, \dividend 67710d565efSmrg movlo \divisor, \divisor, lsl #4 67810d565efSmrg addlo \order, \order, #4 67910d565efSmrg blo 1b 68010d565efSmrg 68110d565efSmrg @ For very big divisors, we must shift it a bit at a time, or 68210d565efSmrg @ we will be in danger of overflowing. 68310d565efSmrg1: cmp \divisor, #0x80000000 68410d565efSmrg cmplo \divisor, \dividend 68510d565efSmrg movlo \divisor, \divisor, lsl #1 68610d565efSmrg addlo \order, \order, #1 68710d565efSmrg blo 1b 68810d565efSmrg 6890fc04c29Smrg#endif /* !defined (__ARM_FEATURE_CLZ) */ 69010d565efSmrg 69110d565efSmrg @ Perform all needed substractions to keep only the reminder. 69210d565efSmrg @ Do comparisons in batch of 4 first. 69310d565efSmrg subs \order, \order, #3 @ yes, 3 is intended here 69410d565efSmrg blt 2f 69510d565efSmrg 69610d565efSmrg1: cmp \dividend, \divisor 69710d565efSmrg subhs \dividend, \dividend, \divisor 69810d565efSmrg cmp \dividend, \divisor, lsr #1 69910d565efSmrg subhs \dividend, \dividend, \divisor, lsr #1 70010d565efSmrg cmp \dividend, \divisor, lsr #2 70110d565efSmrg subhs \dividend, \dividend, \divisor, lsr #2 70210d565efSmrg cmp \dividend, \divisor, lsr #3 70310d565efSmrg subhs \dividend, \dividend, \divisor, lsr #3 70410d565efSmrg cmp \dividend, #1 70510d565efSmrg mov \divisor, \divisor, lsr #4 70610d565efSmrg subges \order, \order, #4 70710d565efSmrg bge 1b 70810d565efSmrg 70910d565efSmrg tst \order, #3 71010d565efSmrg teqne \dividend, #0 71110d565efSmrg beq 5f 71210d565efSmrg 71310d565efSmrg @ Either 1, 2 or 3 comparison/substractions are left. 71410d565efSmrg2: cmn \order, #2 71510d565efSmrg blt 4f 71610d565efSmrg beq 3f 71710d565efSmrg cmp \dividend, \divisor 71810d565efSmrg subhs \dividend, \dividend, \divisor 71910d565efSmrg mov \divisor, \divisor, lsr #1 72010d565efSmrg3: cmp \dividend, \divisor 72110d565efSmrg subhs \dividend, \dividend, \divisor 72210d565efSmrg mov \divisor, \divisor, lsr #1 72310d565efSmrg4: cmp \dividend, \divisor 72410d565efSmrg subhs \dividend, \dividend, \divisor 72510d565efSmrg5: 72610d565efSmrg 7270fc04c29Smrg#endif /* !defined (__ARM_FEATURE_CLZ) || defined (__OPTIMIZE_SIZE__) */ 72810d565efSmrg 72910d565efSmrg.endm 73010d565efSmrg/* ------------------------------------------------------------------------ */ 73110d565efSmrg.macro THUMB_DIV_MOD_BODY modulo 73210d565efSmrg @ Load the constant 0x10000000 into our work register. 733*ec02198aSmrg movs work, #1 734*ec02198aSmrg lsls work, #28 73510d565efSmrgLSYM(Loop1): 73610d565efSmrg @ Unless the divisor is very big, shift it up in multiples of 73710d565efSmrg @ four bits, since this is the amount of unwinding in the main 73810d565efSmrg @ division loop. Continue shifting until the divisor is 73910d565efSmrg @ larger than the dividend. 74010d565efSmrg cmp divisor, work 74110d565efSmrg bhs LSYM(Lbignum) 74210d565efSmrg cmp divisor, dividend 74310d565efSmrg bhs LSYM(Lbignum) 744*ec02198aSmrg lsls divisor, #4 745*ec02198aSmrg lsls curbit, #4 74610d565efSmrg b LSYM(Loop1) 74710d565efSmrgLSYM(Lbignum): 74810d565efSmrg @ Set work to 0x80000000 749*ec02198aSmrg lsls work, #3 75010d565efSmrgLSYM(Loop2): 75110d565efSmrg @ For very big divisors, we must shift it a bit at a time, or 75210d565efSmrg @ we will be in danger of overflowing. 75310d565efSmrg cmp divisor, work 75410d565efSmrg bhs LSYM(Loop3) 75510d565efSmrg cmp divisor, dividend 75610d565efSmrg bhs LSYM(Loop3) 757*ec02198aSmrg lsls divisor, #1 758*ec02198aSmrg lsls curbit, #1 75910d565efSmrg b LSYM(Loop2) 76010d565efSmrgLSYM(Loop3): 76110d565efSmrg @ Test for possible subtractions ... 76210d565efSmrg .if \modulo 76310d565efSmrg @ ... On the final pass, this may subtract too much from the dividend, 76410d565efSmrg @ so keep track of which subtractions are done, we can fix them up 76510d565efSmrg @ afterwards. 766*ec02198aSmrg movs overdone, #0 76710d565efSmrg cmp dividend, divisor 76810d565efSmrg blo LSYM(Lover1) 769*ec02198aSmrg subs dividend, dividend, divisor 77010d565efSmrgLSYM(Lover1): 771*ec02198aSmrg lsrs work, divisor, #1 77210d565efSmrg cmp dividend, work 77310d565efSmrg blo LSYM(Lover2) 774*ec02198aSmrg subs dividend, dividend, work 77510d565efSmrg mov ip, curbit 776*ec02198aSmrg movs work, #1 777*ec02198aSmrg rors curbit, work 778*ec02198aSmrg orrs overdone, curbit 77910d565efSmrg mov curbit, ip 78010d565efSmrgLSYM(Lover2): 781*ec02198aSmrg lsrs work, divisor, #2 78210d565efSmrg cmp dividend, work 78310d565efSmrg blo LSYM(Lover3) 784*ec02198aSmrg subs dividend, dividend, work 78510d565efSmrg mov ip, curbit 786*ec02198aSmrg movs work, #2 787*ec02198aSmrg rors curbit, work 788*ec02198aSmrg orrs overdone, curbit 78910d565efSmrg mov curbit, ip 79010d565efSmrgLSYM(Lover3): 791*ec02198aSmrg lsrs work, divisor, #3 79210d565efSmrg cmp dividend, work 79310d565efSmrg blo LSYM(Lover4) 794*ec02198aSmrg subs dividend, dividend, work 79510d565efSmrg mov ip, curbit 796*ec02198aSmrg movs work, #3 797*ec02198aSmrg rors curbit, work 798*ec02198aSmrg orrs overdone, curbit 79910d565efSmrg mov curbit, ip 80010d565efSmrgLSYM(Lover4): 80110d565efSmrg mov ip, curbit 80210d565efSmrg .else 80310d565efSmrg @ ... and note which bits are done in the result. On the final pass, 80410d565efSmrg @ this may subtract too much from the dividend, but the result will be ok, 80510d565efSmrg @ since the "bit" will have been shifted out at the bottom. 80610d565efSmrg cmp dividend, divisor 80710d565efSmrg blo LSYM(Lover1) 808*ec02198aSmrg subs dividend, dividend, divisor 809*ec02198aSmrg orrs result, result, curbit 81010d565efSmrgLSYM(Lover1): 811*ec02198aSmrg lsrs work, divisor, #1 81210d565efSmrg cmp dividend, work 81310d565efSmrg blo LSYM(Lover2) 814*ec02198aSmrg subs dividend, dividend, work 815*ec02198aSmrg lsrs work, curbit, #1 816*ec02198aSmrg orrs result, work 81710d565efSmrgLSYM(Lover2): 818*ec02198aSmrg lsrs work, divisor, #2 81910d565efSmrg cmp dividend, work 82010d565efSmrg blo LSYM(Lover3) 821*ec02198aSmrg subs dividend, dividend, work 822*ec02198aSmrg lsrs work, curbit, #2 823*ec02198aSmrg orrs result, work 82410d565efSmrgLSYM(Lover3): 825*ec02198aSmrg lsrs work, divisor, #3 82610d565efSmrg cmp dividend, work 82710d565efSmrg blo LSYM(Lover4) 828*ec02198aSmrg subs dividend, dividend, work 829*ec02198aSmrg lsrs work, curbit, #3 830*ec02198aSmrg orrs result, work 83110d565efSmrgLSYM(Lover4): 83210d565efSmrg .endif 83310d565efSmrg 83410d565efSmrg cmp dividend, #0 @ Early termination? 83510d565efSmrg beq LSYM(Lover5) 836*ec02198aSmrg lsrs curbit, #4 @ No, any more bits to do? 83710d565efSmrg beq LSYM(Lover5) 838*ec02198aSmrg lsrs divisor, #4 83910d565efSmrg b LSYM(Loop3) 84010d565efSmrgLSYM(Lover5): 84110d565efSmrg .if \modulo 84210d565efSmrg @ Any subtractions that we should not have done will be recorded in 84310d565efSmrg @ the top three bits of "overdone". Exactly which were not needed 84410d565efSmrg @ are governed by the position of the bit, stored in ip. 845*ec02198aSmrg movs work, #0xe 846*ec02198aSmrg lsls work, #28 847*ec02198aSmrg ands overdone, work 84810d565efSmrg beq LSYM(Lgot_result) 84910d565efSmrg 85010d565efSmrg @ If we terminated early, because dividend became zero, then the 85110d565efSmrg @ bit in ip will not be in the bottom nibble, and we should not 85210d565efSmrg @ perform the additions below. We must test for this though 85310d565efSmrg @ (rather relying upon the TSTs to prevent the additions) since 85410d565efSmrg @ the bit in ip could be in the top two bits which might then match 85510d565efSmrg @ with one of the smaller RORs. 85610d565efSmrg mov curbit, ip 857*ec02198aSmrg movs work, #0x7 85810d565efSmrg tst curbit, work 85910d565efSmrg beq LSYM(Lgot_result) 86010d565efSmrg 86110d565efSmrg mov curbit, ip 862*ec02198aSmrg movs work, #3 863*ec02198aSmrg rors curbit, work 86410d565efSmrg tst overdone, curbit 86510d565efSmrg beq LSYM(Lover6) 866*ec02198aSmrg lsrs work, divisor, #3 867*ec02198aSmrg adds dividend, work 86810d565efSmrgLSYM(Lover6): 86910d565efSmrg mov curbit, ip 870*ec02198aSmrg movs work, #2 871*ec02198aSmrg rors curbit, work 87210d565efSmrg tst overdone, curbit 87310d565efSmrg beq LSYM(Lover7) 874*ec02198aSmrg lsrs work, divisor, #2 875*ec02198aSmrg adds dividend, work 87610d565efSmrgLSYM(Lover7): 87710d565efSmrg mov curbit, ip 878*ec02198aSmrg movs work, #1 879*ec02198aSmrg rors curbit, work 88010d565efSmrg tst overdone, curbit 88110d565efSmrg beq LSYM(Lgot_result) 882*ec02198aSmrg lsrs work, divisor, #1 883*ec02198aSmrg adds dividend, work 88410d565efSmrg .endif 88510d565efSmrgLSYM(Lgot_result): 88610d565efSmrg.endm 88710d565efSmrg 88810d565efSmrg/* If performance is preferred, the following functions are provided. */ 88910d565efSmrg#if defined(__prefer_thumb__) && !defined(__OPTIMIZE_SIZE__) 89010d565efSmrg 89110d565efSmrg/* Branch to div(n), and jump to label if curbit is lo than divisior. */ 89210d565efSmrg.macro BranchToDiv n, label 893*ec02198aSmrg lsrs curbit, dividend, \n 89410d565efSmrg cmp curbit, divisor 89510d565efSmrg blo \label 89610d565efSmrg.endm 89710d565efSmrg 89810d565efSmrg/* Body of div(n). Shift the divisor in n bits and compare the divisor 89910d565efSmrg and dividend. Update the dividend as the substruction result. */ 90010d565efSmrg.macro DoDiv n 901*ec02198aSmrg lsrs curbit, dividend, \n 90210d565efSmrg cmp curbit, divisor 90310d565efSmrg bcc 1f 904*ec02198aSmrg lsls curbit, divisor, \n 905*ec02198aSmrg subs dividend, dividend, curbit 90610d565efSmrg 907*ec02198aSmrg1: adcs result, result 90810d565efSmrg.endm 90910d565efSmrg 91010d565efSmrg/* The body of division with positive divisor. Unless the divisor is very 91110d565efSmrg big, shift it up in multiples of four bits, since this is the amount of 91210d565efSmrg unwinding in the main division loop. Continue shifting until the divisor 91310d565efSmrg is larger than the dividend. */ 91410d565efSmrg.macro THUMB1_Div_Positive 915*ec02198aSmrg movs result, #0 91610d565efSmrg BranchToDiv #1, LSYM(Lthumb1_div1) 91710d565efSmrg BranchToDiv #4, LSYM(Lthumb1_div4) 91810d565efSmrg BranchToDiv #8, LSYM(Lthumb1_div8) 91910d565efSmrg BranchToDiv #12, LSYM(Lthumb1_div12) 92010d565efSmrg BranchToDiv #16, LSYM(Lthumb1_div16) 92110d565efSmrgLSYM(Lthumb1_div_large_positive): 922*ec02198aSmrg movs result, #0xff 923*ec02198aSmrg lsls divisor, divisor, #8 92410d565efSmrg rev result, result 925*ec02198aSmrg lsrs curbit, dividend, #16 92610d565efSmrg cmp curbit, divisor 92710d565efSmrg blo 1f 928*ec02198aSmrg asrs result, #8 929*ec02198aSmrg lsls divisor, divisor, #8 93010d565efSmrg beq LSYM(Ldivbyzero_waypoint) 93110d565efSmrg 932*ec02198aSmrg1: lsrs curbit, dividend, #12 93310d565efSmrg cmp curbit, divisor 93410d565efSmrg blo LSYM(Lthumb1_div12) 93510d565efSmrg b LSYM(Lthumb1_div16) 93610d565efSmrgLSYM(Lthumb1_div_loop): 937*ec02198aSmrg lsrs divisor, divisor, #8 93810d565efSmrgLSYM(Lthumb1_div16): 93910d565efSmrg Dodiv #15 94010d565efSmrg Dodiv #14 94110d565efSmrg Dodiv #13 94210d565efSmrg Dodiv #12 94310d565efSmrgLSYM(Lthumb1_div12): 94410d565efSmrg Dodiv #11 94510d565efSmrg Dodiv #10 94610d565efSmrg Dodiv #9 94710d565efSmrg Dodiv #8 94810d565efSmrg bcs LSYM(Lthumb1_div_loop) 94910d565efSmrgLSYM(Lthumb1_div8): 95010d565efSmrg Dodiv #7 95110d565efSmrg Dodiv #6 95210d565efSmrg Dodiv #5 95310d565efSmrgLSYM(Lthumb1_div5): 95410d565efSmrg Dodiv #4 95510d565efSmrgLSYM(Lthumb1_div4): 95610d565efSmrg Dodiv #3 95710d565efSmrgLSYM(Lthumb1_div3): 95810d565efSmrg Dodiv #2 95910d565efSmrgLSYM(Lthumb1_div2): 96010d565efSmrg Dodiv #1 96110d565efSmrgLSYM(Lthumb1_div1): 962*ec02198aSmrg subs divisor, dividend, divisor 96310d565efSmrg bcs 1f 96410d565efSmrg cpy divisor, dividend 96510d565efSmrg 966*ec02198aSmrg1: adcs result, result 96710d565efSmrg cpy dividend, result 96810d565efSmrg RET 96910d565efSmrg 97010d565efSmrgLSYM(Ldivbyzero_waypoint): 97110d565efSmrg b LSYM(Ldiv0) 97210d565efSmrg.endm 97310d565efSmrg 97410d565efSmrg/* The body of division with negative divisor. Similar with 97510d565efSmrg THUMB1_Div_Positive except that the shift steps are in multiples 97610d565efSmrg of six bits. */ 97710d565efSmrg.macro THUMB1_Div_Negative 978*ec02198aSmrg lsrs result, divisor, #31 97910d565efSmrg beq 1f 980*ec02198aSmrg negs divisor, divisor 98110d565efSmrg 982*ec02198aSmrg1: asrs curbit, dividend, #32 98310d565efSmrg bcc 2f 984*ec02198aSmrg negs dividend, dividend 98510d565efSmrg 986*ec02198aSmrg2: eors curbit, result 987*ec02198aSmrg movs result, #0 98810d565efSmrg cpy ip, curbit 98910d565efSmrg BranchToDiv #4, LSYM(Lthumb1_div_negative4) 99010d565efSmrg BranchToDiv #8, LSYM(Lthumb1_div_negative8) 99110d565efSmrgLSYM(Lthumb1_div_large): 992*ec02198aSmrg movs result, #0xfc 993*ec02198aSmrg lsls divisor, divisor, #6 99410d565efSmrg rev result, result 995*ec02198aSmrg lsrs curbit, dividend, #8 99610d565efSmrg cmp curbit, divisor 99710d565efSmrg blo LSYM(Lthumb1_div_negative8) 99810d565efSmrg 999*ec02198aSmrg lsls divisor, divisor, #6 1000*ec02198aSmrg asrs result, result, #6 100110d565efSmrg cmp curbit, divisor 100210d565efSmrg blo LSYM(Lthumb1_div_negative8) 100310d565efSmrg 1004*ec02198aSmrg lsls divisor, divisor, #6 1005*ec02198aSmrg asrs result, result, #6 100610d565efSmrg cmp curbit, divisor 100710d565efSmrg blo LSYM(Lthumb1_div_negative8) 100810d565efSmrg 1009*ec02198aSmrg lsls divisor, divisor, #6 101010d565efSmrg beq LSYM(Ldivbyzero_negative) 1011*ec02198aSmrg asrs result, result, #6 101210d565efSmrg b LSYM(Lthumb1_div_negative8) 101310d565efSmrgLSYM(Lthumb1_div_negative_loop): 1014*ec02198aSmrg lsrs divisor, divisor, #6 101510d565efSmrgLSYM(Lthumb1_div_negative8): 101610d565efSmrg DoDiv #7 101710d565efSmrg DoDiv #6 101810d565efSmrg DoDiv #5 101910d565efSmrg DoDiv #4 102010d565efSmrgLSYM(Lthumb1_div_negative4): 102110d565efSmrg DoDiv #3 102210d565efSmrg DoDiv #2 102310d565efSmrg bcs LSYM(Lthumb1_div_negative_loop) 102410d565efSmrg DoDiv #1 1025*ec02198aSmrg subs divisor, dividend, divisor 102610d565efSmrg bcs 1f 102710d565efSmrg cpy divisor, dividend 102810d565efSmrg 102910d565efSmrg1: cpy curbit, ip 1030*ec02198aSmrg adcs result, result 1031*ec02198aSmrg asrs curbit, curbit, #1 103210d565efSmrg cpy dividend, result 103310d565efSmrg bcc 2f 1034*ec02198aSmrg negs dividend, dividend 103510d565efSmrg cmp curbit, #0 103610d565efSmrg 103710d565efSmrg2: bpl 3f 1038*ec02198aSmrg negs divisor, divisor 103910d565efSmrg 104010d565efSmrg3: RET 104110d565efSmrg 104210d565efSmrgLSYM(Ldivbyzero_negative): 104310d565efSmrg cpy curbit, ip 1044*ec02198aSmrg asrs curbit, curbit, #1 104510d565efSmrg bcc LSYM(Ldiv0) 1046*ec02198aSmrg negs dividend, dividend 104710d565efSmrg.endm 104810d565efSmrg#endif /* ARM Thumb version. */ 104910d565efSmrg 105010d565efSmrg/* ------------------------------------------------------------------------ */ 105110d565efSmrg/* Start of the Real Functions */ 105210d565efSmrg/* ------------------------------------------------------------------------ */ 105310d565efSmrg#ifdef L_udivsi3 105410d565efSmrg 105510d565efSmrg#if defined(__prefer_thumb__) 105610d565efSmrg 105710d565efSmrg FUNC_START udivsi3 105810d565efSmrg FUNC_ALIAS aeabi_uidiv udivsi3 105910d565efSmrg#if defined(__OPTIMIZE_SIZE__) 106010d565efSmrg 106110d565efSmrg cmp divisor, #0 106210d565efSmrg beq LSYM(Ldiv0) 106310d565efSmrgLSYM(udivsi3_skip_div0_test): 1064*ec02198aSmrg movs curbit, #1 1065*ec02198aSmrg movs result, #0 106610d565efSmrg 106710d565efSmrg push { work } 106810d565efSmrg cmp dividend, divisor 106910d565efSmrg blo LSYM(Lgot_result) 107010d565efSmrg 107110d565efSmrg THUMB_DIV_MOD_BODY 0 107210d565efSmrg 1073*ec02198aSmrg movs r0, result 107410d565efSmrg pop { work } 107510d565efSmrg RET 107610d565efSmrg 107710d565efSmrg/* Implementation of aeabi_uidiv for ARMv6m. This version is only 107810d565efSmrg used in ARMv6-M when we need an efficient implementation. */ 107910d565efSmrg#else 108010d565efSmrgLSYM(udivsi3_skip_div0_test): 108110d565efSmrg THUMB1_Div_Positive 108210d565efSmrg 108310d565efSmrg#endif /* __OPTIMIZE_SIZE__ */ 108410d565efSmrg 108510d565efSmrg#elif defined(__ARM_ARCH_EXT_IDIV__) 108610d565efSmrg 108710d565efSmrg ARM_FUNC_START udivsi3 108810d565efSmrg ARM_FUNC_ALIAS aeabi_uidiv udivsi3 108910d565efSmrg 109010d565efSmrg cmp r1, #0 109110d565efSmrg beq LSYM(Ldiv0) 109210d565efSmrg 109310d565efSmrg udiv r0, r0, r1 109410d565efSmrg RET 109510d565efSmrg 109610d565efSmrg#else /* ARM version/Thumb-2. */ 109710d565efSmrg 109810d565efSmrg ARM_FUNC_START udivsi3 109910d565efSmrg ARM_FUNC_ALIAS aeabi_uidiv udivsi3 110010d565efSmrg 110110d565efSmrg /* Note: if called via udivsi3_skip_div0_test, this will unnecessarily 110210d565efSmrg check for division-by-zero a second time. */ 110310d565efSmrgLSYM(udivsi3_skip_div0_test): 110410d565efSmrg subs r2, r1, #1 110510d565efSmrg do_it eq 110610d565efSmrg RETc(eq) 110710d565efSmrg bcc LSYM(Ldiv0) 110810d565efSmrg cmp r0, r1 110910d565efSmrg bls 11f 111010d565efSmrg tst r1, r2 111110d565efSmrg beq 12f 111210d565efSmrg 111310d565efSmrg ARM_DIV_BODY r0, r1, r2, r3 111410d565efSmrg 111510d565efSmrg mov r0, r2 111610d565efSmrg RET 111710d565efSmrg 111810d565efSmrg11: do_it eq, e 111910d565efSmrg moveq r0, #1 112010d565efSmrg movne r0, #0 112110d565efSmrg RET 112210d565efSmrg 112310d565efSmrg12: ARM_DIV2_ORDER r1, r2 112410d565efSmrg 112510d565efSmrg mov r0, r0, lsr r2 112610d565efSmrg RET 112710d565efSmrg 112810d565efSmrg#endif /* ARM version */ 112910d565efSmrg 113010d565efSmrg DIV_FUNC_END udivsi3 unsigned 113110d565efSmrg 113210d565efSmrg#if defined(__prefer_thumb__) 113310d565efSmrgFUNC_START aeabi_uidivmod 113410d565efSmrg cmp r1, #0 113510d565efSmrg beq LSYM(Ldiv0) 113610d565efSmrg# if defined(__OPTIMIZE_SIZE__) 113710d565efSmrg push {r0, r1, lr} 113810d565efSmrg bl LSYM(udivsi3_skip_div0_test) 113910d565efSmrg POP {r1, r2, r3} 1140*ec02198aSmrg muls r2, r0 1141*ec02198aSmrg subs r1, r1, r2 114210d565efSmrg bx r3 114310d565efSmrg# else 114410d565efSmrg /* Both the quotient and remainder are calculated simultaneously 114510d565efSmrg in THUMB1_Div_Positive. There is no need to calculate the 114610d565efSmrg remainder again here. */ 114710d565efSmrg b LSYM(udivsi3_skip_div0_test) 114810d565efSmrg RET 114910d565efSmrg# endif /* __OPTIMIZE_SIZE__ */ 115010d565efSmrg 115110d565efSmrg#elif defined(__ARM_ARCH_EXT_IDIV__) 115210d565efSmrgARM_FUNC_START aeabi_uidivmod 115310d565efSmrg cmp r1, #0 115410d565efSmrg beq LSYM(Ldiv0) 115510d565efSmrg mov r2, r0 115610d565efSmrg udiv r0, r0, r1 115710d565efSmrg mls r1, r0, r1, r2 115810d565efSmrg RET 115910d565efSmrg#else 116010d565efSmrgARM_FUNC_START aeabi_uidivmod 116110d565efSmrg cmp r1, #0 116210d565efSmrg beq LSYM(Ldiv0) 116310d565efSmrg stmfd sp!, { r0, r1, lr } 116410d565efSmrg bl LSYM(udivsi3_skip_div0_test) 116510d565efSmrg ldmfd sp!, { r1, r2, lr } 116610d565efSmrg mul r3, r2, r0 116710d565efSmrg sub r1, r1, r3 116810d565efSmrg RET 116910d565efSmrg#endif 117010d565efSmrg FUNC_END aeabi_uidivmod 117110d565efSmrg 117210d565efSmrg#endif /* L_udivsi3 */ 117310d565efSmrg/* ------------------------------------------------------------------------ */ 117410d565efSmrg#ifdef L_umodsi3 117510d565efSmrg 117610d565efSmrg#if defined(__ARM_ARCH_EXT_IDIV__) && __ARM_ARCH_ISA_THUMB != 1 117710d565efSmrg 117810d565efSmrg ARM_FUNC_START umodsi3 117910d565efSmrg 118010d565efSmrg cmp r1, #0 118110d565efSmrg beq LSYM(Ldiv0) 118210d565efSmrg udiv r2, r0, r1 118310d565efSmrg mls r0, r1, r2, r0 118410d565efSmrg RET 118510d565efSmrg 118610d565efSmrg#elif defined(__thumb__) 118710d565efSmrg 118810d565efSmrg FUNC_START umodsi3 118910d565efSmrg 119010d565efSmrg cmp divisor, #0 119110d565efSmrg beq LSYM(Ldiv0) 1192*ec02198aSmrg movs curbit, #1 119310d565efSmrg cmp dividend, divisor 119410d565efSmrg bhs LSYM(Lover10) 119510d565efSmrg RET 119610d565efSmrg 119710d565efSmrgLSYM(Lover10): 119810d565efSmrg push { work } 119910d565efSmrg 120010d565efSmrg THUMB_DIV_MOD_BODY 1 120110d565efSmrg 120210d565efSmrg pop { work } 120310d565efSmrg RET 120410d565efSmrg 120510d565efSmrg#else /* ARM version. */ 120610d565efSmrg 120710d565efSmrg FUNC_START umodsi3 120810d565efSmrg 120910d565efSmrg subs r2, r1, #1 @ compare divisor with 1 121010d565efSmrg bcc LSYM(Ldiv0) 121110d565efSmrg cmpne r0, r1 @ compare dividend with divisor 121210d565efSmrg moveq r0, #0 121310d565efSmrg tsthi r1, r2 @ see if divisor is power of 2 121410d565efSmrg andeq r0, r0, r2 121510d565efSmrg RETc(ls) 121610d565efSmrg 121710d565efSmrg ARM_MOD_BODY r0, r1, r2, r3 121810d565efSmrg 121910d565efSmrg RET 122010d565efSmrg 122110d565efSmrg#endif /* ARM version. */ 122210d565efSmrg 122310d565efSmrg DIV_FUNC_END umodsi3 unsigned 122410d565efSmrg 122510d565efSmrg#endif /* L_umodsi3 */ 122610d565efSmrg/* ------------------------------------------------------------------------ */ 122710d565efSmrg#ifdef L_divsi3 122810d565efSmrg 122910d565efSmrg#if defined(__prefer_thumb__) 123010d565efSmrg 123110d565efSmrg FUNC_START divsi3 123210d565efSmrg FUNC_ALIAS aeabi_idiv divsi3 123310d565efSmrg#if defined(__OPTIMIZE_SIZE__) 123410d565efSmrg 123510d565efSmrg cmp divisor, #0 123610d565efSmrg beq LSYM(Ldiv0) 123710d565efSmrgLSYM(divsi3_skip_div0_test): 123810d565efSmrg push { work } 1239*ec02198aSmrg movs work, dividend 1240*ec02198aSmrg eors work, divisor @ Save the sign of the result. 124110d565efSmrg mov ip, work 1242*ec02198aSmrg movs curbit, #1 1243*ec02198aSmrg movs result, #0 124410d565efSmrg cmp divisor, #0 124510d565efSmrg bpl LSYM(Lover10) 1246*ec02198aSmrg negs divisor, divisor @ Loops below use unsigned. 124710d565efSmrgLSYM(Lover10): 124810d565efSmrg cmp dividend, #0 124910d565efSmrg bpl LSYM(Lover11) 1250*ec02198aSmrg negs dividend, dividend 125110d565efSmrgLSYM(Lover11): 125210d565efSmrg cmp dividend, divisor 125310d565efSmrg blo LSYM(Lgot_result) 125410d565efSmrg 125510d565efSmrg THUMB_DIV_MOD_BODY 0 125610d565efSmrg 1257*ec02198aSmrg movs r0, result 125810d565efSmrg mov work, ip 125910d565efSmrg cmp work, #0 126010d565efSmrg bpl LSYM(Lover12) 1261*ec02198aSmrg negs r0, r0 126210d565efSmrgLSYM(Lover12): 126310d565efSmrg pop { work } 126410d565efSmrg RET 126510d565efSmrg 126610d565efSmrg/* Implementation of aeabi_idiv for ARMv6m. This version is only 126710d565efSmrg used in ARMv6-M when we need an efficient implementation. */ 126810d565efSmrg#else 126910d565efSmrgLSYM(divsi3_skip_div0_test): 127010d565efSmrg cpy curbit, dividend 1271*ec02198aSmrg orrs curbit, divisor 127210d565efSmrg bmi LSYM(Lthumb1_div_negative) 127310d565efSmrg 127410d565efSmrgLSYM(Lthumb1_div_positive): 127510d565efSmrg THUMB1_Div_Positive 127610d565efSmrg 127710d565efSmrgLSYM(Lthumb1_div_negative): 127810d565efSmrg THUMB1_Div_Negative 127910d565efSmrg 128010d565efSmrg#endif /* __OPTIMIZE_SIZE__ */ 128110d565efSmrg 128210d565efSmrg#elif defined(__ARM_ARCH_EXT_IDIV__) 128310d565efSmrg 128410d565efSmrg ARM_FUNC_START divsi3 128510d565efSmrg ARM_FUNC_ALIAS aeabi_idiv divsi3 128610d565efSmrg 128710d565efSmrg cmp r1, #0 128810d565efSmrg beq LSYM(Ldiv0) 128910d565efSmrg sdiv r0, r0, r1 129010d565efSmrg RET 129110d565efSmrg 129210d565efSmrg#else /* ARM/Thumb-2 version. */ 129310d565efSmrg 129410d565efSmrg ARM_FUNC_START divsi3 129510d565efSmrg ARM_FUNC_ALIAS aeabi_idiv divsi3 129610d565efSmrg 129710d565efSmrg cmp r1, #0 129810d565efSmrg beq LSYM(Ldiv0) 129910d565efSmrgLSYM(divsi3_skip_div0_test): 130010d565efSmrg eor ip, r0, r1 @ save the sign of the result. 130110d565efSmrg do_it mi 130210d565efSmrg rsbmi r1, r1, #0 @ loops below use unsigned. 130310d565efSmrg subs r2, r1, #1 @ division by 1 or -1 ? 130410d565efSmrg beq 10f 130510d565efSmrg movs r3, r0 130610d565efSmrg do_it mi 130710d565efSmrg rsbmi r3, r0, #0 @ positive dividend value 130810d565efSmrg cmp r3, r1 130910d565efSmrg bls 11f 131010d565efSmrg tst r1, r2 @ divisor is power of 2 ? 131110d565efSmrg beq 12f 131210d565efSmrg 131310d565efSmrg ARM_DIV_BODY r3, r1, r0, r2 131410d565efSmrg 131510d565efSmrg cmp ip, #0 131610d565efSmrg do_it mi 131710d565efSmrg rsbmi r0, r0, #0 131810d565efSmrg RET 131910d565efSmrg 132010d565efSmrg10: teq ip, r0 @ same sign ? 132110d565efSmrg do_it mi 132210d565efSmrg rsbmi r0, r0, #0 132310d565efSmrg RET 132410d565efSmrg 132510d565efSmrg11: do_it lo 132610d565efSmrg movlo r0, #0 132710d565efSmrg do_it eq,t 132810d565efSmrg moveq r0, ip, asr #31 132910d565efSmrg orreq r0, r0, #1 133010d565efSmrg RET 133110d565efSmrg 133210d565efSmrg12: ARM_DIV2_ORDER r1, r2 133310d565efSmrg 133410d565efSmrg cmp ip, #0 133510d565efSmrg mov r0, r3, lsr r2 133610d565efSmrg do_it mi 133710d565efSmrg rsbmi r0, r0, #0 133810d565efSmrg RET 133910d565efSmrg 134010d565efSmrg#endif /* ARM version */ 134110d565efSmrg 134210d565efSmrg DIV_FUNC_END divsi3 signed 134310d565efSmrg 134410d565efSmrg#if defined(__prefer_thumb__) 134510d565efSmrgFUNC_START aeabi_idivmod 134610d565efSmrg cmp r1, #0 134710d565efSmrg beq LSYM(Ldiv0) 134810d565efSmrg# if defined(__OPTIMIZE_SIZE__) 134910d565efSmrg push {r0, r1, lr} 135010d565efSmrg bl LSYM(divsi3_skip_div0_test) 135110d565efSmrg POP {r1, r2, r3} 1352*ec02198aSmrg muls r2, r0 1353*ec02198aSmrg subs r1, r1, r2 135410d565efSmrg bx r3 135510d565efSmrg# else 135610d565efSmrg /* Both the quotient and remainder are calculated simultaneously 135710d565efSmrg in THUMB1_Div_Positive and THUMB1_Div_Negative. There is no 135810d565efSmrg need to calculate the remainder again here. */ 135910d565efSmrg b LSYM(divsi3_skip_div0_test) 136010d565efSmrg RET 136110d565efSmrg# endif /* __OPTIMIZE_SIZE__ */ 136210d565efSmrg 136310d565efSmrg#elif defined(__ARM_ARCH_EXT_IDIV__) 136410d565efSmrgARM_FUNC_START aeabi_idivmod 136510d565efSmrg cmp r1, #0 136610d565efSmrg beq LSYM(Ldiv0) 136710d565efSmrg mov r2, r0 136810d565efSmrg sdiv r0, r0, r1 136910d565efSmrg mls r1, r0, r1, r2 137010d565efSmrg RET 137110d565efSmrg#else 137210d565efSmrgARM_FUNC_START aeabi_idivmod 137310d565efSmrg cmp r1, #0 137410d565efSmrg beq LSYM(Ldiv0) 137510d565efSmrg stmfd sp!, { r0, r1, lr } 137610d565efSmrg bl LSYM(divsi3_skip_div0_test) 137710d565efSmrg ldmfd sp!, { r1, r2, lr } 137810d565efSmrg mul r3, r2, r0 137910d565efSmrg sub r1, r1, r3 138010d565efSmrg RET 138110d565efSmrg#endif 138210d565efSmrg FUNC_END aeabi_idivmod 138310d565efSmrg 138410d565efSmrg#endif /* L_divsi3 */ 138510d565efSmrg/* ------------------------------------------------------------------------ */ 138610d565efSmrg#ifdef L_modsi3 138710d565efSmrg 138810d565efSmrg#if defined(__ARM_ARCH_EXT_IDIV__) && __ARM_ARCH_ISA_THUMB != 1 138910d565efSmrg 139010d565efSmrg ARM_FUNC_START modsi3 139110d565efSmrg 139210d565efSmrg cmp r1, #0 139310d565efSmrg beq LSYM(Ldiv0) 139410d565efSmrg 139510d565efSmrg sdiv r2, r0, r1 139610d565efSmrg mls r0, r1, r2, r0 139710d565efSmrg RET 139810d565efSmrg 139910d565efSmrg#elif defined(__thumb__) 140010d565efSmrg 140110d565efSmrg FUNC_START modsi3 140210d565efSmrg 1403*ec02198aSmrg movs curbit, #1 140410d565efSmrg cmp divisor, #0 140510d565efSmrg beq LSYM(Ldiv0) 140610d565efSmrg bpl LSYM(Lover10) 1407*ec02198aSmrg negs divisor, divisor @ Loops below use unsigned. 140810d565efSmrgLSYM(Lover10): 140910d565efSmrg push { work } 141010d565efSmrg @ Need to save the sign of the dividend, unfortunately, we need 141110d565efSmrg @ work later on. Must do this after saving the original value of 141210d565efSmrg @ the work register, because we will pop this value off first. 141310d565efSmrg push { dividend } 141410d565efSmrg cmp dividend, #0 141510d565efSmrg bpl LSYM(Lover11) 1416*ec02198aSmrg negs dividend, dividend 141710d565efSmrgLSYM(Lover11): 141810d565efSmrg cmp dividend, divisor 141910d565efSmrg blo LSYM(Lgot_result) 142010d565efSmrg 142110d565efSmrg THUMB_DIV_MOD_BODY 1 142210d565efSmrg 142310d565efSmrg pop { work } 142410d565efSmrg cmp work, #0 142510d565efSmrg bpl LSYM(Lover12) 1426*ec02198aSmrg negs dividend, dividend 142710d565efSmrgLSYM(Lover12): 142810d565efSmrg pop { work } 142910d565efSmrg RET 143010d565efSmrg 143110d565efSmrg#else /* ARM version. */ 143210d565efSmrg 143310d565efSmrg FUNC_START modsi3 143410d565efSmrg 143510d565efSmrg cmp r1, #0 143610d565efSmrg beq LSYM(Ldiv0) 143710d565efSmrg rsbmi r1, r1, #0 @ loops below use unsigned. 143810d565efSmrg movs ip, r0 @ preserve sign of dividend 143910d565efSmrg rsbmi r0, r0, #0 @ if negative make positive 144010d565efSmrg subs r2, r1, #1 @ compare divisor with 1 144110d565efSmrg cmpne r0, r1 @ compare dividend with divisor 144210d565efSmrg moveq r0, #0 144310d565efSmrg tsthi r1, r2 @ see if divisor is power of 2 144410d565efSmrg andeq r0, r0, r2 144510d565efSmrg bls 10f 144610d565efSmrg 144710d565efSmrg ARM_MOD_BODY r0, r1, r2, r3 144810d565efSmrg 144910d565efSmrg10: cmp ip, #0 145010d565efSmrg rsbmi r0, r0, #0 145110d565efSmrg RET 145210d565efSmrg 145310d565efSmrg#endif /* ARM version */ 145410d565efSmrg 145510d565efSmrg DIV_FUNC_END modsi3 signed 145610d565efSmrg 145710d565efSmrg#endif /* L_modsi3 */ 145810d565efSmrg/* ------------------------------------------------------------------------ */ 145910d565efSmrg#ifdef L_dvmd_tls 146010d565efSmrg 146110d565efSmrg#ifdef __ARM_EABI__ 146210d565efSmrg WEAK aeabi_idiv0 146310d565efSmrg WEAK aeabi_ldiv0 146410d565efSmrg FUNC_START aeabi_idiv0 146510d565efSmrg FUNC_START aeabi_ldiv0 146610d565efSmrg RET 146710d565efSmrg FUNC_END aeabi_ldiv0 146810d565efSmrg FUNC_END aeabi_idiv0 146910d565efSmrg#else 147010d565efSmrg FUNC_START div0 147110d565efSmrg RET 147210d565efSmrg FUNC_END div0 147310d565efSmrg#endif 147410d565efSmrg 147510d565efSmrg#endif /* L_divmodsi_tools */ 147610d565efSmrg/* ------------------------------------------------------------------------ */ 147710d565efSmrg#ifdef L_dvmd_lnx 147810d565efSmrg@ GNU/Linux division-by zero handler. Used in place of L_dvmd_tls 147910d565efSmrg 148010d565efSmrg/* Constant taken from <asm/signal.h>. */ 148110d565efSmrg#define SIGFPE 8 148210d565efSmrg 148310d565efSmrg#ifdef __ARM_EABI__ 148410d565efSmrg cfi_start __aeabi_ldiv0, LSYM(Lend_aeabi_ldiv0) 148510d565efSmrg WEAK aeabi_idiv0 148610d565efSmrg WEAK aeabi_ldiv0 148710d565efSmrg ARM_FUNC_START aeabi_idiv0 148810d565efSmrg ARM_FUNC_START aeabi_ldiv0 148910d565efSmrg do_push {r1, lr} 149010d565efSmrg98: cfi_push 98b - __aeabi_ldiv0, 0xe, -0x4, 0x8 149110d565efSmrg#else 149210d565efSmrg cfi_start __div0, LSYM(Lend_div0) 149310d565efSmrg ARM_FUNC_START div0 149410d565efSmrg do_push {r1, lr} 149510d565efSmrg98: cfi_push 98b - __div0, 0xe, -0x4, 0x8 149610d565efSmrg#endif 149710d565efSmrg 149810d565efSmrg mov r0, #SIGFPE 149910d565efSmrg bl SYM(raise) __PLT__ 150010d565efSmrg RETLDM r1 unwind=98b 150110d565efSmrg 150210d565efSmrg#ifdef __ARM_EABI__ 150310d565efSmrg cfi_end LSYM(Lend_aeabi_ldiv0) 150410d565efSmrg FUNC_END aeabi_ldiv0 150510d565efSmrg FUNC_END aeabi_idiv0 150610d565efSmrg#else 150710d565efSmrg cfi_end LSYM(Lend_div0) 150810d565efSmrg FUNC_END div0 150910d565efSmrg#endif 151010d565efSmrg 151110d565efSmrg#endif /* L_dvmd_lnx */ 151210d565efSmrg#ifdef L_clear_cache 151310d565efSmrg#if defined __ARM_EABI__ && defined __linux__ 151410d565efSmrg@ EABI GNU/Linux call to cacheflush syscall. 151510d565efSmrg ARM_FUNC_START clear_cache 151610d565efSmrg do_push {r7} 15170fc04c29Smrg#if __ARM_ARCH >= 7 || defined(__ARM_ARCH_6T2__) 151810d565efSmrg movw r7, #2 151910d565efSmrg movt r7, #0xf 152010d565efSmrg#else 152110d565efSmrg mov r7, #0xf0000 152210d565efSmrg add r7, r7, #2 152310d565efSmrg#endif 152410d565efSmrg mov r2, #0 152510d565efSmrg swi 0 152610d565efSmrg do_pop {r7} 152710d565efSmrg RET 152810d565efSmrg FUNC_END clear_cache 152910d565efSmrg#else 153010d565efSmrg#error "This is only for ARM EABI GNU/Linux" 153110d565efSmrg#endif 153210d565efSmrg#endif /* L_clear_cache */ 15330fc04c29Smrg 15340fc04c29Smrg#ifdef L_speculation_barrier 15350fc04c29Smrg FUNC_START speculation_barrier 15360fc04c29Smrg#if __ARM_ARCH >= 7 15370fc04c29Smrg isb 15380fc04c29Smrg dsb sy 15390fc04c29Smrg#elif defined __ARM_EABI__ && defined __linux__ 15400fc04c29Smrg /* We don't have a speculation barrier directly for this 15410fc04c29Smrg platform/architecture variant. But we can use a kernel 15420fc04c29Smrg clear_cache service routine which will emit such instructions 15430fc04c29Smrg if run on a later version of the architecture. We don't 15440fc04c29Smrg really want to flush the cache, but we must give it a valid 15450fc04c29Smrg address, so just clear pc..pc+1. */ 15460fc04c29Smrg#if defined __thumb__ && !defined __thumb2__ 15470fc04c29Smrg push {r7} 1548*ec02198aSmrg movs r7, #0xf 1549*ec02198aSmrg lsls r7, #16 1550*ec02198aSmrg adds r7, #2 15510fc04c29Smrg adr r0, . + 4 1552*ec02198aSmrg adds r1, r0, #1 1553*ec02198aSmrg movs r2, #0 15540fc04c29Smrg svc 0 15550fc04c29Smrg pop {r7} 15560fc04c29Smrg#else 15570fc04c29Smrg do_push {r7} 15580fc04c29Smrg#ifdef __ARM_ARCH_6T2__ 15590fc04c29Smrg movw r7, #2 15600fc04c29Smrg movt r7, #0xf 15610fc04c29Smrg#else 15620fc04c29Smrg mov r7, #0xf0000 15630fc04c29Smrg add r7, r7, #2 15640fc04c29Smrg#endif 15650fc04c29Smrg add r0, pc, #0 /* ADR. */ 15660fc04c29Smrg add r1, r0, #1 15670fc04c29Smrg mov r2, #0 15680fc04c29Smrg svc 0 15690fc04c29Smrg do_pop {r7} 15700fc04c29Smrg#endif /* Thumb1 only */ 15710fc04c29Smrg#else 15720fc04c29Smrg#warning "No speculation barrier defined for this platform" 15730fc04c29Smrg#endif 15740fc04c29Smrg RET 15750fc04c29Smrg FUNC_END speculation_barrier 15760fc04c29Smrg#endif 157710d565efSmrg/* ------------------------------------------------------------------------ */ 157810d565efSmrg/* Dword shift operations. */ 157910d565efSmrg/* All the following Dword shift variants rely on the fact that 158010d565efSmrg shft xxx, Reg 158110d565efSmrg is in fact done as 158210d565efSmrg shft xxx, (Reg & 255) 158310d565efSmrg so for Reg value in (32...63) and (-1...-31) we will get zero (in the 158410d565efSmrg case of logical shifts) or the sign (for asr). */ 158510d565efSmrg 158610d565efSmrg#ifdef __ARMEB__ 158710d565efSmrg#define al r1 158810d565efSmrg#define ah r0 158910d565efSmrg#else 159010d565efSmrg#define al r0 159110d565efSmrg#define ah r1 159210d565efSmrg#endif 159310d565efSmrg 159410d565efSmrg/* Prevent __aeabi double-word shifts from being produced on SymbianOS. */ 159510d565efSmrg#ifndef __symbian__ 159610d565efSmrg 159710d565efSmrg#ifdef L_lshrdi3 159810d565efSmrg 159910d565efSmrg FUNC_START lshrdi3 160010d565efSmrg FUNC_ALIAS aeabi_llsr lshrdi3 160110d565efSmrg 160210d565efSmrg#ifdef __thumb__ 1603*ec02198aSmrg lsrs al, r2 1604*ec02198aSmrg movs r3, ah 1605*ec02198aSmrg lsrs ah, r2 160610d565efSmrg mov ip, r3 1607*ec02198aSmrg subs r2, #32 1608*ec02198aSmrg lsrs r3, r2 1609*ec02198aSmrg orrs al, r3 1610*ec02198aSmrg negs r2, r2 161110d565efSmrg mov r3, ip 1612*ec02198aSmrg lsls r3, r2 1613*ec02198aSmrg orrs al, r3 161410d565efSmrg RET 161510d565efSmrg#else 161610d565efSmrg subs r3, r2, #32 161710d565efSmrg rsb ip, r2, #32 161810d565efSmrg movmi al, al, lsr r2 161910d565efSmrg movpl al, ah, lsr r3 162010d565efSmrg orrmi al, al, ah, lsl ip 162110d565efSmrg mov ah, ah, lsr r2 162210d565efSmrg RET 162310d565efSmrg#endif 162410d565efSmrg FUNC_END aeabi_llsr 162510d565efSmrg FUNC_END lshrdi3 162610d565efSmrg 162710d565efSmrg#endif 162810d565efSmrg 162910d565efSmrg#ifdef L_ashrdi3 163010d565efSmrg 163110d565efSmrg FUNC_START ashrdi3 163210d565efSmrg FUNC_ALIAS aeabi_lasr ashrdi3 163310d565efSmrg 163410d565efSmrg#ifdef __thumb__ 1635*ec02198aSmrg lsrs al, r2 1636*ec02198aSmrg movs r3, ah 1637*ec02198aSmrg asrs ah, r2 1638*ec02198aSmrg subs r2, #32 163910d565efSmrg @ If r2 is negative at this point the following step would OR 164010d565efSmrg @ the sign bit into all of AL. That's not what we want... 164110d565efSmrg bmi 1f 164210d565efSmrg mov ip, r3 1643*ec02198aSmrg asrs r3, r2 1644*ec02198aSmrg orrs al, r3 164510d565efSmrg mov r3, ip 164610d565efSmrg1: 1647*ec02198aSmrg negs r2, r2 1648*ec02198aSmrg lsls r3, r2 1649*ec02198aSmrg orrs al, r3 165010d565efSmrg RET 165110d565efSmrg#else 165210d565efSmrg subs r3, r2, #32 165310d565efSmrg rsb ip, r2, #32 165410d565efSmrg movmi al, al, lsr r2 165510d565efSmrg movpl al, ah, asr r3 165610d565efSmrg orrmi al, al, ah, lsl ip 165710d565efSmrg mov ah, ah, asr r2 165810d565efSmrg RET 165910d565efSmrg#endif 166010d565efSmrg 166110d565efSmrg FUNC_END aeabi_lasr 166210d565efSmrg FUNC_END ashrdi3 166310d565efSmrg 166410d565efSmrg#endif 166510d565efSmrg 166610d565efSmrg#ifdef L_ashldi3 166710d565efSmrg 166810d565efSmrg FUNC_START ashldi3 166910d565efSmrg FUNC_ALIAS aeabi_llsl ashldi3 167010d565efSmrg 167110d565efSmrg#ifdef __thumb__ 1672*ec02198aSmrg lsls ah, r2 1673*ec02198aSmrg movs r3, al 1674*ec02198aSmrg lsls al, r2 167510d565efSmrg mov ip, r3 1676*ec02198aSmrg subs r2, #32 1677*ec02198aSmrg lsls r3, r2 1678*ec02198aSmrg orrs ah, r3 1679*ec02198aSmrg negs r2, r2 168010d565efSmrg mov r3, ip 1681*ec02198aSmrg lsrs r3, r2 1682*ec02198aSmrg orrs ah, r3 168310d565efSmrg RET 168410d565efSmrg#else 168510d565efSmrg subs r3, r2, #32 168610d565efSmrg rsb ip, r2, #32 168710d565efSmrg movmi ah, ah, lsl r2 168810d565efSmrg movpl ah, al, lsl r3 168910d565efSmrg orrmi ah, ah, al, lsr ip 169010d565efSmrg mov al, al, lsl r2 169110d565efSmrg RET 169210d565efSmrg#endif 169310d565efSmrg FUNC_END aeabi_llsl 169410d565efSmrg FUNC_END ashldi3 169510d565efSmrg 169610d565efSmrg#endif 169710d565efSmrg 169810d565efSmrg#endif /* __symbian__ */ 169910d565efSmrg 170010d565efSmrg#ifdef L_clzsi2 170110d565efSmrg#ifdef NOT_ISA_TARGET_32BIT 170210d565efSmrgFUNC_START clzsi2 1703*ec02198aSmrg movs r1, #28 1704*ec02198aSmrg movs r3, #1 1705*ec02198aSmrg lsls r3, r3, #16 170610d565efSmrg cmp r0, r3 /* 0x10000 */ 170710d565efSmrg bcc 2f 1708*ec02198aSmrg lsrs r0, r0, #16 1709*ec02198aSmrg subs r1, r1, #16 1710*ec02198aSmrg2: lsrs r3, r3, #8 171110d565efSmrg cmp r0, r3 /* #0x100 */ 171210d565efSmrg bcc 2f 1713*ec02198aSmrg lsrs r0, r0, #8 1714*ec02198aSmrg subs r1, r1, #8 1715*ec02198aSmrg2: lsrs r3, r3, #4 171610d565efSmrg cmp r0, r3 /* #0x10 */ 171710d565efSmrg bcc 2f 1718*ec02198aSmrg lsrs r0, r0, #4 1719*ec02198aSmrg subs r1, r1, #4 172010d565efSmrg2: adr r2, 1f 172110d565efSmrg ldrb r0, [r2, r0] 1722*ec02198aSmrg adds r0, r0, r1 172310d565efSmrg bx lr 172410d565efSmrg.align 2 172510d565efSmrg1: 172610d565efSmrg.byte 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 172710d565efSmrg FUNC_END clzsi2 172810d565efSmrg#else 172910d565efSmrgARM_FUNC_START clzsi2 17300fc04c29Smrg# if defined (__ARM_FEATURE_CLZ) 173110d565efSmrg clz r0, r0 173210d565efSmrg RET 173310d565efSmrg# else 173410d565efSmrg mov r1, #28 173510d565efSmrg cmp r0, #0x10000 173610d565efSmrg do_it cs, t 173710d565efSmrg movcs r0, r0, lsr #16 173810d565efSmrg subcs r1, r1, #16 173910d565efSmrg cmp r0, #0x100 174010d565efSmrg do_it cs, t 174110d565efSmrg movcs r0, r0, lsr #8 174210d565efSmrg subcs r1, r1, #8 174310d565efSmrg cmp r0, #0x10 174410d565efSmrg do_it cs, t 174510d565efSmrg movcs r0, r0, lsr #4 174610d565efSmrg subcs r1, r1, #4 174710d565efSmrg adr r2, 1f 174810d565efSmrg ldrb r0, [r2, r0] 174910d565efSmrg add r0, r0, r1 175010d565efSmrg RET 175110d565efSmrg.align 2 175210d565efSmrg1: 175310d565efSmrg.byte 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 17540fc04c29Smrg# endif /* !defined (__ARM_FEATURE_CLZ) */ 175510d565efSmrg FUNC_END clzsi2 175610d565efSmrg#endif 175710d565efSmrg#endif /* L_clzsi2 */ 175810d565efSmrg 175910d565efSmrg#ifdef L_clzdi2 17600fc04c29Smrg#if !defined (__ARM_FEATURE_CLZ) 176110d565efSmrg 176210d565efSmrg# ifdef NOT_ISA_TARGET_32BIT 176310d565efSmrgFUNC_START clzdi2 176410d565efSmrg push {r4, lr} 1765*ec02198aSmrg cmp xxh, #0 1766*ec02198aSmrg bne 1f 1767*ec02198aSmrg# ifdef __ARMEB__ 1768*ec02198aSmrg movs r0, xxl 1769*ec02198aSmrg bl __clzsi2 1770*ec02198aSmrg adds r0, r0, #32 1771*ec02198aSmrg b 2f 1772*ec02198aSmrg1: 1773*ec02198aSmrg bl __clzsi2 177410d565efSmrg# else 1775*ec02198aSmrg bl __clzsi2 1776*ec02198aSmrg adds r0, r0, #32 1777*ec02198aSmrg b 2f 1778*ec02198aSmrg1: 1779*ec02198aSmrg movs r0, xxh 1780*ec02198aSmrg bl __clzsi2 1781*ec02198aSmrg# endif 1782*ec02198aSmrg2: 1783*ec02198aSmrg pop {r4, pc} 1784*ec02198aSmrg# else /* NOT_ISA_TARGET_32BIT */ 178510d565efSmrgARM_FUNC_START clzdi2 178610d565efSmrg do_push {r4, lr} 178710d565efSmrg cmp xxh, #0 178810d565efSmrg bne 1f 178910d565efSmrg# ifdef __ARMEB__ 179010d565efSmrg mov r0, xxl 179110d565efSmrg bl __clzsi2 179210d565efSmrg add r0, r0, #32 179310d565efSmrg b 2f 179410d565efSmrg1: 179510d565efSmrg bl __clzsi2 179610d565efSmrg# else 179710d565efSmrg bl __clzsi2 179810d565efSmrg add r0, r0, #32 179910d565efSmrg b 2f 180010d565efSmrg1: 180110d565efSmrg mov r0, xxh 180210d565efSmrg bl __clzsi2 180310d565efSmrg# endif 180410d565efSmrg2: 180510d565efSmrg RETLDM r4 180610d565efSmrg FUNC_END clzdi2 1807*ec02198aSmrg# endif /* NOT_ISA_TARGET_32BIT */ 180810d565efSmrg 18090fc04c29Smrg#else /* defined (__ARM_FEATURE_CLZ) */ 181010d565efSmrg 181110d565efSmrgARM_FUNC_START clzdi2 181210d565efSmrg cmp xxh, #0 181310d565efSmrg do_it eq, et 181410d565efSmrg clzeq r0, xxl 181510d565efSmrg clzne r0, xxh 181610d565efSmrg addeq r0, r0, #32 181710d565efSmrg RET 181810d565efSmrg FUNC_END clzdi2 181910d565efSmrg 182010d565efSmrg#endif 182110d565efSmrg#endif /* L_clzdi2 */ 182210d565efSmrg 182310d565efSmrg#ifdef L_ctzsi2 182410d565efSmrg#ifdef NOT_ISA_TARGET_32BIT 182510d565efSmrgFUNC_START ctzsi2 1826*ec02198aSmrg negs r1, r0 1827*ec02198aSmrg ands r0, r0, r1 1828*ec02198aSmrg movs r1, #28 1829*ec02198aSmrg movs r3, #1 1830*ec02198aSmrg lsls r3, r3, #16 183110d565efSmrg cmp r0, r3 /* 0x10000 */ 183210d565efSmrg bcc 2f 1833*ec02198aSmrg lsrs r0, r0, #16 1834*ec02198aSmrg subs r1, r1, #16 1835*ec02198aSmrg2: lsrs r3, r3, #8 183610d565efSmrg cmp r0, r3 /* #0x100 */ 183710d565efSmrg bcc 2f 1838*ec02198aSmrg lsrs r0, r0, #8 1839*ec02198aSmrg subs r1, r1, #8 1840*ec02198aSmrg2: lsrs r3, r3, #4 184110d565efSmrg cmp r0, r3 /* #0x10 */ 184210d565efSmrg bcc 2f 1843*ec02198aSmrg lsrs r0, r0, #4 1844*ec02198aSmrg subs r1, r1, #4 184510d565efSmrg2: adr r2, 1f 184610d565efSmrg ldrb r0, [r2, r0] 1847*ec02198aSmrg subs r0, r0, r1 184810d565efSmrg bx lr 184910d565efSmrg.align 2 185010d565efSmrg1: 185110d565efSmrg.byte 27, 28, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31 185210d565efSmrg FUNC_END ctzsi2 185310d565efSmrg#else 185410d565efSmrgARM_FUNC_START ctzsi2 185510d565efSmrg rsb r1, r0, #0 185610d565efSmrg and r0, r0, r1 18570fc04c29Smrg# if defined (__ARM_FEATURE_CLZ) 185810d565efSmrg clz r0, r0 185910d565efSmrg rsb r0, r0, #31 186010d565efSmrg RET 186110d565efSmrg# else 186210d565efSmrg mov r1, #28 186310d565efSmrg cmp r0, #0x10000 186410d565efSmrg do_it cs, t 186510d565efSmrg movcs r0, r0, lsr #16 186610d565efSmrg subcs r1, r1, #16 186710d565efSmrg cmp r0, #0x100 186810d565efSmrg do_it cs, t 186910d565efSmrg movcs r0, r0, lsr #8 187010d565efSmrg subcs r1, r1, #8 187110d565efSmrg cmp r0, #0x10 187210d565efSmrg do_it cs, t 187310d565efSmrg movcs r0, r0, lsr #4 187410d565efSmrg subcs r1, r1, #4 187510d565efSmrg adr r2, 1f 187610d565efSmrg ldrb r0, [r2, r0] 187710d565efSmrg sub r0, r0, r1 187810d565efSmrg RET 187910d565efSmrg.align 2 188010d565efSmrg1: 188110d565efSmrg.byte 27, 28, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31 18820fc04c29Smrg# endif /* !defined (__ARM_FEATURE_CLZ) */ 188310d565efSmrg FUNC_END ctzsi2 188410d565efSmrg#endif 188510d565efSmrg#endif /* L_clzsi2 */ 188610d565efSmrg 188710d565efSmrg/* ------------------------------------------------------------------------ */ 188810d565efSmrg/* These next two sections are here despite the fact that they contain Thumb 188910d565efSmrg assembler because their presence allows interworked code to be linked even 189010d565efSmrg when the GCC library is this one. */ 189110d565efSmrg 189210d565efSmrg/* Do not build the interworking functions when the target architecture does 189310d565efSmrg not support Thumb instructions. (This can be a multilib option). */ 189410d565efSmrg#if defined __ARM_ARCH_4T__ || defined __ARM_ARCH_5T__\ 189510d565efSmrg || defined __ARM_ARCH_5TE__ || defined __ARM_ARCH_5TEJ__ \ 18960fc04c29Smrg || __ARM_ARCH >= 6 189710d565efSmrg 189810d565efSmrg#if defined L_call_via_rX 189910d565efSmrg 190010d565efSmrg/* These labels & instructions are used by the Arm/Thumb interworking code. 190110d565efSmrg The address of function to be called is loaded into a register and then 190210d565efSmrg one of these labels is called via a BL instruction. This puts the 190310d565efSmrg return address into the link register with the bottom bit set, and the 190410d565efSmrg code here switches to the correct mode before executing the function. */ 190510d565efSmrg 190610d565efSmrg .text 190710d565efSmrg .align 0 190810d565efSmrg .force_thumb 190910d565efSmrg 191010d565efSmrg.macro call_via register 191110d565efSmrg THUMB_FUNC_START _call_via_\register 191210d565efSmrg 191310d565efSmrg bx \register 191410d565efSmrg nop 191510d565efSmrg 191610d565efSmrg SIZE (_call_via_\register) 191710d565efSmrg.endm 191810d565efSmrg 191910d565efSmrg call_via r0 192010d565efSmrg call_via r1 192110d565efSmrg call_via r2 192210d565efSmrg call_via r3 192310d565efSmrg call_via r4 192410d565efSmrg call_via r5 192510d565efSmrg call_via r6 192610d565efSmrg call_via r7 192710d565efSmrg call_via r8 192810d565efSmrg call_via r9 192910d565efSmrg call_via sl 193010d565efSmrg call_via fp 193110d565efSmrg call_via ip 193210d565efSmrg call_via sp 193310d565efSmrg call_via lr 193410d565efSmrg 193510d565efSmrg#endif /* L_call_via_rX */ 193610d565efSmrg 193710d565efSmrg/* Don't bother with the old interworking routines for Thumb-2. */ 193810d565efSmrg/* ??? Maybe only omit these on "m" variants. */ 193910d565efSmrg#if !defined(__thumb2__) && __ARM_ARCH_ISA_ARM 194010d565efSmrg 194110d565efSmrg#if defined L_interwork_call_via_rX 194210d565efSmrg 194310d565efSmrg/* These labels & instructions are used by the Arm/Thumb interworking code, 194410d565efSmrg when the target address is in an unknown instruction set. The address 194510d565efSmrg of function to be called is loaded into a register and then one of these 194610d565efSmrg labels is called via a BL instruction. This puts the return address 194710d565efSmrg into the link register with the bottom bit set, and the code here 194810d565efSmrg switches to the correct mode before executing the function. Unfortunately 194910d565efSmrg the target code cannot be relied upon to return via a BX instruction, so 195010d565efSmrg instead we have to store the resturn address on the stack and allow the 195110d565efSmrg called function to return here instead. Upon return we recover the real 195210d565efSmrg return address and use a BX to get back to Thumb mode. 195310d565efSmrg 195410d565efSmrg There are three variations of this code. The first, 195510d565efSmrg _interwork_call_via_rN(), will push the return address onto the 195610d565efSmrg stack and pop it in _arm_return(). It should only be used if all 195710d565efSmrg arguments are passed in registers. 195810d565efSmrg 195910d565efSmrg The second, _interwork_r7_call_via_rN(), instead stores the return 196010d565efSmrg address at [r7, #-4]. It is the caller's responsibility to ensure 196110d565efSmrg that this address is valid and contains no useful data. 196210d565efSmrg 196310d565efSmrg The third, _interwork_r11_call_via_rN(), works in the same way but 196410d565efSmrg uses r11 instead of r7. It is useful if the caller does not really 196510d565efSmrg need a frame pointer. */ 196610d565efSmrg 196710d565efSmrg .text 196810d565efSmrg .align 0 196910d565efSmrg 197010d565efSmrg .code 32 197110d565efSmrg .globl _arm_return 197210d565efSmrgLSYM(Lstart_arm_return): 197310d565efSmrg cfi_start LSYM(Lstart_arm_return) LSYM(Lend_arm_return) 197410d565efSmrg cfi_push 0, 0xe, -0x8, 0x8 197510d565efSmrg nop @ This nop is for the benefit of debuggers, so that 197610d565efSmrg @ backtraces will use the correct unwind information. 197710d565efSmrg_arm_return: 197810d565efSmrg RETLDM unwind=LSYM(Lstart_arm_return) 197910d565efSmrg cfi_end LSYM(Lend_arm_return) 198010d565efSmrg 198110d565efSmrg .globl _arm_return_r7 198210d565efSmrg_arm_return_r7: 198310d565efSmrg ldr lr, [r7, #-4] 198410d565efSmrg bx lr 198510d565efSmrg 198610d565efSmrg .globl _arm_return_r11 198710d565efSmrg_arm_return_r11: 198810d565efSmrg ldr lr, [r11, #-4] 198910d565efSmrg bx lr 199010d565efSmrg 199110d565efSmrg.macro interwork_with_frame frame, register, name, return 199210d565efSmrg .code 16 199310d565efSmrg 199410d565efSmrg THUMB_FUNC_START \name 199510d565efSmrg 199610d565efSmrg bx pc 199710d565efSmrg nop 199810d565efSmrg 199910d565efSmrg .code 32 200010d565efSmrg tst \register, #1 200110d565efSmrg streq lr, [\frame, #-4] 200210d565efSmrg adreq lr, _arm_return_\frame 200310d565efSmrg bx \register 200410d565efSmrg 200510d565efSmrg SIZE (\name) 200610d565efSmrg.endm 200710d565efSmrg 200810d565efSmrg.macro interwork register 200910d565efSmrg .code 16 201010d565efSmrg 201110d565efSmrg THUMB_FUNC_START _interwork_call_via_\register 201210d565efSmrg 201310d565efSmrg bx pc 201410d565efSmrg nop 201510d565efSmrg 201610d565efSmrg .code 32 201710d565efSmrg .globl LSYM(Lchange_\register) 201810d565efSmrgLSYM(Lchange_\register): 201910d565efSmrg tst \register, #1 202010d565efSmrg streq lr, [sp, #-8]! 202110d565efSmrg adreq lr, _arm_return 202210d565efSmrg bx \register 202310d565efSmrg 202410d565efSmrg SIZE (_interwork_call_via_\register) 202510d565efSmrg 202610d565efSmrg interwork_with_frame r7,\register,_interwork_r7_call_via_\register 202710d565efSmrg interwork_with_frame r11,\register,_interwork_r11_call_via_\register 202810d565efSmrg.endm 202910d565efSmrg 203010d565efSmrg interwork r0 203110d565efSmrg interwork r1 203210d565efSmrg interwork r2 203310d565efSmrg interwork r3 203410d565efSmrg interwork r4 203510d565efSmrg interwork r5 203610d565efSmrg interwork r6 203710d565efSmrg interwork r7 203810d565efSmrg interwork r8 203910d565efSmrg interwork r9 204010d565efSmrg interwork sl 204110d565efSmrg interwork fp 204210d565efSmrg interwork ip 204310d565efSmrg interwork sp 204410d565efSmrg 204510d565efSmrg /* The LR case has to be handled a little differently... */ 204610d565efSmrg .code 16 204710d565efSmrg 204810d565efSmrg THUMB_FUNC_START _interwork_call_via_lr 204910d565efSmrg 205010d565efSmrg bx pc 205110d565efSmrg nop 205210d565efSmrg 205310d565efSmrg .code 32 205410d565efSmrg .globl .Lchange_lr 205510d565efSmrg.Lchange_lr: 205610d565efSmrg tst lr, #1 205710d565efSmrg stmeqdb r13!, {lr, pc} 205810d565efSmrg mov ip, lr 205910d565efSmrg adreq lr, _arm_return 206010d565efSmrg bx ip 206110d565efSmrg 206210d565efSmrg SIZE (_interwork_call_via_lr) 206310d565efSmrg 206410d565efSmrg#endif /* L_interwork_call_via_rX */ 206510d565efSmrg#endif /* !__thumb2__ */ 206610d565efSmrg 206710d565efSmrg/* Functions to support compact pic switch tables in thumb1 state. 206810d565efSmrg All these routines take an index into the table in r0. The 206910d565efSmrg table is at LR & ~1 (but this must be rounded up in the case 207010d565efSmrg of 32-bit entires). They are only permitted to clobber r12 207110d565efSmrg and r14 and r0 must be preserved on exit. */ 207210d565efSmrg#ifdef L_thumb1_case_sqi 207310d565efSmrg 207410d565efSmrg .text 207510d565efSmrg .align 0 207610d565efSmrg .force_thumb 207710d565efSmrg .syntax unified 207810d565efSmrg THUMB_FUNC_START __gnu_thumb1_case_sqi 207910d565efSmrg push {r1} 208010d565efSmrg mov r1, lr 208110d565efSmrg lsrs r1, r1, #1 208210d565efSmrg lsls r1, r1, #1 208310d565efSmrg ldrsb r1, [r1, r0] 208410d565efSmrg lsls r1, r1, #1 208510d565efSmrg add lr, lr, r1 208610d565efSmrg pop {r1} 208710d565efSmrg bx lr 208810d565efSmrg SIZE (__gnu_thumb1_case_sqi) 208910d565efSmrg#endif 209010d565efSmrg 209110d565efSmrg#ifdef L_thumb1_case_uqi 209210d565efSmrg 209310d565efSmrg .text 209410d565efSmrg .align 0 209510d565efSmrg .force_thumb 209610d565efSmrg .syntax unified 209710d565efSmrg THUMB_FUNC_START __gnu_thumb1_case_uqi 209810d565efSmrg push {r1} 209910d565efSmrg mov r1, lr 210010d565efSmrg lsrs r1, r1, #1 210110d565efSmrg lsls r1, r1, #1 210210d565efSmrg ldrb r1, [r1, r0] 210310d565efSmrg lsls r1, r1, #1 210410d565efSmrg add lr, lr, r1 210510d565efSmrg pop {r1} 210610d565efSmrg bx lr 210710d565efSmrg SIZE (__gnu_thumb1_case_uqi) 210810d565efSmrg#endif 210910d565efSmrg 211010d565efSmrg#ifdef L_thumb1_case_shi 211110d565efSmrg 211210d565efSmrg .text 211310d565efSmrg .align 0 211410d565efSmrg .force_thumb 211510d565efSmrg .syntax unified 211610d565efSmrg THUMB_FUNC_START __gnu_thumb1_case_shi 211710d565efSmrg push {r0, r1} 211810d565efSmrg mov r1, lr 211910d565efSmrg lsrs r1, r1, #1 212010d565efSmrg lsls r0, r0, #1 212110d565efSmrg lsls r1, r1, #1 212210d565efSmrg ldrsh r1, [r1, r0] 212310d565efSmrg lsls r1, r1, #1 212410d565efSmrg add lr, lr, r1 212510d565efSmrg pop {r0, r1} 212610d565efSmrg bx lr 212710d565efSmrg SIZE (__gnu_thumb1_case_shi) 212810d565efSmrg#endif 212910d565efSmrg 213010d565efSmrg#ifdef L_thumb1_case_uhi 213110d565efSmrg 213210d565efSmrg .text 213310d565efSmrg .align 0 213410d565efSmrg .force_thumb 213510d565efSmrg .syntax unified 213610d565efSmrg THUMB_FUNC_START __gnu_thumb1_case_uhi 213710d565efSmrg push {r0, r1} 213810d565efSmrg mov r1, lr 213910d565efSmrg lsrs r1, r1, #1 214010d565efSmrg lsls r0, r0, #1 214110d565efSmrg lsls r1, r1, #1 214210d565efSmrg ldrh r1, [r1, r0] 214310d565efSmrg lsls r1, r1, #1 214410d565efSmrg add lr, lr, r1 214510d565efSmrg pop {r0, r1} 214610d565efSmrg bx lr 214710d565efSmrg SIZE (__gnu_thumb1_case_uhi) 214810d565efSmrg#endif 214910d565efSmrg 215010d565efSmrg#ifdef L_thumb1_case_si 215110d565efSmrg 215210d565efSmrg .text 215310d565efSmrg .align 0 215410d565efSmrg .force_thumb 215510d565efSmrg .syntax unified 215610d565efSmrg THUMB_FUNC_START __gnu_thumb1_case_si 215710d565efSmrg push {r0, r1} 215810d565efSmrg mov r1, lr 215910d565efSmrg adds.n r1, r1, #2 /* Align to word. */ 216010d565efSmrg lsrs r1, r1, #2 216110d565efSmrg lsls r0, r0, #2 216210d565efSmrg lsls r1, r1, #2 216310d565efSmrg ldr r0, [r1, r0] 216410d565efSmrg adds r0, r0, r1 216510d565efSmrg mov lr, r0 216610d565efSmrg pop {r0, r1} 216710d565efSmrg mov pc, lr /* We know we were called from thumb code. */ 216810d565efSmrg SIZE (__gnu_thumb1_case_si) 216910d565efSmrg#endif 217010d565efSmrg 217110d565efSmrg#endif /* Arch supports thumb. */ 217210d565efSmrg 217310d565efSmrg.macro CFI_START_FUNCTION 217410d565efSmrg .cfi_startproc 217510d565efSmrg .cfi_remember_state 217610d565efSmrg.endm 217710d565efSmrg 217810d565efSmrg.macro CFI_END_FUNCTION 217910d565efSmrg .cfi_restore_state 218010d565efSmrg .cfi_endproc 218110d565efSmrg.endm 218210d565efSmrg 218310d565efSmrg#ifndef __symbian__ 21840fc04c29Smrg/* The condition here must match the one in gcc/config/arm/elf.h and 21850fc04c29Smrg libgcc/config/arm/t-elf. */ 218610d565efSmrg#ifndef NOT_ISA_TARGET_32BIT 218710d565efSmrg#include "ieee754-df.S" 218810d565efSmrg#include "ieee754-sf.S" 218910d565efSmrg#include "bpabi.S" 219010d565efSmrg#else /* NOT_ISA_TARGET_32BIT */ 219110d565efSmrg#include "bpabi-v6m.S" 219210d565efSmrg#endif /* NOT_ISA_TARGET_32BIT */ 219310d565efSmrg#endif /* !__symbian__ */ 2194