mirror of
https://gitlab.os-k.eu/os-k-team/kvisc.git
synced 2023-08-25 14:05:46 +02:00
299 lines
4.5 KiB
C
299 lines
4.5 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;
|
|
|
|
//
|
|
// Logical instructions
|
|
//
|
|
|
|
IMPL_START_2(and)
|
|
{
|
|
v1 &= v2;
|
|
}
|
|
IMPL_OUT;
|
|
|
|
IMPL_START_2(or)
|
|
{
|
|
v1 |= v2;
|
|
}
|
|
IMPL_OUT;
|
|
|
|
IMPL_START_2(xor)
|
|
{
|
|
v1 ^= v2;
|
|
}
|
|
IMPL_OUT;
|
|
|
|
IMPL_START_2(shl)
|
|
{
|
|
v1 <<= v2;
|
|
}
|
|
IMPL_OUT;
|
|
|
|
IMPL_START_2(shr)
|
|
{
|
|
v1 >>= v2;
|
|
}
|
|
IMPL_OUT;
|
|
|
|
IMPL_START_1(not)
|
|
{
|
|
v1 = ~v1;
|
|
}
|
|
IMPL_OUT;
|
|
|
|
//
|
|
// Unsigned arithmetic instructions
|
|
//
|
|
|
|
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;
|
|
|
|
//
|
|
// Comparison instructions
|
|
//
|
|
|
|
IMPL_START_2(cmp)
|
|
{
|
|
if (v1 == v2) {
|
|
ctx->r[FLG].val |= ZF;
|
|
ctx->r[FLG].val &= ~CF;
|
|
}
|
|
|
|
else if (v1 < v2) {
|
|
ctx->r[FLG].val &= ~ZF;
|
|
ctx->r[FLG].val |= CF;
|
|
}
|
|
|
|
else {
|
|
ctx->r[FLG].val &= ~ZF;
|
|
ctx->r[FLG].val &= ~CF;
|
|
}
|
|
}
|
|
IMPL_END;
|
|
|
|
IMPL_START_2(test)
|
|
{
|
|
ulong v = v1 & v2;
|
|
|
|
if (v == 0) ctx->r[FLG].val |= ZF;
|
|
else ctx->r[FLG].val &= ~ZF;
|
|
}
|
|
IMPL_END;
|
|
|
|
//
|
|
// Jump instructions
|
|
//
|
|
|
|
//
|
|
// Movement instructions
|
|
//
|
|
|
|
IMPL_START_2(mov)
|
|
{
|
|
v1 = v2;
|
|
}
|
|
IMPL_OUT;
|
|
|
|
IMPL_START_2(xchg)
|
|
{
|
|
ulong t = v1;
|
|
v1 = v2;
|
|
v2 = t;
|
|
}
|
|
IMPL_OUT;
|
|
|
|
IMPL_START_1(lea)
|
|
{
|
|
assert(p2->mem);
|
|
|
|
v1 = (p2->type == A_REG ? ctx->r[p2->val].val : p2->val) + p2->off;
|
|
}
|
|
IMPL_OUT;
|
|
|
|
//
|
|
// Stack manipulation instructions
|
|
//
|
|
|
|
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(pushf)
|
|
{
|
|
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[FLG].val, ctx->r[RSP].val);
|
|
ctx->r[RSP].val -= 8;
|
|
}
|
|
IMPL_END;
|
|
|
|
IMPL_START_0(popf)
|
|
{
|
|
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");
|
|
}
|
|
|
|
CHK_SUPERV(); // XXX
|
|
|
|
ctx->r[RSP].val += 8;
|
|
ctx->r[FLG].val = readmem64(ctx, ctx->r[RSP].val);
|
|
}
|
|
IMPL_END;
|
|
|
|
//
|
|
// Supervisor only instructions
|
|
//
|
|
|
|
IMPL_START_0(cli)
|
|
{
|
|
CHK_SUPERV();
|
|
ctx->r[FLG].val &= ~IF;
|
|
}
|
|
IMPL_END;
|
|
|
|
IMPL_START_0(sti)
|
|
{
|
|
CHK_SUPERV();
|
|
ctx->r[FLG].val |= IF;
|
|
}
|
|
IMPL_END;
|
|
|
|
IMPL_START_0(stop)
|
|
{
|
|
_except(ctx, E_SHT, "STOP INSTR");
|
|
}
|
|
IMPL_END;
|
|
|