new decoding
This commit is contained in:
parent
1a12699fb6
commit
0a9d1bdc93
|
@ -10,15 +10,15 @@ dv_src = $(shell ls dv/*.c)
|
||||||
in_src = $(shell ls in/*.c)
|
in_src = $(shell ls in/*.c)
|
||||||
pc_src = $(shell ls pc/*.c)
|
pc_src = $(shell ls pc/*.c)
|
||||||
|
|
||||||
obj = pc/disd.o
|
#obj = pc/disd.o
|
||||||
obj += $(patsubst %.c,%.o,$(dv_src))
|
obj = $(patsubst %.c,%.o,$(dv_src))
|
||||||
obj += $(patsubst %.c,%.o,$(in_src))
|
obj += $(patsubst %.c,%.o,$(in_src))
|
||||||
obj += $(patsubst %.c,%.o,$(pc_src))
|
obj += $(patsubst %.c,%.o,$(pc_src))
|
||||||
|
|
||||||
FLAGS=-O2 -g -Wall -fno-builtin-log -I.
|
FLAGS=-O2 -g -Wall -fno-builtin-log -I.
|
||||||
|
|
||||||
pc/disd.o: in/i_arch.h */*.h pc/decd.c
|
#pc/disd.o: in/i_arch.h */*.h pc/decd.c
|
||||||
@cc $(FLAGS) -D_NEED_DISASM -c pc/decd.c -o $@
|
# @cc $(FLAGS) -D_NEED_DISASM -c pc/decd.c -o $@
|
||||||
|
|
||||||
%.o: %.c in/i_arch.h */*.h $(src)
|
%.o: %.c in/i_arch.h */*.h $(src)
|
||||||
@cc $(FLAGS) -c $< -o $@
|
@cc $(FLAGS) -c $< -o $@
|
||||||
|
|
|
@ -46,7 +46,7 @@ IMPL_START_2(devctl)
|
||||||
dev_t *dev = devctl_common(ctx, v1, v2);
|
dev_t *dev = devctl_common(ctx, v1, v2);
|
||||||
|
|
||||||
if (dev == NULL)
|
if (dev == NULL)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
switch (v2) {
|
switch (v2) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -90,7 +90,7 @@ IMPL_START_2(iocall)
|
||||||
dev_t *dev = devctl_common(ctx, v1, v2);
|
dev_t *dev = devctl_common(ctx, v1, v2);
|
||||||
|
|
||||||
if (dev == NULL)
|
if (dev == NULL)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
if (v2 >= DEVSLOTS)
|
if (v2 >= DEVSLOTS)
|
||||||
rax = -6;
|
rax = -6;
|
||||||
|
|
|
@ -31,38 +31,7 @@ def getflag(s):
|
||||||
|
|
||||||
return "__FLAG_ERROR__"
|
return "__FLAG_ERROR__"
|
||||||
|
|
||||||
def doprnt(i, p1, p2, cond):
|
def doprnt(i, p1, p2):
|
||||||
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):
|
|
||||||
for c1 in p1:
|
for c1 in p1:
|
||||||
for c2 in p2:
|
for c2 in p2:
|
||||||
fp.write("{} {} {}".format(i, c1, c2).strip())
|
fp.write("{} {} {}".format(i, c1, c2).strip())
|
||||||
|
@ -83,17 +52,16 @@ for _, line in enumerate(fi):
|
||||||
if tok[0][0] == '!':
|
if tok[0][0] == '!':
|
||||||
assert(len(tok[0]) > 1)
|
assert(len(tok[0]) > 1)
|
||||||
tok[0] = tok[0][1:]
|
tok[0] = tok[0][1:]
|
||||||
cond = True
|
|
||||||
|
|
||||||
i = tok[0].strip()
|
i = tok[0].strip()
|
||||||
|
|
||||||
if len(tok) == 1:
|
if len(tok) == 1:
|
||||||
doprnt(i, ' ', ' ', cond)
|
doprnt(i, ' ', ' ')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if len(tok) == 2:
|
if len(tok) == 2:
|
||||||
p = tok[1].strip()
|
p = tok[1].strip()
|
||||||
doprnt(i, p, ' ', cond)
|
doprnt(i, p, ' ')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
assert(len(tok) == 3)
|
assert(len(tok) == 3)
|
||||||
|
@ -101,7 +69,7 @@ for _, line in enumerate(fi):
|
||||||
p1 = tok[1].strip()
|
p1 = tok[1].strip()
|
||||||
p2 = tok[2].strip()
|
p2 = tok[2].strip()
|
||||||
|
|
||||||
doprnt(i, p1, p2, cond)
|
doprnt(i, p1, p2)
|
||||||
|
|
||||||
fp.seek(0)
|
fp.seek(0)
|
||||||
|
|
||||||
|
@ -135,7 +103,7 @@ for _, line in enumerate(fp):
|
||||||
.format(tok[0], name, p1, p2, tok[0]))
|
.format(tok[0], name, p1, p2, tok[0]))
|
||||||
hd.write("#else\n")
|
hd.write("#else\n")
|
||||||
hd.write("#define I_{} {}\n".format(name.upper(), count))
|
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]))
|
.format(tok[0]))
|
||||||
hd.write("#endif\n\n")
|
hd.write("#endif\n\n")
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// The OS/K Team licenses this file to you under the MIT license.
|
// The OS/K Team licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
/*
|
||||||
#define _IMPL_IF_COND(name, suf, cond) \
|
#define _IMPL_IF_COND(name, suf, cond) \
|
||||||
IMPL_START_0(name##$##suf) \
|
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, g, !(flg&ZF) && (!!(flg&SF) == !!(flg&OF))); \
|
||||||
_IMPL_IF_COND(name, ge, !!(flg&SF) == !!(flg&OF)); \
|
_IMPL_IF_COND(name, ge, !!(flg&SF) == !!(flg&OF)); \
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define IMPL_COND(name)
|
||||||
|
|
|
@ -7,62 +7,38 @@
|
||||||
#include <in/flags.h>
|
#include <in/flags.h>
|
||||||
#include <in/arch_i.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) \
|
#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) \
|
#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) \
|
#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); \
|
ulong v1 = p1->val; \
|
||||||
DECV(p2, v2);
|
ulong v2 = p2->val;
|
||||||
|
|
||||||
#define IMPL_START_3(name) \
|
|
||||||
void i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2) \
|
|
||||||
{ \
|
|
||||||
DECV(p2, v2);
|
|
||||||
|
|
||||||
#define IMPL_OUT_ZSF \
|
#define IMPL_OUT_ZSF \
|
||||||
SET_ZSF(v1); \
|
SET_ZSF(v1); \
|
||||||
IMPL_OUT
|
IMPL_OUT
|
||||||
|
|
||||||
#define IMPL_OUT \
|
#define IMPL_OUT \
|
||||||
assert(p1->type == A_REG || p1->mem); \
|
*ret = v1; \
|
||||||
if (p1->mem) { \
|
return 1; \
|
||||||
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; \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX
|
||||||
#define IMPL_OUT_2 \
|
#define IMPL_OUT_2 \
|
||||||
assert(p1->type == A_REG || p1->mem); \
|
*ret = v1; \
|
||||||
if (p1->mem) { \
|
return 1; \
|
||||||
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; \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IMPL_END \
|
#define IMPL_END \
|
||||||
|
return 0; \
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -68,13 +68,7 @@ IMPL_OUT_2;
|
||||||
|
|
||||||
IMPL_START_1(lea)
|
IMPL_START_1(lea)
|
||||||
{
|
{
|
||||||
ulong v2 = (p2->type == A_REG ? R(p2->val) : p2->val);
|
v1 = p2->addr;
|
||||||
|
|
||||||
if (p2->mem) {
|
|
||||||
v2 += p2->off + R(p2->offreg);
|
|
||||||
}
|
|
||||||
|
|
||||||
v1 = v2;
|
|
||||||
}
|
}
|
||||||
IMPL_OUT;
|
IMPL_OUT;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
66
vm/pc/arch.h
66
vm/pc/arch.h
|
@ -35,67 +35,6 @@ typedef struct dev_t dev_t;
|
||||||
void log(const char *, ...);
|
void log(const char *, ...);
|
||||||
void vlog(const char *, va_list);
|
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
|
struct ctx_t
|
||||||
{
|
{
|
||||||
reg_t *r;
|
reg_t *r;
|
||||||
|
@ -142,11 +81,9 @@ enum
|
||||||
void dumpregs(ctx_t *);
|
void dumpregs(ctx_t *);
|
||||||
void dumpinstr(ctx_t *, ulong, uint, ushort, acc_t *, acc_t *);
|
void dumpinstr(ctx_t *, ulong, uint, ushort, acc_t *, acc_t *);
|
||||||
void dumpmem(ctx_t *, ulong, ulong);
|
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);
|
void decode(ctx_t *ctx);
|
||||||
|
|
||||||
#define MEMOFF (1 * 1024 * 1024)
|
#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);
|
void writemem(ctx_t *, ulong val, ulong addr, uint len);
|
||||||
|
|
||||||
#include <pc/regs.h>
|
#include <pc/regs.h>
|
||||||
|
#include <pc/decd.h>
|
||||||
#include <in/arch_i.h>
|
#include <in/arch_i.h>
|
||||||
|
|
||||||
extern reg_t arch_r[NREGS];
|
extern reg_t arch_r[NREGS];
|
||||||
|
|
501
vm/pc/decd.c
501
vm/pc/decd.c
|
@ -3,149 +3,392 @@
|
||||||
|
|
||||||
#include <pc/arch.h>
|
#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);
|
else if (prm == P_IMM)
|
||||||
vlog(fmt, ap);
|
ok = (fmt == A_IMM64);
|
||||||
va_end(ap);
|
|
||||||
|
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");
|
log("\n");
|
||||||
|
|
||||||
if (ctx->disf)
|
|
||||||
fclose(ctx->disf);
|
|
||||||
|
|
||||||
exit(-1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
//
|
||||||
|
// Executes an instruction
|
||||||
static void scan_param(ctx_t *ctx, acc_t *p)
|
//
|
||||||
|
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;
|
bool out = 0;
|
||||||
reg_t *r;
|
ulong ret = 0;
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
|
// Debugging
|
||||||
|
dump_instr(ctx, in, p1, p2, lock, rep, cond, pc);
|
||||||
|
|
||||||
|
if (rep && !cond)
|
||||||
|
cond = CD_CXZ;
|
||||||
|
|
||||||
do_rep:
|
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;
|
goto do_rep;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
85
vm/pc/dump.c
85
vm/pc/dump.c
|
@ -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");
|
|
||||||
}
|
|
|
@ -28,8 +28,6 @@ void _except(ctx_t *ctx, int code, char *fmt, ...)
|
||||||
dumpregs(ctx);
|
dumpregs(ctx);
|
||||||
log("\n");
|
log("\n");
|
||||||
|
|
||||||
dumpfwstack(ctx);
|
|
||||||
|
|
||||||
if (ctx->mp)
|
if (ctx->mp)
|
||||||
free(ctx->mp);
|
free(ctx->mp);
|
||||||
|
|
||||||
|
|
62
vm/pc/main.c
62
vm/pc/main.c
|
@ -112,63 +112,37 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
fwsize = fread(fwprog, 1, FWPROGSIZE, fwfile);
|
fwsize = fread(fwprog, 1, FWPROGSIZE, fwfile);
|
||||||
|
|
||||||
//log("Loaded %lu bytes
|
|
||||||
|
|
||||||
if (fwsize < 2) {
|
if (fwsize < 2) {
|
||||||
log("Program file too small or empty\n");
|
log("Program file too small or empty\n");
|
||||||
exit(-3);
|
exit(-3);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(argc > 2 && !strcmp(argv[2], "-d"))) {
|
main_ctx.mp = malloc(MEMSIZE + 16);
|
||||||
main_ctx.mp = malloc(MEMSIZE + 16);
|
main_ctx.mz = MEMSIZE;
|
||||||
main_ctx.mz = MEMSIZE;
|
|
||||||
|
|
||||||
main_ctx.get = bget;
|
main_ctx.get = bget;
|
||||||
main_ctx.disf = NULL;
|
main_ctx.disf = NULL;
|
||||||
|
|
||||||
main_ctx.r[RIP].val = MEMOFF;
|
main_ctx.r[RIP].val = MEMOFF;
|
||||||
|
|
||||||
if (main_ctx.mp == 0) {
|
if (main_ctx.mp == 0) {
|
||||||
log("Couldn't allocate RAM\n");
|
log("Couldn't allocate RAM\n");
|
||||||
exit(-1);
|
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disassembly
|
memcpy(&main_ctx.mp[addr2real(main_ctx.r[RIP].val)], fwprog, fwsize);
|
||||||
else {
|
|
||||||
main_ctx.disf = fopen("fwprog.dis", "w");
|
|
||||||
|
|
||||||
if (main_ctx.disf == NULL) {
|
main_ctx.dh = 0;
|
||||||
log("Couldn't open fwprog.dis\n");
|
if (devinitall(&main_ctx) < 0) {
|
||||||
exit(-2);
|
log("Couldn't initialize devices\n");
|
||||||
}
|
exit(-10);
|
||||||
|
|
||||||
main_ctx.mp = NULL;
|
|
||||||
main_ctx.mz = 0;
|
|
||||||
|
|
||||||
main_ctx.get = dget;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
disasm(&main_ctx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
decode(&main_ctx);
|
||||||
|
|
||||||
return 0;
|
if (main_ctx.step)
|
||||||
|
getchar();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue