text: /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
  │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
  ╞══════════════════════════════════════════════════════════════════════════════╡
  │ Copyright 2020 Justine Alexandra Roberts Tunney                              │
  │                                                                              │
  │ Permission to use, copy, modify, and/or distribute this software for         │
  │ any purpose with or without fee is hereby granted, provided that the         │
  │ above copyright notice and this permission notice appear in all copies.      │
  │                                                                              │
  │ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
  │ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
  │ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
  │ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
  │ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
  │ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
  │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
  │ PERFORMANCE OF THIS SOFTWARE.                                                │
  ╚─────────────────────────────────────────────────────────────────────────────*/
  #include "libc/calls/struct/sigaction.h"
  #include "libc/log/check.h"
  #include "libc/runtime/gc.internal.h"
  #include "libc/sysv/consts/sa.h"
  #include "libc/sysv/consts/sig.h"
  #include "libc/testlib/ezbench.h"
  #include "libc/testlib/testlib.h"
  #include "libc/x/x.h"
  #include "tool/build/lib/divmul.h"
  #include "tool/build/lib/endian.h"
  #include "tool/build/lib/flags.h"
  
  #define CX     1
  #define OSZ    00000000040
  #define REXW   00000000100
  #define RM(x)  (0000001600 & ((x) << 007))
  #define MOD(x) (0060000000 & ((x) << 026))
  
  jmp_buf sigfpejmp;
  struct Machine m[1];
  struct sigaction oldsigfpe[1];
  struct XedDecodedInst xedd[1];
  
  void OnSigFpe(void) {
    /* ProTip: gdb -ex 'handle SIGFPE nostop noprint pass' */
    longjmp(sigfpejmp, 1);
  }
  
  void SetUp(void) {
    m->xedd = xedd;
    CHECK_NE(-1, xsigaction(SIGFPE, OnSigFpe, SA_NODEFER, 0, oldsigfpe));
  }
  
  void TearDown(void) {
    m->xedd = xedd;
    CHECK_NE(-1, sigaction(SIGFPE, oldsigfpe, NULL));
  }
  
  TEST(imul8, test) {
    static const uint8_t A[] = {0x00, 0x01, 0x80, 0x7F, 0x81, 0x7E, 0xFF, 0xBF};
    int i, j;
    int16_t ax;
    bool cf, of;
    for (i = 0; i < ARRAYLEN(A); ++i) {
      for (j = 0; j < ARRAYLEN(A); ++j) {
        Write8(m->ax, A[i]);
        Write8(m->cx, A[j]);
        OpMulAxAlEbSigned(m, MOD(3) | RM(CX));
        asm volatile("imulb\t%3"
                     : "=a"(ax), "=@ccc"(cf), "=@cco"(of)
                     : "q"(A[j]), "0"(A[i])
                     : "cc");
        EXPECT_EQ(ax, (int16_t)Read16(m->ax));
        EXPECT_EQ(cf, GetFlag(m->flags, FLAGS_CF));
        EXPECT_EQ(of, GetFlag(m->flags, FLAGS_OF));
      }
    }
  }
  
  TEST(imul16, test) {
    static const uint16_t A[] = {0x0000, 0x0001, 0x8000, 0x7FFF, 0x8001, 0x7FFE,
                                 0xFFFF, 0xBeef, 0x00b5, 0x00b6, 0xb504, 0xb505};
    int i, j;
    bool cf, of;
    uint16_t dx, ax;
    for (i = 0; i < ARRAYLEN(A); ++i) {
      for (j = 0; j < ARRAYLEN(A); ++j) {
        Write16(m->ax, A[i]);
        Write16(m->cx, A[j]);
        OpMulRdxRaxEvqpSigned(m, OSZ | MOD(3) | RM(CX));
        asm("imulw\t%4"
            : "=d"(dx), "=a"(ax), "=@ccc"(cf), "=@cco"(of)
            : "r"(A[j]), "1"(A[i])
            : "cc");
        EXPECT_EQ((int32_t)((uint32_t)dx << 16 | ax),
                  (int32_t)((uint32_t)Read16(m->dx) << 16 | Read16(m->ax)));
        EXPECT_EQ(cf, GetFlag(m->flags, FLAGS_CF));
        EXPECT_EQ(of, GetFlag(m->flags, FLAGS_OF));
      }
    }
  }
  
  TEST(imul32, test) {
    static const uint32_t A[] = {0x00000000, 0x00000001, 0x80000000, 0x7FFFFFFF,
                                 0x80000001, 0x7FFFFFFE, 0xFFFFFFFF, 0xDeadBeef,
                                 0x000000b6, 0x0000b504, 0x0000b505, 0xb504f334};
    int i, j;
    bool cf, of;
    uint32_t dx, ax;
    for (i = 0; i < ARRAYLEN(A); ++i) {
      for (j = 0; j < ARRAYLEN(A); ++j) {
        Write32(m->ax, A[i]);
        Write32(m->cx, A[j]);
        OpMulRdxRaxEvqpSigned(m, MOD(3) | RM(CX));
        asm("imull\t%4"
            : "=d"(dx), "=a"(ax), "=@ccc"(cf), "=@cco"(of)
            : "r"(A[j]), "1"(A[i])
            : "cc");
        EXPECT_EQ((int64_t)((uint64_t)dx << 32 | ax),
                  (int64_t)((uint64_t)Read32(m->dx) << 32 | Read32(m->ax)));
        EXPECT_EQ(cf, GetFlag(m->flags, FLAGS_CF));
        EXPECT_EQ(of, GetFlag(m->flags, FLAGS_OF));
      }
    }
  }
  
  TEST(imul64, test) {
    static const uint64_t A[] = {0x00000000, 0x00000001, 0x80000000, 0x7FFFFFFF,
                                 0x80000001, 0x7FFFFFFE, 0xFFFFFFFF, 0xDeadBeef,
                                 0x000000b6, 0x0000b504, 0x0000b505, 0xb504f334};
    int i, j;
    bool cf, of;
    uint64_t dx, ax;
    for (i = 0; i < ARRAYLEN(A); ++i) {
      for (j = 0; j < ARRAYLEN(A); ++j) {
        Write64(m->ax, A[i]);
        Write64(m->cx, A[j]);
        OpMulRdxRaxEvqpSigned(m, REXW | MOD(3) | RM(CX));
        asm("imulq\t%4"
            : "=d"(dx), "=a"(ax), "=@ccc"(cf), "=@cco"(of)
            : "r"(A[j]), "1"(A[i])
            : "cc");
        EXPECT_EQ((int128_t)((uint128_t)dx << 64 | ax),
                  (int128_t)((uint128_t)Read64(m->dx) << 64 | Read64(m->ax)));
        EXPECT_EQ(cf, GetFlag(m->flags, FLAGS_CF));
        EXPECT_EQ(of, GetFlag(m->flags, FLAGS_OF));
      }
    }
  }
  
  TEST(mul8, test) {
    static const uint8_t A[] = {0x00, 0x01, 0x80, 0x7F, 0x81, 0x7E, 0xFF, 0xb6};
    int i, j;
    uint16_t ax;
    bool cf, of;
    for (i = 0; i < ARRAYLEN(A); ++i) {
      for (j = 0; j < ARRAYLEN(A); ++j) {
        Write8(m->ax, A[i]);
        Write8(m->cx, A[j]);
        OpMulAxAlEbUnsigned(m, MOD(3) | RM(CX));
        asm volatile("mulb\t%3"
                     : "=a"(ax), "=@ccc"(cf), "=@cco"(of)
                     : "q"(A[j]), "0"(A[i])
                     : "cc");
        EXPECT_EQ(ax, Read16(m->ax));
        EXPECT_EQ(cf, GetFlag(m->flags, FLAGS_CF));
        EXPECT_EQ(of, GetFlag(m->flags, FLAGS_OF));
      }
    }
  }
  
  TEST(mul16, test) {
    static const uint16_t A[] = {0x0000, 0x0001, 0x8000, 0x7FFF,
                                 0x8001, 0x7FFE, 0xFFFF, 0x00b6};
    int i, j;
    bool cf, of;
    uint16_t dx, ax;
    for (i = 0; i < ARRAYLEN(A); ++i) {
      for (j = 0; j < ARRAYLEN(A); ++j) {
        Write16(m->ax, A[i]);
        Write16(m->cx, A[j]);
        OpMulRdxRaxEvqpUnsigned(m, OSZ | MOD(3) | RM(CX));
        asm("mulw\t%4"
            : "=d"(dx), "=a"(ax), "=@ccc"(cf), "=@cco"(of)
            : "r"(A[j]), "1"(A[i])
            : "cc");
        EXPECT_EQ((uint32_t)((uint32_t)dx << 16 | ax),
                  (uint32_t)((uint32_t)Read16(m->dx) << 16 | Read16(m->ax)));
        EXPECT_EQ(cf, GetFlag(m->flags, FLAGS_CF));
        EXPECT_EQ(of, GetFlag(m->flags, FLAGS_OF));
      }
    }
  }
  
  TEST(mul32, test) {
    static const uint32_t A[] = {0x00000000, 0x00000001, 0x80000000, 0x7FFFFFFF,
                                 0x80000001, 0x7FFFFFFE, 0xFFFFFFFF, 0x000000b5,
                                 0x000000b6, 0x0000b504, 0x0000b505, 0xb504f334};
    int i, j;
    bool cf, of;
    uint32_t dx, ax;
    for (i = 0; i < ARRAYLEN(A); ++i) {
      for (j = 0; j < ARRAYLEN(A); ++j) {
        Write32(m->ax, A[i]);
        Write32(m->cx, A[j]);
        OpMulRdxRaxEvqpUnsigned(m, MOD(3) | RM(CX));
        asm("mull\t%4"
            : "=d"(dx), "=a"(ax), "=@ccc"(cf), "=@cco"(of)
            : "r"(A[j]), "1"(A[i])
            : "cc");
        EXPECT_EQ((uint64_t)((uint64_t)dx << 32 | ax),
                  (uint64_t)((uint64_t)Read32(m->dx) << 32 | Read32(m->ax)));
        EXPECT_EQ(cf, GetFlag(m->flags, FLAGS_CF));
        EXPECT_EQ(of, GetFlag(m->flags, FLAGS_OF));
      }
    }
  }
  
  TEST(mul64, test) {
    static const uint64_t A[] = {0x00000000, 0x00000001, 0x80000000, 0x7FFFFFFF,
                                 0x80000001, 0x7FFFFFFE, 0xFFFFFFFF, 0x000000b6,
                                 0x0000b504, 0x0000b505, 0xb504f333, 0xb504f334};
    int i, j;
    bool cf, of;
    uint64_t dx, ax;
    for (i = 0; i < ARRAYLEN(A); ++i) {
      for (j = 0; j < ARRAYLEN(A); ++j) {
        Write64(m->ax, A[i]);
        Write64(m->cx, A[j]);
        OpMulRdxRaxEvqpUnsigned(m, REXW | MOD(3) | RM(CX));
        asm("mulq\t%4"
            : "=d"(dx), "=a"(ax), "=@ccc"(cf), "=@cco"(of)
            : "r"(A[j]), "1"(A[i])
            : "cc");
        EXPECT_EQ((uint128_t)((uint128_t)dx << 64 | ax),
                  (uint128_t)((uint128_t)Read64(m->dx) << 64 | Read64(m->ax)));
        EXPECT_EQ(cf, GetFlag(m->flags, FLAGS_CF));
        EXPECT_EQ(of, GetFlag(m->flags, FLAGS_OF));
      }
    }
  }
  
  TEST(idiv8, test) {
    if (IsWindows()) return; /* TODO */
    static const uint8_t A[] = {0x00, 0x01, 0x80, 0x7F, 0x81, 0x7E, 0xFF, 0xBF};
    uint16_t remquo;
    bool gotthrow, gotsigfpe;
    int8_t i, j, k, w, x, a, b;
    int8_t quotient, remainder;
    for (i = 0; i < ARRAYLEN(A); ++i) {
      for (j = 0; j < ARRAYLEN(A); ++j) {
        for (k = 0; k < ARRAYLEN(A); ++k) {
          m->ax[1] = A[i];
          m->ax[0] = A[j];
          m->cx[0] = A[k];
          gotthrow = false;
          gotsigfpe = false;
          if (!setjmp(m->onhalt)) {
            OpDivAlAhAxEbSigned(m, MOD(3) | RM(CX));
          } else {
            gotthrow = true;
          }
          if (!setjmp(sigfpejmp)) {
            asm("idivb\t%1"
                : "=a"(remquo)
                : "q"(A[k]), "0"((int16_t)(A[i] << 8 | A[j]))
                : "cc");
          } else {
            gotsigfpe = true;
          }
          EXPECT_EQ(gotsigfpe, gotthrow);
          if (!gotsigfpe && !gotthrow) {
            quotient = (int8_t)remquo;
            remainder = (int8_t)(remquo >> 8);
            EXPECT_EQ(quotient, (int8_t)m->ax[0]);
            EXPECT_EQ(remainder, (int8_t)m->ax[1]);
          }
        }
      }
    }
  }
  
  TEST(idiv16, test) {
    if (IsWindows()) return; /* TODO */
    static const uint16_t A[] = {0x0000, 0x0001, 0x8000, 0x7FFF,
                                 0x8001, 0x7FFE, 0xFFFF, 0xBeef};
    bool gotthrow, gotsigfpe;
    int16_t i, j, k, w, x, a, b;
    int16_t quotient, remainder;
    for (i = 0; i < ARRAYLEN(A); ++i) {
      for (j = 0; j < ARRAYLEN(A); ++j) {
        for (k = 0; k < ARRAYLEN(A); ++k) {
          memcpy(m->dx, &A[i], 2);
          memcpy(m->ax, &A[j], 2);
          memcpy(m->cx, &A[k], 2);
          if (!setjmp(m->onhalt)) {
            gotthrow = false;
            OpDivRdxRaxEvqpSigned(m, OSZ | MOD(3) | RM(CX));
          } else {
            gotthrow = true;
          }
          if (!setjmp(sigfpejmp)) {
            gotsigfpe = false;
            asm("idivw\t%2"
                : "=d"(remainder), "=a"(quotient)
                : "r"(A[k]), "0"(A[i]), "1"(A[j])
                : "cc");
          } else {
            gotsigfpe = true;
          }
          EXPECT_EQ(gotsigfpe, gotthrow);
          if (!gotsigfpe && !gotthrow) {
            EXPECT_EQ(quotient, (int16_t)Read16(m->ax));
            EXPECT_EQ(remainder, (int16_t)Read16(m->dx));
          }
        }
      }
    }
  }
  
  TEST(idiv32, test) {
    if (IsWindows()) return; /* TODO */
    static const uint32_t A[] = {0x00000000, 0x00000001, 0x80000000, 0x7FFFFFFF,
                                 0x80000001, 0x7FFFFFFE, 0xFFFFFFFF, 0xDeadBeef};
    bool gotthrow, gotsigfpe;
    int32_t i, j, k, w, x, a, b;
    int32_t quotient, remainder;
    for (i = 0; i < ARRAYLEN(A); ++i) {
      for (j = 0; j < ARRAYLEN(A); ++j) {
        for (k = 0; k < ARRAYLEN(A); ++k) {
          memcpy(m->dx, &A[i], 4);
          memcpy(m->ax, &A[j], 4);
          memcpy(m->cx, &A[k], 4);
          if (!setjmp(m->onhalt)) {
            gotthrow = false;
            OpDivRdxRaxEvqpSigned(m, MOD(3) | RM(CX));
          } else {
            gotthrow = true;
          }
          if (!setjmp(sigfpejmp)) {
            gotsigfpe = false;
            asm("idivl\t%2"
                : "=d"(remainder), "=a"(quotient)
                : "r"(A[k]), "0"(A[i]), "1"(A[j])
                : "cc");
          } else {
            gotsigfpe = true;
          }
          EXPECT_EQ(gotsigfpe, gotthrow);
          if (!gotsigfpe && !gotthrow) {
            EXPECT_EQ(quotient, (int32_t)Read32(m->ax));
            EXPECT_EQ(remainder, (int32_t)Read32(m->dx));
          }
        }
      }
    }
  }
  
  TEST(idiv64, test) {
    if (IsWindows()) return; /* TODO */
    static const uint64_t A[] = {0x0000000000000000, 0x0000000000000001,
                                 0x8000000000000000, 0x7FFFFFFFFFFFFFFF,
                                 0x8000000000000001, 0x7FFFFFFFFFFFFFFE,
                                 0xFFFFFFFFFFFFFFFF, 0x00DeadBeefCafe00};
    bool gotthrow, gotsigfpe;
    int64_t i, j, k, w, x, a, b;
    int64_t quotient, remainder;
    for (i = 0; i < ARRAYLEN(A); ++i) {
      for (j = 0; j < ARRAYLEN(A); ++j) {
        for (k = 0; k < ARRAYLEN(A); ++k) {
          memcpy(m->dx, &A[i], 8);
          memcpy(m->ax, &A[j], 8);
          memcpy(m->cx, &A[k], 8);
          if (!setjmp(m->onhalt)) {
            gotthrow = false;
            OpDivRdxRaxEvqpSigned(m, REXW | MOD(3) | RM(CX));
          } else {
            gotthrow = true;
          }
          if (!setjmp(sigfpejmp)) {
            gotsigfpe = false;
            asm("idivq\t%2"
                : "=d"(remainder), "=a"(quotient)
                : "r"(A[k]), "0"(A[i]), "1"(A[j])
                : "cc");
          } else {
            gotsigfpe = true;
          }
          EXPECT_EQ(gotsigfpe, gotthrow);
          if (!gotsigfpe && !gotthrow) {
            EXPECT_EQ(quotient, (int64_t)Read64(m->ax));
            EXPECT_EQ(remainder, (int64_t)Read64(m->dx));
          }
        }
      }
    }
  }
  
  TEST(div, test) {
    if (IsWindows()) return; /* TODO */
    static const uint8_t A[] = {0x00, 0x01, 0x80, 0x7F, 0x81, 0x7E, 0xFF, 0xBF};
    uint16_t remquo;
    bool gotthrow, gotsigfpe;
    uint8_t i, j, k, w, x, a, b;
    uint8_t quotient, remainder;
    for (i = 0; i < ARRAYLEN(A); ++i) {
      for (j = 0; j < ARRAYLEN(A); ++j) {
        for (k = 0; k < ARRAYLEN(A); ++k) {
          m->ax[1] = A[i];
          m->ax[0] = A[j];
          m->cx[0] = A[k];
          gotthrow = false;
          gotsigfpe = false;
          if (!setjmp(m->onhalt)) {
            OpDivAlAhAxEbUnsigned(m, MOD(3) | RM(CX));
          } else {
            gotthrow = true;
          }
          if (!setjmp(sigfpejmp)) {
            asm("divb\t%1"
                : "=a"(remquo)
                : "q"(A[k]), "0"((uint16_t)(A[i] << 8 | A[j]))
                : "cc");
          } else {
            gotsigfpe = true;
          }
          EXPECT_EQ(gotsigfpe, gotthrow);
          if (!gotsigfpe && !gotthrow) {
            quotient = (uint8_t)remquo;
            remainder = (uint8_t)(remquo >> 8);
            EXPECT_EQ(quotient, (uint8_t)m->ax[0]);
            EXPECT_EQ(remainder, (uint8_t)m->ax[1]);
          }
        }
      }
    }
  }
  
  TEST(div16, test) {
    if (IsWindows()) return; /* TODO */
    static const uint16_t A[] = {0x0000, 0x0001, 0x8000, 0x7FFF,
                                 0x8001, 0x7FFE, 0xFFFF, 0xBeef};
    bool gotthrow, gotsigfpe;
    uint16_t i, j, k, w, x, a, b;
    uint16_t quotient, remainder;
    for (i = 0; i < ARRAYLEN(A); ++i) {
      for (j = 0; j < ARRAYLEN(A); ++j) {
        for (k = 0; k < ARRAYLEN(A); ++k) {
          memcpy(m->dx, &A[i], 2);
          memcpy(m->ax, &A[j], 2);
          memcpy(m->cx, &A[k], 2);
          if (!setjmp(m->onhalt)) {
            gotthrow = false;
            OpDivRdxRaxEvqpUnsigned(m, OSZ | MOD(3) | RM(CX));
          } else {
            gotthrow = true;
          }
          if (!setjmp(sigfpejmp)) {
            gotsigfpe = false;
            asm("divw\t%2"
                : "=d"(remainder), "=a"(quotient)
                : "r"(A[k]), "0"(A[i]), "1"(A[j])
                : "cc");
          } else {
            gotsigfpe = true;
          }
          EXPECT_EQ(gotsigfpe, gotthrow);
          if (!gotsigfpe && !gotthrow) {
            EXPECT_EQ(quotient, (uint16_t)Read16(m->ax));
            EXPECT_EQ(remainder, (uint16_t)Read16(m->dx));
          }
        }
      }
    }
  }
  
  TEST(div32, test) {
    if (IsWindows()) return; /* TODO */
    static const uint32_t A[] = {0x00000000, 0x00000001, 0x80000000, 0x7FFFFFFF,
                                 0x80000001, 0x7FFFFFFE, 0xFFFFFFFF, 0xDeadBeef};
    bool gotthrow, gotsigfpe;
    uint32_t i, j, k, w, x, a, b;
    uint32_t quotient, remainder;
    for (i = 0; i < ARRAYLEN(A); ++i) {
      for (j = 0; j < ARRAYLEN(A); ++j) {
        for (k = 0; k < ARRAYLEN(A); ++k) {
          memcpy(m->dx, &A[i], 4);
          memcpy(m->ax, &A[j], 4);
          memcpy(m->cx, &A[k], 4);
          if (!setjmp(m->onhalt)) {
            gotthrow = false;
            OpDivRdxRaxEvqpUnsigned(m, MOD(3) | RM(CX));
          } else {
            gotthrow = true;
          }
          if (!setjmp(sigfpejmp)) {
            gotsigfpe = false;
            asm("divl\t%2"
                : "=d"(remainder), "=a"(quotient)
                : "r"(A[k]), "0"(A[i]), "1"(A[j])
                : "cc");
          } else {
            gotsigfpe = true;
          }
          EXPECT_EQ(gotsigfpe, gotthrow);
          if (!gotsigfpe && !gotthrow) {
            EXPECT_EQ(quotient, (uint32_t)Read32(m->ax));
            EXPECT_EQ(remainder, (uint32_t)Read32(m->dx));
          }
        }
      }
    }
  }
  
  TEST(div64, test) {
    if (IsWindows()) return; /* TODO */
    static const uint64_t A[] = {0x0000000000000000, 0x0000000000000001,
                                 0x8000000000000000, 0x7FFFFFFFFFFFFFFF,
                                 0x8000000000000001, 0x7FFFFFFFFFFFFFFE,
                                 0xFFFFFFFFFFFFFFFF, 0x00DeadBeefCafe00};
    bool gotthrow, gotsigfpe;
    uint64_t i, j, k, w, x, a, b;
    uint64_t quotient, remainder;
    for (i = 0; i < ARRAYLEN(A); ++i) {
      for (j = 0; j < ARRAYLEN(A); ++j) {
        for (k = 0; k < ARRAYLEN(A); ++k) {
          memcpy(m->dx, &A[i], 8);
          memcpy(m->ax, &A[j], 8);
          memcpy(m->cx, &A[k], 8);
          if (!setjmp(m->onhalt)) {
            gotthrow = false;
            OpDivRdxRaxEvqpUnsigned(m, REXW | MOD(3) | RM(CX));
          } else {
            gotthrow = true;
          }
          if (!setjmp(sigfpejmp)) {
            gotsigfpe = false;
            asm("divq\t%2"
                : "=d"(remainder), "=a"(quotient)
                : "r"(A[k]), "0"(A[i]), "1"(A[j])
                : "cc");
          } else {
            gotsigfpe = true;
          }
          EXPECT_EQ(gotsigfpe, gotthrow);
          if (!gotsigfpe && !gotthrow) {
            EXPECT_EQ(quotient, (uint64_t)Read64(m->ax));
            EXPECT_EQ(remainder, (uint64_t)Read64(m->dx));
          }
        }
      }
    }
  }
  