{"id":108704,"date":"2023-09-04T07:00:00","date_gmt":"2023-09-04T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=108704"},"modified":"2023-09-01T08:48:52","modified_gmt":"2023-09-01T15:48:52","slug":"20230904-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20230904-00\/?p=108704","title":{"rendered":"Just for fun: What happens when you shift a register by more than the register size?"},"content":{"rendered":"<p>Just for fun, let&#8217;s compare what happens on different processor architectures when you shift a register by more than the register size.<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>Processor<\/th>\n<th>Register size<\/th>\n<th>Behavior<\/th>\n<\/tr>\n<tr>\n<td>8086<\/td>\n<td>Any<\/td>\n<td>mod 256 (Note 1)<\/td>\n<\/tr>\n<tr>\n<td>Alpha AXP<\/td>\n<td>64<\/td>\n<td>mod \u200764<\/td>\n<\/tr>\n<tr>\n<td>80386<\/td>\n<td>Any<\/td>\n<td>mod \u200732<\/td>\n<\/tr>\n<tr>\n<td rowspan=\"2\">x86-64<\/td>\n<td>\u2264 32<\/td>\n<td>mod \u200732<\/td>\n<\/tr>\n<tr>\n<td>64<\/td>\n<td>mod \u200764<\/td>\n<\/tr>\n<tr>\n<td>Intel ia64<\/td>\n<td>64<\/td>\n<td>full value<\/td>\n<\/tr>\n<tr>\n<td rowspan=\"2\">MIPS<\/td>\n<td>32<\/td>\n<td>mod \u200732<\/td>\n<\/tr>\n<tr>\n<td>64<\/td>\n<td>mod \u200764<\/td>\n<\/tr>\n<tr>\n<td rowspan=\"2\">PowerPC<\/td>\n<td>32<\/td>\n<td>mod \u200764<\/td>\n<\/tr>\n<tr>\n<td>64<\/td>\n<td>mod 128<\/td>\n<\/tr>\n<tr>\n<td>SH-4<\/td>\n<td>32<\/td>\n<td>mod \u200732 + sign (Note 2)<\/td>\n<\/tr>\n<tr>\n<td>ARM (Thumb-2)<\/td>\n<td>Any<\/td>\n<td>mod 256<\/td>\n<\/tr>\n<tr>\n<td rowspan=\"2\">ARM (AArch 64)<\/td>\n<td>32<\/td>\n<td>mod \u200732<\/td>\n<\/tr>\n<tr>\n<td>64<\/td>\n<td>mod \u200764<\/td>\n<\/tr>\n<tr>\n<td>68000<\/td>\n<td>32<\/td>\n<td>mod \u200764<\/td>\n<\/tr>\n<tr>\n<td>SPARC<\/td>\n<td>32<\/td>\n<td>mod \u200732<\/td>\n<\/tr>\n<tr>\n<td rowspan=\"2\">RISC-V<\/td>\n<td>32<\/td>\n<td>mod \u200732<\/td>\n<\/tr>\n<tr>\n<td>64<\/td>\n<td>mod \u200764<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Notes:<\/p>\n<ol>\n<li>On the 8086, the shift amount is given by the 8-bit <code>cl<\/code> register. The running time of the instruction is proportional to the number of bits shifted, and the processor does not optimize shifts that are larger than the register size, so if you ask to shift by 255 places, it will run a loop 255 times.<\/li>\n<li>On the SH-4, the sign of the shift amount controls the direction of the shift, and the lower 5 bits control how far to shift.<\/li>\n<\/ol>\n<p>I&#8217;ve added some architectures that are of historic or current interest. Do not assume that the presence of an architecture on this list implies that I will someday cover it, and don&#8217;t assume that omission of your favorite architecture means that I never will.<\/p>\n<p>From the above table, you can sort of come up with a taxonomy of shifts.<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>\u00a0<\/th>\n<th>Unsigned<\/th>\n<th>Signed<\/th>\n<\/tr>\n<tr>\n<th>mod register size<\/th>\n<td>Alpha AXP, x86-32, x86-64,<br \/>\nMIPS, AArch64, SPARC, RISC-V<\/td>\n<td>SH-4<\/td>\n<\/tr>\n<tr>\n<th>mod 2 \u00d7 register size<\/th>\n<td>PowerPC, 68000<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<th>mod 256<\/th>\n<td>8086, Thumb-2<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<th>full value<\/th>\n<td>ia64<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>For x86-32, I&#8217;m kind of cheating and ignoring the registers smaller than 32 bits.<\/p>\n<p><b>Bonus chatter<\/b>: The wide variety of behavior when shifting by more than the register size is one of the reasons why the C and C++ languages leave undefined what happens when you shift by more than the bit width of the shifted type.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A comparative study of processor architectures.<\/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-108704","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>A comparative study of processor architectures.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/108704","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=108704"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/108704\/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=108704"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=108704"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=108704"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}