diff --git a/as/k-as.py b/as/k-as.py index 10d4c8b..882c9ae 100755 --- a/as/k-as.py +++ b/as/k-as.py @@ -303,6 +303,76 @@ def parse_preproc(line): #------------------------------------------------------------------------------- +pconds = { + 'c': 0b00001, + 'o': 0b00010, + 'z': 0b00011, + 'e': 0b00011, + 's': 0b00100, + 'p': 0b00101, + 'a': 0b00110, + 'ae': 0b00111, + 'b': 0b01000, + 'be': 0b01001, + 'g': 0b01010, + 'ge': 0b01011, + 'l': 0b01100, + 'le': 0b01101, + 'cxz': 0b01110, + 'cxnz': 0b11110, +} + +def get_cond_mask(cond, line): + + mask = 0 + + if cond[0] == 'n': + cond = cond[1:] + mask = 0b10000 + + if cond not in pconds: + print("Invalid condition suffix: {}".format(line)) + leave() + sys.exit(1) + + return (mask | pconds[cond]) << 10 + +#------------------------------------------------------------------------------- + +pfts = { + "reg": 0b00001, + "imm64": 0b00010, + + "bimm64": 0b00100, + "brr": 0b00101, + "brri": 0b00110, + "brrii": 0b00111, + + "wimm64": 0b01000, + "wrr": 0b01001, + "wrri": 0b01010, + "wrrii": 0b01011, + + "limm64": 0b01100, + "lrr": 0b01101, + "lrri": 0b01110, + "lrrii": 0b01111, + + "qimm64": 0b10000, + "qrr": 0b10001, + "qrri": 0b10010, + "qrrii": 0b10011, +} + +def get_fts_mask(ft, line): + if ft not in pfts: + print("Invalid operand format ({}): {}".format(ft, line)) + + else: + return pfts[ft] + +#------------------------------------------------------------------------------- + def parse_instr(line): if line == None or len(line) == 0: return 0 @@ -318,7 +388,10 @@ def parse_instr(line): fellthrough = False - size = 2 + size = 4 + + # Word 2 (rep|cond|ft1|ft2) + w2 = 0 if instr == "rep": if params == None: @@ -326,36 +399,46 @@ def parse_instr(line): leave() sys.exit(1) - instrs.write("%rep ") + w2 |= 0x8000 # 16th bit instr, params = params.split(' ', 1) - size += 2 + + if '.' in instr: + w2 |= get_cond_mask(instr.split('.', 1)[1], line) + instr_name = instr.split('.', 1)[0] + + else: + instr_name = instr - instr_name = instr.replace('.', '$', 1) instr_args = '' if params == None or len(params) == 0: - instrs.write("{}".format(instr_name)) - return 2 # instruction + instrs.write("{} ".format(instr_name)) + instrs.write("%%imm16 {}".format(w2)) + + return size tok = params.split(',') + + # FT1 and FT2 + fts = '' + # + # Parse operands, generating fts along the way + # for word in tok: word = word.strip() instr_args += ' ' - pref = None + gotPref = False + if len(fts) != 0: + fts += ' ' # memory length prefixes if len(word) > 2 and '[' in word: - if word[0] == 'b': - pref = "%b" - elif word[0] == 'w': - pref = "%w" - elif word[0] == 'l' or word[0] == 'd': - pref = "%l" - elif word[0] == 'q': - pref = "%q" + if word[0] in 'bwlq': + fts += word[0] + gotPref = True else: print("Bad memory length prefix: {}".format(line)) leave() @@ -364,20 +447,116 @@ def parse_instr(line): word = word[1:].strip() assert(word[0] == '[') - # [reg+off], [reg+regoff+off] or [imm64] + # + # Determine memory format and save it into fts + # if word[0] == '[': assert(word[-1] == ']') word = word[1:-1] - if pref == None: + # + # Make sure we got an access length prefix + # + if not gotPref: print("Missing access length modifier: {}".format(line)) leave() sys.exit(1) instr_name += "_m" - instr_args += "{}".format(pref) + # + # Offsets + # if '+' in word: + + reg1 = "inv" + reg2 = "inv" + imm1 = '1' + imm2 = '0' + + wtok = word.split('+') + + # + # [reg] and [reg*imm16] + # + + if len(wtok) == 1: + if '*' in wtok[0]: + assert(len(wtok[0].split('*')) == 2) + + reg2, imm1 = wtok[0].split('*', 1) + + else: + reg1 = wtok[0] + + # + # [reg+reg], [reg+imm16], [reg*imm16+imm16], [reg+reg*imm16] + # + elif len(wtok) == 2: + # Must be [reg*imm16+imm16] + if '*' in wtok[0]: + assert(len(wtok[0].split('*')) == 2) + assert(is_number(wtok[1].strip())) + + print(wtok) + reg2, imm1 = wtok[0].split('*', 1) + imm2 = wtok[1] + + # Must be [reg+reg*imm16] + elif '*' in wtok[1]: + assert(len(wtok[1].split('*')) == 2) + + reg1 = wtok[0] + reg2, imm1 = wtok[1].split('*', 1) + + elif is_number(wtok[1].strip()): + reg1 = wtok[0] + imm2 = wtok[1] + + # Must be [reg+reg] + else: + reg1 = wtok[0] + reg2 = wtok[1] + + # + # [reg+reg+imm16], [reg+reg*imm16+imm16] + # + else: + assert(len(wtok) == 3) + + reg1 = wtok[0] + imm2 = wtok[2] + + if '*' in wtok[1]: + assert(len(wtok[1].split('*')) == 2) + reg2, imm1 = wtok[1].split('*', 1) + + else: + reg2 = wtok[1] + + # + # Update fts and instr_args + # + + instr_args += "{}:{} ".format(reg2.strip(), reg1.strip()) + size += 2 + + if imm1 == '1': + if imm2 == '0': + fts += 'rr' + else: + fts += 'rri' + size += 2 + instr_args += "%%imm16 {}".format(imm2) + + else: + size += 4 + fts += 'rrii' + instr_args += "%%imm16 {} %%imm16 {}".format(imm1, imm2) + + continue + + """ # +2 for A_OFF, +2 for offset, +2 for regoff, +2 for register size += 2 + 2 + 2 + 2 instr_args += "off " @@ -406,47 +585,60 @@ def parse_instr(line): instr_args += "{} {} {}".format(off, regoff, reg) continue + """ - # [imm64] + # + # [imm64] or [reg] + # else: - # +2 for A_MEM - size += 2 - 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 - if not fellthrough: - instr_name += "_i" - instr_args += "%imm64 " - instr_args += word - fellthrough = False - continue - # preprocessor if word in pdefs: word = pdefs[word] # Fall through + # for now every immediate is 64-bit + if is_number(word): + # +8 for immediate + size += 8 + + if not fellthrough: + instr_name += "_i" + + fts += "imm64" + + instr_args += "%%imm64 " + instr_args += word + + fellthrough = False + continue + # register if word in pregs: size += 2 + if not fellthrough: instr_name += "_r" + fts += "reg" + + else: + fts += "rr" + instr_args += word fellthrough = False continue # it's a label (a 64-bit immediate) - # +2 for A_IMM64, +8 for immediate - size += 2 + 8 + # +8 for immediate + size += 8 + if not fellthrough: instr_name += "_i" - instr_args += "%imm64 " + + fts += "imm64" + instr_args += "%%imm64 " if word[0] == '.': instr_args += plastlabel @@ -454,31 +646,37 @@ def parse_instr(line): instr_args += word fellthrough = False - instrs.write("{}{}".format(instr_name, instr_args)) + # + # Compute FT1 and FT2 + # + if ' ' in fts: + assert(len(fts.split(' ')) == 2) + ft1, ft2 = fts.split(' ') + + w2 |= get_fts_mask(ft1, line) << 5 + w2 |= get_fts_mask(ft2, line) + + else: + assert(len(fts) > 0) + w2 |= get_fts_mask(fts, line) << 5 + + instrs.write("{} %%imm16 {}{}".format(instr_name, w2, instr_args)) return size #------------------------------------------------------------------------------- special_syms = { - "%bmem": 0x7001, - "%wmem": 0x7002, - "%lmem": 0x7004, - "%qmem": 0x7008, - - "%boff": 0x7701, - "%woff": 0x7702, - "%loff": 0x7704, - "%qoff": 0x7708, - - "%imm16": 0x7772, - "%imm32": 0x7774, - "%imm64": 0x7778, - - "%rep": 0x8000 + "%%imm16", + "%%imm32", + "%%imm64", + "%%signed" } def gentext(): instrs.seek(0) + print(instrs.read()) + instrs.seek(0) + text_start = 0x100000 data_start = text_start + ptext data_start += (8 - data_start % 8) @@ -487,11 +685,21 @@ def gentext(): tok = line.strip().split(' ') for word in tok: + if len(word) == 0: + continue + if word in pregs: idx = pregs.index(word) b_text.write(idx.to_bytes(2, byteorder='little', signed=False)) continue + if ':' in word: + reg2, reg1 = word.split(':', 1) + idx1 = pregs.index(reg1) + idx2 = pregs.index(reg2) + b_text.write(((idx1 << 8) | idx2).to_bytes(2, byteorder='little', signed=False)) + continue + if word in pinstrs: idx = pinstrs.index(word) b_text.write(idx.to_bytes(2, byteorder='little', signed=False)) @@ -508,20 +716,19 @@ def gentext(): continue if word in special_syms: - if word == "%imm16": + if word == "%%imm16": lastimm = 2 - elif word == "%imm32": + elif word == "%%imm32": lastimm = 4 - elif word == "%imm64": + elif word == "%%imm64": lastimm = 8 - if word[2:] == "off" and word[0] == '%': + elif word == "%%signed": lastimm = 2 isSigned = True else: isSigned = False - b_text.write(special_syms[word].to_bytes(2, byteorder='little', signed=isSigned)) continue if is_number(word): diff --git a/ka/str/strcmp.k b/ka/str/strcmp.k index 2314748..142feec 100644 --- a/ka/str/strcmp.k +++ b/ka/str/strcmp.k @@ -33,7 +33,7 @@ strcmp: strncmp: mov rcx, ax2 -.1: +.0: cmp b[ax0], b[ax1] jmp.nz .1 @@ -42,7 +42,7 @@ strncmp: inc ax0 inc ax1 - loop strcmp + loop .0 .1: mov rax, b[ax0] diff --git a/vm/in/INSTRS b/vm/in/INSTRS index 28b2b9b..bc3a0f6 100644 --- a/vm/in/INSTRS +++ b/vm/in/INSTRS @@ -28,7 +28,7 @@ stop # # Preserves all flags # -!not rm +not rm # # Bitwise OR operation @@ -38,7 +38,8 @@ stop # Clears OF and CF # Sets ZF and SF according to the result # -!or rm rim +or rm rim +orf rm rim # # Bitwise AND operation @@ -48,7 +49,8 @@ stop # Clears OF and CF # Sets ZF and SF according to the result # -!and rm rim +and rm rim +andf rm rim # # Bitwise XOR operation @@ -58,11 +60,14 @@ stop # Clears OF and CF # Sets ZF and SF according to the result # -!xor rm rim +xor rm rim +xorf rm rim # To document -!shl rm rim -!shr rm rim +shl rm rim +shr rm rim +shlf rm rim +shrf rm rim #---------------------------------------------------------------------------# # Arithmetic instructions # @@ -82,7 +87,8 @@ stop # Treats $1 and $2 as signed values # Sets ZF and SF according to the result # -!sgn rm rim +sgn rm rim +sgnf rm rim # # Arithmetical NEG operation @@ -93,7 +99,8 @@ stop # Sets OF if $1 == $LONG_MIN; clears it otherwise # Sets ZF and SF according to the result # -!neg rm +neg rm +negf rm # # Arithmetical INC operation @@ -104,7 +111,8 @@ stop # Sets OF if $1 == $LONG_MAX, clears it otherwise # Sets ZF and SF according to the result # -!inc rm +inc rm +incf rm # # Arithmetical DEC operation @@ -115,7 +123,8 @@ stop # Sets OF if $1 == $LONG_MIN, clears it otherwise # Sets ZF and SF according to the result # -!dec rm +dec rm +decf rm # # Arithmetical ADD operation @@ -126,7 +135,8 @@ stop # Sets OF is signed integer overflow occur, clears it otherwise # Sets ZF and SF according to the result # -!add rm rim +add rm rim +addf rm rim # # Arithmetical SUB operation @@ -137,7 +147,8 @@ stop # Sets OF is signed integer overflow occur, clears it otherwise # Sets ZF and SF according to the result # -!sub rm rim +sub rm rim +subf rm rim # # Arithmetical unsigned MUL operation @@ -147,7 +158,8 @@ stop # Sets CF and OF if HI($1 * $2) > 0, clears them otherwise # Preserves ZF and SF # -!mul rm rim +mul rm rim +mulf rm rim # # Arithmetical unsigned DIV operation @@ -156,7 +168,7 @@ stop # # Preserves all flags # -!div rm rim +div rm rim # # Arithmetical unsigned MOD operation @@ -165,7 +177,7 @@ stop # # Preserves all flags # -!mod rm rim +mod rm rim # # Arithmetical unsigned 128-bit MUL operation @@ -177,6 +189,7 @@ stop # Preserves ZF and SF # mul2 rim +mul2f rim # # Arithmetical unsigned combined DIV and MOD operations @@ -222,8 +235,8 @@ cmp rim rim # # RIP = CR1 + $1 # -!j ri -!jmp ri +j ri +jmp ri # # RCX-dependent jump (LOOP) instruction @@ -233,7 +246,7 @@ cmp rim rim # RIP = CR1 + $1 # FI # -!loop ri +loop ri #---------------------------------------------------------------------------# # Movement instructions # @@ -251,14 +264,14 @@ cmp rim rim # # Preserves all flags # -!lea rm m +lea rm m # # Movement (MOV) instruction # # $1 = $2 # -!mov rm rim +mov rm rim # # Exchange (XCHG) instruction @@ -267,7 +280,7 @@ cmp rim rim # $1 = $2 # $2 = $_ # -!xchg rm rim +xchg rm rim # # Compare-and-exchange (CMPXCHG) instruction @@ -305,7 +318,7 @@ cmpxchg rm rim # #STA if RSP MOD 8 > 0 # #STU if RSP > RBP # -!push rim +push rim # # POP value from stack @@ -318,7 +331,7 @@ cmpxchg rm rim # #STA if RSP MOD 8 > 0 # #STU if RSP >= RBP # -!pop rm +pop rm # # Unconditional jump with possible return (CALL) @@ -329,7 +342,7 @@ cmpxchg rm rim # Throws: # See PUSH and JMP # -!call rim +call rim # # Return to caller (RET) @@ -339,7 +352,7 @@ cmpxchg rm rim # Throws: # See POP # -!ret +ret # # Make new stack frame (ENTER) @@ -358,7 +371,7 @@ enter # RBP = *RSP # RSP = RSP + 8 # -!leave +leave #---------------------------------------------------------------------------# # Supervisor only instructions # @@ -460,7 +473,7 @@ prn rim # (cause register dump on standard error) # (wait for user input before proceeeding) # -!break +break # # Step-by-step execution (STEP) diff --git a/vm/in/arith.c b/vm/in/arith.c index 655dcfc..f190ea5 100644 --- a/vm/in/arith.c +++ b/vm/in/arith.c @@ -3,27 +3,27 @@ #include -IMPL_COND(sgn); -IMPL_COND(neg); -IMPL_COND(inc); -IMPL_COND(dec); -IMPL_COND(add); -IMPL_COND(sub); -IMPL_COND(mul); -IMPL_COND(div); -IMPL_COND(mod); -IMPL_COND(mul2); -IMPL_COND(div2); - //-------------------------------------------------------------------------- IMPL_START_2(sgn) { v1 = (long)v2 < 0 ? (ulong)-1L : 1; } +IMPL_OUT; + +IMPL_START_2(sgnf) +{ + v1 = (long)v2 < 0 ? (ulong)-1L : 1; +} IMPL_OUT_ZSF; IMPL_START_1(neg) +{ + v1 = ~v1 + 1; +} +IMPL_OUT; + +IMPL_START_1(negf) { if (v1 == 0) flg |= CF; @@ -41,6 +41,12 @@ IMPL_OUT_ZSF; //-------------------------------------------------------------------------- IMPL_START_1(inc) +{ + v1++; +} +IMPL_OUT; + +IMPL_START_1(incf) { if (v1 == LONG_MAX) flg |= OF; else flg &= ~OF; @@ -50,6 +56,12 @@ IMPL_START_1(inc) IMPL_OUT_ZSF; IMPL_START_1(dec) +{ + v1--; +} +IMPL_OUT; + +IMPL_START_1(decf) { if (v1 == LONG_MIN) flg |= OF; else flg &= ~OF; @@ -61,6 +73,12 @@ IMPL_OUT_ZSF; //-------------------------------------------------------------------------- IMPL_START_2(add) +{ + v1 += v2; +} +IMPL_OUT; + +IMPL_START_2(addf) { if (v1 + v2 < v1) flg |= OF; else flg &= ~OF; @@ -75,6 +93,12 @@ IMPL_START_2(add) IMPL_OUT_ZSF; IMPL_START_2(sub) +{ + v1 -= v2; +} +IMPL_OUT; + +IMPL_START_2(subf) { if (v1 < v2) flg |= CF; else flg &= ~CF; @@ -89,7 +113,7 @@ IMPL_START_2(sub) IMPL_OUT_ZSF; // -// i_sub but discards result +// i_subf but discards result // IMPL_START_2(cmp) { @@ -132,6 +156,13 @@ static void multiply(ulong u, ulong v, ulong *hi, ulong *lo) } IMPL_START_2(mul) +{ + ulong hi; + multiply(v1, v2, &hi, &v1); +} +IMPL_OUT; + +IMPL_START_2(mulf) { ulong hi; @@ -149,7 +180,14 @@ IMPL_START_2(mul) } IMPL_OUT; + IMPL_START_1(mul2) +{ + multiply(rax, v1, &rdx, &rax); +} +IMPL_END; + +IMPL_START_1(mul2f) { multiply(rax, v1, &rdx, &rax); diff --git a/vm/in/cond.h b/vm/in/cond.h deleted file mode 100644 index 431f105..0000000 --- a/vm/in/cond.h +++ /dev/null @@ -1,50 +0,0 @@ -// The OS/K Team licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -/* -#define _IMPL_IF_COND(name, suf, cond) \ -IMPL_START_0(name##$##suf) \ -{ \ - if (cond) { \ - i_##name(ctx, p1, p2); \ - } \ -} \ -IMPL_END \ - -#define IMPL_COND(name) \ - \ - _IMPL_IF_COND(name, cxz, rcx == 0); \ - _IMPL_IF_COND(name, cxnz, rcx != 0); \ - \ - _IMPL_IF_COND(name, c, flg&CF); \ - _IMPL_IF_COND(name, o, flg&OF); \ - \ - _IMPL_IF_COND(name, nc, !(flg&CF)); \ - _IMPL_IF_COND(name, no, !(flg&OF)); \ - \ - _IMPL_IF_COND(name, z, flg&ZF); \ - _IMPL_IF_COND(name, s, flg&SF); \ - _IMPL_IF_COND(name, p, flg&PF); \ - \ - _IMPL_IF_COND(name, nz, !(flg&ZF)); \ - _IMPL_IF_COND(name, ns, !(flg&SF)); \ - _IMPL_IF_COND(name, np, !(flg&PF)); \ - \ - _IMPL_IF_COND(name, e, flg&ZF); \ - _IMPL_IF_COND(name, eq, flg&ZF); \ - _IMPL_IF_COND(name, ne, !(flg&ZF)); \ - \ - _IMPL_IF_COND(name, b, flg&CF); \ - _IMPL_IF_COND(name, be, flg&ZF || flg&CF); \ - \ - _IMPL_IF_COND(name, a, !(flg&CF || flg&ZF)); \ - _IMPL_IF_COND(name, ae, !(flg&CF)); \ - \ - _IMPL_IF_COND(name, l, !!(flg&SF) != !!(flg&OF)); \ - _IMPL_IF_COND(name, le, flg&ZF || (!!(flg&SF) != !!(flg&OF))); \ - \ - _IMPL_IF_COND(name, g, !(flg&ZF) && (!!(flg&SF) == !!(flg&OF))); \ - _IMPL_IF_COND(name, ge, !!(flg&SF) == !!(flg&OF)); \ -*/ - -#define IMPL_COND(name) diff --git a/vm/in/debug.c b/vm/in/debug.c index 231c138..d1c322c 100644 --- a/vm/in/debug.c +++ b/vm/in/debug.c @@ -3,8 +3,6 @@ #include -IMPL_COND(break); - IMPL_START_0(break) { log("\nExecuting BREAK INSTR\n"); diff --git a/vm/in/flags.h b/vm/in/flags.h index 667bfc0..ecbe3e2 100644 --- a/vm/in/flags.h +++ b/vm/in/flags.h @@ -16,7 +16,7 @@ SET_ZF(v); \ SET_SF(v) -#define _SET_ZSPF(v) \ +#define SET_ZSPF(v) \ SET_ZF(v); \ SET_SF(v); \ SET_PF(v) diff --git a/vm/in/instrs.h b/vm/in/instrs.h index 8b36803..12da00e 100644 --- a/vm/in/instrs.h +++ b/vm/in/instrs.h @@ -3,10 +3,17 @@ #include -#include #include #include +#define GETV(v, p) \ + ulong v; \ + assert(p); \ + if (ACC_FMT_IS_MEM(p->type)) \ + v = readmem(ctx, p->addr, p->mlen); \ + else v = p->val + + #define IMPL_START_0(name) \ bool i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, ulong *ret) \ { @@ -14,13 +21,13 @@ bool i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, ulong *ret) \ #define IMPL_START_1(name) \ bool i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, ulong *ret) \ { \ - ulong v1 = p1->val; + GETV(v1, p1); #define IMPL_START_2(name) \ bool i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, ulong *ret) \ { \ - ulong v1 = p1->val; \ - ulong v2 = p2->val; + GETV(v1, p1); \ + GETV(v2, p2); #define IMPL_OUT_ZSF \ SET_ZSF(v1); \ diff --git a/vm/in/jumps.c b/vm/in/jumps.c index faca2a1..1b67971 100644 --- a/vm/in/jumps.c +++ b/vm/in/jumps.c @@ -3,10 +3,6 @@ #include -IMPL_COND(j); -IMPL_COND(jmp); -IMPL_COND(loop); - // // Jump instructions // diff --git a/vm/in/logic.c b/vm/in/logic.c index 7d1d809..6d9eead 100644 --- a/vm/in/logic.c +++ b/vm/in/logic.c @@ -3,12 +3,11 @@ #include -IMPL_COND(not); -IMPL_COND(and); -IMPL_COND(or); -IMPL_COND(xor); -IMPL_COND(shl); -IMPL_COND(shr); +IMPL_START_1(not) +{ + v1 = ~v1; +} +IMPL_OUT; //-------------------------------------------------------------------------- @@ -21,15 +20,28 @@ IMPL_START_2(test) IMPL_END; IMPL_START_2(and) +{ + v1 &= v2; +} +IMPL_OUT; + +IMPL_START_2(andf) { flg &= ~OF; flg &= ~CF; v1 &= v2; - } IMPL_OUT_ZSF; +//-------------------------------------------------------------------------- + IMPL_START_2(or) +{ + v1 |= v2; +} +IMPL_OUT; + +IMPL_START_2(orf) { flg &= ~OF; flg &= ~CF; @@ -38,6 +50,12 @@ IMPL_START_2(or) IMPL_OUT_ZSF; IMPL_START_2(xor) +{ + v1 ^= v2; +} +IMPL_OUT; + +IMPL_START_2(xorf) { flg &= ~OF; flg &= ~CF; @@ -45,21 +63,31 @@ IMPL_START_2(xor) } IMPL_OUT_ZSF; +//-------------------------------------------------------------------------- + IMPL_START_2(shl) { v1 <<= v2; } +IMPL_OUT; + +IMPL_START_2(shlf) +{ + v1 <<= v2; +} IMPL_OUT_ZSF; IMPL_START_2(shr) { v1 >>= v2; } -IMPL_OUT_ZSF; - -IMPL_START_1(not) -{ - v1 = ~v1; -} IMPL_OUT; +IMPL_START_2(shrf) +{ + v1 >>= v2; +} +IMPL_OUT_ZSF; + +//-------------------------------------------------------------------------- + diff --git a/vm/in/mov.c b/vm/in/mov.c index f681dd3..382bc8f 100644 --- a/vm/in/mov.c +++ b/vm/in/mov.c @@ -3,18 +3,6 @@ #include -IMPL_COND(lea); -IMPL_COND(mov); -IMPL_COND(xchg); -IMPL_COND(cmpxchg); - -/* -IMPL_COND(xchgb); -IMPL_COND(xchgw); -IMPL_COND(xchgl); -IMPL_COND(xchgt); -*/ - // // Movement instructions // @@ -53,11 +41,6 @@ IMPL_START_2(movt) } IMPL_OUT; -IMPL_COND(movb); -IMPL_COND(movw); -IMPL_COND(movl); -IMPL_COND(movt); - IMPL_START_2(xchg) { ulong t = v1; diff --git a/vm/in/stack.c b/vm/in/stack.c index d4af40a..007515c 100644 --- a/vm/in/stack.c +++ b/vm/in/stack.c @@ -3,12 +3,6 @@ #include -IMPL_COND(push); -IMPL_COND(pop); -IMPL_COND(call); -IMPL_COND(ret); -IMPL_COND(leave); - // // Stack manipulation instructions // diff --git a/vm/pc/DECD b/vm/pc/DECD index f276771..c824575 100644 --- a/vm/pc/DECD +++ b/vm/pc/DECD @@ -36,9 +36,9 @@ Values for COND: Highest (6th) bit of COND indicates negation Fx values: -0000 (none) -0001 reg -0010 imm64 +00000 (none) +00001 reg +00010 imm64 xxx00 [imm64] xxx01 [reg+reg] code(reg)|code(reg) diff --git a/vm/pc/decd.c b/vm/pc/decd.c index 738f82b..a5c000c 100644 --- a/vm/pc/decd.c +++ b/vm/pc/decd.c @@ -22,7 +22,8 @@ static void check_param_type(ctx_t *ctx, uint prm, uchar fmt) if (!ok) _except(ctx, E_ILL, - "FT1 or FT2 not matching INSTR's expected parameter types"); + "FT1 or FT2 not matching INSTR's expected parameter types: " + "fmt=0x%x prm=0x%x", fmt, prm); } void decode(ctx_t *ctx) @@ -66,7 +67,7 @@ void decode(ctx_t *ctx) in = &ctx->i[w1]; - if (!nomore) + if (nomore) goto skip_w2; // @@ -147,7 +148,7 @@ static void checkreg(ctx_t *ctx, uint reg, bool inv_is_ok) } if (ctx->r[reg].flags & (RES | CTL)) - _except(ctx, E_ACC, "Reserved REG: %u", reg); + //_except(ctx, E_ACC, "Reserved REG: %u", reg); if (ctx->r[reg].flags & SYS) if (cr0 & UF) @@ -159,7 +160,7 @@ static void checkreg(ctx_t *ctx, uint reg, bool inv_is_ok) // void extract_param(ctx_t *ctx, acc_t *p, uchar fmt) { - uint mlen, mfmt, reg1, reg2, imm1 = 0, imm2 = 0; + uint mlen, mfmt; ushort temp; p->type = fmt; @@ -170,6 +171,8 @@ void extract_param(ctx_t *ctx, acc_t *p, uchar fmt) checkreg(ctx, p->reg, 0); p->val = R(p->reg); + + return; } else if (fmt == A_IMM64) @@ -178,6 +181,8 @@ void extract_param(ctx_t *ctx, acc_t *p, uchar fmt) p->val |= (ulong)ctx->get(ctx) << 16; p->val |= (ulong)ctx->get(ctx) << 32; p->val |= (ulong)ctx->get(ctx) << 48; + + return; } assert(ACC_FMT_IS_MEM(fmt)); @@ -210,41 +215,45 @@ void extract_param(ctx_t *ctx, acc_t *p, uchar fmt) case AM_RRI: case AM_RRII: temp = ctx->get(ctx); - reg1 = temp >> 8; - reg2 = temp & 0xFF; + p->reg1 = temp >> 8; + p->reg2 = temp & 0xFF; - checkreg(ctx, reg1, 0); - checkreg(ctx, reg2, 1); + checkreg(ctx, p->reg1, 1); + checkreg(ctx, p->reg2, 1); - if (fmt == AM_RRI) + if (mfmt == AM_RRI) { - imm1 = 1; - imm2 = ctx->get(ctx); + p->imm1 = 1; + p->imm2 = ctx->get(ctx); } - else if (fmt == AM_RRII) + else if (mfmt == AM_RRII) { - imm1 = ctx->get(ctx); - imm2 = ctx->get(ctx); + p->imm1 = ctx->get(ctx); + p->imm2 = ctx->get(ctx); + } + + else + { + p->imm1 = 1; + p->imm2 = 0; } - p->addr = R(reg1) + R(reg2) * imm1 + (long)imm2; + p->addr = R(p->reg1) + R(p->reg2) * p->imm1 + (long)p->imm2; break; default: _except(ctx, E_ILL, "Invalid MFMT for access: %x", fmt); } - - p->val = readmem(ctx, p->addr, p->mlen); } static bool eval_cond(ctx_t *ctx, uint cond) { - bool neg = cond & (1 << 5); + bool neg = cond & (1 << 4); bool ok; - cond &= ~(1 << 5); + cond &= ~(1 << 4); switch (cond) { @@ -271,81 +280,12 @@ static bool eval_cond(ctx_t *ctx, uint cond) case CD_CXZ: ok = !rcx; break; default: - _except(ctx, E_ILL, "Invalid COND value: %x", cond); + _except(ctx, E_ILL, "Invalid COND value: 0x%x", (neg?cond|(1<<4):cond)); } return neg ? !ok : !!ok; } -char *cond_suffixes[] = -{ - "", - ".c" -}; - -static void dump_acc(ctx_t *ctx, acc_t *p) -{ - uint mfmt; - - if (p->type == A_REG) - log("%s", ctx->r[p->reg].name); - - else if (p->type == A_IMM64) - log("imm64:0x%016lX", p->val); - - else - { - log("%c[", getmempref(p->mlen)); - - mfmt = p->type & AM_MFMT_MASK; - - if (mfmt == AM_IMM64) - log("imm64:"); - - else if (mfmt == AM_RR) - log("rr:"); - - else if (mfmt == AM_RRI) - log("rri:"); - - else if (mfmt == AM_RRII) - log("rrii:"); - - log("0x%016lX]", p->addr); - } -} - -static void dump_instr( - ctx_t *ctx, instr_t *in, - acc_t *p1, acc_t *p2, - bool lock, bool rep, - uint cond, ulong pc) -{ - log("0x%016lX: ", pc); - - if (lock) - log("lock "); - - if (rep) - log("rep "); - - if (cond) - log("cond%u ", cond); - - log("%s ", in->full); - - if (p1) { - dump_acc(ctx, p1); - - if (p2) { - log(", "); - dump_acc(ctx, p2); - } - } - - log("\n"); -} - // // Executes an instruction // diff --git a/vm/pc/decd.h b/vm/pc/decd.h index 5ba1f27..bcd8313 100644 --- a/vm/pc/decd.h +++ b/vm/pc/decd.h @@ -21,7 +21,7 @@ enum BITS_COND = (1 << 14) | (1 << 13) | (1 << 12) | (1 << 11) | (1 << 10), - COND_SHIFT = 8, + COND_SHIFT = 10, Fx_MASK = 0x1F, F1_SHIFT = 5, @@ -65,6 +65,8 @@ struct acc_t ulong addr; uint mlen; + // For instruction dumping ONLY + ushort reg1, reg2, imm1, imm2; }; enum { NOPRM, P_REG, P_IMM, P_MEM=4 }; @@ -93,3 +95,12 @@ void extract_param(ctx_t *ctx, acc_t *p, uchar fmt); +void dump_instr(ctx_t *ctx, + instr_t *in, + acc_t *p1, + acc_t *p2, + bool lock, + bool rep, + uint cond, + ulong pc); + diff --git a/vm/pc/dump.c b/vm/pc/dump.c new file mode 100644 index 0000000..3586bc1 --- /dev/null +++ b/vm/pc/dump.c @@ -0,0 +1,95 @@ +// 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 + +char *cond_suffixes[] = +{ + "", + ".c" +}; + +static void dump_acc(ctx_t *ctx, acc_t *p) +{ + uint mfmt; + + if (p->type == A_REG) + log("%s", ctx->r[p->reg].name); + + else if (p->type == A_IMM64) + log("0x%lX", p->val); + + else + { + log("%c[", getmempref(p->mlen)); + + mfmt = p->type & AM_MFMT_MASK; + + if (mfmt == AM_IMM64) + log("0x%lX]", p->addr); + + else if (mfmt == AM_RR) + { + if (p->reg1 && p->reg2) + log("%s+%s]", ctx->r[p->reg1].name, ctx->r[p->reg2].name); + + else log("%s]", ctx->r[p->reg1 ? p->reg1 : p->reg2].name); + } + + else if (mfmt == AM_RRI) + { + if (p->reg1 && p->reg2) + log("%s+%s+%lX]", ctx->r[p->reg1].name, + ctx->r[p->reg2].name, p->imm2); + + else log("%s+%lX]", ctx->r[p->reg1 ? p->reg1 : p->reg2].name, p->imm2); + } + + else if (mfmt == AM_RRII) + { + if (p->reg1) + log("%s+%s*0x%x+0x%x]", + ctx->r[p->reg1].name, + ctx->r[p->reg2].name, + p->imm1, p->imm2); + else + log("%s*0x%x+0x%x]", + ctx->r[p->reg2].name, + p->imm1, p->imm2); + } + } +} + +void dump_instr( + ctx_t *ctx, instr_t *in, + acc_t *p1, acc_t *p2, + bool lock, bool rep, + uint cond, ulong pc) +{ + log("0x%lX: ", pc); + + if (lock) + log("lock "); + + if (rep) + log("rep "); + + if (cond) + log("c%x", cond); + + log("\t"); + + log("%s\t", in->name); + + if (p1) { + dump_acc(ctx, p1); + + if (p2) { + log(", "); + dump_acc(ctx, p2); + } + } + + log("\n"); +} +