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 位表示,可以在 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<<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 并且还具有以下其他变体:
如果您在 arm 文档中查看 if 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' 的 [9:8] 意味着我们可以有 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