Remove blinkenlights

New home: https://github.com/jart/blink
This commit is contained in:
Justine Tunney 2023-06-11 03:10:58 -07:00
parent 50d8d953ce
commit 06b749ae03
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
130 changed files with 2 additions and 26665 deletions

View file

@ -1,9 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_ABP_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_ABP_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
#define Abp8(x) ((uint8_t *)__builtin_assume_aligned(x, 8))
#define Abp16(x) ((uint8_t *)__builtin_assume_aligned(x, 16))
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_ABP_H_ */

View file

@ -1,88 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "tool/build/lib/address.h"
#include "third_party/xed/x86.h"
#include "tool/build/lib/endian.h"
#include "tool/build/lib/modrm.h"
#include "tool/build/lib/throw.h"
uint64_t AddressOb(struct Machine *m, uint32_t rde) {
return AddSegment(m, rde, m->xedd->op.disp, m->ds);
}
uint8_t *GetSegment(struct Machine *m, uint32_t rde, int s) {
switch (s & 7) {
case 0:
return m->es;
case 1:
return m->cs;
case 2:
return m->ss;
case 3:
return m->ds;
case 4:
return m->fs;
case 5:
return m->gs;
case 6:
case 7:
OpUd(m, rde);
default:
__builtin_unreachable();
}
}
uint64_t AddSegment(struct Machine *m, uint32_t rde, uint64_t i, uint8_t s[8]) {
if (!Sego(rde)) {
return i + Read64(s);
} else {
return i + Read64(GetSegment(m, rde, Sego(rde) - 1));
}
}
uint64_t DataSegment(struct Machine *m, uint32_t rde, uint64_t i) {
return AddSegment(m, rde, i, m->ds);
}
uint64_t AddressSi(struct Machine *m, uint32_t rde) {
switch (Eamode(rde)) {
case XED_MODE_LONG:
return DataSegment(m, rde, Read64(m->si));
case XED_MODE_REAL:
return DataSegment(m, rde, Read16(m->si));
case XED_MODE_LEGACY:
return DataSegment(m, rde, Read32(m->si));
default:
__builtin_unreachable();
}
}
uint64_t AddressDi(struct Machine *m, uint32_t rde) {
uint64_t i = Read64(m->es);
switch (Eamode(rde)) {
case XED_MODE_LONG:
return i + Read64(m->di);
case XED_MODE_REAL:
return i + Read16(m->di);
case XED_MODE_LEGACY:
return i + Read32(m->di);
default:
__builtin_unreachable();
}
}

View file

@ -1,29 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_ADDRESS_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_ADDRESS_H_
#include "libc/assert.h"
#include "third_party/xed/x86.h"
#include "tool/build/lib/machine.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
uint64_t AddressOb(struct Machine *, uint32_t);
uint64_t AddressDi(struct Machine *, uint32_t);
uint64_t AddressSi(struct Machine *, uint32_t);
uint64_t DataSegment(struct Machine *, uint32_t, uint64_t);
uint64_t AddSegment(struct Machine *, uint32_t, uint64_t, uint8_t[8]);
uint8_t *GetSegment(struct Machine *, uint32_t, int) nosideeffect;
forceinline uint64_t MaskAddress(uint32_t mode, uint64_t x) {
if (mode != XED_MODE_LONG) {
if (mode == XED_MODE_REAL) {
x &= 0xffff;
} else {
x &= 0xffffffff;
}
}
return x;
}
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_ADDRESS_H_ */

View file

@ -1,763 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "tool/build/lib/alu.h"
#include "tool/build/lib/flags.h"
const aluop_f kAlu[12][4] = {
{Add8, Add16, Add32, Add64}, {Or8, Or16, Or32, Or64},
{Adc8, Adc16, Adc32, Adc64}, {Sbb8, Sbb16, Sbb32, Sbb64},
{And8, And16, And32, And64}, {Sub8, Sub16, Sub32, Sub64},
{Xor8, Xor16, Xor32, Xor64}, {Sub8, Sub16, Sub32, Sub64},
{Not8, Not16, Not32, Not64}, {Neg8, Neg16, Neg32, Neg64},
{Inc8, Inc16, Inc32, Inc64}, {Dec8, Dec16, Dec32, Dec64},
};
const aluop_f kBsu[8][4] = {
{Rol8, Rol16, Rol32, Rol64}, {Ror8, Ror16, Ror32, Ror64},
{Rcl8, Rcl16, Rcl32, Rcl64}, {Rcr8, Rcr16, Rcr32, Rcr64},
{Shl8, Shl16, Shl32, Shl64}, {Shr8, Shr16, Shr32, Shr64},
{Shl8, Shl16, Shl32, Shl64}, {Sar8, Sar16, Sar32, Sar64},
};
int64_t AluFlags8(uint8_t z, uint32_t af, uint32_t *f, uint32_t of,
uint32_t cf) {
return AluFlags(z, af, f, of, cf, z >> 7);
}
int64_t AluFlags32(uint32_t z, uint32_t af, uint32_t *f, uint32_t of,
uint32_t cf) {
return AluFlags(z, af, f, of, cf, z >> 31);
}
int64_t Xor32(uint64_t x, uint64_t y, uint32_t *f) {
return AluFlags32(x ^ y, 0, f, 0, 0);
}
int64_t Sub32(uint64_t x64, uint64_t y64, uint32_t *f) {
bool cf, of, af;
uint32_t x, y, z;
x = x64;
y = y64;
z = x - y;
cf = x < z;
af = (x & 15) < (z & 15);
of = ((z ^ x) & (x ^ y)) >> 31;
return AluFlags32(z, af, f, of, cf);
}
int64_t AluFlags64(uint64_t z, uint32_t af, uint32_t *f, uint32_t of,
uint32_t cf) {
return AluFlags(z, af, f, of, cf, z >> 63);
}
int64_t Sub64(uint64_t x, uint64_t y, uint32_t *f) {
uint64_t z;
bool cf, of, af;
z = x - y;
cf = x < z;
af = (x & 15) < (z & 15);
of = ((z ^ x) & (x ^ y)) >> 63;
return AluFlags64(z, af, f, of, cf);
}
int64_t Xor8(uint64_t x, uint64_t y, uint32_t *f) {
return AluFlags8(x ^ y, 0, f, 0, 0);
}
int64_t Xor64(uint64_t x, uint64_t y, uint32_t *f) {
return AluFlags64(x ^ y, 0, f, 0, 0);
}
int64_t Or8(uint64_t x, uint64_t y, uint32_t *f) {
return AluFlags8(x | y, 0, f, 0, 0);
}
int64_t Or32(uint64_t x, uint64_t y, uint32_t *f) {
return AluFlags32(x | y, 0, f, 0, 0);
}
int64_t Or64(uint64_t x, uint64_t y, uint32_t *f) {
return AluFlags64(x | y, 0, f, 0, 0);
}
int64_t And8(uint64_t x, uint64_t y, uint32_t *f) {
return AluFlags8(x & y, 0, f, 0, 0);
}
int64_t And32(uint64_t x, uint64_t y, uint32_t *f) {
return AluFlags32(x & y, 0, f, 0, 0);
}
int64_t And64(uint64_t x, uint64_t y, uint32_t *f) {
return AluFlags64(x & y, 0, f, 0, 0);
}
int64_t Sub8(uint64_t x64, uint64_t y64, uint32_t *f) {
bool cf, of, af;
uint8_t x, y, z;
x = x64;
y = y64;
z = x - y;
cf = x < z;
af = (x & 15) < (z & 15);
of = ((z ^ x) & (x ^ y)) >> 7;
return AluFlags8(z, af, f, of, cf);
}
int64_t Add8(uint64_t x64, uint64_t y64, uint32_t *f) {
bool cf, of, af;
uint8_t x, y, z;
x = x64;
y = y64;
z = x + y;
cf = z < y;
af = (z & 15) < (y & 15);
of = ((z ^ x) & (z ^ y)) >> 7;
return AluFlags8(z, af, f, of, cf);
}
int64_t Add32(uint64_t x64, uint64_t y64, uint32_t *f) {
bool cf, of, af;
uint32_t x, y, z;
x = x64;
y = y64;
z = x + y;
cf = z < y;
af = (z & 15) < (y & 15);
of = ((z ^ x) & (z ^ y)) >> 31;
return AluFlags32(z, af, f, of, cf);
}
int64_t Add64(uint64_t x, uint64_t y, uint32_t *f) {
uint64_t z;
bool cf, of, af;
z = x + y;
cf = z < y;
af = (z & 15) < (y & 15);
of = ((z ^ x) & (z ^ y)) >> 63;
return AluFlags64(z, af, f, of, cf);
}
int64_t Adc8(uint64_t x64, uint64_t y64, uint32_t *f) {
bool cf, of, af;
uint8_t x, y, z, t;
x = x64;
y = y64;
t = x + GetFlag(*f, FLAGS_CF);
z = t + y;
cf = (t < x) | (z < y);
of = ((z ^ x) & (z ^ y)) >> 7;
af = ((t & 15) < (x & 15)) | ((z & 15) < (y & 15));
return AluFlags8(z, af, f, of, cf);
}
int64_t Adc32(uint64_t x64, uint64_t y64, uint32_t *f) {
bool cf, of, af;
uint32_t x, y, z, t;
x = x64;
y = y64;
t = x + GetFlag(*f, FLAGS_CF);
z = t + y;
cf = (t < x) | (z < y);
of = ((z ^ x) & (z ^ y)) >> 31;
af = ((t & 15) < (x & 15)) | ((z & 15) < (y & 15));
return AluFlags32(z, af, f, of, cf);
}
int64_t Adc64(uint64_t x, uint64_t y, uint32_t *f) {
uint64_t z, t;
bool cf, of, af;
t = x + GetFlag(*f, FLAGS_CF);
z = t + y;
cf = (t < x) | (z < y);
of = ((z ^ x) & (z ^ y)) >> 63;
af = ((t & 15) < (x & 15)) | ((z & 15) < (y & 15));
return AluFlags64(z, af, f, of, cf);
}
int64_t Sbb8(uint64_t x64, uint64_t y64, uint32_t *f) {
bool cf, of, af;
uint8_t x, y, z, t;
x = x64;
y = y64;
t = x - GetFlag(*f, FLAGS_CF);
z = t - y;
cf = (x < t) | (t < z);
of = ((z ^ x) & (x ^ y)) >> 7;
af = ((x & 15) < (t & 15)) | ((t & 15) < (z & 15));
return AluFlags8(z, af, f, of, cf);
}
int64_t Sbb32(uint64_t x64, uint64_t y64, uint32_t *f) {
bool cf, of, af;
uint32_t x, y, z, t;
x = x64;
y = y64;
t = x - GetFlag(*f, FLAGS_CF);
z = t - y;
cf = (x < t) | (t < z);
of = ((z ^ x) & (x ^ y)) >> 31;
af = ((x & 15) < (t & 15)) | ((t & 15) < (z & 15));
return AluFlags32(z, af, f, of, cf);
}
int64_t Sbb64(uint64_t x, uint64_t y, uint32_t *f) {
uint64_t z, t;
bool cf, of, af;
t = x - GetFlag(*f, FLAGS_CF);
z = t - y;
cf = (x < t) | (t < z);
of = ((z ^ x) & (x ^ y)) >> 63;
af = ((x & 15) < (t & 15)) | ((t & 15) < (z & 15));
return AluFlags64(z, af, f, of, cf);
}
int64_t Not8(uint64_t x, uint64_t y, uint32_t *f) {
return ~x & 0xFF;
}
int64_t Not32(uint64_t x, uint64_t y, uint32_t *f) {
return ~x & 0xFFFFFFFF;
}
int64_t Not64(uint64_t x, uint64_t y, uint32_t *f) {
return ~x & 0xFFFFFFFFFFFFFFFF;
}
int64_t Neg8(uint64_t x64, uint64_t y, uint32_t *f) {
uint8_t x;
bool cf, of, af;
x = x64;
af = cf = !!x;
of = x == 0x80;
x = ~x + 1;
return AluFlags8(x, af, f, of, cf);
}
int64_t Neg32(uint64_t x64, uint64_t y, uint32_t *f) {
uint32_t x;
bool cf, of, af;
x = x64;
af = cf = !!x;
of = x == 0x80000000;
x = ~x + 1;
return AluFlags32(x, af, f, of, cf);
}
int64_t Neg64(uint64_t x64, uint64_t y, uint32_t *f) {
uint64_t x;
bool cf, of, af;
x = x64;
af = cf = !!x;
of = x == 0x8000000000000000;
x = ~x + 1;
return AluFlags64(x, af, f, of, cf);
}
static int64_t BumpFlags(uint64_t x, uint32_t af, uint32_t *f, uint32_t of,
uint32_t sf) {
return AluFlags(x, af, f, of, GetFlag(*f, FLAGS_CF), sf);
}
int64_t Dec32(uint64_t x64, uint64_t y, uint32_t *f) {
uint32_t x, z, of, sf, af;
x = x64;
z = x - 1;
sf = z >> 31;
af = (x & 15) < (z & 15);
of = ((z ^ x) & (x ^ 1)) >> 31;
return BumpFlags(z, af, f, of, sf);
}
int64_t Inc32(uint64_t x64, uint64_t y, uint32_t *f) {
uint32_t x, z, of, sf, af;
x = x64;
z = x + 1;
sf = z >> 31;
af = (z & 15) < (y & 15);
of = ((z ^ x) & (z ^ 1)) >> 31;
return BumpFlags(z, af, f, of, sf);
}
int64_t Inc64(uint64_t x, uint64_t y, uint32_t *f) {
uint64_t z;
uint32_t of, sf, af;
z = x + 1;
sf = z >> 63;
af = (z & 15) < (y & 15);
of = ((z ^ x) & (z ^ 1)) >> 63;
return BumpFlags(z, af, f, of, sf);
}
int64_t Dec64(uint64_t x, uint64_t y, uint32_t *f) {
uint64_t z;
uint32_t of, sf, af;
z = x - 1;
sf = z >> 63;
af = (x & 15) < (z & 15);
of = ((z ^ x) & (x ^ 1)) >> 63;
return BumpFlags(z, af, f, of, sf);
}
int64_t Inc8(uint64_t x64, uint64_t y, uint32_t *f) {
uint8_t x, z;
uint32_t of, sf, af;
x = x64;
z = x + 1;
sf = z >> 7;
af = (z & 15) < (y & 15);
of = ((z ^ x) & (z ^ 1)) >> 7;
return BumpFlags(z, af, f, of, sf);
}
int64_t Dec8(uint64_t x64, uint64_t y, uint32_t *f) {
uint8_t x, z;
uint32_t of, sf, af;
x = x64;
z = x - 1;
sf = z >> 7;
af = (x & 15) < (z & 15);
of = ((z ^ x) & (x ^ 1)) >> 7;
return BumpFlags(z, af, f, of, sf);
}
int64_t Shr8(uint64_t x64, uint64_t y, uint32_t *f) {
uint32_t x, cf;
x = x64 & 0xff;
if ((y &= 31)) {
cf = (x >> (y - 1)) & 1;
x >>= y;
return AluFlags8(x, 0, f, ((x << 1) ^ x) >> 7, cf);
} else {
return x;
}
}
int64_t Shr32(uint64_t x64, uint64_t y, uint32_t *f) {
uint32_t cf, x = x64;
if ((y &= 31)) {
cf = (x >> (y - 1)) & 1;
x >>= y;
return AluFlags32(x, 0, f, ((x << 1) ^ x) >> 31, cf);
} else {
return x;
}
}
int64_t Shr64(uint64_t x, uint64_t y, uint32_t *f) {
uint32_t cf;
if ((y &= 63)) {
cf = (x >> (y - 1)) & 1;
x >>= y;
return AluFlags64(x, 0, f, ((x << 1) ^ x) >> 63, cf);
} else {
return x;
}
}
int64_t Shl8(uint64_t x64, uint64_t y, uint32_t *f) {
uint32_t x, cf;
x = x64 & 0xff;
if ((y &= 31)) {
cf = (x >> ((8 - y) & 31)) & 1;
x = (x << y) & 0xff;
return AluFlags8(x, 0, f, (x >> 7) ^ cf, cf);
} else {
return x;
}
}
int64_t Shl32(uint64_t x64, uint64_t y, uint32_t *f) {
uint32_t cf, x = x64;
if ((y &= 31)) {
cf = (x >> (32 - y)) & 1;
x <<= y;
return AluFlags32(x, 0, f, (x >> 31) ^ cf, cf);
} else {
return x;
}
}
int64_t Shl64(uint64_t x, uint64_t y, uint32_t *f) {
uint32_t cf;
if ((y &= 63)) {
cf = (x >> (64 - y)) & 1;
x <<= y;
return AluFlags64(x, 0, f, (x >> 63) ^ cf, cf);
} else {
return x;
}
}
int64_t Sar8(uint64_t x64, uint64_t y, uint32_t *f) {
uint32_t x, cf;
x = x64 & 0xff;
if ((y &= 31)) {
cf = ((int32_t)(int8_t)x >> (y - 1)) & 1;
x = ((int32_t)(int8_t)x >> y) & 0xff;
return AluFlags8(x, 0, f, 0, cf);
} else {
return x;
}
}
int64_t Sar32(uint64_t x64, uint64_t y, uint32_t *f) {
uint32_t cf, x = x64;
if ((y &= 31)) {
cf = ((int32_t)x >> (y - 1)) & 1;
x = (int32_t)x >> y;
return AluFlags32(x, 0, f, 0, cf);
} else {
return x;
}
}
int64_t Sar64(uint64_t x, uint64_t y, uint32_t *f) {
uint32_t cf;
if ((y &= 63)) {
cf = ((int64_t)x >> (y - 1)) & 1;
x = (int64_t)x >> y;
return AluFlags64(x, 0, f, 0, cf);
} else {
return x;
}
}
static int64_t RotateFlags(uint64_t x, uint32_t cf, uint32_t *f, uint32_t of) {
*f &= ~(1u << FLAGS_CF | 1u << FLAGS_OF);
*f |= cf << FLAGS_CF | of << FLAGS_OF;
return x;
}
int64_t Rol32(uint64_t x64, uint64_t y, uint32_t *f) {
uint32_t x = x64;
if ((y &= 31)) {
x = x << y | x >> (32 - y);
return RotateFlags(x, x & 1, f, ((x >> 31) ^ x) & 1);
} else {
return x;
}
}
int64_t Rol64(uint64_t x, uint64_t y, uint32_t *f) {
if ((y &= 63)) {
x = x << y | x >> (64 - y);
return RotateFlags(x, x & 1, f, ((x >> 63) ^ x) & 1);
} else {
return x;
}
}
int64_t Ror32(uint64_t x64, uint64_t y, uint32_t *f) {
uint32_t x = x64;
if ((y &= 31)) {
x = x >> y | x << (32 - y);
return RotateFlags(x, x >> 31, f, ((x >> 31) ^ (x >> 30)) & 1);
} else {
return x;
}
}
int64_t Ror64(uint64_t x, uint64_t y, uint32_t *f) {
if ((y &= 63)) {
x = x >> y | x << (64 - y);
return RotateFlags(x, x >> 63, f, ((x >> 63) ^ (x >> 62)) & 1);
} else {
return x;
}
}
int64_t Rol8(uint64_t x64, uint64_t y, uint32_t *f) {
uint8_t x = x64;
if (y & 31) {
if ((y &= 7)) x = x << y | x >> (8 - y);
return RotateFlags(x, x & 1, f, ((x >> 7) ^ x) & 1);
} else {
return x;
}
}
int64_t Ror8(uint64_t x64, uint64_t y, uint32_t *f) {
uint8_t x = x64;
if (y & 31) {
if ((y &= 7)) x = x >> y | x << (8 - y);
return RotateFlags(x, x >> 7, f, ((x >> 7) ^ (x >> 6)) & 1);
} else {
return x;
}
}
static int64_t Rcr(uint64_t x, uint64_t y, uint32_t *f, uint64_t xm,
uint64_t k) {
uint64_t cf;
uint32_t ct;
x &= xm;
if (y) {
cf = GetFlag(*f, FLAGS_CF);
ct = (x >> (y - 1)) & 1;
if (y == 1) {
x = (x >> 1 | cf << (k - 1)) & xm;
} else {
x = (x >> y | cf << (k - y) | x << (k + 1 - y)) & xm;
}
return RotateFlags(x, ct, f, (((x << 1) ^ x) >> (k - 1)) & 1);
} else {
return x;
}
}
int64_t Rcr8(uint64_t x, uint64_t y, uint32_t *f) {
return Rcr(x, (y & 31) % 9, f, 0xff, 8);
}
int64_t Rcr16(uint64_t x, uint64_t y, uint32_t *f) {
return Rcr(x, (y & 31) % 17, f, 0xffff, 16);
}
int64_t Rcr32(uint64_t x, uint64_t y, uint32_t *f) {
return Rcr(x, y & 31, f, 0xffffffff, 32);
}
int64_t Rcr64(uint64_t x, uint64_t y, uint32_t *f) {
return Rcr(x, y & 63, f, 0xffffffffffffffff, 64);
}
static int64_t Rcl(uint64_t x, uint64_t y, uint32_t *f, uint64_t xm,
uint64_t k) {
uint64_t cf;
uint32_t ct;
x &= xm;
if (y) {
cf = GetFlag(*f, FLAGS_CF);
ct = (x >> (k - y)) & 1;
if (y == 1) {
x = (x << 1 | cf) & xm;
} else {
x = (x << y | cf << (y - 1) | x >> (k + 1 - y)) & xm;
}
return RotateFlags(x, ct, f, ct ^ ((x >> (k - 1)) & 1));
} else {
return x;
}
}
int64_t Rcl8(uint64_t x, uint64_t y, uint32_t *f) {
return Rcl(x, (y & 31) % 9, f, 0xff, 8);
}
int64_t Rcl16(uint64_t x, uint64_t y, uint32_t *f) {
return Rcl(x, (y & 31) % 17, f, 0xffff, 16);
}
int64_t Rcl32(uint64_t x, uint64_t y, uint32_t *f) {
return Rcl(x, y & 31, f, 0xffffffff, 32);
}
int64_t Rcl64(uint64_t x, uint64_t y, uint32_t *f) {
return Rcl(x, y & 63, f, 0xffffffffffffffff, 64);
}
uint64_t BsuDoubleShift(int w, uint64_t x, uint64_t y, uint8_t b, bool isright,
uint32_t *f) {
bool cf, of;
uint64_t s, k, m, z;
k = 8;
k <<= w;
s = 1;
s <<= k - 1;
m = s | s - 1;
b &= w == 3 ? 63 : 31;
x &= m;
if (b) {
if (isright) {
z = x >> b | y << (k - b);
cf = (x >> (b - 1)) & 1;
of = b == 1 && (z & s) != (x & s);
} else {
z = x << b | y >> (k - b);
cf = (x >> (k - b)) & 1;
of = b == 1 && (z & s) != (x & s);
}
x = z;
x &= m;
return AluFlags(x, 0, f, of, cf, !!(x & s));
} else {
return x;
}
}
int64_t AluFlags16(uint16_t z, uint32_t af, uint32_t *f, uint32_t of,
uint32_t cf) {
return AluFlags(z, af, f, of, cf, z >> 15);
}
int64_t Xor16(uint64_t x, uint64_t y, uint32_t *f) {
return AluFlags16(x ^ y, 0, f, 0, 0);
}
int64_t Or16(uint64_t x, uint64_t y, uint32_t *f) {
return AluFlags16(x | y, 0, f, 0, 0);
}
int64_t And16(uint64_t x, uint64_t y, uint32_t *f) {
return AluFlags16(x & y, 0, f, 0, 0);
}
int64_t Sub16(uint64_t x64, uint64_t y64, uint32_t *f) {
bool cf, of, af;
uint16_t x, y, z;
x = x64;
y = y64;
z = x - y;
cf = x < z;
af = (x & 15) < (z & 15);
of = ((z ^ x) & (x ^ y)) >> 15;
return AluFlags16(z, af, f, of, cf);
}
int64_t Add16(uint64_t x64, uint64_t y64, uint32_t *f) {
bool cf, of, af;
uint16_t x, y, z;
x = x64;
y = y64;
z = x + y;
cf = z < y;
af = (z & 15) < (y & 15);
of = ((z ^ x) & (z ^ y)) >> 15;
return AluFlags16(z, af, f, of, cf);
}
int64_t Adc16(uint64_t x64, uint64_t y64, uint32_t *f) {
bool cf, of, af;
uint16_t x, y, z, t;
x = x64;
y = y64;
t = x + GetFlag(*f, FLAGS_CF);
z = t + y;
cf = (t < x) | (z < y);
of = ((z ^ x) & (z ^ y)) >> 15;
af = ((t & 15) < (x & 15)) | ((z & 15) < (y & 15));
return AluFlags16(z, af, f, of, cf);
}
int64_t Sbb16(uint64_t x64, uint64_t y64, uint32_t *f) {
bool cf, of, af;
uint16_t x, y, z, t;
x = x64;
y = y64;
t = x - GetFlag(*f, FLAGS_CF);
z = t - y;
cf = (x < t) | (t < z);
of = ((z ^ x) & (x ^ y)) >> 15;
af = ((x & 15) < (t & 15)) | ((t & 15) < (z & 15));
return AluFlags16(z, af, f, of, cf);
}
int64_t Not16(uint64_t x, uint64_t y, uint32_t *f) {
return ~x & 0xFFFF;
}
int64_t Neg16(uint64_t x64, uint64_t y, uint32_t *f) {
uint16_t x;
bool cf, of, af;
x = x64;
af = cf = !!x;
of = x == 0x8000;
x = ~x + 1;
return AluFlags16(x, af, f, of, cf);
}
int64_t Inc16(uint64_t x64, uint64_t y, uint32_t *f) {
uint16_t x, z;
uint32_t of, sf, af;
x = x64;
z = x + 1;
sf = z >> 15;
af = (z & 15) < (y & 15);
of = ((z ^ x) & (z ^ 1)) >> 15;
return BumpFlags(z, af, f, of, sf);
}
int64_t Dec16(uint64_t x64, uint64_t y, uint32_t *f) {
uint16_t x, z;
uint32_t of, sf, af;
x = x64;
z = x - 1;
sf = z >> 15;
af = (x & 15) < (z & 15);
of = ((z ^ x) & (x ^ 1)) >> 15;
return BumpFlags(z, af, f, of, sf);
}
int64_t Shr16(uint64_t x64, uint64_t y, uint32_t *f) {
uint32_t x, cf;
x = x64 & 0xffff;
if ((y &= 31)) {
cf = (x >> (y - 1)) & 1;
x >>= y;
return AluFlags16(x, 0, f, ((x << 1) ^ x) >> 15, cf);
} else {
return x;
}
}
int64_t Shl16(uint64_t x64, uint64_t y, uint32_t *f) {
uint32_t x, cf;
x = x64 & 0xffff;
if ((y &= 31)) {
cf = (x >> ((16 - y) & 31)) & 1;
x = (x << y) & 0xffff;
return AluFlags16(x, 0, f, (x >> 15) ^ cf, cf);
} else {
return x;
}
}
int64_t Sar16(uint64_t x64, uint64_t y, uint32_t *f) {
uint32_t x, cf;
x = x64 & 0xffff;
if ((y &= 31)) {
cf = ((int32_t)(int16_t)x >> (y - 1)) & 1;
x = ((int32_t)(int16_t)x >> y) & 0xffff;
return AluFlags16(x, 0, f, 0, cf);
} else {
return x;
}
}
int64_t Rol16(uint64_t x64, uint64_t y, uint32_t *f) {
uint16_t x = x64;
if (y & 31) {
if ((y &= 15)) x = x << y | x >> (16 - y);
return RotateFlags(x, x & 1, f, ((x >> 15) ^ x) & 1);
} else {
return x;
}
}
int64_t Ror16(uint64_t x64, uint64_t y, uint32_t *f) {
uint16_t x = x64;
if (y & 31) {
if ((y &= 15)) x = x >> y | x << (16 - y);
return RotateFlags(x, x >> 15, f, ((x >> 15) ^ (x >> 14)) & 1);
} else {
return x;
}
}

View file

@ -1,118 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_ALU_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_ALU_H_
#include "tool/build/lib/machine.h"
#define ALU_ADD 0
#define ALU_OR 1
#define ALU_ADC 2
#define ALU_SBB 3
#define ALU_AND 4
#define ALU_SUB 5
#define ALU_XOR 6
#define ALU_CMP 7
#define ALU_NOT 8
#define ALU_NEG 9
#define ALU_INC 10
#define ALU_DEC 11
#define BSU_ROL 0
#define BSU_ROR 1
#define BSU_RCL 2
#define BSU_RCR 3
#define BSU_SHL 4
#define BSU_SHR 5
#define BSU_SAL 6
#define BSU_SAR 7
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
typedef int64_t (*aluop_f)(uint64_t, uint64_t, uint32_t *);
extern const aluop_f kAlu[12][4];
extern const aluop_f kBsu[8][4];
int64_t Xor8(uint64_t, uint64_t, uint32_t *);
int64_t Xor16(uint64_t, uint64_t, uint32_t *);
int64_t Xor32(uint64_t, uint64_t, uint32_t *);
int64_t Xor64(uint64_t, uint64_t, uint32_t *);
int64_t Or8(uint64_t, uint64_t, uint32_t *);
int64_t Or16(uint64_t, uint64_t, uint32_t *);
int64_t Or32(uint64_t, uint64_t, uint32_t *);
int64_t Or64(uint64_t, uint64_t, uint32_t *);
int64_t And8(uint64_t, uint64_t, uint32_t *);
int64_t And16(uint64_t, uint64_t, uint32_t *);
int64_t And32(uint64_t, uint64_t, uint32_t *);
int64_t And64(uint64_t, uint64_t, uint32_t *);
int64_t Sub8(uint64_t, uint64_t, uint32_t *);
int64_t Sbb8(uint64_t, uint64_t, uint32_t *);
int64_t Sub16(uint64_t, uint64_t, uint32_t *);
int64_t Sbb16(uint64_t, uint64_t, uint32_t *);
int64_t Sub32(uint64_t, uint64_t, uint32_t *);
int64_t Sbb32(uint64_t, uint64_t, uint32_t *);
int64_t Sub64(uint64_t, uint64_t, uint32_t *);
int64_t Sbb64(uint64_t, uint64_t, uint32_t *);
int64_t Add8(uint64_t, uint64_t, uint32_t *);
int64_t Adc8(uint64_t, uint64_t, uint32_t *);
int64_t Add16(uint64_t, uint64_t, uint32_t *);
int64_t Adc16(uint64_t, uint64_t, uint32_t *);
int64_t Add32(uint64_t, uint64_t, uint32_t *);
int64_t Adc32(uint64_t, uint64_t, uint32_t *);
int64_t Add64(uint64_t, uint64_t, uint32_t *);
int64_t Adc64(uint64_t, uint64_t, uint32_t *);
int64_t Not8(uint64_t, uint64_t, uint32_t *);
int64_t Not16(uint64_t, uint64_t, uint32_t *);
int64_t Not32(uint64_t, uint64_t, uint32_t *);
int64_t Not64(uint64_t, uint64_t, uint32_t *);
int64_t Neg8(uint64_t, uint64_t, uint32_t *);
int64_t Neg16(uint64_t, uint64_t, uint32_t *);
int64_t Neg32(uint64_t, uint64_t, uint32_t *);
int64_t Neg64(uint64_t, uint64_t, uint32_t *);
int64_t Inc8(uint64_t, uint64_t, uint32_t *);
int64_t Inc16(uint64_t, uint64_t, uint32_t *);
int64_t Inc32(uint64_t, uint64_t, uint32_t *);
int64_t Inc64(uint64_t, uint64_t, uint32_t *);
int64_t Dec8(uint64_t, uint64_t, uint32_t *);
int64_t Dec16(uint64_t, uint64_t, uint32_t *);
int64_t Dec32(uint64_t, uint64_t, uint32_t *);
int64_t Dec64(uint64_t, uint64_t, uint32_t *);
int64_t Shr8(uint64_t, uint64_t, uint32_t *);
int64_t Shr16(uint64_t, uint64_t, uint32_t *);
int64_t Shr32(uint64_t, uint64_t, uint32_t *);
int64_t Shr64(uint64_t, uint64_t, uint32_t *);
int64_t Shl8(uint64_t, uint64_t, uint32_t *);
int64_t Shl16(uint64_t, uint64_t, uint32_t *);
int64_t Shl32(uint64_t, uint64_t, uint32_t *);
int64_t Shl64(uint64_t, uint64_t, uint32_t *);
int64_t Sar8(uint64_t, uint64_t, uint32_t *);
int64_t Sar16(uint64_t, uint64_t, uint32_t *);
int64_t Sar32(uint64_t, uint64_t, uint32_t *);
int64_t Sar64(uint64_t, uint64_t, uint32_t *);
int64_t Rol8(uint64_t, uint64_t, uint32_t *);
int64_t Rol16(uint64_t, uint64_t, uint32_t *);
int64_t Rol32(uint64_t, uint64_t, uint32_t *);
int64_t Rol64(uint64_t, uint64_t, uint32_t *);
int64_t Ror8(uint64_t, uint64_t, uint32_t *);
int64_t Ror16(uint64_t, uint64_t, uint32_t *);
int64_t Ror32(uint64_t, uint64_t, uint32_t *);
int64_t Ror64(uint64_t, uint64_t, uint32_t *);
int64_t Rcr8(uint64_t, uint64_t, uint32_t *);
int64_t Rcr16(uint64_t, uint64_t, uint32_t *);
int64_t Rcr32(uint64_t, uint64_t, uint32_t *);
int64_t Rcr64(uint64_t, uint64_t, uint32_t *);
int64_t Rcl8(uint64_t, uint64_t, uint32_t *);
int64_t Rcl16(uint64_t, uint64_t, uint32_t *);
int64_t Rcl32(uint64_t, uint64_t, uint32_t *);
int64_t Rcl64(uint64_t, uint64_t, uint32_t *);
uint64_t BsuDoubleShift(int, uint64_t, uint64_t, uint8_t, bool, uint32_t *);
int64_t AluFlags8(uint8_t, uint32_t, uint32_t *, uint32_t, uint32_t);
int64_t AluFlags16(uint16_t, uint32_t, uint32_t *, uint32_t, uint32_t);
int64_t AluFlags32(uint32_t, uint32_t, uint32_t *, uint32_t, uint32_t);
int64_t AluFlags64(uint64_t, uint32_t, uint32_t *, uint32_t, uint32_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_ALU_H_ */

View file

@ -1,75 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/log/check.h"
#include "libc/mem/mem.h"
#include "libc/mem/gc.internal.h"
#include "libc/str/str.h"
#include "tool/build/lib/endian.h"
#include "tool/build/lib/machine.h"
#include "tool/build/lib/memory.h"
#define STACKALIGN 16
#define LINUX_AT_EXECFN 31
static size_t GetArgListLen(char **p) {
size_t n;
for (n = 0; *p; ++p) ++n;
return n;
}
static int64_t PushString(struct Machine *m, const char *s) {
size_t n;
int64_t sp;
n = strlen(s) + 1;
sp = Read64(m->sp);
sp -= n;
Write64(m->sp, sp);
VirtualRecv(m, sp, s, n);
return sp;
}
void LoadArgv(struct Machine *m, const char *prog, char **args, char **vars) {
int64_t i, n, sp, *p, *bloc;
size_t narg, nenv, naux, nall;
DCHECK_NOTNULL(prog);
DCHECK_NOTNULL(args);
DCHECK_NOTNULL(vars);
naux = 1;
nenv = GetArgListLen(vars);
narg = GetArgListLen(args);
nall = 1 + 1 + narg + 1 + nenv + 1 + (naux + 1) * 2;
bloc = gc(malloc(sizeof(int64_t) * nall));
p = bloc + nall;
*--p = 0;
*--p = 0;
*--p = PushString(m, prog);
*--p = LINUX_AT_EXECFN;
for (*--p = 0, i = nenv; i--;) *--p = PushString(m, vars[i]);
for (*--p = 0, i = narg; i--;) *--p = PushString(m, args[i]);
*--p = PushString(m, prog);
*--p = 1 + narg;
DCHECK_EQ(bloc, p);
sp = Read64(m->sp);
while ((sp - nall * sizeof(int64_t)) & (STACKALIGN - 1)) --sp;
sp -= nall * sizeof(int64_t);
DCHECK_EQ(0, sp % STACKALIGN);
Write64(m->sp, sp);
Write64(m->di, 0); /* or ape detects freebsd */
VirtualRecv(m, sp, bloc, sizeof(int64_t) * nall);
}

View file

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

View file

@ -1,77 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "tool/build/lib/alu.h"
#include "tool/build/lib/bcd.h"
#include "tool/build/lib/endian.h"
#include "tool/build/lib/flags.h"
#include "tool/build/lib/throw.h"
relegated void OpDas(struct Machine *m, uint32_t rde) {
uint8_t al, af, cf;
af = cf = 0;
al = m->ax[0];
if ((al & 0x0f) > 9 || GetFlag(m->flags, FLAGS_AF)) {
cf = m->ax[0] < 6 || GetFlag(m->flags, FLAGS_CF);
m->ax[0] -= 0x06;
af = 1;
}
if (al > 0x99 || GetFlag(m->flags, FLAGS_CF)) {
m->ax[0] -= 0x60;
cf = 1;
}
AluFlags8(m->ax[0], af, &m->flags, 0, cf);
}
relegated void OpAaa(struct Machine *m, uint32_t rde) {
uint8_t af, cf;
af = cf = 0;
if ((m->ax[0] & 0x0f) > 9 || GetFlag(m->flags, FLAGS_AF)) {
cf = m->ax[0] < 6 || GetFlag(m->flags, FLAGS_CF);
Write16(m->ax, Read16(m->ax) + 0x106);
af = cf = 1;
}
m->ax[0] &= 0x0f;
AluFlags8(m->ax[0], af, &m->flags, 0, cf);
}
relegated void OpAas(struct Machine *m, uint32_t rde) {
uint8_t af, cf;
af = cf = 0;
if ((m->ax[0] & 0x0f) > 9 || GetFlag(m->flags, FLAGS_AF)) {
cf = m->ax[0] < 6 || GetFlag(m->flags, FLAGS_CF);
Write16(m->ax, Read16(m->ax) - 0x106);
af = cf = 1;
}
m->ax[0] &= 0x0f;
AluFlags8(m->ax[0], af, &m->flags, 0, cf);
}
relegated void OpAam(struct Machine *m, uint32_t rde) {
uint8_t i = m->xedd->op.uimm0;
if (!i) ThrowDivideError(m);
m->ax[1] = m->ax[0] / i;
m->ax[0] = m->ax[0] % i;
AluFlags8(m->ax[0], 0, &m->flags, 0, 0);
}
relegated void OpAad(struct Machine *m, uint32_t rde) {
uint8_t i = m->xedd->op.uimm0;
Write16(m->ax, (m->ax[1] * i + m->ax[0]) & 0xff);
AluFlags8(m->ax[0], 0, &m->flags, 0, 0);
}

View file

@ -1,15 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_BCD_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_BCD_H_
#include "tool/build/lib/machine.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
void OpDas(struct Machine *, uint32_t);
void OpAaa(struct Machine *, uint32_t);
void OpAas(struct Machine *, uint32_t);
void OpAam(struct Machine *, uint32_t);
void OpAad(struct Machine *, uint32_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_BCD_H_ */

View file

@ -1,145 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "tool/build/lib/bitscan.h"
#include "tool/build/lib/flags.h"
#include "tool/build/lib/machine.h"
#include "tool/build/lib/modrm.h"
uint64_t AluPopcnt(struct Machine *m, uint32_t rde, 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);
m->flags = SetFlag(m->flags, FLAGS_OF, false);
m->flags = SetFlag(m->flags, FLAGS_PF, false);
x = x - ((x >> 1) & 0x5555555555555555);
x = ((x >> 2) & 0x3333333333333333) + (x & 0x3333333333333333);
x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f;
x = (x + (x >> 32)) & 0xffffffff;
x = x + (x >> 16);
x = (x + (x >> 8)) & 0x7f;
return x;
}
uint64_t AluBsr(struct Machine *m, uint32_t rde, uint64_t x) {
unsigned i;
if (Rexw(rde)) {
x &= 0xffffffffffffffff;
if (Rep(rde) == 3) {
if (!x) {
m->flags = SetFlag(m->flags, FLAGS_CF, true);
m->flags = SetFlag(m->flags, FLAGS_ZF, false);
return 64;
} else {
m->flags = SetFlag(m->flags, FLAGS_CF, false);
m->flags = SetFlag(m->flags, FLAGS_ZF, x == 1);
}
} else {
m->flags = SetFlag(m->flags, FLAGS_ZF, !x);
if (!x) return 0;
}
return 63 ^ __builtin_clzll(x);
} else if (!Osz(rde)) {
x &= 0xffffffff;
if (Rep(rde) == 3) {
if (!x) {
m->flags = SetFlag(m->flags, FLAGS_CF, true);
m->flags = SetFlag(m->flags, FLAGS_ZF, false);
return 32;
} else {
m->flags = SetFlag(m->flags, FLAGS_CF, false);
m->flags = SetFlag(m->flags, FLAGS_ZF, x == 1);
}
} else {
m->flags = SetFlag(m->flags, FLAGS_ZF, !x);
if (!x) return 0;
}
return 31 ^ __builtin_clz(x);
} else {
x &= 0xffff;
if (Rep(rde) == 3) {
if (!x) {
m->flags = SetFlag(m->flags, FLAGS_CF, true);
m->flags = SetFlag(m->flags, FLAGS_ZF, false);
return 16;
} else {
m->flags = SetFlag(m->flags, FLAGS_CF, false);
m->flags = SetFlag(m->flags, FLAGS_ZF, x == 1);
}
} else {
m->flags = SetFlag(m->flags, FLAGS_ZF, !x);
if (!x) return 0;
}
for (i = 15; !(x & 0x8000); --i) x <<= 1;
return i;
}
}
uint64_t AluBsf(struct Machine *m, uint32_t rde, uint64_t x) {
unsigned i;
if (Rexw(rde)) {
x &= 0xffffffffffffffff;
if (Rep(rde) == 3) {
if (!x) {
m->flags = SetFlag(m->flags, FLAGS_CF, true);
m->flags = SetFlag(m->flags, FLAGS_ZF, false);
return 64;
} else {
m->flags = SetFlag(m->flags, FLAGS_CF, false);
m->flags = SetFlag(m->flags, FLAGS_ZF, x & 1);
}
} else {
m->flags = SetFlag(m->flags, FLAGS_ZF, !x);
if (!x) return 0;
}
return __builtin_ctzll(x);
} else if (!Osz(rde)) {
x &= 0xffffffff;
if (Rep(rde) == 3) {
if (!x) {
m->flags = SetFlag(m->flags, FLAGS_CF, true);
m->flags = SetFlag(m->flags, FLAGS_ZF, false);
return 32;
} else {
m->flags = SetFlag(m->flags, FLAGS_CF, false);
m->flags = SetFlag(m->flags, FLAGS_ZF, x & 1);
}
} else {
m->flags = SetFlag(m->flags, FLAGS_ZF, !x);
if (!x) return 0;
}
return __builtin_ctz(x);
} else {
x &= 0xffff;
if (Rep(rde) == 3) {
if (!x) {
m->flags = SetFlag(m->flags, FLAGS_CF, true);
m->flags = SetFlag(m->flags, FLAGS_ZF, false);
return 16;
} else {
m->flags = SetFlag(m->flags, FLAGS_CF, false);
m->flags = SetFlag(m->flags, FLAGS_ZF, x & 1);
}
} else {
m->flags = SetFlag(m->flags, FLAGS_ZF, !x);
if (!x) return 0;
}
for (i = 0; !(x & 1); ++i) x >>= 1;
return i;
}
}

View file

@ -1,15 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_BITSCAN_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_BITSCAN_H_
#include "tool/build/lib/machine.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
typedef uint64_t (*bitscan_f)(struct Machine *, uint32_t, uint64_t);
uint64_t AluBsr(struct Machine *, uint32_t, uint64_t);
uint64_t AluBsf(struct Machine *, uint32_t, uint64_t);
uint64_t AluPopcnt(struct Machine *, uint32_t, uint64_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_BITSCAN_H_ */

View file

@ -1,56 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/mem/arraylist2.internal.h"
#include "libc/assert.h"
#include "libc/log/log.h"
#include "tool/build/lib/breakpoint.h"
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) {
memcpy(&bps->p[i], b, sizeof(*b));
return i;
}
}
return APPEND(&bps->p, &bps->i, &bps->n, b);
}
ssize_t IsAtBreakpoint(struct Breakpoints *bps, int64_t addr) {
size_t i;
for (i = bps->i; i--;) {
if (bps->p[i].disable) continue;
if (bps->p[i].addr == addr) {
if (bps->p[i].oneshot) {
bps->p[i].disable = true;
if (i == bps->i - 1) {
--bps->i;
}
}
return i;
}
}
return -1;
}

View file

@ -1,22 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_BREAKPOINT_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_BREAKPOINT_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct Breakpoints {
size_t i, n;
struct Breakpoint {
int64_t addr;
const char *symbol;
bool disable;
bool oneshot;
} * p;
};
ssize_t IsAtBreakpoint(struct Breakpoints *, int64_t);
ssize_t PushBreakpoint(struct Breakpoints *, struct Breakpoint *);
void PopBreakpoint(struct Breakpoints *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_BREAKPOINT_H_ */

View file

@ -1,36 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "tool/build/lib/modrm.h"
/**
* Byte register offsets.
*
* for (i = 0; i < 2; ++i) { // rex
* for (j = 0; j < 2; ++j) { // rexb, or rexr
* for (k = 0; k < 8; ++k) { // reg, rm, or srm
* kByteReg[i << 4 | j << 3 | k] =
* i ? (j << 3 | k) * 8 : (k & 0b11) * 8 + ((k & 0b100) >> 2);
* }
* }
* }
*/
const uint8_t kByteReg[32] = {0x00, 0x08, 0x10, 0x18, 0x01, 0x09, 0x11, 0x19,
0x00, 0x08, 0x10, 0x18, 0x01, 0x09, 0x11, 0x19,
0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38,
0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78};

View file

@ -1,56 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/itoa.h"
#include "libc/macros.internal.h"
#include "libc/str/str.h"
#include "libc/str/tab.internal.h"
#include "tool/build/lib/buffer.h"
#include "tool/build/lib/cga.h"
/* blk blu grn cyn red mag yel wht */
static const uint8_t kCgaToAnsi[16] = {30, 34, 32, 36, 31, 35, 33, 37,
90, 94, 92, 96, 91, 95, 93, 97};
size_t FormatCga(uint8_t bgfg, char buf[hasatleast 11]) {
char *p = buf;
*p++ = '\e';
*p++ = '[';
p = FormatUint32(p, kCgaToAnsi[(bgfg & 0xF0) >> 4] + 10);
*p++ = ';';
p = FormatUint32(p, kCgaToAnsi[bgfg & 0x0F]);
*p++ = 'm';
*p = '\0';
return p - buf;
}
void DrawCga(struct Panel *p, uint8_t v[25][80][2]) {
char buf[11];
unsigned y, x, n, a;
n = MIN(25, p->bottom - p->top);
for (y = 0; y < n; ++y) {
a = -1;
for (x = 0; x < 80; ++x) {
if (v[y][x][1] != a) {
AppendData(&p->lines[y], buf, FormatCga((a = v[y][x][1]), buf));
}
AppendWide(&p->lines[y], kCp437[v[y][x][0]]);
}
AppendStr(&p->lines[y], "\e[0m");
}
}

View file

@ -1,12 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_CGA_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_CGA_H_
#include "tool/build/lib/panel.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
void DrawCga(struct Panel *, uint8_t[25][80][2]);
size_t FormatCga(uint8_t, char[hasatleast 11]);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_CGA_H_ */

View file

@ -1,52 +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 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/bsr.h"
#include "libc/nexgen32e/x86feature.h"
#include "tool/build/lib/clmul.h"
#include "tool/build/lib/endian.h"
#include "tool/build/lib/modrm.h"
/**
* @fileoverview Carryless Multiplication ISA
*/
struct clmul {
uint64_t x, y;
};
static struct clmul clmul(uint64_t a, uint64_t b) {
uint64_t t, x = 0, y = 0;
if (a && b) {
if (_bsrl(a) < _bsrl(b)) t = a, a = b, b = t;
for (t = 0; b; a <<= 1, b >>= 1) {
if (b & 1) x ^= a, y ^= t;
t = t << 1 | a >> 63;
}
}
return (struct clmul){x, y};
}
void OpSsePclmulqdq(struct Machine *m, uint32_t rde) {
struct clmul res;
res = clmul(Read64(XmmRexrReg(m, rde) + ((m->xedd->op.uimm0 & 0x01) << 3)),
Read64(GetModrmRegisterXmmPointerRead16(m, rde) +
((m->xedd->op.uimm0 & 0x10) >> 1)));
Write64(XmmRexrReg(m, rde) + 0, res.x);
Write64(XmmRexrReg(m, rde) + 8, res.y);
}

View file

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

View file

@ -1,88 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "tool/build/lib/endian.h"
#include "tool/build/lib/machine.h"
void OpCpuid(struct Machine *m, uint32_t rde) {
uint32_t ax, bx, cx, dx;
ax = 0;
bx = 0;
cx = 0;
dx = 0;
switch (Read32(m->ax)) {
case 0:
case 0x80000000:
ax = 7;
bx = 'G' | 'e' << 8 | 'n' << 16 | 'u' << 24;
dx = 'i' | 'n' << 8 | 'e' << 16 | 'C' << 24;
cx = 'o' | 's' << 8 | 'm' << 16 | 'o' << 24;
break;
case 1:
cx |= 1 << 0; // sse3
cx |= 1 << 1; // pclmulqdq
cx |= 1 << 9; // ssse3
cx |= 1 << 23; // popcnt
cx |= 1 << 30; // rdrnd
cx |= 0 << 25; // aes
cx |= 1 << 13; // cmpxchg16b
dx |= 1 << 0; // fpu
dx |= 1 << 4; // tsc
dx |= 1 << 6; // pae
dx |= 1 << 8; // cmpxchg8b
dx |= 1 << 15; // cmov
dx |= 1 << 19; // clflush
dx |= 1 << 23; // mmx
dx |= 1 << 24; // fxsave
dx |= 1 << 25; // sse
dx |= 1 << 26; // sse2
break;
case 7:
switch (Read32(m->cx)) {
case 0:
bx |= 1 << 0; // fsgsbase
bx |= 1 << 9; // erms
bx |= 0 << 18; // rdseed
cx |= 1 << 22; // rdpid
break;
default:
break;
}
break;
case 0x80000001:
cx |= 1 << 0; // lahf
dx |= 1 << 0; // fpu
dx |= 1 << 8; // cmpxchg8b
dx |= 1 << 11; // syscall
dx |= 1 << 15; // cmov
dx |= 1 << 23; // mmx
dx |= 1 << 24; // fxsave
dx |= 1 << 27; // rdtscp
dx |= 1 << 29; // long
break;
case 0x80000007:
dx |= 1 << 8; // invtsc
break;
default:
break;
}
Write64(m->ax, ax);
Write64(m->bx, bx);
Write64(m->cx, cx);
Write64(m->dx, dx);
}

View file

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

View file

@ -1,458 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.internal.h"
#include "libc/math.h"
#include "libc/str/str.h"
#include "tool/build/lib/cvt.h"
#include "tool/build/lib/endian.h"
#include "tool/build/lib/fpu.h"
#include "tool/build/lib/machine.h"
#include "tool/build/lib/memory.h"
#include "tool/build/lib/modrm.h"
#include "tool/build/lib/pun.h"
#include "tool/build/lib/throw.h"
#define kOpCvt0f2a 0
#define kOpCvtt0f2c 4
#define kOpCvt0f2d 8
#define kOpCvt0f5a 12
#define kOpCvt0f5b 16
#define kOpCvt0fE6 20
static double SseRoundDouble(struct Machine *m, double x) {
switch ((m->mxcsr & kMxcsrRc) >> 13) {
case 0:
return rint(x);
case 1:
return floor(x);
case 2:
return ceil(x);
case 3:
return trunc(x);
default:
for (;;) (void)0;
}
}
static void OpGdqpWssCvttss2si(struct Machine *m, uint32_t rde) {
int64_t n;
union FloatPun f;
f.i = Read32(GetModrmRegisterXmmPointerRead4(m, rde));
n = f.f;
if (!Rexw(rde)) n &= 0xffffffff;
Write64(RegRexrReg(m, rde), n);
}
static void OpGdqpWsdCvttsd2si(struct Machine *m, uint32_t rde) {
int64_t n;
union DoublePun d;
d.i = Read64(GetModrmRegisterXmmPointerRead8(m, rde));
n = d.f;
if (!Rexw(rde)) n &= 0xffffffff;
Write64(RegRexrReg(m, rde), n);
}
static void OpGdqpWssCvtss2si(struct Machine *m, uint32_t rde) {
int64_t n;
union FloatPun f;
f.i = Read32(GetModrmRegisterXmmPointerRead4(m, rde));
n = rintf(f.f);
if (!Rexw(rde)) n &= 0xffffffff;
Write64(RegRexrReg(m, rde), n);
}
static void OpGdqpWsdCvtsd2si(struct Machine *m, uint32_t rde) {
int64_t n;
union DoublePun d;
d.i = Read64(GetModrmRegisterXmmPointerRead8(m, rde));
n = SseRoundDouble(m, d.f);
if (!Rexw(rde)) n &= 0xffffffff;
Write64(RegRexrReg(m, rde), n);
}
static void OpVssEdqpCvtsi2ss(struct Machine *m, uint32_t rde) {
union FloatPun f;
if (Rexw(rde)) {
int64_t n;
n = Read64(GetModrmRegisterWordPointerRead8(m, rde));
f.f = n;
Write32(XmmRexrReg(m, rde), f.i);
} else {
int32_t n;
n = Read32(GetModrmRegisterWordPointerRead4(m, rde));
f.f = n;
Write32(XmmRexrReg(m, rde), f.i);
}
}
static void OpVsdEdqpCvtsi2sd(struct Machine *m, uint32_t rde) {
union DoublePun d;
if (Rexw(rde)) {
int64_t n;
n = Read64(GetModrmRegisterWordPointerRead8(m, rde));
d.f = n;
Write64(XmmRexrReg(m, rde), d.i);
} else {
int32_t n;
n = Read32(GetModrmRegisterWordPointerRead4(m, rde));
d.f = n;
Write64(XmmRexrReg(m, rde), d.i);
}
}
static void OpVpsQpiCvtpi2ps(struct Machine *m, uint32_t rde) {
uint8_t *p;
int32_t i[2];
union FloatPun f[2];
p = GetModrmRegisterMmPointerRead8(m, rde);
i[0] = Read32(p + 0);
i[1] = Read32(p + 4);
f[0].f = i[0];
f[1].f = i[1];
Write32(XmmRexrReg(m, rde) + 0, f[0].i);
Write32(XmmRexrReg(m, rde) + 4, f[1].i);
}
static void OpVpdQpiCvtpi2pd(struct Machine *m, uint32_t rde) {
uint8_t *p;
int32_t n[2];
union DoublePun f[2];
p = GetModrmRegisterMmPointerRead8(m, rde);
n[0] = Read32(p + 0);
n[1] = Read32(p + 4);
f[0].f = n[0];
f[1].f = n[1];
Write64(XmmRexrReg(m, rde) + 0, f[0].i);
Write64(XmmRexrReg(m, rde) + 8, f[1].i);
}
static void OpPpiWpsqCvtps2pi(struct Machine *m, uint32_t rde) {
uint8_t *p;
unsigned i;
int32_t n[2];
union FloatPun f[2];
p = GetModrmRegisterXmmPointerRead8(m, rde);
f[0].i = Read32(p + 0 * 4);
f[1].i = Read32(p + 1 * 4);
switch ((m->mxcsr & kMxcsrRc) >> 13) {
case 0:
for (i = 0; i < 2; ++i) n[i] = rintf(f[i].f);
break;
case 1:
for (i = 0; i < 2; ++i) n[i] = floorf(f[i].f);
break;
case 2:
for (i = 0; i < 2; ++i) n[i] = ceilf(f[i].f);
break;
case 3:
for (i = 0; i < 2; ++i) n[i] = truncf(f[i].f);
break;
default:
for (;;) (void)0;
}
Write32(MmReg(m, rde) + 0, n[0]);
Write32(MmReg(m, rde) + 4, n[1]);
}
static void OpPpiWpsqCvttps2pi(struct Machine *m, uint32_t rde) {
uint8_t *p;
int32_t n[2];
union FloatPun f[2];
p = GetModrmRegisterXmmPointerRead8(m, rde);
f[0].i = Read32(p + 0);
f[1].i = Read32(p + 4);
n[0] = f[0].f;
n[1] = f[1].f;
Write32(MmReg(m, rde) + 0, n[0]);
Write32(MmReg(m, rde) + 4, n[1]);
}
static void OpPpiWpdCvtpd2pi(struct Machine *m, uint32_t rde) {
uint8_t *p;
unsigned i;
int32_t n[2];
union DoublePun d[2];
p = GetModrmRegisterXmmPointerRead16(m, rde);
d[0].i = Read64(p + 0);
d[1].i = Read64(p + 8);
for (i = 0; i < 2; ++i) n[i] = SseRoundDouble(m, d[i].f);
Write32(MmReg(m, rde) + 0, n[0]);
Write32(MmReg(m, rde) + 4, n[1]);
}
static void OpPpiWpdCvttpd2pi(struct Machine *m, uint32_t rde) {
uint8_t *p;
int32_t n[2];
union DoublePun d[2];
p = GetModrmRegisterXmmPointerRead16(m, rde);
d[0].i = Read64(p + 0);
d[1].i = Read64(p + 8);
n[0] = d[0].f;
n[1] = d[1].f;
Write32(MmReg(m, rde) + 0, n[0]);
Write32(MmReg(m, rde) + 4, n[1]);
}
static void OpVpdWpsCvtps2pd(struct Machine *m, uint32_t rde) {
uint8_t *p;
union FloatPun f[2];
union DoublePun d[2];
p = GetModrmRegisterXmmPointerRead8(m, rde);
f[0].i = Read32(p + 0);
f[1].i = Read32(p + 4);
d[0].f = f[0].f;
d[1].f = f[1].f;
Write64(XmmRexrReg(m, rde) + 0, d[0].i);
Write64(XmmRexrReg(m, rde) + 8, d[1].i);
}
static void OpVpsWpdCvtpd2ps(struct Machine *m, uint32_t rde) {
uint8_t *p;
union FloatPun f[2];
union DoublePun d[2];
p = GetModrmRegisterXmmPointerRead16(m, rde);
d[0].i = Read64(p + 0);
d[1].i = Read64(p + 8);
f[0].f = d[0].f;
f[1].f = d[1].f;
Write32(XmmRexrReg(m, rde) + 0, f[0].i);
Write32(XmmRexrReg(m, rde) + 4, f[1].i);
}
static void OpVssWsdCvtsd2ss(struct Machine *m, uint32_t rde) {
union FloatPun f;
union DoublePun d;
d.i = Read64(GetModrmRegisterXmmPointerRead8(m, rde));
f.f = d.f;
Write32(XmmRexrReg(m, rde), f.i);
}
static void OpVsdWssCvtss2sd(struct Machine *m, uint32_t rde) {
union FloatPun f;
union DoublePun d;
f.i = Read32(GetModrmRegisterXmmPointerRead4(m, rde));
d.f = f.f;
Write64(XmmRexrReg(m, rde), d.i);
}
static void OpVpsWdqCvtdq2ps(struct Machine *m, uint32_t rde) {
uint8_t *p;
int32_t n[4];
union FloatPun f[4];
p = GetModrmRegisterXmmPointerRead16(m, rde);
n[0] = Read32(p + 0 * 4);
n[1] = Read32(p + 1 * 4);
n[2] = Read32(p + 2 * 4);
n[3] = Read32(p + 3 * 4);
f[0].f = n[0];
f[1].f = n[1];
f[2].f = n[2];
f[3].f = n[3];
Write32(XmmRexrReg(m, rde) + 0 * 4, f[0].i);
Write32(XmmRexrReg(m, rde) + 1 * 4, f[1].i);
Write32(XmmRexrReg(m, rde) + 2 * 4, f[2].i);
Write32(XmmRexrReg(m, rde) + 3 * 4, f[3].i);
}
static void OpVpdWdqCvtdq2pd(struct Machine *m, uint32_t rde) {
uint8_t *p;
int32_t n[2];
union DoublePun d[2];
p = GetModrmRegisterXmmPointerRead8(m, rde);
n[0] = Read32(p + 0 * 4);
n[1] = Read32(p + 1 * 4);
d[0].f = n[0];
d[1].f = n[1];
Write64(XmmRexrReg(m, rde) + 0, d[0].i);
Write64(XmmRexrReg(m, rde) + 8, d[1].i);
}
static void OpVdqWpsCvttps2dq(struct Machine *m, uint32_t rde) {
uint8_t *p;
int32_t n[4];
union FloatPun f[4];
p = GetModrmRegisterXmmPointerRead16(m, rde);
f[0].i = Read32(p + 0 * 4);
f[1].i = Read32(p + 1 * 4);
f[2].i = Read32(p + 2 * 4);
f[3].i = Read32(p + 3 * 4);
n[0] = f[0].f;
n[1] = f[1].f;
n[2] = f[2].f;
n[3] = f[3].f;
Write32(XmmRexrReg(m, rde) + 0 * 4, n[0]);
Write32(XmmRexrReg(m, rde) + 1 * 4, n[1]);
Write32(XmmRexrReg(m, rde) + 2 * 4, n[2]);
Write32(XmmRexrReg(m, rde) + 3 * 4, n[3]);
}
static void OpVdqWpsCvtps2dq(struct Machine *m, uint32_t rde) {
uint8_t *p;
unsigned i;
int32_t n[4];
union FloatPun f[4];
p = GetModrmRegisterXmmPointerRead16(m, rde);
f[0].i = Read32(p + 0 * 4);
f[1].i = Read32(p + 1 * 4);
f[2].i = Read32(p + 2 * 4);
f[3].i = Read32(p + 3 * 4);
switch ((m->mxcsr & kMxcsrRc) >> 13) {
case 0:
for (i = 0; i < 4; ++i) n[i] = rintf(f[i].f);
break;
case 1:
for (i = 0; i < 4; ++i) n[i] = floorf(f[i].f);
break;
case 2:
for (i = 0; i < 4; ++i) n[i] = ceilf(f[i].f);
break;
case 3:
for (i = 0; i < 4; ++i) n[i] = truncf(f[i].f);
break;
default:
for (;;) (void)0;
}
Write32(XmmRexrReg(m, rde) + 0 * 4, n[0]);
Write32(XmmRexrReg(m, rde) + 1 * 4, n[1]);
Write32(XmmRexrReg(m, rde) + 2 * 4, n[2]);
Write32(XmmRexrReg(m, rde) + 3 * 4, n[3]);
}
static void OpVdqWpdCvttpd2dq(struct Machine *m, uint32_t rde) {
uint8_t *p;
int32_t n[2];
union DoublePun d[2];
p = GetModrmRegisterXmmPointerRead16(m, rde);
d[0].i = Read64(p + 0);
d[1].i = Read64(p + 8);
n[0] = d[0].f;
n[1] = d[1].f;
Write32(XmmRexrReg(m, rde) + 0, n[0]);
Write32(XmmRexrReg(m, rde) + 4, n[1]);
}
static void OpVdqWpdCvtpd2dq(struct Machine *m, uint32_t rde) {
uint8_t *p;
unsigned i;
int32_t n[2];
union DoublePun d[2];
p = GetModrmRegisterXmmPointerRead16(m, rde);
d[0].i = Read64(p + 0);
d[1].i = Read64(p + 8);
for (i = 0; i < 2; ++i) n[i] = SseRoundDouble(m, d[i].f);
Write32(XmmRexrReg(m, rde) + 0, n[0]);
Write32(XmmRexrReg(m, rde) + 4, n[1]);
}
static void OpCvt(struct Machine *m, uint32_t rde, unsigned long op) {
switch (op | Rep(rde) | Osz(rde)) {
case kOpCvt0f2a + 0:
OpVpsQpiCvtpi2ps(m, rde);
break;
case kOpCvt0f2a + 1:
OpVpdQpiCvtpi2pd(m, rde);
break;
case kOpCvt0f2a + 2:
OpVsdEdqpCvtsi2sd(m, rde);
break;
case kOpCvt0f2a + 3:
OpVssEdqpCvtsi2ss(m, rde);
break;
case kOpCvtt0f2c + 0:
OpPpiWpsqCvttps2pi(m, rde);
break;
case kOpCvtt0f2c + 1:
OpPpiWpdCvttpd2pi(m, rde);
break;
case kOpCvtt0f2c + 2:
OpGdqpWsdCvttsd2si(m, rde);
break;
case kOpCvtt0f2c + 3:
OpGdqpWssCvttss2si(m, rde);
break;
case kOpCvt0f2d + 0:
OpPpiWpsqCvtps2pi(m, rde);
break;
case kOpCvt0f2d + 1:
OpPpiWpdCvtpd2pi(m, rde);
break;
case kOpCvt0f2d + 2:
OpGdqpWsdCvtsd2si(m, rde);
break;
case kOpCvt0f2d + 3:
OpGdqpWssCvtss2si(m, rde);
break;
case kOpCvt0f5a + 0:
OpVpdWpsCvtps2pd(m, rde);
break;
case kOpCvt0f5a + 1:
OpVpsWpdCvtpd2ps(m, rde);
break;
case kOpCvt0f5a + 2:
OpVssWsdCvtsd2ss(m, rde);
break;
case kOpCvt0f5a + 3:
OpVsdWssCvtss2sd(m, rde);
break;
case kOpCvt0f5b + 0:
OpVpsWdqCvtdq2ps(m, rde);
break;
case kOpCvt0f5b + 1:
OpVdqWpsCvtps2dq(m, rde);
break;
case kOpCvt0f5b + 3:
OpVdqWpsCvttps2dq(m, rde);
break;
case kOpCvt0fE6 + 1:
OpVdqWpdCvtpd2dq(m, rde);
break;
case kOpCvt0fE6 + 2:
OpVdqWpdCvttpd2dq(m, rde);
break;
case kOpCvt0fE6 + 3:
OpVpdWdqCvtdq2pd(m, rde);
break;
default:
OpUd(m, rde);
}
}
void OpCvt0f2a(struct Machine *m, uint32_t rde) {
OpCvt(m, rde, kOpCvt0f2a);
}
void OpCvtt0f2c(struct Machine *m, uint32_t rde) {
OpCvt(m, rde, kOpCvtt0f2c);
}
void OpCvt0f2d(struct Machine *m, uint32_t rde) {
OpCvt(m, rde, kOpCvt0f2d);
}
void OpCvt0f5a(struct Machine *m, uint32_t rde) {
OpCvt(m, rde, kOpCvt0f5a);
}
void OpCvt0f5b(struct Machine *m, uint32_t rde) {
OpCvt(m, rde, kOpCvt0f5b);
}
void OpCvt0fE6(struct Machine *m, uint32_t rde) {
OpCvt(m, rde, kOpCvt0fE6);
}

View file

@ -1,16 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_CVT_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_CVT_H_
#include "tool/build/lib/machine.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
void OpCvt0f2a(struct Machine *, uint32_t);
void OpCvtt0f2c(struct Machine *, uint32_t);
void OpCvt0f2d(struct Machine *, uint32_t);
void OpCvt0f5a(struct Machine *, uint32_t);
void OpCvt0f5b(struct Machine *, uint32_t);
void OpCvt0fE6(struct Machine *, uint32_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_CVT_H_ */

View file

@ -1,47 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/elf/elf.h"
#include "libc/log/check.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
#include "libc/x/x.h"
#include "tool/build/lib/loader.h"
void LoadDebugSymbols(struct Elf *elf) {
int fd;
size_t n;
void *elfmap;
struct stat st;
const char *path;
if (elf->ehdr && GetElfSymbolTable(elf->ehdr, elf->size, &n) && n) return;
DCHECK_NOTNULL(elf->prog);
if ((fd = open(xstrcat(elf->prog, ".dbg"), O_RDONLY)) != -1) {
if (fstat(fd, &st) != -1 &&
(elfmap = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) !=
MAP_FAILED) {
elf->ehdr = elfmap;
elf->size = st.st_size;
}
close(fd);
}
}

View file

@ -1,296 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/bing.internal.h"
#include "libc/fmt/itoa.h"
#include "libc/intrin/tpenc.h"
#include "libc/limits.h"
#include "libc/log/check.h"
#include "libc/mem/arraylist2.internal.h"
#include "libc/mem/mem.h"
#include "libc/str/str.h"
#include "third_party/xed/x86.h"
#include "tool/build/lib/demangle.h"
#include "tool/build/lib/dis.h"
#include "tool/build/lib/endian.h"
#include "tool/build/lib/high.h"
#include "tool/build/lib/memory.h"
#include "tool/build/lib/modrm.h"
#define ADDRLEN 8
#define BYTELEN 11
#define PFIXLEN 4
#define NAMELEN 8
#define CODELEN 40
#define CODELIM 15
#define DATALIM 8
#define PIVOTOP pos_opcode
static char *DisColumn(char *p2, char *p1, long need) {
char *p;
unsigned long have;
DCHECK_GE(p2, p1);
have = p2 - p1;
p = p2;
do {
*p++ = ' ';
} while (++have < need);
*p = '\0';
return p;
}
static char *DisOctets(char *p, const uint8_t *d, size_t n) {
size_t i;
for (i = 0; i < n; ++i) {
if (i) *p++ = ',';
*p++ = '0';
*p++ = 'x';
*p++ = "0123456789abcdef"[(d[i] & 0xf0) >> 4];
*p++ = "0123456789abcdef"[(d[i] & 0x0f) >> 0];
}
*p = '\0';
return p;
}
static char *DisByte(char *p, const uint8_t *d, size_t n) {
p = HighStart(p, g_high.keyword);
p = DisColumn(stpcpy(p, ".byte"), p, NAMELEN);
p = HighEnd(p);
p = DisOctets(p, d, n);
return p;
}
static char *DisError(struct Dis *d, char *p) {
p = DisColumn(DisByte(p, d->xedd->bytes, MIN(15, d->xedd->length)), p,
CODELEN);
p = HighStart(p, g_high.comment);
*p++ = '#';
*p++ = ' ';
p = stpcpy(p, IndexDoubleNulString(kXedErrorNames, d->xedd->op.error));
p = HighEnd(p);
*p = '\0';
return p;
}
static char *DisAddr(struct Dis *d, char *p) {
int64_t x = d->addr;
if (0 <= x && x < 0x10fff0) {
return p + uint64toarray_fixed16(x, p, 24);
} else if (INT_MIN <= x && x <= INT_MAX) {
return p + uint64toarray_fixed16(x, p, 32);
} else {
return p + uint64toarray_fixed16(x, p, 48);
}
}
static char *DisRaw(struct Dis *d, char *p) {
long i;
int plen;
if (0 <= d->addr && d->addr < 0x10fff0) {
plen = 2;
} else {
plen = PFIXLEN;
}
for (i = 0; i < plen - MIN(plen, d->xedd->op.PIVOTOP); ++i) {
*p++ = ' ';
*p++ = ' ';
}
for (i = 0; i < MIN(15, d->xedd->length); ++i) {
if (i == d->xedd->op.PIVOTOP) *p++ = ' ';
*p++ = "0123456789abcdef"[(d->xedd->bytes[i] & 0xf0) >> 4];
*p++ = "0123456789abcdef"[(d->xedd->bytes[i] & 0x0f) >> 0];
}
*p = '\0';
return p;
}
static char *DisCode(struct Dis *d, char *p) {
char optspecbuf[128];
if (!d->xedd->op.error) {
return DisInst(d, p, DisSpec(d->xedd, optspecbuf));
} else {
return DisError(d, p);
}
}
static char *DisLineCode(struct Dis *d, char *p) {
int blen, plen;
if (0 <= d->addr && d->addr < 0x10fff0) {
plen = 2;
blen = 6;
} else {
blen = BYTELEN;
plen = PFIXLEN;
}
p = DisColumn(DisAddr(d, p), p, ADDRLEN);
p = DisColumn(DisRaw(d, p), p, plen * 2 + 1 + blen * 2);
p = DisCode(d, p);
return p;
}
static char *DisLineData(struct Dis *d, char *p, const uint8_t *b, size_t n) {
size_t i;
uint64_t w;
p = DisColumn(DisAddr(d, p), p, ADDRLEN);
p = DisColumn(DisByte(p, b, n), p, 64);
p = HighStart(p, g_high.comment);
*p++ = '#';
*p++ = ' ';
for (i = 0; i < n; ++i) {
w = _tpenc(bing(b[i], 0));
do {
*p++ = w;
} while ((w >>= 8));
}
p = HighEnd(p);
*p = '\0';
return p;
}
static char *DisLabel(struct Dis *d, char *p, const char *name) {
p = DisColumn(DisAddr(d, p), p, ADDRLEN);
p = HighStart(p, g_high.label);
p = Demangle(p, name, DIS_MAX_SYMBOL_LENGTH);
p = HighEnd(p);
*p++ = ':';
*p = '\0';
return p;
}
long DisFind(struct Dis *d, int64_t addr) {
int l, r, m, i;
l = 0;
r = d->ops.i - 1;
while (l <= r) {
m = (l + r) >> 1;
if (d->ops.p[m].addr < addr) {
l = m + 1;
} else if (d->ops.p[m].addr > addr) {
r = m - 1;
} else {
return m;
}
}
return -1;
}
static long DisAppendOpLines(struct Dis *d, struct Machine *m, int64_t addr) {
void *r;
int64_t ip;
unsigned k;
struct DisOp op;
long i, n, symbol;
uint8_t *p, b[15];
n = 15;
ip = addr - Read64(m->cs);
if ((symbol = DisFindSym(d, ip)) != -1) {
if (d->syms.p[symbol].addr <= ip &&
ip < d->syms.p[symbol].addr + d->syms.p[symbol].size) {
n = d->syms.p[symbol].size - (ip - d->syms.p[symbol].addr);
}
if (ip == d->syms.p[symbol].addr && d->syms.p[symbol].name) {
op.addr = addr;
op.size = 0;
op.active = true;
d->addr = addr;
DisLabel(d, d->buf, d->syms.stab + d->syms.p[symbol].name);
if (!(op.s = strdup(d->buf))) return -1;
APPEND(&d->ops.p, &d->ops.i, &d->ops.n, &op);
}
}
n = MAX(1, MIN(15, n));
if (!(r = FindReal(m, addr))) return -1;
k = 0x1000 - (addr & 0xfff);
if (n <= k) {
p = r;
} else {
p = b;
memcpy(b, r, k);
if ((r = FindReal(m, addr + k))) {
memcpy(b + k, r, n - k);
} else {
n = k;
}
}
xed_decoded_inst_zero_set_mode(d->xedd, m->mode);
xed_instruction_length_decode(d->xedd, p, n);
d->xedd->op.rde = EncodeRde(d->xedd);
n = d->xedd->op.error ? 1 : d->xedd->length;
op.addr = addr;
op.size = n;
op.active = true;
op.s = NULL;
APPEND(&d->ops.p, &d->ops.i, &d->ops.n, &op);
return n;
}
long Dis(struct Dis *d, struct Machine *m, uint64_t addr, uint64_t ip,
int lines) {
int64_t i, j, symbol;
DisFreeOps(&d->ops);
if ((symbol = DisFindSym(d, addr)) != -1 &&
(d->syms.p[symbol].addr < addr &&
addr < d->syms.p[symbol].addr + d->syms.p[symbol].size)) {
for (i = d->syms.p[symbol].addr; i < addr; i += j) {
if ((j = DisAppendOpLines(d, m, i)) == -1) return -1;
}
}
for (i = 0; i < lines; ++i, addr += j) {
if ((j = DisAppendOpLines(d, m, addr)) == -1) return -1;
}
return 0;
}
const char *DisGetLine(struct Dis *d, struct Machine *m, size_t i) {
void *r[2];
uint8_t b[15];
if (i >= d->ops.i) return "";
if (d->ops.p[i].s) return d->ops.p[i].s;
DCHECK_LE(d->ops.p[i].size, 15);
xed_decoded_inst_zero_set_mode(d->xedd, m->mode);
xed_instruction_length_decode(
d->xedd, AccessRam(m, d->ops.p[i].addr, d->ops.p[i].size, r, b, true),
d->ops.p[i].size);
d->xedd->op.rde = EncodeRde(d->xedd);
d->m = m;
d->addr = d->ops.p[i].addr;
CHECK_LT(DisLineCode(d, d->buf) - d->buf, sizeof(d->buf));
return d->buf;
}
void DisFreeOp(struct DisOp *o) {
free(o->s);
}
void DisFreeOps(struct DisOps *ops) {
long i;
for (i = 0; i < ops->i; ++i) {
DisFreeOp(&ops->p[i]);
}
free(ops->p);
bzero(ops, sizeof(*ops));
}
void DisFree(struct Dis *d) {
long i;
DisFreeOps(&d->ops);
free(d->edges.p);
free(d->loads.p);
free(d->syms.p);
bzero(d, sizeof(*d));
}

View file

@ -1,74 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_DIS_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_DIS_H_
#include "third_party/xed/x86.h"
#include "tool/build/lib/loader.h"
#include "tool/build/lib/machine.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define DIS_MAX_SYMBOL_LENGTH 32
struct Dis {
struct DisOps {
size_t i, n;
struct DisOp {
int64_t addr;
uint8_t size;
bool active;
char *s;
} * p;
} ops;
struct DisLoads {
size_t i, n;
struct DisLoad {
int64_t addr;
uint64_t size;
bool istext;
} * p;
} loads;
struct DisSyms {
size_t i, n;
struct DisSym {
int64_t addr;
int unique;
int size;
int name;
char rank;
bool iscode;
bool isabs;
} * p;
const char *stab;
} syms;
struct DisEdges {
size_t i, n;
struct DisEdge {
int64_t src;
int64_t dst;
} * p;
} edges;
struct XedDecodedInst xedd[1];
struct Machine *m; /* for the segment registers */
uint64_t addr; /* current effective address */
char buf[512];
};
extern bool g_disisprog_disable;
long Dis(struct Dis *, struct Machine *, uint64_t, uint64_t, int);
long DisFind(struct Dis *, int64_t);
void DisFree(struct Dis *);
void DisFreeOp(struct DisOp *);
void DisFreeOps(struct DisOps *);
void DisLoadElf(struct Dis *, struct Elf *);
long DisFindSym(struct Dis *, int64_t);
long DisFindSymByName(struct Dis *, const char *);
bool DisIsText(struct Dis *, int64_t);
bool DisIsProg(struct Dis *, int64_t);
char *DisInst(struct Dis *, char *, const char *);
char *DisArg(struct Dis *, char *, const char *);
const char *DisSpec(struct XedDecodedInst *, char *);
const char *DisGetLine(struct Dis *, struct Machine *, size_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_DIS_H_ */

View file

@ -1,747 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/itoa.h"
#include "libc/intrin/bits.h"
#include "libc/limits.h"
#include "libc/log/check.h"
#include "libc/macros.internal.h"
#include "libc/str/str.h"
#include "tool/build/lib/demangle.h"
#include "tool/build/lib/dis.h"
#include "tool/build/lib/endian.h"
#include "tool/build/lib/high.h"
#include "tool/build/lib/modrm.h"
static const char kRiz[2][4] = {"eiz", "riz"};
static const char kRip[2][4] = {"eip", "rip"};
static const char kSka[4][4] = {"", ",2", ",4", ",8"};
static const char kSeg[8][3] = {"es", "cs", "ss", "ds", "fs", "gs"};
static const char kCtl[8][4] = {"cr0", "wut", "cr2", "cr3",
"cr4", "wut", "wut", "wut"};
static const char kBreg[2][2][8][5] = {
{{"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"},
{"al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil"}},
{{"wut", "wut", "wut", "wut", "wut", "wut", "wut", "wut"},
{"r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"}},
};
static const char kGreg[2][2][2][8][5] = {
{{{"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"},
{"r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"}},
{{"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"},
{"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}}},
{{{"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"},
{"r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"}},
{{"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"},
{"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}}},
};
static int64_t RipRelative(struct Dis *d, int64_t i) {
return d->addr + d->xedd->length + i;
}
static int64_t ZeroExtend(uint32_t rde, int64_t i) {
switch (Mode(rde)) {
case XED_MODE_REAL:
return i & 0xffff;
case XED_MODE_LEGACY:
return i & 0xffffffff;
default:
return i;
}
}
static int64_t Unrelative(uint32_t rde, int64_t i) {
switch (Eamode(rde)) {
case XED_MODE_REAL:
return i & 0xffff;
case XED_MODE_LEGACY:
return i & 0xffffffff;
default:
return i;
}
}
static int64_t GetSeg(struct Dis *d, uint32_t rde, unsigned char *s) {
switch (Sego(rde) ? Sego(rde) : d->xedd->op.hint) {
default:
return Read64(s);
case 1:
return Read64(d->m->es);
case 2:
return Read64(d->m->cs);
case 3:
return Read64(d->m->ss);
case 4:
return Read64(d->m->ds);
}
}
static const char *GetAddrReg(struct Dis *d, uint32_t rde, uint8_t x,
uint8_t r) {
return kGreg[Eamode(rde) == XED_MODE_REAL][Eamode(rde) == XED_MODE_LONG]
[x & 1][r & 7];
}
static char *DisRegister(char *p, const char *s) {
p = HighStart(p, g_high.reg);
*p++ = '%';
p = stpcpy(p, s);
p = HighEnd(p);
return p;
}
static char *DisComment(char *p, const char *s) {
p = HighStart(p, g_high.comment);
p = stpcpy(p, s);
p = HighEnd(p);
return p;
}
static char *DisRegisterByte(struct Dis *d, uint32_t rde, char *p, bool g,
int r) {
return DisRegister(p, kBreg[g][Rex(rde)][r]);
}
static char *DisRegisterWord(struct Dis *d, uint32_t rde, char *p, bool g,
int r) {
return DisRegister(p, kGreg[Osz(rde)][Rexw(rde)][g][r]);
}
static char *DisInt(char *p, int64_t x) {
if (-15 <= x && x <= 15) {
p = FormatInt64(p, x);
} else if (x == INT64_MIN) {
p = stpcpy(p, "-0x");
p += uint64toarray_radix16(INT64_MIN, p);
} else if (x < 0 && -x < 0xFFFFFFFF) {
p = stpcpy(p, "-0x");
p += uint64toarray_radix16(-x, p);
} else {
p = stpcpy(p, "0x");
p += uint64toarray_radix16(x, p);
}
return p;
}
static char *DisSymImpl(struct Dis *d, char *p, int64_t x, long sym) {
int64_t addend;
const char *name;
addend = x - d->syms.p[sym].addr;
name = d->syms.stab + d->syms.p[sym].name;
p = Demangle(p, name, DIS_MAX_SYMBOL_LENGTH);
if (addend) {
*p++ = '+';
p = DisInt(p, addend);
}
return p;
}
static char *DisSym(struct Dis *d, char *p, int64_t value, int64_t addr) {
long sym;
if ((sym = DisFindSym(d, addr)) != -1 && d->syms.p[sym].name) {
return DisSymImpl(d, p, addr, sym);
} else {
return DisInt(p, value);
}
}
static char *DisSymLiteral(struct Dis *d, uint32_t rde, char *p, uint64_t addr,
uint64_t ip) {
*p++ = '$';
p = HighStart(p, g_high.literal);
p = DisSym(d, p, addr, addr);
p = HighEnd(p);
return p;
}
static char *DisGvqp(struct Dis *d, uint32_t rde, char *p) {
return DisRegisterWord(d, rde, p, Rexr(rde), ModrmReg(rde));
}
static char *DisGdqp(struct Dis *d, uint32_t rde, char *p) {
return DisRegister(p, kGreg[0][Rexw(rde)][Rexr(rde)][ModrmReg(rde)]);
}
static char *DisGb(struct Dis *d, uint32_t rde, char *p) {
return DisRegisterByte(d, rde, p, Rexr(rde), ModrmReg(rde));
}
static char *DisSego(struct Dis *d, uint32_t rde, char *p) {
int seg;
seg = Sego(rde) ? Sego(rde) : d->xedd->op.hint;
if (seg) {
p = DisRegister(p, kSeg[seg - 1]);
*p++ = ':';
}
return p;
}
static bool IsRealModrmAbsolute(uint32_t rde) {
return Eamode(rde) == XED_MODE_REAL && ModrmRm(rde) == 6 && !ModrmMod(rde);
}
static char *DisDisp(struct Dis *d, uint32_t rde, char *p) {
bool rela;
int64_t disp;
if (ModrmMod(rde) == 0b01 || ModrmMod(rde) == 0b10 || IsRipRelative(rde) ||
IsRealModrmAbsolute(rde) ||
(Eamode(rde) != XED_MODE_REAL && ModrmMod(rde) == 0b00 &&
ModrmRm(rde) == 0b100 && SibBase(d->xedd) == 0b101)) {
disp = d->xedd->op.disp;
if (IsRipRelative(rde)) {
if (Mode(rde) == XED_MODE_LONG) {
disp = RipRelative(d, disp);
rela = true;
} else {
disp = Unrelative(rde, disp);
rela = false;
}
} else if (IsRealModrmAbsolute(rde)) {
disp = Unrelative(rde, disp);
rela = false;
} else {
rela = true;
}
p = DisSym(d, p, disp, disp);
}
return p;
}
static char *DisBis(struct Dis *d, uint32_t rde, char *p) {
const char *base, *index, *scale;
base = index = scale = NULL;
if (Eamode(rde) != XED_MODE_REAL) {
if (!SibExists(rde)) {
DCHECK(!d->xedd->op.has_sib);
if (IsRipRelative(rde)) {
if (Mode(rde) == XED_MODE_LONG) {
base = kRip[Eamode(rde) == XED_MODE_LONG];
}
} else {
base = GetAddrReg(d, rde, Rexb(rde), ModrmRm(rde));
}
} else if (!SibIsAbsolute(d->xedd, rde)) {
if (SibHasBase(d->xedd, rde)) {
base = GetAddrReg(d, rde, Rexb(rde), SibBase(d->xedd));
}
if (SibHasIndex(d->xedd)) {
index = GetAddrReg(d, rde, Rexx(d->xedd), SibIndex(d->xedd));
} else if (d->xedd->op.scale) {
index = kRiz[Eamode(rde) == XED_MODE_LONG];
}
scale = kSka[d->xedd->op.scale];
}
} else {
switch (ModrmRm(rde)) {
case 0:
base = "bx";
index = "si";
break;
case 1:
base = "bx";
index = "di";
break;
case 2:
base = "bp";
index = "si";
break;
case 3:
base = "bp";
index = "di";
break;
case 4:
base = "si";
break;
case 5:
base = "di";
break;
case 6:
if (ModrmMod(rde)) base = "bp";
break;
case 7:
base = "bx";
break;
default:
__builtin_unreachable();
}
}
if (base || index) {
*p++ = '(';
if (base) {
p = DisRegister(p, base);
}
if (index) {
*p++ = ',';
p = DisRegister(p, index);
if (scale) {
p = stpcpy(p, scale);
}
}
*p++ = ')';
}
*p = '\0';
return p;
}
static char *DisM(struct Dis *d, uint32_t rde, char *p) {
p = DisSego(d, rde, p);
p = DisDisp(d, rde, p);
p = DisBis(d, rde, p);
return p;
}
static char *DisRegMem(struct Dis *d, uint32_t rde, char *p,
char *f(struct Dis *, uint32_t, char *)) {
if (IsModrmRegister(rde)) {
return f(d, rde, p);
} else {
return DisM(d, rde, p);
}
}
static dontinline char *DisE(struct Dis *d, uint32_t rde, char *p,
char *f(struct Dis *, uint32_t, char *, bool,
int)) {
if (IsModrmRegister(rde)) {
return f(d, rde, p, Rexb(rde), ModrmRm(rde));
} else {
return DisM(d, rde, p);
}
}
static char *DisEb(struct Dis *d, uint32_t rde, char *p) {
return DisE(d, rde, p, DisRegisterByte);
}
static char *DisEvqp(struct Dis *d, uint32_t rde, char *p) {
return DisE(d, rde, p, DisRegisterWord);
}
static char *DisRv(struct Dis *d, uint32_t rde, char *p) {
return DisRegister(p, kGreg[Osz(rde)][0][Rexb(rde)][ModrmRm(rde)]);
}
static char *DisRvqp(struct Dis *d, uint32_t rde, char *p) {
return DisRegister(p, kGreg[Osz(rde)][Rexw(rde)][Rexb(rde)][ModrmRm(rde)]);
}
static char *DisRdqp(struct Dis *d, uint32_t rde, char *p) {
return DisRegister(p, kGreg[0][Rexw(rde)][Rexb(rde)][ModrmRm(rde)]);
}
static char *DisEdqp(struct Dis *d, uint32_t rde, char *p) {
return DisRegMem(d, rde, p, DisRdqp);
}
static char *DisEv(struct Dis *d, uint32_t rde, char *p) {
return DisRegMem(d, rde, p, DisRv);
}
static char *DisGvq(struct Dis *d, uint32_t rde, char *p, int r) {
const char *s;
if (Mode(rde) == XED_MODE_LONG) {
s = kGreg[Osz(rde)][!Osz(rde)][Rexb(rde)][r];
} else {
s = kGreg[Osz(rde)][0][Rexb(rde)][r];
}
return DisRegister(p, s);
}
static char *DisZvq(struct Dis *d, uint32_t rde, char *p) {
return DisGvq(d, rde, p, ModrmSrm(rde));
}
static char *DisEvqReg(struct Dis *d, uint32_t rde, char *p) {
return DisGvq(d, rde, p, ModrmRm(rde));
}
static char *DisEvq(struct Dis *d, uint32_t rde, char *p) {
return DisRegMem(d, rde, p, DisEvqReg);
}
static char *DisEdReg(struct Dis *d, uint32_t rde, char *p) {
return DisRegister(p, kGreg[0][0][Rexb(rde)][ModrmRm(rde)]);
}
static char *DisEd(struct Dis *d, uint32_t rde, char *p) {
return DisRegMem(d, rde, p, DisEdReg);
}
static char *DisEqReg(struct Dis *d, uint32_t rde, char *p) {
const char *r;
if (Mode(rde) == XED_MODE_LONG) {
r = kGreg[0][1][Rexb(rde)][ModrmRm(rde)];
} else {
r = kGreg[Osz(rde)][0][Rexb(rde)][ModrmRm(rde)];
}
return DisRegister(p, r);
}
static char *DisEq(struct Dis *d, uint32_t rde, char *p) {
return DisRegMem(d, rde, p, DisEqReg);
}
static char *DisZvqp(struct Dis *d, uint32_t rde, char *p) {
return DisRegisterWord(d, rde, p, Rexb(rde), ModrmSrm(rde));
}
static char *DisZb(struct Dis *d, uint32_t rde, char *p) {
return DisRegisterByte(d, rde, p, Rexb(rde), ModrmSrm(rde));
}
static char *DisEax(struct Dis *d, uint32_t rde, char *p) {
return DisRegister(p, kGreg[Osz(rde)][0][0][0]);
}
static char *DisRax(struct Dis *d, uint32_t rde, char *p) {
return DisRegister(p, kGreg[Osz(rde)][Rexw(rde)][0][0]);
}
static char *DisRdx(struct Dis *d, uint32_t rde, char *p) {
return DisRegister(p, kGreg[Osz(rde)][Rexw(rde)][0][2]);
}
static char *DisPort(struct Dis *d, uint32_t rde, char *p) {
*p++ = '(';
p = DisRegister(p, kGreg[1][0][0][2]);
*p++ = ')';
*p = '\0';
return p;
}
static char *DisCd(struct Dis *d, uint32_t rde, char *p) {
return DisRegister(p, kCtl[ModrmReg(rde)]);
}
static char *DisHd(struct Dis *d, uint32_t rde, char *p) {
return DisRegister(p, kGreg[0][Mode(rde) == XED_MODE_LONG][0][ModrmRm(rde)]);
}
static char *DisImm(struct Dis *d, uint32_t rde, char *p) {
return DisSymLiteral(d, rde, p, d->xedd->op.uimm0,
ZeroExtend(rde, d->xedd->op.uimm0));
}
static char *DisRvds(struct Dis *d, uint32_t rde, char *p) {
return DisSymLiteral(d, rde, p, d->xedd->op.disp, d->xedd->op.disp);
}
static char *DisKpvds(struct Dis *d, uint32_t rde, char *p, uint64_t x) {
*p++ = '$';
p = HighStart(p, g_high.literal);
p = DisInt(p, x);
p = HighEnd(p);
return p;
}
static char *DisKvds(struct Dis *d, uint32_t rde, char *p) {
return DisKpvds(d, rde, p, d->xedd->op.uimm0);
}
static char *DisPvds(struct Dis *d, uint32_t rde, char *p) {
return DisKpvds(d, rde, p,
d->xedd->op.disp & (Osz(rde) ? 0xffff : 0xffffffff));
}
static char *DisOne(struct Dis *d, uint32_t rde, char *p) {
*p++ = '$';
p = HighStart(p, g_high.literal);
p = stpcpy(p, "1");
p = HighEnd(p);
return p;
}
static char *DisJbs(struct Dis *d, uint32_t rde, char *p) {
if (d->xedd->op.disp > 0) *p++ = '+';
p = FormatInt64(p, d->xedd->op.disp);
return p;
}
static char *DisJb(struct Dis *d, uint32_t rde, char *p) {
if (d->xedd->op.disp > 0) *p++ = '+';
p = FormatUint32(p, d->xedd->op.disp & 0xff);
return p;
}
static char *DisJvds(struct Dis *d, uint32_t rde, char *p) {
return DisSym(d, p, RipRelative(d, d->xedd->op.disp),
RipRelative(d, d->xedd->op.disp) - Read64(d->m->cs));
}
static char *DisAbs(struct Dis *d, uint32_t rde, char *p) {
return DisSym(d, p, d->xedd->op.disp, d->xedd->op.disp);
}
static char *DisSw(struct Dis *d, uint32_t rde, char *p) {
if (kSeg[ModrmReg(rde)][0]) p = DisRegister(p, kSeg[ModrmReg(rde)]);
return p;
}
static char *DisSpecialAddr(struct Dis *d, uint32_t rde, char *p, int r) {
*p++ = '(';
p = DisRegister(p, GetAddrReg(d, rde, 0, r));
*p++ = ')';
*p = '\0';
return p;
}
static char *DisY(struct Dis *d, uint32_t rde, char *p) {
return DisSpecialAddr(d, rde, p, 7); // es:di
}
static char *DisX(struct Dis *d, uint32_t rde, char *p) {
p = DisSego(d, rde, p);
return DisSpecialAddr(d, rde, p, 6); // ds:si
}
static char *DisBBb(struct Dis *d, uint32_t rde, char *p) {
p = DisSego(d, rde, p);
return DisSpecialAddr(d, rde, p, 3); // ds:bx
}
static char *DisXmm(struct Dis *d, uint32_t rde, char *p, const char *s,
int reg) {
p = HighStart(p, g_high.reg);
*p++ = '%';
p = stpcpy(p, s);
p = FormatUint32(p, reg);
p = HighEnd(p);
return p;
}
static char *DisNq(struct Dis *d, uint32_t rde, char *p) {
return DisXmm(d, rde, p, "mm", ModrmRm(rde));
}
static char *DisPq(struct Dis *d, uint32_t rde, char *p) {
return DisXmm(d, rde, p, "mm", ModrmReg(rde));
}
static char *DisUq(struct Dis *d, uint32_t rde, char *p) {
return DisXmm(d, rde, p, "xmm", RexbRm(rde));
}
static char *DisUdq(struct Dis *d, uint32_t rde, char *p) {
return DisXmm(d, rde, p, "xmm", RexbRm(rde));
}
static char *DisVdq(struct Dis *d, uint32_t rde, char *p) {
return DisXmm(d, rde, p, "xmm", RexrReg(rde));
}
static char *DisQq(struct Dis *d, uint32_t rde, char *p) {
return DisRegMem(d, rde, p, DisNq);
}
static char *DisEst(struct Dis *d, uint32_t rde, char *p) {
p = DisRegister(p, "st");
if (ModrmRm(rde) != 0) {
*p++ = '(';
*p++ = '0' + ModrmRm(rde);
*p++ = ')';
*p = '\0';
}
return p;
}
static char *DisEst1(struct Dis *d, uint32_t rde, char *p) {
if (ModrmRm(rde) != 1) {
p = DisEst(d, rde, p);
} else {
*p = '\0';
}
return p;
}
static char *DisEssr(struct Dis *d, uint32_t rde, char *p) {
return DisRegMem(d, rde, p, DisEst);
}
static char *DisWps(struct Dis *d, uint32_t rde, char *p) {
return DisRegMem(d, rde, p, DisUdq);
}
#define DisEdr DisM
#define DisEqp DisEq
#define DisEsr DisM
#define DisGv DisGvqp
#define DisIb DisImm
#define DisIbs DisImm
#define DisIbss DisImm
#define DisIvds DisImm
#define DisIvqp DisImm
#define DisIvs DisImm
#define DisIw DisImm
#define DisMdi DisM
#define DisMdq DisM
#define DisMdqp DisM
#define DisMdr DisM
#define DisMe DisM
#define DisMer DisM
#define DisMp DisM
#define DisMps DisM
#define DisMq DisM
#define DisMqi DisM
#define DisMs DisM
#define DisMsr DisEssr
#define DisMw DisM
#define DisMwi DisM
#define DisOb DisAbs
#define DisOvqp DisAbs
#define DisPpi DisPq
#define DisQpi DisQq
#define DisVpd DisVdq
#define DisVps DisVdq
#define DisVq DisVdq
#define DisVsd DisVdq
#define DisVss DisVdq
#define DisWdq DisWps
#define DisWpd DisWps
#define DisWpsq DisWps
#define DisWq DisWps
#define DisWsd DisWps
#define DisWss DisWps
#define DisXb DisX
#define DisXv DisX
#define DisXvqp DisX
#define DisYb DisY
#define DisYv DisY
#define DisYvqp DisY
#define DisZv DisZvqp
static const struct DisArg {
char s[8];
char *(*f)(struct Dis *, uint32_t, char *);
} kDisArgs[] = /* <sorted> */ {
{"$1", DisOne}, //
{"%Cd", DisCd}, //
{"%Gb", DisGb}, //
{"%Gdqp", DisGdqp}, //
{"%Gv", DisGv}, //
{"%Gvqp", DisGvqp}, //
{"%Hd", DisHd}, //
{"%Nq", DisNq}, //
{"%Ppi", DisPpi}, //
{"%Pq", DisPq}, //
{"%Rdqp", DisRdqp}, //
{"%Rvqp", DisRvqp}, //
{"%Sw", DisSw}, //
{"%Udq", DisUdq}, //
{"%Uq", DisUq}, //
{"%Vdq", DisVdq}, //
{"%Vpd", DisVpd}, //
{"%Vps", DisVps}, //
{"%Vq", DisVq}, //
{"%Vsd", DisVsd}, //
{"%Vss", DisVss}, //
{"%Zb", DisZb}, //
{"%Zv", DisZv}, //
{"%Zvq", DisZvq}, //
{"%Zvqp", DisZvqp}, //
{"%eAX", DisEax}, //
{"%rAX", DisRax}, //
{"%rDX", DisRdx}, //
{"BBb", DisBBb}, //
{"DX", DisPort}, //
{"EST", DisEst}, //
{"EST1", DisEst1}, //
{"ESsr", DisEssr}, //
{"Eb", DisEb}, //
{"Ed", DisEd}, //
{"Edqp", DisEdqp}, //
{"Edr", DisEdr}, //
{"Eq", DisEq}, //
{"Eqp", DisEqp}, //
{"Esr", DisEsr}, //
{"Ev", DisEv}, //
{"Evq", DisEvq}, //
{"Evqp", DisEvqp}, //
{"Ew", DisEvqp}, //
{"Ib", DisIb}, //
{"Ibs", DisIbs}, //
{"Ibss", DisIbss}, //
{"Ivds", DisIvds}, //
{"Ivqp", DisIvqp}, //
{"Ivs", DisIvs}, //
{"Iw", DisIw}, //
{"Jb", DisJb}, //
{"Jbs", DisJbs}, //
{"Jvds", DisJvds}, //
{"Kvds", DisKvds}, //
{"M", DisM}, //
{"Mdi", DisMdi}, //
{"Mdq", DisMdq}, //
{"Mdqp", DisMdqp}, //
{"Mdr", DisMdr}, //
{"Me", DisMe}, //
{"Mer", DisMer}, //
{"Mp", DisMp}, //
{"Mps", DisMps}, //
{"Mq", DisMq}, //
{"Mqi", DisMqi}, //
{"Ms", DisMs}, //
{"Msr", DisMsr}, //
{"Mw", DisMw}, //
{"Mwi", DisMwi}, //
{"Ob", DisOb}, //
{"Ovqp", DisOvqp}, //
{"Pvds", DisPvds}, //
{"Qpi", DisQpi}, //
{"Qq", DisQq}, //
{"Rvds", DisRvds}, //
{"Wdq", DisWdq}, //
{"Wpd", DisWpd}, //
{"Wps", DisWps}, //
{"Wpsq", DisWpsq}, //
{"Wq", DisWq}, //
{"Wsd", DisWsd}, //
{"Wss", DisWss}, //
{"Xb", DisXb}, //
{"Xv", DisXv}, //
{"Xvqp", DisXvqp}, //
{"Yb", DisYb}, //
{"Yv", DisYv}, //
{"Yvqp", DisYvqp}, //
};
char *DisArg(struct Dis *d, char *p, const char *s) {
char k[8];
int m, l, r;
l = 0;
r = ARRAYLEN(kDisArgs) - 1;
strncpy(k, s, 8);
while (l <= r) {
m = (l + r) >> 1;
if (READ64BE(kDisArgs[m].s) < READ64BE(k)) {
l = m + 1;
} else if (READ64BE(kDisArgs[m].s) > READ64BE(k)) {
r = m - 1;
} else {
return kDisArgs[m].f(d, d->xedd->op.rde, p);
}
}
if (*s == '%') {
p = DisRegister(p, s + 1);
} else {
p = stpcpy(p, s);
}
return p;
}

View file

@ -1,220 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/elf/elf.h"
#include "libc/elf/struct/sym.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/mem/alg.h"
#include "libc/mem/mem.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/str/str.h"
#include "tool/build/lib/dis.h"
bool g_disisprog_disable;
static int DisSymCompare(const struct DisSym *a, const struct DisSym *b) {
if (a->addr != b->addr) {
if (a->addr < b->addr) return -1;
if (a->addr > b->addr) return +1;
}
if (a->rank != b->rank) {
if (a->rank > b->rank) return -1;
if (a->rank < b->rank) return +1;
}
if (a->unique != b->unique) {
if (a->unique < b->unique) return -1;
if (a->unique > b->unique) return +1;
}
return 0;
}
static void DisLoadElfLoads(struct Dis *d, struct Elf *elf) {
long i, j, n;
int64_t addr;
uint64_t size;
Elf64_Phdr *phdr;
j = 0;
n = elf->ehdr->e_phnum;
if (d->loads.n < n) {
d->loads.n = n;
d->loads.p = realloc(d->loads.p, d->loads.n * sizeof(*d->loads.p));
CHECK_NOTNULL(d->loads.p);
}
for (i = 0; i < n; ++i) {
phdr = GetElfSegmentHeaderAddress(elf->ehdr, elf->size, i);
if (phdr->p_type != PT_LOAD) continue;
d->loads.p[j].addr = phdr->p_vaddr;
d->loads.p[j].size = phdr->p_memsz;
d->loads.p[j].istext = (phdr->p_flags & PF_X) == PF_X;
++j;
}
d->loads.i = j;
}
static void DisLoadElfSyms(struct Dis *d, struct Elf *elf) {
size_t i, j, n;
int64_t stablen;
const Elf64_Sym *st, *sym;
bool isabs, iscode, isweak, islocal, ishidden, isprotected, isfunc, isobject;
j = 0;
if ((d->syms.stab = GetElfStringTable(elf->ehdr, elf->size)) &&
(st = GetElfSymbolTable(elf->ehdr, elf->size, &n))) {
stablen = (intptr_t)elf->ehdr + elf->size - (intptr_t)d->syms.stab;
if (d->syms.n < n) {
d->syms.n = n;
d->syms.p = realloc(d->syms.p, d->syms.n * sizeof(*d->syms.p));
CHECK_NOTNULL(d->syms.p);
}
for (i = 0; i < n; ++i) {
if (ELF64_ST_TYPE(st[i].st_info) == STT_SECTION ||
ELF64_ST_TYPE(st[i].st_info) == STT_FILE || !st[i].st_name ||
_startswith(d->syms.stab + st[i].st_name, "v_") ||
!(0 <= st[i].st_name && st[i].st_name < stablen) || !st[i].st_value ||
!IsLegalPointer(st[i].st_value)) {
continue;
}
isabs = st[i].st_shndx == SHN_ABS;
isweak = ELF64_ST_BIND(st[i].st_info) == STB_WEAK;
islocal = ELF64_ST_BIND(st[i].st_info) == STB_LOCAL;
ishidden = st[i].st_other == STV_HIDDEN;
isprotected = st[i].st_other == STV_PROTECTED;
isfunc = ELF64_ST_TYPE(st[i].st_info) == STT_FUNC;
isobject = ELF64_ST_TYPE(st[i].st_info) == STT_OBJECT;
d->syms.p[j].unique = i;
d->syms.p[j].size = st[i].st_size;
d->syms.p[j].name = st[i].st_name;
CHECK_GE(st[i].st_value, 0);
d->syms.p[j].addr = st[i].st_value;
d->syms.p[j].rank =
-islocal + -isweak + -isabs + isprotected + isobject + isfunc;
d->syms.p[j].iscode = DisIsText(d, st[i].st_value) ? !isobject : isfunc;
d->syms.p[j].isabs = isabs;
++j;
}
}
d->syms.i = j;
}
static void DisSortSyms(struct Dis *d) {
size_t i, j;
qsort(d->syms.p, d->syms.i, sizeof(struct DisSym), (void *)DisSymCompare);
for (i = 0; i < d->syms.i; ++i) {
if (!strcmp("_end", d->syms.stab + d->syms.p[i].name)) {
d->syms.i = i;
break;
}
}
}
static void DisCanonizeSyms(struct Dis *d) {
int64_t i, j, a;
if (d->syms.i) {
i = 1;
j = 1;
a = d->syms.p[0].addr;
do {
if (d->syms.p[j].addr > a) {
a = d->syms.p[j].addr;
if (j > i) {
d->syms.p[i] = d->syms.p[j];
}
++i;
}
++j;
} while (j < d->syms.i);
d->syms.p = realloc(d->syms.p, sizeof(*d->syms.p) * i);
d->syms.i = i;
d->syms.n = i;
}
for (i = 0; i < d->syms.i; ++i) {
DEBUGF("%012lx-%012lx %s", d->syms.p[i].addr,
d->syms.p[i].addr + (d->syms.p[i].size ? d->syms.p[i].size - 1 : 0),
d->syms.stab + d->syms.p[i].name);
}
}
bool DisIsProg(struct Dis *d, int64_t addr) {
long i;
if (g_disisprog_disable) return true;
for (i = 0; i < d->loads.i; ++i) {
if (addr >= d->loads.p[i].addr &&
addr < d->loads.p[i].addr + d->loads.p[i].size) {
return true;
}
}
return false;
}
bool DisIsText(struct Dis *d, int64_t addr) {
long i;
for (i = 0; i < d->loads.i; ++i) {
if (addr >= d->loads.p[i].addr &&
addr < d->loads.p[i].addr + d->loads.p[i].size) {
return d->loads.p[i].istext;
}
}
return false;
}
long DisFindSym(struct Dis *d, int64_t addr) {
long l, r, m, n;
if (DisIsProg(d, addr)) {
l = 0;
r = d->syms.i;
while (l < r) {
m = (l + r) >> 1;
if (d->syms.p[m].addr > addr) {
r = m;
} else {
l = m + 1;
}
}
// TODO(jart): This was <256 but that broke SectorLISP debugging
// Why did the Cosmo binbase bootloader need this?
if (r && d->syms.p[r - 1].addr < 32) {
return -1;
}
if (r && (addr == d->syms.p[r - 1].addr ||
(addr > d->syms.p[r - 1].addr &&
(addr <= d->syms.p[r - 1].addr + d->syms.p[r - 1].size ||
!d->syms.p[r - 1].size)))) {
return r - 1;
}
}
return -1;
}
long DisFindSymByName(struct Dis *d, const char *s) {
long i;
for (i = 0; i < d->syms.i; ++i) {
if (strcmp(s, d->syms.stab + d->syms.p[i].name) == 0) {
return i;
}
}
return -1;
}
void DisLoadElf(struct Dis *d, struct Elf *elf) {
if (!elf || !elf->ehdr) return;
DisLoadElfLoads(d, elf);
DisLoadElfSyms(d, elf);
DisSortSyms(d);
/* DisCanonizeSyms(d); */
}

View file

@ -1,215 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/log/check.h"
#include "libc/str/str.h"
#include "tool/build/lib/dis.h"
#include "tool/build/lib/high.h"
#include "tool/build/lib/modrm.h"
static const char kJcxz[3][6] = {"jcxz", "jecxz", "jrcxz"};
static const char kAluOp[8][4] = {"add", "or", "adc", "sbb",
"and", "sub", "xor", "cmp"};
static const char kBitOp[8][4] = {"rol", "ror", "rcl", "rcr",
"shl", "shr", "sal", "sar"};
static const char kCc[16][3] = {"o", "no", "b", "ae", "e", "ne", "be", "a",
"s", "ns", "p", "np", "l", "ge", "le", "g"};
static bool IsProbablyByteOp(struct XedDecodedInst *x) {
return !(x->op.opcode & 1);
}
static int IsRepOpcode(struct Dis *d) {
switch (d->xedd->op.opcode & ~1) {
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;
}
}
static char *DisRepPrefix(struct Dis *d, char *p) {
const char *s;
if (Rep(d->xedd->op.rde) && d->xedd->op.map == XED_ILD_MAP0) {
switch (IsRepOpcode(d)) {
case 0:
break;
case 1:
p = stpcpy(p, "rep ");
break;
case 2:
p = stpcpy(p, Rep(d->xedd->op.rde) == 2 ? "repnz " : "repz ");
break;
default:
break;
}
}
return p;
}
static char *DisBranchTaken(struct Dis *d, char *p) {
switch (d->xedd->op.hint) {
case XED_HINT_NTAKEN:
return stpcpy(p, ",pn");
case XED_HINT_TAKEN:
return stpcpy(p, ",pt");
default:
return p;
}
}
static char *DisName(struct Dis *d, char *bp, const char *name,
bool ambiguous) {
char *p, *np;
uint32_t rde;
bool notbyte, notlong, wantsuffix, wantsuffixsd;
p = bp;
rde = d->xedd->op.rde;
if (d->xedd->op.lock) p = stpcpy(p, "lock ");
p = DisRepPrefix(d, p);
if (strcmp(name, "BIT") == 0) {
p = stpcpy(p, kBitOp[ModrmReg(rde)]);
} else if (strcmp(name, "nop") == 0 && d->xedd->op.rep) {
p = stpcpy(p, "pause");
} else if (strcmp(name, "CALL") == 0) {
p = stpcpy(p, "call");
} else if (strcmp(name, "JMP") == 0) {
p = stpcpy(p, "jmp");
} else if (strcmp(name, "jcxz") == 0) {
p = stpcpy(p, kJcxz[Eamode(rde)]);
p = DisBranchTaken(d, p);
} else if (strcmp(name, "loop") == 0 || strcmp(name, "loope") == 0 ||
strcmp(name, "loopne") == 0) {
p = stpcpy(p, name);
if (Eamode(rde) != Mode(rde)) {
*p++ = "wl"[Eamode(rde)];
*p = '\0';
}
p = DisBranchTaken(d, p);
} else if (strcmp(name, "cwtl") == 0) {
if (Osz(rde)) name = "cbtw";
if (Rexw(rde)) name = "cltq";
p = stpcpy(p, name);
} else if (strcmp(name, "cltd") == 0) {
if (Osz(rde)) name = "cwtd";
if (Rexw(rde)) name = "cqto";
p = stpcpy(p, name);
} else {
notbyte = false;
notlong = false;
wantsuffix = false;
wantsuffixsd = false;
for (np = name; *np && (islower(*np) || isdigit(*np)); ++np) {
*p++ = *np;
}
if (strcmp(name, "ALU") == 0) {
p = stpcpy(p, kAluOp[(d->xedd->op.opcode & 070) >> 3]);
} else if (strcmp(name, "ALU2") == 0) {
p = stpcpy(p, kAluOp[ModrmReg(rde)]);
} else if (strcmp(np, "WLQ") == 0) {
notbyte = true;
wantsuffix = true;
} else if (strcmp(np, "CC") == 0) {
p = stpcpy(p, kCc[d->xedd->op.opcode & 15]);
p = DisBranchTaken(d, p);
} else if (strcmp(np, "WQ") == 0) {
notbyte = true;
notlong = Eamode(rde) != XED_MODE_REAL;
wantsuffix = true;
} else if (strcmp(np, "LQ") == 0 || strcmp(np, "WL") == 0) {
notbyte = true;
wantsuffix = true;
} else if (strcmp(np, "SD") == 0) {
notbyte = true;
wantsuffixsd = true;
} else if (strcmp(np, "ABS") == 0) {
if (Rexw(rde)) p = stpcpy(p, "abs");
}
if (wantsuffixsd) {
if (Osz(rde)) {
*p++ = 'd';
} else {
*p++ = 's';
}
} else if (wantsuffix || (ambiguous && !_startswith(name, "f") &&
!_startswith(name, "set"))) {
if (Osz(rde)) {
if (ambiguous || Mode(rde) != XED_MODE_REAL) {
*p++ = 'w';
}
} else if (Rexw(rde)) {
*p++ = 'q';
} else if (ambiguous && !notbyte && IsProbablyByteOp(d->xedd)) {
*p++ = 'b';
} else if (!notlong) {
*p++ = 'l';
}
}
}
*p++ = ' ';
while (p - bp < 8) *p++ = ' ';
*p = '\0';
return p;
}
/**
* Disassembles instruction based on string spec.
* @see DisSpec()
*/
char *DisInst(struct Dis *d, char *p, const char *spec) {
long i, n;
char sbuf[64];
char args[4][256];
char *s, *name, *state;
bool hasarg, hasmodrm, hasregister, hasmemory;
CHECK_EQ(0, (int)d->xedd->op.error);
DCHECK_LT(strlen(spec), 128);
hasarg = false;
hasmodrm = d->xedd->op.has_modrm;
hasmemory = hasmodrm && !IsModrmRegister(d->xedd->op.rde);
hasregister = hasmodrm && IsModrmRegister(d->xedd->op.rde);
name = strtok_r(strcpy(sbuf, spec), " ", &state);
for (n = 0; (s = strtok_r(NULL, " ", &state)); ++n) {
hasarg = true;
hasregister |= *s == '%';
hasmemory |= *s == 'O';
CHECK_LT(DisArg(d, args[n], s) - args[n], sizeof(args[n]));
}
p = HighStart(p, g_high.keyword);
p = DisName(d, p, name, hasarg && !hasregister && hasmemory);
p = HighEnd(p);
for (i = 0; i < n; ++i) {
if (i && args[n - i][0]) {
*p++ = ',';
}
p = stpcpy(p, args[n - i - 1]);
}
return p;
}

File diff suppressed because it is too large Load diff

View file

@ -1,369 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/limits.h"
#include "tool/build/lib/divmul.h"
#include "tool/build/lib/endian.h"
#include "tool/build/lib/flags.h"
#include "tool/build/lib/modrm.h"
#include "tool/build/lib/throw.h"
struct Dubble {
uint64_t lo;
uint64_t hi;
};
static inline struct Dubble DubbleNeg(struct Dubble x) {
struct Dubble d;
d.lo = -x.lo;
d.hi = ~(x.hi - (x.lo - 1 > x.lo));
return d;
}
static inline struct Dubble DubbleShl(struct Dubble x) {
struct Dubble d;
d.lo = x.lo << 1;
d.hi = x.hi << 1 | x.lo >> 63;
return d;
}
static inline struct Dubble DubbleShr(struct Dubble x) {
struct Dubble d;
d.lo = x.lo >> 1 | x.hi << 63;
d.hi = x.hi >> 1;
return d;
}
static inline unsigned DubbleLte(struct Dubble a, struct Dubble b) {
return a.hi == b.hi ? a.lo <= b.lo : a.hi <= b.hi;
}
static struct Dubble DubbleMul(uint64_t a, uint64_t b) {
struct Dubble d;
uint64_t x, y, t;
x = (a & 0xffffffff) * (b & 0xffffffff);
t = x >> 32;
x &= 0xffffffff;
t += (a >> 32) * (b & 0xffffffff);
x += (t & 0xffffffff) << 32;
y = t >> 32;
t = x >> 32;
x &= 0xffffffff;
t += (b >> 32) * (a & 0xffffffff);
x += (t & 0xffffffff) << 32;
y += t >> 32;
y += (a >> 32) * (b >> 32);
d.lo = x;
d.hi = y;
return d;
}
static struct Dubble DubbleImul(uint64_t a, uint64_t b) {
unsigned s, t;
struct Dubble p;
if ((s = a >> 63)) a = -a;
if ((t = b >> 63)) b = -b;
p = DubbleMul(a, b);
return s ^ t ? DubbleNeg(p) : p;
}
static struct Dubble DubbleDiv(struct Dubble a, uint64_t b, uint64_t *r) {
int n, c;
uint64_t s;
struct Dubble d, q, t;
d.lo = b, d.hi = 0;
q.lo = 0, q.hi = 0;
for (n = 0; DubbleLte(d, a) && n < 128; ++n) {
d = DubbleShl(d);
}
for (; n > 0; --n) {
t = a;
d = DubbleShr(d);
q = DubbleShl(q);
s = a.lo, a.lo -= d.lo + 0, c = a.lo > s;
s = a.hi, a.hi -= d.hi + c, c = a.hi > s;
if (c) {
a = t;
} else {
q.lo++;
}
}
*r = a.lo;
return q;
}
static struct Dubble DubbleIdiv(struct Dubble a, uint64_t b, uint64_t *r) {
unsigned s, t;
struct Dubble q;
if ((s = a.hi >> 63)) a = DubbleNeg(a);
if ((t = b >> 63)) b = -b;
q = DubbleDiv(a, b, r);
if (s ^ t) q = DubbleNeg(q);
if (s) *r = -*r;
return q;
}
void OpDivAlAhAxEbSigned(struct Machine *m, uint32_t rde) {
int8_t y, r;
int16_t x, q;
x = Read16(m->ax);
y = Read8(GetModrmRegisterBytePointerRead(m, rde));
if (!y) ThrowDivideError(m);
if (x == INT16_MIN) ThrowDivideError(m);
q = x / y;
r = x % y;
if (q != (int8_t)q) ThrowDivideError(m);
m->ax[0] = q & 0xff;
m->ax[1] = r & 0xff;
}
void OpDivAlAhAxEbUnsigned(struct Machine *m, uint32_t rde) {
uint8_t y, r;
uint16_t x, q;
x = Read16(m->ax);
y = Read8(GetModrmRegisterBytePointerRead(m, rde));
if (!y) ThrowDivideError(m);
q = x / y;
r = x % y;
if (q > 255) ThrowDivideError(m);
m->ax[0] = q & 0xff;
m->ax[1] = r & 0xff;
}
static void OpDivRdxRaxEvqpSigned64(struct Machine *m, uint32_t rde,
uint8_t *p) {
uint64_t d, r;
struct Dubble q;
q.lo = Read64(m->ax);
q.hi = Read64(m->dx);
d = Read64(p);
if (!d) ThrowDivideError(m);
if (!q.lo && q.hi == 0x8000000000000000) ThrowDivideError(m);
q = DubbleIdiv(q, d, &r);
if ((int64_t)q.lo < 0 && (int64_t)q.hi != -1) ThrowDivideError(m);
if ((int64_t)q.lo >= 0 && q.hi) ThrowDivideError(m);
Write64(m->ax, q.lo);
Write64(m->dx, r);
}
static void OpDivRdxRaxEvqpSigned32(struct Machine *m, uint32_t rde,
uint8_t *p) {
int32_t y, r;
int64_t x, q;
x = (uint64_t)Read32(m->dx) << 32 | Read32(m->ax);
y = Read32(p);
if (!y) ThrowDivideError(m);
if (x == INT64_MIN) ThrowDivideError(m);
q = x / y;
r = x % y;
if (q != (int32_t)q) ThrowDivideError(m);
Write64(m->ax, q & 0xffffffff);
Write64(m->dx, r & 0xffffffff);
}
static void OpDivRdxRaxEvqpSigned16(struct Machine *m, uint32_t rde,
uint8_t *p) {
int16_t y, r;
int32_t x, q;
x = (uint32_t)Read16(m->dx) << 16 | Read16(m->ax);
y = Read16(p);
if (!y) ThrowDivideError(m);
if (x == INT32_MIN) ThrowDivideError(m);
q = x / y;
r = x % y;
if (q != (int16_t)q) ThrowDivideError(m);
Write16(m->ax, q);
Write16(m->dx, r);
}
static void OpDivRdxRaxEvqpUnsigned16(struct Machine *m, uint32_t rde,
uint8_t *p) {
uint16_t y, r;
uint32_t x, q;
x = (uint32_t)Read16(m->dx) << 16 | Read16(m->ax);
y = Read16(p);
if (!y) ThrowDivideError(m);
q = x / y;
r = x % y;
if (q > 65535) ThrowDivideError(m);
Write16(m->ax, q);
Write16(m->dx, r);
}
static void OpDivRdxRaxEvqpUnsigned32(struct Machine *m, uint32_t rde,
uint8_t *p) {
uint32_t y, r;
uint64_t x, q;
x = (uint64_t)Read32(m->dx) << 32 | Read32(m->ax);
y = Read32(p);
if (!y) ThrowDivideError(m);
q = x / y;
r = x % y;
if (q > 4294967295) ThrowDivideError(m);
Write64(m->ax, q & 0xffffffff);
Write64(m->dx, r & 0xffffffff);
}
static void OpDivRdxRaxEvqpUnsigned64(struct Machine *m, uint32_t rde,
uint8_t *p) {
uint64_t d, r;
struct Dubble q;
q.lo = Read64(m->ax);
q.hi = Read64(m->dx);
d = Read64(p);
if (!d) ThrowDivideError(m);
q = DubbleDiv(q, d, &r);
if (q.hi) ThrowDivideError(m);
Write64(m->ax, q.lo);
Write64(m->dx, r);
}
void OpDivRdxRaxEvqpSigned(struct Machine *m, uint32_t rde) {
uint8_t *p;
p = GetModrmRegisterWordPointerReadOszRexw(m, rde);
if (Rexw(rde)) {
OpDivRdxRaxEvqpSigned64(m, rde, p);
} else if (!Osz(rde)) {
OpDivRdxRaxEvqpSigned32(m, rde, p);
} else {
OpDivRdxRaxEvqpSigned16(m, rde, p);
}
}
void OpDivRdxRaxEvqpUnsigned(struct Machine *m, uint32_t rde) {
uint8_t *p;
p = GetModrmRegisterWordPointerReadOszRexw(m, rde);
if (Rexw(rde)) {
OpDivRdxRaxEvqpUnsigned64(m, rde, p);
} else if (!Osz(rde)) {
OpDivRdxRaxEvqpUnsigned32(m, rde, p);
} else {
OpDivRdxRaxEvqpUnsigned16(m, rde, p);
}
}
void OpMulAxAlEbSigned(struct Machine *m, uint32_t rde) {
int16_t ax;
uint8_t *p;
unsigned of;
p = GetModrmRegisterBytePointerRead(m, rde);
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);
}
void OpMulAxAlEbUnsigned(struct Machine *m, uint32_t rde) {
int ax;
uint8_t *p;
unsigned of;
p = GetModrmRegisterBytePointerRead(m, rde);
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);
}
void OpMulRdxRaxEvqpSigned(struct Machine *m, uint32_t rde) {
uint8_t *p;
unsigned of;
int32_t dxax;
int64_t edxeax;
struct Dubble rdxrax;
p = GetModrmRegisterWordPointerReadOszRexw(m, rde);
if (Rexw(rde)) {
rdxrax = DubbleImul(Read64(m->ax), Read64(p));
of = !!(rdxrax.hi + (rdxrax.lo >> 63));
Write64(m->ax, rdxrax.lo);
Write64(m->dx, rdxrax.hi);
} else if (!Osz(rde)) {
edxeax = (int64_t)(int32_t)Read32(m->ax) * (int32_t)Read32(p);
of = edxeax != (int32_t)edxeax;
Write64(m->ax, edxeax);
Write64(m->dx, edxeax >> 32);
} else {
dxax = (int32_t)(int16_t)Read16(m->ax) * (int16_t)Read16(p);
of = dxax != (int16_t)dxax;
Write16(m->ax, dxax);
Write16(m->dx, dxax >> 16);
}
m->flags = SetFlag(m->flags, FLAGS_CF, of);
m->flags = SetFlag(m->flags, FLAGS_OF, of);
}
void OpMulRdxRaxEvqpUnsigned(struct Machine *m, uint32_t rde) {
uint8_t *p;
unsigned of;
uint32_t dxax;
uint64_t edxeax;
struct Dubble rdxrax;
p = GetModrmRegisterWordPointerReadOszRexw(m, rde);
if (Rexw(rde)) {
rdxrax = DubbleMul(Read64(m->ax), Read64(p));
of = !!rdxrax.hi;
Write64(m->ax, rdxrax.lo);
Write64(m->dx, rdxrax.hi);
} else if (!Osz(rde)) {
edxeax = (uint64_t)Read32(m->ax) * Read32(p);
of = (uint32_t)edxeax != edxeax;
Write64(m->ax, edxeax);
Write64(m->dx, edxeax >> 32);
} else {
dxax = (uint32_t)(uint16_t)Read16(m->ax) * (uint16_t)Read16(p);
of = (uint16_t)dxax != dxax;
Write16(m->ax, dxax);
Write16(m->dx, dxax >> 16);
}
m->flags = SetFlag(m->flags, FLAGS_CF, of);
m->flags = SetFlag(m->flags, FLAGS_OF, of);
}
static void AluImul(struct Machine *m, uint32_t rde, uint8_t *a, uint8_t *b) {
unsigned of;
if (Rexw(rde)) {
struct Dubble p;
p = DubbleImul(Read64(a), Read64(b));
of = !!(p.hi + (p.lo >> 63));
Write64(RegRexrReg(m, rde), p.lo);
} else if (!Osz(rde)) {
int64_t z;
z = (int64_t)(int32_t)Read32(a) * (int32_t)Read32(b);
of = z != (int32_t)z;
Write64(RegRexrReg(m, rde), z & 0xffffffff);
} else {
int32_t z;
z = (int32_t)(int16_t)Read16(a) * (int16_t)Read16(b);
of = z != (int16_t)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, uint32_t rde) {
AluImul(m, rde, RegRexrReg(m, rde),
GetModrmRegisterWordPointerReadOszRexw(m, rde));
}
void OpImulGvqpEvqpImm(struct Machine *m, uint32_t rde) {
uint8_t b[8];
Write64(b, m->xedd->op.uimm0);
AluImul(m, rde, GetModrmRegisterWordPointerReadOszRexw(m, rde), b);
}

View file

@ -1,20 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_DIVMUL_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_DIVMUL_H_
#include "tool/build/lib/machine.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
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) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_DIVMUL_H_ */

View file

@ -1,48 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/log/check.h"
#include "libc/mem/mem.h"
#include "tool/build/lib/fds.h"
int MachineFdAdd(struct MachineFds *mf) {
int fd;
struct MachineFdClosed *closed;
if ((closed = mf->closed)) {
fd = closed->fd;
mf->closed = closed->next;
free(closed);
} else {
fd = mf->i;
if (mf->i++ == mf->n) {
mf->n = mf->i + (mf->i >> 1);
mf->p = realloc(mf->p, mf->n * sizeof(*mf->p));
}
}
return fd;
}
void MachineFdRemove(struct MachineFds *mf, int fd) {
struct MachineFdClosed *closed;
mf->p[fd].cb = NULL;
if ((closed = malloc(sizeof(struct MachineFdClosed)))) {
closed->fd = fd;
closed->next = mf->closed;
mf->closed = closed;
}
}

View file

@ -1,38 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_FDS_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_FDS_H_
#include "libc/calls/struct/iovec.h"
#include "libc/sock/sock.h"
#include "libc/sock/struct/pollfd.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct MachineFdClosed {
unsigned fd;
struct MachineFdClosed *next;
};
struct MachineFdCb {
int (*close)(int);
ssize_t (*readv)(int, const struct iovec *, int);
ssize_t (*writev)(int, const struct iovec *, int);
int (*ioctl)(int, int, ...);
int (*poll)(struct pollfd *, uint64_t, int32_t);
};
struct MachineFd {
int fd;
struct MachineFdCb *cb;
};
struct MachineFds {
size_t i, n;
struct MachineFd *p;
struct MachineFdClosed *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

@ -1,63 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "tool/build/lib/flags.h"
bool GetParity(uint8_t b) {
b ^= b >> 4;
b ^= b >> 2;
b ^= b >> 1;
return ~b & 1;
}
void ImportFlags(struct Machine *m, uint64_t flags) {
uint64_t old, mask = 0;
mask |= 1u << FLAGS_CF;
mask |= 1u << FLAGS_PF;
mask |= 1u << FLAGS_AF;
mask |= 1u << FLAGS_ZF;
mask |= 1u << FLAGS_SF;
mask |= 1u << FLAGS_TF;
mask |= 1u << FLAGS_IF;
mask |= 1u << FLAGS_DF;
mask |= 1u << FLAGS_OF;
mask |= 1u << FLAGS_NT;
mask |= 1u << FLAGS_AC;
mask |= 1u << FLAGS_ID;
m->flags = (flags & mask) | (m->flags & ~mask);
m->flags = SetFlag(m->flags, FLAGS_RF, false);
m->flags = SetLazyParityByte(m->flags, !((m->flags >> FLAGS_PF) & 1));
}
uint64_t ExportFlags(uint64_t flags) {
flags = SetFlag(flags, FLAGS_IOPL, 3);
flags = SetFlag(flags, FLAGS_F1, true);
flags = SetFlag(flags, FLAGS_F0, false);
flags = flags & ~(1ull << FLAGS_PF);
flags |= GetLazyParityBool(flags) << FLAGS_PF;
return flags;
}
int64_t AluFlags(uint64_t x, uint32_t af, uint32_t *f, uint32_t of, uint32_t cf,
uint32_t sf) {
*f &= ~(1u << FLAGS_CF | 1u << FLAGS_ZF | 1u << FLAGS_SF | 1u << FLAGS_OF |
1u << FLAGS_AF | 0xFF000000u);
*f |= sf << FLAGS_SF | cf << FLAGS_CF | !x << FLAGS_ZF | of << FLAGS_OF |
af << FLAGS_AF | (x & 0xFF) << 24;
return x;
}

View file

@ -1,71 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_FLAGS_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_FLAGS_H_
#include "tool/build/lib/machine.h"
#define FLAGS_CF 0
#define FLAGS_VF 1
#define FLAGS_PF 2
#define FLAGS_F1 3
#define FLAGS_AF 4
#define FLAGS_KF 5
#define FLAGS_ZF 6
#define FLAGS_SF 7
#define FLAGS_TF 8
#define FLAGS_IF 9
#define FLAGS_DF 10
#define FLAGS_OF 11
#define FLAGS_IOPL 12
#define FLAGS_NT 14
#define FLAGS_F0 15
#define FLAGS_RF 16
#define FLAGS_VM 17
#define FLAGS_AC 18
#define FLAGS_VIF 19
#define FLAGS_VIP 20
#define FLAGS_ID 21
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define GetLazyParityBool(f) GetParity((f) >> 24)
#define SetLazyParityByte(f, x) (((f) & ~0xFF000000u) | ((x)&0xFFu) << 24)
#define GetFlag(FLAGS, BIT) \
({ \
autotype(FLAGS) Flags = (FLAGS); \
typeof(Flags) IsSet; \
switch (BIT) { \
case FLAGS_PF: \
IsSet = GetLazyParityBool(Flags); \
break; \
default: \
IsSet = (Flags >> (BIT)) & 1; \
break; \
} \
IsSet; \
})
#define SetFlag(FLAGS, BIT, VAL) \
({ \
autotype(FLAGS) Flags = (FLAGS); \
typeof(Flags) Val = (VAL); \
typeof(Flags) One = 1; \
switch (BIT) { \
case FLAGS_PF: \
Flags = SetLazyParityByte(Flags, !Val); \
break; \
default: \
Flags = (Flags & ~(One << (BIT))) | Val << (BIT); \
break; \
} \
Flags; \
})
bool GetParity(uint8_t);
uint64_t ExportFlags(uint64_t);
void ImportFlags(struct Machine *, uint64_t);
int64_t AluFlags(uint64_t, uint32_t, uint32_t *, uint32_t, uint32_t, uint32_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_FLAGS_H_ */

File diff suppressed because it is too large Load diff

View file

@ -1,65 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_FPU_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_FPU_H_
#include "tool/build/lib/machine.h"
#define kFpuTagValid 0b00
#define kFpuTagZero 0b01
#define kFpuTagSpecial 0b10
#define kFpuTagEmpty 0b11
#define kFpuCwIm 0x0001 /* invalid operation mask */
#define kFpuCwDm 0x0002 /* denormal operand mask */
#define kFpuCwZm 0x0004 /* zero divide mask */
#define kFpuCwOm 0x0008 /* overflow mask */
#define kFpuCwUm 0x0010 /* underflow mask */
#define kFpuCwPm 0x0020 /* precision mask */
#define kFpuCwPc 0x0300 /* precision: 32,∅,64,80 */
#define kFpuCwRc 0x0c00 /* rounding: even,→-∞,→+∞,→0 */
#define kFpuSwIe 0x0001 /* invalid operation */
#define kFpuSwDe 0x0002 /* denormalized operand */
#define kFpuSwZe 0x0004 /* zero divide */
#define kFpuSwOe 0x0008 /* overflow */
#define kFpuSwUe 0x0010 /* underflow */
#define kFpuSwPe 0x0020 /* precision */
#define kFpuSwSf 0x0040 /* stack fault */
#define kFpuSwEs 0x0080 /* exception summary status */
#define kFpuSwC0 0x0100 /* condition 0 */
#define kFpuSwC1 0x0200 /* condition 1 */
#define kFpuSwC2 0x0400 /* condition 2 */
#define kFpuSwSp 0x3800 /* top stack */
#define kFpuSwC3 0x4000 /* condition 3 */
#define kFpuSwBf 0x8000 /* busy flag */
#define kMxcsrIe 0x0001 /* invalid operation flag */
#define kMxcsrDe 0x0002 /* denormal flag */
#define kMxcsrZe 0x0004 /* divide by zero flag */
#define kMxcsrOe 0x0008 /* overflow flag */
#define kMxcsrUe 0x0010 /* underflow flag */
#define kMxcsrPe 0x0020 /* precision flag */
#define kMxcsrDaz 0x0040 /* denormals are zeros */
#define kMxcsrIm 0x0080 /* invalid operation mask */
#define kMxcsrDm 0x0100 /* denormal mask */
#define kMxcsrZm 0x0200 /* divide by zero mask */
#define kMxcsrOm 0x0400 /* overflow mask */
#define kMxcsrUm 0x0800 /* underflow mask */
#define kMxcsrPm 0x1000 /* precision mask */
#define kMxcsrRc 0x6000 /* rounding control */
#define kMxcsrFtz 0x8000 /* flush to zero */
#define FpuSt(m, i) ((m)->fpu.st + (((i) + ((m->fpu.sw & kFpuSwSp) >> 11)) & 7))
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
double FpuPop(struct Machine *);
int FpuGetTag(struct Machine *, unsigned);
void FpuPush(struct Machine *, double);
void FpuSetTag(struct Machine *, unsigned, unsigned);
void OpFinit(struct Machine *);
void OpFpu(struct Machine *, uint32_t);
void OpFwait(struct Machine *, uint32_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_FPU_H_ */

View file

@ -1,41 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/itoa.h"
#include "libc/str/str.h"
#include "tool/build/lib/high.h"
struct High g_high;
char *HighStart(char *p, int h) {
if (h) {
p = stpcpy(p, "\e[38;5;");
p = FormatUint32(p, h);
p = stpcpy(p, "m");
g_high.active = true;
}
return p;
}
char *HighEnd(char *p) {
if (g_high.active) {
p = stpcpy(p, "\e[39m");
g_high.active = false;
}
return p;
}

View file

@ -1,23 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_HIGH_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_HIGH_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct High {
bool active;
uint8_t keyword;
uint8_t reg;
uint8_t literal;
uint8_t label;
uint8_t comment;
uint8_t quote;
};
extern struct High g_high;
char *HighStart(char *, int);
char *HighEnd(char *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_HIGH_H_ */

View file

@ -1,92 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/bsf.h"
#include "libc/macros.internal.h"
#include "libc/str/str.h"
#include "third_party/xed/x86.h"
#include "tool/build/lib/address.h"
#include "tool/build/lib/endian.h"
#include "tool/build/lib/machine.h"
#include "tool/build/lib/memory.h"
#include "tool/build/lib/modrm.h"
#include "tool/build/lib/stats.h"
#include "tool/build/lib/throw.h"
static bool IsOpcodeEqual(struct XedDecodedInst *xedd, uint8_t *a) {
uint64_t w;
if (xedd->length) {
if (xedd->length <= 7) {
w = Read64(a) ^ Read64(xedd->bytes);
return !w || _bsfl(w) >= (xedd->length << 3);
} else {
return memcmp(a, xedd->bytes, xedd->length) == 0;
}
} else {
return false;
}
}
static void DecodeInstruction(struct Machine *m, uint8_t *p, unsigned n) {
struct XedDecodedInst xedd[1];
xed_decoded_inst_zero_set_mode(xedd, m->mode);
if (!xed_instruction_length_decode(xedd, p, n)) {
xedd->op.rde = EncodeRde(xedd);
memcpy(m->xedd, xedd, sizeof(m->icache[0]));
} else {
HaltMachine(m, kMachineDecodeError);
}
}
static dontinline void LoadInstructionSlow(struct Machine *m, uint64_t ip) {
unsigned i;
uint8_t *addr;
uint8_t copy[15], *toil;
i = 0x1000 - (ip & 0xfff);
addr = ResolveAddress(m, ip);
if ((toil = FindReal(m, ip + i))) {
memcpy(copy, addr, i);
memcpy(copy + i, toil, 15 - i);
DecodeInstruction(m, copy, 15);
} else {
DecodeInstruction(m, addr, i);
}
}
void LoadInstruction(struct Machine *m) {
uint64_t ip;
unsigned key;
uint8_t *addr;
ip = Read64(m->cs) + MaskAddress(m->mode & 3, m->ip);
key = ip & (ARRAYLEN(m->icache) - 1);
m->xedd = (struct XedDecodedInst *)m->icache[key];
if ((ip & 0xfff) < 0x1000 - 15) {
if (ip - (ip & 0xfff) == m->codevirt && m->codehost) {
addr = m->codehost + (ip & 0xfff);
} else {
m->codevirt = ip - (ip & 0xfff);
m->codehost = ResolveAddress(m, m->codevirt);
addr = m->codehost + (ip & 0xfff);
}
if (!IsOpcodeEqual(m->xedd, addr)) {
DecodeInstruction(m, addr, 15);
}
} else {
LoadInstructionSlow(m, ip);
}
}

View file

@ -1,115 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/nexgen32e/uart.internal.h"
#include "libc/sysv/consts/fileno.h"
#include "libc/sysv/consts/poll.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->readv(m->fds.p[fd].fd, &(struct iovec){&b, 1}, 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->writev(m->fds.p[fd].fd, &(struct iovec){&b, 1}, 1);
}
static int OpE9Poll(struct Machine *m) {
int fd, rc;
struct pollfd pf;
fd = STDIN_FILENO;
if (fd >= m->fds.i) return -1;
if (!m->fds.p[fd].cb) return -1;
pf.fd = m->fds.p[fd].fd;
pf.events = POLLIN | POLLOUT;
rc = m->fds.p[fd].cb->poll(&pf, 1, 20);
if (rc <= 0) return rc;
return pf.revents;
}
static int OpSerialIn(struct Machine *m, int r) {
int p, s;
switch (r) {
case UART_DLL:
if (!m->dlab) {
return OpE9Read(m);
} else {
return 0x01;
}
case UART_LSR:
if ((p = OpE9Poll(m)) == -1) return -1;
s = UART_TTYIDL;
if (p & POLLIN) s |= UART_TTYDA;
if (p & POLLOUT) s |= UART_TTYTXR;
return s;
default:
return 0;
}
}
static void OpSerialOut(struct Machine *m, int r, uint32_t x) {
switch (r) {
case UART_DLL:
if (!m->dlab) {
return OpE9Write(m, x);
}
break;
case UART_LCR:
m->dlab = !!(x & UART_DLAB);
break;
default:
break;
}
}
uint64_t OpIn(struct Machine *m, uint16_t p) {
switch (p) {
case 0xE9:
return OpE9Read(m);
case 0x3F8 ... 0x3FF:
return OpSerialIn(m, p - 0x3F8);
default:
return -1;
}
}
void OpOut(struct Machine *m, uint16_t p, uint32_t x) {
switch (p) {
case 0xE9:
OpE9Write(m, x);
break;
case 0x3F8 ... 0x3FF:
OpSerialOut(m, p - 0x3F8, x);
break;
default:
break;
}
}

View file

@ -1,12 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_IOPORTS_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_IOPORTS_H_
#include "tool/build/lib/machine.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
uint64_t OpIn(struct Machine *, uint16_t);
void OpOut(struct Machine *, uint16_t, uint32_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_IOPORTS_H_ */

View file

@ -1,66 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"
#include "libc/str/str.h"
#include "tool/build/lib/iovs.h"
void InitIovs(struct Iovs *ib) {
ib->p = ib->init;
ib->i = 0;
ib->n = ARRAYLEN(ib->init);
}
void FreeIovs(struct Iovs *ib) {
if (ib->p != ib->init) {
free(ib->p);
}
}
/**
* Appends memory region to i/o vector builder.
*/
int AppendIovs(struct Iovs *ib, void *base, size_t len) {
unsigned i, n;
struct iovec *p;
if (len) {
p = ib->p;
i = ib->i;
n = ib->n;
if (i && (intptr_t)base == (intptr_t)p[i - 1].iov_base + p[i - 1].iov_len) {
p[i - 1].iov_len += len;
} else {
if (__builtin_expect(i == n, 0)) {
n += n >> 1;
if (p == ib->init) {
if (!(p = malloc(sizeof(struct iovec) * n))) return -1;
memcpy(p, ib->init, sizeof(ib->init));
} else {
if (!(p = realloc(p, sizeof(struct iovec) * n))) return -1;
}
ib->p = p;
ib->n = n;
}
p[i].iov_base = base;
p[i].iov_len = len;
++ib->i;
}
}
return 0;
}

View file

@ -1,19 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_IOVS_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_IOVS_H_
#include "libc/calls/struct/iovec.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct Iovs {
struct iovec *p;
unsigned i, n;
struct iovec init[2];
};
void InitIovs(struct Iovs *);
void FreeIovs(struct Iovs *);
int AppendIovs(struct Iovs *, void *, size_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_IOVS_H_ */

View file

@ -1,49 +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 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.internal.h"
#include "tool/build/lib/endian.h"
#include "tool/build/lib/ldbl.h"
#include "tool/build/lib/pun.h"
uint8_t *SerializeLdbl(uint8_t b[10], double f) {
int e;
union DoublePun u = {f};
e = (u.i >> 52) & 0x7ff;
if (!e) {
e = 0;
} else if (e == 0x7ff) {
e = 0x7fff;
} else {
e -= 0x3ff;
e += 0x3fff;
}
Write16(b + 8, e | u.i >> 63 << 15);
Write64(b, (u.i & 0x000fffffffffffff) << 11 | (uint64_t) !!u.f << 63);
return b;
}
double DeserializeLdbl(const uint8_t b[10]) {
union DoublePun u;
u.i = (uint64_t)(MAX(-1023, MIN(1024, ((Read16(b + 8) & 0x7fff) - 0x3fff))) +
1023)
<< 52 |
((Read64(b) & 0x7fffffffffffffff) + (1 << (11 - 1))) >> 11 |
(uint64_t)(b[9] >> 7) << 63;
return u.f;
}

View file

@ -1,11 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_LDBL_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_LDBL_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
double DeserializeLdbl(const uint8_t[10]);
uint8_t *SerializeLdbl(uint8_t[10], double);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_LDBL_H_ */

View file

@ -1,227 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "tool/build/lib/loader.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/elf/elf.h"
#include "libc/elf/struct/phdr.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/popcnt.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/runtime/pc.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
#include "third_party/xed/x86.h"
#include "tool/build/lib/argv.h"
#include "tool/build/lib/endian.h"
#include "tool/build/lib/machine.h"
#include "tool/build/lib/memory.h"
static void LoadElfLoadSegment(struct Machine *m, void *code, size_t codesize,
Elf64_Phdr *phdr) {
void *rbss;
int64_t align, bsssize;
int64_t felf, fstart, fend, vstart, vbss, vend;
align = MAX(phdr->p_align, PAGESIZE);
if (popcnt(align) != 1) align = 8;
CHECK_EQ(0, (phdr->p_vaddr - phdr->p_offset) % align);
felf = (int64_t)(intptr_t)code;
vstart = ROUNDDOWN(phdr->p_vaddr, align);
vbss = ROUNDUP(phdr->p_vaddr + phdr->p_filesz, align);
vend = ROUNDUP(phdr->p_vaddr + phdr->p_memsz, align);
fstart = felf + ROUNDDOWN(phdr->p_offset, align);
fend = felf + phdr->p_offset + phdr->p_filesz;
bsssize = vend - vbss;
VERBOSEF("LOADELFLOADSEGMENT"
" VSTART %#lx VBSS %#lx VEND %#lx"
" FSTART %#lx FEND %#lx BSSSIZE %#lx",
vstart, vbss, vend, fstart, fend, bsssize);
m->brk = MAX(m->brk, vend);
CHECK_GE(vend, vstart);
CHECK_GE(fend, fstart);
CHECK_LE(felf, fstart);
CHECK_GE(vstart, -0x800000000000);
CHECK_LE(vend, 0x800000000000);
CHECK_GE(vend - vstart, fstart - fend);
CHECK_LE(phdr->p_filesz, phdr->p_memsz);
CHECK_EQ(felf + phdr->p_offset - fstart, phdr->p_vaddr - vstart);
CHECK_NE(-1, ReserveVirtual(m, vstart, fend - fstart,
PAGE_V | PAGE_RW | PAGE_U | PAGE_RSRV));
VirtualRecv(m, vstart, (void *)fstart, fend - fstart);
if (bsssize)
CHECK_NE(-1, ReserveVirtual(m, vbss, bsssize,
PAGE_V | PAGE_RW | PAGE_U | PAGE_RSRV));
if (phdr->p_memsz - phdr->p_filesz > bsssize) {
VirtualSet(m, phdr->p_vaddr + phdr->p_filesz, 0,
phdr->p_memsz - phdr->p_filesz - bsssize);
}
}
static void LoadElf(struct Machine *m, struct Elf *elf) {
unsigned i;
Elf64_Phdr *phdr;
m->ip = elf->base = 0x400000 /* elf->ehdr->e_entry */;
VERBOSEF("LOADELF ENTRY %012lx", m->ip);
for (i = 0; i < elf->ehdr->e_phnum; ++i) {
phdr = GetElfSegmentHeaderAddress(elf->ehdr, elf->size, i);
switch (phdr->p_type) {
case PT_LOAD:
elf->base = MIN(elf->base, phdr->p_vaddr);
LoadElfLoadSegment(m, elf->ehdr, elf->size, phdr);
break;
default:
break;
}
}
}
static void LoadBin(struct Machine *m, intptr_t base, const char *prog,
void *code, size_t codesize) {
Elf64_Phdr phdr = {
.p_type = PT_LOAD,
.p_flags = PF_X | PF_R | PF_W,
.p_offset = 0,
.p_vaddr = base,
.p_paddr = base,
.p_filesz = codesize,
.p_memsz = ROUNDUP(codesize + FRAMESIZE, 0x200000),
.p_align = PAGESIZE,
};
LoadElfLoadSegment(m, code, codesize, &phdr);
m->ip = base;
}
static void BootProgram(struct Machine *m, struct Elf *elf, size_t codesize) {
m->ip = 0x7c00;
elf->base = 0x7c00;
CHECK_NE(-1, ReserveReal(m, 0x00f00000));
bzero(m->real.p, 0x00f00000);
Write16(m->real.p + 0x400, 0x3F8);
Write16(m->real.p + 0x40E, 0xb0000 >> 4);
Write16(m->real.p + 0x413, 0xb0000 / 1024);
Write16(m->real.p + 0x44A, 80);
Write64(m->cs, 0);
Write64(m->dx, 0);
memcpy(m->real.p + 0x7c00, elf->map, 512);
if (memcmp(elf->map, "\177ELF", 4) == 0) {
elf->ehdr = (void *)elf->map;
elf->size = codesize;
elf->base = elf->ehdr->e_entry;
} else {
elf->base = 0x7c00;
elf->ehdr = NULL;
elf->size = 0;
}
}
static int GetElfHeader(char ehdr[hasatleast 64], const char *prog,
const char *image) {
char *p;
int c, i;
for (p = image; p < image + 4096; ++p) {
if (READ64LE(p) != READ64LE("printf '")) continue;
for (i = 0, p += 8; p + 3 < image + 4096 && (c = *p++) != '\'';) {
if (c == '\\') {
if ('0' <= *p && *p <= '7') {
c = *p++ - '0';
if ('0' <= *p && *p <= '7') {
c *= 8;
c += *p++ - '0';
if ('0' <= *p && *p <= '7') {
c *= 8;
c += *p++ - '0';
}
}
}
}
if (i < 64) {
ehdr[i++] = c;
} else {
WARNF("%s: ape printf elf header too long\n", prog);
return -1;
}
}
if (i != 64) {
WARNF("%s: ape printf elf header too short\n", prog);
return -1;
}
if (READ32LE(ehdr) != READ32LE("\177ELF")) {
WARNF("%s: ape printf elf header didn't have elf magic\n", prog);
return -1;
}
return 0;
}
WARNF("%s: printf statement not found in first 4096 bytes\n", prog);
return -1;
}
void LoadProgram(struct Machine *m, const char *prog, char **args, char **vars,
struct Elf *elf) {
int fd;
ssize_t rc;
int64_t sp;
char ehdr[64];
struct stat st;
size_t i, mappedsize;
DCHECK_NOTNULL(prog);
elf->prog = prog;
if ((fd = open(prog, O_RDONLY)) == -1 ||
(fstat(fd, &st) == -1 || !st.st_size)) {
fputs(prog, stderr);
fputs(": not found\n", stderr);
exit(1);
}
elf->mapsize = st.st_size;
CHECK_NE(MAP_FAILED,
(elf->map = mmap(NULL, elf->mapsize, PROT_READ | PROT_WRITE,
MAP_PRIVATE, fd, 0)));
CHECK_NE(-1, close(fd));
ResetCpu(m);
if ((m->mode & 3) == XED_MODE_REAL) {
BootProgram(m, elf, elf->mapsize);
} else {
sp = 0x800000000000;
Write64(m->sp, sp);
m->cr3 = AllocateLinearPage(m);
CHECK_NE(-1, ReserveVirtual(m, sp - 0x800000, 0x800000,
PAGE_V | PAGE_RW | PAGE_U | PAGE_RSRV));
LoadArgv(m, prog, args, vars);
if (memcmp(elf->map, "\177ELF", 4) == 0) {
elf->ehdr = (void *)elf->map;
elf->size = elf->mapsize;
LoadElf(m, elf);
} else if (READ64LE(elf->map) == READ64LE("MZqFpD='") &&
!GetElfHeader(ehdr, prog, elf->map)) {
memcpy(elf->map, ehdr, 64);
elf->ehdr = (void *)elf->map;
elf->size = elf->mapsize;
LoadElf(m, elf);
} else {
elf->base = IMAGE_BASE_VIRTUAL;
elf->ehdr = NULL;
elf->size = 0;
LoadBin(m, elf->base, prog, elf->map, elf->mapsize);
}
}
}

View file

@ -1,23 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_LOADER_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_LOADER_H_
#include "libc/elf/struct/ehdr.h"
#include "tool/build/lib/machine.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct Elf {
const char *prog;
Elf64_Ehdr *ehdr;
size_t size;
int64_t base;
char *map;
size_t mapsize;
};
void LoadProgram(struct Machine *, const char *, char **, char **,
struct Elf *);
void LoadDebugSymbols(struct Elf *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_LOADER_H_ */

File diff suppressed because it is too large Load diff

View file

@ -1,206 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_MACHINE_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_MACHINE_H_
#include "libc/runtime/runtime.h"
#include "third_party/xed/x86.h"
#include "tool/build/lib/bits.h"
#include "tool/build/lib/fds.h"
#define kMachineHalt -1
#define kMachineDecodeError -2
#define kMachineUndefinedInstruction -3
#define kMachineSegmentationFault -4
#define kMachineExit -5
#define kMachineDivideError -6
#define kMachineFpuException -7
#define kMachineProtectionFault -8
#define kMachineSimdException -9
#define kMachineOverflow -10
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct Machine {
struct XedDecodedInst *xedd;
uint64_t ip;
uint8_t cs[8];
uint8_t ss[8];
uint64_t codevirt;
uint8_t *codehost;
uint32_t mode;
uint32_t flags;
uint32_t tlbindex;
uint32_t stashsize;
int64_t stashaddr;
int64_t readaddr;
int64_t writeaddr;
uint32_t readsize;
uint32_t writesize;
union {
uint8_t reg[16][8];
struct {
uint8_t ax[8];
uint8_t cx[8];
uint8_t dx[8];
uint8_t bx[8];
uint8_t sp[8];
uint8_t bp[8];
uint8_t si[8];
uint8_t di[8];
uint8_t r8[8];
uint8_t r9[8];
uint8_t r10[8];
uint8_t r11[8];
uint8_t r12[8];
uint8_t r13[8];
uint8_t r14[8];
uint8_t r15[8];
};
};
struct MachineTlb {
int64_t virt;
uint64_t entry;
} tlb[16];
struct MachineReal {
size_t i, n;
uint8_t *p;
} real;
uint64_t cr3;
uint8_t xmm[16][16];
uint8_t es[8];
uint8_t ds[8];
uint8_t fs[8];
uint8_t gs[8];
struct MachineFpu {
long double st[8];
union {
uint32_t cw;
struct {
unsigned im : 1; // invalid operation mask
unsigned dm : 1; // denormal operand mask
unsigned zm : 1; // zero divide mask
unsigned om : 1; // overflow mask
unsigned um : 1; // underflow mask
unsigned pm : 1; // precision mask
unsigned _p1 : 2; // reserved
unsigned pc : 2; // precision: 32,∅,64,80
unsigned rc : 2; // rounding: even,→-∞,→+∞,→0
};
};
union {
uint32_t sw;
struct {
unsigned ie : 1; // invalid operation
unsigned de : 1; // denormalized operand
unsigned ze : 1; // zero divide
unsigned oe : 1; // overflow
unsigned ue : 1; // underflow
unsigned pe : 1; // precision
unsigned sf : 1; // stack fault
unsigned es : 1; // exception summary status
unsigned c0 : 1; // condition 0
unsigned c1 : 1; // condition 1
unsigned c2 : 1; // condition 2
unsigned sp : 3; // top stack
unsigned c3 : 1; // condition 3
unsigned bf : 1; // busy flag
};
};
int tw;
int op;
int64_t ip;
int64_t dp;
} fpu;
struct MachineSse {
union {
uint32_t mxcsr;
struct {
unsigned ie : 1; // invalid operation flag
unsigned de : 1; // denormal flag
unsigned ze : 1; // divide by zero flag
unsigned oe : 1; // overflow flag
unsigned ue : 1; // underflow flag
unsigned pe : 1; // precision flag
unsigned daz : 1; // denormals are zeros
unsigned im : 1; // invalid operation mask
unsigned dm : 1; // denormal mask
unsigned zm : 1; // divide by zero mask
unsigned om : 1; // overflow mask
unsigned um : 1; // underflow mask
unsigned pm : 1; // precision mask
unsigned rc : 2; // rounding control
unsigned ftz : 1; // flush to zero
};
};
} sse;
uint64_t cr0;
uint64_t cr2;
uint64_t cr4;
uint64_t gdt_base;
uint64_t idt_base;
uint16_t gdt_limit;
uint16_t idt_limit;
uint32_t mxcsr;
struct MachineRealFree {
uint64_t i;
uint64_t n;
struct MachineRealFree *next;
} * realfree;
struct FreeList {
uint32_t i;
void *p[6];
} freelist;
struct MachineMemstat {
int freed;
int resizes;
int reserved;
int committed;
int allocated;
int reclaimed;
int pagetables;
} memstat;
int64_t brk;
int64_t bofram[2];
jmp_buf onhalt;
int64_t faultaddr;
bool dlab;
bool isfork;
bool ismetal;
struct MachineFds fds;
uint8_t stash[4096];
uint8_t icache[1024][40];
void (*onbinbase)(struct Machine *);
void (*onlongbranch)(struct Machine *);
void (*redraw)(void);
struct sigaction_bits sighand[28];
uint8_t sigmask[8];
int sig;
uint64_t siguc;
uint64_t sigfp;
struct {
int i, n;
struct {
int sig;
int code;
} p[64];
} signals;
} forcealign(64);
struct Machine *NewMachine(void) dontdiscard;
void FreeMachine(struct Machine *);
void ResetMem(struct Machine *);
void ResetCpu(struct Machine *);
void ResetTlb(struct Machine *);
void ResetInstructionCache(struct Machine *);
void LoadInstruction(struct Machine *);
void ExecuteInstruction(struct Machine *);
long AllocateLinearPage(struct Machine *);
long AllocateLinearPageRaw(struct Machine *);
int ReserveReal(struct Machine *, size_t);
int ReserveVirtual(struct Machine *, int64_t, size_t, uint64_t);
char *FormatPml4t(struct Machine *) dontdiscard;
int64_t FindVirtual(struct Machine *, int64_t, size_t);
int FreeVirtual(struct Machine *, int64_t, size_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_MACHINE_H_ */

View file

@ -1,70 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.internal.h"
#include "libc/str/str.h"
#include "libc/str/tab.internal.h"
#include "tool/build/lib/buffer.h"
#include "tool/build/lib/mda.h"
#define kBlink 1
#define kVisible 2
#define kUnderline 4
#define kBold 8
#define kReverse 16
/**
* Decodes Monochrome Display Adapter attributes.
* @see https://www.seasip.info/VintagePC/mda.html
*/
static uint8_t DecodeMdaAttributes(int8_t a) {
uint8_t r = 0;
if (a & 0x77) {
if ((a & 0x77) == 0x70) r |= kReverse;
if ((a & 0x07) == 0x01) r |= kUnderline;
if (a & 0x08) r |= kBold;
if (a < 0) r |= kBlink;
r |= kVisible;
}
return r;
}
void DrawMda(struct Panel *p, uint8_t v[25][80][2]) {
unsigned y, x, n, a, b;
n = MIN(25, p->bottom - p->top);
for (y = 0; y < n; ++y) {
a = -1;
for (x = 0; x < 80; ++x) {
b = DecodeMdaAttributes(v[y][x][1]);
if (a != b) {
a = b;
AppendStr(&p->lines[y], "\e[0");
if (a & kBold) AppendStr(&p->lines[y], ";1");
if (a & kUnderline) AppendStr(&p->lines[y], ";4");
if (a & kBlink) AppendStr(&p->lines[y], ";5");
if (a & kReverse) AppendStr(&p->lines[y], ";7");
AppendChar(&p->lines[y], 'm');
}
if (a) {
AppendWide(&p->lines[y], kCp437[v[y][x][0]]);
} else {
AppendChar(&p->lines[y], ' ');
}
}
}
}

View file

@ -1,11 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_MDA_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_MDA_H_
#include "tool/build/lib/panel.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
void DrawMda(struct Panel *, uint8_t[25][80][2]);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_MDA_H_ */

View file

@ -1,288 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/log/check.h"
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"
#include "libc/nt/struct/importobjectheader.internal.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/pc.internal.h"
#include "libc/str/str.h"
#include "tool/build/lib/memory.h"
#include "tool/build/lib/throw.h"
void SetReadAddr(struct Machine *m, int64_t addr, uint32_t size) {
if (size) {
m->readaddr = addr;
m->readsize = size;
}
}
void SetWriteAddr(struct Machine *m, int64_t addr, uint32_t size) {
if (size) {
m->writeaddr = addr;
m->writesize = size;
}
}
uint64_t HandlePageFault(struct Machine *m, int64_t virt, uint64_t entry,
uint64_t table, unsigned index) {
long page;
if ((page = AllocateLinearPage(m)) != -1) {
--m->memstat.reserved;
if (entry & PAGE_GROD) {
ReserveVirtual(m, virt - 4096, 4096,
PAGE_GROD | PAGE_RSRV |
(entry & (PAGE_XD | PAGE_U | PAGE_RW | PAGE_V)));
}
return (*(uint64_t *)(m->real.p + table + index * 8) =
page | entry & ~(PAGE_TA | PAGE_IGN1));
} else {
return 0;
}
}
uint64_t FindPage(struct Machine *m, int64_t virt) {
uint64_t table, entry;
unsigned level, index, i;
virt &= -4096;
for (i = 0; i < ARRAYLEN(m->tlb); ++i) {
if (m->tlb[i].virt == virt && (m->tlb[i].entry & 1)) {
return m->tlb[i].entry;
}
}
level = 39;
entry = m->cr3;
do {
table = entry & PAGE_TA;
CHECK_LT(table, m->real.n);
index = (virt >> level) & 511;
entry = *(uint64_t *)(m->real.p + table + index * 8);
if (!(entry & 1)) return 0;
} while ((level -= 9) >= 12);
if ((entry & PAGE_RSRV) &&
(entry = HandlePageFault(m, virt, entry, table, index)) == -1) {
return 0;
}
m->tlbindex = (m->tlbindex + 1) & (ARRAYLEN(m->tlb) - 1);
m->tlb[m->tlbindex] = m->tlb[0];
m->tlb[0].virt = virt;
m->tlb[0].entry = entry;
return entry;
}
void *FindReal(struct Machine *m, int64_t virt) {
uint64_t table, entry, page;
unsigned skew, level, index, i;
if ((m->mode & 3) != XED_MODE_REAL) {
if (IsLegalPointer(virt)) {
if (!(entry = FindPage(m, virt))) return NULL;
return m->real.p + (entry & PAGE_TA) + (virt & 0xfff);
} else {
return NULL;
}
} else if (0 <= virt && virt + 0xfff < m->real.n) {
return m->real.p + virt;
} else {
return NULL;
}
}
void *ResolveAddress(struct Machine *m, int64_t v) {
void *r;
if ((r = FindReal(m, v))) return r;
ThrowSegmentationFault(m, v);
}
void VirtualSet(struct Machine *m, int64_t v, char c, uint64_t n) {
char *p;
uint64_t k;
k = 4096 - (v & 0xfff);
while (n) {
k = MIN(k, n);
p = ResolveAddress(m, v);
memset(p, c, k);
n -= k;
v += k;
k = 4096;
}
}
void VirtualCopy(struct Machine *m, int64_t v, char *r, uint64_t n, bool d) {
char *p;
uint64_t k;
k = 4096 - (v & 0xfff);
while (n) {
k = MIN(k, n);
p = ResolveAddress(m, v);
if (d) {
memcpy(r, p, k);
} else {
memcpy(p, r, k);
}
n -= k;
r += k;
v += k;
k = 4096;
}
}
void *VirtualSend(struct Machine *m, void *dst, int64_t src, uint64_t n) {
VirtualCopy(m, src, dst, n, true);
return dst;
}
void VirtualSendRead(struct Machine *m, void *dst, int64_t addr, uint64_t n) {
VirtualSend(m, dst, addr, n);
SetReadAddr(m, addr, n);
}
void VirtualRecv(struct Machine *m, int64_t dst, void *src, uint64_t n) {
VirtualCopy(m, dst, src, n, false);
}
void VirtualRecvWrite(struct Machine *m, int64_t addr, void *src, uint64_t n) {
VirtualRecv(m, addr, src, n);
SetWriteAddr(m, addr, n);
}
void *ReserveAddress(struct Machine *m, int64_t v, size_t n) {
void *r;
DCHECK_LE(n, sizeof(m->stash));
if ((v & 0xfff) + n <= 4096) return ResolveAddress(m, v);
m->stashaddr = v;
m->stashsize = n;
r = m->stash;
VirtualSend(m, r, v, n);
return r;
}
void *AccessRam(struct Machine *m, int64_t v, size_t n, void *p[2],
uint8_t *tmp, bool copy) {
unsigned k;
uint8_t *a, *b;
DCHECK_LE(n, 4096);
if ((v & 0xfff) + n <= 4096) return ResolveAddress(m, v);
k = 4096;
k -= v & 0xfff;
DCHECK_LE(k, 4096);
a = ResolveAddress(m, v);
b = ResolveAddress(m, v + k);
if (copy) {
memcpy(tmp, a, k);
memcpy(tmp + k, b, n - k);
}
p[0] = a;
p[1] = b;
return tmp;
}
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) {
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) {
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) {
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) {
uint8_t *a;
unsigned k;
DCHECK_LE(n, 4096);
if ((v & 0xfff) + n <= 4096) return;
k = 4096;
k -= v & 0xfff;
DCHECK_GT(k, n);
DCHECK_NOTNULL(p[0]);
DCHECK_NOTNULL(p[1]);
memcpy(p[0], b, k);
memcpy(p[1], b + k, n - k);
}
void EndStoreNp(struct Machine *m, int64_t v, size_t n, void *p[2],
uint8_t *b) {
if (v) EndStore(m, v, n, p, b);
}
void *LoadStr(struct Machine *m, int64_t addr) {
size_t have;
char *copy, *page, *p;
have = 4096 - (addr & 0xfff);
if (!addr) return NULL;
if (!(page = FindReal(m, addr))) return NULL;
if ((p = memchr(page, '\0', have))) {
SetReadAddr(m, addr, p - page + 1);
return page;
}
CHECK_LT(m->freelist.i, ARRAYLEN(m->freelist.p));
if (!(copy = malloc(have + 4096))) return NULL;
memcpy(copy, page, have);
for (;;) {
if (!(page = FindReal(m, addr + have))) break;
if ((p = memccpy(copy + have, page, '\0', 4096))) {
SetReadAddr(m, addr, have + (p - (copy + have)) + 1);
return (m->freelist.p[m->freelist.i++] = copy);
}
have += 4096;
if (!(p = realloc(copy, have + 4096))) break;
copy = p;
}
free(copy);
return NULL;
}
void *LoadBuf(struct Machine *m, int64_t addr, size_t size) {
size_t have, need;
char *buf, *copy, *page;
have = 4096 - (addr & 0xfff);
if (!addr) return NULL;
if (!(buf = FindReal(m, addr))) return NULL;
if (size > have) {
CHECK_LT(m->freelist.i, ARRAYLEN(m->freelist.p));
if (!(copy = malloc(size))) return NULL;
buf = memcpy(copy, buf, have);
do {
need = MIN(4096, size - have);
if ((page = FindReal(m, addr + have))) {
memcpy(copy + have, page, need);
have += need;
} else {
free(copy);
return NULL;
}
} while (have < size);
}
SetReadAddr(m, addr, size);
return buf;
}

View file

@ -1,34 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_MEMORY_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_MEMORY_H_
#include "tool/build/lib/machine.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
int RegisterMemory(struct Machine *, int64_t, void *, size_t);
uint64_t FindPage(struct Machine *, int64_t);
void *AccessRam(struct Machine *, int64_t, size_t, void *[2], uint8_t *, bool);
void *BeginLoadStore(struct Machine *, int64_t, size_t, void *[2], uint8_t *);
void *BeginStore(struct Machine *, int64_t, size_t, void *[2], uint8_t *);
void *BeginStoreNp(struct Machine *, int64_t, size_t, void *[2], uint8_t *);
void *FindReal(struct Machine *, int64_t);
void *Load(struct Machine *, int64_t, size_t, uint8_t *);
void *LoadBuf(struct Machine *, int64_t, size_t);
void *LoadStr(struct Machine *, int64_t);
void *MallocPage(void);
void *RealAddress(struct Machine *, int64_t);
void *ReserveAddress(struct Machine *, int64_t, size_t);
void *ResolveAddress(struct Machine *, int64_t);
void *VirtualSend(struct Machine *, void *, int64_t, uint64_t);
void EndStore(struct Machine *, int64_t, size_t, void *[2], uint8_t *);
void EndStoreNp(struct Machine *, int64_t, size_t, void *[2], uint8_t *);
void ResetRam(struct Machine *);
void SetReadAddr(struct Machine *, int64_t, uint32_t);
void SetWriteAddr(struct Machine *, int64_t, uint32_t);
void VirtualRecv(struct Machine *, int64_t, void *, uint64_t);
void VirtualRecvWrite(struct Machine *, int64_t, void *, uint64_t);
void VirtualSendRead(struct Machine *, void *, int64_t, uint64_t);
void VirtualSet(struct Machine *, int64_t, char, uint64_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_MEMORY_H_ */

View file

@ -1,224 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/log/check.h"
#include "libc/mem/mem.h"
#include "libc/runtime/pc.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
#include "libc/x/x.h"
#include "tool/build/lib/endian.h"
#include "tool/build/lib/machine.h"
struct Machine *NewMachine(void) {
struct Machine *m;
m = xmemalignzero(_Alignof(struct Machine), sizeof(struct Machine));
ResetCpu(m);
ResetMem(m);
return m;
}
static void FreeMachineRealFree(struct Machine *m) {
struct MachineRealFree *rf;
while ((rf = m->realfree)) {
m->realfree = rf->next;
free(rf);
}
}
void FreeMachine(struct Machine *m) {
if (m) {
FreeMachineRealFree(m);
free(m->real.p);
free(m);
}
}
void ResetMem(struct Machine *m) {
FreeMachineRealFree(m);
ResetTlb(m);
bzero(&m->memstat, sizeof(m->memstat));
m->real.i = 0;
m->cr3 = 0;
}
long AllocateLinearPage(struct Machine *m) {
long page;
if ((page = AllocateLinearPageRaw(m)) != -1) {
bzero(m->real.p + page, 4096);
}
return page;
}
long AllocateLinearPageRaw(struct Machine *m) {
uint8_t *p;
size_t i, n;
struct MachineRealFree *rf;
if ((rf = m->realfree)) {
DCHECK(rf->n);
DCHECK_EQ(0, rf->i & 4095);
DCHECK_EQ(0, rf->n & 4095);
DCHECK_LE(rf->i + rf->n, m->real.i);
i = rf->i;
rf->i += 4096;
if (!(rf->n -= 4096)) {
m->realfree = rf->next;
free(rf);
}
--m->memstat.freed;
++m->memstat.reclaimed;
} else {
i = m->real.i;
n = m->real.n;
p = m->real.p;
if (i == n) {
if (n) {
n += n >> 1;
} else {
n = 65536;
}
n = ROUNDUP(n, 4096);
if ((p = realloc(p, n))) {
m->real.p = p;
m->real.n = n;
ResetTlb(m);
++m->memstat.resizes;
} else {
return -1;
}
}
DCHECK_EQ(0, i & 4095);
DCHECK_EQ(0, n & 4095);
DCHECK_LE(i + 4096, n);
m->real.i += 4096;
++m->memstat.allocated;
}
++m->memstat.committed;
return i;
}
static uint64_t MachineRead64(struct Machine *m, unsigned long i) {
CHECK_LE(i + 8, m->real.n);
return Read64(m->real.p + i);
}
static void MachineWrite64(struct Machine *m, unsigned long i, uint64_t x) {
CHECK_LE(i + 8, m->real.n);
Write64(m->real.p + i, x);
}
int ReserveReal(struct Machine *m, size_t n) {
uint8_t *p;
DCHECK_EQ(0, n & 4095);
if (m->real.n < n) {
if ((p = realloc(m->real.p, n))) {
m->real.p = p;
m->real.n = n;
ResetTlb(m);
++m->memstat.resizes;
} else {
return -1;
}
}
return 0;
}
int ReserveVirtual(struct Machine *m, int64_t virt, size_t size, uint64_t key) {
int64_t ti, mi, pt, end, level;
for (end = virt + size;;) {
for (pt = m->cr3, level = 39; level >= 12; level -= 9) {
pt = pt & PAGE_TA;
ti = (virt >> level) & 511;
mi = (pt & PAGE_TA) + ti * 8;
pt = MachineRead64(m, mi);
if (level > 12) {
if (!(pt & 1)) {
if ((pt = AllocateLinearPage(m)) == -1) return -1;
MachineWrite64(m, mi, pt | 7);
++m->memstat.pagetables;
}
continue;
}
for (;;) {
if (!(pt & 1)) {
MachineWrite64(m, mi, key);
++m->memstat.reserved;
}
if ((virt += 4096) >= end) return 0;
if (++ti == 512) break;
pt = MachineRead64(m, (mi += 8));
}
}
}
}
int64_t FindVirtual(struct Machine *m, int64_t virt, size_t size) {
uint64_t i, pt, got;
got = 0;
do {
if (virt >= 0x800000000000) return enomem();
for (pt = m->cr3, i = 39; i >= 12; i -= 9) {
pt = MachineRead64(m, (pt & PAGE_TA) + ((virt >> i) & 511) * 8);
if (!(pt & 1)) break;
}
if (i >= 12) {
got += 1ull << i;
} else {
virt += 4096;
got = 0;
}
} while (got < size);
return virt;
}
static void AppendRealFree(struct Machine *m, uint64_t real) {
struct MachineRealFree *rf;
if (m->realfree && real == m->realfree->i + m->realfree->n) {
m->realfree->n += 4096;
} else if ((rf = malloc(sizeof(struct MachineRealFree)))) {
rf->i = real;
rf->n = 4096;
rf->next = m->realfree;
m->realfree = rf;
}
}
int FreeVirtual(struct Machine *m, int64_t base, size_t size) {
uint64_t i, mi, pt, end, virt;
for (virt = base, end = virt + size; virt < end; virt += 1ull << i) {
for (pt = m->cr3, i = 39;; i -= 9) {
mi = (pt & PAGE_TA) + ((virt >> i) & 511) * 8;
pt = MachineRead64(m, mi);
if (!(pt & 1)) {
break;
} else if (i == 12) {
++m->memstat.freed;
if (pt & PAGE_RSRV) {
--m->memstat.reserved;
} else {
--m->memstat.committed;
AppendRealFree(m, pt & PAGE_TA);
}
MachineWrite64(m, mi, 0);
break;
}
}
}
ResetTlb(m);
return 0;
}

View file

@ -1,66 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/log/check.h"
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"
#include "libc/str/str.h"
#include "libc/str/strwidth.h"
#include "tool/build/lib/buffer.h"
#include "tool/build/lib/lines.h"
#include "tool/build/lib/panel.h"
static int GetWidthOfLongestLine(struct Lines *lines) {
int i, w, m;
for (m = i = 0; i < lines->n; ++i) {
w = strwidth(lines->p[i], 0);
m = MAX(m, w);
}
return m;
}
void PrintMessageBox(int fd, const char *msg, long tyn, long txn) {
struct Buffer b;
int i, w, h, x, y;
struct Lines *lines;
lines = NewLines();
AppendLines(lines, msg);
h = 3 + lines->n + 3;
w = 4 + GetWidthOfLongestLine(lines) + 4;
x = (txn / 2. - w / 2.) + .5;
y = (tyn / 2. - h / 2.) + .5;
bzero(&b, sizeof(b));
AppendFmt(&b, "\e[%d;%dH", y++, x);
for (i = 0; i < w; ++i) AppendStr(&b, " ");
AppendFmt(&b, "\e[%d;%dH ╔", y++, x);
for (i = 0; i < w - 4; ++i) AppendStr(&b, "");
AppendStr(&b, "");
AppendFmt(&b, "\e[%d;%dH ║ %-*s ║ ", y++, x, w - 8, "");
for (i = 0; i < lines->n; ++i) {
AppendFmt(&b, "\e[%d;%dH ║ %-*s ║ ", y++, x, w - 8, lines->p[i]);
}
FreeLines(lines);
AppendFmt(&b, "\e[%d;%dH ║ %-*s ║ ", y++, x, w - 8, "");
AppendFmt(&b, "\e[%d;%dH ╚", y++, x);
for (i = 0; i < w - 4; ++i) AppendStr(&b, "");
AppendStr(&b, "");
AppendFmt(&b, "\e[%d;%dH", y++, x);
for (i = 0; i < w; ++i) AppendStr(&b, " ");
CHECK_NE(-1, WriteBuffer(&b, fd));
free(b.p);
}

View file

@ -1,324 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "tool/build/lib/modrm.h"
#include "libc/log/check.h"
#include "third_party/xed/x86.h"
#include "tool/build/lib/address.h"
#include "tool/build/lib/endian.h"
#include "tool/build/lib/machine.h"
#include "tool/build/lib/memory.h"
#include "tool/build/lib/throw.h"
/**
* Compactly represents important parts of xed ild result.
*/
uint32_t EncodeRde(struct XedDecodedInst *x) {
uint8_t kWordLog2[2][2][2] = {{{2, 3}, {1, 3}}, {{0, 0}, {0, 0}}};
uint32_t osz = x->op.osz ^ x->op.realmode;
return kWordLog2[~x->op.opcode & 1][osz][x->op.rexw] << 28 |
x->op.mode << 26 | kXedEamode[x->op.asz][x->op.mode] << 24 |
(uint32_t)x->op.rep << 30 | x->op.mod << 22 | x->op.asz << 17 |
x->op.seg_ovd << 18 | x->op.rexw << 6 | osz << 5 |
(x->op.rex << 4 | x->op.rexb << 3 | x->op.srm) << 12 |
(x->op.rex << 4 | x->op.rexb << 3 | x->op.rm) << 7 |
(x->op.rex << 4 | x->op.rexr << 3 | x->op.reg);
}
struct AddrSeg LoadEffectiveAddress(const struct Machine *m, uint32_t rde) {
uint8_t *s = m->ds;
uint64_t i = m->xedd->op.disp;
DCHECK(!IsModrmRegister(rde));
if (Eamode(rde) != XED_MODE_REAL) {
if (!SibExists(rde)) {
if (IsRipRelative(rde)) {
if (Mode(rde) == XED_MODE_LONG) {
i += m->ip;
}
} else {
i += Read64(RegRexbRm(m, rde));
if (RexbRm(rde) == 4 || RexbRm(rde) == 5) {
s = m->ss;
}
}
} else {
if (SibHasBase(m->xedd, rde)) {
i += Read64(RegRexbBase(m, rde));
if (RexbBase(m, rde) == 4 || RexbBase(m, rde) == 5) {
s = m->ss;
}
}
if (SibHasIndex(m->xedd)) {
i += Read64(RegRexxIndex(m)) << m->xedd->op.scale;
}
}
if (Eamode(rde) == XED_MODE_LEGACY) {
i &= 0xffffffff;
}
} else {
switch (ModrmRm(rde)) {
case 0:
i += Read16(m->bx);
i += Read16(m->si);
break;
case 1:
i += Read16(m->bx);
i += Read16(m->di);
break;
case 2:
s = m->ss;
i += Read16(m->bp);
i += Read16(m->si);
break;
case 3:
s = m->ss;
i += Read16(m->bp);
i += Read16(m->di);
break;
case 4:
i += Read16(m->si);
break;
case 5:
i += Read16(m->di);
break;
case 6:
if (ModrmMod(rde)) {
s = m->ss;
i += Read16(m->bp);
}
break;
case 7:
i += Read16(m->bx);
break;
default:
__builtin_unreachable();
}
i &= 0xffff;
}
return (struct AddrSeg){i, s};
}
int64_t ComputeAddress(const struct Machine *m, uint32_t rde) {
struct AddrSeg ea;
ea = LoadEffectiveAddress(m, rde);
return AddSegment(m, rde, ea.addr, ea.seg);
}
void *ComputeReserveAddressRead(struct Machine *m, uint32_t rde, size_t n) {
int64_t v;
v = ComputeAddress(m, rde);
SetReadAddr(m, v, n);
return ReserveAddress(m, v, n);
}
void *ComputeReserveAddressRead1(struct Machine *m, uint32_t rde) {
return ComputeReserveAddressRead(m, rde, 1);
}
void *ComputeReserveAddressRead4(struct Machine *m, uint32_t rde) {
return ComputeReserveAddressRead(m, rde, 4);
}
void *ComputeReserveAddressRead8(struct Machine *m, uint32_t rde) {
return ComputeReserveAddressRead(m, rde, 8);
}
void *ComputeReserveAddressWrite(struct Machine *m, uint32_t rde, size_t n) {
int64_t v;
v = ComputeAddress(m, rde);
SetWriteAddr(m, v, n);
return ReserveAddress(m, v, n);
}
void *ComputeReserveAddressWrite1(struct Machine *m, uint32_t rde) {
return ComputeReserveAddressWrite(m, rde, 1);
}
void *ComputeReserveAddressWrite4(struct Machine *m, uint32_t rde) {
return ComputeReserveAddressWrite(m, rde, 4);
}
void *ComputeReserveAddressWrite8(struct Machine *m, uint32_t rde) {
return ComputeReserveAddressWrite(m, rde, 8);
}
uint8_t *GetModrmRegisterMmPointerRead(struct Machine *m, uint32_t rde,
size_t n) {
if (IsModrmRegister(rde)) {
return MmRm(m, rde);
} else {
return ComputeReserveAddressRead(m, rde, n);
}
}
uint8_t *GetModrmRegisterMmPointerRead8(struct Machine *m, uint32_t rde) {
return GetModrmRegisterMmPointerRead(m, rde, 8);
}
uint8_t *GetModrmRegisterMmPointerWrite(struct Machine *m, uint32_t rde,
size_t n) {
if (IsModrmRegister(rde)) {
return MmRm(m, rde);
} else {
return ComputeReserveAddressWrite(m, rde, n);
}
}
uint8_t *GetModrmRegisterMmPointerWrite8(struct Machine *m, uint32_t rde) {
return GetModrmRegisterMmPointerWrite(m, rde, 8);
}
uint8_t *GetModrmRegisterBytePointerRead(struct Machine *m, uint32_t rde) {
int64_t v;
if (IsModrmRegister(rde)) {
return ByteRexbRm(m, rde);
} else {
return ComputeReserveAddressRead1(m, rde);
}
}
uint8_t *GetModrmRegisterBytePointerWrite(struct Machine *m, uint32_t rde) {
int64_t v;
if (IsModrmRegister(rde)) {
return ByteRexbRm(m, rde);
} else {
return ComputeReserveAddressWrite1(m, rde);
}
}
uint8_t *GetModrmRegisterWordPointerRead(struct Machine *m, uint32_t rde,
size_t n) {
if (IsModrmRegister(rde)) {
return RegRexbRm(m, rde);
} else {
return ComputeReserveAddressRead(m, rde, n);
}
}
uint8_t *GetModrmRegisterWordPointerRead2(struct Machine *m, uint32_t rde) {
return GetModrmRegisterWordPointerRead(m, rde, 2);
}
uint8_t *GetModrmRegisterWordPointerRead4(struct Machine *m, uint32_t rde) {
return GetModrmRegisterWordPointerRead(m, rde, 4);
}
uint8_t *GetModrmRegisterWordPointerRead8(struct Machine *m, uint32_t rde) {
return GetModrmRegisterWordPointerRead(m, rde, 8);
}
uint8_t *GetModrmRegisterWordPointerReadOsz(struct Machine *m, uint32_t rde) {
if (!Osz(rde)) {
return GetModrmRegisterWordPointerRead8(m, rde);
} else {
return GetModrmRegisterWordPointerRead2(m, rde);
}
}
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, rde);
}
}
uint8_t *GetModrmRegisterWordPointerWrite(struct Machine *m, uint32_t rde,
size_t n) {
if (IsModrmRegister(rde)) {
return RegRexbRm(m, rde);
} else {
return ComputeReserveAddressWrite(m, rde, n);
}
}
uint8_t *GetModrmRegisterWordPointerWrite2(struct Machine *m, uint32_t rde) {
return GetModrmRegisterWordPointerWrite(m, rde, 2);
}
uint8_t *GetModrmRegisterWordPointerWrite4(struct Machine *m, uint32_t rde) {
return GetModrmRegisterWordPointerWrite(m, rde, 4);
}
uint8_t *GetModrmRegisterWordPointerWrite8(struct Machine *m, uint32_t rde) {
return GetModrmRegisterWordPointerWrite(m, rde, 8);
}
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, rde, 2);
}
}
uint8_t *GetModrmRegisterWordPointerWriteOsz(struct Machine *m, uint32_t rde) {
if (!Osz(rde)) {
return GetModrmRegisterWordPointerWrite(m, rde, 8);
} else {
return GetModrmRegisterWordPointerWrite(m, rde, 2);
}
}
uint8_t *GetModrmRegisterXmmPointerRead(struct Machine *m, uint32_t rde,
size_t n) {
if (IsModrmRegister(rde)) {
return XmmRexbRm(m, rde);
} else {
return ComputeReserveAddressRead(m, rde, n);
}
}
uint8_t *GetModrmRegisterXmmPointerRead4(struct Machine *m, uint32_t rde) {
return GetModrmRegisterXmmPointerRead(m, rde, 4);
}
uint8_t *GetModrmRegisterXmmPointerRead8(struct Machine *m, uint32_t rde) {
return GetModrmRegisterXmmPointerRead(m, rde, 8);
}
uint8_t *GetModrmRegisterXmmPointerRead16(struct Machine *m, uint32_t rde) {
return GetModrmRegisterXmmPointerRead(m, rde, 16);
}
uint8_t *GetModrmRegisterXmmPointerWrite(struct Machine *m, uint32_t rde,
size_t n) {
if (IsModrmRegister(rde)) {
return XmmRexbRm(m, rde);
} else {
return ComputeReserveAddressWrite(m, rde, n);
}
}
uint8_t *GetModrmRegisterXmmPointerWrite4(struct Machine *m, uint32_t rde) {
return GetModrmRegisterXmmPointerWrite(m, rde, 4);
}
uint8_t *GetModrmRegisterXmmPointerWrite8(struct Machine *m, uint32_t rde) {
return GetModrmRegisterXmmPointerWrite(m, rde, 8);
}
uint8_t *GetModrmRegisterXmmPointerWrite16(struct Machine *m, uint32_t rde) {
return GetModrmRegisterXmmPointerWrite(m, rde, 16);
}

View file

@ -1,100 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_MODRM_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_MODRM_H_
#include "tool/build/lib/abp.h"
#include "tool/build/lib/machine.h"
#define Rex(x) ((x & 000000000020) >> 004)
#define Osz(x) ((x & 000000000040) >> 005)
#define Rep(x) ((x & 030000000000) >> 036)
#define Rexr(x) ((x & 000000000010) >> 003)
#define Rexw(x) ((x & 000000000100) >> 006)
#define Rexb(x) ((x & 000000002000) >> 012)
#define Sego(x) ((x & 000007000000) >> 022)
#define Mode(x) ((x & 001400000000) >> 032)
#define Eamode(x) ((x & 000300000000) >> 030)
#define RexbRm(x) ((x & 000000003600) >> 007)
#define RexrReg(x) ((x & 000000000017) >> 000)
#define RegLog2(x) ((x & 006000000000) >> 034)
#define ModrmRm(x) ((x & 000000001600) >> 007)
#define ModrmReg(x) ((x & 000000000007) >> 000)
#define ModrmSrm(x) ((x & 000000070000) >> 014)
#define ModrmMod(x) ((x & 000060000000) >> 026)
#define Modrm(x) (ModrmMod(x) << 6 | ModrmReg(x) << 3 | ModrmRm(x))
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define RexbBase(m, x) (Rexb(x) << 3 | m->xedd->op.base)
#define AddrByteReg(m, k) ((uint8_t *)m->reg + kByteReg[k])
#define ByteRexrReg(m, x) AddrByteReg(m, (x & 00000000037) >> 0)
#define ByteRexbRm(m, x) AddrByteReg(m, (x & 00000007600) >> 7)
#define ByteRexbSrm(m, x) AddrByteReg(m, (x & 00000370000) >> 12)
#define RegSrm(m, x) Abp8(m->reg[(x & 00000070000) >> 12])
#define RegRexbRm(m, x) Abp8(m->reg[RexbRm(x)])
#define RegRexbSrm(m, x) Abp8(m->reg[(x & 00000170000) >> 12])
#define RegRexrReg(m, x) Abp8(m->reg[RexrReg(x)])
#define RegRexbBase(m, x) Abp8(m->reg[RexbBase(m, x)])
#define RegRexxIndex(m) Abp8(m->reg[m->xedd->op.rexx << 3 | m->xedd->op.index])
#define MmRm(m, x) Abp16(m->xmm[(x & 00000001600) >> 7])
#define MmReg(m, x) Abp16(m->xmm[(x & 00000000007) >> 0])
#define XmmRexbRm(m, x) Abp16(m->xmm[RexbRm(x)])
#define XmmRexrReg(m, x) Abp16(m->xmm[RexrReg(x)])
#define Rexx(m) m->op.rexx
#define SibBase(m) m->op.base
#define SibIndex(m) m->op.index
#define SibExists(x) (ModrmRm(x) == 4)
#define IsModrmRegister(x) (ModrmMod(x) == 3)
#define SibHasIndex(x) (SibIndex(x) != 4 || Rexx(x))
#define SibHasBase(x, r) (SibBase(x) != 5 || ModrmMod(r))
#define SibIsAbsolute(x, r) (!SibHasBase(x, r) && !SibHasIndex(x))
#define IsRipRelative(x) (Eamode(x) && ModrmRm(x) == 5 && !ModrmMod(x))
struct AddrSeg {
int64_t addr;
uint8_t *seg;
};
extern const uint8_t kByteReg[32];
uint32_t EncodeRde(struct XedDecodedInst *);
int64_t ComputeAddress(const struct Machine *, uint32_t);
struct AddrSeg LoadEffectiveAddress(const struct Machine *, uint32_t);
void *ComputeReserveAddressRead(struct Machine *, uint32_t, size_t);
void *ComputeReserveAddressRead1(struct Machine *, uint32_t);
void *ComputeReserveAddressRead4(struct Machine *, uint32_t);
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 *GetModrmRegisterWordPointerWrite2(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterWordPointerWrite4(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterWordPointerWrite8(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterWordPointerWriteOsz(struct Machine *, uint32_t);
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) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_MODRM_H_ */

View file

@ -1,216 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/log/log.h"
#include "tool/build/lib/endian.h"
#include "tool/build/lib/memory.h"
#include "tool/build/lib/modrm.h"
#include "tool/build/lib/op101.h"
#include "tool/build/lib/throw.h"
#include "tool/build/lib/time.h"
static void StoreDescriptorTable(struct Machine *m, uint32_t rde,
uint16_t limit, uint64_t base) {
uint64_t l;
l = ComputeAddress(m, rde);
if (l + 10 <= m->real.n) {
Write16(m->real.p + l, limit);
if (Rexw(rde)) {
Write64(m->real.p + l + 2, base);
SetWriteAddr(m, l, 10);
} else if (!Osz(rde)) {
Write32(m->real.p + l + 2, base);
SetWriteAddr(m, l, 6);
} else {
Write16(m->real.p + l + 2, base);
SetWriteAddr(m, l, 4);
}
} else {
ThrowSegmentationFault(m, l);
}
}
static void LoadDescriptorTable(struct Machine *m, uint32_t rde,
uint16_t *out_limit, uint64_t *out_base) {
uint16_t limit;
uint64_t l, base;
l = ComputeAddress(m, rde);
if (l + 10 <= m->real.n) {
limit = Read16(m->real.p + l);
if (Rexw(rde)) {
base = Read64(m->real.p + l + 2) & 0x00ffffff;
SetReadAddr(m, l, 10);
} else if (!Osz(rde)) {
base = Read32(m->real.p + l + 2);
SetReadAddr(m, l, 6);
} else {
base = Read16(m->real.p + l + 2);
SetReadAddr(m, l, 4);
}
if (base + limit <= m->real.n) {
*out_limit = limit;
*out_base = base;
} else {
ThrowProtectionFault(m);
}
} else {
ThrowSegmentationFault(m, l);
}
}
static void SgdtMs(struct Machine *m, uint32_t rde) {
StoreDescriptorTable(m, rde, m->gdt_limit, m->gdt_base);
}
static void LgdtMs(struct Machine *m, uint32_t rde) {
LoadDescriptorTable(m, rde, &m->gdt_limit, &m->gdt_base);
INFOF("set gdt %p lim %,d", m->gdt_base, m->gdt_limit);
}
static void SidtMs(struct Machine *m, uint32_t rde) {
StoreDescriptorTable(m, rde, m->idt_limit, m->idt_base);
}
static void LidtMs(struct Machine *m, uint32_t rde) {
LoadDescriptorTable(m, rde, &m->idt_limit, &m->idt_base);
INFOF("set idt %p lim %,d", m->idt_base, m->idt_limit);
}
static void Monitor(struct Machine *m, uint32_t rde) {
}
static void Mwait(struct Machine *m, uint32_t rde) {
}
static void Swapgs(struct Machine *m, uint32_t rde) {
}
static void Vmcall(struct Machine *m, uint32_t rde) {
}
static void Vmlaunch(struct Machine *m, uint32_t rde) {
}
static void Vmresume(struct Machine *m, uint32_t rde) {
}
static void Vmxoff(struct Machine *m, uint32_t rde) {
}
static void InvlpgM(struct Machine *m, uint32_t rde) {
ResetTlb(m);
}
static void Smsw(struct Machine *m, uint32_t rde, bool ismem) {
if (ismem) {
Write16(GetModrmRegisterWordPointerWrite2(m, rde), m->cr0);
} else if (Rexw(rde)) {
Write64(RegRexrReg(m, rde), m->cr0);
} else if (!Osz(rde)) {
Write64(RegRexrReg(m, rde), m->cr0 & 0xffffffff);
} else {
Write16(RegRexrReg(m, rde), m->cr0);
}
}
static void Lmsw(struct Machine *m, uint32_t rde) {
m->cr0 = Read16(GetModrmRegisterWordPointerRead2(m, rde));
}
void Op101(struct Machine *m, uint32_t rde) {
bool ismem;
ismem = !IsModrmRegister(rde);
switch (ModrmReg(rde)) {
case 0:
if (ismem) {
SgdtMs(m, rde);
} else {
switch (ModrmRm(rde)) {
case 1:
Vmcall(m, rde);
break;
case 2:
Vmlaunch(m, rde);
break;
case 3:
Vmresume(m, rde);
break;
case 4:
Vmxoff(m, rde);
break;
default:
OpUd(m, rde);
}
}
break;
case 1:
if (ismem) {
SidtMs(m, rde);
} else {
switch (ModrmRm(rde)) {
case 0:
Monitor(m, rde);
break;
case 1:
Mwait(m, rde);
break;
default:
OpUd(m, rde);
}
}
break;
case 2:
if (ismem) {
LgdtMs(m, rde);
} else {
OpUd(m, rde);
}
break;
case 3:
if (ismem) {
LidtMs(m, rde);
} else {
OpUd(m, rde);
}
break;
case 4:
Smsw(m, rde, ismem);
break;
case 6:
Lmsw(m, rde);
break;
case 7:
if (ismem) {
InvlpgM(m, rde);
} else {
switch (ModrmRm(rde)) {
case 0:
Swapgs(m, rde);
break;
case 1:
OpRdtscp(m, rde);
break;
default:
OpUd(m, rde);
}
}
break;
default:
OpUd(m, rde);
}
}

View file

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

View file

@ -1,62 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/mem/arraylist2.internal.h"
#include "tool/build/lib/endian.h"
#include "tool/build/lib/machine.h"
#include "tool/build/lib/pml4t.h"
static void AppendContiguousMemoryRange(struct ContiguousMemoryRanges *ranges,
int64_t a, int64_t b) {
APPEND(&ranges->p, &ranges->i, &ranges->n,
(&(struct ContiguousMemoryRange){a, b}));
}
static void FindContiguousMemoryRangesImpl(
struct Machine *m, struct ContiguousMemoryRanges *ranges, int64_t addr,
unsigned level, int64_t pt, int64_t a, int64_t b) {
int64_t i, page, entry;
for (i = a; i < b; ++i) {
entry = Read64(m->real.p + pt + i * 8);
if (!(entry & 1)) continue;
entry &= 0x7ffffffff000;
page = (int64_t)((uint64_t)(addr | i << level) << 16) >> 16;
if (level == 12) {
if (ranges->i && page == ranges->p[ranges->i - 1].b) {
ranges->p[ranges->i - 1].b += 0x1000;
} else {
AppendContiguousMemoryRange(ranges, page, page + 0x1000);
}
} else if (entry + 512 * 8 <= m->real.n) {
FindContiguousMemoryRangesImpl(m, ranges, page, level - 9, entry, 0, 512);
}
}
}
void FindContiguousMemoryRanges(struct Machine *m,
struct ContiguousMemoryRanges *ranges) {
uint64_t cr3;
ranges->i = 0;
if ((m->mode & 3) == XED_MODE_LONG) {
cr3 = m->cr3 & 0x7ffffffff000;
FindContiguousMemoryRangesImpl(m, ranges, 0, 39, cr3, 256, 512);
FindContiguousMemoryRangesImpl(m, ranges, 0, 39, cr3, 0, 256);
} else {
AppendContiguousMemoryRange(ranges, 0, m->real.n);
}
}

View file

@ -1,25 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_PML4T_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_PML4T_H_
#include "tool/build/lib/machine.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define IsValidPage(x) ((x)&1)
#define MaskPageAddr(x) ((x)&0x00007ffffffff000)
#define UnmaskPageAddr(x) SignExtendAddr(MaskPageAddr(x))
#define SignExtendAddr(x) ((int64_t)((uint64_t)(x) << 16) >> 16)
struct ContiguousMemoryRanges {
size_t i, n;
struct ContiguousMemoryRange {
int64_t a;
int64_t b;
} * p;
};
void FindContiguousMemoryRanges(struct Machine *,
struct ContiguousMemoryRanges *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_PML4T_H_ */

View file

@ -1,118 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/log/check.h"
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"
#include "libc/x/x.h"
#include "tool/build/lib/buffer.h"
#include "tool/build/lib/memory.h"
#include "tool/build/lib/pml4t.h"
struct Pml4tFormatter {
bool t;
int64_t start;
struct Buffer b;
long lines;
};
static int64_t MakeAddress(unsigned short a[4]) {
uint64_t x;
x = 0;
x |= a[0];
x <<= 9;
x |= a[1];
x <<= 9;
x |= a[2];
x <<= 9;
x |= a[3];
x <<= 12;
return x;
}
static void FormatStartPage(struct Pml4tFormatter *pp, int64_t start) {
pp->t = true;
pp->start = start;
if (pp->lines++) AppendChar(&pp->b, '\n');
AppendFmt(&pp->b, "%012lx-", start);
}
static void FormatEndPage(struct Pml4tFormatter *pp, int64_t end) {
int64_t size;
pp->t = false;
size = end - pp->start;
AppendFmt(&pp->b, "%012lx %012lx %,ld bytes", end - 1, size, size);
}
static void *GetPt(struct Machine *m, uint64_t r) {
CHECK_LE(r + 0x1000, m->real.n);
return m->real.p + r;
}
char *FormatPml4t(struct Machine *m) {
uint64_t *pd[4];
unsigned short i, a[4];
struct Pml4tFormatter pp = {0};
unsigned short range[][2] = {{256, 512}, {0, 256}};
if ((m->mode & 3) != XED_MODE_LONG) return strdup("");
pd[0] = GetPt(m, m->cr3);
for (i = 0; i < ARRAYLEN(range); ++i) {
a[0] = range[i][0];
do {
a[1] = a[2] = a[3] = 0;
if (!IsValidPage(pd[0][a[0]])) {
if (pp.t) FormatEndPage(&pp, MakeAddress(a));
} else {
pd[1] = GetPt(m, UnmaskPageAddr(pd[0][a[0]]));
do {
a[2] = a[3] = 0;
if (!IsValidPage(pd[1][a[1]])) {
if (pp.t) FormatEndPage(&pp, MakeAddress(a));
} else {
pd[2] = GetPt(m, UnmaskPageAddr(pd[1][a[1]]));
do {
a[3] = 0;
if (!IsValidPage(pd[2][a[2]])) {
if (pp.t) FormatEndPage(&pp, MakeAddress(a));
} else {
pd[3] = GetPt(m, UnmaskPageAddr(pd[2][a[2]]));
do {
if (!IsValidPage(pd[3][a[3]])) {
if (pp.t) FormatEndPage(&pp, MakeAddress(a));
} else {
if (!pp.t) {
FormatStartPage(&pp, MakeAddress(a));
}
}
} while (++a[3] != 512);
}
} while (++a[2] != 512);
}
} while (++a[1] != 512);
}
} while (++a[0] != range[i][1]);
}
if (pp.t) {
FormatEndPage(&pp, 0x800000000000);
}
if (pp.b.p) {
return xrealloc(pp.b.p, pp.b.i + 1);
} else {
return strdup("");
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,82 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_PTY_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_PTY_H_
#include "tool/build/lib/buffer.h"
#define kPtyFg 0x0001
#define kPtyBg 0x0002
#define kPtyBold 0x0004
#define kPtyFlip 0x0008
#define kPtyFaint 0x0010
#define kPtyUnder 0x0020
#define kPtyDunder 0x0040
#define kPtyTrue 0x0080
#define kPtyBlink 0x0100
#define kPtyItalic 0x0200
#define kPtyFraktur 0x0400
#define kPtyStrike 0x0800
#define kPtyConceal 0x1000
#define kPtyBell 0x001
#define kPtyRedzone 0x002
#define kPtyNocursor 0x004
#define kPtyBlinkcursor 0x008
#define kPtyNocanon 0x010
#define kPtyNoecho 0x020
#define kPtyNoopost 0x040
#define kPtyLed1 0x080
#define kPtyLed2 0x100
#define kPtyLed3 0x200
#define kPtyLed4 0x400
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct Pty {
int y;
int x;
int yn;
int xn;
uint32_t u8;
uint32_t n8;
uint32_t pr;
uint32_t fg;
uint32_t bg;
uint32_t conf;
uint32_t save;
uint32_t *wcs;
uint32_t *prs;
uint32_t *fgs;
uint32_t *bgs;
wchar_t *xlat;
enum PtyState {
kPtyAscii,
kPtyUtf8,
kPtyEsc,
kPtyCsi,
} state;
struct PtyEsc {
unsigned i;
char s[64];
} esc;
struct PtyInput {
size_t i, n;
char *p;
} input;
};
void FreePty(struct Pty *);
struct Pty *NewPty(void) dontdiscard;
void PtyResize(struct Pty *, int, int);
ssize_t PtyRead(struct Pty *, void *, size_t);
ssize_t PtyWrite(struct Pty *, const void *, size_t);
ssize_t PtyWriteInput(struct Pty *, const void *, size_t);
int PtyAppendLine(struct Pty *, struct Buffer *, unsigned);
void PtyFullReset(struct Pty *);
void PtyMemmove(struct Pty *, long, long, long);
void PtyErase(struct Pty *, long, long);
void PtySetY(struct Pty *, int);
void PtySetX(struct Pty *, int);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_PTY_H_ */

View file

@ -1,28 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_PUN_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_PUN_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
union FloatPun {
float f;
uint32_t i;
};
union DoublePun {
double f;
uint64_t i;
};
union FloatVectorPun {
union FloatPun u[4];
float f[4];
};
union DoubleVectorPun {
union DoublePun u[2];
double f[2];
};
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_PUN_H_ */

View file

@ -1,96 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/macros.internal.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"
#define LDBL 3
#define RINT 0
static void ResetFpu(struct Machine *m) {
long i;
long double fval;
fval = -NAN;
m->fpu.sw = 0;
m->fpu.tw = -1;
m->fpu.cw = 0;
m->fpu.im = true;
m->fpu.dm = true;
m->fpu.zm = true;
m->fpu.om = true;
m->fpu.um = true;
m->fpu.pm = true;
m->fpu.pc = LDBL;
m->fpu.rc = RINT;
for (i = 0; i < ARRAYLEN(m->fpu.st); ++i) {
memcpy(&m->fpu.st[i], &fval, sizeof(fval));
}
}
static void ResetSse(struct Machine *m) {
m->sse.mxcsr = 0;
m->sse.daz = false;
m->sse.im = true;
m->sse.dm = true;
m->sse.zm = true;
m->sse.om = true;
m->sse.um = true;
m->sse.pm = true;
m->sse.rc = RINT;
m->sse.ftz = false;
bzero(m->xmm, sizeof(m->xmm));
}
void ResetInstructionCache(struct Machine *m) {
memset(m->icache, -1, sizeof(m->icache));
}
void ResetCpu(struct Machine *m) {
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);
m->flags = SetFlag(m->flags, FLAGS_SF, false);
m->flags = SetFlag(m->flags, FLAGS_IF, true);
m->flags = SetFlag(m->flags, FLAGS_F1, true);
m->flags = SetFlag(m->flags, FLAGS_F0, false);
m->flags = SetFlag(m->flags, FLAGS_IOPL, 3);
bzero(m->reg, sizeof(m->reg));
bzero(m->bofram, sizeof(m->bofram));
bzero(&m->freelist, sizeof(m->freelist));
ResetSse(m);
ResetFpu(m);
}
void ResetTlb(struct Machine *m) {
m->tlbindex = 0;
bzero(m->tlb, sizeof(m->tlb));
m->codevirt = 0;
m->codehost = 0;
}

View file

@ -1,165 +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 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/macros.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "tool/build/lib/bits.h"
#include "tool/build/lib/endian.h"
#include "tool/build/lib/machine.h"
#include "tool/build/lib/memory.h"
#include "tool/build/lib/signal.h"
#include "tool/build/lib/xlat.h"
#define SIGCHLD_LINUX 17
#define SIGURG_LINUX 23
#define SIGWINCH_LINUX 28
void OpRestore(struct Machine *m) {
union {
struct fpstate_bits fp;
struct ucontext_bits uc;
} u;
VirtualSendRead(m, &u.uc, m->siguc, sizeof(u.uc));
m->ip = Read64(u.uc.rip);
m->flags = Read64(u.uc.eflags);
memcpy(m->r8, u.uc.r8, 8);
memcpy(m->r9, u.uc.r9, 8);
memcpy(m->r10, u.uc.r10, 8);
memcpy(m->r11, u.uc.r11, 8);
memcpy(m->r12, u.uc.r12, 8);
memcpy(m->r13, u.uc.r13, 8);
memcpy(m->r14, u.uc.r14, 8);
memcpy(m->r15, u.uc.r15, 8);
memcpy(m->di, u.uc.rdi, 8);
memcpy(m->si, u.uc.rsi, 8);
memcpy(m->bp, u.uc.rbp, 8);
memcpy(m->bx, u.uc.rbx, 8);
memcpy(m->dx, u.uc.rdx, 8);
memcpy(m->ax, u.uc.rax, 8);
memcpy(m->cx, u.uc.rcx, 8);
memcpy(m->sp, u.uc.rsp, 8);
VirtualSendRead(m, &u.fp, m->sigfp, sizeof(u.fp));
m->fpu.cw = Read16(u.fp.cwd);
m->fpu.sw = Read16(u.fp.swd);
m->fpu.tw = Read16(u.fp.ftw);
m->fpu.op = Read16(u.fp.fop);
m->fpu.ip = Read64(u.fp.rip);
m->fpu.dp = Read64(u.fp.rdp);
memcpy(m->fpu.st, u.fp.st, 128);
memcpy(m->xmm, u.fp.xmm, 256);
m->sig = 0;
}
int DeliverSignal(struct Machine *m, int sig, int code) {
uint64_t sp, siaddr;
static struct siginfo_bits si;
static struct fpstate_bits fp;
static struct ucontext_bits uc;
switch (Read64(m->sighand[sig - 1].handler)) {
case 1: // SIG_IGN
return 0;
case 0: // SIG_DFL
if (sig == SIGCHLD_LINUX || sig == SIGURG_LINUX ||
sig == SIGWINCH_LINUX) {
return 0;
}
raise(sig);
_exit(128 + sig);
default:
break;
}
Write32(si.si_signo, sig);
Write32(si.si_code, code);
memcpy(uc.r8, m->r8, 8);
memcpy(uc.r9, m->r9, 8);
memcpy(uc.r10, m->r10, 8);
memcpy(uc.r11, m->r11, 8);
memcpy(uc.r12, m->r12, 8);
memcpy(uc.r13, m->r13, 8);
memcpy(uc.r14, m->r14, 8);
memcpy(uc.r15, m->r15, 8);
memcpy(uc.rdi, m->di, 8);
memcpy(uc.rsi, m->si, 8);
memcpy(uc.rbp, m->bp, 8);
memcpy(uc.rbx, m->bx, 8);
memcpy(uc.rdx, m->dx, 8);
memcpy(uc.rax, m->ax, 8);
memcpy(uc.rcx, m->cx, 8);
memcpy(uc.rsp, m->sp, 8);
Write64(uc.rip, m->ip);
Write64(uc.eflags, m->flags);
Write16(fp.cwd, m->fpu.cw);
Write16(fp.swd, m->fpu.sw);
Write16(fp.ftw, m->fpu.tw);
Write16(fp.fop, m->fpu.op);
Write64(fp.rip, m->fpu.ip);
Write64(fp.rdp, m->fpu.dp);
memcpy(fp.st, m->fpu.st, 128);
memcpy(fp.xmm, m->xmm, 256);
sp = Read64(m->sp);
sp = ROUNDDOWN(sp - sizeof(si), 16);
VirtualRecvWrite(m, sp, &si, sizeof(si));
siaddr = sp;
sp = ROUNDDOWN(sp - sizeof(fp), 16);
VirtualRecvWrite(m, sp, &fp, sizeof(fp));
m->sigfp = sp;
Write64(uc.fpstate, sp);
sp = ROUNDDOWN(sp - sizeof(uc), 16);
VirtualRecvWrite(m, sp, &uc, sizeof(uc));
m->siguc = sp;
m->sig = sig;
sp -= 8;
VirtualRecvWrite(m, sp, m->sighand[sig - 1].restorer, 8);
Write64(m->sp, sp);
Write64(m->di, sig);
Write64(m->si, siaddr);
Write64(m->dx, m->siguc);
m->ip = Read64(m->sighand[sig - 1].handler);
return 0;
}
void EnqueueSignal(struct Machine *m, int sig, int code) {
if (m->signals.n < ARRAYLEN(m->signals.p)) {
m->signals.p[m->signals.n].code = UnXlatSicode(sig, code);
m->signals.p[m->signals.n].sig = UnXlatSignal(sig);
m->signals.n++;
}
}
int ConsumeSignal(struct Machine *m) {
int sig, code;
sig = m->signals.p[m->signals.i].sig;
code = m->signals.p[m->signals.i].code;
if (!m->sig ||
((sig != m->sig || (Read64(m->sighand[m->sig - 1].flags) & 0x40000000)) &&
!(Read64(m->sighand[m->sig - 1].mask) & (1ull << (m->sig - 1))))) {
if (++m->signals.i == m->signals.n) m->signals.i = m->signals.n = 0;
return DeliverSignal(m, sig, code);
}
return 0;
}
void TerminateSignal(struct Machine *m, int sig) {
if (m->isfork) {
_exit(28 + sig);
} else {
exit(128 + sig);
}
}

View file

@ -1,15 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_SIGNAL_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_SIGNAL_H_
#include "tool/build/lib/machine.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
void OpRestore(struct Machine *);
void TerminateSignal(struct Machine *, int);
int DeliverSignal(struct Machine *, int, int);
int ConsumeSignal(struct Machine *);
void EnqueueSignal(struct Machine *, int, int);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_SIGNAL_H_ */

File diff suppressed because it is too large Load diff

View file

@ -1,87 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_SSE_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_SSE_H_
#include "tool/build/lib/machine.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
void Op171(struct Machine *, uint32_t);
void Op172(struct Machine *, uint32_t);
void Op173(struct Machine *, uint32_t);
void OpSsePabsb(struct Machine *, uint32_t);
void OpSsePabsd(struct Machine *, uint32_t);
void OpSsePabsw(struct Machine *, uint32_t);
void OpSsePackssdw(struct Machine *, uint32_t);
void OpSsePacksswb(struct Machine *, uint32_t);
void OpSsePackuswb(struct Machine *, uint32_t);
void OpSsePaddb(struct Machine *, uint32_t);
void OpSsePaddd(struct Machine *, uint32_t);
void OpSsePaddq(struct Machine *, uint32_t);
void OpSsePaddsb(struct Machine *, uint32_t);
void OpSsePaddsw(struct Machine *, uint32_t);
void OpSsePaddusb(struct Machine *, uint32_t);
void OpSsePaddusw(struct Machine *, uint32_t);
void OpSsePaddw(struct Machine *, uint32_t);
void OpSsePalignr(struct Machine *, uint32_t);
void OpSsePand(struct Machine *, uint32_t);
void OpSsePandn(struct Machine *, uint32_t);
void OpSsePavgb(struct Machine *, uint32_t);
void OpSsePavgw(struct Machine *, uint32_t);
void OpSsePcmpeqb(struct Machine *, uint32_t);
void OpSsePcmpeqd(struct Machine *, uint32_t);
void OpSsePcmpeqw(struct Machine *, uint32_t);
void OpSsePcmpgtb(struct Machine *, uint32_t);
void OpSsePcmpgtd(struct Machine *, uint32_t);
void OpSsePcmpgtw(struct Machine *, uint32_t);
void OpSsePhaddd(struct Machine *, uint32_t);
void OpSsePhaddsw(struct Machine *, uint32_t);
void OpSsePhaddw(struct Machine *, uint32_t);
void OpSsePhsubd(struct Machine *, uint32_t);
void OpSsePhsubsw(struct Machine *, uint32_t);
void OpSsePhsubw(struct Machine *, uint32_t);
void OpSsePmaddubsw(struct Machine *, uint32_t);
void OpSsePmaddwd(struct Machine *, uint32_t);
void OpSsePmaxsw(struct Machine *, uint32_t);
void OpSsePmaxub(struct Machine *, uint32_t);
void OpSsePminsw(struct Machine *, uint32_t);
void OpSsePminub(struct Machine *, uint32_t);
void OpSsePmulhrsw(struct Machine *, uint32_t);
void OpSsePmulhuw(struct Machine *, uint32_t);
void OpSsePmulhw(struct Machine *, uint32_t);
void OpSsePmulld(struct Machine *, uint32_t);
void OpSsePmullw(struct Machine *, uint32_t);
void OpSsePmuludq(struct Machine *, uint32_t);
void OpSsePor(struct Machine *, uint32_t);
void OpSsePsadbw(struct Machine *, uint32_t);
void OpSsePshufb(struct Machine *, uint32_t);
void OpSsePsignb(struct Machine *, uint32_t);
void OpSsePsignd(struct Machine *, uint32_t);
void OpSsePsignw(struct Machine *, uint32_t);
void OpSsePslldv(struct Machine *, uint32_t);
void OpSsePsllqv(struct Machine *, uint32_t);
void OpSsePsllwv(struct Machine *, uint32_t);
void OpSsePsradv(struct Machine *, uint32_t);
void OpSsePsrawv(struct Machine *, uint32_t);
void OpSsePsrldv(struct Machine *, uint32_t);
void OpSsePsrlqv(struct Machine *, uint32_t);
void OpSsePsrlwv(struct Machine *, uint32_t);
void OpSsePsubb(struct Machine *, uint32_t);
void OpSsePsubd(struct Machine *, uint32_t);
void OpSsePsubq(struct Machine *, uint32_t);
void OpSsePsubsb(struct Machine *, uint32_t);
void OpSsePsubsw(struct Machine *, uint32_t);
void OpSsePsubusb(struct Machine *, uint32_t);
void OpSsePsubusw(struct Machine *, uint32_t);
void OpSsePsubw(struct Machine *, uint32_t);
void OpSsePunpckhbw(struct Machine *, uint32_t);
void OpSsePunpckhdq(struct Machine *, uint32_t);
void OpSsePunpckhqdq(struct Machine *, uint32_t);
void OpSsePunpckhwd(struct Machine *, uint32_t);
void OpSsePunpcklbw(struct Machine *, uint32_t);
void OpSsePunpckldq(struct Machine *, uint32_t);
void OpSsePunpcklqdq(struct Machine *, uint32_t);
void OpSsePunpcklwd(struct Machine *, uint32_t);
void OpSsePxor(struct Machine *, uint32_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_SSE_H_ */

View file

@ -1,719 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.internal.h"
#include "libc/math.h"
#include "libc/str/str.h"
#include "tool/build/lib/endian.h"
#include "tool/build/lib/flags.h"
#include "tool/build/lib/fpu.h"
#include "tool/build/lib/modrm.h"
#include "tool/build/lib/pun.h"
#include "tool/build/lib/ssefloat.h"
#include "tool/build/lib/throw.h"
static void pshufw(int16_t b[4], const int16_t a[4], int m) {
int16_t t[4];
t[0] = a[(m & 0003) >> 0];
t[1] = a[(m & 0014) >> 2];
t[2] = a[(m & 0060) >> 4];
t[3] = a[(m & 0300) >> 6];
b[0] = t[0];
b[1] = t[1];
b[2] = t[2];
b[3] = t[3];
}
static void pshufd(int32_t b[4], const int32_t a[4], int m) {
int32_t t[4];
t[0] = a[(m & 0003) >> 0];
t[1] = a[(m & 0014) >> 2];
t[2] = a[(m & 0060) >> 4];
t[3] = a[(m & 0300) >> 6];
b[0] = t[0];
b[1] = t[1];
b[2] = t[2];
b[3] = t[3];
}
static void pshuflw(int16_t b[8], const int16_t a[8], int m) {
int16_t t[4];
t[0] = a[(m & 0003) >> 0];
t[1] = a[(m & 0014) >> 2];
t[2] = a[(m & 0060) >> 4];
t[3] = a[(m & 0300) >> 6];
b[0] = t[0];
b[1] = t[1];
b[2] = t[2];
b[3] = t[3];
b[4] = a[4];
b[5] = a[5];
b[6] = a[6];
b[7] = a[7];
}
static void pshufhw(int16_t b[8], const int16_t a[8], int m) {
int16_t t[4];
t[0] = a[4 + ((m & 0003) >> 0)];
t[1] = a[4 + ((m & 0014) >> 2)];
t[2] = a[4 + ((m & 0060) >> 4)];
t[3] = a[4 + ((m & 0300) >> 6)];
b[0] = a[0];
b[1] = a[1];
b[2] = a[2];
b[3] = a[3];
b[4] = t[0];
b[5] = t[1];
b[6] = t[2];
b[7] = t[3];
}
void OpUnpcklpsd(struct Machine *m, uint32_t rde) {
uint8_t *a, *b;
a = XmmRexrReg(m, rde);
b = GetModrmRegisterXmmPointerRead8(m, rde);
if (Osz(rde)) {
memcpy(a + 8, b, 8);
} else {
memcpy(a + 4 * 3, b + 4, 4);
memcpy(a + 4 * 2, a + 4, 4);
memcpy(a + 4 * 1, b + 0, 4);
}
}
void OpUnpckhpsd(struct Machine *m, uint32_t rde) {
uint8_t *a, *b;
a = XmmRexrReg(m, rde);
b = GetModrmRegisterXmmPointerRead16(m, rde);
if (Osz(rde)) {
memcpy(a + 0, b + 8, 8);
memcpy(a + 8, b + 8, 8);
} else {
memcpy(a + 4 * 0, a + 4 * 2, 4);
memcpy(a + 4 * 1, b + 4 * 2, 4);
memcpy(a + 4 * 2, a + 4 * 3, 4);
memcpy(a + 4 * 3, b + 4 * 3, 4);
}
}
void OpPextrwGdqpUdqIb(struct Machine *m, uint32_t rde) {
uint8_t i;
i = m->xedd->op.uimm0;
i &= Osz(rde) ? 7 : 3;
Write16(RegRexrReg(m, rde), Read16(XmmRexbRm(m, rde) + i * 2));
}
void OpPinsrwVdqEwIb(struct Machine *m, uint32_t rde) {
uint8_t i;
i = m->xedd->op.uimm0;
i &= Osz(rde) ? 7 : 3;
Write16(XmmRexrReg(m, rde) + i * 2,
Read16(GetModrmRegisterWordPointerRead2(m, rde)));
}
void OpShuffle(struct Machine *m, uint32_t rde) {
int16_t q16[4];
int16_t x16[8];
int32_t x32[4];
switch (Rep(rde) | Osz(rde)) {
case 0:
memcpy(q16, GetModrmRegisterXmmPointerRead8(m, rde), 8);
pshufw(q16, q16, m->xedd->op.uimm0);
memcpy(XmmRexrReg(m, rde), q16, 8);
break;
case 1:
memcpy(x32, GetModrmRegisterXmmPointerRead16(m, rde), 16);
pshufd(x32, x32, m->xedd->op.uimm0);
memcpy(XmmRexrReg(m, rde), x32, 16);
break;
case 2:
memcpy(x16, GetModrmRegisterXmmPointerRead16(m, rde), 16);
pshuflw(x16, x16, m->xedd->op.uimm0);
memcpy(XmmRexrReg(m, rde), x16, 16);
break;
case 3:
memcpy(x16, GetModrmRegisterXmmPointerRead16(m, rde), 16);
pshufhw(x16, x16, m->xedd->op.uimm0);
memcpy(XmmRexrReg(m, rde), x16, 16);
break;
default:
for (;;) (void)0;
}
}
static void Shufps(struct Machine *m, uint32_t rde) {
uint8_t *p;
union FloatPun x[4], y[4], z[4];
p = GetModrmRegisterXmmPointerRead16(m, rde);
y[0].i = Read32(p + 0 * 4);
y[1].i = Read32(p + 1 * 4);
y[2].i = Read32(p + 2 * 4);
y[3].i = Read32(p + 3 * 4);
p = XmmRexrReg(m, rde);
x[0].i = Read32(p + 0 * 4);
x[1].i = Read32(p + 1 * 4);
x[2].i = Read32(p + 2 * 4);
x[3].i = Read32(p + 3 * 4);
z[0].f = y[(m->xedd->op.uimm0 & 0003) >> 0].f;
z[1].f = y[(m->xedd->op.uimm0 & 0014) >> 2].f;
z[2].f = x[(m->xedd->op.uimm0 & 0060) >> 4].f;
z[3].f = x[(m->xedd->op.uimm0 & 0300) >> 6].f;
Write32(p + 0 * 4, z[0].i);
Write32(p + 1 * 4, z[1].i);
Write32(p + 2 * 4, z[2].i);
Write32(p + 3 * 4, z[3].i);
}
static void Shufpd(struct Machine *m, uint32_t rde) {
uint8_t *p;
union DoublePun x[2], y[2], z[2];
p = GetModrmRegisterXmmPointerRead16(m, rde);
y[0].i = Read64(p + 0 * 4);
y[1].i = Read64(p + 1 * 4);
p = XmmRexrReg(m, rde);
x[0].i = Read64(p + 0 * 4);
x[1].i = Read64(p + 1 * 4);
z[0].f = y[(m->xedd->op.uimm0 & 0001) >> 0].f;
z[1].f = x[(m->xedd->op.uimm0 & 0002) >> 1].f;
Write64(p + 0 * 4, z[0].i);
Write64(p + 1 * 4, z[1].i);
}
void OpShufpsd(struct Machine *m, uint32_t rde) {
if (Osz(rde)) {
Shufpd(m, rde);
} else {
Shufps(m, rde);
}
}
void OpSqrtpsd(struct Machine *m, uint32_t rde) {
switch (Rep(rde) | Osz(rde)) {
case 0: {
int i;
uint8_t *p;
union FloatPun u[4];
p = GetModrmRegisterXmmPointerRead16(m, rde);
u[0].i = Read32(p + 0 * 4);
u[1].i = Read32(p + 1 * 4);
u[2].i = Read32(p + 2 * 4);
u[3].i = Read32(p + 3 * 4);
for (i = 0; i < 4; ++i) u[i].f = sqrtf(u[i].f);
p = XmmRexrReg(m, rde);
Write32(p + 0 * 4, u[0].i);
Write32(p + 1 * 4, u[1].i);
Write32(p + 2 * 4, u[2].i);
Write32(p + 3 * 4, u[3].i);
break;
}
case 1: {
int i;
uint8_t *p;
union DoublePun u[2];
p = GetModrmRegisterXmmPointerRead16(m, rde);
u[0].i = Read32(p + 0 * 8);
u[1].i = Read32(p + 1 * 8);
for (i = 0; i < 2; ++i) u[i].f = sqrt(u[i].f);
p = XmmRexrReg(m, rde);
Write32(p + 0 * 8, u[0].i);
Write32(p + 1 * 8, u[1].i);
break;
}
case 2: {
union DoublePun u;
u.i = Read64(GetModrmRegisterXmmPointerRead8(m, rde));
u.f = sqrt(u.f);
Write64(XmmRexrReg(m, rde), u.i);
break;
}
case 3: {
union FloatPun u;
u.i = Read32(GetModrmRegisterXmmPointerRead4(m, rde));
u.f = sqrtf(u.f);
Write32(XmmRexrReg(m, rde), u.i);
break;
}
default:
for (;;) (void)0;
}
}
void OpRsqrtps(struct Machine *m, uint32_t rde) {
if (Rep(rde) != 3) {
int i;
uint8_t *p;
union FloatPun u[4];
p = GetModrmRegisterXmmPointerRead16(m, rde);
u[0].i = Read32(p + 0 * 4);
u[1].i = Read32(p + 1 * 4);
u[2].i = Read32(p + 2 * 4);
u[3].i = Read32(p + 3 * 4);
for (i = 0; i < 4; ++i) u[i].f = 1.f / sqrtf(u[i].f);
p = XmmRexrReg(m, rde);
Write32(p + 0 * 4, u[0].i);
Write32(p + 1 * 4, u[1].i);
Write32(p + 2 * 4, u[2].i);
Write32(p + 3 * 4, u[3].i);
} else {
union FloatPun u;
u.i = Read32(GetModrmRegisterXmmPointerRead4(m, rde));
u.f = 1.f / sqrtf(u.f);
Write32(XmmRexrReg(m, rde), u.i);
}
}
void OpRcpps(struct Machine *m, uint32_t rde) {
if (Rep(rde) != 3) {
int i;
uint8_t *p;
union FloatPun u[4];
p = GetModrmRegisterXmmPointerRead16(m, rde);
u[0].i = Read32(p + 0 * 4);
u[1].i = Read32(p + 1 * 4);
u[2].i = Read32(p + 2 * 4);
u[3].i = Read32(p + 3 * 4);
for (i = 0; i < 4; ++i) u[i].f = 1.f / u[i].f;
p = XmmRexrReg(m, rde);
Write32(p + 0 * 4, u[0].i);
Write32(p + 1 * 4, u[1].i);
Write32(p + 2 * 4, u[2].i);
Write32(p + 3 * 4, u[3].i);
} else {
union FloatPun u;
u.i = Read32(GetModrmRegisterXmmPointerRead4(m, rde));
u.f = 1.f / u.f;
Write32(XmmRexrReg(m, rde), u.i);
}
}
void OpComissVsWs(struct Machine *m, uint32_t rde) {
uint8_t zf, cf, pf, ie;
if (!Osz(rde)) {
union FloatPun xf, yf;
xf.i = Read32(XmmRexrReg(m, rde));
yf.i = Read32(GetModrmRegisterXmmPointerRead4(m, rde));
if (!isnan(xf.f) && !isnan(yf.f)) {
zf = xf.f == yf.f;
cf = xf.f < yf.f;
pf = false;
ie = false;
} else {
zf = cf = pf = ie = true;
}
} else {
union DoublePun xd, yd;
xd.i = Read64(XmmRexrReg(m, rde));
yd.i = Read64(GetModrmRegisterXmmPointerRead8(m, rde));
if (!isnan(xd.f) && !isnan(yd.f)) {
zf = xd.f == yd.f;
cf = xd.f < yd.f;
pf = false;
ie = false;
} else {
zf = cf = pf = ie = true;
}
}
m->flags = SetFlag(m->flags, FLAGS_ZF, zf);
m->flags = SetFlag(m->flags, FLAGS_PF, pf);
m->flags = SetFlag(m->flags, FLAGS_CF, cf);
m->flags = SetFlag(m->flags, FLAGS_SF, false);
m->flags = SetFlag(m->flags, FLAGS_OF, false);
if (m->xedd->op.opcode & 1) {
m->mxcsr &= ~kMxcsrIe;
if (ie) {
m->mxcsr |= kMxcsrIe;
if (!(m->mxcsr & kMxcsrIm)) {
HaltMachine(m, kMachineSimdException);
}
}
}
}
static inline void OpPsd(struct Machine *m, uint32_t rde,
float fs(float x, float y),
double fd(double x, double y)) {
if (Rep(rde) == 2) {
union DoublePun x, y;
y.i = Read64(GetModrmRegisterXmmPointerRead8(m, rde));
x.i = Read64(XmmRexrReg(m, rde));
x.f = fd(x.f, y.f);
Write64(XmmRexrReg(m, rde), x.i);
} else if (Rep(rde) == 3) {
union FloatPun x, y;
y.i = Read32(GetModrmRegisterXmmPointerRead4(m, rde));
x.i = Read32(XmmRexrReg(m, rde));
x.f = fs(x.f, y.f);
Write32(XmmRexrReg(m, rde), x.i);
} else if (Osz(rde)) {
uint8_t *p;
union DoublePun x[2], y[2];
p = GetModrmRegisterXmmPointerRead16(m, rde);
y[0].i = Read64(p + 0 * 8);
y[1].i = Read64(p + 1 * 8);
p = XmmRexrReg(m, rde);
x[0].i = Read64(p + 0 * 8);
x[1].i = Read64(p + 1 * 8);
x[0].f = fd(x[0].f, y[0].f);
x[1].f = fd(x[1].f, y[1].f);
Write64(p + 0 * 8, x[0].i);
Write64(p + 1 * 8, x[1].i);
} else {
uint8_t *p;
union FloatPun x[4], y[4];
p = GetModrmRegisterXmmPointerRead16(m, rde);
y[0].i = Read32(p + 0 * 4);
y[1].i = Read32(p + 1 * 4);
y[2].i = Read32(p + 2 * 4);
y[3].i = Read32(p + 3 * 4);
p = XmmRexrReg(m, rde);
x[0].i = Read32(p + 0 * 4);
x[1].i = Read32(p + 1 * 4);
x[2].i = Read32(p + 2 * 4);
x[3].i = Read32(p + 3 * 4);
x[0].f = fs(x[0].f, y[0].f);
x[1].f = fs(x[1].f, y[1].f);
x[2].f = fs(x[2].f, y[2].f);
x[3].f = fs(x[3].f, y[3].f);
Write32(p + 0 * 4, x[0].i);
Write32(p + 1 * 4, x[1].i);
Write32(p + 2 * 4, x[2].i);
Write32(p + 3 * 4, x[3].i);
}
}
static inline float Adds(float x, float y) {
return x + y;
}
static inline double Addd(double x, double y) {
return x + y;
}
void OpAddpsd(struct Machine *m, uint32_t rde) {
OpPsd(m, rde, Adds, Addd);
}
static inline float Subs(float x, float y) {
return x - y;
}
static inline double Subd(double x, double y) {
return x - y;
}
void OpSubpsd(struct Machine *m, uint32_t rde) {
OpPsd(m, rde, Subs, Subd);
}
static inline float Muls(float x, float y) {
return x * y;
}
static inline double Muld(double x, double y) {
return x * y;
}
void OpMulpsd(struct Machine *m, uint32_t rde) {
OpPsd(m, rde, Muls, Muld);
}
static inline float Divs(float x, float y) {
return x / y;
}
static inline double Divd(double x, double y) {
return x / y;
}
void OpDivpsd(struct Machine *m, uint32_t rde) {
OpPsd(m, rde, Divs, Divd);
}
static inline float Mins(float x, float y) {
return MIN(x, y);
}
static inline double Mind(double x, double y) {
return MIN(x, y);
}
void OpMinpsd(struct Machine *m, uint32_t rde) {
OpPsd(m, rde, Mins, Mind);
}
static inline float Maxs(float x, float y) {
return MAX(x, y);
}
static inline double Maxd(double x, double y) {
return MAX(x, y);
}
void OpMaxpsd(struct Machine *m, uint32_t rde) {
OpPsd(m, rde, Maxs, Maxd);
}
static int Cmps(int imm, float x, float y) {
switch (imm) {
case 0:
return x == y ? -1 : 0;
case 1:
return x < y ? -1 : 0;
case 2:
return x <= y ? -1 : 0;
case 3:
return isnan(x) || isnan(y) ? -1 : 0;
case 4:
return x != y ? -1 : 0;
case 5:
return x >= y ? -1 : 0;
case 6:
return x > y ? -1 : 0;
case 7:
return !(isnan(x) || isnan(y)) ? -1 : 0;
default:
return 0;
}
}
static int32_t Cmpd(int imm, double x, double y) {
switch (imm) {
case 0:
return x == y ? -1 : 0;
case 1:
return x < y ? -1 : 0;
case 2:
return x <= y ? -1 : 0;
case 3:
return isnan(x) || isnan(y) ? -1 : 0;
case 4:
return x != y ? -1 : 0;
case 5:
return x >= y ? -1 : 0;
case 6:
return x > y ? -1 : 0;
case 7:
return !(isnan(x) || isnan(y)) ? -1 : 0;
default:
return 0;
}
}
void OpCmppsd(struct Machine *m, uint32_t rde) {
int imm = m->xedd->op.uimm0;
if (Rep(rde) == 2) {
union DoublePun x, y;
y.i = Read64(GetModrmRegisterXmmPointerRead8(m, rde));
x.i = Read64(XmmRexrReg(m, rde));
x.f = Cmpd(imm, x.f, y.f);
Write64(XmmRexrReg(m, rde), x.i);
} else if (Rep(rde) == 3) {
union FloatPun x, y;
y.i = Read32(GetModrmRegisterXmmPointerRead4(m, rde));
x.i = Read32(XmmRexrReg(m, rde));
x.f = Cmps(imm, x.f, y.f);
Write32(XmmRexrReg(m, rde), x.i);
} else if (Osz(rde)) {
uint8_t *p;
union DoublePun x[2], y[2];
p = GetModrmRegisterXmmPointerRead16(m, rde);
y[0].i = Read64(p + 0 * 8);
y[1].i = Read64(p + 1 * 8);
p = XmmRexrReg(m, rde);
x[0].i = Read64(p + 0 * 8);
x[1].i = Read64(p + 1 * 8);
x[0].f = Cmpd(imm, x[0].f, y[0].f);
x[1].f = Cmpd(imm, x[1].f, y[1].f);
Write64(p + 0 * 8, x[0].i);
Write64(p + 1 * 8, x[1].i);
} else {
uint8_t *p;
union FloatPun x[4], y[4];
p = GetModrmRegisterXmmPointerRead16(m, rde);
y[0].i = Read32(p + 0 * 4);
y[1].i = Read32(p + 1 * 4);
y[2].i = Read32(p + 2 * 4);
y[3].i = Read32(p + 3 * 4);
p = XmmRexrReg(m, rde);
x[0].i = Read32(p + 0 * 4);
x[1].i = Read32(p + 1 * 4);
x[2].i = Read32(p + 2 * 4);
x[3].i = Read32(p + 3 * 4);
x[0].f = Cmps(imm, x[0].f, y[0].f);
x[1].f = Cmps(imm, x[1].f, y[1].f);
x[2].f = Cmps(imm, x[2].f, y[2].f);
x[3].f = Cmps(imm, x[3].f, y[3].f);
Write32(p + 0 * 4, x[0].i);
Write32(p + 1 * 4, x[1].i);
Write32(p + 2 * 4, x[2].i);
Write32(p + 3 * 4, x[3].i);
}
}
void OpAndpsd(struct Machine *m, uint32_t rde) {
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) {
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) {
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) {
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) {
uint8_t *p;
if (Rep(rde) == 2) {
union FloatPun x[4], y[4], z[4];
p = GetModrmRegisterXmmPointerRead16(m, rde);
y[0].i = Read32(p + 0 * 4);
y[1].i = Read32(p + 1 * 4);
y[2].i = Read32(p + 2 * 4);
y[3].i = Read32(p + 3 * 4);
p = XmmRexrReg(m, rde);
x[0].i = Read32(p + 0 * 4);
x[1].i = Read32(p + 1 * 4);
x[2].i = Read32(p + 2 * 4);
x[3].i = Read32(p + 3 * 4);
z[0].f = x[0].f + x[1].f;
z[1].f = x[2].f + x[3].f;
z[2].f = y[0].f + y[1].f;
z[3].f = y[2].f + y[3].f;
Write32(p + 0 * 4, z[0].i);
Write32(p + 1 * 4, z[1].i);
Write32(p + 2 * 4, z[2].i);
Write32(p + 3 * 4, z[3].i);
} else if (Osz(rde)) {
union DoublePun x[2], y[2], z[2];
p = GetModrmRegisterXmmPointerRead16(m, rde);
y[0].i = Read64(p + 0 * 8);
y[1].i = Read64(p + 1 * 8);
p = XmmRexrReg(m, rde);
x[0].i = Read64(p + 0 * 8);
x[1].i = Read64(p + 1 * 8);
z[0].f = x[0].f + x[1].f;
z[1].f = y[0].f + y[1].f;
Write64(p + 0 * 8, z[0].i);
Write64(p + 1 * 8, z[1].i);
} else {
OpUd(m, rde);
}
}
void OpHsubpsd(struct Machine *m, uint32_t rde) {
uint8_t *p;
if (Rep(rde) == 2) {
union FloatPun x[4], y[4], z[4];
p = GetModrmRegisterXmmPointerRead16(m, rde);
y[0].i = Read32(p + 0 * 4);
y[1].i = Read32(p + 1 * 4);
y[2].i = Read32(p + 2 * 4);
y[3].i = Read32(p + 3 * 4);
p = XmmRexrReg(m, rde);
x[0].i = Read32(p + 0 * 4);
x[1].i = Read32(p + 1 * 4);
x[2].i = Read32(p + 2 * 4);
x[3].i = Read32(p + 3 * 4);
z[0].f = x[0].f - x[1].f;
z[1].f = x[2].f - x[3].f;
z[2].f = y[0].f - y[1].f;
z[3].f = y[2].f - y[3].f;
Write32(p + 0 * 4, z[0].i);
Write32(p + 1 * 4, z[1].i);
Write32(p + 2 * 4, z[2].i);
Write32(p + 3 * 4, z[3].i);
} else if (Osz(rde)) {
union DoublePun x[2], y[2], z[2];
p = GetModrmRegisterXmmPointerRead16(m, rde);
y[0].i = Read64(p + 0 * 8);
y[1].i = Read64(p + 1 * 8);
p = XmmRexrReg(m, rde);
x[0].i = Read64(p + 0 * 8);
x[1].i = Read64(p + 1 * 8);
z[0].f = x[0].f - x[1].f;
z[1].f = y[0].f - y[1].f;
Write64(p + 0 * 8, z[0].i);
Write64(p + 1 * 8, z[1].i);
} else {
OpUd(m, rde);
}
}
void OpAddsubpsd(struct Machine *m, uint32_t rde) {
uint8_t *p;
if (Rep(rde) == 2) {
union FloatPun x[4], y[4], z[4];
p = GetModrmRegisterXmmPointerRead16(m, rde);
y[0].i = Read32(p + 0 * 4);
y[1].i = Read32(p + 1 * 4);
y[2].i = Read32(p + 2 * 4);
y[3].i = Read32(p + 3 * 4);
p = XmmRexrReg(m, rde);
x[0].i = Read32(p + 0 * 4);
x[1].i = Read32(p + 1 * 4);
x[2].i = Read32(p + 2 * 4);
x[3].i = Read32(p + 3 * 4);
z[0].f = x[0].f - y[0].f;
z[1].f = x[1].f + y[1].f;
z[2].f = x[2].f - y[2].f;
z[3].f = x[3].f + y[3].f;
Write32(p + 0 * 4, z[0].i);
Write32(p + 1 * 4, z[1].i);
Write32(p + 2 * 4, z[2].i);
Write32(p + 3 * 4, z[3].i);
} else if (Osz(rde)) {
union DoublePun x[2], y[2], z[2];
p = GetModrmRegisterXmmPointerRead16(m, rde);
y[0].i = Read64(p + 0 * 8);
y[1].i = Read64(p + 1 * 8);
p = XmmRexrReg(m, rde);
x[0].i = Read64(p + 0 * 8);
x[1].i = Read64(p + 1 * 8);
z[0].f = x[0].f - y[0].f;
z[1].f = x[1].f + y[1].f;
Write64(p + 0 * 8, z[0].i);
Write64(p + 1 * 8, z[1].i);
} else {
OpUd(m, rde);
}
}

View file

@ -1,37 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_SSEFLOAT_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_SSEFLOAT_H_
#include "tool/build/lib/machine.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
typedef float float_v _Vector_size(16) forcealign(16);
typedef double double_v _Vector_size(16) forcealign(16);
void OpUnpcklpsd(struct Machine *, uint32_t);
void OpUnpckhpsd(struct Machine *, uint32_t);
void OpPextrwGdqpUdqIb(struct Machine *, uint32_t);
void OpPinsrwVdqEwIb(struct Machine *, uint32_t);
void OpShuffle(struct Machine *, uint32_t);
void OpShufpsd(struct Machine *, uint32_t);
void OpSqrtpsd(struct Machine *, uint32_t);
void OpRsqrtps(struct Machine *, uint32_t);
void OpRcpps(struct Machine *, uint32_t);
void OpComissVsWs(struct Machine *, uint32_t);
void OpAddpsd(struct Machine *, uint32_t);
void OpMulpsd(struct Machine *, uint32_t);
void OpSubpsd(struct Machine *, uint32_t);
void OpDivpsd(struct Machine *, uint32_t);
void OpMinpsd(struct Machine *, uint32_t);
void OpMaxpsd(struct Machine *, uint32_t);
void OpCmppsd(struct Machine *, uint32_t);
void OpAndpsd(struct Machine *, uint32_t);
void OpAndnpsd(struct Machine *, uint32_t);
void OpOrpsd(struct Machine *, uint32_t);
void OpXorpsd(struct Machine *, uint32_t);
void OpHaddpsd(struct Machine *, uint32_t);
void OpHsubpsd(struct Machine *, uint32_t);
void OpAddsubpsd(struct Machine *, uint32_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_SSEFLOAT_H_ */

View file

@ -1,518 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "tool/build/lib/ssemov.h"
#include "libc/intrin/pmovmskb.h"
#include "libc/str/str.h"
#include "tool/build/lib/address.h"
#include "tool/build/lib/endian.h"
#include "tool/build/lib/memory.h"
#include "tool/build/lib/modrm.h"
#include "tool/build/lib/throw.h"
static void MovdquVdqWdq(struct Machine *m, uint32_t rde) {
memcpy(XmmRexrReg(m, rde), GetModrmRegisterXmmPointerRead16(m, rde), 16);
}
static void MovdquWdqVdq(struct Machine *m, uint32_t rde) {
memcpy(GetModrmRegisterXmmPointerWrite16(m, rde), XmmRexrReg(m, rde), 16);
}
static void MovupsVpsWps(struct Machine *m, uint32_t rde) {
MovdquVdqWdq(m, rde);
}
static void MovupsWpsVps(struct Machine *m, uint32_t rde) {
MovdquWdqVdq(m, rde);
}
static void MovupdVpsWps(struct Machine *m, uint32_t rde) {
MovdquVdqWdq(m, rde);
}
static void MovupdWpsVps(struct Machine *m, uint32_t rde) {
MovdquWdqVdq(m, rde);
}
void OpLddquVdqMdq(struct Machine *m, uint32_t rde) {
MovdquVdqWdq(m, rde);
}
void OpMovntiMdqpGdqp(struct Machine *m, uint32_t rde) {
if (Rexw(rde)) {
memcpy(ComputeReserveAddressWrite8(m, rde), XmmRexrReg(m, rde), 8);
} else {
memcpy(ComputeReserveAddressWrite4(m, rde), XmmRexrReg(m, rde), 4);
}
}
static void MovdqaVdqMdq(struct Machine *m, uint32_t rde) {
int64_t v;
uint8_t *p;
v = ComputeAddress(m, rde);
SetReadAddr(m, v, 16);
if ((v & 15) || !(p = FindReal(m, v))) ThrowSegmentationFault(m, v);
memcpy(XmmRexrReg(m, rde), Abp16(p), 16);
}
static void MovdqaMdqVdq(struct Machine *m, uint32_t rde) {
int64_t v;
uint8_t *p;
v = ComputeAddress(m, rde);
SetWriteAddr(m, v, 16);
if ((v & 15) || !(p = FindReal(m, v))) ThrowSegmentationFault(m, v);
memcpy(Abp16(p), XmmRexrReg(m, rde), 16);
}
static void MovdqaVdqWdq(struct Machine *m, uint32_t rde) {
if (IsModrmRegister(rde)) {
memcpy(XmmRexrReg(m, rde), XmmRexbRm(m, rde), 16);
} else {
MovdqaVdqMdq(m, rde);
}
}
static void MovdqaWdqVdq(struct Machine *m, uint32_t rde) {
if (IsModrmRegister(rde)) {
memcpy(XmmRexbRm(m, rde), XmmRexrReg(m, rde), 16);
} else {
MovdqaMdqVdq(m, rde);
}
}
static void MovntdqMdqVdq(struct Machine *m, uint32_t rde) {
MovdqaMdqVdq(m, rde);
}
static void MovntpsMpsVps(struct Machine *m, uint32_t rde) {
MovdqaMdqVdq(m, rde);
}
static void MovntpdMpdVpd(struct Machine *m, uint32_t rde) {
MovdqaMdqVdq(m, rde);
}
void OpMovntdqaVdqMdq(struct Machine *m, uint32_t rde) {
MovdqaVdqMdq(m, rde);
}
static void MovqPqQq(struct Machine *m, uint32_t rde) {
memcpy(MmReg(m, rde), GetModrmRegisterMmPointerRead8(m, rde), 8);
}
static void MovqQqPq(struct Machine *m, uint32_t rde) {
memcpy(GetModrmRegisterMmPointerWrite8(m, rde), MmReg(m, rde), 8);
}
static void MovqVdqEqp(struct Machine *m, uint32_t rde) {
memcpy(XmmRexrReg(m, rde), GetModrmRegisterWordPointerRead8(m, rde), 8);
bzero(XmmRexrReg(m, rde) + 8, 8);
}
static void MovdVdqEd(struct Machine *m, uint32_t rde) {
bzero(XmmRexrReg(m, rde), 16);
memcpy(XmmRexrReg(m, rde), GetModrmRegisterWordPointerRead4(m, rde), 4);
}
static void MovqPqEqp(struct Machine *m, uint32_t rde) {
memcpy(MmReg(m, rde), GetModrmRegisterWordPointerRead8(m, rde), 8);
}
static void MovdPqEd(struct Machine *m, uint32_t rde) {
memcpy(MmReg(m, rde), GetModrmRegisterWordPointerRead4(m, rde), 4);
bzero(MmReg(m, rde) + 4, 4);
}
static void MovdEdVdq(struct Machine *m, uint32_t rde) {
if (IsModrmRegister(rde)) {
Write64(RegRexbRm(m, rde), Read32(XmmRexrReg(m, rde)));
} else {
memcpy(ComputeReserveAddressWrite4(m, rde), XmmRexrReg(m, rde), 4);
}
}
static void MovqEqpVdq(struct Machine *m, uint32_t rde) {
memcpy(GetModrmRegisterWordPointerWrite8(m, rde), XmmRexrReg(m, rde), 8);
}
static void MovdEdPq(struct Machine *m, uint32_t rde) {
if (IsModrmRegister(rde)) {
Write64(RegRexbRm(m, rde), Read32(MmReg(m, rde)));
} else {
memcpy(ComputeReserveAddressWrite4(m, rde), MmReg(m, rde), 4);
}
}
static void MovqEqpPq(struct Machine *m, uint32_t rde) {
memcpy(GetModrmRegisterWordPointerWrite(m, rde, 8), MmReg(m, rde), 8);
}
static void MovntqMqPq(struct Machine *m, uint32_t rde) {
memcpy(ComputeReserveAddressWrite8(m, rde), MmReg(m, rde), 8);
}
static void MovqVqWq(struct Machine *m, uint32_t rde) {
memcpy(XmmRexrReg(m, rde), GetModrmRegisterXmmPointerRead8(m, rde), 8);
bzero(XmmRexrReg(m, rde) + 8, 8);
}
static void MovssVpsWps(struct Machine *m, uint32_t rde) {
if (IsModrmRegister(rde)) {
memcpy(XmmRexrReg(m, rde), XmmRexbRm(m, rde), 4);
} else {
memcpy(XmmRexrReg(m, rde), ComputeReserveAddressRead4(m, rde), 4);
bzero(XmmRexrReg(m, rde) + 4, 12);
}
}
static void MovssWpsVps(struct Machine *m, uint32_t rde) {
memcpy(GetModrmRegisterXmmPointerWrite4(m, rde), XmmRexrReg(m, rde), 4);
}
static void MovsdVpsWps(struct Machine *m, uint32_t rde) {
if (IsModrmRegister(rde)) {
memcpy(XmmRexrReg(m, rde), XmmRexbRm(m, rde), 8);
} else {
memcpy(XmmRexrReg(m, rde), ComputeReserveAddressRead8(m, rde), 8);
bzero(XmmRexrReg(m, rde) + 8, 8);
}
}
static void MovsdWpsVps(struct Machine *m, uint32_t rde) {
memcpy(GetModrmRegisterXmmPointerWrite8(m, rde), XmmRexrReg(m, rde), 8);
}
static void MovhlpsVqUq(struct Machine *m, uint32_t rde) {
memcpy(XmmRexrReg(m, rde), XmmRexbRm(m, rde) + 8, 8);
}
static void MovlpsVqMq(struct Machine *m, uint32_t rde) {
memcpy(XmmRexrReg(m, rde), ComputeReserveAddressRead8(m, rde), 8);
}
static void MovlpdVqMq(struct Machine *m, uint32_t rde) {
memcpy(XmmRexrReg(m, rde), ComputeReserveAddressRead8(m, rde), 8);
}
static void MovddupVqWq(struct Machine *m, uint32_t rde) {
uint8_t *src;
src = GetModrmRegisterXmmPointerRead8(m, rde);
memcpy(XmmRexrReg(m, rde) + 0, src, 8);
memcpy(XmmRexrReg(m, rde) + 8, src, 8);
}
static void MovsldupVqWq(struct Machine *m, uint32_t rde) {
uint8_t *dst, *src;
dst = XmmRexrReg(m, rde);
src = GetModrmRegisterXmmPointerRead16(m, rde);
memcpy(dst + 0 + 0, src + 0, 4);
memcpy(dst + 0 + 4, src + 0, 4);
memcpy(dst + 8 + 0, src + 8, 4);
memcpy(dst + 8 + 4, src + 8, 4);
}
static void MovlpsMqVq(struct Machine *m, uint32_t rde) {
memcpy(ComputeReserveAddressWrite8(m, rde), XmmRexrReg(m, rde), 8);
}
static void MovlpdMqVq(struct Machine *m, uint32_t rde) {
memcpy(ComputeReserveAddressWrite8(m, rde), XmmRexrReg(m, rde), 8);
}
static void MovlhpsVqUq(struct Machine *m, uint32_t rde) {
memcpy(XmmRexrReg(m, rde) + 8, XmmRexbRm(m, rde), 8);
}
static void MovhpsVqMq(struct Machine *m, uint32_t rde) {
memcpy(XmmRexrReg(m, rde) + 8, ComputeReserveAddressRead8(m, rde), 8);
}
static void MovhpdVqMq(struct Machine *m, uint32_t rde) {
memcpy(XmmRexrReg(m, rde) + 8, ComputeReserveAddressRead8(m, rde), 8);
}
static void MovshdupVqWq(struct Machine *m, uint32_t rde) {
uint8_t *dst, *src;
dst = XmmRexrReg(m, rde);
src = GetModrmRegisterXmmPointerRead16(m, rde);
memcpy(dst + 0 + 0, src + 04, 4);
memcpy(dst + 0 + 4, src + 04, 4);
memcpy(dst + 8 + 0, src + 12, 4);
memcpy(dst + 8 + 4, src + 12, 4);
}
static void MovhpsMqVq(struct Machine *m, uint32_t rde) {
memcpy(ComputeReserveAddressWrite8(m, rde), XmmRexrReg(m, rde) + 8, 8);
}
static void MovhpdMqVq(struct Machine *m, uint32_t rde) {
memcpy(ComputeReserveAddressWrite8(m, rde), XmmRexrReg(m, rde) + 8, 8);
}
static void MovqWqVq(struct Machine *m, uint32_t rde) {
if (IsModrmRegister(rde)) {
memcpy(XmmRexbRm(m, rde), XmmRexrReg(m, rde), 8);
bzero(XmmRexbRm(m, rde) + 8, 8);
} else {
memcpy(ComputeReserveAddressWrite8(m, rde), XmmRexrReg(m, rde), 8);
}
}
static void Movq2dqVdqNq(struct Machine *m, uint32_t rde) {
memcpy(XmmRexrReg(m, rde), MmRm(m, rde), 8);
bzero(XmmRexrReg(m, rde) + 8, 8);
}
static void Movdq2qPqUq(struct Machine *m, uint32_t rde) {
memcpy(MmReg(m, rde), XmmRexbRm(m, rde), 8);
}
static void MovapsVpsWps(struct Machine *m, uint32_t rde) {
MovdqaVdqWdq(m, rde);
}
static void MovapdVpdWpd(struct Machine *m, uint32_t rde) {
MovdqaVdqWdq(m, rde);
}
static void MovapsWpsVps(struct Machine *m, uint32_t rde) {
MovdqaWdqVdq(m, rde);
}
static void MovapdWpdVpd(struct Machine *m, uint32_t rde) {
MovdqaWdqVdq(m, rde);
}
void OpMovWpsVps(struct Machine *m, uint32_t rde) {
uint8_t *p, *r;
switch (Rep(rde) | Osz(rde)) {
case 0:
MovupsWpsVps(m, rde);
break;
case 1:
MovupdWpsVps(m, rde);
break;
case 2:
MovsdWpsVps(m, rde);
break;
case 3:
MovssWpsVps(m, rde);
break;
default:
__builtin_unreachable();
}
}
void OpMov0f28(struct Machine *m, uint32_t rde) {
if (!Osz(rde)) {
MovapsVpsWps(m, rde);
} else {
MovapdVpdWpd(m, rde);
}
}
void OpMov0f6e(struct Machine *m, uint32_t rde) {
if (Osz(rde)) {
if (Rexw(rde)) {
MovqVdqEqp(m, rde);
} else {
MovdVdqEd(m, rde);
}
} else {
if (Rexw(rde)) {
MovqPqEqp(m, rde);
} else {
MovdPqEd(m, rde);
}
}
}
void OpMov0f6f(struct Machine *m, uint32_t rde) {
if (Osz(rde)) {
MovdqaVdqWdq(m, rde);
} else if (Rep(rde) == 3) {
MovdquVdqWdq(m, rde);
} else {
MovqPqQq(m, rde);
}
}
void OpMov0fE7(struct Machine *m, uint32_t rde) {
if (!Osz(rde)) {
MovntqMqPq(m, rde);
} else {
MovntdqMdqVdq(m, rde);
}
}
void OpMov0f7e(struct Machine *m, uint32_t rde) {
if (Rep(rde) == 3) {
MovqVqWq(m, rde);
} else if (Osz(rde)) {
if (Rexw(rde)) {
MovqEqpVdq(m, rde);
} else {
MovdEdVdq(m, rde);
}
} else {
if (Rexw(rde)) {
MovqEqpPq(m, rde);
} else {
MovdEdPq(m, rde);
}
}
}
void OpMov0f7f(struct Machine *m, uint32_t rde) {
if (Rep(rde) == 3) {
MovdquWdqVdq(m, rde);
} else if (Osz(rde)) {
MovdqaWdqVdq(m, rde);
} else {
MovqQqPq(m, rde);
}
}
void OpMov0f10(struct Machine *m, uint32_t rde) {
uint8_t *p, *r;
switch (Rep(rde) | Osz(rde)) {
case 0:
MovupsVpsWps(m, rde);
break;
case 1:
MovupdVpsWps(m, rde);
break;
case 2:
MovsdVpsWps(m, rde);
break;
case 3:
MovssVpsWps(m, rde);
break;
default:
__builtin_unreachable();
}
}
void OpMov0f29(struct Machine *m, uint32_t rde) {
if (!Osz(rde)) {
MovapsWpsVps(m, rde);
} else {
MovapdWpdVpd(m, rde);
}
}
void OpMov0f2b(struct Machine *m, uint32_t rde) {
if (!Osz(rde)) {
MovntpsMpsVps(m, rde);
} else {
MovntpdMpdVpd(m, rde);
}
}
void OpMov0f12(struct Machine *m, uint32_t rde) {
switch (Rep(rde) | Osz(rde)) {
case 0:
if (IsModrmRegister(rde)) {
MovhlpsVqUq(m, rde);
} else {
MovlpsVqMq(m, rde);
}
break;
case 1:
MovlpdVqMq(m, rde);
break;
case 2:
MovddupVqWq(m, rde);
break;
case 3:
MovsldupVqWq(m, rde);
break;
default:
__builtin_unreachable();
}
}
void OpMov0f13(struct Machine *m, uint32_t rde) {
if (Osz(rde)) {
MovlpdMqVq(m, rde);
} else {
MovlpsMqVq(m, rde);
}
}
void OpMov0f16(struct Machine *m, uint32_t rde) {
switch (Rep(rde) | Osz(rde)) {
case 0:
if (IsModrmRegister(rde)) {
MovlhpsVqUq(m, rde);
} else {
MovhpsVqMq(m, rde);
}
break;
case 1:
MovhpdVqMq(m, rde);
break;
case 3:
MovshdupVqWq(m, rde);
break;
default:
OpUd(m, rde);
break;
}
}
void OpMov0f17(struct Machine *m, uint32_t rde) {
if (Osz(rde)) {
MovhpdMqVq(m, rde);
} else {
MovhpsMqVq(m, rde);
}
}
void OpMov0fD6(struct Machine *m, uint32_t rde) {
if (Rep(rde) == 3) {
Movq2dqVdqNq(m, rde);
} else if (Rep(rde) == 2) {
Movdq2qPqUq(m, rde);
} else if (Osz(rde)) {
MovqWqVq(m, rde);
} else {
OpUd(m, rde);
}
}
void OpPmovmskbGdqpNqUdq(struct Machine *m, uint32_t rde) {
Write64(RegRexrReg(m, rde),
pmovmskb(XmmRexbRm(m, rde)) & (Osz(rde) ? 0xffff : 0xff));
}
void OpMaskMovDiXmmRegXmmRm(struct Machine *m, uint32_t rde) {
void *p[2];
uint64_t v;
unsigned i, n;
uint8_t *mem, b[16];
v = AddressDi(m, rde);
n = Osz(rde) ? 16 : 8;
mem = BeginStore(m, v, n, p, b);
for (i = 0; i < n; ++i) {
if (XmmRexbRm(m, rde)[i] & 0x80) {
mem[i] = XmmRexrReg(m, rde)[i];
}
}
EndStore(m, v, n, p, b);
}

View file

@ -1,30 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_SSEMOV_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_SSEMOV_H_
#include "tool/build/lib/machine.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
void OpLddquVdqMdq(struct Machine *, uint32_t);
void OpMovntiMdqpGdqp(struct Machine *, uint32_t);
void OpPmovmskbGdqpNqUdq(struct Machine *, uint32_t);
void OpMaskMovDiXmmRegXmmRm(struct Machine *, uint32_t);
void OpMovntdqaVdqMdq(struct Machine *, uint32_t);
void OpMovWpsVps(struct Machine *, uint32_t);
void OpMov0f28(struct Machine *, uint32_t);
void OpMov0f6e(struct Machine *, uint32_t);
void OpMov0f6f(struct Machine *, uint32_t);
void OpMov0fE7(struct Machine *, uint32_t);
void OpMov0f7e(struct Machine *, uint32_t);
void OpMov0f7f(struct Machine *, uint32_t);
void OpMov0f10(struct Machine *, uint32_t);
void OpMov0f29(struct Machine *, uint32_t);
void OpMov0f2b(struct Machine *, uint32_t);
void OpMov0f12(struct Machine *, uint32_t);
void OpMov0f13(struct Machine *, uint32_t);
void OpMov0f16(struct Machine *, uint32_t);
void OpMov0f17(struct Machine *, uint32_t);
void OpMov0fD6(struct Machine *, uint32_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_SSEMOV_H_ */

View file

@ -1,314 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "tool/build/lib/stack.h"
#include "libc/log/check.h"
#include "libc/macros.internal.h"
#include "libc/str/str.h"
#include "tool/build/lib/address.h"
#include "tool/build/lib/endian.h"
#include "tool/build/lib/memory.h"
#include "tool/build/lib/modrm.h"
#include "tool/build/lib/throw.h"
static const uint8_t kStackOsz[2][3] = {
[0][XED_MODE_REAL] = 2, [0][XED_MODE_LEGACY] = 4, [0][XED_MODE_LONG] = 8,
[1][XED_MODE_REAL] = 4, [1][XED_MODE_LEGACY] = 2, [1][XED_MODE_LONG] = 2,
};
static const uint8_t kCallOsz[2][3] = {
[0][XED_MODE_REAL] = 2, [0][XED_MODE_LEGACY] = 4, [0][XED_MODE_LONG] = 8,
[1][XED_MODE_REAL] = 4, [1][XED_MODE_LEGACY] = 2, [1][XED_MODE_LONG] = 8,
};
static void WriteStackWord(uint8_t *p, uint32_t rde, uint32_t osz, uint64_t x) {
if (osz == 8) {
Write64(p, x);
} else if (osz == 2) {
Write16(p, x);
} else {
Write32(p, x);
}
}
static uint64_t ReadStackWord(uint8_t *p, uint32_t osz) {
if (osz == 8) {
return Read64(p);
} else if (osz == 2) {
return Read16(p);
} else {
return Read32(p);
}
}
static void PushN(struct Machine *m, uint32_t rde, uint64_t x, unsigned osz) {
uint64_t v;
void *p[2];
uint8_t b[8];
switch (Eamode(rde)) {
case XED_MODE_REAL:
v = (Read32(m->sp) - osz) & 0xffff;
Write16(m->sp, v);
v += Read64(m->ss);
break;
case XED_MODE_LEGACY:
v = (Read32(m->sp) - osz) & 0xffffffff;
Write64(m->sp, v);
v += Read64(m->ss);
break;
case XED_MODE_LONG:
v = (Read64(m->sp) - osz) & 0xffffffffffffffff;
Write64(m->sp, v);
break;
default:
__builtin_unreachable();
}
WriteStackWord(AccessRam(m, v, osz, p, b, false), rde, osz, x);
EndStore(m, v, osz, p, b);
}
void Push(struct Machine *m, uint32_t rde, uint64_t x) {
PushN(m, rde, x, kStackOsz[m->xedd->op.osz][Mode(rde)]);
}
void OpPushZvq(struct Machine *m, uint32_t rde) {
unsigned osz;
osz = kStackOsz[m->xedd->op.osz][Mode(rde)];
PushN(m, rde, ReadStackWord(RegRexbSrm(m, rde), osz), osz);
}
static uint64_t PopN(struct Machine *m, uint32_t rde, uint16_t extra,
unsigned osz) {
uint64_t v;
void *p[2];
uint8_t b[8];
switch (Eamode(rde)) {
case XED_MODE_LONG:
v = Read64(m->sp);
Write64(m->sp, v + osz + extra);
break;
case XED_MODE_LEGACY:
v = Read32(m->sp);
Write64(m->sp, (v + osz + extra) & 0xffffffff);
v += Read64(m->ss);
break;
case XED_MODE_REAL:
v = Read32(m->sp);
Write16(m->sp, v + osz + extra);
v += Read64(m->ss);
break;
default:
__builtin_unreachable();
}
return ReadStackWord(AccessRam(m, v, osz, p, b, true), osz);
}
uint64_t Pop(struct Machine *m, uint32_t rde, uint16_t extra) {
return PopN(m, rde, extra, kStackOsz[m->xedd->op.osz][Mode(rde)]);
}
void OpPopZvq(struct Machine *m, uint32_t rde) {
uint64_t x;
unsigned osz;
osz = kStackOsz[m->xedd->op.osz][Mode(rde)];
x = PopN(m, rde, 0, osz);
switch (osz) {
case 8:
case 4:
Write64(RegRexbSrm(m, rde), x);
break;
case 2:
Write16(RegRexbSrm(m, rde), x);
break;
default:
__builtin_unreachable();
}
}
static void OpCall(struct Machine *m, uint32_t rde, uint64_t func) {
if (!func) {
/*
* call null is technically possible but too fringe and disastrous
* to accommodate at least until our debugger has rewind capability
*/
HaltMachine(m, kMachineProtectionFault);
}
Push(m, rde, m->ip);
m->ip = func;
}
void OpCallJvds(struct Machine *m, uint32_t rde) {
OpCall(m, rde, m->ip + m->xedd->op.disp);
}
static uint64_t LoadAddressFromMemory(struct Machine *m, uint32_t rde) {
unsigned osz;
osz = kCallOsz[m->xedd->op.osz][Mode(rde)];
return ReadStackWord(GetModrmRegisterWordPointerRead(m, rde, osz), osz);
}
void OpCallEq(struct Machine *m, uint32_t rde) {
OpCall(m, rde, LoadAddressFromMemory(m, rde));
}
void OpJmpEq(struct Machine *m, uint32_t rde) {
m->ip = LoadAddressFromMemory(m, rde);
}
void OpLeave(struct Machine *m, uint32_t rde) {
switch (Eamode(rde)) {
case XED_MODE_LONG:
Write64(m->sp, Read64(m->bp));
Write64(m->bp, Pop(m, rde, 0));
break;
case XED_MODE_LEGACY:
Write64(m->sp, Read32(m->bp));
Write64(m->bp, Pop(m, rde, 0));
break;
case XED_MODE_REAL:
Write16(m->sp, Read16(m->bp));
Write16(m->bp, Pop(m, rde, 0));
break;
default:
__builtin_unreachable();
}
}
void OpRet(struct Machine *m, uint32_t rde) {
m->ip = Pop(m, rde, m->xedd->op.uimm0);
}
void OpPushEvq(struct Machine *m, uint32_t rde) {
unsigned osz;
osz = kStackOsz[m->xedd->op.osz][Mode(rde)];
Push(m, rde,
ReadStackWord(GetModrmRegisterWordPointerRead(m, rde, osz), osz));
}
void OpPopEvq(struct Machine *m, uint32_t rde) {
unsigned osz;
osz = kStackOsz[m->xedd->op.osz][Mode(rde)];
WriteStackWord(GetModrmRegisterWordPointerWrite(m, rde, osz), rde, osz,
Pop(m, rde, 0));
}
static relegated void Pushaw(struct Machine *m, uint32_t rde) {
uint16_t v;
uint8_t b[8][2];
memcpy(b[0], m->di, 2);
memcpy(b[1], m->si, 2);
memcpy(b[2], m->bp, 2);
memcpy(b[3], m->sp, 2);
memcpy(b[4], m->bx, 2);
memcpy(b[5], m->dx, 2);
memcpy(b[6], m->cx, 2);
memcpy(b[7], m->ax, 2);
Write16(m->sp, (v = (Read16(m->sp) - sizeof(b)) & 0xffff));
VirtualRecv(m, Read64(m->ss) + v, b, sizeof(b));
}
static relegated void Pushad(struct Machine *m, uint32_t rde) {
uint32_t v;
uint8_t b[8][4];
memcpy(b[0], m->di, 4);
memcpy(b[1], m->si, 4);
memcpy(b[2], m->bp, 4);
memcpy(b[3], m->sp, 4);
memcpy(b[4], m->bx, 4);
memcpy(b[5], m->dx, 4);
memcpy(b[6], m->cx, 4);
memcpy(b[7], m->ax, 4);
Write64(m->sp, (v = (Read32(m->sp) - sizeof(b)) & 0xffffffff));
VirtualRecv(m, Read64(m->ss) + v, b, sizeof(b));
}
static relegated void Popaw(struct Machine *m, uint32_t rde) {
uint8_t b[8][2];
VirtualSend(m, b, Read64(m->ss) + Read16(m->sp), sizeof(b));
Write16(m->sp, (Read32(m->sp) + sizeof(b)) & 0xffff);
memcpy(m->di, b[0], 2);
memcpy(m->si, b[1], 2);
memcpy(m->bp, b[2], 2);
memcpy(m->sp, b[3], 2);
memcpy(m->bx, b[4], 2);
memcpy(m->dx, b[5], 2);
memcpy(m->cx, b[6], 2);
memcpy(m->ax, b[7], 2);
}
static relegated void Popad(struct Machine *m, uint32_t rde) {
uint8_t b[8][4];
VirtualSend(m, b, Read64(m->ss) + Read32(m->sp), sizeof(b));
Write64(m->sp, (Read32(m->sp) + sizeof(b)) & 0xffffffff);
memcpy(m->di, b[0], 4);
memcpy(m->si, b[1], 4);
memcpy(m->bp, b[2], 4);
memcpy(m->sp, b[3], 4);
memcpy(m->bx, b[4], 4);
memcpy(m->dx, b[5], 4);
memcpy(m->cx, b[6], 4);
memcpy(m->ax, b[7], 4);
}
relegated void OpPusha(struct Machine *m, uint32_t rde) {
switch (Eamode(rde)) {
case XED_MODE_REAL:
Pushaw(m, rde);
break;
case XED_MODE_LEGACY:
Pushad(m, rde);
break;
case XED_MODE_LONG:
OpUd(m, rde);
default:
__builtin_unreachable();
}
}
relegated void OpPopa(struct Machine *m, uint32_t rde) {
switch (Eamode(rde)) {
case XED_MODE_REAL:
Popaw(m, rde);
break;
case XED_MODE_LEGACY:
Popad(m, rde);
break;
case XED_MODE_LONG:
OpUd(m, rde);
default:
__builtin_unreachable();
}
}
relegated void OpCallf(struct Machine *m, uint32_t rde) {
Push(m, rde, Read64(m->cs) >> 4);
Push(m, rde, m->ip);
Write64(m->cs, m->xedd->op.uimm0 << 4);
m->ip = m->xedd->op.disp & (Osz(rde) ? 0xffff : 0xffffffff);
if (m->onlongbranch) {
m->onlongbranch(m);
}
}
relegated void OpRetf(struct Machine *m, uint32_t rde) {
m->ip = Pop(m, rde, 0);
Write64(m->cs, Pop(m, rde, m->xedd->op.uimm0) << 4);
if (m->onlongbranch) {
m->onlongbranch(m);
}
}

View file

@ -1,27 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_STACK_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_STACK_H_
#include "tool/build/lib/machine.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
void Push(struct Machine *, uint32_t, uint64_t);
uint64_t Pop(struct Machine *, uint32_t, uint16_t);
void OpCallJvds(struct Machine *, uint32_t);
void OpRet(struct Machine *, uint32_t);
void OpRetf(struct Machine *, uint32_t);
void OpLeave(struct Machine *, uint32_t);
void OpCallEq(struct Machine *, uint32_t);
void OpPopEvq(struct Machine *, uint32_t);
void OpPopZvq(struct Machine *, uint32_t);
void OpPushZvq(struct Machine *, uint32_t);
void OpPushEvq(struct Machine *, uint32_t);
void PopVq(struct Machine *, uint32_t);
void PushVq(struct Machine *, uint32_t);
void OpJmpEq(struct Machine *, uint32_t);
void OpPusha(struct Machine *, uint32_t);
void OpPopa(struct Machine *, uint32_t);
void OpCallf(struct Machine *, uint32_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_STACK_H_ */

View file

@ -1,23 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "tool/build/lib/stats.h"
unsigned long taken;
unsigned long ntaken;
unsigned long opcount;

View file

@ -1,12 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_STATS_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_STATS_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
extern unsigned long taken;
extern unsigned long ntaken;
extern unsigned long opcount;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_STATS_H_ */

View file

@ -1,285 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "tool/build/lib/string.h"
#include "libc/assert.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "tool/build/lib/address.h"
#include "tool/build/lib/alu.h"
#include "tool/build/lib/endian.h"
#include "tool/build/lib/flags.h"
#include "tool/build/lib/ioports.h"
#include "tool/build/lib/machine.h"
#include "tool/build/lib/memory.h"
#include "tool/build/lib/modrm.h"
#include "tool/build/lib/throw.h"
static uint64_t ReadInt(uint8_t p[8], unsigned long w) {
switch (w) {
case 0:
return Read8(p);
case 1:
return Read16(p);
case 2:
return Read32(p);
case 3:
return Read64(p);
default:
__builtin_unreachable();
}
}
static void WriteInt(uint8_t p[8], uint64_t x, unsigned long w) {
switch (w) {
case 0:
Write8(p, x);
break;
case 1:
Write16(p, x);
break;
case 2:
Write64(p, x & 0xffffffff);
break;
case 3:
Write64(p, x);
break;
default:
__builtin_unreachable();
}
}
static void AddDi(struct Machine *m, uint32_t rde, uint64_t x) {
switch (Eamode(rde)) {
case XED_MODE_LONG:
Write64(m->di, Read64(m->di) + x);
return;
case XED_MODE_LEGACY:
Write64(m->di, (Read32(m->di) + x) & 0xffffffff);
return;
case XED_MODE_REAL:
Write16(m->di, Read16(m->di) + x);
return;
default:
__builtin_unreachable();
}
}
static void AddSi(struct Machine *m, uint32_t rde, uint64_t x) {
switch (Eamode(rde)) {
case XED_MODE_LONG:
Write64(m->si, Read64(m->si) + x);
return;
case XED_MODE_LEGACY:
Write64(m->si, (Read32(m->si) + x) & 0xffffffff);
return;
case XED_MODE_REAL:
Write16(m->si, Read16(m->si) + x);
return;
default:
__builtin_unreachable();
}
}
static uint64_t ReadCx(struct Machine *m, uint32_t rde) {
switch (Eamode(rde)) {
case XED_MODE_LONG:
return Read64(m->cx);
case XED_MODE_LEGACY:
return Read32(m->cx);
case XED_MODE_REAL:
return Read16(m->cx);
default:
__builtin_unreachable();
}
}
static uint64_t SubtractCx(struct Machine *m, uint32_t rde, uint64_t x) {
uint64_t cx;
cx = Read64(m->cx) - x;
if (Eamode(rde) != XED_MODE_REAL) {
if (Eamode(rde) == XED_MODE_LEGACY) {
cx &= 0xffffffff;
}
Write64(m->cx, cx);
} else {
cx &= 0xffff;
Write16(m->cx, cx);
}
return cx;
}
static void StringOp(struct Machine *m, uint32_t rde, int op) {
bool stop;
void *p[2];
unsigned n;
int64_t sgn, v;
uint8_t s[3][8];
stop = false;
n = 1 << RegLog2(rde);
sgn = GetFlag(m->flags, FLAGS_DF) ? -1 : 1;
do {
if (Rep(rde) && !ReadCx(m, rde)) break;
switch (op) {
case STRING_CMPS:
kAlu[ALU_SUB][RegLog2(rde)](
ReadInt(Load(m, AddressSi(m, rde), n, s[2]), RegLog2(rde)),
ReadInt(Load(m, AddressDi(m, rde), n, s[1]), RegLog2(rde)),
&m->flags);
AddDi(m, rde, sgn * n);
AddSi(m, rde, sgn * n);
stop = (Rep(rde) == 2 && GetFlag(m->flags, FLAGS_ZF)) ||
(Rep(rde) == 3 && !GetFlag(m->flags, FLAGS_ZF));
break;
case STRING_MOVS:
memcpy(BeginStore(m, (v = AddressDi(m, rde)), n, p, s[0]),
Load(m, AddressSi(m, rde), n, s[1]), n);
AddDi(m, rde, sgn * n);
AddSi(m, rde, sgn * n);
EndStore(m, v, n, p, s[0]);
break;
case STRING_STOS:
memcpy(BeginStore(m, (v = AddressDi(m, rde)), n, p, s[0]), m->ax, n);
AddDi(m, rde, sgn * n);
EndStore(m, v, n, p, s[0]);
break;
case STRING_LODS:
memcpy(m->ax, Load(m, AddressSi(m, rde), n, s[1]), n);
AddSi(m, rde, sgn * n);
break;
case STRING_SCAS:
kAlu[ALU_SUB][RegLog2(rde)](
ReadInt(Load(m, AddressDi(m, rde), n, s[1]), RegLog2(rde)),
ReadInt(m->ax, RegLog2(rde)), &m->flags);
AddDi(m, rde, sgn * n);
stop = (Rep(rde) == 2 && GetFlag(m->flags, FLAGS_ZF)) ||
(Rep(rde) == 3 && !GetFlag(m->flags, FLAGS_ZF));
break;
case STRING_OUTS:
OpOut(m, Read16(m->dx),
ReadInt(Load(m, AddressSi(m, rde), n, s[1]), RegLog2(rde)));
AddSi(m, rde, sgn * n);
break;
case STRING_INS:
WriteInt(BeginStore(m, (v = AddressDi(m, rde)), n, p, s[0]),
OpIn(m, Read16(m->dx)), RegLog2(rde));
AddDi(m, rde, sgn * n);
EndStore(m, v, n, p, s[0]);
break;
default:
abort();
}
if (Rep(rde)) {
SubtractCx(m, rde, 1);
} else {
break;
}
} while (!stop);
}
static void RepMovsbEnhanced(struct Machine *m, uint32_t rde) {
uint8_t *direal, *sireal;
uint64_t diactual, siactual, cx;
unsigned diremain, siremain, i, n;
if ((cx = ReadCx(m, rde))) {
do {
diactual = AddressDi(m, rde);
siactual = AddressSi(m, rde);
SetWriteAddr(m, diactual, cx);
SetReadAddr(m, siactual, cx);
direal = ResolveAddress(m, diactual);
sireal = ResolveAddress(m, siactual);
diremain = 0x1000 - (diactual & 0xfff);
siremain = 0x1000 - (siactual & 0xfff);
n = MIN(cx, MIN(diremain, siremain));
if ((uintptr_t)direal <= (uintptr_t)sireal ||
(uintptr_t)direal >= (uintptr_t)sireal + n) {
memcpy(direal, sireal, n);
} else {
for (i = 0; i < n; ++i) {
direal[i] = sireal[i];
}
}
AddDi(m, rde, n);
AddSi(m, rde, n);
} while ((cx = SubtractCx(m, rde, n)));
}
}
static void RepStosbEnhanced(struct Machine *m, uint32_t rde) {
uint8_t *direal;
unsigned diremain, n;
uint64_t divirtual, diactual, cx;
if ((cx = ReadCx(m, rde))) {
do {
diactual = AddressDi(m, rde);
SetWriteAddr(m, diactual, cx);
direal = ResolveAddress(m, diactual);
diremain = 0x1000 - (diactual & 0xfff);
n = MIN(cx, diremain);
memset(direal, Read8(m->ax), n);
AddDi(m, rde, n);
} while ((cx = SubtractCx(m, rde, n)));
}
}
void OpMovs(struct Machine *m, uint32_t rde) {
StringOp(m, rde, STRING_MOVS);
}
void OpCmps(struct Machine *m, uint32_t rde) {
StringOp(m, rde, STRING_CMPS);
}
void OpStos(struct Machine *m, uint32_t rde) {
StringOp(m, rde, STRING_STOS);
}
void OpLods(struct Machine *m, uint32_t rde) {
StringOp(m, rde, STRING_LODS);
}
void OpScas(struct Machine *m, uint32_t rde) {
StringOp(m, rde, STRING_SCAS);
}
void OpIns(struct Machine *m, uint32_t rde) {
StringOp(m, rde, STRING_INS);
}
void OpOuts(struct Machine *m, uint32_t rde) {
StringOp(m, rde, STRING_OUTS);
}
void OpMovsb(struct Machine *m, uint32_t rde) {
if (Rep(rde) && !GetFlag(m->flags, FLAGS_DF)) {
RepMovsbEnhanced(m, rde);
} else {
OpMovs(m, rde);
}
}
void OpStosb(struct Machine *m, uint32_t rde) {
if (Rep(rde) && !GetFlag(m->flags, FLAGS_DF)) {
RepStosbEnhanced(m, rde);
} else {
OpStos(m, rde);
}
}

View file

@ -1,28 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_STRING_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_STRING_H_
#include "tool/build/lib/machine.h"
#define STRING_CMPS 0
#define STRING_MOVS 1
#define STRING_STOS 2
#define STRING_LODS 3
#define STRING_SCAS 4
#define STRING_OUTS 5
#define STRING_INS 6
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
void OpMovsb(struct Machine *, uint32_t);
void OpStosb(struct Machine *, uint32_t);
void OpMovs(struct Machine *, uint32_t);
void OpCmps(struct Machine *, uint32_t);
void OpStos(struct Machine *, uint32_t);
void OpLods(struct Machine *, uint32_t);
void OpScas(struct Machine *, uint32_t);
void OpIns(struct Machine *, uint32_t);
void OpOuts(struct Machine *, uint32_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_STRING_H_ */

File diff suppressed because it is too large Load diff

View file

@ -1,14 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_SYSCALL_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_SYSCALL_H_
#include "tool/build/lib/fds.h"
#include "tool/build/lib/machine.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
extern const struct MachineFdCb kMachineFdCbHost;
void OpSyscall(struct Machine *, uint32_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_SYSCALL_H_ */

View file

@ -1,69 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/mem/gc.internal.h"
#include "libc/nexgen32e/vendor.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "tool/build/lib/address.h"
#include "tool/build/lib/endian.h"
#include "tool/build/lib/throw.h"
static bool IsHaltingInitialized(struct Machine *m) {
jmp_buf zb;
bzero(zb, sizeof(zb));
return memcmp(m->onhalt, zb, sizeof(m->onhalt)) != 0;
}
void HaltMachine(struct Machine *m, int code) {
CHECK(IsHaltingInitialized(m));
_gclongjmp(m->onhalt, code);
}
void ThrowDivideError(struct Machine *m) {
HaltMachine(m, kMachineDivideError);
}
void ThrowSegmentationFault(struct Machine *m, int64_t va) {
m->faultaddr = va;
if (m->xedd) m->ip -= m->xedd->length;
WARNF("%s%s ADDR %012lx IP %012lx AX %lx CX %lx DX %lx BX %lx SP %lx "
"BP %lx SI %lx DI %lx R8 %lx R9 %lx R10 %lx R11 %lx R12 %lx R13 %lx "
"R14 %lx R15 %lx",
"SEGMENTATION FAULT", IsGenuineBlink() ? " SIMULATED" : "", va, m->ip,
Read64(m->ax), Read64(m->cx), Read64(m->dx), Read64(m->bx),
Read64(m->sp), Read64(m->bp), Read64(m->si), Read64(m->di),
Read64(m->r8), Read64(m->r9), Read64(m->r10), Read64(m->r11),
Read64(m->r12), Read64(m->r13), Read64(m->r14), Read64(m->r15));
HaltMachine(m, kMachineSegmentationFault);
}
void ThrowProtectionFault(struct Machine *m) {
HaltMachine(m, kMachineProtectionFault);
}
void OpUd(struct Machine *m, uint32_t rde) {
if (m->xedd) m->ip -= m->xedd->length;
HaltMachine(m, kMachineUndefinedInstruction);
}
void OpHlt(struct Machine *m, uint32_t rde) {
HaltMachine(m, kMachineHalt);
}

View file

@ -1,16 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_THROW_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_THROW_H_
#include "tool/build/lib/machine.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
void OpUd(struct Machine *, uint32_t) wontreturn;
void HaltMachine(struct Machine *, int) wontreturn;
void ThrowDivideError(struct Machine *) wontreturn;
void ThrowSegmentationFault(struct Machine *, int64_t) wontreturn;
void ThrowProtectionFault(struct Machine *) wontreturn;
void OpHlt(struct Machine *, uint32_t) wontreturn;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_THROW_H_ */

View file

@ -1,69 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/struct/timespec.h"
#include "libc/nexgen32e/rdtsc.h"
#include "libc/sock/sock.h"
#include "libc/sysv/consts/clock.h"
#include "libc/sysv/consts/poll.h"
#include "libc/time/time.h"
#include "tool/build/lib/endian.h"
#include "tool/build/lib/modrm.h"
#include "tool/build/lib/time.h"
/**
* @fileoverview i am the timelorde
*/
void OpPause(struct Machine *m, uint32_t rde) {
struct pollfd pf;
static bool once, interactive;
if (!once) {
interactive = isatty(0);
once = true;
}
pf.fd = 0;
pf.events = POLLIN;
poll(&pf, 1, 20); /* make spin loops less brutal */
}
void OpRdtsc(struct Machine *m, uint32_t rde) {
uint64_t c;
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
c = ts.tv_sec * 1000000000 + ts.tv_nsec;
Write64(m->ax, (c >> 000) & 0xffffffff);
Write64(m->dx, (c >> 040) & 0xffffffff);
}
static int64_t GetTscAux(struct Machine *m) {
uint32_t core, node;
core = 0;
node = 0;
return (node & 0xfff) << 12 | (core & 0xfff);
}
void OpRdtscp(struct Machine *m, uint32_t rde) {
OpRdtsc(m, rde);
Write64(m->cx, GetTscAux(m));
}
void OpRdpid(struct Machine *m, uint32_t rde) {
Write64(RegRexbRm(m, rde), GetTscAux(m));
}

View file

@ -1,14 +0,0 @@
#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 OpPause(struct Machine *, uint32_t);
void OpRdtsc(struct Machine *, uint32_t);
void OpRdtscp(struct Machine *, uint32_t);
void OpRdpid(struct Machine *, uint32_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_TIME_H_ */

View file

@ -1,64 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/str/str.h"
#include "tool/build/lib/endian.h"
#include "tool/build/lib/memory.h"
#include "tool/build/lib/word.h"
void SetMemoryShort(struct Machine *m, int64_t v, int16_t i) {
void *p[2];
uint8_t b[2];
Write16(BeginStore(m, v, 2, p, b), i);
EndStore(m, v, 2, p, b);
}
void SetMemoryInt(struct Machine *m, int64_t v, int32_t i) {
void *p[2];
uint8_t b[4];
Write32(BeginStore(m, v, 4, p, b), i);
EndStore(m, v, 4, p, b);
}
void SetMemoryLong(struct Machine *m, int64_t v, int64_t i) {
void *p[2];
uint8_t b[8];
Write64(BeginStore(m, v, 8, p, b), i);
EndStore(m, v, 8, p, b);
}
void SetMemoryFloat(struct Machine *m, int64_t v, float f) {
void *p[2];
uint8_t b[4];
memcpy(BeginStore(m, v, 4, p, b), &f, 4);
EndStore(m, v, 4, p, b);
}
void SetMemoryDouble(struct Machine *m, int64_t v, double f) {
void *p[2];
uint8_t b[8];
memcpy(BeginStore(m, v, 8, p, b), &f, 8);
EndStore(m, v, 8, p, b);
}
void SetMemoryLdbl(struct Machine *m, int64_t v, long double f) {
void *p[2];
uint8_t b[10];
memcpy(BeginStore(m, v, 10, p, b), &f, 10);
EndStore(m, v, 10, p, b);
}

View file

@ -1,16 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_WORD_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_WORD_H_
#include "tool/build/lib/machine.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
void SetMemoryShort(struct Machine *, int64_t, int16_t);
void SetMemoryInt(struct Machine *, int64_t, int32_t);
void SetMemoryLong(struct Machine *, int64_t, int64_t);
void SetMemoryFloat(struct Machine *, int64_t, float);
void SetMemoryDouble(struct Machine *, int64_t, double);
void SetMemoryLdbl(struct Machine *, int64_t, long double);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_WORD_H_ */

File diff suppressed because it is too large Load diff

View file

@ -1,53 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_XLAT_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_XLAT_H_
#include "libc/calls/struct/itimerval.h"
#include "libc/calls/struct/rusage.h"
#include "libc/calls/struct/sigset.h"
#include "libc/calls/struct/stat.h"
#include "libc/calls/struct/termios.h"
#include "libc/calls/struct/winsize.h"
#include "libc/sock/struct/sockaddr.h"
#include "tool/build/lib/bits.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
int UnXlatSicode(int, int);
int UnXlatSignal(int);
int XlatAccess(int);
int XlatAdvice(int);
int XlatAtf(int);
int XlatClock(int);
int XlatErrno(int);
int XlatFcntlArg(int);
int XlatFcntlCmd(int);
int XlatLock(int);
int XlatMapFlags(int);
int XlatMsyncFlags(int);
int XlatOpenFlags(int);
int XlatOpenMode(int);
int XlatRusage(int);
int XlatSig(int);
int XlatSignal(int);
int XlatSocketFamily(int);
int XlatSocketFlags(int);
int XlatSocketLevel(int);
int XlatSocketOptname(int, int);
int XlatSocketProtocol(int);
int XlatSocketType(int);
int XlatWait(int);
void XlatSockaddrToHost(struct sockaddr_in *, const struct sockaddr_in_bits *);
void XlatSockaddrToLinux(struct sockaddr_in_bits *, const struct sockaddr_in *);
void XlatStatToLinux(struct stat_bits *, const struct stat *);
void XlatRusageToLinux(struct rusage_bits *, const struct rusage *);
void XlatItimervalToLinux(struct itimerval_bits *, const struct itimerval *);
void XlatLinuxToItimerval(struct itimerval *, const struct itimerval_bits *);
void XlatLinuxToTermios(struct termios *, const struct termios_bits *);
void XlatTermiosToLinux(struct termios_bits *, const struct termios *);
void XlatWinsizeToLinux(struct winsize_bits *, const struct winsize *);
void XlatSigsetToLinux(uint8_t[8], const sigset_t *);
void XlatLinuxToSigset(sigset_t *, const uint8_t[8]);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_XLAT_H_ */

View file

@ -1,40 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/errno.h"
#include "libc/mem/mem.h"
struct thatispacked LinuxErrno {
int32_t local;
uint8_t linux;
};
extern const struct LinuxErrno kLinuxErrnos[];
/**
* Turns local errno into Linux errno.
*/
int XlatErrno(int local) {
int i;
for (i = 0; kLinuxErrnos[i].local; ++i) {
if (local == *(int *)((intptr_t)kLinuxErrnos + kLinuxErrnos[i].local)) {
return kLinuxErrnos[i].linux;
}
}
return ENOSYS;
}

View file

@ -1,186 +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
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "tool/build/lib/modrm.h"
#include "tool/build/lib/xmmtype.h"
static void UpdateXmmTypes(struct Machine *m, struct XmmType *xt, int regtype,
int rmtype) {
xt->type[RexrReg(m->xedd->op.rde)] = regtype;
if (IsModrmRegister(m->xedd->op.rde)) {
xt->type[RexbRm(m->xedd->op.rde)] = rmtype;
}
}
static void UpdateXmmSizes(struct Machine *m, struct XmmType *xt, int regsize,
int rmsize) {
xt->size[RexrReg(m->xedd->op.rde)] = regsize;
if (IsModrmRegister(m->xedd->op.rde)) {
xt->size[RexbRm(m->xedd->op.rde)] = rmsize;
}
}
void UpdateXmmType(struct Machine *m, struct XmmType *xt) {
switch (m->xedd->op.dispatch) {
case 0x110:
case 0x111: // MOVSS,MOVSD
if (Rep(m->xedd->op.rde) == 3) {
UpdateXmmTypes(m, xt, kXmmFloat, kXmmFloat);
} else if (Rep(m->xedd->op.rde) == 2) {
UpdateXmmTypes(m, xt, kXmmDouble, kXmmDouble);
}
break;
case 0x12E: // UCOMIS
case 0x12F: // COMIS
case 0x151: // SQRT
case 0x152: // RSQRT
case 0x153: // RCP
case 0x158: // ADD
case 0x159: // MUL
case 0x15C: // SUB
case 0x15D: // MIN
case 0x15E: // DIV
case 0x15F: // MAX
case 0x1C2: // CMP
if (Osz(m->xedd->op.rde) || Rep(m->xedd->op.rde) == 2) {
UpdateXmmTypes(m, xt, kXmmDouble, kXmmDouble);
} else {
UpdateXmmTypes(m, xt, kXmmFloat, kXmmFloat);
}
break;
case 0x12A: // CVTPI2PS,CVTSI2SS,CVTPI2PD,CVTSI2SD
if (Osz(m->xedd->op.rde) || Rep(m->xedd->op.rde) == 2) {
UpdateXmmSizes(m, xt, 8, 4);
UpdateXmmTypes(m, xt, kXmmDouble, kXmmIntegral);
} else {
UpdateXmmSizes(m, xt, 4, 4);
UpdateXmmTypes(m, xt, kXmmFloat, kXmmIntegral);
}
break;
case 0x15A: // CVT{P,S}{S,D}2{P,S}{S,D}
if (Osz(m->xedd->op.rde) || Rep(m->xedd->op.rde) == 2) {
UpdateXmmTypes(m, xt, kXmmFloat, kXmmDouble);
} else {
UpdateXmmTypes(m, xt, kXmmDouble, kXmmFloat);
}
break;
case 0x15B: // CVT{,T}{DQ,PS}2{PS,DQ}
UpdateXmmSizes(m, xt, 4, 4);
if (Osz(m->xedd->op.rde) || Rep(m->xedd->op.rde) == 3) {
UpdateXmmTypes(m, xt, kXmmIntegral, kXmmFloat);
} else {
UpdateXmmTypes(m, xt, kXmmFloat, kXmmIntegral);
}
break;
case 0x17C: // HADD
case 0x17D: // HSUB
case 0x1D0: // ADDSUB
if (Osz(m->xedd->op.rde)) {
UpdateXmmTypes(m, xt, kXmmDouble, kXmmDouble);
} else {
UpdateXmmTypes(m, xt, kXmmFloat, kXmmFloat);
}
break;
case 0x164: // PCMPGTB
case 0x174: // PCMPEQB
case 0x1D8: // PSUBUSB
case 0x1DA: // PMINUB
case 0x1DC: // PADDUSB
case 0x1DE: // PMAXUB
case 0x1E0: // PAVGB
case 0x1E8: // PSUBSB
case 0x1EC: // PADDSB
case 0x1F8: // PSUBB
case 0x1FC: // PADDB
UpdateXmmSizes(m, xt, 1, 1);
UpdateXmmTypes(m, xt, kXmmIntegral, kXmmIntegral);
break;
case 0x165: // PCMPGTW
case 0x175: // PCMPEQW
case 0x171: // PSRLW,PSRAW,PSLLW
case 0x1D1: // PSRLW
case 0x1D5: // PMULLW
case 0x1D9: // PSUBUSW
case 0x1DD: // PADDUSW
case 0x1E1: // PSRAW
case 0x1E3: // PAVGW
case 0x1E4: // PMULHUW
case 0x1E5: // PMULHW
case 0x1E9: // PSUBSW
case 0x1EA: // PMINSW
case 0x1ED: // PADDSW
case 0x1EE: // PMAXSW
case 0x1F1: // PSLLW
case 0x1F6: // PSADBW
case 0x1F9: // PSUBW
case 0x1FD: // PADDW
UpdateXmmSizes(m, xt, 2, 2);
UpdateXmmTypes(m, xt, kXmmIntegral, kXmmIntegral);
break;
case 0x166: // PCMPGTD
case 0x176: // PCMPEQD
case 0x172: // PSRLD,PSRAD,PSLLD
case 0x1D2: // PSRLD
case 0x1E2: // PSRAD
case 0x1F2: // PSLLD
case 0x1FA: // PSUBD
case 0x1FE: // PADDD
UpdateXmmSizes(m, xt, 4, 4);
UpdateXmmTypes(m, xt, kXmmIntegral, kXmmIntegral);
break;
case 0x173: // PSRLQ,PSRLQ,PSRLDQ,PSLLQ,PSLLDQ
case 0x1D3: // PSRLQ
case 0x1D4: // PADDQ
case 0x1F3: // PSLLQ
case 0x1F4: // PMULUDQ
case 0x1FB: // PSUBQ
UpdateXmmSizes(m, xt, 8, 8);
UpdateXmmTypes(m, xt, kXmmIntegral, kXmmIntegral);
break;
case 0x16B: // PACKSSDW
case 0x1F5: // PMADDWD
UpdateXmmSizes(m, xt, 4, 2);
UpdateXmmTypes(m, xt, kXmmIntegral, kXmmIntegral);
break;
case 0x163: // PACKSSWB
case 0x167: // PACKUSWB
UpdateXmmSizes(m, xt, 1, 2);
UpdateXmmTypes(m, xt, kXmmIntegral, kXmmIntegral);
break;
case 0x128: // MOVAPS Vps Wps
if (IsModrmRegister(m->xedd->op.rde)) {
xt->type[RexrReg(m->xedd->op.rde)] = xt->type[RexbRm(m->xedd->op.rde)];
xt->size[RexrReg(m->xedd->op.rde)] = xt->size[RexbRm(m->xedd->op.rde)];
}
break;
case 0x129: // MOVAPS Wps Vps
if (IsModrmRegister(m->xedd->op.rde)) {
xt->type[RexbRm(m->xedd->op.rde)] = xt->type[RexrReg(m->xedd->op.rde)];
xt->size[RexbRm(m->xedd->op.rde)] = xt->size[RexrReg(m->xedd->op.rde)];
}
break;
case 0x16F: // MOVDQA Vdq Wdq
if (Osz(m->xedd->op.rde) && IsModrmRegister(m->xedd->op.rde)) {
xt->type[RexrReg(m->xedd->op.rde)] = xt->type[RexbRm(m->xedd->op.rde)];
xt->size[RexrReg(m->xedd->op.rde)] = xt->size[RexbRm(m->xedd->op.rde)];
}
break;
default:
return;
}
}

View file

@ -1,21 +0,0 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_XMMTYPE_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_XMMTYPE_H_
#include "tool/build/lib/machine.h"
#define kXmmIntegral 0
#define kXmmDouble 1
#define kXmmFloat 2
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct XmmType {
uint8_t type[16];
uint8_t size[16];
};
void UpdateXmmType(struct Machine *, struct XmmType *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_XMMTYPE_H_ */