diff --git a/Makefile b/Makefile index b8ec093..1e7d72e 100644 --- a/Makefile +++ b/Makefile @@ -3,10 +3,10 @@ all: k.exe -src = instr/instrs.c karch/decd.c karch/main.c karch/regs.c +src = instr/instrs.c karch/decd.c karch/main.c karch/regs.c karch/dump.c obj = $(patsubst %.c,%.o,$(src)) -%.o: %.c instrs/i_arch.h */*.h */*.c +%.o: %.c instrs/i_arch.h */*.h $(src) @gcc -O2 -Wall -I./karch -c $< -o $@ instrs/i_arch.h: instr/INSTRS instr/instrs.py diff --git a/instr/INSTRS b/instr/INSTRS index c4054b0..bd2cb95 100644 --- a/instr/INSTRS +++ b/instr/INSTRS @@ -38,5 +38,13 @@ mov r i mov r m mov m r mov m i -mov m m + +xchg r r +xchg r i +xchg r m +xchg m r +xchg m i + +cli +sti diff --git a/instr/instrs.c b/instr/instrs.c index f37ba73..94043c6 100644 --- a/instr/instrs.c +++ b/instr/instrs.c @@ -2,6 +2,10 @@ // 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) { @@ -79,6 +83,17 @@ IMPL_START_2(xchg) } IMPL_OUT; -#define _NEED_ARCH_I -#include "arch_i.h" +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; diff --git a/instr/instrs.h b/instr/instrs.h index 081b5d8..a64c732 100644 --- a/instr/instrs.h +++ b/instr/instrs.h @@ -11,19 +11,38 @@ void i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2) \ void i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2) \ { \ ulong v1 = (p1->type == A_REG ? ctx->r[p1->val].val : p1->val); \ + if (p1->mem) v1 = readmem64(ctx, v1 + p1->off); \ #define IMPL_START_2(name) \ void i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2) \ { \ ulong v1 = (p1->type == A_REG ? ctx->r[p1->val].val : p1->val); \ ulong v2 = (p2->type == A_REG ? ctx->r[p2->val].val : p2->val); \ - + if (p1->mem) v1 = readmem64(ctx, v1 + p1->off); \ + if (p2->mem) v2 = readmem64(ctx, v2 + p2->off); \ + +#define IMPL_START_3(name) \ +void i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2) \ +{ \ + ulong v2 = (p2->type == A_REG ? ctx->r[p2->val].val : p2->val); \ + if (p2->mem) v2 = readmem64(ctx, v2 + p2->off); \ + #define IMPL_OUT \ - assert(p1->type == A_REG); \ - ctx->r[p1->val].val = v1; \ + assert(p1->type == A_REG || p1->mem); \ + if (p1->mem) { \ + ulong addr = p1->type == A_REG ? ctx->r[p1->val].val : p1->val; \ + writemem64(ctx, v1, addr); \ + } \ + else ctx->r[p1->val].val = v1; \ } \ #define IMPL_END \ } - + +#define CHK_SUPERV() \ + do { \ + if ((ctx->r[FLG].val & (1L << 62)) == 1) { \ + _except(ctx, E_SYS, "Supervisor-only INSTR"); \ + } \ + } while (0) diff --git a/instr/instrs.py b/instr/instrs.py index c8b8c6d..f491788 100644 --- a/instr/instrs.py +++ b/instr/instrs.py @@ -28,39 +28,43 @@ for _, line in enumerate(fi): if line[0] == '#' or line[0] == ' ' or line[0] == '\n': continue - tok = line.split(' ') + tok = line.strip().split(' ') if len(tok) == 1: - name = tok[0].strip() + name = tok[0] p1 = "NOPRM" p2 = "NOPRM" elif len(tok) == 2: name = "{}_{}".format(tok[0], tok[1].strip()) - p1 = getflag(tok[1].strip()) + p1 = getflag(tok[1]) p2 = "NOPRM" elif len(tok) == 3: name = "{}_{}_{}".format(tok[0], tok[1], tok[2].strip()) p1 = getflag(tok[1]) - p2 = getflag(tok[2].strip()) + p2 = getflag(tok[2]) else: name = "__ERROR__" p1 = "__ERROR__" p2 = "__ERROR__" - hd.write("#define I_{} {}\n".format(name.upper(), count)) hd.write("#ifdef _NEED_ARCH_I\n") hd.write('{{ "{}", "{}", {}, {}, i_{} }},\n'\ - .format(tok[0].strip(), name, p1, p2, tok[0])) + .format(tok[0], name, p1, p2, tok[0])) + hd.write("#else\n") + hd.write("#define I_{} {}\n".format(name.upper(), count)) + hd.write("extern void i_{}(ctx_t *, acc_t *, acc_t *);\n" + .format(tok[0])) hd.write("#endif\n\n") count = count + 1 -hd.write("#define NINSTRS {}\n\n".format(count)) hd.write("#ifdef _NEED_ARCH_I\n") hd.write("};\n") +hd.write("#else\n") +hd.write("#define NINSTRS {}\n\n".format(count)) hd.write("#endif\n") hd.close() diff --git a/karch/arch.h b/karch/arch.h index f876e9a..d99c48e 100644 --- a/karch/arch.h +++ b/karch/arch.h @@ -32,7 +32,7 @@ enum 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, FLG, RET, + RIP, FLG, NREGS }; @@ -54,13 +54,17 @@ struct reg_t ulong flags; }; -enum { A_MEM=0x7000 }; +// A_REG is implicit +// A_MEM denotes a memory access +// A_OFF is A_MEM but a 16-bit offset is expected immediatly next +enum { A_REG=0, A_MEM=0x7000, A_OFF, A_IMM16, A_IMM32, A_IMM64 }; struct acc_t { - bool mem; - enum { A_REG=0, A_IMM16=0x7001, A_IMM32, A_IMM64 } type; + bool mem; // A_MEM? + uint type; ulong val; + short off; }; enum { NOPREF, PREF_REP=0x8000, PREF_LOCK, NPREFS }; @@ -105,7 +109,10 @@ enum NEXCPTS }; -void dumpregs(ctx_t *ctx); +void dumpregs(ctx_t *); +void dumpinstr(ctx_t *, ulong, ushort, acc_t *, acc_t *); +void dumpmem(ctx_t *, ulong, ulong); +void dumpfwstack(ctx_t *); static inline void _except(ctx_t *ctx, int code, char *fmt, ...) { @@ -120,6 +127,8 @@ static inline void _except(ctx_t *ctx, int code, char *fmt, ...) log("\n"); dumpregs(ctx); + dumpfwstack(ctx); + free(ctx->mp); exit(code+1); } @@ -132,16 +141,19 @@ void decode(ctx_t *ctx); #define addr2real(p) ((p) - MEMOFF) #define real2addr(p) ((p) + MEMOFF) +// Address of boot firmware stack +#define FWSTACK (MEMOFF * 2) // 2MB + static inline ulong readmem64(ctx_t *ctx, ulong addr) { ulong real = addr2real(addr); if (addr % alignof(ulong) > 0) { - _except(ctx, E_ALI, "Non-aligned memory access"); + _except(ctx, E_ALI, "Non-aligned memory access: 0x%012lX(0x%012lX)", addr, real); } if (addr < MEMOFF || real >= MEMSIZE) { - _except(ctx, E_ACC, "Accessing inexistent memory"); + _except(ctx, E_ACC, "Invalid MEM access: 0x%012lX(0x%012lX)", addr, real); } ulong val = (ulong)ctx->mp[real++]; @@ -152,5 +164,23 @@ static inline ulong readmem64(ctx_t *ctx, ulong addr) return val; } +static inline void writemem64(ctx_t *ctx, ulong val, ulong addr) +{ + ulong real = addr2real(addr); + + if (addr % alignof(ulong) > 0) { + _except(ctx, E_ALI, "Non-aligned memory access: 0x%012lX(0x%012lX)", addr, real); + } + + if (addr < MEMOFF || real >= MEMSIZE) { + _except(ctx, E_ACC, "Invalid MEM access: 0x%012lX(0x%012lX)", addr, real); + } + + ctx->mp[real++] = val >> 48; + ctx->mp[real++] = (val >> 32) & 0xFFFF; + ctx->mp[real++] = (val >> 16) & 0xFFFF; + ctx->mp[real++] = val & 0xFFFF; +} + #include "../instr/arch_i.h" diff --git a/karch/decd.c b/karch/decd.c index 2e94c78..bf171d3 100644 --- a/karch/decd.c +++ b/karch/decd.c @@ -14,6 +14,13 @@ void scan_param(ctx_t *ctx, acc_t *p) if (c == A_MEM) { p->mem = 1; + p->off = 0; + c = ctx->get(ctx); + } + + else if (c == A_OFF) { + p->mem = 1; + p->off = (short)ctx->get(ctx); c = ctx->get(ctx); } @@ -48,49 +55,6 @@ void scan_param(ctx_t *ctx, acc_t *p) } } -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, ulong rip, ushort c, acc_t *p1, acc_t *p2) -{ - acc_t *p = 0; - instr_t *i = &ctx->i[c]; - log("0x%016lX: %s", rip, i->name); - - if (i->prm1 != NOPRM) - 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->prm2 != NOPRM) { - p = p2; - goto lp; - } - } - - log("\n"); -} - void decode(ctx_t *ctx) { instr_t *i; diff --git a/karch/dump.c b/karch/dump.c new file mode 100644 index 0000000..687fdf7 --- /dev/null +++ b/karch/dump.c @@ -0,0 +1,81 @@ +// 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 "arch.h" + +void dumpregs(ctx_t *ctx) +{ + int i; + reg_t *r; + + log("\nRegisters:\n"); + log("rip=0x%016lX flg=0x%016lX", ctx->r[RIP].val, ctx->r[FLG].val); + + for (i = 0; i < K00; i++) { + if (i % 4 == 0) + log("\n"); + + r = &ctx->r[i]; + log("%s=0x%016lX ", r->name, r->val); + } + log("\n"); +} + +void dumpmem(ctx_t *ctx, ulong start, ulong size) +{ + uint i; + for (i = 0; i < size/sizeof(ushort); i++) { + if (i % 4 == 0) { + if (i > 0) { + if (i % 8 == 0) log("\n"); + else log(" "); + } + + log("[0x%08lX]=0x", start + i * 2); + } + + log("%04hX", ctx->mp[addr2real(start) + i]); + + } + log("\n"); +} + +void dumpfwstack(ctx_t *ctx) +{ + log("\nFirmware stack:\n"); + dumpmem(ctx, FWSTACK, 128); +} + +void dumpinstr(ctx_t *ctx, ulong rip, ushort c, acc_t *p1, acc_t *p2) +{ + acc_t *p = 0; + instr_t *i = &ctx->i[c]; + log("0x%016lX: %s", rip, i->name); + + if (i->prm1 != NOPRM) + p = p1; +lp: + if (p != 0) { + if (p->mem) log(" ["); + else log(" "); + + if (p->type == A_REG) + log("%s", ctx->r[p->val].name); + else + log("0x%lX", p->val); + + if (p->mem) { + if (p->off) + log("+%hd", p->off); + log("]"); + } + + if (p == p1 && i->prm2 != NOPRM) { + p = p2; + log(","); + goto lp; + } + } + + log("\n"); +} diff --git a/karch/main.c b/karch/main.c index 1c745dc..ecf0fb5 100644 --- a/karch/main.c +++ b/karch/main.c @@ -3,8 +3,15 @@ #include "arch.h" +// Boot firware, loaded at MEMOFF (1MB) ushort fwprog[] = { - I_MOV_R_I, RBP, A_IMM16, MEMOFF+sizeof(fwprog)+0xFF, + I_MOV_R_I, RBP, A_IMM32, FWSTACK>>16, FWSTACK&0xFF, + I_MOV_R_I, RSP, A_IMM32, FWSTACK>>16, FWSTACK&0xFF, + + I_MOV_M_I, A_MEM, RBP, A_IMM16, 0xAC, + I_SUB_R_I, RBP, A_IMM16, 8, + I_ADD_M_R, A_OFF, 8, RBP, RSP, + I_MOV_R_M, RAX, A_MEM, RBP, }; ushort bget(ctx_t *ctx) diff --git a/karch/regs.c b/karch/regs.c index bed98a7..5fbe145 100644 --- a/karch/regs.c +++ b/karch/regs.c @@ -39,6 +39,5 @@ reg_t arch_r[NREGS] = { "cr7", "Control register 7", 0, CTL }, { "rip", "Instruction pointer", 0, RES }, { "flg", "Flags register", 0, RES }, - { "ret", "Return address", 0, RES }, };