mirror of
https://gitlab.os-k.eu/os-k-team/kvisc.git
synced 2023-08-25 14:05:46 +02:00
initial commit
This commit is contained in:
commit
06594207f9
26
INSTRS
Normal file
26
INSTRS
Normal file
@ -0,0 +1,26 @@
|
||||
# The OS/K Team licences this file to you under the MIT license.
|
||||
# See the LICENCE file in the project root for more information.
|
||||
|
||||
ADD r ri
|
||||
%0 = %0 + %1
|
||||
|
||||
SUB r ri
|
||||
%0 = %0 + %1
|
||||
|
||||
MUL ri
|
||||
RDX = hi(%0 * %1)
|
||||
RAX = lo(%0 * %1)
|
||||
|
||||
DIV ri
|
||||
RDX = RAX % %0
|
||||
RAX = RAX / %0
|
||||
|
||||
INC r
|
||||
%0 = %0 + 1
|
||||
|
||||
DEC r
|
||||
%0 = %0 - 1
|
||||
|
||||
MOV ri ri
|
||||
%0 = %1
|
||||
|
21
LICENCE
Normal file
21
LICENCE
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright © 2019 The OS/K Team
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
13
Makefile
Normal file
13
Makefile
Normal file
@ -0,0 +1,13 @@
|
||||
# The OS/K Team licences this file to you under the MIT license.
|
||||
# See the LICENCE file in the project root for more information.
|
||||
|
||||
src = arch.c instrs.c main.c regs.c
|
||||
obj = $(patsubst %.c,%.o,$(src))
|
||||
|
||||
%.o: %.c
|
||||
@gcc -O2 -Wall -c $< -o $@
|
||||
|
||||
k.exe: $(obj)
|
||||
@gcc -O2 -Wall $(obj) -o k.exe
|
||||
@rm *.o
|
||||
|
128
arch.c
Normal file
128
arch.c
Normal file
@ -0,0 +1,128 @@
|
||||
// The OS/K Team licences this file to you under the MIT license.
|
||||
// See the LICENCE file in the project root for more information.
|
||||
|
||||
#include "arch.h"
|
||||
|
||||
void scan_param(ctx_t *ctx, acc_t *p)
|
||||
{
|
||||
ushort c;
|
||||
reg_t *r;
|
||||
|
||||
assert(p != 0);
|
||||
|
||||
c = ctx->get(ctx);
|
||||
|
||||
if (c == A_MEM) {
|
||||
p->mem = 1;
|
||||
c = ctx->get(ctx);
|
||||
}
|
||||
|
||||
if (c >= A_IMM16) {
|
||||
assert(p->type == A_REG);
|
||||
p->type = c;
|
||||
c = ctx->get(ctx);
|
||||
}
|
||||
|
||||
p->val = c;
|
||||
|
||||
if (p->type == A_IMM32) {
|
||||
p->val = (p->val << 16) | ctx->get(ctx);
|
||||
}
|
||||
|
||||
else if (p->type == A_IMM64) {
|
||||
p->val = (p->val << 16) | ctx->get(ctx);
|
||||
p->val = (p->val << 16) | ctx->get(ctx);
|
||||
p->val = (p->val << 16) | ctx->get(ctx);
|
||||
}
|
||||
|
||||
else if (p->type == A_REG) {
|
||||
if (p->val > NREGS) {
|
||||
_except(ctx, E_ILL, "Inexistent REG");
|
||||
}
|
||||
|
||||
r = &ctx->r[p->val];
|
||||
|
||||
if (r->flags & (RES | CTL)) {
|
||||
_except(ctx, E_ACC, "Reserved REG");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dumpregs(ctx_t *ctx)
|
||||
{
|
||||
int i;
|
||||
reg_t *r;
|
||||
|
||||
for (i = 0; i < NREGS; i++) {
|
||||
if (i > 0 && i % 4 == 0)
|
||||
log("\n");
|
||||
|
||||
r = &ctx->r[i];
|
||||
log("%s=0x%016lX ", r->name, r->val);
|
||||
}
|
||||
log("\n");
|
||||
}
|
||||
|
||||
void dumpinstr(ctx_t *ctx, ushort c, acc_t *p1, acc_t *p2)
|
||||
{
|
||||
acc_t *p = 0;
|
||||
instr_t *i = &ctx->i[c];
|
||||
log("%s", i->name);
|
||||
|
||||
if (i->prms > 0)
|
||||
p = p1;
|
||||
lp:
|
||||
if (p != 0) {
|
||||
if (p->mem) log("[");
|
||||
|
||||
if (p->type == A_REG)
|
||||
log(" %s", ctx->r[p->val].name);
|
||||
else
|
||||
log(" 0x%lX", p->val);
|
||||
|
||||
if (p->mem) log("]");
|
||||
|
||||
if (p == p1 && i->prms == 2) {
|
||||
p = p2;
|
||||
goto lp;
|
||||
}
|
||||
}
|
||||
|
||||
log("\n");
|
||||
}
|
||||
|
||||
void decode(ctx_t *ctx)
|
||||
{
|
||||
instr_t *i;
|
||||
acc_t p1 = { 0 }, p2 = { 0 };
|
||||
|
||||
ushort c = ctx->get(ctx);
|
||||
|
||||
if (c == 0xFFFF) {
|
||||
_except(ctx, E_SHT, "Shutdown INSTR");
|
||||
}
|
||||
|
||||
else if (ISPREF(c)) {
|
||||
// nothing for now
|
||||
}
|
||||
|
||||
else if (!ISINSTR(c)) {
|
||||
_except(ctx, E_ILL, "Bad opcode");
|
||||
}
|
||||
|
||||
// Scanning an instruction
|
||||
|
||||
i = &ctx->i[c];
|
||||
|
||||
// Scan for parameters
|
||||
if (i->prms > 0) {
|
||||
scan_param(ctx, &p1);
|
||||
if (i->prms == 2) {
|
||||
scan_param(ctx, &p2);
|
||||
}
|
||||
}
|
||||
|
||||
dumpinstr(ctx, c, &p1, &p2);
|
||||
i->func(ctx, &p1, &p2);
|
||||
}
|
||||
|
124
arch.h
Normal file
124
arch.h
Normal file
@ -0,0 +1,124 @@
|
||||
// The OS/K Team licences this file to you under the MIT license.
|
||||
// See the LICENCE file in the project root for more information.
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define log printf
|
||||
|
||||
#define packed __attribute__ ((__packed__))
|
||||
#define static_assert _Static_assert
|
||||
|
||||
typedef unsigned int bool;
|
||||
typedef unsigned char uchar;
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned long ulong;
|
||||
|
||||
typedef struct reg_t reg_t;
|
||||
typedef struct ctx_t ctx_t;
|
||||
typedef struct instr_t instr_t;
|
||||
typedef struct acc_t acc_t;
|
||||
typedef struct arch_t arch_t;
|
||||
|
||||
enum
|
||||
{
|
||||
RAX, RBX, RCX, RDX, RDI, RSI, RBP, RSP,
|
||||
R08, R09, R10, R11, R12, R13, R14, R15,
|
||||
K00, K01, K02, K03, K04, K05, K06, K07,
|
||||
CR0, CR1, CR2, CR3, CR4, CR5, CR6, CR7,
|
||||
RIP, RFG,
|
||||
|
||||
NREGS
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
I_ADD, I_SUB, I_MUL, I_DIV, I_INC, I_DEC,
|
||||
I_AND, I_OR, I_XOR, I_NEG, I_CMD, I_TST,
|
||||
|
||||
I_PUSH, I_PUSHF, I_PUSHA,
|
||||
I_POP, I_POPF, I_POPA,
|
||||
|
||||
I_MOV, I_XCHG,
|
||||
|
||||
I_BSWP,
|
||||
|
||||
I_PSE, I_HLT, I_INT,
|
||||
|
||||
NINSTRS
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
GPR = 1 << 0, // General
|
||||
CTL = 1 << 1, // Control
|
||||
SEG = 1 << 2, // Segment
|
||||
RES = 1 << 8, // Reserved for insternal use
|
||||
SYS = 1 << 9, // Reserved for supervisor mode
|
||||
};
|
||||
|
||||
struct reg_t
|
||||
{
|
||||
char *name;
|
||||
char *desc;
|
||||
ulong val;
|
||||
ulong flags;
|
||||
};
|
||||
|
||||
enum { A_MEM=0x7000 };
|
||||
struct acc_t
|
||||
{
|
||||
bool mem;
|
||||
enum { A_REG=0, A_IMM16=0x7001, A_IMM32, A_IMM64 } type;
|
||||
|
||||
ulong val;
|
||||
};
|
||||
|
||||
enum { NOPREF, PREF_REP=0x8000, PREF_LOCK, NPREFS };
|
||||
|
||||
#define ISPREF(x) ((x) & 0x8000 && (x)<NPREFS)
|
||||
#define ISINSTR(x) ((x) < NINSTRS)
|
||||
|
||||
struct instr_t
|
||||
{
|
||||
char *name;
|
||||
uint prms;
|
||||
void (*func)(ctx_t *, acc_t *, acc_t *);
|
||||
};
|
||||
|
||||
struct ctx_t
|
||||
{
|
||||
reg_t *r;
|
||||
instr_t *i;
|
||||
|
||||
// Memory and memory size
|
||||
uchar *mp;
|
||||
ulong mz;
|
||||
|
||||
// Read next instruction
|
||||
ushort (*get)(ctx_t *ctx);
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
E_ILL, // Ill-formed
|
||||
E_IMP, // Not implemented
|
||||
E_ACC, // Invalid access
|
||||
E_SYS, // Supervisor only
|
||||
E_SHT, // Shutdown instruction
|
||||
NEXCPTS
|
||||
};
|
||||
|
||||
void dumpregs(ctx_t *ctx);
|
||||
|
||||
static inline void _except(ctx_t *ctx, int code, char *str)
|
||||
{
|
||||
log("Exception %d - %s\n", code, str);
|
||||
dumpregs(ctx);
|
||||
exit(code);
|
||||
}
|
||||
|
||||
void decode(ctx_t *ctx);
|
||||
|
142
instrs.c
Normal file
142
instrs.c
Normal file
@ -0,0 +1,142 @@
|
||||
// The OS/K Team licences this file to you under the MIT license.
|
||||
// See the LICENCE file in the project root for more information.
|
||||
|
||||
#include "arch.h"
|
||||
|
||||
void i_add(ctx_t *ctx, acc_t *p1, acc_t *p2)
|
||||
{
|
||||
if (p1->type != A_REG) {
|
||||
_except(ctx, E_ILL, "ADD into IMM");
|
||||
}
|
||||
|
||||
if (p1->mem || p2->mem) {
|
||||
_except(ctx, E_IMP, "Memory access");
|
||||
}
|
||||
|
||||
ctx->r[p1->val].val += p2->type >= A_IMM16 ? p2->val
|
||||
: ctx->r[p2->val].val;
|
||||
}
|
||||
|
||||
void i_sub(ctx_t *ctx, acc_t *p1, acc_t *p2)
|
||||
{
|
||||
if (p1->type != A_REG) {
|
||||
_except(ctx, E_ILL, "SUB into IMM");
|
||||
}
|
||||
|
||||
if (p1->mem || p2->mem) {
|
||||
_except(ctx, E_IMP, "Memory access");
|
||||
}
|
||||
|
||||
ctx->r[p1->val].val -= p2->type >= A_IMM16 ? p2->val
|
||||
: ctx->r[p2->val].val;
|
||||
}
|
||||
|
||||
void i_mul(ctx_t *ctx, acc_t *p1, acc_t *p2)
|
||||
{
|
||||
if (p1->mem) {
|
||||
_except(ctx, E_IMP, "Memory access");
|
||||
}
|
||||
|
||||
// Adapted from
|
||||
// https://www.codeproject.com/Tips/618570/UInt-Multiplication-Squaring
|
||||
|
||||
ulong u = p1->type >= A_IMM16 ? p1->val : ctx->r[p1->val].val;
|
||||
ulong v = ctx->r[RAX].val;
|
||||
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);
|
||||
|
||||
ctx->r[RDX].val = (u * v) + w1 + k;
|
||||
ctx->r[RAX].val = (t << 32) + w3;
|
||||
}
|
||||
|
||||
void i_div(ctx_t *ctx, acc_t *p1, acc_t *p2)
|
||||
{
|
||||
if (p1->mem) {
|
||||
_except(ctx, E_IMP, "Memory access");
|
||||
}
|
||||
|
||||
ulong val = p1->type >= A_IMM16 ? p1->val : ctx->r[p1->val].val;
|
||||
|
||||
ctx->r[RDX].val = ctx->r[RAX].val % val;
|
||||
ctx->r[RAX].val = ctx->r[RAX].val / val;
|
||||
}
|
||||
|
||||
void i_inc(ctx_t *ctx, acc_t *p1, acc_t *p2)
|
||||
{
|
||||
if (p1->type != A_REG) {
|
||||
_except(ctx, E_ILL, "INC on an IMM");
|
||||
}
|
||||
|
||||
if (p1->mem) {
|
||||
_except(ctx, E_IMP, "Memory access");
|
||||
}
|
||||
|
||||
ctx->r[p1->val].val++;
|
||||
}
|
||||
|
||||
void i_dec(ctx_t *ctx, acc_t *p1, acc_t *p2)
|
||||
{
|
||||
if (p1->type != A_REG) {
|
||||
_except(ctx, E_ILL, "DEC on an IMM");
|
||||
}
|
||||
|
||||
if (p1->mem) {
|
||||
_except(ctx, E_IMP, "Memory access");
|
||||
}
|
||||
|
||||
ctx->r[p1->val].val--;
|
||||
}
|
||||
|
||||
void i_mov(ctx_t *ctx, acc_t *p1, acc_t *p2)
|
||||
{
|
||||
if (p1->type != A_REG) {
|
||||
_except(ctx, E_ILL, "MOV into IMM");
|
||||
}
|
||||
|
||||
if (p1->mem || p2->mem) {
|
||||
_except(ctx, E_IMP, "Memory access");
|
||||
}
|
||||
|
||||
ctx->r[p1->val].val = p2->type >= A_IMM16 ? p2->val
|
||||
: ctx->r[p2->val].val;
|
||||
}
|
||||
|
||||
void i_xchg(ctx_t *ctx, acc_t *p1, acc_t *p2)
|
||||
{
|
||||
if (p1->type != A_REG || p2->type != A_REG) {
|
||||
_except(ctx, E_ILL, "XCHG of IMM(s)");
|
||||
}
|
||||
|
||||
if (p1->mem || p2->mem) {
|
||||
_except(ctx, E_IMP, "Memory access");
|
||||
}
|
||||
|
||||
ulong temp = ctx->r[p1->val].val;
|
||||
ctx->r[p1->val].val = ctx->r[p2->val].val;
|
||||
ctx->r[p2->val].val = temp;
|
||||
}
|
||||
|
||||
instr_t arch_i[NINSTRS] =
|
||||
{
|
||||
[I_ADD] = { "ADD", 2, i_add },
|
||||
[I_SUB] = { "SUB", 2, i_sub },
|
||||
[I_MUL] = { "MUL", 1, i_mul },
|
||||
[I_DIV] = { "DIV", 1, i_div },
|
||||
[I_INC] = { "INC", 1, i_inc },
|
||||
[I_DEC] = { "DEC", 1, i_dec },
|
||||
[I_MOV] = { "MOV", 2, i_mov },
|
||||
[I_XCHG] = { "XCHG", 2, i_xchg },
|
||||
};
|
||||
|
48
main.c
Normal file
48
main.c
Normal file
@ -0,0 +1,48 @@
|
||||
// The OS/K Team licences this file to you under the MIT license.
|
||||
// See the LICENCE file in the project root for more information.
|
||||
|
||||
#include "arch.h"
|
||||
|
||||
ushort prog[] = {
|
||||
I_ADD, RDX, A_IMM32, 0xAABB, 0xCCDD,
|
||||
I_MOV, RAX, RDX,
|
||||
I_MOV, RBX, A_IMM64, 0x7777, 0x6666, 0x5555, 0x4444,
|
||||
I_SUB, RDX, A_IMM16, 0xCCDD,
|
||||
I_MOV, RBP, A_IMM16, 0x0010,
|
||||
I_MUL, A_IMM64, 0xFFFF,0xFFFF,0xFFFF,0xFFFF,
|
||||
I_ADD, RAX, A_IMM32, 0xAABB, 0xCCDD,
|
||||
};
|
||||
|
||||
ushort bget(ctx_t *ctx)
|
||||
{
|
||||
static int i = 0;
|
||||
|
||||
if (i >= sizeof(prog)/sizeof(ushort)) {
|
||||
_except(ctx, E_ACC, "End of text");
|
||||
}
|
||||
|
||||
return prog[i++];
|
||||
}
|
||||
|
||||
extern reg_t arch_r[NREGS];
|
||||
extern instr_t arch_i[NINSTRS];
|
||||
|
||||
int main(void)
|
||||
{
|
||||
static ctx_t main_ctx;
|
||||
|
||||
main_ctx.r = arch_r;
|
||||
main_ctx.i = arch_i;
|
||||
|
||||
main_ctx.mp = 0;
|
||||
main_ctx.mz = 0;
|
||||
|
||||
main_ctx.get = bget;
|
||||
|
||||
while (1) {
|
||||
decode(&main_ctx);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
43
regs.c
Normal file
43
regs.c
Normal file
@ -0,0 +1,43 @@
|
||||
// The OS/K Team licences this file to you under the MIT license.
|
||||
// See the LICENCE file in the project root for more information.
|
||||
|
||||
#include "arch.h"
|
||||
|
||||
reg_t arch_r[NREGS] =
|
||||
{
|
||||
{ "RAX", "Accumulator 0", 0, GPR },
|
||||
{ "RBX", "Accumulator 1", 0, GPR },
|
||||
{ "RCX", "Accumulator 2", 0, GPR },
|
||||
{ "RDX", "Accumulator 3", 0, GPR },
|
||||
{ "RDI", "Accumulator 4", 0, GPR },
|
||||
{ "RSI", "Accumulator 5", 0, GPR },
|
||||
{ "RBP", "Stack base", 0, GPR },
|
||||
{ "RSP", "Stack pointer", 0, GPR },
|
||||
{ "R08", "Accumulator 8", 0, GPR },
|
||||
{ "R09", "Accumulator 9", 0, GPR },
|
||||
{ "R10", "Accumulator 10", 0, GPR },
|
||||
{ "R11", "Accumulator 11", 0, GPR },
|
||||
{ "R12", "Accumulator 12", 0, GPR },
|
||||
{ "R13", "Accumulator 13", 0, GPR },
|
||||
{ "R14", "Accumulator 14", 0, GPR },
|
||||
{ "R15", "Accumulator 15", 0, GPR },
|
||||
{ "K00", "Supervisor accumulator 0", 0, SYS },
|
||||
{ "K01", "Supervisor accumulator 1", 0, SYS },
|
||||
{ "K02", "Supervisor accumulator 2", 0, SYS },
|
||||
{ "K03", "Supervisor accumulator 3", 0, SYS },
|
||||
{ "K04", "Supervisor accumulator 4", 0, SYS },
|
||||
{ "K05", "Supervisor accumulator 5", 0, SYS },
|
||||
{ "K06", "Supervisor accumulator 6", 0, SYS },
|
||||
{ "K07", "Supervisor accumulator 7", 0, SYS },
|
||||
{ "CR0", "Control register 0", 0, CTL },
|
||||
{ "CR1", "Control register 1", 0, CTL },
|
||||
{ "CR2", "Control register 2", 0, CTL },
|
||||
{ "CR3", "Control register 3", 0, CTL },
|
||||
{ "CR4", "Control register 4", 0, CTL },
|
||||
{ "CR5", "Control register 5", 0, CTL },
|
||||
{ "CR6", "Control register 6", 0, CTL },
|
||||
{ "CR7", "Control register 7", 0, CTL },
|
||||
{ "RIP", "Instruction pointer", 0, RES },
|
||||
{ "RFG", "Flags register", 0, RES },
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user