mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-25 07:19:02 +00:00
Add pseudoteletypewriter to emulator
https://justine.storage.googleapis.com/emulator628.mp4
This commit is contained in:
parent
e86cff8ba0
commit
5aabacb361
94 changed files with 3245 additions and 2179 deletions
|
@ -39,7 +39,7 @@ int ttyrestorecursor(int);
|
||||||
int ttyenablealtbuf(int);
|
int ttyenablealtbuf(int);
|
||||||
int ttydisablealtbuf(int);
|
int ttydisablealtbuf(int);
|
||||||
int ttysend(int, const char *);
|
int ttysend(int, const char *);
|
||||||
int ttywrite(int, const void *, size_t);
|
ssize_t ttywrite(int, const void *, size_t);
|
||||||
int ttysendtitle(int, const char *, const struct TtyIdent *);
|
int ttysendtitle(int, const char *, const struct TtyIdent *);
|
||||||
int ttyident(struct TtyIdent *, int, int);
|
int ttyident(struct TtyIdent *, int, int);
|
||||||
void ttyidentclear(struct TtyIdent *);
|
void ttyidentclear(struct TtyIdent *);
|
||||||
|
|
|
@ -101,7 +101,9 @@ static relegated void ttyraw_onsig(int sig, struct siginfo *info,
|
||||||
if (g_ttyraw.sigs[i] == sig) {
|
if (g_ttyraw.sigs[i] == sig) {
|
||||||
if (g_ttyraw.next[i] != SIG_IGN) {
|
if (g_ttyraw.next[i] != SIG_IGN) {
|
||||||
if (g_ttyraw.next[i] != SIG_DFL) {
|
if (g_ttyraw.next[i] != SIG_DFL) {
|
||||||
|
if (g_ttyraw.next[i]) {
|
||||||
g_ttyraw.next[i](sig, info, ctx);
|
g_ttyraw.next[i](sig, info, ctx);
|
||||||
|
}
|
||||||
} else if (sig != SIGCONT) {
|
} else if (sig != SIGCONT) {
|
||||||
_Exit(128 + sig);
|
_Exit(128 + sig);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
*
|
*
|
||||||
* @return 0 on success, or -1 w/ errno
|
* @return 0 on success, or -1 w/ errno
|
||||||
*/
|
*/
|
||||||
int ttywrite(int fd, const void *data, size_t size) {
|
ssize_t ttywrite(int fd, const void *data, size_t size) {
|
||||||
char *p;
|
char *p;
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
size_t wrote, n;
|
size_t wrote, n;
|
||||||
|
|
|
@ -7,11 +7,11 @@
|
||||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||||
╚─────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────*/
|
||||||
#endif
|
#endif
|
||||||
#include "libc/str/str.h"
|
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/fileno.h"
|
#include "libc/sysv/consts/fileno.h"
|
||||||
|
|
||||||
#define kMessage "hello world\r\n"
|
#define kMessage "hello \e[1mworld\e[0m\r\n"
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -18,42 +18,36 @@
|
||||||
│ 02110-1301 USA │
|
│ 02110-1301 USA │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/alg/alg.h"
|
#include "libc/alg/alg.h"
|
||||||
#include "libc/fmt/bing.h"
|
#include "libc/macros.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/nexgen32e/nexgen32e.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
|
|
||||||
#define ALTCOUNT 21
|
static const int kCp437iMultimappings[] = {
|
||||||
|
u'\n' << 8 | '\n', // NEWLINE
|
||||||
static const struct Cp437Multimappings {
|
u'\r' << 8 | '\r', // CARRIAGE RETURN
|
||||||
unsigned char b[ALTCOUNT];
|
u'?' << 8 | '?', // TRIGRAPH
|
||||||
char16_t c[ALTCOUNT];
|
u'\'' << 8 | '\'', // CHARACTER LITERAL
|
||||||
} kCp437iMultimappings = {
|
u'\"' << 8 | '\"', // STRING LITERAL
|
||||||
#define ALT(I, C, B) .c[I] = C, .b[I] = B
|
u'\\' << 8 | '\\', // ESCAPE LITERAL
|
||||||
ALT(0, u'\n', '\n'),
|
u'∅' << 8 | '\0', // EMPTY SET
|
||||||
ALT(1, u'\r', '\r'),
|
u'␀' << 8 | '\0', // SYMBOL FOR NULL [sic]
|
||||||
ALT(2, u'?', '?'), /* TRIGRAPH */
|
0x20A7 << 8 | 0x9E, // PESETA SIGN
|
||||||
ALT(3, u'\'', '\''), /* CHARACTER LITERAL */
|
u'Π' << 8 | 0xE3, // GREEK CAPITAL LETTER PI
|
||||||
ALT(4, u'\"', '\"'), /* STRING LITERAL */
|
u'∏' << 8 | 0xE3, // N-ARY PRODUCT
|
||||||
ALT(5, u'\\', '\\'), /* ESCAPE LITERAL */
|
u'∑' << 8 | 0xE4, // N-ARY SUMMATION
|
||||||
ALT(6, u'∅', '\0'), /* EMPTY SET */
|
u'µ' << 8 | 0xE6, // MICRO SIGN
|
||||||
ALT(7, u'␀', '\0'), /* SYMBOL FOR NULL [sic] */
|
u'Ω' << 8 | 0xEA, // OHM SIGN
|
||||||
ALT(7, 0x20A7, 0x9E), /* PESETA SIGN */
|
u'∂' << 8 | 0xEB, // PARTIAL DIFFERENTIAL
|
||||||
ALT(8, u'Π' /* 03A0: GREEK CAPITAL LETTER PI */, 0xE3),
|
u'ϕ' << 8 | 0xED, // PHI SMALL (CLOSED FORM)
|
||||||
ALT(9, u'∏' /* 220F: N-ARY PRODUCT */, 0xE3),
|
u'ε' << 8 | 0xEE, // LATIN SMALL LETTER EPSILON
|
||||||
ALT(10, u'∑' /* 2211: N-ARY SUMMATION */, 0xE4),
|
u'∊' << 8 | 0xEE, // SMALL ELEMENT OF
|
||||||
ALT(11, u'µ' /* 03BC: MICRO SIGN */, 0xE6),
|
u'∈' << 8 | 0xEE, // ELEMENT-OF SIGN
|
||||||
ALT(12, u'Ω' /* 2126: OHM SIGN */, 0xEA),
|
u'β' << 8 | 0xE1, // GREEK SMALL BETA
|
||||||
ALT(13, u'∂' /* 2202: PARTIAL DIFFERENTIAL */, 0xEB),
|
u'ſ' << 8 | 0xF4, // LATIN SMALL LETTER LONG S
|
||||||
ALT(14, u'ε' /* 03D5: PHI SMALL (CLOSED FORM) */, 0xED),
|
|
||||||
ALT(15, u'ϕ' /* 03D5: PHI SMALL (CLOSED FORM) */, 0xED),
|
|
||||||
ALT(16, u'∈' /* 2208: ELEMENT-OF SIGN */, 0xED),
|
|
||||||
ALT(17, u'∊' /* 220A: SMALL ELEMENT OF */, 0xEE),
|
|
||||||
ALT(18, u'∈' /* 03B5: ELEMENT-OF SIGN */, 0xEE),
|
|
||||||
ALT(19, u'β' /* 03B2: GREEK SMALL BETA */, 0xE1),
|
|
||||||
ALT(20, u'ſ' /* 017F: LATIN SMALL LETTER LONG S */, 0xF4),
|
|
||||||
#undef ALT
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int g_cp437i[256 + ARRAYLEN(kCp437iMultimappings)];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Turns CP437 unicode glyph into its binary representation.
|
* Turns CP437 unicode glyph into its binary representation.
|
||||||
*
|
*
|
||||||
|
@ -62,15 +56,24 @@ static const struct Cp437Multimappings {
|
||||||
* @see bing()
|
* @see bing()
|
||||||
*/
|
*/
|
||||||
int unbing(int c) {
|
int unbing(int c) {
|
||||||
int i;
|
int i, m, l, r;
|
||||||
for (i = 0; i < 256; ++i) {
|
static bool once;
|
||||||
if (c == kCp437[i]) {
|
if (!once) {
|
||||||
return i;
|
for (i = 0; i < 256; ++i) g_cp437i[i] = kCp437[i] << 8 | i;
|
||||||
|
memcpy(g_cp437i + 256, kCp437iMultimappings, sizeof(kCp437iMultimappings));
|
||||||
|
insertionsort(ARRAYLEN(g_cp437i), g_cp437i);
|
||||||
|
once = true;
|
||||||
}
|
}
|
||||||
}
|
l = 0;
|
||||||
for (i = 0; i < ALTCOUNT; ++i) {
|
r = ARRAYLEN(g_cp437i) - 1;
|
||||||
if (c == kCp437iMultimappings.c[i]) {
|
while (l <= r) {
|
||||||
return kCp437iMultimappings.b[i];
|
m = (l + r) >> 1;
|
||||||
|
if ((g_cp437i[m] >> 8) < c) {
|
||||||
|
l = m + 1;
|
||||||
|
} else if ((g_cp437i[m] >> 8) > c) {
|
||||||
|
r = m - 1;
|
||||||
|
} else {
|
||||||
|
return g_cp437i[m] & 0xff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -318,6 +318,15 @@ typedef uint64_t uintmax_t;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef noclone
|
||||||
|
#if !defined(__STRICT_ANSI__) && \
|
||||||
|
(__has_attribute(__noclone__) || __GNUC__ * 100 + __GNUC_MINOR__ >= 405)
|
||||||
|
#define noclone __attribute__((__noclone__))
|
||||||
|
#else
|
||||||
|
#define noclone
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes function behave as much like macro as possible, meaning:
|
* Makes function behave as much like macro as possible, meaning:
|
||||||
*
|
*
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
#define kLogError 1u
|
#define kLogError 1u
|
||||||
#define kLogWarn 2u
|
#define kLogWarn 2u
|
||||||
#define kLogInfo 3u
|
#define kLogInfo 3u
|
||||||
#define kLogDebug 4u
|
#define kLogVerbose 4u
|
||||||
|
#define kLogDebug 5u
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log level for compile-time DCE.
|
* Log level for compile-time DCE.
|
||||||
|
@ -20,7 +21,7 @@
|
||||||
/* #elif IsTiny() */
|
/* #elif IsTiny() */
|
||||||
/* #define LOGGABLELEVEL kLogInfo */
|
/* #define LOGGABLELEVEL kLogInfo */
|
||||||
#else
|
#else
|
||||||
#define LOGGABLELEVEL kLogInfo
|
#define LOGGABLELEVEL kLogVerbose
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -149,6 +150,13 @@ extern unsigned g_loglevel; /* log level for runtime check */
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define VERBOSEF(FMT, ...) \
|
||||||
|
do { \
|
||||||
|
if (LOGGABLE(kLogVerbose)) { \
|
||||||
|
fverbosef(kLogVerbose, __FILE__, __LINE__, NULL, FMT, ##__VA_ARGS__); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define VDEBUGF(FMT, VA) \
|
#define VDEBUGF(FMT, VA) \
|
||||||
do { \
|
do { \
|
||||||
if (LOGGABLE(kLogDebug)) { \
|
if (LOGGABLE(kLogDebug)) { \
|
||||||
|
@ -163,6 +171,13 @@ extern unsigned g_loglevel; /* log level for runtime check */
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define VFVERBOSEF(F, FMT, VA) \
|
||||||
|
do { \
|
||||||
|
if (LOGGABLE(kLogVerbose)) { \
|
||||||
|
vfverbosef(kLogVerbose, __FILE__, __LINE__, F, FMT, VA); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define VFDEBUGF(F, FMT, VA) \
|
#define VFDEBUGF(F, FMT, VA) \
|
||||||
do { \
|
do { \
|
||||||
if (LOGGABLE(kLogDebug)) { \
|
if (LOGGABLE(kLogDebug)) { \
|
||||||
|
@ -203,6 +218,8 @@ void __logerrno(const char *, int, const char *) relegated;
|
||||||
#define ATTRV paramsnonnull((5, 6))
|
#define ATTRV paramsnonnull((5, 6))
|
||||||
void flogf(ARGS, ...) ATTR libcesque;
|
void flogf(ARGS, ...) ATTR libcesque;
|
||||||
void vflogf(ARGS, va_list) ATTRV libcesque;
|
void vflogf(ARGS, va_list) ATTRV libcesque;
|
||||||
|
void fverbosef(ARGS, ...) asm("flogf") ATTR relegated libcesque;
|
||||||
|
void vfverbosef(ARGS, va_list) asm("vflogf") ATTRV relegated libcesque;
|
||||||
void fdebugf(ARGS, ...) asm("flogf") ATTR relegated libcesque;
|
void fdebugf(ARGS, ...) asm("flogf") ATTR relegated libcesque;
|
||||||
void vfdebugf(ARGS, va_list) asm("vflogf") ATTRV relegated libcesque;
|
void vfdebugf(ARGS, va_list) asm("vflogf") ATTRV relegated libcesque;
|
||||||
void ffatalf(ARGS, ...) asm("flogf") ATTR relegated noreturn libcesque;
|
void ffatalf(ARGS, ...) asm("flogf") ATTR relegated noreturn libcesque;
|
||||||
|
|
|
@ -76,7 +76,6 @@ void vflogf_onfail(FILE *f) {
|
||||||
void(vflogf)(unsigned level, const char *file, int line, FILE *f,
|
void(vflogf)(unsigned level, const char *file, int line, FILE *f,
|
||||||
const char *fmt, va_list va) {
|
const char *fmt, va_list va) {
|
||||||
static struct timespec ts;
|
static struct timespec ts;
|
||||||
bool flush;
|
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
long double t2;
|
long double t2;
|
||||||
const char *prog;
|
const char *prog;
|
||||||
|
@ -95,12 +94,10 @@ void(vflogf)(unsigned level, const char *file, int line, FILE *f,
|
||||||
timebufp = timebuf;
|
timebufp = timebuf;
|
||||||
zonebufp = zonebuf;
|
zonebufp = zonebuf;
|
||||||
dots = nsec;
|
dots = nsec;
|
||||||
flush = true;
|
|
||||||
} else {
|
} else {
|
||||||
timebufp = "---------------";
|
timebufp = "---------------";
|
||||||
zonebufp = "---";
|
zonebufp = "---";
|
||||||
dots = nsec - ts.tv_nsec;
|
dots = nsec - ts.tv_nsec;
|
||||||
flush = true;
|
|
||||||
}
|
}
|
||||||
ts.tv_sec = secs;
|
ts.tv_sec = secs;
|
||||||
ts.tv_nsec = nsec;
|
ts.tv_nsec = nsec;
|
||||||
|
@ -113,7 +110,6 @@ void(vflogf)(unsigned level, const char *file, int line, FILE *f,
|
||||||
(vfprintf)(f, fmt, va);
|
(vfprintf)(f, fmt, va);
|
||||||
va_end(va);
|
va_end(va);
|
||||||
fputc('\n', f);
|
fputc('\n', f);
|
||||||
if (flush) fflush(f);
|
|
||||||
if (level == kLogFatal) {
|
if (level == kLogFatal) {
|
||||||
startfatal(file, line);
|
startfatal(file, line);
|
||||||
fprintf(stderr, "fatal error see logfile\n");
|
fprintf(stderr, "fatal error see logfile\n");
|
||||||
|
|
24
libc/nexgen32e/bsf.c
Normal file
24
libc/nexgen32e/bsf.c
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/*-*- 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/nexgen32e/bsf.h"
|
||||||
|
|
||||||
|
int(bsf)(int x) {
|
||||||
|
return bsf(x);
|
||||||
|
}
|
|
@ -17,12 +17,15 @@ COSMOPOLITAN_C_START_
|
||||||
* 0xffffffff 0 0 1 31 0
|
* 0xffffffff 0 0 1 31 0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
int bsf(int);
|
||||||
|
int bsfl(long);
|
||||||
|
int bsfll(long long);
|
||||||
|
int bsfmax(uintmax_t);
|
||||||
|
|
||||||
#define bsf(u) __builtin_ctz(u)
|
#define bsf(u) __builtin_ctz(u)
|
||||||
#define bsfl(u) __builtin_ctzl(u)
|
#define bsfl(u) __builtin_ctzl(u)
|
||||||
#define bsfll(u) __builtin_ctzll(u)
|
#define bsfll(u) __builtin_ctzll(u)
|
||||||
|
|
||||||
unsigned bsfmax(uintmax_t);
|
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
#endif /* COSMOPOLITAN_LIBC_NEXGEN32E_BSF_H_ */
|
#endif /* COSMOPOLITAN_LIBC_NEXGEN32E_BSF_H_ */
|
||||||
|
|
24
libc/nexgen32e/bsfl.c
Normal file
24
libc/nexgen32e/bsfl.c
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/*-*- 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/nexgen32e/bsf.h"
|
||||||
|
|
||||||
|
int(bsfl)(long x) {
|
||||||
|
return bsfl(x);
|
||||||
|
}
|
24
libc/nexgen32e/bsfll.c
Normal file
24
libc/nexgen32e/bsfll.c
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/*-*- 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/nexgen32e/bsf.h"
|
||||||
|
|
||||||
|
int(bsfll)(long long x) {
|
||||||
|
return bsfll(x);
|
||||||
|
}
|
24
libc/nexgen32e/bsr.c
Normal file
24
libc/nexgen32e/bsr.c
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/*-*- 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/nexgen32e/bsr.h"
|
||||||
|
|
||||||
|
int(bsr)(int x) {
|
||||||
|
return bsr(x);
|
||||||
|
}
|
|
@ -17,11 +17,14 @@ COSMOPOLITAN_C_START_
|
||||||
* 0xffffffff 0 0 1 31 0
|
* 0xffffffff 0 0 1 31 0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define bsr(u) ((sizeof(unsigned) * 8 - 1) ^ __builtin_clz(u))
|
int bsr(int);
|
||||||
#define bsrl(u) ((sizeof(unsigned long) * 8 - 1) ^ __builtin_clzl(u))
|
int bsrl(long);
|
||||||
#define bsrll(u) ((sizeof(unsigned long long) * 8 - 1) ^ __builtin_clzll(u))
|
int bsrll(long long);
|
||||||
|
int bsrmax(uintmax_t);
|
||||||
|
|
||||||
unsigned bsrmax(uintmax_t);
|
#define bsr(u) ((sizeof(int) * 8 - 1) ^ __builtin_clz(u))
|
||||||
|
#define bsrl(u) ((sizeof(long) * 8 - 1) ^ __builtin_clzl(u))
|
||||||
|
#define bsrll(u) ((sizeof(long long) * 8 - 1) ^ __builtin_clzll(u))
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
24
libc/nexgen32e/bsrl.c
Normal file
24
libc/nexgen32e/bsrl.c
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/*-*- 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/nexgen32e/bsr.h"
|
||||||
|
|
||||||
|
int(bsrl)(long x) {
|
||||||
|
return bsrl(x);
|
||||||
|
}
|
24
libc/nexgen32e/bsrll.c
Normal file
24
libc/nexgen32e/bsrll.c
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/*-*- 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/nexgen32e/bsr.h"
|
||||||
|
|
||||||
|
int(bsrll)(long long x) {
|
||||||
|
return bsrll(x);
|
||||||
|
}
|
|
@ -24,9 +24,9 @@
|
||||||
void djbsort$avx2(int32_t *, long);
|
void djbsort$avx2(int32_t *, long);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* D.J. Bernstein's fast integer sorting algorithm.
|
* D.J. Bernstein's outrageously fast integer sorting algorithm.
|
||||||
*/
|
*/
|
||||||
void djbsort(size_t n, int32_t *a) {
|
void djbsort(size_t n, int32_t a[n]) {
|
||||||
if (X86_HAVE(AVX2)) {
|
if (X86_HAVE(AVX2)) {
|
||||||
djbsort$avx2(a, n);
|
djbsort$avx2(a, n);
|
||||||
} else {
|
} else {
|
|
@ -49,11 +49,11 @@ CollectGarbage:
|
||||||
sub $0x20,%rsp
|
sub $0x20,%rsp
|
||||||
push %rax
|
push %rax
|
||||||
push %rdx
|
push %rdx
|
||||||
movaps %xmm0,-0x20(%rbp)
|
movdqa %xmm0,-0x20(%rbp)
|
||||||
movaps %xmm1,-0x10(%rbp)
|
movdqa %xmm1,-0x10(%rbp)
|
||||||
call *%r9
|
call *%r9
|
||||||
movaps -0x10(%rbp),%xmm1
|
movdqa -0x10(%rbp),%xmm1
|
||||||
movaps -0x20(%rbp),%xmm0
|
movdqa -0x20(%rbp),%xmm0
|
||||||
pop %rdx
|
pop %rdx
|
||||||
pop %rax
|
pop %rax
|
||||||
leave
|
leave
|
||||||
|
|
|
@ -70,7 +70,7 @@ kCpuids:.long 0,0,0,0 # EAX=0 (Basic Processor Info)
|
||||||
add $4*4,%rdi
|
add $4*4,%rdi
|
||||||
jmp 2b
|
jmp 2b
|
||||||
3: nop
|
3: nop
|
||||||
#if 0 && !X86_NEED(AVX2)
|
#if !X86_NEED(AVX2)
|
||||||
testb X86_HAVE(AVX)(%r8)
|
testb X86_HAVE(AVX)(%r8)
|
||||||
jz 5f
|
jz 5f
|
||||||
testb X86_HAVE(OSXSAVE)(%r8)
|
testb X86_HAVE(OSXSAVE)(%r8)
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
#define X86_AES 1H, ECX, 25, _X86_CC_AES, _ /* westmere c. 2010 */
|
#define X86_AES 1H, ECX, 25, _X86_CC_AES, _ /* westmere c. 2010 */
|
||||||
#define X86_APIC 1H, EDX, 9, 0, _
|
#define X86_APIC 1H, EDX, 9, 0, _
|
||||||
#define X86_ARCH_CAPABILITIES 7H, EDX, 29, 0, _
|
#define X86_ARCH_CAPABILITIES 7H, EDX, 29, 0, _
|
||||||
#define X86_AVX 1H, ECX, 28, _X86_CC_AVX, AVX /* sandybridge c. 2012 */
|
#define X86_AVX 1H, ECX, 28, _X86_CC_AVX, _ /* sandybridge c. 2012 */
|
||||||
#define X86_AVX2 7H, EBX, 5, _X86_CC_AVX2, AVX /* haswell c. 2013 */
|
#define X86_AVX2 7H, EBX, 5, _X86_CC_AVX2, _ /* haswell c. 2013 */
|
||||||
#define X86_AVX512BW 7H, EBX, 30, 0, _
|
#define X86_AVX512BW 7H, EBX, 30, 0, _
|
||||||
#define X86_AVX512CD 7H, EBX, 28, 0, _
|
#define X86_AVX512CD 7H, EBX, 28, 0, _
|
||||||
#define X86_AVX512DQ 7H, EBX, 17, 0, _
|
#define X86_AVX512DQ 7H, EBX, 17, 0, _
|
||||||
|
@ -246,17 +246,5 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define _X86_HOOK__(X) X
|
#define _X86_HOOK__(X) X
|
||||||
#define _X86_HOOK_AVX(X) \
|
|
||||||
({ \
|
|
||||||
YOINK(_init_enableavx); \
|
|
||||||
X; \
|
|
||||||
})
|
|
||||||
|
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
|
||||||
COSMOPOLITAN_C_START_
|
|
||||||
|
|
||||||
int _init_enableavx(void) pureconst;
|
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
|
||||||
#endif /* COSMOPOLITAN_LIBC_NEXGEN32E_X86FEATURE_H_ */
|
#endif /* COSMOPOLITAN_LIBC_NEXGEN32E_X86FEATURE_H_ */
|
||||||
|
|
|
@ -23,6 +23,11 @@
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
/ Calls global initialization functions.
|
/ Calls global initialization functions.
|
||||||
|
/
|
||||||
|
/ @param r12 is argc
|
||||||
|
/ @param r13 is argv
|
||||||
|
/ @param r14 is environ
|
||||||
|
/ @param r15 is auxv
|
||||||
_construct:
|
_construct:
|
||||||
push %rbp
|
push %rbp
|
||||||
mov %rsp,%rbp
|
mov %rsp,%rbp
|
||||||
|
|
|
@ -43,8 +43,8 @@ static struct CxaAtexitBlocks {
|
||||||
*
|
*
|
||||||
* Destructors are called in reverse order. They won't be called if the
|
* Destructors are called in reverse order. They won't be called if the
|
||||||
* program aborts or _exit() is called. Invocations of this function are
|
* program aborts or _exit() is called. Invocations of this function are
|
||||||
* usually generated by the C++ compiler. Behavior is limitless if you
|
* usually generated by the C++ compiler. Behavior is limitless if some
|
||||||
* choose to link calloc() and free().
|
* other module has linked calloc().
|
||||||
*
|
*
|
||||||
* @param fp is void(*)(T)
|
* @param fp is void(*)(T)
|
||||||
* @param arg is passed to callback
|
* @param arg is passed to callback
|
||||||
|
@ -78,8 +78,11 @@ int __cxa_atexit(void *fp, void *arg, void *pred) {
|
||||||
/**
|
/**
|
||||||
* Triggers global destructors.
|
* Triggers global destructors.
|
||||||
*
|
*
|
||||||
|
* They're called in LIFO order. If a destructor adds more destructors,
|
||||||
|
* then those destructors will be called immediately following, before
|
||||||
|
* iteration continues.
|
||||||
|
*
|
||||||
* @param pred can be null to match all
|
* @param pred can be null to match all
|
||||||
* @note reentrant emptor
|
|
||||||
*/
|
*/
|
||||||
void __cxa_finalize(void *pred) {
|
void __cxa_finalize(void *pred) {
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
|
@ -129,7 +129,7 @@ void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) {
|
||||||
if (!CANONICAL(addr)) return VIP(einval());
|
if (!CANONICAL(addr)) return VIP(einval());
|
||||||
if (!(!!(flags & MAP_ANONYMOUS) ^ (fd != -1))) return VIP(einval());
|
if (!(!!(flags & MAP_ANONYMOUS) ^ (fd != -1))) return VIP(einval());
|
||||||
if (!(!!(flags & MAP_PRIVATE) ^ !!(flags & MAP_SHARED))) return VIP(einval());
|
if (!(!!(flags & MAP_PRIVATE) ^ !!(flags & MAP_SHARED))) return VIP(einval());
|
||||||
if (!(IsWindows() && fd != -1)) size = ROUNDUP(size, FRAMESIZE);
|
if (fd != -1) size = ROUNDUP(size, FRAMESIZE);
|
||||||
if (flags & MAP_FIXED) {
|
if (flags & MAP_FIXED) {
|
||||||
if (UntrackMemoryIntervals(addr, size) == -1) {
|
if (UntrackMemoryIntervals(addr, size) == -1) {
|
||||||
return MAP_FAILED;
|
return MAP_FAILED;
|
||||||
|
|
|
@ -37,6 +37,7 @@ LIBC_RUNTIME_A_DIRECTDEPS = \
|
||||||
LIBC_BITS \
|
LIBC_BITS \
|
||||||
LIBC_CALLS \
|
LIBC_CALLS \
|
||||||
LIBC_CONV \
|
LIBC_CONV \
|
||||||
|
LIBC_TINYMATH \
|
||||||
LIBC_ELF \
|
LIBC_ELF \
|
||||||
LIBC_FMT \
|
LIBC_FMT \
|
||||||
LIBC_NEXGEN32E \
|
LIBC_NEXGEN32E \
|
||||||
|
|
|
@ -22,6 +22,11 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
|
|
||||||
/ Self-bootstraps process upon existence before calling main.
|
/ Self-bootstraps process upon existence before calling main.
|
||||||
|
/
|
||||||
|
/ @param r12 is argc
|
||||||
|
/ @param r13 is argv
|
||||||
|
/ @param r14 is environ
|
||||||
|
/ @param r15 is auxv
|
||||||
_spawn: push %rbp
|
_spawn: push %rbp
|
||||||
mov %rsp,%rbp
|
mov %rsp,%rbp
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,7 @@ void *isnotplaintext(const void *, size_t) nothrow nocallback nosideeffect;
|
||||||
└──────────────3 Continuations follow */
|
└──────────────3 Continuations follow */
|
||||||
|
|
||||||
#define INVALID_CODEPOINT 0xfffd
|
#define INVALID_CODEPOINT 0xfffd
|
||||||
|
|
||||||
#define UTF16_MASK 0b1111110000000000
|
#define UTF16_MASK 0b1111110000000000
|
||||||
#define UTF16_MOAR 0b1101100000000000 /* 0xD800..0xDBFF */
|
#define UTF16_MOAR 0b1101100000000000 /* 0xD800..0xDBFF */
|
||||||
#define UTF16_CONT 0b1101110000000000 /* 0xDC00..0xDBFF */
|
#define UTF16_CONT 0b1101110000000000 /* 0xDC00..0xDBFF */
|
||||||
|
|
8
libc/str/thompike.h
Normal file
8
libc/str/thompike.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef COSMOPOLITAN_LIBC_STR_THOMPIKE_H_
|
||||||
|
#define COSMOPOLITAN_LIBC_STR_THOMPIKE_H_
|
||||||
|
#include "libc/nexgen32e/bsr.h"
|
||||||
|
|
||||||
|
#define ThomPikeCont(x) ((x & 0b11000000) == 0b10000000)
|
||||||
|
#define ThomPikeByte(x) (x & (((1 << (x < 252 ? bsr(~x & 0xff) : 1)) - 1) | 3))
|
||||||
|
|
||||||
|
#endif /* COSMOPOLITAN_LIBC_STR_THOMPIKE_H_ */
|
|
@ -2611,7 +2611,7 @@ syscon ioctl FIONREAD 0x541b 0x4004667f 0x4004667f 0x4004667f 0x4004667f
|
||||||
#syscon ioctl FIONWRITE 0x0 0x0 0x40046677 0x0 -1 # [FreeBSD Generalization] bytes queued in FD's output buffer (same as TIOCOUTQ for TTY FDs; see also SO_SNDBUF)
|
#syscon ioctl FIONWRITE 0x0 0x0 0x40046677 0x0 -1 # [FreeBSD Generalization] bytes queued in FD's output buffer (same as TIOCOUTQ for TTY FDs; see also SO_SNDBUF)
|
||||||
#syscon ioctl FIONSPACE 0x0 0x0 0x40046676 0x0 -1 # [FreeBSD Generalization] capacity of FD's output buffer, e.g. equivalent to TIOCGSERIAL w/ UART
|
#syscon ioctl FIONSPACE 0x0 0x0 0x40046676 0x0 -1 # [FreeBSD Generalization] capacity of FD's output buffer, e.g. equivalent to TIOCGSERIAL w/ UART
|
||||||
syscon ioctl TIOCINQ 0x541b 0x4004667f 0x4004667f 0x4004667f 0x4004667f # [Linuxism] same as FIONREAD
|
syscon ioctl TIOCINQ 0x541b 0x4004667f 0x4004667f 0x4004667f 0x4004667f # [Linuxism] same as FIONREAD
|
||||||
syscon ioctl TIOCOUTQ 0x5411 0x40047473 0x40047473 0x40047473 -1 # bytes queued in TTY's output buffer
|
#syscon ioctl TIOCOUTQ 0x5411 0x40047473 0x40047473 0x40047473 -1 # bytes queued in TTY's output buffer
|
||||||
|
|
||||||
syscon misc FANOTIFY_METADATA_VERSION 3 0 0 0 0
|
syscon misc FANOTIFY_METADATA_VERSION 3 0 0 0 0
|
||||||
syscon misc FAPPEND 0x0400 8 8 8 0 # bsd consensus
|
syscon misc FAPPEND 0x0400 8 8 8 0 # bsd consensus
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
__fpclassify:
|
tinymath_fpclassify:
|
||||||
.leafprologue
|
.leafprologue
|
||||||
movd %xmm0,%rax
|
movd %xmm0,%rax
|
||||||
movd %xmm0,%rdx
|
movd %xmm0,%rdx
|
||||||
|
@ -41,4 +41,5 @@ __fpclassify:
|
||||||
sal $12,%rdx
|
sal $12,%rdx
|
||||||
sete %al
|
sete %al
|
||||||
1: .leafepilogue
|
1: .leafepilogue
|
||||||
.endfn __fpclassify,globl
|
.endfn tinymath_fpclassify,globl
|
||||||
|
.alias tinymath_fpclassify,__fpclassify
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
__fpclassifyf:
|
tinymath_fpclassifyf:
|
||||||
.leafprologue
|
.leafprologue
|
||||||
movd %xmm0,%edx
|
movd %xmm0,%edx
|
||||||
movd %xmm0,%eax
|
movd %xmm0,%eax
|
||||||
|
@ -42,4 +42,5 @@ __fpclassifyf:
|
||||||
sete %al
|
sete %al
|
||||||
movzbl %al,%eax
|
movzbl %al,%eax
|
||||||
1: .leafepilogue
|
1: .leafepilogue
|
||||||
.endfn __fpclassifyf,globl
|
.endfn tinymath_fpclassifyf,globl
|
||||||
|
.alias tinymath_fpclassifyf,__fpclassifyf
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
__fpclassifyl:
|
tinymath_fpclassifyl:
|
||||||
push %rbp
|
push %rbp
|
||||||
mov %rsp,%rbp
|
mov %rsp,%rbp
|
||||||
mov 24(%rbp),%rax
|
mov 24(%rbp),%rax
|
||||||
|
@ -50,4 +50,5 @@ __fpclassifyl:
|
||||||
and $FP_NORMAL,%eax
|
and $FP_NORMAL,%eax
|
||||||
1: pop %rbp
|
1: pop %rbp
|
||||||
ret
|
ret
|
||||||
.endfn __fpclassifyl,globl
|
.endfn tinymath_fpclassifyl,globl
|
||||||
|
.alias tinymath_fpclassifyl,__fpclassifyl
|
||||||
|
|
|
@ -20,6 +20,10 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
|
/ Returns 𝑥 × 2ʸ.
|
||||||
|
/
|
||||||
|
/ @param 𝑥 is double passed in %xmm0
|
||||||
|
/ @param 𝑦 is exponent via %edi
|
||||||
tinymath_scalbn:
|
tinymath_scalbn:
|
||||||
push %rbp
|
push %rbp
|
||||||
mov %rsp,%rbp
|
mov %rsp,%rbp
|
||||||
|
|
|
@ -20,6 +20,10 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
|
/ Returns 𝑥 × 2ʸ.
|
||||||
|
/
|
||||||
|
/ @param 𝑥 is float passed in %xmm0
|
||||||
|
/ @param 𝑦 is exponent via %edi
|
||||||
tinymath_scalbnf:
|
tinymath_scalbnf:
|
||||||
push %rbp
|
push %rbp
|
||||||
mov %rsp,%rbp
|
mov %rsp,%rbp
|
||||||
|
|
|
@ -20,11 +20,10 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
/ Returns 𝑥 × 𝑟ʸ where 𝑟 is radix of hardware architecture.
|
/ Returns 𝑥 × 2ʸ.
|
||||||
/
|
/
|
||||||
/ @param 𝑥 is long double passed on stack
|
/ @param 𝑥 is long double passed on stack
|
||||||
/ @param 𝑦 is exponent via %edi
|
/ @param 𝑦 is exponent via %edi
|
||||||
/ @see FLT_RADIX
|
|
||||||
tinymath_scalbnl:
|
tinymath_scalbnl:
|
||||||
push %rbp
|
push %rbp
|
||||||
mov %rsp,%rbp
|
mov %rsp,%rbp
|
||||||
|
|
|
@ -19,12 +19,14 @@ TEST_LIBC_FMT_CHECKS = \
|
||||||
$(TEST_LIBC_FMT_SRCS_TEST:%.c=o/$(MODE)/%.com.runs)
|
$(TEST_LIBC_FMT_SRCS_TEST:%.c=o/$(MODE)/%.com.runs)
|
||||||
|
|
||||||
TEST_LIBC_FMT_DIRECTDEPS = \
|
TEST_LIBC_FMT_DIRECTDEPS = \
|
||||||
|
LIBC_ALG \
|
||||||
LIBC_CALLS_HEFTY \
|
LIBC_CALLS_HEFTY \
|
||||||
LIBC_CONV \
|
LIBC_CONV \
|
||||||
LIBC_FMT \
|
LIBC_FMT \
|
||||||
LIBC_MEM \
|
LIBC_MEM \
|
||||||
LIBC_NEXGEN32E \
|
LIBC_NEXGEN32E \
|
||||||
LIBC_RUNTIME \
|
LIBC_RUNTIME \
|
||||||
|
LIBC_STDIO \
|
||||||
LIBC_STR \
|
LIBC_STR \
|
||||||
LIBC_STUBS \
|
LIBC_STUBS \
|
||||||
LIBC_SYSV \
|
LIBC_SYSV \
|
||||||
|
|
|
@ -355,14 +355,14 @@ TEST(punpckhwd, test) {
|
||||||
uint16_t b[8] = {9, 10, 11, 12, 13, 14, 15, 16};
|
uint16_t b[8] = {9, 10, 11, 12, 13, 14, 15, 16};
|
||||||
uint16_t c[8];
|
uint16_t c[8];
|
||||||
punpckhwd(c, a, b);
|
punpckhwd(c, a, b);
|
||||||
ASSERT_EQ(5, c[0]);
|
EXPECT_EQ(5, c[0]);
|
||||||
ASSERT_EQ(13, c[1]);
|
EXPECT_EQ(13, c[1]);
|
||||||
ASSERT_EQ(6, c[2]);
|
EXPECT_EQ(6, c[2]);
|
||||||
ASSERT_EQ(14, c[3]);
|
EXPECT_EQ(14, c[3]);
|
||||||
ASSERT_EQ(7, c[4]);
|
EXPECT_EQ(7, c[4]);
|
||||||
ASSERT_EQ(15, c[5]);
|
EXPECT_EQ(15, c[5]);
|
||||||
ASSERT_EQ(8, c[6]);
|
EXPECT_EQ(8, c[6]);
|
||||||
ASSERT_EQ(16, c[7]);
|
EXPECT_EQ(16, c[7]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(punpckhwd, pure) {
|
TEST(punpckhwd, pure) {
|
||||||
|
@ -370,70 +370,70 @@ TEST(punpckhwd, pure) {
|
||||||
uint16_t b[8] = {9, 10, 11, 12, 13, 14, 15, 16};
|
uint16_t b[8] = {9, 10, 11, 12, 13, 14, 15, 16};
|
||||||
uint16_t c[8];
|
uint16_t c[8];
|
||||||
punpckhwd(c, a, b);
|
punpckhwd(c, a, b);
|
||||||
ASSERT_EQ(5, c[0]);
|
EXPECT_EQ(5, c[0]);
|
||||||
ASSERT_EQ(13, c[1]);
|
EXPECT_EQ(13, c[1]);
|
||||||
ASSERT_EQ(6, c[2]);
|
EXPECT_EQ(6, c[2]);
|
||||||
ASSERT_EQ(14, c[3]);
|
EXPECT_EQ(14, c[3]);
|
||||||
ASSERT_EQ(7, c[4]);
|
EXPECT_EQ(7, c[4]);
|
||||||
ASSERT_EQ(15, c[5]);
|
EXPECT_EQ(15, c[5]);
|
||||||
ASSERT_EQ(8, c[6]);
|
EXPECT_EQ(8, c[6]);
|
||||||
ASSERT_EQ(16, c[7]);
|
EXPECT_EQ(16, c[7]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(punpckhwd, testAlias) {
|
TEST(punpckhwd, testAlias) {
|
||||||
uint16_t a[8] = {1, 02, 03, 04, 05, 06, 07, 8};
|
uint16_t a[8] = {1, 02, 03, 04, 05, 06, 07, 8};
|
||||||
uint16_t b[8] = {9, 10, 11, 12, 13, 14, 15, 16};
|
uint16_t b[8] = {9, 10, 11, 12, 13, 14, 15, 16};
|
||||||
punpckhwd(a, a, b);
|
punpckhwd(a, a, b);
|
||||||
ASSERT_EQ(5, a[0]);
|
EXPECT_EQ(5, a[0]);
|
||||||
ASSERT_EQ(13, a[1]);
|
EXPECT_EQ(13, a[1]);
|
||||||
ASSERT_EQ(6, a[2]);
|
EXPECT_EQ(6, a[2]);
|
||||||
ASSERT_EQ(14, a[3]);
|
EXPECT_EQ(14, a[3]);
|
||||||
ASSERT_EQ(7, a[4]);
|
EXPECT_EQ(7, a[4]);
|
||||||
ASSERT_EQ(15, a[5]);
|
EXPECT_EQ(15, a[5]);
|
||||||
ASSERT_EQ(8, a[6]);
|
EXPECT_EQ(8, a[6]);
|
||||||
ASSERT_EQ(16, a[7]);
|
EXPECT_EQ(16, a[7]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(punpckhwd, pureAlias) {
|
TEST(punpckhwd, pureAlias) {
|
||||||
uint16_t a[8] = {1, 02, 03, 04, 05, 06, 07, 8};
|
uint16_t a[8] = {1, 02, 03, 04, 05, 06, 07, 8};
|
||||||
uint16_t b[8] = {9, 10, 11, 12, 13, 14, 15, 16};
|
uint16_t b[8] = {9, 10, 11, 12, 13, 14, 15, 16};
|
||||||
(punpckhwd)(a, a, b);
|
(punpckhwd)(a, a, b);
|
||||||
ASSERT_EQ(5, a[0]);
|
EXPECT_EQ(5, a[0]);
|
||||||
ASSERT_EQ(13, a[1]);
|
EXPECT_EQ(13, a[1]);
|
||||||
ASSERT_EQ(6, a[2]);
|
EXPECT_EQ(6, a[2]);
|
||||||
ASSERT_EQ(14, a[3]);
|
EXPECT_EQ(14, a[3]);
|
||||||
ASSERT_EQ(7, a[4]);
|
EXPECT_EQ(7, a[4]);
|
||||||
ASSERT_EQ(15, a[5]);
|
EXPECT_EQ(15, a[5]);
|
||||||
ASSERT_EQ(8, a[6]);
|
EXPECT_EQ(8, a[6]);
|
||||||
ASSERT_EQ(16, a[7]);
|
EXPECT_EQ(16, a[7]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(punpckhwd, testAlias2) {
|
TEST(punpckhwd, testAlias2) {
|
||||||
uint16_t a[8] = {1, 02, 03, 04, 05, 06, 07, 8};
|
uint16_t a[8] = {1, 02, 03, 04, 05, 06, 07, 8};
|
||||||
uint16_t b[8] = {9, 10, 11, 12, 13, 14, 15, 16};
|
uint16_t b[8] = {9, 10, 11, 12, 13, 14, 15, 16};
|
||||||
punpckhwd(b, a, b);
|
punpckhwd(b, a, b);
|
||||||
ASSERT_EQ(5, b[0]);
|
EXPECT_EQ(5, b[0]);
|
||||||
ASSERT_EQ(13, b[1]);
|
EXPECT_EQ(13, b[1]);
|
||||||
ASSERT_EQ(6, b[2]);
|
EXPECT_EQ(6, b[2]);
|
||||||
ASSERT_EQ(14, b[3]);
|
EXPECT_EQ(14, b[3]);
|
||||||
ASSERT_EQ(7, b[4]);
|
EXPECT_EQ(7, b[4]);
|
||||||
ASSERT_EQ(15, b[5]);
|
EXPECT_EQ(15, b[5]);
|
||||||
ASSERT_EQ(8, b[6]);
|
EXPECT_EQ(8, b[6]);
|
||||||
ASSERT_EQ(16, b[7]);
|
EXPECT_EQ(16, b[7]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(punpckhwd, pureAlias2) {
|
TEST(punpckhwd, pureAlias2) {
|
||||||
uint16_t a[8] = {1, 02, 03, 04, 05, 06, 07, 8};
|
uint16_t a[8] = {1, 02, 03, 04, 05, 06, 07, 8};
|
||||||
uint16_t b[8] = {9, 10, 11, 12, 13, 14, 15, 16};
|
uint16_t b[8] = {9, 10, 11, 12, 13, 14, 15, 16};
|
||||||
(punpckhwd)(b, a, b);
|
(punpckhwd)(b, a, b);
|
||||||
ASSERT_EQ(5, b[0]);
|
EXPECT_EQ(5, b[0]);
|
||||||
ASSERT_EQ(13, b[1]);
|
EXPECT_EQ(13, b[1]);
|
||||||
ASSERT_EQ(6, b[2]);
|
EXPECT_EQ(6, b[2]);
|
||||||
ASSERT_EQ(14, b[3]);
|
EXPECT_EQ(14, b[3]);
|
||||||
ASSERT_EQ(7, b[4]);
|
EXPECT_EQ(7, b[4]);
|
||||||
ASSERT_EQ(15, b[5]);
|
EXPECT_EQ(15, b[5]);
|
||||||
ASSERT_EQ(8, b[6]);
|
EXPECT_EQ(8, b[6]);
|
||||||
ASSERT_EQ(16, b[7]);
|
EXPECT_EQ(16, b[7]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(punpckhqdq, test) {
|
TEST(punpckhqdq, test) {
|
||||||
|
@ -441,8 +441,8 @@ TEST(punpckhqdq, test) {
|
||||||
uint64_t b[2] = {3, 4};
|
uint64_t b[2] = {3, 4};
|
||||||
uint64_t c[2];
|
uint64_t c[2];
|
||||||
punpckhqdq(c, a, b);
|
punpckhqdq(c, a, b);
|
||||||
ASSERT_EQ(2, c[0]);
|
EXPECT_EQ(2, c[0]);
|
||||||
ASSERT_EQ(4, c[1]);
|
EXPECT_EQ(4, c[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(punpckhqdq, pure) {
|
TEST(punpckhqdq, pure) {
|
||||||
|
@ -450,24 +450,24 @@ TEST(punpckhqdq, pure) {
|
||||||
uint64_t b[2] = {3, 4};
|
uint64_t b[2] = {3, 4};
|
||||||
uint64_t c[2];
|
uint64_t c[2];
|
||||||
(punpckhqdq)(c, a, b);
|
(punpckhqdq)(c, a, b);
|
||||||
ASSERT_EQ(2, c[0]);
|
EXPECT_EQ(2, c[0]);
|
||||||
ASSERT_EQ(4, c[1]);
|
EXPECT_EQ(4, c[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(punpckhqdq, testAlias) {
|
TEST(punpckhqdq, testAlias) {
|
||||||
uint64_t a[2] = {1, 2};
|
uint64_t a[2] = {1, 2};
|
||||||
uint64_t b[2] = {3, 4};
|
uint64_t b[2] = {3, 4};
|
||||||
punpckhqdq(a, a, b);
|
punpckhqdq(a, a, b);
|
||||||
ASSERT_EQ(2, a[0]);
|
EXPECT_EQ(2, a[0]);
|
||||||
ASSERT_EQ(4, a[1]);
|
EXPECT_EQ(4, a[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(punpckhqdq, pureAlias) {
|
TEST(punpckhqdq, pureAlias) {
|
||||||
uint64_t a[2] = {1, 2};
|
uint64_t a[2] = {1, 2};
|
||||||
uint64_t b[2] = {3, 4};
|
uint64_t b[2] = {3, 4};
|
||||||
(punpckhqdq)(a, a, b);
|
(punpckhqdq)(a, a, b);
|
||||||
ASSERT_EQ(2, a[0]);
|
EXPECT_EQ(2, a[0]);
|
||||||
ASSERT_EQ(4, a[1]);
|
EXPECT_EQ(4, a[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(punpckhdq, test) {
|
TEST(punpckhdq, test) {
|
||||||
|
@ -475,10 +475,10 @@ TEST(punpckhdq, test) {
|
||||||
uint32_t b[4] = {5, 6, 7, 8};
|
uint32_t b[4] = {5, 6, 7, 8};
|
||||||
uint32_t c[4];
|
uint32_t c[4];
|
||||||
punpckhdq(c, a, b);
|
punpckhdq(c, a, b);
|
||||||
ASSERT_EQ(3, c[0]);
|
EXPECT_EQ(3, c[0]);
|
||||||
ASSERT_EQ(7, c[1]);
|
EXPECT_EQ(7, c[1]);
|
||||||
ASSERT_EQ(4, c[2]);
|
EXPECT_EQ(4, c[2]);
|
||||||
ASSERT_EQ(8, c[3]);
|
EXPECT_EQ(8, c[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(punpckhdq, pure) {
|
TEST(punpckhdq, pure) {
|
||||||
|
@ -486,50 +486,50 @@ TEST(punpckhdq, pure) {
|
||||||
uint32_t b[4] = {5, 6, 7, 8};
|
uint32_t b[4] = {5, 6, 7, 8};
|
||||||
uint32_t c[4];
|
uint32_t c[4];
|
||||||
punpckhdq(c, a, b);
|
punpckhdq(c, a, b);
|
||||||
ASSERT_EQ(3, c[0]);
|
EXPECT_EQ(3, c[0]);
|
||||||
ASSERT_EQ(7, c[1]);
|
EXPECT_EQ(7, c[1]);
|
||||||
ASSERT_EQ(4, c[2]);
|
EXPECT_EQ(4, c[2]);
|
||||||
ASSERT_EQ(8, c[3]);
|
EXPECT_EQ(8, c[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(punpckhdq, testAlias) {
|
TEST(punpckhdq, testAlias) {
|
||||||
uint32_t a[4] = {1, 2, 3, 4};
|
uint32_t a[4] = {1, 2, 3, 4};
|
||||||
uint32_t b[4] = {5, 6, 7, 8};
|
uint32_t b[4] = {5, 6, 7, 8};
|
||||||
punpckhdq(a, a, b);
|
punpckhdq(a, a, b);
|
||||||
ASSERT_EQ(3, a[0]);
|
EXPECT_EQ(3, a[0]);
|
||||||
ASSERT_EQ(7, a[1]);
|
EXPECT_EQ(7, a[1]);
|
||||||
ASSERT_EQ(4, a[2]);
|
EXPECT_EQ(4, a[2]);
|
||||||
ASSERT_EQ(8, a[3]);
|
EXPECT_EQ(8, a[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(punpckhdq, pureAlias) {
|
TEST(punpckhdq, pureAlias) {
|
||||||
uint32_t a[4] = {1, 2, 3, 4};
|
uint32_t a[4] = {1, 2, 3, 4};
|
||||||
uint32_t b[4] = {5, 6, 7, 8};
|
uint32_t b[4] = {5, 6, 7, 8};
|
||||||
(punpckhdq)(a, a, b);
|
(punpckhdq)(a, a, b);
|
||||||
ASSERT_EQ(3, a[0]);
|
EXPECT_EQ(3, a[0]);
|
||||||
ASSERT_EQ(7, a[1]);
|
EXPECT_EQ(7, a[1]);
|
||||||
ASSERT_EQ(4, a[2]);
|
EXPECT_EQ(4, a[2]);
|
||||||
ASSERT_EQ(8, a[3]);
|
EXPECT_EQ(8, a[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(punpckhdq, testAlias2) {
|
TEST(punpckhdq, testAlias2) {
|
||||||
uint32_t a[4] = {1, 2, 3, 4};
|
uint32_t a[4] = {1, 2, 3, 4};
|
||||||
uint32_t b[4] = {5, 6, 7, 8};
|
uint32_t b[4] = {5, 6, 7, 8};
|
||||||
punpckhdq(b, a, b);
|
punpckhdq(b, a, b);
|
||||||
ASSERT_EQ(3, b[0]);
|
EXPECT_EQ(3, b[0]);
|
||||||
ASSERT_EQ(7, b[1]);
|
EXPECT_EQ(7, b[1]);
|
||||||
ASSERT_EQ(4, b[2]);
|
EXPECT_EQ(4, b[2]);
|
||||||
ASSERT_EQ(8, b[3]);
|
EXPECT_EQ(8, b[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(punpckhdq, pureAlias2) {
|
TEST(punpckhdq, pureAlias2) {
|
||||||
uint32_t a[4] = {1, 2, 3, 4};
|
uint32_t a[4] = {1, 2, 3, 4};
|
||||||
uint32_t b[4] = {5, 6, 7, 8};
|
uint32_t b[4] = {5, 6, 7, 8};
|
||||||
(punpckhdq)(b, a, b);
|
(punpckhdq)(b, a, b);
|
||||||
ASSERT_EQ(3, b[0]);
|
EXPECT_EQ(3, b[0]);
|
||||||
ASSERT_EQ(7, b[1]);
|
EXPECT_EQ(7, b[1]);
|
||||||
ASSERT_EQ(4, b[2]);
|
EXPECT_EQ(4, b[2]);
|
||||||
ASSERT_EQ(8, b[3]);
|
EXPECT_EQ(8, b[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(punpckhwd, fuzz) {
|
TEST(punpckhwd, fuzz) {
|
||||||
|
|
|
@ -29,6 +29,7 @@ TEST_LIBC_RUNTIME_DIRECTDEPS = \
|
||||||
LIBC_CALLS_HEFTY \
|
LIBC_CALLS_HEFTY \
|
||||||
LIBC_FMT \
|
LIBC_FMT \
|
||||||
LIBC_MEM \
|
LIBC_MEM \
|
||||||
|
LIBC_TINYMATH \
|
||||||
LIBC_NEXGEN32E \
|
LIBC_NEXGEN32E \
|
||||||
LIBC_RAND \
|
LIBC_RAND \
|
||||||
LIBC_RUNTIME \
|
LIBC_RUNTIME \
|
||||||
|
|
|
@ -36,10 +36,9 @@ void SetUp(void) {
|
||||||
TEST(bsr64, test) {
|
TEST(bsr64, test) {
|
||||||
bool zf;
|
bool zf;
|
||||||
uint64_t i, w, x, a, b;
|
uint64_t i, w, x, a, b;
|
||||||
m->xedd->op.rde = REXW;
|
|
||||||
for (i = 0; i < ARRAYLEN(kNumbers); ++i) {
|
for (i = 0; i < ARRAYLEN(kNumbers); ++i) {
|
||||||
x = kNumbers[i];
|
x = kNumbers[i];
|
||||||
a = AluBsr(m, 0, x);
|
a = AluBsr(m, REXW, 0, x);
|
||||||
asm("bsrq\t%2,%0" : "=r"(b), "=@ccz"(zf) : "r"(x));
|
asm("bsrq\t%2,%0" : "=r"(b), "=@ccz"(zf) : "r"(x));
|
||||||
ASSERT_EQ(zf, GetFlag(m->flags, FLAGS_ZF));
|
ASSERT_EQ(zf, GetFlag(m->flags, FLAGS_ZF));
|
||||||
if (!zf) ASSERT_EQ(a, b);
|
if (!zf) ASSERT_EQ(a, b);
|
||||||
|
@ -49,10 +48,9 @@ TEST(bsr64, test) {
|
||||||
TEST(bsr32, test) {
|
TEST(bsr32, test) {
|
||||||
bool zf;
|
bool zf;
|
||||||
uint32_t i, w, x, a, b;
|
uint32_t i, w, x, a, b;
|
||||||
m->xedd->op.rde = 0;
|
|
||||||
for (i = 0; i < ARRAYLEN(kNumbers); ++i) {
|
for (i = 0; i < ARRAYLEN(kNumbers); ++i) {
|
||||||
x = kNumbers[i];
|
x = kNumbers[i];
|
||||||
a = AluBsr(m, 0, x);
|
a = AluBsr(m, 0, 0, x);
|
||||||
asm("bsrl\t%2,%0" : "=r"(b), "=@ccz"(zf) : "r"(x));
|
asm("bsrl\t%2,%0" : "=r"(b), "=@ccz"(zf) : "r"(x));
|
||||||
ASSERT_EQ(zf, GetFlag(m->flags, FLAGS_ZF));
|
ASSERT_EQ(zf, GetFlag(m->flags, FLAGS_ZF));
|
||||||
if (!zf) ASSERT_EQ(a, b);
|
if (!zf) ASSERT_EQ(a, b);
|
||||||
|
@ -62,10 +60,9 @@ TEST(bsr32, test) {
|
||||||
TEST(bsr16, test) {
|
TEST(bsr16, test) {
|
||||||
bool zf;
|
bool zf;
|
||||||
uint16_t i, w, x, a, b;
|
uint16_t i, w, x, a, b;
|
||||||
m->xedd->op.rde = OSZ;
|
|
||||||
for (i = 0; i < ARRAYLEN(kNumbers); ++i) {
|
for (i = 0; i < ARRAYLEN(kNumbers); ++i) {
|
||||||
x = kNumbers[i];
|
x = kNumbers[i];
|
||||||
a = AluBsr(m, 0, x);
|
a = AluBsr(m, OSZ, 0, x);
|
||||||
asm("bsrw\t%2,%0" : "=r"(b), "=@ccz"(zf) : "r"(x));
|
asm("bsrw\t%2,%0" : "=r"(b), "=@ccz"(zf) : "r"(x));
|
||||||
ASSERT_EQ(zf, GetFlag(m->flags, FLAGS_ZF));
|
ASSERT_EQ(zf, GetFlag(m->flags, FLAGS_ZF));
|
||||||
if (!zf) ASSERT_EQ(a, b);
|
if (!zf) ASSERT_EQ(a, b);
|
||||||
|
@ -75,10 +72,9 @@ TEST(bsr16, test) {
|
||||||
TEST(bsf64, test) {
|
TEST(bsf64, test) {
|
||||||
bool zf;
|
bool zf;
|
||||||
uint64_t i, w, x, a, b;
|
uint64_t i, w, x, a, b;
|
||||||
m->xedd->op.rde = REXW;
|
|
||||||
for (i = 0; i < ARRAYLEN(kNumbers); ++i) {
|
for (i = 0; i < ARRAYLEN(kNumbers); ++i) {
|
||||||
x = kNumbers[i];
|
x = kNumbers[i];
|
||||||
a = AluBsf(m, 0, x);
|
a = AluBsf(m, REXW, 0, x);
|
||||||
asm("bsfq\t%2,%0" : "=r"(b), "=@ccz"(zf) : "r"(x));
|
asm("bsfq\t%2,%0" : "=r"(b), "=@ccz"(zf) : "r"(x));
|
||||||
ASSERT_EQ(zf, GetFlag(m->flags, FLAGS_ZF));
|
ASSERT_EQ(zf, GetFlag(m->flags, FLAGS_ZF));
|
||||||
if (!zf) ASSERT_EQ(a, b);
|
if (!zf) ASSERT_EQ(a, b);
|
||||||
|
@ -88,10 +84,9 @@ TEST(bsf64, test) {
|
||||||
TEST(bsf32, test) {
|
TEST(bsf32, test) {
|
||||||
bool zf;
|
bool zf;
|
||||||
uint32_t i, w, x, a, b;
|
uint32_t i, w, x, a, b;
|
||||||
m->xedd->op.rde = 0;
|
|
||||||
for (i = 0; i < ARRAYLEN(kNumbers); ++i) {
|
for (i = 0; i < ARRAYLEN(kNumbers); ++i) {
|
||||||
x = kNumbers[i];
|
x = kNumbers[i];
|
||||||
a = AluBsf(m, 0, x);
|
a = AluBsf(m, 0, 0, x);
|
||||||
asm("bsfl\t%2,%0" : "=r"(b), "=@ccz"(zf) : "r"(x));
|
asm("bsfl\t%2,%0" : "=r"(b), "=@ccz"(zf) : "r"(x));
|
||||||
ASSERT_EQ(zf, GetFlag(m->flags, FLAGS_ZF));
|
ASSERT_EQ(zf, GetFlag(m->flags, FLAGS_ZF));
|
||||||
if (!zf) ASSERT_EQ(a, b);
|
if (!zf) ASSERT_EQ(a, b);
|
||||||
|
@ -101,10 +96,9 @@ TEST(bsf32, test) {
|
||||||
TEST(bsf16, test) {
|
TEST(bsf16, test) {
|
||||||
bool zf;
|
bool zf;
|
||||||
uint16_t i, w, x, a, b;
|
uint16_t i, w, x, a, b;
|
||||||
m->xedd->op.rde = OSZ;
|
|
||||||
for (i = 0; i < ARRAYLEN(kNumbers); ++i) {
|
for (i = 0; i < ARRAYLEN(kNumbers); ++i) {
|
||||||
x = kNumbers[i];
|
x = kNumbers[i];
|
||||||
a = AluBsf(m, 0, x);
|
a = AluBsf(m, OSZ, 0, x);
|
||||||
asm("bsfw\t%2,%0" : "=r"(b), "=@ccz"(zf) : "r"(x));
|
asm("bsfw\t%2,%0" : "=r"(b), "=@ccz"(zf) : "r"(x));
|
||||||
ASSERT_EQ(zf, GetFlag(m->flags, FLAGS_ZF));
|
ASSERT_EQ(zf, GetFlag(m->flags, FLAGS_ZF));
|
||||||
if (!zf) ASSERT_EQ(a, b, "%#lx", x);
|
if (!zf) ASSERT_EQ(a, b, "%#lx", x);
|
||||||
|
|
|
@ -62,12 +62,11 @@ TEST(imul8, test) {
|
||||||
int i, j;
|
int i, j;
|
||||||
int16_t ax;
|
int16_t ax;
|
||||||
bool cf, of;
|
bool cf, of;
|
||||||
m->xedd->op.rde = MOD(3) | RM(CX);
|
|
||||||
for (i = 0; i < ARRAYLEN(A); ++i) {
|
for (i = 0; i < ARRAYLEN(A); ++i) {
|
||||||
for (j = 0; j < ARRAYLEN(A); ++j) {
|
for (j = 0; j < ARRAYLEN(A); ++j) {
|
||||||
Write8(m->ax, A[i]);
|
Write8(m->ax, A[i]);
|
||||||
Write8(m->cx, A[j]);
|
Write8(m->cx, A[j]);
|
||||||
OpMulAxAlEbSigned(m);
|
OpMulAxAlEbSigned(m, MOD(3) | RM(CX));
|
||||||
asm volatile("imulb\t%3"
|
asm volatile("imulb\t%3"
|
||||||
: "=a"(ax), "=@ccc"(cf), "=@cco"(of)
|
: "=a"(ax), "=@ccc"(cf), "=@cco"(of)
|
||||||
: "q"(A[j]), "0"(A[i])
|
: "q"(A[j]), "0"(A[i])
|
||||||
|
@ -85,12 +84,11 @@ TEST(imul16, test) {
|
||||||
int i, j;
|
int i, j;
|
||||||
bool cf, of;
|
bool cf, of;
|
||||||
uint16_t dx, ax;
|
uint16_t dx, ax;
|
||||||
m->xedd->op.rde = OSZ | MOD(3) | RM(CX);
|
|
||||||
for (i = 0; i < ARRAYLEN(A); ++i) {
|
for (i = 0; i < ARRAYLEN(A); ++i) {
|
||||||
for (j = 0; j < ARRAYLEN(A); ++j) {
|
for (j = 0; j < ARRAYLEN(A); ++j) {
|
||||||
Write16(m->ax, A[i]);
|
Write16(m->ax, A[i]);
|
||||||
Write16(m->cx, A[j]);
|
Write16(m->cx, A[j]);
|
||||||
OpMulRdxRaxEvqpSigned(m);
|
OpMulRdxRaxEvqpSigned(m, OSZ | MOD(3) | RM(CX));
|
||||||
asm("imulw\t%4"
|
asm("imulw\t%4"
|
||||||
: "=d"(dx), "=a"(ax), "=@ccc"(cf), "=@cco"(of)
|
: "=d"(dx), "=a"(ax), "=@ccc"(cf), "=@cco"(of)
|
||||||
: "r"(A[j]), "1"(A[i])
|
: "r"(A[j]), "1"(A[i])
|
||||||
|
@ -110,12 +108,11 @@ TEST(imul32, test) {
|
||||||
int i, j;
|
int i, j;
|
||||||
bool cf, of;
|
bool cf, of;
|
||||||
uint32_t dx, ax;
|
uint32_t dx, ax;
|
||||||
m->xedd->op.rde = MOD(3) | RM(CX);
|
|
||||||
for (i = 0; i < ARRAYLEN(A); ++i) {
|
for (i = 0; i < ARRAYLEN(A); ++i) {
|
||||||
for (j = 0; j < ARRAYLEN(A); ++j) {
|
for (j = 0; j < ARRAYLEN(A); ++j) {
|
||||||
Write32(m->ax, A[i]);
|
Write32(m->ax, A[i]);
|
||||||
Write32(m->cx, A[j]);
|
Write32(m->cx, A[j]);
|
||||||
OpMulRdxRaxEvqpSigned(m);
|
OpMulRdxRaxEvqpSigned(m, MOD(3) | RM(CX));
|
||||||
asm("imull\t%4"
|
asm("imull\t%4"
|
||||||
: "=d"(dx), "=a"(ax), "=@ccc"(cf), "=@cco"(of)
|
: "=d"(dx), "=a"(ax), "=@ccc"(cf), "=@cco"(of)
|
||||||
: "r"(A[j]), "1"(A[i])
|
: "r"(A[j]), "1"(A[i])
|
||||||
|
@ -135,12 +132,11 @@ TEST(imul64, test) {
|
||||||
int i, j;
|
int i, j;
|
||||||
bool cf, of;
|
bool cf, of;
|
||||||
uint64_t dx, ax;
|
uint64_t dx, ax;
|
||||||
m->xedd->op.rde = REXW | MOD(3) | RM(CX);
|
|
||||||
for (i = 0; i < ARRAYLEN(A); ++i) {
|
for (i = 0; i < ARRAYLEN(A); ++i) {
|
||||||
for (j = 0; j < ARRAYLEN(A); ++j) {
|
for (j = 0; j < ARRAYLEN(A); ++j) {
|
||||||
Write64(m->ax, A[i]);
|
Write64(m->ax, A[i]);
|
||||||
Write64(m->cx, A[j]);
|
Write64(m->cx, A[j]);
|
||||||
OpMulRdxRaxEvqpSigned(m);
|
OpMulRdxRaxEvqpSigned(m, REXW | MOD(3) | RM(CX));
|
||||||
asm("imulq\t%4"
|
asm("imulq\t%4"
|
||||||
: "=d"(dx), "=a"(ax), "=@ccc"(cf), "=@cco"(of)
|
: "=d"(dx), "=a"(ax), "=@ccc"(cf), "=@cco"(of)
|
||||||
: "r"(A[j]), "1"(A[i])
|
: "r"(A[j]), "1"(A[i])
|
||||||
|
@ -158,12 +154,11 @@ TEST(mul8, test) {
|
||||||
int i, j;
|
int i, j;
|
||||||
uint16_t ax;
|
uint16_t ax;
|
||||||
bool cf, of;
|
bool cf, of;
|
||||||
m->xedd->op.rde = MOD(3) | RM(CX);
|
|
||||||
for (i = 0; i < ARRAYLEN(A); ++i) {
|
for (i = 0; i < ARRAYLEN(A); ++i) {
|
||||||
for (j = 0; j < ARRAYLEN(A); ++j) {
|
for (j = 0; j < ARRAYLEN(A); ++j) {
|
||||||
Write8(m->ax, A[i]);
|
Write8(m->ax, A[i]);
|
||||||
Write8(m->cx, A[j]);
|
Write8(m->cx, A[j]);
|
||||||
OpMulAxAlEbUnsigned(m);
|
OpMulAxAlEbUnsigned(m, MOD(3) | RM(CX));
|
||||||
asm volatile("mulb\t%3"
|
asm volatile("mulb\t%3"
|
||||||
: "=a"(ax), "=@ccc"(cf), "=@cco"(of)
|
: "=a"(ax), "=@ccc"(cf), "=@cco"(of)
|
||||||
: "q"(A[j]), "0"(A[i])
|
: "q"(A[j]), "0"(A[i])
|
||||||
|
@ -181,12 +176,11 @@ TEST(mul16, test) {
|
||||||
int i, j;
|
int i, j;
|
||||||
bool cf, of;
|
bool cf, of;
|
||||||
uint16_t dx, ax;
|
uint16_t dx, ax;
|
||||||
m->xedd->op.rde = OSZ | MOD(3) | RM(CX);
|
|
||||||
for (i = 0; i < ARRAYLEN(A); ++i) {
|
for (i = 0; i < ARRAYLEN(A); ++i) {
|
||||||
for (j = 0; j < ARRAYLEN(A); ++j) {
|
for (j = 0; j < ARRAYLEN(A); ++j) {
|
||||||
Write16(m->ax, A[i]);
|
Write16(m->ax, A[i]);
|
||||||
Write16(m->cx, A[j]);
|
Write16(m->cx, A[j]);
|
||||||
OpMulRdxRaxEvqpUnsigned(m);
|
OpMulRdxRaxEvqpUnsigned(m, OSZ | MOD(3) | RM(CX));
|
||||||
asm("mulw\t%4"
|
asm("mulw\t%4"
|
||||||
: "=d"(dx), "=a"(ax), "=@ccc"(cf), "=@cco"(of)
|
: "=d"(dx), "=a"(ax), "=@ccc"(cf), "=@cco"(of)
|
||||||
: "r"(A[j]), "1"(A[i])
|
: "r"(A[j]), "1"(A[i])
|
||||||
|
@ -206,12 +200,11 @@ TEST(mul32, test) {
|
||||||
int i, j;
|
int i, j;
|
||||||
bool cf, of;
|
bool cf, of;
|
||||||
uint32_t dx, ax;
|
uint32_t dx, ax;
|
||||||
m->xedd->op.rde = MOD(3) | RM(CX);
|
|
||||||
for (i = 0; i < ARRAYLEN(A); ++i) {
|
for (i = 0; i < ARRAYLEN(A); ++i) {
|
||||||
for (j = 0; j < ARRAYLEN(A); ++j) {
|
for (j = 0; j < ARRAYLEN(A); ++j) {
|
||||||
Write32(m->ax, A[i]);
|
Write32(m->ax, A[i]);
|
||||||
Write32(m->cx, A[j]);
|
Write32(m->cx, A[j]);
|
||||||
OpMulRdxRaxEvqpUnsigned(m);
|
OpMulRdxRaxEvqpUnsigned(m, MOD(3) | RM(CX));
|
||||||
asm("mull\t%4"
|
asm("mull\t%4"
|
||||||
: "=d"(dx), "=a"(ax), "=@ccc"(cf), "=@cco"(of)
|
: "=d"(dx), "=a"(ax), "=@ccc"(cf), "=@cco"(of)
|
||||||
: "r"(A[j]), "1"(A[i])
|
: "r"(A[j]), "1"(A[i])
|
||||||
|
@ -231,12 +224,11 @@ TEST(mul64, test) {
|
||||||
int i, j;
|
int i, j;
|
||||||
bool cf, of;
|
bool cf, of;
|
||||||
uint64_t dx, ax;
|
uint64_t dx, ax;
|
||||||
m->xedd->op.rde = REXW | MOD(3) | RM(CX);
|
|
||||||
for (i = 0; i < ARRAYLEN(A); ++i) {
|
for (i = 0; i < ARRAYLEN(A); ++i) {
|
||||||
for (j = 0; j < ARRAYLEN(A); ++j) {
|
for (j = 0; j < ARRAYLEN(A); ++j) {
|
||||||
Write64(m->ax, A[i]);
|
Write64(m->ax, A[i]);
|
||||||
Write64(m->cx, A[j]);
|
Write64(m->cx, A[j]);
|
||||||
OpMulRdxRaxEvqpUnsigned(m);
|
OpMulRdxRaxEvqpUnsigned(m, REXW | MOD(3) | RM(CX));
|
||||||
asm("mulq\t%4"
|
asm("mulq\t%4"
|
||||||
: "=d"(dx), "=a"(ax), "=@ccc"(cf), "=@cco"(of)
|
: "=d"(dx), "=a"(ax), "=@ccc"(cf), "=@cco"(of)
|
||||||
: "r"(A[j]), "1"(A[i])
|
: "r"(A[j]), "1"(A[i])
|
||||||
|
@ -255,7 +247,6 @@ TEST(idiv8, test) {
|
||||||
bool gotthrow, gotsigfpe;
|
bool gotthrow, gotsigfpe;
|
||||||
int8_t i, j, k, w, x, a, b;
|
int8_t i, j, k, w, x, a, b;
|
||||||
int8_t quotient, remainder;
|
int8_t quotient, remainder;
|
||||||
m->xedd->op.rde = MOD(3) | RM(CX);
|
|
||||||
for (i = 0; i < ARRAYLEN(A); ++i) {
|
for (i = 0; i < ARRAYLEN(A); ++i) {
|
||||||
for (j = 0; j < ARRAYLEN(A); ++j) {
|
for (j = 0; j < ARRAYLEN(A); ++j) {
|
||||||
for (k = 0; k < ARRAYLEN(A); ++k) {
|
for (k = 0; k < ARRAYLEN(A); ++k) {
|
||||||
|
@ -265,7 +256,7 @@ TEST(idiv8, test) {
|
||||||
gotthrow = false;
|
gotthrow = false;
|
||||||
gotsigfpe = false;
|
gotsigfpe = false;
|
||||||
if (!setjmp(m->onhalt)) {
|
if (!setjmp(m->onhalt)) {
|
||||||
OpDivAlAhAxEbSigned(m);
|
OpDivAlAhAxEbSigned(m, MOD(3) | RM(CX));
|
||||||
} else {
|
} else {
|
||||||
gotthrow = true;
|
gotthrow = true;
|
||||||
}
|
}
|
||||||
|
@ -295,7 +286,6 @@ TEST(idiv16, test) {
|
||||||
bool gotthrow, gotsigfpe;
|
bool gotthrow, gotsigfpe;
|
||||||
int16_t i, j, k, w, x, a, b;
|
int16_t i, j, k, w, x, a, b;
|
||||||
int16_t quotient, remainder;
|
int16_t quotient, remainder;
|
||||||
m->xedd->op.rde = OSZ | MOD(3) | RM(CX);
|
|
||||||
for (i = 0; i < ARRAYLEN(A); ++i) {
|
for (i = 0; i < ARRAYLEN(A); ++i) {
|
||||||
for (j = 0; j < ARRAYLEN(A); ++j) {
|
for (j = 0; j < ARRAYLEN(A); ++j) {
|
||||||
for (k = 0; k < ARRAYLEN(A); ++k) {
|
for (k = 0; k < ARRAYLEN(A); ++k) {
|
||||||
|
@ -304,7 +294,7 @@ TEST(idiv16, test) {
|
||||||
memcpy(m->cx, &A[k], 2);
|
memcpy(m->cx, &A[k], 2);
|
||||||
if (!setjmp(m->onhalt)) {
|
if (!setjmp(m->onhalt)) {
|
||||||
gotthrow = false;
|
gotthrow = false;
|
||||||
OpDivRdxRaxEvqpSigned(m);
|
OpDivRdxRaxEvqpSigned(m, OSZ | MOD(3) | RM(CX));
|
||||||
} else {
|
} else {
|
||||||
gotthrow = true;
|
gotthrow = true;
|
||||||
}
|
}
|
||||||
|
@ -333,7 +323,6 @@ TEST(idiv32, test) {
|
||||||
bool gotthrow, gotsigfpe;
|
bool gotthrow, gotsigfpe;
|
||||||
int32_t i, j, k, w, x, a, b;
|
int32_t i, j, k, w, x, a, b;
|
||||||
int32_t quotient, remainder;
|
int32_t quotient, remainder;
|
||||||
m->xedd->op.rde = MOD(3) | RM(CX);
|
|
||||||
for (i = 0; i < ARRAYLEN(A); ++i) {
|
for (i = 0; i < ARRAYLEN(A); ++i) {
|
||||||
for (j = 0; j < ARRAYLEN(A); ++j) {
|
for (j = 0; j < ARRAYLEN(A); ++j) {
|
||||||
for (k = 0; k < ARRAYLEN(A); ++k) {
|
for (k = 0; k < ARRAYLEN(A); ++k) {
|
||||||
|
@ -342,7 +331,7 @@ TEST(idiv32, test) {
|
||||||
memcpy(m->cx, &A[k], 4);
|
memcpy(m->cx, &A[k], 4);
|
||||||
if (!setjmp(m->onhalt)) {
|
if (!setjmp(m->onhalt)) {
|
||||||
gotthrow = false;
|
gotthrow = false;
|
||||||
OpDivRdxRaxEvqpSigned(m);
|
OpDivRdxRaxEvqpSigned(m, MOD(3) | RM(CX));
|
||||||
} else {
|
} else {
|
||||||
gotthrow = true;
|
gotthrow = true;
|
||||||
}
|
}
|
||||||
|
@ -373,7 +362,6 @@ TEST(idiv64, test) {
|
||||||
bool gotthrow, gotsigfpe;
|
bool gotthrow, gotsigfpe;
|
||||||
int64_t i, j, k, w, x, a, b;
|
int64_t i, j, k, w, x, a, b;
|
||||||
int64_t quotient, remainder;
|
int64_t quotient, remainder;
|
||||||
m->xedd->op.rde = REXW | MOD(3) | RM(CX);
|
|
||||||
for (i = 0; i < ARRAYLEN(A); ++i) {
|
for (i = 0; i < ARRAYLEN(A); ++i) {
|
||||||
for (j = 0; j < ARRAYLEN(A); ++j) {
|
for (j = 0; j < ARRAYLEN(A); ++j) {
|
||||||
for (k = 0; k < ARRAYLEN(A); ++k) {
|
for (k = 0; k < ARRAYLEN(A); ++k) {
|
||||||
|
@ -382,7 +370,7 @@ TEST(idiv64, test) {
|
||||||
memcpy(m->cx, &A[k], 8);
|
memcpy(m->cx, &A[k], 8);
|
||||||
if (!setjmp(m->onhalt)) {
|
if (!setjmp(m->onhalt)) {
|
||||||
gotthrow = false;
|
gotthrow = false;
|
||||||
OpDivRdxRaxEvqpSigned(m);
|
OpDivRdxRaxEvqpSigned(m, REXW | MOD(3) | RM(CX));
|
||||||
} else {
|
} else {
|
||||||
gotthrow = true;
|
gotthrow = true;
|
||||||
}
|
}
|
||||||
|
@ -411,7 +399,6 @@ TEST(div, test) {
|
||||||
bool gotthrow, gotsigfpe;
|
bool gotthrow, gotsigfpe;
|
||||||
uint8_t i, j, k, w, x, a, b;
|
uint8_t i, j, k, w, x, a, b;
|
||||||
uint8_t quotient, remainder;
|
uint8_t quotient, remainder;
|
||||||
m->xedd->op.rde = MOD(3) | RM(CX);
|
|
||||||
for (i = 0; i < ARRAYLEN(A); ++i) {
|
for (i = 0; i < ARRAYLEN(A); ++i) {
|
||||||
for (j = 0; j < ARRAYLEN(A); ++j) {
|
for (j = 0; j < ARRAYLEN(A); ++j) {
|
||||||
for (k = 0; k < ARRAYLEN(A); ++k) {
|
for (k = 0; k < ARRAYLEN(A); ++k) {
|
||||||
|
@ -421,7 +408,7 @@ TEST(div, test) {
|
||||||
gotthrow = false;
|
gotthrow = false;
|
||||||
gotsigfpe = false;
|
gotsigfpe = false;
|
||||||
if (!setjmp(m->onhalt)) {
|
if (!setjmp(m->onhalt)) {
|
||||||
OpDivAlAhAxEbUnsigned(m);
|
OpDivAlAhAxEbUnsigned(m, MOD(3) | RM(CX));
|
||||||
} else {
|
} else {
|
||||||
gotthrow = true;
|
gotthrow = true;
|
||||||
}
|
}
|
||||||
|
@ -451,7 +438,6 @@ TEST(div16, test) {
|
||||||
bool gotthrow, gotsigfpe;
|
bool gotthrow, gotsigfpe;
|
||||||
uint16_t i, j, k, w, x, a, b;
|
uint16_t i, j, k, w, x, a, b;
|
||||||
uint16_t quotient, remainder;
|
uint16_t quotient, remainder;
|
||||||
m->xedd->op.rde = OSZ | MOD(3) | RM(CX);
|
|
||||||
for (i = 0; i < ARRAYLEN(A); ++i) {
|
for (i = 0; i < ARRAYLEN(A); ++i) {
|
||||||
for (j = 0; j < ARRAYLEN(A); ++j) {
|
for (j = 0; j < ARRAYLEN(A); ++j) {
|
||||||
for (k = 0; k < ARRAYLEN(A); ++k) {
|
for (k = 0; k < ARRAYLEN(A); ++k) {
|
||||||
|
@ -460,7 +446,7 @@ TEST(div16, test) {
|
||||||
memcpy(m->cx, &A[k], 2);
|
memcpy(m->cx, &A[k], 2);
|
||||||
if (!setjmp(m->onhalt)) {
|
if (!setjmp(m->onhalt)) {
|
||||||
gotthrow = false;
|
gotthrow = false;
|
||||||
OpDivRdxRaxEvqpUnsigned(m);
|
OpDivRdxRaxEvqpUnsigned(m, OSZ | MOD(3) | RM(CX));
|
||||||
} else {
|
} else {
|
||||||
gotthrow = true;
|
gotthrow = true;
|
||||||
}
|
}
|
||||||
|
@ -489,7 +475,6 @@ TEST(div32, test) {
|
||||||
bool gotthrow, gotsigfpe;
|
bool gotthrow, gotsigfpe;
|
||||||
uint32_t i, j, k, w, x, a, b;
|
uint32_t i, j, k, w, x, a, b;
|
||||||
uint32_t quotient, remainder;
|
uint32_t quotient, remainder;
|
||||||
m->xedd->op.rde = MOD(3) | RM(CX);
|
|
||||||
for (i = 0; i < ARRAYLEN(A); ++i) {
|
for (i = 0; i < ARRAYLEN(A); ++i) {
|
||||||
for (j = 0; j < ARRAYLEN(A); ++j) {
|
for (j = 0; j < ARRAYLEN(A); ++j) {
|
||||||
for (k = 0; k < ARRAYLEN(A); ++k) {
|
for (k = 0; k < ARRAYLEN(A); ++k) {
|
||||||
|
@ -498,7 +483,7 @@ TEST(div32, test) {
|
||||||
memcpy(m->cx, &A[k], 4);
|
memcpy(m->cx, &A[k], 4);
|
||||||
if (!setjmp(m->onhalt)) {
|
if (!setjmp(m->onhalt)) {
|
||||||
gotthrow = false;
|
gotthrow = false;
|
||||||
OpDivRdxRaxEvqpUnsigned(m);
|
OpDivRdxRaxEvqpUnsigned(m, MOD(3) | RM(CX));
|
||||||
} else {
|
} else {
|
||||||
gotthrow = true;
|
gotthrow = true;
|
||||||
}
|
}
|
||||||
|
@ -529,7 +514,6 @@ TEST(div64, test) {
|
||||||
bool gotthrow, gotsigfpe;
|
bool gotthrow, gotsigfpe;
|
||||||
uint64_t i, j, k, w, x, a, b;
|
uint64_t i, j, k, w, x, a, b;
|
||||||
uint64_t quotient, remainder;
|
uint64_t quotient, remainder;
|
||||||
m->xedd->op.rde = REXW | MOD(3) | RM(CX);
|
|
||||||
for (i = 0; i < ARRAYLEN(A); ++i) {
|
for (i = 0; i < ARRAYLEN(A); ++i) {
|
||||||
for (j = 0; j < ARRAYLEN(A); ++j) {
|
for (j = 0; j < ARRAYLEN(A); ++j) {
|
||||||
for (k = 0; k < ARRAYLEN(A); ++k) {
|
for (k = 0; k < ARRAYLEN(A); ++k) {
|
||||||
|
@ -538,7 +522,7 @@ TEST(div64, test) {
|
||||||
memcpy(m->cx, &A[k], 8);
|
memcpy(m->cx, &A[k], 8);
|
||||||
if (!setjmp(m->onhalt)) {
|
if (!setjmp(m->onhalt)) {
|
||||||
gotthrow = false;
|
gotthrow = false;
|
||||||
OpDivRdxRaxEvqpUnsigned(m);
|
OpDivRdxRaxEvqpUnsigned(m, REXW | MOD(3) | RM(CX));
|
||||||
} else {
|
} else {
|
||||||
gotthrow = true;
|
gotthrow = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ TEST(modrm, testAddressSizeOverride_isNotPresent_keepsWholeExpression) {
|
||||||
Write64(m->ax, 0xffffffff);
|
Write64(m->ax, 0xffffffff);
|
||||||
xed_decoded_inst_zero_set_mode(xedd, XED_MACHINE_MODE_LONG_64);
|
xed_decoded_inst_zero_set_mode(xedd, XED_MACHINE_MODE_LONG_64);
|
||||||
ASSERT_EQ(0, xed_instruction_length_decode(xedd, op, sizeof(op)));
|
ASSERT_EQ(0, xed_instruction_length_decode(xedd, op, sizeof(op)));
|
||||||
EXPECT_EQ(0x100000001, ComputeAddress(m));
|
EXPECT_EQ(0x100000001, ComputeAddress(m, m->xedd->op.rde));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(modrm, testAddressSizeOverride_isPresent_modulesWholeExpression) {
|
TEST(modrm, testAddressSizeOverride_isPresent_modulesWholeExpression) {
|
||||||
|
@ -46,7 +46,7 @@ TEST(modrm, testAddressSizeOverride_isPresent_modulesWholeExpression) {
|
||||||
Write64(m->ax, 0xffffffff);
|
Write64(m->ax, 0xffffffff);
|
||||||
xed_decoded_inst_zero_set_mode(xedd, XED_MACHINE_MODE_LONG_64);
|
xed_decoded_inst_zero_set_mode(xedd, XED_MACHINE_MODE_LONG_64);
|
||||||
ASSERT_EQ(0, xed_instruction_length_decode(xedd, op, sizeof(op)));
|
ASSERT_EQ(0, xed_instruction_length_decode(xedd, op, sizeof(op)));
|
||||||
EXPECT_EQ(0x000000001, ComputeAddress(m));
|
EXPECT_EQ(0x000000001, ComputeAddress(m, m->xedd->op.rde));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(modrm, testOverflow_doesntTriggerTooling) {
|
TEST(modrm, testOverflow_doesntTriggerTooling) {
|
||||||
|
@ -58,7 +58,8 @@ TEST(modrm, testOverflow_doesntTriggerTooling) {
|
||||||
Write64(m->ax, 0x7fffffffffffffff);
|
Write64(m->ax, 0x7fffffffffffffff);
|
||||||
xed_decoded_inst_zero_set_mode(xedd, XED_MACHINE_MODE_LONG_64);
|
xed_decoded_inst_zero_set_mode(xedd, XED_MACHINE_MODE_LONG_64);
|
||||||
ASSERT_EQ(0, xed_instruction_length_decode(xedd, op, sizeof(op)));
|
ASSERT_EQ(0, xed_instruction_length_decode(xedd, op, sizeof(op)));
|
||||||
EXPECT_EQ(0x8000000000000000ull, (uint64_t)ComputeAddress(m));
|
EXPECT_EQ(0x8000000000000000ull,
|
||||||
|
(uint64_t)ComputeAddress(m, m->xedd->op.rde));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(modrm, testPuttingOnTheRiz) {
|
TEST(modrm, testPuttingOnTheRiz) {
|
||||||
|
@ -74,16 +75,16 @@ TEST(modrm, testPuttingOnTheRiz) {
|
||||||
Write64(m->bp, 0x200000002);
|
Write64(m->bp, 0x200000002);
|
||||||
xed_decoded_inst_zero_set_mode(m->xedd, XED_MACHINE_MODE_LONG_64);
|
xed_decoded_inst_zero_set_mode(m->xedd, XED_MACHINE_MODE_LONG_64);
|
||||||
ASSERT_EQ(0, xed_instruction_length_decode(m->xedd, ops[0], sizeof(ops[0])));
|
ASSERT_EQ(0, xed_instruction_length_decode(m->xedd, ops[0], sizeof(ops[0])));
|
||||||
EXPECT_EQ(0x100000001, ComputeAddress(m));
|
EXPECT_EQ(0x100000001, ComputeAddress(m, m->xedd->op.rde));
|
||||||
xed_decoded_inst_zero_set_mode(m->xedd, XED_MACHINE_MODE_LONG_64);
|
xed_decoded_inst_zero_set_mode(m->xedd, XED_MACHINE_MODE_LONG_64);
|
||||||
ASSERT_EQ(0, xed_instruction_length_decode(m->xedd, ops[1], sizeof(ops[1])));
|
ASSERT_EQ(0, xed_instruction_length_decode(m->xedd, ops[1], sizeof(ops[1])));
|
||||||
EXPECT_EQ(0x000000001, ComputeAddress(m));
|
EXPECT_EQ(0x000000001, ComputeAddress(m, m->xedd->op.rde));
|
||||||
xed_decoded_inst_zero_set_mode(m->xedd, XED_MACHINE_MODE_LONG_64);
|
xed_decoded_inst_zero_set_mode(m->xedd, XED_MACHINE_MODE_LONG_64);
|
||||||
ASSERT_EQ(0, xed_instruction_length_decode(m->xedd, ops[2], sizeof(ops[2])));
|
ASSERT_EQ(0, xed_instruction_length_decode(m->xedd, ops[2], sizeof(ops[2])));
|
||||||
EXPECT_EQ(0x31339, ComputeAddress(m));
|
EXPECT_EQ(0x31339, ComputeAddress(m, m->xedd->op.rde));
|
||||||
xed_decoded_inst_zero_set_mode(m->xedd, XED_MACHINE_MODE_LONG_64);
|
xed_decoded_inst_zero_set_mode(m->xedd, XED_MACHINE_MODE_LONG_64);
|
||||||
ASSERT_EQ(0, xed_instruction_length_decode(m->xedd, ops[3], sizeof(ops[3])));
|
ASSERT_EQ(0, xed_instruction_length_decode(m->xedd, ops[3], sizeof(ops[3])));
|
||||||
EXPECT_EQ(0x31337, ComputeAddress(m));
|
EXPECT_EQ(0x31337, ComputeAddress(m, m->xedd->op.rde));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(modrm, testSibIndexOnly) {
|
TEST(modrm, testSibIndexOnly) {
|
||||||
|
@ -101,5 +102,5 @@ TEST(modrm, testSibIndexOnly) {
|
||||||
Write64(m->cx, 0x123);
|
Write64(m->cx, 0x123);
|
||||||
xed_decoded_inst_zero_set_mode(xedd, XED_MACHINE_MODE_LONG_64);
|
xed_decoded_inst_zero_set_mode(xedd, XED_MACHINE_MODE_LONG_64);
|
||||||
ASSERT_EQ(0, xed_instruction_length_decode(xedd, op, sizeof(op)));
|
ASSERT_EQ(0, xed_instruction_length_decode(xedd, op, sizeof(op)));
|
||||||
EXPECT_EQ(0x123 * 4, (uint64_t)ComputeAddress(m));
|
EXPECT_EQ(0x123 * 4, (uint64_t)ComputeAddress(m, m->xedd->op.rde));
|
||||||
}
|
}
|
||||||
|
|
2
third_party/compiler_rt/divmodti4.c
vendored
2
third_party/compiler_rt/divmodti4.c
vendored
|
@ -24,7 +24,7 @@ COMPILER_RT_ABI ti_int __divmodti4(ti_int a, ti_int b, tu_int *opt_out_rem) {
|
||||||
tu_int r;
|
tu_int r;
|
||||||
ti_int sa, sb, sq, sr, x, y, q;
|
ti_int sa, sb, sq, sr, x, y, q;
|
||||||
k = sizeof(ti_int) * CHAR_BIT - 1;
|
k = sizeof(ti_int) * CHAR_BIT - 1;
|
||||||
if (b < 0 && a == ((ti_int)1 << k)) {
|
if (b == -1 && a == ((ti_int)1 << k)) {
|
||||||
volatile int x = 0;
|
volatile int x = 0;
|
||||||
x = 1 / x; // raise(SIGFPE)
|
x = 1 / x; // raise(SIGFPE)
|
||||||
}
|
}
|
||||||
|
|
7
third_party/xed/x86.h
vendored
7
third_party/xed/x86.h
vendored
|
@ -493,16 +493,15 @@ forceinline void xed_set_chip_modes(struct XedDecodedInst *d,
|
||||||
extern const char kXedErrorNames[];
|
extern const char kXedErrorNames[];
|
||||||
extern const uint64_t xed_chip_features[XED_CHIP_LAST][3];
|
extern const uint64_t xed_chip_features[XED_CHIP_LAST][3];
|
||||||
|
|
||||||
|
struct XedDecodedInst *xed_decoded_inst_zero_set_mode(struct XedDecodedInst *,
|
||||||
|
enum XedMachineMode);
|
||||||
|
|
||||||
enum XedError xed_instruction_length_decode(struct XedDecodedInst *,
|
enum XedError xed_instruction_length_decode(struct XedDecodedInst *,
|
||||||
const void *, size_t);
|
const void *, size_t);
|
||||||
enum XedError __xed_instruction_length_decode(struct XedDecodedInst *,
|
|
||||||
const void *, size_t);
|
|
||||||
|
|
||||||
bool xed_isa_set_is_valid_for_chip(enum XedIsaSet, enum XedChip);
|
bool xed_isa_set_is_valid_for_chip(enum XedIsaSet, enum XedChip);
|
||||||
bool xed_test_chip_features(struct XedChipFeatures *, enum XedIsaSet);
|
bool xed_test_chip_features(struct XedChipFeatures *, enum XedIsaSet);
|
||||||
void xed_get_chip_features(struct XedChipFeatures *, enum XedChip);
|
void xed_get_chip_features(struct XedChipFeatures *, enum XedChip);
|
||||||
struct XedDecodedInst *xed_decoded_inst_zero_set_mode(struct XedDecodedInst *,
|
|
||||||
enum XedMachineMode);
|
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
8
third_party/xed/x86ild.greg.c
vendored
8
third_party/xed/x86ild.greg.c
vendored
|
@ -375,19 +375,16 @@ privileged static void XED_LF_SIMM8_IMM_WIDTH_CONST_l2(
|
||||||
privileged static void XED_LF_UIMM16_IMM_WIDTH_CONST_l2(
|
privileged static void XED_LF_UIMM16_IMM_WIDTH_CONST_l2(
|
||||||
struct XedDecodedInst *x) {
|
struct XedDecodedInst *x) {
|
||||||
x->op.imm_width = 16;
|
x->op.imm_width = 16;
|
||||||
x->op.imm_signed = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
privileged static void XED_LF_SE_IMM8_IMM_WIDTH_CONST_l2(
|
privileged static void XED_LF_SE_IMM8_IMM_WIDTH_CONST_l2(
|
||||||
struct XedDecodedInst *x) {
|
struct XedDecodedInst *x) {
|
||||||
x->op.imm_width = 8;
|
x->op.imm_width = 8;
|
||||||
x->op.imm_signed = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
privileged static void XED_LF_UIMM32_IMM_WIDTH_CONST_l2(
|
privileged static void XED_LF_UIMM32_IMM_WIDTH_CONST_l2(
|
||||||
struct XedDecodedInst *x) {
|
struct XedDecodedInst *x) {
|
||||||
x->op.imm_width = 32;
|
x->op.imm_width = 32;
|
||||||
x->op.imm_signed = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
privileged static void xed_set_simmz_imm_width_eosz(
|
privileged static void xed_set_simmz_imm_width_eosz(
|
||||||
|
@ -401,18 +398,15 @@ privileged static void xed_set_uimmv_imm_width_eosz(
|
||||||
struct XedDecodedInst *x, const xed_bits_t eosz[2][2][3]) {
|
struct XedDecodedInst *x, const xed_bits_t eosz[2][2][3]) {
|
||||||
x->op.imm_width =
|
x->op.imm_width =
|
||||||
kXed.UIMMv_IMM_WIDTH[eosz[x->op.rexw][x->op.osz][x->op.mode]];
|
kXed.UIMMv_IMM_WIDTH[eosz[x->op.rexw][x->op.osz][x->op.mode]];
|
||||||
x->op.imm_signed = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
privileged static void XED_LF_UIMM8_IMM_WIDTH_CONST_l2(
|
privileged static void XED_LF_UIMM8_IMM_WIDTH_CONST_l2(
|
||||||
struct XedDecodedInst *x) {
|
struct XedDecodedInst *x) {
|
||||||
x->op.imm_width = 8;
|
x->op.imm_width = 8;
|
||||||
x->op.imm_signed = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
privileged static void XED_LF_0_IMM_WIDTH_CONST_l2(struct XedDecodedInst *x) {
|
privileged static void XED_LF_0_IMM_WIDTH_CONST_l2(struct XedDecodedInst *x) {
|
||||||
x->op.imm_width = 0;
|
x->op.imm_width = 0;
|
||||||
x->op.imm_signed = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
privileged static void XED_LF_RESOLVE_BYREG_IMM_WIDTH_map0x0_op0xc7_l1(
|
privileged static void XED_LF_RESOLVE_BYREG_IMM_WIDTH_map0x0_op0xc7_l1(
|
||||||
|
@ -1212,7 +1206,7 @@ privileged static void xed_encode_rde(struct XedDecodedInst *x) {
|
||||||
/**
|
/**
|
||||||
* Clears instruction decoder state.
|
* Clears instruction decoder state.
|
||||||
*/
|
*/
|
||||||
struct XedDecodedInst *xed_decoded_inst_zero_set_mode(
|
privileged struct XedDecodedInst *xed_decoded_inst_zero_set_mode(
|
||||||
struct XedDecodedInst *p, enum XedMachineMode mmode) {
|
struct XedDecodedInst *p, enum XedMachineMode mmode) {
|
||||||
__builtin_memset(p, 0, sizeof(*p));
|
__builtin_memset(p, 0, sizeof(*p));
|
||||||
xed_operands_set_mode(&p->op, mmode);
|
xed_operands_set_mode(&p->op, mmode);
|
||||||
|
|
|
@ -19,8 +19,6 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
|
|
||||||
cmpxchg %ecx,(%rdx)
|
|
||||||
|
|
||||||
.section .start,"ax",@progbits
|
.section .start,"ax",@progbits
|
||||||
emucrt: bofram 9f
|
emucrt: bofram 9f
|
||||||
movslq (%rsp),%rdi # argc
|
movslq (%rsp),%rdi # argc
|
||||||
|
|
|
@ -22,7 +22,7 @@ ENTRY(_start)
|
||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
|
|
||||||
.text : {
|
.text IMAGE_BASE_VIRTUAL : {
|
||||||
*(.start)
|
*(.start)
|
||||||
KEEP(*(.initprologue))
|
KEEP(*(.initprologue))
|
||||||
KEEP(*(SORT_BY_NAME(.init.*)))
|
KEEP(*(SORT_BY_NAME(.init.*)))
|
||||||
|
|
|
@ -5,7 +5,7 @@ PKGS += TOOL_BUILD_EMUCRT
|
||||||
|
|
||||||
TOOL_BUILD_EMUCRT = \
|
TOOL_BUILD_EMUCRT = \
|
||||||
o/$(MODE)/tool/build/emucrt/emucrt.o \
|
o/$(MODE)/tool/build/emucrt/emucrt.o \
|
||||||
tool/build/emucrt/emucrt.lds
|
o/$(MODE)/tool/build/emucrt/emucrt.lds
|
||||||
|
|
||||||
.PHONY: o/$(MODE)/tool/build/emucrt
|
.PHONY: o/$(MODE)/tool/build/emucrt
|
||||||
o/$(MODE)/tool/build/emucrt: \
|
o/$(MODE)/tool/build/emucrt: \
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "libc/alg/arraylist2.h"
|
#include "libc/alg/arraylist2.h"
|
||||||
#include "libc/bits/safemacros.h"
|
#include "libc/bits/safemacros.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/ioctl.h"
|
||||||
#include "libc/calls/struct/sigaction.h"
|
#include "libc/calls/struct/sigaction.h"
|
||||||
#include "libc/calls/struct/stat.h"
|
#include "libc/calls/struct/stat.h"
|
||||||
#include "libc/calls/struct/termios.h"
|
#include "libc/calls/struct/termios.h"
|
||||||
|
@ -51,6 +52,7 @@
|
||||||
#include "libc/sysv/consts/o.h"
|
#include "libc/sysv/consts/o.h"
|
||||||
#include "libc/sysv/consts/poll.h"
|
#include "libc/sysv/consts/poll.h"
|
||||||
#include "libc/sysv/consts/prot.h"
|
#include "libc/sysv/consts/prot.h"
|
||||||
|
#include "libc/sysv/consts/sa.h"
|
||||||
#include "libc/sysv/consts/sig.h"
|
#include "libc/sysv/consts/sig.h"
|
||||||
#include "libc/sysv/consts/termios.h"
|
#include "libc/sysv/consts/termios.h"
|
||||||
#include "libc/unicode/unicode.h"
|
#include "libc/unicode/unicode.h"
|
||||||
|
@ -61,6 +63,7 @@
|
||||||
#include "tool/build/lib/case.h"
|
#include "tool/build/lib/case.h"
|
||||||
#include "tool/build/lib/dis.h"
|
#include "tool/build/lib/dis.h"
|
||||||
#include "tool/build/lib/endian.h"
|
#include "tool/build/lib/endian.h"
|
||||||
|
#include "tool/build/lib/fds.h"
|
||||||
#include "tool/build/lib/flags.h"
|
#include "tool/build/lib/flags.h"
|
||||||
#include "tool/build/lib/fpu.h"
|
#include "tool/build/lib/fpu.h"
|
||||||
#include "tool/build/lib/loader.h"
|
#include "tool/build/lib/loader.h"
|
||||||
|
@ -69,6 +72,7 @@
|
||||||
#include "tool/build/lib/modrm.h"
|
#include "tool/build/lib/modrm.h"
|
||||||
#include "tool/build/lib/panel.h"
|
#include "tool/build/lib/panel.h"
|
||||||
#include "tool/build/lib/pml4t.h"
|
#include "tool/build/lib/pml4t.h"
|
||||||
|
#include "tool/build/lib/pty.h"
|
||||||
#include "tool/build/lib/stats.h"
|
#include "tool/build/lib/stats.h"
|
||||||
#include "tool/build/lib/throw.h"
|
#include "tool/build/lib/throw.h"
|
||||||
|
|
||||||
|
@ -103,6 +107,15 @@ PERFORMANCE\n\
|
||||||
\n\
|
\n\
|
||||||
1500 MIPS w/ NOP loop\n\
|
1500 MIPS w/ NOP loop\n\
|
||||||
Over 9000 MIPS w/ SIMD & Algorithms\n\
|
Over 9000 MIPS w/ SIMD & Algorithms\n\
|
||||||
|
\n\
|
||||||
|
PROTIP\n\
|
||||||
|
\n\
|
||||||
|
Fix SSH keyboard latency for debugger TUI in CONTINUE mode:\n\
|
||||||
|
\n\
|
||||||
|
sudo sh -c 'echo -n 8192 >/proc/sys/net/core/rmem_default'\n\
|
||||||
|
sudo sh -c 'echo -n 8192 >/proc/sys/net/core/wmem_default'\n\
|
||||||
|
\n\
|
||||||
|
\n\
|
||||||
\n"
|
\n"
|
||||||
|
|
||||||
#define DUMPWIDTH 64
|
#define DUMPWIDTH 64
|
||||||
|
@ -115,8 +128,9 @@ PERFORMANCE\n\
|
||||||
#define FINISH 0x020
|
#define FINISH 0x020
|
||||||
#define FAILURE 0x040
|
#define FAILURE 0x040
|
||||||
#define WINCHED 0x080
|
#define WINCHED 0x080
|
||||||
#define CTRLC 0x100
|
#define INT 0x100
|
||||||
#define QUIT 0x200
|
#define QUIT 0x200
|
||||||
|
#define EXIT 0x400
|
||||||
|
|
||||||
#define CTRL(C) ((C) ^ 0100)
|
#define CTRL(C) ((C) ^ 0100)
|
||||||
#define ALT(C) (('\e' << 010) | (C))
|
#define ALT(C) (('\e' << 010) | (C))
|
||||||
|
@ -131,6 +145,8 @@ struct Panels {
|
||||||
struct Panel maps;
|
struct Panel maps;
|
||||||
struct Panel tracehr;
|
struct Panel tracehr;
|
||||||
struct Panel trace;
|
struct Panel trace;
|
||||||
|
struct Panel terminalhr;
|
||||||
|
struct Panel terminal;
|
||||||
struct Panel registers;
|
struct Panel registers;
|
||||||
struct Panel ssehr;
|
struct Panel ssehr;
|
||||||
struct Panel sse;
|
struct Panel sse;
|
||||||
|
@ -143,7 +159,7 @@ struct Panels {
|
||||||
struct Panel stackhr;
|
struct Panel stackhr;
|
||||||
struct Panel stack;
|
struct Panel stack;
|
||||||
};
|
};
|
||||||
struct Panel p[18];
|
struct Panel p[20];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -164,6 +180,7 @@ static bool colorize;
|
||||||
static long codesize;
|
static long codesize;
|
||||||
static long ssewidth;
|
static long ssewidth;
|
||||||
static char *codepath;
|
static char *codepath;
|
||||||
|
static void *onbusted;
|
||||||
static unsigned focus;
|
static unsigned focus;
|
||||||
static unsigned opline;
|
static unsigned opline;
|
||||||
static bool printstats;
|
static bool printstats;
|
||||||
|
@ -178,11 +195,15 @@ static int64_t writestart;
|
||||||
static int64_t stackstart;
|
static int64_t stackstart;
|
||||||
static struct DisHigh high;
|
static struct DisHigh high;
|
||||||
static struct Machine m[2];
|
static struct Machine m[2];
|
||||||
|
static struct MachinePty *pty;
|
||||||
static char logpath[PATH_MAX];
|
static char logpath[PATH_MAX];
|
||||||
static char systemfailure[128];
|
static char systemfailure[128];
|
||||||
static struct sigaction oldsig[4];
|
static struct sigaction oldsig[4];
|
||||||
static struct Breakpoints breakpoints;
|
static struct Breakpoints breakpoints;
|
||||||
|
|
||||||
|
static void SetupDraw(void);
|
||||||
|
static void Redraw(void);
|
||||||
|
|
||||||
static uint64_t SignExtend(uint64_t x, uint8_t b) {
|
static uint64_t SignExtend(uint64_t x, uint8_t b) {
|
||||||
uint64_t s;
|
uint64_t s;
|
||||||
s = 1;
|
s = 1;
|
||||||
|
@ -252,13 +273,28 @@ static uint8_t CycleSseWidth(uint8_t w) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int VirtualBing(int64_t v, int c) {
|
static void OnBusted(void) {
|
||||||
uint8_t *p;
|
LOGF("OnBusted");
|
||||||
if ((p = FindReal(m, v))) {
|
CHECK(onbusted);
|
||||||
return bing(p[0], 0);
|
longjmp(onbusted, 1);
|
||||||
} else {
|
|
||||||
return c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int VirtualBing(int64_t v) {
|
||||||
|
int rc;
|
||||||
|
uint8_t *p;
|
||||||
|
jmp_buf busted;
|
||||||
|
onbusted = busted;
|
||||||
|
if ((p = FindReal(m, v))) {
|
||||||
|
if (!setjmp(busted)) {
|
||||||
|
rc = bing(p[0], 0);
|
||||||
|
} else {
|
||||||
|
rc = u'≀';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rc = u'⋅';
|
||||||
|
}
|
||||||
|
onbusted = NULL;
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ScrollOp(struct Panel *p, long op) {
|
static void ScrollOp(struct Panel *p, long op) {
|
||||||
|
@ -283,29 +319,36 @@ static void GetTtySize(void) {
|
||||||
static void TuiRejuvinate(void) {
|
static void TuiRejuvinate(void) {
|
||||||
GetTtySize();
|
GetTtySize();
|
||||||
ttyhidecursor(STDOUT_FILENO);
|
ttyhidecursor(STDOUT_FILENO);
|
||||||
ttyraw(kTtySigs);
|
ttyraw(0);
|
||||||
|
xsigaction(SIGBUS, OnBusted, SA_NODEFER, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OnCtrlC(void) {
|
static void OnCtrlC(void) {
|
||||||
action |= CTRLC;
|
LOGF("OnCtrlC");
|
||||||
|
action |= INT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnQ(void) {
|
||||||
|
LOGF("OnQ");
|
||||||
|
action |= INT;
|
||||||
|
breakpoints.i = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OnWinch(void) {
|
static void OnWinch(void) {
|
||||||
|
LOGF("OnWinch");
|
||||||
action |= WINCHED;
|
action |= WINCHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OnGdbHandoff(void) {
|
static void OnCont(void) {
|
||||||
|
LOGF("OnCont");
|
||||||
TuiRejuvinate();
|
TuiRejuvinate();
|
||||||
}
|
SetupDraw();
|
||||||
|
Redraw();
|
||||||
static void OnUsr1(void) {
|
|
||||||
if (g_logfile) fflush(g_logfile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TuiCleanup(void) {
|
static void TuiCleanup(void) {
|
||||||
sigaction(SIGWINCH, oldsig + 0, NULL);
|
sigaction(SIGWINCH, oldsig + 0, NULL);
|
||||||
sigaction(SIGCONT, oldsig + 2, NULL);
|
sigaction(SIGCONT, oldsig + 2, NULL);
|
||||||
sigaction(SIGUSR1, oldsig + 3, NULL);
|
|
||||||
ttyraw((enum TtyRawFlags)(-1u));
|
ttyraw((enum TtyRawFlags)(-1u));
|
||||||
ttyshowcursor(STDOUT_FILENO);
|
ttyshowcursor(STDOUT_FILENO);
|
||||||
CHECK_NE(-1, close(ttyfd));
|
CHECK_NE(-1, close(ttyfd));
|
||||||
|
@ -329,7 +372,7 @@ static void ResolveBreakpoints(void) {
|
||||||
|
|
||||||
static void BreakAtNextInstruction(void) {
|
static void BreakAtNextInstruction(void) {
|
||||||
struct Breakpoint b = {.addr = m->ip + m->xedd->length, .oneshot = true};
|
struct Breakpoint b = {.addr = m->ip + m->xedd->length, .oneshot = true};
|
||||||
AddBreakpoint(&breakpoints, &b);
|
PushBreakpoint(&breakpoints, &b);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LoadSyms(void) {
|
static void LoadSyms(void) {
|
||||||
|
@ -347,13 +390,23 @@ static void TuiSetup(void) {
|
||||||
once = true;
|
once = true;
|
||||||
}
|
}
|
||||||
CHECK_NE(-1, (ttyfd = open("/dev/tty", O_RDWR)));
|
CHECK_NE(-1, (ttyfd = open("/dev/tty", O_RDWR)));
|
||||||
xsigaction(SIGWINCH, (void *)OnWinch, 0, 0, oldsig + 0);
|
xsigaction(SIGWINCH, OnWinch, 0, 0, oldsig + 0);
|
||||||
xsigaction(SIGCONT, (void *)OnGdbHandoff, 0, 0, oldsig + 2);
|
xsigaction(SIGCONT, OnCont, SA_RESTART, 0, oldsig + 2);
|
||||||
xsigaction(SIGUSR1, (void *)OnUsr1, 0, 0, oldsig + 3);
|
|
||||||
memcpy(&m[1], &m[0], sizeof(m[0]));
|
memcpy(&m[1], &m[0], sizeof(m[0]));
|
||||||
TuiRejuvinate();
|
TuiRejuvinate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ExecSetup(void) {
|
||||||
|
static bool once;
|
||||||
|
if (!once) {
|
||||||
|
if (breakpoints.i) {
|
||||||
|
LoadSyms();
|
||||||
|
ResolveBreakpoints();
|
||||||
|
}
|
||||||
|
once = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void AppendPanel(struct Panel *p, long line, const char *s) {
|
static void AppendPanel(struct Panel *p, long line, const char *s) {
|
||||||
if (0 <= line && line < p->bottom - p->top) {
|
if (0 <= line && line < p->bottom - p->top) {
|
||||||
AppendStr(&p->lines[line], s);
|
AppendStr(&p->lines[line], s);
|
||||||
|
@ -384,8 +437,8 @@ static int PickNumberOfXmmRegistersToShow(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void StartDraw(void) {
|
static void SetupDraw(void) {
|
||||||
int i, j, n, a, b, cpuy, ssey, dx[2], c2y[2], c3y[5];
|
int i, j, n, a, b, cpuy, ssey, dx[2], c2y[3], c3y[5];
|
||||||
|
|
||||||
for (i = 0; i < ARRAYLEN(pan.p); ++i) {
|
for (i = 0; i < ARRAYLEN(pan.p); ++i) {
|
||||||
n = pan.p[i].bottom - pan.p[i].top;
|
n = pan.p[i].bottom - pan.p[i].top;
|
||||||
|
@ -404,9 +457,11 @@ static void StartDraw(void) {
|
||||||
dx[1] = txn >= a + b ? txn - a : txn;
|
dx[1] = txn >= a + b ? txn - a : txn;
|
||||||
dx[0] = txn >= a + b + b ? txn - a - b : dx[1];
|
dx[0] = txn >= a + b + b ? txn - a - b : dx[1];
|
||||||
|
|
||||||
a = tyn / 3;
|
a = 1 / 8. * tyn;
|
||||||
|
b = 3 / 8. * tyn;
|
||||||
c2y[0] = a;
|
c2y[0] = a;
|
||||||
c2y[1] = a * 2;
|
c2y[1] = a * 2;
|
||||||
|
c2y[2] = a * 2 + b;
|
||||||
|
|
||||||
a = (tyn - (cpuy + ssey) - 3) / 4;
|
a = (tyn - (cpuy + ssey) - 3) / 4;
|
||||||
c3y[0] = cpuy;
|
c3y[0] = cpuy;
|
||||||
|
@ -422,7 +477,7 @@ static void StartDraw(void) {
|
||||||
pan.disassembly.bottom = tyn;
|
pan.disassembly.bottom = tyn;
|
||||||
pan.disassembly.right = dx[0];
|
pan.disassembly.right = dx[0];
|
||||||
|
|
||||||
/* COLUMN #2: BREAKPOINTS, MEMORY MAPS, BACKTRACE */
|
/* COLUMN #2: BREAKPOINTS, MEMORY MAPS, BACKTRACE, TERMINAL */
|
||||||
|
|
||||||
pan.breakpointshr.top = 0;
|
pan.breakpointshr.top = 0;
|
||||||
pan.breakpointshr.left = dx[0];
|
pan.breakpointshr.left = dx[0];
|
||||||
|
@ -451,9 +506,19 @@ static void StartDraw(void) {
|
||||||
|
|
||||||
pan.trace.top = c2y[1] + 1;
|
pan.trace.top = c2y[1] + 1;
|
||||||
pan.trace.left = dx[0];
|
pan.trace.left = dx[0];
|
||||||
pan.trace.bottom = tyn;
|
pan.trace.bottom = c2y[2];
|
||||||
pan.trace.right = dx[1] - 1;
|
pan.trace.right = dx[1] - 1;
|
||||||
|
|
||||||
|
pan.terminalhr.top = c2y[2];
|
||||||
|
pan.terminalhr.left = dx[0];
|
||||||
|
pan.terminalhr.bottom = c2y[2] + 1;
|
||||||
|
pan.terminalhr.right = dx[1] - 1;
|
||||||
|
|
||||||
|
pan.terminal.top = c2y[2] + 1;
|
||||||
|
pan.terminal.left = dx[0];
|
||||||
|
pan.terminal.bottom = tyn;
|
||||||
|
pan.terminal.right = dx[1] - 1;
|
||||||
|
|
||||||
/* COLUMN #3: REGISTERS, VECTORS, CODE, MEMORY READS, MEMORY WRITES, STACK */
|
/* COLUMN #3: REGISTERS, VECTORS, CODE, MEMORY READS, MEMORY WRITES, STACK */
|
||||||
|
|
||||||
pan.registers.top = 0;
|
pan.registers.top = 0;
|
||||||
|
@ -517,6 +582,14 @@ static void StartDraw(void) {
|
||||||
pan.p[i].lines =
|
pan.p[i].lines =
|
||||||
xcalloc(pan.p[i].bottom - pan.p[i].top, sizeof(struct Buffer));
|
xcalloc(pan.p[i].bottom - pan.p[i].top, sizeof(struct Buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pty->yn != pan.terminal.bottom - pan.terminal.top ||
|
||||||
|
pty->xn != pan.terminal.right - pan.terminal.left) {
|
||||||
|
LOGF("MachinePtyNew");
|
||||||
|
MachinePtyFree(pty);
|
||||||
|
pty = MachinePtyNew(pan.terminal.bottom - pan.terminal.top,
|
||||||
|
pan.terminal.right - pan.terminal.left);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static long GetDisIndex(int64_t addr) {
|
static long GetDisIndex(int64_t addr) {
|
||||||
|
@ -541,6 +614,13 @@ static void DrawDisassembly(struct Panel *p) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void DrawTerminal(struct Panel *p) {
|
||||||
|
long y, yn;
|
||||||
|
for (yn = MIN(pty->yn, p->bottom - p->top), y = 0; y < yn; ++y) {
|
||||||
|
MachinePtyAppendLine(pty, p->lines + y, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void DrawFlag(struct Panel *p, long i, char *name, bool value,
|
static void DrawFlag(struct Panel *p, long i, char *name, bool value,
|
||||||
bool previous) {
|
bool previous) {
|
||||||
AppendPanel(p, i, " ");
|
AppendPanel(p, i, " ");
|
||||||
|
@ -599,30 +679,14 @@ static void DrawHr(struct Panel *p, const char *s) {
|
||||||
|
|
||||||
static void DrawCpu(struct Panel *p) {
|
static void DrawCpu(struct Panel *p) {
|
||||||
char buf[48];
|
char buf[48];
|
||||||
DrawRegister(p, 0, 7);
|
DrawRegister(p, 0, 7), DrawRegister(p, 0, 0), DrawSt(p, 0, 0);
|
||||||
DrawRegister(p, 0, 0);
|
DrawRegister(p, 1, 6), DrawRegister(p, 1, 3), DrawSt(p, 1, 1);
|
||||||
DrawSt(p, 0, 0);
|
DrawRegister(p, 2, 2), DrawRegister(p, 2, 5), DrawSt(p, 2, 2);
|
||||||
DrawRegister(p, 1, 6);
|
DrawRegister(p, 3, 1), DrawRegister(p, 3, 4), DrawSt(p, 3, 3);
|
||||||
DrawRegister(p, 1, 3);
|
DrawRegister(p, 4, 8), DrawRegister(p, 4, 12), DrawSt(p, 4, 4);
|
||||||
DrawSt(p, 1, 1);
|
DrawRegister(p, 5, 9), DrawRegister(p, 5, 13), DrawSt(p, 5, 5);
|
||||||
DrawRegister(p, 2, 2);
|
DrawRegister(p, 6, 10), DrawRegister(p, 6, 14), DrawSt(p, 6, 6);
|
||||||
DrawRegister(p, 2, 5);
|
DrawRegister(p, 7, 11), DrawRegister(p, 7, 15), DrawSt(p, 7, 7);
|
||||||
DrawSt(p, 2, 2);
|
|
||||||
DrawRegister(p, 3, 1);
|
|
||||||
DrawRegister(p, 3, 4);
|
|
||||||
DrawSt(p, 3, 3);
|
|
||||||
DrawRegister(p, 4, 8);
|
|
||||||
DrawRegister(p, 4, 12);
|
|
||||||
DrawSt(p, 4, 4);
|
|
||||||
DrawRegister(p, 5, 9);
|
|
||||||
DrawRegister(p, 5, 13);
|
|
||||||
DrawSt(p, 5, 5);
|
|
||||||
DrawRegister(p, 6, 10);
|
|
||||||
DrawRegister(p, 6, 14);
|
|
||||||
DrawSt(p, 6, 6);
|
|
||||||
DrawRegister(p, 7, 11);
|
|
||||||
DrawRegister(p, 7, 15);
|
|
||||||
DrawSt(p, 7, 7);
|
|
||||||
snprintf(buf, sizeof(buf), "RIP 0x%016x FLG", m[0].ip);
|
snprintf(buf, sizeof(buf), "RIP 0x%016x FLG", m[0].ip);
|
||||||
AppendPanel(p, 8, buf);
|
AppendPanel(p, 8, buf);
|
||||||
DrawFlag(p, 8, "C", GetFlag(m[0].flags, FLAGS_CF),
|
DrawFlag(p, 8, "C", GetFlag(m[0].flags, FLAGS_CF),
|
||||||
|
@ -766,7 +830,7 @@ static void DrawMemory(struct Panel *p, long beg, long a, long b) {
|
||||||
AppendStr(&p->lines[i], buf);
|
AppendStr(&p->lines[i], buf);
|
||||||
for (j = 0; j < DUMPWIDTH; ++j) {
|
for (j = 0; j < DUMPWIDTH; ++j) {
|
||||||
k = (beg + i) * DUMPWIDTH + j;
|
k = (beg + i) * DUMPWIDTH + j;
|
||||||
c = VirtualBing(k, L'⋅');
|
c = VirtualBing(k);
|
||||||
changed = a <= k && k < b;
|
changed = a <= k && k < b;
|
||||||
if (changed && !high) {
|
if (changed && !high) {
|
||||||
high = true;
|
high = true;
|
||||||
|
@ -800,7 +864,7 @@ static void DrawBreakpoints(struct Panel *p) {
|
||||||
char buf[128];
|
char buf[128];
|
||||||
const char *name;
|
const char *name;
|
||||||
long i, line, sym;
|
long i, line, sym;
|
||||||
for (line = i = 0; i < breakpoints.i; ++i) {
|
for (line = 0, i = breakpoints.i; i--;) {
|
||||||
if (breakpoints.p[i].disable) continue;
|
if (breakpoints.p[i].disable) continue;
|
||||||
addr = breakpoints.p[i].addr;
|
addr = breakpoints.p[i].addr;
|
||||||
sym = DisFindSym(dis, addr);
|
sym = DisFindSym(dis, addr);
|
||||||
|
@ -885,7 +949,14 @@ forceinline void CheckFramePointer(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Redraw(void) {
|
static void Redraw(void) {
|
||||||
|
int i, j;
|
||||||
|
for (i = 0; i < ARRAYLEN(pan.p); ++i) {
|
||||||
|
for (j = 0; j < pan.p[i].bottom - pan.p[i].top; ++j) {
|
||||||
|
pan.p[i].lines[j].i = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
DrawDisassembly(&pan.disassembly);
|
DrawDisassembly(&pan.disassembly);
|
||||||
|
DrawTerminal(&pan.terminal);
|
||||||
DrawCpu(&pan.registers);
|
DrawCpu(&pan.registers);
|
||||||
DrawSse(&pan.sse);
|
DrawSse(&pan.sse);
|
||||||
ScrollCode(&pan.code);
|
ScrollCode(&pan.code);
|
||||||
|
@ -895,6 +966,7 @@ static void Redraw(void) {
|
||||||
DrawHr(&pan.breakpointshr, "BREAKPOINTS");
|
DrawHr(&pan.breakpointshr, "BREAKPOINTS");
|
||||||
DrawHr(&pan.mapshr, "MAPS");
|
DrawHr(&pan.mapshr, "MAPS");
|
||||||
DrawHr(&pan.tracehr, m->bofram[0] ? "PROTECTED FRAMES" : "FRAMES");
|
DrawHr(&pan.tracehr, m->bofram[0] ? "PROTECTED FRAMES" : "FRAMES");
|
||||||
|
DrawHr(&pan.terminalhr, "TELETYPEWRITER");
|
||||||
DrawHr(&pan.ssehr, "SSE");
|
DrawHr(&pan.ssehr, "SSE");
|
||||||
DrawHr(&pan.codehr, "CODE");
|
DrawHr(&pan.codehr, "CODE");
|
||||||
DrawHr(&pan.readhr, "READ");
|
DrawHr(&pan.readhr, "READ");
|
||||||
|
@ -908,8 +980,34 @@ static void Redraw(void) {
|
||||||
DrawMemory(&pan.writedata, writestart, m->writeaddr,
|
DrawMemory(&pan.writedata, writestart, m->writeaddr,
|
||||||
m->writeaddr + m->writesize);
|
m->writeaddr + m->writesize);
|
||||||
DrawMemory(&pan.stack, stackstart, Read64(m->sp), Read64(m->sp) + 8);
|
DrawMemory(&pan.stack, stackstart, Read64(m->sp), Read64(m->sp) + 8);
|
||||||
CHECK_NE(-1, PrintPanels(ttyfd, ARRAYLEN(pan.p), pan.p, tyn, txn));
|
if (PrintPanels(ttyfd, ARRAYLEN(pan.p), pan.p, tyn, txn) == -1) {
|
||||||
|
LOGF("PrintPanels Interrupted");
|
||||||
|
CHECK_EQ(EINTR, errno);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int OnPtyFdClose(int fd) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t OnPtyFdRead(int fd, void *data, size_t size) {
|
||||||
|
return read(fd, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t OnPtyFdWrite(int fd, const void *data, size_t size) {
|
||||||
|
if (tuimode) {
|
||||||
|
return MachinePtyWrite(pty, data, size);
|
||||||
|
} else {
|
||||||
|
MachinePtyWrite(pty, data, size);
|
||||||
|
return write(fd, data, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct MachineFdCb kMachineFdCbPty = {
|
||||||
|
.close = OnPtyFdClose,
|
||||||
|
.read = OnPtyFdRead,
|
||||||
|
.write = OnPtyFdWrite,
|
||||||
|
};
|
||||||
|
|
||||||
static void LaunchDebuggerReactively(void) {
|
static void LaunchDebuggerReactively(void) {
|
||||||
LOGF("%s", systemfailure);
|
LOGF("%s", systemfailure);
|
||||||
|
@ -948,6 +1046,7 @@ static void OnSimdException(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OnUndefinedInstruction(void) {
|
static void OnUndefinedInstruction(void) {
|
||||||
|
die();
|
||||||
strcpy(systemfailure, "UNDEFINED INSTRUCTION");
|
strcpy(systemfailure, "UNDEFINED INSTRUCTION");
|
||||||
LaunchDebuggerReactively();
|
LaunchDebuggerReactively();
|
||||||
}
|
}
|
||||||
|
@ -968,6 +1067,11 @@ static void OnFpuException(void) {
|
||||||
LaunchDebuggerReactively();
|
LaunchDebuggerReactively();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void OnExit(int rc) {
|
||||||
|
exitcode = rc;
|
||||||
|
action |= EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
static void OnHalt(int interrupt) {
|
static void OnHalt(int interrupt) {
|
||||||
switch (interrupt) {
|
switch (interrupt) {
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -998,8 +1102,7 @@ static void OnHalt(int interrupt) {
|
||||||
case kMachineExit:
|
case kMachineExit:
|
||||||
case kMachineHalt:
|
case kMachineHalt:
|
||||||
default:
|
default:
|
||||||
exitcode = interrupt;
|
OnExit(interrupt);
|
||||||
action |= QUIT;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1134,7 +1237,7 @@ static void ReadKeyboard(void) {
|
||||||
if ((rc = read(ttyfd, b, 16)) != -1) {
|
if ((rc = read(ttyfd, b, 16)) != -1) {
|
||||||
for (n = rc, i = 0; i < n; ++i) {
|
for (n = rc, i = 0; i < n; ++i) {
|
||||||
switch (b[i++]) {
|
switch (b[i++]) {
|
||||||
CASE('q', OnQuit());
|
CASE('q', OnQ());
|
||||||
CASE('s', OnStep());
|
CASE('s', OnStep());
|
||||||
CASE('n', OnNext());
|
CASE('n', OnNext());
|
||||||
CASE('f', OnFinish());
|
CASE('f', OnFinish());
|
||||||
|
@ -1145,9 +1248,14 @@ static void ReadKeyboard(void) {
|
||||||
CASE('w', OnSseWidth());
|
CASE('w', OnSseWidth());
|
||||||
CASE('u', OnUp());
|
CASE('u', OnUp());
|
||||||
CASE('d', OnDown());
|
CASE('d', OnDown());
|
||||||
|
CASE('B', PopBreakpoint(&breakpoints));
|
||||||
CASE('\t', OnTab());
|
CASE('\t', OnTab());
|
||||||
CASE('\r', OnEnter());
|
CASE('\r', OnEnter());
|
||||||
CASE('\n', OnEnter());
|
CASE('\n', OnEnter());
|
||||||
|
CASE(CTRL('C'), OnCtrlC());
|
||||||
|
CASE(CTRL('D'), OnCtrlC());
|
||||||
|
CASE(CTRL('\\'), OnQuit());
|
||||||
|
CASE(CTRL('Z'), raise(SIGSTOP));
|
||||||
CASE(CTRL('L'), OnFeed());
|
CASE(CTRL('L'), OnFeed());
|
||||||
CASE(CTRL('P'), OnUpArrow());
|
CASE(CTRL('P'), OnUpArrow());
|
||||||
CASE(CTRL('N'), OnDownArrow());
|
CASE(CTRL('N'), OnDownArrow());
|
||||||
|
@ -1215,8 +1323,13 @@ static void ReadKeyboard(void) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (errno == EINTR) {
|
||||||
|
LOGF("ReadKeyboard Interrupted");
|
||||||
|
} else if (errno == EAGAIN) {
|
||||||
|
poll((struct pollfd[]){{ttyfd, POLLIN}}, 1, -1);
|
||||||
} else {
|
} else {
|
||||||
CHECK_EQ(EINTR, errno);
|
perror("ReadKeyboard");
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1240,7 +1353,7 @@ static void HandleBreakpointFlag(const char *s) {
|
||||||
} else {
|
} else {
|
||||||
b.symbol = optarg;
|
b.symbol = optarg;
|
||||||
}
|
}
|
||||||
AddBreakpoint(&breakpoints, &b);
|
PushBreakpoint(&breakpoints, &b);
|
||||||
}
|
}
|
||||||
|
|
||||||
static noreturn void PrintUsage(int rc, FILE *f) {
|
static noreturn void PrintUsage(int rc, FILE *f) {
|
||||||
|
@ -1253,13 +1366,170 @@ static void LeaveScreen(void) {
|
||||||
write(ttyfd, buf, sprintf(buf, "\e[%d;%dH\e[S\r\n", tyn - 1, txn - 1));
|
write(ttyfd, buf, sprintf(buf, "\e[%d;%dH\e[S\r\n", tyn - 1, txn - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void Exec(void) {
|
||||||
|
long op;
|
||||||
|
ssize_t bp;
|
||||||
|
int interrupt;
|
||||||
|
ExecSetup();
|
||||||
|
if (!(interrupt = setjmp(m->onhalt))) {
|
||||||
|
if ((bp = IsAtBreakpoint(&breakpoints, m->ip)) != -1) {
|
||||||
|
LOGF("BREAK %p", breakpoints.p[bp].addr);
|
||||||
|
tuimode = true;
|
||||||
|
LoadInstruction(m);
|
||||||
|
ExecuteInstruction(m);
|
||||||
|
CheckFramePointer();
|
||||||
|
ops++;
|
||||||
|
} else {
|
||||||
|
for (;;) {
|
||||||
|
LoadInstruction(m);
|
||||||
|
ExecuteInstruction(m);
|
||||||
|
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, m->ip)) != -1) {
|
||||||
|
LOGF("BREAK %p", breakpoints.p[bp].addr);
|
||||||
|
tuimode = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
OnHalt(interrupt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Tui(void) {
|
||||||
|
long op;
|
||||||
|
ssize_t bp;
|
||||||
|
int interrupt;
|
||||||
|
LOGF("TUI");
|
||||||
|
TuiSetup();
|
||||||
|
SetupDraw();
|
||||||
|
ScrollOp(&pan.disassembly, GetDisIndex(m->ip));
|
||||||
|
if (!(interrupt = setjmp(m->onhalt))) {
|
||||||
|
for (;;) {
|
||||||
|
if (!(action & FAILURE)) {
|
||||||
|
LoadInstruction(m);
|
||||||
|
} else {
|
||||||
|
m->xedd = m->icache;
|
||||||
|
m->xedd->length = 1;
|
||||||
|
m->xedd->bytes[0] = 0xCC;
|
||||||
|
m->xedd->op.opcode = 0xCC;
|
||||||
|
}
|
||||||
|
if (action & WINCHED) {
|
||||||
|
LOGF("WINCHED");
|
||||||
|
GetTtySize();
|
||||||
|
action &= ~WINCHED;
|
||||||
|
}
|
||||||
|
SetupDraw();
|
||||||
|
Redraw();
|
||||||
|
if (action & FAILURE) {
|
||||||
|
LOGF("TUI FAILURE");
|
||||||
|
PrintMessageBox(ttyfd, systemfailure, tyn, txn);
|
||||||
|
ReadKeyboard();
|
||||||
|
} else if (!IsExecuting() || HasPendingKeyboard()) {
|
||||||
|
ReadKeyboard();
|
||||||
|
}
|
||||||
|
if (action & INT) {
|
||||||
|
LOGF("TUI INT");
|
||||||
|
action &= ~INT;
|
||||||
|
if (action & (CONTINUE | NEXT | FINISH)) {
|
||||||
|
action &= ~(CONTINUE | NEXT | FINISH);
|
||||||
|
} else {
|
||||||
|
tuimode = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (action & EXIT) {
|
||||||
|
LeaveScreen();
|
||||||
|
LOGF("TUI EXIT");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (action & QUIT) {
|
||||||
|
LOGF("TUI QUIT");
|
||||||
|
action &= ~QUIT;
|
||||||
|
raise(SIGQUIT);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (action & RESTART) {
|
||||||
|
LOGF("TUI RESTART");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (IsExecuting()) {
|
||||||
|
op = GetDisIndex(m->ip);
|
||||||
|
ScrollOp(&pan.disassembly, op);
|
||||||
|
VERBOSEF("%s", dis->ops.p[op].s);
|
||||||
|
memcpy(&m[1], &m[0], sizeof(m[0]));
|
||||||
|
if (!(action & CONTINUE)) {
|
||||||
|
action &= ~STEP;
|
||||||
|
if (action & NEXT) {
|
||||||
|
action &= ~NEXT;
|
||||||
|
if (IsCall()) {
|
||||||
|
BreakAtNextInstruction();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (action & FINISH) {
|
||||||
|
if (IsCall()) {
|
||||||
|
BreakAtNextInstruction();
|
||||||
|
break;
|
||||||
|
} else if (IsRet()) {
|
||||||
|
action &= ~FINISH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!IsDebugBreak()) {
|
||||||
|
ExecuteInstruction(m);
|
||||||
|
} else {
|
||||||
|
m->ip += m->xedd->length;
|
||||||
|
action &= ~NEXT;
|
||||||
|
action &= ~FINISH;
|
||||||
|
action &= ~CONTINUE;
|
||||||
|
}
|
||||||
|
CheckFramePointer();
|
||||||
|
ops++;
|
||||||
|
if (!(action & CONTINUE)) {
|
||||||
|
ScrollOp(&pan.disassembly, GetDisIndex(m->ip));
|
||||||
|
if ((action & FINISH) && IsRet()) action &= ~FINISH;
|
||||||
|
if (((action & NEXT) && IsRet()) || (action & FINISH)) {
|
||||||
|
action &= ~NEXT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((action & (FINISH | NEXT | CONTINUE)) &&
|
||||||
|
(bp = IsAtBreakpoint(&breakpoints, m->ip)) != -1) {
|
||||||
|
action &= ~(FINISH | NEXT | CONTINUE);
|
||||||
|
LOGF("BREAK %p", breakpoints.p[bp].addr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
OnHalt(interrupt);
|
||||||
|
ScrollOp(&pan.disassembly, GetDisIndex(m->ip));
|
||||||
|
}
|
||||||
|
TuiCleanup();
|
||||||
|
}
|
||||||
|
|
||||||
static void GetOpts(int argc, char *argv[]) {
|
static void GetOpts(int argc, char *argv[]) {
|
||||||
int opt;
|
int opt;
|
||||||
stpcpy(stpcpy(stpcpy(logpath, kTmpPath), basename(argv[0])), ".log");
|
stpcpy(stpcpy(stpcpy(logpath, kTmpPath), basename(argv[0])), ".log");
|
||||||
while ((opt = getopt(argc, argv, "?hvtrsb:HL:")) != -1) {
|
while ((opt = getopt(argc, argv, "?hvtrsb:HL:")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 't':
|
case 't':
|
||||||
react = true;
|
|
||||||
tuimode = true;
|
tuimode = true;
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
|
@ -1288,166 +1558,44 @@ static void GetOpts(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_logfile = fopen(logpath, "a");
|
g_logfile = fopen(logpath, "a");
|
||||||
|
setvbuf(g_logfile, xmalloc(PAGESIZE), _IOLBF, PAGESIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Emulator(int argc, char *argv[]) {
|
int Emulator(int argc, char *argv[]) {
|
||||||
long op;
|
|
||||||
void *code;
|
void *code;
|
||||||
ssize_t bp;
|
int rc, fd;
|
||||||
int rc, fd, interrupt;
|
|
||||||
|
|
||||||
codepath = argv[optind++];
|
codepath = argv[optind++];
|
||||||
|
pty = MachinePtyNew(20, 80);
|
||||||
|
InitMachine(m);
|
||||||
|
m->fds.p = xcalloc((m->fds.n = 8), sizeof(struct MachineFd));
|
||||||
Restart:
|
Restart:
|
||||||
action = 0;
|
action = 0;
|
||||||
LoadProgram(m, codepath, argv + optind, environ, elf);
|
LoadProgram(m, codepath, argv + optind, environ, elf);
|
||||||
|
m->fds.i = 3;
|
||||||
if (!tuimode && breakpoints.i) {
|
m->fds.p[0].fd = STDIN_FILENO;
|
||||||
LoadSyms();
|
m->fds.p[0].cb = &kMachineFdCbPty;
|
||||||
ResolveBreakpoints();
|
m->fds.p[1].fd = STDOUT_FILENO;
|
||||||
}
|
m->fds.p[1].cb = &kMachineFdCbPty;
|
||||||
|
m->fds.p[2].fd = STDERR_FILENO;
|
||||||
while (!(action & QUIT)) {
|
m->fds.p[2].cb = &kMachineFdCbPty;
|
||||||
|
while (!(action & EXIT)) {
|
||||||
if (!tuimode) {
|
if (!tuimode) {
|
||||||
if (!(interrupt = setjmp(m->onhalt))) {
|
Exec();
|
||||||
for (;;) {
|
|
||||||
if (action || breakpoints.i) {
|
|
||||||
if (action & QUIT) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (action & CTRLC) {
|
|
||||||
if (react) {
|
|
||||||
LOGF("CTRLC EXEC REACT");
|
|
||||||
action &= ~(CTRLC | STEP | FINISH | NEXT);
|
|
||||||
tuimode = true;
|
|
||||||
} else {
|
} else {
|
||||||
LOGF("CTRLC EXEC");
|
Tui();
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((bp = IsAtBreakpoint(&breakpoints, m->ip)) != -1) {
|
|
||||||
LOGF("BREAK %p", breakpoints.p[bp].addr);
|
|
||||||
tuimode = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LoadInstruction(m);
|
|
||||||
ExecuteInstruction(m);
|
|
||||||
CheckFramePointer();
|
|
||||||
ops++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
OnHalt(interrupt);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LOGF("TUI");
|
|
||||||
TuiSetup();
|
|
||||||
StartDraw();
|
|
||||||
ScrollOp(&pan.disassembly, GetDisIndex(m->ip));
|
|
||||||
if (!(interrupt = setjmp(m->onhalt))) {
|
|
||||||
for (;;) {
|
|
||||||
if (!(action & FAILURE)) {
|
|
||||||
LoadInstruction(m);
|
|
||||||
} else {
|
|
||||||
m->xedd = m->icache;
|
|
||||||
m->xedd->length = 1;
|
|
||||||
m->xedd->bytes[0] = 0xCC;
|
|
||||||
m->xedd->op.opcode = 0xCC;
|
|
||||||
}
|
|
||||||
if (action & WINCHED) {
|
|
||||||
LOGF("WINCHED");
|
|
||||||
GetTtySize();
|
|
||||||
action &= ~WINCHED;
|
|
||||||
}
|
|
||||||
StartDraw();
|
|
||||||
Redraw();
|
|
||||||
if (action & FAILURE) {
|
|
||||||
LOGF("FAILURE");
|
|
||||||
PrintMessageBox(ttyfd, systemfailure, tyn, txn);
|
|
||||||
ReadKeyboard();
|
|
||||||
} else if (!IsExecuting() || HasPendingKeyboard()) {
|
|
||||||
ReadKeyboard();
|
|
||||||
}
|
|
||||||
if (action & CTRLC) {
|
|
||||||
LOGF("CTRLC TUI");
|
|
||||||
action |= QUIT;
|
|
||||||
}
|
|
||||||
if (action & QUIT) {
|
|
||||||
LeaveScreen();
|
|
||||||
LOGF("QUIT2");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (action & RESTART) {
|
if (action & RESTART) {
|
||||||
LOGF("RESTART");
|
|
||||||
goto Restart;
|
goto Restart;
|
||||||
}
|
}
|
||||||
if (action & CONTINUE) {
|
|
||||||
LOGF("CONTINUE");
|
|
||||||
action &= ~CONTINUE;
|
|
||||||
tuimode = false;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (IsExecuting()) {
|
|
||||||
op = GetDisIndex(m->ip);
|
|
||||||
ScrollOp(&pan.disassembly, op);
|
|
||||||
LOGF("%s", dis->ops.p[op].s);
|
|
||||||
memcpy(&m[1], &m[0], sizeof(m[0]));
|
|
||||||
action &= ~STEP;
|
|
||||||
if (action & NEXT) {
|
|
||||||
action &= ~NEXT;
|
|
||||||
if (IsCall()) {
|
|
||||||
BreakAtNextInstruction();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (action & FINISH) {
|
|
||||||
if (IsCall()) {
|
|
||||||
BreakAtNextInstruction();
|
|
||||||
break;
|
|
||||||
} else if (IsRet()) {
|
|
||||||
action &= ~FINISH;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!IsDebugBreak()) {
|
|
||||||
ExecuteInstruction(m);
|
|
||||||
} else {
|
|
||||||
m->ip += m->xedd->length;
|
|
||||||
action &= ~NEXT;
|
|
||||||
action &= ~FINISH;
|
|
||||||
}
|
|
||||||
CheckFramePointer();
|
|
||||||
ops++;
|
|
||||||
ScrollOp(&pan.disassembly, GetDisIndex(m->ip));
|
|
||||||
if ((action & FINISH) && IsRet()) action &= ~FINISH;
|
|
||||||
if (((action & NEXT) && IsRet()) || (action & FINISH)) {
|
|
||||||
action &= ~NEXT;
|
|
||||||
}
|
|
||||||
if ((action & (FINISH | NEXT)) &&
|
|
||||||
(bp = IsAtBreakpoint(&breakpoints, m->ip)) != -1) {
|
|
||||||
action &= ~(FINISH | NEXT);
|
|
||||||
LOGF("BREAK %p", breakpoints.p[bp].addr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
OnHalt(interrupt);
|
|
||||||
ScrollOp(&pan.disassembly, GetDisIndex(m->ip));
|
|
||||||
}
|
|
||||||
TuiCleanup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tuimode) {
|
if (tuimode) {
|
||||||
LeaveScreen();
|
LeaveScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (printstats) {
|
if (printstats) {
|
||||||
fprintf(stderr, "taken: %,ld\n", taken);
|
fprintf(stderr, "taken: %,ld\n", taken);
|
||||||
fprintf(stderr, "ntaken: %,ld\n", ntaken);
|
fprintf(stderr, "ntaken: %,ld\n", ntaken);
|
||||||
fprintf(stderr, "ops: %,ld\n", ops);
|
fprintf(stderr, "ops: %,ld\n", ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
munmap(elf->ehdr, elf->size);
|
munmap(elf->ehdr, elf->size);
|
||||||
DisFree(dis);
|
DisFree(dis);
|
||||||
return exitcode;
|
return exitcode;
|
||||||
|
@ -1462,8 +1610,7 @@ static void OnlyRunOnFirstCpu(void) {
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
int rc;
|
int rc;
|
||||||
ssewidth = 2; /* 16-bit is best bit */
|
ssewidth = 2; /* 16-bit is best bit */
|
||||||
showcrashreports();
|
if (!NoDebug()) showcrashreports();
|
||||||
xsigaction(SIGINT, (void *)OnCtrlC, 0, 0, NULL);
|
|
||||||
// OnlyRunOnFirstCpu();
|
// OnlyRunOnFirstCpu();
|
||||||
if ((colorize = cancolor())) {
|
if ((colorize = cancolor())) {
|
||||||
high.keyword = 155;
|
high.keyword = 155;
|
||||||
|
|
|
@ -12,8 +12,6 @@
|
||||||
#define ALU_CMP 7
|
#define ALU_CMP 7
|
||||||
#define ALU_TEST 8
|
#define ALU_TEST 8
|
||||||
#define ALU_FLIP 16
|
#define ALU_FLIP 16
|
||||||
#define ALU_XCHG 64
|
|
||||||
#define ALU_BYTE 128
|
|
||||||
|
|
||||||
#define BSU_ROL 0
|
#define BSU_ROL 0
|
||||||
#define BSU_ROR 1
|
#define BSU_ROR 1
|
||||||
|
@ -27,8 +25,8 @@
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
typedef uint64_t (*aluop1_f)(struct Machine *, uint64_t);
|
typedef uint64_t (*aluop1_f)(struct Machine *, uint32_t, uint64_t);
|
||||||
typedef uint64_t (*aluop2_f)(struct Machine *, uint64_t, uint64_t);
|
typedef uint64_t (*aluop2_f)(struct Machine *, uint32_t, uint64_t, uint64_t);
|
||||||
|
|
||||||
int64_t Alu(int, int, uint64_t, uint64_t, uint32_t *);
|
int64_t Alu(int, int, uint64_t, uint64_t, uint32_t *);
|
||||||
int64_t Bsu(int, int, uint64_t, uint64_t, uint32_t *);
|
int64_t Bsu(int, int, uint64_t, uint64_t, uint32_t *);
|
||||||
|
|
|
@ -22,14 +22,14 @@
|
||||||
#include "tool/build/lib/machine.h"
|
#include "tool/build/lib/machine.h"
|
||||||
#include "tool/build/lib/modrm.h"
|
#include "tool/build/lib/modrm.h"
|
||||||
|
|
||||||
uint64_t AluBsr(struct Machine *m, uint64_t _, uint64_t x) {
|
uint64_t AluBsr(struct Machine *m, uint32_t rde, uint64_t _, uint64_t x) {
|
||||||
unsigned i;
|
unsigned i;
|
||||||
if (Rexw(m->xedd)) {
|
if (Rexw(rde)) {
|
||||||
x &= 0xffffffffffffffff;
|
x &= 0xffffffffffffffff;
|
||||||
m->flags = SetFlag(m->flags, FLAGS_ZF, !x);
|
m->flags = SetFlag(m->flags, FLAGS_ZF, !x);
|
||||||
if (!x) return 0;
|
if (!x) return 0;
|
||||||
return 63 ^ __builtin_clzll(x);
|
return 63 ^ __builtin_clzll(x);
|
||||||
} else if (!Osz(m->xedd)) {
|
} else if (!Osz(rde)) {
|
||||||
x &= 0xffffffff;
|
x &= 0xffffffff;
|
||||||
m->flags = SetFlag(m->flags, FLAGS_ZF, !x);
|
m->flags = SetFlag(m->flags, FLAGS_ZF, !x);
|
||||||
if (!x) return 0;
|
if (!x) return 0;
|
||||||
|
@ -43,14 +43,14 @@ uint64_t AluBsr(struct Machine *m, uint64_t _, uint64_t x) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t AluBsf(struct Machine *m, uint64_t _, uint64_t x) {
|
uint64_t AluBsf(struct Machine *m, uint32_t rde, uint64_t _, uint64_t x) {
|
||||||
unsigned i;
|
unsigned i;
|
||||||
if (Rexw(m->xedd)) {
|
if (Rexw(rde)) {
|
||||||
x &= 0xffffffffffffffff;
|
x &= 0xffffffffffffffff;
|
||||||
m->flags = SetFlag(m->flags, FLAGS_ZF, !x);
|
m->flags = SetFlag(m->flags, FLAGS_ZF, !x);
|
||||||
if (!x) return 0;
|
if (!x) return 0;
|
||||||
return __builtin_ctzll(x);
|
return __builtin_ctzll(x);
|
||||||
} else if (!Osz(m->xedd)) {
|
} else if (!Osz(rde)) {
|
||||||
x &= 0xffffffff;
|
x &= 0xffffffff;
|
||||||
m->flags = SetFlag(m->flags, FLAGS_ZF, !x);
|
m->flags = SetFlag(m->flags, FLAGS_ZF, !x);
|
||||||
if (!x) return 0;
|
if (!x) return 0;
|
||||||
|
@ -64,7 +64,7 @@ uint64_t AluBsf(struct Machine *m, uint64_t _, uint64_t x) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t AluPopcnt(struct Machine *m, uint64_t _, uint64_t x) {
|
uint64_t AluPopcnt(struct Machine *m, uint32_t rde, uint64_t _, uint64_t x) {
|
||||||
m->flags = SetFlag(m->flags, FLAGS_ZF, !x);
|
m->flags = SetFlag(m->flags, FLAGS_ZF, !x);
|
||||||
m->flags = SetFlag(m->flags, FLAGS_CF, false);
|
m->flags = SetFlag(m->flags, FLAGS_CF, false);
|
||||||
m->flags = SetFlag(m->flags, FLAGS_SF, false);
|
m->flags = SetFlag(m->flags, FLAGS_SF, false);
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
uint64_t AluBsr(struct Machine *, uint64_t, uint64_t);
|
uint64_t AluBsr(struct Machine *, uint32_t, uint64_t, uint64_t);
|
||||||
uint64_t AluBsf(struct Machine *, uint64_t, uint64_t);
|
uint64_t AluBsf(struct Machine *, uint32_t, uint64_t, uint64_t);
|
||||||
uint64_t AluPopcnt(struct Machine *, uint64_t, uint64_t);
|
uint64_t AluPopcnt(struct Machine *, uint32_t, uint64_t, uint64_t);
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -21,7 +21,13 @@
|
||||||
#include "libc/assert.h"
|
#include "libc/assert.h"
|
||||||
#include "tool/build/lib/breakpoint.h"
|
#include "tool/build/lib/breakpoint.h"
|
||||||
|
|
||||||
ssize_t AddBreakpoint(struct Breakpoints *bps, struct Breakpoint *b) {
|
void PopBreakpoint(struct Breakpoints *bps) {
|
||||||
|
if (bps->i) {
|
||||||
|
--bps->i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t PushBreakpoint(struct Breakpoints *bps, struct Breakpoint *b) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < bps->i; ++i) {
|
for (i = 0; i < bps->i; ++i) {
|
||||||
if (bps->p[i].disable) {
|
if (bps->p[i].disable) {
|
||||||
|
|
|
@ -14,7 +14,8 @@ struct Breakpoints {
|
||||||
};
|
};
|
||||||
|
|
||||||
ssize_t IsAtBreakpoint(struct Breakpoints *, int64_t);
|
ssize_t IsAtBreakpoint(struct Breakpoints *, int64_t);
|
||||||
ssize_t AddBreakpoint(struct Breakpoints *, struct Breakpoint *);
|
ssize_t PushBreakpoint(struct Breakpoints *, struct Breakpoint *);
|
||||||
|
void PopBreakpoint(struct Breakpoints *);
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||||
│ 02110-1301 USA │
|
│ 02110-1301 USA │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "dsp/tty/tty.h"
|
||||||
#include "libc/alg/arraylist2.h"
|
#include "libc/alg/arraylist2.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/fmt/fmt.h"
|
#include "libc/fmt/fmt.h"
|
||||||
|
@ -57,12 +58,5 @@ void AppendFmt(struct Buffer *b, const char *fmt, ...) {
|
||||||
* Writes buffer until completion, interrupt, or error occurs.
|
* Writes buffer until completion, interrupt, or error occurs.
|
||||||
*/
|
*/
|
||||||
ssize_t WriteBuffer(struct Buffer *b, int fd) {
|
ssize_t WriteBuffer(struct Buffer *b, int fd) {
|
||||||
size_t i;
|
return ttywrite(fd, b->p, b->i);
|
||||||
ssize_t rc;
|
|
||||||
for (i = 0; i < b->i; i += rc) {
|
|
||||||
if ((rc = write(fd, b->p + i, b->i - i)) == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ TOOL_BUILD_LIB_A_OBJS = \
|
||||||
$(TOOL_BUILD_LIB_A_SRCS_C:%.c=o/$(MODE)/%.o)
|
$(TOOL_BUILD_LIB_A_SRCS_C:%.c=o/$(MODE)/%.o)
|
||||||
|
|
||||||
TOOL_BUILD_LIB_A_DIRECTDEPS = \
|
TOOL_BUILD_LIB_A_DIRECTDEPS = \
|
||||||
|
DSP_TTY \
|
||||||
LIBC_ALG \
|
LIBC_ALG \
|
||||||
LIBC_BITS \
|
LIBC_BITS \
|
||||||
LIBC_CONV \
|
LIBC_CONV \
|
||||||
|
|
|
@ -26,287 +26,287 @@
|
||||||
#include "tool/build/lib/modrm.h"
|
#include "tool/build/lib/modrm.h"
|
||||||
#include "tool/build/lib/throw.h"
|
#include "tool/build/lib/throw.h"
|
||||||
|
|
||||||
static void OpGdqpWssCvttss2si(struct Machine *m) {
|
static void OpGdqpWssCvttss2si(struct Machine *m, uint32_t rde) {
|
||||||
float f;
|
float f;
|
||||||
int64_t n;
|
int64_t n;
|
||||||
memcpy(&f, GetModrmRegisterXmmPointerRead4(m), 4);
|
memcpy(&f, GetModrmRegisterXmmPointerRead4(m, rde), 4);
|
||||||
n = f;
|
n = f;
|
||||||
if (!Rexw(m->xedd)) n &= 0xffffffff;
|
if (!Rexw(rde)) n &= 0xffffffff;
|
||||||
Write64(RegRexrReg(m), n);
|
Write64(RegRexrReg(m, rde), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpGdqpWsdCvttsd2si(struct Machine *m) {
|
static void OpGdqpWsdCvttsd2si(struct Machine *m, uint32_t rde) {
|
||||||
double d;
|
double d;
|
||||||
int64_t n;
|
int64_t n;
|
||||||
memcpy(&d, GetModrmRegisterXmmPointerRead8(m), 8);
|
memcpy(&d, GetModrmRegisterXmmPointerRead8(m, rde), 8);
|
||||||
n = d;
|
n = d;
|
||||||
if (!Rexw(m->xedd)) n &= 0xffffffff;
|
if (!Rexw(rde)) n &= 0xffffffff;
|
||||||
Write64(RegRexrReg(m), n);
|
Write64(RegRexrReg(m, rde), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpGdqpWssCvtss2si(struct Machine *m) {
|
static void OpGdqpWssCvtss2si(struct Machine *m, uint32_t rde) {
|
||||||
float f;
|
float f;
|
||||||
int64_t n;
|
int64_t n;
|
||||||
memcpy(&f, GetModrmRegisterXmmPointerRead4(m), 4);
|
memcpy(&f, GetModrmRegisterXmmPointerRead4(m, rde), 4);
|
||||||
n = rintf(f);
|
n = rintf(f);
|
||||||
if (!Rexw(m->xedd)) n &= 0xffffffff;
|
if (!Rexw(rde)) n &= 0xffffffff;
|
||||||
Write64(RegRexrReg(m), n);
|
Write64(RegRexrReg(m, rde), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpGdqpWsdCvtsd2si(struct Machine *m) {
|
static void OpGdqpWsdCvtsd2si(struct Machine *m, uint32_t rde) {
|
||||||
double d;
|
double d;
|
||||||
int64_t n;
|
int64_t n;
|
||||||
memcpy(&d, GetModrmRegisterXmmPointerRead8(m), 8);
|
memcpy(&d, GetModrmRegisterXmmPointerRead8(m, rde), 8);
|
||||||
n = nearbyint(d);
|
n = nearbyint(d);
|
||||||
if (!Rexw(m->xedd)) n &= 0xffffffff;
|
if (!Rexw(rde)) n &= 0xffffffff;
|
||||||
Write64(RegRexrReg(m), n);
|
Write64(RegRexrReg(m, rde), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpVssEdqpCvtsi2ss(struct Machine *m) {
|
static void OpVssEdqpCvtsi2ss(struct Machine *m, uint32_t rde) {
|
||||||
float f;
|
float f;
|
||||||
int64_t n;
|
int64_t n;
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
if (Rexw(m->xedd)) {
|
if (Rexw(rde)) {
|
||||||
n = (int64_t)Read64(GetModrmRegisterWordPointerRead8(m));
|
n = (int64_t)Read64(GetModrmRegisterWordPointerRead8(m, rde));
|
||||||
} else {
|
} else {
|
||||||
n = (int32_t)Read32(GetModrmRegisterWordPointerRead4(m));
|
n = (int32_t)Read32(GetModrmRegisterWordPointerRead4(m, rde));
|
||||||
}
|
}
|
||||||
f = n;
|
f = n;
|
||||||
memcpy(XmmRexrReg(m), &f, 4);
|
memcpy(XmmRexrReg(m, rde), &f, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpVsdEdqpCvtsi2sd(struct Machine *m) {
|
static void OpVsdEdqpCvtsi2sd(struct Machine *m, uint32_t rde) {
|
||||||
double d;
|
double d;
|
||||||
int64_t n;
|
int64_t n;
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
if (Rexw(m->xedd)) {
|
if (Rexw(rde)) {
|
||||||
n = (int64_t)Read64(GetModrmRegisterWordPointerRead8(m));
|
n = (int64_t)Read64(GetModrmRegisterWordPointerRead8(m, rde));
|
||||||
} else {
|
} else {
|
||||||
n = (int32_t)Read32(GetModrmRegisterWordPointerRead4(m));
|
n = (int32_t)Read32(GetModrmRegisterWordPointerRead4(m, rde));
|
||||||
}
|
}
|
||||||
d = n;
|
d = n;
|
||||||
memcpy(XmmRexrReg(m), &d, 8);
|
memcpy(XmmRexrReg(m, rde), &d, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpVpsQpiCvtpi2ps(struct Machine *m) {
|
static void OpVpsQpiCvtpi2ps(struct Machine *m, uint32_t rde) {
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
float f[2];
|
float f[2];
|
||||||
int32_t i[2];
|
int32_t i[2];
|
||||||
p = GetModrmRegisterMmPointerRead8(m);
|
p = GetModrmRegisterMmPointerRead8(m, rde);
|
||||||
i[0] = Read32(p + 0);
|
i[0] = Read32(p + 0);
|
||||||
i[1] = Read32(p + 4);
|
i[1] = Read32(p + 4);
|
||||||
f[0] = i[0];
|
f[0] = i[0];
|
||||||
f[1] = i[1];
|
f[1] = i[1];
|
||||||
memcpy(XmmRexrReg(m), f, 8);
|
memcpy(XmmRexrReg(m, rde), f, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpVpdQpiCvtpi2pd(struct Machine *m) {
|
static void OpVpdQpiCvtpi2pd(struct Machine *m, uint32_t rde) {
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
double f[2];
|
double f[2];
|
||||||
int32_t n[2];
|
int32_t n[2];
|
||||||
p = GetModrmRegisterMmPointerRead8(m);
|
p = GetModrmRegisterMmPointerRead8(m, rde);
|
||||||
n[0] = Read32(p + 0);
|
n[0] = Read32(p + 0);
|
||||||
n[1] = Read32(p + 4);
|
n[1] = Read32(p + 4);
|
||||||
f[0] = n[0];
|
f[0] = n[0];
|
||||||
f[1] = n[1];
|
f[1] = n[1];
|
||||||
memcpy(XmmRexrReg(m), f, 16);
|
memcpy(XmmRexrReg(m, rde), f, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpPpiWpsqCvtps2pi(struct Machine *m) {
|
static void OpPpiWpsqCvtps2pi(struct Machine *m, uint32_t rde) {
|
||||||
float f[2];
|
float f[2];
|
||||||
int32_t n[2];
|
int32_t n[2];
|
||||||
memcpy(f, GetModrmRegisterXmmPointerRead8(m), 8);
|
memcpy(f, GetModrmRegisterXmmPointerRead8(m, rde), 8);
|
||||||
n[0] = nearbyintf(f[0]);
|
n[0] = nearbyintf(f[0]);
|
||||||
n[1] = nearbyintf(f[1]);
|
n[1] = nearbyintf(f[1]);
|
||||||
Write32(MmReg(m) + 0, n[0]);
|
Write32(MmReg(m, rde) + 0, n[0]);
|
||||||
Write32(MmReg(m) + 4, n[1]);
|
Write32(MmReg(m, rde) + 4, n[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpPpiWpsqCvttps2pi(struct Machine *m) {
|
static void OpPpiWpsqCvttps2pi(struct Machine *m, uint32_t rde) {
|
||||||
float f[2];
|
float f[2];
|
||||||
int32_t n[2];
|
int32_t n[2];
|
||||||
memcpy(&f, GetModrmRegisterXmmPointerRead8(m), 8);
|
memcpy(&f, GetModrmRegisterXmmPointerRead8(m, rde), 8);
|
||||||
n[0] = f[0];
|
n[0] = f[0];
|
||||||
n[1] = f[1];
|
n[1] = f[1];
|
||||||
Write32(MmReg(m) + 0, n[0]);
|
Write32(MmReg(m, rde) + 0, n[0]);
|
||||||
Write32(MmReg(m) + 4, n[1]);
|
Write32(MmReg(m, rde) + 4, n[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpPpiWpdCvtpd2pi(struct Machine *m) {
|
static void OpPpiWpdCvtpd2pi(struct Machine *m, uint32_t rde) {
|
||||||
double d[2];
|
double d[2];
|
||||||
int32_t n[2];
|
int32_t n[2];
|
||||||
memcpy(d, GetModrmRegisterXmmPointerRead16(m), 16);
|
memcpy(d, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||||
n[0] = nearbyint(d[0]);
|
n[0] = nearbyint(d[0]);
|
||||||
n[1] = nearbyint(d[1]);
|
n[1] = nearbyint(d[1]);
|
||||||
Write32(MmReg(m) + 0, n[0]);
|
Write32(MmReg(m, rde) + 0, n[0]);
|
||||||
Write32(MmReg(m) + 4, n[1]);
|
Write32(MmReg(m, rde) + 4, n[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpPpiWpdCvttpd2pi(struct Machine *m) {
|
static void OpPpiWpdCvttpd2pi(struct Machine *m, uint32_t rde) {
|
||||||
double d[2];
|
double d[2];
|
||||||
int32_t n[2];
|
int32_t n[2];
|
||||||
memcpy(&d, GetModrmRegisterXmmPointerRead16(m), 16);
|
memcpy(&d, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||||
n[0] = d[0];
|
n[0] = d[0];
|
||||||
n[1] = d[1];
|
n[1] = d[1];
|
||||||
Write32(MmReg(m) + 0, n[0]);
|
Write32(MmReg(m, rde) + 0, n[0]);
|
||||||
Write32(MmReg(m) + 4, n[1]);
|
Write32(MmReg(m, rde) + 4, n[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpVpdWpsCvtps2pd(struct Machine *m) {
|
static void OpVpdWpsCvtps2pd(struct Machine *m, uint32_t rde) {
|
||||||
float f[2];
|
float f[2];
|
||||||
double d[2];
|
double d[2];
|
||||||
memcpy(f, GetModrmRegisterXmmPointerRead8(m), 8);
|
memcpy(f, GetModrmRegisterXmmPointerRead8(m, rde), 8);
|
||||||
d[0] = f[0];
|
d[0] = f[0];
|
||||||
d[1] = f[1];
|
d[1] = f[1];
|
||||||
memcpy(XmmRexrReg(m), d, 16);
|
memcpy(XmmRexrReg(m, rde), d, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpVpsWpdCvtpd2ps(struct Machine *m) {
|
static void OpVpsWpdCvtpd2ps(struct Machine *m, uint32_t rde) {
|
||||||
float f[2];
|
float f[2];
|
||||||
double d[2];
|
double d[2];
|
||||||
memcpy(d, GetModrmRegisterXmmPointerRead16(m), 16);
|
memcpy(d, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||||
f[0] = d[0];
|
f[0] = d[0];
|
||||||
f[1] = d[1];
|
f[1] = d[1];
|
||||||
memcpy(XmmRexrReg(m), f, 8);
|
memcpy(XmmRexrReg(m, rde), f, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpVssWsdCvtsd2ss(struct Machine *m) {
|
static void OpVssWsdCvtsd2ss(struct Machine *m, uint32_t rde) {
|
||||||
float f;
|
float f;
|
||||||
double d;
|
double d;
|
||||||
memcpy(&d, GetModrmRegisterXmmPointerRead8(m), 8);
|
memcpy(&d, GetModrmRegisterXmmPointerRead8(m, rde), 8);
|
||||||
f = d;
|
f = d;
|
||||||
memcpy(XmmRexrReg(m), &f, 4);
|
memcpy(XmmRexrReg(m, rde), &f, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpVsdWssCvtss2sd(struct Machine *m) {
|
static void OpVsdWssCvtss2sd(struct Machine *m, uint32_t rde) {
|
||||||
float f;
|
float f;
|
||||||
double d;
|
double d;
|
||||||
memcpy(&f, GetModrmRegisterXmmPointerRead4(m), 4);
|
memcpy(&f, GetModrmRegisterXmmPointerRead4(m, rde), 4);
|
||||||
d = f;
|
d = f;
|
||||||
memcpy(XmmRexrReg(m), &d, 8);
|
memcpy(XmmRexrReg(m, rde), &d, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpVpsWdqCvtdq2ps(struct Machine *m) {
|
static void OpVpsWdqCvtdq2ps(struct Machine *m, uint32_t rde) {
|
||||||
unsigned i;
|
unsigned i;
|
||||||
float f[4];
|
float f[4];
|
||||||
int32_t n[4];
|
int32_t n[4];
|
||||||
memcpy(n, GetModrmRegisterXmmPointerRead16(m), 16);
|
memcpy(n, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||||
for (i = 0; i < 4; ++i) f[i] = n[i];
|
for (i = 0; i < 4; ++i) f[i] = n[i];
|
||||||
memcpy(XmmRexrReg(m), f, 16);
|
memcpy(XmmRexrReg(m, rde), f, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpVpdWdqCvtdq2pd(struct Machine *m) {
|
static void OpVpdWdqCvtdq2pd(struct Machine *m, uint32_t rde) {
|
||||||
unsigned i;
|
unsigned i;
|
||||||
double d[2];
|
double d[2];
|
||||||
int32_t n[2];
|
int32_t n[2];
|
||||||
memcpy(n, GetModrmRegisterXmmPointerRead8(m), 8);
|
memcpy(n, GetModrmRegisterXmmPointerRead8(m, rde), 8);
|
||||||
for (i = 0; i < 2; ++i) d[i] = n[i];
|
for (i = 0; i < 2; ++i) d[i] = n[i];
|
||||||
memcpy(XmmRexrReg(m), d, 16);
|
memcpy(XmmRexrReg(m, rde), d, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpVdqWpsCvttps2dq(struct Machine *m) {
|
static void OpVdqWpsCvttps2dq(struct Machine *m, uint32_t rde) {
|
||||||
unsigned i;
|
unsigned i;
|
||||||
float f[4];
|
float f[4];
|
||||||
int32_t n[4];
|
int32_t n[4];
|
||||||
memcpy(f, GetModrmRegisterXmmPointerRead16(m), 16);
|
memcpy(f, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||||
for (i = 0; i < 4; ++i) n[i] = f[i];
|
for (i = 0; i < 4; ++i) n[i] = f[i];
|
||||||
memcpy(XmmRexrReg(m), n, 16);
|
memcpy(XmmRexrReg(m, rde), n, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpVdqWpsCvtps2dq(struct Machine *m) {
|
static void OpVdqWpsCvtps2dq(struct Machine *m, uint32_t rde) {
|
||||||
unsigned i;
|
unsigned i;
|
||||||
float f[4];
|
float f[4];
|
||||||
int32_t n[4];
|
int32_t n[4];
|
||||||
memcpy(f, GetModrmRegisterXmmPointerRead16(m), 16);
|
memcpy(f, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||||
for (i = 0; i < 4; ++i) n[i] = nearbyintf(f[i]);
|
for (i = 0; i < 4; ++i) n[i] = nearbyintf(f[i]);
|
||||||
memcpy(XmmRexrReg(m), n, 16);
|
memcpy(XmmRexrReg(m, rde), n, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpVdqWpdCvttpd2dq(struct Machine *m) {
|
static void OpVdqWpdCvttpd2dq(struct Machine *m, uint32_t rde) {
|
||||||
unsigned i;
|
unsigned i;
|
||||||
double d[2];
|
double d[2];
|
||||||
int32_t n[2];
|
int32_t n[2];
|
||||||
memcpy(d, GetModrmRegisterXmmPointerRead16(m), 16);
|
memcpy(d, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||||
for (i = 0; i < 2; ++i) n[i] = d[i];
|
for (i = 0; i < 2; ++i) n[i] = d[i];
|
||||||
memcpy(XmmRexrReg(m), n, 8);
|
memcpy(XmmRexrReg(m, rde), n, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpVdqWpdCvtpd2dq(struct Machine *m) {
|
static void OpVdqWpdCvtpd2dq(struct Machine *m, uint32_t rde) {
|
||||||
unsigned i;
|
unsigned i;
|
||||||
double d[2];
|
double d[2];
|
||||||
int32_t n[2];
|
int32_t n[2];
|
||||||
memcpy(d, GetModrmRegisterXmmPointerRead16(m), 16);
|
memcpy(d, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||||
for (i = 0; i < 2; ++i) n[i] = nearbyintf(d[i]);
|
for (i = 0; i < 2; ++i) n[i] = nearbyintf(d[i]);
|
||||||
memcpy(XmmRexrReg(m), n, 8);
|
memcpy(XmmRexrReg(m, rde), n, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpCvt(struct Machine *m, unsigned long op) {
|
void OpCvt(struct Machine *m, uint32_t rde, unsigned long op) {
|
||||||
switch (op | Rep(m->xedd) | Osz(m->xedd)) {
|
switch (op | Rep(rde) | Osz(rde)) {
|
||||||
case kOpCvt0f2a + 0:
|
case kOpCvt0f2a + 0:
|
||||||
OpVpsQpiCvtpi2ps(m);
|
OpVpsQpiCvtpi2ps(m, rde);
|
||||||
break;
|
break;
|
||||||
case kOpCvt0f2a + 1:
|
case kOpCvt0f2a + 1:
|
||||||
OpVpdQpiCvtpi2pd(m);
|
OpVpdQpiCvtpi2pd(m, rde);
|
||||||
break;
|
break;
|
||||||
case kOpCvt0f2a + 2:
|
case kOpCvt0f2a + 2:
|
||||||
OpVsdEdqpCvtsi2sd(m);
|
OpVsdEdqpCvtsi2sd(m, rde);
|
||||||
break;
|
break;
|
||||||
case kOpCvt0f2a + 3:
|
case kOpCvt0f2a + 3:
|
||||||
OpVssEdqpCvtsi2ss(m);
|
OpVssEdqpCvtsi2ss(m, rde);
|
||||||
break;
|
break;
|
||||||
case kOpCvtt0f2c + 0:
|
case kOpCvtt0f2c + 0:
|
||||||
OpPpiWpsqCvttps2pi(m);
|
OpPpiWpsqCvttps2pi(m, rde);
|
||||||
break;
|
break;
|
||||||
case kOpCvtt0f2c + 1:
|
case kOpCvtt0f2c + 1:
|
||||||
OpPpiWpdCvttpd2pi(m);
|
OpPpiWpdCvttpd2pi(m, rde);
|
||||||
break;
|
break;
|
||||||
case kOpCvtt0f2c + 2:
|
case kOpCvtt0f2c + 2:
|
||||||
OpGdqpWsdCvttsd2si(m);
|
OpGdqpWsdCvttsd2si(m, rde);
|
||||||
break;
|
break;
|
||||||
case kOpCvtt0f2c + 3:
|
case kOpCvtt0f2c + 3:
|
||||||
OpGdqpWssCvttss2si(m);
|
OpGdqpWssCvttss2si(m, rde);
|
||||||
break;
|
break;
|
||||||
case kOpCvt0f2d + 0:
|
case kOpCvt0f2d + 0:
|
||||||
OpPpiWpsqCvtps2pi(m);
|
OpPpiWpsqCvtps2pi(m, rde);
|
||||||
break;
|
break;
|
||||||
case kOpCvt0f2d + 1:
|
case kOpCvt0f2d + 1:
|
||||||
OpPpiWpdCvtpd2pi(m);
|
OpPpiWpdCvtpd2pi(m, rde);
|
||||||
break;
|
break;
|
||||||
case kOpCvt0f2d + 2:
|
case kOpCvt0f2d + 2:
|
||||||
OpGdqpWsdCvtsd2si(m);
|
OpGdqpWsdCvtsd2si(m, rde);
|
||||||
break;
|
break;
|
||||||
case kOpCvt0f2d + 3:
|
case kOpCvt0f2d + 3:
|
||||||
OpGdqpWssCvtss2si(m);
|
OpGdqpWssCvtss2si(m, rde);
|
||||||
break;
|
break;
|
||||||
case kOpCvt0f5a + 0:
|
case kOpCvt0f5a + 0:
|
||||||
OpVpdWpsCvtps2pd(m);
|
OpVpdWpsCvtps2pd(m, rde);
|
||||||
break;
|
break;
|
||||||
case kOpCvt0f5a + 1:
|
case kOpCvt0f5a + 1:
|
||||||
OpVpsWpdCvtpd2ps(m);
|
OpVpsWpdCvtpd2ps(m, rde);
|
||||||
break;
|
break;
|
||||||
case kOpCvt0f5a + 2:
|
case kOpCvt0f5a + 2:
|
||||||
OpVssWsdCvtsd2ss(m);
|
OpVssWsdCvtsd2ss(m, rde);
|
||||||
break;
|
break;
|
||||||
case kOpCvt0f5a + 3:
|
case kOpCvt0f5a + 3:
|
||||||
OpVsdWssCvtss2sd(m);
|
OpVsdWssCvtss2sd(m, rde);
|
||||||
break;
|
break;
|
||||||
case kOpCvt0f5b + 0:
|
case kOpCvt0f5b + 0:
|
||||||
OpVpsWdqCvtdq2ps(m);
|
OpVpsWdqCvtdq2ps(m, rde);
|
||||||
break;
|
break;
|
||||||
case kOpCvt0f5b + 1:
|
case kOpCvt0f5b + 1:
|
||||||
OpVdqWpsCvtps2dq(m);
|
OpVdqWpsCvtps2dq(m, rde);
|
||||||
break;
|
break;
|
||||||
case kOpCvt0f5b + 3:
|
case kOpCvt0f5b + 3:
|
||||||
OpVdqWpsCvttps2dq(m);
|
OpVdqWpsCvttps2dq(m, rde);
|
||||||
break;
|
break;
|
||||||
case kOpCvt0fE6 + 1:
|
case kOpCvt0fE6 + 1:
|
||||||
OpVdqWpdCvtpd2dq(m);
|
OpVdqWpdCvtpd2dq(m, rde);
|
||||||
break;
|
break;
|
||||||
case kOpCvt0fE6 + 2:
|
case kOpCvt0fE6 + 2:
|
||||||
OpVdqWpdCvttpd2dq(m);
|
OpVdqWpdCvttpd2dq(m, rde);
|
||||||
break;
|
break;
|
||||||
case kOpCvt0fE6 + 3:
|
case kOpCvt0fE6 + 3:
|
||||||
OpVpdWdqCvtdq2pd(m);
|
OpVpdWdqCvtdq2pd(m, rde);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
OpUd(m);
|
OpUd(m);
|
||||||
|
|
|
@ -11,7 +11,7 @@ COSMOPOLITAN_C_START_
|
||||||
#define kOpCvt0f5b 16
|
#define kOpCvt0f5b 16
|
||||||
#define kOpCvt0fE6 20
|
#define kOpCvt0fE6 20
|
||||||
|
|
||||||
void OpCvt(struct Machine *, unsigned long);
|
void OpCvt(struct Machine *, uint32_t, unsigned long);
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "third_party/xed/x86.h"
|
#include "third_party/xed/x86.h"
|
||||||
#include "tool/build/lib/case.h"
|
#include "tool/build/lib/case.h"
|
||||||
#include "tool/build/lib/dis.h"
|
#include "tool/build/lib/dis.h"
|
||||||
|
#include "tool/build/lib/memory.h"
|
||||||
#include "tool/build/lib/modrm.h"
|
#include "tool/build/lib/modrm.h"
|
||||||
|
|
||||||
#define ADDRLEN 8
|
#define ADDRLEN 8
|
||||||
|
|
|
@ -61,7 +61,7 @@ static int64_t RipRelative(struct DisBuilder b, int64_t d) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *GetAddrReg(struct DisBuilder b, uint8_t x, uint8_t r) {
|
static const char *GetAddrReg(struct DisBuilder b, uint8_t x, uint8_t r) {
|
||||||
return kRegisterName[0][!Asz(b.xedd)][x & 1][r & 7];
|
return kRegisterName[0][!Asz(b.xedd->op.rde)][x & 1][r & 7];
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisRegister(char *p, const char *s) {
|
static char *DisRegister(char *p, const char *s) {
|
||||||
|
@ -87,24 +87,25 @@ static char *DisComment(char *p, const char *s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisRegisterByte(struct DisBuilder b, char *p, bool g, int r) {
|
static char *DisRegisterByte(struct DisBuilder b, char *p, bool g, int r) {
|
||||||
return DisRegister(p, kRegisterName8[g][Rex(b.xedd)][r]);
|
return DisRegister(p, kRegisterName8[g][Rex(b.xedd->op.rde)][r]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisRegisterWord(struct DisBuilder b, char *p, bool g, int r) {
|
static char *DisRegisterWord(struct DisBuilder b, char *p, bool g, int r) {
|
||||||
return DisRegister(p, kRegisterName[Osz(b.xedd)][Rexw(b.xedd)][g][r]);
|
return DisRegister(
|
||||||
|
p, kRegisterName[Osz(b.xedd->op.rde)][Rexw(b.xedd->op.rde)][g][r]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisGvqp(struct DisBuilder b, char *p) {
|
static char *DisGvqp(struct DisBuilder b, char *p) {
|
||||||
return DisRegisterWord(b, p, Rexr(b.xedd), ModrmReg(b.xedd));
|
return DisRegisterWord(b, p, Rexr(b.xedd->op.rde), ModrmReg(b.xedd->op.rde));
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisGdqp(struct DisBuilder b, char *p) {
|
static char *DisGdqp(struct DisBuilder b, char *p) {
|
||||||
return DisRegister(
|
return DisRegister(p, kRegisterName[0][Rexw(b.xedd->op.rde)][Rexr(
|
||||||
p, kRegisterName[0][Rexw(b.xedd)][Rexr(b.xedd)][ModrmReg(b.xedd)]);
|
b.xedd->op.rde)][ModrmReg(b.xedd->op.rde)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisGb(struct DisBuilder b, char *p) {
|
static char *DisGb(struct DisBuilder b, char *p) {
|
||||||
return DisRegisterByte(b, p, Rexr(b.xedd), ModrmReg(b.xedd));
|
return DisRegisterByte(b, p, Rexr(b.xedd->op.rde), ModrmReg(b.xedd->op.rde));
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t DisSeg(struct DisBuilder b) {
|
static uint8_t DisSeg(struct DisBuilder b) {
|
||||||
|
@ -154,30 +155,29 @@ static char *DisM(struct DisBuilder b, char *p) {
|
||||||
p = DisRegister(p, seg);
|
p = DisRegister(p, seg);
|
||||||
*p++ = ':';
|
*p++ = ':';
|
||||||
}
|
}
|
||||||
if (ModrmMod(b.xedd) == 0b01 || ModrmMod(b.xedd) == 0b10 ||
|
if (ModrmMod(b.xedd->op.rde) == 0b01 || ModrmMod(b.xedd->op.rde) == 0b10 ||
|
||||||
IsRipRelative(b.xedd) ||
|
IsRipRelative(b.xedd->op.rde) ||
|
||||||
(ModrmMod(b.xedd) == 0b00 && ModrmRm(b.xedd) == 0b100 &&
|
(ModrmMod(b.xedd->op.rde) == 0b00 && ModrmRm(b.xedd->op.rde) == 0b100 &&
|
||||||
SibBase(b.xedd) == 0b101)) {
|
SibBase(b.xedd->op.rde) == 0b101)) {
|
||||||
disp = b.xedd->op.disp;
|
disp = b.xedd->op.disp;
|
||||||
if (IsRipRelative(b.xedd)) disp = RipRelative(b, disp);
|
if (IsRipRelative(b.xedd->op.rde)) disp = RipRelative(b, disp);
|
||||||
p = DisSym(b, p, disp);
|
p = DisSym(b, p, disp);
|
||||||
}
|
}
|
||||||
if (!SibExists(b.xedd)) {
|
if (!SibExists(b.xedd->op.rde)) {
|
||||||
DCHECK(!b.xedd->op.has_sib);
|
DCHECK(!b.xedd->op.has_sib);
|
||||||
if (IsRipRelative(b.xedd)) {
|
if (IsRipRelative(b.xedd->op.rde)) {
|
||||||
base = "rip";
|
base = "rip";
|
||||||
} else {
|
} else {
|
||||||
base = GetAddrReg(b, Rexb(b.xedd), ModrmRm(b.xedd));
|
base = GetAddrReg(b, Rexb(b.xedd->op.rde), ModrmRm(b.xedd->op.rde));
|
||||||
}
|
}
|
||||||
} else if (!SibIsAbsolute(b.xedd)) {
|
} else if (!SibIsAbsolute(b.xedd->op.rde)) {
|
||||||
DCHECK(b.xedd->op.has_sib);
|
if (SibHasBase(b.xedd->op.rde)) {
|
||||||
if (SibHasBase(b.xedd)) {
|
base = GetAddrReg(b, Rexb(b.xedd->op.rde), SibBase(b.xedd->op.rde));
|
||||||
base = GetAddrReg(b, Rexb(b.xedd), SibBase(b.xedd));
|
|
||||||
}
|
}
|
||||||
if (SibHasIndex(b.xedd)) {
|
if (SibHasIndex(b.xedd->op.rde)) {
|
||||||
index = GetAddrReg(b, Rexx(b.xedd), SibIndex(b.xedd));
|
index = GetAddrReg(b, Rexx(b.xedd->op.rde), SibIndex(b.xedd->op.rde));
|
||||||
} else if (b.xedd->op.scale) {
|
} else if (b.xedd->op.scale) {
|
||||||
index = Asz(b.xedd) ? "eiz" : "riz";
|
index = Asz(b.xedd->op.rde) ? "eiz" : "riz";
|
||||||
}
|
}
|
||||||
scale = kScale[b.xedd->op.scale];
|
scale = kScale[b.xedd->op.scale];
|
||||||
}
|
}
|
||||||
|
@ -198,25 +198,25 @@ static char *DisM(struct DisBuilder b, char *p) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisEb(struct DisBuilder b, char *p) {
|
static char *DisEb(struct DisBuilder b, char *p) {
|
||||||
if (IsModrmRegister(b.xedd)) {
|
if (IsModrmRegister(b.xedd->op.rde)) {
|
||||||
return DisRegisterByte(b, p, Rexb(b.xedd), ModrmRm(b.xedd));
|
return DisRegisterByte(b, p, Rexb(b.xedd->op.rde), ModrmRm(b.xedd->op.rde));
|
||||||
} else {
|
} else {
|
||||||
return DisM(b, p);
|
return DisM(b, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisEvqp(struct DisBuilder b, char *p) {
|
static char *DisEvqp(struct DisBuilder b, char *p) {
|
||||||
if (IsModrmRegister(b.xedd)) {
|
if (IsModrmRegister(b.xedd->op.rde)) {
|
||||||
return DisRegisterWord(b, p, Rexb(b.xedd), ModrmRm(b.xedd));
|
return DisRegisterWord(b, p, Rexb(b.xedd->op.rde), ModrmRm(b.xedd->op.rde));
|
||||||
} else {
|
} else {
|
||||||
return DisM(b, p);
|
return DisM(b, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisEdqp(struct DisBuilder b, char *p) {
|
static char *DisEdqp(struct DisBuilder b, char *p) {
|
||||||
if (IsModrmRegister(b.xedd)) {
|
if (IsModrmRegister(b.xedd->op.rde)) {
|
||||||
return DisRegister(
|
return DisRegister(p, kRegisterName[0][Rexw(b.xedd->op.rde)][Rexb(
|
||||||
p, kRegisterName[0][Rexw(b.xedd)][Rexb(b.xedd)][ModrmRm(b.xedd)]);
|
b.xedd->op.rde)][ModrmRm(b.xedd->op.rde)]);
|
||||||
} else {
|
} else {
|
||||||
return DisM(b, p);
|
return DisM(b, p);
|
||||||
}
|
}
|
||||||
|
@ -224,11 +224,11 @@ static char *DisEdqp(struct DisBuilder b, char *p) {
|
||||||
|
|
||||||
static char *DisEvq(struct DisBuilder b, char *p) {
|
static char *DisEvq(struct DisBuilder b, char *p) {
|
||||||
const char *s;
|
const char *s;
|
||||||
if (IsModrmRegister(b.xedd)) {
|
if (IsModrmRegister(b.xedd->op.rde)) {
|
||||||
if (Osz(b.xedd)) {
|
if (Osz(b.xedd->op.rde)) {
|
||||||
s = kRegisterName[1][0][Rexb(b.xedd)][ModrmRm(b.xedd)];
|
s = kRegisterName[1][0][Rexb(b.xedd->op.rde)][ModrmRm(b.xedd->op.rde)];
|
||||||
} else {
|
} else {
|
||||||
s = kRegisterName[0][1][Rexb(b.xedd)][ModrmRm(b.xedd)];
|
s = kRegisterName[0][1][Rexb(b.xedd->op.rde)][ModrmRm(b.xedd->op.rde)];
|
||||||
}
|
}
|
||||||
return DisRegister(p, s);
|
return DisRegister(p, s);
|
||||||
} else {
|
} else {
|
||||||
|
@ -237,47 +237,53 @@ static char *DisEvq(struct DisBuilder b, char *p) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisEd(struct DisBuilder b, char *p) {
|
static char *DisEd(struct DisBuilder b, char *p) {
|
||||||
if (IsModrmRegister(b.xedd)) {
|
if (IsModrmRegister(b.xedd->op.rde)) {
|
||||||
return DisRegister(p, kRegisterName[0][0][Rexb(b.xedd)][ModrmRm(b.xedd)]);
|
return DisRegister(
|
||||||
|
p, kRegisterName[0][0][Rexb(b.xedd->op.rde)][ModrmRm(b.xedd->op.rde)]);
|
||||||
} else {
|
} else {
|
||||||
return DisM(b, p);
|
return DisM(b, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisEq(struct DisBuilder b, char *p) {
|
static char *DisEq(struct DisBuilder b, char *p) {
|
||||||
if (IsModrmRegister(b.xedd)) {
|
if (IsModrmRegister(b.xedd->op.rde)) {
|
||||||
return DisRegister(p, kRegisterName[0][1][Rexb(b.xedd)][ModrmRm(b.xedd)]);
|
return DisRegister(
|
||||||
|
p, kRegisterName[0][1][Rexb(b.xedd->op.rde)][ModrmRm(b.xedd->op.rde)]);
|
||||||
} else {
|
} else {
|
||||||
return DisM(b, p);
|
return DisM(b, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisZvq(struct DisBuilder b, char *p) {
|
static char *DisZvq(struct DisBuilder b, char *p) {
|
||||||
if (Osz(b.xedd)) {
|
if (Osz(b.xedd->op.rde)) {
|
||||||
return DisRegister(p, kRegisterName[1][0][Rexb(b.xedd)][ModrmSrm(b.xedd)]);
|
return DisRegister(
|
||||||
|
p, kRegisterName[1][0][Rexb(b.xedd->op.rde)][ModrmSrm(b.xedd->op.rde)]);
|
||||||
} else {
|
} else {
|
||||||
return DisRegister(p, kRegisterName[0][1][Rexb(b.xedd)][ModrmSrm(b.xedd)]);
|
return DisRegister(
|
||||||
|
p, kRegisterName[0][1][Rexb(b.xedd->op.rde)][ModrmSrm(b.xedd->op.rde)]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisZvqp(struct DisBuilder b, char *p) {
|
static char *DisZvqp(struct DisBuilder b, char *p) {
|
||||||
return DisRegisterWord(b, p, Rexb(b.xedd), ModrmSrm(b.xedd));
|
return DisRegisterWord(b, p, Rexb(b.xedd->op.rde), ModrmSrm(b.xedd->op.rde));
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisZb(struct DisBuilder b, char *p) {
|
static char *DisZb(struct DisBuilder b, char *p) {
|
||||||
return DisRegisterByte(b, p, Rexb(b.xedd), ModrmSrm(b.xedd));
|
return DisRegisterByte(b, p, Rexb(b.xedd->op.rde), ModrmSrm(b.xedd->op.rde));
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisEax(struct DisBuilder b, char *p) {
|
static char *DisEax(struct DisBuilder b, char *p) {
|
||||||
return DisRegister(p, kRegisterName[Osz(b.xedd)][0][0][0]);
|
return DisRegister(p, kRegisterName[Osz(b.xedd->op.rde)][0][0][0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisRax(struct DisBuilder b, char *p) {
|
static char *DisRax(struct DisBuilder b, char *p) {
|
||||||
return DisRegister(p, kRegisterName[Osz(b.xedd)][Rexw(b.xedd)][0][0]);
|
return DisRegister(
|
||||||
|
p, kRegisterName[Osz(b.xedd->op.rde)][Rexw(b.xedd->op.rde)][0][0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisRdx(struct DisBuilder b, char *p) {
|
static char *DisRdx(struct DisBuilder b, char *p) {
|
||||||
return DisRegister(p, kRegisterName[Osz(b.xedd)][Rexw(b.xedd)][0][2]);
|
return DisRegister(
|
||||||
|
p, kRegisterName[Osz(b.xedd->op.rde)][Rexw(b.xedd->op.rde)][0][2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisImm(struct DisBuilder b, char *p) {
|
static char *DisImm(struct DisBuilder b, char *p) {
|
||||||
|
@ -309,8 +315,8 @@ static char *DisAbs(struct DisBuilder b, char *p) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisSw(struct DisBuilder b, char *p) {
|
static char *DisSw(struct DisBuilder b, char *p) {
|
||||||
if (kSegName[ModrmReg(b.xedd)][0]) {
|
if (kSegName[ModrmReg(b.xedd->op.rde)][0]) {
|
||||||
p = DisRegister(p, kSegName[ModrmReg(b.xedd)]);
|
p = DisRegister(p, kSegName[ModrmReg(b.xedd->op.rde)]);
|
||||||
}
|
}
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
return p;
|
return p;
|
||||||
|
@ -318,7 +324,7 @@ static char *DisSw(struct DisBuilder b, char *p) {
|
||||||
|
|
||||||
static char *DisY(struct DisBuilder b, char *p) {
|
static char *DisY(struct DisBuilder b, char *p) {
|
||||||
*p++ = '(';
|
*p++ = '(';
|
||||||
p = DisRegister(p, Asz(b.xedd) ? "edi" : "rdi");
|
p = DisRegister(p, Asz(b.xedd->op.rde) ? "edi" : "rdi");
|
||||||
*p++ = ')';
|
*p++ = ')';
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
return p;
|
return p;
|
||||||
|
@ -329,7 +335,7 @@ static char *DisX(struct DisBuilder b, char *p) {
|
||||||
p = DisRegister(p, kSegOverride[b.xedd->op.seg_ovd]);
|
p = DisRegister(p, kSegOverride[b.xedd->op.seg_ovd]);
|
||||||
}
|
}
|
||||||
*p++ = '(';
|
*p++ = '(';
|
||||||
p = DisRegister(p, Asz(b.xedd) ? "esi" : "rsi");
|
p = DisRegister(p, Asz(b.xedd->op.rde) ? "esi" : "rsi");
|
||||||
*p++ = ')';
|
*p++ = ')';
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
return p;
|
return p;
|
||||||
|
@ -340,7 +346,7 @@ static char *DisBBb(struct DisBuilder b, char *p) {
|
||||||
p = DisRegister(p, kSegOverride[b.xedd->op.seg_ovd]);
|
p = DisRegister(p, kSegOverride[b.xedd->op.seg_ovd]);
|
||||||
}
|
}
|
||||||
*p++ = '(';
|
*p++ = '(';
|
||||||
p = DisRegister(p, Asz(b.xedd) ? "ebx" : "rbx");
|
p = DisRegister(p, Asz(b.xedd->op.rde) ? "ebx" : "rbx");
|
||||||
*p++ = ')';
|
*p++ = ')';
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
return p;
|
return p;
|
||||||
|
@ -350,33 +356,33 @@ static char *DisXmm(struct DisBuilder b, char *p, const char *s, int reg) {
|
||||||
if (g_dis_high) p = DisHigh(p, g_dis_high->reg);
|
if (g_dis_high) p = DisHigh(p, g_dis_high->reg);
|
||||||
*p++ = '%';
|
*p++ = '%';
|
||||||
p = stpcpy(p, s);
|
p = stpcpy(p, s);
|
||||||
p += uint64toarray_radix10(Rexr(b.xedd) << 3 | reg, p);
|
p += uint64toarray_radix10(Rexr(b.xedd->op.rde) << 3 | reg, p);
|
||||||
if (g_dis_high) p = DisHigh(p, -1);
|
if (g_dis_high) p = DisHigh(p, -1);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisNq(struct DisBuilder b, char *p) {
|
static char *DisNq(struct DisBuilder b, char *p) {
|
||||||
return DisXmm(b, p, "mm", ModrmRm(b.xedd));
|
return DisXmm(b, p, "mm", ModrmRm(b.xedd->op.rde));
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisUq(struct DisBuilder b, char *p) {
|
static char *DisUq(struct DisBuilder b, char *p) {
|
||||||
return DisXmm(b, p, "mm", ModrmRm(b.xedd));
|
return DisXmm(b, p, "mm", ModrmRm(b.xedd->op.rde));
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisPq(struct DisBuilder b, char *p) {
|
static char *DisPq(struct DisBuilder b, char *p) {
|
||||||
return DisXmm(b, p, "mm", ModrmReg(b.xedd));
|
return DisXmm(b, p, "mm", ModrmReg(b.xedd->op.rde));
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisUdq(struct DisBuilder b, char *p) {
|
static char *DisUdq(struct DisBuilder b, char *p) {
|
||||||
return DisXmm(b, p, "xmm", ModrmRm(b.xedd));
|
return DisXmm(b, p, "xmm", ModrmRm(b.xedd->op.rde));
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisVdq(struct DisBuilder b, char *p) {
|
static char *DisVdq(struct DisBuilder b, char *p) {
|
||||||
return DisXmm(b, p, "xmm", ModrmReg(b.xedd));
|
return DisXmm(b, p, "xmm", ModrmReg(b.xedd->op.rde));
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisQq(struct DisBuilder b, char *p) {
|
static char *DisQq(struct DisBuilder b, char *p) {
|
||||||
if (IsModrmRegister(b.xedd)) {
|
if (IsModrmRegister(b.xedd->op.rde)) {
|
||||||
return DisNq(b, p);
|
return DisNq(b, p);
|
||||||
} else {
|
} else {
|
||||||
return DisM(b, p);
|
return DisM(b, p);
|
||||||
|
@ -385,9 +391,9 @@ static char *DisQq(struct DisBuilder b, char *p) {
|
||||||
|
|
||||||
static char *DisEst(struct DisBuilder b, char *p) {
|
static char *DisEst(struct DisBuilder b, char *p) {
|
||||||
p = DisRegister(p, "st");
|
p = DisRegister(p, "st");
|
||||||
if (ModrmRm(b.xedd) != 0) {
|
if (ModrmRm(b.xedd->op.rde) != 0) {
|
||||||
*p++ = '(';
|
*p++ = '(';
|
||||||
*p++ = '0' + ModrmRm(b.xedd);
|
*p++ = '0' + ModrmRm(b.xedd->op.rde);
|
||||||
*p++ = ')';
|
*p++ = ')';
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
}
|
}
|
||||||
|
@ -395,7 +401,7 @@ static char *DisEst(struct DisBuilder b, char *p) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisEst1(struct DisBuilder b, char *p) {
|
static char *DisEst1(struct DisBuilder b, char *p) {
|
||||||
if (ModrmRm(b.xedd) != 1) {
|
if (ModrmRm(b.xedd->op.rde) != 1) {
|
||||||
p = DisEst(b, p);
|
p = DisEst(b, p);
|
||||||
} else {
|
} else {
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
|
@ -404,7 +410,7 @@ static char *DisEst1(struct DisBuilder b, char *p) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisEssr(struct DisBuilder b, char *p) {
|
static char *DisEssr(struct DisBuilder b, char *p) {
|
||||||
if (IsModrmRegister(b.xedd)) {
|
if (IsModrmRegister(b.xedd->op.rde)) {
|
||||||
return DisEst(b, p);
|
return DisEst(b, p);
|
||||||
} else {
|
} else {
|
||||||
return DisM(b, p);
|
return DisM(b, p);
|
||||||
|
@ -412,7 +418,7 @@ static char *DisEssr(struct DisBuilder b, char *p) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *DisWps(struct DisBuilder b, char *p) {
|
static char *DisWps(struct DisBuilder b, char *p) {
|
||||||
if (IsModrmRegister(b.xedd)) {
|
if (IsModrmRegister(b.xedd->op.rde)) {
|
||||||
return DisUdq(b, p);
|
return DisUdq(b, p);
|
||||||
} else {
|
} else {
|
||||||
return DisM(b, p);
|
return DisM(b, p);
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
#include "libc/log/check.h"
|
#include "libc/log/check.h"
|
||||||
#include "libc/nexgen32e/tinystrcmp.h"
|
#include "libc/nexgen32e/tinystrcmp.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "tool/build/lib/case.h"
|
|
||||||
#include "tool/build/lib/dis.h"
|
#include "tool/build/lib/dis.h"
|
||||||
#include "tool/build/lib/modrm.h"
|
#include "tool/build/lib/modrm.h"
|
||||||
|
|
||||||
|
@ -29,15 +28,26 @@ static const char kAluOp[8][4] = {"add", "or", "adc", "sbb",
|
||||||
static const char kBitOp[8][4] = {"rol", "ror", "rcl", "rcr",
|
static const char kBitOp[8][4] = {"rol", "ror", "rcl", "rcr",
|
||||||
"shl", "shr", "sal", "sar"};
|
"shl", "shr", "sal", "sar"};
|
||||||
|
|
||||||
|
static bool IsProbablyByteOp(struct XedDecodedInst *x) {
|
||||||
|
return !(x->op.opcode & 1);
|
||||||
|
}
|
||||||
|
|
||||||
static int IsRepOpcode(struct DisBuilder b) {
|
static int IsRepOpcode(struct DisBuilder b) {
|
||||||
switch (b.xedd->op.opcode & ~1u) {
|
switch (b.xedd->op.opcode & ~1u) {
|
||||||
CASE(0x6C /*INS */, return 1);
|
case 0x6C: /* INS */
|
||||||
CASE(0x6E /*OUTS*/, return 1);
|
return 1;
|
||||||
CASE(0xA4 /*MOVS*/, return 1);
|
case 0x6E: /* OUTS */
|
||||||
CASE(0xAA /*STOS*/, return 1);
|
return 1;
|
||||||
CASE(0xAC /*LODS*/, return 1);
|
case 0xA4: /* MOVS */
|
||||||
CASE(0xA6 /*CMPS*/, return 2);
|
return 1;
|
||||||
CASE(0xAE /*SCAS*/, return 2);
|
case 0xAA: /* STOS */
|
||||||
|
return 1;
|
||||||
|
case 0xAC: /* LODS */
|
||||||
|
return 1;
|
||||||
|
case 0xA6: /* CMPS */
|
||||||
|
return 2;
|
||||||
|
case 0xAE: /* SCAS */
|
||||||
|
return 2;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -45,7 +55,7 @@ static int IsRepOpcode(struct DisBuilder b) {
|
||||||
|
|
||||||
static char *DisRepPrefix(struct DisBuilder b, char *p) {
|
static char *DisRepPrefix(struct DisBuilder b, char *p) {
|
||||||
const char *s;
|
const char *s;
|
||||||
if (Rep(b.xedd) && b.xedd->op.map == XED_ILD_MAP0) {
|
if (Rep(b.xedd->op.rde) && b.xedd->op.map == XED_ILD_MAP0) {
|
||||||
switch (IsRepOpcode(b)) {
|
switch (IsRepOpcode(b)) {
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
|
@ -53,7 +63,7 @@ static char *DisRepPrefix(struct DisBuilder b, char *p) {
|
||||||
p = stpcpy(p, "rep ");
|
p = stpcpy(p, "rep ");
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
p = stpcpy(p, Rep(b.xedd) == 2 ? "repnz " : "repz ");
|
p = stpcpy(p, Rep(b.xedd->op.rde) == 2 ? "repnz " : "repz ");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -81,30 +91,30 @@ static char *DisName(struct DisBuilder b, char *bp, const char *name,
|
||||||
if (b.xedd->op.lock) p = stpcpy(p, "lock ");
|
if (b.xedd->op.lock) p = stpcpy(p, "lock ");
|
||||||
p = DisRepPrefix(b, p);
|
p = DisRepPrefix(b, p);
|
||||||
if (tinystrcmp(name, "BIT") == 0) {
|
if (tinystrcmp(name, "BIT") == 0) {
|
||||||
p = stpcpy(p, kBitOp[ModrmReg(b.xedd)]);
|
p = stpcpy(p, kBitOp[ModrmReg(b.xedd->op.rde)]);
|
||||||
} else if (tinystrcmp(name, "CALL") == 0) {
|
} else if (tinystrcmp(name, "CALL") == 0) {
|
||||||
p = stpcpy(p, "call");
|
p = stpcpy(p, "call");
|
||||||
} else if (tinystrcmp(name, "JMP") == 0) {
|
} else if (tinystrcmp(name, "JMP") == 0) {
|
||||||
p = stpcpy(p, "jmp");
|
p = stpcpy(p, "jmp");
|
||||||
} else if (tinystrcmp(name, "jcxz") == 0) {
|
} else if (tinystrcmp(name, "jcxz") == 0) {
|
||||||
p = stpcpy(p, Asz(b.xedd) ? "jecxz" : "jrcxz");
|
p = stpcpy(p, Asz(b.xedd->op.rde) ? "jecxz" : "jrcxz");
|
||||||
p = DisBranchTaken(b, p);
|
p = DisBranchTaken(b, p);
|
||||||
} else if (tinystrcmp(name, "loop") == 0) {
|
} else if (tinystrcmp(name, "loop") == 0) {
|
||||||
p = stpcpy(p, Asz(b.xedd) ? "loopl" : "loop");
|
p = stpcpy(p, Asz(b.xedd->op.rde) ? "loopl" : "loop");
|
||||||
p = DisBranchTaken(b, p);
|
p = DisBranchTaken(b, p);
|
||||||
} else if (tinystrcmp(name, "loope") == 0) {
|
} else if (tinystrcmp(name, "loope") == 0) {
|
||||||
p = stpcpy(p, Asz(b.xedd) ? "loopel" : "loope");
|
p = stpcpy(p, Asz(b.xedd->op.rde) ? "loopel" : "loope");
|
||||||
p = DisBranchTaken(b, p);
|
p = DisBranchTaken(b, p);
|
||||||
} else if (tinystrcmp(name, "loopne") == 0) {
|
} else if (tinystrcmp(name, "loopne") == 0) {
|
||||||
p = stpcpy(p, Asz(b.xedd) ? "loopnel" : "loopne");
|
p = stpcpy(p, Asz(b.xedd->op.rde) ? "loopnel" : "loopne");
|
||||||
p = DisBranchTaken(b, p);
|
p = DisBranchTaken(b, p);
|
||||||
} else if (tinystrcmp(name, "cwtl") == 0) {
|
} else if (tinystrcmp(name, "cwtl") == 0) {
|
||||||
if (Osz(b.xedd)) name = "cbtw";
|
if (Osz(b.xedd->op.rde)) name = "cbtw";
|
||||||
if (Rexw(b.xedd)) name = "cltq";
|
if (Rexw(b.xedd->op.rde)) name = "cltq";
|
||||||
p = stpcpy(p, name);
|
p = stpcpy(p, name);
|
||||||
} else if (tinystrcmp(name, "cltd") == 0) {
|
} else if (tinystrcmp(name, "cltd") == 0) {
|
||||||
if (Osz(b.xedd)) name = "cwtd";
|
if (Osz(b.xedd->op.rde)) name = "cwtd";
|
||||||
if (Rexw(b.xedd)) name = "cqto";
|
if (Rexw(b.xedd->op.rde)) name = "cqto";
|
||||||
p = stpcpy(p, name);
|
p = stpcpy(p, name);
|
||||||
} else {
|
} else {
|
||||||
notbyte = false;
|
notbyte = false;
|
||||||
|
@ -115,7 +125,7 @@ static char *DisName(struct DisBuilder b, char *bp, const char *name,
|
||||||
*p++ = *np;
|
*p++ = *np;
|
||||||
}
|
}
|
||||||
if (tinystrcmp(name, "ALU") == 0) {
|
if (tinystrcmp(name, "ALU") == 0) {
|
||||||
p = stpcpy(p, kAluOp[ModrmReg(b.xedd)]);
|
p = stpcpy(p, kAluOp[ModrmReg(b.xedd->op.rde)]);
|
||||||
} else if (tinystrcmp(np, "WLQ") == 0) {
|
} else if (tinystrcmp(np, "WLQ") == 0) {
|
||||||
notbyte = true;
|
notbyte = true;
|
||||||
wantsuffix = true;
|
wantsuffix = true;
|
||||||
|
@ -130,21 +140,21 @@ static char *DisName(struct DisBuilder b, char *bp, const char *name,
|
||||||
notbyte = true;
|
notbyte = true;
|
||||||
wantsuffixsd = true;
|
wantsuffixsd = true;
|
||||||
} else if (tinystrcmp(np, "ABS") == 0) {
|
} else if (tinystrcmp(np, "ABS") == 0) {
|
||||||
if (Rexw(b.xedd)) p = stpcpy(p, "abs");
|
if (Rexw(b.xedd->op.rde)) p = stpcpy(p, "abs");
|
||||||
} else if (tinystrcmp(np, "BT") == 0) {
|
} else if (tinystrcmp(np, "BT") == 0) {
|
||||||
p = DisBranchTaken(b, p);
|
p = DisBranchTaken(b, p);
|
||||||
}
|
}
|
||||||
if (wantsuffixsd) {
|
if (wantsuffixsd) {
|
||||||
if (Osz(b.xedd)) {
|
if (Osz(b.xedd->op.rde)) {
|
||||||
*p++ = 'd';
|
*p++ = 'd';
|
||||||
} else {
|
} else {
|
||||||
*p++ = 's';
|
*p++ = 's';
|
||||||
}
|
}
|
||||||
} else if (wantsuffix || (ambiguous && !startswith(name, "f") &&
|
} else if (wantsuffix || (ambiguous && !startswith(name, "f") &&
|
||||||
!startswith(name, "set"))) {
|
!startswith(name, "set"))) {
|
||||||
if (Osz(b.xedd)) {
|
if (Osz(b.xedd->op.rde)) {
|
||||||
*p++ = 'w';
|
*p++ = 'w';
|
||||||
} else if (Rexw(b.xedd)) {
|
} else if (Rexw(b.xedd->op.rde)) {
|
||||||
*p++ = 'q';
|
*p++ = 'q';
|
||||||
} else if (ambiguous && !notbyte && IsProbablyByteOp(b.xedd)) {
|
} else if (ambiguous && !notbyte && IsProbablyByteOp(b.xedd)) {
|
||||||
*p++ = 'b';
|
*p++ = 'b';
|
||||||
|
@ -169,11 +179,12 @@ char *DisInst(struct DisBuilder b, char *p, const char *spec) {
|
||||||
char args[4][64];
|
char args[4][64];
|
||||||
char *s, *name, *state;
|
char *s, *name, *state;
|
||||||
bool hasarg, hasmodrm, hasregister, hasmemory;
|
bool hasarg, hasmodrm, hasregister, hasmemory;
|
||||||
|
CHECK_EQ(0, (int)b.xedd->op.error);
|
||||||
DCHECK_LT(strlen(spec), 128);
|
DCHECK_LT(strlen(spec), 128);
|
||||||
hasarg = false;
|
hasarg = false;
|
||||||
hasmodrm = b.xedd->op.has_modrm;
|
hasmodrm = b.xedd->op.has_modrm;
|
||||||
hasmemory = hasmodrm && !IsModrmRegister(b.xedd);
|
hasmemory = hasmodrm && !IsModrmRegister(b.xedd->op.rde);
|
||||||
hasregister = hasmodrm && IsModrmRegister(b.xedd);
|
hasregister = hasmodrm && IsModrmRegister(b.xedd->op.rde);
|
||||||
name = strtok_r(strcpy(sbuf, spec), " ", &state);
|
name = strtok_r(strcpy(sbuf, spec), " ", &state);
|
||||||
for (n = 0; (s = strtok_r(NULL, " ", &state)); ++n) {
|
for (n = 0; (s = strtok_r(NULL, " ", &state)); ++n) {
|
||||||
hasarg = true;
|
hasarg = true;
|
||||||
|
|
|
@ -38,18 +38,18 @@ static const char kFpuName[][8][8] = {
|
||||||
|
|
||||||
char *DisOpFpu0(struct XedDecodedInst *x, int group) {
|
char *DisOpFpu0(struct XedDecodedInst *x, int group) {
|
||||||
const char *s;
|
const char *s;
|
||||||
s = kFpuName[group][ModrmRm(x)];
|
s = kFpuName[group][ModrmRm(x->op.rde)];
|
||||||
return *s ? s : UNKNOWN;
|
return *s ? s : UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *DisOpFpu1(struct XedDecodedInst *x, char *p, const char *extra) {
|
char *DisOpFpu1(struct XedDecodedInst *x, char *p, const char *extra) {
|
||||||
stpcpy(stpcpy(p, kFpuName[0][ModrmReg(x)]), extra);
|
stpcpy(stpcpy(p, kFpuName[0][ModrmReg(x->op.rde)]), extra);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *DisOp66(struct XedDecodedInst *x, char *p, const char *s, const char *a,
|
char *DisOp66(struct XedDecodedInst *x, char *p, const char *s, const char *a,
|
||||||
const char *b) {
|
const char *b) {
|
||||||
stpcpy(stpcpy(p, s), !Osz(x) ? a : b);
|
stpcpy(stpcpy(p, s), !Osz(x->op.rde) ? a : b);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,11 +76,11 @@ char *DisOpNqIbUdqIb(struct XedDecodedInst *x, char *p, const char *s) {
|
||||||
char *DisOpVpsWpsVssWssVpdWpdVsdWsd(struct XedDecodedInst *x, char *p,
|
char *DisOpVpsWpsVssWssVpdWpdVsdWsd(struct XedDecodedInst *x, char *p,
|
||||||
const char *s) {
|
const char *s) {
|
||||||
char *q = stpcpy(p, s);
|
char *q = stpcpy(p, s);
|
||||||
if (x->op.ild_f3) {
|
if (Rep(x->op.rde) == 3) {
|
||||||
stpcpy(q, "ss %Vss Wss");
|
stpcpy(q, "ss %Vss Wss");
|
||||||
} else if (x->op.ild_f2) {
|
} else if (Rep(x->op.rde) == 2) {
|
||||||
stpcpy(q, "sd %Vsd Wsd");
|
stpcpy(q, "sd %Vsd Wsd");
|
||||||
} else if (Osz(x)) {
|
} else if (Osz(x->op.rde)) {
|
||||||
stpcpy(q, "pd %Vpd Wpd");
|
stpcpy(q, "pd %Vpd Wpd");
|
||||||
} else {
|
} else {
|
||||||
stpcpy(q, "ps %Vps Wps");
|
stpcpy(q, "ps %Vps Wps");
|
||||||
|
@ -265,53 +265,53 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
|
||||||
RCASE(0xFC, "cld");
|
RCASE(0xFC, "cld");
|
||||||
RCASE(0xFD, "std");
|
RCASE(0xFD, "std");
|
||||||
case 0x8F:
|
case 0x8F:
|
||||||
switch (ModrmReg(x)) {
|
switch (ModrmReg(x->op.rde)) {
|
||||||
RCASE(0, "popWQ Evq");
|
RCASE(0, "popWQ Evq");
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xD9:
|
case 0xD9:
|
||||||
switch (ModrmReg(x)) {
|
switch (ModrmReg(x->op.rde)) {
|
||||||
RCASE(1, "fxch EST1");
|
RCASE(1, "fxch EST1");
|
||||||
RCASE(3, "fstps Msr %st");
|
RCASE(3, "fstps Msr %st");
|
||||||
case 0:
|
case 0:
|
||||||
if (IsModrmRegister(x)) {
|
if (IsModrmRegister(x->op.rde)) {
|
||||||
return "fld EST";
|
return "fld EST";
|
||||||
} else {
|
} else {
|
||||||
return "flds Msr";
|
return "flds Msr";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if (IsModrmRegister(x)) {
|
if (IsModrmRegister(x->op.rde)) {
|
||||||
return "fnop";
|
return "fnop";
|
||||||
} else {
|
} else {
|
||||||
return "fsts Msr %st";
|
return "fsts Msr %st";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
if (IsModrmRegister(x)) {
|
if (IsModrmRegister(x->op.rde)) {
|
||||||
return DisOpFpu0(x, 1);
|
return DisOpFpu0(x, 1);
|
||||||
} else {
|
} else {
|
||||||
return "fldenv Me";
|
return "fldenv Me";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
if (IsModrmRegister(x)) {
|
if (IsModrmRegister(x->op.rde)) {
|
||||||
return DisOpFpu0(x, 2);
|
return DisOpFpu0(x, 2);
|
||||||
} else {
|
} else {
|
||||||
return "fldcw Mw";
|
return "fldcw Mw";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
if (IsModrmRegister(x)) {
|
if (IsModrmRegister(x->op.rde)) {
|
||||||
return DisOpFpu0(x, 3);
|
return DisOpFpu0(x, 3);
|
||||||
} else {
|
} else {
|
||||||
return "fnstenv M";
|
return "fnstenv M";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
if (IsModrmRegister(x)) {
|
if (IsModrmRegister(x->op.rde)) {
|
||||||
return DisOpFpu0(x, 4);
|
return DisOpFpu0(x, 4);
|
||||||
} else {
|
} else {
|
||||||
return "fnstcw Mw";
|
return "fnstcw Mw";
|
||||||
|
@ -320,58 +320,58 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xDA:
|
case 0xDA:
|
||||||
switch (ModrmReg(x)) {
|
switch (ModrmReg(x->op.rde)) {
|
||||||
case 0:
|
case 0:
|
||||||
if (!IsModrmRegister(x)) {
|
if (!IsModrmRegister(x->op.rde)) {
|
||||||
return "fiaddl Mdi";
|
return "fiaddl Mdi";
|
||||||
} else {
|
} else {
|
||||||
return "fcmovb %st EST";
|
return "fcmovb %st EST";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (!IsModrmRegister(x)) {
|
if (!IsModrmRegister(x->op.rde)) {
|
||||||
return "fimull Mdi";
|
return "fimull Mdi";
|
||||||
} else {
|
} else {
|
||||||
return "fcmove %st EST";
|
return "fcmove %st EST";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if (!IsModrmRegister(x)) {
|
if (!IsModrmRegister(x->op.rde)) {
|
||||||
return "ficoml Mdi";
|
return "ficoml Mdi";
|
||||||
} else {
|
} else {
|
||||||
return "fcmovbe %st EST";
|
return "fcmovbe %st EST";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if (!IsModrmRegister(x)) {
|
if (!IsModrmRegister(x->op.rde)) {
|
||||||
return "ficompl Mdi";
|
return "ficompl Mdi";
|
||||||
} else {
|
} else {
|
||||||
return "fcmovu %st EST";
|
return "fcmovu %st EST";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
if (!IsModrmRegister(x)) {
|
if (!IsModrmRegister(x->op.rde)) {
|
||||||
return "fisubl Mdi";
|
return "fisubl Mdi";
|
||||||
} else {
|
} else {
|
||||||
return "fisubr Mdi";
|
return "fisubr Mdi";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
if (!IsModrmRegister(x)) {
|
if (!IsModrmRegister(x->op.rde)) {
|
||||||
return "fisubrl Mdi";
|
return "fisubrl Mdi";
|
||||||
} else {
|
} else {
|
||||||
return "fucompp";
|
return "fucompp";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
if (!IsModrmRegister(x)) {
|
if (!IsModrmRegister(x->op.rde)) {
|
||||||
return "fidivl Mdi";
|
return "fidivl Mdi";
|
||||||
} else {
|
} else {
|
||||||
return UNKNOWN;
|
return UNKNOWN;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
if (!IsModrmRegister(x)) {
|
if (!IsModrmRegister(x->op.rde)) {
|
||||||
return "fidivrl Mdi";
|
return "fidivrl Mdi";
|
||||||
} else {
|
} else {
|
||||||
return UNKNOWN;
|
return UNKNOWN;
|
||||||
|
@ -380,30 +380,30 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xDB:
|
case 0xDB:
|
||||||
switch (ModrmReg(x)) {
|
switch (ModrmReg(x->op.rde)) {
|
||||||
case 0:
|
case 0:
|
||||||
if (!IsModrmRegister(x)) {
|
if (!IsModrmRegister(x->op.rde)) {
|
||||||
return "fildl Mdi";
|
return "fildl Mdi";
|
||||||
} else {
|
} else {
|
||||||
return "fcmovnb %st EST";
|
return "fcmovnb %st EST";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (!IsModrmRegister(x)) {
|
if (!IsModrmRegister(x->op.rde)) {
|
||||||
return "fisttpl Mdi";
|
return "fisttpl Mdi";
|
||||||
} else {
|
} else {
|
||||||
return "fcmovne %st EST";
|
return "fcmovne %st EST";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if (!IsModrmRegister(x)) {
|
if (!IsModrmRegister(x->op.rde)) {
|
||||||
return "fistl Mdi";
|
return "fistl Mdi";
|
||||||
} else {
|
} else {
|
||||||
return "fcmovnbe %st EST";
|
return "fcmovnbe %st EST";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if (!IsModrmRegister(x)) {
|
if (!IsModrmRegister(x->op.rde)) {
|
||||||
return "fistpl Mdi";
|
return "fistpl Mdi";
|
||||||
} else {
|
} else {
|
||||||
return "fcmovnu %st EST";
|
return "fcmovnu %st EST";
|
||||||
|
@ -412,21 +412,21 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
|
||||||
case 4:
|
case 4:
|
||||||
return DisOpFpu0(x, 5);
|
return DisOpFpu0(x, 5);
|
||||||
case 5:
|
case 5:
|
||||||
if (!IsModrmRegister(x)) {
|
if (!IsModrmRegister(x->op.rde)) {
|
||||||
return "fldt Mer";
|
return "fldt Mer";
|
||||||
} else {
|
} else {
|
||||||
return "fucomi %st EST";
|
return "fucomi %st EST";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
if (IsModrmRegister(x)) {
|
if (IsModrmRegister(x->op.rde)) {
|
||||||
return "fcomi %st EST";
|
return "fcomi %st EST";
|
||||||
} else {
|
} else {
|
||||||
return UNKNOWN;
|
return UNKNOWN;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
if (!IsModrmRegister(x)) {
|
if (!IsModrmRegister(x->op.rde)) {
|
||||||
return "fstpt Mer";
|
return "fstpt Mer";
|
||||||
} else {
|
} else {
|
||||||
return UNKNOWN;
|
return UNKNOWN;
|
||||||
|
@ -435,12 +435,12 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xD8:
|
case 0xD8:
|
||||||
return DisOpFpu1(x, p, !IsModrmRegister(x) ? "s Msr" : " EST1");
|
return DisOpFpu1(x, p, !IsModrmRegister(x->op.rde) ? "s Msr" : " EST1");
|
||||||
case 0xDC:
|
case 0xDC:
|
||||||
if (!IsModrmRegister(x)) {
|
if (!IsModrmRegister(x->op.rde)) {
|
||||||
return DisOpFpu1(x, p, "l Mdr");
|
return DisOpFpu1(x, p, "l Mdr");
|
||||||
} else {
|
} else {
|
||||||
switch (ModrmReg(x)) {
|
switch (ModrmReg(x->op.rde)) {
|
||||||
RCASE(0, "fadd EST %st");
|
RCASE(0, "fadd EST %st");
|
||||||
RCASE(1, "fmul EST %st");
|
RCASE(1, "fmul EST %st");
|
||||||
RCASE(2, "fcom %st EST");
|
RCASE(2, "fcom %st EST");
|
||||||
|
@ -453,8 +453,8 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xDD:
|
case 0xDD:
|
||||||
if (!IsModrmRegister(x)) {
|
if (!IsModrmRegister(x->op.rde)) {
|
||||||
switch (ModrmReg(x)) {
|
switch (ModrmReg(x->op.rde)) {
|
||||||
RCASE(0, "fldl Mdr");
|
RCASE(0, "fldl Mdr");
|
||||||
RCASE(1, "fisttpll Mqi");
|
RCASE(1, "fisttpll Mqi");
|
||||||
RCASE(2, "fstl Mdr");
|
RCASE(2, "fstl Mdr");
|
||||||
|
@ -464,7 +464,7 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
|
||||||
RCASE(7, "fnstsw Mst");
|
RCASE(7, "fnstsw Mst");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (ModrmReg(x)) {
|
switch (ModrmReg(x->op.rde)) {
|
||||||
RCASE(0, "ffree EST");
|
RCASE(0, "ffree EST");
|
||||||
RCASE(1, "fxch EST");
|
RCASE(1, "fxch EST");
|
||||||
RCASE(2, "fst EST");
|
RCASE(2, "fst EST");
|
||||||
|
@ -475,8 +475,8 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xDE:
|
case 0xDE:
|
||||||
if (!IsModrmRegister(x)) {
|
if (!IsModrmRegister(x->op.rde)) {
|
||||||
switch (ModrmReg(x)) {
|
switch (ModrmReg(x->op.rde)) {
|
||||||
RCASE(0, "fiadds Mwi");
|
RCASE(0, "fiadds Mwi");
|
||||||
RCASE(1, "fimuls Mwi");
|
RCASE(1, "fimuls Mwi");
|
||||||
RCASE(2, "ficoms Mwi");
|
RCASE(2, "ficoms Mwi");
|
||||||
|
@ -487,7 +487,7 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
|
||||||
RCASE(7, "fidivrs Mwi");
|
RCASE(7, "fidivrs Mwi");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (ModrmReg(x)) {
|
switch (ModrmReg(x->op.rde)) {
|
||||||
RCASE(0, "faddp EST1");
|
RCASE(0, "faddp EST1");
|
||||||
RCASE(1, "fmulp EST1");
|
RCASE(1, "fmulp EST1");
|
||||||
RCASE(2, "fcomp EST1");
|
RCASE(2, "fcomp EST1");
|
||||||
|
@ -500,8 +500,8 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xDF:
|
case 0xDF:
|
||||||
if (!IsModrmRegister(x)) {
|
if (!IsModrmRegister(x->op.rde)) {
|
||||||
switch (ModrmReg(x)) {
|
switch (ModrmReg(x->op.rde)) {
|
||||||
RCASE(0, "filds Mwi");
|
RCASE(0, "filds Mwi");
|
||||||
RCASE(1, "fisttps Mwi");
|
RCASE(1, "fisttps Mwi");
|
||||||
RCASE(2, "fists Mwi");
|
RCASE(2, "fists Mwi");
|
||||||
|
@ -512,7 +512,7 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
|
||||||
RCASE(7, "fistpll Mqi");
|
RCASE(7, "fistpll Mqi");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (ModrmReg(x)) {
|
switch (ModrmReg(x->op.rde)) {
|
||||||
RCASE(0, "ffreep EST");
|
RCASE(0, "ffreep EST");
|
||||||
RCASE(1, "fxch");
|
RCASE(1, "fxch");
|
||||||
RCASE(2, "fstp EST");
|
RCASE(2, "fstp EST");
|
||||||
|
@ -524,7 +524,7 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xF6:
|
case 0xF6:
|
||||||
switch (ModrmReg(x)) {
|
switch (ModrmReg(x->op.rde)) {
|
||||||
RCASE(0, "test Eb Ib");
|
RCASE(0, "test Eb Ib");
|
||||||
RCASE(1, "test Eb Ib");
|
RCASE(1, "test Eb Ib");
|
||||||
RCASE(2, "not Eb");
|
RCASE(2, "not Eb");
|
||||||
|
@ -536,7 +536,7 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xF7:
|
case 0xF7:
|
||||||
switch (ModrmReg(x)) {
|
switch (ModrmReg(x->op.rde)) {
|
||||||
RCASE(0, "test Evqp Ivds");
|
RCASE(0, "test Evqp Ivds");
|
||||||
RCASE(1, "test Evqp Ivds");
|
RCASE(1, "test Evqp Ivds");
|
||||||
RCASE(2, "not Evqp");
|
RCASE(2, "not Evqp");
|
||||||
|
@ -548,13 +548,13 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xFE:
|
case 0xFE:
|
||||||
switch (ModrmReg(x)) {
|
switch (ModrmReg(x->op.rde)) {
|
||||||
RCASE(0, "inc Eb");
|
RCASE(0, "inc Eb");
|
||||||
RCASE(1, "dec Eb");
|
RCASE(1, "dec Eb");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xFF:
|
case 0xFF:
|
||||||
switch (ModrmReg(x)) {
|
switch (ModrmReg(x->op.rde)) {
|
||||||
RCASE(0, "inc Evqp");
|
RCASE(0, "inc Evqp");
|
||||||
RCASE(1, "dec Evqp");
|
RCASE(1, "dec Evqp");
|
||||||
RCASE(2, "CALL Eq");
|
RCASE(2, "CALL Eq");
|
||||||
|
@ -580,8 +580,8 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
|
||||||
RCASE(0x28, "movapSD %Vps Wps");
|
RCASE(0x28, "movapSD %Vps Wps");
|
||||||
RCASE(0x29, "movapSD Wps %Vps");
|
RCASE(0x29, "movapSD Wps %Vps");
|
||||||
RCASE(0x2B, "movntpSD Mps %Vps");
|
RCASE(0x2B, "movntpSD Mps %Vps");
|
||||||
RCASE(0x2E, Osz(x) ? "ucomisd %Vsd Wsd" : "ucomiss %Vss Wss");
|
RCASE(0x2E, Osz(x->op.rde) ? "ucomisd %Vsd Wsd" : "ucomiss %Vss Wss");
|
||||||
RCASE(0x2F, Osz(x) ? "comisd %Vsd Wsd" : "comiss %Vss Wss");
|
RCASE(0x2F, Osz(x->op.rde) ? "comisd %Vsd Wsd" : "comiss %Vss Wss");
|
||||||
RCASE(0x31, "rdtsc");
|
RCASE(0x31, "rdtsc");
|
||||||
RCASE(0x40, "cmovo %Gvqp Evqp");
|
RCASE(0x40, "cmovo %Gvqp Evqp");
|
||||||
RCASE(0x41, "cmovno %Gvqp Evqp");
|
RCASE(0x41, "cmovno %Gvqp Evqp");
|
||||||
|
@ -693,7 +693,7 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
|
||||||
RCASE(0xD3, DisOpPqQqVdqWdq(x, p, "psrlq"));
|
RCASE(0xD3, DisOpPqQqVdqWdq(x, p, "psrlq"));
|
||||||
RCASE(0xD4, DisOpPqQqVdqWdq(x, p, "paddq"));
|
RCASE(0xD4, DisOpPqQqVdqWdq(x, p, "paddq"));
|
||||||
RCASE(0xD5, DisOpPqQqVdqWdq(x, p, "pmullw"));
|
RCASE(0xD5, DisOpPqQqVdqWdq(x, p, "pmullw"));
|
||||||
RCASE(0xD7, Osz(x) ? "pmovmskb %Gdqp %Udq" : "pmovmskb %Gdqp %Nq");
|
RCASE(0xD7, Osz(x->op.rde) ? "pmovmskb %Gdqp %Udq" : "pmovmskb %Gdqp %Nq");
|
||||||
RCASE(0xD8, DisOpPqQqVdqWdq(x, p, "psubusb"));
|
RCASE(0xD8, DisOpPqQqVdqWdq(x, p, "psubusb"));
|
||||||
RCASE(0xD9, DisOpPqQqVdqWdq(x, p, "psubusw"));
|
RCASE(0xD9, DisOpPqQqVdqWdq(x, p, "psubusw"));
|
||||||
RCASE(0xDA, DisOpPqQqVdqWdq(x, p, "pminub"));
|
RCASE(0xDA, DisOpPqQqVdqWdq(x, p, "pminub"));
|
||||||
|
@ -708,7 +708,7 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
|
||||||
RCASE(0xE3, DisOpPqQqVdqWdq(x, p, "pavgw"));
|
RCASE(0xE3, DisOpPqQqVdqWdq(x, p, "pavgw"));
|
||||||
RCASE(0xE4, DisOpPqQqVdqWdq(x, p, "pmulhuw"));
|
RCASE(0xE4, DisOpPqQqVdqWdq(x, p, "pmulhuw"));
|
||||||
RCASE(0xE5, DisOpPqQqVdqWdq(x, p, "pmulhw"));
|
RCASE(0xE5, DisOpPqQqVdqWdq(x, p, "pmulhw"));
|
||||||
RCASE(0xE7, Osz(x) ? "movntdq Mdq %Vdq" : "movntq Mq %Pq");
|
RCASE(0xE7, Osz(x->op.rde) ? "movntdq Mdq %Vdq" : "movntq Mq %Pq");
|
||||||
RCASE(0xE8, DisOpPqQqVdqWdq(x, p, "psubsb"));
|
RCASE(0xE8, DisOpPqQqVdqWdq(x, p, "psubsb"));
|
||||||
RCASE(0xE9, DisOpPqQqVdqWdq(x, p, "psubsw"));
|
RCASE(0xE9, DisOpPqQqVdqWdq(x, p, "psubsw"));
|
||||||
RCASE(0xEA, DisOpPqQqVdqWdq(x, p, "pminsw"));
|
RCASE(0xEA, DisOpPqQqVdqWdq(x, p, "pminsw"));
|
||||||
|
@ -740,7 +740,7 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x70:
|
case 0x70:
|
||||||
switch (Rep(x) | Osz(x)) {
|
switch (Rep(x->op.rde) | Osz(x->op.rde)) {
|
||||||
RCASE(0, "pshufw %Pq Qq Ib");
|
RCASE(0, "pshufw %Pq Qq Ib");
|
||||||
RCASE(1, "pshufd %Vdq Wdq Ib");
|
RCASE(1, "pshufd %Vdq Wdq Ib");
|
||||||
RCASE(2, "pshuflw %Vdq Wdq Ib");
|
RCASE(2, "pshuflw %Vdq Wdq Ib");
|
||||||
|
@ -748,21 +748,21 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x71:
|
case 0x71:
|
||||||
switch (ModrmReg(x)) {
|
switch (ModrmReg(x->op.rde)) {
|
||||||
RCASE(2, DisOpNqIbUdqIb(x, p, "psrlw"));
|
RCASE(2, DisOpNqIbUdqIb(x, p, "psrlw"));
|
||||||
RCASE(4, DisOpNqIbUdqIb(x, p, "psraw"));
|
RCASE(4, DisOpNqIbUdqIb(x, p, "psraw"));
|
||||||
RCASE(6, DisOpNqIbUdqIb(x, p, "psllw"));
|
RCASE(6, DisOpNqIbUdqIb(x, p, "psllw"));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x72:
|
case 0x72:
|
||||||
switch (ModrmReg(x)) {
|
switch (ModrmReg(x->op.rde)) {
|
||||||
RCASE(2, DisOpNqIbUdqIb(x, p, "psrld"));
|
RCASE(2, DisOpNqIbUdqIb(x, p, "psrld"));
|
||||||
RCASE(4, DisOpNqIbUdqIb(x, p, "psrad"));
|
RCASE(4, DisOpNqIbUdqIb(x, p, "psrad"));
|
||||||
RCASE(6, DisOpNqIbUdqIb(x, p, "pslld"));
|
RCASE(6, DisOpNqIbUdqIb(x, p, "pslld"));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x73:
|
case 0x73:
|
||||||
switch (ModrmReg(x)) {
|
switch (ModrmReg(x->op.rde)) {
|
||||||
RCASE(2, DisOpNqIbUdqIb(x, p, "psrlq"));
|
RCASE(2, DisOpNqIbUdqIb(x, p, "psrlq"));
|
||||||
RCASE(3, DisOpNqIbUdqIb(x, p, "psrldq"));
|
RCASE(3, DisOpNqIbUdqIb(x, p, "psrldq"));
|
||||||
RCASE(6, DisOpNqIbUdqIb(x, p, "psllq"));
|
RCASE(6, DisOpNqIbUdqIb(x, p, "psllq"));
|
||||||
|
@ -770,7 +770,7 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xAE:
|
case 0xAE:
|
||||||
switch (ModrmReg(x)) {
|
switch (ModrmReg(x->op.rde)) {
|
||||||
RCASE(0, "fxsave Mstx %st %st(1)");
|
RCASE(0, "fxsave Mstx %st %st(1)");
|
||||||
RCASE(1, "fxrstor Mstx %st %st(1)");
|
RCASE(1, "fxrstor Mstx %st %st(1)");
|
||||||
RCASE(2, "ldmxcsr Md");
|
RCASE(2, "ldmxcsr Md");
|
||||||
|
@ -787,7 +787,7 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xBA:
|
case 0xBA:
|
||||||
switch (ModrmReg(x)) {
|
switch (ModrmReg(x->op.rde)) {
|
||||||
RCASE(4, "btWLQ Evqp Ib");
|
RCASE(4, "btWLQ Evqp Ib");
|
||||||
RCASE(5, "btsWLQ Evqp Ib");
|
RCASE(5, "btsWLQ Evqp Ib");
|
||||||
RCASE(6, "btrWLQ Evqp Ib");
|
RCASE(6, "btrWLQ Evqp Ib");
|
||||||
|
@ -795,36 +795,36 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x10:
|
case 0x10:
|
||||||
if (x->op.ild_f3) {
|
if (Rep(x->op.rde) == 3) {
|
||||||
return "movss %Vss Wss";
|
return "movss %Vss Wss";
|
||||||
} else if (x->op.ild_f2) {
|
} else if (Rep(x->op.rde) == 2) {
|
||||||
return "movsd %Vsd Wsd";
|
return "movsd %Vsd Wsd";
|
||||||
} else if (Osz(x)) {
|
} else if (Osz(x->op.rde)) {
|
||||||
return "movupd %Vpd Wpd";
|
return "movupd %Vpd Wpd";
|
||||||
} else {
|
} else {
|
||||||
return "movups %Vps Wps";
|
return "movups %Vps Wps";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x11:
|
case 0x11:
|
||||||
if (x->op.ild_f3) {
|
if (Rep(x->op.rde) == 3) {
|
||||||
return "movss Wss %Vss";
|
return "movss Wss %Vss";
|
||||||
} else if (x->op.ild_f2) {
|
} else if (Rep(x->op.rde) == 2) {
|
||||||
return "movsd Wsd %Vsd";
|
return "movsd Wsd %Vsd";
|
||||||
} else if (Osz(x)) {
|
} else if (Osz(x->op.rde)) {
|
||||||
return "movupd Wpd %Vpd";
|
return "movupd Wpd %Vpd";
|
||||||
} else {
|
} else {
|
||||||
return "movups Wps %Vps";
|
return "movups Wps %Vps";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xC4:
|
case 0xC4:
|
||||||
if (!Osz(x)) {
|
if (!Osz(x->op.rde)) {
|
||||||
if (IsModrmRegister(x)) {
|
if (IsModrmRegister(x->op.rde)) {
|
||||||
return "pinsrw %Pq %Rdqp Ib";
|
return "pinsrw %Pq %Rdqp Ib";
|
||||||
} else {
|
} else {
|
||||||
return "pinsrw %Pq Mw Ib";
|
return "pinsrw %Pq Mw Ib";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (IsModrmRegister(x)) {
|
if (IsModrmRegister(x->op.rde)) {
|
||||||
return "pinsrw %Vdq %Rdqp Ib";
|
return "pinsrw %Vdq %Rdqp Ib";
|
||||||
} else {
|
} else {
|
||||||
return "pinsrw %Vdq Mw Ib";
|
return "pinsrw %Vdq Mw Ib";
|
||||||
|
@ -832,39 +832,39 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xC5:
|
case 0xC5:
|
||||||
if (!Osz(x)) {
|
if (!Osz(x->op.rde)) {
|
||||||
return "pextrw %Gdqp %Nq Ib";
|
return "pextrw %Gdqp %Nq Ib";
|
||||||
} else {
|
} else {
|
||||||
return "pextrw %Gdqp %Udq Ib";
|
return "pextrw %Gdqp %Udq Ib";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xC6:
|
case 0xC6:
|
||||||
if (!Osz(x)) {
|
if (!Osz(x->op.rde)) {
|
||||||
return "shufps %Vps Wps Ib";
|
return "shufps %Vps Wps Ib";
|
||||||
} else {
|
} else {
|
||||||
return "shufpd %Vpd Wpd Ib";
|
return "shufpd %Vpd Wpd Ib";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xC7:
|
case 0xC7:
|
||||||
if (Rexw(x)) {
|
if (Rexw(x->op.rde)) {
|
||||||
return "cmpxchg16b Mdq";
|
return "cmpxchg16b Mdq";
|
||||||
} else {
|
} else {
|
||||||
return "cmpxchg8b Mq";
|
return "cmpxchg8b Mq";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xD6:
|
case 0xD6:
|
||||||
if (Osz(x)) {
|
if (Osz(x->op.rde)) {
|
||||||
return "movq Wq %Vq";
|
return "movq Wq %Vq";
|
||||||
} else if (x->op.ild_f3) {
|
} else if (Rep(x->op.rde) == 3) {
|
||||||
return "movq2dq %Vdq %Nq";
|
return "movq2dq %Vdq %Nq";
|
||||||
} else if (x->op.ild_f2) {
|
} else if (Rep(x->op.rde) == 2) {
|
||||||
return "movq2dq %Pq %Uq";
|
return "movq2dq %Pq %Uq";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x12:
|
case 0x12:
|
||||||
switch (Rep(x) | Osz(x)) {
|
switch (Rep(x->op.rde) | Osz(x->op.rde)) {
|
||||||
case 0:
|
case 0:
|
||||||
if (IsModrmRegister(x)) {
|
if (IsModrmRegister(x->op.rde)) {
|
||||||
return "movhlps %Vq %Uq";
|
return "movhlps %Vq %Uq";
|
||||||
} else {
|
} else {
|
||||||
return "movlps %Vq Mq";
|
return "movlps %Vq Mq";
|
||||||
|
@ -881,16 +881,16 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x13:
|
case 0x13:
|
||||||
if (Osz(x)) {
|
if (Osz(x->op.rde)) {
|
||||||
return "movlpd Mq %Vq";
|
return "movlpd Mq %Vq";
|
||||||
} else {
|
} else {
|
||||||
return "movlps Mq %Vq";
|
return "movlps Mq %Vq";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x16:
|
case 0x16:
|
||||||
switch (Rep(x) | Osz(x)) {
|
switch (Rep(x->op.rde) | Osz(x->op.rde)) {
|
||||||
case 0:
|
case 0:
|
||||||
if (IsModrmRegister(x)) {
|
if (IsModrmRegister(x->op.rde)) {
|
||||||
return "movlhps %Vq %Uq";
|
return "movlhps %Vq %Uq";
|
||||||
} else {
|
} else {
|
||||||
return "movhps %Vq Mq";
|
return "movhps %Vq Mq";
|
||||||
|
@ -905,85 +905,85 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x17:
|
case 0x17:
|
||||||
if (Osz(x)) {
|
if (Osz(x->op.rde)) {
|
||||||
return "movhpd Mq %Vq";
|
return "movhpd Mq %Vq";
|
||||||
} else {
|
} else {
|
||||||
return "movhps Mq %Vq";
|
return "movhps Mq %Vq";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x2A:
|
case 0x2A:
|
||||||
if (x->op.ild_f3) {
|
if (Rep(x->op.rde) == 3) {
|
||||||
return "cvtsi2ss %Vss Edqp";
|
return "cvtsi2ss %Vss Edqp";
|
||||||
} else if (x->op.ild_f2) {
|
} else if (Rep(x->op.rde) == 2) {
|
||||||
return "cvtsi2sd %Vsd Edqp";
|
return "cvtsi2sd %Vsd Edqp";
|
||||||
} else if (Osz(x)) {
|
} else if (Osz(x->op.rde)) {
|
||||||
return "cvtpi2pd %Vpd Qpi";
|
return "cvtpi2pd %Vpd Qpi";
|
||||||
} else {
|
} else {
|
||||||
return "cvtpi2ps %Vps Qpi";
|
return "cvtpi2ps %Vps Qpi";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x2C:
|
case 0x2C:
|
||||||
if (x->op.ild_f3) {
|
if (Rep(x->op.rde) == 3) {
|
||||||
return "cvttss2si %Gdqp Wss";
|
return "cvttss2si %Gdqp Wss";
|
||||||
} else if (x->op.ild_f2) {
|
} else if (Rep(x->op.rde) == 2) {
|
||||||
return "cvttsd2si %Gdqp Wsd";
|
return "cvttsd2si %Gdqp Wsd";
|
||||||
} else if (Osz(x)) {
|
} else if (Osz(x->op.rde)) {
|
||||||
return "cvttpd2pi %Ppi Wpd";
|
return "cvttpd2pi %Ppi Wpd";
|
||||||
} else {
|
} else {
|
||||||
return "cvttps2pi %Ppi Wpsq";
|
return "cvttps2pi %Ppi Wpsq";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x2D:
|
case 0x2D:
|
||||||
if (x->op.ild_f3) {
|
if (Rep(x->op.rde) == 3) {
|
||||||
return "cvtss2si %Gdqp Wss";
|
return "cvtss2si %Gdqp Wss";
|
||||||
} else if (x->op.ild_f2) {
|
} else if (Rep(x->op.rde) == 2) {
|
||||||
return "cvtsd2si %Gdqp Wsd";
|
return "cvtsd2si %Gdqp Wsd";
|
||||||
} else if (Osz(x)) {
|
} else if (Osz(x->op.rde)) {
|
||||||
return "cvtpd2pi %Ppi Wpd";
|
return "cvtpd2pi %Ppi Wpd";
|
||||||
} else {
|
} else {
|
||||||
return "cvtps2pi %Ppi Wpsq";
|
return "cvtps2pi %Ppi Wpsq";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x5a:
|
case 0x5a:
|
||||||
if (x->op.ild_f3) {
|
if (Rep(x->op.rde) == 3) {
|
||||||
return "cvtss2sd %Vsd Wss";
|
return "cvtss2sd %Vsd Wss";
|
||||||
} else if (x->op.ild_f2) {
|
} else if (Rep(x->op.rde) == 2) {
|
||||||
return "cvtsd2ss %Vss Wsd";
|
return "cvtsd2ss %Vss Wsd";
|
||||||
} else if (Osz(x)) {
|
} else if (Osz(x->op.rde)) {
|
||||||
return "cvtpd2ps %Vps Wpd";
|
return "cvtpd2ps %Vps Wpd";
|
||||||
} else {
|
} else {
|
||||||
return "cvtps2pd %Vpd Wps";
|
return "cvtps2pd %Vpd Wps";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x5b:
|
case 0x5b:
|
||||||
if (x->op.ild_f3) {
|
if (Rep(x->op.rde) == 3) {
|
||||||
return "cvttps2dq %Vdq Wps";
|
return "cvttps2dq %Vdq Wps";
|
||||||
} else if (Osz(x)) {
|
} else if (Osz(x->op.rde)) {
|
||||||
return "cvtps2dq %Vdq Wps";
|
return "cvtps2dq %Vdq Wps";
|
||||||
} else {
|
} else {
|
||||||
return "cvtdq2ps %Vps Wdq";
|
return "cvtdq2ps %Vps Wdq";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x51:
|
case 0x51:
|
||||||
if (x->op.ild_f3) {
|
if (Rep(x->op.rde) == 3) {
|
||||||
return "sqrtss %Vss Wss";
|
return "sqrtss %Vss Wss";
|
||||||
} else if (x->op.ild_f2) {
|
} else if (Rep(x->op.rde) == 2) {
|
||||||
return "sqrtsd %Vsd Wsd";
|
return "sqrtsd %Vsd Wsd";
|
||||||
} else if (Osz(x)) {
|
} else if (Osz(x->op.rde)) {
|
||||||
return "sqrtpd %Vpd Wpd";
|
return "sqrtpd %Vpd Wpd";
|
||||||
} else {
|
} else {
|
||||||
return "sqrtps %Vps Wps";
|
return "sqrtps %Vps Wps";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x6E:
|
case 0x6E:
|
||||||
if (Osz(x)) {
|
if (Osz(x->op.rde)) {
|
||||||
if (Rexw(x)) {
|
if (Rexw(x->op.rde)) {
|
||||||
return "movq %Vdq Eqp";
|
return "movq %Vdq Eqp";
|
||||||
} else {
|
} else {
|
||||||
return "movd %Vdq Ed";
|
return "movd %Vdq Ed";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Rexw(x)) {
|
if (Rexw(x->op.rde)) {
|
||||||
return "movq %Pq Eqp";
|
return "movq %Pq Eqp";
|
||||||
} else {
|
} else {
|
||||||
return "movd %Pq Ed";
|
return "movd %Pq Ed";
|
||||||
|
@ -991,25 +991,25 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x6F:
|
case 0x6F:
|
||||||
if (x->op.ild_f3) {
|
if (Rep(x->op.rde) == 3) {
|
||||||
return "movdqu %Vdq Wdq";
|
return "movdqu %Vdq Wdq";
|
||||||
} else if (Osz(x)) {
|
} else if (Osz(x->op.rde)) {
|
||||||
return "movdqa %Vdq Wdq";
|
return "movdqa %Vdq Wdq";
|
||||||
} else {
|
} else {
|
||||||
return "movq %Pq Qq";
|
return "movq %Pq Qq";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x7E:
|
case 0x7E:
|
||||||
if (x->op.ild_f3) {
|
if (Rep(x->op.rde) == 3) {
|
||||||
return "movq %Vq Wq";
|
return "movq %Vq Wq";
|
||||||
} else if (Osz(x)) {
|
} else if (Osz(x->op.rde)) {
|
||||||
if (Rexw(x)) {
|
if (Rexw(x->op.rde)) {
|
||||||
return "movq Eqp %Vdq";
|
return "movq Eqp %Vdq";
|
||||||
} else {
|
} else {
|
||||||
return "movd Ed %Vdq";
|
return "movd Ed %Vdq";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Rexw(x)) {
|
if (Rexw(x->op.rde)) {
|
||||||
return "movq Eqp %Pq";
|
return "movq Eqp %Pq";
|
||||||
} else {
|
} else {
|
||||||
return "movd Ed %Pq";
|
return "movd Ed %Pq";
|
||||||
|
@ -1017,20 +1017,20 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x7F:
|
case 0x7F:
|
||||||
if (x->op.ild_f3) {
|
if (Rep(x->op.rde) == 3) {
|
||||||
return "movdqu Wdq %Vdq";
|
return "movdqu Wdq %Vdq";
|
||||||
} else if (Osz(x)) {
|
} else if (Osz(x->op.rde)) {
|
||||||
return "movdqa Wdq %Vdq";
|
return "movdqa Wdq %Vdq";
|
||||||
} else {
|
} else {
|
||||||
return "movq Qq %Pq";
|
return "movq Qq %Pq";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xE6:
|
case 0xE6:
|
||||||
if (x->op.ild_f2) {
|
if (Rep(x->op.rde) == 2) {
|
||||||
return "cvtpd2dq %Vdq Wpd";
|
return "cvtpd2dq %Vdq Wpd";
|
||||||
} else if (Osz(x)) {
|
} else if (Osz(x->op.rde)) {
|
||||||
return "cvttpd2dq %Vdq Wpd";
|
return "cvttpd2dq %Vdq Wpd";
|
||||||
} else if (x->op.ild_f3) {
|
} else if (Rep(x->op.rde) == 3) {
|
||||||
return "cvtdq2pd %Vpd Wdq";
|
return "cvtdq2pd %Vpd Wdq";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -25,12 +25,12 @@
|
||||||
#include "tool/build/lib/modrm.h"
|
#include "tool/build/lib/modrm.h"
|
||||||
#include "tool/build/lib/throw.h"
|
#include "tool/build/lib/throw.h"
|
||||||
|
|
||||||
void OpDivAlAhAxEbSigned(struct Machine *m) {
|
void OpDivAlAhAxEbSigned(struct Machine *m, uint32_t rde) {
|
||||||
int8_t y, rem;
|
int8_t y, rem;
|
||||||
int16_t x, quo;
|
int16_t x, quo;
|
||||||
x = Read16(m->ax);
|
x = Read16(m->ax);
|
||||||
y = Read8(GetModrmRegisterBytePointerRead(m));
|
y = Read8(GetModrmRegisterBytePointerRead(m, rde));
|
||||||
if (!y || (x == INT16_MIN && y < 0)) ThrowDivideError(m);
|
if (!y || (x == INT16_MIN && y == -1)) ThrowDivideError(m);
|
||||||
quo = x / y;
|
quo = x / y;
|
||||||
rem = x % y;
|
rem = x % y;
|
||||||
if (!(INT8_MIN <= quo && quo <= INT8_MAX)) ThrowDivideError(m);
|
if (!(INT8_MIN <= quo && quo <= INT8_MAX)) ThrowDivideError(m);
|
||||||
|
@ -38,11 +38,11 @@ void OpDivAlAhAxEbSigned(struct Machine *m) {
|
||||||
m->ax[1] = rem & 0xff;
|
m->ax[1] = rem & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpDivAlAhAxEbUnsigned(struct Machine *m) {
|
void OpDivAlAhAxEbUnsigned(struct Machine *m, uint32_t rde) {
|
||||||
uint8_t y, rem;
|
uint8_t y, rem;
|
||||||
uint16_t x, quo;
|
uint16_t x, quo;
|
||||||
x = Read16(m->ax);
|
x = Read16(m->ax);
|
||||||
y = Read8(GetModrmRegisterBytePointerRead(m));
|
y = Read8(GetModrmRegisterBytePointerRead(m, rde));
|
||||||
if (!y) ThrowDivideError(m);
|
if (!y) ThrowDivideError(m);
|
||||||
quo = x / y;
|
quo = x / y;
|
||||||
rem = x % y;
|
rem = x % y;
|
||||||
|
@ -51,12 +51,13 @@ void OpDivAlAhAxEbUnsigned(struct Machine *m) {
|
||||||
m->ax[1] = rem & 0xff;
|
m->ax[1] = rem & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpDivRdxRaxEvqpSigned64(struct Machine *m, uint8_t *p) {
|
static void OpDivRdxRaxEvqpSigned64(struct Machine *m, uint32_t rde,
|
||||||
|
uint8_t *p) {
|
||||||
int64_t y, rem;
|
int64_t y, rem;
|
||||||
int128_t x, quo;
|
int128_t x, quo;
|
||||||
x = (uint128_t)Read64(m->dx) << 64 | Read64(m->ax);
|
x = (uint128_t)Read64(m->dx) << 64 | Read64(m->ax);
|
||||||
y = Read64(p);
|
y = Read64(p);
|
||||||
if (!y || (x == INT128_MIN && y < 0)) ThrowDivideError(m);
|
if (!y || (x == INT128_MIN && y == -1)) ThrowDivideError(m);
|
||||||
quo = x / y;
|
quo = x / y;
|
||||||
rem = x % y;
|
rem = x % y;
|
||||||
if (!(INT64_MIN <= quo && quo <= INT64_MAX)) ThrowDivideError(m);
|
if (!(INT64_MIN <= quo && quo <= INT64_MAX)) ThrowDivideError(m);
|
||||||
|
@ -64,12 +65,13 @@ static void OpDivRdxRaxEvqpSigned64(struct Machine *m, uint8_t *p) {
|
||||||
Write64(m->dx, rem);
|
Write64(m->dx, rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpDivRdxRaxEvqpSigned32(struct Machine *m, uint8_t *p) {
|
static void OpDivRdxRaxEvqpSigned32(struct Machine *m, uint32_t rde,
|
||||||
|
uint8_t *p) {
|
||||||
int32_t y, rem;
|
int32_t y, rem;
|
||||||
int64_t x, quo;
|
int64_t x, quo;
|
||||||
x = (uint64_t)Read32(m->dx) << 32 | Read32(m->ax);
|
x = (uint64_t)Read32(m->dx) << 32 | Read32(m->ax);
|
||||||
y = Read32(p);
|
y = Read32(p);
|
||||||
if (!y || (x == INT64_MIN && y < 0)) ThrowDivideError(m);
|
if (!y || (x == INT64_MIN && y == -1)) ThrowDivideError(m);
|
||||||
quo = x / y;
|
quo = x / y;
|
||||||
rem = x % y;
|
rem = x % y;
|
||||||
if (!(INT32_MIN <= quo && quo <= INT32_MAX)) ThrowDivideError(m);
|
if (!(INT32_MIN <= quo && quo <= INT32_MAX)) ThrowDivideError(m);
|
||||||
|
@ -77,12 +79,13 @@ static void OpDivRdxRaxEvqpSigned32(struct Machine *m, uint8_t *p) {
|
||||||
Write64(m->dx, rem & 0xffffffff);
|
Write64(m->dx, rem & 0xffffffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpDivRdxRaxEvqpSigned16(struct Machine *m, uint8_t *p) {
|
static void OpDivRdxRaxEvqpSigned16(struct Machine *m, uint32_t rde,
|
||||||
|
uint8_t *p) {
|
||||||
int16_t y, rem;
|
int16_t y, rem;
|
||||||
int32_t x, quo;
|
int32_t x, quo;
|
||||||
x = (uint32_t)Read16(m->dx) << 16 | Read16(m->ax);
|
x = (uint32_t)Read16(m->dx) << 16 | Read16(m->ax);
|
||||||
y = Read16(p);
|
y = Read16(p);
|
||||||
if (!y || (x == INT32_MIN && y < 0)) ThrowDivideError(m);
|
if (!y || (x == INT32_MIN && y == -1)) ThrowDivideError(m);
|
||||||
quo = x / y;
|
quo = x / y;
|
||||||
rem = x % y;
|
rem = x % y;
|
||||||
if (!(INT16_MIN <= quo && quo <= INT16_MAX)) ThrowDivideError(m);
|
if (!(INT16_MIN <= quo && quo <= INT16_MAX)) ThrowDivideError(m);
|
||||||
|
@ -90,7 +93,8 @@ static void OpDivRdxRaxEvqpSigned16(struct Machine *m, uint8_t *p) {
|
||||||
Write16(m->dx, rem);
|
Write16(m->dx, rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpDivRdxRaxEvqpUnsigned16(struct Machine *m, uint8_t *p) {
|
static void OpDivRdxRaxEvqpUnsigned16(struct Machine *m, uint32_t rde,
|
||||||
|
uint8_t *p) {
|
||||||
uint16_t y, rem;
|
uint16_t y, rem;
|
||||||
uint32_t x, quo;
|
uint32_t x, quo;
|
||||||
x = (uint32_t)Read16(m->dx) << 16 | Read16(m->ax);
|
x = (uint32_t)Read16(m->dx) << 16 | Read16(m->ax);
|
||||||
|
@ -103,7 +107,8 @@ static void OpDivRdxRaxEvqpUnsigned16(struct Machine *m, uint8_t *p) {
|
||||||
Write16(m->dx, rem);
|
Write16(m->dx, rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpDivRdxRaxEvqpUnsigned32(struct Machine *m, uint8_t *p) {
|
static void OpDivRdxRaxEvqpUnsigned32(struct Machine *m, uint32_t rde,
|
||||||
|
uint8_t *p) {
|
||||||
uint32_t y, rem;
|
uint32_t y, rem;
|
||||||
uint64_t x, quo;
|
uint64_t x, quo;
|
||||||
x = (uint64_t)Read32(m->dx) << 32 | Read32(m->ax);
|
x = (uint64_t)Read32(m->dx) << 32 | Read32(m->ax);
|
||||||
|
@ -116,7 +121,8 @@ static void OpDivRdxRaxEvqpUnsigned32(struct Machine *m, uint8_t *p) {
|
||||||
Write64(m->dx, rem & 0xffffffff);
|
Write64(m->dx, rem & 0xffffffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpDivRdxRaxEvqpUnsigned64(struct Machine *m, uint8_t *p) {
|
static void OpDivRdxRaxEvqpUnsigned64(struct Machine *m, uint32_t rde,
|
||||||
|
uint8_t *p) {
|
||||||
uint64_t y, rem;
|
uint64_t y, rem;
|
||||||
uint128_t x, quo;
|
uint128_t x, quo;
|
||||||
x = (uint128_t)Read64(m->dx) << 64 | Read64(m->ax);
|
x = (uint128_t)Read64(m->dx) << 64 | Read64(m->ax);
|
||||||
|
@ -129,35 +135,35 @@ static void OpDivRdxRaxEvqpUnsigned64(struct Machine *m, uint8_t *p) {
|
||||||
Write64(m->dx, rem);
|
Write64(m->dx, rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpDivRdxRaxEvqpSigned(struct Machine *m) {
|
void OpDivRdxRaxEvqpSigned(struct Machine *m, uint32_t rde) {
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
p = GetModrmRegisterWordPointerReadOszRexw(m);
|
p = GetModrmRegisterWordPointerReadOszRexw(m, rde);
|
||||||
if (Rexw(m->xedd)) {
|
if (Rexw(rde)) {
|
||||||
OpDivRdxRaxEvqpSigned64(m, p);
|
OpDivRdxRaxEvqpSigned64(m, rde, p);
|
||||||
} else if (!Osz(m->xedd)) {
|
} else if (!Osz(rde)) {
|
||||||
OpDivRdxRaxEvqpSigned32(m, p);
|
OpDivRdxRaxEvqpSigned32(m, rde, p);
|
||||||
} else {
|
} else {
|
||||||
OpDivRdxRaxEvqpSigned16(m, p);
|
OpDivRdxRaxEvqpSigned16(m, rde, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpDivRdxRaxEvqpUnsigned(struct Machine *m) {
|
void OpDivRdxRaxEvqpUnsigned(struct Machine *m, uint32_t rde) {
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
p = GetModrmRegisterWordPointerReadOszRexw(m);
|
p = GetModrmRegisterWordPointerReadOszRexw(m, rde);
|
||||||
if (Rexw(m->xedd)) {
|
if (Rexw(rde)) {
|
||||||
OpDivRdxRaxEvqpUnsigned64(m, p);
|
OpDivRdxRaxEvqpUnsigned64(m, rde, p);
|
||||||
} else if (!Osz(m->xedd)) {
|
} else if (!Osz(rde)) {
|
||||||
OpDivRdxRaxEvqpUnsigned32(m, p);
|
OpDivRdxRaxEvqpUnsigned32(m, rde, p);
|
||||||
} else {
|
} else {
|
||||||
OpDivRdxRaxEvqpUnsigned16(m, p);
|
OpDivRdxRaxEvqpUnsigned16(m, rde, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpMulAxAlEbSigned(struct Machine *m) {
|
void OpMulAxAlEbSigned(struct Machine *m, uint32_t rde) {
|
||||||
bool of;
|
bool of;
|
||||||
int16_t ax;
|
int16_t ax;
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
p = GetModrmRegisterBytePointerRead(m);
|
p = GetModrmRegisterBytePointerRead(m, rde);
|
||||||
__builtin_mul_overflow((int8_t)Read8(m->ax), (int8_t)Read8(p), &ax);
|
__builtin_mul_overflow((int8_t)Read8(m->ax), (int8_t)Read8(p), &ax);
|
||||||
of = (int)ax != (int8_t)ax;
|
of = (int)ax != (int8_t)ax;
|
||||||
m->flags = SetFlag(m->flags, FLAGS_CF, of);
|
m->flags = SetFlag(m->flags, FLAGS_CF, of);
|
||||||
|
@ -165,11 +171,11 @@ void OpMulAxAlEbSigned(struct Machine *m) {
|
||||||
Write16(m->ax, ax);
|
Write16(m->ax, ax);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpMulAxAlEbUnsigned(struct Machine *m) {
|
void OpMulAxAlEbUnsigned(struct Machine *m, uint32_t rde) {
|
||||||
int ax;
|
int ax;
|
||||||
bool of;
|
bool of;
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
p = GetModrmRegisterBytePointerRead(m);
|
p = GetModrmRegisterBytePointerRead(m, rde);
|
||||||
__builtin_mul_overflow(Read8(m->ax), Read8(p), &ax);
|
__builtin_mul_overflow(Read8(m->ax), Read8(p), &ax);
|
||||||
of = (uint8_t)ax != ax;
|
of = (uint8_t)ax != ax;
|
||||||
m->flags = SetFlag(m->flags, FLAGS_CF, of);
|
m->flags = SetFlag(m->flags, FLAGS_CF, of);
|
||||||
|
@ -177,20 +183,20 @@ void OpMulAxAlEbUnsigned(struct Machine *m) {
|
||||||
Write16(m->ax, ax);
|
Write16(m->ax, ax);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpMulRdxRaxEvqpSigned(struct Machine *m) {
|
void OpMulRdxRaxEvqpSigned(struct Machine *m, uint32_t rde) {
|
||||||
bool of;
|
bool of;
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
int32_t dxax;
|
int32_t dxax;
|
||||||
int64_t edxeax;
|
int64_t edxeax;
|
||||||
int128_t rdxrax;
|
int128_t rdxrax;
|
||||||
p = GetModrmRegisterWordPointerReadOszRexw(m);
|
p = GetModrmRegisterWordPointerReadOszRexw(m, rde);
|
||||||
if (Rexw(m->xedd)) {
|
if (Rexw(rde)) {
|
||||||
__builtin_mul_overflow((int128_t)(int64_t)Read64(m->ax), (int64_t)Read64(p),
|
__builtin_mul_overflow((int128_t)(int64_t)Read64(m->ax), (int64_t)Read64(p),
|
||||||
&rdxrax);
|
&rdxrax);
|
||||||
of = (int128_t)rdxrax != (int64_t)rdxrax;
|
of = (int128_t)rdxrax != (int64_t)rdxrax;
|
||||||
Write64(m->ax, rdxrax);
|
Write64(m->ax, rdxrax);
|
||||||
Write64(m->dx, rdxrax >> 64);
|
Write64(m->dx, rdxrax >> 64);
|
||||||
} else if (!Osz(m->xedd)) {
|
} else if (!Osz(rde)) {
|
||||||
__builtin_mul_overflow((int64_t)(int32_t)Read32(m->ax), (int32_t)Read32(p),
|
__builtin_mul_overflow((int64_t)(int32_t)Read32(m->ax), (int32_t)Read32(p),
|
||||||
&edxeax);
|
&edxeax);
|
||||||
of = (int64_t)edxeax != (int32_t)edxeax;
|
of = (int64_t)edxeax != (int32_t)edxeax;
|
||||||
|
@ -207,19 +213,19 @@ void OpMulRdxRaxEvqpSigned(struct Machine *m) {
|
||||||
m->flags = SetFlag(m->flags, FLAGS_OF, of);
|
m->flags = SetFlag(m->flags, FLAGS_OF, of);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpMulRdxRaxEvqpUnsigned(struct Machine *m) {
|
void OpMulRdxRaxEvqpUnsigned(struct Machine *m, uint32_t rde) {
|
||||||
bool of;
|
bool of;
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
uint32_t dxax;
|
uint32_t dxax;
|
||||||
uint64_t edxeax;
|
uint64_t edxeax;
|
||||||
uint128_t rdxrax;
|
uint128_t rdxrax;
|
||||||
p = GetModrmRegisterWordPointerReadOszRexw(m);
|
p = GetModrmRegisterWordPointerReadOszRexw(m, rde);
|
||||||
if (Rexw(m->xedd)) {
|
if (Rexw(rde)) {
|
||||||
__builtin_mul_overflow((uint128_t)Read64(m->ax), Read64(p), &rdxrax);
|
__builtin_mul_overflow((uint128_t)Read64(m->ax), Read64(p), &rdxrax);
|
||||||
of = (uint64_t)rdxrax != rdxrax;
|
of = (uint64_t)rdxrax != rdxrax;
|
||||||
Write64(m->ax, rdxrax);
|
Write64(m->ax, rdxrax);
|
||||||
Write64(m->dx, rdxrax >> 64);
|
Write64(m->dx, rdxrax >> 64);
|
||||||
} else if (!Osz(m->xedd)) {
|
} else if (!Osz(rde)) {
|
||||||
__builtin_mul_overflow((uint64_t)Read32(m->ax), Read32(p), &edxeax);
|
__builtin_mul_overflow((uint64_t)Read32(m->ax), Read32(p), &edxeax);
|
||||||
of = (uint32_t)edxeax != edxeax;
|
of = (uint32_t)edxeax != edxeax;
|
||||||
Write64(m->ax, edxeax);
|
Write64(m->ax, edxeax);
|
||||||
|
@ -235,37 +241,38 @@ void OpMulRdxRaxEvqpUnsigned(struct Machine *m) {
|
||||||
m->flags = SetFlag(m->flags, FLAGS_OF, of);
|
m->flags = SetFlag(m->flags, FLAGS_OF, of);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AluImul(struct Machine *m, uint8_t *a, uint8_t *b) {
|
static void AluImul(struct Machine *m, uint32_t rde, uint8_t *a, uint8_t *b) {
|
||||||
unsigned of;
|
unsigned of;
|
||||||
if (Rexw(m->xedd)) {
|
if (Rexw(rde)) {
|
||||||
int64_t x, y, z;
|
int64_t x, y, z;
|
||||||
x = Read64(a);
|
x = Read64(a);
|
||||||
y = Read64(b);
|
y = Read64(b);
|
||||||
of = __builtin_mul_overflow(x, y, &z);
|
of = __builtin_mul_overflow(x, y, &z);
|
||||||
Write64(RegRexrReg(m), z);
|
Write64(RegRexrReg(m, rde), z);
|
||||||
} else if (!Osz(m->xedd)) {
|
} else if (!Osz(rde)) {
|
||||||
int32_t x, y, z;
|
int32_t x, y, z;
|
||||||
x = Read32(a);
|
x = Read32(a);
|
||||||
y = Read32(b);
|
y = Read32(b);
|
||||||
of = __builtin_mul_overflow(x, y, &z);
|
of = __builtin_mul_overflow(x, y, &z);
|
||||||
Write64(RegRexrReg(m), z & 0xffffffff);
|
Write64(RegRexrReg(m, rde), z & 0xffffffff);
|
||||||
} else {
|
} else {
|
||||||
int16_t x, y, z;
|
int16_t x, y, z;
|
||||||
x = Read16(a);
|
x = Read16(a);
|
||||||
y = Read16(b);
|
y = Read16(b);
|
||||||
of = __builtin_mul_overflow(x, y, &z);
|
of = __builtin_mul_overflow(x, y, &z);
|
||||||
Write16(RegRexrReg(m), z);
|
Write16(RegRexrReg(m, rde), z);
|
||||||
}
|
}
|
||||||
m->flags = SetFlag(m->flags, FLAGS_CF, of);
|
m->flags = SetFlag(m->flags, FLAGS_CF, of);
|
||||||
m->flags = SetFlag(m->flags, FLAGS_OF, of);
|
m->flags = SetFlag(m->flags, FLAGS_OF, of);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpImulGvqpEvqp(struct Machine *m) {
|
void OpImulGvqpEvqp(struct Machine *m, uint32_t rde) {
|
||||||
AluImul(m, RegRexrReg(m), GetModrmRegisterWordPointerReadOszRexw(m));
|
AluImul(m, rde, RegRexrReg(m, rde),
|
||||||
|
GetModrmRegisterWordPointerReadOszRexw(m, rde));
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpImulGvqpEvqpImm(struct Machine *m) {
|
void OpImulGvqpEvqpImm(struct Machine *m, uint32_t rde) {
|
||||||
uint8_t b[8];
|
uint8_t b[8];
|
||||||
Write64(b, m->xedd->op.uimm0);
|
Write64(b, m->xedd->op.uimm0);
|
||||||
AluImul(m, GetModrmRegisterWordPointerReadOszRexw(m), b);
|
AluImul(m, rde, GetModrmRegisterWordPointerReadOszRexw(m, rde), b);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,16 +4,16 @@
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
void OpDivAlAhAxEbSigned(struct Machine *);
|
void OpDivAlAhAxEbSigned(struct Machine *, uint32_t);
|
||||||
void OpDivAlAhAxEbUnsigned(struct Machine *);
|
void OpDivAlAhAxEbUnsigned(struct Machine *, uint32_t);
|
||||||
void OpDivRdxRaxEvqpSigned(struct Machine *);
|
void OpDivRdxRaxEvqpSigned(struct Machine *, uint32_t);
|
||||||
void OpDivRdxRaxEvqpUnsigned(struct Machine *);
|
void OpDivRdxRaxEvqpUnsigned(struct Machine *, uint32_t);
|
||||||
void OpImulGvqpEvqp(struct Machine *);
|
void OpImulGvqpEvqp(struct Machine *, uint32_t);
|
||||||
void OpImulGvqpEvqpImm(struct Machine *);
|
void OpImulGvqpEvqpImm(struct Machine *, uint32_t);
|
||||||
void OpMulAxAlEbSigned(struct Machine *);
|
void OpMulAxAlEbSigned(struct Machine *, uint32_t);
|
||||||
void OpMulAxAlEbUnsigned(struct Machine *);
|
void OpMulAxAlEbUnsigned(struct Machine *, uint32_t);
|
||||||
void OpMulRdxRaxEvqpSigned(struct Machine *);
|
void OpMulRdxRaxEvqpSigned(struct Machine *, uint32_t);
|
||||||
void OpMulRdxRaxEvqpUnsigned(struct Machine *);
|
void OpMulRdxRaxEvqpUnsigned(struct Machine *, uint32_t);
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
55
tool/build/lib/fds.c
Normal file
55
tool/build/lib/fds.c
Normal 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 "libc/log/check.h"
|
||||||
|
#include "libc/mem/mem.h"
|
||||||
|
#include "libc/x/x.h"
|
||||||
|
#include "tool/build/lib/fds.h"
|
||||||
|
|
||||||
|
int MachineFdAdd(struct MachineFds *mf) {
|
||||||
|
int fd;
|
||||||
|
struct MachineFdClosed *closed;
|
||||||
|
if ((closed = mf->closed)) {
|
||||||
|
DCHECK_LT(closed->fd, mf->i);
|
||||||
|
fd = closed->fd;
|
||||||
|
mf->closed = closed->next;
|
||||||
|
free(closed);
|
||||||
|
} else {
|
||||||
|
DCHECK_LE(mf->i, mf->n);
|
||||||
|
if (mf->i == mf->n) {
|
||||||
|
if (!grow(&mf->p, &mf->n, sizeof(struct MachineFd), 0)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fd = mf->i++;
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MachineFdRemove(struct MachineFds *mf, int fd) {
|
||||||
|
struct MachineFdClosed *closed;
|
||||||
|
DCHECK_GE(fd, 0);
|
||||||
|
DCHECK_LT(fd, mf->i);
|
||||||
|
mf->p[fd].cb = NULL;
|
||||||
|
if ((closed = malloc(sizeof(struct MachineFdClosed)))) {
|
||||||
|
closed->fd = fd;
|
||||||
|
closed->next = mf->closed;
|
||||||
|
mf->closed = closed;
|
||||||
|
}
|
||||||
|
}
|
27
tool/build/lib/fds.h
Normal file
27
tool/build/lib/fds.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_FDS_H_
|
||||||
|
#define COSMOPOLITAN_TOOL_BUILD_LIB_FDS_H_
|
||||||
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
|
struct MachineFds {
|
||||||
|
size_t i, n;
|
||||||
|
struct MachineFd {
|
||||||
|
int fd;
|
||||||
|
struct MachineFdCb {
|
||||||
|
int (*close)(int);
|
||||||
|
ssize_t (*read)(int, void *, size_t);
|
||||||
|
ssize_t (*write)(int, const void *, size_t);
|
||||||
|
} * cb;
|
||||||
|
} * p;
|
||||||
|
struct MachineFdClosed {
|
||||||
|
unsigned fd;
|
||||||
|
struct MachineFdClosed *next;
|
||||||
|
} * closed;
|
||||||
|
};
|
||||||
|
|
||||||
|
int MachineFdAdd(struct MachineFds *);
|
||||||
|
void MachineFdRemove(struct MachineFds *, int);
|
||||||
|
|
||||||
|
COSMOPOLITAN_C_END_
|
||||||
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_FDS_H_ */
|
|
@ -50,26 +50,6 @@ static long double OnFpuStackUnderflow(struct Machine *m) {
|
||||||
return -NAN;
|
return -NAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FpuPush(struct Machine *m, long double x) {
|
|
||||||
if (FpuGetTag(m, -1) != kFpuTagEmpty) OnFpuStackOverflow(m);
|
|
||||||
m->fpu.sp -= 1;
|
|
||||||
*FpuSt(m, 0) = x;
|
|
||||||
FpuSetTag(m, 0, kFpuTagValid);
|
|
||||||
}
|
|
||||||
|
|
||||||
long double FpuPop(struct Machine *m) {
|
|
||||||
long double x;
|
|
||||||
if (FpuGetTag(m, 0) != kFpuTagEmpty) {
|
|
||||||
x = *FpuSt(m, 0);
|
|
||||||
FpuSetTag(m, 0, kFpuTagEmpty);
|
|
||||||
/* *FpuSt(m, 0) = -NAN; */
|
|
||||||
} else {
|
|
||||||
x = OnFpuStackUnderflow(m);
|
|
||||||
}
|
|
||||||
m->fpu.sp += 1;
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
static long double St(struct Machine *m, int i) {
|
static long double St(struct Machine *m, int i) {
|
||||||
if (FpuGetTag(m, i) == kFpuTagEmpty) OnFpuStackUnderflow(m);
|
if (FpuGetTag(m, i) == kFpuTagEmpty) OnFpuStackUnderflow(m);
|
||||||
return *FpuSt(m, i);
|
return *FpuSt(m, i);
|
||||||
|
@ -84,7 +64,7 @@ static long double St1(struct Machine *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static long double StRm(struct Machine *m) {
|
static long double StRm(struct Machine *m) {
|
||||||
return St(m, ModrmRm(m->xedd));
|
return St(m, ModrmRm(m->xedd->op.rde));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FpuClearRoundup(struct Machine *m) {
|
static void FpuClearRoundup(struct Machine *m) {
|
||||||
|
@ -100,7 +80,7 @@ static void FpuSetSt0(struct Machine *m, long double x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FpuSetStRm(struct Machine *m, long double x) {
|
static void FpuSetStRm(struct Machine *m, long double x) {
|
||||||
*FpuSt(m, ModrmRm(m->xedd)) = x;
|
*FpuSt(m, ModrmRm(m->xedd->op.rde)) = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FpuSetStPop(struct Machine *m, int i, long double x) {
|
static void FpuSetStPop(struct Machine *m, int i, long double x) {
|
||||||
|
@ -109,7 +89,7 @@ static void FpuSetStPop(struct Machine *m, int i, long double x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FpuSetStRmPop(struct Machine *m, long double x) {
|
static void FpuSetStRmPop(struct Machine *m, long double x) {
|
||||||
FpuSetStPop(m, ModrmRm(m->xedd), x);
|
FpuSetStPop(m, ModrmRm(m->xedd->op.rde), x);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int16_t GetMemoryShort(struct Machine *m) {
|
static int16_t GetMemoryShort(struct Machine *m) {
|
||||||
|
@ -414,11 +394,11 @@ static void OpFmulEstSt(struct Machine *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpFsubEstSt(struct Machine *m) {
|
static void OpFsubEstSt(struct Machine *m) {
|
||||||
FpuSetStRm(m, StRm(m) - St0(m));
|
FpuSetStRm(m, St0(m) - StRm(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpFsubrEstSt(struct Machine *m) {
|
static void OpFsubrEstSt(struct Machine *m) {
|
||||||
FpuSetStRm(m, St0(m) - StRm(m));
|
FpuSetStRm(m, StRm(m) - St0(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpFdivEstSt(struct Machine *m) {
|
static void OpFdivEstSt(struct Machine *m) {
|
||||||
|
@ -666,8 +646,7 @@ static void OpFstp(struct Machine *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpFxch(struct Machine *m) {
|
static void OpFxch(struct Machine *m) {
|
||||||
long double t;
|
long double t = StRm(m);
|
||||||
t = StRm(m);
|
|
||||||
FpuSetStRm(m, St0(m));
|
FpuSetStRm(m, St0(m));
|
||||||
FpuSetSt0(m, t);
|
FpuSetSt0(m, t);
|
||||||
}
|
}
|
||||||
|
@ -686,7 +665,7 @@ static void OpFldl(struct Machine *m) {
|
||||||
|
|
||||||
static void OpFldConstant(struct Machine *m) {
|
static void OpFldConstant(struct Machine *m) {
|
||||||
long double x;
|
long double x;
|
||||||
switch (ModrmRm(m->xedd)) {
|
switch (ModrmRm(m->xedd->op.rde)) {
|
||||||
case 0:
|
case 0:
|
||||||
x = fld1();
|
x = fld1();
|
||||||
break;
|
break;
|
||||||
|
@ -769,7 +748,7 @@ static void OpFistps(struct Machine *m) {
|
||||||
FpuPop(m);
|
FpuPop(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpFcomi(struct Machine *m) {
|
static void OpFcomi(struct Machine *m) {
|
||||||
long double x, y;
|
long double x, y;
|
||||||
x = St0(m);
|
x = St0(m);
|
||||||
y = StRm(m);
|
y = StRm(m);
|
||||||
|
@ -808,7 +787,7 @@ static void OpFucomip(struct Machine *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpFfree(struct Machine *m) {
|
static void OpFfree(struct Machine *m) {
|
||||||
FpuSetTag(m, ModrmRm(m->xedd), kFpuTagEmpty);
|
FpuSetTag(m, ModrmRm(m->xedd->op.rde), kFpuTagEmpty);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpFfreep(struct Machine *m) {
|
static void OpFfreep(struct Machine *m) {
|
||||||
|
@ -890,6 +869,10 @@ static void OpFnclex(struct Machine *m) {
|
||||||
m->fpu.bf = false;
|
m->fpu.bf = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void OpFnop(struct Machine *m) {
|
||||||
|
/* do nothing */
|
||||||
|
}
|
||||||
|
|
||||||
void OpFinit(struct Machine *m) {
|
void OpFinit(struct Machine *m) {
|
||||||
m->fpu.cw = X87_NORMAL;
|
m->fpu.cw = X87_NORMAL;
|
||||||
m->fpu.sw = 0;
|
m->fpu.sw = 0;
|
||||||
|
@ -905,18 +888,59 @@ void OpFwait(struct Machine *m) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpFnop(struct Machine *m) {
|
long double *FpuSt(struct Machine *m, unsigned i) {
|
||||||
/* do nothing */
|
i += m->fpu.sp;
|
||||||
|
i &= 0b111;
|
||||||
|
return m->fpu.st + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FpuGetTag(struct Machine *m, unsigned i) {
|
||||||
|
unsigned t;
|
||||||
|
t = m->fpu.tw;
|
||||||
|
i += m->fpu.sp;
|
||||||
|
i &= 0b111;
|
||||||
|
i *= 2;
|
||||||
|
t &= 0b11 << i;
|
||||||
|
t >>= i;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FpuSetTag(struct Machine *m, unsigned i, unsigned t) {
|
||||||
|
i += m->fpu.sp;
|
||||||
|
t &= 0b11;
|
||||||
|
i &= 0b111;
|
||||||
|
i *= 2;
|
||||||
|
m->fpu.tw &= ~(0b11 << i);
|
||||||
|
m->fpu.tw |= t << i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FpuPush(struct Machine *m, long double x) {
|
||||||
|
if (FpuGetTag(m, -1) != kFpuTagEmpty) OnFpuStackOverflow(m);
|
||||||
|
m->fpu.sp -= 1;
|
||||||
|
*FpuSt(m, 0) = x;
|
||||||
|
FpuSetTag(m, 0, kFpuTagValid);
|
||||||
|
}
|
||||||
|
|
||||||
|
long double FpuPop(struct Machine *m) {
|
||||||
|
long double x;
|
||||||
|
if (FpuGetTag(m, 0) != kFpuTagEmpty) {
|
||||||
|
x = *FpuSt(m, 0);
|
||||||
|
FpuSetTag(m, 0, kFpuTagEmpty);
|
||||||
|
} else {
|
||||||
|
x = OnFpuStackUnderflow(m);
|
||||||
|
}
|
||||||
|
m->fpu.sp += 1;
|
||||||
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpFpu(struct Machine *m) {
|
void OpFpu(struct Machine *m) {
|
||||||
unsigned op;
|
unsigned op;
|
||||||
bool ismemory;
|
bool ismemory;
|
||||||
op = m->xedd->op.opcode & 0b111;
|
op = m->xedd->op.opcode & 0b111;
|
||||||
ismemory = ModrmMod(m->xedd) != 0b11;
|
ismemory = ModrmMod(m->xedd->op.rde) != 0b11;
|
||||||
m->fpu.ip = m->ip - m->xedd->length;
|
m->fpu.ip = m->ip - m->xedd->length;
|
||||||
m->fpu.op = op << 8 | m->xedd->op.modrm;
|
m->fpu.op = op << 8 | m->xedd->op.modrm;
|
||||||
m->fpu.dp = ismemory ? ComputeAddress(m) : 0;
|
m->fpu.dp = ismemory ? ComputeAddress(m, m->xedd->op.rde) : 0;
|
||||||
switch (DISP(op, ismemory, m->xedd->op.reg)) {
|
switch (DISP(op, ismemory, m->xedd->op.reg)) {
|
||||||
CASE(DISP(0xD8, FPUREG, 0), OpFaddStEst(m));
|
CASE(DISP(0xD8, FPUREG, 0), OpFaddStEst(m));
|
||||||
CASE(DISP(0xD8, FPUREG, 1), OpFmulStEst(m));
|
CASE(DISP(0xD8, FPUREG, 1), OpFmulStEst(m));
|
||||||
|
@ -1029,7 +1053,7 @@ void OpFpu(struct Machine *m) {
|
||||||
CASE(DISP(0xDf, MEMORY, 5), OpFildll(m));
|
CASE(DISP(0xDf, MEMORY, 5), OpFildll(m));
|
||||||
CASE(DISP(0xDf, MEMORY, 7), OpFistpll(m));
|
CASE(DISP(0xDf, MEMORY, 7), OpFistpll(m));
|
||||||
case DISP(0xD9, FPUREG, 4):
|
case DISP(0xD9, FPUREG, 4):
|
||||||
switch (ModrmRm(m->xedd)) {
|
switch (ModrmRm(m->xedd->op.rde)) {
|
||||||
CASE(0, OpFchs(m));
|
CASE(0, OpFchs(m));
|
||||||
CASE(1, OpFabs(m));
|
CASE(1, OpFabs(m));
|
||||||
CASE(4, OpFtst(m));
|
CASE(4, OpFtst(m));
|
||||||
|
@ -1039,7 +1063,7 @@ void OpFpu(struct Machine *m) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DISP(0xD9, FPUREG, 6):
|
case DISP(0xD9, FPUREG, 6):
|
||||||
switch (ModrmRm(m->xedd)) {
|
switch (ModrmRm(m->xedd->op.rde)) {
|
||||||
CASE(0, OpF2xm1(m));
|
CASE(0, OpF2xm1(m));
|
||||||
CASE(1, OpFyl2x(m));
|
CASE(1, OpFyl2x(m));
|
||||||
CASE(2, OpFptan(m));
|
CASE(2, OpFptan(m));
|
||||||
|
@ -1053,7 +1077,7 @@ void OpFpu(struct Machine *m) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DISP(0xD9, FPUREG, 7):
|
case DISP(0xD9, FPUREG, 7):
|
||||||
switch (ModrmRm(m->xedd)) {
|
switch (ModrmRm(m->xedd->op.rde)) {
|
||||||
CASE(0, OpFprem(m));
|
CASE(0, OpFprem(m));
|
||||||
CASE(1, OpFyl2xp1(m));
|
CASE(1, OpFyl2xp1(m));
|
||||||
CASE(2, OpFsqrt(m));
|
CASE(2, OpFsqrt(m));
|
||||||
|
@ -1067,7 +1091,7 @@ void OpFpu(struct Machine *m) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DISP(0xDb, FPUREG, 4):
|
case DISP(0xDb, FPUREG, 4):
|
||||||
switch (ModrmRm(m->xedd)) {
|
switch (ModrmRm(m->xedd->op.rde)) {
|
||||||
CASE(2, OpFnclex(m));
|
CASE(2, OpFnclex(m));
|
||||||
CASE(3, OpFinit(m));
|
CASE(3, OpFinit(m));
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -15,32 +15,9 @@ void OpFinit(struct Machine *);
|
||||||
void OpFwait(struct Machine *);
|
void OpFwait(struct Machine *);
|
||||||
void FpuPush(struct Machine *, long double);
|
void FpuPush(struct Machine *, long double);
|
||||||
long double FpuPop(struct Machine *);
|
long double FpuPop(struct Machine *);
|
||||||
|
long double *FpuSt(struct Machine *, unsigned);
|
||||||
forceinline long double *FpuSt(struct Machine *m, unsigned i) {
|
int FpuGetTag(struct Machine *, unsigned);
|
||||||
i += m->fpu.sp;
|
void FpuSetTag(struct Machine *, unsigned, unsigned);
|
||||||
i &= 0b111;
|
|
||||||
return m->fpu.st + i;
|
|
||||||
}
|
|
||||||
|
|
||||||
forceinline int FpuGetTag(struct Machine *m, unsigned i) {
|
|
||||||
unsigned t;
|
|
||||||
t = m->fpu.tw;
|
|
||||||
i += m->fpu.sp;
|
|
||||||
i &= 0b111;
|
|
||||||
i *= 2;
|
|
||||||
t &= 0b11 << i;
|
|
||||||
t >>= i;
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
forceinline void FpuSetTag(struct Machine *m, unsigned i, unsigned t) {
|
|
||||||
i += m->fpu.sp;
|
|
||||||
t &= 0b11;
|
|
||||||
i &= 0b111;
|
|
||||||
i *= 2;
|
|
||||||
m->fpu.tw &= ~(0b11 << i);
|
|
||||||
m->fpu.tw |= t << i;
|
|
||||||
}
|
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -17,13 +17,34 @@
|
||||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||||
│ 02110-1301 USA │
|
│ 02110-1301 USA │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/stdio/stdio.h"
|
#include "libc/sysv/consts/fileno.h"
|
||||||
#include "tool/build/lib/ioports.h"
|
#include "tool/build/lib/ioports.h"
|
||||||
|
|
||||||
|
static int OpE9Read(struct Machine *m) {
|
||||||
|
int fd;
|
||||||
|
uint8_t b;
|
||||||
|
fd = STDIN_FILENO;
|
||||||
|
if (fd >= m->fds.i) return -1;
|
||||||
|
if (!m->fds.p[fd].cb) return -1;
|
||||||
|
if (m->fds.p[fd].cb->read(m->fds.p[fd].fd, &b, 1) == 1) {
|
||||||
|
return b;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OpE9Write(struct Machine *m, uint8_t b) {
|
||||||
|
int fd;
|
||||||
|
fd = STDOUT_FILENO;
|
||||||
|
if (fd >= m->fds.i) return;
|
||||||
|
if (!m->fds.p[fd].cb) return;
|
||||||
|
m->fds.p[fd].cb->write(m->fds.p[fd].fd, &b, 1);
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t OpIn(struct Machine *m, uint16_t p) {
|
uint64_t OpIn(struct Machine *m, uint16_t p) {
|
||||||
switch (p) {
|
switch (p) {
|
||||||
case 0xE9:
|
case 0xE9:
|
||||||
return getc(stdin);
|
return OpE9Read(m);
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -32,9 +53,7 @@ uint64_t OpIn(struct Machine *m, uint16_t p) {
|
||||||
void OpOut(struct Machine *m, uint16_t p, uint32_t x) {
|
void OpOut(struct Machine *m, uint16_t p, uint32_t x) {
|
||||||
switch (p) {
|
switch (p) {
|
||||||
case 0xE9:
|
case 0xE9:
|
||||||
do {
|
OpE9Write(m, x);
|
||||||
putc(x, stdout);
|
|
||||||
} while (x >> 8);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -3,6 +3,7 @@
|
||||||
#include "libc/elf/struct/ehdr.h"
|
#include "libc/elf/struct/ehdr.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "third_party/xed/x86.h"
|
#include "third_party/xed/x86.h"
|
||||||
|
#include "tool/build/lib/fds.h"
|
||||||
#include "tool/build/lib/pml4t.h"
|
#include "tool/build/lib/pml4t.h"
|
||||||
|
|
||||||
#define kXmmIntegral 0
|
#define kXmmIntegral 0
|
||||||
|
@ -136,6 +137,7 @@ struct Machine {
|
||||||
uint8_t stash[4096];
|
uint8_t stash[4096];
|
||||||
uint8_t xmmtype[2][8];
|
uint8_t xmmtype[2][8];
|
||||||
struct XedDecodedInst icache[512];
|
struct XedDecodedInst icache[512];
|
||||||
|
struct MachineFds fds;
|
||||||
};
|
};
|
||||||
|
|
||||||
void ResetCpu(struct Machine *);
|
void ResetCpu(struct Machine *);
|
||||||
|
|
|
@ -26,207 +26,223 @@
|
||||||
/**
|
/**
|
||||||
* Computes virtual address based on modrm and sib bytes.
|
* Computes virtual address based on modrm and sib bytes.
|
||||||
*/
|
*/
|
||||||
int64_t ComputeAddress(const struct Machine *m) {
|
int64_t ComputeAddress(const struct Machine *m, uint32_t rde) {
|
||||||
uint64_t i;
|
uint64_t i;
|
||||||
DCHECK(m->xedd->op.has_modrm);
|
DCHECK(m->xedd->op.has_modrm);
|
||||||
DCHECK(!IsModrmRegister(m->xedd));
|
DCHECK(!IsModrmRegister(rde));
|
||||||
i = m->xedd->op.disp;
|
i = m->xedd->op.disp;
|
||||||
if (!SibExists(m->xedd)) {
|
if (!SibExists(rde)) {
|
||||||
i += IsRipRelative(m->xedd) ? m->ip : Read64(RegRexbRm(m));
|
if (IsRipRelative(rde)) {
|
||||||
|
i += m->ip;
|
||||||
|
} else {
|
||||||
|
i += Read64(RegRexbRm(m, rde));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
DCHECK(m->xedd->op.has_sib);
|
DCHECK(m->xedd->op.has_sib);
|
||||||
if (SibHasBase(m->xedd)) i += Read64(RegRexbBase(m));
|
if (SibHasBase(rde)) {
|
||||||
if (SibHasIndex(m->xedd)) i += Read64(RegRexxIndex(m)) << m->xedd->op.scale;
|
i += Read64(RegRexbBase(m, rde));
|
||||||
|
}
|
||||||
|
if (SibHasIndex(rde)) {
|
||||||
|
i += Read64(RegRexxIndex(m, rde)) << m->xedd->op.scale;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
i += GetSegment(m);
|
i += GetSegment(m);
|
||||||
if (Asz(m->xedd)) i &= 0xffffffff;
|
if (Asz(rde)) i &= 0xffffffff;
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ComputeReserveAddressRead(struct Machine *m, size_t n) {
|
void *ComputeReserveAddressRead(struct Machine *m, uint32_t rde, size_t n) {
|
||||||
int64_t v;
|
int64_t v;
|
||||||
v = ComputeAddress(m);
|
v = ComputeAddress(m, rde);
|
||||||
SetReadAddr(m, v, n);
|
SetReadAddr(m, v, n);
|
||||||
return ReserveAddress(m, v, n);
|
return ReserveAddress(m, v, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ComputeReserveAddressRead1(struct Machine *m) {
|
void *ComputeReserveAddressRead1(struct Machine *m, uint32_t rde) {
|
||||||
return ComputeReserveAddressRead(m, 1);
|
return ComputeReserveAddressRead(m, rde, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ComputeReserveAddressRead8(struct Machine *m) {
|
void *ComputeReserveAddressRead8(struct Machine *m, uint32_t rde) {
|
||||||
return ComputeReserveAddressRead(m, 8);
|
return ComputeReserveAddressRead(m, rde, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ComputeReserveAddressWrite(struct Machine *m, size_t n) {
|
void *ComputeReserveAddressWrite(struct Machine *m, uint32_t rde, size_t n) {
|
||||||
int64_t v;
|
int64_t v;
|
||||||
v = ComputeAddress(m);
|
v = ComputeAddress(m, rde);
|
||||||
SetWriteAddr(m, v, n);
|
SetWriteAddr(m, v, n);
|
||||||
return ReserveAddress(m, v, n);
|
return ReserveAddress(m, v, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ComputeReserveAddressWrite1(struct Machine *m) {
|
void *ComputeReserveAddressWrite1(struct Machine *m, uint32_t rde) {
|
||||||
return ComputeReserveAddressWrite(m, 1);
|
return ComputeReserveAddressWrite(m, rde, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ComputeReserveAddressWrite4(struct Machine *m) {
|
void *ComputeReserveAddressWrite4(struct Machine *m, uint32_t rde) {
|
||||||
return ComputeReserveAddressWrite(m, 4);
|
return ComputeReserveAddressWrite(m, rde, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ComputeReserveAddressWrite8(struct Machine *m) {
|
void *ComputeReserveAddressWrite8(struct Machine *m, uint32_t rde) {
|
||||||
return ComputeReserveAddressWrite(m, 8);
|
return ComputeReserveAddressWrite(m, rde, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterMmPointerRead(struct Machine *m, size_t n) {
|
uint8_t *GetModrmRegisterMmPointerRead(struct Machine *m, uint32_t rde,
|
||||||
if (IsModrmRegister(m->xedd)) {
|
size_t n) {
|
||||||
return MmRm(m);
|
if (IsModrmRegister(rde)) {
|
||||||
|
return MmRm(m, rde);
|
||||||
} else {
|
} else {
|
||||||
return ComputeReserveAddressRead(m, n);
|
return ComputeReserveAddressRead(m, rde, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterMmPointerRead8(struct Machine *m) {
|
uint8_t *GetModrmRegisterMmPointerRead8(struct Machine *m, uint32_t rde) {
|
||||||
return GetModrmRegisterMmPointerRead(m, 8);
|
return GetModrmRegisterMmPointerRead(m, rde, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterMmPointerWrite(struct Machine *m, size_t n) {
|
uint8_t *GetModrmRegisterMmPointerWrite(struct Machine *m, uint32_t rde,
|
||||||
if (IsModrmRegister(m->xedd)) {
|
size_t n) {
|
||||||
return MmRm(m);
|
if (IsModrmRegister(rde)) {
|
||||||
|
return MmRm(m, rde);
|
||||||
} else {
|
} else {
|
||||||
return ComputeReserveAddressWrite(m, n);
|
return ComputeReserveAddressWrite(m, rde, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterMmPointerWrite8(struct Machine *m) {
|
uint8_t *GetModrmRegisterMmPointerWrite8(struct Machine *m, uint32_t rde) {
|
||||||
return GetModrmRegisterMmPointerWrite(m, 8);
|
return GetModrmRegisterMmPointerWrite(m, rde, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterBytePointerRead(struct Machine *m) {
|
uint8_t *GetModrmRegisterBytePointerRead(struct Machine *m, uint32_t rde) {
|
||||||
int64_t v;
|
int64_t v;
|
||||||
if (IsModrmRegister(m->xedd)) {
|
if (IsModrmRegister(rde)) {
|
||||||
return ByteRexbRm(m);
|
return ByteRexbRm(m, rde);
|
||||||
} else {
|
} else {
|
||||||
return ComputeReserveAddressRead1(m);
|
return ComputeReserveAddressRead1(m, rde);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterBytePointerWrite(struct Machine *m) {
|
uint8_t *GetModrmRegisterBytePointerWrite(struct Machine *m, uint32_t rde) {
|
||||||
int64_t v;
|
int64_t v;
|
||||||
if (IsModrmRegister(m->xedd)) {
|
if (IsModrmRegister(rde)) {
|
||||||
return ByteRexbRm(m);
|
return ByteRexbRm(m, rde);
|
||||||
} else {
|
} else {
|
||||||
return ComputeReserveAddressWrite1(m);
|
return ComputeReserveAddressWrite1(m, rde);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterWordPointerRead(struct Machine *m, size_t n) {
|
uint8_t *GetModrmRegisterWordPointerRead(struct Machine *m, uint32_t rde,
|
||||||
if (IsModrmRegister(m->xedd)) {
|
size_t n) {
|
||||||
return RegRexbRm(m);
|
if (IsModrmRegister(rde)) {
|
||||||
|
return RegRexbRm(m, rde);
|
||||||
} else {
|
} else {
|
||||||
return ComputeReserveAddressRead(m, n);
|
return ComputeReserveAddressRead(m, rde, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterWordPointerRead2(struct Machine *m) {
|
uint8_t *GetModrmRegisterWordPointerRead2(struct Machine *m, uint32_t rde) {
|
||||||
return GetModrmRegisterWordPointerRead(m, 2);
|
return GetModrmRegisterWordPointerRead(m, rde, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterWordPointerRead4(struct Machine *m) {
|
uint8_t *GetModrmRegisterWordPointerRead4(struct Machine *m, uint32_t rde) {
|
||||||
return GetModrmRegisterWordPointerRead(m, 4);
|
return GetModrmRegisterWordPointerRead(m, rde, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterWordPointerRead8(struct Machine *m) {
|
uint8_t *GetModrmRegisterWordPointerRead8(struct Machine *m, uint32_t rde) {
|
||||||
return GetModrmRegisterWordPointerRead(m, 8);
|
return GetModrmRegisterWordPointerRead(m, rde, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterWordPointerReadOsz(struct Machine *m) {
|
uint8_t *GetModrmRegisterWordPointerReadOsz(struct Machine *m, uint32_t rde) {
|
||||||
if (!Osz(m->xedd)) {
|
if (!Osz(rde)) {
|
||||||
return GetModrmRegisterWordPointerRead8(m);
|
return GetModrmRegisterWordPointerRead8(m, rde);
|
||||||
} else {
|
} else {
|
||||||
return GetModrmRegisterWordPointerRead2(m);
|
return GetModrmRegisterWordPointerRead2(m, rde);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterWordPointerReadOszRexw(struct Machine *m) {
|
uint8_t *GetModrmRegisterWordPointerReadOszRexw(struct Machine *m,
|
||||||
if (Rexw(m->xedd)) {
|
uint32_t rde) {
|
||||||
return GetModrmRegisterWordPointerRead8(m);
|
if (Rexw(rde)) {
|
||||||
} else if (!Osz(m->xedd)) {
|
return GetModrmRegisterWordPointerRead8(m, rde);
|
||||||
return GetModrmRegisterWordPointerRead4(m);
|
} else if (!Osz(rde)) {
|
||||||
|
return GetModrmRegisterWordPointerRead4(m, rde);
|
||||||
} else {
|
} else {
|
||||||
return GetModrmRegisterWordPointerRead2(m);
|
return GetModrmRegisterWordPointerRead2(m, rde);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterWordPointerWrite(struct Machine *m, size_t n) {
|
uint8_t *GetModrmRegisterWordPointerWrite(struct Machine *m, uint32_t rde,
|
||||||
if (IsModrmRegister(m->xedd)) {
|
size_t n) {
|
||||||
return RegRexbRm(m);
|
if (IsModrmRegister(rde)) {
|
||||||
|
return RegRexbRm(m, rde);
|
||||||
} else {
|
} else {
|
||||||
return ComputeReserveAddressWrite(m, n);
|
return ComputeReserveAddressWrite(m, rde, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterWordPointerWrite4(struct Machine *m) {
|
uint8_t *GetModrmRegisterWordPointerWrite4(struct Machine *m, uint32_t rde) {
|
||||||
return GetModrmRegisterWordPointerWrite(m, 4);
|
return GetModrmRegisterWordPointerWrite(m, rde, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterWordPointerWrite8(struct Machine *m) {
|
uint8_t *GetModrmRegisterWordPointerWrite8(struct Machine *m, uint32_t rde) {
|
||||||
return GetModrmRegisterWordPointerWrite(m, 8);
|
return GetModrmRegisterWordPointerWrite(m, rde, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterWordPointerWriteOszRexw(struct Machine *m) {
|
uint8_t *GetModrmRegisterWordPointerWriteOszRexw(struct Machine *m,
|
||||||
if (Rexw(m->xedd)) {
|
uint32_t rde) {
|
||||||
return GetModrmRegisterWordPointerWrite(m, 8);
|
if (Rexw(rde)) {
|
||||||
} else if (!Osz(m->xedd)) {
|
return GetModrmRegisterWordPointerWrite(m, rde, 8);
|
||||||
return GetModrmRegisterWordPointerWrite(m, 4);
|
} else if (!Osz(rde)) {
|
||||||
|
return GetModrmRegisterWordPointerWrite(m, rde, 4);
|
||||||
} else {
|
} else {
|
||||||
return GetModrmRegisterWordPointerWrite(m, 2);
|
return GetModrmRegisterWordPointerWrite(m, rde, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterWordPointerWriteOsz(struct Machine *m) {
|
uint8_t *GetModrmRegisterWordPointerWriteOsz(struct Machine *m, uint32_t rde) {
|
||||||
if (!Osz(m->xedd)) {
|
if (!Osz(rde)) {
|
||||||
return GetModrmRegisterWordPointerWrite(m, 8);
|
return GetModrmRegisterWordPointerWrite(m, rde, 8);
|
||||||
} else {
|
} else {
|
||||||
return GetModrmRegisterWordPointerWrite(m, 2);
|
return GetModrmRegisterWordPointerWrite(m, rde, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterXmmPointerRead(struct Machine *m, size_t n) {
|
uint8_t *GetModrmRegisterXmmPointerRead(struct Machine *m, uint32_t rde,
|
||||||
if (IsModrmRegister(m->xedd)) {
|
size_t n) {
|
||||||
return XmmRexbRm(m);
|
if (IsModrmRegister(rde)) {
|
||||||
|
return XmmRexbRm(m, rde);
|
||||||
} else {
|
} else {
|
||||||
return ComputeReserveAddressRead(m, n);
|
return ComputeReserveAddressRead(m, rde, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterXmmPointerRead4(struct Machine *m) {
|
uint8_t *GetModrmRegisterXmmPointerRead4(struct Machine *m, uint32_t rde) {
|
||||||
return GetModrmRegisterXmmPointerRead(m, 4);
|
return GetModrmRegisterXmmPointerRead(m, rde, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterXmmPointerRead8(struct Machine *m) {
|
uint8_t *GetModrmRegisterXmmPointerRead8(struct Machine *m, uint32_t rde) {
|
||||||
return GetModrmRegisterXmmPointerRead(m, 8);
|
return GetModrmRegisterXmmPointerRead(m, rde, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterXmmPointerRead16(struct Machine *m) {
|
uint8_t *GetModrmRegisterXmmPointerRead16(struct Machine *m, uint32_t rde) {
|
||||||
return GetModrmRegisterXmmPointerRead(m, 16);
|
return GetModrmRegisterXmmPointerRead(m, rde, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterXmmPointerWrite(struct Machine *m, size_t n) {
|
uint8_t *GetModrmRegisterXmmPointerWrite(struct Machine *m, uint32_t rde,
|
||||||
if (IsModrmRegister(m->xedd)) {
|
size_t n) {
|
||||||
return XmmRexbRm(m);
|
if (IsModrmRegister(rde)) {
|
||||||
|
return XmmRexbRm(m, rde);
|
||||||
} else {
|
} else {
|
||||||
return ComputeReserveAddressWrite(m, n);
|
return ComputeReserveAddressWrite(m, rde, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterXmmPointerWrite4(struct Machine *m) {
|
uint8_t *GetModrmRegisterXmmPointerWrite4(struct Machine *m, uint32_t rde) {
|
||||||
return GetModrmRegisterXmmPointerWrite(m, 4);
|
return GetModrmRegisterXmmPointerWrite(m, rde, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterXmmPointerWrite8(struct Machine *m) {
|
uint8_t *GetModrmRegisterXmmPointerWrite8(struct Machine *m, uint32_t rde) {
|
||||||
return GetModrmRegisterXmmPointerWrite(m, 8);
|
return GetModrmRegisterXmmPointerWrite(m, rde, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterXmmPointerWrite16(struct Machine *m) {
|
uint8_t *GetModrmRegisterXmmPointerWrite16(struct Machine *m, uint32_t rde) {
|
||||||
return GetModrmRegisterXmmPointerWrite(m, 16);
|
return GetModrmRegisterXmmPointerWrite(m, rde, 16);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,80 +2,80 @@
|
||||||
#define COSMOPOLITAN_TOOL_BUILD_LIB_MODRM_H_
|
#define COSMOPOLITAN_TOOL_BUILD_LIB_MODRM_H_
|
||||||
#include "tool/build/lib/abp.h"
|
#include "tool/build/lib/abp.h"
|
||||||
#include "tool/build/lib/machine.h"
|
#include "tool/build/lib/machine.h"
|
||||||
#include "tool/build/lib/memory.h"
|
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
|
#define SibBase(x) ((x & 000007000000) >> 022)
|
||||||
|
#define SibIndex(x) ((x & 000700000000) >> 030)
|
||||||
|
#define ModrmRm(x) ((x & 000000000700) >> 006)
|
||||||
|
#define ModrmReg(x) ((x & 000000000007) >> 000)
|
||||||
|
#define ModrmSrm(x) ((x & 000000070000) >> 014)
|
||||||
|
#define ModrmMod(x) ((x & 000060000000) >> 026)
|
||||||
|
#define RegLog2(x) ((x & 006000000000) >> 034)
|
||||||
|
#define Rexx(x) ((x & 001000000000) >> 033)
|
||||||
|
#define Asz(x) ((x & 000000400000) >> 021)
|
||||||
|
#define Rexw(x) ((x & 000000004000) >> 013)
|
||||||
|
#define Rexr(x) ((x & 000000000010) >> 003)
|
||||||
|
#define Rexb(x) ((x & 000010000000) >> 025)
|
||||||
|
#define Rex(x) ((x & 000000000020) >> 004)
|
||||||
|
#define Osz(x) ((x & 000000000040) >> 005)
|
||||||
|
#define Rep(x) ((x & 030000000000) >> 036)
|
||||||
|
|
||||||
#define IsModrmRegister(x) (ModrmMod(x) == 3)
|
#define IsModrmRegister(x) (ModrmMod(x) == 3)
|
||||||
#define IsProbablyByteOp(x) !((x)->op.opcode & 1)
|
|
||||||
#define SibExists(x) (ModrmRm(x) == 4)
|
#define SibExists(x) (ModrmRm(x) == 4)
|
||||||
#define SibHasIndex(x) (SibIndex(x) != 4 || Rexx(x))
|
#define SibHasIndex(x) (SibIndex(x) != 4 || Rexx(x))
|
||||||
#define SibHasBase(x) (SibBase(x) != 5 || ModrmMod(x))
|
#define SibHasBase(x) (SibBase(x) != 5 || ModrmMod(x))
|
||||||
#define SibIsAbsolute(x) (!SibHasBase(x) && !SibHasIndex(x))
|
#define SibIsAbsolute(x) (!SibHasBase(x) && !SibHasIndex(x))
|
||||||
#define IsRipRelative(x) (ModrmRm(x) == 5 && !ModrmMod(x))
|
#define IsRipRelative(x) (ModrmRm(x) == 5 && !ModrmMod(x))
|
||||||
#define SibBase(x) (((x)->op.rde & 000007000000) >> 18)
|
|
||||||
#define SibIndex(x) (((x)->op.rde & 000700000000) >> 24)
|
|
||||||
#define ModrmRm(x) (((x)->op.rde & 000000000700) >> 6)
|
|
||||||
#define ModrmReg(x) (((x)->op.rde & 000000000007) >> 0)
|
|
||||||
#define ModrmSrm(x) (((x)->op.rde & 000000070000) >> 12)
|
|
||||||
#define ModrmMod(x) (((x)->op.rde & 000060000000) >> 22)
|
|
||||||
#define RegLog2(x) (((x)->op.rde & 006000000000) >> 28)
|
|
||||||
#define Rexx(x) (((x)->op.rde & 001000000000) >> 27)
|
|
||||||
#define Asz(x) (((x)->op.rde & 000000400000) >> 17)
|
|
||||||
#define Rexw(x) (((x)->op.rde & 000000004000) >> 11)
|
|
||||||
#define Rexr(x) (((x)->op.rde & 000000000010) >> 3)
|
|
||||||
#define Rexb(x) (((x)->op.rde & 000010000000) >> 21)
|
|
||||||
#define Rex(x) (((x)->op.rde & 000000000020) >> 4)
|
|
||||||
#define Osz(x) (((x)->op.rde & 000000000040) >> 5)
|
|
||||||
#define Rep(x) (((x)->op.rde & 030000000000) >> 30)
|
|
||||||
#define ByteRexrReg(m) m->beg[(m->xedd->op.rde & 00000000037) >> 0]
|
|
||||||
#define ByteRexbRm(m) m->beg[(m->xedd->op.rde & 00000003700) >> 6]
|
|
||||||
#define ByteRexbSrm(m) m->beg[(m->xedd->op.rde & 00000370000) >> 12]
|
|
||||||
#define RegRexrReg(m) Abp8(m->reg[(m->xedd->op.rde & 00000000017) >> 0])
|
|
||||||
#define RegRexbRm(m) Abp8(m->reg[(m->xedd->op.rde & 00000001700) >> 6])
|
|
||||||
#define RegRexbSrm(m) Abp8(m->reg[(m->xedd->op.rde & 00000170000) >> 12])
|
|
||||||
#define RegRexbBase(m) Abp8(m->reg[(m->xedd->op.rde & 00017000000) >> 18])
|
|
||||||
#define RegRexxIndex(m) Abp8(m->reg[(m->xedd->op.rde & 01700000000) >> 24])
|
|
||||||
#define XmmRexrReg(m) Abp16(m->veg[(m->xedd->op.rde & 00000000017) >> 0])
|
|
||||||
#define XmmRexbRm(m) Abp16(m->veg[(m->xedd->op.rde & 00000001700) >> 6])
|
|
||||||
#define MmReg(m) Abp16(m->veg[(m->xedd->op.rde & 00000000007) >> 0])
|
|
||||||
#define MmRm(m) Abp16(m->veg[(m->xedd->op.rde & 00000000700) >> 6])
|
|
||||||
|
|
||||||
int64_t ComputeAddress(const struct Machine *) nosideeffect;
|
#define ByteRexrReg(m, x) m->beg[(x & 00000000037) >> 0]
|
||||||
|
#define ByteRexbRm(m, x) m->beg[(x & 00000003700) >> 6]
|
||||||
|
#define ByteRexbSrm(m, x) m->beg[(x & 00000370000) >> 12]
|
||||||
|
#define RegRexbSrm(m, x) Abp8(m->reg[(x & 00000170000) >> 12])
|
||||||
|
#define RegRexrReg(m, x) Abp8(m->reg[(x & 00000000017) >> 0])
|
||||||
|
#define RegRexbRm(m, x) Abp8(m->reg[(x & 00000001700) >> 6])
|
||||||
|
#define RegRexbBase(m, x) Abp8(m->reg[(x & 00017000000) >> 18])
|
||||||
|
#define RegRexxIndex(m, x) Abp8(m->reg[(x & 01700000000) >> 24])
|
||||||
|
#define XmmRexrReg(m, x) Abp16(m->veg[(x & 00000000017) >> 0])
|
||||||
|
#define XmmRexbRm(m, x) Abp16(m->veg[(x & 00000001700) >> 6])
|
||||||
|
#define MmReg(m, x) Abp16(m->veg[(x & 00000000007) >> 0])
|
||||||
|
#define MmRm(m, x) Abp16(m->veg[(x & 00000000700) >> 6])
|
||||||
|
|
||||||
void *ComputeReserveAddressRead(struct Machine *, size_t);
|
int64_t ComputeAddress(const struct Machine *, uint32_t) nosideeffect;
|
||||||
void *ComputeReserveAddressRead1(struct Machine *);
|
|
||||||
void *ComputeReserveAddressRead8(struct Machine *);
|
|
||||||
void *ComputeReserveAddressWrite(struct Machine *, size_t);
|
|
||||||
void *ComputeReserveAddressWrite1(struct Machine *);
|
|
||||||
void *ComputeReserveAddressWrite4(struct Machine *);
|
|
||||||
void *ComputeReserveAddressWrite8(struct Machine *);
|
|
||||||
|
|
||||||
uint8_t *GetModrmRegisterBytePointerRead(struct Machine *);
|
void *ComputeReserveAddressRead(struct Machine *, uint32_t, size_t);
|
||||||
uint8_t *GetModrmRegisterBytePointerWrite(struct Machine *);
|
void *ComputeReserveAddressRead1(struct Machine *, uint32_t);
|
||||||
uint8_t *GetModrmRegisterMmPointerRead(struct Machine *, size_t);
|
void *ComputeReserveAddressRead8(struct Machine *, uint32_t);
|
||||||
uint8_t *GetModrmRegisterMmPointerRead8(struct Machine *);
|
void *ComputeReserveAddressWrite(struct Machine *, uint32_t, size_t);
|
||||||
uint8_t *GetModrmRegisterMmPointerWrite(struct Machine *, size_t);
|
void *ComputeReserveAddressWrite1(struct Machine *, uint32_t);
|
||||||
uint8_t *GetModrmRegisterMmPointerWrite8(struct Machine *);
|
void *ComputeReserveAddressWrite4(struct Machine *, uint32_t);
|
||||||
uint8_t *GetModrmRegisterWordPointerRead(struct Machine *, size_t);
|
void *ComputeReserveAddressWrite8(struct Machine *, uint32_t);
|
||||||
uint8_t *GetModrmRegisterWordPointerRead2(struct Machine *);
|
|
||||||
uint8_t *GetModrmRegisterWordPointerRead4(struct Machine *);
|
uint8_t *GetModrmRegisterBytePointerRead(struct Machine *, uint32_t);
|
||||||
uint8_t *GetModrmRegisterWordPointerRead8(struct Machine *);
|
uint8_t *GetModrmRegisterBytePointerWrite(struct Machine *, uint32_t);
|
||||||
uint8_t *GetModrmRegisterWordPointerReadOsz(struct Machine *);
|
uint8_t *GetModrmRegisterMmPointerRead(struct Machine *, uint32_t, size_t);
|
||||||
uint8_t *GetModrmRegisterWordPointerReadOszRexw(struct Machine *);
|
uint8_t *GetModrmRegisterMmPointerRead8(struct Machine *, uint32_t);
|
||||||
uint8_t *GetModrmRegisterWordPointerWrite(struct Machine *, size_t);
|
uint8_t *GetModrmRegisterMmPointerWrite(struct Machine *, uint32_t, size_t);
|
||||||
uint8_t *GetModrmRegisterWordPointerWrite4(struct Machine *);
|
uint8_t *GetModrmRegisterMmPointerWrite8(struct Machine *, uint32_t);
|
||||||
uint8_t *GetModrmRegisterWordPointerWrite8(struct Machine *);
|
uint8_t *GetModrmRegisterWordPointerRead(struct Machine *, uint32_t, size_t);
|
||||||
uint8_t *GetModrmRegisterWordPointerWriteOsz(struct Machine *);
|
uint8_t *GetModrmRegisterWordPointerRead2(struct Machine *, uint32_t);
|
||||||
uint8_t *GetModrmRegisterWordPointerWriteOszRexw(struct Machine *);
|
uint8_t *GetModrmRegisterWordPointerRead4(struct Machine *, uint32_t);
|
||||||
uint8_t *GetModrmRegisterXmmPointerRead(struct Machine *, size_t);
|
uint8_t *GetModrmRegisterWordPointerRead8(struct Machine *, uint32_t);
|
||||||
uint8_t *GetModrmRegisterXmmPointerRead16(struct Machine *);
|
uint8_t *GetModrmRegisterWordPointerReadOsz(struct Machine *, uint32_t);
|
||||||
uint8_t *GetModrmRegisterXmmPointerRead4(struct Machine *);
|
uint8_t *GetModrmRegisterWordPointerReadOszRexw(struct Machine *, uint32_t);
|
||||||
uint8_t *GetModrmRegisterXmmPointerRead8(struct Machine *);
|
uint8_t *GetModrmRegisterWordPointerWrite(struct Machine *, uint32_t, size_t);
|
||||||
uint8_t *GetModrmRegisterXmmPointerWrite(struct Machine *, size_t);
|
uint8_t *GetModrmRegisterWordPointerWrite4(struct Machine *, uint32_t);
|
||||||
uint8_t *GetModrmRegisterXmmPointerWrite16(struct Machine *);
|
uint8_t *GetModrmRegisterWordPointerWrite8(struct Machine *, uint32_t);
|
||||||
uint8_t *GetModrmRegisterXmmPointerWrite4(struct Machine *);
|
uint8_t *GetModrmRegisterWordPointerWriteOsz(struct Machine *, uint32_t);
|
||||||
uint8_t *GetModrmRegisterXmmPointerWrite8(struct Machine *);
|
uint8_t *GetModrmRegisterWordPointerWriteOszRexw(struct Machine *, uint32_t);
|
||||||
|
uint8_t *GetModrmRegisterXmmPointerRead(struct Machine *, uint32_t, size_t);
|
||||||
|
uint8_t *GetModrmRegisterXmmPointerRead16(struct Machine *, uint32_t);
|
||||||
|
uint8_t *GetModrmRegisterXmmPointerRead4(struct Machine *, uint32_t);
|
||||||
|
uint8_t *GetModrmRegisterXmmPointerRead8(struct Machine *, uint32_t);
|
||||||
|
uint8_t *GetModrmRegisterXmmPointerWrite(struct Machine *, uint32_t, size_t);
|
||||||
|
uint8_t *GetModrmRegisterXmmPointerWrite16(struct Machine *, uint32_t);
|
||||||
|
uint8_t *GetModrmRegisterXmmPointerWrite4(struct Machine *, uint32_t);
|
||||||
|
uint8_t *GetModrmRegisterXmmPointerWrite8(struct Machine *, uint32_t);
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
512
tool/build/lib/pty.c
Normal file
512
tool/build/lib/pty.c
Normal file
|
@ -0,0 +1,512 @@
|
||||||
|
/*-*- 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/bits/bits.h"
|
||||||
|
#include "libc/bits/safemacros.h"
|
||||||
|
#include "libc/conv/conv.h"
|
||||||
|
#include "libc/log/check.h"
|
||||||
|
#include "libc/macros.h"
|
||||||
|
#include "libc/mem/mem.h"
|
||||||
|
#include "libc/nexgen32e/bsr.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
|
#include "libc/str/thompike.h"
|
||||||
|
#include "libc/unicode/unicode.h"
|
||||||
|
#include "libc/x/x.h"
|
||||||
|
#include "tool/build/lib/pty.h"
|
||||||
|
|
||||||
|
struct MachinePty *MachinePtyNew(unsigned yn, unsigned xn) {
|
||||||
|
struct MachinePty *pty;
|
||||||
|
DCHECK_GT(yn, 0);
|
||||||
|
DCHECK_GT(xn, 0);
|
||||||
|
pty = xcalloc(1, sizeof(struct MachinePty));
|
||||||
|
pty->yn = yn;
|
||||||
|
pty->xn = xn;
|
||||||
|
pty->wcs = xcalloc(yn * xn, sizeof(pty->wcs[0]));
|
||||||
|
pty->fgs = xcalloc(yn * xn, sizeof(pty->fgs[0]));
|
||||||
|
pty->bgs = xcalloc(yn * xn, sizeof(pty->bgs[0]));
|
||||||
|
pty->prs = xcalloc(yn * xn, sizeof(pty->prs[0]));
|
||||||
|
return pty;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MachinePtyFree(struct MachinePty *pty) {
|
||||||
|
if (pty) {
|
||||||
|
free(pty->wcs);
|
||||||
|
free(pty->fgs);
|
||||||
|
free(pty->bgs);
|
||||||
|
free(pty->prs);
|
||||||
|
free(pty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MachinePtyScrollPlane(struct MachinePty *pty, uint32_t *p) {
|
||||||
|
memcpy(p, p + pty->xn, sizeof(p[0]) * pty->xn * (pty->yn - 1));
|
||||||
|
memset(p + pty->xn * (pty->yn - 1), 0, sizeof(p[0]) * pty->xn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MachinePtyScroll(struct MachinePty *pty) {
|
||||||
|
MachinePtyScrollPlane(pty, pty->wcs);
|
||||||
|
MachinePtyScrollPlane(pty, pty->fgs);
|
||||||
|
MachinePtyScrollPlane(pty, pty->bgs);
|
||||||
|
MachinePtyScrollPlane(pty, pty->prs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MachinePtyNewline(struct MachinePty *pty) {
|
||||||
|
pty->x = 0;
|
||||||
|
if (++pty->y == pty->yn) {
|
||||||
|
--pty->y;
|
||||||
|
MachinePtyScroll(pty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetMachinePtyCell(struct MachinePty *pty, wint_t wc) {
|
||||||
|
uint32_t w, i;
|
||||||
|
if ((w = MAX(0, wcwidth(wc))) > 0) {
|
||||||
|
i = pty->y * pty->xn + pty->x;
|
||||||
|
pty->wcs[i] = wc;
|
||||||
|
pty->fgs[i] = pty->fg;
|
||||||
|
pty->bgs[i] = pty->bg;
|
||||||
|
pty->prs[i] = pty->pr;
|
||||||
|
if ((pty->x += w) >= pty->xn) {
|
||||||
|
pty->x = 0;
|
||||||
|
MachinePtyNewline(pty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MachinePtyTab(struct MachinePty *pty) {
|
||||||
|
unsigned x, x2;
|
||||||
|
x2 = pty->x + ROUNDUP(pty->x + 1, 8);
|
||||||
|
if (x2 >= pty->xn) x2 = pty->xn - 1;
|
||||||
|
for (x = pty->x; x < x2; ++x) {
|
||||||
|
pty->wcs[pty->y * pty->xn + x] = 0;
|
||||||
|
}
|
||||||
|
pty->x = x2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MachinePtyCursorSet(struct MachinePty *pty, int y, int x) {
|
||||||
|
pty->y = MAX(0, MIN(pty->yn - 1, y));
|
||||||
|
pty->x = MAX(0, MIN(pty->xn - 1, x));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MachinePtyCursorMove(struct MachinePty *pty, int dy, int dx) {
|
||||||
|
int n;
|
||||||
|
if (pty->esc.i > 1) {
|
||||||
|
n = atoi(pty->esc.s);
|
||||||
|
dy *= n;
|
||||||
|
dx *= n;
|
||||||
|
}
|
||||||
|
MachinePtyCursorSet(pty, pty->y + dy, pty->x + dx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MachinePtyCursorPosition(struct MachinePty *pty) {
|
||||||
|
int row, col;
|
||||||
|
row = MAX(1, atoi(pty->esc.s));
|
||||||
|
col = MAX(1, atoi((char *)firstnonnull(strchr(pty->esc.s, ';'), "x") + 1));
|
||||||
|
MachinePtyCursorSet(pty, row - 1, col - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MachinePtyEraseRange(struct MachinePty *pty, size_t i, size_t j) {
|
||||||
|
size_t n;
|
||||||
|
n = (j - i) * sizeof(uint32_t);
|
||||||
|
memset(pty->wcs + i, 0, n);
|
||||||
|
memset(pty->fgs + i, 0, n);
|
||||||
|
memset(pty->bgs + i, 0, n);
|
||||||
|
memset(pty->prs + i, 0, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MachinePtyEraseDisplay(struct MachinePty *pty) {
|
||||||
|
switch (atoi(pty->esc.s)) {
|
||||||
|
case 3:
|
||||||
|
case 2:
|
||||||
|
pty->y = 0;
|
||||||
|
pty->x = 0;
|
||||||
|
case 0:
|
||||||
|
MachinePtyEraseRange(pty, pty->y * pty->xn + pty->x, pty->yn * pty->xn);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
MachinePtyEraseRange(pty, 0, pty->y * pty->xn + pty->x);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MachinePtyEraseLine(struct MachinePty *pty) {
|
||||||
|
switch (atoi(pty->esc.s)) {
|
||||||
|
case 0:
|
||||||
|
MachinePtyEraseRange(pty, pty->y * pty->xn + pty->x,
|
||||||
|
pty->y * pty->xn + pty->xn);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
MachinePtyEraseRange(pty, pty->y * pty->xn + pty->xn,
|
||||||
|
pty->y * pty->xn + pty->x);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
MachinePtyEraseRange(pty, pty->y * pty->xn, pty->y * pty->xn + pty->xn);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MachinePtySelectGraphicsRendition(struct MachinePty *pty) {
|
||||||
|
char *p, c;
|
||||||
|
unsigned x;
|
||||||
|
uint8_t code[4];
|
||||||
|
enum {
|
||||||
|
kSgr,
|
||||||
|
kSgrFg = 010,
|
||||||
|
kSgrFgTrue = 012,
|
||||||
|
kSgrFgXterm = 015,
|
||||||
|
kSgrBg = 020,
|
||||||
|
kSgrBgTrue = 022,
|
||||||
|
kSgrBgXterm = 025,
|
||||||
|
} t;
|
||||||
|
x = 0;
|
||||||
|
t = kSgr;
|
||||||
|
p = pty->esc.s;
|
||||||
|
memset(code, 0, sizeof(code));
|
||||||
|
for (;;) {
|
||||||
|
c = *p++;
|
||||||
|
switch (c) {
|
||||||
|
case '\0':
|
||||||
|
return;
|
||||||
|
case '0' ... '9':
|
||||||
|
x *= 10;
|
||||||
|
x += c - '0';
|
||||||
|
break;
|
||||||
|
case ';':
|
||||||
|
case 'm':
|
||||||
|
code[code[3]] = x;
|
||||||
|
x = 0;
|
||||||
|
switch (t) {
|
||||||
|
case kSgr:
|
||||||
|
switch (code[0]) {
|
||||||
|
case 0:
|
||||||
|
pty->fg = 0;
|
||||||
|
pty->bg = 0;
|
||||||
|
pty->pr = 0;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
pty->pr |= kMachinePtyBold;
|
||||||
|
break;
|
||||||
|
case 21:
|
||||||
|
pty->pr &= ~kMachinePtyBold;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
pty->pr |= kMachinePtyFaint;
|
||||||
|
break;
|
||||||
|
case 22:
|
||||||
|
pty->pr &= ~kMachinePtyFaint;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
pty->pr |= kMachinePtyFlip;
|
||||||
|
break;
|
||||||
|
case 27:
|
||||||
|
pty->pr &= ~kMachinePtyFlip;
|
||||||
|
break;
|
||||||
|
case 90 ... 97:
|
||||||
|
code[0] -= 90 - 30;
|
||||||
|
code[0] += 8;
|
||||||
|
case 30 ... 37:
|
||||||
|
pty->fg = code[0] - 30;
|
||||||
|
pty->pr |= kMachinePtyFg;
|
||||||
|
pty->pr &= ~kMachinePtyTrue;
|
||||||
|
break;
|
||||||
|
case 38:
|
||||||
|
t = kSgrFg;
|
||||||
|
break;
|
||||||
|
case 39:
|
||||||
|
pty->pr &= kMachinePtyFg;
|
||||||
|
break;
|
||||||
|
case 100 ... 107:
|
||||||
|
code[0] -= 100 - 40;
|
||||||
|
code[0] += 8;
|
||||||
|
case 40 ... 47:
|
||||||
|
pty->bg = code[0] - 40;
|
||||||
|
pty->pr |= kMachinePtyBg;
|
||||||
|
pty->pr &= ~kMachinePtyTrue;
|
||||||
|
break;
|
||||||
|
case 48:
|
||||||
|
t = kSgrBg;
|
||||||
|
break;
|
||||||
|
case 49:
|
||||||
|
pty->pr &= kMachinePtyBg;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case kSgrFg:
|
||||||
|
case kSgrBg:
|
||||||
|
switch (code[0]) {
|
||||||
|
case 2:
|
||||||
|
case 5:
|
||||||
|
t += code[0];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
t = kSgr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case kSgrFgTrue:
|
||||||
|
if (++code[3] == 3) {
|
||||||
|
code[3] = 0;
|
||||||
|
t = kSgr;
|
||||||
|
pty->fg = READ32LE(code);
|
||||||
|
pty->pr |= kMachinePtyFg;
|
||||||
|
pty->pr |= kMachinePtyTrue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case kSgrBgTrue:
|
||||||
|
if (++code[3] == 3) {
|
||||||
|
code[3] = 0;
|
||||||
|
t = kSgr;
|
||||||
|
pty->bg = READ32LE(code);
|
||||||
|
pty->pr |= kMachinePtyBg;
|
||||||
|
pty->pr |= kMachinePtyTrue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case kSgrFgXterm:
|
||||||
|
t = kSgr;
|
||||||
|
pty->fg = code[0];
|
||||||
|
pty->pr |= kMachinePtyFg;
|
||||||
|
pty->pr &= ~kMachinePtyTrue;
|
||||||
|
break;
|
||||||
|
case kSgrBgXterm:
|
||||||
|
t = kSgr;
|
||||||
|
pty->bg = code[0];
|
||||||
|
pty->pr |= kMachinePtyBg;
|
||||||
|
pty->pr &= ~kMachinePtyTrue;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MachinePtyHideCursor(struct MachinePty *pty) {
|
||||||
|
pty->conf |= kMachinePtyNocursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MachinePtyShowCursor(struct MachinePty *pty) {
|
||||||
|
pty->conf &= ~kMachinePtyNocursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MachinePtyCsi(struct MachinePty *pty) {
|
||||||
|
switch (pty->esc.s[pty->esc.i - 1]) {
|
||||||
|
case 'A':
|
||||||
|
MachinePtyCursorMove(pty, -1, +0);
|
||||||
|
break;
|
||||||
|
case 'B':
|
||||||
|
MachinePtyCursorMove(pty, +1, +0);
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
MachinePtyCursorMove(pty, +0, +1);
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
MachinePtyCursorMove(pty, +0, -1);
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
case 'H':
|
||||||
|
MachinePtyCursorPosition(pty);
|
||||||
|
break;
|
||||||
|
case 'J':
|
||||||
|
MachinePtyEraseDisplay(pty);
|
||||||
|
break;
|
||||||
|
case 'K':
|
||||||
|
MachinePtyEraseLine(pty);
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
MachinePtySelectGraphicsRendition(pty);
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
if (strcmp(pty->esc.s, "?25l") == 0) {
|
||||||
|
MachinePtyHideCursor(pty);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
if (strcmp(pty->esc.s, "?25h") == 0) {
|
||||||
|
MachinePtyShowCursor(pty);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MachinePtyEsc(struct MachinePty *pty) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MachinePtyEscAppend(struct MachinePty *pty, char c) {
|
||||||
|
pty->esc.i = MIN(pty->esc.i + 1, ARRAYLEN(pty->esc.s) - 1);
|
||||||
|
pty->esc.s[pty->esc.i - 1] = c;
|
||||||
|
pty->esc.s[pty->esc.i - 0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t MachinePtyWrite(struct MachinePty *pty, const void *data, size_t n) {
|
||||||
|
int i;
|
||||||
|
const uint8_t *p;
|
||||||
|
for (p = data, i = 0; i < n; ++i) {
|
||||||
|
switch (pty->state) {
|
||||||
|
case kMachinePtyAscii:
|
||||||
|
if (p[i] < 0b10000000) {
|
||||||
|
switch (p[i]) {
|
||||||
|
case '\e':
|
||||||
|
pty->state = kMachinePtyEsc;
|
||||||
|
pty->esc.i = 0;
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
MachinePtyTab(pty);
|
||||||
|
break;
|
||||||
|
case '\r':
|
||||||
|
pty->x = 0;
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
MachinePtyNewline(pty);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SetMachinePtyCell(pty, p[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (!ThomPikeCont(p[i])) {
|
||||||
|
pty->state = kMachinePtyUtf8;
|
||||||
|
pty->u8 = ThomPikeByte(p[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case kMachinePtyUtf8:
|
||||||
|
if (ThomPikeCont(p[i])) {
|
||||||
|
pty->u8 <<= 6;
|
||||||
|
pty->u8 |= p[i] & 0b00111111;
|
||||||
|
} else {
|
||||||
|
SetMachinePtyCell(pty, pty->u8);
|
||||||
|
pty->state = kMachinePtyAscii;
|
||||||
|
pty->u8 = 0;
|
||||||
|
--i;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case kMachinePtyEsc:
|
||||||
|
if (p[i] == '[') {
|
||||||
|
pty->state = kMachinePtyCsi;
|
||||||
|
} else if (0x30 <= p[i] && p[i] <= 0x7e) {
|
||||||
|
MachinePtyEscAppend(pty, p[i]);
|
||||||
|
MachinePtyEsc(pty);
|
||||||
|
pty->state = kMachinePtyAscii;
|
||||||
|
} else if (0x20 <= p[i] && p[i] <= 0x2f) {
|
||||||
|
MachinePtyEscAppend(pty, p[i]);
|
||||||
|
} else {
|
||||||
|
pty->state = kMachinePtyAscii;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case kMachinePtyCsi:
|
||||||
|
MachinePtyEscAppend(pty, p[i]);
|
||||||
|
switch (p[i]) {
|
||||||
|
case ':':
|
||||||
|
case ';':
|
||||||
|
case '<':
|
||||||
|
case '=':
|
||||||
|
case '>':
|
||||||
|
case '?':
|
||||||
|
case '0' ... '9':
|
||||||
|
break;
|
||||||
|
case '`':
|
||||||
|
case '~':
|
||||||
|
case '^':
|
||||||
|
case '@':
|
||||||
|
case '[':
|
||||||
|
case ']':
|
||||||
|
case '{':
|
||||||
|
case '}':
|
||||||
|
case '_':
|
||||||
|
case '|':
|
||||||
|
case '\\':
|
||||||
|
case 'A' ... 'Z':
|
||||||
|
case 'a' ... 'z':
|
||||||
|
MachinePtyCsi(pty);
|
||||||
|
pty->state = kMachinePtyAscii;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pty->state = kMachinePtyAscii;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pty->u8) {
|
||||||
|
SetMachinePtyCell(pty, pty->u8);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MachinePtyAppendLine(struct MachinePty *pty, struct Buffer *buf,
|
||||||
|
unsigned y) {
|
||||||
|
uint32_t x, i, fg, bg, pr, wc, w;
|
||||||
|
CHECK_LT(y, pty->yn);
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
AppendWide(buf, wc);
|
||||||
|
} else {
|
||||||
|
w = 1;
|
||||||
|
if (y == pty->y && x == pty->x) {
|
||||||
|
if (!(pty->conf & kMachinePtyNocursor)) {
|
||||||
|
AppendStr(buf, "\e[5m▂\e[25m");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
AppendChar(buf, ' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AppendStr(buf, "\e[0m");
|
||||||
|
}
|
50
tool/build/lib/pty.h
Normal file
50
tool/build/lib/pty.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_PTY_H_
|
||||||
|
#define COSMOPOLITAN_TOOL_BUILD_LIB_PTY_H_
|
||||||
|
#include "tool/build/lib/buffer.h"
|
||||||
|
|
||||||
|
#define kMachinePtyFg 0x01
|
||||||
|
#define kMachinePtyBg 0x02
|
||||||
|
#define kMachinePtyTrue 0x04
|
||||||
|
#define kMachinePtyBold 0x08
|
||||||
|
#define kMachinePtyFaint 0x10
|
||||||
|
#define kMachinePtyFlip 0x20
|
||||||
|
|
||||||
|
#define kMachinePtyNocursor 0x01
|
||||||
|
|
||||||
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
|
struct MachinePty {
|
||||||
|
uint32_t yn;
|
||||||
|
uint32_t xn;
|
||||||
|
uint32_t y;
|
||||||
|
uint32_t x;
|
||||||
|
uint32_t pr;
|
||||||
|
uint32_t fg;
|
||||||
|
uint32_t bg;
|
||||||
|
uint32_t u8;
|
||||||
|
uint32_t *wcs;
|
||||||
|
uint32_t *fgs;
|
||||||
|
uint32_t *bgs;
|
||||||
|
uint32_t *prs;
|
||||||
|
uint32_t conf;
|
||||||
|
enum MachinePtyState {
|
||||||
|
kMachinePtyAscii,
|
||||||
|
kMachinePtyUtf8,
|
||||||
|
kMachinePtyEsc,
|
||||||
|
kMachinePtyCsi,
|
||||||
|
} state;
|
||||||
|
struct MachinePtyEsc {
|
||||||
|
unsigned i;
|
||||||
|
char s[64];
|
||||||
|
} esc;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MachinePty *MachinePtyNew(unsigned, unsigned) nodiscard;
|
||||||
|
void MachinePtyFree(struct MachinePty *);
|
||||||
|
ssize_t MachinePtyWrite(struct MachinePty *, const void *, size_t);
|
||||||
|
void MachinePtyAppendLine(struct MachinePty *, struct Buffer *, unsigned);
|
||||||
|
|
||||||
|
COSMOPOLITAN_C_END_
|
||||||
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_PTY_H_ */
|
|
@ -17,8 +17,10 @@
|
||||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||||
│ 02110-1301 USA │
|
│ 02110-1301 USA │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
#include "libc/math.h"
|
#include "libc/math.h"
|
||||||
|
#include "libc/mem/mem.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "tool/build/lib/flags.h"
|
#include "tool/build/lib/flags.h"
|
||||||
#include "tool/build/lib/machine.h"
|
#include "tool/build/lib/machine.h"
|
||||||
|
@ -61,8 +63,25 @@ static void ResetSse(struct Machine *m) {
|
||||||
memset(m->xmmtype, 0, sizeof(m->xmmtype));
|
memset(m->xmmtype, 0, sizeof(m->xmmtype));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ResetTlb(struct Machine *m) {
|
||||||
|
m->tlbindex = 0;
|
||||||
|
memset(m->tlb, 0, sizeof(m->tlb));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ResetMem(struct Machine *m) {
|
||||||
|
FreePml4t(m->cr3, -0x800000000000, 0x800000000000, free, munmap);
|
||||||
|
}
|
||||||
|
|
||||||
void ResetCpu(struct Machine *m) {
|
void ResetCpu(struct Machine *m) {
|
||||||
InitMachine(m);
|
m->codevirt = 0;
|
||||||
|
m->codereal = NULL;
|
||||||
|
m->faultaddr = 0;
|
||||||
|
m->stashsize = 0;
|
||||||
|
m->stashaddr = 0;
|
||||||
|
m->writeaddr = 0;
|
||||||
|
m->readaddr = 0;
|
||||||
|
m->writesize = 0;
|
||||||
|
m->readsize = 0;
|
||||||
m->flags = SetFlag(m->flags, FLAGS_DF, false);
|
m->flags = SetFlag(m->flags, FLAGS_DF, false);
|
||||||
m->flags = SetFlag(m->flags, FLAGS_CF, false);
|
m->flags = SetFlag(m->flags, FLAGS_CF, false);
|
||||||
m->flags = SetFlag(m->flags, FLAGS_ZF, false);
|
m->flags = SetFlag(m->flags, FLAGS_ZF, false);
|
||||||
|
@ -73,6 +92,9 @@ void ResetCpu(struct Machine *m) {
|
||||||
m->flags = SetFlag(m->flags, FLAGS_IOPL, 3);
|
m->flags = SetFlag(m->flags, FLAGS_IOPL, 3);
|
||||||
memset(m->reg, 0, sizeof(m->reg));
|
memset(m->reg, 0, sizeof(m->reg));
|
||||||
memset(m->bofram, 0, sizeof(m->bofram));
|
memset(m->bofram, 0, sizeof(m->bofram));
|
||||||
|
memset(&m->freelist, 0, sizeof(m->freelist));
|
||||||
|
ResetTlb(m);
|
||||||
ResetSse(m);
|
ResetSse(m);
|
||||||
ResetFpu(m);
|
ResetFpu(m);
|
||||||
|
ResetMem(m);
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,19 +114,19 @@ union MachineVector {
|
||||||
uint64_t u64[2];
|
uint64_t u64[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
void OpSse(struct Machine *m, enum OpSseKernel kernel) {
|
void OpSse(struct Machine *m, uint32_t rde, enum OpSseKernel kernel) {
|
||||||
int i;
|
int i;
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
union MachineVector x, y, t;
|
union MachineVector x, y, t;
|
||||||
p = GetModrmRegisterXmmPointerRead16(m);
|
p = GetModrmRegisterXmmPointerRead16(m, rde);
|
||||||
if (Osz(m->xedd)) {
|
if (Osz(rde)) {
|
||||||
memcpy(&y, p, 16);
|
memcpy(&y, p, 16);
|
||||||
} else {
|
} else {
|
||||||
memset(&t, 0, 16);
|
memset(&t, 0, 16);
|
||||||
memcpy(&t, p, 8);
|
memcpy(&t, p, 8);
|
||||||
memcpy(&y, &t, 16);
|
memcpy(&y, &t, 16);
|
||||||
}
|
}
|
||||||
memcpy(&x, XmmRexrReg(m), 16);
|
memcpy(&x, XmmRexrReg(m, rde), 16);
|
||||||
switch (kernel) {
|
switch (kernel) {
|
||||||
CASE(kOpSsePsubb, psubb(x.i8, x.i8, y.i8));
|
CASE(kOpSsePsubb, psubb(x.i8, x.i8, y.i8));
|
||||||
CASE(kOpSsePaddb, paddb(x.i8, x.i8, y.i8));
|
CASE(kOpSsePaddb, paddb(x.i8, x.i8, y.i8));
|
||||||
|
@ -204,18 +204,18 @@ void OpSse(struct Machine *m, enum OpSseKernel kernel) {
|
||||||
default:
|
default:
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
if (Osz(m->xedd)) {
|
if (Osz(rde)) {
|
||||||
memcpy(XmmRexrReg(m), &x, 16);
|
memcpy(XmmRexrReg(m, rde), &x, 16);
|
||||||
} else {
|
} else {
|
||||||
memcpy(XmmRexrReg(m), &x, 8);
|
memcpy(XmmRexrReg(m, rde), &x, 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpSseUdqIb(struct Machine *m, enum OpSseUdqIbKernel kernel) {
|
void OpSseUdqIb(struct Machine *m, uint32_t rde, enum OpSseUdqIbKernel kernel) {
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
union MachineVector x;
|
union MachineVector x;
|
||||||
i = m->xedd->op.uimm0;
|
i = m->xedd->op.uimm0;
|
||||||
memcpy(&x, XmmRexbRm(m), 16);
|
memcpy(&x, XmmRexbRm(m, rde), 16);
|
||||||
switch (kernel) {
|
switch (kernel) {
|
||||||
CASE(kOpSseUdqIbPsrlw, (psrlw)(x.u16, x.u16, i));
|
CASE(kOpSseUdqIbPsrlw, (psrlw)(x.u16, x.u16, i));
|
||||||
CASE(kOpSseUdqIbPsraw, (psraw)(x.i16, x.i16, i));
|
CASE(kOpSseUdqIbPsraw, (psraw)(x.i16, x.i16, i));
|
||||||
|
@ -230,26 +230,26 @@ void OpSseUdqIb(struct Machine *m, enum OpSseUdqIbKernel kernel) {
|
||||||
default:
|
default:
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
if (Osz(m->xedd)) {
|
if (Osz(rde)) {
|
||||||
memcpy(XmmRexbRm(m), &x, 16);
|
memcpy(XmmRexbRm(m, rde), &x, 16);
|
||||||
} else {
|
} else {
|
||||||
memcpy(XmmRexbRm(m), &x, 8);
|
memcpy(XmmRexbRm(m, rde), &x, 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OpSsePalignrMmx(struct Machine *m) {
|
static void OpSsePalignrMmx(struct Machine *m, uint32_t rde) {
|
||||||
char t[24];
|
char t[24];
|
||||||
memcpy(t, GetModrmRegisterXmmPointerRead8(m), 8);
|
memcpy(t, GetModrmRegisterXmmPointerRead8(m, rde), 8);
|
||||||
memcpy(t + 8, XmmRexrReg(m), 8);
|
memcpy(t + 8, XmmRexrReg(m, rde), 8);
|
||||||
memset(t + 16, 0, 8);
|
memset(t + 16, 0, 8);
|
||||||
memcpy(XmmRexrReg(m), t + MIN(m->xedd->op.uimm0, 16), 8);
|
memcpy(XmmRexrReg(m, rde), t + MIN(m->xedd->op.uimm0, 16), 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpSsePalignr(struct Machine *m) {
|
void OpSsePalignr(struct Machine *m, uint32_t rde) {
|
||||||
if (Osz(m->xedd)) {
|
if (Osz(rde)) {
|
||||||
palignr(XmmRexrReg(m), XmmRexrReg(m), GetModrmRegisterXmmPointerRead8(m),
|
palignr(XmmRexrReg(m, rde), XmmRexrReg(m, rde),
|
||||||
m->xedd->op.uimm0);
|
GetModrmRegisterXmmPointerRead8(m, rde), m->xedd->op.uimm0);
|
||||||
} else {
|
} else {
|
||||||
OpSsePalignrMmx(m);
|
OpSsePalignrMmx(m, rde);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,9 +93,9 @@ enum OpSseUdqIbKernel {
|
||||||
kOpSseUdqIbPslldq,
|
kOpSseUdqIbPslldq,
|
||||||
};
|
};
|
||||||
|
|
||||||
void OpSse(struct Machine *, enum OpSseKernel);
|
void OpSse(struct Machine *, uint32_t, enum OpSseKernel);
|
||||||
void OpSseUdqIb(struct Machine *, enum OpSseUdqIbKernel);
|
void OpSseUdqIb(struct Machine *, uint32_t, enum OpSseUdqIbKernel);
|
||||||
void OpSsePalignr(struct Machine *);
|
void OpSsePalignr(struct Machine *, uint32_t);
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -76,12 +76,12 @@ void OpCallJvds(struct Machine *m) {
|
||||||
OpCall(m, m->ip + m->xedd->op.disp);
|
OpCall(m, m->ip + m->xedd->op.disp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpCallEq(struct Machine *m) {
|
void OpCallEq(struct Machine *m, uint32_t rde) {
|
||||||
void *p[2];
|
void *p[2];
|
||||||
uint8_t b[8];
|
uint8_t b[8];
|
||||||
OpCall(m, Read64(IsModrmRegister(m->xedd)
|
OpCall(m, Read64(IsModrmRegister(rde)
|
||||||
? RegRexbRm(m)
|
? RegRexbRm(m, rde)
|
||||||
: AccessRam(m, ComputeAddress(m), 8, p, b, true)));
|
: AccessRam(m, ComputeAddress(m, rde), 8, p, b, true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpLeave(struct Machine *m) {
|
void OpLeave(struct Machine *m) {
|
||||||
|
@ -93,10 +93,20 @@ void OpRet(struct Machine *m, uint16_t n) {
|
||||||
m->ip = Pop64(m, n);
|
m->ip = Pop64(m, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PushOsz(struct Machine *m, uint64_t x) {
|
void PushOsz(struct Machine *m, uint32_t rde, uint64_t x) {
|
||||||
if (!Osz(m->xedd)) {
|
if (!Osz(rde)) {
|
||||||
Push64(m, x);
|
Push64(m, x);
|
||||||
} else {
|
} else {
|
||||||
Push16(m, x);
|
Push16(m, x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpBofram(struct Machine *m) {
|
||||||
|
if (m->xedd->op.disp) {
|
||||||
|
m->bofram[0] = m->ip;
|
||||||
|
m->bofram[1] = m->ip + (m->xedd->op.disp & 0xff);
|
||||||
|
} else {
|
||||||
|
m->bofram[0] = 0;
|
||||||
|
m->bofram[1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -11,8 +11,9 @@ uint16_t Pop16(struct Machine *, uint16_t);
|
||||||
void OpCallJvds(struct Machine *);
|
void OpCallJvds(struct Machine *);
|
||||||
void OpRet(struct Machine *, uint16_t);
|
void OpRet(struct Machine *, uint16_t);
|
||||||
void OpLeave(struct Machine *);
|
void OpLeave(struct Machine *);
|
||||||
void PushOsz(struct Machine *, uint64_t);
|
void PushOsz(struct Machine *, uint32_t, uint64_t);
|
||||||
void OpCallEq(struct Machine *);
|
void OpCallEq(struct Machine *, uint32_t);
|
||||||
|
void OpBofram(struct Machine *);
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -65,7 +65,7 @@ static void WriteInt(uint8_t p[8], uint64_t x, unsigned long w) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpString(struct Machine *m, int op) {
|
void OpString(struct Machine *m, uint32_t rde, int op) {
|
||||||
void *p[2];
|
void *p[2];
|
||||||
bool compare;
|
bool compare;
|
||||||
int64_t sgn, v;
|
int64_t sgn, v;
|
||||||
|
@ -73,12 +73,12 @@ void OpString(struct Machine *m, int op) {
|
||||||
unsigned n, lg2;
|
unsigned n, lg2;
|
||||||
uint64_t asz, seg;
|
uint64_t asz, seg;
|
||||||
sgn = GetFlag(m->flags, FLAGS_DF) ? -1 : 1;
|
sgn = GetFlag(m->flags, FLAGS_DF) ? -1 : 1;
|
||||||
asz = Asz(m->xedd) ? 0xffffffff : 0xffffffffffffffff;
|
asz = Asz(rde) ? 0xffffffff : 0xffffffffffffffff;
|
||||||
seg = GetSegment(m);
|
seg = GetSegment(m);
|
||||||
lg2 = RegLog2(m->xedd);
|
lg2 = RegLog2(rde);
|
||||||
n = 1 << lg2;
|
n = 1 << lg2;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (Rep(m->xedd) && !Read64(m->cx)) break;
|
if (Rep(rde) && !Read64(m->cx)) break;
|
||||||
v = 0;
|
v = 0;
|
||||||
*p = NULL;
|
*p = NULL;
|
||||||
compare = false;
|
compare = false;
|
||||||
|
@ -125,16 +125,16 @@ void OpString(struct Machine *m, int op) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
EndStore(m, v, n, p, s[0]);
|
EndStore(m, v, n, p, s[0]);
|
||||||
if (!Rep(m->xedd)) break;
|
if (!Rep(rde)) break;
|
||||||
Write64(m->cx, Read64(m->cx) - 1);
|
Write64(m->cx, Read64(m->cx) - 1);
|
||||||
if (compare) {
|
if (compare) {
|
||||||
if (Rep(m->xedd) == 2 && GetFlag(m->flags, FLAGS_ZF)) break;
|
if (Rep(rde) == 2 && GetFlag(m->flags, FLAGS_ZF)) break;
|
||||||
if (Rep(m->xedd) == 3 && !GetFlag(m->flags, FLAGS_ZF)) break;
|
if (Rep(rde) == 3 && !GetFlag(m->flags, FLAGS_ZF)) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpRepMovsbEnhanced(struct Machine *m) {
|
void OpRepMovsbEnhanced(struct Machine *m, uint32_t rde) {
|
||||||
bool failed;
|
bool failed;
|
||||||
uint8_t *direal, *sireal;
|
uint8_t *direal, *sireal;
|
||||||
unsigned diremain, siremain, i, n;
|
unsigned diremain, siremain, i, n;
|
||||||
|
@ -143,7 +143,7 @@ void OpRepMovsbEnhanced(struct Machine *m) {
|
||||||
failed = false;
|
failed = false;
|
||||||
failaddr = 0;
|
failaddr = 0;
|
||||||
seg = GetSegment(m);
|
seg = GetSegment(m);
|
||||||
asz = Asz(m->xedd) ? 0xffffffff : 0xffffffffffffffff;
|
asz = Asz(rde) ? 0xffffffff : 0xffffffffffffffff;
|
||||||
divirtual = Read64(m->di) & asz;
|
divirtual = Read64(m->di) & asz;
|
||||||
sivirtual = Read64(m->si) & asz;
|
sivirtual = Read64(m->si) & asz;
|
||||||
SetWriteAddr(m, (seg + divirtual) & asz, cx);
|
SetWriteAddr(m, (seg + divirtual) & asz, cx);
|
||||||
|
@ -177,7 +177,7 @@ void OpRepMovsbEnhanced(struct Machine *m) {
|
||||||
if (failed) ThrowSegmentationFault(m, failaddr);
|
if (failed) ThrowSegmentationFault(m, failaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpRepStosbEnhanced(struct Machine *m) {
|
void OpRepStosbEnhanced(struct Machine *m, uint32_t rde) {
|
||||||
bool failed;
|
bool failed;
|
||||||
uint8_t *direal, al;
|
uint8_t *direal, al;
|
||||||
unsigned diremain, i, n;
|
unsigned diremain, i, n;
|
||||||
|
@ -187,7 +187,7 @@ void OpRepStosbEnhanced(struct Machine *m) {
|
||||||
failed = false;
|
failed = false;
|
||||||
al = Read8(m->ax);
|
al = Read8(m->ax);
|
||||||
seg = GetSegment(m);
|
seg = GetSegment(m);
|
||||||
asz = Asz(m->xedd) ? 0xffffffff : 0xffffffffffffffff;
|
asz = Asz(rde) ? 0xffffffff : 0xffffffffffffffff;
|
||||||
divirtual = Read64(m->di) & asz;
|
divirtual = Read64(m->di) & asz;
|
||||||
SetWriteAddr(m, (seg + divirtual) & asz, cx);
|
SetWriteAddr(m, (seg + divirtual) & asz, cx);
|
||||||
do {
|
do {
|
||||||
|
@ -210,18 +210,18 @@ void OpRepStosbEnhanced(struct Machine *m) {
|
||||||
if (failed) ThrowSegmentationFault(m, failaddr);
|
if (failed) ThrowSegmentationFault(m, failaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpMovsb(struct Machine *m) {
|
void OpMovsb(struct Machine *m, uint32_t rde) {
|
||||||
if (Rep(m->xedd) && !GetFlag(m->flags, FLAGS_DF)) {
|
if (Rep(rde) && !GetFlag(m->flags, FLAGS_DF)) {
|
||||||
OpRepMovsbEnhanced(m);
|
OpRepMovsbEnhanced(m, rde);
|
||||||
} else {
|
} else {
|
||||||
OpString(m, STRING_MOVS);
|
OpString(m, rde, STRING_MOVS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpStosb(struct Machine *m) {
|
void OpStosb(struct Machine *m, uint32_t rde) {
|
||||||
if (Rep(m->xedd) && !GetFlag(m->flags, FLAGS_DF)) {
|
if (Rep(rde) && !GetFlag(m->flags, FLAGS_DF)) {
|
||||||
OpRepStosbEnhanced(m);
|
OpRepStosbEnhanced(m, rde);
|
||||||
} else {
|
} else {
|
||||||
OpString(m, STRING_STOS);
|
OpString(m, rde, STRING_STOS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,9 @@
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
void OpString(struct Machine *, int);
|
void OpString(struct Machine *, uint32_t, int);
|
||||||
void OpMovsb(struct Machine *);
|
void OpMovsb(struct Machine *, uint32_t);
|
||||||
void OpStosb(struct Machine *);
|
void OpStosb(struct Machine *, uint32_t);
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/time/struct/timezone.h"
|
#include "libc/time/struct/timezone.h"
|
||||||
#include "libc/time/time.h"
|
#include "libc/time/time.h"
|
||||||
|
#include "libc/x/x.h"
|
||||||
#include "tool/build/lib/case.h"
|
#include "tool/build/lib/case.h"
|
||||||
#include "tool/build/lib/endian.h"
|
#include "tool/build/lib/endian.h"
|
||||||
#include "tool/build/lib/machine.h"
|
#include "tool/build/lib/machine.h"
|
||||||
|
@ -65,6 +66,12 @@
|
||||||
#define P(x) ((x) ? PNN(x) : 0)
|
#define P(x) ((x) ? PNN(x) : 0)
|
||||||
#define ASSIGN(D, S) memcpy(&D, &S, MIN(sizeof(S), sizeof(D)))
|
#define ASSIGN(D, S) memcpy(&D, &S, MIN(sizeof(S), sizeof(D)))
|
||||||
|
|
||||||
|
static const struct MachineFdCb kMachineFdCbHost = {
|
||||||
|
.close = close,
|
||||||
|
.read = read,
|
||||||
|
.write = write,
|
||||||
|
};
|
||||||
|
|
||||||
static int XlatSignal(int sig) {
|
static int XlatSignal(int sig) {
|
||||||
switch (sig) {
|
switch (sig) {
|
||||||
XLAT(1, SIGHUP);
|
XLAT(1, SIGHUP);
|
||||||
|
@ -188,9 +195,15 @@ static int XlatTcp(int x) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int XlatAfd(int x) {
|
static int XlatFd(struct Machine *m, int fd) {
|
||||||
if (x == AT_FDCWD_LINUX) x = AT_FDCWD;
|
if (!(0 <= fd && fd < m->fds.i)) return ebadf();
|
||||||
return x;
|
if (!m->fds.p[fd].cb) return ebadf();
|
||||||
|
return m->fds.p[fd].fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int XlatAfd(struct Machine *m, int fd) {
|
||||||
|
if (fd == AT_FDCWD_LINUX) return AT_FDCWD;
|
||||||
|
return XlatFd(m, fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int XlatAtf(int x) {
|
static int XlatAtf(int x) {
|
||||||
|
@ -264,6 +277,7 @@ static int64_t OpMmap(struct Machine *m, int64_t virt, size_t size, int prot,
|
||||||
int flags, int fd, int64_t off) {
|
int flags, int fd, int64_t off) {
|
||||||
void *real;
|
void *real;
|
||||||
flags = XlatMapFlags(flags);
|
flags = XlatMapFlags(flags);
|
||||||
|
if (fd != -1 && (fd = XlatFd(m, fd)) == -1) return -1;
|
||||||
real = mmap(NULL, size, prot, flags & ~MAP_FIXED, fd, off);
|
real = mmap(NULL, size, prot, flags & ~MAP_FIXED, fd, off);
|
||||||
if (real == MAP_FAILED) return -1;
|
if (real == MAP_FAILED) return -1;
|
||||||
if (!(flags & MAP_FIXED)) {
|
if (!(flags & MAP_FIXED)) {
|
||||||
|
@ -297,19 +311,70 @@ static void *GetDirectBuf(struct Machine *m, int64_t addr, size_t *size) {
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int OpClose(struct Machine *m, int fd) {
|
||||||
|
int rc;
|
||||||
|
struct FdClosed *closed;
|
||||||
|
if (!(0 <= fd && fd < m->fds.i)) return ebadf();
|
||||||
|
if (!m->fds.p[fd].cb) return ebadf();
|
||||||
|
rc = m->fds.p[fd].cb->close(m->fds.p[fd].fd);
|
||||||
|
MachineFdRemove(&m->fds, fd);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int OpOpenat(struct Machine *m, int dirfd, int64_t path, int flags,
|
||||||
|
int mode) {
|
||||||
|
int fd, i;
|
||||||
|
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) {
|
||||||
|
m->fds.p[i].cb = &kMachineFdCbHost;
|
||||||
|
m->fds.p[i].fd = fd;
|
||||||
|
fd = i;
|
||||||
|
} else {
|
||||||
|
MachineFdRemove(&m->fds, i);
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int OpPipe(struct Machine *m, int64_t pipefds_addr) {
|
||||||
|
void *p[2];
|
||||||
|
uint8_t b[8];
|
||||||
|
int rc, i, j, *pipefds;
|
||||||
|
if ((i = MachineFdAdd(&m->fds)) == -1) return -1;
|
||||||
|
if ((j = MachineFdAdd(&m->fds)) == -1) return -1;
|
||||||
|
if ((rc = pipe((pipefds = BeginStoreNp(m, pipefds_addr, 8, p, b)))) != -1) {
|
||||||
|
EndStoreNp(m, pipefds_addr, 8, p, b);
|
||||||
|
m->fds.p[i].cb = &kMachineFdCbHost;
|
||||||
|
m->fds.p[i].fd = pipefds[0];
|
||||||
|
m->fds.p[j].cb = &kMachineFdCbHost;
|
||||||
|
m->fds.p[j].fd = pipefds[1];
|
||||||
|
} else {
|
||||||
|
MachineFdRemove(&m->fds, i);
|
||||||
|
MachineFdRemove(&m->fds, j);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t OpRead(struct Machine *m, int fd, int64_t addr, size_t size) {
|
static ssize_t OpRead(struct Machine *m, int fd, int64_t addr, size_t size) {
|
||||||
void *data;
|
void *data;
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
|
if (!(0 <= fd && fd < m->fds.i) || !m->fds.p[fd].cb) return ebadf();
|
||||||
if ((data = GetDirectBuf(m, addr, &size)) == MAP_FAILED) return efault();
|
if ((data = GetDirectBuf(m, addr, &size)) == MAP_FAILED) return efault();
|
||||||
if ((rc = read(fd, data, size)) != -1) SetWriteAddr(m, addr, rc);
|
if ((rc = m->fds.p[fd].cb->read(m->fds.p[fd].fd, data, size)) != -1) {
|
||||||
|
SetWriteAddr(m, addr, rc);
|
||||||
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t OpWrite(struct Machine *m, int fd, int64_t addr, size_t size) {
|
static ssize_t OpWrite(struct Machine *m, int fd, int64_t addr, size_t size) {
|
||||||
void *data;
|
void *data;
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
|
if (!(0 <= fd && fd < m->fds.i) || !m->fds.p[fd].cb) return ebadf();
|
||||||
if ((data = GetDirectBuf(m, addr, &size)) == MAP_FAILED) return efault();
|
if ((data = GetDirectBuf(m, addr, &size)) == MAP_FAILED) return efault();
|
||||||
if ((rc = write(fd, data, size)) != -1) SetReadAddr(m, addr, size);
|
if ((rc = m->fds.p[fd].cb->write(m->fds.p[fd].fd, data, size)) != -1) {
|
||||||
|
SetReadAddr(m, addr, size);
|
||||||
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,6 +382,7 @@ static ssize_t OpPread(struct Machine *m, int fd, int64_t addr, size_t size,
|
||||||
int64_t offset) {
|
int64_t offset) {
|
||||||
void *data;
|
void *data;
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
|
if ((fd = XlatFd(m, fd)) == -1) return -1;
|
||||||
if ((data = GetDirectBuf(m, addr, &size)) == MAP_FAILED) return efault();
|
if ((data = GetDirectBuf(m, addr, &size)) == MAP_FAILED) return efault();
|
||||||
if ((rc = pread(fd, data, size, offset)) != -1) SetWriteAddr(m, addr, rc);
|
if ((rc = pread(fd, data, size, offset)) != -1) SetWriteAddr(m, addr, rc);
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -326,20 +392,31 @@ static ssize_t OpPwrite(struct Machine *m, int fd, int64_t addr, size_t size,
|
||||||
int64_t offset) {
|
int64_t offset) {
|
||||||
void *data;
|
void *data;
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
|
if ((fd = XlatFd(m, fd)) == -1) return -1;
|
||||||
if ((data = GetDirectBuf(m, addr, &size)) == MAP_FAILED) return efault();
|
if ((data = GetDirectBuf(m, addr, &size)) == MAP_FAILED) return efault();
|
||||||
if ((rc = pwrite(fd, data, size, offset)) != -1) SetReadAddr(m, addr, size);
|
if ((rc = pwrite(fd, data, size, offset)) != -1) SetReadAddr(m, addr, size);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int OpFaccessat(struct Machine *m, int dirfd, int64_t path, int mode,
|
||||||
|
int flags) {
|
||||||
|
flags = XlatAtf(flags);
|
||||||
|
mode = XlatAccess(mode);
|
||||||
|
if ((dirfd = XlatAfd(m, dirfd)) == -1) return -1;
|
||||||
|
return faccessat(dirfd, LoadStr(m, path), mode, flags);
|
||||||
|
}
|
||||||
|
|
||||||
static int OpFstatat(struct Machine *m, int dirfd, int64_t path, int64_t st,
|
static int OpFstatat(struct Machine *m, int dirfd, int64_t path, int64_t st,
|
||||||
int flags) {
|
int flags) {
|
||||||
int rc;
|
int rc;
|
||||||
void *stp[2];
|
void *stp[2];
|
||||||
uint8_t *stbuf;
|
uint8_t *stbuf;
|
||||||
|
flags = XlatAtf(flags);
|
||||||
|
if ((dirfd = XlatAfd(m, dirfd)) == -1) return -1;
|
||||||
if (!(stbuf = malloc(sizeof(struct stat)))) return enomem();
|
if (!(stbuf = malloc(sizeof(struct stat)))) return enomem();
|
||||||
if ((rc = fstatat(XlatAfd(dirfd), LoadStr(m, path),
|
if ((rc = fstatat(dirfd, LoadStr(m, path),
|
||||||
BeginStoreNp(m, st, sizeof(stbuf), stp, stbuf),
|
BeginStoreNp(m, st, sizeof(stbuf), stp, stbuf), flags)) !=
|
||||||
XlatAtf(flags))) != -1) {
|
-1) {
|
||||||
EndStoreNp(m, st, sizeof(stbuf), stp, stbuf);
|
EndStoreNp(m, st, sizeof(stbuf), stp, stbuf);
|
||||||
}
|
}
|
||||||
free(stbuf);
|
free(stbuf);
|
||||||
|
@ -350,6 +427,7 @@ static int OpFstat(struct Machine *m, int fd, int64_t st) {
|
||||||
int rc;
|
int rc;
|
||||||
void *stp[2];
|
void *stp[2];
|
||||||
uint8_t *stbuf;
|
uint8_t *stbuf;
|
||||||
|
if ((fd = XlatFd(m, fd)) == -1) return -1;
|
||||||
if (!(stbuf = malloc(sizeof(struct stat)))) return enomem();
|
if (!(stbuf = malloc(sizeof(struct stat)))) return enomem();
|
||||||
if ((rc = fstat(fd, BeginStoreNp(m, st, sizeof(stbuf), stp, stbuf))) != -1) {
|
if ((rc = fstat(fd, BeginStoreNp(m, st, sizeof(stbuf), stp, stbuf))) != -1) {
|
||||||
EndStoreNp(m, st, sizeof(stbuf), stp, stbuf);
|
EndStoreNp(m, st, sizeof(stbuf), stp, stbuf);
|
||||||
|
@ -358,17 +436,6 @@ static int OpFstat(struct Machine *m, int fd, int64_t st) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int OpOpenat(struct Machine *m, int dirfd, int64_t path, int flags,
|
|
||||||
int mode) {
|
|
||||||
return openat(XlatAfd(dirfd), LoadStr(m, path), XlatOpenFlags(flags), mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int OpFaccessat(struct Machine *m, int dirfd, int64_t path, int mode,
|
|
||||||
int flags) {
|
|
||||||
return faccessat(XlatAfd(dirfd), LoadStr(m, path), XlatAccess(mode),
|
|
||||||
XlatAtf(flags));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int OpChdir(struct Machine *m, int64_t path) {
|
static int OpChdir(struct Machine *m, int64_t path) {
|
||||||
return chdir(LoadStr(m, path));
|
return chdir(LoadStr(m, path));
|
||||||
}
|
}
|
||||||
|
@ -449,16 +516,6 @@ static int OpSigaction(struct Machine *m, int sig, int64_t act, int64_t old) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int OpPipe(struct Machine *m, int64_t pipefds_addr) {
|
|
||||||
int rc;
|
|
||||||
void *p[2];
|
|
||||||
uint8_t b[8];
|
|
||||||
if ((rc = pipe(BeginStoreNp(m, pipefds_addr, 8, p, b))) != -1) {
|
|
||||||
EndStoreNp(m, pipefds_addr, 8, p, b);
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int OpNanosleep(struct Machine *m, int64_t req, int64_t rem) {
|
static int OpNanosleep(struct Machine *m, int64_t req, int64_t rem) {
|
||||||
int rc;
|
int rc;
|
||||||
void *p[2];
|
void *p[2];
|
||||||
|
@ -536,7 +593,7 @@ void OpSyscall(struct Machine *m) {
|
||||||
SYSCALL(0x000, OpRead(m, di, si, dx));
|
SYSCALL(0x000, OpRead(m, di, si, dx));
|
||||||
SYSCALL(0x001, OpWrite(m, di, si, dx));
|
SYSCALL(0x001, OpWrite(m, di, si, dx));
|
||||||
SYSCALL(0x002, DoOpen(m, di, si, dx));
|
SYSCALL(0x002, DoOpen(m, di, si, dx));
|
||||||
SYSCALL(0x003, close(di));
|
SYSCALL(0x003, OpClose(m, di));
|
||||||
SYSCALL(0x004, DoStat(m, di, si));
|
SYSCALL(0x004, DoStat(m, di, si));
|
||||||
SYSCALL(0x005, OpFstat(m, di, si));
|
SYSCALL(0x005, OpFstat(m, di, si));
|
||||||
SYSCALL(0x006, DoLstat(m, di, si));
|
SYSCALL(0x006, DoLstat(m, di, si));
|
||||||
|
@ -624,16 +681,16 @@ void OpSyscall(struct Machine *m) {
|
||||||
SYSCALL(0x0DD, fadvise(di, si, dx, r0));
|
SYSCALL(0x0DD, fadvise(di, si, dx, r0));
|
||||||
SYSCALL(0x0E4, OpClockGettime(m, di, si));
|
SYSCALL(0x0E4, OpClockGettime(m, di, si));
|
||||||
SYSCALL(0x101, OpOpenat(m, di, si, dx, r0));
|
SYSCALL(0x101, OpOpenat(m, di, si, dx, r0));
|
||||||
SYSCALL(0x102, mkdirat(XlatAfd(di), P(si), dx));
|
SYSCALL(0x102, mkdirat(XlatAfd(m, di), P(si), dx));
|
||||||
SYSCALL(0x104, fchownat(XlatAfd(di), P(si), dx, r0, XlatAtf(r8)));
|
SYSCALL(0x104, fchownat(XlatAfd(m, di), P(si), dx, r0, XlatAtf(r8)));
|
||||||
SYSCALL(0x105, futimesat(XlatAfd(di), P(si), P(dx)));
|
SYSCALL(0x105, futimesat(XlatAfd(m, di), P(si), P(dx)));
|
||||||
SYSCALL(0x106, OpFstatat(m, di, si, dx, r0));
|
SYSCALL(0x106, OpFstatat(m, di, si, dx, r0));
|
||||||
SYSCALL(0x107, unlinkat(XlatAfd(di), P(si), XlatAtf(dx)));
|
SYSCALL(0x107, unlinkat(XlatAfd(m, di), P(si), XlatAtf(dx)));
|
||||||
SYSCALL(0x108, renameat(XlatAfd(di), P(si), XlatAfd(dx), P(r0)));
|
SYSCALL(0x108, renameat(XlatAfd(m, di), P(si), XlatAfd(m, dx), P(r0)));
|
||||||
SYSCALL(0x10D, OpFaccessat(m, di, si, dx, r0));
|
SYSCALL(0x10D, OpFaccessat(m, di, si, dx, r0));
|
||||||
SYSCALL(0x113, splice(di, P(si), dx, P(r0), r8, XlatAtf(r9)));
|
SYSCALL(0x113, splice(di, P(si), dx, P(r0), r8, XlatAtf(r9)));
|
||||||
SYSCALL(0x115, sync_file_range(di, si, dx, XlatAtf(r0)));
|
SYSCALL(0x115, sync_file_range(di, si, dx, XlatAtf(r0)));
|
||||||
SYSCALL(0x118, utimensat(XlatAfd(di), P(si), P(dx), XlatAtf(r0)));
|
SYSCALL(0x118, utimensat(XlatAfd(m, di), P(si), P(dx), XlatAtf(r0)));
|
||||||
SYSCALL(0x177, vmsplice(di, P(si), dx, r0));
|
SYSCALL(0x177, vmsplice(di, P(si), dx, r0));
|
||||||
CASE(0xE7, HaltMachine(m, di | 0x100));
|
CASE(0xE7, HaltMachine(m, di | 0x100));
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
enum MachineStatus;
|
|
||||||
|
|
||||||
void OpSyscall(struct Machine *);
|
void OpSyscall(struct Machine *);
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
|
|
|
@ -17,55 +17,24 @@
|
||||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||||
│ 02110-1301 USA │
|
│ 02110-1301 USA │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "ape/lib/pc.h"
|
#include "libc/nexgen32e/rdtsc.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/sysv/consts/clock.h"
|
||||||
#include "libc/nexgen32e/nexgen32e.h"
|
#include "libc/time/time.h"
|
||||||
#include "libc/nt/struct/context.h"
|
#include "tool/build/lib/endian.h"
|
||||||
#include "libc/nt/thunk/msabi.h"
|
#include "tool/build/lib/time.h"
|
||||||
|
|
||||||
#define kNtContextXstate 0x00100040
|
|
||||||
#define kNtXstateAvx 2
|
|
||||||
#define kNtXstateMaskAvx (1ull << kNtXstateAvx)
|
|
||||||
|
|
||||||
static void EnableAvx(void) {
|
|
||||||
asm volatile("mov\t%%cr4,%%rax\n\t"
|
|
||||||
"or\t%0,%%rax\n\t"
|
|
||||||
"mov\t%%rax,%%cr4\n\t"
|
|
||||||
"xor\t%%ecx,%%ecx\n\t"
|
|
||||||
"xgetbv\n\t"
|
|
||||||
"or\t%1,%%eax\n\t"
|
|
||||||
"xsetbv"
|
|
||||||
: /* no outputs */
|
|
||||||
: "i"(CR4_OSXSAVE), "i"(XCR0_X87 | XCR0_SSE | XCR0_AVX)
|
|
||||||
: "rax", "rcx", "rdx", "memory", "cc");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void EnableAvxOnWindows(void) {
|
|
||||||
/* typedef uint64_t (*getenabledxstatefeatures_f)(void) __msabi; */
|
|
||||||
/* typedef bool32 (*initializecontext_f)(void *buffer, uint32_t flags, */
|
|
||||||
/* struct NtContext **out_context, */
|
|
||||||
/* uint32_t *inout_buffersize) __msabi;
|
|
||||||
*/
|
|
||||||
/* typedef bool32 (*getxstatefeaturesmask_f)(struct NtContext * context, */
|
|
||||||
/* uint64_t * out_featuremask)
|
|
||||||
* __msabi; */
|
|
||||||
/* typedef bool32 (*setxstatefeaturesmask_f)(struct NtContext * context, */
|
|
||||||
/* uint64_t featuremask) __msabi; */
|
|
||||||
/* getenabledxstatefeatures_f GetEnabledXStateFeatures; */
|
|
||||||
/* initializecontext_f InitializeContext; */
|
|
||||||
/* getxstatefeaturesmask_f GetXStateFeaturesMask; */
|
|
||||||
/* setxstatefeaturesmask_f SetXStateFeaturesMask; */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requests authorization from operating system to do 256-bit math.
|
* I am the timelorde.
|
||||||
* @assume avx cpuid check performed by caller
|
|
||||||
*/
|
*/
|
||||||
int _init_enableavx(void) {
|
void OpRdtsc(struct Machine *m) {
|
||||||
if (IsMetal()) {
|
uint64_t c;
|
||||||
EnableAvx();
|
#ifdef __x86_64__
|
||||||
} else if (IsWindows()) {
|
c = rdtsc();
|
||||||
EnableAvxOnWindows();
|
#else
|
||||||
}
|
struct timespec ts;
|
||||||
return 0;
|
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);
|
||||||
}
|
}
|
11
tool/build/lib/time.h
Normal file
11
tool/build/lib/time.h
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_TIME_H_
|
||||||
|
#define COSMOPOLITAN_TOOL_BUILD_LIB_TIME_H_
|
||||||
|
#include "tool/build/lib/machine.h"
|
||||||
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
|
void OpRdtsc(struct Machine *);
|
||||||
|
|
||||||
|
COSMOPOLITAN_C_END_
|
||||||
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_TIME_H_ */
|
|
@ -36,6 +36,7 @@ int main(int argc, char *argv[]) {
|
||||||
fputs(" PROG [ARGS...]\n", stderr);
|
fputs(" PROG [ARGS...]\n", stderr);
|
||||||
return EX_USAGE;
|
return EX_USAGE;
|
||||||
}
|
}
|
||||||
|
InitMachine(m);
|
||||||
LoadProgram(m, argv[1], argv + 2, environ, &elf);
|
LoadProgram(m, argv[1], argv + 2, environ, &elf);
|
||||||
if (!(rc = setjmp(m->onhalt))) {
|
if (!(rc = setjmp(m->onhalt))) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
|
@ -134,6 +134,7 @@
|
||||||
"textexit"
|
"textexit"
|
||||||
"externinline"
|
"externinline"
|
||||||
"noinline"
|
"noinline"
|
||||||
|
"noclone"
|
||||||
"donothing"
|
"donothing"
|
||||||
"byanymeansnecessary"
|
"byanymeansnecessary"
|
||||||
"threadlocal"
|
"threadlocal"
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
#ifndef COSMOPOLITAN_TOOL_VIZ_LIB_ANSITRINSICS_H_
|
|
||||||
#define COSMOPOLITAN_TOOL_VIZ_LIB_ANSITRINSICS_H_
|
|
||||||
#include "libc/limits.h"
|
|
||||||
#include "libc/macros.h"
|
|
||||||
#include "libc/str/str.h"
|
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
|
||||||
COSMOPOLITAN_C_START_
|
|
||||||
|
|
||||||
static unsigned char avgb(unsigned char a, unsigned char b) {
|
|
||||||
return (a + b + 1) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pavgb(const unsigned char *restrict c,
|
|
||||||
const unsigned char *restrict b, unsigned char *restrict a) {
|
|
||||||
unsigned i;
|
|
||||||
for (i = 0; i < 16; ++i) a[i] = avgb(c[i], b[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vpavgb(const unsigned char *restrict c,
|
|
||||||
const unsigned char *restrict b, unsigned char *restrict a) {
|
|
||||||
unsigned i;
|
|
||||||
for (i = 0; i < 32; ++i) a[i] = avgb(c[i], b[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void paddsw(const short c[8], const short b[8], short a[8]) {
|
|
||||||
size_t j;
|
|
||||||
for (j = 0; j < 8; ++j) {
|
|
||||||
a[j] = MIN(SHRT_MAX, MAX(SHRT_MIN, b[j] + c[j]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vpaddsw(const short c[16], const short b[16], short a[16]) {
|
|
||||||
size_t j;
|
|
||||||
for (j = 0; j < 16; ++j) {
|
|
||||||
a[j] = MAX(SHRT_MIN, MIN(SHRT_MAX, b[j] + c[j]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
|
||||||
#endif /* COSMOPOLITAN_TOOL_VIZ_LIB_ANSITRINSICS_H_ */
|
|
|
@ -1,12 +0,0 @@
|
||||||
#ifndef COSMOPOLITAN_TOOL_VIZ_LIB_SCALE_H_
|
|
||||||
#define COSMOPOLITAN_TOOL_VIZ_LIB_SCALE_H_
|
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
|
||||||
COSMOPOLITAN_C_START_
|
|
||||||
|
|
||||||
void *Scale(long dcw, long dyw, long dxw, float dst[dcw][dyw][dxw], long scw,
|
|
||||||
long syw, long sxw, const float src[scw][syw][sxw], long, long,
|
|
||||||
long, long, long, long, double, double, double, double);
|
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
|
||||||
#endif /* COSMOPOLITAN_TOOL_VIZ_LIB_SCALE_H_ */
|
|
|
@ -49,7 +49,6 @@
|
||||||
#include "third_party/avir/lanczos.h"
|
#include "third_party/avir/lanczos.h"
|
||||||
#include "tool/viz/lib/graphic.h"
|
#include "tool/viz/lib/graphic.h"
|
||||||
#include "tool/viz/lib/knobs.h"
|
#include "tool/viz/lib/knobs.h"
|
||||||
#include "tool/viz/lib/scale.h"
|
|
||||||
#include "tool/viz/lib/ycbcr.h"
|
#include "tool/viz/lib/ycbcr.h"
|
||||||
|
|
||||||
#define M 15
|
#define M 15
|
||||||
|
|
|
@ -48,7 +48,6 @@
|
||||||
#include "third_party/stb/stb_image.h"
|
#include "third_party/stb/stb_image.h"
|
||||||
#include "tool/viz/lib/bilinearscale.h"
|
#include "tool/viz/lib/bilinearscale.h"
|
||||||
#include "tool/viz/lib/graphic.h"
|
#include "tool/viz/lib/graphic.h"
|
||||||
#include "tool/viz/lib/scale.h"
|
|
||||||
|
|
||||||
#define LONG long
|
#define LONG long
|
||||||
#define CHAR char
|
#define CHAR char
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||||
│ 02110-1301 USA │
|
│ 02110-1301 USA │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "dsp/core/half.h"
|
||||||
#include "dsp/core/twixt8.h"
|
#include "dsp/core/twixt8.h"
|
||||||
#include "dsp/scale/scale.h"
|
#include "dsp/scale/scale.h"
|
||||||
#include "dsp/tty/quant.h"
|
#include "dsp/tty/quant.h"
|
||||||
|
@ -59,6 +60,7 @@ static struct Flags {
|
||||||
bool unsharp;
|
bool unsharp;
|
||||||
bool dither;
|
bool dither;
|
||||||
bool ruler;
|
bool ruler;
|
||||||
|
bool trailingnewline;
|
||||||
long half;
|
long half;
|
||||||
bool full;
|
bool full;
|
||||||
long width;
|
long width;
|
||||||
|
@ -129,9 +131,11 @@ static void GetOpts(int *argc, char *argv[]) {
|
||||||
g_flags.unsharp = true;
|
g_flags.unsharp = true;
|
||||||
break;
|
break;
|
||||||
case 'w':
|
case 'w':
|
||||||
|
g_flags.trailingnewline = true;
|
||||||
g_flags.width = ParseNumberOption(optarg);
|
g_flags.width = ParseNumberOption(optarg);
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
|
g_flags.trailingnewline = true;
|
||||||
g_flags.height = ParseNumberOption(optarg);
|
g_flags.height = ParseNumberOption(optarg);
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
|
@ -202,19 +206,19 @@ static unsigned char OutOfBoundsBackground(unsigned y, unsigned x) {
|
||||||
static void PrintRulerRight(long yn, long xn, long y, long x,
|
static void PrintRulerRight(long yn, long xn, long y, long x,
|
||||||
bool *inout_didhalfy) {
|
bool *inout_didhalfy) {
|
||||||
if (y == 0) {
|
if (y == 0) {
|
||||||
printf("\e[0m‾0");
|
printf("‾0");
|
||||||
} else if (yn / 2 <= y && y <= yn / 2 + 1 && !*inout_didhalfy) {
|
} else if (yn / 2 <= y && y <= yn / 2 + 1 && !*inout_didhalfy) {
|
||||||
printf("\e[0m‾%s%s", "yn/2", y % 2 ? "+1" : "");
|
printf("‾%s%s", "yn/2", y % 2 ? "+1" : "");
|
||||||
*inout_didhalfy = true;
|
*inout_didhalfy = true;
|
||||||
} else if (y + 1 == yn / 2 && !*inout_didhalfy) {
|
} else if (y + 1 == yn / 2 && !*inout_didhalfy) {
|
||||||
printf("\e[0m⎯yn/2");
|
printf("⎯yn/2");
|
||||||
*inout_didhalfy = true;
|
*inout_didhalfy = true;
|
||||||
} else if (y + 1 == yn) {
|
} else if (y + 1 == yn) {
|
||||||
printf("\e[0m⎯yn");
|
printf("⎯yn");
|
||||||
} else if (y + 2 == yn) {
|
} else if (y + 2 == yn) {
|
||||||
printf("\e[0m_yn");
|
printf("_yn");
|
||||||
} else if (!(y % 10)) {
|
} else if (!(y % 10)) {
|
||||||
printf("\e[0m‾%,u", y);
|
printf("‾%,u", y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,11 +247,12 @@ static void PrintImageImpl(long syn, long sxn, unsigned char RGB[3][syn][sxn],
|
||||||
b[2], dy > 1 ? u'▄' : u'▐');
|
b[2], dy > 1 ? u'▄' : u'▐');
|
||||||
didfirstx = true;
|
didfirstx = true;
|
||||||
}
|
}
|
||||||
|
printf("\e[0m");
|
||||||
if (g_flags.ruler) {
|
if (g_flags.ruler) {
|
||||||
PrintRulerRight(yn, xn, y, x, &didhalfy);
|
PrintRulerRight(yn, xn, y, x, &didhalfy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("\e[0m\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintImage(long syn, long sxn, unsigned char RGB[3][syn][sxn],
|
static void PrintImage(long syn, long sxn, unsigned char RGB[3][syn][sxn],
|
||||||
|
@ -334,7 +339,9 @@ static void PrintImageSerious(long yn, long xn, unsigned char RGB[3][yn][xn],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p = ttyraster(vt, (void *)TTY, yn, xn, bg, fg);
|
p = ttyraster(vt, (void *)TTY, yn, xn, bg, fg);
|
||||||
p = stpcpy(p, "\r\e[0m");
|
*p++ = '\r';
|
||||||
|
if (g_flags.trailingnewline) *p++ = '\n';
|
||||||
|
p = stpcpy(p, "\e[0m");
|
||||||
ttywrite(STDOUT_FILENO, vt, p - vt);
|
ttywrite(STDOUT_FILENO, vt, p - vt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue