2014-01-31 5 views
1

Я хочу использовать встроенный asm для ARMv7 с clang 3.4, чтобы написать код низкого уровня, который обращается к регистрам управления ЦП. В качестве теста я написал программу, которая читает из регистра, условно спрятается с некоторыми битами и записывает новое значение.Inline asm с побочными эффектами

Однако, когда я смотрю на произведенный машинный код, вся бит-вождение оптимизирована. По-видимому, я не использовал правильные ограничения asm, чтобы сказать clang, что результат записи в регистр зависит от того, что написано. (Я использовал простой «изменчивый» модификатор).

Как написать встроенный код asm, чтобы clang генерировал правильный asm? Вот код test.c

typedef unsigned int uint32_t; 

// code that reads and writes the ID_PFR1 register 

uint32_t read_ID_PFR1() { 
    uint32_t a; 
    asm volatile ("mrc  p15, 0, %0, c0, c1, 1" : : "r"(a) :); 
    return a; 
} 

void write_ID_PFR1(uint32_t a) { 
    asm volatile ("mcr  p15, 0, %0, c0, c1, 1" :"=r"(a) : : ); 
} 

// regular c code that modifies the register 

uint32_t foo(uint32_t b) { 
    uint32_t a; 
    a = read_ID_PFR1(); 
    write_ID_PFR1(b); 
    return a+b; 
} 

void bit_fiddle() { 
    uint32_t a; 
    a = read_ID_PFR1(); 
    if ((a & 0x3) == 1) { 
    a |= 1<<2; 
    } 
    a |= 1<<3; 
    write_ID_PFR1(a); 
} 

Я составил его с

clang-3.4 -target armv7a-none-eabi test.c -o test -O3 

Это результирующий машинный код

$ arm-linux-gnueabi-objdump -S test 

test:  file format elf32-littlearm 


Disassembly of section .text: 

00000000 <read_ID_PFR1>: 
    0: ee100f31 mrc 15, 0, r0, cr0, cr1, {1} 
    4: e12fff1e bx lr 

00000008 <write_ID_PFR1>: 
    8: ee000f31 mcr 15, 0, r0, cr0, cr1, {1} 
    c: e12fff1e bx lr 

00000010 <foo>: 
    10: ee100f31 mrc 15, 0, r0, cr0, cr1, {1} 
    14: ee000f31 mcr 15, 0, r0, cr0, cr1, {1} 
    18: e12fff1e bx lr 

0000001c <bit_fiddle>: 
    1c: ee100f31 mrc 15, 0, r0, cr0, cr1, {1} 
    20: ee000f31 mcr 15, 0, r0, cr0, cr1, {1} 
    24: e12fff1e bx lr 

Как вы можете видеть в <bit_fiddle>, ничего не осталось между mrc и mcr инструкция. А также посмотрите, как foo не может добавить вместе a+b в полученный машинный код.

+0

попробовать скомпилировать с 'лязгом-3,4 -target armv7a-ни-EABI test.c -o тест -O0' – 0x90

+0

ли я просто перепутать "г" и "= г" ограничения? Разве это будет наоборот? – larsr

ответ

1

Вы близки "=": Означает, что этот операнд предназначен только для записи:

При использовании ограничений, для более точного управления эффектами ограничений , GCC предоставляет нам модификаторы ограничений. В основном используются модификаторы ограничений :

«=": означает, что этот операнд предназначен только для записи для этой инструкции; предыдущее значение отбрасывается и заменяется выходными данными. «&»: означает , что этот операнд является операндом раннего склеивания, который был изменен до , инструкция закончена с использованием входных операндов. Следовательно, этот операнд может не находиться в регистре, который используется в качестве входного операнда или как часть любого адреса памяти. Входной операнд может быть привязан к операнду раннего склеивания , если его использование только в качестве входа происходит до того, как будет записан ранний результат .

Входной и выходной сигнал определяется порядком в списке разделенных :

asm (assembler template 
     : output operands     /* optional */ 
     : input operands     /* optional */ 
     : list of clobbered registers  /* optional */ 
     ); 
  1. чтения gcc inline assembly HOWTO.
  2. Copy content of C variable into a register (GCC)
1

Я использовал неправильные ограничения «r» и «= r». write должно иметь ограничение ввода, а read должно иметь ограничение вывода.

Это способ сделать это:

uint32_t read_ID_PFR1() { 
    uint32_t a; 
    asm volatile ("mrc  p15, 0, %0, c0, c1, 1" : "=r"(a) : :); 
    return a; 
} 

void write_ID_PFR1(uint32_t a) { 
    asm volatile ("mcr  p15, 0, %0, c0, c1, 1" : : "r"(a) : ); 
} 

Вот код, созданный для bit_fiddle:

00000020 <bit_fiddle>: 
    20: ee100f31 mrc 15, 0, r0, cr0, cr1, {1} 
    24: e2001003 and r1, r0, #3 
    28: e3510001 cmp r1, #1 
    2c: 03800004 orreq r0, r0, #4 
    30: e3800008 orr r0, r0, #8 
    34: ee000f31 mcr 15, 0, r0, cr0, cr1, {1} 
    38: e12fff1e bx lr 

Довольно хороший ...

+0

Лучше всего быть самостоятельным учеником, пожалуйста, см. Мой ответ о вашем наблюдении, вы получили его почти сразу. – 0x90

Смежные вопросы