lots of stuff

This commit is contained in:
julianb0 2019-05-29 16:57:22 +02:00
parent 8e50810bf7
commit 29ef2b35b5
No known key found for this signature in database
GPG Key ID: DDF8325C95299A62
25 changed files with 788 additions and 523 deletions

View File

@ -8,9 +8,13 @@ kpc:
@cd pc && make --no-print-directory @cd pc && make --no-print-directory
kas: kpc as/k-as.py as/regs.lst as/testfile.asm 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 test: kas
@cd as && ./k-as.py testfile.asm 0x100000 testout.out @cd as && ./k-as.py testfile.asm 0x100000 testout.out
@pc/k.exe as/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

View File

@ -13,11 +13,9 @@ if len(sys.argv) != 4:
.format(sys.argv[0])) .format(sys.argv[0]))
sys.exit(1) sys.exit(1)
# TemporaryFile(mode='w+') instrs = open("{}.instr".format(sys.argv[3]), "w+")
instrs = open("testfile.out.1", "w+") b_data = open("{}.data".format(sys.argv[3]), "w+b")
b_text = open("{}.text".format(sys.argv[3]), "w+b")
b_data = open("testfile.out.2", "w+b")
b_text = open("testfile.out.3", "w+b")
lst_regs = open("regs.lst") lst_regs = open("regs.lst")
lst_instrs = open("instrs.lst") lst_instrs = open("instrs.lst")
@ -69,7 +67,7 @@ pdata_pad = 0
def name_valid(name): def name_valid(name):
for c in name.lower(): for c in name.lower():
if not(c in 'abcdefghijklmnopqrstuvwxyz0123456789[$%._+]='): if not(c in 'abcdefghijklmnopqrstuvwxyz0123456789[$._+]='):
print("BAD '{}'".format(c)) print("BAD '{}'".format(c))
return False return False
return True return True
@ -93,27 +91,59 @@ def parse_preproc(line):
tok = line.split(' ', 2) tok = line.split(' ', 2)
for word in tok: #for word in tok:
if not name_valid(word): # if not name_valid(word):
print("Invalid token in line: {}".format(line)) # print("Invalid token in line: {}".format(line))
return # return
if tok[0] == 'def': # preprocessor
if len(tok) > 1 and tok[1] == ':=':
if len(tok) < 3: if len(tok) < 3:
print("Invalid format: {}".format(line)) print("Invalid format: {}".format(line))
else: leave()
pdefs[tok[1]] = tok[2] sys.exit(1)
pdefs[tok[0]] = tok[2]
return return
# .data # .data
if len(tok) > 1 and tok[1] == '=': if len(tok) > 1 and tok[1] == '=':
if len(tok) < 3: if len(tok) < 3:
print("Invalid format: {}".format(line)) print("Invalid format: {}".format(line))
else: leave()
sys.exit(1)
if is_number(tok[2]):
plabels_data[tok[0]] = pdata 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) assert(written == 8)
pdata += written 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 return
print("Unrecognized directive: {}".format(line)) print("Unrecognized directive: {}".format(line))
@ -205,8 +235,17 @@ def is_number(s):
return True return True
def parse_instr(line): def parse_instr(line):
# instrs.write(hex(ptext))
tok = line.split(' ') tok = line.split(' ')
fellthrough = False fellthrough = False
size = 2
if tok[0] == "rep":
instrs.write("%rep ")
tok = tok[1:]
size += 2
instr_name = tok[0] instr_name = tok[0]
instr_args = '' instr_args = ''
@ -214,8 +253,9 @@ def parse_instr(line):
instrs.write("{}".format(instr_name)) instrs.write("{}".format(instr_name))
return 2 # instruction return 2 # instruction
size = 2 tok = tok[1:]
for word in line.split(' ')[1:]:
for word in tok:
instr_args += ' ' instr_args += ' '
pref = None pref = None
@ -226,7 +266,7 @@ def parse_instr(line):
pref = "%b" pref = "%b"
elif word[0] == 'w': elif word[0] == 'w':
pref = "%w" pref = "%w"
elif word[0] == 'l': elif word[0] == 'l' or word[0] == 'd':
pref = "%l" pref = "%l"
elif word[0] == 'q': elif word[0] == 'q':
pref = "%q" pref = "%q"
@ -254,14 +294,15 @@ def parse_instr(line):
instr_args += "off " instr_args += "off "
assert(len(word) > 3) assert(len(word) > 3)
assert(word[2] == '+' or word[3] == '+')
reg, off = word.strip().split('+', 1)
if word[2] == '+': reg = reg.strip()
# r8, k0, etc off = off.strip()
instr_args += "{} {}".format(word[3:], word[:2])
else: print(reg)
# rax, cr0, etc print(off)
instr_args += "{} {}".format(word[4:], word[:3])
instr_args += "{} {}".format(off, reg)
continue continue
@ -293,7 +334,7 @@ def parse_instr(line):
continue continue
# it's a label (a 64-bit immediate) # 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 size += 2 + 8
if not fellthrough: if not fellthrough:
instr_name += "_i" instr_name += "_i"
@ -320,11 +361,15 @@ special_syms = {
"%imm16": 0x7772, "%imm16": 0x7772,
"%imm32": 0x7774, "%imm32": 0x7774,
"%imm64": 0x7778, "%imm64": 0x7778,
"%rep": 0x8000
} }
def gentext(): def gentext():
instrs.seek(0) 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): for _, line in enumerate(instrs):
tok = line.strip().split(' ') tok = line.strip().split(' ')
@ -342,12 +387,11 @@ def gentext():
if word in plabels_text: if word in plabels_text:
addr = text_start + plabels_text[word] addr = text_start + plabels_text[word]
print(addr.to_bytes(8, byteorder='big', signed=False)) b_text.write(addr.to_bytes(8, byteorder='little', signed=False))
b_text.write(addr.to_bytes(8, byteorder='big', signed=False))
continue continue
if word in plabels_data: 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)) b_text.write(addr.to_bytes(8, byteorder='little', signed=False))
continue continue
@ -358,6 +402,8 @@ def gentext():
lastimm = 4 lastimm = 4
elif word == "%imm64": elif word == "%imm64":
lastimm = 8 lastimm = 8
elif word[2:] == "off" and word[0] == '%':
lastimm = 2
b_text.write(special_syms[word].to_bytes(2, byteorder='little', signed=False)) b_text.write(special_syms[word].to_bytes(2, byteorder='little', signed=False))
continue continue
@ -375,6 +421,12 @@ def genout():
b_text.seek(0) b_text.seek(0)
b_data.seek(0) b_data.seek(0)
b_out.write(b_text.read()) 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()) b_out.write(b_data.read())
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------

BIN
as/k-as.py.text Normal file

Binary file not shown.

View File

@ -1,28 +1,32 @@
inv inv
rip
flg
rbp
rsp
rax rax
rbx rbx
rcx rcx
rdx rdx
rsx
rbi
rdi rdi
rsi rsi
rbp nx0
rsp nx1
r8 nx2
r9 nx3
r10 nx4
r11 nx5
r12 nx6
r13 nx7
r14 ax0
r15 ax1
k0 ax2
k1 ax3
k2 ax4
k3 ax5
k4 ax6
k5 ax7
k6
k7
cr0 cr0
cr1 cr1
cr2 cr2
@ -31,5 +35,11 @@ cr4
cr5 cr5
cr6 cr6
cr7 cr7
rip sa0
flg sa1
sa2
sa3
sa4
sa5
sa6
sa7

View File

@ -1,13 +1,35 @@
# Test assembly file # Test assembly file
# Wololo! # 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 stop
label2: print:
add rax, 1 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 ret

View File

@ -3,23 +3,25 @@
all: k.exe 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)) obj = $(patsubst %.c,%.o,$(src))
%.o: %.c i_arch.h *.h $(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 i_arch.h: instrs/INSTRS instrs/arch_i.py
@python3 instrs.py @cd instrs && python3 arch_i.py
.PHONY: clean .PHONY: clean
clean: clean:
@rm *.o @rm *.o
k.exe: $(obj) i_arch.h INSTRS instrs.py k.exe: $(obj) i_arch.h
@gcc -O2 -Wall $(obj) -o k.exe @gcc -O2 -Wall $(obj) -o k.exe
@rm arch_i.h @rm instrs/arch_i.h
@rm *.o @rm *.o */*.o

View File

@ -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.
#include <ctype.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -26,50 +27,6 @@ typedef struct instr_t instr_t;
typedef struct acc_t acc_t; typedef struct acc_t acc_t;
typedef struct arch_t arch_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_REG is implicit
// A_MEM denotes a memory access // A_MEM denotes a memory access
// A_OFF is A_MEM but a 16-bit offset is expected immediatly next // A_OFF is A_MEM but a 16-bit offset is expected immediatly next
@ -104,11 +61,12 @@ enum
struct acc_t struct acc_t
{ {
bool mem; bool mem;
uint len; uint mlen;
uint type;
ulong val;
short off; short off;
uint type;
uint ilen;
ulong val;
}; };
enum { NOPREF, PREF_REP=0x8000, PREF_LOCK, NPREFS }; enum { NOPREF, PREF_REP=0x8000, PREF_LOCK, NPREFS };
@ -145,6 +103,12 @@ struct ctx_t
FILE *disf; 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 enum
{ {
E_SHT, // Shutdown instruction E_SHT, // Shutdown instruction
@ -158,7 +122,7 @@ enum
}; };
void dumpregs(ctx_t *); 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 dumpmem(ctx_t *, ulong, ulong);
void dumpfwstack(ctx_t *); 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 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 "arch_i.h" #include "regs.h"
#include "instrs/arch_i.h"
extern reg_t arch_r[NREGS];
extern instr_t arch_i[NINSTRS];

View File

@ -36,13 +36,13 @@ static void scan_param(ctx_t *ctx, acc_t *p)
if (A_IS_MEM(c)) { if (A_IS_MEM(c)) {
p->mem = 1; p->mem = 1;
p->off = 0; p->off = 0;
p->len = c & 0xF; p->mlen = c & 0xF;
c = ctx->get(ctx); c = ctx->get(ctx);
} }
else if (A_IS_OFF(c)) { else if (A_IS_OFF(c)) {
p->mem = 1; p->mem = 1;
p->len = c & 0xF; p->mlen = c & 0xF;
p->off = (short)ctx->get(ctx); p->off = (short)ctx->get(ctx);
c = ctx->get(ctx); c = ctx->get(ctx);
} }
@ -59,13 +59,15 @@ static void scan_param(ctx_t *ctx, acc_t *p)
p->val = c; p->val = c;
if (p->type == A_IMM32) { 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) { else if (p->type == A_IMM64) {
p->val = (p->val << 16) | ctx->get(ctx); p->ilen = 8;
p->val = (p->val << 16) | ctx->get(ctx); p->val = p->val | ((ulong)ctx->get(ctx) << 16);
p->val = (p->val << 16) | ctx->get(ctx); p->val = p->val | ((ulong)ctx->get(ctx) << 32);
p->val = p->val | ((ulong)ctx->get(ctx) << 48);
} }
else if (p->type == A_REG) { else if (p->type == A_REG) {
@ -90,11 +92,15 @@ void disasm(ctx_t *ctx)
instr_t *i; instr_t *i;
acc_t p1 = { 0 }, p2 = { 0 }; acc_t p1 = { 0 }, p2 = { 0 };
uint rep = 0;
ulong rip = ctx->r[RIP].val; ulong rip = ctx->r[RIP].val;
ushort c = ctx->get(ctx); ushort c = ctx->get(ctx);
if (ISPREF(c)) { if (ISPREF(c)) {
// nothing for now if (c == PREF_REP) {
rep = 1;
c = ctx->get(ctx);
}
} }
else if (!ISINSTR(c)) { 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 #ifndef _NEED_DISASM
do_rep:
i->func(ctx, &p1, &p2); i->func(ctx, &p1, &p2);
if (rep && ctx->r[RCX].val > 0) {
ctx->r[RCX].val--;
goto do_rep;
}
#endif #endif
} }

View File

@ -3,25 +3,6 @@
#include "arch.h" #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) void dumpmem(ctx_t *ctx, ulong start, ulong size)
{ {
uint i; uint i;
@ -63,24 +44,27 @@ void d_log(ctx_t *ctx, char *fmt, ...)
va_end(ap); 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; acc_t *p = 0;
instr_t *i = &ctx->i[c]; 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) if (i->prm1 != NOPRM)
p = p1; p = p1;
lp: lp:
if (p != 0) { if (p != 0) {
if (p->mem) d_log(ctx, " ["); if (p->mem) d_log(ctx, " %c:[", getmempref(p->mlen));
else d_log(ctx, " "); else d_log(ctx, " ");
if (p->type == A_REG) if (p->type == A_REG)
d_log(ctx, "%s", ctx->r[p->val].name); d_log(ctx, "%s", ctx->r[p->val].name);
else else
d_log(ctx, "0x%lX", p->val); d_log(ctx, "%c:0x%lX", getmempref(p->ilen), p->val);
if (p->mem) { if (p->mem) {
if (p->off) if (p->off)

View File

@ -20,6 +20,6 @@ void _except(ctx_t *ctx, int code, char *fmt, ...)
if (ctx->mp) if (ctx->mp)
free(ctx->mp); free(ctx->mp);
exit(code+1); exit(code);
} }

View File

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

View File

@ -157,14 +157,19 @@ xchg m m
lea r m lea r m
lea m m lea m m
# get code segment
gcs r m
# #
# Stack manipulation instructions # Stack manipulation instructions
# #
push i push i
push r push r
push m
pop r pop r
pop m
call r call r
call i call i
@ -172,6 +177,9 @@ call m
ret ret
enter
leave
pushf pushf
# #
@ -183,3 +191,8 @@ popf
cli cli
sti sti
# Prints a character on the screen
prn r
prn i
prn m

View File

@ -9,7 +9,7 @@ ls = open("instrs.lst", "w")
count = 0 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("#ifdef _NEED_ARCH_I\n")
hd.write("instr_t arch_i[] =\n{\n\n") hd.write("instr_t arch_i[] =\n{\n\n")

67
pc/instrs/arith.c Normal file
View File

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

70
pc/instrs/instrs.c Normal file
View File

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

View File

@ -1,7 +1,7 @@
// The OS/K Team licences this file to you under the MIT license. // The OS/K Team licences 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.
#include "arch.h" #include "../arch.h"
#define IMPL_START_0(name) \ #define IMPL_START_0(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) \
@ -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) \ 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 = readmem(ctx, v1 + p1->off, p1->len); \ if (p1->mem) v1 = readmem(ctx, v1 + p1->off, p1->mlen); \
#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 = readmem(ctx, v1 + p1->off, p1->len); \ if (p1->mem) v1 = readmem(ctx, v1 + p1->off, p1->mlen); \
if (p2->mem) v2 = readmem(ctx, v2 + p2->off, p2->len); \ if (p2->mem) v2 = readmem(ctx, v2 + p2->off, p2->mlen); \
#define IMPL_START_3(name) \ #define IMPL_START_3(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 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 (p2->mem) v2 = readmem(ctx, v2 + p2->off, p2->len); \ if (p2->mem) v2 = readmem(ctx, v2 + p2->off, p2->mlen); \
#define IMPL_OUT \ #define IMPL_OUT \
assert(p1->type == A_REG || p1->mem); \ assert(p1->type == A_REG || p1->mem); \
if (p1->mem) { \ if (p1->mem) { \
ulong addr = p1->type == A_REG ? ctx->r[p1->val].val : p1->val; \ 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; \ 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) } 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

View File

@ -4,6 +4,10 @@
#include "instrs.h" #include "instrs.h"
#include "arch_i.h" #include "arch_i.h"
//
// Jump instructions
//
IMPL_START_1(jmp) IMPL_START_1(jmp)
{ {
ctx->r[RIP].val = v1; ctx->r[RIP].val = v1;
@ -13,62 +17,62 @@ IMPL_END;
IMPL_START_1(jz) IMPL_START_1(jz)
{ {
if (ctx->r[FLG].val & ZF) if (ctx->r[FLG].val & ZF)
ctx->r[RIP].val = v1; JUMP(v1);
} }
IMPL_END; IMPL_END;
IMPL_START_1(jnz) IMPL_START_1(jnz)
{ {
if (!(ctx->r[FLG].val & ZF)) if (!(ctx->r[FLG].val & ZF))
ctx->r[RIP].val = v1; JUMP(v1);
} }
IMPL_END; IMPL_END;
IMPL_START_1(je) IMPL_START_1(je)
{ {
if (ctx->r[FLG].val & ZF) if (ctx->r[FLG].val & ZF)
ctx->r[RIP].val = v1; JUMP(v1);
} }
IMPL_END; IMPL_END;
IMPL_START_1(jne) IMPL_START_1(jne)
{ {
if (!(ctx->r[FLG].val & ZF)) if (!(ctx->r[FLG].val & ZF))
ctx->r[RIP].val = v1; JUMP(v1);
} }
IMPL_END; IMPL_END;
IMPL_START_1(ja) IMPL_START_1(ja)
{ {
if (!(ctx->r[FLG].val & ZF) && !(ctx->r[FLG].val & CF)) if (!(ctx->r[FLG].val & ZF) && !(ctx->r[FLG].val & CF))
ctx->r[RIP].val = v1; JUMP(v1);
} }
IMPL_END; IMPL_END;
IMPL_START_1(jae) IMPL_START_1(jae)
{ {
if (!(ctx->r[FLG].val & CF)) if (!(ctx->r[FLG].val & CF))
ctx->r[RIP].val = v1; JUMP(v1);
} }
IMPL_END; IMPL_END;
IMPL_START_1(jb) IMPL_START_1(jb)
{ {
if (!(ctx->r[FLG].val & ZF) && ctx->r[FLG].val & CF) if (!(ctx->r[FLG].val & ZF) && ctx->r[FLG].val & CF)
ctx->r[RIP].val = v1; JUMP(v1);
} }
IMPL_END; IMPL_END;
IMPL_START_1(jbe) IMPL_START_1(jbe)
{ {
if (ctx->r[FLG].val & CF) if (ctx->r[FLG].val & CF)
ctx->r[RIP].val = v1; JUMP(v1);
} }
IMPL_END; IMPL_END;
IMPL_START_1(jcxz) IMPL_START_1(jcxz)
{ {
if (!ctx->r[RCX].val) if (!ctx->r[RCX].val)
ctx->r[RIP].val = v1; JUMP(v1);
} }
IMPL_END; IMPL_END;

78
pc/instrs/logic.c Normal file
View File

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

75
pc/instrs/stack.c Normal file
View File

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

30
pc/instrs/super.c Normal file
View File

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

View File

@ -18,7 +18,7 @@ ushort bget(ctx_t *ctx)
_except(ctx, E_ACC, "Executing out of memory: 0x%016lX", _except(ctx, E_ACC, "Executing out of memory: 0x%016lX",
ctx->r[RIP].val); ctx->r[RIP].val);
} }
ushort c = ctx->mp[addr2real(ctx->r[RIP].val)]; ushort c = ctx->mp[addr2real(ctx->r[RIP].val)];
ctx->r[RIP].val += 2; ctx->r[RIP].val += 2;
@ -40,9 +40,6 @@ ushort dget(ctx_t *ctx)
return fwprog[i++]; return fwprog[i++];
} }
extern reg_t arch_r[NREGS];
extern instr_t arch_i[NINSTRS];
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
ctx_t main_ctx; ctx_t main_ctx;

View File

@ -16,26 +16,28 @@ ulong readmem(ctx_t *ctx, ulong addr, uint len)
ulong readmem8(ctx_t *ctx, ulong addr) ulong readmem8(ctx_t *ctx, ulong addr)
{ {
addr += ctx->r[CR2].val;
ulong real = addr2real(addr); ulong real = addr2real(addr);
if (addr < MEMOFF || real >= MEMSIZE) { 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; else return ((ulong)ctx->mp[real] & 0xFF00) >> 8;
} }
ulong readmem16(ctx_t *ctx, ulong addr) ulong readmem16(ctx_t *ctx, ulong addr)
{ {
addr += ctx->r[CR2].val;
ulong real = addr2real(addr); ulong real = addr2real(addr);
if (addr % alignof(ushort) > 0) { 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) { 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]; return (ulong)ctx->mp[real];
@ -43,44 +45,47 @@ ulong readmem16(ctx_t *ctx, ulong addr)
ulong readmem32(ctx_t *ctx, ulong addr) ulong readmem32(ctx_t *ctx, ulong addr)
{ {
addr += ctx->r[CR2].val;
ulong real = addr2real(addr); ulong real = addr2real(addr);
if (addr % alignof(uint) > 0) { 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) { 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++]; ulong val = ctx->mp[real++];
val = (val << 16) | (ulong)ctx->mp[real]; val = val | ((ulong)ctx->mp[real] << 16);
return val; return val;
} }
ulong readmem64(ctx_t *ctx, ulong addr) ulong readmem64(ctx_t *ctx, ulong addr)
{ {
addr += ctx->r[CR2].val;
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: 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) { 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++]; ulong val = (ulong)ctx->mp[real++];
val = (val << 16) | (ulong)ctx->mp[real++]; val = val | ((ulong)ctx->mp[real++] << 16);
val = (val << 16) | (ulong)ctx->mp[real++]; val = val | ((ulong)ctx->mp[real++] << 32);
val = (val << 16) | (ulong)ctx->mp[real]; val = val | ((ulong)ctx->mp[real] << 48);
return val; return val;
} }
void writemem(ctx_t *ctx, ulong val, ulong addr, uint len) void writemem(ctx_t *ctx, ulong val, ulong addr, uint len)
{ {
addr += ctx->r[CR2].val;
switch (len) { switch (len) {
case 1: writemem8(ctx, val, addr); break; case 1: writemem8(ctx, val, addr); break;
case 2: writemem16(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) void writemem8(ctx_t *ctx, ulong val, ulong addr)
{ {
addr += ctx->r[CR2].val;
ulong real = addr2real(addr); ulong real = addr2real(addr);
if (addr < MEMOFF || real >= MEMSIZE) { 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]; 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) void writemem16(ctx_t *ctx, ulong val, ulong addr)
{ {
addr += ctx->r[CR2].val;
ulong real = addr2real(addr); ulong real = addr2real(addr);
if (addr % alignof(ushort) > 0) { 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) { 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; 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) void writemem32(ctx_t *ctx, ulong val, ulong addr)
{ {
addr += ctx->r[CR2].val;
ulong real = addr2real(addr); ulong real = addr2real(addr);
if (addr % alignof(uint) > 0) { 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) { 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) void writemem64(ctx_t *ctx, ulong val, ulong addr)
{ {
addr += ctx->r[CR2].val;
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: 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) { 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;
ctx->mp[real++] = (val >> 32) & 0xFFFF;
ctx->mp[real++] = (val >> 16) & 0xFFFF; ctx->mp[real++] = (val >> 16) & 0xFFFF;
ctx->mp[real] = val & 0xFFFF; ctx->mp[real++] = (val >> 32) & 0xFFFF;
ctx->mp[real] = (val >> 48) & 0xFFFF;
} }

114
pc/regs.c
View File

@ -6,39 +6,85 @@
reg_t arch_r[NREGS] = reg_t arch_r[NREGS] =
{ {
{ "inv", "Invalid register", 0, RES }, { "inv", "Invalid register", 0, RES },
{ "rax", "Accumulator 0", 0, GPR },
{ "rbx", "Accumulator 1", 0, GPR }, { "rip", "Instruction pointer", "Special; Volatile", 0, RES },
{ "rcx", "Accumulator 2", 0, GPR }, { "flg", "Flags register", "Special; Volatile", 0, RES },
{ "rdx", "Accumulator 3", 0, GPR },
{ "rdi", "Accumulator 4", 0, GPR }, { "rbp", "Stack base", "Special; Non-volatile", 0, GPR },
{ "rsi", "Accumulator 5", 0, GPR }, { "rsp", "Stack pointer", "Special; Non-volatile", 0, GPR },
{ "rbp", "Stack base", 0, GPR },
{ "rsp", "Stack pointer", 0, GPR }, { "rax", "Accumulator 0", "Volatile", 0, GPR },
{ "r8", "Accumulator 8", 0, GPR }, { "rbx", "Accumulator 1", "Volatile", 0, GPR },
{ "r9", "Accumulator 9", 0, GPR }, { "rcx", "Accumulator 2", "Volatile", 0, GPR },
{ "r10", "Accumulator 10", 0, GPR }, { "rdx", "Accumulator 3", "Volatile", 0, GPR },
{ "r11", "Accumulator 11", 0, GPR }, { "rsx", "Accumulator 4", "Volatile", 0, GPR },
{ "r12", "Accumulator 12", 0, GPR }, { "rbi", "Accumulator 5", "Volatile", 0, GPR },
{ "r13", "Accumulator 13", 0, GPR }, { "rdi", "Accumulator 6", "Volatile", 0, GPR },
{ "r14", "Accumulator 14", 0, GPR }, { "rsi", "Accumulator 7", "Volatile", 0, GPR },
{ "r15", "Accumulator 15", 0, GPR },
{ "k0", "Supervisor accumulator 0", 0, SYS }, { "nx0", "Accumulator 8", "Non-volatile", 0, GPR },
{ "k1", "Supervisor accumulator 1", 0, SYS }, { "nx1", "Accumulator 9", "Non-volatile", 0, GPR },
{ "k2", "Supervisor accumulator 2", 0, SYS }, { "nx2", "Accumulator 10", "Non-volatile", 0, GPR },
{ "k3", "Supervisor accumulator 3", 0, SYS }, { "nx3", "Accumulator 11", "Non-volatile", 0, GPR },
{ "k4", "Supervisor accumulator 4", 0, SYS }, { "nx4", "Accumulator 12", "Non-volatile", 0, GPR },
{ "k5", "Supervisor accumulator 5", 0, SYS }, { "nx5", "Accumulator 13", "Non-volatile", 0, GPR },
{ "k6", "Supervisor accumulator 6", 0, SYS }, { "nx6", "Accumulator 14", "Non-volatile", 0, GPR },
{ "k7", "Supervisor accumulator 7", 0, SYS }, { "nx7", "Accumulator 15", "Non-volatile", 0, GPR },
{ "cr0", "Control register 0", 0, CTL },
{ "cr1", "Control register 1", 0, CTL }, { "ax0", "Argument 0", "Volatile", 0, GPR },
{ "cr2", "Control register 2", 0, CTL }, { "ax1", "Argument 1", "Volatile", 0, GPR },
{ "cr3", "Control register 3", 0, CTL }, { "ax2", "Argument 2", "Volatile", 0, GPR },
{ "cr4", "Control register 4", 0, CTL }, { "ax3", "Argument 3", "Volatile", 0, GPR },
{ "cr5", "Control register 5", 0, CTL }, { "ax4", "Argument 4", "Volatile", 0, GPR },
{ "cr6", "Control register 6", 0, CTL }, { "ax5", "Argument 5", "Volatile", 0, GPR },
{ "cr7", "Control register 7", 0, CTL }, { "ax6", "Argument 6", "Volatile", 0, GPR },
{ "rip", "Instruction pointer", 0, RES }, { "ax7", "Argument 7", "Volatile", 0, GPR },
{ "flg", "Flags register", 0, RES },
// 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");
}

95
pc/regs.h Normal file
View File

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