2013-04-18 1 views
5

Я хочу вызвать исключение Undefined Инструкция ARM Cortex-M3 для проверки моего тестового прибора. Компилятор IAR поддерживает это с помощью встроенных сборок следующим образом:Программно вызывать исключение Undefined Instruction

asm ("udf.w # 0");

К сожалению, встроенный ассемблер GNU CC не знает этот код операции для NXP LPC177x8x. Он пишет диагностику:

ccw3kZ46.s:404: Error: bad instruction `udf.w #0' 

Как создать функцию, которая вызывает исключение Undefined Instruction?

+0

Согласно http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0337e/I1010015.html BLX от thumb16 не поддерживается M3 и «всегда неисправности». –

ответ

7

Опираясь на ответ Masta79 «s:

Существует "постоянно неопределенными" кодирование перечислены в ARMv7-M эталонной архитектуры руководство - ARM DDI 0403D (documentation placeholder, registration required). Кодировка - 0xf7fXaXXX (где «X» игнорируется). Конечно инструкции выборок, которые мало-младшему, так (без тестирования):

asm volatile (".word 0xf7f0a000\n");

должен дать гарантированную неопределенную инструкцию по любому ARMv7-M или более поздней версии процессора.

+0

Я думаю, что он находится в режиме «большого пальца»; выполните эту работу в этом режиме? –

+2

Cortex-M3 имеет только режим Thumb. Тем не менее Thumb с Thumb-2 расширениями, то есть есть 16-разрядные и 32-битные инструкции. «Постоянно неопределенный» - 32-битный. – unixsmurf

+1

Я не думаю, что вы должны вручную изменить этот символ здесь. Ассемблер автоматически поменяет конечный элемент. – tangrs

4

Версия неизменной команды thumbn-16 - 0xDExx. Таким образом, вы можете сделать это в вашем коде, чтобы вызвать исключение:

.short 0xde00 

Код: ARMv7-M Architecture Reference Manual, раздел A5.2.6.

(Обратите внимание, что кодирование 0xF7Fx, 0xAxxx также постоянно не определено, но это 32-разрядная инструкция.)

2

Некоторые дополнительные информации ...

Один из НКУ-х builtins является

void __builtin_trap (void)

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

Его implementation for ARMv7 is:

(define_insn "trap" 
    [(trap_if (const_int 1) (const_int 0))] 
    "" 
    "* 
    if (TARGET_ARM) 
    return \".inst\\t0xe7f000f0\"; 
    else 
    return \".inst\\t0xdeff\"; 
    " 
    [(set (attr "length") 
    (if_then_else (eq_attr "is_thumb" "yes") 
       (const_int 2) 
       (const_int 4))) 
    (set_attr "type" "trap") 
    (set_attr "conds" "unconditional")] 
) 

Так что для ARM режима GCC будет генерировать 0x7f000f0 (f0 00 f0 07) и для других режимов 0xdeff (ff de) (удобна при разборке/отладки).

Also note that:

these encodings match the UDF instruction that is defined in the most 
recent edition of the ARM architecture reference manual. 

Thumb: 0xde00 | imm8 (we chose 0xff for the imm8) 
ARM: 0xe7f000f0 | (imm12 << 8) | imm4 (we chose to use 0 for both imms) 

Для LLVM__builtin_trap значений генерироваться является 0xe7ffdefe и 0xdefe:

case ARM::TRAP: { 
    // Non-Darwin binutils don't yet support the "trap" mnemonic. 
    // FIXME: Remove this special case when they do. 
    if (!Subtarget->isTargetDarwin()) { 
    //.long 0xe7ffdefe @ trap 
    uint32_t Val = 0xe7ffdefeUL; 
    OutStreamer.AddComment("trap"); 
    OutStreamer.EmitIntValue(Val, 4); 
    return; 
    } 
    break; 
} 
case ARM::tTRAP: { 
    // Non-Darwin binutils don't yet support the "trap" mnemonic. 
    // FIXME: Remove this special case when they do. 
    if (!Subtarget->isTargetDarwin()) { 
    //.short 57086 @ trap 
    uint16_t Val = 0xdefe; 
    OutStreamer.AddComment("trap"); 
    OutStreamer.EmitIntValue(Val, 2); 
    return; 
    } 
    break; 
} 
2

Существует различные официальные неопределенные инструкции в [1] (ищите UDF, . ниже, может быть заменен с любой шестнадцатеричной цифрой):

  • 0xe7f...f. - ARM или А1 кодирование (ARMv4T, ARMv5T, ARMv6, ARMv7)
  • 0xde.. - большой палец рука или кодирование Т1 (ARMv4T, ARMv5T, ARMv6, ARMv7)
  • 0xf7f.a... - Thumb2 или кодирование Т2 (ARMv6T2, ARMv7)

Есть и другие, но они, вероятно, являются такими же надежными, как и в будущем.

Как для генерации кода, который запускает его, вы можете просто использовать .short или .word, как это:

  • asm volatile (".short 0xde00\n");/* большой палец запрещенная команда */
  • asm volatile (".word 0xe7f000f0\n");/* вооружить запрещенная команда */
  • asm volatile (".word 0xe7f0def0\n");/* рука + палец нелегальный инструкция */

Обратите внимание, что последний будет decod e до 0xdef0, 0xe7f0 в контексте большого пальца и, следовательно, также вызывает неопределенное исключение инструкции.

[1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.subset.architecture.reference/index.html

+0

Имеет ли какой-либо вкус языка сборки ARM для мнемоники для любого из них, как у x86 есть ['UD2'] (http://www.felixcloutier.com/x86/UD2.html)? –

+1

Документы ARM ссылаются на 'UDF', но я не знаю, признано ли это ассемблерами. gcc/gas не признает это. – domen

+0

И для ARMv8/aarch64/arm64 существуют 'BRK',' HLT', 'HVC',' SMC' и 'SVC', задокументированные в * C3.1.4 Генерация и возврат исключений * DDI0487A (ARM ARM).Не совсем «неопределенно неопределенный», но может быть полезным. – domen