Justine Tunney 2020-08-26 23:08:08 -07:00
parent e86cff8ba0
commit 5aabacb361
94 changed files with 3245 additions and 2179 deletions

View File

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

View File

@ -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) {
if (g_ttyraw.next[i]) {
g_ttyraw.next[i](sig, info, ctx);
}
} else if (sig != SIGCONT) {
_Exit(128 + sig);
}

View File

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

View File

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

View File

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

View File

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

View File

@ -9,7 +9,8 @@
#define kLogError 1u
#define kLogWarn 2u
#define kLogInfo 3u
#define kLogDebug 4u
#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;

View File

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

View File

@ -0,0 +1,24 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/nexgen32e/bsf.h"
int(bsf)(int x) {
return bsf(x);
}

View File

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

View File

@ -0,0 +1,24 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/nexgen32e/bsf.h"
int(bsfl)(long x) {
return bsfl(x);
}

View File

@ -0,0 +1,24 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/nexgen32e/bsf.h"
int(bsfll)(long long x) {
return bsfll(x);
}

View File

@ -0,0 +1,24 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/nexgen32e/bsr.h"
int(bsr)(int x) {
return bsr(x);
}

View File

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

View File

@ -0,0 +1,24 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/nexgen32e/bsr.h"
int(bsrl)(long x) {
return bsrl(x);
}

View File

@ -0,0 +1,24 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/nexgen32e/bsr.h"
int(bsrll)(long long x) {
return bsrll(x);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -37,6 +37,7 @@ LIBC_RUNTIME_A_DIRECTDEPS = \
LIBC_BITS \
LIBC_CALLS \
LIBC_CONV \
LIBC_TINYMATH \
LIBC_ELF \
LIBC_FMT \
LIBC_NEXGEN32E \

View File

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

View File

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

View File

@ -0,0 +1,8 @@
#ifndef COSMOPOLITAN_LIBC_STR_THOMPIKE_H_
#define COSMOPOLITAN_LIBC_STR_THOMPIKE_H_
#include "libc/nexgen32e/bsr.h"
#define ThomPikeCont(x) ((x & 0b11000000) == 0b10000000)
#define ThomPikeByte(x) (x & (((1 << (x < 252 ? bsr(~x & 0xff) : 1)) - 1) | 3))
#endif /* COSMOPOLITAN_LIBC_STR_THOMPIKE_H_ */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -29,6 +29,7 @@ TEST_LIBC_RUNTIME_DIRECTDEPS = \
LIBC_CALLS_HEFTY \
LIBC_FMT \
LIBC_MEM \
LIBC_TINYMATH \
LIBC_NEXGEN32E \
LIBC_RAND \
LIBC_RUNTIME \

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -19,8 +19,6 @@
*/
#include "libc/macros.h"
cmpxchg %ecx,(%rdx)
.section .start,"ax",@progbits
emucrt: bofram 9f
movslq (%rsp),%rdi # argc

View File

@ -22,7 +22,7 @@ ENTRY(_start)
SECTIONS {
.text : {
.text IMAGE_BASE_VIRTUAL : {
*(.start)
KEEP(*(.initprologue))
KEEP(*(SORT_BY_NAME(.init.*)))

View File

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

View File

@ -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) {
uint8_t *p;
if ((p = FindReal(m, v))) {
return bing(p[0], 0);
} else {
return 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))) {
if (!setjmp(busted)) {
rc = bing(p[0], 0);
} else {
rc = u'';
}
} else {
rc = u'';
}
onbusted = NULL;
return rc;
}
static void ScrollOp(struct Panel *p, long op) {
@ -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,8 +980,34 @@ 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);
@ -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;
Exec();
} 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);
}
} 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;
Tui();
}
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();
}
}
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;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,55 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "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;
}
}

View File

@ -0,0 +1,27 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_FDS_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_FDS_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct MachineFds {
size_t i, n;
struct MachineFd {
int fd;
struct MachineFdCb {
int (*close)(int);
ssize_t (*read)(int, void *, size_t);
ssize_t (*write)(int, const void *, size_t);
} * cb;
} * p;
struct MachineFdClosed {
unsigned fd;
struct MachineFdClosed *next;
} * closed;
};
int MachineFdAdd(struct MachineFds *);
void MachineFdRemove(struct MachineFds *, int);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_FDS_H_ */

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@ -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 SibBase(x) ((x & 000007000000) >> 022)
#define SibIndex(x) ((x & 000700000000) >> 030)
#define ModrmRm(x) ((x & 000000000700) >> 006)
#define ModrmReg(x) ((x & 000000000007) >> 000)
#define ModrmSrm(x) ((x & 000000070000) >> 014)
#define ModrmMod(x) ((x & 000060000000) >> 026)
#define RegLog2(x) ((x & 006000000000) >> 034)
#define Rexx(x) ((x & 001000000000) >> 033)
#define Asz(x) ((x & 000000400000) >> 021)
#define Rexw(x) ((x & 000000004000) >> 013)
#define Rexr(x) ((x & 000000000010) >> 003)
#define Rexb(x) ((x & 000010000000) >> 025)
#define Rex(x) ((x & 000000000020) >> 004)
#define Osz(x) ((x & 000000000040) >> 005)
#define Rep(x) ((x & 030000000000) >> 036)
#define IsModrmRegister(x) (ModrmMod(x) == 3)
#define 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])
int64_t ComputeAddress(const struct Machine *) nosideeffect;
#define ByteRexrReg(m, x) m->beg[(x & 00000000037) >> 0]
#define ByteRexbRm(m, x) m->beg[(x & 00000003700) >> 6]
#define ByteRexbSrm(m, x) m->beg[(x & 00000370000) >> 12]
#define RegRexbSrm(m, x) Abp8(m->reg[(x & 00000170000) >> 12])
#define RegRexrReg(m, x) Abp8(m->reg[(x & 00000000017) >> 0])
#define RegRexbRm(m, x) Abp8(m->reg[(x & 00000001700) >> 6])
#define RegRexbBase(m, x) Abp8(m->reg[(x & 00017000000) >> 18])
#define RegRexxIndex(m, x) Abp8(m->reg[(x & 01700000000) >> 24])
#define XmmRexrReg(m, x) Abp16(m->veg[(x & 00000000017) >> 0])
#define XmmRexbRm(m, x) Abp16(m->veg[(x & 00000001700) >> 6])
#define MmReg(m, x) Abp16(m->veg[(x & 00000000007) >> 0])
#define MmRm(m, x) Abp16(m->veg[(x & 00000000700) >> 6])
void *ComputeReserveAddressRead(struct Machine *, size_t);
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 *);
int64_t ComputeAddress(const struct Machine *, uint32_t) nosideeffect;
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 *);
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) */

View File

@ -0,0 +1,512 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.h"
#include "libc/conv/conv.h"
#include "libc/log/check.h"
#include "libc/macros.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/bsr.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/str/thompike.h"
#include "libc/unicode/unicode.h"
#include "libc/x/x.h"
#include "tool/build/lib/pty.h"
struct MachinePty *MachinePtyNew(unsigned yn, unsigned xn) {
struct MachinePty *pty;
DCHECK_GT(yn, 0);
DCHECK_GT(xn, 0);
pty = xcalloc(1, sizeof(struct MachinePty));
pty->yn = yn;
pty->xn = xn;
pty->wcs = xcalloc(yn * xn, sizeof(pty->wcs[0]));
pty->fgs = xcalloc(yn * xn, sizeof(pty->fgs[0]));
pty->bgs = xcalloc(yn * xn, sizeof(pty->bgs[0]));
pty->prs = xcalloc(yn * xn, sizeof(pty->prs[0]));
return pty;
}
void MachinePtyFree(struct MachinePty *pty) {
if (pty) {
free(pty->wcs);
free(pty->fgs);
free(pty->bgs);
free(pty->prs);
free(pty);
}
}
static void MachinePtyScrollPlane(struct MachinePty *pty, uint32_t *p) {
memcpy(p, p + pty->xn, sizeof(p[0]) * pty->xn * (pty->yn - 1));
memset(p + pty->xn * (pty->yn - 1), 0, sizeof(p[0]) * pty->xn);
}
static void MachinePtyScroll(struct MachinePty *pty) {
MachinePtyScrollPlane(pty, pty->wcs);
MachinePtyScrollPlane(pty, pty->fgs);
MachinePtyScrollPlane(pty, pty->bgs);
MachinePtyScrollPlane(pty, pty->prs);
}
static void MachinePtyNewline(struct MachinePty *pty) {
pty->x = 0;
if (++pty->y == pty->yn) {
--pty->y;
MachinePtyScroll(pty);
}
}
static void SetMachinePtyCell(struct MachinePty *pty, wint_t wc) {
uint32_t w, i;
if ((w = MAX(0, wcwidth(wc))) > 0) {
i = pty->y * pty->xn + pty->x;
pty->wcs[i] = wc;
pty->fgs[i] = pty->fg;
pty->bgs[i] = pty->bg;
pty->prs[i] = pty->pr;
if ((pty->x += w) >= pty->xn) {
pty->x = 0;
MachinePtyNewline(pty);
}
}
}
static void MachinePtyTab(struct MachinePty *pty) {
unsigned x, x2;
x2 = pty->x + ROUNDUP(pty->x + 1, 8);
if (x2 >= pty->xn) x2 = pty->xn - 1;
for (x = pty->x; x < x2; ++x) {
pty->wcs[pty->y * pty->xn + x] = 0;
}
pty->x = x2;
}
static void MachinePtyCursorSet(struct MachinePty *pty, int y, int x) {
pty->y = MAX(0, MIN(pty->yn - 1, y));
pty->x = MAX(0, MIN(pty->xn - 1, x));
}
static void MachinePtyCursorMove(struct MachinePty *pty, int dy, int dx) {
int n;
if (pty->esc.i > 1) {
n = atoi(pty->esc.s);
dy *= n;
dx *= n;
}
MachinePtyCursorSet(pty, pty->y + dy, pty->x + dx);
}
static void MachinePtyCursorPosition(struct MachinePty *pty) {
int row, col;
row = MAX(1, atoi(pty->esc.s));
col = MAX(1, atoi((char *)firstnonnull(strchr(pty->esc.s, ';'), "x") + 1));
MachinePtyCursorSet(pty, row - 1, col - 1);
}
static void MachinePtyEraseRange(struct MachinePty *pty, size_t i, size_t j) {
size_t n;
n = (j - i) * sizeof(uint32_t);
memset(pty->wcs + i, 0, n);
memset(pty->fgs + i, 0, n);
memset(pty->bgs + i, 0, n);
memset(pty->prs + i, 0, n);
}
static void MachinePtyEraseDisplay(struct MachinePty *pty) {
switch (atoi(pty->esc.s)) {
case 3:
case 2:
pty->y = 0;
pty->x = 0;
case 0:
MachinePtyEraseRange(pty, pty->y * pty->xn + pty->x, pty->yn * pty->xn);
break;
case 1:
MachinePtyEraseRange(pty, 0, pty->y * pty->xn + pty->x);
break;
default:
break;
}
}
static void MachinePtyEraseLine(struct MachinePty *pty) {
switch (atoi(pty->esc.s)) {
case 0:
MachinePtyEraseRange(pty, pty->y * pty->xn + pty->x,
pty->y * pty->xn + pty->xn);
break;
case 1:
MachinePtyEraseRange(pty, pty->y * pty->xn + pty->xn,
pty->y * pty->xn + pty->x);
break;
case 2:
MachinePtyEraseRange(pty, pty->y * pty->xn, pty->y * pty->xn + pty->xn);
break;
default:
break;
}
}
static void MachinePtySelectGraphicsRendition(struct MachinePty *pty) {
char *p, c;
unsigned x;
uint8_t code[4];
enum {
kSgr,
kSgrFg = 010,
kSgrFgTrue = 012,
kSgrFgXterm = 015,
kSgrBg = 020,
kSgrBgTrue = 022,
kSgrBgXterm = 025,
} t;
x = 0;
t = kSgr;
p = pty->esc.s;
memset(code, 0, sizeof(code));
for (;;) {
c = *p++;
switch (c) {
case '\0':
return;
case '0' ... '9':
x *= 10;
x += c - '0';
break;
case ';':
case 'm':
code[code[3]] = x;
x = 0;
switch (t) {
case kSgr:
switch (code[0]) {
case 0:
pty->fg = 0;
pty->bg = 0;
pty->pr = 0;
break;
case 1:
pty->pr |= kMachinePtyBold;
break;
case 21:
pty->pr &= ~kMachinePtyBold;
break;
case 2:
pty->pr |= kMachinePtyFaint;
break;
case 22:
pty->pr &= ~kMachinePtyFaint;
break;
case 7:
pty->pr |= kMachinePtyFlip;
break;
case 27:
pty->pr &= ~kMachinePtyFlip;
break;
case 90 ... 97:
code[0] -= 90 - 30;
code[0] += 8;
case 30 ... 37:
pty->fg = code[0] - 30;
pty->pr |= kMachinePtyFg;
pty->pr &= ~kMachinePtyTrue;
break;
case 38:
t = kSgrFg;
break;
case 39:
pty->pr &= kMachinePtyFg;
break;
case 100 ... 107:
code[0] -= 100 - 40;
code[0] += 8;
case 40 ... 47:
pty->bg = code[0] - 40;
pty->pr |= kMachinePtyBg;
pty->pr &= ~kMachinePtyTrue;
break;
case 48:
t = kSgrBg;
break;
case 49:
pty->pr &= kMachinePtyBg;
break;
default:
break;
}
break;
case kSgrFg:
case kSgrBg:
switch (code[0]) {
case 2:
case 5:
t += code[0];
break;
default:
t = kSgr;
break;
}
break;
case kSgrFgTrue:
if (++code[3] == 3) {
code[3] = 0;
t = kSgr;
pty->fg = READ32LE(code);
pty->pr |= kMachinePtyFg;
pty->pr |= kMachinePtyTrue;
}
break;
case kSgrBgTrue:
if (++code[3] == 3) {
code[3] = 0;
t = kSgr;
pty->bg = READ32LE(code);
pty->pr |= kMachinePtyBg;
pty->pr |= kMachinePtyTrue;
}
break;
case kSgrFgXterm:
t = kSgr;
pty->fg = code[0];
pty->pr |= kMachinePtyFg;
pty->pr &= ~kMachinePtyTrue;
break;
case kSgrBgXterm:
t = kSgr;
pty->bg = code[0];
pty->pr |= kMachinePtyBg;
pty->pr &= ~kMachinePtyTrue;
break;
default:
abort();
}
break;
default:
break;
}
}
}
static void MachinePtyHideCursor(struct MachinePty *pty) {
pty->conf |= kMachinePtyNocursor;
}
static void MachinePtyShowCursor(struct MachinePty *pty) {
pty->conf &= ~kMachinePtyNocursor;
}
static void MachinePtyCsi(struct MachinePty *pty) {
switch (pty->esc.s[pty->esc.i - 1]) {
case 'A':
MachinePtyCursorMove(pty, -1, +0);
break;
case 'B':
MachinePtyCursorMove(pty, +1, +0);
break;
case 'C':
MachinePtyCursorMove(pty, +0, +1);
break;
case 'D':
MachinePtyCursorMove(pty, +0, -1);
break;
case 'f':
case 'H':
MachinePtyCursorPosition(pty);
break;
case 'J':
MachinePtyEraseDisplay(pty);
break;
case 'K':
MachinePtyEraseLine(pty);
break;
case 'm':
MachinePtySelectGraphicsRendition(pty);
break;
case 'l':
if (strcmp(pty->esc.s, "?25l") == 0) {
MachinePtyHideCursor(pty);
}
break;
case 'h':
if (strcmp(pty->esc.s, "?25h") == 0) {
MachinePtyShowCursor(pty);
}
break;
default:
break;
}
}
static void MachinePtyEsc(struct MachinePty *pty) {
}
static void MachinePtyEscAppend(struct MachinePty *pty, char c) {
pty->esc.i = MIN(pty->esc.i + 1, ARRAYLEN(pty->esc.s) - 1);
pty->esc.s[pty->esc.i - 1] = c;
pty->esc.s[pty->esc.i - 0] = '\0';
}
ssize_t MachinePtyWrite(struct MachinePty *pty, const void *data, size_t n) {
int i;
const uint8_t *p;
for (p = data, i = 0; i < n; ++i) {
switch (pty->state) {
case kMachinePtyAscii:
if (p[i] < 0b10000000) {
switch (p[i]) {
case '\e':
pty->state = kMachinePtyEsc;
pty->esc.i = 0;
break;
case '\t':
MachinePtyTab(pty);
break;
case '\r':
pty->x = 0;
break;
case '\n':
MachinePtyNewline(pty);
break;
default:
SetMachinePtyCell(pty, p[i]);
break;
}
} else if (!ThomPikeCont(p[i])) {
pty->state = kMachinePtyUtf8;
pty->u8 = ThomPikeByte(p[i]);
}
break;
case kMachinePtyUtf8:
if (ThomPikeCont(p[i])) {
pty->u8 <<= 6;
pty->u8 |= p[i] & 0b00111111;
} else {
SetMachinePtyCell(pty, pty->u8);
pty->state = kMachinePtyAscii;
pty->u8 = 0;
--i;
}
break;
case kMachinePtyEsc:
if (p[i] == '[') {
pty->state = kMachinePtyCsi;
} else if (0x30 <= p[i] && p[i] <= 0x7e) {
MachinePtyEscAppend(pty, p[i]);
MachinePtyEsc(pty);
pty->state = kMachinePtyAscii;
} else if (0x20 <= p[i] && p[i] <= 0x2f) {
MachinePtyEscAppend(pty, p[i]);
} else {
pty->state = kMachinePtyAscii;
}
break;
case kMachinePtyCsi:
MachinePtyEscAppend(pty, p[i]);
switch (p[i]) {
case ':':
case ';':
case '<':
case '=':
case '>':
case '?':
case '0' ... '9':
break;
case '`':
case '~':
case '^':
case '@':
case '[':
case ']':
case '{':
case '}':
case '_':
case '|':
case '\\':
case 'A' ... 'Z':
case 'a' ... 'z':
MachinePtyCsi(pty);
pty->state = kMachinePtyAscii;
break;
default:
pty->state = kMachinePtyAscii;
continue;
}
break;
default:
abort();
}
}
if (pty->u8) {
SetMachinePtyCell(pty, pty->u8);
}
return n;
}
void MachinePtyAppendLine(struct MachinePty *pty, struct Buffer *buf,
unsigned y) {
uint32_t x, i, fg, bg, pr, wc, w;
CHECK_LT(y, pty->yn);
for (fg = bg = pr = x = 0; x < pty->xn; x += w) {
i = y * pty->xn + x;
wc = pty->wcs[i];
w = MAX(0, wcwidth(wc));
if (w) {
if (pty->prs[i] != pr || pty->fgs[i] != fg || pty->bgs[i] != bg) {
fg = pty->fgs[i];
bg = pty->bgs[i];
pr = pty->prs[i];
AppendStr(buf, "\e[0");
if (pr & kMachinePtyBold) AppendStr(buf, ";1");
if (pr & kMachinePtyFaint) AppendStr(buf, ";2");
if (pr & kMachinePtyFlip) AppendStr(buf, ";7");
if (pr & kMachinePtyFg) {
if (pr & kMachinePtyTrue) {
AppendFmt(buf, ";38;2;%d;%d;%d", (fg & 0x0000ff) >> 000,
(fg & 0x00ff00) >> 010, (fg & 0xff0000) >> 020);
} else {
AppendFmt(buf, ";38;5;%d", fg);
}
}
if (pr & kMachinePtyBg) {
if (pr & kMachinePtyTrue) {
AppendFmt(buf, ";48;2;%d;%d;%d", (bg & 0x0000ff) >> 000,
(bg & 0x00ff00) >> 010, (bg & 0xff0000) >> 020);
} else {
AppendFmt(buf, ";48;5;%d", bg);
}
}
AppendStr(buf, "m");
}
AppendWide(buf, wc);
} else {
w = 1;
if (y == pty->y && x == pty->x) {
if (!(pty->conf & kMachinePtyNocursor)) {
AppendStr(buf, "\e[5m▂\e[25m");
}
} else {
AppendChar(buf, ' ');
}
}
}
AppendStr(buf, "\e[0m");
}

View File

@ -0,0 +1,50 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_PTY_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_PTY_H_
#include "tool/build/lib/buffer.h"
#define kMachinePtyFg 0x01
#define kMachinePtyBg 0x02
#define kMachinePtyTrue 0x04
#define kMachinePtyBold 0x08
#define kMachinePtyFaint 0x10
#define kMachinePtyFlip 0x20
#define kMachinePtyNocursor 0x01
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct MachinePty {
uint32_t yn;
uint32_t xn;
uint32_t y;
uint32_t x;
uint32_t pr;
uint32_t fg;
uint32_t bg;
uint32_t u8;
uint32_t *wcs;
uint32_t *fgs;
uint32_t *bgs;
uint32_t *prs;
uint32_t conf;
enum MachinePtyState {
kMachinePtyAscii,
kMachinePtyUtf8,
kMachinePtyEsc,
kMachinePtyCsi,
} state;
struct MachinePtyEsc {
unsigned i;
char s[64];
} esc;
};
struct MachinePty *MachinePtyNew(unsigned, unsigned) nodiscard;
void MachinePtyFree(struct MachinePty *);
ssize_t MachinePtyWrite(struct MachinePty *, const void *, size_t);
void MachinePtyAppendLine(struct MachinePty *, struct Buffer *, unsigned);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_PTY_H_ */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -4,8 +4,6 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
enum MachineStatus;
void OpSyscall(struct Machine *);
COSMOPOLITAN_C_END_

View File

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

View File

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

View File

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

View File

@ -134,6 +134,7 @@
"textexit"
"externinline"
"noinline"
"noclone"
"donothing"
"byanymeansnecessary"
"threadlocal"

View File

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

View File

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

View File

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

View File

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

View File

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