1
0
mirror of https://gitlab.os-k.eu/os-k-team/kvisc.git synced 2023-08-25 14:05:46 +02:00
This commit is contained in:
julianb0 2019-07-01 21:46:36 +02:00
parent b4f36ab137
commit 6f59eebedb
No known key found for this signature in database
GPG Key ID: DDF8325C95299A62
18 changed files with 284 additions and 145 deletions

View File

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

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

View File

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

View File

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

View File

@ -13,4 +13,5 @@ include "FLAGS"
include "INOUT"
include "DEBUG"
include "STRING"
include "KINSTRS"

View File

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

View File

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

View File

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

View File

@ -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
View 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);
//----------------------------------------------------------------------------//

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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