diff --git a/Makefile b/Makefile index 1b03c2d..f86b627 100644 --- a/Makefile +++ b/Makefile @@ -8,9 +8,13 @@ kpc: @cd pc && make --no-print-directory kas: kpc as/k-as.py as/regs.lst as/testfile.asm - @cp pc/instrs.lst as + @cp pc/instrs/instrs.lst as + @rm -f pc/instrs/instrs.lst test: kas @cd as && ./k-as.py testfile.asm 0x100000 testout.out @pc/k.exe as/testout.out +disasm: kas + @cd as && ./k-as.py testfile.asm 0x100000 testout.out + @pc/k.exe as/testout.out -d diff --git a/as/k-as.py b/as/k-as.py index 4b7402b..642da44 100755 --- a/as/k-as.py +++ b/as/k-as.py @@ -13,11 +13,9 @@ if len(sys.argv) != 4: .format(sys.argv[0])) sys.exit(1) -# TemporaryFile(mode='w+') -instrs = open("testfile.out.1", "w+") - -b_data = open("testfile.out.2", "w+b") -b_text = open("testfile.out.3", "w+b") +instrs = open("{}.instr".format(sys.argv[3]), "w+") +b_data = open("{}.data".format(sys.argv[3]), "w+b") +b_text = open("{}.text".format(sys.argv[3]), "w+b") lst_regs = open("regs.lst") lst_instrs = open("instrs.lst") @@ -69,7 +67,7 @@ pdata_pad = 0 def name_valid(name): for c in name.lower(): - if not(c in 'abcdefghijklmnopqrstuvwxyz0123456789[$%._+]='): + if not(c in 'abcdefghijklmnopqrstuvwxyz0123456789[$._+]='): print("BAD '{}'".format(c)) return False return True @@ -93,27 +91,59 @@ def parse_preproc(line): tok = line.split(' ', 2) - for word in tok: - if not name_valid(word): - print("Invalid token in line: {}".format(line)) - return + #for word in tok: + # if not name_valid(word): + # print("Invalid token in line: {}".format(line)) + # return - if tok[0] == 'def': + # preprocessor + if len(tok) > 1 and tok[1] == ':=': if len(tok) < 3: print("Invalid format: {}".format(line)) - else: - pdefs[tok[1]] = tok[2] + leave() + sys.exit(1) + pdefs[tok[0]] = tok[2] return # .data if len(tok) > 1 and tok[1] == '=': if len(tok) < 3: print("Invalid format: {}".format(line)) - else: + leave() + sys.exit(1) + + if is_number(tok[2]): plabels_data[tok[0]] = pdata - written = b_data.write(int(tok[2]).to_bytes(8, byteorder='little', signed=False)) + written = b_data.write(int(tok[2], base=0).to_bytes(8, byteorder='little', signed=False)) assert(written == 8) pdata += written + + elif tok[2][0] == "'": + s = tok[2].strip() + assert(s[-1] == "'") + + s = s[1:-1] + assert(not "'" in s) + + plabels_data[tok[0]] = pdata + pdefs[tok[0] + "_len"] = str(len(s)) + + for c in s: + written = b_data.write(ord(c).to_bytes(1, byteorder='little', signed=False)) + assert(written == 1) + pdata += 1 + + # align + for i in range(8 - len(s) % 8): + written = b_data.write(int(0).to_bytes(1, byteorder='little', signed=False)) + assert(written == 1) + pdata += 1 + + else: + print("Invalid format: {}".format(line)) + leave() + sys.exit(1) + return print("Unrecognized directive: {}".format(line)) @@ -205,8 +235,17 @@ def is_number(s): return True def parse_instr(line): + # instrs.write(hex(ptext)) tok = line.split(' ') fellthrough = False + + size = 2 + + if tok[0] == "rep": + instrs.write("%rep ") + tok = tok[1:] + size += 2 + instr_name = tok[0] instr_args = '' @@ -214,8 +253,9 @@ def parse_instr(line): instrs.write("{}".format(instr_name)) return 2 # instruction - size = 2 - for word in line.split(' ')[1:]: + tok = tok[1:] + + for word in tok: instr_args += ' ' pref = None @@ -226,7 +266,7 @@ def parse_instr(line): pref = "%b" elif word[0] == 'w': pref = "%w" - elif word[0] == 'l': + elif word[0] == 'l' or word[0] == 'd': pref = "%l" elif word[0] == 'q': pref = "%q" @@ -254,14 +294,15 @@ def parse_instr(line): instr_args += "off " assert(len(word) > 3) - assert(word[2] == '+' or word[3] == '+') - - if word[2] == '+': - # r8, k0, etc - instr_args += "{} {}".format(word[3:], word[:2]) - else: - # rax, cr0, etc - instr_args += "{} {}".format(word[4:], word[:3]) + + reg, off = word.strip().split('+', 1) + reg = reg.strip() + off = off.strip() + + print(reg) + print(off) + + instr_args += "{} {}".format(off, reg) continue @@ -293,7 +334,7 @@ def parse_instr(line): continue # it's a label (a 64-bit immediate) - # +2 for A_IMM16, +2 for immediate + # +2 for A_IMM64, +8 for immediate size += 2 + 8 if not fellthrough: instr_name += "_i" @@ -320,11 +361,15 @@ special_syms = { "%imm16": 0x7772, "%imm32": 0x7774, "%imm64": 0x7778, + + "%rep": 0x8000 } def gentext(): instrs.seek(0) - text_start = 0x100000 + text_start = 0 # 0x100000 + data_start = text_start + ptext + data_start += (8 - data_start % 8) for _, line in enumerate(instrs): tok = line.strip().split(' ') @@ -342,12 +387,11 @@ def gentext(): if word in plabels_text: addr = text_start + plabels_text[word] - print(addr.to_bytes(8, byteorder='big', signed=False)) - b_text.write(addr.to_bytes(8, byteorder='big', signed=False)) + b_text.write(addr.to_bytes(8, byteorder='little', signed=False)) continue if word in plabels_data: - addr = text_start + plabels_data[word] + ptext + pdata_pad + addr = data_start + plabels_data[word] + pdata_pad b_text.write(addr.to_bytes(8, byteorder='little', signed=False)) continue @@ -358,6 +402,8 @@ def gentext(): lastimm = 4 elif word == "%imm64": lastimm = 8 + elif word[2:] == "off" and word[0] == '%': + lastimm = 2 b_text.write(special_syms[word].to_bytes(2, byteorder='little', signed=False)) continue @@ -375,6 +421,12 @@ def genout(): b_text.seek(0) b_data.seek(0) b_out.write(b_text.read()) + + data_align = (8 - ptext % 8) + + for i in range(data_align): + b_out.write(int(0).to_bytes(1, byteorder='little', signed=False)) + b_out.write(b_data.read()) #------------------------------------------------------------------------------- diff --git a/as/k-as.py.text b/as/k-as.py.text new file mode 100644 index 0000000..cdc4e1a Binary files /dev/null and b/as/k-as.py.text differ diff --git a/as/regs.lst b/as/regs.lst index fc2caad..c824489 100644 --- a/as/regs.lst +++ b/as/regs.lst @@ -1,28 +1,32 @@ inv +rip +flg +rbp +rsp rax rbx rcx rdx +rsx +rbi rdi rsi -rbp -rsp -r8 -r9 -r10 -r11 -r12 -r13 -r14 -r15 -k0 -k1 -k2 -k3 -k4 -k5 -k6 -k7 +nx0 +nx1 +nx2 +nx3 +nx4 +nx5 +nx6 +nx7 +ax0 +ax1 +ax2 +ax3 +ax4 +ax5 +ax6 +ax7 cr0 cr1 cr2 @@ -31,5 +35,11 @@ cr4 cr5 cr6 cr7 -rip -flg +sa0 +sa1 +sa2 +sa3 +sa4 +sa5 +sa6 +sa7 diff --git a/as/testfile.asm b/as/testfile.asm index ec92e5a..187f3af 100644 --- a/as/testfile.asm +++ b/as/testfile.asm @@ -1,13 +1,35 @@ # Test assembly file # Wololo! -def y 4 +hw = 'Hello World' + +main: + ; This comment is successfully ignored + mov rbp, 0x200000 + mov rsp, rbp + + mov ax0, hw + mov ax1, hw_len + call print -label1: - call label2 stop -label2: - add rax, 1 +print: + enter + + mov rcx, ax1 + rep call .pch1 + + leave + ret + +.pch1: + test b[ax0], b[ax0] + jnz .pch2 + ret + +.pch2: + prn b[ax0] + inc ax0 ret diff --git a/pc/Makefile b/pc/Makefile index 3270bc4..e59f9f6 100644 --- a/pc/Makefile +++ b/pc/Makefile @@ -3,23 +3,25 @@ all: k.exe -src = instrs.c decd.c main.c regs.c dump.c jumps.c except.c disdec.c mem.c +src = instrs/instrs.c decd.c main.c regs.c dump.c \ + instrs/jumps.c except.c disd.c mem.c instrs/logic.c \ + instrs/stack.c instrs/super.c instrs/arith.c obj = $(patsubst %.c,%.o,$(src)) %.o: %.c i_arch.h *.h $(src) - @gcc -O2 -Wall -c $< -o $@ + @gcc -O2 -g -Wall -c $< -o $@ -i_arch.h: INSTRS instrs.py - @python3 instrs.py +i_arch.h: instrs/INSTRS instrs/arch_i.py + @cd instrs && python3 arch_i.py .PHONY: clean clean: @rm *.o -k.exe: $(obj) i_arch.h INSTRS instrs.py +k.exe: $(obj) i_arch.h @gcc -O2 -Wall $(obj) -o k.exe - @rm arch_i.h - @rm *.o + @rm instrs/arch_i.h + @rm *.o */*.o diff --git a/pc/arch.h b/pc/arch.h index fd0377f..a2f3c44 100644 --- a/pc/arch.h +++ b/pc/arch.h @@ -1,6 +1,7 @@ // 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 @@ -26,50 +27,6 @@ typedef struct instr_t instr_t; typedef struct acc_t acc_t; typedef struct arch_t arch_t; -enum -{ - INV, - RAX, RBX, RCX, RDX, RDI, RSI, RBP, RSP, - R8, R9, R10, R11, R12, R13, R14, R15, - K0, K1, K2, K3, K4, K5, K6, K7, - CR0, CR1, CR2, CR3, CR4, CR5, CR6, CR7, - RIP, FLG, - - NREGS -}; - -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 -}; - -// FLG register -enum -{ - CF = 1 << 0, // Carry flag - PF = 1 << 1, // Parity flag - AC = 1 << 2, // Auxiliary flag - ZF = 1 << 3, // Zero flag - OV = 1 << 4, // Overflow flag - DF = 1 << 5, // Direction flag - SF = 1 << 6, // Sign flag - - UF = 1 << 16, // User-mode flag - IF = 1 << 17, // Interrupts enable flag -}; - -struct reg_t -{ - char *name; - char *desc; - ulong val; - ulong flags; -}; - // A_REG is implicit // A_MEM denotes a memory access // A_OFF is A_MEM but a 16-bit offset is expected immediatly next @@ -104,11 +61,12 @@ enum struct acc_t { bool mem; - uint len; - uint type; - - ulong val; + uint mlen; short off; + + uint type; + uint ilen; + ulong val; }; enum { NOPREF, PREF_REP=0x8000, PREF_LOCK, NPREFS }; @@ -145,6 +103,12 @@ struct ctx_t FILE *disf; }; +static inline ushort bswap16(ushort u) +{ return ((u<<8) | (u>>8)); } + +static inline char getmempref(ushort len) +{ return (len==1?'b':(len==2?'w':(len==4?'l':(len==8?'q':'x')))); } + enum { E_SHT, // Shutdown instruction @@ -158,7 +122,7 @@ enum }; void dumpregs(ctx_t *); -void dumpinstr(ctx_t *, ulong, ushort, acc_t *, acc_t *); +void dumpinstr(ctx_t *, ulong, uint, ushort, acc_t *, acc_t *); void dumpmem(ctx_t *, ulong, ulong); void dumpfwstack(ctx_t *); @@ -188,5 +152,9 @@ void writemem32(ctx_t *, ulong val, ulong addr); void writemem64(ctx_t *, ulong val, ulong addr); void writemem(ctx_t *, ulong val, ulong addr, uint len); -#include "arch_i.h" +#include "regs.h" +#include "instrs/arch_i.h" + +extern reg_t arch_r[NREGS]; +extern instr_t arch_i[NINSTRS]; diff --git a/pc/decd.c b/pc/decd.c index 21b0b01..c7e1061 100644 --- a/pc/decd.c +++ b/pc/decd.c @@ -36,13 +36,13 @@ static void scan_param(ctx_t *ctx, acc_t *p) if (A_IS_MEM(c)) { p->mem = 1; p->off = 0; - p->len = c & 0xF; + p->mlen = c & 0xF; c = ctx->get(ctx); } else if (A_IS_OFF(c)) { p->mem = 1; - p->len = c & 0xF; + p->mlen = c & 0xF; p->off = (short)ctx->get(ctx); c = ctx->get(ctx); } @@ -59,13 +59,15 @@ static void scan_param(ctx_t *ctx, acc_t *p) p->val = c; if (p->type == A_IMM32) { - p->val = (p->val << 16) | ctx->get(ctx); + p->ilen = 4; + p->val = p->val | ((ulong)ctx->get(ctx) << 16); } 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); + p->ilen = 8; + p->val = p->val | ((ulong)ctx->get(ctx) << 16); + p->val = p->val | ((ulong)ctx->get(ctx) << 32); + p->val = p->val | ((ulong)ctx->get(ctx) << 48); } else if (p->type == A_REG) { @@ -90,11 +92,15 @@ void disasm(ctx_t *ctx) instr_t *i; acc_t p1 = { 0 }, p2 = { 0 }; + uint rep = 0; ulong rip = ctx->r[RIP].val; ushort c = ctx->get(ctx); if (ISPREF(c)) { - // nothing for now + if (c == PREF_REP) { + rep = 1; + c = ctx->get(ctx); + } } else if (!ISINSTR(c)) { @@ -111,10 +117,18 @@ void disasm(ctx_t *ctx) } } - dumpinstr(ctx, rip, c, &p1, &p2); + dumpinstr(ctx, rip, rep, c, &p1, &p2); #ifndef _NEED_DISASM + +do_rep: i->func(ctx, &p1, &p2); + + if (rep && ctx->r[RCX].val > 0) { + ctx->r[RCX].val--; + goto do_rep; + } + #endif } diff --git a/pc/disdec.c b/pc/disd.c similarity index 100% rename from pc/disdec.c rename to pc/disd.c diff --git a/pc/dump.c b/pc/dump.c index a4a181f..6dd89b5 100644 --- a/pc/dump.c +++ b/pc/dump.c @@ -3,25 +3,6 @@ #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 < K0; i++) { - if (i % 4 == 0) - log("\n"); - - r = &ctx->r[i]; - log("%s%s=0x%016lX ", r->name, - (strlen(r->name) == 2 ? "=" : ""), r->val); - } - log("\n"); -} - void dumpmem(ctx_t *ctx, ulong start, ulong size) { uint i; @@ -63,24 +44,27 @@ void d_log(ctx_t *ctx, char *fmt, ...) va_end(ap); } -void dumpinstr(ctx_t *ctx, ulong rip, ushort c, acc_t *p1, acc_t *p2) +void dumpinstr(ctx_t *ctx, ulong rip, uint rep, + ushort c, acc_t *p1, acc_t *p2) { acc_t *p = 0; instr_t *i = &ctx->i[c]; - d_log(ctx, "0x%08lX: %s", rip, i->name); + d_log(ctx, "0x%08lX: %s%s", rip, + (rep ? "rep " : ""), + i->name); if (i->prm1 != NOPRM) p = p1; lp: if (p != 0) { - if (p->mem) d_log(ctx, " ["); + if (p->mem) d_log(ctx, " %c:[", getmempref(p->mlen)); else d_log(ctx, " "); if (p->type == A_REG) d_log(ctx, "%s", ctx->r[p->val].name); else - d_log(ctx, "0x%lX", p->val); + d_log(ctx, "%c:0x%lX", getmempref(p->ilen), p->val); if (p->mem) { if (p->off) diff --git a/pc/except.c b/pc/except.c index 4cae3bb..8619df8 100644 --- a/pc/except.c +++ b/pc/except.c @@ -20,6 +20,6 @@ void _except(ctx_t *ctx, int code, char *fmt, ...) if (ctx->mp) free(ctx->mp); - exit(code+1); + exit(code); } diff --git a/pc/instrs.c b/pc/instrs.c deleted file mode 100644 index 770478b..0000000 --- a/pc/instrs.c +++ /dev/null @@ -1,298 +0,0 @@ -// 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; - diff --git a/pc/INSTRS b/pc/instrs/INSTRS similarity index 92% rename from pc/INSTRS rename to pc/instrs/INSTRS index 896e123..bc5a4f7 100644 --- a/pc/INSTRS +++ b/pc/instrs/INSTRS @@ -157,14 +157,19 @@ xchg m m lea r m lea m m +# get code segment +gcs r m + # # Stack manipulation instructions # push i push r +push m pop r +pop m call r call i @@ -172,6 +177,9 @@ call m ret +enter +leave + pushf # @@ -183,3 +191,8 @@ popf cli sti +# Prints a character on the screen +prn r +prn i +prn m + diff --git a/pc/instrs.py b/pc/instrs/arch_i.py similarity index 96% rename from pc/instrs.py rename to pc/instrs/arch_i.py index f1b4940..f51911f 100644 --- a/pc/instrs.py +++ b/pc/instrs/arch_i.py @@ -9,7 +9,7 @@ ls = open("instrs.lst", "w") count = 0 -hd.write("// Auto-generated by instrs.py from INSTRS\n\n"); +hd.write("// Auto-generated by arch_i.py from INSTRS\n\n"); hd.write("#ifdef _NEED_ARCH_I\n") hd.write("instr_t arch_i[] =\n{\n\n") diff --git a/pc/instrs/arith.c b/pc/instrs/arith.c new file mode 100644 index 0000000..638c864 --- /dev/null +++ b/pc/instrs/arith.c @@ -0,0 +1,67 @@ +// 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" + +// +// 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; + diff --git a/pc/instrs/instrs.c b/pc/instrs/instrs.c new file mode 100644 index 0000000..b98c014 --- /dev/null +++ b/pc/instrs/instrs.c @@ -0,0 +1,70 @@ +// 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; + +// +// 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; + +IMPL_START_1(gcs) +{ + v1 = ctx->r[CR1].val; +} +IMPL_OUT; + +// +// Misc. instructions +// + +IMPL_START_1(prn) +{ + if (p1->mlen > 1) { + log("prn warning: large access size\n"); + } + + if (!(v1 >= ' ' && v1 < 128) && v1 != '\t') { + if (v1 == '\n') { + log("prn on newline character\n"); + } + else + log("prn on invalid character: %ld\n", v1); + } + + else { + log("prn instruction with character: '%c'\n", (char)v1); + } +} +IMPL_END; + diff --git a/pc/instrs.h b/pc/instrs/instrs.h similarity index 64% rename from pc/instrs.h rename to pc/instrs/instrs.h index cdb846c..ef42c07 100644 --- a/pc/instrs.h +++ b/pc/instrs/instrs.h @@ -1,7 +1,7 @@ // 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 "arch.h" +#include "../arch.h" #define IMPL_START_0(name) \ void i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2) \ @@ -11,27 +11,27 @@ 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 = readmem(ctx, v1 + p1->off, p1->len); \ + if (p1->mem) v1 = readmem(ctx, v1 + p1->off, p1->mlen); \ #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 = readmem(ctx, v1 + p1->off, p1->len); \ - if (p2->mem) v2 = readmem(ctx, v2 + p2->off, p2->len); \ + if (p1->mem) v1 = readmem(ctx, v1 + p1->off, p1->mlen); \ + if (p2->mem) v2 = readmem(ctx, v2 + p2->off, p2->mlen); \ #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 = readmem(ctx, v2 + p2->off, p2->len); \ + if (p2->mem) v2 = readmem(ctx, v2 + p2->off, p2->mlen); \ #define IMPL_OUT \ assert(p1->type == A_REG || p1->mem); \ if (p1->mem) { \ ulong addr = p1->type == A_REG ? ctx->r[p1->val].val : p1->val; \ - writemem(ctx, v1, addr, p1->len); \ + writemem(ctx, v1, addr, p1->mlen); \ } \ else ctx->r[p1->val].val = v1; \ } \ @@ -46,3 +46,25 @@ void i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2) \ } \ } while (0) +#define CHK_STACK(op) \ + if (ctx->r[RSP].val % 8 > 0 || ctx->r[RBP].val % 8 > 0) { \ + _except(ctx, E_STK, "Misaligned stack REGS"); \ + } \ + if (ctx->r[RBP].val op ctx->r[RSP].val) { \ + _except(ctx, E_STK, "RSP above RBP"); \ + } + +#define PUSH(v) \ + writemem64(ctx, v, ctx->r[RSP].val); \ + ctx->r[RSP].val -= 8; \ + +#define POP(v) \ + ctx->r[RSP].val += 8; \ + v = readmem64(ctx, ctx->r[RSP].val); + +#define JUMP(v) \ + ctx->r[RIP].val = v + ctx->r[CR1].val + + + + diff --git a/pc/jumps.c b/pc/instrs/jumps.c similarity index 76% rename from pc/jumps.c rename to pc/instrs/jumps.c index 607aa4f..1ca7b63 100644 --- a/pc/jumps.c +++ b/pc/instrs/jumps.c @@ -4,6 +4,10 @@ #include "instrs.h" #include "arch_i.h" +// +// Jump instructions +// + IMPL_START_1(jmp) { ctx->r[RIP].val = v1; @@ -13,62 +17,62 @@ IMPL_END; IMPL_START_1(jz) { if (ctx->r[FLG].val & ZF) - ctx->r[RIP].val = v1; + JUMP(v1); } IMPL_END; IMPL_START_1(jnz) { if (!(ctx->r[FLG].val & ZF)) - ctx->r[RIP].val = v1; + JUMP(v1); } IMPL_END; IMPL_START_1(je) { if (ctx->r[FLG].val & ZF) - ctx->r[RIP].val = v1; + JUMP(v1); } IMPL_END; IMPL_START_1(jne) { if (!(ctx->r[FLG].val & ZF)) - ctx->r[RIP].val = v1; + JUMP(v1); } IMPL_END; IMPL_START_1(ja) { if (!(ctx->r[FLG].val & ZF) && !(ctx->r[FLG].val & CF)) - ctx->r[RIP].val = v1; + JUMP(v1); } IMPL_END; IMPL_START_1(jae) { if (!(ctx->r[FLG].val & CF)) - ctx->r[RIP].val = v1; + JUMP(v1); } IMPL_END; IMPL_START_1(jb) { if (!(ctx->r[FLG].val & ZF) && ctx->r[FLG].val & CF) - ctx->r[RIP].val = v1; + JUMP(v1); } IMPL_END; IMPL_START_1(jbe) { if (ctx->r[FLG].val & CF) - ctx->r[RIP].val = v1; + JUMP(v1); } IMPL_END; IMPL_START_1(jcxz) { if (!ctx->r[RCX].val) - ctx->r[RIP].val = v1; + JUMP(v1); } IMPL_END; diff --git a/pc/instrs/logic.c b/pc/instrs/logic.c new file mode 100644 index 0000000..721fa68 --- /dev/null +++ b/pc/instrs/logic.c @@ -0,0 +1,78 @@ +// 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" + +// +// Comparison instructions +// + +IMPL_START_2(test) +{ + ulong v = v1 & v2; + + if (v == 0) ctx->r[FLG].val |= ZF; + else ctx->r[FLG].val &= ~ZF; +} +IMPL_END; + +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; + +// +// 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; + diff --git a/pc/instrs/stack.c b/pc/instrs/stack.c new file mode 100644 index 0000000..ee29bf2 --- /dev/null +++ b/pc/instrs/stack.c @@ -0,0 +1,75 @@ +// 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" + +// +// Stack manipulation instructions +// + +IMPL_START_1(push) +{ + CHK_STACK(<); + PUSH(v1); +} +IMPL_END; + +IMPL_START_1(pop) +{ + CHK_STACK(<=); + POP(v1); +} +IMPL_OUT; + +IMPL_START_1(call) +{ + CHK_STACK(<); + PUSH(ctx->r[RIP].val); + JUMP(v1); +} +IMPL_END; + +IMPL_START_0(ret) +{ + CHK_STACK(<=); + POP(ctx->r[RIP].val); +} +IMPL_END; + +IMPL_START_0(enter) +{ + CHK_STACK(<); + PUSH(ctx->r[RBP].val); + ctx->r[RBP].val = ctx->r[RSP].val; +} +IMPL_END; + +IMPL_START_0(leave) +{ + // Do NOT check stack here! + POP(ctx->r[RBP].val); +} +IMPL_END; + +IMPL_START_0(pushf) +{ + CHK_STACK(<); + + writemem64(ctx, ctx->r[FLG].val, ctx->r[RSP].val); + ctx->r[RSP].val -= 8; +} +IMPL_END; + +IMPL_START_0(popf) +{ + CHK_STACK(<=); + + CHK_SUPERV(); // XXX + + ctx->r[RSP].val += 8; + ctx->r[FLG].val = readmem64(ctx, ctx->r[RSP].val); +} +IMPL_END; + + diff --git a/pc/instrs/super.c b/pc/instrs/super.c new file mode 100644 index 0000000..a3812f2 --- /dev/null +++ b/pc/instrs/super.c @@ -0,0 +1,30 @@ +// 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" + +// +// 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; + diff --git a/pc/main.c b/pc/main.c index ecef88f..1b37a33 100644 --- a/pc/main.c +++ b/pc/main.c @@ -18,7 +18,7 @@ ushort bget(ctx_t *ctx) _except(ctx, E_ACC, "Executing out of memory: 0x%016lX", ctx->r[RIP].val); } - + ushort c = ctx->mp[addr2real(ctx->r[RIP].val)]; ctx->r[RIP].val += 2; @@ -40,9 +40,6 @@ ushort dget(ctx_t *ctx) return fwprog[i++]; } -extern reg_t arch_r[NREGS]; -extern instr_t arch_i[NINSTRS]; - int main(int argc, char **argv) { ctx_t main_ctx; diff --git a/pc/mem.c b/pc/mem.c index 30c7b8d..c5a6d62 100644 --- a/pc/mem.c +++ b/pc/mem.c @@ -16,26 +16,28 @@ ulong readmem(ctx_t *ctx, ulong addr, uint len) ulong readmem8(ctx_t *ctx, ulong addr) { + addr += ctx->r[CR2].val; ulong real = addr2real(addr); if (addr < MEMOFF || real >= MEMSIZE) { - _except(ctx, E_ACC, "Invalid MEM access: 0x%012lX(0x%012lX)", addr, real); + _except(ctx, E_ACC, "Invalid MEM access: 0x%012lX (0x%012lX)", addr, real); } - if (addr % 2) return (ulong)ctx->mp[real] & 0xFF; + if (addr % 2 == 0) return (ulong)ctx->mp[real] & 0xFF; else return ((ulong)ctx->mp[real] & 0xFF00) >> 8; } ulong readmem16(ctx_t *ctx, ulong addr) { + addr += ctx->r[CR2].val; ulong real = addr2real(addr); if (addr % alignof(ushort) > 0) { - _except(ctx, E_ALI, "Non-aligned memory access: 0x%012lX(0x%012lX)", addr, real); + _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); + _except(ctx, E_ACC, "Invalid MEM access: 0x%012lX (0x%012lX)", addr, real); } return (ulong)ctx->mp[real]; @@ -43,44 +45,47 @@ ulong readmem16(ctx_t *ctx, ulong addr) ulong readmem32(ctx_t *ctx, ulong addr) { + addr += ctx->r[CR2].val; ulong real = addr2real(addr); if (addr % alignof(uint) > 0) { - _except(ctx, E_ALI, "Non-aligned memory access: 0x%012lX(0x%012lX)", addr, real); + _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); + _except(ctx, E_ACC, "Invalid MEM access: 0x%012lX (0x%012lX)", addr, real); } - ulong val = (ulong)ctx->mp[real++]; - val = (val << 16) | (ulong)ctx->mp[real]; + ulong val = ctx->mp[real++]; + val = val | ((ulong)ctx->mp[real] << 16); return val; } ulong readmem64(ctx_t *ctx, ulong addr) { + addr += ctx->r[CR2].val; ulong real = addr2real(addr); if (addr % alignof(ulong) > 0) { - _except(ctx, E_ALI, "Non-aligned memory access: 0x%012lX(0x%012lX)", addr, real); + _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); + _except(ctx, E_ACC, "Invalid MEM access: 0x%012lX (0x%012lX)", addr, real); } 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]; + val = val | ((ulong)ctx->mp[real++] << 16); + val = val | ((ulong)ctx->mp[real++] << 32); + val = val | ((ulong)ctx->mp[real] << 48); return val; } void writemem(ctx_t *ctx, ulong val, ulong addr, uint len) { + addr += ctx->r[CR2].val; switch (len) { case 1: writemem8(ctx, val, addr); break; case 2: writemem16(ctx, val, addr); break; @@ -92,10 +97,11 @@ void writemem(ctx_t *ctx, ulong val, ulong addr, uint len) void writemem8(ctx_t *ctx, ulong val, ulong addr) { + addr += ctx->r[CR2].val; ulong real = addr2real(addr); if (addr < MEMOFF || real >= MEMSIZE) { - _except(ctx, E_ACC, "Invalid MEM access: 0x%012lX(0x%012lX)", addr, real); + _except(ctx, E_ACC, "Invalid MEM access: 0x%012lX (0x%012lX)", addr, real); } ushort v = ctx->mp[real]; @@ -111,14 +117,15 @@ void writemem8(ctx_t *ctx, ulong val, ulong addr) void writemem16(ctx_t *ctx, ulong val, ulong addr) { + addr += ctx->r[CR2].val; ulong real = addr2real(addr); if (addr % alignof(ushort) > 0) { - _except(ctx, E_ALI, "Non-aligned memory access: 0x%012lX(0x%012lX)", addr, real); + _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); + _except(ctx, E_ACC, "Invalid MEM access: 0x%012lX (0x%012lX)", addr, real); } ctx->mp[real] = val & 0xFFFF; @@ -126,34 +133,37 @@ void writemem16(ctx_t *ctx, ulong val, ulong addr) void writemem32(ctx_t *ctx, ulong val, ulong addr) { + addr += ctx->r[CR2].val; ulong real = addr2real(addr); if (addr % alignof(uint) > 0) { - _except(ctx, E_ALI, "Non-aligned memory access: 0x%012lX(0x%012lX)", addr, real); + _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); + _except(ctx, E_ACC, "Invalid MEM access: 0x%012lX (0x%012lX)", addr, real); } - ctx->mp[real++] = (val >> 16) & 0xFFFF; - ctx->mp[real] = val & 0xFFFF; + ctx->mp[real++] = val & 0xFFFF; + ctx->mp[real] = (val >> 16) & 0xFFFF; } void writemem64(ctx_t *ctx, ulong val, ulong addr) { + addr += ctx->r[CR2].val; ulong real = addr2real(addr); if (addr % alignof(ulong) > 0) { - _except(ctx, E_ALI, "Non-aligned memory access: 0x%012lX(0x%012lX)", addr, real); + _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); + _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; ctx->mp[real++] = (val >> 16) & 0xFFFF; - ctx->mp[real] = val & 0xFFFF; + ctx->mp[real++] = (val >> 32) & 0xFFFF; + ctx->mp[real] = (val >> 48) & 0xFFFF; } + diff --git a/pc/regs.c b/pc/regs.c index 35c2cc0..469df6e 100644 --- a/pc/regs.c +++ b/pc/regs.c @@ -6,39 +6,85 @@ reg_t arch_r[NREGS] = { { "inv", "Invalid register", 0, RES }, - { "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 }, - { "r8", "Accumulator 8", 0, GPR }, - { "r9", "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 }, - { "k0", "Supervisor accumulator 0", 0, SYS }, - { "k1", "Supervisor accumulator 1", 0, SYS }, - { "k2", "Supervisor accumulator 2", 0, SYS }, - { "k3", "Supervisor accumulator 3", 0, SYS }, - { "k4", "Supervisor accumulator 4", 0, SYS }, - { "k5", "Supervisor accumulator 5", 0, SYS }, - { "k6", "Supervisor accumulator 6", 0, SYS }, - { "k7", "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 }, - { "flg", "Flags register", 0, RES }, + + { "rip", "Instruction pointer", "Special; Volatile", 0, RES }, + { "flg", "Flags register", "Special; Volatile", 0, RES }, + + { "rbp", "Stack base", "Special; Non-volatile", 0, GPR }, + { "rsp", "Stack pointer", "Special; Non-volatile", 0, GPR }, + + { "rax", "Accumulator 0", "Volatile", 0, GPR }, + { "rbx", "Accumulator 1", "Volatile", 0, GPR }, + { "rcx", "Accumulator 2", "Volatile", 0, GPR }, + { "rdx", "Accumulator 3", "Volatile", 0, GPR }, + { "rsx", "Accumulator 4", "Volatile", 0, GPR }, + { "rbi", "Accumulator 5", "Volatile", 0, GPR }, + { "rdi", "Accumulator 6", "Volatile", 0, GPR }, + { "rsi", "Accumulator 7", "Volatile", 0, GPR }, + + { "nx0", "Accumulator 8", "Non-volatile", 0, GPR }, + { "nx1", "Accumulator 9", "Non-volatile", 0, GPR }, + { "nx2", "Accumulator 10", "Non-volatile", 0, GPR }, + { "nx3", "Accumulator 11", "Non-volatile", 0, GPR }, + { "nx4", "Accumulator 12", "Non-volatile", 0, GPR }, + { "nx5", "Accumulator 13", "Non-volatile", 0, GPR }, + { "nx6", "Accumulator 14", "Non-volatile", 0, GPR }, + { "nx7", "Accumulator 15", "Non-volatile", 0, GPR }, + + { "ax0", "Argument 0", "Volatile", 0, GPR }, + { "ax1", "Argument 1", "Volatile", 0, GPR }, + { "ax2", "Argument 2", "Volatile", 0, GPR }, + { "ax3", "Argument 3", "Volatile", 0, GPR }, + { "ax4", "Argument 4", "Volatile", 0, GPR }, + { "ax5", "Argument 5", "Volatile", 0, GPR }, + { "ax6", "Argument 6", "Volatile", 0, GPR }, + { "ax7", "Argument 7", "Volatile", 0, GPR }, + + // cr0: various flags + { "cr0", "Control register 0", "Control", 0, CTL }, + + // cr1: code offset + { "cr1", "Control register 1", "Control", 0x100000, CTL }, + + // cr2: data offset + { "cr2", "Control register 2", "Control", 0x100000, CTL }, + + // unused + { "cr3", "Control register 3", "Control", 0, CTL }, + { "cr4", "Control register 4", "Control", 0, CTL }, + { "cr5", "Control register 5", "Control", 0, CTL }, + { "cr6", "Control register 6", "Control", 0, CTL }, + { "cr7", "Control register 7", "Control", 0, CTL }, + + { "sa0", "Supervisor acc. 0", "System; Non-volatile", 0, SYS }, + { "sa1", "Supervisor acc. 1", "System; Non-volatile", 0, SYS }, + { "sa2", "Supervisor acc. 2", "System; Non-volatile", 0, SYS }, + { "sa3", "Supervisor acc. 3", "System; Non-volatile", 0, SYS }, + { "sa4", "Supervisor acc. 4", "System; Non-volatile", 0, SYS }, + { "sa5", "Supervisor acc. 5", "System; Non-volatile", 0, SYS }, + { "sa6", "Supervisor acc. 6", "System; Non-volatile", 0, SYS }, + { "sa7", "Supervisor acc. 7", "System; Non-volatile", 0, SYS }, }; +void dumpregs(ctx_t *ctx) +{ + int i; + reg_t *r; + + //assert(ctx->r[INV].val == 0); + + log("\nRegisters:\n"); + log("rip=0x%-16lX flg=0x%-16lX ", ctx->r[RIP].val, ctx->r[FLG].val); + log("rbp=0x%-16lX rsp=0x%-16lX", ctx->r[RBP].val, ctx->r[RSP].val); + + for (i = RAX; i < CR4; i++) { + if ((i-1) % 4 == 0) + log("\n"); + + r = &ctx->r[i]; + log("%s%s=0x%-16lX ", r->name, + (strlen(r->name) == 2 ? "=" : ""), r->val); + } + log("\n"); +} + diff --git a/pc/regs.h b/pc/regs.h new file mode 100644 index 0000000..7afa634 --- /dev/null +++ b/pc/regs.h @@ -0,0 +1,95 @@ +// The OS/K Team licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +enum +{ + INV, + + RIP, + FLG, + + RBP, + RSP, + + RAX, + RBX, + RCX, + RDX, + RSX, + RBI, + RDI, + RSI, + + NX0, + NX1, + NX2, + NX3, + NX4, + NX5, + NX6, + NX7, + + AX0, + AX1, + AX2, + AX3, + AX4, + AX5, + AX6, + AX7, + + CR0, + CR1, + CR2, + CR3, + CR4, + CR5, + CR6, + CR7, + + SA0, + SA1, + SA2, + SA3, + SA4, + SA5, + SA6, + SA7, + + NREGS +}; + +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 +}; + +// FLG register +enum +{ + CF = 1 << 0, // Carry flag + PF = 1 << 1, // Parity flag + AC = 1 << 2, // Auxiliary flag + ZF = 1 << 3, // Zero flag + OV = 1 << 4, // Overflow flag + DF = 1 << 5, // Direction flag + SF = 1 << 6, // Sign flag + + UF = 1 << 16, // User-mode flag + IF = 1 << 17, // Interrupts enable flag +}; + +struct reg_t +{ + char *name; + char *desc; + char *conv; + ulong val; + ulong flags; +}; + +