{"id":102782,"date":"2019-08-14T07:00:00","date_gmt":"2019-08-14T14:00:00","guid":{"rendered":"http:\/\/devblogs.microsoft.com\/oldnewthing\/?p=102782"},"modified":"2019-09-13T21:36:19","modified_gmt":"2019-09-14T04:36:19","slug":"20190814-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20190814-00\/?p=102782","title":{"rendered":"The SuperH-3, part 8: Bit shifting"},"content":{"rendered":"<p>The bit shifting operations are fairly straightforward.<\/p>\n<pre>    ; arithmetic (signed) shifts\r\n    SHAL Rn         ; Rn &lt;&lt;= 1, T = the bit shifted out\r\n    SHAR Rn         ; Rn &gt;&gt;= 1, T = the bit shifted out\r\n\r\n    ; logical (unsigned) shifts\r\n    SHLL Rn         ; Rn &lt;&lt;= 1, T = the bit shifted out\r\n    SHLR Rn         ; Rn &gt;&gt;= 1, T = the bit shifted out\r\n    SHLL2 Rn        ; Rn &lt;&lt;= 2\r\n    SHLR2 Rn        ; Rn &gt;&gt;= 2\r\n    SHLL8 Rn        ; Rn &lt;&lt;= 8\r\n    SHLR8 Rn        ; Rn &gt;&gt;= 8\r\n    SHLL16 Rn       ; Rn &lt;&lt;= 16\r\n    SHLR16 Rn       ; Rn &gt;&gt;= 16\r\n<\/pre>\n<p>You cannot shift by arbitrary constant amounts. Only certain fixed values are permitted. If you want to shift left by, say, 9, you&#8217;ll have to construct it from a <code>SHLL8<\/code> and a <code>SHLL<\/code>.<\/p>\n<p>Note also that <code>SHAL<\/code> and <code>SHLL<\/code> are functionally equivalent. But they have different encodings, so the designers burned an opcode for a redundant operation.<\/p>\n<p>There are no &#8220;large shift&#8221; options for right shifts. You can perform multiple one-bit shifts, or use a variable shift:<\/p>\n<pre>    SHAD Rm, Rn     ; if Rm &gt; 0: Rn &lt;&lt;= (31 &amp; Rm)\r\n                    ; if Rm = 0: nop\r\n                    ; if Rm &lt; 0: Rn &gt;&gt;= (31 &amp; -Rm), signed\r\n\r\n    SHLD Rm, Rn     ; if Rm &gt; 0: Rn &lt;&lt;= (31 &amp; Rm)\r\n                    ; if Rm = 0: nop\r\n                    ; if Rm &lt; 0: Rn &gt;&gt;= (31 &amp; -Rm), unsigned\r\n<\/pre>\n<p>Note that these shift instructions shift both left <i>and<\/i> right, depending on the sign of the shift amount. If you want to shift right by an amount in a register, you therefore need to negate the value, and then shift left.<\/p>\n<p>Finally, we have rotation.<\/p>\n<pre>    ROTL Rn        ; rotate left, T contains carried-out bit\r\n    ROTR Rn        ; rotate right, T contains carried-out bit\r\n    ROTCL Rn       ; 33-bit rotate through T\r\n    ROTCR Rn       ; 33-bit rotate through T\r\n<\/pre>\n<p>The rotation instructions rotate either a 32-bit or 33-bit value by one position. For the 32-bit rotations, the bit that rotated off the end is copied to <var>T<\/var>. For the 33-bit rotations, the <var>T<\/var> flag acts as the 33rd bit.<\/p>\n<p>We saw earlier that there is no <code>NEGV<\/code> instruction. To detect overflow from a negation, you just have to check for the value <code>0x80000000<\/code> directly. Here&#8217;s the shortest sequence I could come up with:<\/p>\n<pre>    ; branch if Rn equals 0x80000000\r\n    rotl Rn        ; rotate left one bit\r\n    dt   Rn        ; decrement and test for zero\r\n    bt   underflow ; Y: underflow occurred\r\n<\/pre>\n<p>The result of the <code>DT<\/code> is zero if the previous value was 1, and the previous value was 1 if the original value was <code>0x80000000<\/code>.<\/p>\n<p>This is a destructive operation, so do it in a scratch register. You should have one available, since it&#8217;s the source register for the <code>NEGV<\/code> you were checking.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20190815-00\/?p=102784\"> We&#8217;ll look more at constants next time<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Sliding left and right.<\/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-102782","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>Sliding left and right.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/102782","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=102782"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/102782\/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=102782"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=102782"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=102782"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}