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): def parse_instr(line):
if line == None or len(line) == 0: if line == None or len(line) == 0:
return 0 return 0
@ -318,7 +388,10 @@ def parse_instr(line):
fellthrough = False fellthrough = False
size = 2 size = 4
# Word 2 (rep|cond|ft1|ft2)
w2 = 0
if instr == "rep": if instr == "rep":
if params == None: if params == None:
@ -326,36 +399,46 @@ def parse_instr(line):
leave() leave()
sys.exit(1) sys.exit(1)
instrs.write("%rep ") w2 |= 0x8000 # 16th bit
instr, params = params.split(' ', 1) 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 = '' instr_args = ''
if params == None or len(params) == 0: if params == None or len(params) == 0:
instrs.write("{}".format(instr_name)) instrs.write("{} ".format(instr_name))
return 2 # instruction instrs.write("%%imm16 {}".format(w2))
return size
tok = params.split(',') tok = params.split(',')
# FT1 and FT2
fts = ''
#
# Parse operands, generating fts along the way
#
for word in tok: for word in tok:
word = word.strip() word = word.strip()
instr_args += ' ' instr_args += ' '
pref = None gotPref = False
if len(fts) != 0:
fts += ' '
# memory length prefixes # memory length prefixes
if len(word) > 2 and '[' in word: if len(word) > 2 and '[' in word:
if word[0] == 'b': if word[0] in 'bwlq':
pref = "%b" fts += word[0]
elif word[0] == 'w': gotPref = True
pref = "%w"
elif word[0] == 'l' or word[0] == 'd':
pref = "%l"
elif word[0] == 'q':
pref = "%q"
else: else:
print("Bad memory length prefix: {}".format(line)) print("Bad memory length prefix: {}".format(line))
leave() leave()
@ -364,20 +447,116 @@ def parse_instr(line):
word = word[1:].strip() word = word[1:].strip()
assert(word[0] == '[') assert(word[0] == '[')
# [reg+off], [reg+regoff+off] or [imm64] #
# Determine memory format and save it into fts
#
if word[0] == '[': if word[0] == '[':
assert(word[-1] == ']') assert(word[-1] == ']')
word = word[1:-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)) print("Missing access length modifier: {}".format(line))
leave() leave()
sys.exit(1) sys.exit(1)
instr_name += "_m" instr_name += "_m"
instr_args += "{}".format(pref)
#
# Offsets
#
if '+' in word: 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 # +2 for A_OFF, +2 for offset, +2 for regoff, +2 for register
size += 2 + 2 + 2 + 2 size += 2 + 2 + 2 + 2
instr_args += "off " instr_args += "off "
@ -406,47 +585,60 @@ def parse_instr(line):
instr_args += "{} {} {}".format(off, regoff, reg) instr_args += "{} {} {}".format(off, regoff, reg)
continue continue
"""
# [imm64] #
# [imm64] or [reg]
#
else: else:
# +2 for A_MEM
size += 2
instr_args += "mem "
fellthrough = True fellthrough = True
# FALLTHROUGH # 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 # preprocessor
if word in pdefs: if word in pdefs:
word = pdefs[word] word = pdefs[word]
# Fall through # 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 # register
if word in pregs: if word in pregs:
size += 2 size += 2
if not fellthrough: if not fellthrough:
instr_name += "_r" instr_name += "_r"
fts += "reg"
else:
fts += "rr"
instr_args += word instr_args += word
fellthrough = False fellthrough = False
continue continue
# it's a label (a 64-bit immediate) # it's a label (a 64-bit immediate)
# +2 for A_IMM64, +8 for immediate # +8 for immediate
size += 2 + 8 size += 8
if not fellthrough: if not fellthrough:
instr_name += "_i" instr_name += "_i"
instr_args += "%imm64 "
fts += "imm64"
instr_args += "%%imm64 "
if word[0] == '.': if word[0] == '.':
instr_args += plastlabel instr_args += plastlabel
@ -454,31 +646,37 @@ def parse_instr(line):
instr_args += word instr_args += word
fellthrough = False 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 return size
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
special_syms = { special_syms = {
"%bmem": 0x7001, "%%imm16",
"%wmem": 0x7002, "%%imm32",
"%lmem": 0x7004, "%%imm64",
"%qmem": 0x7008, "%%signed"
"%boff": 0x7701,
"%woff": 0x7702,
"%loff": 0x7704,
"%qoff": 0x7708,
"%imm16": 0x7772,
"%imm32": 0x7774,
"%imm64": 0x7778,
"%rep": 0x8000
} }
def gentext(): def gentext():
instrs.seek(0) instrs.seek(0)
print(instrs.read())
instrs.seek(0)
text_start = 0x100000 text_start = 0x100000
data_start = text_start + ptext data_start = text_start + ptext
data_start += (8 - data_start % 8) data_start += (8 - data_start % 8)
@ -487,11 +685,21 @@ def gentext():
tok = line.strip().split(' ') tok = line.strip().split(' ')
for word in tok: for word in tok:
if len(word) == 0:
continue
if word in pregs: if word in pregs:
idx = pregs.index(word) idx = pregs.index(word)
b_text.write(idx.to_bytes(2, byteorder='little', signed=False)) b_text.write(idx.to_bytes(2, byteorder='little', signed=False))
continue 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: if word in pinstrs:
idx = pinstrs.index(word) idx = pinstrs.index(word)
b_text.write(idx.to_bytes(2, byteorder='little', signed=False)) b_text.write(idx.to_bytes(2, byteorder='little', signed=False))
@ -508,20 +716,19 @@ def gentext():
continue continue
if word in special_syms: if word in special_syms:
if word == "%imm16": if word == "%%imm16":
lastimm = 2 lastimm = 2
elif word == "%imm32": elif word == "%%imm32":
lastimm = 4 lastimm = 4
elif word == "%imm64": elif word == "%%imm64":
lastimm = 8 lastimm = 8
if word[2:] == "off" and word[0] == '%': elif word == "%%signed":
lastimm = 2 lastimm = 2
isSigned = True isSigned = True
else: else:
isSigned = False isSigned = False
b_text.write(special_syms[word].to_bytes(2, byteorder='little', signed=isSigned))
continue continue
if is_number(word): if is_number(word):

View File

@ -33,7 +33,7 @@ strcmp:
strncmp: strncmp:
mov rcx, ax2 mov rcx, ax2
.1: .0:
cmp b[ax0], b[ax1] cmp b[ax0], b[ax1]
jmp.nz .1 jmp.nz .1
@ -42,7 +42,7 @@ strncmp:
inc ax0 inc ax0
inc ax1 inc ax1
loop strcmp loop .0
.1: .1:
mov rax, b[ax0] mov rax, b[ax0]

View File

@ -28,7 +28,7 @@ stop
# #
# Preserves all flags # Preserves all flags
# #
!not rm not rm
# #
# Bitwise OR operation # Bitwise OR operation
@ -38,7 +38,8 @@ stop
# Clears OF and CF # Clears OF and CF
# Sets ZF and SF according to the result # Sets ZF and SF according to the result
# #
!or rm rim or rm rim
orf rm rim
# #
# Bitwise AND operation # Bitwise AND operation
@ -48,7 +49,8 @@ stop
# Clears OF and CF # Clears OF and CF
# Sets ZF and SF according to the result # Sets ZF and SF according to the result
# #
!and rm rim and rm rim
andf rm rim
# #
# Bitwise XOR operation # Bitwise XOR operation
@ -58,11 +60,14 @@ stop
# Clears OF and CF # Clears OF and CF
# Sets ZF and SF according to the result # Sets ZF and SF according to the result
# #
!xor rm rim xor rm rim
xorf rm rim
# To document # To document
!shl rm rim shl rm rim
!shr rm rim shr rm rim
shlf rm rim
shrf rm rim
#---------------------------------------------------------------------------# #---------------------------------------------------------------------------#
# Arithmetic instructions # # Arithmetic instructions #
@ -82,7 +87,8 @@ stop
# Treats $1 and $2 as signed values # Treats $1 and $2 as signed values
# Sets ZF and SF according to the result # Sets ZF and SF according to the result
# #
!sgn rm rim sgn rm rim
sgnf rm rim
# #
# Arithmetical NEG operation # Arithmetical NEG operation
@ -93,7 +99,8 @@ stop
# Sets OF if $1 == $LONG_MIN; clears it otherwise # Sets OF if $1 == $LONG_MIN; clears it otherwise
# Sets ZF and SF according to the result # Sets ZF and SF according to the result
# #
!neg rm neg rm
negf rm
# #
# Arithmetical INC operation # Arithmetical INC operation
@ -104,7 +111,8 @@ stop
# Sets OF if $1 == $LONG_MAX, clears it otherwise # Sets OF if $1 == $LONG_MAX, clears it otherwise
# Sets ZF and SF according to the result # Sets ZF and SF according to the result
# #
!inc rm inc rm
incf rm
# #
# Arithmetical DEC operation # Arithmetical DEC operation
@ -115,7 +123,8 @@ stop
# Sets OF if $1 == $LONG_MIN, clears it otherwise # Sets OF if $1 == $LONG_MIN, clears it otherwise
# Sets ZF and SF according to the result # Sets ZF and SF according to the result
# #
!dec rm dec rm
decf rm
# #
# Arithmetical ADD operation # Arithmetical ADD operation
@ -126,7 +135,8 @@ stop
# Sets OF is signed integer overflow occur, clears it otherwise # Sets OF is signed integer overflow occur, clears it otherwise
# Sets ZF and SF according to the result # Sets ZF and SF according to the result
# #
!add rm rim add rm rim
addf rm rim
# #
# Arithmetical SUB operation # Arithmetical SUB operation
@ -137,7 +147,8 @@ stop
# Sets OF is signed integer overflow occur, clears it otherwise # Sets OF is signed integer overflow occur, clears it otherwise
# Sets ZF and SF according to the result # Sets ZF and SF according to the result
# #
!sub rm rim sub rm rim
subf rm rim
# #
# Arithmetical unsigned MUL operation # Arithmetical unsigned MUL operation
@ -147,7 +158,8 @@ stop
# Sets CF and OF if HI($1 * $2) > 0, clears them otherwise # Sets CF and OF if HI($1 * $2) > 0, clears them otherwise
# Preserves ZF and SF # Preserves ZF and SF
# #
!mul rm rim mul rm rim
mulf rm rim
# #
# Arithmetical unsigned DIV operation # Arithmetical unsigned DIV operation
@ -156,7 +168,7 @@ stop
# #
# Preserves all flags # Preserves all flags
# #
!div rm rim div rm rim
# #
# Arithmetical unsigned MOD operation # Arithmetical unsigned MOD operation
@ -165,7 +177,7 @@ stop
# #
# Preserves all flags # Preserves all flags
# #
!mod rm rim mod rm rim
# #
# Arithmetical unsigned 128-bit MUL operation # Arithmetical unsigned 128-bit MUL operation
@ -177,6 +189,7 @@ stop
# Preserves ZF and SF # Preserves ZF and SF
# #
mul2 rim mul2 rim
mul2f rim
# #
# Arithmetical unsigned combined DIV and MOD operations # Arithmetical unsigned combined DIV and MOD operations
@ -222,8 +235,8 @@ cmp rim rim
# #
# RIP = CR1 + $1 # RIP = CR1 + $1
# #
!j ri j ri
!jmp ri jmp ri
# #
# RCX-dependent jump (LOOP) instruction # RCX-dependent jump (LOOP) instruction
@ -233,7 +246,7 @@ cmp rim rim
# RIP = CR1 + $1 # RIP = CR1 + $1
# FI # FI
# #
!loop ri loop ri
#---------------------------------------------------------------------------# #---------------------------------------------------------------------------#
# Movement instructions # # Movement instructions #
@ -251,14 +264,14 @@ cmp rim rim
# #
# Preserves all flags # Preserves all flags
# #
!lea rm m lea rm m
# #
# Movement (MOV) instruction # Movement (MOV) instruction
# #
# $1 = $2 # $1 = $2
# #
!mov rm rim mov rm rim
# #
# Exchange (XCHG) instruction # Exchange (XCHG) instruction
@ -267,7 +280,7 @@ cmp rim rim
# $1 = $2 # $1 = $2
# $2 = $_ # $2 = $_
# #
!xchg rm rim xchg rm rim
# #
# Compare-and-exchange (CMPXCHG) instruction # Compare-and-exchange (CMPXCHG) instruction
@ -305,7 +318,7 @@ cmpxchg rm rim
# #STA if RSP MOD 8 > 0 # #STA if RSP MOD 8 > 0
# #STU if RSP > RBP # #STU if RSP > RBP
# #
!push rim push rim
# #
# POP value from stack # POP value from stack
@ -318,7 +331,7 @@ cmpxchg rm rim
# #STA if RSP MOD 8 > 0 # #STA if RSP MOD 8 > 0
# #STU if RSP >= RBP # #STU if RSP >= RBP
# #
!pop rm pop rm
# #
# Unconditional jump with possible return (CALL) # Unconditional jump with possible return (CALL)
@ -329,7 +342,7 @@ cmpxchg rm rim
# Throws: # Throws:
# See PUSH and JMP # See PUSH and JMP
# #
!call rim call rim
# #
# Return to caller (RET) # Return to caller (RET)
@ -339,7 +352,7 @@ cmpxchg rm rim
# Throws: # Throws:
# See POP # See POP
# #
!ret ret
# #
# Make new stack frame (ENTER) # Make new stack frame (ENTER)
@ -358,7 +371,7 @@ enter
# RBP = *RSP # RBP = *RSP
# RSP = RSP + 8 # RSP = RSP + 8
# #
!leave leave
#---------------------------------------------------------------------------# #---------------------------------------------------------------------------#
# Supervisor only instructions # # Supervisor only instructions #
@ -460,7 +473,7 @@ prn rim
# (cause register dump on standard error) # (cause register dump on standard error)
# (wait for user input before proceeeding) # (wait for user input before proceeeding)
# #
!break break
# #
# Step-by-step execution (STEP) # Step-by-step execution (STEP)

View File

@ -3,27 +3,27 @@
#include <in/instrs.h> #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) IMPL_START_2(sgn)
{ {
v1 = (long)v2 < 0 ? (ulong)-1L : 1; v1 = (long)v2 < 0 ? (ulong)-1L : 1;
} }
IMPL_OUT;
IMPL_START_2(sgnf)
{
v1 = (long)v2 < 0 ? (ulong)-1L : 1;
}
IMPL_OUT_ZSF; IMPL_OUT_ZSF;
IMPL_START_1(neg) IMPL_START_1(neg)
{
v1 = ~v1 + 1;
}
IMPL_OUT;
IMPL_START_1(negf)
{ {
if (v1 == 0) flg |= CF; if (v1 == 0) flg |= CF;
@ -41,6 +41,12 @@ IMPL_OUT_ZSF;
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
IMPL_START_1(inc) IMPL_START_1(inc)
{
v1++;
}
IMPL_OUT;
IMPL_START_1(incf)
{ {
if (v1 == LONG_MAX) flg |= OF; if (v1 == LONG_MAX) flg |= OF;
else flg &= ~OF; else flg &= ~OF;
@ -50,6 +56,12 @@ IMPL_START_1(inc)
IMPL_OUT_ZSF; IMPL_OUT_ZSF;
IMPL_START_1(dec) IMPL_START_1(dec)
{
v1--;
}
IMPL_OUT;
IMPL_START_1(decf)
{ {
if (v1 == LONG_MIN) flg |= OF; if (v1 == LONG_MIN) flg |= OF;
else flg &= ~OF; else flg &= ~OF;
@ -61,6 +73,12 @@ IMPL_OUT_ZSF;
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
IMPL_START_2(add) IMPL_START_2(add)
{
v1 += v2;
}
IMPL_OUT;
IMPL_START_2(addf)
{ {
if (v1 + v2 < v1) flg |= OF; if (v1 + v2 < v1) flg |= OF;
else flg &= ~OF; else flg &= ~OF;
@ -75,6 +93,12 @@ IMPL_START_2(add)
IMPL_OUT_ZSF; IMPL_OUT_ZSF;
IMPL_START_2(sub) IMPL_START_2(sub)
{
v1 -= v2;
}
IMPL_OUT;
IMPL_START_2(subf)
{ {
if (v1 < v2) flg |= CF; if (v1 < v2) flg |= CF;
else flg &= ~CF; else flg &= ~CF;
@ -89,7 +113,7 @@ IMPL_START_2(sub)
IMPL_OUT_ZSF; IMPL_OUT_ZSF;
// //
// i_sub but discards result // i_subf but discards result
// //
IMPL_START_2(cmp) IMPL_START_2(cmp)
{ {
@ -132,6 +156,13 @@ static void multiply(ulong u, ulong v, ulong *hi, ulong *lo)
} }
IMPL_START_2(mul) IMPL_START_2(mul)
{
ulong hi;
multiply(v1, v2, &hi, &v1);
}
IMPL_OUT;
IMPL_START_2(mulf)
{ {
ulong hi; ulong hi;
@ -149,7 +180,14 @@ IMPL_START_2(mul)
} }
IMPL_OUT; IMPL_OUT;
IMPL_START_1(mul2) IMPL_START_1(mul2)
{
multiply(rax, v1, &rdx, &rax);
}
IMPL_END;
IMPL_START_1(mul2f)
{ {
multiply(rax, v1, &rdx, &rax); 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> #include <in/instrs.h>
IMPL_COND(break);
IMPL_START_0(break) IMPL_START_0(break)
{ {
log("\nExecuting BREAK INSTR\n"); log("\nExecuting BREAK INSTR\n");

View File

@ -16,7 +16,7 @@
SET_ZF(v); \ SET_ZF(v); \
SET_SF(v) SET_SF(v)
#define _SET_ZSPF(v) \ #define SET_ZSPF(v) \
SET_ZF(v); \ SET_ZF(v); \
SET_SF(v); \ SET_SF(v); \
SET_PF(v) SET_PF(v)

View File

@ -3,10 +3,17 @@
#include <pc/arch.h> #include <pc/arch.h>
#include <in/cond.h>
#include <in/flags.h> #include <in/flags.h>
#include <in/arch_i.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) \ #define IMPL_START_0(name) \
bool i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, ulong *ret) \ 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) \ #define IMPL_START_1(name) \
bool i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, ulong *ret) \ 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) \ #define IMPL_START_2(name) \
bool i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, ulong *ret) \ bool i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, ulong *ret) \
{ \ { \
ulong v1 = p1->val; \ GETV(v1, p1); \
ulong v2 = p2->val; GETV(v2, p2);
#define IMPL_OUT_ZSF \ #define IMPL_OUT_ZSF \
SET_ZSF(v1); \ SET_ZSF(v1); \

View File

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

View File

@ -3,12 +3,11 @@
#include <in/instrs.h> #include <in/instrs.h>
IMPL_COND(not); IMPL_START_1(not)
IMPL_COND(and); {
IMPL_COND(or); v1 = ~v1;
IMPL_COND(xor); }
IMPL_COND(shl); IMPL_OUT;
IMPL_COND(shr);
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
@ -21,15 +20,28 @@ IMPL_START_2(test)
IMPL_END; IMPL_END;
IMPL_START_2(and) IMPL_START_2(and)
{
v1 &= v2;
}
IMPL_OUT;
IMPL_START_2(andf)
{ {
flg &= ~OF; flg &= ~OF;
flg &= ~CF; flg &= ~CF;
v1 &= v2; v1 &= v2;
} }
IMPL_OUT_ZSF; IMPL_OUT_ZSF;
//--------------------------------------------------------------------------
IMPL_START_2(or) IMPL_START_2(or)
{
v1 |= v2;
}
IMPL_OUT;
IMPL_START_2(orf)
{ {
flg &= ~OF; flg &= ~OF;
flg &= ~CF; flg &= ~CF;
@ -38,6 +50,12 @@ IMPL_START_2(or)
IMPL_OUT_ZSF; IMPL_OUT_ZSF;
IMPL_START_2(xor) IMPL_START_2(xor)
{
v1 ^= v2;
}
IMPL_OUT;
IMPL_START_2(xorf)
{ {
flg &= ~OF; flg &= ~OF;
flg &= ~CF; flg &= ~CF;
@ -45,21 +63,31 @@ IMPL_START_2(xor)
} }
IMPL_OUT_ZSF; IMPL_OUT_ZSF;
//--------------------------------------------------------------------------
IMPL_START_2(shl) IMPL_START_2(shl)
{ {
v1 <<= v2; v1 <<= v2;
} }
IMPL_OUT;
IMPL_START_2(shlf)
{
v1 <<= v2;
}
IMPL_OUT_ZSF; IMPL_OUT_ZSF;
IMPL_START_2(shr) IMPL_START_2(shr)
{ {
v1 >>= v2; v1 >>= v2;
} }
IMPL_OUT_ZSF;
IMPL_START_1(not)
{
v1 = ~v1;
}
IMPL_OUT; IMPL_OUT;
IMPL_START_2(shrf)
{
v1 >>= v2;
}
IMPL_OUT_ZSF;
//--------------------------------------------------------------------------

View File

@ -3,18 +3,6 @@
#include <in/instrs.h> #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 // Movement instructions
// //
@ -53,11 +41,6 @@ IMPL_START_2(movt)
} }
IMPL_OUT; IMPL_OUT;
IMPL_COND(movb);
IMPL_COND(movw);
IMPL_COND(movl);
IMPL_COND(movt);
IMPL_START_2(xchg) IMPL_START_2(xchg)
{ {
ulong t = v1; ulong t = v1;

View File

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

View File

@ -36,9 +36,9 @@ Values for COND:
Highest (6th) bit of COND indicates negation Highest (6th) bit of COND indicates negation
Fx values: Fx values:
0000 (none) 00000 (none)
0001 reg 00001 reg
0010 imm64 00010 imm64
xxx00 [imm64] xxx00 [imm64]
xxx01 [reg+reg] code(reg)|code(reg) 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) if (!ok)
_except(ctx, E_ILL, _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) void decode(ctx_t *ctx)
@ -66,7 +67,7 @@ void decode(ctx_t *ctx)
in = &ctx->i[w1]; in = &ctx->i[w1];
if (!nomore) if (nomore)
goto skip_w2; 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)) 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 (ctx->r[reg].flags & SYS)
if (cr0 & UF) 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) 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; ushort temp;
p->type = fmt; p->type = fmt;
@ -170,6 +171,8 @@ void extract_param(ctx_t *ctx, acc_t *p, uchar fmt)
checkreg(ctx, p->reg, 0); checkreg(ctx, p->reg, 0);
p->val = R(p->reg); p->val = R(p->reg);
return;
} }
else if (fmt == A_IMM64) 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) << 16;
p->val |= (ulong)ctx->get(ctx) << 32; p->val |= (ulong)ctx->get(ctx) << 32;
p->val |= (ulong)ctx->get(ctx) << 48; p->val |= (ulong)ctx->get(ctx) << 48;
return;
} }
assert(ACC_FMT_IS_MEM(fmt)); 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_RRI:
case AM_RRII: case AM_RRII:
temp = ctx->get(ctx); temp = ctx->get(ctx);
reg1 = temp >> 8; p->reg1 = temp >> 8;
reg2 = temp & 0xFF; p->reg2 = temp & 0xFF;
checkreg(ctx, reg1, 0); checkreg(ctx, p->reg1, 1);
checkreg(ctx, reg2, 1); checkreg(ctx, p->reg2, 1);
if (fmt == AM_RRI) if (mfmt == AM_RRI)
{ {
imm1 = 1; p->imm1 = 1;
imm2 = ctx->get(ctx); p->imm2 = ctx->get(ctx);
} }
else if (fmt == AM_RRII) else if (mfmt == AM_RRII)
{ {
imm1 = ctx->get(ctx); p->imm1 = ctx->get(ctx);
imm2 = 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; break;
default: default:
_except(ctx, E_ILL, "Invalid MFMT for access: %x", fmt); _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) static bool eval_cond(ctx_t *ctx, uint cond)
{ {
bool neg = cond & (1 << 5); bool neg = cond & (1 << 4);
bool ok; bool ok;
cond &= ~(1 << 5); cond &= ~(1 << 4);
switch (cond) switch (cond)
{ {
@ -271,81 +280,12 @@ static bool eval_cond(ctx_t *ctx, uint cond)
case CD_CXZ: ok = !rcx; break; case CD_CXZ: ok = !rcx; break;
default: 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; 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 // Executes an instruction
// //

View File

@ -21,7 +21,7 @@ enum
BITS_COND = (1 << 14) | (1 << 13) | (1 << 12) BITS_COND = (1 << 14) | (1 << 13) | (1 << 12)
| (1 << 11) | (1 << 10), | (1 << 11) | (1 << 10),
COND_SHIFT = 8, COND_SHIFT = 10,
Fx_MASK = 0x1F, Fx_MASK = 0x1F,
F1_SHIFT = 5, F1_SHIFT = 5,
@ -65,6 +65,8 @@ struct acc_t
ulong addr; ulong addr;
uint mlen; uint mlen;
// For instruction dumping ONLY
ushort reg1, reg2, imm1, imm2;
}; };
enum { NOPRM, P_REG, P_IMM, P_MEM=4 }; enum { NOPRM, P_REG, P_IMM, P_MEM=4 };
@ -93,3 +95,12 @@ void extract_param(ctx_t *ctx,
acc_t *p, acc_t *p,
uchar fmt); 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");
}