Unverified Commit 71f8a6a9 authored by davidcunado-arm's avatar davidcunado-arm Committed by GitHub
Browse files

Merge pull request #1145 from etienne-lms/rfc-armv7-2

Support ARMv7 architectures
Showing with 578 additions and 14 deletions
+578 -14
......@@ -126,20 +126,28 @@ OD := ${CROSS_COMPILE}objdump
NM := ${CROSS_COMPILE}nm
PP := ${CROSS_COMPILE}gcc -E
ifeq (${ARM_ARCH_MAJOR},7)
target32-directive = -target arm-none-eabi
# Will set march32-directive from platform configuration
else
target32-directive = -target armv8a-none-eabi
march32-directive = -march armv8-a
endif
ifeq ($(notdir $(CC)),armclang)
TF_CFLAGS_aarch32 = -target arm-arm-none-eabi -march=armv8-a
TF_CFLAGS_aarch32 = -target arm-arm-none-eabi $(march32-directive)
TF_CFLAGS_aarch64 = -target aarch64-arm-none-eabi -march=armv8-a
else ifneq ($(findstring clang,$(notdir $(CC))),)
TF_CFLAGS_aarch32 = -target armv8a-none-eabi
TF_CFLAGS_aarch32 = $(target32-directive)
TF_CFLAGS_aarch64 = -target aarch64-elf
else
TF_CFLAGS_aarch32 = -march=armv8-a
TF_CFLAGS_aarch32 = $(march32-directive)
TF_CFLAGS_aarch64 = -march=armv8-a
endif
TF_CFLAGS_aarch64 += -mgeneral-regs-only -mstrict-align
ASFLAGS_aarch32 = -march=armv8-a
ASFLAGS_aarch32 = $(march32-directive)
ASFLAGS_aarch64 = -march=armv8-a
CPPFLAGS = ${DEFINES} ${INCLUDES} -nostdinc \
......@@ -263,6 +271,10 @@ include ${PLAT_MAKEFILE_FULL}
$(eval $(call MAKE_PREREQ_DIR,${BUILD_PLAT}))
ifeq (${ARM_ARCH_MAJOR},7)
include make_helpers/armv7-a-cpus.mk
endif
# Platform compatibility is not supported in AArch32
ifneq (${ARCH},aarch32)
# If the platform has not defined ENABLE_PLAT_COMPAT, then enable it by default
......
......@@ -30,6 +30,16 @@
stcopr \reg, SCR
.endm
.macro clrex_on_monitor_entry
#if (ARM_ARCH_MAJOR == 7)
/*
* ARMv7 architectures need to clear the exclusive access when
* entering Monitor mode.
*/
clrex
#endif
.endm
vector_base sp_min_vector_table
b sp_min_entrypoint
b plat_panic_handler /* Undef */
......@@ -147,6 +157,8 @@ func handle_smc
smcc_save_gp_mode_regs
clrex_on_monitor_entry
/*
* `sp` still points to `smc_ctx_t`. Save it to a register
* and restore the C runtime stack pointer to `sp`.
......@@ -203,11 +215,7 @@ func handle_fiq
smcc_save_gp_mode_regs
/*
* AArch32 architectures need to clear the exclusive access when
* entering Monitor mode.
*/
clrex
clrex_on_monitor_entry
/* load run-time stack */
mov r2, sp
......
......@@ -71,7 +71,15 @@ endfunc report_exception
assert_msg1:
.asciz "ASSERT: File "
assert_msg2:
#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
/******************************************************************
* Virtualization comes with the UDIV/SDIV instructions. If missing
* write file line number in hexadecimal format.
******************************************************************/
.asciz " Line 0x"
#else
.asciz " Line "
#endif
/* ---------------------------------------------------------------------------
* Assertion support in assembly.
......@@ -113,6 +121,13 @@ func asm_assert
bne 1f
mov r4, r6
#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
/******************************************************************
* Virtualization comes with the UDIV/SDIV instructions. If missing
* write file line number in hexadecimal format.
******************************************************************/
bl asm_print_hex
#else
/* Print line number in decimal */
mov r6, #10 /* Divide by 10 after every loop iteration */
ldr r5, =MAX_DEC_DIVISOR
......@@ -124,6 +139,7 @@ dec_print_loop:
udiv r5, r5, r6 /* Reduce divisor */
cmp r5, #0
bne dec_print_loop
#endif
bl plat_crash_console_flush
......
......@@ -2519,6 +2519,35 @@ This Architecture Extension is targeted when ``ARM_ARCH_MAJOR`` == 8 and
table entries for a given stage of translation for a particular translation
regime.
ARMv7
~~~~~
This Architecture Extension is targeted when ``ARM_ARCH_MAJOR`` == 7.
There are several ARMv7 extensions available. Obviously the TrustZone
extension is mandatory to support the ARM Trusted Firmware bootloader
and runtime services.
Platform implementing an ARMv7 system can to define from its target
Cortex-A architecture through ``ARM_CORTEX_A<X> = yes`` in their
``plaform.mk`` script. For example ``ARM_CORTEX_A15=yes`` for a
Cortex-A15 target.
Platform can also set ``ARM_WITH_NEON=yes`` to enable neon support.
Note that using neon at runtime has constraints on non secure wolrd context.
The trusted firmware does not yet provide VFP context management.
Directive ``ARM_CORTEX_A<x>`` and ``ARM_WITH_NEON`` are used to set
the toolchain target architecture directive.
Platform may choose to not define straight the toolchain target architecture
directive by defining ``MARCH32_DIRECTIVE``.
I.e:
::
MARCH32_DIRECTIVE := -mach=armv7-a
Code Structure
--------------
......
......@@ -219,7 +219,8 @@ Common build options
- ``ARM_ARCH_MAJOR``: The major version of ARM Architecture to target when
compiling ARM Trusted Firmware. Its value must be numeric, and defaults to
8 . See also, *ARMv8 Architecture Extensions* in `Firmware Design`_.
8 . See also, *ARMv8 Architecture Extensions* and
*ARMv7 Architecture Extensions* in `Firmware Design`_.
- ``ARM_ARCH_MINOR``: The minor version of ARM Architecture to target when
compiling ARM Trusted Firmware. Its value must be a numeric, and defaults
......
......@@ -176,7 +176,19 @@ void gicv2_driver_init(const gicv2_driver_data_t *plat_driver_data)
gic_version = gicd_read_pidr2(plat_driver_data->gicd_base);
gic_version = (gic_version >> PIDR2_ARCH_REV_SHIFT)
& PIDR2_ARCH_REV_MASK;
assert(gic_version == ARCH_REV_GICV2);
/*
* GICv1 with security extension complies with trusted firmware
* GICv2 driver as far as virtualization and few tricky power
* features are not used. GICv2 features that are not supported
* by GICv1 with Security Extensions are:
* - virtual interrupt support.
* - wake up events.
* - writeable GIC state register (for power sequences)
* - interrupt priority drop.
* - interrupt signal bypass.
*/
assert(gic_version == ARCH_REV_GICV2 || gic_version == ARCH_REV_GICV1);
driver_data = plat_driver_data;
......
......@@ -79,6 +79,25 @@
ldr r0, =(\_name + \_size)
.endm
#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
/*
* ARMv7 cores without Virtualization extension do not support the
* eret instruction.
*/
.macro eret
movs pc, lr
.endm
#endif
#if (ARM_ARCH_MAJOR == 7)
/* ARMv7 does not support stl instruction */
.macro stl _reg, _write_lock
dmb
str \_reg, \_write_lock
dsb
.endm
#endif
/*
* Helper macro to generate the best mov/movw/movt combinations
* according to the value to be moved.
......
......@@ -107,6 +107,7 @@
vmsr FPEXC, r0
isb
#if (ARM_ARCH_MAJOR > 7)
/* ---------------------------------------------------------------------
* Initialise SDCR, setting all the fields rather than relying on hw.
*
......@@ -116,6 +117,7 @@
*/
ldr r0, =(SDCR_RESET_VAL | SDCR_SPD(SDCR_SPD_DISABLE))
stcopr r0, SDCR
#endif
.endm
......
......@@ -72,6 +72,8 @@
#define ARCH_REV_GICV3 0x3
/* GICv2 revision as reported by the PIDR2 register */
#define ARCH_REV_GICV2 0x2
/* GICv1 revision as reported by the PIDR2 register */
#define ARCH_REV_GICV1 0x1
#define IGROUPR_SHIFT 5
#define ISENABLER_SHIFT 5
......
......@@ -87,15 +87,21 @@
#define ID_PFR1_GIC_MASK 0xf
/* SCTLR definitions */
#define SCTLR_RES1 ((1 << 23) | (1 << 22) | (1 << 11) | (1 << 4) | \
(1 << 3))
#define SCTLR_RES1_DEF ((1 << 23) | (1 << 22) | (1 << 4) | (1 << 3))
#if ARM_ARCH_MAJOR == 7
#define SCTLR_RES1 SCTLR_RES1_DEF
#else
#define SCTLR_RES1 (SCTLR_RES1_DEF | (1 << 11))
#endif
#define SCTLR_M_BIT (1 << 0)
#define SCTLR_A_BIT (1 << 1)
#define SCTLR_C_BIT (1 << 2)
#define SCTLR_CP15BEN_BIT (1 << 5)
#define SCTLR_ITD_BIT (1 << 7)
#define SCTLR_Z_BIT (1 << 11)
#define SCTLR_I_BIT (1 << 12)
#define SCTLR_V_BIT (1 << 13)
#define SCTLR_RR_BIT (1 << 14)
#define SCTLR_NTWI_BIT (1 << 16)
#define SCTLR_NTWE_BIT (1 << 18)
#define SCTLR_WXN_BIT (1 << 19)
......@@ -385,6 +391,7 @@
/* System register defines The format is: coproc, opt1, CRn, CRm, opt2 */
#define SCR p15, 0, c1, c1, 0
#define SCTLR p15, 0, c1, c0, 0
#define ACTLR p15, 0, c1, c0, 1
#define SDCR p15, 0, c1, c3, 1
#define MPIDR p15, 0, c0, c0, 5
#define MIDR p15, 0, c0, c0, 0
......@@ -431,6 +438,11 @@
#define PMCR p15, 0, c9, c12, 0
#define CNTHP_CTL p15, 4, c14, c2, 1
/* AArch32 coproc registers for 32bit MMU descriptor support */
#define PRRR p15, 0, c10, c2, 0
#define NMRR p15, 0, c10, c2, 1
#define DACR p15, 0, c3, c0, 0
/* GICv3 CPU Interface system register defines. The format is: coproc, opt1, CRn, CRm, opt2 */
#define ICC_IAR1 p15, 0, c12, c12, 0
#define ICC_IAR0 p15, 0, c12, c8, 0
......
......@@ -235,6 +235,7 @@ DEFINE_COPROCR_READ_FUNC_64(cntpct, CNTPCT_64)
DEFINE_COPROCR_RW_FUNCS(scr, SCR)
DEFINE_COPROCR_RW_FUNCS(ctr, CTR)
DEFINE_COPROCR_RW_FUNCS(sctlr, SCTLR)
DEFINE_COPROCR_RW_FUNCS(actlr, ACTLR)
DEFINE_COPROCR_RW_FUNCS(hsctlr, HSCTLR)
DEFINE_COPROCR_RW_FUNCS(hcr, HCR)
DEFINE_COPROCR_RW_FUNCS(hcptr, HCPTR)
......@@ -273,6 +274,13 @@ DEFINE_COPROCR_RW_FUNCS(hdcr, HDCR)
DEFINE_COPROCR_RW_FUNCS(cnthp_ctl, CNTHP_CTL)
DEFINE_COPROCR_READ_FUNC(pmcr, PMCR)
DEFINE_COPROCR_RW_FUNCS(nsacr, NSACR)
/* AArch32 coproc registers for 32bit MMU descriptor support */
DEFINE_COPROCR_RW_FUNCS(prrr, PRRR)
DEFINE_COPROCR_RW_FUNCS(nmrr, NMRR)
DEFINE_COPROCR_RW_FUNCS(dacr, DACR)
/*
* TLBI operation prototypes
*/
......@@ -296,6 +304,7 @@ DEFINE_DCOP_PARAM_FUNC(cvac, DCCMVAC)
/* Previously defined accessor functions with incomplete register names */
#define dsb() dsbsy()
#define dmb() dmbsy()
#define IS_IN_SECURE() \
(GET_NS_BIT(read_scr()) == 0)
......
......@@ -22,6 +22,44 @@
mov r0, sp
add r0, r0, #SMC_CTX_SP_USR
#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
/* Must be in secure state to restore Monitor mode */
ldcopr r4, SCR
bic r2, r4, #SCR_NS_BIT
stcopr r2, SCR
isb
cps #MODE32_sys
stm r0!, {sp, lr}
cps #MODE32_irq
mrs r2, spsr
stm r0!, {r2, sp, lr}
cps #MODE32_fiq
mrs r2, spsr
stm r0!, {r2, sp, lr}
cps #MODE32_svc
mrs r2, spsr
stm r0!, {r2, sp, lr}
cps #MODE32_abt
mrs r2, spsr
stm r0!, {r2, sp, lr}
cps #MODE32_und
mrs r2, spsr
stm r0!, {r2, sp, lr}
/* lr_mon is already saved by caller */
cps #MODE32_mon
mrs r2, spsr
stm r0!, {r2}
stcopr r4, SCR
isb
#else
/* Save the banked registers including the current SPSR and LR */
mrs r4, sp_usr
mrs r5, lr_usr
......@@ -44,9 +82,10 @@
mrs r11, lr_und
mrs r12, spsr
stm r0!, {r4-r12}
/* lr_mon is already saved by caller */
ldcopr r4, SCR
#endif
str r4, [sp, #SMC_CTX_SCR]
ldcopr r4, PMCR
str r4, [sp, #SMC_CTX_PMCR]
......@@ -82,6 +121,44 @@
/* Restore the banked registers including the current SPSR */
add r1, r0, #SMC_CTX_SP_USR
#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
/* Must be in secure state to restore Monitor mode */
ldcopr r4, SCR
bic r2, r4, #SCR_NS_BIT
stcopr r2, SCR
isb
cps #MODE32_sys
ldm r1!, {sp, lr}
cps #MODE32_irq
ldm r1!, {r2, sp, lr}
msr spsr_fsxc, r2
cps #MODE32_fiq
ldm r1!, {r2, sp, lr}
msr spsr_fsxc, r2
cps #MODE32_svc
ldm r1!, {r2, sp, lr}
msr spsr_fsxc, r2
cps #MODE32_abt
ldm r1!, {r2, sp, lr}
msr spsr_fsxc, r2
cps #MODE32_und
ldm r1!, {r2, sp, lr}
msr spsr_fsxc, r2
cps #MODE32_mon
ldm r1!, {r2}
msr spsr_fsxc, r2
stcopr r4, SCR
isb
#else
ldm r1!, {r4-r12}
msr sp_usr, r4
msr lr_usr, r5
......@@ -109,6 +186,7 @@
* f->[31:24] and c->[7:0] bits of SPSR.
*/
msr spsr_fsxc, r12
#endif
/* Restore the LR */
ldr lr, [r0, #SMC_CTX_LR_MON]
......
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __CORTEX_A12_H__
#define __CORTEX_A12_H__
/*******************************************************************************
* Cortex-A12 midr with version/revision set to 0
******************************************************************************/
#define CORTEX_A12_MIDR 0x410FC0C0
/*******************************************************************************
* CPU Auxiliary Control register specific definitions.
******************************************************************************/
#define CORTEX_A12_ACTLR_SMP_BIT (1 << 6)
#endif /* __CORTEX_A12_H__ */
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __CORTEX_A15_H__
#define __CORTEX_A15_H__
/*******************************************************************************
* Cortex-A15 midr with version/revision set to 0
******************************************************************************/
#define CORTEX_A15_MIDR 0x410FC0F0
/*******************************************************************************
* CPU Auxiliary Control register specific definitions.
******************************************************************************/
#define CORTEX_A15_ACTLR_SMP_BIT (1 << 6)
#endif /* __CORTEX_A15_H__ */
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __CORTEX_A17_H__
#define __CORTEX_A17_H__
/*******************************************************************************
* Cortex-A17 midr with version/revision set to 0
******************************************************************************/
#define CORTEX_A17_MIDR 0x410FC0E0
/*******************************************************************************
* CPU Auxiliary Control register specific definitions.
******************************************************************************/
#define CORTEX_A17_ACTLR_SMP_BIT (1 << 6)
#endif /* __CORTEX_A17_H__ */
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __CORTEX_A5_H__
#define __CORTEX_A5_H__
/*******************************************************************************
* Cortex-A8 midr with version/revision set to 0
******************************************************************************/
#define CORTEX_A5_MIDR 0x410FC050
/*******************************************************************************
* CPU Auxiliary Control register specific definitions.
******************************************************************************/
#define CORTEX_A5_ACTLR_SMP_BIT (1 << 6)
#endif /* __CORTEX_A5_H__ */
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __CORTEX_A7_H__
#define __CORTEX_A7_H__
/*******************************************************************************
* Cortex-A7 midr with version/revision set to 0
******************************************************************************/
#define CORTEX_A7_MIDR 0x410FC070
/*******************************************************************************
* CPU Auxiliary Control register specific definitions.
******************************************************************************/
#define CORTEX_A7_ACTLR_SMP_BIT (1 << 6)
#endif /* __CORTEX_A7_H__ */
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __CORTEX_A9_H__
#define __CORTEX_A9_H__
/*******************************************************************************
* Cortex-A9 midr with version/revision set to 0
******************************************************************************/
#define CORTEX_A9_MIDR 0x410FC090
/*******************************************************************************
* CPU Auxiliary Control register specific definitions.
******************************************************************************/
#define CORTEX_A9_ACTLR_SMP_BIT (1 << 6)
#define CORTEX_A9_ACTLR_FLZW_BIT (1 << 3)
/*******************************************************************************
* CPU Power Control Register
******************************************************************************/
#define PCR p15, 0, c15, c0, 0
#ifndef __ASSEMBLY__
#include <arch_helpers.h>
DEFINE_COPROCR_RW_FUNCS(pcr, PCR)
#endif
#endif /* __CORTEX_A9_H__ */
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* Form ABI specifications:
* int __aeabi_idiv(int numerator, int denominator);
* unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator);
*
* typedef struct { int quot; int rem; } idiv_return;
* typedef struct { unsigned quot; unsigned rem; } uidiv_return;
*
* __value_in_regs idiv_return __aeabi_idivmod(int numerator,
* int *denominator);
* __value_in_regs uidiv_return __aeabi_uidivmod(unsigned *numerator,
* unsigned denominator);
*/
/* struct qr - stores qutient/remainder to handle divmod EABI interfaces. */
struct qr {
unsigned int q; /* computed quotient */
unsigned int r; /* computed remainder */
unsigned int q_n; /* specficies if quotient shall be negative */
unsigned int r_n; /* specficies if remainder shall be negative */
};
static void uint_div_qr(unsigned int numerator, unsigned int denominator,
struct qr *qr);
/* returns in R0 and R1 by tail calling an asm function */
unsigned int __aeabi_uidivmod(unsigned int numerator, unsigned int denominator);
unsigned int __aeabi_uidiv(unsigned int numerator, unsigned int denominator);
unsigned int __aeabi_uimod(unsigned int numerator, unsigned int denominator);
/* returns in R0 and R1 by tail calling an asm function */
signed int __aeabi_idivmod(signed int numerator, signed int denominator);
signed int __aeabi_idiv(signed int numerator, signed int denominator);
signed int __aeabi_imod(signed int numerator, signed int denominator);
/*
* __ste_idivmod_ret_t __aeabi_idivmod(signed numerator, signed denominator)
* Numerator and Denominator are received in R0 and R1.
* Where __ste_idivmod_ret_t is returned in R0 and R1.
*
* __ste_uidivmod_ret_t __aeabi_uidivmod(unsigned numerator,
* unsigned denominator)
* Numerator and Denominator are received in R0 and R1.
* Where __ste_uidivmod_ret_t is returned in R0 and R1.
*/
#ifdef __GNUC__
signed int ret_idivmod_values(signed int quotient, signed int remainder);
unsigned int ret_uidivmod_values(unsigned int quotient, unsigned int remainder);
#else
#error "Compiler not supported"
#endif
static void division_qr(unsigned int n, unsigned int p, struct qr *qr)
{
unsigned int i = 1, q = 0;
if (p == 0) {
qr->r = 0xFFFFFFFF; /* division by 0 */
return;
}
while ((p >> 31) == 0) {
i = i << 1; /* count the max division steps */
p = p << 1; /* increase p until it has maximum size*/
}
while (i > 0) {
q = q << 1; /* write bit in q at index (size-1) */
if (n >= p) {
n -= p;
q++;
}
p = p >> 1; /* decrease p */
i = i >> 1; /* decrease remaining size in q */
}
qr->r = n;
qr->q = q;
}
static void uint_div_qr(unsigned int numerator, unsigned int denominator,
struct qr *qr)
{
division_qr(numerator, denominator, qr);
/* negate quotient and/or remainder according to requester */
if (qr->q_n)
qr->q = -qr->q;
if (qr->r_n)
qr->r = -qr->r;
}
unsigned int __aeabi_uidiv(unsigned int numerator, unsigned int denominator)
{
struct qr qr = { .q_n = 0, .r_n = 0 };
uint_div_qr(numerator, denominator, &qr);
return qr.q;
}
unsigned int __aeabi_uimod(unsigned int numerator, unsigned int denominator)
{
struct qr qr = { .q_n = 0, .r_n = 0 };
uint_div_qr(numerator, denominator, &qr);
return qr.r;
}
unsigned int __aeabi_uidivmod(unsigned int numerator, unsigned int denominator)
{
struct qr qr = { .q_n = 0, .r_n = 0 };
uint_div_qr(numerator, denominator, &qr);
return ret_uidivmod_values(qr.q, qr.r);
}
signed int __aeabi_idiv(signed int numerator, signed int denominator)
{
struct qr qr = { .q_n = 0, .r_n = 0 };
if (((numerator < 0) && (denominator > 0)) ||
((numerator > 0) && (denominator < 0)))
qr.q_n = 1; /* quotient shall be negate */
if (numerator < 0) {
numerator = -numerator;
qr.r_n = 1; /* remainder shall be negate */
}
if (denominator < 0)
denominator = -denominator;
uint_div_qr(numerator, denominator, &qr);
return qr.q;
}
signed int __aeabi_imod(signed int numerator, signed int denominator)
{
signed int s;
signed int i;
signed int j;
signed int h;
struct qr qr = { .q_n = 0, .r_n = 0 };
/* in case modulo of a power of 2 */
for (i = 0, j = 0, h = 0, s = denominator; (s != 0) || (h > 1); i++) {
if (s & 1) {
j = i;
h++;
}
s = s >> 1;
}
if (h == 1)
return numerator >> j;
if (((numerator < 0) && (denominator > 0)) ||
((numerator > 0) && (denominator < 0)))
qr.q_n = 1; /* quotient shall be negate */
if (numerator < 0) {
numerator = -numerator;
qr.r_n = 1; /* remainder shall be negate */
}
if (denominator < 0)
denominator = -denominator;
uint_div_qr(numerator, denominator, &qr);
return qr.r;
}
signed int __aeabi_idivmod(signed int numerator, signed int denominator)
{
struct qr qr = { .q_n = 0, .r_n = 0 };
if (((numerator < 0) && (denominator > 0)) ||
((numerator > 0) && (denominator < 0)))
qr.q_n = 1; /* quotient shall be negate */
if (numerator < 0) {
numerator = -numerator;
qr.r_n = 1; /* remainder shall be negate */
}
if (denominator < 0)
denominator = -denominator;
uint_div_qr(numerator, denominator, &qr);
return ret_idivmod_values(qr.q, qr.r);
}
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <asm_macros.S>
/*
* EABI wrappers from the udivmod and idivmod functions
*/
.globl ret_uidivmod_values
.globl ret_idivmod_values
/*
* signed ret_idivmod_values(signed quot, signed rem);
* return quotient and remaining the EABI way (regs r0,r1)
*/
func ret_idivmod_values
bx lr
endfunc ret_idivmod_values
/*
* unsigned ret_uidivmod_values(unsigned quot, unsigned rem);
* return quotient and remaining the EABI way (regs r0,r1)
*/
func ret_uidivmod_values
bx lr
endfunc ret_uidivmod_values
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment