kvisc/vm/in/arith.c

172 lines
2.7 KiB
C
Raw Normal View History

2019-05-30 12:44:56 +02:00
// The OS/K Team licenses this file to you under the MIT license.
2019-05-29 16:57:22 +02:00
// See the LICENSE file in the project root for more information.
2019-06-05 12:53:09 +02:00
#include <in/instrs.h>
2019-05-29 16:57:22 +02:00
2019-06-06 14:57:34 +02:00
IMPL_COND(sgn);
2019-05-30 20:23:27 +02:00
IMPL_COND(inc);
IMPL_COND(dec);
IMPL_COND(add);
IMPL_COND(sub);
IMPL_COND(mul);
IMPL_COND(div);
2019-06-06 14:57:34 +02:00
IMPL_COND(mod);
IMPL_COND(mul2);
IMPL_COND(div2);
2019-05-30 20:23:27 +02:00
2019-06-06 22:07:34 +02:00
//--------------------------------------------------------------------------
IMPL_START_1(inc)
{
if (v1 == LONG_MAX) flg |= OF;
else flg &= ~OF;
v1++;
}
IMPL_OUT_ZSF;
IMPL_START_1(dec)
{
if (v1 == LONG_MIN) flg |= OF;
else flg &= ~OF;
v1--;
}
IMPL_OUT_ZSF;
//--------------------------------------------------------------------------
2019-05-29 16:57:22 +02:00
IMPL_START_2(add)
{
2019-06-06 22:07:34 +02:00
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;
2019-05-29 16:57:22 +02:00
v1 += v2;
}
2019-06-06 22:07:34 +02:00
IMPL_OUT_ZSF;
2019-05-29 16:57:22 +02:00
IMPL_START_2(sub)
{
2019-06-06 22:07:34 +02:00
if (v1 < v2) flg |= CF;
else flg &= ~CF;
if ( ((v2 < 0) && (v1 > LONG_MAX + v2))
|| ((v2 > 0) && (v1 < LONG_MIN + v2)) )
flg |= OF;
else flg &= ~OF;
2019-05-29 16:57:22 +02:00
v1 -= v2;
}
2019-06-06 22:07:34 +02:00
IMPL_OUT_ZSF;
//
// i_sub but discards result
//
IMPL_START_2(cmp)
{
if (v1 < v2) flg |= CF;
else flg &= ~CF;
if ( ((v2 < 0) && (v1 > LONG_MAX + v2))
|| ((v2 > 0) && (v1 < LONG_MIN + v2)) )
flg |= OF;
else flg &= ~OF;
SET_ZSF(v1 - v2);
}
IMPL_END;
//--------------------------------------------------------------------------
2019-05-29 16:57:22 +02:00
2019-06-05 22:11:45 +02:00
IMPL_START_2(mul)
{
v1 *= v2;
}
IMPL_OUT;
IMPL_START_1(mul2)
2019-05-29 16:57:22 +02:00
{
// Adapted from www.codeproject.com/Tips/618570/UInt-Multiplication-Squaring
ulong v2 = v1;
2019-06-02 16:33:28 +02:00
v1 = rax;
2019-05-29 16:57:22 +02:00
ulong u1 = (v1 & 0xffffffff);
ulong u2 = (v2 & 0xffffffff);
ulong t = (u1 * u2);
ulong w3 = (t & 0xffffffff);
ulong k = (t >> 32);
2019-05-30 12:44:56 +02:00
2019-05-29 16:57:22 +02:00
v1 >>= 32;
t = (v1 * u2) + k;
k = (t & 0xffffffff);
ulong w1 = (t >> 32);
2019-05-30 12:44:56 +02:00
2019-05-29 16:57:22 +02:00
v2 >>= 32;
t = (u1 * v2) + k;
k = (t >> 32);
2019-05-30 12:44:56 +02:00
2019-06-02 16:33:28 +02:00
rdx = (v1 * v2) + w1 + k;
rax = (t << 32) + w3;
2019-05-29 16:57:22 +02:00
}
IMPL_END;
2019-06-06 22:07:34 +02:00
//--------------------------------------------------------------------------
2019-06-05 22:11:45 +02:00
IMPL_START_2(div)
{
v1 /= v2;
}
IMPL_OUT;
IMPL_START_2(mod)
{
v1 %= v2;
}
IMPL_OUT;
IMPL_START_1(div2)
2019-05-29 16:57:22 +02:00
{
2019-06-02 16:33:28 +02:00
rdx = rax % v1;
rax = rax / v1;
2019-05-29 16:57:22 +02:00
}
IMPL_END;
2019-06-06 22:07:34 +02:00
//--------------------------------------------------------------------------
2019-05-29 16:57:22 +02:00
2019-06-06 22:07:34 +02:00
IMPL_START_2(sgn)
2019-05-29 16:57:22 +02:00
{
2019-06-06 22:07:34 +02:00
if (v2 == 0) v1 = 0;
else if ((long)v2 > 0) {
flg &= ~CF;
v1 = 1;
}
else {
flg |= CF;
v1 = (ulong)-1L;
}
2019-05-29 16:57:22 +02:00
}
2019-06-06 22:07:34 +02:00
IMPL_OUT_ZSF;
2019-05-29 16:57:22 +02:00
2019-06-06 22:07:34 +02:00
IMPL_START_1(neg)
2019-05-31 21:25:56 +02:00
{
2019-06-06 22:07:34 +02:00
if (v1 == 0) flg |= CF;
else {
flg &= ~CF;
if (v1 == LONG_MIN) flg |= OF;
else flg &= ~OF;
}
v1 = ~v1 + 1;
2019-05-31 21:25:56 +02:00
}
2019-06-06 22:07:34 +02:00
IMPL_OUT_ZSF;
2019-05-31 21:25:56 +02:00