kvisc/vm/in/arith.c

249 lines
3.5 KiB
C

// The OS/K Team licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#include <in/instrs.h>
//----------------------------------------------------------------------------//
IMPL_START_2(sgn)
{
v1 = (v2 == 0 ? 0 :
((long)v2 < 0 ? (ulong)-1L : 1));
}
IMPL_OUT;
IMPL_START_2(sgnf)
{
v1 = (long)v2 < 0 ? (ulong)-1L : 1;
}
IMPL_OUT_ZSF;
IMPL_START_2(neg)
{
v1 = ~v2 + 1;
}
IMPL_OUT;
IMPL_START_2(negf)
{
if (v2 == 0) {
flg |= CF;
flg &= ~OF;
}
else {
flg &= ~CF;
if (v2 == LONG_MIN) flg |= OF;
else flg &= ~OF;
}
v1 = ~v2 + 1;
}
IMPL_OUT_ZSF;
//----------------------------------------------------------------------------//
IMPL_START_1(inc)
{
v1++;
}
IMPL_OUT;
IMPL_START_1(incf)
{
if (v1 == LONG_MAX) flg |= OF;
else flg &= ~OF;
v1++;
}
IMPL_OUT_ZSF;
IMPL_START_1(dec)
{
v1--;
}
IMPL_OUT;
IMPL_START_1(decf)
{
if (v1 == LONG_MIN) flg |= OF;
else flg &= ~OF;
v1--;
}
IMPL_OUT_ZSF;
//----------------------------------------------------------------------------//
IMPL_START_2(add)
{
v1 += v2;
}
IMPL_OUT;
IMPL_START_2(xadd)
{
ulong tmp = v1;
v1 += v2;
v2 = tmp;
}
IMPL_OUT_2;
IMPL_START_2(addf)
{
if (v1 + v2 < v1) flg |= OF;
else flg &= ~OF;
if ( ((v2 > 0) && (v1 > LONG_MAX - v2))
|| ((v2 < 0) && (v1 < LONG_MIN - v2)) )
flg |= CF;
else flg &= ~CF;
v1 += v2;
}
IMPL_OUT_ZSF;
IMPL_START_2(adc)
{
v1 += v2 + !!(flg&CF);
}
IMPL_OUT;
IMPL_START_2(adcf)
{
if (v1 + v2 + !!(flg&CF) < v1) flg |= OF;
else flg &= ~OF;
v1 += !!(flg&CF);
if ( ((v2 > 0) && (v1 > LONG_MAX - v2))
|| ((v2 < 0) && (v1 < LONG_MIN - v2)) )
flg |= CF;
else flg &= ~CF;
v1 += v2;
}
IMPL_OUT_ZSF;
//----------------------------------------------------------------------------//
IMPL_START_2(sub)
{
v1 -= v2;
}
IMPL_OUT;
IMPL_START_2(subf)
{
COMPARE(v1, v2);
v1 -= v2;
}
IMPL_OUT;
//
// i_subf but discards result
//
IMPL_START_2(cmp)
{
COMPARE(v1, v2);
}
IMPL_END;
//----------------------------------------------------------------------------//
//
// www.codeproject.com/Tips/618570/UInt-Multiplication-Squaring
//
static void multiply(ulong u, ulong v, ulong *hi, ulong *lo)
{
ulong u1 = (u & 0xffffffff);
ulong v1 = (v & 0xffffffff);
ulong t = (u1 * v1);
ulong w3 = (t & 0xffffffff);
ulong k = (t >> 32);
u >>= 32;
t = (u * v1) + k;
k = (t & 0xffffffff);
ulong w1 = (t >> 32);
v >>= 32;
t = (u1 * v) + k;
k = (t >> 32);
*hi = (u * v) + w1 + k;
*lo = (t << 32) + w3;
}
IMPL_START_2(mul)
{
ulong hi;
multiply(v1, v2, &hi, &v1);
}
IMPL_OUT;
IMPL_START_2(mulf)
{
ulong hi;
multiply(v1, v2, &hi, &v1);
if (hi > 0) {
flg |= CF;
flg |= OF;
}
else {
flg &= ~CF;
flg &= ~OF;
}
}
IMPL_OUT;
IMPL_START_3(mulx)
{
multiply(v2, v3, &v1, &v2);
}
IMPL_OUT_2;
IMPL_START_3(mulfx)
{
multiply(v2, v3, &v1, &v2);
if (v1 > 0) {
flg |= CF;
flg |= OF;
}
else {
flg &= ~CF;
flg &= ~OF;
}
}
IMPL_OUT_2;
//----------------------------------------------------------------------------//
IMPL_START_2(div)
{
v1 /= v2;
}
IMPL_OUT;
IMPL_START_2(rem)
{
v1 %= v2;
}
IMPL_OUT;
IMPL_START_3(divx)
{
v1 = v2 % v3;
v2 = v2 / v3;
}
IMPL_OUT_2;
//----------------------------------------------------------------------------//