Source file test/codegen/rotate.go
1 // asmcheck 2 3 // Copyright 2018 The Go Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file. 6 7 package codegen 8 9 import "math/bits" 10 11 // ------------------- // 12 // const rotates // 13 // ------------------- // 14 15 func rot64(x uint64) uint64 { 16 var a uint64 17 18 // amd64:"ROLQ\t[$]7" 19 // ppc64x:"ROTL\t[$]7" 20 // loong64: "ROTRV\t[$]57" 21 // riscv64: "RORI\t[$]57" 22 a += x<<7 | x>>57 23 24 // amd64:"ROLQ\t[$]8" 25 // arm64:"ROR\t[$]56" 26 // s390x:"RISBGZ\t[$]0, [$]63, [$]8, " 27 // ppc64x:"ROTL\t[$]8" 28 // loong64: "ROTRV\t[$]56" 29 // riscv64: "RORI\t[$]56" 30 a += x<<8 + x>>56 31 32 // amd64:"ROLQ\t[$]9" 33 // arm64:"ROR\t[$]55" 34 // s390x:"RISBGZ\t[$]0, [$]63, [$]9, " 35 // ppc64x:"ROTL\t[$]9" 36 // loong64: "ROTRV\t[$]55" 37 // riscv64: "RORI\t[$]55" 38 a += x<<9 ^ x>>55 39 40 // amd64:"ROLQ\t[$]10" 41 // arm64:"ROR\t[$]54" 42 // s390x:"RISBGZ\t[$]0, [$]63, [$]10, " 43 // ppc64x:"ROTL\t[$]10" 44 // arm64:"ROR\t[$]54" 45 // s390x:"RISBGZ\t[$]0, [$]63, [$]10, " 46 // loong64: "ROTRV\t[$]54" 47 // riscv64: "RORI\t[$]54" 48 a += bits.RotateLeft64(x, 10) 49 50 return a 51 } 52 53 func rot32(x uint32) uint32 { 54 var a uint32 55 56 // amd64:"ROLL\t[$]7" 57 // arm:"MOVW\tR\\d+@>25" 58 // ppc64x:"ROTLW\t[$]7" 59 // loong64: "ROTR\t[$]25" 60 // riscv64: "RORIW\t[$]25" 61 a += x<<7 | x>>25 62 63 // amd64:`ROLL\t[$]8` 64 // arm:"MOVW\tR\\d+@>24" 65 // arm64:"RORW\t[$]24" 66 // s390x:"RLL\t[$]8" 67 // ppc64x:"ROTLW\t[$]8" 68 // loong64: "ROTR\t[$]24" 69 // riscv64: "RORIW\t[$]24" 70 a += x<<8 + x>>24 71 72 // amd64:"ROLL\t[$]9" 73 // arm:"MOVW\tR\\d+@>23" 74 // arm64:"RORW\t[$]23" 75 // s390x:"RLL\t[$]9" 76 // ppc64x:"ROTLW\t[$]9" 77 // loong64: "ROTR\t[$]23" 78 // riscv64: "RORIW\t[$]23" 79 a += x<<9 ^ x>>23 80 81 // amd64:"ROLL\t[$]10" 82 // arm:"MOVW\tR\\d+@>22" 83 // arm64:"RORW\t[$]22" 84 // s390x:"RLL\t[$]10" 85 // ppc64x:"ROTLW\t[$]10" 86 // arm64:"RORW\t[$]22" 87 // s390x:"RLL\t[$]10" 88 // loong64: "ROTR\t[$]22" 89 // riscv64: "RORIW\t[$]22" 90 a += bits.RotateLeft32(x, 10) 91 92 return a 93 } 94 95 func rot16(x uint16) uint16 { 96 var a uint16 97 98 // amd64:"ROLW\t[$]7" 99 // riscv64: "OR","SLLI","SRLI",-"AND" 100 a += x<<7 | x>>9 101 102 // amd64:`ROLW\t[$]8` 103 // riscv64: "OR","SLLI","SRLI",-"AND" 104 a += x<<8 + x>>8 105 106 // amd64:"ROLW\t[$]9" 107 // riscv64: "OR","SLLI","SRLI",-"AND" 108 a += x<<9 ^ x>>7 109 110 return a 111 } 112 113 func rot8(x uint8) uint8 { 114 var a uint8 115 116 // amd64:"ROLB\t[$]5" 117 // riscv64: "OR","SLLI","SRLI",-"AND" 118 a += x<<5 | x>>3 119 120 // amd64:`ROLB\t[$]6` 121 // riscv64: "OR","SLLI","SRLI",-"AND" 122 a += x<<6 + x>>2 123 124 // amd64:"ROLB\t[$]7" 125 // riscv64: "OR","SLLI","SRLI",-"AND" 126 a += x<<7 ^ x>>1 127 128 return a 129 } 130 131 // ----------------------- // 132 // non-const rotates // 133 // ----------------------- // 134 135 func rot64nc(x uint64, z uint) uint64 { 136 var a uint64 137 138 z &= 63 139 140 // amd64:"ROLQ",-"AND" 141 // arm64:"ROR","NEG",-"AND" 142 // ppc64x:"ROTL",-"NEG",-"AND" 143 // loong64: "ROTRV", -"AND" 144 // riscv64: "ROL",-"AND" 145 a += x<<z | x>>(64-z) 146 147 // amd64:"RORQ",-"AND" 148 // arm64:"ROR",-"NEG",-"AND" 149 // ppc64x:"ROTL","NEG",-"AND" 150 // loong64: "ROTRV", -"AND" 151 // riscv64: "ROR",-"AND" 152 a += x>>z | x<<(64-z) 153 154 return a 155 } 156 157 func rot32nc(x uint32, z uint) uint32 { 158 var a uint32 159 160 z &= 31 161 162 // amd64:"ROLL",-"AND" 163 // arm64:"ROR","NEG",-"AND" 164 // ppc64x:"ROTLW",-"NEG",-"AND" 165 // loong64: "ROTR", -"AND" 166 // riscv64: "ROLW",-"AND" 167 a += x<<z | x>>(32-z) 168 169 // amd64:"RORL",-"AND" 170 // arm64:"ROR",-"NEG",-"AND" 171 // ppc64x:"ROTLW","NEG",-"AND" 172 // loong64: "ROTR", -"AND" 173 // riscv64: "RORW",-"AND" 174 a += x>>z | x<<(32-z) 175 176 return a 177 } 178 179 func rot16nc(x uint16, z uint) uint16 { 180 var a uint16 181 182 z &= 15 183 184 // amd64:"ROLW",-"ANDQ" 185 // riscv64: "OR","SLL","SRL",-"AND\t" 186 a += x<<z | x>>(16-z) 187 188 // amd64:"RORW",-"ANDQ" 189 // riscv64: "OR","SLL","SRL",-"AND\t" 190 a += x>>z | x<<(16-z) 191 192 return a 193 } 194 195 func rot8nc(x uint8, z uint) uint8 { 196 var a uint8 197 198 z &= 7 199 200 // amd64:"ROLB",-"ANDQ" 201 // riscv64: "OR","SLL","SRL",-"AND\t" 202 a += x<<z | x>>(8-z) 203 204 // amd64:"RORB",-"ANDQ" 205 // riscv64: "OR","SLL","SRL",-"AND\t" 206 a += x>>z | x<<(8-z) 207 208 return a 209 } 210 211 // Issue 18254: rotate after inlining 212 func f32(x uint32) uint32 { 213 // amd64:"ROLL\t[$]7" 214 return rot32nc(x, 7) 215 } 216 217 func doubleRotate(x uint64) uint64 { 218 x = (x << 5) | (x >> 59) 219 // amd64:"ROLQ\t[$]15" 220 // arm64:"ROR\t[$]49" 221 x = (x << 10) | (x >> 54) 222 return x 223 } 224 225 // --------------------------------------- // 226 // Combined Rotate + Masking operations // 227 // --------------------------------------- // 228 229 func checkMaskedRotate32(a []uint32, r int) { 230 i := 0 231 232 // ppc64x: "RLWNM\t[$]16, R[0-9]+, [$]8, [$]15, R[0-9]+" 233 a[i] = bits.RotateLeft32(a[i], 16) & 0xFF0000 234 i++ 235 // ppc64x: "RLWNM\t[$]16, R[0-9]+, [$]8, [$]15, R[0-9]+" 236 a[i] = bits.RotateLeft32(a[i]&0xFF, 16) 237 i++ 238 // ppc64x: "RLWNM\t[$]4, R[0-9]+, [$]20, [$]27, R[0-9]+" 239 a[i] = bits.RotateLeft32(a[i], 4) & 0xFF0 240 i++ 241 // ppc64x: "RLWNM\t[$]16, R[0-9]+, [$]24, [$]31, R[0-9]+" 242 a[i] = bits.RotateLeft32(a[i]&0xFF0000, 16) 243 i++ 244 245 // ppc64x: "RLWNM\tR[0-9]+, R[0-9]+, [$]8, [$]15, R[0-9]+" 246 a[i] = bits.RotateLeft32(a[i], r) & 0xFF0000 247 i++ 248 // ppc64x: "RLWNM\tR[0-9]+, R[0-9]+, [$]16, [$]23, R[0-9]+" 249 a[i] = bits.RotateLeft32(a[i], r) & 0xFF00 250 i++ 251 252 // ppc64x: "RLWNM\tR[0-9]+, R[0-9]+, [$]20, [$]11, R[0-9]+" 253 a[i] = bits.RotateLeft32(a[i], r) & 0xFFF00FFF 254 i++ 255 // ppc64x: "RLWNM\t[$]4, R[0-9]+, [$]20, [$]11, R[0-9]+" 256 a[i] = bits.RotateLeft32(a[i], 4) & 0xFFF00FFF 257 i++ 258 } 259 260 // combined arithmetic and rotate on arm64 261 func checkArithmeticWithRotate(a *[1000]uint64) { 262 // arm64: "AND\tR[0-9]+@>51, R[0-9]+, R[0-9]+" 263 a[2] = a[1] & bits.RotateLeft64(a[0], 13) 264 // arm64: "ORR\tR[0-9]+@>51, R[0-9]+, R[0-9]+" 265 a[5] = a[4] | bits.RotateLeft64(a[3], 13) 266 // arm64: "EOR\tR[0-9]+@>51, R[0-9]+, R[0-9]+" 267 a[8] = a[7] ^ bits.RotateLeft64(a[6], 13) 268 // arm64: "MVN\tR[0-9]+@>51, R[0-9]+" 269 a[10] = ^bits.RotateLeft64(a[9], 13) 270 // arm64: "BIC\tR[0-9]+@>51, R[0-9]+, R[0-9]+" 271 a[13] = a[12] &^ bits.RotateLeft64(a[11], 13) 272 // arm64: "EON\tR[0-9]+@>51, R[0-9]+, R[0-9]+" 273 a[16] = a[15] ^ ^bits.RotateLeft64(a[14], 13) 274 // arm64: "ORN\tR[0-9]+@>51, R[0-9]+, R[0-9]+" 275 a[19] = a[18] | ^bits.RotateLeft64(a[17], 13) 276 // arm64: "TST\tR[0-9]+@>51, R[0-9]+" 277 if a[18]&bits.RotateLeft64(a[19], 13) == 0 { 278 a[20] = 1 279 } 280 281 } 282