Add minor improvements and cleanup

This commit is contained in:
Justine Tunney 2020-10-27 03:39:46 -07:00
parent 9e3e985ae5
commit feed0d2b0e
163 changed files with 2286 additions and 2245 deletions

View file

@ -34,7 +34,10 @@
#include "libc/errno.h"
#include "libc/fmt/bing.h"
#include "libc/fmt/fmt.h"
#include "libc/intrin/pcmpeqb.h"
#include "libc/intrin/pmovmskb.h"
#include "libc/log/check.h"
#include "libc/log/color.h"
#include "libc/log/log.h"
#include "libc/macros.h"
#include "libc/math.h"
@ -143,21 +146,19 @@ FEATURES\n\
#define kXmmHex 1
#define kXmmChar 2
#define CTRL(C) ((C) ^ 0100)
#define kMouseLeftDown 0
#define kMouseMiddleDown 1
#define kMouseRightDown 2
#define kMouseLeftUp 4
#define kMouseMiddleUp 5
#define kMouseRightUp 6
#define kMouseLeftDrag 32
#define kMouseMiddleDrag 33
#define kMouseRightDrag 34
#define kMouseWheelUp 64
#define kMouseWheelDown 65
enum Mouse {
kMouseLeftDown = 0,
kMouseMiddleDown = 1,
kMouseRightDown = 2,
kMouseLeftUp = 4,
kMouseMiddleUp = 5,
kMouseRightUp = 6,
kMouseLeftDrag = 32,
kMouseMiddleDrag = 33,
kMouseRightDrag = 34,
kMouseWheelUp = 64,
kMouseWheelDown = 65,
};
#define CTRL(C) ((C) ^ 0100)
struct MachineState {
uint64_t ip;
@ -171,6 +172,7 @@ struct MachineState {
uint8_t xmm[16][16];
struct MachineFpu fpu;
struct MachineSse sse;
struct MachineMemstat memstat;
};
struct Panels {
@ -196,8 +198,9 @@ struct Panels {
struct Panel writedata;
struct Panel stackhr;
struct Panel stack;
struct Panel status;
};
struct Panel p[20];
struct Panel p[21];
};
};
@ -230,6 +233,7 @@ static int readzoom;
static int writezoom;
static int stackzoom;
static long ips;
static long rombase;
static long codesize;
static int64_t opstart;
@ -240,20 +244,23 @@ static int64_t writestart;
static int64_t stackstart;
static int64_t framesstart;
static int64_t breakpointsstart;
static uint64_t last_opcount;
static char *codepath;
static void *onbusted;
static char *statusmessage;
static struct Machine *m;
static struct MachinePty *pty;
static struct Pty *pty;
static struct Panels pan;
static struct MachineState laststate;
static struct Breakpoints breakpoints;
static struct MachineMemstat lastmemstat;
static struct Elf elf[1];
static struct Dis dis[1];
static uint8_t xmmtype[16];
static uint8_t xmmsize[16];
long double last_seconds;
static long double statusexpires;
static struct termios oldterm;
static char logpath[PATH_MAX];
@ -386,6 +393,18 @@ static int64_t GetSp(void) {
}
}
static int64_t ReadWord(uint8_t *p) {
switch (GetPointerWidth()) {
default:
case 8:
return Read64(p);
case 4:
return Read32(p);
case 2:
return Read16(p);
}
}
static void UpdateXmmTypes(int regtype, int rmtype) {
xmmtype[RexrReg(m->xedd->op.rde)] = regtype;
if (IsModrmRegister(m->xedd->op.rde)) {
@ -519,6 +538,18 @@ static void UpdateXmmType(void) {
UpdateXmmSizes(1, 2);
UpdateXmmTypes(kXmmIntegral, kXmmIntegral);
break;
case 0x128: // MOVAPS Vps Wps
if (IsModrmRegister(m->xedd->op.rde)) {
xmmtype[RexrReg(m->xedd->op.rde)] = xmmtype[RexbRm(m->xedd->op.rde)];
xmmsize[RexrReg(m->xedd->op.rde)] = xmmsize[RexbRm(m->xedd->op.rde)];
}
break;
case 0x129: // MOVAPS Wps Vps
if (IsModrmRegister(m->xedd->op.rde)) {
xmmtype[RexbRm(m->xedd->op.rde)] = xmmtype[RexrReg(m->xedd->op.rde)];
xmmsize[RexbRm(m->xedd->op.rde)] = xmmsize[RexrReg(m->xedd->op.rde)];
}
break;
case 0x16F: // MOVDQA Vdq Wdq
if (Osz(m->xedd->op.rde) && IsModrmRegister(m->xedd->op.rde)) {
xmmtype[RexrReg(m->xedd->op.rde)] = xmmtype[RexbRm(m->xedd->op.rde)];
@ -671,7 +702,6 @@ static void OnSigAlarm(void) {
static void OnSigCont(void) {
TuiRejuvinate();
SetupDraw();
Redraw();
}
@ -771,12 +801,12 @@ void TuiSetup(void) {
LoadSyms();
ResolveBreakpoints();
ioctl(ttyout, TCGETS, &oldterm);
xsigaction(SIGALRM, OnSigAlarm, 0, 0, 0);
xsigaction(SIGINT, OnSigInt, 0, 0, oldsig + 3);
atexit(TtyRestore2);
once = true;
report = true;
}
setitimer(ITIMER_REAL, &((struct itimerval){0}), NULL);
xsigaction(SIGCONT, OnSigCont, SA_RESTART | SA_NODEFER, 0, oldsig + 2);
CopyMachineState(&laststate);
TuiRejuvinate();
@ -798,6 +828,9 @@ static void ExecSetup(void) {
}
once = true;
}
setitimer(ITIMER_REAL,
&((struct itimerval){{0, 1. / 60 * 1e6}, {0, 1. / 60 * 1e6}}),
NULL);
}
static void AppendPanel(struct Panel *p, long line, const char *s) {
@ -807,12 +840,14 @@ static void AppendPanel(struct Panel *p, long line, const char *s) {
}
static bool IsXmmNonZero(long start, long end) {
long i, j;
long i;
uint8_t v1[16], vz[16];
for (i = start; i < end; ++i) {
for (j = 0; j < 16; ++j) {
if (m->xmm[i][j]) {
return true;
}
memset(vz, 0, 16);
memcpy(v1, m->xmm[i], 16);
pcmpeqb(v1, v1, vz);
if (pmovmskb(v1) != 0xffff) {
return true;
}
}
return false;
@ -840,16 +875,8 @@ static int PickNumberOfXmmRegistersToShow(void) {
}
}
static void SetupDraw(void) {
int i, j, n, a, b, cpuy, ssey, dx[2], c2y[3], c3y[5];
for (i = 0; i < ARRAYLEN(pan.p); ++i) {
n = pan.p[i].bottom - pan.p[i].top;
for (j = 0; j < n; ++j) {
free(pan.p[i].lines[j].p);
}
free(pan.p[i].lines);
}
void SetupDraw(void) {
int i, j, n, a, b, yn, cpuy, ssey, dx[2], c2y[3], c3y[5];
cpuy = 9;
if (IsSegNonZero()) cpuy += 2;
@ -861,20 +888,21 @@ static void SetupDraw(void) {
dx[1] = txn >= a + b ? txn - a : txn;
dx[0] = txn >= a + b + b ? txn - a - b : dx[1];
a = 1 / 8. * tyn;
b = 3 / 8. * tyn;
yn = tyn - 1;
a = 1 / 8. * yn;
b = 3 / 8. * yn;
c2y[0] = a * .7;
c2y[1] = a * 2;
c2y[2] = a * 2 + b;
if (tyn - c2y[2] > 26) {
c2y[1] -= tyn - c2y[2] - 26;
c2y[2] = tyn - 26;
if (yn - c2y[2] > 26) {
c2y[1] -= yn - c2y[2] - 26;
c2y[2] = yn - 26;
}
if (tyn - c2y[2] < 26) {
c2y[2] = tyn - 26;
if (yn - c2y[2] < 26) {
c2y[2] = yn - 26;
}
a = (tyn - (cpuy + ssey) - 3) / 4;
a = (yn - (cpuy + ssey) - 3) / 4;
c3y[0] = cpuy;
c3y[1] = cpuy + ssey;
c3y[2] = cpuy + ssey + 1 + 1 + a * 1;
@ -885,8 +913,8 @@ static void SetupDraw(void) {
pan.disassembly.top = 0;
pan.disassembly.left = 0;
pan.disassembly.bottom = tyn;
pan.disassembly.right = dx[0];
pan.disassembly.bottom = yn;
pan.disassembly.right = dx[0] - 1;
/* COLUMN #2: BREAKPOINTS, MEMORY MAPS, BACKTRACE, DISPLAY */
@ -927,7 +955,7 @@ static void SetupDraw(void) {
pan.display.top = c2y[2] + 1;
pan.display.left = dx[0];
pan.display.bottom = tyn;
pan.display.bottom = yn;
pan.display.right = dx[1] - 1;
/* COLUMN #3: REGISTERS, VECTORS, CODE, MEMORY READS, MEMORY WRITES, STACK */
@ -984,18 +1012,38 @@ static void SetupDraw(void) {
pan.stack.top = c3y[4] + 1;
pan.stack.left = dx[1];
pan.stack.bottom = tyn;
pan.stack.bottom = yn;
pan.stack.right = txn;
pan.status.top = yn;
pan.status.left = 0;
pan.status.bottom = yn + 1;
pan.status.right = txn;
for (i = 0; i < ARRAYLEN(pan.p); ++i) {
if (pan.p[i].top > pan.p[i].bottom) pan.p[i].top = pan.p[i].bottom = 0;
if (pan.p[i].left > pan.p[i].right) pan.p[i].left = pan.p[i].right = 0;
pan.p[i].lines =
xcalloc(pan.p[i].bottom - pan.p[i].top, sizeof(struct Buffer));
if (pan.p[i].left > pan.p[i].right) {
pan.p[i].left = pan.p[i].right = 0;
}
if (pan.p[i].top > pan.p[i].bottom) {
pan.p[i].top = pan.p[i].bottom = 0;
}
n = pan.p[i].bottom - pan.p[i].top;
if (n == pan.p[i].n) {
for (j = 0; j < n; ++j) {
pan.p[i].lines[j].i = 0;
}
} else {
for (j = 0; j < pan.p[i].n; ++j) {
free(pan.p[i].lines[j].p);
}
free(pan.p[i].lines);
pan.p[i].lines = xcalloc(n, sizeof(struct Buffer));
pan.p[i].n = n;
}
}
MachinePtyResize(pty, pan.display.bottom - pan.display.top,
pan.display.right - pan.display.left);
PtyResize(pty, pan.display.bottom - pan.display.top,
pan.display.right - pan.display.left);
}
static long Disassemble(void) {
@ -1043,30 +1091,30 @@ static void DrawHr(struct Panel *p, const char *s) {
void DrawTerminal(struct Panel *p) {
long i, y, yn;
if (pty->conf & kMachinePtyBell) {
if (pty->conf & kPtyBell) {
if (!alarmed) {
alarmed = true;
setitimer(ITIMER_REAL, &((struct itimerval){{0, 0}, {0, 800000}}), NULL);
}
AppendStr(&pan.displayhr.lines[0], "\e[1m");
}
AppendStr(
&pan.displayhr.lines[0],
gc(xasprintf("──────────TELETYPEWRITER──%s──%s──%s──%s",
(pty->conf & kMachinePtyLed1) ? "\e[1;31m◎\e[0m" : "",
(pty->conf & kMachinePtyLed2) ? "\e[1;32m◎\e[0m" : "",
(pty->conf & kMachinePtyLed3) ? "\e[1;33m◎\e[0m" : "",
(pty->conf & kMachinePtyLed4) ? "\e[1;34m◎\e[0m" : "")));
AppendStr(&pan.displayhr.lines[0],
gc(xasprintf("──────────TELETYPEWRITER──%s──%s──%s──%s",
(pty->conf & kPtyLed1) ? "\e[1;31m◎\e[0m" : "",
(pty->conf & kPtyLed2) ? "\e[1;32m◎\e[0m" : "",
(pty->conf & kPtyLed3) ? "\e[1;33m◎\e[0m" : "",
(pty->conf & kPtyLed4) ? "\e[1;34m◎\e[0m" : "")));
for (i = 36; i < pan.displayhr.right - pan.displayhr.left; ++i) {
AppendWide(&pan.displayhr.lines[0], u'');
}
for (yn = MIN(pty->yn, p->bottom - p->top), y = 0; y < yn; ++y) {
MachinePtyAppendLine(pty, p->lines + y, y);
PtyAppendLine(pty, p->lines + y, y);
AppendStr(p->lines + y, "\e[0m");
}
}
void DrawDisplay(struct Panel *p) {
if (p->top == p->bottom) return;
switch (vidya) {
case 7:
DrawHr(&pan.displayhr, "MONOCHROME DISPLAY ADAPTER");
@ -1140,6 +1188,7 @@ static void DrawSt(struct Panel *p, long i, long r) {
static void DrawCpu(struct Panel *p) {
char buf[48];
if (p->top == p->bottom) return;
DrawRegister(p, 0, 7), DrawRegister(p, 0, 0), DrawSt(p, 0, 0);
DrawRegister(p, 1, 6), DrawRegister(p, 1, 3), DrawSt(p, 1, 1);
DrawRegister(p, 2, 2), DrawRegister(p, 2, 5), DrawSt(p, 2, 2);
@ -1239,6 +1288,7 @@ static void DrawXmm(struct Panel *p, long i, long r) {
static void DrawSse(struct Panel *p) {
long i;
if (p->top == p->bottom) return;
for (i = 0; i < MIN(16, MAX(0, p->bottom - p->top)); ++i) {
DrawXmm(p, i, i);
}
@ -1314,6 +1364,7 @@ static void DrawMemory(struct Panel *p, int zoom, long startline, long histart,
char buf[16];
bool high, changed;
long i, j, k, c, width;
if (p->top == p->bottom) return;
high = false;
width = DUMPWIDTH * (1 << zoom);
for (i = 0; i < p->bottom - p->top; ++i) {
@ -1342,6 +1393,7 @@ static void DrawMemory(struct Panel *p, int zoom, long startline, long histart,
static void DrawMaps(struct Panel *p) {
int i;
char *text, *p1, *p2;
if (p->top == p->bottom) return;
p1 = text = FormatPml4t(m);
for (i = 0; p1; ++i, p1 = p2) {
if ((p2 = strchr(p1, '\n'))) *p2++ = '\0';
@ -1357,6 +1409,7 @@ static void DrawBreakpoints(struct Panel *p) {
const char *name;
char *s, buf[256];
long i, line, sym;
if (p->top == p->bottom) return;
for (line = 0, i = breakpoints.i; i--;) {
if (breakpoints.p[i].disable) continue;
if (line >= breakpointsstart) {
@ -1396,6 +1449,7 @@ static void DrawFrames(struct Panel *p) {
const char *name;
char *s, line[256];
int64_t sp, bp, rp;
if (p->top == p->bottom) return;
rp = m->ip;
bp = Read64(m->bp);
sp = Read64(m->sp);
@ -1427,8 +1481,8 @@ static void DrawFrames(struct Panel *p) {
break;
}
sp = bp;
bp = Read64(r + 0);
rp = Read64(r + 8);
bp = ReadWord(r + 0);
rp = ReadWord(r + 8);
}
}
@ -1466,8 +1520,60 @@ static bool IsExecuting(void) {
return (action & (CONTINUE | STEP | NEXT | FINISH)) && !(action & FAILURE);
}
static int AppendStat(struct Buffer *b, const char *name, int64_t value,
bool changed) {
int width;
AppendChar(b, ' ');
if (changed) AppendStr(b, "\e[31m");
width = AppendFmt(b, "%,8ld %s", value, name);
if (changed) AppendStr(b, "\e[39m");
return 1 + width;
}
void DrawStatus(struct Panel *p) {
int yn, xn, rw;
struct Buffer s;
struct MachineMemstat *a, *b;
yn = p->top - p->bottom;
xn = p->right - p->left;
if (!yn || !xn) return;
rw = 0;
a = &m->memstat;
b = &lastmemstat;
memset(&s, 0, sizeof(s));
if (ips > 0) rw += AppendStat(&s, "ips", ips, false);
rw += AppendStat(&s, "kb", m->real.n / 1024, false);
rw += AppendStat(&s, "reserve", a->reserved, a->reserved != b->reserved);
rw += AppendStat(&s, "commit", a->committed, a->committed != b->committed);
rw += AppendStat(&s, "freed", a->freed, a->freed != b->freed);
rw += AppendStat(&s, "tables", a->pagetables, a->pagetables != b->pagetables);
rw += AppendStat(&s, "fds", m->fds.i, false);
AppendFmt(&p->lines[0], "\e[7m%-*s%s\e[0m", xn - rw,
statusmessage && nowl() < statusexpires ? statusmessage
: "das blinkenlights",
s.p);
free(s.p);
memcpy(b, a, sizeof(*a));
}
static void PreventBufferbloat(void) {
long double now, rate;
static long double last;
now = nowl();
rate = 1. / 60;
if (now - last < rate) {
dsleep(rate - (now - last));
}
last = now;
}
static void Redraw(void) {
int i, j;
ScrollOp(&pan.disassembly, GetDisIndex());
if (last_opcount) {
ips = unsignedsubtract(opcount, last_opcount) / (nowl() - last_seconds);
}
SetupDraw();
for (i = 0; i < ARRAYLEN(pan.p); ++i) {
for (j = 0; j < pan.p[i].bottom - pan.p[i].top; ++j) {
pan.p[i].lines[j].i = 0;
@ -1478,7 +1584,7 @@ static void Redraw(void) {
DrawCpu(&pan.registers);
DrawSse(&pan.sse);
DrawHr(&pan.breakpointshr, "BREAKPOINTS");
DrawHr(&pan.mapshr, "MAPS");
DrawHr(&pan.mapshr, "PML4T");
DrawHr(&pan.frameshr, m->bofram[0] ? "PROTECTED FRAMES" : "FRAMES");
DrawHr(&pan.ssehr, "SSE");
DrawHr(&pan.codehr, "CODE");
@ -1496,19 +1602,20 @@ static void Redraw(void) {
m->writeaddr + m->writesize);
DrawMemory(&pan.stack, stackzoom, stackstart, GetSp(),
GetSp() + GetPointerWidth());
DrawStatus(&pan.status);
PreventBufferbloat();
if (PrintPanels(ttyout, ARRAYLEN(pan.p), pan.p, tyn, txn) == -1) {
LOGF("PrintPanels Interrupted");
CHECK_EQ(EINTR, errno);
}
if (statusmessage && nowl() < statusexpires) {
TtyWriteString(statusmessage);
}
last_opcount = opcount;
last_seconds = nowl();
CopyMachineState(&laststate);
}
static void ReactiveDraw(void) {
if (tuimode) {
m->ip -= m->xedd->length;
SetupDraw();
Redraw();
m->ip += m->xedd->length;
tick = speed;
@ -1518,7 +1625,7 @@ static void ReactiveDraw(void) {
static void HandleAlarm(void) {
alarmed = false;
action &= ~ALARM;
pty->conf &= ~kMachinePtyBell;
pty->conf &= ~kPtyBell;
free(statusmessage);
statusmessage = NULL;
}
@ -1547,7 +1654,7 @@ static void HandleAppReadInterrupt(void) {
}
static int OnPtyFdClose(int fd) {
return 0;
return close(fd);
}
static bool HasPendingInput(int fd) {
@ -1564,7 +1671,7 @@ static ssize_t ReadPtyFdDirect(int fd, void *data, size_t size) {
ssize_t rc;
DEBUGF("ReadPtyFdDirect");
buf = malloc(PAGESIZE);
pty->conf |= kMachinePtyBlinkcursor;
pty->conf |= kPtyBlinkcursor;
if (tuimode) DisableMouseTracking();
for (;;) {
ReactiveDraw();
@ -1573,11 +1680,11 @@ static ssize_t ReadPtyFdDirect(int fd, void *data, size_t size) {
HandleAppReadInterrupt();
}
if (tuimode) EnableMouseTracking();
pty->conf &= ~kMachinePtyBlinkcursor;
pty->conf &= ~kPtyBlinkcursor;
if (rc > 0) {
MachinePtyWriteInput(pty, buf, rc);
PtyWriteInput(pty, buf, rc);
ReactiveDraw();
rc = MachinePtyRead(pty, data, size);
rc = PtyRead(pty, data, size);
}
free(buf);
return rc;
@ -1596,7 +1703,7 @@ static ssize_t OnPtyFdReadv(int fd, const struct iovec *iov, int iovlen) {
}
}
if (size) {
if (!(rc = MachinePtyRead(pty, data, size))) {
if (!(rc = PtyRead(pty, data, size))) {
rc = ReadPtyFdDirect(fd, data, size);
}
return rc;
@ -1605,14 +1712,16 @@ static ssize_t OnPtyFdReadv(int fd, const struct iovec *iov, int iovlen) {
}
}
static void DrawTerminalOnly(void) {
static void DrawDisplayOnly(struct Panel *p) {
struct Buffer b;
int i, y, yn, xn, tly, tlx, conf;
conf = pty->conf & kMachinePtyNocursor;
pty->conf |= kMachinePtyNocursor;
yn = MIN(tyn, p->bottom - p->top);
xn = MIN(txn, p->right - p->left);
for (i = 0; i < yn; ++i) {
p->lines[i].i = 0;
}
DrawDisplay(p);
memset(&b, 0, sizeof(b));
yn = MIN(tyn, pty->yn);
xn = MIN(txn, pty->xn);
tly = tyn / 2 - yn / 2;
tlx = txn / 2 - xn / 2;
AppendStr(&b, "\e[0m\e[H");
@ -1622,24 +1731,21 @@ static void DrawTerminalOnly(void) {
for (i = 0; i < tlx; ++i) {
AppendChar(&b, ' ');
}
MachinePtyAppendLine(pty, &b, y - tly);
AppendData(&b, p->lines[y - tly].p, p->lines[y - tly].i);
}
AppendStr(&b, "\e[0m\e[K");
}
AppendFmt(&b, "\e[%d;%dH", tly + pty->y + 1, tlx + pty->x + 1);
write(ttyout, b.p, b.i);
free(b.p);
pty->conf |= conf;
}
static ssize_t OnPtyFdWritev(int fd, const struct iovec *iov, int iovlen) {
int i;
size_t size;
for (size = i = 0; i < iovlen; ++i) {
MachinePtyWrite(pty, iov[i].iov_base, iov[i].iov_len);
PtyWrite(pty, iov[i].iov_base, iov[i].iov_len);
size += iov[i].iov_len;
}
if (!tuimode) DrawTerminalOnly();
return size;
}
@ -1651,27 +1757,27 @@ static int OnPtyFdTiocgwinsz(int fd, struct winsize *ws) {
static int OnPtyFdTcgets(int fd, struct termios *c) {
memset(c, 0, sizeof(*c));
if (!(pty->conf & kMachinePtyNocanon)) c->c_iflag |= ICANON;
if (!(pty->conf & kMachinePtyNoecho)) c->c_iflag |= ECHO;
if (!(pty->conf & kMachinePtyNoopost)) c->c_oflag |= OPOST;
if (!(pty->conf & kPtyNocanon)) c->c_iflag |= ICANON;
if (!(pty->conf & kPtyNoecho)) c->c_iflag |= ECHO;
if (!(pty->conf & kPtyNoopost)) c->c_oflag |= OPOST;
return 0;
}
static int OnPtyFdTcsets(int fd, uint64_t request, struct termios *c) {
if (c->c_iflag & ICANON) {
pty->conf &= ~kMachinePtyNocanon;
pty->conf &= ~kPtyNocanon;
} else {
pty->conf |= kMachinePtyNocanon;
pty->conf |= kPtyNocanon;
}
if (c->c_iflag & ECHO) {
pty->conf &= ~kMachinePtyNoecho;
pty->conf &= ~kPtyNoecho;
} else {
pty->conf |= kMachinePtyNoecho;
pty->conf |= kPtyNoecho;
}
if (c->c_oflag & OPOST) {
pty->conf &= ~kMachinePtyNoopost;
pty->conf &= ~kPtyNoopost;
} else {
pty->conf |= kMachinePtyNoopost;
pty->conf |= kPtyNoopost;
}
return 0;
}
@ -1732,14 +1838,13 @@ static void OnSimdException(void) {
}
static void OnUndefinedInstruction(void) {
die();
strcpy(systemfailure, "UNDEFINED INSTRUCTION");
LaunchDebuggerReactively();
}
static void OnDecodeError(void) {
strcpy(stpcpy(systemfailure, "DECODE: "),
indexdoublenulstring(kXedErrorNames, m->xedd->op.error));
IndexDoubleNulString(kXedErrorNames, m->xedd->op.error));
LaunchDebuggerReactively();
}
@ -1854,15 +1959,15 @@ static void OnVidyaServiceGetMode(void) {
}
static void OnVidyaServiceSetCursorPosition(void) {
MachinePtySetY(pty, m->dx[1]);
MachinePtySetX(pty, m->dx[0]);
PtySetY(pty, m->dx[1]);
PtySetX(pty, m->dx[0]);
}
static void OnVidyaServiceGetCursorPosition(void) {
m->dx[1] = pty->y;
m->dx[0] = pty->x;
m->cx[1] = 5; // cursor ▂ scan lines 5..7 of 0..7
m->cx[0] = 7 | !!(pty->conf & kMachinePtyNocursor) << 5;
m->cx[0] = 7 | !!(pty->conf & kPtyNocursor) << 5;
}
static int GetVidyaByte(unsigned char b) {
@ -1880,7 +1985,7 @@ static void OnVidyaServiceWriteCharacter(void) {
p += tpencode(p, 8, GetVidyaByte(m->ax[0]), false);
p = stpcpy(p, "\e8");
for (i = Read16(m->cx); i--;) {
MachinePtyWrite(pty, buf, p - buf);
PtyWrite(pty, buf, p - buf);
}
}
@ -1902,7 +2007,7 @@ static void OnVidyaServiceTeletypeOutput(void) {
char buf[12];
n = FormatCga(m->bx[0], buf);
n += tpencode(buf + n, 6, VidyaServiceXlatTeletype(m->ax[0]), false);
MachinePtyWrite(pty, buf, n);
PtyWrite(pty, buf, n);
}
static void OnVidyaService(void) {
@ -1933,7 +2038,7 @@ static void OnVidyaService(void) {
static void OnKeyboardServiceReadKeyPress(void) {
uint8_t b;
ssize_t rc;
pty->conf |= kMachinePtyBlinkcursor;
pty->conf |= kPtyBlinkcursor;
if (tuimode) DisableMouseTracking();
for (;;) {
ReactiveDraw();
@ -1942,7 +2047,7 @@ static void OnKeyboardServiceReadKeyPress(void) {
HandleAppReadInterrupt();
}
if (tuimode) EnableMouseTracking();
pty->conf &= ~kMachinePtyBlinkcursor;
pty->conf &= ~kPtyBlinkcursor;
ReactiveDraw();
if (b == 0x7F) b = '\b';
m->ax[0] = b;
@ -2065,16 +2170,12 @@ static void SetStatus(const char *fmt, ...) {
va_list va;
int y, x, n;
va_start(va, fmt);
s = gc(xvasprintf(fmt, va));
s = xvasprintf(fmt, va);
va_end(va);
n = strwidth(s);
y = tyn - (n / txn + 1);
x = txn / 2 - n / 2;
free(statusmessage);
statusmessage = xasprintf("\e[0m\e[%d;%dH%s", y + 1, x + 1, s);
TtyWriteString(statusmessage);
setitimer(ITIMER_REAL, &((struct itimerval){{0, 0}, {1, 0}}), NULL);
statusmessage = s;
statusexpires = nowl() + 1;
setitimer(ITIMER_REAL, &((struct itimerval){{0, 0}, {1, 0}}), NULL);
}
static void OnTurbo(void) {
@ -2201,8 +2302,7 @@ static void Sleep(int ms) {
}
static void OnMouse(char *p) {
enum Mouse e;
int i, x, y, dy;
int e, i, x, y, dy;
struct Panel *ep;
e = strtol(p, &p, 10);
if (*p == ';') ++p;
@ -2251,7 +2351,10 @@ static void OnMouse(char *p) {
static void ReadKeyboard(void) {
char buf[64], *p = buf;
if (readansi(ttyin, buf, sizeof(buf)) == -1) {
if (errno == EINTR) return;
if (errno == EINTR) {
LOGF("readkeyboard interrupted");
return;
}
FATALF("readkeyboard failed: %s", strerror(errno));
}
switch (*p++) {
@ -2384,39 +2487,42 @@ static void Exec(void) {
if (!(interrupt = setjmp(m->onhalt))) {
if (!(action & CONTINUE) &&
(bp = IsAtBreakpoint(&breakpoints, GetIp())) != -1) {
LOGF("BREAK %p", breakpoints.p[bp].addr);
LOGF("BREAK1 %p", breakpoints.p[bp].addr);
tuimode = true;
LoadInstruction(m);
ExecuteInstruction(m);
++opcount;
CheckFramePointer();
ops++;
} else {
action &= ~CONTINUE;
for (;;) {
LoadInstruction(m);
if ((bp = IsAtBreakpoint(&breakpoints, GetIp())) != -1) {
LOGF("BREAK2 %p", breakpoints.p[bp].addr);
action &= ~(FINISH | NEXT | CONTINUE);
tuimode = true;
break;
}
ExecuteInstruction(m);
++opcount;
KeepGoing:
CheckFramePointer();
ops++;
if (action || breakpoints.i) {
if (action & EXIT) {
LOGF("EXEC EXIT");
break;
}
if (action & INT) {
LOGF("EXEC INT");
if (react) {
LOGF("REACT");
action &= ~(INT | STEP | FINISH | NEXT);
tuimode = true;
}
break;
}
if ((bp = IsAtBreakpoint(&breakpoints, GetIp())) != -1) {
LOGF("BREAK %p", breakpoints.p[bp].addr);
if (action & ALARM) {
DrawDisplayOnly(&pan.display);
action &= ~ALARM;
}
if (action & EXIT) {
LOGF("EXEC EXIT");
break;
}
if (action & INT) {
LOGF("EXEC INT");
if (react) {
LOGF("REACT");
action &= ~(INT | STEP | FINISH | NEXT);
tuimode = true;
break;
}
break;
}
}
}
@ -2441,6 +2547,12 @@ static void Tui(void) {
if (!(action & FAILURE)) {
LoadInstruction(m);
UpdateXmmType();
if ((action & (FINISH | NEXT | CONTINUE)) &&
(bp = IsAtBreakpoint(&breakpoints, GetIp())) != -1) {
action &= ~(FINISH | NEXT | CONTINUE);
LOGF("BREAK %p", breakpoints.p[bp].addr);
break;
}
} else {
m->xedd = (struct XedDecodedInst *)m->icache[0];
m->xedd->length = 1;
@ -2466,14 +2578,17 @@ static void Tui(void) {
}
if (!(action & CONTINUE) || interactive) {
tick = 0;
GetDisIndex();
SetupDraw();
Redraw();
}
if (action & FAILURE) {
LOGF("TUI FAILURE");
PrintMessageBox(ttyout, systemfailure, tyn, txn);
ReadKeyboard();
if (action & INT) {
LOGF("TUI INT");
LeaveScreen();
exit(1);
}
} else if (!IsExecuting() || (!(action & CONTINUE) && !(action & INT) &&
HasPendingKeyboard())) {
ReadKeyboard();
@ -2505,10 +2620,6 @@ static void Tui(void) {
break;
}
if (IsExecuting()) {
op = GetDisIndex();
ScrollOp(&pan.disassembly, op);
VERBOSEF("%s", DisGetLine(dis, m, op));
CopyMachineState(&laststate);
if (!(action & CONTINUE)) {
action &= ~STEP;
if (action & NEXT) {
@ -2529,6 +2640,7 @@ static void Tui(void) {
}
if (!IsDebugBreak()) {
ExecuteInstruction(m);
++opcount;
if (!(action & CONTINUE) || interactive) {
ScrollCode(&pan.code);
ScrollStack(&pan.stack);
@ -2546,7 +2658,6 @@ static void Tui(void) {
}
KeepGoing:
CheckFramePointer();
ops++;
if (!(action & CONTINUE)) {
ScrollOp(&pan.disassembly, GetDisIndex());
if ((action & FINISH) && IsRet()) action &= ~FINISH;
@ -2554,12 +2665,6 @@ static void Tui(void) {
action &= ~NEXT;
}
}
if ((action & (FINISH | NEXT | CONTINUE)) &&
(bp = IsAtBreakpoint(&breakpoints, GetIp())) != -1) {
action &= ~(FINISH | NEXT | CONTINUE);
LOGF("BREAK %p", breakpoints.p[bp].addr);
break;
}
}
}
} else {
@ -2611,25 +2716,30 @@ static void GetOpts(int argc, char *argv[]) {
setvbuf(g_logfile, xmalloc(PAGESIZE), _IOLBF, PAGESIZE);
}
static int OpenDevTty(void) {
return open("/dev/tty", O_RDWR | O_NOCTTY);
}
static void AddHostFd(int fd) {
int i = m->fds.i++;
CHECK_NE(-1, (m->fds.p[i].fd = fd));
m->fds.p[i].cb = &kMachineFdCbHost;
}
int Emulator(int argc, char *argv[]) {
void *code;
int rc, fd;
codepath = argv[optind++];
pty = MachinePtyNew();
m->fds.p = xcalloc((m->fds.n = 8), sizeof(struct MachineFd));
Restart:
action = 0;
LoadProgram(m, codepath, argv + optind, environ, elf);
m->fds.i = 3;
m->fds.p[0].fd = STDIN_FILENO;
m->fds.p[0].cb = &kMachineFdCbHost;
m->fds.p[1].fd = STDOUT_FILENO;
m->fds.p[1].cb = &kMachineFdCbHost;
m->fds.p[2].fd = STDERR_FILENO;
m->fds.p[2].cb = &kMachineFdCbHost;
AddHostFd(STDIN_FILENO);
AddHostFd(STDOUT_FILENO);
AddHostFd(STDERR_FILENO);
if (tuimode) {
ttyin = isatty(0) ? 0 : open("/dev/tty", O_RDWR | O_NOCTTY);
ttyout = isatty(1) ? 1 : open("/dev/tty", O_RDWR | O_NOCTTY);
ttyin = isatty(STDIN_FILENO) ? STDIN_FILENO : OpenDevTty();
ttyout = isatty(STDOUT_FILENO) ? STDOUT_FILENO : OpenDevTty();
} else {
ttyin = -1;
ttyout = -1;
@ -2640,18 +2750,9 @@ Restart:
tyn = 24;
txn = 80;
GetTtySize(ttyout);
if (isatty(0)) {
m->fds.p[0].fd = 0;
m->fds.p[0].cb = &kMachineFdCbPty;
}
if (isatty(1)) {
m->fds.p[1].fd = 1;
m->fds.p[1].cb = &kMachineFdCbPty;
}
if (isatty(2)) {
m->fds.p[2].fd = 2;
m->fds.p[2].cb = &kMachineFdCbPty;
}
if (isatty(STDIN_FILENO)) m->fds.p[STDIN_FILENO].cb = &kMachineFdCbPty;
if (isatty(STDOUT_FILENO)) m->fds.p[STDOUT_FILENO].cb = &kMachineFdCbPty;
if (isatty(STDERR_FILENO)) m->fds.p[STDERR_FILENO].cb = &kMachineFdCbPty;
}
while (!(action & EXIT)) {
if (!tuimode) {
@ -2669,7 +2770,7 @@ Restart:
if (printstats) {
fprintf(stderr, "taken: %,ld\n", taken);
fprintf(stderr, "ntaken: %,ld\n", ntaken);
fprintf(stderr, "ops: %,ld\n", ops);
fprintf(stderr, "ops: %,ld\n", opcount);
}
munmap(elf->ehdr, elf->size);
DisFree(dis);
@ -2682,12 +2783,13 @@ static void OnlyRunOnFirstCpu(void) {
}
int main(int argc, char *argv[]) {
if (!NoDebug()) showcrashreports();
pty = NewPty();
m = NewMachine();
m->mode = XED_MACHINE_MODE_LONG_64;
speed = 16;
SetXmmSize(2);
SetXmmDisp(kXmmHex);
if (!NoDebug()) showcrashreports();
/* OnlyRunOnFirstCpu(); */
if ((colorize = cancolor())) {
g_high.keyword = 155;
g_high.reg = 215;
@ -2697,6 +2799,7 @@ int main(int argc, char *argv[]) {
g_high.quote = 215;
}
GetOpts(argc, argv);
xsigaction(SIGALRM, OnSigAlarm, 0, 0, 0);
if (optind == argc) PrintUsage(EX_USAGE, stderr);
return Emulator(argc, argv);
}

View file

@ -19,6 +19,7 @@
#include "libc/dce.h"
#include "libc/fmt/fmt.h"
#include "libc/limits.h"
#include "libc/log/color.h"
#include "libc/log/log.h"
#include "libc/macros.h"
#include "libc/math.h"

View file

@ -58,6 +58,14 @@ o/$(MODE)/tool/build/emubin/%.elf: \
$(ELF)
@$(ELFLINK)
o/$(MODE)/tool/build/emubin/lisp.elf: \
$(TOOL_BUILD_EMUBIN_DEPS) \
$(TOOL_BUILD_EMUBIN_A) \
o/$(MODE)/tool/build/emubin/lisp.o \
o/$(MODE)/tool/build/emubin/lispelf.o \
$(ELF)
@$(ELFLINK)
o/dbg/tool/build/emubin/lisp.real.com.dbg: \
$(TOOL_BUILD_EMUBIN_DEPS) \
$(TOOL_BUILD_EMUBIN_A) \
@ -73,6 +81,13 @@ o/$(MODE)/tool/build/emubin/lisp.bin.dbg: \
tool/build/emubin/lisp.lds
@$(ELFLINK) -z max-page-size=0x10
o/$(MODE)/tool/build/emubin/love.bin.dbg: \
$(TOOL_BUILD_EMUBIN_DEPS) \
o/$(MODE)/tool/build/emubin/love.o \
o/$(MODE)/tool/build/emubin/lispstart.o \
tool/build/emubin/lisp.lds
@$(ELFLINK) -z max-page-size=0x10
o/tiny/tool/build/emubin/spiral.bin.dbg: \
$(TOOL_BUILD_EMUBIN_DEPS) \
o/tiny/tool/build/emubin/spiral.real.o

View file

@ -18,15 +18,13 @@
*/
#include "tool/build/emubin/lisp.h"
#define TRACE 0 // print eval input output
#define RETRO 1 // auto capitalize input
#define ERRORS 1 // print messages or undefined behavior
#define DELETE 1 // allow backspace to rub out symbol
#define QUOTES 1 // allow 'X shorthand (QUOTE X)
#define MUTABLE 0 // allow setting globals
#define PROMPT 1 // show repl prompt
#define WORD short
#define WORDS 8192
#define TRACE 0 // print eval input output
#define RETRO 0 // auto capitalize input
#define DELETE 0 // allow backspace to rub out symbol
#define QUOTES 0 // allow 'X shorthand (QUOTE X)
#define PROMPT 0 // show repl prompt
#define WORD short
#define WORDS 8192
/*───────────────────────────────────────────────────────────────────────────│─╗
The LISP Challenge § LISP Machine
@ -36,25 +34,16 @@
#define CONS 1
#define NIL 0
#define ATOM_T 8
#define ATOM_QUOTE 12
#define ATOM_ATOM 24
#define ATOM_EQ 34
#define ATOM_COND 40
#define ATOM_CAR 50
#define ATOM_CDR 58
#define ATOM_CONS 66
#define ATOM_LAMBDA 76
#define ATOM_SET 90
#define Quote(x) List(ATOM_QUOTE, x)
#define List(x, y) Cons(x, Cons(y, NIL))
#define Caar(x) Car(Car(x)) // ((A B C D) (E F G) H I) → A
#define Cdar(x) Cdr(Car(x)) // ((A B C D) (E F G) H I) → (B C D)
#define Cadar(x) Cadr(Car(x)) // ((A B C D) (E F G) H I) → B
#define Caddar(x) Caddr(Car(x)) // ((A B C D) (E F G) H I) → C
#define Cadr(x) Car(Cdr(x)) // ((A B C D) (E F G) H I) → (E F G)
#define Caddr(x) Cadr(Cdr(x)) // ((A B C D) (E F G) H I) → H
#define UNDEFINED 8
#define ATOM_T 30
#define ATOM_QUOTE 34
#define ATOM_ATOM 46
#define ATOM_EQ 56
#define ATOM_COND 62
#define ATOM_CAR 72
#define ATOM_CDR 80
#define ATOM_CONS 88
#define ATOM_LAMBDA 98
#define BOOL(x) ((x) ? ATOM_T : NIL)
#define VALUE(x) ((x) >> 1)
@ -67,7 +56,6 @@ struct Lisp {
WORD globals;
WORD index;
char token[128];
long jb[8];
char str[WORDS];
};
@ -75,6 +63,7 @@ _Static_assert(sizeof(struct Lisp) <= 0x7c00 - 0x600,
"LISP Machine too large for real mode");
_Alignas(char) const char kSymbols[] = "NIL\0"
"*UNDEFINED\0"
"T\0"
"QUOTE\0"
"ATOM\0"
@ -83,8 +72,7 @@ _Alignas(char) const char kSymbols[] = "NIL\0"
"CAR\0"
"CDR\0"
"CONS\0"
"LAMBDA\0"
"SET\0";
"LAMBDA\0";
#ifdef __REAL_MODE__
static struct Lisp *const q;
@ -112,6 +100,10 @@ static void SetupSyntax(void) {
#endif
}
static void SetupBuiltins(void) {
CopyMemory(q->str, kSymbols, sizeof(kSymbols));
}
static inline WORD Car(long x) {
return PEEK_ARRAY(q, mem, VALUE(x), 0);
}
@ -136,23 +128,16 @@ static WORD Cons(WORD car, WORD cdr) {
return cell;
}
static void SetupBuiltins(void) {
CopyMemory(q->str, kSymbols, sizeof(kSymbols));
q->mem[0] = PTR(2);
q->globals = PTR(0);
q->index = 4;
}
static char *StpCpy(char *d, char *s) {
char c;
do {
c = LODS(s); /* a.k.a. c = *s++; */
STOS(d, c); /* a.k.a. *d++ = c; */
c = LODS(s); // a.k.a. c = *s++
STOS(d, c); // a.k.a. *d++ = c
} while (c);
return d;
}
WORD Intern(char *s) {
static WORD Intern(char *s) {
int j, cx;
char c, *z, *t;
z = q->str;
@ -175,7 +160,7 @@ WORD Intern(char *s) {
return OBJECT(ATOM, SUB((long)z, q->str));
}
forceinline unsigned char XlatSyntax(unsigned char b) {
static unsigned char XlatSyntax(unsigned char b) {
return PEEK_ARRAY(q, syntax, b, 0);
}
@ -207,17 +192,19 @@ static int GetChar(void) {
static void GetToken(void) {
char *t;
unsigned char b;
unsigned char b, x;
b = q->look;
t = q->token;
while (XlatSyntax(b) == ' ') {
for (;;) {
x = XlatSyntax(b);
if (x != ' ') break;
b = GetChar();
}
if (XlatSyntax(b)) {
if (x) {
STOS(t, b);
b = GetChar();
} else {
while (b && !XlatSyntax(b)) {
while (b && !x) {
if (!DELETE || b != '\b') {
STOS(t, b);
} else if (t > q->token) {
@ -225,6 +212,7 @@ static void GetToken(void) {
if (t > q->token) --t;
}
b = GetChar();
x = XlatSyntax(b);
}
}
STOS(t, 0);
@ -236,6 +224,18 @@ static WORD ConsumeObject(void) {
return GetObject();
}
static WORD Cadr(long x) {
return Car(Cdr(x)); // ((A B C D) (E F G) H I) → (E F G)
}
static WORD List(long x, long y) {
return Cons(x, Cons(y, NIL));
}
static WORD Quote(long x) {
return List(ATOM_QUOTE, x);
}
static WORD GetQuote(void) {
return Quote(ConsumeObject());
}
@ -298,7 +298,7 @@ static void PrintList(long x) {
PrintChar('(');
PrintObject(Car(x));
while ((x = Cdr(x))) {
if (TYPE(x) == CONS) {
if (!ISATOM(x)) {
PrintChar(' ');
PrintObject(Car(x));
} else {
@ -311,7 +311,7 @@ static void PrintList(long x) {
}
static void PrintObject(long x) {
if (TYPE(x) == ATOM) {
if (ISATOM(x)) {
PrintAtom(x);
} else {
PrintList(x);
@ -323,42 +323,38 @@ static void Print(long i) {
PrintString("\r\n");
}
__attribute__((__noreturn__)) static void Reset(void) {
longjmp(q->jb, 1);
}
__attribute__((__noreturn__)) static void OnArity(void) {
PrintString("ARITY!\n");
Reset();
}
__attribute__((__noreturn__)) static void OnUndefined(long x) {
PrintString("UNDEF! ");
Print(x);
Reset();
}
#if !ERRORS
#define OnArity() __builtin_unreachable()
#define OnUndefined(x) __builtin_unreachable()
#endif
/*───────────────────────────────────────────────────────────────────────────│─╗
The LISP Challenge § Bootstrap John McCarthy's Metacircular Evaluator
*/
static WORD Atom(long x) {
return BOOL(TYPE(x) == ATOM);
return BOOL(ISATOM(x));
}
static WORD Null(long x) {
return BOOL(!x);
}
static WORD Eq(long x, long y) {
WORD Eq(long x, long y) {
return BOOL(x == y);
}
static WORD Caar(long x) {
return Car(Car(x)); // ((A B C D) (E F G) H I) → A
}
static WORD Cdar(long x) {
return Cdr(Car(x)); // ((A B C D) (E F G) H I) → (B C D)
}
static WORD Cadar(long x) {
return Cadr(Car(x)); // ((A B C D) (E F G) H I) → B
}
static WORD Caddr(long x) {
return Cadr(Cdr(x)); // ((A B C D) (E F G) H I) → H
}
static WORD Caddar(long x) {
return Caddr(Car(x)); // ((A B C D) (E F G) H I) → C
}
static WORD Arg1(long e, long a) {
return Eval(Cadr(e), a);
}
@ -368,37 +364,36 @@ static WORD Arg2(long e, long a) {
}
static WORD Append(long x, long y) {
return Null(x) ? y : Cons(Car(x), Append(Cdr(x), y));
return x ? Cons(Car(x), Append(Cdr(x), y)) : y;
}
static WORD Evcon(long c, long a) {
return Eval(Caar(c), a) ? Eval(Cadar(c), a) : Evcon(Cdr(c), a);
}
static WORD Evlis(long m, long a) {
return m ? Cons(Eval(Car(m), a), Evlis(Cdr(m), a)) : NIL;
static WORD Bind(long v, long a, long e) {
return v ? Cons(Cons(Car(v), Eval(Car(a), e)), Bind(Cdr(v), Cdr(a), e)) : e;
}
static WORD Assoc(long x, long y) {
if (!y) OnUndefined(x);
return Eq(Caar(y), x) ? Cdar(y) : Assoc(x, Cdr(y));
return y ? Eq(Caar(y), x) ? Cdar(y) : Assoc(x, Cdr(y)) : NIL;
}
static WORD Pair(long x, long y) {
if (Null(x) && Null(y)) {
if (Atom(x) || Atom(y)) {
return NIL;
} else if (!Atom(x) && !Atom(y)) {
return Cons(Cons(Car(x), Car(y)), Pair(Cdr(x), Cdr(y)));
} else {
OnArity();
return Cons(Cons(Car(x), Car(y)), Pair(Cdr(x), Cdr(y)));
}
}
static WORD Evaluate(long e, long a) {
__attribute__((__noinline__)) static WORD Evaluate(long e, long a) {
if (Atom(e)) {
return Assoc(e, a);
} else if (Atom(Car(e))) {
switch (Car(e)) {
case NIL:
return UNDEFINED;
case ATOM_QUOTE:
return Cadr(e);
case ATOM_ATOM:
@ -413,17 +408,13 @@ static WORD Evaluate(long e, long a) {
return Cdr(Arg1(e, a));
case ATOM_CONS:
return Cons(Arg1(e, a), Arg2(e, a));
#if MUTABLE
case ATOM_SET:
return Cdar(Set(a, Cons(Arg1(e, a), Arg2(e, a)), Cons(Car(a), Cdr(a))));
#endif
default:
return Eval(Cons(Assoc(Car(e), a), Evlis(Cdr(e), a)), a);
return Eval(Cons(Assoc(Car(e), a), Cdr(e)), a);
}
} else if (Eq(Caar(e), ATOM_LAMBDA)) {
return Eval(Caddar(e), Append(Pair(Cadar(e), Evlis(Cdr(e), a)), a));
return Eval(Caddar(e), Bind(Cadar(e), Cdr(e), a));
} else {
OnUndefined(Caar(e));
return UNDEFINED;
}
}
@ -448,9 +439,6 @@ static WORD Eval(long e, long a) {
*/
void Repl(void) {
#if ERRORS
setjmp(q->jb);
#endif
for (;;) {
#if PROMPT
PrintString("* ");
@ -460,7 +448,7 @@ void Repl(void) {
}
int main(int argc, char *argv[]) {
/* RawMode(); */
RawMode();
SetupSyntax();
SetupBuiltins();
#if PROMPT

View file

@ -4,11 +4,11 @@
#define CompilerBarrier() asm volatile("" ::: "memory");
#define TYPE(x) /* a.k.a. x&1 */ \
({ \
char IsAtom; \
asm("test%z1\t$1,%1" : "=@ccnz"(IsAtom) : "Qm"((char)x)); \
IsAtom; \
#define ISATOM(x) /* a.k.a. !(x&1) */ \
({ \
_Bool IsAtom; \
asm("test%z1\t$1,%1" : "=@ccz"(IsAtom) : "Qm"((char)x)); \
IsAtom; \
})
#define OBJECT(t, v) /* a.k.a. v<<1|t */ \
@ -112,9 +112,6 @@
} \
} while (0)
int setjmp(void *) __attribute__((__returns_twice__));
int longjmp(void *, int) __attribute__((__noreturn__));
static inline void *SetMemory(void *di, int al, unsigned long cx) {
asm("rep stosb"
: "=D"(di), "=c"(cx), "=m"(*(char(*)[cx])di)
@ -170,6 +167,7 @@ static int ReadChar(void) {
int c;
#ifdef __REAL_MODE__
asm volatile("int\t$0x16" : "=a"(c) : "0"(0) : "memory");
c &= 0xff;
#else
static int buf;
asm volatile("syscall"

View file

@ -29,7 +29,7 @@ SECTIONS {
. = 0x1fe;
SHORT(0xaa55);
*(.text .text.*)
BYTE(0x90);
/*BYTE(0x90);*/
_etext = .;
. = ALIGN(512);
}

View file

@ -1,30 +1,105 @@
;; (SET 'APPLY '(LAMBDA (E ARGS)
;; ((LAMBDA (APPQ)
;; (CONS ))
;; '(LAMBDA (M)
;; (COND ((EQ M 'NIL) 'NIL)
;; ('T (CONS (QUOTE (CAR M))
;; (APPQ (CONS 'QUOTE (CDR M))))))))))
;; (SET 'LIST '(LAMBDA (X Y) (CONS X (CONS Y 'NIL))))
;; (SET 'AND '(LAMBDA (P Q) (COND ((EQ P 'T) Q) ('T 'F))))
;; (SET 'OR '(LAMBDA (P Q) (COND ((EQ P 'T) 'T) ('T Q))))
;; (SET 'NOT '(LAMBDA (P) (COND ((EQ P 'F) 'T) ('T 'T))))
;; (SET 'IMPLIES '(LAMBDA (P Q) (COND ((EQ P 'T) Q) ('T 'T))))
;; (setq lisp-indent-function 'common-lisp-indent-function)
;; (paredit-mode)
((LAMBDA (CALL MKQUOT NULL AND APPEND KEYS VALS E A)
(CALL (CONS (CONS (QUOTE LAMBDA) (CONS (KEYS (QUOTE A)) (CONS E NIL))) (VALS (QUOTE A)))))
(QUOTE (LAMBDA (X) (X)))
(QUOTE (LAMBDA (X) (CONS (QUOTE QUOTE) (CONS X NIL))))
(QUOTE (LAMBDA (P Q) (COND ((EQ P (QUOTE T)) Q) ((QUOTE T) (QUOTE F)))))
(QUOTE (LAMBDA (X) (AND (QUOTE (ATOM X)) (QUOTE (EQ X NIL)))))
(QUOTE (LAMBDA (X Y) (COND ((EQ X NIL) Y) ((QUOTE T) (CONS (CAR X) (APPEND (QUOTE (CDR X)) (QUOTE Y)))))))
(QUOTE (LAMBDA (A) (COND ((EQ A NIL) NIL) ((QUOTE T) (CONS (CAR (CAR A)) (KEYS (QUOTE (CDR A))))))))
(QUOTE (LAMBDA (A) (COND ((EQ A NIL) NIL) ((QUOTE T) (CONS (MKQUOT (QUOTE (CDR (CAR A)))) (VALS (QUOTE (CDR A))))))))
(QUOTE (AND (QUOTE A) (QUOTE C)))
(CONS (CONS (QUOTE A) (QUOTE B)) (CONS (CONS (QUOTE C) (QUOTE D)) NIL)))
;; ________
;; /_ __/ /_ ___
;; / / / __ \/ _ \
;; / / / / / / __/
;; /_/ /_/ /_/\___/
;; __ _________ ____ ________ ____
;; / / / _/ ___// __ \ / ____/ /_ ____ _/ / /__ ____ ____ ____
;; / / / / \__ \/ /_/ / / / / __ \/ __ `/ / / _ \/ __ \/ __ `/ _ \
;; / /____/ / ___/ / ____/ / /___/ / / / /_/ / / / __/ / / / /_/ / __/
;; /_____/___//____/_/ \____/_/ /_/\__,_/_/_/\___/_/ /_/\__, /\___/
;; /____/
;;
;; THE LISP CHALLENGE
;;
;; PICK YOUR FAVORITE PROGRAMMING LANGUAGE
;; IMPLEMENT THE TINIEST POSSIBLE LISP MACHINE THAT
;; BOOTSTRAPS JOHN MCCARTHY'S METACIRCULAR EVALUATOR
;; WINNING IS DEFINED BY LINES OF CODE FOR SCRIPTING LANGUAGES
;; WINNING IS DEFINED BY BINARY FOOTPRINT FOR COMPILED LANGUAGES
;;
;; @SEE LISP FROM NOTHING; NILS M. HOLM; LULU PRESS, INC. 2020
;; @SEE RECURSIVE FUNCTIONS OF SYMBOLIC EXPRESSIONS AND THEIR
;; COMPUTATION BY MACHINE, PART I; JOHN MCCARTHY, MASSACHUSETTS
;; INSTITUTE OF TECHNOLOGY, CAMBRIDGE, MASS. APRIL 1960
((LAMBDA (FF X) (FF 'X))
'(LAMBDA (X)
(COND ((ATOM X) X)
((QUOTE T) (FF '(CAR X)))))
'((A) B C))
;; NIL ATOM
;; ABSENCE OF VALUE
NIL
;; CONS CELL
;; BUILDING BLOCK OF DATA STRUCTURES
(CONS NIL NIL)
;; REFLECTION
;; EVERYTHING IS AN ATOM OR NOT AN ATOM
(ATOM NIL)
(ATOM (CONS NIL NIL))
;; QUOTING
;; CODE IS DATA AND DATA IS CODE
(QUOTE (CONS NIL NIL))
(CONS (QUOTE CONS) (CONS NIL (CONS NIL NIL)))
;; LOGIC
;; LAW OF IDENTITY VIA STRING INTERNING
(EQ (QUOTE A) (QUOTE A))
;; FIND FIRST ATOM IN TREE
;; RECURSIVE CONDITIONAL FUNCTION BINDING
((LAMBDA (FF X) (FF X))
(QUOTE (LAMBDA (X)
(COND ((ATOM X) X)
((QUOTE T) (FF (CAR X))))))
(QUOTE ((A) B C)))
;; LISP IMPLEMENTED IN LISP
;; USED TO EVALUATE FIND FIRST ATOM IN TREE
;; REQUIRES CONS CAR CDR QUOTE ATOM EQ LAMBDA COND
;; FIXES BUGS FROM JOHN MCCARTHY PAPER AND MORE MINIMAL
((LAMBDA (ASSOC EVCON BIND APPEND EVAL)
(EVAL (QUOTE ((LAMBDA (FF X) (FF X))
(QUOTE (LAMBDA (X)
(COND ((ATOM X) X)
((QUOTE T) (FF (CAR X))))))
(QUOTE ((A) B C))))
NIL))
(QUOTE (LAMBDA (X E)
(COND ((EQ E NIL) NIL)
((EQ X (CAR (CAR E))) (CDR (CAR E)))
((QUOTE T) (ASSOC X (CDR E))))))
(QUOTE (LAMBDA (C E)
(COND ((EVAL (CAR (CAR C)) E) (EVAL (CAR (CDR (CAR C))) E))
((QUOTE T) (EVCON (CDR C) E)))))
(QUOTE (LAMBDA (V A E)
(COND ((EQ V NIL) E)
((QUOTE T) (CONS (CONS (CAR V) (EVAL (CAR A) E))
(BIND (CDR V) (CDR A) E))))))
(QUOTE (LAMBDA (A B)
(COND ((EQ A NIL) B)
((QUOTE T) (CONS (CAR A) (APPEND (CDR A) B))))))
(QUOTE (LAMBDA (E A)
(COND
((ATOM E) (ASSOC E A))
((ATOM (CAR E))
(COND
((EQ (CAR E) NIL) (QUOTE *UNDEFINED))
((EQ (CAR E) (QUOTE QUOTE)) (CAR (CDR E)))
((EQ (CAR E) (QUOTE ATOM)) (ATOM (EVAL (CAR (CDR E)) A)))
((EQ (CAR E) (QUOTE EQ)) (EQ (EVAL (CAR (CDR E)) A)
(EVAL (CAR (CDR (CDR E))) A)))
((EQ (CAR E) (QUOTE CAR)) (CAR (EVAL (CAR (CDR E)) A)))
((EQ (CAR E) (QUOTE CDR)) (CDR (EVAL (CAR (CDR E)) A)))
((EQ (CAR E) (QUOTE CONS)) (CONS (EVAL (CAR (CDR E)) A)
(EVAL (CAR (CDR (CDR E))) A)))
((EQ (CAR E) (QUOTE COND)) (EVCON (CDR E) A))
((EQ (CAR E) (QUOTE LABEL)) (EVAL (CAR (CDR (CDR E)))
(APPEND (CAR (CDR E)) A)))
((EQ (CAR E) (QUOTE LAMBDA)) E)
((QUOTE T) (EVAL (CONS (EVAL (CAR E) A) (CDR E)) A))))
((EQ (CAR (CAR E)) (QUOTE LAMBDA))
(EVAL (CAR (CDR (CDR (CAR E))))
(BIND (CAR (CDR (CAR E))) (CDR E) A)))))))

View file

@ -0,0 +1,23 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
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/macros.h"
_start: jmp main
.endfn _start,globl

View file

@ -49,29 +49,3 @@ _begin: push %cs
jmp main
.type _begin,@function
.size _begin,.-_begin
.section .start.setjmp,"ax",@progbits
setjmp: mov %sp,%ax
stosw
xchg %ax,%si
movsw %ss:(%si),(%di)
mov %bp,%ax
stosw
ret $6
.type setjmp,@function
.size setjmp,.-setjmp
.globl setjmp
.previous
.section .start.longjmp,"ax",@progbits
longjmp:
mov (%di),%sp
mov 2(%di),%dx
mov 4(%di),%bp
pop %ax
mov %si,%ax
jmp *%dx
.type longjmp,@function
.size longjmp,.-longjmp
.globl longjmp
.previous

View file

@ -37,15 +37,6 @@ const aluop_f kBsu[8][4] = {
{Shl8, Shl16, Shl32, Shl64}, {Sar8, Sar16, Sar32, Sar64},
};
int64_t AluFlags(uint64_t x, uint32_t af, uint32_t *f, uint32_t of, uint32_t cf,
uint32_t sf) {
*f &= ~(1u << FLAGS_CF | 1u << FLAGS_ZF | 1u << FLAGS_SF | 1u << FLAGS_OF |
1u << FLAGS_AF | 0xFF000000u);
*f |= sf << FLAGS_SF | cf << FLAGS_CF | !x << FLAGS_ZF | of << FLAGS_OF |
af << FLAGS_AF | (x & 0xFF) << 24;
return x;
}
int64_t AluFlags8(uint8_t z, uint32_t af, uint32_t *f, uint32_t of,
uint32_t cf) {
return AluFlags(z, af, f, of, cf, z >> 7);

View file

@ -108,7 +108,6 @@ int64_t Rcl64(uint64_t, uint64_t, uint32_t *);
uint64_t BsuDoubleShift(int, uint64_t, uint64_t, uint8_t, bool, uint32_t *);
int64_t AluFlags(uint64_t, uint32_t, uint32_t *, uint32_t, uint32_t, uint32_t);
int64_t AluFlags8(uint8_t, uint32_t, uint32_t *, uint32_t, uint32_t);
int64_t AluFlags16(uint16_t, uint32_t, uint32_t *, uint32_t, uint32_t);
int64_t AluFlags32(uint32_t, uint32_t, uint32_t *, uint32_t, uint32_t);

View file

@ -49,16 +49,17 @@ void AppendWide(struct Buffer *b, wint_t wc) {
} while (wb);
}
void AppendFmt(struct Buffer *b, const char *fmt, ...) {
int size;
int AppendFmt(struct Buffer *b, const char *fmt, ...) {
int bytes;
char *tmp;
va_list va;
tmp = NULL;
va_start(va, fmt);
size = vasprintf(&tmp, fmt, va);
bytes = vasprintf(&tmp, fmt, va);
va_end(va);
if (size != -1) AppendData(b, tmp, size);
if (bytes != -1) AppendData(b, tmp, bytes);
free(tmp);
return bytes;
}
/**

View file

@ -12,7 +12,7 @@ void AppendChar(struct Buffer *, char);
void AppendData(struct Buffer *, char *, size_t);
void AppendStr(struct Buffer *, const char *);
void AppendWide(struct Buffer *, wint_t);
void AppendFmt(struct Buffer *, const char *, ...);
int AppendFmt(struct Buffer *, const char *, ...);
ssize_t WriteBuffer(struct Buffer *, int);
COSMOPOLITAN_C_END_

View file

@ -68,6 +68,10 @@ $(TOOL_BUILD_LIB_A_OBJS): \
-fsanitize=address
endif
o/$(MODE)/tool/build/lib/memory-gcc.asm: \
OVERRIDE_CFLAGS += \
-fsanitize=address
o/$(MODE)/tool/build/lib/ssefloat.o: \
TARGET_ARCH += \
-msse3

View file

@ -31,8 +31,8 @@ void OpCpuid(struct Machine *m, uint32_t rde) {
case 0x80000000:
ax = 7;
bx = 'G' | 'e' << 8 | 'n' << 16 | 'u' << 24;
cx = 'i' | 'n' << 8 | 'e' << 16 | 'C' << 24;
dx = 'o' | 's' << 8 | 'm' << 16 | 'o' << 24;
dx = 'i' | 'n' << 8 | 'e' << 16 | 'C' << 24;
cx = 'o' | 's' << 8 | 'm' << 16 | 'o' << 24;
break;
case 1:
cx |= 1 << 0; // sse3

View file

@ -89,7 +89,7 @@ static char *DisError(struct Dis *d, char *p) {
p = HighStart(p, g_high.comment);
*p++ = '#';
*p++ = ' ';
p = stpcpy(p, indexdoublenulstring(kXedErrorNames, d->xedd->op.error));
p = stpcpy(p, IndexDoubleNulString(kXedErrorNames, d->xedd->op.error));
p = HighEnd(p);
*p = '\0';
return p;

View file

@ -30,10 +30,10 @@ struct Dis {
size_t i, n;
struct DisSym {
int64_t addr;
int rank;
int unique;
int size;
int name;
char rank;
bool iscode;
bool isabs;
} * p;

View file

@ -156,17 +156,12 @@ static char *DisSymImpl(struct Dis *d, char *p, int64_t x, long sym) {
return p;
}
static char *DisSym(struct Dis *d, char *p, int64_t x1, int64_t x2,
bool isrelative) {
static char *DisSym(struct Dis *d, char *p, int64_t value, int64_t addr) {
long sym;
if ((sym = DisFindSym(d, x2)) != -1 && d->syms.p[sym].name &&
(d->syms.p[sym].isabs ^ isrelative)) {
return DisSymImpl(d, p, x2, sym);
} else if ((sym = DisFindSym(d, x1)) != -1 && d->syms.p[sym].name &&
(d->syms.p[sym].isabs ^ isrelative)) {
return DisSymImpl(d, p, x1, sym);
if ((sym = DisFindSym(d, addr)) != -1 && d->syms.p[sym].name) {
return DisSymImpl(d, p, addr, sym);
} else {
return DisInt(p, x1);
return DisInt(p, value);
}
}
@ -174,7 +169,7 @@ static char *DisSymLiteral(struct Dis *d, uint32_t rde, char *p, uint64_t addr,
uint64_t ip) {
*p++ = '$';
p = HighStart(p, g_high.literal);
p = DisSym(d, p, addr, addr, false);
p = DisSym(d, p, addr, addr);
p = HighEnd(p);
return p;
}
@ -227,7 +222,7 @@ static char *DisDisp(struct Dis *d, uint32_t rde, char *p) {
} else {
rela = true;
}
p = DisSym(d, p, disp, disp, rela);
p = DisSym(d, p, disp, disp);
}
return p;
}
@ -477,11 +472,11 @@ static char *DisJb(struct Dis *d, uint32_t rde, char *p) {
static char *DisJvds(struct Dis *d, uint32_t rde, char *p) {
return DisSym(d, p, RipRelative(d, d->xedd->op.disp),
RipRelative(d, d->xedd->op.disp) - Read64(d->m->cs), true);
RipRelative(d, d->xedd->op.disp) - Read64(d->m->cs));
}
static char *DisAbs(struct Dis *d, uint32_t rde, char *p) {
return DisSym(d, p, d->xedd->op.disp, d->xedd->op.disp, false);
return DisSym(d, p, d->xedd->op.disp, d->xedd->op.disp);
}
static char *DisSw(struct Dis *d, uint32_t rde, char *p) {

View file

@ -18,12 +18,12 @@
02110-1301 USA
*/
#include "libc/alg/alg.h"
#include "libc/alg/arraylist2.h"
#include "libc/elf/elf.h"
#include "libc/elf/struct/sym.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.h"
#include "libc/mem/mem.h"
#include "libc/str/str.h"
#include "tool/build/lib/dis.h"
@ -46,38 +46,51 @@ static int DisSymCompare(const struct DisSym *a, const struct DisSym *b) {
}
static void DisLoadElfLoads(struct Dis *d, struct Elf *elf) {
long i;
long i, j, n;
int64_t addr;
uint64_t size;
Elf64_Phdr *phdr;
struct DisLoad l;
d->loads.i = 0;
for (i = 0; i < elf->ehdr->e_phnum; ++i) {
j = 0;
n = elf->ehdr->e_phnum;
if (d->loads.n < n) {
d->loads.n = n;
d->loads.p = realloc(d->loads.p, d->loads.n * sizeof(*d->loads.p));
CHECK_NOTNULL(d->loads.p);
}
for (i = 0; i < n; ++i) {
phdr = getelfsegmentheaderaddress(elf->ehdr, elf->size, i);
if (phdr->p_type != PT_LOAD) continue;
l.addr = phdr->p_vaddr;
l.size = phdr->p_memsz;
l.istext = (phdr->p_flags & PF_X) == PF_X;
APPEND(&d->loads.p, &d->loads.i, &d->loads.n, &l);
d->loads.p[j].addr = phdr->p_vaddr;
d->loads.p[j].size = phdr->p_memsz;
d->loads.p[j].istext = (phdr->p_flags & PF_X) == PF_X;
++j;
}
d->loads.i = j;
}
static void DisLoadElfSyms(struct Dis *d, struct Elf *elf) {
size_t i, n;
size_t i, j, n;
int64_t stablen;
struct DisSym t;
const Elf64_Sym *st, *sym;
bool isabs, iscode, isweak, islocal, ishidden, isprotected, isfunc, isobject;
d->syms.i = 0;
j = 0;
if ((d->syms.stab = getelfstringtable(elf->ehdr, elf->size)) &&
(st = getelfsymboltable(elf->ehdr, elf->size, &n))) {
stablen = (intptr_t)elf->ehdr + elf->size - (intptr_t)d->syms.stab;
if (d->syms.n < n) {
d->syms.n = n;
d->syms.p = realloc(d->syms.p, d->syms.n * sizeof(*d->syms.p));
CHECK_NOTNULL(d->syms.p);
}
for (i = 0; i < n; ++i) {
if (!st[i].st_name) continue;
if (!(0 <= st[i].st_name && st[i].st_name < stablen)) continue;
if (ELF64_ST_TYPE(st[i].st_info) == STT_SECTION) continue;
if (ELF64_ST_TYPE(st[i].st_info) == STT_FILE) continue;
if (startswith(d->syms.stab + st[i].st_name, "v_")) continue;
if (ELF64_ST_TYPE(st[i].st_info) == STT_SECTION ||
ELF64_ST_TYPE(st[i].st_info) == STT_FILE || !st[i].st_name ||
startswith(d->syms.stab + st[i].st_name, "v_") ||
!(0 <= st[i].st_name && st[i].st_name < stablen) || !st[i].st_value ||
!(-0x800000000000 <= (int64_t)st[i].st_value &&
(int64_t)st[i].st_value < 0x800000000000)) {
continue;
}
isabs = st[i].st_shndx == SHN_ABS;
isweak = ELF64_ST_BIND(st[i].st_info) == STB_WEAK;
islocal = ELF64_ST_BIND(st[i].st_info) == STB_LOCAL;
@ -85,19 +98,51 @@ static void DisLoadElfSyms(struct Dis *d, struct Elf *elf) {
isprotected = st[i].st_other == STV_PROTECTED;
isfunc = ELF64_ST_TYPE(st[i].st_info) == STT_FUNC;
isobject = ELF64_ST_TYPE(st[i].st_info) == STT_OBJECT;
t.unique = i;
t.size = st[i].st_size;
t.name = st[i].st_name;
t.addr = st[i].st_value;
t.rank = -islocal + -isweak + -isabs + isprotected + isobject + isfunc;
t.iscode = DisIsText(d, st[i].st_value) ? !isobject : isfunc;
t.isabs = isabs;
APPEND(&d->syms.p, &d->syms.i, &d->syms.n, &t);
d->syms.p[j].unique = i;
d->syms.p[j].size = st[i].st_size;
d->syms.p[j].name = st[i].st_name;
d->syms.p[j].addr = st[i].st_value;
d->syms.p[j].rank =
-islocal + -isweak + -isabs + isprotected + isobject + isfunc;
d->syms.p[j].iscode = DisIsText(d, st[i].st_value) ? !isobject : isfunc;
d->syms.p[j].isabs = isabs;
++j;
}
}
d->syms.i = j;
}
static void DisSortSyms(struct Dis *d) {
qsort(d->syms.p, d->syms.i, sizeof(struct DisSym), (void *)DisSymCompare);
}
static void DisCanonizeSyms(struct Dis *d) {
int64_t i, j, a;
if (d->syms.i) {
i = 1;
j = 1;
a = d->syms.p[0].addr;
do {
if (d->syms.p[j].addr > a) {
a = d->syms.p[j].addr;
if (j > i) {
d->syms.p[i] = d->syms.p[j];
}
++i;
}
++j;
} while (j < d->syms.i);
d->syms.p = realloc(d->syms.p, sizeof(*d->syms.p) * i);
d->syms.i = i;
d->syms.n = i;
}
for (i = 0; i < d->syms.i; ++i) {
DEBUGF("%p-%p %s", d->syms.p[i].addr,
d->syms.p[i].addr + (d->syms.p[i].size ? d->syms.p[i].size - 1 : 0),
d->syms.stab + d->syms.p[i].name);
}
}
bool DisIsProg(struct Dis *d, int64_t addr) {
long i;
if (g_disisprog_disable) return true;
@ -122,36 +167,24 @@ bool DisIsText(struct Dis *d, int64_t addr) {
}
long DisFindSym(struct Dis *d, int64_t addr) {
size_t i, l, r, m, n;
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;
}
}
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;
}
long l, r, m, n;
if (DisIsProg(d, addr)) {
l = 0;
r = d->syms.i;
while (l < r) {
m = (l + r) >> 1;
if (d->syms.p[m].addr > addr) {
r = m;
} else {
l = m + 1;
}
}
if (r && (addr == d->syms.p[r - 1].addr ||
(addr > d->syms.p[r - 1].addr &&
(addr <= d->syms.p[r - 1].addr + d->syms.p[r - 1].size ||
!d->syms.p[r - 1].size)))) {
return r - 1;
}
}
return -1;
}
@ -170,4 +203,6 @@ void DisLoadElf(struct Dis *d, struct Elf *elf) {
if (!elf || !elf->ehdr) return;
DisLoadElfLoads(d, elf);
DisLoadElfSyms(d, elf);
DisSortSyms(d);
DisCanonizeSyms(d);
}

View file

@ -53,3 +53,12 @@ uint64_t ExportFlags(uint64_t flags) {
flags |= GetLazyParityBool(flags) << FLAGS_PF;
return flags;
}
int64_t AluFlags(uint64_t x, uint32_t af, uint32_t *f, uint32_t of, uint32_t cf,
uint32_t sf) {
*f &= ~(1u << FLAGS_CF | 1u << FLAGS_ZF | 1u << FLAGS_SF | 1u << FLAGS_OF |
1u << FLAGS_AF | 0xFF000000u);
*f |= sf << FLAGS_SF | cf << FLAGS_CF | !x << FLAGS_ZF | of << FLAGS_OF |
af << FLAGS_AF | (x & 0xFF) << 24;
return x;
}

View file

@ -64,6 +64,7 @@ COSMOPOLITAN_C_START_
bool GetParity(uint8_t);
uint64_t ExportFlags(uint64_t);
void ImportFlags(struct Machine *, uint64_t);
int64_t AluFlags(uint64_t, uint32_t, uint32_t *, uint32_t, uint32_t, uint32_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -46,9 +46,6 @@ static void LoadElfLoadSegment(struct Machine *m, void *code, size_t codesize,
align = MAX(phdr->p_align, PAGESIZE);
CHECK_EQ(1, popcnt(align));
CHECK_EQ(0, (phdr->p_vaddr - phdr->p_offset) % align);
/*-Type-Offset---VirtAddr-----------PhysAddr-----------FileSiz--MemSiz---Flg-Align----*/
/*-LOAD-0x000000-0x0000000000400000-0x0000000000400000-0x0008e4-0x0008e4-R-E-0x200000-*/
/*-LOAD-0x000fe0-0x0000000000600fe0-0x0000000000600fe0-0x000030-0x000310-RW--0x200000-*/
felf = (int64_t)(intptr_t)code;
vstart = ROUNDDOWN(phdr->p_vaddr, align);
vbss = ROUNDUP(phdr->p_vaddr + phdr->p_filesz, align);
@ -56,10 +53,10 @@ static void LoadElfLoadSegment(struct Machine *m, void *code, size_t codesize,
fstart = felf + ROUNDDOWN(phdr->p_offset, align);
fend = felf + phdr->p_offset + phdr->p_filesz;
bsssize = vend - vbss;
LOGF("LOADELFLOADSEGMENT"
" VSTART %#lx VBSS %#lx VEND %#lx"
" FSTART %#lx FEND %#lx BSSSIZE %#lx",
vstart, vbss, vend, fstart, fend, bsssize);
VERBOSEF("LOADELFLOADSEGMENT"
" VSTART %#lx VBSS %#lx VEND %#lx"
" FSTART %#lx FEND %#lx BSSSIZE %#lx",
vstart, vbss, vend, fstart, fend, bsssize);
m->brk = MAX(m->brk, vend);
CHECK_GE(vend, vstart);
CHECK_GE(fend, fstart);
@ -69,9 +66,9 @@ static void LoadElfLoadSegment(struct Machine *m, void *code, size_t codesize,
CHECK_GE(vend - vstart, fstart - fend);
CHECK_LE(phdr->p_filesz, phdr->p_memsz);
CHECK_EQ(felf + phdr->p_offset - fstart, phdr->p_vaddr - vstart);
CHECK_NE(-1, ReserveVirtual(m, vstart, fend - fstart));
CHECK_NE(-1, ReserveVirtual(m, vstart, fend - fstart, 0x0207));
VirtualRecv(m, vstart, (void *)fstart, fend - fstart);
if (bsssize) CHECK_NE(-1, ReserveVirtual(m, vbss, bsssize));
if (bsssize) CHECK_NE(-1, ReserveVirtual(m, vbss, bsssize, 0x0207));
if (phdr->p_memsz - phdr->p_filesz > bsssize) {
VirtualSet(m, phdr->p_vaddr + phdr->p_filesz, 0,
phdr->p_memsz - phdr->p_filesz - bsssize);
@ -82,7 +79,7 @@ static void LoadElf(struct Machine *m, struct Elf *elf) {
unsigned i;
Elf64_Phdr *phdr;
m->ip = elf->base = elf->ehdr->e_entry;
LOGF("LOADELF ENTRY %p", m->ip);
VERBOSEF("LOADELF ENTRY %p", m->ip);
for (i = 0; i < elf->ehdr->e_phnum; ++i) {
phdr = getelfsegmentheaderaddress(elf->ehdr, elf->size, i);
switch (phdr->p_type) {
@ -149,9 +146,9 @@ void LoadProgram(struct Machine *m, const char *prog, char **args, char **vars,
}
CHECK_NE(-1, close(fd));
ResetCpu(m);
if (m->mode == XED_MACHINE_MODE_REAL) {
if ((m->mode & 3) == XED_MODE_REAL) {
elf->base = 0x7c00;
CHECK_NE(-1, ReserveVirtual(m, 0, BIGPAGESIZE));
CHECK_NE(-1, ReserveReal(m, BIGPAGESIZE));
m->ip = 0x7c00;
Write64(m->cs, 0);
Write64(m->dx, 0);
@ -168,7 +165,8 @@ void LoadProgram(struct Machine *m, const char *prog, char **args, char **vars,
} else {
sp = 0x800000000000;
Write64(m->sp, sp);
CHECK_NE(-1, ReserveVirtual(m, sp - STACKSIZE, STACKSIZE));
m->cr3 = AllocateLinearPage(m);
CHECK_NE(-1, ReserveVirtual(m, sp - STACKSIZE, STACKSIZE, 0x0207));
LoadArgv(m, prog, args, vars);
if (memcmp(elf->map, "\177ELF", 4) == 0) {
elf->ehdr = (void *)elf->map;

View file

@ -35,6 +35,7 @@
#include "tool/build/lib/machine.h"
#include "tool/build/lib/memory.h"
#include "tool/build/lib/modrm.h"
#include "tool/build/lib/op101.h"
#include "tool/build/lib/sse.h"
#include "tool/build/lib/ssefloat.h"
#include "tool/build/lib/ssemov.h"
@ -883,9 +884,6 @@ static void OpBsubiImm(struct Machine *m, uint32_t rde) {
Bsubi(m, rde, m->xedd->op.uimm0);
}
static void OpLgdtMs(struct Machine *m, uint32_t rde) {
}
static void OpPushImm(struct Machine *m, uint32_t rde) {
Push(m, rde, m->xedd->op.uimm0);
}
@ -1328,21 +1326,6 @@ static void Op0ff(struct Machine *m, uint32_t rde) {
kOp0ff[ModrmReg(rde)](m, rde);
}
static void Op101(struct Machine *m, uint32_t rde) {
if (IsModrmRegister(rde)) {
if (ModrmReg(rde) == 0b111 && ModrmRm(rde) == 0b001) {
OpRdtscp(m, rde);
return;
}
} else {
if (ModrmReg(rde) == 2) {
OpLgdtMs(m, rde);
return;
}
}
OpUd(m, rde);
}
static void OpDoubleShift(struct Machine *m, uint32_t rde) {
uint8_t *p;
uint64_t x;
@ -1400,6 +1383,44 @@ static void OpNop(struct Machine *m, uint32_t rde) {
}
}
static void OpMovRqCq(struct Machine *m, uint32_t rde) {
switch (ModrmReg(rde)) {
case 0:
Write64(RegRexbRm(m, rde), m->cr0);
break;
case 2:
Write64(RegRexbRm(m, rde), m->cr2);
break;
case 3:
Write64(RegRexbRm(m, rde), m->cr3);
break;
case 4:
Write64(RegRexbRm(m, rde), m->cr4);
break;
default:
OpUd(m, rde);
}
}
static void OpMovCqRq(struct Machine *m, uint32_t rde) {
switch (ModrmReg(rde)) {
case 0:
m->cr0 = Read64(RegRexbRm(m, rde));
break;
case 2:
m->cr2 = Read64(RegRexbRm(m, rde));
break;
case 3:
m->cr3 = Read64(RegRexbRm(m, rde));
break;
case 4:
m->cr4 = Read64(RegRexbRm(m, rde));
break;
default:
OpUd(m, rde);
}
}
static const nexgen32e_f kNexgen32e[] = {
[0x000] = OpAlubAdd,
[0x001] = OpAluw,
@ -1689,9 +1710,9 @@ static const nexgen32e_f kNexgen32e[] = {
[0x11D] = OpHintNopEv,
[0x11E] = OpUd,
[0x11F] = OpNopEv,
[0x120] = OpUd,
[0x120] = OpMovRqCq,
[0x121] = OpUd,
[0x122] = OpUd,
[0x122] = OpMovCqRq,
[0x123] = OpUd,
[0x124] = OpUd,
[0x125] = OpUd,

View file

@ -131,6 +131,9 @@ struct Machine {
};
};
} sse;
uint64_t cr0;
uint64_t cr2;
uint64_t cr4;
struct MachineRealFree {
uint64_t i;
uint64_t n;
@ -140,6 +143,15 @@ struct Machine {
uint32_t i;
void *p[6];
} freelist;
struct MachineMemstat {
int freed;
int resizes;
int reserved;
int committed;
int allocated;
int reclaimed;
int pagetables;
} memstat;
int64_t brk;
int64_t bofram[2];
jmp_buf onhalt;
@ -157,7 +169,9 @@ void ResetTlb(struct Machine *);
void LoadInstruction(struct Machine *);
void ExecuteInstruction(struct Machine *);
long AllocateLinearPage(struct Machine *);
int ReserveVirtual(struct Machine *, int64_t, size_t);
long AllocateLinearPageRaw(struct Machine *);
int ReserveReal(struct Machine *, size_t);
int ReserveVirtual(struct Machine *, int64_t, size_t, uint64_t);
char *FormatPml4t(struct Machine *) nodiscard;
int64_t FindVirtual(struct Machine *, int64_t, size_t);
int FreeVirtual(struct Machine *, int64_t, size_t);

View file

@ -19,6 +19,7 @@
*/
#include "libc/assert.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.h"
#include "libc/mem/mem.h"
#include "libc/str/str.h"
@ -44,41 +45,58 @@ void SetWriteAddr(struct Machine *m, int64_t addr, uint32_t size) {
}
}
long HandlePageFault(struct Machine *m, uint64_t entry, uint64_t table,
unsigned index) {
long page;
if ((page = AllocateLinearPage(m)) != -1) {
--m->memstat.reserved;
*(uint64_t *)(m->real.p + table + index * 8) =
page | entry & ~0x7ffffffffe00;
}
return page;
}
void *FindReal(struct Machine *m, int64_t virt) {
uint8_t *host;
uint64_t real, pte, *pt;
unsigned skew, level, i;
if (!(-0x800000000000 <= virt && virt < 0x800000000000)) {
long page;
uint64_t table, entry;
unsigned skew, level, index, i;
if ((m->mode & 3) != XED_MODE_REAL) {
if (-0x800000000000 <= virt && virt < 0x800000000000) {
skew = virt & 0xfff;
virt &= -0x1000;
for (i = 0; i < ARRAYLEN(m->tlb); ++i) {
if (m->tlb[i].virt == virt && m->tlb[i].host) {
return m->tlb[i].host + skew;
}
}
level = 39;
entry = m->cr3;
do {
table = entry & 0x7ffffffff000;
CHECK_LT(table, m->real.n);
index = (virt >> level) & 511;
entry = *(uint64_t *)(m->real.p + table + index * 8);
if (!(entry & 1)) return NULL;
} while ((level -= 9) >= 12);
if (!(entry & 0x0e00)) {
page = entry & 0x7ffffffff000;
CHECK_LT(page, m->real.n);
} else if ((page = HandlePageFault(m, entry, table, index)) == -1) {
return NULL;
}
m->tlbindex = (m->tlbindex + 1) & (ARRAYLEN(m->tlb) - 1);
m->tlb[m->tlbindex] = m->tlb[0];
m->tlb[0].virt = virt;
m->tlb[0].host = m->real.p + page;
return m->real.p + page + skew;
} else {
return NULL;
}
} else if (0 <= virt && virt + 0xfff < m->real.n) {
return m->real.p + virt;
} else {
return NULL;
}
skew = virt & 0xfff;
virt &= -0x1000;
for (i = 0; i < ARRAYLEN(m->tlb); ++i) {
if (m->tlb[i].virt == virt && m->tlb[i].host) {
return m->tlb[i].host + skew;
}
}
level = 39;
real = m->cr3;
for (;;) {
if (real + 0x1000 > m->real.n) {
return NULL;
}
host = m->real.p + real;
if (level < 12) break;
pt = (uint64_t *)host;
pte = pt[(virt >> level) & 511];
if (!(pte & 1)) {
return NULL;
}
real = pte & 0x00007ffffffff000;
level -= 9;
}
m->tlbindex = (m->tlbindex + 1) & (ARRAYLEN(m->tlb) - 1);
m->tlb[m->tlbindex] = m->tlb[0];
m->tlb[0].host = host;
m->tlb[0].virt = virt;
return host + skew;
}
void *ResolveAddress(struct Machine *m, int64_t v) {

View file

@ -35,7 +35,6 @@
struct Machine *NewMachine(void) {
struct Machine *m;
m = xmemalignzero(alignof(struct Machine), sizeof(struct Machine));
m->mode = XED_MACHINE_MODE_LONG_64;
ResetCpu(m);
ResetMem(m);
return m;
@ -60,11 +59,20 @@ void FreeMachine(struct Machine *m) {
void ResetMem(struct Machine *m) {
FreeMachineRealFree(m);
ResetTlb(m);
memset(&m->memstat, 0, sizeof(m->memstat));
m->real.i = 0;
m->cr3 = AllocateLinearPage(m);
m->cr3 = 0;
}
long AllocateLinearPage(struct Machine *m) {
long page;
if ((page = AllocateLinearPageRaw(m)) != -1) {
memset(m->real.p + page, 0, 0x1000);
}
return page;
}
long AllocateLinearPageRaw(struct Machine *m) {
uint8_t *p;
size_t i, n;
struct MachineRealFree *rf;
@ -79,6 +87,8 @@ long AllocateLinearPage(struct Machine *m) {
m->realfree = rf->next;
free(rf);
}
--m->memstat.freed;
++m->memstat.reclaimed;
} else {
i = m->real.i;
n = m->real.n;
@ -94,6 +104,7 @@ long AllocateLinearPage(struct Machine *m) {
m->real.p = p;
m->real.n = n;
ResetTlb(m);
++m->memstat.resizes;
} else {
return -1;
}
@ -102,8 +113,9 @@ long AllocateLinearPage(struct Machine *m) {
DCHECK_EQ(0, n & 0xfff);
DCHECK_LE(i + 0x1000, n);
m->real.i += 0x1000;
++m->memstat.allocated;
}
memset(m->real.p + i, 0, 0x1000); /* TODO: lazy page clearing */
++m->memstat.committed;
return i;
}
@ -117,24 +129,51 @@ static void MachineWrite64(struct Machine *m, unsigned long i, uint64_t x) {
Write64(m->real.p + i, x);
}
int ReserveVirtual(struct Machine *m, int64_t virt, size_t size) {
int64_t level, pt, ti, mi, end;
for (end = virt + size; virt < end; virt += 0x1000) {
for (pt = m->cr3, level = 39; level >= 12; level -= 9) {
pt = pt & 0x00007ffffffff000;
ti = (virt >> level) & 511;
DEBUGF("reserve %p level %d table %p index %ld", virt, level, pt, ti);
mi = pt + ti * 8;
pt = MachineRead64(m, mi);
if (!(pt & 1)) {
if ((pt = AllocateLinearPage(m)) == -1) return -1;
MachineWrite64(m, mi, pt | 7);
}
int ReserveReal(struct Machine *m, size_t n) {
uint8_t *p;
DCHECK_EQ(0, n & 0xfff);
if (m->real.n < n) {
if ((p = realloc(m->real.p, n))) {
m->real.p = p;
m->real.n = n;
ResetTlb(m);
++m->memstat.resizes;
} else {
return -1;
}
}
return 0;
}
int ReserveVirtual(struct Machine *m, int64_t virt, size_t size, uint64_t key) {
int64_t ti, mi, pt, end, level;
for (end = virt + size;;) {
for (pt = m->cr3, level = 39; level >= 12; level -= 9) {
pt = pt & 0x7ffffffff000;
ti = (virt >> level) & 511;
mi = (pt & 0x7ffffffff000) + ti * 8;
pt = MachineRead64(m, mi);
if (level > 12) {
if (!(pt & 1)) {
if ((pt = AllocateLinearPage(m)) == -1) return -1;
MachineWrite64(m, mi, pt | 7);
++m->memstat.pagetables;
}
continue;
}
for (;;) {
if (!(pt & 1)) {
MachineWrite64(m, mi, key);
++m->memstat.reserved;
}
if ((virt += 0x1000) >= end) return 0;
if (++ti == 512) break;
pt = MachineRead64(m, (mi += 8));
}
}
}
}
int64_t FindVirtual(struct Machine *m, int64_t virt, size_t size) {
uint64_t i, pt, got;
got = 0;
@ -154,30 +193,39 @@ int64_t FindVirtual(struct Machine *m, int64_t virt, size_t size) {
return virt;
}
int FreeVirtual(struct Machine *m, int64_t base, size_t size) {
static void AppendRealFree(struct Machine *m, uint64_t real) {
struct MachineRealFree *rf;
uint64_t i, mi, pt, la, end, virt;
for (virt = base, end = virt + size; virt < end;) {
if (m->realfree && real == m->realfree->i + m->realfree->n) {
m->realfree->n += 0x1000;
} else if ((rf = malloc(sizeof(struct MachineRealFree)))) {
rf->i = real;
rf->n = 0x1000;
rf->next = m->realfree;
m->realfree = rf;
}
}
int FreeVirtual(struct Machine *m, int64_t base, size_t size) {
uint64_t i, mi, pt, end, virt;
for (virt = base, end = virt + size; virt < end; virt += 1ull << i) {
for (pt = m->cr3, i = 39;; i -= 9) {
mi = (pt & 0x7ffffffff000) + ((virt >> i) & 511) * 8;
pt = MachineRead64(m, mi);
if (!(pt & 1)) {
break;
} else if (i == 12) {
MachineWrite64(m, mi, 0);
la = pt & 0x7ffffffff000;
if (m->realfree && la == m->realfree->i + m->realfree->n) {
m->realfree->n += 0x1000;
} else if ((rf = malloc(sizeof(struct MachineRealFree)))) {
rf->i = la;
rf->n = 0x1000;
rf->next = m->realfree;
m->realfree = rf;
++m->memstat.freed;
if (pt & 0x0e00) {
--m->memstat.reserved;
} else {
--m->memstat.committed;
AppendRealFree(m, pt & 0x7ffffffff000);
}
MachineWrite64(m, mi, 0);
break;
}
}
virt += 1ull << i;
}
ResetTlb(m);
return 0;
}

View file

@ -236,6 +236,10 @@ uint8_t *GetModrmRegisterWordPointerWrite(struct Machine *m, uint32_t rde,
}
}
uint8_t *GetModrmRegisterWordPointerWrite2(struct Machine *m, uint32_t rde) {
return GetModrmRegisterWordPointerWrite(m, rde, 2);
}
uint8_t *GetModrmRegisterWordPointerWrite4(struct Machine *m, uint32_t rde) {
return GetModrmRegisterWordPointerWrite(m, rde, 4);
}

View file

@ -59,7 +59,6 @@ extern const uint8_t kByteReg[32];
int64_t ComputeAddress(const struct Machine *, uint32_t);
struct AddrSeg LoadEffectiveAddress(const struct Machine *, uint32_t);
void *ComputeReserveAddressRead(struct Machine *, uint32_t, size_t);
void *ComputeReserveAddressRead1(struct Machine *, uint32_t);
void *ComputeReserveAddressRead4(struct Machine *, uint32_t);
@ -68,7 +67,6 @@ void *ComputeReserveAddressWrite(struct Machine *, uint32_t, size_t);
void *ComputeReserveAddressWrite1(struct Machine *, uint32_t);
void *ComputeReserveAddressWrite4(struct Machine *, uint32_t);
void *ComputeReserveAddressWrite8(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterBytePointerRead(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterBytePointerWrite(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterMmPointerRead(struct Machine *, uint32_t, size_t);
@ -82,6 +80,7 @@ uint8_t *GetModrmRegisterWordPointerRead8(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterWordPointerReadOsz(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterWordPointerReadOszRexw(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterWordPointerWrite(struct Machine *, uint32_t, size_t);
uint8_t *GetModrmRegisterWordPointerWrite2(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterWordPointerWrite4(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterWordPointerWrite8(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterWordPointerWriteOsz(struct Machine *, uint32_t);

160
tool/build/lib/op101.c Normal file
View file

@ -0,0 +1,160 @@
/*-*- 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/endian.h"
#include "tool/build/lib/modrm.h"
#include "tool/build/lib/op101.h"
#include "tool/build/lib/throw.h"
#include "tool/build/lib/time.h"
static void SgdtMs(struct Machine *m, uint32_t rde) {
}
static void LgdtMs(struct Machine *m, uint32_t rde) {
}
static void SidtMs(struct Machine *m, uint32_t rde) {
}
static void LidtMs(struct Machine *m, uint32_t rde) {
}
static void Monitor(struct Machine *m, uint32_t rde) {
}
static void Mwait(struct Machine *m, uint32_t rde) {
}
static void Swapgs(struct Machine *m, uint32_t rde) {
}
static void Vmcall(struct Machine *m, uint32_t rde) {
}
static void Vmlaunch(struct Machine *m, uint32_t rde) {
}
static void Vmresume(struct Machine *m, uint32_t rde) {
}
static void Vmxoff(struct Machine *m, uint32_t rde) {
}
static void InvlpgM(struct Machine *m, uint32_t rde) {
ResetTlb(m);
}
static void Smsw(struct Machine *m, uint32_t rde, bool ismem) {
if (ismem) {
Write16(GetModrmRegisterWordPointerWrite2(m, rde), m->cr0);
} else if (Rexw(rde)) {
Write64(RegRexrReg(m, rde), m->cr0);
} else if (!Osz(rde)) {
Write64(RegRexrReg(m, rde), m->cr0 & 0xffffffff);
} else {
Write16(RegRexrReg(m, rde), m->cr0);
}
}
static void Lmsw(struct Machine *m, uint32_t rde) {
m->cr0 = Read16(GetModrmRegisterWordPointerRead2(m, rde));
}
void Op101(struct Machine *m, uint32_t rde) {
bool ismem;
ismem = !IsModrmRegister(rde);
switch (ModrmReg(rde)) {
case 0:
if (ismem) {
SgdtMs(m, rde);
} else {
switch (ModrmRm(rde)) {
case 1:
Vmcall(m, rde);
break;
case 2:
Vmlaunch(m, rde);
break;
case 3:
Vmresume(m, rde);
break;
case 4:
Vmxoff(m, rde);
break;
default:
OpUd(m, rde);
}
}
break;
case 1:
if (ismem) {
SidtMs(m, rde);
} else {
switch (ModrmRm(rde)) {
case 0:
Monitor(m, rde);
break;
case 1:
Mwait(m, rde);
break;
default:
OpUd(m, rde);
}
}
break;
case 2:
if (ismem) {
LgdtMs(m, rde);
} else {
OpUd(m, rde);
}
break;
case 3:
if (ismem) {
LidtMs(m, rde);
} else {
OpUd(m, rde);
}
break;
case 4:
Smsw(m, rde, ismem);
break;
case 6:
Lmsw(m, rde);
break;
case 7:
if (ismem) {
InvlpgM(m, rde);
} else {
switch (ModrmRm(rde)) {
case 0:
Swapgs(m, rde);
break;
case 1:
OpRdtscp(m, rde);
break;
default:
OpUd(m, rde);
}
}
break;
default:
OpUd(m, rde);
}
}

11
tool/build/lib/op101.h Normal file
View file

@ -0,0 +1,11 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_OP101_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_OP101_H_
#include "tool/build/lib/machine.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
void Op101(struct Machine *, uint32_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_OP101_H_ */

View file

@ -5,10 +5,12 @@
COSMOPOLITAN_C_START_
struct Panel {
int i;
int top, bottom;
int left, right;
int top;
int bottom;
int left;
int right;
struct Buffer *lines;
size_t n;
};
ssize_t PrintPanels(int, long, struct Panel *, long, long);

View file

@ -70,6 +70,7 @@ char *FormatPml4t(struct Machine *m) {
unsigned short i, a[4];
struct Pml4tFormater pp = {0};
unsigned short range[][2] = {{256, 512}, {0, 256}};
if ((m->mode & 3) != XED_MODE_LONG) return strdup("");
pd[0] = GetPt(m, m->cr3);
for (i = 0; i < ARRAYLEN(range); ++i) {
a[0] = range[i][0];

File diff suppressed because it is too large Load diff

View file

@ -2,36 +2,36 @@
#define COSMOPOLITAN_TOOL_BUILD_LIB_PTY_H_
#include "tool/build/lib/buffer.h"
#define kMachinePtyFg 0x0001
#define kMachinePtyBg 0x0002
#define kMachinePtyBold 0x0004
#define kMachinePtyFlip 0x0008
#define kMachinePtyFaint 0x0010
#define kMachinePtyUnder 0x0020
#define kMachinePtyDunder 0x0040
#define kMachinePtyTrue 0x0080
#define kMachinePtyBlink 0x0100
#define kMachinePtyItalic 0x0200
#define kMachinePtyFraktur 0x0400
#define kMachinePtyStrike 0x0800
#define kMachinePtyConceal 0x1000
#define kPtyFg 0x0001
#define kPtyBg 0x0002
#define kPtyBold 0x0004
#define kPtyFlip 0x0008
#define kPtyFaint 0x0010
#define kPtyUnder 0x0020
#define kPtyDunder 0x0040
#define kPtyTrue 0x0080
#define kPtyBlink 0x0100
#define kPtyItalic 0x0200
#define kPtyFraktur 0x0400
#define kPtyStrike 0x0800
#define kPtyConceal 0x1000
#define kMachinePtyBell 0x001
#define kMachinePtyRedzone 0x002
#define kMachinePtyNocursor 0x004
#define kMachinePtyBlinkcursor 0x008
#define kMachinePtyNocanon 0x010
#define kMachinePtyNoecho 0x020
#define kMachinePtyNoopost 0x040
#define kMachinePtyLed1 0x080
#define kMachinePtyLed2 0x100
#define kMachinePtyLed3 0x200
#define kMachinePtyLed4 0x400
#define kPtyBell 0x001
#define kPtyRedzone 0x002
#define kPtyNocursor 0x004
#define kPtyBlinkcursor 0x008
#define kPtyNocanon 0x010
#define kPtyNoecho 0x020
#define kPtyNoopost 0x040
#define kPtyLed1 0x080
#define kPtyLed2 0x100
#define kPtyLed3 0x200
#define kPtyLed4 0x400
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct MachinePty {
struct Pty {
int y;
int x;
int yn;
@ -48,34 +48,34 @@ struct MachinePty {
uint32_t *fgs;
uint32_t *bgs;
wchar_t *xlat;
enum MachinePtyState {
kMachinePtyAscii,
kMachinePtyUtf8,
kMachinePtyEsc,
kMachinePtyCsi,
enum PtyState {
kPtyAscii,
kPtyUtf8,
kPtyEsc,
kPtyCsi,
} state;
struct MachinePtyEsc {
struct PtyEsc {
unsigned i;
char s[64];
} esc;
struct MachinePtyInput {
struct PtyInput {
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);
void MachinePtyFullReset(struct MachinePty *);
void MachinePtyMemmove(struct MachinePty *, long, long, long);
void MachinePtyErase(struct MachinePty *, long, long);
void MachinePtySetY(struct MachinePty *, int);
void MachinePtySetX(struct MachinePty *, int);
void FreePty(struct Pty *);
struct Pty *NewPty(void) nodiscard;
void PtyResize(struct Pty *, int, int);
ssize_t PtyRead(struct Pty *, void *, size_t);
ssize_t PtyWrite(struct Pty *, const void *, size_t);
ssize_t PtyWriteInput(struct Pty *, const void *, size_t);
int PtyAppendLine(struct Pty *, struct Buffer *, unsigned);
void PtyFullReset(struct Pty *);
void PtyMemmove(struct Pty *, long, long, long);
void PtyErase(struct Pty *, long, long);
void PtySetY(struct Pty *, int);
void PtySetX(struct Pty *, int);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -17,6 +17,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/intrin/pmovmskb.h"
#include "libc/str/str.h"
#include "tool/build/lib/address.h"
#include "tool/build/lib/endian.h"
@ -496,23 +497,9 @@ void OpMov0fD6(struct Machine *m, uint32_t rde) {
}
}
static uint8_t pmovmskb(uint64_t x) {
return (x & 0x0000000000000080) >> 007 | (x & 0x0000000000008000) >> 016 |
(x & 0x0000000000800000) >> 025 | (x & 0x0000000080000000) >> 034 |
(x & 0x0000008000000000) >> 043 | (x & 0x0000800000000000) >> 052 |
(x & 0x0080000000000000) >> 061 | (x & 0x8000000000000000) >> 070;
}
void OpPmovmskbGdqpNqUdq(struct Machine *m, uint32_t rde) {
uint64_t bitmask;
if (Osz(rde)) {
bitmask = pmovmskb(Read64(XmmRexbRm(m, rde) + 8)) << 8 |
pmovmskb(Read64(XmmRexbRm(m, rde)));
} else {
bitmask = pmovmskb(Read64(MmRm(m, rde) + 8)) << 8 |
pmovmskb(Read64(MmRm(m, rde)));
}
Write64(RegRexrReg(m, rde), bitmask);
Write64(RegRexrReg(m, rde),
pmovmskb(XmmRexbRm(m, rde)) & (Osz(rde) ? 0xffff : 0xff));
}
void OpMaskMovDiXmmRegXmmRm(struct Machine *m, uint32_t rde) {

View file

@ -19,6 +19,6 @@
*/
#include "tool/build/lib/stats.h"
unsigned long ops;
unsigned long taken;
unsigned long ntaken;
unsigned long opcount;

View file

@ -3,9 +3,9 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
extern unsigned long ops;
extern unsigned long taken;
extern unsigned long ntaken;
extern unsigned long opcount;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -30,6 +30,7 @@
#include "libc/calls/struct/timeval.h"
#include "libc/calls/struct/winsize.h"
#include "libc/errno.h"
#include "libc/fmt/fmt.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.h"
@ -321,11 +322,22 @@ static int XlatMsyncFlags(int x) {
return res;
}
static unsigned XlatOpenMode(unsigned flags) {
switch (flags & 3) {
case 0:
return O_RDONLY;
case 1:
return O_WRONLY;
case 2:
return O_RDWR;
default:
unreachable;
}
}
static unsigned XlatOpenFlags(unsigned flags) {
unsigned res = 0;
if ((flags & 3) == 0) res = O_RDONLY;
if ((flags & 3) == 1) res = O_WRONLY;
if ((flags & 3) == 3) res = O_RDWR;
res = XlatOpenMode(flags);
if (flags & 0x80000) res |= O_CLOEXEC;
if (flags & 0x400) res |= O_APPEND;
if (flags & 0x40) res |= O_CREAT;
@ -355,6 +367,7 @@ static int XlatFcntlArg(int x) {
switch (x) {
XLAT(0, 0);
XLAT(1, FD_CLOEXEC);
XLAT(0x0800, O_NONBLOCK);
default:
return einval();
}
@ -401,6 +414,14 @@ static int XlatRusage(int x) {
}
}
static const char *GetSimulated(void) {
if (IsGenuineCosmo()) {
return " SIMULATED";
} else {
return "";
}
}
static void VirtualSendRead(struct Machine *m, void *dst, int64_t addr,
uint64_t n) {
VirtualSend(m, dst, addr, n);
@ -508,7 +529,7 @@ static int OpMadvise(struct Machine *m, int64_t addr, size_t length,
static int64_t OpBrk(struct Machine *m, int64_t addr) {
addr = ROUNDUP(addr, PAGESIZE);
if (addr > m->brk) {
if (ReserveVirtual(m, m->brk, addr - m->brk) != -1) {
if (ReserveVirtual(m, m->brk, addr - m->brk, 0x0207) != -1) {
m->brk = addr;
}
} else if (addr < m->brk) {
@ -519,34 +540,47 @@ static int64_t OpBrk(struct Machine *m, int64_t addr) {
return m->brk;
}
static int OpMunmap(struct Machine *m, int64_t virt, uint64_t size) {
VERBOSEF("MUNMAP%s %p %,ld", GetSimulated(), virt, size);
return FreeVirtual(m, virt, size);
}
static int64_t OpMmap(struct Machine *m, int64_t virt, size_t size, int prot,
int flags, int fd, int64_t offset) {
void *tmp;
LOGF("MMAP%s %p %,ld %#x %#x %d %#lx", IsGenuineCosmo() ? " SIMULATED" : "",
virt, size, prot, flags, fd, offset);
flags = XlatMapFlags(flags);
if (fd != -1 && (fd = XlatFd(m, fd)) == -1) return -1;
if (!(flags & MAP_FIXED)) {
if (!virt) {
if ((virt = FindVirtual(m, m->brk, size)) == -1) return -1;
m->brk = virt + size;
} else {
if ((virt = FindVirtual(m, virt, size)) == -1) return -1;
uint64_t key;
VERBOSEF("MMAP%s %p %,ld %#x %#x %d %#lx", GetSimulated(), virt, size, prot,
flags, fd, offset);
if (prot & PROT_READ) {
key = 0x0205;
if (prot & PROT_WRITE) key |= 2;
if (!(prot & PROT_EXEC)) key |= 0x8000000000000000;
flags = XlatMapFlags(flags);
if (fd != -1 && (fd = XlatFd(m, fd)) == -1) return -1;
if (!(flags & MAP_FIXED)) {
if (!virt) {
if ((virt = FindVirtual(m, m->brk, size)) == -1) return -1;
m->brk = virt + size;
} else {
if ((virt = FindVirtual(m, virt, size)) == -1) return -1;
}
}
if (ReserveVirtual(m, virt, size, key) != -1) {
if (fd != -1 && !(flags & MAP_ANONYMOUS)) {
/* TODO: lazy file mappings */
CHECK_NOTNULL((tmp = malloc(size)));
CHECK_EQ(size, pread(fd, tmp, size, offset));
VirtualRecvWrite(m, virt, tmp, size);
free(tmp);
}
} else {
FreeVirtual(m, virt, size);
return -1;
}
return virt;
} else {
return FreeVirtual(m, virt, size);
}
if (ReserveVirtual(m, virt, size) == -1) return -1;
if (fd != -1 && !(flags & MAP_ANONYMOUS)) {
/* TODO: lazy page loading */
CHECK_NOTNULL((tmp = malloc(size)));
CHECK_EQ(size, pread(fd, tmp, size, offset));
VirtualRecvWrite(m, virt, tmp, size);
free(tmp);
}
return virt;
}
static int OpMunmap(struct Machine *m, int64_t addr, uint64_t size) {
return FreeVirtual(m, addr, size);
}
static int OpMsync(struct Machine *m, int64_t virt, size_t size, int flags) {
@ -574,18 +608,23 @@ static int OpClose(struct Machine *m, int fd) {
return rc;
}
static int OpOpenat(struct Machine *m, int dirfd, int64_t path, int flags,
static int OpOpenat(struct Machine *m, int dirfd, int64_t pathaddr, int flags,
int mode) {
int fd, i;
const char *path;
flags = XlatOpenFlags(flags);
if ((dirfd = XlatAfd(m, dirfd)) == -1) return -1;
if ((i = MachineFdAdd(&m->fds)) == -1) return -1;
if ((fd = openat(dirfd, LoadStr(m, path), flags, mode)) != -1) {
path = LoadStr(m, pathaddr);
if ((fd = openat(dirfd, path, flags, mode)) != -1) {
m->fds.p[i].cb = &kMachineFdCbHost;
m->fds.p[i].fd = fd;
VERBOSEF("openat(%#x, %`'s, %#x, %#x) → %d [%d]", dirfd, path, flags, mode,
i, fd);
fd = i;
} else {
MachineFdRemove(&m->fds, i);
VERBOSEF("openat(%#x, %`'s, %#x, %#x) failed", dirfd, path, flags, mode);
}
return fd;
}
@ -768,9 +807,13 @@ static ssize_t OpWrite(struct Machine *m, int fd, int64_t addr, size_t size) {
if ((rc = AppendIovsReal(m, &iv, addr, size)) != -1) {
if ((rc = m->fds.p[fd].cb->writev(m->fds.p[fd].fd, iv.p, iv.i)) != -1) {
SetReadAddr(m, addr, rc);
} else {
VERBOSEF("write(%d [%d], %p, %zu) failed: %s", fd, m->fds.p[fd].fd,
addr, size, strerror(errno));
}
}
} else {
VERBOSEF("write(%d, %p, %zu) bad fd", fd, addr, size);
rc = ebadf();
}
FreeIovs(&iv);
@ -1363,7 +1406,7 @@ void OpSyscall(struct Machine *m, uint32_t rde) {
SYSCALL(0x177, vmsplice(di, P(si), dx, r0));
CASE(0xE7, HaltMachine(m, di | 0x100));
default:
LOGF("missing syscall 0x%03x", ax);
VERBOSEF("missing syscall 0x%03x", ax);
ax = enosys();
break;
}

View file

@ -20,6 +20,7 @@
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/nexgen32e/vendor.h"
#include "libc/runtime/gc.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "tool/build/lib/address.h"
@ -34,7 +35,7 @@ static bool IsHaltingInitialized(struct Machine *m) {
void HaltMachine(struct Machine *m, int code) {
CHECK(IsHaltingInitialized(m));
longjmp(m->onhalt, code);
gclongjmp(m->onhalt, code);
}
void ThrowDivideError(struct Machine *m) {

View file

@ -17,19 +17,22 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/log/log.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/calls/calls.h"
#include "libc/log/check.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/ex.h"
#include "libc/sysv/consts/fileno.h"
#include "libc/x/x.h"
#include "tool/build/lib/loader.h"
#include "tool/build/lib/machine.h"
#include "tool/build/lib/memory.h"
#include "tool/build/lib/pty.h"
#include "tool/build/lib/syscall.h"
static void AddHostFd(struct Machine *m, int fd) {
int i = m->fds.i++;
CHECK_NE(-1, (m->fds.p[i].fd = dup(fd)));
m->fds.p[i].cb = &kMachineFdCbHost;
}
int main(int argc, char *argv[]) {
int rc;
struct Elf elf;
@ -42,15 +45,10 @@ int main(int argc, char *argv[]) {
}
m = NewMachine();
LoadProgram(m, argv[1], argv + 2, environ, &elf);
m->fds.i = 3;
m->fds.n = 8;
m->fds.p = xcalloc(m->fds.n, sizeof(struct MachineFd));
m->fds.p[0].fd = STDIN_FILENO;
m->fds.p[0].cb = &kMachineFdCbHost;
m->fds.p[1].fd = STDOUT_FILENO;
m->fds.p[1].cb = &kMachineFdCbHost;
m->fds.p[2].fd = STDERR_FILENO;
m->fds.p[2].cb = &kMachineFdCbHost;
m->fds.p = xcalloc((m->fds.n = 8), sizeof(struct MachineFd));
AddHostFd(m, STDIN_FILENO);
AddHostFd(m, STDOUT_FILENO);
AddHostFd(m, STDERR_FILENO);
if (!(rc = setjmp(m->onhalt))) {
for (;;) {
LoadInstruction(m);

View file

@ -248,7 +248,6 @@ int main(int argc, char *argv[]) {
void *rgb;
size_t size;
unsigned yn, xn;
cancolor();
GetTermSize(&yn, &xn);
yn *= 2;
size = yn * xn * 4;

View file

@ -17,6 +17,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/log/color.h"
#include "libc/log/log.h"
#include "libc/nexgen32e/cpuid4.h"
#include "libc/nexgen32e/nexgen32e.h"
@ -30,9 +31,6 @@
#include "tool/decode/lib/idname.h"
#include "tool/decode/lib/x86idnames.h"
#define RED (cancolor() ? "\x1b[91m" : "")
#define GREEN (cancolor() ? "\x1b[32m" : "")
#define RESET (cancolor() ? "\x1b[0m" : "")
#define CANIUSE(FEATURE) caniuse(#FEATURE, X86_HAVE(FEATURE))
#define SHOW(CONSTANT) show(#CONSTANT, CONSTANT)

View file

@ -1,7 +1,9 @@
#include "dsp/tty/tty.h"
#include "libc/bits/safemacros.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/termios.h"
#include "libc/log/check.h"
#include "libc/log/color.h"
#include "libc/log/log.h"
#include "libc/macros.h"
#include "libc/math.h"
@ -21,10 +23,10 @@
#define WRITE(s) write(STDOUT_FILENO, s, strlen(s))
struct Sphere {
double cx, cy, cz, r;
long double cx, cy, cz, r;
};
const char *kShades[] = {
static const char *kShades[] = {
"\e[48;5;232m ", "\e[48;5;233m ", "\e[48;5;234m ", "\e[48;5;235m ",
"\e[48;5;236m ", "\e[48;5;237m ", "\e[48;5;238m ", "\e[48;5;239m ",
"\e[48;5;240m ", "\e[48;5;241m ", "\e[48;5;242m ", "\e[48;5;243m ",
@ -33,52 +35,53 @@ const char *kShades[] = {
"\e[48;5;252m ", "\e[48;5;253m ", "\e[48;5;254m ", "\e[48;5;255m ",
};
jmp_buf jb_;
double light_[3] = {-50, 0, 50};
struct Sphere pos_ = {11, 11, 11, 11};
struct Sphere neg_ = {1, 1, -4, 11};
static jmp_buf jb_;
static long double light_[3] = {-50, 0, 50};
static struct Sphere pos_ = {11, 11, 11, 11};
static struct Sphere neg_ = {1, 1, -4, 11};
static void OnCtrlC(int sig) {
longjmp(jb_, 1);
}
static void Normalize(double v[3]) {
double len;
len = 1 / sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
static void Normalize(long double v[3]) {
long double len;
len = 1 / sqrtl(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
v[0] *= len;
v[1] *= len;
v[2] *= len;
}
static double Dot(const double x[3], const double y[3]) {
return fabs(x[0] * y[0] + x[1] * y[1] + x[2] * y[2]);
static long double Dot(const long double x[3], const long double y[3]) {
return fabsl(x[0] * y[0] + x[1] * y[1] + x[2] * y[2]);
}
/* check if a ray (x,y, -inf)->(x, y, inf) hits a sphere; if so, return
the intersecting z values. z1 is closer to the eye */
static int HitSphere(struct Sphere *s, double x, double y, double z[2]) {
double zsq;
static int HitSphere(struct Sphere *s, long double x, long double y,
long double z[2]) {
long double zsq;
x -= s->cx;
y -= s->cy;
zsq = s->r * s->r - (x * x + y * y);
if (zsq < 0) {
return 0;
} else {
zsq = sqrt(zsq);
zsq = sqrtl(zsq);
z[0] = s->cz - zsq;
z[1] = s->cz + zsq;
return 1;
}
}
static void DrawSphere(double k, double ambient) {
static void DrawSphere(long double k, long double ambient) {
int i, j, hit_result;
double x, y, vec[3], zb[2], zs[2];
for (i = floor(pos_.cy - pos_.r); i <= ceil(pos_.cy + pos_.r); i++) {
y = i + .5;
for (j = floor(pos_.cx - 2 * pos_.r); j <= ceil(pos_.cx + 2 * pos_.r);
long double x, y, vec[3], zb[2], zs[2];
for (i = floorl(pos_.cy - pos_.r); i <= ceill(pos_.cy + pos_.r); i++) {
y = i + .5L;
for (j = floorl(pos_.cx - 2 * pos_.r); j <= ceill(pos_.cx + 2 * pos_.r);
j++) {
x = .5 * (j - pos_.cx) + .5 + pos_.cx;
x = .5L * (j - pos_.cx) + .5L + pos_.cx;
if (!HitSphere(&pos_, x, y, zb)) {
/* ray lands in blank space, draw bg */
hit_result = 0;
@ -114,10 +117,10 @@ static void DrawSphere(double k, double ambient) {
break;
}
Normalize(vec);
WRITE(
kShades[MIN(ARRAYLEN(kShades) - 1,
MAX(0, lround((1 - (pow(Dot(light_, vec), k) + ambient)) *
(ARRAYLEN(kShades) - 1))))]);
WRITE(kShades[min(
ARRAYLEN(kShades) - 1,
max(0, lroundl((1 - (powl(Dot(light_, vec), k) + ambient)) *
(ARRAYLEN(kShades) - 1))))]);
}
WRITE("\e[0m\n");
}
@ -125,7 +128,7 @@ static void DrawSphere(double k, double ambient) {
}
int main() {
double ang;
long double ang;
struct termios old;
if (cancolor()) {
WRITE("\e[?25l");
@ -134,13 +137,12 @@ int main() {
ang = 0;
for (;;) {
WRITE("\e[H");
light_[1] = cos(ang * 2);
light_[2] = cos(ang);
light_[0] = sin(ang);
light_[1] = cosl(ang * 2);
sincosl(ang, &light_[0], &light_[2]);
Normalize(light_);
ang += .05;
DrawSphere(1.5, .01);
usleep(1. / FRAMERATE * 1e6);
ang += .05L;
DrawSphere(1.5L, .01L);
usleep(1.L / FRAMERATE * 1e6);
}
}
WRITE("\e[0m\e[H\e[J\e[?25h");

View file

@ -590,7 +590,6 @@ int main(int argc, char *argv[]) {
unsigned yd, xd;
__fast_math();
showcrashreports();
cancolor();
GetOpts(argc, argv);
// if sizes are given, 2 cases:
// - positive values: use that as the target size

View file

@ -668,7 +668,6 @@ int main(int argc, char *argv[]) {
break;
}
}
cancolor();
showcrashreports();
for (i = optind; i < argc; ++i) {
WithImageFile(argv[i], scaler);

View file

@ -399,7 +399,6 @@ void WithImageFile(const char *path,
int main(int argc, char *argv[]) {
int i;
cancolor();
GetOpts(&argc, argv);
stbi_set_unpremultiply_on_load(true);
for (i = optind; i < argc; ++i) {

View file

@ -41,7 +41,7 @@ int main(int argc, char *argv[]) {
r = (rgb & 0xff0000) >> 020;
tty = rgb2tty(r, g, b);
printf("\e[48;5;%dm \e[0m %d \\e[48;5;%dm %s #%02x%02x%02x\n", tty.xt,
tty.xt, tty.xt, indexdoublenulstring(kXtermName, tty.xt), r, g, b);
tty.xt, tty.xt, IndexDoubleNulString(kXtermName, tty.xt), r, g, b);
}
return 0;
}

View file

@ -1603,7 +1603,6 @@ int main(int argc, char *argv[]) {
sigaddset(&wut, SIGPIPE);
sigprocmask(SIG_SETMASK, &wut, NULL);
if (!NoDebug()) showcrashreports();
cancolor();
fullclear_ = true;
GetOpts(argc, argv);
if (!tuned_) PickDefaults();
@ -1613,7 +1612,7 @@ int main(int argc, char *argv[]) {
ffplay_ = commandvenv("FFPLAY", "ffplay");
infd_ = STDIN_FILENO;
outfd_ = STDOUT_FILENO;
nullfd_ = open("/dev/null", O_APPEND | O_RDWR | O_NONBLOCK);
nullfd_ = open("/dev/null", O_APPEND | O_RDWR);
if (!setjmp(jb_)) {
xsigaction(SIGINT, OnCtrlC, 0, 0, NULL);
xsigaction(SIGHUP, OnCtrlC, 0, 0, NULL);
@ -1625,11 +1624,11 @@ int main(int argc, char *argv[]) {
__cxa_atexit(OnExit, NULL, NULL);
g_logfile = fopen(logpath_, "a");
if (ischardev(infd_) && ischardev(outfd_)) {
CHECK_NE(-1, fcntl(infd_, F_SETFL, O_NONBLOCK));
/* CHECK_NE(-1, fcntl(infd_, F_SETFL, O_NONBLOCK)); */
} else if (infd_ != outfd_) {
infd_ = -1;
}
CHECK_NE(-1, fcntl(outfd_, F_SETFL, O_NONBLOCK));
/* CHECK_NE(-1, fcntl(outfd_, F_SETFL, O_NONBLOCK)); */
if (CanPlayAudio()) MakeLatencyLittleLessBad();
TryToOpenFrameBuffer();
RenounceSpecialPrivileges();

View file

@ -700,7 +700,7 @@ int main(int argc, char *argv[]) {
for (i = 0; i < 256; ++i) {
printf("\e[48;5;%dm \e[0m \e[38;5;%dm██\e[0m \e[1;48;5;%dm "
"\e[0m \e[1;38;5;%dm██\e[0m %-6hhu%-18s#%02hhx%02hhx%02hhx\n",
i, i, i, i, i, indexdoublenulstring(kXtermName, i), kXtermRgb[i].r,
i, i, i, i, i, IndexDoubleNulString(kXtermName, i), kXtermRgb[i].r,
kXtermRgb[i].g, kXtermRgb[i].b);
}
return 0;