Опция ARMv7 gcc для принудительного разделения - PullRequest
0 голосов
/ 08 октября 2018

Я использую GCC для создания голого металлического приложения для ядра ARMv7, которое поддерживает собственные деления.Я удалил все зависимости библиотеки.

Компилятор C GCC иногда ссылается на __aeabi_uidiv ().В других случаях он решит использовать аппаратное деление (для целочисленного деления без знака).Я не смог найти флаг компилятора, который заставил бы его использовать аппаратные деления (вместо вызовов __aeabi_ * lib).Кто-нибудь знает о таком флаге?

РЕДАКТИРОВАТЬ: Я должен уточнить, что я правильно использую флаги компилятора -mtune = cortex-a7 и -march = armv7-a для i.MX6ULL.

Пример ошибки:

uint32_t GenerateError(uint32_t num, uint32_t den) {
    return num / den; //generates undefined reference to __aeabi_uidiv
}

Ответы [ 2 ]

0 голосов
/ 09 октября 2018

То, что вы ищете, это -march=armv7ve.Это будет предназначаться для Armv7 с инструкцией аппаратного разделения.-mcpu=cortex-a15 и cortex-a7 предназначены для этой архитектуры, поэтому они будут генерировать инструкции деления.

0 голосов
/ 08 октября 2018

gcc - такой компилятор.

uint8_t fun_u8 ( uint8_t a, uint8_t b )
{
    return(a/b);
}
uint16_t fun_u16 ( uint16_t a, uint16_t b )
{
    return(a/b);
}
uint32_t fun_u32 ( uint32_t a, uint32_t b )
{
    return(a/b);
}
uint64_t fun_u64 ( uint64_t a, uint64_t b )
{
    return(a/b);
}

int8_t fun_s8 ( int8_t a, int8_t b )
{
    return(a/b);
}
int16_t fun_s16 ( int16_t a, int16_t b )
{
    return(a/b);
}
int32_t fun_s32 ( int32_t a, int32_t b )
{
    return(a/b);
}
int64_t fun_s64 ( int64_t a, int64_t b )
{
    return(a/b);
}

build

arm-none-eabi-gcc -O2 -mcpu = cortex-a7 -c so.c -o so.o

результат

00000000 <fun_u8>:
   0:   e730f110    udiv    r0, r0, r1
   4:   e12fff1e    bx  lr

00000008 <fun_u16>:
   8:   e730f110    udiv    r0, r0, r1
   c:   e12fff1e    bx  lr

00000010 <fun_u32>:
  10:   e730f110    udiv    r0, r0, r1
  14:   e12fff1e    bx  lr

00000018 <fun_u64>:
  18:   e92d4010    push    {r4, lr}
  1c:   ebfffffe    bl  0 <__aeabi_uldivmod>
  20:   e8bd8010    pop {r4, pc}

00000024 <fun_s8>:
  24:   e730f110    udiv    r0, r0, r1
  28:   e12fff1e    bx  lr

0000002c <fun_s16>:
  2c:   e710f110    sdiv    r0, r0, r1
  30:   e6bf0070    sxth    r0, r0
  34:   e12fff1e    bx  lr

00000038 <fun_s32>:
  38:   e710f110    sdiv    r0, r0, r1
  3c:   e12fff1e    bx  lr

00000040 <fun_s64>:
  40:   e92d4010    push    {r4, lr}
  44:   ebfffffe    bl  0 <__aeabi_ldivmod>
  48:   e8bd8010    pop {r4, pc}

Из документации по правильной документации имеется аппаратная поддержка до 32 бит / 32 бит.Выше того, что вам нужно вызвать библиотеку (то же самое относится и к умножению), просто чтобы подтвердить ожидания, можно добавить:

uint8_t fun_m8 ( uint32_t a, uint8_t b )
{
    return(a/b);
}
uint16_t fun_m16 ( uint32_t a, uint16_t b )
{
    return(a/b);
}
uint32_t fun_m32 ( uint32_t a, uint32_t b )
{
    return(a/b);
}

0000004c <fun_m8>:
  4c:   e730f110    udiv    r0, r0, r1
  50:   e6ef0070    uxtb    r0, r0
  54:   e12fff1e    bx  lr

00000058 <fun_m16>:
  58:   e730f110    udiv    r0, r0, r1
  5c:   e6ff0070    uxth    r0, r0
  60:   e12fff1e    bx  lr

00000064 <fun_m32>:
  64:   e730f110    udiv    r0, r0, r1
  68:   e12fff1e    bx  lr

нет ничего удивительного.

теперь в режиме arm часто компиляторы делают большой палецmode ...

00000000 <fun_u8>:
   0:   fbb0 f0f1   udiv    r0, r0, r1
   4:   4770        bx  lr
   6:   bf00        nop

00000008 <fun_u16>:
   8:   fbb0 f0f1   udiv    r0, r0, r1
   c:   4770        bx  lr
   e:   bf00        nop

...

Без изменений thumb2 на этой платформе также поддерживает деление, поэтому оно больше, чем требования к компилируемому коду, который определяет, может ли он использовать инструкцию по аппаратному обеспечению и для этого теста, gcc выбрал желаемую инструкцию по аппаратному обеспечению, а не вызов gcclib (для тех, которые он может).

Если вы хотите, чтобы компилятор использовал инструкции по аппаратному обеспечению, то проинструктируйте компилятор использовать нужный набор инструкций.И держите свой код в пределах возможностей этого набора инструкций.И используйте библиотеки, которые также скомпилированы для интересующего набора команд, и этот код находится в пределах этого набора инструкций.(а затем посмотрите, использует ли компилятор весь набор инструкций или, по крайней мере, интересующие инструкции, если нет, то создайте свою собственную библиотечную функцию для разделения в сборке и вызовите ее).

...