mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 19:43:32 +00:00
416fd86676
- 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
773 lines
19 KiB
C
773 lines
19 KiB
C
/*-*- 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 "tool/build/lib/alu.h"
|
|
#include "tool/build/lib/flags.h"
|
|
|
|
const aluop_f kAlu[12][4] = {
|
|
{Add8, Add16, Add32, Add64}, {Or8, Or16, Or32, Or64},
|
|
{Adc8, Adc16, Adc32, Adc64}, {Sbb8, Sbb16, Sbb32, Sbb64},
|
|
{And8, And16, And32, And64}, {Sub8, Sub16, Sub32, Sub64},
|
|
{Xor8, Xor16, Xor32, Xor64}, {Sub8, Sub16, Sub32, Sub64},
|
|
{Not8, Not16, Not32, Not64}, {Neg8, Neg16, Neg32, Neg64},
|
|
{Inc8, Inc16, Inc32, Inc64}, {Dec8, Dec16, Dec32, Dec64},
|
|
};
|
|
|
|
const aluop_f kBsu[8][4] = {
|
|
{Rol8, Rol16, Rol32, Rol64}, {Ror8, Ror16, Ror32, Ror64},
|
|
{Rcl8, Rcl16, Rcl32, Rcl64}, {Rcr8, Rcr16, Rcr32, Rcr64},
|
|
{Shl8, Shl16, Shl32, Shl64}, {Shr8, Shr16, Shr32, Shr64},
|
|
{Shl8, Shl16, Shl32, Shl64}, {Sar8, Sar16, Sar32, Sar64},
|
|
};
|
|
|
|
int64_t 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 | 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;
|
|
}
|
|
}
|