{"id":105293,"date":"2021-06-09T07:00:00","date_gmt":"2021-06-09T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=105293"},"modified":"2021-06-17T07:03:01","modified_gmt":"2021-06-17T14:03:01","slug":"20210609-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20210609-00\/?p=105293","title":{"rendered":"The ARM processor (Thumb-2), part 8: Bit shifting and bitfield access"},"content":{"rendered":"<p>The ARM processor shows off its barrel shifter once again in its collection of bit shifting instructions.<\/p>\n<pre>    ; logical shift right\r\n    lsr     Rd, Rn, #imm5       ; Rd = Rn &gt;&gt; imm5        (unsigned)\r\n    lsr     Rd, Rn, Rm          ; Rd = Rn &gt;&gt; (Rm &amp; 0xFF) (unsigned)\r\n\r\n    ; arithmetic shift right\r\n    asr     Rd, Rn, #imm5       ; Rd = Rn &gt;&gt; imm5        (signed)\r\n    asr     Rd, Rn, Rm          ; Rd = Rn &gt;&gt; (Rm &amp; 0xFF) (signed)\r\n\r\n    ; logical shift left\r\n    lsl     Rd, Rn, #imm5       ; Rd = Rn &lt;&lt; imm5\r\n    lsl     Rd, Rn, Rm          ; Rd = Rn &lt;&lt; (Rm &amp; 0xFF)\r\n\r\n    ; rotate right\r\n    ror     Rd, Rn, #imm5       ; Rd = rotate_right(Rn, imm5)\r\n    ror     Rd, Rn, Rm          ; Rd = rotate_right(Rn, Rm &amp; 0xFF)\r\n\r\n    ; rotate right extended\r\n    rrx     Rd, Rn              ; temp = Rn\r\n                                ; Rd = (carry &lt;&lt; 31) | (temp &gt;&gt; 1)\r\n                                ; carry = temp &amp; 1\r\n\r\n    ; all support the S suffix\r\n<\/pre>\n<p>For register-counted shifts, only the bottom byte of the shift amount is used. The &#8220;rotate right extended&#8221; instruction performs a 33-bit rotation, where the carry bit is the extra bit.<\/p>\n<p>If flags are updated, then the negative (N) and zero (Z) flags reflect the resulting value. The carry (C) flag contains the last bit shifted out. and the overflow (V) flag is unchanged. If the shift amount is zero, then carry is unchanged.<\/p>\n<p>There is no <code>RLX<\/code> instruction for rotating left through carry, but that&#8217;s okay, because you can emulate it:<\/p>\n<pre>    adcs    Rd, Rn, Rn          ; Rd = Rn + Rn + carry, set carry on overflow\r\n<\/pre>\n<p>Adding a number to itself is the same as shifting left one position. Adding with carry puts the former carry bit into bit 0 of the result. And setting flags on carry-out means that the previous bit 31 becomes the new carry bit. Voil\u00e0: Rotate left through carry.<\/p>\n<p>Note that for the shift instructions, the shift amount cannot itself be a shifted register. The barrel shifter is already being used by the primary opcode; it can&#8217;t be used to generate the shift amount, too.<\/p>\n<p>There are also some instructions specifically for manipulating bitfields.<\/p>\n<pre>    ; bitfield clear: zero out #w bits starting at #lsb\r\n    bfc     Rd, #lsb, #w        ; Rd[lsb+w-1:lsb] = 0\r\n\r\n    ; bitfield insert: replace #w bits in starting at #lsb\r\n    ; with least significant bits of source\r\n    bfi     Rd, Rn, #lsb, #w    ; Rd[lsb+w-1:lsb] = Rn[w-1:0]\r\n\r\n    ; unsigned bitfield extract\r\n    ubfx    Rd, Rn, #lsb, #w    ; Rd = Rn[lsb+w-1:lsb], zero-extended\r\n\r\n    ; signed bitfield extract\r\n    sbfx    Rd, Rn, #lsb, #w    ; Rd = Rn[lsb+w-1:lsb], sign-extended\r\n<\/pre>\n<p>Suppose you have a C structure like this:<\/p>\n<pre>struct S\r\n{\r\n    int x:10;\r\n    int y:12;\r\n    unsigned int z:10;\r\n};\r\n<\/pre>\n<p>which might correspond to<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse; text-align: center;\" title=\"A 32-bit bitfield, with x in bits 0 to 9, y in bits 10 to 21, and z in bits 22 to 31\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr style=\"font-size: 75%;\">\n<td>3<br \/>\n1<\/td>\n<td>3<br \/>\n0<\/td>\n<td>2<br \/>\n9<\/td>\n<td>2<br \/>\n8<\/td>\n<td>2<br \/>\n7<\/td>\n<td>2<br \/>\n6<\/td>\n<td>2<br \/>\n5<\/td>\n<td>2<br \/>\n4<\/td>\n<td>2<br \/>\n3<\/td>\n<td>2<br \/>\n2<\/td>\n<td>2<br \/>\n1<\/td>\n<td>2<br \/>\n0<\/td>\n<td>1<br \/>\n9<\/td>\n<td>1<br \/>\n8<\/td>\n<td>1<br \/>\n7<\/td>\n<td>1<br \/>\n6<\/td>\n<td>1<br \/>\n5<\/td>\n<td>1<br \/>\n4<\/td>\n<td>1<br \/>\n3<\/td>\n<td>1<br \/>\n2<\/td>\n<td>1<br \/>\n1<\/td>\n<td>1<br \/>\n0<\/td>\n<td>\n9<\/td>\n<td>\n8<\/td>\n<td>\n7<\/td>\n<td>\n6<\/td>\n<td>\n5<\/td>\n<td>\n4<\/td>\n<td>\n3<\/td>\n<td>\n2<\/td>\n<td>\n1<\/td>\n<td>\n0<\/td>\n<\/tr>\n<tr>\n<td colspan=\"10\">z<\/td>\n<td colspan=\"12\">y<\/td>\n<td colspan=\"10\">x<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Suppose the bitfield is held in register <var>r0<\/var> and the variable <var>v<\/var> is in the register <var>r1<\/var>. The bitfield instructions would correspond to these C statements:<\/p>\n<pre>    bfc     r0, #10, #12        ; s.y = 0\r\n\r\n    bfi     r0, r1, #10, #12    ; s.y = v\r\n\r\n    ubfx    r1, r0, #22, #10    ; v = s.z\r\n    sbfx    r1, r0, #10, #12    ; v = s.y\r\n<\/pre>\n<p>The &#8220;bitfield clear&#8221; instruction sets a range of bits to zero. The &#8220;bitfield insert&#8221; instruction copies the specific number of least significant bits of the source to a position in the destination. The bitfield extraction instructions copy the specific bits from the source to the least significant bits of the destination, and either zero-extends or sign-extends the result.<\/p>\n<p>The bitfield clear instruction can also be used for things other than bitfields, For example, you can write<\/p>\n<pre>    bfc     r0, r0, #14, #18    ; r0 = r0 &amp; 0x0003FFFF<\/pre>\n<p>You would be tempted to write something like<\/p>\n<pre>    and     r0, r0, #0x0003FFFF ; not a valid instruction\r\n<\/pre>\n<p>but if you try, the assembler will get mad at you because the constant <code>0x0003FFFF<\/code> cannot be encoded. There are too many 1-bits for it to be encoded as a shifted 8-bit value, and there are too many 0-bits for it to be encoded as the inverse of a shifted 8-bit value.<\/p>\n<p>The signed bit field extraction instruction is useful for sign-extending a sub-word value in a single instruction:<\/p>\n<pre>    sbfx    r0, r0, #0, #12     ; sign extend a 12-bit value\r\n\r\n    ; alternative version would have been\r\n    lsl     r0, r0, #20         ; r0 = r0 &lt;&lt; 20\r\n    asr     r0, r0, #20         ; r0 = r0 &gt;&gt; 20 (signed)\r\n<\/pre>\n<p>The bitfield instructions use a 32-bit encoding. While you could use them to sign-extend or zero-extend a byte or halfword, there are dedicated 16-bit instructions for those operations. We&#8217;ll look at those next time.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>That barrel shifter again.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[2],"class_list":["post-105293","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>That barrel shifter again.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/105293","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=105293"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/105293\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=105293"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=105293"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=105293"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}