0
4

1 回答 1

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
于 2013-08-08T04:44:29.090 回答