new decoding

This commit is contained in:
julianb0 2019-06-07 22:23:38 +02:00
parent 1a12699fb6
commit 0a9d1bdc93
No known key found for this signature in database
GPG Key ID: DDF8325C95299A62
13 changed files with 587 additions and 410 deletions

View File

@ -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 $@

View File

@ -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;

View File

@ -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")

View File

@ -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)

View File

@ -7,62 +7,38 @@
#include <in/flags.h>
#include <in/arch_i.h>
#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; \
}
//

View File

@ -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;

52
vm/pc/DECD Normal file
View File

@ -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

View File

@ -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)<NPREFS)
#define ISINSTR(x) ((x) < NINSTRS)
enum { NOPRM, P_REG, P_IMM, P_MEM=4 };
struct instr_t
{
char *name;
char *full;
uint prm1;
uint prm2;
void (*func)(ctx_t *, acc_t *, acc_t *);
};
struct ctx_t
{
reg_t *r;
@ -142,11 +81,9 @@ enum
void dumpregs(ctx_t *);
void dumpinstr(ctx_t *, ulong, uint, ushort, acc_t *, acc_t *);
void dumpmem(ctx_t *, ulong, ulong);
void dumpfwstack(ctx_t *);
void _except(ctx_t *, int, char *, ...);
void _except(ctx_t *, int, char *, ...) __attribute__((__noreturn__));
void disasm(ctx_t *ctx);
void decode(ctx_t *ctx);
#define MEMOFF (1 * 1024 * 1024)
@ -171,6 +108,7 @@ void writemem64(ctx_t *, ulong val, ulong addr);
void writemem(ctx_t *, ulong val, ulong addr, uint len);
#include <pc/regs.h>
#include <pc/decd.h>
#include <in/arch_i.h>
extern reg_t arch_r[NREGS];

View File

@ -3,149 +3,392 @@
#include <pc/arch.h>
#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
}

116
vm/pc/decd.h Normal file
View File

@ -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);

View File

@ -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 <pc/arch.h>
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");
}

View File

@ -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);

View File

@ -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();
}
}