{"id":107032,"date":"2022-08-22T07:00:00","date_gmt":"2022-08-22T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=107032"},"modified":"2022-08-21T18:09:56","modified_gmt":"2022-08-22T01:09:56","slug":"20220822-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20220822-00\/?p=107032","title":{"rendered":"The AArch64 processor (aka arm64), part 19: Miscellaneous instructions"},"content":{"rendered":"<p>There are far more instructions than I&#8217;m going to cover here in this series. I&#8217;ve skipped over the floating point instructions, the SIMD instructions, and specialty instructions that I haven&#8217;t yet seen come out of the compiler. I&#8217;m also largely skipping over the instructions that are not part of the core instruction set but are available only in optional extensions.<\/p>\n<p>Here are a few that are still interesting, even if I haven&#8217;t seen the compiler generate them.<\/p>\n<pre>    ; count leading zeroes (high order bits)\r\n    clz     Rd, Rm          ; Rd = number of leading zeroes in Rm\r\n\r\n    ; count leading sign bits (high order bits)\r\n    cls     Rd, Rm          ; Rd = number of leading sign bits in Rm\r\n\r\n    ; reverse bits in register\r\n    rbit    Rd, Rm          ; Rd = Rm bitwise reversed\r\n\r\n    ; reverse bytes in register\r\n    rev     Rd, Rm          ; Rd = Rm bytewise reversed\r\n\r\n    ; reverse bytes in each halfword\r\n    rev16   Rd, Rm\r\n\r\n    ; reverse bytes in each word\r\n    rev32   Rd, Rm\r\n\r\n    ; reverse bytes in doubleword\r\n    ; (pseudo-instruction, equivalent to rev with 64-bit register)\r\n    rev64   Rd, Rm\r\n<\/pre>\n<p>A few miscellaneous bit-fiddling instructions. The reversal instructions are primarily for changing data endianness. AArch64 lost the <code>REVSH<\/code> instruction from AArch32.<\/p>\n<p>The next few instructions provide multiprocessing hints.<\/p>\n<pre>    ; yield to other threads\r\n    yield\r\n\r\n    ; wait for interrupt (privileged instruction)\r\n    wfi\r\n<\/pre>\n<p>The <code>YIELD<\/code> instruction is a hint to multi-threading processors that the current thread should be de-prioritized in favor of other threads. You typically see this instruction dropped into spin loops, via the intrinsic <code>__yield()<\/code>.<\/p>\n<p>The <code>WFI<\/code> instruction instructs the processor to go into a low-power state until an interrupt occurs. There are other instructions related to &#8220;events&#8221; which I won&#8217;t bother going into.<\/p>\n<p>The next few instructions are for communicating with the operating system:<\/p>\n<pre>        hlt     #imm16      ; halt\r\n        svc     #imm16      ; system call\r\n        brk     #imm16      ; software breakpoint\r\n        udf     #imm16      ; undefined opcode\r\n<\/pre>\n<p>The instructions carry a 16-bit immediate that the operating system can choose to use for whatever purpose it desires.<\/p>\n<p>The undefined opcode is a range of instructions from <code>0x00000000<\/code> through <code>0x0000ffff<\/code> that are architecturally set aside as permanently undefined instructions.\u00b9<\/p>\n<p>Windows uses <code>BRK<\/code> for special operations.<\/p>\n<pre>        brk     #0xf000     ; breakpoint\r\n        brk     #0xf001     ; assertion failure\r\n        brk     #0xf002     ; debug service\r\n        brk     #0xf003     ; fastfail\r\n        brk     #0xf004     ; divide by zero\r\n<\/pre>\n<p>The divide-by-zero breakpoint is emitted by the compiler if it detects a zero denominator.<\/p>\n<pre>    cbnz    w0, @F          ; jump if denominator is nonzero\r\n    brk     #0xf004         ; oops: manually raise div0 exception\r\n@@: sdiv    w0, w1, w2      ; signed divide\r\n<\/pre>\n<p>And of course, we have this guy:<\/p>\n<pre>    nop\r\n<\/pre>\n<p>The <code>NOP<\/code> instruction does nothing but occupy space. Use it to pad code to meet alignment requirements, but do not use it for timing.<\/p>\n<p>Now that we have the basic instruction set under our belt, we&#8217;ll look at the calling convention next time.<\/p>\n<p>\u00b9 This means that zero encodes <code>udf #0<\/code>, which will trap on an invalid instruction. This is different from classic ARM, where zero encodes <code>andeq r0, r0, r0<\/code> which is functionally a nop, and Thumb-2, where zero is the <code>movs r0, r0<\/code> instruction, which is a mostly-nop except that it sets flags. Personally, I&#8217;m a big fan of having zero encode an invalid instruction. It helps post-mortem debugging a lot.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Sweeping up the crumbs.<\/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-107032","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>Sweeping up the crumbs.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/107032","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=107032"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/107032\/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=107032"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=107032"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=107032"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}