diff --git a/dsp/tty/tty.h b/dsp/tty/tty.h index be4f53ac..73e110af 100644 --- a/dsp/tty/tty.h +++ b/dsp/tty/tty.h @@ -39,7 +39,7 @@ int ttyrestorecursor(int); int ttyenablealtbuf(int); int ttydisablealtbuf(int); 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 ttyident(struct TtyIdent *, int, int); void ttyidentclear(struct TtyIdent *); diff --git a/dsp/tty/ttyraw.c b/dsp/tty/ttyraw.c index e6cbfa09..025aed48 100644 --- a/dsp/tty/ttyraw.c +++ b/dsp/tty/ttyraw.c @@ -101,7 +101,9 @@ static relegated void ttyraw_onsig(int sig, struct siginfo *info, if (g_ttyraw.sigs[i] == sig) { if (g_ttyraw.next[i] != SIG_IGN) { if (g_ttyraw.next[i] != SIG_DFL) { - g_ttyraw.next[i](sig, info, ctx); + if (g_ttyraw.next[i]) { + g_ttyraw.next[i](sig, info, ctx); + } } else if (sig != SIGCONT) { _Exit(128 + sig); } diff --git a/dsp/tty/write.c b/dsp/tty/write.c index 7e356ddb..ee5f24ab 100644 --- a/dsp/tty/write.c +++ b/dsp/tty/write.c @@ -35,7 +35,7 @@ * * @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; ssize_t rc; size_t wrote, n; diff --git a/examples/hello2.c b/examples/hello2.c index d1fc18fe..6c8c8504 100644 --- a/examples/hello2.c +++ b/examples/hello2.c @@ -7,11 +7,11 @@ │ • http://creativecommons.org/publicdomain/zero/1.0/ │ ╚─────────────────────────────────────────────────────────────────*/ #endif -#include "libc/str/str.h" #include "libc/calls/calls.h" +#include "libc/str/str.h" #include "libc/sysv/consts/fileno.h" -#define kMessage "hello world\r\n" +#define kMessage "hello \e[1mworld\e[0m\r\n" int main() { /* diff --git a/libc/fmt/unbing.c b/libc/fmt/unbing.c index c1b16d0a..319628a4 100644 --- a/libc/fmt/unbing.c +++ b/libc/fmt/unbing.c @@ -18,42 +18,36 @@ │ 02110-1301 USA │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/alg/alg.h" -#include "libc/fmt/bing.h" -#include "libc/log/log.h" +#include "libc/macros.h" +#include "libc/nexgen32e/nexgen32e.h" #include "libc/str/str.h" -#define ALTCOUNT 21 - -static const struct Cp437Multimappings { - unsigned char b[ALTCOUNT]; - char16_t c[ALTCOUNT]; -} kCp437iMultimappings = { -#define ALT(I, C, B) .c[I] = C, .b[I] = B - ALT(0, u'\n', '\n'), - ALT(1, u'\r', '\r'), - ALT(2, u'?', '?'), /* TRIGRAPH */ - ALT(3, u'\'', '\''), /* CHARACTER LITERAL */ - ALT(4, u'\"', '\"'), /* STRING LITERAL */ - ALT(5, u'\\', '\\'), /* ESCAPE LITERAL */ - ALT(6, u'∅', '\0'), /* EMPTY SET */ - ALT(7, u'␀', '\0'), /* SYMBOL FOR NULL [sic] */ - ALT(7, 0x20A7, 0x9E), /* PESETA SIGN */ - ALT(8, u'Π' /* 03A0: GREEK CAPITAL LETTER PI */, 0xE3), - ALT(9, u'∏' /* 220F: N-ARY PRODUCT */, 0xE3), - ALT(10, u'∑' /* 2211: N-ARY SUMMATION */, 0xE4), - ALT(11, u'µ' /* 03BC: MICRO SIGN */, 0xE6), - ALT(12, u'Ω' /* 2126: OHM SIGN */, 0xEA), - ALT(13, u'∂' /* 2202: PARTIAL DIFFERENTIAL */, 0xEB), - 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 const int kCp437iMultimappings[] = { + u'\n' << 8 | '\n', // NEWLINE + u'\r' << 8 | '\r', // CARRIAGE RETURN + u'?' << 8 | '?', // TRIGRAPH + u'\'' << 8 | '\'', // CHARACTER LITERAL + u'\"' << 8 | '\"', // STRING LITERAL + u'\\' << 8 | '\\', // ESCAPE LITERAL + u'∅' << 8 | '\0', // EMPTY SET + u'␀' << 8 | '\0', // SYMBOL FOR NULL [sic] + 0x20A7 << 8 | 0x9E, // PESETA SIGN + u'Π' << 8 | 0xE3, // GREEK CAPITAL LETTER PI + u'∏' << 8 | 0xE3, // N-ARY PRODUCT + u'∑' << 8 | 0xE4, // N-ARY SUMMATION + u'µ' << 8 | 0xE6, // MICRO SIGN + u'Ω' << 8 | 0xEA, // OHM SIGN + u'∂' << 8 | 0xEB, // PARTIAL DIFFERENTIAL + u'ϕ' << 8 | 0xED, // PHI SMALL (CLOSED FORM) + u'ε' << 8 | 0xEE, // LATIN SMALL LETTER EPSILON + u'∊' << 8 | 0xEE, // SMALL ELEMENT OF + u'∈' << 8 | 0xEE, // ELEMENT-OF SIGN + u'β' << 8 | 0xE1, // GREEK SMALL BETA + u'ſ' << 8 | 0xF4, // LATIN SMALL LETTER LONG S }; +static int g_cp437i[256 + ARRAYLEN(kCp437iMultimappings)]; + /** * Turns CP437 unicode glyph into its binary representation. * @@ -62,15 +56,24 @@ static const struct Cp437Multimappings { * @see bing() */ int unbing(int c) { - int i; - for (i = 0; i < 256; ++i) { - if (c == kCp437[i]) { - return i; - } + int i, m, l, r; + static bool once; + if (!once) { + 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; } - for (i = 0; i < ALTCOUNT; ++i) { - if (c == kCp437iMultimappings.c[i]) { - return kCp437iMultimappings.b[i]; + l = 0; + r = ARRAYLEN(g_cp437i) - 1; + while (l <= r) { + 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; diff --git a/libc/integral/c.inc b/libc/integral/c.inc index eebeda14..3101b9ce 100644 --- a/libc/integral/c.inc +++ b/libc/integral/c.inc @@ -318,6 +318,15 @@ typedef uint64_t uintmax_t; #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: * diff --git a/libc/log/log.h b/libc/log/log.h index 1ea9e1bc..39fadaf8 100644 --- a/libc/log/log.h +++ b/libc/log/log.h @@ -5,11 +5,12 @@ │ cosmopolitan § liblog ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ -#define kLogFatal 0u -#define kLogError 1u -#define kLogWarn 2u -#define kLogInfo 3u -#define kLogDebug 4u +#define kLogFatal 0u +#define kLogError 1u +#define kLogWarn 2u +#define kLogInfo 3u +#define kLogVerbose 4u +#define kLogDebug 5u /** * Log level for compile-time DCE. @@ -20,7 +21,7 @@ /* #elif IsTiny() */ /* #define LOGGABLELEVEL kLogInfo */ #else -#define LOGGABLELEVEL kLogInfo +#define LOGGABLELEVEL kLogVerbose #endif #endif @@ -149,6 +150,13 @@ extern unsigned g_loglevel; /* log level for runtime check */ } \ } while (0) +#define VERBOSEF(FMT, ...) \ + do { \ + if (LOGGABLE(kLogVerbose)) { \ + fverbosef(kLogVerbose, __FILE__, __LINE__, NULL, FMT, ##__VA_ARGS__); \ + } \ + } while (0) + #define VDEBUGF(FMT, VA) \ do { \ if (LOGGABLE(kLogDebug)) { \ @@ -163,6 +171,13 @@ extern unsigned g_loglevel; /* log level for runtime check */ } \ } 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) \ do { \ if (LOGGABLE(kLogDebug)) { \ @@ -203,6 +218,8 @@ void __logerrno(const char *, int, const char *) relegated; #define ATTRV paramsnonnull((5, 6)) void flogf(ARGS, ...) ATTR 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 vfdebugf(ARGS, va_list) asm("vflogf") ATTRV relegated libcesque; void ffatalf(ARGS, ...) asm("flogf") ATTR relegated noreturn libcesque; diff --git a/libc/log/vflogf.c b/libc/log/vflogf.c index 2136f064..ed76dd89 100644 --- a/libc/log/vflogf.c +++ b/libc/log/vflogf.c @@ -76,7 +76,6 @@ void vflogf_onfail(FILE *f) { void(vflogf)(unsigned level, const char *file, int line, FILE *f, const char *fmt, va_list va) { static struct timespec ts; - bool flush; struct tm tm; long double t2; const char *prog; @@ -95,12 +94,10 @@ void(vflogf)(unsigned level, const char *file, int line, FILE *f, timebufp = timebuf; zonebufp = zonebuf; dots = nsec; - flush = true; } else { timebufp = "---------------"; zonebufp = "---"; dots = nsec - ts.tv_nsec; - flush = true; } ts.tv_sec = secs; ts.tv_nsec = nsec; @@ -113,7 +110,6 @@ void(vflogf)(unsigned level, const char *file, int line, FILE *f, (vfprintf)(f, fmt, va); va_end(va); fputc('\n', f); - if (flush) fflush(f); if (level == kLogFatal) { startfatal(file, line); fprintf(stderr, "fatal error see logfile\n"); diff --git a/libc/nexgen32e/bsf.c b/libc/nexgen32e/bsf.c new file mode 100644 index 00000000..01f19dce --- /dev/null +++ b/libc/nexgen32e/bsf.c @@ -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); +} diff --git a/libc/nexgen32e/bsf.h b/libc/nexgen32e/bsf.h index ea4d9e73..7d161522 100644 --- a/libc/nexgen32e/bsf.h +++ b/libc/nexgen32e/bsf.h @@ -17,12 +17,15 @@ COSMOPOLITAN_C_START_ * 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 bsfl(u) __builtin_ctzl(u) #define bsfll(u) __builtin_ctzll(u) -unsigned bsfmax(uintmax_t); - COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* COSMOPOLITAN_LIBC_NEXGEN32E_BSF_H_ */ diff --git a/libc/nexgen32e/bsfl.c b/libc/nexgen32e/bsfl.c new file mode 100644 index 00000000..2619b723 --- /dev/null +++ b/libc/nexgen32e/bsfl.c @@ -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); +} diff --git a/libc/nexgen32e/bsfll.c b/libc/nexgen32e/bsfll.c new file mode 100644 index 00000000..10639e6f --- /dev/null +++ b/libc/nexgen32e/bsfll.c @@ -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); +} diff --git a/libc/nexgen32e/bsr.c b/libc/nexgen32e/bsr.c new file mode 100644 index 00000000..10c12e7e --- /dev/null +++ b/libc/nexgen32e/bsr.c @@ -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); +} diff --git a/libc/nexgen32e/bsr.h b/libc/nexgen32e/bsr.h index 4d77806f..b0b640e2 100644 --- a/libc/nexgen32e/bsr.h +++ b/libc/nexgen32e/bsr.h @@ -17,11 +17,14 @@ COSMOPOLITAN_C_START_ * 0xffffffff 0 0 1 31 0 */ -#define bsr(u) ((sizeof(unsigned) * 8 - 1) ^ __builtin_clz(u)) -#define bsrl(u) ((sizeof(unsigned long) * 8 - 1) ^ __builtin_clzl(u)) -#define bsrll(u) ((sizeof(unsigned long long) * 8 - 1) ^ __builtin_clzll(u)) +int bsr(int); +int bsrl(long); +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_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/libc/nexgen32e/bsrl.c b/libc/nexgen32e/bsrl.c new file mode 100644 index 00000000..56e60d66 --- /dev/null +++ b/libc/nexgen32e/bsrl.c @@ -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); +} diff --git a/libc/nexgen32e/bsrll.c b/libc/nexgen32e/bsrll.c new file mode 100644 index 00000000..46e08f41 --- /dev/null +++ b/libc/nexgen32e/bsrll.c @@ -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); +} diff --git a/libc/alg/djbsort-avx2.S b/libc/nexgen32e/djbsort-avx2.S similarity index 100% rename from libc/alg/djbsort-avx2.S rename to libc/nexgen32e/djbsort-avx2.S diff --git a/libc/alg/djbsort.c b/libc/nexgen32e/djbsort.c similarity index 95% rename from libc/alg/djbsort.c rename to libc/nexgen32e/djbsort.c index 895b6c7a..c5f3e75b 100644 --- a/libc/alg/djbsort.c +++ b/libc/nexgen32e/djbsort.c @@ -24,9 +24,9 @@ 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)) { djbsort$avx2(a, n); } else { diff --git a/libc/nexgen32e/gc.S b/libc/nexgen32e/gc.S index 215a8121..c884406f 100644 --- a/libc/nexgen32e/gc.S +++ b/libc/nexgen32e/gc.S @@ -49,11 +49,11 @@ CollectGarbage: sub $0x20,%rsp push %rax push %rdx - movaps %xmm0,-0x20(%rbp) - movaps %xmm1,-0x10(%rbp) + movdqa %xmm0,-0x20(%rbp) + movdqa %xmm1,-0x10(%rbp) call *%r9 - movaps -0x10(%rbp),%xmm1 - movaps -0x20(%rbp),%xmm0 + movdqa -0x10(%rbp),%xmm1 + movdqa -0x20(%rbp),%xmm0 pop %rdx pop %rax leave diff --git a/libc/str/insertionsort.greg.c b/libc/nexgen32e/insertionsort.greg.c similarity index 100% rename from libc/str/insertionsort.greg.c rename to libc/nexgen32e/insertionsort.greg.c diff --git a/libc/nexgen32e/kcpuids.S b/libc/nexgen32e/kcpuids.S index f3a2cebf..7be7cad6 100644 --- a/libc/nexgen32e/kcpuids.S +++ b/libc/nexgen32e/kcpuids.S @@ -70,7 +70,7 @@ kCpuids:.long 0,0,0,0 # EAX=0 (Basic Processor Info) add $4*4,%rdi jmp 2b 3: nop -#if 0 && !X86_NEED(AVX2) +#if !X86_NEED(AVX2) testb X86_HAVE(AVX)(%r8) jz 5f testb X86_HAVE(OSXSAVE)(%r8) diff --git a/libc/nexgen32e/x86feature.h b/libc/nexgen32e/x86feature.h index f3ba0d5a..913d9f0d 100644 --- a/libc/nexgen32e/x86feature.h +++ b/libc/nexgen32e/x86feature.h @@ -17,8 +17,8 @@ #define X86_AES 1H, ECX, 25, _X86_CC_AES, _ /* westmere c. 2010 */ #define X86_APIC 1H, EDX, 9, 0, _ #define X86_ARCH_CAPABILITIES 7H, EDX, 29, 0, _ -#define X86_AVX 1H, ECX, 28, _X86_CC_AVX, AVX /* sandybridge c. 2012 */ -#define X86_AVX2 7H, EBX, 5, _X86_CC_AVX2, AVX /* haswell c. 2013 */ +#define X86_AVX 1H, ECX, 28, _X86_CC_AVX, _ /* sandybridge c. 2012 */ +#define X86_AVX2 7H, EBX, 5, _X86_CC_AVX2, _ /* haswell c. 2013 */ #define X86_AVX512BW 7H, EBX, 30, 0, _ #define X86_AVX512CD 7H, EBX, 28, 0, _ #define X86_AVX512DQ 7H, EBX, 17, 0, _ @@ -246,17 +246,5 @@ #endif #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_ */ diff --git a/libc/runtime/construct.S b/libc/runtime/construct.S index 24caf77b..c64f54c6 100644 --- a/libc/runtime/construct.S +++ b/libc/runtime/construct.S @@ -23,6 +23,11 @@ .source __FILE__ / Calls global initialization functions. +/ +/ @param r12 is argc +/ @param r13 is argv +/ @param r14 is environ +/ @param r15 is auxv _construct: push %rbp mov %rsp,%rbp diff --git a/libc/runtime/cxaatexit.c b/libc/runtime/cxaatexit.c index b68ef8dd..ee589c6e 100644 --- a/libc/runtime/cxaatexit.c +++ b/libc/runtime/cxaatexit.c @@ -43,8 +43,8 @@ static struct CxaAtexitBlocks { * * Destructors are called in reverse order. They won't be called if the * program aborts or _exit() is called. Invocations of this function are - * usually generated by the C++ compiler. Behavior is limitless if you - * choose to link calloc() and free(). + * usually generated by the C++ compiler. Behavior is limitless if some + * other module has linked calloc(). * * @param fp is void(*)(T) * @param arg is passed to callback @@ -78,8 +78,11 @@ int __cxa_atexit(void *fp, void *arg, void *pred) { /** * 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 - * @note reentrant emptor */ void __cxa_finalize(void *pred) { unsigned i; diff --git a/libc/runtime/mmap.c b/libc/runtime/mmap.c index 5dc21f38..e18028fe 100644 --- a/libc/runtime/mmap.c +++ b/libc/runtime/mmap.c @@ -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 (!(!!(flags & MAP_ANONYMOUS) ^ (fd != -1))) 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 (UntrackMemoryIntervals(addr, size) == -1) { return MAP_FAILED; diff --git a/libc/runtime/runtime.mk b/libc/runtime/runtime.mk index e0aaddf0..497a5006 100644 --- a/libc/runtime/runtime.mk +++ b/libc/runtime/runtime.mk @@ -37,6 +37,7 @@ LIBC_RUNTIME_A_DIRECTDEPS = \ LIBC_BITS \ LIBC_CALLS \ LIBC_CONV \ + LIBC_TINYMATH \ LIBC_ELF \ LIBC_FMT \ LIBC_NEXGEN32E \ diff --git a/libc/runtime/spawn.S b/libc/runtime/spawn.S index 701fe60a..428113d9 100644 --- a/libc/runtime/spawn.S +++ b/libc/runtime/spawn.S @@ -22,6 +22,11 @@ #include "libc/macros.h" / 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 mov %rsp,%rbp diff --git a/libc/str/str.h b/libc/str/str.h index 980b32de..e08e112b 100644 --- a/libc/str/str.h +++ b/libc/str/str.h @@ -64,9 +64,10 @@ void *isnotplaintext(const void *, size_t) nothrow nocallback nosideeffect; └──────────────3 Continuations follow */ #define INVALID_CODEPOINT 0xfffd -#define UTF16_MASK 0b1111110000000000 -#define UTF16_MOAR 0b1101100000000000 /* 0xD800..0xDBFF */ -#define UTF16_CONT 0b1101110000000000 /* 0xDC00..0xDBFF */ + +#define UTF16_MASK 0b1111110000000000 +#define UTF16_MOAR 0b1101100000000000 /* 0xD800..0xDBFF */ +#define UTF16_CONT 0b1101110000000000 /* 0xDC00..0xDBFF */ unsigned getutf16(const char16_t *, wint_t *); int pututf16(char16_t *, size_t, wint_t, bool); diff --git a/libc/str/thompike.h b/libc/str/thompike.h new file mode 100644 index 00000000..4736a57e --- /dev/null +++ b/libc/str/thompike.h @@ -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_ */ diff --git a/libc/sysv/consts.sh b/libc/sysv/consts.sh index 5b68920c..eb319daa 100755 --- a/libc/sysv/consts.sh +++ b/libc/sysv/consts.sh @@ -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 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 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 FAPPEND 0x0400 8 8 8 0 # bsd consensus diff --git a/libc/tinymath/fpclassify.S b/libc/tinymath/fpclassify.S index 8e6eb06d..05a646bc 100644 --- a/libc/tinymath/fpclassify.S +++ b/libc/tinymath/fpclassify.S @@ -21,7 +21,7 @@ #include "libc/macros.h" .source __FILE__ -__fpclassify: +tinymath_fpclassify: .leafprologue movd %xmm0,%rax movd %xmm0,%rdx @@ -41,4 +41,5 @@ __fpclassify: sal $12,%rdx sete %al 1: .leafepilogue - .endfn __fpclassify,globl + .endfn tinymath_fpclassify,globl + .alias tinymath_fpclassify,__fpclassify diff --git a/libc/tinymath/fpclassifyf.S b/libc/tinymath/fpclassifyf.S index 76df6d3d..d1eb15fc 100644 --- a/libc/tinymath/fpclassifyf.S +++ b/libc/tinymath/fpclassifyf.S @@ -21,7 +21,7 @@ #include "libc/macros.h" .source __FILE__ -__fpclassifyf: +tinymath_fpclassifyf: .leafprologue movd %xmm0,%edx movd %xmm0,%eax @@ -42,4 +42,5 @@ __fpclassifyf: sete %al movzbl %al,%eax 1: .leafepilogue - .endfn __fpclassifyf,globl + .endfn tinymath_fpclassifyf,globl + .alias tinymath_fpclassifyf,__fpclassifyf diff --git a/libc/tinymath/fpclassifyl.S b/libc/tinymath/fpclassifyl.S index 2529208c..a872f4eb 100644 --- a/libc/tinymath/fpclassifyl.S +++ b/libc/tinymath/fpclassifyl.S @@ -21,7 +21,7 @@ #include "libc/macros.h" .source __FILE__ -__fpclassifyl: +tinymath_fpclassifyl: push %rbp mov %rsp,%rbp mov 24(%rbp),%rax @@ -50,4 +50,5 @@ __fpclassifyl: and $FP_NORMAL,%eax 1: pop %rbp ret - .endfn __fpclassifyl,globl + .endfn tinymath_fpclassifyl,globl + .alias tinymath_fpclassifyl,__fpclassifyl diff --git a/libc/tinymath/scalbn.S b/libc/tinymath/scalbn.S index f2e9ed48..164e1569 100644 --- a/libc/tinymath/scalbn.S +++ b/libc/tinymath/scalbn.S @@ -20,6 +20,10 @@ #include "libc/macros.h" .source __FILE__ +/ Returns 𝑥 × 2ʸ. +/ +/ @param 𝑥 is double passed in %xmm0 +/ @param 𝑦 is exponent via %edi tinymath_scalbn: push %rbp mov %rsp,%rbp diff --git a/libc/tinymath/scalbnf.S b/libc/tinymath/scalbnf.S index 6c7a7bb1..9ea55181 100644 --- a/libc/tinymath/scalbnf.S +++ b/libc/tinymath/scalbnf.S @@ -20,6 +20,10 @@ #include "libc/macros.h" .source __FILE__ +/ Returns 𝑥 × 2ʸ. +/ +/ @param 𝑥 is float passed in %xmm0 +/ @param 𝑦 is exponent via %edi tinymath_scalbnf: push %rbp mov %rsp,%rbp diff --git a/libc/tinymath/scalbnl.S b/libc/tinymath/scalbnl.S index 8e97cc5f..ea7135fe 100644 --- a/libc/tinymath/scalbnl.S +++ b/libc/tinymath/scalbnl.S @@ -20,11 +20,10 @@ #include "libc/macros.h" .source __FILE__ -/ Returns 𝑥 × 𝑟ʸ where 𝑟 is radix of hardware architecture. +/ Returns 𝑥 × 2ʸ. / / @param 𝑥 is long double passed on stack / @param 𝑦 is exponent via %edi -/ @see FLT_RADIX tinymath_scalbnl: push %rbp mov %rsp,%rbp diff --git a/test/libc/fmt/test.mk b/test/libc/fmt/test.mk index 98c6bc94..2f03bac9 100644 --- a/test/libc/fmt/test.mk +++ b/test/libc/fmt/test.mk @@ -19,12 +19,14 @@ TEST_LIBC_FMT_CHECKS = \ $(TEST_LIBC_FMT_SRCS_TEST:%.c=o/$(MODE)/%.com.runs) TEST_LIBC_FMT_DIRECTDEPS = \ + LIBC_ALG \ LIBC_CALLS_HEFTY \ LIBC_CONV \ LIBC_FMT \ LIBC_MEM \ LIBC_NEXGEN32E \ LIBC_RUNTIME \ + LIBC_STDIO \ LIBC_STR \ LIBC_STUBS \ LIBC_SYSV \ diff --git a/test/libc/intrin/intrin_test.c b/test/libc/intrin/intrin_test.c index b4b90b36..fade3aa0 100644 --- a/test/libc/intrin/intrin_test.c +++ b/test/libc/intrin/intrin_test.c @@ -355,14 +355,14 @@ TEST(punpckhwd, test) { uint16_t b[8] = {9, 10, 11, 12, 13, 14, 15, 16}; uint16_t c[8]; punpckhwd(c, a, b); - ASSERT_EQ(5, c[0]); - ASSERT_EQ(13, c[1]); - ASSERT_EQ(6, c[2]); - ASSERT_EQ(14, c[3]); - ASSERT_EQ(7, c[4]); - ASSERT_EQ(15, c[5]); - ASSERT_EQ(8, c[6]); - ASSERT_EQ(16, c[7]); + EXPECT_EQ(5, c[0]); + EXPECT_EQ(13, c[1]); + EXPECT_EQ(6, c[2]); + EXPECT_EQ(14, c[3]); + EXPECT_EQ(7, c[4]); + EXPECT_EQ(15, c[5]); + EXPECT_EQ(8, c[6]); + EXPECT_EQ(16, c[7]); } TEST(punpckhwd, pure) { @@ -370,70 +370,70 @@ TEST(punpckhwd, pure) { uint16_t b[8] = {9, 10, 11, 12, 13, 14, 15, 16}; uint16_t c[8]; punpckhwd(c, a, b); - ASSERT_EQ(5, c[0]); - ASSERT_EQ(13, c[1]); - ASSERT_EQ(6, c[2]); - ASSERT_EQ(14, c[3]); - ASSERT_EQ(7, c[4]); - ASSERT_EQ(15, c[5]); - ASSERT_EQ(8, c[6]); - ASSERT_EQ(16, c[7]); + EXPECT_EQ(5, c[0]); + EXPECT_EQ(13, c[1]); + EXPECT_EQ(6, c[2]); + EXPECT_EQ(14, c[3]); + EXPECT_EQ(7, c[4]); + EXPECT_EQ(15, c[5]); + EXPECT_EQ(8, c[6]); + EXPECT_EQ(16, c[7]); } TEST(punpckhwd, testAlias) { uint16_t a[8] = {1, 02, 03, 04, 05, 06, 07, 8}; uint16_t b[8] = {9, 10, 11, 12, 13, 14, 15, 16}; punpckhwd(a, a, b); - ASSERT_EQ(5, a[0]); - ASSERT_EQ(13, a[1]); - ASSERT_EQ(6, a[2]); - ASSERT_EQ(14, a[3]); - ASSERT_EQ(7, a[4]); - ASSERT_EQ(15, a[5]); - ASSERT_EQ(8, a[6]); - ASSERT_EQ(16, a[7]); + EXPECT_EQ(5, a[0]); + EXPECT_EQ(13, a[1]); + EXPECT_EQ(6, a[2]); + EXPECT_EQ(14, a[3]); + EXPECT_EQ(7, a[4]); + EXPECT_EQ(15, a[5]); + EXPECT_EQ(8, a[6]); + EXPECT_EQ(16, a[7]); } TEST(punpckhwd, pureAlias) { uint16_t a[8] = {1, 02, 03, 04, 05, 06, 07, 8}; uint16_t b[8] = {9, 10, 11, 12, 13, 14, 15, 16}; (punpckhwd)(a, a, b); - ASSERT_EQ(5, a[0]); - ASSERT_EQ(13, a[1]); - ASSERT_EQ(6, a[2]); - ASSERT_EQ(14, a[3]); - ASSERT_EQ(7, a[4]); - ASSERT_EQ(15, a[5]); - ASSERT_EQ(8, a[6]); - ASSERT_EQ(16, a[7]); + EXPECT_EQ(5, a[0]); + EXPECT_EQ(13, a[1]); + EXPECT_EQ(6, a[2]); + EXPECT_EQ(14, a[3]); + EXPECT_EQ(7, a[4]); + EXPECT_EQ(15, a[5]); + EXPECT_EQ(8, a[6]); + EXPECT_EQ(16, a[7]); } TEST(punpckhwd, testAlias2) { uint16_t a[8] = {1, 02, 03, 04, 05, 06, 07, 8}; uint16_t b[8] = {9, 10, 11, 12, 13, 14, 15, 16}; punpckhwd(b, a, b); - ASSERT_EQ(5, b[0]); - ASSERT_EQ(13, b[1]); - ASSERT_EQ(6, b[2]); - ASSERT_EQ(14, b[3]); - ASSERT_EQ(7, b[4]); - ASSERT_EQ(15, b[5]); - ASSERT_EQ(8, b[6]); - ASSERT_EQ(16, b[7]); + EXPECT_EQ(5, b[0]); + EXPECT_EQ(13, b[1]); + EXPECT_EQ(6, b[2]); + EXPECT_EQ(14, b[3]); + EXPECT_EQ(7, b[4]); + EXPECT_EQ(15, b[5]); + EXPECT_EQ(8, b[6]); + EXPECT_EQ(16, b[7]); } TEST(punpckhwd, pureAlias2) { uint16_t a[8] = {1, 02, 03, 04, 05, 06, 07, 8}; uint16_t b[8] = {9, 10, 11, 12, 13, 14, 15, 16}; (punpckhwd)(b, a, b); - ASSERT_EQ(5, b[0]); - ASSERT_EQ(13, b[1]); - ASSERT_EQ(6, b[2]); - ASSERT_EQ(14, b[3]); - ASSERT_EQ(7, b[4]); - ASSERT_EQ(15, b[5]); - ASSERT_EQ(8, b[6]); - ASSERT_EQ(16, b[7]); + EXPECT_EQ(5, b[0]); + EXPECT_EQ(13, b[1]); + EXPECT_EQ(6, b[2]); + EXPECT_EQ(14, b[3]); + EXPECT_EQ(7, b[4]); + EXPECT_EQ(15, b[5]); + EXPECT_EQ(8, b[6]); + EXPECT_EQ(16, b[7]); } TEST(punpckhqdq, test) { @@ -441,8 +441,8 @@ TEST(punpckhqdq, test) { uint64_t b[2] = {3, 4}; uint64_t c[2]; punpckhqdq(c, a, b); - ASSERT_EQ(2, c[0]); - ASSERT_EQ(4, c[1]); + EXPECT_EQ(2, c[0]); + EXPECT_EQ(4, c[1]); } TEST(punpckhqdq, pure) { @@ -450,24 +450,24 @@ TEST(punpckhqdq, pure) { uint64_t b[2] = {3, 4}; uint64_t c[2]; (punpckhqdq)(c, a, b); - ASSERT_EQ(2, c[0]); - ASSERT_EQ(4, c[1]); + EXPECT_EQ(2, c[0]); + EXPECT_EQ(4, c[1]); } TEST(punpckhqdq, testAlias) { uint64_t a[2] = {1, 2}; uint64_t b[2] = {3, 4}; punpckhqdq(a, a, b); - ASSERT_EQ(2, a[0]); - ASSERT_EQ(4, a[1]); + EXPECT_EQ(2, a[0]); + EXPECT_EQ(4, a[1]); } TEST(punpckhqdq, pureAlias) { uint64_t a[2] = {1, 2}; uint64_t b[2] = {3, 4}; (punpckhqdq)(a, a, b); - ASSERT_EQ(2, a[0]); - ASSERT_EQ(4, a[1]); + EXPECT_EQ(2, a[0]); + EXPECT_EQ(4, a[1]); } TEST(punpckhdq, test) { @@ -475,10 +475,10 @@ TEST(punpckhdq, test) { uint32_t b[4] = {5, 6, 7, 8}; uint32_t c[4]; punpckhdq(c, a, b); - ASSERT_EQ(3, c[0]); - ASSERT_EQ(7, c[1]); - ASSERT_EQ(4, c[2]); - ASSERT_EQ(8, c[3]); + EXPECT_EQ(3, c[0]); + EXPECT_EQ(7, c[1]); + EXPECT_EQ(4, c[2]); + EXPECT_EQ(8, c[3]); } TEST(punpckhdq, pure) { @@ -486,50 +486,50 @@ TEST(punpckhdq, pure) { uint32_t b[4] = {5, 6, 7, 8}; uint32_t c[4]; punpckhdq(c, a, b); - ASSERT_EQ(3, c[0]); - ASSERT_EQ(7, c[1]); - ASSERT_EQ(4, c[2]); - ASSERT_EQ(8, c[3]); + EXPECT_EQ(3, c[0]); + EXPECT_EQ(7, c[1]); + EXPECT_EQ(4, c[2]); + EXPECT_EQ(8, c[3]); } TEST(punpckhdq, testAlias) { uint32_t a[4] = {1, 2, 3, 4}; uint32_t b[4] = {5, 6, 7, 8}; punpckhdq(a, a, b); - ASSERT_EQ(3, a[0]); - ASSERT_EQ(7, a[1]); - ASSERT_EQ(4, a[2]); - ASSERT_EQ(8, a[3]); + EXPECT_EQ(3, a[0]); + EXPECT_EQ(7, a[1]); + EXPECT_EQ(4, a[2]); + EXPECT_EQ(8, a[3]); } TEST(punpckhdq, pureAlias) { uint32_t a[4] = {1, 2, 3, 4}; uint32_t b[4] = {5, 6, 7, 8}; (punpckhdq)(a, a, b); - ASSERT_EQ(3, a[0]); - ASSERT_EQ(7, a[1]); - ASSERT_EQ(4, a[2]); - ASSERT_EQ(8, a[3]); + EXPECT_EQ(3, a[0]); + EXPECT_EQ(7, a[1]); + EXPECT_EQ(4, a[2]); + EXPECT_EQ(8, a[3]); } TEST(punpckhdq, testAlias2) { uint32_t a[4] = {1, 2, 3, 4}; uint32_t b[4] = {5, 6, 7, 8}; punpckhdq(b, a, b); - ASSERT_EQ(3, b[0]); - ASSERT_EQ(7, b[1]); - ASSERT_EQ(4, b[2]); - ASSERT_EQ(8, b[3]); + EXPECT_EQ(3, b[0]); + EXPECT_EQ(7, b[1]); + EXPECT_EQ(4, b[2]); + EXPECT_EQ(8, b[3]); } TEST(punpckhdq, pureAlias2) { uint32_t a[4] = {1, 2, 3, 4}; uint32_t b[4] = {5, 6, 7, 8}; (punpckhdq)(b, a, b); - ASSERT_EQ(3, b[0]); - ASSERT_EQ(7, b[1]); - ASSERT_EQ(4, b[2]); - ASSERT_EQ(8, b[3]); + EXPECT_EQ(3, b[0]); + EXPECT_EQ(7, b[1]); + EXPECT_EQ(4, b[2]); + EXPECT_EQ(8, b[3]); } TEST(punpckhwd, fuzz) { diff --git a/test/libc/runtime/test.mk b/test/libc/runtime/test.mk index 224a7e9c..f7cc408f 100644 --- a/test/libc/runtime/test.mk +++ b/test/libc/runtime/test.mk @@ -29,6 +29,7 @@ TEST_LIBC_RUNTIME_DIRECTDEPS = \ LIBC_CALLS_HEFTY \ LIBC_FMT \ LIBC_MEM \ + LIBC_TINYMATH \ LIBC_NEXGEN32E \ LIBC_RAND \ LIBC_RUNTIME \ diff --git a/test/tool/build/lib/bitscan_test.c b/test/tool/build/lib/bitscan_test.c index babab3dd..f35e7d29 100644 --- a/test/tool/build/lib/bitscan_test.c +++ b/test/tool/build/lib/bitscan_test.c @@ -36,10 +36,9 @@ void SetUp(void) { TEST(bsr64, test) { bool zf; uint64_t i, w, x, a, b; - m->xedd->op.rde = REXW; for (i = 0; i < ARRAYLEN(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)); ASSERT_EQ(zf, GetFlag(m->flags, FLAGS_ZF)); if (!zf) ASSERT_EQ(a, b); @@ -49,10 +48,9 @@ TEST(bsr64, test) { TEST(bsr32, test) { bool zf; uint32_t i, w, x, a, b; - m->xedd->op.rde = 0; for (i = 0; i < ARRAYLEN(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)); ASSERT_EQ(zf, GetFlag(m->flags, FLAGS_ZF)); if (!zf) ASSERT_EQ(a, b); @@ -62,10 +60,9 @@ TEST(bsr32, test) { TEST(bsr16, test) { bool zf; uint16_t i, w, x, a, b; - m->xedd->op.rde = OSZ; for (i = 0; i < ARRAYLEN(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)); ASSERT_EQ(zf, GetFlag(m->flags, FLAGS_ZF)); if (!zf) ASSERT_EQ(a, b); @@ -75,10 +72,9 @@ TEST(bsr16, test) { TEST(bsf64, test) { bool zf; uint64_t i, w, x, a, b; - m->xedd->op.rde = REXW; for (i = 0; i < ARRAYLEN(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)); ASSERT_EQ(zf, GetFlag(m->flags, FLAGS_ZF)); if (!zf) ASSERT_EQ(a, b); @@ -88,10 +84,9 @@ TEST(bsf64, test) { TEST(bsf32, test) { bool zf; uint32_t i, w, x, a, b; - m->xedd->op.rde = 0; for (i = 0; i < ARRAYLEN(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)); ASSERT_EQ(zf, GetFlag(m->flags, FLAGS_ZF)); if (!zf) ASSERT_EQ(a, b); @@ -101,10 +96,9 @@ TEST(bsf32, test) { TEST(bsf16, test) { bool zf; uint16_t i, w, x, a, b; - m->xedd->op.rde = OSZ; for (i = 0; i < ARRAYLEN(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)); ASSERT_EQ(zf, GetFlag(m->flags, FLAGS_ZF)); if (!zf) ASSERT_EQ(a, b, "%#lx", x); diff --git a/test/tool/build/lib/divmul_test.c b/test/tool/build/lib/divmul_test.c index f1831b66..cce414d7 100644 --- a/test/tool/build/lib/divmul_test.c +++ b/test/tool/build/lib/divmul_test.c @@ -62,12 +62,11 @@ TEST(imul8, test) { int i, j; int16_t ax; bool cf, of; - m->xedd->op.rde = MOD(3) | RM(CX); for (i = 0; i < ARRAYLEN(A); ++i) { for (j = 0; j < ARRAYLEN(A); ++j) { Write8(m->ax, A[i]); Write8(m->cx, A[j]); - OpMulAxAlEbSigned(m); + OpMulAxAlEbSigned(m, MOD(3) | RM(CX)); asm volatile("imulb\t%3" : "=a"(ax), "=@ccc"(cf), "=@cco"(of) : "q"(A[j]), "0"(A[i]) @@ -85,12 +84,11 @@ TEST(imul16, test) { int i, j; bool cf, of; uint16_t dx, ax; - m->xedd->op.rde = OSZ | MOD(3) | RM(CX); for (i = 0; i < ARRAYLEN(A); ++i) { for (j = 0; j < ARRAYLEN(A); ++j) { Write16(m->ax, A[i]); Write16(m->cx, A[j]); - OpMulRdxRaxEvqpSigned(m); + OpMulRdxRaxEvqpSigned(m, OSZ | MOD(3) | RM(CX)); asm("imulw\t%4" : "=d"(dx), "=a"(ax), "=@ccc"(cf), "=@cco"(of) : "r"(A[j]), "1"(A[i]) @@ -110,12 +108,11 @@ TEST(imul32, test) { int i, j; bool cf, of; uint32_t dx, ax; - m->xedd->op.rde = MOD(3) | RM(CX); for (i = 0; i < ARRAYLEN(A); ++i) { for (j = 0; j < ARRAYLEN(A); ++j) { Write32(m->ax, A[i]); Write32(m->cx, A[j]); - OpMulRdxRaxEvqpSigned(m); + OpMulRdxRaxEvqpSigned(m, MOD(3) | RM(CX)); asm("imull\t%4" : "=d"(dx), "=a"(ax), "=@ccc"(cf), "=@cco"(of) : "r"(A[j]), "1"(A[i]) @@ -135,12 +132,11 @@ TEST(imul64, test) { int i, j; bool cf, of; uint64_t dx, ax; - m->xedd->op.rde = REXW | MOD(3) | RM(CX); for (i = 0; i < ARRAYLEN(A); ++i) { for (j = 0; j < ARRAYLEN(A); ++j) { Write64(m->ax, A[i]); Write64(m->cx, A[j]); - OpMulRdxRaxEvqpSigned(m); + OpMulRdxRaxEvqpSigned(m, REXW | MOD(3) | RM(CX)); asm("imulq\t%4" : "=d"(dx), "=a"(ax), "=@ccc"(cf), "=@cco"(of) : "r"(A[j]), "1"(A[i]) @@ -158,12 +154,11 @@ TEST(mul8, test) { int i, j; uint16_t ax; bool cf, of; - m->xedd->op.rde = MOD(3) | RM(CX); for (i = 0; i < ARRAYLEN(A); ++i) { for (j = 0; j < ARRAYLEN(A); ++j) { Write8(m->ax, A[i]); Write8(m->cx, A[j]); - OpMulAxAlEbUnsigned(m); + OpMulAxAlEbUnsigned(m, MOD(3) | RM(CX)); asm volatile("mulb\t%3" : "=a"(ax), "=@ccc"(cf), "=@cco"(of) : "q"(A[j]), "0"(A[i]) @@ -181,12 +176,11 @@ TEST(mul16, test) { int i, j; bool cf, of; uint16_t dx, ax; - m->xedd->op.rde = OSZ | MOD(3) | RM(CX); for (i = 0; i < ARRAYLEN(A); ++i) { for (j = 0; j < ARRAYLEN(A); ++j) { Write16(m->ax, A[i]); Write16(m->cx, A[j]); - OpMulRdxRaxEvqpUnsigned(m); + OpMulRdxRaxEvqpUnsigned(m, OSZ | MOD(3) | RM(CX)); asm("mulw\t%4" : "=d"(dx), "=a"(ax), "=@ccc"(cf), "=@cco"(of) : "r"(A[j]), "1"(A[i]) @@ -206,12 +200,11 @@ TEST(mul32, test) { int i, j; bool cf, of; uint32_t dx, ax; - m->xedd->op.rde = MOD(3) | RM(CX); for (i = 0; i < ARRAYLEN(A); ++i) { for (j = 0; j < ARRAYLEN(A); ++j) { Write32(m->ax, A[i]); Write32(m->cx, A[j]); - OpMulRdxRaxEvqpUnsigned(m); + OpMulRdxRaxEvqpUnsigned(m, MOD(3) | RM(CX)); asm("mull\t%4" : "=d"(dx), "=a"(ax), "=@ccc"(cf), "=@cco"(of) : "r"(A[j]), "1"(A[i]) @@ -231,12 +224,11 @@ TEST(mul64, test) { int i, j; bool cf, of; uint64_t dx, ax; - m->xedd->op.rde = REXW | MOD(3) | RM(CX); for (i = 0; i < ARRAYLEN(A); ++i) { for (j = 0; j < ARRAYLEN(A); ++j) { Write64(m->ax, A[i]); Write64(m->cx, A[j]); - OpMulRdxRaxEvqpUnsigned(m); + OpMulRdxRaxEvqpUnsigned(m, REXW | MOD(3) | RM(CX)); asm("mulq\t%4" : "=d"(dx), "=a"(ax), "=@ccc"(cf), "=@cco"(of) : "r"(A[j]), "1"(A[i]) @@ -255,7 +247,6 @@ TEST(idiv8, test) { bool gotthrow, gotsigfpe; int8_t i, j, k, w, x, a, b; int8_t quotient, remainder; - m->xedd->op.rde = MOD(3) | RM(CX); for (i = 0; i < ARRAYLEN(A); ++i) { for (j = 0; j < ARRAYLEN(A); ++j) { for (k = 0; k < ARRAYLEN(A); ++k) { @@ -265,7 +256,7 @@ TEST(idiv8, test) { gotthrow = false; gotsigfpe = false; if (!setjmp(m->onhalt)) { - OpDivAlAhAxEbSigned(m); + OpDivAlAhAxEbSigned(m, MOD(3) | RM(CX)); } else { gotthrow = true; } @@ -295,7 +286,6 @@ TEST(idiv16, test) { bool gotthrow, gotsigfpe; int16_t i, j, k, w, x, a, b; int16_t quotient, remainder; - m->xedd->op.rde = OSZ | MOD(3) | RM(CX); for (i = 0; i < ARRAYLEN(A); ++i) { for (j = 0; j < ARRAYLEN(A); ++j) { for (k = 0; k < ARRAYLEN(A); ++k) { @@ -304,7 +294,7 @@ TEST(idiv16, test) { memcpy(m->cx, &A[k], 2); if (!setjmp(m->onhalt)) { gotthrow = false; - OpDivRdxRaxEvqpSigned(m); + OpDivRdxRaxEvqpSigned(m, OSZ | MOD(3) | RM(CX)); } else { gotthrow = true; } @@ -333,7 +323,6 @@ TEST(idiv32, test) { bool gotthrow, gotsigfpe; int32_t i, j, k, w, x, a, b; int32_t quotient, remainder; - m->xedd->op.rde = MOD(3) | RM(CX); for (i = 0; i < ARRAYLEN(A); ++i) { for (j = 0; j < ARRAYLEN(A); ++j) { for (k = 0; k < ARRAYLEN(A); ++k) { @@ -342,7 +331,7 @@ TEST(idiv32, test) { memcpy(m->cx, &A[k], 4); if (!setjmp(m->onhalt)) { gotthrow = false; - OpDivRdxRaxEvqpSigned(m); + OpDivRdxRaxEvqpSigned(m, MOD(3) | RM(CX)); } else { gotthrow = true; } @@ -373,7 +362,6 @@ TEST(idiv64, test) { bool gotthrow, gotsigfpe; int64_t i, j, k, w, x, a, b; int64_t quotient, remainder; - m->xedd->op.rde = REXW | MOD(3) | RM(CX); for (i = 0; i < ARRAYLEN(A); ++i) { for (j = 0; j < ARRAYLEN(A); ++j) { for (k = 0; k < ARRAYLEN(A); ++k) { @@ -382,7 +370,7 @@ TEST(idiv64, test) { memcpy(m->cx, &A[k], 8); if (!setjmp(m->onhalt)) { gotthrow = false; - OpDivRdxRaxEvqpSigned(m); + OpDivRdxRaxEvqpSigned(m, REXW | MOD(3) | RM(CX)); } else { gotthrow = true; } @@ -411,7 +399,6 @@ TEST(div, test) { bool gotthrow, gotsigfpe; uint8_t i, j, k, w, x, a, b; uint8_t quotient, remainder; - m->xedd->op.rde = MOD(3) | RM(CX); for (i = 0; i < ARRAYLEN(A); ++i) { for (j = 0; j < ARRAYLEN(A); ++j) { for (k = 0; k < ARRAYLEN(A); ++k) { @@ -421,7 +408,7 @@ TEST(div, test) { gotthrow = false; gotsigfpe = false; if (!setjmp(m->onhalt)) { - OpDivAlAhAxEbUnsigned(m); + OpDivAlAhAxEbUnsigned(m, MOD(3) | RM(CX)); } else { gotthrow = true; } @@ -451,7 +438,6 @@ TEST(div16, test) { bool gotthrow, gotsigfpe; uint16_t i, j, k, w, x, a, b; uint16_t quotient, remainder; - m->xedd->op.rde = OSZ | MOD(3) | RM(CX); for (i = 0; i < ARRAYLEN(A); ++i) { for (j = 0; j < ARRAYLEN(A); ++j) { for (k = 0; k < ARRAYLEN(A); ++k) { @@ -460,7 +446,7 @@ TEST(div16, test) { memcpy(m->cx, &A[k], 2); if (!setjmp(m->onhalt)) { gotthrow = false; - OpDivRdxRaxEvqpUnsigned(m); + OpDivRdxRaxEvqpUnsigned(m, OSZ | MOD(3) | RM(CX)); } else { gotthrow = true; } @@ -489,7 +475,6 @@ TEST(div32, test) { bool gotthrow, gotsigfpe; uint32_t i, j, k, w, x, a, b; uint32_t quotient, remainder; - m->xedd->op.rde = MOD(3) | RM(CX); for (i = 0; i < ARRAYLEN(A); ++i) { for (j = 0; j < ARRAYLEN(A); ++j) { for (k = 0; k < ARRAYLEN(A); ++k) { @@ -498,7 +483,7 @@ TEST(div32, test) { memcpy(m->cx, &A[k], 4); if (!setjmp(m->onhalt)) { gotthrow = false; - OpDivRdxRaxEvqpUnsigned(m); + OpDivRdxRaxEvqpUnsigned(m, MOD(3) | RM(CX)); } else { gotthrow = true; } @@ -529,7 +514,6 @@ TEST(div64, test) { bool gotthrow, gotsigfpe; uint64_t i, j, k, w, x, a, b; uint64_t quotient, remainder; - m->xedd->op.rde = REXW | MOD(3) | RM(CX); for (i = 0; i < ARRAYLEN(A); ++i) { for (j = 0; j < ARRAYLEN(A); ++j) { for (k = 0; k < ARRAYLEN(A); ++k) { @@ -538,7 +522,7 @@ TEST(div64, test) { memcpy(m->cx, &A[k], 8); if (!setjmp(m->onhalt)) { gotthrow = false; - OpDivRdxRaxEvqpUnsigned(m); + OpDivRdxRaxEvqpUnsigned(m, REXW | MOD(3) | RM(CX)); } else { gotthrow = true; } diff --git a/test/tool/build/lib/modrm_test.c b/test/tool/build/lib/modrm_test.c index 4a63a2fd..89faba18 100644 --- a/test/tool/build/lib/modrm_test.c +++ b/test/tool/build/lib/modrm_test.c @@ -34,7 +34,7 @@ TEST(modrm, testAddressSizeOverride_isNotPresent_keepsWholeExpression) { Write64(m->ax, 0xffffffff); xed_decoded_inst_zero_set_mode(xedd, XED_MACHINE_MODE_LONG_64); 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) { @@ -46,7 +46,7 @@ TEST(modrm, testAddressSizeOverride_isPresent_modulesWholeExpression) { Write64(m->ax, 0xffffffff); xed_decoded_inst_zero_set_mode(xedd, XED_MACHINE_MODE_LONG_64); 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) { @@ -58,7 +58,8 @@ TEST(modrm, testOverflow_doesntTriggerTooling) { Write64(m->ax, 0x7fffffffffffffff); xed_decoded_inst_zero_set_mode(xedd, XED_MACHINE_MODE_LONG_64); 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) { @@ -74,16 +75,16 @@ TEST(modrm, testPuttingOnTheRiz) { Write64(m->bp, 0x200000002); 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]))); - 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); 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); 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); 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) { @@ -101,5 +102,5 @@ TEST(modrm, testSibIndexOnly) { Write64(m->cx, 0x123); xed_decoded_inst_zero_set_mode(xedd, XED_MACHINE_MODE_LONG_64); 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)); } diff --git a/third_party/compiler_rt/divmodti4.c b/third_party/compiler_rt/divmodti4.c index 4816b8e1..643ce06f 100644 --- a/third_party/compiler_rt/divmodti4.c +++ b/third_party/compiler_rt/divmodti4.c @@ -24,7 +24,7 @@ COMPILER_RT_ABI ti_int __divmodti4(ti_int a, ti_int b, tu_int *opt_out_rem) { tu_int r; ti_int sa, sb, sq, sr, x, y, q; 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; x = 1 / x; // raise(SIGFPE) } diff --git a/third_party/xed/x86.h b/third_party/xed/x86.h index cadc587f..07c8d267 100644 --- a/third_party/xed/x86.h +++ b/third_party/xed/x86.h @@ -493,16 +493,15 @@ forceinline void xed_set_chip_modes(struct XedDecodedInst *d, extern const char kXedErrorNames[]; 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 *, 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_test_chip_features(struct XedChipFeatures *, enum XedIsaSet); void xed_get_chip_features(struct XedChipFeatures *, enum XedChip); -struct XedDecodedInst *xed_decoded_inst_zero_set_mode(struct XedDecodedInst *, - enum XedMachineMode); COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/third_party/xed/x86ild.greg.c b/third_party/xed/x86ild.greg.c index aa70b71a..75d1a394 100644 --- a/third_party/xed/x86ild.greg.c +++ b/third_party/xed/x86ild.greg.c @@ -375,19 +375,16 @@ privileged static void XED_LF_SIMM8_IMM_WIDTH_CONST_l2( privileged static void XED_LF_UIMM16_IMM_WIDTH_CONST_l2( struct XedDecodedInst *x) { x->op.imm_width = 16; - x->op.imm_signed = false; } privileged static void XED_LF_SE_IMM8_IMM_WIDTH_CONST_l2( struct XedDecodedInst *x) { x->op.imm_width = 8; - x->op.imm_signed = false; } privileged static void XED_LF_UIMM32_IMM_WIDTH_CONST_l2( struct XedDecodedInst *x) { x->op.imm_width = 32; - x->op.imm_signed = false; } 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]) { x->op.imm_width = 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( struct XedDecodedInst *x) { x->op.imm_width = 8; - x->op.imm_signed = false; } privileged static void XED_LF_0_IMM_WIDTH_CONST_l2(struct XedDecodedInst *x) { x->op.imm_width = 0; - x->op.imm_signed = false; } 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. */ -struct XedDecodedInst *xed_decoded_inst_zero_set_mode( +privileged struct XedDecodedInst *xed_decoded_inst_zero_set_mode( struct XedDecodedInst *p, enum XedMachineMode mmode) { __builtin_memset(p, 0, sizeof(*p)); xed_operands_set_mode(&p->op, mmode); diff --git a/tool/build/emucrt/emucrt.S b/tool/build/emucrt/emucrt.S index 0ab49c92..525c06a7 100644 --- a/tool/build/emucrt/emucrt.S +++ b/tool/build/emucrt/emucrt.S @@ -19,8 +19,6 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/macros.h" - cmpxchg %ecx,(%rdx) - .section .start,"ax",@progbits emucrt: bofram 9f movslq (%rsp),%rdi # argc diff --git a/tool/build/emucrt/emucrt.lds b/tool/build/emucrt/emucrt.lds index b35f07d8..d67c0c03 100644 --- a/tool/build/emucrt/emucrt.lds +++ b/tool/build/emucrt/emucrt.lds @@ -22,7 +22,7 @@ ENTRY(_start) SECTIONS { - .text : { + .text IMAGE_BASE_VIRTUAL : { *(.start) KEEP(*(.initprologue)) KEEP(*(SORT_BY_NAME(.init.*))) diff --git a/tool/build/emucrt/emucrt.mk b/tool/build/emucrt/emucrt.mk index 99c3510a..84d3248a 100644 --- a/tool/build/emucrt/emucrt.mk +++ b/tool/build/emucrt/emucrt.mk @@ -5,7 +5,7 @@ PKGS += TOOL_BUILD_EMUCRT TOOL_BUILD_EMUCRT = \ 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 o/$(MODE)/tool/build/emucrt: \ diff --git a/tool/build/emulator.c b/tool/build/emulator.c index c96f38b3..cb6b7362 100644 --- a/tool/build/emulator.c +++ b/tool/build/emulator.c @@ -21,6 +21,7 @@ #include "libc/alg/arraylist2.h" #include "libc/bits/safemacros.h" #include "libc/calls/calls.h" +#include "libc/calls/ioctl.h" #include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/stat.h" #include "libc/calls/struct/termios.h" @@ -51,6 +52,7 @@ #include "libc/sysv/consts/o.h" #include "libc/sysv/consts/poll.h" #include "libc/sysv/consts/prot.h" +#include "libc/sysv/consts/sa.h" #include "libc/sysv/consts/sig.h" #include "libc/sysv/consts/termios.h" #include "libc/unicode/unicode.h" @@ -61,6 +63,7 @@ #include "tool/build/lib/case.h" #include "tool/build/lib/dis.h" #include "tool/build/lib/endian.h" +#include "tool/build/lib/fds.h" #include "tool/build/lib/flags.h" #include "tool/build/lib/fpu.h" #include "tool/build/lib/loader.h" @@ -69,6 +72,7 @@ #include "tool/build/lib/modrm.h" #include "tool/build/lib/panel.h" #include "tool/build/lib/pml4t.h" +#include "tool/build/lib/pty.h" #include "tool/build/lib/stats.h" #include "tool/build/lib/throw.h" @@ -103,6 +107,15 @@ PERFORMANCE\n\ \n\ 1500 MIPS w/ NOP loop\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" #define DUMPWIDTH 64 @@ -115,8 +128,9 @@ PERFORMANCE\n\ #define FINISH 0x020 #define FAILURE 0x040 #define WINCHED 0x080 -#define CTRLC 0x100 +#define INT 0x100 #define QUIT 0x200 +#define EXIT 0x400 #define CTRL(C) ((C) ^ 0100) #define ALT(C) (('\e' << 010) | (C)) @@ -131,6 +145,8 @@ struct Panels { struct Panel maps; struct Panel tracehr; struct Panel trace; + struct Panel terminalhr; + struct Panel terminal; struct Panel registers; struct Panel ssehr; struct Panel sse; @@ -143,7 +159,7 @@ struct Panels { struct Panel stackhr; struct Panel stack; }; - struct Panel p[18]; + struct Panel p[20]; }; }; @@ -164,6 +180,7 @@ static bool colorize; static long codesize; static long ssewidth; static char *codepath; +static void *onbusted; static unsigned focus; static unsigned opline; static bool printstats; @@ -178,11 +195,15 @@ static int64_t writestart; static int64_t stackstart; static struct DisHigh high; static struct Machine m[2]; +static struct MachinePty *pty; static char logpath[PATH_MAX]; static char systemfailure[128]; static struct sigaction oldsig[4]; static struct Breakpoints breakpoints; +static void SetupDraw(void); +static void Redraw(void); + static uint64_t SignExtend(uint64_t x, uint8_t b) { uint64_t s; 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) { + LOGF("OnBusted"); + CHECK(onbusted); + longjmp(onbusted, 1); +} + +static int VirtualBing(int64_t v) { + int rc; uint8_t *p; + jmp_buf busted; + onbusted = busted; if ((p = FindReal(m, v))) { - return bing(p[0], 0); + if (!setjmp(busted)) { + rc = bing(p[0], 0); + } else { + rc = u'≀'; + } } else { - return c; + rc = u'⋅'; } + onbusted = NULL; + return rc; } static void ScrollOp(struct Panel *p, long op) { @@ -283,29 +319,36 @@ static void GetTtySize(void) { static void TuiRejuvinate(void) { GetTtySize(); ttyhidecursor(STDOUT_FILENO); - ttyraw(kTtySigs); + ttyraw(0); + xsigaction(SIGBUS, OnBusted, SA_NODEFER, 0, NULL); } 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) { + LOGF("OnWinch"); action |= WINCHED; } -static void OnGdbHandoff(void) { +static void OnCont(void) { + LOGF("OnCont"); TuiRejuvinate(); -} - -static void OnUsr1(void) { - if (g_logfile) fflush(g_logfile); + SetupDraw(); + Redraw(); } static void TuiCleanup(void) { sigaction(SIGWINCH, oldsig + 0, NULL); sigaction(SIGCONT, oldsig + 2, NULL); - sigaction(SIGUSR1, oldsig + 3, NULL); ttyraw((enum TtyRawFlags)(-1u)); ttyshowcursor(STDOUT_FILENO); CHECK_NE(-1, close(ttyfd)); @@ -329,7 +372,7 @@ static void ResolveBreakpoints(void) { static void BreakAtNextInstruction(void) { struct Breakpoint b = {.addr = m->ip + m->xedd->length, .oneshot = true}; - AddBreakpoint(&breakpoints, &b); + PushBreakpoint(&breakpoints, &b); } static void LoadSyms(void) { @@ -347,13 +390,23 @@ static void TuiSetup(void) { once = true; } CHECK_NE(-1, (ttyfd = open("/dev/tty", O_RDWR))); - xsigaction(SIGWINCH, (void *)OnWinch, 0, 0, oldsig + 0); - xsigaction(SIGCONT, (void *)OnGdbHandoff, 0, 0, oldsig + 2); - xsigaction(SIGUSR1, (void *)OnUsr1, 0, 0, oldsig + 3); + xsigaction(SIGWINCH, OnWinch, 0, 0, oldsig + 0); + xsigaction(SIGCONT, OnCont, SA_RESTART, 0, oldsig + 2); memcpy(&m[1], &m[0], sizeof(m[0])); 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) { if (0 <= line && line < p->bottom - p->top) { AppendStr(&p->lines[line], s); @@ -384,8 +437,8 @@ static int PickNumberOfXmmRegistersToShow(void) { } } -static void StartDraw(void) { - int i, j, n, a, b, cpuy, ssey, dx[2], c2y[2], c3y[5]; +static void SetupDraw(void) { + int i, j, n, a, b, cpuy, ssey, dx[2], c2y[3], c3y[5]; for (i = 0; i < ARRAYLEN(pan.p); ++i) { n = pan.p[i].bottom - pan.p[i].top; @@ -404,9 +457,11 @@ static void StartDraw(void) { dx[1] = txn >= a + b ? txn - a : txn; 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[1] = a * 2; + c2y[2] = a * 2 + b; a = (tyn - (cpuy + ssey) - 3) / 4; c3y[0] = cpuy; @@ -422,7 +477,7 @@ static void StartDraw(void) { pan.disassembly.bottom = tyn; pan.disassembly.right = dx[0]; - /* COLUMN #2: BREAKPOINTS, MEMORY MAPS, BACKTRACE */ + /* COLUMN #2: BREAKPOINTS, MEMORY MAPS, BACKTRACE, TERMINAL */ pan.breakpointshr.top = 0; pan.breakpointshr.left = dx[0]; @@ -451,9 +506,19 @@ static void StartDraw(void) { pan.trace.top = c2y[1] + 1; pan.trace.left = dx[0]; - pan.trace.bottom = tyn; + pan.trace.bottom = c2y[2]; 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 */ pan.registers.top = 0; @@ -517,6 +582,14 @@ static void StartDraw(void) { pan.p[i].lines = 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) { @@ -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, bool previous) { AppendPanel(p, i, " "); @@ -599,30 +679,14 @@ static void DrawHr(struct Panel *p, const char *s) { static void DrawCpu(struct Panel *p) { char buf[48]; - DrawRegister(p, 0, 7); - DrawRegister(p, 0, 0); - DrawSt(p, 0, 0); - DrawRegister(p, 1, 6); - DrawRegister(p, 1, 3); - DrawSt(p, 1, 1); - DrawRegister(p, 2, 2); - DrawRegister(p, 2, 5); - DrawSt(p, 2, 2); - DrawRegister(p, 3, 1); - DrawRegister(p, 3, 4); - DrawSt(p, 3, 3); - DrawRegister(p, 4, 8); - DrawRegister(p, 4, 12); - DrawSt(p, 4, 4); - DrawRegister(p, 5, 9); - DrawRegister(p, 5, 13); - DrawSt(p, 5, 5); - DrawRegister(p, 6, 10); - DrawRegister(p, 6, 14); - DrawSt(p, 6, 6); - DrawRegister(p, 7, 11); - DrawRegister(p, 7, 15); - DrawSt(p, 7, 7); + DrawRegister(p, 0, 7), DrawRegister(p, 0, 0), DrawSt(p, 0, 0); + DrawRegister(p, 1, 6), DrawRegister(p, 1, 3), DrawSt(p, 1, 1); + DrawRegister(p, 2, 2), DrawRegister(p, 2, 5), DrawSt(p, 2, 2); + DrawRegister(p, 3, 1), DrawRegister(p, 3, 4), DrawSt(p, 3, 3); + DrawRegister(p, 4, 8), DrawRegister(p, 4, 12), DrawSt(p, 4, 4); + DrawRegister(p, 5, 9), DrawRegister(p, 5, 13), DrawSt(p, 5, 5); + DrawRegister(p, 6, 10), DrawRegister(p, 6, 14), DrawSt(p, 6, 6); + DrawRegister(p, 7, 11), DrawRegister(p, 7, 15), DrawSt(p, 7, 7); snprintf(buf, sizeof(buf), "RIP 0x%016x FLG", m[0].ip); AppendPanel(p, 8, buf); 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); for (j = 0; j < DUMPWIDTH; ++j) { k = (beg + i) * DUMPWIDTH + j; - c = VirtualBing(k, L'⋅'); + c = VirtualBing(k); changed = a <= k && k < b; if (changed && !high) { high = true; @@ -800,7 +864,7 @@ static void DrawBreakpoints(struct Panel *p) { char buf[128]; const char *name; 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; addr = breakpoints.p[i].addr; sym = DisFindSym(dis, addr); @@ -885,7 +949,14 @@ forceinline void CheckFramePointer(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); + DrawTerminal(&pan.terminal); DrawCpu(&pan.registers); DrawSse(&pan.sse); ScrollCode(&pan.code); @@ -895,6 +966,7 @@ static void Redraw(void) { DrawHr(&pan.breakpointshr, "BREAKPOINTS"); DrawHr(&pan.mapshr, "MAPS"); DrawHr(&pan.tracehr, m->bofram[0] ? "PROTECTED FRAMES" : "FRAMES"); + DrawHr(&pan.terminalhr, "TELETYPEWRITER"); DrawHr(&pan.ssehr, "SSE"); DrawHr(&pan.codehr, "CODE"); DrawHr(&pan.readhr, "READ"); @@ -908,9 +980,35 @@ static void Redraw(void) { DrawMemory(&pan.writedata, writestart, m->writeaddr, m->writeaddr + m->writesize); 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) { LOGF("%s", systemfailure); if (tuimode) { @@ -948,6 +1046,7 @@ static void OnSimdException(void) { } static void OnUndefinedInstruction(void) { + die(); strcpy(systemfailure, "UNDEFINED INSTRUCTION"); LaunchDebuggerReactively(); } @@ -968,6 +1067,11 @@ static void OnFpuException(void) { LaunchDebuggerReactively(); } +static void OnExit(int rc) { + exitcode = rc; + action |= EXIT; +} + static void OnHalt(int interrupt) { switch (interrupt) { case 1: @@ -998,8 +1102,7 @@ static void OnHalt(int interrupt) { case kMachineExit: case kMachineHalt: default: - exitcode = interrupt; - action |= QUIT; + OnExit(interrupt); break; } } @@ -1134,7 +1237,7 @@ static void ReadKeyboard(void) { if ((rc = read(ttyfd, b, 16)) != -1) { for (n = rc, i = 0; i < n; ++i) { switch (b[i++]) { - CASE('q', OnQuit()); + CASE('q', OnQ()); CASE('s', OnStep()); CASE('n', OnNext()); CASE('f', OnFinish()); @@ -1145,9 +1248,14 @@ static void ReadKeyboard(void) { CASE('w', OnSseWidth()); CASE('u', OnUp()); CASE('d', OnDown()); + CASE('B', PopBreakpoint(&breakpoints)); CASE('\t', OnTab()); CASE('\r', 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('P'), OnUpArrow()); CASE(CTRL('N'), OnDownArrow()); @@ -1215,8 +1323,13 @@ static void ReadKeyboard(void) { break; } } + } else if (errno == EINTR) { + LOGF("ReadKeyboard Interrupted"); + } else if (errno == EAGAIN) { + poll((struct pollfd[]){{ttyfd, POLLIN}}, 1, -1); } else { - CHECK_EQ(EINTR, errno); + perror("ReadKeyboard"); + exit(1); } } @@ -1240,7 +1353,7 @@ static void HandleBreakpointFlag(const char *s) { } else { b.symbol = optarg; } - AddBreakpoint(&breakpoints, &b); + PushBreakpoint(&breakpoints, &b); } 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)); } +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[]) { int opt; stpcpy(stpcpy(stpcpy(logpath, kTmpPath), basename(argv[0])), ".log"); while ((opt = getopt(argc, argv, "?hvtrsb:HL:")) != -1) { switch (opt) { case 't': - react = true; tuimode = true; break; case 'r': @@ -1288,166 +1558,44 @@ static void GetOpts(int argc, char *argv[]) { } } g_logfile = fopen(logpath, "a"); + setvbuf(g_logfile, xmalloc(PAGESIZE), _IOLBF, PAGESIZE); } int Emulator(int argc, char *argv[]) { - long op; void *code; - ssize_t bp; - int rc, fd, interrupt; - + int rc, fd; codepath = argv[optind++]; - + pty = MachinePtyNew(20, 80); + InitMachine(m); + m->fds.p = xcalloc((m->fds.n = 8), sizeof(struct MachineFd)); Restart: action = 0; LoadProgram(m, codepath, argv + optind, environ, elf); - - if (!tuimode && breakpoints.i) { - LoadSyms(); - ResolveBreakpoints(); - } - - while (!(action & QUIT)) { + m->fds.i = 3; + m->fds.p[0].fd = STDIN_FILENO; + m->fds.p[0].cb = &kMachineFdCbPty; + m->fds.p[1].fd = STDOUT_FILENO; + m->fds.p[1].cb = &kMachineFdCbPty; + m->fds.p[2].fd = STDERR_FILENO; + m->fds.p[2].cb = &kMachineFdCbPty; + while (!(action & EXIT)) { if (!tuimode) { - if (!(interrupt = setjmp(m->onhalt))) { - 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 { - LOGF("CTRLC EXEC"); - } - 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); - } + Exec(); } 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) { - LOGF("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(); + Tui(); + } + if (action & RESTART) { + goto Restart; } } - if (tuimode) { LeaveScreen(); } - if (printstats) { fprintf(stderr, "taken: %,ld\n", taken); fprintf(stderr, "ntaken: %,ld\n", ntaken); fprintf(stderr, "ops: %,ld\n", ops); } - munmap(elf->ehdr, elf->size); DisFree(dis); return exitcode; @@ -1462,8 +1610,7 @@ static void OnlyRunOnFirstCpu(void) { int main(int argc, char *argv[]) { int rc; ssewidth = 2; /* 16-bit is best bit */ - showcrashreports(); - xsigaction(SIGINT, (void *)OnCtrlC, 0, 0, NULL); + if (!NoDebug()) showcrashreports(); // OnlyRunOnFirstCpu(); if ((colorize = cancolor())) { high.keyword = 155; diff --git a/tool/build/lib/alu.h b/tool/build/lib/alu.h index e93b258d..c09e71ea 100644 --- a/tool/build/lib/alu.h +++ b/tool/build/lib/alu.h @@ -12,8 +12,6 @@ #define ALU_CMP 7 #define ALU_TEST 8 #define ALU_FLIP 16 -#define ALU_XCHG 64 -#define ALU_BYTE 128 #define BSU_ROL 0 #define BSU_ROR 1 @@ -27,8 +25,8 @@ #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ -typedef uint64_t (*aluop1_f)(struct Machine *, uint64_t); -typedef uint64_t (*aluop2_f)(struct Machine *, uint64_t, uint64_t); +typedef uint64_t (*aluop1_f)(struct Machine *, uint32_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 Bsu(int, int, uint64_t, uint64_t, uint32_t *); diff --git a/tool/build/lib/bitscan.c b/tool/build/lib/bitscan.c index 072c584d..51bbb1d2 100644 --- a/tool/build/lib/bitscan.c +++ b/tool/build/lib/bitscan.c @@ -22,14 +22,14 @@ #include "tool/build/lib/machine.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; - if (Rexw(m->xedd)) { + if (Rexw(rde)) { x &= 0xffffffffffffffff; m->flags = SetFlag(m->flags, FLAGS_ZF, !x); if (!x) return 0; return 63 ^ __builtin_clzll(x); - } else if (!Osz(m->xedd)) { + } else if (!Osz(rde)) { x &= 0xffffffff; m->flags = SetFlag(m->flags, FLAGS_ZF, !x); 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; - if (Rexw(m->xedd)) { + if (Rexw(rde)) { x &= 0xffffffffffffffff; m->flags = SetFlag(m->flags, FLAGS_ZF, !x); if (!x) return 0; return __builtin_ctzll(x); - } else if (!Osz(m->xedd)) { + } else if (!Osz(rde)) { x &= 0xffffffff; m->flags = SetFlag(m->flags, FLAGS_ZF, !x); 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_CF, false); m->flags = SetFlag(m->flags, FLAGS_SF, false); diff --git a/tool/build/lib/bitscan.h b/tool/build/lib/bitscan.h index d13500aa..95ae962f 100644 --- a/tool/build/lib/bitscan.h +++ b/tool/build/lib/bitscan.h @@ -4,9 +4,9 @@ #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ -uint64_t AluBsr(struct Machine *, uint64_t, uint64_t); -uint64_t AluBsf(struct Machine *, uint64_t, uint64_t); -uint64_t AluPopcnt(struct Machine *, uint64_t, uint64_t); +uint64_t AluBsr(struct Machine *, uint32_t, uint64_t, uint64_t); +uint64_t AluBsf(struct Machine *, uint32_t, uint64_t, uint64_t); +uint64_t AluPopcnt(struct Machine *, uint32_t, uint64_t, uint64_t); COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/tool/build/lib/breakpoint.c b/tool/build/lib/breakpoint.c index 2b64a15f..434d0869 100644 --- a/tool/build/lib/breakpoint.c +++ b/tool/build/lib/breakpoint.c @@ -21,7 +21,13 @@ #include "libc/assert.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; for (i = 0; i < bps->i; ++i) { if (bps->p[i].disable) { diff --git a/tool/build/lib/breakpoint.h b/tool/build/lib/breakpoint.h index 340018a6..24e16d39 100644 --- a/tool/build/lib/breakpoint.h +++ b/tool/build/lib/breakpoint.h @@ -14,7 +14,8 @@ struct Breakpoints { }; 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_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/tool/build/lib/buffer.c b/tool/build/lib/buffer.c index 5bf5aaab..048c63b2 100644 --- a/tool/build/lib/buffer.c +++ b/tool/build/lib/buffer.c @@ -17,6 +17,7 @@ │ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │ │ 02110-1301 USA │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "dsp/tty/tty.h" #include "libc/alg/arraylist2.h" #include "libc/calls/calls.h" #include "libc/fmt/fmt.h" @@ -57,12 +58,5 @@ void AppendFmt(struct Buffer *b, const char *fmt, ...) { * Writes buffer until completion, interrupt, or error occurs. */ ssize_t WriteBuffer(struct Buffer *b, int fd) { - size_t 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; + return ttywrite(fd, b->p, b->i); } diff --git a/tool/build/lib/buildlib.mk b/tool/build/lib/buildlib.mk index 9a70f79b..60516f4c 100644 --- a/tool/build/lib/buildlib.mk +++ b/tool/build/lib/buildlib.mk @@ -25,6 +25,7 @@ TOOL_BUILD_LIB_A_OBJS = \ $(TOOL_BUILD_LIB_A_SRCS_C:%.c=o/$(MODE)/%.o) TOOL_BUILD_LIB_A_DIRECTDEPS = \ + DSP_TTY \ LIBC_ALG \ LIBC_BITS \ LIBC_CONV \ diff --git a/tool/build/lib/cvt.c b/tool/build/lib/cvt.c index f694df3e..51839d4c 100644 --- a/tool/build/lib/cvt.c +++ b/tool/build/lib/cvt.c @@ -26,287 +26,287 @@ #include "tool/build/lib/modrm.h" #include "tool/build/lib/throw.h" -static void OpGdqpWssCvttss2si(struct Machine *m) { +static void OpGdqpWssCvttss2si(struct Machine *m, uint32_t rde) { float f; int64_t n; - memcpy(&f, GetModrmRegisterXmmPointerRead4(m), 4); + memcpy(&f, GetModrmRegisterXmmPointerRead4(m, rde), 4); n = f; - if (!Rexw(m->xedd)) n &= 0xffffffff; - Write64(RegRexrReg(m), n); + if (!Rexw(rde)) n &= 0xffffffff; + Write64(RegRexrReg(m, rde), n); } -static void OpGdqpWsdCvttsd2si(struct Machine *m) { +static void OpGdqpWsdCvttsd2si(struct Machine *m, uint32_t rde) { double d; int64_t n; - memcpy(&d, GetModrmRegisterXmmPointerRead8(m), 8); + memcpy(&d, GetModrmRegisterXmmPointerRead8(m, rde), 8); n = d; - if (!Rexw(m->xedd)) n &= 0xffffffff; - Write64(RegRexrReg(m), n); + if (!Rexw(rde)) n &= 0xffffffff; + Write64(RegRexrReg(m, rde), n); } -static void OpGdqpWssCvtss2si(struct Machine *m) { +static void OpGdqpWssCvtss2si(struct Machine *m, uint32_t rde) { float f; int64_t n; - memcpy(&f, GetModrmRegisterXmmPointerRead4(m), 4); + memcpy(&f, GetModrmRegisterXmmPointerRead4(m, rde), 4); n = rintf(f); - if (!Rexw(m->xedd)) n &= 0xffffffff; - Write64(RegRexrReg(m), n); + if (!Rexw(rde)) n &= 0xffffffff; + Write64(RegRexrReg(m, rde), n); } -static void OpGdqpWsdCvtsd2si(struct Machine *m) { +static void OpGdqpWsdCvtsd2si(struct Machine *m, uint32_t rde) { double d; int64_t n; - memcpy(&d, GetModrmRegisterXmmPointerRead8(m), 8); + memcpy(&d, GetModrmRegisterXmmPointerRead8(m, rde), 8); n = nearbyint(d); - if (!Rexw(m->xedd)) n &= 0xffffffff; - Write64(RegRexrReg(m), n); + if (!Rexw(rde)) n &= 0xffffffff; + Write64(RegRexrReg(m, rde), n); } -static void OpVssEdqpCvtsi2ss(struct Machine *m) { +static void OpVssEdqpCvtsi2ss(struct Machine *m, uint32_t rde) { float f; int64_t n; uint8_t *p; - if (Rexw(m->xedd)) { - n = (int64_t)Read64(GetModrmRegisterWordPointerRead8(m)); + if (Rexw(rde)) { + n = (int64_t)Read64(GetModrmRegisterWordPointerRead8(m, rde)); } else { - n = (int32_t)Read32(GetModrmRegisterWordPointerRead4(m)); + n = (int32_t)Read32(GetModrmRegisterWordPointerRead4(m, rde)); } 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; int64_t n; uint8_t *p; - if (Rexw(m->xedd)) { - n = (int64_t)Read64(GetModrmRegisterWordPointerRead8(m)); + if (Rexw(rde)) { + n = (int64_t)Read64(GetModrmRegisterWordPointerRead8(m, rde)); } else { - n = (int32_t)Read32(GetModrmRegisterWordPointerRead4(m)); + n = (int32_t)Read32(GetModrmRegisterWordPointerRead4(m, rde)); } 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; float f[2]; int32_t i[2]; - p = GetModrmRegisterMmPointerRead8(m); + p = GetModrmRegisterMmPointerRead8(m, rde); i[0] = Read32(p + 0); i[1] = Read32(p + 4); f[0] = i[0]; 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; double f[2]; int32_t n[2]; - p = GetModrmRegisterMmPointerRead8(m); + p = GetModrmRegisterMmPointerRead8(m, rde); n[0] = Read32(p + 0); n[1] = Read32(p + 4); f[0] = n[0]; 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]; int32_t n[2]; - memcpy(f, GetModrmRegisterXmmPointerRead8(m), 8); + memcpy(f, GetModrmRegisterXmmPointerRead8(m, rde), 8); n[0] = nearbyintf(f[0]); n[1] = nearbyintf(f[1]); - Write32(MmReg(m) + 0, n[0]); - Write32(MmReg(m) + 4, n[1]); + Write32(MmReg(m, rde) + 0, n[0]); + 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]; int32_t n[2]; - memcpy(&f, GetModrmRegisterXmmPointerRead8(m), 8); + memcpy(&f, GetModrmRegisterXmmPointerRead8(m, rde), 8); n[0] = f[0]; n[1] = f[1]; - Write32(MmReg(m) + 0, n[0]); - Write32(MmReg(m) + 4, n[1]); + Write32(MmReg(m, rde) + 0, n[0]); + 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]; int32_t n[2]; - memcpy(d, GetModrmRegisterXmmPointerRead16(m), 16); + memcpy(d, GetModrmRegisterXmmPointerRead16(m, rde), 16); n[0] = nearbyint(d[0]); n[1] = nearbyint(d[1]); - Write32(MmReg(m) + 0, n[0]); - Write32(MmReg(m) + 4, n[1]); + Write32(MmReg(m, rde) + 0, n[0]); + 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]; int32_t n[2]; - memcpy(&d, GetModrmRegisterXmmPointerRead16(m), 16); + memcpy(&d, GetModrmRegisterXmmPointerRead16(m, rde), 16); n[0] = d[0]; n[1] = d[1]; - Write32(MmReg(m) + 0, n[0]); - Write32(MmReg(m) + 4, n[1]); + Write32(MmReg(m, rde) + 0, n[0]); + 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]; double d[2]; - memcpy(f, GetModrmRegisterXmmPointerRead8(m), 8); + memcpy(f, GetModrmRegisterXmmPointerRead8(m, rde), 8); d[0] = f[0]; 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]; double d[2]; - memcpy(d, GetModrmRegisterXmmPointerRead16(m), 16); + memcpy(d, GetModrmRegisterXmmPointerRead16(m, rde), 16); f[0] = d[0]; 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; double d; - memcpy(&d, GetModrmRegisterXmmPointerRead8(m), 8); + memcpy(&d, GetModrmRegisterXmmPointerRead8(m, rde), 8); 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; double d; - memcpy(&f, GetModrmRegisterXmmPointerRead4(m), 4); + memcpy(&f, GetModrmRegisterXmmPointerRead4(m, rde), 4); 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; float f[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]; - 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; double d[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]; - 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; float f[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]; - 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; float f[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]); - 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; double d[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]; - 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; double d[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]); - memcpy(XmmRexrReg(m), n, 8); + memcpy(XmmRexrReg(m, rde), n, 8); } -void OpCvt(struct Machine *m, unsigned long op) { - switch (op | Rep(m->xedd) | Osz(m->xedd)) { +void OpCvt(struct Machine *m, uint32_t rde, unsigned long op) { + switch (op | Rep(rde) | Osz(rde)) { case kOpCvt0f2a + 0: - OpVpsQpiCvtpi2ps(m); + OpVpsQpiCvtpi2ps(m, rde); break; case kOpCvt0f2a + 1: - OpVpdQpiCvtpi2pd(m); + OpVpdQpiCvtpi2pd(m, rde); break; case kOpCvt0f2a + 2: - OpVsdEdqpCvtsi2sd(m); + OpVsdEdqpCvtsi2sd(m, rde); break; case kOpCvt0f2a + 3: - OpVssEdqpCvtsi2ss(m); + OpVssEdqpCvtsi2ss(m, rde); break; case kOpCvtt0f2c + 0: - OpPpiWpsqCvttps2pi(m); + OpPpiWpsqCvttps2pi(m, rde); break; case kOpCvtt0f2c + 1: - OpPpiWpdCvttpd2pi(m); + OpPpiWpdCvttpd2pi(m, rde); break; case kOpCvtt0f2c + 2: - OpGdqpWsdCvttsd2si(m); + OpGdqpWsdCvttsd2si(m, rde); break; case kOpCvtt0f2c + 3: - OpGdqpWssCvttss2si(m); + OpGdqpWssCvttss2si(m, rde); break; case kOpCvt0f2d + 0: - OpPpiWpsqCvtps2pi(m); + OpPpiWpsqCvtps2pi(m, rde); break; case kOpCvt0f2d + 1: - OpPpiWpdCvtpd2pi(m); + OpPpiWpdCvtpd2pi(m, rde); break; case kOpCvt0f2d + 2: - OpGdqpWsdCvtsd2si(m); + OpGdqpWsdCvtsd2si(m, rde); break; case kOpCvt0f2d + 3: - OpGdqpWssCvtss2si(m); + OpGdqpWssCvtss2si(m, rde); break; case kOpCvt0f5a + 0: - OpVpdWpsCvtps2pd(m); + OpVpdWpsCvtps2pd(m, rde); break; case kOpCvt0f5a + 1: - OpVpsWpdCvtpd2ps(m); + OpVpsWpdCvtpd2ps(m, rde); break; case kOpCvt0f5a + 2: - OpVssWsdCvtsd2ss(m); + OpVssWsdCvtsd2ss(m, rde); break; case kOpCvt0f5a + 3: - OpVsdWssCvtss2sd(m); + OpVsdWssCvtss2sd(m, rde); break; case kOpCvt0f5b + 0: - OpVpsWdqCvtdq2ps(m); + OpVpsWdqCvtdq2ps(m, rde); break; case kOpCvt0f5b + 1: - OpVdqWpsCvtps2dq(m); + OpVdqWpsCvtps2dq(m, rde); break; case kOpCvt0f5b + 3: - OpVdqWpsCvttps2dq(m); + OpVdqWpsCvttps2dq(m, rde); break; case kOpCvt0fE6 + 1: - OpVdqWpdCvtpd2dq(m); + OpVdqWpdCvtpd2dq(m, rde); break; case kOpCvt0fE6 + 2: - OpVdqWpdCvttpd2dq(m); + OpVdqWpdCvttpd2dq(m, rde); break; case kOpCvt0fE6 + 3: - OpVpdWdqCvtdq2pd(m); + OpVpdWdqCvtdq2pd(m, rde); break; default: OpUd(m); diff --git a/tool/build/lib/cvt.h b/tool/build/lib/cvt.h index 88b19c8f..cb306d89 100644 --- a/tool/build/lib/cvt.h +++ b/tool/build/lib/cvt.h @@ -11,7 +11,7 @@ COSMOPOLITAN_C_START_ #define kOpCvt0f5b 16 #define kOpCvt0fE6 20 -void OpCvt(struct Machine *, unsigned long); +void OpCvt(struct Machine *, uint32_t, unsigned long); COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/tool/build/lib/dis.c b/tool/build/lib/dis.c index ad5e67e8..76a22e7e 100644 --- a/tool/build/lib/dis.c +++ b/tool/build/lib/dis.c @@ -33,6 +33,7 @@ #include "third_party/xed/x86.h" #include "tool/build/lib/case.h" #include "tool/build/lib/dis.h" +#include "tool/build/lib/memory.h" #include "tool/build/lib/modrm.h" #define ADDRLEN 8 diff --git a/tool/build/lib/disarg.c b/tool/build/lib/disarg.c index c31b1ded..45c4c72a 100644 --- a/tool/build/lib/disarg.c +++ b/tool/build/lib/disarg.c @@ -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) { - 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) { @@ -87,24 +87,25 @@ static char *DisComment(char *p, const char *s) { } 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) { - 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) { - 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) { - return DisRegister( - p, kRegisterName[0][Rexw(b.xedd)][Rexr(b.xedd)][ModrmReg(b.xedd)]); + return DisRegister(p, kRegisterName[0][Rexw(b.xedd->op.rde)][Rexr( + b.xedd->op.rde)][ModrmReg(b.xedd->op.rde)]); } 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) { @@ -154,30 +155,29 @@ static char *DisM(struct DisBuilder b, char *p) { p = DisRegister(p, seg); *p++ = ':'; } - if (ModrmMod(b.xedd) == 0b01 || ModrmMod(b.xedd) == 0b10 || - IsRipRelative(b.xedd) || - (ModrmMod(b.xedd) == 0b00 && ModrmRm(b.xedd) == 0b100 && - SibBase(b.xedd) == 0b101)) { + if (ModrmMod(b.xedd->op.rde) == 0b01 || ModrmMod(b.xedd->op.rde) == 0b10 || + IsRipRelative(b.xedd->op.rde) || + (ModrmMod(b.xedd->op.rde) == 0b00 && ModrmRm(b.xedd->op.rde) == 0b100 && + SibBase(b.xedd->op.rde) == 0b101)) { 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); } - if (!SibExists(b.xedd)) { + if (!SibExists(b.xedd->op.rde)) { DCHECK(!b.xedd->op.has_sib); - if (IsRipRelative(b.xedd)) { + if (IsRipRelative(b.xedd->op.rde)) { base = "rip"; } 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)) { - DCHECK(b.xedd->op.has_sib); - if (SibHasBase(b.xedd)) { - base = GetAddrReg(b, Rexb(b.xedd), SibBase(b.xedd)); + } else if (!SibIsAbsolute(b.xedd->op.rde)) { + if (SibHasBase(b.xedd->op.rde)) { + base = GetAddrReg(b, Rexb(b.xedd->op.rde), SibBase(b.xedd->op.rde)); } - if (SibHasIndex(b.xedd)) { - index = GetAddrReg(b, Rexx(b.xedd), SibIndex(b.xedd)); + if (SibHasIndex(b.xedd->op.rde)) { + index = GetAddrReg(b, Rexx(b.xedd->op.rde), SibIndex(b.xedd->op.rde)); } 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]; } @@ -198,25 +198,25 @@ static char *DisM(struct DisBuilder b, char *p) { } static char *DisEb(struct DisBuilder b, char *p) { - if (IsModrmRegister(b.xedd)) { - return DisRegisterByte(b, p, Rexb(b.xedd), ModrmRm(b.xedd)); + if (IsModrmRegister(b.xedd->op.rde)) { + return DisRegisterByte(b, p, Rexb(b.xedd->op.rde), ModrmRm(b.xedd->op.rde)); } else { return DisM(b, p); } } static char *DisEvqp(struct DisBuilder b, char *p) { - if (IsModrmRegister(b.xedd)) { - return DisRegisterWord(b, p, Rexb(b.xedd), ModrmRm(b.xedd)); + if (IsModrmRegister(b.xedd->op.rde)) { + return DisRegisterWord(b, p, Rexb(b.xedd->op.rde), ModrmRm(b.xedd->op.rde)); } else { return DisM(b, p); } } static char *DisEdqp(struct DisBuilder b, char *p) { - if (IsModrmRegister(b.xedd)) { - return DisRegister( - p, kRegisterName[0][Rexw(b.xedd)][Rexb(b.xedd)][ModrmRm(b.xedd)]); + if (IsModrmRegister(b.xedd->op.rde)) { + return DisRegister(p, kRegisterName[0][Rexw(b.xedd->op.rde)][Rexb( + b.xedd->op.rde)][ModrmRm(b.xedd->op.rde)]); } else { return DisM(b, p); } @@ -224,11 +224,11 @@ static char *DisEdqp(struct DisBuilder b, char *p) { static char *DisEvq(struct DisBuilder b, char *p) { const char *s; - if (IsModrmRegister(b.xedd)) { - if (Osz(b.xedd)) { - s = kRegisterName[1][0][Rexb(b.xedd)][ModrmRm(b.xedd)]; + if (IsModrmRegister(b.xedd->op.rde)) { + if (Osz(b.xedd->op.rde)) { + s = kRegisterName[1][0][Rexb(b.xedd->op.rde)][ModrmRm(b.xedd->op.rde)]; } 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); } else { @@ -237,47 +237,53 @@ static char *DisEvq(struct DisBuilder b, char *p) { } static char *DisEd(struct DisBuilder b, char *p) { - if (IsModrmRegister(b.xedd)) { - return DisRegister(p, kRegisterName[0][0][Rexb(b.xedd)][ModrmRm(b.xedd)]); + if (IsModrmRegister(b.xedd->op.rde)) { + return DisRegister( + p, kRegisterName[0][0][Rexb(b.xedd->op.rde)][ModrmRm(b.xedd->op.rde)]); } else { return DisM(b, p); } } static char *DisEq(struct DisBuilder b, char *p) { - if (IsModrmRegister(b.xedd)) { - return DisRegister(p, kRegisterName[0][1][Rexb(b.xedd)][ModrmRm(b.xedd)]); + if (IsModrmRegister(b.xedd->op.rde)) { + return DisRegister( + p, kRegisterName[0][1][Rexb(b.xedd->op.rde)][ModrmRm(b.xedd->op.rde)]); } else { return DisM(b, p); } } static char *DisZvq(struct DisBuilder b, char *p) { - if (Osz(b.xedd)) { - return DisRegister(p, kRegisterName[1][0][Rexb(b.xedd)][ModrmSrm(b.xedd)]); + if (Osz(b.xedd->op.rde)) { + return DisRegister( + p, kRegisterName[1][0][Rexb(b.xedd->op.rde)][ModrmSrm(b.xedd->op.rde)]); } 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) { - 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) { - 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) { - 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) { - 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) { - 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) { @@ -309,8 +315,8 @@ static char *DisAbs(struct DisBuilder b, char *p) { } static char *DisSw(struct DisBuilder b, char *p) { - if (kSegName[ModrmReg(b.xedd)][0]) { - p = DisRegister(p, kSegName[ModrmReg(b.xedd)]); + if (kSegName[ModrmReg(b.xedd->op.rde)][0]) { + p = DisRegister(p, kSegName[ModrmReg(b.xedd->op.rde)]); } *p = '\0'; return p; @@ -318,7 +324,7 @@ static char *DisSw(struct DisBuilder b, char *p) { static char *DisY(struct DisBuilder b, char *p) { *p++ = '('; - p = DisRegister(p, Asz(b.xedd) ? "edi" : "rdi"); + p = DisRegister(p, Asz(b.xedd->op.rde) ? "edi" : "rdi"); *p++ = ')'; *p = '\0'; return p; @@ -329,7 +335,7 @@ static char *DisX(struct DisBuilder b, char *p) { p = DisRegister(p, kSegOverride[b.xedd->op.seg_ovd]); } *p++ = '('; - p = DisRegister(p, Asz(b.xedd) ? "esi" : "rsi"); + p = DisRegister(p, Asz(b.xedd->op.rde) ? "esi" : "rsi"); *p++ = ')'; *p = '\0'; return p; @@ -340,7 +346,7 @@ static char *DisBBb(struct DisBuilder b, char *p) { p = DisRegister(p, kSegOverride[b.xedd->op.seg_ovd]); } *p++ = '('; - p = DisRegister(p, Asz(b.xedd) ? "ebx" : "rbx"); + p = DisRegister(p, Asz(b.xedd->op.rde) ? "ebx" : "rbx"); *p++ = ')'; *p = '\0'; 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); *p++ = '%'; 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); return 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) { - 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) { - 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) { - 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) { - 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) { - if (IsModrmRegister(b.xedd)) { + if (IsModrmRegister(b.xedd->op.rde)) { return DisNq(b, p); } else { return DisM(b, p); @@ -385,9 +391,9 @@ static char *DisQq(struct DisBuilder b, char *p) { static char *DisEst(struct DisBuilder b, char *p) { p = DisRegister(p, "st"); - if (ModrmRm(b.xedd) != 0) { + if (ModrmRm(b.xedd->op.rde) != 0) { *p++ = '('; - *p++ = '0' + ModrmRm(b.xedd); + *p++ = '0' + ModrmRm(b.xedd->op.rde); *p++ = ')'; *p = '\0'; } @@ -395,7 +401,7 @@ static char *DisEst(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); } else { *p = '\0'; @@ -404,7 +410,7 @@ static char *DisEst1(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); } else { return DisM(b, p); @@ -412,7 +418,7 @@ static char *DisEssr(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); } else { return DisM(b, p); diff --git a/tool/build/lib/disinst.c b/tool/build/lib/disinst.c index 19095004..0fd8c72e 100644 --- a/tool/build/lib/disinst.c +++ b/tool/build/lib/disinst.c @@ -20,7 +20,6 @@ #include "libc/log/check.h" #include "libc/nexgen32e/tinystrcmp.h" #include "libc/str/str.h" -#include "tool/build/lib/case.h" #include "tool/build/lib/dis.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", "shl", "shr", "sal", "sar"}; +static bool IsProbablyByteOp(struct XedDecodedInst *x) { + return !(x->op.opcode & 1); +} + static int IsRepOpcode(struct DisBuilder b) { switch (b.xedd->op.opcode & ~1u) { - CASE(0x6C /*INS */, return 1); - CASE(0x6E /*OUTS*/, return 1); - CASE(0xA4 /*MOVS*/, return 1); - CASE(0xAA /*STOS*/, return 1); - CASE(0xAC /*LODS*/, return 1); - CASE(0xA6 /*CMPS*/, return 2); - CASE(0xAE /*SCAS*/, return 2); + case 0x6C: /* INS */ + return 1; + case 0x6E: /* OUTS */ + return 1; + case 0xA4: /* MOVS */ + return 1; + case 0xAA: /* STOS */ + return 1; + case 0xAC: /* LODS */ + return 1; + case 0xA6: /* CMPS */ + return 2; + case 0xAE: /* SCAS */ + return 2; default: return 0; } @@ -45,7 +55,7 @@ static int IsRepOpcode(struct DisBuilder b) { static char *DisRepPrefix(struct DisBuilder b, char *p) { 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)) { case 0: break; @@ -53,7 +63,7 @@ static char *DisRepPrefix(struct DisBuilder b, char *p) { p = stpcpy(p, "rep "); break; case 2: - p = stpcpy(p, Rep(b.xedd) == 2 ? "repnz " : "repz "); + p = stpcpy(p, Rep(b.xedd->op.rde) == 2 ? "repnz " : "repz "); break; default: 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 "); p = DisRepPrefix(b, p); 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) { p = stpcpy(p, "call"); } else if (tinystrcmp(name, "JMP") == 0) { p = stpcpy(p, "jmp"); } 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); } 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); } 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); } 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); } else if (tinystrcmp(name, "cwtl") == 0) { - if (Osz(b.xedd)) name = "cbtw"; - if (Rexw(b.xedd)) name = "cltq"; + if (Osz(b.xedd->op.rde)) name = "cbtw"; + if (Rexw(b.xedd->op.rde)) name = "cltq"; p = stpcpy(p, name); } else if (tinystrcmp(name, "cltd") == 0) { - if (Osz(b.xedd)) name = "cwtd"; - if (Rexw(b.xedd)) name = "cqto"; + if (Osz(b.xedd->op.rde)) name = "cwtd"; + if (Rexw(b.xedd->op.rde)) name = "cqto"; p = stpcpy(p, name); } else { notbyte = false; @@ -115,7 +125,7 @@ static char *DisName(struct DisBuilder b, char *bp, const char *name, *p++ = *np; } 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) { notbyte = true; wantsuffix = true; @@ -130,21 +140,21 @@ static char *DisName(struct DisBuilder b, char *bp, const char *name, notbyte = true; wantsuffixsd = true; } 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) { p = DisBranchTaken(b, p); } if (wantsuffixsd) { - if (Osz(b.xedd)) { + if (Osz(b.xedd->op.rde)) { *p++ = 'd'; } else { *p++ = 's'; } } else if (wantsuffix || (ambiguous && !startswith(name, "f") && !startswith(name, "set"))) { - if (Osz(b.xedd)) { + if (Osz(b.xedd->op.rde)) { *p++ = 'w'; - } else if (Rexw(b.xedd)) { + } else if (Rexw(b.xedd->op.rde)) { *p++ = 'q'; } else if (ambiguous && !notbyte && IsProbablyByteOp(b.xedd)) { *p++ = 'b'; @@ -169,11 +179,12 @@ char *DisInst(struct DisBuilder b, char *p, const char *spec) { char args[4][64]; char *s, *name, *state; bool hasarg, hasmodrm, hasregister, hasmemory; + CHECK_EQ(0, (int)b.xedd->op.error); DCHECK_LT(strlen(spec), 128); hasarg = false; hasmodrm = b.xedd->op.has_modrm; - hasmemory = hasmodrm && !IsModrmRegister(b.xedd); - hasregister = hasmodrm && IsModrmRegister(b.xedd); + hasmemory = hasmodrm && !IsModrmRegister(b.xedd->op.rde); + hasregister = hasmodrm && IsModrmRegister(b.xedd->op.rde); name = strtok_r(strcpy(sbuf, spec), " ", &state); for (n = 0; (s = strtok_r(NULL, " ", &state)); ++n) { hasarg = true; diff --git a/tool/build/lib/disspec.c b/tool/build/lib/disspec.c index 2a5adcc1..5c0684b0 100644 --- a/tool/build/lib/disspec.c +++ b/tool/build/lib/disspec.c @@ -38,18 +38,18 @@ static const char kFpuName[][8][8] = { char *DisOpFpu0(struct XedDecodedInst *x, int group) { const char *s; - s = kFpuName[group][ModrmRm(x)]; + s = kFpuName[group][ModrmRm(x->op.rde)]; return *s ? s : UNKNOWN; } char *DisOpFpu1(struct XedDecodedInst *x, char *p, const char *extra) { - stpcpy(stpcpy(p, kFpuName[0][ModrmReg(x)]), extra); + stpcpy(stpcpy(p, kFpuName[0][ModrmReg(x->op.rde)]), extra); return p; } char *DisOp66(struct XedDecodedInst *x, char *p, const char *s, const char *a, const char *b) { - stpcpy(stpcpy(p, s), !Osz(x) ? a : b); + stpcpy(stpcpy(p, s), !Osz(x->op.rde) ? a : b); return p; } @@ -76,11 +76,11 @@ char *DisOpNqIbUdqIb(struct XedDecodedInst *x, char *p, const char *s) { char *DisOpVpsWpsVssWssVpdWpdVsdWsd(struct XedDecodedInst *x, char *p, const char *s) { char *q = stpcpy(p, s); - if (x->op.ild_f3) { + if (Rep(x->op.rde) == 3) { stpcpy(q, "ss %Vss Wss"); - } else if (x->op.ild_f2) { + } else if (Rep(x->op.rde) == 2) { stpcpy(q, "sd %Vsd Wsd"); - } else if (Osz(x)) { + } else if (Osz(x->op.rde)) { stpcpy(q, "pd %Vpd Wpd"); } else { stpcpy(q, "ps %Vps Wps"); @@ -265,53 +265,53 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) { RCASE(0xFC, "cld"); RCASE(0xFD, "std"); case 0x8F: - switch (ModrmReg(x)) { + switch (ModrmReg(x->op.rde)) { RCASE(0, "popWQ Evq"); default: break; } break; case 0xD9: - switch (ModrmReg(x)) { + switch (ModrmReg(x->op.rde)) { RCASE(1, "fxch EST1"); RCASE(3, "fstps Msr %st"); case 0: - if (IsModrmRegister(x)) { + if (IsModrmRegister(x->op.rde)) { return "fld EST"; } else { return "flds Msr"; } break; case 2: - if (IsModrmRegister(x)) { + if (IsModrmRegister(x->op.rde)) { return "fnop"; } else { return "fsts Msr %st"; } break; case 4: - if (IsModrmRegister(x)) { + if (IsModrmRegister(x->op.rde)) { return DisOpFpu0(x, 1); } else { return "fldenv Me"; } break; case 5: - if (IsModrmRegister(x)) { + if (IsModrmRegister(x->op.rde)) { return DisOpFpu0(x, 2); } else { return "fldcw Mw"; } break; case 6: - if (IsModrmRegister(x)) { + if (IsModrmRegister(x->op.rde)) { return DisOpFpu0(x, 3); } else { return "fnstenv M"; } break; case 7: - if (IsModrmRegister(x)) { + if (IsModrmRegister(x->op.rde)) { return DisOpFpu0(x, 4); } else { return "fnstcw Mw"; @@ -320,58 +320,58 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) { } break; case 0xDA: - switch (ModrmReg(x)) { + switch (ModrmReg(x->op.rde)) { case 0: - if (!IsModrmRegister(x)) { + if (!IsModrmRegister(x->op.rde)) { return "fiaddl Mdi"; } else { return "fcmovb %st EST"; } break; case 1: - if (!IsModrmRegister(x)) { + if (!IsModrmRegister(x->op.rde)) { return "fimull Mdi"; } else { return "fcmove %st EST"; } break; case 2: - if (!IsModrmRegister(x)) { + if (!IsModrmRegister(x->op.rde)) { return "ficoml Mdi"; } else { return "fcmovbe %st EST"; } break; case 3: - if (!IsModrmRegister(x)) { + if (!IsModrmRegister(x->op.rde)) { return "ficompl Mdi"; } else { return "fcmovu %st EST"; } break; case 4: - if (!IsModrmRegister(x)) { + if (!IsModrmRegister(x->op.rde)) { return "fisubl Mdi"; } else { return "fisubr Mdi"; } break; case 5: - if (!IsModrmRegister(x)) { + if (!IsModrmRegister(x->op.rde)) { return "fisubrl Mdi"; } else { return "fucompp"; } break; case 6: - if (!IsModrmRegister(x)) { + if (!IsModrmRegister(x->op.rde)) { return "fidivl Mdi"; } else { return UNKNOWN; } break; case 7: - if (!IsModrmRegister(x)) { + if (!IsModrmRegister(x->op.rde)) { return "fidivrl Mdi"; } else { return UNKNOWN; @@ -380,30 +380,30 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) { } break; case 0xDB: - switch (ModrmReg(x)) { + switch (ModrmReg(x->op.rde)) { case 0: - if (!IsModrmRegister(x)) { + if (!IsModrmRegister(x->op.rde)) { return "fildl Mdi"; } else { return "fcmovnb %st EST"; } break; case 1: - if (!IsModrmRegister(x)) { + if (!IsModrmRegister(x->op.rde)) { return "fisttpl Mdi"; } else { return "fcmovne %st EST"; } break; case 2: - if (!IsModrmRegister(x)) { + if (!IsModrmRegister(x->op.rde)) { return "fistl Mdi"; } else { return "fcmovnbe %st EST"; } break; case 3: - if (!IsModrmRegister(x)) { + if (!IsModrmRegister(x->op.rde)) { return "fistpl Mdi"; } else { return "fcmovnu %st EST"; @@ -412,21 +412,21 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) { case 4: return DisOpFpu0(x, 5); case 5: - if (!IsModrmRegister(x)) { + if (!IsModrmRegister(x->op.rde)) { return "fldt Mer"; } else { return "fucomi %st EST"; } break; case 6: - if (IsModrmRegister(x)) { + if (IsModrmRegister(x->op.rde)) { return "fcomi %st EST"; } else { return UNKNOWN; } break; case 7: - if (!IsModrmRegister(x)) { + if (!IsModrmRegister(x->op.rde)) { return "fstpt Mer"; } else { return UNKNOWN; @@ -435,12 +435,12 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) { } break; case 0xD8: - return DisOpFpu1(x, p, !IsModrmRegister(x) ? "s Msr" : " EST1"); + return DisOpFpu1(x, p, !IsModrmRegister(x->op.rde) ? "s Msr" : " EST1"); case 0xDC: - if (!IsModrmRegister(x)) { + if (!IsModrmRegister(x->op.rde)) { return DisOpFpu1(x, p, "l Mdr"); } else { - switch (ModrmReg(x)) { + switch (ModrmReg(x->op.rde)) { RCASE(0, "fadd EST %st"); RCASE(1, "fmul EST %st"); RCASE(2, "fcom %st EST"); @@ -453,8 +453,8 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) { } break; case 0xDD: - if (!IsModrmRegister(x)) { - switch (ModrmReg(x)) { + if (!IsModrmRegister(x->op.rde)) { + switch (ModrmReg(x->op.rde)) { RCASE(0, "fldl Mdr"); RCASE(1, "fisttpll Mqi"); RCASE(2, "fstl Mdr"); @@ -464,7 +464,7 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) { RCASE(7, "fnstsw Mst"); } } else { - switch (ModrmReg(x)) { + switch (ModrmReg(x->op.rde)) { RCASE(0, "ffree EST"); RCASE(1, "fxch EST"); RCASE(2, "fst EST"); @@ -475,8 +475,8 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) { } break; case 0xDE: - if (!IsModrmRegister(x)) { - switch (ModrmReg(x)) { + if (!IsModrmRegister(x->op.rde)) { + switch (ModrmReg(x->op.rde)) { RCASE(0, "fiadds Mwi"); RCASE(1, "fimuls Mwi"); RCASE(2, "ficoms Mwi"); @@ -487,7 +487,7 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) { RCASE(7, "fidivrs Mwi"); } } else { - switch (ModrmReg(x)) { + switch (ModrmReg(x->op.rde)) { RCASE(0, "faddp EST1"); RCASE(1, "fmulp EST1"); RCASE(2, "fcomp EST1"); @@ -500,8 +500,8 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) { } break; case 0xDF: - if (!IsModrmRegister(x)) { - switch (ModrmReg(x)) { + if (!IsModrmRegister(x->op.rde)) { + switch (ModrmReg(x->op.rde)) { RCASE(0, "filds Mwi"); RCASE(1, "fisttps Mwi"); RCASE(2, "fists Mwi"); @@ -512,7 +512,7 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) { RCASE(7, "fistpll Mqi"); } } else { - switch (ModrmReg(x)) { + switch (ModrmReg(x->op.rde)) { RCASE(0, "ffreep EST"); RCASE(1, "fxch"); RCASE(2, "fstp EST"); @@ -524,7 +524,7 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) { } break; case 0xF6: - switch (ModrmReg(x)) { + switch (ModrmReg(x->op.rde)) { RCASE(0, "test Eb Ib"); RCASE(1, "test Eb Ib"); RCASE(2, "not Eb"); @@ -536,7 +536,7 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) { } break; case 0xF7: - switch (ModrmReg(x)) { + switch (ModrmReg(x->op.rde)) { RCASE(0, "test Evqp Ivds"); RCASE(1, "test Evqp Ivds"); RCASE(2, "not Evqp"); @@ -548,13 +548,13 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) { } break; case 0xFE: - switch (ModrmReg(x)) { + switch (ModrmReg(x->op.rde)) { RCASE(0, "inc Eb"); RCASE(1, "dec Eb"); } break; case 0xFF: - switch (ModrmReg(x)) { + switch (ModrmReg(x->op.rde)) { RCASE(0, "inc Evqp"); RCASE(1, "dec Evqp"); RCASE(2, "CALL Eq"); @@ -580,8 +580,8 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) { RCASE(0x28, "movapSD %Vps Wps"); RCASE(0x29, "movapSD Wps %Vps"); RCASE(0x2B, "movntpSD Mps %Vps"); - RCASE(0x2E, Osz(x) ? "ucomisd %Vsd Wsd" : "ucomiss %Vss Wss"); - RCASE(0x2F, Osz(x) ? "comisd %Vsd Wsd" : "comiss %Vss Wss"); + RCASE(0x2E, Osz(x->op.rde) ? "ucomisd %Vsd Wsd" : "ucomiss %Vss Wss"); + RCASE(0x2F, Osz(x->op.rde) ? "comisd %Vsd Wsd" : "comiss %Vss Wss"); RCASE(0x31, "rdtsc"); RCASE(0x40, "cmovo %Gvqp Evqp"); RCASE(0x41, "cmovno %Gvqp Evqp"); @@ -693,7 +693,7 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) { RCASE(0xD3, DisOpPqQqVdqWdq(x, p, "psrlq")); RCASE(0xD4, DisOpPqQqVdqWdq(x, p, "paddq")); 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(0xD9, DisOpPqQqVdqWdq(x, p, "psubusw")); 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(0xE4, DisOpPqQqVdqWdq(x, p, "pmulhuw")); 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(0xE9, DisOpPqQqVdqWdq(x, p, "psubsw")); RCASE(0xEA, DisOpPqQqVdqWdq(x, p, "pminsw")); @@ -740,7 +740,7 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) { } break; case 0x70: - switch (Rep(x) | Osz(x)) { + switch (Rep(x->op.rde) | Osz(x->op.rde)) { RCASE(0, "pshufw %Pq Qq Ib"); RCASE(1, "pshufd %Vdq Wdq Ib"); RCASE(2, "pshuflw %Vdq Wdq Ib"); @@ -748,21 +748,21 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) { } break; case 0x71: - switch (ModrmReg(x)) { + switch (ModrmReg(x->op.rde)) { RCASE(2, DisOpNqIbUdqIb(x, p, "psrlw")); RCASE(4, DisOpNqIbUdqIb(x, p, "psraw")); RCASE(6, DisOpNqIbUdqIb(x, p, "psllw")); } break; case 0x72: - switch (ModrmReg(x)) { + switch (ModrmReg(x->op.rde)) { RCASE(2, DisOpNqIbUdqIb(x, p, "psrld")); RCASE(4, DisOpNqIbUdqIb(x, p, "psrad")); RCASE(6, DisOpNqIbUdqIb(x, p, "pslld")); } break; case 0x73: - switch (ModrmReg(x)) { + switch (ModrmReg(x->op.rde)) { RCASE(2, DisOpNqIbUdqIb(x, p, "psrlq")); RCASE(3, DisOpNqIbUdqIb(x, p, "psrldq")); RCASE(6, DisOpNqIbUdqIb(x, p, "psllq")); @@ -770,7 +770,7 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) { } break; case 0xAE: - switch (ModrmReg(x)) { + switch (ModrmReg(x->op.rde)) { RCASE(0, "fxsave Mstx %st %st(1)"); RCASE(1, "fxrstor Mstx %st %st(1)"); RCASE(2, "ldmxcsr Md"); @@ -787,7 +787,7 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) { } break; case 0xBA: - switch (ModrmReg(x)) { + switch (ModrmReg(x->op.rde)) { RCASE(4, "btWLQ Evqp Ib"); RCASE(5, "btsWLQ Evqp Ib"); RCASE(6, "btrWLQ Evqp Ib"); @@ -795,36 +795,36 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) { } break; case 0x10: - if (x->op.ild_f3) { + if (Rep(x->op.rde) == 3) { return "movss %Vss Wss"; - } else if (x->op.ild_f2) { + } else if (Rep(x->op.rde) == 2) { return "movsd %Vsd Wsd"; - } else if (Osz(x)) { + } else if (Osz(x->op.rde)) { return "movupd %Vpd Wpd"; } else { return "movups %Vps Wps"; } break; case 0x11: - if (x->op.ild_f3) { + if (Rep(x->op.rde) == 3) { return "movss Wss %Vss"; - } else if (x->op.ild_f2) { + } else if (Rep(x->op.rde) == 2) { return "movsd Wsd %Vsd"; - } else if (Osz(x)) { + } else if (Osz(x->op.rde)) { return "movupd Wpd %Vpd"; } else { return "movups Wps %Vps"; } break; case 0xC4: - if (!Osz(x)) { - if (IsModrmRegister(x)) { + if (!Osz(x->op.rde)) { + if (IsModrmRegister(x->op.rde)) { return "pinsrw %Pq %Rdqp Ib"; } else { return "pinsrw %Pq Mw Ib"; } } else { - if (IsModrmRegister(x)) { + if (IsModrmRegister(x->op.rde)) { return "pinsrw %Vdq %Rdqp Ib"; } else { return "pinsrw %Vdq Mw Ib"; @@ -832,39 +832,39 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) { } break; case 0xC5: - if (!Osz(x)) { + if (!Osz(x->op.rde)) { return "pextrw %Gdqp %Nq Ib"; } else { return "pextrw %Gdqp %Udq Ib"; } break; case 0xC6: - if (!Osz(x)) { + if (!Osz(x->op.rde)) { return "shufps %Vps Wps Ib"; } else { return "shufpd %Vpd Wpd Ib"; } break; case 0xC7: - if (Rexw(x)) { + if (Rexw(x->op.rde)) { return "cmpxchg16b Mdq"; } else { return "cmpxchg8b Mq"; } break; case 0xD6: - if (Osz(x)) { + if (Osz(x->op.rde)) { return "movq Wq %Vq"; - } else if (x->op.ild_f3) { + } else if (Rep(x->op.rde) == 3) { return "movq2dq %Vdq %Nq"; - } else if (x->op.ild_f2) { + } else if (Rep(x->op.rde) == 2) { return "movq2dq %Pq %Uq"; } break; case 0x12: - switch (Rep(x) | Osz(x)) { + switch (Rep(x->op.rde) | Osz(x->op.rde)) { case 0: - if (IsModrmRegister(x)) { + if (IsModrmRegister(x->op.rde)) { return "movhlps %Vq %Uq"; } else { return "movlps %Vq Mq"; @@ -881,16 +881,16 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) { } break; case 0x13: - if (Osz(x)) { + if (Osz(x->op.rde)) { return "movlpd Mq %Vq"; } else { return "movlps Mq %Vq"; } break; case 0x16: - switch (Rep(x) | Osz(x)) { + switch (Rep(x->op.rde) | Osz(x->op.rde)) { case 0: - if (IsModrmRegister(x)) { + if (IsModrmRegister(x->op.rde)) { return "movlhps %Vq %Uq"; } else { return "movhps %Vq Mq"; @@ -905,85 +905,85 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) { } break; case 0x17: - if (Osz(x)) { + if (Osz(x->op.rde)) { return "movhpd Mq %Vq"; } else { return "movhps Mq %Vq"; } break; case 0x2A: - if (x->op.ild_f3) { + if (Rep(x->op.rde) == 3) { return "cvtsi2ss %Vss Edqp"; - } else if (x->op.ild_f2) { + } else if (Rep(x->op.rde) == 2) { return "cvtsi2sd %Vsd Edqp"; - } else if (Osz(x)) { + } else if (Osz(x->op.rde)) { return "cvtpi2pd %Vpd Qpi"; } else { return "cvtpi2ps %Vps Qpi"; } break; case 0x2C: - if (x->op.ild_f3) { + if (Rep(x->op.rde) == 3) { return "cvttss2si %Gdqp Wss"; - } else if (x->op.ild_f2) { + } else if (Rep(x->op.rde) == 2) { return "cvttsd2si %Gdqp Wsd"; - } else if (Osz(x)) { + } else if (Osz(x->op.rde)) { return "cvttpd2pi %Ppi Wpd"; } else { return "cvttps2pi %Ppi Wpsq"; } break; case 0x2D: - if (x->op.ild_f3) { + if (Rep(x->op.rde) == 3) { return "cvtss2si %Gdqp Wss"; - } else if (x->op.ild_f2) { + } else if (Rep(x->op.rde) == 2) { return "cvtsd2si %Gdqp Wsd"; - } else if (Osz(x)) { + } else if (Osz(x->op.rde)) { return "cvtpd2pi %Ppi Wpd"; } else { return "cvtps2pi %Ppi Wpsq"; } break; case 0x5a: - if (x->op.ild_f3) { + if (Rep(x->op.rde) == 3) { return "cvtss2sd %Vsd Wss"; - } else if (x->op.ild_f2) { + } else if (Rep(x->op.rde) == 2) { return "cvtsd2ss %Vss Wsd"; - } else if (Osz(x)) { + } else if (Osz(x->op.rde)) { return "cvtpd2ps %Vps Wpd"; } else { return "cvtps2pd %Vpd Wps"; } break; case 0x5b: - if (x->op.ild_f3) { + if (Rep(x->op.rde) == 3) { return "cvttps2dq %Vdq Wps"; - } else if (Osz(x)) { + } else if (Osz(x->op.rde)) { return "cvtps2dq %Vdq Wps"; } else { return "cvtdq2ps %Vps Wdq"; } break; case 0x51: - if (x->op.ild_f3) { + if (Rep(x->op.rde) == 3) { return "sqrtss %Vss Wss"; - } else if (x->op.ild_f2) { + } else if (Rep(x->op.rde) == 2) { return "sqrtsd %Vsd Wsd"; - } else if (Osz(x)) { + } else if (Osz(x->op.rde)) { return "sqrtpd %Vpd Wpd"; } else { return "sqrtps %Vps Wps"; } break; case 0x6E: - if (Osz(x)) { - if (Rexw(x)) { + if (Osz(x->op.rde)) { + if (Rexw(x->op.rde)) { return "movq %Vdq Eqp"; } else { return "movd %Vdq Ed"; } } else { - if (Rexw(x)) { + if (Rexw(x->op.rde)) { return "movq %Pq Eqp"; } else { return "movd %Pq Ed"; @@ -991,25 +991,25 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) { } break; case 0x6F: - if (x->op.ild_f3) { + if (Rep(x->op.rde) == 3) { return "movdqu %Vdq Wdq"; - } else if (Osz(x)) { + } else if (Osz(x->op.rde)) { return "movdqa %Vdq Wdq"; } else { return "movq %Pq Qq"; } break; case 0x7E: - if (x->op.ild_f3) { + if (Rep(x->op.rde) == 3) { return "movq %Vq Wq"; - } else if (Osz(x)) { - if (Rexw(x)) { + } else if (Osz(x->op.rde)) { + if (Rexw(x->op.rde)) { return "movq Eqp %Vdq"; } else { return "movd Ed %Vdq"; } } else { - if (Rexw(x)) { + if (Rexw(x->op.rde)) { return "movq Eqp %Pq"; } else { return "movd Ed %Pq"; @@ -1017,20 +1017,20 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) { } break; case 0x7F: - if (x->op.ild_f3) { + if (Rep(x->op.rde) == 3) { return "movdqu Wdq %Vdq"; - } else if (Osz(x)) { + } else if (Osz(x->op.rde)) { return "movdqa Wdq %Vdq"; } else { return "movq Qq %Pq"; } break; case 0xE6: - if (x->op.ild_f2) { + if (Rep(x->op.rde) == 2) { return "cvtpd2dq %Vdq Wpd"; - } else if (Osz(x)) { + } else if (Osz(x->op.rde)) { return "cvttpd2dq %Vdq Wpd"; - } else if (x->op.ild_f3) { + } else if (Rep(x->op.rde) == 3) { return "cvtdq2pd %Vpd Wdq"; } break; diff --git a/tool/build/lib/divmul.c b/tool/build/lib/divmul.c index 7c79e547..b36568f6 100644 --- a/tool/build/lib/divmul.c +++ b/tool/build/lib/divmul.c @@ -25,12 +25,12 @@ #include "tool/build/lib/modrm.h" #include "tool/build/lib/throw.h" -void OpDivAlAhAxEbSigned(struct Machine *m) { +void OpDivAlAhAxEbSigned(struct Machine *m, uint32_t rde) { int8_t y, rem; int16_t x, quo; x = Read16(m->ax); - y = Read8(GetModrmRegisterBytePointerRead(m)); - if (!y || (x == INT16_MIN && y < 0)) ThrowDivideError(m); + y = Read8(GetModrmRegisterBytePointerRead(m, rde)); + if (!y || (x == INT16_MIN && y == -1)) ThrowDivideError(m); quo = x / y; rem = x % y; if (!(INT8_MIN <= quo && quo <= INT8_MAX)) ThrowDivideError(m); @@ -38,11 +38,11 @@ void OpDivAlAhAxEbSigned(struct Machine *m) { m->ax[1] = rem & 0xff; } -void OpDivAlAhAxEbUnsigned(struct Machine *m) { +void OpDivAlAhAxEbUnsigned(struct Machine *m, uint32_t rde) { uint8_t y, rem; uint16_t x, quo; x = Read16(m->ax); - y = Read8(GetModrmRegisterBytePointerRead(m)); + y = Read8(GetModrmRegisterBytePointerRead(m, rde)); if (!y) ThrowDivideError(m); quo = x / y; rem = x % y; @@ -51,12 +51,13 @@ void OpDivAlAhAxEbUnsigned(struct Machine *m) { 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; int128_t x, quo; x = (uint128_t)Read64(m->dx) << 64 | Read64(m->ax); y = Read64(p); - if (!y || (x == INT128_MIN && y < 0)) ThrowDivideError(m); + if (!y || (x == INT128_MIN && y == -1)) ThrowDivideError(m); quo = x / y; rem = x % y; 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); } -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; int64_t x, quo; x = (uint64_t)Read32(m->dx) << 32 | Read32(m->ax); y = Read32(p); - if (!y || (x == INT64_MIN && y < 0)) ThrowDivideError(m); + if (!y || (x == INT64_MIN && y == -1)) ThrowDivideError(m); quo = x / y; rem = x % y; 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); } -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; int32_t x, quo; x = (uint32_t)Read16(m->dx) << 16 | Read16(m->ax); y = Read16(p); - if (!y || (x == INT32_MIN && y < 0)) ThrowDivideError(m); + if (!y || (x == INT32_MIN && y == -1)) ThrowDivideError(m); quo = x / y; rem = x % y; 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); } -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; uint32_t x, quo; 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); } -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; uint64_t x, quo; 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); } -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; uint128_t x, quo; 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); } -void OpDivRdxRaxEvqpSigned(struct Machine *m) { +void OpDivRdxRaxEvqpSigned(struct Machine *m, uint32_t rde) { uint8_t *p; - p = GetModrmRegisterWordPointerReadOszRexw(m); - if (Rexw(m->xedd)) { - OpDivRdxRaxEvqpSigned64(m, p); - } else if (!Osz(m->xedd)) { - OpDivRdxRaxEvqpSigned32(m, p); + p = GetModrmRegisterWordPointerReadOszRexw(m, rde); + if (Rexw(rde)) { + OpDivRdxRaxEvqpSigned64(m, rde, p); + } else if (!Osz(rde)) { + OpDivRdxRaxEvqpSigned32(m, rde, p); } else { - OpDivRdxRaxEvqpSigned16(m, p); + OpDivRdxRaxEvqpSigned16(m, rde, p); } } -void OpDivRdxRaxEvqpUnsigned(struct Machine *m) { +void OpDivRdxRaxEvqpUnsigned(struct Machine *m, uint32_t rde) { uint8_t *p; - p = GetModrmRegisterWordPointerReadOszRexw(m); - if (Rexw(m->xedd)) { - OpDivRdxRaxEvqpUnsigned64(m, p); - } else if (!Osz(m->xedd)) { - OpDivRdxRaxEvqpUnsigned32(m, p); + p = GetModrmRegisterWordPointerReadOszRexw(m, rde); + if (Rexw(rde)) { + OpDivRdxRaxEvqpUnsigned64(m, rde, p); + } else if (!Osz(rde)) { + OpDivRdxRaxEvqpUnsigned32(m, rde, p); } else { - OpDivRdxRaxEvqpUnsigned16(m, p); + OpDivRdxRaxEvqpUnsigned16(m, rde, p); } } -void OpMulAxAlEbSigned(struct Machine *m) { +void OpMulAxAlEbSigned(struct Machine *m, uint32_t rde) { bool of; int16_t ax; uint8_t *p; - p = GetModrmRegisterBytePointerRead(m); + p = GetModrmRegisterBytePointerRead(m, rde); __builtin_mul_overflow((int8_t)Read8(m->ax), (int8_t)Read8(p), &ax); of = (int)ax != (int8_t)ax; m->flags = SetFlag(m->flags, FLAGS_CF, of); @@ -165,11 +171,11 @@ void OpMulAxAlEbSigned(struct Machine *m) { Write16(m->ax, ax); } -void OpMulAxAlEbUnsigned(struct Machine *m) { +void OpMulAxAlEbUnsigned(struct Machine *m, uint32_t rde) { int ax; bool of; uint8_t *p; - p = GetModrmRegisterBytePointerRead(m); + p = GetModrmRegisterBytePointerRead(m, rde); __builtin_mul_overflow(Read8(m->ax), Read8(p), &ax); of = (uint8_t)ax != ax; m->flags = SetFlag(m->flags, FLAGS_CF, of); @@ -177,20 +183,20 @@ void OpMulAxAlEbUnsigned(struct Machine *m) { Write16(m->ax, ax); } -void OpMulRdxRaxEvqpSigned(struct Machine *m) { +void OpMulRdxRaxEvqpSigned(struct Machine *m, uint32_t rde) { bool of; uint8_t *p; int32_t dxax; int64_t edxeax; int128_t rdxrax; - p = GetModrmRegisterWordPointerReadOszRexw(m); - if (Rexw(m->xedd)) { + p = GetModrmRegisterWordPointerReadOszRexw(m, rde); + if (Rexw(rde)) { __builtin_mul_overflow((int128_t)(int64_t)Read64(m->ax), (int64_t)Read64(p), &rdxrax); of = (int128_t)rdxrax != (int64_t)rdxrax; Write64(m->ax, rdxrax); 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), &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); } -void OpMulRdxRaxEvqpUnsigned(struct Machine *m) { +void OpMulRdxRaxEvqpUnsigned(struct Machine *m, uint32_t rde) { bool of; uint8_t *p; uint32_t dxax; uint64_t edxeax; uint128_t rdxrax; - p = GetModrmRegisterWordPointerReadOszRexw(m); - if (Rexw(m->xedd)) { + p = GetModrmRegisterWordPointerReadOszRexw(m, rde); + if (Rexw(rde)) { __builtin_mul_overflow((uint128_t)Read64(m->ax), Read64(p), &rdxrax); of = (uint64_t)rdxrax != rdxrax; Write64(m->ax, rdxrax); 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); of = (uint32_t)edxeax != edxeax; Write64(m->ax, edxeax); @@ -235,37 +241,38 @@ void OpMulRdxRaxEvqpUnsigned(struct Machine *m) { 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; - if (Rexw(m->xedd)) { + if (Rexw(rde)) { int64_t x, y, z; x = Read64(a); y = Read64(b); of = __builtin_mul_overflow(x, y, &z); - Write64(RegRexrReg(m), z); - } else if (!Osz(m->xedd)) { + Write64(RegRexrReg(m, rde), z); + } else if (!Osz(rde)) { int32_t x, y, z; x = Read32(a); y = Read32(b); of = __builtin_mul_overflow(x, y, &z); - Write64(RegRexrReg(m), z & 0xffffffff); + Write64(RegRexrReg(m, rde), z & 0xffffffff); } else { int16_t x, y, z; x = Read16(a); y = Read16(b); 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_OF, of); } -void OpImulGvqpEvqp(struct Machine *m) { - AluImul(m, RegRexrReg(m), GetModrmRegisterWordPointerReadOszRexw(m)); +void OpImulGvqpEvqp(struct Machine *m, uint32_t rde) { + 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]; Write64(b, m->xedd->op.uimm0); - AluImul(m, GetModrmRegisterWordPointerReadOszRexw(m), b); + AluImul(m, rde, GetModrmRegisterWordPointerReadOszRexw(m, rde), b); } diff --git a/tool/build/lib/divmul.h b/tool/build/lib/divmul.h index a503ae99..941b42ce 100644 --- a/tool/build/lib/divmul.h +++ b/tool/build/lib/divmul.h @@ -4,16 +4,16 @@ #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ -void OpDivAlAhAxEbSigned(struct Machine *); -void OpDivAlAhAxEbUnsigned(struct Machine *); -void OpDivRdxRaxEvqpSigned(struct Machine *); -void OpDivRdxRaxEvqpUnsigned(struct Machine *); -void OpImulGvqpEvqp(struct Machine *); -void OpImulGvqpEvqpImm(struct Machine *); -void OpMulAxAlEbSigned(struct Machine *); -void OpMulAxAlEbUnsigned(struct Machine *); -void OpMulRdxRaxEvqpSigned(struct Machine *); -void OpMulRdxRaxEvqpUnsigned(struct Machine *); +void OpDivAlAhAxEbSigned(struct Machine *, uint32_t); +void OpDivAlAhAxEbUnsigned(struct Machine *, uint32_t); +void OpDivRdxRaxEvqpSigned(struct Machine *, uint32_t); +void OpDivRdxRaxEvqpUnsigned(struct Machine *, uint32_t); +void OpImulGvqpEvqp(struct Machine *, uint32_t); +void OpImulGvqpEvqpImm(struct Machine *, uint32_t); +void OpMulAxAlEbSigned(struct Machine *, uint32_t); +void OpMulAxAlEbUnsigned(struct Machine *, uint32_t); +void OpMulRdxRaxEvqpSigned(struct Machine *, uint32_t); +void OpMulRdxRaxEvqpUnsigned(struct Machine *, uint32_t); COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/tool/build/lib/fds.c b/tool/build/lib/fds.c new file mode 100644 index 00000000..24187658 --- /dev/null +++ b/tool/build/lib/fds.c @@ -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; + } +} diff --git a/tool/build/lib/fds.h b/tool/build/lib/fds.h new file mode 100644 index 00000000..f31cbbdf --- /dev/null +++ b/tool/build/lib/fds.h @@ -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_ */ diff --git a/tool/build/lib/fpu.c b/tool/build/lib/fpu.c index dec05841..a2dc50e8 100644 --- a/tool/build/lib/fpu.c +++ b/tool/build/lib/fpu.c @@ -50,26 +50,6 @@ static long double OnFpuStackUnderflow(struct Machine *m) { 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) { if (FpuGetTag(m, i) == kFpuTagEmpty) OnFpuStackUnderflow(m); return *FpuSt(m, i); @@ -84,7 +64,7 @@ static long double St1(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) { @@ -100,7 +80,7 @@ static void FpuSetSt0(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) { @@ -109,7 +89,7 @@ static void FpuSetStPop(struct Machine *m, int i, 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) { @@ -414,11 +394,11 @@ static void OpFmulEstSt(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) { - FpuSetStRm(m, St0(m) - StRm(m)); + FpuSetStRm(m, StRm(m) - St0(m)); } static void OpFdivEstSt(struct Machine *m) { @@ -666,8 +646,7 @@ static void OpFstp(struct Machine *m) { } static void OpFxch(struct Machine *m) { - long double t; - t = StRm(m); + long double t = StRm(m); FpuSetStRm(m, St0(m)); FpuSetSt0(m, t); } @@ -686,7 +665,7 @@ static void OpFldl(struct Machine *m) { static void OpFldConstant(struct Machine *m) { long double x; - switch (ModrmRm(m->xedd)) { + switch (ModrmRm(m->xedd->op.rde)) { case 0: x = fld1(); break; @@ -769,7 +748,7 @@ static void OpFistps(struct Machine *m) { FpuPop(m); } -void OpFcomi(struct Machine *m) { +static void OpFcomi(struct Machine *m) { long double x, y; x = St0(m); y = StRm(m); @@ -808,7 +787,7 @@ static void OpFucomip(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) { @@ -890,6 +869,10 @@ static void OpFnclex(struct Machine *m) { m->fpu.bf = false; } +static void OpFnop(struct Machine *m) { + /* do nothing */ +} + void OpFinit(struct Machine *m) { m->fpu.cw = X87_NORMAL; m->fpu.sw = 0; @@ -905,18 +888,59 @@ void OpFwait(struct Machine *m) { } } -static void OpFnop(struct Machine *m) { - /* do nothing */ +long double *FpuSt(struct Machine *m, unsigned i) { + 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) { unsigned op; bool ismemory; 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.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)) { CASE(DISP(0xD8, FPUREG, 0), OpFaddStEst(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, 7), OpFistpll(m)); case DISP(0xD9, FPUREG, 4): - switch (ModrmRm(m->xedd)) { + switch (ModrmRm(m->xedd->op.rde)) { CASE(0, OpFchs(m)); CASE(1, OpFabs(m)); CASE(4, OpFtst(m)); @@ -1039,7 +1063,7 @@ void OpFpu(struct Machine *m) { } break; case DISP(0xD9, FPUREG, 6): - switch (ModrmRm(m->xedd)) { + switch (ModrmRm(m->xedd->op.rde)) { CASE(0, OpF2xm1(m)); CASE(1, OpFyl2x(m)); CASE(2, OpFptan(m)); @@ -1053,7 +1077,7 @@ void OpFpu(struct Machine *m) { } break; case DISP(0xD9, FPUREG, 7): - switch (ModrmRm(m->xedd)) { + switch (ModrmRm(m->xedd->op.rde)) { CASE(0, OpFprem(m)); CASE(1, OpFyl2xp1(m)); CASE(2, OpFsqrt(m)); @@ -1067,7 +1091,7 @@ void OpFpu(struct Machine *m) { } break; case DISP(0xDb, FPUREG, 4): - switch (ModrmRm(m->xedd)) { + switch (ModrmRm(m->xedd->op.rde)) { CASE(2, OpFnclex(m)); CASE(3, OpFinit(m)); default: diff --git a/tool/build/lib/fpu.h b/tool/build/lib/fpu.h index 8b02ce26..346db037 100644 --- a/tool/build/lib/fpu.h +++ b/tool/build/lib/fpu.h @@ -15,32 +15,9 @@ void OpFinit(struct Machine *); void OpFwait(struct Machine *); void FpuPush(struct Machine *, long double); long double FpuPop(struct Machine *); - -forceinline long double *FpuSt(struct Machine *m, unsigned i) { - i += m->fpu.sp; - 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; -} +long double *FpuSt(struct Machine *, unsigned); +int FpuGetTag(struct Machine *, unsigned); +void FpuSetTag(struct Machine *, unsigned, unsigned); COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/tool/build/lib/initmachine.c b/tool/build/lib/init.c similarity index 100% rename from tool/build/lib/initmachine.c rename to tool/build/lib/init.c diff --git a/tool/build/lib/ioports.c b/tool/build/lib/ioports.c index a405e4bf..21591368 100644 --- a/tool/build/lib/ioports.c +++ b/tool/build/lib/ioports.c @@ -17,13 +17,34 @@ │ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │ │ 02110-1301 USA │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/stdio/stdio.h" +#include "libc/sysv/consts/fileno.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) { switch (p) { case 0xE9: - return getc(stdin); + return OpE9Read(m); default: 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) { switch (p) { case 0xE9: - do { - putc(x, stdout); - } while (x >> 8); + OpE9Write(m, x); break; default: break; diff --git a/tool/build/lib/machine.c b/tool/build/lib/machine.c index 81c6573a..bd4f4b0a 100644 --- a/tool/build/lib/machine.c +++ b/tool/build/lib/machine.c @@ -32,10 +32,7 @@ #include "libc/log/log.h" #include "libc/macros.h" #include "libc/math.h" -#include "libc/nexgen32e/rdtsc.h" #include "libc/runtime/runtime.h" -#include "libc/sysv/consts/clock.h" -#include "libc/time/time.h" #include "tool/build/lib/abp.h" #include "tool/build/lib/alu.h" #include "tool/build/lib/bitscan.h" @@ -57,30 +54,35 @@ #include "tool/build/lib/string.h" #include "tool/build/lib/syscall.h" #include "tool/build/lib/throw.h" +#include "tool/build/lib/time.h" #define MUTATING true #define READONLY false #define UNCONDITIONAL true -#define REG ModrmReg(m->xedd) +#define REG ModrmReg(rde) #define UIMM0 m->xedd->op.uimm0 -#define BITS (8 << RegLog2(m->xedd)) +#define BITS (8 << RegLog2(rde)) #define SIGN (1ull << (BITS - 1)) #define MASK (SIGN | (SIGN - 1)) #define SHIFTMASK (BITS - 1) +#define TEST ALU_TEST | ALU_AND +#define ZF GetFlag(m->flags, FLAGS_ZF) typedef int int_v _Vector_size(16) aligned(16); typedef long long_v _Vector_size(16) aligned(16); typedef float float_v _Vector_size(16) aligned(16); typedef double double_v _Vector_size(16) aligned(16); -typedef void (*machine_f)(struct Machine *); -typedef void (*machine_u8p_u8p_f)(struct Machine *, uint8_t *, uint8_t *); -typedef void (*alu_f)(struct Machine *, aluop2_f, bool); -static uint64_t AluNot(struct Machine *m, uint64_t x) { +typedef void (*machine_f)(struct Machine *); +typedef void (*map_f)(struct Machine *, uint32_t); +typedef void (*alu_f)(struct Machine *, aluop2_f, bool); +typedef void (*machine_u8p_u8p_f)(struct Machine *, uint8_t *, uint8_t *); + +static uint64_t AluNot(struct Machine *m, uint32_t rde, uint64_t x) { return ~x & MASK; } -static uint64_t AluNeg(struct Machine *m, uint64_t x) { +static uint64_t AluNeg(struct Machine *m, uint32_t rde, uint64_t x) { m->flags = SetFlag(m->flags, FLAGS_CF, !!(x & MASK)); m->flags = SetFlag(m->flags, FLAGS_OF, (x & MASK) == SIGN); x = ~x + 1; @@ -90,7 +92,7 @@ static uint64_t AluNeg(struct Machine *m, uint64_t x) { return x & MASK; } -static uint64_t AluInc(struct Machine *m, uint64_t a) { +static uint64_t AluInc(struct Machine *m, uint32_t rde, uint64_t a) { uint64_t c; uint128_t x, z; a &= MASK; @@ -104,7 +106,7 @@ static uint64_t AluInc(struct Machine *m, uint64_t a) { return c & MASK; } -static uint64_t AluDec(struct Machine *m, uint64_t a) { +static uint64_t AluDec(struct Machine *m, uint32_t rde, uint64_t a) { uint64_t c; uint128_t x, z; a &= MASK; @@ -137,51 +139,51 @@ static void ImportFlags(struct Machine *m, uint64_t flags) { m->flags = SetLazyParityByte(m->flags, !((m->flags >> FLAGS_PF) & 1)); } -static uint64_t ReadMemory(struct Machine *m, uint8_t p[8]) { - if (Rexw(m->xedd)) { +static uint64_t ReadMemory(uint32_t rde, uint8_t p[8]) { + if (Rexw(rde)) { return Read64(p); - } else if (!Osz(m->xedd)) { + } else if (!Osz(rde)) { return Read32(p); } else { return Read16(p); } } -static int64_t ReadMemorySigned(struct Machine *m, uint8_t p[8]) { - if (Rexw(m->xedd)) { +static int64_t ReadMemorySigned(uint32_t rde, uint8_t p[8]) { + if (Rexw(rde)) { return (int64_t)Read64(p); - } else if (!Osz(m->xedd)) { + } else if (!Osz(rde)) { return (int32_t)Read32(p); } else { return (int16_t)Read16(p); } } -static void WriteRegister(struct Machine *m, uint8_t p[8], uint64_t x) { - if (Rexw(m->xedd)) { +static void WriteRegister(uint32_t rde, uint8_t p[8], uint64_t x) { + if (Rexw(rde)) { Write64(p, x); - } else if (!Osz(m->xedd)) { + } else if (!Osz(rde)) { Write64(p, x & 0xffffffff); } else { Write16(p, x); } } -static void WriteMemory(struct Machine *m, uint8_t p[8], uint64_t x) { - if (Rexw(m->xedd)) { +static void WriteMemory(uint32_t rde, uint8_t p[8], uint64_t x) { + if (Rexw(rde)) { Write64(p, x); - } else if (!Osz(m->xedd)) { + } else if (!Osz(rde)) { Write32(p, x); } else { Write16(p, x); } } -static void WriteRegisterOrMemory(struct Machine *m, uint8_t p[8], uint64_t x) { - if (IsModrmRegister(m->xedd)) { - WriteRegister(m, p, x); +static void WriteRegisterOrMemory(uint32_t rde, uint8_t p[8], uint64_t x) { + if (IsModrmRegister(rde)) { + WriteRegister(rde, p, x); } else { - WriteMemory(m, p, x); + WriteMemory(rde, p, x); } } @@ -228,15 +230,15 @@ static void OpStd(struct Machine *m) { m->flags = SetFlag(m->flags, FLAGS_DF, true); } -static void OpPushf(struct Machine *m) { - PushOsz(m, ExportFlags(m->flags) & 0xFCFFFF); +static void OpPushf(struct Machine *m, uint32_t rde) { + PushOsz(m, rde, ExportFlags(m->flags) & 0xFCFFFF); } -static void OpPopf(struct Machine *m) { - if (!Osz(m->xedd)) { +static void OpPopf(struct Machine *m, uint32_t rde) { + if (!Osz(rde)) { ImportFlags(m, Pop64(m, 0)); } else { - ImportFlags(m, (m->flags & ~0xFFFFull) | Pop16(m, 0)); + ImportFlags(m, (m->flags & ~0xffff) | Pop16(m, 0)); } } @@ -261,126 +263,116 @@ static void OpPopGs(struct Machine *m) { } static void OpSahf(struct Machine *m) { - ImportFlags(m, (m->flags & ~0xFFull) | m->ax[1]); + ImportFlags(m, (m->flags & ~0xff) | m->ax[1]); } -static void OpEbSetCc(struct Machine *m, bool x) { - Write8(GetModrmRegisterBytePointerWrite(m), x); +static void OpEbSetCc(struct Machine *m, uint32_t rde, bool x) { + Write8(GetModrmRegisterBytePointerWrite(m, rde), x); } -static void OpLeaGvqpM(struct Machine *m) { - Write64(RegRexrReg(m), ComputeAddress(m)); +static void OpLeaGvqpM(struct Machine *m, uint32_t rde) { + Write64(RegRexrReg(m, rde), ComputeAddress(m, rde)); } -static void PushVq(struct Machine *m, uint8_t *p) { - if (!Osz(m->xedd)) { +static void PushVq(struct Machine *m, uint32_t rde, uint8_t *p) { + if (!Osz(rde)) { Push64(m, Read64(p)); } else { Push16(m, Read16(p)); } } -static void PopVq(struct Machine *m, uint8_t *p) { - if (!Osz(m->xedd)) { +static void PopVq(struct Machine *m, uint32_t rde, uint8_t *p) { + if (!Osz(rde)) { Write64(p, Pop64(m, 0)); } else { Write16(p, Pop16(m, 0)); } } -static void OpPushEvq(struct Machine *m) { - PushVq(m, GetModrmRegisterWordPointerReadOsz(m)); +static void OpPushEvq(struct Machine *m, uint32_t rde) { + PushVq(m, rde, GetModrmRegisterWordPointerReadOsz(m, rde)); } -static void OpPushZvq(struct Machine *m) { - PushVq(m, RegRexbSrm(m)); +static void OpPushZvq(struct Machine *m, uint32_t rde) { + PushVq(m, rde, RegRexbSrm(m, rde)); } -static void OpPopZvq(struct Machine *m) { - PopVq(m, RegRexbSrm(m)); +static void OpPopZvq(struct Machine *m, uint32_t rde) { + PopVq(m, rde, RegRexbSrm(m, rde)); } -static void OpPopEvq(struct Machine *m) { - PopVq(m, GetModrmRegisterWordPointerWriteOsz(m)); +static void OpPopEvq(struct Machine *m, uint32_t rde) { + PopVq(m, rde, GetModrmRegisterWordPointerWriteOsz(m, rde)); } static void OpJmp(struct Machine *m) { m->ip += m->xedd->op.disp; } -static void OpJmpEq(struct Machine *m) { - m->ip = Read64(GetModrmRegisterWordPointerRead8(m)); +static void OpJmpEq(struct Machine *m, uint32_t rde) { + m->ip = Read64(GetModrmRegisterWordPointerRead8(m, rde)); } -static void OpJcxz(struct Machine *m) { +static void OpJcxz(struct Machine *m, uint32_t rde) { uint64_t count; count = Read64(m->cx); - if (Asz(m->xedd)) count &= 0xffffffff; + if (Asz(rde)) count &= 0xffffffff; if (!count) OpJmp(m); } -static void OpLoop(struct Machine *m, bool cond) { +static void OpLoop(struct Machine *m, uint32_t rde, bool cond) { uint64_t count; count = Read64(m->cx) - 1; - if (Asz(m->xedd)) count &= 0xffffffff; + if (Asz(rde)) count &= 0xffffffff; Write64(m->cx, count); if (count && cond) m->ip += m->xedd->op.disp; } -static void OpXlat(struct Machine *m) { +static void OpXlat(struct Machine *m, uint32_t rde) { int64_t v; uint8_t al; v = Read64(m->bx) + Read8(m->ax); - if (Asz(m->xedd)) v &= 0xffffffff; + if (Asz(rde)) v &= 0xffffffff; SetReadAddr(m, v, 1); Write8(m->ax, Read8(ResolveAddress(m, v))); } -static void OpEb(struct Machine *m, aluop1_f op) { +static void OpEb(struct Machine *m, uint32_t rde, aluop1_f op) { uint8_t *p; - p = GetModrmRegisterBytePointerWrite(m); - Write8(p, op(m, Read8(p))); + p = GetModrmRegisterBytePointerWrite(m, rde); + Write8(p, op(m, rde, Read8(p))); } -static void OpEvqp(struct Machine *m, aluop1_f op) { +static void OpEvqp(struct Machine *m, uint32_t rde, aluop1_f op) { uint8_t *p; - p = GetModrmRegisterWordPointerWriteOszRexw(m); - WriteRegisterOrMemory(m, p, op(m, ReadMemory(m, p))); + p = GetModrmRegisterWordPointerWriteOszRexw(m, rde); + WriteRegisterOrMemory(rde, p, op(m, rde, ReadMemory(rde, p))); } -static void OpGvqpEvqp(struct Machine *m, aluop2_f op, bool write) { +static void OpGvqpEvqp(struct Machine *m, uint32_t rde, aluop2_f op, + bool write) { uint64_t x; - x = op(m, ReadMemory(m, RegRexrReg(m)), - ReadMemory(m, GetModrmRegisterWordPointerReadOszRexw(m))); - if (write) WriteRegister(m, RegRexrReg(m), x); + x = op(m, rde, ReadMemory(rde, RegRexrReg(m, rde)), + ReadMemory(rde, GetModrmRegisterWordPointerReadOszRexw(m, rde))); + if (write) WriteRegister(rde, RegRexrReg(m, rde), x); } -static void OpEvqpGvqp(struct Machine *m, aluop2_f op, bool write) { +static void OpEvqpGvqp(struct Machine *m, uint32_t rde, aluop2_f op, + bool write) { uint8_t *p; - uint64_t x, y; - p = GetModrmRegisterWordPointerWriteOszRexw(m); - x = ReadMemory(m, p); - y = ReadMemory(m, RegRexrReg(m)); - x = op(m, x, y); - if (write) WriteRegisterOrMemory(m, p, x); + uint64_t x; + p = GetModrmRegisterWordPointerWriteOszRexw(m, rde); + x = op(m, rde, ReadMemory(rde, p), ReadMemory(rde, RegRexrReg(m, rde))); + if (write) WriteRegisterOrMemory(rde, p, x); } -static void OpXchgZvqp(struct Machine *m) { +static void OpXchgZvqp(struct Machine *m, uint32_t rde) { uint64_t x, y; x = Read64(m->ax); - y = Read64(RegRexbSrm(m)); - WriteRegister(m, m->ax, y); - WriteRegister(m, RegRexbSrm(m), x); -} - -static 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; - } + y = Read64(RegRexbSrm(m, rde)); + WriteRegister(rde, m->ax, y); + WriteRegister(rde, RegRexbSrm(m, rde), x); } static void OpNopEv(struct Machine *m) { @@ -393,41 +385,41 @@ static void OpPause(struct Machine *m) { sched_yield(); } -static void OpNop(struct Machine *m) { +static void OpNop(struct Machine *m, uint32_t rde) { if (m->xedd->op.rexb) { - OpXchgZvqp(m); - } else if (m->xedd->op.ild_f3) { + OpXchgZvqp(m, rde); + } else if (Rep(rde) == 3) { OpPause(m); } } -static void OpXchgGbEb(struct Machine *m) { - uint8_t *b; +static void OpXchgGbEb(struct Machine *m, uint32_t rde) { + uint8_t *p; uint8_t x, y; - b = GetModrmRegisterBytePointerWrite(m); - x = Read8(ByteRexrReg(m)); - y = Read8(b); - Write8(ByteRexrReg(m), y); - Write8(b, x); + p = GetModrmRegisterBytePointerWrite(m, rde); + x = Read8(ByteRexrReg(m, rde)); + y = Read8(p); + Write8(ByteRexrReg(m, rde), y); + Write8(p, x); } -static void OpXchgGvqpEvqp(struct Machine *m) { +static void OpXchgGvqpEvqp(struct Machine *m, uint32_t rde) { uint8_t *p; uint64_t x, y; - p = GetModrmRegisterWordPointerWriteOszRexw(m); - x = ReadMemory(m, RegRexrReg(m)); - y = ReadMemory(m, p); - WriteRegister(m, RegRexrReg(m), y); - WriteRegisterOrMemory(m, p, x); + p = GetModrmRegisterWordPointerWriteOszRexw(m, rde); + x = ReadMemory(rde, RegRexrReg(m, rde)); + y = ReadMemory(rde, p); + WriteRegister(rde, RegRexrReg(m, rde), y); + WriteRegisterOrMemory(rde, p, x); } -static void OpCmpxchgEbAlGb(struct Machine *m) { +static void OpCmpxchgEbAlGb(struct Machine *m, uint32_t rde) { uint8_t *p; uint8_t x, y, z; - p = GetModrmRegisterBytePointerWrite(m); + p = GetModrmRegisterBytePointerWrite(m, rde); x = Read8(m->ax); y = Read8(p); - z = Read8(ByteRexrReg(m)); + z = Read8(ByteRexrReg(m, rde)); Alu(0, ALU_SUB, x, y, &m->flags); if (GetFlag(m->flags, FLAGS_ZF)) { Write8(p, z); @@ -436,25 +428,25 @@ static void OpCmpxchgEbAlGb(struct Machine *m) { } } -static void OpCmpxchgEvqpRaxGvqp(struct Machine *m) { +static void OpCmpxchgEvqpRaxGvqp(struct Machine *m, uint32_t rde) { uint8_t *p; uint64_t x, y, z; - p = GetModrmRegisterWordPointerWriteOszRexw(m); - x = ReadMemory(m, m->ax); - y = ReadMemory(m, p); - z = ReadMemory(m, RegRexrReg(m)); - Alu(RegLog2(m->xedd), ALU_SUB, x, y, &m->flags); + p = GetModrmRegisterWordPointerWriteOszRexw(m, rde); + x = ReadMemory(rde, m->ax); + y = ReadMemory(rde, p); + z = ReadMemory(rde, RegRexrReg(m, rde)); + Alu(RegLog2(rde), ALU_SUB, x, y, &m->flags); if (GetFlag(m->flags, FLAGS_ZF)) { - WriteRegisterOrMemory(m, p, z); + WriteRegisterOrMemory(rde, p, z); } else { - WriteRegister(m, m->ax, y); + WriteRegister(rde, m->ax, y); } } -static void OpCmpxchg8b(struct Machine *m) { +static void OpCmpxchg8b(struct Machine *m, uint32_t rde) { uint8_t *p; uint32_t d, a; - p = GetModrmRegisterXmmPointerRead8(m); + p = GetModrmRegisterXmmPointerRead8(m, rde); a = Read32(p + 0); d = Read32(p + 4); if (a == Read32(m->ax) && d == Read32(m->dx)) { @@ -468,10 +460,10 @@ static void OpCmpxchg8b(struct Machine *m) { } } -static void OpCmpxchg16b(struct Machine *m) { +static void OpCmpxchg16b(struct Machine *m, uint32_t rde) { uint8_t *p; uint64_t d, a; - p = GetModrmRegisterXmmPointerRead16(m); + p = GetModrmRegisterXmmPointerRead16(m, rde); a = Read64(p + 0); d = Read64(p + 8); if (a == Read64(m->ax) && d == Read64(m->dx)) { @@ -485,18 +477,41 @@ static void OpCmpxchg16b(struct Machine *m) { } } -static void OpCmpxchgDxAx(struct Machine *m) { - if (Rexw(m->xedd)) { - OpCmpxchg16b(m); +static void OpCmpxchgDxAx(struct Machine *m, uint32_t rde) { + if (Rexw(rde)) { + OpCmpxchg16b(m, rde); } else { - OpCmpxchg8b(m); + OpCmpxchg8b(m, rde); } } -static uint64_t OpDoubleShift(struct Machine *m, uint64_t x, uint64_t y) { +static void OpXaddEbGb(struct Machine *m, uint32_t rde) { + uint8_t *p; + uint8_t x, y, z; + p = GetModrmRegisterWordPointerWriteOszRexw(m, rde); + x = Read8(p); + y = Read8(RegRexrReg(m, rde)); + z = Alu(0, ALU_ADD, x, y, &m->flags); + Write8(p, z); + Write8(RegRexrReg(m, rde), x); +} + +static void OpXaddEvqpGvqp(struct Machine *m, uint32_t rde) { + uint8_t *p; + uint64_t x, y, z; + p = GetModrmRegisterWordPointerWriteOszRexw(m, rde); + x = ReadMemory(rde, p); + y = ReadMemory(rde, RegRexrReg(m, rde)); + z = Alu(RegLog2(rde), ALU_ADD, x, y, &m->flags); + WriteRegisterOrMemory(rde, p, z); + WriteRegister(rde, RegRexrReg(m, rde), x); +} + +static uint64_t OpDoubleShift(struct Machine *m, uint32_t rde, uint64_t x, + uint64_t y) { uint8_t b, w, W[2][2] = {{2, 3}, {1, 3}}; return BsuDoubleShift( - W[Osz(m->xedd)][Rexw(m->xedd)], x, y, + W[Osz(rde)][Rexw(rde)], x, y, m->xedd->op.opcode & 1 ? Read8(m->cx) : m->xedd->op.uimm0, m->xedd->op.opcode & 8, &m->flags); } @@ -513,30 +528,30 @@ static uint64_t OpBtc(uint64_t x, uint64_t y) { return (x & ~y) | (~x & y); } -static void OpBit(struct Machine *m) { +static void OpBit(struct Machine *m, uint32_t rde) { int op; uint8_t *p; unsigned bit; int64_t disp; uint64_t v, x, y, z; uint8_t w, W[2][2] = {{2, 3}, {1, 3}}; - w = W[Osz(m->xedd)][Rexw(m->xedd)]; + w = W[Osz(rde)][Rexw(rde)]; if (m->xedd->op.opcode == 0xBA) { - op = ModrmReg(m->xedd); + op = ModrmReg(rde); bit = m->xedd->op.uimm0 & ((8 << w) - 1); disp = 0; } else { op = (m->xedd->op.opcode & 070) >> 3; - disp = ReadMemorySigned(m, RegRexrReg(m)); + disp = ReadMemorySigned(rde, RegRexrReg(m, rde)); bit = disp & ((8 << w) - 1); disp &= -(8 << w); disp >>= 3; } - if (IsModrmRegister(m->xedd)) { - p = RegRexbRm(m); + if (IsModrmRegister(rde)) { + p = RegRexbRm(m, rde); } else { - v = ComputeAddress(m) + disp; - if (Asz(m->xedd)) v &= 0xffffffff; + v = ComputeAddress(m, rde) + disp; + if (Asz(rde)) v &= 0xffffffff; p = ReserveAddress(m, v, 1 << w); if (op == 4) { SetReadAddr(m, v, 1 << w); @@ -545,7 +560,7 @@ static void OpBit(struct Machine *m) { } } y = 1ull << bit; - x = ReadMemory(m, p); + x = ReadMemory(rde, p); m->flags = SetFlag(m->flags, FLAGS_CF, !!(y & x)); switch (op) { case 4: @@ -562,45 +577,46 @@ static void OpBit(struct Machine *m) { default: OpUd(m); } - WriteRegisterOrMemory(m, p, z); + WriteRegisterOrMemory(rde, p, z); } -static void OpConvert1(struct Machine *m) { - if (Rexw(m->xedd)) { +static void OpConvert1(struct Machine *m, uint32_t rde) { + if (Rexw(rde)) { Write64(m->ax, Read32(m->ax) | (Read32(m->ax) & 0x80000000 ? 0xffffffff00000000 : 0)); - } else if (!Osz(m->xedd)) { + } else if (!Osz(rde)) { Write64(m->ax, Read16(m->ax) | (Read16(m->ax) & 0x8000 ? 0xffff0000 : 0)); } else { Write16(m->ax, Read8(m->ax) | (Read8(m->ax) & 0x0080 ? 0xff00 : 0)); } } -static void OpConvert2(struct Machine *m) { - if (Rexw(m->xedd)) { +static void OpConvert2(struct Machine *m, uint32_t rde) { + if (Rexw(rde)) { Write64(m->dx, Read64(m->ax) & 0x8000000000000000 ? 0xffffffffffffffff : 0); - } else if (!Osz(m->xedd)) { + } else if (!Osz(rde)) { Write64(m->dx, Read32(m->ax) & 0x80000000 ? 0xffffffff : 0); } else { Write16(m->dx, Read16(m->ax) & 0x8000 ? 0xffff : 0); } } -static void OpBswapZvqp(struct Machine *m) { +static void OpBswapZvqp(struct Machine *m, uint32_t rde) { uint64_t x; - x = Read64(RegRexbSrm(m)); - if (Rexw(m->xedd)) { + x = Read64(RegRexbSrm(m, rde)); + if (Rexw(rde)) { Write64( - RegRexbSrm(m), + RegRexbSrm(m, rde), ((x & 0xff00000000000000) >> 070 | (x & 0x00000000000000ff) << 070 | (x & 0x00ff000000000000) >> 050 | (x & 0x000000000000ff00) << 050 | (x & 0x0000ff0000000000) >> 030 | (x & 0x0000000000ff0000) << 030 | (x & 0x000000ff00000000) >> 010 | (x & 0x00000000ff000000) << 010)); - } else if (!Osz(m->xedd)) { - Write64(RegRexbSrm(m), ((x & 0xff000000) >> 030 | (x & 0x000000ff) << 030 | - (x & 0x00ff0000) >> 010 | (x & 0x0000ff00) << 010)); + } else if (!Osz(rde)) { + Write64(RegRexbSrm(m, rde), + ((x & 0xff000000) >> 030 | (x & 0x000000ff) << 030 | + (x & 0x00ff0000) >> 010 | (x & 0x0000ff00) << 010)); } else { - Write16(RegRexbSrm(m), (x & 0x00ff) << 010 | (x & 0xff00) << 010); + Write16(RegRexbSrm(m, rde), ((x & 0x00ff) << 010 | (x & 0xff00) << 010)); } } @@ -611,29 +627,16 @@ static uint8_t pmovmskb(uint64_t x) { (x & 0x0080000000000000) >> 061 | (x & 0x8000000000000000) >> 070; } -static void OpPmovmskbGdqpNqUdq(struct Machine *m) { +static void OpPmovmskbGdqpNqUdq(struct Machine *m, uint32_t rde) { uint64_t bitmask; - if (Osz(m->xedd)) { - bitmask = pmovmskb(Read64(XmmRexbRm(m) + 8)) << 8 | - pmovmskb(Read64(XmmRexbRm(m))); + if (Osz(rde)) { + bitmask = pmovmskb(Read64(XmmRexbRm(m, rde) + 8)) << 8 | + pmovmskb(Read64(XmmRexbRm(m, rde))); } else { - bitmask = pmovmskb(Read64(MmRm(m) + 8)) << 8 | pmovmskb(Read64(MmRm(m))); + bitmask = pmovmskb(Read64(MmRm(m, rde) + 8)) << 8 | + pmovmskb(Read64(MmRm(m, rde))); } - Write64(RegRexrReg(m), bitmask); -} - -static void OpRdtsc(struct Machine *m) { - uint64_t c; -#ifdef __x86_64__ - c = rdtsc(); -#else - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - c = ts.tv_sec * 1000000000 + ts.tv_nsec; -#endif - Write64(m->ax, c & 0xffffffff); - c >>= 32; - Write64(m->dx, c & 0xffffffff); + Write64(RegRexrReg(m, rde), bitmask); } static void OpMovEvqpSw(struct Machine *m) { @@ -644,8 +647,8 @@ static void OpMovSwEvqp(struct Machine *m) { ThrowSegmentationFault(m, m->ip); } -static void OpMovEbIb(struct Machine *m) { - Write8(GetModrmRegisterBytePointerWrite(m), m->xedd->op.uimm0); +static void OpMovEbIb(struct Machine *m, uint32_t rde) { + Write8(GetModrmRegisterBytePointerWrite(m, rde), m->xedd->op.uimm0); } static void OpMovAlOb(struct Machine *m) { @@ -656,530 +659,532 @@ static void OpMovObAl(struct Machine *m) { memcpy(m->ax, ResolveAddress(m, m->xedd->op.uimm0), 1); } -static void OpMovRaxOvqp(struct Machine *m) { - WriteRegister(m, m->ax, ReadMemory(m, ResolveAddress(m, m->xedd->op.uimm0))); +static void OpMovRaxOvqp(struct Machine *m, uint32_t rde) { + WriteRegister(rde, m->ax, + ReadMemory(rde, ResolveAddress(m, m->xedd->op.uimm0))); } -static void OpMovOvqpRax(struct Machine *m) { - WriteMemory(m, ResolveAddress(m, m->xedd->op.uimm0), Read64(m->ax)); +static void OpMovOvqpRax(struct Machine *m, uint32_t rde) { + WriteMemory(rde, ResolveAddress(m, m->xedd->op.uimm0), Read64(m->ax)); } -static void OpMovEbGb(struct Machine *m) { - memcpy(GetModrmRegisterBytePointerWrite(m), ByteRexrReg(m), 1); +static void OpMovEbGb(struct Machine *m, uint32_t rde) { + memcpy(GetModrmRegisterBytePointerWrite(m, rde), ByteRexrReg(m, rde), 1); } -static void OpMovGbEb(struct Machine *m) { - memcpy(ByteRexrReg(m), GetModrmRegisterBytePointerRead(m), 1); +static void OpMovGbEb(struct Machine *m, uint32_t rde) { + memcpy(ByteRexrReg(m, rde), GetModrmRegisterBytePointerRead(m, rde), 1); } -static void OpMovZbIb(struct Machine *m) { - Write8(ByteRexbSrm(m), m->xedd->op.uimm0); +static void OpMovZbIb(struct Machine *m, uint32_t rde) { + Write8(ByteRexbSrm(m, rde), m->xedd->op.uimm0); } -static void OpMovZvqpIvqp(struct Machine *m) { - WriteRegister(m, RegRexbSrm(m), m->xedd->op.uimm0); +static void OpMovZvqpIvqp(struct Machine *m, uint32_t rde) { + WriteRegister(rde, RegRexbSrm(m, rde), m->xedd->op.uimm0); } -static void OpMovEvqpIvds(struct Machine *m) { - WriteRegisterOrMemory(m, GetModrmRegisterWordPointerWriteOszRexw(m), +static void OpMovEvqpIvds(struct Machine *m, uint32_t rde) { + WriteRegisterOrMemory(rde, GetModrmRegisterWordPointerWriteOszRexw(m, rde), m->xedd->op.uimm0); } -static void OpMovEvqpGvqp(struct Machine *m) { - WriteRegisterOrMemory(m, GetModrmRegisterWordPointerWriteOszRexw(m), - ReadMemory(m, RegRexrReg(m))); +noinline void OpMovEvqpGvqp(struct Machine *m, uint32_t rde) { + WriteRegisterOrMemory(rde, GetModrmRegisterWordPointerWriteOszRexw(m, rde), + ReadMemory(rde, RegRexrReg(m, rde))); } -static void OpMovGvqpEvqp(struct Machine *m) { - WriteRegister(m, RegRexrReg(m), - ReadMemory(m, GetModrmRegisterWordPointerReadOszRexw(m))); +static void OpMovGvqpEvqp(struct Machine *m, uint32_t rde) { + WriteRegister( + rde, RegRexrReg(m, rde), + ReadMemory(rde, GetModrmRegisterWordPointerReadOszRexw(m, rde))); } -static void OpMovzbGvqpEb(struct Machine *m) { - WriteRegister(m, RegRexrReg(m), Read8(GetModrmRegisterBytePointerRead(m))); +static void OpMovzbGvqpEb(struct Machine *m, uint32_t rde) { + WriteRegister(rde, RegRexrReg(m, rde), + Read8(GetModrmRegisterBytePointerRead(m, rde))); } -static void OpMovzwGvqpEw(struct Machine *m) { - WriteRegister(m, RegRexrReg(m), Read16(GetModrmRegisterWordPointerRead2(m))); +static void OpMovzwGvqpEw(struct Machine *m, uint32_t rde) { + WriteRegister(rde, RegRexrReg(m, rde), + Read16(GetModrmRegisterWordPointerRead2(m, rde))); } -static void OpMovsbGvqpEb(struct Machine *m) { - WriteRegister(m, RegRexrReg(m), - (int8_t)Read8(GetModrmRegisterBytePointerRead(m))); +static void OpMovsbGvqpEb(struct Machine *m, uint32_t rde) { + WriteRegister(rde, RegRexrReg(m, rde), + (int8_t)Read8(GetModrmRegisterBytePointerRead(m, rde))); } -static void OpMovswGvqpEw(struct Machine *m) { - WriteRegister(m, RegRexrReg(m), - (int16_t)Read16(GetModrmRegisterWordPointerRead2(m))); +static void OpMovswGvqpEw(struct Machine *m, uint32_t rde) { + WriteRegister(rde, RegRexrReg(m, rde), + (int16_t)Read16(GetModrmRegisterWordPointerRead2(m, rde))); } -static void OpMovsxdGdqpEd(struct Machine *m) { +static void OpMovsxdGdqpEd(struct Machine *m, uint32_t rde) { uint64_t x; uint8_t *p; - x = (int32_t)Read32(GetModrmRegisterWordPointerRead4(m)); - if (!Rexw(m->xedd)) x &= 0xffffffff; /* wut */ - Write64(RegRexrReg(m), x); + x = (int32_t)Read32(GetModrmRegisterWordPointerRead4(m, rde)); + if (!Rexw(rde)) x &= 0xffffffff; /* wut */ + Write64(RegRexrReg(m, rde), x); } -static void OpMovdquVdqWdq(struct Machine *m) { - memcpy(XmmRexrReg(m), GetModrmRegisterXmmPointerRead16(m), 16); +static void OpMovdquVdqWdq(struct Machine *m, uint32_t rde) { + memcpy(XmmRexrReg(m, rde), GetModrmRegisterXmmPointerRead16(m, rde), 16); } -static void OpMovdquWdqVdq(struct Machine *m) { - memcpy(GetModrmRegisterXmmPointerWrite16(m), XmmRexrReg(m), 16); +static void OpMovdquWdqVdq(struct Machine *m, uint32_t rde) { + memcpy(GetModrmRegisterXmmPointerWrite16(m, rde), XmmRexrReg(m, rde), 16); } -static void OpMovupsVpsWps(struct Machine *m) { - OpMovdquVdqWdq(m); +static void OpMovupsVpsWps(struct Machine *m, uint32_t rde) { + OpMovdquVdqWdq(m, rde); } -static void OpMovupsWpsVps(struct Machine *m) { - OpMovdquWdqVdq(m); +static void OpMovupsWpsVps(struct Machine *m, uint32_t rde) { + OpMovdquWdqVdq(m, rde); } -static void OpMovupdVpsWps(struct Machine *m) { - OpMovdquVdqWdq(m); +static void OpMovupdVpsWps(struct Machine *m, uint32_t rde) { + OpMovdquVdqWdq(m, rde); } -static void OpMovupdWpsVps(struct Machine *m) { - OpMovdquWdqVdq(m); +static void OpMovupdWpsVps(struct Machine *m, uint32_t rde) { + OpMovdquWdqVdq(m, rde); } -static void OpLddquVdqMdq(struct Machine *m) { - OpMovdquVdqWdq(m); +static void OpLddquVdqMdq(struct Machine *m, uint32_t rde) { + OpMovdquVdqWdq(m, rde); } -static void OpMovdqaVdqMdq(struct Machine *m) { +static void OpMovdqaVdqMdq(struct Machine *m, uint32_t rde) { int64_t v; uint8_t *p; - v = ComputeAddress(m); + v = ComputeAddress(m, rde); SetReadAddr(m, v, 16); if ((v & 15) || !(p = FindReal(m, v))) ThrowSegmentationFault(m, v); - memcpy(XmmRexrReg(m), Abp16(p), 16); + memcpy(XmmRexrReg(m, rde), Abp16(p), 16); } -static void OpMovdqaMdqVdq(struct Machine *m) { +static void OpMovdqaMdqVdq(struct Machine *m, uint32_t rde) { int64_t v; uint8_t *p; - v = ComputeAddress(m); + v = ComputeAddress(m, rde); SetWriteAddr(m, v, 16); if ((v & 15) || !(p = FindReal(m, v))) ThrowSegmentationFault(m, v); - memcpy(Abp16(p), XmmRexrReg(m), 16); + memcpy(Abp16(p), XmmRexrReg(m, rde), 16); } -static void OpMovdqaVdqWdq(struct Machine *m) { - if (IsModrmRegister(m->xedd)) { - memcpy(XmmRexrReg(m), XmmRexbRm(m), 16); +static void OpMovdqaVdqWdq(struct Machine *m, uint32_t rde) { + if (IsModrmRegister(rde)) { + memcpy(XmmRexrReg(m, rde), XmmRexbRm(m, rde), 16); } else { - OpMovdqaVdqMdq(m); + OpMovdqaVdqMdq(m, rde); } } -static void OpMovdqaWdqVdq(struct Machine *m) { - if (IsModrmRegister(m->xedd)) { - memcpy(XmmRexbRm(m), XmmRexrReg(m), 16); +static void OpMovdqaWdqVdq(struct Machine *m, uint32_t rde) { + if (IsModrmRegister(rde)) { + memcpy(XmmRexbRm(m, rde), XmmRexrReg(m, rde), 16); } else { - OpMovdqaMdqVdq(m); + OpMovdqaMdqVdq(m, rde); } } -static void OpMovntiMdqpGdqp(struct Machine *m) { +static void OpMovntiMdqpGdqp(struct Machine *m, uint32_t rde) { int64_t v; uint8_t *a; void *p[2]; uint8_t n, b[8]; - v = ComputeAddress(m); - n = Rexw(m->xedd) ? 8 : 4; + v = ComputeAddress(m, rde); + n = Rexw(rde) ? 8 : 4; a = BeginStore(m, v, n, p, b); SetWriteAddr(m, v, n); - memcpy(p, XmmRexrReg(m), n); + memcpy(p, XmmRexrReg(m, rde), n); EndStore(m, v, n, p, b); } -static void OpMovntdqMdqVdq(struct Machine *m) { - OpMovdqaMdqVdq(m); +static void OpMovntdqMdqVdq(struct Machine *m, uint32_t rde) { + OpMovdqaMdqVdq(m, rde); } -static void OpMovntpsMpsVps(struct Machine *m) { - OpMovdqaMdqVdq(m); +static void OpMovntpsMpsVps(struct Machine *m, uint32_t rde) { + OpMovdqaMdqVdq(m, rde); } -static void OpMovntpdMpdVpd(struct Machine *m) { - OpMovdqaMdqVdq(m); +static void OpMovntpdMpdVpd(struct Machine *m, uint32_t rde) { + OpMovdqaMdqVdq(m, rde); } -static void OpMovntdqaVdqMdq(struct Machine *m) { - OpMovdqaVdqMdq(m); +static void OpMovntdqaVdqMdq(struct Machine *m, uint32_t rde) { + OpMovdqaVdqMdq(m, rde); } -static void OpMovqPqQq(struct Machine *m) { - memcpy(MmReg(m), GetModrmRegisterMmPointerRead8(m), 8); +static void OpMovqPqQq(struct Machine *m, uint32_t rde) { + memcpy(MmReg(m, rde), GetModrmRegisterMmPointerRead8(m, rde), 8); } -static void OpMovqQqPq(struct Machine *m) { - memcpy(GetModrmRegisterMmPointerWrite8(m), MmReg(m), 8); +static void OpMovqQqPq(struct Machine *m, uint32_t rde) { + memcpy(GetModrmRegisterMmPointerWrite8(m, rde), MmReg(m, rde), 8); } -static void OpMovqVdqEqp(struct Machine *m) { - memcpy(XmmRexrReg(m), GetModrmRegisterWordPointerRead8(m), 8); - memset(XmmRexrReg(m) + 8, 0, 8); +static void OpMovqVdqEqp(struct Machine *m, uint32_t rde) { + memcpy(XmmRexrReg(m, rde), GetModrmRegisterWordPointerRead8(m, rde), 8); + memset(XmmRexrReg(m, rde) + 8, 0, 8); } -static void OpMovdVdqEd(struct Machine *m) { - memset(XmmRexrReg(m), 0, 16); - memcpy(XmmRexrReg(m), GetModrmRegisterWordPointerRead4(m), 4); +static void OpMovdVdqEd(struct Machine *m, uint32_t rde) { + memset(XmmRexrReg(m, rde), 0, 16); + memcpy(XmmRexrReg(m, rde), GetModrmRegisterWordPointerRead4(m, rde), 4); } -static void OpMovqPqEqp(struct Machine *m) { - memcpy(MmReg(m), GetModrmRegisterWordPointerRead8(m), 8); +static void OpMovqPqEqp(struct Machine *m, uint32_t rde) { + memcpy(MmReg(m, rde), GetModrmRegisterWordPointerRead8(m, rde), 8); } -static void OpMovdPqEd(struct Machine *m) { - memcpy(MmReg(m), GetModrmRegisterWordPointerRead4(m), 4); - memset(MmReg(m) + 4, 0, 4); +static void OpMovdPqEd(struct Machine *m, uint32_t rde) { + memcpy(MmReg(m, rde), GetModrmRegisterWordPointerRead4(m, rde), 4); + memset(MmReg(m, rde) + 4, 0, 4); } -static void OpMovdEdVdq(struct Machine *m) { - if (IsModrmRegister(m->xedd)) { - memset(RegRexbRm(m), 0, 16); - memcpy(RegRexbRm(m), XmmRexrReg(m), 4); +static void OpMovdEdVdq(struct Machine *m, uint32_t rde) { + if (IsModrmRegister(rde)) { + Write64(RegRexbRm(m, rde), Read32(XmmRexrReg(m, rde))); } else { - memcpy(ComputeReserveAddressWrite4(m), XmmRexrReg(m), 4); + memcpy(ComputeReserveAddressWrite4(m, rde), XmmRexrReg(m, rde), 4); } } -static void OpMovqEqpVdq(struct Machine *m) { - memcpy(GetModrmRegisterWordPointerWrite8(m), XmmRexrReg(m), 8); +static void OpMovqEqpVdq(struct Machine *m, uint32_t rde) { + memcpy(GetModrmRegisterWordPointerWrite8(m, rde), XmmRexrReg(m, rde), 8); } -static void OpMovdEdPq(struct Machine *m) { - if (IsModrmRegister(m->xedd)) { - memcpy(RegRexbRm(m), MmReg(m), 4); - memset(RegRexbRm(m) + 4, 0, 4); +static void OpMovdEdPq(struct Machine *m, uint32_t rde) { + if (IsModrmRegister(rde)) { + Write64(RegRexbRm(m, rde), Read32(MmReg(m, rde))); } else { - memcpy(ComputeReserveAddressWrite4(m), MmReg(m), 4); + memcpy(ComputeReserveAddressWrite4(m, rde), MmReg(m, rde), 4); } } -static void OpMovqEqpPq(struct Machine *m) { - memcpy(GetModrmRegisterWordPointerWrite(m, 8), MmReg(m), 8); +static void OpMovqEqpPq(struct Machine *m, uint32_t rde) { + memcpy(GetModrmRegisterWordPointerWrite(m, rde, 8), MmReg(m, rde), 8); } -static void OpMovntqMqPq(struct Machine *m) { - memcpy(ComputeReserveAddressWrite8(m), MmReg(m), 8); +static void OpMovntqMqPq(struct Machine *m, uint32_t rde) { + memcpy(ComputeReserveAddressWrite8(m, rde), MmReg(m, rde), 8); } -static void OpMovqVqWq(struct Machine *m) { - memcpy(XmmRexrReg(m), GetModrmRegisterXmmPointerRead8(m), 8); - memset(XmmRexrReg(m) + 8, 0, 8); +static void OpMovqVqWq(struct Machine *m, uint32_t rde) { + memcpy(XmmRexrReg(m, rde), GetModrmRegisterXmmPointerRead8(m, rde), 8); + memset(XmmRexrReg(m, rde) + 8, 0, 8); } -static void OpMovssVpsWps(struct Machine *m) { - memcpy(XmmRexrReg(m), GetModrmRegisterXmmPointerRead4(m), 4); +static void OpMovssVpsWps(struct Machine *m, uint32_t rde) { + memcpy(XmmRexrReg(m, rde), GetModrmRegisterXmmPointerRead4(m, rde), 4); } -static void OpMovssWpsVps(struct Machine *m) { - memcpy(GetModrmRegisterXmmPointerWrite4(m), XmmRexrReg(m), 4); +static void OpMovssWpsVps(struct Machine *m, uint32_t rde) { + memcpy(GetModrmRegisterXmmPointerWrite4(m, rde), XmmRexrReg(m, rde), 4); } -static void OpMovsdVpsWps(struct Machine *m) { - memcpy(XmmRexrReg(m), GetModrmRegisterXmmPointerRead16(m), 8); +static void OpMovsdVpsWps(struct Machine *m, uint32_t rde) { + memcpy(XmmRexrReg(m, rde), GetModrmRegisterXmmPointerRead16(m, rde), 8); } -static void OpMovsdWpsVps(struct Machine *m) { - memcpy(GetModrmRegisterXmmPointerWrite16(m), XmmRexrReg(m), 8); +static void OpMovsdWpsVps(struct Machine *m, uint32_t rde) { + memcpy(GetModrmRegisterXmmPointerWrite16(m, rde), XmmRexrReg(m, rde), 8); } -static void OpMaskMovDiXmmRegXmmRm(struct Machine *m) { +static void OpMaskMovDiXmmRegXmmRm(struct Machine *m, uint32_t rde) { void *p[2]; uint64_t v; unsigned i, n; uint8_t *mem, b[16]; - n = Osz(m->xedd) ? 16 : 8; + n = Osz(rde) ? 16 : 8; v = GetSegment() + Read64(m->di); - if (Asz(m->xedd)) v &= 0xffffffff; + if (Asz(rde)) v &= 0xffffffff; mem = BeginStore(m, v, n, p, b); for (i = 0; i < n; ++i) { - if (XmmRexbRm(m)[i] & 0x80) { - mem[i] = XmmRexrReg(m)[i]; + if (XmmRexbRm(m, rde)[i] & 0x80) { + mem[i] = XmmRexrReg(m, rde)[i]; } } EndStore(m, v, n, p, b); } -static void OpMovhlpsVqUq(struct Machine *m) { - memcpy(XmmRexrReg(m), XmmRexbRm(m) + 8, 8); +static void OpMovhlpsVqUq(struct Machine *m, uint32_t rde) { + memcpy(XmmRexrReg(m, rde), XmmRexbRm(m, rde) + 8, 8); } -static void OpMovlpsVqMq(struct Machine *m) { - memcpy(XmmRexrReg(m), ComputeReserveAddressRead8(m), 8); +static void OpMovlpsVqMq(struct Machine *m, uint32_t rde) { + memcpy(XmmRexrReg(m, rde), ComputeReserveAddressRead8(m, rde), 8); } -static void OpMovlpdVqMq(struct Machine *m) { - memcpy(XmmRexrReg(m), ComputeReserveAddressRead8(m), 8); +static void OpMovlpdVqMq(struct Machine *m, uint32_t rde) { + memcpy(XmmRexrReg(m, rde), ComputeReserveAddressRead8(m, rde), 8); } -static void OpMovddupVqWq(struct Machine *m) { +static void OpMovddupVqWq(struct Machine *m, uint32_t rde) { uint8_t *dst, *src; - dst = XmmRexrReg(m); - src = GetModrmRegisterXmmPointerRead8(m); + dst = XmmRexrReg(m, rde); + src = GetModrmRegisterXmmPointerRead8(m, rde); memcpy(dst + 0, src, 8); memcpy(dst + 8, src, 8); } -static void OpMovsldupVqWq(struct Machine *m) { +static void OpMovsldupVqWq(struct Machine *m, uint32_t rde) { uint8_t *dst, *src; - dst = XmmRexrReg(m); - src = GetModrmRegisterXmmPointerRead16(m); + dst = XmmRexrReg(m, rde); + src = GetModrmRegisterXmmPointerRead16(m, rde); memcpy(dst + 0 + 0, src + 0, 4); memcpy(dst + 0 + 4, src + 0, 4); memcpy(dst + 8 + 0, src + 8, 4); memcpy(dst + 8 + 4, src + 8, 4); } -static void OpMovlpsMqVq(struct Machine *m) { - memcpy(ComputeReserveAddressWrite8(m), XmmRexrReg(m), 8); +static void OpMovlpsMqVq(struct Machine *m, uint32_t rde) { + memcpy(ComputeReserveAddressWrite8(m, rde), XmmRexrReg(m, rde), 8); } -static void OpMovlpdMqVq(struct Machine *m) { - memcpy(ComputeReserveAddressWrite8(m), XmmRexrReg(m), 8); +static void OpMovlpdMqVq(struct Machine *m, uint32_t rde) { + memcpy(ComputeReserveAddressWrite8(m, rde), XmmRexrReg(m, rde), 8); } -static void OpMovlhpsVqUq(struct Machine *m) { - memcpy(XmmRexrReg(m) + 8, XmmRexbRm(m), 8); +static void OpMovlhpsVqUq(struct Machine *m, uint32_t rde) { + memcpy(XmmRexrReg(m, rde) + 8, XmmRexbRm(m, rde), 8); } -static void OpMovhpsVqMq(struct Machine *m) { - memcpy(XmmRexrReg(m) + 8, ComputeReserveAddressRead8(m), 8); +static void OpMovhpsVqMq(struct Machine *m, uint32_t rde) { + memcpy(XmmRexrReg(m, rde) + 8, ComputeReserveAddressRead8(m, rde), 8); } -static void OpMovhpdVqMq(struct Machine *m) { - memcpy(XmmRexrReg(m) + 8, ComputeReserveAddressRead8(m), 8); +static void OpMovhpdVqMq(struct Machine *m, uint32_t rde) { + memcpy(XmmRexrReg(m, rde) + 8, ComputeReserveAddressRead8(m, rde), 8); } -static void OpMovshdupVqWq(struct Machine *m) { +static void OpMovshdupVqWq(struct Machine *m, uint32_t rde) { uint8_t *dst, *src; - dst = XmmRexrReg(m); - src = GetModrmRegisterXmmPointerRead16(m); + dst = XmmRexrReg(m, rde); + src = GetModrmRegisterXmmPointerRead16(m, rde); memcpy(dst + 0 + 0, src + 04, 4); memcpy(dst + 0 + 4, src + 04, 4); memcpy(dst + 8 + 0, src + 12, 4); memcpy(dst + 8 + 4, src + 12, 4); } -static void OpMovhpsMqVq(struct Machine *m) { - memcpy(ComputeReserveAddressRead8(m), XmmRexrReg(m) + 8, 8); +static void OpMovhpsMqVq(struct Machine *m, uint32_t rde) { + memcpy(ComputeReserveAddressRead8(m, rde), XmmRexrReg(m, rde) + 8, 8); } -static void OpMovhpdMqVq(struct Machine *m) { - memcpy(ComputeReserveAddressRead8(m), XmmRexrReg(m) + 8, 8); +static void OpMovhpdMqVq(struct Machine *m, uint32_t rde) { + memcpy(ComputeReserveAddressRead8(m, rde), XmmRexrReg(m, rde) + 8, 8); } -static void OpMovqWqVq(struct Machine *m) { - if (IsModrmRegister(m->xedd)) { - memcpy(XmmRexbRm(m), XmmRexrReg(m), 8); - memset(XmmRexbRm(m) + 8, 0, 8); +static void OpMovqWqVq(struct Machine *m, uint32_t rde) { + if (IsModrmRegister(rde)) { + memcpy(XmmRexbRm(m, rde), XmmRexrReg(m, rde), 8); + memset(XmmRexbRm(m, rde) + 8, 0, 8); } else { - memcpy(ComputeReserveAddressWrite8(m), XmmRexrReg(m), 8); + memcpy(ComputeReserveAddressWrite8(m, rde), XmmRexrReg(m, rde), 8); } } -static void OpMovq2dqVdqNq(struct Machine *m) { - memcpy(XmmRexrReg(m), MmRm(m), 8); - memset(XmmRexrReg(m) + 8, 0, 8); +static void OpMovq2dqVdqNq(struct Machine *m, uint32_t rde) { + memcpy(XmmRexrReg(m, rde), MmRm(m, rde), 8); + memset(XmmRexrReg(m, rde) + 8, 0, 8); } -static void OpMovdq2qPqUq(struct Machine *m) { - memcpy(MmReg(m), XmmRexbRm(m), 8); +static void OpMovdq2qPqUq(struct Machine *m, uint32_t rde) { + memcpy(MmReg(m, rde), XmmRexbRm(m, rde), 8); } -static void OpMovapsVpsWps(struct Machine *m) { - OpMovdqaVdqWdq(m); +static void OpMovapsVpsWps(struct Machine *m, uint32_t rde) { + OpMovdqaVdqWdq(m, rde); } -static void OpMovapdVpdWpd(struct Machine *m) { - OpMovdqaVdqWdq(m); +static void OpMovapdVpdWpd(struct Machine *m, uint32_t rde) { + OpMovdqaVdqWdq(m, rde); } -static void OpMovapsWpsVps(struct Machine *m) { - OpMovdqaWdqVdq(m); +static void OpMovapsWpsVps(struct Machine *m, uint32_t rde) { + OpMovdqaWdqVdq(m, rde); } -static void OpMovapdWpdVpd(struct Machine *m) { - OpMovdqaWdqVdq(m); +static void OpMovapdWpdVpd(struct Machine *m, uint32_t rde) { + OpMovdqaWdqVdq(m, rde); } -static void OpMovWpsVps(struct Machine *m) { +static void OpMovWpsVps(struct Machine *m, uint32_t rde) { uint8_t *p, *r; - switch (Rep(m->xedd) | Osz(m->xedd)) { + switch (Rep(rde) | Osz(rde)) { case 0: - OpMovupsWpsVps(m); + OpMovupsWpsVps(m, rde); break; case 1: - OpMovupdWpsVps(m); + OpMovupdWpsVps(m, rde); break; case 2: - OpMovsdWpsVps(m); + OpMovsdWpsVps(m, rde); break; case 3: - OpMovssWpsVps(m); + OpMovssWpsVps(m, rde); break; default: unreachable; } } -static void OpMov0f28(struct Machine *m) { - if (!Osz(m->xedd)) { - OpMovapsVpsWps(m); +static void OpMov0f28(struct Machine *m, uint32_t rde) { + if (!Osz(rde)) { + OpMovapsVpsWps(m, rde); } else { - OpMovapdVpdWpd(m); + OpMovapdVpdWpd(m, rde); } } -static void OpMov0f6e(struct Machine *m) { - if (Osz(m->xedd)) { - if (Rexw(m->xedd)) { - OpMovqVdqEqp(m); +static void OpMov0f6e(struct Machine *m, uint32_t rde) { + if (Osz(rde)) { + if (Rexw(rde)) { + OpMovqVdqEqp(m, rde); } else { - OpMovdVdqEd(m); + OpMovdVdqEd(m, rde); } } else { - if (Rexw(m->xedd)) { - OpMovqPqEqp(m); + if (Rexw(rde)) { + OpMovqPqEqp(m, rde); } else { - OpMovdPqEd(m); + OpMovdPqEd(m, rde); } } } -static void OpMov0f6f(struct Machine *m) { - if (Osz(m->xedd)) { - OpMovdqaVdqWdq(m); - } else if (m->xedd->op.ild_f3) { - OpMovdquVdqWdq(m); +static void OpMov0f6f(struct Machine *m, uint32_t rde) { + if (Osz(rde)) { + OpMovdqaVdqWdq(m, rde); + } else if (Rep(rde) == 3) { + OpMovdquVdqWdq(m, rde); } else { - OpMovqPqQq(m); + OpMovqPqQq(m, rde); } } -static void OpMov0fE7(struct Machine *m) { - if (!Osz(m->xedd)) { - OpMovntqMqPq(m); +static void OpMov0fE7(struct Machine *m, uint32_t rde) { + if (!Osz(rde)) { + OpMovntqMqPq(m, rde); } else { - OpMovntdqMdqVdq(m); + OpMovntdqMdqVdq(m, rde); } } -static void OpMov0f7e(struct Machine *m) { - if (m->xedd->op.ild_f3) { - OpMovqVqWq(m); - } else if (Osz(m->xedd)) { - if (Rexw(m->xedd)) { - OpMovqEqpVdq(m); +static void OpMov0f7e(struct Machine *m, uint32_t rde) { + if (Rep(rde) == 3) { + OpMovqVqWq(m, rde); + } else if (Osz(rde)) { + if (Rexw(rde)) { + OpMovqEqpVdq(m, rde); } else { - OpMovdEdVdq(m); + OpMovdEdVdq(m, rde); } } else { - if (Rexw(m->xedd)) { - OpMovqEqpPq(m); + if (Rexw(rde)) { + OpMovqEqpPq(m, rde); } else { - OpMovdEdPq(m); + OpMovdEdPq(m, rde); } } } -static void OpMov0f7f(struct Machine *m) { - if (m->xedd->op.ild_f3) { - OpMovdquWdqVdq(m); - } else if (Osz(m->xedd)) { - OpMovdqaWdqVdq(m); +static void OpMov0f7f(struct Machine *m, uint32_t rde) { + if (Rep(rde) == 3) { + OpMovdquWdqVdq(m, rde); + } else if (Osz(rde)) { + OpMovdqaWdqVdq(m, rde); } else { - OpMovqQqPq(m); + OpMovqQqPq(m, rde); } } -static void OpMov0f10(struct Machine *m) { +static void OpMov0f10(struct Machine *m, uint32_t rde) { uint8_t *p, *r; - switch (Rep(m->xedd) | Osz(m->xedd)) { + switch (Rep(rde) | Osz(rde)) { case 0: - OpMovupsVpsWps(m); + OpMovupsVpsWps(m, rde); break; case 1: - OpMovupdVpsWps(m); + OpMovupdVpsWps(m, rde); break; case 2: - OpMovsdVpsWps(m); + OpMovsdVpsWps(m, rde); break; case 3: - OpMovssVpsWps(m); + OpMovssVpsWps(m, rde); break; default: unreachable; } } -static void OpMov0f29(struct Machine *m) { - if (!Osz(m->xedd)) { - OpMovapsWpsVps(m); +static void OpMov0f29(struct Machine *m, uint32_t rde) { + if (!Osz(rde)) { + OpMovapsWpsVps(m, rde); } else { - OpMovapdWpdVpd(m); + OpMovapdWpdVpd(m, rde); } } -static void OpMov0f2b(struct Machine *m) { - if (!Osz(m->xedd)) { - OpMovntpsMpsVps(m); +static void OpMov0f2b(struct Machine *m, uint32_t rde) { + if (!Osz(rde)) { + OpMovntpsMpsVps(m, rde); } else { - OpMovntpdMpdVpd(m); + OpMovntpdMpdVpd(m, rde); } } -static void OpMov0f12(struct Machine *m) { - switch (Rep(m->xedd) | Osz(m->xedd)) { +static void OpMov0f12(struct Machine *m, uint32_t rde) { + switch (Rep(rde) | Osz(rde)) { case 0: - if (IsModrmRegister(m->xedd)) { - OpMovhlpsVqUq(m); + if (IsModrmRegister(rde)) { + OpMovhlpsVqUq(m, rde); } else { - OpMovlpsVqMq(m); + OpMovlpsVqMq(m, rde); } break; case 1: - OpMovlpdVqMq(m); + OpMovlpdVqMq(m, rde); break; case 2: - OpMovddupVqWq(m); + OpMovddupVqWq(m, rde); break; case 3: - OpMovsldupVqWq(m); + OpMovsldupVqWq(m, rde); break; default: unreachable; } } -static void OpMov0f13(struct Machine *m) { - if (Osz(m->xedd)) { - OpMovlpdMqVq(m); +static void OpMov0f13(struct Machine *m, uint32_t rde) { + if (Osz(rde)) { + OpMovlpdMqVq(m, rde); } else { - OpMovlpsMqVq(m); + OpMovlpsMqVq(m, rde); } } -static void OpMov0f16(struct Machine *m) { - switch (Rep(m->xedd) | Osz(m->xedd)) { +static void OpMov0f16(struct Machine *m, uint32_t rde) { + switch (Rep(rde) | Osz(rde)) { case 0: - if (IsModrmRegister(m->xedd)) { - OpMovlhpsVqUq(m); + if (IsModrmRegister(rde)) { + OpMovlhpsVqUq(m, rde); } else { - OpMovhpsVqMq(m); + OpMovhpsVqMq(m, rde); } break; case 1: - OpMovhpdVqMq(m); + OpMovhpdVqMq(m, rde); break; case 3: - OpMovshdupVqWq(m); + OpMovshdupVqWq(m, rde); break; default: OpUd(m); @@ -1187,31 +1192,31 @@ static void OpMov0f16(struct Machine *m) { } } -static void OpMov0f17(struct Machine *m) { - if (Osz(m->xedd)) { - OpMovhpdMqVq(m); +static void OpMov0f17(struct Machine *m, uint32_t rde) { + if (Osz(rde)) { + OpMovhpdMqVq(m, rde); } else { - OpMovhpsMqVq(m); + OpMovhpsMqVq(m, rde); } } -static void OpMov0fD6(struct Machine *m) { - if (m->xedd->op.ild_f3) { - OpMovq2dqVdqNq(m); - } else if (m->xedd->op.ild_f2) { - OpMovdq2qPqUq(m); - } else if (Osz(m->xedd)) { - OpMovqWqVq(m); +static void OpMov0fD6(struct Machine *m, uint32_t rde) { + if (Rep(rde) == 3) { + OpMovq2dqVdqNq(m, rde); + } else if (Rep(rde) == 2) { + OpMovdq2qPqUq(m, rde); + } else if (Osz(rde)) { + OpMovqWqVq(m, rde); } else { OpUd(m); } } -static void OpUnpcklpsd(struct Machine *m) { +static void OpUnpcklpsd(struct Machine *m, uint32_t rde) { uint8_t *a, *b; - a = XmmRexrReg(m); - b = GetModrmRegisterXmmPointerRead8(m); - if (Osz(m->xedd)) { + a = XmmRexrReg(m, rde); + b = GetModrmRegisterXmmPointerRead8(m, rde); + if (Osz(rde)) { memcpy(a + 8, b, 8); } else { memcpy(a + 4 * 3, b + 4, 4); @@ -1220,11 +1225,11 @@ static void OpUnpcklpsd(struct Machine *m) { } } -static void OpUnpckhpsd(struct Machine *m) { +static void OpUnpckhpsd(struct Machine *m, uint32_t rde) { uint8_t *a, *b; - a = XmmRexrReg(m); - b = GetModrmRegisterXmmPointerRead16(m); - if (Osz(m->xedd)) { + a = XmmRexrReg(m, rde); + b = GetModrmRegisterXmmPointerRead16(m, rde); + if (Osz(rde)) { memcpy(a + 0, b + 8, 8); memcpy(a + 8, b + 8, 8); } else { @@ -1235,197 +1240,198 @@ static void OpUnpckhpsd(struct Machine *m) { } } -static void OpPextrwGdqpUdqIb(struct Machine *m) { +static void OpPextrwGdqpUdqIb(struct Machine *m, uint32_t rde) { uint8_t i; i = m->xedd->op.uimm0; - i &= Osz(m->xedd) ? 7 : 3; - Write16(RegRexrReg(m), Read16(XmmRexbRm(m) + i * 2)); + i &= Osz(rde) ? 7 : 3; + Write16(RegRexrReg(m, rde), Read16(XmmRexbRm(m, rde) + i * 2)); } -static void OpPinsrwVdqEwIb(struct Machine *m) { +static void OpPinsrwVdqEwIb(struct Machine *m, uint32_t rde) { uint8_t i; i = m->xedd->op.uimm0; - i &= Osz(m->xedd) ? 7 : 3; - Write16(XmmRexrReg(m) + i * 2, Read16(GetModrmRegisterWordPointerRead2(m))); + i &= Osz(rde) ? 7 : 3; + Write16(XmmRexrReg(m, rde) + i * 2, + Read16(GetModrmRegisterWordPointerRead2(m, rde))); } -static void OpShuffle(struct Machine *m) { +static void OpShuffle(struct Machine *m, uint32_t rde) { int16_t q16[4]; int16_t x16[8]; int32_t x32[4]; - switch (Rep(m->xedd) | Osz(m->xedd)) { + switch (Rep(rde) | Osz(rde)) { case 0: - memcpy(q16, GetModrmRegisterXmmPointerRead8(m), 8); + memcpy(q16, GetModrmRegisterXmmPointerRead8(m, rde), 8); (pshufw)(q16, q16, m->xedd->op.uimm0); - memcpy(XmmRexrReg(m), q16, 8); + memcpy(XmmRexrReg(m, rde), q16, 8); break; case 1: - memcpy(x32, GetModrmRegisterXmmPointerRead16(m), 16); + memcpy(x32, GetModrmRegisterXmmPointerRead16(m, rde), 16); (pshufd)(x32, x32, m->xedd->op.uimm0); - memcpy(XmmRexrReg(m), x32, 16); + memcpy(XmmRexrReg(m, rde), x32, 16); break; case 2: - memcpy(x16, GetModrmRegisterXmmPointerRead16(m), 16); + memcpy(x16, GetModrmRegisterXmmPointerRead16(m, rde), 16); (pshuflw)(x16, x16, m->xedd->op.uimm0); - memcpy(XmmRexrReg(m), x16, 16); + memcpy(XmmRexrReg(m, rde), x16, 16); break; case 3: - memcpy(x16, GetModrmRegisterXmmPointerRead16(m), 16); + memcpy(x16, GetModrmRegisterXmmPointerRead16(m, rde), 16); (pshufhw)(x16, x16, m->xedd->op.uimm0); - memcpy(XmmRexrReg(m), x16, 16); + memcpy(XmmRexrReg(m, rde), x16, 16); break; default: unreachable; } } -static void OpShufpsd(struct Machine *m) { +static void OpShufpsd(struct Machine *m, uint32_t rde) { float s[4]; double d[2]; - if (Osz(m->xedd)) { - memcpy(d, GetModrmRegisterXmmPointerRead16(m), 16); + if (Osz(rde)) { + memcpy(d, GetModrmRegisterXmmPointerRead16(m, rde), 16); (shufpd)(d, d, m->xedd->op.uimm0); - memcpy(XmmRexrReg(m), d, 16); + memcpy(XmmRexrReg(m, rde), d, 16); } else { - memcpy(s, GetModrmRegisterXmmPointerRead16(m), 16); + memcpy(s, GetModrmRegisterXmmPointerRead16(m, rde), 16); (shufps)(s, s, m->xedd->op.uimm0); - memcpy(XmmRexrReg(m), s, 16); + memcpy(XmmRexrReg(m, rde), s, 16); } } -static void OpSqrtpsd(struct Machine *m) { +static void OpSqrtpsd(struct Machine *m, uint32_t rde) { long i; float_v xf; double_v xd; - switch (Rep(m->xedd) | Osz(m->xedd)) { + switch (Rep(rde) | Osz(rde)) { case 0: - memcpy(&xf, GetModrmRegisterXmmPointerRead16(m), 16); + memcpy(&xf, GetModrmRegisterXmmPointerRead16(m, rde), 16); for (i = 0; i < 4; ++i) xf[i] = sqrtf(xf[i]); - memcpy(XmmRexrReg(m), &xf, 16); + memcpy(XmmRexrReg(m, rde), &xf, 16); break; case 1: - memcpy(&xd, GetModrmRegisterXmmPointerRead16(m), 16); + memcpy(&xd, GetModrmRegisterXmmPointerRead16(m, rde), 16); for (i = 0; i < 2; ++i) xd[i] = sqrt(xd[i]); - memcpy(XmmRexrReg(m), &xd, 16); + memcpy(XmmRexrReg(m, rde), &xd, 16); break; case 2: - memcpy(&xd, GetModrmRegisterXmmPointerRead8(m), 8); + memcpy(&xd, GetModrmRegisterXmmPointerRead8(m, rde), 8); xd[0] = sqrt(xd[0]); - memcpy(XmmRexrReg(m), &xd, 8); + memcpy(XmmRexrReg(m, rde), &xd, 8); break; case 3: - memcpy(&xf, GetModrmRegisterXmmPointerRead4(m), 4); + memcpy(&xf, GetModrmRegisterXmmPointerRead4(m, rde), 4); xf[0] = sqrtf(xf[0]); - memcpy(XmmRexrReg(m), &xf, 4); + memcpy(XmmRexrReg(m, rde), &xf, 4); break; default: unreachable; } } -static void OpRsqrtps(struct Machine *m) { +static void OpRsqrtps(struct Machine *m, uint32_t rde) { unsigned i; float_v x; - if (!m->xedd->op.ild_f3) { - memcpy(&x, GetModrmRegisterXmmPointerRead16(m), 16); + if (Rep(rde) != 3) { + memcpy(&x, GetModrmRegisterXmmPointerRead16(m, rde), 16); for (i = 0; i < 4; ++i) x[i] = 1.f / sqrtf(x[i]); - memcpy(XmmRexrReg(m), &x, 16); + memcpy(XmmRexrReg(m, rde), &x, 16); } else { - memcpy(&x, GetModrmRegisterXmmPointerRead4(m), 4); + memcpy(&x, GetModrmRegisterXmmPointerRead4(m, rde), 4); x[0] = 1.f / sqrtf(x[0]); - memcpy(XmmRexrReg(m), &x, 4); + memcpy(XmmRexrReg(m, rde), &x, 4); } } -static void OpRcpps(struct Machine *m) { +static void OpRcpps(struct Machine *m, uint32_t rde) { int i; float_v x; - if (!m->xedd->op.ild_f3) { - memcpy(&x, GetModrmRegisterXmmPointerRead16(m), 16); + if (Rep(rde) != 3) { + memcpy(&x, GetModrmRegisterXmmPointerRead16(m, rde), 16); for (i = 0; i < 4; ++i) x[i] = 1.f / x[i]; - memcpy(XmmRexrReg(m), &x, 16); + memcpy(XmmRexrReg(m, rde), &x, 16); } else { - memcpy(&x, GetModrmRegisterXmmPointerRead4(m), 4); + memcpy(&x, GetModrmRegisterXmmPointerRead4(m, rde), 4); x[0] = 1.f / x[0]; - memcpy(XmmRexrReg(m), &x, 4); + memcpy(XmmRexrReg(m, rde), &x, 4); } } -static void OpVpsdWpsd(struct Machine *m, +static void OpVpsdWpsd(struct Machine *m, uint32_t rde, float_v opf(struct Machine *, float_v, float_v), double_v opd(struct Machine *, double_v, double_v), bool isfloat, bool isdouble) { float_v xf, yf; double_v xd, yd; if (isfloat) { - memcpy(&xf, XmmRexrReg(m), 16); - memcpy(&yf, GetModrmRegisterXmmPointerRead16(m), 16); + memcpy(&xf, XmmRexrReg(m, rde), 16); + memcpy(&yf, GetModrmRegisterXmmPointerRead16(m, rde), 16); xf = opf(m, xf, yf); - memcpy(XmmRexrReg(m), &xf, 16); + memcpy(XmmRexrReg(m, rde), &xf, 16); } else if (isdouble) { - memcpy(&xd, XmmRexrReg(m), 16); - memcpy(&yd, GetModrmRegisterXmmPointerRead16(m), 16); + memcpy(&xd, XmmRexrReg(m, rde), 16); + memcpy(&yd, GetModrmRegisterXmmPointerRead16(m, rde), 16); xd = opd(m, xd, yd); - memcpy(XmmRexrReg(m), &xd, 16); + memcpy(XmmRexrReg(m, rde), &xd, 16); } else { OpUd(m); } } -static void OpVpsdWpsd66(struct Machine *m, +static void OpVpsdWpsd66(struct Machine *m, uint32_t rde, float_v opf(struct Machine *, float_v, float_v), double_v opd(struct Machine *, double_v, double_v)) { - OpVpsdWpsd(m, opf, opd, !Osz(m->xedd), Osz(m->xedd)); + OpVpsdWpsd(m, rde, opf, opd, !Osz(rde), Osz(rde)); } -static void OpVpsdWpsd66f2(struct Machine *m, +static void OpVpsdWpsd66f2(struct Machine *m, uint32_t rde, float_v opf(struct Machine *, float_v, float_v), double_v opd(struct Machine *, double_v, double_v)) { - OpVpsdWpsd(m, opf, opd, m->xedd->op.ild_f2, Osz(m->xedd)); + OpVpsdWpsd(m, rde, opf, opd, Rep(rde) == 2, Osz(rde)); } -static void OpVspsdWspsd(struct Machine *m, +static void OpVspsdWspsd(struct Machine *m, uint32_t rde, float_v opf(struct Machine *, float_v, float_v), double_v opd(struct Machine *, double_v, double_v)) { float_v xf, yf; double_v xd, yd; - switch (Rep(m->xedd) | Osz(m->xedd)) { + switch (Rep(rde) | Osz(rde)) { case 0: - memcpy(&yf, GetModrmRegisterXmmPointerRead16(m), 16); - memcpy(&xf, XmmRexrReg(m), 16); + memcpy(&yf, GetModrmRegisterXmmPointerRead16(m, rde), 16); + memcpy(&xf, XmmRexrReg(m, rde), 16); xf = opf(m, xf, yf); - memcpy(XmmRexrReg(m), &xf, 16); + memcpy(XmmRexrReg(m, rde), &xf, 16); break; case 1: - memcpy(&yd, GetModrmRegisterXmmPointerRead16(m), 16); - memcpy(&xd, XmmRexrReg(m), 16); + memcpy(&yd, GetModrmRegisterXmmPointerRead16(m, rde), 16); + memcpy(&xd, XmmRexrReg(m, rde), 16); xd = opd(m, xd, yd); - memcpy(XmmRexrReg(m), &xd, 16); + memcpy(XmmRexrReg(m, rde), &xd, 16); break; case 2: - memcpy(&yd, GetModrmRegisterXmmPointerRead8(m), 8); - memcpy(&xd, XmmRexrReg(m), 8); + memcpy(&yd, GetModrmRegisterXmmPointerRead8(m, rde), 8); + memcpy(&xd, XmmRexrReg(m, rde), 8); xd = opd(m, xd, yd); - memcpy(XmmRexrReg(m), &xd, 8); + memcpy(XmmRexrReg(m, rde), &xd, 8); break; case 3: - memcpy(&yf, GetModrmRegisterXmmPointerRead4(m), 4); - memcpy(&xf, XmmRexrReg(m), 4); + memcpy(&yf, GetModrmRegisterXmmPointerRead4(m, rde), 4); + memcpy(&xf, XmmRexrReg(m, rde), 4); xf = opf(m, xf, yf); - memcpy(XmmRexrReg(m), &xf, 4); + memcpy(XmmRexrReg(m, rde), &xf, 4); break; default: unreachable; } } -static void OpComissVsWs(struct Machine *m) { +static void OpComissVsWs(struct Machine *m, uint32_t rde) { float xf, yf; double xd, yd; uint8_t zf, cf, pf, ie; - if (!Osz(m->xedd)) { - memcpy(&xf, XmmRexrReg(m), 4); - memcpy(&yf, GetModrmRegisterXmmPointerRead4(m), 4); + if (!Osz(rde)) { + memcpy(&xf, XmmRexrReg(m, rde), 4); + memcpy(&yf, GetModrmRegisterXmmPointerRead4(m, rde), 4); if (!isnan(xf) && !isnan(yf)) { zf = xf == yf; cf = xf < yf; @@ -1435,8 +1441,8 @@ static void OpComissVsWs(struct Machine *m) { zf = cf = pf = ie = true; } } else { - memcpy(&xd, XmmRexrReg(m), 8); - memcpy(&yd, GetModrmRegisterXmmPointerRead8(m), 8); + memcpy(&xd, XmmRexrReg(m, rde), 8); + memcpy(&yd, GetModrmRegisterXmmPointerRead8(m, rde), 8); if (!isnan(xd) && !isnan(yd)) { zf = xd == yd; cf = xd < yd; @@ -1636,81 +1642,88 @@ static double_v OpCmppd(struct Machine *m, double_v x, double_v y) { } } -static void OpAddpsd(struct Machine *m) { - OpVspsdWspsd(m, OpAddps, OpAddpd); +static void OpAddpsd(struct Machine *m, uint32_t rde) { + OpVspsdWspsd(m, rde, OpAddps, OpAddpd); } -static void OpMulpsd(struct Machine *m) { - OpVspsdWspsd(m, OpMulps, OpMulpd); +static void OpMulpsd(struct Machine *m, uint32_t rde) { + OpVspsdWspsd(m, rde, OpMulps, OpMulpd); } -static void OpSubpsd(struct Machine *m) { - OpVspsdWspsd(m, OpSubps, OpSubpd); +static void OpSubpsd(struct Machine *m, uint32_t rde) { + OpVspsdWspsd(m, rde, OpSubps, OpSubpd); } -static void OpDivpsd(struct Machine *m) { - OpVspsdWspsd(m, OpDivps, OpDivpd); +static void OpDivpsd(struct Machine *m, uint32_t rde) { + OpVspsdWspsd(m, rde, OpDivps, OpDivpd); } -static void OpMinpsd(struct Machine *m) { - OpVspsdWspsd(m, OpMinps, OpMinpd); +static void OpMinpsd(struct Machine *m, uint32_t rde) { + OpVspsdWspsd(m, rde, OpMinps, OpMinpd); } -static void OpMaxpsd(struct Machine *m) { - OpVspsdWspsd(m, OpMaxps, OpMaxpd); +static void OpMaxpsd(struct Machine *m, uint32_t rde) { + OpVspsdWspsd(m, rde, OpMaxps, OpMaxpd); } -static void OpCmppsd(struct Machine *m) { - OpVspsdWspsd(m, OpCmpps, OpCmppd); +static void OpCmppsd(struct Machine *m, uint32_t rde) { + OpVspsdWspsd(m, rde, OpCmpps, OpCmppd); } -static void OpAndpsd(struct Machine *m) { - OpVpsdWpsd66(m, OpAndps, OpAndpd); +static void OpAndpsd(struct Machine *m, uint32_t rde) { + OpVpsdWpsd66(m, rde, OpAndps, OpAndpd); } -static void OpAndnpsd(struct Machine *m) { - OpVpsdWpsd66(m, OpAndnps, OpAndnpd); +static void OpAndnpsd(struct Machine *m, uint32_t rde) { + OpVpsdWpsd66(m, rde, OpAndnps, OpAndnpd); } -static void OpOrpsd(struct Machine *m) { - OpVpsdWpsd66(m, OpOrps, OpOrpd); +static void OpOrpsd(struct Machine *m, uint32_t rde) { + OpVpsdWpsd66(m, rde, OpOrps, OpOrpd); } -static void OpXorpsd(struct Machine *m) { - OpVpsdWpsd66(m, OpXorps, OpXorpd); +static void OpXorpsd(struct Machine *m, uint32_t rde) { + OpVpsdWpsd66(m, rde, OpXorps, OpXorpd); } -static void OpHaddpsd(struct Machine *m) { - OpVpsdWpsd66f2(m, OpHaddps, OpHaddpd); +static void OpHaddpsd(struct Machine *m, uint32_t rde) { + OpVpsdWpsd66f2(m, rde, OpHaddps, OpHaddpd); } -static void OpHsubpsd(struct Machine *m) { - OpVpsdWpsd66f2(m, OpHsubps, OpHsubpd); +static void OpHsubpsd(struct Machine *m, uint32_t rde) { + OpVpsdWpsd66f2(m, rde, OpHsubps, OpHsubpd); } -static void OpAddsubpsd(struct Machine *m) { - OpVpsdWpsd66f2(m, OpAddsubps, OpAddsubpd); +static void OpAddsubpsd(struct Machine *m, uint32_t rde) { + OpVpsdWpsd66f2(m, rde, OpAddsubps, OpAddsubpd); } -static void OpAluw(struct Machine *m, +static void OpAluw(struct Machine *m, uint32_t rde, int64_t f(int, int, uint64_t, uint64_t, uint32_t *), int h) { int64_t v; void *p[2]; + bool readonly; uint64_t x, y, z; uint8_t w, *a, *b, *c, split[8]; - w = RegLog2(m->xedd); - if (ModrmMod(m->xedd) != 0b11) { - v = ComputeAddress(m); + w = RegLog2(rde); + readonly = (h & ALU_TEST) || (h & 7) == ALU_CMP; + if (IsModrmRegister(rde)) { + v = 0; + a = RegRexbRm(m, rde); + } else { + v = ComputeAddress(m, rde); if (h & ALU_FLIP) { a = Load(m, v, 1 << w, split); } else { - a = BeginLoadStore(m, v, 1 << w, p, split); + a = AccessRam(m, v, 1 << w, p, split, true); + if (readonly) { + SetReadAddr(m, v, 1); + } else { + SetWriteAddr(m, v, 1); + } } - } else { - v = 0; - a = RegRexbRm(m); } - b = RegRexrReg(m); + b = RegRexrReg(m, rde); if (h & ALU_FLIP) { c = b; b = a; @@ -1719,56 +1732,31 @@ static void OpAluw(struct Machine *m, y = Read64(b); x = Read64(a); z = f(w, h, x, y, &m->flags); - switch (w) { - case 0: - Write8(a, z); - break; - case 1: - Write16(a, z); - break; - case 2: - case 3: - Write64(a, z); - break; - default: - unreachable; - } - EndStore(m, v, 1 << w, p, split); - if (h & ALU_XCHG) { - switch (w) { - case 0: - Write8(b, x); - break; - case 1: - Write16(b, x); - break; - case 2: - case 3: - Write64(b, x); - break; - default: - unreachable; - } + if (!readonly) { + WriteRegisterOrMemory(rde, a, z); + EndStore(m, v, 1 << w, p, split); } } -static void OpAlub(struct Machine *m, +static void OpAlub(struct Machine *m, uint32_t rde, int64_t f(int, int, uint64_t, uint64_t, uint32_t *), int h) { int64_t v; + bool readonly; uint64_t x, y, z; uint8_t *a, *b, *c; - if (!m->xedd->op.has_modrm || IsModrmRegister(m->xedd)) { - a = ByteRexbRm(m); + readonly = (h & ALU_TEST) || (h & 7) == ALU_CMP; + if (!m->xedd->op.has_modrm || IsModrmRegister(rde)) { + a = ByteRexbRm(m, rde); } else { - v = ComputeAddress(m); + v = ComputeAddress(m, rde); a = ResolveAddress(m, v); - if (h & ALU_FLIP) { + if ((h & ALU_FLIP) || readonly) { SetReadAddr(m, v, 1); } else { SetWriteAddr(m, v, 1); } } - b = ByteRexrReg(m); + b = ByteRexrReg(m, rde); if (h & ALU_FLIP) { c = b; b = a; @@ -1777,78 +1765,105 @@ static void OpAlub(struct Machine *m, y = Read8(b); x = Read8(a); z = f(0, h, x, y, &m->flags); - Write8(a, z); - if (h & ALU_XCHG) Write8(b, x); + if (!readonly) Write8(a, z); } -static void OpAluwi(struct Machine *m, +static void OpAluwi(struct Machine *m, uint32_t rde, int64_t f(int, int, uint64_t, uint64_t, uint32_t *), int h, uint64_t yimm) { int64_t v; void *p[2]; + bool readonly; uint64_t x, y, z; uint8_t w, *a, *c, split[8]; - w = RegLog2(m->xedd); - if (m->xedd->op.has_modrm && ModrmMod(m->xedd) != 0b11) { - v = ComputeAddress(m); - a = BeginLoadStore(m, v, 1 << w, p, split); - } else { + w = RegLog2(rde); + readonly = (h & ALU_TEST) || (h & 7) == ALU_CMP; + if (!m->xedd->op.has_modrm || IsModrmRegister(rde)) { v = 0; - a = RegRexbRm(m); + a = RegRexbRm(m, rde); + } else { + v = ComputeAddress(m, rde); + a = AccessRam(m, v, 1 << w, p, split, true); + if (readonly) { + SetReadAddr(m, v, 1 << w); + } else { + SetWriteAddr(m, v, 1 << w); + } } y = yimm; x = Read64(a); z = f(w, h, x, y, &m->flags); - switch (w) { - case 0: - Write8(a, z); - break; - case 1: - Write16(a, z); - break; - case 2: - case 3: - Write64(a, z); - break; - default: - unreachable; + if (!readonly) { + WriteRegisterOrMemory(rde, a, z); + EndStore(m, v, 1 << w, p, split); } - EndStore(m, v, 1 << w, p, split); } -static void OpAlubi(struct Machine *m, +static void OpAlubi(struct Machine *m, uint32_t rde, int64_t f(int, int, uint64_t, uint64_t, uint32_t *), int h, uint64_t yimm) { int64_t v; + bool readonly; uint64_t x, y, z; uint8_t *a, *b, *c; - if (!m->xedd->op.has_modrm || IsModrmRegister(m->xedd)) { - a = ByteRexbRm(m); + readonly = (h & ALU_TEST) || (h & 7) == ALU_CMP; + if (!m->xedd->op.has_modrm || IsModrmRegister(rde)) { + a = ByteRexbRm(m, rde); } else { - v = ComputeAddress(m); + v = ComputeAddress(m, rde); a = ResolveAddress(m, v); - SetWriteAddr(m, v, 1); + if (readonly) { + SetReadAddr(m, v, 1); + } else { + SetWriteAddr(m, v, 1); + } } y = yimm; b = NULL; x = Read8(a); z = f(0, h, x, y, &m->flags); - Write8(a, z); + if (!readonly) Write8(a, z); } -static void ExecuteInstructionMap0(struct Machine *m) { +static void OpBsuwi(struct Machine *m, uint32_t rde, + int64_t f(int, int, uint64_t, uint64_t, uint32_t *), int h, + uint64_t yimm) { + int64_t v; + void *p[2]; + uint8_t w, *a, split[8]; + w = RegLog2(rde); + if (IsModrmRegister(rde)) { + v = 0; + a = RegRexbRm(m, rde); + } else { + v = ComputeAddress(m, rde); + a = BeginLoadStore(m, v, 1 << w, p, split); + } + WriteRegisterOrMemory(rde, a, f(w, h, Read64(a), yimm, &m->flags)); + EndStore(m, v, 1 << w, p, split); +} + +static void OpBsubi(struct Machine *m, uint32_t rde, + int64_t f(int, int, uint64_t, uint64_t, uint32_t *), int h, + uint64_t yimm) { + uint8_t *a; + a = GetModrmRegisterBytePointerWrite(m, rde); + Write8(a, f(0, h, Read8(a), yimm, &m->flags)); +} + +void ExecuteInstructionMap0(struct Machine *m, uint32_t rde) { switch (m->xedd->op.opcode) { - CASE(/*0120 0x50*/ 0b01010000 ... 0x57, OpPushZvq(m)); - CASE(/*0130 0x58*/ 0b01011000 ... 0x5f, OpPopZvq(m)); - CASE(/*0143 0x63*/ 0b01100011, OpMovsxdGdqpEd(m)); - CASE(/*0150 0x68*/ 0b01101000, PushOsz(m, m->xedd->op.uimm0)); - CASE(/*0151 0x69*/ 0b01101001, OpImulGvqpEvqpImm(m)); - CASE(/*0152 0x6A*/ 0b01101010, PushOsz(m, m->xedd->op.uimm0)); - CASE(/*0153 0x6B*/ 0b01101011, OpImulGvqpEvqpImm(m)); - CASE(/*0154 0x6C*/ 0b01101100, OpString(m, STRING_INS)); - CASE(/*0155 0x6D*/ 0b01101101, OpString(m, STRING_INS)); - CASE(/*0156 0x6E*/ 0b01101110, OpString(m, STRING_OUTS)); - CASE(/*0157 0x6F*/ 0b01101111, OpString(m, STRING_OUTS)); + CASE(/*0120 0x50*/ 0b01010000 ... 0x57, OpPushZvq(m, rde)); + CASE(/*0130 0x58*/ 0b01011000 ... 0x5f, OpPopZvq(m, rde)); + CASE(/*0143 0x63*/ 0b01100011, OpMovsxdGdqpEd(m, rde)); + CASE(/*0150 0x68*/ 0b01101000, PushOsz(m, rde, m->xedd->op.uimm0)); + CASE(/*0151 0x69*/ 0b01101001, OpImulGvqpEvqpImm(m, rde)); + CASE(/*0152 0x6A*/ 0b01101010, PushOsz(m, rde, m->xedd->op.uimm0)); + CASE(/*0153 0x6B*/ 0b01101011, OpImulGvqpEvqpImm(m, rde)); + CASE(/*0154 0x6C*/ 0b01101100, OpString(m, rde, STRING_INS)); + CASE(/*0155 0x6D*/ 0b01101101, OpString(m, rde, STRING_INS)); + CASE(/*0156 0x6E*/ 0b01101110, OpString(m, rde, STRING_OUTS)); + CASE(/*0157 0x6F*/ 0b01101111, OpString(m, rde, STRING_OUTS)); CASE(/*0160 0x70*/ 0b01110000, if (GetCond(m, 0x0)) OpJmp(m)); CASE(/*0161 0x71*/ 0b01110001, if (GetCond(m, 0x1)) OpJmp(m)); CASE(/*0162 0x72*/ 0b01110010, if (GetCond(m, 0x2)) OpJmp(m)); @@ -1865,67 +1880,67 @@ static void ExecuteInstructionMap0(struct Machine *m) { CASE(/*0175 0x7D*/ 0b01111101, if (GetCond(m, 0xd)) OpJmp(m)); CASE(/*0176 0x7E*/ 0b01111110, if (GetCond(m, 0xe)) OpJmp(m)); CASE(/*0177 0x7F*/ 0b01111111, if (GetCond(m, 0xf)) OpJmp(m)); - CASE(/*0200 0x80*/ 0b10000000, OpAlubi(m, Alu, ModrmReg(m->xedd), UIMM0)); - CASE(/*0201 0x81*/ 0b10000001, OpAluwi(m, Alu, ModrmReg(m->xedd), UIMM0)); - CASE(/*0202 0x82*/ 0b10000010, OpAlubi(m, Alu, ModrmReg(m->xedd), UIMM0)); - CASE(/*0203 0x83*/ 0b10000011, OpAluwi(m, Alu, ModrmReg(m->xedd), UIMM0)); - CASE(/*0204 0x84*/ 0b10000100, OpAlub(m, Alu, ALU_TEST | ALU_AND)); - CASE(/*0205 0x85*/ 0b10000101, OpAluw(m, Alu, ALU_TEST | ALU_AND)); - CASE(/*0206 0x86*/ 0b10000110, OpXchgGbEb(m)); - CASE(/*0207 0x87*/ 0b10000111, OpXchgGvqpEvqp(m)); - CASE(/*0210 0x88*/ 0b10001000, OpMovEbGb(m)); - CASE(/*0211 0x89*/ 0b10001001, OpMovEvqpGvqp(m)); - CASE(/*0212 0x8A*/ 0b10001010, OpMovGbEb(m)); - CASE(/*0213 0x8B*/ 0b10001011, OpMovGvqpEvqp(m)); + CASE(/*0200 0x80*/ 0b10000000, OpAlubi(m, rde, Alu, ModrmReg(rde), UIMM0)); + CASE(/*0201 0x81*/ 0b10000001, OpAluwi(m, rde, Alu, ModrmReg(rde), UIMM0)); + CASE(/*0202 0x82*/ 0b10000010, OpAlubi(m, rde, Alu, ModrmReg(rde), UIMM0)); + CASE(/*0203 0x83*/ 0b10000011, OpAluwi(m, rde, Alu, ModrmReg(rde), UIMM0)); + CASE(/*0204 0x84*/ 0b10000100, OpAlub(m, rde, Alu, TEST)); + CASE(/*0205 0x85*/ 0b10000101, OpAluw(m, rde, Alu, TEST)); + CASE(/*0206 0x86*/ 0b10000110, OpXchgGbEb(m, rde)); + CASE(/*0207 0x87*/ 0b10000111, OpXchgGvqpEvqp(m, rde)); + CASE(/*0210 0x88*/ 0b10001000, OpMovEbGb(m, rde)); + CASE(/*0211 0x89*/ 0b10001001, OpMovEvqpGvqp(m, rde)); + CASE(/*0212 0x8A*/ 0b10001010, OpMovGbEb(m, rde)); + CASE(/*0213 0x8B*/ 0b10001011, OpMovGvqpEvqp(m, rde)); CASE(/*0214 0x8C*/ 0b10001100, OpMovEvqpSw(m)); - CASE(/*0215 0x8D*/ 0b10001101, OpLeaGvqpM(m)); + CASE(/*0215 0x8D*/ 0b10001101, OpLeaGvqpM(m, rde)); CASE(/*0216 0x8E*/ 0b10001110, OpMovSwEvqp(m)); - CASE(/*0217 0x8F*/ 0b10001111, OpPopEvq(m)); - CASE(/*0220 0x90*/ 0b10010000, OpNop(m)); - CASE(/*0221 0x91*/ 0b10010001 ... 0x97, OpXchgZvqp(m)); - CASE(/*0230 0x98*/ 0b10011000, OpConvert1(m)); - CASE(/*0231 0x99*/ 0b10011001, OpConvert2(m)); - CASE(/*0234 0x9C*/ 0b10011100, OpPushf(m)); - CASE(/*0235 0x9D*/ 0b10011101, OpPopf(m)); + CASE(/*0217 0x8F*/ 0b10001111, OpPopEvq(m, rde)); + CASE(/*0220 0x90*/ 0b10010000, OpNop(m, rde)); + CASE(/*0221 0x91*/ 0b10010001 ... 0x97, OpXchgZvqp(m, rde)); + CASE(/*0230 0x98*/ 0b10011000, OpConvert1(m, rde)); + CASE(/*0231 0x99*/ 0b10011001, OpConvert2(m, rde)); + CASE(/*0234 0x9C*/ 0b10011100, OpPushf(m, rde)); + CASE(/*0235 0x9D*/ 0b10011101, OpPopf(m, rde)); CASE(/*0236 0x9E*/ 0b10011110, OpSahf(m)); CASE(/*0237 0x9F*/ 0b10011111, OpLahf(m)); CASE(/*0233 0x9b*/ 0b10011011, OpFwait(m)); CASE(/*0240 0xA0*/ 0b10100000, OpMovAlOb(m)); - CASE(/*0241 0xA1*/ 0b10100001, OpMovRaxOvqp(m)); + CASE(/*0241 0xA1*/ 0b10100001, OpMovRaxOvqp(m, rde)); CASE(/*0242 0xA2*/ 0b10100010, OpMovObAl(m)); - CASE(/*0243 0xA3*/ 0b10100011, OpMovOvqpRax(m)); - CASE(/*0244 0xA4*/ 0b10100100, OpMovsb(m)); - CASE(/*0245 0xA5*/ 0b10100101, OpString(m, STRING_MOVS)); - CASE(/*0246 0xA6*/ 0b10100110, OpString(m, STRING_CMPS)); - CASE(/*0247 0xA7*/ 0b10100111, OpString(m, STRING_CMPS)); - CASE(/*0250 0xA8*/ 0b10101000, OpAlubi(m, Alu, ALU_TEST | ALU_AND, UIMM0)); - CASE(/*0251 0xA9*/ 0b10101001, OpAluwi(m, Alu, ALU_TEST | ALU_AND, UIMM0)); - CASE(/*0252 0xAA*/ 0b10101010, OpStosb(m)); - CASE(/*0253 0xAB*/ 0b10101011, OpString(m, STRING_STOS)); - CASE(/*0254 0xAC*/ 0b10101100, OpString(m, STRING_LODS)); - CASE(/*0255 0xAD*/ 0b10101101, OpString(m, STRING_LODS)); - CASE(/*0256 0xAE*/ 0b10101110, OpString(m, STRING_SCAS)); - CASE(/*0257 0xAF*/ 0b10101111, OpString(m, STRING_SCAS)); - CASE(/*0260 0xB0*/ 0b10110000 ... 0b10110111, OpMovZbIb(m)); - CASE(/*0270 0xB8*/ 0b10111000 ... 0b10111111, OpMovZvqpIvqp(m)); - CASE(/*0300 0xC0*/ 0b11000000, OpAlubi(m, Bsu, ModrmReg(m->xedd), UIMM0)); - CASE(/*0301 0xC1*/ 0b11000001, OpAluwi(m, Bsu, ModrmReg(m->xedd), UIMM0)); + CASE(/*0243 0xA3*/ 0b10100011, OpMovOvqpRax(m, rde)); + CASE(/*0244 0xA4*/ 0b10100100, OpMovsb(m, rde)); + CASE(/*0245 0xA5*/ 0b10100101, OpString(m, rde, STRING_MOVS)); + CASE(/*0246 0xA6*/ 0b10100110, OpString(m, rde, STRING_CMPS)); + CASE(/*0247 0xA7*/ 0b10100111, OpString(m, rde, STRING_CMPS)); + CASE(/*0250 0xA8*/ 0b10101000, OpAlubi(m, rde, Alu, TEST, UIMM0)); + CASE(/*0251 0xA9*/ 0b10101001, OpAluwi(m, rde, Alu, TEST, UIMM0)); + CASE(/*0252 0xAA*/ 0b10101010, OpStosb(m, rde)); + CASE(/*0253 0xAB*/ 0b10101011, OpString(m, rde, STRING_STOS)); + CASE(/*0254 0xAC*/ 0b10101100, OpString(m, rde, STRING_LODS)); + CASE(/*0255 0xAD*/ 0b10101101, OpString(m, rde, STRING_LODS)); + CASE(/*0256 0xAE*/ 0b10101110, OpString(m, rde, STRING_SCAS)); + CASE(/*0257 0xAF*/ 0b10101111, OpString(m, rde, STRING_SCAS)); + CASE(/*0260 0xB0*/ 0b10110000 ... 0b10110111, OpMovZbIb(m, rde)); + CASE(/*0270 0xB8*/ 0b10111000 ... 0b10111111, OpMovZvqpIvqp(m, rde)); + CASE(/*0300 0xC0*/ 0b11000000, OpBsubi(m, rde, Bsu, ModrmReg(rde), UIMM0)); + CASE(/*0301 0xC1*/ 0b11000001, OpBsuwi(m, rde, Bsu, ModrmReg(rde), UIMM0)); CASE(/*0302 0xC2*/ 0b11000010, OpRet(m, m->xedd->op.uimm0)); CASE(/*0303 0xC3*/ 0b11000011, OpRet(m, 0)); - CASE(/*0306 0xC6*/ 0b11000110, OpMovEbIb(m)); - CASE(/*0307 0xC7*/ 0b11000111, OpMovEvqpIvds(m)); + CASE(/*0306 0xC6*/ 0b11000110, OpMovEbIb(m, rde)); + CASE(/*0307 0xC7*/ 0b11000111, OpMovEvqpIvds(m, rde)); CASE(/*0311 0xC9*/ 0b11001001, OpLeave(m)); CASE(/*0314 0xCC*/ 0b11001100, OpInterrupt(m, 3)); CASE(/*0315 0xCD*/ 0b11001101, OpInterrupt(m, m->xedd->op.uimm0)); - CASE(/*0320 0xD0*/ 0b11010000, OpAlubi(m, Bsu, ModrmReg(m->xedd), 1)); - CASE(/*0321 0xD1*/ 0b11010001, OpAluwi(m, Bsu, ModrmReg(m->xedd), 1)); - CASE(/*0322 0xD2*/ 0b11010010, OpAlubi(m, Bsu, REG, m->cx[0])); - CASE(/*0323 0xD3*/ 0b11010011, OpAluwi(m, Bsu, REG, m->cx[0])); - CASE(/*0327 0xD7*/ 0b11010111, OpXlat(m)); - CASE(/*0340 0xE0*/ 0b11100000, OpLoop(m, !GetFlag(m->flags, FLAGS_ZF))); - CASE(/*0341 0xE1*/ 0b11100001, OpLoop(m, GetFlag(m->flags, FLAGS_ZF))); - CASE(/*0342 0xE2*/ 0b11100010, OpLoop(m, 1)); - CASE(/*0343 0xE3*/ 0b11100011, OpJcxz(m)); + CASE(/*0320 0xD0*/ 0b11010000, OpBsubi(m, rde, Bsu, ModrmReg(rde), 1)); + CASE(/*0321 0xD1*/ 0b11010001, OpBsuwi(m, rde, Bsu, ModrmReg(rde), 1)); + CASE(/*0322 0xD2*/ 0b11010010, OpBsubi(m, rde, Bsu, REG, m->cx[0])); + CASE(/*0323 0xD3*/ 0b11010011, OpBsuwi(m, rde, Bsu, REG, m->cx[0])); + CASE(/*0327 0xD7*/ 0b11010111, OpXlat(m, rde)); + CASE(/*0340 0xE0*/ 0b11100000, OpLoop(m, rde, !ZF)); + CASE(/*0341 0xE1*/ 0b11100001, OpLoop(m, rde, ZF)); + CASE(/*0342 0xE2*/ 0b11100010, OpLoop(m, rde, 1)); + CASE(/*0343 0xE3*/ 0b11100011, OpJcxz(m, rde)); CASE(/*0344 0xE4*/ 0b11100100, Write8(m->ax, OpIn(m, UIMM0))); CASE(/*0345 0xE5*/ 0b11100101, Write32(m->ax, OpIn(m, UIMM0))); CASE(/*0346 0xE6*/ 0b11100110, OpOut(m, UIMM0, Read8(m->ax))); @@ -1954,7 +1969,7 @@ static void ExecuteInstructionMap0(struct Machine *m) { case /*0054 0x2C*/ 0b00101100: case /*0064 0x34*/ 0b00110100: case /*0074 0x3C*/ 0b00111100: - OpAlubi(m, Alu, (m->xedd->op.opcode & 070) >> 3, m->xedd->op.uimm0); + OpAlubi(m, rde, Alu, (m->xedd->op.opcode & 070) >> 3, m->xedd->op.uimm0); break; case /*0005 0x05*/ 0b00000101: case /*0015 0x0D*/ 0b00001101: @@ -1964,7 +1979,7 @@ static void ExecuteInstructionMap0(struct Machine *m) { case /*0055 0x2D*/ 0b00101101: case /*0065 0x35*/ 0b00110101: case /*0075 0x3D*/ 0b00111101: - OpAluwi(m, Alu, (m->xedd->op.opcode & 070) >> 3, m->xedd->op.uimm0); + OpAluwi(m, rde, Alu, (m->xedd->op.opcode & 070) >> 3, m->xedd->op.uimm0); break; case /*0000 0x00*/ 0b00000000: case /*0002 0x02*/ 0b00000010: @@ -1982,7 +1997,7 @@ static void ExecuteInstructionMap0(struct Machine *m) { case /*0062 0x32*/ 0b00110010: case /*0070 0x38*/ 0b00111000: case /*0072 0x3A*/ 0b00111010: - OpAlub(m, Alu, + OpAlub(m, rde, Alu, ((m->xedd->op.opcode & 070) >> 3 | (m->xedd->op.opcode & 0b010 ? ALU_FLIP : 0))); break; @@ -2002,7 +2017,7 @@ static void ExecuteInstructionMap0(struct Machine *m) { case /*0063 0x33*/ 0b00110011: case /*0071 0x39*/ 0b00111001: case /*0073 0x3B*/ 0b00111011: - OpAluw(m, Alu, + OpAluw(m, rde, Alu, ((m->xedd->op.opcode & 070) >> 3 | (m->xedd->op.opcode & 0b010 ? ALU_FLIP : 0))); break; @@ -2017,48 +2032,48 @@ static void ExecuteInstructionMap0(struct Machine *m) { OpFpu(m); break; case /*0366 0xF6*/ 0b11110110: - switch (ModrmReg(m->xedd)) { - CASE(0, OpAlubi(m, Alu, ALU_TEST | ALU_AND, UIMM0)); - CASE(1, OpAlubi(m, Alu, ALU_TEST | ALU_AND, UIMM0)); - CASE(2, OpEb(m, AluNot)); - CASE(3, OpEb(m, AluNeg)); - CASE(4, OpMulAxAlEbUnsigned(m)); - CASE(5, OpMulAxAlEbSigned(m)); - CASE(6, OpDivAlAhAxEbUnsigned(m)); - CASE(7, OpDivAlAhAxEbSigned(m)); + switch (ModrmReg(rde)) { + CASE(0, OpAlubi(m, rde, Alu, TEST, UIMM0)); + CASE(1, OpAlubi(m, rde, Alu, TEST, UIMM0)); + CASE(2, OpEb(m, rde, AluNot)); + CASE(3, OpEb(m, rde, AluNeg)); + CASE(4, OpMulAxAlEbUnsigned(m, rde)); + CASE(5, OpMulAxAlEbSigned(m, rde)); + CASE(6, OpDivAlAhAxEbUnsigned(m, rde)); + CASE(7, OpDivAlAhAxEbSigned(m, rde)); default: unreachable; } break; case /*0367 0xF7*/ 0b11110111: - switch (ModrmReg(m->xedd)) { - CASE(0, OpAluwi(m, Alu, ALU_TEST | ALU_AND, UIMM0)); - CASE(1, OpAluwi(m, Alu, ALU_TEST | ALU_AND, UIMM0)); - CASE(2, OpEvqp(m, AluNot)); - CASE(3, OpEvqp(m, AluNeg)); - CASE(4, OpMulRdxRaxEvqpUnsigned(m)); - CASE(5, OpMulRdxRaxEvqpSigned(m)); - CASE(6, OpDivRdxRaxEvqpUnsigned(m)); - CASE(7, OpDivRdxRaxEvqpSigned(m)); + switch (ModrmReg(rde)) { + CASE(0, OpAluwi(m, rde, Alu, TEST, UIMM0)); + CASE(1, OpAluwi(m, rde, Alu, TEST, UIMM0)); + CASE(2, OpEvqp(m, rde, AluNot)); + CASE(3, OpEvqp(m, rde, AluNeg)); + CASE(4, OpMulRdxRaxEvqpUnsigned(m, rde)); + CASE(5, OpMulRdxRaxEvqpSigned(m, rde)); + CASE(6, OpDivRdxRaxEvqpUnsigned(m, rde)); + CASE(7, OpDivRdxRaxEvqpSigned(m, rde)); default: unreachable; } break; case /*0376 0xFE*/ 0b11111110: - switch (ModrmReg(m->xedd)) { - CASE(0b000, OpEb(m, AluInc)); - CASE(0b001, OpEb(m, AluDec)); + switch (ModrmReg(rde)) { + CASE(0b000, OpEb(m, rde, AluInc)); + CASE(0b001, OpEb(m, rde, AluDec)); default: OpUd(m); } break; case /*0377 0xFF*/ 0b11111111: - switch (ModrmReg(m->xedd)) { - CASE(0, OpEvqp(m, AluInc)); - CASE(1, OpEvqp(m, AluDec)); - CASE(2, OpCallEq(m)); - CASE(4, OpJmpEq(m)); - CASE(6, OpPushEvq(m)); + switch (ModrmReg(rde)) { + CASE(0, OpEvqp(m, rde, AluInc)); + CASE(1, OpEvqp(m, rde, AluDec)); + CASE(2, OpCallEq(m, rde)); + CASE(4, OpJmpEq(m, rde)); + CASE(6, OpPushEvq(m, rde)); default: OpUd(m); } @@ -2068,81 +2083,81 @@ static void ExecuteInstructionMap0(struct Machine *m) { } } -static void ExecuteInstructionMap1(struct Machine *m) { +void ExecuteInstructionMap1(struct Machine *m, uint32_t rde) { switch (m->xedd->op.opcode) { CASE(/*0005 0x05*/ 0b00000101, OpSyscall(m)); - CASE(/*0020 0x10*/ 0b00010000, OpMov0f10(m)); - CASE(/*0021 0x11*/ 0b00010001, OpMovWpsVps(m)); - CASE(/*0022 0x12*/ 0b00010010, OpMov0f12(m)); - CASE(/*0023 0x13*/ 0b00010011, OpMov0f13(m)); - CASE(/*0024 0x14*/ 0b00010100, OpUnpcklpsd(m)); - CASE(/*0025 0x15*/ 0b00010101, OpUnpckhpsd(m)); - CASE(/*0026 0x16*/ 0b00010110, OpMov0f16(m)); - CASE(/*0027 0x17*/ 0b00010111, OpMov0f17(m)); - CASE(/*0050 0x28*/ 0b00101000, OpMov0f28(m)); - CASE(/*0051 0x29*/ 0b00101001, OpMovWpsVps(m)); - CASE(/*0052 0x2A*/ 0b00101010, OpCvt(m, kOpCvt0f2a)); - CASE(/*0053 0x2B*/ 0b00101011, OpMov0f2b(m)); - CASE(/*0054 0x2C*/ 0b00101100, OpCvt(m, kOpCvtt0f2c)); - CASE(/*0055 0x2D*/ 0b00101101, OpCvt(m, kOpCvt0f2d)); - CASE(/*0056 0x2E*/ 0b00101110, OpComissVsWs(m)); - CASE(/*0057 0x2F*/ 0b00101111, OpComissVsWs(m)); + CASE(/*0020 0x10*/ 0b00010000, OpMov0f10(m, rde)); + CASE(/*0021 0x11*/ 0b00010001, OpMovWpsVps(m, rde)); + CASE(/*0022 0x12*/ 0b00010010, OpMov0f12(m, rde)); + CASE(/*0023 0x13*/ 0b00010011, OpMov0f13(m, rde)); + CASE(/*0024 0x14*/ 0b00010100, OpUnpcklpsd(m, rde)); + CASE(/*0025 0x15*/ 0b00010101, OpUnpckhpsd(m, rde)); + CASE(/*0026 0x16*/ 0b00010110, OpMov0f16(m, rde)); + CASE(/*0027 0x17*/ 0b00010111, OpMov0f17(m, rde)); + CASE(/*0050 0x28*/ 0b00101000, OpMov0f28(m, rde)); + CASE(/*0051 0x29*/ 0b00101001, OpMovWpsVps(m, rde)); + CASE(/*0052 0x2A*/ 0b00101010, OpCvt(m, rde, kOpCvt0f2a)); + CASE(/*0053 0x2B*/ 0b00101011, OpMov0f2b(m, rde)); + CASE(/*0054 0x2C*/ 0b00101100, OpCvt(m, rde, kOpCvtt0f2c)); + CASE(/*0055 0x2D*/ 0b00101101, OpCvt(m, rde, kOpCvt0f2d)); + CASE(/*0056 0x2E*/ 0b00101110, OpComissVsWs(m, rde)); + CASE(/*0057 0x2F*/ 0b00101111, OpComissVsWs(m, rde)); CASE(/*0061 0x31*/ 0b00110001, OpRdtsc(m)); - CASE(/*0100 0x40*/ 0b01000000, if (GetCond(m, 0x0)) OpMovGvqpEvqp(m)); - CASE(/*0101 0x41*/ 0b01000001, if (GetCond(m, 0x1)) OpMovGvqpEvqp(m)); - CASE(/*0102 0x42*/ 0b01000010, if (GetCond(m, 0x2)) OpMovGvqpEvqp(m)); - CASE(/*0103 0x43*/ 0b01000011, if (GetCond(m, 0x3)) OpMovGvqpEvqp(m)); - CASE(/*0104 0x44*/ 0b01000100, if (GetCond(m, 0x4)) OpMovGvqpEvqp(m)); - CASE(/*0105 0x45*/ 0b01000101, if (GetCond(m, 0x5)) OpMovGvqpEvqp(m)); - CASE(/*0106 0x46*/ 0b01000110, if (GetCond(m, 0x6)) OpMovGvqpEvqp(m)); - CASE(/*0107 0x47*/ 0b01000111, if (GetCond(m, 0x7)) OpMovGvqpEvqp(m)); - CASE(/*0110 0x48*/ 0b01001000, if (GetCond(m, 0x8)) OpMovGvqpEvqp(m)); - CASE(/*0111 0x49*/ 0b01001001, if (GetCond(m, 0x9)) OpMovGvqpEvqp(m)); - CASE(/*0112 0x4a*/ 0b01001010, if (GetCond(m, 0xa)) OpMovGvqpEvqp(m)); - CASE(/*0113 0x4b*/ 0b01001011, if (GetCond(m, 0xb)) OpMovGvqpEvqp(m)); - CASE(/*0114 0x4c*/ 0b01001100, if (GetCond(m, 0xc)) OpMovGvqpEvqp(m)); - CASE(/*0115 0x4d*/ 0b01001101, if (GetCond(m, 0xd)) OpMovGvqpEvqp(m)); - CASE(/*0116 0x4e*/ 0b01001110, if (GetCond(m, 0xe)) OpMovGvqpEvqp(m)); - CASE(/*0117 0x4f*/ 0b01001111, if (GetCond(m, 0xf)) OpMovGvqpEvqp(m)); - CASE(/*0121 0x51*/ 0b01010001, OpSqrtpsd(m)); - CASE(/*0122 0x52*/ 0b01010010, OpRsqrtps(m)); - CASE(/*0123 0x53*/ 0b01010011, OpRcpps(m)); - CASE(/*0124 0x54*/ 0b01010100, OpAndpsd(m)); - CASE(/*0125 0x55*/ 0b01010101, OpAndnpsd(m)); - CASE(/*0126 0x56*/ 0b01010110, OpOrpsd(m)); - CASE(/*0127 0x57*/ 0b01010111, OpXorpsd(m)); - CASE(/*0130 0x58*/ 0b01011000, OpAddpsd(m)); - CASE(/*0131 0x59*/ 0b01011001, OpMulpsd(m)); - CASE(/*0132 0x5A*/ 0b01011010, OpCvt(m, kOpCvt0f5a)); - CASE(/*0133 0x5B*/ 0b01011011, OpCvt(m, kOpCvt0f5b)); - CASE(/*0134 0x5C*/ 0b01011100, OpSubpsd(m)); - CASE(/*0135 0x5D*/ 0b01011101, OpMinpsd(m)); - CASE(/*0136 0x5E*/ 0b01011110, OpDivpsd(m)); - CASE(/*0137 0x5F*/ 0b01011111, OpMaxpsd(m)); - CASE(/*0140 0x60*/ 0b01100000, OpSse(m, kOpSsePunpcklbw)); - CASE(/*0141 0x61*/ 0b01100001, OpSse(m, kOpSsePunpcklwd)); - CASE(/*0142 0x62*/ 0b01100010, OpSse(m, kOpSsePunpckldq)); - CASE(/*0143 0x63*/ 0b01100011, OpSse(m, kOpSsePacksswb)); - CASE(/*0144 0x64*/ 0b01100100, OpSse(m, kOpSsePcmpgtb)); - CASE(/*0145 0x65*/ 0b01100101, OpSse(m, kOpSsePcmpgtw)); - CASE(/*0146 0x66*/ 0b01100110, OpSse(m, kOpSsePcmpgtd)); - CASE(/*0147 0x67*/ 0b01100111, OpSse(m, kOpSsePackuswb)); - CASE(/*0150 0x68*/ 0b01101000, OpSse(m, kOpSsePunpckhbw)); - CASE(/*0151 0x69*/ 0b01101001, OpSse(m, kOpSsePunpckhwd)); - CASE(/*0152 0x6A*/ 0b01101010, OpSse(m, kOpSsePunpckhdq)); - CASE(/*0153 0x6B*/ 0b01101011, OpSse(m, kOpSsePackssdw)); - CASE(/*0154 0x6C*/ 0b01101100, OpSse(m, kOpSsePunpcklqdq)); - CASE(/*0155 0x6D*/ 0b01101101, OpSse(m, kOpSsePunpckhqdq)); - CASE(/*0156 0x6E*/ 0b01101110, OpMov0f6e(m)); - CASE(/*0157 0x6F*/ 0b01101111, OpMov0f6f(m)); - CASE(/*0160 0x70*/ 0b01110000, OpShuffle(m)); - CASE(/*0164 0x74*/ 0b01110100, OpSse(m, kOpSsePcmpeqb)); - CASE(/*0165 0x75*/ 0b01110101, OpSse(m, kOpSsePcmpeqw)); - CASE(/*0166 0x76*/ 0b01110110, OpSse(m, kOpSsePcmpeqd)); - CASE(/*0174 0x7C*/ 0b01111100, OpHaddpsd(m)); - CASE(/*0175 0x7D*/ 0b01111101, OpHsubpsd(m)); - CASE(/*0176 0x7E*/ 0b01111110, OpMov0f7e(m)); - CASE(/*0177 0x7F*/ 0b01111111, OpMov0f7f(m)); + CASE(/*0100 0x40*/ 0b01000000, if (GetCond(m, 0x0)) OpMovGvqpEvqp(m, rde)); + CASE(/*0101 0x41*/ 0b01000001, if (GetCond(m, 0x1)) OpMovGvqpEvqp(m, rde)); + CASE(/*0102 0x42*/ 0b01000010, if (GetCond(m, 0x2)) OpMovGvqpEvqp(m, rde)); + CASE(/*0103 0x43*/ 0b01000011, if (GetCond(m, 0x3)) OpMovGvqpEvqp(m, rde)); + CASE(/*0104 0x44*/ 0b01000100, if (GetCond(m, 0x4)) OpMovGvqpEvqp(m, rde)); + CASE(/*0105 0x45*/ 0b01000101, if (GetCond(m, 0x5)) OpMovGvqpEvqp(m, rde)); + CASE(/*0106 0x46*/ 0b01000110, if (GetCond(m, 0x6)) OpMovGvqpEvqp(m, rde)); + CASE(/*0107 0x47*/ 0b01000111, if (GetCond(m, 0x7)) OpMovGvqpEvqp(m, rde)); + CASE(/*0110 0x48*/ 0b01001000, if (GetCond(m, 0x8)) OpMovGvqpEvqp(m, rde)); + CASE(/*0111 0x49*/ 0b01001001, if (GetCond(m, 0x9)) OpMovGvqpEvqp(m, rde)); + CASE(/*0112 0x4a*/ 0b01001010, if (GetCond(m, 0xa)) OpMovGvqpEvqp(m, rde)); + CASE(/*0113 0x4b*/ 0b01001011, if (GetCond(m, 0xb)) OpMovGvqpEvqp(m, rde)); + CASE(/*0114 0x4c*/ 0b01001100, if (GetCond(m, 0xc)) OpMovGvqpEvqp(m, rde)); + CASE(/*0115 0x4d*/ 0b01001101, if (GetCond(m, 0xd)) OpMovGvqpEvqp(m, rde)); + CASE(/*0116 0x4e*/ 0b01001110, if (GetCond(m, 0xe)) OpMovGvqpEvqp(m, rde)); + CASE(/*0117 0x4f*/ 0b01001111, if (GetCond(m, 0xf)) OpMovGvqpEvqp(m, rde)); + CASE(/*0121 0x51*/ 0b01010001, OpSqrtpsd(m, rde)); + CASE(/*0122 0x52*/ 0b01010010, OpRsqrtps(m, rde)); + CASE(/*0123 0x53*/ 0b01010011, OpRcpps(m, rde)); + CASE(/*0124 0x54*/ 0b01010100, OpAndpsd(m, rde)); + CASE(/*0125 0x55*/ 0b01010101, OpAndnpsd(m, rde)); + CASE(/*0126 0x56*/ 0b01010110, OpOrpsd(m, rde)); + CASE(/*0127 0x57*/ 0b01010111, OpXorpsd(m, rde)); + CASE(/*0130 0x58*/ 0b01011000, OpAddpsd(m, rde)); + CASE(/*0131 0x59*/ 0b01011001, OpMulpsd(m, rde)); + CASE(/*0132 0x5A*/ 0b01011010, OpCvt(m, rde, kOpCvt0f5a)); + CASE(/*0133 0x5B*/ 0b01011011, OpCvt(m, rde, kOpCvt0f5b)); + CASE(/*0134 0x5C*/ 0b01011100, OpSubpsd(m, rde)); + CASE(/*0135 0x5D*/ 0b01011101, OpMinpsd(m, rde)); + CASE(/*0136 0x5E*/ 0b01011110, OpDivpsd(m, rde)); + CASE(/*0137 0x5F*/ 0b01011111, OpMaxpsd(m, rde)); + CASE(/*0140 0x60*/ 0b01100000, OpSse(m, rde, kOpSsePunpcklbw)); + CASE(/*0141 0x61*/ 0b01100001, OpSse(m, rde, kOpSsePunpcklwd)); + CASE(/*0142 0x62*/ 0b01100010, OpSse(m, rde, kOpSsePunpckldq)); + CASE(/*0143 0x63*/ 0b01100011, OpSse(m, rde, kOpSsePacksswb)); + CASE(/*0144 0x64*/ 0b01100100, OpSse(m, rde, kOpSsePcmpgtb)); + CASE(/*0145 0x65*/ 0b01100101, OpSse(m, rde, kOpSsePcmpgtw)); + CASE(/*0146 0x66*/ 0b01100110, OpSse(m, rde, kOpSsePcmpgtd)); + CASE(/*0147 0x67*/ 0b01100111, OpSse(m, rde, kOpSsePackuswb)); + CASE(/*0150 0x68*/ 0b01101000, OpSse(m, rde, kOpSsePunpckhbw)); + CASE(/*0151 0x69*/ 0b01101001, OpSse(m, rde, kOpSsePunpckhwd)); + CASE(/*0152 0x6A*/ 0b01101010, OpSse(m, rde, kOpSsePunpckhdq)); + CASE(/*0153 0x6B*/ 0b01101011, OpSse(m, rde, kOpSsePackssdw)); + CASE(/*0154 0x6C*/ 0b01101100, OpSse(m, rde, kOpSsePunpcklqdq)); + CASE(/*0155 0x6D*/ 0b01101101, OpSse(m, rde, kOpSsePunpckhqdq)); + CASE(/*0156 0x6E*/ 0b01101110, OpMov0f6e(m, rde)); + CASE(/*0157 0x6F*/ 0b01101111, OpMov0f6f(m, rde)); + CASE(/*0160 0x70*/ 0b01110000, OpShuffle(m, rde)); + CASE(/*0164 0x74*/ 0b01110100, OpSse(m, rde, kOpSsePcmpeqb)); + CASE(/*0165 0x75*/ 0b01110101, OpSse(m, rde, kOpSsePcmpeqw)); + CASE(/*0166 0x76*/ 0b01110110, OpSse(m, rde, kOpSsePcmpeqd)); + CASE(/*0174 0x7C*/ 0b01111100, OpHaddpsd(m, rde)); + CASE(/*0175 0x7D*/ 0b01111101, OpHsubpsd(m, rde)); + CASE(/*0176 0x7E*/ 0b01111110, OpMov0f7e(m, rde)); + CASE(/*0177 0x7F*/ 0b01111111, OpMov0f7f(m, rde)); CASE(/*0200 0x80*/ 0b10000000, if (GetCond(m, 0x0)) OpJmp(m)); CASE(/*0201 0x81*/ 0b10000001, if (GetCond(m, 0x1)) OpJmp(m)); CASE(/*0202 0x82*/ 0b10000010, if (GetCond(m, 0x2)) OpJmp(m)); @@ -2159,97 +2174,97 @@ static void ExecuteInstructionMap1(struct Machine *m) { CASE(/*0215 0x8d*/ 0b10001101, if (GetCond(m, 0xd)) OpJmp(m)); CASE(/*0216 0x8e*/ 0b10001110, if (GetCond(m, 0xe)) OpJmp(m)); CASE(/*0217 0x8f*/ 0b10001111, if (GetCond(m, 0xf)) OpJmp(m)); - CASE(/*0220 0x90*/ 0b10010000, OpEbSetCc(m, GetCond(m, 0x0))); - CASE(/*0221 0x91*/ 0b10010001, OpEbSetCc(m, GetCond(m, 0x1))); - CASE(/*0222 0x92*/ 0b10010010, OpEbSetCc(m, GetCond(m, 0x2))); - CASE(/*0223 0x93*/ 0b10010011, OpEbSetCc(m, GetCond(m, 0x3))); - CASE(/*0224 0x94*/ 0b10010100, OpEbSetCc(m, GetCond(m, 0x4))); - CASE(/*0225 0x95*/ 0b10010101, OpEbSetCc(m, GetCond(m, 0x5))); - CASE(/*0226 0x96*/ 0b10010110, OpEbSetCc(m, GetCond(m, 0x6))); - CASE(/*0227 0x97*/ 0b10010111, OpEbSetCc(m, GetCond(m, 0x7))); - CASE(/*0230 0x98*/ 0b10011000, OpEbSetCc(m, GetCond(m, 0x8))); - CASE(/*0231 0x99*/ 0b10011001, OpEbSetCc(m, GetCond(m, 0x9))); - CASE(/*0232 0x9A*/ 0b10011010, OpEbSetCc(m, GetCond(m, 0xa))); - CASE(/*0233 0x9B*/ 0b10011011, OpEbSetCc(m, GetCond(m, 0xb))); - CASE(/*0234 0x9C*/ 0b10011100, OpEbSetCc(m, GetCond(m, 0xc))); - CASE(/*0235 0x9D*/ 0b10011101, OpEbSetCc(m, GetCond(m, 0xd))); - CASE(/*0236 0x9E*/ 0b10011110, OpEbSetCc(m, GetCond(m, 0xe))); - CASE(/*0237 0x9F*/ 0b10011111, OpEbSetCc(m, GetCond(m, 0xf))); + CASE(/*0220 0x90*/ 0b10010000, OpEbSetCc(m, rde, GetCond(m, 0x0))); + CASE(/*0221 0x91*/ 0b10010001, OpEbSetCc(m, rde, GetCond(m, 0x1))); + CASE(/*0222 0x92*/ 0b10010010, OpEbSetCc(m, rde, GetCond(m, 0x2))); + CASE(/*0223 0x93*/ 0b10010011, OpEbSetCc(m, rde, GetCond(m, 0x3))); + CASE(/*0224 0x94*/ 0b10010100, OpEbSetCc(m, rde, GetCond(m, 0x4))); + CASE(/*0225 0x95*/ 0b10010101, OpEbSetCc(m, rde, GetCond(m, 0x5))); + CASE(/*0226 0x96*/ 0b10010110, OpEbSetCc(m, rde, GetCond(m, 0x6))); + CASE(/*0227 0x97*/ 0b10010111, OpEbSetCc(m, rde, GetCond(m, 0x7))); + CASE(/*0230 0x98*/ 0b10011000, OpEbSetCc(m, rde, GetCond(m, 0x8))); + CASE(/*0231 0x99*/ 0b10011001, OpEbSetCc(m, rde, GetCond(m, 0x9))); + CASE(/*0232 0x9A*/ 0b10011010, OpEbSetCc(m, rde, GetCond(m, 0xa))); + CASE(/*0233 0x9B*/ 0b10011011, OpEbSetCc(m, rde, GetCond(m, 0xb))); + CASE(/*0234 0x9C*/ 0b10011100, OpEbSetCc(m, rde, GetCond(m, 0xc))); + CASE(/*0235 0x9D*/ 0b10011101, OpEbSetCc(m, rde, GetCond(m, 0xd))); + CASE(/*0236 0x9E*/ 0b10011110, OpEbSetCc(m, rde, GetCond(m, 0xe))); + CASE(/*0237 0x9F*/ 0b10011111, OpEbSetCc(m, rde, GetCond(m, 0xf))); CASE(/*0240 0xA0*/ 0b10100000, OpPushFs(m)); CASE(/*0241 0xA1*/ 0b10100001, OpPopFs(m)); CASE(/*0242 0xA2*/ 0b10100010, OpCpuid(m)); - CASE(/*0243 0xA3*/ 0b10100011, OpBit(m)); + CASE(/*0243 0xA3*/ 0b10100011, OpBit(m, rde)); CASE(/*0250 0xA8*/ 0b10101000, OpPushGs(m)); CASE(/*0251 0xA9*/ 0b10101001, OpPopGs(m)); - CASE(/*0253 0xAB*/ 0b10101011, OpBit(m)); - CASE(/*0257 0xAF*/ 0b10101111, OpImulGvqpEvqp(m)); - CASE(/*0260 0xB0*/ 0b10110000, OpCmpxchgEbAlGb(m)); - CASE(/*0261 0xB1*/ 0b10110001, OpCmpxchgEvqpRaxGvqp(m)); - CASE(/*0263 0xB3*/ 0b10110011, OpBit(m)); - CASE(/*0266 0xB6*/ 0b10110110, OpMovzbGvqpEb(m)); - CASE(/*0267 0xB7*/ 0b10110111, OpMovzwGvqpEw(m)); - CASE(/*0272 0xBA*/ 0b10111010, OpBit(m)); - CASE(/*0273 0xBB*/ 0b10111011, OpBit(m)); - CASE(/*0274 0xBC*/ 0b10111100, OpGvqpEvqp(m, AluBsf, MUTATING)); - CASE(/*0275 0xBD*/ 0b10111101, OpGvqpEvqp(m, AluBsr, MUTATING)); - CASE(/*0276 0xBE*/ 0b10111110, OpMovsbGvqpEb(m)); - CASE(/*0277 0xBF*/ 0b10111111, OpMovswGvqpEw(m)); - CASE(/*0300 0xC0*/ 0b11000000, OpAlub(m, Alu, ALU_XCHG | ALU_ADD)); - CASE(/*0301 0xC1*/ 0b11000001, OpAluw(m, Alu, ALU_XCHG | ALU_ADD)); - CASE(/*0302 0xC2*/ 0b11000010, OpCmppsd(m)); - CASE(/*0303 0xC3*/ 0b11000011, OpMovntiMdqpGdqp(m)); - CASE(/*0304 0xC4*/ 0b11000100, OpPinsrwVdqEwIb(m)); - CASE(/*0305 0xC5*/ 0b11000101, OpPextrwGdqpUdqIb(m)); - CASE(/*0306 0xC6*/ 0b11000110, OpShufpsd(m)); - CASE(/*0307 0xC7*/ 0b11000111, OpCmpxchgDxAx(m)); - CASE(/*0310 0xC8*/ 0b11001000 ... 0b11001111, OpBswapZvqp(m)); - CASE(/*0320 0xD0*/ 0b11010000, OpAddsubpsd(m)); - CASE(/*0321 0xD1*/ 0b11010001, OpSse(m, kOpSsePsrlwv)); - CASE(/*0322 0xD2*/ 0b11010010, OpSse(m, kOpSsePsrldv)); - CASE(/*0323 0xD3*/ 0b11010011, OpSse(m, kOpSsePsrlqv)); - CASE(/*0324 0xD4*/ 0b11010100, OpSse(m, kOpSsePaddq)); - CASE(/*0325 0xD5*/ 0b11010101, OpSse(m, kOpSsePmullw)); - CASE(/*0326 0xD6*/ 0b11010110, OpMov0fD6(m)); - CASE(/*0327 0xD7*/ 0b11010111, OpPmovmskbGdqpNqUdq(m)); - CASE(/*0330 0xD8*/ 0b11011000, OpSse(m, kOpSsePsubusb)); - CASE(/*0331 0xD9*/ 0b11011001, OpSse(m, kOpSsePsubusw)); - CASE(/*0332 0xDA*/ 0b11011010, OpSse(m, kOpSsePminub)); - CASE(/*0333 0xDB*/ 0b11011011, OpSse(m, kOpSsePand)); - CASE(/*0334 0xDC*/ 0b11011100, OpSse(m, kOpSsePaddusb)); - CASE(/*0335 0xDD*/ 0b11011101, OpSse(m, kOpSsePaddusw)); - CASE(/*0336 0xDE*/ 0b11011110, OpSse(m, kOpSsePmaxub)); - CASE(/*0337 0xDF*/ 0b11011111, OpSse(m, kOpSsePandn)); - CASE(/*0340 0xE0*/ 0b11100000, OpSse(m, kOpSsePavgb)); - CASE(/*0341 0xE1*/ 0b11100001, OpSse(m, kOpSsePsrawv)); - CASE(/*0342 0xE2*/ 0b11100010, OpSse(m, kOpSsePsradv)); - CASE(/*0343 0xE3*/ 0b11100011, OpSse(m, kOpSsePavgw)); - CASE(/*0344 0xE4*/ 0b11100100, OpSse(m, kOpSsePmulhuw)); - CASE(/*0345 0xE5*/ 0b11100101, OpSse(m, kOpSsePmulhw)); - CASE(/*0346 0xE6*/ 0b11100110, OpCvt(m, kOpCvt0fE6)); - CASE(/*0347 0xE7*/ 0b11100111, OpMov0fE7(m)); - CASE(/*0350 0xE8*/ 0b11101000, OpSse(m, kOpSsePsubsb)); - CASE(/*0351 0xE9*/ 0b11101001, OpSse(m, kOpSsePsubsw)); - CASE(/*0352 0xEA*/ 0b11101010, OpSse(m, kOpSsePminsw)); - CASE(/*0353 0xEB*/ 0b11101011, OpSse(m, kOpSsePor)); - CASE(/*0354 0xEC*/ 0b11101100, OpSse(m, kOpSsePaddsb)); - CASE(/*0355 0xED*/ 0b11101101, OpSse(m, kOpSsePaddsw)); - CASE(/*0356 0xEE*/ 0b11101110, OpSse(m, kOpSsePmaxsw)); - CASE(/*0357 0xEF*/ 0b11101111, OpSse(m, kOpSsePxor)); - CASE(/*0360 0xF0*/ 0b11110000, OpLddquVdqMdq(m)); - CASE(/*0361 0xF1*/ 0b11110001, OpSse(m, kOpSsePsllwv)); - CASE(/*0362 0xF2*/ 0b11110010, OpSse(m, kOpSsePslldv)); - CASE(/*0363 0xF3*/ 0b11110011, OpSse(m, kOpSsePsllqv)); - CASE(/*0364 0xF4*/ 0b11110100, OpSse(m, kOpSsePmuludq)); - CASE(/*0365 0xF5*/ 0b11110101, OpSse(m, kOpSsePmaddwd)); - CASE(/*0366 0xF6*/ 0b11110110, OpSse(m, kOpSsePsadbw)); - CASE(/*0367 0xF7*/ 0b11110111, OpMaskMovDiXmmRegXmmRm(m)); - CASE(/*0370 0xF8*/ 0b11111000, OpSse(m, kOpSsePsubb)); - CASE(/*0371 0xF9*/ 0b11111001, OpSse(m, kOpSsePsubw)); - CASE(/*0372 0xFA*/ 0b11111010, OpSse(m, kOpSsePsubd)); - CASE(/*0373 0xFB*/ 0b11111011, OpSse(m, kOpSsePsubq)); - CASE(/*0374 0xFC*/ 0b11111100, OpSse(m, kOpSsePaddb)); - CASE(/*0375 0xFD*/ 0b11111101, OpSse(m, kOpSsePaddw)); - CASE(/*0376 0xFE*/ 0b11111110, OpSse(m, kOpSsePaddd)); + CASE(/*0253 0xAB*/ 0b10101011, OpBit(m, rde)); + CASE(/*0257 0xAF*/ 0b10101111, OpImulGvqpEvqp(m, rde)); + CASE(/*0260 0xB0*/ 0b10110000, OpCmpxchgEbAlGb(m, rde)); + CASE(/*0261 0xB1*/ 0b10110001, OpCmpxchgEvqpRaxGvqp(m, rde)); + CASE(/*0263 0xB3*/ 0b10110011, OpBit(m, rde)); + CASE(/*0266 0xB6*/ 0b10110110, OpMovzbGvqpEb(m, rde)); + CASE(/*0267 0xB7*/ 0b10110111, OpMovzwGvqpEw(m, rde)); + CASE(/*0272 0xBA*/ 0b10111010, OpBit(m, rde)); + CASE(/*0273 0xBB*/ 0b10111011, OpBit(m, rde)); + CASE(/*0274 0xBC*/ 0b10111100, OpGvqpEvqp(m, rde, AluBsf, MUTATING)); + CASE(/*0275 0xBD*/ 0b10111101, OpGvqpEvqp(m, rde, AluBsr, MUTATING)); + CASE(/*0276 0xBE*/ 0b10111110, OpMovsbGvqpEb(m, rde)); + CASE(/*0277 0xBF*/ 0b10111111, OpMovswGvqpEw(m, rde)); + CASE(/*0300 0xC0*/ 0b11000000, OpXaddEbGb(m, rde)); + CASE(/*0301 0xC1*/ 0b11000001, OpXaddEvqpGvqp(m, rde)); + CASE(/*0302 0xC2*/ 0b11000010, OpCmppsd(m, rde)); + CASE(/*0303 0xC3*/ 0b11000011, OpMovntiMdqpGdqp(m, rde)); + CASE(/*0304 0xC4*/ 0b11000100, OpPinsrwVdqEwIb(m, rde)); + CASE(/*0305 0xC5*/ 0b11000101, OpPextrwGdqpUdqIb(m, rde)); + CASE(/*0306 0xC6*/ 0b11000110, OpShufpsd(m, rde)); + CASE(/*0307 0xC7*/ 0b11000111, OpCmpxchgDxAx(m, rde)); + CASE(/*0310 0xC8*/ 0b11001000 ... 0b11001111, OpBswapZvqp(m, rde)); + CASE(/*0320 0xD0*/ 0b11010000, OpAddsubpsd(m, rde)); + CASE(/*0321 0xD1*/ 0b11010001, OpSse(m, rde, kOpSsePsrlwv)); + CASE(/*0322 0xD2*/ 0b11010010, OpSse(m, rde, kOpSsePsrldv)); + CASE(/*0323 0xD3*/ 0b11010011, OpSse(m, rde, kOpSsePsrlqv)); + CASE(/*0324 0xD4*/ 0b11010100, OpSse(m, rde, kOpSsePaddq)); + CASE(/*0325 0xD5*/ 0b11010101, OpSse(m, rde, kOpSsePmullw)); + CASE(/*0326 0xD6*/ 0b11010110, OpMov0fD6(m, rde)); + CASE(/*0327 0xD7*/ 0b11010111, OpPmovmskbGdqpNqUdq(m, rde)); + CASE(/*0330 0xD8*/ 0b11011000, OpSse(m, rde, kOpSsePsubusb)); + CASE(/*0331 0xD9*/ 0b11011001, OpSse(m, rde, kOpSsePsubusw)); + CASE(/*0332 0xDA*/ 0b11011010, OpSse(m, rde, kOpSsePminub)); + CASE(/*0333 0xDB*/ 0b11011011, OpSse(m, rde, kOpSsePand)); + CASE(/*0334 0xDC*/ 0b11011100, OpSse(m, rde, kOpSsePaddusb)); + CASE(/*0335 0xDD*/ 0b11011101, OpSse(m, rde, kOpSsePaddusw)); + CASE(/*0336 0xDE*/ 0b11011110, OpSse(m, rde, kOpSsePmaxub)); + CASE(/*0337 0xDF*/ 0b11011111, OpSse(m, rde, kOpSsePandn)); + CASE(/*0340 0xE0*/ 0b11100000, OpSse(m, rde, kOpSsePavgb)); + CASE(/*0341 0xE1*/ 0b11100001, OpSse(m, rde, kOpSsePsrawv)); + CASE(/*0342 0xE2*/ 0b11100010, OpSse(m, rde, kOpSsePsradv)); + CASE(/*0343 0xE3*/ 0b11100011, OpSse(m, rde, kOpSsePavgw)); + CASE(/*0344 0xE4*/ 0b11100100, OpSse(m, rde, kOpSsePmulhuw)); + CASE(/*0345 0xE5*/ 0b11100101, OpSse(m, rde, kOpSsePmulhw)); + CASE(/*0346 0xE6*/ 0b11100110, OpCvt(m, rde, kOpCvt0fE6)); + CASE(/*0347 0xE7*/ 0b11100111, OpMov0fE7(m, rde)); + CASE(/*0350 0xE8*/ 0b11101000, OpSse(m, rde, kOpSsePsubsb)); + CASE(/*0351 0xE9*/ 0b11101001, OpSse(m, rde, kOpSsePsubsw)); + CASE(/*0352 0xEA*/ 0b11101010, OpSse(m, rde, kOpSsePminsw)); + CASE(/*0353 0xEB*/ 0b11101011, OpSse(m, rde, kOpSsePor)); + CASE(/*0354 0xEC*/ 0b11101100, OpSse(m, rde, kOpSsePaddsb)); + CASE(/*0355 0xED*/ 0b11101101, OpSse(m, rde, kOpSsePaddsw)); + CASE(/*0356 0xEE*/ 0b11101110, OpSse(m, rde, kOpSsePmaxsw)); + CASE(/*0357 0xEF*/ 0b11101111, OpSse(m, rde, kOpSsePxor)); + CASE(/*0360 0xF0*/ 0b11110000, OpLddquVdqMdq(m, rde)); + CASE(/*0361 0xF1*/ 0b11110001, OpSse(m, rde, kOpSsePsllwv)); + CASE(/*0362 0xF2*/ 0b11110010, OpSse(m, rde, kOpSsePslldv)); + CASE(/*0363 0xF3*/ 0b11110011, OpSse(m, rde, kOpSsePsllqv)); + CASE(/*0364 0xF4*/ 0b11110100, OpSse(m, rde, kOpSsePmuludq)); + CASE(/*0365 0xF5*/ 0b11110101, OpSse(m, rde, kOpSsePmaddwd)); + CASE(/*0366 0xF6*/ 0b11110110, OpSse(m, rde, kOpSsePsadbw)); + CASE(/*0367 0xF7*/ 0b11110111, OpMaskMovDiXmmRegXmmRm(m, rde)); + CASE(/*0370 0xF8*/ 0b11111000, OpSse(m, rde, kOpSsePsubb)); + CASE(/*0371 0xF9*/ 0b11111001, OpSse(m, rde, kOpSsePsubw)); + CASE(/*0372 0xFA*/ 0b11111010, OpSse(m, rde, kOpSsePsubd)); + CASE(/*0373 0xFB*/ 0b11111011, OpSse(m, rde, kOpSsePsubq)); + CASE(/*0374 0xFC*/ 0b11111100, OpSse(m, rde, kOpSsePaddb)); + CASE(/*0375 0xFD*/ 0b11111101, OpSse(m, rde, kOpSsePaddw)); + CASE(/*0376 0xFE*/ 0b11111110, OpSse(m, rde, kOpSsePaddd)); case /*0013 0x0B*/ 0b00001011: case /*0271 0xB9*/ 0b10111001: case /*0377 0xFF*/ 0b11111111: @@ -2268,29 +2283,29 @@ static void ExecuteInstructionMap1(struct Machine *m) { OpNopEv(m); break; case /*0161 0x71*/ 0b01110001: - switch (ModrmReg(m->xedd)) { - CASE(2, OpSseUdqIb(m, kOpSseUdqIbPsrlw)); - CASE(4, OpSseUdqIb(m, kOpSseUdqIbPsraw)); - CASE(6, OpSseUdqIb(m, kOpSseUdqIbPsllw)); + switch (ModrmReg(rde)) { + CASE(2, OpSseUdqIb(m, rde, kOpSseUdqIbPsrlw)); + CASE(4, OpSseUdqIb(m, rde, kOpSseUdqIbPsraw)); + CASE(6, OpSseUdqIb(m, rde, kOpSseUdqIbPsllw)); default: OpUd(m); } break; case /*0162 0x72*/ 0b01110010: - switch (ModrmReg(m->xedd)) { - CASE(2, OpSseUdqIb(m, kOpSseUdqIbPsrld)); - CASE(4, OpSseUdqIb(m, kOpSseUdqIbPsrad)); - CASE(6, OpSseUdqIb(m, kOpSseUdqIbPslld)); + switch (ModrmReg(rde)) { + CASE(2, OpSseUdqIb(m, rde, kOpSseUdqIbPsrld)); + CASE(4, OpSseUdqIb(m, rde, kOpSseUdqIbPsrad)); + CASE(6, OpSseUdqIb(m, rde, kOpSseUdqIbPslld)); default: OpUd(m); } break; case /*0163 0x73*/ 0b01110011: - switch (ModrmReg(m->xedd)) { - CASE(2, OpSseUdqIb(m, kOpSseUdqIbPsrlq)); - CASE(3, OpSseUdqIb(m, kOpSseUdqIbPsrldq)); - CASE(6, OpSseUdqIb(m, kOpSseUdqIbPsllq)); - CASE(7, OpSseUdqIb(m, kOpSseUdqIbPslldq)); + switch (ModrmReg(rde)) { + CASE(2, OpSseUdqIb(m, rde, kOpSseUdqIbPsrlq)); + CASE(3, OpSseUdqIb(m, rde, kOpSseUdqIbPsrldq)); + CASE(6, OpSseUdqIb(m, rde, kOpSseUdqIbPsllq)); + CASE(7, OpSseUdqIb(m, rde, kOpSseUdqIbPslldq)); default: OpUd(m); } @@ -2299,10 +2314,10 @@ static void ExecuteInstructionMap1(struct Machine *m) { case /*0245 0xA5*/ 0b10100101: case /*0254 0xAC*/ 0b10101100: case /*0255 0xAD*/ 0b10101101: - OpEvqpGvqp(m, OpDoubleShift, MUTATING); + OpEvqpGvqp(m, rde, OpDoubleShift, MUTATING); break; case /*0256 0xAE*/ 0b10101110: - switch (ModrmReg(m->xedd)) { + switch (ModrmReg(rde)) { CASE(5, OpLfence(m)); CASE(6, OpMfence(m)); case 7: @@ -2317,8 +2332,8 @@ static void ExecuteInstructionMap1(struct Machine *m) { } break; case 0xB8: - if (m->xedd->op.ild_f3) { - OpGvqpEvqp(m, AluPopcnt, MUTATING); + if (Rep(rde) == 3) { + OpGvqpEvqp(m, rde, AluPopcnt, MUTATING); } else { OpUd(m); } @@ -2328,55 +2343,59 @@ static void ExecuteInstructionMap1(struct Machine *m) { } } -static void ExecuteInstructionMap2(struct Machine *m) { +void ExecuteInstructionMap2(struct Machine *m, uint32_t rde) { switch (m->xedd->op.opcode) { - CASE(0x00, OpSse(m, kOpSsePshufb)); - CASE(0x01, OpSse(m, kOpSsePhaddw)); - CASE(0x02, OpSse(m, kOpSsePhaddd)); - CASE(0x03, OpSse(m, kOpSsePhaddsw)); - CASE(0x04, OpSse(m, kOpSsePmaddubsw)); - CASE(0x05, OpSse(m, kOpSsePhsubw)); - CASE(0x06, OpSse(m, kOpSsePhsubd)); - CASE(0x07, OpSse(m, kOpSsePhsubsw)); - CASE(0x08, OpSse(m, kOpSsePsignb)); - CASE(0x09, OpSse(m, kOpSsePsignw)); - CASE(0x0A, OpSse(m, kOpSsePsignd)); - CASE(0x0B, OpSse(m, kOpSsePmulhrsw)); - CASE(0x1C, OpSse(m, kOpSsePabsb)); - CASE(0x1D, OpSse(m, kOpSsePabsw)); - CASE(0x1E, OpSse(m, kOpSsePabsd)); - CASE(0x2A, OpMovntdqaVdqMdq(m)); - CASE(0x40, OpSse(m, kOpSsePmulld)); + CASE(0x00, OpSse(m, rde, kOpSsePshufb)); + CASE(0x01, OpSse(m, rde, kOpSsePhaddw)); + CASE(0x02, OpSse(m, rde, kOpSsePhaddd)); + CASE(0x03, OpSse(m, rde, kOpSsePhaddsw)); + CASE(0x04, OpSse(m, rde, kOpSsePmaddubsw)); + CASE(0x05, OpSse(m, rde, kOpSsePhsubw)); + CASE(0x06, OpSse(m, rde, kOpSsePhsubd)); + CASE(0x07, OpSse(m, rde, kOpSsePhsubsw)); + CASE(0x08, OpSse(m, rde, kOpSsePsignb)); + CASE(0x09, OpSse(m, rde, kOpSsePsignw)); + CASE(0x0A, OpSse(m, rde, kOpSsePsignd)); + CASE(0x0B, OpSse(m, rde, kOpSsePmulhrsw)); + CASE(0x1C, OpSse(m, rde, kOpSsePabsb)); + CASE(0x1D, OpSse(m, rde, kOpSsePabsw)); + CASE(0x1E, OpSse(m, rde, kOpSsePabsd)); + CASE(0x2A, OpMovntdqaVdqMdq(m, rde)); + CASE(0x40, OpSse(m, rde, kOpSsePmulld)); default: OpUd(m); } } -static void ExecuteInstructionMap3(struct Machine *m) { +void ExecuteInstructionMap3(struct Machine *m, uint32_t rde) { switch (m->xedd->op.opcode) { - CASE(0x0F, OpSsePalignr(m)); + CASE(0x0F, OpSsePalignr(m, rde)); default: OpUd(m); } } -static void SaveStash(struct Machine *m) { - VirtualRecv(m, m->stashaddr, m->stash, m->stashsize); - m->stashaddr = 0; +void ExecuteInstructionMapUndefined(struct Machine *m, uint32_t rde) { + OpUd(m); } +static const map_f kExecuteInstructionMap[16] = { + ExecuteInstructionMap0, ExecuteInstructionMap1, + ExecuteInstructionMap2, ExecuteInstructionMap3, + ExecuteInstructionMapUndefined, ExecuteInstructionMapUndefined, + ExecuteInstructionMapUndefined, ExecuteInstructionMapUndefined, + ExecuteInstructionMapUndefined, ExecuteInstructionMapUndefined, + ExecuteInstructionMapUndefined, ExecuteInstructionMapUndefined, + ExecuteInstructionMapUndefined, ExecuteInstructionMapUndefined, + ExecuteInstructionMapUndefined, ExecuteInstructionMapUndefined, +}; + void ExecuteInstruction(struct Machine *m) { uint8_t *p; m->ip += m->xedd->length; - switch (m->xedd->op.map) { - CASE(XED_ILD_MAP0, ExecuteInstructionMap0(m)); - CASE(XED_ILD_MAP1, ExecuteInstructionMap1(m)); - CASE(XED_ILD_MAP2, ExecuteInstructionMap2(m)); - CASE(XED_ILD_MAP3, ExecuteInstructionMap3(m)); - default: - OpUd(m); - } + kExecuteInstructionMap[m->xedd->op.map & 15](m, m->xedd->op.rde); if (m->stashaddr) { - SaveStash(m); + VirtualRecv(m, m->stashaddr, m->stash, m->stashsize); + m->stashaddr = 0; } } diff --git a/tool/build/lib/machine.h b/tool/build/lib/machine.h index 17b85a92..d26c884f 100644 --- a/tool/build/lib/machine.h +++ b/tool/build/lib/machine.h @@ -3,6 +3,7 @@ #include "libc/elf/struct/ehdr.h" #include "libc/runtime/runtime.h" #include "third_party/xed/x86.h" +#include "tool/build/lib/fds.h" #include "tool/build/lib/pml4t.h" #define kXmmIntegral 0 @@ -136,6 +137,7 @@ struct Machine { uint8_t stash[4096]; uint8_t xmmtype[2][8]; struct XedDecodedInst icache[512]; + struct MachineFds fds; }; void ResetCpu(struct Machine *); diff --git a/tool/build/lib/modrm.c b/tool/build/lib/modrm.c index 548824f2..2bd2b3b5 100644 --- a/tool/build/lib/modrm.c +++ b/tool/build/lib/modrm.c @@ -26,207 +26,223 @@ /** * 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; DCHECK(m->xedd->op.has_modrm); - DCHECK(!IsModrmRegister(m->xedd)); + DCHECK(!IsModrmRegister(rde)); i = m->xedd->op.disp; - if (!SibExists(m->xedd)) { - i += IsRipRelative(m->xedd) ? m->ip : Read64(RegRexbRm(m)); + if (!SibExists(rde)) { + if (IsRipRelative(rde)) { + i += m->ip; + } else { + i += Read64(RegRexbRm(m, rde)); + } } else { DCHECK(m->xedd->op.has_sib); - if (SibHasBase(m->xedd)) i += Read64(RegRexbBase(m)); - if (SibHasIndex(m->xedd)) i += Read64(RegRexxIndex(m)) << m->xedd->op.scale; + if (SibHasBase(rde)) { + i += Read64(RegRexbBase(m, rde)); + } + if (SibHasIndex(rde)) { + i += Read64(RegRexxIndex(m, rde)) << m->xedd->op.scale; + } } i += GetSegment(m); - if (Asz(m->xedd)) i &= 0xffffffff; + if (Asz(rde)) i &= 0xffffffff; return i; } -void *ComputeReserveAddressRead(struct Machine *m, size_t n) { +void *ComputeReserveAddressRead(struct Machine *m, uint32_t rde, size_t n) { int64_t v; - v = ComputeAddress(m); + v = ComputeAddress(m, rde); SetReadAddr(m, v, n); return ReserveAddress(m, v, n); } -void *ComputeReserveAddressRead1(struct Machine *m) { - return ComputeReserveAddressRead(m, 1); +void *ComputeReserveAddressRead1(struct Machine *m, uint32_t rde) { + return ComputeReserveAddressRead(m, rde, 1); } -void *ComputeReserveAddressRead8(struct Machine *m) { - return ComputeReserveAddressRead(m, 8); +void *ComputeReserveAddressRead8(struct Machine *m, uint32_t rde) { + 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; - v = ComputeAddress(m); + v = ComputeAddress(m, rde); SetWriteAddr(m, v, n); return ReserveAddress(m, v, n); } -void *ComputeReserveAddressWrite1(struct Machine *m) { - return ComputeReserveAddressWrite(m, 1); +void *ComputeReserveAddressWrite1(struct Machine *m, uint32_t rde) { + return ComputeReserveAddressWrite(m, rde, 1); } -void *ComputeReserveAddressWrite4(struct Machine *m) { - return ComputeReserveAddressWrite(m, 4); +void *ComputeReserveAddressWrite4(struct Machine *m, uint32_t rde) { + return ComputeReserveAddressWrite(m, rde, 4); } -void *ComputeReserveAddressWrite8(struct Machine *m) { - return ComputeReserveAddressWrite(m, 8); +void *ComputeReserveAddressWrite8(struct Machine *m, uint32_t rde) { + return ComputeReserveAddressWrite(m, rde, 8); } -uint8_t *GetModrmRegisterMmPointerRead(struct Machine *m, size_t n) { - if (IsModrmRegister(m->xedd)) { - return MmRm(m); +uint8_t *GetModrmRegisterMmPointerRead(struct Machine *m, uint32_t rde, + size_t n) { + if (IsModrmRegister(rde)) { + return MmRm(m, rde); } else { - return ComputeReserveAddressRead(m, n); + return ComputeReserveAddressRead(m, rde, n); } } -uint8_t *GetModrmRegisterMmPointerRead8(struct Machine *m) { - return GetModrmRegisterMmPointerRead(m, 8); +uint8_t *GetModrmRegisterMmPointerRead8(struct Machine *m, uint32_t rde) { + return GetModrmRegisterMmPointerRead(m, rde, 8); } -uint8_t *GetModrmRegisterMmPointerWrite(struct Machine *m, size_t n) { - if (IsModrmRegister(m->xedd)) { - return MmRm(m); +uint8_t *GetModrmRegisterMmPointerWrite(struct Machine *m, uint32_t rde, + size_t n) { + if (IsModrmRegister(rde)) { + return MmRm(m, rde); } else { - return ComputeReserveAddressWrite(m, n); + return ComputeReserveAddressWrite(m, rde, n); } } -uint8_t *GetModrmRegisterMmPointerWrite8(struct Machine *m) { - return GetModrmRegisterMmPointerWrite(m, 8); +uint8_t *GetModrmRegisterMmPointerWrite8(struct Machine *m, uint32_t rde) { + return GetModrmRegisterMmPointerWrite(m, rde, 8); } -uint8_t *GetModrmRegisterBytePointerRead(struct Machine *m) { +uint8_t *GetModrmRegisterBytePointerRead(struct Machine *m, uint32_t rde) { int64_t v; - if (IsModrmRegister(m->xedd)) { - return ByteRexbRm(m); + if (IsModrmRegister(rde)) { + return ByteRexbRm(m, rde); } 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; - if (IsModrmRegister(m->xedd)) { - return ByteRexbRm(m); + if (IsModrmRegister(rde)) { + return ByteRexbRm(m, rde); } else { - return ComputeReserveAddressWrite1(m); + return ComputeReserveAddressWrite1(m, rde); } } -uint8_t *GetModrmRegisterWordPointerRead(struct Machine *m, size_t n) { - if (IsModrmRegister(m->xedd)) { - return RegRexbRm(m); +uint8_t *GetModrmRegisterWordPointerRead(struct Machine *m, uint32_t rde, + size_t n) { + if (IsModrmRegister(rde)) { + return RegRexbRm(m, rde); } else { - return ComputeReserveAddressRead(m, n); + return ComputeReserveAddressRead(m, rde, n); } } -uint8_t *GetModrmRegisterWordPointerRead2(struct Machine *m) { - return GetModrmRegisterWordPointerRead(m, 2); +uint8_t *GetModrmRegisterWordPointerRead2(struct Machine *m, uint32_t rde) { + return GetModrmRegisterWordPointerRead(m, rde, 2); } -uint8_t *GetModrmRegisterWordPointerRead4(struct Machine *m) { - return GetModrmRegisterWordPointerRead(m, 4); +uint8_t *GetModrmRegisterWordPointerRead4(struct Machine *m, uint32_t rde) { + return GetModrmRegisterWordPointerRead(m, rde, 4); } -uint8_t *GetModrmRegisterWordPointerRead8(struct Machine *m) { - return GetModrmRegisterWordPointerRead(m, 8); +uint8_t *GetModrmRegisterWordPointerRead8(struct Machine *m, uint32_t rde) { + return GetModrmRegisterWordPointerRead(m, rde, 8); } -uint8_t *GetModrmRegisterWordPointerReadOsz(struct Machine *m) { - if (!Osz(m->xedd)) { - return GetModrmRegisterWordPointerRead8(m); +uint8_t *GetModrmRegisterWordPointerReadOsz(struct Machine *m, uint32_t rde) { + if (!Osz(rde)) { + return GetModrmRegisterWordPointerRead8(m, rde); } else { - return GetModrmRegisterWordPointerRead2(m); + return GetModrmRegisterWordPointerRead2(m, rde); } } -uint8_t *GetModrmRegisterWordPointerReadOszRexw(struct Machine *m) { - if (Rexw(m->xedd)) { - return GetModrmRegisterWordPointerRead8(m); - } else if (!Osz(m->xedd)) { - return GetModrmRegisterWordPointerRead4(m); +uint8_t *GetModrmRegisterWordPointerReadOszRexw(struct Machine *m, + uint32_t rde) { + if (Rexw(rde)) { + return GetModrmRegisterWordPointerRead8(m, rde); + } else if (!Osz(rde)) { + return GetModrmRegisterWordPointerRead4(m, rde); } else { - return GetModrmRegisterWordPointerRead2(m); + return GetModrmRegisterWordPointerRead2(m, rde); } } -uint8_t *GetModrmRegisterWordPointerWrite(struct Machine *m, size_t n) { - if (IsModrmRegister(m->xedd)) { - return RegRexbRm(m); +uint8_t *GetModrmRegisterWordPointerWrite(struct Machine *m, uint32_t rde, + size_t n) { + if (IsModrmRegister(rde)) { + return RegRexbRm(m, rde); } else { - return ComputeReserveAddressWrite(m, n); + return ComputeReserveAddressWrite(m, rde, n); } } -uint8_t *GetModrmRegisterWordPointerWrite4(struct Machine *m) { - return GetModrmRegisterWordPointerWrite(m, 4); +uint8_t *GetModrmRegisterWordPointerWrite4(struct Machine *m, uint32_t rde) { + return GetModrmRegisterWordPointerWrite(m, rde, 4); } -uint8_t *GetModrmRegisterWordPointerWrite8(struct Machine *m) { - return GetModrmRegisterWordPointerWrite(m, 8); +uint8_t *GetModrmRegisterWordPointerWrite8(struct Machine *m, uint32_t rde) { + return GetModrmRegisterWordPointerWrite(m, rde, 8); } -uint8_t *GetModrmRegisterWordPointerWriteOszRexw(struct Machine *m) { - if (Rexw(m->xedd)) { - return GetModrmRegisterWordPointerWrite(m, 8); - } else if (!Osz(m->xedd)) { - return GetModrmRegisterWordPointerWrite(m, 4); +uint8_t *GetModrmRegisterWordPointerWriteOszRexw(struct Machine *m, + uint32_t rde) { + if (Rexw(rde)) { + return GetModrmRegisterWordPointerWrite(m, rde, 8); + } else if (!Osz(rde)) { + return GetModrmRegisterWordPointerWrite(m, rde, 4); } else { - return GetModrmRegisterWordPointerWrite(m, 2); + return GetModrmRegisterWordPointerWrite(m, rde, 2); } } -uint8_t *GetModrmRegisterWordPointerWriteOsz(struct Machine *m) { - if (!Osz(m->xedd)) { - return GetModrmRegisterWordPointerWrite(m, 8); +uint8_t *GetModrmRegisterWordPointerWriteOsz(struct Machine *m, uint32_t rde) { + if (!Osz(rde)) { + return GetModrmRegisterWordPointerWrite(m, rde, 8); } else { - return GetModrmRegisterWordPointerWrite(m, 2); + return GetModrmRegisterWordPointerWrite(m, rde, 2); } } -uint8_t *GetModrmRegisterXmmPointerRead(struct Machine *m, size_t n) { - if (IsModrmRegister(m->xedd)) { - return XmmRexbRm(m); +uint8_t *GetModrmRegisterXmmPointerRead(struct Machine *m, uint32_t rde, + size_t n) { + if (IsModrmRegister(rde)) { + return XmmRexbRm(m, rde); } else { - return ComputeReserveAddressRead(m, n); + return ComputeReserveAddressRead(m, rde, n); } } -uint8_t *GetModrmRegisterXmmPointerRead4(struct Machine *m) { - return GetModrmRegisterXmmPointerRead(m, 4); +uint8_t *GetModrmRegisterXmmPointerRead4(struct Machine *m, uint32_t rde) { + return GetModrmRegisterXmmPointerRead(m, rde, 4); } -uint8_t *GetModrmRegisterXmmPointerRead8(struct Machine *m) { - return GetModrmRegisterXmmPointerRead(m, 8); +uint8_t *GetModrmRegisterXmmPointerRead8(struct Machine *m, uint32_t rde) { + return GetModrmRegisterXmmPointerRead(m, rde, 8); } -uint8_t *GetModrmRegisterXmmPointerRead16(struct Machine *m) { - return GetModrmRegisterXmmPointerRead(m, 16); +uint8_t *GetModrmRegisterXmmPointerRead16(struct Machine *m, uint32_t rde) { + return GetModrmRegisterXmmPointerRead(m, rde, 16); } -uint8_t *GetModrmRegisterXmmPointerWrite(struct Machine *m, size_t n) { - if (IsModrmRegister(m->xedd)) { - return XmmRexbRm(m); +uint8_t *GetModrmRegisterXmmPointerWrite(struct Machine *m, uint32_t rde, + size_t n) { + if (IsModrmRegister(rde)) { + return XmmRexbRm(m, rde); } else { - return ComputeReserveAddressWrite(m, n); + return ComputeReserveAddressWrite(m, rde, n); } } -uint8_t *GetModrmRegisterXmmPointerWrite4(struct Machine *m) { - return GetModrmRegisterXmmPointerWrite(m, 4); +uint8_t *GetModrmRegisterXmmPointerWrite4(struct Machine *m, uint32_t rde) { + return GetModrmRegisterXmmPointerWrite(m, rde, 4); } -uint8_t *GetModrmRegisterXmmPointerWrite8(struct Machine *m) { - return GetModrmRegisterXmmPointerWrite(m, 8); +uint8_t *GetModrmRegisterXmmPointerWrite8(struct Machine *m, uint32_t rde) { + return GetModrmRegisterXmmPointerWrite(m, rde, 8); } -uint8_t *GetModrmRegisterXmmPointerWrite16(struct Machine *m) { - return GetModrmRegisterXmmPointerWrite(m, 16); +uint8_t *GetModrmRegisterXmmPointerWrite16(struct Machine *m, uint32_t rde) { + return GetModrmRegisterXmmPointerWrite(m, rde, 16); } diff --git a/tool/build/lib/modrm.h b/tool/build/lib/modrm.h index 93906e8a..3a29c403 100644 --- a/tool/build/lib/modrm.h +++ b/tool/build/lib/modrm.h @@ -2,80 +2,80 @@ #define COSMOPOLITAN_TOOL_BUILD_LIB_MODRM_H_ #include "tool/build/lib/abp.h" #include "tool/build/lib/machine.h" -#include "tool/build/lib/memory.h" #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ -#define IsModrmRegister(x) (ModrmMod(x) == 3) -#define IsProbablyByteOp(x) !((x)->op.opcode & 1) -#define SibExists(x) (ModrmRm(x) == 4) -#define SibHasIndex(x) (SibIndex(x) != 4 || Rexx(x)) -#define SibHasBase(x) (SibBase(x) != 5 || ModrmMod(x)) -#define SibIsAbsolute(x) (!SibHasBase(x) && !SibHasIndex(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]) +#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) -int64_t ComputeAddress(const struct Machine *) nosideeffect; +#define IsModrmRegister(x) (ModrmMod(x) == 3) +#define SibExists(x) (ModrmRm(x) == 4) +#define SibHasIndex(x) (SibIndex(x) != 4 || Rexx(x)) +#define SibHasBase(x) (SibBase(x) != 5 || ModrmMod(x)) +#define SibIsAbsolute(x) (!SibHasBase(x) && !SibHasIndex(x)) +#define IsRipRelative(x) (ModrmRm(x) == 5 && !ModrmMod(x)) -void *ComputeReserveAddressRead(struct Machine *, size_t); -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 *); +#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]) -uint8_t *GetModrmRegisterBytePointerRead(struct Machine *); -uint8_t *GetModrmRegisterBytePointerWrite(struct Machine *); -uint8_t *GetModrmRegisterMmPointerRead(struct Machine *, size_t); -uint8_t *GetModrmRegisterMmPointerRead8(struct Machine *); -uint8_t *GetModrmRegisterMmPointerWrite(struct Machine *, size_t); -uint8_t *GetModrmRegisterMmPointerWrite8(struct Machine *); -uint8_t *GetModrmRegisterWordPointerRead(struct Machine *, size_t); -uint8_t *GetModrmRegisterWordPointerRead2(struct Machine *); -uint8_t *GetModrmRegisterWordPointerRead4(struct Machine *); -uint8_t *GetModrmRegisterWordPointerRead8(struct Machine *); -uint8_t *GetModrmRegisterWordPointerReadOsz(struct Machine *); -uint8_t *GetModrmRegisterWordPointerReadOszRexw(struct Machine *); -uint8_t *GetModrmRegisterWordPointerWrite(struct Machine *, size_t); -uint8_t *GetModrmRegisterWordPointerWrite4(struct Machine *); -uint8_t *GetModrmRegisterWordPointerWrite8(struct Machine *); -uint8_t *GetModrmRegisterWordPointerWriteOsz(struct Machine *); -uint8_t *GetModrmRegisterWordPointerWriteOszRexw(struct Machine *); -uint8_t *GetModrmRegisterXmmPointerRead(struct Machine *, size_t); -uint8_t *GetModrmRegisterXmmPointerRead16(struct Machine *); -uint8_t *GetModrmRegisterXmmPointerRead4(struct Machine *); -uint8_t *GetModrmRegisterXmmPointerRead8(struct Machine *); -uint8_t *GetModrmRegisterXmmPointerWrite(struct Machine *, size_t); -uint8_t *GetModrmRegisterXmmPointerWrite16(struct Machine *); -uint8_t *GetModrmRegisterXmmPointerWrite4(struct Machine *); -uint8_t *GetModrmRegisterXmmPointerWrite8(struct Machine *); +int64_t ComputeAddress(const struct Machine *, uint32_t) nosideeffect; + +void *ComputeReserveAddressRead(struct Machine *, uint32_t, size_t); +void *ComputeReserveAddressRead1(struct Machine *, uint32_t); +void *ComputeReserveAddressRead8(struct Machine *, uint32_t); +void *ComputeReserveAddressWrite(struct Machine *, uint32_t, size_t); +void *ComputeReserveAddressWrite1(struct Machine *, uint32_t); +void *ComputeReserveAddressWrite4(struct Machine *, uint32_t); +void *ComputeReserveAddressWrite8(struct Machine *, uint32_t); + +uint8_t *GetModrmRegisterBytePointerRead(struct Machine *, uint32_t); +uint8_t *GetModrmRegisterBytePointerWrite(struct Machine *, uint32_t); +uint8_t *GetModrmRegisterMmPointerRead(struct Machine *, uint32_t, size_t); +uint8_t *GetModrmRegisterMmPointerRead8(struct Machine *, uint32_t); +uint8_t *GetModrmRegisterMmPointerWrite(struct Machine *, uint32_t, size_t); +uint8_t *GetModrmRegisterMmPointerWrite8(struct Machine *, uint32_t); +uint8_t *GetModrmRegisterWordPointerRead(struct Machine *, uint32_t, size_t); +uint8_t *GetModrmRegisterWordPointerRead2(struct Machine *, uint32_t); +uint8_t *GetModrmRegisterWordPointerRead4(struct Machine *, uint32_t); +uint8_t *GetModrmRegisterWordPointerRead8(struct Machine *, uint32_t); +uint8_t *GetModrmRegisterWordPointerReadOsz(struct Machine *, uint32_t); +uint8_t *GetModrmRegisterWordPointerReadOszRexw(struct Machine *, uint32_t); +uint8_t *GetModrmRegisterWordPointerWrite(struct Machine *, uint32_t, size_t); +uint8_t *GetModrmRegisterWordPointerWrite4(struct Machine *, uint32_t); +uint8_t *GetModrmRegisterWordPointerWrite8(struct Machine *, uint32_t); +uint8_t *GetModrmRegisterWordPointerWriteOsz(struct Machine *, uint32_t); +uint8_t *GetModrmRegisterWordPointerWriteOszRexw(struct Machine *, uint32_t); +uint8_t *GetModrmRegisterXmmPointerRead(struct Machine *, uint32_t, size_t); +uint8_t *GetModrmRegisterXmmPointerRead16(struct Machine *, uint32_t); +uint8_t *GetModrmRegisterXmmPointerRead4(struct Machine *, uint32_t); +uint8_t *GetModrmRegisterXmmPointerRead8(struct Machine *, uint32_t); +uint8_t *GetModrmRegisterXmmPointerWrite(struct Machine *, uint32_t, size_t); +uint8_t *GetModrmRegisterXmmPointerWrite16(struct Machine *, uint32_t); +uint8_t *GetModrmRegisterXmmPointerWrite4(struct Machine *, uint32_t); +uint8_t *GetModrmRegisterXmmPointerWrite8(struct Machine *, uint32_t); COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/tool/build/lib/pty.c b/tool/build/lib/pty.c new file mode 100644 index 00000000..2409d21f --- /dev/null +++ b/tool/build/lib/pty.c @@ -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"); +} diff --git a/tool/build/lib/pty.h b/tool/build/lib/pty.h new file mode 100644 index 00000000..1cbeb73f --- /dev/null +++ b/tool/build/lib/pty.h @@ -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_ */ diff --git a/tool/build/lib/reset.c b/tool/build/lib/reset.c index b574b5a1..f767e14b 100644 --- a/tool/build/lib/reset.c +++ b/tool/build/lib/reset.c @@ -17,8 +17,10 @@ │ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │ │ 02110-1301 USA │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" #include "libc/macros.h" #include "libc/math.h" +#include "libc/mem/mem.h" #include "libc/str/str.h" #include "tool/build/lib/flags.h" #include "tool/build/lib/machine.h" @@ -61,8 +63,25 @@ static void ResetSse(struct Machine *m) { 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) { - 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_CF, 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); memset(m->reg, 0, sizeof(m->reg)); memset(m->bofram, 0, sizeof(m->bofram)); + memset(&m->freelist, 0, sizeof(m->freelist)); + ResetTlb(m); ResetSse(m); ResetFpu(m); + ResetMem(m); } diff --git a/tool/build/lib/sse.c b/tool/build/lib/sse.c index 7a488368..3a7eab2c 100644 --- a/tool/build/lib/sse.c +++ b/tool/build/lib/sse.c @@ -114,19 +114,19 @@ union MachineVector { 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; uint8_t *p; union MachineVector x, y, t; - p = GetModrmRegisterXmmPointerRead16(m); - if (Osz(m->xedd)) { + p = GetModrmRegisterXmmPointerRead16(m, rde); + if (Osz(rde)) { memcpy(&y, p, 16); } else { memset(&t, 0, 16); memcpy(&t, p, 8); memcpy(&y, &t, 16); } - memcpy(&x, XmmRexrReg(m), 16); + memcpy(&x, XmmRexrReg(m, rde), 16); switch (kernel) { CASE(kOpSsePsubb, psubb(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: unreachable; } - if (Osz(m->xedd)) { - memcpy(XmmRexrReg(m), &x, 16); + if (Osz(rde)) { + memcpy(XmmRexrReg(m, rde), &x, 16); } 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; union MachineVector x; i = m->xedd->op.uimm0; - memcpy(&x, XmmRexbRm(m), 16); + memcpy(&x, XmmRexbRm(m, rde), 16); switch (kernel) { CASE(kOpSseUdqIbPsrlw, (psrlw)(x.u16, x.u16, i)); CASE(kOpSseUdqIbPsraw, (psraw)(x.i16, x.i16, i)); @@ -230,26 +230,26 @@ void OpSseUdqIb(struct Machine *m, enum OpSseUdqIbKernel kernel) { default: unreachable; } - if (Osz(m->xedd)) { - memcpy(XmmRexbRm(m), &x, 16); + if (Osz(rde)) { + memcpy(XmmRexbRm(m, rde), &x, 16); } 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]; - memcpy(t, GetModrmRegisterXmmPointerRead8(m), 8); - memcpy(t + 8, XmmRexrReg(m), 8); + memcpy(t, GetModrmRegisterXmmPointerRead8(m, rde), 8); + memcpy(t + 8, XmmRexrReg(m, rde), 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) { - if (Osz(m->xedd)) { - palignr(XmmRexrReg(m), XmmRexrReg(m), GetModrmRegisterXmmPointerRead8(m), - m->xedd->op.uimm0); +void OpSsePalignr(struct Machine *m, uint32_t rde) { + if (Osz(rde)) { + palignr(XmmRexrReg(m, rde), XmmRexrReg(m, rde), + GetModrmRegisterXmmPointerRead8(m, rde), m->xedd->op.uimm0); } else { - OpSsePalignrMmx(m); + OpSsePalignrMmx(m, rde); } } diff --git a/tool/build/lib/sse.h b/tool/build/lib/sse.h index 9a0d2988..78c40ccf 100644 --- a/tool/build/lib/sse.h +++ b/tool/build/lib/sse.h @@ -93,9 +93,9 @@ enum OpSseUdqIbKernel { kOpSseUdqIbPslldq, }; -void OpSse(struct Machine *, enum OpSseKernel); -void OpSseUdqIb(struct Machine *, enum OpSseUdqIbKernel); -void OpSsePalignr(struct Machine *); +void OpSse(struct Machine *, uint32_t, enum OpSseKernel); +void OpSseUdqIb(struct Machine *, uint32_t, enum OpSseUdqIbKernel); +void OpSsePalignr(struct Machine *, uint32_t); COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/tool/build/lib/stack.c b/tool/build/lib/stack.c index 3274cfa3..2794d410 100644 --- a/tool/build/lib/stack.c +++ b/tool/build/lib/stack.c @@ -76,12 +76,12 @@ void OpCallJvds(struct Machine *m) { OpCall(m, m->ip + m->xedd->op.disp); } -void OpCallEq(struct Machine *m) { +void OpCallEq(struct Machine *m, uint32_t rde) { void *p[2]; uint8_t b[8]; - OpCall(m, Read64(IsModrmRegister(m->xedd) - ? RegRexbRm(m) - : AccessRam(m, ComputeAddress(m), 8, p, b, true))); + OpCall(m, Read64(IsModrmRegister(rde) + ? RegRexbRm(m, rde) + : AccessRam(m, ComputeAddress(m, rde), 8, p, b, true))); } void OpLeave(struct Machine *m) { @@ -93,10 +93,20 @@ void OpRet(struct Machine *m, uint16_t n) { m->ip = Pop64(m, n); } -void PushOsz(struct Machine *m, uint64_t x) { - if (!Osz(m->xedd)) { +void PushOsz(struct Machine *m, uint32_t rde, uint64_t x) { + if (!Osz(rde)) { Push64(m, x); } else { 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; + } +} diff --git a/tool/build/lib/stack.h b/tool/build/lib/stack.h index 91c5a073..255533cc 100644 --- a/tool/build/lib/stack.h +++ b/tool/build/lib/stack.h @@ -11,8 +11,9 @@ uint16_t Pop16(struct Machine *, uint16_t); void OpCallJvds(struct Machine *); void OpRet(struct Machine *, uint16_t); void OpLeave(struct Machine *); -void PushOsz(struct Machine *, uint64_t); -void OpCallEq(struct Machine *); +void PushOsz(struct Machine *, uint32_t, uint64_t); +void OpCallEq(struct Machine *, uint32_t); +void OpBofram(struct Machine *); COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/tool/build/lib/string.c b/tool/build/lib/string.c index c6d1e902..0e49593d 100644 --- a/tool/build/lib/string.c +++ b/tool/build/lib/string.c @@ -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]; bool compare; int64_t sgn, v; @@ -73,12 +73,12 @@ void OpString(struct Machine *m, int op) { unsigned n, lg2; uint64_t asz, seg; sgn = GetFlag(m->flags, FLAGS_DF) ? -1 : 1; - asz = Asz(m->xedd) ? 0xffffffff : 0xffffffffffffffff; + asz = Asz(rde) ? 0xffffffff : 0xffffffffffffffff; seg = GetSegment(m); - lg2 = RegLog2(m->xedd); + lg2 = RegLog2(rde); n = 1 << lg2; for (;;) { - if (Rep(m->xedd) && !Read64(m->cx)) break; + if (Rep(rde) && !Read64(m->cx)) break; v = 0; *p = NULL; compare = false; @@ -125,16 +125,16 @@ void OpString(struct Machine *m, int op) { abort(); } EndStore(m, v, n, p, s[0]); - if (!Rep(m->xedd)) break; + if (!Rep(rde)) break; Write64(m->cx, Read64(m->cx) - 1); if (compare) { - if (Rep(m->xedd) == 2 && GetFlag(m->flags, FLAGS_ZF)) break; - if (Rep(m->xedd) == 3 && !GetFlag(m->flags, FLAGS_ZF)) break; + if (Rep(rde) == 2 && 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; uint8_t *direal, *sireal; unsigned diremain, siremain, i, n; @@ -143,7 +143,7 @@ void OpRepMovsbEnhanced(struct Machine *m) { failed = false; failaddr = 0; seg = GetSegment(m); - asz = Asz(m->xedd) ? 0xffffffff : 0xffffffffffffffff; + asz = Asz(rde) ? 0xffffffff : 0xffffffffffffffff; divirtual = Read64(m->di) & asz; sivirtual = Read64(m->si) & asz; SetWriteAddr(m, (seg + divirtual) & asz, cx); @@ -177,7 +177,7 @@ void OpRepMovsbEnhanced(struct Machine *m) { if (failed) ThrowSegmentationFault(m, failaddr); } -void OpRepStosbEnhanced(struct Machine *m) { +void OpRepStosbEnhanced(struct Machine *m, uint32_t rde) { bool failed; uint8_t *direal, al; unsigned diremain, i, n; @@ -187,7 +187,7 @@ void OpRepStosbEnhanced(struct Machine *m) { failed = false; al = Read8(m->ax); seg = GetSegment(m); - asz = Asz(m->xedd) ? 0xffffffff : 0xffffffffffffffff; + asz = Asz(rde) ? 0xffffffff : 0xffffffffffffffff; divirtual = Read64(m->di) & asz; SetWriteAddr(m, (seg + divirtual) & asz, cx); do { @@ -210,18 +210,18 @@ void OpRepStosbEnhanced(struct Machine *m) { if (failed) ThrowSegmentationFault(m, failaddr); } -void OpMovsb(struct Machine *m) { - if (Rep(m->xedd) && !GetFlag(m->flags, FLAGS_DF)) { - OpRepMovsbEnhanced(m); +void OpMovsb(struct Machine *m, uint32_t rde) { + if (Rep(rde) && !GetFlag(m->flags, FLAGS_DF)) { + OpRepMovsbEnhanced(m, rde); } else { - OpString(m, STRING_MOVS); + OpString(m, rde, STRING_MOVS); } } -void OpStosb(struct Machine *m) { - if (Rep(m->xedd) && !GetFlag(m->flags, FLAGS_DF)) { - OpRepStosbEnhanced(m); +void OpStosb(struct Machine *m, uint32_t rde) { + if (Rep(rde) && !GetFlag(m->flags, FLAGS_DF)) { + OpRepStosbEnhanced(m, rde); } else { - OpString(m, STRING_STOS); + OpString(m, rde, STRING_STOS); } } diff --git a/tool/build/lib/string.h b/tool/build/lib/string.h index 3aa08f8c..698b9a8a 100644 --- a/tool/build/lib/string.h +++ b/tool/build/lib/string.h @@ -13,9 +13,9 @@ #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ -void OpString(struct Machine *, int); -void OpMovsb(struct Machine *); -void OpStosb(struct Machine *); +void OpString(struct Machine *, uint32_t, int); +void OpMovsb(struct Machine *, uint32_t); +void OpStosb(struct Machine *, uint32_t); COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/tool/build/lib/syscall.c b/tool/build/lib/syscall.c index 0d5b187e..5eec8c45 100644 --- a/tool/build/lib/syscall.c +++ b/tool/build/lib/syscall.c @@ -46,6 +46,7 @@ #include "libc/sysv/errfuns.h" #include "libc/time/struct/timezone.h" #include "libc/time/time.h" +#include "libc/x/x.h" #include "tool/build/lib/case.h" #include "tool/build/lib/endian.h" #include "tool/build/lib/machine.h" @@ -65,6 +66,12 @@ #define P(x) ((x) ? PNN(x) : 0) #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) { switch (sig) { XLAT(1, SIGHUP); @@ -188,9 +195,15 @@ static int XlatTcp(int x) { } } -static int XlatAfd(int x) { - if (x == AT_FDCWD_LINUX) x = AT_FDCWD; - return x; +static int XlatFd(struct Machine *m, int fd) { + if (!(0 <= fd && fd < m->fds.i)) return ebadf(); + if (!m->fds.p[fd].cb) return ebadf(); + return m->fds.p[fd].fd; +} + +static int XlatAfd(struct Machine *m, int fd) { + if (fd == AT_FDCWD_LINUX) return AT_FDCWD; + return XlatFd(m, fd); } 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) { void *real; flags = XlatMapFlags(flags); + if (fd != -1 && (fd = XlatFd(m, fd)) == -1) return -1; real = mmap(NULL, size, prot, flags & ~MAP_FIXED, fd, off); if (real == MAP_FAILED) return -1; if (!(flags & MAP_FIXED)) { @@ -297,19 +311,70 @@ static void *GetDirectBuf(struct Machine *m, int64_t addr, size_t *size) { 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) { void *data; 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 ((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; } static ssize_t OpWrite(struct Machine *m, int fd, int64_t addr, size_t size) { void *data; 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 ((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; } @@ -317,6 +382,7 @@ static ssize_t OpPread(struct Machine *m, int fd, int64_t addr, size_t size, int64_t offset) { void *data; ssize_t rc; + if ((fd = XlatFd(m, fd)) == -1) return -1; if ((data = GetDirectBuf(m, addr, &size)) == MAP_FAILED) return efault(); if ((rc = pread(fd, data, size, offset)) != -1) SetWriteAddr(m, addr, 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) { void *data; ssize_t rc; + if ((fd = XlatFd(m, fd)) == -1) return -1; if ((data = GetDirectBuf(m, addr, &size)) == MAP_FAILED) return efault(); if ((rc = pwrite(fd, data, size, offset)) != -1) SetReadAddr(m, addr, size); 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, int flags) { int rc; void *stp[2]; uint8_t *stbuf; + flags = XlatAtf(flags); + if ((dirfd = XlatAfd(m, dirfd)) == -1) return -1; if (!(stbuf = malloc(sizeof(struct stat)))) return enomem(); - if ((rc = fstatat(XlatAfd(dirfd), LoadStr(m, path), - BeginStoreNp(m, st, sizeof(stbuf), stp, stbuf), - XlatAtf(flags))) != -1) { + if ((rc = fstatat(dirfd, LoadStr(m, path), + BeginStoreNp(m, st, sizeof(stbuf), stp, stbuf), flags)) != + -1) { EndStoreNp(m, st, sizeof(stbuf), stp, stbuf); } free(stbuf); @@ -350,6 +427,7 @@ static int OpFstat(struct Machine *m, int fd, int64_t st) { int rc; void *stp[2]; uint8_t *stbuf; + if ((fd = XlatFd(m, fd)) == -1) return -1; if (!(stbuf = malloc(sizeof(struct stat)))) return enomem(); if ((rc = fstat(fd, BeginStoreNp(m, st, sizeof(stbuf), stp, stbuf))) != -1) { EndStoreNp(m, st, sizeof(stbuf), stp, stbuf); @@ -358,17 +436,6 @@ static int OpFstat(struct Machine *m, int fd, int64_t st) { 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) { 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; } -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) { int rc; void *p[2]; @@ -536,7 +593,7 @@ void OpSyscall(struct Machine *m) { SYSCALL(0x000, OpRead(m, di, si, dx)); SYSCALL(0x001, OpWrite(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(0x005, OpFstat(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(0x0E4, OpClockGettime(m, di, si)); SYSCALL(0x101, OpOpenat(m, di, si, dx, r0)); - SYSCALL(0x102, mkdirat(XlatAfd(di), P(si), dx)); - SYSCALL(0x104, fchownat(XlatAfd(di), P(si), dx, r0, XlatAtf(r8))); - SYSCALL(0x105, futimesat(XlatAfd(di), P(si), P(dx))); + SYSCALL(0x102, mkdirat(XlatAfd(m, di), P(si), dx)); + SYSCALL(0x104, fchownat(XlatAfd(m, di), P(si), dx, r0, XlatAtf(r8))); + SYSCALL(0x105, futimesat(XlatAfd(m, di), P(si), P(dx))); SYSCALL(0x106, OpFstatat(m, di, si, dx, r0)); - SYSCALL(0x107, unlinkat(XlatAfd(di), P(si), XlatAtf(dx))); - SYSCALL(0x108, renameat(XlatAfd(di), P(si), XlatAfd(dx), P(r0))); + SYSCALL(0x107, unlinkat(XlatAfd(m, di), P(si), XlatAtf(dx))); + SYSCALL(0x108, renameat(XlatAfd(m, di), P(si), XlatAfd(m, dx), P(r0))); SYSCALL(0x10D, OpFaccessat(m, di, si, dx, r0)); SYSCALL(0x113, splice(di, P(si), dx, P(r0), r8, XlatAtf(r9))); SYSCALL(0x115, sync_file_range(di, si, dx, XlatAtf(r0))); - SYSCALL(0x118, utimensat(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)); CASE(0xE7, HaltMachine(m, di | 0x100)); default: diff --git a/tool/build/lib/syscall.h b/tool/build/lib/syscall.h index 747150e2..6227e4b3 100644 --- a/tool/build/lib/syscall.h +++ b/tool/build/lib/syscall.h @@ -4,8 +4,6 @@ #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ -enum MachineStatus; - void OpSyscall(struct Machine *); COSMOPOLITAN_C_END_ diff --git a/libc/runtime/enableavx.greg.c b/tool/build/lib/time.c similarity index 51% rename from libc/runtime/enableavx.greg.c rename to tool/build/lib/time.c index 528b18de..0fac5e20 100644 --- a/libc/runtime/enableavx.greg.c +++ b/tool/build/lib/time.c @@ -17,55 +17,24 @@ │ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │ │ 02110-1301 USA │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" -#include "libc/dce.h" -#include "libc/nexgen32e/nexgen32e.h" -#include "libc/nt/struct/context.h" -#include "libc/nt/thunk/msabi.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; */ -} +#include "libc/nexgen32e/rdtsc.h" +#include "libc/sysv/consts/clock.h" +#include "libc/time/time.h" +#include "tool/build/lib/endian.h" +#include "tool/build/lib/time.h" /** - * Requests authorization from operating system to do 256-bit math. - * @assume avx cpuid check performed by caller + * I am the timelorde. */ -int _init_enableavx(void) { - if (IsMetal()) { - EnableAvx(); - } else if (IsWindows()) { - EnableAvxOnWindows(); - } - return 0; +void OpRdtsc(struct Machine *m) { + uint64_t c; +#ifdef __x86_64__ + c = rdtsc(); +#else + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + c = ts.tv_sec * 1000000000 + ts.tv_nsec; +#endif + Write64(m->ax, (c >> 000) & 0xffffffff); + Write64(m->dx, (c >> 040) & 0xffffffff); } diff --git a/tool/build/lib/time.h b/tool/build/lib/time.h new file mode 100644 index 00000000..739230bb --- /dev/null +++ b/tool/build/lib/time.h @@ -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_ */ diff --git a/tool/build/tinyemu.c b/tool/build/tinyemu.c index 9cf311c9..760f36b2 100644 --- a/tool/build/tinyemu.c +++ b/tool/build/tinyemu.c @@ -36,6 +36,7 @@ int main(int argc, char *argv[]) { fputs(" PROG [ARGS...]\n", stderr); return EX_USAGE; } + InitMachine(m); LoadProgram(m, argv[1], argv + 2, environ, &elf); if (!(rc = setjmp(m->onhalt))) { for (;;) { diff --git a/tool/emacs/cosmo-c-keywords.el b/tool/emacs/cosmo-c-keywords.el index df573e46..5a626b14 100644 --- a/tool/emacs/cosmo-c-keywords.el +++ b/tool/emacs/cosmo-c-keywords.el @@ -134,6 +134,7 @@ "textexit" "externinline" "noinline" + "noclone" "donothing" "byanymeansnecessary" "threadlocal" diff --git a/tool/viz/lib/ansitrinsics.h b/tool/viz/lib/ansitrinsics.h deleted file mode 100644 index a3451b9d..00000000 --- a/tool/viz/lib/ansitrinsics.h +++ /dev/null @@ -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_ */ diff --git a/tool/viz/lib/scale.h b/tool/viz/lib/scale.h deleted file mode 100644 index bbc5585f..00000000 --- a/tool/viz/lib/scale.h +++ /dev/null @@ -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_ */ diff --git a/tool/viz/lib/ycbcr2rgb3.c b/tool/viz/lib/ycbcr2rgb3.c index 1833fe4c..9a0feb0b 100644 --- a/tool/viz/lib/ycbcr2rgb3.c +++ b/tool/viz/lib/ycbcr2rgb3.c @@ -49,7 +49,6 @@ #include "third_party/avir/lanczos.h" #include "tool/viz/lib/graphic.h" #include "tool/viz/lib/knobs.h" -#include "tool/viz/lib/scale.h" #include "tool/viz/lib/ycbcr.h" #define M 15 diff --git a/tool/viz/magikarp.c b/tool/viz/magikarp.c index f7d4c4fe..467eff69 100644 --- a/tool/viz/magikarp.c +++ b/tool/viz/magikarp.c @@ -48,7 +48,6 @@ #include "third_party/stb/stb_image.h" #include "tool/viz/lib/bilinearscale.h" #include "tool/viz/lib/graphic.h" -#include "tool/viz/lib/scale.h" #define LONG long #define CHAR char diff --git a/tool/viz/printimage.c b/tool/viz/printimage.c index 6cb7f6cf..65b1b761 100644 --- a/tool/viz/printimage.c +++ b/tool/viz/printimage.c @@ -17,6 +17,7 @@ │ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │ │ 02110-1301 USA │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "dsp/core/half.h" #include "dsp/core/twixt8.h" #include "dsp/scale/scale.h" #include "dsp/tty/quant.h" @@ -59,6 +60,7 @@ static struct Flags { bool unsharp; bool dither; bool ruler; + bool trailingnewline; long half; bool full; long width; @@ -129,9 +131,11 @@ static void GetOpts(int *argc, char *argv[]) { g_flags.unsharp = true; break; case 'w': + g_flags.trailingnewline = true; g_flags.width = ParseNumberOption(optarg); break; case 'h': + g_flags.trailingnewline = true; g_flags.height = ParseNumberOption(optarg); break; 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, bool *inout_didhalfy) { if (y == 0) { - printf("\e[0m‾0"); + printf("‾0"); } 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; } else if (y + 1 == yn / 2 && !*inout_didhalfy) { - printf("\e[0m⎯yn/2"); + printf("⎯yn/2"); *inout_didhalfy = true; } else if (y + 1 == yn) { - printf("\e[0m⎯yn"); + printf("⎯yn"); } else if (y + 2 == yn) { - printf("\e[0m_yn"); + printf("_yn"); } 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'▐'); didfirstx = true; } + printf("\e[0m"); if (g_flags.ruler) { 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], @@ -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 = stpcpy(p, "\r\e[0m"); + *p++ = '\r'; + if (g_flags.trailingnewline) *p++ = '\n'; + p = stpcpy(p, "\e[0m"); ttywrite(STDOUT_FILENO, vt, p - vt); }