mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-03 09:48:29 +00:00
Enhance chibicc
This commit is contained in:
parent
8da931a7f6
commit
9df2cef4c4
52 changed files with 2606 additions and 2004 deletions
|
@ -88,12 +88,6 @@ o/$(MODE)/tool/build/emulator.o: \
|
|||
OVERRIDE_COPTS += \
|
||||
-fno-sanitize=pointer-overflow
|
||||
|
||||
# ifeq (,$(MODE))
|
||||
# $(TOOL_BUILD_OBJS): \
|
||||
# OVERRIDE_COPTS += \
|
||||
# -fsanitize=address
|
||||
# endif
|
||||
|
||||
.PHONY: o/$(MODE)/tool/build
|
||||
o/$(MODE)/tool/build: \
|
||||
o/$(MODE)/tool/build/emucrt \
|
||||
|
|
|
@ -1,230 +0,0 @@
|
|||
/*-*- 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 "dsp/core/half.h"
|
||||
#include "dsp/core/q.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/ex.h"
|
||||
#include "libc/sysv/consts/exit.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "third_party/gdtoa/gdtoa.h"
|
||||
#include "third_party/getopt/getopt.h"
|
||||
|
||||
#define USAGE \
|
||||
" [FLAGS] [INT|FLOAT...]\n\
|
||||
\n\
|
||||
Example:\n\
|
||||
\n\
|
||||
coefficients -n -- 1 4 6 4 1 # Gaussian Blur\n\
|
||||
coefficients -L16 -H235 -- .299 .587 .114 # BT.601 RGB→Y\n\
|
||||
\n\
|
||||
Flags:\n\
|
||||
-v verbose\n\
|
||||
-n normalize\n\
|
||||
-m FLEX explicit Q(bits)\n\
|
||||
-L FLEX low data value [default 0]\n\
|
||||
-H FLEX high data value [default 255]\n\
|
||||
-? shows this information\n\
|
||||
\n"
|
||||
|
||||
static struct Flags {
|
||||
bool n;
|
||||
long L, H, m;
|
||||
} flags_ = {
|
||||
.L = 0,
|
||||
.H = 255,
|
||||
};
|
||||
|
||||
static wontreturn void PrintUsage(int rc, FILE *f) {
|
||||
fprintf(f, "Usage: %s%s", program_invocation_name, USAGE);
|
||||
exit(rc);
|
||||
}
|
||||
|
||||
static void GetOpts(int argc, char *argv[]) {
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "?nvrL:H:m:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'v':
|
||||
g_loglevel++;
|
||||
break;
|
||||
case 'n':
|
||||
flags_.n = true;
|
||||
break;
|
||||
case 'L':
|
||||
flags_.L = strtol(optarg, NULL, 0);
|
||||
break;
|
||||
case 'H':
|
||||
flags_.H = strtol(optarg, NULL, 0);
|
||||
break;
|
||||
case 'm':
|
||||
flags_.m = strtol(optarg, NULL, 0);
|
||||
break;
|
||||
case '?':
|
||||
PrintUsage(EXIT_SUCCESS, stdout);
|
||||
default:
|
||||
PrintUsage(EX_USAGE, stderr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void *Normalize(int n, double A[static 8]) {
|
||||
int i;
|
||||
double sum, rnorm;
|
||||
for (sum = i = 0; i < n; ++i) {
|
||||
sum += A[i];
|
||||
}
|
||||
if (fabs(sum - 1) > DBL_MIN * n) {
|
||||
rnorm = 1 / sum;
|
||||
for (i = 0; i < n; ++i) {
|
||||
A[i] *= rnorm;
|
||||
}
|
||||
}
|
||||
return A;
|
||||
}
|
||||
|
||||
static void GetLimits(int n, const long I[static 8], long m, long L, long H,
|
||||
long res[2][2]) {
|
||||
int i, j[8];
|
||||
long x, p[2] = {L, H};
|
||||
DCHECK(0 < n && n <= 8);
|
||||
memset(res, 0, sizeof(long) * 2 * 2);
|
||||
for (j[0] = 0; j[0] < ARRAYLEN(p); ++j[0]) {
|
||||
for (j[1] = 0; j[1] < ARRAYLEN(p); ++j[1]) {
|
||||
for (j[2] = 0; j[2] < ARRAYLEN(p); ++j[2]) {
|
||||
for (j[3] = 0; j[3] < ARRAYLEN(p); ++j[3]) {
|
||||
for (j[4] = 0; j[4] < ARRAYLEN(p); ++j[4]) {
|
||||
for (j[5] = 0; j[5] < ARRAYLEN(p); ++j[5]) {
|
||||
for (j[6] = 0; j[6] < ARRAYLEN(p); ++j[6]) {
|
||||
for (j[7] = 0; j[7] < ARRAYLEN(p); ++j[7]) {
|
||||
x = 0;
|
||||
for (i = 0; i < ARRAYLEN(j); ++i) {
|
||||
x += p[j[i]] * I[i];
|
||||
if (x < res[0][0]) res[0][0] = x;
|
||||
if (x > res[0][1]) res[0][1] = x;
|
||||
}
|
||||
x += 1l << (m - 1);
|
||||
if (x < res[0][0]) res[0][0] = x;
|
||||
if (x > res[0][1]) res[0][1] = x;
|
||||
x >>= m;
|
||||
if (x < res[1][0]) res[1][0] = x;
|
||||
if (x > res[1][1]) res[1][1] = x;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const char *GetFittingMachineWord(long L, long H) {
|
||||
if (-128 <= L && H <= 127) return "int8";
|
||||
if (0 <= L && H <= 255) return "uint8";
|
||||
if (-0x8000 <= L && H <= 0x7fff) return "int16";
|
||||
if (~0x7fffffff <= L && H <= 0x7fffffff) return "int32";
|
||||
if (0 <= L && H <= 0xffffffff) return "uint32";
|
||||
return "INT64";
|
||||
}
|
||||
|
||||
static char *DescribeMachineWord(long L, long H) {
|
||||
return xasprintf("%s[%,ld..%,ld]", GetFittingMachineWord(L, H), L, H);
|
||||
}
|
||||
|
||||
static void ShowBetterCoefficients(int n, double C[static 8], long L, long H) {
|
||||
long err, I[8], lim[2][2];
|
||||
char buf[32], kAlphabet[] = "abcdefgh";
|
||||
int i, j, m, emitted, count, indices[8];
|
||||
CHECK_LT(L, H);
|
||||
DCHECK(0 < n && n <= 8);
|
||||
for (m = 2; m < 40; ++m) {
|
||||
memset(I, 0, sizeof(I));
|
||||
if (C[6] || C[7]) {
|
||||
err = GetIntegerCoefficients8(I, C, m, L, H);
|
||||
} else {
|
||||
err = GetIntegerCoefficients(I, C, m, L, H);
|
||||
}
|
||||
GetLimits(n, I, m, L, H, lim);
|
||||
for (count = i = 0; i < n; ++i) {
|
||||
if (I[i]) {
|
||||
indices[count++] = i;
|
||||
}
|
||||
}
|
||||
if (count) {
|
||||
emitted = 0;
|
||||
if (m) emitted += printf("(");
|
||||
for (i = 0; i < count; ++i) {
|
||||
if (i) emitted += printf(" + ");
|
||||
if (I[indices[i]] != 1) {
|
||||
emitted += printf("%ld*%c", I[indices[i]], kAlphabet[indices[i]]);
|
||||
} else {
|
||||
emitted += printf("%c", kAlphabet[indices[i]]);
|
||||
}
|
||||
}
|
||||
if (m) {
|
||||
if (m > 1) {
|
||||
emitted += printf(" + %ld", 1l << (m - 1));
|
||||
}
|
||||
emitted += printf(")>>%d", m);
|
||||
}
|
||||
printf("%*s", MAX(0, 80 - emitted), " ");
|
||||
printf("/* %s %s %s ε=%,ld */\n", gc(DescribeMachineWord(L, H)),
|
||||
gc(DescribeMachineWord(lim[0][0], lim[0][1])),
|
||||
gc(DescribeMachineWord(lim[1][0], lim[1][1])), err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int ReadIdealCoefficients(double C[static 8], int sn, char *S[sn]) {
|
||||
int i, n;
|
||||
if ((n = MIN(8, sn)) > 0) {
|
||||
C[0] = C[1] = C[2] = C[3] = C[4] = C[5] = 0;
|
||||
for (i = 0; i < n; ++i) {
|
||||
C[i] = strtod(S[i], NULL);
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
int ToolBuildCoefficients(int argc, char *argv[]) {
|
||||
int n;
|
||||
double C[8];
|
||||
GetOpts(argc, argv);
|
||||
setvbuf(stdout, malloc(PAGESIZE), _IOLBF, PAGESIZE);
|
||||
if ((n = ReadIdealCoefficients(C, argc - optind, argv + optind))) {
|
||||
if (flags_.n) Normalize(n, C);
|
||||
ShowBetterCoefficients(n, C, flags_.L, flags_.H);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
g_loglevel = kLogWarn;
|
||||
showcrashreports();
|
||||
return ToolBuildCoefficients(argc, argv);
|
||||
}
|
|
@ -1,267 +0,0 @@
|
|||
/*-*- 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 "dsp/scale/scale.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/fmt/bing.internal.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/ex.h"
|
||||
#include "libc/sysv/consts/exit.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "third_party/gdtoa/gdtoa.h"
|
||||
#include "third_party/getopt/getopt.h"
|
||||
#include "third_party/stb/stb_image.h"
|
||||
#include "third_party/xed/x86.h"
|
||||
|
||||
#define USAGE \
|
||||
" [FLAGS] [PATH]\n\
|
||||
\n\
|
||||
Example:\n\
|
||||
\n\
|
||||
img2code -cw79 -p2 foo.png\n\
|
||||
\n\
|
||||
Flags:\n\
|
||||
-c compress range\n\
|
||||
-o PATH out\n\
|
||||
-r FLEX ratio\n\
|
||||
-w FLEX new width\n\
|
||||
-h FLEX new height\n\
|
||||
-p FLEX pixel y ratio\n\
|
||||
-? shows this information\n\
|
||||
\n"
|
||||
|
||||
static struct Flags {
|
||||
const char *o;
|
||||
double r, p;
|
||||
int w, h;
|
||||
bool c;
|
||||
} flags_ = {
|
||||
.o = "-",
|
||||
.p = 1,
|
||||
};
|
||||
|
||||
static wontreturn void PrintUsage(int rc, FILE *f) {
|
||||
fprintf(f, "Usage: %s%s", program_invocation_name, USAGE);
|
||||
exit(rc);
|
||||
}
|
||||
|
||||
static void GetOpts(int *argc, char *argv[]) {
|
||||
int opt;
|
||||
if (*argc == 2 &&
|
||||
(strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-help") == 0)) {
|
||||
PrintUsage(EXIT_SUCCESS, stdout);
|
||||
}
|
||||
while ((opt = getopt(*argc, argv, "?co:r:w:h:p:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'c':
|
||||
flags_.c = true;
|
||||
break;
|
||||
case 'o':
|
||||
flags_.o = optarg;
|
||||
break;
|
||||
case 'r':
|
||||
flags_.r = strtod(optarg, NULL);
|
||||
break;
|
||||
case 'p':
|
||||
flags_.p = strtod(optarg, NULL);
|
||||
break;
|
||||
case 'w':
|
||||
flags_.w = strtol(optarg, NULL, 0);
|
||||
break;
|
||||
case 'h':
|
||||
flags_.h = strtol(optarg, NULL, 0);
|
||||
break;
|
||||
case '?':
|
||||
PrintUsage(EXIT_SUCCESS, stdout);
|
||||
default:
|
||||
PrintUsage(EX_USAGE, stderr);
|
||||
}
|
||||
}
|
||||
if (optind == *argc) {
|
||||
argv[(*argc)++] = "-";
|
||||
}
|
||||
}
|
||||
|
||||
static void GetOutputGeometry(long syn, long sxn, long *out_dyn, long *out_dxn,
|
||||
double *out_ry, double *out_rx) {
|
||||
double ry, rx;
|
||||
long dyn, dxn;
|
||||
if (!flags_.h && !flags_.w) {
|
||||
if (flags_.r) {
|
||||
ry = flags_.r * flags_.p;
|
||||
rx = flags_.r;
|
||||
} else {
|
||||
ry = flags_.p;
|
||||
rx = 1;
|
||||
}
|
||||
dyn = round(syn / ry);
|
||||
dxn = round(sxn / rx);
|
||||
} else if (flags_.w && !flags_.h) {
|
||||
if (flags_.r) {
|
||||
rx = 1. * sxn / flags_.w;
|
||||
ry = flags_.r * flags_.p;
|
||||
dxn = flags_.w;
|
||||
dyn = round(syn / ry);
|
||||
} else {
|
||||
rx = 1. * sxn / flags_.w;
|
||||
ry = flags_.p * rx;
|
||||
dxn = flags_.w;
|
||||
dyn = round(syn / ry);
|
||||
}
|
||||
} else if (flags_.h && !flags_.w) {
|
||||
if (flags_.r) {
|
||||
rx = flags_.r;
|
||||
ry = flags_.p * syn / flags_.h;
|
||||
dxn = flags_.w;
|
||||
dyn = round(syn / ry);
|
||||
} else {
|
||||
ry = flags_.p * syn / flags_.h;
|
||||
rx = ry;
|
||||
dyn = flags_.h;
|
||||
dxn = round(syn / rx);
|
||||
}
|
||||
} else {
|
||||
ry = flags_.p;
|
||||
rx = 1;
|
||||
dyn = round(flags_.h / ry);
|
||||
dxn = flags_.w;
|
||||
}
|
||||
*out_dyn = dyn;
|
||||
*out_dxn = dxn;
|
||||
*out_ry = ry;
|
||||
*out_rx = rx;
|
||||
}
|
||||
|
||||
static void *Deinterlace(long dcn, long dyn, long dxn,
|
||||
unsigned char dst[dcn][dyn][dxn], long syw, long sxw,
|
||||
long scw, const unsigned char src[syw][sxw][scw],
|
||||
long syn, long sxn, long sy0, long sx0, long sc0) {
|
||||
long y, x, c;
|
||||
for (y = 0; y < dyn; ++y) {
|
||||
for (x = 0; x < dxn; ++x) {
|
||||
for (c = 0; c < dcn; ++c) {
|
||||
dst[c][y][x] = src[sy0 + y][sx0 + x][sc0 + c];
|
||||
}
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
static void CompressRange(long cn, long yn, long xn,
|
||||
unsigned char img[cn][yn][xn]) {
|
||||
static const char R[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
double f;
|
||||
long c, y, x, L, H;
|
||||
L = R[0], H = R[strlen(R) - 1];
|
||||
for (c = 0; c < cn; ++c) {
|
||||
for (y = 0; y < yn; ++y) {
|
||||
for (x = 0; x < xn; ++x) {
|
||||
f = img[c][y][x];
|
||||
f /= 255;
|
||||
f *= H - L;
|
||||
f += L;
|
||||
img[c][y][x] = MIN(H, MAX(L, lround(f)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintCode(FILE *f, long cn, long yn, long xn,
|
||||
unsigned char img[cn][yn][xn]) {
|
||||
long c, y, x;
|
||||
if (flags_.c) CompressRange(cn, yn, xn, img);
|
||||
for (c = 0; c < cn; ++c) {
|
||||
fputc('\n', f);
|
||||
for (y = 0; y < yn; ++y) {
|
||||
fputc('\n', f);
|
||||
for (x = 0; x < xn; ++x) {
|
||||
fputwc(bing(img[c][y][x], 0), f);
|
||||
}
|
||||
}
|
||||
}
|
||||
fputc('\n', f);
|
||||
}
|
||||
|
||||
static void ProcessImage(const char *path, long scn, long syn, long sxn,
|
||||
unsigned char img[syn][sxn][scn], FILE *f) {
|
||||
double ry, rx;
|
||||
long dyn, dxn, cn;
|
||||
GetOutputGeometry(syn, sxn, &dyn, &dxn, &ry, &rx);
|
||||
if (dyn == syn && dxn == sxn) {
|
||||
/* TODO(jart): Why doesn't Gyarados no-op? */
|
||||
PrintCode(f, scn, dyn, dxn,
|
||||
Deinterlace(scn, syn, sxn, gc(memalign(32, scn * syn * sxn)), syn,
|
||||
sxn, scn, img, syn, sxn, 0, 0, 0));
|
||||
} else {
|
||||
PrintCode(
|
||||
f, scn, dyn, dxn,
|
||||
EzGyarados(scn, dyn, dxn, gc(memalign(32, scn * dyn * dxn)), scn, syn,
|
||||
sxn,
|
||||
Deinterlace(scn, syn, sxn, gc(memalign(32, scn * syn * sxn)),
|
||||
syn, sxn, scn, img, syn, sxn, 0, 0, 0),
|
||||
0, scn, dyn, dxn, syn, sxn, ry, rx, 0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
static void WithImageFile(const char *path, FILE *f,
|
||||
void fn(const char *path, long cn, long yn, long xn,
|
||||
unsigned char src[yn][xn][cn], FILE *f)) {
|
||||
struct stat st;
|
||||
void *map, *data;
|
||||
int fd, yn, xn, cn;
|
||||
CHECK_NE(-1, (fd = open(path, O_RDONLY)), "%s", path);
|
||||
CHECK_NE(-1, fstat(fd, &st));
|
||||
CHECK_GT(st.st_size, 0);
|
||||
CHECK_LE(st.st_size, INT_MAX);
|
||||
CHECK_NE(MAP_FAILED,
|
||||
(map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)));
|
||||
CHECK_NOTNULL(
|
||||
(data = stbi_load_from_memory(map, st.st_size, &xn, &yn, &cn, 0)), "%s",
|
||||
path);
|
||||
CHECK_NE(-1, munmap(map, st.st_size));
|
||||
CHECK_NE(-1, close(fd));
|
||||
fn(path, cn, yn, xn, data, f);
|
||||
free(data);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int i;
|
||||
FILE *f;
|
||||
showcrashreports();
|
||||
GetOpts(&argc, argv);
|
||||
stbi_set_unpremultiply_on_load(true);
|
||||
CHECK_NOTNULL((f = fopen(flags_.o, "w")));
|
||||
for (i = optind; i < argc; ++i) {
|
||||
WithImageFile(argv[i], f, ProcessImage);
|
||||
}
|
||||
return fclose(f);
|
||||
}
|
|
@ -164,8 +164,8 @@ void OpMulAxAlEbSigned(struct Machine *m, uint32_t rde) {
|
|||
int16_t ax;
|
||||
uint8_t *p;
|
||||
p = GetModrmRegisterBytePointerRead(m, rde);
|
||||
__builtin_mul_overflow((int8_t)Read8(m->ax), (int8_t)Read8(p), &ax);
|
||||
of = (int)ax != (int8_t)ax;
|
||||
ax = (int8_t)Read8(m->ax) * (int8_t)Read8(p);
|
||||
of = ax != (int8_t)ax;
|
||||
m->flags = SetFlag(m->flags, FLAGS_CF, of);
|
||||
m->flags = SetFlag(m->flags, FLAGS_OF, of);
|
||||
Write16(m->ax, ax);
|
||||
|
@ -176,8 +176,8 @@ void OpMulAxAlEbUnsigned(struct Machine *m, uint32_t rde) {
|
|||
bool of;
|
||||
uint8_t *p;
|
||||
p = GetModrmRegisterBytePointerRead(m, rde);
|
||||
__builtin_mul_overflow(Read8(m->ax), Read8(p), &ax);
|
||||
of = (uint8_t)ax != ax;
|
||||
ax = Read8(m->ax) * Read8(p);
|
||||
of = ax != (uint8_t)ax;
|
||||
m->flags = SetFlag(m->flags, FLAGS_CF, of);
|
||||
m->flags = SetFlag(m->flags, FLAGS_OF, of);
|
||||
Write16(m->ax, ax);
|
||||
|
@ -256,10 +256,12 @@ static void AluImul(struct Machine *m, uint32_t rde, uint8_t *a, uint8_t *b) {
|
|||
of = __builtin_mul_overflow(x, y, &z);
|
||||
Write64(RegRexrReg(m, rde), z & 0xffffffff);
|
||||
} else {
|
||||
int16_t x, y, z;
|
||||
int z;
|
||||
int16_t x, y;
|
||||
x = Read16(a);
|
||||
y = Read16(b);
|
||||
of = __builtin_mul_overflow(x, y, &z);
|
||||
z = x * y;
|
||||
of = z != (int16_t)z;
|
||||
Write16(RegRexrReg(m, rde), z);
|
||||
}
|
||||
m->flags = SetFlag(m->flags, FLAGS_CF, of);
|
||||
|
|
|
@ -169,7 +169,7 @@ void *ReserveAddress(struct Machine *m, int64_t v, size_t n) {
|
|||
}
|
||||
|
||||
void *AccessRam(struct Machine *m, int64_t v, size_t n, void *p[2],
|
||||
uint8_t tmp[n], bool copy) {
|
||||
uint8_t *tmp, bool copy) {
|
||||
unsigned k;
|
||||
uint8_t *a, *b;
|
||||
DCHECK_LE(n, 0x1000);
|
||||
|
@ -188,32 +188,31 @@ void *AccessRam(struct Machine *m, int64_t v, size_t n, void *p[2],
|
|||
return tmp;
|
||||
}
|
||||
|
||||
void *Load(struct Machine *m, int64_t v, size_t n, uint8_t b[n]) {
|
||||
void *Load(struct Machine *m, int64_t v, size_t n, uint8_t *b) {
|
||||
void *p[2];
|
||||
SetReadAddr(m, v, n);
|
||||
return AccessRam(m, v, n, p, b, true);
|
||||
}
|
||||
|
||||
void *BeginStore(struct Machine *m, int64_t v, size_t n, void *p[2],
|
||||
uint8_t b[n]) {
|
||||
uint8_t *b) {
|
||||
SetWriteAddr(m, v, n);
|
||||
return AccessRam(m, v, n, p, b, false);
|
||||
}
|
||||
|
||||
void *BeginStoreNp(struct Machine *m, int64_t v, size_t n, void *p[2],
|
||||
uint8_t b[n]) {
|
||||
uint8_t *b) {
|
||||
if (!v) return NULL;
|
||||
return BeginStore(m, v, n, p, b);
|
||||
}
|
||||
|
||||
void *BeginLoadStore(struct Machine *m, int64_t v, size_t n, void *p[2],
|
||||
uint8_t b[n]) {
|
||||
uint8_t *b) {
|
||||
SetWriteAddr(m, v, n);
|
||||
return AccessRam(m, v, n, p, b, true);
|
||||
}
|
||||
|
||||
void EndStore(struct Machine *m, int64_t v, size_t n, void *p[2],
|
||||
uint8_t b[n]) {
|
||||
void EndStore(struct Machine *m, int64_t v, size_t n, void *p[2], uint8_t *b) {
|
||||
uint8_t *a;
|
||||
unsigned k;
|
||||
DCHECK_LE(n, 0x1000);
|
||||
|
@ -228,7 +227,7 @@ void EndStore(struct Machine *m, int64_t v, size_t n, void *p[2],
|
|||
}
|
||||
|
||||
void EndStoreNp(struct Machine *m, int64_t v, size_t n, void *p[2],
|
||||
uint8_t b[n]) {
|
||||
uint8_t *b) {
|
||||
if (v) EndStore(m, v, n, p, b);
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
* @return -1 w/ errno if an error happened
|
||||
* @see nblack's notcurses project too!
|
||||
*/
|
||||
ssize_t PrintPanels(int fd, long pn, struct Panel p[pn], long tyn, long txn) {
|
||||
ssize_t PrintPanels(int fd, long pn, struct Panel *p, long tyn, long txn) {
|
||||
wint_t wc;
|
||||
ssize_t rc;
|
||||
size_t wrote;
|
||||
|
|
|
@ -34,173 +34,6 @@
|
|||
#include "tool/build/lib/ssefloat.h"
|
||||
#include "tool/build/lib/throw.h"
|
||||
|
||||
#define SSE_BUILTINS \
|
||||
(!IsModeDbg() && __SSE3__ + 0 && \
|
||||
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 408)
|
||||
|
||||
typedef int int_v _Vector_size(16) forcealign(16);
|
||||
typedef long long_v _Vector_size(16) forcealign(16);
|
||||
|
||||
static float_v Addps(struct Machine *m, float_v x, float_v y) {
|
||||
return x + y;
|
||||
}
|
||||
|
||||
static double_v Addpd(struct Machine *m, double_v x, double_v y) {
|
||||
return x + y;
|
||||
}
|
||||
|
||||
static float_v Mulps(struct Machine *m, float_v x, float_v y) {
|
||||
return x * y;
|
||||
}
|
||||
|
||||
static double_v Mulpd(struct Machine *m, double_v x, double_v y) {
|
||||
return x * y;
|
||||
}
|
||||
|
||||
static float_v Subps(struct Machine *m, float_v x, float_v y) {
|
||||
return x - y;
|
||||
}
|
||||
|
||||
static double_v Subpd(struct Machine *m, double_v x, double_v y) {
|
||||
return x - y;
|
||||
}
|
||||
|
||||
static float_v Divps(struct Machine *m, float_v x, float_v y) {
|
||||
return x / y;
|
||||
}
|
||||
|
||||
static double_v Divpd(struct Machine *m, double_v x, double_v y) {
|
||||
return x / y;
|
||||
}
|
||||
|
||||
static float_v Andps(struct Machine *m, float_v x, float_v y) {
|
||||
return (float_v)((int_v)x & (int_v)y);
|
||||
}
|
||||
|
||||
static double_v Andpd(struct Machine *m, double_v x, double_v y) {
|
||||
return (double_v)((long_v)x & (long_v)y);
|
||||
}
|
||||
|
||||
static float_v Andnps(struct Machine *m, float_v x, float_v y) {
|
||||
return (float_v)(~(int_v)x & (int_v)y);
|
||||
}
|
||||
|
||||
static double_v Andnpd(struct Machine *m, double_v x, double_v y) {
|
||||
return (double_v)(~(long_v)x & (long_v)y);
|
||||
}
|
||||
|
||||
static float_v Orps(struct Machine *m, float_v x, float_v y) {
|
||||
return (float_v)((int_v)x | (int_v)y);
|
||||
}
|
||||
|
||||
static double_v Orpd(struct Machine *m, double_v x, double_v y) {
|
||||
return (double_v)((long_v)x | (long_v)y);
|
||||
}
|
||||
|
||||
static float_v Xorps(struct Machine *m, float_v x, float_v y) {
|
||||
return (float_v)((int_v)x ^ (int_v)y);
|
||||
}
|
||||
|
||||
static double_v Xorpd(struct Machine *m, double_v x, double_v y) {
|
||||
return (double_v)((long_v)x ^ (long_v)y);
|
||||
}
|
||||
|
||||
static float_v Minps(struct Machine *m, float_v x, float_v y) {
|
||||
#if SSE_BUILTINS
|
||||
return __builtin_ia32_minps(x, y);
|
||||
#else
|
||||
unsigned i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
x[i] = MIN(x[i], y[i]);
|
||||
}
|
||||
return x;
|
||||
#endif
|
||||
}
|
||||
|
||||
static double_v Minpd(struct Machine *m, double_v x, double_v y) {
|
||||
#if SSE_BUILTINS
|
||||
return __builtin_ia32_minpd(x, y);
|
||||
#else
|
||||
unsigned i;
|
||||
for (i = 0; i < 2; ++i) {
|
||||
x[i] = MIN(x[i], y[i]);
|
||||
}
|
||||
return x;
|
||||
#endif
|
||||
}
|
||||
|
||||
static float_v Maxps(struct Machine *m, float_v x, float_v y) {
|
||||
#if SSE_BUILTINS
|
||||
return __builtin_ia32_maxps(x, y);
|
||||
#else
|
||||
unsigned i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
x[i] = MAX(x[i], y[i]);
|
||||
}
|
||||
return x;
|
||||
#endif
|
||||
}
|
||||
|
||||
static double_v Maxpd(struct Machine *m, double_v x, double_v y) {
|
||||
#if SSE_BUILTINS
|
||||
return __builtin_ia32_maxpd(x, y);
|
||||
#else
|
||||
unsigned i;
|
||||
for (i = 0; i < 2; ++i) {
|
||||
x[i] = MAX(x[i], y[i]);
|
||||
}
|
||||
return x;
|
||||
#endif
|
||||
}
|
||||
|
||||
static double_v Haddpd(struct Machine *m, double_v x, double_v y) {
|
||||
#if SSE_BUILTINS
|
||||
return __builtin_ia32_haddpd(x, y);
|
||||
#else
|
||||
return (double_v){x[0] + x[1], y[0] + y[1]};
|
||||
#endif
|
||||
}
|
||||
|
||||
static float_v Haddps(struct Machine *m, float_v x, float_v y) {
|
||||
#if SSE_BUILTINS
|
||||
return __builtin_ia32_haddps(x, y);
|
||||
#else
|
||||
return (float_v){x[0] + x[1], x[2] + x[3], y[0] + y[1], y[2] + y[3]};
|
||||
#endif
|
||||
}
|
||||
|
||||
static double_v Hsubpd(struct Machine *m, double_v x, double_v y) {
|
||||
#if SSE_BUILTINS
|
||||
return __builtin_ia32_hsubpd(x, y);
|
||||
#else
|
||||
return (double_v){x[0] - x[1], y[0] - y[1]};
|
||||
#endif
|
||||
}
|
||||
|
||||
static float_v Hsubps(struct Machine *m, float_v x, float_v y) {
|
||||
#if SSE_BUILTINS
|
||||
return __builtin_ia32_hsubps(x, y);
|
||||
#else
|
||||
return (float_v){x[0] - x[1], x[2] - x[3], y[0] - y[1], y[2] - y[3]};
|
||||
#endif
|
||||
}
|
||||
|
||||
static double_v Addsubpd(struct Machine *m, double_v x, double_v y) {
|
||||
#if SSE_BUILTINS
|
||||
return __builtin_ia32_addsubpd(x, y);
|
||||
#else
|
||||
return (double_v){x[0] - y[0], x[1] + y[1]};
|
||||
#endif
|
||||
}
|
||||
|
||||
static float_v Addsubps(struct Machine *m, float_v x, float_v y) {
|
||||
#if SSE_BUILTINS
|
||||
return __builtin_ia32_addsubps(x, y);
|
||||
#else
|
||||
return (float_v){x[0] - y[0], x[1] + y[1], x[2] - y[2], x[3] + y[3]};
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpUnpcklpsd(struct Machine *m, uint32_t rde) {
|
||||
uint8_t *a, *b;
|
||||
a = XmmRexrReg(m, rde);
|
||||
|
@ -294,28 +127,28 @@ void OpShufpsd(struct Machine *m, uint32_t rde) {
|
|||
|
||||
void OpSqrtpsd(struct Machine *m, uint32_t rde) {
|
||||
long i;
|
||||
float_v xf;
|
||||
double_v xd;
|
||||
float xf[4];
|
||||
double xd[2];
|
||||
switch (Rep(rde) | Osz(rde)) {
|
||||
case 0:
|
||||
memcpy(&xf, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
memcpy(xf, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
for (i = 0; i < 4; ++i) xf[i] = sqrtf(xf[i]);
|
||||
memcpy(XmmRexrReg(m, rde), &xf, 16);
|
||||
memcpy(XmmRexrReg(m, rde), xf, 16);
|
||||
break;
|
||||
case 1:
|
||||
memcpy(&xd, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
memcpy(xd, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
for (i = 0; i < 2; ++i) xd[i] = sqrt(xd[i]);
|
||||
memcpy(XmmRexrReg(m, rde), &xd, 16);
|
||||
memcpy(XmmRexrReg(m, rde), xd, 16);
|
||||
break;
|
||||
case 2:
|
||||
memcpy(&xd, GetModrmRegisterXmmPointerRead8(m, rde), 8);
|
||||
memcpy(xd, GetModrmRegisterXmmPointerRead8(m, rde), 8);
|
||||
xd[0] = sqrt(xd[0]);
|
||||
memcpy(XmmRexrReg(m, rde), &xd, 8);
|
||||
memcpy(XmmRexrReg(m, rde), xd, 8);
|
||||
break;
|
||||
case 3:
|
||||
memcpy(&xf, GetModrmRegisterXmmPointerRead4(m, rde), 4);
|
||||
memcpy(xf, GetModrmRegisterXmmPointerRead4(m, rde), 4);
|
||||
xf[0] = sqrtf(xf[0]);
|
||||
memcpy(XmmRexrReg(m, rde), &xf, 4);
|
||||
memcpy(XmmRexrReg(m, rde), xf, 4);
|
||||
break;
|
||||
default:
|
||||
unreachable;
|
||||
|
@ -323,91 +156,30 @@ void OpSqrtpsd(struct Machine *m, uint32_t rde) {
|
|||
}
|
||||
|
||||
void OpRsqrtps(struct Machine *m, uint32_t rde) {
|
||||
float_v x;
|
||||
float x[4];
|
||||
unsigned i;
|
||||
if (Rep(rde) != 3) {
|
||||
memcpy(&x, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
memcpy(x, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
for (i = 0; i < 4; ++i) x[i] = 1.f / sqrtf(x[i]);
|
||||
memcpy(XmmRexrReg(m, rde), &x, 16);
|
||||
memcpy(XmmRexrReg(m, rde), x, 16);
|
||||
} else {
|
||||
memcpy(&x, GetModrmRegisterXmmPointerRead4(m, rde), 4);
|
||||
memcpy(x, GetModrmRegisterXmmPointerRead4(m, rde), 4);
|
||||
x[0] = 1.f / sqrtf(x[0]);
|
||||
memcpy(XmmRexrReg(m, rde), &x, 4);
|
||||
memcpy(XmmRexrReg(m, rde), x, 4);
|
||||
}
|
||||
}
|
||||
|
||||
void OpRcpps(struct Machine *m, uint32_t rde) {
|
||||
float_v x;
|
||||
float x[4];
|
||||
unsigned i;
|
||||
if (Rep(rde) != 3) {
|
||||
memcpy(&x, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
memcpy(x, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
for (i = 0; i < 4; ++i) x[i] = 1.f / x[i];
|
||||
memcpy(XmmRexrReg(m, rde), &x, 16);
|
||||
memcpy(XmmRexrReg(m, rde), x, 16);
|
||||
} else {
|
||||
memcpy(&x, GetModrmRegisterXmmPointerRead4(m, rde), 4);
|
||||
memcpy(x, GetModrmRegisterXmmPointerRead4(m, rde), 4);
|
||||
x[0] = 1.f / x[0];
|
||||
memcpy(XmmRexrReg(m, rde), &x, 4);
|
||||
}
|
||||
}
|
||||
|
||||
static void VpsdWpsd(struct Machine *m, uint32_t rde,
|
||||
float_v opf(struct Machine *, float_v, float_v),
|
||||
double_v opd(struct Machine *, double_v, double_v),
|
||||
bool isfloat, bool isdouble) {
|
||||
float_v xf, yf;
|
||||
double_v xd, yd;
|
||||
if (isfloat) {
|
||||
memcpy(&xf, XmmRexrReg(m, rde), 16);
|
||||
memcpy(&yf, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
xf = opf(m, xf, yf);
|
||||
memcpy(XmmRexrReg(m, rde), &xf, 16);
|
||||
} else if (isdouble) {
|
||||
memcpy(&xd, XmmRexrReg(m, rde), 16);
|
||||
memcpy(&yd, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
xd = opd(m, xd, yd);
|
||||
memcpy(XmmRexrReg(m, rde), &xd, 16);
|
||||
} else {
|
||||
OpUd(m, rde);
|
||||
}
|
||||
}
|
||||
|
||||
static void VpsdWpsd66(struct Machine *m, uint32_t rde,
|
||||
float_v opf(struct Machine *, float_v, float_v),
|
||||
double_v opd(struct Machine *, double_v, double_v)) {
|
||||
VpsdWpsd(m, rde, opf, opd, !Osz(rde), Osz(rde));
|
||||
}
|
||||
|
||||
static void VpsdWpsd66f2(struct Machine *m, uint32_t rde,
|
||||
float_v opf(struct Machine *, float_v, float_v),
|
||||
double_v opd(struct Machine *, double_v, double_v)) {
|
||||
VpsdWpsd(m, rde, opf, opd, Rep(rde) == 2, Osz(rde));
|
||||
}
|
||||
|
||||
static void VspsdWspsd(struct Machine *m, uint32_t rde,
|
||||
float_v opf(struct Machine *, float_v, float_v),
|
||||
double_v opd(struct Machine *, double_v, double_v)) {
|
||||
float_v xf, yf;
|
||||
double_v xd, yd;
|
||||
if (Rep(rde) == 2) {
|
||||
memcpy(&yd, GetModrmRegisterXmmPointerRead8(m, rde), 8);
|
||||
memcpy(&xd, XmmRexrReg(m, rde), 8);
|
||||
xd = opd(m, xd, yd);
|
||||
memcpy(XmmRexrReg(m, rde), &xd, 8);
|
||||
} else if (Rep(rde) == 3) {
|
||||
memcpy(&yf, GetModrmRegisterXmmPointerRead4(m, rde), 4);
|
||||
memcpy(&xf, XmmRexrReg(m, rde), 4);
|
||||
xf = opf(m, xf, yf);
|
||||
memcpy(XmmRexrReg(m, rde), &xf, 4);
|
||||
} else if (Osz(rde)) {
|
||||
memcpy(&yd, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
memcpy(&xd, XmmRexrReg(m, rde), 16);
|
||||
xd = opd(m, xd, yd);
|
||||
memcpy(XmmRexrReg(m, rde), &xd, 16);
|
||||
} else {
|
||||
memcpy(&yf, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
memcpy(&xf, XmmRexrReg(m, rde), 16);
|
||||
xf = opf(m, xf, yf);
|
||||
memcpy(XmmRexrReg(m, rde), &xf, 16);
|
||||
memcpy(XmmRexrReg(m, rde), x, 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -448,118 +220,376 @@ void OpComissVsWs(struct Machine *m, uint32_t rde) {
|
|||
}
|
||||
}
|
||||
|
||||
static float_v Cmpps(struct Machine *m, float_v x, float_v y) {
|
||||
long i;
|
||||
switch (m->xedd->op.uimm0) {
|
||||
static int Cmps(int imm, float x, float y) {
|
||||
switch (imm) {
|
||||
case 0:
|
||||
return x == y;
|
||||
return x == y ? -1 : 0;
|
||||
case 1:
|
||||
return x < y;
|
||||
return x < y ? -1 : 0;
|
||||
case 2:
|
||||
return x <= y;
|
||||
return x <= y ? -1 : 0;
|
||||
case 3:
|
||||
for (i = 0; i < 4; ++i) {
|
||||
x[i] = isnan(x[i]) || isnan(y[i]);
|
||||
}
|
||||
return x;
|
||||
return isnan(x) || isnan(y) ? -1 : 0;
|
||||
case 4:
|
||||
return x != y;
|
||||
return x != y ? -1 : 0;
|
||||
case 5:
|
||||
return x >= y;
|
||||
return x >= y ? -1 : 0;
|
||||
case 6:
|
||||
return x > y;
|
||||
return x > y ? -1 : 0;
|
||||
case 7:
|
||||
for (i = 0; i < 4; ++i) {
|
||||
x[i] = !(isnan(x[i]) || isnan(y[i]));
|
||||
}
|
||||
return x;
|
||||
return !(isnan(x) || isnan(y)) ? -1 : 0;
|
||||
default:
|
||||
OpUd(m, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static double_v Cmppd(struct Machine *m, double_v x, double_v y) {
|
||||
static int32_t Cmpd(int imm, double x, double y) {
|
||||
long i;
|
||||
switch (m->xedd->op.uimm0) {
|
||||
switch (imm) {
|
||||
case 0:
|
||||
return x == y;
|
||||
return x == y ? -1 : 0;
|
||||
case 1:
|
||||
return x < y;
|
||||
return x < y ? -1 : 0;
|
||||
case 2:
|
||||
return x <= y;
|
||||
return x <= y ? -1 : 0;
|
||||
case 3:
|
||||
for (i = 0; i < 2; ++i) {
|
||||
x[i] = isnan(x[i]) || isnan(y[i]);
|
||||
}
|
||||
return x;
|
||||
return isnan(x) || isnan(y) ? -1 : 0;
|
||||
case 4:
|
||||
return x != y;
|
||||
return x != y ? -1 : 0;
|
||||
case 5:
|
||||
return x >= y;
|
||||
return x >= y ? -1 : 0;
|
||||
case 6:
|
||||
return x > y;
|
||||
return x > y ? -1 : 0;
|
||||
case 7:
|
||||
for (i = 0; i < 2; ++i) {
|
||||
x[i] = !(isnan(x[i]) || isnan(y[i]));
|
||||
}
|
||||
return x;
|
||||
return !(isnan(x) || isnan(y)) ? -1 : 0;
|
||||
default:
|
||||
OpUd(m, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void OpAddpsd(struct Machine *m, uint32_t rde) {
|
||||
VspsdWspsd(m, rde, Addps, Addpd);
|
||||
if (Rep(rde) == 2) {
|
||||
double x, y;
|
||||
memcpy(&y, GetModrmRegisterXmmPointerRead8(m, rde), 8);
|
||||
memcpy(&x, XmmRexrReg(m, rde), 8);
|
||||
x += y;
|
||||
memcpy(XmmRexrReg(m, rde), &x, 8);
|
||||
} else if (Rep(rde) == 3) {
|
||||
float x, y;
|
||||
memcpy(&y, GetModrmRegisterXmmPointerRead4(m, rde), 4);
|
||||
memcpy(&x, XmmRexrReg(m, rde), 4);
|
||||
x += y;
|
||||
memcpy(XmmRexrReg(m, rde), &x, 4);
|
||||
} else if (Osz(rde)) {
|
||||
double x[2], y[2];
|
||||
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
memcpy(x, XmmRexrReg(m, rde), 16);
|
||||
x[0] += y[0];
|
||||
x[1] += y[1];
|
||||
memcpy(XmmRexrReg(m, rde), x, 16);
|
||||
} else {
|
||||
float x[4], y[4];
|
||||
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
memcpy(x, XmmRexrReg(m, rde), 16);
|
||||
x[0] += y[0];
|
||||
x[1] += y[1];
|
||||
x[2] += y[2];
|
||||
x[3] += y[3];
|
||||
memcpy(XmmRexrReg(m, rde), x, 16);
|
||||
}
|
||||
}
|
||||
|
||||
void OpMulpsd(struct Machine *m, uint32_t rde) {
|
||||
VspsdWspsd(m, rde, Mulps, Mulpd);
|
||||
if (Rep(rde) == 2) {
|
||||
double x, y;
|
||||
memcpy(&y, GetModrmRegisterXmmPointerRead8(m, rde), 8);
|
||||
memcpy(&x, XmmRexrReg(m, rde), 8);
|
||||
x *= y;
|
||||
memcpy(XmmRexrReg(m, rde), &x, 8);
|
||||
} else if (Rep(rde) == 3) {
|
||||
float x, y;
|
||||
memcpy(&y, GetModrmRegisterXmmPointerRead4(m, rde), 4);
|
||||
memcpy(&x, XmmRexrReg(m, rde), 4);
|
||||
x *= y;
|
||||
memcpy(XmmRexrReg(m, rde), &x, 4);
|
||||
} else if (Osz(rde)) {
|
||||
double x[2], y[2];
|
||||
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
memcpy(x, XmmRexrReg(m, rde), 16);
|
||||
x[0] *= y[0];
|
||||
x[1] *= y[1];
|
||||
memcpy(XmmRexrReg(m, rde), x, 16);
|
||||
} else {
|
||||
float x[4], y[4];
|
||||
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
memcpy(x, XmmRexrReg(m, rde), 16);
|
||||
x[0] *= y[0];
|
||||
x[1] *= y[1];
|
||||
x[2] *= y[2];
|
||||
x[3] *= y[3];
|
||||
memcpy(XmmRexrReg(m, rde), x, 16);
|
||||
}
|
||||
}
|
||||
|
||||
void OpSubpsd(struct Machine *m, uint32_t rde) {
|
||||
VspsdWspsd(m, rde, Subps, Subpd);
|
||||
if (Rep(rde) == 2) {
|
||||
double x, y;
|
||||
memcpy(&y, GetModrmRegisterXmmPointerRead8(m, rde), 8);
|
||||
memcpy(&x, XmmRexrReg(m, rde), 8);
|
||||
x -= y;
|
||||
memcpy(XmmRexrReg(m, rde), &x, 8);
|
||||
} else if (Rep(rde) == 3) {
|
||||
float x, y;
|
||||
memcpy(&y, GetModrmRegisterXmmPointerRead4(m, rde), 4);
|
||||
memcpy(&x, XmmRexrReg(m, rde), 4);
|
||||
x -= y;
|
||||
memcpy(XmmRexrReg(m, rde), &x, 4);
|
||||
} else if (Osz(rde)) {
|
||||
double x[2], y[2];
|
||||
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
memcpy(x, XmmRexrReg(m, rde), 16);
|
||||
x[0] -= y[0];
|
||||
x[1] -= y[1];
|
||||
memcpy(XmmRexrReg(m, rde), x, 16);
|
||||
} else {
|
||||
float x[4], y[4];
|
||||
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
memcpy(x, XmmRexrReg(m, rde), 16);
|
||||
x[0] -= y[0];
|
||||
x[1] -= y[1];
|
||||
x[2] -= y[2];
|
||||
x[3] -= y[3];
|
||||
memcpy(XmmRexrReg(m, rde), x, 16);
|
||||
}
|
||||
}
|
||||
|
||||
void OpDivpsd(struct Machine *m, uint32_t rde) {
|
||||
VspsdWspsd(m, rde, Divps, Divpd);
|
||||
if (Rep(rde) == 2) {
|
||||
double x, y;
|
||||
memcpy(&y, GetModrmRegisterXmmPointerRead8(m, rde), 8);
|
||||
memcpy(&x, XmmRexrReg(m, rde), 8);
|
||||
x /= y;
|
||||
memcpy(XmmRexrReg(m, rde), &x, 8);
|
||||
} else if (Rep(rde) == 3) {
|
||||
float x, y;
|
||||
memcpy(&y, GetModrmRegisterXmmPointerRead4(m, rde), 4);
|
||||
memcpy(&x, XmmRexrReg(m, rde), 4);
|
||||
x /= y;
|
||||
memcpy(XmmRexrReg(m, rde), &x, 4);
|
||||
} else if (Osz(rde)) {
|
||||
double x[2], y[2];
|
||||
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
memcpy(x, XmmRexrReg(m, rde), 16);
|
||||
x[0] /= y[0];
|
||||
x[1] /= y[1];
|
||||
memcpy(XmmRexrReg(m, rde), x, 16);
|
||||
} else {
|
||||
float x[4], y[4];
|
||||
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
memcpy(x, XmmRexrReg(m, rde), 16);
|
||||
x[0] /= y[0];
|
||||
x[1] /= y[1];
|
||||
x[2] /= y[2];
|
||||
x[3] /= y[3];
|
||||
memcpy(XmmRexrReg(m, rde), x, 16);
|
||||
}
|
||||
}
|
||||
|
||||
void OpMinpsd(struct Machine *m, uint32_t rde) {
|
||||
VspsdWspsd(m, rde, Minps, Minpd);
|
||||
if (Rep(rde) == 2) {
|
||||
double x, y;
|
||||
memcpy(&y, GetModrmRegisterXmmPointerRead8(m, rde), 8);
|
||||
memcpy(&x, XmmRexrReg(m, rde), 8);
|
||||
x = MIN(x, y);
|
||||
memcpy(XmmRexrReg(m, rde), &x, 8);
|
||||
} else if (Rep(rde) == 3) {
|
||||
float x, y;
|
||||
memcpy(&y, GetModrmRegisterXmmPointerRead4(m, rde), 4);
|
||||
memcpy(&x, XmmRexrReg(m, rde), 4);
|
||||
x = MIN(x, y);
|
||||
memcpy(XmmRexrReg(m, rde), &x, 4);
|
||||
} else if (Osz(rde)) {
|
||||
double x[2], y[2];
|
||||
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
memcpy(x, XmmRexrReg(m, rde), 16);
|
||||
x[0] = MIN(x[0], y[0]);
|
||||
x[1] = MIN(x[1], y[1]);
|
||||
memcpy(XmmRexrReg(m, rde), x, 16);
|
||||
} else {
|
||||
float x[4], y[4];
|
||||
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
memcpy(x, XmmRexrReg(m, rde), 16);
|
||||
x[0] = MIN(x[0], y[0]);
|
||||
x[1] = MIN(x[1], y[1]);
|
||||
x[2] = MIN(x[2], y[2]);
|
||||
x[3] = MIN(x[3], y[3]);
|
||||
memcpy(XmmRexrReg(m, rde), x, 16);
|
||||
}
|
||||
}
|
||||
|
||||
void OpMaxpsd(struct Machine *m, uint32_t rde) {
|
||||
VspsdWspsd(m, rde, Maxps, Maxpd);
|
||||
if (Rep(rde) == 2) {
|
||||
double x, y;
|
||||
memcpy(&y, GetModrmRegisterXmmPointerRead8(m, rde), 8);
|
||||
memcpy(&x, XmmRexrReg(m, rde), 8);
|
||||
x = MAX(x, y);
|
||||
memcpy(XmmRexrReg(m, rde), &x, 8);
|
||||
} else if (Rep(rde) == 3) {
|
||||
float x, y;
|
||||
memcpy(&y, GetModrmRegisterXmmPointerRead4(m, rde), 4);
|
||||
memcpy(&x, XmmRexrReg(m, rde), 4);
|
||||
x = MAX(x, y);
|
||||
memcpy(XmmRexrReg(m, rde), &x, 4);
|
||||
} else if (Osz(rde)) {
|
||||
double x[2], y[2];
|
||||
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
memcpy(x, XmmRexrReg(m, rde), 16);
|
||||
x[0] = MAX(x[0], y[0]);
|
||||
x[1] = MAX(x[1], y[1]);
|
||||
memcpy(XmmRexrReg(m, rde), x, 16);
|
||||
} else {
|
||||
float x[4], y[4];
|
||||
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
memcpy(x, XmmRexrReg(m, rde), 16);
|
||||
x[0] = MAX(x[0], y[0]);
|
||||
x[1] = MAX(x[1], y[1]);
|
||||
x[2] = MAX(x[2], y[2]);
|
||||
x[3] = MAX(x[3], y[3]);
|
||||
memcpy(XmmRexrReg(m, rde), x, 16);
|
||||
}
|
||||
}
|
||||
|
||||
void OpCmppsd(struct Machine *m, uint32_t rde) {
|
||||
VspsdWspsd(m, rde, Cmpps, Cmppd);
|
||||
int imm = m->xedd->op.uimm0;
|
||||
if (Rep(rde) == 2) {
|
||||
double x, y;
|
||||
memcpy(&y, GetModrmRegisterXmmPointerRead8(m, rde), 8);
|
||||
memcpy(&x, XmmRexrReg(m, rde), 8);
|
||||
x = Cmpd(imm, x, y);
|
||||
memcpy(XmmRexrReg(m, rde), &x, 8);
|
||||
} else if (Rep(rde) == 3) {
|
||||
float x, y;
|
||||
memcpy(&y, GetModrmRegisterXmmPointerRead4(m, rde), 4);
|
||||
memcpy(&x, XmmRexrReg(m, rde), 4);
|
||||
x = Cmps(imm, x, y);
|
||||
memcpy(XmmRexrReg(m, rde), &x, 4);
|
||||
} else if (Osz(rde)) {
|
||||
double x[2], y[2];
|
||||
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
memcpy(x, XmmRexrReg(m, rde), 16);
|
||||
x[0] = Cmpd(imm, x[0], y[0]);
|
||||
x[1] = Cmpd(imm, x[1], y[1]);
|
||||
memcpy(XmmRexrReg(m, rde), x, 16);
|
||||
} else {
|
||||
float x[4], y[4];
|
||||
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
memcpy(x, XmmRexrReg(m, rde), 16);
|
||||
x[0] = Cmps(imm, x[0], y[0]);
|
||||
x[1] = Cmps(imm, x[1], y[1]);
|
||||
x[2] = Cmps(imm, x[2], y[2]);
|
||||
x[3] = Cmps(imm, x[3], y[3]);
|
||||
memcpy(XmmRexrReg(m, rde), x, 16);
|
||||
}
|
||||
}
|
||||
|
||||
void OpAndpsd(struct Machine *m, uint32_t rde) {
|
||||
VpsdWpsd66(m, rde, Andps, Andpd);
|
||||
uint64_t x[2], y[2];
|
||||
memcpy(x, XmmRexrReg(m, rde), 16);
|
||||
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
x[0] &= y[0];
|
||||
x[1] &= y[1];
|
||||
memcpy(XmmRexrReg(m, rde), x, 16);
|
||||
}
|
||||
|
||||
void OpAndnpsd(struct Machine *m, uint32_t rde) {
|
||||
VpsdWpsd66(m, rde, Andnps, Andnpd);
|
||||
uint64_t x[2], y[2];
|
||||
memcpy(x, XmmRexrReg(m, rde), 16);
|
||||
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
x[0] = ~x[0] & y[0];
|
||||
x[1] = ~x[1] & y[1];
|
||||
memcpy(XmmRexrReg(m, rde), x, 16);
|
||||
}
|
||||
|
||||
void OpOrpsd(struct Machine *m, uint32_t rde) {
|
||||
VpsdWpsd66(m, rde, Orps, Orpd);
|
||||
uint64_t x[2], y[2];
|
||||
memcpy(x, XmmRexrReg(m, rde), 16);
|
||||
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
x[0] |= y[0];
|
||||
x[1] |= y[1];
|
||||
memcpy(XmmRexrReg(m, rde), x, 16);
|
||||
}
|
||||
|
||||
void OpXorpsd(struct Machine *m, uint32_t rde) {
|
||||
VpsdWpsd66(m, rde, Xorps, Xorpd);
|
||||
uint64_t x[2], y[2];
|
||||
memcpy(x, XmmRexrReg(m, rde), 16);
|
||||
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
x[0] ^= y[0];
|
||||
x[1] ^= y[1];
|
||||
memcpy(XmmRexrReg(m, rde), x, 16);
|
||||
}
|
||||
|
||||
void OpHaddpsd(struct Machine *m, uint32_t rde) {
|
||||
VpsdWpsd66f2(m, rde, Haddps, Haddpd);
|
||||
if (Rep(rde) == 2) {
|
||||
float x[4], y[4], z[4];
|
||||
memcpy(x, XmmRexrReg(m, rde), 16);
|
||||
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
z[0] = x[0] + x[1];
|
||||
z[1] = x[2] + x[3];
|
||||
z[2] = y[0] + y[1];
|
||||
z[3] = y[2] + y[3];
|
||||
memcpy(XmmRexrReg(m, rde), x, 16);
|
||||
} else if (Osz(rde)) {
|
||||
double x[2], y[2], z[2];
|
||||
memcpy(x, XmmRexrReg(m, rde), 16);
|
||||
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
z[0] = x[0] + x[1];
|
||||
z[1] = y[0] + y[1];
|
||||
memcpy(XmmRexrReg(m, rde), z, 16);
|
||||
} else {
|
||||
OpUd(m, rde);
|
||||
}
|
||||
}
|
||||
|
||||
void OpHsubpsd(struct Machine *m, uint32_t rde) {
|
||||
VpsdWpsd66f2(m, rde, Hsubps, Hsubpd);
|
||||
if (Rep(rde) == 2) {
|
||||
float x[4], y[4], z[4];
|
||||
memcpy(x, XmmRexrReg(m, rde), 16);
|
||||
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
z[0] = x[0] - x[1];
|
||||
z[1] = x[2] - x[3];
|
||||
z[2] = y[0] - y[1];
|
||||
z[3] = y[2] - y[3];
|
||||
memcpy(XmmRexrReg(m, rde), x, 16);
|
||||
} else if (Osz(rde)) {
|
||||
double x[2], y[2], z[2];
|
||||
memcpy(x, XmmRexrReg(m, rde), 16);
|
||||
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
z[0] = x[0] - x[1];
|
||||
z[1] = y[0] - y[1];
|
||||
memcpy(XmmRexrReg(m, rde), z, 16);
|
||||
} else {
|
||||
OpUd(m, rde);
|
||||
}
|
||||
}
|
||||
|
||||
void OpAddsubpsd(struct Machine *m, uint32_t rde) {
|
||||
VpsdWpsd66f2(m, rde, Addsubps, Addsubpd);
|
||||
if (Rep(rde) == 2) {
|
||||
float x[4], y[4], z[4];
|
||||
memcpy(x, XmmRexrReg(m, rde), 16);
|
||||
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
z[0] = x[0] - y[0];
|
||||
z[1] = x[1] + y[1];
|
||||
z[2] = x[2] - y[2];
|
||||
z[3] = x[3] + y[3];
|
||||
memcpy(XmmRexrReg(m, rde), x, 16);
|
||||
} else if (Osz(rde)) {
|
||||
double x[2], y[2], z[2];
|
||||
memcpy(x, XmmRexrReg(m, rde), 16);
|
||||
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
z[0] = x[0] - y[0];
|
||||
z[1] = x[1] + y[1];
|
||||
memcpy(XmmRexrReg(m, rde), z, 16);
|
||||
} else {
|
||||
OpUd(m, rde);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -442,7 +442,7 @@ static int AppendIovsReal(struct Machine *m, struct Iovs *ib, int64_t addr,
|
|||
static int AppendIovsGuest(struct Machine *m, struct Iovs *iv, int64_t iovaddr,
|
||||
long iovlen) {
|
||||
int rc;
|
||||
long i, iovsize;
|
||||
size_t i, iovsize;
|
||||
struct iovec *guestiovs;
|
||||
if (!__builtin_mul_overflow(iovlen, sizeof(struct iovec), &iovsize) &&
|
||||
(0 <= iovsize && iovsize <= 0x7ffff000)) {
|
||||
|
|
|
@ -69,6 +69,9 @@
|
|||
"__builtin_va_end"
|
||||
"__builtin_abs"
|
||||
"__builtin_strcpy"
|
||||
"__builtin_strstr"
|
||||
"__builtin_strpbrk"
|
||||
"__builtin_strchr"
|
||||
"__builtin_stpcpy"
|
||||
"__builtin_setjmp"
|
||||
"__builtin_longjmp"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
(defconst cosmo-c-keywords-regex
|
||||
(let (
|
||||
|
||||
|
||||
;; (kar
|
||||
;; '("case"
|
||||
;; "do"
|
||||
|
@ -237,6 +237,7 @@
|
|||
"__aligned__"
|
||||
"__alloc_align__"
|
||||
"__alloc_size__"
|
||||
"__warn_if_not_aligned__"
|
||||
"__artificial__"
|
||||
"__assume_aligned__"
|
||||
"__cold__"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue