我的问题与拇指编码可能的常数值有关。
我正在使用ARM v7
指令集。
参考手册说,在用拇指书写指令时可以使用的常量被编码为12位编码,而psudocode ThumbExpandImm()
(ARM的ARM中的第233页)描述了编码过程和可能的常量。与指令一起使用。
I am trying to generate the constants values that are possible with the instruction using the process described by `ThumbExpandImm()` .
我对<11:10>
常量编码的12 bit
位不等于'00'
时提到的最后一种可能性有疑问
,在这种情况下,手册说这个数字用旋转表示为立即值。
当我生成这样的数字并尝试汇编时,汇编程序会发出一条消息:
“cannot be represented by 0-255 shifted left by 0-23 or duplicated in all, odd or even bytes”
我不明白为什么汇编程序在谈论左移时手动说旋转。 我也想知道使用这种方案编码背后的想法,因为在编码中允许弄清楚我想要使用的常数值是否很难。
答案 0 :(得分:1)
我会帮助你解决这个问题......
if imm12<11:10> == ‘00’ then
....
else
unrotated_value = ZeroExtend(‘1’:imm12<6:0>, 32);
(imm32, carry_out) = ROR_C(unrotated_value, UInt(imm12<11:7>));
return (imm32, carry_out);
所以试试这个,这是gnu汇编程序。
.syntax unified
.thumb
movs r0,#1
movs r0,#2
movs r0,#3
movw r5,#0x123
movw r6,#0x123
movw r7,#0x123
movw r0,#0x076
movw r0,#0x876
movs.w r0,#0x2000
movs.w r0,#0x4000
movs.w r0,#0x8000
我猜您根据错误消息使用其他内容,但这不会影响编码......
00000000 <.text>:
0: 2001 movs r0, #1
2: 2002 movs r0, #2
4: 2003 movs r0, #3
6: f240 1523 movw r5, #291 ; 0x123
a: f240 1623 movw r6, #291 ; 0x123
e: f240 1723 movw r7, #291 ; 0x123
12: f240 0076 movw r0, #118 ; 0x76
16: f640 0076 movw r0, #2166 ; 0x876
1a: f45f 5000 movs.w r0, #8192 ; 0x2000
1e: f45f 4080 movs.w r0, #16384 ; 0x4000
22: f45f 4000 movs.w r0, #32768 ; 0x8000
拿这一个
1e:f45f 4080 movs.w r0,#16384; 0x4000的
i = 1,imm3 = 0b100,imm8 = 0b10000000
imm12是0xC80,位11:10是0b11,它不等于0b00所以
未旋转值= ZeroExtend(0b100000000)= 0x00000080 imm32 = ror(0x00000080,0b11001)= ror(0x00000080,25)
旋转24将是从右边取6个半字节并将它们移到左边
00000080
00 000080
000080 00
0x00008000
右边的一个给出0x00004000,这是我们想要的常数。
所以基本上你的常数必须用你选择的7位代表1,它可以在0b01000和0b11111(8和63)之间旋转
0: f45f 3090 movs.w r0, #73728 ; 0x12000
0x00000090向右旋转(10111)23
0x00009000是24的旋转,因此0x00012000是23的旋转。
或者将其视为0x00000090向左旋转32-23 = 9
向左旋转8是0x00009000所以9是0x00012000。
4: f45f 2009 movs.w r0, #561152 ; 0x89000
0x00000089向左旋转32-20 = 12(10100)
0x00000089&lt;&lt;&lt; 12 = 0x00089000
这与ARM编码几乎相同。基本上如果你不能在0x00和0xFF之间取一个数字并向左移动以获得你想要的常数你可能不能使用该常数。或者另一种看待它的方法是你最重要的非零与最小之间的距离是多少,如果它们相距8位以上,就这种旋转而言它就不会起作用。
这些都有位模式10011001,两边都有一些零,可以编码。
f45f 7099 movs.w r0, #0x132
f45f 7019 movs.w r0, #0x264
f45f 6099 movs.w r0, #0x4c8
f45f 6019 movs.w r0, #0x990
现在对于mov指令,因为我碰巧看着它,我可以这样做:
f241 2034 movw r0, #0x1234
因为只要你不想做一个movs就会有16位立即崩溃。如果你确实想要movs那么你有imm12情况而不是imm16情况。
thumb2编码比arm编码灵活得多,因为它有imm16,还有其他变体:
如果你看到你的手臂文件中的相同位置,如果imm12 [11:10] ='00'
case imm12<9:8> of
when ‘00’
imm32 = ZeroExtend(imm12<7:0>, 32);
when ‘01’
if imm12<7:0> == ‘00000000’ then UNPREDICTABLE;
imm32 = ‘00000000’ : imm12<7:0> : ‘00000000’ : imm12<7:0>;
when ‘10’
if imm12<7:0> == ‘00000000’ then UNPREDICTABLE;
imm32 = imm12<7:0> : ‘00000000’ : imm12<7:0> : ‘00000000’;
when ‘11’
if imm12<7:0> == ‘00000000’ then UNPREDICTABLE;
imm32 = imm12<7:0> : imm12<7:0> : imm12<7:0> : imm12<7:0>;
所以[00:8]的'00'意味着我们可以有0到255之间的任何数字。
f05f 0099 movs.w r0, #0x00000099
'01'表示1到255之间的任何数字,但相同的数字必须位于[7:0]和[23:16]位置的常数
f05f 1099 movs.w r0, #0x00990099
'10'的情况是指1到255之间的任何数字,但该数字必须位于数字的[31:24]和[15:8]位置
f05f 2099 movs.w r0, #0x99009900
和'11'的情况,1到255之间的任何数字,但相同的数字必须在所有四个字节中
f05f 3012 movs.w r0, #0x12121212
f05f 3089 movs.w r0, #0x89898989