mirror of
https://gitlab.os-k.eu/os-k-team/kvisc.git
synced 2023-08-25 14:05:46 +02:00
new encoding
This commit is contained in:
parent
9eee4817cd
commit
f89e535fbd
269
as/k-as.py
269
as/k-as.py
@ -213,7 +213,7 @@ def parse():
|
||||
|
||||
if line[0] == ' ' or line[0] == '\t':
|
||||
line = line.lstrip()
|
||||
instrs.write(pcurfile + ' ')
|
||||
instrs.write(pcurfile + ' ' + hex(ptext) + ' ')
|
||||
ptext += parse_instr(line)
|
||||
instrs.write("\n")
|
||||
|
||||
@ -411,43 +411,31 @@ def get_cond_mask(cond, line):
|
||||
leave(1)
|
||||
|
||||
return (mask | pconds[cond])
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
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]
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
fmts = {
|
||||
"r": 0b00000000,
|
||||
"m_r": 0b00100000,
|
||||
"m_rr": 0b01000000,
|
||||
"m_rriw": 0b01100000,
|
||||
"m_rrid": 0b10000000,
|
||||
"m_rrii": 0b10100000,
|
||||
"m_riq": 0b11000000,
|
||||
"imm8": 0b11100001,
|
||||
"imm16": 0b11100010,
|
||||
"imm32": 0b11100100,
|
||||
"imm64": 0b11101000,
|
||||
}
|
||||
|
||||
pref2len = {
|
||||
"b" : 1,
|
||||
"w" : 2,
|
||||
"d" : 4,
|
||||
"l" : 4,
|
||||
"q" : 8,
|
||||
}
|
||||
|
||||
def parse_instr(line):
|
||||
if line == None or len(line) == 0:
|
||||
return 0
|
||||
@ -463,12 +451,10 @@ def parse_instr(line):
|
||||
|
||||
fellthrough = False
|
||||
|
||||
size = 4
|
||||
size = 2
|
||||
|
||||
# Word 2 (rep|ft3|ft2|ft1)
|
||||
w2 = 0
|
||||
|
||||
cond = None
|
||||
# Byte 2 (rep|lock|0|cond)
|
||||
b2 = 0
|
||||
|
||||
if len(instr) > 2 and '.' in instr:
|
||||
instr, suf = instr.split('.', 1)
|
||||
@ -485,42 +471,30 @@ def parse_instr(line):
|
||||
else:
|
||||
suf = ''
|
||||
|
||||
w2 |= 0x8000 # REP
|
||||
|
||||
b2 |= 1<<7 # REP
|
||||
|
||||
if len(suf) > 0:
|
||||
instrs.write("%%cond ")
|
||||
cond = "%%imm16 {}".format(get_cond_mask(suf, line))
|
||||
b2 |= get_cond_mask(suf, line)
|
||||
|
||||
instr_name = instr
|
||||
instr_args = ''
|
||||
|
||||
if params == None or len(params) == 0:
|
||||
instrs.write("{} ".format(instr_name))
|
||||
|
||||
if cond != None:
|
||||
size += 2
|
||||
instrs.write("{} ".format(cond))
|
||||
|
||||
instrs.write("%%imm16 {}".format(w2))
|
||||
instrs.write("{} %%imm8 {}".format(instr_name, b2))
|
||||
|
||||
return size
|
||||
|
||||
tok = params.split(',')
|
||||
|
||||
# FTn
|
||||
fts = ''
|
||||
|
||||
#
|
||||
# Parse operands, generating fts along the way
|
||||
# Parse operands
|
||||
#
|
||||
for word in tok:
|
||||
word = word.strip()
|
||||
|
||||
instr_args += ' '
|
||||
|
||||
gotPref = False
|
||||
if len(fts) != 0:
|
||||
fts += ' '
|
||||
mlen = 0
|
||||
|
||||
if len(word) == 0:
|
||||
print("Wrong syntax in line: '{}'".format(line))
|
||||
@ -540,9 +514,8 @@ def parse_instr(line):
|
||||
|
||||
# memory length prefixes
|
||||
if len(word) > 2 and '[' in word:
|
||||
if word[0] in 'bwlq':
|
||||
fts += word[0]
|
||||
gotPref = True
|
||||
if word[0] in 'bwldq':
|
||||
mlen = pref2len[word[0]]
|
||||
else:
|
||||
print("Bad memory length prefix: {}".format(line))
|
||||
leave(1)
|
||||
@ -551,7 +524,7 @@ def parse_instr(line):
|
||||
assert(word[0] == '[')
|
||||
|
||||
#
|
||||
# Determine memory format and save it into fts
|
||||
# Determine memory format
|
||||
#
|
||||
if word[0] == '[':
|
||||
assert(word[-1] == ']')
|
||||
@ -562,10 +535,8 @@ def parse_instr(line):
|
||||
word = pdefs[word]
|
||||
# Fall through
|
||||
|
||||
#
|
||||
# Make sure we got an access length prefix
|
||||
#
|
||||
if not gotPref:
|
||||
if mlen == 0:
|
||||
print("Missing access length modifier: {}".format(line))
|
||||
leave(1)
|
||||
|
||||
@ -581,15 +552,15 @@ def parse_instr(line):
|
||||
# Offsets
|
||||
#
|
||||
if '+' in word:
|
||||
reg1 = "rzx"
|
||||
reg2 = "rzx"
|
||||
reg1 = "zero"
|
||||
reg2 = "zero"
|
||||
imm1 = '1'
|
||||
imm2 = '0'
|
||||
|
||||
wtok = word.split('+')
|
||||
|
||||
#
|
||||
# [reg] and [reg*imm16]
|
||||
# [reg] and [reg*imm]
|
||||
#
|
||||
|
||||
if len(wtok) == 1:
|
||||
@ -602,10 +573,10 @@ def parse_instr(line):
|
||||
reg1 = wtok[0]
|
||||
|
||||
#
|
||||
# [reg+reg], [reg+imm16], [reg*imm16+imm16], [reg+reg*imm16]
|
||||
# [reg+reg], [reg+imm], [reg*imm+imm], [reg+reg*imm]
|
||||
#
|
||||
elif len(wtok) == 2:
|
||||
# Must be [reg*imm16+imm16]
|
||||
# Must be [reg*imm+imm]
|
||||
if '*' in wtok[0]:
|
||||
assert(len(wtok[0].split('*')) == 2)
|
||||
assert(is_number(wtok[1].strip()))
|
||||
@ -614,7 +585,7 @@ def parse_instr(line):
|
||||
reg2, imm1 = wtok[0].split('*', 1)
|
||||
imm2 = wtok[1]
|
||||
|
||||
# Must be [reg+reg*imm16]
|
||||
# Must be [reg+reg*imm]
|
||||
elif '*' in wtok[1]:
|
||||
assert(len(wtok[1].split('*')) == 2)
|
||||
|
||||
@ -631,7 +602,7 @@ def parse_instr(line):
|
||||
reg2 = wtok[1]
|
||||
|
||||
#
|
||||
# [reg+reg+imm16], [reg+reg*imm16+imm16]
|
||||
# [reg+reg+imm], [reg+reg*imm8+imm]
|
||||
#
|
||||
else:
|
||||
assert(len(wtok) == 3)
|
||||
@ -647,129 +618,91 @@ def parse_instr(line):
|
||||
reg2 = wtok[1]
|
||||
|
||||
#
|
||||
# Update fts and instr_args
|
||||
# Update instr_args
|
||||
#
|
||||
|
||||
instr_args += "{}:{} ".format(reg2, reg1)
|
||||
if imm1 == '1':
|
||||
# [reg+reg]
|
||||
if imm2 == '0':
|
||||
instr_args += "%%imm8 {} {} {}".format(fmts["m_rr"]|mlen, reg1, reg2)
|
||||
size += 3
|
||||
|
||||
# [reg+reg+imm]
|
||||
else:
|
||||
instr_args += "%%imm8 {} {} {} %%imm16 {}".format(fmts["m_rriw"]|mlen, reg1, reg2, imm2)
|
||||
size += 5
|
||||
|
||||
# [reg+reg*imm+imm]
|
||||
else:
|
||||
instr_args += "%%imm8 {} {} {} %%imm8 {} %%imm32 {}".format(fmts["m_rriw"]|mlen, reg1, reg2, imm1, imm2)
|
||||
size += 8
|
||||
|
||||
# [reg]
|
||||
elif word in pregs:
|
||||
instr_args += "%%imm8 {} {}".format(fmts["m_r"]|mlen, word)
|
||||
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
|
||||
|
||||
#
|
||||
# [imm64] or [reg]
|
||||
#
|
||||
# [imm], converted to [zero+imm]
|
||||
else:
|
||||
fellthrough = True
|
||||
# FALLTHROUGH
|
||||
instr_args += "%%imm8 {} zero zero %%imm32 {}".format(fmts["m_rrid"]|mlen, word)
|
||||
size += 7
|
||||
|
||||
continue
|
||||
|
||||
# preprocessor, yet again
|
||||
if word in pdefs:
|
||||
word = pdefs[word]
|
||||
# Fall through
|
||||
# fallthrough
|
||||
|
||||
# characters 'c'
|
||||
if len(word) == 3 and word[0] == word[-1] == "'":
|
||||
word = str(ord(word[1]))
|
||||
# fallthrough
|
||||
|
||||
# register index $reg
|
||||
if len(word) == 4 and word[0] == '$':
|
||||
if word[1:] in pregs:
|
||||
word = str(pregs[word[1:]])
|
||||
# fallthrough
|
||||
|
||||
# for now every immediate is 64-bit
|
||||
if is_number(word):
|
||||
# +8 for immediate
|
||||
size += 8
|
||||
size += 9 # ModRM + imm
|
||||
|
||||
if not fellthrough:
|
||||
instr_name += "_i"
|
||||
|
||||
fts += "imm64"
|
||||
|
||||
instr_args += "%%imm64 "
|
||||
instr_args += word
|
||||
instr_name += "_i"
|
||||
instr_args += "%%imm8 {} ".format(fmts["imm64"])
|
||||
instr_args += "%%imm64 {}".format(word)
|
||||
|
||||
fellthrough = False
|
||||
continue
|
||||
|
||||
# register
|
||||
if word in pregs:
|
||||
size += 2
|
||||
|
||||
if not fellthrough:
|
||||
instr_name += "_r"
|
||||
fts += "reg"
|
||||
|
||||
else:
|
||||
fts += "rr"
|
||||
|
||||
elif word in pregs:
|
||||
size += 1
|
||||
instr_name += "_r"
|
||||
instr_args += word
|
||||
fellthrough = False
|
||||
continue
|
||||
|
||||
# it's a label (a 64-bit immediate)
|
||||
# +8 for immediate
|
||||
size += 8
|
||||
# it's a label (a 32-bit immediate)
|
||||
# ModRM + imm
|
||||
size += 5
|
||||
|
||||
if not fellthrough:
|
||||
instr_name += "_i"
|
||||
|
||||
fts += "imm64"
|
||||
instr_args += "%%imm64 "
|
||||
instr_name += "_i"
|
||||
instr_args += "%%imm8 {} ".format(fmts["imm32"])
|
||||
|
||||
if word[0] == '.':
|
||||
instr_args += plastlabel
|
||||
|
||||
instr_args += word
|
||||
fellthrough = False
|
||||
|
||||
#
|
||||
# Compute FTn
|
||||
#
|
||||
l = len(fts.split())
|
||||
|
||||
if l == 3:
|
||||
ft1, ft2, ft3 = fts.split()
|
||||
|
||||
w2 |= get_fts_mask(ft3, line) << 10
|
||||
w2 |= get_fts_mask(ft2, line) << 5
|
||||
w2 |= get_fts_mask(ft1, line)
|
||||
|
||||
elif l == 2:
|
||||
ft1, ft2 = fts.split()
|
||||
|
||||
w2 |= get_fts_mask(ft2, line) << 5
|
||||
w2 |= get_fts_mask(ft1, line)
|
||||
|
||||
else:
|
||||
assert(l == 1)
|
||||
w2 |= get_fts_mask(fts, line)
|
||||
|
||||
if cond == None:
|
||||
instrs.write("{} %%imm16 {}{}".format(instr_name, w2, instr_args))
|
||||
else:
|
||||
size += 2
|
||||
instrs.write("{} {} %%imm16 {}{}".format(instr_name, cond, w2, instr_args))
|
||||
instrs.write("{} %%imm8 {} {}".format(instr_name, b2, instr_args))
|
||||
|
||||
return size
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
special_syms = {
|
||||
"%%cond",
|
||||
"%%imm8",
|
||||
"%%imm16",
|
||||
"%%imm32",
|
||||
"%%imm64",
|
||||
@ -785,15 +718,13 @@ def gentext():
|
||||
|
||||
instrs.seek(0)
|
||||
|
||||
cond_mask = 0
|
||||
|
||||
for _, line in enumerate(instrs):
|
||||
tok = line.strip().split()
|
||||
|
||||
if WANT_DISASM:
|
||||
print(tok)
|
||||
|
||||
tok = tok[1:]
|
||||
tok = tok[2:]
|
||||
|
||||
for word in tok:
|
||||
if len(word) == 0:
|
||||
@ -801,45 +732,33 @@ def gentext():
|
||||
|
||||
if word in pregs:
|
||||
idx = pregs[word]
|
||||
b_text.write(idx.to_bytes(2, byteorder='little', signed=False))
|
||||
continue
|
||||
|
||||
if ':' in word:
|
||||
if len(word.split(':')) < 2:
|
||||
print("Stray ':' in line: {}".format(line))
|
||||
leave(1)
|
||||
|
||||
reg2, reg1 = word.split(':', 1)
|
||||
idx1 = pregs[reg1]
|
||||
idx2 = pregs[reg2]
|
||||
b_text.write(((idx1 << 8) | idx2).to_bytes(2, byteorder='little', signed=False))
|
||||
b_text.write(idx.to_bytes(1, byteorder='little', signed=False))
|
||||
continue
|
||||
|
||||
if word in pinstrs:
|
||||
idx = pinstrs.index(word) | cond_mask
|
||||
cond_mask = 0
|
||||
b_text.write(idx.to_bytes(2, byteorder='little', signed=False))
|
||||
idx = pinstrs.index(word)
|
||||
b_text.write(idx.to_bytes(1, byteorder='little', signed=False))
|
||||
continue
|
||||
|
||||
if word in plabels_text:
|
||||
addr = text_start + plabels_text[word]
|
||||
b_text.write(addr.to_bytes(8, byteorder='little', signed=False))
|
||||
b_text.write(addr.to_bytes(4, byteorder='little', signed=False))
|
||||
continue
|
||||
|
||||
if word in plabels_data:
|
||||
addr = data_start + plabels_data[word]
|
||||
b_text.write(addr.to_bytes(8, byteorder='little', signed=False))
|
||||
b_text.write(addr.to_bytes(4, byteorder='little', signed=False))
|
||||
continue
|
||||
|
||||
if word in special_syms:
|
||||
if word == "%%imm16":
|
||||
if word == "%%imm8":
|
||||
lastimm = 1
|
||||
elif word == "%%imm16":
|
||||
lastimm = 2
|
||||
elif word == "%%imm32":
|
||||
lastimm = 4
|
||||
elif word == "%%imm64":
|
||||
lastimm = 8
|
||||
elif word == "%%cond":
|
||||
cond_mask = (1 << 13)
|
||||
elif word == "%%signed":
|
||||
lastimm = 2
|
||||
isSigned = True
|
||||
|
36
ka/crt/crt.k
36
ka/crt/crt.k
@ -2,10 +2,42 @@
|
||||
; See the LICENSE file in the project root for more information.
|
||||
|
||||
;
|
||||
; Include CRT librairies
|
||||
; Limits
|
||||
;
|
||||
|
||||
CHAR_MIN := 0x0000000000000080
|
||||
SHRT_MIN := 0x0000000000008000
|
||||
INT_MIN := 0x0000000080000000
|
||||
LONG_MIN := 0x8000000000000000
|
||||
|
||||
XCHAR_MIN := 0xFFFFFFFFFFFFFF80
|
||||
XSHRT_MIN := 0xFFFFFFFFFFFF8000
|
||||
XINT_MIN := 0xFFFFFFFF80000000
|
||||
|
||||
CHAR_MAX := 0x000000000000007F
|
||||
SHRT_MAX := 0x0000000000007FFF
|
||||
INT_MAX := 0x000000007FFFFFFF
|
||||
LONG_MAX := 0x7FFFFFFFFFFFFFFF
|
||||
|
||||
BYTE_MAX := 0x00000000000000FF
|
||||
WORD_MAX := 0x000000000000FFFF
|
||||
LWORD_MAX := 0x00000000FFFFFFFF
|
||||
QWORD_MAX := 0xFFFFFFFFFFFFFFFF
|
||||
|
||||
STRLEN_MAX := 0x000000007AFFFFFF
|
||||
FILE_MAXSZ := 0x0000000000008000
|
||||
|
||||
;
|
||||
; Magic numbers
|
||||
;
|
||||
|
||||
PRN_CLEAR := 0x000000008BF00001
|
||||
|
||||
;
|
||||
; CRT librairies
|
||||
;
|
||||
|
||||
include "crt/sys.k"
|
||||
include "crt/limits.k"
|
||||
include "crt/err/errno.k"
|
||||
include "crt/fmt/format.k"
|
||||
include "crt/str/string.k"
|
||||
|
@ -1,25 +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.
|
||||
|
||||
CHAR_MIN := 0x80
|
||||
SHRT_MIN := 0x8000
|
||||
INT_MIN := 0x80000000
|
||||
LONG_MIN := 0x8000000000000000
|
||||
|
||||
XCHAR_MIN := 0xFFFFFFFFFFFFFF80
|
||||
XSHRT_MIN := 0xFFFFFFFFFFFF8000
|
||||
XINT_MIN := 0xFFFFFFFF80000000
|
||||
|
||||
CHAR_MAX := 0x7F
|
||||
SHRT_MAX := 0x7FFF
|
||||
INT_MAX := 0x7FFFFFFF
|
||||
LONG_MAX := 0x7FFFFFFFFFFFFFFF
|
||||
|
||||
BYTE_MAX := 0xFF
|
||||
WORD_MAX := 0xFFFF
|
||||
LWORD_MAX := 0xFFFFFFFF
|
||||
QWORD_MAX := 0xFFFFFFFFFFFFFFFF
|
||||
|
||||
STRLEN_MAX := 0xFFFFFFFF
|
||||
|
||||
FILE_MAXSZ := 0x8000 ; 512KB
|
@ -10,9 +10,10 @@
|
||||
; <0 if the first character that does not match has a lower value in str1 than in str2
|
||||
;
|
||||
strcmp:
|
||||
mov rcx, zero
|
||||
.l:
|
||||
movzx rax, b[ax0]
|
||||
movzx rdx, b[ax1]
|
||||
movzx rax, b[ax0+rcx]
|
||||
movzx rdx, b[ax1+rcx]
|
||||
|
||||
cmp rax, rdx
|
||||
jmp.nz .r
|
||||
@ -21,8 +22,7 @@ strcmp:
|
||||
add rbx, rax, rdx
|
||||
jmp.bxz .r
|
||||
|
||||
add ax0, ax0, 1
|
||||
add ax1, ax1, 1
|
||||
add rcx, rcx, 1
|
||||
jmp .l
|
||||
|
||||
.r:
|
||||
@ -37,8 +37,8 @@ strncmp:
|
||||
jmp.cxz .r
|
||||
|
||||
.l:
|
||||
mov rax, b[ax0]
|
||||
mov rdx, b[ax1]
|
||||
movzx rax, b[ax0]
|
||||
movzx rdx, b[ax1]
|
||||
|
||||
cmp rax, rdx
|
||||
jmp.nz .r
|
||||
|
16
ka/crt/sys.k
16
ka/crt/sys.k
@ -1,19 +1,19 @@
|
||||
; The OS/K Team licenses this file to you under the MIT license.
|
||||
; See the LICENSE file in the project root for more information.
|
||||
|
||||
;
|
||||
; EXIT syscall
|
||||
;
|
||||
; Return to COMMAND.COM
|
||||
;
|
||||
Sys.Exit := 0x00
|
||||
|
||||
;
|
||||
; SHUTDOWN syscall
|
||||
;
|
||||
; End virtual machine
|
||||
;
|
||||
Sys.Shutdown := 0x01
|
||||
Sys.Shutdown := 0x00
|
||||
|
||||
;
|
||||
; EXIT syscall
|
||||
;
|
||||
; Return to COMMAND.COM
|
||||
;
|
||||
Sys.Exit := 0x01
|
||||
|
||||
; FIND syscalls
|
||||
;
|
||||
|
@ -2,6 +2,11 @@
|
||||
; See the LICENSE file in the project root for more information.
|
||||
|
||||
__sysmain:
|
||||
pause
|
||||
add rax, rax, 1
|
||||
jmp .1
|
||||
|
||||
.1:
|
||||
jmp start
|
||||
|
||||
|
||||
@ -26,8 +31,7 @@ start:
|
||||
mov rsp, DOSKRNL_STACK
|
||||
mov rbp, zero
|
||||
|
||||
dump
|
||||
mov rcx, 44
|
||||
mov rcx, 1
|
||||
crash.cxz
|
||||
|
||||
call main
|
||||
|
@ -3,25 +3,19 @@
|
||||
|
||||
TrapHandlers.prolog:
|
||||
mov rbp, rsp
|
||||
sub rsp, rsp, 24
|
||||
mov q[rbp-8], r13
|
||||
mov q[rbp-16], r14
|
||||
mov q[rbp-24], r15
|
||||
|
||||
; nx0 = caller's cr2
|
||||
mov ax0, r14
|
||||
mov ax1, $cr2
|
||||
call RFS.LoadReg
|
||||
|
||||
; we don't preserve the r12 we got
|
||||
mov r12, rax
|
||||
mov rdx, zero
|
||||
|
||||
jmp rcx
|
||||
|
||||
TrapHandlers.epilog:
|
||||
mov r15, q[rbp-24]
|
||||
mov r14, q[rbp-16]
|
||||
mov r13, q[rbp-8]
|
||||
|
||||
; TRAP return values: RAX-RDX
|
||||
|
||||
|
@ -14,8 +14,8 @@ trap0_handler:
|
||||
call RFS.LoadReg
|
||||
call RFS.LoadArgs
|
||||
|
||||
b.z rax, zero, .handle_Shutdown
|
||||
b.z rax, Sys.Exit, .handle_Exit
|
||||
b.z rax, Sys.Shutdown, .handle_Shutdown
|
||||
b.z rax, Sys.FindNext, .handle_FindNext
|
||||
b.z rax, Sys.FindFirst, .handle_FindFirst
|
||||
b.z rax, Sys.OpenFile, .handle_OpenFile
|
||||
@ -114,19 +114,10 @@ trap0_handler:
|
||||
; Misc.
|
||||
;
|
||||
.handle_Shutdown:
|
||||
mov r12, zero
|
||||
stop
|
||||
|
||||
.handle_HaltMode:
|
||||
hlt
|
||||
.HLT.loop:
|
||||
pause
|
||||
pause
|
||||
pause
|
||||
|
||||
scan rax
|
||||
b.z rax, zero, .HLT.loop
|
||||
|
||||
prn rax
|
||||
jmp .HLT.loop
|
||||
mov rcx, -1
|
||||
hlt.rep
|
||||
stop
|
||||
|
||||
|
@ -2,9 +2,7 @@
|
||||
; See the LICENSE file in the project root for more information.
|
||||
|
||||
PrintBootMsg:
|
||||
mov rcx, STRLEN_MAX
|
||||
mov rdx, .bootmsg
|
||||
prns.rep.nz rdx
|
||||
call print, .bootmsg
|
||||
ret
|
||||
|
||||
.bootmsg = "Starting DOS...\n\n"
|
||||
|
@ -123,43 +123,47 @@ main:
|
||||
|
||||
.builtin_cls = "cls"
|
||||
call strcmp, argv0, .builtin_cls
|
||||
b.z rax, 0, .handle_CLS
|
||||
b.z rax, zero, .handle_CLS
|
||||
|
||||
.builtin_date = "date"
|
||||
call strcmp, argv0, .builtin_date
|
||||
b.z rax, 0, .handle_DATE
|
||||
b.z rax, zero, .handle_DATE
|
||||
|
||||
.builtin_dir = "dir"
|
||||
call strcmp, argv0, .builtin_dir
|
||||
b.z rax, 0, .handle_DIR
|
||||
b.z rax, zero, .handle_DIR
|
||||
|
||||
.builtin_dump = "dump"
|
||||
call strcmp, argv0, .builtin_dump
|
||||
b.z rax, 0, .handle_DUMP
|
||||
b.z rax, zero, .handle_DUMP
|
||||
|
||||
.builtin_echo = "echo"
|
||||
call strcmp, argv0, .builtin_echo
|
||||
b.z rax, 0, .handle_ECHO
|
||||
b.z rax, zero, .handle_ECHO
|
||||
|
||||
.builtin_exit = "exit"
|
||||
call strcmp, argv0, .builtin_exit
|
||||
b.z rax, 0, .handle_EXIT
|
||||
b.z rax, zero, .handle_EXIT
|
||||
|
||||
.builtin_help = "help"
|
||||
call strcmp, argv0, .builtin_help
|
||||
b.z rax, 0, .handle_HELP
|
||||
b.z rax, zero, .handle_HELP
|
||||
|
||||
.builtin_halt = "halt"
|
||||
call strcmp, argv0, .builtin_halt
|
||||
b.z rax, zero, .handle_HALT
|
||||
|
||||
.builtin_print = "print"
|
||||
call strcmp, argv0, .builtin_print
|
||||
b.z rax, 0, .handle_PRINT
|
||||
b.z rax, zero, .handle_PRINT
|
||||
|
||||
.builtin_time = "time"
|
||||
call strcmp, argv0, .builtin_time
|
||||
b.z rax, 0, .handle_TIME
|
||||
b.z rax, zero, .handle_TIME
|
||||
|
||||
.builtin_ver = "ver"
|
||||
call strcmp, argv0, .builtin_ver
|
||||
b.z rax, 0, .handle_VER
|
||||
b.z rax, zero, .handle_VER
|
||||
|
||||
jmp .command_not_found
|
||||
|
||||
@ -167,7 +171,7 @@ main:
|
||||
; call builtins
|
||||
;
|
||||
.handle_CLS:
|
||||
prn 0xC15000AF
|
||||
prn PRN_CLEAR
|
||||
jmp .print_prompt
|
||||
|
||||
.handle_DATE:
|
||||
@ -209,6 +213,12 @@ main:
|
||||
.handle_EXIT:
|
||||
mov rax, Sys.Shutdown
|
||||
trap 0
|
||||
jmp .print_prompt
|
||||
|
||||
.handle_HALT:
|
||||
mov rax, Sys.EnterHaltMode
|
||||
trap 0
|
||||
jmp .print_prompt
|
||||
|
||||
.handle_PRINT:
|
||||
mov rax, Sys.OpenFile
|
||||
@ -266,6 +276,7 @@ main:
|
||||
call print, .helpmsg.echo
|
||||
call print, .helpmsg.exit
|
||||
call print, .helpmsg.help
|
||||
call print, .helpmsg.halt
|
||||
call print, .helpmsg.print
|
||||
call print, .helpmsg.time
|
||||
call print, .helpmsg.ver
|
||||
@ -280,6 +291,7 @@ main:
|
||||
.helpmsg.echo = " ECHO Write arguments to standard output\n"
|
||||
.helpmsg.exit = " EXIT Initiate machine shutdown\n"
|
||||
.helpmsg.help = " HELP Display these messages\n"
|
||||
.helpmsg.halt = " HALT Put processor in halt mode\n"
|
||||
.helpmsg.print = " PRINT Display contents of text file\n"
|
||||
.helpmsg.time = " TIME Display current time of day\n"
|
||||
.helpmsg.ver = " VER Display current COMMAND.COM and DOS kernel versions\n"
|
||||
|
@ -6,7 +6,7 @@
|
||||
verbose ?= yes
|
||||
OBJDIR = ob
|
||||
|
||||
FLAGS=-O2 -Wall -fno-builtin-log -I. -Werror=implicit-function-declaration
|
||||
FLAGS=-O2 -Wall -fno-builtin-log -I. -Werror=implicit-function-declaration -Werror
|
||||
|
||||
dv_src = $(shell ls dv/*.c)
|
||||
in_src = $(shell ls in/*.c)
|
||||
|
128
vm/dv/cpudev.c
128
vm/dv/cpudev.c
@ -29,19 +29,19 @@ size_t rfs_current_idx = 0;
|
||||
|
||||
long cpudev_getmaxidx(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
rax = MAX_RFRAME_IDX;
|
||||
R(RAX) = MAX_RFRAME_IDX;
|
||||
return 0;
|
||||
}
|
||||
|
||||
long cpudev_getrfusage(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
rax = rfs_used;
|
||||
R(RAX) = rfs_used;
|
||||
return 0;
|
||||
}
|
||||
|
||||
long cpudev_getcuridx(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
rax = rfs_current_idx;
|
||||
R(RAX) = rfs_current_idx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -53,12 +53,12 @@ long cpudev_leastavail(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
if (rfs[it] == NULL)
|
||||
{
|
||||
rax = it;
|
||||
R(RAX) = it;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
rax = -1;
|
||||
R(RAX) = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -66,24 +66,24 @@ long cpudev_leastavail(ctx_t *ctx, dev_t *dev)
|
||||
|
||||
long cpudev_isactive(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
CHK_INDEX(ax0);
|
||||
CHK_INDEX(R(AX0));
|
||||
|
||||
rax = (rfs[ax0] != NULL);
|
||||
R(RAX) = (rfs[R(AX0)] != NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long cpudev_activate(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
CHK_INDEX(ax0);
|
||||
CHK_INDEX(R(AX0));
|
||||
|
||||
if (rfs[ax0] != NULL)
|
||||
if (rfs[R(AX0)] != NULL)
|
||||
_except(ctx, E_UDF,
|
||||
"cpudev: activating already activated rframe: #%u", ax0);
|
||||
"cpudev: activating already activated rframe: #%u", R(AX0));
|
||||
|
||||
rfs[ax0] = calloc(NREGS, sizeof(ulong));
|
||||
rfs[R(AX0)] = calloc(NREGS, sizeof(ulong));
|
||||
|
||||
if (rfs[ax0] == 0)
|
||||
if (rfs[R(AX0)] == 0)
|
||||
return -1;
|
||||
|
||||
rfs_used++;
|
||||
@ -93,13 +93,13 @@ long cpudev_activate(ctx_t *ctx, dev_t *dev)
|
||||
|
||||
long cpudev_deactivate(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
CHK_FRAME(ax0);
|
||||
CHK_FRAME(R(AX0));
|
||||
|
||||
if (ax0 == 0)
|
||||
if (R(AX0) == 0)
|
||||
_except(ctx, E_UDF, "cpudev: deactivating rframe #0");
|
||||
|
||||
free(rfs[ax0]);
|
||||
rfs[ax0] = NULL;
|
||||
free(rfs[R(AX0)]);
|
||||
rfs[R(AX0)] = NULL;
|
||||
|
||||
rfs_used--;
|
||||
assert(rfs_used > 0);
|
||||
@ -111,41 +111,41 @@ long cpudev_deactivate(ctx_t *ctx, dev_t *dev)
|
||||
|
||||
long cpudev_copyframe(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
CHK_FRAME(ax0);
|
||||
CHK_FRAME(ax1);
|
||||
CHK_FRAME(R(AX0));
|
||||
CHK_FRAME(R(AX1));
|
||||
|
||||
if (ax0 == ax1)
|
||||
if (R(AX0) == R(AX1))
|
||||
return -1;
|
||||
|
||||
memcpy(rfs[ax0], rfs[ax1], NREGS * sizeof(ulong));
|
||||
memcpy(rfs[R(AX0)], rfs[R(AX1)], NREGS * sizeof(ulong));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long cpudev_moveframe(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
CHK_INDEX(ax0);
|
||||
CHK_FRAME(ax1);
|
||||
CHK_INDEX(R(AX0));
|
||||
CHK_FRAME(R(AX1));
|
||||
|
||||
if (ax1 == 0)
|
||||
if (R(AX1) == 0)
|
||||
_except(ctx, E_UDF, "cpudev: trying to move frame #0");
|
||||
|
||||
if (rfs[ax0] != NULL)
|
||||
if (rfs[R(AX0)] != NULL)
|
||||
_except(ctx, E_UDF, "cpudev: trying to move frame #%u "
|
||||
"active frame #%u", ax1, ax0);
|
||||
"active frame #%u", R(AX1), R(AX0));
|
||||
|
||||
rfs[ax0] = rfs[ax1];
|
||||
rfs[ax1] = NULL;
|
||||
rfs[R(AX0)] = rfs[R(AX1)];
|
||||
rfs[R(AX1)] = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long cpudev_switchframe(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
CHK_FRAME(ax0);
|
||||
CHK_FRAME(R(AX0));
|
||||
|
||||
rfs_current_idx = ax0;
|
||||
ctx->rf = rfs[ax0];
|
||||
rfs_current_idx = R(AX0);
|
||||
ctx->rf = rfs[R(AX0)];
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -154,39 +154,39 @@ long cpudev_switchframe(ctx_t *ctx, dev_t *dev)
|
||||
|
||||
long cpudev_loadargs(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
CHK_FRAME(ax0);
|
||||
CHK_FRAME(R(AX0));
|
||||
|
||||
R(AX5) = rfs[ax0][AX5];
|
||||
R(AX4) = rfs[ax0][AX4];
|
||||
R(AX3) = rfs[ax0][AX3];
|
||||
R(AX2) = rfs[ax0][AX2];
|
||||
R(AX1) = rfs[ax0][AX1];
|
||||
R(AX0) = rfs[ax0][AX0];
|
||||
R(AX5) = rfs[R(AX0)][AX5];
|
||||
R(AX4) = rfs[R(AX0)][AX4];
|
||||
R(AX3) = rfs[R(AX0)][AX3];
|
||||
R(AX2) = rfs[R(AX0)][AX2];
|
||||
R(AX1) = rfs[R(AX0)][AX1];
|
||||
R(AX0) = rfs[R(AX0)][AX0];
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
long cpudev_loadreg(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
CHK_FRAME(ax0);
|
||||
CHK_FRAME(R(AX0));
|
||||
|
||||
if ((ushort)ax1 >= NREGS || ax1 == RZX)
|
||||
if ((ushort)R(AX1) >= NREGS || R(AX1) == RZX)
|
||||
_except(ctx, E_UDF,
|
||||
"cpudev: register invalid or index out of range: #%u", ax1);
|
||||
"cpudev: register invalid or index out of range: #%u", R(AX1));
|
||||
|
||||
R(RAX) = rfs[ax0][ax1];
|
||||
R(RAX) = rfs[R(AX0)][R(AX1)];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long cpudev_storereg(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
CHK_FRAME(ax0);
|
||||
CHK_FRAME(R(AX0));
|
||||
|
||||
if ((ushort)ax1 >= NREGS)
|
||||
_except(ctx, E_UDF, "cpudev: register index out of range: #%u", ax1);
|
||||
if ((ushort)R(AX1) >= NREGS)
|
||||
_except(ctx, E_UDF, "cpudev: register index out of range: #%u", R(AX1));
|
||||
|
||||
rfs[ax0][ax1] = R(AX2);
|
||||
rfs[R(AX0)][R(AX1)] = R(AX2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -204,40 +204,40 @@ bool idt_handling[IDT_SLOTS] = { 0 }; // a handler is already running
|
||||
|
||||
long cpudev_idtadd(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
CHK_FRAME(ax1);
|
||||
CHK_IDT_INDEX(ax0);
|
||||
CHK_FRAME(R(AX1));
|
||||
CHK_IDT_INDEX(R(AX0));
|
||||
|
||||
if (idt[ax0] != 0)
|
||||
_except(ctx, E_UDF, "cpudev: IDT slot index already in use: #%u", ax0);
|
||||
if (idt[R(AX0)] != 0)
|
||||
_except(ctx, E_UDF, "cpudev: IDT slot index already in use: #%u", R(AX0));
|
||||
|
||||
assert(idt_handling[ax0] == 0);
|
||||
assert(idt_handling[R(AX0)] == 0);
|
||||
|
||||
idt[ax0] = ax1;
|
||||
idt[R(AX0)] = R(AX1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long cpudev_idtdel(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
CHK_IDT_INDEX(ax0);
|
||||
CHK_IDT_INDEX(R(AX0));
|
||||
|
||||
if (idt[ax0] == 0)
|
||||
_except(ctx, E_UDF, "cpudev: IDT slot index not in use: #%u", ax0);
|
||||
if (idt[R(AX0)] == 0)
|
||||
_except(ctx, E_UDF, "cpudev: IDT slot index not in use: #%u", R(AX0));
|
||||
|
||||
idt[ax0] = 0;
|
||||
idt_handling[ax0] = 0;
|
||||
idt[R(AX0)] = 0;
|
||||
idt_handling[R(AX0)] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long cpudev_idtquery(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
if (ax0 >= IDT_SLOTS || idt[ax0] == 0)
|
||||
rax = rdx = 0;
|
||||
if (R(AX0) >= IDT_SLOTS || idt[R(AX0)] == 0)
|
||||
R(RAX) = R(RDX) = 0;
|
||||
|
||||
else {
|
||||
rax = 1;
|
||||
rdx = idt[ax0];
|
||||
R(RAX) = 1;
|
||||
R(RDX) = idt[R(AX0)];
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -245,12 +245,12 @@ long cpudev_idtquery(ctx_t *ctx, dev_t *dev)
|
||||
|
||||
long cpudev_idtdone(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
CHK_IDT_INDEX(ax0);
|
||||
CHK_IDT_INDEX(R(AX0));
|
||||
|
||||
if (idt_handling[ax0] == 0)
|
||||
_except(ctx, E_UDF, "cpudev: idtdone, not handling E/I #%u", ax0);
|
||||
if (idt_handling[R(AX0)] == 0)
|
||||
_except(ctx, E_UDF, "cpudev: idtdone, not handling E/I #%u", R(AX0));
|
||||
|
||||
idt_handling[ax0]--;
|
||||
idt_handling[R(AX0)]--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ long diskdev_findnext(ctx_t *ctx, dev_t *dev)
|
||||
|
||||
if (ent == NULL)
|
||||
{
|
||||
rax = 0;
|
||||
R(RAX) = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -51,18 +51,18 @@ long diskdev_findnext(ctx_t *ctx, dev_t *dev)
|
||||
break;
|
||||
}
|
||||
|
||||
rax = writestr(ctx, ax0, ax1, ent->d_name);
|
||||
R(RAX) = writestr(ctx, R(AX0), R(AX1), ent->d_name);
|
||||
|
||||
snprintf(name, NAME_MAX+4, "fs/%s", ent->d_name);
|
||||
|
||||
if (stat(name, &st) < 0)
|
||||
{
|
||||
perror("diskdev: couldn't stat file in directory: ");
|
||||
rdx = -1;
|
||||
R(RDX) = -1;
|
||||
}
|
||||
|
||||
else
|
||||
rdx = st.st_size;
|
||||
R(RDX) = st.st_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -85,7 +85,7 @@ long diskdev_open(ctx_t *ctx, dev_t *dev)
|
||||
int fd, tmp;
|
||||
char buf[NAME_MAX+4] = { 'f', 's', '/', 0 };
|
||||
|
||||
readstr(ctx, ax0, NAME_MAX, buf+3);
|
||||
readstr(ctx, R(AX0), NAME_MAX, buf+3);
|
||||
|
||||
for (fd = 0; fd < MAXOPEN; fd++)
|
||||
if (disk->table[fd] == 0)
|
||||
@ -103,7 +103,7 @@ long diskdev_open(ctx_t *ctx, dev_t *dev)
|
||||
}
|
||||
|
||||
disk->table[fd] = tmp;
|
||||
rax = fd;
|
||||
R(RAX) = fd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -112,13 +112,13 @@ long diskdev_close(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
GETDISK();
|
||||
|
||||
if (ax0 >= MAXOPEN)
|
||||
if (R(AX0) >= MAXOPEN)
|
||||
return -1;
|
||||
|
||||
if (disk->table[ax0] <= 0)
|
||||
if (disk->table[R(AX0)] <= 0)
|
||||
return -1;
|
||||
|
||||
close(disk->table[ax0]);
|
||||
close(disk->table[R(AX0)]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -129,7 +129,7 @@ long diskdev_read(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
GETDISK();
|
||||
|
||||
if (ax0 >= MAXOPEN || disk->table[ax0] <= 0 || R(AX2) >= MAXRW)
|
||||
if (R(AX0) >= MAXOPEN || disk->table[R(AX0)] <= 0 || R(AX2) >= MAXRW)
|
||||
return -1;
|
||||
|
||||
int ret;
|
||||
@ -138,7 +138,7 @@ long diskdev_read(ctx_t *ctx, dev_t *dev)
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
ret = read(disk->table[ax0], buf, R(AX2));
|
||||
ret = read(disk->table[R(AX0)], buf, R(AX2));
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
@ -146,12 +146,11 @@ long diskdev_read(ctx_t *ctx, dev_t *dev)
|
||||
return -1;
|
||||
}
|
||||
|
||||
rax = ret;
|
||||
R(RAX) = ret;
|
||||
|
||||
// Xxx dedicated function & faster copy
|
||||
for (; ret; ret--, ax1++, buf++)
|
||||
writemem(ctx, *buf, ax1, 1);
|
||||
|
||||
for (; ret; ret--, R(AX1)++, buf++)
|
||||
writemem(ctx, *buf, R(AX1), 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -5,14 +5,14 @@
|
||||
|
||||
long memdev_getmemoff(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
rax = MEMOFF;
|
||||
R(RAX) = MEMOFF;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long memdev_getmemsize(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
rax = ctx->mz;
|
||||
R(RAX) = ctx->mz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ sar r r ri
|
||||
#
|
||||
# CMP Comparison instruction
|
||||
#
|
||||
# $1 - $2
|
||||
# SignExtend($1) - $2
|
||||
#
|
||||
# Sets CF if unsigned integer overflow occur, clears it otherwise
|
||||
# Sets OF is signed integer overflow occur, clears it otherwise
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
include "SUPER"
|
||||
include "ALU"
|
||||
include "MOV"
|
||||
include "MEM"
|
||||
include "MISC"
|
||||
include "STRING"
|
||||
|
||||
|
@ -25,7 +25,7 @@ loop ri
|
||||
#
|
||||
# Conditional absolute jumps (B)
|
||||
#
|
||||
# COMPARE($1, $2)
|
||||
# COMPARE(SignExtend($1), $2)
|
||||
#
|
||||
# IF (COND) THEN
|
||||
# RIP = $3
|
||||
@ -114,28 +114,28 @@ pop r
|
||||
lea r m
|
||||
|
||||
#
|
||||
# Movement with sign-extension (MOV) instruction
|
||||
# Move data (MOV) instruction
|
||||
#
|
||||
# $1 = $2
|
||||
# $1 = SignExtend($2)
|
||||
#
|
||||
mov r rim
|
||||
mov m ri
|
||||
|
||||
#
|
||||
# Movement with sign-extension (MOVSXx) instruction
|
||||
# Load from memory with zero-extension (MOVSX/MOVZX) instruction
|
||||
#
|
||||
# $1 = ZeroExtend($2)
|
||||
#
|
||||
movzx r m
|
||||
|
||||
#
|
||||
# Move with sign-extension (MOVSXx) instruction
|
||||
#
|
||||
# $1 = SignExtend($2 & (2^(8 * sizeof(x)) - 1)
|
||||
#
|
||||
movsxb r r
|
||||
movsxw r r
|
||||
movsxl r r
|
||||
|
||||
#
|
||||
# Movement with zero-extension (MOVZX) instruction
|
||||
#
|
||||
# $1 = ZeroExtend($2)
|
||||
#
|
||||
movzx r m
|
||||
movsxd r r
|
||||
|
||||
#
|
||||
# Exchange (XCHG) instruction
|
@ -17,7 +17,7 @@
|
||||
#
|
||||
stosb r ri
|
||||
stosw r ri
|
||||
stosl r ri
|
||||
stosd r ri
|
||||
stosq r ri
|
||||
|
||||
#
|
||||
@ -44,7 +44,7 @@ stosq r ri
|
||||
#
|
||||
scasb r ri
|
||||
scasw r ri
|
||||
scasl r ri
|
||||
scasd r ri
|
||||
scasq r ri
|
||||
|
||||
#---------------------------------------------------------------------------#
|
||||
|
100
vm/in/alu.c
100
vm/in/alu.c
@ -8,47 +8,66 @@
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START_3(or) { v1 = v2 | v3; } IMPL_OUT;
|
||||
IMPL_START_3(and) { v1 = v2 & v3; } IMPL_OUT;
|
||||
IMPL_START_3(xor) { v1 = v2 ^ v3; } IMPL_OUT;
|
||||
IMPL_START(or) { *r1 = p2->val | p3->val; return 1; }
|
||||
IMPL_START(and) { *r1 = p2->val & p3->val; return 1; }
|
||||
IMPL_START(xor) { *r1 = p2->val ^ p3->val; return 1; }
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START_3(shl) { v1 = v2 << v3; } IMPL_OUT;
|
||||
IMPL_START_3(shr) { v1 = v2 >> v3; } IMPL_OUT;
|
||||
IMPL_START_3(sal) { v1 = (ulong)((long)v2 << (long)v3); } IMPL_OUT;
|
||||
IMPL_START_3(sar) { v1 = (ulong)((long)v2 >> (long)v3); } IMPL_OUT;
|
||||
IMPL_START(shl) { *r1 = p2->val << p3->val; return 1; }
|
||||
IMPL_START(shr) { *r1 = p2->val >> p3->val; return 1; }
|
||||
IMPL_START(sal) { *r1 = (ulong)((long)p2->val << (long)p3->val); return 1; }
|
||||
IMPL_START(sar) { *r1 = (ulong)((long)p2->val >> (long)p3->val); return 1; }
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START_3(add) { v1 = v2 + v3; } IMPL_OUT;
|
||||
IMPL_START_3(addf) { COMPARE_ADD(v2, v3); v1 = v2 + v3; } IMPL_OUT;
|
||||
IMPL_START(add) { *r1 = p2->val + p3->val; return 1; }
|
||||
IMPL_START(addf) { COMPARE_ADD(p2->val, p3->val); *r1 = p2->val + p3->val; return 1; }
|
||||
|
||||
IMPL_START(sub) { *r1 = p2->val - p3->val; return 1; }
|
||||
IMPL_START(subf) { COMPARE_SUB(p2->val, p3->val); *r1 = p2->val - p3->val; return 1; }
|
||||
|
||||
IMPL_START(adcx)
|
||||
{
|
||||
p3->val += !!(R(RFX)&CF);
|
||||
COMPARE_ADD(p2->val, p3->val);
|
||||
*r1 = p2->val + p3->val;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
IMPL_START(sbbx)
|
||||
{
|
||||
p3->val += !!(R(RFX)&CF);
|
||||
COMPARE_SUB(p2->val, p3->val);
|
||||
*r1 = p2->val - p3->val;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START_2(cmp) { COMPARE_SUB(v1, v2); } IMPL_END;
|
||||
IMPL_START_3(sub) { v1 = v2 - v3; } IMPL_OUT;
|
||||
IMPL_START_3(subf){ COMPARE_SUB(v2, v3); v1 = v2 - v3; } IMPL_OUT;
|
||||
IMPL_START(mul) { *r1 = p2->val * p3->val; return 1; }
|
||||
IMPL_START(rem) { *r1 = p2->val % p3->val; return 1; }
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START_3(adcx) { v3 += !!(R(RFX)&CF); COMPARE_ADD(v2, v3); v1 = v2 + v3; } IMPL_OUT;
|
||||
IMPL_START_3(sbbx) { v3 += !!(R(RFX)&CF); COMPARE_SUB(v2, v3); v1 = v2 - v3; } IMPL_OUT;
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START_3(mul) { v1 = v2 * v3; } IMPL_OUT;
|
||||
IMPL_START_3(rem) { v1 = v2 % v3; } IMPL_OUT;
|
||||
IMPL_START_3(div) {
|
||||
if (!v3)
|
||||
IMPL_START(div)
|
||||
{
|
||||
if (!p3->val)
|
||||
_except(ctx, E_DIV, "DIV by 0");
|
||||
v1 = v2 / v3;
|
||||
} IMPL_OUT;
|
||||
IMPL_START_3(idiv) {
|
||||
if (!v3)
|
||||
*r1 = p2->val / p3->val;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
IMPL_START(idiv)
|
||||
{
|
||||
if (!p3->val)
|
||||
_except(ctx, E_DIV, "IDIV by 0");
|
||||
v1 = (ulong)((long)v2/(long)v3);
|
||||
} IMPL_OUT;
|
||||
|
||||
*r1 = (ulong)((long)p2->val/(long)p3->val);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
@ -60,13 +79,20 @@ static void __unsigned_multiply128(ulong u, ulong v, ulong *hi, ulong *lo)
|
||||
*lo = r;
|
||||
}
|
||||
|
||||
IMPL_START_3(mulhi) { __unsigned_multiply128(v2, v3, &v1, &v2); } IMPL_OUT_2;
|
||||
IMPL_START(mulhi)
|
||||
{
|
||||
__unsigned_multiply128(p2->val, p3->val, r1, r2);
|
||||
return 2;
|
||||
}
|
||||
|
||||
IMPL_START_3(mulf) {
|
||||
IMPL_START(mulf)
|
||||
{
|
||||
ulong tmp;
|
||||
__unsigned_multiply128(v2, v3, &tmp, &v1);
|
||||
R(RFX) = v2 ? (R(RFX)|CF|OF) : R(RFX)&~(CF|OF);
|
||||
} IMPL_OUT;
|
||||
__unsigned_multiply128(p2->val, p3->val, &tmp, r1);
|
||||
R(RFX) = p2->val ? (R(RFX)|CF|OF) : R(RFX)&~(CF|OF);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
@ -78,7 +104,11 @@ static void __signed_multiply128(ulong u, ulong v, ulong *hi, ulong *lo)
|
||||
*lo = r;
|
||||
}
|
||||
|
||||
IMPL_START_3(imulhi) { __signed_multiply128(v2, v3, &v1, &v2); } IMPL_OUT_2;
|
||||
IMPL_START(imulhi)
|
||||
{
|
||||
__signed_multiply128(p2->val, p3->val, r1, r2);
|
||||
return 2;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
|
@ -5,80 +5,9 @@
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#define DECV(v, p) \
|
||||
ulong v; \
|
||||
GETV(v, p)
|
||||
|
||||
#define GETV(v, p) \
|
||||
if (ACC_FMT_IS_MEM(p->type)) \
|
||||
v = readmem(ctx, p->addr, p->mlen); \
|
||||
else v = p->val
|
||||
|
||||
#define DECVZX(v, p) \
|
||||
ulong v; \
|
||||
GETVZX(v, p)
|
||||
|
||||
#define GETVZX(v, p) \
|
||||
if (ACC_FMT_IS_MEM(p->type)) \
|
||||
v = readmemzx(ctx, p->addr, p->mlen); \
|
||||
else v = p->val
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#define IMPL_START_0(name) \
|
||||
#define IMPL_START(name) \
|
||||
uint i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, acc_t *p3, \
|
||||
ulong *r1, ulong *r2, ulong *r3) \
|
||||
{
|
||||
|
||||
#define IMPL_START_1(name) \
|
||||
IMPL_START_0(name) \
|
||||
DECV(v1, p1);
|
||||
|
||||
#define IMPL_START_X_NOIN(name) \
|
||||
IMPL_START_0(name) \
|
||||
ulong v1, v2, v3; \
|
||||
(void)v1; (void)v2; (void)v3;
|
||||
|
||||
#define IMPL_START_2(name) \
|
||||
IMPL_START_1(name) \
|
||||
DECV(v2, p2);
|
||||
|
||||
#define IMPL_START_2_ONLY(name) \
|
||||
IMPL_START_0(name) \
|
||||
ulong v1; \
|
||||
DECV(v2, p2);
|
||||
|
||||
#define IMPL_START_3(name) \
|
||||
IMPL_START_2(name) \
|
||||
DECV(v3, p3);
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#define IMPL_END \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define IMPL_OUT \
|
||||
*r1 = v1; \
|
||||
return 1; \
|
||||
}
|
||||
|
||||
#define IMPL_OUT_ZSF \
|
||||
SET_ZSF(v1); \
|
||||
IMPL_OUT
|
||||
|
||||
#define IMPL_OUT_2 \
|
||||
*r1 = v1; \
|
||||
*r2 = v2; \
|
||||
return 2; \
|
||||
}
|
||||
|
||||
#define IMPL_OUT_3 \
|
||||
*r1 = v1; \
|
||||
*r2 = v2; \
|
||||
*r3 = v3; \
|
||||
return 3; \
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
@ -100,11 +29,6 @@ IMPL_START_2(name) \
|
||||
SET_ZF(v); \
|
||||
SET_SF(v)
|
||||
|
||||
#define SET_ZSPF(v) \
|
||||
SET_ZF(v); \
|
||||
SET_SF(v); \
|
||||
SET_PF(v)
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#define COMPARE_ADD(v1, v2) \
|
||||
|
166
vm/in/mem.c
Normal file
166
vm/in/mem.c
Normal file
@ -0,0 +1,166 @@
|
||||
// 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 <in/instrs.h>
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START(jmp) { R(RIP) = p1->val; return 0; }
|
||||
|
||||
IMPL_START(loop) {
|
||||
if (R(RCX) > 0) {
|
||||
R(RCX)--;
|
||||
R(RIP) = p1->val;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
IMPL_START(b)
|
||||
{
|
||||
ulong v;
|
||||
|
||||
if (ACC_FMT_IS_MEM(p1->type))
|
||||
v = readmemsx(ctx, p1->addr, p1->mlen);
|
||||
|
||||
else v = p1->val;
|
||||
|
||||
COMPARE_SUB(v, p2->val);
|
||||
|
||||
if (eval_cond(ctx, ctx->cond))
|
||||
R(RIP) = p3->val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
IMPL_START(cmp)
|
||||
{
|
||||
ulong v;
|
||||
|
||||
if (ACC_FMT_IS_MEM(p1->type))
|
||||
v = readmemsx(ctx, p1->addr, p1->mlen);
|
||||
|
||||
else v = p1->val;
|
||||
|
||||
COMPARE_SUB(v, p2->val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START(lea) { *r1 = p2->addr; return 1; }
|
||||
|
||||
IMPL_START(mov)
|
||||
{
|
||||
if (ACC_FMT_IS_MEM(p2->type))
|
||||
*r1 = readmemsx(ctx, p2->addr, p2->mlen);
|
||||
|
||||
else *r1 = p2->val;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
IMPL_START(movzx)
|
||||
{
|
||||
if (ACC_FMT_IS_MEM(p2->type))
|
||||
{
|
||||
if (__builtin_expect(p2->mlen == 8, 0))
|
||||
_except(ctx, E_ILL, "MOVZX with qword memory source");
|
||||
|
||||
*r1 = readmemzx(ctx, p2->addr, p2->mlen);
|
||||
}
|
||||
|
||||
else *r1 = p2->val;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
IMPL_START(movsxb) { *r1 = (ulong)(long)(char)(p2->val & 0xFF); return 1; }
|
||||
IMPL_START(movsxw) { *r1 = (ulong)(long)(short)(p2->val & 0xFFFF); return 1; }
|
||||
IMPL_START(movsxd) { *r1 = (ulong)(long)(int)(p2->val & 0xFFFFFFFF); return 1; }
|
||||
|
||||
IMPL_START(xchg)
|
||||
{
|
||||
*r2 = p1->val;
|
||||
|
||||
if (ACC_FMT_IS_MEM(p2->type))
|
||||
*r1 = readmemsx(ctx, p2->addr, p2->mlen);
|
||||
|
||||
else *r1 = p2->val;
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
//
|
||||
// Stack manipulation instructions
|
||||
//
|
||||
|
||||
IMPL_START(push)
|
||||
{
|
||||
ulong v;
|
||||
|
||||
if (ACC_FMT_IS_MEM(p1->type))
|
||||
v = readmemzx(ctx, p1->addr, p1->mlen);
|
||||
|
||||
else v = p1->val;
|
||||
|
||||
R(RSP) -= 8;
|
||||
writemem(ctx, v, R(RSP), 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
IMPL_START(pop)
|
||||
{
|
||||
*r1 = readmemzx(ctx, R(RSP), 8);
|
||||
R(RSP) += 8;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
IMPL_START(call)
|
||||
{
|
||||
R(RSP) -= 8;
|
||||
writemem(ctx, R(RIP), R(RSP), 8);
|
||||
R(RIP) = p1->val;
|
||||
|
||||
if (p2)
|
||||
{
|
||||
R(AX0) = p2->val;
|
||||
|
||||
if (p3)
|
||||
R(AX1) = p3->val;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
IMPL_START(ret)
|
||||
{
|
||||
R(RIP) = readmemzx(ctx, R(RSP), 8);
|
||||
R(RSP) += 8;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
IMPL_START(enter)
|
||||
{
|
||||
writemem(ctx, R(RBP), R(RSP) - 8, 8);
|
||||
R(RBP) = R(RSP) - 8;
|
||||
R(RSP) -= (p1->val + 1) * 8;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
IMPL_START(leave)
|
||||
{
|
||||
R(RSP) = R(RBP) + 8;
|
||||
R(RBP) = readmemzx(ctx, R(RBP), 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
135
vm/in/misc.c
135
vm/in/misc.c
@ -9,12 +9,12 @@
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START_0(into) { INTO(); } IMPL_END;
|
||||
IMPL_START_0(pause) { usleep(5000); } IMPL_END;
|
||||
IMPL_START(into) { INTO(); return 0; }
|
||||
IMPL_START(pause) { usleep(5000); return 0; }
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START_0(break)
|
||||
IMPL_START(break)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
trace("\nExecuting BREAK INSTR\n");
|
||||
@ -24,107 +24,116 @@ IMPL_START_0(break)
|
||||
|
||||
trace("Resuming execution\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
IMPL_END;
|
||||
|
||||
IMPL_START_0(dump)
|
||||
IMPL_START(dump)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (ctx->dumpsw)
|
||||
trace("0x%lX:\t...\n", rpc);
|
||||
trace("0x%lX:\t...\n", ctx->cur_pc);
|
||||
|
||||
else if (!ctx->dumpsw)
|
||||
dump_instr(ctx, ctx->cur_in, p1, p2, p3, 0, 0);
|
||||
|
||||
ctx->dumpsw = !ctx->dumpsw;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
IMPL_END;
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START_X_NOIN(ytime)
|
||||
IMPL_START(ytime)
|
||||
{
|
||||
time_t t = time(NULL);
|
||||
struct tm *tm = localtime(&t);
|
||||
|
||||
v1 = tm->tm_sec + tm->tm_min * 60
|
||||
*r1 = tm->tm_sec + tm->tm_min * 60
|
||||
+ tm->tm_hour * 60 * 60
|
||||
+ tm->tm_mday * 60 * 60 * 24;
|
||||
|
||||
v2 = tm->tm_mon;
|
||||
v3 = tm->tm_year + 1900;
|
||||
}
|
||||
IMPL_OUT_3;
|
||||
*r2 = tm->tm_mon;
|
||||
*r3 = tm->tm_year + 1900;
|
||||
|
||||
IMPL_START_1(utime)
|
||||
return 3;
|
||||
}
|
||||
|
||||
IMPL_START(utime)
|
||||
{
|
||||
struct timeval time;
|
||||
gettimeofday(&time, NULL);
|
||||
v1 = (time.tv_sec * 1000) + (time.tv_usec / 1000);
|
||||
*r1 = (time.tv_sec * 1000) + (time.tv_usec / 1000);
|
||||
|
||||
return 1;
|
||||
}
|
||||
IMPL_OUT;
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START_0(cls) {
|
||||
IMPL_START(cls)
|
||||
{
|
||||
R(RFX) = 0;
|
||||
for (int i = RAX; i <= R20; i++) R(i) = 0;
|
||||
} IMPL_END;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START_2(bswap)
|
||||
IMPL_START(bswap)
|
||||
{
|
||||
v1 = ((v2 & 0xFF00000000000000) >> 56)
|
||||
| ((v2 & 0x00FF000000000000) >> 40)
|
||||
| ((v2 & 0x0000FF0000000000) >> 24)
|
||||
| ((v2 & 0x000000FF00000000) >> 8)
|
||||
| ((v2 & 0x00000000FF000000) << 8)
|
||||
| ((v2 & 0x0000000000FF0000) << 24)
|
||||
| ((v2 & 0x000000000000FF00) << 40)
|
||||
| ((v2 & 0x00000000000000FF) << 56);
|
||||
}
|
||||
IMPL_OUT;
|
||||
ulong v = p2->val;
|
||||
|
||||
IMPL_START_2(wswap)
|
||||
{
|
||||
v1 = ((v2 & 0xFFFF000000000000) >> 48)
|
||||
| ((v2 & 0x0000FFFF00000000) >> 16)
|
||||
| ((v2 & 0x00000000FFFF0000) << 16)
|
||||
| ((v2 & 0x000000000000FFFF) << 48);
|
||||
}
|
||||
IMPL_OUT;
|
||||
*r1 = ((v & 0xFF00000000000000) >> 56)
|
||||
| ((v & 0x00FF000000000000) >> 40)
|
||||
| ((v & 0x0000FF0000000000) >> 24)
|
||||
| ((v & 0x000000FF00000000) >> 8)
|
||||
| ((v & 0x00000000FF000000) << 8)
|
||||
| ((v & 0x0000000000FF0000) << 24)
|
||||
| ((v & 0x000000000000FF00) << 40)
|
||||
| ((v & 0x00000000000000FF) << 56);
|
||||
|
||||
IMPL_START_2(dswap)
|
||||
{
|
||||
v1 = ((v2 & 0xFFFFFFFF00000000) >> 32)
|
||||
| ((v2 & 0x00000000FFFFFFFF) << 32);
|
||||
return 1;
|
||||
}
|
||||
|
||||
IMPL_START(wswap)
|
||||
{
|
||||
ulong v = p2->val;
|
||||
|
||||
*r1 = ((v & 0xFFFF000000000000) >> 48)
|
||||
| ((v & 0x0000FFFF00000000) >> 16)
|
||||
| ((v & 0x00000000FFFF0000) << 16)
|
||||
| ((v & 0x000000000000FFFF) << 48);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
IMPL_START(dswap)
|
||||
{
|
||||
*r1 = ((p2->val & 0xFFFFFFFF00000000) >> 32)
|
||||
| ((p2->val & 0x00000000FFFFFFFF) << 32);
|
||||
|
||||
return 1;
|
||||
}
|
||||
IMPL_OUT;
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START_0(prn)
|
||||
#define PRN_CLEAR_MAGIC 0x8BF00001
|
||||
|
||||
IMPL_START(prn)
|
||||
{
|
||||
DECVZX(v1, p1);
|
||||
ulong v = p1->val;
|
||||
|
||||
// Magic value? :)
|
||||
if (__builtin_expect(v1 == 0xC15000AF, 0))
|
||||
if (__builtin_expect(v == PRN_CLEAR_MAGIC, 0))
|
||||
console_clear(ctx);
|
||||
|
||||
else
|
||||
{
|
||||
if (p1->mlen > 1) {
|
||||
trace("prn warning: large access size\n");
|
||||
}
|
||||
if (v1 > 0)
|
||||
console_putc(ctx, (char)v1);
|
||||
}
|
||||
}
|
||||
IMPL_END
|
||||
else if (v > 0)
|
||||
console_putc(ctx, (char)v);
|
||||
|
||||
IMPL_START_0(prns)
|
||||
return 0;
|
||||
}
|
||||
|
||||
IMPL_START(prns)
|
||||
{
|
||||
uchar ch = readmemzx(ctx, R(p1->reg), 1);
|
||||
|
||||
@ -139,14 +148,16 @@ IMPL_START_0(prns)
|
||||
else
|
||||
R(p1->reg)++;
|
||||
}
|
||||
}
|
||||
IMPL_END
|
||||
|
||||
IMPL_START_X_NOIN(scan)
|
||||
{
|
||||
v1 = console_scankeybuf(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
IMPL_START(scan)
|
||||
{
|
||||
*r1 = console_scankeybuf(ctx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
IMPL_OUT;
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
|
97
vm/in/mov.c
97
vm/in/mov.c
@ -1,97 +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.
|
||||
|
||||
#include <in/instrs.h>
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START_1(jmp) { R(RIP) = v1; } IMPL_END;
|
||||
IMPL_START_1(loop) {
|
||||
if (R(RCX) > 0) {
|
||||
R(RCX)--;
|
||||
R(RIP) = v1;
|
||||
}
|
||||
}
|
||||
IMPL_END;
|
||||
|
||||
IMPL_START_3(b) {
|
||||
COMPARE_SUB(v1, v2);
|
||||
|
||||
if (eval_cond(ctx, ctx->cond))
|
||||
R(RIP) = v3;
|
||||
}
|
||||
IMPL_END;
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START_X_NOIN(lea) { v1 = p2->addr; } IMPL_OUT;
|
||||
IMPL_START_2_ONLY(mov) { v1 = v2; } IMPL_OUT;
|
||||
|
||||
IMPL_START_2_ONLY(movsxb) { v1 = (ulong)(long)(char)(v2 & 0xFF); }IMPL_OUT;
|
||||
IMPL_START_2_ONLY(movsxw) { v1 = (ulong)(long)(short)(v2 & 0xFFFF); }IMPL_OUT;
|
||||
IMPL_START_2_ONLY(movsxl) { v1 = (ulong)(long)(int)(v2 & 0xFFFFFFFF); }IMPL_OUT;
|
||||
|
||||
IMPL_START_X_NOIN(movzx) { DECVZX(v2, p2); v1 = v2; } IMPL_OUT;
|
||||
|
||||
IMPL_START_2(xchg) { ulong t = v1; v1 = v2; v2 = t; } IMPL_OUT_2;
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
//
|
||||
// Stack manipulation instructions
|
||||
//
|
||||
|
||||
IMPL_START_1(push) {
|
||||
R(RSP) -= 8;
|
||||
writemem(ctx, v1, R(RSP), 8);
|
||||
} IMPL_END;
|
||||
|
||||
IMPL_START_1(pop) {
|
||||
v1 = readmem(ctx, R(RSP), 8);
|
||||
R(RSP) += 8;
|
||||
} IMPL_OUT;
|
||||
|
||||
/*
|
||||
IMPL_START_1(call) {
|
||||
R(RSP) -= 8;
|
||||
writemem(ctx, R(RIP), R(RSP), 8);
|
||||
R(RIP) = v1;
|
||||
} IMPL_END;
|
||||
*/
|
||||
|
||||
IMPL_START_1(call) {
|
||||
R(RSP) -= 8;
|
||||
writemem(ctx, R(RIP), R(RSP), 8);
|
||||
R(RIP) = v1;
|
||||
|
||||
if (p2)
|
||||
{
|
||||
DECV(v2, p2);
|
||||
ax0 = v2;
|
||||
|
||||
if (p3)
|
||||
{
|
||||
DECV(v3, p3);
|
||||
ax1 = v3;
|
||||
}
|
||||
}
|
||||
|
||||
} IMPL_END;
|
||||
|
||||
IMPL_START_0(ret) {
|
||||
R(RIP) = readmem(ctx, R(RSP), 8); R(RSP) += 8;
|
||||
} IMPL_END;
|
||||
|
||||
IMPL_START_1(enter) {
|
||||
writemem(ctx, R(RBP), R(RSP) - 8, 8);
|
||||
R(RBP) = R(RSP) - 8;
|
||||
R(RSP) -= (v1 + 1) * 8;
|
||||
} IMPL_END;
|
||||
|
||||
IMPL_START_0(leave) {
|
||||
R(RSP) = R(RBP) + 8;
|
||||
R(RBP) = readmem(ctx, R(RBP), 8);
|
||||
} IMPL_END;
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
@ -13,24 +13,21 @@
|
||||
|
||||
static void stos_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len)
|
||||
{
|
||||
DECV(v2, p2);
|
||||
writemem(ctx, v2, R(p1->reg), len);
|
||||
writemem(ctx, p2->val, R(p1->reg), len);
|
||||
STR_MOVE(p1->reg, len);
|
||||
}
|
||||
|
||||
IMPL_START_0(stosb) { stos_impl(ctx, p1, p2, 1); } IMPL_END;
|
||||
IMPL_START_0(stosw) { stos_impl(ctx, p1, p2, 2); } IMPL_END;
|
||||
IMPL_START_0(stosl) { stos_impl(ctx, p1, p2, 4); } IMPL_END;
|
||||
IMPL_START_0(stosq) { stos_impl(ctx, p1, p2, 8); } IMPL_END;
|
||||
IMPL_START(stosb) { stos_impl(ctx, p1, p2, 1); return 0; }
|
||||
IMPL_START(stosw) { stos_impl(ctx, p1, p2, 2); return 0; }
|
||||
IMPL_START(stosd) { stos_impl(ctx, p1, p2, 4); return 0; }
|
||||
IMPL_START(stosq) { stos_impl(ctx, p1, p2, 8); return 0; }
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
static void scas_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len)
|
||||
{
|
||||
DECV(v2, p2);
|
||||
|
||||
ulong x = readmem(ctx, R(p1->reg), len);
|
||||
COMPARE_SUB(x, v2);
|
||||
ulong x = readmemsx(ctx, R(p1->reg), len);
|
||||
COMPARE_SUB(x, p2->val);
|
||||
|
||||
if (x == 0) {
|
||||
R(RFX) |= ZF;
|
||||
@ -41,28 +38,10 @@ static void scas_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len)
|
||||
}
|
||||
}
|
||||
|
||||
IMPL_START_0(scasb) { scas_impl(ctx, p1, p2, 1); } IMPL_END;
|
||||
IMPL_START_0(scasw) { scas_impl(ctx, p1, p2, 2); } IMPL_END;
|
||||
IMPL_START_0(scasl) { scas_impl(ctx, p1, p2, 4); } IMPL_END;
|
||||
IMPL_START_0(scasq) { scas_impl(ctx, p1, p2, 8); } IMPL_END;
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
static void movs_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len)
|
||||
{
|
||||
ulong x = readmem(ctx, R(p2->reg), len);
|
||||
writemem(ctx, x, R(p1->reg), len);
|
||||
|
||||
R(RFX) = (x == 0 ? R(RFX)|ZF : R(RFX)&~ZF);
|
||||
|
||||
STR_MOVE(p1->reg, len);
|
||||
STR_MOVE(p2->reg, len);
|
||||
}
|
||||
|
||||
IMPL_START_0(movsb) { movs_impl(ctx, p1, p2, 1); } IMPL_END;
|
||||
IMPL_START_0(movsw) { movs_impl(ctx, p1, p2, 2); } IMPL_END;
|
||||
IMPL_START_0(movsl) { movs_impl(ctx, p1, p2, 4); } IMPL_END;
|
||||
IMPL_START_0(movsq) { movs_impl(ctx, p1, p2, 8); } IMPL_END;
|
||||
IMPL_START(scasb) { scas_impl(ctx, p1, p2, 1); return 0; }
|
||||
IMPL_START(scasw) { scas_impl(ctx, p1, p2, 2); return 0; }
|
||||
IMPL_START(scasd) { scas_impl(ctx, p1, p2, 4); return 0; }
|
||||
IMPL_START(scasq) { scas_impl(ctx, p1, p2, 8); return 0; }
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
|
@ -31,19 +31,20 @@ void do_hlt(ctx_t *ctx)
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START_0(hlt) { CHK_SUPERV(); do_hlt(ctx); } IMPL_END;
|
||||
IMPL_START_0(stop) { CHK_SUPERV(); _except(ctx, E_SHT, "STOP INSTR"); } IMPL_END;
|
||||
IMPL_START_0(crash) { CHK_SUPERV(); _except(ctx, 1023, "CRASH instruction"); } IMPL_END;
|
||||
IMPL_START(hlt) { CHK_SUPERV(); do_hlt(ctx); return 0; }
|
||||
IMPL_START(stop) { CHK_SUPERV(); _except(ctx, E_SHT, "STOP INSTR"); }
|
||||
IMPL_START(crash) { CHK_SUPERV(); _except(ctx, 1023, "CRASH instruction"); }
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START_1(trap) {
|
||||
if (v1 > 255) _except(ctx, E_ILL, "TRAP number greater than 255");
|
||||
_except(ctx, v1 + 256, "TRAP instruction");
|
||||
} IMPL_END;
|
||||
IMPL_START(trap)
|
||||
{
|
||||
if (p1->val > 255) _except(ctx, E_ILL, "TRAP number greater than 255");
|
||||
_except(ctx, p1->val + 256, "TRAP instruction");
|
||||
}
|
||||
|
||||
|
||||
IMPL_START_0(iret) {
|
||||
IMPL_START(iret) {
|
||||
if (ctx->dumpsw)
|
||||
trace("\nReturning from exception #%ld\n\n", R(R13));
|
||||
|
||||
@ -51,66 +52,69 @@ IMPL_START_0(iret) {
|
||||
R(RIP) = R(R15);
|
||||
rfs_current_idx = R(R14);
|
||||
ctx->rf = rfs[R(R14)];
|
||||
}
|
||||
IMPL_END;
|
||||
|
||||
IMPL_START_0(cli) { CHK_SUPERV(); R(CR0) &= ~IF; } IMPL_END;
|
||||
IMPL_START_0(sti) { CHK_SUPERV(); R(CR0) |= IF; } IMPL_END;
|
||||
return 0;
|
||||
}
|
||||
|
||||
IMPL_START(cli) { CHK_SUPERV(); R(CR0) &= ~IF; return 0; }
|
||||
IMPL_START(sti) { CHK_SUPERV(); R(CR0) |= IF; return 0; }
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
//
|
||||
// code common to devctl and iocall
|
||||
//
|
||||
dev_t *devctl_common(ctx_t *ctx, ulong v1, ulong v2)
|
||||
dev_t *devctl_common(ctx_t *ctx, ulong idx)
|
||||
{
|
||||
dev_t *dev = devget(ctx, v1);
|
||||
dev_t *dev = devget(ctx, idx);
|
||||
|
||||
if (!dev) rax = -2;
|
||||
else if (dev->state == DEVPWOF) rax = -3;
|
||||
else if (dev->state == DEVFERR) rax = -4;
|
||||
else if (dev->state == DEVPLUG) rax = -5;
|
||||
if (!dev) R(RAX) = -2;
|
||||
else if (dev->state == DEVPWOF) R(RAX) = -3;
|
||||
else if (dev->state == DEVFERR) R(RAX) = -4;
|
||||
else if (dev->state == DEVPLUG) R(RAX) = -5;
|
||||
else return dev;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IMPL_START_2(devctl)
|
||||
IMPL_START(devctl)
|
||||
{
|
||||
CHK_SUPERV();
|
||||
|
||||
dev_t *dev = devctl_common(ctx, v1, v2);
|
||||
dev_t *dev = devctl_common(ctx, p1->val);
|
||||
|
||||
if (dev == NULL)
|
||||
return 0;
|
||||
|
||||
switch (v2) {
|
||||
case 0: writestr(ctx, ax0, DEVLEN, dev->type); break;
|
||||
case 1: writestr(ctx, ax0, DEVLEN, dev->name); break;
|
||||
case 2: writestr(ctx, ax0, DEVLEN, dev->modl); break;
|
||||
case 3: writestr(ctx, ax0, DEVLEN, dev->vend); break;
|
||||
case 4: rax = dev->major; rdx = dev->minor; break;
|
||||
case 5: rax = dev->feats; rdx = dev->revis; break;
|
||||
default: rax = -6; break;
|
||||
switch (p2->val) {
|
||||
case 0: writestr(ctx, R(AX0), DEVLEN, dev->type); break;
|
||||
case 1: writestr(ctx, R(AX0), DEVLEN, dev->name); break;
|
||||
case 2: writestr(ctx, R(AX0), DEVLEN, dev->modl); break;
|
||||
case 3: writestr(ctx, R(AX0), DEVLEN, dev->vend); break;
|
||||
case 4: R(RAX) = dev->major; R(RDX) = dev->minor; break;
|
||||
case 5: R(RAX) = dev->feats; R(RDX) = dev->revis; break;
|
||||
default: R(RAX) = -6; break;
|
||||
}
|
||||
}
|
||||
IMPL_END;
|
||||
|
||||
IMPL_START_2(iocall)
|
||||
return 0;
|
||||
}
|
||||
|
||||
IMPL_START(iocall)
|
||||
{
|
||||
CHK_SUPERV();
|
||||
|
||||
long rc;
|
||||
dev_t *dev = devctl_common(ctx, v1, v2);
|
||||
dev_t *dev = devctl_common(ctx, p1->val);
|
||||
|
||||
if (dev == NULL) return 0;
|
||||
else if (v2 >= DEVSLOTS || dev->fslots[v2] == NULL) rax = -6;
|
||||
else if (p2->val >= DEVSLOTS || dev->fslots[p2->val] == NULL) R(RAX) = -6;
|
||||
|
||||
else {
|
||||
rc = dev->fslots[v2](ctx, dev);
|
||||
if (rc < 0) { rax = rc; rdx = 0; }
|
||||
rc = dev->fslots[p2->val](ctx, dev);
|
||||
if (rc < 0) { R(RAX) = rc; R(RDX) = 0; }
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
IMPL_END;
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
|
47
vm/pc/DECD
47
vm/pc/DECD
@ -3,19 +3,26 @@
|
||||
|
||||
Instruction encoding:
|
||||
|
||||
15 0 15 0
|
||||
xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
|
||||
│││└───────────┘ │└───┘└───┘└───┘
|
||||
│││ INSTR. │ FT3 FT2 FT1
|
||||
│││ │
|
||||
LMC R
|
||||
Byte 1: Instruction number
|
||||
Byte 2:
|
||||
xx0xxxxx
|
||||
|| └───┘
|
||||
RL CND
|
||||
|
||||
M No more words
|
||||
C COND suffix
|
||||
L LOCK suffix
|
||||
R REP suffix
|
||||
FT1 First operand format
|
||||
FT2 Second operand format
|
||||
Values for ModRMs:
|
||||
000xxxxx xxxxx = reg
|
||||
|
||||
(for memory accesses, xxxxx = access size)
|
||||
001xxxxx [reg]
|
||||
010xxxxx [reg+reg]
|
||||
011xxxxx [reg+reg+imm16]
|
||||
100xxxxx [reg+reg+imm32]
|
||||
101xxxxx [reg+reg*imm8+imm32]
|
||||
110xxxxx [reg+imm64]
|
||||
11100001 imm8 (zero extended)
|
||||
11100010 imm16 (zero extended)
|
||||
11100100 imm32 (zero extended)
|
||||
11101000 imm64 (zero extended)
|
||||
|
||||
Values for COND:
|
||||
00000 (none)
|
||||
@ -33,19 +40,3 @@ Values for COND:
|
||||
01100 .DXZ
|
||||
Highest (6th) bit of COND indicates negation
|
||||
|
||||
Fx values:
|
||||
00000 (none)
|
||||
00001 reg
|
||||
00010 imm64
|
||||
|
||||
xxx00 [imm64]
|
||||
xxx01 [reg+reg] code(reg)|code(reg)
|
||||
xxx10 [reg+reg+imm16] code(reg)|code(reg) imm16
|
||||
xxx11 [reg+reg*imm16+imm16] code(reg)|code(reg) imm16 imm16
|
||||
|
||||
Where xxx is:
|
||||
001 8-bit access
|
||||
010 16-bit access
|
||||
011 32-bit access
|
||||
100 64-bit access
|
||||
|
||||
|
@ -62,12 +62,9 @@ struct ctx_t
|
||||
ulong cur_pc;
|
||||
|
||||
// Memory and memory size
|
||||
ushort *mp;
|
||||
uchar *mp;
|
||||
ulong mz;
|
||||
|
||||
// Read next instruction
|
||||
ushort (*get)(ctx_t *ctx);
|
||||
|
||||
// Devices list head
|
||||
dev_t *dh;
|
||||
|
||||
|
307
vm/pc/decode.c
307
vm/pc/decode.c
@ -7,24 +7,40 @@
|
||||
// Read the "DECD" file before reading this code
|
||||
//
|
||||
|
||||
static void check_param_type(ctx_t *ctx, instr_t *in,
|
||||
uint prm, uchar fmt, int which)
|
||||
//
|
||||
// Instruction fetch
|
||||
//
|
||||
|
||||
static uchar fetchb(ctx_t *ctx)
|
||||
{
|
||||
bool ok;
|
||||
uchar v = *(ctx->mp + R(RIP) + R(CR1) - MEMOFF);
|
||||
R(RIP) += 1;
|
||||
|
||||
if (prm == P_REG)
|
||||
ok = (fmt == A_REG);
|
||||
return v;
|
||||
}
|
||||
|
||||
else if (prm == P_IMM)
|
||||
ok = (fmt == A_IMM64);
|
||||
static ushort fetchw(ctx_t *ctx)
|
||||
{
|
||||
ushort v = *(ushort *)(ctx->mp + R(RIP) + R(CR1) - MEMOFF);
|
||||
R(RIP) += 2;
|
||||
|
||||
else /* if (prm == P_MEM) */
|
||||
ok = ACC_FMT_IS_MEM(fmt);
|
||||
return v;
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
_except(ctx, E_ILL,
|
||||
"FT%d not matching %s's expected parameter types: "
|
||||
"fmt=0x%x prm=0x%x", which, in->full, fmt, prm);
|
||||
static uint fetchd(ctx_t *ctx)
|
||||
{
|
||||
uint v = *(uint *)(ctx->mp + R(RIP) + R(CR1) - MEMOFF);
|
||||
R(RIP) += 4;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static ulong fetchq(ctx_t *ctx)
|
||||
{
|
||||
ulong v = *(ulong *)(ctx->mp + R(RIP) + R(CR1) - MEMOFF);
|
||||
R(RIP) += 8;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
//
|
||||
@ -44,184 +60,205 @@ static void checkreg(ctx_t *ctx, uint reg)
|
||||
}
|
||||
|
||||
//
|
||||
// Extract operand according to fmt
|
||||
// Verify that given access length is that of a byte/word/dword/qword
|
||||
//
|
||||
void extract_param(ctx_t *ctx, acc_t *p, uchar fmt)
|
||||
static void checklength(ctx_t *ctx, uint len)
|
||||
{
|
||||
uint mlen, mfmt;
|
||||
ushort temp;
|
||||
static const int lentab[9] = { 0, 1, 1, 0, 1, 0, 0, 0, 1 };
|
||||
|
||||
p->type = fmt;
|
||||
if (len > 8 || lentab[len] == 0)
|
||||
_except(ctx, E_ILL, "Invalid memory access length: %u", len);
|
||||
}
|
||||
|
||||
if (fmt == A_REG)
|
||||
//
|
||||
// Extracts one operand
|
||||
//
|
||||
static void extract_param(ctx_t *ctx, uint prm, acc_t *p)
|
||||
{
|
||||
// Get next operand ModRM-like byte
|
||||
uchar fmt = fetchb(ctx);
|
||||
|
||||
ulong hi = (fmt & 0b11100000) >> 5;
|
||||
ulong lo = fmt & 0b00011111;
|
||||
|
||||
//
|
||||
// Registers
|
||||
//
|
||||
if (hi == 0)
|
||||
{
|
||||
p->reg = ctx->get(ctx);
|
||||
if (prm != P_REG)
|
||||
_except(ctx, E_ILL, "Not expecting a register: %s",
|
||||
ctx->cur_in->full);
|
||||
|
||||
p->reg = lo;
|
||||
p->type = A_REG;
|
||||
checkreg(ctx, p->reg);
|
||||
|
||||
p->val = R(p->reg);
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
else if (fmt == A_IMM64)
|
||||
//
|
||||
// Immediates
|
||||
//
|
||||
if (hi == 7)
|
||||
{
|
||||
p->val = ctx->get(ctx);
|
||||
p->val |= (ulong)ctx->get(ctx) << 16;
|
||||
p->val |= (ulong)ctx->get(ctx) << 32;
|
||||
p->val |= (ulong)ctx->get(ctx) << 48;
|
||||
|
||||
return;
|
||||
}
|
||||
if (prm != P_IMM)
|
||||
_except(ctx, E_ILL, "Not expecting an immediate: %s",
|
||||
ctx->cur_in->full);
|
||||
|
||||
assert(ACC_FMT_IS_MEM(fmt));
|
||||
|
||||
// Handle a memory access
|
||||
|
||||
mlen = fmt & AM_MLEN_MASK;
|
||||
mfmt = fmt & AM_MFMT_MASK;
|
||||
|
||||
p->mlen = (mlen == AM_8ACC ? 1
|
||||
: (mlen == AM_16ACC ? 2
|
||||
: (mlen == AM_32ACC ? 4
|
||||
: (mlen == AM_64ACC ? 8 : 0))));
|
||||
|
||||
if (p->mlen == 0)
|
||||
_except(ctx, E_ILL, "Invalid MLEN for access: %x", fmt);
|
||||
|
||||
switch (mfmt)
|
||||
{
|
||||
case AM_IMM64:
|
||||
p->addr = ctx->get(ctx);
|
||||
p->addr |= (ulong)ctx->get(ctx) << 16;
|
||||
p->addr |= (ulong)ctx->get(ctx) << 32;
|
||||
p->addr |= (ulong)ctx->get(ctx) << 48;
|
||||
switch (lo)
|
||||
{
|
||||
case 1:
|
||||
p->type = A_IMM8;
|
||||
p->val = fetchb(ctx);
|
||||
break;
|
||||
|
||||
case AM_RR:
|
||||
case AM_RRI:
|
||||
case AM_RRII:
|
||||
temp = ctx->get(ctx);
|
||||
p->reg1 = temp >> 8;
|
||||
p->reg2 = temp & 0xFF;
|
||||
|
||||
checkreg(ctx, p->reg1);
|
||||
checkreg(ctx, p->reg2);
|
||||
|
||||
if (mfmt == AM_RRI)
|
||||
{
|
||||
p->imm1 = 1;
|
||||
p->imm2 = ctx->get(ctx);
|
||||
}
|
||||
|
||||
else if (mfmt == AM_RRII)
|
||||
{
|
||||
p->imm1 = ctx->get(ctx);
|
||||
p->imm2 = ctx->get(ctx);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
p->imm1 = 1;
|
||||
p->imm2 = 0;
|
||||
}
|
||||
|
||||
p->addr = R(p->reg1) + R(p->reg2)
|
||||
* (long)(short)p->imm1
|
||||
+ (long)(short)p->imm2;
|
||||
|
||||
case 2:
|
||||
p->type = A_IMM16;
|
||||
p->val = fetchw(ctx);
|
||||
break;
|
||||
|
||||
|
||||
case 4:
|
||||
p->type = A_IMM32;
|
||||
p->val = fetchd(ctx);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
p->type = A_IMM64;
|
||||
p->val = fetchq(ctx);
|
||||
break;
|
||||
|
||||
default:
|
||||
_except(ctx, E_ILL, "Invalid MFMT for access: %x", fmt);
|
||||
_except(ctx, E_ILL, "Invalid immediate length: %hhu", lo);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Memory operands
|
||||
//
|
||||
|
||||
if (prm != P_MEM)
|
||||
_except(ctx, E_ILL, "Not expecting a memory access: %s",
|
||||
ctx->cur_in->full);
|
||||
|
||||
checklength(ctx, lo);
|
||||
p->mlen = lo;
|
||||
|
||||
switch (hi)
|
||||
{
|
||||
case 1:
|
||||
p->type = AM_RR;
|
||||
p->reg1 = fetchb(ctx);
|
||||
p->reg2 = p->imm1 = p->imm2 = 0;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
p->type = AM_RR;
|
||||
p->reg1 = fetchb(ctx);
|
||||
p->reg2 = fetchb(ctx);
|
||||
p->imm1 = 1;
|
||||
p->imm2 = 0;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
p->type = AM_RRI;
|
||||
p->reg1 = fetchb(ctx);
|
||||
p->reg2 = fetchb(ctx);
|
||||
p->imm2 = (short)fetchw(ctx);
|
||||
p->imm1 = 1;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
p->type = AM_RRI;
|
||||
p->reg1 = fetchb(ctx);
|
||||
p->reg2 = fetchb(ctx);
|
||||
p->imm2 = (int)fetchd(ctx);
|
||||
p->imm1 = 1;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
p->type = AM_RRII;
|
||||
p->reg1 = fetchb(ctx);
|
||||
p->reg2 = fetchb(ctx);
|
||||
p->imm1 = fetchb(ctx);
|
||||
p->imm2 = (short)fetchw(ctx);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
p->type = AM_RRI;
|
||||
p->reg1 = fetchb(ctx);
|
||||
p->imm2 = fetchq(ctx);
|
||||
p->reg2 = RZX;
|
||||
p->imm1 = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
p->addr = R(p->reg1) + R(p->reg2) * (long)p->imm1 + p->imm2;
|
||||
}
|
||||
|
||||
//
|
||||
// Instruction fetch & decode
|
||||
//
|
||||
void decode(ctx_t *ctx)
|
||||
{
|
||||
instr_t *in;
|
||||
uchar f1 = 0, f2 = 0, f3 = 0;
|
||||
ushort w1, w2, rep = 0, lock, nomore;
|
||||
ushort b1, b2, rep = 0, lock;
|
||||
acc_t p1 = { 0 }, p2 = { 0 }, p3 = { 0 };
|
||||
|
||||
rpc = R(RIP);
|
||||
ctx->cur_pc = R(RIP);
|
||||
|
||||
// Process the first word of the instruction
|
||||
w1 = ctx->get(ctx);
|
||||
lock = !!(w1 & SUFF_LOCK);
|
||||
nomore = !!(w1 & SUFF_NOMORE);
|
||||
// Address range check
|
||||
// (assumes max. instruction length is 32 bytes)
|
||||
if (R(RIP) + R(CR1) - MEMOFF >= ctx->mz - 32)
|
||||
_except(ctx, E_ACC, "Executing out of memory");
|
||||
|
||||
if (w1 & SUFF_COND)
|
||||
ctx->cond = ctx->get(ctx);
|
||||
else
|
||||
ctx->cond = 0;
|
||||
// Instruction bytes
|
||||
b1 = fetchb(ctx);
|
||||
b2 = fetchb(ctx);
|
||||
|
||||
w1 &= ~(SUFF_LOCK|SUFF_NOMORE|SUFF_COND);
|
||||
|
||||
if (w1 >= NINSTRS)
|
||||
_except(ctx, E_ILL, "No such INSTR: 0x%hX", w1);
|
||||
// Renge check
|
||||
if (b1 >= NINSTRS)
|
||||
_except(ctx, E_ILL, "No such INSTR: 0x%hhX", b1);
|
||||
|
||||
// Find instruction
|
||||
in = &ctx->i[w1];
|
||||
in = &ctx->i[b1];
|
||||
ctx->cur_in = in;
|
||||
|
||||
// Second word?
|
||||
if (!nomore)
|
||||
{
|
||||
w2 = ctx->get(ctx);
|
||||
|
||||
// REP and COND
|
||||
rep = !!(w2 & SUFF_REP);
|
||||
|
||||
// Fn
|
||||
f3 = (w2 >> F3_SHIFT) & Fx_MASK;
|
||||
f2 = (w2 >> F2_SHIFT) & Fx_MASK;
|
||||
f1 = w2 & Fx_MASK;
|
||||
}
|
||||
// Get flags/etc
|
||||
rep = !!(b2 & SUFF_REP);
|
||||
lock = !!(b2 & SUFF_LOCK);
|
||||
ctx->cond = b2 & SUFF_COND;
|
||||
|
||||
// Operand 1?
|
||||
if (in->prm1 == NOPRM)
|
||||
{
|
||||
if (f1 || f2 || f3)
|
||||
_except(ctx, E_ILL,
|
||||
"FTn (%u,%u,%u) filled for 0-param INSTR '%s'",
|
||||
f1, f2, f3, in->full);
|
||||
|
||||
exec_instr(ctx, in, NULL, NULL, NULL, lock, rep);
|
||||
return;
|
||||
}
|
||||
|
||||
check_param_type(ctx, in, in->prm1, f1, 1);
|
||||
extract_param(ctx, &p1, f1);
|
||||
extract_param(ctx, in->prm1, &p1);
|
||||
|
||||
// Operand 2?
|
||||
if (in->prm2 == NOPRM)
|
||||
{
|
||||
if (f2 || f3)
|
||||
_except(ctx, E_ILL,
|
||||
"FT3/FT2 (%u,%u,%u) filled for 1-param INSTR '%s'",
|
||||
f1, f2, f3, in->full);
|
||||
|
||||
exec_instr(ctx, in, &p1, NULL, NULL, lock, rep);
|
||||
return;
|
||||
}
|
||||
|
||||
check_param_type(ctx, in, in->prm2, f2, 2);
|
||||
extract_param(ctx, &p2, f2);
|
||||
extract_param(ctx, in->prm2, &p2);
|
||||
|
||||
// Operand 1?
|
||||
if (in->prm3 == NOPRM)
|
||||
{
|
||||
if (f3)
|
||||
_except(ctx, E_ILL,
|
||||
"FT3 (%u,%u,%u) filled for 2-param INSTR '%s'",
|
||||
f1, f2, f3, in->full);
|
||||
|
||||
exec_instr(ctx, in, &p1, &p2, NULL, lock, rep);
|
||||
return;
|
||||
}
|
||||
|
||||
check_param_type(ctx, in, in->prm3, f3, 3);
|
||||
extract_param(ctx, &p3, f3);
|
||||
extract_param(ctx, in->prm3, &p3);
|
||||
|
||||
exec_instr(ctx, in, &p1, &p2, &p3, lock, rep);
|
||||
}
|
||||
|
@ -20,41 +20,28 @@ enum
|
||||
|
||||
enum
|
||||
{
|
||||
SUFF_LOCK = (1 << 15),
|
||||
SUFF_NOMORE = (1 << 14),
|
||||
SUFF_COND = (1 << 13),
|
||||
SUFF_REP = (1 << 15),
|
||||
|
||||
Fx_MASK = 0x1F,
|
||||
F3_SHIFT = 10,
|
||||
F2_SHIFT = 5,
|
||||
SUFF_REP = (1 << 7),
|
||||
SUFF_LOCK = (1 << 6),
|
||||
SUFF_COND = 0b00011111,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
A_NONE = 0b00000,
|
||||
A_REG = 0b00001,
|
||||
A_IMM64 = 0b00010,
|
||||
|
||||
AM_START = 0b00100,
|
||||
A_IMM8 = 1,
|
||||
A_IMM16 = 2,
|
||||
A_IMM32 = 4,
|
||||
A_IMM64 = 8,
|
||||
|
||||
AM_IMM64 = 0b00,
|
||||
AM_RR = 0b01,
|
||||
AM_RRI = 0b10,
|
||||
AM_RRII = 0b11,
|
||||
|
||||
AM_8ACC = 0b00100,
|
||||
AM_16ACC = 0b01000,
|
||||
AM_32ACC = 0b01100,
|
||||
AM_64ACC = 0b10000,
|
||||
|
||||
AM_MLEN_MASK = 0b11100,
|
||||
AM_MFMT_MASK = 0b00011,
|
||||
AM_RR = 0xF0,
|
||||
AM_RRI = 0xF1,
|
||||
AM_RRII = 0xF2,
|
||||
};
|
||||
|
||||
#define ACC_FMT_IS_MEM(x) ((x) >= AM_START && (x) <= (AM_64ACC|AM_RRII))
|
||||
|
||||
#define ACC_IS_MEM(x) (ACC_FMT_IS_MEM((x)->type))
|
||||
#define ACC_FMT_IS_MEM(x) (((x) & 0xF0) != 0)
|
||||
#define ACC_IS_MEM(p) ACC_FMT_IS_MEM((p)->type)
|
||||
|
||||
struct acc_t
|
||||
{
|
||||
@ -62,15 +49,16 @@ struct acc_t
|
||||
ulong val;
|
||||
|
||||
// A_REG
|
||||
ulong reg;
|
||||
uchar reg;
|
||||
|
||||
// AM_...
|
||||
ulong addr;
|
||||
uint mlen;
|
||||
|
||||
// For instruction dumping ONLY
|
||||
ushort reg1, reg2;
|
||||
short imm1, imm2;
|
||||
uchar reg1, reg2;
|
||||
char imm1;
|
||||
long imm2;
|
||||
};
|
||||
|
||||
enum { NOPRM, P_REG, P_IMM, P_MEM=4 };
|
||||
@ -98,10 +86,6 @@ void exec_instr(ctx_t *ctx,
|
||||
bool lock,
|
||||
bool rep);
|
||||
|
||||
void extract_param(ctx_t *ctx,
|
||||
acc_t *p,
|
||||
uchar fmt);
|
||||
|
||||
void dump_instr(ctx_t *ctx,
|
||||
instr_t *in,
|
||||
acc_t *p1,
|
||||
|
45
vm/pc/dump.c
45
vm/pc/dump.c
@ -26,7 +26,7 @@ void dump_instr(ctx_t *ctx,
|
||||
{
|
||||
uint cond = ctx->cond;
|
||||
|
||||
trace("0x%lX:\t", rpc);
|
||||
trace("0x%lX:\t", ctx->cur_pc);
|
||||
|
||||
if (lock)
|
||||
trace("lock");
|
||||
@ -41,9 +41,7 @@ void dump_instr(ctx_t *ctx,
|
||||
trace(".");
|
||||
|
||||
if (cond & (1 << 4))
|
||||
{
|
||||
trace("n");
|
||||
}
|
||||
|
||||
assert((cond & ~(1 << 4)) <= sizeof(cond_suffixes)/sizeof(char *));
|
||||
|
||||
@ -81,6 +79,12 @@ void dump_acc(ctx_t *ctx, acc_t *p)
|
||||
trace("%s", ctx->r[p->reg].name);
|
||||
|
||||
else if (p->type == A_IMM64)
|
||||
{
|
||||
if (p->val < 0xA) trace("%lu", p->val);
|
||||
else trace("0x%lX", p->val);
|
||||
}
|
||||
|
||||
else if (p->type == A_IMM32)
|
||||
{
|
||||
if (p->val < 0xA)
|
||||
trace("%lu", p->val);
|
||||
@ -96,16 +100,25 @@ void dump_acc(ctx_t *ctx, acc_t *p)
|
||||
}
|
||||
}
|
||||
|
||||
else if (p->type == A_IMM16)
|
||||
{
|
||||
if (p->val < 0xA) trace("%lu", p->val);
|
||||
else trace("0x%hX", (ushort)p->val);
|
||||
}
|
||||
|
||||
else if (p->type == A_IMM8)
|
||||
{
|
||||
if (p->val < 0xA) trace("%lu", p->val);
|
||||
else trace("0x%hhX", (uchar)p->val);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
trace("%c[", getmempref(p->mlen));
|
||||
|
||||
mfmt = p->type & AM_MFMT_MASK;
|
||||
|
||||
if (mfmt == AM_IMM64)
|
||||
trace("0x%lX]", p->addr);
|
||||
mfmt = p->type;
|
||||
|
||||
else if (mfmt == AM_RR)
|
||||
if (mfmt == AM_RR)
|
||||
{
|
||||
if (p->reg1 && p->reg2)
|
||||
trace("%s+%s]", ctx->r[p->reg1].name, ctx->r[p->reg2].name);
|
||||
@ -116,30 +129,30 @@ void dump_acc(ctx_t *ctx, acc_t *p)
|
||||
else if (mfmt == AM_RRI)
|
||||
{
|
||||
if (p->reg1 && p->reg2)
|
||||
trace("%s+%s%c%hd]",
|
||||
trace("%s+%s%c%ld]",
|
||||
ctx->r[p->reg1].name,
|
||||
ctx->r[p->reg2].name,
|
||||
((short)p->imm2 < 0 ? '-' : '+'),
|
||||
(p->imm2 < 0 ? '-' : '+'),
|
||||
ABS(p->imm2));
|
||||
|
||||
else trace("%s%c%hd]",
|
||||
else trace("%s%c%ld]",
|
||||
ctx->r[p->reg1 ? p->reg1 : p->reg2].name,
|
||||
((short)p->imm2 < 0 ? '-' : '+'),
|
||||
(p->imm2 < 0 ? '-' : '+'),
|
||||
ABS(p->imm2));
|
||||
}
|
||||
|
||||
else if (mfmt == AM_RRII)
|
||||
{
|
||||
if (p->reg1)
|
||||
trace("%s+%s*%hd%c%hd]",
|
||||
trace("%s+%s*%hhd%c%ld]",
|
||||
ctx->r[p->reg1].name,
|
||||
ctx->r[p->reg2].name, p->imm1,
|
||||
((short)p->imm2 < 0 ? '-' : '+'),
|
||||
(p->imm2 < 0 ? '-' : '+'),
|
||||
ABS(p->imm2));
|
||||
else
|
||||
trace("%s*%hd%c%hd]",
|
||||
trace("%s*%hhd%c%ld]",
|
||||
ctx->r[p->reg2].name, p->imm1,
|
||||
((short)p->imm2 < 0 ? '-' : '+'),
|
||||
(p->imm2 < 0 ? '-' : '+'),
|
||||
ABS(p->imm2));
|
||||
}
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ void _except(ctx_t *ctx, int _code, char *fmt, ...)
|
||||
trace("\nException %u - ", code);
|
||||
|
||||
va_start(ap, fmt);
|
||||
vlog(fmt, ap);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
trace("\n\n");
|
||||
@ -105,7 +105,7 @@ actually_die:
|
||||
logerr("\nException %u - ", code);
|
||||
|
||||
va_start(ap, fmt);
|
||||
vlog(fmt, ap);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
logerr("\n\n");
|
||||
|
@ -63,7 +63,7 @@ void exec_instr(ctx_t *ctx,
|
||||
ulong r1 = 0, r2 = 0, r3 = 0;
|
||||
|
||||
// Global instruction counter
|
||||
fc0++;
|
||||
ctx->ninstrs++;
|
||||
|
||||
//
|
||||
// For REPs we evaluate the condition AFTER running the instruction,
|
||||
@ -77,8 +77,6 @@ void exec_instr(ctx_t *ctx,
|
||||
dump_instr(ctx, in, p1, p2, p3, lock, rep);
|
||||
|
||||
do_rep:
|
||||
assert(R(RZX) == 0);
|
||||
|
||||
out = in->func(ctx, p1, p2, p3, &r1, &r2, &r3);
|
||||
|
||||
if (out)
|
||||
@ -102,7 +100,7 @@ do_rep:
|
||||
return;
|
||||
|
||||
// Should we really count REP's in instruction count?
|
||||
fc0++;
|
||||
ctx->ninstrs++;
|
||||
#if 0
|
||||
// Show that we're REP'ing
|
||||
if (ctx->dumpsw)
|
||||
|
16
vm/pc/log.c
16
vm/pc/log.c
@ -3,17 +3,6 @@
|
||||
|
||||
#include <pc/arch.h>
|
||||
|
||||
/*
|
||||
void trace(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
*/
|
||||
|
||||
void logerr(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
@ -23,8 +12,3 @@ void logerr(const char *fmt, ...)
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void vlog(const char *fmt, va_list ap)
|
||||
{
|
||||
vfprintf(stderr, fmt, ap);
|
||||
}
|
||||
|
||||
|
23
vm/pc/main.c
23
vm/pc/main.c
@ -11,23 +11,6 @@
|
||||
static ssize_t fwsize;
|
||||
static ushort *fwprog;
|
||||
|
||||
ushort bget(ctx_t *ctx)
|
||||
{
|
||||
ulong addr = R(RIP) + R(CR1);
|
||||
|
||||
if (addr2real(addr) >= ctx->mz) {
|
||||
_except(ctx, E_ACC, "Executing out of memory: "
|
||||
"rip=0x%lX cr1=0x%lX",
|
||||
R(RIP), R(RIP));
|
||||
}
|
||||
|
||||
ushort c = ctx->mp[addr2real(addr)];
|
||||
|
||||
R(RIP) += 2;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
ctx_t main_ctx;
|
||||
|
||||
void sigcommon(void)
|
||||
@ -53,9 +36,10 @@ jmp_buf exc_jmp_buf;
|
||||
//
|
||||
void main_loop(void)
|
||||
{
|
||||
/*
|
||||
if (main_ctx.dumpsw)
|
||||
trace("\n\n\n");
|
||||
|
||||
*/
|
||||
setjmp(exc_jmp_buf);
|
||||
|
||||
//
|
||||
@ -78,7 +62,7 @@ int main(int argc, char **argv)
|
||||
main_ctx.r = arch_r;
|
||||
main_ctx.i = arch_i;
|
||||
|
||||
#if 0 && defined(NDEBUG)
|
||||
#if 1 && !defined(NDEBUG)
|
||||
main_ctx.dumpsw = 1;
|
||||
#endif
|
||||
|
||||
@ -141,7 +125,6 @@ int main(int argc, char **argv)
|
||||
main_ctx.mp = malloc(MEMSIZE + 16);
|
||||
main_ctx.mz = MEMSIZE;
|
||||
|
||||
main_ctx.get = bget;
|
||||
main_ctx.rf[RIP] = MEMOFF;
|
||||
|
||||
if (main_ctx.mp == 0) {
|
||||
|
85
vm/pc/mem.c
85
vm/pc/mem.c
@ -47,77 +47,54 @@ ulong writestr(ctx_t *ctx, ulong addr, ulong maxn, char *str)
|
||||
|
||||
static ulong readmem8(ctx_t *ctx, ulong real, ulong addr)
|
||||
{
|
||||
if (addr % 2 == 0) return (ulong)ctx->mp[real] & 0xFF;
|
||||
else return ((ulong)ctx->mp[real] & 0xFF00) >> 8;
|
||||
return (ulong)ctx->mp[real];
|
||||
}
|
||||
|
||||
static ulong readmem16(ctx_t *ctx, ulong real, ulong addr)
|
||||
{
|
||||
CHK_ALIGN(ushort);
|
||||
|
||||
return (ulong)ctx->mp[real];
|
||||
return (ulong)*(ushort *)(ctx->mp + real);
|
||||
}
|
||||
|
||||
static ulong readmem32(ctx_t *ctx, ulong real, ulong addr)
|
||||
{
|
||||
CHK_ALIGN(uint);
|
||||
|
||||
ulong val = ctx->mp[real++];
|
||||
val = val | ((ulong)ctx->mp[real] << 16);
|
||||
|
||||
return val;
|
||||
return (ulong)*(uint *)(ctx->mp + real);
|
||||
}
|
||||
|
||||
static ulong readmem64(ctx_t *ctx, ulong real, ulong addr)
|
||||
{
|
||||
CHK_ALIGN(ulong);
|
||||
|
||||
ulong val = (ulong)ctx->mp[real++];
|
||||
val = val | ((ulong)ctx->mp[real++] << 16);
|
||||
val = val | ((ulong)ctx->mp[real++] << 32);
|
||||
val = val | ((ulong)ctx->mp[real] << 48);
|
||||
|
||||
return val;
|
||||
return (ulong)*(ulong *)(ctx->mp + real);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
static void writemem8(ctx_t *ctx, ulong val, ulong real, ulong addr)
|
||||
{
|
||||
ushort v = ctx->mp[real];
|
||||
|
||||
if (!(addr % 2)) {
|
||||
ctx->mp[real] = (v & 0xFF00) | (val & 0xFF);
|
||||
}
|
||||
|
||||
else {
|
||||
ctx->mp[real] = (v & 0xFF) | (((val & 0xFF) << 8));
|
||||
}
|
||||
ctx->mp[real] = val & 0xFF;
|
||||
}
|
||||
|
||||
static void writemem16(ctx_t *ctx, ulong val, ulong real, ulong addr)
|
||||
{
|
||||
CHK_ALIGN(ushort);
|
||||
|
||||
ctx->mp[real] = val & 0xFFFF;
|
||||
*(ushort*)(ctx->mp + real) = val & 0xFFFF;
|
||||
}
|
||||
|
||||
static void writemem32(ctx_t *ctx, ulong val, ulong real, ulong addr)
|
||||
{
|
||||
CHK_ALIGN(uint);
|
||||
|
||||
ctx->mp[real++] = val & 0xFFFF;
|
||||
ctx->mp[real] = (val >> 16) & 0xFFFF;
|
||||
*(uint*)(ctx->mp + real) = val & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
static void writemem64(ctx_t *ctx, ulong val, ulong real, ulong addr)
|
||||
{
|
||||
CHK_ALIGN(ulong);
|
||||
|
||||
ctx->mp[real++] = val;
|
||||
ctx->mp[real++] = (val >> 16) & 0xFFFF;
|
||||
ctx->mp[real++] = (val >> 32) & 0xFFFF;
|
||||
ctx->mp[real] = (val >> 48) & 0xFFFF;
|
||||
*(ulong*)(ctx->mp + real) = val;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
@ -133,7 +110,22 @@ static void writemem64(ctx_t *ctx, ulong val, ulong real, ulong addr)
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
ulong readmem(ctx_t *ctx, ulong addr, uint len)
|
||||
ulong readmemzx(ctx_t *ctx, ulong addr, uint len)
|
||||
{
|
||||
GETREAL();
|
||||
CHK_RANGE();
|
||||
|
||||
switch (len) {
|
||||
case 1: return readmem8(ctx, real, addr); break;
|
||||
case 2: return readmem16(ctx, real, addr); break;
|
||||
case 4: return readmem32(ctx, real, addr); break;
|
||||
case 8: return readmem64(ctx, real, addr); break;
|
||||
|
||||
default: logerr("readmemzx() bad length %d!\n", len); abort();
|
||||
}
|
||||
}
|
||||
|
||||
ulong readmemsx(ctx_t *ctx, ulong addr, uint len)
|
||||
{
|
||||
GETREAL();
|
||||
CHK_RANGE();
|
||||
@ -143,23 +135,23 @@ ulong readmem(ctx_t *ctx, ulong addr, uint len)
|
||||
switch (len) {
|
||||
case 1:
|
||||
val = readmem8(ctx, real, addr);
|
||||
val = (ulong)(long)(char)(val & 0xFF);
|
||||
val = (ulong)(long)(char)val;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
val = readmem16(ctx, real, addr);
|
||||
val = (ulong)(long)(short)(val & 0xFFFF);
|
||||
val = (ulong)(long)(short)val;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
val = readmem32(ctx, real, addr);
|
||||
val = (ulong)(long)(int)(val & 0xFFFFFFFF);
|
||||
val = (ulong)(long)(int)val;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
return readmem64(ctx, real, addr);
|
||||
|
||||
default: logerr("readmem() bad length %d!\n", len); abort();
|
||||
default: logerr("readmemsx() bad length %d!\n", len); abort();
|
||||
}
|
||||
|
||||
return val;
|
||||
@ -183,24 +175,3 @@ void writemem(ctx_t *ctx, ulong val, ulong addr, uint len)
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
//
|
||||
// The following function zero-extend rather than sign-extend
|
||||
//
|
||||
|
||||
ulong readmemzx(ctx_t *ctx, ulong addr, uint len)
|
||||
{
|
||||
GETREAL();
|
||||
CHK_RANGE();
|
||||
|
||||
switch (len) {
|
||||
case 1: return readmem8(ctx, real, addr); break;
|
||||
case 2: return readmem16(ctx, real, addr); break;
|
||||
case 4: return readmem32(ctx, real, addr); break;
|
||||
case 8: return readmem64(ctx, real, addr); break;
|
||||
|
||||
default: logerr("readmemzx() bad length %d!\n", len); abort();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
|
11
vm/pc/mem.h
11
vm/pc/mem.h
@ -5,15 +5,15 @@ static inline ushort bswap16(ushort u)
|
||||
{ return ((u<<8) | (u>>8)); }
|
||||
|
||||
static inline char getmempref(ushort len)
|
||||
{ return (len==1?'b':(len==2?'w':(len==4?'l':(len==8?'q':'x')))); }
|
||||
{ return (len==1?'b':(len==2?'w':(len==4?'d':(len==8?'q':'x')))); }
|
||||
|
||||
#define MEMOFF (1 * 1024 * 1024)
|
||||
#define MEMSIZE (16 * 1024 * 1024) // 16MB
|
||||
|
||||
#define MAXADDR 0x8000000000000 // 2^48 - 1
|
||||
|
||||
#define addr2real(p) (((p) - MEMOFF) / 2)
|
||||
#define real2addr(p) (((p) + MEMOFF) / 2)
|
||||
#define addr2real(p) ((p) - MEMOFF)
|
||||
#define real2addr(p) ((p) + MEMOFF)
|
||||
|
||||
// Address of boot firmware stack
|
||||
#define FWSTACK (MEMOFF * 2) // 2MB
|
||||
@ -21,11 +21,10 @@ static inline char getmempref(ushort len)
|
||||
ulong readstr(ctx_t *ctx, ulong addr, ulong maxn, char *buf);
|
||||
ulong writestr(ctx_t *ctx, ulong addr, ulong maxn, char *str);
|
||||
|
||||
ulong readmem(ctx_t *c, ulong addr, uint len);
|
||||
ulong readmemzx(ctx_t *c, ulong addr, uint len);
|
||||
ulong readmemsx(ctx_t *c, ulong addr, uint len);
|
||||
void writemem(ctx_t *, ulong val, ulong addr, uint len);
|
||||
|
||||
ulong readmemzx(ctx_t *c, ulong addr, uint len);
|
||||
void writememzx(ctx_t *, ulong val, ulong addr, uint len);
|
||||
|
||||
#define SIGN_EXTEND(val, mask) \
|
||||
(val & ((mask + 1) >> 1) \
|
||||
|
@ -26,9 +26,9 @@ void dumpregs(ctx_t *ctx)
|
||||
TRACE("Current RFRAME index: #%lu", rfs_current_idx);
|
||||
|
||||
TRACE("\n\nEnviron:");
|
||||
TRACE("\nrpc=0x%-16lX rip=0x%-16lX rfx=0x%-16lX", rpc, R(RIP), R(RFX));
|
||||
TRACE("\nrpc=0x%-16lX rip=0x%-16lX rfx=0x%-16lX", ctx->cur_pc, R(RIP), R(RFX));
|
||||
TRACE("\nrsp=0x%-16lX rbp=0x%-16lX trp=0x%-16lX", R(RSP), R(RBP), R(TRP));
|
||||
TRACE("\nfc0=0x%-16lu cr0=0x%-16lX cr1=0x%-16lX", fc0, R(CR0), R(CR1));
|
||||
TRACE("\nfc0=0x%-16lu cr0=0x%-16lX cr1=0x%-16lX", ctx->ninstrs, R(CR0), R(CR1));
|
||||
|
||||
TRACE("\n\nArgument:");
|
||||
TRACE("\nax0=0x%-16lX ax1=0x%-16lX ax2=0x%-16lX", R(AX0), R(AX1), R(AX2));
|
||||
|
10
vm/pc/regs.h
10
vm/pc/regs.h
@ -45,12 +45,6 @@ enum
|
||||
NREGS
|
||||
};
|
||||
|
||||
#define fc0 ctx->ninstrs
|
||||
#define rpc ctx->cur_pc
|
||||
|
||||
#define rax R(RAX)
|
||||
#define rdx R(RDX)
|
||||
|
||||
#define ax0 R(AX0)
|
||||
#define ax1 R(AX1)
|
||||
#define _fc0 ctx->ninstrs
|
||||
#define _rpc ctx->cur_pc
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user