mirror of
https://gitlab.os-k.eu/os-k-team/kvisc.git
synced 2023-08-25 14:05:46 +02:00
memory, stack, dumping
This commit is contained in:
parent
72f27a22c3
commit
b324b120fc
4
Makefile
4
Makefile
@ -3,10 +3,10 @@
|
|||||||
|
|
||||||
all: k.exe
|
all: k.exe
|
||||||
|
|
||||||
src = instr/instrs.c karch/decd.c karch/main.c karch/regs.c
|
src = instr/instrs.c karch/decd.c karch/main.c karch/regs.c karch/dump.c
|
||||||
obj = $(patsubst %.c,%.o,$(src))
|
obj = $(patsubst %.c,%.o,$(src))
|
||||||
|
|
||||||
%.o: %.c instrs/i_arch.h */*.h */*.c
|
%.o: %.c instrs/i_arch.h */*.h $(src)
|
||||||
@gcc -O2 -Wall -I./karch -c $< -o $@
|
@gcc -O2 -Wall -I./karch -c $< -o $@
|
||||||
|
|
||||||
instrs/i_arch.h: instr/INSTRS instr/instrs.py
|
instrs/i_arch.h: instr/INSTRS instr/instrs.py
|
||||||
|
10
instr/INSTRS
10
instr/INSTRS
@ -38,5 +38,13 @@ mov r i
|
|||||||
mov r m
|
mov r m
|
||||||
mov m r
|
mov m r
|
||||||
mov m i
|
mov m i
|
||||||
mov m m
|
|
||||||
|
xchg r r
|
||||||
|
xchg r i
|
||||||
|
xchg r m
|
||||||
|
xchg m r
|
||||||
|
xchg m i
|
||||||
|
|
||||||
|
cli
|
||||||
|
sti
|
||||||
|
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
#include "instrs.h"
|
#include "instrs.h"
|
||||||
|
#include "arch_i.h"
|
||||||
|
|
||||||
|
#define _NEED_ARCH_I
|
||||||
|
#include "arch_i.h"
|
||||||
|
|
||||||
IMPL_START_0(nop)
|
IMPL_START_0(nop)
|
||||||
{
|
{
|
||||||
@ -79,6 +83,17 @@ IMPL_START_2(xchg)
|
|||||||
}
|
}
|
||||||
IMPL_OUT;
|
IMPL_OUT;
|
||||||
|
|
||||||
#define _NEED_ARCH_I
|
IMPL_START_0(cli)
|
||||||
#include "arch_i.h"
|
{
|
||||||
|
CHK_SUPERV();
|
||||||
|
ctx->r[FLG].val &= ~(1L<<63);
|
||||||
|
}
|
||||||
|
IMPL_END;
|
||||||
|
|
||||||
|
IMPL_START_0(sti)
|
||||||
|
{
|
||||||
|
CHK_SUPERV();
|
||||||
|
ctx->r[FLG].val |= 1L<<63;
|
||||||
|
}
|
||||||
|
IMPL_END;
|
||||||
|
|
||||||
|
@ -11,19 +11,38 @@ void i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2) \
|
|||||||
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); \
|
ulong v1 = (p1->type == A_REG ? ctx->r[p1->val].val : p1->val); \
|
||||||
|
if (p1->mem) v1 = readmem64(ctx, v1 + p1->off); \
|
||||||
|
|
||||||
#define IMPL_START_2(name) \
|
#define IMPL_START_2(name) \
|
||||||
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); \
|
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); \
|
ulong v2 = (p2->type == A_REG ? ctx->r[p2->val].val : p2->val); \
|
||||||
|
if (p1->mem) v1 = readmem64(ctx, v1 + p1->off); \
|
||||||
|
if (p2->mem) v2 = readmem64(ctx, v2 + p2->off); \
|
||||||
|
|
||||||
|
#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 = readmem64(ctx, v2 + p2->off); \
|
||||||
|
|
||||||
#define IMPL_OUT \
|
#define IMPL_OUT \
|
||||||
assert(p1->type == A_REG); \
|
assert(p1->type == A_REG || p1->mem); \
|
||||||
ctx->r[p1->val].val = v1; \
|
if (p1->mem) { \
|
||||||
|
ulong addr = p1->type == A_REG ? ctx->r[p1->val].val : p1->val; \
|
||||||
|
writemem64(ctx, v1, addr); \
|
||||||
|
} \
|
||||||
|
else ctx->r[p1->val].val = v1; \
|
||||||
} \
|
} \
|
||||||
|
|
||||||
#define IMPL_END \
|
#define IMPL_END \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define CHK_SUPERV() \
|
||||||
|
do { \
|
||||||
|
if ((ctx->r[FLG].val & (1L << 62)) == 1) { \
|
||||||
|
_except(ctx, E_SYS, "Supervisor-only INSTR"); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
@ -28,39 +28,43 @@ for _, line in enumerate(fi):
|
|||||||
if line[0] == '#' or line[0] == ' ' or line[0] == '\n':
|
if line[0] == '#' or line[0] == ' ' or line[0] == '\n':
|
||||||
continue
|
continue
|
||||||
|
|
||||||
tok = line.split(' ')
|
tok = line.strip().split(' ')
|
||||||
|
|
||||||
if len(tok) == 1:
|
if len(tok) == 1:
|
||||||
name = tok[0].strip()
|
name = tok[0]
|
||||||
p1 = "NOPRM"
|
p1 = "NOPRM"
|
||||||
p2 = "NOPRM"
|
p2 = "NOPRM"
|
||||||
|
|
||||||
elif len(tok) == 2:
|
elif len(tok) == 2:
|
||||||
name = "{}_{}".format(tok[0], tok[1].strip())
|
name = "{}_{}".format(tok[0], tok[1].strip())
|
||||||
p1 = getflag(tok[1].strip())
|
p1 = getflag(tok[1])
|
||||||
p2 = "NOPRM"
|
p2 = "NOPRM"
|
||||||
|
|
||||||
elif len(tok) == 3:
|
elif len(tok) == 3:
|
||||||
name = "{}_{}_{}".format(tok[0], tok[1], tok[2].strip())
|
name = "{}_{}_{}".format(tok[0], tok[1], tok[2].strip())
|
||||||
p1 = getflag(tok[1])
|
p1 = getflag(tok[1])
|
||||||
p2 = getflag(tok[2].strip())
|
p2 = getflag(tok[2])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
name = "__ERROR__"
|
name = "__ERROR__"
|
||||||
p1 = "__ERROR__"
|
p1 = "__ERROR__"
|
||||||
p2 = "__ERROR__"
|
p2 = "__ERROR__"
|
||||||
|
|
||||||
hd.write("#define I_{} {}\n".format(name.upper(), count))
|
|
||||||
hd.write("#ifdef _NEED_ARCH_I\n")
|
hd.write("#ifdef _NEED_ARCH_I\n")
|
||||||
hd.write('{{ "{}", "{}", {}, {}, i_{} }},\n'\
|
hd.write('{{ "{}", "{}", {}, {}, i_{} }},\n'\
|
||||||
.format(tok[0].strip(), name, p1, p2, tok[0]))
|
.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"
|
||||||
|
.format(tok[0]))
|
||||||
hd.write("#endif\n\n")
|
hd.write("#endif\n\n")
|
||||||
|
|
||||||
count = count + 1
|
count = count + 1
|
||||||
hd.write("#define NINSTRS {}\n\n".format(count))
|
|
||||||
|
|
||||||
hd.write("#ifdef _NEED_ARCH_I\n")
|
hd.write("#ifdef _NEED_ARCH_I\n")
|
||||||
hd.write("};\n")
|
hd.write("};\n")
|
||||||
|
hd.write("#else\n")
|
||||||
|
hd.write("#define NINSTRS {}\n\n".format(count))
|
||||||
hd.write("#endif\n")
|
hd.write("#endif\n")
|
||||||
|
|
||||||
hd.close()
|
hd.close()
|
||||||
|
44
karch/arch.h
44
karch/arch.h
@ -32,7 +32,7 @@ enum
|
|||||||
R08, R09, R10, R11, R12, R13, R14, R15,
|
R08, R09, R10, R11, R12, R13, R14, R15,
|
||||||
K00, K01, K02, K03, K04, K05, K06, K07,
|
K00, K01, K02, K03, K04, K05, K06, K07,
|
||||||
CR0, CR1, CR2, CR3, CR4, CR5, CR6, CR7,
|
CR0, CR1, CR2, CR3, CR4, CR5, CR6, CR7,
|
||||||
RIP, FLG, RET,
|
RIP, FLG,
|
||||||
|
|
||||||
NREGS
|
NREGS
|
||||||
};
|
};
|
||||||
@ -54,13 +54,17 @@ struct reg_t
|
|||||||
ulong flags;
|
ulong flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum { A_MEM=0x7000 };
|
// 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_MEM=0x7000, A_OFF, A_IMM16, A_IMM32, A_IMM64 };
|
||||||
struct acc_t
|
struct acc_t
|
||||||
{
|
{
|
||||||
bool mem;
|
bool mem; // A_MEM?
|
||||||
enum { A_REG=0, A_IMM16=0x7001, A_IMM32, A_IMM64 } type;
|
uint type;
|
||||||
|
|
||||||
ulong val;
|
ulong val;
|
||||||
|
short off;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum { NOPREF, PREF_REP=0x8000, PREF_LOCK, NPREFS };
|
enum { NOPREF, PREF_REP=0x8000, PREF_LOCK, NPREFS };
|
||||||
@ -105,7 +109,10 @@ enum
|
|||||||
NEXCPTS
|
NEXCPTS
|
||||||
};
|
};
|
||||||
|
|
||||||
void dumpregs(ctx_t *ctx);
|
void dumpregs(ctx_t *);
|
||||||
|
void dumpinstr(ctx_t *, ulong, ushort, acc_t *, acc_t *);
|
||||||
|
void dumpmem(ctx_t *, ulong, ulong);
|
||||||
|
void dumpfwstack(ctx_t *);
|
||||||
|
|
||||||
static inline void _except(ctx_t *ctx, int code, char *fmt, ...)
|
static inline void _except(ctx_t *ctx, int code, char *fmt, ...)
|
||||||
{
|
{
|
||||||
@ -120,6 +127,8 @@ static inline void _except(ctx_t *ctx, int code, char *fmt, ...)
|
|||||||
log("\n");
|
log("\n");
|
||||||
|
|
||||||
dumpregs(ctx);
|
dumpregs(ctx);
|
||||||
|
dumpfwstack(ctx);
|
||||||
|
|
||||||
free(ctx->mp);
|
free(ctx->mp);
|
||||||
exit(code+1);
|
exit(code+1);
|
||||||
}
|
}
|
||||||
@ -132,16 +141,19 @@ void decode(ctx_t *ctx);
|
|||||||
#define addr2real(p) ((p) - MEMOFF)
|
#define addr2real(p) ((p) - MEMOFF)
|
||||||
#define real2addr(p) ((p) + MEMOFF)
|
#define real2addr(p) ((p) + MEMOFF)
|
||||||
|
|
||||||
|
// Address of boot firmware stack
|
||||||
|
#define FWSTACK (MEMOFF * 2) // 2MB
|
||||||
|
|
||||||
static inline ulong readmem64(ctx_t *ctx, ulong addr)
|
static inline ulong readmem64(ctx_t *ctx, ulong addr)
|
||||||
{
|
{
|
||||||
ulong real = addr2real(addr);
|
ulong real = addr2real(addr);
|
||||||
|
|
||||||
if (addr % alignof(ulong) > 0) {
|
if (addr % alignof(ulong) > 0) {
|
||||||
_except(ctx, E_ALI, "Non-aligned memory access");
|
_except(ctx, E_ALI, "Non-aligned memory access: 0x%012lX(0x%012lX)", addr, real);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr < MEMOFF || real >= MEMSIZE) {
|
if (addr < MEMOFF || real >= MEMSIZE) {
|
||||||
_except(ctx, E_ACC, "Accessing inexistent memory");
|
_except(ctx, E_ACC, "Invalid MEM access: 0x%012lX(0x%012lX)", addr, real);
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong val = (ulong)ctx->mp[real++];
|
ulong val = (ulong)ctx->mp[real++];
|
||||||
@ -152,5 +164,23 @@ static inline ulong readmem64(ctx_t *ctx, ulong addr)
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void writemem64(ctx_t *ctx, ulong val, ulong addr)
|
||||||
|
{
|
||||||
|
ulong real = addr2real(addr);
|
||||||
|
|
||||||
|
if (addr % alignof(ulong) > 0) {
|
||||||
|
_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->mp[real++] = val >> 48;
|
||||||
|
ctx->mp[real++] = (val >> 32) & 0xFFFF;
|
||||||
|
ctx->mp[real++] = (val >> 16) & 0xFFFF;
|
||||||
|
ctx->mp[real++] = val & 0xFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
#include "../instr/arch_i.h"
|
#include "../instr/arch_i.h"
|
||||||
|
|
||||||
|
50
karch/decd.c
50
karch/decd.c
@ -14,6 +14,13 @@ void scan_param(ctx_t *ctx, acc_t *p)
|
|||||||
|
|
||||||
if (c == A_MEM) {
|
if (c == A_MEM) {
|
||||||
p->mem = 1;
|
p->mem = 1;
|
||||||
|
p->off = 0;
|
||||||
|
c = ctx->get(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (c == A_OFF) {
|
||||||
|
p->mem = 1;
|
||||||
|
p->off = (short)ctx->get(ctx);
|
||||||
c = ctx->get(ctx);
|
c = ctx->get(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,49 +55,6 @@ void scan_param(ctx_t *ctx, acc_t *p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dumpregs(ctx_t *ctx)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
reg_t *r;
|
|
||||||
|
|
||||||
for (i = 0; i < NREGS; i++) {
|
|
||||||
if (i > 0 && i % 4 == 0)
|
|
||||||
log("\n");
|
|
||||||
|
|
||||||
r = &ctx->r[i];
|
|
||||||
log("%s=0x%016lX ", r->name, r->val);
|
|
||||||
}
|
|
||||||
log("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void dumpinstr(ctx_t *ctx, ulong rip, ushort c, acc_t *p1, acc_t *p2)
|
|
||||||
{
|
|
||||||
acc_t *p = 0;
|
|
||||||
instr_t *i = &ctx->i[c];
|
|
||||||
log("0x%016lX: %s", rip, i->name);
|
|
||||||
|
|
||||||
if (i->prm1 != NOPRM)
|
|
||||||
p = p1;
|
|
||||||
lp:
|
|
||||||
if (p != 0) {
|
|
||||||
if (p->mem) log("[");
|
|
||||||
|
|
||||||
if (p->type == A_REG)
|
|
||||||
log(" %s", ctx->r[p->val].name);
|
|
||||||
else
|
|
||||||
log(" 0x%lX", p->val);
|
|
||||||
|
|
||||||
if (p->mem) log("]");
|
|
||||||
|
|
||||||
if (p == p1 && i->prm2 != NOPRM) {
|
|
||||||
p = p2;
|
|
||||||
goto lp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void decode(ctx_t *ctx)
|
void decode(ctx_t *ctx)
|
||||||
{
|
{
|
||||||
instr_t *i;
|
instr_t *i;
|
||||||
|
81
karch/dump.c
Normal file
81
karch/dump.c
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
// 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 "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 < K00; i++) {
|
||||||
|
if (i % 4 == 0)
|
||||||
|
log("\n");
|
||||||
|
|
||||||
|
r = &ctx->r[i];
|
||||||
|
log("%s=0x%016lX ", r->name, r->val);
|
||||||
|
}
|
||||||
|
log("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dumpinstr(ctx_t *ctx, ulong rip, ushort c, acc_t *p1, acc_t *p2)
|
||||||
|
{
|
||||||
|
acc_t *p = 0;
|
||||||
|
instr_t *i = &ctx->i[c];
|
||||||
|
log("0x%016lX: %s", rip, i->name);
|
||||||
|
|
||||||
|
if (i->prm1 != NOPRM)
|
||||||
|
p = p1;
|
||||||
|
lp:
|
||||||
|
if (p != 0) {
|
||||||
|
if (p->mem) log(" [");
|
||||||
|
else log(" ");
|
||||||
|
|
||||||
|
if (p->type == A_REG)
|
||||||
|
log("%s", ctx->r[p->val].name);
|
||||||
|
else
|
||||||
|
log("0x%lX", p->val);
|
||||||
|
|
||||||
|
if (p->mem) {
|
||||||
|
if (p->off)
|
||||||
|
log("+%hd", p->off);
|
||||||
|
log("]");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p == p1 && i->prm2 != NOPRM) {
|
||||||
|
p = p2;
|
||||||
|
log(",");
|
||||||
|
goto lp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log("\n");
|
||||||
|
}
|
@ -3,8 +3,15 @@
|
|||||||
|
|
||||||
#include "arch.h"
|
#include "arch.h"
|
||||||
|
|
||||||
|
// Boot firware, loaded at MEMOFF (1MB)
|
||||||
ushort fwprog[] = {
|
ushort fwprog[] = {
|
||||||
I_MOV_R_I, RBP, A_IMM16, MEMOFF+sizeof(fwprog)+0xFF,
|
I_MOV_R_I, RBP, A_IMM32, FWSTACK>>16, FWSTACK&0xFF,
|
||||||
|
I_MOV_R_I, RSP, A_IMM32, FWSTACK>>16, FWSTACK&0xFF,
|
||||||
|
|
||||||
|
I_MOV_M_I, A_MEM, RBP, A_IMM16, 0xAC,
|
||||||
|
I_SUB_R_I, RBP, A_IMM16, 8,
|
||||||
|
I_ADD_M_R, A_OFF, 8, RBP, RSP,
|
||||||
|
I_MOV_R_M, RAX, A_MEM, RBP,
|
||||||
};
|
};
|
||||||
|
|
||||||
ushort bget(ctx_t *ctx)
|
ushort bget(ctx_t *ctx)
|
||||||
|
@ -39,6 +39,5 @@ reg_t arch_r[NREGS] =
|
|||||||
{ "cr7", "Control register 7", 0, CTL },
|
{ "cr7", "Control register 7", 0, CTL },
|
||||||
{ "rip", "Instruction pointer", 0, RES },
|
{ "rip", "Instruction pointer", 0, RES },
|
||||||
{ "flg", "Flags register", 0, RES },
|
{ "flg", "Flags register", 0, RES },
|
||||||
{ "ret", "Return address", 0, RES },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user