kvisc/instr/instrs.c

161 lines
2.7 KiB
C

// The OS/K Team licences this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#include "instrs.h"
#include "arch_i.h"
#define _NEED_ARCH_I
#include "arch_i.h"
IMPL_START_0(nop)
{
}
IMPL_END;
IMPL_START_2(add)
{
v1 += v2;
}
IMPL_OUT;
IMPL_START_2(sub)
{
v1 -= v2;
}
IMPL_OUT;
IMPL_START_1(mul)
{
// Adapted from www.codeproject.com/Tips/618570/UInt-Multiplication-Squaring
ulong v2 = v1;
v1 = ctx->r[RAX].val;
ulong u1 = (v1 & 0xffffffff);
ulong u2 = (v2 & 0xffffffff);
ulong t = (u1 * u2);
ulong w3 = (t & 0xffffffff);
ulong k = (t >> 32);
v1 >>= 32;
t = (v1 * u2) + k;
k = (t & 0xffffffff);
ulong w1 = (t >> 32);
v2 >>= 32;
t = (u1 * v2) + k;
k = (t >> 32);
ctx->r[RDX].val = (v1 * v2) + w1 + k;
ctx->r[RAX].val = (t << 32) + w3;
}
IMPL_END;
IMPL_START_1(div)
{
ctx->r[RDX].val = ctx->r[RAX].val % v1;
ctx->r[RAX].val = ctx->r[RAX].val / v1;
}
IMPL_END;
IMPL_START_1(inc)
{
v1++;
}
IMPL_OUT;
IMPL_START_1(dec)
{
v1--;
}
IMPL_OUT;
IMPL_START_2(mov)
{
v1 = v2;
}
IMPL_OUT;
IMPL_START_2(xchg)
{
ulong t = v1;
v1 = v2;
v2 = t;
}
IMPL_OUT;
IMPL_START_1(push)
{
if (ctx->r[RSP].val % 8 > 0 || ctx->r[RBP].val % 8 > 0) {
_except(ctx, E_STK, "Misaligned stack REGS");
}
if (ctx->r[RSP].val > ctx->r[RBP].val) {
_except(ctx, E_STK, "RSP above RBP");
}
writemem64(ctx, v1, ctx->r[RSP].val);
ctx->r[RSP].val -= 8;
}
IMPL_END;
IMPL_START_1(pop)
{
if (ctx->r[RSP].val % 8 > 0 || ctx->r[RBP].val % 8 > 0) {
_except(ctx, E_STK, "Misaligned stack REGS");
}
if (ctx->r[RSP].val >= ctx->r[RBP].val) {
_except(ctx, E_STK, "RBP above RSP");
}
ctx->r[RSP].val += 8;
v1 = readmem64(ctx, ctx->r[RSP].val);
}
IMPL_OUT;
IMPL_START_1(call)
{
if (ctx->r[RSP].val % 8 > 0 || ctx->r[RBP].val % 8 > 0) {
_except(ctx, E_STK, "Misaligned stack REGS");
}
if (ctx->r[RSP].val > ctx->r[RBP].val) {
_except(ctx, E_STK, "RSP above RBP");
}
writemem64(ctx, ctx->r[RIP].val, ctx->r[RSP].val);
ctx->r[RSP].val -= 8;
ctx->r[RIP].val = v1;
}
IMPL_END;
IMPL_START_0(ret)
{
if (ctx->r[RSP].val % 8 > 0 || ctx->r[RBP].val % 8 > 0) {
_except(ctx, E_STK, "Misaligned stack REGS");
}
if (ctx->r[RSP].val >= ctx->r[RBP].val) {
_except(ctx, E_STK, "RBP above RSP");
}
ctx->r[RSP].val += 8;
ctx->r[RIP].val = readmem64(ctx, ctx->r[RSP].val);
}
IMPL_END;
IMPL_START_0(cli)
{
CHK_SUPERV();
ctx->r[FLG].val &= ~(1L<<63);
}
IMPL_END;
IMPL_START_0(sti)
{
CHK_SUPERV();
ctx->r[FLG].val |= 1L<<63;
}
IMPL_END;