{"id":106907,"date":"2022-07-27T07:00:00","date_gmt":"2022-07-27T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=106907"},"modified":"2022-11-29T10:19:49","modified_gmt":"2022-11-29T18:19:49","slug":"20220727-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20220727-00\/?p=106907","title":{"rendered":"The AArch64 processor (aka arm64), part 2: Extended register operations"},"content":{"rendered":"<p>There are a number of places where the instruction set permits the value in a register to be transformed before it is used. The set of valid transforms vary from instruction to instruction, but they share a common syntax.<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th style=\"border: solid 1px gray;\">\u00a0<\/th>\n<th style=\"border: solid 1px gray;\">Operand<\/th>\n<th style=\"border: solid 1px gray;\" colspan=\"3\">Meaning<\/th>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px gray; vertical-align: middle; width: 1em;\" rowspan=\"3\"><span style=\"writing-mode: vertical-lr; -ms-writing-mode: tb-rl; transform: rotate(180deg);\">Shifted<\/span><\/td>\n<td style=\"border: solid 1px gray;\"><code>Rn\/zr, LSL #n<\/code><\/td>\n<td style=\"border: solid 1px gray;\" colspan=\"3\">Logical shift left.<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px gray;\"><code>Rn\/zr, LSR #n<\/code><\/td>\n<td style=\"border: solid 1px gray;\" colspan=\"3\">Logical (unsigned) shift right.<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px gray;\"><code>Rn\/zr, ASR #n<\/code><\/td>\n<td style=\"border: solid 1px gray;\" colspan=\"3\">Arithmetic (signed) shift right.<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px gray; vertical-align: middle; width: 1em;\" rowspan=\"8\"><span style=\"writing-mode: vertical-lr; -ms-writing-mode: tb-rl; transform: rotate(180deg);\">Extended<\/span><\/td>\n<td style=\"border: solid 1px gray;\"><code>Wn\/sp, UXTB #n<\/code><\/td>\n<td style=\"border: solid 1px gray; border-right: none;\">Unsigned<\/td>\n<td style=\"border: 1px gray; border-style: solid none;\">extend low byte<\/td>\n<td style=\"border: solid 1px gray; border-left: none;\">shifted left.<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px gray;\"><code>Wn\/sp, UXTH #n<\/code><\/td>\n<td style=\"border: solid 1px gray; border-right: none;\">Unsigned<\/td>\n<td style=\"border: 1px gray; border-style: solid none;\">extend low halfword<\/td>\n<td style=\"border: solid 1px gray; border-left: none;\">shifted left.<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px gray;\"><code>Wn\/sp, UXTW #n<\/code><\/td>\n<td style=\"border: solid 1px gray; border-right: none;\">Unsigned<\/td>\n<td style=\"border: 1px gray; border-style: solid none;\">extend low word<\/td>\n<td style=\"border: solid 1px gray; border-left: none;\">shifted left.<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px gray;\"><code>Xn\/sp, UXTX #n<\/code><\/td>\n<td style=\"border: solid 1px gray; border-right: none;\">Unsigned<\/td>\n<td style=\"border: 1px gray; border-style: solid none;\">extend low doubleword<\/td>\n<td style=\"border: solid 1px gray; border-left: none;\">shifted left.<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px gray;\"><code>Wn\/sp, SXTB #n<\/code><\/td>\n<td style=\"border: solid 1px gray; border-right: none;\">Signed<\/td>\n<td style=\"border: 1px gray; border-style: solid none;\">extend low byte<\/td>\n<td style=\"border: solid 1px gray; border-left: none;\">shifted left.<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px gray;\"><code>Wn\/sp, SXTH #n<\/code><\/td>\n<td style=\"border: solid 1px gray; border-right: none;\">Signed<\/td>\n<td style=\"border: 1px gray; border-style: solid none;\">extend low halfword<\/td>\n<td style=\"border: solid 1px gray; border-left: none;\">shifted left.<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px gray;\"><code>Wn\/sp, SXTW #n<\/code><\/td>\n<td style=\"border: solid 1px gray; border-right: none;\">Signed<\/td>\n<td style=\"border: 1px gray; border-style: solid none;\">extend low word<\/td>\n<td style=\"border: solid 1px gray; border-left: none;\">shifted left.<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px gray;\"><code>Xn\/sp, SXTX #n<\/code><\/td>\n<td style=\"border: solid 1px gray; border-right: none;\">Signed<\/td>\n<td style=\"border: 1px gray; border-style: solid none;\">extend low doubleword<\/td>\n<td style=\"border: solid 1px gray; border-left: none;\">shifted left.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The <code>LSL<\/code>, <code>LSR<\/code>, and <code>ASR<\/code> transformations are formally known as <i>shifted registers<\/i>. They take a value in a register and shift it.<\/p>\n<p>The extend+shift transformations are formally known as <i>extended registers<\/i>. They extract a subset of the source register, extend it either as a signed or unsigned value to the full operand size, and then shift the extended result.<\/p>\n<p>Shifting the zero register isn&#8217;t particular useful since you still get zero, but the instruction encoding lets you do it. Similarly, there is no practical difference between <code>UXTX<\/code> and <code>SXTX<\/code> (unsigned and signed extension of the low doubleword of a 64-bit register) since the low doubleword of a 64-bit register is <i>the whole register<\/i>.<\/p>\n<p>For extended registers, the assembler lets you omit the shift amount, in which case it defaults to zero. The shift amount is not optional for the shifted registers.<\/p>\n<p>Before you get all excited about the possibilities, know that not all instructions support all of these transformations, and for the ones that they do, the shift amounts are limited. We&#8217;ll look at the restrictions as they arise. For now, I just wanted to introduce the concepts.<\/p>\n<p>As a convenience, if you are using an instruction that accepts only extended registers, but you want to use a <code>LSL<\/code>, you can write <code>LSL #n<\/code>, and the assembler will autoconvert it to <code>UXTW #n<\/code> or <code>UXTX #n<\/code>, depending on the operand size.<\/p>\n<p>Next time, we&#8217;ll start putting these transforms to use when we look at addressing modes.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The weird ways of transforming the value in a register.<\/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-106907","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>The weird ways of transforming the value in a register.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/106907","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=106907"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/106907\/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=106907"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=106907"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=106907"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}