From 06b749ae0362bf0f28b93ad87021db1fe7c6ff3b Mon Sep 17 00:00:00 2001 From: Justine Tunney <jtunney@gmail.com> Date: Sun, 11 Jun 2023 03:10:58 -0700 Subject: [PATCH] Remove blinkenlights New home: https://github.com/jart/blink --- test/tool/build/lib/alu_test.c | 139 -- test/tool/build/lib/bitscan_test.c | 108 - test/tool/build/lib/bsu_test.c | 329 --- test/tool/build/lib/disinst_test.c | 263 --- test/tool/build/lib/divmul_test.c | 556 ----- test/tool/build/lib/iovs_test.c | 84 - test/tool/build/lib/machine_test.c | 348 --- test/tool/build/lib/modrm_test.c | 110 - test/tool/build/lib/numbers.c | 56 - test/tool/build/lib/numbers.h | 10 - test/tool/build/lib/optest.c | 96 - test/tool/build/lib/optest.h | 21 - test/tool/build/lib/pty_test.c | 235 -- test/tool/build/lib/xlaterrno_test.c | 26 - tool/build/blinkenlights.c | 3180 -------------------------- tool/build/build.mk | 15 - tool/build/dis.c | 318 --- tool/build/emubin/emubin.mk | 68 - tool/build/emubin/linmap.c | 31 - tool/build/emubin/mdatest.real.c | 44 - tool/build/emubin/metalsha256.c | 154 -- tool/build/emubin/metalsha256.h | 19 - tool/build/emubin/mips.c | 49 - tool/build/emubin/pi.c | 55 - tool/build/emubin/poke.h | 11 - tool/build/emubin/prime.c | 41 - tool/build/emubin/real.h | 18 - tool/build/emubin/realstart.inc | 7 - tool/build/emubin/sha256.c | 52 - tool/build/emubin/spiral.c | 138 -- tool/build/emucrt/emucrt.S | 31 - tool/build/emucrt/emucrt.lds | 80 - tool/build/emucrt/emucrt.mk | 18 - tool/build/emucrt/real.lds | 38 - tool/build/lib/abp.h | 9 - tool/build/lib/address.c | 88 - tool/build/lib/address.h | 29 - tool/build/lib/alu.c | 763 ------ tool/build/lib/alu.h | 118 - tool/build/lib/argv.c | 75 - tool/build/lib/argv.h | 11 - tool/build/lib/bcd.c | 77 - tool/build/lib/bcd.h | 15 - tool/build/lib/bitscan.c | 145 -- tool/build/lib/bitscan.h | 15 - tool/build/lib/breakpoint.c | 56 - tool/build/lib/breakpoint.h | 22 - tool/build/lib/breg.c | 36 - tool/build/lib/cga.c | 56 - tool/build/lib/cga.h | 12 - tool/build/lib/clmul.c | 52 - tool/build/lib/clmul.h | 11 - tool/build/lib/cpuid.c | 88 - tool/build/lib/cpuid.h | 11 - tool/build/lib/cvt.c | 458 ---- tool/build/lib/cvt.h | 16 - tool/build/lib/debug.c | 47 - tool/build/lib/dis.c | 296 --- tool/build/lib/dis.h | 74 - tool/build/lib/disarg.c | 747 ------ tool/build/lib/diself.c | 220 -- tool/build/lib/disinst.c | 215 -- tool/build/lib/disspec.c | 1116 --------- tool/build/lib/divmul.c | 369 --- tool/build/lib/divmul.h | 20 - tool/build/lib/fds.c | 48 - tool/build/lib/fds.h | 38 - tool/build/lib/flags.c | 63 - tool/build/lib/flags.h | 71 - tool/build/lib/fpu.c | 1190 ---------- tool/build/lib/fpu.h | 65 - tool/build/lib/high.c | 41 - tool/build/lib/high.h | 23 - tool/build/lib/instruction.c | 92 - tool/build/lib/ioports.c | 115 - tool/build/lib/ioports.h | 12 - tool/build/lib/iovs.c | 66 - tool/build/lib/iovs.h | 19 - tool/build/lib/ldbl.c | 49 - tool/build/lib/ldbl.h | 11 - tool/build/lib/loader.c | 227 -- tool/build/lib/loader.h | 23 - tool/build/lib/machine.c | 2245 ------------------ tool/build/lib/machine.h | 206 -- tool/build/lib/mda.c | 70 - tool/build/lib/mda.h | 11 - tool/build/lib/memory.c | 288 --- tool/build/lib/memory.h | 34 - tool/build/lib/memorymalloc.c | 224 -- tool/build/lib/message.c | 66 - tool/build/lib/modrm.c | 324 --- tool/build/lib/modrm.h | 100 - tool/build/lib/op101.c | 216 -- tool/build/lib/op101.h | 11 - tool/build/lib/pml4t.c | 62 - tool/build/lib/pml4t.h | 25 - tool/build/lib/pml4tfmt.c | 118 - tool/build/lib/pty.c | 1407 ------------ tool/build/lib/pty.h | 82 - tool/build/lib/pun.h | 28 - tool/build/lib/reset.c | 96 - tool/build/lib/signal.c | 165 -- tool/build/lib/signal.h | 15 - tool/build/lib/sse.c | 1575 ------------- tool/build/lib/sse.h | 87 - tool/build/lib/ssefloat.c | 719 ------ tool/build/lib/ssefloat.h | 37 - tool/build/lib/ssemov.c | 518 ----- tool/build/lib/ssemov.h | 30 - tool/build/lib/stack.c | 314 --- tool/build/lib/stack.h | 27 - tool/build/lib/stats.c | 23 - tool/build/lib/stats.h | 12 - tool/build/lib/string.c | 285 --- tool/build/lib/string.h | 28 - tool/build/lib/syscall.c | 1423 ------------ tool/build/lib/syscall.h | 14 - tool/build/lib/throw.c | 69 - tool/build/lib/throw.h | 16 - tool/build/lib/time.c | 69 - tool/build/lib/time.h | 14 - tool/build/lib/word.c | 64 - tool/build/lib/word.h | 16 - tool/build/lib/xlat.c | 1002 -------- tool/build/lib/xlat.h | 53 - tool/build/lib/xlaterrno.c | 40 - tool/build/lib/xmmtype.c | 186 -- tool/build/lib/xmmtype.h | 21 - tool/build/tinyemu.c | 60 - tool/build/unbuffer.c | 4 +- 130 files changed, 2 insertions(+), 26665 deletions(-) delete mode 100644 test/tool/build/lib/alu_test.c delete mode 100644 test/tool/build/lib/bitscan_test.c delete mode 100644 test/tool/build/lib/bsu_test.c delete mode 100644 test/tool/build/lib/disinst_test.c delete mode 100644 test/tool/build/lib/divmul_test.c delete mode 100644 test/tool/build/lib/iovs_test.c delete mode 100644 test/tool/build/lib/machine_test.c delete mode 100644 test/tool/build/lib/modrm_test.c delete mode 100644 test/tool/build/lib/numbers.c delete mode 100644 test/tool/build/lib/numbers.h delete mode 100644 test/tool/build/lib/optest.c delete mode 100644 test/tool/build/lib/optest.h delete mode 100644 test/tool/build/lib/pty_test.c delete mode 100644 test/tool/build/lib/xlaterrno_test.c delete mode 100644 tool/build/blinkenlights.c delete mode 100644 tool/build/dis.c delete mode 100644 tool/build/emubin/emubin.mk delete mode 100644 tool/build/emubin/linmap.c delete mode 100644 tool/build/emubin/mdatest.real.c delete mode 100644 tool/build/emubin/metalsha256.c delete mode 100644 tool/build/emubin/metalsha256.h delete mode 100644 tool/build/emubin/mips.c delete mode 100644 tool/build/emubin/pi.c delete mode 100644 tool/build/emubin/poke.h delete mode 100644 tool/build/emubin/prime.c delete mode 100644 tool/build/emubin/real.h delete mode 100644 tool/build/emubin/realstart.inc delete mode 100644 tool/build/emubin/sha256.c delete mode 100644 tool/build/emubin/spiral.c delete mode 100644 tool/build/emucrt/emucrt.S delete mode 100644 tool/build/emucrt/emucrt.lds delete mode 100644 tool/build/emucrt/emucrt.mk delete mode 100644 tool/build/emucrt/real.lds delete mode 100644 tool/build/lib/abp.h delete mode 100644 tool/build/lib/address.c delete mode 100644 tool/build/lib/address.h delete mode 100644 tool/build/lib/alu.c delete mode 100644 tool/build/lib/alu.h delete mode 100644 tool/build/lib/argv.c delete mode 100644 tool/build/lib/argv.h delete mode 100644 tool/build/lib/bcd.c delete mode 100644 tool/build/lib/bcd.h delete mode 100644 tool/build/lib/bitscan.c delete mode 100644 tool/build/lib/bitscan.h delete mode 100644 tool/build/lib/breakpoint.c delete mode 100644 tool/build/lib/breakpoint.h delete mode 100644 tool/build/lib/breg.c delete mode 100644 tool/build/lib/cga.c delete mode 100644 tool/build/lib/cga.h delete mode 100644 tool/build/lib/clmul.c delete mode 100644 tool/build/lib/clmul.h delete mode 100644 tool/build/lib/cpuid.c delete mode 100644 tool/build/lib/cpuid.h delete mode 100644 tool/build/lib/cvt.c delete mode 100644 tool/build/lib/cvt.h delete mode 100644 tool/build/lib/debug.c delete mode 100644 tool/build/lib/dis.c delete mode 100644 tool/build/lib/dis.h delete mode 100644 tool/build/lib/disarg.c delete mode 100644 tool/build/lib/diself.c delete mode 100644 tool/build/lib/disinst.c delete mode 100644 tool/build/lib/disspec.c delete mode 100644 tool/build/lib/divmul.c delete mode 100644 tool/build/lib/divmul.h delete mode 100644 tool/build/lib/fds.c delete mode 100644 tool/build/lib/fds.h delete mode 100644 tool/build/lib/flags.c delete mode 100644 tool/build/lib/flags.h delete mode 100644 tool/build/lib/fpu.c delete mode 100644 tool/build/lib/fpu.h delete mode 100644 tool/build/lib/high.c delete mode 100644 tool/build/lib/high.h delete mode 100644 tool/build/lib/instruction.c delete mode 100644 tool/build/lib/ioports.c delete mode 100644 tool/build/lib/ioports.h delete mode 100644 tool/build/lib/iovs.c delete mode 100644 tool/build/lib/iovs.h delete mode 100644 tool/build/lib/ldbl.c delete mode 100644 tool/build/lib/ldbl.h delete mode 100644 tool/build/lib/loader.c delete mode 100644 tool/build/lib/loader.h delete mode 100644 tool/build/lib/machine.c delete mode 100644 tool/build/lib/machine.h delete mode 100644 tool/build/lib/mda.c delete mode 100644 tool/build/lib/mda.h delete mode 100644 tool/build/lib/memory.c delete mode 100644 tool/build/lib/memory.h delete mode 100644 tool/build/lib/memorymalloc.c delete mode 100644 tool/build/lib/message.c delete mode 100644 tool/build/lib/modrm.c delete mode 100644 tool/build/lib/modrm.h delete mode 100644 tool/build/lib/op101.c delete mode 100644 tool/build/lib/op101.h delete mode 100644 tool/build/lib/pml4t.c delete mode 100644 tool/build/lib/pml4t.h delete mode 100644 tool/build/lib/pml4tfmt.c delete mode 100644 tool/build/lib/pty.c delete mode 100644 tool/build/lib/pty.h delete mode 100644 tool/build/lib/pun.h delete mode 100644 tool/build/lib/reset.c delete mode 100644 tool/build/lib/signal.c delete mode 100644 tool/build/lib/signal.h delete mode 100644 tool/build/lib/sse.c delete mode 100644 tool/build/lib/sse.h delete mode 100644 tool/build/lib/ssefloat.c delete mode 100644 tool/build/lib/ssefloat.h delete mode 100644 tool/build/lib/ssemov.c delete mode 100644 tool/build/lib/ssemov.h delete mode 100644 tool/build/lib/stack.c delete mode 100644 tool/build/lib/stack.h delete mode 100644 tool/build/lib/stats.c delete mode 100644 tool/build/lib/stats.h delete mode 100644 tool/build/lib/string.c delete mode 100644 tool/build/lib/string.h delete mode 100644 tool/build/lib/syscall.c delete mode 100644 tool/build/lib/syscall.h delete mode 100644 tool/build/lib/throw.c delete mode 100644 tool/build/lib/throw.h delete mode 100644 tool/build/lib/time.c delete mode 100644 tool/build/lib/time.h delete mode 100644 tool/build/lib/word.c delete mode 100644 tool/build/lib/word.h delete mode 100644 tool/build/lib/xlat.c delete mode 100644 tool/build/lib/xlat.h delete mode 100644 tool/build/lib/xlaterrno.c delete mode 100644 tool/build/lib/xmmtype.c delete mode 100644 tool/build/lib/xmmtype.h delete mode 100644 tool/build/tinyemu.c diff --git a/test/tool/build/lib/alu_test.c b/test/tool/build/lib/alu_test.c deleted file mode 100644 index d92033680..000000000 --- a/test/tool/build/lib/alu_test.c +++ /dev/null @@ -1,139 +0,0 @@ -/*-*- 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 "tool/build/lib/alu.h" -#include "libc/assert.h" -#include "libc/limits.h" -#include "libc/runtime/runtime.h" -#include "libc/stdio/stdio.h" -#include "libc/testlib/ezbench.h" -#include "libc/testlib/testlib.h" -#include "test/tool/build/lib/optest.h" -#include "tool/build/lib/case.h" -#include "tool/build/lib/flags.h" -#ifdef __x86_64__ - -#define ALU_TEST 8 - -#define NATIVE_ALU2(MODE, INSTRUCTION) \ - do { \ - intptr_t flags; \ - asm("pushf\n\t" \ - "andl\t%3,(%%rsp)\n\t" \ - "orl\t%4,(%%rsp)\n\t" \ - "popf\n\t" INSTRUCTION "\t%" MODE "2,%" MODE "0\n\t" \ - "pushf\n\t" \ - "pop\t%q1" \ - : "+r"(x), "=rm"(flags) \ - : "r"(y), "i"(~FMASK), "r"(*f & FMASK) \ - : "cc"); \ - *f = flags; \ - } while (0) - -#define NATIVE_ALU2_ANYBITS(INSTRUCTION, MUTATING) \ - switch (w) { \ - case 0: \ - NATIVE_ALU2("b", INSTRUCTION); \ - if (MUTATING) x &= 0xff; \ - return x; \ - case 1: \ - NATIVE_ALU2("w", INSTRUCTION); \ - if (MUTATING) x &= 0xffff; \ - return x; \ - case 2: \ - NATIVE_ALU2("k", INSTRUCTION); \ - return x; \ - case 3: \ - NATIVE_ALU2("q", INSTRUCTION); \ - return x; \ - default: \ - abort(); \ - } - -int64_t RunGolden(char w, int h, uint64_t x, uint64_t y, uint32_t *f) { - bool rw; - rw = !(h & ALU_TEST); - switch (h & 7) { - case ALU_OR: - NATIVE_ALU2_ANYBITS("or", rw); - case ALU_AND: - if (rw) { - NATIVE_ALU2_ANYBITS("and", rw); - } else { - NATIVE_ALU2_ANYBITS("test", rw); - } - case ALU_XOR: - NATIVE_ALU2_ANYBITS("xor", rw); - case ALU_SBB: - NATIVE_ALU2_ANYBITS("sbb", rw); - case ALU_CMP: - rw = false; - NATIVE_ALU2_ANYBITS("cmp", rw); - case ALU_SUB: - NATIVE_ALU2_ANYBITS("sub", rw); - case ALU_ADC: - NATIVE_ALU2_ANYBITS("adc", rw); - case ALU_ADD: - NATIVE_ALU2_ANYBITS("add", rw); - default: - abort(); - } -} - -const uint8_t kAluOps[] = { - ALU_ADD, // - ALU_OR, // - ALU_ADC, // - ALU_SBB, // - ALU_AND, // - ALU_SUB, // - ALU_XOR, // - ALU_CMP, // - ALU_AND | ALU_TEST, // -}; - -const char *const kAluNames[] = { - [ALU_ADD] = "add", // - [ALU_OR] = "or", // - [ALU_ADC] = "adc", // - [ALU_SBB] = "sbb", // - [ALU_AND] = "and", // - [ALU_SUB] = "sub", // - [ALU_XOR] = "xor", // - [ALU_CMP] = "cmp", // - [ALU_AND | ALU_TEST] = "test", // -}; - -int64_t Alu(int w, int h, uint64_t x, uint64_t y, uint32_t *flags) { - if (h < ALU_CMP) { - return kAlu[h][w](x, y, flags); - } else { - kAlu[h & 7][w](x, y, flags); - return x; - } -} - -int64_t RunOpTest(char w, int h, uint64_t x, uint64_t y, uint32_t *f) { - return Alu(w, h, x, y, f); -} - -TEST(alu, test) { - RunOpTests(kAluOps, ARRAYLEN(kAluOps), kAluNames); -} - -#endif /* __x86_64__ */ diff --git a/test/tool/build/lib/bitscan_test.c b/test/tool/build/lib/bitscan_test.c deleted file mode 100644 index 9e718f34e..000000000 --- a/test/tool/build/lib/bitscan_test.c +++ /dev/null @@ -1,108 +0,0 @@ -/*-*- 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 "tool/build/lib/bitscan.h" -#include "libc/macros.internal.h" -#include "libc/testlib/testlib.h" -#include "test/tool/build/lib/numbers.h" -#include "tool/build/lib/flags.h" -#ifdef __x86_64__ - -#define OSZ 00000000040 -#define REXW 00000000100 - -struct Machine m[1]; -struct XedDecodedInst xedd[1]; - -void SetUp(void) { - m->xedd = xedd; -} - -TEST(bsr64, test) { - bool zf; - uint64_t i, w, x, a, b; - for (i = 0; i < ARRAYLEN(kNumbers); ++i) { - x = kNumbers[i]; - a = AluBsr(m, REXW, x); - asm("bsrq\t%2,%0" : "=r"(b), "=@ccz"(zf) : "r"(x)); - ASSERT_EQ(zf, GetFlag(m->flags, FLAGS_ZF)); - if (!zf) ASSERT_EQ(a, b); - } -} - -TEST(bsr32, test) { - bool zf; - uint32_t i, w, x, a, b; - for (i = 0; i < ARRAYLEN(kNumbers); ++i) { - x = kNumbers[i]; - a = AluBsr(m, 0, x); - asm("bsrl\t%2,%0" : "=r"(b), "=@ccz"(zf) : "r"(x)); - ASSERT_EQ(zf, GetFlag(m->flags, FLAGS_ZF)); - if (!zf) ASSERT_EQ(a, b); - } -} - -TEST(bsr16, test) { - bool zf; - uint16_t i, w, x, a, b; - for (i = 0; i < ARRAYLEN(kNumbers); ++i) { - x = kNumbers[i]; - a = AluBsr(m, OSZ, x); - asm("bsrw\t%2,%0" : "=r"(b), "=@ccz"(zf) : "r"(x)); - ASSERT_EQ(zf, GetFlag(m->flags, FLAGS_ZF)); - if (!zf) ASSERT_EQ(a, b); - } -} - -TEST(bsf64, test) { - bool zf; - uint64_t i, w, x, a, b; - for (i = 0; i < ARRAYLEN(kNumbers); ++i) { - x = kNumbers[i]; - a = AluBsf(m, REXW, x); - asm("bsfq\t%2,%0" : "=r"(b), "=@ccz"(zf) : "r"(x)); - ASSERT_EQ(zf, GetFlag(m->flags, FLAGS_ZF)); - if (!zf) ASSERT_EQ(a, b); - } -} - -TEST(bsf32, test) { - bool zf; - uint32_t i, w, x, a, b; - for (i = 0; i < ARRAYLEN(kNumbers); ++i) { - x = kNumbers[i]; - a = AluBsf(m, 0, x); - asm("bsfl\t%2,%0" : "=r"(b), "=@ccz"(zf) : "r"(x)); - ASSERT_EQ(zf, GetFlag(m->flags, FLAGS_ZF)); - if (!zf) ASSERT_EQ(a, b); - } -} - -TEST(bsf16, test) { - bool zf; - uint16_t i, w, x, a, b; - for (i = 0; i < ARRAYLEN(kNumbers); ++i) { - x = kNumbers[i]; - a = AluBsf(m, OSZ, x); - asm("bsfw\t%2,%0" : "=r"(b), "=@ccz"(zf) : "r"(x)); - ASSERT_EQ(zf, GetFlag(m->flags, FLAGS_ZF)); - if (!zf) ASSERT_EQ(a, b, "%#lx", x); - } -} - -#endif /* __x86_64__ */ diff --git a/test/tool/build/lib/bsu_test.c b/test/tool/build/lib/bsu_test.c deleted file mode 100644 index 0ce18839a..000000000 --- a/test/tool/build/lib/bsu_test.c +++ /dev/null @@ -1,329 +0,0 @@ -/*-*- 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/macros.internal.h" -#include "libc/runtime/runtime.h" -#include "libc/stdio/stdio.h" -#include "libc/testlib/testlib.h" -#include "test/tool/build/lib/numbers.h" -#include "test/tool/build/lib/optest.h" -#include "tool/build/lib/alu.h" -#include "tool/build/lib/flags.h" -#include "tool/build/lib/machine.h" -#ifdef __x86_64__ - -#define NATIVE_ALU2(MODE, INSTRUCTION) \ - asm("pushf\n\t" \ - "andl\t%3,(%%rsp)\n\t" \ - "orl\t%4,(%%rsp)\n\t" \ - "popf\n\t" INSTRUCTION "\t%b2,%" MODE "0\n\t" \ - "pushf\n\t" \ - "pop\t%q1" \ - : "+r"(x), "=r"(*f) \ - : "c"(y), "i"(~FMASK), "r"(*f & FMASK) \ - : "cc") - -#define NATIVE_ALU2_ANYBITS(INSTRUCTION, MUTATING) \ - switch (w) { \ - case 0: \ - NATIVE_ALU2("b", INSTRUCTION); \ - if (MUTATING) x &= 0xff; \ - return x; \ - case 1: \ - NATIVE_ALU2("w", INSTRUCTION); \ - if (MUTATING) x &= 0xffff; \ - return x; \ - case 2: \ - NATIVE_ALU2("k", INSTRUCTION); \ - return x; \ - case 3: \ - NATIVE_ALU2("q", INSTRUCTION); \ - return x; \ - default: \ - abort(); \ - } - -int64_t Bsu(int w, int h, uint64_t x, uint64_t y, uint32_t *f) { - switch (h & 7) { - case BSU_SHR: - switch (w) { - case 0: - return Shr8(x, y, f); - case 1: - return Shr16(x, y, f); - case 2: - return Shr32(x, y, f); - case 3: - return Shr64(x, y, f); - default: - __builtin_unreachable(); - } - case BSU_SAL: - case BSU_SHL: - switch (w) { - case 0: - return Shl8(x, y, f); - case 1: - return Shl16(x, y, f); - case 2: - return Shl32(x, y, f); - case 3: - return Shl64(x, y, f); - default: - __builtin_unreachable(); - } - case BSU_SAR: - switch (w) { - case 0: - return Sar8(x, y, f); - case 1: - return Sar16(x, y, f); - case 2: - return Sar32(x, y, f); - case 3: - return Sar64(x, y, f); - default: - __builtin_unreachable(); - } - case BSU_ROL: - switch (w) { - case 0: - return Rol8(x, y, f); - case 1: - return Rol16(x, y, f); - case 2: - return Rol32(x, y, f); - case 3: - return Rol64(x, y, f); - default: - __builtin_unreachable(); - } - case BSU_ROR: - switch (w) { - case 0: - return Ror8(x, y, f); - case 1: - return Ror16(x, y, f); - case 2: - return Ror32(x, y, f); - case 3: - return Ror64(x, y, f); - default: - __builtin_unreachable(); - } - case BSU_RCR: - switch (w) { - case 0: - return Rcr8(x, y, f); - case 1: - return Rcr16(x, y, f); - case 2: - return Rcr32(x, y, f); - case 3: - return Rcr64(x, y, f); - default: - __builtin_unreachable(); - } - case BSU_RCL: - switch (w) { - case 0: - return Rcl8(x, y, f); - case 1: - return Rcl16(x, y, f); - case 2: - return Rcl32(x, y, f); - case 3: - return Rcl64(x, y, f); - default: - __builtin_unreachable(); - } - default: - __builtin_unreachable(); - } -} - -int64_t RunGolden(char w, int h, uint64_t x, uint64_t y, uint32_t *f) { - switch (h & 7) { - case BSU_ROR: - NATIVE_ALU2_ANYBITS("ror", true); - case BSU_SHL: - NATIVE_ALU2_ANYBITS("shl", true); - case BSU_SAL: - NATIVE_ALU2_ANYBITS("sal", true); - case BSU_RCR: - NATIVE_ALU2_ANYBITS("rcr", true); - case BSU_SAR: - NATIVE_ALU2_ANYBITS("sar", true); - case BSU_SHR: - NATIVE_ALU2_ANYBITS("shr", true); - case BSU_RCL: - NATIVE_ALU2_ANYBITS("rcl", true); - case BSU_ROL: - NATIVE_ALU2_ANYBITS("rol", true); - default: - abort(); - } -} - -const uint8_t kBsuOps[] = { - BSU_SHR, BSU_SHL, BSU_ROL, BSU_ROR, BSU_RCL, - BSU_RCR, BSU_SHL, BSU_SAL, BSU_SAR, -}; - -const char *const kBsuNames[] = { - [BSU_ROL] = "rol", [BSU_ROR] = "ror", [BSU_RCL] = "rcl", [BSU_RCR] = "rcr", - [BSU_SHL] = "shl", [BSU_SHR] = "shr", [BSU_SAL] = "sal", [BSU_SAR] = "sar", -}; - -int64_t RunOpTest(char w, int h, uint64_t x, uint64_t y, uint32_t *f) { - return Bsu(w, h, x, y, f); -} - -void FixupUndefOpTestFlags(char w, int h, uint64_t x, uint64_t y, - uint32_t goldenflags, uint32_t *flags) { - y &= w == 3 ? 0x3F : 0x1F; - if (y != 0 && y != 1) { - *flags = SetFlag(*flags, FLAGS_OF, GetFlag(goldenflags, FLAGS_OF)); - } - if (y >= w) { - *flags = SetFlag(*flags, FLAGS_CF, GetFlag(goldenflags, FLAGS_CF)); - } -} - -TEST(bsu, test) { - RunOpTests(kBsuOps, ARRAYLEN(kBsuOps), kBsuNames); -} - -TEST(shrd32, smoke) { - int i, j, k; - uint8_t b, cf, of; - uint32_t x, y, z1, f, z2, unflag; - for (i = 0; i < ARRAYLEN(kNumbers); ++i) { - x = kNumbers[i]; - for (j = 0; j < ARRAYLEN(kNumbers); ++j) { - y = kNumbers[j]; - for (k = 0; k < ARRAYLEN(kNumbers); ++k) { - f = 0; - cf = 0; - of = 0; - b = kNumbers[k]; - z1 = BsuDoubleShift(2, x, y, b, true, &f); - z2 = x; - asm("xor\t%1,%1\n\t" - "shrd\t%5,%4,%0" - : "+rm"(z2), "=&r"(unflag), "=@ccc"(cf), "=@cco"(of) - : "r"(y), "c"(b) - : "cc"); - ASSERT_EQ(z2, z1); - ASSERT_EQ(cf, GetFlag(f, FLAGS_CF)); - if (b <= 1) ASSERT_EQ(of, GetFlag(f, FLAGS_OF)); - } - } - } -} - -TEST(shld16, smoke) { - uint32_t f; - int i, j, k; - uint8_t b, cf, of; - uint16_t x, y, z1, z2, unflag; - for (i = 0; i < ARRAYLEN(kNumbers); ++i) { - x = kNumbers[i]; - for (j = 0; j < ARRAYLEN(kNumbers); ++j) { - y = kNumbers[j]; - for (k = 0; k < ARRAYLEN(kNumbers); ++k) { - f = 0; - cf = 0; - of = 0; - b = kNumbers[k]; - if (b > 16) continue; - z1 = BsuDoubleShift(1, x, y, b, false, &f); - z2 = x; - asm("xor\t%1,%1\n\t" - "shldw\t%5,%4,%0" - : "+rm"(z2), "=&r"(unflag), "=@ccc"(cf), "=@cco"(of) - : "r"(y), "c"(b) - : "cc"); - ASSERT_EQ(z2, z1); - ASSERT_EQ(cf, GetFlag(f, FLAGS_CF)); - if (b <= 1) ASSERT_EQ(of, GetFlag(f, FLAGS_OF)); - } - } - } -} - -TEST(shld32, smoke) { - int i, j, k; - uint8_t b, cf, of; - uint32_t x, y, z1, f, z2, unflag; - for (i = 0; i < ARRAYLEN(kNumbers); ++i) { - x = kNumbers[i]; - for (j = 0; j < ARRAYLEN(kNumbers); ++j) { - y = kNumbers[j]; - for (k = 0; k < ARRAYLEN(kNumbers); ++k) { - f = 0; - cf = 0; - of = 0; - b = kNumbers[k]; - if (b > 32) continue; - z1 = BsuDoubleShift(2, x, y, b, false, &f); - z2 = x; - asm("xor\t%1,%1\n\t" - "shld\t%5,%4,%0" - : "+rm"(z2), "=&r"(unflag), "=@ccc"(cf), "=@cco"(of) - : "r"(y), "c"(b) - : "cc"); - ASSERT_EQ(z2, z1); - ASSERT_EQ(cf, GetFlag(f, FLAGS_CF)); - if (b <= 1) ASSERT_EQ(of, GetFlag(f, FLAGS_OF)); - } - } - } -} - -TEST(shld64, smoke) { - uint32_t f; - int i, j, k; - uint8_t b, cf, of; - uint64_t x, y, z1, z2, unflag; - for (i = 0; i < ARRAYLEN(kNumbers); ++i) { - x = kNumbers[i]; - for (j = 0; j < ARRAYLEN(kNumbers); ++j) { - y = kNumbers[j]; - for (k = 0; k < ARRAYLEN(kNumbers); ++k) { - f = 0; - cf = 0; - of = 0; - b = kNumbers[k]; - if (b > 64) continue; - z1 = BsuDoubleShift(3, x, y, b, false, &f); - z2 = x; - asm("xor\t%1,%1\n\t" - "shldq\t%5,%4,%0" - : "+rm"(z2), "=&r"(unflag), "=@ccc"(cf), "=@cco"(of) - : "r"(y), "c"(b) - : "cc"); - ASSERT_EQ(z2, z1); - ASSERT_EQ(cf, GetFlag(f, FLAGS_CF)); - if (b <= 1) ASSERT_EQ(of, GetFlag(f, FLAGS_OF)); - } - } - } -} - -#endif /* __x86_64__ */ diff --git a/test/tool/build/lib/disinst_test.c b/test/tool/build/lib/disinst_test.c deleted file mode 100644 index 7cc355b05..000000000 --- a/test/tool/build/lib/disinst_test.c +++ /dev/null @@ -1,263 +0,0 @@ -/*-*- 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/stdio/lcg.internal.h" -#include "libc/stdio/rand.h" -#include "libc/stdio/stdio.h" -#include "libc/testlib/ezbench.h" -#include "libc/testlib/testlib.h" -#include "tool/build/lib/dis.h" -#include "tool/build/lib/modrm.h" - -char b1[64]; -char b2[64]; -struct Dis d[1]; - -#define ILD(OP, MODE) \ - do { \ - xed_decoded_inst_zero_set_mode(d->xedd, MODE); \ - ASSERT_EQ(0, xed_instruction_length_decode(d->xedd, OP, sizeof(OP))); \ - d->xedd->op.rde = EncodeRde(d->xedd); \ - } while (0) - -TEST(DisInst, testInt3) { - uint8_t op[] = {0xcc}; - ILD(op, XED_MACHINE_MODE_LONG_64); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("int3 ", b1); -} - -TEST(DisInst, testImmMem_needsSuffix) { - uint8_t op[] = {0x80, 0x3c, 0x07, 0x00}; - ILD(op, XED_MACHINE_MODE_LONG_64); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("cmpb $0,(%rdi,%rax)", b1); -} - -TEST(DisInst, testImmReg_doesntNeedSuffix) { - uint8_t op[] = {0xb8, 0x08, 0x70, 0x40, 0x00}; - ILD(op, XED_MACHINE_MODE_LONG_64); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("mov $0x407008,%eax", b1); -} - -TEST(DisInst, testPuttingOnTheRiz) { - static uint8_t ops[][15] = { - {0x8d, 0b00110100, 0b00100110}, - {0x67, 0x8d, 0b00110100, 0b11100110}, - {0x67, 0x8d, 0b10110100, 0b11100101, 0, 0, 0, 0}, - {0x8d, 0b00110100, 0b11100101, 0x37, 0x13, 0x03, 0}, - {0x8d, 0b10110100, 0b11100101, 0, 0, 0, 0}, - }; - ILD(ops[0], XED_MACHINE_MODE_LONG_64); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("lea (%rsi),%esi", b1); - ILD(ops[1], XED_MACHINE_MODE_LONG_64); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("lea (%esi,%eiz,8),%esi", b1); - ILD(ops[2], XED_MACHINE_MODE_LONG_64); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("lea 0(%ebp,%eiz,8),%esi", b1); - ILD(ops[3], XED_MACHINE_MODE_LONG_64); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("lea 0x31337,%esi", b1); - ILD(ops[4], XED_MACHINE_MODE_LONG_64); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("lea 0(%rbp,%riz,8),%esi", b1); -} - -TEST(DisInst, testSibIndexOnly) { - uint8_t op[] = {76, 141, 4, 141, 0, 0, 0, 0}; - ILD(op, XED_MACHINE_MODE_LONG_64); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("lea 0(,%rcx,4),%r8", b1); -} - -TEST(DisInst, testRealMode) { - uint8_t op[] = {0x89, 0xe5}; - ILD(op, XED_MACHINE_MODE_REAL); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("mov %sp,%bp", b1); -} - -TEST(DisInst, testNop) { - uint8_t op[] = {0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}; - ILD(op, XED_MACHINE_MODE_LONG_64); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("nopw %cs:0(%rax,%rax)", b1); -} - -TEST(DisInst, testPush) { - uint8_t op[] = {0x41, 0x5c}; - ILD(op, XED_MACHINE_MODE_LONG_64); - EXPECT_EQ(4, ModrmSrm(d->xedd->op.rde)); - EXPECT_EQ(1, Rexb(d->xedd->op.rde)); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("pop %r12", b1); -} - -TEST(DisInst, testMovb) { - uint8_t op[] = {0x8a, 0x1e, 0x0c, 0x32}; - ILD(op, XED_MACHINE_MODE_LONG_64); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("mov (%rsi),%bl", b1); - ILD(op, XED_MACHINE_MODE_REAL); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("mov 0x320c,%bl", b1); -} - -TEST(DisInst, testLes) { - uint8_t op[] = {0xc4, 0x3e, 0x16, 0x32}; - ILD(op, XED_MACHINE_MODE_REAL); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("les 0x3216,%di", b1); -} - -TEST(DisInst, testStosbLong) { - uint8_t op[] = {0xAA}; - ILD(op, XED_MACHINE_MODE_LONG_64); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("stosb %al,(%rdi)", b1); -} - -TEST(DisInst, testStosbReal) { - uint8_t op[] = {0xAA}; - ILD(op, XED_MACHINE_MODE_REAL); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("stosb %al,(%di)", b1); -} - -TEST(DisInst, testStosbLegacy) { - uint8_t op[] = {0xAA}; - ILD(op, XED_MACHINE_MODE_LEGACY_32); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("stosb %al,(%edi)", b1); -} - -TEST(DisInst, testStosbLongAsz) { - uint8_t op[] = {0x67, 0xAA}; - ILD(op, XED_MACHINE_MODE_LONG_64); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("stosb %al,(%edi)", b1); -} - -TEST(DisInst, testAddLong) { - uint8_t op[] = {0x01, 0xff}; - ILD(op, XED_MACHINE_MODE_LONG_64); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("add %edi,%edi", b1); -} - -TEST(DisInst, testAddLegacy) { - uint8_t op[] = {0x01, 0xff}; - ILD(op, XED_MACHINE_MODE_LEGACY_32); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("add %edi,%edi", b1); -} - -TEST(DisInst, testAddReal) { - uint8_t op[] = {0x01, 0xff}; - ILD(op, XED_MACHINE_MODE_REAL); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("add %di,%di", b1); -} - -TEST(DisInst, testAddLongOsz) { - uint8_t op[] = {0x66, 0x01, 0xff}; - ILD(op, XED_MACHINE_MODE_LONG_64); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("add %di,%di", b1); -} - -TEST(DisInst, testAddLegacyOsz) { - uint8_t op[] = {0x66, 0x01, 0xff}; - ILD(op, XED_MACHINE_MODE_LEGACY_32); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("add %di,%di", b1); -} - -TEST(DisInst, testAddRealOsz) { - uint8_t op[] = {0x66, 0x01, 0xff}; - ILD(op, XED_MACHINE_MODE_REAL); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("add %edi,%edi", b1); -} - -TEST(DisInst, testFxam) { - uint8_t op[] = {0xd9, 0xe5}; - ILD(op, XED_MACHINE_MODE_LONG_64); - ASSERT_EQ(4, ModrmReg(d->xedd->op.rde)); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("fxam ", b1); -} - -TEST(DisInst, testOrImmCode16gcc) { - uint8_t op[] = {0x67, 0x81, 0x4c, 0x24, 0x0c, 0x00, 0x0c}; - ILD(op, XED_MACHINE_MODE_REAL); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("orw $0xc00,12(%esp)", b1); -} - -TEST(DisInst, testPause) { - uint8_t op[] = {0xf3, 0x90}; - ILD(op, XED_MACHINE_MODE_LONG_64); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("pause ", b1); -} - -TEST(DisInst, testJmpEw) { - uint8_t op[] = {0xff, 0xe0}; - ILD(op, XED_MACHINE_MODE_REAL); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("jmp %ax", b1); -} - -TEST(DisInst, testJmpEv16) { - uint8_t op[] = {0x66, 0xff, 0xe0}; - ILD(op, XED_MACHINE_MODE_REAL); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("jmp %eax", b1); -} - -TEST(DisInst, testJmpEv32) { - uint8_t op[] = {0xff, 0xe0}; - ILD(op, XED_MACHINE_MODE_LEGACY_32); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("jmp %eax", b1); -} - -TEST(DisInst, testJmpEq) { - uint8_t op[] = {0x66, 0xff, 0xe0}; - ILD(op, XED_MACHINE_MODE_LONG_64); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("jmp %rax", b1); -} - -TEST(DisInst, testMovswSs) { - uint8_t op[] = {0x36, 0xA5}; - ILD(op, XED_MACHINE_MODE_REAL); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("movs %ss:(%si),(%di)", b1); -} - -TEST(DisInst, testRealModrm_sibOverlap_showsNoDisplacement) { - uint8_t op[] = {0x8b, 0b00100101}; - ILD(op, XED_MACHINE_MODE_REAL); - DisInst(d, b1, DisSpec(d->xedd, b2)); - EXPECT_STREQ("mov (%di),%sp", b1); -} diff --git a/test/tool/build/lib/divmul_test.c b/test/tool/build/lib/divmul_test.c deleted file mode 100644 index aaef0059e..000000000 --- a/test/tool/build/lib/divmul_test.c +++ /dev/null @@ -1,556 +0,0 @@ -/*-*- 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 "tool/build/lib/divmul.h" -#include "libc/calls/struct/sigaction.h" -#include "libc/macros.internal.h" -#include "libc/runtime/runtime.h" -#include "libc/str/str.h" -#include "libc/sysv/consts/sa.h" -#include "libc/sysv/consts/sig.h" -#include "libc/testlib/testlib.h" -#include "libc/x/xsigaction.h" -#include "third_party/xed/x86.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/flags.h" -#include "tool/build/lib/machine.h" -#ifdef __x86_64__ - -#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; - ASSERT_NE(-1, xsigaction(SIGFPE, OnSigFpe, SA_NODEFER, 0, oldsigfpe)); -} - -void TearDown(void) { - m->xedd = xedd; - ASSERT_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)); - } - } - } - } -} - -#endif /* __x86_64__ */ diff --git a/test/tool/build/lib/iovs_test.c b/test/tool/build/lib/iovs_test.c deleted file mode 100644 index 9f84a3eef..000000000 --- a/test/tool/build/lib/iovs_test.c +++ /dev/null @@ -1,84 +0,0 @@ -/*-*- 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/testlib/testlib.h" -#include "tool/build/lib/iovs.h" - -TEST(iovs, testEmpty) { - struct Iovs iv; - InitIovs(&iv); - EXPECT_EQ(0, iv.i); - EXPECT_GE(iv.n, iv.i); - FreeIovs(&iv); -} - -TEST(iovs, testAppendEmptyString_wontCreateEmptyEntries) { - struct Iovs iv; - InitIovs(&iv); - EXPECT_NE(-1, AppendIovs(&iv, "", 0)); - EXPECT_NE(-1, AppendIovs(&iv, NULL, 0)); - EXPECT_EQ(0, iv.i); - EXPECT_GE(iv.n, iv.i); - FreeIovs(&iv); -} - -TEST(iovs, testAppendContiguousVectors_coalescesAdjacentEntries) { - struct Iovs iv; - char buf[8], *b = buf; - InitIovs(&iv); - EXPECT_NE(-1, AppendIovs(&iv, b + 0, 4)); - EXPECT_NE(-1, AppendIovs(&iv, b + 4, 4)); - EXPECT_EQ(1, iv.i); - EXPECT_GE(iv.n, iv.i); - EXPECT_EQ(8, iv.p[0].iov_len); - EXPECT_EQ(b, iv.p[0].iov_base); - FreeIovs(&iv); -} - -TEST(iovs, testAppendNoncontiguousVectors_growsMemoryAndPreservesOrdering) { - struct Iovs iv; - char buf[8], *b = buf; - InitIovs(&iv); - EXPECT_NE(-1, AppendIovs(&iv, b + 0, 1)); - EXPECT_NE(-1, AppendIovs(&iv, b + 2, 1)); - EXPECT_NE(-1, AppendIovs(&iv, b + 4, 1)); - EXPECT_NE(-1, AppendIovs(&iv, b + 6, 1)); - EXPECT_NE(-1, AppendIovs(&iv, b + 1, 1)); - EXPECT_NE(-1, AppendIovs(&iv, b + 3, 1)); - EXPECT_NE(-1, AppendIovs(&iv, b + 5, 1)); - EXPECT_NE(-1, AppendIovs(&iv, b + 7, 1)); - EXPECT_EQ(8, iv.i); - EXPECT_GE(iv.n, iv.i); - EXPECT_EQ(b + 0, iv.p[0].iov_base); - EXPECT_EQ(1, iv.p[0].iov_len); - EXPECT_EQ(b + 2, iv.p[1].iov_base); - EXPECT_EQ(1, iv.p[1].iov_len); - EXPECT_EQ(b + 4, iv.p[2].iov_base); - EXPECT_EQ(1, iv.p[2].iov_len); - EXPECT_EQ(b + 6, iv.p[3].iov_base); - EXPECT_EQ(1, iv.p[3].iov_len); - EXPECT_EQ(b + 1, iv.p[4].iov_base); - EXPECT_EQ(1, iv.p[4].iov_len); - EXPECT_EQ(b + 3, iv.p[5].iov_base); - EXPECT_EQ(1, iv.p[5].iov_len); - EXPECT_EQ(b + 5, iv.p[6].iov_base); - EXPECT_EQ(1, iv.p[6].iov_len); - EXPECT_EQ(b + 7, iv.p[7].iov_base); - EXPECT_EQ(1, iv.p[7].iov_len); - FreeIovs(&iv); -} diff --git a/test/tool/build/lib/machine_test.c b/test/tool/build/lib/machine_test.c deleted file mode 100644 index 8a66bc347..000000000 --- a/test/tool/build/lib/machine_test.c +++ /dev/null @@ -1,348 +0,0 @@ -/*-*- 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/fmt/bing.internal.h" -#include "libc/math.h" -#include "libc/mem/mem.h" -#include "libc/mem/gc.internal.h" -#include "libc/stdio/stdio.h" -#include "libc/testlib/ezbench.h" -#include "libc/testlib/testlib.h" -#include "libc/x/x.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/fpu.h" -#include "tool/build/lib/machine.h" -#include "tool/build/lib/memory.h" - -const uint8_t kPi80[] = { - 0xd9, 0xe8, // fld1 - 0xb8, 0x0a, 0x00, 0x00, 0x00, // mov $0xa,%eax - 0x31, 0xd2, // xor %edx,%edx - 0xd9, 0xee, // fldz - 0x48, 0x98, // cltq - 0x48, 0x39, 0xc2, // cmp %rax,%rdx - 0xd9, 0x05, 0x1a, 0x00, 0x00, 0x00, // flds 0x1a(%rip) - 0x7d, 0x13, // jge 2b <pi80+0x2b> - 0xde, 0xc1, // faddp - 0x48, 0xff, 0xc2, // inc %rdx - 0xd9, 0xfa, // fsqrt - 0xd9, 0x05, 0x0f, 0x00, 0x00, 0x00, // flds 15(%rip) - 0xd8, 0xc9, // fmul %st(1),%st - 0xde, 0xca, // fmulp %st,%st(2) - 0xeb, 0xe2, // jmp d <pi80+0xd> - 0xdd, 0xd9, // fstp %st(1) - 0xde, 0xf1, // fdivp - 0xf4, // hlt - 0x00, 0x00, 0x00, 0x40, // .float 2.0 - 0x00, 0x00, 0x00, 0x3f, // .float 0.5 -}; - -const uint8_t kTenthprime[] = { - 0x31, 0xd2, // xor %edx,%edx - 0x45, 0x31, 0xc0, // xor %r8d,%r8d - 0x31, 0xc9, // xor %ecx,%ecx - 0xbe, 0x03, 0x00, 0x00, 0x00, // mov $0x3,%esi - 0x41, 0xff, 0xc0, // inc %r8d - 0x44, 0x89, 0xc0, // mov %r8d,%eax - 0x83, 0xf9, 0x0a, // cmp $0xa,%ecx - 0x74, 0x0b, // je 20 - 0x99, // cltd - 0xf7, 0xfe, // idiv %esi - 0x83, 0xfa, 0x01, // cmp $0x1,%edx - 0x83, 0xd9, 0xff, // sbb $-1,%ecx - 0xeb, 0xea, // jmp a - 0xf4, // hlt -}; - -const uint8_t kTenthprime2[] = { - 0xE8, 0x11, 0x00, 0x00, 0x00, // - 0xF4, // - 0x89, 0xF8, // - 0xB9, 0x03, 0x00, 0x00, 0x00, // - 0x99, // - 0xF7, 0xF9, // - 0x85, 0xD2, // - 0x0F, 0x95, 0xC0, // - 0xC3, // - 0x55, // - 0x48, 0x89, 0xE5, // - 0x31, 0xF6, // - 0x45, 0x31, 0xC0, // - 0x44, 0x89, 0xC7, // - 0xE8, 0xDF, 0xFF, 0xFF, 0xFF, // - 0x0F, 0xB6, 0xC0, // - 0x66, 0x83, 0xF8, 0x01, // - 0x83, 0xDE, 0xFF, // - 0x41, 0xFF, 0xC0, // - 0x83, 0xFE, 0x0A, // - 0x75, 0xE6, // - 0x44, 0x89, 0xC0, // - 0x5D, // - 0xC3, // -}; - -struct Machine *m; - -void SetUp(void) { - m = NewMachine(); - m->mode = XED_MACHINE_MODE_LONG_64; - m->cr3 = AllocateLinearPage(m); - ReserveVirtual(m, 0, 4096, 0x0207); - ASSERT_EQ(0x1007, Read64(m->real.p + 0x0000)); // PML4T - ASSERT_EQ(0x2007, Read64(m->real.p + 0x1000)); // PDPT - ASSERT_EQ(0x3007, Read64(m->real.p + 0x2000)); // PDE - ASSERT_EQ(0x0207, Read64(m->real.p + 0x3000)); // PT - ASSERT_EQ(0x4000, m->real.i); - ASSERT_EQ(1, m->memstat.reserved); - ASSERT_EQ(4, m->memstat.committed); - ASSERT_EQ(4, m->memstat.allocated); - ASSERT_EQ(3, m->memstat.pagetables); - Write64(m->sp, 4096); -} - -void TearDown(void) { - FreeVirtual(m, 0, 4096); - ASSERT_EQ(0x1007, Read64(m->real.p + 0x0000)); // PML4T - ASSERT_EQ(0x2007, Read64(m->real.p + 0x1000)); // PDPT - ASSERT_EQ(0x3007, Read64(m->real.p + 0x2000)); // PDE - ASSERT_EQ(0x0000, Read64(m->real.p + 0x3000)); // PT - FreeMachine(m); -} - -int ExecuteUntilHalt(struct Machine *m) { - int rc; - if (!(rc = setjmp(m->onhalt))) { - for (;;) { - LoadInstruction(m); - ExecuteInstruction(m); - } - } else { - return rc; - } -} - -TEST(machine, test) { - VirtualRecv(m, 0, kTenthprime, sizeof(kTenthprime)); - ASSERT_EQ(kMachineHalt, ExecuteUntilHalt(m)); - ASSERT_EQ(15, Read32(m->ax)); -} - -TEST(machine, testFpu) { - VirtualRecv(m, 0, kPi80, sizeof(kPi80)); - ASSERT_EQ(kMachineHalt, ExecuteUntilHalt(m)); - ASSERT_TRUE(fabsl(3.14159 - FpuPop(m)) < 0.0001); - m->ip = 0; - ASSERT_EQ(kMachineHalt, ExecuteUntilHalt(m)); - ASSERT_TRUE(fabsl(3.14159 - FpuPop(m)) < 0.0001); -} - -BENCH(machine, benchPrimeNumberPrograms) { - VirtualRecv(m, 0, kTenthprime2, sizeof(kTenthprime2)); - EZBENCH2("tenthprime2", m->ip = 0, ExecuteUntilHalt(m)); - ASSERT_EQ(15, Read32(m->ax)); - VirtualRecv(m, 0, kTenthprime, sizeof(kTenthprime)); - EZBENCH2("tenthprime", m->ip = 0, ExecuteUntilHalt(m)); - ASSERT_EQ(15, Read32(m->ax)); -} - -static void machine_benchFpu_fn(void) { - ExecuteUntilHalt(m); - FpuPop(m); -} - -BENCH(machine, benchFpu) { - VirtualRecv(m, 0, kPi80, sizeof(kPi80)); - EZBENCH2("pi80", m->ip = 0, machine_benchFpu_fn()); -} - -BENCH(machine, benchLoadExec2) { - uint8_t kMovCode[] = {0xbe, 0x03, 0x00, 0x00, 0x00}; - VirtualRecv(m, 0, kMovCode, sizeof(kMovCode)); - LoadInstruction(m); - EZBENCH2("mov", m->ip = 0, ExecuteInstruction(m)); -} - -BENCH(machine, benchLoadExec3) { - uint8_t kMovdCode[] = {0x66, 0x0f, 0x6e, 0xc0}; - Write64(m->ax, 0); - VirtualRecv(m, 0, kMovdCode, sizeof(kMovdCode)); - LoadInstruction(m); - EZBENCH2("movd", m->ip = 0, ExecuteInstruction(m)); -} - -BENCH(machine, benchLoadExec4) { - uint8_t kAddpsRegregCode[] = {0x0f, 0x58, 0xC0}; - uint8_t kAddpsMemregCode[] = {0x0f, 0x58, 0x00}; - Write64(m->ax, 0); - VirtualRecv(m, 0, kAddpsRegregCode, sizeof(kAddpsRegregCode)); - LoadInstruction(m); - EZBENCH2("addps reg reg", m->ip = 0, ExecuteInstruction(m)); - VirtualRecv(m, 0, kAddpsMemregCode, sizeof(kAddpsMemregCode)); - LoadInstruction(m); - EZBENCH2("addps mem reg", m->ip = 0, ExecuteInstruction(m)); -} - -BENCH(machine, benchLoadExec5) { - uint8_t kPaddwRegregCode[] = {0x66, 0x0F, 0xFD, 0xC0}; - uint8_t kPaddwMemregCode[] = {0x66, 0x0F, 0xFD, 0x00}; - Write64(m->ax, 0); - VirtualRecv(m, 0, kPaddwRegregCode, sizeof(kPaddwRegregCode)); - LoadInstruction(m); - EZBENCH2("paddw", m->ip = 0, ExecuteInstruction(m)); - VirtualRecv(m, 0, kPaddwMemregCode, sizeof(kPaddwMemregCode)); - LoadInstruction(m); - EZBENCH2("paddw mem", m->ip = 0, ExecuteInstruction(m)); -} - -BENCH(machine, benchLoadExec6) { - uint8_t kPsubqRegregCode[] = {0x66, 0x0F, 0xFB, 0xC0}; - uint8_t kPsubqMemregCode[] = {0x66, 0x0F, 0xFB, 0x00}; - Write64(m->ax, 0); - VirtualRecv(m, 0, kPsubqRegregCode, sizeof(kPsubqRegregCode)); - LoadInstruction(m); - EZBENCH2("psubq", m->ip = 0, ExecuteInstruction(m)); - VirtualRecv(m, 0, kPsubqMemregCode, sizeof(kPsubqMemregCode)); - LoadInstruction(m); - EZBENCH2("psubq mem", m->ip = 0, ExecuteInstruction(m)); -} - -BENCH(machine, benchAddqMem) { - uint8_t kAddMemregCode[] = {0x48, 0x03, 0x08}; - Write64(m->ax, 0); - VirtualRecv(m, 0, kAddMemregCode, sizeof(kAddMemregCode)); - LoadInstruction(m); - EZBENCH2("addq mem", m->ip = 0, ExecuteInstruction(m)); -} - -BENCH(machine, benchAddlMem) { - uint8_t kAddMemregCode[] = {0x03, 0x08}; - Write64(m->ax, 0); - VirtualRecv(m, 0, kAddMemregCode, sizeof(kAddMemregCode)); - LoadInstruction(m); - EZBENCH2("addl mem", m->ip = 0, ExecuteInstruction(m)); -} - -BENCH(machine, benchAddq) { - uint8_t kAddqCode[] = {0x48, 0x01, 0xd8}; - Write64(m->ax, 0); - VirtualRecv(m, 0, kAddqCode, sizeof(kAddqCode)); - LoadInstruction(m); - EZBENCH2("addq", m->ip = 0, ExecuteInstruction(m)); -} - -BENCH(machine, benchAddb) { - uint8_t kAddbCode[] = {0x00, 0xd8}; - Write64(m->ax, 0); - VirtualRecv(m, 0, kAddbCode, sizeof(kAddbCode)); - LoadInstruction(m); - EZBENCH2("addb", m->ip = 0, ExecuteInstruction(m)); -} - -BENCH(machine, benchXorReg) { - VirtualRecv(m, 0, kTenthprime, sizeof(kTenthprime)); - LoadInstruction(m); - EZBENCH2("xor", m->ip = 0, ExecuteInstruction(m)); -} - -BENCH(machine, benchLoadExec8) { - uint8_t kFchsCode[] = {0xd9, 0xe0}; - Write64(m->ax, 0); - OpFinit(m); - *FpuSt(m, 0) = M_PI; - FpuSetTag(m, 0, kFpuTagValid); - VirtualRecv(m, 0, kFchsCode, sizeof(kFchsCode)); - LoadInstruction(m); - EZBENCH2("fchs", m->ip = 0, ExecuteInstruction(m)); -} - -static void machine_benchPushpop_fn(void) { - LoadInstruction(m); - ExecuteInstruction(m); - LoadInstruction(m); - ExecuteInstruction(m); -} - -BENCH(machine, benchPushpop) { - uint8_t kPushpop[] = {0x50, 0x58}; - Write64(m->ax, 0); - VirtualRecv(m, 0, kPushpop, sizeof(kPushpop)); - EZBENCH2("pushpop", m->ip = 0, machine_benchPushpop_fn()); -} - -BENCH(machine, benchPause) { - uint8_t kPause[] = {0xf3, 0x90}; - Write64(m->ax, 0); - VirtualRecv(m, 0, kPause, sizeof(kPause)); - LoadInstruction(m); - EZBENCH2("pause", m->ip = 0, ExecuteInstruction(m)); -} - -BENCH(machine, benchClc) { - uint8_t kClc[] = {0xf8}; - Write64(m->ax, 0); - VirtualRecv(m, 0, kClc, sizeof(kClc)); - LoadInstruction(m); - EZBENCH2("clc", m->ip = 0, ExecuteInstruction(m)); -} - -static void machine_benchNop_fn(void) { - LoadInstruction(m); - ExecuteInstruction(m); -} - -BENCH(machine, benchNop) { - uint8_t kNop[] = {0x90}; - Write64(m->ax, 0); - VirtualRecv(m, 0, kNop, sizeof(kNop)); - LoadInstruction(m); - EZBENCH2("nop", m->ip = 0, ExecuteInstruction(m)); - EZBENCH2("nop w/ load", m->ip = 0, machine_benchNop_fn()); -} - -TEST(x87, fprem1) { - // 1 rem -1.5 - const uint8_t prog[] = { - 0xd9, 0x05, 0x05, 0x00, 0x00, 0x00, // flds - 0xd9, 0xe8, // fld1 - 0xd9, 0xf8, // fprem - 0xf4, // hlt - 0x00, 0x00, 0xc0, 0xbf, // .float -1.5 - }; - VirtualRecv(m, 0, prog, sizeof(prog)); - ASSERT_EQ(kMachineHalt, ExecuteUntilHalt(m)); - ASSERT_LDBL_EQ(1, FpuPop(m)); -} - -TEST(x87, fprem2) { - // 12300000000000000. rem .0000000000000123 - const uint8_t prog[] = { - 0xdd, 0x05, 0x11, 0x00, 0x00, 0x00, // fldl - 0xdd, 0x05, 0x03, 0x00, 0x00, 0x00, // fldl - 0xd9, 0xf8, // fprem - 0xf4, // hlt - 0x00, 0x60, 0x5e, 0x75, 0x64, 0xd9, 0x45, 0x43, // - 0x5b, 0x14, 0xea, 0x9d, 0x77, 0xb2, 0x0b, 0x3d, // - }; - VirtualRecv(m, 0, prog, sizeof(prog)); - ASSERT_EQ(kMachineHalt, ExecuteUntilHalt(m)); - ASSERT_LDBL_EQ(1.1766221079117338e-14, FpuPop(m)); -} - -TEST(machine, sizeIsReasonable) { - ASSERT_LE(sizeof(struct Machine), 65536 * 3); -} diff --git a/test/tool/build/lib/modrm_test.c b/test/tool/build/lib/modrm_test.c deleted file mode 100644 index 73f50dfa5..000000000 --- a/test/tool/build/lib/modrm_test.c +++ /dev/null @@ -1,110 +0,0 @@ -/*-*- 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/mem/mem.h" -#include "libc/mem/gc.internal.h" -#include "libc/testlib/testlib.h" -#include "third_party/xed/x86.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/machine.h" -#include "tool/build/lib/modrm.h" - -#define ILD(XEDD, OP, MODE) \ - do { \ - xed_decoded_inst_zero_set_mode(XEDD, MODE); \ - ASSERT_EQ(0, xed_instruction_length_decode(XEDD, OP, sizeof(OP))); \ - XEDD->op.rde = EncodeRde(XEDD); \ - } while (0) - -TEST(modrm, testAddressSizeOverride_isNotPresent_keepsWholeExpression) { - struct Machine *m = gc(NewMachine()); - struct XedDecodedInst *xedd = gc(calloc(1, sizeof(struct XedDecodedInst))); - uint8_t op[] = {0x8d, 0x04, 0x03}; /* lea (%rbx,%rax,1),%eax */ - m->xedd = xedd; - Write64(m->bx, 0x2); - Write64(m->ax, 0xffffffff); - ILD(xedd, op, XED_MACHINE_MODE_LONG_64); - EXPECT_EQ(0x100000001, ComputeAddress(m, m->xedd->op.rde)); -} - -TEST(modrm, testAddressSizeOverride_isPresent_modulesWholeExpression) { - struct Machine *m = gc(NewMachine()); - struct XedDecodedInst *xedd = gc(calloc(1, sizeof(struct XedDecodedInst))); - uint8_t op[] = {0x67, 0x8d, 0x04, 0x03}; /* lea (%ebx,%eax,1),%eax */ - m->xedd = xedd; - Write64(m->bx, 0x2); - Write64(m->ax, 0xffffffff); - ILD(xedd, op, XED_MACHINE_MODE_LONG_64); - EXPECT_EQ(0x000000001, ComputeAddress(m, m->xedd->op.rde)); -} - -TEST(modrm, testOverflow_doesntTriggerTooling) { - struct Machine *m = gc(NewMachine()); - struct XedDecodedInst *xedd = gc(calloc(1, sizeof(struct XedDecodedInst))); - uint8_t op[] = {0x8d, 0x04, 0x03}; /* lea (%rbx,%rax,1),%eax */ - m->xedd = xedd; - Write64(m->bx, 0x0000000000000001); - Write64(m->ax, 0x7fffffffffffffff); - ILD(xedd, op, XED_MACHINE_MODE_LONG_64); - EXPECT_EQ(0x8000000000000000ull, - (uint64_t)ComputeAddress(m, m->xedd->op.rde)); -} - -TEST(modrm, testPuttingOnTheRiz) { - struct Machine *m = gc(NewMachine()); - static uint8_t ops[][15] = { - {0x8d, 0b00110100, 0b00100110}, // lea (%rsi),%esi - {0x67, 0x8d, 0b00110100, 0b11100110}, // lea (%esi,%eiz,8),%esi - {103, 141, 180, 229, 55, 19, 3, 0}, // lea 0x31337(%ebp,%eiz,8),%esi - {141, 52, 229, 55, 19, 3, 0}, // lea 0x31337,%esi - }; - m->xedd = gc(calloc(1, sizeof(struct XedDecodedInst))); - Write64(m->si, 0x100000001); - Write64(m->bp, 0x200000002); - ILD(m->xedd, ops[0], XED_MACHINE_MODE_LONG_64); - EXPECT_EQ(0x100000001, ComputeAddress(m, m->xedd->op.rde)); - ILD(m->xedd, ops[1], XED_MACHINE_MODE_LONG_64); - EXPECT_EQ(0x000000001, ComputeAddress(m, m->xedd->op.rde)); - ILD(m->xedd, ops[2], XED_MACHINE_MODE_LONG_64); - EXPECT_EQ(0x31339, ComputeAddress(m, m->xedd->op.rde)); - ILD(m->xedd, ops[3], XED_MACHINE_MODE_LONG_64); - EXPECT_EQ(0x31337, ComputeAddress(m, m->xedd->op.rde)); -} - -TEST(modrm, testSibIndexOnly) { - // lea 0x0(,%rcx,4),%r8 - // mod = 0b00 (0) - // reg = 0b000 (0) - // rm = 0b100 (4) - // scale = 0b10 (2) - // index = 0b001 (1) - // base = 0b101 (5) - struct Machine *m = gc(NewMachine()); - struct XedDecodedInst *xedd = gc(calloc(1, sizeof(struct XedDecodedInst))); - uint8_t op[] = {0x4c, 0x8d, 0x04, 0x8d, 0, 0, 0, 0}; - m->xedd = xedd; - Write64(m->bp, 0x123); - Write64(m->cx, 0x123); - ILD(xedd, op, XED_MACHINE_MODE_LONG_64); - EXPECT_TRUE(Rexw(m->xedd->op.rde)); - EXPECT_TRUE(Rexr(m->xedd->op.rde)); - EXPECT_FALSE(Rexb(m->xedd->op.rde)); - EXPECT_EQ(0b000, ModrmReg(m->xedd->op.rde)); - EXPECT_EQ(0b100, ModrmRm(m->xedd->op.rde)); - EXPECT_EQ(0x123 * 4, (uint64_t)ComputeAddress(m, m->xedd->op.rde)); -} diff --git a/test/tool/build/lib/numbers.c b/test/tool/build/lib/numbers.c deleted file mode 100644 index 4c56c3ccb..000000000 --- a/test/tool/build/lib/numbers.c +++ /dev/null @@ -1,56 +0,0 @@ -/*-*- 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 "test/tool/build/lib/numbers.h" - -const uint64_t kNumbers[102] = { - 0x0000000000000000, 0x0000000080000000, 0x0000000000008000, - 0x0000000000000001, 0x0000000000000002, 0x0000000000000003, - 0x0000000000000004, 0x0000000000000005, 0x0000000000000006, - 0x0000000000000007, 0x0000000000000008, 0x0000000000000009, - 0x000000000000000a, 0x000000000000000b, 0x000000000000000c, - 0x000000000000000d, 0x000000000000000e, 0x000000000000000f, - 0x0000000000000010, 0x0000000000000011, 0x0000000000000012, - 0x0000000000000013, 0x0000000000000014, 0x0000000000000015, - 0x0000000000000016, 0x0000000000000017, 0x0000000000000018, - 0x0000000000000019, 0x000000000000001a, 0x000000000000001b, - 0x000000000000001c, 0x000000000000001d, 0x000000000000001e, - 0x000000000000001f, 0x0000000000000020, 0x0000000000000040, - 0x8000000000000000, 0x0000000000000080, 0x0000000000000002, - 0x0000000000000001, 0x0000000000000004, 0x00000000C0000000, - 0xC000000000000000, 0x000000000000C000, 0x00000000000000C0, - 0x0000000000000003, 0x000000000000E000, 0x00000000E0000000, - 0xE000000000000000, 0x00000000000000E0, 0x000000000000001F, - 0x00000000000000FC, 0x000000000000003F, 0x000000000000007F, - 0x00000000000000FB, 0x00000000000000FD, 0x00000000000000FE, - 0x00000000000000FF, 0x000000000000FF1F, 0x0000000000001FFF, - 0x000000000000FFFC, 0x0000000000003FFF, 0x000000000000FF3F, - 0x000000000000FFFD, 0x000000000000FFFE, 0x000000000000FFFB, - 0x000000000000FF7F, 0x0000000000007FFF, 0x000000000000FFFF, - 0x00000000FFFF1FFF, 0x00000000FFFFFF1F, 0x000000001FFFFFFF, - 0x00000000FFFFFF3F, 0x00000000FFFF3FFF, 0x00000000FFFFFFFC, - 0x000000003FFFFFFF, 0x00000000FFFFFF7F, 0x00000000FFFFFFFD, - 0x00000000FFFFFFFE, 0x00000000FFFFFFFB, 0x000000007FFFFFFF, - 0x00000000FFFF7FFF, 0x00000000FFFFFFFF, 0xFFFFFFFF1FFFFFFF, - 0x1FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFF1FFF, 0xFFFFFFFFFFFFFF1F, - 0xFFFFFFFFFFFFFFFC, 0xFFFFFFFFFFFF3FFF, 0xFFFFFFFF3FFFFFFF, - 0xFFFFFFFFFFFFFF3F, 0x3FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFD, - 0xFFFFFFFFFFFFFFFE, 0xFFFFFFFFFFFFFFFB, 0xFFFFFFFF7FFFFFFF, - 0x7FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFF7F, 0xFFFFFFFFFFFF7FFF, - 0xFFFFFFFFFFFFFFFF, 0x00DeadBeefCafe00, 0x0000031337000000, -}; diff --git a/test/tool/build/lib/numbers.h b/test/tool/build/lib/numbers.h deleted file mode 100644 index 6ab84b2d1..000000000 --- a/test/tool/build/lib/numbers.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef COSMOPOLITAN_TEST_TOOL_BUILD_LIB_NUMBERS_H_ -#define COSMOPOLITAN_TEST_TOOL_BUILD_LIB_NUMBERS_H_ -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -extern const uint64_t kNumbers[102]; - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TEST_TOOL_BUILD_LIB_NUMBERS_H_ */ diff --git a/test/tool/build/lib/optest.c b/test/tool/build/lib/optest.c deleted file mode 100644 index 1be12f7a1..000000000 --- a/test/tool/build/lib/optest.c +++ /dev/null @@ -1,96 +0,0 @@ -/*-*- 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 "test/tool/build/lib/optest.h" -#include "libc/intrin/weaken.h" -#include "libc/macros.internal.h" -#include "libc/runtime/runtime.h" -#include "libc/stdio/stdio.h" -#include "test/tool/build/lib/numbers.h" -#include "tool/build/lib/flags.h" -#ifdef __x86_64__ - -const char kOpSuffix[] = {'b', 'w', 'l', 'q'}; - -void(RunOpTests)(const uint8_t *ops, size_t n, const char *const *opnames, - const char *file, int line, const char *func) { - uint64_t x, y; - uint64_t xn, xp; - uint32_t f0, f1, f2; - long failed, succeeded; - int w, h, i, j, c, z, s, o, p; - failed = 0; - succeeded = 0; - for (w = 0; w < 4; ++w) { - for (h = 0; h < n; ++h) { - for (z = 0; z < 2; ++z) { - for (o = 0; o < 2; ++o) { - for (s = 0; s < 2; ++s) { - for (i = 0; i < ARRAYLEN(kNumbers); ++i) { - for (j = 0; j < ARRAYLEN(kNumbers); ++j) { - for (c = 0; c < 2; ++c) { - x = kNumbers[i]; - y = kNumbers[j]; - f2 = f1 = f0 = c << FLAGS_CF | z << FLAGS_ZF | s << FLAGS_SF | - o << FLAGS_OF; - xn = RunGolden(w, ops[h], x, y, &f1); - xp = RunOpTest(w, ops[h], x, y, &f2); - if (_weaken(FixupUndefOpTestFlags)) { - FixupUndefOpTestFlags(w, ops[h], x, y, f1, &f2); - } - if (xn == xp && (f1 & FMASK) == (f2 & FMASK)) { - succeeded++; - } else if (failed++ < 10) { - fprintf(stderr, - "%s:%d:%s: %s%c failed\n\t" - "𝑥 %016x\n\t" - "𝑦 %016x %c%c%c%c 0NPlODITSZKA1PVC\n\t" - "𝑥ₙ %016x %c%c%c%c %016b\n\t" - "𝑥ₚ %016x %c%c%c%c %016b\n", - file, line, func, opnames[ops[h]], kOpSuffix[w], x, - y, ".C"[c], ".Z"[z], ".S"[s], ".O"[o], xn, - ".C"[!!(f1 & (1 << FLAGS_CF))], - ".Z"[!!(f1 & (1 << FLAGS_ZF))], - ".S"[!!(f1 & (1 << FLAGS_SF))], - ".O"[!!(f1 & (1 << FLAGS_OF))], f1, xp, - ".C"[!!(f2 & (1 << FLAGS_CF))], - ".Z"[!!(f2 & (1 << FLAGS_ZF))], - ".S"[!!(f2 & (1 << FLAGS_SF))], - ".O"[!!(f2 & (1 << FLAGS_OF))], f2); - } - } - } - } - } - } - } - } - } - if (failed) { - fprintf(stderr, - "\n" - "passing: %d%%\n" - "succeeded: %,ld\n" - "failed: %,ld\n" - "\n", - (int)((1 - (double)failed / succeeded) * 100), succeeded, failed); - exit(1); - } -} - -#endif /* __x86_64__ */ diff --git a/test/tool/build/lib/optest.h b/test/tool/build/lib/optest.h deleted file mode 100644 index b2ed6e1fc..000000000 --- a/test/tool/build/lib/optest.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef COSMOPOLITAN_TEST_TOOL_BUILD_LIB_OPTEST_H_ -#define COSMOPOLITAN_TEST_TOOL_BUILD_LIB_OPTEST_H_ -#include "tool/build/lib/flags.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -#define FMASK (1 << FLAGS_CF | 1 << FLAGS_ZF | 1 << FLAGS_SF | 1 << FLAGS_OF) - -void RunOpTests(const uint8_t *, size_t, const char *const *, const char *, int, - const char *); - -int64_t RunGolden(char, int, uint64_t, uint64_t, uint32_t *); -int64_t RunOpTest(char, int, uint64_t, uint64_t, uint32_t *); -void FixupUndefOpTestFlags(char, int, uint64_t, uint64_t, uint32_t, uint32_t *); - -#define RunOpTests(ops, n, names) \ - RunOpTests(ops, n, names, __FILE__, __LINE__, __func__) - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TEST_TOOL_BUILD_LIB_OPTEST_H_ */ diff --git a/test/tool/build/lib/pty_test.c b/test/tool/build/lib/pty_test.c deleted file mode 100644 index 6b0e498a5..000000000 --- a/test/tool/build/lib/pty_test.c +++ /dev/null @@ -1,235 +0,0 @@ -/*-*- 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 "tool/build/lib/pty.h" -#include "libc/log/log.h" -#include "libc/mem/gc.internal.h" -#include "libc/mem/mem.h" -#include "libc/stdio/stdio.h" -#include "libc/str/str.h" -#include "libc/str/unicode.h" -#include "libc/testlib/ezbench.h" -#include "libc/testlib/testlib.h" - -char *render(struct Pty *pty) { - static struct Buffer b; - int y; - b.i = 0; - for (y = 0; y < pty->yn; ++y) { - PtyAppendLine(pty, &b, y); - } - b.p[b.i] = 0; - return b.p; -} - -const char widelatin[] forcealign(16) = "\ -A-BCDEFGHIJKLMNOPQRSTUVWXYZ\r\n\ -ab-cdefghijklmnopqrstuvwxyz\r\n\ -012-3456789\r\n\ -ABCD-EFGHIJKLMNOPQRSTUVWXYZ\r\n\ -abcde-fghijklmnopqrstuvwxyz\r\n\ -012345-6789\r\n\ -ABCDEFG-HIJKLMNOPQRSTUVWXYZ\r\n\ -abcdefgh-ijklmnopqrstuvwxyz\r\n\ -012345678-9"; - -static const char widelatin_golden[] = "\ -A-BCDEFGHIJKLMNOPQRSTUVWXYZ \ -ab-cdefghijklmnopqrstuvwxyz \ -012-3456789 \ -ABCD-EFGHIJKLMNOPQRSTUVWXYZ \ -abcde-fghijklmnopqrstuvwxyz \ -012345-6789 \ -ABCDEFG-HIJKLMNOPQRSTUVWXYZ \ -abcdefgh-ijklmnopqrstuvwxyz \ -012345678-9▂ \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - "; - -TEST(pty, testFunWidth) { - struct Pty *pty = NewPty(); - PtyWrite(pty, widelatin, ARRAYLEN(widelatin) - 1); - EXPECT_STREQ(widelatin_golden, gc(render(pty))); - FreePty(pty); -} - -const char hyperion[] forcealign(16) = "\ -Fanatics have their dreams, wherewith they weave \ -A paradise for a sect; the savage too \ -From forth the loftiest fashion of his sleep \ -Guesses at Heaven; pity these have not \ -Trac'd upon vellum or wild Indian leaf \ -The shadows of melodious utterance. \ -But bare of laurel they live, dream, and die; \ -For Poesy alone can tell her dreams, \ -With the fine spell of words alone can save \ -Imagination from the sable charm \ -And dumb enchantment. Who alive can say, \ -'Thou art no Poet may'st not tell thy dreams?' \ -Since every man whose soul is not a clod \ -Hath visions, and would speak, if he had loved \ -And been well nurtured in his mother tongue. \ -Whether the dream now purpos'd to rehearse \ -Be poet's or fanatic's will be known \ -When this warm scribe my hand is in the grave."; - -static const wchar_t hyperion_golden[] = L"\ -Fanatics have their dreams, wherewith they weave A paradise for a sect; the sava\ -ge too From forth the loftiest fashion of his sleep Guesses at Heaven; pity thes\ -e have not Trac'd upon vellum or wild Indian leaf The shadows of melodious utter\ -ance. But bare of laurel they live, dream, and die; For Poesy alone can tell her\ - dreams, With the fine spell of words alone can save Imagination from the sable \ -charm And dumb enchantment. Who alive can say, 'Thou art no Poet may'st not tell\ - thy dreams?' Since every man whose soul is not a clod Hath visions, and would s\ -peak, if he had loved And been well nurtured in his mother tongue. Whether the d\ -ream now purpos'd to rehearse Be poet's or fanatic's will be known When this war\ -m scribe my hand is in the grave. \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - "; - -TEST(pty, testPureAscii_benefitsFromVectorization) { - struct Pty *pty = NewPty(); - PtyWrite(pty, hyperion, ARRAYLEN(hyperion) - 1); - EXPECT_STREQN(pty->wcs, hyperion_golden, ARRAYLEN(hyperion_golden) - 1); - FreePty(pty); -} - -static const char kKiloAnsi[] = "\ -\e[?25l\e[H\ -#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐\e[39m\e[0K\r\n\ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi─────────\e[39m\e[0K\r\n\ -#\e[39m\e[0K\r\n\ -# SYNOPSIS\e[39m\e[0K\r\n\ -#\e[39m\e[0K\r\n\ -# Freestanding Hermetically-Sealed Monolithic Repository\e[39m\e[0K\r\n\ -#\e[39m\e[0K\r\n\ -# REQUIREMENTS\e[39m\e[0K\r\n\ -#\e[39m\e[0K\r\n\ -# You can run your programs on any operating system, but you have\e[39m\e[0K\r\n\ -# to build them on Linux 2.6+ (or WSL) using GNU Make. A modern C\e[39m\e[0K\r\n\ -# compiler that\'s statically-linked comes included as a courtesy.\e[39m\e[0K\r\n\ -#\e[39m\e[0K\r\n\ -# EXAMPLES\e[39m\e[0K\r\n\ -#\e[39m\e[0K\r\n\ -# # build and run everything\e[39m\e[0K\r\n\ -# make -j8 -O\e[39m\e[0K\r\n\ -# make -j8 -O MODE=dbg\e[39m\e[0K\r\n\ -# make -j8 -O MODE=opt\e[39m\e[0K\r\n\ -# make -j8 -O MODE=rel\e[39m\e[0K\r\n\ -# make -j8 -O MODE=tiny\e[39m\e[0K\r\n\ -#\e[39m\e[0K\r\n\ -# # build individual target\e[39m\e[0K\r\n\ -\e[0K\e[7mMakefile - 340 lines 1/340\e[0m\r\n\ -\e[0KHELP: Ctrl-S = save | Ctrl-Q = quit | Ctrl-F = find\e[1;1H\e[?25h"; - -static const wchar_t kKiloGolden[] = L"\ -#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ \ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────── \ -# \ -# SYNOPSIS \ -# \ -# Freestanding Hermetically-Sealed Monolithic Repository \ -# \ -# REQUIREMENTS \ -# \ -# You can run your programs on any operating system, but you have \ -# to build them on Linux 2.6+ (or WSL) using GNU Make. A modern C \ -# compiler that's statically-linked comes included as a courtesy. \ -# \ -# EXAMPLES \ -# \ -# # build and run everything \ -# make -j8 -O \ -# make -j8 -O MODE=dbg \ -# make -j8 -O MODE=opt \ -# make -j8 -O MODE=rel \ -# make -j8 -O MODE=tiny \ -# \ -# # build individual target \ -Makefile - 340 lines 1/340\ -HELP: Ctrl-S = save | Ctrl-Q = quit | Ctrl-F = find \ -"; - -TEST(pty, testLongestPossibleCharacter) { - EXPECT_EQ(60, strlen("\e[21;22;27;24;25;29;38;2;255;255;255;48;2;255;255;" - "255m\377\277\277\277\277\277")); - struct Buffer b = {0}; - struct Pty *pty = NewPty(); - const char *s = "\e[1;2;3;4;5;6;7;9m" - "h" - "\e[0;" - "38;2;255;255;255;" - "48;2;255;255;255m" - "\377\277\277\277\277\277" - "\e[0m"; - PtyWrite(pty, s, strlen(s)); - PtyAppendLine(pty, &b, 0); - AppendChar(&b, '\0'); - EXPECT_STREQ("\e[1;2;4;7;5;9m" - "𝒉" - "\e[22;24;27;25;29;38;2;255;255;255;48;2;255;255;255m" - " " - "\e[0m▂ " - " ", - b.p); - FreePty(pty); - free(b.p); -} - -TEST(pty, test) { - struct Pty *pty = NewPty(); - PtyWrite(pty, kKiloAnsi, strlen(kKiloAnsi)); - EXPECT_STREQN(kKiloGolden, pty->wcs, wcslen(kKiloGolden)); - FreePty(pty); -} - -BENCH(pty, bench) { - struct Pty *pty = NewPty(); - EZBENCH2("pty write ascii", donothing, - PtyWrite(pty, hyperion, sizeof(hyperion) - 1)); - EZBENCH2("pty write kilo", donothing, - PtyWrite(pty, kKiloAnsi, sizeof(kKiloAnsi) - 1)); - FreePty(pty); -} diff --git a/test/tool/build/lib/xlaterrno_test.c b/test/tool/build/lib/xlaterrno_test.c deleted file mode 100644 index 9d41acf49..000000000 --- a/test/tool/build/lib/xlaterrno_test.c +++ /dev/null @@ -1,26 +0,0 @@ -/*-*- 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/errno.h" -#include "libc/testlib/testlib.h" -#include "tool/build/lib/xlat.h" - -TEST(xlaterrno, test) { - EXPECT_EQ(95, XlatErrno(EOPNOTSUPP)); - EXPECT_EQ(90, XlatErrno(EMSGSIZE)); -} diff --git a/tool/build/blinkenlights.c b/tool/build/blinkenlights.c deleted file mode 100644 index 58b3b9598..000000000 --- a/tool/build/blinkenlights.c +++ /dev/null @@ -1,3180 +0,0 @@ -/*-*- 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 "dsp/scale/cdecimate2xuint8x8.h" -#include "dsp/tty/tty.h" -#include "libc/assert.h" -#include "libc/calls/calls.h" -#include "libc/calls/ioctl.h" -#include "libc/calls/struct/cpuset.h" -#include "libc/calls/struct/iovec.h" -#include "libc/calls/struct/itimerval.h" -#include "libc/calls/struct/sigaction.h" -#include "libc/calls/struct/stat.h" -#include "libc/calls/struct/termios.h" -#include "libc/calls/struct/winsize.h" -#include "libc/calls/termios.h" -#include "libc/calls/ucontext.h" -#include "libc/dce.h" -#include "libc/errno.h" -#include "libc/fmt/bing.internal.h" -#include "libc/fmt/conv.h" -#include "libc/fmt/fmt.h" -#include "libc/fmt/itoa.h" -#include "libc/intrin/asan.internal.h" -#include "libc/intrin/bits.h" -#include "libc/intrin/pcmpeqb.h" -#include "libc/intrin/pmovmskb.h" -#include "libc/intrin/safemacros.internal.h" -#include "libc/intrin/tpenc.h" -#include "libc/limits.h" -#include "libc/log/check.h" -#include "libc/log/color.internal.h" -#include "libc/log/internal.h" -#include "libc/log/log.h" -#include "libc/macros.internal.h" -#include "libc/math.h" -#include "libc/mem/arraylist2.internal.h" -#include "libc/mem/gc.h" -#include "libc/mem/mem.h" -#include "libc/runtime/runtime.h" -#include "libc/sock/sock.h" -#include "libc/stdio/append.h" -#include "libc/stdio/rand.h" -#include "libc/stdio/stdio.h" -#include "libc/str/str.h" -#include "libc/str/strwidth.h" -#include "libc/str/tab.internal.h" -#include "libc/str/thompike.h" -#include "libc/sysv/consts/auxv.h" -#include "libc/sysv/consts/ex.h" -#include "libc/sysv/consts/exit.h" -#include "libc/sysv/consts/fileno.h" -#include "libc/sysv/consts/itimer.h" -#include "libc/sysv/consts/map.h" -#include "libc/sysv/consts/o.h" -#include "libc/sysv/consts/poll.h" -#include "libc/sysv/consts/prot.h" -#include "libc/sysv/consts/sa.h" -#include "libc/sysv/consts/sig.h" -#include "libc/sysv/consts/termios.h" -#include "libc/sysv/errfuns.h" -#include "libc/time/time.h" -#include "libc/x/x.h" -#include "libc/x/xasprintf.h" -#include "libc/x/xsigaction.h" -#include "third_party/gdtoa/gdtoa.h" -#include "third_party/getopt/getopt.h" -#include "tool/build/lib/address.h" -#include "tool/build/lib/breakpoint.h" -#include "tool/build/lib/case.h" -#include "tool/build/lib/cga.h" -#include "tool/build/lib/demangle.h" -#include "tool/build/lib/dis.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/fds.h" -#include "tool/build/lib/flags.h" -#include "tool/build/lib/fpu.h" -#include "tool/build/lib/high.h" -#include "tool/build/lib/loader.h" -#include "tool/build/lib/machine.h" -#include "tool/build/lib/mda.h" -#include "tool/build/lib/memory.h" -#include "tool/build/lib/modrm.h" -#include "tool/build/lib/panel.h" -#include "tool/build/lib/pml4t.h" -#include "tool/build/lib/pty.h" -#include "tool/build/lib/signal.h" -#include "tool/build/lib/stats.h" -#include "tool/build/lib/syscall.h" -#include "tool/build/lib/throw.h" -#include "tool/build/lib/xmmtype.h" - -#define USAGE \ - " [-?HhrRstv] [ROM] [ARGS...]\n\ -\n\ -DESCRIPTION\n\ -\n\ - Emulates x86 Linux Programs w/ Dense Machine State Visualization\n\ - Please keep still and only watchen astaunished das blinkenlights\n\ -\n\ -FLAGS\n\ -\n\ - -h help\n\ - -z zoom\n\ - -v verbosity\n\ - -r real mode\n\ - -s statistics\n\ - -H disable highlight\n\ - -t tui debugger mode\n\ - -R reactive tui mode\n\ - -b ADDR push a breakpoint\n\ - -L PATH log file location\n\ -\n\ -ARGUMENTS\n\ -\n\ - ROM files can be ELF or a flat αcτµαlly pδrταblε εxεcµταblε.\n\ - It should use x86_64 in accordance with the System Five ABI.\n\ - The SYSCALL ABI is defined as it is written in Linux Kernel.\n\ -\n\ -FEATURES\n\ -\n\ - 8086, 8087, i386, x86_64, SSE3, SSSE3, POPCNT, MDA, CGA, TTY\n\ -\n" - -#define HELP \ - "\e[1mBLINKENLIGHTS v1.o\e[22m\ - https://justine.lol/blinkenlights/\n\ -\n\ -KEYBOARD SHORTCUTS CLI FLAGS\n\ -\n\ -ctrl-c interrupt -t tui mode\n\ -s step -r real mode\n\ -n next -s statistics\n\ -c continue -b ADDR push breakpoint\n\ -C continue harder -L PATH log file location\n\ -q quit -R reactive tui mode\n\ -f finish -H disable highlighting\n\ -R restart -v increase verbosity\n\ -x hex -? help\n\ -? help\n\ -t sse type\n\ -w sse width\n\ -B pop breakpoint\n\ -ctrl-t turbo\n\ -alt-t slowmo" - -#define MAXZOOM 16 -#define DISWIDTH 40 -#define DUMPWIDTH 64 -#define DISPWIDTH 80 -#define WHEELDELTA 1 - -#define RESTART 0x001 -#define REDRAW 0x002 -#define CONTINUE 0x004 -#define STEP 0x008 -#define NEXT 0x010 -#define FINISH 0x020 -#define FAILURE 0x040 -#define WINCHED 0x080 -#define INT 0x100 -#define QUIT 0x200 -#define EXIT 0x400 -#define ALARM 0x800 - -#define kXmmDecimal 0 -#define kXmmHex 1 -#define kXmmChar 2 - -#define kMouseLeftDown 0 -#define kMouseMiddleDown 1 -#define kMouseRightDown 2 -#define kMouseLeftUp 4 -#define kMouseMiddleUp 5 -#define kMouseRightUp 6 -#define kMouseLeftDrag 32 -#define kMouseMiddleDrag 33 -#define kMouseRightDrag 34 -#define kMouseWheelUp 64 -#define kMouseWheelDown 65 -#define kMouseCtrlWheelUp 80 -#define kMouseCtrlWheelDown 81 - -#define CTRL(C) ((C) ^ 0100) - -struct Mouse { - short y; - short x; - int e; -}; - -struct MemoryView { - int64_t start; - int zoom; -}; - -struct Keystrokes { - unsigned i; - char p[4][32]; - long double s[4]; -}; - -struct MachineState { - uint64_t ip; - uint8_t cs[8]; - uint8_t ss[8]; - uint8_t es[8]; - uint8_t ds[8]; - uint8_t fs[8]; - uint8_t gs[8]; - uint8_t reg[16][8]; - uint8_t xmm[16][16]; - struct MachineFpu fpu; - struct MachineSse sse; - struct MachineMemstat memstat; -}; - -struct Panels { - union { - struct { - struct Panel disassembly; - struct Panel breakpointshr; - struct Panel breakpoints; - struct Panel mapshr; - struct Panel maps; - struct Panel frameshr; - struct Panel frames; - struct Panel displayhr; - struct Panel display; - struct Panel registers; - struct Panel ssehr; - struct Panel sse; - struct Panel codehr; - struct Panel code; - struct Panel readhr; - struct Panel readdata; - struct Panel writehr; - struct Panel writedata; - struct Panel stackhr; - struct Panel stack; - struct Panel status; - }; - struct Panel p[21]; - }; -}; - -static const signed char kThePerfectKernel[8] = {-1, -3, 3, 17, 17, 3, -3, -1}; - -static const char kRipName[3][4] = {"IP", "EIP", "RIP"}; - -static const char kRegisterNames[3][16][4] = { - {"AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI"}, - {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"}, - {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", "R8", "R9", "R10", - "R11", "R12", "R13", "R14", "R15"}, -}; - -static bool belay; -static bool react; -static bool tuimode; -static bool alarmed; -static bool colorize; -static bool mousemode; -static bool printstats; -static bool showhighsse; - -static int tyn; -static int txn; -static int tick; -static int speed; -static int vidya; -static int ttyin; -static int focus; -static int ttyout; -static int opline; -static int action; -static int xmmdisp; -static int exitcode; - -static long ips; -static long rombase; -static long codesize; -static int64_t oldlen; -static int64_t opstart; -static int64_t mapsstart; -static uint64_t readaddr; -static uint64_t readsize; -static uint64_t writeaddr; -static uint64_t writesize; -static int64_t framesstart; -static int64_t breakpointsstart; -static uint64_t last_opcount; -static char *codepath; -static void *onbusted; -static char *dialog; -static char *statusmessage; -static struct Pty *pty; -static struct Machine *m; - -static struct Panels pan; -static struct Keystrokes keystrokes; -static struct Breakpoints breakpoints; -static struct MemoryView codeview; -static struct MemoryView readview; -static struct MemoryView writeview; -static struct MemoryView stackview; -static struct MachineState laststate; -static struct MachineMemstat lastmemstat; -static struct XmmType xmmtype; -static struct Elf elf[1]; -static struct Dis dis[1]; - -static long double last_seconds; -static long double statusexpires; -static struct termios oldterm; -static char logpath[PATH_MAX]; -static char systemfailure[128]; -static struct sigaction oldsig[4]; - -static void SetupDraw(void); -static void Redraw(void); -static void HandleKeyboard(const char *); - -static char *FormatDouble(char buf[32], long double x) { - g_xfmt_p(buf, &x, 15, 32, 0); - return buf; -} - -static int64_t SignExtend(uint64_t x, char b) { - char k; - assert(1 <= b && b <= 64); - k = 64 - b; - return (int64_t)(x << k) >> k; -} - -static void SetCarry(bool cf) { - m->flags = SetFlag(m->flags, FLAGS_CF, cf); -} - -static bool IsCall(void) { - return (m->xedd->op.dispatch == 0x0E8 || - (m->xedd->op.dispatch == 0x0FF && m->xedd->op.reg == 2)); -} - -static bool IsDebugBreak(void) { - return m->xedd->op.map == XED_ILD_MAP0 && m->xedd->op.opcode == 0xCC; -} - -static bool IsRet(void) { - switch (m->xedd->op.dispatch) { - case 0x0C2: - case 0x0C3: - case 0x0CA: - case 0x0CB: - case 0x0CF: - return true; - default: - return false; - } -} - -static int GetXmmTypeCellCount(int r) { - switch (xmmtype.type[r]) { - case kXmmIntegral: - return 16 / xmmtype.size[r]; - case kXmmFloat: - return 4; - case kXmmDouble: - return 2; - default: - __builtin_unreachable(); - } -} - -static uint8_t CycleXmmType(uint8_t t) { - switch (t) { - default: - case kXmmIntegral: - return kXmmFloat; - case kXmmFloat: - return kXmmDouble; - case kXmmDouble: - return kXmmIntegral; - } -} - -static uint8_t CycleXmmDisp(uint8_t t) { - switch (t) { - default: - case kXmmDecimal: - return kXmmHex; - case kXmmHex: - return kXmmChar; - case kXmmChar: - return kXmmDecimal; - } -} - -static uint8_t CycleXmmSize(uint8_t w) { - switch (w) { - default: - case 1: - return 2; - case 2: - return 4; - case 4: - return 8; - case 8: - return 1; - } -} - -static int GetPointerWidth(void) { - return 2 << (m->mode & 3); -} - -static int64_t GetIp(void) { - switch (GetPointerWidth()) { - default: - case 8: - return m->ip; - case 4: - return Read64(m->cs) + (m->ip & 0xffff); - case 2: - return Read64(m->cs) + (m->ip & 0xffff); - } -} - -static int64_t GetSp(void) { - switch (GetPointerWidth()) { - default: - case 8: - return Read64(m->sp); - case 4: - return Read64(m->ss) + Read32(m->sp); - case 2: - return Read64(m->ss) + Read16(m->sp); - } -} - -static int64_t ReadWord(uint8_t *p) { - switch (GetPointerWidth()) { - default: - case 8: - return Read64(p); - case 4: - return Read32(p); - case 2: - return Read16(p); - } -} - -static void CopyMachineState(struct MachineState *ms) { - ms->ip = m->ip; - memcpy(ms->cs, m->cs, sizeof(m->cs)); - memcpy(ms->ss, m->ss, sizeof(m->ss)); - memcpy(ms->es, m->es, sizeof(m->es)); - memcpy(ms->ds, m->ds, sizeof(m->ds)); - memcpy(ms->fs, m->fs, sizeof(m->fs)); - memcpy(ms->gs, m->gs, sizeof(m->gs)); - memcpy(ms->reg, m->reg, sizeof(m->reg)); - memcpy(ms->xmm, m->xmm, sizeof(m->xmm)); - memcpy(&ms->fpu, &m->fpu, sizeof(m->fpu)); - memcpy(&ms->sse, &m->sse, sizeof(m->sse)); -} - -/** - * Handles file mapped page faults in valid page but past eof. - */ -static void OnSigBusted(void) { - CHECK(onbusted); - longjmp(onbusted, 1); -} - -/** - * Returns true if 𝑣 is a shadow memory virtual address. - */ -static bool IsShadow(int64_t v) { - return 0x7fff8000 <= v && v < 0x100080000000; -} - -/** - * Returns glyph representing byte at virtual address 𝑣. - */ -static int VirtualBing(int64_t v) { - int rc; - uint8_t *p; - jmp_buf busted; - onbusted = busted; - if ((p = FindReal(m, v))) { - if (!setjmp(busted)) { - rc = bing(p[0], 0); - } else { - rc = u'≀'; - } - } else { - rc = u'⋅'; - } - onbusted = NULL; - return rc; -} - -/** - * Returns ASAN shadow uint8 concomitant to address 𝑣 or -1. - */ -static int VirtualShadow(int64_t v) { - int rc; - char *p; - jmp_buf busted; - if (IsShadow(v)) return -2; - onbusted = busted; - if ((p = FindReal(m, (v >> 3) + 0x7fff8000))) { - if (!setjmp(busted)) { - rc = p[0] & 0xff; - } else { - rc = -1; - } - } else { - rc = -1; - } - onbusted = NULL; - return rc; -} - -static void ScrollOp(struct Panel *p, long op) { - long n; - opline = op; - if ((n = p->bottom - p->top) > 1) { - if (!(opstart + 1 <= op && op < opstart + n)) { - opstart = MIN(MAX(0, op - n / 8), MAX(0, dis->ops.i - n)); - } - } -} - -static int TtyWriteString(const char *s) { - return write(ttyout, s, strlen(s)); -} - -static void OnFeed(void) { - TtyWriteString("\e[K\e[2J"); -} - -static void HideCursor(void) { - TtyWriteString("\e[?25l"); -} - -static void ShowCursor(void) { - TtyWriteString("\e[?25h"); -} - -static void EnableSafePaste(void) { - TtyWriteString("\e[?2004h"); -} - -static void DisableSafePaste(void) { - TtyWriteString("\e[?2004l"); -} - -static void EnableMouseTracking(void) { - mousemode = true; - TtyWriteString("\e[?1000;1002;1015;1006h"); -} - -static void DisableMouseTracking(void) { - mousemode = false; - TtyWriteString("\e[?1000;1002;1015;1006l"); -} - -static void ToggleMouseTracking(void) { - if (mousemode) { - DisableMouseTracking(); - } else { - EnableMouseTracking(); - } -} - -static void LeaveScreen(void) { - TtyWriteString(_gc(xasprintf("\e[%d;%dH\e[S\r\n", tyn, txn))); -} - -static void GetTtySize(int fd) { - struct winsize wsize; - wsize.ws_row = tyn; - wsize.ws_col = txn; - _getttysize(fd, &wsize); - tyn = wsize.ws_row; - txn = wsize.ws_col; -} - -static void TuiRejuvinate(void) { - struct termios term; - DEBUGF("TuiRejuvinate"); - GetTtySize(ttyout); - HideCursor(); - memcpy(&term, &oldterm, sizeof(term)); - term.c_cc[VMIN] = 1; - term.c_cc[VTIME] = 1; - term.c_iflag &= ~(INPCK | ISTRIP | PARMRK | INLCR | IGNCR | ICRNL | IXON); - term.c_lflag &= ~(IEXTEN | ICANON | ECHO | ECHONL); - term.c_cflag &= ~(CSIZE | PARENB); - term.c_cflag |= CS8; - term.c_iflag |= IUTF8; - CHECK_NE(-1, ioctl(ttyout, TCSETS, &term)); - xsigaction(SIGBUS, OnSigBusted, SA_NODEFER, 0, NULL); - EnableMouseTracking(); - EnableSafePaste(); -} - -static void OnQ(void) { - INFOF("OnQ"); - action |= EXIT; -} - -static void OnV(void) { - vidya = !vidya; -} - -static void OnSigWinch(void) { - action |= WINCHED; -} - -static void OnSigInt(void) { - if (tuimode) { - action |= INT; - } else { - action |= EXIT; - } -} - -static void OnSigAlarm(void) { - action |= ALARM; -} - -static void OnSigCont(void) { - TuiRejuvinate(); - Redraw(); -} - -static void TtyRestore1(void) { - DEBUGF("TtyRestore1"); - ShowCursor(); - TtyWriteString("\e[0m"); -} - -static void TtyRestore2(void) { - DEBUGF("TtyRestore2"); - ioctl(ttyout, TCSETS, &oldterm); - DisableMouseTracking(); - DisableSafePaste(); -} - -static void TuiCleanup(void) { - sigaction(SIGCONT, oldsig + 2, NULL); - TtyRestore1(); - DisableMouseTracking(); - DisableSafePaste(); - tuimode = false; - LeaveScreen(); -} - -static void ResolveBreakpoints(void) { - long i, sym; - for (i = 0; i < breakpoints.i; ++i) { - if (breakpoints.p[i].symbol && !breakpoints.p[i].addr) { - if ((sym = DisFindSymByName(dis, breakpoints.p[i].symbol)) != -1) { - breakpoints.p[i].addr = dis->syms.p[sym].addr; - } else { - fprintf( - stderr, - "error: breakpoint not found: %s (out of %,ld loaded symbols)\n", - breakpoints.p[i].symbol, dis->syms.i); - exit(1); - } - } - } -} - -static void BreakAtNextInstruction(void) { - struct Breakpoint b; - bzero(&b, sizeof(b)); - b.addr = GetIp() + m->xedd->length; - b.oneshot = true; - PushBreakpoint(&breakpoints, &b); -} - -static void LoadSyms(void) { - LoadDebugSymbols(elf); - DisLoadElf(dis, elf); -} - -static int DrainInput(int fd) { - char buf[32]; - struct pollfd fds[1]; - if (!IsWindows()) { - for (;;) { - fds[0].fd = fd; - fds[0].events = POLLIN; - if (poll(fds, ARRAYLEN(fds), 0) == -1) return -1; - if (!(fds[0].revents & POLLIN)) break; - if (read(fd, buf, sizeof(buf)) == -1) return -1; - } - } - return 0; -} - -static int ReadCursorPosition(int *out_y, int *out_x) { - int y, x; - char *p, buf[32]; - if (readansi(ttyin, buf, sizeof(buf)) == 1) return -1; - p = buf; - if (*p == '\e') ++p; - if (*p == '[') ++p; - y = strtol(p, &p, 10); - if (*p == ';') ++p; - x = strtol(p, &p, 10); - if (*p != 'R') return ebadmsg(); - if (out_y) *out_y = MAX(1, y) - 1; - if (out_x) *out_x = MAX(1, x) - 1; - return 0; -} - -static int GetCursorPosition(int *out_y, int *out_x) { - TtyWriteString("\e[6n"); - return ReadCursorPosition(out_y, out_x); -} - -static int GetTerminalDimensions(int *out_y, int *out_x) { - TtyWriteString("\e7\e[9979;9979H\e[6n\e8"); - return ReadCursorPosition(out_y, out_x); -} - -void CommonSetup(void) { - static bool once; - if (!once) { - if (tuimode || breakpoints.i) { - LoadSyms(); - ResolveBreakpoints(); - } - once = true; - } -} - -void TuiSetup(void) { - int y, x; - bool report; - static bool once; - report = false; - if (!once) { - INFOF("loaded program %s\n%s", codepath, _gc(FormatPml4t(m))); - CommonSetup(); - ioctl(ttyout, TCGETS, &oldterm); - xsigaction(SIGINT, OnSigInt, 0, 0, oldsig + 3); - atexit(TtyRestore2); - once = true; - report = true; - } - setitimer(ITIMER_REAL, &((struct itimerval){0}), NULL); - xsigaction(SIGCONT, OnSigCont, SA_RESTART | SA_NODEFER, 0, oldsig + 2); - CopyMachineState(&laststate); - TuiRejuvinate(); - if (report) { - DrainInput(ttyin); - y = 0; - if (GetCursorPosition(&y, NULL) != -1) { - TtyWriteString(_gc(xasprintf("\e[%dS", y))); - } - } -} - -static void ExecSetup(void) { - CommonSetup(); - setitimer(ITIMER_REAL, - &((struct itimerval){{0, 1. / 60 * 1e6}, {0, 1. / 60 * 1e6}}), - NULL); -} - -static void AppendPanel(struct Panel *p, long line, const char *s) { - if (0 <= line && line < p->bottom - p->top) { - AppendStr(&p->lines[line], s); - } -} - -static bool IsXmmNonZero(long start, long end) { - long i; - uint8_t v1[16], vz[16]; - for (i = start; i < end; ++i) { - bzero(vz, 16); - memcpy(v1, m->xmm[i], 16); - pcmpeqb(v1, v1, vz); - if (pmovmskb(v1) != 0xffff) { - return true; - } - } - return false; -} - -static bool IsSegNonZero(void) { - unsigned i; - for (i = 0; i < 6; ++i) { - if (Read64(GetSegment(m, 0, i))) { - return true; - } - } - return false; -} - -static int PickNumberOfXmmRegistersToShow(void) { - if (IsXmmNonZero(0, 8) || IsXmmNonZero(8, 16)) { - if (showhighsse || IsXmmNonZero(8, 16)) { - showhighsse = true; - return 16; - } else { - return 8; - } - } else { - showhighsse = false; - return 0; - } -} - -static int GetRegHexWidth(void) { - switch (m->mode & 3) { - case XED_MODE_LONG: - return 16; - case XED_MODE_LEGACY: - return 8; - case XED_MODE_REAL: - if ((Read64(m->ax) >> 16) || (Read64(m->cx) >> 16) || - (Read64(m->dx) >> 16) || (Read64(m->bx) >> 16) || - (Read64(m->sp) >> 16) || (Read64(m->bp) >> 16) || - (Read64(m->si) >> 16) || (Read64(m->di) >> 16)) { - return 8; - } else { - return 4; - } - default: - __builtin_unreachable(); - } -} - -static int GetAddrHexWidth(void) { - switch (m->mode & 3) { - case XED_MODE_LONG: - return 12; - case XED_MODE_LEGACY: - return 8; - case XED_MODE_REAL: - if (Read64(m->fs) >= 0x10fff0 || Read64(m->gs) >= 0x10fff0) { - return 8; - } else { - return 6; - } - default: - __builtin_unreachable(); - } -} - -void SetupDraw(void) { - int i, j, n, a, b, c, yn, cpuy, ssey, dx[2], c2y[3], c3y[5]; - - cpuy = 9; - if (IsSegNonZero()) cpuy += 2; - ssey = PickNumberOfXmmRegistersToShow(); - if (ssey) ++ssey; - - a = GetAddrHexWidth() + 1 + DUMPWIDTH; - b = DISPWIDTH + 1; - c = GetAddrHexWidth() + 1 + DISWIDTH; - dx[1] = txn >= a + b ? txn - a : txn; - dx[0] = txn >= c + b + a ? txn - a - b : dx[1]; - - yn = tyn - 1; - a = 1 / 8. * yn; - b = 3 / 8. * yn; - c2y[0] = a * .7; - c2y[1] = a * 2; - c2y[2] = a * 2 + b; - if (yn - c2y[2] > 26) { - c2y[1] -= yn - c2y[2] - 26; - c2y[2] = yn - 26; - } - if (yn - c2y[2] < 26) { - c2y[2] = yn - 26; - } - - a = (yn - (cpuy + ssey) - 3) / 4; - c3y[0] = cpuy; - c3y[1] = cpuy + ssey; - c3y[2] = cpuy + ssey + 1 + 1 + a * 1; - c3y[3] = cpuy + ssey + 1 + 1 + a * 2 + 1; - c3y[4] = cpuy + ssey + 1 + 1 + 1 + a * 3 + 1; - - /* COLUMN #1: DISASSEMBLY */ - - pan.disassembly.top = 0; - pan.disassembly.left = 0; - pan.disassembly.bottom = yn; - pan.disassembly.right = dx[0] - 1; - - /* COLUMN #2: BREAKPOINTS, MEMORY MAPS, BACKTRACE, DISPLAY */ - - pan.breakpointshr.top = 0; - pan.breakpointshr.left = dx[0]; - pan.breakpointshr.bottom = 1; - pan.breakpointshr.right = dx[1] - 1; - - pan.breakpoints.top = 1; - pan.breakpoints.left = dx[0]; - pan.breakpoints.bottom = c2y[0]; - pan.breakpoints.right = dx[1] - 1; - - pan.mapshr.top = c2y[0]; - pan.mapshr.left = dx[0]; - pan.mapshr.bottom = c2y[0] + 1; - pan.mapshr.right = dx[1] - 1; - - pan.maps.top = c2y[0] + 1; - pan.maps.left = dx[0]; - pan.maps.bottom = c2y[1]; - pan.maps.right = dx[1] - 1; - - pan.frameshr.top = c2y[1]; - pan.frameshr.left = dx[0]; - pan.frameshr.bottom = c2y[1] + 1; - pan.frameshr.right = dx[1] - 1; - - pan.frames.top = c2y[1] + 1; - pan.frames.left = dx[0]; - pan.frames.bottom = c2y[2]; - pan.frames.right = dx[1] - 1; - - pan.displayhr.top = c2y[2]; - pan.displayhr.left = dx[0]; - pan.displayhr.bottom = c2y[2] + 1; - pan.displayhr.right = dx[1] - 1; - - pan.display.top = c2y[2] + 1; - pan.display.left = dx[0]; - pan.display.bottom = yn; - pan.display.right = dx[1] - 1; - - /* COLUMN #3: REGISTERS, VECTORS, CODE, MEMORY READS, MEMORY WRITES, STACK */ - - pan.registers.top = 0; - pan.registers.left = dx[1]; - pan.registers.bottom = c3y[0]; - pan.registers.right = txn; - - pan.ssehr.top = c3y[0]; - pan.ssehr.left = dx[1]; - pan.ssehr.bottom = c3y[0] + (ssey ? 1 : 0); - pan.ssehr.right = txn; - - pan.sse.top = c3y[0] + (ssey ? 1 : 0); - pan.sse.left = dx[1]; - pan.sse.bottom = c3y[1]; - pan.sse.right = txn; - - pan.codehr.top = c3y[1]; - pan.codehr.left = dx[1]; - pan.codehr.bottom = c3y[1] + 1; - pan.codehr.right = txn; - - pan.code.top = c3y[1] + 1; - pan.code.left = dx[1]; - pan.code.bottom = c3y[2]; - pan.code.right = txn; - - pan.readhr.top = c3y[2]; - pan.readhr.left = dx[1]; - pan.readhr.bottom = c3y[2] + 1; - pan.readhr.right = txn; - - pan.readdata.top = c3y[2] + 1; - pan.readdata.left = dx[1]; - pan.readdata.bottom = c3y[3]; - pan.readdata.right = txn; - - pan.writehr.top = c3y[3]; - pan.writehr.left = dx[1]; - pan.writehr.bottom = c3y[3] + 1; - pan.writehr.right = txn; - - pan.writedata.top = c3y[3] + 1; - pan.writedata.left = dx[1]; - pan.writedata.bottom = c3y[4]; - pan.writedata.right = txn; - - pan.stackhr.top = c3y[4]; - pan.stackhr.left = dx[1]; - pan.stackhr.bottom = c3y[4] + 1; - pan.stackhr.right = txn; - - pan.stack.top = c3y[4] + 1; - pan.stack.left = dx[1]; - pan.stack.bottom = yn; - pan.stack.right = txn; - - pan.status.top = yn; - pan.status.left = 0; - pan.status.bottom = yn + 1; - pan.status.right = txn; - - for (i = 0; i < ARRAYLEN(pan.p); ++i) { - if (pan.p[i].left > pan.p[i].right) { - pan.p[i].left = pan.p[i].right = 0; - } - if (pan.p[i].top > pan.p[i].bottom) { - pan.p[i].top = pan.p[i].bottom = 0; - } - n = pan.p[i].bottom - pan.p[i].top; - if (n == pan.p[i].n) { - for (j = 0; j < n; ++j) { - pan.p[i].lines[j].i = 0; - } - } else { - for (j = 0; j < pan.p[i].n; ++j) { - free(pan.p[i].lines[j].p); - } - free(pan.p[i].lines); - pan.p[i].lines = xcalloc(n, sizeof(struct Buffer)); - pan.p[i].n = n; - } - } - - PtyResize(pty, pan.display.bottom - pan.display.top, - pan.display.right - pan.display.left); -} - -static long Disassemble(void) { - long lines, current; - lines = pan.disassembly.bottom - pan.disassembly.top * 2; - if (Dis(dis, m, GetIp(), m->ip, lines) != -1) { - return DisFind(dis, GetIp()); - } else { - return -1; - } -} - -static long GetDisIndex(void) { - long i; - if ((i = DisFind(dis, GetIp())) == -1) { - i = Disassemble(); - } - while (i + 1 < dis->ops.i && !dis->ops.p[i].size) ++i; - return i; -} - -static void DrawDisassembly(struct Panel *p) { - long i, j; - for (i = 0; i < p->bottom - p->top; ++i) { - j = opstart + i; - if (0 <= j && j < dis->ops.i) { - if (j == opline) AppendPanel(p, i, "\e[7m"); - AppendPanel(p, i, DisGetLine(dis, m, j)); - if (j == opline) AppendPanel(p, i, "\e[27m"); - } - } -} - -static void DrawHr(struct Panel *p, const char *s) { - long i, wp, ws, wl, wr; - if (p->bottom - p->top < 1) return; - wp = p->right - p->left; - ws = strwidth(s, 0); - wl = wp / 4 - ws / 2; - wr = wp - (wl + ws); - for (i = 0; i < wl; ++i) AppendWide(&p->lines[0], u'─'); - AppendStr(&p->lines[0], s); - for (i = 0; i < wr; ++i) AppendWide(&p->lines[0], u'─'); - AppendStr(&p->lines[0], "\e[0m"); -} - -static void DrawTerminalHr(struct Panel *p) { - long i; - if (p->bottom == p->top) return; - if (pty->conf & kPtyBell) { - if (!alarmed) { - alarmed = true; - setitimer(ITIMER_REAL, &((struct itimerval){{0, 0}, {0, 800000}}), NULL); - } - AppendStr(&p->lines[0], "\e[1m"); - } - AppendFmt(&p->lines[0], "──────────TELETYPEWRITER──%s──%s──%s──%s", - (pty->conf & kPtyLed1) ? "\e[1;31m◎\e[0m" : "○", - (pty->conf & kPtyLed2) ? "\e[1;32m◎\e[0m" : "○", - (pty->conf & kPtyLed3) ? "\e[1;33m◎\e[0m" : "○", - (pty->conf & kPtyLed4) ? "\e[1;34m◎\e[0m" : "○"); - for (i = 36; i < p->right - p->left; ++i) { - AppendWide(&p->lines[0], u'─'); - } -} - -static void DrawTerminal(struct Panel *p) { - long y, yn; - if (p->top == p->bottom) return; - for (yn = MIN(pty->yn, p->bottom - p->top), y = 0; y < yn; ++y) { - PtyAppendLine(pty, p->lines + y, y); - AppendStr(p->lines + y, "\e[0m"); - } -} - -static void DrawDisplay(struct Panel *p) { - switch (vidya) { - case 7: - DrawHr(&pan.displayhr, "MONOCHROME DISPLAY ADAPTER"); - if (0xb0000 + 25 * 80 * 2 > m->real.n) return; - DrawMda(p, (void *)(m->real.p + 0xb0000)); - break; - case 3: - DrawHr(&pan.displayhr, "COLOR GRAPHICS ADAPTER"); - if (0xb8000 + 25 * 80 * 2 > m->real.n) return; - DrawCga(p, (void *)(m->real.p + 0xb8000)); - break; - default: - DrawTerminalHr(&pan.displayhr); - DrawTerminal(p); - break; - } -} - -static void DrawFlag(struct Panel *p, long i, char name, bool value) { - char str[3] = " "; - if (value) str[1] = name; - AppendPanel(p, i, str); -} - -static void DrawRegister(struct Panel *p, long i, long r) { - char buf[32]; - uint64_t value, previous; - value = Read64(m->reg[r]); - previous = Read64(laststate.reg[r]); - if (value != previous) AppendPanel(p, i, "\e[7m"); - snprintf(buf, sizeof(buf), "%-3s", kRegisterNames[m->mode & 3][r]); - AppendPanel(p, i, buf); - AppendPanel(p, i, " "); - snprintf(buf, sizeof(buf), "%0*lx", GetRegHexWidth(), value); - AppendPanel(p, i, buf); - if (value != previous) AppendPanel(p, i, "\e[27m"); - AppendPanel(p, i, " "); -} - -static void DrawSegment(struct Panel *p, long i, const uint8_t seg[8], - const uint8_t last[8], const char *name) { - char buf[32]; - uint64_t value, previous; - value = Read64(seg); - previous = Read64(last); - if (value != previous) AppendPanel(p, i, "\e[7m"); - snprintf(buf, sizeof(buf), "%-3s", name); - AppendPanel(p, i, buf); - AppendPanel(p, i, " "); - if ((m->mode & 3) == XED_MODE_REAL) { - snprintf(buf, sizeof(buf), "%0*lx", GetRegHexWidth(), value >> 4); - } else { - snprintf(buf, sizeof(buf), "%0*lx", GetRegHexWidth(), value); - } - AppendPanel(p, i, buf); - if (value != previous) AppendPanel(p, i, "\e[27m"); - AppendPanel(p, i, " "); -} - -static void DrawSt(struct Panel *p, long i, long r) { - char buf[32]; - long double value; - bool isempty, changed; - isempty = FpuGetTag(m, r) == kFpuTagEmpty; - if (isempty) AppendPanel(p, i, "\e[38;5;241m"); - value = m->fpu.st[(r + m->fpu.sp) & 0b111]; - changed = value != laststate.fpu.st[(r + m->fpu.sp) & 0b111]; - if (!isempty && changed) AppendPanel(p, i, "\e[7m"); - snprintf(buf, sizeof(buf), "ST%d ", r); - AppendPanel(p, i, buf); - AppendPanel(p, i, FormatDouble(buf, value)); - if (changed) AppendPanel(p, i, "\e[27m"); - AppendPanel(p, i, " "); - if (isempty) AppendPanel(p, i, "\e[39m"); -} - -static void DrawCpu(struct Panel *p) { - char buf[48]; - if (p->top == p->bottom) return; - DrawRegister(p, 0, 7), DrawRegister(p, 0, 0), DrawSt(p, 0, 0); - DrawRegister(p, 1, 6), DrawRegister(p, 1, 3), DrawSt(p, 1, 1); - DrawRegister(p, 2, 2), DrawRegister(p, 2, 5), DrawSt(p, 2, 2); - DrawRegister(p, 3, 1), DrawRegister(p, 3, 4), DrawSt(p, 3, 3); - DrawRegister(p, 4, 8), DrawRegister(p, 4, 12), DrawSt(p, 4, 4); - DrawRegister(p, 5, 9), DrawRegister(p, 5, 13), DrawSt(p, 5, 5); - DrawRegister(p, 6, 10), DrawRegister(p, 6, 14), DrawSt(p, 6, 6); - DrawRegister(p, 7, 11), DrawRegister(p, 7, 15), DrawSt(p, 7, 7); - snprintf(buf, sizeof(buf), "%-3s %0*x FLG", kRipName[m->mode & 3], - GetRegHexWidth(), m->ip); - AppendPanel(p, 8, buf); - DrawFlag(p, 8, 'C', GetFlag(m->flags, FLAGS_CF)); - DrawFlag(p, 8, 'P', GetFlag(m->flags, FLAGS_PF)); - DrawFlag(p, 8, 'A', GetFlag(m->flags, FLAGS_AF)); - DrawFlag(p, 8, 'Z', GetFlag(m->flags, FLAGS_ZF)); - DrawFlag(p, 8, 'S', GetFlag(m->flags, FLAGS_SF)); - DrawFlag(p, 8, 'I', GetFlag(m->flags, FLAGS_IF)); - DrawFlag(p, 8, 'D', GetFlag(m->flags, FLAGS_DF)); - DrawFlag(p, 8, 'O', GetFlag(m->flags, FLAGS_OF)); - AppendPanel(p, 8, " "); - if (m->fpu.ie) AppendPanel(p, 8, " IE"); - if (m->fpu.de) AppendPanel(p, 8, " DE"); - if (m->fpu.ze) AppendPanel(p, 8, " ZE"); - if (m->fpu.oe) AppendPanel(p, 8, " OE"); - if (m->fpu.ue) AppendPanel(p, 8, " UE"); - if (m->fpu.pe) AppendPanel(p, 8, " PE"); - if (m->fpu.sf) AppendPanel(p, 8, " SF"); - if (m->fpu.es) AppendPanel(p, 8, " ES"); - if (m->fpu.c0) AppendPanel(p, 8, " C0"); - if (m->fpu.c1) AppendPanel(p, 8, " C1"); - if (m->fpu.c2) AppendPanel(p, 8, " C2"); - if (m->fpu.bf) AppendPanel(p, 8, " BF"); - DrawSegment(p, 9, m->fs, laststate.fs, "FS"); - DrawSegment(p, 9, m->ds, laststate.ds, "DS"); - DrawSegment(p, 9, m->cs, laststate.cs, "CS"); - DrawSegment(p, 10, m->gs, laststate.gs, "GS"); - DrawSegment(p, 10, m->es, laststate.es, "ES"); - DrawSegment(p, 10, m->ss, laststate.ss, "SS"); -} - -static void DrawXmm(struct Panel *p, long i, long r) { - float f; - double d; - long j, k, n; - bool changed; - char buf[32]; - uint8_t xmm[16]; - uint64_t ival, itmp; - int cells, left, cellwidth, panwidth; - memcpy(xmm, m->xmm[r], sizeof(xmm)); - changed = memcmp(xmm, laststate.xmm[r], sizeof(xmm)) != 0; - if (changed) AppendPanel(p, i, "\e[7m"); - left = sprintf(buf, "XMM%-2d", r); - AppendPanel(p, i, buf); - cells = GetXmmTypeCellCount(r); - panwidth = p->right - p->left; - cellwidth = MIN(MAX(0, (panwidth - left) / cells - 1), sizeof(buf) - 1); - for (j = 0; j < cells; ++j) { - AppendPanel(p, i, " "); - switch (xmmtype.type[r]) { - case kXmmFloat: - memcpy(&f, xmm + j * sizeof(f), sizeof(f)); - FormatDouble(buf, f); - break; - case kXmmDouble: - memcpy(&d, xmm + j * sizeof(d), sizeof(d)); - FormatDouble(buf, d); - break; - case kXmmIntegral: - ival = 0; - for (k = 0; k < xmmtype.size[r]; ++k) { - itmp = xmm[j * xmmtype.size[r] + k] & 0xff; - itmp <<= k * 8; - ival |= itmp; - } - if (xmmdisp == kXmmHex || xmmdisp == kXmmChar) { - if (xmmdisp == kXmmChar && iswalnum(ival)) { - sprintf(buf, "%lc", ival); - } else { - uint64toarray_fixed16(ival, buf, xmmtype.size[r] * 8); - } - } else { - FormatInt64(buf, SignExtend(ival, xmmtype.size[r] * 8)); - } - break; - default: - __builtin_unreachable(); - } - buf[cellwidth] = '\0'; - AppendPanel(p, i, buf); - n = cellwidth - strlen(buf); - for (k = 0; k < n; ++k) { - AppendPanel(p, i, " "); - } - } - if (changed) AppendPanel(p, i, "\e[27m"); -} - -static void DrawSse(struct Panel *p) { - long i, n; - n = p->bottom - p->top; - if (n > 0) { - for (i = 0; i < MIN(16, n); ++i) { - DrawXmm(p, i, i); - } - } -} - -static void ScrollMemoryView(struct Panel *p, struct MemoryView *v, int64_t a) { - long i, n, w; - w = DUMPWIDTH * (1ull << v->zoom); - n = p->bottom - p->top; - i = a / w; - if (!(v->start <= i && i < v->start + n)) { - v->start = i - n / 4; - } -} - -static void ZoomMemoryView(struct MemoryView *v, long y, long x, int dy) { - long a, b, i, s; - s = v->start; - a = v->zoom; - b = MIN(MAXZOOM, MAX(0, a + dy)); - i = y * DUMPWIDTH - x; - s *= DUMPWIDTH * (1L << a); - s += i * (1L << a) - i * (1L << b); - s /= DUMPWIDTH * (1L << b); - v->zoom = b; - v->start = s; -} - -static void ScrollMemoryViews(void) { - ScrollMemoryView(&pan.code, &codeview, GetIp()); - ScrollMemoryView(&pan.readdata, &readview, readaddr); - ScrollMemoryView(&pan.writedata, &writeview, writeaddr); - ScrollMemoryView(&pan.stack, &stackview, GetSp()); -} - -static void ZoomMemoryViews(struct Panel *p, int y, int x, int dy) { - if (p == &pan.code) { - ZoomMemoryView(&codeview, y, x, dy); - } else if (p == &pan.readdata) { - ZoomMemoryView(&readview, y, x, dy); - } else if (p == &pan.writedata) { - ZoomMemoryView(&writeview, y, x, dy); - } else if (p == &pan.stack) { - ZoomMemoryView(&stackview, y, x, dy); - } -} - -static void DrawMemoryZoomed(struct Panel *p, struct MemoryView *view, - long histart, long hiend) { - bool high, changed; - uint8_t *canvas, *chunk, *invalid; - int64_t a, b, c, d, n, i, j, k, size; - struct ContiguousMemoryRanges ranges; - a = view->start * DUMPWIDTH * (1ull << view->zoom); - b = (view->start + (p->bottom - p->top)) * DUMPWIDTH * (1ull << view->zoom); - size = (p->bottom - p->top) * DUMPWIDTH; - canvas = xcalloc(1, size); - invalid = xcalloc(1, size); - bzero(&ranges, sizeof(ranges)); - FindContiguousMemoryRanges(m, &ranges); - for (k = i = 0; i < ranges.i; ++i) { - if ((a >= ranges.p[i].a && a < ranges.p[i].b) || - (b >= ranges.p[i].a && b < ranges.p[i].b) || - (a < ranges.p[i].a && b >= ranges.p[i].b)) { - c = MAX(a, ranges.p[i].a); - d = MIN(b, ranges.p[i].b); - n = ROUNDUP(ROUNDUP(d - c, 16), 1ull << view->zoom); - chunk = xmalloc(n); - VirtualSend(m, chunk, c, d - c); - bzero(chunk + (d - c), n - (d - c)); - for (j = 0; j < view->zoom; ++j) { - cDecimate2xUint8x8(ROUNDUP(n, 16), chunk, kThePerfectKernel); - n >>= 1; - } - j = (c - a) / (1ull << view->zoom); - memset(invalid + k, -1, j - k); - memcpy(canvas + j, chunk, MIN(n, size - j)); - k = j + MIN(n, size - j); - free(chunk); - } - } - memset(invalid + k, -1, size - k); - free(ranges.p); - high = false; - for (c = i = 0; i < p->bottom - p->top; ++i) { - AppendFmt(&p->lines[i], "%0*lx ", GetAddrHexWidth(), - ((view->start + i) * DUMPWIDTH * (1ull << view->zoom)) & - 0x0000ffffffffffff); - for (j = 0; j < DUMPWIDTH; ++j, ++c) { - a = ((view->start + i) * DUMPWIDTH + j + 0) * (1ull << view->zoom); - b = ((view->start + i) * DUMPWIDTH + j + 1) * (1ull << view->zoom); - changed = ((histart >= a && hiend < b) || - (histart && hiend && histart >= a && hiend < b)); - if (changed && !high) { - high = true; - AppendStr(&p->lines[i], "\e[7m"); - } else if (!changed && high) { - AppendStr(&p->lines[i], "\e[27m"); - high = false; - } - if (invalid[c]) { - AppendWide(&p->lines[i], u'⋅'); - } else { - AppendWide(&p->lines[i], kCp437[canvas[c]]); - } - } - if (high) { - AppendStr(&p->lines[i], "\e[27m"); - high = false; - } - } - free(invalid); - free(canvas); -} - -static void DrawMemoryUnzoomed(struct Panel *p, struct MemoryView *view, - long histart, long hiend) { - long i, j, k; - int c, s, x, sc; - bool high, changed; - high = false; - for (i = 0; i < p->bottom - p->top; ++i) { - AppendFmt(&p->lines[i], "%0*lx ", GetAddrHexWidth(), - ((view->start + i) * DUMPWIDTH) & 0x0000ffffffffffff); - for (j = 0; j < DUMPWIDTH; ++j) { - k = (view->start + i) * DUMPWIDTH + j; - c = VirtualBing(k); - s = VirtualShadow(k); - if (s != -1) { - if (s == -2) { - /* grey for shadow memory */ - x = 235; - } else { - sc = (signed char)s; - if (sc > 7) { - x = 129; /* PURPLE: shadow corruption */ - } else if (sc == kAsanHeapFree) { - x = 20; /* BLUE: heap freed */ - } else if (sc == kAsanHeapRelocated) { - x = 16; /* BLACK: heap relocated */ - } else if (sc == kAsanHeapUnderrun || sc == kAsanAllocaUnderrun) { - x = 53; /* RED+PURPLETINGE: heap underrun */ - } else if (sc == kAsanHeapOverrun || sc == kAsanAllocaOverrun) { - x = 52; /* RED: heap overrun */ - } else if (sc < 0) { - x = 52; /* RED: uncategorized invalid */ - } else if (sc > 0 && (k & 7) >= sc) { - x = 88; /* BRIGHTRED: invalid address (skew) */ - } else if (!sc || (sc > 0 && (k & 7) < sc)) { - x = 22; /* GREEN: valid address */ - } else { - abort(); - } - } - AppendFmt(&p->lines[i], "\e[38;5;253;48;5;%dm", x); - } - changed = histart <= k && k < hiend; - if (changed && !high) { - high = true; - AppendStr(&p->lines[i], "\e[7m"); - } else if (!changed && high) { - AppendStr(&p->lines[i], "\e[27m"); - high = false; - } - AppendWide(&p->lines[i], c); - if (s != -1) { - AppendStr(&p->lines[i], "\e[39;49m"); - } - } - if (high) { - AppendStr(&p->lines[i], "\e[27m"); - high = false; - } - } -} - -static void DrawMemory(struct Panel *p, struct MemoryView *view, long histart, - long hiend) { - if (p->top == p->bottom) return; - if (view->zoom) { - DrawMemoryZoomed(p, view, histart, hiend); - } else { - DrawMemoryUnzoomed(p, view, histart, hiend); - } -} - -static void DrawMaps(struct Panel *p) { - int i; - char *text, *p1, *p2; - if (p->top == p->bottom) return; - p1 = text = FormatPml4t(m); - for (i = 0; p1; ++i, p1 = p2) { - if ((p2 = strchr(p1, '\n'))) *p2++ = '\0'; - if (i >= mapsstart) { - AppendPanel(p, i - mapsstart, p1); - } - } - free(text); -} - -static void DrawBreakpoints(struct Panel *p) { - int64_t addr; - const char *name; - char *s, buf[256]; - long i, line, sym; - if (p->top == p->bottom) return; - for (line = 0, i = breakpoints.i; i--;) { - if (breakpoints.p[i].disable) continue; - if (line >= breakpointsstart) { - addr = breakpoints.p[i].addr; - sym = DisFindSym(dis, addr); - name = sym != -1 ? dis->syms.stab + dis->syms.p[sym].name : "UNKNOWN"; - s = buf; - s += sprintf(s, "%0*lx ", GetAddrHexWidth(), addr & 0x0000ffffffffffff); - CHECK_LT(Demangle(s, name, DIS_MAX_SYMBOL_LENGTH), buf + ARRAYLEN(buf)); - AppendPanel(p, line - breakpointsstart, buf); - if (sym != -1 && addr != dis->syms.p[sym].addr) { - snprintf(buf, sizeof(buf), "+%#lx", addr - dis->syms.p[sym].addr); - AppendPanel(p, line, buf); - } - } - ++line; - } -} - -static int GetPreferredStackAlignmentMask(void) { - switch (m->mode & 3) { - case XED_MODE_LONG: - return 15; - case XED_MODE_LEGACY: - return 3; - case XED_MODE_REAL: - return 3; - default: - __builtin_unreachable(); - } -} - -static void DrawFrames(struct Panel *p) { - int i, n; - long sym; - uint8_t *r; - const char *name; - char *s, line[256]; - int64_t sp, bp, rp; - if (p->top == p->bottom) return; - rp = m->ip; - bp = Read64(m->bp); - sp = Read64(m->sp); - for (i = 0; i < p->bottom - p->top;) { - sym = DisFindSym(dis, rp); - name = sym != -1 ? dis->syms.stab + dis->syms.p[sym].name : "UNKNOWN"; - s = line; - s += sprintf(s, "%0*lx %0*lx ", GetAddrHexWidth(), - (Read64(m->ss) + bp) & 0x0000ffffffffffff, GetAddrHexWidth(), - rp & 0x0000ffffffffffff); - s = Demangle(s, name, DIS_MAX_SYMBOL_LENGTH); - AppendPanel(p, i - framesstart, line); - if (sym != -1 && rp != dis->syms.p[sym].addr) { - snprintf(line, sizeof(line), "+%#lx", rp - dis->syms.p[sym].addr); - AppendPanel(p, i - framesstart, line); - } - if (!bp) break; - if (bp < sp) { - AppendPanel(p, i - framesstart, " [STRAY]"); - } else if (bp - sp <= 0x1000) { - snprintf(line, sizeof(line), " %,ld bytes", bp - sp); - AppendPanel(p, i - framesstart, line); - } - if (bp & GetPreferredStackAlignmentMask() && i) { - AppendPanel(p, i - framesstart, " [MISALIGN]"); - } - ++i; - if (((Read64(m->ss) + bp) & 0xfff) > 0xff0) break; - if (!(r = FindReal(m, Read64(m->ss) + bp))) { - AppendPanel(p, i - framesstart, "CORRUPT FRAME POINTER"); - break; - } - sp = bp; - bp = ReadWord(r + 0); - rp = ReadWord(r + 8); - } -} - -static void CheckFramePointerImpl(void) { - uint8_t *r; - int64_t bp, sp, rp; - static int64_t lastbp; - bp = Read64(m->bp); - if (bp && bp == lastbp) return; - lastbp = bp; - rp = m->ip; - sp = Read64(m->sp); - while (bp) { - if (!(r = FindReal(m, Read64(m->ss) + bp))) { - INFOF("corrupt frame: %0*lx", GetAddrHexWidth(), bp & 0x0000ffffffffffff); - ThrowProtectionFault(m); - } - sp = bp; - bp = Read64(r + 0) - 0; - rp = Read64(r + 8) - 1; - if (!bp && !(m->bofram[0] <= rp && rp <= m->bofram[1])) { - INFOF("bad frame !(%0*lx <= %0*lx <= %0*lx)", GetAddrHexWidth(), - m->bofram[0], GetAddrHexWidth(), rp, GetAddrHexWidth(), - m->bofram[1]); - ThrowProtectionFault(m); - } - } -} - -forceinline void CheckFramePointer(void) { - if (m->bofram[0]) { - CheckFramePointerImpl(); - } -} - -static bool IsExecuting(void) { - return (action & (CONTINUE | STEP | NEXT | FINISH)) && !(action & FAILURE); -} - -static int AppendStat(struct Buffer *b, const char *name, int64_t value, - bool changed) { - int width; - AppendChar(b, ' '); - if (changed) AppendStr(b, "\e[31m"); - width = AppendFmt(b, "%,8ld %s", value, name); - if (changed) AppendStr(b, "\e[39m"); - return 1 + width; -} - -static char *GetStatus(int m) { - bool first; - char *b = 0; - unsigned i, n; - long double t; - if (statusmessage && nowl() < statusexpires) { - appends(&b, statusmessage); - } else { - appends(&b, "das blinkenlights"); - } - n = ARRAYLEN(keystrokes.p); - for (first = true, t = nowl(), i = 1; i <= n; --i) { - if (!keystrokes.p[(keystrokes.i - i) % n][0]) continue; - if (t - keystrokes.s[(keystrokes.i - i) % n] > 1) continue; - if (first) { - first = false; - appends(&b, " (keystroke: "); - } else { - appendw(&b, ' '); - } - appends(&b, keystrokes.p[(keystrokes.i - i) % n]); - } - if (!first) { - appendw(&b, ')'); - } - if (action & RESTART) appends(&b, " RESTART"); - if (action & REDRAW) appends(&b, " REDRAW"); - if (action & CONTINUE) appends(&b, " CONTINUE"); - if (action & STEP) appends(&b, " STEP"); - if (action & NEXT) appends(&b, " NEXT"); - if (action & FINISH) appends(&b, " FINISH"); - if (action & FAILURE) appends(&b, " FAILURE"); - if (action & WINCHED) appends(&b, " WINCHED"); - if (action & INT) appends(&b, " INT"); - if (action & QUIT) appends(&b, " QUIT"); - if (action & EXIT) appends(&b, " EXIT"); - if (action & ALARM) appends(&b, " ALARM"); - return b; -} - -static void DrawStatus(struct Panel *p) { - int yn, xn, rw; - struct Buffer *s; - struct MachineMemstat *a, *b; - yn = p->top - p->bottom; - xn = p->right - p->left; - if (!yn || !xn) return; - rw = 0; - a = &m->memstat; - b = &lastmemstat; - s = xmalloc(sizeof(struct Buffer)); - bzero(s, sizeof(*s)); - if (ips > 0) rw += AppendStat(s, "ips", ips, false); - rw += AppendStat(s, "kb", m->real.n / 1024, false); - rw += AppendStat(s, "reserve", a->reserved, a->reserved != b->reserved); - rw += AppendStat(s, "commit", a->committed, a->committed != b->committed); - rw += AppendStat(s, "freed", a->freed, a->freed != b->freed); - rw += AppendStat(s, "tables", a->pagetables, a->pagetables != b->pagetables); - rw += AppendStat(s, "fds", m->fds.i, false); - AppendFmt(&p->lines[0], "\e[7m%-*s%s\e[0m", xn - rw, _gc(GetStatus(xn - rw)), - s->p); - free(s->p); - free(s); - memcpy(b, a, sizeof(*a)); -} - -static void PreventBufferbloat(void) { - long double now, rate; - static long double last; - now = nowl(); - rate = 1. / 60; - if (now - last < rate) { - dsleep(rate - (now - last)); - } - last = now; -} - -static void Redraw(void) { - int i, j; - if (belay) return; - oldlen = m->xedd->length; - if (!IsShadow(m->readaddr) && !IsShadow(m->readaddr + m->readsize)) { - readaddr = m->readaddr; - readsize = m->readsize; - } - if (!IsShadow(m->writeaddr) && !IsShadow(m->writeaddr + m->writesize)) { - writeaddr = m->writeaddr; - writesize = m->writesize; - } - ScrollOp(&pan.disassembly, GetDisIndex()); - if (last_opcount) { - ips = unsignedsubtract(opcount, last_opcount) / (nowl() - last_seconds); - } - SetupDraw(); - for (i = 0; i < ARRAYLEN(pan.p); ++i) { - for (j = 0; j < pan.p[i].bottom - pan.p[i].top; ++j) { - pan.p[i].lines[j].i = 0; - } - } - DrawDisassembly(&pan.disassembly); - DrawDisplay(&pan.display); - DrawCpu(&pan.registers); - DrawSse(&pan.sse); - DrawHr(&pan.breakpointshr, "BREAKPOINTS"); - DrawHr(&pan.mapshr, "PML4T"); - DrawHr(&pan.frameshr, m->bofram[0] ? "PROTECTED FRAMES" : "FRAMES"); - DrawHr(&pan.ssehr, "SSE"); - DrawHr(&pan.codehr, "CODE"); - DrawHr(&pan.readhr, "READ"); - DrawHr(&pan.writehr, "WRITE"); - DrawHr(&pan.stackhr, "STACK"); - DrawMaps(&pan.maps); - DrawFrames(&pan.frames); - DrawBreakpoints(&pan.breakpoints); - DrawMemory(&pan.code, &codeview, GetIp(), GetIp() + m->xedd->length); - DrawMemory(&pan.readdata, &readview, readaddr, readaddr + readsize); - DrawMemory(&pan.writedata, &writeview, writeaddr, writeaddr + writesize); - DrawMemory(&pan.stack, &stackview, GetSp(), GetSp() + GetPointerWidth()); - DrawStatus(&pan.status); - PreventBufferbloat(); - if (PrintPanels(ttyout, ARRAYLEN(pan.p), pan.p, tyn, txn) == -1) { - INFOF("PrintPanels Interrupted"); - CHECK_EQ(EINTR, errno); - } - last_opcount = opcount; - last_seconds = nowl(); - CopyMachineState(&laststate); -} - -static void ReactiveDraw(void) { - if (tuimode) { - Redraw(); - tick = speed; - } -} - -static void DescribeKeystroke(char *b, const char *p) { - int c; - do { - c = *p++ & 255; - if (c == '\e') { - b = stpcpy(b, "ALT-"); - c = *p++ & 255; - } - if (c <= 32) { - b = stpcpy(b, "CTRL-"); - c = CTRL(c); - } - *b++ = c; - *b = 0; - } while (*p); -} - -static void RecordKeystroke(const char *k) { - keystrokes.s[keystrokes.i] = nowl(); - DescribeKeystroke(keystrokes.p[keystrokes.i], k); - keystrokes.i = (keystrokes.i + 1) % ARRAYLEN(keystrokes.p); -} - -static void HandleAlarm(void) { - alarmed = false; - action &= ~ALARM; - pty->conf &= ~kPtyBell; - free(statusmessage); - statusmessage = NULL; -} - -static void HandleAppReadInterrupt(void) { - DEBUGF("HandleAppReadInterrupt"); - if (action & ALARM) { - HandleAlarm(); - } - if (action & WINCHED) { - GetTtySize(ttyout); - action &= ~WINCHED; - } - if (action & INT) { - action &= ~INT; - RecordKeystroke("\3"); - ReactiveDraw(); - if (action & CONTINUE) { - action &= ~CONTINUE; - } else { - if (tuimode) { - LeaveScreen(); - TuiCleanup(); - } - exit(0); - } - } -} - -static int OnPtyFdClose(int fd) { - return close(fd); -} - -static bool HasPendingInput(int fd) { - struct pollfd fds[1]; - fds[0].fd = fd; - fds[0].events = POLLIN; - fds[0].revents = 0; - poll(fds, ARRAYLEN(fds), 0); - return fds[0].revents & (POLLIN | POLLERR); -} - -static struct Panel *LocatePanel(int y, int x) { - int i; - for (i = 0; i < ARRAYLEN(pan.p); ++i) { - if ((pan.p[i].left <= x && x < pan.p[i].right) && - (pan.p[i].top <= y && y < pan.p[i].bottom)) { - return &pan.p[i]; - } - } - return NULL; -} - -static struct Mouse ParseMouse(char *p) { - int e, x, y; - struct Mouse m; - e = strtol(p, &p, 10); - if (*p == ';') ++p; - x = min(txn, max(1, strtol(p, &p, 10))) - 1; - if (*p == ';') ++p; - y = min(tyn, max(1, strtol(p, &p, 10))) - 1; - e |= (*p == 'm') << 2; - m.y = y; - m.x = x; - m.e = e; - return m; -} - -static ssize_t ReadAnsi(int fd, char *p, size_t n) { - ssize_t rc; - struct Mouse m; - for (;;) { - ReactiveDraw(); - if ((rc = readansi(fd, p, n)) != -1) { - if (tuimode && rc > 3 && p[0] == '\e' && p[1] == '[') { - if (p[2] == '2' && p[3] == '0' && p[4] == '0' && p[5] == '~') { - belay = true; - continue; - } - if (p[2] == '2' && p[3] == '0' && p[4] == '1' && p[5] == '~') { - belay = false; - continue; - } - if (p[2] == '<') { - m = ParseMouse(p + 3); - if (LocatePanel(m.y, m.x) != &pan.display) { - HandleKeyboard(p); - continue; - } - } - } - return rc; - } else { - CHECK_EQ(EINTR, errno); - HandleAppReadInterrupt(); - } - } -} - -static ssize_t ReadPtyFdDirect(int fd) { - ssize_t rc; - char buf[32]; - pty->conf |= kPtyBlinkcursor; - rc = ReadAnsi(fd, buf, sizeof(buf)); - pty->conf &= ~kPtyBlinkcursor; - if (rc > 0) { - PtyWriteInput(pty, buf, rc); - ReactiveDraw(); - rc = 0; - } - return rc; -} - -static ssize_t OnPtyFdReadv(int fd, const struct iovec *iov, int iovlen) { - int i; - ssize_t rc; - void *data; - size_t size; - for (size = i = 0; i < iovlen; ++i) { - if (iov[i].iov_len) { - data = iov[i].iov_base; - size = iov[i].iov_len; - break; - } - } - if (size) { - for (;;) { - if ((rc = PtyRead(pty, data, size))) { - return rc; - } - if (ReadPtyFdDirect(fd) == -1) { - return -1; - } - } - } else { - return 0; - } -} - -static int OnPtyFdPoll(struct pollfd *fds, size_t nfds, int ms) { - bool once, rem; - int i, t, re, rc; - struct pollfd p2; - ms &= INT_MAX; - for (once = t = i = 0; i < nfds; ++i) { - re = 0; - if (fds[i].fd >= 0) { - if (pty->input.i) { - re = POLLIN | POLLOUT; - ++t; - } else { - if (!once) { - ReactiveDraw(); - once = true; - } - p2.fd = fds[i].fd; - p2.events = fds[i].events; - if (!IsWindows()) { - switch (poll(&p2, 1, ms)) { - case -1: - re = POLLERR; - ++t; - break; - case 0: - break; - case 1: - re = p2.revents; - ++t; - break; - default: - __builtin_unreachable(); - } - } - } - } - fds[i].revents = re; - } - return t; -} - -static void DrawDisplayOnly(struct Panel *p) { - struct Buffer b; - int i, y, yn, xn, tly, tlx, conf; - yn = MIN(tyn, p->bottom - p->top); - xn = MIN(txn, p->right - p->left); - for (i = 0; i < yn; ++i) { - p->lines[i].i = 0; - } - DrawDisplay(p); - bzero(&b, sizeof(b)); - tly = tyn / 2 - yn / 2; - tlx = txn / 2 - xn / 2; - AppendStr(&b, "\e[0m\e[H"); - for (y = 0; y < tyn; ++y) { - if (y) AppendStr(&b, "\r\n"); - if (tly <= y && y <= tly + yn) { - for (i = 0; i < tlx; ++i) { - AppendChar(&b, ' '); - } - AppendData(&b, p->lines[y - tly].p, p->lines[y - tly].i); - } - AppendStr(&b, "\e[0m\e[K"); - } - write(ttyout, b.p, b.i); - free(b.p); -} - -static ssize_t OnPtyFdWritev(int fd, const struct iovec *iov, int iovlen) { - int i; - size_t size; - for (size = i = 0; i < iovlen; ++i) { - PtyWrite(pty, iov[i].iov_base, iov[i].iov_len); - size += iov[i].iov_len; - } - return size; -} - -static int OnPtyFdTiocgwinsz(int fd, struct winsize *ws) { - ws->ws_row = pty->yn; - ws->ws_col = pty->xn; - return 0; -} - -static int OnPtyFdTcgets(int fd, struct termios *c) { - bzero(c, sizeof(*c)); - if (!(pty->conf & kPtyNocanon)) c->c_iflag |= ICANON; - if (!(pty->conf & kPtyNoecho)) c->c_iflag |= ECHO; - if (!(pty->conf & kPtyNoopost)) c->c_oflag |= OPOST; - return 0; -} - -static int OnPtyFdTcsets(int fd, uint64_t request, struct termios *c) { - if (c->c_iflag & ICANON) { - pty->conf &= ~kPtyNocanon; - } else { - pty->conf |= kPtyNocanon; - } - if (c->c_iflag & ECHO) { - pty->conf &= ~kPtyNoecho; - } else { - pty->conf |= kPtyNoecho; - } - if (c->c_oflag & OPOST) { - pty->conf &= ~kPtyNoopost; - } else { - pty->conf |= kPtyNoopost; - } - return 0; -} - -static int OnPtyFdIoctl(int fd, int request, void *memory) { - if (request == TIOCGWINSZ) { - return OnPtyFdTiocgwinsz(fd, memory); - } else if (request == TCGETS) { - return OnPtyFdTcgets(fd, memory); - } else if (request == TCSETS || request == TCSETSW || request == TCSETSF) { - return OnPtyFdTcsets(fd, request, memory); - } else { - return einval(); - } -} - -static const struct MachineFdCb kMachineFdCbPty = { - .close = OnPtyFdClose, - .readv = OnPtyFdReadv, - .writev = OnPtyFdWritev, - .ioctl = (void *)OnPtyFdIoctl, - .poll = OnPtyFdPoll, -}; - -static void LaunchDebuggerReactively(void) { - INFOF("%s", systemfailure); - if (tuimode) { - action |= FAILURE; - } else { - if (react) { - tuimode = true; - action |= FAILURE; - } else { - fprintf(stderr, "ERROR: %s\n", systemfailure); - exit(1); - } - } -} - -static void OnDebug(void) { - strcpy(systemfailure, "IT'S A TRAP"); - LaunchDebuggerReactively(); -} - -static void OnSegmentationFault(void) { - snprintf(systemfailure, sizeof(systemfailure), "SEGMENTATION FAULT %0*lx", - GetAddrHexWidth(), m->faultaddr & 0x0000ffffffffffff); - LaunchDebuggerReactively(); -} - -static void OnProtectionFault(void) { - strcpy(systemfailure, "PROTECTION FAULT"); - LaunchDebuggerReactively(); -} - -static void OnSimdException(void) { - strcpy(systemfailure, "SIMD FAULT"); - LaunchDebuggerReactively(); -} - -static void OnUndefinedInstruction(void) { - strcpy(systemfailure, "UNDEFINED INSTRUCTION"); - LaunchDebuggerReactively(); -} - -static void OnDecodeError(void) { - strcpy(stpcpy(systemfailure, "DECODE: "), - IndexDoubleNulString(kXedErrorNames, m->xedd->op.error)); - LaunchDebuggerReactively(); -} - -static void OnDivideError(void) { - strcpy(systemfailure, "DIVIDE BY ZERO OR BANE/-1"); - LaunchDebuggerReactively(); -} - -static void OnFpuException(void) { - strcpy(systemfailure, "FPU EXCEPTION"); - LaunchDebuggerReactively(); -} - -static void OnExit(int rc) { - exitcode = rc; - action |= EXIT; -} - -static size_t GetLastIndex(size_t size, unsigned unit, int i, unsigned limit) { - unsigned q, r; - if (!size) return 0; - q = size / unit; - r = size % unit; - if (!r) --q; - q += i; - if (q > limit) q = limit; - return q; -} - -static void OnDiskServiceReset(void) { - m->ax[1] = 0x00; - SetCarry(false); -} - -static void OnDiskServiceBadCommand(void) { - m->ax[1] = 0x01; - SetCarry(true); -} - -static void OnDiskServiceGetParams(void) { - size_t lastsector, lastcylinder, lasthead; - lastcylinder = GetLastIndex(elf->mapsize, 512 * 63 * 255, 0, 1023); - lasthead = GetLastIndex(elf->mapsize, 512 * 63, 0, 255); - lastsector = GetLastIndex(elf->mapsize, 512, 1, 63); - m->dx[0] = 1; - m->dx[1] = lasthead; - m->cx[0] = lastcylinder >> 8 << 6 | lastsector; - m->cx[1] = lastcylinder; - m->ax[1] = 0; - Write64(m->es, 0); - Write16(m->di, 0); - SetCarry(false); -} - -static void OnDiskServiceReadSectors(void) { - static int x; - uint64_t addr, size; - int64_t sectors, drive, head, cylinder, sector, offset; - sectors = m->ax[0]; - drive = m->dx[0]; - head = m->dx[1]; - cylinder = (m->cx[0] & 0b11000000) << 2 | m->cx[1]; - sector = (m->cx[0] & 0b00111111) - 1; - size = sectors * 512; - offset = sector * 512 + head * 512 * 63 + cylinder * 512 * 63 * 255; - VERBOSEF("bios read sectors %d " - "@ sector %ld cylinder %ld head %ld drive %ld offset %#lx", - sectors, sector, cylinder, head, drive, offset); - if (0 <= sector && offset + size <= elf->mapsize) { - addr = Read64(m->es) + Read16(m->bx); - if (addr + size <= m->real.n) { - SetWriteAddr(m, addr, size); - memcpy(m->real.p + addr, elf->map + offset, size); - m->ax[1] = 0x00; - SetCarry(false); - } else { - m->ax[0] = 0x00; - m->ax[1] = 0x02; - SetCarry(true); - } - } else { - WARNF("bios read sector failed 0 <= %d && %lx + %lx <= %lx", sector, offset, - size, elf->mapsize); - m->ax[0] = 0x00; - m->ax[1] = 0x0d; - SetCarry(true); - } -} - -static void OnDiskService(void) { - switch (m->ax[1]) { - case 0x00: - OnDiskServiceReset(); - break; - case 0x02: - OnDiskServiceReadSectors(); - break; - case 0x08: - OnDiskServiceGetParams(); - break; - default: - OnDiskServiceBadCommand(); - break; - } -} - -static void OnVidyaServiceSetMode(void) { - if (FindReal(m, 0xB0000)) { - vidya = m->ax[0]; - } else { - WARNF("maybe you forgot -r flag"); - } -} - -static void OnVidyaServiceGetMode(void) { - m->ax[0] = vidya; - m->ax[1] = 80; // columns - m->bx[1] = 0; // page -} - -static void OnVidyaServiceSetCursorPosition(void) { - PtySetY(pty, m->dx[1]); - PtySetX(pty, m->dx[0]); -} - -static void OnVidyaServiceGetCursorPosition(void) { - m->dx[1] = pty->y; - m->dx[0] = pty->x; - m->cx[1] = 5; // cursor ▂ scan lines 5..7 of 0..7 - m->cx[0] = 7 | !!(pty->conf & kPtyNocursor) << 5; -} - -static int GetVidyaByte(unsigned char b) { - if (0x20 <= b && b <= 0x7F) return b; -#if 0 - /* - * The original hardware displayed 0x00, 0x20, and 0xff as space. It - * made sense for viewing sparse binary data that 0x00 be blank. But - * it doesn't make sense for dense data too, and we don't need three - * space characters. So we diverge in our implementation and display - * 0xff as lambda. - */ - if (b == 0xFF) b = 0x00; -#endif - return kCp437[b]; -} - -static void OnVidyaServiceWriteCharacter(void) { - uint64_t w; - int i, n, y, x; - char *p, buf[32]; - p = buf; - p += FormatCga(m->bx[0], p); - p = stpcpy(p, "\e7"); - w = _tpenc(GetVidyaByte(m->ax[0])); - do { - *p++ = w; - } while ((w >>= 8)); - p = stpcpy(p, "\e8"); - for (i = Read16(m->cx); i--;) { - PtyWrite(pty, buf, p - buf); - } -} - -static char16_t VidyaServiceXlatTeletype(uint8_t c) { - switch (c) { - case '\a': - case '\b': - case '\r': - case '\n': - case 0177: - return c; - default: - return GetVidyaByte(c); - } -} - -static void OnVidyaServiceTeletypeOutput(void) { - int n; - uint64_t w; - char buf[12]; - n = 0 /* FormatCga(m->bx[0], buf) */; - w = _tpenc(VidyaServiceXlatTeletype(m->ax[0])); - do buf[n++] = w; - while ((w >>= 8)); - PtyWrite(pty, buf, n); -} - -static void OnVidyaService(void) { - switch (m->ax[1]) { - case 0x00: - OnVidyaServiceSetMode(); - break; - case 0x02: - OnVidyaServiceSetCursorPosition(); - break; - case 0x03: - OnVidyaServiceGetCursorPosition(); - break; - case 0x09: - OnVidyaServiceWriteCharacter(); - break; - case 0x0E: - OnVidyaServiceTeletypeOutput(); - break; - case 0x0F: - OnVidyaServiceGetMode(); - break; - default: - break; - } -} - -static void OnKeyboardServiceReadKeyPress(void) { - wint_t x; - uint8_t b; - size_t i, n; - struct Mouse mo; - static char buf[32]; - static size_t pending; - pty->conf |= kPtyBlinkcursor; - if (!pending && !(pending = ReadAnsi(ttyin, buf, sizeof(buf)))) { - exitcode = 0; - action |= EXIT; - return; - } - b = buf[0]; - memmove(buf, buf + 1, pending - 1); - --pending; - pty->conf &= ~kPtyBlinkcursor; - ReactiveDraw(); - if (b == 0x7F) b = '\b'; - m->ax[0] = b; - m->ax[1] = 0; -} - -static void OnKeyboardService(void) { - switch (m->ax[1]) { - case 0x00: - OnKeyboardServiceReadKeyPress(); - break; - default: - break; - } -} - -static void OnApmService(void) { - if (Read16(m->ax) == 0x5300 && Read16(m->bx) == 0x0000) { - Write16(m->bx, 'P' << 8 | 'M'); - SetCarry(false); - } else if (Read16(m->ax) == 0x5301 && Read16(m->bx) == 0x0000) { - SetCarry(false); - } else if (Read16(m->ax) == 0x5307 && m->bx[0] == 1 && m->cx[0] == 3) { - INFOF("APM SHUTDOWN"); - exit(0); - } else { - SetCarry(true); - } -} - -static void OnE820(void) { - uint8_t p[20]; - uint64_t addr; - addr = Read64(m->es) + Read16(m->di); - if (Read32(m->dx) == 0x534D4150 && Read32(m->cx) == 24 && - addr + sizeof(p) <= m->real.n) { - if (!Read32(m->bx)) { - Write64(p + 0, 0); - Write64(p + 8, m->real.n); - Write32(p + 16, 1); - memcpy(m->real.p + addr, p, sizeof(p)); - SetWriteAddr(m, addr, sizeof(p)); - Write32(m->cx, sizeof(p)); - Write32(m->bx, 1); - } else { - Write32(m->bx, 0); - Write32(m->cx, 0); - } - Write32(m->ax, 0x534D4150); - SetCarry(false); - } else { - SetCarry(true); - } -} - -static void OnInt15h(void) { - if (Read32(m->ax) == 0xE820) { - OnE820(); - } else if (m->ax[1] == 0x53) { - OnApmService(); - } else { - SetCarry(true); - } -} - -static bool OnHalt(int interrupt) { - ReactiveDraw(); - switch (interrupt) { - case 1: - case 3: - OnDebug(); - return false; - case 0x13: - OnDiskService(); - return true; - case 0x10: - OnVidyaService(); - return true; - case 0x15: - OnInt15h(); - return true; - case 0x16: - OnKeyboardService(); - return true; - case kMachineSegmentationFault: - OnSegmentationFault(); - return false; - case kMachineProtectionFault: - OnProtectionFault(); - return false; - case kMachineSimdException: - OnSimdException(); - return false; - case kMachineUndefinedInstruction: - OnUndefinedInstruction(); - return false; - case kMachineDecodeError: - OnDecodeError(); - return false; - case kMachineDivideError: - OnDivideError(); - return false; - case kMachineFpuException: - OnFpuException(); - return false; - case kMachineExit: - case kMachineHalt: - default: - OnExit(interrupt); - return false; - } -} - -static void OnBinbase(struct Machine *m) { - unsigned i; - int64_t skew; - skew = m->xedd->op.disp * 512; - INFOF("skew binbase %,ld @ %0*lx", skew, GetAddrHexWidth(), - GetIp() & 0x0000ffffffffffff); - for (i = 0; i < dis->syms.i; ++i) dis->syms.p[i].addr += skew; - for (i = 0; i < dis->loads.i; ++i) dis->loads.p[i].addr += skew; - for (i = 0; i < breakpoints.i; ++i) breakpoints.p[i].addr += skew; - Disassemble(); -} - -static void OnLongBranch(struct Machine *m) { - if (tuimode) { - Disassemble(); - } -} - -static void OnPageUp(void) { - opstart -= tyn / 2; -} - -static void OnPageDown(void) { - opstart += tyn / 2; -} - -static void SetStatus(const char *fmt, ...) { - char *s; - va_list va; - int y, x, n; - va_start(va, fmt); - s = xvasprintf(fmt, va); - va_end(va); - free(statusmessage); - statusmessage = s; - statusexpires = nowl() + 1; - setitimer(ITIMER_REAL, &((struct itimerval){{0, 0}, {1, 0}}), NULL); -} - -static int ClampSpeed(int s) { - return MAX(-0x1000, MIN(0x40000000, s)); -} - -static void OnTurbo(void) { - if (!speed || speed == -1) { - speed = 1; - } else if (speed > 0) { - speed = ClampSpeed(speed << 1); - } else { - speed = ClampSpeed(speed >> 1); - } - SetStatus("speed %,d", speed); -} - -static void OnSlowmo(void) { - if (!speed || speed == 1) { - speed = -1; - } else if (speed > 0) { - speed = ClampSpeed(speed >> 1); - } else { - speed = ClampSpeed((unsigned)speed << 1); - } - SetStatus("speed %,d", speed); -} - -static void OnUpArrow(void) { - --opstart; -} - -static void OnDownArrow(void) { - ++opstart; -} - -static void OnHome(void) { - opstart = 0; -} - -static void OnEnd(void) { - opstart = dis->ops.i - (pan.disassembly.bottom - pan.disassembly.top); -} - -static void OnEnter(void) { - action &= ~FAILURE; -} - -static void OnTab(void) { - focus = (focus + 1) % ARRAYLEN(pan.p); -} - -static void OnUp(void) { -} - -static void OnDown(void) { -} - -static void OnStep(void) { - if (action & FAILURE) return; - action |= STEP; - action &= ~NEXT; - action &= ~CONTINUE; -} - -static void OnNext(void) { - if (action & FAILURE) return; - action ^= NEXT; - action &= ~STEP; - action &= ~FINISH; - action &= ~CONTINUE; -} - -static void OnFinish(void) { - if (action & FAILURE) return; - action ^= FINISH; - action &= ~NEXT; - action &= ~FAILURE; - action &= ~CONTINUE; -} - -static void OnContinueTui(void) { - action ^= CONTINUE; - action &= ~STEP; - action &= ~NEXT; - action &= ~FINISH; - action &= ~FAILURE; -} - -static void OnContinueExec(void) { - tuimode = false; - action |= CONTINUE; - action &= ~STEP; - action &= ~NEXT; - action &= ~FINISH; - action &= ~FAILURE; -} - -static void OnQuit(void) { - action |= QUIT; -} - -static void OnRestart(void) { - action |= RESTART; -} - -static void OnXmmType(void) { - uint8_t t; - unsigned i; - t = CycleXmmType(xmmtype.type[0]); - for (i = 0; i < 16; ++i) { - xmmtype.type[i] = t; - } -} - -static void SetXmmSize(int bytes) { - unsigned i; - for (i = 0; i < 16; ++i) { - xmmtype.size[i] = bytes; - } -} - -static void SetXmmDisp(int disp) { - xmmdisp = disp; -} - -static void OnXmmSize(void) { - SetXmmSize(CycleXmmSize(xmmtype.size[0])); -} - -static void OnXmmDisp(void) { - SetXmmDisp(CycleXmmDisp(xmmdisp)); -} - -static bool HasPendingKeyboard(void) { - return HasPendingInput(ttyin); -} - -static void Sleep(int ms) { - if (IsWindows()) { - usleep(ms * 1000L); - } else { - poll((struct pollfd[]){{ttyin, POLLIN}}, 1, ms); - } -} - -static void OnMouseWheelUp(struct Panel *p, int y, int x) { - if (p == &pan.disassembly) { - opstart -= WHEELDELTA; - } else if (p == &pan.code) { - codeview.start -= WHEELDELTA; - } else if (p == &pan.readdata) { - readview.start -= WHEELDELTA; - } else if (p == &pan.writedata) { - writeview.start -= WHEELDELTA; - } else if (p == &pan.stack) { - stackview.start -= WHEELDELTA; - } else if (p == &pan.maps) { - mapsstart = MAX(0, mapsstart - 1); - } else if (p == &pan.frames) { - framesstart = MAX(0, framesstart - 1); - } else if (p == &pan.breakpoints) { - breakpointsstart = MAX(0, breakpointsstart - 1); - } -} - -static void OnMouseWheelDown(struct Panel *p, int y, int x) { - if (p == &pan.disassembly) { - opstart += WHEELDELTA; - } else if (p == &pan.code) { - codeview.start += WHEELDELTA; - } else if (p == &pan.readdata) { - readview.start += WHEELDELTA; - } else if (p == &pan.writedata) { - writeview.start += WHEELDELTA; - } else if (p == &pan.stack) { - stackview.start += WHEELDELTA; - } else if (p == &pan.maps) { - mapsstart += 1; - } else if (p == &pan.frames) { - framesstart += 1; - } else if (p == &pan.breakpoints) { - breakpointsstart += 1; - } -} - -static void OnMouseCtrlWheelUp(struct Panel *p, int y, int x) { - ZoomMemoryViews(p, y, x, -1); -} - -static void OnMouseCtrlWheelDown(struct Panel *p, int y, int x) { - ZoomMemoryViews(p, y, x, +1); -} - -static void OnMouse(char *p) { - int e, x, y; - struct Mouse m; - struct Panel *ep; - m = ParseMouse(p); - if ((ep = LocatePanel(m.y, m.x))) { - m.y -= ep->top; - m.x -= ep->left; - switch (m.e) { - CASE(kMouseWheelUp, OnMouseWheelUp(ep, m.y, m.x)); - CASE(kMouseWheelDown, OnMouseWheelDown(ep, m.y, m.x)); - CASE(kMouseCtrlWheelUp, OnMouseCtrlWheelUp(ep, m.y, m.x)); - CASE(kMouseCtrlWheelDown, OnMouseCtrlWheelDown(ep, m.y, m.x)); - default: - break; - } - } -} - -static void OnHelp(void) { - DEBUGF("setting dialog"); - dialog = HELP; -} - -static void HandleKeyboard(const char *k) { - const char *p = k; - switch (*p++) { - CASE('q', OnQ()); - CASE('v', OnV()); - CASE('?', OnHelp()); - CASE('s', OnStep()); - CASE('n', OnNext()); - CASE('f', OnFinish()); - CASE('c', OnContinueTui()); - CASE('C', OnContinueExec()); - CASE('R', OnRestart()); - CASE('x', OnXmmDisp()); - CASE('t', OnXmmType()); - CASE('T', OnXmmSize()); - CASE('u', OnUp()); - CASE('d', OnDown()); - CASE('B', PopBreakpoint(&breakpoints)); - CASE('M', ToggleMouseTracking()); - CASE('\t', OnTab()); - CASE('\r', OnEnter()); - CASE('\n', OnEnter()); - CASE(CTRL('C'), OnSigInt()); - CASE(CTRL('D'), OnSigInt()); - CASE(CTRL('\\'), OnQuit()); - CASE(CTRL('Z'), raise(SIGSTOP)); - CASE(CTRL('L'), OnFeed()); - CASE(CTRL('P'), OnUpArrow()); - CASE(CTRL('N'), OnDownArrow()); - CASE(CTRL('V'), OnPageDown()); - CASE(CTRL('T'), OnTurbo()); - case '\e': - switch (*p++) { - CASE('v', OnPageUp()); /* alt+v */ - CASE('t', OnSlowmo()); /* alt+t */ - case 'O': - switch (*p++) { - CASE('P', OnHelp()); /* \eOP is F1 */ - default: - return; - } - return; - case '[': - switch (*p++) { - CASE('<', OnMouse(p)); - CASE('A', OnUpArrow()); /* \e[A is up */ - CASE('B', OnDownArrow()); /* \e[B is down */ - CASE('F', OnEnd()); /* \e[F is end */ - CASE('H', OnHome()); /* \e[H is home */ - CASE('1', OnHome()); /* \e[1~ is home */ - CASE('4', OnEnd()); /* \e[1~ is end */ - CASE('5', OnPageUp()); /* \e[1~ is pgup */ - CASE('6', OnPageDown()); /* \e[1~ is pgdn */ - default: - return; - } - return; - default: - return; - } - break; - default: - return; - } - RecordKeystroke(k); -} - -static void ReadKeyboard(void) { - char buf[64]; - bzero(buf, sizeof(buf)); - dialog = NULL; - if (readansi(ttyin, buf, sizeof(buf)) == -1) { - if (errno == EINTR) { - INFOF("ReadKeyboard interrupted"); - return; - } - FATALF("ReadKeyboard failed: %s", strerror(errno)); - } - HandleKeyboard(buf); -} - -static int64_t ParseHexValue(const char *s) { - char *ep; - int64_t x; - x = strtoll(s, &ep, 16); - if (*ep) { - fputs("ERROR: bad hexadecimal: ", stderr); - fputs(s, stderr); - fputc('\n', stderr); - exit(EXIT_FAILURE); - } - return x; -} - -static void HandleBreakpointFlag(const char *s) { - struct Breakpoint b; - bzero(&b, sizeof(b)); - if (isdigit(*s)) { - b.addr = ParseHexValue(s); - } else { - b.symbol = optarg; - } - PushBreakpoint(&breakpoints, &b); -} - -static wontreturn void PrintUsage(int rc, FILE *f) { - fprintf(f, "SYNOPSIS\n\n %s%s", program_invocation_name, USAGE); - exit(rc); -} - -static void Exec(void) { - long op; - ssize_t bp; - int interrupt; - ExecSetup(); - if (!(interrupt = setjmp(m->onhalt))) { - if (!(action & CONTINUE) && - (bp = IsAtBreakpoint(&breakpoints, GetIp())) != -1) { - INFOF("BREAK1 %0*lx", GetAddrHexWidth(), - breakpoints.p[bp].addr & 0x0000ffffffffffff); - tuimode = true; - LoadInstruction(m); - ExecuteInstruction(m); - if (m->signals.i < m->signals.n) { - ConsumeSignal(m); - } - ++opcount; - CheckFramePointer(); - } else { - action &= ~CONTINUE; - for (;;) { - LoadInstruction(m); - if ((bp = IsAtBreakpoint(&breakpoints, GetIp())) != -1) { - INFOF("BREAK2 %0*lx", GetAddrHexWidth(), - breakpoints.p[bp].addr & 0x0000ffffffffffff); - action &= ~(FINISH | NEXT | CONTINUE); - tuimode = true; - break; - } - ExecuteInstruction(m); - if (m->signals.i < m->signals.n) { - ConsumeSignal(m); - } - ++opcount; - KeepGoing: - CheckFramePointer(); - if (action & ALARM) { - /* TODO(jart): Fix me */ - /* DrawDisplayOnly(&pan.display); */ - action &= ~ALARM; - } - if (action & EXIT) { - INFOF("EXEC EXIT"); - break; - } - if (action & INT) { - INFOF("EXEC INT"); - if (react) { - INFOF("REACT"); - action &= ~(INT | STEP | FINISH | NEXT); - tuimode = true; - } - break; - } - } - } - } else { - if (OnHalt(interrupt)) { - goto KeepGoing; - } - } -} - -static void Tui(void) { - long op; - ssize_t bp; - int interrupt; - bool interactive; - INFOF("TUI"); - TuiSetup(); - SetupDraw(); - ScrollOp(&pan.disassembly, GetDisIndex()); - if (!(interrupt = setjmp(m->onhalt))) { - do { - if (!(action & FAILURE)) { - LoadInstruction(m); - if ((action & (FINISH | NEXT | CONTINUE)) && - (bp = IsAtBreakpoint(&breakpoints, GetIp())) != -1) { - action &= ~(FINISH | NEXT | CONTINUE); - INFOF("BREAK %0*lx", GetAddrHexWidth(), - breakpoints.p[bp].addr & 0x0000ffffffffffff); - } - } else { - m->xedd = (struct XedDecodedInst *)m->icache[0]; - m->xedd->length = 1; - m->xedd->bytes[0] = 0xCC; - m->xedd->op.opcode = 0xCC; - } - if (action & WINCHED) { - GetTtySize(ttyout); - action &= ~WINCHED; - } - interactive = ++tick > speed; - if (interactive && speed < 0) { - Sleep(-speed); - } - if (action & ALARM) { - HandleAlarm(); - } - if (action & FAILURE) { - ScrollMemoryViews(); - } - if (!(action & CONTINUE) || interactive) { - tick = 0; - Redraw(); - } - if (dialog) { - PrintMessageBox(ttyout, dialog, tyn, txn); - } - if (action & FAILURE) { - INFOF("TUI FAILURE"); - PrintMessageBox(ttyout, systemfailure, tyn, txn); - ReadKeyboard(); - if (action & INT) { - INFOF("TUI INT"); - LeaveScreen(); - exit(1); - } - } else if (dialog || !IsExecuting() || - (!(action & CONTINUE) && !(action & INT) && - HasPendingKeyboard())) { - ReadKeyboard(); - } - if (action & INT) { - INFOF("TUI INT"); - action &= ~INT; - RecordKeystroke("\3"); - ReactiveDraw(); - if (action & (CONTINUE | NEXT | FINISH)) { - action &= ~(CONTINUE | NEXT | FINISH); - } else { - action |= EXIT; - break; - } - } - if (action & EXIT) { - INFOF("TUI EXIT"); - break; - } - if (action & QUIT) { - INFOF("TUI QUIT"); - action &= ~QUIT; - raise(SIGQUIT); - continue; - } - if (action & RESTART) { - INFOF("TUI RESTART"); - break; - } - if (IsExecuting()) { - if (!(action & CONTINUE)) { - action &= ~STEP; - if (action & NEXT) { - action &= ~NEXT; - if (IsCall()) { - BreakAtNextInstruction(); - break; - } - } - if (action & FINISH) { - if (IsCall()) { - BreakAtNextInstruction(); - break; - } else if (IsRet()) { - action &= ~FINISH; - } - } - } - if (!IsDebugBreak()) { - UpdateXmmType(m, &xmmtype); - ExecuteInstruction(m); - if (m->signals.i < m->signals.n) { - ConsumeSignal(m); - } - ++opcount; - if (!(action & CONTINUE) || interactive) { - if (!(action & CONTINUE)) ReactiveDraw(); - ScrollMemoryViews(); - } - } else { - m->ip += m->xedd->length; - action &= ~NEXT; - action &= ~FINISH; - action &= ~CONTINUE; - } - KeepGoing: - CheckFramePointer(); - if (!(action & CONTINUE)) { - ScrollOp(&pan.disassembly, GetDisIndex()); - if ((action & FINISH) && IsRet()) action &= ~FINISH; - if (((action & NEXT) && IsRet()) || (action & FINISH)) { - action &= ~NEXT; - } - } - } - } while (tuimode); - } else { - if (OnHalt(interrupt)) { - ReactiveDraw(); - ScrollMemoryViews(); - goto KeepGoing; - } - ReactiveDraw(); - ScrollOp(&pan.disassembly, GetDisIndex()); - } - TuiCleanup(); -} - -static void GetOpts(int argc, char *argv[]) { - int opt; - stpcpy(stpcpy(stpcpy(logpath, kTmpPath), basename(argv[0])), ".log"); - while ((opt = getopt(argc, argv, "hvtrzRsb:HL:")) != -1) { - switch (opt) { - case 't': - tuimode = true; - break; - case 'R': - react = true; - break; - case 'r': - m->ismetal = true; - m->mode = XED_MACHINE_MODE_REAL; - g_disisprog_disable = true; - break; - case 's': - printstats = true; - break; - case 'b': - HandleBreakpointFlag(optarg); - break; - case 'H': - bzero(&g_high, sizeof(g_high)); - break; - case 'v': - ++__log_level; - break; - case 'L': - strcpy(logpath, optarg); - break; - case 'z': - ++codeview.zoom; - ++readview.zoom; - ++writeview.zoom; - ++stackview.zoom; - break; - case 'h': - PrintUsage(EXIT_SUCCESS, stdout); - default: - PrintUsage(EX_USAGE, stderr); - } - } - __log_file = fopen(logpath, "a"); - setvbuf(__log_file, xmalloc(PAGESIZE), _IOLBF, PAGESIZE); -} - -static int OpenDevTty(void) { - return open("/dev/tty", O_RDWR | O_NOCTTY); -} - -static void AddHostFd(int fd) { - int i = m->fds.i++; - CHECK_NE(-1, (m->fds.p[i].fd = fd)); - m->fds.p[i].cb = &kMachineFdCbHost; -} - -int Emulator(int argc, char *argv[]) { - void *code; - int rc, fd; - codepath = argv[optind++]; - m->fds.p = xcalloc((m->fds.n = 8), sizeof(struct MachineFd)); - do { - action = 0; - LoadProgram(m, codepath, argv + optind, environ, elf); - AddHostFd(0); - AddHostFd(1); - AddHostFd(2); - if (tuimode) { - ttyin = isatty(0) ? 0 : OpenDevTty(); - ttyout = isatty(1) ? 1 : OpenDevTty(); - } else { - ttyin = -1; - ttyout = -1; - } - if (ttyout != -1) { - atexit(TtyRestore1); - xsigaction(SIGWINCH, OnSigWinch, 0, 0, 0); - tyn = 24; - txn = 80; - GetTtySize(ttyout); - if (isatty(0)) m->fds.p[0].cb = &kMachineFdCbPty; - if (isatty(1)) m->fds.p[1].cb = &kMachineFdCbPty; - if (isatty(2)) m->fds.p[2].cb = &kMachineFdCbPty; - } - do { - if (!tuimode) { - Exec(); - } else { - Tui(); - } - } while (!(action & (RESTART | EXIT))); - } while (action & RESTART); - if (printstats) { - fprintf(stderr, "taken: %,ld\n", taken); - fprintf(stderr, "ntaken: %,ld\n", ntaken); - fprintf(stderr, "ops: %,ld\n", opcount); - } - munmap(elf->ehdr, elf->size); - DisFree(dis); - return exitcode; -} - -static void OnlyRunOnFirstCpu(void) { - cpu_set_t bs; - CPU_ZERO(&bs); - CPU_SET(0, &bs); - sched_setaffinity(0, sizeof(bs), &bs); -} - -static void OnSignal(int sig, siginfo_t *si, void *uc) { - EnqueueSignal(m, sig, si->si_code); -} - -int main(int argc, char *argv[]) { - struct sigaction sa; - if (!NoDebug()) { - ShowCrashReports(); - } - pty = NewPty(); - pty->conf |= kPtyNocanon; - m = NewMachine(); - m->mode = XED_MACHINE_MODE_LONG_64; - m->redraw = Redraw; - m->onbinbase = OnBinbase; - m->onlongbranch = OnLongBranch; - speed = 4; - SetXmmSize(2); - SetXmmDisp(kXmmHex); - if ((colorize = !__nocolor)) { - g_high.keyword = 155; - g_high.reg = 215; - g_high.literal = 182; - g_high.label = 221; - g_high.comment = 112; - g_high.quote = 215; - } - GetOpts(argc, argv); - if (optind == argc) { - PrintUsage(EX_USAGE, stderr); - } - xsigaction(SIGALRM, OnSigAlarm, 0, 0, 0); - memset(&sa, 0, sizeof(sa)); - sigfillset(&sa.sa_mask); - sa.sa_flags |= SA_SIGINFO; - sa.sa_sigaction = OnSignal; - sigaction(SIGHUP, &sa, 0); - sigaction(SIGQUIT, &sa, 0); - sigaction(SIGABRT, &sa, 0); - sigaction(SIGUSR1, &sa, 0); - sigaction(SIGUSR2, &sa, 0); - sigaction(SIGPIPE, &sa, 0); - sigaction(SIGTERM, &sa, 0); - sigaction(SIGCHLD, &sa, 0); - sigaction(SIGWINCH, &sa, 0); - return Emulator(argc, argv); -} diff --git a/tool/build/build.mk b/tool/build/build.mk index 23f833750..7af5ae4f5 100644 --- a/tool/build/build.mk +++ b/tool/build/build.mk @@ -95,19 +95,6 @@ o/$(MODE)/tool/build/%.com.dbg: \ $(APE_NO_MODIFY_SELF) @$(APELINK) -o/$(MODE)/tool/build/blinkenlights.com: \ - o/$(MODE)/tool/build/blinkenlights.com.dbg \ - o/$(MODE)/third_party/zip/zip.com \ - o/$(MODE)/tool/build/symtab.com \ - $(VM) - @$(MAKE_OBJCOPY) - @$(MAKE_SYMTAB_CREATE) - @$(MAKE_SYMTAB_ZIP) - -o/$(MODE)/tool/build/emulator.o: private \ - COPTS += \ - -fno-sanitize=pointer-overflow - o/$(MODE)/tool/build/dso/sandbox.so.zip.o \ o/$(MODE)/tool/build/mkdir.zip.o \ o/$(MODE)/tool/build/chmod.zip.o \ @@ -165,8 +152,6 @@ o/$(MODE)/tool/build/pledge.com.dbg: \ .PHONY: o/$(MODE)/tool/build o/$(MODE)/tool/build: \ - o/$(MODE)/tool/build/emucrt \ - o/$(MODE)/tool/build/emubin \ o/$(MODE)/tool/build/lib \ $(TOOL_BUILD_BINS) \ $(TOOL_BUILD_CHECKS) diff --git a/tool/build/dis.c b/tool/build/dis.c deleted file mode 100644 index 390b1ee1a..000000000 --- a/tool/build/dis.c +++ /dev/null @@ -1,318 +0,0 @@ -/*-*- 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 2021 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 "tool/build/lib/dis.h" -#include "libc/calls/calls.h" -#include "libc/calls/struct/stat.h" -#include "libc/elf/def.h" -#include "libc/elf/elf.h" -#include "libc/elf/struct/ehdr.h" -#include "libc/elf/struct/shdr.h" -#include "libc/elf/struct/sym.h" -#include "libc/log/check.h" -#include "libc/log/log.h" -#include "libc/macros.internal.h" -#include "libc/nt/struct/importobjectheader.internal.h" -#include "libc/runtime/runtime.h" -#include "libc/stdio/stdio.h" -#include "libc/str/str.h" -#include "libc/sysv/consts/map.h" -#include "libc/sysv/consts/o.h" -#include "libc/sysv/consts/prot.h" -#include "third_party/xed/x86.h" -#include "tool/build/lib/high.h" -#include "tool/build/lib/loader.h" - -#define HEXWIDTH 8 - -const char *const kRealSymbols[] = { - "a20", "ape.mbrpad", "ape.str", - "ape_disk", "ape_grub", "ape_mz", - "apesh", "dsknfo", "e820", - "gdt", "golong", "hiload", - "lcheck", "longmodeloader", "pc", - "pcread", "pinit", "realmodeloader", - "rldie", "rvputs", "sconf", - "sinit", "sinit4", "str.cpuid", - "str.crlf", "str.dsknfo", "str.e820", - "str.error", "str.long", "str.memory", - "str.oldskool", "stub", "unreal", -}; - -const char *const kLegacySymbols[] = { - "ape_grub_entry", -}; - -bool boop; -long cursym; -Elf64_Ehdr *elf; -Elf64_Shdr *sec; -struct Dis dis[1]; -struct Machine m[1]; -struct Elf diself[1]; -char codebuf[256]; -char optspecbuf[128]; -const Elf64_Sym *syms; -char *symstrs, *secstrs; -size_t i, j, k, l, size, skip, symcount; - -bool IsRealSymbol(const char *s) { - int m, l, r, x; - l = 0; - r = ARRAYLEN(kRealSymbols) - 1; - while (l <= r) { - m = (l + r) >> 1; - x = strcmp(s, kRealSymbols[m]); - if (x < 0) { - r = m - 1; - } else if (x > 0) { - l = m + 1; - } else { - return true; - } - } - return false; -} - -bool IsLegacySymbol(const char *s) { - int m, l, r, x; - l = 0; - r = ARRAYLEN(kLegacySymbols) - 1; - while (l <= r) { - m = (l + r) >> 1; - x = strcmp(s, kLegacySymbols[m]); - if (x < 0) { - r = m - 1; - } else if (x > 0) { - l = m + 1; - } else { - return true; - } - } - return false; -} - -void SetSymbol(bool printit) { - if (!boop) { - printf("\n"); - boop = true; - } - if (printit) { - printf("\e[38;5;%dm%s\e[0m:\n", g_high.label, symstrs + syms[k].st_name); - } - if (IsRealSymbol(symstrs + syms[k].st_name)) { - if (m->mode != XED_MACHINE_MODE_REAL) { - printf("\t\e[38;5;%dm.code16\e[0m\n", g_high.keyword); - } - m->mode = XED_MACHINE_MODE_REAL; - } else if (IsLegacySymbol(symstrs + syms[k].st_name)) { - if (m->mode != XED_MACHINE_MODE_LEGACY_32) { - printf("\t\e[38;5;%dm.code32\e[0m\n", g_high.keyword); - } - m->mode = XED_MACHINE_MODE_LEGACY_32; - } else { - if (m->mode != XED_MACHINE_MODE_LONG_64) { - printf("\t\e[38;5;%dm.code64\e[0m\n", g_high.keyword); - } - m->mode = XED_MACHINE_MODE_LONG_64; - } - cursym = k; - if (syms[k].st_size) { - skip = syms[k].st_size; - } else { - skip = -1; - for (l = 0; l < symcount; ++l) { - if (syms[l].st_shndx == i && syms[l].st_name && - syms[l].st_value > syms[cursym].st_value) { - skip = MIN(skip, syms[l].st_value - syms[cursym].st_value); - } - } - if (skip == -1) { - skip = sec->sh_addr + sec->sh_size - syms[cursym].st_value; - } - } -} - -void PrintSymbolName(void) { - bool done; - done = false; - boop = false; - for (k = 0; k < symcount; ++k) { - if (syms[k].st_value == sec->sh_addr + j && syms[k].st_name) { - if (!done && syms[k].st_size) { - SetSymbol(true); - done = true; - } else { - if (!boop) { - printf("\n"); - boop = true; - } - printf("\e[38;5;%dm%s\e[0m:\n", g_high.label, - symstrs + syms[k].st_name); - } - } - } - if (done) { - return; - } - for (k = 0; k < symcount; ++k) { - if (ELF64_ST_TYPE(syms[k].st_info) && syms[k].st_name && - syms[k].st_value == sec->sh_addr + j) { - SetSymbol(false); - return; - } - } - for (k = 0; k < symcount; ++k) { - if (syms[k].st_name && syms[k].st_value == sec->sh_addr + j) { - SetSymbol(false); - return; - } - } - if (cursym != -1 && syms[cursym].st_size && - sec->sh_addr + j >= syms[cursym].st_value + syms[cursym].st_size) { - cursym = -1; - skip = 1; - } -} - -bool Ild(void) { - int remain; - remain = 15; - if (cursym != -1 && syms[cursym].st_size) { - remain = - (syms[cursym].st_value + syms[cursym].st_size) - (sec->sh_addr + j); - } - xed_decoded_inst_zero_set_mode(dis->xedd, m->mode); - xed_instruction_length_decode(dis->xedd, (char *)elf + sec->sh_offset + j, - remain); - skip = dis->xedd->op.error ? 1 : MAX(1, dis->xedd->length); - return !dis->xedd->op.error; -} - -bool IsCode(void) { - if (!(sec->sh_flags & SHF_EXECINSTR)) return false; - if (cursym != -1 && ELF64_ST_TYPE(syms[cursym].st_info) == STT_OBJECT) { - return false; - } - return true; -} - -bool IsBss(void) { - return sec->sh_type == SHT_NOBITS; -} - -void Disassemble(void) { - int c; - bool istext; - cursym = -1; - secstrs = GetElfSectionNameStringTable(elf, size); - symstrs = GetElfStringTable(elf, size); - syms = GetElfSymbolTable(elf, size, &symcount); - for (i = 0; i < elf->e_shnum; ++i) { - sec = GetElfSectionHeaderAddress(elf, size, i); - if (!sec->sh_size) continue; - if (!(sec->sh_flags & SHF_ALLOC)) continue; - printf("\n\t\e[38;5;%dm.section\e[0m %s\n", g_high.keyword, - secstrs + sec->sh_name); - for (j = 0; j < sec->sh_size; j += MAX(1, skip)) { - PrintSymbolName(); - if (cursym == -1) continue; - if (sec->sh_type == SHT_NOBITS) { - printf("\t\e[38;5;%dm.zero\e[0m\t%ld\n", g_high.keyword, skip); - } else if (IsCode()) { - if (Ild()) { - dis->addr = sec->sh_addr + j; - DisInst(dis, codebuf, DisSpec(dis->xedd, optspecbuf)); - printf("\t%s\n", codebuf); - } else { - printf("\t.wut\t%ld\n", dis->xedd->op.error); - } - } else { - for (k = 0; k < skip; ++k) { - if (!(k & (HEXWIDTH - 1))) { - if (k) { - printf(" \e[38;5;%dm# %#.*s\e[0m\n", g_high.comment, HEXWIDTH, - (unsigned char *)elf + sec->sh_offset + j + k - HEXWIDTH); - } - printf("\t\e[38;5;%dm.byte\e[0m\t", g_high.keyword); - } else if (k) { - printf(","); - } - printf("0x%02x", ((unsigned char *)elf)[sec->sh_offset + j + k]); - } - if (k) { - if (!(k & (HEXWIDTH - 1))) { - printf(" \e[38;5;%dm# %#.*s\e[0m\n", g_high.comment, HEXWIDTH, - (unsigned char *)elf + sec->sh_offset + j + skip - HEXWIDTH); - } else { - for (l = 0; l < HEXWIDTH - (k & (HEXWIDTH - 1)); ++l) { - printf(" "); - } - printf(" \e[38;5;%dm# %#.*s\e[0m\n", g_high.comment, - skip - ROUNDDOWN(skip, HEXWIDTH), - (unsigned char *)elf + sec->sh_offset + j + - ROUNDDOWN(skip, HEXWIDTH)); - } - } - } - } - } -} - -int main(int argc, char *argv[]) { - ShowCrashReports(); - int fd; - void *map; - struct stat st; - const char *path; - if (argc == 1) { - fprintf(stderr, "USAGE: %s ELF\n", program_invocation_name); - exit(1); - } else { - path = argv[1]; - } - if ((fd = open(path, O_RDONLY)) == -1) { - fprintf(stderr, "ERROR: NOT FOUND: %`'s\n", path); - exit(1); - } - CHECK_NE(-1, fstat(fd, &st)); - CHECK_NE(0, st.st_size); - CHECK_NE(MAP_FAILED, - (map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0))); - if (memcmp(map, ELFMAG, 4)) { - fprintf(stderr, "ERROR: NOT AN ELF: %`'s\n", path); - exit(1); - } - m->mode = XED_MACHINE_MODE_LONG_64; - g_high.keyword = 155; - g_high.reg = 215; - g_high.literal = 182; - g_high.label = 221; - g_high.comment = 112; - g_high.quote = 180; - dis->m = m; - diself->prog = path; - LoadDebugSymbols(diself); - DisLoadElf(dis, diself); - LOGIFNEG1(close(fd)); - elf = map; - size = st.st_size; - Disassemble(); - LOGIFNEG1(munmap(map, st.st_size)); - return 0; -} diff --git a/tool/build/emubin/emubin.mk b/tool/build/emubin/emubin.mk deleted file mode 100644 index 671b6e2c0..000000000 --- a/tool/build/emubin/emubin.mk +++ /dev/null @@ -1,68 +0,0 @@ -#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ - -PKGS += TOOL_BUILD_EMUBIN - -TOOL_BUILD_EMUBIN_BINS = \ - o/$(MODE)/tool/build/emubin/sha256.bin \ - o/$(MODE)/tool/build/emubin/sha256.bin.dbg \ - o/$(MODE)/tool/build/emubin/mips.bin \ - o/$(MODE)/tool/build/emubin/mips.bin.dbg \ - o/$(MODE)/tool/build/emubin/prime.bin \ - o/$(MODE)/tool/build/emubin/prime.bin.dbg \ - o/$(MODE)/tool/build/emubin/pi.bin \ - o/$(MODE)/tool/build/emubin/pi.bin.dbg - -TOOL_BUILD_EMUBIN_A = o/$(MODE)/tool/build/emubin/emubin.a -TOOL_BUILD_EMUBIN_FILES := $(wildcard tool/build/emubin/*) -TOOL_BUILD_EMUBIN_SRCS = $(filter %.c,$(TOOL_BUILD_EMUBIN_FILES)) -TOOL_BUILD_EMUBIN_HDRS = $(filter %.h,$(TOOL_BUILD_EMUBIN_FILES)) - -TOOL_BUILD_EMUBIN_OBJS = \ - $(TOOL_BUILD_EMUBIN_SRCS:%.c=o/$(MODE)/%.o) - -TOOL_BUILD_EMUBIN_CHECKS = \ - $(TOOL_BUILD_EMUBIN_HDRS:%=o/$(MODE)/%.ok) - -TOOL_BUILD_EMUBIN_DIRECTDEPS = \ - LIBC_INTRIN \ - LIBC_NEXGEN32E \ - LIBC_STUBS \ - LIBC_TINYMATH - -TOOL_BUILD_EMUBIN_DEPS := \ - $(call uniq,$(foreach x,$(TOOL_BUILD_EMUBIN_DIRECTDEPS),$($(x)))) - -$(TOOL_BUILD_EMUBIN_A): \ - tool/build/emubin/ \ - $(TOOL_BUILD_EMUBIN_A).pkg \ - $(TOOL_BUILD_EMUBIN_OBJS) - -$(TOOL_BUILD_EMUBIN_A).pkg: \ - $(TOOL_BUILD_EMUBIN_OBJS) \ - $(foreach x,$(TOOL_BUILD_EMUBIN_DIRECTDEPS),$($(x)_A).pkg) - -o/$(MODE)/tool/build/emubin/%.bin.dbg: \ - $(TOOL_BUILD_EMUCRT) \ - $(TOOL_BUILD_EMUBIN_DEPS) \ - $(TOOL_BUILD_EMUBIN_A) \ - o/$(MODE)/tool/build/emubin/%.o \ - $(TOOL_BUILD_EMUBIN_A).pkg - @$(ELFLINK) -e emucrt -z common-page-size=0x10 -z max-page-size=0x10 - -o/tiny/tool/build/emubin/spiral.bin.dbg: \ - $(TOOL_BUILD_EMUBIN_DEPS) \ - o/tiny/tool/build/emubin/spiral.real.o - @$(ELFLINK) -z common-page-size=0x10 -z max-page-size=0x10 -T tool/build/emucrt/real.lds - -o/tiny/tool/build/emubin/mdatest.bin.dbg: \ - $(TOOL_BUILD_EMUBIN_DEPS) \ - o/tiny/tool/build/emubin/mdatest.real.o - @$(ELFLINK) -z common-page-size=0x10 -z max-page-size=0x10 -T tool/build/emucrt/real.lds - -$(TOOL_BUILD_EMUBIN_OBJS): private \ - CFLAGS += \ - $(NO_MAGIC) - -.PHONY: o/$(MODE)/tool/build/emubin -o/$(MODE)/tool/build/emubin: diff --git a/tool/build/emubin/linmap.c b/tool/build/emubin/linmap.c deleted file mode 100644 index 64a148270..000000000 --- a/tool/build/emubin/linmap.c +++ /dev/null @@ -1,31 +0,0 @@ -/*-*- 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/linux/exit.h" -#include "libc/linux/fstat.h" -#include "libc/linux/mmap.h" -#include "libc/linux/open.h" - -struct stat st; - -void _start(void) { - long fd = LinuxOpen("/etc/passwd", 0, 0); - LinuxFstat(fd, &st); - LinuxMmap((void *)0x000000000000, st.st_size, 1, 2, fd, 0); - LinuxExit(0); -} diff --git a/tool/build/emubin/mdatest.real.c b/tool/build/emubin/mdatest.real.c deleted file mode 100644 index 40845447b..000000000 --- a/tool/build/emubin/mdatest.real.c +++ /dev/null @@ -1,44 +0,0 @@ -/*-*- 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 "tool/build/emubin/poke.h" -#include "tool/build/emubin/real.h" -#include "tool/build/emubin/realstart.inc" - -/* -m=tiny; make -j12 MODE=$m o/$m/tool/build/{tinyemu,emulator}.com \ -o/$m/tool/build/emubin/mdatest.bin && o/$m/tool/build/emulator.com \ --rt o/$m/tool/build/emubin/mdatest.bin -*/ - -static void MdaTest(uint16_t p[25][80]) { - int i, y, x; - for (i = 0; i < 256; ++i) { - y = i / 16; - x = i % 16 * 3; - POKE(p[y][x + 0], i << 8 | "0123456789abcdef"[(i & 0xf0) >> 4]); - POKE(p[y][x + 1], i << 8 | "0123456789abcdef"[(i & 0x0f) >> 0]); - } -} - -int main() { - SetVideoMode(7); - SetEs(0xb0000 >> 4); - MdaTest((void *)0); - for (;;) __builtin_ia32_pause(); -} diff --git a/tool/build/emubin/metalsha256.c b/tool/build/emubin/metalsha256.c deleted file mode 100644 index 2d68469c5..000000000 --- a/tool/build/emubin/metalsha256.c +++ /dev/null @@ -1,154 +0,0 @@ -/*-*- 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 "tool/build/emubin/metalsha256.h" -#include "libc/intrin/repstosb.h" - -#define ROTR(a, b) (((a) >> (b)) | ((a) << (32 - (b)))) -#define CH(x, y, z) (((x) & (y)) ^ (~(x) & (z))) -#define MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) -#define EP0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) -#define EP1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) -#define SIG0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ ((x) >> 3)) -#define SIG1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ ((x) >> 10)) - -const uint32_t kMetalSha256Tab[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, - 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, - 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, - 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, - 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, - 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, -}; - -void MetalSha256Cleanup(struct MetalSha256Ctx *ctx) { - repstosb(ctx, 0, sizeof(*ctx)); - asm("pxor\t%xmm0,%xmm0\n\t" - "pxor\t%xmm1,%xmm1\n\t" - "pxor\t%xmm2,%xmm2\n\t" - "pxor\t%xmm3,%xmm3\n\t" - "pxor\t%xmm4,%xmm4\n\t" - "pxor\t%xmm5,%xmm5\n\t" - "pxor\t%xmm6,%xmm6\n\t" - "pxor\t%xmm7,%xmm7"); -} - -void MetalSha256Transform(uint32_t state[8], const uint8_t data[64]) { - unsigned i; - uint32_t a, b, c, d, e, f, g, h, t1, t2, m[64]; - for (i = 0; i < 16; ++i, data += 4) { - m[i] = (uint32_t)data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; - } - for (; i < 64; ++i) { - m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16]; - } - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - f = state[5]; - g = state[6]; - h = state[7]; - for (i = 0; i < 64; ++i) { - t1 = h + EP1(e) + CH(e, f, g) + kMetalSha256Tab[i] + m[i]; - t2 = EP0(a) + MAJ(a, b, c); - h = g; - g = f; - f = e; - e = d + t1; - d = c; - c = b; - b = a; - a = t1 + t2; - } - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; - state[5] += f; - state[6] += g; - state[7] += h; -} - -void MetalSha256Init(struct MetalSha256Ctx *ctx) { - ctx->datalen = 0; - ctx->bitlen = 0; - ctx->state[0] = 0x6a09e667; - ctx->state[1] = 0xbb67ae85; - ctx->state[2] = 0x3c6ef372; - ctx->state[3] = 0xa54ff53a; - ctx->state[4] = 0x510e527f; - ctx->state[5] = 0x9b05688c; - ctx->state[6] = 0x1f83d9ab; - ctx->state[7] = 0x5be0cd19; -} - -void MetalSha256Update(struct MetalSha256Ctx *ctx, const uint8_t *data, - long size) { - long i; - for (i = 0; i < size; ++i) { - ctx->data[ctx->datalen] = data[i]; - ctx->datalen++; - if (ctx->datalen == 64) { - MetalSha256Transform(ctx->state, ctx->data); - ctx->bitlen += 512; - ctx->datalen = 0; - } - } -} - -void MetalSha256Final(struct MetalSha256Ctx *ctx, uint8_t *hash) { - long i; - i = ctx->datalen; - ctx->data[i++] = 0x80; - if (ctx->datalen < 56) { - repstosb(ctx->data + i, 0, 56 - i); - } else { - repstosb(ctx->data + i, 0, 64 - i); - MetalSha256Transform(ctx->state, ctx->data); - repstosb(ctx->data, 0, 56); - } - ctx->bitlen += ctx->datalen * 8; - ctx->data[63] = ctx->bitlen; - ctx->data[62] = ctx->bitlen >> 8; - ctx->data[61] = ctx->bitlen >> 16; - ctx->data[60] = ctx->bitlen >> 24; - ctx->data[59] = ctx->bitlen >> 32; - ctx->data[58] = ctx->bitlen >> 40; - ctx->data[57] = ctx->bitlen >> 48; - ctx->data[56] = ctx->bitlen >> 56; - MetalSha256Transform(ctx->state, ctx->data); - for (i = 0; i < 4; ++i) { - hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0xff; - hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0xff; - hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0xff; - hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0xff; - hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0xff; - hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0xff; - hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0xff; - hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0xff; - } - MetalSha256Cleanup(ctx); -} diff --git a/tool/build/emubin/metalsha256.h b/tool/build/emubin/metalsha256.h deleted file mode 100644 index 2e77cc5af..000000000 --- a/tool/build/emubin/metalsha256.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_EMUBIN_METALSHA256_H_ -#define COSMOPOLITAN_TOOL_BUILD_EMUBIN_METALSHA256_H_ -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -struct MetalSha256Ctx { - uint8_t data[64]; - uint32_t datalen; - uint64_t bitlen; - uint32_t state[8]; -}; - -void MetalSha256Init(struct MetalSha256Ctx *); -void MetalSha256Update(struct MetalSha256Ctx *, const uint8_t *, long); -void MetalSha256Final(struct MetalSha256Ctx *, uint8_t *); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_EMUBIN_METALSHA256_H_ */ diff --git a/tool/build/emubin/mips.c b/tool/build/emubin/mips.c deleted file mode 100644 index ec9c278c8..000000000 --- a/tool/build/emubin/mips.c +++ /dev/null @@ -1,49 +0,0 @@ -/*-*- 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 "tool/build/emubin/metalsha256.h" - -//#define DISINGENUOUS /* 100 million NOPs is still 100 MIPS lool */ - -static void Print(uint8_t c) { - asm volatile("out\t%0,$0xE9" : /* no outputs */ : "a"(c) : "memory"); -} - -int main(int argc, char *argv[]) { - int i; -#ifdef DISINGENUOUS - for (i = 0; i < 150 * 1000 * 1000 / 3; ++i) asm("nop"); -#else - size_t size; - struct MetalSha256Ctx ctx; - unsigned char hash[32], *data; - data = (void *)0x7fffffff0000; - size = 0x10000; - MetalSha256Init(&ctx); - for (i = 0; i < 10; ++i) { - MetalSha256Update(&ctx, data, size); - } - MetalSha256Final(&ctx, hash); - for (i = 0; i < sizeof(hash); ++i) { - Print("0123456789abcdef"[(hash[i] >> 4) & 15]); - Print("0123456789abcdef"[(hash[i] >> 0) & 15]); - } - Print('\n'); -#endif - return 0; -} diff --git a/tool/build/emubin/pi.c b/tool/build/emubin/pi.c deleted file mode 100644 index cc7ac886b..000000000 --- a/tool/build/emubin/pi.c +++ /dev/null @@ -1,55 +0,0 @@ -/*-*- 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/math.h" - -#if 1 -#define FLOAT long double -#define SQRT sqrtl -#else -#define FLOAT float -#define SQRT sqrt -#endif - -/** - * Computes π w/ François Viète method. - * - * make -j8 MODE=tiny - * o/tiny/tool/build/emulator.com.dbg -t o/tiny/tool/build/pi.bin - * - */ -FLOAT Main(void) { - long i, n; - FLOAT pi, q, t; - n = VEIL("r", 10); - q = 0; - t = 1; - for (i = 0; i < n; ++i) { - q += 2; - q = SQRT(q); - t *= q / 2; - } - return 2 / t; -} - -volatile FLOAT st0; - -int main(int argc, char *argv[]) { - st0 = Main(); - return 0; -} diff --git a/tool/build/emubin/poke.h b/tool/build/emubin/poke.h deleted file mode 100644 index 5bc451df1..000000000 --- a/tool/build/emubin/poke.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_EMUBIN_POKE_H_ -#define COSMOPOLITAN_TOOL_BUILD_EMUBIN_POKE_H_ -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -#define POKE(MEM, VAL) \ - asm volatile("mov%z0\t%1,%%es:%0" : "=m"(MEM) : "Qi"((typeof(MEM))(VAL))) - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_EMUBIN_POKE_H_ */ diff --git a/tool/build/emubin/prime.c b/tool/build/emubin/prime.c deleted file mode 100644 index 213a40d35..000000000 --- a/tool/build/emubin/prime.c +++ /dev/null @@ -1,41 +0,0 @@ -/*-*- 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. │ -╚─────────────────────────────────────────────────────────────────────────────*/ - -dontinline bool IsPrime(int i) { - int j, n; - for (j = 3, n = VEIL("r", 3); j <= n; j += 2) { - if (VEIL("r", i) % VEIL("r", j) == 0) { - return false; - } - } - return true; -} - -/** - * Places 10th prime number in RAX. - */ -int main(int argc, char *argv[]) { - int i, c; - for (c = i = 0; c < VEIL("r", 10); ++i) { - if (IsPrime(i)) { - ++c; - } - } - return i; -} diff --git a/tool/build/emubin/real.h b/tool/build/emubin/real.h deleted file mode 100644 index 1223f1dc3..000000000 --- a/tool/build/emubin/real.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_EMUBIN_REAL_H_ -#define COSMOPOLITAN_TOOL_BUILD_EMUBIN_REAL_H_ -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -forceinline void SetEs(int base) { - asm volatile("mov%z0\t%0,%%es" : /* no outputs */ : "r"(base)); -} - -forceinline void SetVideoMode(int mode) { - asm volatile("int\t$0x10" - : /* no outputs */ - : "a"(mode)); -} - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_EMUBIN_REAL_H_ */ diff --git a/tool/build/emubin/realstart.inc b/tool/build/emubin/realstart.inc deleted file mode 100644 index eab57194b..000000000 --- a/tool/build/emubin/realstart.inc +++ /dev/null @@ -1,7 +0,0 @@ -asm(".section .start,\"ax\",@progbits\n\t" - ".globl\t_start\n" - "_start:\n\t" - "jmp\t1f\n1:\t" - "call\tmain\n\t" - "nop\n\t" - ".previous"); diff --git a/tool/build/emubin/sha256.c b/tool/build/emubin/sha256.c deleted file mode 100644 index 39c8f5743..000000000 --- a/tool/build/emubin/sha256.c +++ /dev/null @@ -1,52 +0,0 @@ -/*-*- 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 "tool/build/emubin/metalsha256.h" - -#define SHA256_BLOCK_SIZE 32 - -#define OUTB(PORT, BYTE) asm volatile("outb\t%b1,%0" : : "N"(PORT), "a"(BYTE)) -#define INW(PORT) \ - ({ \ - int Word; \ - asm volatile("in\t%1,%0" : "=a"(Word) : "N"(PORT)); \ - Word; \ - }) - -static void PrintHexBytes(int n, const uint8_t p[n]) { - int i; - for (i = 0; i < n; ++i) { - OUTB(0xE9, "0123456789abcdef"[(p[i] >> 4) & 15]); - OUTB(0xE9, "0123456789abcdef"[(p[i] >> 0) & 15]); - } - OUTB(0xE9, '\n'); -} - -int main(int argc, char *argv[]) { - int rc; - uint8_t hash[32], buf[1]; - struct MetalSha256Ctx ctx; - MetalSha256Init(&ctx); - while ((rc = INW(0xE9)) != -1) { - buf[0] = rc; - MetalSha256Update(&ctx, buf, sizeof(buf)); - } - MetalSha256Final(&ctx, hash); - PrintHexBytes(sizeof(hash), hash); - return 0; -} diff --git a/tool/build/emubin/spiral.c b/tool/build/emubin/spiral.c deleted file mode 100644 index b7ce27dac..000000000 --- a/tool/build/emubin/spiral.c +++ /dev/null @@ -1,138 +0,0 @@ -/*-*- 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 "tool/build/emubin/poke.h" -#include "tool/build/emubin/real.h" -#include "tool/build/emubin/realstart.inc" - -#define signbit(x) __builtin_signbit(x) - -static const unsigned char kBlocks[] = { - [0b1111] = 0xdb, // █ - [0b0110] = 0xdb, // █ - [0b1001] = 0xdb, // █ - [0b0111] = 0xdb, // █ - [0b1011] = 0xdb, // █ - [0b1110] = 0xdb, // █ - [0b1101] = 0xdb, // █ - [0b1100] = 0xdc, // ▄ - [0b0100] = 0xdc, // ▄ - [0b1000] = 0xdc, // ▄ - [0b0101] = 0xdd, // ▌ - [0b1010] = 0xde, // ▐ - [0b0011] = 0xdf, // ▀ - [0b0010] = 0xdf, // ▀ - [0b0001] = 0xdf, // ▀ -}; - -forceinline void *SetMemory(void *di, int al, unsigned long cx) { - asm("rep stosb" - : "=D"(di), "=c"(cx), "=m"(*(char(*)[cx])di) - : "0"(di), "1"(cx), "a"(al)); - return di; -} - -forceinline long double pi(void) { - long double x; - asm("fldpi" : "=t"(x)); - return x; -} - -forceinline long double tau(void) { - return pi() * 2; -} - -forceinline void sincosl_(long double x, long double *sin, long double *cos) { - asm("fsincos" : "=t"(*sin), "=u"(*cos) : "0"(x)); -} - -forceinline long double atan2l_(long double x, long double y) { - asm("fpatan" : "+t"(x) : "u"(y) : "st(1)"); - return x; -} - -forceinline long lrintl_(long double x) { - long i; - asm("fistp%z0\t%0" : "=m"(i) : "t"(x) : "st"); - return i; -} - -forceinline long double truncl_(long double x) { - asm("frndint" : "+t"(x)); - return x; -} - -forceinline long double fabsl_(long double x) { - asm("fabs" : "+t"(x)); - return x; -} - -forceinline long lroundl_(long double x) { - int s = signbit(x); - x = truncl_(fabsl_(x) + .5); - if (s) x = -x; - return lrintl_(x); -} - -static unsigned short GetFpuControlWord(void) { - unsigned short cw; - asm("fnstcw\t%0" : "=m"(cw)); - return cw; -} - -static void SetFpuControlWord(unsigned short cw) { - asm volatile("fldcw\t%0" : /* no outputs */ : "m"(cw)); -} - -static void InitializeFpu(void) { - asm("fninit"); -} - -static void SetTruncationRounding(void) { - SetFpuControlWord(GetFpuControlWord() | 0x0c00); -} - -static void spiral(unsigned char p[25][80][2], unsigned char B[25][80], int g) { - int i, x, y; - long double a, b, u, v, h; - for (a = b = i = 0; i < 1000; ++i) { - sincosl_(a, &u, &v); - h = atan2l_(u, v) - .333L * g; - x = lroundl_(80 + u * b); - y = lroundl_(25 + v * b * (1. / ((266 / 64.) * (900 / 1600.)))); - B[y >> 1][x >> 1] |= 1 << ((y & 1) << 1 | (x & 1)); - POKE(p[y >> 1][x >> 1][0], kBlocks[B[y >> 1][x >> 1]]); - POKE(p[y >> 1][x >> 1][1], (lrintl_((h + tau()) * (8 / tau())) & 7) + 8); - a += .05; - b += .05; - } -} - -int main() { - int g; - InitializeFpu(); - SetTruncationRounding(); - SetVideoMode(3); - for (g = 0;; ++g) { - SetEs(0); - SetMemory((void *)(0x7c00 + 512), 0, 25 * 80); - SetEs(0xb8000 >> 4); - /* SetMemory((void *)0, 0, 25 * 80 * 2); */ - spiral((void *)0, (void *)(0x7c00 + 512), g); - } -} diff --git a/tool/build/emucrt/emucrt.S b/tool/build/emucrt/emucrt.S deleted file mode 100644 index 6c8142688..000000000 --- a/tool/build/emucrt/emucrt.S +++ /dev/null @@ -1,31 +0,0 @@ -/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 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/macros.internal.h" - - .section .start,"ax",@progbits -emucrt: bofram 9f - movslq (%rsp),%rdi # argc - lea 8(%rsp),%rsi # argv - lea 24(%rsp,%rdi,8),%rdx # envp - .weak main - call main - movzbl %al,%edi - mov $0xE7,%eax - syscall -9: .endfn emucrt,globl diff --git a/tool/build/emucrt/emucrt.lds b/tool/build/emucrt/emucrt.lds deleted file mode 100644 index 945960599..000000000 --- a/tool/build/emucrt/emucrt.lds +++ /dev/null @@ -1,80 +0,0 @@ -/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│ -│vi: set et sts=2 tw=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. │ -╚─────────────────────────────────────────────────────────────────────────────*/ - -ENTRY(_start) - -SECTIONS { - - .text IMAGE_BASE_VIRTUAL : { - *(.start) - KEEP(*(.initprologue)) - KEEP(*(SORT_BY_NAME(.init.*))) - KEEP(*(SORT_NONE(.init))) - KEEP(*(.initepilogue)) - *(.text .text.*) - *(.privileged) - *(.rodata .rodata.*) - KEEP(*(.initroprologue)) - KEEP(*(SORT_BY_NAME(.initro.*))) - KEEP(*(.initroepilogue)) - *(.ubsan.types) - *(.ubsan.data) - *(.data .data.*) - *(.bss .bss.*) - *(COMMON) - } - - .gnu_debuglink 0 : { *(.gnu_debuglink) } - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } - .debug_pubtypes 0 : { *(.debug_pubtypes) } - .debug_ranges 0 : { *(.debug_ranges) } - .debug_macro 0 : { *(.debug_macro) } - .debug_addr 0 : { *(.debug_addr) } - .gnu.attributes 0 : { KEEP(*(.gnu.attributes)) } - - /DISCARD/ : { - *(.GCC.command.line) - *(.comment) - *(.discard) - *(.yoink) - *(.*) - } -} diff --git a/tool/build/emucrt/emucrt.mk b/tool/build/emucrt/emucrt.mk deleted file mode 100644 index c2b546014..000000000 --- a/tool/build/emucrt/emucrt.mk +++ /dev/null @@ -1,18 +0,0 @@ -#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ - -PKGS += TOOL_BUILD_EMUCRT - -TOOL_BUILD_EMUCRT = \ - o/$(MODE)/tool/build/emucrt/emucrt.o \ - o/$(MODE)/tool/build/emucrt/emucrt.lds - -o/$(MODE)/tool/build/emucrt/emucrt.o: \ - tool/build/emucrt/emucrt.S \ - libc/macros.internal.h \ - libc/intrin/asancodes.h \ - ape/relocations.h - -.PHONY: o/$(MODE)/tool/build/emucrt -o/$(MODE)/tool/build/emucrt: \ - $(TOOL_BUILD_EMUCRT) diff --git a/tool/build/emucrt/real.lds b/tool/build/emucrt/real.lds deleted file mode 100644 index 5322561c5..000000000 --- a/tool/build/emucrt/real.lds +++ /dev/null @@ -1,38 +0,0 @@ -/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│ -│vi: set et sts=2 tw=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. │ -╚─────────────────────────────────────────────────────────────────────────────*/ - -ENTRY(_start) - -SECTIONS { - - .text 0x7c00 : { - *(.start) - *(.text .text.*) - *(.rodata .rodata.*) - *(.data .data.*) - . = 0x1fe; - SHORT(0xaa55); - *(.bss .bss.*) - *(COMMON) - } - - /DISCARD/ : { - *(.*) - } -} diff --git a/tool/build/lib/abp.h b/tool/build/lib/abp.h deleted file mode 100644 index 3199bfa73..000000000 --- a/tool/build/lib/abp.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_ABP_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_ABP_H_ -#if !(__ASSEMBLER__ + __LINKER__ + 0) - -#define Abp8(x) ((uint8_t *)__builtin_assume_aligned(x, 8)) -#define Abp16(x) ((uint8_t *)__builtin_assume_aligned(x, 16)) - -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_ABP_H_ */ diff --git a/tool/build/lib/address.c b/tool/build/lib/address.c deleted file mode 100644 index 2a285b974..000000000 --- a/tool/build/lib/address.c +++ /dev/null @@ -1,88 +0,0 @@ -/*-*- 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 "tool/build/lib/address.h" -#include "third_party/xed/x86.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/modrm.h" -#include "tool/build/lib/throw.h" - -uint64_t AddressOb(struct Machine *m, uint32_t rde) { - return AddSegment(m, rde, m->xedd->op.disp, m->ds); -} - -uint8_t *GetSegment(struct Machine *m, uint32_t rde, int s) { - switch (s & 7) { - case 0: - return m->es; - case 1: - return m->cs; - case 2: - return m->ss; - case 3: - return m->ds; - case 4: - return m->fs; - case 5: - return m->gs; - case 6: - case 7: - OpUd(m, rde); - default: - __builtin_unreachable(); - } -} - -uint64_t AddSegment(struct Machine *m, uint32_t rde, uint64_t i, uint8_t s[8]) { - if (!Sego(rde)) { - return i + Read64(s); - } else { - return i + Read64(GetSegment(m, rde, Sego(rde) - 1)); - } -} - -uint64_t DataSegment(struct Machine *m, uint32_t rde, uint64_t i) { - return AddSegment(m, rde, i, m->ds); -} - -uint64_t AddressSi(struct Machine *m, uint32_t rde) { - switch (Eamode(rde)) { - case XED_MODE_LONG: - return DataSegment(m, rde, Read64(m->si)); - case XED_MODE_REAL: - return DataSegment(m, rde, Read16(m->si)); - case XED_MODE_LEGACY: - return DataSegment(m, rde, Read32(m->si)); - default: - __builtin_unreachable(); - } -} - -uint64_t AddressDi(struct Machine *m, uint32_t rde) { - uint64_t i = Read64(m->es); - switch (Eamode(rde)) { - case XED_MODE_LONG: - return i + Read64(m->di); - case XED_MODE_REAL: - return i + Read16(m->di); - case XED_MODE_LEGACY: - return i + Read32(m->di); - default: - __builtin_unreachable(); - } -} diff --git a/tool/build/lib/address.h b/tool/build/lib/address.h deleted file mode 100644 index 1f3afcbe9..000000000 --- a/tool/build/lib/address.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_ADDRESS_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_ADDRESS_H_ -#include "libc/assert.h" -#include "third_party/xed/x86.h" -#include "tool/build/lib/machine.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -uint64_t AddressOb(struct Machine *, uint32_t); -uint64_t AddressDi(struct Machine *, uint32_t); -uint64_t AddressSi(struct Machine *, uint32_t); -uint64_t DataSegment(struct Machine *, uint32_t, uint64_t); -uint64_t AddSegment(struct Machine *, uint32_t, uint64_t, uint8_t[8]); -uint8_t *GetSegment(struct Machine *, uint32_t, int) nosideeffect; - -forceinline uint64_t MaskAddress(uint32_t mode, uint64_t x) { - if (mode != XED_MODE_LONG) { - if (mode == XED_MODE_REAL) { - x &= 0xffff; - } else { - x &= 0xffffffff; - } - } - return x; -} - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_ADDRESS_H_ */ diff --git a/tool/build/lib/alu.c b/tool/build/lib/alu.c deleted file mode 100644 index 88527f92f..000000000 --- a/tool/build/lib/alu.c +++ /dev/null @@ -1,763 +0,0 @@ -/*-*- 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/assert.h" -#include "tool/build/lib/alu.h" -#include "tool/build/lib/flags.h" - -const aluop_f kAlu[12][4] = { - {Add8, Add16, Add32, Add64}, {Or8, Or16, Or32, Or64}, - {Adc8, Adc16, Adc32, Adc64}, {Sbb8, Sbb16, Sbb32, Sbb64}, - {And8, And16, And32, And64}, {Sub8, Sub16, Sub32, Sub64}, - {Xor8, Xor16, Xor32, Xor64}, {Sub8, Sub16, Sub32, Sub64}, - {Not8, Not16, Not32, Not64}, {Neg8, Neg16, Neg32, Neg64}, - {Inc8, Inc16, Inc32, Inc64}, {Dec8, Dec16, Dec32, Dec64}, -}; - -const aluop_f kBsu[8][4] = { - {Rol8, Rol16, Rol32, Rol64}, {Ror8, Ror16, Ror32, Ror64}, - {Rcl8, Rcl16, Rcl32, Rcl64}, {Rcr8, Rcr16, Rcr32, Rcr64}, - {Shl8, Shl16, Shl32, Shl64}, {Shr8, Shr16, Shr32, Shr64}, - {Shl8, Shl16, Shl32, Shl64}, {Sar8, Sar16, Sar32, Sar64}, -}; - -int64_t AluFlags8(uint8_t z, uint32_t af, uint32_t *f, uint32_t of, - uint32_t cf) { - return AluFlags(z, af, f, of, cf, z >> 7); -} - -int64_t AluFlags32(uint32_t z, uint32_t af, uint32_t *f, uint32_t of, - uint32_t cf) { - return AluFlags(z, af, f, of, cf, z >> 31); -} - -int64_t Xor32(uint64_t x, uint64_t y, uint32_t *f) { - return AluFlags32(x ^ y, 0, f, 0, 0); -} - -int64_t Sub32(uint64_t x64, uint64_t y64, uint32_t *f) { - bool cf, of, af; - uint32_t x, y, z; - x = x64; - y = y64; - z = x - y; - cf = x < z; - af = (x & 15) < (z & 15); - of = ((z ^ x) & (x ^ y)) >> 31; - return AluFlags32(z, af, f, of, cf); -} - -int64_t AluFlags64(uint64_t z, uint32_t af, uint32_t *f, uint32_t of, - uint32_t cf) { - return AluFlags(z, af, f, of, cf, z >> 63); -} - -int64_t Sub64(uint64_t x, uint64_t y, uint32_t *f) { - uint64_t z; - bool cf, of, af; - z = x - y; - cf = x < z; - af = (x & 15) < (z & 15); - of = ((z ^ x) & (x ^ y)) >> 63; - return AluFlags64(z, af, f, of, cf); -} - -int64_t Xor8(uint64_t x, uint64_t y, uint32_t *f) { - return AluFlags8(x ^ y, 0, f, 0, 0); -} - -int64_t Xor64(uint64_t x, uint64_t y, uint32_t *f) { - return AluFlags64(x ^ y, 0, f, 0, 0); -} - -int64_t Or8(uint64_t x, uint64_t y, uint32_t *f) { - return AluFlags8(x | y, 0, f, 0, 0); -} - -int64_t Or32(uint64_t x, uint64_t y, uint32_t *f) { - return AluFlags32(x | y, 0, f, 0, 0); -} - -int64_t Or64(uint64_t x, uint64_t y, uint32_t *f) { - return AluFlags64(x | y, 0, f, 0, 0); -} - -int64_t And8(uint64_t x, uint64_t y, uint32_t *f) { - return AluFlags8(x & y, 0, f, 0, 0); -} - -int64_t And32(uint64_t x, uint64_t y, uint32_t *f) { - return AluFlags32(x & y, 0, f, 0, 0); -} - -int64_t And64(uint64_t x, uint64_t y, uint32_t *f) { - return AluFlags64(x & y, 0, f, 0, 0); -} - -int64_t Sub8(uint64_t x64, uint64_t y64, uint32_t *f) { - bool cf, of, af; - uint8_t x, y, z; - x = x64; - y = y64; - z = x - y; - cf = x < z; - af = (x & 15) < (z & 15); - of = ((z ^ x) & (x ^ y)) >> 7; - return AluFlags8(z, af, f, of, cf); -} - -int64_t Add8(uint64_t x64, uint64_t y64, uint32_t *f) { - bool cf, of, af; - uint8_t x, y, z; - x = x64; - y = y64; - z = x + y; - cf = z < y; - af = (z & 15) < (y & 15); - of = ((z ^ x) & (z ^ y)) >> 7; - return AluFlags8(z, af, f, of, cf); -} - -int64_t Add32(uint64_t x64, uint64_t y64, uint32_t *f) { - bool cf, of, af; - uint32_t x, y, z; - x = x64; - y = y64; - z = x + y; - cf = z < y; - af = (z & 15) < (y & 15); - of = ((z ^ x) & (z ^ y)) >> 31; - return AluFlags32(z, af, f, of, cf); -} - -int64_t Add64(uint64_t x, uint64_t y, uint32_t *f) { - uint64_t z; - bool cf, of, af; - z = x + y; - cf = z < y; - af = (z & 15) < (y & 15); - of = ((z ^ x) & (z ^ y)) >> 63; - return AluFlags64(z, af, f, of, cf); -} - -int64_t Adc8(uint64_t x64, uint64_t y64, uint32_t *f) { - bool cf, of, af; - uint8_t x, y, z, t; - x = x64; - y = y64; - t = x + GetFlag(*f, FLAGS_CF); - z = t + y; - cf = (t < x) | (z < y); - of = ((z ^ x) & (z ^ y)) >> 7; - af = ((t & 15) < (x & 15)) | ((z & 15) < (y & 15)); - return AluFlags8(z, af, f, of, cf); -} - -int64_t Adc32(uint64_t x64, uint64_t y64, uint32_t *f) { - bool cf, of, af; - uint32_t x, y, z, t; - x = x64; - y = y64; - t = x + GetFlag(*f, FLAGS_CF); - z = t + y; - cf = (t < x) | (z < y); - of = ((z ^ x) & (z ^ y)) >> 31; - af = ((t & 15) < (x & 15)) | ((z & 15) < (y & 15)); - return AluFlags32(z, af, f, of, cf); -} - -int64_t Adc64(uint64_t x, uint64_t y, uint32_t *f) { - uint64_t z, t; - bool cf, of, af; - t = x + GetFlag(*f, FLAGS_CF); - z = t + y; - cf = (t < x) | (z < y); - of = ((z ^ x) & (z ^ y)) >> 63; - af = ((t & 15) < (x & 15)) | ((z & 15) < (y & 15)); - return AluFlags64(z, af, f, of, cf); -} - -int64_t Sbb8(uint64_t x64, uint64_t y64, uint32_t *f) { - bool cf, of, af; - uint8_t x, y, z, t; - x = x64; - y = y64; - t = x - GetFlag(*f, FLAGS_CF); - z = t - y; - cf = (x < t) | (t < z); - of = ((z ^ x) & (x ^ y)) >> 7; - af = ((x & 15) < (t & 15)) | ((t & 15) < (z & 15)); - return AluFlags8(z, af, f, of, cf); -} - -int64_t Sbb32(uint64_t x64, uint64_t y64, uint32_t *f) { - bool cf, of, af; - uint32_t x, y, z, t; - x = x64; - y = y64; - t = x - GetFlag(*f, FLAGS_CF); - z = t - y; - cf = (x < t) | (t < z); - of = ((z ^ x) & (x ^ y)) >> 31; - af = ((x & 15) < (t & 15)) | ((t & 15) < (z & 15)); - return AluFlags32(z, af, f, of, cf); -} - -int64_t Sbb64(uint64_t x, uint64_t y, uint32_t *f) { - uint64_t z, t; - bool cf, of, af; - t = x - GetFlag(*f, FLAGS_CF); - z = t - y; - cf = (x < t) | (t < z); - of = ((z ^ x) & (x ^ y)) >> 63; - af = ((x & 15) < (t & 15)) | ((t & 15) < (z & 15)); - return AluFlags64(z, af, f, of, cf); -} - -int64_t Not8(uint64_t x, uint64_t y, uint32_t *f) { - return ~x & 0xFF; -} - -int64_t Not32(uint64_t x, uint64_t y, uint32_t *f) { - return ~x & 0xFFFFFFFF; -} - -int64_t Not64(uint64_t x, uint64_t y, uint32_t *f) { - return ~x & 0xFFFFFFFFFFFFFFFF; -} - -int64_t Neg8(uint64_t x64, uint64_t y, uint32_t *f) { - uint8_t x; - bool cf, of, af; - x = x64; - af = cf = !!x; - of = x == 0x80; - x = ~x + 1; - return AluFlags8(x, af, f, of, cf); -} - -int64_t Neg32(uint64_t x64, uint64_t y, uint32_t *f) { - uint32_t x; - bool cf, of, af; - x = x64; - af = cf = !!x; - of = x == 0x80000000; - x = ~x + 1; - return AluFlags32(x, af, f, of, cf); -} - -int64_t Neg64(uint64_t x64, uint64_t y, uint32_t *f) { - uint64_t x; - bool cf, of, af; - x = x64; - af = cf = !!x; - of = x == 0x8000000000000000; - x = ~x + 1; - return AluFlags64(x, af, f, of, cf); -} - -static int64_t BumpFlags(uint64_t x, uint32_t af, uint32_t *f, uint32_t of, - uint32_t sf) { - return AluFlags(x, af, f, of, GetFlag(*f, FLAGS_CF), sf); -} - -int64_t Dec32(uint64_t x64, uint64_t y, uint32_t *f) { - uint32_t x, z, of, sf, af; - x = x64; - z = x - 1; - sf = z >> 31; - af = (x & 15) < (z & 15); - of = ((z ^ x) & (x ^ 1)) >> 31; - return BumpFlags(z, af, f, of, sf); -} - -int64_t Inc32(uint64_t x64, uint64_t y, uint32_t *f) { - uint32_t x, z, of, sf, af; - x = x64; - z = x + 1; - sf = z >> 31; - af = (z & 15) < (y & 15); - of = ((z ^ x) & (z ^ 1)) >> 31; - return BumpFlags(z, af, f, of, sf); -} - -int64_t Inc64(uint64_t x, uint64_t y, uint32_t *f) { - uint64_t z; - uint32_t of, sf, af; - z = x + 1; - sf = z >> 63; - af = (z & 15) < (y & 15); - of = ((z ^ x) & (z ^ 1)) >> 63; - return BumpFlags(z, af, f, of, sf); -} - -int64_t Dec64(uint64_t x, uint64_t y, uint32_t *f) { - uint64_t z; - uint32_t of, sf, af; - z = x - 1; - sf = z >> 63; - af = (x & 15) < (z & 15); - of = ((z ^ x) & (x ^ 1)) >> 63; - return BumpFlags(z, af, f, of, sf); -} - -int64_t Inc8(uint64_t x64, uint64_t y, uint32_t *f) { - uint8_t x, z; - uint32_t of, sf, af; - x = x64; - z = x + 1; - sf = z >> 7; - af = (z & 15) < (y & 15); - of = ((z ^ x) & (z ^ 1)) >> 7; - return BumpFlags(z, af, f, of, sf); -} - -int64_t Dec8(uint64_t x64, uint64_t y, uint32_t *f) { - uint8_t x, z; - uint32_t of, sf, af; - x = x64; - z = x - 1; - sf = z >> 7; - af = (x & 15) < (z & 15); - of = ((z ^ x) & (x ^ 1)) >> 7; - return BumpFlags(z, af, f, of, sf); -} - -int64_t Shr8(uint64_t x64, uint64_t y, uint32_t *f) { - uint32_t x, cf; - x = x64 & 0xff; - if ((y &= 31)) { - cf = (x >> (y - 1)) & 1; - x >>= y; - return AluFlags8(x, 0, f, ((x << 1) ^ x) >> 7, cf); - } else { - return x; - } -} - -int64_t Shr32(uint64_t x64, uint64_t y, uint32_t *f) { - uint32_t cf, x = x64; - if ((y &= 31)) { - cf = (x >> (y - 1)) & 1; - x >>= y; - return AluFlags32(x, 0, f, ((x << 1) ^ x) >> 31, cf); - } else { - return x; - } -} - -int64_t Shr64(uint64_t x, uint64_t y, uint32_t *f) { - uint32_t cf; - if ((y &= 63)) { - cf = (x >> (y - 1)) & 1; - x >>= y; - return AluFlags64(x, 0, f, ((x << 1) ^ x) >> 63, cf); - } else { - return x; - } -} - -int64_t Shl8(uint64_t x64, uint64_t y, uint32_t *f) { - uint32_t x, cf; - x = x64 & 0xff; - if ((y &= 31)) { - cf = (x >> ((8 - y) & 31)) & 1; - x = (x << y) & 0xff; - return AluFlags8(x, 0, f, (x >> 7) ^ cf, cf); - } else { - return x; - } -} - -int64_t Shl32(uint64_t x64, uint64_t y, uint32_t *f) { - uint32_t cf, x = x64; - if ((y &= 31)) { - cf = (x >> (32 - y)) & 1; - x <<= y; - return AluFlags32(x, 0, f, (x >> 31) ^ cf, cf); - } else { - return x; - } -} - -int64_t Shl64(uint64_t x, uint64_t y, uint32_t *f) { - uint32_t cf; - if ((y &= 63)) { - cf = (x >> (64 - y)) & 1; - x <<= y; - return AluFlags64(x, 0, f, (x >> 63) ^ cf, cf); - } else { - return x; - } -} - -int64_t Sar8(uint64_t x64, uint64_t y, uint32_t *f) { - uint32_t x, cf; - x = x64 & 0xff; - if ((y &= 31)) { - cf = ((int32_t)(int8_t)x >> (y - 1)) & 1; - x = ((int32_t)(int8_t)x >> y) & 0xff; - return AluFlags8(x, 0, f, 0, cf); - } else { - return x; - } -} - -int64_t Sar32(uint64_t x64, uint64_t y, uint32_t *f) { - uint32_t cf, x = x64; - if ((y &= 31)) { - cf = ((int32_t)x >> (y - 1)) & 1; - x = (int32_t)x >> y; - return AluFlags32(x, 0, f, 0, cf); - } else { - return x; - } -} - -int64_t Sar64(uint64_t x, uint64_t y, uint32_t *f) { - uint32_t cf; - if ((y &= 63)) { - cf = ((int64_t)x >> (y - 1)) & 1; - x = (int64_t)x >> y; - return AluFlags64(x, 0, f, 0, cf); - } else { - return x; - } -} - -static int64_t RotateFlags(uint64_t x, uint32_t cf, uint32_t *f, uint32_t of) { - *f &= ~(1u << FLAGS_CF | 1u << FLAGS_OF); - *f |= cf << FLAGS_CF | of << FLAGS_OF; - return x; -} - -int64_t Rol32(uint64_t x64, uint64_t y, uint32_t *f) { - uint32_t x = x64; - if ((y &= 31)) { - x = x << y | x >> (32 - y); - return RotateFlags(x, x & 1, f, ((x >> 31) ^ x) & 1); - } else { - return x; - } -} - -int64_t Rol64(uint64_t x, uint64_t y, uint32_t *f) { - if ((y &= 63)) { - x = x << y | x >> (64 - y); - return RotateFlags(x, x & 1, f, ((x >> 63) ^ x) & 1); - } else { - return x; - } -} - -int64_t Ror32(uint64_t x64, uint64_t y, uint32_t *f) { - uint32_t x = x64; - if ((y &= 31)) { - x = x >> y | x << (32 - y); - return RotateFlags(x, x >> 31, f, ((x >> 31) ^ (x >> 30)) & 1); - } else { - return x; - } -} - -int64_t Ror64(uint64_t x, uint64_t y, uint32_t *f) { - if ((y &= 63)) { - x = x >> y | x << (64 - y); - return RotateFlags(x, x >> 63, f, ((x >> 63) ^ (x >> 62)) & 1); - } else { - return x; - } -} - -int64_t Rol8(uint64_t x64, uint64_t y, uint32_t *f) { - uint8_t x = x64; - if (y & 31) { - if ((y &= 7)) x = x << y | x >> (8 - y); - return RotateFlags(x, x & 1, f, ((x >> 7) ^ x) & 1); - } else { - return x; - } -} - -int64_t Ror8(uint64_t x64, uint64_t y, uint32_t *f) { - uint8_t x = x64; - if (y & 31) { - if ((y &= 7)) x = x >> y | x << (8 - y); - return RotateFlags(x, x >> 7, f, ((x >> 7) ^ (x >> 6)) & 1); - } else { - return x; - } -} - -static int64_t Rcr(uint64_t x, uint64_t y, uint32_t *f, uint64_t xm, - uint64_t k) { - uint64_t cf; - uint32_t ct; - x &= xm; - if (y) { - cf = GetFlag(*f, FLAGS_CF); - ct = (x >> (y - 1)) & 1; - if (y == 1) { - x = (x >> 1 | cf << (k - 1)) & xm; - } else { - x = (x >> y | cf << (k - y) | x << (k + 1 - y)) & xm; - } - return RotateFlags(x, ct, f, (((x << 1) ^ x) >> (k - 1)) & 1); - } else { - return x; - } -} - -int64_t Rcr8(uint64_t x, uint64_t y, uint32_t *f) { - return Rcr(x, (y & 31) % 9, f, 0xff, 8); -} - -int64_t Rcr16(uint64_t x, uint64_t y, uint32_t *f) { - return Rcr(x, (y & 31) % 17, f, 0xffff, 16); -} - -int64_t Rcr32(uint64_t x, uint64_t y, uint32_t *f) { - return Rcr(x, y & 31, f, 0xffffffff, 32); -} - -int64_t Rcr64(uint64_t x, uint64_t y, uint32_t *f) { - return Rcr(x, y & 63, f, 0xffffffffffffffff, 64); -} - -static int64_t Rcl(uint64_t x, uint64_t y, uint32_t *f, uint64_t xm, - uint64_t k) { - uint64_t cf; - uint32_t ct; - x &= xm; - if (y) { - cf = GetFlag(*f, FLAGS_CF); - ct = (x >> (k - y)) & 1; - if (y == 1) { - x = (x << 1 | cf) & xm; - } else { - x = (x << y | cf << (y - 1) | x >> (k + 1 - y)) & xm; - } - return RotateFlags(x, ct, f, ct ^ ((x >> (k - 1)) & 1)); - } else { - return x; - } -} - -int64_t Rcl8(uint64_t x, uint64_t y, uint32_t *f) { - return Rcl(x, (y & 31) % 9, f, 0xff, 8); -} - -int64_t Rcl16(uint64_t x, uint64_t y, uint32_t *f) { - return Rcl(x, (y & 31) % 17, f, 0xffff, 16); -} - -int64_t Rcl32(uint64_t x, uint64_t y, uint32_t *f) { - return Rcl(x, y & 31, f, 0xffffffff, 32); -} - -int64_t Rcl64(uint64_t x, uint64_t y, uint32_t *f) { - return Rcl(x, y & 63, f, 0xffffffffffffffff, 64); -} - -uint64_t BsuDoubleShift(int w, uint64_t x, uint64_t y, uint8_t b, bool isright, - uint32_t *f) { - bool cf, of; - uint64_t s, k, m, z; - k = 8; - k <<= w; - s = 1; - s <<= k - 1; - m = s | s - 1; - b &= w == 3 ? 63 : 31; - x &= m; - if (b) { - if (isright) { - z = x >> b | y << (k - b); - cf = (x >> (b - 1)) & 1; - of = b == 1 && (z & s) != (x & s); - } else { - z = x << b | y >> (k - b); - cf = (x >> (k - b)) & 1; - of = b == 1 && (z & s) != (x & s); - } - x = z; - x &= m; - return AluFlags(x, 0, f, of, cf, !!(x & s)); - } else { - return x; - } -} - -int64_t AluFlags16(uint16_t z, uint32_t af, uint32_t *f, uint32_t of, - uint32_t cf) { - return AluFlags(z, af, f, of, cf, z >> 15); -} - -int64_t Xor16(uint64_t x, uint64_t y, uint32_t *f) { - return AluFlags16(x ^ y, 0, f, 0, 0); -} - -int64_t Or16(uint64_t x, uint64_t y, uint32_t *f) { - return AluFlags16(x | y, 0, f, 0, 0); -} - -int64_t And16(uint64_t x, uint64_t y, uint32_t *f) { - return AluFlags16(x & y, 0, f, 0, 0); -} - -int64_t Sub16(uint64_t x64, uint64_t y64, uint32_t *f) { - bool cf, of, af; - uint16_t x, y, z; - x = x64; - y = y64; - z = x - y; - cf = x < z; - af = (x & 15) < (z & 15); - of = ((z ^ x) & (x ^ y)) >> 15; - return AluFlags16(z, af, f, of, cf); -} - -int64_t Add16(uint64_t x64, uint64_t y64, uint32_t *f) { - bool cf, of, af; - uint16_t x, y, z; - x = x64; - y = y64; - z = x + y; - cf = z < y; - af = (z & 15) < (y & 15); - of = ((z ^ x) & (z ^ y)) >> 15; - return AluFlags16(z, af, f, of, cf); -} - -int64_t Adc16(uint64_t x64, uint64_t y64, uint32_t *f) { - bool cf, of, af; - uint16_t x, y, z, t; - x = x64; - y = y64; - t = x + GetFlag(*f, FLAGS_CF); - z = t + y; - cf = (t < x) | (z < y); - of = ((z ^ x) & (z ^ y)) >> 15; - af = ((t & 15) < (x & 15)) | ((z & 15) < (y & 15)); - return AluFlags16(z, af, f, of, cf); -} - -int64_t Sbb16(uint64_t x64, uint64_t y64, uint32_t *f) { - bool cf, of, af; - uint16_t x, y, z, t; - x = x64; - y = y64; - t = x - GetFlag(*f, FLAGS_CF); - z = t - y; - cf = (x < t) | (t < z); - of = ((z ^ x) & (x ^ y)) >> 15; - af = ((x & 15) < (t & 15)) | ((t & 15) < (z & 15)); - return AluFlags16(z, af, f, of, cf); -} - -int64_t Not16(uint64_t x, uint64_t y, uint32_t *f) { - return ~x & 0xFFFF; -} - -int64_t Neg16(uint64_t x64, uint64_t y, uint32_t *f) { - uint16_t x; - bool cf, of, af; - x = x64; - af = cf = !!x; - of = x == 0x8000; - x = ~x + 1; - return AluFlags16(x, af, f, of, cf); -} - -int64_t Inc16(uint64_t x64, uint64_t y, uint32_t *f) { - uint16_t x, z; - uint32_t of, sf, af; - x = x64; - z = x + 1; - sf = z >> 15; - af = (z & 15) < (y & 15); - of = ((z ^ x) & (z ^ 1)) >> 15; - return BumpFlags(z, af, f, of, sf); -} - -int64_t Dec16(uint64_t x64, uint64_t y, uint32_t *f) { - uint16_t x, z; - uint32_t of, sf, af; - x = x64; - z = x - 1; - sf = z >> 15; - af = (x & 15) < (z & 15); - of = ((z ^ x) & (x ^ 1)) >> 15; - return BumpFlags(z, af, f, of, sf); -} - -int64_t Shr16(uint64_t x64, uint64_t y, uint32_t *f) { - uint32_t x, cf; - x = x64 & 0xffff; - if ((y &= 31)) { - cf = (x >> (y - 1)) & 1; - x >>= y; - return AluFlags16(x, 0, f, ((x << 1) ^ x) >> 15, cf); - } else { - return x; - } -} - -int64_t Shl16(uint64_t x64, uint64_t y, uint32_t *f) { - uint32_t x, cf; - x = x64 & 0xffff; - if ((y &= 31)) { - cf = (x >> ((16 - y) & 31)) & 1; - x = (x << y) & 0xffff; - return AluFlags16(x, 0, f, (x >> 15) ^ cf, cf); - } else { - return x; - } -} - -int64_t Sar16(uint64_t x64, uint64_t y, uint32_t *f) { - uint32_t x, cf; - x = x64 & 0xffff; - if ((y &= 31)) { - cf = ((int32_t)(int16_t)x >> (y - 1)) & 1; - x = ((int32_t)(int16_t)x >> y) & 0xffff; - return AluFlags16(x, 0, f, 0, cf); - } else { - return x; - } -} - -int64_t Rol16(uint64_t x64, uint64_t y, uint32_t *f) { - uint16_t x = x64; - if (y & 31) { - if ((y &= 15)) x = x << y | x >> (16 - y); - return RotateFlags(x, x & 1, f, ((x >> 15) ^ x) & 1); - } else { - return x; - } -} - -int64_t Ror16(uint64_t x64, uint64_t y, uint32_t *f) { - uint16_t x = x64; - if (y & 31) { - if ((y &= 15)) x = x >> y | x << (16 - y); - return RotateFlags(x, x >> 15, f, ((x >> 15) ^ (x >> 14)) & 1); - } else { - return x; - } -} diff --git a/tool/build/lib/alu.h b/tool/build/lib/alu.h deleted file mode 100644 index 4b73d7ca6..000000000 --- a/tool/build/lib/alu.h +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_ALU_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_ALU_H_ -#include "tool/build/lib/machine.h" - -#define ALU_ADD 0 -#define ALU_OR 1 -#define ALU_ADC 2 -#define ALU_SBB 3 -#define ALU_AND 4 -#define ALU_SUB 5 -#define ALU_XOR 6 -#define ALU_CMP 7 -#define ALU_NOT 8 -#define ALU_NEG 9 -#define ALU_INC 10 -#define ALU_DEC 11 - -#define BSU_ROL 0 -#define BSU_ROR 1 -#define BSU_RCL 2 -#define BSU_RCR 3 -#define BSU_SHL 4 -#define BSU_SHR 5 -#define BSU_SAL 6 -#define BSU_SAR 7 - -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -typedef int64_t (*aluop_f)(uint64_t, uint64_t, uint32_t *); - -extern const aluop_f kAlu[12][4]; -extern const aluop_f kBsu[8][4]; - -int64_t Xor8(uint64_t, uint64_t, uint32_t *); -int64_t Xor16(uint64_t, uint64_t, uint32_t *); -int64_t Xor32(uint64_t, uint64_t, uint32_t *); -int64_t Xor64(uint64_t, uint64_t, uint32_t *); -int64_t Or8(uint64_t, uint64_t, uint32_t *); -int64_t Or16(uint64_t, uint64_t, uint32_t *); -int64_t Or32(uint64_t, uint64_t, uint32_t *); -int64_t Or64(uint64_t, uint64_t, uint32_t *); -int64_t And8(uint64_t, uint64_t, uint32_t *); -int64_t And16(uint64_t, uint64_t, uint32_t *); -int64_t And32(uint64_t, uint64_t, uint32_t *); -int64_t And64(uint64_t, uint64_t, uint32_t *); -int64_t Sub8(uint64_t, uint64_t, uint32_t *); -int64_t Sbb8(uint64_t, uint64_t, uint32_t *); -int64_t Sub16(uint64_t, uint64_t, uint32_t *); -int64_t Sbb16(uint64_t, uint64_t, uint32_t *); -int64_t Sub32(uint64_t, uint64_t, uint32_t *); -int64_t Sbb32(uint64_t, uint64_t, uint32_t *); -int64_t Sub64(uint64_t, uint64_t, uint32_t *); -int64_t Sbb64(uint64_t, uint64_t, uint32_t *); -int64_t Add8(uint64_t, uint64_t, uint32_t *); -int64_t Adc8(uint64_t, uint64_t, uint32_t *); -int64_t Add16(uint64_t, uint64_t, uint32_t *); -int64_t Adc16(uint64_t, uint64_t, uint32_t *); -int64_t Add32(uint64_t, uint64_t, uint32_t *); -int64_t Adc32(uint64_t, uint64_t, uint32_t *); -int64_t Add64(uint64_t, uint64_t, uint32_t *); -int64_t Adc64(uint64_t, uint64_t, uint32_t *); -int64_t Not8(uint64_t, uint64_t, uint32_t *); -int64_t Not16(uint64_t, uint64_t, uint32_t *); -int64_t Not32(uint64_t, uint64_t, uint32_t *); -int64_t Not64(uint64_t, uint64_t, uint32_t *); -int64_t Neg8(uint64_t, uint64_t, uint32_t *); -int64_t Neg16(uint64_t, uint64_t, uint32_t *); -int64_t Neg32(uint64_t, uint64_t, uint32_t *); -int64_t Neg64(uint64_t, uint64_t, uint32_t *); -int64_t Inc8(uint64_t, uint64_t, uint32_t *); -int64_t Inc16(uint64_t, uint64_t, uint32_t *); -int64_t Inc32(uint64_t, uint64_t, uint32_t *); -int64_t Inc64(uint64_t, uint64_t, uint32_t *); -int64_t Dec8(uint64_t, uint64_t, uint32_t *); -int64_t Dec16(uint64_t, uint64_t, uint32_t *); -int64_t Dec32(uint64_t, uint64_t, uint32_t *); -int64_t Dec64(uint64_t, uint64_t, uint32_t *); - -int64_t Shr8(uint64_t, uint64_t, uint32_t *); -int64_t Shr16(uint64_t, uint64_t, uint32_t *); -int64_t Shr32(uint64_t, uint64_t, uint32_t *); -int64_t Shr64(uint64_t, uint64_t, uint32_t *); -int64_t Shl8(uint64_t, uint64_t, uint32_t *); -int64_t Shl16(uint64_t, uint64_t, uint32_t *); -int64_t Shl32(uint64_t, uint64_t, uint32_t *); -int64_t Shl64(uint64_t, uint64_t, uint32_t *); -int64_t Sar8(uint64_t, uint64_t, uint32_t *); -int64_t Sar16(uint64_t, uint64_t, uint32_t *); -int64_t Sar32(uint64_t, uint64_t, uint32_t *); -int64_t Sar64(uint64_t, uint64_t, uint32_t *); -int64_t Rol8(uint64_t, uint64_t, uint32_t *); -int64_t Rol16(uint64_t, uint64_t, uint32_t *); -int64_t Rol32(uint64_t, uint64_t, uint32_t *); -int64_t Rol64(uint64_t, uint64_t, uint32_t *); -int64_t Ror8(uint64_t, uint64_t, uint32_t *); -int64_t Ror16(uint64_t, uint64_t, uint32_t *); -int64_t Ror32(uint64_t, uint64_t, uint32_t *); -int64_t Ror64(uint64_t, uint64_t, uint32_t *); -int64_t Rcr8(uint64_t, uint64_t, uint32_t *); -int64_t Rcr16(uint64_t, uint64_t, uint32_t *); -int64_t Rcr32(uint64_t, uint64_t, uint32_t *); -int64_t Rcr64(uint64_t, uint64_t, uint32_t *); -int64_t Rcl8(uint64_t, uint64_t, uint32_t *); -int64_t Rcl16(uint64_t, uint64_t, uint32_t *); -int64_t Rcl32(uint64_t, uint64_t, uint32_t *); -int64_t Rcl64(uint64_t, uint64_t, uint32_t *); - -uint64_t BsuDoubleShift(int, uint64_t, uint64_t, uint8_t, bool, uint32_t *); - -int64_t AluFlags8(uint8_t, uint32_t, uint32_t *, uint32_t, uint32_t); -int64_t AluFlags16(uint16_t, uint32_t, uint32_t *, uint32_t, uint32_t); -int64_t AluFlags32(uint32_t, uint32_t, uint32_t *, uint32_t, uint32_t); -int64_t AluFlags64(uint64_t, uint32_t, uint32_t *, uint32_t, uint32_t); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_ALU_H_ */ diff --git a/tool/build/lib/argv.c b/tool/build/lib/argv.c deleted file mode 100644 index b311f0afb..000000000 --- a/tool/build/lib/argv.c +++ /dev/null @@ -1,75 +0,0 @@ -/*-*- 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/log/check.h" -#include "libc/mem/mem.h" -#include "libc/mem/gc.internal.h" -#include "libc/str/str.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/machine.h" -#include "tool/build/lib/memory.h" - -#define STACKALIGN 16 -#define LINUX_AT_EXECFN 31 - -static size_t GetArgListLen(char **p) { - size_t n; - for (n = 0; *p; ++p) ++n; - return n; -} - -static int64_t PushString(struct Machine *m, const char *s) { - size_t n; - int64_t sp; - n = strlen(s) + 1; - sp = Read64(m->sp); - sp -= n; - Write64(m->sp, sp); - VirtualRecv(m, sp, s, n); - return sp; -} - -void LoadArgv(struct Machine *m, const char *prog, char **args, char **vars) { - int64_t i, n, sp, *p, *bloc; - size_t narg, nenv, naux, nall; - DCHECK_NOTNULL(prog); - DCHECK_NOTNULL(args); - DCHECK_NOTNULL(vars); - naux = 1; - nenv = GetArgListLen(vars); - narg = GetArgListLen(args); - nall = 1 + 1 + narg + 1 + nenv + 1 + (naux + 1) * 2; - bloc = gc(malloc(sizeof(int64_t) * nall)); - p = bloc + nall; - *--p = 0; - *--p = 0; - *--p = PushString(m, prog); - *--p = LINUX_AT_EXECFN; - for (*--p = 0, i = nenv; i--;) *--p = PushString(m, vars[i]); - for (*--p = 0, i = narg; i--;) *--p = PushString(m, args[i]); - *--p = PushString(m, prog); - *--p = 1 + narg; - DCHECK_EQ(bloc, p); - sp = Read64(m->sp); - while ((sp - nall * sizeof(int64_t)) & (STACKALIGN - 1)) --sp; - sp -= nall * sizeof(int64_t); - DCHECK_EQ(0, sp % STACKALIGN); - Write64(m->sp, sp); - Write64(m->di, 0); /* or ape detects freebsd */ - VirtualRecv(m, sp, bloc, sizeof(int64_t) * nall); -} diff --git a/tool/build/lib/argv.h b/tool/build/lib/argv.h deleted file mode 100644 index 11328fccf..000000000 --- a/tool/build/lib/argv.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_ARGV_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_ARGV_H_ -#include "tool/build/lib/machine.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -void LoadArgv(struct Machine *, const char *, char **, char **); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_ARGV_H_ */ diff --git a/tool/build/lib/bcd.c b/tool/build/lib/bcd.c deleted file mode 100644 index bb836bfa2..000000000 --- a/tool/build/lib/bcd.c +++ /dev/null @@ -1,77 +0,0 @@ -/*-*- 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 "tool/build/lib/alu.h" -#include "tool/build/lib/bcd.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/flags.h" -#include "tool/build/lib/throw.h" - -relegated void OpDas(struct Machine *m, uint32_t rde) { - uint8_t al, af, cf; - af = cf = 0; - al = m->ax[0]; - if ((al & 0x0f) > 9 || GetFlag(m->flags, FLAGS_AF)) { - cf = m->ax[0] < 6 || GetFlag(m->flags, FLAGS_CF); - m->ax[0] -= 0x06; - af = 1; - } - if (al > 0x99 || GetFlag(m->flags, FLAGS_CF)) { - m->ax[0] -= 0x60; - cf = 1; - } - AluFlags8(m->ax[0], af, &m->flags, 0, cf); -} - -relegated void OpAaa(struct Machine *m, uint32_t rde) { - uint8_t af, cf; - af = cf = 0; - if ((m->ax[0] & 0x0f) > 9 || GetFlag(m->flags, FLAGS_AF)) { - cf = m->ax[0] < 6 || GetFlag(m->flags, FLAGS_CF); - Write16(m->ax, Read16(m->ax) + 0x106); - af = cf = 1; - } - m->ax[0] &= 0x0f; - AluFlags8(m->ax[0], af, &m->flags, 0, cf); -} - -relegated void OpAas(struct Machine *m, uint32_t rde) { - uint8_t af, cf; - af = cf = 0; - if ((m->ax[0] & 0x0f) > 9 || GetFlag(m->flags, FLAGS_AF)) { - cf = m->ax[0] < 6 || GetFlag(m->flags, FLAGS_CF); - Write16(m->ax, Read16(m->ax) - 0x106); - af = cf = 1; - } - m->ax[0] &= 0x0f; - AluFlags8(m->ax[0], af, &m->flags, 0, cf); -} - -relegated void OpAam(struct Machine *m, uint32_t rde) { - uint8_t i = m->xedd->op.uimm0; - if (!i) ThrowDivideError(m); - m->ax[1] = m->ax[0] / i; - m->ax[0] = m->ax[0] % i; - AluFlags8(m->ax[0], 0, &m->flags, 0, 0); -} - -relegated void OpAad(struct Machine *m, uint32_t rde) { - uint8_t i = m->xedd->op.uimm0; - Write16(m->ax, (m->ax[1] * i + m->ax[0]) & 0xff); - AluFlags8(m->ax[0], 0, &m->flags, 0, 0); -} diff --git a/tool/build/lib/bcd.h b/tool/build/lib/bcd.h deleted file mode 100644 index 206ec6efc..000000000 --- a/tool/build/lib/bcd.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_BCD_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_BCD_H_ -#include "tool/build/lib/machine.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -void OpDas(struct Machine *, uint32_t); -void OpAaa(struct Machine *, uint32_t); -void OpAas(struct Machine *, uint32_t); -void OpAam(struct Machine *, uint32_t); -void OpAad(struct Machine *, uint32_t); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_BCD_H_ */ diff --git a/tool/build/lib/bitscan.c b/tool/build/lib/bitscan.c deleted file mode 100644 index d7f80910c..000000000 --- a/tool/build/lib/bitscan.c +++ /dev/null @@ -1,145 +0,0 @@ -/*-*- 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 "tool/build/lib/bitscan.h" -#include "tool/build/lib/flags.h" -#include "tool/build/lib/machine.h" -#include "tool/build/lib/modrm.h" - -uint64_t AluPopcnt(struct Machine *m, uint32_t rde, uint64_t x) { - m->flags = SetFlag(m->flags, FLAGS_ZF, !x); - m->flags = SetFlag(m->flags, FLAGS_CF, false); - m->flags = SetFlag(m->flags, FLAGS_SF, false); - m->flags = SetFlag(m->flags, FLAGS_OF, false); - m->flags = SetFlag(m->flags, FLAGS_PF, false); - x = x - ((x >> 1) & 0x5555555555555555); - x = ((x >> 2) & 0x3333333333333333) + (x & 0x3333333333333333); - x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f; - x = (x + (x >> 32)) & 0xffffffff; - x = x + (x >> 16); - x = (x + (x >> 8)) & 0x7f; - return x; -} - -uint64_t AluBsr(struct Machine *m, uint32_t rde, uint64_t x) { - unsigned i; - if (Rexw(rde)) { - x &= 0xffffffffffffffff; - if (Rep(rde) == 3) { - if (!x) { - m->flags = SetFlag(m->flags, FLAGS_CF, true); - m->flags = SetFlag(m->flags, FLAGS_ZF, false); - return 64; - } else { - m->flags = SetFlag(m->flags, FLAGS_CF, false); - m->flags = SetFlag(m->flags, FLAGS_ZF, x == 1); - } - } else { - m->flags = SetFlag(m->flags, FLAGS_ZF, !x); - if (!x) return 0; - } - return 63 ^ __builtin_clzll(x); - } else if (!Osz(rde)) { - x &= 0xffffffff; - if (Rep(rde) == 3) { - if (!x) { - m->flags = SetFlag(m->flags, FLAGS_CF, true); - m->flags = SetFlag(m->flags, FLAGS_ZF, false); - return 32; - } else { - m->flags = SetFlag(m->flags, FLAGS_CF, false); - m->flags = SetFlag(m->flags, FLAGS_ZF, x == 1); - } - } else { - m->flags = SetFlag(m->flags, FLAGS_ZF, !x); - if (!x) return 0; - } - return 31 ^ __builtin_clz(x); - } else { - x &= 0xffff; - if (Rep(rde) == 3) { - if (!x) { - m->flags = SetFlag(m->flags, FLAGS_CF, true); - m->flags = SetFlag(m->flags, FLAGS_ZF, false); - return 16; - } else { - m->flags = SetFlag(m->flags, FLAGS_CF, false); - m->flags = SetFlag(m->flags, FLAGS_ZF, x == 1); - } - } else { - m->flags = SetFlag(m->flags, FLAGS_ZF, !x); - if (!x) return 0; - } - for (i = 15; !(x & 0x8000); --i) x <<= 1; - return i; - } -} - -uint64_t AluBsf(struct Machine *m, uint32_t rde, uint64_t x) { - unsigned i; - if (Rexw(rde)) { - x &= 0xffffffffffffffff; - if (Rep(rde) == 3) { - if (!x) { - m->flags = SetFlag(m->flags, FLAGS_CF, true); - m->flags = SetFlag(m->flags, FLAGS_ZF, false); - return 64; - } else { - m->flags = SetFlag(m->flags, FLAGS_CF, false); - m->flags = SetFlag(m->flags, FLAGS_ZF, x & 1); - } - } else { - m->flags = SetFlag(m->flags, FLAGS_ZF, !x); - if (!x) return 0; - } - return __builtin_ctzll(x); - } else if (!Osz(rde)) { - x &= 0xffffffff; - if (Rep(rde) == 3) { - if (!x) { - m->flags = SetFlag(m->flags, FLAGS_CF, true); - m->flags = SetFlag(m->flags, FLAGS_ZF, false); - return 32; - } else { - m->flags = SetFlag(m->flags, FLAGS_CF, false); - m->flags = SetFlag(m->flags, FLAGS_ZF, x & 1); - } - } else { - m->flags = SetFlag(m->flags, FLAGS_ZF, !x); - if (!x) return 0; - } - return __builtin_ctz(x); - } else { - x &= 0xffff; - if (Rep(rde) == 3) { - if (!x) { - m->flags = SetFlag(m->flags, FLAGS_CF, true); - m->flags = SetFlag(m->flags, FLAGS_ZF, false); - return 16; - } else { - m->flags = SetFlag(m->flags, FLAGS_CF, false); - m->flags = SetFlag(m->flags, FLAGS_ZF, x & 1); - } - } else { - m->flags = SetFlag(m->flags, FLAGS_ZF, !x); - if (!x) return 0; - } - for (i = 0; !(x & 1); ++i) x >>= 1; - return i; - } -} diff --git a/tool/build/lib/bitscan.h b/tool/build/lib/bitscan.h deleted file mode 100644 index 26d865747..000000000 --- a/tool/build/lib/bitscan.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_BITSCAN_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_BITSCAN_H_ -#include "tool/build/lib/machine.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -typedef uint64_t (*bitscan_f)(struct Machine *, uint32_t, uint64_t); - -uint64_t AluBsr(struct Machine *, uint32_t, uint64_t); -uint64_t AluBsf(struct Machine *, uint32_t, uint64_t); -uint64_t AluPopcnt(struct Machine *, uint32_t, uint64_t); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_BITSCAN_H_ */ diff --git a/tool/build/lib/breakpoint.c b/tool/build/lib/breakpoint.c deleted file mode 100644 index f363ea2d2..000000000 --- a/tool/build/lib/breakpoint.c +++ /dev/null @@ -1,56 +0,0 @@ -/*-*- 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/mem/arraylist2.internal.h" -#include "libc/assert.h" -#include "libc/log/log.h" -#include "tool/build/lib/breakpoint.h" - -void PopBreakpoint(struct Breakpoints *bps) { - if (bps->i) { - --bps->i; - } -} - -ssize_t PushBreakpoint(struct Breakpoints *bps, struct Breakpoint *b) { - int i; - for (i = 0; i < bps->i; ++i) { - if (bps->p[i].disable) { - memcpy(&bps->p[i], b, sizeof(*b)); - return i; - } - } - return APPEND(&bps->p, &bps->i, &bps->n, b); -} - -ssize_t IsAtBreakpoint(struct Breakpoints *bps, int64_t addr) { - size_t i; - for (i = bps->i; i--;) { - if (bps->p[i].disable) continue; - if (bps->p[i].addr == addr) { - if (bps->p[i].oneshot) { - bps->p[i].disable = true; - if (i == bps->i - 1) { - --bps->i; - } - } - return i; - } - } - return -1; -} diff --git a/tool/build/lib/breakpoint.h b/tool/build/lib/breakpoint.h deleted file mode 100644 index 24e16d395..000000000 --- a/tool/build/lib/breakpoint.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_BREAKPOINT_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_BREAKPOINT_H_ -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -struct Breakpoints { - size_t i, n; - struct Breakpoint { - int64_t addr; - const char *symbol; - bool disable; - bool oneshot; - } * p; -}; - -ssize_t IsAtBreakpoint(struct Breakpoints *, int64_t); -ssize_t PushBreakpoint(struct Breakpoints *, struct Breakpoint *); -void PopBreakpoint(struct Breakpoints *); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_BREAKPOINT_H_ */ diff --git a/tool/build/lib/breg.c b/tool/build/lib/breg.c deleted file mode 100644 index f092c6267..000000000 --- a/tool/build/lib/breg.c +++ /dev/null @@ -1,36 +0,0 @@ -/*-*- 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 "tool/build/lib/modrm.h" - -/** - * Byte register offsets. - * - * for (i = 0; i < 2; ++i) { // rex - * for (j = 0; j < 2; ++j) { // rexb, or rexr - * for (k = 0; k < 8; ++k) { // reg, rm, or srm - * kByteReg[i << 4 | j << 3 | k] = - * i ? (j << 3 | k) * 8 : (k & 0b11) * 8 + ((k & 0b100) >> 2); - * } - * } - * } - */ -const uint8_t kByteReg[32] = {0x00, 0x08, 0x10, 0x18, 0x01, 0x09, 0x11, 0x19, - 0x00, 0x08, 0x10, 0x18, 0x01, 0x09, 0x11, 0x19, - 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, - 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78}; diff --git a/tool/build/lib/cga.c b/tool/build/lib/cga.c deleted file mode 100644 index 144d9c7f6..000000000 --- a/tool/build/lib/cga.c +++ /dev/null @@ -1,56 +0,0 @@ -/*-*- 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/fmt/itoa.h" -#include "libc/macros.internal.h" -#include "libc/str/str.h" -#include "libc/str/tab.internal.h" -#include "tool/build/lib/buffer.h" -#include "tool/build/lib/cga.h" - -/* blk blu grn cyn red mag yel wht */ -static const uint8_t kCgaToAnsi[16] = {30, 34, 32, 36, 31, 35, 33, 37, - 90, 94, 92, 96, 91, 95, 93, 97}; - -size_t FormatCga(uint8_t bgfg, char buf[hasatleast 11]) { - char *p = buf; - *p++ = '\e'; - *p++ = '['; - p = FormatUint32(p, kCgaToAnsi[(bgfg & 0xF0) >> 4] + 10); - *p++ = ';'; - p = FormatUint32(p, kCgaToAnsi[bgfg & 0x0F]); - *p++ = 'm'; - *p = '\0'; - return p - buf; -} - -void DrawCga(struct Panel *p, uint8_t v[25][80][2]) { - char buf[11]; - unsigned y, x, n, a; - n = MIN(25, p->bottom - p->top); - for (y = 0; y < n; ++y) { - a = -1; - for (x = 0; x < 80; ++x) { - if (v[y][x][1] != a) { - AppendData(&p->lines[y], buf, FormatCga((a = v[y][x][1]), buf)); - } - AppendWide(&p->lines[y], kCp437[v[y][x][0]]); - } - AppendStr(&p->lines[y], "\e[0m"); - } -} diff --git a/tool/build/lib/cga.h b/tool/build/lib/cga.h deleted file mode 100644 index d45c76cae..000000000 --- a/tool/build/lib/cga.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_CGA_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_CGA_H_ -#include "tool/build/lib/panel.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -void DrawCga(struct Panel *, uint8_t[25][80][2]); -size_t FormatCga(uint8_t, char[hasatleast 11]); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_CGA_H_ */ diff --git a/tool/build/lib/clmul.c b/tool/build/lib/clmul.c deleted file mode 100644 index 003db5f57..000000000 --- a/tool/build/lib/clmul.c +++ /dev/null @@ -1,52 +0,0 @@ -/*-*- 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 2021 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/intrin/bsr.h" -#include "libc/nexgen32e/x86feature.h" -#include "tool/build/lib/clmul.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/modrm.h" - -/** - * @fileoverview Carryless Multiplication ISA - */ - -struct clmul { - uint64_t x, y; -}; - -static struct clmul clmul(uint64_t a, uint64_t b) { - uint64_t t, x = 0, y = 0; - if (a && b) { - if (_bsrl(a) < _bsrl(b)) t = a, a = b, b = t; - for (t = 0; b; a <<= 1, b >>= 1) { - if (b & 1) x ^= a, y ^= t; - t = t << 1 | a >> 63; - } - } - return (struct clmul){x, y}; -} - -void OpSsePclmulqdq(struct Machine *m, uint32_t rde) { - struct clmul res; - res = clmul(Read64(XmmRexrReg(m, rde) + ((m->xedd->op.uimm0 & 0x01) << 3)), - Read64(GetModrmRegisterXmmPointerRead16(m, rde) + - ((m->xedd->op.uimm0 & 0x10) >> 1))); - Write64(XmmRexrReg(m, rde) + 0, res.x); - Write64(XmmRexrReg(m, rde) + 8, res.y); -} diff --git a/tool/build/lib/clmul.h b/tool/build/lib/clmul.h deleted file mode 100644 index 803495e22..000000000 --- a/tool/build/lib/clmul.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_CLMUL_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_CLMUL_H_ -#include "tool/build/lib/machine.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -void OpSsePclmulqdq(struct Machine *, uint32_t); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_CLMUL_H_ */ diff --git a/tool/build/lib/cpuid.c b/tool/build/lib/cpuid.c deleted file mode 100644 index 94c46810b..000000000 --- a/tool/build/lib/cpuid.c +++ /dev/null @@ -1,88 +0,0 @@ -/*-*- 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 "tool/build/lib/endian.h" -#include "tool/build/lib/machine.h" - -void OpCpuid(struct Machine *m, uint32_t rde) { - uint32_t ax, bx, cx, dx; - ax = 0; - bx = 0; - cx = 0; - dx = 0; - switch (Read32(m->ax)) { - case 0: - case 0x80000000: - ax = 7; - bx = 'G' | 'e' << 8 | 'n' << 16 | 'u' << 24; - dx = 'i' | 'n' << 8 | 'e' << 16 | 'C' << 24; - cx = 'o' | 's' << 8 | 'm' << 16 | 'o' << 24; - break; - case 1: - cx |= 1 << 0; // sse3 - cx |= 1 << 1; // pclmulqdq - cx |= 1 << 9; // ssse3 - cx |= 1 << 23; // popcnt - cx |= 1 << 30; // rdrnd - cx |= 0 << 25; // aes - cx |= 1 << 13; // cmpxchg16b - dx |= 1 << 0; // fpu - dx |= 1 << 4; // tsc - dx |= 1 << 6; // pae - dx |= 1 << 8; // cmpxchg8b - dx |= 1 << 15; // cmov - dx |= 1 << 19; // clflush - dx |= 1 << 23; // mmx - dx |= 1 << 24; // fxsave - dx |= 1 << 25; // sse - dx |= 1 << 26; // sse2 - break; - case 7: - switch (Read32(m->cx)) { - case 0: - bx |= 1 << 0; // fsgsbase - bx |= 1 << 9; // erms - bx |= 0 << 18; // rdseed - cx |= 1 << 22; // rdpid - break; - default: - break; - } - break; - case 0x80000001: - cx |= 1 << 0; // lahf - dx |= 1 << 0; // fpu - dx |= 1 << 8; // cmpxchg8b - dx |= 1 << 11; // syscall - dx |= 1 << 15; // cmov - dx |= 1 << 23; // mmx - dx |= 1 << 24; // fxsave - dx |= 1 << 27; // rdtscp - dx |= 1 << 29; // long - break; - case 0x80000007: - dx |= 1 << 8; // invtsc - break; - default: - break; - } - Write64(m->ax, ax); - Write64(m->bx, bx); - Write64(m->cx, cx); - Write64(m->dx, dx); -} diff --git a/tool/build/lib/cpuid.h b/tool/build/lib/cpuid.h deleted file mode 100644 index 6bc161162..000000000 --- a/tool/build/lib/cpuid.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_CPUID_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_CPUID_H_ -#include "tool/build/lib/machine.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -void OpCpuid(struct Machine *, uint32_t); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_CPUID_H_ */ diff --git a/tool/build/lib/cvt.c b/tool/build/lib/cvt.c deleted file mode 100644 index f0756cf27..000000000 --- a/tool/build/lib/cvt.c +++ /dev/null @@ -1,458 +0,0 @@ -/*-*- 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/macros.internal.h" -#include "libc/math.h" -#include "libc/str/str.h" -#include "tool/build/lib/cvt.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/fpu.h" -#include "tool/build/lib/machine.h" -#include "tool/build/lib/memory.h" -#include "tool/build/lib/modrm.h" -#include "tool/build/lib/pun.h" -#include "tool/build/lib/throw.h" - -#define kOpCvt0f2a 0 -#define kOpCvtt0f2c 4 -#define kOpCvt0f2d 8 -#define kOpCvt0f5a 12 -#define kOpCvt0f5b 16 -#define kOpCvt0fE6 20 - -static double SseRoundDouble(struct Machine *m, double x) { - switch ((m->mxcsr & kMxcsrRc) >> 13) { - case 0: - return rint(x); - case 1: - return floor(x); - case 2: - return ceil(x); - case 3: - return trunc(x); - default: - for (;;) (void)0; - } -} - -static void OpGdqpWssCvttss2si(struct Machine *m, uint32_t rde) { - int64_t n; - union FloatPun f; - f.i = Read32(GetModrmRegisterXmmPointerRead4(m, rde)); - n = f.f; - if (!Rexw(rde)) n &= 0xffffffff; - Write64(RegRexrReg(m, rde), n); -} - -static void OpGdqpWsdCvttsd2si(struct Machine *m, uint32_t rde) { - int64_t n; - union DoublePun d; - d.i = Read64(GetModrmRegisterXmmPointerRead8(m, rde)); - n = d.f; - if (!Rexw(rde)) n &= 0xffffffff; - Write64(RegRexrReg(m, rde), n); -} - -static void OpGdqpWssCvtss2si(struct Machine *m, uint32_t rde) { - int64_t n; - union FloatPun f; - f.i = Read32(GetModrmRegisterXmmPointerRead4(m, rde)); - n = rintf(f.f); - if (!Rexw(rde)) n &= 0xffffffff; - Write64(RegRexrReg(m, rde), n); -} - -static void OpGdqpWsdCvtsd2si(struct Machine *m, uint32_t rde) { - int64_t n; - union DoublePun d; - d.i = Read64(GetModrmRegisterXmmPointerRead8(m, rde)); - n = SseRoundDouble(m, d.f); - if (!Rexw(rde)) n &= 0xffffffff; - Write64(RegRexrReg(m, rde), n); -} - -static void OpVssEdqpCvtsi2ss(struct Machine *m, uint32_t rde) { - union FloatPun f; - if (Rexw(rde)) { - int64_t n; - n = Read64(GetModrmRegisterWordPointerRead8(m, rde)); - f.f = n; - Write32(XmmRexrReg(m, rde), f.i); - } else { - int32_t n; - n = Read32(GetModrmRegisterWordPointerRead4(m, rde)); - f.f = n; - Write32(XmmRexrReg(m, rde), f.i); - } -} - -static void OpVsdEdqpCvtsi2sd(struct Machine *m, uint32_t rde) { - union DoublePun d; - if (Rexw(rde)) { - int64_t n; - n = Read64(GetModrmRegisterWordPointerRead8(m, rde)); - d.f = n; - Write64(XmmRexrReg(m, rde), d.i); - } else { - int32_t n; - n = Read32(GetModrmRegisterWordPointerRead4(m, rde)); - d.f = n; - Write64(XmmRexrReg(m, rde), d.i); - } -} - -static void OpVpsQpiCvtpi2ps(struct Machine *m, uint32_t rde) { - uint8_t *p; - int32_t i[2]; - union FloatPun f[2]; - p = GetModrmRegisterMmPointerRead8(m, rde); - i[0] = Read32(p + 0); - i[1] = Read32(p + 4); - f[0].f = i[0]; - f[1].f = i[1]; - Write32(XmmRexrReg(m, rde) + 0, f[0].i); - Write32(XmmRexrReg(m, rde) + 4, f[1].i); -} - -static void OpVpdQpiCvtpi2pd(struct Machine *m, uint32_t rde) { - uint8_t *p; - int32_t n[2]; - union DoublePun f[2]; - p = GetModrmRegisterMmPointerRead8(m, rde); - n[0] = Read32(p + 0); - n[1] = Read32(p + 4); - f[0].f = n[0]; - f[1].f = n[1]; - Write64(XmmRexrReg(m, rde) + 0, f[0].i); - Write64(XmmRexrReg(m, rde) + 8, f[1].i); -} - -static void OpPpiWpsqCvtps2pi(struct Machine *m, uint32_t rde) { - uint8_t *p; - unsigned i; - int32_t n[2]; - union FloatPun f[2]; - p = GetModrmRegisterXmmPointerRead8(m, rde); - f[0].i = Read32(p + 0 * 4); - f[1].i = Read32(p + 1 * 4); - switch ((m->mxcsr & kMxcsrRc) >> 13) { - case 0: - for (i = 0; i < 2; ++i) n[i] = rintf(f[i].f); - break; - case 1: - for (i = 0; i < 2; ++i) n[i] = floorf(f[i].f); - break; - case 2: - for (i = 0; i < 2; ++i) n[i] = ceilf(f[i].f); - break; - case 3: - for (i = 0; i < 2; ++i) n[i] = truncf(f[i].f); - break; - default: - for (;;) (void)0; - } - Write32(MmReg(m, rde) + 0, n[0]); - Write32(MmReg(m, rde) + 4, n[1]); -} - -static void OpPpiWpsqCvttps2pi(struct Machine *m, uint32_t rde) { - uint8_t *p; - int32_t n[2]; - union FloatPun f[2]; - p = GetModrmRegisterXmmPointerRead8(m, rde); - f[0].i = Read32(p + 0); - f[1].i = Read32(p + 4); - n[0] = f[0].f; - n[1] = f[1].f; - Write32(MmReg(m, rde) + 0, n[0]); - Write32(MmReg(m, rde) + 4, n[1]); -} - -static void OpPpiWpdCvtpd2pi(struct Machine *m, uint32_t rde) { - uint8_t *p; - unsigned i; - int32_t n[2]; - union DoublePun d[2]; - p = GetModrmRegisterXmmPointerRead16(m, rde); - d[0].i = Read64(p + 0); - d[1].i = Read64(p + 8); - for (i = 0; i < 2; ++i) n[i] = SseRoundDouble(m, d[i].f); - Write32(MmReg(m, rde) + 0, n[0]); - Write32(MmReg(m, rde) + 4, n[1]); -} - -static void OpPpiWpdCvttpd2pi(struct Machine *m, uint32_t rde) { - uint8_t *p; - int32_t n[2]; - union DoublePun d[2]; - p = GetModrmRegisterXmmPointerRead16(m, rde); - d[0].i = Read64(p + 0); - d[1].i = Read64(p + 8); - n[0] = d[0].f; - n[1] = d[1].f; - Write32(MmReg(m, rde) + 0, n[0]); - Write32(MmReg(m, rde) + 4, n[1]); -} - -static void OpVpdWpsCvtps2pd(struct Machine *m, uint32_t rde) { - uint8_t *p; - union FloatPun f[2]; - union DoublePun d[2]; - p = GetModrmRegisterXmmPointerRead8(m, rde); - f[0].i = Read32(p + 0); - f[1].i = Read32(p + 4); - d[0].f = f[0].f; - d[1].f = f[1].f; - Write64(XmmRexrReg(m, rde) + 0, d[0].i); - Write64(XmmRexrReg(m, rde) + 8, d[1].i); -} - -static void OpVpsWpdCvtpd2ps(struct Machine *m, uint32_t rde) { - uint8_t *p; - union FloatPun f[2]; - union DoublePun d[2]; - p = GetModrmRegisterXmmPointerRead16(m, rde); - d[0].i = Read64(p + 0); - d[1].i = Read64(p + 8); - f[0].f = d[0].f; - f[1].f = d[1].f; - Write32(XmmRexrReg(m, rde) + 0, f[0].i); - Write32(XmmRexrReg(m, rde) + 4, f[1].i); -} - -static void OpVssWsdCvtsd2ss(struct Machine *m, uint32_t rde) { - union FloatPun f; - union DoublePun d; - d.i = Read64(GetModrmRegisterXmmPointerRead8(m, rde)); - f.f = d.f; - Write32(XmmRexrReg(m, rde), f.i); -} - -static void OpVsdWssCvtss2sd(struct Machine *m, uint32_t rde) { - union FloatPun f; - union DoublePun d; - f.i = Read32(GetModrmRegisterXmmPointerRead4(m, rde)); - d.f = f.f; - Write64(XmmRexrReg(m, rde), d.i); -} - -static void OpVpsWdqCvtdq2ps(struct Machine *m, uint32_t rde) { - uint8_t *p; - int32_t n[4]; - union FloatPun f[4]; - p = GetModrmRegisterXmmPointerRead16(m, rde); - n[0] = Read32(p + 0 * 4); - n[1] = Read32(p + 1 * 4); - n[2] = Read32(p + 2 * 4); - n[3] = Read32(p + 3 * 4); - f[0].f = n[0]; - f[1].f = n[1]; - f[2].f = n[2]; - f[3].f = n[3]; - Write32(XmmRexrReg(m, rde) + 0 * 4, f[0].i); - Write32(XmmRexrReg(m, rde) + 1 * 4, f[1].i); - Write32(XmmRexrReg(m, rde) + 2 * 4, f[2].i); - Write32(XmmRexrReg(m, rde) + 3 * 4, f[3].i); -} - -static void OpVpdWdqCvtdq2pd(struct Machine *m, uint32_t rde) { - uint8_t *p; - int32_t n[2]; - union DoublePun d[2]; - p = GetModrmRegisterXmmPointerRead8(m, rde); - n[0] = Read32(p + 0 * 4); - n[1] = Read32(p + 1 * 4); - d[0].f = n[0]; - d[1].f = n[1]; - Write64(XmmRexrReg(m, rde) + 0, d[0].i); - Write64(XmmRexrReg(m, rde) + 8, d[1].i); -} - -static void OpVdqWpsCvttps2dq(struct Machine *m, uint32_t rde) { - uint8_t *p; - int32_t n[4]; - union FloatPun f[4]; - p = GetModrmRegisterXmmPointerRead16(m, rde); - f[0].i = Read32(p + 0 * 4); - f[1].i = Read32(p + 1 * 4); - f[2].i = Read32(p + 2 * 4); - f[3].i = Read32(p + 3 * 4); - n[0] = f[0].f; - n[1] = f[1].f; - n[2] = f[2].f; - n[3] = f[3].f; - Write32(XmmRexrReg(m, rde) + 0 * 4, n[0]); - Write32(XmmRexrReg(m, rde) + 1 * 4, n[1]); - Write32(XmmRexrReg(m, rde) + 2 * 4, n[2]); - Write32(XmmRexrReg(m, rde) + 3 * 4, n[3]); -} - -static void OpVdqWpsCvtps2dq(struct Machine *m, uint32_t rde) { - uint8_t *p; - unsigned i; - int32_t n[4]; - union FloatPun f[4]; - p = GetModrmRegisterXmmPointerRead16(m, rde); - f[0].i = Read32(p + 0 * 4); - f[1].i = Read32(p + 1 * 4); - f[2].i = Read32(p + 2 * 4); - f[3].i = Read32(p + 3 * 4); - switch ((m->mxcsr & kMxcsrRc) >> 13) { - case 0: - for (i = 0; i < 4; ++i) n[i] = rintf(f[i].f); - break; - case 1: - for (i = 0; i < 4; ++i) n[i] = floorf(f[i].f); - break; - case 2: - for (i = 0; i < 4; ++i) n[i] = ceilf(f[i].f); - break; - case 3: - for (i = 0; i < 4; ++i) n[i] = truncf(f[i].f); - break; - default: - for (;;) (void)0; - } - Write32(XmmRexrReg(m, rde) + 0 * 4, n[0]); - Write32(XmmRexrReg(m, rde) + 1 * 4, n[1]); - Write32(XmmRexrReg(m, rde) + 2 * 4, n[2]); - Write32(XmmRexrReg(m, rde) + 3 * 4, n[3]); -} - -static void OpVdqWpdCvttpd2dq(struct Machine *m, uint32_t rde) { - uint8_t *p; - int32_t n[2]; - union DoublePun d[2]; - p = GetModrmRegisterXmmPointerRead16(m, rde); - d[0].i = Read64(p + 0); - d[1].i = Read64(p + 8); - n[0] = d[0].f; - n[1] = d[1].f; - Write32(XmmRexrReg(m, rde) + 0, n[0]); - Write32(XmmRexrReg(m, rde) + 4, n[1]); -} - -static void OpVdqWpdCvtpd2dq(struct Machine *m, uint32_t rde) { - uint8_t *p; - unsigned i; - int32_t n[2]; - union DoublePun d[2]; - p = GetModrmRegisterXmmPointerRead16(m, rde); - d[0].i = Read64(p + 0); - d[1].i = Read64(p + 8); - for (i = 0; i < 2; ++i) n[i] = SseRoundDouble(m, d[i].f); - Write32(XmmRexrReg(m, rde) + 0, n[0]); - Write32(XmmRexrReg(m, rde) + 4, n[1]); -} - -static void OpCvt(struct Machine *m, uint32_t rde, unsigned long op) { - switch (op | Rep(rde) | Osz(rde)) { - case kOpCvt0f2a + 0: - OpVpsQpiCvtpi2ps(m, rde); - break; - case kOpCvt0f2a + 1: - OpVpdQpiCvtpi2pd(m, rde); - break; - case kOpCvt0f2a + 2: - OpVsdEdqpCvtsi2sd(m, rde); - break; - case kOpCvt0f2a + 3: - OpVssEdqpCvtsi2ss(m, rde); - break; - case kOpCvtt0f2c + 0: - OpPpiWpsqCvttps2pi(m, rde); - break; - case kOpCvtt0f2c + 1: - OpPpiWpdCvttpd2pi(m, rde); - break; - case kOpCvtt0f2c + 2: - OpGdqpWsdCvttsd2si(m, rde); - break; - case kOpCvtt0f2c + 3: - OpGdqpWssCvttss2si(m, rde); - break; - case kOpCvt0f2d + 0: - OpPpiWpsqCvtps2pi(m, rde); - break; - case kOpCvt0f2d + 1: - OpPpiWpdCvtpd2pi(m, rde); - break; - case kOpCvt0f2d + 2: - OpGdqpWsdCvtsd2si(m, rde); - break; - case kOpCvt0f2d + 3: - OpGdqpWssCvtss2si(m, rde); - break; - case kOpCvt0f5a + 0: - OpVpdWpsCvtps2pd(m, rde); - break; - case kOpCvt0f5a + 1: - OpVpsWpdCvtpd2ps(m, rde); - break; - case kOpCvt0f5a + 2: - OpVssWsdCvtsd2ss(m, rde); - break; - case kOpCvt0f5a + 3: - OpVsdWssCvtss2sd(m, rde); - break; - case kOpCvt0f5b + 0: - OpVpsWdqCvtdq2ps(m, rde); - break; - case kOpCvt0f5b + 1: - OpVdqWpsCvtps2dq(m, rde); - break; - case kOpCvt0f5b + 3: - OpVdqWpsCvttps2dq(m, rde); - break; - case kOpCvt0fE6 + 1: - OpVdqWpdCvtpd2dq(m, rde); - break; - case kOpCvt0fE6 + 2: - OpVdqWpdCvttpd2dq(m, rde); - break; - case kOpCvt0fE6 + 3: - OpVpdWdqCvtdq2pd(m, rde); - break; - default: - OpUd(m, rde); - } -} - -void OpCvt0f2a(struct Machine *m, uint32_t rde) { - OpCvt(m, rde, kOpCvt0f2a); -} - -void OpCvtt0f2c(struct Machine *m, uint32_t rde) { - OpCvt(m, rde, kOpCvtt0f2c); -} - -void OpCvt0f2d(struct Machine *m, uint32_t rde) { - OpCvt(m, rde, kOpCvt0f2d); -} - -void OpCvt0f5a(struct Machine *m, uint32_t rde) { - OpCvt(m, rde, kOpCvt0f5a); -} - -void OpCvt0f5b(struct Machine *m, uint32_t rde) { - OpCvt(m, rde, kOpCvt0f5b); -} - -void OpCvt0fE6(struct Machine *m, uint32_t rde) { - OpCvt(m, rde, kOpCvt0fE6); -} diff --git a/tool/build/lib/cvt.h b/tool/build/lib/cvt.h deleted file mode 100644 index 9f5f1eec9..000000000 --- a/tool/build/lib/cvt.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_CVT_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_CVT_H_ -#include "tool/build/lib/machine.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -void OpCvt0f2a(struct Machine *, uint32_t); -void OpCvtt0f2c(struct Machine *, uint32_t); -void OpCvt0f2d(struct Machine *, uint32_t); -void OpCvt0f5a(struct Machine *, uint32_t); -void OpCvt0f5b(struct Machine *, uint32_t); -void OpCvt0fE6(struct Machine *, uint32_t); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_CVT_H_ */ diff --git a/tool/build/lib/debug.c b/tool/build/lib/debug.c deleted file mode 100644 index f6f6ab48d..000000000 --- a/tool/build/lib/debug.c +++ /dev/null @@ -1,47 +0,0 @@ -/*-*- 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/calls.h" -#include "libc/calls/struct/stat.h" -#include "libc/elf/elf.h" -#include "libc/log/check.h" -#include "libc/runtime/runtime.h" -#include "libc/sysv/consts/map.h" -#include "libc/sysv/consts/o.h" -#include "libc/sysv/consts/prot.h" -#include "libc/x/x.h" -#include "tool/build/lib/loader.h" - -void LoadDebugSymbols(struct Elf *elf) { - int fd; - size_t n; - void *elfmap; - struct stat st; - const char *path; - if (elf->ehdr && GetElfSymbolTable(elf->ehdr, elf->size, &n) && n) return; - DCHECK_NOTNULL(elf->prog); - if ((fd = open(xstrcat(elf->prog, ".dbg"), O_RDONLY)) != -1) { - if (fstat(fd, &st) != -1 && - (elfmap = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) != - MAP_FAILED) { - elf->ehdr = elfmap; - elf->size = st.st_size; - } - close(fd); - } -} diff --git a/tool/build/lib/dis.c b/tool/build/lib/dis.c deleted file mode 100644 index 3a4a0df89..000000000 --- a/tool/build/lib/dis.c +++ /dev/null @@ -1,296 +0,0 @@ -/*-*- 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/fmt/bing.internal.h" -#include "libc/fmt/itoa.h" -#include "libc/intrin/tpenc.h" -#include "libc/limits.h" -#include "libc/log/check.h" -#include "libc/mem/arraylist2.internal.h" -#include "libc/mem/mem.h" -#include "libc/str/str.h" -#include "third_party/xed/x86.h" -#include "tool/build/lib/demangle.h" -#include "tool/build/lib/dis.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/high.h" -#include "tool/build/lib/memory.h" -#include "tool/build/lib/modrm.h" - -#define ADDRLEN 8 -#define BYTELEN 11 -#define PFIXLEN 4 -#define NAMELEN 8 -#define CODELEN 40 -#define CODELIM 15 -#define DATALIM 8 -#define PIVOTOP pos_opcode - -static char *DisColumn(char *p2, char *p1, long need) { - char *p; - unsigned long have; - DCHECK_GE(p2, p1); - have = p2 - p1; - p = p2; - do { - *p++ = ' '; - } while (++have < need); - *p = '\0'; - return p; -} - -static char *DisOctets(char *p, const uint8_t *d, size_t n) { - size_t i; - for (i = 0; i < n; ++i) { - if (i) *p++ = ','; - *p++ = '0'; - *p++ = 'x'; - *p++ = "0123456789abcdef"[(d[i] & 0xf0) >> 4]; - *p++ = "0123456789abcdef"[(d[i] & 0x0f) >> 0]; - } - *p = '\0'; - return p; -} - -static char *DisByte(char *p, const uint8_t *d, size_t n) { - p = HighStart(p, g_high.keyword); - p = DisColumn(stpcpy(p, ".byte"), p, NAMELEN); - p = HighEnd(p); - p = DisOctets(p, d, n); - return p; -} - -static char *DisError(struct Dis *d, char *p) { - p = DisColumn(DisByte(p, d->xedd->bytes, MIN(15, d->xedd->length)), p, - CODELEN); - p = HighStart(p, g_high.comment); - *p++ = '#'; - *p++ = ' '; - p = stpcpy(p, IndexDoubleNulString(kXedErrorNames, d->xedd->op.error)); - p = HighEnd(p); - *p = '\0'; - return p; -} - -static char *DisAddr(struct Dis *d, char *p) { - int64_t x = d->addr; - if (0 <= x && x < 0x10fff0) { - return p + uint64toarray_fixed16(x, p, 24); - } else if (INT_MIN <= x && x <= INT_MAX) { - return p + uint64toarray_fixed16(x, p, 32); - } else { - return p + uint64toarray_fixed16(x, p, 48); - } -} - -static char *DisRaw(struct Dis *d, char *p) { - long i; - int plen; - if (0 <= d->addr && d->addr < 0x10fff0) { - plen = 2; - } else { - plen = PFIXLEN; - } - for (i = 0; i < plen - MIN(plen, d->xedd->op.PIVOTOP); ++i) { - *p++ = ' '; - *p++ = ' '; - } - for (i = 0; i < MIN(15, d->xedd->length); ++i) { - if (i == d->xedd->op.PIVOTOP) *p++ = ' '; - *p++ = "0123456789abcdef"[(d->xedd->bytes[i] & 0xf0) >> 4]; - *p++ = "0123456789abcdef"[(d->xedd->bytes[i] & 0x0f) >> 0]; - } - *p = '\0'; - return p; -} - -static char *DisCode(struct Dis *d, char *p) { - char optspecbuf[128]; - if (!d->xedd->op.error) { - return DisInst(d, p, DisSpec(d->xedd, optspecbuf)); - } else { - return DisError(d, p); - } -} - -static char *DisLineCode(struct Dis *d, char *p) { - int blen, plen; - if (0 <= d->addr && d->addr < 0x10fff0) { - plen = 2; - blen = 6; - } else { - blen = BYTELEN; - plen = PFIXLEN; - } - p = DisColumn(DisAddr(d, p), p, ADDRLEN); - p = DisColumn(DisRaw(d, p), p, plen * 2 + 1 + blen * 2); - p = DisCode(d, p); - return p; -} - -static char *DisLineData(struct Dis *d, char *p, const uint8_t *b, size_t n) { - size_t i; - uint64_t w; - p = DisColumn(DisAddr(d, p), p, ADDRLEN); - p = DisColumn(DisByte(p, b, n), p, 64); - p = HighStart(p, g_high.comment); - *p++ = '#'; - *p++ = ' '; - for (i = 0; i < n; ++i) { - w = _tpenc(bing(b[i], 0)); - do { - *p++ = w; - } while ((w >>= 8)); - } - p = HighEnd(p); - *p = '\0'; - return p; -} - -static char *DisLabel(struct Dis *d, char *p, const char *name) { - p = DisColumn(DisAddr(d, p), p, ADDRLEN); - p = HighStart(p, g_high.label); - p = Demangle(p, name, DIS_MAX_SYMBOL_LENGTH); - p = HighEnd(p); - *p++ = ':'; - *p = '\0'; - return p; -} - -long DisFind(struct Dis *d, int64_t addr) { - int l, r, m, i; - l = 0; - r = d->ops.i - 1; - while (l <= r) { - m = (l + r) >> 1; - if (d->ops.p[m].addr < addr) { - l = m + 1; - } else if (d->ops.p[m].addr > addr) { - r = m - 1; - } else { - return m; - } - } - return -1; -} - -static long DisAppendOpLines(struct Dis *d, struct Machine *m, int64_t addr) { - void *r; - int64_t ip; - unsigned k; - struct DisOp op; - long i, n, symbol; - uint8_t *p, b[15]; - n = 15; - ip = addr - Read64(m->cs); - if ((symbol = DisFindSym(d, ip)) != -1) { - if (d->syms.p[symbol].addr <= ip && - ip < d->syms.p[symbol].addr + d->syms.p[symbol].size) { - n = d->syms.p[symbol].size - (ip - d->syms.p[symbol].addr); - } - if (ip == d->syms.p[symbol].addr && d->syms.p[symbol].name) { - op.addr = addr; - op.size = 0; - op.active = true; - d->addr = addr; - DisLabel(d, d->buf, d->syms.stab + d->syms.p[symbol].name); - if (!(op.s = strdup(d->buf))) return -1; - APPEND(&d->ops.p, &d->ops.i, &d->ops.n, &op); - } - } - n = MAX(1, MIN(15, n)); - if (!(r = FindReal(m, addr))) return -1; - k = 0x1000 - (addr & 0xfff); - if (n <= k) { - p = r; - } else { - p = b; - memcpy(b, r, k); - if ((r = FindReal(m, addr + k))) { - memcpy(b + k, r, n - k); - } else { - n = k; - } - } - xed_decoded_inst_zero_set_mode(d->xedd, m->mode); - xed_instruction_length_decode(d->xedd, p, n); - d->xedd->op.rde = EncodeRde(d->xedd); - n = d->xedd->op.error ? 1 : d->xedd->length; - op.addr = addr; - op.size = n; - op.active = true; - op.s = NULL; - APPEND(&d->ops.p, &d->ops.i, &d->ops.n, &op); - return n; -} - -long Dis(struct Dis *d, struct Machine *m, uint64_t addr, uint64_t ip, - int lines) { - int64_t i, j, symbol; - DisFreeOps(&d->ops); - if ((symbol = DisFindSym(d, addr)) != -1 && - (d->syms.p[symbol].addr < addr && - addr < d->syms.p[symbol].addr + d->syms.p[symbol].size)) { - for (i = d->syms.p[symbol].addr; i < addr; i += j) { - if ((j = DisAppendOpLines(d, m, i)) == -1) return -1; - } - } - for (i = 0; i < lines; ++i, addr += j) { - if ((j = DisAppendOpLines(d, m, addr)) == -1) return -1; - } - return 0; -} - -const char *DisGetLine(struct Dis *d, struct Machine *m, size_t i) { - void *r[2]; - uint8_t b[15]; - if (i >= d->ops.i) return ""; - if (d->ops.p[i].s) return d->ops.p[i].s; - DCHECK_LE(d->ops.p[i].size, 15); - xed_decoded_inst_zero_set_mode(d->xedd, m->mode); - xed_instruction_length_decode( - d->xedd, AccessRam(m, d->ops.p[i].addr, d->ops.p[i].size, r, b, true), - d->ops.p[i].size); - d->xedd->op.rde = EncodeRde(d->xedd); - d->m = m; - d->addr = d->ops.p[i].addr; - CHECK_LT(DisLineCode(d, d->buf) - d->buf, sizeof(d->buf)); - return d->buf; -} - -void DisFreeOp(struct DisOp *o) { - free(o->s); -} - -void DisFreeOps(struct DisOps *ops) { - long i; - for (i = 0; i < ops->i; ++i) { - DisFreeOp(&ops->p[i]); - } - free(ops->p); - bzero(ops, sizeof(*ops)); -} - -void DisFree(struct Dis *d) { - long i; - DisFreeOps(&d->ops); - free(d->edges.p); - free(d->loads.p); - free(d->syms.p); - bzero(d, sizeof(*d)); -} diff --git a/tool/build/lib/dis.h b/tool/build/lib/dis.h deleted file mode 100644 index 6eb7aad5c..000000000 --- a/tool/build/lib/dis.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_DIS_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_DIS_H_ -#include "third_party/xed/x86.h" -#include "tool/build/lib/loader.h" -#include "tool/build/lib/machine.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -#define DIS_MAX_SYMBOL_LENGTH 32 - -struct Dis { - struct DisOps { - size_t i, n; - struct DisOp { - int64_t addr; - uint8_t size; - bool active; - char *s; - } * p; - } ops; - struct DisLoads { - size_t i, n; - struct DisLoad { - int64_t addr; - uint64_t size; - bool istext; - } * p; - } loads; - struct DisSyms { - size_t i, n; - struct DisSym { - int64_t addr; - int unique; - int size; - int name; - char rank; - bool iscode; - bool isabs; - } * p; - const char *stab; - } syms; - struct DisEdges { - size_t i, n; - struct DisEdge { - int64_t src; - int64_t dst; - } * p; - } edges; - struct XedDecodedInst xedd[1]; - struct Machine *m; /* for the segment registers */ - uint64_t addr; /* current effective address */ - char buf[512]; -}; - -extern bool g_disisprog_disable; - -long Dis(struct Dis *, struct Machine *, uint64_t, uint64_t, int); -long DisFind(struct Dis *, int64_t); -void DisFree(struct Dis *); -void DisFreeOp(struct DisOp *); -void DisFreeOps(struct DisOps *); -void DisLoadElf(struct Dis *, struct Elf *); -long DisFindSym(struct Dis *, int64_t); -long DisFindSymByName(struct Dis *, const char *); -bool DisIsText(struct Dis *, int64_t); -bool DisIsProg(struct Dis *, int64_t); -char *DisInst(struct Dis *, char *, const char *); -char *DisArg(struct Dis *, char *, const char *); -const char *DisSpec(struct XedDecodedInst *, char *); -const char *DisGetLine(struct Dis *, struct Machine *, size_t); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_DIS_H_ */ diff --git a/tool/build/lib/disarg.c b/tool/build/lib/disarg.c deleted file mode 100644 index 55e44efb8..000000000 --- a/tool/build/lib/disarg.c +++ /dev/null @@ -1,747 +0,0 @@ -/*-*- 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/fmt/itoa.h" -#include "libc/intrin/bits.h" -#include "libc/limits.h" -#include "libc/log/check.h" -#include "libc/macros.internal.h" -#include "libc/str/str.h" -#include "tool/build/lib/demangle.h" -#include "tool/build/lib/dis.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/high.h" -#include "tool/build/lib/modrm.h" - -static const char kRiz[2][4] = {"eiz", "riz"}; -static const char kRip[2][4] = {"eip", "rip"}; -static const char kSka[4][4] = {"", ",2", ",4", ",8"}; -static const char kSeg[8][3] = {"es", "cs", "ss", "ds", "fs", "gs"}; -static const char kCtl[8][4] = {"cr0", "wut", "cr2", "cr3", - "cr4", "wut", "wut", "wut"}; - -static const char kBreg[2][2][8][5] = { - {{"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"}, - {"al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil"}}, - {{"wut", "wut", "wut", "wut", "wut", "wut", "wut", "wut"}, - {"r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"}}, -}; - -static const char kGreg[2][2][2][8][5] = { - {{{"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"}, - {"r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"}}, - {{"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"}, - {"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}}}, - {{{"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"}, - {"r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"}}, - {{"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"}, - {"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}}}, -}; - -static int64_t RipRelative(struct Dis *d, int64_t i) { - return d->addr + d->xedd->length + i; -} - -static int64_t ZeroExtend(uint32_t rde, int64_t i) { - switch (Mode(rde)) { - case XED_MODE_REAL: - return i & 0xffff; - case XED_MODE_LEGACY: - return i & 0xffffffff; - default: - return i; - } -} - -static int64_t Unrelative(uint32_t rde, int64_t i) { - switch (Eamode(rde)) { - case XED_MODE_REAL: - return i & 0xffff; - case XED_MODE_LEGACY: - return i & 0xffffffff; - default: - return i; - } -} - -static int64_t GetSeg(struct Dis *d, uint32_t rde, unsigned char *s) { - switch (Sego(rde) ? Sego(rde) : d->xedd->op.hint) { - default: - return Read64(s); - case 1: - return Read64(d->m->es); - case 2: - return Read64(d->m->cs); - case 3: - return Read64(d->m->ss); - case 4: - return Read64(d->m->ds); - } -} - -static const char *GetAddrReg(struct Dis *d, uint32_t rde, uint8_t x, - uint8_t r) { - return kGreg[Eamode(rde) == XED_MODE_REAL][Eamode(rde) == XED_MODE_LONG] - [x & 1][r & 7]; -} - -static char *DisRegister(char *p, const char *s) { - p = HighStart(p, g_high.reg); - *p++ = '%'; - p = stpcpy(p, s); - p = HighEnd(p); - return p; -} - -static char *DisComment(char *p, const char *s) { - p = HighStart(p, g_high.comment); - p = stpcpy(p, s); - p = HighEnd(p); - return p; -} - -static char *DisRegisterByte(struct Dis *d, uint32_t rde, char *p, bool g, - int r) { - return DisRegister(p, kBreg[g][Rex(rde)][r]); -} - -static char *DisRegisterWord(struct Dis *d, uint32_t rde, char *p, bool g, - int r) { - return DisRegister(p, kGreg[Osz(rde)][Rexw(rde)][g][r]); -} - -static char *DisInt(char *p, int64_t x) { - if (-15 <= x && x <= 15) { - p = FormatInt64(p, x); - } else if (x == INT64_MIN) { - p = stpcpy(p, "-0x"); - p += uint64toarray_radix16(INT64_MIN, p); - } else if (x < 0 && -x < 0xFFFFFFFF) { - p = stpcpy(p, "-0x"); - p += uint64toarray_radix16(-x, p); - } else { - p = stpcpy(p, "0x"); - p += uint64toarray_radix16(x, p); - } - return p; -} - -static char *DisSymImpl(struct Dis *d, char *p, int64_t x, long sym) { - int64_t addend; - const char *name; - addend = x - d->syms.p[sym].addr; - name = d->syms.stab + d->syms.p[sym].name; - p = Demangle(p, name, DIS_MAX_SYMBOL_LENGTH); - if (addend) { - *p++ = '+'; - p = DisInt(p, addend); - } - return p; -} - -static char *DisSym(struct Dis *d, char *p, int64_t value, int64_t addr) { - long sym; - if ((sym = DisFindSym(d, addr)) != -1 && d->syms.p[sym].name) { - return DisSymImpl(d, p, addr, sym); - } else { - return DisInt(p, value); - } -} - -static char *DisSymLiteral(struct Dis *d, uint32_t rde, char *p, uint64_t addr, - uint64_t ip) { - *p++ = '$'; - p = HighStart(p, g_high.literal); - p = DisSym(d, p, addr, addr); - p = HighEnd(p); - return p; -} - -static char *DisGvqp(struct Dis *d, uint32_t rde, char *p) { - return DisRegisterWord(d, rde, p, Rexr(rde), ModrmReg(rde)); -} - -static char *DisGdqp(struct Dis *d, uint32_t rde, char *p) { - return DisRegister(p, kGreg[0][Rexw(rde)][Rexr(rde)][ModrmReg(rde)]); -} - -static char *DisGb(struct Dis *d, uint32_t rde, char *p) { - return DisRegisterByte(d, rde, p, Rexr(rde), ModrmReg(rde)); -} - -static char *DisSego(struct Dis *d, uint32_t rde, char *p) { - int seg; - seg = Sego(rde) ? Sego(rde) : d->xedd->op.hint; - if (seg) { - p = DisRegister(p, kSeg[seg - 1]); - *p++ = ':'; - } - return p; -} - -static bool IsRealModrmAbsolute(uint32_t rde) { - return Eamode(rde) == XED_MODE_REAL && ModrmRm(rde) == 6 && !ModrmMod(rde); -} - -static char *DisDisp(struct Dis *d, uint32_t rde, char *p) { - bool rela; - int64_t disp; - if (ModrmMod(rde) == 0b01 || ModrmMod(rde) == 0b10 || IsRipRelative(rde) || - IsRealModrmAbsolute(rde) || - (Eamode(rde) != XED_MODE_REAL && ModrmMod(rde) == 0b00 && - ModrmRm(rde) == 0b100 && SibBase(d->xedd) == 0b101)) { - disp = d->xedd->op.disp; - if (IsRipRelative(rde)) { - if (Mode(rde) == XED_MODE_LONG) { - disp = RipRelative(d, disp); - rela = true; - } else { - disp = Unrelative(rde, disp); - rela = false; - } - } else if (IsRealModrmAbsolute(rde)) { - disp = Unrelative(rde, disp); - rela = false; - } else { - rela = true; - } - p = DisSym(d, p, disp, disp); - } - return p; -} - -static char *DisBis(struct Dis *d, uint32_t rde, char *p) { - const char *base, *index, *scale; - base = index = scale = NULL; - if (Eamode(rde) != XED_MODE_REAL) { - if (!SibExists(rde)) { - DCHECK(!d->xedd->op.has_sib); - if (IsRipRelative(rde)) { - if (Mode(rde) == XED_MODE_LONG) { - base = kRip[Eamode(rde) == XED_MODE_LONG]; - } - } else { - base = GetAddrReg(d, rde, Rexb(rde), ModrmRm(rde)); - } - } else if (!SibIsAbsolute(d->xedd, rde)) { - if (SibHasBase(d->xedd, rde)) { - base = GetAddrReg(d, rde, Rexb(rde), SibBase(d->xedd)); - } - if (SibHasIndex(d->xedd)) { - index = GetAddrReg(d, rde, Rexx(d->xedd), SibIndex(d->xedd)); - } else if (d->xedd->op.scale) { - index = kRiz[Eamode(rde) == XED_MODE_LONG]; - } - scale = kSka[d->xedd->op.scale]; - } - } else { - switch (ModrmRm(rde)) { - case 0: - base = "bx"; - index = "si"; - break; - case 1: - base = "bx"; - index = "di"; - break; - case 2: - base = "bp"; - index = "si"; - break; - case 3: - base = "bp"; - index = "di"; - break; - case 4: - base = "si"; - break; - case 5: - base = "di"; - break; - case 6: - if (ModrmMod(rde)) base = "bp"; - break; - case 7: - base = "bx"; - break; - default: - __builtin_unreachable(); - } - } - if (base || index) { - *p++ = '('; - if (base) { - p = DisRegister(p, base); - } - if (index) { - *p++ = ','; - p = DisRegister(p, index); - if (scale) { - p = stpcpy(p, scale); - } - } - *p++ = ')'; - } - *p = '\0'; - return p; -} - -static char *DisM(struct Dis *d, uint32_t rde, char *p) { - p = DisSego(d, rde, p); - p = DisDisp(d, rde, p); - p = DisBis(d, rde, p); - return p; -} - -static char *DisRegMem(struct Dis *d, uint32_t rde, char *p, - char *f(struct Dis *, uint32_t, char *)) { - if (IsModrmRegister(rde)) { - return f(d, rde, p); - } else { - return DisM(d, rde, p); - } -} - -static dontinline char *DisE(struct Dis *d, uint32_t rde, char *p, - char *f(struct Dis *, uint32_t, char *, bool, - int)) { - if (IsModrmRegister(rde)) { - return f(d, rde, p, Rexb(rde), ModrmRm(rde)); - } else { - return DisM(d, rde, p); - } -} - -static char *DisEb(struct Dis *d, uint32_t rde, char *p) { - return DisE(d, rde, p, DisRegisterByte); -} - -static char *DisEvqp(struct Dis *d, uint32_t rde, char *p) { - return DisE(d, rde, p, DisRegisterWord); -} - -static char *DisRv(struct Dis *d, uint32_t rde, char *p) { - return DisRegister(p, kGreg[Osz(rde)][0][Rexb(rde)][ModrmRm(rde)]); -} - -static char *DisRvqp(struct Dis *d, uint32_t rde, char *p) { - return DisRegister(p, kGreg[Osz(rde)][Rexw(rde)][Rexb(rde)][ModrmRm(rde)]); -} - -static char *DisRdqp(struct Dis *d, uint32_t rde, char *p) { - return DisRegister(p, kGreg[0][Rexw(rde)][Rexb(rde)][ModrmRm(rde)]); -} - -static char *DisEdqp(struct Dis *d, uint32_t rde, char *p) { - return DisRegMem(d, rde, p, DisRdqp); -} - -static char *DisEv(struct Dis *d, uint32_t rde, char *p) { - return DisRegMem(d, rde, p, DisRv); -} - -static char *DisGvq(struct Dis *d, uint32_t rde, char *p, int r) { - const char *s; - if (Mode(rde) == XED_MODE_LONG) { - s = kGreg[Osz(rde)][!Osz(rde)][Rexb(rde)][r]; - } else { - s = kGreg[Osz(rde)][0][Rexb(rde)][r]; - } - return DisRegister(p, s); -} - -static char *DisZvq(struct Dis *d, uint32_t rde, char *p) { - return DisGvq(d, rde, p, ModrmSrm(rde)); -} - -static char *DisEvqReg(struct Dis *d, uint32_t rde, char *p) { - return DisGvq(d, rde, p, ModrmRm(rde)); -} - -static char *DisEvq(struct Dis *d, uint32_t rde, char *p) { - return DisRegMem(d, rde, p, DisEvqReg); -} - -static char *DisEdReg(struct Dis *d, uint32_t rde, char *p) { - return DisRegister(p, kGreg[0][0][Rexb(rde)][ModrmRm(rde)]); -} - -static char *DisEd(struct Dis *d, uint32_t rde, char *p) { - return DisRegMem(d, rde, p, DisEdReg); -} - -static char *DisEqReg(struct Dis *d, uint32_t rde, char *p) { - const char *r; - if (Mode(rde) == XED_MODE_LONG) { - r = kGreg[0][1][Rexb(rde)][ModrmRm(rde)]; - } else { - r = kGreg[Osz(rde)][0][Rexb(rde)][ModrmRm(rde)]; - } - return DisRegister(p, r); -} - -static char *DisEq(struct Dis *d, uint32_t rde, char *p) { - return DisRegMem(d, rde, p, DisEqReg); -} - -static char *DisZvqp(struct Dis *d, uint32_t rde, char *p) { - return DisRegisterWord(d, rde, p, Rexb(rde), ModrmSrm(rde)); -} - -static char *DisZb(struct Dis *d, uint32_t rde, char *p) { - return DisRegisterByte(d, rde, p, Rexb(rde), ModrmSrm(rde)); -} - -static char *DisEax(struct Dis *d, uint32_t rde, char *p) { - return DisRegister(p, kGreg[Osz(rde)][0][0][0]); -} - -static char *DisRax(struct Dis *d, uint32_t rde, char *p) { - return DisRegister(p, kGreg[Osz(rde)][Rexw(rde)][0][0]); -} - -static char *DisRdx(struct Dis *d, uint32_t rde, char *p) { - return DisRegister(p, kGreg[Osz(rde)][Rexw(rde)][0][2]); -} - -static char *DisPort(struct Dis *d, uint32_t rde, char *p) { - *p++ = '('; - p = DisRegister(p, kGreg[1][0][0][2]); - *p++ = ')'; - *p = '\0'; - return p; -} - -static char *DisCd(struct Dis *d, uint32_t rde, char *p) { - return DisRegister(p, kCtl[ModrmReg(rde)]); -} - -static char *DisHd(struct Dis *d, uint32_t rde, char *p) { - return DisRegister(p, kGreg[0][Mode(rde) == XED_MODE_LONG][0][ModrmRm(rde)]); -} - -static char *DisImm(struct Dis *d, uint32_t rde, char *p) { - return DisSymLiteral(d, rde, p, d->xedd->op.uimm0, - ZeroExtend(rde, d->xedd->op.uimm0)); -} - -static char *DisRvds(struct Dis *d, uint32_t rde, char *p) { - return DisSymLiteral(d, rde, p, d->xedd->op.disp, d->xedd->op.disp); -} - -static char *DisKpvds(struct Dis *d, uint32_t rde, char *p, uint64_t x) { - *p++ = '$'; - p = HighStart(p, g_high.literal); - p = DisInt(p, x); - p = HighEnd(p); - return p; -} - -static char *DisKvds(struct Dis *d, uint32_t rde, char *p) { - return DisKpvds(d, rde, p, d->xedd->op.uimm0); -} - -static char *DisPvds(struct Dis *d, uint32_t rde, char *p) { - return DisKpvds(d, rde, p, - d->xedd->op.disp & (Osz(rde) ? 0xffff : 0xffffffff)); -} - -static char *DisOne(struct Dis *d, uint32_t rde, char *p) { - *p++ = '$'; - p = HighStart(p, g_high.literal); - p = stpcpy(p, "1"); - p = HighEnd(p); - return p; -} - -static char *DisJbs(struct Dis *d, uint32_t rde, char *p) { - if (d->xedd->op.disp > 0) *p++ = '+'; - p = FormatInt64(p, d->xedd->op.disp); - return p; -} - -static char *DisJb(struct Dis *d, uint32_t rde, char *p) { - if (d->xedd->op.disp > 0) *p++ = '+'; - p = FormatUint32(p, d->xedd->op.disp & 0xff); - return p; -} - -static char *DisJvds(struct Dis *d, uint32_t rde, char *p) { - return DisSym(d, p, RipRelative(d, d->xedd->op.disp), - RipRelative(d, d->xedd->op.disp) - Read64(d->m->cs)); -} - -static char *DisAbs(struct Dis *d, uint32_t rde, char *p) { - return DisSym(d, p, d->xedd->op.disp, d->xedd->op.disp); -} - -static char *DisSw(struct Dis *d, uint32_t rde, char *p) { - if (kSeg[ModrmReg(rde)][0]) p = DisRegister(p, kSeg[ModrmReg(rde)]); - return p; -} - -static char *DisSpecialAddr(struct Dis *d, uint32_t rde, char *p, int r) { - *p++ = '('; - p = DisRegister(p, GetAddrReg(d, rde, 0, r)); - *p++ = ')'; - *p = '\0'; - return p; -} - -static char *DisY(struct Dis *d, uint32_t rde, char *p) { - return DisSpecialAddr(d, rde, p, 7); // es:di -} - -static char *DisX(struct Dis *d, uint32_t rde, char *p) { - p = DisSego(d, rde, p); - return DisSpecialAddr(d, rde, p, 6); // ds:si -} - -static char *DisBBb(struct Dis *d, uint32_t rde, char *p) { - p = DisSego(d, rde, p); - return DisSpecialAddr(d, rde, p, 3); // ds:bx -} - -static char *DisXmm(struct Dis *d, uint32_t rde, char *p, const char *s, - int reg) { - p = HighStart(p, g_high.reg); - *p++ = '%'; - p = stpcpy(p, s); - p = FormatUint32(p, reg); - p = HighEnd(p); - return p; -} - -static char *DisNq(struct Dis *d, uint32_t rde, char *p) { - return DisXmm(d, rde, p, "mm", ModrmRm(rde)); -} - -static char *DisPq(struct Dis *d, uint32_t rde, char *p) { - return DisXmm(d, rde, p, "mm", ModrmReg(rde)); -} - -static char *DisUq(struct Dis *d, uint32_t rde, char *p) { - return DisXmm(d, rde, p, "xmm", RexbRm(rde)); -} - -static char *DisUdq(struct Dis *d, uint32_t rde, char *p) { - return DisXmm(d, rde, p, "xmm", RexbRm(rde)); -} - -static char *DisVdq(struct Dis *d, uint32_t rde, char *p) { - return DisXmm(d, rde, p, "xmm", RexrReg(rde)); -} - -static char *DisQq(struct Dis *d, uint32_t rde, char *p) { - return DisRegMem(d, rde, p, DisNq); -} - -static char *DisEst(struct Dis *d, uint32_t rde, char *p) { - p = DisRegister(p, "st"); - if (ModrmRm(rde) != 0) { - *p++ = '('; - *p++ = '0' + ModrmRm(rde); - *p++ = ')'; - *p = '\0'; - } - return p; -} - -static char *DisEst1(struct Dis *d, uint32_t rde, char *p) { - if (ModrmRm(rde) != 1) { - p = DisEst(d, rde, p); - } else { - *p = '\0'; - } - return p; -} - -static char *DisEssr(struct Dis *d, uint32_t rde, char *p) { - return DisRegMem(d, rde, p, DisEst); -} - -static char *DisWps(struct Dis *d, uint32_t rde, char *p) { - return DisRegMem(d, rde, p, DisUdq); -} - -#define DisEdr DisM -#define DisEqp DisEq -#define DisEsr DisM -#define DisGv DisGvqp -#define DisIb DisImm -#define DisIbs DisImm -#define DisIbss DisImm -#define DisIvds DisImm -#define DisIvqp DisImm -#define DisIvs DisImm -#define DisIw DisImm -#define DisMdi DisM -#define DisMdq DisM -#define DisMdqp DisM -#define DisMdr DisM -#define DisMe DisM -#define DisMer DisM -#define DisMp DisM -#define DisMps DisM -#define DisMq DisM -#define DisMqi DisM -#define DisMs DisM -#define DisMsr DisEssr -#define DisMw DisM -#define DisMwi DisM -#define DisOb DisAbs -#define DisOvqp DisAbs -#define DisPpi DisPq -#define DisQpi DisQq -#define DisVpd DisVdq -#define DisVps DisVdq -#define DisVq DisVdq -#define DisVsd DisVdq -#define DisVss DisVdq -#define DisWdq DisWps -#define DisWpd DisWps -#define DisWpsq DisWps -#define DisWq DisWps -#define DisWsd DisWps -#define DisWss DisWps -#define DisXb DisX -#define DisXv DisX -#define DisXvqp DisX -#define DisYb DisY -#define DisYv DisY -#define DisYvqp DisY -#define DisZv DisZvqp - -static const struct DisArg { - char s[8]; - char *(*f)(struct Dis *, uint32_t, char *); -} kDisArgs[] = /* <sorted> */ { - {"$1", DisOne}, // - {"%Cd", DisCd}, // - {"%Gb", DisGb}, // - {"%Gdqp", DisGdqp}, // - {"%Gv", DisGv}, // - {"%Gvqp", DisGvqp}, // - {"%Hd", DisHd}, // - {"%Nq", DisNq}, // - {"%Ppi", DisPpi}, // - {"%Pq", DisPq}, // - {"%Rdqp", DisRdqp}, // - {"%Rvqp", DisRvqp}, // - {"%Sw", DisSw}, // - {"%Udq", DisUdq}, // - {"%Uq", DisUq}, // - {"%Vdq", DisVdq}, // - {"%Vpd", DisVpd}, // - {"%Vps", DisVps}, // - {"%Vq", DisVq}, // - {"%Vsd", DisVsd}, // - {"%Vss", DisVss}, // - {"%Zb", DisZb}, // - {"%Zv", DisZv}, // - {"%Zvq", DisZvq}, // - {"%Zvqp", DisZvqp}, // - {"%eAX", DisEax}, // - {"%rAX", DisRax}, // - {"%rDX", DisRdx}, // - {"BBb", DisBBb}, // - {"DX", DisPort}, // - {"EST", DisEst}, // - {"EST1", DisEst1}, // - {"ESsr", DisEssr}, // - {"Eb", DisEb}, // - {"Ed", DisEd}, // - {"Edqp", DisEdqp}, // - {"Edr", DisEdr}, // - {"Eq", DisEq}, // - {"Eqp", DisEqp}, // - {"Esr", DisEsr}, // - {"Ev", DisEv}, // - {"Evq", DisEvq}, // - {"Evqp", DisEvqp}, // - {"Ew", DisEvqp}, // - {"Ib", DisIb}, // - {"Ibs", DisIbs}, // - {"Ibss", DisIbss}, // - {"Ivds", DisIvds}, // - {"Ivqp", DisIvqp}, // - {"Ivs", DisIvs}, // - {"Iw", DisIw}, // - {"Jb", DisJb}, // - {"Jbs", DisJbs}, // - {"Jvds", DisJvds}, // - {"Kvds", DisKvds}, // - {"M", DisM}, // - {"Mdi", DisMdi}, // - {"Mdq", DisMdq}, // - {"Mdqp", DisMdqp}, // - {"Mdr", DisMdr}, // - {"Me", DisMe}, // - {"Mer", DisMer}, // - {"Mp", DisMp}, // - {"Mps", DisMps}, // - {"Mq", DisMq}, // - {"Mqi", DisMqi}, // - {"Ms", DisMs}, // - {"Msr", DisMsr}, // - {"Mw", DisMw}, // - {"Mwi", DisMwi}, // - {"Ob", DisOb}, // - {"Ovqp", DisOvqp}, // - {"Pvds", DisPvds}, // - {"Qpi", DisQpi}, // - {"Qq", DisQq}, // - {"Rvds", DisRvds}, // - {"Wdq", DisWdq}, // - {"Wpd", DisWpd}, // - {"Wps", DisWps}, // - {"Wpsq", DisWpsq}, // - {"Wq", DisWq}, // - {"Wsd", DisWsd}, // - {"Wss", DisWss}, // - {"Xb", DisXb}, // - {"Xv", DisXv}, // - {"Xvqp", DisXvqp}, // - {"Yb", DisYb}, // - {"Yv", DisYv}, // - {"Yvqp", DisYvqp}, // -}; - -char *DisArg(struct Dis *d, char *p, const char *s) { - char k[8]; - int m, l, r; - l = 0; - r = ARRAYLEN(kDisArgs) - 1; - strncpy(k, s, 8); - while (l <= r) { - m = (l + r) >> 1; - if (READ64BE(kDisArgs[m].s) < READ64BE(k)) { - l = m + 1; - } else if (READ64BE(kDisArgs[m].s) > READ64BE(k)) { - r = m - 1; - } else { - return kDisArgs[m].f(d, d->xedd->op.rde, p); - } - } - if (*s == '%') { - p = DisRegister(p, s + 1); - } else { - p = stpcpy(p, s); - } - return p; -} diff --git a/tool/build/lib/diself.c b/tool/build/lib/diself.c deleted file mode 100644 index 9e81dd023..000000000 --- a/tool/build/lib/diself.c +++ /dev/null @@ -1,220 +0,0 @@ -/*-*- 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/elf/elf.h" -#include "libc/elf/struct/sym.h" -#include "libc/log/check.h" -#include "libc/log/log.h" -#include "libc/macros.internal.h" -#include "libc/mem/alg.h" -#include "libc/mem/mem.h" -#include "libc/runtime/memtrack.internal.h" -#include "libc/str/str.h" -#include "tool/build/lib/dis.h" - -bool g_disisprog_disable; - -static int DisSymCompare(const struct DisSym *a, const struct DisSym *b) { - if (a->addr != b->addr) { - if (a->addr < b->addr) return -1; - if (a->addr > b->addr) return +1; - } - if (a->rank != b->rank) { - if (a->rank > b->rank) return -1; - if (a->rank < b->rank) return +1; - } - if (a->unique != b->unique) { - if (a->unique < b->unique) return -1; - if (a->unique > b->unique) return +1; - } - return 0; -} - -static void DisLoadElfLoads(struct Dis *d, struct Elf *elf) { - long i, j, n; - int64_t addr; - uint64_t size; - Elf64_Phdr *phdr; - j = 0; - n = elf->ehdr->e_phnum; - if (d->loads.n < n) { - d->loads.n = n; - d->loads.p = realloc(d->loads.p, d->loads.n * sizeof(*d->loads.p)); - CHECK_NOTNULL(d->loads.p); - } - for (i = 0; i < n; ++i) { - phdr = GetElfSegmentHeaderAddress(elf->ehdr, elf->size, i); - if (phdr->p_type != PT_LOAD) continue; - d->loads.p[j].addr = phdr->p_vaddr; - d->loads.p[j].size = phdr->p_memsz; - d->loads.p[j].istext = (phdr->p_flags & PF_X) == PF_X; - ++j; - } - d->loads.i = j; -} - -static void DisLoadElfSyms(struct Dis *d, struct Elf *elf) { - size_t i, j, n; - int64_t stablen; - const Elf64_Sym *st, *sym; - bool isabs, iscode, isweak, islocal, ishidden, isprotected, isfunc, isobject; - j = 0; - if ((d->syms.stab = GetElfStringTable(elf->ehdr, elf->size)) && - (st = GetElfSymbolTable(elf->ehdr, elf->size, &n))) { - stablen = (intptr_t)elf->ehdr + elf->size - (intptr_t)d->syms.stab; - if (d->syms.n < n) { - d->syms.n = n; - d->syms.p = realloc(d->syms.p, d->syms.n * sizeof(*d->syms.p)); - CHECK_NOTNULL(d->syms.p); - } - for (i = 0; i < n; ++i) { - if (ELF64_ST_TYPE(st[i].st_info) == STT_SECTION || - ELF64_ST_TYPE(st[i].st_info) == STT_FILE || !st[i].st_name || - _startswith(d->syms.stab + st[i].st_name, "v_") || - !(0 <= st[i].st_name && st[i].st_name < stablen) || !st[i].st_value || - !IsLegalPointer(st[i].st_value)) { - continue; - } - isabs = st[i].st_shndx == SHN_ABS; - isweak = ELF64_ST_BIND(st[i].st_info) == STB_WEAK; - islocal = ELF64_ST_BIND(st[i].st_info) == STB_LOCAL; - ishidden = st[i].st_other == STV_HIDDEN; - isprotected = st[i].st_other == STV_PROTECTED; - isfunc = ELF64_ST_TYPE(st[i].st_info) == STT_FUNC; - isobject = ELF64_ST_TYPE(st[i].st_info) == STT_OBJECT; - d->syms.p[j].unique = i; - d->syms.p[j].size = st[i].st_size; - d->syms.p[j].name = st[i].st_name; - CHECK_GE(st[i].st_value, 0); - d->syms.p[j].addr = st[i].st_value; - d->syms.p[j].rank = - -islocal + -isweak + -isabs + isprotected + isobject + isfunc; - d->syms.p[j].iscode = DisIsText(d, st[i].st_value) ? !isobject : isfunc; - d->syms.p[j].isabs = isabs; - ++j; - } - } - d->syms.i = j; -} - -static void DisSortSyms(struct Dis *d) { - size_t i, j; - qsort(d->syms.p, d->syms.i, sizeof(struct DisSym), (void *)DisSymCompare); - for (i = 0; i < d->syms.i; ++i) { - if (!strcmp("_end", d->syms.stab + d->syms.p[i].name)) { - d->syms.i = i; - break; - } - } -} - -static void DisCanonizeSyms(struct Dis *d) { - int64_t i, j, a; - if (d->syms.i) { - i = 1; - j = 1; - a = d->syms.p[0].addr; - do { - if (d->syms.p[j].addr > a) { - a = d->syms.p[j].addr; - if (j > i) { - d->syms.p[i] = d->syms.p[j]; - } - ++i; - } - ++j; - } while (j < d->syms.i); - d->syms.p = realloc(d->syms.p, sizeof(*d->syms.p) * i); - d->syms.i = i; - d->syms.n = i; - } - for (i = 0; i < d->syms.i; ++i) { - DEBUGF("%012lx-%012lx %s", d->syms.p[i].addr, - d->syms.p[i].addr + (d->syms.p[i].size ? d->syms.p[i].size - 1 : 0), - d->syms.stab + d->syms.p[i].name); - } -} - -bool DisIsProg(struct Dis *d, int64_t addr) { - long i; - if (g_disisprog_disable) return true; - for (i = 0; i < d->loads.i; ++i) { - if (addr >= d->loads.p[i].addr && - addr < d->loads.p[i].addr + d->loads.p[i].size) { - return true; - } - } - return false; -} - -bool DisIsText(struct Dis *d, int64_t addr) { - long i; - for (i = 0; i < d->loads.i; ++i) { - if (addr >= d->loads.p[i].addr && - addr < d->loads.p[i].addr + d->loads.p[i].size) { - return d->loads.p[i].istext; - } - } - return false; -} - -long DisFindSym(struct Dis *d, int64_t addr) { - long l, r, m, n; - if (DisIsProg(d, addr)) { - l = 0; - r = d->syms.i; - while (l < r) { - m = (l + r) >> 1; - if (d->syms.p[m].addr > addr) { - r = m; - } else { - l = m + 1; - } - } - // TODO(jart): This was <256 but that broke SectorLISP debugging - // Why did the Cosmo binbase bootloader need this? - if (r && d->syms.p[r - 1].addr < 32) { - return -1; - } - if (r && (addr == d->syms.p[r - 1].addr || - (addr > d->syms.p[r - 1].addr && - (addr <= d->syms.p[r - 1].addr + d->syms.p[r - 1].size || - !d->syms.p[r - 1].size)))) { - return r - 1; - } - } - return -1; -} - -long DisFindSymByName(struct Dis *d, const char *s) { - long i; - for (i = 0; i < d->syms.i; ++i) { - if (strcmp(s, d->syms.stab + d->syms.p[i].name) == 0) { - return i; - } - } - return -1; -} - -void DisLoadElf(struct Dis *d, struct Elf *elf) { - if (!elf || !elf->ehdr) return; - DisLoadElfLoads(d, elf); - DisLoadElfSyms(d, elf); - DisSortSyms(d); - /* DisCanonizeSyms(d); */ -} diff --git a/tool/build/lib/disinst.c b/tool/build/lib/disinst.c deleted file mode 100644 index e6d75bbcd..000000000 --- a/tool/build/lib/disinst.c +++ /dev/null @@ -1,215 +0,0 @@ -/*-*- 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/log/check.h" -#include "libc/str/str.h" -#include "tool/build/lib/dis.h" -#include "tool/build/lib/high.h" -#include "tool/build/lib/modrm.h" - -static const char kJcxz[3][6] = {"jcxz", "jecxz", "jrcxz"}; -static const char kAluOp[8][4] = {"add", "or", "adc", "sbb", - "and", "sub", "xor", "cmp"}; -static const char kBitOp[8][4] = {"rol", "ror", "rcl", "rcr", - "shl", "shr", "sal", "sar"}; -static const char kCc[16][3] = {"o", "no", "b", "ae", "e", "ne", "be", "a", - "s", "ns", "p", "np", "l", "ge", "le", "g"}; - -static bool IsProbablyByteOp(struct XedDecodedInst *x) { - return !(x->op.opcode & 1); -} - -static int IsRepOpcode(struct Dis *d) { - switch (d->xedd->op.opcode & ~1) { - case 0x6C: // INS - return 1; - case 0x6E: // OUTS - return 1; - case 0xA4: // MOVS - return 1; - case 0xAA: // STOS - return 1; - case 0xAC: // LODS - return 1; - case 0xA6: // CMPS - return 2; - case 0xAE: // SCAS - return 2; - default: - return 0; - } -} - -static char *DisRepPrefix(struct Dis *d, char *p) { - const char *s; - if (Rep(d->xedd->op.rde) && d->xedd->op.map == XED_ILD_MAP0) { - switch (IsRepOpcode(d)) { - case 0: - break; - case 1: - p = stpcpy(p, "rep "); - break; - case 2: - p = stpcpy(p, Rep(d->xedd->op.rde) == 2 ? "repnz " : "repz "); - break; - default: - break; - } - } - return p; -} - -static char *DisBranchTaken(struct Dis *d, char *p) { - switch (d->xedd->op.hint) { - case XED_HINT_NTAKEN: - return stpcpy(p, ",pn"); - case XED_HINT_TAKEN: - return stpcpy(p, ",pt"); - default: - return p; - } -} - -static char *DisName(struct Dis *d, char *bp, const char *name, - bool ambiguous) { - char *p, *np; - uint32_t rde; - bool notbyte, notlong, wantsuffix, wantsuffixsd; - p = bp; - rde = d->xedd->op.rde; - if (d->xedd->op.lock) p = stpcpy(p, "lock "); - p = DisRepPrefix(d, p); - if (strcmp(name, "BIT") == 0) { - p = stpcpy(p, kBitOp[ModrmReg(rde)]); - } else if (strcmp(name, "nop") == 0 && d->xedd->op.rep) { - p = stpcpy(p, "pause"); - } else if (strcmp(name, "CALL") == 0) { - p = stpcpy(p, "call"); - } else if (strcmp(name, "JMP") == 0) { - p = stpcpy(p, "jmp"); - } else if (strcmp(name, "jcxz") == 0) { - p = stpcpy(p, kJcxz[Eamode(rde)]); - p = DisBranchTaken(d, p); - } else if (strcmp(name, "loop") == 0 || strcmp(name, "loope") == 0 || - strcmp(name, "loopne") == 0) { - p = stpcpy(p, name); - if (Eamode(rde) != Mode(rde)) { - *p++ = "wl"[Eamode(rde)]; - *p = '\0'; - } - p = DisBranchTaken(d, p); - } else if (strcmp(name, "cwtl") == 0) { - if (Osz(rde)) name = "cbtw"; - if (Rexw(rde)) name = "cltq"; - p = stpcpy(p, name); - } else if (strcmp(name, "cltd") == 0) { - if (Osz(rde)) name = "cwtd"; - if (Rexw(rde)) name = "cqto"; - p = stpcpy(p, name); - } else { - notbyte = false; - notlong = false; - wantsuffix = false; - wantsuffixsd = false; - for (np = name; *np && (islower(*np) || isdigit(*np)); ++np) { - *p++ = *np; - } - if (strcmp(name, "ALU") == 0) { - p = stpcpy(p, kAluOp[(d->xedd->op.opcode & 070) >> 3]); - } else if (strcmp(name, "ALU2") == 0) { - p = stpcpy(p, kAluOp[ModrmReg(rde)]); - } else if (strcmp(np, "WLQ") == 0) { - notbyte = true; - wantsuffix = true; - } else if (strcmp(np, "CC") == 0) { - p = stpcpy(p, kCc[d->xedd->op.opcode & 15]); - p = DisBranchTaken(d, p); - } else if (strcmp(np, "WQ") == 0) { - notbyte = true; - notlong = Eamode(rde) != XED_MODE_REAL; - wantsuffix = true; - } else if (strcmp(np, "LQ") == 0 || strcmp(np, "WL") == 0) { - notbyte = true; - wantsuffix = true; - } else if (strcmp(np, "SD") == 0) { - notbyte = true; - wantsuffixsd = true; - } else if (strcmp(np, "ABS") == 0) { - if (Rexw(rde)) p = stpcpy(p, "abs"); - } - if (wantsuffixsd) { - if (Osz(rde)) { - *p++ = 'd'; - } else { - *p++ = 's'; - } - } else if (wantsuffix || (ambiguous && !_startswith(name, "f") && - !_startswith(name, "set"))) { - if (Osz(rde)) { - if (ambiguous || Mode(rde) != XED_MODE_REAL) { - *p++ = 'w'; - } - } else if (Rexw(rde)) { - *p++ = 'q'; - } else if (ambiguous && !notbyte && IsProbablyByteOp(d->xedd)) { - *p++ = 'b'; - } else if (!notlong) { - *p++ = 'l'; - } - } - } - *p++ = ' '; - while (p - bp < 8) *p++ = ' '; - *p = '\0'; - return p; -} - -/** - * Disassembles instruction based on string spec. - * @see DisSpec() - */ -char *DisInst(struct Dis *d, char *p, const char *spec) { - long i, n; - char sbuf[64]; - char args[4][256]; - char *s, *name, *state; - bool hasarg, hasmodrm, hasregister, hasmemory; - CHECK_EQ(0, (int)d->xedd->op.error); - DCHECK_LT(strlen(spec), 128); - hasarg = false; - hasmodrm = d->xedd->op.has_modrm; - hasmemory = hasmodrm && !IsModrmRegister(d->xedd->op.rde); - hasregister = hasmodrm && IsModrmRegister(d->xedd->op.rde); - name = strtok_r(strcpy(sbuf, spec), " ", &state); - for (n = 0; (s = strtok_r(NULL, " ", &state)); ++n) { - hasarg = true; - hasregister |= *s == '%'; - hasmemory |= *s == 'O'; - CHECK_LT(DisArg(d, args[n], s) - args[n], sizeof(args[n])); - } - p = HighStart(p, g_high.keyword); - p = DisName(d, p, name, hasarg && !hasregister && hasmemory); - p = HighEnd(p); - for (i = 0; i < n; ++i) { - if (i && args[n - i][0]) { - *p++ = ','; - } - p = stpcpy(p, args[n - i - 1]); - } - return p; -} diff --git a/tool/build/lib/disspec.c b/tool/build/lib/disspec.c deleted file mode 100644 index c6500489f..000000000 --- a/tool/build/lib/disspec.c +++ /dev/null @@ -1,1116 +0,0 @@ -/*-*- 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/str/str.h" -#include "third_party/xed/x86.h" -#include "tool/build/lib/case.h" -#include "tool/build/lib/modrm.h" - -#define UNKNOWN "wut" -#define RCASE(x, y) CASE(x, return y) - -static const char kFpuName[][8][8] = { - {"fadd", "fmul", "fcom", "fcomp", "fsub", "fsubr", "fdiv", "fdivr"}, - {"fchs", "fabs", UNKNOWN, UNKNOWN, "ftst", "fxam", UNKNOWN, UNKNOWN}, - {"fld1", "fldl2t", "fldl2e", "fldpi", "fldlg2", "fldln2", "fldz"}, - {"f2xm1", "fyl2x", "fptan", "fpatan", "fxtract", "fprem1", "fdecstp", - "fincstp"}, - {"fprem", "fyl2xp1", "fsqrt", "fsincos", "frndint", "fscale", "fsin", - "fcos"}, - {"fneni", "fndisi", "fnclex", "fninit", "fnsetpm"}, -}; - -char *DisOpFpu1(struct XedDecodedInst *x, char *p, const char *extra) { - stpcpy(stpcpy(p, kFpuName[0][ModrmReg(x->op.rde)]), extra); - return p; -} - -char *DisOp66(struct XedDecodedInst *x, char *p, const char *s, const char *a, - const char *b) { - stpcpy(stpcpy(p, s), !Osz(x->op.rde) ? a : b); - return p; -} - -char *DisOpVpsWpsVssWss(struct XedDecodedInst *x, char *p, const char *s) { - return DisOp66(x, p, s, "ps %Vps Wps", "ss %Vss Wss"); -} - -char *DisOpVpdWpdVpsWps(struct XedDecodedInst *x, char *p, const char *s) { - return DisOp66(x, p, s, "ps %Vps Wps", "pd %Vpd Wpd"); -} - -char *DisOpPqQqVdqWdq(struct XedDecodedInst *x, char *p, const char *s) { - return DisOp66(x, p, s, " %Pq Qq", " %Vdq Wdq"); -} - -char *DisOpPqQqIbVdqWdqIb(struct XedDecodedInst *x, char *p, const char *s) { - return DisOp66(x, p, s, " %Pq Qq Ib", " %Vdq Wdq Ib"); -} - -char *DisOpNqIbUdqIb(struct XedDecodedInst *x, char *p, const char *s) { - return DisOp66(x, p, s, " %Nq Ib", " %Udq Ib"); -} - -char *DisOpVpsWpsVssWssVpdWpdVsdWsd(struct XedDecodedInst *x, char *p, - const char *s) { - char *q = stpcpy(p, s); - if (Rep(x->op.rde) == 3) { - stpcpy(q, "ss %Vss Wss"); - } else if (Rep(x->op.rde) == 2) { - stpcpy(q, "sd %Vsd Wsd"); - } else if (Osz(x->op.rde)) { - stpcpy(q, "pd %Vpd Wpd"); - } else { - stpcpy(q, "ps %Vps Wps"); - } - return p; -} - -const char *DisSpecFpu0(struct XedDecodedInst *x, int group) { - const char *s; - s = kFpuName[group][ModrmRm(x->op.rde)]; - return *s ? s : UNKNOWN; -} - -const char *DisSpecRegMem(struct XedDecodedInst *x, const char *a, - const char *b) { - if (IsModrmRegister(x->op.rde)) { - return a; - } else { - return b; - } -} - -const char *DisSpecRegMemFpu0(struct XedDecodedInst *x, int group, - const char *b) { - return DisSpecRegMem(x, DisSpecFpu0(x, group), b); -} - -const char *DisSpecMap0(struct XedDecodedInst *x, char *p) { - switch (x->op.opcode & 0xff) { - RCASE(0x00, "ALU Eb %Gb"); - RCASE(0x01, "ALU Evqp %Gvqp"); - RCASE(0x02, "ALU %Gb Eb"); - RCASE(0x03, "ALU %Gvqp Evqp"); - RCASE(0x04, "ALU %al Ib"); - RCASE(0x05, "ALU %rAX Ivds"); - RCASE(0x06, "push %es"); - RCASE(0x07, "pop %es"); - RCASE(0x08, "ALU Eb %Gb"); - RCASE(0x09, "ALU Evqp %Gvqp"); - RCASE(0x0a, "ALU %Gb Eb"); - RCASE(0x0b, "ALU %Gvqp Evqp"); - RCASE(0x0c, "ALU %al Ib"); - RCASE(0x0d, "ALU %rAX Ivds"); - RCASE(0x0e, "push %cs"); - RCASE(0x0f, "pop %cs"); - RCASE(0x10, "ALU Eb %Gb"); - RCASE(0x11, "ALU Evqp %Gvqp"); - RCASE(0x12, "ALU %Gb Eb"); - RCASE(0x13, "ALU %Gvqp Evqp"); - RCASE(0x14, "ALU %al Ib"); - RCASE(0x15, "ALU %rAX Ivds"); - RCASE(0x16, "push %ss"); - RCASE(0x17, "pop %ss"); - RCASE(0x18, "ALU Eb %Gb"); - RCASE(0x19, "ALU Evqp %Gvqp"); - RCASE(0x1a, "ALU %Gb Eb"); - RCASE(0x1b, "ALU %Gvqp Evqp"); - RCASE(0x1c, "ALU %al Ib"); - RCASE(0x1d, "ALU %rAX Ivds"); - RCASE(0x1e, "push %ds"); - RCASE(0x1f, "pop %ds"); - RCASE(0x20, "ALU Eb %Gb"); - RCASE(0x21, "ALU Evqp %Gvqp"); - RCASE(0x22, "ALU %Gb Eb"); - RCASE(0x23, "ALU %Gvqp Evqp"); - RCASE(0x24, "ALU %al Ib"); - RCASE(0x25, "ALU %rAX Ivds"); - RCASE(0x26, "push %es"); - RCASE(0x27, "pop %es"); - RCASE(0x28, "ALU Eb %Gb"); - RCASE(0x29, "ALU Evqp %Gvqp"); - RCASE(0x2a, "ALU %Gb Eb"); - RCASE(0x2b, "ALU %Gvqp Evqp"); - RCASE(0x2c, "ALU %al Ib"); - RCASE(0x2d, "ALU %rAX Ivds"); - RCASE(0x2F, "das"); - RCASE(0x30, "ALU Eb %Gb"); - RCASE(0x31, "ALU Evqp %Gvqp"); - RCASE(0x32, "ALU %Gb Eb"); - RCASE(0x33, "ALU %Gvqp Evqp"); - RCASE(0x34, "ALU %al Ib"); - RCASE(0x35, "ALU %rAX Ivds"); - RCASE(0x37, "aaa"); - RCASE(0x38, "ALU Eb %Gb"); - RCASE(0x39, "ALU Evqp %Gvqp"); - RCASE(0x3A, "ALU %Gb Eb"); - RCASE(0x3B, "ALU %Gvqp Evqp"); - RCASE(0x3C, "ALU %al Ib"); - RCASE(0x3D, "ALU %rAX Ivds"); - RCASE(0x3F, "aas"); - RCASE(0x40 ... 0x47, "inc %Zv"); - RCASE(0x48 ... 0x4f, "dec %Zv"); - RCASE(0x50 ... 0x57, "push %Zvq"); - RCASE(0x58 ... 0x5f, "pop %Zvq"); - RCASE(0x60, "pusha"); - RCASE(0x61, "popa"); - RCASE(0x62, "bound"); - RCASE(0x63, "movslLQ %Gdqp Ed"); - RCASE(0x68, "pushWQ Ivs"); - RCASE(0x69, "imul %Gvqp Evqp Ivds"); - RCASE(0x6A, "pushWQ Ibss"); - RCASE(0x6B, "imul %Gvqp Evqp Ibs"); - RCASE(0x6C, "insb Yb DX"); - RCASE(0x6D, "insWL Yv DX"); - RCASE(0x6E, "outsb DX Xb"); - RCASE(0x6F, "outsWL DX Xv"); - RCASE(0x70 ... 0x7f, "jCC Jbs"); - RCASE(0x80, "ALU2 Eb Ib"); - RCASE(0x81, "ALU2 Evqp Ivds"); - RCASE(0x82, "ALU2 Eb Ib"); - RCASE(0x83, "ALU2 Evqp Ibs"); - RCASE(0x84, "test Eb %Gb"); - RCASE(0x85, "test %Gvqp Evqp"); - RCASE(0x86, "xchg %Gb Eb"); - RCASE(0x87, "xchg %Gvqp Evqp"); - RCASE(0x88, "mov Eb %Gb"); - RCASE(0x89, "mov Evqp %Gvqp"); - RCASE(0x8A, "mov %Gb Eb"); - RCASE(0x8B, "mov %Gvqp Evqp"); - RCASE(0x8C, "mov Evqp %Sw"); - RCASE(0x8D, "lea %Gvqp M"); - RCASE(0x8E, "mov %Sw Evqp"); - RCASE(0x90, "nop"); - RCASE(0x91 ... 0x97, "xchg %Zvqp %rAX"); - RCASE(0x98, "cwtl"); - RCASE(0x99, "cltd"); - RCASE(0x9A, "lcall Pvds Kvds"); - RCASE(0x9B, "fwait"); - RCASE(0x9C, "pushfWQ"); - RCASE(0x9D, "popfWQ"); - RCASE(0x9E, "sahf"); - RCASE(0x9F, "lahf"); - RCASE(0xA0, "movABS %al Ob"); - RCASE(0xA1, "movABS %rAX Ovqp"); - RCASE(0xA2, "movABS Ob %al"); - RCASE(0xA3, "movABS Ovqp %rAX"); - RCASE(0xA4, "movsb Yb Xb"); - RCASE(0xA5, "movsWLQ Yvqp Xvqp"); - RCASE(0xA6, "cmpsb Yb Xb"); - RCASE(0xA7, "cmpsWLQ Yvqp Xvqp"); - RCASE(0xA8, "test %al Ib"); - RCASE(0xA9, "test %rAX Ivds"); - RCASE(0xAA, "stosb Yb %al"); - RCASE(0xAB, "stosWLQ Yvqp %rAX"); - RCASE(0xAC, "lodsb %al Xb"); - RCASE(0xAD, "lodsWLQ %rAX Xvqp"); - RCASE(0xAE, "scasb %al Yb"); - RCASE(0xAF, "scasWLQ %rAX Yvqp"); - RCASE(0xB0 ... 0xb7, "mov %Zb Ib"); - RCASE(0xB8 ... 0xbf, "movABS %Zvqp Ivqp"); - RCASE(0xC0, "BIT Eb Ib"); - RCASE(0xC1, "BIT Evqp Ib"); - RCASE(0xC2, "ret Iw"); - RCASE(0xC3, "ret"); - RCASE(0xC4, "les %Gv Mp"); - RCASE(0xC5, "lds %Gv Mp"); - RCASE(0xC6, "mov Eb Ib"); - RCASE(0xC7, "mov Evqp Ivds"); - RCASE(0xC9, "leave"); - RCASE(0xCA, "lret Iw"); - RCASE(0xCB, "lret"); - RCASE(0xCC, "int3"); - RCASE(0xCD, "int Ib"); - RCASE(0xCE, "into"); - RCASE(0xCF, "iret"); - RCASE(0xD0, "BIT Eb"); - RCASE(0xD1, "BIT Evqp"); - RCASE(0xD2, "BIT Evqp %cl"); - RCASE(0xD3, "BIT Evqp %cl"); - RCASE(0xD4, x->op.uimm0 == 0x0a ? "aam" : "aam Ib"); - RCASE(0xD5, x->op.uimm0 == 0x0a ? "aad" : "aad Ib"); - RCASE(0xD6, "salc"); - RCASE(0xD7, "xlat BBb"); - RCASE(0xE0, "loopne Jbs"); - RCASE(0xE1, "loope Jbs"); - RCASE(0xE2, "loop Jbs"); - RCASE(0xE3, "jcxz Jbs"); - RCASE(0xE4, "in %al Ib"); - RCASE(0xE5, "in %eAX Ib"); - RCASE(0xE6, "out Ib %al"); - RCASE(0xE7, "out Ib %eAX"); - RCASE(0xE8, "call Jvds"); - RCASE(0xE9, "jmp Jvds"); - RCASE(0xEA, "ljmp Rvds Kvds"); - RCASE(0xEB, "jmp Jbs"); - RCASE(0xEC, "in %al DX"); - RCASE(0xED, "in %eAX DX"); - RCASE(0xEE, "out DX %al"); - RCASE(0xEF, "out DX %eAX"); - RCASE(0xF1, "int1"); - RCASE(0xF4, "hlt"); - RCASE(0xF5, "cmc"); - RCASE(0xF8, "clc"); - RCASE(0xF9, "stc"); - RCASE(0xFA, "cli"); - RCASE(0xFB, "sti"); - RCASE(0xFC, "cld"); - RCASE(0xFD, "std"); - case 0x8F: - switch (ModrmReg(x->op.rde)) { - RCASE(0, "popWQ Evq"); - default: - break; - } - break; - case 0xD9: - switch (ModrmReg(x->op.rde)) { - RCASE(1, "fxch EST1"); - RCASE(3, "fstps Msr %st"); - RCASE(0, DisSpecRegMem(x, "fld EST", "flds Msr")); - RCASE(2, DisSpecRegMem(x, "fnop", "fsts Msr %st")); - RCASE(4, DisSpecRegMemFpu0(x, 1, "fldenv Me")); - RCASE(5, DisSpecRegMemFpu0(x, 2, "fldcw Mw")); - RCASE(6, DisSpecRegMemFpu0(x, 3, "fnstenv M")); - RCASE(7, DisSpecRegMemFpu0(x, 4, "fnstcw Mw")); - } - break; - case 0xDA: - switch (ModrmReg(x->op.rde)) { - RCASE(0, DisSpecRegMem(x, "fcmovb %st EST", "fiaddl Mdi")); - RCASE(1, DisSpecRegMem(x, "fcmove %st EST", "fimull Mdi")); - RCASE(2, DisSpecRegMem(x, "fcmovbe %st EST", "ficoml Mdi")); - RCASE(3, DisSpecRegMem(x, "fcmovu %st EST", "ficompl Mdi")); - RCASE(4, DisSpecRegMem(x, "fisubr Mdi", "fisubl Mdi")); - RCASE(5, DisSpecRegMem(x, "fucompp", "fisubrl Mdi")); - RCASE(6, DisSpecRegMem(x, "fidivl Mdi", "UNKNOWN")); - RCASE(7, DisSpecRegMem(x, "fidivrl Mdi", "UNKNOWN")); - } - break; - case 0xDB: - switch (ModrmReg(x->op.rde)) { - RCASE(0, DisSpecRegMem(x, "fcmovnb %st EST", "fildl Mdi")); - RCASE(1, DisSpecRegMem(x, "fcmovne %st EST", "fisttpl Mdi")); - RCASE(2, DisSpecRegMem(x, "fcmovnbe %st EST", "fistl Mdi")); - RCASE(3, DisSpecRegMem(x, "fcmovnu %st EST", "fistpl Mdi")); - RCASE(4, DisSpecFpu0(x, 5)); - RCASE(5, DisSpecRegMem(x, "fucomi %st EST", "fldt Mer")); - RCASE(6, DisSpecRegMem(x, "fcomi %st EST", UNKNOWN)); - RCASE(7, DisSpecRegMem(x, UNKNOWN, "fstpt Mer")); - } - break; - case 0xD8: - return DisOpFpu1(x, p, !IsModrmRegister(x->op.rde) ? "s Msr" : " EST1"); - case 0xDC: - if (!IsModrmRegister(x->op.rde)) { - return DisOpFpu1(x, p, "l Mdr"); - } else { - switch (ModrmReg(x->op.rde)) { - RCASE(0, "fadd EST %st"); - RCASE(1, "fmul EST %st"); - RCASE(2, "fcom %st EST"); - RCASE(3, "fcomp %st EST"); - RCASE(4, "fsub EST %st"); - RCASE(5, "fsubr EST %st"); - RCASE(6, "fdiv EST %st"); - RCASE(7, "fdivr EST %st"); - } - } - break; - case 0xDD: - if (!IsModrmRegister(x->op.rde)) { - switch (ModrmReg(x->op.rde)) { - RCASE(0, "fldl Mdr"); - RCASE(1, "fisttpll Mqi"); - RCASE(2, "fstl Mdr"); - RCASE(3, "fstpl Mdr"); - RCASE(4, "frstor Mdr"); - RCASE(6, "fnsave Mst"); - RCASE(7, "fnstsw Mst"); - } - } else { - switch (ModrmReg(x->op.rde)) { - RCASE(0, "ffree EST"); - RCASE(1, "fxch EST"); - RCASE(2, "fst EST"); - RCASE(3, "fstp EST"); - RCASE(4, "fucom EST1"); - RCASE(5, "fucomp EST1"); - } - } - break; - case 0xDE: - if (!IsModrmRegister(x->op.rde)) { - switch (ModrmReg(x->op.rde)) { - RCASE(0, "fiadds Mwi"); - RCASE(1, "fimuls Mwi"); - RCASE(2, "ficoms Mwi"); - RCASE(3, "ficomps Mwi"); - RCASE(4, "fisubs Mwi"); - RCASE(5, "fisubrs Mwi"); - RCASE(6, "fidivs Mwi"); - RCASE(7, "fidivrs Mwi"); - } - } else { - switch (ModrmReg(x->op.rde)) { - RCASE(0, "faddp EST1"); - RCASE(1, "fmulp EST1"); - RCASE(2, "fcomp EST1"); - RCASE(3, "fcompp"); - RCASE(4, "fsubp EST1"); - RCASE(5, "fsubrp EST1"); - RCASE(6, "fdivp EST1"); - RCASE(7, "fdivrp EST1"); - } - } - break; - case 0xDF: - if (!IsModrmRegister(x->op.rde)) { - switch (ModrmReg(x->op.rde)) { - RCASE(0, "filds Mwi"); - RCASE(1, "fisttps Mwi"); - RCASE(2, "fists Mwi"); - RCASE(3, "fistps Mwi"); - RCASE(4, "fbld"); - RCASE(5, "fildll Mqi"); - RCASE(6, "fbstp"); - RCASE(7, "fistpll Mqi"); - } - } else { - switch (ModrmReg(x->op.rde)) { - RCASE(0, "ffreep EST"); - RCASE(1, "fxch"); - RCASE(2, "fstp EST"); - RCASE(3, "fstp EST"); - RCASE(4, "fnstsw"); - RCASE(5, "fucomip EST"); - RCASE(6, "fcomip EST"); - } - } - break; - case 0xF6: - switch (ModrmReg(x->op.rde)) { - RCASE(0, "test Eb Ib"); - RCASE(1, "test Eb Ib"); - RCASE(2, "not Eb"); - RCASE(3, "neg Eb"); - RCASE(4, "mulb Eb"); - RCASE(5, "imulb Eb"); - RCASE(6, "divb Eb"); - RCASE(7, "idivb Eb"); - } - break; - case 0xF7: - switch (ModrmReg(x->op.rde)) { - RCASE(0, "test Evqp Ivds"); - RCASE(1, "test Evqp Ivds"); - RCASE(2, "not Evqp"); - RCASE(3, "neg Evqp"); - RCASE(4, "mul Evqp"); - RCASE(5, "imul Evqp"); - RCASE(6, "div Evqp"); - RCASE(7, "idiv Evqp"); - } - break; - case 0xFE: - switch (ModrmReg(x->op.rde)) { - RCASE(0, "inc Eb"); - RCASE(1, "dec Eb"); - } - break; - case 0xFF: - switch (ModrmReg(x->op.rde)) { - RCASE(0, "inc Evqp"); - RCASE(1, "dec Evqp"); - RCASE(2, "CALL Eq"); - RCASE(4, "JMP Eq"); - RCASE(6, "pushWQ Evq"); - } - break; - } - return UNKNOWN; -} - -const char *DisSpecMap1(struct XedDecodedInst *x, char *p) { - bool isreg; - isreg = IsModrmRegister(x->op.rde); - switch (x->op.opcode & 0xff) { - RCASE(0x02, "lar %Gvqp Ev"); - RCASE(0x03, "lsl %Gvqp Ev"); - RCASE(0x05, "syscall"); - RCASE(0x0B, "ud2"); - RCASE(0x0D, "nop Ev"); - RCASE(0x18, "nop Ev"); - RCASE(0x19, "nop Ev"); - RCASE(0x1A, "nop Ev"); - RCASE(0x1B, "nop Ev"); - RCASE(0x1C, "nop Ev"); - RCASE(0x1D, "nop Ev"); - RCASE(0x20, "mov %Hd %Cd"); - RCASE(0x22, "mov %Cd %Hd"); - RCASE(0x28, "movapSD %Vps Wps"); - RCASE(0x29, "movapSD Wps %Vps"); - RCASE(0x2B, "movntpSD Mps %Vps"); - RCASE(0x2E, Osz(x->op.rde) ? "ucomisd %Vsd Wsd" : "ucomiss %Vss Wss"); - RCASE(0x2F, Osz(x->op.rde) ? "comisd %Vsd Wsd" : "comiss %Vss Wss"); - RCASE(0x30, "wrmsr"); - RCASE(0x31, "rdtsc"); - RCASE(0x32, "rdmsr"); - RCASE(0x33, "rdpmc"); - RCASE(0x34, "sysenter"); - RCASE(0x35, "sysexit"); - RCASE(0x40 ... 0x4f, "cmovCC %Gvqp Evqp"); - RCASE(0x52, DisOpVpsWpsVssWss(x, p, "rsqrt")); - RCASE(0x53, DisOpVpsWpsVssWss(x, p, "rcp")); - RCASE(0x54, DisOpVpdWpdVpsWps(x, p, "and")); - RCASE(0x55, DisOpVpdWpdVpsWps(x, p, "andn")); - RCASE(0x56, DisOpVpdWpdVpsWps(x, p, "or")); - RCASE(0x57, DisOpVpdWpdVpsWps(x, p, "xor")); - RCASE(0x58, DisOpVpsWpsVssWssVpdWpdVsdWsd(x, p, "add")); - RCASE(0x59, DisOpVpsWpsVssWssVpdWpdVsdWsd(x, p, "mul")); - RCASE(0x5C, DisOpVpsWpsVssWssVpdWpdVsdWsd(x, p, "sub")); - RCASE(0x5D, DisOpVpsWpsVssWssVpdWpdVsdWsd(x, p, "min")); - RCASE(0x5E, DisOpVpsWpsVssWssVpdWpdVsdWsd(x, p, "div")); - RCASE(0x5F, DisOpVpsWpsVssWssVpdWpdVsdWsd(x, p, "max")); - RCASE(0x60, DisOpPqQqVdqWdq(x, p, "punpcklbw")); - RCASE(0x61, DisOpPqQqVdqWdq(x, p, "punpcklwd")); - RCASE(0x62, DisOpPqQqVdqWdq(x, p, "punpckldq")); - RCASE(0x63, DisOpPqQqVdqWdq(x, p, "packsswb")); - RCASE(0x64, DisOpPqQqVdqWdq(x, p, "pcmpgtb")); - RCASE(0x65, DisOpPqQqVdqWdq(x, p, "pcmpgtw")); - RCASE(0x66, DisOpPqQqVdqWdq(x, p, "pcmpgtd")); - RCASE(0x67, DisOpPqQqVdqWdq(x, p, "packuswb")); - RCASE(0x68, DisOpPqQqVdqWdq(x, p, "punpckhbw")); - RCASE(0x69, DisOpPqQqVdqWdq(x, p, "punpckhwd")); - RCASE(0x6A, DisOpPqQqVdqWdq(x, p, "punpckhdq")); - RCASE(0x6B, DisOpPqQqVdqWdq(x, p, "packssdw")); - RCASE(0x6C, DisOpPqQqVdqWdq(x, p, "punpcklqdq")); - RCASE(0x6D, DisOpPqQqVdqWdq(x, p, "punpckhqdq")); - RCASE(0x74, DisOpPqQqVdqWdq(x, p, "pcmpeqb")); - RCASE(0x75, DisOpPqQqVdqWdq(x, p, "pcmpeqw")); - RCASE(0x76, DisOpPqQqVdqWdq(x, p, "pcmpeqd")); - RCASE(0x77, "emms"); - RCASE(0x80 ... 0x8f, "jCC Jvds"); - RCASE(0x90 ... 0x9f, "setCC Jvds"); - RCASE(0xA0, "push %fs"); - RCASE(0xA1, "pop %fs"); - RCASE(0xA2, "cpuid"); - RCASE(0xA3, "bt Evqp %Gvqp"); - RCASE(0xA4, "shld Evqp %Gvqp Ib"); - RCASE(0xA5, "shld Evqp %Gvqp %cl"); - RCASE(0xA8, "push %gs"); - RCASE(0xA9, "pop %gs"); - RCASE(0xAB, "bts Evqp %Gvqp"); - RCASE(0xAC, "shrd Evqp %Gvqp Ib"); - RCASE(0xAD, "shrd Evqp %Gvqp %cl"); - RCASE(0xAF, "imul %Gvqp Evqp"); - RCASE(0xB0, "cmpxchg Eb %Gb"); - RCASE(0xB1, "cmpxchg Evqp %Gvqp"); - RCASE(0xB3, "btr Evqp %Gvqp"); - RCASE(0xB6, "movzbWLQ %Gvqp Eb"); - RCASE(0xB7, "movzwWLQ %Gvqp Ew"); - RCASE(0xB9, "ud %Gvqp Evqp"); - RCASE(0xBB, "btc Evqp %Gvqp"); - RCASE(0xBE, "movsbWLQ %Gvqp Eb"); - RCASE(0xBF, "movswWLQ %Gvqp Ew"); - RCASE(0xC0, "xadd Eb %Gb"); - RCASE(0xC1, "xadd Evqp %Gvqp"); - RCASE(0xC2, DisOpVpsWpsVssWssVpdWpdVsdWsd(x, p, "cmp")); - RCASE(0xC3, "movnti Mdqp %Gdqp"); - RCASE(0xC8 ... 0xCF, "bswap %Zvqp"); - RCASE(0xD1, DisOpPqQqVdqWdq(x, p, "psrlw")); - RCASE(0xD2, DisOpPqQqVdqWdq(x, p, "psrld")); - RCASE(0xD3, DisOpPqQqVdqWdq(x, p, "psrlq")); - RCASE(0xD4, DisOpPqQqVdqWdq(x, p, "paddq")); - RCASE(0xD5, DisOpPqQqVdqWdq(x, p, "pmullw")); - RCASE(0xD7, Osz(x->op.rde) ? "pmovmskb %Gdqp %Udq" : "pmovmskb %Gdqp %Nq"); - RCASE(0xD8, DisOpPqQqVdqWdq(x, p, "psubusb")); - RCASE(0xD9, DisOpPqQqVdqWdq(x, p, "psubusw")); - RCASE(0xDA, DisOpPqQqVdqWdq(x, p, "pminub")); - RCASE(0xDB, DisOpPqQqVdqWdq(x, p, "pand")); - RCASE(0xDC, DisOpPqQqVdqWdq(x, p, "paddusb")); - RCASE(0xDD, DisOpPqQqVdqWdq(x, p, "paddusw")); - RCASE(0xDE, DisOpPqQqVdqWdq(x, p, "pmaxub")); - RCASE(0xDF, DisOpPqQqVdqWdq(x, p, "pandn")); - RCASE(0xE0, DisOpPqQqVdqWdq(x, p, "pavgb")); - RCASE(0xE1, DisOpPqQqVdqWdq(x, p, "psrawv")); - RCASE(0xE2, DisOpPqQqVdqWdq(x, p, "psradv")); - RCASE(0xE3, DisOpPqQqVdqWdq(x, p, "pavgw")); - RCASE(0xE4, DisOpPqQqVdqWdq(x, p, "pmulhuw")); - RCASE(0xE5, DisOpPqQqVdqWdq(x, p, "pmulhw")); - RCASE(0xE7, Osz(x->op.rde) ? "movntdq Mdq %Vdq" : "movntq Mq %Pq"); - RCASE(0xE8, DisOpPqQqVdqWdq(x, p, "psubsb")); - RCASE(0xE9, DisOpPqQqVdqWdq(x, p, "psubsw")); - RCASE(0xEA, DisOpPqQqVdqWdq(x, p, "pminsw")); - RCASE(0xEB, DisOpPqQqVdqWdq(x, p, "por")); - RCASE(0xEC, DisOpPqQqVdqWdq(x, p, "paddsb")); - RCASE(0xED, DisOpPqQqVdqWdq(x, p, "paddsw")); - RCASE(0xEE, DisOpPqQqVdqWdq(x, p, "pmaxsw")); - RCASE(0xEF, DisOpPqQqVdqWdq(x, p, "pxor")); - RCASE(0xF0, "lddqu %Vdq Mdq"); - RCASE(0xF1, DisOpPqQqVdqWdq(x, p, "psllwv")); - RCASE(0xF2, DisOpPqQqVdqWdq(x, p, "pslldv")); - RCASE(0xF3, DisOpPqQqVdqWdq(x, p, "psllqv")); - RCASE(0xF4, DisOpPqQqVdqWdq(x, p, "pmuludq")); - RCASE(0xF5, DisOpPqQqVdqWdq(x, p, "pmaddwd")); - RCASE(0xF6, DisOpPqQqVdqWdq(x, p, "psadbw")); - RCASE(0xF8, DisOpPqQqVdqWdq(x, p, "psubb")); - RCASE(0xF9, DisOpPqQqVdqWdq(x, p, "psubw")); - RCASE(0xFA, DisOpPqQqVdqWdq(x, p, "psubd")); - RCASE(0xFB, DisOpPqQqVdqWdq(x, p, "psubq")); - RCASE(0xFC, DisOpPqQqVdqWdq(x, p, "paddb")); - RCASE(0xFD, DisOpPqQqVdqWdq(x, p, "paddw")); - RCASE(0xFE, DisOpPqQqVdqWdq(x, p, "paddd")); - RCASE(0xFF, "ud0 %Gvqp Evqp"); - case 0xBC: - if (Rep(x->op.rde) == 3) { - return "tzcnt %Gvqp Evqp"; - } else { - return "bsf %Gvqp Evqp"; - } - case 0xBD: - if (Rep(x->op.rde) == 3) { - return "lzcnt %Gvqp Evqp"; - } else { - return "bsr %Gvqp Evqp"; - } - case 0x01: - switch (ModrmReg(x->op.rde)) { - case 0: - if (!isreg) { - return "sgdt Ms"; - } else { - switch (ModrmRm(x->op.rde)) { - case 1: - return "vmcall"; - case 2: - return "vmlaunch"; - case 3: - return "vmresume"; - case 4: - return "vmxoff"; - default: - return UNKNOWN; - } - } - break; - case 1: - if (!isreg) { - return "sidt Ms"; - } else { - switch (ModrmRm(x->op.rde)) { - case 0: - return "monitor"; - case 1: - return "mwait"; - default: - return UNKNOWN; - } - } - break; - case 2: - if (!isreg) { - return "lgdt Ms"; - } else if (ModrmRm(x->op.rde) == 0) { - return "xgetbv"; - } else if (ModrmRm(x->op.rde) == 1) { - return "xsetbv"; - } else { - return UNKNOWN; - } - break; - case 3: - if (!isreg) { - return "lidt Ms"; - } else { - return UNKNOWN; - } - case 4: - return "smsw Ew"; - case 6: - return "lmsw Ew"; - case 7: - if (!isreg) { - return "invlpg M"; - } else { - switch (ModrmRm(x->op.rde)) { - case 0: - return "swapgs"; - case 1: - return "rdtscp"; - default: - return UNKNOWN; - } - } - default: - return UNKNOWN; - } - case 0x1F: - if (ModrmMod(x->op.rde) == 1 && ModrmReg(x->op.rde) == 0 && - ModrmRm(x->op.rde) == 0b101) { - return "bofram Jb"; - } else { - return "nop Ev"; - } - break; - case 0x70: - switch (Rep(x->op.rde) | Osz(x->op.rde)) { - RCASE(0, "pshufw %Pq Qq Ib"); - RCASE(1, "pshufd %Vdq Wdq Ib"); - RCASE(2, "pshuflw %Vdq Wdq Ib"); - RCASE(3, "pshufhw %Vdq Wdq Ib"); - } - break; - case 0x71: - switch (ModrmReg(x->op.rde)) { - RCASE(2, DisOpNqIbUdqIb(x, p, "psrlw")); - RCASE(4, DisOpNqIbUdqIb(x, p, "psraw")); - RCASE(6, DisOpNqIbUdqIb(x, p, "psllw")); - } - break; - case 0x72: - switch (ModrmReg(x->op.rde)) { - RCASE(2, DisOpNqIbUdqIb(x, p, "psrld")); - RCASE(4, DisOpNqIbUdqIb(x, p, "psrad")); - RCASE(6, DisOpNqIbUdqIb(x, p, "pslld")); - } - break; - case 0x73: - switch (ModrmReg(x->op.rde)) { - RCASE(2, DisOpNqIbUdqIb(x, p, "psrlq")); - RCASE(3, DisOpNqIbUdqIb(x, p, "psrldq")); - RCASE(6, DisOpNqIbUdqIb(x, p, "psllq")); - RCASE(7, DisOpNqIbUdqIb(x, p, "pslldq")); - } - break; - case 0xAE: - switch (ModrmReg(x->op.rde)) { - case 0: - if (isreg) { - return "rdfsbase %Rdqp"; - } else { - return "fxsave M"; - } - case 1: - if (isreg) { - return "rdgsbase %Rdqp"; - } else { - return "fxrstor M"; - } - case 2: - if (isreg) { - return "wrfsbase %Rdqp"; - } else { - return "ldmxcsr Md"; - } - case 3: - if (isreg) { - return "wrgsbase %Rdqp"; - } else { - return "stmxcsr Md"; - } - case 4: - if (isreg) { - return UNKNOWN; - } else { - return "xsave M %edx %eax"; - } - case 5: - return "lfence"; - case 6: - return "mfence"; - case 7: - if (isreg && ModrmReg(x->op.rde) == 0b111) { - return "sfence"; - } else { - return "clflush"; - } - } - break; - case 0xBA: - switch (ModrmReg(x->op.rde)) { - RCASE(4, "btWLQ Evqp Ib"); - RCASE(5, "btsWLQ Evqp Ib"); - RCASE(6, "btrWLQ Evqp Ib"); - RCASE(7, "btcWLQ Evqp Ib"); - } - break; - case 0x10: - if (Rep(x->op.rde) == 3) { - return "movss %Vss Wss"; - } else if (Rep(x->op.rde) == 2) { - return "movsd %Vsd Wsd"; - } else if (Osz(x->op.rde)) { - return "movupd %Vpd Wpd"; - } else { - return "movups %Vps Wps"; - } - break; - case 0x11: - if (Rep(x->op.rde) == 3) { - return "movss Wss %Vss"; - } else if (Rep(x->op.rde) == 2) { - return "movsd Wsd %Vsd"; - } else if (Osz(x->op.rde)) { - return "movupd Wpd %Vpd"; - } else { - return "movups Wps %Vps"; - } - break; - case 0xC4: - if (!Osz(x->op.rde)) { - if (isreg) { - return "pinsrw %Pq %Rdqp Ib"; - } else { - return "pinsrw %Pq Mw Ib"; - } - } else { - if (isreg) { - return "pinsrw %Vdq %Rdqp Ib"; - } else { - return "pinsrw %Vdq Mw Ib"; - } - } - break; - case 0xC5: - if (!Osz(x->op.rde)) { - return "pextrw %Gdqp %Nq Ib"; - } else { - return "pextrw %Gdqp %Udq Ib"; - } - break; - case 0xC6: - if (!Osz(x->op.rde)) { - return "shufps %Vps Wps Ib"; - } else { - return "shufpd %Vpd Wpd Ib"; - } - break; - case 0xC7: - switch (ModrmReg(x->op.rde)) { - case 1: - if (!isreg) { - if (Rexw(x->op.rde)) { - return "cmpxchg16b Mdq"; - } else { - return "cmpxchg8b Mq"; - } - } else { - return UNKNOWN; - } - break; - case 6: - if (isreg) { - return "rdrand %Rdqp"; - } else { - return UNKNOWN; - } - break; - case 7: - if (isreg) { - if (Rep(x->op.rde) == 3) { - return "rdpid %Rdqp"; - } else { - return "rdseed %Rdqp"; - } - } else { - return UNKNOWN; - } - break; - default: - return UNKNOWN; - } - break; - case 0xD6: - if (Osz(x->op.rde)) { - return "movq Wq %Vq"; - } else if (Rep(x->op.rde) == 3) { - return "movq2dq %Vdq %Nq"; - } else if (Rep(x->op.rde) == 2) { - return "movq2dq %Pq %Uq"; - } - break; - case 0x12: - switch (Rep(x->op.rde) | Osz(x->op.rde)) { - case 0: - if (isreg) { - return "movhlps %Vq %Uq"; - } else { - return "movlps %Vq Mq"; - } - break; - case 1: - return "movlpd %Vq Mq"; - case 2: - return "movddup %Vq Wq"; - case 3: - return "movsldup %Vq Wq"; - default: - __builtin_unreachable(); - } - break; - case 0x13: - if (Osz(x->op.rde)) { - return "movlpd Mq %Vq"; - } else { - return "movlps Mq %Vq"; - } - break; - case 0x16: - switch (Rep(x->op.rde) | Osz(x->op.rde)) { - case 0: - if (isreg) { - return "movlhps %Vq %Uq"; - } else { - return "movhps %Vq Mq"; - } - break; - case 1: - return "movhpd %Vq Mq"; - case 3: - return "movshdup %Vq Wq"; - default: - break; - } - break; - case 0x17: - if (Osz(x->op.rde)) { - return "movhpd Mq %Vq"; - } else { - return "movhps Mq %Vq"; - } - break; - case 0x2A: - if (Rep(x->op.rde) == 3) { - return "cvtsi2ss %Vss Edqp"; - } else if (Rep(x->op.rde) == 2) { - return "cvtsi2sd %Vsd Edqp"; - } else if (Osz(x->op.rde)) { - return "cvtpi2pd %Vpd Qpi"; - } else { - return "cvtpi2ps %Vps Qpi"; - } - break; - case 0x2C: - if (Rep(x->op.rde) == 3) { - return "cvttss2si %Gdqp Wss"; - } else if (Rep(x->op.rde) == 2) { - return "cvttsd2si %Gdqp Wsd"; - } else if (Osz(x->op.rde)) { - return "cvttpd2pi %Ppi Wpd"; - } else { - return "cvttps2pi %Ppi Wpsq"; - } - break; - case 0x2D: - if (Rep(x->op.rde) == 3) { - return "cvtss2si %Gdqp Wss"; - } else if (Rep(x->op.rde) == 2) { - return "cvtsd2si %Gdqp Wsd"; - } else if (Osz(x->op.rde)) { - return "cvtpd2pi %Ppi Wpd"; - } else { - return "cvtps2pi %Ppi Wpsq"; - } - break; - case 0x5a: - if (Rep(x->op.rde) == 3) { - return "cvtss2sd %Vsd Wss"; - } else if (Rep(x->op.rde) == 2) { - return "cvtsd2ss %Vss Wsd"; - } else if (Osz(x->op.rde)) { - return "cvtpd2ps %Vps Wpd"; - } else { - return "cvtps2pd %Vpd Wps"; - } - break; - case 0x5b: - if (Rep(x->op.rde) == 3) { - return "cvttps2dq %Vdq Wps"; - } else if (Osz(x->op.rde)) { - return "cvtps2dq %Vdq Wps"; - } else { - return "cvtdq2ps %Vps Wdq"; - } - break; - case 0x51: - if (Rep(x->op.rde) == 3) { - return "sqrtss %Vss Wss"; - } else if (Rep(x->op.rde) == 2) { - return "sqrtsd %Vsd Wsd"; - } else if (Osz(x->op.rde)) { - return "sqrtpd %Vpd Wpd"; - } else { - return "sqrtps %Vps Wps"; - } - break; - case 0x6E: - if (Osz(x->op.rde)) { - if (Rexw(x->op.rde)) { - return "movq %Vdq Eqp"; - } else { - return "movd %Vdq Ed"; - } - } else { - if (Rexw(x->op.rde)) { - return "movq %Pq Eqp"; - } else { - return "movd %Pq Ed"; - } - } - break; - case 0x6F: - if (Rep(x->op.rde) == 3) { - return "movdqu %Vdq Wdq"; - } else if (Osz(x->op.rde)) { - return "movdqa %Vdq Wdq"; - } else { - return "movq %Pq Qq"; - } - break; - case 0x7E: - if (Rep(x->op.rde) == 3) { - return "movq %Vq Wq"; - } else if (Osz(x->op.rde)) { - if (Rexw(x->op.rde)) { - return "movq Eqp %Vdq"; - } else { - return "movd Ed %Vdq"; - } - } else { - if (Rexw(x->op.rde)) { - return "movq Eqp %Pq"; - } else { - return "movd Ed %Pq"; - } - } - break; - case 0x7F: - if (Rep(x->op.rde) == 3) { - return "movdqu Wdq %Vdq"; - } else if (Osz(x->op.rde)) { - return "movdqa Wdq %Vdq"; - } else { - return "movq Qq %Pq"; - } - break; - case 0xE6: - if (Rep(x->op.rde) == 2) { - return "cvtpd2dq %Vdq Wpd"; - } else if (Osz(x->op.rde)) { - return "cvttpd2dq %Vdq Wpd"; - } else if (Rep(x->op.rde) == 3) { - return "cvtdq2pd %Vpd Wdq"; - } - break; - } - return UNKNOWN; -} - -const char *DisSpecMap2(struct XedDecodedInst *x, char *p) { - switch (x->op.opcode & 0xff) { - RCASE(0x00, DisOpPqQqVdqWdq(x, p, "pshufb")); - RCASE(0x01, DisOpPqQqVdqWdq(x, p, "phaddw")); - RCASE(0x02, DisOpPqQqVdqWdq(x, p, "phaddd")); - RCASE(0x03, DisOpPqQqVdqWdq(x, p, "phaddsw")); - RCASE(0x04, DisOpPqQqVdqWdq(x, p, "pmaddubsw")); - RCASE(0x05, DisOpPqQqVdqWdq(x, p, "phsubw")); - RCASE(0x06, DisOpPqQqVdqWdq(x, p, "phsubd")); - RCASE(0x07, DisOpPqQqVdqWdq(x, p, "phsubsw")); - RCASE(0x08, DisOpPqQqVdqWdq(x, p, "psignb")); - RCASE(0x09, DisOpPqQqVdqWdq(x, p, "psignw")); - RCASE(0x0A, DisOpPqQqVdqWdq(x, p, "psignd")); - RCASE(0x0B, DisOpPqQqVdqWdq(x, p, "pmulhrsw")); - RCASE(0x10, "pblendvb %Vdq Wdq"); - RCASE(0x14, "blendvps Vps Wps"); - RCASE(0x15, "blendvpd Vpd Wpd"); - RCASE(0x17, "ptest %Vdq Wdq"); - RCASE(0x1C, DisOpPqQqVdqWdq(x, p, "pabsb")); - RCASE(0x1D, DisOpPqQqVdqWdq(x, p, "pabsw")); - RCASE(0x1E, DisOpPqQqVdqWdq(x, p, "pabsd")); - RCASE(0x20, "pmovsxbw %Vdq Mq"); - RCASE(0x21, "pmovsxbd %Vdq Md"); - RCASE(0x22, "pmovsxbq %Vdq Mw"); - RCASE(0x23, "pmovsxwd %Vdq Mq"); - RCASE(0x24, "pmovsxwq %Vdq Md"); - RCASE(0x25, "pmovsxdq %Vdq Mq"); - RCASE(0x28, "pmuldq %Vdq Wdq"); - RCASE(0x29, "pcmpeqq %Vdq Wdq"); - RCASE(0x2A, "movntdqa %Vdq Mdq"); - RCASE(0x2B, "packusdw %Vdq Wdq"); - RCASE(0x30, "pmovzxbw %Vdq Mq"); - RCASE(0x31, "pmovzxbd %Vdq Md"); - RCASE(0x32, "pmovzxbq %Vdq Mw"); - RCASE(0x33, "pmovzxwd %Vdq Mq"); - RCASE(0x34, "pmovzxwq %Vdq Md"); - RCASE(0x35, "pmovzxdq %Vdq Mq"); - RCASE(0x37, "pcmpgtq %Vdq Wdq"); - RCASE(0x38, "pminsb %Vdq Wdq"); - RCASE(0x39, "pminsd %Vdq Wdq"); - RCASE(0x3A, "pminuw %Vdq Wdq"); - RCASE(0x3B, "pminud %Vdq Wdq"); - RCASE(0x3C, "pmaxsb %Vdq Wdq"); - RCASE(0x3D, "pmaxsd %Vdq Wdq"); - RCASE(0x3E, "pmaxuw %Vdq Wdq"); - RCASE(0x3F, "pmaxud %Vdq Wdq"); - RCASE(0x40, "pmulld %Vdq Wdq"); - RCASE(0x41, "phminposuw %Vdq Wdq"); - RCASE(0x80, "invept %Gq Mdq"); - RCASE(0x81, "invvpid %Gq Mdq"); - case 0xF0: - if (Rep(x->op.rde) == 2) { - return "crc32 %Gvqp Eb"; - } else { - return "movbe %Gvqp M"; - } - break; - case 0xF1: - if (Rep(x->op.rde) == 2) { - return "crc32 %Gvqp Evqp"; - } else { - return "movbe M %Gvqp"; - } - break; - default: - return UNKNOWN; - } -} - -const char *DisSpecMap3(struct XedDecodedInst *x, char *p) { - switch (x->op.opcode & 0xff) { - RCASE(0x0F, DisOpPqQqIbVdqWdqIb(x, p, "palignr")); - default: - return UNKNOWN; - } -} - -const char *DisSpec(struct XedDecodedInst *x, char *p) { - switch (x->op.map & 7) { - case XED_ILD_MAP0: - return DisSpecMap0(x, p); - case XED_ILD_MAP1: - return DisSpecMap1(x, p); - case XED_ILD_MAP2: - return DisSpecMap2(x, p); - case XED_ILD_MAP3: - return DisSpecMap3(x, p); - default: - return UNKNOWN; - } -} diff --git a/tool/build/lib/divmul.c b/tool/build/lib/divmul.c deleted file mode 100644 index 450674f9f..000000000 --- a/tool/build/lib/divmul.c +++ /dev/null @@ -1,369 +0,0 @@ -/*-*- 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/limits.h" -#include "tool/build/lib/divmul.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/flags.h" -#include "tool/build/lib/modrm.h" -#include "tool/build/lib/throw.h" - -struct Dubble { - uint64_t lo; - uint64_t hi; -}; - -static inline struct Dubble DubbleNeg(struct Dubble x) { - struct Dubble d; - d.lo = -x.lo; - d.hi = ~(x.hi - (x.lo - 1 > x.lo)); - return d; -} - -static inline struct Dubble DubbleShl(struct Dubble x) { - struct Dubble d; - d.lo = x.lo << 1; - d.hi = x.hi << 1 | x.lo >> 63; - return d; -} - -static inline struct Dubble DubbleShr(struct Dubble x) { - struct Dubble d; - d.lo = x.lo >> 1 | x.hi << 63; - d.hi = x.hi >> 1; - return d; -} - -static inline unsigned DubbleLte(struct Dubble a, struct Dubble b) { - return a.hi == b.hi ? a.lo <= b.lo : a.hi <= b.hi; -} - -static struct Dubble DubbleMul(uint64_t a, uint64_t b) { - struct Dubble d; - uint64_t x, y, t; - x = (a & 0xffffffff) * (b & 0xffffffff); - t = x >> 32; - x &= 0xffffffff; - t += (a >> 32) * (b & 0xffffffff); - x += (t & 0xffffffff) << 32; - y = t >> 32; - t = x >> 32; - x &= 0xffffffff; - t += (b >> 32) * (a & 0xffffffff); - x += (t & 0xffffffff) << 32; - y += t >> 32; - y += (a >> 32) * (b >> 32); - d.lo = x; - d.hi = y; - return d; -} - -static struct Dubble DubbleImul(uint64_t a, uint64_t b) { - unsigned s, t; - struct Dubble p; - if ((s = a >> 63)) a = -a; - if ((t = b >> 63)) b = -b; - p = DubbleMul(a, b); - return s ^ t ? DubbleNeg(p) : p; -} - -static struct Dubble DubbleDiv(struct Dubble a, uint64_t b, uint64_t *r) { - int n, c; - uint64_t s; - struct Dubble d, q, t; - d.lo = b, d.hi = 0; - q.lo = 0, q.hi = 0; - for (n = 0; DubbleLte(d, a) && n < 128; ++n) { - d = DubbleShl(d); - } - for (; n > 0; --n) { - t = a; - d = DubbleShr(d); - q = DubbleShl(q); - s = a.lo, a.lo -= d.lo + 0, c = a.lo > s; - s = a.hi, a.hi -= d.hi + c, c = a.hi > s; - if (c) { - a = t; - } else { - q.lo++; - } - } - *r = a.lo; - return q; -} - -static struct Dubble DubbleIdiv(struct Dubble a, uint64_t b, uint64_t *r) { - unsigned s, t; - struct Dubble q; - if ((s = a.hi >> 63)) a = DubbleNeg(a); - if ((t = b >> 63)) b = -b; - q = DubbleDiv(a, b, r); - if (s ^ t) q = DubbleNeg(q); - if (s) *r = -*r; - return q; -} - -void OpDivAlAhAxEbSigned(struct Machine *m, uint32_t rde) { - int8_t y, r; - int16_t x, q; - x = Read16(m->ax); - y = Read8(GetModrmRegisterBytePointerRead(m, rde)); - if (!y) ThrowDivideError(m); - if (x == INT16_MIN) ThrowDivideError(m); - q = x / y; - r = x % y; - if (q != (int8_t)q) ThrowDivideError(m); - m->ax[0] = q & 0xff; - m->ax[1] = r & 0xff; -} - -void OpDivAlAhAxEbUnsigned(struct Machine *m, uint32_t rde) { - uint8_t y, r; - uint16_t x, q; - x = Read16(m->ax); - y = Read8(GetModrmRegisterBytePointerRead(m, rde)); - if (!y) ThrowDivideError(m); - q = x / y; - r = x % y; - if (q > 255) ThrowDivideError(m); - m->ax[0] = q & 0xff; - m->ax[1] = r & 0xff; -} - -static void OpDivRdxRaxEvqpSigned64(struct Machine *m, uint32_t rde, - uint8_t *p) { - uint64_t d, r; - struct Dubble q; - q.lo = Read64(m->ax); - q.hi = Read64(m->dx); - d = Read64(p); - if (!d) ThrowDivideError(m); - if (!q.lo && q.hi == 0x8000000000000000) ThrowDivideError(m); - q = DubbleIdiv(q, d, &r); - if ((int64_t)q.lo < 0 && (int64_t)q.hi != -1) ThrowDivideError(m); - if ((int64_t)q.lo >= 0 && q.hi) ThrowDivideError(m); - Write64(m->ax, q.lo); - Write64(m->dx, r); -} - -static void OpDivRdxRaxEvqpSigned32(struct Machine *m, uint32_t rde, - uint8_t *p) { - int32_t y, r; - int64_t x, q; - x = (uint64_t)Read32(m->dx) << 32 | Read32(m->ax); - y = Read32(p); - if (!y) ThrowDivideError(m); - if (x == INT64_MIN) ThrowDivideError(m); - q = x / y; - r = x % y; - if (q != (int32_t)q) ThrowDivideError(m); - Write64(m->ax, q & 0xffffffff); - Write64(m->dx, r & 0xffffffff); -} - -static void OpDivRdxRaxEvqpSigned16(struct Machine *m, uint32_t rde, - uint8_t *p) { - int16_t y, r; - int32_t x, q; - x = (uint32_t)Read16(m->dx) << 16 | Read16(m->ax); - y = Read16(p); - if (!y) ThrowDivideError(m); - if (x == INT32_MIN) ThrowDivideError(m); - q = x / y; - r = x % y; - if (q != (int16_t)q) ThrowDivideError(m); - Write16(m->ax, q); - Write16(m->dx, r); -} - -static void OpDivRdxRaxEvqpUnsigned16(struct Machine *m, uint32_t rde, - uint8_t *p) { - uint16_t y, r; - uint32_t x, q; - x = (uint32_t)Read16(m->dx) << 16 | Read16(m->ax); - y = Read16(p); - if (!y) ThrowDivideError(m); - q = x / y; - r = x % y; - if (q > 65535) ThrowDivideError(m); - Write16(m->ax, q); - Write16(m->dx, r); -} - -static void OpDivRdxRaxEvqpUnsigned32(struct Machine *m, uint32_t rde, - uint8_t *p) { - uint32_t y, r; - uint64_t x, q; - x = (uint64_t)Read32(m->dx) << 32 | Read32(m->ax); - y = Read32(p); - if (!y) ThrowDivideError(m); - q = x / y; - r = x % y; - if (q > 4294967295) ThrowDivideError(m); - Write64(m->ax, q & 0xffffffff); - Write64(m->dx, r & 0xffffffff); -} - -static void OpDivRdxRaxEvqpUnsigned64(struct Machine *m, uint32_t rde, - uint8_t *p) { - uint64_t d, r; - struct Dubble q; - q.lo = Read64(m->ax); - q.hi = Read64(m->dx); - d = Read64(p); - if (!d) ThrowDivideError(m); - q = DubbleDiv(q, d, &r); - if (q.hi) ThrowDivideError(m); - Write64(m->ax, q.lo); - Write64(m->dx, r); -} - -void OpDivRdxRaxEvqpSigned(struct Machine *m, uint32_t rde) { - uint8_t *p; - p = GetModrmRegisterWordPointerReadOszRexw(m, rde); - if (Rexw(rde)) { - OpDivRdxRaxEvqpSigned64(m, rde, p); - } else if (!Osz(rde)) { - OpDivRdxRaxEvqpSigned32(m, rde, p); - } else { - OpDivRdxRaxEvqpSigned16(m, rde, p); - } -} - -void OpDivRdxRaxEvqpUnsigned(struct Machine *m, uint32_t rde) { - uint8_t *p; - p = GetModrmRegisterWordPointerReadOszRexw(m, rde); - if (Rexw(rde)) { - OpDivRdxRaxEvqpUnsigned64(m, rde, p); - } else if (!Osz(rde)) { - OpDivRdxRaxEvqpUnsigned32(m, rde, p); - } else { - OpDivRdxRaxEvqpUnsigned16(m, rde, p); - } -} - -void OpMulAxAlEbSigned(struct Machine *m, uint32_t rde) { - int16_t ax; - uint8_t *p; - unsigned of; - p = GetModrmRegisterBytePointerRead(m, rde); - ax = (int8_t)Read8(m->ax) * (int8_t)Read8(p); - of = ax != (int8_t)ax; - m->flags = SetFlag(m->flags, FLAGS_CF, of); - m->flags = SetFlag(m->flags, FLAGS_OF, of); - Write16(m->ax, ax); -} - -void OpMulAxAlEbUnsigned(struct Machine *m, uint32_t rde) { - int ax; - uint8_t *p; - unsigned of; - p = GetModrmRegisterBytePointerRead(m, rde); - ax = Read8(m->ax) * Read8(p); - of = ax != (uint8_t)ax; - m->flags = SetFlag(m->flags, FLAGS_CF, of); - m->flags = SetFlag(m->flags, FLAGS_OF, of); - Write16(m->ax, ax); -} - -void OpMulRdxRaxEvqpSigned(struct Machine *m, uint32_t rde) { - uint8_t *p; - unsigned of; - int32_t dxax; - int64_t edxeax; - struct Dubble rdxrax; - p = GetModrmRegisterWordPointerReadOszRexw(m, rde); - if (Rexw(rde)) { - rdxrax = DubbleImul(Read64(m->ax), Read64(p)); - of = !!(rdxrax.hi + (rdxrax.lo >> 63)); - Write64(m->ax, rdxrax.lo); - Write64(m->dx, rdxrax.hi); - } else if (!Osz(rde)) { - edxeax = (int64_t)(int32_t)Read32(m->ax) * (int32_t)Read32(p); - of = edxeax != (int32_t)edxeax; - Write64(m->ax, edxeax); - Write64(m->dx, edxeax >> 32); - } else { - dxax = (int32_t)(int16_t)Read16(m->ax) * (int16_t)Read16(p); - of = dxax != (int16_t)dxax; - Write16(m->ax, dxax); - Write16(m->dx, dxax >> 16); - } - m->flags = SetFlag(m->flags, FLAGS_CF, of); - m->flags = SetFlag(m->flags, FLAGS_OF, of); -} - -void OpMulRdxRaxEvqpUnsigned(struct Machine *m, uint32_t rde) { - uint8_t *p; - unsigned of; - uint32_t dxax; - uint64_t edxeax; - struct Dubble rdxrax; - p = GetModrmRegisterWordPointerReadOszRexw(m, rde); - if (Rexw(rde)) { - rdxrax = DubbleMul(Read64(m->ax), Read64(p)); - of = !!rdxrax.hi; - Write64(m->ax, rdxrax.lo); - Write64(m->dx, rdxrax.hi); - } else if (!Osz(rde)) { - edxeax = (uint64_t)Read32(m->ax) * Read32(p); - of = (uint32_t)edxeax != edxeax; - Write64(m->ax, edxeax); - Write64(m->dx, edxeax >> 32); - } else { - dxax = (uint32_t)(uint16_t)Read16(m->ax) * (uint16_t)Read16(p); - of = (uint16_t)dxax != dxax; - Write16(m->ax, dxax); - Write16(m->dx, dxax >> 16); - } - m->flags = SetFlag(m->flags, FLAGS_CF, of); - m->flags = SetFlag(m->flags, FLAGS_OF, of); -} - -static void AluImul(struct Machine *m, uint32_t rde, uint8_t *a, uint8_t *b) { - unsigned of; - if (Rexw(rde)) { - struct Dubble p; - p = DubbleImul(Read64(a), Read64(b)); - of = !!(p.hi + (p.lo >> 63)); - Write64(RegRexrReg(m, rde), p.lo); - } else if (!Osz(rde)) { - int64_t z; - z = (int64_t)(int32_t)Read32(a) * (int32_t)Read32(b); - of = z != (int32_t)z; - Write64(RegRexrReg(m, rde), z & 0xffffffff); - } else { - int32_t z; - z = (int32_t)(int16_t)Read16(a) * (int16_t)Read16(b); - of = z != (int16_t)z; - Write16(RegRexrReg(m, rde), z); - } - m->flags = SetFlag(m->flags, FLAGS_CF, of); - m->flags = SetFlag(m->flags, FLAGS_OF, of); -} - -void OpImulGvqpEvqp(struct Machine *m, uint32_t rde) { - AluImul(m, rde, RegRexrReg(m, rde), - GetModrmRegisterWordPointerReadOszRexw(m, rde)); -} - -void OpImulGvqpEvqpImm(struct Machine *m, uint32_t rde) { - uint8_t b[8]; - Write64(b, m->xedd->op.uimm0); - AluImul(m, rde, GetModrmRegisterWordPointerReadOszRexw(m, rde), b); -} diff --git a/tool/build/lib/divmul.h b/tool/build/lib/divmul.h deleted file mode 100644 index 941b42cee..000000000 --- a/tool/build/lib/divmul.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_DIVMUL_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_DIVMUL_H_ -#include "tool/build/lib/machine.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -void OpDivAlAhAxEbSigned(struct Machine *, uint32_t); -void OpDivAlAhAxEbUnsigned(struct Machine *, uint32_t); -void OpDivRdxRaxEvqpSigned(struct Machine *, uint32_t); -void OpDivRdxRaxEvqpUnsigned(struct Machine *, uint32_t); -void OpImulGvqpEvqp(struct Machine *, uint32_t); -void OpImulGvqpEvqpImm(struct Machine *, uint32_t); -void OpMulAxAlEbSigned(struct Machine *, uint32_t); -void OpMulAxAlEbUnsigned(struct Machine *, uint32_t); -void OpMulRdxRaxEvqpSigned(struct Machine *, uint32_t); -void OpMulRdxRaxEvqpUnsigned(struct Machine *, uint32_t); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_DIVMUL_H_ */ diff --git a/tool/build/lib/fds.c b/tool/build/lib/fds.c deleted file mode 100644 index c0fb5a2ff..000000000 --- a/tool/build/lib/fds.c +++ /dev/null @@ -1,48 +0,0 @@ -/*-*- 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/log/check.h" -#include "libc/mem/mem.h" -#include "tool/build/lib/fds.h" - -int MachineFdAdd(struct MachineFds *mf) { - int fd; - struct MachineFdClosed *closed; - if ((closed = mf->closed)) { - fd = closed->fd; - mf->closed = closed->next; - free(closed); - } else { - fd = mf->i; - if (mf->i++ == mf->n) { - mf->n = mf->i + (mf->i >> 1); - mf->p = realloc(mf->p, mf->n * sizeof(*mf->p)); - } - } - return fd; -} - -void MachineFdRemove(struct MachineFds *mf, int fd) { - struct MachineFdClosed *closed; - mf->p[fd].cb = NULL; - if ((closed = malloc(sizeof(struct MachineFdClosed)))) { - closed->fd = fd; - closed->next = mf->closed; - mf->closed = closed; - } -} diff --git a/tool/build/lib/fds.h b/tool/build/lib/fds.h deleted file mode 100644 index 62f270249..000000000 --- a/tool/build/lib/fds.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_FDS_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_FDS_H_ -#include "libc/calls/struct/iovec.h" -#include "libc/sock/sock.h" -#include "libc/sock/struct/pollfd.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -struct MachineFdClosed { - unsigned fd; - struct MachineFdClosed *next; -}; - -struct MachineFdCb { - int (*close)(int); - ssize_t (*readv)(int, const struct iovec *, int); - ssize_t (*writev)(int, const struct iovec *, int); - int (*ioctl)(int, int, ...); - int (*poll)(struct pollfd *, uint64_t, int32_t); -}; - -struct MachineFd { - int fd; - struct MachineFdCb *cb; -}; - -struct MachineFds { - size_t i, n; - struct MachineFd *p; - struct MachineFdClosed *closed; -}; - -int MachineFdAdd(struct MachineFds *); -void MachineFdRemove(struct MachineFds *, int); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_FDS_H_ */ diff --git a/tool/build/lib/flags.c b/tool/build/lib/flags.c deleted file mode 100644 index 59855ccdd..000000000 --- a/tool/build/lib/flags.c +++ /dev/null @@ -1,63 +0,0 @@ -/*-*- 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 "tool/build/lib/flags.h" - -bool GetParity(uint8_t b) { - b ^= b >> 4; - b ^= b >> 2; - b ^= b >> 1; - return ~b & 1; -} - -void ImportFlags(struct Machine *m, uint64_t flags) { - uint64_t old, mask = 0; - mask |= 1u << FLAGS_CF; - mask |= 1u << FLAGS_PF; - mask |= 1u << FLAGS_AF; - mask |= 1u << FLAGS_ZF; - mask |= 1u << FLAGS_SF; - mask |= 1u << FLAGS_TF; - mask |= 1u << FLAGS_IF; - mask |= 1u << FLAGS_DF; - mask |= 1u << FLAGS_OF; - mask |= 1u << FLAGS_NT; - mask |= 1u << FLAGS_AC; - mask |= 1u << FLAGS_ID; - m->flags = (flags & mask) | (m->flags & ~mask); - m->flags = SetFlag(m->flags, FLAGS_RF, false); - m->flags = SetLazyParityByte(m->flags, !((m->flags >> FLAGS_PF) & 1)); -} - -uint64_t ExportFlags(uint64_t flags) { - flags = SetFlag(flags, FLAGS_IOPL, 3); - flags = SetFlag(flags, FLAGS_F1, true); - flags = SetFlag(flags, FLAGS_F0, false); - flags = flags & ~(1ull << FLAGS_PF); - flags |= GetLazyParityBool(flags) << FLAGS_PF; - return flags; -} - -int64_t AluFlags(uint64_t x, uint32_t af, uint32_t *f, uint32_t of, uint32_t cf, - uint32_t sf) { - *f &= ~(1u << FLAGS_CF | 1u << FLAGS_ZF | 1u << FLAGS_SF | 1u << FLAGS_OF | - 1u << FLAGS_AF | 0xFF000000u); - *f |= sf << FLAGS_SF | cf << FLAGS_CF | !x << FLAGS_ZF | of << FLAGS_OF | - af << FLAGS_AF | (x & 0xFF) << 24; - return x; -} diff --git a/tool/build/lib/flags.h b/tool/build/lib/flags.h deleted file mode 100644 index 2807a7b2a..000000000 --- a/tool/build/lib/flags.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_FLAGS_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_FLAGS_H_ -#include "tool/build/lib/machine.h" - -#define FLAGS_CF 0 -#define FLAGS_VF 1 -#define FLAGS_PF 2 -#define FLAGS_F1 3 -#define FLAGS_AF 4 -#define FLAGS_KF 5 -#define FLAGS_ZF 6 -#define FLAGS_SF 7 -#define FLAGS_TF 8 -#define FLAGS_IF 9 -#define FLAGS_DF 10 -#define FLAGS_OF 11 -#define FLAGS_IOPL 12 -#define FLAGS_NT 14 -#define FLAGS_F0 15 -#define FLAGS_RF 16 -#define FLAGS_VM 17 -#define FLAGS_AC 18 -#define FLAGS_VIF 19 -#define FLAGS_VIP 20 -#define FLAGS_ID 21 - -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -#define GetLazyParityBool(f) GetParity((f) >> 24) -#define SetLazyParityByte(f, x) (((f) & ~0xFF000000u) | ((x)&0xFFu) << 24) - -#define GetFlag(FLAGS, BIT) \ - ({ \ - autotype(FLAGS) Flags = (FLAGS); \ - typeof(Flags) IsSet; \ - switch (BIT) { \ - case FLAGS_PF: \ - IsSet = GetLazyParityBool(Flags); \ - break; \ - default: \ - IsSet = (Flags >> (BIT)) & 1; \ - break; \ - } \ - IsSet; \ - }) - -#define SetFlag(FLAGS, BIT, VAL) \ - ({ \ - autotype(FLAGS) Flags = (FLAGS); \ - typeof(Flags) Val = (VAL); \ - typeof(Flags) One = 1; \ - switch (BIT) { \ - case FLAGS_PF: \ - Flags = SetLazyParityByte(Flags, !Val); \ - break; \ - default: \ - Flags = (Flags & ~(One << (BIT))) | Val << (BIT); \ - break; \ - } \ - Flags; \ - }) - -bool GetParity(uint8_t); -uint64_t ExportFlags(uint64_t); -void ImportFlags(struct Machine *, uint64_t); -int64_t AluFlags(uint64_t, uint32_t, uint32_t *, uint32_t, uint32_t, uint32_t); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_FLAGS_H_ */ diff --git a/tool/build/lib/fpu.c b/tool/build/lib/fpu.c deleted file mode 100644 index 08efd1095..000000000 --- a/tool/build/lib/fpu.c +++ /dev/null @@ -1,1190 +0,0 @@ -/*-*- 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/math.h" -#include "libc/nt/struct/importobjectheader.internal.h" -#include "libc/str/str.h" -#include "tool/build/lib/case.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/flags.h" -#include "tool/build/lib/fpu.h" -#include "tool/build/lib/ldbl.h" -#include "tool/build/lib/memory.h" -#include "tool/build/lib/modrm.h" -#include "tool/build/lib/pun.h" -#include "tool/build/lib/throw.h" - -#define FPUREG 0 -#define MEMORY 1 - -#define DISP(x, y, z) ((7 & (x)) << 4 | (y) << 3 | (z)) - -static void OnFpuStackOverflow(struct Machine *m) { - m->fpu.sw |= kFpuSwIe | kFpuSwC1 | kFpuSwSf; -} - -static double OnFpuStackUnderflow(struct Machine *m) { - m->fpu.sw |= kFpuSwIe | kFpuSwSf; - m->fpu.sw &= ~kFpuSwC1; - return -NAN; -} - -static double St(struct Machine *m, int i) { - if (FpuGetTag(m, i) == kFpuTagEmpty) OnFpuStackUnderflow(m); - return *FpuSt(m, i); -} - -static double St0(struct Machine *m) { - return St(m, 0); -} - -static double St1(struct Machine *m) { - return St(m, 1); -} - -static double StRm(struct Machine *m) { - return St(m, ModrmRm(m->xedd->op.rde)); -} - -static void FpuClearRoundup(struct Machine *m) { - m->fpu.sw &= ~kFpuSwC1; -} - -static void FpuClearOutOfRangeIndicator(struct Machine *m) { - m->fpu.sw &= ~kFpuSwC2; -} - -static void FpuSetSt0(struct Machine *m, double x) { - *FpuSt(m, 0) = x; -} - -static void FpuSetStRm(struct Machine *m, double x) { - *FpuSt(m, ModrmRm(m->xedd->op.rde)) = x; -} - -static void FpuSetStPop(struct Machine *m, int i, double x) { - *FpuSt(m, i) = x; - FpuPop(m); -} - -static void FpuSetStRmPop(struct Machine *m, double x) { - FpuSetStPop(m, ModrmRm(m->xedd->op.rde), x); -} - -static int16_t FpuGetMemoryShort(struct Machine *m) { - uint8_t b[2]; - return Read16(Load(m, m->fpu.dp, 2, b)); -} - -static int32_t FpuGetMemoryInt(struct Machine *m) { - uint8_t b[4]; - return Read32(Load(m, m->fpu.dp, 4, b)); -} - -static int64_t FpuGetMemoryLong(struct Machine *m) { - uint8_t b[8]; - return Read64(Load(m, m->fpu.dp, 8, b)); -} - -static float FpuGetMemoryFloat(struct Machine *m) { - union FloatPun u; - u.i = FpuGetMemoryInt(m); - return u.f; -} - -static double FpuGetMemoryDouble(struct Machine *m) { - union DoublePun u; - u.i = FpuGetMemoryLong(m); - return u.f; -} - -static void FpuSetMemoryShort(struct Machine *m, int16_t i) { - void *p[2]; - uint8_t b[2]; - Write16(BeginStore(m, m->fpu.dp, 2, p, b), i); - EndStore(m, m->fpu.dp, 2, p, b); -} - -static void FpuSetMemoryInt(struct Machine *m, int32_t i) { - void *p[2]; - uint8_t b[4]; - Write32(BeginStore(m, m->fpu.dp, 4, p, b), i); - EndStore(m, m->fpu.dp, 4, p, b); -} - -static void FpuSetMemoryLong(struct Machine *m, int64_t i) { - void *p[2]; - uint8_t b[8]; - Write64(BeginStore(m, m->fpu.dp, 8, p, b), i); - EndStore(m, m->fpu.dp, 8, p, b); -} - -static void FpuSetMemoryFloat(struct Machine *m, float f) { - union FloatPun u = {f}; - FpuSetMemoryInt(m, u.i); -} - -static void FpuSetMemoryDouble(struct Machine *m, double f) { - union DoublePun u = {f}; - FpuSetMemoryLong(m, u.i); -} - -static double FpuGetMemoryLdbl(struct Machine *m) { - uint8_t b[10]; - return DeserializeLdbl(Load(m, m->fpu.dp, 10, b)); -} - -static void FpuSetMemoryLdbl(struct Machine *m, double f) { - void *p[2]; - uint8_t b[10], t[10]; - SerializeLdbl(b, f); - memcpy(BeginStore(m, m->fpu.dp, 10, p, t), b, 10); - EndStore(m, m->fpu.dp, 10, p, t); -} - -static double f2xm1(double x) { - return exp2(x) - 1; -} - -static double fyl2x(double x, double y) { - return y * log2(x); -} - -static double fyl2xp1(double x, double y) { - return y * log2(x + 1); -} - -static double fscale(double significand, double exponent) { - if (isunordered(significand, exponent)) return NAN; - return ldexp(significand, exponent); -} - -static double x87remainder(double x, double y, uint32_t *sw, - double rem(double, double), double rnd(double)) { - int s; - long q; - double r; - s = 0; - r = rem(x, y); - q = rnd(x / y); - s &= ~kFpuSwC2; /* ty libm */ - if (q & 1) s |= kFpuSwC1; - if (q & 2) s |= kFpuSwC3; - if (q & 4) s |= kFpuSwC0; - if (sw) *sw = s | (*sw & ~(kFpuSwC0 | kFpuSwC1 | kFpuSwC2 | kFpuSwC3)); - return r; -} - -static double fprem(double dividend, double modulus, uint32_t *sw) { - return x87remainder(dividend, modulus, sw, fmod, trunc); -} - -static double fprem1(double dividend, double modulus, uint32_t *sw) { - return x87remainder(dividend, modulus, sw, remainder, rint); -} - -static double FpuAdd(struct Machine *m, double x, double y) { - if (!isunordered(x, y)) { - switch (isinf(y) << 1 | isinf(x)) { - case 0: - return x + y; - case 1: - return x; - case 2: - return y; - case 3: - if (signbit(x) == signbit(y)) { - return x; - } else { - m->fpu.sw |= kFpuSwIe; - return copysign(NAN, x); - } - default: - for (;;) (void)0; - } - } else { - return NAN; - } -} - -static double FpuSub(struct Machine *m, double x, double y) { - if (!isunordered(x, y)) { - switch (isinf(y) << 1 | isinf(x)) { - case 0: - return x - y; - case 1: - return -x; - case 2: - return y; - case 3: - if (signbit(x) == signbit(y)) { - m->fpu.sw |= kFpuSwIe; - return copysign(NAN, x); - } else { - return y; - } - default: - for (;;) (void)0; - } - } else { - return NAN; - } -} - -static double FpuMul(struct Machine *m, double x, double y) { - if (!isunordered(x, y)) { - if (!((isinf(x) && !y) || (isinf(y) && !x))) { - return x * y; - } else { - m->fpu.sw |= kFpuSwIe; - return -NAN; - } - } else { - return NAN; - } -} - -static double FpuDiv(struct Machine *m, double x, double y) { - if (!isunordered(x, y)) { - if (x || y) { - if (y) { - return x / y; - } else { - m->fpu.sw |= kFpuSwZe; - return copysign(INFINITY, x); - } - } else { - m->fpu.sw |= kFpuSwIe; - return copysign(NAN, x); - } - } else { - return NAN; - } -} - -static double FpuRound(struct Machine *m, double x) { - switch ((m->fpu.cw & kFpuCwRc) >> 10) { - case 0: - return rint(x); - case 1: - return floor(x); - case 2: - return ceil(x); - case 3: - return trunc(x); - default: - for (;;) (void)0; - } -} - -static void FpuCompare(struct Machine *m, double y) { - double x = St0(m); - m->fpu.sw &= ~(kFpuSwC0 | kFpuSwC1 | kFpuSwC2 | kFpuSwC3); - if (!isunordered(x, y)) { - if (x < y) m->fpu.sw |= kFpuSwC0; - if (x == y) m->fpu.sw |= kFpuSwC3; - } else { - m->fpu.sw |= kFpuSwC0 | kFpuSwC2 | kFpuSwC3 | kFpuSwIe; - } -} - -static void OpFxam(struct Machine *m) { - double x; - x = *FpuSt(m, 0); - m->fpu.sw &= ~(kFpuSwC0 | kFpuSwC1 | kFpuSwC2 | kFpuSwC3); - if (signbit(x)) m->fpu.sw |= kFpuSwC1; - if (FpuGetTag(m, 0) == kFpuTagEmpty) { - m->fpu.sw |= kFpuSwC0 | kFpuSwC3; - } else { - switch (fpclassify(x)) { - case FP_NAN: - m->fpu.sw |= kFpuSwC0; - break; - case FP_INFINITE: - m->fpu.sw |= kFpuSwC0 | kFpuSwC2; - break; - case FP_ZERO: - m->fpu.sw |= kFpuSwC3; - break; - case FP_SUBNORMAL: - m->fpu.sw |= kFpuSwC2 | kFpuSwC3; - break; - case FP_NORMAL: - m->fpu.sw |= kFpuSwC2; - break; - default: - for (;;) (void)0; - } - } -} - -static void OpFtst(struct Machine *m) { - FpuCompare(m, 0); -} - -static void OpFcmovb(struct Machine *m) { - if (GetFlag(m->flags, FLAGS_CF)) { - FpuSetSt0(m, StRm(m)); - } -} - -static void OpFcmove(struct Machine *m) { - if (GetFlag(m->flags, FLAGS_ZF)) { - FpuSetSt0(m, StRm(m)); - } -} - -static void OpFcmovbe(struct Machine *m) { - if (GetFlag(m->flags, FLAGS_CF) || GetFlag(m->flags, FLAGS_ZF)) { - FpuSetSt0(m, StRm(m)); - } -} - -static void OpFcmovu(struct Machine *m) { - if (GetFlag(m->flags, FLAGS_PF)) { - FpuSetSt0(m, StRm(m)); - } -} - -static void OpFcmovnb(struct Machine *m) { - if (!GetFlag(m->flags, FLAGS_CF)) { - FpuSetSt0(m, StRm(m)); - } -} - -static void OpFcmovne(struct Machine *m) { - if (!GetFlag(m->flags, FLAGS_ZF)) { - FpuSetSt0(m, StRm(m)); - } -} - -static void OpFcmovnbe(struct Machine *m) { - if (!(GetFlag(m->flags, FLAGS_CF) || GetFlag(m->flags, FLAGS_ZF))) { - FpuSetSt0(m, StRm(m)); - } -} - -static void OpFcmovnu(struct Machine *m) { - if (!GetFlag(m->flags, FLAGS_PF)) { - FpuSetSt0(m, StRm(m)); - } -} - -static void OpFchs(struct Machine *m) { - FpuSetSt0(m, -St0(m)); -} - -static void OpFabs(struct Machine *m) { - FpuSetSt0(m, fabs(St0(m))); -} - -static void OpF2xm1(struct Machine *m) { - FpuSetSt0(m, f2xm1(St0(m))); -} - -static void OpFyl2x(struct Machine *m) { - FpuSetStPop(m, 1, fyl2x(St0(m), St1(m))); -} - -static void OpFyl2xp1(struct Machine *m) { - FpuSetStPop(m, 1, fyl2xp1(St0(m), St1(m))); -} - -static void OpFcos(struct Machine *m) { - FpuClearOutOfRangeIndicator(m); - FpuSetSt0(m, cos(St0(m))); -} - -static void OpFsin(struct Machine *m) { - FpuClearOutOfRangeIndicator(m); - FpuSetSt0(m, sin(St0(m))); -} - -static void OpFptan(struct Machine *m) { - FpuClearOutOfRangeIndicator(m); - FpuSetSt0(m, tan(St0(m))); - FpuPush(m, 1); -} - -static void OpFsincos(struct Machine *m) { - double tsin, tcos; - FpuClearOutOfRangeIndicator(m); - tsin = sin(St0(m)); - tcos = cos(St0(m)); - FpuSetSt0(m, tsin); - FpuPush(m, tcos); -} - -static void OpFpatan(struct Machine *m) { - FpuClearRoundup(m); - FpuSetStPop(m, 1, atan2(St1(m), St0(m))); -} - -static void OpFcom(struct Machine *m) { - FpuCompare(m, StRm(m)); -} - -static void OpFcomp(struct Machine *m) { - FpuCompare(m, StRm(m)); - FpuPop(m); -} - -static void OpFaddStEst(struct Machine *m) { - FpuSetSt0(m, FpuAdd(m, St0(m), StRm(m))); -} - -static void OpFmulStEst(struct Machine *m) { - FpuSetSt0(m, FpuMul(m, St0(m), StRm(m))); -} - -static void OpFsubStEst(struct Machine *m) { - FpuSetSt0(m, FpuSub(m, St0(m), StRm(m))); -} - -static void OpFsubrStEst(struct Machine *m) { - FpuSetSt0(m, FpuSub(m, StRm(m), St0(m))); -} - -static void OpFdivStEst(struct Machine *m) { - FpuSetSt0(m, FpuDiv(m, St0(m), StRm(m))); -} - -static void OpFdivrStEst(struct Machine *m) { - FpuSetSt0(m, FpuDiv(m, StRm(m), St0(m))); -} - -static void OpFaddEstSt(struct Machine *m) { - FpuSetStRm(m, FpuAdd(m, StRm(m), St0(m))); -} - -static void OpFmulEstSt(struct Machine *m) { - FpuSetStRm(m, FpuMul(m, StRm(m), St0(m))); -} - -static void OpFsubEstSt(struct Machine *m) { - FpuSetStRm(m, FpuSub(m, St0(m), StRm(m))); -} - -static void OpFsubrEstSt(struct Machine *m) { - FpuSetStRm(m, FpuSub(m, StRm(m), St0(m))); -} - -static void OpFdivEstSt(struct Machine *m) { - FpuSetStRm(m, FpuDiv(m, StRm(m), St0(m))); -} - -static void OpFdivrEstSt(struct Machine *m) { - FpuSetStRm(m, FpuDiv(m, St0(m), StRm(m))); -} - -static void OpFaddp(struct Machine *m) { - FpuSetStRmPop(m, FpuAdd(m, St0(m), StRm(m))); -} - -static void OpFmulp(struct Machine *m) { - FpuSetStRmPop(m, FpuMul(m, St0(m), StRm(m))); -} - -static void OpFcompp(struct Machine *m) { - OpFcomp(m); - FpuPop(m); -} - -static void OpFsubp(struct Machine *m) { - FpuSetStRmPop(m, FpuSub(m, St0(m), StRm(m))); -} - -static void OpFsubrp(struct Machine *m) { - FpuSetStPop(m, 1, FpuSub(m, StRm(m), St0(m))); -} - -static void OpFdivp(struct Machine *m) { - FpuSetStRmPop(m, FpuDiv(m, St0(m), StRm(m))); -} - -static void OpFdivrp(struct Machine *m) { - FpuSetStRmPop(m, FpuDiv(m, StRm(m), St0(m))); -} - -static void OpFadds(struct Machine *m) { - FpuSetSt0(m, FpuAdd(m, St0(m), FpuGetMemoryFloat(m))); -} - -static void OpFmuls(struct Machine *m) { - FpuSetSt0(m, FpuMul(m, St0(m), FpuGetMemoryFloat(m))); -} - -static void OpFcoms(struct Machine *m) { - FpuCompare(m, FpuGetMemoryFloat(m)); -} - -static void OpFcomps(struct Machine *m) { - OpFcoms(m); - FpuPop(m); -} - -static void OpFsubs(struct Machine *m) { - FpuSetSt0(m, FpuSub(m, St0(m), FpuGetMemoryFloat(m))); -} - -static void OpFsubrs(struct Machine *m) { - FpuSetSt0(m, FpuSub(m, FpuGetMemoryFloat(m), St0(m))); -} - -static void OpFdivs(struct Machine *m) { - FpuSetSt0(m, FpuDiv(m, St0(m), FpuGetMemoryFloat(m))); -} - -static void OpFdivrs(struct Machine *m) { - FpuSetSt0(m, FpuDiv(m, FpuGetMemoryFloat(m), St0(m))); -} - -static void OpFaddl(struct Machine *m) { - FpuSetSt0(m, FpuAdd(m, St0(m), FpuGetMemoryDouble(m))); -} - -static void OpFmull(struct Machine *m) { - FpuSetSt0(m, FpuMul(m, St0(m), FpuGetMemoryDouble(m))); -} - -static void OpFcoml(struct Machine *m) { - FpuCompare(m, FpuGetMemoryDouble(m)); -} - -static void OpFcompl(struct Machine *m) { - FpuCompare(m, FpuGetMemoryDouble(m)); - FpuPop(m); -} - -static void OpFsubl(struct Machine *m) { - FpuSetSt0(m, FpuSub(m, St0(m), FpuGetMemoryDouble(m))); -} - -static void OpFsubrl(struct Machine *m) { - FpuSetSt0(m, FpuSub(m, FpuGetMemoryDouble(m), St0(m))); -} - -static void OpFdivl(struct Machine *m) { - FpuSetSt0(m, FpuDiv(m, St0(m), FpuGetMemoryDouble(m))); -} - -static void OpFdivrl(struct Machine *m) { - FpuSetSt0(m, FpuDiv(m, FpuGetMemoryDouble(m), St0(m))); -} - -static void OpFiaddl(struct Machine *m) { - FpuSetSt0(m, FpuAdd(m, St0(m), FpuGetMemoryInt(m))); -} - -static void OpFimull(struct Machine *m) { - FpuSetSt0(m, FpuMul(m, St0(m), FpuGetMemoryInt(m))); -} - -static void OpFicoml(struct Machine *m) { - FpuCompare(m, FpuGetMemoryInt(m)); -} - -static void OpFicompl(struct Machine *m) { - OpFicoml(m); - FpuPop(m); -} - -static void OpFisubl(struct Machine *m) { - FpuSetSt0(m, FpuSub(m, St0(m), FpuGetMemoryInt(m))); -} - -static void OpFisubrl(struct Machine *m) { - FpuSetSt0(m, FpuSub(m, FpuGetMemoryInt(m), St0(m))); -} - -static void OpFidivl(struct Machine *m) { - FpuSetSt0(m, FpuDiv(m, St0(m), FpuGetMemoryInt(m))); -} - -static void OpFidivrl(struct Machine *m) { - FpuSetSt0(m, FpuDiv(m, FpuGetMemoryInt(m), St0(m))); -} - -static void OpFiadds(struct Machine *m) { - FpuSetSt0(m, FpuAdd(m, St0(m), FpuGetMemoryShort(m))); -} - -static void OpFimuls(struct Machine *m) { - FpuSetSt0(m, FpuMul(m, St0(m), FpuGetMemoryShort(m))); -} - -static void OpFicoms(struct Machine *m) { - FpuCompare(m, FpuGetMemoryShort(m)); -} - -static void OpFicomps(struct Machine *m) { - OpFicoms(m); - FpuPop(m); -} - -static void OpFisubs(struct Machine *m) { - FpuSetSt0(m, FpuSub(m, St0(m), FpuGetMemoryShort(m))); -} - -static void OpFisubrs(struct Machine *m) { - FpuSetSt0(m, FpuSub(m, FpuGetMemoryShort(m), St0(m))); -} - -static void OpFidivs(struct Machine *m) { - FpuSetSt0(m, FpuDiv(m, St0(m), FpuGetMemoryShort(m))); -} - -static void OpFidivrs(struct Machine *m) { - FpuSetSt0(m, FpuDiv(m, FpuGetMemoryShort(m), St0(m))); -} - -static void OpFsqrt(struct Machine *m) { - FpuClearRoundup(m); - FpuSetSt0(m, sqrt(St0(m))); -} - -static void OpFrndint(struct Machine *m) { - FpuSetSt0(m, FpuRound(m, St0(m))); -} - -static void OpFscale(struct Machine *m) { - FpuClearRoundup(m); - FpuSetSt0(m, fscale(St0(m), St1(m))); -} - -static void OpFprem(struct Machine *m) { - FpuSetSt0(m, fprem(St0(m), St1(m), &m->fpu.sw)); -} - -static void OpFprem1(struct Machine *m) { - FpuSetSt0(m, fprem1(St0(m), St1(m), &m->fpu.sw)); -} - -static void OpFdecstp(struct Machine *m) { - m->fpu.sw = (m->fpu.sw & ~kFpuSwSp) | ((m->fpu.sw - (1 << 11)) & kFpuSwSp); -} - -static void OpFincstp(struct Machine *m) { - m->fpu.sw = (m->fpu.sw & ~kFpuSwSp) | ((m->fpu.sw + (1 << 11)) & kFpuSwSp); -} - -static void OpFxtract(struct Machine *m) { - double x = St0(m); - FpuSetSt0(m, logb(x)); - FpuPush(m, ldexp(x, -ilogb(x))); -} - -static void OpFld(struct Machine *m) { - FpuPush(m, StRm(m)); -} - -static void OpFlds(struct Machine *m) { - FpuPush(m, FpuGetMemoryFloat(m)); -} - -static void OpFsts(struct Machine *m) { - FpuSetMemoryFloat(m, St0(m)); -} - -static void OpFstps(struct Machine *m) { - OpFsts(m); - FpuPop(m); -} - -static void OpFstpt(struct Machine *m) { - FpuSetMemoryLdbl(m, FpuPop(m)); -} - -static void OpFstl(struct Machine *m) { - FpuSetMemoryDouble(m, St0(m)); -} - -static void OpFstpl(struct Machine *m) { - OpFstl(m); - FpuPop(m); -} - -static void OpFst(struct Machine *m) { - FpuSetStRm(m, St0(m)); -} - -static void OpFstp(struct Machine *m) { - FpuSetStRmPop(m, St0(m)); -} - -static void OpFxch(struct Machine *m) { - double t = StRm(m); - FpuSetStRm(m, St0(m)); - FpuSetSt0(m, t); -} - -static void OpFldcw(struct Machine *m) { - m->fpu.cw = FpuGetMemoryShort(m); -} - -static void OpFldt(struct Machine *m) { - FpuPush(m, FpuGetMemoryLdbl(m)); -} - -static void OpFldl(struct Machine *m) { - FpuPush(m, FpuGetMemoryDouble(m)); -} - -static double Fld1(void) { - return 1; -} - -static double Fldl2t(void) { - return 0xd.49a784bcd1b8afep-2L; /* log₂10 */ -} - -static double Fldl2e(void) { - return 0xb.8aa3b295c17f0bcp-3L; /* log₂𝑒 */ -} - -static double Fldpi(void) { - return 0x1.921fb54442d1846ap+1L; /* π */ -} - -static double Fldlg2(void) { - return 0x9.a209a84fbcff799p-5L; /* log₁₀2 */ -} - -static double Fldln2(void) { - return 0xb.17217f7d1cf79acp-4L; /* logₑ2 */ -} - -static double Fldz(void) { - return 0; -} - -static void OpFldConstant(struct Machine *m) { - double x; - switch (ModrmRm(m->xedd->op.rde)) { - CASE(0, x = Fld1()); - CASE(1, x = Fldl2t()); - CASE(2, x = Fldl2e()); - CASE(3, x = Fldpi()); - CASE(4, x = Fldlg2()); - CASE(5, x = Fldln2()); - CASE(6, x = Fldz()); - default: - OpUd(m, m->xedd->op.rde); - } - FpuPush(m, x); -} - -static void OpFstcw(struct Machine *m) { - FpuSetMemoryShort(m, m->fpu.cw); -} - -static void OpFilds(struct Machine *m) { - FpuPush(m, FpuGetMemoryShort(m)); -} - -static void OpFildl(struct Machine *m) { - FpuPush(m, FpuGetMemoryInt(m)); -} - -static void OpFildll(struct Machine *m) { - FpuPush(m, FpuGetMemoryLong(m)); -} - -static void OpFisttpl(struct Machine *m) { - FpuSetMemoryInt(m, FpuPop(m)); -} - -static void OpFisttpll(struct Machine *m) { - FpuSetMemoryLong(m, FpuPop(m)); -} - -static void OpFisttps(struct Machine *m) { - FpuSetMemoryShort(m, FpuPop(m)); -} - -static void OpFists(struct Machine *m) { - FpuSetMemoryShort(m, FpuRound(m, St0(m))); -} - -static void OpFistl(struct Machine *m) { - FpuSetMemoryInt(m, FpuRound(m, St0(m))); -} - -static void OpFistll(struct Machine *m) { - FpuSetMemoryLong(m, FpuRound(m, St0(m))); -} - -static void OpFistpl(struct Machine *m) { - OpFistl(m); - FpuPop(m); -} - -static void OpFistpll(struct Machine *m) { - OpFistll(m); - FpuPop(m); -} - -static void OpFistps(struct Machine *m) { - OpFists(m); - FpuPop(m); -} - -static void OpFcomi(struct Machine *m) { - double x, y; - x = St0(m); - y = StRm(m); - if (!isunordered(x, y)) { - m->flags = SetFlag(m->flags, FLAGS_ZF, x == y); - m->flags = SetFlag(m->flags, FLAGS_CF, x < y); - m->flags = SetFlag(m->flags, FLAGS_PF, false); - } else { - m->fpu.sw |= kFpuSwIe; - m->flags = SetFlag(m->flags, FLAGS_ZF, true); - m->flags = SetFlag(m->flags, FLAGS_CF, true); - m->flags = SetFlag(m->flags, FLAGS_PF, true); - } -} - -static void OpFucom(struct Machine *m) { - FpuCompare(m, StRm(m)); -} - -static void OpFucomp(struct Machine *m) { - FpuCompare(m, StRm(m)); - FpuPop(m); -} - -static void OpFcomip(struct Machine *m) { - OpFcomi(m); - FpuPop(m); -} - -static void OpFucomi(struct Machine *m) { - OpFcomi(m); -} - -static void OpFucomip(struct Machine *m) { - OpFcomip(m); -} - -static void OpFfree(struct Machine *m) { - FpuSetTag(m, ModrmRm(m->xedd->op.rde), kFpuTagEmpty); -} - -static void OpFfreep(struct Machine *m) { - if (ModrmRm(m->xedd->op.rde)) OpFfree(m); - FpuPop(m); -} - -static void OpFstswMw(struct Machine *m) { - FpuSetMemoryShort(m, m->fpu.sw); -} - -static void OpFstswAx(struct Machine *m) { - Write16(m->ax, m->fpu.sw); -} - -static void SetFpuEnv(struct Machine *m, uint8_t p[28]) { - Write16(p + 0, m->fpu.cw); - Write16(p + 4, m->fpu.sw); - Write16(p + 8, m->fpu.tw); - Write64(p + 12, m->fpu.ip); - Write16(p + 18, m->fpu.op); - Write64(p + 20, m->fpu.dp); -} - -static void GetFpuEnv(struct Machine *m, uint8_t p[28]) { - m->fpu.cw = Read16(p + 0); - m->fpu.sw = Read16(p + 4); - m->fpu.tw = Read16(p + 8); -} - -static void OpFstenv(struct Machine *m) { - void *p[2]; - uint8_t b[28]; - SetFpuEnv(m, BeginStore(m, m->fpu.dp, sizeof(b), p, b)); - EndStore(m, m->fpu.dp, sizeof(b), p, b); -} - -static void OpFldenv(struct Machine *m) { - uint8_t b[28]; - GetFpuEnv(m, Load(m, m->fpu.dp, sizeof(b), b)); -} - -static void OpFsave(struct Machine *m) { - int i; - void *p[2]; - uint8_t *a, b[108], t[16]; - a = BeginStore(m, m->fpu.dp, sizeof(b), p, b); - SetFpuEnv(m, a); - memset(t, 0, sizeof(t)); - for (i = 0; i < 8; ++i) { - SerializeLdbl(a + 28 + i * 10, *FpuSt(m, i)); - } - EndStore(m, m->fpu.dp, sizeof(b), p, b); - OpFinit(m); -} - -static void OpFrstor(struct Machine *m) { - int i; - uint8_t *a, b[108]; - a = Load(m, m->fpu.dp, sizeof(b), b); - GetFpuEnv(m, a); - for (i = 0; i < 8; ++i) { - *FpuSt(m, i) = DeserializeLdbl(a + 28 + i * 10); - } -} - -static void OpFnclex(struct Machine *m) { - m->fpu.sw &= ~(kFpuSwIe | kFpuSwDe | kFpuSwZe | kFpuSwOe | kFpuSwUe | - kFpuSwPe | kFpuSwEs | kFpuSwSf | kFpuSwBf); -} - -static void OpFnop(struct Machine *m) { - /* do nothing */ -} - -void OpFinit(struct Machine *m) { - m->fpu.cw = 0x037f; - m->fpu.sw = 0; - m->fpu.tw = -1; -} - -void OpFwait(struct Machine *m, uint32_t rde) { - int sw, cw; - sw = m->fpu.sw; - cw = m->fpu.cw; - if (((sw & kFpuSwIe) && !(cw & kFpuCwIm)) || - ((sw & kFpuSwDe) && !(cw & kFpuCwDm)) || - ((sw & kFpuSwZe) && !(cw & kFpuCwZm)) || - ((sw & kFpuSwOe) && !(cw & kFpuCwOm)) || - ((sw & kFpuSwUe) && !(cw & kFpuCwUm)) || - ((sw & kFpuSwPe) && !(cw & kFpuCwPm)) || - ((sw & kFpuSwSf) && !(cw & kFpuCwIm))) { - HaltMachine(m, kMachineFpuException); - } -} - -int FpuGetTag(struct Machine *m, unsigned i) { - unsigned t; - t = m->fpu.tw; - i += (m->fpu.sw & kFpuSwSp) >> 11; - i &= 7; - i *= 2; - t &= 3 << i; - t >>= i; - return t; -} - -void FpuSetTag(struct Machine *m, unsigned i, unsigned t) { - i += (m->fpu.sw & kFpuSwSp) >> 11; - t &= 3; - i &= 7; - i *= 2; - m->fpu.tw &= ~(3 << i); - m->fpu.tw |= t << i; -} - -void FpuPush(struct Machine *m, double x) { - if (FpuGetTag(m, -1) != kFpuTagEmpty) OnFpuStackOverflow(m); - m->fpu.sw = (m->fpu.sw & ~kFpuSwSp) | ((m->fpu.sw - (1 << 11)) & kFpuSwSp); - *FpuSt(m, 0) = x; - FpuSetTag(m, 0, kFpuTagValid); -} - -double FpuPop(struct Machine *m) { - double x; - if (FpuGetTag(m, 0) != kFpuTagEmpty) { - x = *FpuSt(m, 0); - FpuSetTag(m, 0, kFpuTagEmpty); - } else { - x = OnFpuStackUnderflow(m); - } - m->fpu.sw = (m->fpu.sw & ~kFpuSwSp) | ((m->fpu.sw + (1 << 11)) & kFpuSwSp); - return x; -} - -void OpFpu(struct Machine *m, uint32_t rde) { - unsigned op; - bool ismemory; - op = m->xedd->op.opcode & 7; - ismemory = ModrmMod(rde) != 3; - m->fpu.ip = m->ip - m->xedd->length; - m->fpu.op = op << 8 | ModrmMod(rde) << 6 | ModrmReg(rde) << 3 | ModrmRm(rde); - m->fpu.dp = ismemory ? ComputeAddress(m, rde) : 0; - switch (DISP(op, ismemory, ModrmReg(rde))) { - CASE(DISP(0xD8, FPUREG, 0), OpFaddStEst(m)); - CASE(DISP(0xD8, FPUREG, 1), OpFmulStEst(m)); - CASE(DISP(0xD8, FPUREG, 2), OpFcom(m)); - CASE(DISP(0xD8, FPUREG, 3), OpFcomp(m)); - CASE(DISP(0xD8, FPUREG, 4), OpFsubStEst(m)); - CASE(DISP(0xD8, FPUREG, 5), OpFsubrStEst(m)); - CASE(DISP(0xD8, FPUREG, 6), OpFdivStEst(m)); - CASE(DISP(0xD8, FPUREG, 7), OpFdivrStEst(m)); - CASE(DISP(0xD8, MEMORY, 0), OpFadds(m)); - CASE(DISP(0xD8, MEMORY, 1), OpFmuls(m)); - CASE(DISP(0xD8, MEMORY, 2), OpFcoms(m)); - CASE(DISP(0xD8, MEMORY, 3), OpFcomps(m)); - CASE(DISP(0xD8, MEMORY, 4), OpFsubs(m)); - CASE(DISP(0xD8, MEMORY, 5), OpFsubrs(m)); - CASE(DISP(0xD8, MEMORY, 6), OpFdivs(m)); - CASE(DISP(0xD8, MEMORY, 7), OpFdivrs(m)); - CASE(DISP(0xD9, FPUREG, 0), OpFld(m)); - CASE(DISP(0xD9, FPUREG, 1), OpFxch(m)); - CASE(DISP(0xD9, FPUREG, 2), OpFnop(m)); - CASE(DISP(0xD9, FPUREG, 3), OpFstp(m)); - CASE(DISP(0xD9, FPUREG, 5), OpFldConstant(m)); - CASE(DISP(0xD9, MEMORY, 0), OpFlds(m)); - CASE(DISP(0xD9, MEMORY, 2), OpFsts(m)); - CASE(DISP(0xD9, MEMORY, 3), OpFstps(m)); - CASE(DISP(0xD9, MEMORY, 4), OpFldenv(m)); - CASE(DISP(0xD9, MEMORY, 5), OpFldcw(m)); - CASE(DISP(0xD9, MEMORY, 6), OpFstenv(m)); - CASE(DISP(0xD9, MEMORY, 7), OpFstcw(m)); - CASE(DISP(0xDA, FPUREG, 0), OpFcmovb(m)); - CASE(DISP(0xDA, FPUREG, 1), OpFcmove(m)); - CASE(DISP(0xDA, FPUREG, 2), OpFcmovbe(m)); - CASE(DISP(0xDA, FPUREG, 3), OpFcmovu(m)); - CASE(DISP(0xDA, MEMORY, 0), OpFiaddl(m)); - CASE(DISP(0xDA, MEMORY, 1), OpFimull(m)); - CASE(DISP(0xDA, MEMORY, 2), OpFicoml(m)); - CASE(DISP(0xDA, MEMORY, 3), OpFicompl(m)); - CASE(DISP(0xDA, MEMORY, 4), OpFisubl(m)); - CASE(DISP(0xDA, MEMORY, 5), OpFisubrl(m)); - CASE(DISP(0xDA, MEMORY, 6), OpFidivl(m)); - CASE(DISP(0xDA, MEMORY, 7), OpFidivrl(m)); - CASE(DISP(0xDB, FPUREG, 0), OpFcmovnb(m)); - CASE(DISP(0xDB, FPUREG, 1), OpFcmovne(m)); - CASE(DISP(0xDB, FPUREG, 2), OpFcmovnbe(m)); - CASE(DISP(0xDB, FPUREG, 3), OpFcmovnu(m)); - CASE(DISP(0xDB, FPUREG, 5), OpFucomi(m)); - CASE(DISP(0xDB, FPUREG, 6), OpFcomi(m)); - CASE(DISP(0xDB, MEMORY, 0), OpFildl(m)); - CASE(DISP(0xDB, MEMORY, 1), OpFisttpl(m)); - CASE(DISP(0xDB, MEMORY, 2), OpFistl(m)); - CASE(DISP(0xDB, MEMORY, 3), OpFistpl(m)); - CASE(DISP(0xDB, MEMORY, 5), OpFldt(m)); - CASE(DISP(0xDB, MEMORY, 7), OpFstpt(m)); - CASE(DISP(0xDC, FPUREG, 0), OpFaddEstSt(m)); - CASE(DISP(0xDC, FPUREG, 1), OpFmulEstSt(m)); - CASE(DISP(0xDC, FPUREG, 2), OpFcom(m)); - CASE(DISP(0xDC, FPUREG, 3), OpFcomp(m)); - CASE(DISP(0xDC, FPUREG, 4), OpFsubEstSt(m)); - CASE(DISP(0xDC, FPUREG, 5), OpFsubrEstSt(m)); - CASE(DISP(0xDC, FPUREG, 6), OpFdivEstSt(m)); - CASE(DISP(0xDC, FPUREG, 7), OpFdivrEstSt(m)); - CASE(DISP(0xDC, MEMORY, 0), OpFaddl(m)); - CASE(DISP(0xDC, MEMORY, 1), OpFmull(m)); - CASE(DISP(0xDC, MEMORY, 2), OpFcoml(m)); - CASE(DISP(0xDC, MEMORY, 3), OpFcompl(m)); - CASE(DISP(0xDC, MEMORY, 4), OpFsubl(m)); - CASE(DISP(0xDC, MEMORY, 5), OpFsubrl(m)); - CASE(DISP(0xDC, MEMORY, 6), OpFdivl(m)); - CASE(DISP(0xDC, MEMORY, 7), OpFdivrl(m)); - CASE(DISP(0xDD, FPUREG, 0), OpFfree(m)); - CASE(DISP(0xDD, FPUREG, 1), OpFxch(m)); - CASE(DISP(0xDD, FPUREG, 2), OpFst(m)); - CASE(DISP(0xDD, FPUREG, 3), OpFstp(m)); - CASE(DISP(0xDD, FPUREG, 4), OpFucom(m)); - CASE(DISP(0xDD, FPUREG, 5), OpFucomp(m)); - CASE(DISP(0xDD, MEMORY, 0), OpFldl(m)); - CASE(DISP(0xDD, MEMORY, 1), OpFisttpll(m)); - CASE(DISP(0xDD, MEMORY, 2), OpFstl(m)); - CASE(DISP(0xDD, MEMORY, 3), OpFstpl(m)); - CASE(DISP(0xDD, MEMORY, 4), OpFrstor(m)); - CASE(DISP(0xDD, MEMORY, 6), OpFsave(m)); - CASE(DISP(0xDD, MEMORY, 7), OpFstswMw(m)); - CASE(DISP(0xDE, FPUREG, 0), OpFaddp(m)); - CASE(DISP(0xDE, FPUREG, 1), OpFmulp(m)); - CASE(DISP(0xDE, FPUREG, 2), OpFcomp(m)); - CASE(DISP(0xDE, FPUREG, 3), OpFcompp(m)); - CASE(DISP(0xDE, FPUREG, 4), OpFsubp(m)); - CASE(DISP(0xDE, FPUREG, 5), OpFsubrp(m)); - CASE(DISP(0xDE, FPUREG, 6), OpFdivp(m)); - CASE(DISP(0xDE, FPUREG, 7), OpFdivrp(m)); - CASE(DISP(0xDE, MEMORY, 0), OpFiadds(m)); - CASE(DISP(0xDE, MEMORY, 1), OpFimuls(m)); - CASE(DISP(0xDE, MEMORY, 2), OpFicoms(m)); - CASE(DISP(0xDE, MEMORY, 3), OpFicomps(m)); - CASE(DISP(0xDE, MEMORY, 4), OpFisubs(m)); - CASE(DISP(0xDE, MEMORY, 5), OpFisubrs(m)); - CASE(DISP(0xDE, MEMORY, 6), OpFidivs(m)); - CASE(DISP(0xDE, MEMORY, 7), OpFidivrs(m)); - CASE(DISP(0xDF, FPUREG, 0), OpFfreep(m)); - CASE(DISP(0xDF, FPUREG, 1), OpFxch(m)); - CASE(DISP(0xDF, FPUREG, 2), OpFstp(m)); - CASE(DISP(0xDF, FPUREG, 3), OpFstp(m)); - CASE(DISP(0xDF, FPUREG, 4), OpFstswAx(m)); - CASE(DISP(0xDF, FPUREG, 5), OpFucomip(m)); - CASE(DISP(0xDF, FPUREG, 6), OpFcomip(m)); - CASE(DISP(0xDF, MEMORY, 0), OpFilds(m)); - CASE(DISP(0xDF, MEMORY, 1), OpFisttps(m)); - CASE(DISP(0xDF, MEMORY, 2), OpFists(m)); - CASE(DISP(0xDF, MEMORY, 3), OpFistps(m)); - CASE(DISP(0xDF, MEMORY, 5), OpFildll(m)); - CASE(DISP(0xDF, MEMORY, 7), OpFistpll(m)); - case DISP(0xD9, FPUREG, 4): - switch (ModrmRm(rde)) { - CASE(0, OpFchs(m)); - CASE(1, OpFabs(m)); - CASE(4, OpFtst(m)); - CASE(5, OpFxam(m)); - default: - OpUd(m, rde); - } - break; - case DISP(0xD9, FPUREG, 6): - switch (ModrmRm(rde)) { - CASE(0, OpF2xm1(m)); - CASE(1, OpFyl2x(m)); - CASE(2, OpFptan(m)); - CASE(3, OpFpatan(m)); - CASE(4, OpFxtract(m)); - CASE(5, OpFprem1(m)); - CASE(6, OpFdecstp(m)); - CASE(7, OpFincstp(m)); - default: - for (;;) (void)0; - } - break; - case DISP(0xD9, FPUREG, 7): - switch (ModrmRm(rde)) { - CASE(0, OpFprem(m)); - CASE(1, OpFyl2xp1(m)); - CASE(2, OpFsqrt(m)); - CASE(3, OpFsincos(m)); - CASE(4, OpFrndint(m)); - CASE(5, OpFscale(m)); - CASE(6, OpFsin(m)); - CASE(7, OpFcos(m)); - default: - for (;;) (void)0; - } - break; - case DISP(0xDb, FPUREG, 4): - switch (ModrmRm(rde)) { - CASE(2, OpFnclex(m)); - CASE(3, OpFinit(m)); - default: - OpUd(m, rde); - } - break; - default: - OpUd(m, rde); - } -} diff --git a/tool/build/lib/fpu.h b/tool/build/lib/fpu.h deleted file mode 100644 index 48c6fb1e1..000000000 --- a/tool/build/lib/fpu.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_FPU_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_FPU_H_ -#include "tool/build/lib/machine.h" - -#define kFpuTagValid 0b00 -#define kFpuTagZero 0b01 -#define kFpuTagSpecial 0b10 -#define kFpuTagEmpty 0b11 - -#define kFpuCwIm 0x0001 /* invalid operation mask */ -#define kFpuCwDm 0x0002 /* denormal operand mask */ -#define kFpuCwZm 0x0004 /* zero divide mask */ -#define kFpuCwOm 0x0008 /* overflow mask */ -#define kFpuCwUm 0x0010 /* underflow mask */ -#define kFpuCwPm 0x0020 /* precision mask */ -#define kFpuCwPc 0x0300 /* precision: 32,∅,64,80 */ -#define kFpuCwRc 0x0c00 /* rounding: even,→-∞,→+∞,→0 */ - -#define kFpuSwIe 0x0001 /* invalid operation */ -#define kFpuSwDe 0x0002 /* denormalized operand */ -#define kFpuSwZe 0x0004 /* zero divide */ -#define kFpuSwOe 0x0008 /* overflow */ -#define kFpuSwUe 0x0010 /* underflow */ -#define kFpuSwPe 0x0020 /* precision */ -#define kFpuSwSf 0x0040 /* stack fault */ -#define kFpuSwEs 0x0080 /* exception summary status */ -#define kFpuSwC0 0x0100 /* condition 0 */ -#define kFpuSwC1 0x0200 /* condition 1 */ -#define kFpuSwC2 0x0400 /* condition 2 */ -#define kFpuSwSp 0x3800 /* top stack */ -#define kFpuSwC3 0x4000 /* condition 3 */ -#define kFpuSwBf 0x8000 /* busy flag */ - -#define kMxcsrIe 0x0001 /* invalid operation flag */ -#define kMxcsrDe 0x0002 /* denormal flag */ -#define kMxcsrZe 0x0004 /* divide by zero flag */ -#define kMxcsrOe 0x0008 /* overflow flag */ -#define kMxcsrUe 0x0010 /* underflow flag */ -#define kMxcsrPe 0x0020 /* precision flag */ -#define kMxcsrDaz 0x0040 /* denormals are zeros */ -#define kMxcsrIm 0x0080 /* invalid operation mask */ -#define kMxcsrDm 0x0100 /* denormal mask */ -#define kMxcsrZm 0x0200 /* divide by zero mask */ -#define kMxcsrOm 0x0400 /* overflow mask */ -#define kMxcsrUm 0x0800 /* underflow mask */ -#define kMxcsrPm 0x1000 /* precision mask */ -#define kMxcsrRc 0x6000 /* rounding control */ -#define kMxcsrFtz 0x8000 /* flush to zero */ - -#define FpuSt(m, i) ((m)->fpu.st + (((i) + ((m->fpu.sw & kFpuSwSp) >> 11)) & 7)) - -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -double FpuPop(struct Machine *); -int FpuGetTag(struct Machine *, unsigned); -void FpuPush(struct Machine *, double); -void FpuSetTag(struct Machine *, unsigned, unsigned); -void OpFinit(struct Machine *); -void OpFpu(struct Machine *, uint32_t); -void OpFwait(struct Machine *, uint32_t); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_FPU_H_ */ diff --git a/tool/build/lib/high.c b/tool/build/lib/high.c deleted file mode 100644 index f81801223..000000000 --- a/tool/build/lib/high.c +++ /dev/null @@ -1,41 +0,0 @@ -/*-*- 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/fmt/itoa.h" -#include "libc/str/str.h" -#include "tool/build/lib/high.h" - -struct High g_high; - -char *HighStart(char *p, int h) { - if (h) { - p = stpcpy(p, "\e[38;5;"); - p = FormatUint32(p, h); - p = stpcpy(p, "m"); - g_high.active = true; - } - return p; -} - -char *HighEnd(char *p) { - if (g_high.active) { - p = stpcpy(p, "\e[39m"); - g_high.active = false; - } - return p; -} diff --git a/tool/build/lib/high.h b/tool/build/lib/high.h deleted file mode 100644 index 4d3f5730b..000000000 --- a/tool/build/lib/high.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_HIGH_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_HIGH_H_ -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -struct High { - bool active; - uint8_t keyword; - uint8_t reg; - uint8_t literal; - uint8_t label; - uint8_t comment; - uint8_t quote; -}; - -extern struct High g_high; - -char *HighStart(char *, int); -char *HighEnd(char *); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_HIGH_H_ */ diff --git a/tool/build/lib/instruction.c b/tool/build/lib/instruction.c deleted file mode 100644 index 76e5751f1..000000000 --- a/tool/build/lib/instruction.c +++ /dev/null @@ -1,92 +0,0 @@ -/*-*- 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/intrin/bsf.h" -#include "libc/macros.internal.h" -#include "libc/str/str.h" -#include "third_party/xed/x86.h" -#include "tool/build/lib/address.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/machine.h" -#include "tool/build/lib/memory.h" -#include "tool/build/lib/modrm.h" -#include "tool/build/lib/stats.h" -#include "tool/build/lib/throw.h" - -static bool IsOpcodeEqual(struct XedDecodedInst *xedd, uint8_t *a) { - uint64_t w; - if (xedd->length) { - if (xedd->length <= 7) { - w = Read64(a) ^ Read64(xedd->bytes); - return !w || _bsfl(w) >= (xedd->length << 3); - } else { - return memcmp(a, xedd->bytes, xedd->length) == 0; - } - } else { - return false; - } -} - -static void DecodeInstruction(struct Machine *m, uint8_t *p, unsigned n) { - struct XedDecodedInst xedd[1]; - xed_decoded_inst_zero_set_mode(xedd, m->mode); - if (!xed_instruction_length_decode(xedd, p, n)) { - xedd->op.rde = EncodeRde(xedd); - memcpy(m->xedd, xedd, sizeof(m->icache[0])); - } else { - HaltMachine(m, kMachineDecodeError); - } -} - -static dontinline void LoadInstructionSlow(struct Machine *m, uint64_t ip) { - unsigned i; - uint8_t *addr; - uint8_t copy[15], *toil; - i = 0x1000 - (ip & 0xfff); - addr = ResolveAddress(m, ip); - if ((toil = FindReal(m, ip + i))) { - memcpy(copy, addr, i); - memcpy(copy + i, toil, 15 - i); - DecodeInstruction(m, copy, 15); - } else { - DecodeInstruction(m, addr, i); - } -} - -void LoadInstruction(struct Machine *m) { - uint64_t ip; - unsigned key; - uint8_t *addr; - ip = Read64(m->cs) + MaskAddress(m->mode & 3, m->ip); - key = ip & (ARRAYLEN(m->icache) - 1); - m->xedd = (struct XedDecodedInst *)m->icache[key]; - if ((ip & 0xfff) < 0x1000 - 15) { - if (ip - (ip & 0xfff) == m->codevirt && m->codehost) { - addr = m->codehost + (ip & 0xfff); - } else { - m->codevirt = ip - (ip & 0xfff); - m->codehost = ResolveAddress(m, m->codevirt); - addr = m->codehost + (ip & 0xfff); - } - if (!IsOpcodeEqual(m->xedd, addr)) { - DecodeInstruction(m, addr, 15); - } - } else { - LoadInstructionSlow(m, ip); - } -} diff --git a/tool/build/lib/ioports.c b/tool/build/lib/ioports.c deleted file mode 100644 index 396835b6b..000000000 --- a/tool/build/lib/ioports.c +++ /dev/null @@ -1,115 +0,0 @@ -/*-*- 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/nexgen32e/uart.internal.h" -#include "libc/sysv/consts/fileno.h" -#include "libc/sysv/consts/poll.h" -#include "tool/build/lib/ioports.h" - -static int OpE9Read(struct Machine *m) { - int fd; - uint8_t b; - fd = STDIN_FILENO; - if (fd >= m->fds.i) return -1; - if (!m->fds.p[fd].cb) return -1; - if (m->fds.p[fd].cb->readv(m->fds.p[fd].fd, &(struct iovec){&b, 1}, 1) == 1) { - return b; - } else { - return -1; - } -} - -static void OpE9Write(struct Machine *m, uint8_t b) { - int fd; - fd = STDOUT_FILENO; - if (fd >= m->fds.i) return; - if (!m->fds.p[fd].cb) return; - m->fds.p[fd].cb->writev(m->fds.p[fd].fd, &(struct iovec){&b, 1}, 1); -} - -static int OpE9Poll(struct Machine *m) { - int fd, rc; - struct pollfd pf; - fd = STDIN_FILENO; - if (fd >= m->fds.i) return -1; - if (!m->fds.p[fd].cb) return -1; - pf.fd = m->fds.p[fd].fd; - pf.events = POLLIN | POLLOUT; - rc = m->fds.p[fd].cb->poll(&pf, 1, 20); - if (rc <= 0) return rc; - return pf.revents; -} - -static int OpSerialIn(struct Machine *m, int r) { - int p, s; - switch (r) { - case UART_DLL: - if (!m->dlab) { - return OpE9Read(m); - } else { - return 0x01; - } - case UART_LSR: - if ((p = OpE9Poll(m)) == -1) return -1; - s = UART_TTYIDL; - if (p & POLLIN) s |= UART_TTYDA; - if (p & POLLOUT) s |= UART_TTYTXR; - return s; - default: - return 0; - } -} - -static void OpSerialOut(struct Machine *m, int r, uint32_t x) { - switch (r) { - case UART_DLL: - if (!m->dlab) { - return OpE9Write(m, x); - } - break; - case UART_LCR: - m->dlab = !!(x & UART_DLAB); - break; - default: - break; - } -} - -uint64_t OpIn(struct Machine *m, uint16_t p) { - switch (p) { - case 0xE9: - return OpE9Read(m); - case 0x3F8 ... 0x3FF: - return OpSerialIn(m, p - 0x3F8); - default: - return -1; - } -} - -void OpOut(struct Machine *m, uint16_t p, uint32_t x) { - switch (p) { - case 0xE9: - OpE9Write(m, x); - break; - case 0x3F8 ... 0x3FF: - OpSerialOut(m, p - 0x3F8, x); - break; - default: - break; - } -} diff --git a/tool/build/lib/ioports.h b/tool/build/lib/ioports.h deleted file mode 100644 index e045da03a..000000000 --- a/tool/build/lib/ioports.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_IOPORTS_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_IOPORTS_H_ -#include "tool/build/lib/machine.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -uint64_t OpIn(struct Machine *, uint16_t); -void OpOut(struct Machine *, uint16_t, uint32_t); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_IOPORTS_H_ */ diff --git a/tool/build/lib/iovs.c b/tool/build/lib/iovs.c deleted file mode 100644 index b5ef19a5b..000000000 --- a/tool/build/lib/iovs.c +++ /dev/null @@ -1,66 +0,0 @@ -/*-*- 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/macros.internal.h" -#include "libc/mem/mem.h" -#include "libc/str/str.h" -#include "tool/build/lib/iovs.h" - -void InitIovs(struct Iovs *ib) { - ib->p = ib->init; - ib->i = 0; - ib->n = ARRAYLEN(ib->init); -} - -void FreeIovs(struct Iovs *ib) { - if (ib->p != ib->init) { - free(ib->p); - } -} - -/** - * Appends memory region to i/o vector builder. - */ -int AppendIovs(struct Iovs *ib, void *base, size_t len) { - unsigned i, n; - struct iovec *p; - if (len) { - p = ib->p; - i = ib->i; - n = ib->n; - if (i && (intptr_t)base == (intptr_t)p[i - 1].iov_base + p[i - 1].iov_len) { - p[i - 1].iov_len += len; - } else { - if (__builtin_expect(i == n, 0)) { - n += n >> 1; - if (p == ib->init) { - if (!(p = malloc(sizeof(struct iovec) * n))) return -1; - memcpy(p, ib->init, sizeof(ib->init)); - } else { - if (!(p = realloc(p, sizeof(struct iovec) * n))) return -1; - } - ib->p = p; - ib->n = n; - } - p[i].iov_base = base; - p[i].iov_len = len; - ++ib->i; - } - } - return 0; -} diff --git a/tool/build/lib/iovs.h b/tool/build/lib/iovs.h deleted file mode 100644 index a22e667d8..000000000 --- a/tool/build/lib/iovs.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_IOVS_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_IOVS_H_ -#include "libc/calls/struct/iovec.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -struct Iovs { - struct iovec *p; - unsigned i, n; - struct iovec init[2]; -}; - -void InitIovs(struct Iovs *); -void FreeIovs(struct Iovs *); -int AppendIovs(struct Iovs *, void *, size_t); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_IOVS_H_ */ diff --git a/tool/build/lib/ldbl.c b/tool/build/lib/ldbl.c deleted file mode 100644 index 3d4339805..000000000 --- a/tool/build/lib/ldbl.c +++ /dev/null @@ -1,49 +0,0 @@ -/*-*- 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 2022 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/macros.internal.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/ldbl.h" -#include "tool/build/lib/pun.h" - -uint8_t *SerializeLdbl(uint8_t b[10], double f) { - int e; - union DoublePun u = {f}; - e = (u.i >> 52) & 0x7ff; - if (!e) { - e = 0; - } else if (e == 0x7ff) { - e = 0x7fff; - } else { - e -= 0x3ff; - e += 0x3fff; - } - Write16(b + 8, e | u.i >> 63 << 15); - Write64(b, (u.i & 0x000fffffffffffff) << 11 | (uint64_t) !!u.f << 63); - return b; -} - -double DeserializeLdbl(const uint8_t b[10]) { - union DoublePun u; - u.i = (uint64_t)(MAX(-1023, MIN(1024, ((Read16(b + 8) & 0x7fff) - 0x3fff))) + - 1023) - << 52 | - ((Read64(b) & 0x7fffffffffffffff) + (1 << (11 - 1))) >> 11 | - (uint64_t)(b[9] >> 7) << 63; - return u.f; -} diff --git a/tool/build/lib/ldbl.h b/tool/build/lib/ldbl.h deleted file mode 100644 index 656046945..000000000 --- a/tool/build/lib/ldbl.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_LDBL_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_LDBL_H_ -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -double DeserializeLdbl(const uint8_t[10]); -uint8_t *SerializeLdbl(uint8_t[10], double); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_LDBL_H_ */ diff --git a/tool/build/lib/loader.c b/tool/build/lib/loader.c deleted file mode 100644 index 2282cc62b..000000000 --- a/tool/build/lib/loader.c +++ /dev/null @@ -1,227 +0,0 @@ -/*-*- 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 "tool/build/lib/loader.h" -#include "libc/calls/calls.h" -#include "libc/calls/struct/stat.h" -#include "libc/elf/elf.h" -#include "libc/elf/struct/phdr.h" -#include "libc/intrin/bits.h" -#include "libc/intrin/popcnt.h" -#include "libc/log/check.h" -#include "libc/log/log.h" -#include "libc/runtime/pc.internal.h" -#include "libc/runtime/runtime.h" -#include "libc/stdio/stdio.h" -#include "libc/str/str.h" -#include "libc/sysv/consts/map.h" -#include "libc/sysv/consts/o.h" -#include "libc/sysv/consts/prot.h" -#include "third_party/xed/x86.h" -#include "tool/build/lib/argv.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/machine.h" -#include "tool/build/lib/memory.h" - -static void LoadElfLoadSegment(struct Machine *m, void *code, size_t codesize, - Elf64_Phdr *phdr) { - void *rbss; - int64_t align, bsssize; - int64_t felf, fstart, fend, vstart, vbss, vend; - align = MAX(phdr->p_align, PAGESIZE); - if (popcnt(align) != 1) align = 8; - CHECK_EQ(0, (phdr->p_vaddr - phdr->p_offset) % align); - felf = (int64_t)(intptr_t)code; - vstart = ROUNDDOWN(phdr->p_vaddr, align); - vbss = ROUNDUP(phdr->p_vaddr + phdr->p_filesz, align); - vend = ROUNDUP(phdr->p_vaddr + phdr->p_memsz, align); - fstart = felf + ROUNDDOWN(phdr->p_offset, align); - fend = felf + phdr->p_offset + phdr->p_filesz; - bsssize = vend - vbss; - VERBOSEF("LOADELFLOADSEGMENT" - " VSTART %#lx VBSS %#lx VEND %#lx" - " FSTART %#lx FEND %#lx BSSSIZE %#lx", - vstart, vbss, vend, fstart, fend, bsssize); - m->brk = MAX(m->brk, vend); - CHECK_GE(vend, vstart); - CHECK_GE(fend, fstart); - CHECK_LE(felf, fstart); - CHECK_GE(vstart, -0x800000000000); - CHECK_LE(vend, 0x800000000000); - CHECK_GE(vend - vstart, fstart - fend); - CHECK_LE(phdr->p_filesz, phdr->p_memsz); - CHECK_EQ(felf + phdr->p_offset - fstart, phdr->p_vaddr - vstart); - CHECK_NE(-1, ReserveVirtual(m, vstart, fend - fstart, - PAGE_V | PAGE_RW | PAGE_U | PAGE_RSRV)); - VirtualRecv(m, vstart, (void *)fstart, fend - fstart); - if (bsssize) - CHECK_NE(-1, ReserveVirtual(m, vbss, bsssize, - PAGE_V | PAGE_RW | PAGE_U | PAGE_RSRV)); - if (phdr->p_memsz - phdr->p_filesz > bsssize) { - VirtualSet(m, phdr->p_vaddr + phdr->p_filesz, 0, - phdr->p_memsz - phdr->p_filesz - bsssize); - } -} - -static void LoadElf(struct Machine *m, struct Elf *elf) { - unsigned i; - Elf64_Phdr *phdr; - m->ip = elf->base = 0x400000 /* elf->ehdr->e_entry */; - VERBOSEF("LOADELF ENTRY %012lx", m->ip); - for (i = 0; i < elf->ehdr->e_phnum; ++i) { - phdr = GetElfSegmentHeaderAddress(elf->ehdr, elf->size, i); - switch (phdr->p_type) { - case PT_LOAD: - elf->base = MIN(elf->base, phdr->p_vaddr); - LoadElfLoadSegment(m, elf->ehdr, elf->size, phdr); - break; - default: - break; - } - } -} - -static void LoadBin(struct Machine *m, intptr_t base, const char *prog, - void *code, size_t codesize) { - Elf64_Phdr phdr = { - .p_type = PT_LOAD, - .p_flags = PF_X | PF_R | PF_W, - .p_offset = 0, - .p_vaddr = base, - .p_paddr = base, - .p_filesz = codesize, - .p_memsz = ROUNDUP(codesize + FRAMESIZE, 0x200000), - .p_align = PAGESIZE, - }; - LoadElfLoadSegment(m, code, codesize, &phdr); - m->ip = base; -} - -static void BootProgram(struct Machine *m, struct Elf *elf, size_t codesize) { - m->ip = 0x7c00; - elf->base = 0x7c00; - CHECK_NE(-1, ReserveReal(m, 0x00f00000)); - bzero(m->real.p, 0x00f00000); - Write16(m->real.p + 0x400, 0x3F8); - Write16(m->real.p + 0x40E, 0xb0000 >> 4); - Write16(m->real.p + 0x413, 0xb0000 / 1024); - Write16(m->real.p + 0x44A, 80); - Write64(m->cs, 0); - Write64(m->dx, 0); - memcpy(m->real.p + 0x7c00, elf->map, 512); - if (memcmp(elf->map, "\177ELF", 4) == 0) { - elf->ehdr = (void *)elf->map; - elf->size = codesize; - elf->base = elf->ehdr->e_entry; - } else { - elf->base = 0x7c00; - elf->ehdr = NULL; - elf->size = 0; - } -} - -static int GetElfHeader(char ehdr[hasatleast 64], const char *prog, - const char *image) { - char *p; - int c, i; - for (p = image; p < image + 4096; ++p) { - if (READ64LE(p) != READ64LE("printf '")) continue; - for (i = 0, p += 8; p + 3 < image + 4096 && (c = *p++) != '\'';) { - if (c == '\\') { - if ('0' <= *p && *p <= '7') { - c = *p++ - '0'; - if ('0' <= *p && *p <= '7') { - c *= 8; - c += *p++ - '0'; - if ('0' <= *p && *p <= '7') { - c *= 8; - c += *p++ - '0'; - } - } - } - } - if (i < 64) { - ehdr[i++] = c; - } else { - WARNF("%s: ape printf elf header too long\n", prog); - return -1; - } - } - if (i != 64) { - WARNF("%s: ape printf elf header too short\n", prog); - return -1; - } - if (READ32LE(ehdr) != READ32LE("\177ELF")) { - WARNF("%s: ape printf elf header didn't have elf magic\n", prog); - return -1; - } - return 0; - } - WARNF("%s: printf statement not found in first 4096 bytes\n", prog); - return -1; -} - -void LoadProgram(struct Machine *m, const char *prog, char **args, char **vars, - struct Elf *elf) { - int fd; - ssize_t rc; - int64_t sp; - char ehdr[64]; - struct stat st; - size_t i, mappedsize; - DCHECK_NOTNULL(prog); - elf->prog = prog; - if ((fd = open(prog, O_RDONLY)) == -1 || - (fstat(fd, &st) == -1 || !st.st_size)) { - fputs(prog, stderr); - fputs(": not found\n", stderr); - exit(1); - } - elf->mapsize = st.st_size; - CHECK_NE(MAP_FAILED, - (elf->map = mmap(NULL, elf->mapsize, PROT_READ | PROT_WRITE, - MAP_PRIVATE, fd, 0))); - CHECK_NE(-1, close(fd)); - ResetCpu(m); - if ((m->mode & 3) == XED_MODE_REAL) { - BootProgram(m, elf, elf->mapsize); - } else { - sp = 0x800000000000; - Write64(m->sp, sp); - m->cr3 = AllocateLinearPage(m); - CHECK_NE(-1, ReserveVirtual(m, sp - 0x800000, 0x800000, - PAGE_V | PAGE_RW | PAGE_U | PAGE_RSRV)); - LoadArgv(m, prog, args, vars); - if (memcmp(elf->map, "\177ELF", 4) == 0) { - elf->ehdr = (void *)elf->map; - elf->size = elf->mapsize; - LoadElf(m, elf); - } else if (READ64LE(elf->map) == READ64LE("MZqFpD='") && - !GetElfHeader(ehdr, prog, elf->map)) { - memcpy(elf->map, ehdr, 64); - elf->ehdr = (void *)elf->map; - elf->size = elf->mapsize; - LoadElf(m, elf); - } else { - elf->base = IMAGE_BASE_VIRTUAL; - elf->ehdr = NULL; - elf->size = 0; - LoadBin(m, elf->base, prog, elf->map, elf->mapsize); - } - } -} diff --git a/tool/build/lib/loader.h b/tool/build/lib/loader.h deleted file mode 100644 index 80b190268..000000000 --- a/tool/build/lib/loader.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_LOADER_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_LOADER_H_ -#include "libc/elf/struct/ehdr.h" -#include "tool/build/lib/machine.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -struct Elf { - const char *prog; - Elf64_Ehdr *ehdr; - size_t size; - int64_t base; - char *map; - size_t mapsize; -}; - -void LoadProgram(struct Machine *, const char *, char **, char **, - struct Elf *); -void LoadDebugSymbols(struct Elf *); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_LOADER_H_ */ diff --git a/tool/build/lib/machine.c b/tool/build/lib/machine.c deleted file mode 100644 index 69a25a539..000000000 --- a/tool/build/lib/machine.c +++ /dev/null @@ -1,2245 +0,0 @@ -/*-*- 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 "tool/build/lib/machine.h" -#include "libc/log/check.h" -#include "libc/macros.internal.h" -#include "libc/runtime/runtime.h" -#include "libc/stdio/rand.h" -#include "libc/str/str.h" -#include "tool/build/lib/abp.h" -#include "tool/build/lib/address.h" -#include "tool/build/lib/alu.h" -#include "tool/build/lib/bcd.h" -#include "tool/build/lib/bitscan.h" -#include "tool/build/lib/case.h" -#include "tool/build/lib/clmul.h" -#include "tool/build/lib/cpuid.h" -#include "tool/build/lib/cvt.h" -#include "tool/build/lib/divmul.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/flags.h" -#include "tool/build/lib/fpu.h" -#include "tool/build/lib/ioports.h" -#include "tool/build/lib/memory.h" -#include "tool/build/lib/modrm.h" -#include "tool/build/lib/op101.h" -#include "tool/build/lib/sse.h" -#include "tool/build/lib/ssefloat.h" -#include "tool/build/lib/ssemov.h" -#include "tool/build/lib/stack.h" -#include "tool/build/lib/stats.h" -#include "tool/build/lib/string.h" -#include "tool/build/lib/syscall.h" -#include "tool/build/lib/throw.h" -#include "tool/build/lib/time.h" - -#define OpLfence OpNoop -#define OpMfence OpNoop -#define OpSfence OpNoop -#define OpClflush OpNoop -#define OpHintNopEv OpNoop - -typedef void (*nexgen32e_f)(struct Machine *, uint32_t); - -static uint64_t ReadMemory(uint32_t rde, uint8_t p[8]) { - if (Rexw(rde)) { - return Read64(p); - } else if (!Osz(rde)) { - return Read32(p); - } else { - return Read16(p); - } -} - -static int64_t ReadMemorySigned(uint32_t rde, uint8_t p[8]) { - if (Rexw(rde)) { - return (int64_t)Read64(p); - } else if (!Osz(rde)) { - return (int32_t)Read32(p); - } else { - return (int16_t)Read16(p); - } -} - -static void WriteRegister(uint32_t rde, uint8_t p[8], uint64_t x) { - if (Rexw(rde)) { - Write64(p, x); - } else if (!Osz(rde)) { - Write64(p, x & 0xffffffff); - } else { - Write16(p, x); - } -} - -static void WriteMemory(uint32_t rde, uint8_t p[8], uint64_t x) { - if (Rexw(rde)) { - Write64(p, x); - } else if (!Osz(rde)) { - Write32(p, x); - } else { - Write16(p, x); - } -} - -static void WriteRegisterOrMemory(uint32_t rde, uint8_t p[8], uint64_t x) { - if (IsModrmRegister(rde)) { - WriteRegister(rde, p, x); - } else { - WriteMemory(rde, p, x); - } -} - -static bool IsParity(struct Machine *m) { - return GetFlag(m->flags, FLAGS_PF); -} - -static bool IsBelowOrEqual(struct Machine *m) { - return GetFlag(m->flags, FLAGS_CF) | GetFlag(m->flags, FLAGS_ZF); -} - -static bool IsAbove(struct Machine *m) { - return !GetFlag(m->flags, FLAGS_CF) && !GetFlag(m->flags, FLAGS_ZF); -} - -static bool IsLess(struct Machine *m) { - return GetFlag(m->flags, FLAGS_SF) != GetFlag(m->flags, FLAGS_OF); -} - -static bool IsGreaterOrEqual(struct Machine *m) { - return GetFlag(m->flags, FLAGS_SF) == GetFlag(m->flags, FLAGS_OF); -} - -static bool IsLessOrEqual(struct Machine *m) { - return GetFlag(m->flags, FLAGS_ZF) | - (GetFlag(m->flags, FLAGS_SF) != GetFlag(m->flags, FLAGS_OF)); -} - -static bool IsGreater(struct Machine *m) { - return !GetFlag(m->flags, FLAGS_ZF) & - (GetFlag(m->flags, FLAGS_SF) == GetFlag(m->flags, FLAGS_OF)); -} - -static void OpNoop(struct Machine *m, uint32_t rde) { -} - -static void OpCmc(struct Machine *m, uint32_t rde) { - m->flags = SetFlag(m->flags, FLAGS_CF, !GetFlag(m->flags, FLAGS_CF)); -} - -static void OpClc(struct Machine *m, uint32_t rde) { - m->flags = SetFlag(m->flags, FLAGS_CF, false); -} - -static void OpStc(struct Machine *m, uint32_t rde) { - m->flags = SetFlag(m->flags, FLAGS_CF, true); -} - -static void OpCli(struct Machine *m, uint32_t rde) { - m->flags = SetFlag(m->flags, FLAGS_IF, false); -} - -static void OpSti(struct Machine *m, uint32_t rde) { - m->flags = SetFlag(m->flags, FLAGS_IF, true); -} - -static void OpCld(struct Machine *m, uint32_t rde) { - m->flags = SetFlag(m->flags, FLAGS_DF, false); -} - -static void OpStd(struct Machine *m, uint32_t rde) { - m->flags = SetFlag(m->flags, FLAGS_DF, true); -} - -static void OpPushf(struct Machine *m, uint32_t rde) { - Push(m, rde, ExportFlags(m->flags) & 0xFCFFFF); -} - -static void OpPopf(struct Machine *m, uint32_t rde) { - if (!Osz(rde)) { - ImportFlags(m, Pop(m, rde, 0)); - } else { - ImportFlags(m, (m->flags & ~0xffff) | Pop(m, rde, 0)); - } -} - -static void OpLahf(struct Machine *m, uint32_t rde) { - Write8(m->ax + 1, ExportFlags(m->flags)); -} - -static void OpSahf(struct Machine *m, uint32_t rde) { - ImportFlags(m, (m->flags & ~0xff) | m->ax[1]); -} - -static void OpLeaGvqpM(struct Machine *m, uint32_t rde) { - WriteRegister(rde, RegRexrReg(m, rde), LoadEffectiveAddress(m, rde).addr); -} - -static relegated void OpPushSeg(struct Machine *m, uint32_t rde) { - uint8_t seg = (m->xedd->op.opcode & 070) >> 3; - Push(m, rde, Read64(GetSegment(m, rde, seg)) >> 4); -} - -static relegated void OpPopSeg(struct Machine *m, uint32_t rde) { - uint8_t seg = (m->xedd->op.opcode & 070) >> 3; - Write64(GetSegment(m, rde, seg), Pop(m, rde, 0) << 4); -} - -static relegated void OpMovEvqpSw(struct Machine *m, uint32_t rde) { - WriteRegisterOrMemory(rde, GetModrmRegisterWordPointerWriteOszRexw(m, rde), - Read64(GetSegment(m, rde, ModrmReg(rde))) >> 4); -} - -static relegated int GetDescriptor(struct Machine *m, int selector, - uint64_t *out_descriptor) { - uint8_t buf[8]; - DCHECK(m->gdt_base + m->gdt_limit <= m->real.n); - selector &= -8; - if (8 <= selector && selector + 8 <= m->gdt_limit) { - SetReadAddr(m, m->gdt_base + selector, 8); - *out_descriptor = Read64(m->real.p + m->gdt_base + selector); - return 0; - } else { - return -1; - } -} - -static uint64_t GetDescriptorBase(uint64_t d) { - return (d & 0xff00000000000000) >> 32 | (d & 0x000000ffffff0000) >> 16; -} - -static uint64_t GetDescriptorLimit(uint64_t d) { - return (d & 0x000f000000000000) >> 32 | d & 0xffff; -} - -static int GetDescriptorMode(uint64_t d) { - uint8_t kMode[] = { - XED_MACHINE_MODE_REAL, - XED_MACHINE_MODE_LONG_64, - XED_MACHINE_MODE_LEGACY_32, - XED_MACHINE_MODE_LONG_64, - }; - return kMode[(d & 0x0060000000000000) >> 53]; -} - -static bool IsProtectedMode(struct Machine *m) { - return m->cr0 & 1; -} - -static relegated void OpMovSwEvqp(struct Machine *m, uint32_t rde) { - uint64_t x, d; - x = ReadMemory(rde, GetModrmRegisterWordPointerReadOszRexw(m, rde)); - if (!IsProtectedMode(m)) { - x <<= 4; - } else if (GetDescriptor(m, x, &d) != -1) { - x = GetDescriptorBase(d); - } else { - ThrowProtectionFault(m); - } - Write64(GetSegment(m, rde, ModrmReg(rde)), x); -} - -static void OpLsl(struct Machine *m, uint32_t rde) { - uint64_t descriptor; - if (GetDescriptor(m, Read16(GetModrmRegisterWordPointerRead2(m, rde)), - &descriptor) != -1) { - WriteRegister(rde, RegRexrReg(m, rde), GetDescriptorLimit(descriptor)); - SetFlag(m->flags, FLAGS_ZF, true); - } else { - SetFlag(m->flags, FLAGS_ZF, false); - } -} - -static void ChangeMachineMode(struct Machine *m, int mode) { - if (mode == m->mode) return; - ResetInstructionCache(m); - m->mode = mode; -} - -static void OpJmpf(struct Machine *m, uint32_t rde) { - uint64_t descriptor; - if (!IsProtectedMode(m)) { - Write64(m->cs, m->xedd->op.uimm0 << 4); - m->ip = m->xedd->op.disp; - } else if (GetDescriptor(m, m->xedd->op.uimm0, &descriptor) != -1) { - Write64(m->cs, GetDescriptorBase(descriptor)); - m->ip = m->xedd->op.disp; - ChangeMachineMode(m, GetDescriptorMode(descriptor)); - } else { - ThrowProtectionFault(m); - } - if (m->onlongbranch) { - m->onlongbranch(m); - } -} - -static void OpInto(struct Machine *m, uint32_t rde) { - if (GetFlag(m->flags, FLAGS_OF)) { - HaltMachine(m, kMachineOverflow); - } -} - -static relegated void OpXlatAlBbb(struct Machine *m, uint32_t rde) { - uint64_t v; - v = MaskAddress(Eamode(rde), Read64(m->bx) + Read8(m->ax)); - v = DataSegment(m, rde, v); - SetReadAddr(m, v, 1); - Write8(m->ax, Read8(ResolveAddress(m, v))); -} - -static void WriteEaxAx(struct Machine *m, uint32_t rde, uint32_t x) { - if (!Osz(rde)) { - Write64(m->ax, x); - } else { - Write16(m->ax, x); - } -} - -static uint32_t ReadEaxAx(struct Machine *m, uint32_t rde) { - if (!Osz(rde)) { - return Read32(m->ax); - } else { - return Read16(m->ax); - } -} - -static void OpInAlImm(struct Machine *m, uint32_t rde) { - Write8(m->ax, OpIn(m, m->xedd->op.uimm0)); -} - -static void OpInAxImm(struct Machine *m, uint32_t rde) { - WriteEaxAx(m, rde, OpIn(m, m->xedd->op.uimm0)); -} - -static void OpInAlDx(struct Machine *m, uint32_t rde) { - Write8(m->ax, OpIn(m, Read16(m->dx))); -} - -static void OpInAxDx(struct Machine *m, uint32_t rde) { - WriteEaxAx(m, rde, OpIn(m, Read16(m->dx))); -} - -static void OpOutImmAl(struct Machine *m, uint32_t rde) { - OpOut(m, m->xedd->op.uimm0, Read8(m->ax)); -} - -static void OpOutImmAx(struct Machine *m, uint32_t rde) { - OpOut(m, m->xedd->op.uimm0, ReadEaxAx(m, rde)); -} - -static void OpOutDxAl(struct Machine *m, uint32_t rde) { - OpOut(m, Read16(m->dx), Read8(m->ax)); -} - -static void OpOutDxAx(struct Machine *m, uint32_t rde) { - OpOut(m, Read16(m->dx), ReadEaxAx(m, rde)); -} - -static void AluEb(struct Machine *m, uint32_t rde, aluop_f op) { - uint8_t *p; - p = GetModrmRegisterBytePointerWrite(m, rde); - Write8(p, op(Read8(p), 0, &m->flags)); -} - -static void AluEvqp(struct Machine *m, uint32_t rde, aluop_f ops[4]) { - uint8_t *p; - p = GetModrmRegisterWordPointerWriteOszRexw(m, rde); - WriteRegisterOrMemory(rde, p, - ops[RegLog2(rde)](ReadMemory(rde, p), 0, &m->flags)); -} - -static void OpXchgZvqp(struct Machine *m, uint32_t rde) { - uint64_t x, y; - x = Read64(m->ax); - y = Read64(RegRexbSrm(m, rde)); - WriteRegister(rde, m->ax, y); - WriteRegister(rde, RegRexbSrm(m, rde), x); -} - -static void OpXchgGbEb(struct Machine *m, uint32_t rde) { - uint8_t *p; - uint8_t x, y; - p = GetModrmRegisterBytePointerWrite(m, rde); - x = Read8(ByteRexrReg(m, rde)); - y = Read8(p); - Write8(ByteRexrReg(m, rde), y); - Write8(p, x); -} - -static void OpXchgGvqpEvqp(struct Machine *m, uint32_t rde) { - uint8_t *p; - uint64_t x, y; - p = GetModrmRegisterWordPointerWriteOszRexw(m, rde); - x = ReadMemory(rde, RegRexrReg(m, rde)); - y = ReadMemory(rde, p); - WriteRegister(rde, RegRexrReg(m, rde), y); - WriteRegisterOrMemory(rde, p, x); -} - -static void OpCmpxchgEbAlGb(struct Machine *m, uint32_t rde) { - uint8_t *p; - uint8_t x, y, z; - p = GetModrmRegisterBytePointerWrite(m, rde); - x = Read8(m->ax); - y = Read8(p); - z = Read8(ByteRexrReg(m, rde)); - Sub8(x, y, &m->flags); - if (GetFlag(m->flags, FLAGS_ZF)) { - Write8(p, z); - } else { - Write8(m->ax, y); - } -} - -static void OpCmpxchgEvqpRaxGvqp(struct Machine *m, uint32_t rde) { - uint8_t *p; - uint64_t x, y, z; - p = GetModrmRegisterWordPointerWriteOszRexw(m, rde); - x = ReadMemory(rde, m->ax); - y = ReadMemory(rde, p); - z = ReadMemory(rde, RegRexrReg(m, rde)); - kAlu[ALU_SUB][RegLog2(rde)](x, y, &m->flags); - if (GetFlag(m->flags, FLAGS_ZF)) { - WriteRegisterOrMemory(rde, p, z); - } else { - WriteRegister(rde, m->ax, y); - } -} - -static void OpCmpxchg8b(struct Machine *m, uint32_t rde) { - uint8_t *p; - uint32_t d, a; - p = GetModrmRegisterXmmPointerRead8(m, rde); - a = Read32(p + 0); - d = Read32(p + 4); - if (a == Read32(m->ax) && d == Read32(m->dx)) { - SetFlag(m->flags, FLAGS_ZF, true); - memcpy(p + 0, m->bx, 4); - memcpy(p + 4, m->cx, 4); - } else { - SetFlag(m->flags, FLAGS_ZF, false); - Write32(m->ax, a); - Write32(m->dx, d); - } -} - -static void OpCmpxchg16b(struct Machine *m, uint32_t rde) { - uint8_t *p; - uint64_t d, a; - p = GetModrmRegisterXmmPointerRead16(m, rde); - a = Read64(p + 0); - d = Read64(p + 8); - if (a == Read64(m->ax) && d == Read64(m->dx)) { - SetFlag(m->flags, FLAGS_ZF, true); - memcpy(p + 0, m->bx, 8); - memcpy(p + 8, m->cx, 8); - } else { - SetFlag(m->flags, FLAGS_ZF, false); - Write64(m->ax, a); - Write64(m->dx, d); - } -} - -static void OpRdrand(struct Machine *m, uint32_t rde) { - WriteRegister(rde, RegRexbRm(m, rde), rdrand()); - m->flags = SetFlag(m->flags, FLAGS_CF, true); -} - -static void OpRdseed(struct Machine *m, uint32_t rde) { - OpRdrand(m, rde); -} - -static void Op1c7(struct Machine *m, uint32_t rde) { - bool ismem; - ismem = !IsModrmRegister(rde); - switch (ModrmReg(rde)) { - case 1: - if (ismem) { - if (Rexw(rde)) { - OpCmpxchg16b(m, rde); - } else { - OpCmpxchg8b(m, rde); - } - } else { - OpUd(m, rde); - } - break; - case 6: - if (!ismem) { - OpRdrand(m, rde); - } else { - OpUd(m, rde); - } - break; - case 7: - if (!ismem) { - if (Rep(rde) == 3) { - OpRdpid(m, rde); - } else { - OpRdseed(m, rde); - } - } else { - OpUd(m, rde); - } - break; - default: - OpUd(m, rde); - } -} - -static void OpXaddEbGb(struct Machine *m, uint32_t rde) { - uint8_t *p; - uint8_t x, y, z; - p = GetModrmRegisterWordPointerWriteOszRexw(m, rde); - x = Read8(p); - y = Read8(RegRexrReg(m, rde)); - z = Add8(x, y, &m->flags); - Write8(p, z); - Write8(RegRexrReg(m, rde), x); -} - -static void OpXaddEvqpGvqp(struct Machine *m, uint32_t rde) { - uint8_t *p; - uint64_t x, y, z; - p = GetModrmRegisterWordPointerWriteOszRexw(m, rde); - x = ReadMemory(rde, p); - y = ReadMemory(rde, RegRexrReg(m, rde)); - z = kAlu[ALU_ADD][RegLog2(rde)](x, y, &m->flags); - WriteRegisterOrMemory(rde, p, z); - WriteRegister(rde, RegRexrReg(m, rde), x); -} - -static uint64_t Bts(uint64_t x, uint64_t y) { - return x | y; -} - -static uint64_t Btr(uint64_t x, uint64_t y) { - return x & ~y; -} - -static uint64_t Btc(uint64_t x, uint64_t y) { - return (x & ~y) | (~x & y); -} - -static void OpBit(struct Machine *m, uint32_t rde) { - int op; - uint8_t *p; - unsigned bit; - int64_t disp; - uint64_t v, x, y, z; - uint8_t w, W[2][2] = {{2, 3}, {1, 3}}; - w = W[Osz(rde)][Rexw(rde)]; - if (m->xedd->op.opcode == 0xBA) { - op = ModrmReg(rde); - bit = m->xedd->op.uimm0 & ((8 << w) - 1); - disp = 0; - } else { - op = (m->xedd->op.opcode & 070) >> 3; - disp = ReadMemorySigned(rde, RegRexrReg(m, rde)); - bit = disp & ((8 << w) - 1); - disp &= -(8 << w); - disp >>= 3; - } - if (IsModrmRegister(rde)) { - p = RegRexbRm(m, rde); - } else { - v = MaskAddress(Eamode(rde), ComputeAddress(m, rde) + disp); - p = ReserveAddress(m, v, 1 << w); - if (op == 4) { - SetReadAddr(m, v, 1 << w); - } else { - SetWriteAddr(m, v, 1 << w); - } - } - y = 1; - y <<= bit; - x = ReadMemory(rde, p); - m->flags = SetFlag(m->flags, FLAGS_CF, !!(y & x)); - switch (op) { - case 4: - return; - case 5: - z = Bts(x, y); - break; - case 6: - z = Btr(x, y); - break; - case 7: - z = Btc(x, y); - break; - default: - OpUd(m, rde); - } - WriteRegisterOrMemory(rde, p, z); -} - -static void OpSax(struct Machine *m, uint32_t rde) { - if (Rexw(rde)) { - Write64(m->ax, (int32_t)Read32(m->ax)); - } else if (!Osz(rde)) { - Write64(m->ax, (uint32_t)(int16_t)Read16(m->ax)); - } else { - Write16(m->ax, (int8_t)Read8(m->ax)); - } -} - -static void OpConvert(struct Machine *m, uint32_t rde) { - if (Rexw(rde)) { - Write64(m->dx, (uint64_t)((int64_t)Read64(m->ax) >> 63)); - } else if (!Osz(rde)) { - Write64(m->dx, (uint32_t)((int32_t)Read32(m->ax) >> 31)); - } else { - Write16(m->dx, (uint16_t)((int16_t)Read16(m->ax) >> 15)); - } -} - -static void OpBswapZvqp(struct Machine *m, uint32_t rde) { - uint64_t x; - x = Read64(RegRexbSrm(m, rde)); - if (Rexw(rde)) { - Write64( - RegRexbSrm(m, rde), - ((x & 0xff00000000000000) >> 070 | (x & 0x00000000000000ff) << 070 | - (x & 0x00ff000000000000) >> 050 | (x & 0x000000000000ff00) << 050 | - (x & 0x0000ff0000000000) >> 030 | (x & 0x0000000000ff0000) << 030 | - (x & 0x000000ff00000000) >> 010 | (x & 0x00000000ff000000) << 010)); - } else if (!Osz(rde)) { - Write64(RegRexbSrm(m, rde), - ((x & 0xff000000) >> 030 | (x & 0x000000ff) << 030 | - (x & 0x00ff0000) >> 010 | (x & 0x0000ff00) << 010)); - } else { - Write16(RegRexbSrm(m, rde), (x & 0x00ff) << 010 | (x & 0xff00) << 010); - } -} - -static void OpMovEbIb(struct Machine *m, uint32_t rde) { - Write8(GetModrmRegisterBytePointerWrite(m, rde), m->xedd->op.uimm0); -} - -static void OpMovAlOb(struct Machine *m, uint32_t rde) { - int64_t addr; - addr = AddressOb(m, rde); - SetWriteAddr(m, addr, 1); - Write8(m->ax, Read8(ResolveAddress(m, addr))); -} - -static void OpMovObAl(struct Machine *m, uint32_t rde) { - int64_t addr; - addr = AddressOb(m, rde); - SetReadAddr(m, addr, 1); - Write8(ResolveAddress(m, addr), Read8(m->ax)); -} - -static void OpMovRaxOvqp(struct Machine *m, uint32_t rde) { - uint64_t v; - v = DataSegment(m, rde, m->xedd->op.disp); - SetReadAddr(m, v, 1 << RegLog2(rde)); - WriteRegister(rde, m->ax, ReadMemory(rde, ResolveAddress(m, v))); -} - -static void OpMovOvqpRax(struct Machine *m, uint32_t rde) { - uint64_t v; - v = DataSegment(m, rde, m->xedd->op.disp); - SetWriteAddr(m, v, 1 << RegLog2(rde)); - WriteMemory(rde, ResolveAddress(m, v), Read64(m->ax)); -} - -static void OpMovEbGb(struct Machine *m, uint32_t rde) { - memcpy(GetModrmRegisterBytePointerWrite(m, rde), ByteRexrReg(m, rde), 1); -} - -static void OpMovGbEb(struct Machine *m, uint32_t rde) { - memcpy(ByteRexrReg(m, rde), GetModrmRegisterBytePointerRead(m, rde), 1); -} - -static void OpMovZbIb(struct Machine *m, uint32_t rde) { - Write8(ByteRexbSrm(m, rde), m->xedd->op.uimm0); -} - -static void OpMovZvqpIvqp(struct Machine *m, uint32_t rde) { - WriteRegister(rde, RegRexbSrm(m, rde), m->xedd->op.uimm0); -} - -static relegated void OpIncZv(struct Machine *m, uint32_t rde) { - if (!Osz(rde)) { - Write32(RegSrm(m, rde), Inc32(Read32(RegSrm(m, rde)), 0, &m->flags)); - } else { - Write16(RegSrm(m, rde), Inc16(Read16(RegSrm(m, rde)), 0, &m->flags)); - } -} - -static relegated void OpDecZv(struct Machine *m, uint32_t rde) { - if (!Osz(rde)) { - Write32(RegSrm(m, rde), Dec32(Read32(RegSrm(m, rde)), 0, &m->flags)); - } else { - Write16(RegSrm(m, rde), Dec16(Read16(RegSrm(m, rde)), 0, &m->flags)); - } -} - -static void OpMovEvqpIvds(struct Machine *m, uint32_t rde) { - WriteRegisterOrMemory(rde, GetModrmRegisterWordPointerWriteOszRexw(m, rde), - m->xedd->op.uimm0); -} - -static void OpMovEvqpGvqp(struct Machine *m, uint32_t rde) { - WriteRegisterOrMemory(rde, GetModrmRegisterWordPointerWriteOszRexw(m, rde), - ReadMemory(rde, RegRexrReg(m, rde))); -} - -static void OpMovzbGvqpEb(struct Machine *m, uint32_t rde) { - WriteRegister(rde, RegRexrReg(m, rde), - Read8(GetModrmRegisterBytePointerRead(m, rde))); -} - -static void OpMovzwGvqpEw(struct Machine *m, uint32_t rde) { - WriteRegister(rde, RegRexrReg(m, rde), - Read16(GetModrmRegisterWordPointerRead2(m, rde))); -} - -static void OpMovsbGvqpEb(struct Machine *m, uint32_t rde) { - WriteRegister(rde, RegRexrReg(m, rde), - (int8_t)Read8(GetModrmRegisterBytePointerRead(m, rde))); -} - -static void OpMovswGvqpEw(struct Machine *m, uint32_t rde) { - WriteRegister(rde, RegRexrReg(m, rde), - (int16_t)Read16(GetModrmRegisterWordPointerRead2(m, rde))); -} - -static void OpMovsxdGdqpEd(struct Machine *m, uint32_t rde) { - Write64(RegRexrReg(m, rde), - (int32_t)Read32(GetModrmRegisterWordPointerRead4(m, rde))); -} - -static void Alub(struct Machine *m, uint32_t rde, aluop_f op) { - uint8_t *a = GetModrmRegisterBytePointerWrite(m, rde); - Write8(a, op(Read8(a), Read8(ByteRexrReg(m, rde)), &m->flags)); -} - -static void OpAlubAdd(struct Machine *m, uint32_t rde) { - Alub(m, rde, Add8); -} - -static void OpAlubOr(struct Machine *m, uint32_t rde) { - Alub(m, rde, Or8); -} - -static void OpAlubAdc(struct Machine *m, uint32_t rde) { - Alub(m, rde, Adc8); -} - -static void OpAlubSbb(struct Machine *m, uint32_t rde) { - Alub(m, rde, Sbb8); -} - -static void OpAlubAnd(struct Machine *m, uint32_t rde) { - Alub(m, rde, And8); -} - -static void OpAlubSub(struct Machine *m, uint32_t rde) { - Alub(m, rde, Sub8); -} - -static void OpAlubXor(struct Machine *m, uint32_t rde) { - Alub(m, rde, Xor8); -} - -static void AlubRo(struct Machine *m, uint32_t rde, aluop_f op) { - op(Read8(GetModrmRegisterBytePointerRead(m, rde)), Read8(ByteRexrReg(m, rde)), - &m->flags); -} - -static void OpAlubCmp(struct Machine *m, uint32_t rde) { - AlubRo(m, rde, Sub8); -} - -static void OpAlubTest(struct Machine *m, uint32_t rde) { - AlubRo(m, rde, And8); -} - -static void AlubFlip(struct Machine *m, uint32_t rde, aluop_f op) { - Write8(ByteRexrReg(m, rde), - op(Read8(ByteRexrReg(m, rde)), - Read8(GetModrmRegisterBytePointerRead(m, rde)), &m->flags)); -} - -static void OpAlubFlipAdd(struct Machine *m, uint32_t rde) { - AlubFlip(m, rde, Add8); -} - -static void OpAlubFlipOr(struct Machine *m, uint32_t rde) { - AlubFlip(m, rde, Or8); -} - -static void OpAlubFlipAdc(struct Machine *m, uint32_t rde) { - AlubFlip(m, rde, Adc8); -} - -static void OpAlubFlipSbb(struct Machine *m, uint32_t rde) { - AlubFlip(m, rde, Sbb8); -} - -static void OpAlubFlipAnd(struct Machine *m, uint32_t rde) { - AlubFlip(m, rde, And8); -} - -static void OpAlubFlipSub(struct Machine *m, uint32_t rde) { - AlubFlip(m, rde, Sub8); -} - -static void OpAlubFlipXor(struct Machine *m, uint32_t rde) { - AlubFlip(m, rde, Xor8); -} - -static void AlubFlipRo(struct Machine *m, uint32_t rde, aluop_f op) { - op(Read8(ByteRexrReg(m, rde)), Read8(GetModrmRegisterBytePointerRead(m, rde)), - &m->flags); -} - -static void OpAlubFlipCmp(struct Machine *m, uint32_t rde) { - AlubFlipRo(m, rde, Sub8); -} - -static void OpAlubFlipTest(struct Machine *m, uint32_t rde) { - AlubFlipRo(m, rde, And8); -} - -static void Alubi(struct Machine *m, uint32_t rde, aluop_f op) { - uint8_t *a = GetModrmRegisterBytePointerWrite(m, rde); - Write8(a, op(Read8(a), m->xedd->op.uimm0, &m->flags)); -} - -static void AlubiRo(struct Machine *m, uint32_t rde, aluop_f op) { - op(Read8(GetModrmRegisterBytePointerRead(m, rde)), m->xedd->op.uimm0, - &m->flags); -} - -static void OpAlubiTest(struct Machine *m, uint32_t rde) { - AlubiRo(m, rde, And8); -} - -static void OpAlubiReg(struct Machine *m, uint32_t rde) { - if (ModrmReg(rde) == ALU_CMP) { - AlubiRo(m, rde, kAlu[ModrmReg(rde)][0]); - } else { - Alubi(m, rde, kAlu[ModrmReg(rde)][0]); - } -} - -static void OpAluw(struct Machine *m, uint32_t rde) { - uint8_t *a; - a = GetModrmRegisterWordPointerWriteOszRexw(m, rde); - WriteRegisterOrMemory( - rde, a, - kAlu[(m->xedd->op.opcode & 070) >> 3][RegLog2(rde)]( - ReadMemory(rde, a), Read64(RegRexrReg(m, rde)), &m->flags)); -} - -static void AluwRo(struct Machine *m, uint32_t rde, aluop_f ops[4]) { - ops[RegLog2(rde)]( - ReadMemory(rde, GetModrmRegisterWordPointerReadOszRexw(m, rde)), - Read64(RegRexrReg(m, rde)), &m->flags); -} - -static void OpAluwCmp(struct Machine *m, uint32_t rde) { - AluwRo(m, rde, kAlu[ALU_SUB]); -} - -static void OpAluwTest(struct Machine *m, uint32_t rde) { - AluwRo(m, rde, kAlu[ALU_AND]); -} - -static void OpAluwFlip(struct Machine *m, uint32_t rde) { - WriteRegister( - rde, RegRexrReg(m, rde), - kAlu[(m->xedd->op.opcode & 070) >> 3][RegLog2(rde)]( - Read64(RegRexrReg(m, rde)), - ReadMemory(rde, GetModrmRegisterWordPointerReadOszRexw(m, rde)), - &m->flags)); -} - -static void AluwFlipRo(struct Machine *m, uint32_t rde, aluop_f ops[4]) { - ops[RegLog2(rde)]( - Read64(RegRexrReg(m, rde)), - ReadMemory(rde, GetModrmRegisterWordPointerReadOszRexw(m, rde)), - &m->flags); -} - -static void OpAluwFlipCmp(struct Machine *m, uint32_t rde) { - AluwFlipRo(m, rde, kAlu[ALU_SUB]); -} - -static void OpAluwFlipTest(struct Machine *m, uint32_t rde) { - AluwFlipRo(m, rde, kAlu[ALU_AND]); -} - -static void Aluwi(struct Machine *m, uint32_t rde, aluop_f ops[4]) { - uint8_t *a; - a = GetModrmRegisterWordPointerWriteOszRexw(m, rde); - WriteRegisterOrMemory( - rde, a, - ops[RegLog2(rde)](ReadMemory(rde, a), m->xedd->op.uimm0, &m->flags)); -} - -static void AluwiRo(struct Machine *m, uint32_t rde, aluop_f ops[4]) { - ops[RegLog2(rde)]( - ReadMemory(rde, GetModrmRegisterWordPointerReadOszRexw(m, rde)), - m->xedd->op.uimm0, &m->flags); -} - -static void OpAluwiReg(struct Machine *m, uint32_t rde) { - if (ModrmReg(rde) == ALU_CMP) { - AluwiRo(m, rde, kAlu[ModrmReg(rde)]); - } else { - Aluwi(m, rde, kAlu[ModrmReg(rde)]); - } -} - -static void AluAlIb(struct Machine *m, aluop_f op) { - Write8(m->ax, op(Read8(m->ax), m->xedd->op.uimm0, &m->flags)); -} - -static void OpAluAlIbAdd(struct Machine *m, uint32_t rde) { - AluAlIb(m, Add8); -} - -static void OpAluAlIbOr(struct Machine *m, uint32_t rde) { - AluAlIb(m, Or8); -} - -static void OpAluAlIbAdc(struct Machine *m, uint32_t rde) { - AluAlIb(m, Adc8); -} - -static void OpAluAlIbSbb(struct Machine *m, uint32_t rde) { - AluAlIb(m, Sbb8); -} - -static void OpAluAlIbAnd(struct Machine *m, uint32_t rde) { - AluAlIb(m, And8); -} - -static void OpAluAlIbSub(struct Machine *m, uint32_t rde) { - AluAlIb(m, Sub8); -} - -static void OpAluAlIbXor(struct Machine *m, uint32_t rde) { - AluAlIb(m, Xor8); -} - -static void OpAluRaxIvds(struct Machine *m, uint32_t rde) { - WriteRegister(rde, m->ax, - kAlu[(m->xedd->op.opcode & 070) >> 3][RegLog2(rde)]( - ReadMemory(rde, m->ax), m->xedd->op.uimm0, &m->flags)); -} - -static void OpCmpAlIb(struct Machine *m, uint32_t rde) { - Sub8(Read8(m->ax), m->xedd->op.uimm0, &m->flags); -} - -static void OpCmpRaxIvds(struct Machine *m, uint32_t rde) { - kAlu[ALU_SUB][RegLog2(rde)](ReadMemory(rde, m->ax), m->xedd->op.uimm0, - &m->flags); -} - -static void OpTestAlIb(struct Machine *m, uint32_t rde) { - And8(Read8(m->ax), m->xedd->op.uimm0, &m->flags); -} - -static void OpTestRaxIvds(struct Machine *m, uint32_t rde) { - kAlu[ALU_AND][RegLog2(rde)](ReadMemory(rde, m->ax), m->xedd->op.uimm0, - &m->flags); -} - -static void Bsuwi(struct Machine *m, uint32_t rde, uint64_t y) { - uint8_t *p; - p = GetModrmRegisterWordPointerWriteOszRexw(m, rde); - WriteRegisterOrMemory( - rde, p, - kBsu[ModrmReg(rde)][RegLog2(rde)](ReadMemory(rde, p), y, &m->flags)); -} - -static void OpBsuwi1(struct Machine *m, uint32_t rde) { - Bsuwi(m, rde, 1); -} - -static void OpBsuwiCl(struct Machine *m, uint32_t rde) { - Bsuwi(m, rde, Read8(m->cx)); -} - -static void OpBsuwiImm(struct Machine *m, uint32_t rde) { - Bsuwi(m, rde, m->xedd->op.uimm0); -} - -static void Bsubi(struct Machine *m, uint32_t rde, uint64_t y) { - uint8_t *a = GetModrmRegisterBytePointerWrite(m, rde); - Write8(a, kBsu[ModrmReg(rde)][RegLog2(rde)](Read8(a), y, &m->flags)); -} - -static void OpBsubi1(struct Machine *m, uint32_t rde) { - Bsubi(m, rde, 1); -} - -static void OpBsubiCl(struct Machine *m, uint32_t rde) { - Bsubi(m, rde, Read8(m->cx)); -} - -static void OpBsubiImm(struct Machine *m, uint32_t rde) { - Bsubi(m, rde, m->xedd->op.uimm0); -} - -static void OpPushImm(struct Machine *m, uint32_t rde) { - Push(m, rde, m->xedd->op.uimm0); -} - -static void Interrupt(struct Machine *m, uint32_t rde, int i) { - HaltMachine(m, i); -} - -static void OpInterruptImm(struct Machine *m, uint32_t rde) { - Interrupt(m, rde, m->xedd->op.uimm0); -} - -static void OpInterrupt1(struct Machine *m, uint32_t rde) { - Interrupt(m, rde, 1); -} - -static void OpInterrupt3(struct Machine *m, uint32_t rde) { - Interrupt(m, rde, 3); -} - -static void OpJmp(struct Machine *m, uint32_t rde) { - m->ip += m->xedd->op.disp; -} - -static void OpJe(struct Machine *m, uint32_t rde) { - if (GetFlag(m->flags, FLAGS_ZF)) { - OpJmp(m, rde); - } -} - -static void OpJne(struct Machine *m, uint32_t rde) { - if (!GetFlag(m->flags, FLAGS_ZF)) { - OpJmp(m, rde); - } -} - -static void OpJb(struct Machine *m, uint32_t rde) { - if (GetFlag(m->flags, FLAGS_CF)) { - OpJmp(m, rde); - } -} - -static void OpJbe(struct Machine *m, uint32_t rde) { - if (IsBelowOrEqual(m)) { - OpJmp(m, rde); - } -} - -static void OpJo(struct Machine *m, uint32_t rde) { - if (GetFlag(m->flags, FLAGS_OF)) { - OpJmp(m, rde); - } -} - -static void OpJno(struct Machine *m, uint32_t rde) { - if (!GetFlag(m->flags, FLAGS_OF)) { - OpJmp(m, rde); - } -} - -static void OpJae(struct Machine *m, uint32_t rde) { - if (!GetFlag(m->flags, FLAGS_CF)) { - OpJmp(m, rde); - } -} - -static void OpJa(struct Machine *m, uint32_t rde) { - if (IsAbove(m)) { - OpJmp(m, rde); - } -} - -static void OpJs(struct Machine *m, uint32_t rde) { - if (GetFlag(m->flags, FLAGS_SF)) { - OpJmp(m, rde); - } -} - -static void OpJns(struct Machine *m, uint32_t rde) { - if (!GetFlag(m->flags, FLAGS_SF)) { - OpJmp(m, rde); - } -} - -static void OpJp(struct Machine *m, uint32_t rde) { - if (IsParity(m)) { - OpJmp(m, rde); - } -} - -static void OpJnp(struct Machine *m, uint32_t rde) { - if (!IsParity(m)) { - OpJmp(m, rde); - } -} - -static void OpJl(struct Machine *m, uint32_t rde) { - if (IsLess(m)) { - OpJmp(m, rde); - } -} - -static void OpJge(struct Machine *m, uint32_t rde) { - if (IsGreaterOrEqual(m)) { - OpJmp(m, rde); - } -} - -static void OpJle(struct Machine *m, uint32_t rde) { - if (IsLessOrEqual(m)) { - OpJmp(m, rde); - } -} - -static void OpJg(struct Machine *m, uint32_t rde) { - if (IsGreater(m)) { - OpJmp(m, rde); - } -} - -static void OpMovGvqpEvqp(struct Machine *m, uint32_t rde) { - WriteRegister( - rde, RegRexrReg(m, rde), - ReadMemory(rde, GetModrmRegisterWordPointerReadOszRexw(m, rde))); -} - -static void OpCmovo(struct Machine *m, uint32_t rde) { - if (GetFlag(m->flags, FLAGS_OF)) { - OpMovGvqpEvqp(m, rde); - } -} - -static void OpCmovno(struct Machine *m, uint32_t rde) { - if (!GetFlag(m->flags, FLAGS_OF)) { - OpMovGvqpEvqp(m, rde); - } -} - -static void OpCmovb(struct Machine *m, uint32_t rde) { - if (GetFlag(m->flags, FLAGS_CF)) { - OpMovGvqpEvqp(m, rde); - } -} - -static void OpCmovae(struct Machine *m, uint32_t rde) { - if (!GetFlag(m->flags, FLAGS_CF)) { - OpMovGvqpEvqp(m, rde); - } -} - -static void OpCmove(struct Machine *m, uint32_t rde) { - if (GetFlag(m->flags, FLAGS_ZF)) { - OpMovGvqpEvqp(m, rde); - } -} - -static void OpCmovne(struct Machine *m, uint32_t rde) { - if (!GetFlag(m->flags, FLAGS_ZF)) { - OpMovGvqpEvqp(m, rde); - } -} - -static void OpCmovbe(struct Machine *m, uint32_t rde) { - if (IsBelowOrEqual(m)) { - OpMovGvqpEvqp(m, rde); - } -} - -static void OpCmova(struct Machine *m, uint32_t rde) { - if (IsAbove(m)) { - OpMovGvqpEvqp(m, rde); - } -} - -static void OpCmovs(struct Machine *m, uint32_t rde) { - if (GetFlag(m->flags, FLAGS_SF)) { - OpMovGvqpEvqp(m, rde); - } -} - -static void OpCmovns(struct Machine *m, uint32_t rde) { - if (!GetFlag(m->flags, FLAGS_SF)) { - OpMovGvqpEvqp(m, rde); - } -} - -static void OpCmovp(struct Machine *m, uint32_t rde) { - if (IsParity(m)) { - OpMovGvqpEvqp(m, rde); - } -} - -static void OpCmovnp(struct Machine *m, uint32_t rde) { - if (!IsParity(m)) { - OpMovGvqpEvqp(m, rde); - } -} - -static void OpCmovl(struct Machine *m, uint32_t rde) { - if (IsLess(m)) { - OpMovGvqpEvqp(m, rde); - } -} - -static void OpCmovge(struct Machine *m, uint32_t rde) { - if (IsGreaterOrEqual(m)) { - OpMovGvqpEvqp(m, rde); - } -} - -static void OpCmovle(struct Machine *m, uint32_t rde) { - if (IsLessOrEqual(m)) { - OpMovGvqpEvqp(m, rde); - } -} - -static void OpCmovg(struct Machine *m, uint32_t rde) { - if (IsGreater(m)) { - OpMovGvqpEvqp(m, rde); - } -} - -static void SetEb(struct Machine *m, uint32_t rde, bool x) { - Write8(GetModrmRegisterBytePointerWrite(m, rde), x); -} - -static void OpSeto(struct Machine *m, uint32_t rde) { - SetEb(m, rde, GetFlag(m->flags, FLAGS_OF)); -} - -static void OpSetno(struct Machine *m, uint32_t rde) { - SetEb(m, rde, !GetFlag(m->flags, FLAGS_OF)); -} - -static void OpSetb(struct Machine *m, uint32_t rde) { - SetEb(m, rde, GetFlag(m->flags, FLAGS_CF)); -} - -static void OpSetae(struct Machine *m, uint32_t rde) { - SetEb(m, rde, !GetFlag(m->flags, FLAGS_CF)); -} - -static void OpSete(struct Machine *m, uint32_t rde) { - SetEb(m, rde, GetFlag(m->flags, FLAGS_ZF)); -} - -static void OpSetne(struct Machine *m, uint32_t rde) { - SetEb(m, rde, !GetFlag(m->flags, FLAGS_ZF)); -} - -static void OpSetbe(struct Machine *m, uint32_t rde) { - SetEb(m, rde, IsBelowOrEqual(m)); -} - -static void OpSeta(struct Machine *m, uint32_t rde) { - SetEb(m, rde, IsAbove(m)); -} - -static void OpSets(struct Machine *m, uint32_t rde) { - SetEb(m, rde, GetFlag(m->flags, FLAGS_SF)); -} - -static void OpSetns(struct Machine *m, uint32_t rde) { - SetEb(m, rde, !GetFlag(m->flags, FLAGS_SF)); -} - -static void OpSetp(struct Machine *m, uint32_t rde) { - SetEb(m, rde, IsParity(m)); -} - -static void OpSetnp(struct Machine *m, uint32_t rde) { - SetEb(m, rde, !IsParity(m)); -} - -static void OpSetl(struct Machine *m, uint32_t rde) { - SetEb(m, rde, IsLess(m)); -} - -static void OpSetge(struct Machine *m, uint32_t rde) { - SetEb(m, rde, IsGreaterOrEqual(m)); -} - -static void OpSetle(struct Machine *m, uint32_t rde) { - SetEb(m, rde, IsLessOrEqual(m)); -} - -static void OpSetg(struct Machine *m, uint32_t rde) { - SetEb(m, rde, IsGreater(m)); -} - -static void OpJcxz(struct Machine *m, uint32_t rde) { - if (!MaskAddress(Eamode(rde), Read64(m->cx))) { - OpJmp(m, rde); - } -} - -static void Bitscan(struct Machine *m, uint32_t rde, bitscan_f op) { - WriteRegister( - rde, RegRexrReg(m, rde), - op(m, rde, - ReadMemory(rde, GetModrmRegisterWordPointerReadOszRexw(m, rde)))); -} - -static void OpBsf(struct Machine *m, uint32_t rde) { - Bitscan(m, rde, AluBsf); -} - -static void OpBsr(struct Machine *m, uint32_t rde) { - Bitscan(m, rde, AluBsr); -} - -static void Op1b8(struct Machine *m, uint32_t rde) { - if (Rep(rde) == 3) { - Bitscan(m, rde, AluPopcnt); - } else { - OpUd(m, rde); - } -} - -static void OpNotEb(struct Machine *m, uint32_t rde) { - AluEb(m, rde, Not8); -} - -static void OpNegEb(struct Machine *m, uint32_t rde) { - AluEb(m, rde, Neg8); -} - -static relegated void LoadFarPointer(struct Machine *m, uint32_t rde, - uint8_t seg[8]) { - uint32_t fp; - fp = Read32(ComputeReserveAddressRead4(m, rde)); - Write64(seg, (fp & 0x0000ffff) << 4); - Write16(RegRexrReg(m, rde), fp >> 16); -} - -static relegated void OpLes(struct Machine *m, uint32_t rde) { - LoadFarPointer(m, rde, m->es); -} - -static relegated void OpLds(struct Machine *m, uint32_t rde) { - LoadFarPointer(m, rde, m->ds); -} - -static relegated void Loop(struct Machine *m, uint32_t rde, bool cond) { - uint64_t cx; - cx = Read64(m->cx) - 1; - if (Eamode(rde) != XED_MODE_REAL) { - if (Eamode(rde) == XED_MODE_LEGACY) { - cx &= 0xffffffff; - } - Write64(m->cx, cx); - } else { - cx &= 0xffff; - Write16(m->cx, cx); - } - if (cx && cond) { - OpJmp(m, rde); - } -} - -static relegated void OpLoope(struct Machine *m, uint32_t rde) { - Loop(m, rde, GetFlag(m->flags, FLAGS_ZF)); -} - -static relegated void OpLoopne(struct Machine *m, uint32_t rde) { - Loop(m, rde, !GetFlag(m->flags, FLAGS_ZF)); -} - -static relegated void OpLoop1(struct Machine *m, uint32_t rde) { - Loop(m, rde, true); -} - -static const nexgen32e_f kOp0f6[] = { - OpAlubiTest, - OpAlubiTest, - OpNotEb, - OpNegEb, - OpMulAxAlEbUnsigned, - OpMulAxAlEbSigned, - OpDivAlAhAxEbUnsigned, - OpDivAlAhAxEbSigned, -}; - -static void Op0f6(struct Machine *m, uint32_t rde) { - kOp0f6[ModrmReg(rde)](m, rde); -} - -static void OpTestEvqpIvds(struct Machine *m, uint32_t rde) { - AluwiRo(m, rde, kAlu[ALU_AND]); -} - -static void OpNotEvqp(struct Machine *m, uint32_t rde) { - AluEvqp(m, rde, kAlu[ALU_NOT]); -} - -static void OpNegEvqp(struct Machine *m, uint32_t rde) { - AluEvqp(m, rde, kAlu[ALU_NEG]); -} - -static const nexgen32e_f kOp0f7[] = { - OpTestEvqpIvds, - OpTestEvqpIvds, - OpNotEvqp, - OpNegEvqp, - OpMulRdxRaxEvqpUnsigned, - OpMulRdxRaxEvqpSigned, - OpDivRdxRaxEvqpUnsigned, - OpDivRdxRaxEvqpSigned, -}; - -static void Op0f7(struct Machine *m, uint32_t rde) { - kOp0f7[ModrmReg(rde)](m, rde); -} - -static void Op0fe(struct Machine *m, uint32_t rde) { - switch (ModrmReg(rde)) { - case 0: - AluEb(m, rde, Inc8); - break; - case 1: - AluEb(m, rde, Dec8); - break; - default: - OpUd(m, rde); - } -} - -static void OpIncEvqp(struct Machine *m, uint32_t rde) { - AluEvqp(m, rde, kAlu[ALU_INC]); -} - -static void OpDecEvqp(struct Machine *m, uint32_t rde) { - AluEvqp(m, rde, kAlu[ALU_DEC]); -} - -static const nexgen32e_f kOp0ff[] = {OpIncEvqp, OpDecEvqp, OpCallEq, OpUd, - OpJmpEq, OpUd, OpPushEvq, OpUd}; - -static void Op0ff(struct Machine *m, uint32_t rde) { - kOp0ff[ModrmReg(rde)](m, rde); -} - -static void OpDoubleShift(struct Machine *m, uint32_t rde) { - uint8_t *p; - uint64_t x; - uint8_t W[2][2] = {{2, 3}, {1, 3}}; - p = GetModrmRegisterWordPointerWriteOszRexw(m, rde); - WriteRegisterOrMemory( - rde, p, - BsuDoubleShift(W[Osz(rde)][Rexw(rde)], ReadMemory(rde, p), - ReadMemory(rde, RegRexrReg(m, rde)), - m->xedd->op.opcode & 1 ? Read8(m->cx) : m->xedd->op.uimm0, - m->xedd->op.opcode & 8, &m->flags)); -} - -static void OpFxsave(struct Machine *m, uint32_t rde) { - int64_t v; - uint8_t buf[32]; - bzero(buf, 32); - Write16(buf + 0, m->fpu.cw); - Write16(buf + 2, m->fpu.sw); - Write8(buf + 4, m->fpu.tw); - Write16(buf + 6, m->fpu.op); - Write32(buf + 8, m->fpu.ip); - Write32(buf + 24, m->sse.mxcsr); - v = ComputeAddress(m, rde); - VirtualRecv(m, v + 0, buf, 32); - VirtualRecv(m, v + 32, m->fpu.st, 128); - VirtualRecv(m, v + 160, m->xmm, 256); - SetWriteAddr(m, v, 416); -} - -static void OpFxrstor(struct Machine *m, uint32_t rde) { - int64_t v; - uint8_t buf[32]; - v = ComputeAddress(m, rde); - SetReadAddr(m, v, 416); - VirtualSend(m, buf, v + 0, 32); - VirtualSend(m, m->fpu.st, v + 32, 128); - VirtualSend(m, m->xmm, v + 160, 256); - m->fpu.cw = Read16(buf + 0); - m->fpu.sw = Read16(buf + 2); - m->fpu.tw = Read8(buf + 4); - m->fpu.op = Read16(buf + 6); - m->fpu.ip = Read32(buf + 8); - m->sse.mxcsr = Read32(buf + 24); -} - -static void OpXsave(struct Machine *m, uint32_t rde) { -} - -static void OpLdmxcsr(struct Machine *m, uint32_t rde) { - m->sse.mxcsr = Read32(ComputeReserveAddressRead4(m, rde)); -} - -static void OpStmxcsr(struct Machine *m, uint32_t rde) { - Write32(ComputeReserveAddressWrite4(m, rde), m->sse.mxcsr); -} - -static void OpRdfsbase(struct Machine *m, uint32_t rde) { - WriteRegister(rde, RegRexbRm(m, rde), Read64(m->fs)); -} - -static void OpRdgsbase(struct Machine *m, uint32_t rde) { - WriteRegister(rde, RegRexbRm(m, rde), Read64(m->gs)); -} - -static void OpWrfsbase(struct Machine *m, uint32_t rde) { - Write64(m->fs, ReadMemory(rde, RegRexbRm(m, rde))); -} - -static void OpWrgsbase(struct Machine *m, uint32_t rde) { - Write64(m->gs, ReadMemory(rde, RegRexbRm(m, rde))); -} - -static void Op1ae(struct Machine *m, uint32_t rde) { - bool ismem; - ismem = !IsModrmRegister(rde); - switch (ModrmReg(rde)) { - case 0: - if (ismem) { - OpFxsave(m, rde); - } else { - OpRdfsbase(m, rde); - } - break; - case 1: - if (ismem) { - OpFxrstor(m, rde); - } else { - OpRdgsbase(m, rde); - } - break; - case 2: - if (ismem) { - OpLdmxcsr(m, rde); - } else { - OpWrfsbase(m, rde); - } - break; - case 3: - if (ismem) { - OpStmxcsr(m, rde); - } else { - OpWrgsbase(m, rde); - } - break; - case 4: - if (ismem) { - OpXsave(m, rde); - } else { - OpUd(m, rde); - } - break; - case 5: - OpLfence(m, rde); - break; - case 6: - OpMfence(m, rde); - break; - case 7: - if (ismem) { - OpClflush(m, rde); - } else { - OpSfence(m, rde); - } - break; - default: - OpUd(m, rde); - } -} - -static void OpSalc(struct Machine *m, uint32_t rde) { - if (GetFlag(m->flags, FLAGS_CF)) { - m->ax[0] = 255; - } else { - m->ax[0] = 0; - } -} - -static void OpBofram(struct Machine *m, uint32_t rde) { - if (m->xedd->op.disp) { - m->bofram[0] = m->ip; - m->bofram[1] = m->ip + (m->xedd->op.disp & 0xff); - } else { - m->bofram[0] = 0; - m->bofram[1] = 0; - } -} - -static void OpBinbase(struct Machine *m, uint32_t rde) { - if (m->onbinbase) { - m->onbinbase(m); - } -} - -static void OpNopEv(struct Machine *m, uint32_t rde) { - switch (ModrmMod(rde) << 6 | ModrmReg(rde) << 3 | ModrmRm(rde)) { - case 0105: - OpBofram(m, rde); - break; - case 0106: - OpBofram(m, rde); - break; - case 0007: - case 0107: - case 0207: - OpBinbase(m, rde); - break; - default: - OpNoop(m, rde); - } -} - -static void OpNop(struct Machine *m, uint32_t rde) { - if (Rexb(rde)) { - OpXchgZvqp(m, rde); - } else if (Rep(rde) == 3) { - OpPause(m, rde); - } else { - OpNoop(m, rde); - } -} - -static void OpMovRqCq(struct Machine *m, uint32_t rde) { - switch (ModrmReg(rde)) { - case 0: - Write64(RegRexbRm(m, rde), m->cr0); - break; - case 2: - Write64(RegRexbRm(m, rde), m->cr2); - break; - case 3: - Write64(RegRexbRm(m, rde), m->cr3); - break; - case 4: - Write64(RegRexbRm(m, rde), m->cr4); - break; - default: - OpUd(m, rde); - } -} - -static void OpMovCqRq(struct Machine *m, uint32_t rde) { - int64_t cr3; - switch (ModrmReg(rde)) { - case 0: - m->cr0 = Read64(RegRexbRm(m, rde)); - break; - case 2: - m->cr2 = Read64(RegRexbRm(m, rde)); - break; - case 3: - cr3 = Read64(RegRexbRm(m, rde)); - if (0 <= cr3 && cr3 + 512 * 8 <= m->real.n) { - m->cr3 = cr3; - } else { - ThrowProtectionFault(m); - } - break; - case 4: - m->cr4 = Read64(RegRexbRm(m, rde)); - break; - default: - OpUd(m, rde); - } -} - -static void OpWrmsr(struct Machine *m, uint32_t rde) { -} - -static void OpRdmsr(struct Machine *m, uint32_t rde) { - Write32(m->dx, 0); - Write32(m->ax, 0); -} - -static void OpVzeroupper(struct Machine *m, uint32_t rde) { -} - -static void OpEmms(struct Machine *m, uint32_t rde) { - if (m->xedd->op.vexvalid) { - OpVzeroupper(m, rde); - } else { - m->fpu.tw = -1; - } -} - -static const nexgen32e_f kNexgen32e[] = { - [0x000] = OpAlubAdd, - [0x001] = OpAluw, - [0x002] = OpAlubFlipAdd, - [0x003] = OpAluwFlip, - [0x004] = OpAluAlIbAdd, - [0x005] = OpAluRaxIvds, - [0x006] = OpPushSeg, - [0x007] = OpPopSeg, - [0x008] = OpAlubOr, - [0x009] = OpAluw, - [0x00A] = OpAlubFlipOr, - [0x00B] = OpAluwFlip, - [0x00C] = OpAluAlIbOr, - [0x00D] = OpAluRaxIvds, - [0x00E] = OpPushSeg, - [0x00F] = OpPopSeg, - [0x010] = OpAlubAdc, - [0x011] = OpAluw, - [0x012] = OpAlubFlipAdc, - [0x013] = OpAluwFlip, - [0x014] = OpAluAlIbAdc, - [0x015] = OpAluRaxIvds, - [0x016] = OpPushSeg, - [0x017] = OpPopSeg, - [0x018] = OpAlubSbb, - [0x019] = OpAluw, - [0x01A] = OpAlubFlipSbb, - [0x01B] = OpAluwFlip, - [0x01C] = OpAluAlIbSbb, - [0x01D] = OpAluRaxIvds, - [0x01E] = OpPushSeg, - [0x01F] = OpPopSeg, - [0x020] = OpAlubAnd, - [0x021] = OpAluw, - [0x022] = OpAlubFlipAnd, - [0x023] = OpAluwFlip, - [0x024] = OpAluAlIbAnd, - [0x025] = OpAluRaxIvds, - [0x026] = OpPushSeg, - [0x027] = OpPopSeg, - [0x028] = OpAlubSub, - [0x029] = OpAluw, - [0x02A] = OpAlubFlipSub, - [0x02B] = OpAluwFlip, - [0x02C] = OpAluAlIbSub, - [0x02D] = OpAluRaxIvds, - [0x02E] = OpUd, - [0x02F] = OpDas, - [0x030] = OpAlubXor, - [0x031] = OpAluw, - [0x032] = OpAlubFlipXor, - [0x033] = OpAluwFlip, - [0x034] = OpAluAlIbXor, - [0x035] = OpAluRaxIvds, - [0x036] = OpUd, - [0x037] = OpAaa, - [0x038] = OpAlubCmp, - [0x039] = OpAluwCmp, - [0x03A] = OpAlubFlipCmp, - [0x03B] = OpAluwFlipCmp, - [0x03C] = OpCmpAlIb, - [0x03D] = OpCmpRaxIvds, - [0x03E] = OpUd, - [0x03F] = OpAas, - [0x040] = OpIncZv, - [0x041] = OpIncZv, - [0x042] = OpIncZv, - [0x043] = OpIncZv, - [0x044] = OpIncZv, - [0x045] = OpIncZv, - [0x046] = OpIncZv, - [0x047] = OpIncZv, - [0x048] = OpDecZv, - [0x049] = OpDecZv, - [0x04A] = OpDecZv, - [0x04B] = OpDecZv, - [0x04C] = OpDecZv, - [0x04D] = OpDecZv, - [0x04E] = OpDecZv, - [0x04F] = OpDecZv, - [0x050] = OpPushZvq, - [0x051] = OpPushZvq, - [0x052] = OpPushZvq, - [0x053] = OpPushZvq, - [0x054] = OpPushZvq, - [0x055] = OpPushZvq, - [0x056] = OpPushZvq, - [0x057] = OpPushZvq, - [0x058] = OpPopZvq, - [0x059] = OpPopZvq, - [0x05A] = OpPopZvq, - [0x05B] = OpPopZvq, - [0x05C] = OpPopZvq, - [0x05D] = OpPopZvq, - [0x05E] = OpPopZvq, - [0x05F] = OpPopZvq, - [0x060] = OpPusha, - [0x061] = OpPopa, - [0x062] = OpUd, - [0x063] = OpMovsxdGdqpEd, - [0x064] = OpUd, - [0x065] = OpUd, - [0x066] = OpUd, - [0x067] = OpUd, - [0x068] = OpPushImm, - [0x069] = OpImulGvqpEvqpImm, - [0x06A] = OpPushImm, - [0x06B] = OpImulGvqpEvqpImm, - [0x06C] = OpIns, - [0x06D] = OpIns, - [0x06E] = OpOuts, - [0x06F] = OpOuts, - [0x070] = OpJo, - [0x071] = OpJno, - [0x072] = OpJb, - [0x073] = OpJae, - [0x074] = OpJe, - [0x075] = OpJne, - [0x076] = OpJbe, - [0x077] = OpJa, - [0x078] = OpJs, - [0x079] = OpJns, - [0x07A] = OpJp, - [0x07B] = OpJnp, - [0x07C] = OpJl, - [0x07D] = OpJge, - [0x07E] = OpJle, - [0x07F] = OpJg, - [0x080] = OpAlubiReg, - [0x081] = OpAluwiReg, - [0x082] = OpAlubiReg, - [0x083] = OpAluwiReg, - [0x084] = OpAlubTest, - [0x085] = OpAluwTest, - [0x086] = OpXchgGbEb, - [0x087] = OpXchgGvqpEvqp, - [0x088] = OpMovEbGb, - [0x089] = OpMovEvqpGvqp, - [0x08A] = OpMovGbEb, - [0x08B] = OpMovGvqpEvqp, - [0x08C] = OpMovEvqpSw, - [0x08D] = OpLeaGvqpM, - [0x08E] = OpMovSwEvqp, - [0x08F] = OpPopEvq, - [0x090] = OpNop, - [0x091] = OpXchgZvqp, - [0x092] = OpXchgZvqp, - [0x093] = OpXchgZvqp, - [0x094] = OpXchgZvqp, - [0x095] = OpXchgZvqp, - [0x096] = OpXchgZvqp, - [0x097] = OpXchgZvqp, - [0x098] = OpSax, - [0x099] = OpConvert, - [0x09A] = OpCallf, - [0x09B] = OpFwait, - [0x09C] = OpPushf, - [0x09D] = OpPopf, - [0x09E] = OpSahf, - [0x09F] = OpLahf, - [0x0A0] = OpMovAlOb, - [0x0A1] = OpMovRaxOvqp, - [0x0A2] = OpMovObAl, - [0x0A3] = OpMovOvqpRax, - [0x0A4] = OpMovsb, - [0x0A5] = OpMovs, - [0x0A6] = OpCmps, - [0x0A7] = OpCmps, - [0x0A8] = OpTestAlIb, - [0x0A9] = OpTestRaxIvds, - [0x0AA] = OpStosb, - [0x0AB] = OpStos, - [0x0AC] = OpLods, - [0x0AD] = OpLods, - [0x0AE] = OpScas, - [0x0AF] = OpScas, - [0x0B0] = OpMovZbIb, - [0x0B1] = OpMovZbIb, - [0x0B2] = OpMovZbIb, - [0x0B3] = OpMovZbIb, - [0x0B4] = OpMovZbIb, - [0x0B5] = OpMovZbIb, - [0x0B6] = OpMovZbIb, - [0x0B7] = OpMovZbIb, - [0x0B8] = OpMovZvqpIvqp, - [0x0B9] = OpMovZvqpIvqp, - [0x0BA] = OpMovZvqpIvqp, - [0x0BB] = OpMovZvqpIvqp, - [0x0BC] = OpMovZvqpIvqp, - [0x0BD] = OpMovZvqpIvqp, - [0x0BE] = OpMovZvqpIvqp, - [0x0BF] = OpMovZvqpIvqp, - [0x0C0] = OpBsubiImm, - [0x0C1] = OpBsuwiImm, - [0x0C2] = OpRet, - [0x0C3] = OpRet, - [0x0C4] = OpLes, - [0x0C5] = OpLds, - [0x0C6] = OpMovEbIb, - [0x0C7] = OpMovEvqpIvds, - [0x0C8] = OpUd, - [0x0C9] = OpLeave, - [0x0CA] = OpRetf, - [0x0CB] = OpRetf, - [0x0CC] = OpInterrupt3, - [0x0CD] = OpInterruptImm, - [0x0CE] = OpInto, - [0x0CF] = OpUd, - [0x0D0] = OpBsubi1, - [0x0D1] = OpBsuwi1, - [0x0D2] = OpBsubiCl, - [0x0D3] = OpBsuwiCl, - [0x0D4] = OpAam, - [0x0D5] = OpAad, - [0x0D6] = OpSalc, - [0x0D7] = OpXlatAlBbb, - [0x0D8] = OpFpu, - [0x0D9] = OpFpu, - [0x0DA] = OpFpu, - [0x0DB] = OpFpu, - [0x0DC] = OpFpu, - [0x0DD] = OpFpu, - [0x0DE] = OpFpu, - [0x0DF] = OpFpu, - [0x0E0] = OpLoopne, - [0x0E1] = OpLoope, - [0x0E2] = OpLoop1, - [0x0E3] = OpJcxz, - [0x0E4] = OpInAlImm, - [0x0E5] = OpInAxImm, - [0x0E6] = OpOutImmAl, - [0x0E7] = OpOutImmAx, - [0x0E8] = OpCallJvds, - [0x0E9] = OpJmp, - [0x0EA] = OpJmpf, - [0x0EB] = OpJmp, - [0x0EC] = OpInAlDx, - [0x0ED] = OpInAxDx, - [0x0EE] = OpOutDxAl, - [0x0EF] = OpOutDxAx, - [0x0F0] = OpUd, - [0x0F1] = OpInterrupt1, - [0x0F2] = OpUd, - [0x0F3] = OpUd, - [0x0F4] = OpHlt, - [0x0F5] = OpCmc, - [0x0F6] = Op0f6, - [0x0F7] = Op0f7, - [0x0F8] = OpClc, - [0x0F9] = OpStc, - [0x0FA] = OpCli, - [0x0FB] = OpSti, - [0x0FC] = OpCld, - [0x0FD] = OpStd, - [0x0FE] = Op0fe, - [0x0FF] = Op0ff, - [0x100] = OpUd, - [0x101] = Op101, - [0x102] = OpUd, - [0x103] = OpLsl, - [0x104] = OpUd, - [0x105] = OpSyscall, - [0x106] = OpUd, - [0x107] = OpUd, - [0x108] = OpUd, - [0x109] = OpUd, - [0x10A] = OpUd, - [0x10B] = OpUd, - [0x10C] = OpUd, - [0x10D] = OpHintNopEv, - [0x10E] = OpUd, - [0x10F] = OpUd, - [0x110] = OpMov0f10, - [0x111] = OpMovWpsVps, - [0x112] = OpMov0f12, - [0x113] = OpMov0f13, - [0x114] = OpUnpcklpsd, - [0x115] = OpUnpckhpsd, - [0x116] = OpMov0f16, - [0x117] = OpMov0f17, - [0x118] = OpHintNopEv, - [0x119] = OpHintNopEv, - [0x11A] = OpHintNopEv, - [0x11B] = OpHintNopEv, - [0x11C] = OpHintNopEv, - [0x11D] = OpHintNopEv, - [0x11E] = OpHintNopEv, - [0x11F] = OpNopEv, - [0x120] = OpMovRqCq, - [0x121] = OpUd, - [0x122] = OpMovCqRq, - [0x123] = OpUd, - [0x124] = OpUd, - [0x125] = OpUd, - [0x126] = OpUd, - [0x127] = OpUd, - [0x128] = OpMov0f28, - [0x129] = OpMovWpsVps, - [0x12A] = OpCvt0f2a, - [0x12B] = OpMov0f2b, - [0x12C] = OpCvtt0f2c, - [0x12D] = OpCvt0f2d, - [0x12E] = OpComissVsWs, - [0x12F] = OpComissVsWs, - [0x130] = OpWrmsr, - [0x131] = OpRdtsc, - [0x132] = OpRdmsr, - [0x133] = OpUd, - [0x134] = OpUd, - [0x135] = OpUd, - [0x136] = OpUd, - [0x137] = OpUd, - [0x138] = OpUd, - [0x139] = OpUd, - [0x13A] = OpUd, - [0x13B] = OpUd, - [0x13C] = OpUd, - [0x13D] = OpUd, - [0x13E] = OpUd, - [0x13F] = OpUd, - [0x140] = OpCmovo, - [0x141] = OpCmovno, - [0x142] = OpCmovb, - [0x143] = OpCmovae, - [0x144] = OpCmove, - [0x145] = OpCmovne, - [0x146] = OpCmovbe, - [0x147] = OpCmova, - [0x148] = OpCmovs, - [0x149] = OpCmovns, - [0x14A] = OpCmovp, - [0x14B] = OpCmovnp, - [0x14C] = OpCmovl, - [0x14D] = OpCmovge, - [0x14E] = OpCmovle, - [0x14F] = OpCmovg, - [0x150] = OpUd, - [0x151] = OpSqrtpsd, - [0x152] = OpRsqrtps, - [0x153] = OpRcpps, - [0x154] = OpAndpsd, - [0x155] = OpAndnpsd, - [0x156] = OpOrpsd, - [0x157] = OpXorpsd, - [0x158] = OpAddpsd, - [0x159] = OpMulpsd, - [0x15A] = OpCvt0f5a, - [0x15B] = OpCvt0f5b, - [0x15C] = OpSubpsd, - [0x15D] = OpMinpsd, - [0x15E] = OpDivpsd, - [0x15F] = OpMaxpsd, - [0x160] = OpSsePunpcklbw, - [0x161] = OpSsePunpcklwd, - [0x162] = OpSsePunpckldq, - [0x163] = OpSsePacksswb, - [0x164] = OpSsePcmpgtb, - [0x165] = OpSsePcmpgtw, - [0x166] = OpSsePcmpgtd, - [0x167] = OpSsePackuswb, - [0x168] = OpSsePunpckhbw, - [0x169] = OpSsePunpckhwd, - [0x16A] = OpSsePunpckhdq, - [0x16B] = OpSsePackssdw, - [0x16C] = OpSsePunpcklqdq, - [0x16D] = OpSsePunpckhqdq, - [0x16E] = OpMov0f6e, - [0x16F] = OpMov0f6f, - [0x170] = OpShuffle, - [0x171] = Op171, - [0x172] = Op172, - [0x173] = Op173, - [0x174] = OpSsePcmpeqb, - [0x175] = OpSsePcmpeqw, - [0x176] = OpSsePcmpeqd, - [0x177] = OpEmms, - [0x178] = OpUd, - [0x179] = OpUd, - [0x17A] = OpUd, - [0x17B] = OpUd, - [0x17C] = OpHaddpsd, - [0x17D] = OpHsubpsd, - [0x17E] = OpMov0f7e, - [0x17F] = OpMov0f7f, - [0x180] = OpJo, - [0x181] = OpJno, - [0x182] = OpJb, - [0x183] = OpJae, - [0x184] = OpJe, - [0x185] = OpJne, - [0x186] = OpJbe, - [0x187] = OpJa, - [0x188] = OpJs, - [0x189] = OpJns, - [0x18A] = OpJp, - [0x18B] = OpJnp, - [0x18C] = OpJl, - [0x18D] = OpJge, - [0x18E] = OpJle, - [0x18F] = OpJg, - [0x190] = OpSeto, - [0x191] = OpSetno, - [0x192] = OpSetb, - [0x193] = OpSetae, - [0x194] = OpSete, - [0x195] = OpSetne, - [0x196] = OpSetbe, - [0x197] = OpSeta, - [0x198] = OpSets, - [0x199] = OpSetns, - [0x19A] = OpSetp, - [0x19B] = OpSetnp, - [0x19C] = OpSetl, - [0x19D] = OpSetge, - [0x19E] = OpSetle, - [0x19F] = OpSetg, - [0x1A0] = OpPushSeg, - [0x1A1] = OpPopSeg, - [0x1A2] = OpCpuid, - [0x1A3] = OpBit, - [0x1A4] = OpDoubleShift, - [0x1A5] = OpDoubleShift, - [0x1A6] = OpUd, - [0x1A7] = OpUd, - [0x1A8] = OpPushSeg, - [0x1A9] = OpPopSeg, - [0x1AA] = OpUd, - [0x1AB] = OpBit, - [0x1AC] = OpDoubleShift, - [0x1AD] = OpDoubleShift, - [0x1AE] = Op1ae, - [0x1AF] = OpImulGvqpEvqp, - [0x1B0] = OpCmpxchgEbAlGb, - [0x1B1] = OpCmpxchgEvqpRaxGvqp, - [0x1B2] = OpUd, - [0x1B3] = OpBit, - [0x1B4] = OpUd, - [0x1B5] = OpUd, - [0x1B6] = OpMovzbGvqpEb, - [0x1B7] = OpMovzwGvqpEw, - [0x1B8] = Op1b8, - [0x1B9] = OpUd, - [0x1BA] = OpBit, - [0x1BB] = OpBit, - [0x1BC] = OpBsf, - [0x1BD] = OpBsr, - [0x1BE] = OpMovsbGvqpEb, - [0x1BF] = OpMovswGvqpEw, - [0x1C0] = OpXaddEbGb, - [0x1C1] = OpXaddEvqpGvqp, - [0x1C2] = OpCmppsd, - [0x1C3] = OpMovntiMdqpGdqp, - [0x1C4] = OpPinsrwVdqEwIb, - [0x1C5] = OpPextrwGdqpUdqIb, - [0x1C6] = OpShufpsd, - [0x1C7] = Op1c7, - [0x1C8] = OpBswapZvqp, - [0x1C9] = OpBswapZvqp, - [0x1CA] = OpBswapZvqp, - [0x1CB] = OpBswapZvqp, - [0x1CC] = OpBswapZvqp, - [0x1CD] = OpBswapZvqp, - [0x1CE] = OpBswapZvqp, - [0x1CF] = OpBswapZvqp, - [0x1D0] = OpAddsubpsd, - [0x1D1] = OpSsePsrlwv, - [0x1D2] = OpSsePsrldv, - [0x1D3] = OpSsePsrlqv, - [0x1D4] = OpSsePaddq, - [0x1D5] = OpSsePmullw, - [0x1D6] = OpMov0fD6, - [0x1D7] = OpPmovmskbGdqpNqUdq, - [0x1D8] = OpSsePsubusb, - [0x1D9] = OpSsePsubusw, - [0x1DA] = OpSsePminub, - [0x1DB] = OpSsePand, - [0x1DC] = OpSsePaddusb, - [0x1DD] = OpSsePaddusw, - [0x1DE] = OpSsePmaxub, - [0x1DF] = OpSsePandn, - [0x1E0] = OpSsePavgb, - [0x1E1] = OpSsePsrawv, - [0x1E2] = OpSsePsradv, - [0x1E3] = OpSsePavgw, - [0x1E4] = OpSsePmulhuw, - [0x1E5] = OpSsePmulhw, - [0x1E6] = OpCvt0fE6, - [0x1E7] = OpMov0fE7, - [0x1E8] = OpSsePsubsb, - [0x1E9] = OpSsePsubsw, - [0x1EA] = OpSsePminsw, - [0x1EB] = OpSsePor, - [0x1EC] = OpSsePaddsb, - [0x1ED] = OpSsePaddsw, - [0x1EE] = OpSsePmaxsw, - [0x1EF] = OpSsePxor, - [0x1F0] = OpLddquVdqMdq, - [0x1F1] = OpSsePsllwv, - [0x1F2] = OpSsePslldv, - [0x1F3] = OpSsePsllqv, - [0x1F4] = OpSsePmuludq, - [0x1F5] = OpSsePmaddwd, - [0x1F6] = OpSsePsadbw, - [0x1F7] = OpMaskMovDiXmmRegXmmRm, - [0x1F8] = OpSsePsubb, - [0x1F9] = OpSsePsubw, - [0x1FA] = OpSsePsubd, - [0x1FB] = OpSsePsubq, - [0x1FC] = OpSsePaddb, - [0x1FD] = OpSsePaddw, - [0x1FE] = OpSsePaddd, - [0x1FF] = OpUd, - [0x200] = OpSsePshufb, - [0x201] = OpSsePhaddw, - [0x202] = OpSsePhaddd, - [0x203] = OpSsePhaddsw, - [0x204] = OpSsePmaddubsw, - [0x205] = OpSsePhsubw, - [0x206] = OpSsePhsubd, - [0x207] = OpSsePhsubsw, - [0x208] = OpSsePsignb, - [0x209] = OpSsePsignw, - [0x20A] = OpSsePsignd, - [0x20B] = OpSsePmulhrsw, -}; - -void ExecuteSparseInstruction(struct Machine *m, uint32_t rde, uint32_t d) { - switch (d) { - CASE(0x21c, OpSsePabsb(m, rde)); - CASE(0x21d, OpSsePabsw(m, rde)); - CASE(0x21e, OpSsePabsd(m, rde)); - CASE(0x22a, OpMovntdqaVdqMdq(m, rde)); - CASE(0x240, OpSsePmulld(m, rde)); - CASE(0x30f, OpSsePalignr(m, rde)); - CASE(0x344, OpSsePclmulqdq(m, rde)); - default: - OpUd(m, rde); - } -} - -void ExecuteInstruction(struct Machine *m) { - m->ip += m->xedd->length; - if (m->xedd->op.dispatch < ARRAYLEN(kNexgen32e)) { - kNexgen32e[m->xedd->op.dispatch](m, m->xedd->op.rde); - } else { - ExecuteSparseInstruction(m, m->xedd->op.rde, m->xedd->op.dispatch); - } - if (m->stashaddr) { - VirtualRecv(m, m->stashaddr, m->stash, m->stashsize); - m->stashaddr = 0; - } -} diff --git a/tool/build/lib/machine.h b/tool/build/lib/machine.h deleted file mode 100644 index c9cf4db0f..000000000 --- a/tool/build/lib/machine.h +++ /dev/null @@ -1,206 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_MACHINE_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_MACHINE_H_ -#include "libc/runtime/runtime.h" -#include "third_party/xed/x86.h" -#include "tool/build/lib/bits.h" -#include "tool/build/lib/fds.h" - -#define kMachineHalt -1 -#define kMachineDecodeError -2 -#define kMachineUndefinedInstruction -3 -#define kMachineSegmentationFault -4 -#define kMachineExit -5 -#define kMachineDivideError -6 -#define kMachineFpuException -7 -#define kMachineProtectionFault -8 -#define kMachineSimdException -9 -#define kMachineOverflow -10 - -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -struct Machine { - struct XedDecodedInst *xedd; - uint64_t ip; - uint8_t cs[8]; - uint8_t ss[8]; - uint64_t codevirt; - uint8_t *codehost; - uint32_t mode; - uint32_t flags; - uint32_t tlbindex; - uint32_t stashsize; - int64_t stashaddr; - int64_t readaddr; - int64_t writeaddr; - uint32_t readsize; - uint32_t writesize; - union { - uint8_t reg[16][8]; - struct { - uint8_t ax[8]; - uint8_t cx[8]; - uint8_t dx[8]; - uint8_t bx[8]; - uint8_t sp[8]; - uint8_t bp[8]; - uint8_t si[8]; - uint8_t di[8]; - uint8_t r8[8]; - uint8_t r9[8]; - uint8_t r10[8]; - uint8_t r11[8]; - uint8_t r12[8]; - uint8_t r13[8]; - uint8_t r14[8]; - uint8_t r15[8]; - }; - }; - struct MachineTlb { - int64_t virt; - uint64_t entry; - } tlb[16]; - struct MachineReal { - size_t i, n; - uint8_t *p; - } real; - uint64_t cr3; - uint8_t xmm[16][16]; - uint8_t es[8]; - uint8_t ds[8]; - uint8_t fs[8]; - uint8_t gs[8]; - struct MachineFpu { - long double st[8]; - union { - uint32_t cw; - struct { - unsigned im : 1; // invalid operation mask - unsigned dm : 1; // denormal operand mask - unsigned zm : 1; // zero divide mask - unsigned om : 1; // overflow mask - unsigned um : 1; // underflow mask - unsigned pm : 1; // precision mask - unsigned _p1 : 2; // reserved - unsigned pc : 2; // precision: 32,∅,64,80 - unsigned rc : 2; // rounding: even,→-∞,→+∞,→0 - }; - }; - union { - uint32_t sw; - struct { - unsigned ie : 1; // invalid operation - unsigned de : 1; // denormalized operand - unsigned ze : 1; // zero divide - unsigned oe : 1; // overflow - unsigned ue : 1; // underflow - unsigned pe : 1; // precision - unsigned sf : 1; // stack fault - unsigned es : 1; // exception summary status - unsigned c0 : 1; // condition 0 - unsigned c1 : 1; // condition 1 - unsigned c2 : 1; // condition 2 - unsigned sp : 3; // top stack - unsigned c3 : 1; // condition 3 - unsigned bf : 1; // busy flag - }; - }; - int tw; - int op; - int64_t ip; - int64_t dp; - } fpu; - struct MachineSse { - union { - uint32_t mxcsr; - struct { - unsigned ie : 1; // invalid operation flag - unsigned de : 1; // denormal flag - unsigned ze : 1; // divide by zero flag - unsigned oe : 1; // overflow flag - unsigned ue : 1; // underflow flag - unsigned pe : 1; // precision flag - unsigned daz : 1; // denormals are zeros - unsigned im : 1; // invalid operation mask - unsigned dm : 1; // denormal mask - unsigned zm : 1; // divide by zero mask - unsigned om : 1; // overflow mask - unsigned um : 1; // underflow mask - unsigned pm : 1; // precision mask - unsigned rc : 2; // rounding control - unsigned ftz : 1; // flush to zero - }; - }; - } sse; - uint64_t cr0; - uint64_t cr2; - uint64_t cr4; - uint64_t gdt_base; - uint64_t idt_base; - uint16_t gdt_limit; - uint16_t idt_limit; - uint32_t mxcsr; - struct MachineRealFree { - uint64_t i; - uint64_t n; - struct MachineRealFree *next; - } * realfree; - struct FreeList { - uint32_t i; - void *p[6]; - } freelist; - struct MachineMemstat { - int freed; - int resizes; - int reserved; - int committed; - int allocated; - int reclaimed; - int pagetables; - } memstat; - int64_t brk; - int64_t bofram[2]; - jmp_buf onhalt; - int64_t faultaddr; - bool dlab; - bool isfork; - bool ismetal; - struct MachineFds fds; - uint8_t stash[4096]; - uint8_t icache[1024][40]; - void (*onbinbase)(struct Machine *); - void (*onlongbranch)(struct Machine *); - void (*redraw)(void); - struct sigaction_bits sighand[28]; - uint8_t sigmask[8]; - int sig; - uint64_t siguc; - uint64_t sigfp; - struct { - int i, n; - struct { - int sig; - int code; - } p[64]; - } signals; -} forcealign(64); - -struct Machine *NewMachine(void) dontdiscard; -void FreeMachine(struct Machine *); -void ResetMem(struct Machine *); -void ResetCpu(struct Machine *); -void ResetTlb(struct Machine *); -void ResetInstructionCache(struct Machine *); -void LoadInstruction(struct Machine *); -void ExecuteInstruction(struct Machine *); -long AllocateLinearPage(struct Machine *); -long AllocateLinearPageRaw(struct Machine *); -int ReserveReal(struct Machine *, size_t); -int ReserveVirtual(struct Machine *, int64_t, size_t, uint64_t); -char *FormatPml4t(struct Machine *) dontdiscard; -int64_t FindVirtual(struct Machine *, int64_t, size_t); -int FreeVirtual(struct Machine *, int64_t, size_t); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_MACHINE_H_ */ diff --git a/tool/build/lib/mda.c b/tool/build/lib/mda.c deleted file mode 100644 index 012509479..000000000 --- a/tool/build/lib/mda.c +++ /dev/null @@ -1,70 +0,0 @@ -/*-*- 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/macros.internal.h" -#include "libc/str/str.h" -#include "libc/str/tab.internal.h" -#include "tool/build/lib/buffer.h" -#include "tool/build/lib/mda.h" - -#define kBlink 1 -#define kVisible 2 -#define kUnderline 4 -#define kBold 8 -#define kReverse 16 - -/** - * Decodes Monochrome Display Adapter attributes. - * @see https://www.seasip.info/VintagePC/mda.html - */ -static uint8_t DecodeMdaAttributes(int8_t a) { - uint8_t r = 0; - if (a & 0x77) { - if ((a & 0x77) == 0x70) r |= kReverse; - if ((a & 0x07) == 0x01) r |= kUnderline; - if (a & 0x08) r |= kBold; - if (a < 0) r |= kBlink; - r |= kVisible; - } - return r; -} - -void DrawMda(struct Panel *p, uint8_t v[25][80][2]) { - unsigned y, x, n, a, b; - n = MIN(25, p->bottom - p->top); - for (y = 0; y < n; ++y) { - a = -1; - for (x = 0; x < 80; ++x) { - b = DecodeMdaAttributes(v[y][x][1]); - if (a != b) { - a = b; - AppendStr(&p->lines[y], "\e[0"); - if (a & kBold) AppendStr(&p->lines[y], ";1"); - if (a & kUnderline) AppendStr(&p->lines[y], ";4"); - if (a & kBlink) AppendStr(&p->lines[y], ";5"); - if (a & kReverse) AppendStr(&p->lines[y], ";7"); - AppendChar(&p->lines[y], 'm'); - } - if (a) { - AppendWide(&p->lines[y], kCp437[v[y][x][0]]); - } else { - AppendChar(&p->lines[y], ' '); - } - } - } -} diff --git a/tool/build/lib/mda.h b/tool/build/lib/mda.h deleted file mode 100644 index 84eb7c465..000000000 --- a/tool/build/lib/mda.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_MDA_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_MDA_H_ -#include "tool/build/lib/panel.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -void DrawMda(struct Panel *, uint8_t[25][80][2]); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_MDA_H_ */ diff --git a/tool/build/lib/memory.c b/tool/build/lib/memory.c deleted file mode 100644 index f8e6391dd..000000000 --- a/tool/build/lib/memory.c +++ /dev/null @@ -1,288 +0,0 @@ -/*-*- 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/log/check.h" -#include "libc/macros.internal.h" -#include "libc/mem/mem.h" -#include "libc/nt/struct/importobjectheader.internal.h" -#include "libc/runtime/memtrack.internal.h" -#include "libc/runtime/pc.internal.h" -#include "libc/str/str.h" -#include "tool/build/lib/memory.h" -#include "tool/build/lib/throw.h" - -void SetReadAddr(struct Machine *m, int64_t addr, uint32_t size) { - if (size) { - m->readaddr = addr; - m->readsize = size; - } -} - -void SetWriteAddr(struct Machine *m, int64_t addr, uint32_t size) { - if (size) { - m->writeaddr = addr; - m->writesize = size; - } -} - -uint64_t HandlePageFault(struct Machine *m, int64_t virt, uint64_t entry, - uint64_t table, unsigned index) { - long page; - if ((page = AllocateLinearPage(m)) != -1) { - --m->memstat.reserved; - if (entry & PAGE_GROD) { - ReserveVirtual(m, virt - 4096, 4096, - PAGE_GROD | PAGE_RSRV | - (entry & (PAGE_XD | PAGE_U | PAGE_RW | PAGE_V))); - } - return (*(uint64_t *)(m->real.p + table + index * 8) = - page | entry & ~(PAGE_TA | PAGE_IGN1)); - } else { - return 0; - } -} - -uint64_t FindPage(struct Machine *m, int64_t virt) { - uint64_t table, entry; - unsigned level, index, i; - virt &= -4096; - for (i = 0; i < ARRAYLEN(m->tlb); ++i) { - if (m->tlb[i].virt == virt && (m->tlb[i].entry & 1)) { - return m->tlb[i].entry; - } - } - level = 39; - entry = m->cr3; - do { - table = entry & PAGE_TA; - CHECK_LT(table, m->real.n); - index = (virt >> level) & 511; - entry = *(uint64_t *)(m->real.p + table + index * 8); - if (!(entry & 1)) return 0; - } while ((level -= 9) >= 12); - if ((entry & PAGE_RSRV) && - (entry = HandlePageFault(m, virt, entry, table, index)) == -1) { - return 0; - } - m->tlbindex = (m->tlbindex + 1) & (ARRAYLEN(m->tlb) - 1); - m->tlb[m->tlbindex] = m->tlb[0]; - m->tlb[0].virt = virt; - m->tlb[0].entry = entry; - return entry; -} - -void *FindReal(struct Machine *m, int64_t virt) { - uint64_t table, entry, page; - unsigned skew, level, index, i; - if ((m->mode & 3) != XED_MODE_REAL) { - if (IsLegalPointer(virt)) { - if (!(entry = FindPage(m, virt))) return NULL; - return m->real.p + (entry & PAGE_TA) + (virt & 0xfff); - } else { - return NULL; - } - } else if (0 <= virt && virt + 0xfff < m->real.n) { - return m->real.p + virt; - } else { - return NULL; - } -} - -void *ResolveAddress(struct Machine *m, int64_t v) { - void *r; - if ((r = FindReal(m, v))) return r; - ThrowSegmentationFault(m, v); -} - -void VirtualSet(struct Machine *m, int64_t v, char c, uint64_t n) { - char *p; - uint64_t k; - k = 4096 - (v & 0xfff); - while (n) { - k = MIN(k, n); - p = ResolveAddress(m, v); - memset(p, c, k); - n -= k; - v += k; - k = 4096; - } -} - -void VirtualCopy(struct Machine *m, int64_t v, char *r, uint64_t n, bool d) { - char *p; - uint64_t k; - k = 4096 - (v & 0xfff); - while (n) { - k = MIN(k, n); - p = ResolveAddress(m, v); - if (d) { - memcpy(r, p, k); - } else { - memcpy(p, r, k); - } - n -= k; - r += k; - v += k; - k = 4096; - } -} - -void *VirtualSend(struct Machine *m, void *dst, int64_t src, uint64_t n) { - VirtualCopy(m, src, dst, n, true); - return dst; -} - -void VirtualSendRead(struct Machine *m, void *dst, int64_t addr, uint64_t n) { - VirtualSend(m, dst, addr, n); - SetReadAddr(m, addr, n); -} - -void VirtualRecv(struct Machine *m, int64_t dst, void *src, uint64_t n) { - VirtualCopy(m, dst, src, n, false); -} - -void VirtualRecvWrite(struct Machine *m, int64_t addr, void *src, uint64_t n) { - VirtualRecv(m, addr, src, n); - SetWriteAddr(m, addr, n); -} - -void *ReserveAddress(struct Machine *m, int64_t v, size_t n) { - void *r; - DCHECK_LE(n, sizeof(m->stash)); - if ((v & 0xfff) + n <= 4096) return ResolveAddress(m, v); - m->stashaddr = v; - m->stashsize = n; - r = m->stash; - VirtualSend(m, r, v, n); - return r; -} - -void *AccessRam(struct Machine *m, int64_t v, size_t n, void *p[2], - uint8_t *tmp, bool copy) { - unsigned k; - uint8_t *a, *b; - DCHECK_LE(n, 4096); - if ((v & 0xfff) + n <= 4096) return ResolveAddress(m, v); - k = 4096; - k -= v & 0xfff; - DCHECK_LE(k, 4096); - a = ResolveAddress(m, v); - b = ResolveAddress(m, v + k); - if (copy) { - memcpy(tmp, a, k); - memcpy(tmp + k, b, n - k); - } - p[0] = a; - p[1] = b; - return tmp; -} - -void *Load(struct Machine *m, int64_t v, size_t n, uint8_t *b) { - void *p[2]; - SetReadAddr(m, v, n); - return AccessRam(m, v, n, p, b, true); -} - -void *BeginStore(struct Machine *m, int64_t v, size_t n, void *p[2], - uint8_t *b) { - SetWriteAddr(m, v, n); - return AccessRam(m, v, n, p, b, false); -} - -void *BeginStoreNp(struct Machine *m, int64_t v, size_t n, void *p[2], - uint8_t *b) { - if (!v) return NULL; - return BeginStore(m, v, n, p, b); -} - -void *BeginLoadStore(struct Machine *m, int64_t v, size_t n, void *p[2], - uint8_t *b) { - SetWriteAddr(m, v, n); - return AccessRam(m, v, n, p, b, true); -} - -void EndStore(struct Machine *m, int64_t v, size_t n, void *p[2], uint8_t *b) { - uint8_t *a; - unsigned k; - DCHECK_LE(n, 4096); - if ((v & 0xfff) + n <= 4096) return; - k = 4096; - k -= v & 0xfff; - DCHECK_GT(k, n); - DCHECK_NOTNULL(p[0]); - DCHECK_NOTNULL(p[1]); - memcpy(p[0], b, k); - memcpy(p[1], b + k, n - k); -} - -void EndStoreNp(struct Machine *m, int64_t v, size_t n, void *p[2], - uint8_t *b) { - if (v) EndStore(m, v, n, p, b); -} - -void *LoadStr(struct Machine *m, int64_t addr) { - size_t have; - char *copy, *page, *p; - have = 4096 - (addr & 0xfff); - if (!addr) return NULL; - if (!(page = FindReal(m, addr))) return NULL; - if ((p = memchr(page, '\0', have))) { - SetReadAddr(m, addr, p - page + 1); - return page; - } - CHECK_LT(m->freelist.i, ARRAYLEN(m->freelist.p)); - if (!(copy = malloc(have + 4096))) return NULL; - memcpy(copy, page, have); - for (;;) { - if (!(page = FindReal(m, addr + have))) break; - if ((p = memccpy(copy + have, page, '\0', 4096))) { - SetReadAddr(m, addr, have + (p - (copy + have)) + 1); - return (m->freelist.p[m->freelist.i++] = copy); - } - have += 4096; - if (!(p = realloc(copy, have + 4096))) break; - copy = p; - } - free(copy); - return NULL; -} - -void *LoadBuf(struct Machine *m, int64_t addr, size_t size) { - size_t have, need; - char *buf, *copy, *page; - have = 4096 - (addr & 0xfff); - if (!addr) return NULL; - if (!(buf = FindReal(m, addr))) return NULL; - if (size > have) { - CHECK_LT(m->freelist.i, ARRAYLEN(m->freelist.p)); - if (!(copy = malloc(size))) return NULL; - buf = memcpy(copy, buf, have); - do { - need = MIN(4096, size - have); - if ((page = FindReal(m, addr + have))) { - memcpy(copy + have, page, need); - have += need; - } else { - free(copy); - return NULL; - } - } while (have < size); - } - SetReadAddr(m, addr, size); - return buf; -} diff --git a/tool/build/lib/memory.h b/tool/build/lib/memory.h deleted file mode 100644 index a2d7c075c..000000000 --- a/tool/build/lib/memory.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_MEMORY_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_MEMORY_H_ -#include "tool/build/lib/machine.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -int RegisterMemory(struct Machine *, int64_t, void *, size_t); -uint64_t FindPage(struct Machine *, int64_t); -void *AccessRam(struct Machine *, int64_t, size_t, void *[2], uint8_t *, bool); -void *BeginLoadStore(struct Machine *, int64_t, size_t, void *[2], uint8_t *); -void *BeginStore(struct Machine *, int64_t, size_t, void *[2], uint8_t *); -void *BeginStoreNp(struct Machine *, int64_t, size_t, void *[2], uint8_t *); -void *FindReal(struct Machine *, int64_t); -void *Load(struct Machine *, int64_t, size_t, uint8_t *); -void *LoadBuf(struct Machine *, int64_t, size_t); -void *LoadStr(struct Machine *, int64_t); -void *MallocPage(void); -void *RealAddress(struct Machine *, int64_t); -void *ReserveAddress(struct Machine *, int64_t, size_t); -void *ResolveAddress(struct Machine *, int64_t); -void *VirtualSend(struct Machine *, void *, int64_t, uint64_t); -void EndStore(struct Machine *, int64_t, size_t, void *[2], uint8_t *); -void EndStoreNp(struct Machine *, int64_t, size_t, void *[2], uint8_t *); -void ResetRam(struct Machine *); -void SetReadAddr(struct Machine *, int64_t, uint32_t); -void SetWriteAddr(struct Machine *, int64_t, uint32_t); -void VirtualRecv(struct Machine *, int64_t, void *, uint64_t); -void VirtualRecvWrite(struct Machine *, int64_t, void *, uint64_t); -void VirtualSendRead(struct Machine *, void *, int64_t, uint64_t); -void VirtualSet(struct Machine *, int64_t, char, uint64_t); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_MEMORY_H_ */ diff --git a/tool/build/lib/memorymalloc.c b/tool/build/lib/memorymalloc.c deleted file mode 100644 index d4c312cca..000000000 --- a/tool/build/lib/memorymalloc.c +++ /dev/null @@ -1,224 +0,0 @@ -/*-*- 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/log/check.h" -#include "libc/mem/mem.h" -#include "libc/runtime/pc.internal.h" -#include "libc/str/str.h" -#include "libc/sysv/errfuns.h" -#include "libc/x/x.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/machine.h" - -struct Machine *NewMachine(void) { - struct Machine *m; - m = xmemalignzero(_Alignof(struct Machine), sizeof(struct Machine)); - ResetCpu(m); - ResetMem(m); - return m; -} - -static void FreeMachineRealFree(struct Machine *m) { - struct MachineRealFree *rf; - while ((rf = m->realfree)) { - m->realfree = rf->next; - free(rf); - } -} - -void FreeMachine(struct Machine *m) { - if (m) { - FreeMachineRealFree(m); - free(m->real.p); - free(m); - } -} - -void ResetMem(struct Machine *m) { - FreeMachineRealFree(m); - ResetTlb(m); - bzero(&m->memstat, sizeof(m->memstat)); - m->real.i = 0; - m->cr3 = 0; -} - -long AllocateLinearPage(struct Machine *m) { - long page; - if ((page = AllocateLinearPageRaw(m)) != -1) { - bzero(m->real.p + page, 4096); - } - return page; -} - -long AllocateLinearPageRaw(struct Machine *m) { - uint8_t *p; - size_t i, n; - struct MachineRealFree *rf; - if ((rf = m->realfree)) { - DCHECK(rf->n); - DCHECK_EQ(0, rf->i & 4095); - DCHECK_EQ(0, rf->n & 4095); - DCHECK_LE(rf->i + rf->n, m->real.i); - i = rf->i; - rf->i += 4096; - if (!(rf->n -= 4096)) { - m->realfree = rf->next; - free(rf); - } - --m->memstat.freed; - ++m->memstat.reclaimed; - } else { - i = m->real.i; - n = m->real.n; - p = m->real.p; - if (i == n) { - if (n) { - n += n >> 1; - } else { - n = 65536; - } - n = ROUNDUP(n, 4096); - if ((p = realloc(p, n))) { - m->real.p = p; - m->real.n = n; - ResetTlb(m); - ++m->memstat.resizes; - } else { - return -1; - } - } - DCHECK_EQ(0, i & 4095); - DCHECK_EQ(0, n & 4095); - DCHECK_LE(i + 4096, n); - m->real.i += 4096; - ++m->memstat.allocated; - } - ++m->memstat.committed; - return i; -} - -static uint64_t MachineRead64(struct Machine *m, unsigned long i) { - CHECK_LE(i + 8, m->real.n); - return Read64(m->real.p + i); -} - -static void MachineWrite64(struct Machine *m, unsigned long i, uint64_t x) { - CHECK_LE(i + 8, m->real.n); - Write64(m->real.p + i, x); -} - -int ReserveReal(struct Machine *m, size_t n) { - uint8_t *p; - DCHECK_EQ(0, n & 4095); - if (m->real.n < n) { - if ((p = realloc(m->real.p, n))) { - m->real.p = p; - m->real.n = n; - ResetTlb(m); - ++m->memstat.resizes; - } else { - return -1; - } - } - return 0; -} - -int ReserveVirtual(struct Machine *m, int64_t virt, size_t size, uint64_t key) { - int64_t ti, mi, pt, end, level; - for (end = virt + size;;) { - for (pt = m->cr3, level = 39; level >= 12; level -= 9) { - pt = pt & PAGE_TA; - ti = (virt >> level) & 511; - mi = (pt & PAGE_TA) + ti * 8; - pt = MachineRead64(m, mi); - if (level > 12) { - if (!(pt & 1)) { - if ((pt = AllocateLinearPage(m)) == -1) return -1; - MachineWrite64(m, mi, pt | 7); - ++m->memstat.pagetables; - } - continue; - } - for (;;) { - if (!(pt & 1)) { - MachineWrite64(m, mi, key); - ++m->memstat.reserved; - } - if ((virt += 4096) >= end) return 0; - if (++ti == 512) break; - pt = MachineRead64(m, (mi += 8)); - } - } - } -} - -int64_t FindVirtual(struct Machine *m, int64_t virt, size_t size) { - uint64_t i, pt, got; - got = 0; - do { - if (virt >= 0x800000000000) return enomem(); - for (pt = m->cr3, i = 39; i >= 12; i -= 9) { - pt = MachineRead64(m, (pt & PAGE_TA) + ((virt >> i) & 511) * 8); - if (!(pt & 1)) break; - } - if (i >= 12) { - got += 1ull << i; - } else { - virt += 4096; - got = 0; - } - } while (got < size); - return virt; -} - -static void AppendRealFree(struct Machine *m, uint64_t real) { - struct MachineRealFree *rf; - if (m->realfree && real == m->realfree->i + m->realfree->n) { - m->realfree->n += 4096; - } else if ((rf = malloc(sizeof(struct MachineRealFree)))) { - rf->i = real; - rf->n = 4096; - rf->next = m->realfree; - m->realfree = rf; - } -} - -int FreeVirtual(struct Machine *m, int64_t base, size_t size) { - uint64_t i, mi, pt, end, virt; - for (virt = base, end = virt + size; virt < end; virt += 1ull << i) { - for (pt = m->cr3, i = 39;; i -= 9) { - mi = (pt & PAGE_TA) + ((virt >> i) & 511) * 8; - pt = MachineRead64(m, mi); - if (!(pt & 1)) { - break; - } else if (i == 12) { - ++m->memstat.freed; - if (pt & PAGE_RSRV) { - --m->memstat.reserved; - } else { - --m->memstat.committed; - AppendRealFree(m, pt & PAGE_TA); - } - MachineWrite64(m, mi, 0); - break; - } - } - } - ResetTlb(m); - return 0; -} diff --git a/tool/build/lib/message.c b/tool/build/lib/message.c deleted file mode 100644 index 20869d229..000000000 --- a/tool/build/lib/message.c +++ /dev/null @@ -1,66 +0,0 @@ -/*-*- 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/log/check.h" -#include "libc/macros.internal.h" -#include "libc/mem/mem.h" -#include "libc/str/str.h" -#include "libc/str/strwidth.h" -#include "tool/build/lib/buffer.h" -#include "tool/build/lib/lines.h" -#include "tool/build/lib/panel.h" - -static int GetWidthOfLongestLine(struct Lines *lines) { - int i, w, m; - for (m = i = 0; i < lines->n; ++i) { - w = strwidth(lines->p[i], 0); - m = MAX(m, w); - } - return m; -} - -void PrintMessageBox(int fd, const char *msg, long tyn, long txn) { - struct Buffer b; - int i, w, h, x, y; - struct Lines *lines; - lines = NewLines(); - AppendLines(lines, msg); - h = 3 + lines->n + 3; - w = 4 + GetWidthOfLongestLine(lines) + 4; - x = (txn / 2. - w / 2.) + .5; - y = (tyn / 2. - h / 2.) + .5; - bzero(&b, sizeof(b)); - AppendFmt(&b, "\e[%d;%dH", y++, x); - for (i = 0; i < w; ++i) AppendStr(&b, " "); - AppendFmt(&b, "\e[%d;%dH ╔", y++, x); - for (i = 0; i < w - 4; ++i) AppendStr(&b, "═"); - AppendStr(&b, "╗ "); - AppendFmt(&b, "\e[%d;%dH ║ %-*s ║ ", y++, x, w - 8, ""); - for (i = 0; i < lines->n; ++i) { - AppendFmt(&b, "\e[%d;%dH ║ %-*s ║ ", y++, x, w - 8, lines->p[i]); - } - FreeLines(lines); - AppendFmt(&b, "\e[%d;%dH ║ %-*s ║ ", y++, x, w - 8, ""); - AppendFmt(&b, "\e[%d;%dH ╚", y++, x); - for (i = 0; i < w - 4; ++i) AppendStr(&b, "═"); - AppendStr(&b, "╝ "); - AppendFmt(&b, "\e[%d;%dH", y++, x); - for (i = 0; i < w; ++i) AppendStr(&b, " "); - CHECK_NE(-1, WriteBuffer(&b, fd)); - free(b.p); -} diff --git a/tool/build/lib/modrm.c b/tool/build/lib/modrm.c deleted file mode 100644 index 9e2e5fadc..000000000 --- a/tool/build/lib/modrm.c +++ /dev/null @@ -1,324 +0,0 @@ -/*-*- 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 "tool/build/lib/modrm.h" -#include "libc/log/check.h" -#include "third_party/xed/x86.h" -#include "tool/build/lib/address.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/machine.h" -#include "tool/build/lib/memory.h" -#include "tool/build/lib/throw.h" - -/** - * Compactly represents important parts of xed ild result. - */ -uint32_t EncodeRde(struct XedDecodedInst *x) { - uint8_t kWordLog2[2][2][2] = {{{2, 3}, {1, 3}}, {{0, 0}, {0, 0}}}; - uint32_t osz = x->op.osz ^ x->op.realmode; - return kWordLog2[~x->op.opcode & 1][osz][x->op.rexw] << 28 | - x->op.mode << 26 | kXedEamode[x->op.asz][x->op.mode] << 24 | - (uint32_t)x->op.rep << 30 | x->op.mod << 22 | x->op.asz << 17 | - x->op.seg_ovd << 18 | x->op.rexw << 6 | osz << 5 | - (x->op.rex << 4 | x->op.rexb << 3 | x->op.srm) << 12 | - (x->op.rex << 4 | x->op.rexb << 3 | x->op.rm) << 7 | - (x->op.rex << 4 | x->op.rexr << 3 | x->op.reg); -} - -struct AddrSeg LoadEffectiveAddress(const struct Machine *m, uint32_t rde) { - uint8_t *s = m->ds; - uint64_t i = m->xedd->op.disp; - DCHECK(!IsModrmRegister(rde)); - if (Eamode(rde) != XED_MODE_REAL) { - if (!SibExists(rde)) { - if (IsRipRelative(rde)) { - if (Mode(rde) == XED_MODE_LONG) { - i += m->ip; - } - } else { - i += Read64(RegRexbRm(m, rde)); - if (RexbRm(rde) == 4 || RexbRm(rde) == 5) { - s = m->ss; - } - } - } else { - if (SibHasBase(m->xedd, rde)) { - i += Read64(RegRexbBase(m, rde)); - if (RexbBase(m, rde) == 4 || RexbBase(m, rde) == 5) { - s = m->ss; - } - } - if (SibHasIndex(m->xedd)) { - i += Read64(RegRexxIndex(m)) << m->xedd->op.scale; - } - } - if (Eamode(rde) == XED_MODE_LEGACY) { - i &= 0xffffffff; - } - } else { - switch (ModrmRm(rde)) { - case 0: - i += Read16(m->bx); - i += Read16(m->si); - break; - case 1: - i += Read16(m->bx); - i += Read16(m->di); - break; - case 2: - s = m->ss; - i += Read16(m->bp); - i += Read16(m->si); - break; - case 3: - s = m->ss; - i += Read16(m->bp); - i += Read16(m->di); - break; - case 4: - i += Read16(m->si); - break; - case 5: - i += Read16(m->di); - break; - case 6: - if (ModrmMod(rde)) { - s = m->ss; - i += Read16(m->bp); - } - break; - case 7: - i += Read16(m->bx); - break; - default: - __builtin_unreachable(); - } - i &= 0xffff; - } - return (struct AddrSeg){i, s}; -} - -int64_t ComputeAddress(const struct Machine *m, uint32_t rde) { - struct AddrSeg ea; - ea = LoadEffectiveAddress(m, rde); - return AddSegment(m, rde, ea.addr, ea.seg); -} - -void *ComputeReserveAddressRead(struct Machine *m, uint32_t rde, size_t n) { - int64_t v; - v = ComputeAddress(m, rde); - SetReadAddr(m, v, n); - return ReserveAddress(m, v, n); -} - -void *ComputeReserveAddressRead1(struct Machine *m, uint32_t rde) { - return ComputeReserveAddressRead(m, rde, 1); -} - -void *ComputeReserveAddressRead4(struct Machine *m, uint32_t rde) { - return ComputeReserveAddressRead(m, rde, 4); -} - -void *ComputeReserveAddressRead8(struct Machine *m, uint32_t rde) { - return ComputeReserveAddressRead(m, rde, 8); -} - -void *ComputeReserveAddressWrite(struct Machine *m, uint32_t rde, size_t n) { - int64_t v; - v = ComputeAddress(m, rde); - SetWriteAddr(m, v, n); - return ReserveAddress(m, v, n); -} - -void *ComputeReserveAddressWrite1(struct Machine *m, uint32_t rde) { - return ComputeReserveAddressWrite(m, rde, 1); -} - -void *ComputeReserveAddressWrite4(struct Machine *m, uint32_t rde) { - return ComputeReserveAddressWrite(m, rde, 4); -} - -void *ComputeReserveAddressWrite8(struct Machine *m, uint32_t rde) { - return ComputeReserveAddressWrite(m, rde, 8); -} - -uint8_t *GetModrmRegisterMmPointerRead(struct Machine *m, uint32_t rde, - size_t n) { - if (IsModrmRegister(rde)) { - return MmRm(m, rde); - } else { - return ComputeReserveAddressRead(m, rde, n); - } -} - -uint8_t *GetModrmRegisterMmPointerRead8(struct Machine *m, uint32_t rde) { - return GetModrmRegisterMmPointerRead(m, rde, 8); -} - -uint8_t *GetModrmRegisterMmPointerWrite(struct Machine *m, uint32_t rde, - size_t n) { - if (IsModrmRegister(rde)) { - return MmRm(m, rde); - } else { - return ComputeReserveAddressWrite(m, rde, n); - } -} - -uint8_t *GetModrmRegisterMmPointerWrite8(struct Machine *m, uint32_t rde) { - return GetModrmRegisterMmPointerWrite(m, rde, 8); -} - -uint8_t *GetModrmRegisterBytePointerRead(struct Machine *m, uint32_t rde) { - int64_t v; - if (IsModrmRegister(rde)) { - return ByteRexbRm(m, rde); - } else { - return ComputeReserveAddressRead1(m, rde); - } -} - -uint8_t *GetModrmRegisterBytePointerWrite(struct Machine *m, uint32_t rde) { - int64_t v; - if (IsModrmRegister(rde)) { - return ByteRexbRm(m, rde); - } else { - return ComputeReserveAddressWrite1(m, rde); - } -} - -uint8_t *GetModrmRegisterWordPointerRead(struct Machine *m, uint32_t rde, - size_t n) { - if (IsModrmRegister(rde)) { - return RegRexbRm(m, rde); - } else { - return ComputeReserveAddressRead(m, rde, n); - } -} - -uint8_t *GetModrmRegisterWordPointerRead2(struct Machine *m, uint32_t rde) { - return GetModrmRegisterWordPointerRead(m, rde, 2); -} - -uint8_t *GetModrmRegisterWordPointerRead4(struct Machine *m, uint32_t rde) { - return GetModrmRegisterWordPointerRead(m, rde, 4); -} - -uint8_t *GetModrmRegisterWordPointerRead8(struct Machine *m, uint32_t rde) { - return GetModrmRegisterWordPointerRead(m, rde, 8); -} - -uint8_t *GetModrmRegisterWordPointerReadOsz(struct Machine *m, uint32_t rde) { - if (!Osz(rde)) { - return GetModrmRegisterWordPointerRead8(m, rde); - } else { - return GetModrmRegisterWordPointerRead2(m, rde); - } -} - -uint8_t *GetModrmRegisterWordPointerReadOszRexw(struct Machine *m, - uint32_t rde) { - if (Rexw(rde)) { - return GetModrmRegisterWordPointerRead8(m, rde); - } else if (!Osz(rde)) { - return GetModrmRegisterWordPointerRead4(m, rde); - } else { - return GetModrmRegisterWordPointerRead2(m, rde); - } -} - -uint8_t *GetModrmRegisterWordPointerWrite(struct Machine *m, uint32_t rde, - size_t n) { - if (IsModrmRegister(rde)) { - return RegRexbRm(m, rde); - } else { - return ComputeReserveAddressWrite(m, rde, n); - } -} - -uint8_t *GetModrmRegisterWordPointerWrite2(struct Machine *m, uint32_t rde) { - return GetModrmRegisterWordPointerWrite(m, rde, 2); -} - -uint8_t *GetModrmRegisterWordPointerWrite4(struct Machine *m, uint32_t rde) { - return GetModrmRegisterWordPointerWrite(m, rde, 4); -} - -uint8_t *GetModrmRegisterWordPointerWrite8(struct Machine *m, uint32_t rde) { - return GetModrmRegisterWordPointerWrite(m, rde, 8); -} - -uint8_t *GetModrmRegisterWordPointerWriteOszRexw(struct Machine *m, - uint32_t rde) { - if (Rexw(rde)) { - return GetModrmRegisterWordPointerWrite(m, rde, 8); - } else if (!Osz(rde)) { - return GetModrmRegisterWordPointerWrite(m, rde, 4); - } else { - return GetModrmRegisterWordPointerWrite(m, rde, 2); - } -} - -uint8_t *GetModrmRegisterWordPointerWriteOsz(struct Machine *m, uint32_t rde) { - if (!Osz(rde)) { - return GetModrmRegisterWordPointerWrite(m, rde, 8); - } else { - return GetModrmRegisterWordPointerWrite(m, rde, 2); - } -} - -uint8_t *GetModrmRegisterXmmPointerRead(struct Machine *m, uint32_t rde, - size_t n) { - if (IsModrmRegister(rde)) { - return XmmRexbRm(m, rde); - } else { - return ComputeReserveAddressRead(m, rde, n); - } -} - -uint8_t *GetModrmRegisterXmmPointerRead4(struct Machine *m, uint32_t rde) { - return GetModrmRegisterXmmPointerRead(m, rde, 4); -} - -uint8_t *GetModrmRegisterXmmPointerRead8(struct Machine *m, uint32_t rde) { - return GetModrmRegisterXmmPointerRead(m, rde, 8); -} - -uint8_t *GetModrmRegisterXmmPointerRead16(struct Machine *m, uint32_t rde) { - return GetModrmRegisterXmmPointerRead(m, rde, 16); -} - -uint8_t *GetModrmRegisterXmmPointerWrite(struct Machine *m, uint32_t rde, - size_t n) { - if (IsModrmRegister(rde)) { - return XmmRexbRm(m, rde); - } else { - return ComputeReserveAddressWrite(m, rde, n); - } -} - -uint8_t *GetModrmRegisterXmmPointerWrite4(struct Machine *m, uint32_t rde) { - return GetModrmRegisterXmmPointerWrite(m, rde, 4); -} - -uint8_t *GetModrmRegisterXmmPointerWrite8(struct Machine *m, uint32_t rde) { - return GetModrmRegisterXmmPointerWrite(m, rde, 8); -} - -uint8_t *GetModrmRegisterXmmPointerWrite16(struct Machine *m, uint32_t rde) { - return GetModrmRegisterXmmPointerWrite(m, rde, 16); -} diff --git a/tool/build/lib/modrm.h b/tool/build/lib/modrm.h deleted file mode 100644 index 87d628110..000000000 --- a/tool/build/lib/modrm.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_MODRM_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_MODRM_H_ -#include "tool/build/lib/abp.h" -#include "tool/build/lib/machine.h" - -#define Rex(x) ((x & 000000000020) >> 004) -#define Osz(x) ((x & 000000000040) >> 005) -#define Rep(x) ((x & 030000000000) >> 036) -#define Rexr(x) ((x & 000000000010) >> 003) -#define Rexw(x) ((x & 000000000100) >> 006) -#define Rexb(x) ((x & 000000002000) >> 012) -#define Sego(x) ((x & 000007000000) >> 022) -#define Mode(x) ((x & 001400000000) >> 032) -#define Eamode(x) ((x & 000300000000) >> 030) -#define RexbRm(x) ((x & 000000003600) >> 007) -#define RexrReg(x) ((x & 000000000017) >> 000) -#define RegLog2(x) ((x & 006000000000) >> 034) -#define ModrmRm(x) ((x & 000000001600) >> 007) -#define ModrmReg(x) ((x & 000000000007) >> 000) -#define ModrmSrm(x) ((x & 000000070000) >> 014) -#define ModrmMod(x) ((x & 000060000000) >> 026) -#define Modrm(x) (ModrmMod(x) << 6 | ModrmReg(x) << 3 | ModrmRm(x)) - -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -#define RexbBase(m, x) (Rexb(x) << 3 | m->xedd->op.base) -#define AddrByteReg(m, k) ((uint8_t *)m->reg + kByteReg[k]) -#define ByteRexrReg(m, x) AddrByteReg(m, (x & 00000000037) >> 0) -#define ByteRexbRm(m, x) AddrByteReg(m, (x & 00000007600) >> 7) -#define ByteRexbSrm(m, x) AddrByteReg(m, (x & 00000370000) >> 12) -#define RegSrm(m, x) Abp8(m->reg[(x & 00000070000) >> 12]) -#define RegRexbRm(m, x) Abp8(m->reg[RexbRm(x)]) -#define RegRexbSrm(m, x) Abp8(m->reg[(x & 00000170000) >> 12]) -#define RegRexrReg(m, x) Abp8(m->reg[RexrReg(x)]) -#define RegRexbBase(m, x) Abp8(m->reg[RexbBase(m, x)]) -#define RegRexxIndex(m) Abp8(m->reg[m->xedd->op.rexx << 3 | m->xedd->op.index]) -#define MmRm(m, x) Abp16(m->xmm[(x & 00000001600) >> 7]) -#define MmReg(m, x) Abp16(m->xmm[(x & 00000000007) >> 0]) -#define XmmRexbRm(m, x) Abp16(m->xmm[RexbRm(x)]) -#define XmmRexrReg(m, x) Abp16(m->xmm[RexrReg(x)]) - -#define Rexx(m) m->op.rexx -#define SibBase(m) m->op.base -#define SibIndex(m) m->op.index -#define SibExists(x) (ModrmRm(x) == 4) -#define IsModrmRegister(x) (ModrmMod(x) == 3) -#define SibHasIndex(x) (SibIndex(x) != 4 || Rexx(x)) -#define SibHasBase(x, r) (SibBase(x) != 5 || ModrmMod(r)) -#define SibIsAbsolute(x, r) (!SibHasBase(x, r) && !SibHasIndex(x)) -#define IsRipRelative(x) (Eamode(x) && ModrmRm(x) == 5 && !ModrmMod(x)) - -struct AddrSeg { - int64_t addr; - uint8_t *seg; -}; - -extern const uint8_t kByteReg[32]; - -uint32_t EncodeRde(struct XedDecodedInst *); -int64_t ComputeAddress(const struct Machine *, uint32_t); -struct AddrSeg LoadEffectiveAddress(const struct Machine *, uint32_t); -void *ComputeReserveAddressRead(struct Machine *, uint32_t, size_t); -void *ComputeReserveAddressRead1(struct Machine *, uint32_t); -void *ComputeReserveAddressRead4(struct Machine *, uint32_t); -void *ComputeReserveAddressRead8(struct Machine *, uint32_t); -void *ComputeReserveAddressWrite(struct Machine *, uint32_t, size_t); -void *ComputeReserveAddressWrite1(struct Machine *, uint32_t); -void *ComputeReserveAddressWrite4(struct Machine *, uint32_t); -void *ComputeReserveAddressWrite8(struct Machine *, uint32_t); -uint8_t *GetModrmRegisterBytePointerRead(struct Machine *, uint32_t); -uint8_t *GetModrmRegisterBytePointerWrite(struct Machine *, uint32_t); -uint8_t *GetModrmRegisterMmPointerRead(struct Machine *, uint32_t, size_t); -uint8_t *GetModrmRegisterMmPointerRead8(struct Machine *, uint32_t); -uint8_t *GetModrmRegisterMmPointerWrite(struct Machine *, uint32_t, size_t); -uint8_t *GetModrmRegisterMmPointerWrite8(struct Machine *, uint32_t); -uint8_t *GetModrmRegisterWordPointerRead(struct Machine *, uint32_t, size_t); -uint8_t *GetModrmRegisterWordPointerRead2(struct Machine *, uint32_t); -uint8_t *GetModrmRegisterWordPointerRead4(struct Machine *, uint32_t); -uint8_t *GetModrmRegisterWordPointerRead8(struct Machine *, uint32_t); -uint8_t *GetModrmRegisterWordPointerReadOsz(struct Machine *, uint32_t); -uint8_t *GetModrmRegisterWordPointerReadOszRexw(struct Machine *, uint32_t); -uint8_t *GetModrmRegisterWordPointerWrite(struct Machine *, uint32_t, size_t); -uint8_t *GetModrmRegisterWordPointerWrite2(struct Machine *, uint32_t); -uint8_t *GetModrmRegisterWordPointerWrite4(struct Machine *, uint32_t); -uint8_t *GetModrmRegisterWordPointerWrite8(struct Machine *, uint32_t); -uint8_t *GetModrmRegisterWordPointerWriteOsz(struct Machine *, uint32_t); -uint8_t *GetModrmRegisterWordPointerWriteOszRexw(struct Machine *, uint32_t); -uint8_t *GetModrmRegisterXmmPointerRead(struct Machine *, uint32_t, size_t); -uint8_t *GetModrmRegisterXmmPointerRead16(struct Machine *, uint32_t); -uint8_t *GetModrmRegisterXmmPointerRead4(struct Machine *, uint32_t); -uint8_t *GetModrmRegisterXmmPointerRead8(struct Machine *, uint32_t); -uint8_t *GetModrmRegisterXmmPointerWrite(struct Machine *, uint32_t, size_t); -uint8_t *GetModrmRegisterXmmPointerWrite16(struct Machine *, uint32_t); -uint8_t *GetModrmRegisterXmmPointerWrite4(struct Machine *, uint32_t); -uint8_t *GetModrmRegisterXmmPointerWrite8(struct Machine *, uint32_t); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_MODRM_H_ */ diff --git a/tool/build/lib/op101.c b/tool/build/lib/op101.c deleted file mode 100644 index ff5b009c3..000000000 --- a/tool/build/lib/op101.c +++ /dev/null @@ -1,216 +0,0 @@ -/*-*- 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/log/log.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/memory.h" -#include "tool/build/lib/modrm.h" -#include "tool/build/lib/op101.h" -#include "tool/build/lib/throw.h" -#include "tool/build/lib/time.h" - -static void StoreDescriptorTable(struct Machine *m, uint32_t rde, - uint16_t limit, uint64_t base) { - uint64_t l; - l = ComputeAddress(m, rde); - if (l + 10 <= m->real.n) { - Write16(m->real.p + l, limit); - if (Rexw(rde)) { - Write64(m->real.p + l + 2, base); - SetWriteAddr(m, l, 10); - } else if (!Osz(rde)) { - Write32(m->real.p + l + 2, base); - SetWriteAddr(m, l, 6); - } else { - Write16(m->real.p + l + 2, base); - SetWriteAddr(m, l, 4); - } - } else { - ThrowSegmentationFault(m, l); - } -} - -static void LoadDescriptorTable(struct Machine *m, uint32_t rde, - uint16_t *out_limit, uint64_t *out_base) { - uint16_t limit; - uint64_t l, base; - l = ComputeAddress(m, rde); - if (l + 10 <= m->real.n) { - limit = Read16(m->real.p + l); - if (Rexw(rde)) { - base = Read64(m->real.p + l + 2) & 0x00ffffff; - SetReadAddr(m, l, 10); - } else if (!Osz(rde)) { - base = Read32(m->real.p + l + 2); - SetReadAddr(m, l, 6); - } else { - base = Read16(m->real.p + l + 2); - SetReadAddr(m, l, 4); - } - if (base + limit <= m->real.n) { - *out_limit = limit; - *out_base = base; - } else { - ThrowProtectionFault(m); - } - } else { - ThrowSegmentationFault(m, l); - } -} - -static void SgdtMs(struct Machine *m, uint32_t rde) { - StoreDescriptorTable(m, rde, m->gdt_limit, m->gdt_base); -} - -static void LgdtMs(struct Machine *m, uint32_t rde) { - LoadDescriptorTable(m, rde, &m->gdt_limit, &m->gdt_base); - INFOF("set gdt %p lim %,d", m->gdt_base, m->gdt_limit); -} - -static void SidtMs(struct Machine *m, uint32_t rde) { - StoreDescriptorTable(m, rde, m->idt_limit, m->idt_base); -} - -static void LidtMs(struct Machine *m, uint32_t rde) { - LoadDescriptorTable(m, rde, &m->idt_limit, &m->idt_base); - INFOF("set idt %p lim %,d", m->idt_base, m->idt_limit); -} - -static void Monitor(struct Machine *m, uint32_t rde) { -} - -static void Mwait(struct Machine *m, uint32_t rde) { -} - -static void Swapgs(struct Machine *m, uint32_t rde) { -} - -static void Vmcall(struct Machine *m, uint32_t rde) { -} - -static void Vmlaunch(struct Machine *m, uint32_t rde) { -} - -static void Vmresume(struct Machine *m, uint32_t rde) { -} - -static void Vmxoff(struct Machine *m, uint32_t rde) { -} - -static void InvlpgM(struct Machine *m, uint32_t rde) { - ResetTlb(m); -} - -static void Smsw(struct Machine *m, uint32_t rde, bool ismem) { - if (ismem) { - Write16(GetModrmRegisterWordPointerWrite2(m, rde), m->cr0); - } else if (Rexw(rde)) { - Write64(RegRexrReg(m, rde), m->cr0); - } else if (!Osz(rde)) { - Write64(RegRexrReg(m, rde), m->cr0 & 0xffffffff); - } else { - Write16(RegRexrReg(m, rde), m->cr0); - } -} - -static void Lmsw(struct Machine *m, uint32_t rde) { - m->cr0 = Read16(GetModrmRegisterWordPointerRead2(m, rde)); -} - -void Op101(struct Machine *m, uint32_t rde) { - bool ismem; - ismem = !IsModrmRegister(rde); - switch (ModrmReg(rde)) { - case 0: - if (ismem) { - SgdtMs(m, rde); - } else { - switch (ModrmRm(rde)) { - case 1: - Vmcall(m, rde); - break; - case 2: - Vmlaunch(m, rde); - break; - case 3: - Vmresume(m, rde); - break; - case 4: - Vmxoff(m, rde); - break; - default: - OpUd(m, rde); - } - } - break; - case 1: - if (ismem) { - SidtMs(m, rde); - } else { - switch (ModrmRm(rde)) { - case 0: - Monitor(m, rde); - break; - case 1: - Mwait(m, rde); - break; - default: - OpUd(m, rde); - } - } - break; - case 2: - if (ismem) { - LgdtMs(m, rde); - } else { - OpUd(m, rde); - } - break; - case 3: - if (ismem) { - LidtMs(m, rde); - } else { - OpUd(m, rde); - } - break; - case 4: - Smsw(m, rde, ismem); - break; - case 6: - Lmsw(m, rde); - break; - case 7: - if (ismem) { - InvlpgM(m, rde); - } else { - switch (ModrmRm(rde)) { - case 0: - Swapgs(m, rde); - break; - case 1: - OpRdtscp(m, rde); - break; - default: - OpUd(m, rde); - } - } - break; - default: - OpUd(m, rde); - } -} diff --git a/tool/build/lib/op101.h b/tool/build/lib/op101.h deleted file mode 100644 index 7e8cb0a5d..000000000 --- a/tool/build/lib/op101.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_OP101_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_OP101_H_ -#include "tool/build/lib/machine.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -void Op101(struct Machine *, uint32_t); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_OP101_H_ */ diff --git a/tool/build/lib/pml4t.c b/tool/build/lib/pml4t.c deleted file mode 100644 index 5b5356949..000000000 --- a/tool/build/lib/pml4t.c +++ /dev/null @@ -1,62 +0,0 @@ -/*-*- 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/mem/arraylist2.internal.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/machine.h" -#include "tool/build/lib/pml4t.h" - -static void AppendContiguousMemoryRange(struct ContiguousMemoryRanges *ranges, - int64_t a, int64_t b) { - APPEND(&ranges->p, &ranges->i, &ranges->n, - (&(struct ContiguousMemoryRange){a, b})); -} - -static void FindContiguousMemoryRangesImpl( - struct Machine *m, struct ContiguousMemoryRanges *ranges, int64_t addr, - unsigned level, int64_t pt, int64_t a, int64_t b) { - int64_t i, page, entry; - for (i = a; i < b; ++i) { - entry = Read64(m->real.p + pt + i * 8); - if (!(entry & 1)) continue; - entry &= 0x7ffffffff000; - page = (int64_t)((uint64_t)(addr | i << level) << 16) >> 16; - if (level == 12) { - if (ranges->i && page == ranges->p[ranges->i - 1].b) { - ranges->p[ranges->i - 1].b += 0x1000; - } else { - AppendContiguousMemoryRange(ranges, page, page + 0x1000); - } - } else if (entry + 512 * 8 <= m->real.n) { - FindContiguousMemoryRangesImpl(m, ranges, page, level - 9, entry, 0, 512); - } - } -} - -void FindContiguousMemoryRanges(struct Machine *m, - struct ContiguousMemoryRanges *ranges) { - uint64_t cr3; - ranges->i = 0; - if ((m->mode & 3) == XED_MODE_LONG) { - cr3 = m->cr3 & 0x7ffffffff000; - FindContiguousMemoryRangesImpl(m, ranges, 0, 39, cr3, 256, 512); - FindContiguousMemoryRangesImpl(m, ranges, 0, 39, cr3, 0, 256); - } else { - AppendContiguousMemoryRange(ranges, 0, m->real.n); - } -} diff --git a/tool/build/lib/pml4t.h b/tool/build/lib/pml4t.h deleted file mode 100644 index 5df471b5e..000000000 --- a/tool/build/lib/pml4t.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_PML4T_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_PML4T_H_ -#include "tool/build/lib/machine.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -#define IsValidPage(x) ((x)&1) -#define MaskPageAddr(x) ((x)&0x00007ffffffff000) -#define UnmaskPageAddr(x) SignExtendAddr(MaskPageAddr(x)) -#define SignExtendAddr(x) ((int64_t)((uint64_t)(x) << 16) >> 16) - -struct ContiguousMemoryRanges { - size_t i, n; - struct ContiguousMemoryRange { - int64_t a; - int64_t b; - } * p; -}; - -void FindContiguousMemoryRanges(struct Machine *, - struct ContiguousMemoryRanges *); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_PML4T_H_ */ diff --git a/tool/build/lib/pml4tfmt.c b/tool/build/lib/pml4tfmt.c deleted file mode 100644 index 379dfd680..000000000 --- a/tool/build/lib/pml4tfmt.c +++ /dev/null @@ -1,118 +0,0 @@ -/*-*- 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/log/check.h" -#include "libc/macros.internal.h" -#include "libc/mem/mem.h" -#include "libc/x/x.h" -#include "tool/build/lib/buffer.h" -#include "tool/build/lib/memory.h" -#include "tool/build/lib/pml4t.h" - -struct Pml4tFormatter { - bool t; - int64_t start; - struct Buffer b; - long lines; -}; - -static int64_t MakeAddress(unsigned short a[4]) { - uint64_t x; - x = 0; - x |= a[0]; - x <<= 9; - x |= a[1]; - x <<= 9; - x |= a[2]; - x <<= 9; - x |= a[3]; - x <<= 12; - return x; -} - -static void FormatStartPage(struct Pml4tFormatter *pp, int64_t start) { - pp->t = true; - pp->start = start; - if (pp->lines++) AppendChar(&pp->b, '\n'); - AppendFmt(&pp->b, "%012lx-", start); -} - -static void FormatEndPage(struct Pml4tFormatter *pp, int64_t end) { - int64_t size; - pp->t = false; - size = end - pp->start; - AppendFmt(&pp->b, "%012lx %012lx %,ld bytes", end - 1, size, size); -} - -static void *GetPt(struct Machine *m, uint64_t r) { - CHECK_LE(r + 0x1000, m->real.n); - return m->real.p + r; -} - -char *FormatPml4t(struct Machine *m) { - uint64_t *pd[4]; - unsigned short i, a[4]; - struct Pml4tFormatter pp = {0}; - unsigned short range[][2] = {{256, 512}, {0, 256}}; - if ((m->mode & 3) != XED_MODE_LONG) return strdup(""); - pd[0] = GetPt(m, m->cr3); - for (i = 0; i < ARRAYLEN(range); ++i) { - a[0] = range[i][0]; - do { - a[1] = a[2] = a[3] = 0; - if (!IsValidPage(pd[0][a[0]])) { - if (pp.t) FormatEndPage(&pp, MakeAddress(a)); - } else { - pd[1] = GetPt(m, UnmaskPageAddr(pd[0][a[0]])); - do { - a[2] = a[3] = 0; - if (!IsValidPage(pd[1][a[1]])) { - if (pp.t) FormatEndPage(&pp, MakeAddress(a)); - } else { - pd[2] = GetPt(m, UnmaskPageAddr(pd[1][a[1]])); - do { - a[3] = 0; - if (!IsValidPage(pd[2][a[2]])) { - if (pp.t) FormatEndPage(&pp, MakeAddress(a)); - } else { - pd[3] = GetPt(m, UnmaskPageAddr(pd[2][a[2]])); - do { - if (!IsValidPage(pd[3][a[3]])) { - if (pp.t) FormatEndPage(&pp, MakeAddress(a)); - } else { - if (!pp.t) { - FormatStartPage(&pp, MakeAddress(a)); - } - } - } while (++a[3] != 512); - } - } while (++a[2] != 512); - } - } while (++a[1] != 512); - } - } while (++a[0] != range[i][1]); - } - if (pp.t) { - FormatEndPage(&pp, 0x800000000000); - } - if (pp.b.p) { - return xrealloc(pp.b.p, pp.b.i + 1); - } else { - return strdup(""); - } -} diff --git a/tool/build/lib/pty.c b/tool/build/lib/pty.c deleted file mode 100644 index 6ef5ecee1..000000000 --- a/tool/build/lib/pty.c +++ /dev/null @@ -1,1407 +0,0 @@ -/*-*- 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 "tool/build/lib/pty.h" -#include "libc/fmt/itoa.h" -#include "libc/intrin/bits.h" -#include "libc/intrin/safemacros.internal.h" -#include "libc/intrin/tpenc.h" -#include "libc/log/check.h" -#include "libc/mem/arraylist2.internal.h" -#include "libc/mem/mem.h" -#include "libc/str/str.h" -#include "libc/str/thompike.h" -#include "libc/str/unicode.h" -#include "libc/sysv/errfuns.h" -#include "libc/x/x.h" - -/** - * @fileoverview Pseudoteletypewriter - * - * \t TAB - * \a BELL - * \177 BACKSPACE - * \r CURSOR START - * \b CURSOR LEFT OR CURSOR REWIND - * \n CURSOR DOWN AND START IF OPOST - * \f CURSOR DOWN AND START IF OPOST - * \v CURSOR DOWN AND START OR \e[H\e[J - * \eE CURSOR DOWN AND START - * \eD CURSOR DOWN - * \eM CURSOR UP - * \ec FULL RESET - * \e7 SAVE CURSOR POSITION - * \e8 RESTORE CURSOR POSITION - * \e(0 DEC SPECIAL GRAPHICS - * \e(B USAS X3.4-1967 - * \e#5 SINGLE WIDTH - * \e#6 DOUBLE WIDTH - * \e#8 SO MANY E - * \eZ → \e/Z REPORT IDENTITY - * \e[𝑛A CURSOR UP [CLAMPED] - * \e[𝑛B CURSOR DOWN [CLAMPED] - * \e[𝑛C CURSOR RIGHT [CLAMPED] - * \e[𝑛D CURSOR LEFT [CLAMPED] - * \e[𝑦;𝑥H SET CURSOR POSITION [CLAMPED] - * \e[𝑥G SET CURSOR COLUMN [CLAMPED] - * \e[𝑦d SET CURSOR ROW [CLAMPED] - * \e[𝑛E CURSOR DOWN AND START [CLAMPED] - * \e[𝑛F CURSOR UP AND START [CLAMPED] - * \e[𝑛S SCROLL UP - * \e[𝑛T SCROLL DOWN - * \e[𝑛@ INSERT CELLS - * \e[𝑛P DELETE CELLS - * \e[𝑛L INSERT LINES - * \e[𝑛M DELETE LINES - * \e[J ERASE DISPLAY FORWARDS - * \e[1J ERASE DISPLAY BACKWARDS - * \e[2J ERASE DISPLAY - * \e[K ERASE LINE FORWARD - * \e[1K ERASE LINE BACKWARD - * \e[2K ERASE LINE - * \e[𝑛X ERASE CELLS - * \e[0m RESET - * \e[1m BOLD - * \e[2m FAINT - * \e[3m ITALIC - * \e[4m UNDER - * \e[5m BLINK - * \e[7m INVERT - * \e[8m CONCEAL - * \e[9m STRIKE - * \e[20m FRAKTUR - * \e[21m DUNDER - * \e[22m RESET BOLD & FAINT - * \e[23m RESET ITALIC & FRAKTUR - * \e[24m RESET UNDER & DUNDER - * \e[25m RESET BLINK - * \e[27m RESET INVERT - * \e[28m RESET CONCEAL - * \e[29m RESET STRIKE - * \e[39m RESET FOREGROUND - * \e[49m RESET BACKGROUND - * \e[30m BLACK FOREGROUND - * \e[31m RED FOREGROUND - * \e[32m GREEN FOREGROUND - * \e[33m YELLOW FOREGROUND - * \e[34m BLUE FOREGROUND - * \e[35m MAGENTA FOREGROUND - * \e[36m CYAN FOREGROUND - * \e[37m WHITE FOREGROUND - * \e[40m BLACK BACKGROUND - * \e[41m RED BACKGROUND - * \e[42m GREEN BACKGROUND - * \e[44m YELLOW BACKGROUND - * \e[44m BLUE BACKGROUND - * \e[45m MAGENTA BACKGROUND - * \e[46m CYAN BACKGROUND - * \e[47m WHITE BACKGROUND - * \e[90m BRIGHT BLACK FOREGROUND - * \e[91m BRIGHT RED FOREGROUND - * \e[92m BRIGHT GREEN FOREGROUND - * \e[93m BRIGHT YELLOW FOREGROUND - * \e[94m BRIGHT BLUE FOREGROUND - * \e[95m BRIGHT MAGENTA FOREGROUND - * \e[96m BRIGHT CYAN FOREGROUND - * \e[97m BRIGHT WHITE FOREGROUND - * \e[100m BRIGHT BLACK BACKGROUND - * \e[101m BRIGHT RED BACKGROUND - * \e[102m BRIGHT GREEN BACKGROUND - * \e[103m BRIGHT YELLOW BACKGROUND - * \e[104m BRIGHT BLUE BACKGROUND - * \e[105m BRIGHT MAGENTA BACKGROUND - * \e[106m BRIGHT CYAN BACKGROUND - * \e[107m BRIGHT WHITE BACKGROUND - * \e[38;5;𝑥m XTERM256 FOREGROUND - * \e[48;5;𝑥m XTERM256 BACKGROUND - * \e[38;2;𝑟;𝑔;𝑏m RGB FOREGROUND - * \e[48;2;𝑟;𝑔;𝑏m RGB BACKGROUND - * \e[?25h SHOW CURSOR - * \e[?25l HIDE CURSOR - * \e[s SAVE CURSOR POSITION - * \e[u RESTORE CURSOR POSITION - * \e[?5h ... \e[?5l REVERSE VIDEO EPILEPSY - * \e[0q RESET LEDS - * \e[1q TURN ON FIRST LED - * \e[2q TURN ON SECOND LED - * \e[3q TURN ON THIRD LED - * \e[4q TURN ON FOURTH LED - * \e[c → \e[?1;0c REPORT DEVICE TYPE - * \e[5n → \e[0n REPORT DEVICE STATUS - * \e[6n → \e[𝑦;𝑥R REPORT CURSOR POSITION - * \e7\e[9979;9979H\e[6n\e8 → \e[𝑦;𝑥R REPORT DISPLAY DIMENSIONS - * - * @see https://vt100.net/docs/vt220-rm/chapter4.html - * @see https://invisible-island.net/xterm/ - * @see ANSI X3.64-1979 - * @see ISO/IEC 6429 - * @see FIPS-86 - * @see ECMA-48 - */ - -struct Pty *NewPty(void) { - struct Pty *pty; - pty = xcalloc(1, sizeof(struct Pty)); - PtyResize(pty, 25, 80); - PtyFullReset(pty); - PtyErase(pty, 0, pty->yn * pty->xn); - return pty; -} - -static void FreePtyPlanes(struct Pty *pty) { - free(pty->wcs); - free(pty->fgs); - free(pty->bgs); - free(pty->prs); -} - -void FreePty(struct Pty *pty) { - if (pty) { - FreePtyPlanes(pty); - free(pty); - } -} - -static wchar_t *GetXlatAscii(void) { - unsigned i; - static bool once; - static wchar_t xlat[128]; - if (!once) { - for (i = 0; i < 128; ++i) { - xlat[i] = i; - } - once = true; - } - return xlat; -} - -static wchar_t *GetXlatLineDrawing(void) { - unsigned i; - static bool once; - static wchar_t xlat[128]; - if (!once) { - for (i = 0; i < 128; ++i) { - if (0x5F <= i && i <= 0x7E) { - xlat[i] = u" ◆▒␉␌␍␊°±␋┘┐┌└┼⎺⎻─⎼⎽├┤┴┬│≤≥π≠£·"[i - 0x5F]; - } else { - xlat[i] = i; - } - } - once = true; - } - return xlat; -} - -static void XlatAlphabet(wchar_t xlat[128], int a, int b) { - unsigned i; - for (i = 0; i < 128; ++i) { - if ('a' <= i && i <= 'z') { - xlat[i] = i - 'a' + a; - } else if ('A' <= i && i <= 'Z') { - xlat[i] = i - 'A' + b; - } else { - xlat[i] = i; - } - } -} - -static wchar_t *GetXlatItalic(void) { - static bool once; - static wchar_t xlat[128]; - if (!once) { - XlatAlphabet(xlat, L'𝑎', L'𝐴'); - once = true; - } - return xlat; -} - -static wchar_t *GetXlatBoldItalic(void) { - static bool once; - static wchar_t xlat[128]; - if (!once) { - XlatAlphabet(xlat, L'𝒂', L'𝑨'); - once = true; - } - return xlat; -} - -static wchar_t *GetXlatBoldFraktur(void) { - static bool once; - static wchar_t xlat[128]; - if (!once) { - XlatAlphabet(xlat, L'𝖆', L'𝕬'); - once = true; - } - return xlat; -} - -static wchar_t *GetXlatFraktur(void) { - unsigned i; - static bool once; - static wchar_t xlat[128]; - if (!once) { - for (i = 0; i < ARRAYLEN(xlat); ++i) { - if ('A' <= i && i <= 'Z') { - xlat[i] = L"𝔄𝔅ℭ𝔇𝔈𝔉𝔊ℌℑ𝔍𝔎𝔏𝔐𝔑𝔒𝔓𝔔ℜ𝔖𝔗𝔘𝔙𝔚𝔛𝔜ℨ"[i - 'A']; - } else if ('a' <= i && i <= 'z') { - xlat[i] = i - 'a' + L'𝔞'; - } else { - xlat[i] = i; - } - } - once = true; - } - return xlat; -} - -static wchar_t *GetXlatDoubleWidth(void) { - unsigned i; - static bool once; - static wchar_t xlat[128]; - if (!once) { - for (i = 0; i < ARRAYLEN(xlat); ++i) { - if ('!' <= i && i <= '~') { - xlat[i] = -(i - '!' + L'!'); - } else { - xlat[i] = i; - } - } - once = true; - } - return xlat; -} - -static wchar_t *GetXlatSgr(struct Pty *pty) { - switch (!!(pty->pr & kPtyFraktur) << 2 | !!(pty->pr & kPtyItalic) << 1 | - !!(pty->pr & kPtyBold) << 0) { - case 0b100: - case 0b110: - return GetXlatFraktur(); - case 0b101: - case 0b111: - return GetXlatBoldFraktur(); - case 0b011: - return GetXlatBoldItalic(); - case 0b010: - return GetXlatItalic(); - default: - return GetXlatAscii(); - } -} - -static void PtySetXlat(struct Pty *pty, wchar_t *xlat) { - pty->xlat = xlat; - pty->pr &= ~(kPtyItalic | kPtyFraktur); -} - -static void PtySetCodepage(struct Pty *pty, char id) { - unsigned i; - switch (id) { - default: - case 'B': - PtySetXlat(pty, GetXlatAscii()); - break; - case '0': - PtySetXlat(pty, GetXlatLineDrawing()); - break; - } -} - -void PtyErase(struct Pty *pty, long dst, long n) { - DCHECK_LE(dst + n, pty->yn * pty->xn); - wmemset((void *)(pty->wcs + dst), ' ', n); - bzero((void *)(pty->prs + dst), n); -} - -void PtyMemmove(struct Pty *pty, long dst, long src, long n) { - DCHECK_LE(src + n, pty->yn * pty->xn); - DCHECK_LE(dst + n, pty->yn * pty->xn); - memmove(pty->wcs + dst, pty->wcs + src, n * 4); - memmove(pty->fgs + dst, pty->fgs + src, n * 4); - memmove(pty->bgs + dst, pty->bgs + src, n * 4); - memmove(pty->prs + dst, pty->prs + src, n * 4); -} - -void PtyFullReset(struct Pty *pty) { - pty->y = 0; - pty->x = 0; - pty->pr = 0; - pty->u8 = 0; - pty->n8 = 0; - pty->conf = 0; - pty->save = 0; - pty->state = 0; - pty->esc.i = 0; - pty->input.i = 0; - pty->xlat = GetXlatAscii(); - PtyErase(pty, 0, pty->yn * pty->xn); -} - -void PtySetY(struct Pty *pty, int y) { - pty->conf &= ~kPtyRedzone; - pty->y = MAX(0, MIN(pty->yn - 1, y)); -} - -void PtySetX(struct Pty *pty, int x) { - pty->conf &= ~kPtyRedzone; - pty->x = MAX(0, MIN(pty->xn - 1, x)); -} - -void PtyResize(struct Pty *pty, int yn, int xn) { - unsigned y, ym, xm, y0; - uint32_t *wcs, *fgs, *bgs, *prs; - if (xn < 80) xn = 80; - if (yn < 25) yn = 25; - if (xn == pty->xn && yn == pty->yn) return; - wcs = xcalloc(yn * xn, 4); - fgs = xcalloc(yn * xn, 4); - bgs = xcalloc(yn * xn, 4); - prs = xcalloc(yn * xn, 4); - y0 = yn > pty->y + 1 ? 0 : pty->y + 1 - yn; - ym = MIN(yn, pty->yn) + y0; - xm = MIN(xn, pty->xn); - for (y = y0; y < ym; ++y) { - memcpy(wcs + y * xn, pty->wcs + y * pty->xn, xm * 4); - memcpy(fgs + y * xn, pty->fgs + y * pty->xn, xm * 4); - memcpy(bgs + y * xn, pty->bgs + y * pty->xn, xm * 4); - memcpy(prs + y * xn, pty->prs + y * pty->xn, xm * 4); - } - FreePtyPlanes(pty); - pty->wcs = wcs; - pty->fgs = fgs; - pty->bgs = bgs; - pty->prs = prs; - pty->yn = yn; - pty->xn = xn; - PtySetY(pty, pty->y); - PtySetX(pty, pty->x); -} - -static void PtyConcatInput(struct Pty *pty, const char *data, size_t n) { - CONCAT(&pty->input.p, &pty->input.i, &pty->input.n, data, n); -} - -static void PtyScroll(struct Pty *pty) { - PtyMemmove(pty, 0, pty->xn, pty->xn * (pty->yn - 1)); - PtyErase(pty, pty->xn * (pty->yn - 1), pty->xn); -} - -static void PtyReverse(struct Pty *pty) { - PtyMemmove(pty, pty->xn, 0, pty->xn * (pty->yn - 1)); - PtyErase(pty, 0, pty->xn); -} - -static void PtyIndex(struct Pty *pty) { - if (pty->y < pty->yn - 1) { - ++pty->y; - } else { - PtyScroll(pty); - } -} - -static void PtyReverseIndex(struct Pty *pty) { - if (pty->y) { - --pty->y; - } else { - PtyReverse(pty); - } -} - -static void PtyCarriageReturn(struct Pty *pty) { - PtySetX(pty, 0); -} - -static void PtyNewline(struct Pty *pty) { - PtyIndex(pty); - if (!(pty->conf & kPtyNoopost)) { - PtyCarriageReturn(pty); - } -} - -static void PtyAdvance(struct Pty *pty) { - DCHECK_EQ(pty->xn - 1, pty->x); - DCHECK(pty->conf & kPtyRedzone); - pty->conf &= ~kPtyRedzone; - pty->x = 0; - if (pty->y < pty->yn - 1) { - ++pty->y; - } else { - PtyScroll(pty); - } -} - -static void PtyWriteGlyph(struct Pty *pty, wint_t wc, int w) { - uint32_t i; - if (w < 1) wc = ' ', w = 1; - if ((pty->conf & kPtyRedzone) || pty->x + w > pty->xn) { - PtyAdvance(pty); - } - i = pty->y * pty->xn + pty->x; - pty->wcs[i] = wc; - if ((pty->prs[i] = pty->pr) & (kPtyFg | kPtyBg)) { - pty->fgs[i] = pty->fg; - pty->bgs[i] = pty->bg; - } - if ((pty->x += w) >= pty->xn) { - pty->x = pty->xn - 1; - pty->conf |= kPtyRedzone; - } -} - -static void PtyWriteTab(struct Pty *pty) { - unsigned x, x2; - if (pty->conf & kPtyRedzone) { - PtyAdvance(pty); - } - x2 = MIN(pty->xn, ROUNDUP(pty->x + 1, 8)); - for (x = pty->x; x < x2; ++x) { - pty->wcs[pty->y * pty->xn + x] = ' '; - } - if (x2 < pty->xn) { - pty->x = x2; - } else { - pty->x = pty->xn - 1; - pty->conf |= kPtyRedzone; - } -} - -static int PtyAtoi(const char *s, const char **e) { - int i; - for (i = 0; isdigit(*s); ++s) i *= 10, i += *s - '0'; - if (e) *e = s; - return i; -} - -static int PtyGetMoveParam(struct Pty *pty) { - int x = PtyAtoi(pty->esc.s, NULL); - if (x < 1) x = 1; - return x; -} - -static void PtySetCursorPosition(struct Pty *pty) { - int row, col; - const char *s = pty->esc.s; - row = max(1, PtyAtoi(s, &s)); - if (*s == ';') ++s; - col = max(1, PtyAtoi(s, &s)); - PtySetY(pty, row - 1); - PtySetX(pty, col - 1); -} - -static void PtySetCursorRow(struct Pty *pty) { - PtySetY(pty, PtyGetMoveParam(pty) - 1); -} - -static void PtySetCursorColumn(struct Pty *pty) { - PtySetX(pty, PtyGetMoveParam(pty) - 1); -} - -static void PtyMoveCursor(struct Pty *pty, int dy, int dx) { - int n = PtyGetMoveParam(pty); - PtySetY(pty, pty->y + dy * n); - PtySetX(pty, pty->x + dx * n); -} - -static void PtyScrollUp(struct Pty *pty) { - int n = PtyGetMoveParam(pty); - while (n--) PtyScroll(pty); -} - -static void PtyScrollDown(struct Pty *pty) { - int n = PtyGetMoveParam(pty); - while (n--) PtyReverse(pty); -} - -static void PtySetCursorStatus(struct Pty *pty, bool status) { - if (status) { - pty->conf &= ~kPtyNocursor; - } else { - pty->conf |= kPtyNocursor; - } -} - -static void PtySetMode(struct Pty *pty, bool status) { - const char *p = pty->esc.s; - switch (*p++) { - case '?': - while (isdigit(*p)) { - switch (PtyAtoi(p, &p)) { - case 25: - PtySetCursorStatus(pty, status); - break; - default: - break; - } - if (*p == ';') { - ++p; - } - } - break; - default: - break; - } -} - -static void PtySaveCursorPosition(struct Pty *pty) { - pty->save = (pty->y & 0x7FFF) | (pty->x & 0x7FFF) << 16; -} - -static void PtyRestoreCursorPosition(struct Pty *pty) { - PtySetY(pty, (pty->save & 0x00007FFF) >> 000); - PtySetX(pty, (pty->save & 0x7FFF0000) >> 020); -} - -static void PtyEraseDisplay(struct Pty *pty) { - switch (PtyAtoi(pty->esc.s, NULL)) { - case 0: - PtyErase(pty, pty->y * pty->xn + pty->x, - pty->yn * pty->xn - (pty->y * pty->xn + pty->x)); - break; - case 1: - PtyErase(pty, 0, pty->y * pty->xn + pty->x); - break; - case 2: - case 3: - PtyErase(pty, 0, pty->yn * pty->xn); - break; - default: - break; - } -} - -static void PtyEraseLine(struct Pty *pty) { - switch (PtyAtoi(pty->esc.s, NULL)) { - case 0: - PtyErase(pty, pty->y * pty->xn + pty->x, pty->xn - pty->x); - break; - case 1: - PtyErase(pty, pty->y * pty->xn, pty->x); - break; - case 2: - PtyErase(pty, pty->y * pty->xn, pty->xn); - break; - default: - break; - } -} - -static void PtyEraseCells(struct Pty *pty) { - int i, n, x; - i = pty->y * pty->xn + pty->x; - n = pty->yn * pty->xn; - x = min(max(PtyAtoi(pty->esc.s, NULL), 1), n - i); - PtyErase(pty, i, x); -} - -static int PtyArg1(struct Pty *pty) { - return max(1, PtyAtoi(pty->esc.s, NULL)); -} - -static void PtyInsertCells(struct Pty *pty) { - int n = min(pty->xn - pty->x, PtyArg1(pty)); - PtyMemmove(pty, pty->y * pty->xn + pty->x + n, pty->y * pty->xn + pty->x, - pty->xn - (pty->x + n)); - PtyErase(pty, pty->y * pty->xn + pty->x, n); -} - -static void PtyInsertLines(struct Pty *pty) { - int n = min(pty->yn - pty->y, PtyArg1(pty)); - PtyMemmove(pty, (pty->y + n) * pty->xn, pty->y * pty->xn, - (pty->yn - pty->y - n) * pty->xn); - PtyErase(pty, pty->y * pty->xn, n * pty->xn); -} - -static void PtyDeleteCells(struct Pty *pty) { - int n = min(pty->xn - pty->x, PtyArg1(pty)); - PtyMemmove(pty, pty->y * pty->xn + pty->x, pty->y * pty->xn + pty->x + n, - pty->xn - (pty->x + n)); - PtyErase(pty, pty->y * pty->xn + pty->x, n); -} - -static void PtyDeleteLines(struct Pty *pty) { - int n = min(pty->yn - pty->y, PtyArg1(pty)); - PtyMemmove(pty, pty->y * pty->xn, (pty->y + n) * pty->xn, - (pty->yn - pty->y - n) * pty->xn); - PtyErase(pty, (pty->y + n) * pty->xn, n * pty->xn); -} - -static void PtyReportDeviceStatus(struct Pty *pty) { - static const char report[] = "\e[0n"; - PtyWriteInput(pty, report, strlen(report)); -} - -static void PtyReportPreferredVtType(struct Pty *pty) { - static const char report[] = "\e[?1;0c"; - PtyWriteInput(pty, report, strlen(report)); -} - -static void PtyReportPreferredVtIdentity(struct Pty *pty) { - static const char report[] = "\e/Z"; - PtyWriteInput(pty, report, strlen(report)); -} - -static void PtyBell(struct Pty *pty) { - pty->conf |= kPtyBell; -} - -static void PtyLed(struct Pty *pty) { - switch (PtyAtoi(pty->esc.s, NULL)) { - case 0: - pty->conf &= ~kPtyLed1; - pty->conf &= ~kPtyLed2; - pty->conf &= ~kPtyLed3; - pty->conf &= ~kPtyLed4; - break; - case 1: - pty->conf |= kPtyLed1; - break; - case 2: - pty->conf |= kPtyLed2; - break; - case 3: - pty->conf |= kPtyLed3; - break; - case 4: - pty->conf |= kPtyLed4; - break; - default: - break; - } -} - -static void PtyReportCursorPosition(struct Pty *pty) { - char *p; - char buf[2 + 10 + 1 + 10 + 1]; - p = buf; - *p++ = '\e'; - *p++ = '['; - p = FormatInt32(p, (pty->y + 1) & 0x7fff); - *p++ = ';'; - p = FormatInt32(p, (pty->x + 1) & 0x7fff); - *p++ = 'R'; - PtyWriteInput(pty, buf, p - buf); -} - -static void PtyCsiN(struct Pty *pty) { - switch (PtyAtoi(pty->esc.s, NULL)) { - case 5: - PtyReportDeviceStatus(pty); - break; - case 6: - PtyReportCursorPosition(pty); - break; - default: - break; - } -} - -static void PtySelectGraphicsRendition(struct Pty *pty) { - char *p, c; - unsigned x; - uint8_t code[4]; - enum { - kSgr, - kSgrFg = 010, - kSgrFgTrue = 012, - kSgrFgXterm = 015, - kSgrBg = 020, - kSgrBgTrue = 022, - kSgrBgXterm = 025, - } t; - x = 0; - t = kSgr; - p = pty->esc.s; - bzero(code, sizeof(code)); - for (;;) { - c = *p++; - switch (c) { - case '\0': - return; - case '0' ... '9': - x *= 10; - x += c - '0'; - break; - case ';': - case 'm': - code[code[3]] = x; - x = 0; - switch (t) { - case kSgr: - switch (code[0]) { - case 38: - t = kSgrFg; - break; - case 48: - t = kSgrBg; - break; - case 0: - pty->pr = 0; - pty->xlat = GetXlatSgr(pty); - break; - case 1: - pty->pr |= kPtyBold; - pty->xlat = GetXlatSgr(pty); - break; - case 2: - pty->pr |= kPtyFaint; - break; - case 3: - pty->pr |= kPtyItalic; - pty->xlat = GetXlatSgr(pty); - break; - case 4: - pty->pr |= kPtyUnder; - break; - case 5: - pty->pr |= kPtyBlink; - break; - case 7: - pty->pr |= kPtyFlip; - break; - case 8: - pty->pr |= kPtyConceal; - break; - case 9: - pty->pr |= kPtyStrike; - break; - case 20: - pty->pr |= kPtyFraktur; - pty->xlat = GetXlatSgr(pty); - break; - case 21: - pty->pr |= kPtyUnder | kPtyDunder; - break; - case 22: - pty->pr &= ~(kPtyFaint | kPtyBold); - pty->xlat = GetXlatSgr(pty); - break; - case 23: - pty->pr &= ~kPtyItalic; - pty->xlat = GetXlatSgr(pty); - break; - case 24: - pty->pr &= ~(kPtyUnder | kPtyDunder); - break; - case 25: - pty->pr &= ~kPtyBlink; - break; - case 27: - pty->pr &= ~kPtyFlip; - break; - case 28: - pty->pr &= ~kPtyConceal; - break; - case 29: - pty->pr &= ~kPtyStrike; - break; - case 39: - pty->pr &= ~kPtyFg; - break; - case 49: - pty->pr &= ~kPtyBg; - break; - case 90 ... 97: - code[0] -= 90 - 30; - code[0] += 8; - /* fallthrough */ - case 30 ... 37: - pty->fg = code[0] - 30; - pty->pr |= kPtyFg; - pty->pr &= ~kPtyTrue; - break; - case 100 ... 107: - code[0] -= 100 - 40; - code[0] += 8; - /* fallthrough */ - case 40 ... 47: - pty->bg = code[0] - 40; - pty->pr |= kPtyBg; - pty->pr &= ~kPtyTrue; - break; - default: - break; - } - break; - case kSgrFg: - case kSgrBg: - switch (code[0]) { - case 2: - case 5: - t += code[0]; - break; - default: - t = kSgr; - break; - } - break; - case kSgrFgTrue: - if (++code[3] == 3) { - code[3] = 0; - t = kSgr; - pty->fg = READ32LE(code); - pty->pr |= kPtyFg; - pty->pr |= kPtyTrue; - } - break; - case kSgrBgTrue: - if (++code[3] == 3) { - code[3] = 0; - t = kSgr; - pty->bg = READ32LE(code); - pty->pr |= kPtyBg; - pty->pr |= kPtyTrue; - } - break; - case kSgrFgXterm: - t = kSgr; - pty->fg = code[0]; - pty->pr |= kPtyFg; - pty->pr &= ~kPtyTrue; - break; - case kSgrBgXterm: - t = kSgr; - pty->bg = code[0]; - pty->pr |= kPtyBg; - pty->pr &= ~kPtyTrue; - break; - default: - abort(); - } - break; - default: - break; - } - } -} - -static void PtyCsi(struct Pty *pty) { - switch (pty->esc.s[pty->esc.i - 1]) { - case 'f': - case 'H': - PtySetCursorPosition(pty); - break; - case 'G': - PtySetCursorColumn(pty); - break; - case 'd': - PtySetCursorRow(pty); - break; - case 'F': - pty->x = 0; - /* fallthrough */ - case 'A': - PtyMoveCursor(pty, -1, +0); - break; - case 'E': - pty->x = 0; - /* fallthrough */ - case 'B': - PtyMoveCursor(pty, +1, +0); - break; - case 'C': - PtyMoveCursor(pty, +0, +1); - break; - case 'D': - PtyMoveCursor(pty, +0, -1); - break; - case 'S': - PtyScrollUp(pty); - break; - case 'T': - PtyScrollDown(pty); - break; - case '@': - PtyInsertCells(pty); - break; - case 'P': - PtyDeleteCells(pty); - break; - case 'L': - PtyInsertLines(pty); - break; - case 'M': - PtyDeleteLines(pty); - break; - case 'J': - PtyEraseDisplay(pty); - break; - case 'K': - PtyEraseLine(pty); - break; - case 'X': - PtyEraseCells(pty); - break; - case 's': - PtySaveCursorPosition(pty); - break; - case 'u': - PtyRestoreCursorPosition(pty); - break; - case 'n': - PtyCsiN(pty); - break; - case 'm': - PtySelectGraphicsRendition(pty); - break; - case 'h': - PtySetMode(pty, true); - break; - case 'l': - PtySetMode(pty, false); - break; - case 'c': - PtyReportPreferredVtType(pty); - break; - case 'q': - PtyLed(pty); - break; - default: - break; - } -} - -static void PtyScreenAlignmentDisplay(struct Pty *pty) { - wmemset((void *)pty->wcs, 'E', pty->yn * pty->xn); -} - -static void PtyEscHash(struct Pty *pty) { - switch (pty->esc.s[1]) { - case '5': - PtySetXlat(pty, GetXlatAscii()); - break; - case '6': - PtySetXlat(pty, GetXlatDoubleWidth()); - break; - case '8': - PtyScreenAlignmentDisplay(pty); - break; - default: - break; - } -} - -static void PtyEsc(struct Pty *pty) { - switch (pty->esc.s[0]) { - case 'c': - PtyFullReset(pty); - break; - case '7': - PtySaveCursorPosition(pty); - break; - case '8': - PtyRestoreCursorPosition(pty); - break; - case 'E': - pty->x = 0; - case 'D': - PtyIndex(pty); - break; - case 'M': - PtyReverseIndex(pty); - break; - case 'Z': - PtyReportPreferredVtIdentity(pty); - break; - case '(': - PtySetCodepage(pty, pty->esc.s[1]); - break; - case '#': - PtyEscHash(pty); - break; - default: - break; - } -} - -static void PtyCntrl(struct Pty *pty, int c01) { - switch (c01) { - case '\a': - PtyBell(pty); - break; - case 0x85: - case '\f': - case '\v': - case '\n': - PtyNewline(pty); - break; - case '\r': - PtyCarriageReturn(pty); - break; - case '\e': - pty->state = kPtyEsc; - pty->esc.i = 0; - break; - case '\t': - PtyWriteTab(pty); - break; - case 0x7F: - case '\b': - pty->x = MAX(0, pty->x - 1); - break; - case 0x84: - PtyIndex(pty); - break; - case 0x8D: - PtyReverseIndex(pty); - break; - case 0x9B: - pty->state = kPtyCsi; - break; - default: - break; - } -} - -static void PtyEscAppend(struct Pty *pty, char c) { - pty->esc.i = MIN(pty->esc.i + 1, ARRAYLEN(pty->esc.s) - 1); - pty->esc.s[pty->esc.i - 1] = c; - pty->esc.s[pty->esc.i - 0] = 0; -} - -ssize_t PtyWrite(struct Pty *pty, const void *data, size_t n) { - int i; - wchar_t wc; - const uint8_t *p; - for (p = data, i = 0; i < n; ++i) { - switch (pty->state) { - case kPtyAscii: - if (0x00 <= p[i] && p[i] <= 0x7F) { - if (0x20 <= p[i] && p[i] <= 0x7E) { - if ((wc = pty->xlat[p[i]]) >= 0) { - PtyWriteGlyph(pty, wc, 1); - } else { - PtyWriteGlyph(pty, -wc, 2); - } - } else { - PtyCntrl(pty, p[i]); - } - } else if (!ThomPikeCont(p[i])) { - pty->state = kPtyUtf8; - pty->u8 = ThomPikeByte(p[i]); - pty->n8 = ThomPikeLen(p[i]) - 1; - } - break; - case kPtyUtf8: - if (ThomPikeCont(p[i])) { - pty->u8 = ThomPikeMerge(pty->u8, p[i]); - if (--pty->n8) break; - } - wc = pty->u8; - if ((0x00 <= wc && wc <= 0x1F) || // - (0x7F <= wc && wc <= 0x9F)) { - PtyCntrl(pty, wc); - } else { - PtyWriteGlyph(pty, wc, wcwidth(wc)); - } - pty->state = kPtyAscii; - pty->u8 = 0; - --i; - break; - case kPtyEsc: - if (p[i] == '[') { - pty->state = kPtyCsi; - } else if (0x30 <= p[i] && p[i] <= 0x7E) { - PtyEscAppend(pty, p[i]); - PtyEsc(pty); - pty->state = kPtyAscii; - } else if (0x20 <= p[i] && p[i] <= 0x2F) { - PtyEscAppend(pty, p[i]); - } else { - pty->state = kPtyAscii; - } - break; - case kPtyCsi: - PtyEscAppend(pty, p[i]); - switch (p[i]) { - case ':': - case ';': - case '<': - case '=': - case '>': - case '?': - case '0' ... '9': - break; - case '`': - case '~': - case '^': - case '@': - case '[': - case ']': - case '{': - case '}': - case '_': - case '|': - case '\\': - case 'A' ... 'Z': - case 'a' ... 'z': - PtyCsi(pty); - pty->state = kPtyAscii; - break; - default: - pty->state = kPtyAscii; - continue; - } - break; - default: - __builtin_unreachable(); - } - } - return n; -} - -ssize_t PtyWriteInput(struct Pty *pty, const void *data, size_t n) { - int c; - bool cr; - char *p; - const char *q; - size_t i, j, m; - q = data; - p = pty->input.p; - i = pty->input.i; - m = pty->input.n; - if (i + n * 2 + 1 > m) { - m = MAX(m, 8); - do m += m >> 1; - while (i + n * 2 + 1 > m); - if (!(p = realloc(p, m))) { - return -1; - } - pty->input.p = p; - pty->input.n = m; - } - cr = i && p[i - 1] == '\r'; - for (j = 0; j < n; ++j) { - c = q[j] & 255; - if (c == '\r') { - cr = true; - } else if (cr) { - if (c != '\n') { - p[i++] = '\n'; - } - cr = false; - } - p[i++] = c; - } - if (cr) { - p[i++] = '\n'; - } - if (!(pty->conf & kPtyNoecho)) { - PtyWrite(pty, p + pty->input.i, i - pty->input.i); - } - pty->input.i = i; - return n; -} - -ssize_t PtyRead(struct Pty *pty, void *buf, size_t size) { - char *p; - size_t n; - n = MIN(size, pty->input.i); - if (!(pty->conf & kPtyNocanon)) { - if ((p = memchr(pty->input.p, '\n', n))) { - n = MIN(n, pty->input.p - p + 1); - } else { - n = 0; - } - } - memcpy(buf, pty->input.p, n); - memcpy(pty->input.p, pty->input.p + n, pty->input.i - n); - pty->input.i -= n; - return n; -} - -static char *PtyEncodeRgb(char *p, int rgb) { - *p++ = '2'; - *p++ = ';'; - p = FormatUint32(p, (rgb & 0x0000ff) >> 000); - *p++ = ';'; - p = FormatUint32(p, (rgb & 0x00ff00) >> 010); - *p++ = ';'; - p = FormatUint32(p, (rgb & 0xff0000) >> 020); - return p; -} - -static char *PtyEncodeXterm256(char *p, int xt) { - *p++ = '5'; - *p++ = ';'; - p = FormatUint32(p, xt); - return p; -} - -char *PtyEncodeStyle(char *p, uint32_t xr, uint32_t pr, uint32_t fg, - uint32_t bg) { - *p++ = '\e'; - *p++ = '['; - if (pr & (kPtyBold | kPtyFaint | kPtyFlip | kPtyUnder | kPtyDunder | - kPtyBlink | kPtyStrike | kPtyFg | kPtyBg)) { - if (xr & (kPtyBold | kPtyFaint)) { - if ((xr & (kPtyBold | kPtyFaint)) ^ (pr & (kPtyBold | kPtyFaint))) { - *p++ = '2'; - *p++ = '2'; - *p++ = ';'; - } - if (pr & kPtyBold) { - *p++ = '1'; - *p++ = ';'; - } - if (pr & kPtyFaint) { - *p++ = '2'; - *p++ = ';'; - } - } - if (xr & (kPtyUnder | kPtyDunder)) { - if ((xr & (kPtyUnder | kPtyDunder)) ^ (pr & (kPtyUnder | kPtyDunder))) { - *p++ = '2'; - *p++ = '4'; - *p++ = ';'; - } - if (pr & kPtyUnder) { - *p++ = '4'; - *p++ = ';'; - } - if (pr & kPtyDunder) { - *p++ = '2'; - *p++ = '1'; - *p++ = ';'; - } - } - if (xr & (kPtyFlip | kPtyBlink | kPtyStrike)) { - if (xr & kPtyFlip) { - if (!(pr & kPtyFlip)) *p++ = '2'; - *p++ = '7'; - *p++ = ';'; - } - if (xr & kPtyBlink) { - if (!(pr & kPtyBlink)) *p++ = '2'; - *p++ = '5'; - *p++ = ';'; - } - if (xr & kPtyStrike) { - if (!(pr & kPtyStrike)) *p++ = '2'; - *p++ = '9'; - *p++ = ';'; - } - } - if (xr & (kPtyFg | kPtyTrue)) { - *p++ = '3'; - if (pr & kPtyFg) { - *p++ = '8'; - *p++ = ';'; - if (pr & kPtyTrue) { - p = PtyEncodeRgb(p, fg); - } else { - p = PtyEncodeXterm256(p, fg); - } - } else { - *p++ = '9'; - } - *p++ = ';'; - } - if (xr & (kPtyBg | kPtyTrue)) { - *p++ = '4'; - if (pr & kPtyBg) { - *p++ = '8'; - *p++ = ';'; - if (pr & kPtyTrue) { - p = PtyEncodeRgb(p, bg); - } else { - p = PtyEncodeXterm256(p, bg); - } - } else { - *p++ = '9'; - } - *p++ = ';'; - } - DCHECK_EQ(';', p[-1]); - p[-1] = 'm'; - } else { - *p++ = '0'; - *p++ = 'm'; - } - return p; -} - -int PtyAppendLine(struct Pty *pty, struct Buffer *buf, unsigned y) { - uint64_t u; - char *p, *pb; - uint32_t i, j, n, w, wc, np, xp, pr, fg, bg, ci; - if (y >= pty->yn) return einval(); - n = buf->i + pty->xn * 60; /* torture character length */ - if (n > buf->n) { - if (!(p = realloc(buf->p, n))) return -1; - buf->p = p; - buf->n = n; - } - i = y * pty->xn; - j = (y + 1) * pty->xn; - pb = buf->p + buf->i; - ci = !(pty->conf & kPtyNocursor) && y == pty->y ? i + pty->x : -1; - for (pr = 0; i < j; i += w) { - np = pty->prs[i]; - if (!(np & kPtyConceal)) { - wc = pty->wcs[i]; - DCHECK(!(0x00 <= wc && wc <= 0x1F)); - DCHECK(!(0x7F <= wc && wc <= 0x9F)); - if (0x20 <= wc && wc <= 0x7E) { - u = wc; - w = 1; - } else { - u = _tpenc(wc); - w = max(1, wcwidth(wc)); - } - } else { - u = ' '; - w = 1; - } - if (i == ci) { - if (u != ' ') { - np ^= kPtyFlip; - } else { - u = _tpenc(u'▂'); - if (pty->conf & kPtyBlinkcursor) { - np |= kPtyBlink; - } - } - } - fg = bg = -1; - xp = pr ^ np; - if (np & (kPtyFg | kPtyBg)) { - if (np & kPtyFg) { - if (pty->fgs[i] != fg) xp |= kPtyFg; - fg = pty->fgs[i]; - } - if (np & kPtyBg) { - if (pty->bgs[i] != bg) xp |= kPtyBg; - bg = pty->bgs[i]; - } - } - p = pb; - if (xp) { - pr = np; - p = PtyEncodeStyle(p, xp, pr, fg, bg); - } - do { - *p++ = u & 0xFF; - u >>= 8; - } while (u); - DCHECK_LE(p - pb, 60); - pb = p; - } - DCHECK_LE(pb - buf->p, buf->n); - buf->i = pb - buf->p; - return 0; -} diff --git a/tool/build/lib/pty.h b/tool/build/lib/pty.h deleted file mode 100644 index 974d564a2..000000000 --- a/tool/build/lib/pty.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_PTY_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_PTY_H_ -#include "tool/build/lib/buffer.h" - -#define kPtyFg 0x0001 -#define kPtyBg 0x0002 -#define kPtyBold 0x0004 -#define kPtyFlip 0x0008 -#define kPtyFaint 0x0010 -#define kPtyUnder 0x0020 -#define kPtyDunder 0x0040 -#define kPtyTrue 0x0080 -#define kPtyBlink 0x0100 -#define kPtyItalic 0x0200 -#define kPtyFraktur 0x0400 -#define kPtyStrike 0x0800 -#define kPtyConceal 0x1000 - -#define kPtyBell 0x001 -#define kPtyRedzone 0x002 -#define kPtyNocursor 0x004 -#define kPtyBlinkcursor 0x008 -#define kPtyNocanon 0x010 -#define kPtyNoecho 0x020 -#define kPtyNoopost 0x040 -#define kPtyLed1 0x080 -#define kPtyLed2 0x100 -#define kPtyLed3 0x200 -#define kPtyLed4 0x400 - -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -struct Pty { - int y; - int x; - int yn; - int xn; - uint32_t u8; - uint32_t n8; - uint32_t pr; - uint32_t fg; - uint32_t bg; - uint32_t conf; - uint32_t save; - uint32_t *wcs; - uint32_t *prs; - uint32_t *fgs; - uint32_t *bgs; - wchar_t *xlat; - enum PtyState { - kPtyAscii, - kPtyUtf8, - kPtyEsc, - kPtyCsi, - } state; - struct PtyEsc { - unsigned i; - char s[64]; - } esc; - struct PtyInput { - size_t i, n; - char *p; - } input; -}; - -void FreePty(struct Pty *); -struct Pty *NewPty(void) dontdiscard; -void PtyResize(struct Pty *, int, int); -ssize_t PtyRead(struct Pty *, void *, size_t); -ssize_t PtyWrite(struct Pty *, const void *, size_t); -ssize_t PtyWriteInput(struct Pty *, const void *, size_t); -int PtyAppendLine(struct Pty *, struct Buffer *, unsigned); -void PtyFullReset(struct Pty *); -void PtyMemmove(struct Pty *, long, long, long); -void PtyErase(struct Pty *, long, long); -void PtySetY(struct Pty *, int); -void PtySetX(struct Pty *, int); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_PTY_H_ */ diff --git a/tool/build/lib/pun.h b/tool/build/lib/pun.h deleted file mode 100644 index 3186e574d..000000000 --- a/tool/build/lib/pun.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_PUN_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_PUN_H_ -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -union FloatPun { - float f; - uint32_t i; -}; - -union DoublePun { - double f; - uint64_t i; -}; - -union FloatVectorPun { - union FloatPun u[4]; - float f[4]; -}; - -union DoubleVectorPun { - union DoublePun u[2]; - double f[2]; -}; - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_PUN_H_ */ diff --git a/tool/build/lib/reset.c b/tool/build/lib/reset.c deleted file mode 100644 index ff234ebda..000000000 --- a/tool/build/lib/reset.c +++ /dev/null @@ -1,96 +0,0 @@ -/*-*- 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/calls.h" -#include "libc/macros.internal.h" -#include "libc/math.h" -#include "libc/mem/mem.h" -#include "libc/str/str.h" -#include "tool/build/lib/flags.h" -#include "tool/build/lib/machine.h" - -#define LDBL 3 -#define RINT 0 - -static void ResetFpu(struct Machine *m) { - long i; - long double fval; - fval = -NAN; - m->fpu.sw = 0; - m->fpu.tw = -1; - m->fpu.cw = 0; - m->fpu.im = true; - m->fpu.dm = true; - m->fpu.zm = true; - m->fpu.om = true; - m->fpu.um = true; - m->fpu.pm = true; - m->fpu.pc = LDBL; - m->fpu.rc = RINT; - for (i = 0; i < ARRAYLEN(m->fpu.st); ++i) { - memcpy(&m->fpu.st[i], &fval, sizeof(fval)); - } -} - -static void ResetSse(struct Machine *m) { - m->sse.mxcsr = 0; - m->sse.daz = false; - m->sse.im = true; - m->sse.dm = true; - m->sse.zm = true; - m->sse.om = true; - m->sse.um = true; - m->sse.pm = true; - m->sse.rc = RINT; - m->sse.ftz = false; - bzero(m->xmm, sizeof(m->xmm)); -} - -void ResetInstructionCache(struct Machine *m) { - memset(m->icache, -1, sizeof(m->icache)); -} - -void ResetCpu(struct Machine *m) { - m->faultaddr = 0; - m->stashsize = 0; - m->stashaddr = 0; - m->writeaddr = 0; - m->readaddr = 0; - m->writesize = 0; - m->readsize = 0; - m->flags = SetFlag(m->flags, FLAGS_DF, false); - m->flags = SetFlag(m->flags, FLAGS_CF, false); - m->flags = SetFlag(m->flags, FLAGS_ZF, false); - m->flags = SetFlag(m->flags, FLAGS_SF, false); - m->flags = SetFlag(m->flags, FLAGS_IF, true); - m->flags = SetFlag(m->flags, FLAGS_F1, true); - m->flags = SetFlag(m->flags, FLAGS_F0, false); - m->flags = SetFlag(m->flags, FLAGS_IOPL, 3); - bzero(m->reg, sizeof(m->reg)); - bzero(m->bofram, sizeof(m->bofram)); - bzero(&m->freelist, sizeof(m->freelist)); - ResetSse(m); - ResetFpu(m); -} - -void ResetTlb(struct Machine *m) { - m->tlbindex = 0; - bzero(m->tlb, sizeof(m->tlb)); - m->codevirt = 0; - m->codehost = 0; -} diff --git a/tool/build/lib/signal.c b/tool/build/lib/signal.c deleted file mode 100644 index 100cf9f50..000000000 --- a/tool/build/lib/signal.c +++ /dev/null @@ -1,165 +0,0 @@ -/*-*- 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 2022 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/calls.h" -#include "libc/macros.internal.h" -#include "libc/runtime/runtime.h" -#include "libc/str/str.h" -#include "tool/build/lib/bits.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/machine.h" -#include "tool/build/lib/memory.h" -#include "tool/build/lib/signal.h" -#include "tool/build/lib/xlat.h" - -#define SIGCHLD_LINUX 17 -#define SIGURG_LINUX 23 -#define SIGWINCH_LINUX 28 - -void OpRestore(struct Machine *m) { - union { - struct fpstate_bits fp; - struct ucontext_bits uc; - } u; - VirtualSendRead(m, &u.uc, m->siguc, sizeof(u.uc)); - m->ip = Read64(u.uc.rip); - m->flags = Read64(u.uc.eflags); - memcpy(m->r8, u.uc.r8, 8); - memcpy(m->r9, u.uc.r9, 8); - memcpy(m->r10, u.uc.r10, 8); - memcpy(m->r11, u.uc.r11, 8); - memcpy(m->r12, u.uc.r12, 8); - memcpy(m->r13, u.uc.r13, 8); - memcpy(m->r14, u.uc.r14, 8); - memcpy(m->r15, u.uc.r15, 8); - memcpy(m->di, u.uc.rdi, 8); - memcpy(m->si, u.uc.rsi, 8); - memcpy(m->bp, u.uc.rbp, 8); - memcpy(m->bx, u.uc.rbx, 8); - memcpy(m->dx, u.uc.rdx, 8); - memcpy(m->ax, u.uc.rax, 8); - memcpy(m->cx, u.uc.rcx, 8); - memcpy(m->sp, u.uc.rsp, 8); - VirtualSendRead(m, &u.fp, m->sigfp, sizeof(u.fp)); - m->fpu.cw = Read16(u.fp.cwd); - m->fpu.sw = Read16(u.fp.swd); - m->fpu.tw = Read16(u.fp.ftw); - m->fpu.op = Read16(u.fp.fop); - m->fpu.ip = Read64(u.fp.rip); - m->fpu.dp = Read64(u.fp.rdp); - memcpy(m->fpu.st, u.fp.st, 128); - memcpy(m->xmm, u.fp.xmm, 256); - m->sig = 0; -} - -int DeliverSignal(struct Machine *m, int sig, int code) { - uint64_t sp, siaddr; - static struct siginfo_bits si; - static struct fpstate_bits fp; - static struct ucontext_bits uc; - switch (Read64(m->sighand[sig - 1].handler)) { - case 1: // SIG_IGN - return 0; - case 0: // SIG_DFL - if (sig == SIGCHLD_LINUX || sig == SIGURG_LINUX || - sig == SIGWINCH_LINUX) { - return 0; - } - raise(sig); - _exit(128 + sig); - default: - break; - } - Write32(si.si_signo, sig); - Write32(si.si_code, code); - memcpy(uc.r8, m->r8, 8); - memcpy(uc.r9, m->r9, 8); - memcpy(uc.r10, m->r10, 8); - memcpy(uc.r11, m->r11, 8); - memcpy(uc.r12, m->r12, 8); - memcpy(uc.r13, m->r13, 8); - memcpy(uc.r14, m->r14, 8); - memcpy(uc.r15, m->r15, 8); - memcpy(uc.rdi, m->di, 8); - memcpy(uc.rsi, m->si, 8); - memcpy(uc.rbp, m->bp, 8); - memcpy(uc.rbx, m->bx, 8); - memcpy(uc.rdx, m->dx, 8); - memcpy(uc.rax, m->ax, 8); - memcpy(uc.rcx, m->cx, 8); - memcpy(uc.rsp, m->sp, 8); - Write64(uc.rip, m->ip); - Write64(uc.eflags, m->flags); - Write16(fp.cwd, m->fpu.cw); - Write16(fp.swd, m->fpu.sw); - Write16(fp.ftw, m->fpu.tw); - Write16(fp.fop, m->fpu.op); - Write64(fp.rip, m->fpu.ip); - Write64(fp.rdp, m->fpu.dp); - memcpy(fp.st, m->fpu.st, 128); - memcpy(fp.xmm, m->xmm, 256); - sp = Read64(m->sp); - sp = ROUNDDOWN(sp - sizeof(si), 16); - VirtualRecvWrite(m, sp, &si, sizeof(si)); - siaddr = sp; - sp = ROUNDDOWN(sp - sizeof(fp), 16); - VirtualRecvWrite(m, sp, &fp, sizeof(fp)); - m->sigfp = sp; - Write64(uc.fpstate, sp); - sp = ROUNDDOWN(sp - sizeof(uc), 16); - VirtualRecvWrite(m, sp, &uc, sizeof(uc)); - m->siguc = sp; - m->sig = sig; - sp -= 8; - VirtualRecvWrite(m, sp, m->sighand[sig - 1].restorer, 8); - Write64(m->sp, sp); - Write64(m->di, sig); - Write64(m->si, siaddr); - Write64(m->dx, m->siguc); - m->ip = Read64(m->sighand[sig - 1].handler); - return 0; -} - -void EnqueueSignal(struct Machine *m, int sig, int code) { - if (m->signals.n < ARRAYLEN(m->signals.p)) { - m->signals.p[m->signals.n].code = UnXlatSicode(sig, code); - m->signals.p[m->signals.n].sig = UnXlatSignal(sig); - m->signals.n++; - } -} - -int ConsumeSignal(struct Machine *m) { - int sig, code; - sig = m->signals.p[m->signals.i].sig; - code = m->signals.p[m->signals.i].code; - if (!m->sig || - ((sig != m->sig || (Read64(m->sighand[m->sig - 1].flags) & 0x40000000)) && - !(Read64(m->sighand[m->sig - 1].mask) & (1ull << (m->sig - 1))))) { - if (++m->signals.i == m->signals.n) m->signals.i = m->signals.n = 0; - return DeliverSignal(m, sig, code); - } - return 0; -} - -void TerminateSignal(struct Machine *m, int sig) { - if (m->isfork) { - _exit(28 + sig); - } else { - exit(128 + sig); - } -} diff --git a/tool/build/lib/signal.h b/tool/build/lib/signal.h deleted file mode 100644 index fd0743be0..000000000 --- a/tool/build/lib/signal.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_SIGNAL_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_SIGNAL_H_ -#include "tool/build/lib/machine.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -void OpRestore(struct Machine *); -void TerminateSignal(struct Machine *, int); -int DeliverSignal(struct Machine *, int, int); -int ConsumeSignal(struct Machine *); -void EnqueueSignal(struct Machine *, int, int); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_SIGNAL_H_ */ diff --git a/tool/build/lib/sse.c b/tool/build/lib/sse.c deleted file mode 100644 index 95921e4fa..000000000 --- a/tool/build/lib/sse.c +++ /dev/null @@ -1,1575 +0,0 @@ -/*-*- 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/macros.internal.h" -#include "libc/str/str.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/machine.h" -#include "tool/build/lib/modrm.h" -#include "tool/build/lib/throw.h" - -static void MmxPor(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 8; ++i) { - x[i] |= y[i]; - } -} - -static void MmxPxor(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 8; ++i) { - x[i] ^= y[i]; - } -} - -static void MmxPsubb(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 8; ++i) { - x[i] -= y[i]; - } -} - -static void MmxPaddb(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 8; ++i) { - x[i] += y[i]; - } -} - -static void MmxPand(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 8; ++i) { - x[i] &= y[i]; - } -} - -static void MmxPandn(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 8; ++i) { - x[i] = ~x[i] & y[i]; - } -} - -static void MmxPavgb(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 8; ++i) { - x[i] = (x[i] + y[i] + 1) >> 1; - } -} - -static void MmxPabsb(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 8; ++i) { - x[i] = ABS((int8_t)y[i]); - } -} - -static void MmxPminub(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 8; ++i) { - x[i] = MIN(x[i], y[i]); - } -} - -static void MmxPmaxub(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 8; ++i) { - x[i] = MAX(x[i], y[i]); - } -} - -static void MmxPaddusb(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 8; ++i) { - x[i] = MIN(255, x[i] + y[i]); - } -} - -static void MmxPsubusb(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 8; ++i) { - x[i] = MIN(255, MAX(0, x[i] - y[i])); - } -} - -static void MmxPcmpeqb(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 8; ++i) { - x[i] = -(x[i] == y[i]); - } -} - -static void MmxPcmpgtb(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 8; ++i) { - x[i] = -((int8_t)x[i] > (int8_t)y[i]); - } -} - -static void MmxPsubsb(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 8; ++i) { - x[i] = MAX(-128, MIN(127, (int8_t)x[i] - (int8_t)y[i])); - } -} - -static void MmxPaddsb(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 8; ++i) { - x[i] = MAX(-128, MIN(127, (int8_t)x[i] + (int8_t)y[i])); - } -} - -static void MmxPmulhrsw(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - int16_t a, b; - for (i = 0; i < 4; ++i) { - a = Read16(x + i * 2); - b = Read16(y + i * 2); - Write16(x + i * 2, (((a * b) >> 14) + 1) >> 1); - } -} - -static void MmxPmaddubsw(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 4; ++i) { - Write16(x + i * 2, - MAX(-32768, MIN(32767, (x[i * 2 + 0] * (int8_t)y[i * 2 + 0] + - x[i * 2 + 1] * (int8_t)y[i * 2 + 1])))); - } -} - -static void MmxPsraw(uint8_t x[8], unsigned k) { - unsigned i; - if (k > 15) k = 15; - for (i = 0; i < 4; ++i) { - Write16(x + i * 2, (int16_t)Read16(x + i * 2) >> k); - } -} - -static void MmxPsrad(uint8_t x[8], unsigned k) { - unsigned i; - if (k > 31) k = 31; - for (i = 0; i < 2; ++i) { - Write32(x + i * 4, (int32_t)Read32(x + i * 4) >> k); - } -} - -static void MmxPsrlw(uint8_t x[8], unsigned k) { - unsigned i; - if (k < 16) { - for (i = 0; i < 4; ++i) { - Write16(x + i * 2, Read16(x + i * 2) >> k); - } - } else { - memset(x, 0, 8); - } -} - -static void MmxPsllw(uint8_t x[8], unsigned k) { - unsigned i; - if (k <= 15) { - for (i = 0; i < 4; ++i) { - Write16(x + i * 2, Read16(x + i * 2) << k); - } - } else { - memset(x, 0, 8); - } -} - -static void MmxPsrld(uint8_t x[8], unsigned k) { - unsigned i; - if (k <= 31) { - for (i = 0; i < 2; ++i) { - Write32(x + i * 4, Read32(x + i * 4) >> k); - } - } else { - memset(x, 0, 8); - } -} - -static void MmxPslld(uint8_t x[8], unsigned k) { - unsigned i; - if (k <= 31) { - for (i = 0; i < 2; ++i) { - Write32(x + i * 4, Read32(x + i * 4) << k); - } - } else { - memset(x, 0, 8); - } -} - -static void MmxPsrlq(uint8_t x[8], unsigned k) { - if (k <= 63) { - Write64(x, Read64(x) >> k); - } else { - memset(x, 0, 8); - } -} - -static void MmxPsllq(uint8_t x[8], unsigned k) { - if (k <= 63) { - Write64(x, Read64(x) << k); - } else { - memset(x, 0, 8); - } -} - -static void MmxPslldq(uint8_t x[8], unsigned k) { - unsigned i; - uint8_t t[8]; - if (k > 8) k = 8; - for (i = 0; i < k; ++i) t[i] = 0; - for (i = 0; i < 8 - k; ++i) t[k + i] = x[i]; - memcpy(x, t, 8); -} - -static void MmxPsrldq(uint8_t x[8], unsigned k) { - uint8_t t[8]; - if (k > 8) k = 8; - memcpy(t, x + k, 8 - k); - memset(t + (8 - k), 0, k); - memcpy(x, t, 8); -} - -static void MmxPalignr(uint8_t x[8], const uint8_t y[8], unsigned k) { - uint8_t t[24]; - memcpy(t, y, 8); - memcpy(t + 8, x, 8); - memset(t + 16, 0, 8); - memcpy(x, t + MIN(k, 16), 8); -} - -static void MmxPsubw(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 4; ++i) { - Write16(x + i * 2, Read16(x + i * 2) - Read16(y + i * 2)); - } -} - -static void MmxPaddw(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 4; ++i) { - Write16(x + i * 2, Read16(x + i * 2) + Read16(y + i * 2)); - } -} - -static void MmxPsubd(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 2; ++i) { - Write32(x + i * 4, Read32(x + i * 4) - Read32(y + i * 4)); - } -} - -static void MmxPaddd(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 2; ++i) { - Write32(x + i * 4, Read32(x + i * 4) + Read32(y + i * 4)); - } -} - -static void MmxPaddq(uint8_t x[8], const uint8_t y[8]) { - Write64(x, Read64(x) + Read64(y)); -} - -static void MmxPsubq(uint8_t x[8], const uint8_t y[8]) { - Write64(x, Read64(x) - Read64(y)); -} - -static void MmxPaddsw(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 4; ++i) { - Write16(x + i * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(x + i * 2) + - (int16_t)Read16(y + i * 2))))); - } -} - -static void MmxPsubsw(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 4; ++i) { - Write16(x + i * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(x + i * 2) - - (int16_t)Read16(y + i * 2))))); - } -} - -static void MmxPaddusw(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 4; ++i) { - Write16(x + i * 2, MIN(65535, Read16(x + i * 2) + Read16(y + i * 2))); - } -} - -static void MmxPsubusw(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 4; ++i) { - Write16(x + i * 2, - MIN(65535, MAX(0, Read16(x + i * 2) - Read16(y + i * 2)))); - } -} - -static void MmxPminsw(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 4; ++i) { - Write16(x + i * 2, - MIN((int16_t)Read16(x + i * 2), (int16_t)Read16(y + i * 2))); - } -} - -static void MmxPmaxsw(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 4; ++i) { - Write16(x + i * 2, - MAX((int16_t)Read16(x + i * 2), (int16_t)Read16(y + i * 2))); - } -} - -static void MmxPackuswb(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - uint8_t t[8]; - for (i = 0; i < 4; ++i) { - t[i + 0] = MIN(255, MAX(0, (int16_t)Read16(x + i * 2))); - } - for (i = 0; i < 4; ++i) { - t[i + 4] = MIN(255, MAX(0, (int16_t)Read16(y + i * 2))); - } - memcpy(x, t, 8); -} - -static void MmxPacksswb(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - uint8_t t[8]; - for (i = 0; i < 4; ++i) { - t[i + 0] = MAX(-128, MIN(127, (int16_t)Read16(x + i * 2))); - } - for (i = 0; i < 4; ++i) { - t[i + 4] = MAX(-128, MIN(127, (int16_t)Read16(y + i * 2))); - } - memcpy(x, t, 8); -} - -static void MmxPackssdw(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - uint8_t t[8]; - for (i = 0; i < 2; ++i) { - Write16(t + i * 2 + 0, MAX(-32768, MIN(32767, (int32_t)Read32(x + i * 4)))); - } - for (i = 0; i < 2; ++i) { - Write16(t + i * 2 + 4, MAX(-32768, MIN(32767, (int32_t)Read32(y + i * 4)))); - } - memcpy(x, t, 8); -} - -static void MmxPcmpgtw(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 4; ++i) { - Write16(x + i * 2, - -((int16_t)Read16(x + i * 2) > (int16_t)Read16(y + i * 2))); - } -} - -static void MmxPcmpeqw(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 4; ++i) { - Write16(x + i * 2, -(Read16(x + i * 2) == Read16(y + i * 2))); - } -} - -static void MmxPcmpgtd(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 2; ++i) { - Write32(x + i * 4, - -((int32_t)Read32(x + i * 4) > (int32_t)Read32(y + i * 4))); - } -} - -static void MmxPcmpeqd(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 2; ++i) { - Write32(x + i * 4, -(Read32(x + i * 4) == Read32(y + i * 4))); - } -} - -static void MmxPsrawv(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - uint64_t k; - k = Read64(y); - if (k > 15) k = 15; - for (i = 0; i < 4; ++i) { - Write16(x + i * 2, (int16_t)Read16(x + i * 2) >> k); - } -} - -static void MmxPsradv(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - uint64_t k; - k = Read64(y); - if (k > 31) k = 31; - for (i = 0; i < 2; ++i) { - Write32(x + i * 4, (int32_t)Read32(x + i * 4) >> k); - } -} - -static void MmxPsrlwv(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - uint64_t k; - k = Read64(y); - if (k < 16) { - for (i = 0; i < 4; ++i) { - Write16(x + i * 2, Read16(x + i * 2) >> k); - } - } else { - memset(x, 0, 8); - } -} - -static void MmxPsllwv(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - uint64_t k; - k = Read64(y); - if (k < 16) { - for (i = 0; i < 4; ++i) { - Write16(x + i * 2, Read16(x + i * 2) << k); - } - } else { - memset(x, 0, 8); - } -} - -static void MmxPsrldv(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - uint64_t k; - k = Read64(y); - if (k < 32) { - for (i = 0; i < 2; ++i) { - Write32(x + i * 4, Read32(x + i * 4) >> k); - } - } else { - memset(x, 0, 8); - } -} - -static void MmxPslldv(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - uint64_t k; - k = Read64(y); - if (k < 32) { - for (i = 0; i < 2; ++i) { - Write32(x + i * 4, Read32(x + i * 4) << k); - } - } else { - memset(x, 0, 8); - } -} - -static void MmxPsrlqv(uint8_t x[8], const uint8_t y[8]) { - uint64_t k; - k = Read64(y); - if (k < 64) { - Write64(x, Read64(x) >> k); - } else { - memset(x, 0, 8); - } -} - -static void MmxPsllqv(uint8_t x[8], const uint8_t y[8]) { - uint64_t k; - k = Read64(y); - if (k < 64) { - Write64(x, Read64(x) << k); - } else { - memset(x, 0, 8); - } -} - -static void MmxPavgw(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 4; ++i) { - Write16(x + i * 2, (Read16(x + i * 2) + Read16(y + i * 2) + 1) >> 1); - } -} - -static void MmxPsadbw(uint8_t x[8], const uint8_t y[8]) { - unsigned i, s, t; - for (s = i = 0; i < 4; ++i) s += ABS(x[i] - y[i]); - for (t = 0; i < 8; ++i) t += ABS(x[i] - y[i]); - Write32(x + 0, s); - Write32(x + 4, t); -} - -static void MmxPmaddwd(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 2; ++i) { - Write32(x + i * 4, - ((int16_t)Read16(x + i * 4 + 0) * (int16_t)Read16(y + i * 4 + 0) + - (int16_t)Read16(x + i * 4 + 2) * (int16_t)Read16(y + i * 4 + 2))); - } -} - -static void MmxPmulhuw(uint8_t x[8], const uint8_t y[8]) { - uint32_t v; - unsigned i; - for (i = 0; i < 4; ++i) { - v = Read16(x + i * 2); - v *= Read16(y + i * 2); - v >>= 16; - Write16(x + i * 2, v); - } -} - -static void MmxPmulhw(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 4; ++i) { - Write16(x + i * 2, - ((int16_t)Read16(x + i * 2) * (int16_t)Read16(y + i * 2)) >> 16); - } -} - -static void MmxPmuludq(uint8_t x[8], const uint8_t y[8]) { - Write64(x, (uint64_t)Read32(x) * Read32(y)); -} - -static void MmxPmullw(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 4; ++i) { - Write16(x + i * 2, (int16_t)Read16(x + i * 2) * (int16_t)Read16(y + i * 2)); - } -} - -static void MmxPmulld(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 2; ++i) { - Write32(x + i * 4, Read32(x + i * 4) * Read32(y + i * 4)); - } -} - -static void MmxPshufb(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - uint8_t t[8]; - for (i = 0; i < 8; ++i) { - t[i] = (y[i] & 128) ? 0 : x[y[i] & 7]; - } - memcpy(x, t, 8); -} - -static void MmxPsignb(uint8_t x[8], const uint8_t y[8]) { - int v; - unsigned i; - for (i = 0; i < 8; ++i) { - v = (int8_t)y[i]; - if (!v) { - x[i] = 0; - } else if (v < 0) { - x[i] = -(int8_t)x[i]; - } - } -} - -static void MmxPsignw(uint8_t x[8], const uint8_t y[8]) { - int v; - unsigned i; - for (i = 0; i < 4; ++i) { - v = (int16_t)Read16(y + i * 2); - if (!v) { - Write16(x + i * 2, 0); - } else if (v < 0) { - Write16(x + i * 2, -(int16_t)Read16(x + i * 2)); - } - } -} - -static void MmxPsignd(uint8_t x[8], const uint8_t y[8]) { - int32_t v; - unsigned i; - for (i = 0; i < 2; ++i) { - v = Read32(y + i * 4); - if (!v) { - Write32(x + i * 4, 0); - } else if (v < 0) { - Write32(x + i * 4, -Read32(x + i * 4)); - } - } -} - -static void MmxPabsw(uint8_t x[8], const uint8_t y[8]) { - unsigned i; - for (i = 0; i < 4; ++i) { - Write16(x + i * 2, ABS((int16_t)Read16(y + i * 2))); - } -} - -static void MmxPabsd(uint8_t x[8], const uint8_t y[8]) { - int32_t v; - unsigned i; - for (i = 0; i < 2; ++i) { - v = Read32(y + i * 4); - Write32(x + i * 4, v >= 0 ? v : -(uint32_t)v); - } -} - -static void MmxPhaddw(uint8_t x[8], const uint8_t y[8]) { - uint8_t t[8]; - Write16(t + 0 * 2, Read16(x + 0 * 2) + Read16(x + 1 * 2)); - Write16(t + 1 * 2, Read16(x + 2 * 2) + Read16(x + 3 * 2)); - Write16(t + 2 * 2, Read16(y + 0 * 2) + Read16(y + 1 * 2)); - Write16(t + 3 * 2, Read16(y + 2 * 2) + Read16(y + 3 * 2)); - memcpy(x, t, 8); -} - -static void MmxPhsubw(uint8_t x[8], const uint8_t y[8]) { - uint8_t t[8]; - Write16(t + 0 * 2, Read16(x + 0 * 2) - Read16(x + 1 * 2)); - Write16(t + 1 * 2, Read16(x + 2 * 2) - Read16(x + 3 * 2)); - Write16(t + 2 * 2, Read16(y + 0 * 2) - Read16(y + 1 * 2)); - Write16(t + 3 * 2, Read16(y + 2 * 2) - Read16(y + 3 * 2)); - memcpy(x, t, 8); -} - -static void MmxPhaddd(uint8_t x[8], const uint8_t y[8]) { - uint8_t t[8]; - Write32(t + 0 * 4, Read32(x + 0 * 4) + Read32(x + 1 * 4)); - Write32(t + 1 * 4, Read32(y + 0 * 4) + Read32(y + 1 * 4)); - memcpy(x, t, 8); -} - -static void MmxPhsubd(uint8_t x[8], const uint8_t y[8]) { - uint8_t t[8]; - Write32(t + 0 * 4, Read32(x + 0 * 4) - Read32(x + 1 * 4)); - Write32(t + 1 * 4, Read32(y + 0 * 4) - Read32(y + 1 * 4)); - memcpy(x, t, 8); -} - -static void MmxPhaddsw(uint8_t x[8], const uint8_t y[8]) { - uint8_t t[8]; - Write16(t + 0 * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(x + 0 * 2) + - (int16_t)Read16(x + 1 * 2))))); - Write16(t + 1 * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(x + 2 * 2) + - (int16_t)Read16(x + 3 * 2))))); - Write16(t + 2 * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(y + 0 * 2) + - (int16_t)Read16(y + 1 * 2))))); - Write16(t + 3 * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(y + 2 * 2) + - (int16_t)Read16(y + 3 * 2))))); - memcpy(x, t, 8); -} - -static void MmxPhsubsw(uint8_t x[8], const uint8_t y[8]) { - uint8_t t[8]; - Write16(t + 0 * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(x + 0 * 2) - - (int16_t)Read16(x + 1 * 2))))); - Write16(t + 1 * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(x + 2 * 2) - - (int16_t)Read16(x + 3 * 2))))); - Write16(t + 2 * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(y + 0 * 2) - - (int16_t)Read16(x + 1 * 2))))); - Write16(t + 3 * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(y + 2 * 2) - - (int16_t)Read16(y + 3 * 2))))); - memcpy(x, t, 8); -} - -static void MmxPunpcklbw(uint8_t x[8], const uint8_t y[8]) { - x[7] = y[3]; - x[6] = x[3]; - x[5] = y[2]; - x[4] = x[2]; - x[3] = y[1]; - x[2] = x[1]; - x[1] = y[0]; - x[0] = x[0]; -} - -static void MmxPunpckhbw(uint8_t x[8], const uint8_t y[8]) { - x[0] = x[4]; - x[1] = y[4]; - x[2] = x[5]; - x[3] = y[5]; - x[4] = x[6]; - x[5] = y[6]; - x[6] = x[7]; - x[7] = y[7]; -} - -static void MmxPunpcklwd(uint8_t x[8], const uint8_t y[8]) { - x[6] = y[2]; - x[7] = y[3]; - x[4] = x[2]; - x[5] = x[3]; - x[2] = y[0]; - x[3] = y[1]; - x[0] = x[0]; - x[1] = x[1]; -} - -static void MmxPunpckldq(uint8_t x[8], const uint8_t y[8]) { - x[4] = y[0]; - x[5] = y[1]; - x[6] = y[2]; - x[7] = y[3]; - x[0] = x[0]; - x[1] = x[1]; - x[2] = x[2]; - x[3] = x[3]; -} - -static void MmxPunpckhwd(uint8_t x[8], const uint8_t y[8]) { - x[0] = x[4]; - x[1] = x[5]; - x[2] = y[4]; - x[3] = y[5]; - x[4] = x[6]; - x[5] = x[7]; - x[6] = y[6]; - x[7] = y[7]; -} - -static void MmxPunpckhdq(uint8_t x[8], const uint8_t y[8]) { - x[0] = x[4]; - x[1] = x[5]; - x[2] = x[6]; - x[3] = x[7]; - x[4] = y[4]; - x[5] = y[5]; - x[6] = y[6]; - x[7] = y[7]; -} - -static void MmxPunpcklqdq(uint8_t x[8], const uint8_t y[8]) { -} - -static void MmxPunpckhqdq(uint8_t x[8], const uint8_t y[8]) { -} - -static void SsePsubb(uint8_t x[16], const uint8_t y[16]) { - unsigned i; - for (i = 0; i < 16; ++i) { - x[i] -= y[i]; - } -} - -static void SsePaddb(uint8_t x[16], const uint8_t y[16]) { - unsigned i; - for (i = 0; i < 16; ++i) { - x[i] += y[i]; - } -} - -static void SsePor(uint8_t x[16], const uint8_t y[16]) { - unsigned i; - for (i = 0; i < 16; ++i) { - x[i] |= y[i]; - } -} - -static void SsePxor(uint8_t x[16], const uint8_t y[16]) { - unsigned i; - for (i = 0; i < 16; ++i) { - x[i] ^= y[i]; - } -} - -static void SsePand(uint8_t x[16], const uint8_t y[16]) { - unsigned i; - for (i = 0; i < 16; ++i) { - x[i] &= y[i]; - } -} - -static void SsePandn(uint8_t x[16], const uint8_t y[16]) { - unsigned i; - for (i = 0; i < 16; ++i) { - x[i] = ~x[i] & y[i]; - } -} - -static void SsePcmpeqb(uint8_t x[16], const uint8_t y[16]) { - unsigned i; - for (i = 0; i < 16; ++i) { - x[i] = -(x[i] == y[i]); - } -} - -static void SsePcmpgtb(uint8_t x[16], const uint8_t y[16]) { - unsigned i; - for (i = 0; i < 16; ++i) { - x[i] = -((int8_t)x[i] > (int8_t)y[i]); - } -} - -static void SsePavgb(uint8_t x[16], const uint8_t y[16]) { - unsigned i; - for (i = 0; i < 16; ++i) { - x[i] = (x[i] + y[i] + 1) >> 1; - } -} - -static void SsePabsb(uint8_t x[16], const uint8_t y[16]) { - unsigned i; - for (i = 0; i < 16; ++i) { - x[i] = ABS((int8_t)y[i]); - } -} - -static void SsePminub(uint8_t x[16], const uint8_t y[16]) { - unsigned i; - for (i = 0; i < 16; ++i) { - x[i] = MIN(x[i], y[i]); - } -} - -static void SsePmaxub(uint8_t x[16], const uint8_t y[16]) { - unsigned i; - for (i = 0; i < 16; ++i) { - x[i] = MAX(x[i], y[i]); - } -} - -static void SsePslldq(uint8_t x[16], unsigned k) { - unsigned i; - uint8_t t[16]; - if (k > 16) k = 16; - for (i = 0; i < k; ++i) t[i] = 0; - for (i = 0; i < 16 - k; ++i) t[k + i] = x[i]; - memcpy(x, t, 16); -} - -static void SsePsrldq(uint8_t x[16], unsigned k) { - uint8_t t[16]; - if (k > 16) k = 16; - memcpy(t, x + k, 16 - k); - memset(t + (16 - k), 0, k); - memcpy(x, t, 16); -} - -static void SsePalignr(uint8_t x[16], const uint8_t y[16], unsigned k) { - uint8_t t[48]; - memcpy(t, y, 16); - memcpy(t + 16, x, 16); - memset(t + 32, 0, 16); - memcpy(x, t + MIN(k, 32), 16); -} - -static void SsePsubw(uint8_t x[16], const uint8_t y[16]) { - unsigned i; - for (i = 0; i < 8; ++i) { - Write16(x + i * 2, Read16(x + i * 2) - Read16(y + i * 2)); - } -} - -static void SsePaddw(uint8_t x[16], const uint8_t y[16]) { - unsigned i; - for (i = 0; i < 8; ++i) { - Write16(x + i * 2, Read16(x + i * 2) + Read16(y + i * 2)); - } -} - -static void SsePsubd(uint8_t x[16], const uint8_t y[16]) { - unsigned i; - for (i = 0; i < 4; ++i) { - Write32(x + i * 4, Read32(x + i * 4) - Read32(y + i * 4)); - } -} - -static void SsePaddd(uint8_t x[16], const uint8_t y[16]) { - unsigned i; - for (i = 0; i < 4; ++i) { - Write32(x + i * 4, Read32(x + i * 4) + Read32(y + i * 4)); - } -} - -static void SsePaddq(uint8_t x[16], const uint8_t y[16]) { - unsigned i; - for (i = 0; i < 2; ++i) { - Write64(x + i * 8, Read64(x + i * 8) + Read64(y + i * 8)); - } -} - -static void SsePsubq(uint8_t x[16], const uint8_t y[16]) { - unsigned i; - for (i = 0; i < 2; ++i) { - Write64(x + i * 8, Read64(x + i * 8) - Read64(y + i * 8)); - } -} - -static void SsePaddusw(uint8_t x[16], const uint8_t y[16]) { - unsigned i; - for (i = 0; i < 8; ++i) { - Write16(x + i * 2, MIN(65535, Read16(x + i * 2) + Read16(y + i * 2))); - } -} - -static void SsePackuswb(uint8_t x[16], const uint8_t y[16]) { - unsigned i; - uint8_t t[16]; - for (i = 0; i < 8; ++i) { - t[i + 0] = MIN(255, MAX(0, (int16_t)Read16(x + i * 2))); - } - for (i = 0; i < 8; ++i) { - t[i + 8] = MIN(255, MAX(0, (int16_t)Read16(y + i * 2))); - } - memcpy(x, t, 16); -} - -static void SsePacksswb(uint8_t x[16], const uint8_t y[16]) { - unsigned i; - uint8_t t[16]; - for (i = 0; i < 8; ++i) { - t[i + 0] = MAX(-128, MIN(127, (int16_t)Read16(x + i * 2))); - } - for (i = 0; i < 8; ++i) { - t[i + 8] = MAX(-128, MIN(127, (int16_t)Read16(y + i * 2))); - } - memcpy(x, t, 16); -} - -static void SsePackssdw(uint8_t x[16], const uint8_t y[16]) { - unsigned i; - uint8_t t[16]; - for (i = 0; i < 4; ++i) { - Write16(t + i * 2 + 0, MAX(-32768, MIN(32767, (int32_t)Read32(x + i * 4)))); - } - for (i = 0; i < 4; ++i) { - Write16(t + i * 2 + 8, MAX(-32768, MIN(32767, (int32_t)Read32(y + i * 4)))); - } - memcpy(x, t, 16); -} - -static void SsePsadbw(uint8_t x[16], const uint8_t y[16]) { - unsigned i, s, t; - for (s = i = 0; i < 8; ++i) s += ABS(x[i] - y[i]); - for (t = 0; i < 16; ++i) t += ABS(x[i] - y[i]); - Write64(x + 0, s); - Write64(x + 8, t); -} - -static void SsePmuludq(uint8_t x[16], const uint8_t y[16]) { - unsigned i; - for (i = 0; i < 2; ++i) { - Write64(x + i * 8, (uint64_t)Read32(x + i * 8) * Read32(y + i * 8)); - } -} - -static void SsePshufb(uint8_t x[16], const uint8_t y[16]) { - unsigned i; - uint8_t t[16]; - for (i = 0; i < 16; ++i) { - t[i] = (y[i] & 128) ? 0 : x[y[i] & 15]; - } - memcpy(x, t, 16); -} - -static void SsePhaddd(uint8_t x[16], const uint8_t y[16]) { - uint8_t t[16]; - Write32(t + 0 * 4, Read32(x + 0 * 4) + Read32(x + 1 * 4)); - Write32(t + 1 * 4, Read32(x + 2 * 4) + Read32(x + 3 * 4)); - Write32(t + 2 * 4, Read32(y + 0 * 4) + Read32(y + 1 * 4)); - Write32(t + 3 * 4, Read32(y + 2 * 4) + Read32(y + 3 * 4)); - memcpy(x, t, 16); -} - -static void SsePhsubd(uint8_t x[16], const uint8_t y[16]) { - uint8_t t[16]; - Write32(t + 0 * 4, Read32(x + 0 * 4) - Read32(x + 1 * 4)); - Write32(t + 1 * 4, Read32(x + 2 * 4) - Read32(x + 3 * 4)); - Write32(t + 2 * 4, Read32(y + 0 * 4) - Read32(y + 1 * 4)); - Write32(t + 3 * 4, Read32(y + 2 * 4) - Read32(y + 3 * 4)); - memcpy(x, t, 16); -} - -static void SsePhaddw(uint8_t x[16], const uint8_t y[16]) { - uint8_t t[16]; - Write16(t + 0 * 2, Read16(x + 0 * 2) + Read16(x + 1 * 2)); - Write16(t + 1 * 2, Read16(x + 2 * 2) + Read16(x + 3 * 2)); - Write16(t + 2 * 2, Read16(x + 4 * 2) + Read16(x + 5 * 2)); - Write16(t + 3 * 2, Read16(x + 6 * 2) + Read16(x + 7 * 2)); - Write16(t + 4 * 2, Read16(y + 0 * 2) + Read16(y + 1 * 2)); - Write16(t + 5 * 2, Read16(y + 2 * 2) + Read16(y + 3 * 2)); - Write16(t + 6 * 2, Read16(y + 4 * 2) + Read16(y + 5 * 2)); - Write16(t + 7 * 2, Read16(y + 6 * 2) + Read16(y + 7 * 2)); - memcpy(x, t, 16); -} - -static void SsePhsubw(uint8_t x[16], const uint8_t y[16]) { - uint8_t t[16]; - Write16(t + 0 * 2, Read16(x + 0 * 2) - Read16(x + 1 * 2)); - Write16(t + 1 * 2, Read16(x + 2 * 2) - Read16(x + 3 * 2)); - Write16(t + 2 * 2, Read16(x + 4 * 2) - Read16(x + 5 * 2)); - Write16(t + 3 * 2, Read16(x + 6 * 2) - Read16(x + 7 * 2)); - Write16(t + 4 * 2, Read16(y + 0 * 2) - Read16(y + 1 * 2)); - Write16(t + 5 * 2, Read16(y + 2 * 2) - Read16(y + 3 * 2)); - Write16(t + 6 * 2, Read16(y + 4 * 2) - Read16(y + 5 * 2)); - Write16(t + 7 * 2, Read16(y + 6 * 2) - Read16(y + 7 * 2)); - memcpy(x, t, 16); -} - -static void SsePhaddsw(uint8_t x[16], const uint8_t y[16]) { - uint8_t t[16]; - Write16(t + 0 * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(x + 0 * 2) + - (int16_t)Read16(x + 1 * 2))))); - Write16(t + 1 * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(x + 2 * 2) + - (int16_t)Read16(x + 3 * 2))))); - Write16(t + 2 * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(x + 4 * 2) + - (int16_t)Read16(x + 5 * 2))))); - Write16(t + 3 * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(x + 6 * 2) + - (int16_t)Read16(x + 7 * 2))))); - Write16(t + 4 * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(y + 0 * 2) + - (int16_t)Read16(y + 1 * 2))))); - Write16(t + 5 * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(y + 2 * 2) + - (int16_t)Read16(y + 3 * 2))))); - Write16(t + 6 * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(y + 4 * 2) + - (int16_t)Read16(y + 5 * 2))))); - Write16(t + 7 * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(y + 6 * 2) + - (int16_t)Read16(y + 7 * 2))))); - memcpy(x, t, 16); -} - -static void SsePhsubsw(uint8_t x[16], const uint8_t y[16]) { - uint8_t t[16]; - Write16(t + 0 * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(x + 0 * 2) - - (int16_t)Read16(x + 1 * 2))))); - Write16(t + 1 * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(x + 2 * 2) - - (int16_t)Read16(x + 3 * 2))))); - Write16(t + 2 * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(x + 4 * 2) - - (int16_t)Read16(x + 5 * 2))))); - Write16(t + 3 * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(x + 6 * 2) - - (int16_t)Read16(x + 7 * 2))))); - Write16(t + 4 * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(y + 0 * 2) - - (int16_t)Read16(y + 1 * 2))))); - Write16(t + 5 * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(y + 2 * 2) - - (int16_t)Read16(y + 3 * 2))))); - Write16(t + 6 * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(y + 4 * 2) - - (int16_t)Read16(y + 5 * 2))))); - Write16(t + 7 * 2, MAX(-32768, MIN(32767, ((int16_t)Read16(y + 6 * 2) - - (int16_t)Read16(y + 7 * 2))))); - memcpy(x, t, 16); -} - -static void SsePunpcklbw(uint8_t x[16], const uint8_t y[16]) { - x[0xf] = y[0x7]; - x[0xe] = x[0x7]; - x[0xd] = y[0x6]; - x[0xc] = x[0x6]; - x[0xb] = y[0x5]; - x[0xa] = x[0x5]; - x[0x9] = y[0x4]; - x[0x8] = x[0x4]; - x[0x7] = y[0x3]; - x[0x6] = x[0x3]; - x[0x5] = y[0x2]; - x[0x4] = x[0x2]; - x[0x3] = y[0x1]; - x[0x2] = x[0x1]; - x[0x1] = y[0x0]; - x[0x0] = x[0x0]; -} - -static void SsePunpckhbw(uint8_t x[16], const uint8_t y[16]) { - x[0x0] = x[0x8]; - x[0x1] = y[0x8]; - x[0x2] = x[0x9]; - x[0x3] = y[0x9]; - x[0x4] = x[0xa]; - x[0x5] = y[0xa]; - x[0x6] = x[0xb]; - x[0x7] = y[0xb]; - x[0x8] = x[0xc]; - x[0x9] = y[0xc]; - x[0xa] = x[0xd]; - x[0xb] = y[0xd]; - x[0xc] = x[0xe]; - x[0xd] = y[0xe]; - x[0xe] = x[0xf]; - x[0xf] = y[0xf]; -} - -static void SsePunpcklwd(uint8_t x[16], const uint8_t y[16]) { - x[0xe] = y[0x6]; - x[0xf] = y[0x7]; - x[0xc] = x[0x6]; - x[0xd] = x[0x7]; - x[0xa] = y[0x4]; - x[0xb] = y[0x5]; - x[0x8] = x[0x4]; - x[0x9] = x[0x5]; - x[0x6] = y[0x2]; - x[0x7] = y[0x3]; - x[0x4] = x[0x2]; - x[0x5] = x[0x3]; - x[0x2] = y[0x0]; - x[0x3] = y[0x1]; - x[0x0] = x[0x0]; - x[0x1] = x[0x1]; -} - -static void SsePunpckldq(uint8_t x[16], const uint8_t y[16]) { - x[0xc] = y[0x4]; - x[0xd] = y[0x5]; - x[0xe] = y[0x6]; - x[0xf] = y[0x7]; - x[0x8] = x[0x4]; - x[0x9] = x[0x5]; - x[0xa] = x[0x6]; - x[0xb] = x[0x7]; - x[0x4] = y[0x0]; - x[0x5] = y[0x1]; - x[0x6] = y[0x2]; - x[0x7] = y[0x3]; - x[0x0] = x[0x0]; - x[0x1] = x[0x1]; - x[0x2] = x[0x2]; - x[0x3] = x[0x3]; -} - -static void SsePunpckhwd(uint8_t x[16], const uint8_t y[16]) { - x[0x0] = x[0x8]; - x[0x1] = x[0x9]; - x[0x2] = y[0x8]; - x[0x3] = y[0x9]; - x[0x4] = x[0xa]; - x[0x5] = x[0xb]; - x[0x6] = y[0xa]; - x[0x7] = y[0xb]; - x[0x8] = x[0xc]; - x[0x9] = x[0xd]; - x[0xa] = y[0xc]; - x[0xb] = y[0xd]; - x[0xc] = x[0xe]; - x[0xd] = x[0xf]; - x[0xe] = y[0xe]; - x[0xf] = y[0xf]; -} - -static void SsePunpckhdq(uint8_t x[16], const uint8_t y[16]) { - x[0x0] = x[0x8]; - x[0x1] = x[0x9]; - x[0x2] = x[0xa]; - x[0x3] = x[0xb]; - x[0x4] = y[0x8]; - x[0x5] = y[0x9]; - x[0x6] = y[0xa]; - x[0x7] = y[0xb]; - x[0x8] = x[0xc]; - x[0x9] = x[0xd]; - x[0xa] = x[0xe]; - x[0xb] = x[0xf]; - x[0xc] = y[0xc]; - x[0xd] = y[0xd]; - x[0xe] = y[0xe]; - x[0xf] = y[0xf]; -} - -static void SsePunpcklqdq(uint8_t x[16], const uint8_t y[16]) { - x[0x8] = y[0x0]; - x[0x9] = y[0x1]; - x[0xa] = y[0x2]; - x[0xb] = y[0x3]; - x[0xc] = y[0x4]; - x[0xd] = y[0x5]; - x[0xe] = y[0x6]; - x[0xf] = y[0x7]; - x[0x0] = x[0x0]; - x[0x1] = x[0x1]; - x[0x2] = x[0x2]; - x[0x3] = x[0x3]; - x[0x4] = x[0x4]; - x[0x5] = x[0x5]; - x[0x6] = x[0x6]; - x[0x7] = x[0x7]; -} - -static void SsePunpckhqdq(uint8_t x[16], const uint8_t y[16]) { - x[0x0] = x[0x8]; - x[0x1] = x[0x9]; - x[0x2] = x[0xa]; - x[0x3] = x[0xb]; - x[0x4] = x[0xc]; - x[0x5] = x[0xd]; - x[0x6] = x[0xe]; - x[0x7] = x[0xf]; - x[0x8] = y[0x8]; - x[0x9] = y[0x9]; - x[0xa] = y[0xa]; - x[0xb] = y[0xb]; - x[0xc] = y[0xc]; - x[0xd] = y[0xd]; - x[0xe] = y[0xe]; - x[0xf] = y[0xf]; -} - -static void SsePsrlw(uint8_t x[16], unsigned k) { - MmxPsrlw(x + 0, k); - MmxPsrlw(x + 8, k); -} - -static void SsePsraw(uint8_t x[16], unsigned k) { - MmxPsraw(x + 0, k); - MmxPsraw(x + 8, k); -} - -static void SsePsllw(uint8_t x[16], unsigned k) { - MmxPsllw(x + 0, k); - MmxPsllw(x + 8, k); -} - -static void SsePsrld(uint8_t x[16], unsigned k) { - MmxPsrld(x + 0, k); - MmxPsrld(x + 8, k); -} - -static void SsePsrad(uint8_t x[16], unsigned k) { - MmxPsrad(x + 0, k); - MmxPsrad(x + 8, k); -} - -static void SsePslld(uint8_t x[16], unsigned k) { - MmxPslld(x + 0, k); - MmxPslld(x + 8, k); -} - -static void SsePsrlq(uint8_t x[16], unsigned k) { - MmxPsrlq(x + 0, k); - MmxPsrlq(x + 8, k); -} - -static void SsePsllq(uint8_t x[16], unsigned k) { - MmxPsllq(x + 0, k); - MmxPsllq(x + 8, k); -} - -static void SsePsubsb(uint8_t x[16], const uint8_t y[16]) { - MmxPsubsb(x + 0, y + 0); - MmxPsubsb(x + 8, y + 8); -} - -static void SsePaddsb(uint8_t x[16], const uint8_t y[16]) { - MmxPaddsb(x + 0, y + 0); - MmxPaddsb(x + 8, y + 8); -} - -static void SsePsubsw(uint8_t x[16], const uint8_t y[16]) { - MmxPsubsw(x + 0, y + 0); - MmxPsubsw(x + 8, y + 8); -} - -static void SsePaddsw(uint8_t x[16], const uint8_t y[16]) { - MmxPaddsw(x + 0, y + 0); - MmxPaddsw(x + 8, y + 8); -} - -static void SsePaddusb(uint8_t x[16], const uint8_t y[16]) { - MmxPaddusb(x + 0, y + 0); - MmxPaddusb(x + 8, y + 8); -} - -static void SsePsubusb(uint8_t x[16], const uint8_t y[16]) { - MmxPsubusb(x + 0, y + 0); - MmxPsubusb(x + 8, y + 8); -} - -static void SsePsubusw(uint8_t x[16], const uint8_t y[16]) { - MmxPsubusw(x + 0, y + 0); - MmxPsubusw(x + 8, y + 8); -} - -static void SsePminsw(uint8_t x[16], const uint8_t y[16]) { - MmxPminsw(x + 0, y + 0); - MmxPminsw(x + 8, y + 8); -} - -static void SsePmaxsw(uint8_t x[16], const uint8_t y[16]) { - MmxPmaxsw(x + 0, y + 0); - MmxPmaxsw(x + 8, y + 8); -} - -static void SsePsignb(uint8_t x[16], const uint8_t y[16]) { - MmxPsignb(x + 0, y + 0); - MmxPsignb(x + 8, y + 8); -} - -static void SsePsignw(uint8_t x[16], const uint8_t y[16]) { - MmxPsignw(x + 0, y + 0); - MmxPsignw(x + 8, y + 8); -} - -static void SsePsignd(uint8_t x[16], const uint8_t y[16]) { - MmxPsignd(x + 0, y + 0); - MmxPsignd(x + 8, y + 8); -} - -static void SsePmulhrsw(uint8_t x[16], const uint8_t y[16]) { - MmxPmulhrsw(x + 0, y + 0); - MmxPmulhrsw(x + 8, y + 8); -} - -static void SsePabsw(uint8_t x[16], const uint8_t y[16]) { - MmxPabsw(x + 0, y + 0); - MmxPabsw(x + 8, y + 8); -} - -static void SsePabsd(uint8_t x[16], const uint8_t y[16]) { - MmxPabsd(x + 0, y + 0); - MmxPabsd(x + 8, y + 8); -} - -static void SsePcmpgtw(uint8_t x[16], const uint8_t y[16]) { - MmxPcmpgtw(x + 0, y + 0); - MmxPcmpgtw(x + 8, y + 8); -} - -static void SsePcmpeqw(uint8_t x[16], const uint8_t y[16]) { - MmxPcmpeqw(x + 0, y + 0); - MmxPcmpeqw(x + 8, y + 8); -} - -static void SsePcmpgtd(uint8_t x[16], const uint8_t y[16]) { - MmxPcmpgtd(x + 0, y + 0); - MmxPcmpgtd(x + 8, y + 8); -} - -static void SsePcmpeqd(uint8_t x[16], const uint8_t y[16]) { - MmxPcmpeqd(x + 0, y + 0); - MmxPcmpeqd(x + 8, y + 8); -} - -static void SsePsrawv(uint8_t x[16], const uint8_t y[16]) { - MmxPsrawv(x + 0, y); - MmxPsrawv(x + 8, y); -} - -static void SsePsradv(uint8_t x[16], const uint8_t y[16]) { - MmxPsradv(x + 0, y); - MmxPsradv(x + 8, y); -} - -static void SsePsrlwv(uint8_t x[16], const uint8_t y[16]) { - MmxPsrlwv(x + 0, y); - MmxPsrlwv(x + 8, y); -} - -static void SsePsllwv(uint8_t x[16], const uint8_t y[16]) { - MmxPsllwv(x + 0, y); - MmxPsllwv(x + 8, y); -} - -static void SsePsrldv(uint8_t x[16], const uint8_t y[16]) { - MmxPsrldv(x + 0, y); - MmxPsrldv(x + 8, y); -} - -static void SsePslldv(uint8_t x[16], const uint8_t y[16]) { - MmxPslldv(x + 0, y); - MmxPslldv(x + 8, y); -} - -static void SsePsrlqv(uint8_t x[16], const uint8_t y[16]) { - MmxPsrlqv(x + 0, y); - MmxPsrlqv(x + 8, y); -} - -static void SsePsllqv(uint8_t x[16], const uint8_t y[16]) { - MmxPsllqv(x + 0, y); - MmxPsllqv(x + 8, y); -} - -static void SsePavgw(uint8_t x[16], const uint8_t y[16]) { - MmxPavgw(x + 0, y + 0); - MmxPavgw(x + 8, y + 8); -} - -static void SsePmaddwd(uint8_t x[16], const uint8_t y[16]) { - MmxPmaddwd(x + 0, y + 0); - MmxPmaddwd(x + 8, y + 8); -} - -static void SsePmulhuw(uint8_t x[16], const uint8_t y[16]) { - MmxPmulhuw(x + 0, y + 0); - MmxPmulhuw(x + 8, y + 8); -} - -static void SsePmulhw(uint8_t x[16], const uint8_t y[16]) { - MmxPmulhw(x + 0, y + 0); - MmxPmulhw(x + 8, y + 8); -} - -static void SsePmullw(uint8_t x[16], const uint8_t y[16]) { - MmxPmullw(x + 0, y + 0); - MmxPmullw(x + 8, y + 8); -} - -static void SsePmulld(uint8_t x[16], const uint8_t y[16]) { - MmxPmulld(x + 0, y + 0); - MmxPmulld(x + 8, y + 8); -} - -static void SsePmaddubsw(uint8_t x[16], const uint8_t y[16]) { - MmxPmaddubsw(x + 0, y + 0); - MmxPmaddubsw(x + 8, y + 8); -} - -static void OpPsb(struct Machine *m, uint32_t rde, - void MmxKernel(uint8_t[8], unsigned), - void SseKernel(uint8_t[16], unsigned)) { - if (Osz(rde)) { - SseKernel(XmmRexbRm(m, rde), m->xedd->op.uimm0); - } else { - MmxKernel(XmmRexbRm(m, rde), m->xedd->op.uimm0); - } -} - -void Op171(struct Machine *m, uint32_t rde) { - switch (ModrmReg(rde)) { - case 2: - OpPsb(m, rde, MmxPsrlw, SsePsrlw); - break; - case 4: - OpPsb(m, rde, MmxPsraw, SsePsraw); - break; - case 6: - OpPsb(m, rde, MmxPsllw, SsePsllw); - break; - default: - OpUd(m, rde); - } -} - -void Op172(struct Machine *m, uint32_t rde) { - switch (ModrmReg(rde)) { - case 2: - OpPsb(m, rde, MmxPsrld, SsePsrld); - break; - case 4: - OpPsb(m, rde, MmxPsrad, SsePsrad); - break; - case 6: - OpPsb(m, rde, MmxPslld, SsePslld); - break; - default: - OpUd(m, rde); - } -} - -void Op173(struct Machine *m, uint32_t rde) { - switch (ModrmReg(rde)) { - case 2: - OpPsb(m, rde, MmxPsrlq, SsePsrlq); - break; - case 3: - OpPsb(m, rde, MmxPsrldq, SsePsrldq); - break; - case 6: - OpPsb(m, rde, MmxPsllq, SsePsllq); - break; - case 7: - OpPsb(m, rde, MmxPslldq, SsePslldq); - break; - default: - OpUd(m, rde); - } -} - -void OpSsePalignr(struct Machine *m, uint32_t rde) { - if (Osz(rde)) { - SsePalignr(XmmRexrReg(m, rde), GetModrmRegisterXmmPointerRead16(m, rde), - m->xedd->op.uimm0); - } else { - MmxPalignr(XmmRexrReg(m, rde), GetModrmRegisterXmmPointerRead8(m, rde), - m->xedd->op.uimm0); - } -} - -static void OpSse(struct Machine *m, uint32_t rde, - void MmxKernel(uint8_t[8], const uint8_t[8]), - void SseKernel(uint8_t[16], const uint8_t[16])) { - if (Osz(rde)) { - SseKernel(XmmRexrReg(m, rde), GetModrmRegisterXmmPointerRead16(m, rde)); - } else { - MmxKernel(XmmRexrReg(m, rde), GetModrmRegisterXmmPointerRead8(m, rde)); - } -} - -/* clang-format off */ -void OpSsePunpcklbw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPunpcklbw, SsePunpcklbw); } -void OpSsePunpcklwd(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPunpcklwd, SsePunpcklwd); } -void OpSsePunpckldq(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPunpckldq, SsePunpckldq); } -void OpSsePacksswb(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPacksswb, SsePacksswb); } -void OpSsePcmpgtb(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPcmpgtb, SsePcmpgtb); } -void OpSsePcmpgtw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPcmpgtw, SsePcmpgtw); } -void OpSsePcmpgtd(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPcmpgtd, SsePcmpgtd); } -void OpSsePackuswb(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPackuswb, SsePackuswb); } -void OpSsePunpckhbw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPunpckhbw, SsePunpckhbw); } -void OpSsePunpckhwd(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPunpckhwd, SsePunpckhwd); } -void OpSsePunpckhdq(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPunpckhdq, SsePunpckhdq); } -void OpSsePackssdw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPackssdw, SsePackssdw); } -void OpSsePunpcklqdq(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPunpcklqdq, SsePunpcklqdq); } -void OpSsePunpckhqdq(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPunpckhqdq, SsePunpckhqdq); } -void OpSsePcmpeqb(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPcmpeqb, SsePcmpeqb); } -void OpSsePcmpeqw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPcmpeqw, SsePcmpeqw); } -void OpSsePcmpeqd(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPcmpeqd, SsePcmpeqd); } -void OpSsePsrlwv(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPsrlwv, SsePsrlwv); } -void OpSsePsrldv(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPsrldv, SsePsrldv); } -void OpSsePsrlqv(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPsrlqv, SsePsrlqv); } -void OpSsePaddq(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPaddq, SsePaddq); } -void OpSsePmullw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPmullw, SsePmullw); } -void OpSsePsubusb(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPsubusb, SsePsubusb); } -void OpSsePsubusw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPsubusw, SsePsubusw); } -void OpSsePminub(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPminub, SsePminub); } -void OpSsePand(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPand, SsePand); } -void OpSsePaddusb(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPaddusb, SsePaddusb); } -void OpSsePaddusw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPaddusw, SsePaddusw); } -void OpSsePmaxub(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPmaxub, SsePmaxub); } -void OpSsePandn(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPandn, SsePandn); } -void OpSsePavgb(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPavgb, SsePavgb); } -void OpSsePsrawv(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPsrawv, SsePsrawv); } -void OpSsePsradv(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPsradv, SsePsradv); } -void OpSsePavgw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPavgw, SsePavgw); } -void OpSsePmulhuw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPmulhuw, SsePmulhuw); } -void OpSsePmulhw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPmulhw, SsePmulhw); } -void OpSsePsubsb(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPsubsb, SsePsubsb); } -void OpSsePsubsw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPsubsw, SsePsubsw); } -void OpSsePminsw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPminsw, SsePminsw); } -void OpSsePor(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPor, SsePor); } -void OpSsePaddsb(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPaddsb, SsePaddsb); } -void OpSsePaddsw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPaddsw, SsePaddsw); } -void OpSsePmaxsw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPmaxsw, SsePmaxsw); } -void OpSsePxor(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPxor, SsePxor); } -void OpSsePsllwv(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPsllwv, SsePsllwv); } -void OpSsePslldv(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPslldv, SsePslldv); } -void OpSsePsllqv(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPsllqv, SsePsllqv); } -void OpSsePmuludq(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPmuludq, SsePmuludq); } -void OpSsePmaddwd(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPmaddwd, SsePmaddwd); } -void OpSsePsadbw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPsadbw, SsePsadbw); } -void OpSsePsubb(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPsubb, SsePsubb); } -void OpSsePsubw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPsubw, SsePsubw); } -void OpSsePsubd(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPsubd, SsePsubd); } -void OpSsePsubq(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPsubq, SsePsubq); } -void OpSsePaddb(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPaddb, SsePaddb); } -void OpSsePaddw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPaddw, SsePaddw); } -void OpSsePaddd(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPaddd, SsePaddd); } -void OpSsePshufb(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPshufb, SsePshufb); } -void OpSsePhaddw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPhaddw, SsePhaddw); } -void OpSsePhaddd(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPhaddd, SsePhaddd); } -void OpSsePhaddsw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPhaddsw, SsePhaddsw); } -void OpSsePmaddubsw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPmaddubsw, SsePmaddubsw); } -void OpSsePhsubw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPhsubw, SsePhsubw); } -void OpSsePhsubd(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPhsubd, SsePhsubd); } -void OpSsePhsubsw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPhsubsw, SsePhsubsw); } -void OpSsePsignb(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPsignb, SsePsignb); } -void OpSsePsignw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPsignw, SsePsignw); } -void OpSsePsignd(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPsignd, SsePsignd); } -void OpSsePmulhrsw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPmulhrsw, SsePmulhrsw); } -void OpSsePabsb(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPabsb, SsePabsb); } -void OpSsePabsw(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPabsw, SsePabsw); } -void OpSsePabsd(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPabsd, SsePabsd); } -void OpSsePmulld(struct Machine *m, uint32_t rde) { OpSse(m, rde, MmxPmulld, SsePmulld); } -/* clang-format on */ diff --git a/tool/build/lib/sse.h b/tool/build/lib/sse.h deleted file mode 100644 index 8361cdccc..000000000 --- a/tool/build/lib/sse.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_SSE_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_SSE_H_ -#include "tool/build/lib/machine.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -void Op171(struct Machine *, uint32_t); -void Op172(struct Machine *, uint32_t); -void Op173(struct Machine *, uint32_t); -void OpSsePabsb(struct Machine *, uint32_t); -void OpSsePabsd(struct Machine *, uint32_t); -void OpSsePabsw(struct Machine *, uint32_t); -void OpSsePackssdw(struct Machine *, uint32_t); -void OpSsePacksswb(struct Machine *, uint32_t); -void OpSsePackuswb(struct Machine *, uint32_t); -void OpSsePaddb(struct Machine *, uint32_t); -void OpSsePaddd(struct Machine *, uint32_t); -void OpSsePaddq(struct Machine *, uint32_t); -void OpSsePaddsb(struct Machine *, uint32_t); -void OpSsePaddsw(struct Machine *, uint32_t); -void OpSsePaddusb(struct Machine *, uint32_t); -void OpSsePaddusw(struct Machine *, uint32_t); -void OpSsePaddw(struct Machine *, uint32_t); -void OpSsePalignr(struct Machine *, uint32_t); -void OpSsePand(struct Machine *, uint32_t); -void OpSsePandn(struct Machine *, uint32_t); -void OpSsePavgb(struct Machine *, uint32_t); -void OpSsePavgw(struct Machine *, uint32_t); -void OpSsePcmpeqb(struct Machine *, uint32_t); -void OpSsePcmpeqd(struct Machine *, uint32_t); -void OpSsePcmpeqw(struct Machine *, uint32_t); -void OpSsePcmpgtb(struct Machine *, uint32_t); -void OpSsePcmpgtd(struct Machine *, uint32_t); -void OpSsePcmpgtw(struct Machine *, uint32_t); -void OpSsePhaddd(struct Machine *, uint32_t); -void OpSsePhaddsw(struct Machine *, uint32_t); -void OpSsePhaddw(struct Machine *, uint32_t); -void OpSsePhsubd(struct Machine *, uint32_t); -void OpSsePhsubsw(struct Machine *, uint32_t); -void OpSsePhsubw(struct Machine *, uint32_t); -void OpSsePmaddubsw(struct Machine *, uint32_t); -void OpSsePmaddwd(struct Machine *, uint32_t); -void OpSsePmaxsw(struct Machine *, uint32_t); -void OpSsePmaxub(struct Machine *, uint32_t); -void OpSsePminsw(struct Machine *, uint32_t); -void OpSsePminub(struct Machine *, uint32_t); -void OpSsePmulhrsw(struct Machine *, uint32_t); -void OpSsePmulhuw(struct Machine *, uint32_t); -void OpSsePmulhw(struct Machine *, uint32_t); -void OpSsePmulld(struct Machine *, uint32_t); -void OpSsePmullw(struct Machine *, uint32_t); -void OpSsePmuludq(struct Machine *, uint32_t); -void OpSsePor(struct Machine *, uint32_t); -void OpSsePsadbw(struct Machine *, uint32_t); -void OpSsePshufb(struct Machine *, uint32_t); -void OpSsePsignb(struct Machine *, uint32_t); -void OpSsePsignd(struct Machine *, uint32_t); -void OpSsePsignw(struct Machine *, uint32_t); -void OpSsePslldv(struct Machine *, uint32_t); -void OpSsePsllqv(struct Machine *, uint32_t); -void OpSsePsllwv(struct Machine *, uint32_t); -void OpSsePsradv(struct Machine *, uint32_t); -void OpSsePsrawv(struct Machine *, uint32_t); -void OpSsePsrldv(struct Machine *, uint32_t); -void OpSsePsrlqv(struct Machine *, uint32_t); -void OpSsePsrlwv(struct Machine *, uint32_t); -void OpSsePsubb(struct Machine *, uint32_t); -void OpSsePsubd(struct Machine *, uint32_t); -void OpSsePsubq(struct Machine *, uint32_t); -void OpSsePsubsb(struct Machine *, uint32_t); -void OpSsePsubsw(struct Machine *, uint32_t); -void OpSsePsubusb(struct Machine *, uint32_t); -void OpSsePsubusw(struct Machine *, uint32_t); -void OpSsePsubw(struct Machine *, uint32_t); -void OpSsePunpckhbw(struct Machine *, uint32_t); -void OpSsePunpckhdq(struct Machine *, uint32_t); -void OpSsePunpckhqdq(struct Machine *, uint32_t); -void OpSsePunpckhwd(struct Machine *, uint32_t); -void OpSsePunpcklbw(struct Machine *, uint32_t); -void OpSsePunpckldq(struct Machine *, uint32_t); -void OpSsePunpcklqdq(struct Machine *, uint32_t); -void OpSsePunpcklwd(struct Machine *, uint32_t); -void OpSsePxor(struct Machine *, uint32_t); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_SSE_H_ */ diff --git a/tool/build/lib/ssefloat.c b/tool/build/lib/ssefloat.c deleted file mode 100644 index 7a3bd59d5..000000000 --- a/tool/build/lib/ssefloat.c +++ /dev/null @@ -1,719 +0,0 @@ -/*-*- 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/macros.internal.h" -#include "libc/math.h" -#include "libc/str/str.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/flags.h" -#include "tool/build/lib/fpu.h" -#include "tool/build/lib/modrm.h" -#include "tool/build/lib/pun.h" -#include "tool/build/lib/ssefloat.h" -#include "tool/build/lib/throw.h" - -static void pshufw(int16_t b[4], const int16_t a[4], int m) { - int16_t t[4]; - t[0] = a[(m & 0003) >> 0]; - t[1] = a[(m & 0014) >> 2]; - t[2] = a[(m & 0060) >> 4]; - t[3] = a[(m & 0300) >> 6]; - b[0] = t[0]; - b[1] = t[1]; - b[2] = t[2]; - b[3] = t[3]; -} - -static void pshufd(int32_t b[4], const int32_t a[4], int m) { - int32_t t[4]; - t[0] = a[(m & 0003) >> 0]; - t[1] = a[(m & 0014) >> 2]; - t[2] = a[(m & 0060) >> 4]; - t[3] = a[(m & 0300) >> 6]; - b[0] = t[0]; - b[1] = t[1]; - b[2] = t[2]; - b[3] = t[3]; -} - -static void pshuflw(int16_t b[8], const int16_t a[8], int m) { - int16_t t[4]; - t[0] = a[(m & 0003) >> 0]; - t[1] = a[(m & 0014) >> 2]; - t[2] = a[(m & 0060) >> 4]; - t[3] = a[(m & 0300) >> 6]; - b[0] = t[0]; - b[1] = t[1]; - b[2] = t[2]; - b[3] = t[3]; - b[4] = a[4]; - b[5] = a[5]; - b[6] = a[6]; - b[7] = a[7]; -} - -static void pshufhw(int16_t b[8], const int16_t a[8], int m) { - int16_t t[4]; - t[0] = a[4 + ((m & 0003) >> 0)]; - t[1] = a[4 + ((m & 0014) >> 2)]; - t[2] = a[4 + ((m & 0060) >> 4)]; - t[3] = a[4 + ((m & 0300) >> 6)]; - b[0] = a[0]; - b[1] = a[1]; - b[2] = a[2]; - b[3] = a[3]; - b[4] = t[0]; - b[5] = t[1]; - b[6] = t[2]; - b[7] = t[3]; -} - -void OpUnpcklpsd(struct Machine *m, uint32_t rde) { - uint8_t *a, *b; - a = XmmRexrReg(m, rde); - b = GetModrmRegisterXmmPointerRead8(m, rde); - if (Osz(rde)) { - memcpy(a + 8, b, 8); - } else { - memcpy(a + 4 * 3, b + 4, 4); - memcpy(a + 4 * 2, a + 4, 4); - memcpy(a + 4 * 1, b + 0, 4); - } -} - -void OpUnpckhpsd(struct Machine *m, uint32_t rde) { - uint8_t *a, *b; - a = XmmRexrReg(m, rde); - b = GetModrmRegisterXmmPointerRead16(m, rde); - if (Osz(rde)) { - memcpy(a + 0, b + 8, 8); - memcpy(a + 8, b + 8, 8); - } else { - memcpy(a + 4 * 0, a + 4 * 2, 4); - memcpy(a + 4 * 1, b + 4 * 2, 4); - memcpy(a + 4 * 2, a + 4 * 3, 4); - memcpy(a + 4 * 3, b + 4 * 3, 4); - } -} - -void OpPextrwGdqpUdqIb(struct Machine *m, uint32_t rde) { - uint8_t i; - i = m->xedd->op.uimm0; - i &= Osz(rde) ? 7 : 3; - Write16(RegRexrReg(m, rde), Read16(XmmRexbRm(m, rde) + i * 2)); -} - -void OpPinsrwVdqEwIb(struct Machine *m, uint32_t rde) { - uint8_t i; - i = m->xedd->op.uimm0; - i &= Osz(rde) ? 7 : 3; - Write16(XmmRexrReg(m, rde) + i * 2, - Read16(GetModrmRegisterWordPointerRead2(m, rde))); -} - -void OpShuffle(struct Machine *m, uint32_t rde) { - int16_t q16[4]; - int16_t x16[8]; - int32_t x32[4]; - switch (Rep(rde) | Osz(rde)) { - case 0: - memcpy(q16, GetModrmRegisterXmmPointerRead8(m, rde), 8); - pshufw(q16, q16, m->xedd->op.uimm0); - memcpy(XmmRexrReg(m, rde), q16, 8); - break; - case 1: - memcpy(x32, GetModrmRegisterXmmPointerRead16(m, rde), 16); - pshufd(x32, x32, m->xedd->op.uimm0); - memcpy(XmmRexrReg(m, rde), x32, 16); - break; - case 2: - memcpy(x16, GetModrmRegisterXmmPointerRead16(m, rde), 16); - pshuflw(x16, x16, m->xedd->op.uimm0); - memcpy(XmmRexrReg(m, rde), x16, 16); - break; - case 3: - memcpy(x16, GetModrmRegisterXmmPointerRead16(m, rde), 16); - pshufhw(x16, x16, m->xedd->op.uimm0); - memcpy(XmmRexrReg(m, rde), x16, 16); - break; - default: - for (;;) (void)0; - } -} - -static void Shufps(struct Machine *m, uint32_t rde) { - uint8_t *p; - union FloatPun x[4], y[4], z[4]; - p = GetModrmRegisterXmmPointerRead16(m, rde); - y[0].i = Read32(p + 0 * 4); - y[1].i = Read32(p + 1 * 4); - y[2].i = Read32(p + 2 * 4); - y[3].i = Read32(p + 3 * 4); - p = XmmRexrReg(m, rde); - x[0].i = Read32(p + 0 * 4); - x[1].i = Read32(p + 1 * 4); - x[2].i = Read32(p + 2 * 4); - x[3].i = Read32(p + 3 * 4); - z[0].f = y[(m->xedd->op.uimm0 & 0003) >> 0].f; - z[1].f = y[(m->xedd->op.uimm0 & 0014) >> 2].f; - z[2].f = x[(m->xedd->op.uimm0 & 0060) >> 4].f; - z[3].f = x[(m->xedd->op.uimm0 & 0300) >> 6].f; - Write32(p + 0 * 4, z[0].i); - Write32(p + 1 * 4, z[1].i); - Write32(p + 2 * 4, z[2].i); - Write32(p + 3 * 4, z[3].i); -} - -static void Shufpd(struct Machine *m, uint32_t rde) { - uint8_t *p; - union DoublePun x[2], y[2], z[2]; - p = GetModrmRegisterXmmPointerRead16(m, rde); - y[0].i = Read64(p + 0 * 4); - y[1].i = Read64(p + 1 * 4); - p = XmmRexrReg(m, rde); - x[0].i = Read64(p + 0 * 4); - x[1].i = Read64(p + 1 * 4); - z[0].f = y[(m->xedd->op.uimm0 & 0001) >> 0].f; - z[1].f = x[(m->xedd->op.uimm0 & 0002) >> 1].f; - Write64(p + 0 * 4, z[0].i); - Write64(p + 1 * 4, z[1].i); -} - -void OpShufpsd(struct Machine *m, uint32_t rde) { - if (Osz(rde)) { - Shufpd(m, rde); - } else { - Shufps(m, rde); - } -} - -void OpSqrtpsd(struct Machine *m, uint32_t rde) { - switch (Rep(rde) | Osz(rde)) { - case 0: { - int i; - uint8_t *p; - union FloatPun u[4]; - p = GetModrmRegisterXmmPointerRead16(m, rde); - u[0].i = Read32(p + 0 * 4); - u[1].i = Read32(p + 1 * 4); - u[2].i = Read32(p + 2 * 4); - u[3].i = Read32(p + 3 * 4); - for (i = 0; i < 4; ++i) u[i].f = sqrtf(u[i].f); - p = XmmRexrReg(m, rde); - Write32(p + 0 * 4, u[0].i); - Write32(p + 1 * 4, u[1].i); - Write32(p + 2 * 4, u[2].i); - Write32(p + 3 * 4, u[3].i); - break; - } - case 1: { - int i; - uint8_t *p; - union DoublePun u[2]; - p = GetModrmRegisterXmmPointerRead16(m, rde); - u[0].i = Read32(p + 0 * 8); - u[1].i = Read32(p + 1 * 8); - for (i = 0; i < 2; ++i) u[i].f = sqrt(u[i].f); - p = XmmRexrReg(m, rde); - Write32(p + 0 * 8, u[0].i); - Write32(p + 1 * 8, u[1].i); - break; - } - case 2: { - union DoublePun u; - u.i = Read64(GetModrmRegisterXmmPointerRead8(m, rde)); - u.f = sqrt(u.f); - Write64(XmmRexrReg(m, rde), u.i); - break; - } - case 3: { - union FloatPun u; - u.i = Read32(GetModrmRegisterXmmPointerRead4(m, rde)); - u.f = sqrtf(u.f); - Write32(XmmRexrReg(m, rde), u.i); - break; - } - default: - for (;;) (void)0; - } -} - -void OpRsqrtps(struct Machine *m, uint32_t rde) { - if (Rep(rde) != 3) { - int i; - uint8_t *p; - union FloatPun u[4]; - p = GetModrmRegisterXmmPointerRead16(m, rde); - u[0].i = Read32(p + 0 * 4); - u[1].i = Read32(p + 1 * 4); - u[2].i = Read32(p + 2 * 4); - u[3].i = Read32(p + 3 * 4); - for (i = 0; i < 4; ++i) u[i].f = 1.f / sqrtf(u[i].f); - p = XmmRexrReg(m, rde); - Write32(p + 0 * 4, u[0].i); - Write32(p + 1 * 4, u[1].i); - Write32(p + 2 * 4, u[2].i); - Write32(p + 3 * 4, u[3].i); - } else { - union FloatPun u; - u.i = Read32(GetModrmRegisterXmmPointerRead4(m, rde)); - u.f = 1.f / sqrtf(u.f); - Write32(XmmRexrReg(m, rde), u.i); - } -} - -void OpRcpps(struct Machine *m, uint32_t rde) { - if (Rep(rde) != 3) { - int i; - uint8_t *p; - union FloatPun u[4]; - p = GetModrmRegisterXmmPointerRead16(m, rde); - u[0].i = Read32(p + 0 * 4); - u[1].i = Read32(p + 1 * 4); - u[2].i = Read32(p + 2 * 4); - u[3].i = Read32(p + 3 * 4); - for (i = 0; i < 4; ++i) u[i].f = 1.f / u[i].f; - p = XmmRexrReg(m, rde); - Write32(p + 0 * 4, u[0].i); - Write32(p + 1 * 4, u[1].i); - Write32(p + 2 * 4, u[2].i); - Write32(p + 3 * 4, u[3].i); - } else { - union FloatPun u; - u.i = Read32(GetModrmRegisterXmmPointerRead4(m, rde)); - u.f = 1.f / u.f; - Write32(XmmRexrReg(m, rde), u.i); - } -} - -void OpComissVsWs(struct Machine *m, uint32_t rde) { - uint8_t zf, cf, pf, ie; - if (!Osz(rde)) { - union FloatPun xf, yf; - xf.i = Read32(XmmRexrReg(m, rde)); - yf.i = Read32(GetModrmRegisterXmmPointerRead4(m, rde)); - if (!isnan(xf.f) && !isnan(yf.f)) { - zf = xf.f == yf.f; - cf = xf.f < yf.f; - pf = false; - ie = false; - } else { - zf = cf = pf = ie = true; - } - } else { - union DoublePun xd, yd; - xd.i = Read64(XmmRexrReg(m, rde)); - yd.i = Read64(GetModrmRegisterXmmPointerRead8(m, rde)); - if (!isnan(xd.f) && !isnan(yd.f)) { - zf = xd.f == yd.f; - cf = xd.f < yd.f; - pf = false; - ie = false; - } else { - zf = cf = pf = ie = true; - } - } - m->flags = SetFlag(m->flags, FLAGS_ZF, zf); - m->flags = SetFlag(m->flags, FLAGS_PF, pf); - m->flags = SetFlag(m->flags, FLAGS_CF, cf); - m->flags = SetFlag(m->flags, FLAGS_SF, false); - m->flags = SetFlag(m->flags, FLAGS_OF, false); - if (m->xedd->op.opcode & 1) { - m->mxcsr &= ~kMxcsrIe; - if (ie) { - m->mxcsr |= kMxcsrIe; - if (!(m->mxcsr & kMxcsrIm)) { - HaltMachine(m, kMachineSimdException); - } - } - } -} - -static inline void OpPsd(struct Machine *m, uint32_t rde, - float fs(float x, float y), - double fd(double x, double y)) { - if (Rep(rde) == 2) { - union DoublePun x, y; - y.i = Read64(GetModrmRegisterXmmPointerRead8(m, rde)); - x.i = Read64(XmmRexrReg(m, rde)); - x.f = fd(x.f, y.f); - Write64(XmmRexrReg(m, rde), x.i); - } else if (Rep(rde) == 3) { - union FloatPun x, y; - y.i = Read32(GetModrmRegisterXmmPointerRead4(m, rde)); - x.i = Read32(XmmRexrReg(m, rde)); - x.f = fs(x.f, y.f); - Write32(XmmRexrReg(m, rde), x.i); - } else if (Osz(rde)) { - uint8_t *p; - union DoublePun x[2], y[2]; - p = GetModrmRegisterXmmPointerRead16(m, rde); - y[0].i = Read64(p + 0 * 8); - y[1].i = Read64(p + 1 * 8); - p = XmmRexrReg(m, rde); - x[0].i = Read64(p + 0 * 8); - x[1].i = Read64(p + 1 * 8); - x[0].f = fd(x[0].f, y[0].f); - x[1].f = fd(x[1].f, y[1].f); - Write64(p + 0 * 8, x[0].i); - Write64(p + 1 * 8, x[1].i); - } else { - uint8_t *p; - union FloatPun x[4], y[4]; - p = GetModrmRegisterXmmPointerRead16(m, rde); - y[0].i = Read32(p + 0 * 4); - y[1].i = Read32(p + 1 * 4); - y[2].i = Read32(p + 2 * 4); - y[3].i = Read32(p + 3 * 4); - p = XmmRexrReg(m, rde); - x[0].i = Read32(p + 0 * 4); - x[1].i = Read32(p + 1 * 4); - x[2].i = Read32(p + 2 * 4); - x[3].i = Read32(p + 3 * 4); - x[0].f = fs(x[0].f, y[0].f); - x[1].f = fs(x[1].f, y[1].f); - x[2].f = fs(x[2].f, y[2].f); - x[3].f = fs(x[3].f, y[3].f); - Write32(p + 0 * 4, x[0].i); - Write32(p + 1 * 4, x[1].i); - Write32(p + 2 * 4, x[2].i); - Write32(p + 3 * 4, x[3].i); - } -} - -static inline float Adds(float x, float y) { - return x + y; -} - -static inline double Addd(double x, double y) { - return x + y; -} - -void OpAddpsd(struct Machine *m, uint32_t rde) { - OpPsd(m, rde, Adds, Addd); -} - -static inline float Subs(float x, float y) { - return x - y; -} - -static inline double Subd(double x, double y) { - return x - y; -} - -void OpSubpsd(struct Machine *m, uint32_t rde) { - OpPsd(m, rde, Subs, Subd); -} - -static inline float Muls(float x, float y) { - return x * y; -} - -static inline double Muld(double x, double y) { - return x * y; -} - -void OpMulpsd(struct Machine *m, uint32_t rde) { - OpPsd(m, rde, Muls, Muld); -} - -static inline float Divs(float x, float y) { - return x / y; -} - -static inline double Divd(double x, double y) { - return x / y; -} - -void OpDivpsd(struct Machine *m, uint32_t rde) { - OpPsd(m, rde, Divs, Divd); -} - -static inline float Mins(float x, float y) { - return MIN(x, y); -} - -static inline double Mind(double x, double y) { - return MIN(x, y); -} - -void OpMinpsd(struct Machine *m, uint32_t rde) { - OpPsd(m, rde, Mins, Mind); -} - -static inline float Maxs(float x, float y) { - return MAX(x, y); -} - -static inline double Maxd(double x, double y) { - return MAX(x, y); -} - -void OpMaxpsd(struct Machine *m, uint32_t rde) { - OpPsd(m, rde, Maxs, Maxd); -} - -static int Cmps(int imm, float x, float y) { - switch (imm) { - case 0: - return x == y ? -1 : 0; - case 1: - return x < y ? -1 : 0; - case 2: - return x <= y ? -1 : 0; - case 3: - return isnan(x) || isnan(y) ? -1 : 0; - case 4: - return x != y ? -1 : 0; - case 5: - return x >= y ? -1 : 0; - case 6: - return x > y ? -1 : 0; - case 7: - return !(isnan(x) || isnan(y)) ? -1 : 0; - default: - return 0; - } -} - -static int32_t Cmpd(int imm, double x, double y) { - switch (imm) { - case 0: - return x == y ? -1 : 0; - case 1: - return x < y ? -1 : 0; - case 2: - return x <= y ? -1 : 0; - case 3: - return isnan(x) || isnan(y) ? -1 : 0; - case 4: - return x != y ? -1 : 0; - case 5: - return x >= y ? -1 : 0; - case 6: - return x > y ? -1 : 0; - case 7: - return !(isnan(x) || isnan(y)) ? -1 : 0; - default: - return 0; - } -} - -void OpCmppsd(struct Machine *m, uint32_t rde) { - int imm = m->xedd->op.uimm0; - if (Rep(rde) == 2) { - union DoublePun x, y; - y.i = Read64(GetModrmRegisterXmmPointerRead8(m, rde)); - x.i = Read64(XmmRexrReg(m, rde)); - x.f = Cmpd(imm, x.f, y.f); - Write64(XmmRexrReg(m, rde), x.i); - } else if (Rep(rde) == 3) { - union FloatPun x, y; - y.i = Read32(GetModrmRegisterXmmPointerRead4(m, rde)); - x.i = Read32(XmmRexrReg(m, rde)); - x.f = Cmps(imm, x.f, y.f); - Write32(XmmRexrReg(m, rde), x.i); - } else if (Osz(rde)) { - uint8_t *p; - union DoublePun x[2], y[2]; - p = GetModrmRegisterXmmPointerRead16(m, rde); - y[0].i = Read64(p + 0 * 8); - y[1].i = Read64(p + 1 * 8); - p = XmmRexrReg(m, rde); - x[0].i = Read64(p + 0 * 8); - x[1].i = Read64(p + 1 * 8); - x[0].f = Cmpd(imm, x[0].f, y[0].f); - x[1].f = Cmpd(imm, x[1].f, y[1].f); - Write64(p + 0 * 8, x[0].i); - Write64(p + 1 * 8, x[1].i); - } else { - uint8_t *p; - union FloatPun x[4], y[4]; - p = GetModrmRegisterXmmPointerRead16(m, rde); - y[0].i = Read32(p + 0 * 4); - y[1].i = Read32(p + 1 * 4); - y[2].i = Read32(p + 2 * 4); - y[3].i = Read32(p + 3 * 4); - p = XmmRexrReg(m, rde); - x[0].i = Read32(p + 0 * 4); - x[1].i = Read32(p + 1 * 4); - x[2].i = Read32(p + 2 * 4); - x[3].i = Read32(p + 3 * 4); - x[0].f = Cmps(imm, x[0].f, y[0].f); - x[1].f = Cmps(imm, x[1].f, y[1].f); - x[2].f = Cmps(imm, x[2].f, y[2].f); - x[3].f = Cmps(imm, x[3].f, y[3].f); - Write32(p + 0 * 4, x[0].i); - Write32(p + 1 * 4, x[1].i); - Write32(p + 2 * 4, x[2].i); - Write32(p + 3 * 4, x[3].i); - } -} - -void OpAndpsd(struct Machine *m, uint32_t rde) { - uint64_t x[2], y[2]; - memcpy(x, XmmRexrReg(m, rde), 16); - memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16); - x[0] &= y[0]; - x[1] &= y[1]; - memcpy(XmmRexrReg(m, rde), x, 16); -} - -void OpAndnpsd(struct Machine *m, uint32_t rde) { - uint64_t x[2], y[2]; - memcpy(x, XmmRexrReg(m, rde), 16); - memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16); - x[0] = ~x[0] & y[0]; - x[1] = ~x[1] & y[1]; - memcpy(XmmRexrReg(m, rde), x, 16); -} - -void OpOrpsd(struct Machine *m, uint32_t rde) { - uint64_t x[2], y[2]; - memcpy(x, XmmRexrReg(m, rde), 16); - memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16); - x[0] |= y[0]; - x[1] |= y[1]; - memcpy(XmmRexrReg(m, rde), x, 16); -} - -void OpXorpsd(struct Machine *m, uint32_t rde) { - uint64_t x[2], y[2]; - memcpy(x, XmmRexrReg(m, rde), 16); - memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16); - x[0] ^= y[0]; - x[1] ^= y[1]; - memcpy(XmmRexrReg(m, rde), x, 16); -} - -void OpHaddpsd(struct Machine *m, uint32_t rde) { - uint8_t *p; - if (Rep(rde) == 2) { - union FloatPun x[4], y[4], z[4]; - p = GetModrmRegisterXmmPointerRead16(m, rde); - y[0].i = Read32(p + 0 * 4); - y[1].i = Read32(p + 1 * 4); - y[2].i = Read32(p + 2 * 4); - y[3].i = Read32(p + 3 * 4); - p = XmmRexrReg(m, rde); - x[0].i = Read32(p + 0 * 4); - x[1].i = Read32(p + 1 * 4); - x[2].i = Read32(p + 2 * 4); - x[3].i = Read32(p + 3 * 4); - z[0].f = x[0].f + x[1].f; - z[1].f = x[2].f + x[3].f; - z[2].f = y[0].f + y[1].f; - z[3].f = y[2].f + y[3].f; - Write32(p + 0 * 4, z[0].i); - Write32(p + 1 * 4, z[1].i); - Write32(p + 2 * 4, z[2].i); - Write32(p + 3 * 4, z[3].i); - } else if (Osz(rde)) { - union DoublePun x[2], y[2], z[2]; - p = GetModrmRegisterXmmPointerRead16(m, rde); - y[0].i = Read64(p + 0 * 8); - y[1].i = Read64(p + 1 * 8); - p = XmmRexrReg(m, rde); - x[0].i = Read64(p + 0 * 8); - x[1].i = Read64(p + 1 * 8); - z[0].f = x[0].f + x[1].f; - z[1].f = y[0].f + y[1].f; - Write64(p + 0 * 8, z[0].i); - Write64(p + 1 * 8, z[1].i); - } else { - OpUd(m, rde); - } -} - -void OpHsubpsd(struct Machine *m, uint32_t rde) { - uint8_t *p; - if (Rep(rde) == 2) { - union FloatPun x[4], y[4], z[4]; - p = GetModrmRegisterXmmPointerRead16(m, rde); - y[0].i = Read32(p + 0 * 4); - y[1].i = Read32(p + 1 * 4); - y[2].i = Read32(p + 2 * 4); - y[3].i = Read32(p + 3 * 4); - p = XmmRexrReg(m, rde); - x[0].i = Read32(p + 0 * 4); - x[1].i = Read32(p + 1 * 4); - x[2].i = Read32(p + 2 * 4); - x[3].i = Read32(p + 3 * 4); - z[0].f = x[0].f - x[1].f; - z[1].f = x[2].f - x[3].f; - z[2].f = y[0].f - y[1].f; - z[3].f = y[2].f - y[3].f; - Write32(p + 0 * 4, z[0].i); - Write32(p + 1 * 4, z[1].i); - Write32(p + 2 * 4, z[2].i); - Write32(p + 3 * 4, z[3].i); - } else if (Osz(rde)) { - union DoublePun x[2], y[2], z[2]; - p = GetModrmRegisterXmmPointerRead16(m, rde); - y[0].i = Read64(p + 0 * 8); - y[1].i = Read64(p + 1 * 8); - p = XmmRexrReg(m, rde); - x[0].i = Read64(p + 0 * 8); - x[1].i = Read64(p + 1 * 8); - z[0].f = x[0].f - x[1].f; - z[1].f = y[0].f - y[1].f; - Write64(p + 0 * 8, z[0].i); - Write64(p + 1 * 8, z[1].i); - } else { - OpUd(m, rde); - } -} - -void OpAddsubpsd(struct Machine *m, uint32_t rde) { - uint8_t *p; - if (Rep(rde) == 2) { - union FloatPun x[4], y[4], z[4]; - p = GetModrmRegisterXmmPointerRead16(m, rde); - y[0].i = Read32(p + 0 * 4); - y[1].i = Read32(p + 1 * 4); - y[2].i = Read32(p + 2 * 4); - y[3].i = Read32(p + 3 * 4); - p = XmmRexrReg(m, rde); - x[0].i = Read32(p + 0 * 4); - x[1].i = Read32(p + 1 * 4); - x[2].i = Read32(p + 2 * 4); - x[3].i = Read32(p + 3 * 4); - z[0].f = x[0].f - y[0].f; - z[1].f = x[1].f + y[1].f; - z[2].f = x[2].f - y[2].f; - z[3].f = x[3].f + y[3].f; - Write32(p + 0 * 4, z[0].i); - Write32(p + 1 * 4, z[1].i); - Write32(p + 2 * 4, z[2].i); - Write32(p + 3 * 4, z[3].i); - } else if (Osz(rde)) { - union DoublePun x[2], y[2], z[2]; - p = GetModrmRegisterXmmPointerRead16(m, rde); - y[0].i = Read64(p + 0 * 8); - y[1].i = Read64(p + 1 * 8); - p = XmmRexrReg(m, rde); - x[0].i = Read64(p + 0 * 8); - x[1].i = Read64(p + 1 * 8); - z[0].f = x[0].f - y[0].f; - z[1].f = x[1].f + y[1].f; - Write64(p + 0 * 8, z[0].i); - Write64(p + 1 * 8, z[1].i); - } else { - OpUd(m, rde); - } -} diff --git a/tool/build/lib/ssefloat.h b/tool/build/lib/ssefloat.h deleted file mode 100644 index 4471002a3..000000000 --- a/tool/build/lib/ssefloat.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_SSEFLOAT_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_SSEFLOAT_H_ -#include "tool/build/lib/machine.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -typedef float float_v _Vector_size(16) forcealign(16); -typedef double double_v _Vector_size(16) forcealign(16); - -void OpUnpcklpsd(struct Machine *, uint32_t); -void OpUnpckhpsd(struct Machine *, uint32_t); -void OpPextrwGdqpUdqIb(struct Machine *, uint32_t); -void OpPinsrwVdqEwIb(struct Machine *, uint32_t); -void OpShuffle(struct Machine *, uint32_t); -void OpShufpsd(struct Machine *, uint32_t); -void OpSqrtpsd(struct Machine *, uint32_t); -void OpRsqrtps(struct Machine *, uint32_t); -void OpRcpps(struct Machine *, uint32_t); -void OpComissVsWs(struct Machine *, uint32_t); -void OpAddpsd(struct Machine *, uint32_t); -void OpMulpsd(struct Machine *, uint32_t); -void OpSubpsd(struct Machine *, uint32_t); -void OpDivpsd(struct Machine *, uint32_t); -void OpMinpsd(struct Machine *, uint32_t); -void OpMaxpsd(struct Machine *, uint32_t); -void OpCmppsd(struct Machine *, uint32_t); -void OpAndpsd(struct Machine *, uint32_t); -void OpAndnpsd(struct Machine *, uint32_t); -void OpOrpsd(struct Machine *, uint32_t); -void OpXorpsd(struct Machine *, uint32_t); -void OpHaddpsd(struct Machine *, uint32_t); -void OpHsubpsd(struct Machine *, uint32_t); -void OpAddsubpsd(struct Machine *, uint32_t); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_SSEFLOAT_H_ */ diff --git a/tool/build/lib/ssemov.c b/tool/build/lib/ssemov.c deleted file mode 100644 index cf0b65148..000000000 --- a/tool/build/lib/ssemov.c +++ /dev/null @@ -1,518 +0,0 @@ -/*-*- 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 "tool/build/lib/ssemov.h" -#include "libc/intrin/pmovmskb.h" -#include "libc/str/str.h" -#include "tool/build/lib/address.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/memory.h" -#include "tool/build/lib/modrm.h" -#include "tool/build/lib/throw.h" - -static void MovdquVdqWdq(struct Machine *m, uint32_t rde) { - memcpy(XmmRexrReg(m, rde), GetModrmRegisterXmmPointerRead16(m, rde), 16); -} - -static void MovdquWdqVdq(struct Machine *m, uint32_t rde) { - memcpy(GetModrmRegisterXmmPointerWrite16(m, rde), XmmRexrReg(m, rde), 16); -} - -static void MovupsVpsWps(struct Machine *m, uint32_t rde) { - MovdquVdqWdq(m, rde); -} - -static void MovupsWpsVps(struct Machine *m, uint32_t rde) { - MovdquWdqVdq(m, rde); -} - -static void MovupdVpsWps(struct Machine *m, uint32_t rde) { - MovdquVdqWdq(m, rde); -} - -static void MovupdWpsVps(struct Machine *m, uint32_t rde) { - MovdquWdqVdq(m, rde); -} - -void OpLddquVdqMdq(struct Machine *m, uint32_t rde) { - MovdquVdqWdq(m, rde); -} - -void OpMovntiMdqpGdqp(struct Machine *m, uint32_t rde) { - if (Rexw(rde)) { - memcpy(ComputeReserveAddressWrite8(m, rde), XmmRexrReg(m, rde), 8); - } else { - memcpy(ComputeReserveAddressWrite4(m, rde), XmmRexrReg(m, rde), 4); - } -} - -static void MovdqaVdqMdq(struct Machine *m, uint32_t rde) { - int64_t v; - uint8_t *p; - v = ComputeAddress(m, rde); - SetReadAddr(m, v, 16); - if ((v & 15) || !(p = FindReal(m, v))) ThrowSegmentationFault(m, v); - memcpy(XmmRexrReg(m, rde), Abp16(p), 16); -} - -static void MovdqaMdqVdq(struct Machine *m, uint32_t rde) { - int64_t v; - uint8_t *p; - v = ComputeAddress(m, rde); - SetWriteAddr(m, v, 16); - if ((v & 15) || !(p = FindReal(m, v))) ThrowSegmentationFault(m, v); - memcpy(Abp16(p), XmmRexrReg(m, rde), 16); -} - -static void MovdqaVdqWdq(struct Machine *m, uint32_t rde) { - if (IsModrmRegister(rde)) { - memcpy(XmmRexrReg(m, rde), XmmRexbRm(m, rde), 16); - } else { - MovdqaVdqMdq(m, rde); - } -} - -static void MovdqaWdqVdq(struct Machine *m, uint32_t rde) { - if (IsModrmRegister(rde)) { - memcpy(XmmRexbRm(m, rde), XmmRexrReg(m, rde), 16); - } else { - MovdqaMdqVdq(m, rde); - } -} - -static void MovntdqMdqVdq(struct Machine *m, uint32_t rde) { - MovdqaMdqVdq(m, rde); -} - -static void MovntpsMpsVps(struct Machine *m, uint32_t rde) { - MovdqaMdqVdq(m, rde); -} - -static void MovntpdMpdVpd(struct Machine *m, uint32_t rde) { - MovdqaMdqVdq(m, rde); -} - -void OpMovntdqaVdqMdq(struct Machine *m, uint32_t rde) { - MovdqaVdqMdq(m, rde); -} - -static void MovqPqQq(struct Machine *m, uint32_t rde) { - memcpy(MmReg(m, rde), GetModrmRegisterMmPointerRead8(m, rde), 8); -} - -static void MovqQqPq(struct Machine *m, uint32_t rde) { - memcpy(GetModrmRegisterMmPointerWrite8(m, rde), MmReg(m, rde), 8); -} - -static void MovqVdqEqp(struct Machine *m, uint32_t rde) { - memcpy(XmmRexrReg(m, rde), GetModrmRegisterWordPointerRead8(m, rde), 8); - bzero(XmmRexrReg(m, rde) + 8, 8); -} - -static void MovdVdqEd(struct Machine *m, uint32_t rde) { - bzero(XmmRexrReg(m, rde), 16); - memcpy(XmmRexrReg(m, rde), GetModrmRegisterWordPointerRead4(m, rde), 4); -} - -static void MovqPqEqp(struct Machine *m, uint32_t rde) { - memcpy(MmReg(m, rde), GetModrmRegisterWordPointerRead8(m, rde), 8); -} - -static void MovdPqEd(struct Machine *m, uint32_t rde) { - memcpy(MmReg(m, rde), GetModrmRegisterWordPointerRead4(m, rde), 4); - bzero(MmReg(m, rde) + 4, 4); -} - -static void MovdEdVdq(struct Machine *m, uint32_t rde) { - if (IsModrmRegister(rde)) { - Write64(RegRexbRm(m, rde), Read32(XmmRexrReg(m, rde))); - } else { - memcpy(ComputeReserveAddressWrite4(m, rde), XmmRexrReg(m, rde), 4); - } -} - -static void MovqEqpVdq(struct Machine *m, uint32_t rde) { - memcpy(GetModrmRegisterWordPointerWrite8(m, rde), XmmRexrReg(m, rde), 8); -} - -static void MovdEdPq(struct Machine *m, uint32_t rde) { - if (IsModrmRegister(rde)) { - Write64(RegRexbRm(m, rde), Read32(MmReg(m, rde))); - } else { - memcpy(ComputeReserveAddressWrite4(m, rde), MmReg(m, rde), 4); - } -} - -static void MovqEqpPq(struct Machine *m, uint32_t rde) { - memcpy(GetModrmRegisterWordPointerWrite(m, rde, 8), MmReg(m, rde), 8); -} - -static void MovntqMqPq(struct Machine *m, uint32_t rde) { - memcpy(ComputeReserveAddressWrite8(m, rde), MmReg(m, rde), 8); -} - -static void MovqVqWq(struct Machine *m, uint32_t rde) { - memcpy(XmmRexrReg(m, rde), GetModrmRegisterXmmPointerRead8(m, rde), 8); - bzero(XmmRexrReg(m, rde) + 8, 8); -} - -static void MovssVpsWps(struct Machine *m, uint32_t rde) { - if (IsModrmRegister(rde)) { - memcpy(XmmRexrReg(m, rde), XmmRexbRm(m, rde), 4); - } else { - memcpy(XmmRexrReg(m, rde), ComputeReserveAddressRead4(m, rde), 4); - bzero(XmmRexrReg(m, rde) + 4, 12); - } -} - -static void MovssWpsVps(struct Machine *m, uint32_t rde) { - memcpy(GetModrmRegisterXmmPointerWrite4(m, rde), XmmRexrReg(m, rde), 4); -} - -static void MovsdVpsWps(struct Machine *m, uint32_t rde) { - if (IsModrmRegister(rde)) { - memcpy(XmmRexrReg(m, rde), XmmRexbRm(m, rde), 8); - } else { - memcpy(XmmRexrReg(m, rde), ComputeReserveAddressRead8(m, rde), 8); - bzero(XmmRexrReg(m, rde) + 8, 8); - } -} - -static void MovsdWpsVps(struct Machine *m, uint32_t rde) { - memcpy(GetModrmRegisterXmmPointerWrite8(m, rde), XmmRexrReg(m, rde), 8); -} - -static void MovhlpsVqUq(struct Machine *m, uint32_t rde) { - memcpy(XmmRexrReg(m, rde), XmmRexbRm(m, rde) + 8, 8); -} - -static void MovlpsVqMq(struct Machine *m, uint32_t rde) { - memcpy(XmmRexrReg(m, rde), ComputeReserveAddressRead8(m, rde), 8); -} - -static void MovlpdVqMq(struct Machine *m, uint32_t rde) { - memcpy(XmmRexrReg(m, rde), ComputeReserveAddressRead8(m, rde), 8); -} - -static void MovddupVqWq(struct Machine *m, uint32_t rde) { - uint8_t *src; - src = GetModrmRegisterXmmPointerRead8(m, rde); - memcpy(XmmRexrReg(m, rde) + 0, src, 8); - memcpy(XmmRexrReg(m, rde) + 8, src, 8); -} - -static void MovsldupVqWq(struct Machine *m, uint32_t rde) { - uint8_t *dst, *src; - dst = XmmRexrReg(m, rde); - src = GetModrmRegisterXmmPointerRead16(m, rde); - memcpy(dst + 0 + 0, src + 0, 4); - memcpy(dst + 0 + 4, src + 0, 4); - memcpy(dst + 8 + 0, src + 8, 4); - memcpy(dst + 8 + 4, src + 8, 4); -} - -static void MovlpsMqVq(struct Machine *m, uint32_t rde) { - memcpy(ComputeReserveAddressWrite8(m, rde), XmmRexrReg(m, rde), 8); -} - -static void MovlpdMqVq(struct Machine *m, uint32_t rde) { - memcpy(ComputeReserveAddressWrite8(m, rde), XmmRexrReg(m, rde), 8); -} - -static void MovlhpsVqUq(struct Machine *m, uint32_t rde) { - memcpy(XmmRexrReg(m, rde) + 8, XmmRexbRm(m, rde), 8); -} - -static void MovhpsVqMq(struct Machine *m, uint32_t rde) { - memcpy(XmmRexrReg(m, rde) + 8, ComputeReserveAddressRead8(m, rde), 8); -} - -static void MovhpdVqMq(struct Machine *m, uint32_t rde) { - memcpy(XmmRexrReg(m, rde) + 8, ComputeReserveAddressRead8(m, rde), 8); -} - -static void MovshdupVqWq(struct Machine *m, uint32_t rde) { - uint8_t *dst, *src; - dst = XmmRexrReg(m, rde); - src = GetModrmRegisterXmmPointerRead16(m, rde); - memcpy(dst + 0 + 0, src + 04, 4); - memcpy(dst + 0 + 4, src + 04, 4); - memcpy(dst + 8 + 0, src + 12, 4); - memcpy(dst + 8 + 4, src + 12, 4); -} - -static void MovhpsMqVq(struct Machine *m, uint32_t rde) { - memcpy(ComputeReserveAddressWrite8(m, rde), XmmRexrReg(m, rde) + 8, 8); -} - -static void MovhpdMqVq(struct Machine *m, uint32_t rde) { - memcpy(ComputeReserveAddressWrite8(m, rde), XmmRexrReg(m, rde) + 8, 8); -} - -static void MovqWqVq(struct Machine *m, uint32_t rde) { - if (IsModrmRegister(rde)) { - memcpy(XmmRexbRm(m, rde), XmmRexrReg(m, rde), 8); - bzero(XmmRexbRm(m, rde) + 8, 8); - } else { - memcpy(ComputeReserveAddressWrite8(m, rde), XmmRexrReg(m, rde), 8); - } -} - -static void Movq2dqVdqNq(struct Machine *m, uint32_t rde) { - memcpy(XmmRexrReg(m, rde), MmRm(m, rde), 8); - bzero(XmmRexrReg(m, rde) + 8, 8); -} - -static void Movdq2qPqUq(struct Machine *m, uint32_t rde) { - memcpy(MmReg(m, rde), XmmRexbRm(m, rde), 8); -} - -static void MovapsVpsWps(struct Machine *m, uint32_t rde) { - MovdqaVdqWdq(m, rde); -} - -static void MovapdVpdWpd(struct Machine *m, uint32_t rde) { - MovdqaVdqWdq(m, rde); -} - -static void MovapsWpsVps(struct Machine *m, uint32_t rde) { - MovdqaWdqVdq(m, rde); -} - -static void MovapdWpdVpd(struct Machine *m, uint32_t rde) { - MovdqaWdqVdq(m, rde); -} - -void OpMovWpsVps(struct Machine *m, uint32_t rde) { - uint8_t *p, *r; - switch (Rep(rde) | Osz(rde)) { - case 0: - MovupsWpsVps(m, rde); - break; - case 1: - MovupdWpsVps(m, rde); - break; - case 2: - MovsdWpsVps(m, rde); - break; - case 3: - MovssWpsVps(m, rde); - break; - default: - __builtin_unreachable(); - } -} - -void OpMov0f28(struct Machine *m, uint32_t rde) { - if (!Osz(rde)) { - MovapsVpsWps(m, rde); - } else { - MovapdVpdWpd(m, rde); - } -} - -void OpMov0f6e(struct Machine *m, uint32_t rde) { - if (Osz(rde)) { - if (Rexw(rde)) { - MovqVdqEqp(m, rde); - } else { - MovdVdqEd(m, rde); - } - } else { - if (Rexw(rde)) { - MovqPqEqp(m, rde); - } else { - MovdPqEd(m, rde); - } - } -} - -void OpMov0f6f(struct Machine *m, uint32_t rde) { - if (Osz(rde)) { - MovdqaVdqWdq(m, rde); - } else if (Rep(rde) == 3) { - MovdquVdqWdq(m, rde); - } else { - MovqPqQq(m, rde); - } -} - -void OpMov0fE7(struct Machine *m, uint32_t rde) { - if (!Osz(rde)) { - MovntqMqPq(m, rde); - } else { - MovntdqMdqVdq(m, rde); - } -} - -void OpMov0f7e(struct Machine *m, uint32_t rde) { - if (Rep(rde) == 3) { - MovqVqWq(m, rde); - } else if (Osz(rde)) { - if (Rexw(rde)) { - MovqEqpVdq(m, rde); - } else { - MovdEdVdq(m, rde); - } - } else { - if (Rexw(rde)) { - MovqEqpPq(m, rde); - } else { - MovdEdPq(m, rde); - } - } -} - -void OpMov0f7f(struct Machine *m, uint32_t rde) { - if (Rep(rde) == 3) { - MovdquWdqVdq(m, rde); - } else if (Osz(rde)) { - MovdqaWdqVdq(m, rde); - } else { - MovqQqPq(m, rde); - } -} - -void OpMov0f10(struct Machine *m, uint32_t rde) { - uint8_t *p, *r; - switch (Rep(rde) | Osz(rde)) { - case 0: - MovupsVpsWps(m, rde); - break; - case 1: - MovupdVpsWps(m, rde); - break; - case 2: - MovsdVpsWps(m, rde); - break; - case 3: - MovssVpsWps(m, rde); - break; - default: - __builtin_unreachable(); - } -} - -void OpMov0f29(struct Machine *m, uint32_t rde) { - if (!Osz(rde)) { - MovapsWpsVps(m, rde); - } else { - MovapdWpdVpd(m, rde); - } -} - -void OpMov0f2b(struct Machine *m, uint32_t rde) { - if (!Osz(rde)) { - MovntpsMpsVps(m, rde); - } else { - MovntpdMpdVpd(m, rde); - } -} - -void OpMov0f12(struct Machine *m, uint32_t rde) { - switch (Rep(rde) | Osz(rde)) { - case 0: - if (IsModrmRegister(rde)) { - MovhlpsVqUq(m, rde); - } else { - MovlpsVqMq(m, rde); - } - break; - case 1: - MovlpdVqMq(m, rde); - break; - case 2: - MovddupVqWq(m, rde); - break; - case 3: - MovsldupVqWq(m, rde); - break; - default: - __builtin_unreachable(); - } -} - -void OpMov0f13(struct Machine *m, uint32_t rde) { - if (Osz(rde)) { - MovlpdMqVq(m, rde); - } else { - MovlpsMqVq(m, rde); - } -} - -void OpMov0f16(struct Machine *m, uint32_t rde) { - switch (Rep(rde) | Osz(rde)) { - case 0: - if (IsModrmRegister(rde)) { - MovlhpsVqUq(m, rde); - } else { - MovhpsVqMq(m, rde); - } - break; - case 1: - MovhpdVqMq(m, rde); - break; - case 3: - MovshdupVqWq(m, rde); - break; - default: - OpUd(m, rde); - break; - } -} - -void OpMov0f17(struct Machine *m, uint32_t rde) { - if (Osz(rde)) { - MovhpdMqVq(m, rde); - } else { - MovhpsMqVq(m, rde); - } -} - -void OpMov0fD6(struct Machine *m, uint32_t rde) { - if (Rep(rde) == 3) { - Movq2dqVdqNq(m, rde); - } else if (Rep(rde) == 2) { - Movdq2qPqUq(m, rde); - } else if (Osz(rde)) { - MovqWqVq(m, rde); - } else { - OpUd(m, rde); - } -} - -void OpPmovmskbGdqpNqUdq(struct Machine *m, uint32_t rde) { - Write64(RegRexrReg(m, rde), - pmovmskb(XmmRexbRm(m, rde)) & (Osz(rde) ? 0xffff : 0xff)); -} - -void OpMaskMovDiXmmRegXmmRm(struct Machine *m, uint32_t rde) { - void *p[2]; - uint64_t v; - unsigned i, n; - uint8_t *mem, b[16]; - v = AddressDi(m, rde); - n = Osz(rde) ? 16 : 8; - mem = BeginStore(m, v, n, p, b); - for (i = 0; i < n; ++i) { - if (XmmRexbRm(m, rde)[i] & 0x80) { - mem[i] = XmmRexrReg(m, rde)[i]; - } - } - EndStore(m, v, n, p, b); -} diff --git a/tool/build/lib/ssemov.h b/tool/build/lib/ssemov.h deleted file mode 100644 index e8066f056..000000000 --- a/tool/build/lib/ssemov.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_SSEMOV_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_SSEMOV_H_ -#include "tool/build/lib/machine.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -void OpLddquVdqMdq(struct Machine *, uint32_t); -void OpMovntiMdqpGdqp(struct Machine *, uint32_t); -void OpPmovmskbGdqpNqUdq(struct Machine *, uint32_t); -void OpMaskMovDiXmmRegXmmRm(struct Machine *, uint32_t); -void OpMovntdqaVdqMdq(struct Machine *, uint32_t); -void OpMovWpsVps(struct Machine *, uint32_t); -void OpMov0f28(struct Machine *, uint32_t); -void OpMov0f6e(struct Machine *, uint32_t); -void OpMov0f6f(struct Machine *, uint32_t); -void OpMov0fE7(struct Machine *, uint32_t); -void OpMov0f7e(struct Machine *, uint32_t); -void OpMov0f7f(struct Machine *, uint32_t); -void OpMov0f10(struct Machine *, uint32_t); -void OpMov0f29(struct Machine *, uint32_t); -void OpMov0f2b(struct Machine *, uint32_t); -void OpMov0f12(struct Machine *, uint32_t); -void OpMov0f13(struct Machine *, uint32_t); -void OpMov0f16(struct Machine *, uint32_t); -void OpMov0f17(struct Machine *, uint32_t); -void OpMov0fD6(struct Machine *, uint32_t); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_SSEMOV_H_ */ diff --git a/tool/build/lib/stack.c b/tool/build/lib/stack.c deleted file mode 100644 index aa8572d5a..000000000 --- a/tool/build/lib/stack.c +++ /dev/null @@ -1,314 +0,0 @@ -/*-*- 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 "tool/build/lib/stack.h" -#include "libc/log/check.h" -#include "libc/macros.internal.h" -#include "libc/str/str.h" -#include "tool/build/lib/address.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/memory.h" -#include "tool/build/lib/modrm.h" -#include "tool/build/lib/throw.h" - -static const uint8_t kStackOsz[2][3] = { - [0][XED_MODE_REAL] = 2, [0][XED_MODE_LEGACY] = 4, [0][XED_MODE_LONG] = 8, - [1][XED_MODE_REAL] = 4, [1][XED_MODE_LEGACY] = 2, [1][XED_MODE_LONG] = 2, -}; - -static const uint8_t kCallOsz[2][3] = { - [0][XED_MODE_REAL] = 2, [0][XED_MODE_LEGACY] = 4, [0][XED_MODE_LONG] = 8, - [1][XED_MODE_REAL] = 4, [1][XED_MODE_LEGACY] = 2, [1][XED_MODE_LONG] = 8, -}; - -static void WriteStackWord(uint8_t *p, uint32_t rde, uint32_t osz, uint64_t x) { - if (osz == 8) { - Write64(p, x); - } else if (osz == 2) { - Write16(p, x); - } else { - Write32(p, x); - } -} - -static uint64_t ReadStackWord(uint8_t *p, uint32_t osz) { - if (osz == 8) { - return Read64(p); - } else if (osz == 2) { - return Read16(p); - } else { - return Read32(p); - } -} - -static void PushN(struct Machine *m, uint32_t rde, uint64_t x, unsigned osz) { - uint64_t v; - void *p[2]; - uint8_t b[8]; - switch (Eamode(rde)) { - case XED_MODE_REAL: - v = (Read32(m->sp) - osz) & 0xffff; - Write16(m->sp, v); - v += Read64(m->ss); - break; - case XED_MODE_LEGACY: - v = (Read32(m->sp) - osz) & 0xffffffff; - Write64(m->sp, v); - v += Read64(m->ss); - break; - case XED_MODE_LONG: - v = (Read64(m->sp) - osz) & 0xffffffffffffffff; - Write64(m->sp, v); - break; - default: - __builtin_unreachable(); - } - WriteStackWord(AccessRam(m, v, osz, p, b, false), rde, osz, x); - EndStore(m, v, osz, p, b); -} - -void Push(struct Machine *m, uint32_t rde, uint64_t x) { - PushN(m, rde, x, kStackOsz[m->xedd->op.osz][Mode(rde)]); -} - -void OpPushZvq(struct Machine *m, uint32_t rde) { - unsigned osz; - osz = kStackOsz[m->xedd->op.osz][Mode(rde)]; - PushN(m, rde, ReadStackWord(RegRexbSrm(m, rde), osz), osz); -} - -static uint64_t PopN(struct Machine *m, uint32_t rde, uint16_t extra, - unsigned osz) { - uint64_t v; - void *p[2]; - uint8_t b[8]; - switch (Eamode(rde)) { - case XED_MODE_LONG: - v = Read64(m->sp); - Write64(m->sp, v + osz + extra); - break; - case XED_MODE_LEGACY: - v = Read32(m->sp); - Write64(m->sp, (v + osz + extra) & 0xffffffff); - v += Read64(m->ss); - break; - case XED_MODE_REAL: - v = Read32(m->sp); - Write16(m->sp, v + osz + extra); - v += Read64(m->ss); - break; - default: - __builtin_unreachable(); - } - return ReadStackWord(AccessRam(m, v, osz, p, b, true), osz); -} - -uint64_t Pop(struct Machine *m, uint32_t rde, uint16_t extra) { - return PopN(m, rde, extra, kStackOsz[m->xedd->op.osz][Mode(rde)]); -} - -void OpPopZvq(struct Machine *m, uint32_t rde) { - uint64_t x; - unsigned osz; - osz = kStackOsz[m->xedd->op.osz][Mode(rde)]; - x = PopN(m, rde, 0, osz); - switch (osz) { - case 8: - case 4: - Write64(RegRexbSrm(m, rde), x); - break; - case 2: - Write16(RegRexbSrm(m, rde), x); - break; - default: - __builtin_unreachable(); - } -} - -static void OpCall(struct Machine *m, uint32_t rde, uint64_t func) { - if (!func) { - /* - * call null is technically possible but too fringe and disastrous - * to accommodate at least until our debugger has rewind capability - */ - HaltMachine(m, kMachineProtectionFault); - } - Push(m, rde, m->ip); - m->ip = func; -} - -void OpCallJvds(struct Machine *m, uint32_t rde) { - OpCall(m, rde, m->ip + m->xedd->op.disp); -} - -static uint64_t LoadAddressFromMemory(struct Machine *m, uint32_t rde) { - unsigned osz; - osz = kCallOsz[m->xedd->op.osz][Mode(rde)]; - return ReadStackWord(GetModrmRegisterWordPointerRead(m, rde, osz), osz); -} - -void OpCallEq(struct Machine *m, uint32_t rde) { - OpCall(m, rde, LoadAddressFromMemory(m, rde)); -} - -void OpJmpEq(struct Machine *m, uint32_t rde) { - m->ip = LoadAddressFromMemory(m, rde); -} - -void OpLeave(struct Machine *m, uint32_t rde) { - switch (Eamode(rde)) { - case XED_MODE_LONG: - Write64(m->sp, Read64(m->bp)); - Write64(m->bp, Pop(m, rde, 0)); - break; - case XED_MODE_LEGACY: - Write64(m->sp, Read32(m->bp)); - Write64(m->bp, Pop(m, rde, 0)); - break; - case XED_MODE_REAL: - Write16(m->sp, Read16(m->bp)); - Write16(m->bp, Pop(m, rde, 0)); - break; - default: - __builtin_unreachable(); - } -} - -void OpRet(struct Machine *m, uint32_t rde) { - m->ip = Pop(m, rde, m->xedd->op.uimm0); -} - -void OpPushEvq(struct Machine *m, uint32_t rde) { - unsigned osz; - osz = kStackOsz[m->xedd->op.osz][Mode(rde)]; - Push(m, rde, - ReadStackWord(GetModrmRegisterWordPointerRead(m, rde, osz), osz)); -} - -void OpPopEvq(struct Machine *m, uint32_t rde) { - unsigned osz; - osz = kStackOsz[m->xedd->op.osz][Mode(rde)]; - WriteStackWord(GetModrmRegisterWordPointerWrite(m, rde, osz), rde, osz, - Pop(m, rde, 0)); -} - -static relegated void Pushaw(struct Machine *m, uint32_t rde) { - uint16_t v; - uint8_t b[8][2]; - memcpy(b[0], m->di, 2); - memcpy(b[1], m->si, 2); - memcpy(b[2], m->bp, 2); - memcpy(b[3], m->sp, 2); - memcpy(b[4], m->bx, 2); - memcpy(b[5], m->dx, 2); - memcpy(b[6], m->cx, 2); - memcpy(b[7], m->ax, 2); - Write16(m->sp, (v = (Read16(m->sp) - sizeof(b)) & 0xffff)); - VirtualRecv(m, Read64(m->ss) + v, b, sizeof(b)); -} - -static relegated void Pushad(struct Machine *m, uint32_t rde) { - uint32_t v; - uint8_t b[8][4]; - memcpy(b[0], m->di, 4); - memcpy(b[1], m->si, 4); - memcpy(b[2], m->bp, 4); - memcpy(b[3], m->sp, 4); - memcpy(b[4], m->bx, 4); - memcpy(b[5], m->dx, 4); - memcpy(b[6], m->cx, 4); - memcpy(b[7], m->ax, 4); - Write64(m->sp, (v = (Read32(m->sp) - sizeof(b)) & 0xffffffff)); - VirtualRecv(m, Read64(m->ss) + v, b, sizeof(b)); -} - -static relegated void Popaw(struct Machine *m, uint32_t rde) { - uint8_t b[8][2]; - VirtualSend(m, b, Read64(m->ss) + Read16(m->sp), sizeof(b)); - Write16(m->sp, (Read32(m->sp) + sizeof(b)) & 0xffff); - memcpy(m->di, b[0], 2); - memcpy(m->si, b[1], 2); - memcpy(m->bp, b[2], 2); - memcpy(m->sp, b[3], 2); - memcpy(m->bx, b[4], 2); - memcpy(m->dx, b[5], 2); - memcpy(m->cx, b[6], 2); - memcpy(m->ax, b[7], 2); -} - -static relegated void Popad(struct Machine *m, uint32_t rde) { - uint8_t b[8][4]; - VirtualSend(m, b, Read64(m->ss) + Read32(m->sp), sizeof(b)); - Write64(m->sp, (Read32(m->sp) + sizeof(b)) & 0xffffffff); - memcpy(m->di, b[0], 4); - memcpy(m->si, b[1], 4); - memcpy(m->bp, b[2], 4); - memcpy(m->sp, b[3], 4); - memcpy(m->bx, b[4], 4); - memcpy(m->dx, b[5], 4); - memcpy(m->cx, b[6], 4); - memcpy(m->ax, b[7], 4); -} - -relegated void OpPusha(struct Machine *m, uint32_t rde) { - switch (Eamode(rde)) { - case XED_MODE_REAL: - Pushaw(m, rde); - break; - case XED_MODE_LEGACY: - Pushad(m, rde); - break; - case XED_MODE_LONG: - OpUd(m, rde); - default: - __builtin_unreachable(); - } -} - -relegated void OpPopa(struct Machine *m, uint32_t rde) { - switch (Eamode(rde)) { - case XED_MODE_REAL: - Popaw(m, rde); - break; - case XED_MODE_LEGACY: - Popad(m, rde); - break; - case XED_MODE_LONG: - OpUd(m, rde); - default: - __builtin_unreachable(); - } -} - -relegated void OpCallf(struct Machine *m, uint32_t rde) { - Push(m, rde, Read64(m->cs) >> 4); - Push(m, rde, m->ip); - Write64(m->cs, m->xedd->op.uimm0 << 4); - m->ip = m->xedd->op.disp & (Osz(rde) ? 0xffff : 0xffffffff); - if (m->onlongbranch) { - m->onlongbranch(m); - } -} - -relegated void OpRetf(struct Machine *m, uint32_t rde) { - m->ip = Pop(m, rde, 0); - Write64(m->cs, Pop(m, rde, m->xedd->op.uimm0) << 4); - if (m->onlongbranch) { - m->onlongbranch(m); - } -} diff --git a/tool/build/lib/stack.h b/tool/build/lib/stack.h deleted file mode 100644 index 76d94df45..000000000 --- a/tool/build/lib/stack.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_STACK_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_STACK_H_ -#include "tool/build/lib/machine.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -void Push(struct Machine *, uint32_t, uint64_t); -uint64_t Pop(struct Machine *, uint32_t, uint16_t); -void OpCallJvds(struct Machine *, uint32_t); -void OpRet(struct Machine *, uint32_t); -void OpRetf(struct Machine *, uint32_t); -void OpLeave(struct Machine *, uint32_t); -void OpCallEq(struct Machine *, uint32_t); -void OpPopEvq(struct Machine *, uint32_t); -void OpPopZvq(struct Machine *, uint32_t); -void OpPushZvq(struct Machine *, uint32_t); -void OpPushEvq(struct Machine *, uint32_t); -void PopVq(struct Machine *, uint32_t); -void PushVq(struct Machine *, uint32_t); -void OpJmpEq(struct Machine *, uint32_t); -void OpPusha(struct Machine *, uint32_t); -void OpPopa(struct Machine *, uint32_t); -void OpCallf(struct Machine *, uint32_t); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_STACK_H_ */ diff --git a/tool/build/lib/stats.c b/tool/build/lib/stats.c deleted file mode 100644 index 0acaf00f8..000000000 --- a/tool/build/lib/stats.c +++ /dev/null @@ -1,23 +0,0 @@ -/*-*- 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 "tool/build/lib/stats.h" - -unsigned long taken; -unsigned long ntaken; -unsigned long opcount; diff --git a/tool/build/lib/stats.h b/tool/build/lib/stats.h deleted file mode 100644 index 1f5c0819c..000000000 --- a/tool/build/lib/stats.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_STATS_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_STATS_H_ -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -extern unsigned long taken; -extern unsigned long ntaken; -extern unsigned long opcount; - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_STATS_H_ */ diff --git a/tool/build/lib/string.c b/tool/build/lib/string.c deleted file mode 100644 index cf847341c..000000000 --- a/tool/build/lib/string.c +++ /dev/null @@ -1,285 +0,0 @@ -/*-*- 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 "tool/build/lib/string.h" -#include "libc/assert.h" -#include "libc/log/log.h" -#include "libc/macros.internal.h" -#include "libc/runtime/runtime.h" -#include "libc/str/str.h" -#include "tool/build/lib/address.h" -#include "tool/build/lib/alu.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/flags.h" -#include "tool/build/lib/ioports.h" -#include "tool/build/lib/machine.h" -#include "tool/build/lib/memory.h" -#include "tool/build/lib/modrm.h" -#include "tool/build/lib/throw.h" - -static uint64_t ReadInt(uint8_t p[8], unsigned long w) { - switch (w) { - case 0: - return Read8(p); - case 1: - return Read16(p); - case 2: - return Read32(p); - case 3: - return Read64(p); - default: - __builtin_unreachable(); - } -} - -static void WriteInt(uint8_t p[8], uint64_t x, unsigned long w) { - switch (w) { - case 0: - Write8(p, x); - break; - case 1: - Write16(p, x); - break; - case 2: - Write64(p, x & 0xffffffff); - break; - case 3: - Write64(p, x); - break; - default: - __builtin_unreachable(); - } -} - -static void AddDi(struct Machine *m, uint32_t rde, uint64_t x) { - switch (Eamode(rde)) { - case XED_MODE_LONG: - Write64(m->di, Read64(m->di) + x); - return; - case XED_MODE_LEGACY: - Write64(m->di, (Read32(m->di) + x) & 0xffffffff); - return; - case XED_MODE_REAL: - Write16(m->di, Read16(m->di) + x); - return; - default: - __builtin_unreachable(); - } -} - -static void AddSi(struct Machine *m, uint32_t rde, uint64_t x) { - switch (Eamode(rde)) { - case XED_MODE_LONG: - Write64(m->si, Read64(m->si) + x); - return; - case XED_MODE_LEGACY: - Write64(m->si, (Read32(m->si) + x) & 0xffffffff); - return; - case XED_MODE_REAL: - Write16(m->si, Read16(m->si) + x); - return; - default: - __builtin_unreachable(); - } -} - -static uint64_t ReadCx(struct Machine *m, uint32_t rde) { - switch (Eamode(rde)) { - case XED_MODE_LONG: - return Read64(m->cx); - case XED_MODE_LEGACY: - return Read32(m->cx); - case XED_MODE_REAL: - return Read16(m->cx); - default: - __builtin_unreachable(); - } -} - -static uint64_t SubtractCx(struct Machine *m, uint32_t rde, uint64_t x) { - uint64_t cx; - cx = Read64(m->cx) - x; - if (Eamode(rde) != XED_MODE_REAL) { - if (Eamode(rde) == XED_MODE_LEGACY) { - cx &= 0xffffffff; - } - Write64(m->cx, cx); - } else { - cx &= 0xffff; - Write16(m->cx, cx); - } - return cx; -} - -static void StringOp(struct Machine *m, uint32_t rde, int op) { - bool stop; - void *p[2]; - unsigned n; - int64_t sgn, v; - uint8_t s[3][8]; - stop = false; - n = 1 << RegLog2(rde); - sgn = GetFlag(m->flags, FLAGS_DF) ? -1 : 1; - do { - if (Rep(rde) && !ReadCx(m, rde)) break; - switch (op) { - case STRING_CMPS: - kAlu[ALU_SUB][RegLog2(rde)]( - ReadInt(Load(m, AddressSi(m, rde), n, s[2]), RegLog2(rde)), - ReadInt(Load(m, AddressDi(m, rde), n, s[1]), RegLog2(rde)), - &m->flags); - AddDi(m, rde, sgn * n); - AddSi(m, rde, sgn * n); - stop = (Rep(rde) == 2 && GetFlag(m->flags, FLAGS_ZF)) || - (Rep(rde) == 3 && !GetFlag(m->flags, FLAGS_ZF)); - break; - case STRING_MOVS: - memcpy(BeginStore(m, (v = AddressDi(m, rde)), n, p, s[0]), - Load(m, AddressSi(m, rde), n, s[1]), n); - AddDi(m, rde, sgn * n); - AddSi(m, rde, sgn * n); - EndStore(m, v, n, p, s[0]); - break; - case STRING_STOS: - memcpy(BeginStore(m, (v = AddressDi(m, rde)), n, p, s[0]), m->ax, n); - AddDi(m, rde, sgn * n); - EndStore(m, v, n, p, s[0]); - break; - case STRING_LODS: - memcpy(m->ax, Load(m, AddressSi(m, rde), n, s[1]), n); - AddSi(m, rde, sgn * n); - break; - case STRING_SCAS: - kAlu[ALU_SUB][RegLog2(rde)]( - ReadInt(Load(m, AddressDi(m, rde), n, s[1]), RegLog2(rde)), - ReadInt(m->ax, RegLog2(rde)), &m->flags); - AddDi(m, rde, sgn * n); - stop = (Rep(rde) == 2 && GetFlag(m->flags, FLAGS_ZF)) || - (Rep(rde) == 3 && !GetFlag(m->flags, FLAGS_ZF)); - break; - case STRING_OUTS: - OpOut(m, Read16(m->dx), - ReadInt(Load(m, AddressSi(m, rde), n, s[1]), RegLog2(rde))); - AddSi(m, rde, sgn * n); - break; - case STRING_INS: - WriteInt(BeginStore(m, (v = AddressDi(m, rde)), n, p, s[0]), - OpIn(m, Read16(m->dx)), RegLog2(rde)); - AddDi(m, rde, sgn * n); - EndStore(m, v, n, p, s[0]); - break; - default: - abort(); - } - if (Rep(rde)) { - SubtractCx(m, rde, 1); - } else { - break; - } - } while (!stop); -} - -static void RepMovsbEnhanced(struct Machine *m, uint32_t rde) { - uint8_t *direal, *sireal; - uint64_t diactual, siactual, cx; - unsigned diremain, siremain, i, n; - if ((cx = ReadCx(m, rde))) { - do { - diactual = AddressDi(m, rde); - siactual = AddressSi(m, rde); - SetWriteAddr(m, diactual, cx); - SetReadAddr(m, siactual, cx); - direal = ResolveAddress(m, diactual); - sireal = ResolveAddress(m, siactual); - diremain = 0x1000 - (diactual & 0xfff); - siremain = 0x1000 - (siactual & 0xfff); - n = MIN(cx, MIN(diremain, siremain)); - if ((uintptr_t)direal <= (uintptr_t)sireal || - (uintptr_t)direal >= (uintptr_t)sireal + n) { - memcpy(direal, sireal, n); - } else { - for (i = 0; i < n; ++i) { - direal[i] = sireal[i]; - } - } - AddDi(m, rde, n); - AddSi(m, rde, n); - } while ((cx = SubtractCx(m, rde, n))); - } -} - -static void RepStosbEnhanced(struct Machine *m, uint32_t rde) { - uint8_t *direal; - unsigned diremain, n; - uint64_t divirtual, diactual, cx; - if ((cx = ReadCx(m, rde))) { - do { - diactual = AddressDi(m, rde); - SetWriteAddr(m, diactual, cx); - direal = ResolveAddress(m, diactual); - diremain = 0x1000 - (diactual & 0xfff); - n = MIN(cx, diremain); - memset(direal, Read8(m->ax), n); - AddDi(m, rde, n); - } while ((cx = SubtractCx(m, rde, n))); - } -} - -void OpMovs(struct Machine *m, uint32_t rde) { - StringOp(m, rde, STRING_MOVS); -} - -void OpCmps(struct Machine *m, uint32_t rde) { - StringOp(m, rde, STRING_CMPS); -} - -void OpStos(struct Machine *m, uint32_t rde) { - StringOp(m, rde, STRING_STOS); -} - -void OpLods(struct Machine *m, uint32_t rde) { - StringOp(m, rde, STRING_LODS); -} - -void OpScas(struct Machine *m, uint32_t rde) { - StringOp(m, rde, STRING_SCAS); -} - -void OpIns(struct Machine *m, uint32_t rde) { - StringOp(m, rde, STRING_INS); -} - -void OpOuts(struct Machine *m, uint32_t rde) { - StringOp(m, rde, STRING_OUTS); -} - -void OpMovsb(struct Machine *m, uint32_t rde) { - if (Rep(rde) && !GetFlag(m->flags, FLAGS_DF)) { - RepMovsbEnhanced(m, rde); - } else { - OpMovs(m, rde); - } -} - -void OpStosb(struct Machine *m, uint32_t rde) { - if (Rep(rde) && !GetFlag(m->flags, FLAGS_DF)) { - RepStosbEnhanced(m, rde); - } else { - OpStos(m, rde); - } -} diff --git a/tool/build/lib/string.h b/tool/build/lib/string.h deleted file mode 100644 index 0b2fff311..000000000 --- a/tool/build/lib/string.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_STRING_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_STRING_H_ -#include "tool/build/lib/machine.h" - -#define STRING_CMPS 0 -#define STRING_MOVS 1 -#define STRING_STOS 2 -#define STRING_LODS 3 -#define STRING_SCAS 4 -#define STRING_OUTS 5 -#define STRING_INS 6 - -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -void OpMovsb(struct Machine *, uint32_t); -void OpStosb(struct Machine *, uint32_t); -void OpMovs(struct Machine *, uint32_t); -void OpCmps(struct Machine *, uint32_t); -void OpStos(struct Machine *, uint32_t); -void OpLods(struct Machine *, uint32_t); -void OpScas(struct Machine *, uint32_t); -void OpIns(struct Machine *, uint32_t); -void OpOuts(struct Machine *, uint32_t); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_STRING_H_ */ diff --git a/tool/build/lib/syscall.c b/tool/build/lib/syscall.c deleted file mode 100644 index dd03ed94d..000000000 --- a/tool/build/lib/syscall.c +++ /dev/null @@ -1,1423 +0,0 @@ -/*-*- 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 "tool/build/lib/syscall.h" -#include "libc/calls/calls.h" -#include "libc/calls/internal.h" -#include "libc/calls/ioctl.h" -#include "libc/calls/sig.internal.h" -#include "libc/calls/struct/dirent.h" -#include "libc/calls/struct/iovec.h" -#include "libc/calls/struct/rlimit.h" -#include "libc/calls/struct/rusage.h" -#include "libc/calls/struct/sigaction.h" -#include "libc/calls/struct/stat.h" -#include "libc/calls/struct/sysinfo.h" -#include "libc/calls/struct/termios.h" -#include "libc/calls/struct/timespec.h" -#include "libc/calls/struct/timeval.h" -#include "libc/calls/struct/tms.h" -#include "libc/calls/struct/utsname.h" -#include "libc/calls/struct/winsize.h" -#include "libc/calls/weirdtypes.h" -#include "libc/errno.h" -#include "libc/fmt/fmt.h" -#include "libc/log/check.h" -#include "libc/log/log.h" -#include "libc/macros.internal.h" -#include "libc/mem/gc.internal.h" -#include "libc/mem/mem.h" -#include "libc/nexgen32e/vendor.internal.h" -#include "libc/runtime/pc.internal.h" -#include "libc/runtime/runtime.h" -#include "libc/sock/select.h" -#include "libc/sock/sock.h" -#include "libc/sock/struct/sockaddr.h" -#include "libc/stdckdint.h" -#include "libc/str/str.h" -#include "libc/sysv/consts/af.h" -#include "libc/sysv/consts/at.h" -#include "libc/sysv/consts/clock.h" -#include "libc/sysv/consts/f.h" -#include "libc/sysv/consts/fd.h" -#include "libc/sysv/consts/ipproto.h" -#include "libc/sysv/consts/lock.h" -#include "libc/sysv/consts/madv.h" -#include "libc/sysv/consts/map.h" -#include "libc/sysv/consts/msync.h" -#include "libc/sysv/consts/o.h" -#include "libc/sysv/consts/ok.h" -#include "libc/sysv/consts/poll.h" -#include "libc/sysv/consts/pr.h" -#include "libc/sysv/consts/prot.h" -#include "libc/sysv/consts/rusage.h" -#include "libc/sysv/consts/sa.h" -#include "libc/sysv/consts/sicode.h" -#include "libc/sysv/consts/sig.h" -#include "libc/sysv/consts/so.h" -#include "libc/sysv/consts/sock.h" -#include "libc/sysv/consts/sol.h" -#include "libc/sysv/consts/ss.h" -#include "libc/sysv/consts/tcp.h" -#include "libc/sysv/consts/termios.h" -#include "libc/sysv/consts/w.h" -#include "libc/sysv/errfuns.h" -#include "libc/time/struct/timezone.h" -#include "libc/time/struct/utimbuf.h" -#include "libc/time/time.h" -#include "libc/x/x.h" -#include "third_party/mbedtls/endian.h" -#include "tool/build/lib/bits.h" -#include "tool/build/lib/case.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/iovs.h" -#include "tool/build/lib/machine.h" -#include "tool/build/lib/memory.h" -#include "tool/build/lib/pml4t.h" -#include "tool/build/lib/signal.h" -#include "tool/build/lib/throw.h" -#include "tool/build/lib/xlat.h" - -#define TIOCGWINSZ_LINUX 0x5413 -#define TCGETS_LINUX 0x5401 -#define TCSETS_LINUX 0x5402 -#define TCSETSW_LINUX 0x5403 -#define TCSETSF_LINUX 0x5404 -#define ARCH_SET_GS_LINUX 0x1001 -#define ARCH_SET_FS_LINUX 0x1002 -#define ARCH_GET_FS_LINUX 0x1003 -#define ARCH_GET_GS_LINUX 0x1004 -#define SOCK_CLOEXEC_LINUX 0x080000 -#define O_CLOEXEC_LINUX 0x080000 -#define SA_RESTORER 0x04000000 -#define POLLIN_LINUX 0x01 -#define POLLPRI_LINUX 0x02 -#define POLLOUT_LINUX 0x04 -#define POLLERR_LINUX 0x08 -#define POLLHUP_LINUX 0x10 -#define POLLNVAL_LINUX 0x20 - -#define TIOCGWINSZ_LINUX 0x5413 -#define TCGETS_LINUX 0x5401 -#define TCSETS_LINUX 0x5402 -#define TCSETSW_LINUX 0x5403 -#define TCSETSF_LINUX 0x5404 -#define ISIG_LINUX 0b0000000000000001 -#define ICANON_LINUX 0b0000000000000010 -#define ECHO_LINUX 0b0000000000001000 -#define OPOST_LINUX 0b0000000000000001 - -#define POINTER(x) ((void *)(intptr_t)(x)) -#define UNPOINTER(x) ((int64_t)(intptr_t)(x)) -#define SYSCALL(x, y) CASE(x, asm("# " #y); ax = y) -#define XLAT(x, y) CASE(x, return y) -#define PNN(x) ResolveAddress(m, x) -#define P(x) ((x) ? PNN(x) : 0) -#define ASSIGN(D, S) memcpy(&D, &S, MIN(sizeof(S), sizeof(D))) - -const struct MachineFdCb kMachineFdCbHost = { - .close = close, - .readv = readv, - .poll = poll, - .writev = writev, - .ioctl = (void *)ioctl, -}; - -static int GetFd(struct Machine *m, int fd) { - if (!(0 <= fd && fd < m->fds.i)) return ebadf(); - if (!m->fds.p[fd].cb) return ebadf(); - return m->fds.p[fd].fd; -} - -static int GetAfd(struct Machine *m, int fd) { - if (fd == -100) return AT_FDCWD; - return GetFd(m, fd); -} - -static const char *GetSimulated(void) { - if (IsGenuineBlink()) { - return " SIMULATED"; - } else { - return ""; - } -} - -static int AppendIovsReal(struct Machine *m, struct Iovs *ib, int64_t addr, - size_t size) { - void *real; - size_t have; - unsigned got; - while (size) { - if (!(real = FindReal(m, addr))) return efault(); - have = 0x1000 - (addr & 0xfff); - got = MIN(size, have); - if (AppendIovs(ib, real, got) == -1) return -1; - addr += got; - size -= got; - } - return 0; -} - -static int AppendIovsGuest(struct Machine *m, struct Iovs *iv, int64_t iovaddr, - long iovlen) { - int rc; - size_t i, iovsize; - struct iovec *guestiovs; - if (!ckd_mul(&iovsize, iovlen, sizeof(struct iovec)) && - (0 <= iovsize && iovsize <= 0x7ffff000)) { - if ((guestiovs = malloc(iovsize))) { - VirtualSendRead(m, guestiovs, iovaddr, iovsize); - for (rc = i = 0; i < iovlen; ++i) { - if (AppendIovsReal(m, iv, (intptr_t)guestiovs[i].iov_base, - guestiovs[i].iov_len) == -1) { - rc = -1; - break; - } - } - free(guestiovs); - } else { - rc = enomem(); - } - } else { - rc = eoverflow(); - } - return rc; -} - -static int OpPrctl(struct Machine *m, int op, int64_t a, int64_t b, int64_t c, - int64_t d) { - return einval(); -} - -static int OpArchPrctl(struct Machine *m, int code, int64_t addr) { - switch (code) { - case ARCH_SET_GS: - Write64(m->gs, addr); - return 0; - case ARCH_SET_FS: - Write64(m->fs, addr); - return 0; - case ARCH_GET_GS: - VirtualRecvWrite(m, addr, m->gs, 8); - return 0; - case ARCH_GET_FS: - VirtualRecvWrite(m, addr, m->fs, 8); - return 0; - default: - return einval(); - } -} - -static int OpMprotect(struct Machine *m, int64_t addr, uint64_t len, int prot) { - return 0; -} - -static int OpMadvise(struct Machine *m, int64_t addr, size_t length, - int advice) { - return enosys(); -} - -static int64_t OpBrk(struct Machine *m, int64_t addr) { - addr = ROUNDUP(addr, PAGESIZE); - if (addr > m->brk) { - if (ReserveVirtual(m, m->brk, addr - m->brk, - PAGE_V | PAGE_RW | PAGE_U | PAGE_RSRV) != -1) { - m->brk = addr; - } - } else if (addr < m->brk) { - if (FreeVirtual(m, addr, m->brk - addr) != -1) { - m->brk = addr; - } - } - return m->brk; -} - -static int OpMunmap(struct Machine *m, int64_t virt, uint64_t size) { - VERBOSEF("MUNMAP%s %012lx %,ld", GetSimulated(), virt, size); - return FreeVirtual(m, virt, size); -} - -static int64_t OpMmap(struct Machine *m, int64_t virt, size_t size, int prot, - int flags, int fd, int64_t offset) { - int e; - void *tmp; - ssize_t rc; - uint64_t key; - bool recoverable; - VERBOSEF("MMAP%s %012lx %,ld %#x %#x %d %#lx", GetSimulated(), virt, size, - prot, flags, fd, offset); - if (prot & PROT_READ) { - key = PAGE_RSRV | PAGE_U | PAGE_V; - if (prot & PROT_WRITE) key |= PAGE_RW; - if (!(prot & PROT_EXEC)) key |= PAGE_XD; - if (flags & 256 /* MAP_GROWSDOWN */) key |= PAGE_GROD; - flags = XlatMapFlags(flags); - if (fd != -1 && (fd = GetFd(m, fd)) == -1) return -1; - if (flags & MAP_FIXED) { - recoverable = false; - } else { - recoverable = true; - if (!virt) { - if ((virt = FindVirtual(m, m->brk, size)) == -1) return -1; - m->brk = virt + size; - } else { - if ((virt = FindVirtual(m, virt, size)) == -1) return -1; - } - } - if (ReserveVirtual(m, virt, size, key) != -1) { - if (fd != -1 && !(flags & MAP_ANONYMOUS)) { - // TODO: lazy file mappings - CHECK_NOTNULL((tmp = malloc(size))); - for (e = errno;;) { - rc = pread(fd, tmp, size, offset); - if (rc != -1) break; - CHECK_EQ(EINTR, errno); - errno = e; - } - CHECK_EQ(size, rc); - VirtualRecvWrite(m, virt, tmp, size); - free(tmp); - } - return virt; - } else if (recoverable) { - FreeVirtual(m, virt, size); - return -1; - } else { - FATALF("unrecoverable oom with mmap(MAP_FIXED)"); - } - } else { - return FreeVirtual(m, virt, size); - } -} - -static int OpMsync(struct Machine *m, int64_t virt, size_t size, int flags) { - return enosys(); -#if 0 - size_t i; - void *page; - virt = ROUNDDOWN(virt, 4096); - flags = XlatMsyncFlags(flags); - for (i = 0; i < size; i += 4096) { - if (!(page = FindReal(m, virt + i))) return efault(); - if (msync(page, 4096, flags) == -1) return -1; - } - return 0; -#endif -} - -static int OpClose(struct Machine *m, int fd) { - int rc; - struct FdClosed *closed; - if (!(0 <= fd && fd < m->fds.i)) return ebadf(); - if (!m->fds.p[fd].cb) return ebadf(); - rc = m->fds.p[fd].cb->close(m->fds.p[fd].fd); - MachineFdRemove(&m->fds, fd); - return rc; -} - -static int OpOpenat(struct Machine *m, int dirfd, int64_t pathaddr, int flags, - int mode) { - int fd, i; - const char *path; - flags = XlatOpenFlags(flags); - if ((dirfd = GetAfd(m, dirfd)) == -1) return -1; - if ((i = MachineFdAdd(&m->fds)) == -1) return -1; - path = LoadStr(m, pathaddr); - if ((fd = openat(dirfd, path, flags, mode)) != -1) { - m->fds.p[i].cb = &kMachineFdCbHost; - m->fds.p[i].fd = fd; - VERBOSEF("openat(%#x, %`'s, %#x, %#x) → %d [%d]", dirfd, path, flags, mode, - i, fd); - fd = i; - } else { - MachineFdRemove(&m->fds, i); - VERBOSEF("openat(%#x, %`'s, %#x, %#x) failed", dirfd, path, flags, mode); - } - return fd; -} - -static int OpPipe(struct Machine *m, int64_t pipefds_addr) { - int i, j, pipefds[2]; - if ((i = MachineFdAdd(&m->fds)) != -1) { - if ((j = MachineFdAdd(&m->fds)) != -1) { - if (pipe(pipefds) != -1) { - m->fds.p[i].cb = &kMachineFdCbHost; - m->fds.p[i].fd = pipefds[0]; - m->fds.p[j].cb = &kMachineFdCbHost; - m->fds.p[j].fd = pipefds[1]; - pipefds[0] = i; - pipefds[1] = j; - VirtualRecvWrite(m, pipefds_addr, pipefds, sizeof(pipefds)); - return 0; - } - MachineFdRemove(&m->fds, j); - } - MachineFdRemove(&m->fds, i); - } - return -1; -} - -static int OpDup(struct Machine *m, int fd) { - int i; - if ((fd = GetFd(m, fd)) != -1) { - if ((i = MachineFdAdd(&m->fds)) != -1) { - if ((fd = dup(fd)) != -1) { - m->fds.p[i].cb = &kMachineFdCbHost; - m->fds.p[i].fd = fd; - return i; - } - MachineFdRemove(&m->fds, i); - } - } - return -1; -} - -static int OpDup2(struct Machine *m, int fd, int newfd) { - int i, rc; - if ((fd = GetFd(m, fd)) == -1) return -1; - if ((0 <= newfd && newfd < m->fds.i)) { - if ((rc = dup2(fd, m->fds.p[newfd].fd)) != -1) { - m->fds.p[newfd].cb = &kMachineFdCbHost; - m->fds.p[newfd].fd = rc; - rc = newfd; - } - } else if ((i = MachineFdAdd(&m->fds)) != -1) { - if ((rc = dup(fd)) != -1) { - m->fds.p[i].cb = &kMachineFdCbHost; - m->fds.p[i].fd = rc; - rc = i; - } - } else { - rc = -1; - } - return rc; -} - -static int OpDup3(struct Machine *m, int fd, int newfd, int flags) { - int i, rc; - if (!(flags & ~O_CLOEXEC_LINUX)) { - if ((fd = GetFd(m, fd)) == -1) return -1; - if ((0 <= newfd && newfd < m->fds.i)) { - if ((rc = dup2(fd, m->fds.p[newfd].fd)) != -1) { - if (flags & O_CLOEXEC_LINUX) { - fcntl(rc, F_SETFD, FD_CLOEXEC); - } - m->fds.p[newfd].cb = &kMachineFdCbHost; - m->fds.p[newfd].fd = rc; - rc = newfd; - } - } else if ((i = MachineFdAdd(&m->fds)) != -1) { - if ((rc = dup(fd)) != -1) { - m->fds.p[i].cb = &kMachineFdCbHost; - m->fds.p[i].fd = rc; - rc = i; - } - } else { - rc = -1; - } - return rc; - } else { - return einval(); - } -} - -static int OpSocket(struct Machine *m, int family, int type, int protocol) { - int i, fd; - if ((family = XlatSocketFamily(family)) == -1) return -1; - if ((type = XlatSocketType(type)) == -1) return -1; - if ((protocol = XlatSocketProtocol(protocol)) == -1) return -1; - if ((i = MachineFdAdd(&m->fds)) == -1) return -1; - if ((fd = socket(family, type, protocol)) != -1) { - m->fds.p[i].cb = &kMachineFdCbHost; - m->fds.p[i].fd = fd; - fd = i; - } else { - MachineFdRemove(&m->fds, i); - } - return fd; -} - -static int OpAccept4(struct Machine *m, int fd, int64_t aa, int64_t asa, - int flags) { - int i, rc; - uint32_t addrsize; - uint8_t gaddrsize[4]; - struct sockaddr_in addr; - struct sockaddr_in_bits gaddr; - if (!(flags & ~SOCK_CLOEXEC_LINUX)) { - if ((fd = GetFd(m, fd)) == -1) return -1; - if (aa) { - VirtualSendRead(m, gaddrsize, asa, sizeof(gaddrsize)); - if (Read32(gaddrsize) < sizeof(gaddr)) return einval(); - } - if ((i = rc = MachineFdAdd(&m->fds)) != -1) { - addrsize = sizeof(addr); - if ((rc = accept(fd, (struct sockaddr *)&addr, &addrsize)) != -1) { - if (flags & SOCK_CLOEXEC_LINUX) { - fcntl(fd, F_SETFD, FD_CLOEXEC); - } - if (aa) { - Write32(gaddrsize, sizeof(gaddr)); - XlatSockaddrToLinux(&gaddr, &addr); - VirtualRecv(m, asa, gaddrsize, sizeof(gaddrsize)); - VirtualRecvWrite(m, aa, &gaddr, sizeof(gaddr)); - } - m->fds.p[i].cb = &kMachineFdCbHost; - m->fds.p[i].fd = rc; - rc = i; - } else { - MachineFdRemove(&m->fds, i); - } - } - return rc; - } else { - return einval(); - } -} - -static int OpConnectBind(struct Machine *m, int fd, int64_t aa, uint32_t as, - int impl(int, const struct sockaddr *, uint32_t)) { - struct sockaddr_in addr; - struct sockaddr_in_bits gaddr; - if (as != sizeof(gaddr)) return einval(); - if ((fd = GetFd(m, fd)) == -1) return -1; - VirtualSendRead(m, &gaddr, aa, sizeof(gaddr)); - XlatSockaddrToHost(&addr, &gaddr); - return impl(fd, (const struct sockaddr *)&addr, sizeof(addr)); -} - -static int OpBind(struct Machine *m, int fd, int64_t aa, uint32_t as) { - return OpConnectBind(m, fd, aa, as, bind); -} - -static int OpConnect(struct Machine *m, int fd, int64_t aa, uint32_t as) { - return OpConnectBind(m, fd, aa, as, connect); -} - -static int OpSetsockopt(struct Machine *m, int fd, int level, int optname, - int64_t optvaladdr, uint32_t optvalsize) { - int rc; - void *optval; - if ((level = XlatSocketLevel(level)) == -1) return -1; - if ((optname = XlatSocketOptname(level, optname)) == -1) return -1; - if ((fd = GetFd(m, fd)) == -1) return -1; - if (!(optval = malloc(optvalsize))) return -1; - VirtualSendRead(m, optval, optvaladdr, optvalsize); - rc = setsockopt(fd, level, optname, optval, optvalsize); - free(optval); - return rc; -} - -static int OpGetsockopt(struct Machine *m, int fd, int level, int optname, - int64_t optvaladdr, int64_t optsizeaddr) { - int rc; - void *optval; - uint32_t optsize; - if ((level = XlatSocketLevel(level)) == -1) return -1; - if ((optname = XlatSocketOptname(level, optname)) == -1) return -1; - if ((fd = GetFd(m, fd)) == -1) return -1; - if (!optvaladdr) { - rc = getsockopt(fd, level, optname, 0, 0); - } else { - VirtualSendRead(m, &optsize, optsizeaddr, sizeof(optsize)); - if (!(optval = malloc(optsize))) return -1; - if ((rc = getsockopt(fd, level, optname, optval, &optsize)) != -1) { - VirtualRecvWrite(m, optvaladdr, optval, optsize); - VirtualRecvWrite(m, optsizeaddr, &optsize, sizeof(optsize)); - } - free(optval); - } - return rc; -} - -static int OpSocketName(struct Machine *m, int fd, int64_t aa, int64_t asa, - int SocketName(int, struct sockaddr *, socklen_t *)) { - int rc; - uint32_t addrsize; - uint8_t gaddrsize[4]; - struct sockaddr_in addr; - struct sockaddr_in_bits gaddr; - if ((fd = GetFd(m, fd)) == -1) return -1; - VirtualSendRead(m, gaddrsize, asa, sizeof(gaddrsize)); - if (Read32(gaddrsize) < sizeof(gaddr)) return einval(); - addrsize = sizeof(addr); - if ((rc = SocketName(fd, (struct sockaddr *)&addr, &addrsize)) != -1) { - Write32(gaddrsize, sizeof(gaddr)); - XlatSockaddrToLinux(&gaddr, &addr); - VirtualRecv(m, asa, gaddrsize, sizeof(gaddrsize)); - VirtualRecvWrite(m, aa, &gaddr, sizeof(gaddr)); - } - return rc; -} - -static int OpGetsockname(struct Machine *m, int fd, int64_t aa, int64_t asa) { - return OpSocketName(m, fd, aa, asa, getsockname); -} - -static int OpGetpeername(struct Machine *m, int fd, int64_t aa, int64_t asa) { - return OpSocketName(m, fd, aa, asa, getpeername); -} - -static ssize_t OpRead(struct Machine *m, int fd, int64_t addr, size_t size) { - ssize_t rc; - struct Iovs iv; - InitIovs(&iv); - if ((0 <= fd && fd < m->fds.i) && m->fds.p[fd].cb) { - if ((rc = AppendIovsReal(m, &iv, addr, size)) != -1) { - if ((rc = m->fds.p[fd].cb->readv(m->fds.p[fd].fd, iv.p, iv.i)) != -1) { - SetWriteAddr(m, addr, rc); - } - } - } else { - rc = ebadf(); - } - FreeIovs(&iv); - return rc; -} - -static int OpGetdents(struct Machine *m, int dirfd, int64_t addr, - uint32_t size) { - int rc; - DIR *dir; - struct dirent *ent; - if (size < sizeof(struct dirent)) return einval(); - if (0 <= dirfd && dirfd < m->fds.i) { - if ((dir = fdopendir(m->fds.p[dirfd].fd))) { - rc = 0; - while (rc + sizeof(struct dirent) <= size) { - if (!(ent = readdir(dir))) break; - VirtualRecvWrite(m, addr + rc, ent, ent->d_reclen); - rc += ent->d_reclen; - } - free(dir); - } else { - rc = -1; - } - } else { - rc = ebadf(); - } - return rc; -} - -static ssize_t OpPread(struct Machine *m, int fd, int64_t addr, size_t size, - int64_t offset) { - ssize_t rc; - struct Iovs iv; - InitIovs(&iv); - if ((rc = GetFd(m, fd)) != -1) { - fd = rc; - if ((rc = AppendIovsReal(m, &iv, addr, size)) != -1) { - if ((rc = preadv(fd, iv.p, iv.i, offset)) != -1) { - SetWriteAddr(m, addr, rc); - } - } - } - FreeIovs(&iv); - return rc; -} - -static ssize_t OpWrite(struct Machine *m, int fd, int64_t addr, size_t size) { - ssize_t rc; - struct Iovs iv; - InitIovs(&iv); - if ((0 <= fd && fd < m->fds.i) && m->fds.p[fd].cb) { - if ((rc = AppendIovsReal(m, &iv, addr, size)) != -1) { - if ((rc = m->fds.p[fd].cb->writev(m->fds.p[fd].fd, iv.p, iv.i)) != -1) { - SetReadAddr(m, addr, rc); - } else { - VERBOSEF("write(%d [%d], %012lx, %zu) failed: %s", fd, m->fds.p[fd].fd, - addr, size, strerror(errno)); - } - } - } else { - VERBOSEF("write(%d, %012lx, %zu) bad fd", fd, addr, size); - rc = ebadf(); - } - FreeIovs(&iv); - return rc; -} - -static ssize_t OpPwrite(struct Machine *m, int fd, int64_t addr, size_t size, - int64_t offset) { - ssize_t rc; - struct Iovs iv; - InitIovs(&iv); - if ((rc = GetFd(m, fd)) != -1) { - fd = rc; - if ((rc = AppendIovsReal(m, &iv, addr, size)) != -1) { - if ((rc = pwritev(fd, iv.p, iv.i, offset)) != -1) { - SetReadAddr(m, addr, rc); - } - } - } - FreeIovs(&iv); - return rc; -} - -static int IoctlTiocgwinsz(struct Machine *m, int fd, int64_t addr, - int fn(int, int, ...)) { - int rc; - struct winsize ws; - struct winsize_bits gws; - if ((rc = fn(fd, TIOCGWINSZ, &ws)) != -1) { - XlatWinsizeToLinux(&gws, &ws); - VirtualRecvWrite(m, addr, &gws, sizeof(gws)); - } - return rc; -} - -static int IoctlTcgets(struct Machine *m, int fd, int64_t addr, - int fn(int, int, ...)) { - int rc; - struct termios tio; - struct termios_bits gtio; - if ((rc = fn(fd, TCGETS, &tio)) != -1) { - XlatTermiosToLinux(>io, &tio); - VirtualRecvWrite(m, addr, >io, sizeof(gtio)); - } - return rc; -} - -static int IoctlTcsets(struct Machine *m, int fd, int64_t request, int64_t addr, - int (*fn)(int, int, ...)) { - struct termios tio; - struct termios_bits gtio; - VirtualSendRead(m, >io, addr, sizeof(gtio)); - XlatLinuxToTermios(&tio, >io); - return fn(fd, request, &tio); -} - -static int OpIoctl(struct Machine *m, int fd, uint64_t request, int64_t addr) { - int (*fn)(int, int, ...); - if (!(0 <= fd && fd < m->fds.i) || !m->fds.p[fd].cb) return ebadf(); - fn = m->fds.p[fd].cb->ioctl; - fd = m->fds.p[fd].fd; - switch (request) { - case TIOCGWINSZ_LINUX: - return IoctlTiocgwinsz(m, fd, addr, fn); - case TCGETS_LINUX: - return IoctlTcgets(m, fd, addr, fn); - case TCSETS_LINUX: - return IoctlTcsets(m, fd, TCSETS, addr, fn); - case TCSETSW_LINUX: - return IoctlTcsets(m, fd, TCSETSW, addr, fn); - case TCSETSF_LINUX: - return IoctlTcsets(m, fd, TCSETSF, addr, fn); - default: - return einval(); - } -} - -static ssize_t OpReadv(struct Machine *m, int fd, int64_t iovaddr, int iovlen) { - ssize_t rc; - struct Iovs iv; - InitIovs(&iv); - if ((0 <= fd && fd < m->fds.i) && m->fds.p[fd].cb) { - if ((rc = AppendIovsGuest(m, &iv, iovaddr, iovlen)) != -1) { - rc = m->fds.p[fd].cb->readv(m->fds.p[fd].fd, iv.p, iv.i); - } - } else { - rc = ebadf(); - } - FreeIovs(&iv); - return rc; -} - -static ssize_t OpWritev(struct Machine *m, int fd, int64_t iovaddr, - int iovlen) { - ssize_t rc; - struct Iovs iv; - InitIovs(&iv); - if ((0 <= fd && fd < m->fds.i) && m->fds.p[fd].cb) { - if ((rc = AppendIovsGuest(m, &iv, iovaddr, iovlen)) != -1) { - rc = m->fds.p[fd].cb->writev(m->fds.p[fd].fd, iv.p, iv.i); - } - } else { - rc = ebadf(); - } - FreeIovs(&iv); - return rc; -} - -static int64_t OpLseek(struct Machine *m, int fd, int64_t offset, int whence) { - if ((fd = GetFd(m, fd)) == -1) return -1; - return lseek(fd, offset, whence); -} - -static ssize_t OpFtruncate(struct Machine *m, int fd, int64_t size) { - if ((fd = GetFd(m, fd)) == -1) return -1; - return ftruncate(fd, size); -} - -static int OpFaccessat(struct Machine *m, int dirfd, int64_t path, int mode, - int flags) { - flags = XlatAtf(flags); - mode = XlatAccess(mode); - if ((dirfd = GetAfd(m, dirfd)) == -1) return -1; - return faccessat(dirfd, LoadStr(m, path), mode, flags); -} - -static int OpFstatat(struct Machine *m, int dirfd, int64_t path, int64_t staddr, - int flags) { - int rc; - struct stat st; - struct stat_bits gst; - flags = XlatAtf(flags); - if ((dirfd = GetAfd(m, dirfd)) == -1) return -1; - if ((rc = fstatat(dirfd, LoadStr(m, path), &st, flags)) != -1) { - XlatStatToLinux(&gst, &st); - VirtualRecvWrite(m, staddr, &gst, sizeof(gst)); - } - return rc; -} - -static int OpFstat(struct Machine *m, int fd, int64_t staddr) { - int rc; - struct stat st; - struct stat_bits gst; - if ((fd = GetFd(m, fd)) == -1) return -1; - if ((rc = fstat(fd, &st)) != -1) { - XlatStatToLinux(&gst, &st); - VirtualRecvWrite(m, staddr, &gst, sizeof(gst)); - } - return rc; -} - -static int OpListen(struct Machine *m, int fd, int backlog) { - if ((fd = GetFd(m, fd)) == -1) return -1; - return listen(fd, backlog); -} - -static int OpShutdown(struct Machine *m, int fd, int how) { - if ((fd = GetFd(m, fd)) == -1) return -1; - return shutdown(fd, how); -} - -static int OpFsync(struct Machine *m, int fd) { - if ((fd = GetFd(m, fd)) == -1) return -1; - return fsync(fd); -} - -static int OpFdatasync(struct Machine *m, int fd) { - if ((fd = GetFd(m, fd)) == -1) return -1; - return fdatasync(fd); -} - -static int OpFchmod(struct Machine *m, int fd, uint32_t mode) { - if ((fd = GetFd(m, fd)) == -1) return -1; - return fchmod(fd, mode); -} - -static int OpFcntl(struct Machine *m, int fd, int cmd, int arg) { - if ((cmd = XlatFcntlCmd(cmd)) == -1) return -1; - if ((arg = XlatFcntlArg(arg)) == -1) return -1; - if ((fd = GetFd(m, fd)) == -1) return -1; - return fcntl(fd, cmd, arg); -} - -static int OpFadvise(struct Machine *m, int fd, uint64_t offset, uint64_t len, - int advice) { - if ((fd = GetFd(m, fd)) == -1) return -1; - if ((advice = XlatAdvice(advice)) == -1) return -1; - return fadvise(fd, offset, len, advice); -} - -static int OpFlock(struct Machine *m, int fd, int lock) { - if ((fd = GetFd(m, fd)) == -1) return -1; - if ((lock = XlatLock(lock)) == -1) return -1; - return flock(fd, lock); -} - -static int OpChdir(struct Machine *m, int64_t path) { - return chdir(LoadStr(m, path)); -} - -static int OpMkdir(struct Machine *m, int64_t path, int mode) { - return mkdir(LoadStr(m, path), mode); -} - -static int OpMkdirat(struct Machine *m, int dirfd, int64_t path, int mode) { - return mkdirat(GetAfd(m, dirfd), LoadStr(m, path), mode); -} - -static int OpMknod(struct Machine *m, int64_t path, uint32_t mode, - uint64_t dev) { - return mknod(LoadStr(m, path), mode, dev); -} - -static int OpRmdir(struct Machine *m, int64_t path) { - return rmdir(LoadStr(m, path)); -} - -static int OpUnlink(struct Machine *m, int64_t path) { - return unlink(LoadStr(m, path)); -} - -static int OpUnlinkat(struct Machine *m, int dirfd, int64_t path, int flags) { - return unlinkat(GetAfd(m, dirfd), LoadStr(m, path), XlatAtf(flags)); -} - -static int OpRename(struct Machine *m, int64_t src, int64_t dst) { - return rename(LoadStr(m, src), LoadStr(m, dst)); -} - -static int OpRenameat(struct Machine *m, int srcdirfd, int64_t src, - int dstdirfd, int64_t dst) { - return renameat(GetAfd(m, srcdirfd), LoadStr(m, src), GetAfd(m, dstdirfd), - LoadStr(m, dst)); -} - -static int OpTruncate(struct Machine *m, int64_t path, uint64_t length) { - return truncate(LoadStr(m, path), length); -} - -static int OpLink(struct Machine *m, int64_t existingpath, int64_t newpath) { - return link(LoadStr(m, existingpath), LoadStr(m, newpath)); -} - -static int OpSymlink(struct Machine *m, int64_t target, int64_t linkpath) { - return symlink(LoadStr(m, target), LoadStr(m, linkpath)); -} - -static int OpChmod(struct Machine *m, int64_t path, uint32_t mode) { - return chmod(LoadStr(m, path), mode); -} - -static int OpFork(struct Machine *m) { - int pid; - pid = fork(); - if (!pid) m->isfork = true; - return pid; -} - -static int OpExecve(struct Machine *m, int64_t programaddr, int64_t argvaddr, - int64_t envpaddr) { - return enosys(); -} - -wontreturn static void OpExit(struct Machine *m, int rc) { - if (m->isfork) { - _Exit(rc); - } else { - HaltMachine(m, rc | 0x100); - } -} - -_Noreturn static void OpExitGroup(struct Machine *m, int rc) { - OpExit(m, rc); -} - -static int OpWait4(struct Machine *m, int pid, int64_t opt_out_wstatus_addr, - int options, int64_t opt_out_rusage_addr) { - int rc; - int32_t wstatus; - struct rusage hrusage; - struct rusage_bits grusage; - if ((options = XlatWait(options)) == -1) return -1; - if ((rc = wait4(pid, &wstatus, options, &hrusage)) != -1) { - if (opt_out_wstatus_addr) { - VirtualRecvWrite(m, opt_out_wstatus_addr, &wstatus, sizeof(wstatus)); - } - if (opt_out_rusage_addr) { - XlatRusageToLinux(&grusage, &hrusage); - VirtualRecvWrite(m, opt_out_rusage_addr, &grusage, sizeof(grusage)); - } - } - return rc; -} - -static int OpGetrusage(struct Machine *m, int resource, int64_t rusageaddr) { - int rc; - struct rusage hrusage; - struct rusage_bits grusage; - if ((resource = XlatRusage(resource)) == -1) return -1; - if ((rc = getrusage(resource, &hrusage)) != -1) { - XlatRusageToLinux(&grusage, &hrusage); - VirtualRecvWrite(m, rusageaddr, &grusage, sizeof(grusage)); - } - return rc; -} - -static int OpGetrlimit(struct Machine *m, int resource, int64_t rlimitaddr) { - return enosys(); -} - -static ssize_t OpReadlinkat(struct Machine *m, int dirfd, int64_t pathaddr, - int64_t bufaddr, size_t size) { - char *buf; - ssize_t rc; - const char *path; - if ((dirfd = GetAfd(m, dirfd)) == -1) return -1; - path = LoadStr(m, pathaddr); - if (!(buf = malloc(size))) return enomem(); - if ((rc = readlinkat(dirfd, path, buf, size)) != -1) { - VirtualRecvWrite(m, bufaddr, buf, rc); - } - free(buf); - return rc; -} - -static int64_t OpGetcwd(struct Machine *m, int64_t bufaddr, size_t size) { - size_t n; - char *buf; - int64_t res; - size = MIN(size, PATH_MAX); - if (!(buf = malloc(size))) return enomem(); - if ((getcwd)(buf, size)) { - n = strlen(buf); - VirtualRecvWrite(m, bufaddr, buf, n); - res = bufaddr; - } else { - res = -1; - } - free(buf); - return res; -} - -static int OpSigaction(struct Machine *m, int sig, int64_t act, int64_t old, - uint64_t sigsetsize) { - if ((sig = XlatSignal(sig) - 1) != -1 && - (0 <= sig && sig < ARRAYLEN(m->sighand)) && sigsetsize == 8) { - if (old) VirtualRecvWrite(m, old, &m->sighand[sig], sizeof(m->sighand[0])); - if (act) VirtualSendRead(m, &m->sighand[sig], act, sizeof(m->sighand[0])); - return 0; - } else { - return einval(); - } -} - -static int OpSigprocmask(struct Machine *m, int how, int64_t setaddr, - int64_t oldsetaddr, uint64_t sigsetsize) { - uint8_t set[8]; - if ((how = XlatSig(how)) != -1 && sigsetsize == sizeof(set)) { - if (oldsetaddr) { - VirtualRecvWrite(m, oldsetaddr, m->sigmask, sizeof(set)); - } - if (setaddr) { - VirtualSendRead(m, set, setaddr, sizeof(set)); - if (how == SIG_BLOCK) { - Write64(m->sigmask, Read64(m->sigmask) | Read64(set)); - } else if (how == SIG_UNBLOCK) { - Write64(m->sigmask, Read64(m->sigmask) & ~Read64(set)); - } else { - Write64(m->sigmask, Read64(set)); - } - } - return 0; - } else { - return einval(); - } -} - -static int OpGetitimer(struct Machine *m, int which, int64_t curvaladdr) { - int rc; - struct itimerval it; - struct itimerval_bits git; - if ((rc = getitimer(which, &it)) != -1) { - XlatItimervalToLinux(&git, &it); - VirtualRecvWrite(m, curvaladdr, &git, sizeof(git)); - } - return rc; -} - -static int OpSetitimer(struct Machine *m, int which, int64_t neuaddr, - int64_t oldaddr) { - int rc; - struct itimerval neu, old; - struct itimerval_bits git; - VirtualSendRead(m, &git, neuaddr, sizeof(git)); - XlatLinuxToItimerval(&neu, &git); - if ((rc = setitimer(which, &neu, &old)) != -1) { - if (oldaddr) { - XlatItimervalToLinux(&git, &old); - VirtualRecvWrite(m, oldaddr, &git, sizeof(git)); - } - } - return rc; -} - -static int OpNanosleep(struct Machine *m, int64_t req, int64_t rem) { - int rc; - struct timespec hreq, hrem; - struct timespec_bits gtimespec; - if (req) { - VirtualSendRead(m, >imespec, req, sizeof(gtimespec)); - hreq.tv_sec = Read64(gtimespec.tv_sec); - hreq.tv_nsec = Read64(gtimespec.tv_nsec); - } - if ((rc = nanosleep(req ? &hreq : 0, rem ? &hrem : 0)) != -1) { - if (rem) { - Write64(gtimespec.tv_sec, hrem.tv_sec); - Write64(gtimespec.tv_nsec, hrem.tv_nsec); - VirtualRecvWrite(m, rem, >imespec, sizeof(gtimespec)); - } - } - return rc; -} - -static int OpSigsuspend(struct Machine *m, int64_t maskaddr) { - sigset_t mask; - uint8_t gmask[8]; - VirtualSendRead(m, &gmask, maskaddr, 8); - XlatLinuxToSigset(&mask, gmask); - return sigsuspend(&mask); -} - -static int OpClockGettime(struct Machine *m, int clockid, int64_t ts) { - int rc; - struct timespec htimespec; - struct timespec_bits gtimespec; - if ((rc = clock_gettime(XlatClock(clockid), ts ? &htimespec : 0)) != -1) { - if (ts) { - Write64(gtimespec.tv_sec, htimespec.tv_sec); - Write64(gtimespec.tv_nsec, htimespec.tv_nsec); - VirtualRecvWrite(m, ts, >imespec, sizeof(gtimespec)); - } - } - return rc; -} - -static int OpGettimeofday(struct Machine *m, int64_t tv, int64_t tz) { - int rc; - struct timeval htimeval; - struct timezone htimezone; - struct timeval_bits gtimeval; - struct timezone_bits gtimezone; - if ((rc = gettimeofday(&htimeval, tz ? &htimezone : 0)) != -1) { - Write64(gtimeval.tv_sec, htimeval.tv_sec); - Write64(gtimeval.tv_usec, htimeval.tv_usec); - VirtualRecvWrite(m, tv, >imeval, sizeof(gtimeval)); - if (tz) { - Write32(gtimezone.tz_minuteswest, htimezone.tz_minuteswest); - Write32(gtimezone.tz_dsttime, htimezone.tz_dsttime); - VirtualRecvWrite(m, tz, >imezone, sizeof(gtimezone)); - } - } - return rc; -} - -static int OpUtimes(struct Machine *m, int64_t pathaddr, int64_t tvsaddr) { - const char *path; - struct timeval tvs[2]; - struct timeval_bits gtvs[2]; - path = LoadStr(m, pathaddr); - if (tvsaddr) { - VirtualSendRead(m, gtvs, tvsaddr, sizeof(gtvs)); - tvs[0].tv_sec = Read64(gtvs[0].tv_sec); - tvs[0].tv_usec = Read64(gtvs[0].tv_usec); - tvs[1].tv_sec = Read64(gtvs[1].tv_sec); - tvs[1].tv_usec = Read64(gtvs[1].tv_usec); - return utimes(path, tvs); - } else { - return utimes(path, 0); - } -} - -static int OpPoll(struct Machine *m, int64_t fdsaddr, uint64_t nfds, - int32_t timeout_ms) { - uint64_t gfdssize; - struct pollfd hfds[1]; - int i, fd, rc, ev, count; - struct timespec ts1, ts2; - struct pollfd_bits *gfds; - int64_t wait, elapsed, timeout; - timeout = timeout_ms * 1000L; - if (!ckd_mul(&gfdssize, nfds, sizeof(struct pollfd_bits)) && - gfdssize <= 0x7ffff000) { - if ((gfds = malloc(gfdssize))) { - rc = 0; - VirtualSendRead(m, gfds, fdsaddr, gfdssize); - ts1 = timespec_mono(); - for (;;) { - for (i = 0; i < nfds; ++i) { - fd = Read32(gfds[i].fd); - if ((0 <= fd && fd < m->fds.i) && m->fds.p[fd].cb) { - hfds[0].fd = m->fds.p[fd].fd; - ev = Read16(gfds[i].events); - hfds[0].events = (((ev & POLLIN_LINUX) ? POLLIN : 0) | - ((ev & POLLOUT_LINUX) ? POLLOUT : 0) | - ((ev & POLLPRI_LINUX) ? POLLPRI : 0)); - switch (m->fds.p[fd].cb->poll(hfds, 1, 0)) { - case 0: - Write16(gfds[i].revents, 0); - break; - case 1: - ++rc; - ev = 0; - if (hfds[0].revents & POLLIN) ev |= POLLIN_LINUX; - if (hfds[0].revents & POLLPRI) ev |= POLLPRI_LINUX; - if (hfds[0].revents & POLLOUT) ev |= POLLOUT_LINUX; - if (hfds[0].revents & POLLERR) ev |= POLLERR_LINUX; - if (hfds[0].revents & POLLHUP) ev |= POLLHUP_LINUX; - if (hfds[0].revents & POLLNVAL) ev |= POLLERR_LINUX; - if (!ev) ev |= POLLERR_LINUX; - Write16(gfds[i].revents, ev); - break; - case -1: - ++rc; - Write16(gfds[i].revents, POLLERR_LINUX); - break; - default: - break; - } - } else { - Write16(gfds[i].revents, POLLNVAL_LINUX); - } - } - if (rc || !timeout) break; - wait = __SIG_POLLING_INTERVAL_MS * 1000; - if (timeout < 0) { - if (usleep(wait)) { - errno = EINTR; - rc = -1; - goto Finished; - } - } else { - ts2 = timespec_mono(); - elapsed = timespec_tomicros(timespec_sub(ts2, ts1)); - if (elapsed >= timeout) { - break; - } - if (timeout - elapsed < wait) { - wait = timeout - elapsed; - } - if (usleep(wait)) { - errno = EINTR; - rc = -1; - goto Finished; - } - } - } - VirtualRecvWrite(m, fdsaddr, gfds, nfds * sizeof(*gfds)); - } else { - errno = ENOMEM; - rc = -1; - } - Finished: - free(gfds); - return rc; - } else { - return einval(); - } -} - -static int OpGetPid(struct Machine *m) { - return getpid(); -} - -static int OpGetPpid(struct Machine *m) { - return getppid(); -} - -static void OpKill(struct Machine *m, int pid, int sig) { - if (!pid || pid == getpid()) { - DeliverSignal(m, sig, SI_USER); - } else { - Write64(m->ax, -3); // ESRCH - } -} - -static int OpGetUid(struct Machine *m) { - return getuid(); -} - -static int OpGetGid(struct Machine *m) { - return getgid(); -} - -static int OpGetTid(struct Machine *m) { - return gettid(); -} - -static int OpSchedYield(struct Machine *m) { - return sched_yield(); -} - -static int OpAlarm(struct Machine *m, unsigned seconds) { - return alarm(seconds); -} - -static int OpPause(struct Machine *m) { - return pause(); -} - -static int DoOpen(struct Machine *m, int64_t path, int flags, int mode) { - return OpOpenat(m, -100, path, flags, mode); -} - -static int DoCreat(struct Machine *m, int64_t file, int mode) { - return DoOpen(m, file, 0x241, mode); -} - -static int DoAccess(struct Machine *m, int64_t path, int mode) { - return OpFaccessat(m, -100, path, mode, 0); -} - -static int DoStat(struct Machine *m, int64_t path, int64_t st) { - return OpFstatat(m, -100, path, st, 0); -} - -static int DoLstat(struct Machine *m, int64_t path, int64_t st) { - return OpFstatat(m, -100, path, st, 0x0400); -} - -static int OpAccept(struct Machine *m, int fd, int64_t sa, int64_t sas) { - return OpAccept4(m, fd, sa, sas, 0); -} - -void OpSyscall(struct Machine *m, uint32_t rde) { - uint64_t i, ax, di, si, dx, r0, r8, r9; - if (m->redraw) { - m->redraw(); - } - ax = Read64(m->ax); - if (m->ismetal) { - WARNF("metal syscall 0x%03x", ax); - } - di = Read64(m->di); - si = Read64(m->si); - dx = Read64(m->dx); - r0 = Read64(m->r10); - r8 = Read64(m->r8); - r9 = Read64(m->r9); - switch (ax & 0x1ff) { - SYSCALL(0x000, OpRead(m, di, si, dx)); - SYSCALL(0x001, OpWrite(m, di, si, dx)); - SYSCALL(0x002, DoOpen(m, di, si, dx)); - SYSCALL(0x003, OpClose(m, di)); - SYSCALL(0x004, DoStat(m, di, si)); - SYSCALL(0x005, OpFstat(m, di, si)); - SYSCALL(0x006, DoLstat(m, di, si)); - SYSCALL(0x007, OpPoll(m, di, si, dx)); - SYSCALL(0x008, OpLseek(m, di, si, dx)); - SYSCALL(0x009, OpMmap(m, di, si, dx, r0, r8, r9)); - SYSCALL(0x01A, OpMsync(m, di, si, dx)); - SYSCALL(0x00A, OpMprotect(m, di, si, dx)); - SYSCALL(0x00B, OpMunmap(m, di, si)); - SYSCALL(0x00C, OpBrk(m, di)); - SYSCALL(0x00D, OpSigaction(m, di, si, dx, r0)); - SYSCALL(0x00E, OpSigprocmask(m, di, si, dx, r0)); - SYSCALL(0x010, OpIoctl(m, di, si, dx)); - SYSCALL(0x011, OpPread(m, di, si, dx, r0)); - SYSCALL(0x012, OpPwrite(m, di, si, dx, r0)); - SYSCALL(0x013, OpReadv(m, di, si, dx)); - SYSCALL(0x014, OpWritev(m, di, si, dx)); - SYSCALL(0x015, DoAccess(m, di, si)); - SYSCALL(0x016, OpPipe(m, di)); - SYSCALL(0x017, select(di, P(si), P(dx), P(r0), P(r8))); - SYSCALL(0x018, OpSchedYield(m)); - SYSCALL(0x01C, OpMadvise(m, di, si, dx)); - SYSCALL(0x020, OpDup(m, di)); - SYSCALL(0x021, OpDup2(m, di, si)); - SYSCALL(0x124, OpDup3(m, di, si, dx)); - SYSCALL(0x022, OpPause(m)); - SYSCALL(0x023, OpNanosleep(m, di, si)); - SYSCALL(0x024, OpGetitimer(m, di, si)); - SYSCALL(0x025, OpAlarm(m, di)); - SYSCALL(0x026, OpSetitimer(m, di, si, dx)); - SYSCALL(0x027, OpGetPid(m)); - SYSCALL(0x028, sendfile(di, si, P(dx), r0)); - SYSCALL(0x029, OpSocket(m, di, si, dx)); - SYSCALL(0x02A, OpConnect(m, di, si, dx)); - SYSCALL(0x02B, OpAccept(m, di, di, dx)); - SYSCALL(0x02C, sendto(di, PNN(si), dx, r0, P(r8), r9)); - SYSCALL(0x02D, recvfrom(di, P(si), dx, r0, P(r8), P(r9))); - SYSCALL(0x030, OpShutdown(m, di, si)); - SYSCALL(0x031, OpBind(m, di, si, dx)); - SYSCALL(0x032, OpListen(m, di, si)); - SYSCALL(0x033, OpGetsockname(m, di, si, dx)); - SYSCALL(0x034, OpGetpeername(m, di, si, dx)); - SYSCALL(0x036, OpSetsockopt(m, di, si, dx, r0, r8)); - SYSCALL(0x037, OpGetsockopt(m, di, si, dx, r0, r8)); - SYSCALL(0x039, OpFork(m)); - SYSCALL(0x03B, OpExecve(m, di, si, dx)); - SYSCALL(0x03D, OpWait4(m, di, si, dx, r0)); - SYSCALL(0x03F, uname(P(di))); - SYSCALL(0x048, OpFcntl(m, di, si, dx)); - SYSCALL(0x049, OpFlock(m, di, si)); - SYSCALL(0x04A, OpFsync(m, di)); - SYSCALL(0x04B, OpFdatasync(m, di)); - SYSCALL(0x04C, OpTruncate(m, di, si)); - SYSCALL(0x04D, OpFtruncate(m, di, si)); - SYSCALL(0x04F, OpGetcwd(m, di, si)); - SYSCALL(0x050, OpChdir(m, di)); - SYSCALL(0x052, OpRename(m, di, si)); - SYSCALL(0x053, OpMkdir(m, di, si)); - SYSCALL(0x054, OpRmdir(m, di)); - SYSCALL(0x055, DoCreat(m, di, si)); - SYSCALL(0x056, OpLink(m, di, si)); - SYSCALL(0x057, OpUnlink(m, di)); - SYSCALL(0x058, OpSymlink(m, di, si)); - SYSCALL(0x05A, OpChmod(m, di, si)); - SYSCALL(0x05B, OpFchmod(m, di, si)); - SYSCALL(0x060, OpGettimeofday(m, di, si)); - SYSCALL(0x061, OpGetrlimit(m, di, si)); - SYSCALL(0x062, OpGetrusage(m, di, si)); - SYSCALL(0x063, sysinfo(PNN(di))); - SYSCALL(0x064, times(PNN(di))); - SYSCALL(0x066, OpGetUid(m)); - SYSCALL(0x068, OpGetGid(m)); - SYSCALL(0x06E, OpGetPpid(m)); - SYSCALL(0x075, setresuid(di, si, dx)); - SYSCALL(0x077, setresgid(di, si, dx)); - SYSCALL(0x082, OpSigsuspend(m, di)); - SYSCALL(0x085, OpMknod(m, di, si, dx)); - SYSCALL(0x08C, getpriority(di, si)); - SYSCALL(0x08D, setpriority(di, si, dx)); - SYSCALL(0x0A0, setrlimit(di, P(si))); - SYSCALL(0x084, utime(PNN(di), PNN(si))); - SYSCALL(0x0EB, OpUtimes(m, di, si)); - SYSCALL(0x09D, OpPrctl(m, di, si, dx, r0, r8)); - SYSCALL(0x09E, OpArchPrctl(m, di, si)); - SYSCALL(0x0BA, OpGetTid(m)); - SYSCALL(0x0D9, OpGetdents(m, di, si, dx)); - SYSCALL(0x0DD, OpFadvise(m, di, si, dx, r0)); - SYSCALL(0x0E4, OpClockGettime(m, di, si)); - SYSCALL(0x101, OpOpenat(m, di, si, dx, r0)); - SYSCALL(0x102, OpMkdirat(m, di, si, dx)); - SYSCALL(0x104, fchownat(GetAfd(m, di), P(si), dx, r0, XlatAtf(r8))); - SYSCALL(0x105, futimesat(GetAfd(m, di), P(si), P(dx))); - SYSCALL(0x106, OpFstatat(m, di, si, dx, r0)); - SYSCALL(0x107, OpUnlinkat(m, di, si, dx)); - SYSCALL(0x108, OpRenameat(m, di, si, dx, r0)); - SYSCALL(0x10B, OpReadlinkat(m, di, si, dx, r0)); - SYSCALL(0x10D, OpFaccessat(m, di, si, dx, r0)); - SYSCALL(0x113, splice(di, P(si), dx, P(r0), r8, XlatAtf(r9))); - SYSCALL(0x115, sync_file_range(di, si, dx, XlatAtf(r0))); - SYSCALL(0x118, utimensat(GetAfd(m, di), P(si), P(dx), XlatAtf(r0))); - SYSCALL(0x120, OpAccept4(m, di, si, dx, r0)); - SYSCALL(0x177, vmsplice(di, P(si), dx, r0)); - case 0x3C: - OpExit(m, di); - case 0xE7: - OpExitGroup(m, di); - case 0x00F: - OpRestore(m); - return; - case 0x03E: - OpKill(m, di, si); - return; - default: - WARNF("missing syscall 0x%03x", ax); - ax = enosys(); - break; - } - Write64(m->ax, ax != -1 ? ax : -(XlatErrno(errno) & 0xfff)); - for (i = 0; i < m->freelist.i; ++i) free(m->freelist.p[i]); - m->freelist.i = 0; -} diff --git a/tool/build/lib/syscall.h b/tool/build/lib/syscall.h deleted file mode 100644 index 0421d53fc..000000000 --- a/tool/build/lib/syscall.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_SYSCALL_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_SYSCALL_H_ -#include "tool/build/lib/fds.h" -#include "tool/build/lib/machine.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -extern const struct MachineFdCb kMachineFdCbHost; - -void OpSyscall(struct Machine *, uint32_t); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_SYSCALL_H_ */ diff --git a/tool/build/lib/throw.c b/tool/build/lib/throw.c deleted file mode 100644 index 4259f8956..000000000 --- a/tool/build/lib/throw.c +++ /dev/null @@ -1,69 +0,0 @@ -/*-*- 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/log/check.h" -#include "libc/log/log.h" -#include "libc/mem/gc.internal.h" -#include "libc/nexgen32e/vendor.internal.h" -#include "libc/runtime/runtime.h" -#include "libc/str/str.h" -#include "tool/build/lib/address.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/throw.h" - -static bool IsHaltingInitialized(struct Machine *m) { - jmp_buf zb; - bzero(zb, sizeof(zb)); - return memcmp(m->onhalt, zb, sizeof(m->onhalt)) != 0; -} - -void HaltMachine(struct Machine *m, int code) { - CHECK(IsHaltingInitialized(m)); - _gclongjmp(m->onhalt, code); -} - -void ThrowDivideError(struct Machine *m) { - HaltMachine(m, kMachineDivideError); -} - -void ThrowSegmentationFault(struct Machine *m, int64_t va) { - m->faultaddr = va; - if (m->xedd) m->ip -= m->xedd->length; - WARNF("%s%s ADDR %012lx IP %012lx AX %lx CX %lx DX %lx BX %lx SP %lx " - "BP %lx SI %lx DI %lx R8 %lx R9 %lx R10 %lx R11 %lx R12 %lx R13 %lx " - "R14 %lx R15 %lx", - "SEGMENTATION FAULT", IsGenuineBlink() ? " SIMULATED" : "", va, m->ip, - Read64(m->ax), Read64(m->cx), Read64(m->dx), Read64(m->bx), - Read64(m->sp), Read64(m->bp), Read64(m->si), Read64(m->di), - Read64(m->r8), Read64(m->r9), Read64(m->r10), Read64(m->r11), - Read64(m->r12), Read64(m->r13), Read64(m->r14), Read64(m->r15)); - HaltMachine(m, kMachineSegmentationFault); -} - -void ThrowProtectionFault(struct Machine *m) { - HaltMachine(m, kMachineProtectionFault); -} - -void OpUd(struct Machine *m, uint32_t rde) { - if (m->xedd) m->ip -= m->xedd->length; - HaltMachine(m, kMachineUndefinedInstruction); -} - -void OpHlt(struct Machine *m, uint32_t rde) { - HaltMachine(m, kMachineHalt); -} diff --git a/tool/build/lib/throw.h b/tool/build/lib/throw.h deleted file mode 100644 index 6df3b71c1..000000000 --- a/tool/build/lib/throw.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_THROW_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_THROW_H_ -#include "tool/build/lib/machine.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -void OpUd(struct Machine *, uint32_t) wontreturn; -void HaltMachine(struct Machine *, int) wontreturn; -void ThrowDivideError(struct Machine *) wontreturn; -void ThrowSegmentationFault(struct Machine *, int64_t) wontreturn; -void ThrowProtectionFault(struct Machine *) wontreturn; -void OpHlt(struct Machine *, uint32_t) wontreturn; - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_THROW_H_ */ diff --git a/tool/build/lib/time.c b/tool/build/lib/time.c deleted file mode 100644 index 70bdd59fd..000000000 --- a/tool/build/lib/time.c +++ /dev/null @@ -1,69 +0,0 @@ -/*-*- 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/calls.h" -#include "libc/calls/struct/timespec.h" -#include "libc/nexgen32e/rdtsc.h" -#include "libc/sock/sock.h" -#include "libc/sysv/consts/clock.h" -#include "libc/sysv/consts/poll.h" -#include "libc/time/time.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/modrm.h" -#include "tool/build/lib/time.h" - -/** - * @fileoverview i am the timelorde - */ - -void OpPause(struct Machine *m, uint32_t rde) { - struct pollfd pf; - static bool once, interactive; - if (!once) { - interactive = isatty(0); - once = true; - } - pf.fd = 0; - pf.events = POLLIN; - poll(&pf, 1, 20); /* make spin loops less brutal */ -} - -void OpRdtsc(struct Machine *m, uint32_t rde) { - uint64_t c; - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - c = ts.tv_sec * 1000000000 + ts.tv_nsec; - Write64(m->ax, (c >> 000) & 0xffffffff); - Write64(m->dx, (c >> 040) & 0xffffffff); -} - -static int64_t GetTscAux(struct Machine *m) { - uint32_t core, node; - core = 0; - node = 0; - return (node & 0xfff) << 12 | (core & 0xfff); -} - -void OpRdtscp(struct Machine *m, uint32_t rde) { - OpRdtsc(m, rde); - Write64(m->cx, GetTscAux(m)); -} - -void OpRdpid(struct Machine *m, uint32_t rde) { - Write64(RegRexbRm(m, rde), GetTscAux(m)); -} diff --git a/tool/build/lib/time.h b/tool/build/lib/time.h deleted file mode 100644 index b745496f8..000000000 --- a/tool/build/lib/time.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_TIME_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_TIME_H_ -#include "tool/build/lib/machine.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -void OpPause(struct Machine *, uint32_t); -void OpRdtsc(struct Machine *, uint32_t); -void OpRdtscp(struct Machine *, uint32_t); -void OpRdpid(struct Machine *, uint32_t); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_TIME_H_ */ diff --git a/tool/build/lib/word.c b/tool/build/lib/word.c deleted file mode 100644 index fd5d0ab8e..000000000 --- a/tool/build/lib/word.c +++ /dev/null @@ -1,64 +0,0 @@ -/*-*- 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/str/str.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/memory.h" -#include "tool/build/lib/word.h" - -void SetMemoryShort(struct Machine *m, int64_t v, int16_t i) { - void *p[2]; - uint8_t b[2]; - Write16(BeginStore(m, v, 2, p, b), i); - EndStore(m, v, 2, p, b); -} - -void SetMemoryInt(struct Machine *m, int64_t v, int32_t i) { - void *p[2]; - uint8_t b[4]; - Write32(BeginStore(m, v, 4, p, b), i); - EndStore(m, v, 4, p, b); -} - -void SetMemoryLong(struct Machine *m, int64_t v, int64_t i) { - void *p[2]; - uint8_t b[8]; - Write64(BeginStore(m, v, 8, p, b), i); - EndStore(m, v, 8, p, b); -} - -void SetMemoryFloat(struct Machine *m, int64_t v, float f) { - void *p[2]; - uint8_t b[4]; - memcpy(BeginStore(m, v, 4, p, b), &f, 4); - EndStore(m, v, 4, p, b); -} - -void SetMemoryDouble(struct Machine *m, int64_t v, double f) { - void *p[2]; - uint8_t b[8]; - memcpy(BeginStore(m, v, 8, p, b), &f, 8); - EndStore(m, v, 8, p, b); -} - -void SetMemoryLdbl(struct Machine *m, int64_t v, long double f) { - void *p[2]; - uint8_t b[10]; - memcpy(BeginStore(m, v, 10, p, b), &f, 10); - EndStore(m, v, 10, p, b); -} diff --git a/tool/build/lib/word.h b/tool/build/lib/word.h deleted file mode 100644 index 0e148079b..000000000 --- a/tool/build/lib/word.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_WORD_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_WORD_H_ -#include "tool/build/lib/machine.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -void SetMemoryShort(struct Machine *, int64_t, int16_t); -void SetMemoryInt(struct Machine *, int64_t, int32_t); -void SetMemoryLong(struct Machine *, int64_t, int64_t); -void SetMemoryFloat(struct Machine *, int64_t, float); -void SetMemoryDouble(struct Machine *, int64_t, double); -void SetMemoryLdbl(struct Machine *, int64_t, long double); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_WORD_H_ */ diff --git a/tool/build/lib/xlat.c b/tool/build/lib/xlat.c deleted file mode 100644 index 4afb2b22d..000000000 --- a/tool/build/lib/xlat.c +++ /dev/null @@ -1,1002 +0,0 @@ -/*-*- 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 2022 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/errno.h" -#include "libc/str/str.h" -#include "libc/sysv/consts/af.h" -#include "libc/sysv/consts/at.h" -#include "libc/sysv/consts/clock.h" -#include "libc/sysv/consts/f.h" -#include "libc/sysv/consts/fd.h" -#include "libc/sysv/consts/ip.h" -#include "libc/sysv/consts/ipproto.h" -#include "libc/sysv/consts/lock.h" -#include "libc/sysv/consts/madv.h" -#include "libc/sysv/consts/map.h" -#include "libc/sysv/consts/msync.h" -#include "libc/sysv/consts/o.h" -#include "libc/sysv/consts/ok.h" -#include "libc/sysv/consts/rusage.h" -#include "libc/sysv/consts/sicode.h" -#include "libc/sysv/consts/sig.h" -#include "libc/sysv/consts/so.h" -#include "libc/sysv/consts/sock.h" -#include "libc/sysv/consts/sol.h" -#include "libc/sysv/consts/tcp.h" -#include "libc/sysv/consts/termios.h" -#include "libc/sysv/consts/w.h" -#include "libc/sysv/errfuns.h" -#include "tool/build/lib/case.h" -#include "tool/build/lib/endian.h" -#include "tool/build/lib/xlat.h" - -#define XLAT(x, y) CASE(x, return y) - -int XlatSignal(int x) { - switch (x) { - XLAT(1, SIGHUP); - XLAT(2, SIGINT); - XLAT(3, SIGQUIT); - XLAT(4, SIGILL); - XLAT(5, SIGTRAP); - XLAT(6, SIGABRT); - XLAT(7, SIGBUS); - XLAT(8, SIGFPE); - XLAT(9, SIGKILL); - XLAT(10, SIGUSR1); - XLAT(11, SIGSEGV); - XLAT(12, SIGUSR2); - XLAT(13, SIGPIPE); - XLAT(14, SIGALRM); - XLAT(15, SIGTERM); - XLAT(17, SIGCHLD); - XLAT(18, SIGCONT); - XLAT(21, SIGTTIN); - XLAT(22, SIGTTOU); - XLAT(24, SIGXCPU); - XLAT(25, SIGXFSZ); - XLAT(26, SIGVTALRM); - XLAT(27, SIGPROF); - XLAT(28, SIGWINCH); - XLAT(29, SIGIO); - XLAT(19, SIGSTOP); - XLAT(31, SIGSYS); - XLAT(20, SIGTSTP); - XLAT(23, SIGURG); - default: - return einval(); - } -} - -int UnXlatSignal(int x) { - if (x == SIGHUP) return 1; - if (x == SIGINT) return 2; - if (x == SIGQUIT) return 3; - if (x == SIGILL) return 4; - if (x == SIGTRAP) return 5; - if (x == SIGABRT) return 6; - if (x == SIGBUS) return 7; - if (x == SIGFPE) return 8; - if (x == SIGKILL) return 9; - if (x == SIGUSR1) return 10; - if (x == SIGSEGV) return 11; - if (x == SIGUSR2) return 12; - if (x == SIGPIPE) return 13; - if (x == SIGALRM) return 14; - if (x == SIGTERM) return 15; - if (x == SIGCHLD) return 17; - if (x == SIGCONT) return 18; - if (x == SIGTTIN) return 21; - if (x == SIGTTOU) return 22; - if (x == SIGXCPU) return 24; - if (x == SIGXFSZ) return 25; - if (x == SIGVTALRM) return 26; - if (x == SIGPROF) return 27; - if (x == SIGWINCH) return 28; - if (x == SIGIO) return 29; - if (x == SIGSTOP) return 19; - if (x == SIGSYS) return 31; - if (x == SIGTSTP) return 20; - if (x == SIGURG) return 23; - return 15; -} - -int UnXlatSicode(int sig, int code) { - if (code == SI_USER) return 0; - if (code == SI_QUEUE) return -1; - if (code == SI_TIMER) return -2; - if (code == SI_TKILL) return -6; - if (code == SI_MESGQ) return -3; - if (code == SI_ASYNCIO) return -4; - if (code == SI_ASYNCNL) return -60; - if (code == SI_KERNEL) return 0x80; - if (sig == SIGCHLD) { - if (code == CLD_EXITED) return 1; - if (code == CLD_KILLED) return 2; - if (code == CLD_DUMPED) return 3; - if (code == CLD_TRAPPED) return 4; - if (code == CLD_STOPPED) return 5; - if (code == CLD_CONTINUED) return 6; - return -1; - } - if (sig == SIGTRAP) { - if (code == TRAP_BRKPT) return 1; - if (code == TRAP_TRACE) return 2; - return -1; - } - if (sig == SIGSEGV) { - if (code == SEGV_MAPERR) return 1; - if (code == SEGV_ACCERR) return 2; - return -1; - } - if (sig == SIGFPE) { - if (code == FPE_INTDIV) return 1; - if (code == FPE_INTOVF) return 2; - if (code == FPE_FLTDIV) return 3; - if (code == FPE_FLTOVF) return 4; - if (code == FPE_FLTUND) return 5; - if (code == FPE_FLTRES) return 6; - if (code == FPE_FLTINV) return 7; - if (code == FPE_FLTSUB) return 8; - return -1; - } - if (sig == SIGILL) { - if (code == ILL_ILLOPC) return 1; - if (code == ILL_ILLOPN) return 2; - if (code == ILL_ILLADR) return 3; - if (code == ILL_ILLTRP) return 4; - if (code == ILL_PRVOPC) return 5; - if (code == ILL_PRVREG) return 6; - if (code == ILL_COPROC) return 7; - if (code == ILL_BADSTK) return 8; - return -1; - } - if (sig == SIGBUS) { - if (code == BUS_ADRALN) return 1; - if (code == BUS_ADRERR) return 2; - if (code == BUS_OBJERR) return 3; - if (code == BUS_MCEERR_AR) return 4; - if (code == BUS_MCEERR_AO) return 5; - return -1; - } - if (sig == SIGIO) { - if (code == POLL_IN) return 1; - if (code == POLL_OUT) return 2; - if (code == POLL_MSG) return 3; - if (code == POLL_ERR) return 4; - if (code == POLL_PRI) return 5; - if (code == POLL_HUP) return 6; - return -1; - } - return -1; -} - -int XlatSig(int x) { - switch (x) { - XLAT(0, SIG_BLOCK); - XLAT(1, SIG_UNBLOCK); - XLAT(2, SIG_SETMASK); - default: - return einval(); - } -} - -int XlatRusage(int x) { - switch (x) { - XLAT(0, RUSAGE_SELF); - XLAT(-1, RUSAGE_CHILDREN); - XLAT(1, RUSAGE_THREAD); - default: - return einval(); - } -} - -int XlatSocketFamily(int x) { - switch (x) { - XLAT(0, AF_UNSPEC); - XLAT(1, AF_UNIX); - XLAT(2, AF_INET); - default: - errno = EPFNOSUPPORT; - return -1; - } -} - -int UnXlatSocketFamily(int x) { - switch (x) { - XLAT(AF_UNSPEC, 0); - XLAT(AF_UNIX, 1); - XLAT(AF_INET, 2); - default: - return x; - } -} - -int XlatSocketType(int x) { - switch (x) { - XLAT(1, SOCK_STREAM); - XLAT(2, SOCK_DGRAM); - default: - return einval(); - } -} - -int XlatSocketFlags(int flags) { - unsigned res = 0; - if (flags & 0x080000) res |= SOCK_CLOEXEC; - if (flags & 0x000800) res |= SOCK_NONBLOCK; - return res; -} - -int XlatSocketProtocol(int x) { - switch (x) { - XLAT(0, 0); - XLAT(6, IPPROTO_TCP); - XLAT(17, IPPROTO_UDP); - default: - return einval(); - } -} - -int XlatSocketLevel(int level) { - switch (level) { - XLAT(0, SOL_IP); - XLAT(1, SOL_SOCKET); - XLAT(6, SOL_TCP); - XLAT(17, SOL_UDP); - default: - return einval(); - } -} - -int XlatSocketOptname(int level, int optname) { - if (level == SOL_SOCKET) { - switch (optname) { - XLAT(1, SO_DEBUG); - XLAT(2, SO_REUSEADDR); - XLAT(3, SO_TYPE); - XLAT(4, SO_ERROR); - XLAT(5, SO_DONTROUTE); - XLAT(6, SO_BROADCAST); - XLAT(7, SO_SNDBUF); - XLAT(8, SO_RCVBUF); - XLAT(9, SO_KEEPALIVE); - XLAT(13, SO_LINGER); - XLAT(15, SO_REUSEPORT); - XLAT(18, SO_RCVLOWAT); - XLAT(19, SO_SNDLOWAT); - XLAT(30, SO_ACCEPTCONN); - default: - return einval(); - } - } - if (level == SOL_TCP) { - switch (optname) { - XLAT(1, TCP_NODELAY); - XLAT(2, TCP_MAXSEG); -#if defined(TCP_CORK) - XLAT(3, TCP_CORK); -#elif defined(TCP_NOPUSH) - XLAT(3, TCP_NOPUSH); -#endif -#ifdef TCP_KEEPIDLE - XLAT(4, TCP_KEEPIDLE); -#endif -#ifdef TCP_KEEPINTVL - XLAT(5, TCP_KEEPINTVL); -#endif -#ifdef TCP_KEEPCNT - XLAT(6, TCP_KEEPCNT); -#endif -#ifdef TCP_SYNCNT - XLAT(7, TCP_SYNCNT); -#endif -#ifdef TCP_WINDOW_CLAMP - XLAT(10, TCP_WINDOW_CLAMP); -#endif -#ifdef TCP_FASTOPEN - XLAT(23, TCP_FASTOPEN); -#endif -#ifdef TCP_QUICKACK - XLAT(12, TCP_QUICKACK); -#endif -#ifdef TCP_NOTSENT_LOWAT - XLAT(25, TCP_NOTSENT_LOWAT); -#endif -#ifdef TCP_SAVE_SYN - XLAT(27, TCP_SAVE_SYN); -#endif -#ifdef TCP_FASTOPEN_CONNECT - XLAT(30, TCP_FASTOPEN_CONNECT); -#endif - default: - return einval(); - } - } - if (level == SOL_IP) { - switch (optname) { - XLAT(1, IP_TOS); - XLAT(2, IP_TTL); - XLAT(3, IP_HDRINCL); - XLAT(14, IP_MTU); - default: - return einval(); - } - } - return einval(); -} - -int XlatAccess(int x) { - int r = F_OK; - if (x & 1) r |= X_OK; - if (x & 2) r |= W_OK; - if (x & 4) r |= R_OK; - return r; -} - -int XlatLock(int x) { - int r = 0; - if (x & 1) r |= LOCK_SH; - if (x & 2) r |= LOCK_EX; - if (x & 4) r |= LOCK_NB; - if (x & 8) r |= LOCK_UN; - return r; -} - -int XlatWait(int x) { - int r = 0; - if (x & 1) r |= WNOHANG; - if (x & 2) r |= WUNTRACED; - if (x & 8) r |= WCONTINUED; - return r; -} - -int XlatMapFlags(int x) { - int r = 0; - if (x & 1) r |= MAP_SHARED; - if (x & 2) r |= MAP_PRIVATE; - if (x & 16) r |= MAP_FIXED; - if (x & 32) r |= MAP_ANONYMOUS; - return r; -} - -int XlatMsyncFlags(int x) { - unsigned res = 0; - if (x & 1) res |= MS_ASYNC; - if (x & 2) res |= MS_INVALIDATE; - if (x & 4) res |= MS_SYNC; - return res; -} - -int XlatClock(int x) { - switch (x) { - XLAT(0, CLOCK_REALTIME); - XLAT(1, CLOCK_MONOTONIC); - XLAT(2, CLOCK_PROCESS_CPUTIME_ID); -#ifdef CLOCK_MONOTONIC_RAW - XLAT(4, CLOCK_MONOTONIC_RAW); -#endif - default: - return x; - } -} - -int XlatAtf(int x) { - int res = 0; - if (x & 0x0100) res |= AT_SYMLINK_NOFOLLOW; - if (x & 0x0200) res |= AT_REMOVEDIR; - if (x & 0x0400) res |= AT_SYMLINK_FOLLOW; - if (x & 0x1000) res |= AT_EMPTY_PATH; - return res; -} - -int XlatOpenMode(int flags) { - switch (flags & 3) { - case 0: - return O_RDONLY; - case 1: - return O_WRONLY; - case 2: - return O_RDWR; - default: - for (;;) (void)0; - } -} - -int XlatOpenFlags(int flags) { - int res; - res = XlatOpenMode(flags); - if (flags & 0x00400) res |= O_APPEND; - if (flags & 0x00040) res |= O_CREAT; - if (flags & 0x00080) res |= O_EXCL; - if (flags & 0x00200) res |= O_TRUNC; - if (flags & 0x00800) res |= O_NDELAY; - if (flags & 0x04000) res |= O_DIRECT; - if (flags & 0x10000) res |= O_DIRECTORY; - if (flags & 0x20000) res |= O_NOFOLLOW; - if (flags & 0x80000) res |= O_CLOEXEC; - if (flags & 0x00100) res |= O_NOCTTY; -#ifdef O_ASYNC - if (flags & 0x02000) res |= O_ASYNC; -#endif -#ifdef O_NOATIME - if (flags & 0x40000) res |= O_NOATIME; -#endif -#ifdef O_DSYNC - if (flags & 0x000001000) res |= O_DSYNC; -#endif -#ifdef O_SYNC - if ((flags & 0x00101000) == 0x00101000) res |= O_SYNC; -#endif - return res; -} - -int XlatFcntlCmd(int x) { - switch (x) { - XLAT(1, F_GETFD); - XLAT(2, F_SETFD); - XLAT(3, F_GETFL); - XLAT(4, F_SETFL); - default: - return einval(); - } -} - -int XlatFcntlArg(int x) { - switch (x) { - XLAT(0, 0); - XLAT(1, FD_CLOEXEC); - XLAT(0x0800, O_NONBLOCK); - default: - return einval(); - } -} - -int XlatAdvice(int x) { - switch (x) { - XLAT(0, MADV_NORMAL); - XLAT(1, MADV_RANDOM); - XLAT(2, MADV_SEQUENTIAL); - XLAT(3, MADV_WILLNEED); - XLAT(4, MADV_DONTNEED); - XLAT(8, MADV_FREE); - XLAT(12, MADV_MERGEABLE); - default: - return einval(); - } -} - -void XlatSockaddrToHost(struct sockaddr_in *dst, - const struct sockaddr_in_bits *src) { - memset(dst, 0, sizeof(*dst)); - dst->sin_family = XlatSocketFamily(Read16(src->sin_family)); - dst->sin_port = src->sin_port; - dst->sin_addr.s_addr = src->sin_addr; -} - -void XlatSockaddrToLinux(struct sockaddr_in_bits *dst, - const struct sockaddr_in *src) { - memset(dst, 0, sizeof(*dst)); - Write16(dst->sin_family, UnXlatSocketFamily(src->sin_family)); - dst->sin_port = src->sin_port; - dst->sin_addr = src->sin_addr.s_addr; -} - -void XlatStatToLinux(struct stat_bits *dst, const struct stat *src) { - Write64(dst->st_dev, src->st_dev); - Write64(dst->st_ino, src->st_ino); - Write64(dst->st_nlink, src->st_nlink); - Write32(dst->st_mode, src->st_mode); - Write32(dst->st_uid, src->st_uid); - Write32(dst->st_gid, src->st_gid); - Write32(dst->__pad, 0); - Write64(dst->st_rdev, src->st_rdev); - Write64(dst->st_size, src->st_size); - Write64(dst->st_blksize, src->st_blksize); - Write64(dst->st_blocks, src->st_blocks); - Write64(dst->st_dev, src->st_dev); - Write64(dst->st_atim.tv_sec, src->st_atim.tv_sec); - Write64(dst->st_atim.tv_nsec, src->st_atim.tv_nsec); - Write64(dst->st_mtim.tv_sec, src->st_mtim.tv_sec); - Write64(dst->st_mtim.tv_nsec, src->st_mtim.tv_nsec); - Write64(dst->st_ctim.tv_sec, src->st_ctim.tv_sec); - Write64(dst->st_ctim.tv_nsec, src->st_ctim.tv_nsec); -} - -void XlatRusageToLinux(struct rusage_bits *dst, const struct rusage *src) { - Write64(dst->ru_utime.tv_sec, src->ru_utime.tv_sec); - Write64(dst->ru_utime.tv_usec, src->ru_utime.tv_usec); - Write64(dst->ru_stime.tv_sec, src->ru_stime.tv_sec); - Write64(dst->ru_stime.tv_usec, src->ru_stime.tv_usec); - Write64(dst->ru_maxrss, src->ru_maxrss); - Write64(dst->ru_ixrss, src->ru_ixrss); - Write64(dst->ru_idrss, src->ru_idrss); - Write64(dst->ru_isrss, src->ru_isrss); - Write64(dst->ru_minflt, src->ru_minflt); - Write64(dst->ru_majflt, src->ru_majflt); - Write64(dst->ru_nswap, src->ru_nswap); - Write64(dst->ru_inblock, src->ru_inblock); - Write64(dst->ru_oublock, src->ru_oublock); - Write64(dst->ru_msgsnd, src->ru_msgsnd); - Write64(dst->ru_msgrcv, src->ru_msgrcv); - Write64(dst->ru_nsignals, src->ru_nsignals); - Write64(dst->ru_nvcsw, src->ru_nvcsw); - Write64(dst->ru_nivcsw, src->ru_nivcsw); -} - -void XlatItimervalToLinux(struct itimerval_bits *dst, - const struct itimerval *src) { - Write64(dst->it_interval.tv_sec, src->it_interval.tv_sec); - Write64(dst->it_interval.tv_usec, src->it_interval.tv_usec); - Write64(dst->it_value.tv_sec, src->it_value.tv_sec); - Write64(dst->it_value.tv_usec, src->it_value.tv_usec); -} - -void XlatLinuxToItimerval(struct itimerval *dst, - const struct itimerval_bits *src) { - dst->it_interval.tv_sec = Read64(src->it_interval.tv_sec); - dst->it_interval.tv_usec = Read64(src->it_interval.tv_usec); - dst->it_value.tv_sec = Read64(src->it_value.tv_sec); - dst->it_value.tv_usec = Read64(src->it_value.tv_usec); -} - -void XlatWinsizeToLinux(struct winsize_bits *dst, const struct winsize *src) { - memset(dst, 0, sizeof(*dst)); - Write16(dst->ws_row, src->ws_row); - Write16(dst->ws_col, src->ws_col); -} - -void XlatSigsetToLinux(uint8_t dst[8], const sigset_t *src) { - int i; - uint64_t x; - for (x = i = 0; i < 64; ++i) { - if (sigismember(src, i + 1)) { - x |= 1ull << i; - } - } - Write64(dst, x); -} - -void XlatLinuxToSigset(sigset_t *dst, const uint8_t src[8]) { - int i; - uint64_t x; - x = Read64(src); - sigemptyset(dst); - for (i = 0; i < 64; ++i) { - if ((1ull << i) & x) { - sigaddset(dst, i + 1); - } - } -} - -static int XlatTermiosCflag(int x) { - int r = 0; - if (x & 0x0001) r |= ISIG; - if (x & 0x0040) r |= CSTOPB; - if (x & 0x0080) r |= CREAD; - if (x & 0x0100) r |= PARENB; - if (x & 0x0200) r |= PARODD; - if (x & 0x0400) r |= HUPCL; - if (x & 0x0800) r |= CLOCAL; - if ((x & 0x0030) == 0x0010) { - r |= CS6; - } else if ((x & 0x0030) == 0x0020) { - r |= CS7; - } else if ((x & 0x0030) == 0x0030) { - r |= CS8; - } - return r; -} - -static int UnXlatTermiosCflag(int x) { - int r = 0; - if (x & ISIG) r |= 0x0001; - if (x & CSTOPB) r |= 0x0040; - if (x & CREAD) r |= 0x0080; - if (x & PARENB) r |= 0x0100; - if (x & PARODD) r |= 0x0200; - if (x & HUPCL) r |= 0x0400; - if (x & CLOCAL) r |= 0x0800; - if ((x & CSIZE) == CS5) { - r |= 0x0000; - } else if ((x & CSIZE) == CS6) { - r |= 0x0010; - } else if ((x & CSIZE) == CS7) { - r |= 0x0020; - } else if ((x & CSIZE) == CS8) { - r |= 0x0030; - } - return r; -} - -static int XlatTermiosLflag(int x) { - int r = 0; - if (x & 0x0001) r |= ISIG; - if (x & 0x0002) r |= ICANON; - if (x & 0x0008) r |= ECHO; - if (x & 0x0010) r |= ECHOE; - if (x & 0x0020) r |= ECHOK; - if (x & 0x0040) r |= ECHONL; - if (x & 0x0080) r |= NOFLSH; - if (x & 0x0100) r |= TOSTOP; - if (x & 0x8000) r |= IEXTEN; -#ifdef ECHOCTL - if (x & 0x0200) r |= ECHOCTL; -#endif -#ifdef ECHOPRT - if (x & 0x0400) r |= ECHOPRT; -#endif -#ifdef ECHOKE - if (x & 0x0800) r |= ECHOKE; -#endif -#ifdef FLUSHO - if (x & 0x1000) r |= FLUSHO; -#endif -#ifdef PENDIN - if (x & 0x4000) r |= PENDIN; -#endif -#ifdef XCASE - if (x & 0x0004) r |= XCASE; -#endif - return r; -} - -static int UnXlatTermiosLflag(int x) { - int r = 0; - if (x & ISIG) r |= 0x0001; - if (x & ICANON) r |= 0x0002; - if (x & ECHO) r |= 0x0008; - if (x & ECHOE) r |= 0x0010; - if (x & ECHOK) r |= 0x0020; - if (x & ECHONL) r |= 0x0040; - if (x & NOFLSH) r |= 0x0080; - if (x & TOSTOP) r |= 0x0100; - if (x & IEXTEN) r |= 0x8000; -#ifdef ECHOCTL - if (x & ECHOCTL) r |= 0x0200; -#endif -#ifdef ECHOPRT - if (x & ECHOPRT) r |= 0x0400; -#endif -#ifdef ECHOKE - if (x & ECHOKE) r |= 0x0800; -#endif -#ifdef FLUSHO - if (x & FLUSHO) r |= 0x1000; -#endif -#ifdef PENDIN - if (x & PENDIN) r |= 0x4000; -#endif -#ifdef XCASE - if (x & XCASE) r |= 0x0004; -#endif - return r; -} - -static int XlatTermiosIflag(int x) { - int r = 0; - if (x & 0x0001) r |= IGNBRK; - if (x & 0x0002) r |= BRKINT; - if (x & 0x0004) r |= IGNPAR; - if (x & 0x0008) r |= PARMRK; - if (x & 0x0010) r |= INPCK; - if (x & 0x0020) r |= ISTRIP; - if (x & 0x0040) r |= INLCR; - if (x & 0x0080) r |= IGNCR; - if (x & 0x0100) r |= ICRNL; - if (x & 0x0400) r |= IXON; - if (x & 0x0800) r |= IXANY; - if (x & 0x1000) r |= IXOFF; -#ifdef IMAXBEL - if (x & 0x2000) r |= IMAXBEL; -#endif -#ifdef IUTF8 - if (x & 0x4000) r |= IUTF8; -#endif -#ifdef IUCLC - if (x & 0x0200) r |= IUCLC; -#endif - return r; -} - -static int UnXlatTermiosIflag(int x) { - int r = 0; - if (x & IGNBRK) r |= 0x0001; - if (x & BRKINT) r |= 0x0002; - if (x & IGNPAR) r |= 0x0004; - if (x & PARMRK) r |= 0x0008; - if (x & INPCK) r |= 0x0010; - if (x & ISTRIP) r |= 0x0020; - if (x & INLCR) r |= 0x0040; - if (x & IGNCR) r |= 0x0080; - if (x & ICRNL) r |= 0x0100; - if (x & IXON) r |= 0x0400; - if (x & IXANY) r |= 0x0800; - if (x & IXOFF) r |= 0x1000; -#ifdef IMAXBEL - if (x & IMAXBEL) r |= 0x2000; -#endif -#ifdef IUTF8 - if (x & IUTF8) r |= 0x4000; -#endif -#ifdef IUCLC - if (x & IUCLC) r |= 0x0200; -#endif - return r; -} - -static int XlatTermiosOflag(int x) { - int r = 0; - if (x & 0x0001) r |= OPOST; -#ifdef ONLCR - if (x & 0x0004) r |= ONLCR; -#endif -#ifdef OCRNL - if (x & 0x0008) r |= OCRNL; -#endif -#ifdef ONOCR - if (x & 0x0010) r |= ONOCR; -#endif -#ifdef ONLRET - if (x & 0x0020) r |= ONLRET; -#endif -#ifdef OFILL - if (x & 0x0040) r |= OFILL; -#endif -#ifdef OFDEL - if (x & 0x0080) r |= OFDEL; -#endif -#ifdef NLDLY - if ((x & 0x0100) == 0x0000) { - r |= NL0; - } else if ((x & 0x0100) == 0x0100) { - r |= NL1; -#ifdef NL2 - } else if ((x & 0x0100) == 0x0000) { - r |= NL2; -#endif -#ifdef NL3 - } else if ((x & 0x0100) == 0x0000) { - r |= NL3; -#endif - } -#endif -#ifdef CRDLY - if ((x & 0x0600) == 0x0000) { - r |= CR0; - } else if ((x & 0x0600) == 0x0200) { - r |= CR1; - } else if ((x & 0x0600) == 0x0400) { - r |= CR2; - } else if ((x & 0x0600) == 0x0600) { - r |= CR3; - } -#endif -#ifdef TABDLY - if ((x & 0x1800) == 0x0000) { - r |= TAB0; -#ifdef TAB1 - } else if ((x & 0x1800) == 0x0800) { - r |= TAB1; -#endif -#ifdef TAB1 - } else if ((x & 0x1800) == 0x1000) { - r |= TAB2; -#endif - } else if ((x & 0x1800) == 0x1800) { - r |= TAB3; - } -#endif -#ifdef BSDLY - if ((x & 0x2000) == 0x0000) { - r |= BS0; - } else if ((x & 0x2000) == 0x2000) { - r |= BS1; - } -#endif -#ifdef VTBDLY - if ((x & 0x4000) == 0x0000) { - r |= VT0; - } else if ((x & 0x4000) == 0x4000) { - r |= VT1; - } -#endif -#ifdef FFBDLY - if ((x & 0x8000) == 0x0000) { - r |= FF0; - } else if ((x & 0x8000) == 0x8000) { - r |= FF1; - } -#endif -#ifdef OLCUC - if (x & 0x0002) r |= OLCUC; -#endif - return r; -} - -static int UnXlatTermiosOflag(int x) { - int r = 0; - if (x & OPOST) r |= 0x0001; -#ifdef ONLCR - if (x & ONLCR) r |= 0x0004; -#endif -#ifdef OCRNL - if (x & OCRNL) r |= 0x0008; -#endif -#ifdef ONOCR - if (x & ONOCR) r |= 0x0010; -#endif -#ifdef ONLRET - if (x & ONLRET) r |= 0x0020; -#endif -#ifdef OFILL - if (x & OFILL) r |= 0x0040; -#endif -#ifdef OFDEL - if (x & OFDEL) r |= 0x0080; -#endif -#ifdef NLDLY - if ((x & NLDLY) == NL0) { - r |= 0x0000; - } else if ((x & NLDLY) == NL1) { - r |= 0x0100; -#ifdef NL2 - } else if ((x & NLDLY) == NL2) { - r |= 0x0000; -#endif -#ifdef NL3 - } else if ((x & NLDLY) == NL3) { - r |= 0x0000; -#endif - } -#endif -#ifdef CRDLY - if ((x & CRDLY) == CR0) { - r |= 0x0000; - } else if ((x & CRDLY) == CR1) { - r |= 0x0200; - } else if ((x & CRDLY) == CR2) { - r |= 0x0400; - } else if ((x & CRDLY) == CR3) { - r |= 0x0600; - } -#endif -#ifdef TABDLY - if ((x & TABDLY) == TAB0) { - r |= 0x0000; -#ifdef TAB1 - } else if ((x & TABDLY) == TAB1) { - r |= 0x0800; -#endif -#ifdef TAB2 - } else if ((x & TABDLY) == TAB2) { - r |= 0x1000; -#endif - } else if ((x & TABDLY) == TAB3) { - r |= 0x1800; - } -#endif -#ifdef BSDLY - if ((x & BSDLY) == BS0) { - r |= 0x0000; - } else if ((x & BSDLY) == BS1) { - r |= 0x2000; - } -#endif -#ifdef VTDLY - if ((x & VTDLY) == VT0) { - r |= 0x0000; - } else if ((x & VTDLY) == VT1) { - r |= 0x4000; - } -#endif -#ifdef FFDLY - if ((x & FFDLY) == FF0) { - r |= 0x0000; - } else if ((x & FFDLY) == FF1) { - r |= 0x8000; - } -#endif -#ifdef OLCUC - if (x & OLCUC) r |= 0x0002; -#endif - return r; -} - -static void XlatTermiosCc(struct termios *dst, const struct termios_bits *src) { - dst->c_cc[VINTR] = src->c_cc[0]; - dst->c_cc[VQUIT] = src->c_cc[1]; - dst->c_cc[VERASE] = src->c_cc[2]; - dst->c_cc[VKILL] = src->c_cc[3]; - dst->c_cc[VEOF] = src->c_cc[4]; - dst->c_cc[VTIME] = src->c_cc[5]; - dst->c_cc[VMIN] = src->c_cc[6]; - dst->c_cc[VSTART] = src->c_cc[8]; - dst->c_cc[VSTOP] = src->c_cc[9]; - dst->c_cc[VSUSP] = src->c_cc[10]; - dst->c_cc[VEOL] = src->c_cc[11]; -#ifdef VSWTC - dst->c_cc[VSWTC] = src->c_cc[7]; -#endif -#ifdef VREPRINT - dst->c_cc[VREPRINT] = src->c_cc[12]; -#endif -#ifdef VDISCARD - dst->c_cc[VDISCARD] = src->c_cc[13]; -#endif -#ifdef VWERASE - dst->c_cc[VWERASE] = src->c_cc[14]; -#endif -#ifdef VLNEXT - dst->c_cc[VLNEXT] = src->c_cc[15]; -#endif -#ifdef VEOL2 - dst->c_cc[VEOL2] = src->c_cc[16]; -#endif -} - -static void UnXlatTermiosCc(struct termios_bits *dst, - const struct termios *src) { - dst->c_cc[0] = src->c_cc[VINTR]; - dst->c_cc[1] = src->c_cc[VQUIT]; - dst->c_cc[2] = src->c_cc[VERASE]; - dst->c_cc[3] = src->c_cc[VKILL]; - dst->c_cc[4] = src->c_cc[VEOF]; - dst->c_cc[5] = src->c_cc[VTIME]; - dst->c_cc[6] = src->c_cc[VMIN]; - dst->c_cc[8] = src->c_cc[VSTART]; - dst->c_cc[9] = src->c_cc[VSTOP]; - dst->c_cc[10] = src->c_cc[VSUSP]; - dst->c_cc[11] = src->c_cc[VEOL]; -#ifdef VSWTC - dst->c_cc[7] = src->c_cc[VSWTC]; -#endif -#ifdef VREPRINT - dst->c_cc[12] = src->c_cc[VREPRINT]; -#endif -#ifdef VDISCARD - dst->c_cc[13] = src->c_cc[VDISCARD]; -#endif -#ifdef VWERASE - dst->c_cc[14] = src->c_cc[VWERASE]; -#endif -#ifdef VLNEXT - dst->c_cc[15] = src->c_cc[VLNEXT]; -#endif -#ifdef VEOL2 - dst->c_cc[16] = src->c_cc[VEOL2]; -#endif -} - -void XlatLinuxToTermios(struct termios *dst, const struct termios_bits *src) { - memset(dst, 0, sizeof(*dst)); - dst->c_iflag = XlatTermiosIflag(Read32(src->c_iflag)); - dst->c_oflag = XlatTermiosOflag(Read32(src->c_oflag)); - dst->c_cflag = XlatTermiosCflag(Read32(src->c_cflag)); - dst->c_lflag = XlatTermiosLflag(Read32(src->c_lflag)); - XlatTermiosCc(dst, src); -} - -void XlatTermiosToLinux(struct termios_bits *dst, const struct termios *src) { - memset(dst, 0, sizeof(*dst)); - Write32(dst->c_iflag, UnXlatTermiosIflag(src->c_iflag)); - Write32(dst->c_oflag, UnXlatTermiosOflag(src->c_oflag)); - Write32(dst->c_cflag, UnXlatTermiosCflag(src->c_cflag)); - Write32(dst->c_lflag, UnXlatTermiosLflag(src->c_lflag)); - UnXlatTermiosCc(dst, src); -} diff --git a/tool/build/lib/xlat.h b/tool/build/lib/xlat.h deleted file mode 100644 index b69e826d1..000000000 --- a/tool/build/lib/xlat.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_XLAT_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_XLAT_H_ -#include "libc/calls/struct/itimerval.h" -#include "libc/calls/struct/rusage.h" -#include "libc/calls/struct/sigset.h" -#include "libc/calls/struct/stat.h" -#include "libc/calls/struct/termios.h" -#include "libc/calls/struct/winsize.h" -#include "libc/sock/struct/sockaddr.h" -#include "tool/build/lib/bits.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -int UnXlatSicode(int, int); -int UnXlatSignal(int); -int XlatAccess(int); -int XlatAdvice(int); -int XlatAtf(int); -int XlatClock(int); -int XlatErrno(int); -int XlatFcntlArg(int); -int XlatFcntlCmd(int); -int XlatLock(int); -int XlatMapFlags(int); -int XlatMsyncFlags(int); -int XlatOpenFlags(int); -int XlatOpenMode(int); -int XlatRusage(int); -int XlatSig(int); -int XlatSignal(int); -int XlatSocketFamily(int); -int XlatSocketFlags(int); -int XlatSocketLevel(int); -int XlatSocketOptname(int, int); -int XlatSocketProtocol(int); -int XlatSocketType(int); -int XlatWait(int); - -void XlatSockaddrToHost(struct sockaddr_in *, const struct sockaddr_in_bits *); -void XlatSockaddrToLinux(struct sockaddr_in_bits *, const struct sockaddr_in *); -void XlatStatToLinux(struct stat_bits *, const struct stat *); -void XlatRusageToLinux(struct rusage_bits *, const struct rusage *); -void XlatItimervalToLinux(struct itimerval_bits *, const struct itimerval *); -void XlatLinuxToItimerval(struct itimerval *, const struct itimerval_bits *); -void XlatLinuxToTermios(struct termios *, const struct termios_bits *); -void XlatTermiosToLinux(struct termios_bits *, const struct termios *); -void XlatWinsizeToLinux(struct winsize_bits *, const struct winsize *); -void XlatSigsetToLinux(uint8_t[8], const sigset_t *); -void XlatLinuxToSigset(sigset_t *, const uint8_t[8]); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_XLAT_H_ */ diff --git a/tool/build/lib/xlaterrno.c b/tool/build/lib/xlaterrno.c deleted file mode 100644 index 640756702..000000000 --- a/tool/build/lib/xlaterrno.c +++ /dev/null @@ -1,40 +0,0 @@ -/*-*- 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/errno.h" -#include "libc/mem/mem.h" - -struct thatispacked LinuxErrno { - int32_t local; - uint8_t linux; -}; - -extern const struct LinuxErrno kLinuxErrnos[]; - -/** - * Turns local errno into Linux errno. - */ -int XlatErrno(int local) { - int i; - for (i = 0; kLinuxErrnos[i].local; ++i) { - if (local == *(int *)((intptr_t)kLinuxErrnos + kLinuxErrnos[i].local)) { - return kLinuxErrnos[i].linux; - } - } - return ENOSYS; -} diff --git a/tool/build/lib/xmmtype.c b/tool/build/lib/xmmtype.c deleted file mode 100644 index 37e574bf6..000000000 --- a/tool/build/lib/xmmtype.c +++ /dev/null @@ -1,186 +0,0 @@ -/*-*- 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 "tool/build/lib/modrm.h" -#include "tool/build/lib/xmmtype.h" - -static void UpdateXmmTypes(struct Machine *m, struct XmmType *xt, int regtype, - int rmtype) { - xt->type[RexrReg(m->xedd->op.rde)] = regtype; - if (IsModrmRegister(m->xedd->op.rde)) { - xt->type[RexbRm(m->xedd->op.rde)] = rmtype; - } -} - -static void UpdateXmmSizes(struct Machine *m, struct XmmType *xt, int regsize, - int rmsize) { - xt->size[RexrReg(m->xedd->op.rde)] = regsize; - if (IsModrmRegister(m->xedd->op.rde)) { - xt->size[RexbRm(m->xedd->op.rde)] = rmsize; - } -} - -void UpdateXmmType(struct Machine *m, struct XmmType *xt) { - switch (m->xedd->op.dispatch) { - case 0x110: - case 0x111: // MOVSS,MOVSD - if (Rep(m->xedd->op.rde) == 3) { - UpdateXmmTypes(m, xt, kXmmFloat, kXmmFloat); - } else if (Rep(m->xedd->op.rde) == 2) { - UpdateXmmTypes(m, xt, kXmmDouble, kXmmDouble); - } - break; - case 0x12E: // UCOMIS - case 0x12F: // COMIS - case 0x151: // SQRT - case 0x152: // RSQRT - case 0x153: // RCP - case 0x158: // ADD - case 0x159: // MUL - case 0x15C: // SUB - case 0x15D: // MIN - case 0x15E: // DIV - case 0x15F: // MAX - case 0x1C2: // CMP - if (Osz(m->xedd->op.rde) || Rep(m->xedd->op.rde) == 2) { - UpdateXmmTypes(m, xt, kXmmDouble, kXmmDouble); - } else { - UpdateXmmTypes(m, xt, kXmmFloat, kXmmFloat); - } - break; - case 0x12A: // CVTPI2PS,CVTSI2SS,CVTPI2PD,CVTSI2SD - if (Osz(m->xedd->op.rde) || Rep(m->xedd->op.rde) == 2) { - UpdateXmmSizes(m, xt, 8, 4); - UpdateXmmTypes(m, xt, kXmmDouble, kXmmIntegral); - } else { - UpdateXmmSizes(m, xt, 4, 4); - UpdateXmmTypes(m, xt, kXmmFloat, kXmmIntegral); - } - break; - case 0x15A: // CVT{P,S}{S,D}2{P,S}{S,D} - if (Osz(m->xedd->op.rde) || Rep(m->xedd->op.rde) == 2) { - UpdateXmmTypes(m, xt, kXmmFloat, kXmmDouble); - } else { - UpdateXmmTypes(m, xt, kXmmDouble, kXmmFloat); - } - break; - case 0x15B: // CVT{,T}{DQ,PS}2{PS,DQ} - UpdateXmmSizes(m, xt, 4, 4); - if (Osz(m->xedd->op.rde) || Rep(m->xedd->op.rde) == 3) { - UpdateXmmTypes(m, xt, kXmmIntegral, kXmmFloat); - } else { - UpdateXmmTypes(m, xt, kXmmFloat, kXmmIntegral); - } - break; - case 0x17C: // HADD - case 0x17D: // HSUB - case 0x1D0: // ADDSUB - if (Osz(m->xedd->op.rde)) { - UpdateXmmTypes(m, xt, kXmmDouble, kXmmDouble); - } else { - UpdateXmmTypes(m, xt, kXmmFloat, kXmmFloat); - } - break; - case 0x164: // PCMPGTB - case 0x174: // PCMPEQB - case 0x1D8: // PSUBUSB - case 0x1DA: // PMINUB - case 0x1DC: // PADDUSB - case 0x1DE: // PMAXUB - case 0x1E0: // PAVGB - case 0x1E8: // PSUBSB - case 0x1EC: // PADDSB - case 0x1F8: // PSUBB - case 0x1FC: // PADDB - UpdateXmmSizes(m, xt, 1, 1); - UpdateXmmTypes(m, xt, kXmmIntegral, kXmmIntegral); - break; - case 0x165: // PCMPGTW - case 0x175: // PCMPEQW - case 0x171: // PSRLW,PSRAW,PSLLW - case 0x1D1: // PSRLW - case 0x1D5: // PMULLW - case 0x1D9: // PSUBUSW - case 0x1DD: // PADDUSW - case 0x1E1: // PSRAW - case 0x1E3: // PAVGW - case 0x1E4: // PMULHUW - case 0x1E5: // PMULHW - case 0x1E9: // PSUBSW - case 0x1EA: // PMINSW - case 0x1ED: // PADDSW - case 0x1EE: // PMAXSW - case 0x1F1: // PSLLW - case 0x1F6: // PSADBW - case 0x1F9: // PSUBW - case 0x1FD: // PADDW - UpdateXmmSizes(m, xt, 2, 2); - UpdateXmmTypes(m, xt, kXmmIntegral, kXmmIntegral); - break; - case 0x166: // PCMPGTD - case 0x176: // PCMPEQD - case 0x172: // PSRLD,PSRAD,PSLLD - case 0x1D2: // PSRLD - case 0x1E2: // PSRAD - case 0x1F2: // PSLLD - case 0x1FA: // PSUBD - case 0x1FE: // PADDD - UpdateXmmSizes(m, xt, 4, 4); - UpdateXmmTypes(m, xt, kXmmIntegral, kXmmIntegral); - break; - case 0x173: // PSRLQ,PSRLQ,PSRLDQ,PSLLQ,PSLLDQ - case 0x1D3: // PSRLQ - case 0x1D4: // PADDQ - case 0x1F3: // PSLLQ - case 0x1F4: // PMULUDQ - case 0x1FB: // PSUBQ - UpdateXmmSizes(m, xt, 8, 8); - UpdateXmmTypes(m, xt, kXmmIntegral, kXmmIntegral); - break; - case 0x16B: // PACKSSDW - case 0x1F5: // PMADDWD - UpdateXmmSizes(m, xt, 4, 2); - UpdateXmmTypes(m, xt, kXmmIntegral, kXmmIntegral); - break; - case 0x163: // PACKSSWB - case 0x167: // PACKUSWB - UpdateXmmSizes(m, xt, 1, 2); - UpdateXmmTypes(m, xt, kXmmIntegral, kXmmIntegral); - break; - case 0x128: // MOVAPS Vps Wps - if (IsModrmRegister(m->xedd->op.rde)) { - xt->type[RexrReg(m->xedd->op.rde)] = xt->type[RexbRm(m->xedd->op.rde)]; - xt->size[RexrReg(m->xedd->op.rde)] = xt->size[RexbRm(m->xedd->op.rde)]; - } - break; - case 0x129: // MOVAPS Wps Vps - if (IsModrmRegister(m->xedd->op.rde)) { - xt->type[RexbRm(m->xedd->op.rde)] = xt->type[RexrReg(m->xedd->op.rde)]; - xt->size[RexbRm(m->xedd->op.rde)] = xt->size[RexrReg(m->xedd->op.rde)]; - } - break; - case 0x16F: // MOVDQA Vdq Wdq - if (Osz(m->xedd->op.rde) && IsModrmRegister(m->xedd->op.rde)) { - xt->type[RexrReg(m->xedd->op.rde)] = xt->type[RexbRm(m->xedd->op.rde)]; - xt->size[RexrReg(m->xedd->op.rde)] = xt->size[RexbRm(m->xedd->op.rde)]; - } - break; - default: - return; - } -} diff --git a/tool/build/lib/xmmtype.h b/tool/build/lib/xmmtype.h deleted file mode 100644 index 00dc45760..000000000 --- a/tool/build/lib/xmmtype.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_XMMTYPE_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_XMMTYPE_H_ -#include "tool/build/lib/machine.h" - -#define kXmmIntegral 0 -#define kXmmDouble 1 -#define kXmmFloat 2 - -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -struct XmmType { - uint8_t type[16]; - uint8_t size[16]; -}; - -void UpdateXmmType(struct Machine *, struct XmmType *); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_XMMTYPE_H_ */ diff --git a/tool/build/tinyemu.c b/tool/build/tinyemu.c deleted file mode 100644 index 2fa3f6ef2..000000000 --- a/tool/build/tinyemu.c +++ /dev/null @@ -1,60 +0,0 @@ -/*-*- 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/calls.h" -#include "libc/log/check.h" -#include "libc/stdio/stdio.h" -#include "libc/sysv/consts/ex.h" -#include "libc/sysv/consts/fileno.h" -#include "libc/x/x.h" -#include "tool/build/lib/loader.h" -#include "tool/build/lib/machine.h" -#include "tool/build/lib/syscall.h" - -static void AddHostFd(struct Machine *m, int fd) { - int i = m->fds.i++; - CHECK_NE(-1, (m->fds.p[i].fd = dup(fd))); - m->fds.p[i].cb = &kMachineFdCbHost; -} - -int main(int argc, char *argv[]) { - int rc; - struct Elf elf; - struct Machine *m; - if (argc < 2) { - fputs("Usage: ", stderr); - fputs(argv[0], stderr); - fputs(" PROG [ARGS...]\n", stderr); - return EX_USAGE; - } - m = NewMachine(); - m->mode = XED_MACHINE_MODE_LONG_64; - LoadProgram(m, argv[1], argv + 2, environ, &elf); - m->fds.p = xcalloc((m->fds.n = 8), sizeof(struct MachineFd)); - AddHostFd(m, STDIN_FILENO); - AddHostFd(m, STDOUT_FILENO); - AddHostFd(m, STDERR_FILENO); - if (!(rc = setjmp(m->onhalt))) { - for (;;) { - LoadInstruction(m); - ExecuteInstruction(m); - } - } else { - return rc; - } -} diff --git a/tool/build/unbuffer.c b/tool/build/unbuffer.c index 1d8224ac1..3dd6ab9c6 100644 --- a/tool/build/unbuffer.c +++ b/tool/build/unbuffer.c @@ -96,8 +96,8 @@ int main(int argc, char *argv[]) { wsz.ws_col = 80; wsz.ws_row = 45; - if (ioctl(1, TCGETS, &tio)) { - perror("tcgets"); + if (tcgetattr(1, &tio)) { + perror("tcgetattr"); return __COUNTER__ + 1; }