2012-06-21 2 views
5

Я новичок в сборке PowerPC. Я работаю с MPC8245 (да, старая школа). Это семейный процессор 603e.PowerPC Assembly Load Immediate

Я хотел бы знать, как создать немедленную инструкцию по загрузке, где немедленное 16-битное значение «unsigned».

Пример: литий r3,0xFC10

ССАГПЗ кросс-компилятор, 4.4.5, я использую не позволяет этой инструкции, поскольку значение не подписанная постоянным.

Да, я мог бы использовать минус дополнение 2-го уровня, но это затрудняет чтение и документирование кода. При загрузке битовых полей для регистров устройств точное считывание полей бит в инструкции намного проще.

+0

-1008 имеет такое же представление дополнения 2 как 0xFC10.Может быть, вы могли бы написать (0xfc10-0x10000)? –

+0

Или вывести его вручную до 0xFFFFFC10? –

+0

@tc - Интересно. Хотя инструкция li принимает только 16-битные значения, li r3,0xFFFFFC10 является юридической инструкцией. – KeithSmith

ответ

10

li - псевдо-код операции, который фактически переводится как инструкция addi.

addi rD, rA, SIMM добавляет подписанный непосредственным SIMM к rA, помещая результат в rD, кроме когда rA поле 0, в этом случае он указывает буквальное 0 вместо r0. li rD, SIMM действительно addi rD, 0, SIMM.

Это хорошо для значений нагрузки от 0 - 0x7fff и 0xffff8000 - 0xffffffff в регистр, но не другие значения.

Операции с побитовыми операциями (ori и т. Д.) Интерпретируют 16-битовое немедленное поле как значение без знака. Однако у них нет «r0» означает значение 0 «поведение addi.

Вам нужно будет использовать две инструкции, чтобы загрузить константу 0xfc10 в регистр: загружать регистр с 0 с помощью li (или lis, как если бы вы загружали в верхнюю часть произвольной 32-битовую константу), а затем ИЛИ в 16-битном значении без знака с ori.

Это именно то, что делает gcc при обстоятельствах:

$ cat test.c 
unsigned int test(void) 
{ 
    return 0xfc10; 
} 
$ gcc -O2 -c test.c 
$ objdump -d test.o 

test.o:  file format elf32-powerpc 

Disassembly of section .text: 

00000000 <test>: 
    0: 38 60 00 00  li  r3,0 
    4: 60 63 fc 10  ori  r3,r3,64528 
    8: 4e 80 00 20  blr 
    c: 60 00 00 00  nop 
$ 

Я не думаю ассемблер GNU имеет какой-либо способ автоматического генерирования двух команд для загрузки такого значения из одного при сборке для PowerPC. Однако вы можете использовать @h и @l суффиксов для извлечения (без знака) высоких и низких 16-битовых половин константы, например:

lis r3, [email protected]   /* => li r3, 0x1234  */ 
ori r3, r3, [email protected]  /* => ori r3, r3, 0x5678 */ 

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

$ cat test2.s 
     .macro load_const rD, const 
     .if (\const >= -0x8000) && (\const <= 0x7fff) 
     li  \rD, \const 
     .else 
     lis  \rD, \[email protected] 
     ori  \rD, \rD, \[email protected] 
     .endif 
     .endm 

     load_const r3, 0 
     load_const r4, 1 
     load_const r5, -1 
     load_const r6, 0x7fff 
     load_const r7, 0x8000 
     load_const r8, -32767 
     load_const r9, -32768 
     load_const r10, -32769 
     load_const r11, 0xfc10 

$ as -mregnames -o test2.o test2.s 
$ objdump -d test2.o 

test2.o:  file format elf32-powerpc 

Disassembly of section .text: 

00000000 <.text>: 
    0: 38 60 00 00  li  r3,0 
    4: 38 80 00 01  li  r4,1 
    8: 38 a0 ff ff  li  r5,-1 
    c: 38 c0 7f ff  li  r6,32767 
    10: 3c e0 00 00  lis  r7,0 
    14: 60 e7 80 00  ori  r7,r7,32768 
    18: 39 00 80 01  li  r8,-32767 
    1c: 39 20 80 00  li  r9,-32768 
    20: 3d 40 ff ff  lis  r10,-1 
    24: 61 4a 7f ff  ori  r10,r10,32767 
    28: 3d 60 00 00  lis  r11,0 
    2c: 61 6b fc 10  ori  r11,r11,64528 
$ 
+0

Мэтт - Спасибо за подробный ответ. В среде сборки, которую я использую, есть макрос 'lwi'. Ошибка, сообщаемая gcc при использовании значения без знака с 'li', равна« Ошибка: операнд вне диапазона (0x00008000 не находится между 0xffff8000 и 0x00007fff) », как указано выше. – KeithSmith

0

Вы также можете загрузить неподписанный 16-бит немедленного с помощью оператора ori, но не забудьте очистить регистр перед:

xor r3, r3, r3 
ori r3, r3, 0xFC10