assembly wip

This commit is contained in:
julianb0 2019-06-12 15:30:35 +02:00
parent d6089b3999
commit b7fa46e540
No known key found for this signature in database
GPG Key ID: DDF8325C95299A62
16 changed files with 550 additions and 290 deletions

View File

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

View File

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

View File

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

View File

@ -3,27 +3,27 @@
#include <in/instrs.h>
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);

View File

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

View File

@ -3,8 +3,6 @@
#include <in/instrs.h>
IMPL_COND(break);
IMPL_START_0(break)
{
log("\nExecuting BREAK INSTR\n");

View File

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

View File

@ -3,10 +3,17 @@
#include <pc/arch.h>
#include <in/cond.h>
#include <in/flags.h>
#include <in/arch_i.h>
#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); \

View File

@ -3,10 +3,6 @@
#include <in/instrs.h>
IMPL_COND(j);
IMPL_COND(jmp);
IMPL_COND(loop);
//
// Jump instructions
//

View File

@ -3,12 +3,11 @@
#include <in/instrs.h>
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;
//--------------------------------------------------------------------------

View File

@ -3,18 +3,6 @@
#include <in/instrs.h>
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;

View File

@ -3,12 +3,6 @@
#include <in/instrs.h>
IMPL_COND(push);
IMPL_COND(pop);
IMPL_COND(call);
IMPL_COND(ret);
IMPL_COND(leave);
//
// Stack manipulation instructions
//

View File

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

View File

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

View File

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

95
vm/pc/dump.c Normal file
View File

@ -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 <pc/arch.h>
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");
}