cosmopolitan/tool/build/lib/alu.c

764 lines
19 KiB
C
Raw Normal View History

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