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
|
@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
|
||||||
|
112
as/k-as.py
112
as/k-as.py
@ -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] == '+')
|
|
||||||
|
|
||||||
if word[2] == '+':
|
reg, off = word.strip().split('+', 1)
|
||||||
# r8, k0, etc
|
reg = reg.strip()
|
||||||
instr_args += "{} {}".format(word[3:], word[:2])
|
off = off.strip()
|
||||||
else:
|
|
||||||
# rax, cr0, etc
|
print(reg)
|
||||||
instr_args += "{} {}".format(word[4:], word[:3])
|
print(off)
|
||||||
|
|
||||||
|
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
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
|
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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
16
pc/Makefile
16
pc/Makefile
@ -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
|
||||||
|
|
||||||
|
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.
|
// 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];
|
||||||
|
|
||||||
|
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)) {
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
30
pc/dump.c
30
pc/dump.c
@ -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)
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 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
|
||||||
|
|
@ -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
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.
|
// 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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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
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++];
|
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;
|
||||||
|
60
pc/mem.c
60
pc/mem.c
@ -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
114
pc/regs.c
@ -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
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…
x
Reference in New Issue
Block a user