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)
|
||||
|
||||
written = b_data.write(ord(c).to_bytes(1, byteorder='little', signed=False))
|
||||
assert(written == 1)
|
||||
real_len += 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
|
||||
|
||||
pdefs[label + "_len"] = str(real_len)
|
||||
@ -364,7 +362,7 @@ def get_cond_mask(cond, line):
|
||||
leave()
|
||||
sys.exit(1)
|
||||
|
||||
return (mask | pconds[cond]) << 10
|
||||
return (mask | pconds[cond])
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
@ -419,9 +417,11 @@ def parse_instr(line):
|
||||
|
||||
size = 4
|
||||
|
||||
# Word 2 (rep|cond|ft1|ft2)
|
||||
# Word 2 (rep|ft3|ft2|ft1)
|
||||
w2 = 0
|
||||
|
||||
cond = None
|
||||
|
||||
if len(instr) > 2 and '.' in instr:
|
||||
instr, suf = instr.split('.', 1)
|
||||
|
||||
@ -440,20 +440,26 @@ def parse_instr(line):
|
||||
w2 |= 0x8000 # REP
|
||||
|
||||
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_args = ''
|
||||
|
||||
if params == None or len(params) == 0:
|
||||
instrs.write("{} ".format(instr_name))
|
||||
|
||||
if cond != None:
|
||||
size += 2
|
||||
instrs.write("{} ".format(cond))
|
||||
|
||||
instrs.write("%%imm16 {}".format(w2))
|
||||
|
||||
return size
|
||||
|
||||
tok = params.split(',')
|
||||
|
||||
# FT1 and FT2
|
||||
# FTn
|
||||
fts = ''
|
||||
|
||||
#
|
||||
@ -680,29 +686,43 @@ def parse_instr(line):
|
||||
fellthrough = False
|
||||
|
||||
#
|
||||
# Compute FT1 and FT2
|
||||
# Compute FTn
|
||||
#
|
||||
if ' ' in fts:
|
||||
assert(len(fts.split()) == 2)
|
||||
l = len(fts.split())
|
||||
|
||||
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()
|
||||
|
||||
w2 |= get_fts_mask(ft1, line) << 5
|
||||
w2 |= get_fts_mask(ft2, line)
|
||||
w2 |= get_fts_mask(ft2, line) << 5
|
||||
w2 |= get_fts_mask(ft1, line)
|
||||
|
||||
else:
|
||||
assert(len(fts) > 0)
|
||||
w2 |= get_fts_mask(fts, line) << 5
|
||||
assert(l == 1)
|
||||
w2 |= get_fts_mask(fts, line)
|
||||
|
||||
if cond == None:
|
||||
instrs.write("{} %%imm16 {}{}".format(instr_name, w2, instr_args))
|
||||
else:
|
||||
size += 2
|
||||
instrs.write("{} {} %%imm16 {}{}".format(instr_name, cond, w2, instr_args))
|
||||
|
||||
return size
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
special_syms = {
|
||||
"%%cond",
|
||||
"%%imm16",
|
||||
"%%imm32",
|
||||
"%%imm64",
|
||||
"%%signed"
|
||||
"%%signed",
|
||||
}
|
||||
|
||||
def gentext():
|
||||
@ -712,6 +732,8 @@ def gentext():
|
||||
|
||||
instrs.seek(0)
|
||||
|
||||
cond_mask = 0
|
||||
|
||||
for _, line in enumerate(instrs):
|
||||
tok = line.strip().split()
|
||||
|
||||
@ -742,7 +764,8 @@ def gentext():
|
||||
continue
|
||||
|
||||
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))
|
||||
continue
|
||||
|
||||
@ -763,13 +786,13 @@ def gentext():
|
||||
lastimm = 4
|
||||
elif word == "%%imm64":
|
||||
lastimm = 8
|
||||
|
||||
elif word == "%%cond":
|
||||
cond_mask = (1 << 13)
|
||||
elif word == "%%signed":
|
||||
lastimm = 2
|
||||
isSigned = True
|
||||
else:
|
||||
isSigned = False
|
||||
|
||||
continue
|
||||
|
||||
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+0 /
|
||||
|---------------|
|
||||
. (undefined) .
|
||||
. (red zone) .
|
||||
. .
|
||||
. .
|
||||
|
||||
@ -131,9 +131,7 @@ The following registers can only be used by the supervisor:
|
||||
- Debugging registers for the supervisor:
|
||||
dr0-dr7
|
||||
|
||||
The following registers cannot be referenced by machine code at all; they must
|
||||
be manipulated through specific instructions, and manipulating their values
|
||||
allow for controlling the machine in various ways:
|
||||
The following registers cannot be referenced by machine code at all:
|
||||
px0-px1, fc0-fc2, cr0-cr7
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
|
@ -42,8 +42,8 @@ CMD.builtins.dir:
|
||||
j.b .print_file_name
|
||||
|
||||
; calculate where to put extension
|
||||
lea r11, b[r10 - 1]
|
||||
sub r11, .buf
|
||||
ksub r11, r10, .buf
|
||||
dec r11
|
||||
|
||||
.ext_pad:
|
||||
; print at least 11 non-space characters before extension
|
||||
|
16
vm/in/FLAGS
16
vm/in/FLAGS
@ -27,19 +27,3 @@ cmc
|
||||
clc
|
||||
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 "DEBUG"
|
||||
include "STRING"
|
||||
include "KINSTRS"
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
#---------------------------------------------------------------------------#
|
||||
|
||||
#
|
||||
# Absolute jump (JMP) instruction
|
||||
# Jump (JMP) instruction
|
||||
#
|
||||
# RIP = $1
|
||||
#
|
||||
@ -14,7 +14,7 @@ j ri
|
||||
jmp ri
|
||||
|
||||
#
|
||||
# RCX-dependent absolute jump (LOOP) instruction
|
||||
# RCX-dependent jump (LOOP) instruction
|
||||
#
|
||||
# IF (RCX > 0) THEN
|
||||
# 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__"
|
||||
|
||||
def doprnt(fp, i, p1, p2):
|
||||
def doprnt(fp, i, p1, p2, p3):
|
||||
for c1 in p1:
|
||||
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')
|
||||
|
||||
def parse_1(fi, fp):
|
||||
@ -40,28 +41,34 @@ def parse_1(fi, fp):
|
||||
parse_1(fi2, fp)
|
||||
continue
|
||||
|
||||
tok = line.split(' ')
|
||||
tok = line.split()
|
||||
|
||||
if len(tok) == 0:
|
||||
continue
|
||||
|
||||
i = tok[0].strip()
|
||||
i = tok[0]
|
||||
|
||||
if len(tok) == 1:
|
||||
doprnt(fp, i, ' ', ' ')
|
||||
doprnt(fp, i, ' ', ' ', ' ')
|
||||
continue
|
||||
|
||||
if len(tok) == 2:
|
||||
p = tok[1].strip()
|
||||
doprnt(fp, i, p, ' ')
|
||||
p = tok[1]
|
||||
doprnt(fp, i, p, ' ', ' ')
|
||||
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()
|
||||
p2 = tok[2].strip()
|
||||
assert(len(tok) == 4)
|
||||
p1 = tok[1]
|
||||
p2 = tok[2]
|
||||
p3 = tok[3]
|
||||
|
||||
doprnt(fp, i, p1, p2)
|
||||
doprnt(fp, i, p1, p2, p3)
|
||||
|
||||
fi.close()
|
||||
|
||||
@ -84,30 +91,40 @@ def parse_2(fp):
|
||||
name = tok[0]
|
||||
p1 = "NOPRM"
|
||||
p2 = "NOPRM"
|
||||
p3 = "NOPRM"
|
||||
|
||||
elif len(tok) == 2:
|
||||
name = "{}_{}".format(tok[0], tok[1].strip())
|
||||
name = "{}_{}".format(tok[0], tok[1])
|
||||
p1 = getflag(tok[1])
|
||||
p2 = "NOPRM"
|
||||
p3 = "NOPRM"
|
||||
|
||||
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])
|
||||
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:
|
||||
name = "__TOK_ERROR__"
|
||||
p1 = "__TOK_ERROR__"
|
||||
p2 = "__TOK_ERROR__"
|
||||
p3 = "__TOK_ERROR__"
|
||||
|
||||
ls.write("{}{}\n".format(deprecated, name))
|
||||
|
||||
hd.write("#ifdef _NEED_ARCH_I\n")
|
||||
hd.write('{{ "{}{}", "{}{}", {}, {}, i_{} }},\n'\
|
||||
.format(deprecated, tok[0], deprecated, name, p1, p2, tok[0]))
|
||||
hd.write('{{ "{}{}", "{}{}", {}, {}, {}, i_{} }},\n'\
|
||||
.format(deprecated, tok[0], deprecated, name, p1, p2, p3, tok[0]))
|
||||
hd.write("#else\n")
|
||||
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]))
|
||||
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) \
|
||||
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) \
|
||||
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);
|
||||
|
||||
#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(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 \
|
||||
SET_ZSF(v1); \
|
||||
IMPL_OUT
|
||||
@ -60,6 +71,13 @@ bool i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, ulong *r1, ulong *r2) \
|
||||
return 2; \
|
||||
}
|
||||
|
||||
#define IMPL_OUT_3 \
|
||||
*r1 = v1; \
|
||||
*r2 = v2; \
|
||||
*r3 = v3; \
|
||||
return 3; \
|
||||
}
|
||||
|
||||
#define IMPL_END \
|
||||
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
|
||||
xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
|
||||
││└────────────┘ │└───┘└───┘└───┘
|
||||
││ INSTR. │ CND FT1 FT2
|
||||
││ │
|
||||
LM R
|
||||
│││└───────────┘ │└───┘└───┘└───┘
|
||||
│││ INSTR. │ FT3 FT2 FT1
|
||||
│││ │
|
||||
LMC R
|
||||
|
||||
M No more words
|
||||
L LOCK prefix
|
||||
R REP prefix
|
||||
C COND suffix
|
||||
L LOCK suffix
|
||||
R REP suffix
|
||||
FT1 First operand format
|
||||
FT2 Second operand format
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
// 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;
|
||||
|
||||
@ -22,8 +22,8 @@ static void check_param_type(ctx_t *ctx, instr_t *in, uint prm, uchar fmt)
|
||||
|
||||
if (!ok)
|
||||
_except(ctx, E_ILL,
|
||||
"FT1 or FT2 not matching %s's expected parameter types: "
|
||||
"fmt=0x%x prm=0x%x", in->full, fmt, prm);
|
||||
"FT%d not matching %s's expected parameter types: "
|
||||
"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)
|
||||
{
|
||||
char *illmsg;
|
||||
|
||||
instr_t *in;
|
||||
|
||||
acc_t p1 = { 0 };
|
||||
acc_t p2 = { 0 };
|
||||
acc_t p3 = { 0 };
|
||||
|
||||
bool rep = 0;
|
||||
uint cond = 0;
|
||||
bool lock, nomore;
|
||||
|
||||
ushort w1, w2;
|
||||
uchar f1 = 0, f2 = 0;
|
||||
uchar f1 = 0, f2 = 0, f3 = 0;
|
||||
|
||||
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
|
||||
//
|
||||
@ -174,10 +168,15 @@ void decode(ctx_t *ctx)
|
||||
|
||||
// Extract first word flags
|
||||
|
||||
lock = !!(w1 & PREF_LOCK);
|
||||
nomore = !!(w1 & PREF_NOMORE);
|
||||
lock = !!(w1 & SUFF_LOCK);
|
||||
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
|
||||
|
||||
@ -197,12 +196,12 @@ void decode(ctx_t *ctx)
|
||||
w2 = ctx->get(ctx);
|
||||
|
||||
// REP and COND
|
||||
rep = !!(w2 & PREF_REP);
|
||||
cond = (w2 & BITS_COND) >> COND_SHIFT;
|
||||
rep = !!(w2 & SUFF_REP);
|
||||
|
||||
// F1 and F2
|
||||
f1 = (w2 >> F1_SHIFT) & Fx_MASK;
|
||||
f2 = w2 & Fx_MASK;
|
||||
// Fn
|
||||
f3 = (w2 >> F3_SHIFT) & 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 (f1 || f2)
|
||||
if (f1 || f2 || f3)
|
||||
{
|
||||
illmsg = "FT1 and/or FT2 filled for 0-param INSTR";
|
||||
goto ill;
|
||||
_except(ctx, E_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;
|
||||
}
|
||||
|
||||
check_param_type(ctx, in, in->prm1, f1);
|
||||
check_param_type(ctx, in, in->prm1, f1, 1);
|
||||
extract_param(ctx, &p1, f1);
|
||||
|
||||
//
|
||||
@ -230,23 +230,40 @@ void decode(ctx_t *ctx)
|
||||
|
||||
if (in->prm2 == NOPRM)
|
||||
{
|
||||
if (f2)
|
||||
if (f2 || f3)
|
||||
{
|
||||
illmsg = "FT2 filled for 1-param INSTR";
|
||||
goto ill;
|
||||
_except(ctx, E_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;
|
||||
}
|
||||
|
||||
check_param_type(ctx, in, in->prm2, f2);
|
||||
check_param_type(ctx, in, in->prm2, f2, 2);
|
||||
extract_param(ctx, &p2, f2);
|
||||
|
||||
exec_instr(ctx, in, &p1, &p2, lock, rep, cond);
|
||||
return;
|
||||
//
|
||||
// Deal with operand 3
|
||||
//
|
||||
|
||||
ill:
|
||||
_except(ctx, E_ILL, illmsg);
|
||||
if (in->prm3 == NOPRM)
|
||||
{
|
||||
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
|
||||
{
|
||||
PREF_LOCK = (1 << 15),
|
||||
PREF_NOMORE = (1 << 14),
|
||||
|
||||
PREF_REP = (1 << 15),
|
||||
|
||||
BITS_COND = (1 << 14) | (1 << 13) | (1 << 12)
|
||||
| (1 << 11) | (1 << 10),
|
||||
|
||||
COND_SHIFT = 10,
|
||||
SUFF_LOCK = (1 << 15),
|
||||
SUFF_NOMORE = (1 << 14),
|
||||
SUFF_COND = (1 << 13),
|
||||
SUFF_REP = (1 << 15),
|
||||
|
||||
Fx_MASK = 0x1F,
|
||||
F1_SHIFT = 5,
|
||||
F3_SHIFT = 10,
|
||||
F2_SHIFT = 5,
|
||||
};
|
||||
|
||||
enum
|
||||
@ -79,14 +75,17 @@ struct instr_t
|
||||
|
||||
uint prm1;
|
||||
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,
|
||||
instr_t *in,
|
||||
acc_t *p1,
|
||||
acc_t *p2,
|
||||
acc_t *p3,
|
||||
bool lock,
|
||||
bool rep,
|
||||
uint cond);
|
||||
@ -99,6 +98,7 @@ void dump_instr(ctx_t *ctx,
|
||||
instr_t *in,
|
||||
acc_t *p1,
|
||||
acc_t *p2,
|
||||
acc_t *p3,
|
||||
bool lock,
|
||||
bool rep,
|
||||
uint cond);
|
||||
|
@ -23,6 +23,7 @@ void dump_instr(ctx_t *ctx,
|
||||
instr_t *in,
|
||||
acc_t *p1,
|
||||
acc_t *p2,
|
||||
acc_t *p3,
|
||||
bool lock,
|
||||
bool rep,
|
||||
uint cond)
|
||||
@ -62,12 +63,16 @@ void dump_instr(ctx_t *ctx,
|
||||
trace("\t");
|
||||
|
||||
if (p1)
|
||||
{
|
||||
dump_acc(ctx, p1);
|
||||
|
||||
if (p2) {
|
||||
trace(", ");
|
||||
dump_acc(ctx, p2);
|
||||
}
|
||||
|
||||
if (p3) {
|
||||
trace(", ");
|
||||
dump_acc(ctx, p3);
|
||||
}
|
||||
|
||||
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,
|
||||
acc_t *p1,
|
||||
acc_t *p2,
|
||||
acc_t *p3,
|
||||
bool lock,
|
||||
bool rep,
|
||||
uint cond)
|
||||
{
|
||||
bool out;
|
||||
ulong r1 = 0, r2 = 0;
|
||||
ulong r1 = 0, r2 = 0, r3 = 0;
|
||||
|
||||
// Global instruction counter
|
||||
ctx->ninstrs++;
|
||||
@ -75,14 +76,13 @@ void exec_instr(ctx_t *ctx,
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
dump_instr(ctx, in, p1, p2, lock, rep, cond);
|
||||
dump_instr(ctx, in, p1, p2, p3, lock, rep, cond);
|
||||
#endif
|
||||
|
||||
do_rep:
|
||||
|
||||
out = in->func(ctx, p1, p2, &r1, &r2);
|
||||
out = in->func(ctx, p1, p2, p3, &r1, &r2, &r3);
|
||||
|
||||
if (out)
|
||||
{
|
||||
@ -99,7 +99,7 @@ do_rep:
|
||||
}
|
||||
}
|
||||
|
||||
if (out == 2)
|
||||
if (out >= 2)
|
||||
{
|
||||
if (p2->type == A_REG)
|
||||
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)
|
||||
{
|
||||
// RCX remains untouched when condition fails
|
||||
@ -130,7 +145,7 @@ do_rep:
|
||||
|
||||
#ifndef NDEBUG
|
||||
// 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
|
||||
|
||||
goto do_rep;
|
||||
|
@ -6,11 +6,11 @@
|
||||
reg_t arch_r[] =
|
||||
{
|
||||
{ "inv", RES },
|
||||
{ "flg", RES },
|
||||
{ "flg", GPR },
|
||||
{ "rip", GPR },
|
||||
{ "rpc", GPR },
|
||||
{ "px0", CTL },
|
||||
{ "px1", CTL },
|
||||
{ "px0", RES },
|
||||
{ "px1", RES },
|
||||
{ "fc1", RES },
|
||||
{ "fc2", RES },
|
||||
{ "sa0", SYS },
|
||||
|
@ -37,8 +37,6 @@ struct reg_t
|
||||
ulong flags;
|
||||
};
|
||||
|
||||
#define rx0 ctx->ninstrs
|
||||
|
||||
enum
|
||||
{
|
||||
INV, FLG, RIP, RPC, PX0, PX1, FC1, FC2,
|
||||
@ -64,6 +62,8 @@ enum
|
||||
NREGS
|
||||
};
|
||||
|
||||
#define rx0 ctx->ninstrs
|
||||
|
||||
#define inv R(INV)
|
||||
#define rip R(RIP)
|
||||
#define rpc R(RPC)
|
||||
|
Loading…
Reference in New Issue
Block a user