assembly wip
This commit is contained in:
parent
d6089b3999
commit
b7fa46e540
323
as/k-as.py
323
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):
|
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):
|
||||||
|
|
|
@ -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]
|
||||||
|
|
67
vm/in/INSTRS
67
vm/in/INSTRS
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
50
vm/in/cond.h
50
vm/in/cond.h
|
@ -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)
|
|
|
@ -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");
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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); \
|
||||||
|
|
|
@ -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
|
||||||
//
|
//
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
17
vm/in/mov.c
17
vm/in/mov.c
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
//
|
//
|
||||||
|
|
|
@ -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)
|
||||||
|
|
118
vm/pc/decd.c
118
vm/pc/decd.c
|
@ -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
|
||||||
//
|
//
|
||||||
|
|
13
vm/pc/decd.h
13
vm/pc/decd.h
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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");
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue