From 6f59eebedb758bb390a53a62e4901e84b0591feb Mon Sep 17 00:00:00 2001 From: julianb0 Date: Mon, 1 Jul 2019 21:46:36 +0200 Subject: [PATCH] vm --- as/k-as.py | 61 ++++++++++++++++++++++++----------- ka/ABI | 6 ++-- ka/usr/cmd/dir.k | 4 +-- vm/in/FLAGS | 16 ---------- vm/in/INSTRS | 1 + vm/in/JUMPS | 4 +-- vm/in/KINSTRS | 34 ++++++++++++++++++++ vm/in/arch_i.py | 53 ++++++++++++++++++++----------- vm/in/flags.c | 14 -------- vm/in/instrs.h | 24 ++++++++++++-- vm/in/kinstrs.c | 40 +++++++++++++++++++++++ vm/pc/DECD | 13 ++++---- vm/pc/decode.c | 83 +++++++++++++++++++++++++++++------------------- vm/pc/decode.h | 24 +++++++------- vm/pc/dump.c | 15 ++++++--- vm/pc/exec.c | 27 ++++++++++++---- vm/pc/regs.c | 6 ++-- vm/pc/regs.h | 4 +-- 18 files changed, 284 insertions(+), 145 deletions(-) create mode 100644 vm/in/KINSTRS create mode 100644 vm/in/kinstrs.c diff --git a/as/k-as.py b/as/k-as.py index 84c839b..9bf7b69 100755 --- a/as/k-as.py +++ b/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]) #------------------------------------------------------------------------------- @@ -418,10 +416,12 @@ def parse_instr(line): fellthrough = False 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)) - instrs.write("{} %%imm16 {}{}".format(instr_name, 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): diff --git a/ka/ABI b/ka/ABI index da196d0..315448f 100644 --- a/ka/ABI +++ b/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 #------------------------------------------------------------------------------# diff --git a/ka/usr/cmd/dir.k b/ka/usr/cmd/dir.k index 5ca8c22..414eca4 100644 --- a/ka/usr/cmd/dir.k +++ b/ka/usr/cmd/dir.k @@ -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 diff --git a/vm/in/FLAGS b/vm/in/FLAGS index 290e262..d956331 100644 --- a/vm/in/FLAGS +++ b/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 - diff --git a/vm/in/INSTRS b/vm/in/INSTRS index 0975260..4cd75ca 100644 --- a/vm/in/INSTRS +++ b/vm/in/INSTRS @@ -13,4 +13,5 @@ include "FLAGS" include "INOUT" include "DEBUG" include "STRING" +include "KINSTRS" diff --git a/vm/in/JUMPS b/vm/in/JUMPS index cb0f43c..8d0711a 100644 --- a/vm/in/JUMPS +++ b/vm/in/JUMPS @@ -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 diff --git a/vm/in/KINSTRS b/vm/in/KINSTRS new file mode 100644 index 0000000..22c84a3 --- /dev/null +++ b/vm/in/KINSTRS @@ -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 + diff --git a/vm/in/arch_i.py b/vm/in/arch_i.py index 0551f9c..5888a4d 100644 --- a/vm/in/arch_i.py +++ b/vm/in/arch_i.py @@ -17,11 +17,12 @@ 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()) - fp.write('\n') + for c3 in p3: + fp.write("{} {} {} {}".format(i, c1, c2, c3).strip()) + fp.write('\n') def parse_1(fi, fp): global count @@ -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) - - p1 = tok[1].strip() - p2 = tok[2].strip() + if len(tok) == 3: + p1 = tok[1] + p2 = tok[2] + doprnt(fp, i, p1, p2, ' ') + continue - doprnt(fp, i, p1, p2) + assert(len(tok) == 4) + p1 = tok[1] + p2 = tok[2] + p3 = tok[3] + + 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") diff --git a/vm/in/flags.c b/vm/in/flags.c index f4412d3..a909f5e 100644 --- a/vm/in/flags.c +++ b/vm/in/flags.c @@ -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; - -//----------------------------------------------------------------------------// - diff --git a/vm/in/instrs.h b/vm/in/instrs.h index 2528458..e72b25d 100644 --- a/vm/in/instrs.h +++ b/vm/in/instrs.h @@ -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; \ } diff --git a/vm/in/kinstrs.c b/vm/in/kinstrs.c new file mode 100644 index 0000000..6897ed0 --- /dev/null +++ b/vm/in/kinstrs.c @@ -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 + +//----------------------------------------------------------------------------// + +#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); + +//----------------------------------------------------------------------------// + diff --git a/vm/pc/DECD b/vm/pc/DECD index c824575..b91b175 100644 --- a/vm/pc/DECD +++ b/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 diff --git a/vm/pc/decode.c b/vm/pc/decode.c index 22ac7ab..89dff9c 100644 --- a/vm/pc/decode.c +++ b/vm/pc/decode.c @@ -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); } diff --git a/vm/pc/decode.h b/vm/pc/decode.h index 043f90e..217310e 100644 --- a/vm/pc/decode.h +++ b/vm/pc/decode.h @@ -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 *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); diff --git a/vm/pc/dump.c b/vm/pc/dump.c index 5893c9b..685ff08 100644 --- a/vm/pc/dump.c +++ b/vm/pc/dump.c @@ -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 (p2) { + trace(", "); + dump_acc(ctx, p2); + } + + if (p3) { + trace(", "); + dump_acc(ctx, p3); } trace("\n"); diff --git a/vm/pc/exec.c b/vm/pc/exec.c index f332f7a..cbf3f03 100644 --- a/vm/pc/exec.c +++ b/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; diff --git a/vm/pc/regs.c b/vm/pc/regs.c index 6f37b58..791428f 100644 --- a/vm/pc/regs.c +++ b/vm/pc/regs.c @@ -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 }, diff --git a/vm/pc/regs.h b/vm/pc/regs.h index 4cb25df..4dd3a15 100644 --- a/vm/pc/regs.h +++ b/vm/pc/regs.h @@ -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)