tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

binop-divrem-with-constant-arm64-ion-codegen.js (19931B)


      1 // |jit-test| skip-if: !hasDisassembler() || wasmCompileMode() != "ion" || !getBuildConfiguration("arm64"); include:codegen-arm64-test.js
      2 
      3 const WasmTrapIns = `dcps0   \\{#0x0\\} \\(Wasm Trap\\)`;
      4 
      5 // Signed 32-bit division with constants.
      6 const i32_div_s = [
      7  // Division by zero.
      8  {
      9    divisor: 0,
     10    expected: `mov     w2, w0
     11               mov     w1, w2
     12               ${WasmTrapIns}`,
     13  },
     14 
     15  // Power of two divisor
     16  {
     17    divisor: 1,
     18    expected: `mov     w2, w0
     19               mov     w1, w2
     20               mov     w0, w1`,
     21  },
     22  {
     23    divisor: 2,
     24    expected: `mov     w2, w0
     25               mov     w1, w2
     26               lsr     w0, w1, #31
     27               add     w0, w0, w1
     28               asr     w0, w0, #1`,
     29  },
     30  {
     31    divisor: 4,
     32    expected: `mov     w2, w0
     33               mov     w1, w2
     34               asr     w0, w1, #31
     35               lsr     w0, w0, #30
     36               add     w0, w0, w1
     37               asr     w0, w0, #2`,
     38  },
     39 
     40  // Division by -1 needs an overflow check.
     41  {
     42    divisor: -1,
     43    expected: `mov     w2, w0
     44               mov     w1, w2
     45               negs    w0, w1
     46               b.vc    #\\+0x8 \\(addr 0x${HEX}+\\)
     47               ${WasmTrapIns}`,
     48  },
     49 
     50  // Other divisors.
     51  {
     52    divisor: 3,
     53    expected:  `mov     w2, w0
     54                mov     w1, w2
     55                mov     w16, #0x5556
     56                movk    w16, #0x5555, lsl #16
     57                smull   x0, w16, w1
     58                asr     x0, x0, #32
     59                sub     w0, w0, w1, asr #31`,
     60  },
     61  {
     62    divisor: 5,
     63    expected: `mov     w2, w0
     64               mov     w1, w2
     65               mov     w16, #0x6667
     66               movk    w16, #0x6666, lsl #16
     67               smull   x0, w16, w1
     68               asr     x0, x0, #33
     69               sub     w0, w0, w1, asr #31`,
     70  },
     71  {
     72    divisor: 7,
     73    expected: `mov     w2, w0
     74               mov     w1, w2
     75               mov     w16, #0x2493
     76               movk    w16, #0x9249, lsl #16
     77               lsl     x0, x1, #32
     78               smaddl  x0, w16, w1, x0
     79               asr     x0, x0, #34
     80               sub     w0, w0, w1, asr #31`,
     81  },
     82  {
     83    divisor: 9,
     84    expected: `mov     w2, w0
     85               mov     w1, w2
     86               mov     w16, #0x8e39
     87               movk    w16, #0x38e3, lsl #16
     88               smull   x0, w16, w1
     89               asr     x0, x0, #33
     90               sub     w0, w0, w1, asr #31`,
     91  },
     92 ];
     93 
     94 for (let {divisor, expected} of i32_div_s) {
     95  let divs32 =
     96    `(module
     97       (func (export "f") (param i32) (result i32)
     98         (i32.div_s (local.get 0) (i32.const ${divisor}))))`
     99  codegenTestARM64_adhoc(divs32, 'f', expected);
    100 
    101  // Test negative divisors, too.
    102  if (divisor > 1) {
    103    let divs32 =
    104      `(module
    105         (func (export "f") (param i32) (result i32)
    106           (i32.div_s (local.get 0) (i32.const -${divisor}))))`
    107    codegenTestARM64_adhoc(divs32, 'f', expected + `
    108      neg     w0, w0`
    109    );
    110  }
    111 }
    112 
    113 // Unsigned 32-bit division with constants.
    114 const i32_div_u = [
    115  // Division by zero.
    116  {
    117    divisor: 0,
    118    expected: `mov     w2, w0
    119               mov     w1, w2
    120               ${WasmTrapIns}`,
    121  },
    122 
    123  // Power of two divisor
    124  {
    125    divisor: 1,
    126    expected: `mov     w2, w0
    127               mov     w1, w2
    128               mov     w0, w1`,
    129  },
    130  {
    131    divisor: 2,
    132    expected: `mov     w2, w0
    133               mov     w1, w2
    134               lsr     w0, w1, #1`,
    135  },
    136  {
    137    divisor: 4,
    138    expected: `mov     w2, w0
    139               mov     w1, w2
    140               lsr     w0, w1, #2`,
    141  },
    142 
    143  // Other divisors.
    144  {
    145    divisor: 3,
    146    expected:  `mov     w2, w0
    147                mov     w1, w2
    148                mov     w16, #0xaaab
    149                movk    w16, #0xaaaa, lsl #16
    150                umull   x0, w16, w1
    151                lsr     x0, x0, #33`,
    152  },
    153  {
    154    divisor: 5,
    155    expected: `mov     w2, w0
    156               mov     w1, w2
    157               mov     w16, #0xcccd
    158               movk    w16, #0xcccc, lsl #16
    159               umull   x0, w16, w1
    160               lsr     x0, x0, #34`,
    161  },
    162  {
    163    divisor: 7,
    164    expected: `mov     w2, w0
    165               mov     w1, w2
    166               mov     w16, #0x4925
    167               movk    w16, #0x2492, lsl #16
    168               umull   x0, w16, w1
    169               add     x0, x1, x0, lsr #32
    170               lsr     x0, x0, #3`,
    171  },
    172  {
    173    divisor: 9,
    174    expected: `mov     w2, w0
    175               mov     w1, w2
    176               mov     w16, #0x8e39
    177               movk    w16, #0x38e3, lsl #16
    178               umull   x0, w16, w1
    179               lsr     x0, x0, #33`,
    180  },
    181 
    182  // Special case: Zero (additional) shift amount.
    183  {
    184    divisor: 641,
    185    expected: `mov     w2, w0
    186               mov     w1, w2
    187               mov     w16, #0x3d81
    188               movk    w16, #0x66, lsl #16
    189               umull   x0, w16, w1
    190               lsr     x0, x0, #32`,
    191  },
    192 ];
    193 
    194 for (let {divisor, expected} of i32_div_u) {
    195  let divu32 =
    196    `(module
    197       (func (export "f") (param i32) (result i32)
    198         (i32.div_u (local.get 0) (i32.const ${divisor}))))`
    199  codegenTestARM64_adhoc(divu32, 'f', expected);
    200 }
    201 
    202 // Signed 64-bit division with constants.
    203 const i64_div_s = [
    204  // Division by zero.
    205  {
    206    divisor: 0,
    207    expected: `mov     x2, x0
    208               mov     x1, x2
    209               ${WasmTrapIns}`,
    210  },
    211 
    212  // Power of two divisor
    213  {
    214    divisor: 1,
    215    expected: `mov     x2, x0
    216               mov     x1, x2
    217               mov     x0, x1`,
    218  },
    219  {
    220    divisor: 2,
    221    expected: `mov     x2, x0
    222               mov     x1, x2
    223               lsr     x0, x1, #63
    224               add     x0, x0, x1
    225               asr     x0, x0, #1`,
    226  },
    227  {
    228    divisor: 4,
    229    expected: `mov     x2, x0
    230               mov     x1, x2
    231               asr     x0, x1, #63
    232               lsr     x0, x0, #62
    233               add     x0, x0, x1
    234               asr     x0, x0, #2`,
    235  },
    236  {
    237    divisor: 0x1_0000_0000,
    238    expected: `mov     x2, x0
    239               mov     x1, x2
    240               asr     x0, x1, #63
    241               lsr     x0, x0, #32
    242               add     x0, x0, x1
    243               asr     x0, x0, #32`,
    244  },
    245 
    246  // Division by -1 needs an overflow check.
    247  {
    248    divisor: -1,
    249    expected: `mov     x2, x0
    250               mov     x1, x2
    251               negs    x0, x1
    252               b.vc    #\\+0x8 \\(addr 0x${HEX}+\\)
    253               ${WasmTrapIns}`,
    254  },
    255 
    256  // Other divisors.
    257  {
    258    divisor: 3,
    259    expected:  `mov     x2, x0
    260                mov     x1, x2
    261                mov     x16, #0x5556
    262                movk    x16, #0x5555, lsl #16
    263                movk    x16, #0x5555, lsl #32
    264                movk    x16, #0x5555, lsl #48
    265                smulh   x0, x1, x16
    266                sbfx    x0, x0, #0, #64
    267                sub     x0, x0, x1, asr #63`,
    268  },
    269  {
    270    divisor: 5,
    271    expected: `mov     x2, x0
    272               mov     x1, x2
    273               mov     x16, #0x6667
    274               movk    x16, #0x6666, lsl #16
    275               movk    x16, #0x6666, lsl #32
    276               movk    x16, #0x6666, lsl #48
    277               smulh   x0, x1, x16
    278               asr     x0, x0, #1
    279               sub     x0, x0, x1, asr #63`,
    280  },
    281  {
    282    divisor: 7,
    283    expected: `mov     x2, x0
    284               mov     x1, x2
    285               mov     x16, #0x4925
    286               movk    x16, #0x2492, lsl #16
    287               movk    x16, #0x9249, lsl #32
    288               movk    x16, #0x4924, lsl #48
    289               smulh   x0, x1, x16
    290               asr     x0, x0, #1
    291               sub     x0, x0, x1, asr #63`,
    292  },
    293  {
    294    divisor: 9,
    295    expected: `mov     x2, x0
    296               mov     x1, x2
    297               mov     x16, #0x1c72
    298               movk    x16, #0x71c7, lsl #16
    299               movk    x16, #0xc71c, lsl #32
    300               movk    x16, #0x1c71, lsl #48
    301               smulh   x0, x1, x16
    302               sbfx    x0, x0, #0, #64
    303               sub     x0, x0, x1, asr #63`,
    304  },
    305 ];
    306 
    307 for (let {divisor, expected} of i64_div_s) {
    308  let divs64 =
    309    `(module
    310       (func (export "f") (param i64) (result i64)
    311         (i64.div_s (local.get 0) (i64.const ${divisor}))))`
    312  codegenTestARM64_adhoc(divs64, 'f', expected);
    313 
    314  // Test negative divisors, too.
    315  if (divisor > 1) {
    316    let divs64 =
    317      `(module
    318         (func (export "f") (param i64) (result i64)
    319           (i64.div_s (local.get 0) (i64.const -${divisor}))))`
    320    codegenTestARM64_adhoc(divs64, 'f', expected + `
    321      neg     x0, x0`);
    322  }
    323 }
    324 
    325 // Unsigned 64-bit division with constants.
    326 const i64_div_u = [
    327  // Division by zero.
    328  {
    329    divisor: 0,
    330    expected: `mov     x2, x0
    331               mov     x1, x2
    332               ${WasmTrapIns}`,
    333  },
    334 
    335  // Power of two divisor
    336  {
    337    divisor: 1,
    338    expected: `mov     x2, x0
    339               mov     x1, x2
    340               mov     x0, x1`,
    341  },
    342  {
    343    divisor: 2,
    344    expected: `mov     x2, x0
    345               mov     x1, x2
    346               lsr     x0, x1, #1`,
    347  },
    348  {
    349    divisor: 4,
    350    expected: `mov     x2, x0
    351               mov     x1, x2
    352               lsr     x0, x1, #2`,
    353  },
    354  {
    355    divisor: 0x1_0000_0000,
    356    expected: `mov     x2, x0
    357               mov     x1, x2
    358               lsr     x0, x1, #32`,
    359  },
    360 
    361  // Other divisors.
    362  {
    363    divisor: 3,
    364    expected:  `mov     x2, x0
    365                mov     x1, x2
    366                mov     x16, #0xaaab
    367                movk    x16, #0xaaaa, lsl #16
    368                movk    x16, #0xaaaa, lsl #32
    369                movk    x16, #0xaaaa, lsl #48
    370                umulh   x0, x1, x16
    371                lsr     x0, x0, #1`,
    372  },
    373  {
    374    divisor: 5,
    375    expected: `mov     x2, x0
    376               mov     x1, x2
    377               mov     x16, #0xcccd
    378               movk    x16, #0xcccc, lsl #16
    379               movk    x16, #0xcccc, lsl #32
    380               movk    x16, #0xcccc, lsl #48
    381               umulh   x0, x1, x16
    382               lsr     x0, x0, #2`,
    383  },
    384  {
    385    divisor: 7,
    386    expected: `mov     x2, x0
    387               mov     x1, x2
    388               mov     x16, #0x2493
    389               movk    x16, #0x9249, lsl #16
    390               movk    x16, #0x4924, lsl #32
    391               movk    x16, #0x2492, lsl #48
    392               umulh   x0, x1, x16
    393               sub     x16, x1, x0
    394               add     x0, x0, x16, lsr #1
    395               lsr     x0, x0, #2`,
    396  },
    397  {
    398    divisor: 9,
    399    expected: `mov     x2, x0
    400               mov     x1, x2
    401               mov     x16, #0xe38f
    402               movk    x16, #0x8e38, lsl #16
    403               movk    x16, #0x38e3, lsl #32
    404               movk    x16, #0xe38e, lsl #48
    405               umulh   x0, x1, x16
    406               lsr     x0, x0, #3`,
    407  },
    408 
    409  // Special case: Zero shift amount.
    410  {
    411    divisor: 274177,
    412    expected: `mov     x2, x0
    413               mov     x1, x2
    414               mov     x16, #0xd101
    415               movk    x16, #0xf19c, lsl #16
    416               movk    x16, #0x3d30, lsl #32
    417               umulh   x0, x1, x16
    418               lsr     x0, x0, #0`,
    419  },
    420 ];
    421 
    422 for (let {divisor, expected} of i64_div_u) {
    423  let divu64 =
    424    `(module
    425       (func (export "f") (param i64) (result i64)
    426         (i64.div_u (local.get 0) (i64.const ${divisor}))))`
    427  codegenTestARM64_adhoc(divu64, 'f', expected);
    428 }
    429 
    430 //////////////
    431 
    432 
    433 
    434 // Signed 32-bit remainder with constants.
    435 const i32_rem_s = [
    436  // Division by zero.
    437  {
    438    divisor: 0,
    439    expected: `mov     w2, w0
    440               mov     w1, w2
    441               ${WasmTrapIns}`,
    442  },
    443 
    444  // Power of two divisor
    445  {
    446    divisor: 1,
    447    expected: `mov     w2, w0
    448               mov     w1, w2
    449               mov     w0, wzr`,
    450  },
    451  {
    452    divisor: 2,
    453    expected: `mov     w2, w0
    454               mov     w1, w2
    455               tst     w1, w1
    456               b.mi    #\\+0xc \\(addr 0x${HEX}+\\)
    457               and     w0, w1, #0x1
    458               b       #\\+0x10 \\(addr 0x${HEX}+\\)
    459               neg     w0, w1
    460               and     w0, w0, #0x1
    461               neg     w0, w0`,
    462  },
    463  {
    464    divisor: 4,
    465    expected: `mov     w2, w0
    466               mov     w1, w2
    467               tst     w1, w1
    468               b.mi    #\\+0xc \\(addr 0x${HEX}+\\)
    469               and     w0, w1, #0x3
    470               b       #\\+0x10 \\(addr 0x${HEX}+\\)
    471               neg     w0, w1
    472               and     w0, w0, #0x3
    473               neg     w0, w0`,
    474  },
    475  {
    476    divisor: 0x100,
    477    expected: `mov     w2, w0
    478               mov     w1, w2
    479               tst     w1, w1
    480               b.mi    #\\+0xc \\(addr 0x${HEX}+\\)
    481               and     w0, w1, #0xff
    482               b       #\\+0x10 \\(addr 0x${HEX}+\\)
    483               neg     w0, w1
    484               and     w0, w0, #0xff
    485               neg     w0, w0`,
    486  },
    487  {
    488    divisor: 0x10000,
    489    expected: `mov     w2, w0
    490               mov     w1, w2
    491               tst     w1, w1
    492               b.mi    #\\+0xc \\(addr 0x${HEX}+\\)
    493               and     w0, w1, #0xffff
    494               b       #\\+0x10 \\(addr 0x${HEX}+\\)
    495               neg     w0, w1
    496               and     w0, w0, #0xffff
    497               neg     w0, w0`,
    498  },
    499  {
    500    divisor: 0x8000_0000,
    501    expected: `mov     w2, w0
    502               mov     w1, w2
    503               tst     w1, w1
    504               b.mi    #\\+0xc \\(addr 0x${HEX}+\\)
    505               and     w0, w1, #0x7fffffff
    506               b       #\\+0x10 \\(addr 0x${HEX}+\\)
    507               neg     w0, w1
    508               and     w0, w0, #0x7fffffff
    509               neg     w0, w0`,
    510  },
    511 ];
    512 
    513 for (let {divisor, expected} of i32_rem_s) {
    514  let rems32 =
    515    `(module
    516       (func (export "f") (param i32) (result i32)
    517         (i32.rem_s (local.get 0) (i32.const ${divisor}))))`
    518  codegenTestARM64_adhoc(rems32, 'f', expected);
    519 
    520  // Test negative divisors, too.
    521  if (divisor > 0) {
    522    let rems32 =
    523      `(module
    524         (func (export "f") (param i32) (result i32)
    525           (i32.rem_s (local.get 0) (i32.const -${divisor}))))`
    526    codegenTestARM64_adhoc(rems32, 'f', expected);
    527  }
    528 }
    529 
    530 // Unigned 32-bit remainder with constants.
    531 const u32_rem_s = [
    532  // Division by zero.
    533  {
    534    divisor: 0,
    535    expected: `mov     w2, w0
    536               mov     w1, w2
    537               ${WasmTrapIns}`,
    538  },
    539 
    540  // Power of two divisor
    541  {
    542    divisor: 1,
    543    expected: `mov     w2, w0
    544               mov     w1, w2
    545               mov     w0, wzr`,
    546  },
    547  {
    548    divisor: 2,
    549    expected: `mov     w2, w0
    550               mov     w1, w2
    551               and     w0, w1, #0x1`,
    552  },
    553  {
    554    divisor: 4,
    555    expected: `mov     w2, w0
    556               mov     w1, w2
    557               and     w0, w1, #0x3`,
    558  },
    559  {
    560    divisor: 0x100,
    561    expected: `mov     w2, w0
    562               mov     w1, w2
    563               and     w0, w1, #0xff`,
    564  },
    565  {
    566    divisor: 0x10000,
    567    expected: `mov     w2, w0
    568               mov     w1, w2
    569               and     w0, w1, #0xffff`,
    570  },
    571  {
    572    divisor: 0x8000_0000,
    573    expected: `mov     w2, w0
    574               mov     w1, w2
    575               and     w0, w1, #0x7fffffff`,
    576  },
    577 ];
    578 
    579 for (let {divisor, expected} of u32_rem_s) {
    580  let remu32 =
    581    `(module
    582       (func (export "f") (param i32) (result i32)
    583         (i32.rem_u (local.get 0) (i32.const ${divisor}))))`
    584  codegenTestARM64_adhoc(remu32, 'f', expected);
    585 }
    586 
    587 // Signed 64-bit remainder with constants.
    588 const i64_rem_s = [
    589  // Division by zero.
    590  {
    591    divisor: 0,
    592    expected: `mov     x2, x0
    593               mov     x1, x2
    594               ${WasmTrapIns}`,
    595  },
    596 
    597  // Power of two divisor
    598  {
    599    divisor: 1,
    600    expected: `mov     x2, x0
    601               mov     x1, x2
    602               mov     x0, xzr`,
    603  },
    604  {
    605    divisor: 2,
    606    expected: `mov     x2, x0
    607               mov     x1, x2
    608               tst     x1, x1
    609               b.mi    #\\+0xc \\(addr 0x${HEX}+\\)
    610               and     x0, x1, #0x1
    611               b       #\\+0x10 \\(addr 0x${HEX}+\\)
    612               neg     x0, x1
    613               and     x0, x0, #0x1
    614               neg     x0, x0`,
    615  },
    616  {
    617    divisor: 4,
    618    expected: `mov     x2, x0
    619               mov     x1, x2
    620               tst     x1, x1
    621               b.mi    #\\+0xc \\(addr 0x${HEX}+\\)
    622               and     x0, x1, #0x3
    623               b       #\\+0x10 \\(addr 0x${HEX}+\\)
    624               neg     x0, x1
    625               and     x0, x0, #0x3
    626               neg     x0, x0`,
    627  },
    628  {
    629    divisor: 0x100,
    630    expected: `mov     x2, x0
    631               mov     x1, x2
    632               tst     x1, x1
    633               b.mi    #\\+0xc \\(addr 0x${HEX}+\\)
    634               and     x0, x1, #0xff
    635               b       #\\+0x10 \\(addr 0x${HEX}+\\)
    636               neg     x0, x1
    637               and     x0, x0, #0xff
    638               neg     x0, x0`,
    639  },
    640  {
    641    divisor: 0x10000,
    642    expected: `mov     x2, x0
    643               mov     x1, x2
    644               tst     x1, x1
    645               b.mi    #\\+0xc \\(addr 0x${HEX}+\\)
    646               and     x0, x1, #0xffff
    647               b       #\\+0x10 \\(addr 0x${HEX}+\\)
    648               neg     x0, x1
    649               and     x0, x0, #0xffff
    650               neg     x0, x0`,
    651  },
    652  {
    653    divisor: 0x8000_0000,
    654    expected: `mov     x2, x0
    655               mov     x1, x2
    656               tst     x1, x1
    657               b.mi    #\\+0xc \\(addr 0x${HEX}+\\)
    658               and     x0, x1, #0x7fffffff
    659               b       #\\+0x10 \\(addr 0x${HEX}+\\)
    660               neg     x0, x1
    661               and     x0, x0, #0x7fffffff
    662               neg     x0, x0`,
    663  },
    664  {
    665    divisor: 0x1_0000_0000,
    666    expected: `mov     x2, x0
    667               mov     x1, x2
    668               tst     x1, x1
    669               b.mi    #\\+0xc \\(addr 0x${HEX}+\\)
    670               mov     w0, w1
    671               b       #\\+0x10 \\(addr 0x${HEX}+\\)
    672               neg     x0, x1
    673               mov     w0, w0
    674               neg     x0, x0`,
    675  },
    676  {
    677    divisor: 0x8000_0000_0000_0000n,
    678    expected: `mov     x2, x0
    679               mov     x1, x2
    680               tst     x1, x1
    681               b.mi    #\\+0xc \\(addr 0x${HEX}+\\)
    682               and     x0, x1, #0x7fffffffffffffff
    683               b       #\\+0x10 \\(addr 0x${HEX}+\\)
    684               neg     x0, x1
    685               and     x0, x0, #0x7fffffffffffffff
    686               neg     x0, x0`,
    687  },
    688 ];
    689 
    690 for (let {divisor, expected} of i64_rem_s) {
    691  let rems64 =
    692    `(module
    693       (func (export "f") (param i64) (result i64)
    694         (i64.rem_s (local.get 0) (i64.const ${divisor}))))`
    695  codegenTestARM64_adhoc(rems64, 'f', expected);
    696 
    697  // Test negative divisors, too.
    698  if (divisor > 0) {
    699    let rems64 =
    700      `(module
    701         (func (export "f") (param i64) (result i64)
    702           (i64.rem_s (local.get 0) (i64.const -${divisor}))))`
    703    codegenTestARM64_adhoc(rems64, 'f', expected);
    704  }
    705 }
    706 
    707 // Unsigned 64-bit remainder with constants.
    708 const i64_rem_u = [
    709  // Division by zero.
    710  {
    711    divisor: 0,
    712    expected: `mov     x2, x0
    713               mov     x1, x2
    714               ${WasmTrapIns}`,
    715  },
    716 
    717  // Power of two divisor
    718  {
    719    divisor: 1,
    720    expected: `mov     x2, x0
    721               mov     x1, x2
    722               mov     x0, xzr`,
    723  },
    724  {
    725    divisor: 2,
    726    expected: `mov     x2, x0
    727               mov     x1, x2
    728               and     x0, x1, #0x1`,
    729  },
    730  {
    731    divisor: 4,
    732    expected: `mov     x2, x0
    733               mov     x1, x2
    734               and     x0, x1, #0x3`,
    735  },
    736  {
    737    divisor: 0x100,
    738    expected: `mov     x2, x0
    739               mov     x1, x2
    740               and     x0, x1, #0xff`,
    741  },
    742  {
    743    divisor: 0x10000,
    744    expected: `mov     x2, x0
    745               mov     x1, x2
    746               and     x0, x1, #0xffff`,
    747  },
    748  {
    749    divisor: 0x8000_0000,
    750    expected: `mov     x2, x0
    751               mov     x1, x2
    752               and     x0, x1, #0x7fffffff`,
    753  },
    754  {
    755    divisor: 0x1_0000_0000,
    756    expected: `mov     x2, x0
    757               mov     x1, x2
    758               mov     w0, w1`,
    759  },
    760  {
    761    divisor: 0x8000_0000_0000_0000n,
    762    expected: `mov     x2, x0
    763               mov     x1, x2
    764               and     x0, x1, #0x7fffffffffffffff`,
    765  },
    766 ];
    767 
    768 for (let {divisor, expected} of i64_rem_u) {
    769  let remu64 =
    770    `(module
    771       (func (export "f") (param i64) (result i64)
    772         (i64.rem_u (local.get 0) (i64.const ${divisor}))))`
    773  codegenTestARM64_adhoc(remu64, 'f', expected);
    774 }