diff --git a/Makefile b/Makefile index 7e278c1..b8ec093 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ all: k.exe src = instr/instrs.c karch/decd.c karch/main.c karch/regs.c obj = $(patsubst %.c,%.o,$(src)) -%.o: %.c instrs/i_arch.h */*.h +%.o: %.c instrs/i_arch.h */*.h */*.c @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 b09990f..c4054b0 100644 --- a/instr/INSTRS +++ b/instr/INSTRS @@ -1,6 +1,8 @@ # The OS/K Team licences this file to you under the MIT license. # See the LICENSE file in the project root for more information. +nop + add r r add r i add r m diff --git a/instr/instrs.c b/instr/instrs.c index 86bff40..f37ba73 100644 --- a/instr/instrs.c +++ b/instr/instrs.c @@ -3,6 +3,11 @@ #include "instrs.h" +IMPL_START_0(nop) +{ +} +IMPL_END; + IMPL_START_2(add) { v1 += v2; diff --git a/instr/instrs.py b/instr/instrs.py index b817271..c8b8c6d 100644 --- a/instr/instrs.py +++ b/instr/instrs.py @@ -53,7 +53,7 @@ for _, line in enumerate(fi): hd.write("#define I_{} {}\n".format(name.upper(), count)) hd.write("#ifdef _NEED_ARCH_I\n") hd.write('{{ "{}", "{}", {}, {}, i_{} }},\n'\ - .format(tok[0], name, p1, p2, tok[0])) + .format(tok[0].strip(), name, p1, p2, tok[0])) hd.write("#endif\n\n") count = count + 1 diff --git a/karch/arch.h b/karch/arch.h index a2644e3..f876e9a 100644 --- a/karch/arch.h +++ b/karch/arch.h @@ -1,14 +1,18 @@ // 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 #include #include +#include +#include +#include #define log printf +#define vlog vprintf #define packed __attribute__ ((__packed__)) #define static_assert _Static_assert +#define alignof _Alignof typedef unsigned int bool; typedef unsigned char uchar; @@ -28,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, + RIP, FLG, RET, NREGS }; @@ -83,7 +87,7 @@ struct ctx_t instr_t *i; // Memory and memory size - uchar *mp; + ushort *mp; ulong mz; // Read next instruction @@ -92,24 +96,61 @@ struct ctx_t enum { - E_ILL, // Ill-formed + E_SHT, // Shutdown instruction E_IMP, // Not implemented + E_ILL, // Ill-formed E_ACC, // Invalid access E_SYS, // Supervisor only - E_SHT, // Shutdown instruction + E_ALI, // Alignment error NEXCPTS }; void dumpregs(ctx_t *ctx); -static inline void _except(ctx_t *ctx, int code, char *str) +static inline void _except(ctx_t *ctx, int code, char *fmt, ...) { - log("\nException %d - %s\n", code, str); + va_list ap; + + log("\nException %d - ", code); + + va_start(ap, fmt); + vlog(fmt, ap); + va_end(ap); + + log("\n"); + dumpregs(ctx); - exit(code); + free(ctx->mp); + exit(code+1); } void decode(ctx_t *ctx); +#define MEMOFF (1 * 1024 * 1024) +#define MEMSIZE (16 * 1024 * 1024) // 16MB + +#define addr2real(p) ((p) - MEMOFF) +#define real2addr(p) ((p) + MEMOFF) + +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"); + } + + if (addr < MEMOFF || real >= MEMSIZE) { + _except(ctx, E_ACC, "Accessing inexistent memory"); + } + + ulong val = (ulong)ctx->mp[real++]; + val = (val << 16) | (ulong)ctx->mp[real++]; + val = (val << 16) | (ulong)ctx->mp[real++]; + val = (val << 16) | (ulong)ctx->mp[real++]; + + return val; +} + #include "../instr/arch_i.h" diff --git a/karch/decd.c b/karch/decd.c index 963b1c0..2e94c78 100644 --- a/karch/decd.c +++ b/karch/decd.c @@ -63,11 +63,11 @@ void dumpregs(ctx_t *ctx) log("\n"); } -void dumpinstr(ctx_t *ctx, ushort c, acc_t *p1, acc_t *p2) +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("%s", i->name); + log("0x%016lX: %s", rip, i->name); if (i->prm1 != NOPRM) p = p1; @@ -95,7 +95,8 @@ void decode(ctx_t *ctx) { instr_t *i; acc_t p1 = { 0 }, p2 = { 0 }; - + + ulong rip = ctx->r[RIP].val; ushort c = ctx->get(ctx); if (c == 0xFFFF) { @@ -107,7 +108,7 @@ void decode(ctx_t *ctx) } else if (!ISINSTR(c)) { - _except(ctx, E_ILL, "Bad opcode"); + _except(ctx, E_ILL, "Bad opcode 0x%4hX", c); } // Scanning an instruction @@ -122,7 +123,7 @@ void decode(ctx_t *ctx) } } - dumpinstr(ctx, c, &p1, &p2); + dumpinstr(ctx, rip, c, &p1, &p2); i->func(ctx, &p1, &p2); } diff --git a/karch/main.c b/karch/main.c index 9486fa1..b9b1d7f 100644 --- a/karch/main.c +++ b/karch/main.c @@ -3,7 +3,7 @@ #include "arch.h" -ushort prog[] = { +ushort fwprog[] = { I_ADD_R_I, RDX, A_IMM32, 0xAABB, 0xCCDD, I_MOV_R_R, RAX, RDX, I_MOV_R_I, RBX, A_IMM64, 0x7777, 0x6666, 0x5555, 0x4444, @@ -15,13 +15,15 @@ ushort prog[] = { ushort bget(ctx_t *ctx) { - static int i = 0; - - if (i >= sizeof(prog)/sizeof(ushort)) { - _except(ctx, E_ACC, "End of text"); + if (addr2real(ctx->r[RIP].val) >= MEMSIZE) { + _except(ctx, E_ACC, "Executing out of memory"); } - return prog[i++]; + ushort c = ctx->mp[addr2real(ctx->r[RIP].val)]; + + ctx->r[RIP].val++; + + return c; } extern reg_t arch_r[NREGS]; @@ -34,12 +36,22 @@ int main(void) main_ctx.r = arch_r; main_ctx.i = arch_i; - main_ctx.mp = 0; - main_ctx.mz = 0; + main_ctx.mp = malloc(MEMSIZE); + main_ctx.mz = MEMSIZE; main_ctx.get = bget; + + main_ctx.r[RIP].val = MEMOFF; + + if (main_ctx.mp == 0) { + log("Couldn't allocate RAM"); + exit(-1); + } + + memcpy(&main_ctx.mp[addr2real(main_ctx.r[RIP].val)], fwprog, sizeof(fwprog)); + memset(&main_ctx.mp[addr2real(main_ctx.r[RIP].val) + sizeof(fwprog)/2], 0xFF, 0xFF); - while (1) { + while (1) { decode(&main_ctx); } diff --git a/karch/regs.c b/karch/regs.c index 5fbe145..bed98a7 100644 --- a/karch/regs.c +++ b/karch/regs.c @@ -39,5 +39,6 @@ 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 }, };