Make more improvements

This change includes many bug fixes, for the NT polyfills, strings,
memory, boot, and math libraries which were discovered by adding more
tools for recreational programming, such as PC emulation. Lemon has also
been vendored because it works so well at parsing languages.
This commit is contained in:
Justine Tunney 2020-09-28 01:13:56 -07:00
parent 416fd86676
commit 23d333c090
201 changed files with 14558 additions and 3082 deletions

View file

@ -47,11 +47,10 @@ uint8_t *GetSegment(struct Machine *m, uint32_t rde, int s) {
uint64_t AddSegment(struct Machine *m, uint32_t rde, uint64_t i, uint8_t s[8]) {
if (!Sego(rde)) {
i += Read64(s);
return i + Read64(s);
} else {
i += Read64(GetSegment(m, rde, Sego(rde) - 1));
return i + Read64(GetSegment(m, rde, Sego(rde) - 1));
}
return i;
}
uint64_t DataSegment(struct Machine *m, uint32_t rde, uint64_t i) {

37
tool/build/lib/breg.c Normal file
View file

@ -0,0 +1,37 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#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

@ -17,9 +17,9 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "dsp/tty/tty.h"
#include "libc/alg/arraylist2.h"
#include "libc/calls/calls.h"
#include "libc/errno.h"
#include "libc/fmt/fmt.h"
#include "libc/mem/mem.h"
#include "libc/str/tpencode.h"
@ -58,5 +58,22 @@ void AppendFmt(struct Buffer *b, const char *fmt, ...) {
* Writes buffer until completion, interrupt, or error occurs.
*/
ssize_t WriteBuffer(struct Buffer *b, int fd) {
return ttywrite(fd, b->p, b->i);
char *p;
ssize_t rc;
size_t wrote, n;
p = b->p;
n = b->i;
do {
TryAgain:
if ((rc = write(fd, p, n)) != -1) {
wrote = rc;
p += wrote;
n -= wrote;
} else if (errno == EINTR) {
goto TryAgain;
} else {
return -1;
}
} while (n);
return 0;
}

View file

@ -25,7 +25,6 @@ TOOL_BUILD_LIB_A_OBJS = \
$(TOOL_BUILD_LIB_A_SRCS_C:%.c=o/$(MODE)/%.o)
TOOL_BUILD_LIB_A_DIRECTDEPS = \
DSP_TTY \
LIBC_ALG \
LIBC_BITS \
LIBC_CONV \

View file

@ -17,24 +17,37 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/conv/itoa.h"
#include "libc/macros.h"
#include "libc/str/str.h"
#include "tool/build/lib/buffer.h"
#include "tool/build/lib/cga.h"
static const uint8_t kCgaToAnsi[] = {30, 34, 32, 36, 31, 35, 33, 37,
90, 94, 92, 96, 91, 95, 93, 97};
/* 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 += uint64toarray_radix10(kCgaToAnsi[(bgfg & 0xF0) >> 4] + 10, p);
*p++ = ';';
p += uint64toarray_radix10(kCgaToAnsi[bgfg & 0x0F], p);
*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) {
a = v[y][x][1];
AppendFmt(&p->lines[y], "\e[%d;%dm", kCgaToAnsi[a & 0x0F],
kCgaToAnsi[(a & 0xF0) >> 4] + 10);
AppendData(&p->lines[y], buf, FormatCga((a = v[y][x][1]), buf));
}
AppendWide(&p->lines[y], kCp437[v[y][x][0]]);
}

View file

@ -5,6 +5,7 @@
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) */

View file

@ -35,32 +35,32 @@ void OpCpuid(struct Machine *m, uint32_t rde) {
dx = 'o' | 's' << 8 | 'm' << 16 | 'o' << 24;
break;
case 1:
cx |= 1 << 0; /* sse3 */
cx |= 0 << 1; /* pclmulqdq */
cx |= 1 << 9; /* ssse3 */
cx |= 1 << 23; /* popcnt */
cx |= 0 << 30; /* rdrnd */
cx |= 0 << 25; /* aes */
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 << 25; /* sse */
dx |= 1 << 26; /* sse2 */
cx |= 1 << 0; // sse3
cx |= 0 << 1; // pclmulqdq
cx |= 1 << 9; // ssse3
cx |= 1 << 23; // popcnt
cx |= 0 << 30; // rdrnd
cx |= 0 << 25; // aes
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 << 25; // sse
dx |= 1 << 26; // sse2
break;
case 7:
bx |= 1 << 9; /* erms */
bx |= 1 << 9; // erms
break;
case 0x80000001:
cx |= 1 << 0; /* lahf/sahf */
dx |= 1 << 11; /* syscall */
dx |= 1 << 29; /* long mode */
cx |= 1 << 0; // lahf
dx |= 1 << 11; // syscall
dx |= 1 << 29; // long
break;
case 0x80000007:
dx |= 1 << 8; /* invtsc */
dx |= 1 << 8; // invtsc
break;
default:
break;

94
tool/build/lib/demangle.c Normal file
View file

@ -0,0 +1,94 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/hefty/spawn.h"
#include "libc/macros.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "tool/build/lib/demangle.h"
struct CxxFilt {
int pid;
int fds[3];
} g_cxxfilt;
void CloseCxxFilt(void) {
close(g_cxxfilt.fds[0]);
close(g_cxxfilt.fds[1]);
g_cxxfilt.pid = -1;
}
void SpawnCxxFilt(void) {
int pid;
char path[PATH_MAX];
if (commandv("c++filt", path)) {
g_cxxfilt.fds[0] = -1;
g_cxxfilt.fds[1] = -1;
g_cxxfilt.fds[2] = 2;
if ((pid = spawnve(0, g_cxxfilt.fds, path, (char *const[]){"c++filt", NULL},
environ)) != -1) {
atexit(CloseCxxFilt);
}
} else {
pid = -1;
}
g_cxxfilt.pid = pid;
}
char *DemangleCxxFilt(char *p, const char *symbol) {
int n;
char buf[512];
bool iscomplicated;
if (!g_cxxfilt.pid) SpawnCxxFilt();
if (g_cxxfilt.pid == -1) return NULL;
if ((n = strlen(symbol)) >= ARRAYLEN(buf)) return NULL;
memcpy(buf, symbol, n);
buf[n] = '\n';
write(g_cxxfilt.fds[0], buf, n + 1);
n = read(g_cxxfilt.fds[1], buf, ARRAYLEN(buf));
if (n > 1 && buf[n - 1] == '\n') {
if (buf[n - 2] == '\r') --n;
--n;
iscomplicated = memchr(buf, ' ', n) || memchr(buf, '(', n);
if (iscomplicated) *p++ = '"';
p = mempcpy(p, buf, n);
if (iscomplicated) *p++ = '"';
*p = '\0';
return p;
} else {
CloseCxxFilt();
return NULL;
}
}
/**
* Decrypts C++ symbol.
*
* Decoding these takes roughly the same lines of code as an entire
* x86_64 disassembler. That's just for the GNU encoding scheme. So
* what we'll do, is just offload this work to the c++filt program.
*/
char *Demangle(char *p, const char *symbol) {
char *r;
if (startswith(symbol, "_Z")) {
if ((r = DemangleCxxFilt(p, symbol))) return r;
}
return stpcpy(p, symbol);
}

10
tool/build/lib/demangle.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_DEMANGLE_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_DEMANGLE_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
char *Demangle(char *, const char *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_DEMANGLE_H_ */

View file

@ -33,7 +33,9 @@
#include "libc/str/tpencode.h"
#include "third_party/xed/x86.h"
#include "tool/build/lib/case.h"
#include "tool/build/lib/demangle.h"
#include "tool/build/lib/dis.h"
#include "tool/build/lib/high.h"
#include "tool/build/lib/memory.h"
#include "tool/build/lib/modrm.h"
@ -73,93 +75,99 @@ static char *DisOctets(char *p, const uint8_t *d, size_t n) {
}
static char *DisByte(char *p, const uint8_t *d, size_t n) {
if (g_dis_high) p = DisHigh(p, g_dis_high->keyword);
p = HighStart(p, g_high.keyword);
p = DisColumn(stpcpy(p, ".byte"), p, NAMELEN);
if (g_dis_high) p = DisHigh(p, -1);
p = HighEnd(p);
p = DisOctets(p, d, n);
return p;
}
static char *DisError(struct DisBuilder b, char *p) {
p = DisColumn(DisByte(p, b.xedd->bytes, MIN(15, b.xedd->length)), p, CODELEN);
if (g_dis_high) p = DisHigh(p, g_dis_high->comment);
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, b.xedd->op.error));
if (g_dis_high) p = DisHigh(p, -1);
p = stpcpy(p, indexdoublenulstring(kXedErrorNames, d->xedd->op.error));
p = HighEnd(p);
*p = '\0';
return p;
}
static char *DisAddr(struct DisBuilder b, char *p) {
if (INT_MIN <= b.addr && b.addr <= INT_MAX) {
return p + uint64toarray_fixed16(b.addr, p, 32);
static char *DisAddr(struct Dis *d, char *p) {
if (INT32_MIN <= d->addr && d->addr <= INT32_MAX) {
return p + uint64toarray_fixed16(d->addr, p, 32);
} else {
return p + uint64toarray_fixed16(b.addr, p, 48);
return p + uint64toarray_fixed16(d->addr, p, 48);
}
}
static char *DisRaw(struct DisBuilder b, char *p) {
static char *DisRaw(struct Dis *d, char *p) {
long i;
for (i = 0; i < PFIXLEN - MIN(PFIXLEN, b.xedd->op.PIVOTOP); ++i) {
for (i = 0; i < PFIXLEN - MIN(PFIXLEN, d->xedd->op.PIVOTOP); ++i) {
*p++ = ' ';
*p++ = ' ';
}
for (i = 0; i < MIN(15, b.xedd->length); ++i) {
if (i == b.xedd->op.PIVOTOP) *p++ = ' ';
*p++ = "0123456789abcdef"[(b.xedd->bytes[i] & 0xf0) >> 4];
*p++ = "0123456789abcdef"[b.xedd->bytes[i] & 0x0f];
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];
}
*p = '\0';
return p;
}
static char *DisCode(struct DisBuilder b, char *p) {
static char *DisCode(struct Dis *d, char *p) {
char optspecbuf[128];
if (!b.xedd->op.error) {
return DisInst(b, p, DisSpec(b.xedd, optspecbuf));
if (!d->xedd->op.error) {
return DisInst(d, p, DisSpec(d->xedd, optspecbuf));
} else {
return DisError(b, p);
return DisError(d, p);
}
}
static char *DisLineCode(struct DisBuilder b, char *p) {
p = DisColumn(DisAddr(b, p), p, ADDRLEN);
p = DisColumn(DisRaw(b, p), p, PFIXLEN * 2 + 1 + BYTELEN * 2);
p = DisCode(b, p);
static char *DisLineCode(struct Dis *d, char *p) {
p = DisColumn(DisAddr(d, p), p, ADDRLEN);
p = DisColumn(DisRaw(d, p), p, PFIXLEN * 2 + 1 + BYTELEN * 2);
p = DisCode(d, p);
return p;
}
static char *DisLineData(struct DisBuilder b, char *p, const uint8_t *d,
size_t n) {
static char *DisLineData(struct Dis *d, char *p, const uint8_t *b, size_t n) {
size_t i;
p = DisColumn(DisAddr(b, p), p, ADDRLEN);
p = DisColumn(DisByte(p, d, n), p, 64);
if (g_dis_high) p = DisHigh(p, g_dis_high->comment);
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) p += tpencode(p, 8, bing(d[i], 0), false);
if (g_dis_high) p = DisHigh(p, -1);
for (i = 0; i < n; ++i) p += tpencode(p, 8, bing(b[i], 0), false);
p = HighEnd(p);
*p = '\0';
return p;
}
static char *DisLabel(struct DisBuilder b, char *p, const char *name) {
p = DisColumn(DisAddr(b, p), p, ADDRLEN);
if (g_dis_high) p = DisHigh(p, g_dis_high->label);
p = stpcpy(p, name);
if (g_dis_high) p = DisHigh(p, -1);
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);
p = HighEnd(p);
*p++ = ':';
*p = '\0';
return p;
}
long DisFind(struct Dis *d, int64_t addr) {
long i;
for (i = 0; i < d->ops.i; ++i) {
if (addr >= d->ops.p[i].addr &&
addr < d->ops.p[i].addr + d->ops.p[i].size) {
return i;
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;
@ -181,8 +189,8 @@ static long DisOne(struct Dis *d, struct Machine *m, int64_t addr) {
op.addr = addr;
op.size = 0;
op.active = true;
DisLabel((struct DisBuilder){d, d->xedd, addr}, d->buf,
d->syms.stab + d->syms.p[symbol].name);
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);
}
@ -238,7 +246,8 @@ const char *DisGetLine(struct Dis *d, struct Machine *m, size_t i) {
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);
p = DisLineCode((struct DisBuilder){d, d->xedd, d->ops.p[i].addr}, d->buf);
d->addr = d->ops.p[i].addr;
p = DisLineCode(d, d->buf);
CHECK_LT(p - d->buf, sizeof(d->buf));
return d->buf;
}

View file

@ -45,25 +45,10 @@ struct Dis {
} * p;
} edges;
struct XedDecodedInst xedd[1];
uint64_t addr;
char buf[512];
};
struct DisBuilder {
struct Dis *dis;
struct XedDecodedInst *xedd;
int64_t addr;
};
struct DisHigh {
uint8_t keyword;
uint8_t reg;
uint8_t literal;
uint8_t label;
uint8_t comment;
};
extern struct DisHigh *g_dis_high;
long Dis(struct Dis *, struct Machine *, int64_t, int);
long DisFind(struct Dis *, int64_t);
void DisFree(struct Dis *);
@ -74,10 +59,9 @@ 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 *);
char *DisInst(struct DisBuilder, char *, const char *);
char *DisArg(struct DisBuilder, char *, const char *);
char *DisHigh(char *, int);
const char *DisGetLine(struct Dis *, struct Machine *, size_t);
COSMOPOLITAN_C_END_

View file

@ -24,23 +24,27 @@
#include "libc/log/check.h"
#include "libc/macros.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 kScale[4][4] = {"", ",2", ",4", ",8"};
static const char kSegName[8][3] = {"es", "cs", "ss", "ds", "fs", "gs"};
static const char kPuttingOnTheRiz[2][4] = {"eiz", "riz"};
static const char kPuttingOnTheRip[2][4] = {"eip", "rip"};
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 kRegisterName8[2][2][8][5] = {
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 kRegisterName[2][2][2][8][5] = {
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"},
@ -51,43 +55,39 @@ static const char kRegisterName[2][2][2][8][5] = {
{"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}}},
};
static const char kControlName[8][4] = {
"cr0", "wut", "cr2", "cr3", "cr4", "wut", "wut", "wut",
};
static int64_t RipRelative(struct DisBuilder b, int64_t d) {
return b.addr + b.xedd->length + d;
static int64_t RipRelative(struct Dis *d, int64_t i) {
return d->addr + d->xedd->length + i;
}
static const char *GetAddrReg(struct DisBuilder b, uint32_t rde, uint8_t x,
static const char *GetAddrReg(struct Dis *d, uint32_t rde, uint8_t x,
uint8_t r) {
return kRegisterName[Eamode(rde) == XED_MODE_REAL]
[Eamode(rde) == XED_MODE_LONG][x & 1][r & 7];
return kGreg[Eamode(rde) == XED_MODE_REAL][Eamode(rde) == XED_MODE_LONG]
[x & 1][r & 7];
}
static char *DisRegister(char *p, const char *s) {
if (g_dis_high) p = DisHigh(p, g_dis_high->reg);
p = HighStart(p, g_high.reg);
*p++ = '%';
p = stpcpy(p, s);
if (g_dis_high) p = DisHigh(p, -1);
p = HighEnd(p);
return p;
}
static char *DisComment(char *p, const char *s) {
if (g_dis_high) p = DisHigh(p, g_dis_high->comment);
p = HighStart(p, g_high.comment);
p = stpcpy(p, s);
if (g_dis_high) p = DisHigh(p, -1);
p = HighEnd(p);
return p;
}
static char *DisRegisterByte(struct DisBuilder b, uint32_t rde, char *p, bool g,
static char *DisRegisterByte(struct Dis *d, uint32_t rde, char *p, bool g,
int r) {
return DisRegister(p, kRegisterName8[g][Rex(rde)][r]);
return DisRegister(p, kBreg[g][Rex(rde)][r]);
}
static char *DisRegisterWord(struct DisBuilder b, uint32_t rde, char *p, bool g,
static char *DisRegisterWord(struct Dis *d, uint32_t rde, char *p, bool g,
int r) {
return DisRegister(p, kRegisterName[Osz(rde)][Rexw(rde)][g][r]);
return DisRegister(p, kGreg[Osz(rde)][Rexw(rde)][g][r]);
}
static char *DisInt(char *p, int64_t x) {
@ -106,14 +106,14 @@ static char *DisInt(char *p, int64_t x) {
return p;
}
static char *DisSym(struct DisBuilder b, char *p, int64_t addr) {
static char *DisSym(struct Dis *d, char *p, int64_t addr) {
long sym;
int64_t addend;
const char *name;
if ((sym = DisFindSym(b.dis, addr)) != -1 && b.dis->syms.p[sym].name) {
addend = addr - b.dis->syms.p[sym].addr;
name = b.dis->syms.stab + b.dis->syms.p[sym].name;
p = stpcpy(p, name);
if ((sym = DisFindSym(d, addr)) != -1 && d->syms.p[sym].name) {
addend = addr - d->syms.p[sym].addr;
name = d->syms.stab + d->syms.p[sym].name;
p = Demangle(p, name);
if (addend) {
*p++ = '+';
p = DisInt(p, addend);
@ -124,79 +124,69 @@ static char *DisSym(struct DisBuilder b, char *p, int64_t addr) {
}
}
static char *DisSymLiteral(struct DisBuilder b, char *p, uint64_t x) {
static char *DisSymLiteral(struct Dis *d, char *p, uint64_t x) {
*p++ = '$';
if (g_dis_high) p = DisHigh(p, g_dis_high->literal);
p = DisSym(b, p, x);
if (g_dis_high) p = DisHigh(p, -1);
p = HighStart(p, g_high.literal);
p = DisSym(d, p, x);
p = HighEnd(p);
return p;
}
static char *DisXmm(struct DisBuilder b, uint32_t rde, char *p, const char *s,
int reg) {
if (g_dis_high) p = DisHigh(p, g_dis_high->reg);
*p++ = '%';
p = stpcpy(p, s);
p += uint64toarray_radix10(Rexr(rde) << 3 | reg, p);
if (g_dis_high) p = DisHigh(p, -1);
return p;
static char *DisGvqp(struct Dis *d, uint32_t rde, char *p) {
return DisRegisterWord(d, rde, p, Rexr(rde), ModrmReg(rde));
}
static char *DisGvqp(struct DisBuilder b, uint32_t rde, char *p) {
return DisRegisterWord(b, 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 *DisGdqp(struct DisBuilder b, uint32_t rde, char *p) {
return DisRegister(p, kRegisterName[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 *DisGb(struct DisBuilder b, uint32_t rde, char *p) {
return DisRegisterByte(b, rde, p, Rexr(rde), ModrmReg(rde));
}
static char *DisSego(struct DisBuilder b, uint32_t rde, char *p) {
static char *DisSego(struct Dis *d, uint32_t rde, char *p) {
int seg;
seg = Sego(rde) ? Sego(rde) : b.xedd->op.hint;
seg = Sego(rde) ? Sego(rde) : d->xedd->op.hint;
if (seg) {
p = DisRegister(p, kSegName[seg - 1]);
p = DisRegister(p, kSeg[seg - 1]);
*p++ = ':';
}
return p;
}
static char *DisM(struct DisBuilder b, uint32_t rde, char *p) {
static char *DisM(struct Dis *d, uint32_t rde, char *p) {
int64_t disp;
const char *base, *index, *scale;
p = DisSego(b, rde, p);
p = DisSego(d, rde, p);
base = index = scale = NULL;
if (ModrmMod(rde) == 0b01 || ModrmMod(rde) == 0b10 || IsRipRelative(rde) ||
(Eamode(rde) == XED_MODE_REAL && ModrmRm(rde) == 6 && !ModrmMod(rde)) ||
(ModrmMod(rde) == 0b00 && ModrmRm(rde) == 0b100 &&
SibBase(b.xedd) == 0b101)) {
disp = b.xedd->op.disp;
if (IsRipRelative(rde)) disp = RipRelative(b, disp);
p = DisSym(b, p, disp);
SibBase(d->xedd) == 0b101)) {
disp = d->xedd->op.disp;
if (IsRipRelative(rde)) disp = RipRelative(d, disp);
p = DisSym(d, p, disp);
}
if (Eamode(rde) != XED_MODE_REAL) {
if (!SibExists(rde)) {
DCHECK(!b.xedd->op.has_sib);
DCHECK(!d->xedd->op.has_sib);
if (IsRipRelative(rde)) {
if (Mode(rde) == XED_MODE_LONG) {
base = kPuttingOnTheRip[Eamode(rde) == XED_MODE_LONG];
base = kRip[Eamode(rde) == XED_MODE_LONG];
}
} else {
base = GetAddrReg(b, rde, Rexb(rde), ModrmRm(rde));
base = GetAddrReg(d, rde, Rexb(rde), ModrmRm(rde));
}
} else if (!SibIsAbsolute(b.xedd, rde)) {
if (SibHasBase(b.xedd, rde)) {
base = GetAddrReg(b, rde, Rexb(rde), SibBase(b.xedd));
} else if (!SibIsAbsolute(d->xedd, rde)) {
if (SibHasBase(d->xedd, rde)) {
base = GetAddrReg(d, rde, Rexb(rde), SibBase(d->xedd));
}
if (SibHasIndex(b.xedd)) {
index = GetAddrReg(b, rde, Rexx(b.xedd), SibIndex(b.xedd));
} else if (b.xedd->op.scale) {
index = kPuttingOnTheRiz[Eamode(rde) == XED_MODE_LONG];
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 = kScale[b.xedd->op.scale];
scale = kSka[d->xedd->op.scale];
}
} else {
switch (ModrmRm(rde)) {
@ -250,206 +240,235 @@ static char *DisM(struct DisBuilder b, uint32_t rde, char *p) {
return p;
}
static char *DisEb(struct DisBuilder b, uint32_t rde, char *p) {
static char *DisRegMem(struct Dis *d, uint32_t rde, char *p,
char *f(struct Dis *, uint32_t, char *)) {
if (IsModrmRegister(rde)) {
return DisRegisterByte(b, rde, p, Rexb(rde), ModrmRm(rde));
return f(d, rde, p);
} else {
return DisM(b, rde, p);
return DisM(d, rde, p);
}
}
static char *DisEvqp(struct DisBuilder b, uint32_t rde, char *p) {
static noinline char *DisE(struct Dis *d, uint32_t rde, char *p,
char *f(struct Dis *, uint32_t, char *, bool, int)) {
if (IsModrmRegister(rde)) {
return DisRegisterWord(b, rde, p, Rexb(rde), ModrmRm(rde));
return f(d, rde, p, Rexb(rde), ModrmRm(rde));
} else {
return DisM(b, rde, p);
return DisM(d, rde, p);
}
}
static char *DisEdqp(struct DisBuilder b, uint32_t rde, char *p) {
if (IsModrmRegister(rde)) {
return DisRegister(p, kRegisterName[0][Rexw(rde)][Rexb(rde)][ModrmRm(rde)]);
} else {
return DisM(b, rde, p);
}
static char *DisEb(struct Dis *d, uint32_t rde, char *p) {
return DisE(d, rde, p, DisRegisterByte);
}
static char *DisEv(struct DisBuilder b, uint32_t rde, char *p) {
const char *s;
if (IsModrmRegister(rde)) {
return DisRegister(p, kRegisterName[Osz(rde)][0][Rexb(rde)][ModrmRm(rde)]);
} else {
return DisM(b, rde, p);
}
static char *DisEvqp(struct Dis *d, uint32_t rde, char *p) {
return DisE(d, rde, p, DisRegisterWord);
}
static char *DisGvq(struct DisBuilder b, uint32_t rde, char *p, int r) {
static char *DisEdqpReg(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, DisEdqpReg);
}
static char *DisEvReg(struct Dis *d, uint32_t rde, char *p) {
return DisRegister(p, kGreg[Osz(rde)][0][Rexb(rde)][ModrmRm(rde)]);
}
static char *DisEv(struct Dis *d, uint32_t rde, char *p) {
return DisRegMem(d, rde, p, DisEvReg);
}
static char *DisGvq(struct Dis *d, uint32_t rde, char *p, int r) {
const char *s;
if (Mode(rde) == XED_MODE_LONG) {
s = kRegisterName[Osz(rde)][!Osz(rde)][Rexb(rde)][r];
s = kGreg[Osz(rde)][!Osz(rde)][Rexb(rde)][r];
} else {
s = kRegisterName[Osz(rde)][0][Rexb(rde)][r];
s = kGreg[Osz(rde)][0][Rexb(rde)][r];
}
return DisRegister(p, s);
}
static char *DisZvq(struct DisBuilder b, uint32_t rde, char *p) {
return DisGvq(b, rde, p, ModrmSrm(rde));
static char *DisZvq(struct Dis *d, uint32_t rde, char *p) {
return DisGvq(d, rde, p, ModrmSrm(rde));
}
static char *DisEvq(struct DisBuilder b, uint32_t rde, char *p) {
if (IsModrmRegister(rde)) {
return DisGvq(b, rde, p, ModrmRm(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 {
return DisM(b, rde, p);
r = kGreg[Osz(rde)][0][Rexb(rde)][ModrmRm(rde)];
}
return DisRegister(p, r);
}
static char *DisEd(struct DisBuilder b, uint32_t rde, char *p) {
if (IsModrmRegister(rde)) {
return DisRegister(p, kRegisterName[0][0][Rexb(rde)][ModrmRm(rde)]);
} else {
return DisM(b, rde, p);
}
static char *DisEq(struct Dis *d, uint32_t rde, char *p) {
return DisRegMem(d, rde, p, DisEqReg);
}
static char *DisEq(struct DisBuilder b, uint32_t rde, char *p) {
if (IsModrmRegister(rde)) {
return DisRegister(p, kRegisterName[0][1][Rexb(rde)][ModrmRm(rde)]);
} else {
return DisM(b, rde, p);
}
static char *DisZvqp(struct Dis *d, uint32_t rde, char *p) {
return DisRegisterWord(d, rde, p, Rexb(rde), ModrmSrm(rde));
}
static char *DisZvqp(struct DisBuilder b, uint32_t rde, char *p) {
return DisRegisterWord(b, 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 *DisZb(struct DisBuilder b, uint32_t rde, char *p) {
return DisRegisterByte(b, 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 *DisEax(struct DisBuilder b, uint32_t rde, char *p) {
return DisRegister(p, kRegisterName[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 *DisRax(struct DisBuilder b, uint32_t rde, char *p) {
return DisRegister(p, kRegisterName[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 *DisRdx(struct DisBuilder b, uint32_t rde, char *p) {
return DisRegister(p, kRegisterName[Osz(rde)][Rexw(rde)][0][2]);
static char *DisCd(struct Dis *d, uint32_t rde, char *p) {
return DisRegister(p, kCtl[ModrmReg(rde)]);
}
static char *DisCd(struct DisBuilder b, uint32_t rde, char *p) {
return DisRegister(p, kControlName[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 *DisHd(struct DisBuilder b, uint32_t rde, char *p) {
return DisRegister(
p, kRegisterName[0][Mode(rde) == XED_MODE_LONG][0][ModrmRm(rde)]);
static char *DisImm(struct Dis *d, uint32_t rde, char *p) {
return DisSymLiteral(d, p, d->xedd->op.uimm0);
}
static char *DisImm(struct DisBuilder b, uint32_t rde, char *p) {
return DisSymLiteral(b, p, b.xedd->op.uimm0);
static char *DisRvds(struct Dis *d, uint32_t rde, char *p) {
return DisSymLiteral(d, p, d->xedd->op.disp);
}
static char *DisRvds(struct DisBuilder b, uint32_t rde, char *p) {
return DisSymLiteral(b, p, b.xedd->op.disp);
}
static char *DisKvds(struct DisBuilder b, uint32_t rde, char *p) {
static char *DisKpvds(struct Dis *d, uint32_t rde, char *p, uint64_t x) {
*p++ = '$';
if (g_dis_high) p = DisHigh(p, g_dis_high->literal);
p = DisInt(p, b.xedd->op.uimm0);
if (g_dis_high) p = DisHigh(p, -1);
p = HighStart(p, g_high.literal);
p = DisInt(p, x);
p = HighEnd(p);
return p;
}
static char *DisOne(struct DisBuilder b, uint32_t rde, char *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++ = '$';
if (g_dis_high) p = DisHigh(p, g_dis_high->literal);
p = HighStart(p, g_high.literal);
p = stpcpy(p, "1");
if (g_dis_high) p = DisHigh(p, -1);
p = HighEnd(p);
return p;
}
static char *DisJbs(struct DisBuilder b, uint32_t rde, char *p) {
if (b.xedd->op.disp > 0) *p++ = '+';
p += int64toarray_radix10(b.xedd->op.disp, p);
static char *DisJbs(struct Dis *d, uint32_t rde, char *p) {
if (d->xedd->op.disp > 0) *p++ = '+';
p += int64toarray_radix10(d->xedd->op.disp, p);
return p;
}
static char *DisJb(struct DisBuilder b, uint32_t rde, char *p) {
if (b.xedd->op.disp > 0) *p++ = '+';
p += uint64toarray_radix10(b.xedd->op.disp & 0xff, p);
static char *DisJb(struct Dis *d, uint32_t rde, char *p) {
if (d->xedd->op.disp > 0) *p++ = '+';
p += uint64toarray_radix10(d->xedd->op.disp & 0xff, p);
return p;
}
static char *DisJvds(struct DisBuilder b, uint32_t rde, char *p) {
return DisSym(b, p, RipRelative(b, b.xedd->op.disp));
static char *DisJvds(struct Dis *d, uint32_t rde, char *p) {
return DisSym(d, p, RipRelative(d, d->xedd->op.disp));
}
static char *DisAbs(struct DisBuilder b, uint32_t rde, char *p) {
return DisSym(b, p, b.xedd->op.disp);
static char *DisAbs(struct Dis *d, uint32_t rde, char *p) {
return DisSym(d, p, d->xedd->op.disp);
}
static char *DisSw(struct DisBuilder b, uint32_t rde, char *p) {
if (kSegName[ModrmReg(rde)][0]) p = DisRegister(p, kSegName[ModrmReg(rde)]);
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 DisBuilder b, uint32_t rde, char *p, int r) {
static char *DisSpecialAddr(struct Dis *d, uint32_t rde, char *p, int r) {
*p++ = '(';
p = DisRegister(p, GetAddrReg(b, rde, 0, r));
p = DisRegister(p, GetAddrReg(d, rde, 0, r));
*p++ = ')';
*p = '\0';
return p;
}
static char *DisY(struct DisBuilder b, uint32_t rde, char *p) {
return DisSpecialAddr(b, rde, p, 7); // es:di
static char *DisY(struct Dis *d, uint32_t rde, char *p) {
return DisSpecialAddr(d, rde, p, 7); // es:di
}
static char *DisX(struct DisBuilder b, uint32_t rde, char *p) {
DisSego(b, rde, p);
return DisSpecialAddr(b, rde, p, 6); // ds:si
static char *DisX(struct Dis *d, uint32_t rde, char *p) {
DisSego(d, rde, p);
return DisSpecialAddr(d, rde, p, 6); // ds:si
}
static char *DisBBb(struct DisBuilder b, uint32_t rde, char *p) {
DisSego(b, rde, p);
return DisSpecialAddr(b, rde, p, 3); // ds:bx
static char *DisBBb(struct Dis *d, uint32_t rde, char *p) {
DisSego(d, rde, p);
return DisSpecialAddr(d, rde, p, 3); // ds:bx
}
static char *DisNq(struct DisBuilder b, uint32_t rde, char *p) {
return DisXmm(b, rde, p, "mm", ModrmRm(rde));
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 += uint64toarray_radix10(reg, p);
p = HighEnd(p);
return p;
}
static char *DisUq(struct DisBuilder b, uint32_t rde, char *p) {
return DisXmm(b, rde, p, "mm", ModrmRm(rde));
static char *DisNq(struct Dis *d, uint32_t rde, char *p) {
return DisXmm(d, rde, p, "mm", ModrmRm(rde));
}
static char *DisPq(struct DisBuilder b, uint32_t rde, char *p) {
return DisXmm(b, rde, p, "mm", ModrmReg(rde));
static char *DisPq(struct Dis *d, uint32_t rde, char *p) {
return DisXmm(d, rde, p, "mm", ModrmReg(rde));
}
static char *DisUdq(struct DisBuilder b, uint32_t rde, char *p) {
return DisXmm(b, rde, p, "xmm", ModrmRm(rde));
static char *DisUq(struct Dis *d, uint32_t rde, char *p) {
return DisXmm(d, rde, p, "xmm", RexbRm(rde));
}
static char *DisVdq(struct DisBuilder b, uint32_t rde, char *p) {
return DisXmm(b, rde, p, "xmm", ModrmReg(rde));
static char *DisUdq(struct Dis *d, uint32_t rde, char *p) {
return DisXmm(d, rde, p, "xmm", RexbRm(rde));
}
static char *DisQq(struct DisBuilder b, uint32_t rde, char *p) {
if (IsModrmRegister(rde)) {
return DisNq(b, rde, p);
} else {
return DisM(b, rde, p);
}
static char *DisVdq(struct Dis *d, uint32_t rde, char *p) {
return DisXmm(d, rde, p, "xmm", RexrReg(rde));
}
static char *DisEst(struct DisBuilder b, uint32_t rde, char *p) {
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++ = '(';
@ -460,29 +479,21 @@ static char *DisEst(struct DisBuilder b, uint32_t rde, char *p) {
return p;
}
static char *DisEst1(struct DisBuilder b, uint32_t rde, char *p) {
static char *DisEst1(struct Dis *d, uint32_t rde, char *p) {
if (ModrmRm(rde) != 1) {
p = DisEst(b, rde, p);
p = DisEst(d, rde, p);
} else {
*p = '\0';
}
return p;
}
static char *DisEssr(struct DisBuilder b, uint32_t rde, char *p) {
if (IsModrmRegister(rde)) {
return DisEst(b, rde, p);
} else {
return DisM(b, rde, p);
}
static char *DisEssr(struct Dis *d, uint32_t rde, char *p) {
return DisRegMem(d, rde, p, DisEst);
}
static char *DisWps(struct DisBuilder b, uint32_t rde, char *p) {
if (IsModrmRegister(rde)) {
return DisUdq(b, rde, p);
} else {
return DisM(b, rde, p);
}
static char *DisWps(struct Dis *d, uint32_t rde, char *p) {
return DisRegMem(d, rde, p, DisUdq);
}
#define DisEdr DisM
@ -537,7 +548,7 @@ static char *DisWps(struct DisBuilder b, uint32_t rde, char *p) {
static const struct DisArg {
char s[8];
char *(*f)(struct DisBuilder, uint32_t, char *);
char *(*f)(struct Dis *, uint32_t, char *);
} kDisArgs[] = /* <sorted> */ {
{"$1", DisOne}, //
{"%Cd", DisCd}, //
@ -610,6 +621,7 @@ static const struct DisArg {
{"Mwi", DisMwi}, //
{"Ob", DisOb}, //
{"Ovqp", DisOvqp}, //
{"Pvds", DisPvds}, //
{"Qpi", DisQpi}, //
{"Qq", DisQq}, //
{"Rvds", DisRvds}, //
@ -635,7 +647,7 @@ static int CompareString8(const char a[8], const char b[8]) {
return x > y ? 1 : x < y ? -1 : 0;
}
char *DisArg(struct DisBuilder b, char *p, const char *s) {
char *DisArg(struct Dis *d, char *p, const char *s) {
char key[8];
int c, m, l, r;
l = 0;
@ -649,7 +661,7 @@ char *DisArg(struct DisBuilder b, char *p, const char *s) {
} else if (c > 0) {
r = m - 1;
} else {
return kDisArgs[m].f(b, b.xedd->op.rde, p);
return kDisArgs[m].f(d, d->xedd->op.rde, p);
}
}
if (*s == '%') {

View file

@ -115,31 +115,33 @@ bool DisIsText(struct Dis *d, int64_t addr) {
long DisFindSym(struct Dis *d, int64_t addr) {
size_t i, 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) {
l = m + 1;
} else {
r = m;
if (d->syms.p) {
if (DisIsProg(d, addr)) {
l = 0;
r = d->syms.i;
while (l < r) {
m = (l + r) >> 1;
if (d->syms.p[m].addr < addr) {
l = m + 1;
} else {
r = m;
}
}
}
if (d->syms.p[l].addr == addr) {
return l;
}
l = MAX(0, (long)l - 10);
for (n = 0, i = l; i < d->syms.i && n < 20; ++i, ++n) {
if (addr >= d->syms.p[i].addr &&
addr < d->syms.p[i].addr + d->syms.p[i].size) {
return i;
if (d->syms.p[l].addr == addr) {
return l;
}
}
for (n = 0, i = l; i < d->syms.i && n < 20; ++i, ++n) {
if (addr >= d->syms.p[i].addr &&
(i + 1 == d->syms.i || addr < d->syms.p[i + 1].addr)) {
return i;
l = MAX(0, (long)l - 10);
for (n = 0, i = l; i < d->syms.i && n < 20; ++i, ++n) {
if (addr >= d->syms.p[i].addr &&
addr < d->syms.p[i].addr + d->syms.p[i].size) {
return i;
}
}
for (n = 0, i = l; i < d->syms.i && n < 20; ++i, ++n) {
if (addr >= d->syms.p[i].addr &&
(i + 1 == d->syms.i || addr < d->syms.p[i + 1].addr)) {
return i;
}
}
}
}

View file

@ -21,6 +21,7 @@
#include "libc/nexgen32e/tinystrcmp.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"};
@ -28,43 +29,45 @@ 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 DisBuilder b) {
switch (b.xedd->op.opcode & ~1) {
case 0x6C: /* INS */
static int IsRepOpcode(struct Dis *d) {
switch (d->xedd->op.opcode & ~1) {
case 0x6C: // INS
return 1;
case 0x6E: /* OUTS */
case 0x6E: // OUTS
return 1;
case 0xA4: /* MOVS */
case 0xA4: // MOVS
return 1;
case 0xAA: /* STOS */
case 0xAA: // STOS
return 1;
case 0xAC: /* LODS */
case 0xAC: // LODS
return 1;
case 0xA6: /* CMPS */
case 0xA6: // CMPS
return 2;
case 0xAE: /* SCAS */
case 0xAE: // SCAS
return 2;
default:
return 0;
}
}
static char *DisRepPrefix(struct DisBuilder b, char *p) {
static char *DisRepPrefix(struct Dis *d, char *p) {
const char *s;
if (Rep(b.xedd->op.rde) && b.xedd->op.map == XED_ILD_MAP0) {
switch (IsRepOpcode(b)) {
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(b.xedd->op.rde) == 2 ? "repnz " : "repz ");
p = stpcpy(p, Rep(d->xedd->op.rde) == 2 ? "repnz " : "repz ");
break;
default:
break;
@ -73,8 +76,8 @@ static char *DisRepPrefix(struct DisBuilder b, char *p) {
return p;
}
static char *DisBranchTaken(struct DisBuilder b, char *p) {
switch (b.xedd->op.hint) {
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:
@ -84,24 +87,26 @@ static char *DisBranchTaken(struct DisBuilder b, char *p) {
}
}
static char *DisName(struct DisBuilder b, char *bp, const char *name,
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 = b.xedd->op.rde;
if (b.xedd->op.lock) p = stpcpy(p, "lock ");
p = DisRepPrefix(b, p);
rde = d->xedd->op.rde;
if (d->xedd->op.lock) p = stpcpy(p, "lock ");
p = DisRepPrefix(d, p);
if (tinystrcmp(name, "BIT") == 0) {
p = stpcpy(p, kBitOp[ModrmReg(rde)]);
} else if (tinystrcmp(name, "nop") == 0 && d->xedd->op.rep) {
p = stpcpy(p, "pause");
} else if (tinystrcmp(name, "CALL") == 0) {
p = stpcpy(p, "call");
} else if (tinystrcmp(name, "JMP") == 0) {
p = stpcpy(p, "jmp");
} else if (tinystrcmp(name, "jcxz") == 0) {
p = stpcpy(p, kJcxz[Eamode(rde)]);
p = DisBranchTaken(b, p);
p = DisBranchTaken(d, p);
} else if (tinystrcmp(name, "loop") == 0 || tinystrcmp(name, "loope") == 0 ||
tinystrcmp(name, "loopne") == 0) {
p = stpcpy(p, name);
@ -109,7 +114,7 @@ static char *DisName(struct DisBuilder b, char *bp, const char *name,
*p++ = "wl"[Eamode(rde)];
*p = '\0';
}
p = DisBranchTaken(b, p);
p = DisBranchTaken(d, p);
} else if (tinystrcmp(name, "cwtl") == 0) {
if (Osz(rde)) name = "cbtw";
if (Rexw(rde)) name = "cltq";
@ -127,10 +132,15 @@ static char *DisName(struct DisBuilder b, char *bp, const char *name,
*p++ = *np;
}
if (tinystrcmp(name, "ALU") == 0) {
p = stpcpy(p, kAluOp[(d->xedd->op.opcode & 070) >> 3]);
} else if (tinystrcmp(name, "ALU2") == 0) {
p = stpcpy(p, kAluOp[ModrmReg(rde)]);
} else if (tinystrcmp(np, "WLQ") == 0) {
notbyte = true;
wantsuffix = true;
} else if (tinystrcmp(np, "CC") == 0) {
p = stpcpy(p, kCc[d->xedd->op.opcode & 15]);
p = DisBranchTaken(d, p);
} else if (tinystrcmp(np, "WQ") == 0) {
notbyte = true;
notlong = Eamode(rde) != XED_MODE_REAL;
@ -143,8 +153,6 @@ static char *DisName(struct DisBuilder b, char *bp, const char *name,
wantsuffixsd = true;
} else if (tinystrcmp(np, "ABS") == 0) {
if (Rexw(rde)) p = stpcpy(p, "abs");
} else if (tinystrcmp(np, "BT") == 0) {
p = DisBranchTaken(b, p);
}
if (wantsuffixsd) {
if (Osz(rde)) {
@ -155,12 +163,12 @@ static char *DisName(struct DisBuilder b, char *bp, const char *name,
} else if (wantsuffix || (ambiguous && !startswith(name, "f") &&
!startswith(name, "set"))) {
if (Osz(rde)) {
if (Eamode(rde) != XED_MODE_REAL) {
if (Mode(rde) != XED_MODE_REAL) {
*p++ = 'w';
}
} else if (Rexw(rde)) {
*p++ = 'q';
} else if (ambiguous && !notbyte && IsProbablyByteOp(b.xedd)) {
} else if (ambiguous && !notbyte && IsProbablyByteOp(d->xedd)) {
*p++ = 'b';
} else if (!notlong) {
*p++ = 'l';
@ -177,28 +185,28 @@ static char *DisName(struct DisBuilder b, char *bp, const char *name,
* Disassembles instruction based on string spec.
* @see DisSpec()
*/
char *DisInst(struct DisBuilder b, char *p, const char *spec) {
char *DisInst(struct Dis *d, char *p, const char *spec) {
long i, n;
char sbuf[256];
char args[4][128];
char sbuf[300];
char args[4][300];
char *s, *name, *state;
bool hasarg, hasmodrm, hasregister, hasmemory;
CHECK_EQ(0, (int)b.xedd->op.error);
CHECK_EQ(0, (int)d->xedd->op.error);
DCHECK_LT(strlen(spec), 128);
hasarg = false;
hasmodrm = b.xedd->op.has_modrm;
hasmemory = hasmodrm && !IsModrmRegister(b.xedd->op.rde);
hasregister = hasmodrm && IsModrmRegister(b.xedd->op.rde);
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(b, args[n], s) - args[n], sizeof(args[n]));
CHECK_LT(DisArg(d, args[n], s) - args[n], sizeof(args[n]));
}
if (g_dis_high) p = DisHigh(p, g_dis_high->keyword);
p = DisName(b, p, name, hasarg && !hasregister && hasmemory);
if (g_dis_high) p = DisHigh(p, -1);
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++ = ',';

View file

@ -36,12 +36,6 @@ static const char kFpuName[][8][8] = {
{"fneni", "fndisi", "fnclex", "fninit", "fnsetpm"},
};
char *DisOpFpu0(struct XedDecodedInst *x, int group) {
const char *s;
s = kFpuName[group][ModrmRm(x->op.rde)];
return *s ? s : UNKNOWN;
}
char *DisOpFpu1(struct XedDecodedInst *x, char *p, const char *extra) {
stpcpy(stpcpy(p, kFpuName[0][ModrmReg(x->op.rde)]), extra);
return p;
@ -88,68 +82,88 @@ char *DisOpVpsWpsVssWssVpdWpdVsdWsd(struct XedDecodedInst *x, char *p,
return p;
}
const char *DisSpecFpu0(struct XedDecodedInst *x, int group) {
const char *s;
s = kFpuName[group][ModrmRm(x->op.rde)];
return *s ? s : UNKNOWN;
}
const char *DisSpecRegMem(struct XedDecodedInst *x, const char *a,
const char *b) {
if (IsModrmRegister(x->op.rde)) {
return a;
} else {
return b;
}
}
const char *DisSpecRegMemFpu0(struct XedDecodedInst *x, int group,
const char *b) {
return DisSpecRegMem(x, DisSpecFpu0(x, group), b);
}
const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
switch (x->op.opcode & 0xff) {
RCASE(0x00, "add Eb %Gb");
RCASE(0x01, "add Evqp %Gvqp");
RCASE(0x02, "add %Gb Eb");
RCASE(0x03, "add %Gvqp Evqp");
RCASE(0x04, "add %al Ib");
RCASE(0x05, "add %rAX Ivds");
RCASE(0x00, "ALU Eb %Gb");
RCASE(0x01, "ALU Evqp %Gvqp");
RCASE(0x02, "ALU %Gb Eb");
RCASE(0x03, "ALU %Gvqp Evqp");
RCASE(0x04, "ALU %al Ib");
RCASE(0x05, "ALU %rAX Ivds");
RCASE(0x06, "push %es");
RCASE(0x07, "pop %es");
RCASE(0x08, "or Eb %Gb");
RCASE(0x09, "or Evqp %Gvqp");
RCASE(0x0a, "or %Gb Eb");
RCASE(0x0b, "or %Gvqp Evqp");
RCASE(0x0c, "or %al Ib");
RCASE(0x0d, "or %rAX Ivds");
RCASE(0x08, "ALU Eb %Gb");
RCASE(0x09, "ALU Evqp %Gvqp");
RCASE(0x0a, "ALU %Gb Eb");
RCASE(0x0b, "ALU %Gvqp Evqp");
RCASE(0x0c, "ALU %al Ib");
RCASE(0x0d, "ALU %rAX Ivds");
RCASE(0x0e, "push %cs");
RCASE(0x0f, "pop %cs");
RCASE(0x10, "adc Eb %Gb");
RCASE(0x11, "adc Evqp %Gvqp");
RCASE(0x12, "adc %Gb Eb");
RCASE(0x13, "adc %Gvqp Evqp");
RCASE(0x14, "adc %al Ib");
RCASE(0x15, "adc %rAX Ivds");
RCASE(0x10, "ALU Eb %Gb");
RCASE(0x11, "ALU Evqp %Gvqp");
RCASE(0x12, "ALU %Gb Eb");
RCASE(0x13, "ALU %Gvqp Evqp");
RCASE(0x14, "ALU %al Ib");
RCASE(0x15, "ALU %rAX Ivds");
RCASE(0x16, "push %ss");
RCASE(0x17, "pop %ss");
RCASE(0x18, "sbb Eb %Gb");
RCASE(0x19, "sbb Evqp %Gvqp");
RCASE(0x1a, "sbb %Gb Eb");
RCASE(0x1b, "sbb %Gvqp Evqp");
RCASE(0x1c, "sbb %al Ib");
RCASE(0x1d, "sbb %rAX Ivds");
RCASE(0x18, "ALU Eb %Gb");
RCASE(0x19, "ALU Evqp %Gvqp");
RCASE(0x1a, "ALU %Gb Eb");
RCASE(0x1b, "ALU %Gvqp Evqp");
RCASE(0x1c, "ALU %al Ib");
RCASE(0x1d, "ALU %rAX Ivds");
RCASE(0x1e, "push %ds");
RCASE(0x1f, "pop %ds");
RCASE(0x20, "and Eb %Gb");
RCASE(0x21, "and Evqp %Gvqp");
RCASE(0x22, "and %Gb Eb");
RCASE(0x23, "and %Gvqp Evqp");
RCASE(0x24, "and %al Ib");
RCASE(0x25, "and %rAX Ivds");
RCASE(0x20, "ALU Eb %Gb");
RCASE(0x21, "ALU Evqp %Gvqp");
RCASE(0x22, "ALU %Gb Eb");
RCASE(0x23, "ALU %Gvqp Evqp");
RCASE(0x24, "ALU %al Ib");
RCASE(0x25, "ALU %rAX Ivds");
RCASE(0x26, "push %es");
RCASE(0x27, "pop %es");
RCASE(0x28, "sub Eb %Gb");
RCASE(0x29, "sub Evqp %Gvqp");
RCASE(0x28, "ALU Eb %Gb");
RCASE(0x29, "ALU Evqp %Gvqp");
RCASE(0x2a, "ALU %Gb Eb");
RCASE(0x2b, "ALU %Gvqp Evqp");
RCASE(0x2c, "ALU %al Ib");
RCASE(0x2d, "ALU %rAX Ivds");
RCASE(0x2F, "das");
RCASE(0x2a, "sub %Gb Eb");
RCASE(0x2b, "sub %Gvqp Evqp");
RCASE(0x2c, "sub %al Ib");
RCASE(0x2d, "sub %rAX Ivds");
RCASE(0x30, "xor Eb %Gb");
RCASE(0x31, "xor Evqp %Gvqp");
RCASE(0x32, "xor %Gb Eb");
RCASE(0x33, "xor %Gvqp Evqp");
RCASE(0x34, "xor %al Ib");
RCASE(0x35, "xor %rAX Ivds");
RCASE(0x30, "ALU Eb %Gb");
RCASE(0x31, "ALU Evqp %Gvqp");
RCASE(0x32, "ALU %Gb Eb");
RCASE(0x33, "ALU %Gvqp Evqp");
RCASE(0x34, "ALU %al Ib");
RCASE(0x35, "ALU %rAX Ivds");
RCASE(0x37, "aaa");
RCASE(0x38, "cmp Eb %Gb");
RCASE(0x39, "cmp Evqp %Gvqp");
RCASE(0x3A, "cmp %Gb Eb");
RCASE(0x3B, "cmp %Gvqp Evqp");
RCASE(0x3C, "cmp %al Ib");
RCASE(0x3D, "cmp %rAX Ivds");
RCASE(0x38, "ALU Eb %Gb");
RCASE(0x39, "ALU Evqp %Gvqp");
RCASE(0x3A, "ALU %Gb Eb");
RCASE(0x3B, "ALU %Gvqp Evqp");
RCASE(0x3C, "ALU %al Ib");
RCASE(0x3D, "ALU %rAX Ivds");
RCASE(0x3F, "aas");
RCASE(0x40 ... 0x47, "inc %Zv");
RCASE(0x48 ... 0x4f, "dec %Zv");
@ -167,26 +181,11 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
RCASE(0x6D, "insWL Yv %dx");
RCASE(0x6E, "outsb %dx Xb");
RCASE(0x6F, "outsWL %dx Xv");
RCASE(0x70, "joBT Jbs");
RCASE(0x71, "jnoBT Jbs");
RCASE(0x72, "jbBT Jbs");
RCASE(0x73, "jaeBT Jbs");
RCASE(0x74, "jeBT Jbs");
RCASE(0x75, "jneBT Jbs");
RCASE(0x76, "jbeBT Jbs");
RCASE(0x77, "jaBT Jbs");
RCASE(0x78, "jsBT Jbs");
RCASE(0x79, "jnsBT Jbs");
RCASE(0x7a, "jpBT Jbs");
RCASE(0x7b, "jnpBT Jbs");
RCASE(0x7c, "jlBT Jbs");
RCASE(0x7d, "jgeBT Jbs");
RCASE(0x7e, "jleBT Jbs");
RCASE(0x7f, "jgBT Jbs");
RCASE(0x80, "ALU Eb Ib");
RCASE(0x81, "ALU Evqp Ivds");
RCASE(0x82, "ALU Eb Ib");
RCASE(0x83, "ALU Evqp Ibs");
RCASE(0x70 ... 0x7f, "jCC Jbs");
RCASE(0x80, "ALU2 Eb Ib");
RCASE(0x81, "ALU2 Evqp Ivds");
RCASE(0x82, "ALU2 Eb Ib");
RCASE(0x83, "ALU2 Evqp Ibs");
RCASE(0x84, "test Eb %Gb");
RCASE(0x85, "test %Gvqp Evqp");
RCASE(0x86, "xchg %Gb Eb");
@ -202,6 +201,7 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
RCASE(0x91 ... 0x97, "xchg %Zvqp %rAX");
RCASE(0x98, "cwtl");
RCASE(0x99, "cltd");
RCASE(0x9A, "lcall Pvds Kvds");
RCASE(0x9B, "fwait");
RCASE(0x9C, "pushfWQ");
RCASE(0x9D, "popfWQ");
@ -234,6 +234,8 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
RCASE(0xC6, "mov Eb Ib");
RCASE(0xC7, "mov Evqp Ivds");
RCASE(0xC9, "leave");
RCASE(0xCA, "lret Iw");
RCASE(0xCB, "lret");
RCASE(0xCC, "int3");
RCASE(0xCD, "int Ib");
RCASE(0xD0, "BIT Eb $1");
@ -280,163 +282,36 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
switch (ModrmReg(x->op.rde)) {
RCASE(1, "fxch EST1");
RCASE(3, "fstps Msr %st");
case 0:
if (IsModrmRegister(x->op.rde)) {
return "fld EST";
} else {
return "flds Msr";
}
break;
case 2:
if (IsModrmRegister(x->op.rde)) {
return "fnop";
} else {
return "fsts Msr %st";
}
break;
case 4:
if (IsModrmRegister(x->op.rde)) {
return DisOpFpu0(x, 1);
} else {
return "fldenv Me";
}
break;
case 5:
if (IsModrmRegister(x->op.rde)) {
return DisOpFpu0(x, 2);
} else {
return "fldcw Mw";
}
break;
case 6:
if (IsModrmRegister(x->op.rde)) {
return DisOpFpu0(x, 3);
} else {
return "fnstenv M";
}
break;
case 7:
if (IsModrmRegister(x->op.rde)) {
return DisOpFpu0(x, 4);
} else {
return "fnstcw Mw";
}
break;
RCASE(0, DisSpecRegMem(x, "fld EST", "flds Msr"));
RCASE(2, DisSpecRegMem(x, "fnop", "fsts Msr %st"));
RCASE(4, DisSpecRegMemFpu0(x, 1, "fldenv Me"));
RCASE(5, DisSpecRegMemFpu0(x, 2, "fldcw Mw"));
RCASE(6, DisSpecRegMemFpu0(x, 3, "fnstenv M"));
RCASE(7, DisSpecRegMemFpu0(x, 4, "fnstcw Mw"));
}
break;
case 0xDA:
switch (ModrmReg(x->op.rde)) {
case 0:
if (!IsModrmRegister(x->op.rde)) {
return "fiaddl Mdi";
} else {
return "fcmovb %st EST";
}
break;
case 1:
if (!IsModrmRegister(x->op.rde)) {
return "fimull Mdi";
} else {
return "fcmove %st EST";
}
break;
case 2:
if (!IsModrmRegister(x->op.rde)) {
return "ficoml Mdi";
} else {
return "fcmovbe %st EST";
}
break;
case 3:
if (!IsModrmRegister(x->op.rde)) {
return "ficompl Mdi";
} else {
return "fcmovu %st EST";
}
break;
case 4:
if (!IsModrmRegister(x->op.rde)) {
return "fisubl Mdi";
} else {
return "fisubr Mdi";
}
break;
case 5:
if (!IsModrmRegister(x->op.rde)) {
return "fisubrl Mdi";
} else {
return "fucompp";
}
break;
case 6:
if (!IsModrmRegister(x->op.rde)) {
return "fidivl Mdi";
} else {
return UNKNOWN;
}
break;
case 7:
if (!IsModrmRegister(x->op.rde)) {
return "fidivrl Mdi";
} else {
return UNKNOWN;
}
break;
RCASE(0, DisSpecRegMem(x, "fcmovb %st EST", "fiaddl Mdi"));
RCASE(1, DisSpecRegMem(x, "fcmove %st EST", "fimull Mdi"));
RCASE(2, DisSpecRegMem(x, "fcmovbe %st EST", "ficoml Mdi"));
RCASE(3, DisSpecRegMem(x, "fcmovu %st EST", "ficompl Mdi"));
RCASE(4, DisSpecRegMem(x, "fisubr Mdi", "fisubl Mdi"));
RCASE(5, DisSpecRegMem(x, "fucompp", "fisubrl Mdi"));
RCASE(6, DisSpecRegMem(x, "fidivl Mdi", "UNKNOWN"));
RCASE(7, DisSpecRegMem(x, "fidivrl Mdi", "UNKNOWN"));
}
break;
case 0xDB:
switch (ModrmReg(x->op.rde)) {
case 0:
if (!IsModrmRegister(x->op.rde)) {
return "fildl Mdi";
} else {
return "fcmovnb %st EST";
}
break;
case 1:
if (!IsModrmRegister(x->op.rde)) {
return "fisttpl Mdi";
} else {
return "fcmovne %st EST";
}
break;
case 2:
if (!IsModrmRegister(x->op.rde)) {
return "fistl Mdi";
} else {
return "fcmovnbe %st EST";
}
break;
case 3:
if (!IsModrmRegister(x->op.rde)) {
return "fistpl Mdi";
} else {
return "fcmovnu %st EST";
}
break;
case 4:
return DisOpFpu0(x, 5);
case 5:
if (!IsModrmRegister(x->op.rde)) {
return "fldt Mer";
} else {
return "fucomi %st EST";
}
break;
case 6:
if (IsModrmRegister(x->op.rde)) {
return "fcomi %st EST";
} else {
return UNKNOWN;
}
break;
case 7:
if (!IsModrmRegister(x->op.rde)) {
return "fstpt Mer";
} else {
return UNKNOWN;
}
break;
RCASE(0, DisSpecRegMem(x, "fcmovnb %st EST", "fildl Mdi"));
RCASE(1, DisSpecRegMem(x, "fcmovne %st EST", "fisttpl Mdi"));
RCASE(2, DisSpecRegMem(x, "fcmovnbe %st EST", "fistl Mdi"));
RCASE(3, DisSpecRegMem(x, "fcmovnu %st EST", "fistpl Mdi"));
RCASE(4, DisSpecFpu0(x, 5));
RCASE(5, DisSpecRegMem(x, "fucomi %st EST", "fldt Mer"));
RCASE(6, DisSpecRegMem(x, "fcomi %st EST", UNKNOWN));
RCASE(7, DisSpecRegMem(x, UNKNOWN, "fstpt Mer"));
}
break;
case 0xD8:
@ -590,22 +465,7 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
RCASE(0x2E, Osz(x->op.rde) ? "ucomisd %Vsd Wsd" : "ucomiss %Vss Wss");
RCASE(0x2F, Osz(x->op.rde) ? "comisd %Vsd Wsd" : "comiss %Vss Wss");
RCASE(0x31, "rdtsc");
RCASE(0x40, "cmovo %Gvqp Evqp");
RCASE(0x41, "cmovno %Gvqp Evqp");
RCASE(0x42, "cmovb %Gvqp Evqp");
RCASE(0x43, "cmovae %Gvqp Evqp");
RCASE(0x44, "cmove %Gvqp Evqp");
RCASE(0x45, "cmovne %Gvqp Evqp");
RCASE(0x46, "cmovbe %Gvqp Evqp");
RCASE(0x47, "cmova %Gvqp Evqp");
RCASE(0x48, "cmovs %Gvqp Evqp");
RCASE(0x49, "cmovns %Gvqp Evqp");
RCASE(0x4a, "cmovp %Gvqp Evqp");
RCASE(0x4b, "cmovnp %Gvqp Evqp");
RCASE(0x4c, "cmovl %Gvqp Evqp");
RCASE(0x4d, "cmovge %Gvqp Evqp");
RCASE(0x4e, "cmovle %Gvqp Evqp");
RCASE(0x4f, "cmovg %Gvqp Evqp");
RCASE(0x40 ... 0x4f, "cmovCC %Gvqp Evqp");
RCASE(0x52, DisOpVpsWpsVssWss(x, p, "rsqrt"));
RCASE(0x53, DisOpVpsWpsVssWss(x, p, "rcp"));
RCASE(0x54, DisOpVpdWpdVpsWps(x, p, "and"));
@ -635,38 +495,8 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
RCASE(0x74, DisOpPqQqVdqWdq(x, p, "pcmpeqb"));
RCASE(0x75, DisOpPqQqVdqWdq(x, p, "pcmpeqw"));
RCASE(0x76, DisOpPqQqVdqWdq(x, p, "pcmpeqd"));
RCASE(0x80, "jo Jvds");
RCASE(0x81, "jno Jvds");
RCASE(0x82, "jb Jvds");
RCASE(0x83, "jae Jvds");
RCASE(0x84, "je Jvds");
RCASE(0x85, "jne Jvds");
RCASE(0x86, "jbe Jvds");
RCASE(0x87, "ja Jvds");
RCASE(0x88, "js Jvds");
RCASE(0x89, "jns Jvds");
RCASE(0x8a, "jp Jvds");
RCASE(0x8b, "jnp Jvds");
RCASE(0x8c, "jl Jvds");
RCASE(0x8d, "jge Jvds");
RCASE(0x8e, "jle Jvds");
RCASE(0x8f, "jg Jvds");
RCASE(0x90, "seto Eb");
RCASE(0x91, "setno Eb");
RCASE(0x92, "setb Eb");
RCASE(0x93, "setnb Eb");
RCASE(0x94, "sete Eb");
RCASE(0x95, "setne Eb");
RCASE(0x96, "setbe Eb");
RCASE(0x97, "seta Eb");
RCASE(0x98, "sets Eb");
RCASE(0x99, "setns Eb");
RCASE(0x9A, "setp Eb");
RCASE(0x9B, "setnp Eb");
RCASE(0x9C, "setl Eb");
RCASE(0x9D, "setge Eb");
RCASE(0x9E, "setle Eb");
RCASE(0x9F, "setg Eb");
RCASE(0x80 ... 0x8f, "jCC Jvds");
RCASE(0x90 ... 0x9f, "setCC Jvds");
RCASE(0xA0, "push %fs");
RCASE(0xA1, "pop %fs");
RCASE(0xA2, "cpuid");

55
tool/build/lib/flags.c Normal file
View file

@ -0,0 +1,55 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#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;
}

View file

@ -1,5 +1,6 @@
#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
@ -23,18 +24,12 @@
#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 GetParity(WORD) \
({ \
unsigned Byte = (WORD); \
Byte ^= Byte >> 4; \
Byte ^= Byte >> 2; \
Byte ^= Byte >> 1; \
~Byte & 1; \
})
#define GetFlag(FLAGS, BIT) \
({ \
autotype(FLAGS) Flags = (FLAGS); \
@ -66,13 +61,10 @@
Flags; \
})
forceinline 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;
}
bool GetParity(uint8_t);
uint64_t ExportFlags(uint64_t);
void ImportFlags(struct Machine *, uint64_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_FLAGS_H_ */

View file

@ -298,8 +298,7 @@ static long double FpuRound(struct Machine *m, long double x) {
}
static void FpuCompare(struct Machine *m, long double y) {
long double x;
x = St0(m);
long double x = St0(m);
m->fpu.c1 = false;
if (!isunordered(x, y)) {
m->fpu.c0 = x < y;
@ -452,7 +451,7 @@ static void OpFsincos(struct Machine *m) {
static void OpFpatan(struct Machine *m) {
FpuClearRoundup(m);
FpuSetStPop(m, 1, atan2l(St0(m), St1(m)));
FpuSetStPop(m, 1, atan2l(St1(m), St0(m)));
}
static void OpFcom(struct Machine *m) {
@ -704,8 +703,7 @@ static void OpFincstp(struct Machine *m) {
}
static void OpFxtract(struct Machine *m) {
long double x;
x = St0(m);
long double x = St0(m);
FpuSetSt0(m, logbl(x));
FpuPush(m, significandl(x));
}
@ -766,30 +764,44 @@ static void OpFldl(struct Machine *m) {
FpuPush(m, FpuGetMemoryDouble(m));
}
static long double Fld1(void) {
return 1;
}
static long double Fldl2t(void) {
return 0xd.49a784bcd1b8afep-2L; /* log₂10 */
}
static long double Fldl2e(void) {
return 0xb.8aa3b295c17f0bcp-3L; /* log₂𝑒 */
}
static long double Fldpi(void) {
return 0x1.921fb54442d1846ap+1L; /* π */
}
static long double Fldlg2(void) {
return 0x9.a209a84fbcff799p-5L; /* log₁₀2 */
}
static long double Fldln2(void) {
return 0xb.17217f7d1cf79acp-4L; /* logₑ2 */
}
static long double Fldz(void) {
return 0;
}
static void OpFldConstant(struct Machine *m) {
long double x;
switch (ModrmRm(m->xedd->op.rde)) {
case 0:
x = fld1();
break;
case 1:
x = fldl2t();
break;
case 2:
x = fldl2e();
break;
case 3:
x = fldpi();
break;
case 4:
x = fldlg2();
break;
case 5:
x = fldln2();
break;
case 6:
x = fldz();
break;
CASE(0, x = Fld1());
CASE(1, x = Fldl2t());
CASE(2, x = Fldl2e());
CASE(3, x = Fldpi());
CASE(4, x = Fldlg2());
CASE(5, x = Fldln2());
CASE(6, x = Fldz());
default:
OpUd(m, m->xedd->op.rde);
}

View file

@ -19,16 +19,24 @@
*/
#include "libc/conv/itoa.h"
#include "libc/str/str.h"
#include "tool/build/lib/dis.h"
#include "tool/build/lib/high.h"
struct DisHigh *g_dis_high;
struct High g_high;
char *DisHigh(char *p, int h) {
if (h != -1) {
char *HighStart(char *p, int h) {
if (h) {
p = stpcpy(p, "\e[38;5;");
p += uint64toarray_radix10(h, p);
} else {
p = stpcpy(p, "\e[39");
p = stpcpy(p, "m");
g_high.active = true;
}
return stpcpy(p, "m");
return p;
}
char *HighEnd(char *p) {
if (g_high.active) {
p = stpcpy(p, "\e[39m");
g_high.active = false;
}
return p;
}

23
tool/build/lib/high.h Normal file
View file

@ -0,0 +1,23 @@
#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

@ -52,18 +52,33 @@ static void DecodeInstruction(struct Machine *m, uint8_t *p, unsigned n) {
}
}
static noinline 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 i, key;
uint8_t *addr, *toil, copy[15];
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 ((i = 0x1000 - (ip & 0xfff)) >= 15) {
if (ROUNDDOWN(ip, 0x1000) == m->codevirt && ip) {
if ((ip & 0xfff) < 0x1000 - 15) {
if (ip - (ip & 0xfff) == m->codevirt && ip) {
addr = m->codereal + (ip & 0xfff);
} else {
m->codevirt = ROUNDDOWN(ip, 0x1000);
m->codevirt = ip - (ip & 0xfff);
m->codereal = ResolveAddress(m, m->codevirt);
addr = m->codereal + (ip & 0xfff);
}
@ -71,13 +86,6 @@ void LoadInstruction(struct Machine *m) {
DecodeInstruction(m, addr, 15);
}
} else {
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);
}
LoadInstructionSlow(m, ip);
}
}

View file

@ -52,6 +52,7 @@ static void LoadElfLoadSegment(struct Machine *m, void *code, size_t codesize,
fstart = felf + ROUNDDOWN(phdr->p_offset, align);
fend = felf + ROUNDUP(phdr->p_offset + phdr->p_filesz, align);
bsssize = vend - vbss;
m->brk = MAX(m->brk, vend);
CHECK_GE(vend, vstart);
CHECK_GE(fend, fstart);
CHECK_LE(felf, fstart);
@ -120,7 +121,7 @@ void LoadProgram(struct Machine *m, const char *prog, char **args, char **vars,
DCHECK_NOTNULL(prog);
elf->prog = prog;
if ((fd = open(prog, O_RDONLY)) == -1 ||
(fstat(fd, &st) == -1 || !st.st_size) || !S_ISREG(st.st_mode)) {
(fstat(fd, &st) == -1 || !st.st_size) /* || !S_ISREG(st.st_mode) */) {
fputs(prog, stderr);
fputs(": not found\n", stderr);
exit(1);

View file

@ -50,6 +50,12 @@
#include "tool/build/lib/throw.h"
#include "tool/build/lib/time.h"
#define OpLfence OpNoop
#define OpMfence OpNoop
#define OpSfence OpNoop
#define OpClflush OpNoop
#define OpHintNopEv OpNoop
typedef void (*nexgen32e_f)(struct Machine *, uint32_t);
static uint64_t ReadMemory(uint32_t rde, uint8_t p[8]) {
@ -130,38 +136,7 @@ static bool IsGreater(struct Machine *m) {
(GetFlag(m->flags, FLAGS_SF) == GetFlag(m->flags, FLAGS_OF));
}
static 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));
}
static void OpLfence(struct Machine *m, uint32_t rde) {
}
static void OpMfence(struct Machine *m, uint32_t rde) {
}
static void OpSfence(struct Machine *m, uint32_t rde) {
}
static void OpClflush(struct Machine *m, uint32_t rde) {
}
static void OpWutNopEv(struct Machine *m, uint32_t rde) {
static void OpNoop(struct Machine *m, uint32_t rde) {
}
static void OpCmc(struct Machine *m, uint32_t rde) {
@ -216,27 +191,27 @@ static void OpLeaGvqpM(struct Machine *m, uint32_t rde) {
WriteRegister(rde, RegRexrReg(m, rde), ComputeAddress(m, rde));
}
static void OpPushSeg(struct Machine *m, uint32_t rde) {
static relegated void OpPushSeg(struct Machine *m, uint32_t rde) {
uint8_t seg = (m->xedd->op.opcode & 070) >> 3;
Push(m, rde, Read64(GetSegment(m, rde, seg)) >> 4);
}
static void OpPopSeg(struct Machine *m, uint32_t rde) {
static relegated void OpPopSeg(struct Machine *m, uint32_t rde) {
uint8_t seg = (m->xedd->op.opcode & 070) >> 3;
Write64(GetSegment(m, rde, seg), Pop(m, rde, 0) << 4);
}
static void OpMovEvqpSw(struct Machine *m, uint32_t rde) {
static relegated void OpMovEvqpSw(struct Machine *m, uint32_t rde) {
WriteRegisterOrMemory(rde, GetModrmRegisterWordPointerWriteOszRexw(m, rde),
Read64(GetSegment(m, rde, ModrmReg(rde))) >> 4);
}
static void OpMovSwEvqp(struct Machine *m, uint32_t rde) {
static relegated void OpMovSwEvqp(struct Machine *m, uint32_t rde) {
Write64(GetSegment(m, rde, ModrmReg(rde)),
ReadMemory(rde, GetModrmRegisterWordPointerReadOszRexw(m, rde)) << 4);
}
static void OpJmpf(struct Machine *m, uint32_t rde) {
static relegated void OpJmpf(struct Machine *m, uint32_t rde) {
Write64(m->cs, m->xedd->op.uimm0 << 4);
m->ip = m->xedd->op.disp;
}
@ -474,7 +449,8 @@ static void OpBit(struct Machine *m, uint32_t rde) {
SetWriteAddr(m, v, 1 << w);
}
}
y = 1ull << bit;
y = 1;
y <<= bit;
x = ReadMemory(rde, p);
m->flags = SetFlag(m->flags, FLAGS_CF, !!(y & x));
switch (op) {
@ -495,7 +471,7 @@ static void OpBit(struct Machine *m, uint32_t rde) {
WriteRegisterOrMemory(rde, p, z);
}
static void OpConvert1(struct Machine *m, uint32_t rde) {
static void OpSax(struct Machine *m, uint32_t rde) {
if (Rexw(rde)) {
Write64(m->ax, (int32_t)Read32(m->ax));
} else if (!Osz(rde)) {
@ -505,7 +481,7 @@ static void OpConvert1(struct Machine *m, uint32_t rde) {
}
}
static void OpConvert2(struct Machine *m, uint32_t rde) {
static void OpConvert(struct Machine *m, uint32_t rde) {
if (Rexw(rde)) {
Write64(m->dx, Read64(m->ax) & 0x8000000000000000 ? 0xffffffffffffffff : 0);
} else if (!Osz(rde)) {
@ -530,7 +506,7 @@ static void OpBswapZvqp(struct Machine *m, uint32_t rde) {
((x & 0xff000000) >> 030 | (x & 0x000000ff) << 030 |
(x & 0x00ff0000) >> 010 | (x & 0x0000ff00) << 010));
} else {
Write16(RegRexbSrm(m, rde), ((x & 0x00ff) << 010 | (x & 0xff00) << 010));
Write16(RegRexbSrm(m, rde), (x & 0x00ff) << 010 | (x & 0xff00) << 010);
}
}
@ -625,18 +601,41 @@ static void OpMovswGvqpEw(struct Machine *m, uint32_t rde) {
}
static void OpMovsxdGdqpEd(struct Machine *m, uint32_t rde) {
uint64_t x;
uint8_t *p;
x = (int32_t)Read32(GetModrmRegisterWordPointerRead4(m, rde));
if (!Rexw(rde)) x &= 0xffffffff; /* wut */
Write64(RegRexrReg(m, rde), x);
Write64(RegRexrReg(m, rde),
(int32_t)Read32(GetModrmRegisterWordPointerRead4(m, rde)));
}
static void OpAlub(struct Machine *m, uint32_t rde) {
uint8_t *a;
a = GetModrmRegisterBytePointerWrite(m, rde);
Write8(a, kAlu[(m->xedd->op.opcode & 070) >> 3][0](
Read8(a), Read8(ByteRexrReg(m, rde)), &m->flags));
static void Alub(struct Machine *m, uint32_t rde, aluop_f op) {
uint8_t *a = GetModrmRegisterBytePointerWrite(m, rde);
Write8(a, op(Read8(a), Read8(ByteRexrReg(m, rde)), &m->flags));
}
static void OpAlubAdd(struct Machine *m, uint32_t rde) {
Alub(m, rde, Add8);
}
static void OpAlubOr(struct Machine *m, uint32_t rde) {
Alub(m, rde, Or8);
}
static void OpAlubAdc(struct Machine *m, uint32_t rde) {
Alub(m, rde, Adc8);
}
static void OpAlubSbb(struct Machine *m, uint32_t rde) {
Alub(m, rde, Sbb8);
}
static void OpAlubAnd(struct Machine *m, uint32_t rde) {
Alub(m, rde, And8);
}
static void OpAlubSub(struct Machine *m, uint32_t rde) {
Alub(m, rde, Sub8);
}
static void OpAlubXor(struct Machine *m, uint32_t rde) {
Alub(m, rde, Xor8);
}
static void AlubRo(struct Machine *m, uint32_t rde, aluop_f op) {
@ -652,11 +651,38 @@ static void OpAlubTest(struct Machine *m, uint32_t rde) {
AlubRo(m, rde, And8);
}
static void OpAlubFlip(struct Machine *m, uint32_t rde) {
static void AlubFlip(struct Machine *m, uint32_t rde, aluop_f op) {
Write8(ByteRexrReg(m, rde),
kAlu[(m->xedd->op.opcode & 070) >> 3][0](
Read8(ByteRexrReg(m, rde)),
Read8(GetModrmRegisterBytePointerRead(m, rde)), &m->flags));
op(Read8(ByteRexrReg(m, rde)),
Read8(GetModrmRegisterBytePointerRead(m, rde)), &m->flags));
}
static void OpAlubFlipAdd(struct Machine *m, uint32_t rde) {
AlubFlip(m, rde, Add8);
}
static void OpAlubFlipOr(struct Machine *m, uint32_t rde) {
AlubFlip(m, rde, Or8);
}
static void OpAlubFlipAdc(struct Machine *m, uint32_t rde) {
AlubFlip(m, rde, Adc8);
}
static void OpAlubFlipSbb(struct Machine *m, uint32_t rde) {
AlubFlip(m, rde, Sbb8);
}
static void OpAlubFlipAnd(struct Machine *m, uint32_t rde) {
AlubFlip(m, rde, And8);
}
static void OpAlubFlipSub(struct Machine *m, uint32_t rde) {
AlubFlip(m, rde, Sub8);
}
static void OpAlubFlipXor(struct Machine *m, uint32_t rde) {
AlubFlip(m, rde, Xor8);
}
static void AlubFlipRo(struct Machine *m, uint32_t rde, aluop_f op) {
@ -765,9 +791,36 @@ static void OpAluwiReg(struct Machine *m, uint32_t rde) {
}
}
static void OpAluAlIb(struct Machine *m, uint32_t rde) {
Write8(m->ax, kAlu[(m->xedd->op.opcode & 070) >> 3][0](
Read8(m->ax), m->xedd->op.uimm0, &m->flags));
static void AluAlIb(struct Machine *m, aluop_f op) {
Write8(m->ax, op(Read8(m->ax), m->xedd->op.uimm0, &m->flags));
}
static void OpAluAlIbAdd(struct Machine *m, uint32_t rde) {
AluAlIb(m, Add8);
}
static void OpAluAlIbOr(struct Machine *m, uint32_t rde) {
AluAlIb(m, Or8);
}
static void OpAluAlIbAdc(struct Machine *m, uint32_t rde) {
AluAlIb(m, Adc8);
}
static void OpAluAlIbSbb(struct Machine *m, uint32_t rde) {
AluAlIb(m, Sbb8);
}
static void OpAluAlIbAnd(struct Machine *m, uint32_t rde) {
AluAlIb(m, And8);
}
static void OpAluAlIbSub(struct Machine *m, uint32_t rde) {
AluAlIb(m, Sub8);
}
static void OpAluAlIbXor(struct Machine *m, uint32_t rde) {
AluAlIb(m, Xor8);
}
static void OpAluRaxIvds(struct Machine *m, uint32_t rde) {
@ -831,18 +884,19 @@ static void OpBsubiImm(struct Machine *m, uint32_t rde) {
Bsubi(m, rde, m->xedd->op.uimm0);
}
static void LoadFarPointer(struct Machine *m, uint32_t rde, uint8_t seg[8]) {
static relegated void LoadFarPointer(struct Machine *m, uint32_t rde,
uint8_t seg[8]) {
uint32_t fp;
fp = Read32(ComputeReserveAddressRead4(m, rde));
Write64(seg, (fp & 0x0000ffff) << 4);
Write16(RegRexrReg(m, rde), fp >> 16);
}
static void OpLes(struct Machine *m, uint32_t rde) {
static relegated void OpLes(struct Machine *m, uint32_t rde) {
LoadFarPointer(m, rde, m->es);
}
static void OpLds(struct Machine *m, uint32_t rde) {
static relegated void OpLds(struct Machine *m, uint32_t rde) {
LoadFarPointer(m, rde, m->ds);
}
@ -853,14 +907,6 @@ static void OpPushImm(struct Machine *m, uint32_t rde) {
Push(m, rde, m->xedd->op.uimm0);
}
static void OpRet0(struct Machine *m, uint32_t rde) {
OpRet(m, rde, 0);
}
static void OpRetImm(struct Machine *m, uint32_t rde) {
OpRet(m, rde, m->xedd->op.uimm0);
}
static void Interrupt(struct Machine *m, uint32_t rde, int i) {
HaltMachine(m, i);
}
@ -1213,17 +1259,18 @@ static void OpNegEb(struct Machine *m, uint32_t rde) {
AluEb(m, rde, Neg8);
}
static const nexgen32e_f kOp0f6[] = {
OpAlubiTest,
OpAlubiTest,
OpNotEb,
OpNegEb,
OpMulAxAlEbUnsigned,
OpMulAxAlEbSigned,
OpDivAlAhAxEbUnsigned,
OpDivAlAhAxEbSigned,
};
static void Op0f6(struct Machine *m, uint32_t rde) {
static const nexgen32e_f kOp0f6[] = {
OpAlubiTest,
OpAlubiTest,
OpNotEb,
OpNegEb,
OpMulAxAlEbUnsigned,
OpMulAxAlEbSigned,
OpDivAlAhAxEbUnsigned,
OpDivAlAhAxEbSigned,
};
kOp0f6[ModrmReg(rde)](m, rde);
}
@ -1239,17 +1286,18 @@ static void OpNegEvqp(struct Machine *m, uint32_t rde) {
AluEvqp(m, rde, kAlu[ALU_NEG]);
}
static const nexgen32e_f kOp0f7[] = {
OpTestEvqpIvds,
OpTestEvqpIvds,
OpNotEvqp,
OpNegEvqp,
OpMulRdxRaxEvqpUnsigned,
OpMulRdxRaxEvqpSigned,
OpDivRdxRaxEvqpUnsigned,
OpDivRdxRaxEvqpSigned,
};
static void Op0f7(struct Machine *m, uint32_t rde) {
static const nexgen32e_f kOp0f7[] = {
OpTestEvqpIvds,
OpTestEvqpIvds,
OpNotEvqp,
OpNegEvqp,
OpMulRdxRaxEvqpUnsigned,
OpMulRdxRaxEvqpSigned,
OpDivRdxRaxEvqpUnsigned,
OpDivRdxRaxEvqpSigned,
};
kOp0f7[ModrmReg(rde)](m, rde);
}
@ -1274,9 +1322,10 @@ static void OpDecEvqp(struct Machine *m, uint32_t rde) {
AluEvqp(m, rde, kAlu[ALU_DEC]);
}
static const nexgen32e_f kOp0ff[] = {OpIncEvqp, OpDecEvqp, OpCallEq, OpUd,
OpJmpEq, OpUd, OpPushEvq, OpUd};
static void Op0ff(struct Machine *m, uint32_t rde) {
static const nexgen32e_f kOp0ff[] = {OpIncEvqp, OpDecEvqp, OpCallEq, OpUd,
OpJmpEq, OpUd, OpPushEvq, OpUd};
kOp0ff[ModrmReg(rde)](m, rde);
}
@ -1295,57 +1344,6 @@ static void Op101(struct Machine *m, uint32_t rde) {
OpUd(m, rde);
}
static void Op171(struct Machine *m, uint32_t rde) {
switch (ModrmReg(rde)) {
case 2:
OpSseUdqIb(m, rde, kOpSseUdqIbPsrlw);
break;
case 4:
OpSseUdqIb(m, rde, kOpSseUdqIbPsraw);
break;
case 6:
OpSseUdqIb(m, rde, kOpSseUdqIbPsllw);
break;
default:
OpUd(m, rde);
}
}
static void Op172(struct Machine *m, uint32_t rde) {
switch (ModrmReg(rde)) {
case 2:
OpSseUdqIb(m, rde, kOpSseUdqIbPsrld);
break;
case 4:
OpSseUdqIb(m, rde, kOpSseUdqIbPsrad);
break;
case 6:
OpSseUdqIb(m, rde, kOpSseUdqIbPslld);
break;
default:
OpUd(m, rde);
}
}
static void Op173(struct Machine *m, uint32_t rde) {
switch (ModrmReg(rde)) {
case 2:
OpSseUdqIb(m, rde, kOpSseUdqIbPsrlq);
break;
case 3:
OpSseUdqIb(m, rde, kOpSseUdqIbPsrldq);
break;
case 6:
OpSseUdqIb(m, rde, kOpSseUdqIbPsllq);
break;
case 7:
OpSseUdqIb(m, rde, kOpSseUdqIbPslldq);
break;
default:
OpUd(m, rde);
}
}
static void OpDoubleShift(struct Machine *m, uint32_t rde) {
uint8_t *p;
uint64_t x;
@ -1386,6 +1384,8 @@ static void OpSalc(struct Machine *m, uint32_t rde) {
static void OpNopEv(struct Machine *m, uint32_t rde) {
if (ModrmMod(rde) == 0b01 && ModrmReg(rde) == 0 && ModrmRm(rde) == 0b101) {
OpBofram(m, rde);
} else {
OpNoop(m, rde);
}
}
@ -1394,63 +1394,65 @@ static void OpNop(struct Machine *m, uint32_t rde) {
OpXchgZvqp(m, rde);
} else if (Rep(rde) == 3) {
OpPause(m, rde);
} else {
OpNoop(m, rde);
}
}
static const nexgen32e_f kNexgen32e[] = {
[0x000] = OpAlub,
[0x000] = OpAlubAdd,
[0x001] = OpAluw,
[0x002] = OpAlubFlip,
[0x002] = OpAlubFlipAdd,
[0x003] = OpAluwFlip,
[0x004] = OpAluAlIb,
[0x004] = OpAluAlIbAdd,
[0x005] = OpAluRaxIvds,
[0x006] = OpPushSeg,
[0x007] = OpPopSeg,
[0x008] = OpAlub,
[0x008] = OpAlubOr,
[0x009] = OpAluw,
[0x00A] = OpAlubFlip,
[0x00A] = OpAlubFlipOr,
[0x00B] = OpAluwFlip,
[0x00C] = OpAluAlIb,
[0x00C] = OpAluAlIbOr,
[0x00D] = OpAluRaxIvds,
[0x00E] = OpPushSeg,
[0x00F] = OpPopSeg,
[0x010] = OpAlub,
[0x010] = OpAlubAdc,
[0x011] = OpAluw,
[0x012] = OpAlubFlip,
[0x012] = OpAlubFlipAdc,
[0x013] = OpAluwFlip,
[0x014] = OpAluAlIb,
[0x014] = OpAluAlIbAdc,
[0x015] = OpAluRaxIvds,
[0x016] = OpPushSeg,
[0x017] = OpPopSeg,
[0x018] = OpAlub,
[0x018] = OpAlubSbb,
[0x019] = OpAluw,
[0x01A] = OpAlubFlip,
[0x01A] = OpAlubFlipSbb,
[0x01B] = OpAluwFlip,
[0x01C] = OpAluAlIb,
[0x01C] = OpAluAlIbSbb,
[0x01D] = OpAluRaxIvds,
[0x01E] = OpPushSeg,
[0x01F] = OpPopSeg,
[0x020] = OpAlub,
[0x020] = OpAlubAnd,
[0x021] = OpAluw,
[0x022] = OpAlubFlip,
[0x022] = OpAlubFlipAnd,
[0x023] = OpAluwFlip,
[0x024] = OpAluAlIb,
[0x024] = OpAluAlIbAnd,
[0x025] = OpAluRaxIvds,
[0x026] = OpPushSeg,
[0x027] = OpPopSeg,
[0x028] = OpAlub,
[0x028] = OpAlubSub,
[0x029] = OpAluw,
[0x02A] = OpAlubFlip,
[0x02A] = OpAlubFlipSub,
[0x02B] = OpAluwFlip,
[0x02C] = OpAluAlIb,
[0x02C] = OpAluAlIbSub,
[0x02D] = OpAluRaxIvds,
[0x02E] = OpUd,
[0x02F] = OpDas,
[0x030] = OpAlub,
[0x030] = OpAlubXor,
[0x031] = OpAluw,
[0x032] = OpAlubFlip,
[0x032] = OpAlubFlipXor,
[0x033] = OpAluwFlip,
[0x034] = OpAluAlIb,
[0x034] = OpAluAlIbXor,
[0x035] = OpAluRaxIvds,
[0x036] = OpUd,
[0x037] = OpAaa,
@ -1550,9 +1552,9 @@ static const nexgen32e_f kNexgen32e[] = {
[0x095] = OpXchgZvqp,
[0x096] = OpXchgZvqp,
[0x097] = OpXchgZvqp,
[0x098] = OpConvert1,
[0x099] = OpConvert2,
[0x09A] = OpUd,
[0x098] = OpSax,
[0x099] = OpConvert,
[0x09A] = OpCallf,
[0x09B] = OpFwait,
[0x09C] = OpPushf,
[0x09D] = OpPopf,
@ -1592,16 +1594,16 @@ static const nexgen32e_f kNexgen32e[] = {
[0x0BF] = OpMovZvqpIvqp,
[0x0C0] = OpBsubiImm,
[0x0C1] = OpBsuwiImm,
[0x0C2] = OpRetImm,
[0x0C3] = OpRet0,
[0x0C2] = OpRet,
[0x0C3] = OpRet,
[0x0C4] = OpLes,
[0x0C5] = OpLds,
[0x0C6] = OpMovEbIb,
[0x0C7] = OpMovEvqpIvds,
[0x0C8] = OpUd,
[0x0C9] = OpLeave,
[0x0CA] = OpUd,
[0x0CB] = OpUd,
[0x0CA] = OpRetf,
[0x0CB] = OpRetf,
[0x0CC] = OpInterrupt3,
[0x0CD] = OpInterruptImm,
[0x0CE] = OpUd,
@ -1667,7 +1669,7 @@ static const nexgen32e_f kNexgen32e[] = {
[0x10A] = OpUd,
[0x10B] = OpUd,
[0x10C] = OpUd,
[0x10D] = OpWutNopEv,
[0x10D] = OpHintNopEv,
[0x10E] = OpUd,
[0x10F] = OpUd,
[0x110] = OpMov0f10,
@ -1678,12 +1680,12 @@ static const nexgen32e_f kNexgen32e[] = {
[0x115] = OpUnpckhpsd,
[0x116] = OpMov0f16,
[0x117] = OpMov0f17,
[0x118] = OpWutNopEv,
[0x119] = OpWutNopEv,
[0x11A] = OpWutNopEv,
[0x11B] = OpWutNopEv,
[0x11C] = OpWutNopEv,
[0x11D] = OpWutNopEv,
[0x118] = OpHintNopEv,
[0x119] = OpHintNopEv,
[0x11A] = OpHintNopEv,
[0x11B] = OpHintNopEv,
[0x11C] = OpHintNopEv,
[0x11D] = OpHintNopEv,
[0x11E] = OpUd,
[0x11F] = OpNopEv,
[0x120] = OpUd,

View file

@ -137,12 +137,13 @@ struct Machine {
uint32_t i;
void *p[6];
} freelist;
int64_t brk;
int64_t bofram[2];
jmp_buf onhalt;
int64_t faultaddr;
uint8_t stash[4096];
uint8_t xmmtype[2][8];
uint8_t icache[2048][40] aligned(8);
uint8_t icache[4096 / 4][40] aligned(16);
struct MachineFds fds;
} aligned(64);

View file

@ -22,12 +22,45 @@
#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;
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) {
if (v[y][x][1]) {
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

@ -26,29 +26,54 @@
#include "tool/build/lib/modrm.h"
#include "tool/build/lib/throw.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};
static relegated noinline int64_t ComputeAddressReal(const struct Machine *m,
uint32_t rde, uint8_t *s,
uint64_t i) {
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:
unreachable;
}
i &= 0xffff;
return AddSegment(m, rde, i, s);
}
int64_t ComputeAddress(const struct Machine *m, uint32_t rde) {
uint64_t i;
uint8_t *s;
uint8_t *s = m->ds;
uint64_t i = m->xedd->op.disp;
DCHECK(!IsModrmRegister(rde));
s = m->ds;
i = m->xedd->op.disp;
if (Eamode(rde) != XED_MODE_REAL) {
if (!SibExists(rde)) {
if (IsRipRelative(rde)) {
@ -75,47 +100,10 @@ int64_t ComputeAddress(const struct Machine *m, uint32_t rde) {
if (Eamode(rde) == XED_MODE_LEGACY) {
i &= 0xffffffff;
}
return AddSegment(m, rde, i, s);
} 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:
unreachable;
}
i &= 0xffff;
return ComputeAddressReal(m, rde, s, i);
}
return AddSegment(m, rde, i, s);
}
void *ComputeReserveAddressRead(struct Machine *m, uint32_t rde, size_t n) {

View file

@ -2,8 +2,6 @@
#define COSMOPOLITAN_TOOL_BUILD_LIB_MODRM_H_
#include "tool/build/lib/abp.h"
#include "tool/build/lib/machine.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define Rex(x) ((x & 000000000020) >> 004)
#define Osz(x) ((x & 000000000040) >> 005)
@ -21,12 +19,16 @@ COSMOPOLITAN_C_START_
#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 RexbBase(m, x) (Rexb(x) << 3 | m->xedd->op.base)
#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])

View file

@ -36,12 +36,13 @@
* @param p is panel list in logically sorted order
* @param tyn is terminal height in cells
* @param txn is terminal width in cells
* @return bytes emitted, or -1 w/ errno
* @return -1 w/ errno if an error happened
* @see nblack's notcurses project too!
*/
ssize_t PrintPanels(int fd, long pn, struct Panel p[pn], long tyn, long txn) {
wint_t wc;
ssize_t rc;
size_t wrote;
struct Buffer b, *l;
int x, y, i, j, width;
enum { kUtf8, kAnsi, kAnsiCsi } state;

View file

@ -53,10 +53,11 @@ static uint64_t *GetPageTable(pml4t_t p, long i, void *NewPhysicalPage(void)) {
}
static void PtFinder(uint64_t *a, uint64_t *b, uint64_t n, pml4t_t pd, int k) {
unsigned i;
uint64_t e, c;
unsigned start;
for (start = (*b >> k) & 511; *b - *a < n && ((*b >> k) & 511) >= start;) {
e = pd[(*b >> k) & 511];
while (*b - *a < n) {
i = (*b >> k) & 511;
e = pd[i];
c = ROUNDUP(*b + 1, 1 << k);
if (!IsValidPage(e)) {
*b = c;
@ -65,6 +66,9 @@ static void PtFinder(uint64_t *a, uint64_t *b, uint64_t n, pml4t_t pd, int k) {
} else {
*a = *b = c;
}
if (((*b >> k) & 511) < i) {
break;
}
}
}

View file

@ -17,9 +17,11 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/alg/arraylist2.h"
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.h"
#include "libc/conv/conv.h"
#include "libc/conv/itoa.h"
#include "libc/log/check.h"
#include "libc/macros.h"
#include "libc/mem/mem.h"
@ -32,13 +34,18 @@
#include "tool/build/lib/pty.h"
struct MachinePty *MachinePtyNew(void) {
return xcalloc(1, sizeof(struct MachinePty));
struct MachinePty *pty;
pty = xcalloc(1, sizeof(struct MachinePty));
MachinePtyResize(pty, 25, 80);
return pty;
}
void MachinePtyResize(struct MachinePty *pty, int yn, int xn) {
unsigned y, ym, xm, y0;
uint32_t *wcs, *fgs, *bgs, *prs;
if (yn <= 0 || xn <= 0) return;
if (xn < 80) xn = 80;
if (yn < 25) yn = 25;
if (xn == pty->xn && yn == pty->yn) return;
wcs = xcalloc(yn * xn, 4);
fgs = xcalloc(yn * xn, 4);
bgs = xcalloc(yn * xn, 4);
@ -92,7 +99,9 @@ static void MachinePtyNewline(struct MachinePty *pty) {
pty->x = 0;
if (++pty->y == pty->yn) {
--pty->y;
MachinePtyScroll(pty);
if (!(pty->conf & kMachinePtyNoopost)) {
MachinePtyScroll(pty);
}
}
}
@ -335,6 +344,38 @@ static void MachinePtyShowCursor(struct MachinePty *pty) {
pty->conf &= ~kMachinePtyNocursor;
}
static void MachinePtyReportCursorPosition(struct MachinePty *pty) {
char *p;
char buf[2 + 10 + 1 + 10 + 1];
p = buf;
*p++ = '\e';
*p++ = '[';
p += uint64toarray_radix10((pty->y + 1) & 0xffffffff, p);
*p++ = ';';
p += uint64toarray_radix10((pty->x + 1) & 0xffffffff, p);
*p++ = 'R';
CONCAT(&pty->input.p, &pty->input.i, &pty->input.n, buf, p - buf);
}
static void MachinePtyCsiN(struct MachinePty *pty) {
switch (atoi(pty->esc.s)) {
case 6:
MachinePtyReportCursorPosition(pty);
break;
default:
break;
}
}
static void MachinePtyCsiScrollUp(struct MachinePty *pty) {
int n;
n = atoi(pty->esc.s);
n = MAX(1, n);
while (n--) {
MachinePtyScroll(pty);
}
}
static void MachinePtyCsi(struct MachinePty *pty) {
switch (pty->esc.s[pty->esc.i - 1]) {
case 'A':
@ -362,6 +403,12 @@ static void MachinePtyCsi(struct MachinePty *pty) {
case 'm':
MachinePtySelectGraphicsRendition(pty);
break;
case 'n':
MachinePtyCsiN(pty);
break;
case 'S':
MachinePtyCsiScrollUp(pty);
break;
case 'l':
if (strcmp(pty->esc.s, "?25l") == 0) {
MachinePtyHideCursor(pty);
@ -389,7 +436,6 @@ static void MachinePtyEscAppend(struct MachinePty *pty, char c) {
ssize_t MachinePtyWrite(struct MachinePty *pty, const void *data, size_t n) {
int i;
const uint8_t *p;
if (!pty->yn || !pty->xn) return 0;
for (p = data, i = 0; i < n; ++i) {
switch (pty->state) {
case kMachinePtyAscii:
@ -408,6 +454,14 @@ ssize_t MachinePtyWrite(struct MachinePty *pty, const void *data, size_t n) {
case '\n':
MachinePtyNewline(pty);
break;
case 0177:
case '\b':
pty->x = MAX(0, pty->x - 1);
break;
case '\f':
break;
case '\a':
break;
default:
SetMachinePtyCell(pty, p[i]);
break;
@ -483,47 +537,87 @@ ssize_t MachinePtyWrite(struct MachinePty *pty, const void *data, size_t n) {
return n;
}
ssize_t MachinePtyWriteInput(struct MachinePty *pty, const void *data,
size_t n) {
const char *p = data;
CONCAT(&pty->input.p, &pty->input.i, &pty->input.n, data, n);
if (!(pty->conf & kMachinePtyNoecho)) {
MachinePtyWrite(pty, data, n);
}
return n;
}
ssize_t MachinePtyRead(struct MachinePty *pty, void *buf, size_t size) {
char *p;
size_t n;
n = MIN(size, pty->input.i);
if (!(pty->conf & kMachinePtyNocanon)) {
if ((p = memchr(pty->input.p, '\n', n))) {
n = MIN(n, pty->input.p - p + 1);
} else {
n = 0;
}
}
memcpy(buf, pty->input.p, n);
memcpy(pty->input.p, pty->input.p + n, pty->input.i - n);
pty->input.i -= n;
return n;
}
void MachinePtyAppendLine(struct MachinePty *pty, struct Buffer *buf,
unsigned y) {
bool atcursor;
uint32_t x, i, fg, bg, pr, wc, w;
if (y >= pty->yn) return;
for (fg = bg = pr = x = 0; x < pty->xn; x += w) {
i = y * pty->xn + x;
wc = pty->wcs[i];
w = MAX(0, wcwidth(wc));
if (w) {
if (pty->prs[i] != pr || pty->fgs[i] != fg || pty->bgs[i] != bg) {
fg = pty->fgs[i];
bg = pty->bgs[i];
pr = pty->prs[i];
AppendStr(buf, "\e[0");
if (pr & kMachinePtyBold) AppendStr(buf, ";1");
if (pr & kMachinePtyFaint) AppendStr(buf, ";2");
if (pr & kMachinePtyFlip) AppendStr(buf, ";7");
if (pr & kMachinePtyFg) {
if (pr & kMachinePtyTrue) {
AppendFmt(buf, ";38;2;%d;%d;%d", (fg & 0x0000ff) >> 000,
(fg & 0x00ff00) >> 010, (fg & 0xff0000) >> 020);
} else {
AppendFmt(buf, ";38;5;%d", fg);
}
}
if (pr & kMachinePtyBg) {
if (pr & kMachinePtyTrue) {
AppendFmt(buf, ";48;2;%d;%d;%d", (bg & 0x0000ff) >> 000,
(bg & 0x00ff00) >> 010, (bg & 0xff0000) >> 020);
} else {
AppendFmt(buf, ";48;5;%d", bg);
}
}
AppendStr(buf, "m");
atcursor = y == pty->y && x == pty->x;
if ((w && atcursor) ||
(pty->prs[i] != pr || pty->fgs[i] != fg || pty->bgs[i] != bg)) {
fg = pty->fgs[i];
bg = pty->bgs[i];
pr = pty->prs[i];
AppendStr(buf, "\e[0");
if (w && atcursor) {
pr ^= kMachinePtyFlip;
}
if (pr & kMachinePtyBold) AppendStr(buf, ";1");
if (pr & kMachinePtyFaint) AppendStr(buf, ";2");
if (pr & kMachinePtyBlink) AppendStr(buf, ";5");
if (pr & kMachinePtyFlip) AppendStr(buf, ";7");
if (pr & kMachinePtyFg) {
if (pr & kMachinePtyTrue) {
AppendFmt(buf, ";38;2;%d;%d;%d", (fg & 0x0000ff) >> 000,
(fg & 0x00ff00) >> 010, (fg & 0xff0000) >> 020);
} else {
AppendFmt(buf, ";38;5;%d", fg);
}
}
if (pr & kMachinePtyBg) {
if (pr & kMachinePtyTrue) {
AppendFmt(buf, ";48;2;%d;%d;%d", (bg & 0x0000ff) >> 000,
(bg & 0x00ff00) >> 010, (bg & 0xff0000) >> 020);
} else {
AppendFmt(buf, ";48;5;%d", bg);
}
}
AppendStr(buf, "m");
}
if (w) {
AppendWide(buf, wc);
} else {
w = 1;
if (y == pty->y && x == pty->x) {
if (atcursor) {
if (!(pty->conf & kMachinePtyNocursor)) {
AppendStr(buf, "\e[5m▂\e[25m");
if (pty->conf & kMachinePtyBlinkcursor) {
AppendStr(buf, "\e[5m");
}
AppendWide(buf, u'');
if (pty->conf & kMachinePtyBlinkcursor) {
AppendStr(buf, "\e[25m");
}
}
} else {
AppendChar(buf, ' ');

View file

@ -8,17 +8,22 @@
#define kMachinePtyBold 0x08
#define kMachinePtyFaint 0x10
#define kMachinePtyFlip 0x20
#define kMachinePtyBlink 0x40
#define kMachinePtyNocursor 0x01
#define kMachinePtyNocursor 0x01
#define kMachinePtyBlinkcursor 0x02
#define kMachinePtyNocanon 0x04
#define kMachinePtyNoecho 0x08
#define kMachinePtyNoopost 0x10
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct MachinePty {
uint32_t yn;
uint32_t xn;
uint32_t y;
uint32_t x;
int y;
int x;
int yn;
int xn;
uint32_t pr;
uint32_t fg;
uint32_t bg;
@ -38,12 +43,18 @@ struct MachinePty {
unsigned i;
char s[64];
} esc;
struct MachinePtyInput {
size_t i, n;
char *p;
} input;
};
void MachinePtyFree(struct MachinePty *);
struct MachinePty *MachinePtyNew(void) nodiscard;
void MachinePtyResize(struct MachinePty *, int, int);
ssize_t MachinePtyRead(struct MachinePty *, void *, size_t);
ssize_t MachinePtyWrite(struct MachinePty *, const void *, size_t);
ssize_t MachinePtyWriteInput(struct MachinePty *, const void *, size_t);
void MachinePtyAppendLine(struct MachinePty *, struct Buffer *, unsigned);
COSMOPOLITAN_C_END_

View file

@ -100,19 +100,7 @@
#include "tool/build/lib/memory.h"
#include "tool/build/lib/modrm.h"
#include "tool/build/lib/sse.h"
union MachineVector {
float f32[4];
double f64[2];
int8_t i8[16];
int16_t i16[8];
int32_t i32[4];
int64_t i64[2];
uint8_t u8[16];
uint16_t u16[8];
uint32_t u32[4];
uint64_t u64[2];
};
#include "tool/build/lib/throw.h"
static void SsePsubb(void *b, const void *a) {
psubb(b, b, a);
@ -711,29 +699,81 @@ void OpSsePmulld(struct Machine *m, uint32_t rde) {
OpSse(m, rde, SsePmulld);
}
void OpSseUdqIb(struct Machine *m, uint32_t rde, enum OpSseUdqIbKernel kernel) {
static void SseUdqIb(struct Machine *m, uint32_t rde, int kernel) {
void *y;
uint8_t i;
union MachineVector x;
uint8_t x[16];
i = m->xedd->op.uimm0;
memcpy(&x, XmmRexbRm(m, rde), 16);
y = XmmRexbRm(m, rde);
switch (kernel) {
CASE(kOpSseUdqIbPsrlw, (psrlw)(x.u16, x.u16, i));
CASE(kOpSseUdqIbPsraw, (psraw)(x.i16, x.i16, i));
CASE(kOpSseUdqIbPsllw, (psllw)(x.u16, x.u16, i));
CASE(kOpSseUdqIbPsrld, (psrld)(x.u32, x.u32, i));
CASE(kOpSseUdqIbPsrad, (psrad)(x.i32, x.i32, i));
CASE(kOpSseUdqIbPslld, (pslld)(x.u32, x.u32, i));
CASE(kOpSseUdqIbPsrlq, (psrlq)(x.u64, x.u64, i));
CASE(kOpSseUdqIbPsrldq, (psrldq)(x.u8, x.u8, i));
CASE(kOpSseUdqIbPsllq, (psllq)(x.u64, x.u64, i));
CASE(kOpSseUdqIbPslldq, (pslldq)(x.u8, x.u8, i));
CASE(0, (psrlw)((void *)x, y, i));
CASE(1, (psraw)((void *)x, y, i));
CASE(2, (psllw)((void *)x, y, i));
CASE(3, (psrld)((void *)x, y, i));
CASE(4, (psrad)((void *)x, y, i));
CASE(5, (pslld)((void *)x, y, i));
CASE(6, (psrlq)((void *)x, y, i));
CASE(7, (psrldq)((void *)x, y, i));
CASE(8, (psllq)((void *)x, y, i));
CASE(9, (pslldq)((void *)x, y, i));
default:
unreachable;
}
if (Osz(rde)) {
memcpy(XmmRexbRm(m, rde), &x, 16);
memcpy(XmmRexbRm(m, rde), x, 16);
} else {
memcpy(XmmRexbRm(m, rde), &x, 8);
memcpy(XmmRexbRm(m, rde), x, 8);
}
}
void Op171(struct Machine *m, uint32_t rde) {
switch (ModrmReg(rde)) {
case 2:
SseUdqIb(m, rde, 0);
break;
case 4:
SseUdqIb(m, rde, 1);
break;
case 6:
SseUdqIb(m, rde, 2);
break;
default:
OpUd(m, rde);
}
}
void Op172(struct Machine *m, uint32_t rde) {
switch (ModrmReg(rde)) {
case 2:
SseUdqIb(m, rde, 3);
break;
case 4:
SseUdqIb(m, rde, 4);
break;
case 6:
SseUdqIb(m, rde, 5);
break;
default:
OpUd(m, rde);
}
}
void Op173(struct Machine *m, uint32_t rde) {
switch (ModrmReg(rde)) {
case 2:
SseUdqIb(m, rde, 6);
break;
case 3:
SseUdqIb(m, rde, 7);
break;
case 6:
SseUdqIb(m, rde, 8);
break;
case 7:
SseUdqIb(m, rde, 9);
break;
default:
OpUd(m, rde);
}
}

View file

@ -4,96 +4,83 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
typedef void (*sse_f)(void *, void *, void *);
enum OpSseUdqIbKernel {
kOpSseUdqIbPsrlw,
kOpSseUdqIbPsraw,
kOpSseUdqIbPsllw,
kOpSseUdqIbPsrld,
kOpSseUdqIbPsrad,
kOpSseUdqIbPslld,
kOpSseUdqIbPsrlq,
kOpSseUdqIbPsrldq,
kOpSseUdqIbPsllq,
kOpSseUdqIbPslldq,
};
void OpSseUdqIb(struct Machine *, uint32_t, enum OpSseUdqIbKernel);
void OpSsePalignr(struct Machine *, uint32_t);
void OpSsePunpcklbw(struct Machine *, uint32_t);
void OpSsePunpcklwd(struct Machine *, uint32_t);
void OpSsePunpckldq(struct Machine *, uint32_t);
void OpSsePacksswb(struct Machine *, uint32_t);
void OpSsePcmpgtb(struct Machine *, uint32_t);
void OpSsePcmpgtw(struct Machine *, uint32_t);
void OpSsePcmpgtd(struct Machine *, uint32_t);
void OpSsePackuswb(struct Machine *, uint32_t);
void OpSsePunpckhbw(struct Machine *, uint32_t);
void OpSsePunpckhwd(struct Machine *, uint32_t);
void OpSsePunpckhdq(struct Machine *, uint32_t);
void Op171(struct Machine *, uint32_t);
void Op172(struct Machine *, uint32_t);
void Op173(struct Machine *, uint32_t);
void OpSsePabsb(struct Machine *, uint32_t);
void OpSsePabsd(struct Machine *, uint32_t);
void OpSsePabsw(struct Machine *, uint32_t);
void OpSsePackssdw(struct Machine *, uint32_t);
void OpSsePunpcklqdq(struct Machine *, uint32_t);
void OpSsePunpckhqdq(struct Machine *, uint32_t);
void OpSsePcmpeqb(struct Machine *, uint32_t);
void OpSsePcmpeqw(struct Machine *, uint32_t);
void OpSsePcmpeqd(struct Machine *, uint32_t);
void OpSsePsrlwv(struct Machine *, uint32_t);
void OpSsePsrldv(struct Machine *, uint32_t);
void OpSsePsrlqv(struct Machine *, uint32_t);
void OpSsePacksswb(struct Machine *, uint32_t);
void OpSsePackuswb(struct Machine *, uint32_t);
void OpSsePaddb(struct Machine *, uint32_t);
void OpSsePaddd(struct Machine *, uint32_t);
void OpSsePaddq(struct Machine *, uint32_t);
void OpSsePmullw(struct Machine *, uint32_t);
void OpSsePsubusb(struct Machine *, uint32_t);
void OpSsePsubusw(struct Machine *, uint32_t);
void OpSsePminub(struct Machine *, uint32_t);
void OpSsePand(struct Machine *, uint32_t);
void OpSsePaddusb(struct Machine *, uint32_t);
void OpSsePaddusw(struct Machine *, uint32_t);
void OpSsePmaxub(struct Machine *, uint32_t);
void OpSsePandn(struct Machine *, uint32_t);
void OpSsePavgb(struct Machine *, uint32_t);
void OpSsePsrawv(struct Machine *, uint32_t);
void OpSsePsradv(struct Machine *, uint32_t);
void OpSsePavgw(struct Machine *, uint32_t);
void OpSsePmulhuw(struct Machine *, uint32_t);
void OpSsePmulhw(struct Machine *, uint32_t);
void OpSsePsubsb(struct Machine *, uint32_t);
void OpSsePsubsw(struct Machine *, uint32_t);
void OpSsePminsw(struct Machine *, uint32_t);
void OpSsePor(struct Machine *, uint32_t);
void OpSsePaddsb(struct Machine *, uint32_t);
void OpSsePaddsw(struct Machine *, uint32_t);
void OpSsePmaxsw(struct Machine *, uint32_t);
void OpSsePxor(struct Machine *, uint32_t);
void OpSsePsllwv(struct Machine *, uint32_t);
void OpSsePslldv(struct Machine *, uint32_t);
void OpSsePsllqv(struct Machine *, uint32_t);
void OpSsePmuludq(struct Machine *, uint32_t);
void OpSsePmaddwd(struct Machine *, uint32_t);
void OpSsePsadbw(struct Machine *, uint32_t);
void OpSsePsubb(struct Machine *, uint32_t);
void OpSsePsubw(struct Machine *, uint32_t);
void OpSsePsubd(struct Machine *, uint32_t);
void OpSsePsubq(struct Machine *, uint32_t);
void OpSsePaddb(struct Machine *, uint32_t);
void OpSsePaddusb(struct Machine *, uint32_t);
void OpSsePaddusw(struct Machine *, uint32_t);
void OpSsePaddw(struct Machine *, uint32_t);
void OpSsePaddd(struct Machine *, uint32_t);
void OpSsePshufb(struct Machine *, uint32_t);
void OpSsePhaddw(struct Machine *, uint32_t);
void OpSsePalignr(struct Machine *, uint32_t);
void OpSsePand(struct Machine *, uint32_t);
void OpSsePandn(struct Machine *, uint32_t);
void OpSsePavgb(struct Machine *, uint32_t);
void OpSsePavgw(struct Machine *, uint32_t);
void OpSsePcmpeqb(struct Machine *, uint32_t);
void OpSsePcmpeqd(struct Machine *, uint32_t);
void OpSsePcmpeqw(struct Machine *, uint32_t);
void OpSsePcmpgtb(struct Machine *, uint32_t);
void OpSsePcmpgtd(struct Machine *, uint32_t);
void OpSsePcmpgtw(struct Machine *, uint32_t);
void OpSsePhaddd(struct Machine *, uint32_t);
void OpSsePhaddsw(struct Machine *, uint32_t);
void OpSsePmaddubsw(struct Machine *, uint32_t);
void OpSsePhsubw(struct Machine *, uint32_t);
void OpSsePhaddw(struct Machine *, uint32_t);
void OpSsePhsubd(struct Machine *, uint32_t);
void OpSsePhsubsw(struct Machine *, uint32_t);
void OpSsePsignb(struct Machine *, uint32_t);
void OpSsePsignw(struct Machine *, uint32_t);
void OpSsePsignd(struct Machine *, uint32_t);
void OpSsePhsubw(struct Machine *, uint32_t);
void OpSsePmaddubsw(struct Machine *, uint32_t);
void OpSsePmaddwd(struct Machine *, uint32_t);
void OpSsePmaxsw(struct Machine *, uint32_t);
void OpSsePmaxub(struct Machine *, uint32_t);
void OpSsePminsw(struct Machine *, uint32_t);
void OpSsePminub(struct Machine *, uint32_t);
void OpSsePmulhrsw(struct Machine *, uint32_t);
void OpSsePabsb(struct Machine *, uint32_t);
void OpSsePabsw(struct Machine *, uint32_t);
void OpSsePabsd(struct Machine *, uint32_t);
void OpSsePmulhuw(struct Machine *, uint32_t);
void OpSsePmulhw(struct Machine *, uint32_t);
void OpSsePmulld(struct Machine *, uint32_t);
void OpSsePmullw(struct Machine *, uint32_t);
void OpSsePmuludq(struct Machine *, uint32_t);
void OpSsePor(struct Machine *, uint32_t);
void OpSsePsadbw(struct Machine *, uint32_t);
void OpSsePshufb(struct Machine *, uint32_t);
void OpSsePsignb(struct Machine *, uint32_t);
void OpSsePsignd(struct Machine *, uint32_t);
void OpSsePsignw(struct Machine *, uint32_t);
void OpSsePslldv(struct Machine *, uint32_t);
void OpSsePsllqv(struct Machine *, uint32_t);
void OpSsePsllwv(struct Machine *, uint32_t);
void OpSsePsradv(struct Machine *, uint32_t);
void OpSsePsrawv(struct Machine *, uint32_t);
void OpSsePsrldv(struct Machine *, uint32_t);
void OpSsePsrlqv(struct Machine *, uint32_t);
void OpSsePsrlwv(struct Machine *, uint32_t);
void OpSsePsubb(struct Machine *, uint32_t);
void OpSsePsubd(struct Machine *, uint32_t);
void OpSsePsubq(struct Machine *, uint32_t);
void OpSsePsubsb(struct Machine *, uint32_t);
void OpSsePsubsw(struct Machine *, uint32_t);
void OpSsePsubusb(struct Machine *, uint32_t);
void OpSsePsubusw(struct Machine *, uint32_t);
void OpSsePsubw(struct Machine *, uint32_t);
void OpSsePunpckhbw(struct Machine *, uint32_t);
void OpSsePunpckhdq(struct Machine *, uint32_t);
void OpSsePunpckhqdq(struct Machine *, uint32_t);
void OpSsePunpckhwd(struct Machine *, uint32_t);
void OpSsePunpcklbw(struct Machine *, uint32_t);
void OpSsePunpckldq(struct Machine *, uint32_t);
void OpSsePunpcklqdq(struct Machine *, uint32_t);
void OpSsePunpcklwd(struct Machine *, uint32_t);
void OpSsePxor(struct Machine *, uint32_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -56,12 +56,10 @@ static uint64_t ReadStackWord(uint8_t *p, uint32_t osz) {
}
}
void Push(struct Machine *m, uint32_t rde, uint64_t x) {
static void PushN(struct Machine *m, uint32_t rde, uint64_t x, unsigned osz) {
uint64_t v;
void *p[2];
uint8_t b[8];
unsigned osz;
osz = kStackOsz[m->xedd->op.osz][Mode(rde)];
switch (Eamode(rde)) {
case XED_MODE_REAL:
v = (Read32(m->sp) - osz) & 0xffff;
@ -84,18 +82,21 @@ void Push(struct Machine *m, uint32_t rde, uint64_t x) {
EndStore(m, v, osz, p, b);
}
void Push(struct Machine *m, uint32_t rde, uint64_t x) {
PushN(m, rde, x, kStackOsz[m->xedd->op.osz][Mode(rde)]);
}
void OpPushZvq(struct Machine *m, uint32_t rde) {
unsigned osz;
osz = kStackOsz[m->xedd->op.osz][Mode(rde)];
Push(m, rde, ReadStackWord(RegRexbSrm(m, rde), osz));
PushN(m, rde, ReadStackWord(RegRexbSrm(m, rde), osz), osz);
}
uint64_t Pop(struct Machine *m, uint32_t rde, uint16_t extra) {
static uint64_t PopN(struct Machine *m, uint32_t rde, uint16_t extra,
unsigned osz) {
uint64_t v;
void *p[2];
uint8_t b[8];
unsigned osz;
osz = kStackOsz[m->xedd->op.osz][Mode(rde)];
switch (Eamode(rde)) {
case XED_MODE_LONG:
v = Read64(m->sp);
@ -117,10 +118,16 @@ uint64_t Pop(struct Machine *m, uint32_t rde, uint16_t extra) {
return ReadStackWord(AccessRam(m, v, osz, p, b, true), osz);
}
uint64_t Pop(struct Machine *m, uint32_t rde, uint16_t extra) {
return PopN(m, rde, extra, kStackOsz[m->xedd->op.osz][Mode(rde)]);
}
void OpPopZvq(struct Machine *m, uint32_t rde) {
uint64_t x;
x = Pop(m, rde, 0);
switch (kStackOsz[m->xedd->op.osz][Mode(rde)]) {
unsigned osz;
osz = kStackOsz[m->xedd->op.osz][Mode(rde)];
x = PopN(m, rde, 0, osz);
switch (osz) {
case 8:
case 4:
Write64(RegRexbSrm(m, rde), x);
@ -175,8 +182,8 @@ void OpLeave(struct Machine *m, uint32_t rde) {
}
}
void OpRet(struct Machine *m, uint32_t rde, uint16_t n) {
m->ip = Pop(m, rde, n);
void OpRet(struct Machine *m, uint32_t rde) {
m->ip = Pop(m, rde, m->xedd->op.uimm0);
}
void OpBofram(struct Machine *m, uint32_t rde) {
@ -203,7 +210,7 @@ void OpPopEvq(struct Machine *m, uint32_t rde) {
Pop(m, rde, 0));
}
static void Pushaw(struct Machine *m, uint32_t rde) {
static relegated void Pushaw(struct Machine *m, uint32_t rde) {
uint16_t v;
uint8_t b[8][2];
memcpy(b[0], m->di, 2);
@ -218,7 +225,7 @@ static void Pushaw(struct Machine *m, uint32_t rde) {
VirtualRecv(m, Read64(m->ss) + v, b, sizeof(b));
}
static void Pushad(struct Machine *m, uint32_t rde) {
static relegated void Pushad(struct Machine *m, uint32_t rde) {
uint32_t v;
uint8_t b[8][4];
memcpy(b[0], m->di, 4);
@ -233,7 +240,35 @@ static void Pushad(struct Machine *m, uint32_t rde) {
VirtualRecv(m, Read64(m->ss) + v, b, sizeof(b));
}
void OpPusha(struct Machine *m, uint32_t rde) {
static relegated void Popaw(struct Machine *m, uint32_t rde) {
uint8_t b[8][2];
VirtualSend(m, b, Read64(m->ss) + Read16(m->sp), sizeof(b));
Write16(m->sp, (Read32(m->sp) + sizeof(b)) & 0xffff);
memcpy(m->di, b[0], 2);
memcpy(m->si, b[1], 2);
memcpy(m->bp, b[2], 2);
memcpy(m->sp, b[3], 2);
memcpy(m->bx, b[4], 2);
memcpy(m->dx, b[5], 2);
memcpy(m->cx, b[6], 2);
memcpy(m->ax, b[7], 2);
}
static relegated void Popad(struct Machine *m, uint32_t rde) {
uint8_t b[8][4];
VirtualSend(m, b, Read64(m->ss) + Read32(m->sp), sizeof(b));
Write64(m->sp, (Read32(m->sp) + sizeof(b)) & 0xffffffff);
memcpy(m->di, b[0], 4);
memcpy(m->si, b[1], 4);
memcpy(m->bp, b[2], 4);
memcpy(m->sp, b[3], 4);
memcpy(m->bx, b[4], 4);
memcpy(m->dx, b[5], 4);
memcpy(m->cx, b[6], 4);
memcpy(m->ax, b[7], 4);
}
relegated void OpPusha(struct Machine *m, uint32_t rde) {
switch (Eamode(rde)) {
case XED_MODE_REAL:
Pushaw(m, rde);
@ -248,35 +283,7 @@ void OpPusha(struct Machine *m, uint32_t rde) {
}
}
static void Popaw(struct Machine *m, uint32_t rde) {
uint8_t b[8][2];
VirtualSend(m, b, Read64(m->ss) + Read16(m->sp), sizeof(b));
Write16(m->sp, (Read32(m->sp) + sizeof(b)) & 0xffff);
memcpy(m->di, b[0], 2);
memcpy(m->si, b[1], 2);
memcpy(m->bp, b[2], 2);
memcpy(m->sp, b[3], 2);
memcpy(m->bx, b[4], 2);
memcpy(m->dx, b[5], 2);
memcpy(m->cx, b[6], 2);
memcpy(m->ax, b[7], 2);
}
static void Popad(struct Machine *m, uint32_t rde) {
uint8_t b[8][4];
VirtualSend(m, b, Read64(m->ss) + Read32(m->sp), sizeof(b));
Write64(m->sp, (Read32(m->sp) + sizeof(b)) & 0xffffffff);
memcpy(m->di, b[0], 4);
memcpy(m->si, b[1], 4);
memcpy(m->bp, b[2], 4);
memcpy(m->sp, b[3], 4);
memcpy(m->bx, b[4], 4);
memcpy(m->dx, b[5], 4);
memcpy(m->cx, b[6], 4);
memcpy(m->ax, b[7], 4);
}
void OpPopa(struct Machine *m, uint32_t rde) {
relegated void OpPopa(struct Machine *m, uint32_t rde) {
switch (Eamode(rde)) {
case XED_MODE_REAL:
Popaw(m, rde);
@ -290,3 +297,15 @@ void OpPopa(struct Machine *m, uint32_t rde) {
unreachable;
}
}
relegated void OpCallf(struct Machine *m, uint32_t rde) {
Push(m, rde, Read64(m->cs) >> 4);
Push(m, rde, m->ip);
Write64(m->cs, m->xedd->op.uimm0 << 4);
m->ip = m->xedd->op.disp & (Osz(rde) ? 0xffff : 0xffffffff);
}
relegated void OpRetf(struct Machine *m, uint32_t rde) {
m->ip = Pop(m, rde, 0);
Write64(m->cs, Pop(m, rde, m->xedd->op.uimm0) << 4);
}

View file

@ -7,7 +7,8 @@ COSMOPOLITAN_C_START_
void Push(struct Machine *, uint32_t, uint64_t);
uint64_t Pop(struct Machine *, uint32_t, uint16_t);
void OpCallJvds(struct Machine *, uint32_t);
void OpRet(struct Machine *, uint32_t, uint16_t);
void OpRet(struct Machine *, uint32_t);
void OpRetf(struct Machine *, uint32_t);
void OpLeave(struct Machine *, uint32_t);
void OpCallEq(struct Machine *, uint32_t);
void OpBofram(struct Machine *, uint32_t);
@ -20,6 +21,7 @@ void PushVq(struct Machine *, uint32_t);
void OpJmpEq(struct Machine *, uint32_t);
void OpPusha(struct Machine *, uint32_t);
void OpPopa(struct Machine *, uint32_t);
void OpCallf(struct Machine *, uint32_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -21,9 +21,11 @@
#include "libc/calls/internal.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/iovec.h"
#include "libc/calls/struct/rusage.h"
#include "libc/calls/struct/sigaction-linux.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/stat.h"
#include "libc/calls/struct/termios.h"
#include "libc/calls/struct/timespec.h"
#include "libc/calls/struct/timeval.h"
#include "libc/calls/struct/winsize.h"
@ -41,10 +43,14 @@
#include "libc/sysv/consts/f.h"
#include "libc/sysv/consts/fd.h"
#include "libc/sysv/consts/ipproto.h"
#include "libc/sysv/consts/lock.h"
#include "libc/sysv/consts/madv.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/msync.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/ok.h"
#include "libc/sysv/consts/prot.h"
#include "libc/sysv/consts/rusage.h"
#include "libc/sysv/consts/sa.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/consts/so.h"
@ -52,6 +58,7 @@
#include "libc/sysv/consts/sol.h"
#include "libc/sysv/consts/tcp.h"
#include "libc/sysv/consts/termios.h"
#include "libc/sysv/consts/w.h"
#include "libc/sysv/errfuns.h"
#include "libc/time/struct/timezone.h"
#include "libc/time/time.h"
@ -67,6 +74,14 @@
#define AT_FDCWD_LINUX -100
#define TIOCGWINSZ_LINUX 0x5413
#define TCGETS_LINUX 0x5401
#define TCSETS_LINUX 0x5402
#define TCSETSW_LINUX 0x5403
#define TCSETSF_LINUX 0x5404
#define ISIG_LINUX 0b0000000000000001
#define ICANON_LINUX 0b0000000000000010
#define ECHO_LINUX 0b0000000000001000
#define OPOST_LINUX 0b0000000000000001
#define POINTER(x) ((void *)(intptr_t)(x))
#define UNPOINTER(x) ((int64_t)(intptr_t)(x))
@ -322,8 +337,8 @@ static unsigned XlatOpenFlags(unsigned flags) {
return res;
}
static int XlatFcntlCmd(int cmd) {
switch (cmd) {
static int XlatFcntlCmd(int x) {
switch (x) {
XLAT(1, F_GETFD);
XLAT(2, F_SETFD);
XLAT(3, F_GETFL);
@ -333,8 +348,8 @@ static int XlatFcntlCmd(int cmd) {
}
}
static int XlatFcntlArg(int arg) {
switch (arg) {
static int XlatFcntlArg(int x) {
switch (x) {
XLAT(0, 0);
XLAT(1, FD_CLOEXEC);
default:
@ -342,6 +357,61 @@ static int XlatFcntlArg(int arg) {
}
}
static int XlatAdvice(int x) {
switch (x) {
XLAT(0, MADV_NORMAL);
XLAT(1, MADV_RANDOM);
XLAT(2, MADV_SEQUENTIAL);
XLAT(3, MADV_WILLNEED);
XLAT(4, MADV_DONTNEED);
XLAT(8, MADV_FREE);
XLAT(12, MADV_MERGEABLE);
default:
return einval();
}
}
static int XlatLock(int x) {
unsigned res = 0;
if (x & 1) res |= LOCK_SH;
if (x & 2) res |= LOCK_EX;
if (x & 4) res |= LOCK_NB;
if (x & 8) res |= LOCK_UN;
return res;
}
static int XlatWait(int x) {
unsigned res = 0;
if (x & 1) res |= WNOHANG;
if (x & 2) res |= WUNTRACED;
if (x & 8) res |= WCONTINUED;
return res;
}
static int XlatRusage(int x) {
switch (x) {
XLAT(0, RUSAGE_SELF);
XLAT(-1, RUSAGE_CHILDREN);
XLAT(1, RUSAGE_THREAD);
default:
return einval();
}
}
static void *VirtualSendRead(struct Machine *m, void *dst, int64_t addr,
uint64_t n) {
VirtualSend(m, dst, addr, n);
SetReadAddr(m, addr, n);
return dst;
}
static void *VirtualRecvWrite(struct Machine *m, int64_t addr, void *dst,
uint64_t n) {
VirtualRecv(m, addr, dst, n);
SetWriteAddr(m, addr, n);
return dst;
}
static struct sigaction *CoerceSigactionToCosmo(
struct sigaction *dst, const struct sigaction$linux *src) {
if (!src) return NULL;
@ -364,6 +434,25 @@ static struct sigaction$linux *CoerceSigactionToLinux(
return dst;
}
static int OpArchPrctl(struct Machine *m, int code, int64_t addr) {
switch (code) {
case ARCH_SET_GS:
Write64(m->gs, addr);
return 0;
case ARCH_SET_FS:
Write64(m->fs, addr);
return 0;
case ARCH_GET_GS:
VirtualRecvWrite(m, addr, m->gs, 8);
return 0;
case ARCH_GET_FS:
VirtualRecvWrite(m, addr, m->fs, 8);
return 0;
default:
return einval();
}
}
static int OpMprotect(struct Machine *m, int64_t addr, uint64_t len, int prot) {
return 0;
}
@ -373,6 +462,25 @@ static int OpMadvise(struct Machine *m, int64_t addr, size_t length,
return enosys();
}
static int64_t OpBrk(struct Machine *m, int64_t addr) {
void *real;
if (addr && addr != m->brk) {
if (addr < m->brk) {
addr = ROUNDUP(addr, FRAMESIZE);
FreePml4t(m->cr3, addr, m->brk - addr, free, munmap);
m->brk = addr;
} else {
addr = ROUNDUP(addr, FRAMESIZE);
if ((real = mmap(NULL, addr - m->brk, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) != MAP_FAILED) {
CHECK_NE(-1, RegisterMemory(m, m->brk, real, addr - m->brk));
m->brk = addr;
}
}
}
return m->brk;
}
static int64_t OpMmap(struct Machine *m, int64_t virt, size_t size, int prot,
int flags, int fd, int64_t off) {
void *real;
@ -417,8 +525,7 @@ static struct iovec *GetDirectIov(struct Machine *m, int64_t addr, int *len) {
struct iovec *iov;
if (!__builtin_mul_overflow(sizeof(*iov), *len, &n) && n <= 0x7ffff000) {
if ((iov = malloc(n))) {
VirtualSend(m, iov, addr, n);
SetReadAddr(m, addr, n);
VirtualSendRead(m, iov, addr, n);
for (i = 0; i < *len; ++i) {
size = iov[i].iov_len;
if ((iov[i].iov_base = GetDirectBuf(
@ -544,16 +651,14 @@ static int OpAccept4(struct Machine *m, int fd, int64_t addraddr,
uint8_t b[4];
uint32_t addrsize;
if ((fd = XlatFd(m, fd)) == -1) return -1;
VirtualSend(m, b, addrsizeaddr, 4);
SetReadAddr(m, addrsizeaddr, 4);
VirtualSendRead(m, b, addrsizeaddr, 4);
addrsize = Read32(b);
if (!(addr = malloc(addrsize))) return -1;
if ((i = rc = MachineFdAdd(&m->fds)) != -1) {
if ((rc = accept4(fd, addr, &addrsize, XlatSocketFlags(flags))) != -1) {
Write32(b, addrsize);
VirtualRecv(m, addrsizeaddr, b, 4);
VirtualRecv(m, addraddr, addr, addrsize);
SetWriteAddr(m, addraddr, addrsize);
VirtualRecvWrite(m, addraddr, addr, addrsize);
m->fds.p[i].cb = &kMachineFdCbHost;
m->fds.p[i].fd = rc;
rc = i;
@ -572,8 +677,7 @@ static int OpConnectBind(struct Machine *m, int fd, intptr_t addraddr,
void *addr;
if ((fd = XlatFd(m, fd)) == -1) return -1;
if (!(addr = malloc(addrsize))) return -1;
VirtualSend(m, addr, addraddr, addrsize);
SetReadAddr(m, addraddr, addrsize);
VirtualSendRead(m, addr, addraddr, addrsize);
rc = impl(fd, addr, addrsize);
free(addr);
return rc;
@ -597,8 +701,7 @@ static int OpSetsockopt(struct Machine *m, int fd, int level, int optname,
if ((optname = XlatSocketOptname(optname)) == -1) return -1;
if ((fd = XlatFd(m, fd)) == -1) return -1;
if (!(optval = malloc(optvalsize))) return -1;
VirtualSend(m, optval, optvaladdr, optvalsize);
SetReadAddr(m, optvaladdr, optvalsize);
VirtualSendRead(m, optval, optvaladdr, optvalsize);
rc = setsockopt(fd, level, optname, optval, optvalsize);
free(optval);
return rc;
@ -626,17 +729,63 @@ static ssize_t OpWrite(struct Machine *m, int fd, int64_t addr, size_t size) {
return rc;
}
static int OpIoctl(struct Machine *m, int fd, uint64_t request,
int64_t memaddr) {
static int IoctlTiocgwinsz(struct Machine *m, int fd, int64_t addr,
int (*fn)(int, uint64_t, void *)) {
int rc;
struct winsize ws;
if ((rc = fn(fd, TIOCGWINSZ, &ws)) != -1) {
VirtualRecvWrite(m, addr, &ws, sizeof(ws));
}
return rc;
}
static int IoctlTcgets(struct Machine *m, int fd, int64_t addr,
int (*fn)(int, uint64_t, void *)) {
int rc;
struct termios tio, tio2;
if ((rc = fn(fd, TCGETS, &tio)) != -1) {
memcpy(&tio2, &tio, sizeof(tio));
tio2.c_iflag = 0;
if (tio.c_iflag & ISIG) tio2.c_iflag |= ISIG_LINUX;
if (tio.c_iflag & ICANON) tio2.c_iflag |= ICANON_LINUX;
if (tio.c_iflag & ECHO) tio2.c_iflag |= ECHO_LINUX;
tio2.c_oflag = 0;
if (tio.c_oflag & OPOST) tio2.c_oflag |= OPOST_LINUX;
VirtualRecvWrite(m, addr, &tio2, sizeof(tio2));
}
return rc;
}
static int IoctlTcsets(struct Machine *m, int fd, int64_t request, int64_t addr,
int (*fn)(int, uint64_t, void *)) {
struct termios tio, tio2;
VirtualSendRead(m, &tio, addr, sizeof(tio));
memcpy(&tio2, &tio, sizeof(tio));
tio2.c_iflag = 0;
if (tio.c_iflag & ISIG_LINUX) tio2.c_iflag |= ISIG;
if (tio.c_iflag & ICANON_LINUX) tio2.c_iflag |= ICANON;
if (tio.c_iflag & ECHO_LINUX) tio2.c_iflag |= ECHO;
tio2.c_oflag = 0;
if (tio.c_oflag & OPOST_LINUX) tio2.c_oflag |= OPOST;
return fn(fd, request, &tio2);
}
static int OpIoctl(struct Machine *m, int fd, uint64_t request, int64_t addr) {
int (*fn)(int, uint64_t, void *);
if (!(0 <= fd && fd < m->fds.i) || !m->fds.p[fd].cb) return ebadf();
fn = m->fds.p[fd].cb->ioctl;
fd = m->fds.p[fd].fd;
switch (request) {
case TIOCGWINSZ_LINUX:
rc = (m->fds.p[fd].cb->ioctl)(m->fds.p[fd].fd, TIOCGWINSZ, &ws);
VirtualRecv(m, memaddr, &ws, sizeof(ws));
SetWriteAddr(m, memaddr, sizeof(ws));
return rc;
return IoctlTiocgwinsz(m, fd, addr, fn);
case TCGETS_LINUX:
return IoctlTcgets(m, fd, addr, fn);
case TCSETS_LINUX:
return IoctlTcsets(m, fd, TCSETS, addr, fn);
case TCSETSW_LINUX:
return IoctlTcsets(m, fd, TCSETSW, addr, fn);
case TCSETSF_LINUX:
return IoctlTcsets(m, fd, TCSETSF, addr, fn);
default:
return einval();
}
@ -763,6 +912,19 @@ static int OpFcntl(struct Machine *m, int fd, int cmd, int arg) {
return fcntl(fd, cmd, arg);
}
static int OpFadvise(struct Machine *m, int fd, uint64_t offset, uint64_t len,
int advice) {
if ((fd = XlatFd(m, fd)) == -1) return -1;
if ((advice = XlatAdvice(advice)) == -1) return -1;
return fadvise(fd, offset, len, advice);
}
static int OpFlock(struct Machine *m, int fd, int lock) {
if ((fd = XlatFd(m, fd)) == -1) return -1;
if ((lock = XlatLock(lock)) == -1) return -1;
return flock(fd, lock);
}
static int OpChdir(struct Machine *m, int64_t path) {
return chdir(LoadStr(m, path));
}
@ -813,6 +975,37 @@ static int OpExecve(struct Machine *m, int64_t programaddr, int64_t argvaddr,
return enosys();
}
static int OpWait4(struct Machine *m, int pid, int64_t opt_out_wstatus_addr,
int options, int64_t opt_out_rusage_addr) {
int rc;
int32_t wstatus;
struct rusage rusage;
if ((options = XlatWait(options)) == -1) return -1;
if ((rc = wait4(pid, &wstatus, options, &rusage)) != -1) {
if (opt_out_wstatus_addr) {
VirtualRecvWrite(m, opt_out_wstatus_addr, &wstatus, sizeof(wstatus));
}
if (opt_out_rusage_addr) {
VirtualRecvWrite(m, opt_out_rusage_addr, &rusage, sizeof(rusage));
}
}
return rc;
}
static int OpGetrusage(struct Machine *m, int resource, int64_t rusageaddr) {
int rc;
struct rusage rusage;
if ((resource = XlatRusage(resource)) == -1) return -1;
if ((rc = getrusage(resource, &rusage)) != -1) {
VirtualRecvWrite(m, rusageaddr, &rusage, sizeof(rusage));
}
return rc;
}
static int OpGetrlimit(struct Machine *m, int resource, int64_t rlimitaddr) {
return enosys();
}
static int64_t OpGetcwd(struct Machine *m, int64_t bufaddr, size_t size) {
size_t n;
char *buf;
@ -821,8 +1014,7 @@ static int64_t OpGetcwd(struct Machine *m, int64_t bufaddr, size_t size) {
if (!(buf = malloc(size))) return enomem();
if ((getcwd)(buf, size)) {
n = strlen(buf);
VirtualRecv(m, bufaddr, buf, n);
SetWriteAddr(m, bufaddr, n);
VirtualRecvWrite(m, bufaddr, buf, n);
res = bufaddr;
} else {
res = -1;
@ -904,8 +1096,7 @@ static int OpPoll(struct Machine *m, int64_t fdsaddr, uint64_t nfds,
struct pollfd *fds;
if (!__builtin_mul_overflow(sizeof(*fds), nfds, &n) && n <= 0x7ffff000) {
if ((fds = malloc(n))) {
VirtualSend(m, fds, fdsaddr, n);
SetReadAddr(m, fdsaddr, n);
VirtualSendRead(m, fds, fdsaddr, n);
rc = poll(fds, nfds, timeout_ms);
free(fds);
return rc;
@ -924,17 +1115,53 @@ static int OpSigprocmask(struct Machine *m, int how, int64_t setaddr,
if (setaddr) {
set = &ss;
memset(set, 0, sizeof(ss));
VirtualSend(m, set, setaddr, 8);
VirtualSendRead(m, set, setaddr, 8);
} else {
set = NULL;
}
if ((rc = sigprocmask(XlatSig(how), set, &oldset)) != -1) {
if (setaddr) VirtualRecv(m, setaddr, set, 8);
if (oldsetaddr) VirtualRecv(m, oldsetaddr, &oldset, 8);
if (setaddr) VirtualRecvWrite(m, setaddr, set, 8);
if (oldsetaddr) VirtualRecvWrite(m, oldsetaddr, &oldset, 8);
}
return rc;
}
static int OpGetPid(struct Machine *m) {
return getpid();
}
static int OpGetPpid(struct Machine *m) {
return getppid();
}
static int OpKill(struct Machine *m, int pid, int sig) {
return kill(pid, sig);
}
static int OpGetUid(struct Machine *m) {
return getuid();
}
static int OpGetGid(struct Machine *m) {
return getgid();
}
static int OpGetTid(struct Machine *m) {
return gettid();
}
static int OpSchedYield(struct Machine *m) {
return sched_yield();
}
static int OpAlarm(struct Machine *m, unsigned seconds) {
return alarm(seconds);
}
static int OpPause(struct Machine *m) {
return pause();
}
static int DoOpen(struct Machine *m, int64_t path, int flags, int mode) {
return OpOpenat(m, AT_FDCWD_LINUX, path, flags, mode);
}
@ -983,6 +1210,7 @@ void OpSyscall(struct Machine *m, uint32_t rde) {
SYSCALL(0x01A, OpMsync(m, di, si, dx));
SYSCALL(0x00A, OpMprotect(m, di, si, dx));
SYSCALL(0x00B, OpMunmap(m, di, si));
SYSCALL(0x00C, OpBrk(m, di));
SYSCALL(0x00D, OpSigaction(m, di, si, dx));
SYSCALL(0x00E, OpSigprocmask(m, di, si, dx));
SYSCALL(0x010, OpIoctl(m, di, si, dx));
@ -993,16 +1221,16 @@ void OpSyscall(struct Machine *m, uint32_t rde) {
SYSCALL(0x015, DoAccess(m, di, si));
SYSCALL(0x016, OpPipe(m, di));
SYSCALL(0x017, select(di, P(si), P(dx), P(r0), P(r8)));
SYSCALL(0x018, sched_yield());
SYSCALL(0x018, OpSchedYield(m));
SYSCALL(0x01C, OpMadvise(m, di, si, dx));
SYSCALL(0x020, OpDup(m, di));
SYSCALL(0x021, OpDup2(m, di, si));
SYSCALL(0x022, pause());
SYSCALL(0x022, OpPause(m));
SYSCALL(0x023, OpNanosleep(m, di, si));
SYSCALL(0x024, getitimer(di, PNN(si)));
SYSCALL(0x025, alarm(di));
SYSCALL(0x025, OpAlarm(m, di));
SYSCALL(0x026, setitimer(di, PNN(si), P(dx)));
SYSCALL(0x027, getpid());
SYSCALL(0x027, OpGetPid(m));
SYSCALL(0x028, sendfile(di, si, P(dx), r0));
SYSCALL(0x029, OpSocket(m, di, si, dx));
SYSCALL(0x02A, OpConnect(m, di, si, dx));
@ -1018,11 +1246,11 @@ void OpSyscall(struct Machine *m, uint32_t rde) {
SYSCALL(0x037, getsockopt(di, si, dx, PNN(r0), PNN(r8)));
SYSCALL(0x039, OpFork(m));
SYSCALL(0x03B, OpExecve(m, di, si, dx));
SYSCALL(0x03D, wait4(di, P(si), dx, P(r0)));
SYSCALL(0x03E, kill(di, si));
SYSCALL(0x03D, OpWait4(m, di, si, dx, r0));
SYSCALL(0x03E, OpKill(m, di, si));
SYSCALL(0x03F, uname(P(di)));
SYSCALL(0x048, OpFcntl(m, di, si, dx));
SYSCALL(0x049, flock(di, si));
SYSCALL(0x049, OpFlock(m, di, si));
SYSCALL(0x04A, OpFsync(m, di));
SYSCALL(0x04B, OpFdatasync(m, di));
SYSCALL(0x04C, OpTruncate(m, di, si));
@ -1039,13 +1267,13 @@ void OpSyscall(struct Machine *m, uint32_t rde) {
SYSCALL(0x05A, OpChmod(m, di, si));
SYSCALL(0x05B, OpFchmod(m, di, si));
SYSCALL(0x060, OpGettimeofday(m, di, si));
SYSCALL(0x061, getrlimit(di, P(si)));
SYSCALL(0x062, getrusage(di, P(si)));
SYSCALL(0x061, OpGetrlimit(m, di, si));
SYSCALL(0x062, OpGetrusage(m, di, si));
SYSCALL(0x063, sysinfo(PNN(di)));
SYSCALL(0x064, times(PNN(di)));
SYSCALL(0x066, getuid());
SYSCALL(0x068, getgid());
SYSCALL(0x06E, getppid());
SYSCALL(0x066, OpGetUid(m));
SYSCALL(0x068, OpGetGid(m));
SYSCALL(0x06E, OpGetPpid(m));
SYSCALL(0x075, setresuid(di, si, dx));
SYSCALL(0x077, setresgid(di, si, dx));
SYSCALL(0x082, OpSigsuspend(m, di));
@ -1055,10 +1283,10 @@ void OpSyscall(struct Machine *m, uint32_t rde) {
SYSCALL(0x0A0, setrlimit(di, P(si)));
SYSCALL(0x084, utime(PNN(di), PNN(si)));
SYSCALL(0x0EB, utimes(P(di), P(si)));
SYSCALL(0x09E, arch_prctl(di, si));
SYSCALL(0x0BA, gettid());
SYSCALL(0x09E, OpArchPrctl(m, di, si));
SYSCALL(0x0BA, OpGetTid(m));
SYSCALL(0x0CB, sched_setaffinity(di, si, P(dx)));
SYSCALL(0x0DD, fadvise(di, si, dx, r0));
SYSCALL(0x0DD, OpFadvise(m, di, si, dx, r0));
SYSCALL(0x0E4, OpClockGettime(m, di, si));
SYSCALL(0x101, OpOpenat(m, di, si, dx, r0));
SYSCALL(0x102, mkdirat(XlatAfd(m, di), P(si), dx));
@ -1075,7 +1303,7 @@ void OpSyscall(struct Machine *m, uint32_t rde) {
SYSCALL(0x177, vmsplice(di, P(si), dx, r0));
CASE(0xE7, HaltMachine(m, di | 0x100));
default:
DEBUGF("missing syscall %03x", ax);
/* LOGF("missing syscall 0x%03x", ax); */
ax = enosys();
break;
}

View file

@ -49,7 +49,6 @@ void ThrowProtectionFault(struct Machine *m) {
}
void OpUd(struct Machine *m, uint32_t rde) {
DebugBreak();
m->ip -= m->xedd->length;
HaltMachine(m, kMachineUndefinedInstruction);
}

View file

@ -33,13 +33,9 @@ void OpPause(struct Machine *m, uint32_t rde) {
*/
void OpRdtsc(struct Machine *m, uint32_t rde) {
uint64_t c;
#ifdef __x86_64__
c = rdtsc();
#else
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
c = ts.tv_sec * 1000000000 + ts.tv_nsec;
#endif
Write64(m->ax, (c >> 000) & 0xffffffff);
Write64(m->dx, (c >> 040) & 0xffffffff);
}
@ -50,5 +46,5 @@ void OpRdtscp(struct Machine *m, uint32_t rde) {
core = 0;
node = 0;
tscaux = (node & 0xfff) << 12 | (core & 0xfff);
Write64(m->ax, tscaux & 0xffffffff);
Write64(m->cx, tscaux & 0xffffffff);
}