mirror of
https://gitlab.os-k.eu/os-k-team/kvisc.git
synced 2023-08-25 14:05:46 +02:00
vm
This commit is contained in:
parent
b4f36ab137
commit
6f59eebedb
57
as/k-as.py
57
as/k-as.py
@ -308,14 +308,12 @@ def parse_preproc(line):
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
written = b_data.write(ord(c).to_bytes(1, byteorder='little', signed=False))
|
written = b_data.write(ord(c).to_bytes(1, byteorder='little', signed=False))
|
||||||
assert(written == 1)
|
|
||||||
real_len += 1
|
real_len += 1
|
||||||
pdata += 1
|
pdata += 1
|
||||||
|
|
||||||
# align
|
# align
|
||||||
for i in range(8 - len(s) % 8):
|
for i in range(8 - len(s) % 8):
|
||||||
written = b_data.write(int(0).to_bytes(1, byteorder='little', signed=False))
|
written = b_data.write(int(0).to_bytes(1, byteorder='little', signed=False))
|
||||||
assert(written == 1)
|
|
||||||
pdata += 1
|
pdata += 1
|
||||||
|
|
||||||
pdefs[label + "_len"] = str(real_len)
|
pdefs[label + "_len"] = str(real_len)
|
||||||
@ -364,7 +362,7 @@ def get_cond_mask(cond, line):
|
|||||||
leave()
|
leave()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
return (mask | pconds[cond]) << 10
|
return (mask | pconds[cond])
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -419,9 +417,11 @@ def parse_instr(line):
|
|||||||
|
|
||||||
size = 4
|
size = 4
|
||||||
|
|
||||||
# Word 2 (rep|cond|ft1|ft2)
|
# Word 2 (rep|ft3|ft2|ft1)
|
||||||
w2 = 0
|
w2 = 0
|
||||||
|
|
||||||
|
cond = None
|
||||||
|
|
||||||
if len(instr) > 2 and '.' in instr:
|
if len(instr) > 2 and '.' in instr:
|
||||||
instr, suf = instr.split('.', 1)
|
instr, suf = instr.split('.', 1)
|
||||||
|
|
||||||
@ -440,20 +440,26 @@ def parse_instr(line):
|
|||||||
w2 |= 0x8000 # REP
|
w2 |= 0x8000 # REP
|
||||||
|
|
||||||
if len(suf) > 0:
|
if len(suf) > 0:
|
||||||
w2 |= get_cond_mask(suf, line)
|
instrs.write("%%cond ")
|
||||||
|
cond = "%%imm16 {}".format(get_cond_mask(suf, line))
|
||||||
|
|
||||||
instr_name = instr
|
instr_name = instr
|
||||||
instr_args = ''
|
instr_args = ''
|
||||||
|
|
||||||
if params == None or len(params) == 0:
|
if params == None or len(params) == 0:
|
||||||
instrs.write("{} ".format(instr_name))
|
instrs.write("{} ".format(instr_name))
|
||||||
|
|
||||||
|
if cond != None:
|
||||||
|
size += 2
|
||||||
|
instrs.write("{} ".format(cond))
|
||||||
|
|
||||||
instrs.write("%%imm16 {}".format(w2))
|
instrs.write("%%imm16 {}".format(w2))
|
||||||
|
|
||||||
return size
|
return size
|
||||||
|
|
||||||
tok = params.split(',')
|
tok = params.split(',')
|
||||||
|
|
||||||
# FT1 and FT2
|
# FTn
|
||||||
fts = ''
|
fts = ''
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -680,29 +686,43 @@ def parse_instr(line):
|
|||||||
fellthrough = False
|
fellthrough = False
|
||||||
|
|
||||||
#
|
#
|
||||||
# Compute FT1 and FT2
|
# Compute FTn
|
||||||
#
|
#
|
||||||
if ' ' in fts:
|
l = len(fts.split())
|
||||||
assert(len(fts.split()) == 2)
|
|
||||||
|
if l == 3:
|
||||||
|
ft1, ft2, ft3 = fts.split()
|
||||||
|
|
||||||
|
w2 |= get_fts_mask(ft3, line) << 10
|
||||||
|
w2 |= get_fts_mask(ft2, line) << 5
|
||||||
|
w2 |= get_fts_mask(ft1, line)
|
||||||
|
|
||||||
|
elif l == 2:
|
||||||
ft1, ft2 = fts.split()
|
ft1, ft2 = fts.split()
|
||||||
|
|
||||||
w2 |= get_fts_mask(ft1, line) << 5
|
w2 |= get_fts_mask(ft2, line) << 5
|
||||||
w2 |= get_fts_mask(ft2, line)
|
w2 |= get_fts_mask(ft1, line)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
assert(len(fts) > 0)
|
assert(l == 1)
|
||||||
w2 |= get_fts_mask(fts, line) << 5
|
w2 |= get_fts_mask(fts, line)
|
||||||
|
|
||||||
|
if cond == None:
|
||||||
instrs.write("{} %%imm16 {}{}".format(instr_name, w2, instr_args))
|
instrs.write("{} %%imm16 {}{}".format(instr_name, w2, instr_args))
|
||||||
|
else:
|
||||||
|
size += 2
|
||||||
|
instrs.write("{} {} %%imm16 {}{}".format(instr_name, cond, w2, instr_args))
|
||||||
|
|
||||||
return size
|
return size
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
special_syms = {
|
special_syms = {
|
||||||
|
"%%cond",
|
||||||
"%%imm16",
|
"%%imm16",
|
||||||
"%%imm32",
|
"%%imm32",
|
||||||
"%%imm64",
|
"%%imm64",
|
||||||
"%%signed"
|
"%%signed",
|
||||||
}
|
}
|
||||||
|
|
||||||
def gentext():
|
def gentext():
|
||||||
@ -712,6 +732,8 @@ def gentext():
|
|||||||
|
|
||||||
instrs.seek(0)
|
instrs.seek(0)
|
||||||
|
|
||||||
|
cond_mask = 0
|
||||||
|
|
||||||
for _, line in enumerate(instrs):
|
for _, line in enumerate(instrs):
|
||||||
tok = line.strip().split()
|
tok = line.strip().split()
|
||||||
|
|
||||||
@ -742,7 +764,8 @@ def gentext():
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
if word in pinstrs:
|
if word in pinstrs:
|
||||||
idx = pinstrs.index(word)
|
idx = pinstrs.index(word) | cond_mask
|
||||||
|
cond_mask = 0
|
||||||
b_text.write(idx.to_bytes(2, byteorder='little', signed=False))
|
b_text.write(idx.to_bytes(2, byteorder='little', signed=False))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -763,13 +786,13 @@ def gentext():
|
|||||||
lastimm = 4
|
lastimm = 4
|
||||||
elif word == "%%imm64":
|
elif word == "%%imm64":
|
||||||
lastimm = 8
|
lastimm = 8
|
||||||
|
elif word == "%%cond":
|
||||||
|
cond_mask = (1 << 13)
|
||||||
elif word == "%%signed":
|
elif word == "%%signed":
|
||||||
lastimm = 2
|
lastimm = 2
|
||||||
isSigned = True
|
isSigned = True
|
||||||
else:
|
else:
|
||||||
isSigned = False
|
isSigned = False
|
||||||
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if is_number(word):
|
if is_number(word):
|
||||||
|
6
ka/ABI
6
ka/ABI
@ -46,7 +46,7 @@ Between the 'enter' and the 'leave', the stack looks like this:
|
|||||||
| . | rsp+8 |
|
| . | rsp+8 |
|
||||||
| . | rsp+0 /
|
| . | rsp+0 /
|
||||||
|---------------|
|
|---------------|
|
||||||
. (undefined) .
|
. (red zone) .
|
||||||
. .
|
. .
|
||||||
. .
|
. .
|
||||||
|
|
||||||
@ -131,9 +131,7 @@ The following registers can only be used by the supervisor:
|
|||||||
- Debugging registers for the supervisor:
|
- Debugging registers for the supervisor:
|
||||||
dr0-dr7
|
dr0-dr7
|
||||||
|
|
||||||
The following registers cannot be referenced by machine code at all; they must
|
The following registers cannot be referenced by machine code at all:
|
||||||
be manipulated through specific instructions, and manipulating their values
|
|
||||||
allow for controlling the machine in various ways:
|
|
||||||
px0-px1, fc0-fc2, cr0-cr7
|
px0-px1, fc0-fc2, cr0-cr7
|
||||||
|
|
||||||
#------------------------------------------------------------------------------#
|
#------------------------------------------------------------------------------#
|
||||||
|
@ -42,8 +42,8 @@ CMD.builtins.dir:
|
|||||||
j.b .print_file_name
|
j.b .print_file_name
|
||||||
|
|
||||||
; calculate where to put extension
|
; calculate where to put extension
|
||||||
lea r11, b[r10 - 1]
|
ksub r11, r10, .buf
|
||||||
sub r11, .buf
|
dec r11
|
||||||
|
|
||||||
.ext_pad:
|
.ext_pad:
|
||||||
; print at least 11 non-space characters before extension
|
; print at least 11 non-space characters before extension
|
||||||
|
16
vm/in/FLAGS
16
vm/in/FLAGS
@ -27,19 +27,3 @@ cmc
|
|||||||
clc
|
clc
|
||||||
stc
|
stc
|
||||||
|
|
||||||
#
|
|
||||||
# Load FLG register (LODF)
|
|
||||||
#
|
|
||||||
# $1 = FLG
|
|
||||||
#
|
|
||||||
lodf rm
|
|
||||||
|
|
||||||
#
|
|
||||||
# Store FLG register - lower byte only (STOFB)
|
|
||||||
#
|
|
||||||
# FLG[7:0] = $1[7:0]
|
|
||||||
#
|
|
||||||
# Note: FLG's lower byte contains CF, OF, ZF, SF, PF and DF
|
|
||||||
#
|
|
||||||
stofb rm
|
|
||||||
|
|
||||||
|
@ -13,4 +13,5 @@ include "FLAGS"
|
|||||||
include "INOUT"
|
include "INOUT"
|
||||||
include "DEBUG"
|
include "DEBUG"
|
||||||
include "STRING"
|
include "STRING"
|
||||||
|
include "KINSTRS"
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#---------------------------------------------------------------------------#
|
#---------------------------------------------------------------------------#
|
||||||
|
|
||||||
#
|
#
|
||||||
# Absolute jump (JMP) instruction
|
# Jump (JMP) instruction
|
||||||
#
|
#
|
||||||
# RIP = $1
|
# RIP = $1
|
||||||
#
|
#
|
||||||
@ -14,7 +14,7 @@ j ri
|
|||||||
jmp ri
|
jmp ri
|
||||||
|
|
||||||
#
|
#
|
||||||
# RCX-dependent absolute jump (LOOP) instruction
|
# RCX-dependent jump (LOOP) instruction
|
||||||
#
|
#
|
||||||
# IF (RCX > 0) THEN
|
# IF (RCX > 0) THEN
|
||||||
# RCX = RCX - 1
|
# RCX = RCX - 1
|
||||||
|
34
vm/in/KINSTRS
Normal file
34
vm/in/KINSTRS
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# The OS/K Team licenses this file to you under the MIT license.
|
||||||
|
# See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------#
|
||||||
|
# 3-operand instructions #
|
||||||
|
#---------------------------------------------------------------------------#
|
||||||
|
|
||||||
|
#
|
||||||
|
# 2-sources logical & arithmetical operations
|
||||||
|
#
|
||||||
|
# Preserves CF and OF
|
||||||
|
# Sets ZF and SF according to the result
|
||||||
|
#
|
||||||
|
kor rm rim rim
|
||||||
|
kand rm rim rim
|
||||||
|
kxor rm rim rim
|
||||||
|
knor rm rim rim
|
||||||
|
korn rm rim rim
|
||||||
|
knand rm rim rim
|
||||||
|
kandn rm rim rim
|
||||||
|
kxnor rm rim rim
|
||||||
|
kxorn rm rim rim
|
||||||
|
kshl rm rim rim
|
||||||
|
kshr rm rim rim
|
||||||
|
kadd rm rim rim
|
||||||
|
kadc rm rim rim
|
||||||
|
kado rm rim rim
|
||||||
|
ksub rm rim rim
|
||||||
|
ksbb rm rim rim
|
||||||
|
ksbo rm rim rim
|
||||||
|
kmul rm rim rim
|
||||||
|
kdiv rm rim rim
|
||||||
|
krem rm rim rim
|
||||||
|
|
@ -17,10 +17,11 @@ def getflag(s):
|
|||||||
|
|
||||||
return "__FLAG_ERROR__"
|
return "__FLAG_ERROR__"
|
||||||
|
|
||||||
def doprnt(fp, i, p1, p2):
|
def doprnt(fp, i, p1, p2, p3):
|
||||||
for c1 in p1:
|
for c1 in p1:
|
||||||
for c2 in p2:
|
for c2 in p2:
|
||||||
fp.write("{} {} {}".format(i, c1, c2).strip())
|
for c3 in p3:
|
||||||
|
fp.write("{} {} {} {}".format(i, c1, c2, c3).strip())
|
||||||
fp.write('\n')
|
fp.write('\n')
|
||||||
|
|
||||||
def parse_1(fi, fp):
|
def parse_1(fi, fp):
|
||||||
@ -40,28 +41,34 @@ def parse_1(fi, fp):
|
|||||||
parse_1(fi2, fp)
|
parse_1(fi2, fp)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
tok = line.split(' ')
|
tok = line.split()
|
||||||
|
|
||||||
if len(tok) == 0:
|
if len(tok) == 0:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
i = tok[0].strip()
|
i = tok[0]
|
||||||
|
|
||||||
if len(tok) == 1:
|
if len(tok) == 1:
|
||||||
doprnt(fp, i, ' ', ' ')
|
doprnt(fp, i, ' ', ' ', ' ')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if len(tok) == 2:
|
if len(tok) == 2:
|
||||||
p = tok[1].strip()
|
p = tok[1]
|
||||||
doprnt(fp, i, p, ' ')
|
doprnt(fp, i, p, ' ', ' ')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
assert(len(tok) == 3)
|
if len(tok) == 3:
|
||||||
|
p1 = tok[1]
|
||||||
|
p2 = tok[2]
|
||||||
|
doprnt(fp, i, p1, p2, ' ')
|
||||||
|
continue
|
||||||
|
|
||||||
p1 = tok[1].strip()
|
assert(len(tok) == 4)
|
||||||
p2 = tok[2].strip()
|
p1 = tok[1]
|
||||||
|
p2 = tok[2]
|
||||||
|
p3 = tok[3]
|
||||||
|
|
||||||
doprnt(fp, i, p1, p2)
|
doprnt(fp, i, p1, p2, p3)
|
||||||
|
|
||||||
fi.close()
|
fi.close()
|
||||||
|
|
||||||
@ -84,30 +91,40 @@ def parse_2(fp):
|
|||||||
name = tok[0]
|
name = tok[0]
|
||||||
p1 = "NOPRM"
|
p1 = "NOPRM"
|
||||||
p2 = "NOPRM"
|
p2 = "NOPRM"
|
||||||
|
p3 = "NOPRM"
|
||||||
|
|
||||||
elif len(tok) == 2:
|
elif len(tok) == 2:
|
||||||
name = "{}_{}".format(tok[0], tok[1].strip())
|
name = "{}_{}".format(tok[0], tok[1])
|
||||||
p1 = getflag(tok[1])
|
p1 = getflag(tok[1])
|
||||||
p2 = "NOPRM"
|
p2 = "NOPRM"
|
||||||
|
p3 = "NOPRM"
|
||||||
|
|
||||||
elif len(tok) == 3:
|
elif len(tok) == 3:
|
||||||
name = "{}_{}_{}".format(tok[0], tok[1], tok[2].strip())
|
name = "{}_{}_{}".format(tok[0], tok[1], tok[2])
|
||||||
p1 = getflag(tok[1])
|
p1 = getflag(tok[1])
|
||||||
p2 = getflag(tok[2])
|
p2 = getflag(tok[2])
|
||||||
|
p3 = "NOPRM"
|
||||||
|
|
||||||
|
elif len(tok) == 4:
|
||||||
|
name = "{}_{}_{}_{}".format(tok[0], tok[1], tok[2], tok[3])
|
||||||
|
p1 = getflag(tok[1])
|
||||||
|
p2 = getflag(tok[2])
|
||||||
|
p3 = getflag(tok[3])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
name = "__TOK_ERROR__"
|
name = "__TOK_ERROR__"
|
||||||
p1 = "__TOK_ERROR__"
|
p1 = "__TOK_ERROR__"
|
||||||
p2 = "__TOK_ERROR__"
|
p2 = "__TOK_ERROR__"
|
||||||
|
p3 = "__TOK_ERROR__"
|
||||||
|
|
||||||
ls.write("{}{}\n".format(deprecated, name))
|
ls.write("{}{}\n".format(deprecated, name))
|
||||||
|
|
||||||
hd.write("#ifdef _NEED_ARCH_I\n")
|
hd.write("#ifdef _NEED_ARCH_I\n")
|
||||||
hd.write('{{ "{}{}", "{}{}", {}, {}, i_{} }},\n'\
|
hd.write('{{ "{}{}", "{}{}", {}, {}, {}, i_{} }},\n'\
|
||||||
.format(deprecated, tok[0], deprecated, name, p1, p2, tok[0]))
|
.format(deprecated, tok[0], deprecated, name, p1, p2, p3, tok[0]))
|
||||||
hd.write("#else\n")
|
hd.write("#else\n")
|
||||||
hd.write("#define I_{} {}\n".format(name.upper(), count))
|
hd.write("#define I_{} {}\n".format(name.upper(), count))
|
||||||
hd.write("extern bool i_{}(ctx_t *, acc_t *, acc_t *, ulong *, ulong *);\n"
|
hd.write("extern bool i_{}(ctx_t *, acc_t *, acc_t *, acc_t *, ulong *, ulong *, ulong *);\n"
|
||||||
.format(tok[0]))
|
.format(tok[0]))
|
||||||
hd.write("#endif\n\n")
|
hd.write("#endif\n\n")
|
||||||
|
|
||||||
|
@ -55,17 +55,3 @@ IMPL_END;
|
|||||||
|
|
||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
|
|
||||||
IMPL_START_1(lodf)
|
|
||||||
{
|
|
||||||
v1 = flg;
|
|
||||||
}
|
|
||||||
IMPL_OUT;
|
|
||||||
|
|
||||||
IMPL_START_1(stofb)
|
|
||||||
{
|
|
||||||
flg = (flg & ~0xFF) | (v1 & 0xFF);
|
|
||||||
}
|
|
||||||
IMPL_END;
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
|
@ -31,20 +31,31 @@
|
|||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
|
|
||||||
#define IMPL_START_0(name) \
|
#define IMPL_START_0(name) \
|
||||||
bool i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, ulong *r1, ulong *r2) \
|
bool i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, acc_t *p3, \
|
||||||
|
ulong *r1, ulong *r2, ulong *r3) \
|
||||||
{
|
{
|
||||||
|
|
||||||
#define IMPL_START_1(name) \
|
#define IMPL_START_1(name) \
|
||||||
bool i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, ulong *r1, ulong *r2) \
|
bool i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, acc_t *p3, \
|
||||||
|
ulong *r1, ulong *r2, ulong *r3) \
|
||||||
{ \
|
{ \
|
||||||
DECV(v1, p1);
|
DECV(v1, p1);
|
||||||
|
|
||||||
#define IMPL_START_2(name) \
|
#define IMPL_START_2(name) \
|
||||||
bool i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, ulong *r1, ulong *r2) \
|
bool i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, acc_t *p3, \
|
||||||
|
ulong *r1, ulong *r2, ulong *r3) \
|
||||||
{ \
|
{ \
|
||||||
DECV(v1, p1); \
|
DECV(v1, p1); \
|
||||||
DECV(v2, p2);
|
DECV(v2, p2);
|
||||||
|
|
||||||
|
#define IMPL_START_3(name) \
|
||||||
|
bool i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, acc_t *p3, \
|
||||||
|
ulong *r1, ulong *r2, ulong *r3) \
|
||||||
|
{ \
|
||||||
|
DECV(v1, p1); \
|
||||||
|
DECV(v2, p2); \
|
||||||
|
DECV(v3, p3);
|
||||||
|
|
||||||
#define IMPL_OUT_ZSF \
|
#define IMPL_OUT_ZSF \
|
||||||
SET_ZSF(v1); \
|
SET_ZSF(v1); \
|
||||||
IMPL_OUT
|
IMPL_OUT
|
||||||
@ -60,6 +71,13 @@ bool i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, ulong *r1, ulong *r2) \
|
|||||||
return 2; \
|
return 2; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define IMPL_OUT_3 \
|
||||||
|
*r1 = v1; \
|
||||||
|
*r2 = v2; \
|
||||||
|
*r3 = v3; \
|
||||||
|
return 3; \
|
||||||
|
}
|
||||||
|
|
||||||
#define IMPL_END \
|
#define IMPL_END \
|
||||||
return 0; \
|
return 0; \
|
||||||
}
|
}
|
||||||
|
40
vm/in/kinstrs.c
Normal file
40
vm/in/kinstrs.c
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// 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 <in/instrs.h>
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
#define K_IMPL_ALU(name, expr) \
|
||||||
|
IMPL_START_3(k##name) \
|
||||||
|
{ \
|
||||||
|
v1 = expr; \
|
||||||
|
} \
|
||||||
|
IMPL_OUT_ZSF
|
||||||
|
|
||||||
|
K_IMPL_ALU(or, v2 | v3);
|
||||||
|
K_IMPL_ALU(and, v2 & v3);
|
||||||
|
K_IMPL_ALU(xor, v2 ^ v3);
|
||||||
|
|
||||||
|
K_IMPL_ALU(nor, ~(v2 | v3));
|
||||||
|
K_IMPL_ALU(orn, ~v2 | v3);
|
||||||
|
K_IMPL_ALU(nand, ~(v2 & v3));
|
||||||
|
K_IMPL_ALU(andn, ~v2 & v3);
|
||||||
|
K_IMPL_ALU(xnor, ~(v2 ^ v3));
|
||||||
|
K_IMPL_ALU(xorn, ~v2 ^ v3);
|
||||||
|
|
||||||
|
K_IMPL_ALU(shl, v2 << v3);
|
||||||
|
K_IMPL_ALU(shr, v2 >> v3);
|
||||||
|
|
||||||
|
K_IMPL_ALU(add, v2 + v3);
|
||||||
|
K_IMPL_ALU(adc, v2 + v3 + !!(flg&CF));
|
||||||
|
K_IMPL_ALU(ado, v2 + v3 + !!(flg&OF));
|
||||||
|
K_IMPL_ALU(sub, v2 - v3);
|
||||||
|
K_IMPL_ALU(sbb, v2 - v3 - !!(flg&CF));
|
||||||
|
K_IMPL_ALU(sbo, v2 - v3 - !!(flg&OF));
|
||||||
|
K_IMPL_ALU(mul, v2 * v3);
|
||||||
|
K_IMPL_ALU(div, v2 / v3);
|
||||||
|
K_IMPL_ALU(rem, v2 % v3);
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------//
|
||||||
|
|
13
vm/pc/DECD
13
vm/pc/DECD
@ -5,14 +5,15 @@ Instruction encoding:
|
|||||||
|
|
||||||
15 0 15 0
|
15 0 15 0
|
||||||
xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
|
xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
|
||||||
││└────────────┘ │└───┘└───┘└───┘
|
│││└───────────┘ │└───┘└───┘└───┘
|
||||||
││ INSTR. │ CND FT1 FT2
|
│││ INSTR. │ FT3 FT2 FT1
|
||||||
││ │
|
│││ │
|
||||||
LM R
|
LMC R
|
||||||
|
|
||||||
M No more words
|
M No more words
|
||||||
L LOCK prefix
|
C COND suffix
|
||||||
R REP prefix
|
L LOCK suffix
|
||||||
|
R REP suffix
|
||||||
FT1 First operand format
|
FT1 First operand format
|
||||||
FT2 Second operand format
|
FT2 Second operand format
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
// Read the "DECD" file before reading this code
|
// Read the "DECD" file before reading this code
|
||||||
//
|
//
|
||||||
|
|
||||||
static void check_param_type(ctx_t *ctx, instr_t *in, uint prm, uchar fmt)
|
static void check_param_type(ctx_t *ctx, instr_t *in, uint prm, uchar fmt, int which)
|
||||||
{
|
{
|
||||||
bool ok;
|
bool ok;
|
||||||
|
|
||||||
@ -22,8 +22,8 @@ static void check_param_type(ctx_t *ctx, instr_t *in, uint prm, uchar fmt)
|
|||||||
|
|
||||||
if (!ok)
|
if (!ok)
|
||||||
_except(ctx, E_ILL,
|
_except(ctx, E_ILL,
|
||||||
"FT1 or FT2 not matching %s's expected parameter types: "
|
"FT%d not matching %s's expected parameter types: "
|
||||||
"fmt=0x%x prm=0x%x", in->full, fmt, prm);
|
"fmt=0x%x prm=0x%x", which, in->full, fmt, prm);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -146,27 +146,21 @@ void extract_param(ctx_t *ctx, acc_t *p, uchar fmt)
|
|||||||
|
|
||||||
void decode(ctx_t *ctx)
|
void decode(ctx_t *ctx)
|
||||||
{
|
{
|
||||||
char *illmsg;
|
|
||||||
|
|
||||||
instr_t *in;
|
instr_t *in;
|
||||||
|
|
||||||
acc_t p1 = { 0 };
|
acc_t p1 = { 0 };
|
||||||
acc_t p2 = { 0 };
|
acc_t p2 = { 0 };
|
||||||
|
acc_t p3 = { 0 };
|
||||||
|
|
||||||
bool rep = 0;
|
bool rep = 0;
|
||||||
uint cond = 0;
|
uint cond = 0;
|
||||||
bool lock, nomore;
|
bool lock, nomore;
|
||||||
|
|
||||||
ushort w1, w2;
|
ushort w1, w2;
|
||||||
uchar f1 = 0, f2 = 0;
|
uchar f1 = 0, f2 = 0, f3 = 0;
|
||||||
|
|
||||||
rpc = rip;
|
rpc = rip;
|
||||||
|
|
||||||
/*
|
|
||||||
sym_t *sym = find_sym_by_addr(pc);
|
|
||||||
if (sym)
|
|
||||||
trace("0x%lX: %s:\n", pc, sym->name);
|
|
||||||
*/
|
|
||||||
//
|
//
|
||||||
// Process the first word of the instruction
|
// Process the first word of the instruction
|
||||||
//
|
//
|
||||||
@ -174,10 +168,15 @@ void decode(ctx_t *ctx)
|
|||||||
|
|
||||||
// Extract first word flags
|
// Extract first word flags
|
||||||
|
|
||||||
lock = !!(w1 & PREF_LOCK);
|
lock = !!(w1 & SUFF_LOCK);
|
||||||
nomore = !!(w1 & PREF_NOMORE);
|
nomore = !!(w1 & SUFF_NOMORE);
|
||||||
|
|
||||||
w1 &= ~(PREF_LOCK|PREF_NOMORE);
|
if (w1 & SUFF_COND)
|
||||||
|
{
|
||||||
|
cond = ctx->get(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
w1 &= ~(SUFF_LOCK|SUFF_NOMORE|SUFF_COND);
|
||||||
|
|
||||||
// Find instruction
|
// Find instruction
|
||||||
|
|
||||||
@ -197,12 +196,12 @@ void decode(ctx_t *ctx)
|
|||||||
w2 = ctx->get(ctx);
|
w2 = ctx->get(ctx);
|
||||||
|
|
||||||
// REP and COND
|
// REP and COND
|
||||||
rep = !!(w2 & PREF_REP);
|
rep = !!(w2 & SUFF_REP);
|
||||||
cond = (w2 & BITS_COND) >> COND_SHIFT;
|
|
||||||
|
|
||||||
// F1 and F2
|
// Fn
|
||||||
f1 = (w2 >> F1_SHIFT) & Fx_MASK;
|
f3 = (w2 >> F3_SHIFT) & Fx_MASK;
|
||||||
f2 = w2 & Fx_MASK;
|
f2 = (w2 >> F2_SHIFT) & Fx_MASK;
|
||||||
|
f1 = w2 & Fx_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -211,17 +210,18 @@ void decode(ctx_t *ctx)
|
|||||||
|
|
||||||
if (in->prm1 == NOPRM)
|
if (in->prm1 == NOPRM)
|
||||||
{
|
{
|
||||||
if (f1 || f2)
|
if (f1 || f2 || f3)
|
||||||
{
|
{
|
||||||
illmsg = "FT1 and/or FT2 filled for 0-param INSTR";
|
_except(ctx, E_ILL,
|
||||||
goto ill;
|
"FTn (%u,%u,%u) filled for 0-param INSTR '%s'",
|
||||||
|
f1, f2, f3, in->full);
|
||||||
}
|
}
|
||||||
|
|
||||||
exec_instr(ctx, in, NULL, NULL, lock, rep, cond);
|
exec_instr(ctx, in, NULL, NULL, NULL, lock, rep, cond);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
check_param_type(ctx, in, in->prm1, f1);
|
check_param_type(ctx, in, in->prm1, f1, 1);
|
||||||
extract_param(ctx, &p1, f1);
|
extract_param(ctx, &p1, f1);
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -230,23 +230,40 @@ void decode(ctx_t *ctx)
|
|||||||
|
|
||||||
if (in->prm2 == NOPRM)
|
if (in->prm2 == NOPRM)
|
||||||
{
|
{
|
||||||
if (f2)
|
if (f2 || f3)
|
||||||
{
|
{
|
||||||
illmsg = "FT2 filled for 1-param INSTR";
|
_except(ctx, E_ILL,
|
||||||
goto ill;
|
"FT3/FT2 (%u,%u,%u) filled for 1-param INSTR '%s'",
|
||||||
|
f1, f2, f3, in->full);
|
||||||
}
|
}
|
||||||
|
|
||||||
exec_instr(ctx, in, &p1, NULL, lock, rep, cond);
|
exec_instr(ctx, in, &p1, NULL, NULL, lock, rep, cond);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
check_param_type(ctx, in, in->prm2, f2);
|
check_param_type(ctx, in, in->prm2, f2, 2);
|
||||||
extract_param(ctx, &p2, f2);
|
extract_param(ctx, &p2, f2);
|
||||||
|
|
||||||
exec_instr(ctx, in, &p1, &p2, lock, rep, cond);
|
//
|
||||||
return;
|
// Deal with operand 3
|
||||||
|
//
|
||||||
|
|
||||||
ill:
|
if (in->prm3 == NOPRM)
|
||||||
_except(ctx, E_ILL, illmsg);
|
{
|
||||||
|
if (f3)
|
||||||
|
{
|
||||||
|
_except(ctx, E_ILL,
|
||||||
|
"FT3 (%u,%u,%u) filled for 2-param INSTR '%s'",
|
||||||
|
f1, f2, f3, in->full);
|
||||||
|
}
|
||||||
|
|
||||||
|
exec_instr(ctx, in, &p1, &p2, NULL, lock, rep, cond);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
check_param_type(ctx, in, in->prm3, f3, 3);
|
||||||
|
extract_param(ctx, &p3, f3);
|
||||||
|
|
||||||
|
exec_instr(ctx, in, &p1, &p2, &p3, lock, rep, cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,18 +13,14 @@ enum
|
|||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PREF_LOCK = (1 << 15),
|
SUFF_LOCK = (1 << 15),
|
||||||
PREF_NOMORE = (1 << 14),
|
SUFF_NOMORE = (1 << 14),
|
||||||
|
SUFF_COND = (1 << 13),
|
||||||
PREF_REP = (1 << 15),
|
SUFF_REP = (1 << 15),
|
||||||
|
|
||||||
BITS_COND = (1 << 14) | (1 << 13) | (1 << 12)
|
|
||||||
| (1 << 11) | (1 << 10),
|
|
||||||
|
|
||||||
COND_SHIFT = 10,
|
|
||||||
|
|
||||||
Fx_MASK = 0x1F,
|
Fx_MASK = 0x1F,
|
||||||
F1_SHIFT = 5,
|
F3_SHIFT = 10,
|
||||||
|
F2_SHIFT = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
@ -79,14 +75,17 @@ struct instr_t
|
|||||||
|
|
||||||
uint prm1;
|
uint prm1;
|
||||||
uint prm2;
|
uint prm2;
|
||||||
|
uint prm3;
|
||||||
|
|
||||||
bool (*func)(ctx_t *, acc_t *, acc_t *, ulong *, ulong *);
|
bool (*func)(ctx_t *, acc_t *, acc_t *, acc_t *,
|
||||||
|
ulong *, ulong *, ulong *);
|
||||||
};
|
};
|
||||||
|
|
||||||
void exec_instr(ctx_t *ctx,
|
void exec_instr(ctx_t *ctx,
|
||||||
instr_t *in,
|
instr_t *in,
|
||||||
acc_t *p1,
|
acc_t *p1,
|
||||||
acc_t *p2,
|
acc_t *p2,
|
||||||
|
acc_t *p3,
|
||||||
bool lock,
|
bool lock,
|
||||||
bool rep,
|
bool rep,
|
||||||
uint cond);
|
uint cond);
|
||||||
@ -99,6 +98,7 @@ void dump_instr(ctx_t *ctx,
|
|||||||
instr_t *in,
|
instr_t *in,
|
||||||
acc_t *p1,
|
acc_t *p1,
|
||||||
acc_t *p2,
|
acc_t *p2,
|
||||||
|
acc_t *p3,
|
||||||
bool lock,
|
bool lock,
|
||||||
bool rep,
|
bool rep,
|
||||||
uint cond);
|
uint cond);
|
||||||
|
@ -23,6 +23,7 @@ void dump_instr(ctx_t *ctx,
|
|||||||
instr_t *in,
|
instr_t *in,
|
||||||
acc_t *p1,
|
acc_t *p1,
|
||||||
acc_t *p2,
|
acc_t *p2,
|
||||||
|
acc_t *p3,
|
||||||
bool lock,
|
bool lock,
|
||||||
bool rep,
|
bool rep,
|
||||||
uint cond)
|
uint cond)
|
||||||
@ -62,12 +63,16 @@ void dump_instr(ctx_t *ctx,
|
|||||||
trace("\t");
|
trace("\t");
|
||||||
|
|
||||||
if (p1)
|
if (p1)
|
||||||
{
|
|
||||||
dump_acc(ctx, p1);
|
dump_acc(ctx, p1);
|
||||||
|
|
||||||
if (p2) {
|
if (p2) {
|
||||||
trace(", ");
|
trace(", ");
|
||||||
dump_acc(ctx, p2);
|
dump_acc(ctx, p2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p3) {
|
||||||
|
trace(", ");
|
||||||
|
dump_acc(ctx, p3);
|
||||||
}
|
}
|
||||||
|
|
||||||
trace("\n");
|
trace("\n");
|
||||||
|
27
vm/pc/exec.c
27
vm/pc/exec.c
@ -48,12 +48,13 @@ void exec_instr(ctx_t *ctx,
|
|||||||
instr_t *in,
|
instr_t *in,
|
||||||
acc_t *p1,
|
acc_t *p1,
|
||||||
acc_t *p2,
|
acc_t *p2,
|
||||||
|
acc_t *p3,
|
||||||
bool lock,
|
bool lock,
|
||||||
bool rep,
|
bool rep,
|
||||||
uint cond)
|
uint cond)
|
||||||
{
|
{
|
||||||
bool out;
|
bool out;
|
||||||
ulong r1 = 0, r2 = 0;
|
ulong r1 = 0, r2 = 0, r3 = 0;
|
||||||
|
|
||||||
// Global instruction counter
|
// Global instruction counter
|
||||||
ctx->ninstrs++;
|
ctx->ninstrs++;
|
||||||
@ -75,14 +76,13 @@ void exec_instr(ctx_t *ctx,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
dump_instr(ctx, in, p1, p2, lock, rep, cond);
|
dump_instr(ctx, in, p1, p2, p3, lock, rep, cond);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
do_rep:
|
do_rep:
|
||||||
|
|
||||||
out = in->func(ctx, p1, p2, &r1, &r2);
|
out = in->func(ctx, p1, p2, p3, &r1, &r2, &r3);
|
||||||
|
|
||||||
if (out)
|
if (out)
|
||||||
{
|
{
|
||||||
@ -99,7 +99,7 @@ do_rep:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (out == 2)
|
if (out >= 2)
|
||||||
{
|
{
|
||||||
if (p2->type == A_REG)
|
if (p2->type == A_REG)
|
||||||
R(p2->reg) = r2;
|
R(p2->reg) = r2;
|
||||||
@ -114,6 +114,21 @@ do_rep:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (out >= 3)
|
||||||
|
{
|
||||||
|
if (p3->type == A_REG)
|
||||||
|
R(p3->reg) = r3;
|
||||||
|
|
||||||
|
else if (p3->type == A_IMM64)
|
||||||
|
_except(ctx, E_ACC, "Trying to output to an IMM64");
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(ACC_IS_MEM(p3));
|
||||||
|
writemem(ctx, r3, p3->addr, p3->mlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (rep)
|
if (rep)
|
||||||
{
|
{
|
||||||
// RCX remains untouched when condition fails
|
// RCX remains untouched when condition fails
|
||||||
@ -130,7 +145,7 @@ do_rep:
|
|||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
// Show that we're REP'ing
|
// Show that we're REP'ing
|
||||||
dump_instr(ctx, in, p1, p2, lock, rep, cond);
|
dump_instr(ctx, in, p1, p2, p3, lock, rep, cond);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
goto do_rep;
|
goto do_rep;
|
||||||
|
@ -6,11 +6,11 @@
|
|||||||
reg_t arch_r[] =
|
reg_t arch_r[] =
|
||||||
{
|
{
|
||||||
{ "inv", RES },
|
{ "inv", RES },
|
||||||
{ "flg", RES },
|
{ "flg", GPR },
|
||||||
{ "rip", GPR },
|
{ "rip", GPR },
|
||||||
{ "rpc", GPR },
|
{ "rpc", GPR },
|
||||||
{ "px0", CTL },
|
{ "px0", RES },
|
||||||
{ "px1", CTL },
|
{ "px1", RES },
|
||||||
{ "fc1", RES },
|
{ "fc1", RES },
|
||||||
{ "fc2", RES },
|
{ "fc2", RES },
|
||||||
{ "sa0", SYS },
|
{ "sa0", SYS },
|
||||||
|
@ -37,8 +37,6 @@ struct reg_t
|
|||||||
ulong flags;
|
ulong flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define rx0 ctx->ninstrs
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
INV, FLG, RIP, RPC, PX0, PX1, FC1, FC2,
|
INV, FLG, RIP, RPC, PX0, PX1, FC1, FC2,
|
||||||
@ -64,6 +62,8 @@ enum
|
|||||||
NREGS
|
NREGS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define rx0 ctx->ninstrs
|
||||||
|
|
||||||
#define inv R(INV)
|
#define inv R(INV)
|
||||||
#define rip R(RIP)
|
#define rip R(RIP)
|
||||||
#define rpc R(RPC)
|
#define rpc R(RPC)
|
||||||
|
Loading…
Reference in New Issue
Block a user