mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-02 17:28:30 +00:00
Make improvements
- Emulator can now test the αcτµαlly pδrταblε εxεcµταblε bootloader - Whipped up a webserver named redbean. It services 150k requests per second on a single core. Bundling assets inside zip enables extremely fast serving for two reasons. The first is that zip central directory lookups go faster than stat() system calls. The second is that both zip and gzip content-encoding use DEFLATE, therefore, compressed responses can be served via the sendfile() system call which does an in-kernel copy directly from the zip executable structure. Also note that red bean zip executables can be deployed easily to all platforms, since these native executables work on Linux, Mac, BSD, and Windows. - Address sanitizer now works very well
This commit is contained in:
parent
7327c345f9
commit
416fd86676
230 changed files with 9835 additions and 5682 deletions
86
tool/build/lib/address.c
Normal file
86
tool/build/lib/address.c
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "third_party/xed/x86.h"
|
||||
#include "tool/build/lib/address.h"
|
||||
#include "tool/build/lib/endian.h"
|
||||
#include "tool/build/lib/modrm.h"
|
||||
#include "tool/build/lib/throw.h"
|
||||
|
||||
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:
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t AddSegment(struct Machine *m, uint32_t rde, uint64_t i, uint8_t s[8]) {
|
||||
if (!Sego(rde)) {
|
||||
i += Read64(s);
|
||||
} else {
|
||||
i += Read64(GetSegment(m, rde, Sego(rde) - 1));
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
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:
|
||||
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:
|
||||
unreachable;
|
||||
}
|
||||
}
|
28
tool/build/lib/address.h
Normal file
28
tool/build/lib/address.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#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 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_ */
|
|
@ -21,68 +21,753 @@
|
|||
#include "tool/build/lib/alu.h"
|
||||
#include "tool/build/lib/flags.h"
|
||||
|
||||
/**
|
||||
* NexGen32e Arithmetic Unit.
|
||||
*/
|
||||
int64_t Alu(int w, int h, uint64_t x, uint64_t y, uint32_t *flags) {
|
||||
uint64_t t, z, s, m, k;
|
||||
bool cf, of, zf, sf, af, carry;
|
||||
assert(w < 4);
|
||||
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 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;
|
||||
}
|
||||
|
||||
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;
|
||||
m |= s - 1;
|
||||
t = x;
|
||||
cf = 0;
|
||||
of = 0;
|
||||
af = 0;
|
||||
carry = GetFlag(*flags, FLAGS_CF);
|
||||
switch (h & 7) {
|
||||
case ALU_OR:
|
||||
z = x | y;
|
||||
break;
|
||||
case ALU_AND:
|
||||
z = x & y;
|
||||
break;
|
||||
case ALU_XOR:
|
||||
z = x ^ y;
|
||||
break;
|
||||
case ALU_CMP:
|
||||
h |= 8;
|
||||
carry = 0;
|
||||
case ALU_SBB:
|
||||
t = (x & m) - carry;
|
||||
cf = (x & m) < (t & m);
|
||||
af = (x & 15) < (t & 15);
|
||||
case ALU_SUB:
|
||||
z = (t & m) - (y & m);
|
||||
cf |= (t & m) < (z & m);
|
||||
af |= (t & 15) < (z & 15);
|
||||
of = !!((z ^ x) & (x ^ y) & s);
|
||||
break;
|
||||
case ALU_ADC:
|
||||
t = (x & m) + carry;
|
||||
cf = (t & m) < (x & m);
|
||||
af = (t & 15) < (x & 15);
|
||||
case ALU_ADD:
|
||||
z = (t & m) + (y & m);
|
||||
cf |= (z & m) < (y & m);
|
||||
af |= (z & 15) < (y & 15);
|
||||
of = !!((z ^ x) & (z ^ y) & s);
|
||||
break;
|
||||
default:
|
||||
unreachable;
|
||||
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;
|
||||
}
|
||||
z &= m;
|
||||
zf = !z;
|
||||
sf = !!(z & s);
|
||||
*flags = (*flags & ~(1 << FLAGS_CF | 1 << FLAGS_ZF | 1 << FLAGS_SF |
|
||||
1 << FLAGS_OF | 1 << FLAGS_AF)) |
|
||||
cf << FLAGS_CF | zf << FLAGS_ZF | sf << FLAGS_SF | of << FLAGS_OF |
|
||||
af << FLAGS_AF;
|
||||
*flags = SetLazyParityByte(*flags, x);
|
||||
if (h & ALU_TEST) z = x;
|
||||
return z;
|
||||
}
|
||||
|
|
|
@ -2,15 +2,18 @@
|
|||
#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_TEST 8
|
||||
#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
|
||||
|
@ -24,17 +27,93 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
typedef uint64_t (*aluop1_f)(struct Machine *, uint32_t, uint64_t);
|
||||
typedef uint64_t (*aluop2_f)(struct Machine *, uint32_t, uint64_t, uint64_t);
|
||||
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 *);
|
||||
|
||||
int64_t Alu(int, int, uint64_t, uint64_t, uint32_t *);
|
||||
int64_t Bsu(int, int, uint64_t, uint64_t, uint32_t *);
|
||||
uint64_t AluBt(struct Machine *, uint64_t, uint64_t);
|
||||
uint64_t AluBtc(struct Machine *, uint64_t, uint64_t);
|
||||
uint64_t AluBtr(struct Machine *, uint64_t, uint64_t);
|
||||
uint64_t AluBts(struct Machine *, uint64_t, uint64_t);
|
||||
uint64_t BsuDoubleShift(int, uint64_t, uint64_t, uint8_t, bool, uint32_t *);
|
||||
|
||||
int64_t AluFlags(uint64_t, uint32_t, uint32_t *, uint32_t, uint32_t, 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_ */
|
||||
|
|
78
tool/build/lib/bcd.c
Normal file
78
tool/build/lib/bcd.c
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "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"
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
15
tool/build/lib/bcd.h
Normal file
15
tool/build/lib/bcd.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#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_ */
|
|
@ -22,7 +22,7 @@
|
|||
#include "tool/build/lib/machine.h"
|
||||
#include "tool/build/lib/modrm.h"
|
||||
|
||||
uint64_t AluBsr(struct Machine *m, uint32_t rde, uint64_t _, uint64_t x) {
|
||||
uint64_t AluBsr(struct Machine *m, uint32_t rde, uint64_t x) {
|
||||
unsigned i;
|
||||
if (Rexw(rde)) {
|
||||
x &= 0xffffffffffffffff;
|
||||
|
@ -43,7 +43,7 @@ uint64_t AluBsr(struct Machine *m, uint32_t rde, uint64_t _, uint64_t x) {
|
|||
}
|
||||
}
|
||||
|
||||
uint64_t AluBsf(struct Machine *m, uint32_t rde, uint64_t _, uint64_t x) {
|
||||
uint64_t AluBsf(struct Machine *m, uint32_t rde, uint64_t x) {
|
||||
unsigned i;
|
||||
if (Rexw(rde)) {
|
||||
x &= 0xffffffffffffffff;
|
||||
|
@ -64,7 +64,7 @@ uint64_t AluBsf(struct Machine *m, uint32_t rde, uint64_t _, uint64_t x) {
|
|||
}
|
||||
}
|
||||
|
||||
uint64_t AluPopcnt(struct Machine *m, uint32_t rde, uint64_t _, uint64_t x) {
|
||||
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);
|
||||
|
|
|
@ -4,9 +4,11 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
uint64_t AluBsr(struct Machine *, uint32_t, uint64_t, uint64_t);
|
||||
uint64_t AluBsf(struct Machine *, uint32_t, uint64_t, uint64_t);
|
||||
uint64_t AluPopcnt(struct Machine *, uint32_t, uint64_t, uint64_t);
|
||||
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) */
|
||||
|
|
|
@ -1,167 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.h"
|
||||
#include "tool/build/lib/alu.h"
|
||||
#include "tool/build/lib/endian.h"
|
||||
#include "tool/build/lib/flags.h"
|
||||
#include "tool/build/lib/modrm.h"
|
||||
|
||||
/**
|
||||
* NexGen32e Bit Shift Unit.
|
||||
*/
|
||||
int64_t Bsu(int w, int h, uint64_t x, uint64_t y, uint32_t *f) {
|
||||
bool of;
|
||||
uint64_t s, k, t, xm, ym, cf;
|
||||
assert(w < 4);
|
||||
k = 8;
|
||||
k <<= w;
|
||||
s = 1;
|
||||
s <<= k - 1;
|
||||
xm = s;
|
||||
xm |= s - 1;
|
||||
ym = w == 3 ? 0x3F : 0x1F;
|
||||
switch (h & 7) {
|
||||
case BSU_SHR:
|
||||
x &= xm;
|
||||
if ((y &= ym)) {
|
||||
*f = SetFlag(*f, FLAGS_CF, !!(x & (1ull << (y - 1))));
|
||||
x = x >> y;
|
||||
*f = SetLazyParityByte(*f, x);
|
||||
*f = SetFlag(*f, FLAGS_OF, !!(((x << 1) ^ x) & s));
|
||||
*f = SetFlag(*f, FLAGS_ZF, !x);
|
||||
*f = SetFlag(*f, FLAGS_SF, !!(x & s));
|
||||
}
|
||||
return x;
|
||||
case BSU_SAL:
|
||||
case BSU_SHL:
|
||||
x &= xm;
|
||||
if ((y &= ym)) {
|
||||
*f = SetFlag(*f, FLAGS_CF, (cf = !!(x & (1ull << ((k - y) & ym)))));
|
||||
x = (x << y) & xm;
|
||||
*f = SetLazyParityByte(*f, x);
|
||||
*f = SetFlag(*f, FLAGS_OF, !!(x & s) ^ cf);
|
||||
*f = SetFlag(*f, FLAGS_ZF, !x);
|
||||
*f = SetFlag(*f, FLAGS_SF, !!(x & s));
|
||||
}
|
||||
return x;
|
||||
case BSU_SAR:
|
||||
x &= xm;
|
||||
if ((y &= ym)) {
|
||||
x &= xm;
|
||||
t = !!(x & s);
|
||||
x >>= (y - 1);
|
||||
if (t) x |= ~(xm >> (y - 1));
|
||||
*f = SetFlag(*f, FLAGS_CF, x & 1);
|
||||
x >>= 1;
|
||||
if (t) x = (x | ~(xm >> y)) & xm;
|
||||
*f = SetLazyParityByte(*f, x);
|
||||
*f = SetFlag(*f, FLAGS_OF, 0);
|
||||
*f = SetFlag(*f, FLAGS_ZF, !x);
|
||||
*f = SetFlag(*f, FLAGS_SF, !!(x & s));
|
||||
}
|
||||
return x;
|
||||
case BSU_ROL:
|
||||
x &= xm;
|
||||
if (y & (k - 1)) {
|
||||
y &= k - 1;
|
||||
x = (x << y | x >> (k - y)) & xm;
|
||||
*f = SetFlag(*f, FLAGS_CF, x & 1);
|
||||
*f = SetFlag(*f, FLAGS_OF, ((x >> (k - 1)) ^ x) & 1);
|
||||
} else if (y & 0x1F) {
|
||||
*f = SetFlag(*f, FLAGS_CF, x & 1);
|
||||
*f = SetFlag(*f, FLAGS_OF, ((x >> (k - 1)) ^ x) & 1);
|
||||
}
|
||||
return x;
|
||||
case BSU_ROR:
|
||||
x &= xm;
|
||||
if (y & (k - 1)) {
|
||||
y &= k - 1;
|
||||
x = (x >> y | x << (k - y)) & xm;
|
||||
*f = SetFlag(*f, FLAGS_CF, (x >> (k - 1)) & 1);
|
||||
*f = SetFlag(*f, FLAGS_OF, ((x >> (k - 2)) ^ (x >> (k - 1))) & 1);
|
||||
} else if (y & 0x1F) {
|
||||
*f = SetFlag(*f, FLAGS_CF, (x >> (k - 1)) & 1);
|
||||
*f = SetFlag(*f, FLAGS_OF, ((x >> (k - 2)) ^ (x >> (k - 1))) & 1);
|
||||
}
|
||||
return x;
|
||||
case BSU_RCR:
|
||||
x &= xm;
|
||||
if ((y = (y & ym) % (k + 1))) {
|
||||
cf = GetFlag(*f, FLAGS_CF);
|
||||
*f = SetFlag(*f, FLAGS_CF, (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;
|
||||
}
|
||||
*f = SetFlag(*f, FLAGS_OF, (((x << 1) ^ x) >> (k - 1)) & 1);
|
||||
}
|
||||
return x;
|
||||
case BSU_RCL:
|
||||
x &= xm;
|
||||
if ((y = (y & ym) % (k + 1))) {
|
||||
cf = GetFlag(*f, FLAGS_CF);
|
||||
*f = SetFlag(*f, FLAGS_CF, (t = (x >> (k - y)) & 1));
|
||||
if (y == 1) {
|
||||
x = (x << 1 | cf) & xm;
|
||||
} else {
|
||||
x = (x << y | cf << (y - 1) | x >> (k + 1 - y)) & xm;
|
||||
}
|
||||
*f = SetFlag(*f, FLAGS_OF, t ^ !!(x & s));
|
||||
}
|
||||
return x;
|
||||
default:
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
*f = SetFlag(*f, FLAGS_CF, cf);
|
||||
*f = SetFlag(*f, FLAGS_OF, of);
|
||||
*f = SetFlag(*f, FLAGS_ZF, !x);
|
||||
*f = SetFlag(*f, FLAGS_SF, !!(x & s));
|
||||
*f = SetLazyParityByte(*f, x & 0xff);
|
||||
}
|
||||
return x;
|
||||
}
|
|
@ -63,9 +63,15 @@ $(TOOL_BUILD_LIB_A).pkg: \
|
|||
$(TOOL_BUILD_LIB_A_OBJS) \
|
||||
$(foreach x,$(TOOL_BUILD_LIB_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
# $(TOOL_BUILD_LIB_A_OBJS): \
|
||||
# OVERRIDE_CFLAGS += \
|
||||
# -fsanitize=address
|
||||
ifeq (,$(MODE))
|
||||
$(TOOL_BUILD_LIB_A_OBJS): \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-fsanitize=address
|
||||
endif
|
||||
|
||||
o/$(MODE)/tool/build/lib/ssefloat.o: \
|
||||
TARGET_ARCH += \
|
||||
-msse3
|
||||
|
||||
TOOL_BUILD_LIB_LIBS = $(foreach x,$(TOOL_BUILD_LIB_ARTIFACTS),$($(x)))
|
||||
TOOL_BUILD_LIB_SRCS = $(foreach x,$(TOOL_BUILD_LIB_ARTIFACTS),$($(x)_SRCS))
|
||||
|
|
|
@ -17,55 +17,27 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/lib/pc.h"
|
||||
#include "libc/math.h"
|
||||
#include "tool/build/lib/x87.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "tool/build/lib/buffer.h"
|
||||
#include "tool/build/lib/cga.h"
|
||||
|
||||
static long ltruncl(long double x) {
|
||||
return x;
|
||||
}
|
||||
static const uint8_t kCgaToAnsi[] = {30, 34, 32, 36, 31, 35, 33, 37,
|
||||
90, 94, 92, 96, 91, 95, 93, 97};
|
||||
|
||||
static int ClearC2(int sw) {
|
||||
return sw & ~FPU_C2;
|
||||
}
|
||||
|
||||
static long double x87remainder(long double x, long double y, uint32_t *sw,
|
||||
long double rem(long double, long double),
|
||||
long rnd(long double)) {
|
||||
int s;
|
||||
long q;
|
||||
long double r;
|
||||
s = 0;
|
||||
r = rem(x, y);
|
||||
q = rnd(x / y);
|
||||
s &= ~FPU_C2; /* ty libm */
|
||||
if (q & 0b001) s |= FPU_C1;
|
||||
if (q & 0b010) s |= FPU_C3;
|
||||
if (q & 0b100) s |= FPU_C0;
|
||||
if (sw) *sw = s | (*sw & ~(FPU_C0 | FPU_C1 | FPU_C2 | FPU_C3));
|
||||
return r;
|
||||
}
|
||||
|
||||
long double f2xm1(long double x) {
|
||||
return exp2l(x) - 1;
|
||||
}
|
||||
|
||||
long double fyl2x(long double x, long double y) {
|
||||
return y * log2l(x);
|
||||
}
|
||||
|
||||
long double fyl2xp1(long double x, long double y) {
|
||||
return y * log2l(x + 1);
|
||||
}
|
||||
|
||||
long double fscale(long double significand, long double exponent) {
|
||||
return scalbl(significand, exponent);
|
||||
}
|
||||
|
||||
long double fprem(long double dividend, long double modulus, uint32_t *sw) {
|
||||
return x87remainder(dividend, modulus, sw, fmodl, ltruncl);
|
||||
}
|
||||
|
||||
long double fprem1(long double dividend, long double modulus, uint32_t *sw) {
|
||||
return x87remainder(dividend, modulus, sw, remainderl, lrintl);
|
||||
void DrawCga(struct Panel *p, uint8_t v[25][80][2]) {
|
||||
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) {
|
||||
a = v[y][x][1];
|
||||
AppendFmt(&p->lines[y], "\e[%d;%dm", kCgaToAnsi[a & 0x0F],
|
||||
kCgaToAnsi[(a & 0xF0) >> 4] + 10);
|
||||
}
|
||||
AppendWide(&p->lines[y], kCp437[v[y][x][0]]);
|
||||
}
|
||||
AppendStr(&p->lines[y], "\e[0m");
|
||||
}
|
||||
}
|
11
tool/build/lib/cga.h
Normal file
11
tool/build/lib/cga.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#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]);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_CGA_H_ */
|
|
@ -1,50 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_COND_H_
|
||||
#define COSMOPOLITAN_TOOL_BUILD_LIB_COND_H_
|
||||
#include "tool/build/lib/flags.h"
|
||||
#include "tool/build/lib/machine.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
forceinline bool GetCond(struct Machine *m, int x) {
|
||||
uint32_t f = m->flags;
|
||||
switch (x) {
|
||||
case 0:
|
||||
return GetFlag(f, FLAGS_OF);
|
||||
case 1:
|
||||
return !GetFlag(f, FLAGS_OF);
|
||||
case 2:
|
||||
return GetFlag(f, FLAGS_CF);
|
||||
case 3:
|
||||
return !GetFlag(f, FLAGS_CF);
|
||||
case 4:
|
||||
return GetFlag(f, FLAGS_ZF);
|
||||
case 5:
|
||||
return !GetFlag(f, FLAGS_ZF);
|
||||
case 6:
|
||||
return GetFlag(f, FLAGS_CF) || GetFlag(f, FLAGS_ZF);
|
||||
case 7:
|
||||
return !GetFlag(f, FLAGS_CF) && !GetFlag(f, FLAGS_ZF);
|
||||
case 8:
|
||||
return GetFlag(f, FLAGS_SF);
|
||||
case 9:
|
||||
return !GetFlag(f, FLAGS_SF);
|
||||
case 10:
|
||||
return GetFlag(f, FLAGS_PF);
|
||||
case 11:
|
||||
return !GetFlag(f, FLAGS_PF);
|
||||
case 12:
|
||||
return GetFlag(f, FLAGS_SF) != GetFlag(f, FLAGS_OF);
|
||||
case 13:
|
||||
return GetFlag(f, FLAGS_SF) == GetFlag(f, FLAGS_OF);
|
||||
case 14:
|
||||
return GetFlag(f, FLAGS_ZF) ||
|
||||
GetFlag(f, FLAGS_SF) != GetFlag(f, FLAGS_OF);
|
||||
case 15:
|
||||
return !GetFlag(f, FLAGS_ZF) &&
|
||||
GetFlag(f, FLAGS_SF) == GetFlag(f, FLAGS_OF);
|
||||
default:
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_COND_H_ */
|
|
@ -20,7 +20,7 @@
|
|||
#include "tool/build/lib/endian.h"
|
||||
#include "tool/build/lib/machine.h"
|
||||
|
||||
void OpCpuid(struct Machine *m) {
|
||||
void OpCpuid(struct Machine *m, uint32_t rde) {
|
||||
uint32_t ax, bx, cx, dx;
|
||||
ax = 0;
|
||||
bx = 0;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#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_
|
||||
#include "tool/build/lib/cvt.h"
|
||||
|
||||
void OpCpuid(struct Machine *);
|
||||
void OpCpuid(struct Machine *, uint32_t);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -26,6 +26,13 @@
|
|||
#include "tool/build/lib/modrm.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->sse.rc) {
|
||||
case 0:
|
||||
|
@ -285,7 +292,7 @@ static void OpVdqWpdCvtpd2dq(struct Machine *m, uint32_t rde) {
|
|||
memcpy(XmmRexrReg(m, rde), n, 8);
|
||||
}
|
||||
|
||||
void OpCvt(struct Machine *m, uint32_t rde, unsigned long op) {
|
||||
static void OpCvt(struct Machine *m, uint32_t rde, unsigned long op) {
|
||||
switch (op | Rep(rde) | Osz(rde)) {
|
||||
case kOpCvt0f2a + 0:
|
||||
OpVpsQpiCvtpi2ps(m, rde);
|
||||
|
@ -354,6 +361,30 @@ void OpCvt(struct Machine *m, uint32_t rde, unsigned long op) {
|
|||
OpVpdWdqCvtdq2pd(m, rde);
|
||||
break;
|
||||
default:
|
||||
OpUd(m);
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -4,14 +4,12 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define kOpCvt0f2a 0
|
||||
#define kOpCvtt0f2c 4
|
||||
#define kOpCvt0f2d 8
|
||||
#define kOpCvt0f5a 12
|
||||
#define kOpCvt0f5b 16
|
||||
#define kOpCvt0fE6 20
|
||||
|
||||
void OpCvt(struct Machine *, uint32_t, unsigned long);
|
||||
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) */
|
||||
|
|
|
@ -165,83 +165,82 @@ long DisFind(struct Dis *d, int64_t addr) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
void Dis(struct Dis *d, struct Machine *m, int64_t addr) {
|
||||
static long DisOne(struct Dis *d, struct Machine *m, int64_t addr) {
|
||||
void *r;
|
||||
unsigned k;
|
||||
uint8_t b[15];
|
||||
struct DisOp op;
|
||||
long i, n, symbol;
|
||||
n = 15;
|
||||
if ((symbol = DisFindSym(d, addr)) != -1) {
|
||||
if (d->syms.p[symbol].addr <= addr &&
|
||||
addr < d->syms.p[symbol].addr + d->syms.p[symbol].size) {
|
||||
n = d->syms.p[symbol].size - (addr - d->syms.p[symbol].addr);
|
||||
}
|
||||
if (addr == d->syms.p[symbol].addr && d->syms.p[symbol].name) {
|
||||
op.addr = addr;
|
||||
op.size = 0;
|
||||
op.active = true;
|
||||
DisLabel((struct DisBuilder){d, d->xedd, addr}, 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) {
|
||||
memcpy(b, r, n);
|
||||
} else {
|
||||
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, b, n);
|
||||
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, int64_t addr, 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 = DisOne(d, m, i)) == -1) return -1;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < lines; ++i, addr += j) {
|
||||
if ((j = DisOne(d, m, addr)) == -1) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *DisGetLine(struct Dis *d, struct Machine *m, size_t i) {
|
||||
char *p;
|
||||
void *r[2];
|
||||
bool iscode;
|
||||
int64_t unique;
|
||||
struct DisOp op;
|
||||
long i, j, n, si, max, toto, symbol;
|
||||
unique = 0;
|
||||
max = 999999;
|
||||
DisFreeOps(&d->ops);
|
||||
for (i = 0; i < max; ++i) {
|
||||
xed_decoded_inst_zero_set_mode(d->xedd, XED_MACHINE_MODE_LONG_64);
|
||||
if ((symbol = DisFindSym(d, addr)) != -1) {
|
||||
iscode = true; /* d->syms.p[symbol].iscode; */
|
||||
n = iscode ? CODELIM : DATALIM;
|
||||
if (d->syms.p[symbol].size) {
|
||||
n = MIN(n, d->syms.p[symbol].size);
|
||||
} else if (symbol + 1 < d->syms.i &&
|
||||
d->syms.p[symbol + 1].addr > d->syms.p[symbol].addr) {
|
||||
n = MIN(n, d->syms.p[symbol + 1].addr - d->syms.p[symbol].addr);
|
||||
}
|
||||
if (addr == d->syms.p[symbol].addr && d->syms.p[symbol].name) {
|
||||
op.addr = addr;
|
||||
op.unique = unique++;
|
||||
op.size = 0;
|
||||
op.active = true;
|
||||
DisLabel((struct DisBuilder){d, d->xedd, addr}, d->buf,
|
||||
d->syms.stab + d->syms.p[symbol].name);
|
||||
if (!(op.s = strdup(d->buf))) break;
|
||||
APPEND(&d->ops.p, &d->ops.i, &d->ops.n, &op);
|
||||
}
|
||||
} else {
|
||||
iscode = DisIsText(d, addr);
|
||||
n = CODELIM;
|
||||
}
|
||||
DCHECK_GT(n, 0);
|
||||
DCHECK_LE(n, ARRAYLEN(d->raw));
|
||||
memset(r, 0, sizeof(r));
|
||||
if (!(r[0] = FindReal(m, addr))) {
|
||||
max = MIN(100, max);
|
||||
n = MIN(DATALIM, 0x1000 - (addr & 0xfff));
|
||||
DCHECK_GT(n, 0);
|
||||
memset(d->raw, 0xCC, DATALIM);
|
||||
} else if ((addr & 0xfff) + n <= 0x1000) {
|
||||
memcpy(d->raw, r[0], n);
|
||||
} else if ((r[1] = FindReal(m, ROUNDUP(addr, 0x1000)))) {
|
||||
si = 0x1000 - (addr & 0xfff);
|
||||
memcpy(d->raw, r[0], si);
|
||||
memcpy(d->raw + si, r[1], n - si);
|
||||
} else {
|
||||
n = 0x1000 - (addr & 0xfff);
|
||||
DCHECK_GT(n, 0);
|
||||
memcpy(d->raw, r[0], n);
|
||||
}
|
||||
if (!NoDebug()) memset(d->buf, 0x55, sizeof(d->buf));
|
||||
if (1 || iscode) {
|
||||
xed_instruction_length_decode(d->xedd, d->raw, n);
|
||||
DCHECK_GT(n, 0);
|
||||
p = DisLineCode((struct DisBuilder){d, d->xedd, addr}, d->buf);
|
||||
CHECK_LT(p - d->buf, sizeof(d->buf));
|
||||
n = d->xedd->op.error ? 1 : d->xedd->length;
|
||||
DCHECK_GT(n, 0);
|
||||
} else {
|
||||
p = DisLineData((struct DisBuilder){d, d->xedd, addr}, d->buf, d->raw, n);
|
||||
CHECK_LT(p - d->buf, sizeof(d->buf));
|
||||
}
|
||||
DCHECK_LT(p, d->buf + sizeof(d->buf));
|
||||
DCHECK_LT(strlen(d->buf), sizeof(d->buf));
|
||||
op.addr = addr;
|
||||
op.unique = unique++;
|
||||
op.size = n;
|
||||
op.active = true;
|
||||
if (!(op.s = strdup(d->buf))) break;
|
||||
APPEND(&d->ops.p, &d->ops.i, &d->ops.n, &op);
|
||||
addr += n;
|
||||
n = 0;
|
||||
}
|
||||
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);
|
||||
p = DisLineCode((struct DisBuilder){d, d->xedd, d->ops.p[i].addr}, d->buf);
|
||||
CHECK_LT(p - d->buf, sizeof(d->buf));
|
||||
return d->buf;
|
||||
}
|
||||
|
||||
void DisFreeOp(struct DisOp *o) {
|
||||
|
|
|
@ -11,8 +11,7 @@ struct Dis {
|
|||
size_t i, n;
|
||||
struct DisOp {
|
||||
int64_t addr;
|
||||
int unique;
|
||||
int size;
|
||||
uint8_t size;
|
||||
bool active;
|
||||
char *s;
|
||||
} * p;
|
||||
|
@ -46,7 +45,6 @@ struct Dis {
|
|||
} * p;
|
||||
} edges;
|
||||
struct XedDecodedInst xedd[1];
|
||||
uint8_t raw[512];
|
||||
char buf[512];
|
||||
};
|
||||
|
||||
|
@ -66,8 +64,8 @@ struct DisHigh {
|
|||
|
||||
extern struct DisHigh *g_dis_high;
|
||||
|
||||
long Dis(struct Dis *, struct Machine *, int64_t, int);
|
||||
long DisFind(struct Dis *, int64_t);
|
||||
void Dis(struct Dis *, struct Machine *, int64_t);
|
||||
void DisFree(struct Dis *);
|
||||
void DisFreeOp(struct DisOp *);
|
||||
void DisFreeOps(struct DisOps *);
|
||||
|
@ -80,6 +78,7 @@ const char *DisSpec(struct XedDecodedInst *, char *);
|
|||
char *DisInst(struct DisBuilder, char *, const char *);
|
||||
char *DisArg(struct DisBuilder, char *, const char *);
|
||||
char *DisHigh(char *, int);
|
||||
const char *DisGetLine(struct Dis *, struct Machine *, size_t);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/conv/itoa.h"
|
||||
#include "libc/limits.h"
|
||||
|
@ -27,22 +28,15 @@
|
|||
#include "tool/build/lib/endian.h"
|
||||
#include "tool/build/lib/modrm.h"
|
||||
|
||||
#define SSTRCMP8(S1, S2) \
|
||||
({ \
|
||||
uint64_t x, y; \
|
||||
x = READ64BE(S1); \
|
||||
y = READ64BE(S2); \
|
||||
x > y ? 1 : x < y ? -1 : 0; \
|
||||
})
|
||||
|
||||
static const char kScale[4][4] = {"", ",2", ",4", ",8"};
|
||||
static const char kSegName[8][3] = {"es", "cs", "ss", "ds", "fs", "gs"};
|
||||
static const char kSegOverride[8][3] = {"", "cs", "ds", "es", "fs", "gs", "ss"};
|
||||
static const char kPuttingOnTheRiz[2][4] = {"eiz", "riz"};
|
||||
static const char kPuttingOnTheRip[2][4] = {"eip", "rip"};
|
||||
|
||||
static const char kRegisterName8[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"}},
|
||||
};
|
||||
|
||||
|
@ -57,12 +51,18 @@ static const char kRegisterName[2][2][2][8][5] = {
|
|||
{"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}}},
|
||||
};
|
||||
|
||||
static const char kControlName[8][4] = {
|
||||
"cr0", "wut", "cr2", "cr3", "cr4", "wut", "wut", "wut",
|
||||
};
|
||||
|
||||
static int64_t RipRelative(struct DisBuilder b, int64_t d) {
|
||||
return b.addr + b.xedd->length + d;
|
||||
}
|
||||
|
||||
static const char *GetAddrReg(struct DisBuilder b, uint8_t x, uint8_t r) {
|
||||
return kRegisterName[0][!Asz(b.xedd->op.rde)][x & 1][r & 7];
|
||||
static const char *GetAddrReg(struct DisBuilder b, uint32_t rde, uint8_t x,
|
||||
uint8_t r) {
|
||||
return kRegisterName[Eamode(rde) == XED_MODE_REAL]
|
||||
[Eamode(rde) == XED_MODE_LONG][x & 1][r & 7];
|
||||
}
|
||||
|
||||
static char *DisRegister(char *p, const char *s) {
|
||||
|
@ -73,13 +73,6 @@ static char *DisRegister(char *p, const char *s) {
|
|||
return p;
|
||||
}
|
||||
|
||||
static char *DisLiteral(char *p, const char *s) {
|
||||
if (g_dis_high) p = DisHigh(p, g_dis_high->literal);
|
||||
p = stpcpy(p, s);
|
||||
if (g_dis_high) p = DisHigh(p, -1);
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *DisComment(char *p, const char *s) {
|
||||
if (g_dis_high) p = DisHigh(p, g_dis_high->comment);
|
||||
p = stpcpy(p, s);
|
||||
|
@ -87,30 +80,14 @@ static char *DisComment(char *p, const char *s) {
|
|||
return p;
|
||||
}
|
||||
|
||||
static char *DisRegisterByte(struct DisBuilder b, char *p, bool g, int r) {
|
||||
return DisRegister(p, kRegisterName8[g][Rex(b.xedd->op.rde)][r]);
|
||||
static char *DisRegisterByte(struct DisBuilder b, uint32_t rde, char *p, bool g,
|
||||
int r) {
|
||||
return DisRegister(p, kRegisterName8[g][Rex(rde)][r]);
|
||||
}
|
||||
|
||||
static char *DisRegisterWord(struct DisBuilder b, char *p, bool g, int r) {
|
||||
return DisRegister(
|
||||
p, kRegisterName[Osz(b.xedd->op.rde)][Rexw(b.xedd->op.rde)][g][r]);
|
||||
}
|
||||
|
||||
static char *DisGvqp(struct DisBuilder b, char *p) {
|
||||
return DisRegisterWord(b, p, Rexr(b.xedd->op.rde), ModrmReg(b.xedd->op.rde));
|
||||
}
|
||||
|
||||
static char *DisGdqp(struct DisBuilder b, char *p) {
|
||||
return DisRegister(p, kRegisterName[0][Rexw(b.xedd->op.rde)][Rexr(
|
||||
b.xedd->op.rde)][ModrmReg(b.xedd->op.rde)]);
|
||||
}
|
||||
|
||||
static char *DisGb(struct DisBuilder b, char *p) {
|
||||
return DisRegisterByte(b, p, Rexr(b.xedd->op.rde), ModrmReg(b.xedd->op.rde));
|
||||
}
|
||||
|
||||
static uint8_t DisSeg(struct DisBuilder b) {
|
||||
return b.xedd->op.seg_ovd ? b.xedd->op.seg_ovd : b.xedd->op.hint;
|
||||
static char *DisRegisterWord(struct DisBuilder b, uint32_t rde, char *p, bool g,
|
||||
int r) {
|
||||
return DisRegister(p, kRegisterName[Osz(rde)][Rexw(rde)][g][r]);
|
||||
}
|
||||
|
||||
static char *DisInt(char *p, int64_t x) {
|
||||
|
@ -147,40 +124,113 @@ static char *DisSym(struct DisBuilder b, char *p, int64_t addr) {
|
|||
}
|
||||
}
|
||||
|
||||
static char *DisM(struct DisBuilder b, char *p) {
|
||||
int64_t disp;
|
||||
const char *seg, *base, *index, *scale;
|
||||
base = index = scale = NULL;
|
||||
seg = kSegOverride[b.xedd->op.seg_ovd ? b.xedd->op.seg_ovd : b.xedd->op.hint];
|
||||
if (*seg) {
|
||||
p = DisRegister(p, seg);
|
||||
static char *DisSymLiteral(struct DisBuilder b, char *p, uint64_t x) {
|
||||
*p++ = '$';
|
||||
if (g_dis_high) p = DisHigh(p, g_dis_high->literal);
|
||||
p = DisSym(b, p, x);
|
||||
if (g_dis_high) p = DisHigh(p, -1);
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *DisXmm(struct DisBuilder b, uint32_t rde, char *p, const char *s,
|
||||
int reg) {
|
||||
if (g_dis_high) p = DisHigh(p, g_dis_high->reg);
|
||||
*p++ = '%';
|
||||
p = stpcpy(p, s);
|
||||
p += uint64toarray_radix10(Rexr(rde) << 3 | reg, p);
|
||||
if (g_dis_high) p = DisHigh(p, -1);
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *DisGvqp(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
return DisRegisterWord(b, rde, p, Rexr(rde), ModrmReg(rde));
|
||||
}
|
||||
|
||||
static char *DisGdqp(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
return DisRegister(p, kRegisterName[0][Rexw(rde)][Rexr(rde)][ModrmReg(rde)]);
|
||||
}
|
||||
|
||||
static char *DisGb(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
return DisRegisterByte(b, rde, p, Rexr(rde), ModrmReg(rde));
|
||||
}
|
||||
|
||||
static char *DisSego(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
int seg;
|
||||
seg = Sego(rde) ? Sego(rde) : b.xedd->op.hint;
|
||||
if (seg) {
|
||||
p = DisRegister(p, kSegName[seg - 1]);
|
||||
*p++ = ':';
|
||||
}
|
||||
if (ModrmMod(b.xedd->op.rde) == 0b01 || ModrmMod(b.xedd->op.rde) == 0b10 ||
|
||||
IsRipRelative(b.xedd->op.rde) ||
|
||||
(ModrmMod(b.xedd->op.rde) == 0b00 && ModrmRm(b.xedd->op.rde) == 0b100 &&
|
||||
SibBase(b.xedd->op.rde) == 0b101)) {
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *DisM(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
int64_t disp;
|
||||
const char *base, *index, *scale;
|
||||
p = DisSego(b, rde, p);
|
||||
base = index = scale = NULL;
|
||||
if (ModrmMod(rde) == 0b01 || ModrmMod(rde) == 0b10 || IsRipRelative(rde) ||
|
||||
(Eamode(rde) == XED_MODE_REAL && ModrmRm(rde) == 6 && !ModrmMod(rde)) ||
|
||||
(ModrmMod(rde) == 0b00 && ModrmRm(rde) == 0b100 &&
|
||||
SibBase(b.xedd) == 0b101)) {
|
||||
disp = b.xedd->op.disp;
|
||||
if (IsRipRelative(b.xedd->op.rde)) disp = RipRelative(b, disp);
|
||||
if (IsRipRelative(rde)) disp = RipRelative(b, disp);
|
||||
p = DisSym(b, p, disp);
|
||||
}
|
||||
if (!SibExists(b.xedd->op.rde)) {
|
||||
DCHECK(!b.xedd->op.has_sib);
|
||||
if (IsRipRelative(b.xedd->op.rde)) {
|
||||
base = "rip";
|
||||
} else {
|
||||
base = GetAddrReg(b, Rexb(b.xedd->op.rde), ModrmRm(b.xedd->op.rde));
|
||||
if (Eamode(rde) != XED_MODE_REAL) {
|
||||
if (!SibExists(rde)) {
|
||||
DCHECK(!b.xedd->op.has_sib);
|
||||
if (IsRipRelative(rde)) {
|
||||
if (Mode(rde) == XED_MODE_LONG) {
|
||||
base = kPuttingOnTheRip[Eamode(rde) == XED_MODE_LONG];
|
||||
}
|
||||
} else {
|
||||
base = GetAddrReg(b, rde, Rexb(rde), ModrmRm(rde));
|
||||
}
|
||||
} else if (!SibIsAbsolute(b.xedd, rde)) {
|
||||
if (SibHasBase(b.xedd, rde)) {
|
||||
base = GetAddrReg(b, rde, Rexb(rde), SibBase(b.xedd));
|
||||
}
|
||||
if (SibHasIndex(b.xedd)) {
|
||||
index = GetAddrReg(b, rde, Rexx(b.xedd), SibIndex(b.xedd));
|
||||
} else if (b.xedd->op.scale) {
|
||||
index = kPuttingOnTheRiz[Eamode(rde) == XED_MODE_LONG];
|
||||
}
|
||||
scale = kScale[b.xedd->op.scale];
|
||||
}
|
||||
} else if (!SibIsAbsolute(b.xedd->op.rde)) {
|
||||
if (SibHasBase(b.xedd->op.rde)) {
|
||||
base = GetAddrReg(b, Rexb(b.xedd->op.rde), SibBase(b.xedd->op.rde));
|
||||
} 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:
|
||||
unreachable;
|
||||
}
|
||||
if (SibHasIndex(b.xedd->op.rde)) {
|
||||
index = GetAddrReg(b, Rexx(b.xedd->op.rde), SibIndex(b.xedd->op.rde));
|
||||
} else if (b.xedd->op.scale) {
|
||||
index = Asz(b.xedd->op.rde) ? "eiz" : "riz";
|
||||
}
|
||||
scale = kScale[b.xedd->op.scale];
|
||||
}
|
||||
if (base || index) {
|
||||
*p++ = '(';
|
||||
|
@ -190,7 +240,9 @@ static char *DisM(struct DisBuilder b, char *p) {
|
|||
if (index) {
|
||||
*p++ = ',';
|
||||
p = DisRegister(p, index);
|
||||
p = stpcpy(p, scale);
|
||||
if (scale) {
|
||||
p = stpcpy(p, scale);
|
||||
}
|
||||
}
|
||||
*p++ = ')';
|
||||
}
|
||||
|
@ -198,237 +250,245 @@ static char *DisM(struct DisBuilder b, char *p) {
|
|||
return p;
|
||||
}
|
||||
|
||||
static char *DisEb(struct DisBuilder b, char *p) {
|
||||
if (IsModrmRegister(b.xedd->op.rde)) {
|
||||
return DisRegisterByte(b, p, Rexb(b.xedd->op.rde), ModrmRm(b.xedd->op.rde));
|
||||
static char *DisEb(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
if (IsModrmRegister(rde)) {
|
||||
return DisRegisterByte(b, rde, p, Rexb(rde), ModrmRm(rde));
|
||||
} else {
|
||||
return DisM(b, p);
|
||||
return DisM(b, rde, p);
|
||||
}
|
||||
}
|
||||
|
||||
static char *DisEvqp(struct DisBuilder b, char *p) {
|
||||
if (IsModrmRegister(b.xedd->op.rde)) {
|
||||
return DisRegisterWord(b, p, Rexb(b.xedd->op.rde), ModrmRm(b.xedd->op.rde));
|
||||
static char *DisEvqp(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
if (IsModrmRegister(rde)) {
|
||||
return DisRegisterWord(b, rde, p, Rexb(rde), ModrmRm(rde));
|
||||
} else {
|
||||
return DisM(b, p);
|
||||
return DisM(b, rde, p);
|
||||
}
|
||||
}
|
||||
|
||||
static char *DisEdqp(struct DisBuilder b, char *p) {
|
||||
if (IsModrmRegister(b.xedd->op.rde)) {
|
||||
return DisRegister(p, kRegisterName[0][Rexw(b.xedd->op.rde)][Rexb(
|
||||
b.xedd->op.rde)][ModrmRm(b.xedd->op.rde)]);
|
||||
static char *DisEdqp(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
if (IsModrmRegister(rde)) {
|
||||
return DisRegister(p, kRegisterName[0][Rexw(rde)][Rexb(rde)][ModrmRm(rde)]);
|
||||
} else {
|
||||
return DisM(b, p);
|
||||
return DisM(b, rde, p);
|
||||
}
|
||||
}
|
||||
|
||||
static char *DisEvq(struct DisBuilder b, char *p) {
|
||||
static char *DisEv(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
const char *s;
|
||||
if (IsModrmRegister(b.xedd->op.rde)) {
|
||||
if (Osz(b.xedd->op.rde)) {
|
||||
s = kRegisterName[1][0][Rexb(b.xedd->op.rde)][ModrmRm(b.xedd->op.rde)];
|
||||
} else {
|
||||
s = kRegisterName[0][1][Rexb(b.xedd->op.rde)][ModrmRm(b.xedd->op.rde)];
|
||||
}
|
||||
return DisRegister(p, s);
|
||||
if (IsModrmRegister(rde)) {
|
||||
return DisRegister(p, kRegisterName[Osz(rde)][0][Rexb(rde)][ModrmRm(rde)]);
|
||||
} else {
|
||||
return DisM(b, p);
|
||||
return DisM(b, rde, p);
|
||||
}
|
||||
}
|
||||
|
||||
static char *DisEd(struct DisBuilder b, char *p) {
|
||||
if (IsModrmRegister(b.xedd->op.rde)) {
|
||||
return DisRegister(
|
||||
p, kRegisterName[0][0][Rexb(b.xedd->op.rde)][ModrmRm(b.xedd->op.rde)]);
|
||||
static char *DisGvq(struct DisBuilder b, uint32_t rde, char *p, int r) {
|
||||
const char *s;
|
||||
if (Mode(rde) == XED_MODE_LONG) {
|
||||
s = kRegisterName[Osz(rde)][!Osz(rde)][Rexb(rde)][r];
|
||||
} else {
|
||||
return DisM(b, p);
|
||||
s = kRegisterName[Osz(rde)][0][Rexb(rde)][r];
|
||||
}
|
||||
return DisRegister(p, s);
|
||||
}
|
||||
|
||||
static char *DisZvq(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
return DisGvq(b, rde, p, ModrmSrm(rde));
|
||||
}
|
||||
|
||||
static char *DisEvq(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
if (IsModrmRegister(rde)) {
|
||||
return DisGvq(b, rde, p, ModrmRm(rde));
|
||||
} else {
|
||||
return DisM(b, rde, p);
|
||||
}
|
||||
}
|
||||
|
||||
static char *DisEq(struct DisBuilder b, char *p) {
|
||||
if (IsModrmRegister(b.xedd->op.rde)) {
|
||||
return DisRegister(
|
||||
p, kRegisterName[0][1][Rexb(b.xedd->op.rde)][ModrmRm(b.xedd->op.rde)]);
|
||||
static char *DisEd(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
if (IsModrmRegister(rde)) {
|
||||
return DisRegister(p, kRegisterName[0][0][Rexb(rde)][ModrmRm(rde)]);
|
||||
} else {
|
||||
return DisM(b, p);
|
||||
return DisM(b, rde, p);
|
||||
}
|
||||
}
|
||||
|
||||
static char *DisZvq(struct DisBuilder b, char *p) {
|
||||
if (Osz(b.xedd->op.rde)) {
|
||||
return DisRegister(
|
||||
p, kRegisterName[1][0][Rexb(b.xedd->op.rde)][ModrmSrm(b.xedd->op.rde)]);
|
||||
static char *DisEq(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
if (IsModrmRegister(rde)) {
|
||||
return DisRegister(p, kRegisterName[0][1][Rexb(rde)][ModrmRm(rde)]);
|
||||
} else {
|
||||
return DisRegister(
|
||||
p, kRegisterName[0][1][Rexb(b.xedd->op.rde)][ModrmSrm(b.xedd->op.rde)]);
|
||||
return DisM(b, rde, p);
|
||||
}
|
||||
}
|
||||
|
||||
static char *DisZvqp(struct DisBuilder b, char *p) {
|
||||
return DisRegisterWord(b, p, Rexb(b.xedd->op.rde), ModrmSrm(b.xedd->op.rde));
|
||||
static char *DisZvqp(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
return DisRegisterWord(b, rde, p, Rexb(rde), ModrmSrm(rde));
|
||||
}
|
||||
|
||||
static char *DisZb(struct DisBuilder b, char *p) {
|
||||
return DisRegisterByte(b, p, Rexb(b.xedd->op.rde), ModrmSrm(b.xedd->op.rde));
|
||||
static char *DisZb(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
return DisRegisterByte(b, rde, p, Rexb(rde), ModrmSrm(rde));
|
||||
}
|
||||
|
||||
static char *DisEax(struct DisBuilder b, char *p) {
|
||||
return DisRegister(p, kRegisterName[Osz(b.xedd->op.rde)][0][0][0]);
|
||||
static char *DisEax(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
return DisRegister(p, kRegisterName[Osz(rde)][0][0][0]);
|
||||
}
|
||||
|
||||
static char *DisRax(struct DisBuilder b, char *p) {
|
||||
static char *DisRax(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
return DisRegister(p, kRegisterName[Osz(rde)][Rexw(rde)][0][0]);
|
||||
}
|
||||
|
||||
static char *DisRdx(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
return DisRegister(p, kRegisterName[Osz(rde)][Rexw(rde)][0][2]);
|
||||
}
|
||||
|
||||
static char *DisCd(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
return DisRegister(p, kControlName[ModrmReg(rde)]);
|
||||
}
|
||||
|
||||
static char *DisHd(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
return DisRegister(
|
||||
p, kRegisterName[Osz(b.xedd->op.rde)][Rexw(b.xedd->op.rde)][0][0]);
|
||||
p, kRegisterName[0][Mode(rde) == XED_MODE_LONG][0][ModrmRm(rde)]);
|
||||
}
|
||||
|
||||
static char *DisRdx(struct DisBuilder b, char *p) {
|
||||
return DisRegister(
|
||||
p, kRegisterName[Osz(b.xedd->op.rde)][Rexw(b.xedd->op.rde)][0][2]);
|
||||
static char *DisImm(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
return DisSymLiteral(b, p, b.xedd->op.uimm0);
|
||||
}
|
||||
|
||||
static char *DisImm(struct DisBuilder b, char *p) {
|
||||
static char *DisRvds(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
return DisSymLiteral(b, p, b.xedd->op.disp);
|
||||
}
|
||||
|
||||
static char *DisKvds(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
*p++ = '$';
|
||||
if (g_dis_high) p = DisHigh(p, g_dis_high->literal);
|
||||
p = DisSym(b, p, b.xedd->op.uimm0);
|
||||
p = DisInt(p, b.xedd->op.uimm0);
|
||||
if (g_dis_high) p = DisHigh(p, -1);
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *DisJbs(struct DisBuilder b, char *p) {
|
||||
static char *DisOne(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
*p++ = '$';
|
||||
if (g_dis_high) p = DisHigh(p, g_dis_high->literal);
|
||||
p = stpcpy(p, "1");
|
||||
if (g_dis_high) p = DisHigh(p, -1);
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *DisJbs(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
if (b.xedd->op.disp > 0) *p++ = '+';
|
||||
p += int64toarray_radix10(b.xedd->op.disp, p);
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *DisJb(struct DisBuilder b, char *p) {
|
||||
static char *DisJb(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
if (b.xedd->op.disp > 0) *p++ = '+';
|
||||
p += uint64toarray_radix10(b.xedd->op.disp & 0xff, p);
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *DisJvds(struct DisBuilder b, char *p) {
|
||||
static char *DisJvds(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
return DisSym(b, p, RipRelative(b, b.xedd->op.disp));
|
||||
}
|
||||
|
||||
static char *DisAbs(struct DisBuilder b, char *p) {
|
||||
static char *DisAbs(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
return DisSym(b, p, b.xedd->op.disp);
|
||||
}
|
||||
|
||||
static char *DisSw(struct DisBuilder b, char *p) {
|
||||
if (kSegName[ModrmReg(b.xedd->op.rde)][0]) {
|
||||
p = DisRegister(p, kSegName[ModrmReg(b.xedd->op.rde)]);
|
||||
}
|
||||
*p = '\0';
|
||||
static char *DisSw(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
if (kSegName[ModrmReg(rde)][0]) p = DisRegister(p, kSegName[ModrmReg(rde)]);
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *DisY(struct DisBuilder b, char *p) {
|
||||
static char *DisSpecialAddr(struct DisBuilder b, uint32_t rde, char *p, int r) {
|
||||
*p++ = '(';
|
||||
p = DisRegister(p, Asz(b.xedd->op.rde) ? "edi" : "rdi");
|
||||
p = DisRegister(p, GetAddrReg(b, rde, 0, r));
|
||||
*p++ = ')';
|
||||
*p = '\0';
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *DisX(struct DisBuilder b, char *p) {
|
||||
if (kSegOverride[b.xedd->op.seg_ovd][0]) {
|
||||
p = DisRegister(p, kSegOverride[b.xedd->op.seg_ovd]);
|
||||
}
|
||||
*p++ = '(';
|
||||
p = DisRegister(p, Asz(b.xedd->op.rde) ? "esi" : "rsi");
|
||||
*p++ = ')';
|
||||
*p = '\0';
|
||||
return p;
|
||||
static char *DisY(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
return DisSpecialAddr(b, rde, p, 7); // es:di
|
||||
}
|
||||
|
||||
static char *DisBBb(struct DisBuilder b, char *p) {
|
||||
if (kSegOverride[b.xedd->op.seg_ovd][0]) {
|
||||
p = DisRegister(p, kSegOverride[b.xedd->op.seg_ovd]);
|
||||
}
|
||||
*p++ = '(';
|
||||
p = DisRegister(p, Asz(b.xedd->op.rde) ? "ebx" : "rbx");
|
||||
*p++ = ')';
|
||||
*p = '\0';
|
||||
return p;
|
||||
static char *DisX(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
DisSego(b, rde, p);
|
||||
return DisSpecialAddr(b, rde, p, 6); // ds:si
|
||||
}
|
||||
|
||||
static char *DisXmm(struct DisBuilder b, char *p, const char *s, int reg) {
|
||||
if (g_dis_high) p = DisHigh(p, g_dis_high->reg);
|
||||
*p++ = '%';
|
||||
p = stpcpy(p, s);
|
||||
p += uint64toarray_radix10(Rexr(b.xedd->op.rde) << 3 | reg, p);
|
||||
if (g_dis_high) p = DisHigh(p, -1);
|
||||
return p;
|
||||
static char *DisBBb(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
DisSego(b, rde, p);
|
||||
return DisSpecialAddr(b, rde, p, 3); // ds:bx
|
||||
}
|
||||
|
||||
static char *DisNq(struct DisBuilder b, char *p) {
|
||||
return DisXmm(b, p, "mm", ModrmRm(b.xedd->op.rde));
|
||||
static char *DisNq(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
return DisXmm(b, rde, p, "mm", ModrmRm(rde));
|
||||
}
|
||||
|
||||
static char *DisUq(struct DisBuilder b, char *p) {
|
||||
return DisXmm(b, p, "mm", ModrmRm(b.xedd->op.rde));
|
||||
static char *DisUq(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
return DisXmm(b, rde, p, "mm", ModrmRm(rde));
|
||||
}
|
||||
|
||||
static char *DisPq(struct DisBuilder b, char *p) {
|
||||
return DisXmm(b, p, "mm", ModrmReg(b.xedd->op.rde));
|
||||
static char *DisPq(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
return DisXmm(b, rde, p, "mm", ModrmReg(rde));
|
||||
}
|
||||
|
||||
static char *DisUdq(struct DisBuilder b, char *p) {
|
||||
return DisXmm(b, p, "xmm", ModrmRm(b.xedd->op.rde));
|
||||
static char *DisUdq(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
return DisXmm(b, rde, p, "xmm", ModrmRm(rde));
|
||||
}
|
||||
|
||||
static char *DisVdq(struct DisBuilder b, char *p) {
|
||||
return DisXmm(b, p, "xmm", ModrmReg(b.xedd->op.rde));
|
||||
static char *DisVdq(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
return DisXmm(b, rde, p, "xmm", ModrmReg(rde));
|
||||
}
|
||||
|
||||
static char *DisQq(struct DisBuilder b, char *p) {
|
||||
if (IsModrmRegister(b.xedd->op.rde)) {
|
||||
return DisNq(b, p);
|
||||
static char *DisQq(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
if (IsModrmRegister(rde)) {
|
||||
return DisNq(b, rde, p);
|
||||
} else {
|
||||
return DisM(b, p);
|
||||
return DisM(b, rde, p);
|
||||
}
|
||||
}
|
||||
|
||||
static char *DisEst(struct DisBuilder b, char *p) {
|
||||
static char *DisEst(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
p = DisRegister(p, "st");
|
||||
if (ModrmRm(b.xedd->op.rde) != 0) {
|
||||
if (ModrmRm(rde) != 0) {
|
||||
*p++ = '(';
|
||||
*p++ = '0' + ModrmRm(b.xedd->op.rde);
|
||||
*p++ = '0' + ModrmRm(rde);
|
||||
*p++ = ')';
|
||||
*p = '\0';
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *DisEst1(struct DisBuilder b, char *p) {
|
||||
if (ModrmRm(b.xedd->op.rde) != 1) {
|
||||
p = DisEst(b, p);
|
||||
static char *DisEst1(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
if (ModrmRm(rde) != 1) {
|
||||
p = DisEst(b, rde, p);
|
||||
} else {
|
||||
*p = '\0';
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *DisEssr(struct DisBuilder b, char *p) {
|
||||
if (IsModrmRegister(b.xedd->op.rde)) {
|
||||
return DisEst(b, p);
|
||||
static char *DisEssr(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
if (IsModrmRegister(rde)) {
|
||||
return DisEst(b, rde, p);
|
||||
} else {
|
||||
return DisM(b, p);
|
||||
return DisM(b, rde, p);
|
||||
}
|
||||
}
|
||||
|
||||
static char *DisWps(struct DisBuilder b, char *p) {
|
||||
if (IsModrmRegister(b.xedd->op.rde)) {
|
||||
return DisUdq(b, p);
|
||||
static char *DisWps(struct DisBuilder b, uint32_t rde, char *p) {
|
||||
if (IsModrmRegister(rde)) {
|
||||
return DisUdq(b, rde, p);
|
||||
} else {
|
||||
return DisM(b, p);
|
||||
return DisM(b, rde, p);
|
||||
}
|
||||
}
|
||||
|
||||
#define DisEdr DisM
|
||||
#define DisEqp DisEq
|
||||
#define DisEsr DisM
|
||||
#define DisGv DisGvqp
|
||||
#define DisIb DisImm
|
||||
#define DisIbs DisImm
|
||||
#define DisIbss DisImm
|
||||
|
@ -442,9 +502,11 @@ static char *DisWps(struct DisBuilder b, char *p) {
|
|||
#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
|
||||
|
@ -471,14 +533,19 @@ static char *DisWps(struct DisBuilder b, char *p) {
|
|||
#define DisYb DisY
|
||||
#define DisYv DisY
|
||||
#define DisYvqp DisY
|
||||
#define DisZv DisZvqp
|
||||
|
||||
static const struct DisArg {
|
||||
char s[8];
|
||||
char *(*f)(struct DisBuilder, char *);
|
||||
char *(*f)(struct DisBuilder, 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}, //
|
||||
|
@ -494,6 +561,7 @@ static const struct DisArg {
|
|||
{"%Vsd", DisVsd}, //
|
||||
{"%Vss", DisVss}, //
|
||||
{"%Zb", DisZb}, //
|
||||
{"%Zv", DisZv}, //
|
||||
{"%Zvq", DisZvq}, //
|
||||
{"%Zvqp", DisZvqp}, //
|
||||
{"%eAX", DisEax}, //
|
||||
|
@ -510,7 +578,7 @@ static const struct DisArg {
|
|||
{"Eq", DisEq}, //
|
||||
{"Eqp", DisEqp}, //
|
||||
{"Esr", DisEsr}, //
|
||||
{"Ev", DisEvqp}, //
|
||||
{"Ev", DisEv}, //
|
||||
{"Evq", DisEvq}, //
|
||||
{"Evqp", DisEvqp}, //
|
||||
{"Ew", DisEvqp}, //
|
||||
|
@ -524,6 +592,7 @@ static const struct DisArg {
|
|||
{"Jb", DisJb}, //
|
||||
{"Jbs", DisJbs}, //
|
||||
{"Jvds", DisJvds}, //
|
||||
{"Kvds", DisKvds}, //
|
||||
{"M", DisM}, //
|
||||
{"Mdi", DisMdi}, //
|
||||
{"Mdq", DisMdq}, //
|
||||
|
@ -531,9 +600,11 @@ static const struct DisArg {
|
|||
{"Mdr", DisMdr}, //
|
||||
{"Me", DisMe}, //
|
||||
{"Mer", DisMer}, //
|
||||
{"Mp", DisMp}, //
|
||||
{"Mps", DisMps}, //
|
||||
{"Mq", DisMq}, //
|
||||
{"Mqi", DisMqi}, //
|
||||
{"Ms", DisMs}, //
|
||||
{"Msr", DisMsr}, //
|
||||
{"Mw", DisMw}, //
|
||||
{"Mwi", DisMwi}, //
|
||||
|
@ -541,6 +612,7 @@ static const struct DisArg {
|
|||
{"Ovqp", DisOvqp}, //
|
||||
{"Qpi", DisQpi}, //
|
||||
{"Qq", DisQq}, //
|
||||
{"Rvds", DisRvds}, //
|
||||
{"Wdq", DisWdq}, //
|
||||
{"Wpd", DisWpd}, //
|
||||
{"Wps", DisWps}, //
|
||||
|
@ -556,6 +628,13 @@ static const struct DisArg {
|
|||
{"Yvqp", DisYvqp}, //
|
||||
};
|
||||
|
||||
static int CompareString8(const char a[8], const char b[8]) {
|
||||
uint64_t x, y;
|
||||
x = READ64BE(a);
|
||||
y = READ64BE(b);
|
||||
return x > y ? 1 : x < y ? -1 : 0;
|
||||
}
|
||||
|
||||
char *DisArg(struct DisBuilder b, char *p, const char *s) {
|
||||
char key[8];
|
||||
int c, m, l, r;
|
||||
|
@ -564,13 +643,13 @@ char *DisArg(struct DisBuilder b, char *p, const char *s) {
|
|||
strncpy(key, s, 8);
|
||||
while (l <= r) {
|
||||
m = (l + r) >> 1;
|
||||
c = SSTRCMP8(kDisArgs[m].s, key);
|
||||
c = CompareString8(kDisArgs[m].s, key);
|
||||
if (c < 0) {
|
||||
l = m + 1;
|
||||
} else if (c > 0) {
|
||||
r = m - 1;
|
||||
} else {
|
||||
return kDisArgs[m].f(b, p);
|
||||
return kDisArgs[m].f(b, b.xedd->op.rde, p);
|
||||
}
|
||||
}
|
||||
if (*s == '%') {
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/elf/elf.h"
|
||||
#include "libc/elf/struct/sym.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/macros.h"
|
||||
#include "tool/build/lib/dis.h"
|
||||
|
||||
static int DisSymCompare(const struct DisSym *a, const struct DisSym *b) {
|
||||
|
@ -113,18 +114,29 @@ bool DisIsText(struct Dis *d, int64_t addr) {
|
|||
}
|
||||
|
||||
long DisFindSym(struct Dis *d, int64_t addr) {
|
||||
size_t i;
|
||||
size_t i, l, r, m, n;
|
||||
if (DisIsProg(d, addr)) {
|
||||
for (i = 0; i < d->syms.i; ++i) {
|
||||
if (addr == d->syms.p[i].addr) return i;
|
||||
l = 0;
|
||||
r = d->syms.i;
|
||||
while (l < r) {
|
||||
m = (l + r) >> 1;
|
||||
if (d->syms.p[m].addr < addr) {
|
||||
l = m + 1;
|
||||
} else {
|
||||
r = m;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < d->syms.i; ++i) {
|
||||
if (d->syms.p[l].addr == addr) {
|
||||
return l;
|
||||
}
|
||||
l = MAX(0, (long)l - 10);
|
||||
for (n = 0, i = l; i < d->syms.i && n < 20; ++i, ++n) {
|
||||
if (addr >= d->syms.p[i].addr &&
|
||||
addr < d->syms.p[i].addr + d->syms.p[i].size) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < d->syms.i; ++i) {
|
||||
for (n = 0, i = l; i < d->syms.i && n < 20; ++i, ++n) {
|
||||
if (addr >= d->syms.p[i].addr &&
|
||||
(i + 1 == d->syms.i || addr < d->syms.p[i + 1].addr)) {
|
||||
return i;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "tool/build/lib/dis.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",
|
||||
|
@ -33,7 +34,7 @@ static bool IsProbablyByteOp(struct XedDecodedInst *x) {
|
|||
}
|
||||
|
||||
static int IsRepOpcode(struct DisBuilder b) {
|
||||
switch (b.xedd->op.opcode & ~1u) {
|
||||
switch (b.xedd->op.opcode & ~1) {
|
||||
case 0x6C: /* INS */
|
||||
return 1;
|
||||
case 0x6E: /* OUTS */
|
||||
|
@ -86,35 +87,36 @@ static char *DisBranchTaken(struct DisBuilder b, char *p) {
|
|||
static char *DisName(struct DisBuilder b, char *bp, const char *name,
|
||||
bool ambiguous) {
|
||||
char *p, *np;
|
||||
uint32_t rde;
|
||||
bool notbyte, notlong, wantsuffix, wantsuffixsd;
|
||||
p = bp;
|
||||
rde = b.xedd->op.rde;
|
||||
if (b.xedd->op.lock) p = stpcpy(p, "lock ");
|
||||
p = DisRepPrefix(b, p);
|
||||
if (tinystrcmp(name, "BIT") == 0) {
|
||||
p = stpcpy(p, kBitOp[ModrmReg(b.xedd->op.rde)]);
|
||||
p = stpcpy(p, kBitOp[ModrmReg(rde)]);
|
||||
} else if (tinystrcmp(name, "CALL") == 0) {
|
||||
p = stpcpy(p, "call");
|
||||
} else if (tinystrcmp(name, "JMP") == 0) {
|
||||
p = stpcpy(p, "jmp");
|
||||
} else if (tinystrcmp(name, "jcxz") == 0) {
|
||||
p = stpcpy(p, Asz(b.xedd->op.rde) ? "jecxz" : "jrcxz");
|
||||
p = stpcpy(p, kJcxz[Eamode(rde)]);
|
||||
p = DisBranchTaken(b, p);
|
||||
} else if (tinystrcmp(name, "loop") == 0) {
|
||||
p = stpcpy(p, Asz(b.xedd->op.rde) ? "loopl" : "loop");
|
||||
p = DisBranchTaken(b, p);
|
||||
} else if (tinystrcmp(name, "loope") == 0) {
|
||||
p = stpcpy(p, Asz(b.xedd->op.rde) ? "loopel" : "loope");
|
||||
p = DisBranchTaken(b, p);
|
||||
} else if (tinystrcmp(name, "loopne") == 0) {
|
||||
p = stpcpy(p, Asz(b.xedd->op.rde) ? "loopnel" : "loopne");
|
||||
} else if (tinystrcmp(name, "loop") == 0 || tinystrcmp(name, "loope") == 0 ||
|
||||
tinystrcmp(name, "loopne") == 0) {
|
||||
p = stpcpy(p, name);
|
||||
if (Eamode(rde) != Mode(rde)) {
|
||||
*p++ = "wl"[Eamode(rde)];
|
||||
*p = '\0';
|
||||
}
|
||||
p = DisBranchTaken(b, p);
|
||||
} else if (tinystrcmp(name, "cwtl") == 0) {
|
||||
if (Osz(b.xedd->op.rde)) name = "cbtw";
|
||||
if (Rexw(b.xedd->op.rde)) name = "cltq";
|
||||
if (Osz(rde)) name = "cbtw";
|
||||
if (Rexw(rde)) name = "cltq";
|
||||
p = stpcpy(p, name);
|
||||
} else if (tinystrcmp(name, "cltd") == 0) {
|
||||
if (Osz(b.xedd->op.rde)) name = "cwtd";
|
||||
if (Rexw(b.xedd->op.rde)) name = "cqto";
|
||||
if (Osz(rde)) name = "cwtd";
|
||||
if (Rexw(rde)) name = "cqto";
|
||||
p = stpcpy(p, name);
|
||||
} else {
|
||||
notbyte = false;
|
||||
|
@ -125,13 +127,13 @@ static char *DisName(struct DisBuilder b, char *bp, const char *name,
|
|||
*p++ = *np;
|
||||
}
|
||||
if (tinystrcmp(name, "ALU") == 0) {
|
||||
p = stpcpy(p, kAluOp[ModrmReg(b.xedd->op.rde)]);
|
||||
p = stpcpy(p, kAluOp[ModrmReg(rde)]);
|
||||
} else if (tinystrcmp(np, "WLQ") == 0) {
|
||||
notbyte = true;
|
||||
wantsuffix = true;
|
||||
} else if (tinystrcmp(np, "WQ") == 0) {
|
||||
notbyte = true;
|
||||
notlong = true;
|
||||
notlong = Eamode(rde) != XED_MODE_REAL;
|
||||
wantsuffix = true;
|
||||
} else if (tinystrcmp(np, "LQ") == 0 || tinystrcmp(np, "WL") == 0) {
|
||||
notbyte = true;
|
||||
|
@ -140,21 +142,23 @@ static char *DisName(struct DisBuilder b, char *bp, const char *name,
|
|||
notbyte = true;
|
||||
wantsuffixsd = true;
|
||||
} else if (tinystrcmp(np, "ABS") == 0) {
|
||||
if (Rexw(b.xedd->op.rde)) p = stpcpy(p, "abs");
|
||||
if (Rexw(rde)) p = stpcpy(p, "abs");
|
||||
} else if (tinystrcmp(np, "BT") == 0) {
|
||||
p = DisBranchTaken(b, p);
|
||||
}
|
||||
if (wantsuffixsd) {
|
||||
if (Osz(b.xedd->op.rde)) {
|
||||
if (Osz(rde)) {
|
||||
*p++ = 'd';
|
||||
} else {
|
||||
*p++ = 's';
|
||||
}
|
||||
} else if (wantsuffix || (ambiguous && !startswith(name, "f") &&
|
||||
!startswith(name, "set"))) {
|
||||
if (Osz(b.xedd->op.rde)) {
|
||||
*p++ = 'w';
|
||||
} else if (Rexw(b.xedd->op.rde)) {
|
||||
if (Osz(rde)) {
|
||||
if (Eamode(rde) != XED_MODE_REAL) {
|
||||
*p++ = 'w';
|
||||
}
|
||||
} else if (Rexw(rde)) {
|
||||
*p++ = 'q';
|
||||
} else if (ambiguous && !notbyte && IsProbablyByteOp(b.xedd)) {
|
||||
*p++ = 'b';
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
static const char kFpuName[][8][8] = {
|
||||
{"fadd", "fmul", "fcom", "fcomp", "fsub", "fsubr", "fdiv", "fdivr"},
|
||||
{"fchs", "fabs", "ftst", "fxam"},
|
||||
{"fchs", "fabs", UNKNOWN, UNKNOWN, "ftst", "fxam", UNKNOWN, UNKNOWN},
|
||||
{"fld1", "fldl2t", "fldl2e", "fldpi", "fldlg2", "fldln2", "fldz"},
|
||||
{"f2xm1", "fyl2x", "fptan", "fpatan", "fxtract", "fprem1", "fdecstp",
|
||||
"fincstp"},
|
||||
|
@ -90,15 +90,6 @@ char *DisOpVpsWpsVssWssVpdWpdVsdWsd(struct XedDecodedInst *x, char *p,
|
|||
|
||||
const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
|
||||
switch (x->op.opcode & 0xff) {
|
||||
RCASE(0x2F, "das");
|
||||
RCASE(0x37, "aaa");
|
||||
RCASE(0x3F, "aas");
|
||||
RCASE(0xD6, "salc");
|
||||
RCASE(0x61, "popa");
|
||||
RCASE(0x60, "pusha");
|
||||
RCASE(0x62, "bound");
|
||||
RCASE(0xD4, "aam Ib");
|
||||
RCASE(0xD5, "aad Ib");
|
||||
RCASE(0x00, "add Eb %Gb");
|
||||
RCASE(0x01, "add Evqp %Gvqp");
|
||||
RCASE(0x02, "add %Gb Eb");
|
||||
|
@ -141,6 +132,7 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
|
|||
RCASE(0x27, "pop %es");
|
||||
RCASE(0x28, "sub Eb %Gb");
|
||||
RCASE(0x29, "sub Evqp %Gvqp");
|
||||
RCASE(0x2F, "das");
|
||||
RCASE(0x2a, "sub %Gb Eb");
|
||||
RCASE(0x2b, "sub %Gvqp Evqp");
|
||||
RCASE(0x2c, "sub %al Ib");
|
||||
|
@ -151,14 +143,21 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
|
|||
RCASE(0x33, "xor %Gvqp Evqp");
|
||||
RCASE(0x34, "xor %al Ib");
|
||||
RCASE(0x35, "xor %rAX Ivds");
|
||||
RCASE(0x37, "aaa");
|
||||
RCASE(0x38, "cmp Eb %Gb");
|
||||
RCASE(0x39, "cmp Evqp %Gvqp");
|
||||
RCASE(0x3A, "cmp %Gb Eb");
|
||||
RCASE(0x3B, "cmp %Gvqp Evqp");
|
||||
RCASE(0x3C, "cmp %al Ib");
|
||||
RCASE(0x3D, "cmp %rAX Ivds");
|
||||
RCASE(0x50 ... 0x57, "pushWQ %Zvq");
|
||||
RCASE(0x58 ... 0x5f, "popWQ %Zvq");
|
||||
RCASE(0x3F, "aas");
|
||||
RCASE(0x40 ... 0x47, "inc %Zv");
|
||||
RCASE(0x48 ... 0x4f, "dec %Zv");
|
||||
RCASE(0x50 ... 0x57, "push %Zvq");
|
||||
RCASE(0x58 ... 0x5f, "pop %Zvq");
|
||||
RCASE(0x60, "pusha");
|
||||
RCASE(0x61, "popa");
|
||||
RCASE(0x62, "bound");
|
||||
RCASE(0x63, "movslLQ %Gdqp Ed");
|
||||
RCASE(0x68, "pushWQ Ivs");
|
||||
RCASE(0x69, "imul %Gvqp Evqp Ivds");
|
||||
|
@ -230,6 +229,8 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
|
|||
RCASE(0xC1, "BIT Evqp Ib");
|
||||
RCASE(0xC2, "ret Iw");
|
||||
RCASE(0xC3, "ret");
|
||||
RCASE(0xC4, "les %Gv Mp");
|
||||
RCASE(0xC5, "lds %Gv Mp");
|
||||
RCASE(0xC6, "mov Eb Ib");
|
||||
RCASE(0xC7, "mov Evqp Ivds");
|
||||
RCASE(0xC9, "leave");
|
||||
|
@ -239,6 +240,9 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
|
|||
RCASE(0xD1, "BIT Evqp $1");
|
||||
RCASE(0xD2, "BIT Evqp %cl");
|
||||
RCASE(0xD3, "BIT Evqp %cl");
|
||||
RCASE(0xD4, x->op.uimm0 == 0x0a ? "aam" : "aam Ib");
|
||||
RCASE(0xD5, x->op.uimm0 == 0x0a ? "aad" : "aad Ib");
|
||||
RCASE(0xD6, "salc");
|
||||
RCASE(0xD7, "xlat BBb");
|
||||
RCASE(0xE0, "loopne Jbs");
|
||||
RCASE(0xE1, "loope Jbs");
|
||||
|
@ -250,6 +254,7 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
|
|||
RCASE(0xE7, "out Ib %eAX");
|
||||
RCASE(0xE8, "call Jvds");
|
||||
RCASE(0xE9, "jmp Jvds");
|
||||
RCASE(0xEA, "ljmp Rvds Kvds");
|
||||
RCASE(0xEB, "jmp Jbs");
|
||||
RCASE(0xEC, "in %al %dx");
|
||||
RCASE(0xED, "in %eAX %dx");
|
||||
|
@ -577,6 +582,8 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
|
|||
RCASE(0x1B, "nop Ev");
|
||||
RCASE(0x1C, "nop Ev");
|
||||
RCASE(0x1D, "nop Ev");
|
||||
RCASE(0x20, "mov %Hd %Cd");
|
||||
RCASE(0x22, "mov %Cd %Hd");
|
||||
RCASE(0x28, "movapSD %Vps Wps");
|
||||
RCASE(0x29, "movapSD Wps %Vps");
|
||||
RCASE(0x2B, "movntpSD Mps %Vps");
|
||||
|
@ -732,8 +739,21 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
|
|||
RCASE(0xFD, DisOpPqQqVdqWdq(x, p, "paddw"));
|
||||
RCASE(0xFE, DisOpPqQqVdqWdq(x, p, "paddd"));
|
||||
RCASE(0xFF, "ud0 %Gvqp Evqp");
|
||||
case 0x01:
|
||||
if (ModrmMod(x->op.rde) == 0b11 && ModrmReg(x->op.rde) == 0b111 &&
|
||||
ModrmRm(x->op.rde) == 0b001) {
|
||||
return "rdtscp";
|
||||
} else if (!IsModrmRegister(x->op.rde) && ModrmReg(x->op.rde) == 0) {
|
||||
return "sgdt Ms";
|
||||
} else if (!IsModrmRegister(x->op.rde) && ModrmReg(x->op.rde) == 2) {
|
||||
return "lgdt Ms";
|
||||
} else {
|
||||
return UNKNOWN;
|
||||
}
|
||||
break;
|
||||
case 0x1F:
|
||||
if (x->op.modrm == 0x45) {
|
||||
if (ModrmMod(x->op.rde) == 1 && ModrmReg(x->op.rde) == 0 &&
|
||||
ModrmRm(x->op.rde) == 0b101) {
|
||||
return "bofram Jb";
|
||||
} else {
|
||||
return "nop Ev";
|
||||
|
@ -779,7 +799,7 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
|
|||
RCASE(5, "lfence");
|
||||
RCASE(6, "mfence");
|
||||
case 7:
|
||||
if (0xf8 <= x->op.modrm && x->op.modrm <= 0xff) {
|
||||
if (ModrmMod(x->op.rde) == 0b11 && ModrmReg(x->op.rde) == 0b111) {
|
||||
return "sfence";
|
||||
} else {
|
||||
return "clflush";
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/arraylist.h"
|
||||
#include "libc/alg/arraylist2.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
|
@ -48,7 +49,7 @@ static const Elf64_Ehdr kObjHeader = {
|
|||
static size_t AppendSection(struct ElfWriter *elf, const char *name,
|
||||
int sh_type, int sh_flags) {
|
||||
ssize_t section =
|
||||
append(elf->shdrs,
|
||||
APPEND(&elf->shdrs->p, &elf->shdrs->i, &elf->shdrs->n,
|
||||
(&(Elf64_Shdr){.sh_type = sh_type,
|
||||
.sh_flags = sh_flags,
|
||||
.sh_entsize = elf->entsize,
|
||||
|
@ -72,12 +73,13 @@ static struct ElfWriterSymRef AppendSymbol(struct ElfWriter *elf,
|
|||
size_t st_size, size_t st_shndx,
|
||||
enum ElfWriterSymOrder slg) {
|
||||
ssize_t sym =
|
||||
append(elf->syms[slg], (&(Elf64_Sym){.st_info = st_info,
|
||||
.st_size = st_size,
|
||||
.st_value = st_value,
|
||||
.st_other = st_other,
|
||||
.st_name = intern(elf->strtab, name),
|
||||
.st_shndx = st_shndx}));
|
||||
APPEND(&elf->syms[slg]->p, &elf->syms[slg]->i, &elf->syms[slg]->n,
|
||||
(&(Elf64_Sym){.st_info = st_info,
|
||||
.st_size = st_size,
|
||||
.st_value = st_value,
|
||||
.st_other = st_other,
|
||||
.st_name = intern(elf->strtab, name),
|
||||
.st_shndx = st_shndx}));
|
||||
CHECK_NE(-1, sym);
|
||||
return (struct ElfWriterSymRef){.slg = slg, .sym = sym};
|
||||
}
|
||||
|
@ -147,7 +149,7 @@ static void FlushTables(struct ElfWriter *elf) {
|
|||
elf->ehdr->e_shstrndx = FlushStrtab(elf, ".shstrtab", elf->shstrtab);
|
||||
WriteRelaSections(elf, symtab);
|
||||
size = elf->shdrs->i * sizeof(elf->shdrs->p[0]);
|
||||
elfwriter_align(elf, alignof(elf->shdrs->p[0]), sizeof(elf->shdrs->p[0]));
|
||||
elfwriter_align(elf, alignof(Elf64_Shdr), sizeof(elf->shdrs->p[0]));
|
||||
elf->ehdr->e_shoff = elf->wrote;
|
||||
elf->ehdr->e_shnum = elf->shdrs->i;
|
||||
elf->shdrs->p[symtab].sh_info =
|
||||
|
@ -251,9 +253,9 @@ struct ElfWriterSymRef elfwriter_linksym(struct ElfWriter *elf,
|
|||
void elfwriter_appendrela(struct ElfWriter *elf, uint64_t r_offset,
|
||||
struct ElfWriterSymRef symkey, uint32_t type,
|
||||
int64_t r_addend) {
|
||||
CHECK_NE(-1,
|
||||
append(elf->relas, (&(struct ElfWriterRela){.type = type,
|
||||
.symkey = symkey,
|
||||
.offset = r_offset,
|
||||
.addend = r_addend})));
|
||||
CHECK_NE(-1, APPEND(&elf->relas->p, &elf->relas->i, &elf->relas->n,
|
||||
(&(struct ElfWriterRela){.type = type,
|
||||
.symkey = symkey,
|
||||
.offset = r_offset,
|
||||
.addend = r_addend})));
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ struct MachineFds {
|
|||
int (*close)(int);
|
||||
ssize_t (*read)(int, void *, size_t);
|
||||
ssize_t (*write)(int, const void *, size_t);
|
||||
int (*ioctl)(int, uint64_t, void *);
|
||||
} * cb;
|
||||
} * p;
|
||||
struct MachineFdClosed {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#define FLAGS_ID 21
|
||||
|
||||
#define GetLazyParityBool(f) GetParity((f) >> 24)
|
||||
#define SetLazyParityByte(f, x) (((f) & ~0xFF000000u) | ((x)&0xFF) << 24)
|
||||
#define SetLazyParityByte(f, x) (((f) & ~0xFF000000u) | ((x)&0xFFu) << 24)
|
||||
|
||||
#define GetParity(WORD) \
|
||||
({ \
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include "tool/build/lib/modrm.h"
|
||||
#include "tool/build/lib/throw.h"
|
||||
#include "tool/build/lib/word.h"
|
||||
#include "tool/build/lib/x87.h"
|
||||
|
||||
#define FPUREG 0
|
||||
#define MEMORY 1
|
||||
|
@ -153,6 +152,57 @@ static void FpuSetMemoryLdbl(struct Machine *m, long double f) {
|
|||
SetMemoryLdbl(m, m->fpu.dp, f);
|
||||
}
|
||||
|
||||
static long ltruncl(long double x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
static int ClearC2(int sw) {
|
||||
return sw & ~FPU_C2;
|
||||
}
|
||||
|
||||
static long double f2xm1(long double x) {
|
||||
return exp2l(x) - 1;
|
||||
}
|
||||
|
||||
static long double fyl2x(long double x, long double y) {
|
||||
return y * log2l(x);
|
||||
}
|
||||
|
||||
static long double fyl2xp1(long double x, long double y) {
|
||||
return y * log2l(x + 1);
|
||||
}
|
||||
|
||||
static long double fscale(long double significand, long double exponent) {
|
||||
return scalbl(significand, exponent);
|
||||
}
|
||||
|
||||
static long double x87remainder(long double x, long double y, uint32_t *sw,
|
||||
long double rem(long double, long double),
|
||||
long rnd(long double)) {
|
||||
int s;
|
||||
long q;
|
||||
long double r;
|
||||
s = 0;
|
||||
r = rem(x, y);
|
||||
q = rnd(x / y);
|
||||
s &= ~FPU_C2; /* ty libm */
|
||||
if (q & 0b001) s |= FPU_C1;
|
||||
if (q & 0b010) s |= FPU_C3;
|
||||
if (q & 0b100) s |= FPU_C0;
|
||||
if (sw) *sw = s | (*sw & ~(FPU_C0 | FPU_C1 | FPU_C2 | FPU_C3));
|
||||
return r;
|
||||
}
|
||||
|
||||
static long double fprem(long double dividend, long double modulus,
|
||||
uint32_t *sw) {
|
||||
return x87remainder(dividend, modulus, sw, fmodl, ltruncl);
|
||||
}
|
||||
|
||||
static long double fprem1(long double dividend, long double modulus,
|
||||
uint32_t *sw) {
|
||||
return x87remainder(dividend, modulus, sw, remainderl, lrintl);
|
||||
}
|
||||
|
||||
static long double FpuAdd(struct Machine *m, long double x, long double y) {
|
||||
if (!isunordered(x, y)) {
|
||||
switch (isinf(y) << 1 | isinf(x)) {
|
||||
|
@ -263,7 +313,7 @@ static void FpuCompare(struct Machine *m, long double y) {
|
|||
}
|
||||
}
|
||||
|
||||
void OpFxam(struct Machine *m) {
|
||||
static void OpFxam(struct Machine *m) {
|
||||
long double x;
|
||||
x = *FpuSt(m, 0);
|
||||
m->fpu.c1 = !!signbit(x);
|
||||
|
@ -741,7 +791,7 @@ static void OpFldConstant(struct Machine *m) {
|
|||
x = fldz();
|
||||
break;
|
||||
default:
|
||||
OpUd(m);
|
||||
OpUd(m, m->xedd->op.rde);
|
||||
}
|
||||
FpuPush(m, x);
|
||||
}
|
||||
|
@ -844,7 +894,7 @@ static void OpFfree(struct Machine *m) {
|
|||
}
|
||||
|
||||
static void OpFfreep(struct Machine *m) {
|
||||
OpFfree(m);
|
||||
if (ModrmRm(m->xedd->op.rde)) OpFfree(m);
|
||||
FpuPop(m);
|
||||
}
|
||||
|
||||
|
@ -932,7 +982,7 @@ void OpFinit(struct Machine *m) {
|
|||
m->fpu.tw = -1;
|
||||
}
|
||||
|
||||
void OpFwait(struct Machine *m) {
|
||||
void OpFwait(struct Machine *m, uint32_t rde) {
|
||||
if ((m->fpu.ie & !m->fpu.im) | (m->fpu.de & !m->fpu.dm) |
|
||||
(m->fpu.ze & !m->fpu.zm) | (m->fpu.oe & !m->fpu.om) |
|
||||
(m->fpu.ue & !m->fpu.um) | (m->fpu.pe & !m->fpu.pm) |
|
||||
|
@ -986,15 +1036,15 @@ long double FpuPop(struct Machine *m) {
|
|||
return x;
|
||||
}
|
||||
|
||||
void OpFpu(struct Machine *m) {
|
||||
void OpFpu(struct Machine *m, uint32_t rde) {
|
||||
unsigned op;
|
||||
bool ismemory;
|
||||
op = m->xedd->op.opcode & 0b111;
|
||||
ismemory = ModrmMod(m->xedd->op.rde) != 0b11;
|
||||
ismemory = ModrmMod(rde) != 0b11;
|
||||
m->fpu.ip = m->ip - m->xedd->length;
|
||||
m->fpu.op = op << 8 | m->xedd->op.modrm;
|
||||
m->fpu.dp = ismemory ? ComputeAddress(m, m->xedd->op.rde) : 0;
|
||||
switch (DISP(op, ismemory, m->xedd->op.reg)) {
|
||||
m->fpu.op = op << 8 | ModrmMod(rde) << 6 | ModrmReg(rde) << 3 | ModrmRm(rde);
|
||||
m->fpu.dp = ismemory ? ComputeAddress(m, rde) : 0;
|
||||
switch (DISP(op, ismemory, ModrmReg(rde))) {
|
||||
CASE(DISP(0xD8, FPUREG, 0), OpFaddStEst(m));
|
||||
CASE(DISP(0xD8, FPUREG, 1), OpFmulStEst(m));
|
||||
CASE(DISP(0xD8, FPUREG, 2), OpFcom(m));
|
||||
|
@ -1106,17 +1156,17 @@ void OpFpu(struct Machine *m) {
|
|||
CASE(DISP(0xDF, MEMORY, 5), OpFildll(m));
|
||||
CASE(DISP(0xDF, MEMORY, 7), OpFistpll(m));
|
||||
case DISP(0xD9, FPUREG, 4):
|
||||
switch (ModrmRm(m->xedd->op.rde)) {
|
||||
switch (ModrmRm(rde)) {
|
||||
CASE(0, OpFchs(m));
|
||||
CASE(1, OpFabs(m));
|
||||
CASE(4, OpFtst(m));
|
||||
CASE(5, OpFxam(m));
|
||||
default:
|
||||
OpUd(m);
|
||||
OpUd(m, rde);
|
||||
}
|
||||
break;
|
||||
case DISP(0xD9, FPUREG, 6):
|
||||
switch (ModrmRm(m->xedd->op.rde)) {
|
||||
switch (ModrmRm(rde)) {
|
||||
CASE(0, OpF2xm1(m));
|
||||
CASE(1, OpFyl2x(m));
|
||||
CASE(2, OpFptan(m));
|
||||
|
@ -1130,7 +1180,7 @@ void OpFpu(struct Machine *m) {
|
|||
}
|
||||
break;
|
||||
case DISP(0xD9, FPUREG, 7):
|
||||
switch (ModrmRm(m->xedd->op.rde)) {
|
||||
switch (ModrmRm(rde)) {
|
||||
CASE(0, OpFprem(m));
|
||||
CASE(1, OpFyl2xp1(m));
|
||||
CASE(2, OpFsqrt(m));
|
||||
|
@ -1144,14 +1194,14 @@ void OpFpu(struct Machine *m) {
|
|||
}
|
||||
break;
|
||||
case DISP(0xDb, FPUREG, 4):
|
||||
switch (ModrmRm(m->xedd->op.rde)) {
|
||||
switch (ModrmRm(rde)) {
|
||||
CASE(2, OpFnclex(m));
|
||||
CASE(3, OpFinit(m));
|
||||
default:
|
||||
OpUd(m);
|
||||
OpUd(m, rde);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
OpUd(m);
|
||||
OpUd(m, rde);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
void OpFpu(struct Machine *);
|
||||
void OpFpu(struct Machine *, uint32_t);
|
||||
void OpFinit(struct Machine *);
|
||||
void OpFwait(struct Machine *);
|
||||
void OpFwait(struct Machine *, uint32_t);
|
||||
void FpuPush(struct Machine *, long double);
|
||||
long double FpuPop(struct Machine *);
|
||||
long double *FpuSt(struct Machine *, unsigned);
|
||||
|
|
|
@ -19,31 +19,5 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "tool/build/lib/machine.h"
|
||||
|
||||
static void InitRegisterBytePointers(struct Machine *m) {
|
||||
unsigned i, j, k;
|
||||
for (i = 0; i < 2; ++i) {
|
||||
for (j = 0; j < 2; ++j) {
|
||||
for (k = 0; k < 8; ++k) {
|
||||
if (i) {
|
||||
m->beg[i << 4 | j << 3 | k] = m->reg[j << 3 | k];
|
||||
} else {
|
||||
m->beg[i << 4 | j << 3 | k] = &m->reg[k & 0b11][(k & 0b100) >> 2];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void InitRegisterXmmPointers(struct Machine *m) {
|
||||
unsigned i, j;
|
||||
for (i = 0; i < 2; ++i) {
|
||||
for (j = 0; j < 8; ++j) {
|
||||
m->veg[i << 3 | j] = m->xmm[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InitMachine(struct Machine *m) {
|
||||
InitRegisterBytePointers(m);
|
||||
InitRegisterXmmPointers(m);
|
||||
}
|
||||
|
|
|
@ -18,64 +18,66 @@
|
|||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
#include "libc/nexgen32e/bsf.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/stats.h"
|
||||
#include "tool/build/lib/throw.h"
|
||||
|
||||
static bool IsOpcodeEqual(uint8_t *a, uint8_t b[16], size_t size) {
|
||||
unsigned i;
|
||||
if (size) {
|
||||
i = 0;
|
||||
do {
|
||||
if (a[i] != b[i]) {
|
||||
return false;
|
||||
}
|
||||
} while (++i < size);
|
||||
return true;
|
||||
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)) {
|
||||
memcpy(m->xedd, xedd, sizeof(m->icache[0]));
|
||||
} else {
|
||||
HaltMachine(m, kMachineDecodeError);
|
||||
}
|
||||
}
|
||||
|
||||
void LoadInstruction(struct Machine *m) {
|
||||
unsigned i;
|
||||
enum XedError err;
|
||||
uint64_t ip;
|
||||
unsigned i, key;
|
||||
uint8_t *addr, *toil, copy[15];
|
||||
if ((i = 0x1000 - (m->ip & 0xfff)) >= 15) {
|
||||
if (ROUNDDOWN(m->ip, 0x1000) == m->codevirt && m->ip) {
|
||||
addr = m->codereal + (m->ip & 0xfff);
|
||||
ip = Read64(m->cs) + MaskAddress(m->mode & 3, m->ip);
|
||||
key = ip & (ARRAYLEN(m->icache) - 1);
|
||||
m->xedd = (struct XedDecodedInst *)m->icache[key];
|
||||
if ((i = 0x1000 - (ip & 0xfff)) >= 15) {
|
||||
if (ROUNDDOWN(ip, 0x1000) == m->codevirt && ip) {
|
||||
addr = m->codereal + (ip & 0xfff);
|
||||
} else {
|
||||
m->codevirt = ROUNDDOWN(m->ip, 0x1000);
|
||||
m->codevirt = ROUNDDOWN(ip, 0x1000);
|
||||
m->codereal = ResolveAddress(m, m->codevirt);
|
||||
addr = m->codereal + (m->ip & 0xfff);
|
||||
addr = m->codereal + (ip & 0xfff);
|
||||
}
|
||||
m->xedd = m->icache + (m->ip & (ARRAYLEN(m->icache) - 1));
|
||||
if (IsOpcodeEqual(addr, m->xedd->bytes, m->xedd->length)) {
|
||||
taken++;
|
||||
} else {
|
||||
ntaken++;
|
||||
xed_decoded_inst_zero_set_mode(m->xedd, XED_MACHINE_MODE_LONG_64);
|
||||
if (xed_instruction_length_decode(m->xedd, addr, 15)) {
|
||||
HaltMachine(m, kMachineDecodeError);
|
||||
}
|
||||
if (!IsOpcodeEqual(m->xedd, addr)) {
|
||||
DecodeInstruction(m, addr, 15);
|
||||
}
|
||||
} else {
|
||||
m->xedd = m->icache;
|
||||
xed_decoded_inst_zero_set_mode(m->xedd, XED_MACHINE_MODE_LONG_64);
|
||||
addr = ResolveAddress(m, m->ip);
|
||||
if ((toil = FindReal(m, m->ip + i))) {
|
||||
addr = ResolveAddress(m, ip);
|
||||
if ((toil = FindReal(m, ip + i))) {
|
||||
memcpy(copy, addr, i);
|
||||
memcpy(copy + i, toil, 15 - i);
|
||||
if ((err = xed_instruction_length_decode(m->xedd, copy, 15))) {
|
||||
HaltMachine(m, kMachineDecodeError);
|
||||
}
|
||||
DecodeInstruction(m, copy, 15);
|
||||
} else {
|
||||
if ((err = xed_instruction_length_decode(m->xedd, addr, i))) {
|
||||
HaltMachine(m, kMachineDecodeError);
|
||||
}
|
||||
DecodeInstruction(m, addr, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/arraylist.h"
|
||||
#include "libc/alg/arraylist2.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/knuthmultiplicativehash.h"
|
||||
|
@ -92,12 +93,13 @@ size_t interncount(const struct Interner *t) {
|
|||
* @note use consistent size w/ non-string items
|
||||
*/
|
||||
size_t internobj(struct Interner *t, const void *data, size_t size) {
|
||||
struct InternerObject *it = (struct InternerObject *)t;
|
||||
char *item;
|
||||
unsigned hash;
|
||||
size_t i, step;
|
||||
unsigned char *item;
|
||||
struct InternerObject *it;
|
||||
step = 0;
|
||||
item = data;
|
||||
it = (struct InternerObject *)t;
|
||||
hash = max(1, KnuthMultiplicativeHash32(data, size));
|
||||
do {
|
||||
/* it is written that triangle probe halts iff i<n/2 && popcnt(n)==1 */
|
||||
|
@ -117,7 +119,8 @@ size_t internobj(struct Interner *t, const void *data, size_t size) {
|
|||
} while (it->p[i].hash);
|
||||
}
|
||||
it->p[i].hash = hash;
|
||||
return (it->p[i].index = concat(&it->pool, item, size));
|
||||
return (it->p[i].index =
|
||||
CONCAT(&it->pool.p, &it->pool.i, &it->pool.n, item, size));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -112,10 +112,10 @@ static void LoadBin(struct Machine *m, intptr_t base, const char *prog,
|
|||
void LoadProgram(struct Machine *m, const char *prog, char **args, char **vars,
|
||||
struct Elf *elf) {
|
||||
int fd;
|
||||
char *real;
|
||||
ssize_t rc;
|
||||
void *stack;
|
||||
struct stat st;
|
||||
void *code, *stack;
|
||||
char *real, *memory;
|
||||
size_t i, codesize, mappedsize, extrasize, stacksize;
|
||||
DCHECK_NOTNULL(prog);
|
||||
elf->prog = prog;
|
||||
|
@ -125,39 +125,61 @@ void LoadProgram(struct Machine *m, const char *prog, char **args, char **vars,
|
|||
fputs(": not found\n", stderr);
|
||||
exit(1);
|
||||
}
|
||||
stacksize = STACKSIZE;
|
||||
codesize = st.st_size;
|
||||
mappedsize = ROUNDDOWN(codesize, FRAMESIZE);
|
||||
extrasize = codesize - mappedsize;
|
||||
CHECK_NE(MAP_FAILED, (stack = mmap(NULL, stacksize, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)));
|
||||
code = real = (char *)0x0000400000000000;
|
||||
if (mappedsize) {
|
||||
CHECK_NE(MAP_FAILED, mmap(real, mappedsize, PROT_READ | PROT_WRITE,
|
||||
elf->mapsize = ROUNDDOWN(codesize, FRAMESIZE);
|
||||
extrasize = codesize - elf->mapsize;
|
||||
elf->map = real = (char *)0x0000400000000000;
|
||||
if (elf->mapsize) {
|
||||
CHECK_NE(MAP_FAILED, mmap(real, elf->mapsize, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_FIXED, fd, 0));
|
||||
real += mappedsize;
|
||||
real += elf->mapsize;
|
||||
}
|
||||
if (extrasize) {
|
||||
CHECK_NE(MAP_FAILED,
|
||||
mmap(real, ROUNDUP(extrasize, FRAMESIZE), PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0));
|
||||
for (i = 0; i < extrasize; i += (size_t)rc) {
|
||||
CHECK_NE(-1, (rc = pread(fd, real + i, extrasize - i, mappedsize + i)));
|
||||
CHECK_NE(-1, (rc = pread(fd, real + i, extrasize - i, elf->mapsize + i)));
|
||||
}
|
||||
elf->mapsize += ROUNDUP(extrasize, FRAMESIZE);
|
||||
}
|
||||
CHECK_NE(-1, close(fd));
|
||||
ResetCpu(m);
|
||||
Write64(m->sp, 0x0000800000000000);
|
||||
RegisterMemory(m, 0x0000800000000000 - stacksize, stack, stacksize);
|
||||
LoadArgv(m, prog, args, vars);
|
||||
if (memcmp(code, "\177ELF", 4) == 0) {
|
||||
elf->ehdr = code;
|
||||
elf->size = codesize;
|
||||
LoadElf(m, elf);
|
||||
if (m->mode == XED_MACHINE_MODE_REAL) {
|
||||
elf->base = 0x7c00;
|
||||
CHECK_NE(MAP_FAILED,
|
||||
(memory = mmap(NULL, BIGPAGESIZE, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)));
|
||||
RegisterMemory(m, 0, memory, BIGPAGESIZE);
|
||||
m->ip = 0x7c00;
|
||||
Write64(m->cs, 0);
|
||||
Write64(m->dx, 0);
|
||||
memcpy(memory + 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;
|
||||
}
|
||||
} else {
|
||||
elf->base = IMAGE_BASE_VIRTUAL;
|
||||
elf->ehdr = NULL;
|
||||
elf->size = 0;
|
||||
LoadBin(m, elf->base, prog, code, codesize);
|
||||
stacksize = STACKSIZE;
|
||||
CHECK_NE(MAP_FAILED, (stack = mmap(NULL, stacksize, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)));
|
||||
Write64(m->sp, 0x0000800000000000);
|
||||
RegisterMemory(m, 0x0000800000000000 - stacksize, stack, stacksize);
|
||||
LoadArgv(m, prog, args, vars);
|
||||
if (memcmp(elf->map, "\177ELF", 4) == 0) {
|
||||
elf->ehdr = (void *)elf->map;
|
||||
elf->size = codesize;
|
||||
LoadElf(m, elf);
|
||||
} else {
|
||||
elf->base = IMAGE_BASE_VIRTUAL;
|
||||
elf->ehdr = NULL;
|
||||
elf->size = 0;
|
||||
LoadBin(m, elf->base, prog, elf->map, codesize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ struct Elf {
|
|||
Elf64_Ehdr *ehdr;
|
||||
size_t size;
|
||||
int64_t base;
|
||||
char *map;
|
||||
size_t mapsize;
|
||||
};
|
||||
|
||||
void LoadProgram(struct Machine *, const char *, char **, char **,
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,5 @@
|
|||
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_MACHINE_H_
|
||||
#define COSMOPOLITAN_TOOL_BUILD_LIB_MACHINE_H_
|
||||
#include "libc/elf/struct/ehdr.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "third_party/xed/x86.h"
|
||||
#include "tool/build/lib/fds.h"
|
||||
|
@ -26,9 +25,13 @@ COSMOPOLITAN_C_START_
|
|||
struct Machine {
|
||||
struct XedDecodedInst *xedd;
|
||||
uint64_t ip;
|
||||
uint8_t cs[8];
|
||||
uint8_t ss[8];
|
||||
uint64_t codevirt;
|
||||
uint8_t *codereal;
|
||||
uint32_t mode;
|
||||
uint32_t flags;
|
||||
uint32_t tlbindex;
|
||||
uint32_t stashsize;
|
||||
int64_t stashaddr;
|
||||
int64_t readaddr;
|
||||
|
@ -36,7 +39,7 @@ struct Machine {
|
|||
uint32_t readsize;
|
||||
uint32_t writesize;
|
||||
union {
|
||||
uint8_t reg[2 * 8][8];
|
||||
uint8_t reg[16][8];
|
||||
struct {
|
||||
uint8_t ax[8];
|
||||
uint8_t cx[8];
|
||||
|
@ -55,14 +58,19 @@ struct Machine {
|
|||
uint8_t r14[8];
|
||||
uint8_t r15[8];
|
||||
};
|
||||
} aligned(8);
|
||||
uint32_t tlbindex;
|
||||
};
|
||||
uint8_t *real;
|
||||
uint64_t realsize;
|
||||
uint64_t *cr3;
|
||||
struct TlbEntry {
|
||||
int64_t v;
|
||||
void *r;
|
||||
} tlb[16];
|
||||
uint8_t *veg[2 * 8];
|
||||
uint8_t *beg[2 * 2 * 8];
|
||||
uint8_t xmm[16][16] aligned(16);
|
||||
uint8_t es[8];
|
||||
uint8_t ds[8];
|
||||
uint8_t fs[8];
|
||||
uint8_t gs[8];
|
||||
struct MachineFpu {
|
||||
long double st[8];
|
||||
union {
|
||||
|
@ -129,16 +137,14 @@ struct Machine {
|
|||
uint32_t i;
|
||||
void *p[6];
|
||||
} freelist;
|
||||
pml4t_t cr3;
|
||||
uint8_t xmm[2][8][16] aligned(16);
|
||||
int64_t bofram[2];
|
||||
jmp_buf onhalt;
|
||||
int64_t faultaddr;
|
||||
uint8_t stash[4096];
|
||||
uint8_t xmmtype[2][8];
|
||||
struct XedDecodedInst icache[1024];
|
||||
uint8_t icache[2048][40] aligned(8);
|
||||
struct MachineFds fds;
|
||||
};
|
||||
} aligned(64);
|
||||
|
||||
void ResetCpu(struct Machine *);
|
||||
void LoadInstruction(struct Machine *);
|
||||
|
|
37
tool/build/lib/mda.c
Normal file
37
tool/build/lib/mda.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "tool/build/lib/buffer.h"
|
||||
#include "tool/build/lib/mda.h"
|
||||
|
||||
void DrawMda(struct Panel *p, uint8_t v[25][80][2]) {
|
||||
unsigned y, x, n;
|
||||
n = MIN(25, p->bottom - p->top);
|
||||
for (y = 0; y < n; ++y) {
|
||||
for (x = 0; x < 80; ++x) {
|
||||
if (v[y][x][1]) {
|
||||
AppendWide(&p->lines[y], kCp437[v[y][x][0]]);
|
||||
} else {
|
||||
AppendChar(&p->lines[y], ' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
tool/build/lib/mda.h
Normal file
11
tool/build/lib/mda.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#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_ */
|
|
@ -105,8 +105,9 @@ void VirtualCopy(struct Machine *m, int64_t v, char *r, uint64_t n, bool d) {
|
|||
}
|
||||
}
|
||||
|
||||
void VirtualSend(struct Machine *m, void *dst, int64_t src, uint64_t n) {
|
||||
void *VirtualSend(struct Machine *m, void *dst, int64_t src, uint64_t n) {
|
||||
VirtualCopy(m, src, dst, n, true);
|
||||
return dst;
|
||||
}
|
||||
|
||||
void VirtualRecv(struct Machine *m, int64_t dst, void *src, uint64_t n) {
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define GetSegment(m) 0
|
||||
|
||||
int RegisterMemory(struct Machine *, int64_t, void *, size_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 *);
|
||||
|
@ -24,8 +22,9 @@ 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 VirtualSend(struct Machine *, void *, int64_t, uint64_t);
|
||||
void *VirtualSend(struct Machine *, void *, int64_t, uint64_t);
|
||||
void VirtualSet(struct Machine *, int64_t, char, uint64_t);
|
||||
void *RealAddress(struct Machine *, int64_t);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -45,6 +45,7 @@ struct Machine *NewMachine(void) {
|
|||
struct Machine *m;
|
||||
m = memalign(alignof(struct Machine), sizeof(struct Machine));
|
||||
memset(m, 0, sizeof(struct Machine));
|
||||
m->mode = XED_MACHINE_MODE_LONG_64;
|
||||
InitMachine(m);
|
||||
return m;
|
||||
}
|
||||
|
|
|
@ -18,37 +18,104 @@
|
|||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#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/modrm.h"
|
||||
#include "tool/build/lib/throw.h"
|
||||
|
||||
/**
|
||||
* Computes virtual address based on modrm and sib bytes.
|
||||
* 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};
|
||||
|
||||
int64_t ComputeAddress(const struct Machine *m, uint32_t rde) {
|
||||
uint64_t i;
|
||||
DCHECK(m->xedd->op.has_modrm);
|
||||
uint8_t *s;
|
||||
DCHECK(!IsModrmRegister(rde));
|
||||
s = m->ds;
|
||||
i = m->xedd->op.disp;
|
||||
if (!SibExists(rde)) {
|
||||
if (IsRipRelative(rde)) {
|
||||
i += m->ip;
|
||||
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 {
|
||||
i += Read64(RegRexbRm(m, rde));
|
||||
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 {
|
||||
DCHECK(m->xedd->op.has_sib);
|
||||
if (SibHasBase(rde)) {
|
||||
i += Read64(RegRexbBase(m, rde));
|
||||
}
|
||||
if (SibHasIndex(rde)) {
|
||||
i += Read64(RegRexxIndex(m, rde)) << m->xedd->op.scale;
|
||||
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:
|
||||
unreachable;
|
||||
}
|
||||
i &= 0xffff;
|
||||
}
|
||||
i += GetSegment(m);
|
||||
if (Asz(rde)) i &= 0xffffffff;
|
||||
return i;
|
||||
return AddSegment(m, rde, i, s);
|
||||
}
|
||||
|
||||
void *ComputeReserveAddressRead(struct Machine *m, uint32_t rde, size_t n) {
|
||||
|
@ -62,6 +129,10 @@ 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);
|
||||
}
|
||||
|
|
|
@ -5,46 +5,56 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define SibBase(x) ((x & 000007000000) >> 022)
|
||||
#define SibIndex(x) ((x & 000700000000) >> 030)
|
||||
#define ModrmRm(x) ((x & 000000000700) >> 006)
|
||||
#define ModrmReg(x) ((x & 000000000007) >> 000)
|
||||
#define ModrmSrm(x) ((x & 000000070000) >> 014)
|
||||
#define ModrmMod(x) ((x & 000060000000) >> 026)
|
||||
#define RegLog2(x) ((x & 006000000000) >> 034)
|
||||
#define Rexx(x) ((x & 001000000000) >> 033)
|
||||
#define Asz(x) ((x & 000000400000) >> 021)
|
||||
#define Rexw(x) ((x & 000000004000) >> 013)
|
||||
#define Rexr(x) ((x & 000000000010) >> 003)
|
||||
#define Rexb(x) ((x & 000010000000) >> 025)
|
||||
#define Rex(x) ((x & 000000000020) >> 004)
|
||||
#define Osz(x) ((x & 000000000040) >> 005)
|
||||
#define Rep(x) ((x & 030000000000) >> 036)
|
||||
#define 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 IsModrmRegister(x) (ModrmMod(x) == 3)
|
||||
#define SibExists(x) (ModrmRm(x) == 4)
|
||||
#define SibHasIndex(x) (SibIndex(x) != 4 || Rexx(x))
|
||||
#define SibHasBase(x) (SibBase(x) != 5 || ModrmMod(x))
|
||||
#define SibIsAbsolute(x) (!SibHasBase(x) && !SibHasIndex(x))
|
||||
#define IsRipRelative(x) (ModrmRm(x) == 5 && !ModrmMod(x))
|
||||
#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 RexbBase(m, x) (Rexb(x) << 3 | m->xedd->op.base)
|
||||
#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 ByteRexrReg(m, x) m->beg[(x & 00000000037) >> 0]
|
||||
#define ByteRexbRm(m, x) m->beg[(x & 00000003700) >> 6]
|
||||
#define ByteRexbSrm(m, x) m->beg[(x & 00000370000) >> 12]
|
||||
#define RegRexbSrm(m, x) Abp8(m->reg[(x & 00000170000) >> 12])
|
||||
#define RegRexrReg(m, x) Abp8(m->reg[(x & 00000000017) >> 0])
|
||||
#define RegRexbRm(m, x) Abp8(m->reg[(x & 00000001700) >> 6])
|
||||
#define RegRexbBase(m, x) Abp8(m->reg[(x & 00017000000) >> 18])
|
||||
#define RegRexxIndex(m, x) Abp8(m->reg[(x & 01700000000) >> 24])
|
||||
#define XmmRexrReg(m, x) Abp16(m->veg[(x & 00000000017) >> 0])
|
||||
#define XmmRexbRm(m, x) Abp16(m->veg[(x & 00000001700) >> 6])
|
||||
#define MmReg(m, x) Abp16(m->veg[(x & 00000000007) >> 0])
|
||||
#define MmRm(m, x) Abp16(m->veg[(x & 00000000700) >> 6])
|
||||
#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) (ModrmRm(x) == 5 && !ModrmMod(x))
|
||||
|
||||
extern const uint8_t kByteReg[32];
|
||||
|
||||
int64_t ComputeAddress(const struct Machine *, uint32_t) nosideeffect;
|
||||
|
||||
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);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.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"
|
||||
|
@ -104,8 +105,7 @@ char *FormatPml4t(uint64_t pml4t[512]) {
|
|||
FormatEndPage(&pp, 0x800000000000);
|
||||
}
|
||||
if (pp.b.p) {
|
||||
realloc(pp.b.p, pp.b.i + 1);
|
||||
return pp.b.p;
|
||||
return xrealloc(pp.b.p, pp.b.i + 1);
|
||||
} else {
|
||||
return strdup("");
|
||||
}
|
||||
|
|
|
@ -31,18 +31,39 @@
|
|||
#include "libc/x/x.h"
|
||||
#include "tool/build/lib/pty.h"
|
||||
|
||||
struct MachinePty *MachinePtyNew(unsigned yn, unsigned xn) {
|
||||
struct MachinePty *pty;
|
||||
DCHECK_GT(yn, 0);
|
||||
DCHECK_GT(xn, 0);
|
||||
pty = xcalloc(1, sizeof(struct MachinePty));
|
||||
struct MachinePty *MachinePtyNew(void) {
|
||||
return xcalloc(1, sizeof(struct MachinePty));
|
||||
}
|
||||
|
||||
void MachinePtyResize(struct MachinePty *pty, int yn, int xn) {
|
||||
unsigned y, ym, xm, y0;
|
||||
uint32_t *wcs, *fgs, *bgs, *prs;
|
||||
if (yn <= 0 || xn <= 0) return;
|
||||
wcs = xcalloc(yn * xn, 4);
|
||||
fgs = xcalloc(yn * xn, 4);
|
||||
bgs = xcalloc(yn * xn, 4);
|
||||
prs = xcalloc(yn * xn, 4);
|
||||
y0 = yn > pty->y + 1 ? 0 : pty->y + 1 - yn;
|
||||
ym = MIN(yn, pty->yn) + y0;
|
||||
xm = MIN(xn, pty->xn);
|
||||
for (y = y0; y < ym; ++y) {
|
||||
memcpy(wcs + y * xn, pty->wcs + y * pty->xn, xm * 4);
|
||||
memcpy(fgs + y * xn, pty->fgs + y * pty->xn, xm * 4);
|
||||
memcpy(bgs + y * xn, pty->bgs + y * pty->xn, xm * 4);
|
||||
memcpy(prs + y * xn, pty->prs + y * pty->xn, xm * 4);
|
||||
}
|
||||
free(pty->wcs);
|
||||
free(pty->fgs);
|
||||
free(pty->bgs);
|
||||
free(pty->prs);
|
||||
pty->wcs = wcs;
|
||||
pty->fgs = fgs;
|
||||
pty->bgs = bgs;
|
||||
pty->prs = prs;
|
||||
pty->y = MIN(pty->y, yn - 1);
|
||||
pty->x = MIN(pty->x, xn - 1);
|
||||
pty->yn = yn;
|
||||
pty->xn = xn;
|
||||
pty->wcs = xcalloc(yn * xn, sizeof(pty->wcs[0]));
|
||||
pty->fgs = xcalloc(yn * xn, sizeof(pty->fgs[0]));
|
||||
pty->bgs = xcalloc(yn * xn, sizeof(pty->bgs[0]));
|
||||
pty->prs = xcalloc(yn * xn, sizeof(pty->prs[0]));
|
||||
return pty;
|
||||
}
|
||||
|
||||
void MachinePtyFree(struct MachinePty *pty) {
|
||||
|
@ -234,7 +255,7 @@ static void MachinePtySelectGraphicsRendition(struct MachinePty *pty) {
|
|||
t = kSgrFg;
|
||||
break;
|
||||
case 39:
|
||||
pty->pr &= kMachinePtyFg;
|
||||
pty->pr &= ~kMachinePtyFg;
|
||||
break;
|
||||
case 100 ... 107:
|
||||
code[0] -= 100 - 40;
|
||||
|
@ -248,7 +269,7 @@ static void MachinePtySelectGraphicsRendition(struct MachinePty *pty) {
|
|||
t = kSgrBg;
|
||||
break;
|
||||
case 49:
|
||||
pty->pr &= kMachinePtyBg;
|
||||
pty->pr &= ~kMachinePtyBg;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -368,6 +389,7 @@ static void MachinePtyEscAppend(struct MachinePty *pty, char c) {
|
|||
ssize_t MachinePtyWrite(struct MachinePty *pty, const void *data, size_t n) {
|
||||
int i;
|
||||
const uint8_t *p;
|
||||
if (!pty->yn || !pty->xn) return 0;
|
||||
for (p = data, i = 0; i < n; ++i) {
|
||||
switch (pty->state) {
|
||||
case kMachinePtyAscii:
|
||||
|
@ -464,7 +486,7 @@ ssize_t MachinePtyWrite(struct MachinePty *pty, const void *data, size_t n) {
|
|||
void MachinePtyAppendLine(struct MachinePty *pty, struct Buffer *buf,
|
||||
unsigned y) {
|
||||
uint32_t x, i, fg, bg, pr, wc, w;
|
||||
CHECK_LT(y, pty->yn);
|
||||
if (y >= pty->yn) return;
|
||||
for (fg = bg = pr = x = 0; x < pty->xn; x += w) {
|
||||
i = y * pty->xn + x;
|
||||
wc = pty->wcs[i];
|
||||
|
|
|
@ -40,8 +40,9 @@ struct MachinePty {
|
|||
} esc;
|
||||
};
|
||||
|
||||
struct MachinePty *MachinePtyNew(unsigned, unsigned) nodiscard;
|
||||
void MachinePtyFree(struct MachinePty *);
|
||||
struct MachinePty *MachinePtyNew(void) nodiscard;
|
||||
void MachinePtyResize(struct MachinePty *, int, int);
|
||||
ssize_t MachinePtyWrite(struct MachinePty *, const void *, size_t);
|
||||
void MachinePtyAppendLine(struct MachinePty *, struct Buffer *, unsigned);
|
||||
|
||||
|
|
|
@ -114,102 +114,603 @@ union MachineVector {
|
|||
uint64_t u64[2];
|
||||
};
|
||||
|
||||
void OpSse(struct Machine *m, uint32_t rde, enum OpSseKernel kernel) {
|
||||
int i;
|
||||
uint8_t *p;
|
||||
union MachineVector x, y;
|
||||
p = GetModrmRegisterXmmPointerRead16(m, rde);
|
||||
static void SsePsubb(void *b, const void *a) {
|
||||
psubb(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePaddb(void *b, const void *a) {
|
||||
paddb(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePsubw(void *b, const void *a) {
|
||||
psubw(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePaddw(void *b, const void *a) {
|
||||
paddw(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePsubd(void *b, const void *a) {
|
||||
psubd(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePaddd(void *b, const void *a) {
|
||||
paddd(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePaddq(void *b, const void *a) {
|
||||
paddq(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePsubq(void *b, const void *a) {
|
||||
psubq(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePsubsb(void *b, const void *a) {
|
||||
psubsb(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePsubsw(void *b, const void *a) {
|
||||
psubsw(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePaddsb(void *b, const void *a) {
|
||||
paddsb(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePaddsw(void *b, const void *a) {
|
||||
paddsw(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePaddusb(void *b, const void *a) {
|
||||
paddusb(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePaddusw(void *b, const void *a) {
|
||||
paddusw(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePor(void *b, const void *a) {
|
||||
por(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePxor(void *b, const void *a) {
|
||||
pxor(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePand(void *b, const void *a) {
|
||||
pand(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePandn(void *b, const void *a) {
|
||||
pandn(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePsubusb(void *b, const void *a) {
|
||||
psubusb(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePsubusw(void *b, const void *a) {
|
||||
psubusw(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePminub(void *b, const void *a) {
|
||||
pminub(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePmaxub(void *b, const void *a) {
|
||||
pmaxub(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePminsw(void *b, const void *a) {
|
||||
pminsw(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePmaxsw(void *b, const void *a) {
|
||||
pmaxsw(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePunpcklbw(void *b, const void *a) {
|
||||
punpcklbw(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePunpckhbw(void *b, const void *a) {
|
||||
punpckhbw(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePunpcklwd(void *b, const void *a) {
|
||||
punpcklwd(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePunpckldq(void *b, const void *a) {
|
||||
punpckldq(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePunpckhwd(void *b, const void *a) {
|
||||
punpckhwd(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePunpckhdq(void *b, const void *a) {
|
||||
punpckhdq(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePunpcklqdq(void *b, const void *a) {
|
||||
punpcklqdq(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePunpckhqdq(void *b, const void *a) {
|
||||
punpckhqdq(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePacksswb(void *b, const void *a) {
|
||||
packsswb(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePackuswb(void *b, const void *a) {
|
||||
packuswb(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePackssdw(void *b, const void *a) {
|
||||
packssdw(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePcmpgtb(void *b, const void *a) {
|
||||
pcmpgtb(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePcmpgtw(void *b, const void *a) {
|
||||
pcmpgtw(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePcmpgtd(void *b, const void *a) {
|
||||
pcmpgtd(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePcmpeqb(void *b, const void *a) {
|
||||
pcmpeqb(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePcmpeqw(void *b, const void *a) {
|
||||
pcmpeqw(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePcmpeqd(void *b, const void *a) {
|
||||
pcmpeqd(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePsrawv(void *b, const void *a) {
|
||||
psrawv(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePsrlwv(void *b, const void *a) {
|
||||
psrlwv(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePsllwv(void *b, const void *a) {
|
||||
psllwv(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePsradv(void *b, const void *a) {
|
||||
psradv(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePsrldv(void *b, const void *a) {
|
||||
psrldv(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePslldv(void *b, const void *a) {
|
||||
pslldv(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePsrlqv(void *b, const void *a) {
|
||||
psrlqv(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePsllqv(void *b, const void *a) {
|
||||
psllqv(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePavgb(void *b, const void *a) {
|
||||
pavgb(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePavgw(void *b, const void *a) {
|
||||
pavgw(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePsadbw(void *b, const void *a) {
|
||||
psadbw(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePmaddwd(void *b, const void *a) {
|
||||
pmaddwd(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePmulhuw(void *b, const void *a) {
|
||||
pmulhuw(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePmulhw(void *b, const void *a) {
|
||||
pmulhw(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePmuludq(void *b, const void *a) {
|
||||
pmuludq(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePmullw(void *b, const void *a) {
|
||||
pmullw(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePmulld(void *b, const void *a) {
|
||||
pmulld(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePshufb(void *b, const void *a) {
|
||||
pshufb(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePhaddw(void *b, const void *a) {
|
||||
phaddw(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePhaddd(void *b, const void *a) {
|
||||
phaddd(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePhaddsw(void *b, const void *a) {
|
||||
phaddsw(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePmaddubsw(void *b, const void *a) {
|
||||
pmaddubsw(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePhsubw(void *b, const void *a) {
|
||||
phsubw(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePhsubd(void *b, const void *a) {
|
||||
phsubd(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePhsubsw(void *b, const void *a) {
|
||||
phsubsw(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePsignb(void *b, const void *a) {
|
||||
psignb(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePsignw(void *b, const void *a) {
|
||||
psignw(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePsignd(void *b, const void *a) {
|
||||
psignd(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePmulhrsw(void *b, const void *a) {
|
||||
pmulhrsw(b, b, a);
|
||||
}
|
||||
|
||||
static void SsePabsb(void *b, const void *a) {
|
||||
pabsb(b, a);
|
||||
}
|
||||
|
||||
static void SsePabsw(void *b, const void *a) {
|
||||
pabsw(b, a);
|
||||
}
|
||||
|
||||
static void SsePabsd(void *b, const void *a) {
|
||||
pabsd(b, a);
|
||||
}
|
||||
|
||||
static void OpSse(struct Machine *m, uint32_t rde,
|
||||
void kernel(void *, const void *)) {
|
||||
char x[16], y[16];
|
||||
if (Osz(rde)) {
|
||||
memcpy(&y, p, 16);
|
||||
kernel(XmmRexrReg(m, rde), GetModrmRegisterXmmPointerRead16(m, rde));
|
||||
} else {
|
||||
memset(&y, 0, 16);
|
||||
memcpy(&y, p, 8);
|
||||
}
|
||||
memcpy(&x, XmmRexrReg(m, rde), 16);
|
||||
switch (kernel) {
|
||||
CASE(kOpSsePsubb, psubb(x.i8, x.i8, y.i8));
|
||||
CASE(kOpSsePaddb, paddb(x.i8, x.i8, y.i8));
|
||||
CASE(kOpSsePsubw, psubw(x.i16, x.i16, y.i16));
|
||||
CASE(kOpSsePaddw, paddw(x.i16, x.i16, y.i16));
|
||||
CASE(kOpSsePsubd, psubd(x.i32, x.i32, y.i32));
|
||||
CASE(kOpSsePaddd, paddd(x.i32, x.i32, y.i32));
|
||||
CASE(kOpSsePaddq, paddq(x.i64, x.i64, y.i64));
|
||||
CASE(kOpSsePsubq, psubq(x.i64, x.i64, y.i64));
|
||||
CASE(kOpSsePsubsb, psubsb(x.i8, x.i8, y.i8));
|
||||
CASE(kOpSsePsubsw, psubsw(x.i16, x.i16, y.i16));
|
||||
CASE(kOpSsePaddsb, paddsb(x.i8, x.i8, y.i8));
|
||||
CASE(kOpSsePaddsw, paddsw(x.i16, x.i16, y.i16));
|
||||
CASE(kOpSsePaddusb, paddusb(x.u8, x.u8, y.u8));
|
||||
CASE(kOpSsePaddusw, paddusw(x.u16, x.u16, y.u16));
|
||||
CASE(kOpSsePor, por(x.u64, x.u64, y.u64));
|
||||
CASE(kOpSsePxor, pxor(x.u64, x.u64, y.u64));
|
||||
CASE(kOpSsePand, pand(x.u64, x.u64, y.u64));
|
||||
CASE(kOpSsePandn, pandn(x.u64, x.u64, y.u64));
|
||||
CASE(kOpSsePsubusb, psubusb(x.u8, x.u8, y.u8));
|
||||
CASE(kOpSsePsubusw, psubusw(x.u16, x.u16, y.u16));
|
||||
CASE(kOpSsePminub, pminub(x.u8, x.u8, y.u8));
|
||||
CASE(kOpSsePmaxub, pmaxub(x.u8, x.u8, y.u8));
|
||||
CASE(kOpSsePminsw, pminsw(x.i16, x.i16, y.i16));
|
||||
CASE(kOpSsePmaxsw, pmaxsw(x.i16, x.i16, y.i16));
|
||||
CASE(kOpSsePunpcklbw, punpcklbw(x.u8, x.u8, y.u8));
|
||||
CASE(kOpSsePunpckhbw, punpckhbw(x.u8, x.u8, y.u8));
|
||||
CASE(kOpSsePunpcklwd, punpcklwd(x.u16, x.u16, y.u16));
|
||||
CASE(kOpSsePunpckldq, punpckldq(x.u32, x.u32, y.u32));
|
||||
CASE(kOpSsePunpckhwd, punpckhwd(x.u16, x.u16, y.u16));
|
||||
CASE(kOpSsePunpckhdq, punpckhdq(x.u32, x.u32, y.u32));
|
||||
CASE(kOpSsePunpcklqdq, punpcklqdq(x.u64, x.u64, y.u64));
|
||||
CASE(kOpSsePunpckhqdq, punpckhqdq(x.u64, x.u64, y.u64));
|
||||
CASE(kOpSsePacksswb, packsswb(x.i8, x.i16, y.i16));
|
||||
CASE(kOpSsePackuswb, packuswb(x.u8, x.i16, y.i16));
|
||||
CASE(kOpSsePackssdw, packssdw(x.i16, x.i32, y.i32));
|
||||
CASE(kOpSsePcmpgtb, pcmpgtb(x.i8, x.i8, y.i8));
|
||||
CASE(kOpSsePcmpgtw, pcmpgtw(x.i16, x.i16, y.i16));
|
||||
CASE(kOpSsePcmpgtd, pcmpgtd(x.i32, x.i32, y.i32));
|
||||
CASE(kOpSsePcmpeqb, pcmpeqb(x.u8, x.u8, y.u8));
|
||||
CASE(kOpSsePcmpeqw, pcmpeqw(x.i16, x.i16, y.i16));
|
||||
CASE(kOpSsePcmpeqd, pcmpeqd(x.i32, x.i32, y.i32));
|
||||
CASE(kOpSsePsrawv, psrawv(x.i16, x.i16, y.u64));
|
||||
CASE(kOpSsePsrlwv, psrlwv(x.u16, x.u16, y.u64));
|
||||
CASE(kOpSsePsllwv, psllwv(x.u16, x.u16, y.u64));
|
||||
CASE(kOpSsePsradv, psradv(x.i32, x.i32, y.u64));
|
||||
CASE(kOpSsePsrldv, psrldv(x.u32, x.u32, y.u64));
|
||||
CASE(kOpSsePslldv, pslldv(x.u32, x.u32, y.u64));
|
||||
CASE(kOpSsePsrlqv, psrlqv(x.u64, x.u64, y.u64));
|
||||
CASE(kOpSsePsllqv, psllqv(x.u64, x.u64, y.u64));
|
||||
CASE(kOpSsePavgb, pavgb(x.u8, x.u8, y.u8));
|
||||
CASE(kOpSsePavgw, pavgw(x.u16, x.u16, y.u16));
|
||||
CASE(kOpSsePsadbw, psadbw(x.u64, x.u8, y.u8));
|
||||
CASE(kOpSsePmaddwd, pmaddwd(x.i32, x.i16, y.i16));
|
||||
CASE(kOpSsePmulhuw, pmulhuw(x.u16, x.u16, y.u16));
|
||||
CASE(kOpSsePmulhw, pmulhw(x.i16, x.i16, y.i16));
|
||||
CASE(kOpSsePmuludq, pmuludq(x.u64, x.u32, y.u32));
|
||||
CASE(kOpSsePmullw, pmullw(x.i16, x.i16, y.i16));
|
||||
CASE(kOpSsePmulld, pmulld(x.i32, x.i32, y.i32));
|
||||
CASE(kOpSsePshufb, pshufb(x.u8, x.u8, y.u8));
|
||||
CASE(kOpSsePhaddw, phaddw(x.i16, x.i16, y.i16));
|
||||
CASE(kOpSsePhaddd, phaddd(x.i32, x.i32, y.i32));
|
||||
CASE(kOpSsePhaddsw, phaddsw(x.i16, x.i16, y.i16));
|
||||
CASE(kOpSsePmaddubsw, pmaddubsw(x.i16, x.u8, y.i8));
|
||||
CASE(kOpSsePhsubw, phsubw(x.i16, x.i16, y.i16));
|
||||
CASE(kOpSsePhsubd, phsubd(x.i32, x.i32, y.i32));
|
||||
CASE(kOpSsePhsubsw, phsubsw(x.i16, x.i16, y.i16));
|
||||
CASE(kOpSsePsignb, psignb(x.i8, x.i8, y.i8));
|
||||
CASE(kOpSsePsignw, psignw(x.i16, x.i16, y.i16));
|
||||
CASE(kOpSsePsignd, psignd(x.i32, x.i32, y.i32));
|
||||
CASE(kOpSsePmulhrsw, pmulhrsw(x.i16, x.i16, y.i16));
|
||||
CASE(kOpSsePabsb, pabsb(x.u8, x.i8));
|
||||
CASE(kOpSsePabsw, pabsw(x.u16, x.i16));
|
||||
CASE(kOpSsePabsd, pabsd(x.u32, x.i32));
|
||||
default:
|
||||
unreachable;
|
||||
}
|
||||
if (Osz(rde)) {
|
||||
memcpy(XmmRexrReg(m, rde), &x, 16);
|
||||
} else {
|
||||
memcpy(XmmRexrReg(m, rde), &x, 8);
|
||||
memcpy(x, XmmRexrReg(m, rde), 8);
|
||||
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 8);
|
||||
kernel(x, y);
|
||||
memcpy(XmmRexrReg(m, rde), x, 8);
|
||||
}
|
||||
}
|
||||
|
||||
void OpSsePunpcklbw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePunpcklbw);
|
||||
}
|
||||
|
||||
void OpSsePunpcklwd(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePunpcklwd);
|
||||
}
|
||||
|
||||
void OpSsePunpckldq(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePunpckldq);
|
||||
}
|
||||
|
||||
void OpSsePacksswb(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePacksswb);
|
||||
}
|
||||
|
||||
void OpSsePcmpgtb(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePcmpgtb);
|
||||
}
|
||||
|
||||
void OpSsePcmpgtw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePcmpgtw);
|
||||
}
|
||||
|
||||
void OpSsePcmpgtd(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePcmpgtd);
|
||||
}
|
||||
|
||||
void OpSsePackuswb(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePackuswb);
|
||||
}
|
||||
|
||||
void OpSsePunpckhbw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePunpckhbw);
|
||||
}
|
||||
|
||||
void OpSsePunpckhwd(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePunpckhwd);
|
||||
}
|
||||
|
||||
void OpSsePunpckhdq(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePunpckhdq);
|
||||
}
|
||||
|
||||
void OpSsePackssdw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePackssdw);
|
||||
}
|
||||
|
||||
void OpSsePunpcklqdq(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePunpcklqdq);
|
||||
}
|
||||
|
||||
void OpSsePunpckhqdq(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePunpckhqdq);
|
||||
}
|
||||
|
||||
void OpSsePcmpeqb(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePcmpeqb);
|
||||
}
|
||||
|
||||
void OpSsePcmpeqw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePcmpeqw);
|
||||
}
|
||||
|
||||
void OpSsePcmpeqd(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePcmpeqd);
|
||||
}
|
||||
|
||||
void OpSsePsrlwv(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePsrlwv);
|
||||
}
|
||||
|
||||
void OpSsePsrldv(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePsrldv);
|
||||
}
|
||||
|
||||
void OpSsePsrlqv(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePsrlqv);
|
||||
}
|
||||
|
||||
void OpSsePaddq(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePaddq);
|
||||
}
|
||||
|
||||
void OpSsePmullw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePmullw);
|
||||
}
|
||||
|
||||
void OpSsePsubusb(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePsubusb);
|
||||
}
|
||||
|
||||
void OpSsePsubusw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePsubusw);
|
||||
}
|
||||
|
||||
void OpSsePminub(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePminub);
|
||||
}
|
||||
|
||||
void OpSsePand(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePand);
|
||||
}
|
||||
|
||||
void OpSsePaddusb(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePaddusb);
|
||||
}
|
||||
|
||||
void OpSsePaddusw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePaddusw);
|
||||
}
|
||||
|
||||
void OpSsePmaxub(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePmaxub);
|
||||
}
|
||||
|
||||
void OpSsePandn(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePandn);
|
||||
}
|
||||
|
||||
void OpSsePavgb(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePavgb);
|
||||
}
|
||||
|
||||
void OpSsePsrawv(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePsrawv);
|
||||
}
|
||||
|
||||
void OpSsePsradv(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePsradv);
|
||||
}
|
||||
|
||||
void OpSsePavgw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePavgw);
|
||||
}
|
||||
|
||||
void OpSsePmulhuw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePmulhuw);
|
||||
}
|
||||
|
||||
void OpSsePmulhw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePmulhw);
|
||||
}
|
||||
|
||||
void OpSsePsubsb(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePsubsb);
|
||||
}
|
||||
|
||||
void OpSsePsubsw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePsubsw);
|
||||
}
|
||||
|
||||
void OpSsePminsw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePminsw);
|
||||
}
|
||||
|
||||
void OpSsePor(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePor);
|
||||
}
|
||||
|
||||
void OpSsePaddsb(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePaddsb);
|
||||
}
|
||||
|
||||
void OpSsePaddsw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePaddsw);
|
||||
}
|
||||
|
||||
void OpSsePmaxsw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePmaxsw);
|
||||
}
|
||||
|
||||
void OpSsePxor(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePxor);
|
||||
}
|
||||
|
||||
void OpSsePsllwv(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePsllwv);
|
||||
}
|
||||
|
||||
void OpSsePslldv(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePslldv);
|
||||
}
|
||||
|
||||
void OpSsePsllqv(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePsllqv);
|
||||
}
|
||||
|
||||
void OpSsePmuludq(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePmuludq);
|
||||
}
|
||||
|
||||
void OpSsePmaddwd(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePmaddwd);
|
||||
}
|
||||
|
||||
void OpSsePsadbw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePsadbw);
|
||||
}
|
||||
|
||||
void OpSsePsubb(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePsubb);
|
||||
}
|
||||
|
||||
void OpSsePsubw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePsubw);
|
||||
}
|
||||
|
||||
void OpSsePsubd(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePsubd);
|
||||
}
|
||||
|
||||
void OpSsePsubq(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePsubq);
|
||||
}
|
||||
|
||||
void OpSsePaddb(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePaddb);
|
||||
}
|
||||
|
||||
void OpSsePaddw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePaddw);
|
||||
}
|
||||
|
||||
void OpSsePaddd(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePaddd);
|
||||
}
|
||||
|
||||
void OpSsePshufb(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePshufb);
|
||||
}
|
||||
|
||||
void OpSsePhaddw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePhaddw);
|
||||
}
|
||||
|
||||
void OpSsePhaddd(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePhaddd);
|
||||
}
|
||||
|
||||
void OpSsePhaddsw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePhaddsw);
|
||||
}
|
||||
|
||||
void OpSsePmaddubsw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePmaddubsw);
|
||||
}
|
||||
|
||||
void OpSsePhsubw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePhsubw);
|
||||
}
|
||||
|
||||
void OpSsePhsubd(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePhsubd);
|
||||
}
|
||||
|
||||
void OpSsePhsubsw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePhsubsw);
|
||||
}
|
||||
|
||||
void OpSsePsignb(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePsignb);
|
||||
}
|
||||
|
||||
void OpSsePsignw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePsignw);
|
||||
}
|
||||
|
||||
void OpSsePsignd(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePsignd);
|
||||
}
|
||||
|
||||
void OpSsePmulhrsw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePmulhrsw);
|
||||
}
|
||||
|
||||
void OpSsePabsb(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePabsb);
|
||||
}
|
||||
|
||||
void OpSsePabsw(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePabsw);
|
||||
}
|
||||
|
||||
void OpSsePabsd(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePabsd);
|
||||
}
|
||||
|
||||
void OpSsePmulld(struct Machine *m, uint32_t rde) {
|
||||
OpSse(m, rde, SsePmulld);
|
||||
}
|
||||
|
||||
void OpSseUdqIb(struct Machine *m, uint32_t rde, enum OpSseUdqIbKernel kernel) {
|
||||
uint8_t i;
|
||||
union MachineVector x;
|
||||
|
|
|
@ -4,81 +4,7 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
enum OpSseKernel {
|
||||
kOpSsePaddb,
|
||||
kOpSsePaddw,
|
||||
kOpSsePaddd,
|
||||
kOpSsePaddq,
|
||||
kOpSsePsubb,
|
||||
kOpSsePsubw,
|
||||
kOpSsePsubd,
|
||||
kOpSsePsubq,
|
||||
kOpSsePaddsb,
|
||||
kOpSsePaddsw,
|
||||
kOpSsePaddusb,
|
||||
kOpSsePaddusw,
|
||||
kOpSsePsubsb,
|
||||
kOpSsePsubsw,
|
||||
kOpSsePor,
|
||||
kOpSsePxor,
|
||||
kOpSsePand,
|
||||
kOpSsePandn,
|
||||
kOpSsePsubusb,
|
||||
kOpSsePsubusw,
|
||||
kOpSsePminub,
|
||||
kOpSsePmaxub,
|
||||
kOpSsePminsw,
|
||||
kOpSsePmaxsw,
|
||||
kOpSsePunpcklbw,
|
||||
kOpSsePunpckhbw,
|
||||
kOpSsePunpcklwd,
|
||||
kOpSsePunpckldq,
|
||||
kOpSsePunpckhwd,
|
||||
kOpSsePunpckhdq,
|
||||
kOpSsePunpcklqdq,
|
||||
kOpSsePunpckhqdq,
|
||||
kOpSsePacksswb,
|
||||
kOpSsePackuswb,
|
||||
kOpSsePackssdw,
|
||||
kOpSsePcmpgtb,
|
||||
kOpSsePcmpgtw,
|
||||
kOpSsePcmpgtd,
|
||||
kOpSsePcmpeqb,
|
||||
kOpSsePcmpeqw,
|
||||
kOpSsePcmpeqd,
|
||||
kOpSsePsrawv,
|
||||
kOpSsePsradv,
|
||||
kOpSsePsrlwv,
|
||||
kOpSsePsrldv,
|
||||
kOpSsePsrlqv,
|
||||
kOpSsePsllwv,
|
||||
kOpSsePslldv,
|
||||
kOpSsePsllqv,
|
||||
kOpSsePavgb,
|
||||
kOpSsePavgw,
|
||||
kOpSsePmulhuw,
|
||||
kOpSsePmulhw,
|
||||
kOpSsePmuludq,
|
||||
kOpSsePmaddwd,
|
||||
kOpSsePmullw,
|
||||
kOpSsePmulld,
|
||||
kOpSsePsadbw,
|
||||
kOpSsePshufb,
|
||||
kOpSsePhaddw,
|
||||
kOpSsePhaddd,
|
||||
kOpSsePhaddsw,
|
||||
kOpSsePmaddubsw,
|
||||
kOpSsePhsubw,
|
||||
kOpSsePhsubd,
|
||||
kOpSsePhsubsw,
|
||||
kOpSsePsignb,
|
||||
kOpSsePsignw,
|
||||
kOpSsePsignd,
|
||||
kOpSsePmulhrsw,
|
||||
kOpSsePabsb,
|
||||
kOpSsePabsw,
|
||||
kOpSsePabsd,
|
||||
};
|
||||
typedef void (*sse_f)(void *, void *, void *);
|
||||
|
||||
enum OpSseUdqIbKernel {
|
||||
kOpSseUdqIbPsrlw,
|
||||
|
@ -93,9 +19,81 @@ enum OpSseUdqIbKernel {
|
|||
kOpSseUdqIbPslldq,
|
||||
};
|
||||
|
||||
void OpSse(struct Machine *, uint32_t, enum OpSseKernel);
|
||||
void OpSseUdqIb(struct Machine *, uint32_t, enum OpSseUdqIbKernel);
|
||||
void OpSsePalignr(struct Machine *, uint32_t);
|
||||
void OpSsePunpcklbw(struct Machine *, uint32_t);
|
||||
void OpSsePunpcklwd(struct Machine *, uint32_t);
|
||||
void OpSsePunpckldq(struct Machine *, uint32_t);
|
||||
void OpSsePacksswb(struct Machine *, uint32_t);
|
||||
void OpSsePcmpgtb(struct Machine *, uint32_t);
|
||||
void OpSsePcmpgtw(struct Machine *, uint32_t);
|
||||
void OpSsePcmpgtd(struct Machine *, uint32_t);
|
||||
void OpSsePackuswb(struct Machine *, uint32_t);
|
||||
void OpSsePunpckhbw(struct Machine *, uint32_t);
|
||||
void OpSsePunpckhwd(struct Machine *, uint32_t);
|
||||
void OpSsePunpckhdq(struct Machine *, uint32_t);
|
||||
void OpSsePackssdw(struct Machine *, uint32_t);
|
||||
void OpSsePunpcklqdq(struct Machine *, uint32_t);
|
||||
void OpSsePunpckhqdq(struct Machine *, uint32_t);
|
||||
void OpSsePcmpeqb(struct Machine *, uint32_t);
|
||||
void OpSsePcmpeqw(struct Machine *, uint32_t);
|
||||
void OpSsePcmpeqd(struct Machine *, uint32_t);
|
||||
void OpSsePsrlwv(struct Machine *, uint32_t);
|
||||
void OpSsePsrldv(struct Machine *, uint32_t);
|
||||
void OpSsePsrlqv(struct Machine *, uint32_t);
|
||||
void OpSsePaddq(struct Machine *, uint32_t);
|
||||
void OpSsePmullw(struct Machine *, uint32_t);
|
||||
void OpSsePsubusb(struct Machine *, uint32_t);
|
||||
void OpSsePsubusw(struct Machine *, uint32_t);
|
||||
void OpSsePminub(struct Machine *, uint32_t);
|
||||
void OpSsePand(struct Machine *, uint32_t);
|
||||
void OpSsePaddusb(struct Machine *, uint32_t);
|
||||
void OpSsePaddusw(struct Machine *, uint32_t);
|
||||
void OpSsePmaxub(struct Machine *, uint32_t);
|
||||
void OpSsePandn(struct Machine *, uint32_t);
|
||||
void OpSsePavgb(struct Machine *, uint32_t);
|
||||
void OpSsePsrawv(struct Machine *, uint32_t);
|
||||
void OpSsePsradv(struct Machine *, uint32_t);
|
||||
void OpSsePavgw(struct Machine *, uint32_t);
|
||||
void OpSsePmulhuw(struct Machine *, uint32_t);
|
||||
void OpSsePmulhw(struct Machine *, uint32_t);
|
||||
void OpSsePsubsb(struct Machine *, uint32_t);
|
||||
void OpSsePsubsw(struct Machine *, uint32_t);
|
||||
void OpSsePminsw(struct Machine *, uint32_t);
|
||||
void OpSsePor(struct Machine *, uint32_t);
|
||||
void OpSsePaddsb(struct Machine *, uint32_t);
|
||||
void OpSsePaddsw(struct Machine *, uint32_t);
|
||||
void OpSsePmaxsw(struct Machine *, uint32_t);
|
||||
void OpSsePxor(struct Machine *, uint32_t);
|
||||
void OpSsePsllwv(struct Machine *, uint32_t);
|
||||
void OpSsePslldv(struct Machine *, uint32_t);
|
||||
void OpSsePsllqv(struct Machine *, uint32_t);
|
||||
void OpSsePmuludq(struct Machine *, uint32_t);
|
||||
void OpSsePmaddwd(struct Machine *, uint32_t);
|
||||
void OpSsePsadbw(struct Machine *, uint32_t);
|
||||
void OpSsePsubb(struct Machine *, uint32_t);
|
||||
void OpSsePsubw(struct Machine *, uint32_t);
|
||||
void OpSsePsubd(struct Machine *, uint32_t);
|
||||
void OpSsePsubq(struct Machine *, uint32_t);
|
||||
void OpSsePaddb(struct Machine *, uint32_t);
|
||||
void OpSsePaddw(struct Machine *, uint32_t);
|
||||
void OpSsePaddd(struct Machine *, uint32_t);
|
||||
void OpSsePshufb(struct Machine *, uint32_t);
|
||||
void OpSsePhaddw(struct Machine *, uint32_t);
|
||||
void OpSsePhaddd(struct Machine *, uint32_t);
|
||||
void OpSsePhaddsw(struct Machine *, uint32_t);
|
||||
void OpSsePmaddubsw(struct Machine *, uint32_t);
|
||||
void OpSsePhsubw(struct Machine *, uint32_t);
|
||||
void OpSsePhsubd(struct Machine *, uint32_t);
|
||||
void OpSsePhsubsw(struct Machine *, uint32_t);
|
||||
void OpSsePsignb(struct Machine *, uint32_t);
|
||||
void OpSsePsignw(struct Machine *, uint32_t);
|
||||
void OpSsePsignd(struct Machine *, uint32_t);
|
||||
void OpSsePmulhrsw(struct Machine *, uint32_t);
|
||||
void OpSsePabsb(struct Machine *, uint32_t);
|
||||
void OpSsePabsw(struct Machine *, uint32_t);
|
||||
void OpSsePabsd(struct Machine *, uint32_t);
|
||||
void OpSsePmulld(struct Machine *, uint32_t);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
571
tool/build/lib/ssefloat.c
Normal file
571
tool/build/lib/ssefloat.c
Normal file
|
@ -0,0 +1,571 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/pshufd.h"
|
||||
#include "libc/intrin/pshufhw.h"
|
||||
#include "libc/intrin/pshuflw.h"
|
||||
#include "libc/intrin/pshufw.h"
|
||||
#include "libc/intrin/shufpd.h"
|
||||
#include "libc/intrin/shufps.h"
|
||||
#include "libc/macros.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/modrm.h"
|
||||
#include "tool/build/lib/ssefloat.h"
|
||||
#include "tool/build/lib/throw.h"
|
||||
|
||||
#define SSE_BUILTINS \
|
||||
(!IsModeDbg() && __SSE3__ + 0 && \
|
||||
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 408)
|
||||
|
||||
typedef int int_v _Vector_size(16) aligned(16);
|
||||
typedef long long_v _Vector_size(16) aligned(16);
|
||||
|
||||
static float_v Addps(struct Machine *m, float_v x, float_v y) {
|
||||
return x + y;
|
||||
}
|
||||
|
||||
static double_v Addpd(struct Machine *m, double_v x, double_v y) {
|
||||
return x + y;
|
||||
}
|
||||
|
||||
static float_v Mulps(struct Machine *m, float_v x, float_v y) {
|
||||
return x * y;
|
||||
}
|
||||
|
||||
static double_v Mulpd(struct Machine *m, double_v x, double_v y) {
|
||||
return x * y;
|
||||
}
|
||||
|
||||
static float_v Subps(struct Machine *m, float_v x, float_v y) {
|
||||
return x - y;
|
||||
}
|
||||
|
||||
static double_v Subpd(struct Machine *m, double_v x, double_v y) {
|
||||
return x - y;
|
||||
}
|
||||
|
||||
static float_v Divps(struct Machine *m, float_v x, float_v y) {
|
||||
return x / y;
|
||||
}
|
||||
|
||||
static double_v Divpd(struct Machine *m, double_v x, double_v y) {
|
||||
return x / y;
|
||||
}
|
||||
|
||||
static float_v Andps(struct Machine *m, float_v x, float_v y) {
|
||||
return (float_v)((int_v)x & (int_v)y);
|
||||
}
|
||||
|
||||
static double_v Andpd(struct Machine *m, double_v x, double_v y) {
|
||||
return (double_v)((long_v)x & (long_v)y);
|
||||
}
|
||||
|
||||
static float_v Andnps(struct Machine *m, float_v x, float_v y) {
|
||||
return (float_v)(~(int_v)x & (int_v)y);
|
||||
}
|
||||
|
||||
static double_v Andnpd(struct Machine *m, double_v x, double_v y) {
|
||||
return (double_v)(~(long_v)x & (long_v)y);
|
||||
}
|
||||
|
||||
static float_v Orps(struct Machine *m, float_v x, float_v y) {
|
||||
return (float_v)((int_v)x | (int_v)y);
|
||||
}
|
||||
|
||||
static double_v Orpd(struct Machine *m, double_v x, double_v y) {
|
||||
return (double_v)((long_v)x | (long_v)y);
|
||||
}
|
||||
|
||||
static float_v Xorps(struct Machine *m, float_v x, float_v y) {
|
||||
return (float_v)((int_v)x ^ (int_v)y);
|
||||
}
|
||||
|
||||
static double_v Xorpd(struct Machine *m, double_v x, double_v y) {
|
||||
return (double_v)((long_v)x ^ (long_v)y);
|
||||
}
|
||||
|
||||
static float_v Minps(struct Machine *m, float_v x, float_v y) {
|
||||
#if SSE_BUILTINS
|
||||
return __builtin_ia32_minps(x, y);
|
||||
#else
|
||||
unsigned i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
x[i] = MIN(x[i], y[i]);
|
||||
}
|
||||
return x;
|
||||
#endif
|
||||
}
|
||||
|
||||
static double_v Minpd(struct Machine *m, double_v x, double_v y) {
|
||||
#if SSE_BUILTINS
|
||||
return __builtin_ia32_minpd(x, y);
|
||||
#else
|
||||
unsigned i;
|
||||
for (i = 0; i < 2; ++i) {
|
||||
x[i] = MIN(x[i], y[i]);
|
||||
}
|
||||
return x;
|
||||
#endif
|
||||
}
|
||||
|
||||
static float_v Maxps(struct Machine *m, float_v x, float_v y) {
|
||||
#if SSE_BUILTINS
|
||||
return __builtin_ia32_maxps(x, y);
|
||||
#else
|
||||
unsigned i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
x[i] = MAX(x[i], y[i]);
|
||||
}
|
||||
return x;
|
||||
#endif
|
||||
}
|
||||
|
||||
static double_v Maxpd(struct Machine *m, double_v x, double_v y) {
|
||||
#if SSE_BUILTINS
|
||||
return __builtin_ia32_maxpd(x, y);
|
||||
#else
|
||||
unsigned i;
|
||||
for (i = 0; i < 2; ++i) {
|
||||
x[i] = MAX(x[i], y[i]);
|
||||
}
|
||||
return x;
|
||||
#endif
|
||||
}
|
||||
|
||||
static double_v Haddpd(struct Machine *m, double_v x, double_v y) {
|
||||
#if SSE_BUILTINS
|
||||
return __builtin_ia32_haddpd(x, y);
|
||||
#else
|
||||
return (double_v){x[0] + x[1], y[0] + y[1]};
|
||||
#endif
|
||||
}
|
||||
|
||||
static float_v Haddps(struct Machine *m, float_v x, float_v y) {
|
||||
#if SSE_BUILTINS
|
||||
return __builtin_ia32_haddps(x, y);
|
||||
#else
|
||||
return (float_v){x[0] + x[1], x[2] + x[3], y[0] + y[1], y[2] + y[3]};
|
||||
#endif
|
||||
}
|
||||
|
||||
static double_v Hsubpd(struct Machine *m, double_v x, double_v y) {
|
||||
#if SSE_BUILTINS
|
||||
return __builtin_ia32_hsubpd(x, y);
|
||||
#else
|
||||
return (double_v){x[0] - x[1], y[0] - y[1]};
|
||||
#endif
|
||||
}
|
||||
|
||||
static float_v Hsubps(struct Machine *m, float_v x, float_v y) {
|
||||
#if SSE_BUILTINS
|
||||
return __builtin_ia32_hsubps(x, y);
|
||||
#else
|
||||
return (float_v){x[0] - x[1], x[2] - x[3], y[0] - y[1], y[2] - y[3]};
|
||||
#endif
|
||||
}
|
||||
|
||||
static double_v Addsubpd(struct Machine *m, double_v x, double_v y) {
|
||||
#if SSE_BUILTINS
|
||||
return __builtin_ia32_addsubpd(x, y);
|
||||
#else
|
||||
return (double_v){x[0] - y[0], x[1] + y[1]};
|
||||
#endif
|
||||
}
|
||||
|
||||
static float_v Addsubps(struct Machine *m, float_v x, float_v y) {
|
||||
#if SSE_BUILTINS
|
||||
return __builtin_ia32_addsubps(x, y);
|
||||
#else
|
||||
return (float_v){x[0] - y[0], x[1] + y[1], x[2] - y[2], x[3] + y[3]};
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpUnpcklpsd(struct Machine *m, uint32_t rde) {
|
||||
uint8_t *a, *b;
|
||||
a = XmmRexrReg(m, rde);
|
||||
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:
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
static void Shufps(struct Machine *m, uint32_t rde) {
|
||||
shufps((void *)XmmRexrReg(m, rde), (void *)XmmRexrReg(m, rde),
|
||||
(void *)GetModrmRegisterXmmPointerRead16(m, rde), m->xedd->op.uimm0);
|
||||
}
|
||||
|
||||
static void Shufpd(struct Machine *m, uint32_t rde) {
|
||||
shufpd((void *)XmmRexrReg(m, rde), (void *)XmmRexrReg(m, rde),
|
||||
(void *)GetModrmRegisterXmmPointerRead16(m, rde), m->xedd->op.uimm0);
|
||||
}
|
||||
|
||||
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) {
|
||||
long i;
|
||||
float_v xf;
|
||||
double_v xd;
|
||||
switch (Rep(rde) | Osz(rde)) {
|
||||
case 0:
|
||||
memcpy(&xf, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
for (i = 0; i < 4; ++i) xf[i] = sqrtf(xf[i]);
|
||||
memcpy(XmmRexrReg(m, rde), &xf, 16);
|
||||
break;
|
||||
case 1:
|
||||
memcpy(&xd, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
for (i = 0; i < 2; ++i) xd[i] = sqrt(xd[i]);
|
||||
memcpy(XmmRexrReg(m, rde), &xd, 16);
|
||||
break;
|
||||
case 2:
|
||||
memcpy(&xd, GetModrmRegisterXmmPointerRead8(m, rde), 8);
|
||||
xd[0] = sqrt(xd[0]);
|
||||
memcpy(XmmRexrReg(m, rde), &xd, 8);
|
||||
break;
|
||||
case 3:
|
||||
memcpy(&xf, GetModrmRegisterXmmPointerRead4(m, rde), 4);
|
||||
xf[0] = sqrtf(xf[0]);
|
||||
memcpy(XmmRexrReg(m, rde), &xf, 4);
|
||||
break;
|
||||
default:
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
void OpRsqrtps(struct Machine *m, uint32_t rde) {
|
||||
float_v x;
|
||||
unsigned i;
|
||||
if (Rep(rde) != 3) {
|
||||
memcpy(&x, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
for (i = 0; i < 4; ++i) x[i] = 1.f / sqrtf(x[i]);
|
||||
memcpy(XmmRexrReg(m, rde), &x, 16);
|
||||
} else {
|
||||
memcpy(&x, GetModrmRegisterXmmPointerRead4(m, rde), 4);
|
||||
x[0] = 1.f / sqrtf(x[0]);
|
||||
memcpy(XmmRexrReg(m, rde), &x, 4);
|
||||
}
|
||||
}
|
||||
|
||||
void OpRcpps(struct Machine *m, uint32_t rde) {
|
||||
float_v x;
|
||||
unsigned i;
|
||||
if (Rep(rde) != 3) {
|
||||
memcpy(&x, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
for (i = 0; i < 4; ++i) x[i] = 1.f / x[i];
|
||||
memcpy(XmmRexrReg(m, rde), &x, 16);
|
||||
} else {
|
||||
memcpy(&x, GetModrmRegisterXmmPointerRead4(m, rde), 4);
|
||||
x[0] = 1.f / x[0];
|
||||
memcpy(XmmRexrReg(m, rde), &x, 4);
|
||||
}
|
||||
}
|
||||
|
||||
static void VpsdWpsd(struct Machine *m, uint32_t rde,
|
||||
float_v opf(struct Machine *, float_v, float_v),
|
||||
double_v opd(struct Machine *, double_v, double_v),
|
||||
bool isfloat, bool isdouble) {
|
||||
float_v xf, yf;
|
||||
double_v xd, yd;
|
||||
if (isfloat) {
|
||||
memcpy(&xf, XmmRexrReg(m, rde), 16);
|
||||
memcpy(&yf, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
xf = opf(m, xf, yf);
|
||||
memcpy(XmmRexrReg(m, rde), &xf, 16);
|
||||
} else if (isdouble) {
|
||||
memcpy(&xd, XmmRexrReg(m, rde), 16);
|
||||
memcpy(&yd, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
xd = opd(m, xd, yd);
|
||||
memcpy(XmmRexrReg(m, rde), &xd, 16);
|
||||
} else {
|
||||
OpUd(m, rde);
|
||||
}
|
||||
}
|
||||
|
||||
static void VpsdWpsd66(struct Machine *m, uint32_t rde,
|
||||
float_v opf(struct Machine *, float_v, float_v),
|
||||
double_v opd(struct Machine *, double_v, double_v)) {
|
||||
VpsdWpsd(m, rde, opf, opd, !Osz(rde), Osz(rde));
|
||||
}
|
||||
|
||||
static void VpsdWpsd66f2(struct Machine *m, uint32_t rde,
|
||||
float_v opf(struct Machine *, float_v, float_v),
|
||||
double_v opd(struct Machine *, double_v, double_v)) {
|
||||
VpsdWpsd(m, rde, opf, opd, Rep(rde) == 2, Osz(rde));
|
||||
}
|
||||
|
||||
static void VspsdWspsd(struct Machine *m, uint32_t rde,
|
||||
float_v opf(struct Machine *, float_v, float_v),
|
||||
double_v opd(struct Machine *, double_v, double_v)) {
|
||||
float_v xf, yf;
|
||||
double_v xd, yd;
|
||||
switch (Rep(rde) | Osz(rde)) {
|
||||
case 0:
|
||||
memcpy(&yf, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
memcpy(&xf, XmmRexrReg(m, rde), 16);
|
||||
xf = opf(m, xf, yf);
|
||||
memcpy(XmmRexrReg(m, rde), &xf, 16);
|
||||
break;
|
||||
case 1:
|
||||
memcpy(&yd, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
memcpy(&xd, XmmRexrReg(m, rde), 16);
|
||||
xd = opd(m, xd, yd);
|
||||
memcpy(XmmRexrReg(m, rde), &xd, 16);
|
||||
break;
|
||||
case 2:
|
||||
memcpy(&yd, GetModrmRegisterXmmPointerRead8(m, rde), 8);
|
||||
memcpy(&xd, XmmRexrReg(m, rde), 8);
|
||||
xd = opd(m, xd, yd);
|
||||
memcpy(XmmRexrReg(m, rde), &xd, 8);
|
||||
break;
|
||||
case 3:
|
||||
memcpy(&yf, GetModrmRegisterXmmPointerRead4(m, rde), 4);
|
||||
memcpy(&xf, XmmRexrReg(m, rde), 4);
|
||||
xf = opf(m, xf, yf);
|
||||
memcpy(XmmRexrReg(m, rde), &xf, 4);
|
||||
break;
|
||||
default:
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
void OpComissVsWs(struct Machine *m, uint32_t rde) {
|
||||
float xf, yf;
|
||||
double xd, yd;
|
||||
uint8_t zf, cf, pf, ie;
|
||||
if (!Osz(rde)) {
|
||||
memcpy(&xf, XmmRexrReg(m, rde), 4);
|
||||
memcpy(&yf, GetModrmRegisterXmmPointerRead4(m, rde), 4);
|
||||
if (!isnan(xf) && !isnan(yf)) {
|
||||
zf = xf == yf;
|
||||
cf = xf < yf;
|
||||
pf = false;
|
||||
ie = false;
|
||||
} else {
|
||||
zf = cf = pf = ie = true;
|
||||
}
|
||||
} else {
|
||||
memcpy(&xd, XmmRexrReg(m, rde), 8);
|
||||
memcpy(&yd, GetModrmRegisterXmmPointerRead8(m, rde), 8);
|
||||
if (!isnan(xd) && !isnan(yd)) {
|
||||
zf = xd == yd;
|
||||
cf = xd < yd;
|
||||
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->sse.ie = ie) && !m->sse.im) {
|
||||
HaltMachine(m, kMachineSimdException);
|
||||
}
|
||||
}
|
||||
|
||||
static float_v Cmpps(struct Machine *m, float_v x, float_v y) {
|
||||
long i;
|
||||
switch (m->xedd->op.uimm0) {
|
||||
case 0:
|
||||
return x == y;
|
||||
case 1:
|
||||
return x < y;
|
||||
case 2:
|
||||
return x <= y;
|
||||
case 3:
|
||||
for (i = 0; i < 4; ++i) {
|
||||
x[i] = isnan(x[i]) || isnan(y[i]);
|
||||
}
|
||||
return x;
|
||||
case 4:
|
||||
return x != y;
|
||||
case 5:
|
||||
return x >= y;
|
||||
case 6:
|
||||
return x > y;
|
||||
case 7:
|
||||
for (i = 0; i < 4; ++i) {
|
||||
x[i] = !(isnan(x[i]) || isnan(y[i]));
|
||||
}
|
||||
return x;
|
||||
default:
|
||||
OpUd(m, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static double_v Cmppd(struct Machine *m, double_v x, double_v y) {
|
||||
long i;
|
||||
switch (m->xedd->op.uimm0) {
|
||||
case 0:
|
||||
return x == y;
|
||||
case 1:
|
||||
return x < y;
|
||||
case 2:
|
||||
return x <= y;
|
||||
case 3:
|
||||
for (i = 0; i < 2; ++i) {
|
||||
x[i] = isnan(x[i]) || isnan(y[i]);
|
||||
}
|
||||
return x;
|
||||
case 4:
|
||||
return x != y;
|
||||
case 5:
|
||||
return x >= y;
|
||||
case 6:
|
||||
return x > y;
|
||||
case 7:
|
||||
for (i = 0; i < 2; ++i) {
|
||||
x[i] = !(isnan(x[i]) || isnan(y[i]));
|
||||
}
|
||||
return x;
|
||||
default:
|
||||
OpUd(m, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void OpAddpsd(struct Machine *m, uint32_t rde) {
|
||||
VspsdWspsd(m, rde, Addps, Addpd);
|
||||
}
|
||||
|
||||
void OpMulpsd(struct Machine *m, uint32_t rde) {
|
||||
VspsdWspsd(m, rde, Mulps, Mulpd);
|
||||
}
|
||||
|
||||
void OpSubpsd(struct Machine *m, uint32_t rde) {
|
||||
VspsdWspsd(m, rde, Subps, Subpd);
|
||||
}
|
||||
|
||||
void OpDivpsd(struct Machine *m, uint32_t rde) {
|
||||
VspsdWspsd(m, rde, Divps, Divpd);
|
||||
}
|
||||
|
||||
void OpMinpsd(struct Machine *m, uint32_t rde) {
|
||||
VspsdWspsd(m, rde, Minps, Minpd);
|
||||
}
|
||||
|
||||
void OpMaxpsd(struct Machine *m, uint32_t rde) {
|
||||
VspsdWspsd(m, rde, Maxps, Maxpd);
|
||||
}
|
||||
|
||||
void OpCmppsd(struct Machine *m, uint32_t rde) {
|
||||
VspsdWspsd(m, rde, Cmpps, Cmppd);
|
||||
}
|
||||
|
||||
void OpAndpsd(struct Machine *m, uint32_t rde) {
|
||||
VpsdWpsd66(m, rde, Andps, Andpd);
|
||||
}
|
||||
|
||||
void OpAndnpsd(struct Machine *m, uint32_t rde) {
|
||||
VpsdWpsd66(m, rde, Andnps, Andnpd);
|
||||
}
|
||||
|
||||
void OpOrpsd(struct Machine *m, uint32_t rde) {
|
||||
VpsdWpsd66(m, rde, Orps, Orpd);
|
||||
}
|
||||
|
||||
void OpXorpsd(struct Machine *m, uint32_t rde) {
|
||||
VpsdWpsd66(m, rde, Xorps, Xorpd);
|
||||
}
|
||||
|
||||
void OpHaddpsd(struct Machine *m, uint32_t rde) {
|
||||
VpsdWpsd66f2(m, rde, Haddps, Haddpd);
|
||||
}
|
||||
|
||||
void OpHsubpsd(struct Machine *m, uint32_t rde) {
|
||||
VpsdWpsd66f2(m, rde, Hsubps, Hsubpd);
|
||||
}
|
||||
|
||||
void OpAddsubpsd(struct Machine *m, uint32_t rde) {
|
||||
VpsdWpsd66f2(m, rde, Addsubps, Addsubpd);
|
||||
}
|
37
tool/build/lib/ssefloat.h
Normal file
37
tool/build/lib/ssefloat.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#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) aligned(16);
|
||||
typedef double double_v _Vector_size(16) aligned(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_ */
|
522
tool/build/lib/ssemov.c
Normal file
522
tool/build/lib/ssemov.c
Normal file
|
@ -0,0 +1,522 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/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/ssemov.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);
|
||||
memset(XmmRexrReg(m, rde) + 8, 0, 8);
|
||||
}
|
||||
|
||||
static void MovdVdqEd(struct Machine *m, uint32_t rde) {
|
||||
memset(XmmRexrReg(m, rde), 0, 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);
|
||||
memset(MmReg(m, rde) + 4, 0, 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);
|
||||
memset(XmmRexrReg(m, rde) + 8, 0, 8);
|
||||
}
|
||||
|
||||
static void MovssVpsWps(struct Machine *m, uint32_t rde) {
|
||||
memcpy(XmmRexrReg(m, rde), GetModrmRegisterXmmPointerRead4(m, rde), 4);
|
||||
}
|
||||
|
||||
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) {
|
||||
memcpy(XmmRexrReg(m, rde), GetModrmRegisterXmmPointerRead16(m, rde), 8);
|
||||
}
|
||||
|
||||
static void MovsdWpsVps(struct Machine *m, uint32_t rde) {
|
||||
memcpy(GetModrmRegisterXmmPointerWrite16(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);
|
||||
memset(XmmRexbRm(m, rde) + 8, 0, 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);
|
||||
memset(XmmRexrReg(m, rde) + 8, 0, 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:
|
||||
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:
|
||||
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:
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t pmovmskb(uint64_t x) {
|
||||
return (x & 0x0000000000000080) >> 007 | (x & 0x0000000000008000) >> 016 |
|
||||
(x & 0x0000000000800000) >> 025 | (x & 0x0000000080000000) >> 034 |
|
||||
(x & 0x0000008000000000) >> 043 | (x & 0x0000800000000000) >> 052 |
|
||||
(x & 0x0080000000000000) >> 061 | (x & 0x8000000000000000) >> 070;
|
||||
}
|
||||
|
||||
void OpPmovmskbGdqpNqUdq(struct Machine *m, uint32_t rde) {
|
||||
uint64_t bitmask;
|
||||
if (Osz(rde)) {
|
||||
bitmask = pmovmskb(Read64(XmmRexbRm(m, rde) + 8)) << 8 |
|
||||
pmovmskb(Read64(XmmRexbRm(m, rde)));
|
||||
} else {
|
||||
bitmask = pmovmskb(Read64(MmRm(m, rde) + 8)) << 8 |
|
||||
pmovmskb(Read64(MmRm(m, rde)));
|
||||
}
|
||||
Write64(RegRexrReg(m, rde), bitmask);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
30
tool/build/lib/ssemov.h
Normal file
30
tool/build/lib/ssemov.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
#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_ */
|
|
@ -19,89 +19,167 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/macros.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/stack.h"
|
||||
#include "tool/build/lib/throw.h"
|
||||
|
||||
void Push64(struct Machine *m, uint64_t x) {
|
||||
uint64_t v;
|
||||
void *p[2];
|
||||
uint8_t b[8];
|
||||
v = Read64(m->sp);
|
||||
v -= 8;
|
||||
Write64(m->sp, v);
|
||||
Write64(AccessRam(m, v, 8, p, b, false), x);
|
||||
EndStore(m, v, 8, p, b);
|
||||
}
|
||||
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,
|
||||
};
|
||||
|
||||
void Push16(struct Machine *m, uint16_t x) {
|
||||
uint64_t v;
|
||||
void *p[2];
|
||||
uint8_t b[2];
|
||||
v = Read64(m->sp);
|
||||
v -= 2;
|
||||
Write64(m->sp, v);
|
||||
Write16(b, x);
|
||||
Write64(AccessRam(m, v, 2, p, b, false), x);
|
||||
EndStore(m, v, 2, p, b);
|
||||
}
|
||||
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,
|
||||
};
|
||||
|
||||
uint64_t Pop64(struct Machine *m, uint16_t extra) {
|
||||
void *p[2];
|
||||
uint8_t b[8];
|
||||
uint64_t v, x;
|
||||
v = Read64(m->sp);
|
||||
x = Read64(AccessRam(m, v, 8, p, b, true));
|
||||
Write64(m->sp, v + 8 + extra);
|
||||
return x;
|
||||
}
|
||||
|
||||
uint16_t Pop16(struct Machine *m, uint16_t extra) {
|
||||
void *p[2];
|
||||
uint8_t b[2];
|
||||
uint16_t v, x;
|
||||
v = Read64(m->sp);
|
||||
x = Read16(AccessRam(m, v, 2, p, b, true));
|
||||
Write64(m->sp, v + 2 + extra);
|
||||
return x;
|
||||
}
|
||||
|
||||
static void OpCall(struct Machine *m, uint64_t func) {
|
||||
Push64(m, m->ip);
|
||||
m->ip = func;
|
||||
}
|
||||
|
||||
void OpCallJvds(struct Machine *m) {
|
||||
OpCall(m, m->ip + m->xedd->op.disp);
|
||||
}
|
||||
|
||||
void OpCallEq(struct Machine *m, uint32_t rde) {
|
||||
void *p[2];
|
||||
uint8_t b[8];
|
||||
OpCall(m, Read64(IsModrmRegister(rde)
|
||||
? RegRexbRm(m, rde)
|
||||
: AccessRam(m, ComputeAddress(m, rde), 8, p, b, true)));
|
||||
}
|
||||
|
||||
void OpLeave(struct Machine *m) {
|
||||
memcpy(m->sp, m->bp, sizeof(m->sp));
|
||||
Write64(m->bp, Pop64(m, 0));
|
||||
}
|
||||
|
||||
void OpRet(struct Machine *m, uint16_t n) {
|
||||
m->ip = Pop64(m, n);
|
||||
}
|
||||
|
||||
void PushOsz(struct Machine *m, uint32_t rde, uint64_t x) {
|
||||
if (!Osz(rde)) {
|
||||
Push64(m, x);
|
||||
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 {
|
||||
Push16(m, x);
|
||||
Write32(p, x);
|
||||
}
|
||||
}
|
||||
|
||||
void OpBofram(struct Machine *m) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void Push(struct Machine *m, uint32_t rde, uint64_t x) {
|
||||
uint64_t v;
|
||||
void *p[2];
|
||||
uint8_t b[8];
|
||||
unsigned osz;
|
||||
osz = kStackOsz[m->xedd->op.osz][Mode(rde)];
|
||||
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:
|
||||
unreachable;
|
||||
}
|
||||
WriteStackWord(AccessRam(m, v, osz, p, b, false), rde, osz, x);
|
||||
EndStore(m, v, osz, p, b);
|
||||
}
|
||||
|
||||
void OpPushZvq(struct Machine *m, uint32_t rde) {
|
||||
unsigned osz;
|
||||
osz = kStackOsz[m->xedd->op.osz][Mode(rde)];
|
||||
Push(m, rde, ReadStackWord(RegRexbSrm(m, rde), osz));
|
||||
}
|
||||
|
||||
uint64_t Pop(struct Machine *m, uint32_t rde, uint16_t extra) {
|
||||
uint64_t v;
|
||||
void *p[2];
|
||||
uint8_t b[8];
|
||||
unsigned osz;
|
||||
osz = kStackOsz[m->xedd->op.osz][Mode(rde)];
|
||||
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:
|
||||
unreachable;
|
||||
}
|
||||
return ReadStackWord(AccessRam(m, v, osz, p, b, true), osz);
|
||||
}
|
||||
|
||||
void OpPopZvq(struct Machine *m, uint32_t rde) {
|
||||
uint64_t x;
|
||||
x = Pop(m, rde, 0);
|
||||
switch (kStackOsz[m->xedd->op.osz][Mode(rde)]) {
|
||||
case 8:
|
||||
case 4:
|
||||
Write64(RegRexbSrm(m, rde), x);
|
||||
break;
|
||||
case 2:
|
||||
Write16(RegRexbSrm(m, rde), x);
|
||||
break;
|
||||
default:
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
static void OpCall(struct Machine *m, uint32_t rde, uint64_t func) {
|
||||
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:
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
void OpRet(struct Machine *m, uint32_t rde, uint16_t n) {
|
||||
m->ip = Pop(m, rde, n);
|
||||
}
|
||||
|
||||
void OpBofram(struct Machine *m, uint32_t rde) {
|
||||
if (m->xedd->op.disp) {
|
||||
m->bofram[0] = m->ip;
|
||||
m->bofram[1] = m->ip + (m->xedd->op.disp & 0xff);
|
||||
|
@ -110,3 +188,105 @@ void OpBofram(struct Machine *m) {
|
|||
m->bofram[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
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 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 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));
|
||||
}
|
||||
|
||||
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:
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
static 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 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);
|
||||
}
|
||||
|
||||
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:
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,16 +4,22 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
void Push64(struct Machine *, uint64_t);
|
||||
uint64_t Pop64(struct Machine *, uint16_t);
|
||||
void Push16(struct Machine *, uint16_t);
|
||||
uint16_t Pop16(struct Machine *, uint16_t);
|
||||
void OpCallJvds(struct Machine *);
|
||||
void OpRet(struct Machine *, uint16_t);
|
||||
void OpLeave(struct Machine *);
|
||||
void PushOsz(struct Machine *, uint32_t, uint64_t);
|
||||
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, uint16_t);
|
||||
void OpLeave(struct Machine *, uint32_t);
|
||||
void OpCallEq(struct Machine *, uint32_t);
|
||||
void OpBofram(struct Machine *);
|
||||
void OpBofram(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);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include "libc/log/log.h"
|
||||
#include "libc/macros.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"
|
||||
|
@ -55,7 +57,7 @@ static void WriteInt(uint8_t p[8], uint64_t x, unsigned long w) {
|
|||
Write16(p, x);
|
||||
break;
|
||||
case 2:
|
||||
Write64(p, x);
|
||||
Write64(p, x & 0xffffffff);
|
||||
break;
|
||||
case 3:
|
||||
Write64(p, x);
|
||||
|
@ -65,164 +67,220 @@ static void WriteInt(uint8_t p[8], uint64_t x, unsigned long w) {
|
|||
}
|
||||
}
|
||||
|
||||
void OpString(struct Machine *m, uint32_t rde, int op) {
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
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;
|
||||
uint64_t asz;
|
||||
bool compare;
|
||||
int64_t sgn, v;
|
||||
uint8_t s[3][8];
|
||||
sgn = GetFlag(m->flags, FLAGS_DF) ? -1 : 1;
|
||||
asz = Asz(rde) ? 0xffffffff : 0xffffffffffffffff;
|
||||
stop = false;
|
||||
n = 1 << RegLog2(rde);
|
||||
for (;;) {
|
||||
if (Rep(rde) && !Read64(m->cx)) break;
|
||||
v = 0;
|
||||
*p = NULL;
|
||||
compare = false;
|
||||
sgn = GetFlag(m->flags, FLAGS_DF) ? -1 : 1;
|
||||
do {
|
||||
if (Rep(rde) && !ReadCx(m, rde)) break;
|
||||
switch (op) {
|
||||
case STRING_CMPS:
|
||||
Alu(RegLog2(rde), ALU_SUB,
|
||||
ReadInt(Load(m, (Read64(m->si) + GetSegment(m)) & asz, n, s[2]),
|
||||
RegLog2(rde)),
|
||||
ReadInt(Load(m, Read64(m->di) & asz, n, s[1]), RegLog2(rde)),
|
||||
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);
|
||||
Write64(m->di, (Read64(m->di) + sgn * n) & asz);
|
||||
Write64(m->si, (Read64(m->si) + sgn * n) & asz);
|
||||
compare = true;
|
||||
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 = Read64(m->di) & asz), n, p, s[0]),
|
||||
Load(m, (Read64(m->si) + GetSegment(m)) & asz, n, s[1]), n);
|
||||
Write64(m->di, (Read64(m->di) + sgn * n) & asz);
|
||||
Write64(m->si, (Read64(m->si) + sgn * n) & asz);
|
||||
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 = Read64(m->di) & asz), n, p, s[0]), m->ax, n);
|
||||
Write64(m->di, (Read64(m->di) + sgn * n) & asz);
|
||||
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, (Read64(m->si) + GetSegment(m)) & asz, n, s[1]),
|
||||
n);
|
||||
Write64(m->si, (Read64(m->si) + sgn * n) & asz);
|
||||
memcpy(m->ax, Load(m, AddressSi(m, rde), n, s[1]), n);
|
||||
AddSi(m, rde, sgn * n);
|
||||
break;
|
||||
case STRING_SCAS:
|
||||
Alu(RegLog2(rde), ALU_SUB,
|
||||
ReadInt(Load(m, Read64(m->di) & asz, n, s[1]), RegLog2(rde)),
|
||||
kAlu[ALU_SUB][RegLog2(rde)](
|
||||
ReadInt(Load(m, AddressDi(m, rde), n, s[1]), RegLog2(rde)),
|
||||
ReadInt(m->ax, RegLog2(rde)), &m->flags);
|
||||
Write64(m->di, (Read64(m->di) + sgn * n) & asz);
|
||||
compare = true;
|
||||
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, (Read64(m->si) + GetSegment(m)) & asz, n, s[1]),
|
||||
RegLog2(rde)));
|
||||
Write64(m->si, (Read64(m->si) + sgn * n) & asz);
|
||||
ReadInt(Load(m, AddressSi(m, rde), n, s[1]), RegLog2(rde)));
|
||||
AddSi(m, rde, sgn * n);
|
||||
break;
|
||||
case STRING_INS:
|
||||
WriteInt(BeginStore(m, (v = Read64(m->di) & asz), n, p, s[0]),
|
||||
WriteInt(BeginStore(m, (v = AddressDi(m, rde)), n, p, s[0]),
|
||||
OpIn(m, Read16(m->dx)), RegLog2(rde));
|
||||
Write64(m->di, (Read64(m->di) + sgn * n) & asz);
|
||||
AddDi(m, rde, sgn * n);
|
||||
EndStore(m, v, n, p, s[0]);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
EndStore(m, v, n, p, s[0]);
|
||||
if (!Rep(rde)) break;
|
||||
Write64(m->cx, Read64(m->cx) - 1);
|
||||
if (compare) {
|
||||
if (Rep(rde) == 2 && GetFlag(m->flags, FLAGS_ZF)) break;
|
||||
if (Rep(rde) == 3 && !GetFlag(m->flags, FLAGS_ZF)) break;
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
||||
void OpRepMovsbEnhanced(struct Machine *m, uint32_t rde) {
|
||||
bool failed;
|
||||
uint8_t *direal, *sireal;
|
||||
unsigned diremain, siremain, i, n;
|
||||
uint64_t divirtual, sivirtual, diactual, siactual, failaddr, asz, cx;
|
||||
if (!(cx = Read64(m->cx))) return;
|
||||
failed = false;
|
||||
failaddr = 0;
|
||||
asz = Asz(rde) ? 0xffffffff : 0xffffffffffffffff;
|
||||
divirtual = Read64(m->di) & asz;
|
||||
sivirtual = Read64(m->si) & asz;
|
||||
SetWriteAddr(m, (GetSegment(m) + divirtual) & asz, cx);
|
||||
SetReadAddr(m, (GetSegment(m) + sivirtual) & asz, cx);
|
||||
do {
|
||||
diactual = (GetSegment(m) + divirtual) & asz;
|
||||
siactual = (GetSegment(m) + sivirtual) & asz;
|
||||
if (!(direal = FindReal(m, diactual))) {
|
||||
failaddr = diactual;
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
if (!(sireal = FindReal(m, siactual))) {
|
||||
failaddr = siactual;
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
diremain = 0x1000 - (divirtual & 0xfff);
|
||||
siremain = 0x1000 - (sivirtual & 0xfff);
|
||||
n = MIN(cx, MIN(diremain, siremain));
|
||||
for (i = 0; i < n; ++i) {
|
||||
direal[i] = sireal[i];
|
||||
}
|
||||
cx -= n;
|
||||
divirtual = (divirtual + n) & asz;
|
||||
sivirtual = (sivirtual + n) & asz;
|
||||
} while (cx);
|
||||
Write64(m->cx, cx);
|
||||
Write64(m->di, divirtual);
|
||||
Write64(m->si, sivirtual);
|
||||
if (failed) ThrowSegmentationFault(m, failaddr);
|
||||
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 OpRepStosbEnhanced(struct Machine *m, uint32_t rde) {
|
||||
bool failed;
|
||||
uint8_t *direal, al;
|
||||
unsigned diremain, i, n;
|
||||
uint64_t divirtual, diactual, failaddr, asz, cx;
|
||||
if (!(cx = Read64(m->cx))) return;
|
||||
failaddr = 0;
|
||||
failed = false;
|
||||
al = Read8(m->ax);
|
||||
asz = Asz(rde) ? 0xffffffff : 0xffffffffffffffff;
|
||||
divirtual = Read64(m->di) & asz;
|
||||
SetWriteAddr(m, (GetSegment(m) + divirtual) & asz, cx);
|
||||
do {
|
||||
diactual = (GetSegment(m) + divirtual) & asz;
|
||||
if (!(direal = FindReal(m, diactual))) {
|
||||
failaddr = diactual;
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
diremain = 0x1000 - (divirtual & 0xfff);
|
||||
n = MIN(cx, diremain);
|
||||
for (i = 0; i < n; ++i) {
|
||||
direal[i] = al;
|
||||
}
|
||||
cx -= n;
|
||||
divirtual = (divirtual + n) & asz;
|
||||
} while (cx);
|
||||
Write64(m->cx, cx);
|
||||
Write64(m->di, divirtual);
|
||||
if (failed) ThrowSegmentationFault(m, failaddr);
|
||||
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)) {
|
||||
OpRepMovsbEnhanced(m, rde);
|
||||
RepMovsbEnhanced(m, rde);
|
||||
} else {
|
||||
OpString(m, rde, STRING_MOVS);
|
||||
OpMovs(m, rde);
|
||||
}
|
||||
}
|
||||
|
||||
void OpStosb(struct Machine *m, uint32_t rde) {
|
||||
if (Rep(rde) && !GetFlag(m->flags, FLAGS_DF)) {
|
||||
OpRepStosbEnhanced(m, rde);
|
||||
RepStosbEnhanced(m, rde);
|
||||
} else {
|
||||
OpString(m, rde, STRING_STOS);
|
||||
OpStos(m, rde);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,9 +13,15 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
void OpString(struct Machine *, uint32_t, int);
|
||||
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) */
|
||||
|
|
|
@ -20,11 +20,13 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/calls/struct/sigaction-linux.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
|
@ -33,8 +35,12 @@
|
|||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/af.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/fd.h"
|
||||
#include "libc/sysv/consts/ipproto.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/msync.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
@ -42,7 +48,10 @@
|
|||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/consts/so.h"
|
||||
#include "libc/sysv/consts/sock.h"
|
||||
#include "libc/sysv/consts/sol.h"
|
||||
#include "libc/sysv/consts/tcp.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/time/struct/timezone.h"
|
||||
#include "libc/time/time.h"
|
||||
|
@ -56,7 +65,8 @@
|
|||
#include "tool/build/lib/throw.h"
|
||||
#include "tool/build/lib/xlaterrno.h"
|
||||
|
||||
#define AT_FDCWD_LINUX -100
|
||||
#define AT_FDCWD_LINUX -100
|
||||
#define TIOCGWINSZ_LINUX 0x5413
|
||||
|
||||
#define POINTER(x) ((void *)(intptr_t)(x))
|
||||
#define UNPOINTER(x) ((int64_t)(intptr_t)(x))
|
||||
|
@ -70,6 +80,7 @@ const struct MachineFdCb kMachineFdCbHost = {
|
|||
.close = close,
|
||||
.read = read,
|
||||
.write = write,
|
||||
.ioctl = ioctl,
|
||||
};
|
||||
|
||||
static int XlatSignal(int sig) {
|
||||
|
@ -107,7 +118,76 @@ static int XlatSignal(int sig) {
|
|||
XLAT(30, SIGPWR);
|
||||
XLAT(0x10, SIGSTKFLT);
|
||||
default:
|
||||
return sig;
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
||||
static int XlatSig(int x) {
|
||||
switch (x) {
|
||||
XLAT(0, SIG_BLOCK);
|
||||
XLAT(1, SIG_UNBLOCK);
|
||||
XLAT(2, SIG_SETMASK);
|
||||
default:
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
||||
static int XlatSocketFamily(int x) {
|
||||
switch (x) {
|
||||
XLAT(0, AF_INET);
|
||||
XLAT(2, AF_INET);
|
||||
default:
|
||||
return epfnosupport();
|
||||
}
|
||||
}
|
||||
|
||||
static int XlatSocketType(int x) {
|
||||
switch (x) {
|
||||
XLAT(1, SOCK_STREAM);
|
||||
XLAT(2, SOCK_DGRAM);
|
||||
default:
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
||||
static int XlatSocketProtocol(int x) {
|
||||
switch (x) {
|
||||
XLAT(6, IPPROTO_TCP);
|
||||
XLAT(17, IPPROTO_UDP);
|
||||
default:
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned XlatSocketFlags(int flags) {
|
||||
unsigned res = 0;
|
||||
if (flags & 0x080000) res |= SOCK_CLOEXEC;
|
||||
if (flags & 0x000800) res |= SOCK_NONBLOCK;
|
||||
return res;
|
||||
}
|
||||
|
||||
static int XlatSocketLevel(int x) {
|
||||
switch (x) {
|
||||
XLAT(0, SOL_IP);
|
||||
XLAT(1, SOL_SOCKET);
|
||||
XLAT(6, SOL_TCP);
|
||||
XLAT(17, SOL_UDP);
|
||||
default:
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
||||
static int XlatSocketOptname(int x) {
|
||||
switch (x) {
|
||||
XLAT(2, SO_REUSEADDR);
|
||||
XLAT(15, SO_REUSEPORT);
|
||||
XLAT(9, SO_KEEPALIVE);
|
||||
XLAT(5, SO_DONTROUTE);
|
||||
XLAT(7, SO_SNDBUF);
|
||||
XLAT(8, SO_RCVBUF);
|
||||
XLAT(13, SO_LINGER);
|
||||
default:
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,12 +210,12 @@ static int XlatAccess(int x) {
|
|||
|
||||
static int XlatSigaction(int x) {
|
||||
unsigned res = 0;
|
||||
if (x & 0x00000001) res |= SA_NOCLDSTOP;
|
||||
if (x & 0x00000002) res |= SA_NOCLDWAIT;
|
||||
if (x & 0x00000004) res |= SA_SIGINFO;
|
||||
if (x & 0x04000000) res |= SA_RESTORER;
|
||||
if (x & 0x08000000) res |= SA_ONSTACK;
|
||||
if (x & 0x10000000) res |= SA_RESTART;
|
||||
if (x & 1) res |= SA_NOCLDSTOP;
|
||||
if (x & 2) res |= SA_NOCLDWAIT;
|
||||
if (x & 4) res |= SA_SIGINFO;
|
||||
if (x & 0x40000000) res |= SA_NODEFER;
|
||||
if (x & 0x40000000) res |= SA_NOMASK;
|
||||
if (x & 0x80000000) res |= SA_RESETHAND;
|
||||
|
@ -242,6 +322,26 @@ static unsigned XlatOpenFlags(unsigned flags) {
|
|||
return res;
|
||||
}
|
||||
|
||||
static int XlatFcntlCmd(int cmd) {
|
||||
switch (cmd) {
|
||||
XLAT(1, F_GETFD);
|
||||
XLAT(2, F_SETFD);
|
||||
XLAT(3, F_GETFL);
|
||||
XLAT(4, F_SETFL);
|
||||
default:
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
||||
static int XlatFcntlArg(int arg) {
|
||||
switch (arg) {
|
||||
XLAT(0, 0);
|
||||
XLAT(1, FD_CLOEXEC);
|
||||
default:
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
||||
static struct sigaction *CoerceSigactionToCosmo(
|
||||
struct sigaction *dst, const struct sigaction$linux *src) {
|
||||
if (!src) return NULL;
|
||||
|
@ -311,6 +411,36 @@ static void *GetDirectBuf(struct Machine *m, int64_t addr, size_t *size) {
|
|||
return page;
|
||||
}
|
||||
|
||||
static struct iovec *GetDirectIov(struct Machine *m, int64_t addr, int *len) {
|
||||
int i;
|
||||
size_t n, size;
|
||||
struct iovec *iov;
|
||||
if (!__builtin_mul_overflow(sizeof(*iov), *len, &n) && n <= 0x7ffff000) {
|
||||
if ((iov = malloc(n))) {
|
||||
VirtualSend(m, iov, addr, n);
|
||||
SetReadAddr(m, addr, n);
|
||||
for (i = 0; i < *len; ++i) {
|
||||
size = iov[i].iov_len;
|
||||
if ((iov[i].iov_base = GetDirectBuf(
|
||||
m, (int64_t)(intptr_t)iov[i].iov_base, &size)) == MAP_FAILED) {
|
||||
free(iov);
|
||||
return (struct iovec *)efault();
|
||||
}
|
||||
if (size < iov[i].iov_len) {
|
||||
iov[i].iov_len = size;
|
||||
*len = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return iov;
|
||||
} else {
|
||||
return (struct iovec *)-1;
|
||||
}
|
||||
} else {
|
||||
return (struct iovec *)eoverflow();
|
||||
}
|
||||
}
|
||||
|
||||
static int OpClose(struct Machine *m, int fd) {
|
||||
int rc;
|
||||
struct FdClosed *closed;
|
||||
|
@ -356,6 +486,124 @@ static int OpPipe(struct Machine *m, int64_t pipefds_addr) {
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int OpDup(struct Machine *m, int fd) {
|
||||
int i, rc;
|
||||
if ((fd = XlatFd(m, fd)) == -1) return -1;
|
||||
if ((i = MachineFdAdd(&m->fds)) == -1) return -1;
|
||||
if ((rc = dup(fd)) != -1) {
|
||||
m->fds.p[i].cb = &kMachineFdCbHost;
|
||||
m->fds.p[i].fd = rc;
|
||||
rc = i;
|
||||
} else {
|
||||
MachineFdRemove(&m->fds, i);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int OpDup2(struct Machine *m, int fd, int newfd) {
|
||||
int i, rc;
|
||||
if ((fd = XlatFd(m, fd)) == -1) return -1;
|
||||
if ((0 <= newfd && newfd < m->fds.i)) {
|
||||
if ((rc = dup2(fd, m->fds.p[newfd].fd)) != -1) {
|
||||
m->fds.p[newfd].cb = &kMachineFdCbHost;
|
||||
m->fds.p[newfd].fd = rc;
|
||||
rc = newfd;
|
||||
}
|
||||
} else if ((i = MachineFdAdd(&m->fds)) != -1) {
|
||||
if ((rc = dup(fd)) != -1) {
|
||||
m->fds.p[i].cb = &kMachineFdCbHost;
|
||||
m->fds.p[i].fd = rc;
|
||||
rc = i;
|
||||
}
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int OpSocket(struct Machine *m, int family, int type, int protocol) {
|
||||
int i, fd;
|
||||
if ((family = XlatSocketFamily(family)) == -1) return -1;
|
||||
if ((type = XlatSocketType(type)) == -1) return -1;
|
||||
if ((protocol = XlatSocketProtocol(protocol)) == -1) return -1;
|
||||
if ((i = MachineFdAdd(&m->fds)) == -1) return -1;
|
||||
if ((fd = socket(family, type, protocol)) != -1) {
|
||||
m->fds.p[i].cb = &kMachineFdCbHost;
|
||||
m->fds.p[i].fd = fd;
|
||||
fd = i;
|
||||
} else {
|
||||
MachineFdRemove(&m->fds, i);
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int OpAccept4(struct Machine *m, int fd, int64_t addraddr,
|
||||
int64_t addrsizeaddr, int flags) {
|
||||
int i, rc;
|
||||
void *addr;
|
||||
uint8_t b[4];
|
||||
uint32_t addrsize;
|
||||
if ((fd = XlatFd(m, fd)) == -1) return -1;
|
||||
VirtualSend(m, b, addrsizeaddr, 4);
|
||||
SetReadAddr(m, addrsizeaddr, 4);
|
||||
addrsize = Read32(b);
|
||||
if (!(addr = malloc(addrsize))) return -1;
|
||||
if ((i = rc = MachineFdAdd(&m->fds)) != -1) {
|
||||
if ((rc = accept4(fd, addr, &addrsize, XlatSocketFlags(flags))) != -1) {
|
||||
Write32(b, addrsize);
|
||||
VirtualRecv(m, addrsizeaddr, b, 4);
|
||||
VirtualRecv(m, addraddr, addr, addrsize);
|
||||
SetWriteAddr(m, addraddr, addrsize);
|
||||
m->fds.p[i].cb = &kMachineFdCbHost;
|
||||
m->fds.p[i].fd = rc;
|
||||
rc = i;
|
||||
} else {
|
||||
MachineFdRemove(&m->fds, i);
|
||||
}
|
||||
}
|
||||
free(addr);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int OpConnectBind(struct Machine *m, int fd, intptr_t addraddr,
|
||||
uint32_t addrsize,
|
||||
int impl(int, const void *, uint32_t)) {
|
||||
int rc;
|
||||
void *addr;
|
||||
if ((fd = XlatFd(m, fd)) == -1) return -1;
|
||||
if (!(addr = malloc(addrsize))) return -1;
|
||||
VirtualSend(m, addr, addraddr, addrsize);
|
||||
SetReadAddr(m, addraddr, addrsize);
|
||||
rc = impl(fd, addr, addrsize);
|
||||
free(addr);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int OpBind(struct Machine *m, int fd, intptr_t addraddr,
|
||||
uint32_t addrsize) {
|
||||
return OpConnectBind(m, fd, addraddr, addrsize, bind);
|
||||
}
|
||||
|
||||
static int OpConnect(struct Machine *m, int fd, int64_t addraddr,
|
||||
uint32_t addrsize) {
|
||||
return OpConnectBind(m, fd, addraddr, addrsize, connect);
|
||||
}
|
||||
|
||||
static int OpSetsockopt(struct Machine *m, int fd, int level, int optname,
|
||||
int64_t optvaladdr, uint32_t optvalsize) {
|
||||
int rc;
|
||||
void *optval;
|
||||
if ((level = XlatSocketLevel(level)) == -1) return -1;
|
||||
if ((optname = XlatSocketOptname(optname)) == -1) return -1;
|
||||
if ((fd = XlatFd(m, fd)) == -1) return -1;
|
||||
if (!(optval = malloc(optvalsize))) return -1;
|
||||
VirtualSend(m, optval, optvaladdr, optvalsize);
|
||||
SetReadAddr(m, optvaladdr, optvalsize);
|
||||
rc = setsockopt(fd, level, optname, optval, optvalsize);
|
||||
free(optval);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t OpRead(struct Machine *m, int fd, int64_t addr, size_t size) {
|
||||
void *data;
|
||||
ssize_t rc;
|
||||
|
@ -378,6 +626,22 @@ static ssize_t OpWrite(struct Machine *m, int fd, int64_t addr, size_t size) {
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int OpIoctl(struct Machine *m, int fd, uint64_t request,
|
||||
int64_t memaddr) {
|
||||
int rc;
|
||||
struct winsize ws;
|
||||
if (!(0 <= fd && fd < m->fds.i) || !m->fds.p[fd].cb) return ebadf();
|
||||
switch (request) {
|
||||
case TIOCGWINSZ_LINUX:
|
||||
rc = (m->fds.p[fd].cb->ioctl)(m->fds.p[fd].fd, TIOCGWINSZ, &ws);
|
||||
VirtualRecv(m, memaddr, &ws, sizeof(ws));
|
||||
SetWriteAddr(m, memaddr, sizeof(ws));
|
||||
return rc;
|
||||
default:
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t OpPread(struct Machine *m, int fd, int64_t addr, size_t size,
|
||||
int64_t offset) {
|
||||
void *data;
|
||||
|
@ -398,6 +662,37 @@ static ssize_t OpPwrite(struct Machine *m, int fd, int64_t addr, size_t size,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t OpReadv(struct Machine *m, int fd, int64_t iovaddr, int iovlen) {
|
||||
ssize_t rc;
|
||||
struct iovec *iov;
|
||||
if ((fd = XlatFd(m, fd)) == -1) return -1;
|
||||
if ((iov = GetDirectIov(m, iovaddr, &iovlen)) == MAP_FAILED) return -1;
|
||||
rc = readv(fd, iov, iovlen);
|
||||
free(iov);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t OpWritev(struct Machine *m, int fd, int64_t iovaddr,
|
||||
int iovlen) {
|
||||
ssize_t rc;
|
||||
struct iovec *iov;
|
||||
if ((fd = XlatFd(m, fd)) == -1) return -1;
|
||||
if ((iov = GetDirectIov(m, iovaddr, &iovlen)) == MAP_FAILED) return -1;
|
||||
rc = writev(fd, iov, iovlen);
|
||||
free(iov);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int64_t OpLseek(struct Machine *m, int fd, int64_t offset, int whence) {
|
||||
if ((fd = XlatFd(m, fd)) == -1) return -1;
|
||||
return lseek(fd, offset, whence);
|
||||
}
|
||||
|
||||
static ssize_t OpFtruncate(struct Machine *m, int fd, int64_t size) {
|
||||
if ((fd = XlatFd(m, fd)) == -1) return -1;
|
||||
return ftruncate(fd, size);
|
||||
}
|
||||
|
||||
static int OpFaccessat(struct Machine *m, int dirfd, int64_t path, int mode,
|
||||
int flags) {
|
||||
flags = XlatAtf(flags);
|
||||
|
@ -436,6 +731,38 @@ static int OpFstat(struct Machine *m, int fd, int64_t st) {
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int OpListen(struct Machine *m, int fd, int backlog) {
|
||||
if ((fd = XlatFd(m, fd)) == -1) return -1;
|
||||
return listen(fd, backlog);
|
||||
}
|
||||
|
||||
static int OpShutdown(struct Machine *m, int fd, int how) {
|
||||
if ((fd = XlatFd(m, fd)) == -1) return -1;
|
||||
return shutdown(fd, how);
|
||||
}
|
||||
|
||||
static int OpFsync(struct Machine *m, int fd) {
|
||||
if ((fd = XlatFd(m, fd)) == -1) return -1;
|
||||
return fsync(fd);
|
||||
}
|
||||
|
||||
static int OpFdatasync(struct Machine *m, int fd) {
|
||||
if ((fd = XlatFd(m, fd)) == -1) return -1;
|
||||
return fdatasync(fd);
|
||||
}
|
||||
|
||||
static int OpFchmod(struct Machine *m, int fd, uint32_t mode) {
|
||||
if ((fd = XlatFd(m, fd)) == -1) return -1;
|
||||
return fchmod(fd, mode);
|
||||
}
|
||||
|
||||
static int OpFcntl(struct Machine *m, int fd, int cmd, int arg) {
|
||||
if ((cmd = XlatFcntlCmd(cmd)) == -1) return -1;
|
||||
if ((arg = XlatFcntlArg(arg)) == -1) return -1;
|
||||
if ((fd = XlatFd(m, fd)) == -1) return -1;
|
||||
return fcntl(fd, cmd, arg);
|
||||
}
|
||||
|
||||
static int OpChdir(struct Machine *m, int64_t path) {
|
||||
return chdir(LoadStr(m, path));
|
||||
}
|
||||
|
@ -477,6 +804,15 @@ static int OpChmod(struct Machine *m, int64_t path, uint32_t mode) {
|
|||
return chmod(LoadStr(m, path), mode);
|
||||
}
|
||||
|
||||
static int OpFork(struct Machine *m) {
|
||||
return enosys();
|
||||
}
|
||||
|
||||
static int OpExecve(struct Machine *m, int64_t programaddr, int64_t argvaddr,
|
||||
int64_t envpaddr) {
|
||||
return enosys();
|
||||
}
|
||||
|
||||
static int64_t OpGetcwd(struct Machine *m, int64_t bufaddr, size_t size) {
|
||||
size_t n;
|
||||
char *buf;
|
||||
|
@ -496,6 +832,7 @@ static int64_t OpGetcwd(struct Machine *m, int64_t bufaddr, size_t size) {
|
|||
}
|
||||
|
||||
static int OpSigaction(struct Machine *m, int sig, int64_t act, int64_t old) {
|
||||
return 0;
|
||||
int rc;
|
||||
struct OpSigactionMemory {
|
||||
struct sigaction act, old;
|
||||
|
@ -560,6 +897,44 @@ static int OpGettimeofday(struct Machine *m, int64_t tv, int64_t tz) {
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int OpPoll(struct Machine *m, int64_t fdsaddr, uint64_t nfds,
|
||||
int32_t timeout_ms) {
|
||||
int rc;
|
||||
size_t n;
|
||||
struct pollfd *fds;
|
||||
if (!__builtin_mul_overflow(sizeof(*fds), nfds, &n) && n <= 0x7ffff000) {
|
||||
if ((fds = malloc(n))) {
|
||||
VirtualSend(m, fds, fdsaddr, n);
|
||||
SetReadAddr(m, fdsaddr, n);
|
||||
rc = poll(fds, nfds, timeout_ms);
|
||||
free(fds);
|
||||
return rc;
|
||||
} else {
|
||||
return enomem();
|
||||
}
|
||||
} else {
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
||||
static int OpSigprocmask(struct Machine *m, int how, int64_t setaddr,
|
||||
int64_t oldsetaddr) {
|
||||
int rc;
|
||||
sigset_t *set, oldset, ss;
|
||||
if (setaddr) {
|
||||
set = &ss;
|
||||
memset(set, 0, sizeof(ss));
|
||||
VirtualSend(m, set, setaddr, 8);
|
||||
} else {
|
||||
set = NULL;
|
||||
}
|
||||
if ((rc = sigprocmask(XlatSig(how), set, &oldset)) != -1) {
|
||||
if (setaddr) VirtualRecv(m, setaddr, set, 8);
|
||||
if (oldsetaddr) VirtualRecv(m, oldsetaddr, &oldset, 8);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int DoOpen(struct Machine *m, int64_t path, int flags, int mode) {
|
||||
return OpOpenat(m, AT_FDCWD_LINUX, path, flags, mode);
|
||||
}
|
||||
|
@ -580,15 +955,20 @@ static int DoLstat(struct Machine *m, int64_t path, int64_t st) {
|
|||
return OpFstatat(m, AT_FDCWD_LINUX, path, st, 0x0400);
|
||||
}
|
||||
|
||||
void OpSyscall(struct Machine *m) {
|
||||
static int DoAccept(struct Machine *m, int fd, int64_t addraddr,
|
||||
int64_t addrsizeaddr) {
|
||||
return OpAccept4(m, fd, addraddr, addrsizeaddr, 0);
|
||||
}
|
||||
|
||||
void OpSyscall(struct Machine *m, uint32_t rde) {
|
||||
uint64_t i, ax, di, si, dx, r0, r8, r9;
|
||||
ax = Read64(m->ax);
|
||||
di = Read64(m->di);
|
||||
si = Read64(m->si);
|
||||
dx = Read64(m->dx);
|
||||
r0 = Read32(m->r10);
|
||||
r8 = Read32(m->r8);
|
||||
r9 = Read32(m->r9);
|
||||
r0 = Read64(m->r10);
|
||||
r8 = Read64(m->r8);
|
||||
r9 = Read64(m->r9);
|
||||
switch (ax & 0x1ff) {
|
||||
SYSCALL(0x000, OpRead(m, di, si, dx));
|
||||
SYSCALL(0x001, OpWrite(m, di, si, dx));
|
||||
|
@ -597,26 +977,26 @@ void OpSyscall(struct Machine *m) {
|
|||
SYSCALL(0x004, DoStat(m, di, si));
|
||||
SYSCALL(0x005, OpFstat(m, di, si));
|
||||
SYSCALL(0x006, DoLstat(m, di, si));
|
||||
SYSCALL(0x007, poll(PNN(di), si, dx));
|
||||
SYSCALL(0x008, lseek(di, si, dx));
|
||||
SYSCALL(0x007, OpPoll(m, di, si, dx));
|
||||
SYSCALL(0x008, OpLseek(m, di, si, dx));
|
||||
SYSCALL(0x009, OpMmap(m, di, si, dx, r0, r8, r9));
|
||||
SYSCALL(0x01A, OpMsync(m, di, si, dx));
|
||||
SYSCALL(0x00A, OpMprotect(m, di, si, dx));
|
||||
SYSCALL(0x00B, OpMunmap(m, di, si));
|
||||
SYSCALL(0x00D, OpSigaction(m, di, si, dx));
|
||||
SYSCALL(0x00E, sigprocmask(di, P(si), P(dx)));
|
||||
SYSCALL(0x010, ioctl(di, si, P(dx)));
|
||||
SYSCALL(0x00E, OpSigprocmask(m, di, si, dx));
|
||||
SYSCALL(0x010, OpIoctl(m, di, si, dx));
|
||||
SYSCALL(0x011, OpPread(m, di, si, dx, r0));
|
||||
SYSCALL(0x012, OpPwrite(m, di, si, dx, r0));
|
||||
SYSCALL(0x013, readv(di, P(si), dx));
|
||||
SYSCALL(0x014, writev(di, P(si), dx));
|
||||
SYSCALL(0x013, OpReadv(m, di, si, dx));
|
||||
SYSCALL(0x014, OpWritev(m, di, si, dx));
|
||||
SYSCALL(0x015, DoAccess(m, di, si));
|
||||
SYSCALL(0x016, OpPipe(m, di));
|
||||
SYSCALL(0x017, select(di, P(si), P(dx), P(r0), P(r8)));
|
||||
SYSCALL(0x018, sched_yield());
|
||||
SYSCALL(0x01C, OpMadvise(m, di, si, dx));
|
||||
SYSCALL(0x020, dup(di));
|
||||
SYSCALL(0x021, dup2(di, si));
|
||||
SYSCALL(0x020, OpDup(m, di));
|
||||
SYSCALL(0x021, OpDup2(m, di, si));
|
||||
SYSCALL(0x022, pause());
|
||||
SYSCALL(0x023, OpNanosleep(m, di, si));
|
||||
SYSCALL(0x024, getitimer(di, PNN(si)));
|
||||
|
@ -624,29 +1004,29 @@ void OpSyscall(struct Machine *m) {
|
|||
SYSCALL(0x026, setitimer(di, PNN(si), P(dx)));
|
||||
SYSCALL(0x027, getpid());
|
||||
SYSCALL(0x028, sendfile(di, si, P(dx), r0));
|
||||
SYSCALL(0x029, socket(di, si, dx));
|
||||
SYSCALL(0x02A, connect(di, PNN(si), dx));
|
||||
SYSCALL(0x02B, accept(di, PNN(di), PNN(dx)));
|
||||
SYSCALL(0x029, OpSocket(m, di, si, dx));
|
||||
SYSCALL(0x02A, OpConnect(m, di, si, dx));
|
||||
SYSCALL(0x02B, DoAccept(m, di, di, dx));
|
||||
SYSCALL(0x02C, sendto(di, PNN(si), dx, r0, P(r8), r9));
|
||||
SYSCALL(0x02D, recvfrom(di, P(si), dx, r0, P(r8), P(r9)));
|
||||
SYSCALL(0x030, shutdown(di, si));
|
||||
SYSCALL(0x031, bind(di, PNN(si), dx));
|
||||
SYSCALL(0x032, listen(di, si));
|
||||
SYSCALL(0x030, OpShutdown(m, di, si));
|
||||
SYSCALL(0x031, OpBind(m, di, si, dx));
|
||||
SYSCALL(0x032, OpListen(m, di, si));
|
||||
SYSCALL(0x033, getsockname(di, PNN(si), PNN(dx)));
|
||||
SYSCALL(0x034, getpeername(di, PNN(si), PNN(dx)));
|
||||
SYSCALL(0x036, setsockopt(di, si, dx, PNN(r0), r8));
|
||||
SYSCALL(0x036, OpSetsockopt(m, di, si, dx, r0, r8));
|
||||
SYSCALL(0x037, getsockopt(di, si, dx, PNN(r0), PNN(r8)));
|
||||
SYSCALL(0x039, fork());
|
||||
SYSCALL(0x03B, execve(PNN(r8), PNN(r8), PNN(r8)));
|
||||
SYSCALL(0x039, OpFork(m));
|
||||
SYSCALL(0x03B, OpExecve(m, di, si, dx));
|
||||
SYSCALL(0x03D, wait4(di, P(si), dx, P(r0)));
|
||||
SYSCALL(0x03E, kill(di, si));
|
||||
SYSCALL(0x03F, uname(P(di)));
|
||||
SYSCALL(0x048, fcntl(di, si, dx));
|
||||
SYSCALL(0x048, OpFcntl(m, di, si, dx));
|
||||
SYSCALL(0x049, flock(di, si));
|
||||
SYSCALL(0x04A, fsync(di));
|
||||
SYSCALL(0x04B, fdatasync(di));
|
||||
SYSCALL(0x04A, OpFsync(m, di));
|
||||
SYSCALL(0x04B, OpFdatasync(m, di));
|
||||
SYSCALL(0x04C, OpTruncate(m, di, si));
|
||||
SYSCALL(0x04D, ftruncate(di, si));
|
||||
SYSCALL(0x04D, OpFtruncate(m, di, si));
|
||||
SYSCALL(0x04F, OpGetcwd(m, di, si));
|
||||
SYSCALL(0x050, OpChdir(m, di));
|
||||
SYSCALL(0x052, OpRename(m, di, si));
|
||||
|
@ -657,7 +1037,7 @@ void OpSyscall(struct Machine *m) {
|
|||
SYSCALL(0x057, OpUnlink(m, di));
|
||||
SYSCALL(0x058, OpSymlink(m, di, si));
|
||||
SYSCALL(0x05A, OpChmod(m, di, si));
|
||||
SYSCALL(0x05B, fchmod(di, si));
|
||||
SYSCALL(0x05B, OpFchmod(m, di, si));
|
||||
SYSCALL(0x060, OpGettimeofday(m, di, si));
|
||||
SYSCALL(0x061, getrlimit(di, P(si)));
|
||||
SYSCALL(0x062, getrusage(di, P(si)));
|
||||
|
@ -691,6 +1071,7 @@ void OpSyscall(struct Machine *m) {
|
|||
SYSCALL(0x113, splice(di, P(si), dx, P(r0), r8, XlatAtf(r9)));
|
||||
SYSCALL(0x115, sync_file_range(di, si, dx, XlatAtf(r0)));
|
||||
SYSCALL(0x118, utimensat(XlatAfd(m, di), P(si), P(dx), XlatAtf(r0)));
|
||||
SYSCALL(0x120, OpAccept4(m, di, si, dx, r0));
|
||||
SYSCALL(0x177, vmsplice(di, P(si), dx, r0));
|
||||
CASE(0xE7, HaltMachine(m, di | 0x100));
|
||||
default:
|
||||
|
|
|
@ -7,7 +7,7 @@ COSMOPOLITAN_C_START_
|
|||
|
||||
extern const struct MachineFdCb kMachineFdCbHost;
|
||||
|
||||
void OpSyscall(struct Machine *);
|
||||
void OpSyscall(struct Machine *, uint32_t);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/log/check.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "tool/build/lib/address.h"
|
||||
#include "tool/build/lib/throw.h"
|
||||
|
||||
static bool IsHaltingInitialized(struct Machine *m) {
|
||||
|
@ -39,7 +40,7 @@ void ThrowDivideError(struct Machine *m) {
|
|||
|
||||
void ThrowSegmentationFault(struct Machine *m, int64_t va) {
|
||||
m->faultaddr = va;
|
||||
if (m->xedd) m->ip -= m->xedd->length;
|
||||
m->ip -= m->xedd->length;
|
||||
HaltMachine(m, kMachineSegmentationFault);
|
||||
}
|
||||
|
||||
|
@ -47,15 +48,12 @@ void ThrowProtectionFault(struct Machine *m) {
|
|||
HaltMachine(m, kMachineProtectionFault);
|
||||
}
|
||||
|
||||
void OpUd(struct Machine *m) {
|
||||
void OpUd(struct Machine *m, uint32_t rde) {
|
||||
DebugBreak();
|
||||
m->ip -= m->xedd->length;
|
||||
HaltMachine(m, kMachineUndefinedInstruction);
|
||||
}
|
||||
|
||||
void OpHlt(struct Machine *m) {
|
||||
void OpHlt(struct Machine *m, uint32_t rde) {
|
||||
HaltMachine(m, kMachineHalt);
|
||||
}
|
||||
|
||||
void OpInterrupt(struct Machine *m, int i) {
|
||||
HaltMachine(m, i);
|
||||
}
|
||||
|
|
|
@ -4,13 +4,12 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
void OpUd(struct Machine *) noreturn;
|
||||
void OpUd(struct Machine *, uint32_t) noreturn;
|
||||
void HaltMachine(struct Machine *, int) noreturn;
|
||||
void ThrowDivideError(struct Machine *) noreturn;
|
||||
void ThrowSegmentationFault(struct Machine *, int64_t) noreturn;
|
||||
void ThrowProtectionFault(struct Machine *) noreturn;
|
||||
void OpHlt(struct Machine *) noreturn;
|
||||
void OpInterrupt(struct Machine *, int) noreturn;
|
||||
void OpHlt(struct Machine *, uint32_t) noreturn;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -17,16 +17,21 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/nexgen32e/rdtsc.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "tool/build/lib/endian.h"
|
||||
#include "tool/build/lib/time.h"
|
||||
|
||||
void OpPause(struct Machine *m, uint32_t rde) {
|
||||
sched_yield();
|
||||
}
|
||||
|
||||
/**
|
||||
* I am the timelorde.
|
||||
*/
|
||||
void OpRdtsc(struct Machine *m) {
|
||||
void OpRdtsc(struct Machine *m, uint32_t rde) {
|
||||
uint64_t c;
|
||||
#ifdef __x86_64__
|
||||
c = rdtsc();
|
||||
|
@ -38,3 +43,12 @@ void OpRdtsc(struct Machine *m) {
|
|||
Write64(m->ax, (c >> 000) & 0xffffffff);
|
||||
Write64(m->dx, (c >> 040) & 0xffffffff);
|
||||
}
|
||||
|
||||
void OpRdtscp(struct Machine *m, uint32_t rde) {
|
||||
uint32_t core, node, tscaux;
|
||||
OpRdtsc(m, rde);
|
||||
core = 0;
|
||||
node = 0;
|
||||
tscaux = (node & 0xfff) << 12 | (core & 0xfff);
|
||||
Write64(m->ax, tscaux & 0xffffffff);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
void OpRdtsc(struct Machine *);
|
||||
void OpPause(struct Machine *, uint32_t);
|
||||
void OpRdtsc(struct Machine *, uint32_t);
|
||||
void OpRdtscp(struct Machine *, uint32_t);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_X87_H_
|
||||
#define COSMOPOLITAN_TOOL_BUILD_LIB_X87_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
long double f2xm1(long double);
|
||||
long double fyl2x(long double, long double);
|
||||
long double fyl2xp1(long double, long double);
|
||||
long double fscale(long double, long double);
|
||||
long double fprem(long double, long double, uint32_t *);
|
||||
long double fprem1(long double, long double, uint32_t *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_X87_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue