Remove blinkenlights

New home: https://github.com/jart/blink
This commit is contained in:
Justine Tunney 2023-06-11 03:10:58 -07:00
parent 50d8d953ce
commit 06b749ae03
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
130 changed files with 2 additions and 26665 deletions

View file

@ -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__ */

View file

@ -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__ */

View file

@ -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__ */

View file

@ -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);
}

View file

@ -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__ */

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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));
}

View file

@ -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,
};

View file

@ -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_ */

View file

@ -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__ */

View file

@ -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_ */

View file

@ -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) = "\
-\r\n\
-\r\n\
-\r\n\
-\r\n\
-\r\n\
-\r\n\
-\r\n\
-\r\n\
-";
static const char widelatin_golden[] = "\
- \
- \
- \
- \
- \
- \
- \
- \
- \
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
";
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);
}

View file

@ -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));
}

File diff suppressed because it is too large Load diff

View file

@ -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)

View file

@ -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;
}

View file

@ -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:

View file

@ -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);
}

View file

@ -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();
}

View file

@ -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);
}

View file

@ -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_ */

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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_ */

View file

@ -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;
}

View file

@ -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_ */

View file

@ -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");

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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

View file

@ -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)
*(.*)
}
}

View file

@ -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)

View file

@ -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/ : {
*(.*)
}
}

View file

@ -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_ */

View file

@ -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();
}
}

View file

@ -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_ */

View file

@ -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;
}
}

View file

@ -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_ */

View file

@ -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);
}

View file

@ -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_ */

View file

@ -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);
}

View file

@ -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_ */

View file

@ -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;
}
}

View file

@ -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_ */

View file

@ -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;
}

View file

@ -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_ */

View file

@ -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};

View file

@ -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");
}
}

View file

@ -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_ */

View file

@ -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);
}

View file

@ -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_ */

View file

@ -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);
}

View file

@ -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_ */

View file

@ -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);
}

View file

@ -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_ */

View file

@ -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);
}
}

View file

@ -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));
}

View file

@ -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_ */

View file

@ -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;
}

View file

@ -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); */
}

View file

@ -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;
}

File diff suppressed because it is too large Load diff

View file

@ -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);
}

View file

@ -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_ */

View file

@ -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;
}
}

View file

@ -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_ */

View file

@ -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;
}

View file

@ -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_ */

File diff suppressed because it is too large Load diff

View file

@ -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_ */

View file

@ -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;
}

View file

@ -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_ */

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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_ */

View file

@ -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;
}

View file

@ -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_ */

View file

@ -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;
}

View file

@ -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_ */

View file

@ -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);
}
}
}

View file

@ -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_ */

File diff suppressed because it is too large Load diff

View file

@ -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_ */

View file

@ -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], ' ');
}
}
}
}

View file

@ -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_ */

View file

@ -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;
}

View file

@ -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_ */

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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_ */

View file

@ -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);
}
}

View file

@ -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_ */

View file

@ -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);
}
}

View file

@ -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_ */

View file

@ -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("");
}
}

File diff suppressed because it is too large Load diff

View file

@ -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_ */

View file

@ -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_ */

Some files were not shown because too many files have changed in this diff Show more