mirror of
https://gitlab.os-k.eu/os-k-team/kvisc.git
synced 2023-08-25 14:05:46 +02:00
lots of stuff
This commit is contained in:
parent
8e50810bf7
commit
29ef2b35b5
6
Makefile
6
Makefile
@ -8,9 +8,13 @@ kpc:
|
||||
@cd pc && make --no-print-directory
|
||||
|
||||
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
|
||||
@cd as && ./k-as.py testfile.asm 0x100000 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
|
||||
|
112
as/k-as.py
112
as/k-as.py
@ -13,11 +13,9 @@ if len(sys.argv) != 4:
|
||||
.format(sys.argv[0]))
|
||||
sys.exit(1)
|
||||
|
||||
# TemporaryFile(mode='w+')
|
||||
instrs = open("testfile.out.1", "w+")
|
||||
|
||||
b_data = open("testfile.out.2", "w+b")
|
||||
b_text = open("testfile.out.3", "w+b")
|
||||
instrs = open("{}.instr".format(sys.argv[3]), "w+")
|
||||
b_data = open("{}.data".format(sys.argv[3]), "w+b")
|
||||
b_text = open("{}.text".format(sys.argv[3]), "w+b")
|
||||
|
||||
lst_regs = open("regs.lst")
|
||||
lst_instrs = open("instrs.lst")
|
||||
@ -69,7 +67,7 @@ pdata_pad = 0
|
||||
|
||||
def name_valid(name):
|
||||
for c in name.lower():
|
||||
if not(c in 'abcdefghijklmnopqrstuvwxyz0123456789[$%._+]='):
|
||||
if not(c in 'abcdefghijklmnopqrstuvwxyz0123456789[$._+]='):
|
||||
print("BAD '{}'".format(c))
|
||||
return False
|
||||
return True
|
||||
@ -93,27 +91,59 @@ def parse_preproc(line):
|
||||
|
||||
tok = line.split(' ', 2)
|
||||
|
||||
for word in tok:
|
||||
if not name_valid(word):
|
||||
print("Invalid token in line: {}".format(line))
|
||||
return
|
||||
#for word in tok:
|
||||
# if not name_valid(word):
|
||||
# print("Invalid token in line: {}".format(line))
|
||||
# return
|
||||
|
||||
if tok[0] == 'def':
|
||||
# preprocessor
|
||||
if len(tok) > 1 and tok[1] == ':=':
|
||||
if len(tok) < 3:
|
||||
print("Invalid format: {}".format(line))
|
||||
else:
|
||||
pdefs[tok[1]] = tok[2]
|
||||
leave()
|
||||
sys.exit(1)
|
||||
pdefs[tok[0]] = tok[2]
|
||||
return
|
||||
|
||||
# .data
|
||||
if len(tok) > 1 and tok[1] == '=':
|
||||
if len(tok) < 3:
|
||||
print("Invalid format: {}".format(line))
|
||||
else:
|
||||
leave()
|
||||
sys.exit(1)
|
||||
|
||||
if is_number(tok[2]):
|
||||
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)
|
||||
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
|
||||
|
||||
print("Unrecognized directive: {}".format(line))
|
||||
@ -205,8 +235,17 @@ def is_number(s):
|
||||
return True
|
||||
|
||||
def parse_instr(line):
|
||||
# instrs.write(hex(ptext))
|
||||
tok = line.split(' ')
|
||||
fellthrough = False
|
||||
|
||||
size = 2
|
||||
|
||||
if tok[0] == "rep":
|
||||
instrs.write("%rep ")
|
||||
tok = tok[1:]
|
||||
size += 2
|
||||
|
||||
instr_name = tok[0]
|
||||
instr_args = ''
|
||||
|
||||
@ -214,8 +253,9 @@ def parse_instr(line):
|
||||
instrs.write("{}".format(instr_name))
|
||||
return 2 # instruction
|
||||
|
||||
size = 2
|
||||
for word in line.split(' ')[1:]:
|
||||
tok = tok[1:]
|
||||
|
||||
for word in tok:
|
||||
instr_args += ' '
|
||||
|
||||
pref = None
|
||||
@ -226,7 +266,7 @@ def parse_instr(line):
|
||||
pref = "%b"
|
||||
elif word[0] == 'w':
|
||||
pref = "%w"
|
||||
elif word[0] == 'l':
|
||||
elif word[0] == 'l' or word[0] == 'd':
|
||||
pref = "%l"
|
||||
elif word[0] == 'q':
|
||||
pref = "%q"
|
||||
@ -254,14 +294,15 @@ def parse_instr(line):
|
||||
instr_args += "off "
|
||||
|
||||
assert(len(word) > 3)
|
||||
assert(word[2] == '+' or word[3] == '+')
|
||||
|
||||
if word[2] == '+':
|
||||
# r8, k0, etc
|
||||
instr_args += "{} {}".format(word[3:], word[:2])
|
||||
else:
|
||||
# rax, cr0, etc
|
||||
instr_args += "{} {}".format(word[4:], word[:3])
|
||||
reg, off = word.strip().split('+', 1)
|
||||
reg = reg.strip()
|
||||
off = off.strip()
|
||||
|
||||
print(reg)
|
||||
print(off)
|
||||
|
||||
instr_args += "{} {}".format(off, reg)
|
||||
|
||||
continue
|
||||
|
||||
@ -293,7 +334,7 @@ def parse_instr(line):
|
||||
continue
|
||||
|
||||
# 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
|
||||
if not fellthrough:
|
||||
instr_name += "_i"
|
||||
@ -320,11 +361,15 @@ special_syms = {
|
||||
"%imm16": 0x7772,
|
||||
"%imm32": 0x7774,
|
||||
"%imm64": 0x7778,
|
||||
|
||||
"%rep": 0x8000
|
||||
}
|
||||
|
||||
def gentext():
|
||||
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):
|
||||
tok = line.strip().split(' ')
|
||||
@ -342,12 +387,11 @@ def gentext():
|
||||
|
||||
if word in plabels_text:
|
||||
addr = text_start + plabels_text[word]
|
||||
print(addr.to_bytes(8, byteorder='big', signed=False))
|
||||
b_text.write(addr.to_bytes(8, byteorder='big', signed=False))
|
||||
b_text.write(addr.to_bytes(8, byteorder='little', signed=False))
|
||||
continue
|
||||
|
||||
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))
|
||||
continue
|
||||
|
||||
@ -358,6 +402,8 @@ def gentext():
|
||||
lastimm = 4
|
||||
elif word == "%imm64":
|
||||
lastimm = 8
|
||||
elif word[2:] == "off" and word[0] == '%':
|
||||
lastimm = 2
|
||||
b_text.write(special_syms[word].to_bytes(2, byteorder='little', signed=False))
|
||||
continue
|
||||
|
||||
@ -375,6 +421,12 @@ def genout():
|
||||
b_text.seek(0)
|
||||
b_data.seek(0)
|
||||
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())
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
BIN
as/k-as.py.text
Normal file
BIN
as/k-as.py.text
Normal file
Binary file not shown.
50
as/regs.lst
50
as/regs.lst
@ -1,28 +1,32 @@
|
||||
inv
|
||||
rip
|
||||
flg
|
||||
rbp
|
||||
rsp
|
||||
rax
|
||||
rbx
|
||||
rcx
|
||||
rdx
|
||||
rsx
|
||||
rbi
|
||||
rdi
|
||||
rsi
|
||||
rbp
|
||||
rsp
|
||||
r8
|
||||
r9
|
||||
r10
|
||||
r11
|
||||
r12
|
||||
r13
|
||||
r14
|
||||
r15
|
||||
k0
|
||||
k1
|
||||
k2
|
||||
k3
|
||||
k4
|
||||
k5
|
||||
k6
|
||||
k7
|
||||
nx0
|
||||
nx1
|
||||
nx2
|
||||
nx3
|
||||
nx4
|
||||
nx5
|
||||
nx6
|
||||
nx7
|
||||
ax0
|
||||
ax1
|
||||
ax2
|
||||
ax3
|
||||
ax4
|
||||
ax5
|
||||
ax6
|
||||
ax7
|
||||
cr0
|
||||
cr1
|
||||
cr2
|
||||
@ -31,5 +35,11 @@ cr4
|
||||
cr5
|
||||
cr6
|
||||
cr7
|
||||
rip
|
||||
flg
|
||||
sa0
|
||||
sa1
|
||||
sa2
|
||||
sa3
|
||||
sa4
|
||||
sa5
|
||||
sa6
|
||||
sa7
|
||||
|
@ -1,13 +1,35 @@
|
||||
# Test assembly file
|
||||
# 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
|
||||
|
||||
label2:
|
||||
add rax, 1
|
||||
print:
|
||||
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
|
||||
|
||||
|
16
pc/Makefile
16
pc/Makefile
@ -3,23 +3,25 @@
|
||||
|
||||
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))
|
||||
|
||||
%.o: %.c i_arch.h *.h $(src)
|
||||
@gcc -O2 -Wall -c $< -o $@
|
||||
@gcc -O2 -g -Wall -c $< -o $@
|
||||
|
||||
i_arch.h: INSTRS instrs.py
|
||||
@python3 instrs.py
|
||||
i_arch.h: instrs/INSTRS instrs/arch_i.py
|
||||
@cd instrs && python3 arch_i.py
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
clean:
|
||||
@rm *.o
|
||||
|
||||
k.exe: $(obj) i_arch.h INSTRS instrs.py
|
||||
k.exe: $(obj) i_arch.h
|
||||
@gcc -O2 -Wall $(obj) -o k.exe
|
||||
@rm arch_i.h
|
||||
@rm *.o
|
||||
@rm instrs/arch_i.h
|
||||
@rm *.o */*.o
|
||||
|
||||
|
68
pc/arch.h
68
pc/arch.h
@ -1,6 +1,7 @@
|
||||
// The OS/K Team licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -26,50 +27,6 @@ typedef struct instr_t instr_t;
|
||||
typedef struct acc_t acc_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_MEM denotes a memory access
|
||||
// A_OFF is A_MEM but a 16-bit offset is expected immediatly next
|
||||
@ -104,11 +61,12 @@ enum
|
||||
struct acc_t
|
||||
{
|
||||
bool mem;
|
||||
uint len;
|
||||
uint type;
|
||||
|
||||
ulong val;
|
||||
uint mlen;
|
||||
short off;
|
||||
|
||||
uint type;
|
||||
uint ilen;
|
||||
ulong val;
|
||||
};
|
||||
|
||||
enum { NOPREF, PREF_REP=0x8000, PREF_LOCK, NPREFS };
|
||||
@ -145,6 +103,12 @@ struct ctx_t
|
||||
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
|
||||
{
|
||||
E_SHT, // Shutdown instruction
|
||||
@ -158,7 +122,7 @@ enum
|
||||
};
|
||||
|
||||
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 dumpfwstack(ctx_t *);
|
||||
|
||||
@ -188,5 +152,9 @@ void writemem32(ctx_t *, ulong val, ulong addr);
|
||||
void writemem64(ctx_t *, ulong val, ulong addr);
|
||||
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];
|
||||
|
||||
|
30
pc/decd.c
30
pc/decd.c
@ -36,13 +36,13 @@ static void scan_param(ctx_t *ctx, acc_t *p)
|
||||
if (A_IS_MEM(c)) {
|
||||
p->mem = 1;
|
||||
p->off = 0;
|
||||
p->len = c & 0xF;
|
||||
p->mlen = c & 0xF;
|
||||
c = ctx->get(ctx);
|
||||
}
|
||||
|
||||
else if (A_IS_OFF(c)) {
|
||||
p->mem = 1;
|
||||
p->len = c & 0xF;
|
||||
p->mlen = c & 0xF;
|
||||
p->off = (short)ctx->get(ctx);
|
||||
c = ctx->get(ctx);
|
||||
}
|
||||
@ -59,13 +59,15 @@ static void scan_param(ctx_t *ctx, acc_t *p)
|
||||
p->val = c;
|
||||
|
||||
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) {
|
||||
p->val = (p->val << 16) | ctx->get(ctx);
|
||||
p->val = (p->val << 16) | ctx->get(ctx);
|
||||
p->val = (p->val << 16) | ctx->get(ctx);
|
||||
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) {
|
||||
@ -90,11 +92,15 @@ void disasm(ctx_t *ctx)
|
||||
instr_t *i;
|
||||
acc_t p1 = { 0 }, p2 = { 0 };
|
||||
|
||||
uint rep = 0;
|
||||
ulong rip = ctx->r[RIP].val;
|
||||
ushort c = ctx->get(ctx);
|
||||
|
||||
if (ISPREF(c)) {
|
||||
// nothing for now
|
||||
if (c == PREF_REP) {
|
||||
rep = 1;
|
||||
c = ctx->get(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
do_rep:
|
||||
i->func(ctx, &p1, &p2);
|
||||
|
||||
if (rep && ctx->r[RCX].val > 0) {
|
||||
ctx->r[RCX].val--;
|
||||
goto do_rep;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
30
pc/dump.c
30
pc/dump.c
@ -3,25 +3,6 @@
|
||||
|
||||
#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)
|
||||
{
|
||||
uint i;
|
||||
@ -63,24 +44,27 @@ void d_log(ctx_t *ctx, char *fmt, ...)
|
||||
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;
|
||||
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)
|
||||
p = p1;
|
||||
lp:
|
||||
if (p != 0) {
|
||||
if (p->mem) d_log(ctx, " [");
|
||||
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, "0x%lX", p->val);
|
||||
d_log(ctx, "%c:0x%lX", getmempref(p->ilen), p->val);
|
||||
|
||||
if (p->mem) {
|
||||
if (p->off)
|
||||
|
@ -20,6 +20,6 @@ void _except(ctx_t *ctx, int code, char *fmt, ...)
|
||||
|
||||
if (ctx->mp)
|
||||
free(ctx->mp);
|
||||
exit(code+1);
|
||||
exit(code);
|
||||
}
|
||||
|
||||
|
298
pc/instrs.c
298
pc/instrs.c
@ -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;
|
||||
|
@ -157,14 +157,19 @@ xchg m m
|
||||
lea r m
|
||||
lea m m
|
||||
|
||||
# get code segment
|
||||
gcs r m
|
||||
|
||||
#
|
||||
# Stack manipulation instructions
|
||||
#
|
||||
|
||||
push i
|
||||
push r
|
||||
push m
|
||||
|
||||
pop r
|
||||
pop m
|
||||
|
||||
call r
|
||||
call i
|
||||
@ -172,6 +177,9 @@ call m
|
||||
|
||||
ret
|
||||
|
||||
enter
|
||||
leave
|
||||
|
||||
pushf
|
||||
|
||||
#
|
||||
@ -183,3 +191,8 @@ popf
|
||||
cli
|
||||
sti
|
||||
|
||||
# Prints a character on the screen
|
||||
prn r
|
||||
prn i
|
||||
prn m
|
||||
|
@ -9,7 +9,7 @@ ls = open("instrs.lst", "w")
|
||||
|
||||
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("instr_t arch_i[] =\n{\n\n")
|
67
pc/instrs/arith.c
Normal file
67
pc/instrs/arith.c
Normal 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
70
pc/instrs/instrs.c
Normal 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;
|
||||
|
@ -1,7 +1,7 @@
|
||||
// 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 "arch.h"
|
||||
#include "../arch.h"
|
||||
|
||||
#define IMPL_START_0(name) \
|
||||
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) \
|
||||
{ \
|
||||
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) \
|
||||
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 v2 = (p2->type == A_REG ? ctx->r[p2->val].val : p2->val); \
|
||||
if (p1->mem) v1 = readmem(ctx, v1 + p1->off, p1->len); \
|
||||
if (p2->mem) v2 = readmem(ctx, v2 + p2->off, p2->len); \
|
||||
if (p1->mem) v1 = readmem(ctx, v1 + p1->off, p1->mlen); \
|
||||
if (p2->mem) v2 = readmem(ctx, v2 + p2->off, p2->mlen); \
|
||||
|
||||
#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 = readmem(ctx, v2 + p2->off, p2->len); \
|
||||
if (p2->mem) v2 = readmem(ctx, v2 + p2->off, p2->mlen); \
|
||||
|
||||
#define IMPL_OUT \
|
||||
assert(p1->type == A_REG || p1->mem); \
|
||||
if (p1->mem) { \
|
||||
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; \
|
||||
} \
|
||||
@ -46,3 +46,25 @@ void i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2) \
|
||||
} \
|
||||
} 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
|
||||
|
||||
|
||||
|
||||
|
@ -4,6 +4,10 @@
|
||||
#include "instrs.h"
|
||||
#include "arch_i.h"
|
||||
|
||||
//
|
||||
// Jump instructions
|
||||
//
|
||||
|
||||
IMPL_START_1(jmp)
|
||||
{
|
||||
ctx->r[RIP].val = v1;
|
||||
@ -13,62 +17,62 @@ IMPL_END;
|
||||
IMPL_START_1(jz)
|
||||
{
|
||||
if (ctx->r[FLG].val & ZF)
|
||||
ctx->r[RIP].val = v1;
|
||||
JUMP(v1);
|
||||
}
|
||||
IMPL_END;
|
||||
|
||||
IMPL_START_1(jnz)
|
||||
{
|
||||
if (!(ctx->r[FLG].val & ZF))
|
||||
ctx->r[RIP].val = v1;
|
||||
JUMP(v1);
|
||||
}
|
||||
IMPL_END;
|
||||
|
||||
IMPL_START_1(je)
|
||||
{
|
||||
if (ctx->r[FLG].val & ZF)
|
||||
ctx->r[RIP].val = v1;
|
||||
JUMP(v1);
|
||||
}
|
||||
IMPL_END;
|
||||
|
||||
IMPL_START_1(jne)
|
||||
{
|
||||
if (!(ctx->r[FLG].val & ZF))
|
||||
ctx->r[RIP].val = v1;
|
||||
JUMP(v1);
|
||||
}
|
||||
IMPL_END;
|
||||
|
||||
IMPL_START_1(ja)
|
||||
{
|
||||
if (!(ctx->r[FLG].val & ZF) && !(ctx->r[FLG].val & CF))
|
||||
ctx->r[RIP].val = v1;
|
||||
JUMP(v1);
|
||||
}
|
||||
IMPL_END;
|
||||
|
||||
IMPL_START_1(jae)
|
||||
{
|
||||
if (!(ctx->r[FLG].val & CF))
|
||||
ctx->r[RIP].val = v1;
|
||||
JUMP(v1);
|
||||
}
|
||||
IMPL_END;
|
||||
|
||||
IMPL_START_1(jb)
|
||||
{
|
||||
if (!(ctx->r[FLG].val & ZF) && ctx->r[FLG].val & CF)
|
||||
ctx->r[RIP].val = v1;
|
||||
JUMP(v1);
|
||||
}
|
||||
IMPL_END;
|
||||
|
||||
IMPL_START_1(jbe)
|
||||
{
|
||||
if (ctx->r[FLG].val & CF)
|
||||
ctx->r[RIP].val = v1;
|
||||
JUMP(v1);
|
||||
}
|
||||
IMPL_END;
|
||||
|
||||
IMPL_START_1(jcxz)
|
||||
{
|
||||
if (!ctx->r[RCX].val)
|
||||
ctx->r[RIP].val = v1;
|
||||
JUMP(v1);
|
||||
}
|
||||
IMPL_END;
|
78
pc/instrs/logic.c
Normal file
78
pc/instrs/logic.c
Normal 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
75
pc/instrs/stack.c
Normal 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
30
pc/instrs/super.c
Normal 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;
|
||||
|
@ -40,9 +40,6 @@ ushort dget(ctx_t *ctx)
|
||||
return fwprog[i++];
|
||||
}
|
||||
|
||||
extern reg_t arch_r[NREGS];
|
||||
extern instr_t arch_i[NINSTRS];
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ctx_t main_ctx;
|
||||
|
32
pc/mem.c
32
pc/mem.c
@ -16,18 +16,20 @@ ulong readmem(ctx_t *ctx, ulong addr, uint len)
|
||||
|
||||
ulong readmem8(ctx_t *ctx, ulong addr)
|
||||
{
|
||||
addr += ctx->r[CR2].val;
|
||||
ulong real = addr2real(addr);
|
||||
|
||||
if (addr < MEMOFF || real >= MEMSIZE) {
|
||||
_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;
|
||||
}
|
||||
|
||||
ulong readmem16(ctx_t *ctx, ulong addr)
|
||||
{
|
||||
addr += ctx->r[CR2].val;
|
||||
ulong real = addr2real(addr);
|
||||
|
||||
if (addr % alignof(ushort) > 0) {
|
||||
@ -43,6 +45,7 @@ ulong readmem16(ctx_t *ctx, ulong addr)
|
||||
|
||||
ulong readmem32(ctx_t *ctx, ulong addr)
|
||||
{
|
||||
addr += ctx->r[CR2].val;
|
||||
ulong real = addr2real(addr);
|
||||
|
||||
if (addr % alignof(uint) > 0) {
|
||||
@ -53,14 +56,15 @@ ulong readmem32(ctx_t *ctx, ulong addr)
|
||||
_except(ctx, E_ACC, "Invalid MEM access: 0x%012lX (0x%012lX)", addr, real);
|
||||
}
|
||||
|
||||
ulong val = (ulong)ctx->mp[real++];
|
||||
val = (val << 16) | (ulong)ctx->mp[real];
|
||||
ulong val = ctx->mp[real++];
|
||||
val = val | ((ulong)ctx->mp[real] << 16);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
ulong readmem64(ctx_t *ctx, ulong addr)
|
||||
{
|
||||
addr += ctx->r[CR2].val;
|
||||
ulong real = addr2real(addr);
|
||||
|
||||
if (addr % alignof(ulong) > 0) {
|
||||
@ -72,15 +76,16 @@ ulong readmem64(ctx_t *ctx, ulong addr)
|
||||
}
|
||||
|
||||
ulong val = (ulong)ctx->mp[real++];
|
||||
val = (val << 16) | (ulong)ctx->mp[real++];
|
||||
val = (val << 16) | (ulong)ctx->mp[real++];
|
||||
val = (val << 16) | (ulong)ctx->mp[real];
|
||||
val = val | ((ulong)ctx->mp[real++] << 16);
|
||||
val = val | ((ulong)ctx->mp[real++] << 32);
|
||||
val = val | ((ulong)ctx->mp[real] << 48);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void writemem(ctx_t *ctx, ulong val, ulong addr, uint len)
|
||||
{
|
||||
addr += ctx->r[CR2].val;
|
||||
switch (len) {
|
||||
case 1: writemem8(ctx, val, addr); break;
|
||||
case 2: writemem16(ctx, val, addr); break;
|
||||
@ -92,6 +97,7 @@ void writemem(ctx_t *ctx, ulong val, ulong addr, uint len)
|
||||
|
||||
void writemem8(ctx_t *ctx, ulong val, ulong addr)
|
||||
{
|
||||
addr += ctx->r[CR2].val;
|
||||
ulong real = addr2real(addr);
|
||||
|
||||
if (addr < MEMOFF || real >= MEMSIZE) {
|
||||
@ -111,6 +117,7 @@ void writemem8(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);
|
||||
|
||||
if (addr % alignof(ushort) > 0) {
|
||||
@ -126,6 +133,7 @@ void writemem16(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);
|
||||
|
||||
if (addr % alignof(uint) > 0) {
|
||||
@ -136,12 +144,13 @@ void writemem32(ctx_t *ctx, ulong val, ulong addr)
|
||||
_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)
|
||||
{
|
||||
addr += ctx->r[CR2].val;
|
||||
ulong real = addr2real(addr);
|
||||
|
||||
if (addr % alignof(ulong) > 0) {
|
||||
@ -152,8 +161,9 @@ void writemem64(ctx_t *ctx, ulong val, ulong addr)
|
||||
_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;
|
||||
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
114
pc/regs.c
@ -6,39 +6,85 @@
|
||||
reg_t arch_r[NREGS] =
|
||||
{
|
||||
{ "inv", "Invalid register", 0, RES },
|
||||
{ "rax", "Accumulator 0", 0, GPR },
|
||||
{ "rbx", "Accumulator 1", 0, GPR },
|
||||
{ "rcx", "Accumulator 2", 0, GPR },
|
||||
{ "rdx", "Accumulator 3", 0, GPR },
|
||||
{ "rdi", "Accumulator 4", 0, GPR },
|
||||
{ "rsi", "Accumulator 5", 0, GPR },
|
||||
{ "rbp", "Stack base", 0, GPR },
|
||||
{ "rsp", "Stack pointer", 0, GPR },
|
||||
{ "r8", "Accumulator 8", 0, GPR },
|
||||
{ "r9", "Accumulator 9", 0, GPR },
|
||||
{ "r10", "Accumulator 10", 0, GPR },
|
||||
{ "r11", "Accumulator 11", 0, GPR },
|
||||
{ "r12", "Accumulator 12", 0, GPR },
|
||||
{ "r13", "Accumulator 13", 0, GPR },
|
||||
{ "r14", "Accumulator 14", 0, GPR },
|
||||
{ "r15", "Accumulator 15", 0, GPR },
|
||||
{ "k0", "Supervisor accumulator 0", 0, SYS },
|
||||
{ "k1", "Supervisor accumulator 1", 0, SYS },
|
||||
{ "k2", "Supervisor accumulator 2", 0, SYS },
|
||||
{ "k3", "Supervisor accumulator 3", 0, SYS },
|
||||
{ "k4", "Supervisor accumulator 4", 0, SYS },
|
||||
{ "k5", "Supervisor accumulator 5", 0, SYS },
|
||||
{ "k6", "Supervisor accumulator 6", 0, SYS },
|
||||
{ "k7", "Supervisor accumulator 7", 0, SYS },
|
||||
{ "cr0", "Control register 0", 0, CTL },
|
||||
{ "cr1", "Control register 1", 0, CTL },
|
||||
{ "cr2", "Control register 2", 0, CTL },
|
||||
{ "cr3", "Control register 3", 0, CTL },
|
||||
{ "cr4", "Control register 4", 0, CTL },
|
||||
{ "cr5", "Control register 5", 0, CTL },
|
||||
{ "cr6", "Control register 6", 0, CTL },
|
||||
{ "cr7", "Control register 7", 0, CTL },
|
||||
{ "rip", "Instruction pointer", 0, RES },
|
||||
{ "flg", "Flags register", 0, RES },
|
||||
|
||||
{ "rip", "Instruction pointer", "Special; Volatile", 0, RES },
|
||||
{ "flg", "Flags register", "Special; Volatile", 0, RES },
|
||||
|
||||
{ "rbp", "Stack base", "Special; Non-volatile", 0, GPR },
|
||||
{ "rsp", "Stack pointer", "Special; Non-volatile", 0, GPR },
|
||||
|
||||
{ "rax", "Accumulator 0", "Volatile", 0, GPR },
|
||||
{ "rbx", "Accumulator 1", "Volatile", 0, GPR },
|
||||
{ "rcx", "Accumulator 2", "Volatile", 0, GPR },
|
||||
{ "rdx", "Accumulator 3", "Volatile", 0, GPR },
|
||||
{ "rsx", "Accumulator 4", "Volatile", 0, GPR },
|
||||
{ "rbi", "Accumulator 5", "Volatile", 0, GPR },
|
||||
{ "rdi", "Accumulator 6", "Volatile", 0, GPR },
|
||||
{ "rsi", "Accumulator 7", "Volatile", 0, GPR },
|
||||
|
||||
{ "nx0", "Accumulator 8", "Non-volatile", 0, GPR },
|
||||
{ "nx1", "Accumulator 9", "Non-volatile", 0, GPR },
|
||||
{ "nx2", "Accumulator 10", "Non-volatile", 0, GPR },
|
||||
{ "nx3", "Accumulator 11", "Non-volatile", 0, GPR },
|
||||
{ "nx4", "Accumulator 12", "Non-volatile", 0, GPR },
|
||||
{ "nx5", "Accumulator 13", "Non-volatile", 0, GPR },
|
||||
{ "nx6", "Accumulator 14", "Non-volatile", 0, GPR },
|
||||
{ "nx7", "Accumulator 15", "Non-volatile", 0, GPR },
|
||||
|
||||
{ "ax0", "Argument 0", "Volatile", 0, GPR },
|
||||
{ "ax1", "Argument 1", "Volatile", 0, GPR },
|
||||
{ "ax2", "Argument 2", "Volatile", 0, GPR },
|
||||
{ "ax3", "Argument 3", "Volatile", 0, GPR },
|
||||
{ "ax4", "Argument 4", "Volatile", 0, GPR },
|
||||
{ "ax5", "Argument 5", "Volatile", 0, GPR },
|
||||
{ "ax6", "Argument 6", "Volatile", 0, GPR },
|
||||
{ "ax7", "Argument 7", "Volatile", 0, GPR },
|
||||
|
||||
// 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
95
pc/regs.h
Normal 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;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user