lots of stuff

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

View File

@ -8,9 +8,13 @@ kpc:
@cd pc && make --no-print-directory
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

View File

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

Binary file not shown.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,298 +0,0 @@
// The OS/K Team licences this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#include "instrs.h"
#include "arch_i.h"
#define _NEED_ARCH_I
#include "arch_i.h"
IMPL_START_0(nop)
{
}
IMPL_END;
//
// Logical instructions
//
IMPL_START_2(and)
{
v1 &= v2;
}
IMPL_OUT;
IMPL_START_2(or)
{
v1 |= v2;
}
IMPL_OUT;
IMPL_START_2(xor)
{
v1 ^= v2;
}
IMPL_OUT;
IMPL_START_2(shl)
{
v1 <<= v2;
}
IMPL_OUT;
IMPL_START_2(shr)
{
v1 >>= v2;
}
IMPL_OUT;
IMPL_START_1(not)
{
v1 = ~v1;
}
IMPL_OUT;
//
// Unsigned arithmetic instructions
//
IMPL_START_2(add)
{
v1 += v2;
}
IMPL_OUT;
IMPL_START_2(sub)
{
v1 -= v2;
}
IMPL_OUT;
IMPL_START_1(mul)
{
// Adapted from www.codeproject.com/Tips/618570/UInt-Multiplication-Squaring
ulong v2 = v1;
v1 = ctx->r[RAX].val;
ulong u1 = (v1 & 0xffffffff);
ulong u2 = (v2 & 0xffffffff);
ulong t = (u1 * u2);
ulong w3 = (t & 0xffffffff);
ulong k = (t >> 32);
v1 >>= 32;
t = (v1 * u2) + k;
k = (t & 0xffffffff);
ulong w1 = (t >> 32);
v2 >>= 32;
t = (u1 * v2) + k;
k = (t >> 32);
ctx->r[RDX].val = (v1 * v2) + w1 + k;
ctx->r[RAX].val = (t << 32) + w3;
}
IMPL_END;
IMPL_START_1(div)
{
ctx->r[RDX].val = ctx->r[RAX].val % v1;
ctx->r[RAX].val = ctx->r[RAX].val / v1;
}
IMPL_END;
IMPL_START_1(inc)
{
v1++;
}
IMPL_OUT;
IMPL_START_1(dec)
{
v1--;
}
IMPL_OUT;
//
// Comparison instructions
//
IMPL_START_2(cmp)
{
if (v1 == v2) {
ctx->r[FLG].val |= ZF;
ctx->r[FLG].val &= ~CF;
}
else if (v1 < v2) {
ctx->r[FLG].val &= ~ZF;
ctx->r[FLG].val |= CF;
}
else {
ctx->r[FLG].val &= ~ZF;
ctx->r[FLG].val &= ~CF;
}
}
IMPL_END;
IMPL_START_2(test)
{
ulong v = v1 & v2;
if (v == 0) ctx->r[FLG].val |= ZF;
else ctx->r[FLG].val &= ~ZF;
}
IMPL_END;
//
// Jump instructions
//
//
// Movement instructions
//
IMPL_START_2(mov)
{
v1 = v2;
}
IMPL_OUT;
IMPL_START_2(xchg)
{
ulong t = v1;
v1 = v2;
v2 = t;
}
IMPL_OUT;
IMPL_START_1(lea)
{
assert(p2->mem);
v1 = (p2->type == A_REG ? ctx->r[p2->val].val : p2->val) + p2->off;
}
IMPL_OUT;
//
// Stack manipulation instructions
//
IMPL_START_1(push)
{
if (ctx->r[RSP].val % 8 > 0 || ctx->r[RBP].val % 8 > 0) {
_except(ctx, E_STK, "Misaligned stack REGS");
}
if (ctx->r[RSP].val > ctx->r[RBP].val) {
_except(ctx, E_STK, "RSP above RBP");
}
writemem64(ctx, v1, ctx->r[RSP].val);
ctx->r[RSP].val -= 8;
}
IMPL_END;
IMPL_START_1(pop)
{
if (ctx->r[RSP].val % 8 > 0 || ctx->r[RBP].val % 8 > 0) {
_except(ctx, E_STK, "Misaligned stack REGS");
}
if (ctx->r[RSP].val >= ctx->r[RBP].val) {
_except(ctx, E_STK, "RBP above RSP");
}
ctx->r[RSP].val += 8;
v1 = readmem64(ctx, ctx->r[RSP].val);
}
IMPL_OUT;
IMPL_START_1(call)
{
if (ctx->r[RSP].val % 8 > 0 || ctx->r[RBP].val % 8 > 0) {
_except(ctx, E_STK, "Misaligned stack REGS");
}
if (ctx->r[RSP].val > ctx->r[RBP].val) {
_except(ctx, E_STK, "RSP above RBP");
}
writemem64(ctx, ctx->r[RIP].val, ctx->r[RSP].val);
ctx->r[RSP].val -= 8;
ctx->r[RIP].val = v1;
}
IMPL_END;
IMPL_START_0(ret)
{
if (ctx->r[RSP].val % 8 > 0 || ctx->r[RBP].val % 8 > 0) {
_except(ctx, E_STK, "Misaligned stack REGS");
}
if (ctx->r[RSP].val >= ctx->r[RBP].val) {
_except(ctx, E_STK, "RBP above RSP");
}
ctx->r[RSP].val += 8;
ctx->r[RIP].val = readmem64(ctx, ctx->r[RSP].val);
}
IMPL_END;
IMPL_START_0(pushf)
{
if (ctx->r[RSP].val % 8 > 0 || ctx->r[RBP].val % 8 > 0) {
_except(ctx, E_STK, "Misaligned stack REGS");
}
if (ctx->r[RSP].val > ctx->r[RBP].val) {
_except(ctx, E_STK, "RSP above RBP");
}
writemem64(ctx, ctx->r[FLG].val, ctx->r[RSP].val);
ctx->r[RSP].val -= 8;
}
IMPL_END;
IMPL_START_0(popf)
{
if (ctx->r[RSP].val % 8 > 0 || ctx->r[RBP].val % 8 > 0) {
_except(ctx, E_STK, "Misaligned stack REGS");
}
if (ctx->r[RSP].val >= ctx->r[RBP].val) {
_except(ctx, E_STK, "RBP above RSP");
}
CHK_SUPERV(); // XXX
ctx->r[RSP].val += 8;
ctx->r[FLG].val = readmem64(ctx, ctx->r[RSP].val);
}
IMPL_END;
//
// Supervisor only instructions
//
IMPL_START_0(cli)
{
CHK_SUPERV();
ctx->r[FLG].val &= ~IF;
}
IMPL_END;
IMPL_START_0(sti)
{
CHK_SUPERV();
ctx->r[FLG].val |= IF;
}
IMPL_END;
IMPL_START_0(stop)
{
_except(ctx, E_SHT, "STOP INSTR");
}
IMPL_END;

View File

@ -157,14 +157,19 @@ xchg m m
lea r m
lea 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

View File

@ -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
View File

@ -0,0 +1,67 @@
// The OS/K Team licences this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#include "instrs.h"
#include "arch_i.h"
//
// Unsigned arithmetic instructions
//
IMPL_START_2(add)
{
v1 += v2;
}
IMPL_OUT;
IMPL_START_2(sub)
{
v1 -= v2;
}
IMPL_OUT;
IMPL_START_1(mul)
{
// Adapted from www.codeproject.com/Tips/618570/UInt-Multiplication-Squaring
ulong v2 = v1;
v1 = ctx->r[RAX].val;
ulong u1 = (v1 & 0xffffffff);
ulong u2 = (v2 & 0xffffffff);
ulong t = (u1 * u2);
ulong w3 = (t & 0xffffffff);
ulong k = (t >> 32);
v1 >>= 32;
t = (v1 * u2) + k;
k = (t & 0xffffffff);
ulong w1 = (t >> 32);
v2 >>= 32;
t = (u1 * v2) + k;
k = (t >> 32);
ctx->r[RDX].val = (v1 * v2) + w1 + k;
ctx->r[RAX].val = (t << 32) + w3;
}
IMPL_END;
IMPL_START_1(div)
{
ctx->r[RDX].val = ctx->r[RAX].val % v1;
ctx->r[RAX].val = ctx->r[RAX].val / v1;
}
IMPL_END;
IMPL_START_1(inc)
{
v1++;
}
IMPL_OUT;
IMPL_START_1(dec)
{
v1--;
}
IMPL_OUT;

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

@ -0,0 +1,70 @@
// The OS/K Team licences this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#include "instrs.h"
#include "arch_i.h"
#define _NEED_ARCH_I
#include "arch_i.h"
IMPL_START_0(nop)
{
}
IMPL_END;
//
// Movement instructions
//
IMPL_START_2(mov)
{
v1 = v2;
}
IMPL_OUT;
IMPL_START_2(xchg)
{
ulong t = v1;
v1 = v2;
v2 = t;
}
IMPL_OUT;
IMPL_START_1(lea)
{
assert(p2->mem);
v1 = (p2->type == A_REG ? ctx->r[p2->val].val : p2->val) + p2->off;
}
IMPL_OUT;
IMPL_START_1(gcs)
{
v1 = ctx->r[CR1].val;
}
IMPL_OUT;
//
// Misc. instructions
//
IMPL_START_1(prn)
{
if (p1->mlen > 1) {
log("prn warning: large access size\n");
}
if (!(v1 >= ' ' && v1 < 128) && v1 != '\t') {
if (v1 == '\n') {
log("prn on newline character\n");
}
else
log("prn on invalid character: %ld\n", v1);
}
else {
log("prn instruction with character: '%c'\n", (char)v1);
}
}
IMPL_END;

View File

@ -1,7 +1,7 @@
// The OS/K Team licences this file to you under the MIT license.
// 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

View File

@ -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
View File

@ -0,0 +1,78 @@
// The OS/K Team licences this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#include "instrs.h"
#include "arch_i.h"
//
// Comparison instructions
//
IMPL_START_2(test)
{
ulong v = v1 & v2;
if (v == 0) ctx->r[FLG].val |= ZF;
else ctx->r[FLG].val &= ~ZF;
}
IMPL_END;
IMPL_START_2(cmp)
{
if (v1 == v2) {
ctx->r[FLG].val |= ZF;
ctx->r[FLG].val &= ~CF;
}
else if (v1 < v2) {
ctx->r[FLG].val &= ~ZF;
ctx->r[FLG].val |= CF;
}
else {
ctx->r[FLG].val &= ~ZF;
ctx->r[FLG].val &= ~CF;
}
}
IMPL_END;
//
// Logical instructions
//
IMPL_START_2(and)
{
v1 &= v2;
}
IMPL_OUT;
IMPL_START_2(or)
{
v1 |= v2;
}
IMPL_OUT;
IMPL_START_2(xor)
{
v1 ^= v2;
}
IMPL_OUT;
IMPL_START_2(shl)
{
v1 <<= v2;
}
IMPL_OUT;
IMPL_START_2(shr)
{
v1 >>= v2;
}
IMPL_OUT;
IMPL_START_1(not)
{
v1 = ~v1;
}
IMPL_OUT;

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

@ -0,0 +1,75 @@
// The OS/K Team licences this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#include "instrs.h"
#include "arch_i.h"
//
// Stack manipulation instructions
//
IMPL_START_1(push)
{
CHK_STACK(<);
PUSH(v1);
}
IMPL_END;
IMPL_START_1(pop)
{
CHK_STACK(<=);
POP(v1);
}
IMPL_OUT;
IMPL_START_1(call)
{
CHK_STACK(<);
PUSH(ctx->r[RIP].val);
JUMP(v1);
}
IMPL_END;
IMPL_START_0(ret)
{
CHK_STACK(<=);
POP(ctx->r[RIP].val);
}
IMPL_END;
IMPL_START_0(enter)
{
CHK_STACK(<);
PUSH(ctx->r[RBP].val);
ctx->r[RBP].val = ctx->r[RSP].val;
}
IMPL_END;
IMPL_START_0(leave)
{
// Do NOT check stack here!
POP(ctx->r[RBP].val);
}
IMPL_END;
IMPL_START_0(pushf)
{
CHK_STACK(<);
writemem64(ctx, ctx->r[FLG].val, ctx->r[RSP].val);
ctx->r[RSP].val -= 8;
}
IMPL_END;
IMPL_START_0(popf)
{
CHK_STACK(<=);
CHK_SUPERV(); // XXX
ctx->r[RSP].val += 8;
ctx->r[FLG].val = readmem64(ctx, ctx->r[RSP].val);
}
IMPL_END;

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

@ -0,0 +1,30 @@
// The OS/K Team licences this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#include "instrs.h"
#include "arch_i.h"
//
// Supervisor only instructions
//
IMPL_START_0(cli)
{
CHK_SUPERV();
ctx->r[FLG].val &= ~IF;
}
IMPL_END;
IMPL_START_0(sti)
{
CHK_SUPERV();
ctx->r[FLG].val |= IF;
}
IMPL_END;
IMPL_START_0(stop)
{
_except(ctx, E_SHT, "STOP INSTR");
}
IMPL_END;

View File

@ -18,7 +18,7 @@ ushort bget(ctx_t *ctx)
_except(ctx, E_ACC, "Executing out of memory: 0x%016lX",
ctx->r[RIP].val);
}
ushort c = ctx->mp[addr2real(ctx->r[RIP].val)];
ctx->r[RIP].val += 2;
@ -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;

View File

@ -16,26 +16,28 @@ 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);
_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) {
_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) {
_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];
@ -43,44 +45,47 @@ 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) {
_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) {
_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++];
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) {
_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) {
_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++];
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,10 +97,11 @@ 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) {
_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];
@ -111,14 +117,15 @@ 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) {
_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) {
_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;
@ -126,34 +133,37 @@ 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) {
_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) {
_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)
{
addr += ctx->r[CR2].val;
ulong real = addr2real(addr);
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) {
_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 >> 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
View File

@ -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
View File

@ -0,0 +1,95 @@
// The OS/K Team licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
enum
{
INV,
RIP,
FLG,
RBP,
RSP,
RAX,
RBX,
RCX,
RDX,
RSX,
RBI,
RDI,
RSI,
NX0,
NX1,
NX2,
NX3,
NX4,
NX5,
NX6,
NX7,
AX0,
AX1,
AX2,
AX3,
AX4,
AX5,
AX6,
AX7,
CR0,
CR1,
CR2,
CR3,
CR4,
CR5,
CR6,
CR7,
SA0,
SA1,
SA2,
SA3,
SA4,
SA5,
SA6,
SA7,
NREGS
};
enum
{
GPR = 1 << 0, // General
CTL = 1 << 1, // Control
SEG = 1 << 2, // Segment
RES = 1 << 8, // Reserved for insternal use
SYS = 1 << 9, // Reserved for supervisor mode
};
// FLG register
enum
{
CF = 1 << 0, // Carry flag
PF = 1 << 1, // Parity flag
AC = 1 << 2, // Auxiliary flag
ZF = 1 << 3, // Zero flag
OV = 1 << 4, // Overflow flag
DF = 1 << 5, // Direction flag
SF = 1 << 6, // Sign flag
UF = 1 << 16, // User-mode flag
IF = 1 << 17, // Interrupts enable flag
};
struct reg_t
{
char *name;
char *desc;
char *conv;
ulong val;
ulong flags;
};