cosmopolitan/tool/build/lib/alu.c

765 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 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;
}
}