diff --git a/vm/Makefile b/vm/Makefile index 5bcada7..31956b5 100644 --- a/vm/Makefile +++ b/vm/Makefile @@ -10,15 +10,15 @@ dv_src = $(shell ls dv/*.c) in_src = $(shell ls in/*.c) pc_src = $(shell ls pc/*.c) -obj = pc/disd.o -obj += $(patsubst %.c,%.o,$(dv_src)) +#obj = pc/disd.o +obj = $(patsubst %.c,%.o,$(dv_src)) obj += $(patsubst %.c,%.o,$(in_src)) obj += $(patsubst %.c,%.o,$(pc_src)) FLAGS=-O2 -g -Wall -fno-builtin-log -I. -pc/disd.o: in/i_arch.h */*.h pc/decd.c - @cc $(FLAGS) -D_NEED_DISASM -c pc/decd.c -o $@ +#pc/disd.o: in/i_arch.h */*.h pc/decd.c +# @cc $(FLAGS) -D_NEED_DISASM -c pc/decd.c -o $@ %.o: %.c in/i_arch.h */*.h $(src) @cc $(FLAGS) -c $< -o $@ diff --git a/vm/dv/devctl.c b/vm/dv/devctl.c index 735bbce..2de26cb 100644 --- a/vm/dv/devctl.c +++ b/vm/dv/devctl.c @@ -46,7 +46,7 @@ IMPL_START_2(devctl) dev_t *dev = devctl_common(ctx, v1, v2); if (dev == NULL) - return; + return 0; switch (v2) { case 0: @@ -90,7 +90,7 @@ IMPL_START_2(iocall) dev_t *dev = devctl_common(ctx, v1, v2); if (dev == NULL) - return; + return 0; if (v2 >= DEVSLOTS) rax = -6; diff --git a/vm/in/arch_i.py b/vm/in/arch_i.py index 408cf01..632b019 100644 --- a/vm/in/arch_i.py +++ b/vm/in/arch_i.py @@ -31,38 +31,7 @@ def getflag(s): return "__FLAG_ERROR__" -def doprnt(i, p1, p2, cond): - doprnt_2(i, p1, p2) - - if cond: - doprnt_2(i + '$cxz', p1, p2) - doprnt_2(i + '$cxnz', p1, p2) - - doprnt_2(i + '$c', p1, p2) - doprnt_2(i + '$o', p1, p2) - doprnt_2(i + '$z', p1, p2) - doprnt_2(i + '$s', p1, p2) - doprnt_2(i + '$p', p1, p2) - doprnt_2(i + '$e', p1, p2) - doprnt_2(i + '$eq', p1, p2) - - doprnt_2(i + '$a', p1, p2) - doprnt_2(i + '$ae', p1, p2) - doprnt_2(i + '$b', p1, p2) - doprnt_2(i + '$be', p1, p2) - doprnt_2(i + '$l', p1, p2) - doprnt_2(i + '$le', p1, p2) - doprnt_2(i + '$g', p1, p2) - doprnt_2(i + '$ge', p1, p2) - - doprnt_2(i + '$nc', p1, p2) - doprnt_2(i + '$no', p1, p2) - doprnt_2(i + '$nz', p1, p2) - doprnt_2(i + '$ns', p1, p2) - doprnt_2(i + '$np', p1, p2) - doprnt_2(i + '$ne', p1, p2) - -def doprnt_2(i, p1, p2): +def doprnt(i, p1, p2): for c1 in p1: for c2 in p2: fp.write("{} {} {}".format(i, c1, c2).strip()) @@ -83,17 +52,16 @@ for _, line in enumerate(fi): if tok[0][0] == '!': assert(len(tok[0]) > 1) tok[0] = tok[0][1:] - cond = True i = tok[0].strip() if len(tok) == 1: - doprnt(i, ' ', ' ', cond) + doprnt(i, ' ', ' ') continue if len(tok) == 2: p = tok[1].strip() - doprnt(i, p, ' ', cond) + doprnt(i, p, ' ') continue assert(len(tok) == 3) @@ -101,7 +69,7 @@ for _, line in enumerate(fi): p1 = tok[1].strip() p2 = tok[2].strip() - doprnt(i, p1, p2, cond) + doprnt(i, p1, p2) fp.seek(0) @@ -135,7 +103,7 @@ for _, line in enumerate(fp): .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" + hd.write("extern bool i_{}(ctx_t *, acc_t *, acc_t *, ulong *);\n" .format(tok[0])) hd.write("#endif\n\n") diff --git a/vm/in/cond.h b/vm/in/cond.h index 8ee4621..431f105 100644 --- a/vm/in/cond.h +++ b/vm/in/cond.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. +/* #define _IMPL_IF_COND(name, suf, cond) \ IMPL_START_0(name##$##suf) \ { \ @@ -44,4 +45,6 @@ IMPL_END \ \ _IMPL_IF_COND(name, g, !(flg&ZF) && (!!(flg&SF) == !!(flg&OF))); \ _IMPL_IF_COND(name, ge, !!(flg&SF) == !!(flg&OF)); \ +*/ +#define IMPL_COND(name) diff --git a/vm/in/instrs.h b/vm/in/instrs.h index 27de10e..8b36803 100644 --- a/vm/in/instrs.h +++ b/vm/in/instrs.h @@ -7,62 +7,38 @@ #include #include -#define DECV(p, v) \ - ulong v = (p->type == A_REG ? R(p->val) : p->val); \ - if (p->mem) { \ - v = readmem(ctx, v + p->off + R(p->offreg), p1->mlen); \ - } - #define IMPL_START_0(name) \ -void i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2) \ +bool i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, ulong *ret) \ { #define IMPL_START_1(name) \ -void i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2) \ +bool i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, ulong *ret) \ { \ - DECV(p1, v1); + ulong v1 = p1->val; #define IMPL_START_2(name) \ -void i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2) \ +bool i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, ulong *ret) \ { \ - DECV(p1, v1); \ - DECV(p2, v2); - -#define IMPL_START_3(name) \ -void i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2) \ -{ \ - DECV(p2, v2); + ulong v1 = p1->val; \ + ulong v2 = p2->val; #define IMPL_OUT_ZSF \ SET_ZSF(v1); \ IMPL_OUT #define IMPL_OUT \ - assert(p1->type == A_REG || p1->mem); \ - if (p1->mem) { \ - ulong addr = p1->type == A_REG ? R(p1->val) : p1->val; \ - writemem(ctx, v1, addr + p1->off + R(p1->offreg), p1->mlen); \ - } \ - else R(p1->val) = v1; \ + *ret = v1; \ + return 1; \ } +// XXX #define IMPL_OUT_2 \ - assert(p1->type == A_REG || p1->mem); \ - if (p1->mem) { \ - ulong addr = p1->type == A_REG ? R(p1->val) : p1->val; \ - writemem(ctx, v1, addr + p1->off + R(p1->offreg), p1->mlen); \ - } \ - else R(p1->val) = v1; \ - \ - assert(p2->type == A_REG || p2->mem); \ - if (p2->mem) { \ - ulong addr = p2->type == A_REG ? R(p2->val) : p2->val; \ - writemem(ctx, v2, addr + p2->off + R(p2->offreg), p2->mlen); \ - } \ - else R(p2->val) = v2; \ + *ret = v1; \ + return 1; \ } #define IMPL_END \ + return 0; \ } // diff --git a/vm/in/mov.c b/vm/in/mov.c index 660e4ea..f681dd3 100644 --- a/vm/in/mov.c +++ b/vm/in/mov.c @@ -68,13 +68,7 @@ IMPL_OUT_2; IMPL_START_1(lea) { - ulong v2 = (p2->type == A_REG ? R(p2->val) : p2->val); - - if (p2->mem) { - v2 += p2->off + R(p2->offreg); - } - - v1 = v2; + v1 = p2->addr; } IMPL_OUT; diff --git a/vm/pc/DECD b/vm/pc/DECD new file mode 100644 index 0000000..041856d --- /dev/null +++ b/vm/pc/DECD @@ -0,0 +1,52 @@ +# The OS/K Team licenses this file to you under the MIT license. +# See the LICENSE file in the project root for more information. + +Instruction encoding: + +15 0 15 0 +xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx +││└────────────┘ │└───┘└───┘└───┘ +││ INSTR. │ CND FT1 FT2 +││ │ +LM R + +M No more words +L LOCK prefix +R REP prefix +D Destination register + +Values for COND: +00000 (none) +00001 .C +00010 .O +00011 .Z .E +00100 .S +00101 .P +00110 .A +00111 .AE +01000 .B +01001 .BE +01010 .G +01011 .GE +01100 .L +01101 .LE +01110 .CXZ +01111 (reserved) +Highest (6th) bit of COND indicates negation + +Fx values: +0000 (none) +0001 reg +0010 imm64 + +xxx00 [imm64] +xxx01 [reg+reg] +xxx10 [reg+reg+imm16] code(reg)|code(reg) imm16 +xxx11 [reg+reg*imm16+imm16] code(reg)|code(reg) imm16 imm16 + +Where xxx is: +001 8-bit access +010 16-bit access +011 32-bit access +100 64-bit access + diff --git a/vm/pc/arch.h b/vm/pc/arch.h index 0a47fb7..22aa3aa 100644 --- a/vm/pc/arch.h +++ b/vm/pc/arch.h @@ -35,67 +35,6 @@ typedef struct dev_t dev_t; void log(const char *, ...); void vlog(const char *, va_list); -// 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_MEM8 = 0x7001, - A_MEM16 = 0x7002, - A_MEM32 = 0x7004, - A_MEM64 = 0x7008, - - A_OFF8 = 0x7701, - A_OFF16 = 0x7702, - A_OFF32 = 0x7704, - A_OFF64 = 0x7708, - - A_IMM16 = 0x7772, - A_IMM32 = 0x7774, - A_IMM64 = 0x7778 -}; - -#define A_IS_MEM(x) ((x) >= A_MEM8 && (x) <= A_MEM64) -#define A_IS_OFF(x) ((x) >= A_OFF8 && (x) <= A_OFF64) -#define A_IS_IMM(x) ((x) >= A_IMM16) - -#define A_IS_8(x) ((x) & 0xF == 1) -#define A_IS_16(x) ((x) & 0xF == 2) -#define A_IS_32(x) ((x) & 0xF == 3) -#define A_IS_64(x) ((x) & 0xF == 4) - -struct acc_t -{ - bool mem; - uint mlen; - short off; - uint offreg; - - uint type; - uint ilen; - ulong val; -}; - -enum { NOPREF, PREF_REP=0x8000, PREF_LOCK, NPREFS }; - -#define ISPREF(x) ((x) & 0x8000 && (x) +#include #include extern reg_t arch_r[NREGS]; diff --git a/vm/pc/decd.c b/vm/pc/decd.c index f174df1..8b74a2e 100644 --- a/vm/pc/decd.c +++ b/vm/pc/decd.c @@ -3,149 +3,392 @@ #include -#ifdef _NEED_DISASM -#define _except __except +// +// Imperatively read the "DECD" file before reading this code +// -static inline void _except(ctx_t *ctx, int x, char *fmt, ...) +static void check_param_type(ctx_t *ctx, uint prm, uchar fmt) { - va_list ap; + bool ok; - log("Disassembly error: "); + if (prm == P_REG) + ok = (fmt == A_REG); - va_start(ap, fmt); - vlog(fmt, ap); - va_end(ap); + else if (prm == P_IMM) + ok = (fmt == A_IMM64); + + else /* if (prm == P_MEM */ + ok = ACC_FMT_IS_MEM(fmt); + + if (!ok) + _except(ctx, E_ILL, + "FT1 or FT2 not matching INSTR's expected parameter types"); +} + +void decode(ctx_t *ctx) +{ + char *illmsg; + + instr_t *in; + + acc_t p1 = { 0 }; + acc_t p2 = { 0 }; + + bool rep = 0, cond = 0; + bool lock, nomore; + + ushort w1, w2; + uchar f1 = 0, f2 = 0; + + ulong pc = rip; + + // + // Process the first word of the instruction + // + + w1 = ctx->get(ctx); + + // Extract first word flags + + lock = !!(w1 & PREF_LOCK); + nomore = !!(w1 & PREF_NOMORE); + + w1 &= ~(PREF_LOCK|PREF_NOMORE); + + // Find instruction + + if (w1 >= NINSTRS) + { + illmsg = "No such INSTR"; + goto ill; + } + + in = &ctx->i[w1]; + + if (!nomore) + goto skip_w2; + + // + // Process second word + // + + w2 = ctx->get(ctx); + + // REP and COND + rep = w2 & PREF_REP; + cond = (w2 & BITS_COND) >> COND_SHIFT; + + // F1 and F2 + f1 = (w2 >> F1_SHIFT) & Fx_MASK; + f2 = w2 & Fx_MASK; + +skip_w2: + + // + // Deal with operand 1 + // + + if (in->prm1 == NOPRM) + { + if (f1 || f2) + { + illmsg = "FT1 and/or FT2 filled for 0-param INSTR"; + goto ill; + } + + exec_instr(ctx, in, NULL, NULL, lock, rep, cond, pc); + return; + } + + check_param_type(ctx, in->prm1, f1); + extract_param(ctx, &p1, f1); + + // + // Deal with operand 2 + // + + if (in->prm2 == NOPRM) + { + if (f2) + { + illmsg = "FT2 filled for 1-param INSTR"; + goto ill; + } + + exec_instr(ctx, in, &p1, NULL, lock, rep, cond, pc); + return; + } + + check_param_type(ctx, in->prm2, f2); + extract_param(ctx, &p2, f2); + + exec_instr(ctx, in, &p1, &p2, lock, rep, cond, pc); + return; + +ill: + _except(ctx, E_ILL, illmsg); +} + +// +// Verify that access to a certain register is legal +// +static void checkreg(ctx_t *ctx, uint reg, bool inv_is_ok) +{ + if (reg >= NREGS) + _except(ctx, E_ILL, "Inexistent register: %u", reg); + + if (reg == INV) + { + if (!inv_is_ok) + _except(ctx, E_ILL, "INV dereference"); + else + return; + } + + if (ctx->r[reg].flags & (RES | CTL)) + _except(ctx, E_ACC, "Reserved REG: %u", reg); + + if (ctx->r[reg].flags & SYS) + if (cr0 & UF) + _except(ctx, E_SYS, "User access to SYS REG: %u", reg); +} + +// +// Extract operand according to fmt +// +void extract_param(ctx_t *ctx, acc_t *p, uchar fmt) +{ + uint mlen, mfmt, reg1, reg2, imm1 = 0, imm2 = 0; + ushort temp; + + p->type = fmt; + + if (fmt == A_REG) + { + p->reg = ctx->get(ctx); + checkreg(ctx, p->reg, 0); + + p->val = R(p->reg); + } + + else if (fmt == A_IMM64) + { + p->val = ctx->get(ctx); + p->val |= (ulong)ctx->get(ctx) << 16; + p->val |= (ulong)ctx->get(ctx) << 32; + p->val |= (ulong)ctx->get(ctx) << 48; + } + + assert(ACC_FMT_IS_MEM(fmt)); + + // + // Handle a memory access + // + + mlen = fmt & AM_MLEN_MASK; + mfmt = fmt & AM_MFMT_MASK; + + p->mlen = (mlen == AM_8ACC ? 1 + : (mlen == AM_16ACC ? 2 + : (mlen == AM_32ACC ? 4 + : (mlen == AM_64ACC ? 8 : 0)))); + + if (p->mlen == 0) + _except(ctx, E_ILL, "Invalid MLEN for access: %x", fmt); + + switch (mfmt) + { + case AM_IMM64: + p->addr = ctx->get(ctx); + p->addr |= (ulong)ctx->get(ctx) << 16; + p->addr |= (ulong)ctx->get(ctx) << 32; + p->addr |= (ulong)ctx->get(ctx) << 48; + break; + + case AM_RR: + case AM_RRI: + case AM_RRII: + temp = ctx->get(ctx); + reg1 = temp >> 8; + reg2 = temp & 0xFF; + + checkreg(ctx, reg1, 0); + checkreg(ctx, reg2, 1); + + if (fmt == AM_RRI) + { + imm1 = 1; + imm2 = ctx->get(ctx); + } + + else if (fmt == AM_RRII) + { + imm1 = ctx->get(ctx); + imm2 = ctx->get(ctx); + } + + p->addr = R(reg1) + R(reg2) * imm1 + imm2; + + break; + + default: + _except(ctx, E_ILL, "Invalid MFMT for access: %x", fmt); + } + + p->val = readmem(ctx, p->addr, p->mlen); +} + +static bool eval_cond(ctx_t *ctx, uint cond) +{ + bool neg = cond & (1 << 5); + bool ok; + + cond &= ~(1 << 5); + + switch (cond) + { + case CD_C: ok = flg&CF; break; + case CD_O: ok = flg&OF; break; + case CD_Z: ok = flg&ZF; break; + case CD_S: ok = flg&SF; break; + case CD_P: ok = flg&PF; break; + + case CD_A: ok = !(flg&CF || flg&ZF); break; + case CD_AE: ok = !(flg&CF); break; + + case CD_B: ok = flg&CF; break; + case CD_BE: ok = flg&CF || flg&ZF; break; + + case CD_G: ok = !(flg&ZF) && (!(flg&SF) == !(flg&OF)); break; + case CD_GE: ok = !(flg&SF) == !(flg&OF); break; + + case CD_L: ok = !(flg&SF) != !(flg&OF); break; + case CD_LE: ok = flg&ZF || (!(flg&SF) != !(flg&OF)); break; + + case CD_CXZ: ok = !rcx; break; + + default: + _except(ctx, E_ILL, "Invalid COND value: %x", cond); + } + + return neg ? !ok : !!ok; +} + +char *cond_suffixes[] = +{ + "", + ".c" +}; + +static void dump_acc(ctx_t *ctx, acc_t *p) +{ + uint mfmt; + + if (p->type == A_REG) + log("%s", ctx->r[p->reg].name); + + else if (p->type == A_IMM64) + log("imm64:0x%016lX", p->val); + + else + { + log("%c[", getmempref(p->mlen)); + + mfmt = p->type & AM_MFMT_MASK; + + if (mfmt == AM_IMM64) + log("imm64:"); + + else if (mfmt == AM_RR) + log("rr:"); + + else if (mfmt == AM_RRI) + log("rri:"); + + else if (mfmt == AM_RRII) + log("rrii:"); + + log("0x%016lX]", p->addr); + } +} + +static void dump_instr( + ctx_t *ctx, instr_t *in, + acc_t *p1, acc_t *p2, + bool lock, bool rep, + uint cond, ulong pc) +{ + log("0x%016lX: ", pc); + + if (lock) + log("lock "); + + if (rep) + log("rep "); + + if (cond) + log("cond%u ", cond); + + log("%s ", in->full); + + if (p1) { + dump_acc(ctx, p1); + + if (p2) { + log(", "); + dump_acc(ctx, p2); + } + } log("\n"); - - if (ctx->disf) - fclose(ctx->disf); - - exit(-1); } -#endif - -static void scan_param(ctx_t *ctx, acc_t *p) +// +// Executes an instruction +// +void exec_instr( + ctx_t *ctx, instr_t *in, + acc_t *p1, acc_t *p2, + bool lock, bool rep, + uint cond, ulong pc) { - ushort c; - reg_t *r; - - c = ctx->get(ctx); - - if (A_IS_MEM(c)) { - p->mem = 1; - p->off = 0; - p->mlen = c & 0xF; - c = ctx->get(ctx); - } - - else if (A_IS_OFF(c)) { - p->mem = 1; - p->mlen = c & 0xF; - p->off = (short)ctx->get(ctx); - - p->offreg = ctx->get(ctx); - - if (p->offreg > NREGS) { - _except(ctx, E_ILL, "Inexistent REG (offreg)"); - } - - if (p->offreg != INV) { - r = &ctx->r[p->offreg]; - - if (r->flags & (RES | CTL)) { - _except(ctx, E_ACC, "Reserved REG (offreg): %s", r->name); - } - } - - c = ctx->get(ctx); - } - - if (c >= A_IMM16) { - // Check for double access code - if (p->type != A_REG) - _except(ctx, E_ILL, "Bad access code"); - - p->type = c; - c = ctx->get(ctx); - } - - p->val = c; - - if (p->type == A_IMM32) { - p->ilen = 4; - p->val = p->val | ((ulong)ctx->get(ctx) << 16); - } - - else if (p->type == A_IMM64) { - 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) { - 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: %s", r->name); - } - } -} - -#ifndef _NEED_DISASM -void decode(ctx_t *ctx) -#else -void disasm(ctx_t *ctx) -#endif -{ - instr_t *i; - acc_t p1 = { 0 }, p2 = { 0 }; - - uint rep = 0; - ulong orig_rip = rip; - ushort c = ctx->get(ctx); - - if (ISPREF(c)) { - if (c == PREF_REP) { - rep = 1; - c = ctx->get(ctx); - } - } - - else if (!ISINSTR(c)) { - _except(ctx, E_ILL, "Bad opcode: 0x%04hX", c); - } - - i = &ctx->i[c]; - - // Scan for parameters - if (i->prm1 != NOPRM) { - scan_param(ctx, &p1); - if (i->prm2 != NOPRM) { - scan_param(ctx, &p2); - } - } - -#ifdef _NEED_DISASM - dumpinstr(ctx, orig_rip, rep, c, &p1, &p2); -#else + bool out = 0; + ulong ret = 0; + // Debugging + dump_instr(ctx, in, p1, p2, lock, rep, cond, pc); + + if (rep && !cond) + cond = CD_CXZ; + do_rep: - dumpinstr(ctx, orig_rip, rep, c, &p1, &p2); - i->func(ctx, &p1, &p2); + if (!eval_cond(ctx, cond)) + return; + + out = in->func(ctx, p1, p2, &ret); + + if (out) + { + if (p1->type == A_REG) + R(p1->reg) = ret; + + else if (p1->type == A_IMM64) + _except(ctx, E_ACC, "Trying to output on an IMM64"); + + else + { + assert(ACC_IS_MEM(p1)); + writemem(ctx, ret, p1->addr, p1->mlen); + } + } + + if (rep) + { + if (cond == CD_CXZ) + rcx--; - if (rep && rcx > 0) { - rcx--; goto do_rep; } - -#endif } diff --git a/vm/pc/decd.h b/vm/pc/decd.h new file mode 100644 index 0000000..457af5c --- /dev/null +++ b/vm/pc/decd.h @@ -0,0 +1,116 @@ +// 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 +{ + CD_NONE, + + CD_C, CD_O, CD_Z, CD_S, CD_P, + CD_A, CD_AE, CD_B, CD_BE, + CD_G, CD_GE, CD_L, CD_LE, + CD_CXZ, COND_RES, +}; + +enum +{ + PREF_LOCK = (1 << 15), + PREF_NOMORE = (1 << 14), + + PREF_REP = (1 << 15), + + BITS_COND = (1 << 14) | (1 << 13) | (1 << 12) + | (1 << 11) | (1 << 10), + + COND_SHIFT = 8, + + Fx_MASK = 0x1F, + F1_SHIFT = 5, +}; + +enum +{ + A_NONE = 0b00000, + A_REG = 0b00001, + A_IMM64 = 0b00010, + + AM_START = 0b00100, + + AM_IMM64 = 0b00, + AM_RR = 0b01, + AM_RRI = 0b10, + AM_RRII = 0b11, + + AM_8ACC = 0b00100, + AM_16ACC = 0b01000, + AM_32ACC = 0b01100, + AM_64ACC = 0b10000, + + AM_MLEN_MASK = 0b11100, + AM_MFMT_MASK = 0b00011, +}; + +#define ACC_FMT_IS_MEM(x) ((x) >= AM_START && (x) <= (AM_64ACC|AM_RRII)) + +#define ACC_IS_MEM(x) (ACC_FMT_IS_MEM((x)->type)) + +struct acc_t +{ + uint type; + ulong val; + + // A_REG + ulong reg; + + // AM_... + ulong addr; + uint mlen; + +}; + +enum { NOPRM, P_REG, P_IMM, P_MEM=4 }; + +struct instr_t +{ + char *name; + char *full; + + uint prm1; + uint prm2; + + bool (*func)(ctx_t *, acc_t *, acc_t *, ulong *); +}; + +void exec_instr(ctx_t *ctx, + instr_t *in, + acc_t *p1, + acc_t *p2, + bool lock, + bool rep, + uint cond, + ulong pc); + +void extract_param(ctx_t *ctx, + acc_t *p, + uchar fmt); + + + + + + + + + + + + + + + + + + + + + + diff --git a/vm/pc/dump.c b/vm/pc/dump.c deleted file mode 100644 index 487da71..0000000 --- a/vm/pc/dump.c +++ /dev/null @@ -1,85 +0,0 @@ -// 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 - -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, 128 + 64); -} - -void d_log(ctx_t *ctx, char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - - if (ctx->disf) { - vfprintf(ctx->disf, fmt, ap); - fflush(ctx->disf); - } - else - vlog(fmt, ap); - - va_end(ap); -} - -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%s", _rip, - (rep ? "rep " : ""), - i->name); - - if (i->prm1 != NOPRM) - p = p1; -lp: - if (p != 0) { - 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, "%c0x%lX", getmempref(p->ilen), p->val); - - if (p->mem) { - if (p->offreg) - d_log(ctx, "+%s", ctx->r[p->offreg].name); - if (p->off) - d_log(ctx, "+%hd", p->off); - d_log(ctx, "]"); - } - - if (p == p1 && i->prm2 != NOPRM) { - p = p2; - d_log(ctx, ","); - goto lp; - } - } - - d_log(ctx, "\n"); -} diff --git a/vm/pc/except.c b/vm/pc/except.c index 556b4f6..9ebb94b 100644 --- a/vm/pc/except.c +++ b/vm/pc/except.c @@ -28,8 +28,6 @@ void _except(ctx_t *ctx, int code, char *fmt, ...) dumpregs(ctx); log("\n"); - dumpfwstack(ctx); - if (ctx->mp) free(ctx->mp); diff --git a/vm/pc/main.c b/vm/pc/main.c index 6b143a5..c77e191 100644 --- a/vm/pc/main.c +++ b/vm/pc/main.c @@ -112,63 +112,37 @@ int main(int argc, char **argv) fwsize = fread(fwprog, 1, FWPROGSIZE, fwfile); - //log("Loaded %lu bytes - if (fwsize < 2) { log("Program file too small or empty\n"); exit(-3); } - if (!(argc > 2 && !strcmp(argv[2], "-d"))) { - main_ctx.mp = malloc(MEMSIZE + 16); - main_ctx.mz = MEMSIZE; + main_ctx.mp = malloc(MEMSIZE + 16); + main_ctx.mz = MEMSIZE; - main_ctx.get = bget; - main_ctx.disf = NULL; + main_ctx.get = bget; + main_ctx.disf = NULL; - main_ctx.r[RIP].val = MEMOFF; + main_ctx.r[RIP].val = MEMOFF; - if (main_ctx.mp == 0) { - log("Couldn't allocate RAM\n"); - exit(-1); - } - - memcpy(&main_ctx.mp[addr2real(main_ctx.r[RIP].val)], fwprog, fwsize); - - main_ctx.dh = 0; - if (devinitall(&main_ctx) < 0) { - log("Couldn't initialize devices\n"); - exit(-10); - } - - while (1) { - decode(&main_ctx); - - if (main_ctx.step) - getchar(); - } + if (main_ctx.mp == 0) { + log("Couldn't allocate RAM\n"); + exit(-1); } - // Disassembly - else { - main_ctx.disf = fopen("fwprog.dis", "w"); + memcpy(&main_ctx.mp[addr2real(main_ctx.r[RIP].val)], fwprog, fwsize); - if (main_ctx.disf == NULL) { - log("Couldn't open fwprog.dis\n"); - exit(-2); - } - - main_ctx.mp = NULL; - main_ctx.mz = 0; - - main_ctx.get = dget; - - while (1) { - disasm(&main_ctx); - } + main_ctx.dh = 0; + if (devinitall(&main_ctx) < 0) { + log("Couldn't initialize devices\n"); + exit(-10); } + while (1) { + decode(&main_ctx); - return 0; + if (main_ctx.step) + getchar(); + } }