Source file test/codegen/divmod.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 // Div and mod rewrites, testing cmd/compile/internal/ssa/_gen/divmod.rules. 10 // See comments there for "Case 1" etc. 11 12 // Convert multiplication by a power of two to a shift. 13 14 func mul32_uint8(i uint8) uint8 { 15 // 386: "SHLL [$]5," 16 // arm64: "LSL [$]5," 17 return i * 32 18 } 19 20 func mul32_uint16(i uint16) uint16 { 21 // 386: "SHLL [$]5," 22 // arm64: "LSL [$]5," 23 return i * 32 24 } 25 26 func mul32_uint32(i uint32) uint32 { 27 // 386: "SHLL [$]5," 28 // arm64: "LSL [$]5," 29 return i * 32 30 } 31 32 func mul32_uint64(i uint64) uint64 { 33 // 386: "SHLL [$]5," 34 // 386: "SHRL [$]27," 35 // arm64: "LSL [$]5," 36 return i * 32 37 } 38 39 func mulNeg32_int8(i int8) int8 { 40 // 386: "SHLL [$]5," 41 // 386: "NEGL" 42 // arm64: "NEG R[0-9]+<<5," 43 return i * -32 44 } 45 46 func mulNeg32_int16(i int16) int16 { 47 // 386: "SHLL [$]5," 48 // 386: "NEGL" 49 // arm64: "NEG R[0-9]+<<5," 50 return i * -32 51 } 52 53 func mulNeg32_int32(i int32) int32 { 54 // 386: "SHLL [$]5," 55 // 386: "NEGL" 56 // arm64: "NEG R[0-9]+<<5," 57 return i * -32 58 } 59 60 func mulNeg32_int64(i int64) int64 { 61 // 386: "SHLL [$]5," 62 // 386: "SHRL [$]27," 63 // 386: "SBBL" 64 // arm64: "NEG R[0-9]+<<5," 65 return i * -32 66 } 67 68 // Signed divide by power of 2. 69 70 func div32_int8(i int8) int8 { 71 // 386: "SARB [$]7," 72 // 386: "SHRB [$]3," 73 // 386: "ADDL" 74 // 386: "SARB [$]5," 75 // arm64: "SBFX [$]7, R[0-9]+, [$]1," 76 // arm64: "ADD R[0-9]+>>3," 77 // arm64: "SBFX [$]5, R[0-9]+, [$]3," 78 return i / 32 79 } 80 81 func div32_int16(i int16) int16 { 82 // 386: "SARW [$]15," 83 // 386: "SHRW [$]11," 84 // 386: "ADDL" 85 // 386: "SARW [$]5," 86 // arm64: "SBFX [$]15, R[0-9]+, [$]1," 87 // arm64: "ADD R[0-9]+>>11," 88 // arm64: "SBFX [$]5, R[0-9]+, [$]11," 89 return i / 32 90 } 91 92 func div32_int32(i int32) int32 { 93 // 386: "SARL [$]31," 94 // 386: "SHRL [$]27," 95 // 386: "ADDL" 96 // 386: "SARL [$]5," 97 // arm64: "SBFX [$]31, R[0-9]+, [$]1," 98 // arm64: "ADD R[0-9]+>>27," 99 // arm64: "SBFX [$]5, R[0-9]+, [$]27," 100 return i / 32 101 } 102 103 func div32_int64(i int64) int64 { 104 // 386: "SARL [$]31," 105 // 386: "SHRL [$]27," 106 // 386: "ADDL" 107 // 386: "SARL [$]5," 108 // 386: "SHRL [$]5," 109 // 386: "SHLL [$]27," 110 // arm64: "ASR [$]63," 111 // arm64: "ADD R[0-9]+>>59," 112 // arm64: "ASR [$]5," 113 return i / 32 114 } 115 116 // Case 1. Signed divides where 2N ≤ register size. 117 118 func div7_int8(i int8) int8 { 119 // 386: "SARL [$]31," 120 // 386: "IMUL3L [$]147," 121 // 386: "SARL [$]10," 122 // 386: "SUBL" 123 // arm64: "MOVD [$]147," 124 // arm64: "MULW" 125 // arm64: "SBFX [$]10, R[0-9]+, [$]22," 126 // arm64: "SUB R[0-9]+->31," 127 // wasm: "I64Const [$]147" 128 return i / 7 129 } 130 131 func div7_int16(i int16) int16 { 132 // 386: "SARL [$]31," 133 // 386: "IMUL3L [$]37450," 134 // 386: "SARL [$]18," 135 // 386: "SUBL" 136 // arm64: "MOVD [$]37450," 137 // arm64: "MULW" 138 // arm64: "SBFX [$]18, R[0-9]+, [$]14," 139 // arm64: "SUB R[0-9]+->31," 140 // wasm: "I64Const [$]37450" 141 return i / 7 142 } 143 144 func div7_int32(i int32) int32 { 145 // 64-bit only 146 // arm64: "MOVD [$]2454267027," 147 // arm64: "MUL " 148 // arm64: "ASR [$]34," 149 // arm64: "SUB R[0-9]+->63," 150 // wasm: "I64Const [$]2454267027" 151 return i / 7 152 } 153 154 // Case 2. Signed divides where m is even. 155 156 func div9_int32(i int32) int32 { 157 // 386: "SARL [$]31," 158 // 386: "MOVL [$]1908874354," 159 // 386: "IMULL" 160 // 386: "SARL [$]2," 161 // 386: "SUBL" 162 // arm64: "MOVD [$]3817748708," 163 // arm64: "MUL " 164 // arm64: "ASR [$]35," 165 // arm64: "SUB R[0-9]+->63," 166 // wasm: "I64Const [$]3817748708" 167 return i / 9 168 } 169 170 func div7_int64(i int64) int64 { 171 // 64-bit only 172 // arm64 MOVD $5270498306774157605, SMULH, ASR $1, SUB ->63 173 // arm64: "MOVD [$]5270498306774157605," 174 // arm64: "SMULH" 175 // arm64: "ASR [$]1," 176 // arm64: "SUB R[0-9]+->63," 177 // wasm: "I64Const [$]613566757" 178 // wasm: "I64Const [$]1227133513" 179 return i / 7 180 } 181 182 // Case 3. Signed divides where m is odd. 183 184 func div3_int32(i int32) int32 { 185 // 386: "SARL [$]31," 186 // 386: "MOVL [$]-1431655765," 187 // 386: "IMULL" 188 // 386: "SARL [$]1," 189 // 386: "SUBL" 190 // arm64: "MOVD [$]2863311531," 191 // arm64: "MUL" 192 // arm64: "ASR [$]33," 193 // arm64: "SUB R[0-9]+->63," 194 // wasm: "I64Const [$]2863311531" 195 return i / 3 196 } 197 198 func div3_int64(i int64) int64 { 199 // 64-bit only 200 // arm64: "MOVD [$]-6148914691236517205," 201 // arm64: "SMULH" 202 // arm64: "ADD" 203 // arm64: "ASR [$]1," 204 // arm64: "SUB R[0-9]+->63," 205 // wasm: "I64Const [$]-1431655766" 206 // wasm: "I64Const [$]2863311531" 207 return i / 3 208 } 209 210 // Case 4. Unsigned divide where x < 1<<(N-1). 211 212 func div7_int16u(i int16) int16 { 213 if i < 0 { 214 return 0 215 } 216 // 386: "IMUL3L [$]37450," 217 // 386: "SHRL [$]18," 218 // 386: -"SUBL" 219 // arm64: "MOVD [$]37450," 220 // arm64: "MULW" 221 // arm64: "UBFX [$]18, R[0-9]+, [$]14," 222 // arm64: -"SUB" 223 // wasm: "I64Const [$]37450" 224 // wasm -"I64Sub" 225 return i / 7 226 } 227 228 func div7_int32u(i int32) int32 { 229 if i < 0 { 230 return 0 231 } 232 // 386: "MOVL [$]-1840700269," 233 // 386: "MULL" 234 // 386: "SHRL [$]2" 235 // 386: -"SUBL" 236 // arm64: "MOVD [$]2454267027," 237 // arm64: "MUL" 238 // arm64: "LSR [$]34," 239 // arm64: -"SUB" 240 // wasm: "I64Const [$]2454267027" 241 // wasm -"I64Sub" 242 return i / 7 243 } 244 245 func div7_int64u(i int64) int64 { 246 // 64-bit only 247 if i < 0 { 248 return 0 249 } 250 // arm64: "MOVD [$]-7905747460161236406," 251 // arm64: "UMULH" 252 // arm64: "LSR [$]2," 253 // arm64: -"SUB" 254 // wasm: "I64Const [$]1227133514" 255 // wasm: "I64Const [$]2454267026" 256 // wasm -"I64Sub" 257 return i / 7 258 } 259 260 // Case 5. Unsigned divide where 2N+1 ≤ register size. 261 262 func div7_uint8(i uint8) uint8 { 263 // 386: "IMUL3L [$]293," 264 // 386: "SHRL [$]11," 265 // arm64: "MOVD [$]293," 266 // arm64: "MULW" 267 // arm64: "UBFX [$]11, R[0-9]+, [$]21," 268 // wasm: "I64Const [$]293" 269 return i / 7 270 } 271 272 func div7_uint16(i uint16) uint16 { 273 // only 64-bit 274 // arm64: "MOVD [$]74899," 275 // arm64: "MUL" 276 // arm64: "LSR [$]19," 277 // wasm: "I64Const [$]74899" 278 return i / 7 279 } 280 281 // Case 6. Unsigned divide where m is even. 282 283 func div3_uint16(i uint16) uint16 { 284 // 386: "IMUL3L [$]43691," "SHRL [$]17," 285 // arm64: "MOVD [$]87382," 286 // arm64: "MUL" 287 // arm64: "LSR [$]18," 288 // wasm: "I64Const [$]87382" 289 return i / 3 290 } 291 292 func div3_uint32(i uint32) uint32 { 293 // 386: "MOVL [$]-1431655765," "MULL", "SHRL [$]1," 294 // arm64: "MOVD [$]2863311531," 295 // arm64: "MUL" 296 // arm64: "LSR [$]33," 297 // wasm: "I64Const [$]2863311531" 298 return i / 3 299 } 300 301 func div3_uint64(i uint64) uint64 { 302 // 386: "MOVL [$]-1431655766" 303 // 386: "MULL" 304 // 386: "SHRL [$]1" 305 // 386 -".*CALL" 306 // arm64: "MOVD [$]-6148914691236517205," 307 // arm64: "UMULH" 308 // arm64: "LSR [$]1," 309 // wasm: "I64Const [$]2863311530" 310 // wasm: "I64Const [$]2863311531" 311 return i / 3 312 } 313 314 // Case 7. Unsigned divide where c is even. 315 316 func div14_uint16(i uint16) uint16 { 317 // 32-bit only 318 // 386: "SHRL [$]1," 319 // 386: "IMUL3L [$]37450," 320 // 386: "SHRL [$]18," 321 return i / 14 322 } 323 324 func div14_uint32(i uint32) uint32 { 325 // 386: "SHRL [$]1," 326 // 386: "MOVL [$]-1840700269," 327 // 386: "SHRL [$]2," 328 // arm64: "UBFX [$]1, R[0-9]+, [$]31," 329 // arm64: "MOVD [$]2454267027," 330 // arm64: "MUL" 331 // arm64: "LSR [$]34," 332 // wasm: "I64Const [$]2454267027" 333 return i / 14 334 } 335 336 func div14_uint64(i uint64) uint64 { 337 // 386: "MOVL [$]-1840700270," 338 // 386: "MULL" 339 // 386: "SHRL [$]2," 340 // 386: -".*CALL" 341 // arm64: "MOVD [$]-7905747460161236406," 342 // arm64: "UMULH" 343 // arm64: "LSR [$]2," 344 // wasm: "I64Const [$]1227133514" 345 // wasm: "I64Const [$]2454267026" 346 return i / 14 347 } 348 349 // Case 8. Unsigned divide on systems with avg. 350 351 func div7_uint16a(i uint16) uint16 { 352 // only 32-bit 353 // 386: "SHLL [$]16," 354 // 386: "IMUL3L [$]9363," 355 // 386: "ADDL" 356 // 386: "RCRL [$]1," 357 // 386: "SHRL [$]18," 358 return i / 7 359 } 360 361 func div7_uint32(i uint32) uint32 { 362 // 386: "MOVL [$]613566757," 363 // 386: "MULL" 364 // 386: "ADDL" 365 // 386: "RCRL [$]1," 366 // 386: "SHRL [$]2," 367 // arm64: "UBFIZ [$]32, R[0-9]+, [$]32," 368 // arm64: "MOVD [$]613566757," 369 // arm64: "MUL" 370 // arm64: "SUB" 371 // arm64: "ADD R[0-9]+>>1," 372 // arm64: "LSR [$]34," 373 // wasm: "I64Const [$]613566757" 374 return i / 7 375 } 376 377 func div7_uint64(i uint64) uint64 { 378 // 386: "MOVL [$]-1840700269," 379 // 386: "MULL" 380 // 386: "SHRL [$]2," 381 // 386: -".*CALL" 382 // arm64: "MOVD [$]2635249153387078803," 383 // arm64: "UMULH" 384 // arm64: "SUB", 385 // arm64: "ADD R[0-9]+>>1," 386 // arm64: "LSR [$]2," 387 // wasm: "I64Const [$]613566756" 388 // wasm: "I64Const [$]2454267027" 389 return i / 7 390 } 391 392 func div12345_uint64(i uint64) uint64 { 393 // 386: "MOVL [$]-1444876402," 394 // 386: "MOVL [$]835683390," 395 // 386: "MULL" 396 // 386: "SHRL [$]13," 397 // 386: "SHLL [$]19," 398 // arm64: "MOVD [$]-6205696892516465602," 399 // arm64: "UMULH" 400 // arm64: "LSR [$]13," 401 // wasm: "I64Const [$]835683390" 402 // wasm: "I64Const [$]2850090894" 403 return i / 12345 404 } 405 406 // Divisibility and non-divisibility by power of two. 407 408 func divis32_uint8(i uint8) bool { 409 // 386: "TESTB [$]31," 410 // arm64: "TSTW [$]31," 411 return i%32 == 0 412 } 413 414 func ndivis32_uint8(i uint8) bool { 415 // 386: "TESTB [$]31," 416 // arm64: "TSTW [$]31," 417 return i%32 != 0 418 } 419 420 func divis32_uint16(i uint16) bool { 421 // 386: "TESTW [$]31," 422 // arm64: "TSTW [$]31," 423 return i%32 == 0 424 } 425 426 func ndivis32_uint16(i uint16) bool { 427 // 386: "TESTW [$]31," 428 // arm64: "TSTW [$]31," 429 return i%32 != 0 430 } 431 432 func divis32_uint32(i uint32) bool { 433 // 386: "TESTL [$]31," 434 // arm64: "TSTW [$]31," 435 return i%32 == 0 436 } 437 438 func ndivis32_uint32(i uint32) bool { 439 // 386: "TESTL [$]31," 440 // arm64: "TSTW [$]31," 441 return i%32 != 0 442 } 443 444 func divis32_uint64(i uint64) bool { 445 // 386: "TESTL [$]31," 446 // arm64: "TST [$]31," 447 return i%32 == 0 448 } 449 450 func ndivis32_uint64(i uint64) bool { 451 // 386: "TESTL [$]31," 452 // arm64: "TST [$]31," 453 return i%32 != 0 454 } 455 456 func divis32_int8(i int8) bool { 457 // 386: "TESTB [$]31," 458 // arm64: "TSTW [$]31," 459 return i%32 == 0 460 } 461 462 func ndivis32_int8(i int8) bool { 463 // 386: "TESTB [$]31," 464 // arm64: "TSTW [$]31," 465 return i%32 != 0 466 } 467 468 func divis32_int16(i int16) bool { 469 // 386: "TESTW [$]31," 470 // arm64: "TSTW [$]31," 471 return i%32 == 0 472 } 473 474 func ndivis32_int16(i int16) bool { 475 // 386: "TESTW [$]31," 476 // arm64: "TSTW [$]31," 477 return i%32 != 0 478 } 479 480 func divis32_int32(i int32) bool { 481 // 386: "TESTL [$]31," 482 // arm64: "TSTW [$]31," 483 return i%32 == 0 484 } 485 486 func ndivis32_int32(i int32) bool { 487 // 386: "TESTL [$]31," 488 // arm64: "TSTW [$]31," 489 return i%32 != 0 490 } 491 492 func divis32_int64(i int64) bool { 493 // 386: "TESTL [$]31," 494 // arm64: "TST [$]31," 495 return i%32 == 0 496 } 497 498 func ndivis32_int64(i int64) bool { 499 // 386: "TESTL [$]31," 500 // arm64: "TST [$]31," 501 return i%32 != 0 502 } 503 504 // Divide with divisibility check; reuse divide intermediate mod. 505 506 func div_divis32_uint8(i uint8) (uint8, bool) { 507 // 386: "SHRB [$]5," 508 // 386: "TESTB [$]31,", 509 // 386: "SETEQ" 510 // arm64: "UBFX [$]5, R[0-9]+, [$]3" 511 // arm64: "TSTW [$]31," 512 // arm64: "CSET EQ" 513 return i / 32, i%32 == 0 514 } 515 516 func div_ndivis32_uint8(i uint8) (uint8, bool) { 517 // 386: "SHRB [$]5," 518 // 386: "TESTB [$]31,", 519 // 386: "SETNE" 520 // arm64: "UBFX [$]5, R[0-9]+, [$]3" 521 // arm64: "TSTW [$]31," 522 // arm64: "CSET NE" 523 return i / 32, i%32 != 0 524 } 525 526 func div_divis32_uint16(i uint16) (uint16, bool) { 527 // 386: "SHRW [$]5," 528 // 386: "TESTW [$]31,", 529 // 386: "SETEQ" 530 // arm64: "UBFX [$]5, R[0-9]+, [$]11" 531 // arm64: "TSTW [$]31," 532 // arm64: "CSET EQ" 533 return i / 32, i%32 == 0 534 } 535 536 func div_ndivis32_uint16(i uint16) (uint16, bool) { 537 // 386: "SHRW [$]5," 538 // 386: "TESTW [$]31,", 539 // 386: "SETNE" 540 // arm64: "UBFX [$]5, R[0-9]+, [$]11," 541 // arm64: "TSTW [$]31," 542 // arm64: "CSET NE" 543 return i / 32, i%32 != 0 544 } 545 546 func div_divis32_uint32(i uint32) (uint32, bool) { 547 // 386: "SHRL [$]5," 548 // 386: "TESTL [$]31,", 549 // 386: "SETEQ" 550 // arm64: "UBFX [$]5, R[0-9]+, [$]27," 551 // arm64: "TSTW [$]31," 552 // arm64: "CSET EQ" 553 return i / 32, i%32 == 0 554 } 555 556 func div_ndivis32_uint32(i uint32) (uint32, bool) { 557 // 386: "SHRL [$]5," 558 // 386: "TESTL [$]31,", 559 // 386: "SETNE" 560 // arm64: "UBFX [$]5, R[0-9]+, [$]27," 561 // arm64: "TSTW [$]31," 562 // arm64: "CSET NE" 563 return i / 32, i%32 != 0 564 } 565 566 func div_divis32_uint64(i uint64) (uint64, bool) { 567 // 386: "SHRL [$]5," 568 // 386: "SHLL [$]27," 569 // 386: "TESTL [$]31,", 570 // 386: "SETEQ" 571 // arm64: "LSR [$]5," 572 // arm64: "TST [$]31," 573 // arm64: "CSET EQ" 574 return i / 32, i%32 == 0 575 } 576 577 func div_ndivis32_uint64(i uint64) (uint64, bool) { 578 // 386: "SHRL [$]5," 579 // 386: "SHLL [$]27," 580 // 386: "TESTL [$]31,", 581 // 386: "SETNE" 582 // arm64: "LSR [$]5," 583 // arm64: "TST [$]31," 584 // arm64: "CSET NE" 585 return i / 32, i%32 != 0 586 } 587 588 func div_divis32_int8(i int8) (int8, bool) { 589 // 386: "SARB [$]7," 590 // 386: "SHRB [$]3," 591 // 386: "SARB [$]5," 592 // 386: "TESTB [$]31,", 593 // 386: "SETEQ" 594 // arm64: "SBFX [$]7, R[0-9]+, [$]1," 595 // arm64: "ADD R[0-9]+>>3," 596 // arm64: "SBFX [$]5, R[0-9]+, [$]3," 597 // arm64: "TSTW [$]31," 598 // arm64: "CSET EQ" 599 return i / 32, i%32 == 0 600 } 601 602 func div_ndivis32_int8(i int8) (int8, bool) { 603 // 386: "SARB [$]7," 604 // 386: "SHRB [$]3," 605 // 386: "SARB [$]5," 606 // 386: "TESTB [$]31,", 607 // 386: "SETNE" 608 // arm64: "SBFX [$]7, R[0-9]+, [$]1," 609 // arm64: "ADD R[0-9]+>>3," 610 // arm64: "SBFX [$]5, R[0-9]+, [$]3," 611 // arm64: "TSTW [$]31," 612 // arm64: "CSET NE" 613 return i / 32, i%32 != 0 614 } 615 616 func div_divis32_int16(i int16) (int16, bool) { 617 // 386: "SARW [$]15," 618 // 386: "SHRW [$]11," 619 // 386: "SARW [$]5," 620 // 386: "TESTW [$]31,", 621 // 386: "SETEQ" 622 // arm64: "SBFX [$]15, R[0-9]+, [$]1," 623 // arm64: "ADD R[0-9]+>>11," 624 // arm64: "SBFX [$]5, R[0-9]+, [$]11," 625 // arm64: "TSTW [$]31," 626 // arm64: "CSET EQ" 627 return i / 32, i%32 == 0 628 } 629 630 func div_ndivis32_int16(i int16) (int16, bool) { 631 // 386: "SARW [$]15," 632 // 386: "SHRW [$]11," 633 // 386: "SARW [$]5," 634 // 386: "TESTW [$]31,", 635 // 386: "SETNE" 636 // arm64: "SBFX [$]15, R[0-9]+, [$]1," 637 // arm64: "ADD R[0-9]+>>11," 638 // arm64: "SBFX [$]5, R[0-9]+, [$]11," 639 // arm64: "TSTW [$]31," 640 // arm64: "CSET NE" 641 return i / 32, i%32 != 0 642 } 643 644 func div_divis32_int32(i int32) (int32, bool) { 645 // 386: "SARL [$]31," 646 // 386: "SHRL [$]27," 647 // 386: "SARL [$]5," 648 // 386: "TESTL [$]31,", 649 // 386: "SETEQ" 650 // arm64: "SBFX [$]31, R[0-9]+, [$]1," 651 // arm64: "ADD R[0-9]+>>27," 652 // arm64: "SBFX [$]5, R[0-9]+, [$]27," 653 // arm64: "TSTW [$]31," 654 // arm64: "CSET EQ" 655 return i / 32, i%32 == 0 656 } 657 658 func div_ndivis32_int32(i int32) (int32, bool) { 659 // 386: "SARL [$]31," 660 // 386: "SHRL [$]27," 661 // 386: "SARL [$]5," 662 // 386: "TESTL [$]31,", 663 // 386: "SETNE" 664 // arm64: "SBFX [$]31, R[0-9]+, [$]1," 665 // arm64: "ADD R[0-9]+>>27," 666 // arm64: "SBFX [$]5, R[0-9]+, [$]27," 667 // arm64: "TSTW [$]31," 668 // arm64: "CSET NE" 669 return i / 32, i%32 != 0 670 } 671 672 func div_divis32_int64(i int64) (int64, bool) { 673 // 386: "SARL [$]31," 674 // 386: "SHRL [$]27," 675 // 386: "SARL [$]5," 676 // 386: "SHLL [$]27," 677 // 386: "TESTL [$]31,", 678 // 386: "SETEQ" 679 // arm64: "ASR [$]63," 680 // arm64: "ADD R[0-9]+>>59," 681 // arm64: "ASR [$]5," 682 // arm64: "TST [$]31," 683 // arm64: "CSET EQ" 684 return i / 32, i%32 == 0 685 } 686 687 func div_ndivis32_int64(i int64) (int64, bool) { 688 // 386: "SARL [$]31," 689 // 386: "SHRL [$]27," 690 // 386: "SARL [$]5," 691 // 386: "SHLL [$]27," 692 // 386: "TESTL [$]31,", 693 // 386: "SETNE" 694 // arm64: "ASR [$]63," 695 // arm64: "ADD R[0-9]+>>59," 696 // arm64: "ASR [$]5," 697 // arm64: "TST [$]31," 698 // arm64: "CSET NE" 699 return i / 32, i%32 != 0 700 } 701 702 // Divisibility and non-divisibility by non-power-of-two. 703 704 func divis6_uint8(i uint8) bool { 705 // 386: "IMUL3L [$]-85," 706 // 386: "ROLB [$]7," 707 // 386: "CMPB .*, [$]42" 708 // 386: "SETLS" 709 // arm64: "MOVD [$]-85," 710 // arm64: "MULW" 711 // arm64: "UBFX [$]1, R[0-9]+, [$]7," 712 // arm64: "ORR R[0-9]+<<7" 713 // arm64: "CMPW [$]42," 714 // arm64: "CSET LS" 715 return i%6 == 0 716 } 717 718 func ndivis6_uint8(i uint8) bool { 719 // 386: "IMUL3L [$]-85," 720 // 386: "ROLB [$]7," 721 // 386: "CMPB .*, [$]42" 722 // 386: "SETHI" 723 // arm64: "MOVD [$]-85," 724 // arm64: "MULW" 725 // arm64: "UBFX [$]1, R[0-9]+, [$]7," 726 // arm64: "ORR R[0-9]+<<7" 727 // arm64: "CMPW [$]42," 728 // arm64: "CSET HI" 729 return i%6 != 0 730 } 731 732 func divis6_uint16(i uint16) bool { 733 // 386: "IMUL3L [$]-21845," 734 // 386: "ROLW [$]15," 735 // 386: "CMPW .*, [$]10922" 736 // 386: "SETLS" 737 // arm64: "MOVD [$]-21845," 738 // arm64: "MULW" 739 // arm64: "ORR R[0-9]+<<16" 740 // arm64: "RORW [$]17," 741 // arm64: "MOVD [$]10922," 742 // arm64: "CSET LS" 743 return i%6 == 0 744 } 745 746 func ndivis6_uint16(i uint16) bool { 747 // 386: "IMUL3L [$]-21845," 748 // 386: "ROLW [$]15," 749 // 386: "CMPW .*, [$]10922" 750 // 386: "SETHI" 751 // arm64: "MOVD [$]-21845," 752 // arm64: "MULW" 753 // arm64: "ORR R[0-9]+<<16" 754 // arm64: "RORW [$]17," 755 // arm64: "MOVD [$]10922," 756 // arm64: "CSET HI" 757 return i%6 != 0 758 } 759 760 func divis6_uint32(i uint32) bool { 761 // 386: "IMUL3L [$]-1431655765," 762 // 386: "ROLL [$]31," 763 // 386: "CMPL .*, [$]715827882" 764 // 386: "SETLS" 765 // arm64: "MOVD [$]-1431655765," 766 // arm64: "MULW" 767 // arm64: "RORW [$]1," 768 // arm64: "MOVD [$]715827882," 769 // arm64: "CSET LS" 770 return i%6 == 0 771 } 772 773 func ndivis6_uint32(i uint32) bool { 774 // 386: "IMUL3L [$]-1431655765," 775 // 386: "ROLL [$]31," 776 // 386: "CMPL .*, [$]715827882" 777 // 386: "SETHI" 778 // arm64: "MOVD [$]-1431655765," 779 // arm64: "MULW" 780 // arm64: "RORW [$]1," 781 // arm64: "MOVD [$]715827882," 782 // arm64: "CSET HI" 783 return i%6 != 0 784 } 785 786 func divis6_uint64(i uint64) bool { 787 // 386: "IMUL3L [$]-1431655766," 788 // 386: "IMUL3L [$]-1431655765," 789 // 386: "MULL" 790 // 386: "SHRL [$]1," 791 // 386: "SHLL [$]31," 792 // 386: "CMPL .*, [$]715827882" 793 // 386: "SETLS" 794 // arm64: "MOVD [$]-6148914691236517205," 795 // arm64: "MUL " 796 // arm64: "ROR [$]1," 797 // arm64: "MOVD [$]3074457345618258602," 798 // arm64: "CSET LS" 799 return i%6 == 0 800 } 801 802 func ndivis6_uint64(i uint64) bool { 803 // 386: "IMUL3L [$]-1431655766," 804 // 386: "IMUL3L [$]-1431655765," 805 // 386: "MULL" 806 // 386: "SHRL [$]1," 807 // 386: "SHLL [$]31," 808 // 386: "CMPL .*, [$]715827882" 809 // 386: "SETHI" 810 // arm64: "MOVD [$]-6148914691236517205," 811 // arm64: "MUL " 812 // arm64: "ROR [$]1," 813 // arm64: "MOVD [$]3074457345618258602," 814 // arm64: "CSET HI" 815 return i%6 != 0 816 } 817 818 func divis6_int8(i int8) bool { 819 // 386: "IMUL3L [$]-85," 820 // 386: "ADDL [$]42," 821 // 386: "ROLB [$]7," 822 // 386: "CMPB .*, [$]42" 823 // 386: "SETLS" 824 // arm64: "MOVD [$]-85," 825 // arm64: "MULW" 826 // arm64: "ADD [$]42," 827 // arm64: "UBFX [$]1, R[0-9]+, [$]7," 828 // arm64: "ORR R[0-9]+<<7" 829 // arm64: "CMPW [$]42," 830 // arm64: "CSET LS" 831 return i%6 == 0 832 } 833 834 func ndivis6_int8(i int8) bool { 835 // 386: "IMUL3L [$]-85," 836 // 386: "ADDL [$]42," 837 // 386: "ROLB [$]7," 838 // 386: "CMPB .*, [$]42" 839 // 386: "SETHI" 840 // arm64: "MOVD [$]-85," 841 // arm64: "MULW" 842 // arm64: "ADD [$]42," 843 // arm64: "UBFX [$]1, R[0-9]+, [$]7," 844 // arm64: "ORR R[0-9]+<<7" 845 // arm64: "CMPW [$]42," 846 // arm64: "CSET HI" 847 return i%6 != 0 848 } 849 850 func divis6_int16(i int16) bool { 851 // 386: "IMUL3L [$]-21845," 852 // 386: "ADDL [$]10922," 853 // 386: "ROLW [$]15," 854 // 386: "CMPW .*, [$]10922" 855 // 386: "SETLS" 856 // arm64: "MOVD [$]-21845," 857 // arm64: "MULW" 858 // arm64: "MOVD [$]10922," 859 // arm64: "ADD " 860 // arm64: "ORR R[0-9]+<<16" 861 // arm64: "RORW [$]17," 862 // arm64: "MOVD [$]10922," 863 // arm64: "CSET LS" 864 return i%6 == 0 865 } 866 867 func ndivis6_int16(i int16) bool { 868 // 386: "IMUL3L [$]-21845," 869 // 386: "ADDL [$]10922," 870 // 386: "ROLW [$]15," 871 // 386: "CMPW .*, [$]10922" 872 // 386: "SETHI" 873 // arm64: "MOVD [$]-21845," 874 // arm64: "MULW" 875 // arm64: "MOVD [$]10922," 876 // arm64: "ADD " 877 // arm64: "ORR R[0-9]+<<16" 878 // arm64: "RORW [$]17," 879 // arm64: "MOVD [$]10922," 880 // arm64: "CSET HI" 881 return i%6 != 0 882 } 883 884 func divis6_int32(i int32) bool { 885 // 386: "IMUL3L [$]-1431655765," 886 // 386: "ADDL [$]715827882," 887 // 386: "ROLL [$]31," 888 // 386: "CMPL .*, [$]715827882" 889 // 386: "SETLS" 890 // arm64: "MOVD [$]-1431655765," 891 // arm64: "MULW" 892 // arm64: "MOVD [$]715827882," 893 // arm64: "ADD " 894 // arm64: "RORW [$]1," 895 // arm64: "CSET LS" 896 return i%6 == 0 897 } 898 899 func ndivis6_int32(i int32) bool { 900 // 386: "IMUL3L [$]-1431655765," 901 // 386: "ADDL [$]715827882," 902 // 386: "ROLL [$]31," 903 // 386: "CMPL .*, [$]715827882" 904 // 386: "SETHI" 905 // arm64: "MOVD [$]-1431655765," 906 // arm64: "MULW" 907 // arm64: "MOVD [$]715827882," 908 // arm64: "ADD " 909 // arm64: "RORW [$]1," 910 // arm64: "CSET HI" 911 return i%6 != 0 912 } 913 914 func divis6_int64(i int64) bool { 915 // 386: "IMUL3L [$]-1431655766," 916 // 386: "IMUL3L [$]-1431655765," 917 // 386: "ADCL [$]715827882," 918 // 386: "CMPL .*, [$]715827882" 919 // 386: "CMPL .*, [$]-1431655766" 920 // 386: "SETLS" 921 // arm64: "MOVD [$]-6148914691236517205," 922 // arm64: "MUL " 923 // arm64: "MOVD [$]3074457345618258602," 924 // arm64: "ADD " 925 // arm64: "ROR [$]1," 926 // arm64: "CSET LS" 927 return i%6 == 0 928 } 929 930 func ndivis6_int64(i int64) bool { 931 // 386: "IMUL3L [$]-1431655766," 932 // 386: "IMUL3L [$]-1431655765," 933 // 386: "ADCL [$]715827882," 934 // 386: "CMPL .*, [$]715827882" 935 // 386: "CMPL .*, [$]-1431655766" 936 // 386: "SETHI" 937 // arm64: "MOVD [$]-6148914691236517205," 938 // arm64: "MUL " 939 // arm64: "MOVD [$]3074457345618258602," 940 // arm64: "ADD " 941 // arm64: "ROR [$]1," 942 // arm64: "CSET HI" 943 return i%6 != 0 944 } 945 946 func div_divis6_uint8(i uint8) (uint8, bool) { 947 // 386: "IMUL3L [$]342," 948 // 386: "SHRL [$]11," 949 // 386: "SETEQ" 950 // 386: -"RO[RL]" 951 // arm64: "MOVD [$]342," 952 // arm64: "MULW" 953 // arm64: "UBFX [$]11, R[0-9]+, [$]21," 954 // arm64: "CSET EQ" 955 // arm64: -"RO[RL]" 956 return i / 6, i%6 == 0 957 } 958 959 func div_ndivis6_uint8(i uint8) (uint8, bool) { 960 // 386: "IMUL3L [$]342," 961 // 386: "SHRL [$]11," 962 // 386: "SETNE" 963 // 386: -"RO[RL]" 964 // arm64: "MOVD [$]342," 965 // arm64: "MULW" 966 // arm64: "UBFX [$]11, R[0-9]+, [$]21," 967 // arm64: "CSET NE" 968 // arm64: -"RO[RL]" 969 return i / 6, i%6 != 0 970 } 971 972 func div_divis6_uint16(i uint16) (uint16, bool) { 973 // 386: "IMUL3L [$]43691," 974 // 386: "SHRL [$]18," 975 // 386: "SHLL [$]1," 976 // 386: "SETEQ" 977 // 386: -"RO[RL]" 978 // arm64: "MOVD [$]87382," 979 // arm64: "MUL " 980 // arm64: "LSR [$]19," 981 // arm64: "CSET EQ" 982 // arm64: -"RO[RL]" 983 return i / 6, i%6 == 0 984 } 985 986 func div_ndivis6_uint16(i uint16) (uint16, bool) { 987 // 386: "IMUL3L [$]43691," 988 // 386: "SHRL [$]18," 989 // 386: "SHLL [$]1," 990 // 386: "SETNE" 991 // 386: -"RO[RL]" 992 // arm64: "MOVD [$]87382," 993 // arm64: "MUL " 994 // arm64: "LSR [$]19," 995 // arm64: "CSET NE" 996 // arm64: -"RO[RL]" 997 return i / 6, i%6 != 0 998 } 999 1000 func div_divis6_uint32(i uint32) (uint32, bool) { 1001 // 386: "MOVL [$]-1431655765," 1002 // 386: "SHRL [$]2," 1003 // 386: "SHLL [$]1," 1004 // 386: "SETEQ" 1005 // 386: -"RO[RL]" 1006 // arm64: "MOVD [$]2863311531," 1007 // arm64: "MUL " 1008 // arm64: "LSR [$]34," 1009 // arm64: "CSET EQ" 1010 // arm64: -"RO[RL]" 1011 return i / 6, i%6 == 0 1012 } 1013 1014 func div_ndivis6_uint32(i uint32) (uint32, bool) { 1015 // 386: "MOVL [$]-1431655765," 1016 // 386: "SHRL [$]2," 1017 // 386: "SHLL [$]1," 1018 // 386: "SETNE" 1019 // 386: -"RO[RL]" 1020 // arm64: "MOVD [$]2863311531," 1021 // arm64: "MUL " 1022 // arm64: "LSR [$]34," 1023 // arm64: "CSET NE" 1024 // arm64: -"RO[RL]" 1025 return i / 6, i%6 != 0 1026 } 1027 1028 func div_divis6_uint64(i uint64) (uint64, bool) { 1029 // 386: "MOVL [$]-1431655766," 1030 // 386: "MOVL [$]-1431655765," 1031 // 386: "MULL" 1032 // 386: "SHRL [$]2," 1033 // 386: "SHLL [$]30," 1034 // 386: "SETEQ" 1035 // 386: -".*CALL" 1036 // 386: -"RO[RL]" 1037 // arm64: "MOVD [$]-6148914691236517205," 1038 // arm64: "UMULH" 1039 // arm64: "LSR [$]2," 1040 // arm64: "CSET EQ" 1041 // arm64: -"RO[RL]" 1042 return i / 6, i%6 == 0 1043 } 1044 1045 func div_ndivis6_uint64(i uint64) (uint64, bool) { 1046 // 386: "MOVL [$]-1431655766," 1047 // 386: "MOVL [$]-1431655765," 1048 // 386: "MULL" 1049 // 386: "SHRL [$]2," 1050 // 386: "SHLL [$]30," 1051 // 386: "SETNE" 1052 // 386: -".*CALL" 1053 // 386: -"RO[RL]" 1054 // arm64: "MOVD [$]-6148914691236517205," 1055 // arm64: "UMULH" 1056 // arm64: "LSR [$]2," 1057 // arm64: "CSET NE" 1058 // arm64: -"RO[RL]" 1059 return i / 6, i%6 != 0 1060 } 1061 1062 func div_divis6_int8(i int8) (int8, bool) { 1063 // 386: "SARL [$]31," 1064 // 386: "IMUL3L [$]171," 1065 // 386: "SARL [$]10," 1066 // 386: "SHLL [$]1," 1067 // 386: "SETEQ" 1068 // 386: -"RO[RL]" 1069 // arm64: "MOVD [$]171," 1070 // arm64: "MULW" 1071 // arm64: "SBFX [$]10, R[0-9]+, [$]22," 1072 // arm64: "SUB R[0-9]+->31," 1073 // arm64: "CSET EQ" 1074 // arm64: -"RO[RL]" 1075 return i / 6, i%6 == 0 1076 } 1077 1078 func div_ndivis6_int8(i int8) (int8, bool) { 1079 // 386: "SARL [$]31," 1080 // 386: "IMUL3L [$]171," 1081 // 386: "SARL [$]10," 1082 // 386: "SHLL [$]1," 1083 // 386: "SETNE" 1084 // 386: -"RO[RL]" 1085 // arm64: "MOVD [$]171," 1086 // arm64: "MULW" 1087 // arm64: "SBFX [$]10, R[0-9]+, [$]22," 1088 // arm64: "SUB R[0-9]+->31," 1089 // arm64: "CSET NE" 1090 // arm64: -"RO[RL]" 1091 return i / 6, i%6 != 0 1092 } 1093 1094 func div_divis6_int16(i int16) (int16, bool) { 1095 // 386: "SARL [$]31," 1096 // 386: "IMUL3L [$]43691," 1097 // 386: "SARL [$]18," 1098 // 386: "SHLL [$]1," 1099 // 386: "SETEQ" 1100 // 386: -"RO[RL]" 1101 // arm64: "MOVD [$]43691," 1102 // arm64: "MULW" 1103 // arm64: "SBFX [$]18, R[0-9]+, [$]14," 1104 // arm64: "SUB R[0-9]+->31," 1105 // arm64: "CSET EQ" 1106 // arm64: -"RO[RL]" 1107 return i / 6, i%6 == 0 1108 } 1109 1110 func div_ndivis6_int16(i int16) (int16, bool) { 1111 // 386: "SARL [$]31," 1112 // 386: "IMUL3L [$]43691," 1113 // 386: "SARL [$]18," 1114 // 386: "SHLL [$]1," 1115 // 386: "SETNE" 1116 // 386: -"RO[RL]" 1117 // arm64: "MOVD [$]43691," 1118 // arm64: "MULW" 1119 // arm64: "SBFX [$]18, R[0-9]+, [$]14," 1120 // arm64: "SUB R[0-9]+->31," 1121 // arm64: "CSET NE" 1122 // arm64: -"RO[RL]" 1123 return i / 6, i%6 != 0 1124 } 1125 1126 func div_divis6_int32(i int32) (int32, bool) { 1127 // 386: "SARL [$]31," 1128 // 386: "MOVL [$]-1431655765," 1129 // 386: "IMULL" 1130 // 386: "SARL [$]2," 1131 // 386: "SHLL [$]1," 1132 // 386: "SETEQ" 1133 // 386: -"RO[RL]" 1134 // arm64: "MOVD [$]2863311531," 1135 // arm64: "MUL " 1136 // arm64: "ASR [$]34," 1137 // arm64: "SUB R[0-9]+->63," 1138 // arm64: "CSET EQ" 1139 // arm64: -"RO[RL]" 1140 return i / 6, i%6 == 0 1141 } 1142 1143 func div_ndivis6_int32(i int32) (int32, bool) { 1144 // 386: "SARL [$]31," 1145 // 386: "MOVL [$]-1431655765," 1146 // 386: "IMULL" 1147 // 386: "SARL [$]2," 1148 // 386: "SHLL [$]1," 1149 // 386: "SETNE" 1150 // 386: -"RO[RL]" 1151 // arm64: "MOVD [$]2863311531," 1152 // arm64: "MUL " 1153 // arm64: "ASR [$]34," 1154 // arm64: "SUB R[0-9]+->63," 1155 // arm64: "CSET NE" 1156 // arm64: -"RO[RL]" 1157 return i / 6, i%6 != 0 1158 } 1159 1160 func div_divis6_int64(i int64) (int64, bool) { 1161 // 386: "ANDL [$]-1431655766," 1162 // 386: "ANDL [$]-1431655765," 1163 // 386: "MOVL [$]-1431655766," 1164 // 386: "MOVL [$]-1431655765," 1165 // 386: "SUBL" "SBBL" 1166 // 386: "MULL" 1167 // 386: "SETEQ" 1168 // 386: -"SET(LS|HI)" 1169 // 386: -".*CALL" 1170 // 386: -"RO[RL]" 1171 // arm64: "MOVD [$]-6148914691236517205," 1172 // arm64: "SMULH" 1173 // arm64: "ADD" 1174 // arm64: "ASR [$]2," 1175 // arm64: "SUB R[0-9]+->63," 1176 // arm64: "CSET EQ" 1177 // arm64: -"RO[RL]" 1178 return i / 6, i%6 == 0 1179 } 1180 1181 func div_ndivis6_int64(i int64) (int64, bool) { 1182 // 386: "ANDL [$]-1431655766," 1183 // 386: "ANDL [$]-1431655765," 1184 // 386: "MOVL [$]-1431655766," 1185 // 386: "MOVL [$]-1431655765," 1186 // 386: "SUBL" "SBBL" 1187 // 386: "MULL" 1188 // 386: "SETNE" 1189 // 386: -"SET(LS|HI)" 1190 // 386: -".*CALL" 1191 // 386: -"RO[RL]" 1192 // arm64: "MOVD [$]-6148914691236517205," 1193 // arm64: "SMULH" 1194 // arm64: "ADD" 1195 // arm64: "ASR [$]2," 1196 // arm64: "SUB R[0-9]+->63," 1197 // arm64: "CSET NE" 1198 // arm64: -"RO[RL]" 1199 return i / 6, i%6 != 0 1200 } 1201