mirror of
https://gitlab.os-k.eu/os-k-team/kvisc.git
synced 2023-08-25 14:05:46 +02:00
assembly
This commit is contained in:
parent
b5a9286ce0
commit
8e50810bf7
3
.gitignore
vendored
3
.gitignore
vendored
@ -2,9 +2,8 @@
|
||||
*.out
|
||||
*.bin
|
||||
*.o
|
||||
test*
|
||||
arch_i.h
|
||||
*.dis
|
||||
instrs.lst
|
||||
*.out.*
|
||||
*.out*
|
||||
|
||||
|
3
Makefile
3
Makefile
@ -10,6 +10,7 @@ kpc:
|
||||
kas: kpc as/k-as.py as/regs.lst as/testfile.asm
|
||||
@cp pc/instrs.lst as
|
||||
|
||||
test:
|
||||
test: kas
|
||||
@cd as && ./k-as.py testfile.asm 0x100000 testout.out
|
||||
@pc/k.exe as/testout.out
|
||||
|
||||
|
123
as/k-as.py
123
as/k-as.py
@ -4,6 +4,7 @@
|
||||
# See the LICENSE file in the project root for more information.
|
||||
|
||||
import sys
|
||||
import subprocess
|
||||
from array import array
|
||||
from tempfile import TemporaryFile
|
||||
|
||||
@ -22,14 +23,14 @@ lst_regs = open("regs.lst")
|
||||
lst_instrs = open("instrs.lst")
|
||||
|
||||
fi = open(sys.argv[1])
|
||||
out = open(sys.argv[3], "wb")
|
||||
b_out = open(sys.argv[3], "wb")
|
||||
|
||||
start_addr = int(sys.argv[2], base=0)
|
||||
|
||||
def leave():
|
||||
fi.close()
|
||||
out.close()
|
||||
instrs.close()
|
||||
b_out.close()
|
||||
b_data.close()
|
||||
b_text.close()
|
||||
lst_regs.close()
|
||||
@ -185,6 +186,8 @@ def parse():
|
||||
plabels_text[line[:-1]] = ptext
|
||||
else:
|
||||
print("Bad label name: {}".format(line[:-1]))
|
||||
leave()
|
||||
sys.exit(1)
|
||||
continue
|
||||
|
||||
# Preprocessor, .data, or invalid
|
||||
@ -203,72 +206,125 @@ def is_number(s):
|
||||
|
||||
def parse_instr(line):
|
||||
tok = line.split(' ')
|
||||
instrs.write(tok[0])
|
||||
fellthrough = False
|
||||
instr_name = tok[0]
|
||||
instr_args = ''
|
||||
|
||||
if len(tok) == 1:
|
||||
instrs.write("{}".format(instr_name))
|
||||
return 2 # instruction
|
||||
|
||||
size = 2
|
||||
for word in line.split(' ')[1:]:
|
||||
instrs.write(' ')
|
||||
instr_args += ' '
|
||||
|
||||
pref = None
|
||||
|
||||
# memory length prefixes
|
||||
if len(word) > 1 and word[1] == '[':
|
||||
if word[0] == 'b':
|
||||
pref = "%b"
|
||||
elif word[0] == 'w':
|
||||
pref = "%w"
|
||||
elif word[0] == 'l':
|
||||
pref = "%l"
|
||||
elif word[0] == 'q':
|
||||
pref = "%q"
|
||||
else:
|
||||
print("Bad memory length prefix")
|
||||
leave()
|
||||
sys.exit(1)
|
||||
|
||||
word = word[1:]
|
||||
|
||||
# [reg+off] or [imm64]
|
||||
if word[0] == '[':
|
||||
assert(word[-1] == ']')
|
||||
word = word[1:-1]
|
||||
|
||||
if pref == None:
|
||||
pref = "%q"
|
||||
|
||||
instr_name += "_m"
|
||||
instr_args += "{}".format(pref)
|
||||
|
||||
if '+' in word:
|
||||
# +2 for A_OFF, +2 for offset, +2 for register
|
||||
size += 2 + 2 + 2
|
||||
instrs.write("%off ")
|
||||
instr_args += "off "
|
||||
|
||||
assert(len(word) > 3)
|
||||
assert(word[2] == '+' or word[3] == '+')
|
||||
|
||||
if word[2] == '+':
|
||||
# r8, k0, etc
|
||||
instrs.write("{} {}".format(word[3:], word[:2]))
|
||||
instr_args += "{} {}".format(word[3:], word[:2])
|
||||
else:
|
||||
# rax, cr0, etc
|
||||
instrs.write("{} {}".format(word[4:], word[:3]))
|
||||
instr_args += "{} {}".format(word[4:], word[:3])
|
||||
|
||||
continue
|
||||
|
||||
else:
|
||||
# +2 for A_MEM
|
||||
size += 2
|
||||
instrs.write("%mem ")
|
||||
instr_args += "mem "
|
||||
|
||||
fellthrough = True
|
||||
# FALLTHROUGH
|
||||
|
||||
# for now every immediate is 64-bit
|
||||
if is_number(word):
|
||||
# +2 for A_IMM64, +8 for immediate
|
||||
size += 2 + 8
|
||||
instrs.write("%imm64 ")
|
||||
instrs.write(word)
|
||||
if not fellthrough:
|
||||
instr_name += "_i"
|
||||
instr_args += "%imm64 "
|
||||
instr_args += word
|
||||
fellthrough = False
|
||||
continue
|
||||
|
||||
if word in pregs:
|
||||
size += 2
|
||||
instrs.write(word)
|
||||
if not fellthrough:
|
||||
instr_name += "_r"
|
||||
instr_args += word
|
||||
fellthrough = False
|
||||
continue
|
||||
|
||||
# it's a label (so a 16-bit immediate for now)
|
||||
# it's a label (a 64-bit immediate)
|
||||
# +2 for A_IMM16, +2 for immediate
|
||||
size += 2 + 2
|
||||
instrs.write("%imm16 ")
|
||||
instrs.write(word)
|
||||
size += 2 + 8
|
||||
if not fellthrough:
|
||||
instr_name += "_i"
|
||||
instr_args += "%imm64 "
|
||||
instr_args += word
|
||||
fellthrough = False
|
||||
|
||||
instrs.write("{}{}".format(instr_name, instr_args))
|
||||
return size
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
def gentext():
|
||||
# offset in memory
|
||||
off = start_addr
|
||||
special_syms = {
|
||||
"%bmem": 0x7001,
|
||||
"%wmem": 0x7002,
|
||||
"%lmem": 0x7004,
|
||||
"%qmem": 0x7008,
|
||||
|
||||
"%boff": 0x7701,
|
||||
"%woff": 0x7702,
|
||||
"%loff": 0x7704,
|
||||
"%qoff": 0x7708,
|
||||
|
||||
"%imm16": 0x7772,
|
||||
"%imm32": 0x7774,
|
||||
"%imm64": 0x7778,
|
||||
}
|
||||
|
||||
def gentext():
|
||||
instrs.seek(0)
|
||||
text_start = 0x100000
|
||||
|
||||
for _, line in enumerate(instrs):
|
||||
tok = line.strip().split(' ')
|
||||
@ -285,19 +341,28 @@ def gentext():
|
||||
continue
|
||||
|
||||
if word in plabels_text:
|
||||
addr = plabels_text[word]
|
||||
b_text.write(addr.to_bytes(2, byteorder='little', signed=False))
|
||||
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))
|
||||
continue
|
||||
|
||||
if word in plabels_data:
|
||||
addr = plabels_data[word] + ptext + pdata_pad
|
||||
b_text.write(addr.to_bytes(2, byteorder='little', signed=False))
|
||||
addr = text_start + plabels_data[word] + ptext + pdata_pad
|
||||
b_text.write(addr.to_bytes(8, byteorder='little', signed=False))
|
||||
continue
|
||||
|
||||
if 0:
|
||||
|
||||
if word in special_syms:
|
||||
if word == "%imm16":
|
||||
lastimm = 2
|
||||
elif word == "%imm32":
|
||||
lastimm = 4
|
||||
elif word == "%imm64":
|
||||
lastimm = 8
|
||||
b_text.write(special_syms[word].to_bytes(2, byteorder='little', signed=False))
|
||||
continue
|
||||
|
||||
if is_number(word):
|
||||
b_text.write(int(word, base=0).to_bytes(lastimm, byteorder='little', signed=False))
|
||||
continue
|
||||
|
||||
print("Assembly error, unknown token '{}' in line: {}".format(word, line))
|
||||
@ -306,10 +371,18 @@ def gentext():
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
def genout():
|
||||
b_text.seek(0)
|
||||
b_data.seek(0)
|
||||
b_out.write(b_text.read())
|
||||
b_out.write(b_data.read())
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
parse_lst_instrs()
|
||||
parse_lst_regs()
|
||||
parse()
|
||||
gentext()
|
||||
#genout()
|
||||
genout()
|
||||
leave()
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
inv
|
||||
rax
|
||||
rbx
|
||||
rcx
|
||||
|
13
as/testfile.asm
Normal file
13
as/testfile.asm
Normal file
@ -0,0 +1,13 @@
|
||||
# Test assembly file
|
||||
# Wololo!
|
||||
|
||||
def y 4
|
||||
|
||||
label1:
|
||||
call label2
|
||||
stop
|
||||
|
||||
label2:
|
||||
add rax, 1
|
||||
ret
|
||||
|
@ -1,6 +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.
|
||||
|
||||
stop
|
||||
nop
|
||||
|
||||
#
|
||||
@ -181,5 +182,4 @@ popf
|
||||
|
||||
cli
|
||||
sti
|
||||
stop
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
all: k.exe
|
||||
|
||||
src = instrs.c decd.c main.c regs.c dump.c jumps.c except.c disdec.c
|
||||
src = instrs.c decd.c main.c regs.c dump.c jumps.c except.c disdec.c mem.c
|
||||
|
||||
obj = $(patsubst %.c,%.o,$(src))
|
||||
|
||||
@ -20,5 +20,6 @@ clean:
|
||||
|
||||
k.exe: $(obj) i_arch.h INSTRS instrs.py
|
||||
@gcc -O2 -Wall $(obj) -o k.exe
|
||||
@rm arch_i.h
|
||||
@rm *.o
|
||||
|
||||
|
85
pc/arch.h
85
pc/arch.h
@ -28,6 +28,7 @@ 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,
|
||||
@ -72,12 +73,40 @@ struct reg_t
|
||||
// A_REG is implicit
|
||||
// A_MEM denotes a memory access
|
||||
// A_OFF is A_MEM but a 16-bit offset is expected immediatly next
|
||||
enum { A_REG=0, A_MEM=0x7000, A_OFF, A_IMM16, A_IMM32, A_IMM64 };
|
||||
enum
|
||||
{
|
||||
A_REG = 0,
|
||||
|
||||
A_MEM8 = 0x7001,
|
||||
A_MEM16 = 0x7002,
|
||||
A_MEM32 = 0x7004,
|
||||
A_MEM64 = 0x7008,
|
||||
|
||||
A_OFF8 = 0x7701,
|
||||
A_OFF16 = 0x7702,
|
||||
A_OFF32 = 0x7704,
|
||||
A_OFF64 = 0x7708,
|
||||
|
||||
A_IMM16 = 0x7772,
|
||||
A_IMM32 = 0x7774,
|
||||
A_IMM64 = 0x7778
|
||||
};
|
||||
|
||||
#define A_IS_MEM(x) ((x) >= A_MEM8 && (x) <= A_MEM64)
|
||||
#define A_IS_OFF(x) ((x) >= A_OFF8 && (x) <= A_OFF64)
|
||||
#define A_IS_IMM(x) ((x) >= A_IMM16)
|
||||
|
||||
#define A_IS_8(x) ((x) & 0xF == 1)
|
||||
#define A_IS_16(x) ((x) & 0xF == 2)
|
||||
#define A_IS_32(x) ((x) & 0xF == 3)
|
||||
#define A_IS_64(x) ((x) & 0xF == 4)
|
||||
|
||||
struct acc_t
|
||||
{
|
||||
bool mem; // A_MEM?
|
||||
bool mem;
|
||||
uint len;
|
||||
uint type;
|
||||
|
||||
|
||||
ulong val;
|
||||
short off;
|
||||
};
|
||||
@ -141,49 +170,23 @@ void decode(ctx_t *ctx);
|
||||
#define MEMOFF (1 * 1024 * 1024)
|
||||
#define MEMSIZE (16 * 1024 * 1024) // 16MB
|
||||
|
||||
#define addr2real(p) ((p) - MEMOFF)
|
||||
#define real2addr(p) ((p) + MEMOFF)
|
||||
#define addr2real(p) (((p) - MEMOFF) / 2)
|
||||
#define real2addr(p) (((p) + MEMOFF) / 2)
|
||||
|
||||
// Address of boot firmware stack
|
||||
#define FWSTACK (MEMOFF * 2) // 2MB
|
||||
|
||||
static inline ulong readmem64(ctx_t *ctx, ulong addr)
|
||||
{
|
||||
ulong real = addr2real(addr);
|
||||
ulong readmem8(ctx_t *, ulong addr);
|
||||
ulong readmem16(ctx_t *, ulong addr);
|
||||
ulong readmem32(ctx_t *, ulong addr);
|
||||
ulong readmem64(ctx_t *, ulong addr);
|
||||
ulong readmem(ctx_t *c, ulong addr, uint len);
|
||||
|
||||
if (addr % alignof(ulong) > 0) {
|
||||
_except(ctx, E_ALI, "Non-aligned memory access: 0x%012lX(0x%012lX)", addr, real);
|
||||
}
|
||||
|
||||
if (addr < MEMOFF || real >= MEMSIZE) {
|
||||
_except(ctx, E_ACC, "Invalid MEM access: 0x%012lX(0x%012lX)", addr, real);
|
||||
}
|
||||
|
||||
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++];
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline void writemem64(ctx_t *ctx, ulong val, ulong addr)
|
||||
{
|
||||
ulong real = addr2real(addr);
|
||||
|
||||
if (addr % alignof(ulong) > 0) {
|
||||
_except(ctx, E_ALI, "Non-aligned memory access: 0x%012lX(0x%012lX)", addr, real);
|
||||
}
|
||||
|
||||
if (addr < MEMOFF || real >= MEMSIZE) {
|
||||
_except(ctx, E_ACC, "Invalid MEM access: 0x%012lX(0x%012lX)", addr, real);
|
||||
}
|
||||
|
||||
ctx->mp[real++] = val >> 48;
|
||||
ctx->mp[real++] = (val >> 32) & 0xFFFF;
|
||||
ctx->mp[real++] = (val >> 16) & 0xFFFF;
|
||||
ctx->mp[real++] = val & 0xFFFF;
|
||||
}
|
||||
void writemem8(ctx_t *, ulong val, ulong addr);
|
||||
void writemem16(ctx_t *, ulong val, ulong addr);
|
||||
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"
|
||||
|
||||
|
10
pc/decd.c
10
pc/decd.c
@ -33,14 +33,16 @@ static void scan_param(ctx_t *ctx, acc_t *p)
|
||||
|
||||
c = ctx->get(ctx);
|
||||
|
||||
if (c == A_MEM) {
|
||||
if (A_IS_MEM(c)) {
|
||||
p->mem = 1;
|
||||
p->off = 0;
|
||||
p->len = c & 0xF;
|
||||
c = ctx->get(ctx);
|
||||
}
|
||||
|
||||
else if (c == A_OFF) {
|
||||
else if (A_IS_OFF(c)) {
|
||||
p->mem = 1;
|
||||
p->len = c & 0xF;
|
||||
p->off = (short)ctx->get(ctx);
|
||||
c = ctx->get(ctx);
|
||||
}
|
||||
@ -74,7 +76,7 @@ static void scan_param(ctx_t *ctx, acc_t *p)
|
||||
r = &ctx->r[p->val];
|
||||
|
||||
if (r->flags & (RES | CTL)) {
|
||||
_except(ctx, E_ACC, "Reserved REG");
|
||||
_except(ctx, E_ACC, "Reserved REG: %s", r->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -96,7 +98,7 @@ void disasm(ctx_t *ctx)
|
||||
}
|
||||
|
||||
else if (!ISINSTR(c)) {
|
||||
_except(ctx, E_ILL, "Bad opcode: 0x%4hX", c);
|
||||
_except(ctx, E_ILL, "Bad opcode: 0x%04hX", c);
|
||||
}
|
||||
|
||||
i = &ctx->i[c];
|
||||
|
10
pc/instrs.h
10
pc/instrs.h
@ -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 = readmem64(ctx, v1 + p1->off); \
|
||||
if (p1->mem) v1 = readmem(ctx, v1 + p1->off, p1->len); \
|
||||
|
||||
#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 = readmem64(ctx, v1 + p1->off); \
|
||||
if (p2->mem) v2 = readmem64(ctx, v2 + p2->off); \
|
||||
if (p1->mem) v1 = readmem(ctx, v1 + p1->off, p1->len); \
|
||||
if (p2->mem) v2 = readmem(ctx, v2 + p2->off, p2->len); \
|
||||
|
||||
#define IMPL_START_3(name) \
|
||||
void i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2) \
|
||||
{ \
|
||||
ulong v2 = (p2->type == A_REG ? ctx->r[p2->val].val : p2->val); \
|
||||
if (p2->mem) v2 = readmem64(ctx, v2 + p2->off); \
|
||||
if (p2->mem) v2 = readmem(ctx, v2 + p2->off, p2->len); \
|
||||
|
||||
#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; \
|
||||
writemem64(ctx, v1, addr); \
|
||||
writemem(ctx, v1, addr, p1->len); \
|
||||
} \
|
||||
else ctx->r[p1->val].val = v1; \
|
||||
} \
|
||||
|
59
pc/main.c
59
pc/main.c
@ -3,21 +3,17 @@
|
||||
|
||||
#include "arch.h"
|
||||
|
||||
// Boot firware, loaded at MEMOFF (1MB)
|
||||
ushort fwprog[] = {
|
||||
I_MOV_R_I, RBP, A_IMM32, FWSTACK>>16, FWSTACK&0xFF,
|
||||
I_MOV_R_I, RSP, A_IMM32, FWSTACK>>16, FWSTACK&0xFF,
|
||||
|
||||
I_CALL_I, A_IMM32, (MEMOFF+0x13)>>16, (MEMOFF+0x13)&0xFF,
|
||||
I_ADD_R_I, RAX, A_IMM16, 1,
|
||||
I_STOP,
|
||||
|
||||
I_ADD_R_I, RBX, A_IMM16, 1,
|
||||
I_RET,
|
||||
};
|
||||
#define FWPROGSIZE (1024 * 1024 * 1024)
|
||||
static ssize_t fwsize;
|
||||
static ushort *fwprog;
|
||||
|
||||
ushort bget(ctx_t *ctx)
|
||||
{
|
||||
if (ctx->r[RIP].val % 2) {
|
||||
_except(ctx, E_ALI, "Misaligned RIP register: 0x%016lX",
|
||||
ctx->r[RIP].val);
|
||||
}
|
||||
|
||||
if (addr2real(ctx->r[RIP].val) >= ctx->mz) {
|
||||
_except(ctx, E_ACC, "Executing out of memory: 0x%016lX",
|
||||
ctx->r[RIP].val);
|
||||
@ -25,7 +21,7 @@ ushort bget(ctx_t *ctx)
|
||||
|
||||
ushort c = ctx->mp[addr2real(ctx->r[RIP].val)];
|
||||
|
||||
ctx->r[RIP].val++;
|
||||
ctx->r[RIP].val += 2;
|
||||
|
||||
return c;
|
||||
}
|
||||
@ -34,7 +30,7 @@ ushort dget(ctx_t *ctx)
|
||||
{
|
||||
static int i = 0;
|
||||
|
||||
if (i >= sizeof(fwprog)/2) {
|
||||
if (i >= fwsize) {
|
||||
log("Finished disassembling\n");
|
||||
fclose(ctx->disf);
|
||||
exit(0);
|
||||
@ -50,13 +46,40 @@ extern instr_t arch_i[NINSTRS];
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ctx_t main_ctx;
|
||||
FILE *fwfile;
|
||||
|
||||
main_ctx.r = arch_r;
|
||||
main_ctx.i = arch_i;
|
||||
|
||||
// Execute firmware
|
||||
if (!(argc > 1 && !strcmp(argv[1], "-d"))) {
|
||||
main_ctx.mp = malloc(MEMSIZE);
|
||||
if (argc < 2) {
|
||||
log("Not enough arguments\n");
|
||||
exit(-3);
|
||||
}
|
||||
|
||||
fwprog = malloc(FWPROGSIZE);
|
||||
fwfile = fopen(argv[1], "rb");
|
||||
|
||||
if (!fwprog) {
|
||||
log("Couldn't allocate firmware buffer\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (!fwfile) {
|
||||
log("Couldn't open program file\n");
|
||||
exit(-2);
|
||||
}
|
||||
|
||||
fwsize = fread(fwprog, 1, FWPROGSIZE, fwfile);
|
||||
|
||||
//log("Loaded %lu bytes
|
||||
|
||||
if (fwsize < 2) {
|
||||
log("Error while reading program file\n");
|
||||
exit(-3);
|
||||
}
|
||||
|
||||
if (!(argc > 2 && !strcmp(argv[2], "-d"))) {
|
||||
main_ctx.mp = malloc(MEMSIZE + 16);
|
||||
main_ctx.mz = MEMSIZE;
|
||||
|
||||
main_ctx.get = bget;
|
||||
@ -69,7 +92,7 @@ int main(int argc, char **argv)
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
memcpy(&main_ctx.mp[addr2real(main_ctx.r[RIP].val)], fwprog, sizeof(fwprog));
|
||||
memcpy(&main_ctx.mp[addr2real(main_ctx.r[RIP].val)], fwprog, fwsize);
|
||||
|
||||
while (1) {
|
||||
decode(&main_ctx);
|
||||
|
159
pc/mem.c
Normal file
159
pc/mem.c
Normal file
@ -0,0 +1,159 @@
|
||||
// The OS/K Team licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
#include "arch.h"
|
||||
|
||||
ulong readmem(ctx_t *ctx, ulong addr, uint len)
|
||||
{
|
||||
switch (len) {
|
||||
case 1: return readmem8(ctx, addr); break;
|
||||
case 2: return readmem16(ctx, addr); break;
|
||||
case 4: return readmem32(ctx, addr); break;
|
||||
case 8: return readmem64(ctx, addr); break;
|
||||
default: log("readmem() bad length!\n"); abort();
|
||||
}
|
||||
}
|
||||
|
||||
ulong readmem8(ctx_t *ctx, ulong addr)
|
||||
{
|
||||
ulong real = addr2real(addr);
|
||||
|
||||
if (addr < MEMOFF || real >= MEMSIZE) {
|
||||
_except(ctx, E_ACC, "Invalid MEM access: 0x%012lX(0x%012lX)", addr, real);
|
||||
}
|
||||
|
||||
if (addr % 2) return (ulong)ctx->mp[real] & 0xFF;
|
||||
else return ((ulong)ctx->mp[real] & 0xFF00) >> 8;
|
||||
}
|
||||
|
||||
ulong readmem16(ctx_t *ctx, ulong addr)
|
||||
{
|
||||
ulong real = addr2real(addr);
|
||||
|
||||
if (addr % alignof(ushort) > 0) {
|
||||
_except(ctx, E_ALI, "Non-aligned memory access: 0x%012lX(0x%012lX)", addr, real);
|
||||
}
|
||||
|
||||
if (addr < MEMOFF || real >= MEMSIZE) {
|
||||
_except(ctx, E_ACC, "Invalid MEM access: 0x%012lX(0x%012lX)", addr, real);
|
||||
}
|
||||
|
||||
return (ulong)ctx->mp[real];
|
||||
}
|
||||
|
||||
ulong readmem32(ctx_t *ctx, ulong addr)
|
||||
{
|
||||
ulong real = addr2real(addr);
|
||||
|
||||
if (addr % alignof(uint) > 0) {
|
||||
_except(ctx, E_ALI, "Non-aligned memory access: 0x%012lX(0x%012lX)", addr, real);
|
||||
}
|
||||
|
||||
if (addr < MEMOFF || real >= MEMSIZE) {
|
||||
_except(ctx, E_ACC, "Invalid MEM access: 0x%012lX(0x%012lX)", addr, real);
|
||||
}
|
||||
|
||||
ulong val = (ulong)ctx->mp[real++];
|
||||
val = (val << 16) | (ulong)ctx->mp[real];
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
ulong readmem64(ctx_t *ctx, ulong addr)
|
||||
{
|
||||
ulong real = addr2real(addr);
|
||||
|
||||
if (addr % alignof(ulong) > 0) {
|
||||
_except(ctx, E_ALI, "Non-aligned memory access: 0x%012lX(0x%012lX)", addr, real);
|
||||
}
|
||||
|
||||
if (addr < MEMOFF || real >= MEMSIZE) {
|
||||
_except(ctx, E_ACC, "Invalid MEM access: 0x%012lX(0x%012lX)", addr, real);
|
||||
}
|
||||
|
||||
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];
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void writemem(ctx_t *ctx, ulong val, ulong addr, uint len)
|
||||
{
|
||||
switch (len) {
|
||||
case 1: writemem8(ctx, val, addr); break;
|
||||
case 2: writemem16(ctx, val, addr); break;
|
||||
case 4: writemem32(ctx, val, addr); break;
|
||||
case 8: writemem64(ctx, val, addr); break;
|
||||
default: log("writemem() bad length!\n"); abort();
|
||||
}
|
||||
}
|
||||
|
||||
void writemem8(ctx_t *ctx, ulong val, ulong addr)
|
||||
{
|
||||
ulong real = addr2real(addr);
|
||||
|
||||
if (addr < MEMOFF || real >= MEMSIZE) {
|
||||
_except(ctx, E_ACC, "Invalid MEM access: 0x%012lX(0x%012lX)", addr, real);
|
||||
}
|
||||
|
||||
ushort v = ctx->mp[real];
|
||||
|
||||
if (addr % 2) {
|
||||
ctx->mp[real] = (v & 0xFF00) | (val & 0xFF);
|
||||
}
|
||||
|
||||
else {
|
||||
ctx->mp[real] = (v & 0xFF) | (((val & 0xFF) << 8));
|
||||
}
|
||||
}
|
||||
|
||||
void writemem16(ctx_t *ctx, ulong val, ulong addr)
|
||||
{
|
||||
ulong real = addr2real(addr);
|
||||
|
||||
if (addr % alignof(ushort) > 0) {
|
||||
_except(ctx, E_ALI, "Non-aligned memory access: 0x%012lX(0x%012lX)", addr, real);
|
||||
}
|
||||
|
||||
if (addr < MEMOFF || real >= MEMSIZE) {
|
||||
_except(ctx, E_ACC, "Invalid MEM access: 0x%012lX(0x%012lX)", addr, real);
|
||||
}
|
||||
|
||||
ctx->mp[real] = val & 0xFFFF;
|
||||
}
|
||||
|
||||
void writemem32(ctx_t *ctx, ulong val, ulong addr)
|
||||
{
|
||||
ulong real = addr2real(addr);
|
||||
|
||||
if (addr % alignof(uint) > 0) {
|
||||
_except(ctx, E_ALI, "Non-aligned memory access: 0x%012lX(0x%012lX)", addr, real);
|
||||
}
|
||||
|
||||
if (addr < MEMOFF || real >= MEMSIZE) {
|
||||
_except(ctx, E_ACC, "Invalid MEM access: 0x%012lX(0x%012lX)", addr, real);
|
||||
}
|
||||
|
||||
ctx->mp[real++] = (val >> 16) & 0xFFFF;
|
||||
ctx->mp[real] = val & 0xFFFF;
|
||||
}
|
||||
|
||||
void writemem64(ctx_t *ctx, ulong val, ulong addr)
|
||||
{
|
||||
ulong real = addr2real(addr);
|
||||
|
||||
if (addr % alignof(ulong) > 0) {
|
||||
_except(ctx, E_ALI, "Non-aligned memory access: 0x%012lX(0x%012lX)", addr, real);
|
||||
}
|
||||
|
||||
if (addr < MEMOFF || real >= MEMSIZE) {
|
||||
_except(ctx, E_ACC, "Invalid MEM access: 0x%012lX(0x%012lX)", addr, real);
|
||||
}
|
||||
|
||||
ctx->mp[real++] = val >> 48;
|
||||
ctx->mp[real++] = (val >> 32) & 0xFFFF;
|
||||
ctx->mp[real++] = (val >> 16) & 0xFFFF;
|
||||
ctx->mp[real] = val & 0xFFFF;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user