mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-01 16:58:30 +00:00
parent
50d8d953ce
commit
06b749ae03
130 changed files with 2 additions and 26665 deletions
|
@ -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_ */
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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_ */
|
|
@ -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);
|
||||
}
|
|
@ -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_ */
|
|
@ -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);
|
||||
}
|
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
|
@ -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_ */
|
|
@ -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};
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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_ */
|
|
@ -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);
|
||||
}
|
|
@ -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_ */
|
|
@ -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);
|
||||
}
|
|
@ -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_ */
|
|
@ -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);
|
||||
}
|
|
@ -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_ */
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
|
@ -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); */
|
||||
}
|
|
@ -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
|
@ -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);
|
||||
}
|
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
|
@ -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_ */
|
1190
tool/build/lib/fpu.c
1190
tool/build/lib/fpu.c
File diff suppressed because it is too large
Load diff
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
|
@ -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_ */
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
|
@ -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_ */
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
@ -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_ */
|
|
@ -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], ' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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_ */
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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_ */
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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_ */
|
|
@ -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("");
|
||||
}
|
||||
}
|
1407
tool/build/lib/pty.c
1407
tool/build/lib/pty.c
File diff suppressed because it is too large
Load diff
|
@ -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_ */
|
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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_ */
|
1575
tool/build/lib/sse.c
1575
tool/build/lib/sse.c
File diff suppressed because it is too large
Load diff
|
@ -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_ */
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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_ */
|
|
@ -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);
|
||||
}
|
|
@ -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_ */
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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_ */
|
|
@ -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;
|
|
@ -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_ */
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
@ -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_ */
|
|
@ -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);
|
||||
}
|
|
@ -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_ */
|
|
@ -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));
|
||||
}
|
|
@ -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_ */
|
|
@ -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);
|
||||
}
|
|
@ -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
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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_ */
|
Loading…
Add table
Add a link
Reference in a new issue