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
$
-1008 имеет такое же представление дополнения 2 как 0xFC10.Может быть, вы могли бы написать (0xfc10-0x10000)? –
Или вывести его вручную до 0xFFFFFC10? –
@tc - Интересно. Хотя инструкция li принимает только 16-битные значения, li r3,0xFFFFFC10 является юридической инструкцией. – KeithSmith