new encoding

This commit is contained in:
julianb0 2019-07-24 16:52:26 +02:00
parent 9eee4817cd
commit f89e535fbd
No known key found for this signature in database
GPG Key ID: DDF8325C95299A62
38 changed files with 911 additions and 1019 deletions

View File

@ -213,7 +213,7 @@ def parse():
if line[0] == ' ' or line[0] == '\t': if line[0] == ' ' or line[0] == '\t':
line = line.lstrip() line = line.lstrip()
instrs.write(pcurfile + ' ') instrs.write(pcurfile + ' ' + hex(ptext) + ' ')
ptext += parse_instr(line) ptext += parse_instr(line)
instrs.write("\n") instrs.write("\n")
@ -411,43 +411,31 @@ def get_cond_mask(cond, line):
leave(1) leave(1)
return (mask | pconds[cond]) 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): def parse_instr(line):
if line == None or len(line) == 0: if line == None or len(line) == 0:
return 0 return 0
@ -463,12 +451,10 @@ def parse_instr(line):
fellthrough = False fellthrough = False
size = 4 size = 2
# Word 2 (rep|ft3|ft2|ft1) # Byte 2 (rep|lock|0|cond)
w2 = 0 b2 = 0
cond = None
if len(instr) > 2 and '.' in instr: if len(instr) > 2 and '.' in instr:
instr, suf = instr.split('.', 1) instr, suf = instr.split('.', 1)
@ -485,42 +471,30 @@ def parse_instr(line):
else: else:
suf = '' suf = ''
w2 |= 0x8000 # REP b2 |= 1<<7 # REP
if len(suf) > 0: if len(suf) > 0:
instrs.write("%%cond ") b2 |= get_cond_mask(suf, line)
cond = "%%imm16 {}".format(get_cond_mask(suf, line))
instr_name = instr instr_name = instr
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("{} %%imm8 {}".format(instr_name, b2))
if cond != None:
size += 2
instrs.write("{} ".format(cond))
instrs.write("%%imm16 {}".format(w2))
return size return size
tok = params.split(',') tok = params.split(',')
# FTn
fts = ''
# #
# Parse operands, generating fts along the way # Parse operands
# #
for word in tok: for word in tok:
word = word.strip() word = word.strip()
instr_args += ' ' instr_args += ' '
gotPref = False mlen = 0
if len(fts) != 0:
fts += ' '
if len(word) == 0: if len(word) == 0:
print("Wrong syntax in line: '{}'".format(line)) print("Wrong syntax in line: '{}'".format(line))
@ -540,9 +514,8 @@ def parse_instr(line):
# memory length prefixes # memory length prefixes
if len(word) > 2 and '[' in word: if len(word) > 2 and '[' in word:
if word[0] in 'bwlq': if word[0] in 'bwldq':
fts += word[0] mlen = pref2len[word[0]]
gotPref = True
else: else:
print("Bad memory length prefix: {}".format(line)) print("Bad memory length prefix: {}".format(line))
leave(1) leave(1)
@ -551,7 +524,7 @@ def parse_instr(line):
assert(word[0] == '[') assert(word[0] == '[')
# #
# Determine memory format and save it into fts # Determine memory format
# #
if word[0] == '[': if word[0] == '[':
assert(word[-1] == ']') assert(word[-1] == ']')
@ -562,10 +535,8 @@ def parse_instr(line):
word = pdefs[word] word = pdefs[word]
# Fall through # Fall through
#
# Make sure we got an access length prefix # Make sure we got an access length prefix
# if mlen == 0:
if not gotPref:
print("Missing access length modifier: {}".format(line)) print("Missing access length modifier: {}".format(line))
leave(1) leave(1)
@ -581,15 +552,15 @@ def parse_instr(line):
# Offsets # Offsets
# #
if '+' in word: if '+' in word:
reg1 = "rzx" reg1 = "zero"
reg2 = "rzx" reg2 = "zero"
imm1 = '1' imm1 = '1'
imm2 = '0' imm2 = '0'
wtok = word.split('+') wtok = word.split('+')
# #
# [reg] and [reg*imm16] # [reg] and [reg*imm]
# #
if len(wtok) == 1: if len(wtok) == 1:
@ -602,10 +573,10 @@ def parse_instr(line):
reg1 = wtok[0] 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: elif len(wtok) == 2:
# Must be [reg*imm16+imm16] # Must be [reg*imm+imm]
if '*' in wtok[0]: if '*' in wtok[0]:
assert(len(wtok[0].split('*')) == 2) assert(len(wtok[0].split('*')) == 2)
assert(is_number(wtok[1].strip())) assert(is_number(wtok[1].strip()))
@ -614,7 +585,7 @@ def parse_instr(line):
reg2, imm1 = wtok[0].split('*', 1) reg2, imm1 = wtok[0].split('*', 1)
imm2 = wtok[1] imm2 = wtok[1]
# Must be [reg+reg*imm16] # Must be [reg+reg*imm]
elif '*' in wtok[1]: elif '*' in wtok[1]:
assert(len(wtok[1].split('*')) == 2) assert(len(wtok[1].split('*')) == 2)
@ -631,7 +602,7 @@ def parse_instr(line):
reg2 = wtok[1] reg2 = wtok[1]
# #
# [reg+reg+imm16], [reg+reg*imm16+imm16] # [reg+reg+imm], [reg+reg*imm8+imm]
# #
else: else:
assert(len(wtok) == 3) assert(len(wtok) == 3)
@ -647,129 +618,91 @@ def parse_instr(line):
reg2 = wtok[1] 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 size += 2
if imm1 == '1': # [imm], converted to [zero+imm]
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]
#
else: else:
fellthrough = True instr_args += "%%imm8 {} zero zero %%imm32 {}".format(fmts["m_rrid"]|mlen, word)
# FALLTHROUGH size += 7
continue
# preprocessor, yet again # preprocessor, yet again
if word in pdefs: if word in pdefs:
word = pdefs[word] word = pdefs[word]
# Fall through # fallthrough
# characters 'c' # characters 'c'
if len(word) == 3 and word[0] == word[-1] == "'": if len(word) == 3 and word[0] == word[-1] == "'":
word = str(ord(word[1])) word = str(ord(word[1]))
# fallthrough
# register index $reg # register index $reg
if len(word) == 4 and word[0] == '$': if len(word) == 4 and word[0] == '$':
if word[1:] in pregs: if word[1:] in pregs:
word = str(pregs[word[1:]]) word = str(pregs[word[1:]])
# fallthrough
# for now every immediate is 64-bit # for now every immediate is 64-bit
if is_number(word): if is_number(word):
# +8 for immediate size += 9 # ModRM + imm
size += 8
if not fellthrough: instr_name += "_i"
instr_name += "_i" instr_args += "%%imm8 {} ".format(fmts["imm64"])
instr_args += "%%imm64 {}".format(word)
fts += "imm64"
instr_args += "%%imm64 "
instr_args += word
fellthrough = False fellthrough = False
continue continue
# register # register
if word in pregs: elif word in pregs:
size += 2 size += 1
instr_name += "_r"
if not fellthrough:
instr_name += "_r"
fts += "reg"
else:
fts += "rr"
instr_args += word instr_args += word
fellthrough = False
continue continue
# it's a label (a 64-bit immediate) # it's a label (a 32-bit immediate)
# +8 for immediate # ModRM + imm
size += 8 size += 5
if not fellthrough: instr_name += "_i"
instr_name += "_i" instr_args += "%%imm8 {} ".format(fmts["imm32"])
fts += "imm64"
instr_args += "%%imm64 "
if word[0] == '.': if word[0] == '.':
instr_args += plastlabel instr_args += plastlabel
instr_args += word instr_args += word
fellthrough = False
# instrs.write("{} %%imm8 {} {}".format(instr_name, b2, instr_args))
# 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))
return size return size
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
special_syms = { special_syms = {
"%%cond", "%%imm8",
"%%imm16", "%%imm16",
"%%imm32", "%%imm32",
"%%imm64", "%%imm64",
@ -785,15 +718,13 @@ def gentext():
instrs.seek(0) instrs.seek(0)
cond_mask = 0
for _, line in enumerate(instrs): for _, line in enumerate(instrs):
tok = line.strip().split() tok = line.strip().split()
if WANT_DISASM: if WANT_DISASM:
print(tok) print(tok)
tok = tok[1:] tok = tok[2:]
for word in tok: for word in tok:
if len(word) == 0: if len(word) == 0:
@ -801,45 +732,33 @@ def gentext():
if word in pregs: if word in pregs:
idx = pregs[word] idx = pregs[word]
b_text.write(idx.to_bytes(2, byteorder='little', signed=False)) b_text.write(idx.to_bytes(1, 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))
continue continue
if word in pinstrs: if word in pinstrs:
idx = pinstrs.index(word) | cond_mask idx = pinstrs.index(word)
cond_mask = 0 b_text.write(idx.to_bytes(1, byteorder='little', signed=False))
b_text.write(idx.to_bytes(2, byteorder='little', signed=False))
continue continue
if word in plabels_text: if word in plabels_text:
addr = text_start + plabels_text[word] 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 continue
if word in plabels_data: if word in plabels_data:
addr = data_start + plabels_data[word] 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 continue
if word in special_syms: if word in special_syms:
if word == "%%imm16": if word == "%%imm8":
lastimm = 1
elif 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
elif word == "%%cond":
cond_mask = (1 << 13)
elif word == "%%signed": elif word == "%%signed":
lastimm = 2 lastimm = 2
isSigned = True isSigned = True

View File

@ -2,10 +2,42 @@
; See the LICENSE file in the project root for more information. ; 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/sys.k"
include "crt/limits.k"
include "crt/err/errno.k" include "crt/err/errno.k"
include "crt/fmt/format.k" include "crt/fmt/format.k"
include "crt/str/string.k" include "crt/str/string.k"

View File

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

View File

@ -10,9 +10,10 @@
; <0 if the first character that does not match has a lower value in str1 than in str2 ; <0 if the first character that does not match has a lower value in str1 than in str2
; ;
strcmp: strcmp:
mov rcx, zero
.l: .l:
movzx rax, b[ax0] movzx rax, b[ax0+rcx]
movzx rdx, b[ax1] movzx rdx, b[ax1+rcx]
cmp rax, rdx cmp rax, rdx
jmp.nz .r jmp.nz .r
@ -21,8 +22,7 @@ strcmp:
add rbx, rax, rdx add rbx, rax, rdx
jmp.bxz .r jmp.bxz .r
add ax0, ax0, 1 add rcx, rcx, 1
add ax1, ax1, 1
jmp .l jmp .l
.r: .r:
@ -37,8 +37,8 @@ strncmp:
jmp.cxz .r jmp.cxz .r
.l: .l:
mov rax, b[ax0] movzx rax, b[ax0]
mov rdx, b[ax1] movzx rdx, b[ax1]
cmp rax, rdx cmp rax, rdx
jmp.nz .r jmp.nz .r

View File

@ -1,19 +1,19 @@
; The OS/K Team licenses this file to you under the MIT license. ; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information. ; See the LICENSE file in the project root for more information.
;
; EXIT syscall
;
; Return to COMMAND.COM
;
Sys.Exit := 0x00
; ;
; SHUTDOWN syscall ; SHUTDOWN syscall
; ;
; End virtual machine ; End virtual machine
; ;
Sys.Shutdown := 0x01 Sys.Shutdown := 0x00
;
; EXIT syscall
;
; Return to COMMAND.COM
;
Sys.Exit := 0x01
; FIND syscalls ; FIND syscalls
; ;

View File

@ -2,6 +2,11 @@
; See the LICENSE file in the project root for more information. ; See the LICENSE file in the project root for more information.
__sysmain: __sysmain:
pause
add rax, rax, 1
jmp .1
.1:
jmp start jmp start
@ -26,8 +31,7 @@ start:
mov rsp, DOSKRNL_STACK mov rsp, DOSKRNL_STACK
mov rbp, zero mov rbp, zero
dump mov rcx, 1
mov rcx, 44
crash.cxz crash.cxz
call main call main

View File

@ -3,25 +3,19 @@
TrapHandlers.prolog: TrapHandlers.prolog:
mov rbp, rsp 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 ; nx0 = caller's cr2
mov ax0, r14 mov ax0, r14
mov ax1, $cr2 mov ax1, $cr2
call RFS.LoadReg call RFS.LoadReg
; we don't preserve the r12 we got
mov r12, rax mov r12, rax
mov rdx, zero mov rdx, zero
jmp rcx jmp rcx
TrapHandlers.epilog: TrapHandlers.epilog:
mov r15, q[rbp-24]
mov r14, q[rbp-16]
mov r13, q[rbp-8]
; TRAP return values: RAX-RDX ; TRAP return values: RAX-RDX

View File

@ -14,8 +14,8 @@ trap0_handler:
call RFS.LoadReg call RFS.LoadReg
call RFS.LoadArgs call RFS.LoadArgs
b.z rax, zero, .handle_Shutdown
b.z rax, Sys.Exit, .handle_Exit 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.FindNext, .handle_FindNext
b.z rax, Sys.FindFirst, .handle_FindFirst b.z rax, Sys.FindFirst, .handle_FindFirst
b.z rax, Sys.OpenFile, .handle_OpenFile b.z rax, Sys.OpenFile, .handle_OpenFile
@ -114,19 +114,10 @@ trap0_handler:
; Misc. ; Misc.
; ;
.handle_Shutdown: .handle_Shutdown:
mov r12, zero
stop stop
.handle_HaltMode: .handle_HaltMode:
hlt mov rcx, -1
.HLT.loop: hlt.rep
pause stop
pause
pause
scan rax
b.z rax, zero, .HLT.loop
prn rax
jmp .HLT.loop

View File

@ -2,9 +2,7 @@
; See the LICENSE file in the project root for more information. ; See the LICENSE file in the project root for more information.
PrintBootMsg: PrintBootMsg:
mov rcx, STRLEN_MAX call print, .bootmsg
mov rdx, .bootmsg
prns.rep.nz rdx
ret ret
.bootmsg = "Starting DOS...\n\n" .bootmsg = "Starting DOS...\n\n"

View File

@ -123,43 +123,47 @@ main:
.builtin_cls = "cls" .builtin_cls = "cls"
call strcmp, argv0, .builtin_cls call strcmp, argv0, .builtin_cls
b.z rax, 0, .handle_CLS b.z rax, zero, .handle_CLS
.builtin_date = "date" .builtin_date = "date"
call strcmp, argv0, .builtin_date call strcmp, argv0, .builtin_date
b.z rax, 0, .handle_DATE b.z rax, zero, .handle_DATE
.builtin_dir = "dir" .builtin_dir = "dir"
call strcmp, argv0, .builtin_dir call strcmp, argv0, .builtin_dir
b.z rax, 0, .handle_DIR b.z rax, zero, .handle_DIR
.builtin_dump = "dump" .builtin_dump = "dump"
call strcmp, argv0, .builtin_dump call strcmp, argv0, .builtin_dump
b.z rax, 0, .handle_DUMP b.z rax, zero, .handle_DUMP
.builtin_echo = "echo" .builtin_echo = "echo"
call strcmp, argv0, .builtin_echo call strcmp, argv0, .builtin_echo
b.z rax, 0, .handle_ECHO b.z rax, zero, .handle_ECHO
.builtin_exit = "exit" .builtin_exit = "exit"
call strcmp, argv0, .builtin_exit call strcmp, argv0, .builtin_exit
b.z rax, 0, .handle_EXIT b.z rax, zero, .handle_EXIT
.builtin_help = "help" .builtin_help = "help"
call strcmp, argv0, .builtin_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" .builtin_print = "print"
call strcmp, argv0, .builtin_print call strcmp, argv0, .builtin_print
b.z rax, 0, .handle_PRINT b.z rax, zero, .handle_PRINT
.builtin_time = "time" .builtin_time = "time"
call strcmp, argv0, .builtin_time call strcmp, argv0, .builtin_time
b.z rax, 0, .handle_TIME b.z rax, zero, .handle_TIME
.builtin_ver = "ver" .builtin_ver = "ver"
call strcmp, argv0, .builtin_ver call strcmp, argv0, .builtin_ver
b.z rax, 0, .handle_VER b.z rax, zero, .handle_VER
jmp .command_not_found jmp .command_not_found
@ -167,7 +171,7 @@ main:
; call builtins ; call builtins
; ;
.handle_CLS: .handle_CLS:
prn 0xC15000AF prn PRN_CLEAR
jmp .print_prompt jmp .print_prompt
.handle_DATE: .handle_DATE:
@ -209,6 +213,12 @@ main:
.handle_EXIT: .handle_EXIT:
mov rax, Sys.Shutdown mov rax, Sys.Shutdown
trap 0 trap 0
jmp .print_prompt
.handle_HALT:
mov rax, Sys.EnterHaltMode
trap 0
jmp .print_prompt
.handle_PRINT: .handle_PRINT:
mov rax, Sys.OpenFile mov rax, Sys.OpenFile
@ -266,6 +276,7 @@ main:
call print, .helpmsg.echo call print, .helpmsg.echo
call print, .helpmsg.exit call print, .helpmsg.exit
call print, .helpmsg.help call print, .helpmsg.help
call print, .helpmsg.halt
call print, .helpmsg.print call print, .helpmsg.print
call print, .helpmsg.time call print, .helpmsg.time
call print, .helpmsg.ver call print, .helpmsg.ver
@ -280,6 +291,7 @@ main:
.helpmsg.echo = " ECHO Write arguments to standard output\n" .helpmsg.echo = " ECHO Write arguments to standard output\n"
.helpmsg.exit = " EXIT Initiate machine shutdown\n" .helpmsg.exit = " EXIT Initiate machine shutdown\n"
.helpmsg.help = " HELP Display these messages\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.print = " PRINT Display contents of text file\n"
.helpmsg.time = " TIME Display current time of day\n" .helpmsg.time = " TIME Display current time of day\n"
.helpmsg.ver = " VER Display current COMMAND.COM and DOS kernel versions\n" .helpmsg.ver = " VER Display current COMMAND.COM and DOS kernel versions\n"

View File

@ -6,7 +6,7 @@
verbose ?= yes verbose ?= yes
OBJDIR = ob 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) dv_src = $(shell ls dv/*.c)
in_src = $(shell ls in/*.c) in_src = $(shell ls in/*.c)

View File

@ -29,19 +29,19 @@ size_t rfs_current_idx = 0;
long cpudev_getmaxidx(ctx_t *ctx, dev_t *dev) long cpudev_getmaxidx(ctx_t *ctx, dev_t *dev)
{ {
rax = MAX_RFRAME_IDX; R(RAX) = MAX_RFRAME_IDX;
return 0; return 0;
} }
long cpudev_getrfusage(ctx_t *ctx, dev_t *dev) long cpudev_getrfusage(ctx_t *ctx, dev_t *dev)
{ {
rax = rfs_used; R(RAX) = rfs_used;
return 0; return 0;
} }
long cpudev_getcuridx(ctx_t *ctx, dev_t *dev) long cpudev_getcuridx(ctx_t *ctx, dev_t *dev)
{ {
rax = rfs_current_idx; R(RAX) = rfs_current_idx;
return 0; return 0;
} }
@ -53,12 +53,12 @@ long cpudev_leastavail(ctx_t *ctx, dev_t *dev)
{ {
if (rfs[it] == NULL) if (rfs[it] == NULL)
{ {
rax = it; R(RAX) = it;
return 0; return 0;
} }
} }
rax = -1; R(RAX) = -1;
return 0; return 0;
} }
@ -66,24 +66,24 @@ long cpudev_leastavail(ctx_t *ctx, dev_t *dev)
long cpudev_isactive(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; return 0;
} }
long cpudev_activate(ctx_t *ctx, dev_t *dev) 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, _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; return -1;
rfs_used++; rfs_used++;
@ -93,13 +93,13 @@ long cpudev_activate(ctx_t *ctx, dev_t *dev)
long cpudev_deactivate(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"); _except(ctx, E_UDF, "cpudev: deactivating rframe #0");
free(rfs[ax0]); free(rfs[R(AX0)]);
rfs[ax0] = NULL; rfs[R(AX0)] = NULL;
rfs_used--; rfs_used--;
assert(rfs_used > 0); 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) long cpudev_copyframe(ctx_t *ctx, dev_t *dev)
{ {
CHK_FRAME(ax0); CHK_FRAME(R(AX0));
CHK_FRAME(ax1); CHK_FRAME(R(AX1));
if (ax0 == ax1) if (R(AX0) == R(AX1))
return -1; return -1;
memcpy(rfs[ax0], rfs[ax1], NREGS * sizeof(ulong)); memcpy(rfs[R(AX0)], rfs[R(AX1)], NREGS * sizeof(ulong));
return 0; return 0;
} }
long cpudev_moveframe(ctx_t *ctx, dev_t *dev) long cpudev_moveframe(ctx_t *ctx, dev_t *dev)
{ {
CHK_INDEX(ax0); CHK_INDEX(R(AX0));
CHK_FRAME(ax1); CHK_FRAME(R(AX1));
if (ax1 == 0) if (R(AX1) == 0)
_except(ctx, E_UDF, "cpudev: trying to move frame #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 " _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[R(AX0)] = rfs[R(AX1)];
rfs[ax1] = NULL; rfs[R(AX1)] = NULL;
return 0; return 0;
} }
long cpudev_switchframe(ctx_t *ctx, dev_t *dev) long cpudev_switchframe(ctx_t *ctx, dev_t *dev)
{ {
CHK_FRAME(ax0); CHK_FRAME(R(AX0));
rfs_current_idx = ax0; rfs_current_idx = R(AX0);
ctx->rf = rfs[ax0]; ctx->rf = rfs[R(AX0)];
return 0; return 0;
} }
@ -154,39 +154,39 @@ long cpudev_switchframe(ctx_t *ctx, dev_t *dev)
long cpudev_loadargs(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(AX5) = rfs[R(AX0)][AX5];
R(AX4) = rfs[ax0][AX4]; R(AX4) = rfs[R(AX0)][AX4];
R(AX3) = rfs[ax0][AX3]; R(AX3) = rfs[R(AX0)][AX3];
R(AX2) = rfs[ax0][AX2]; R(AX2) = rfs[R(AX0)][AX2];
R(AX1) = rfs[ax0][AX1]; R(AX1) = rfs[R(AX0)][AX1];
R(AX0) = rfs[ax0][AX0]; R(AX0) = rfs[R(AX0)][AX0];
return 0; return 0;
} }
long cpudev_loadreg(ctx_t *ctx, dev_t *dev) 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, _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; return 0;
} }
long cpudev_storereg(ctx_t *ctx, dev_t *dev) long cpudev_storereg(ctx_t *ctx, dev_t *dev)
{ {
CHK_FRAME(ax0); CHK_FRAME(R(AX0));
if ((ushort)ax1 >= NREGS) if ((ushort)R(AX1) >= NREGS)
_except(ctx, E_UDF, "cpudev: register index out of range: #%u", ax1); _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; 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) long cpudev_idtadd(ctx_t *ctx, dev_t *dev)
{ {
CHK_FRAME(ax1); CHK_FRAME(R(AX1));
CHK_IDT_INDEX(ax0); CHK_IDT_INDEX(R(AX0));
if (idt[ax0] != 0) if (idt[R(AX0)] != 0)
_except(ctx, E_UDF, "cpudev: IDT slot index already in use: #%u", ax0); _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; return 0;
} }
long cpudev_idtdel(ctx_t *ctx, dev_t *dev) long cpudev_idtdel(ctx_t *ctx, dev_t *dev)
{ {
CHK_IDT_INDEX(ax0); CHK_IDT_INDEX(R(AX0));
if (idt[ax0] == 0) if (idt[R(AX0)] == 0)
_except(ctx, E_UDF, "cpudev: IDT slot index not in use: #%u", ax0); _except(ctx, E_UDF, "cpudev: IDT slot index not in use: #%u", R(AX0));
idt[ax0] = 0; idt[R(AX0)] = 0;
idt_handling[ax0] = 0; idt_handling[R(AX0)] = 0;
return 0; return 0;
} }
long cpudev_idtquery(ctx_t *ctx, dev_t *dev) long cpudev_idtquery(ctx_t *ctx, dev_t *dev)
{ {
if (ax0 >= IDT_SLOTS || idt[ax0] == 0) if (R(AX0) >= IDT_SLOTS || idt[R(AX0)] == 0)
rax = rdx = 0; R(RAX) = R(RDX) = 0;
else { else {
rax = 1; R(RAX) = 1;
rdx = idt[ax0]; R(RDX) = idt[R(AX0)];
} }
return 0; return 0;
@ -245,12 +245,12 @@ long cpudev_idtquery(ctx_t *ctx, dev_t *dev)
long cpudev_idtdone(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) if (idt_handling[R(AX0)] == 0)
_except(ctx, E_UDF, "cpudev: idtdone, not handling E/I #%u", ax0); _except(ctx, E_UDF, "cpudev: idtdone, not handling E/I #%u", R(AX0));
idt_handling[ax0]--; idt_handling[R(AX0)]--;
return 0; return 0;
} }

View File

@ -41,7 +41,7 @@ long diskdev_findnext(ctx_t *ctx, dev_t *dev)
if (ent == NULL) if (ent == NULL)
{ {
rax = 0; R(RAX) = 0;
return 0; return 0;
} }
@ -51,18 +51,18 @@ long diskdev_findnext(ctx_t *ctx, dev_t *dev)
break; 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); snprintf(name, NAME_MAX+4, "fs/%s", ent->d_name);
if (stat(name, &st) < 0) if (stat(name, &st) < 0)
{ {
perror("diskdev: couldn't stat file in directory: "); perror("diskdev: couldn't stat file in directory: ");
rdx = -1; R(RDX) = -1;
} }
else else
rdx = st.st_size; R(RDX) = st.st_size;
return 0; return 0;
} }
@ -85,7 +85,7 @@ long diskdev_open(ctx_t *ctx, dev_t *dev)
int fd, tmp; int fd, tmp;
char buf[NAME_MAX+4] = { 'f', 's', '/', 0 }; 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++) for (fd = 0; fd < MAXOPEN; fd++)
if (disk->table[fd] == 0) if (disk->table[fd] == 0)
@ -103,7 +103,7 @@ long diskdev_open(ctx_t *ctx, dev_t *dev)
} }
disk->table[fd] = tmp; disk->table[fd] = tmp;
rax = fd; R(RAX) = fd;
return 0; return 0;
} }
@ -112,13 +112,13 @@ long diskdev_close(ctx_t *ctx, dev_t *dev)
{ {
GETDISK(); GETDISK();
if (ax0 >= MAXOPEN) if (R(AX0) >= MAXOPEN)
return -1; return -1;
if (disk->table[ax0] <= 0) if (disk->table[R(AX0)] <= 0)
return -1; return -1;
close(disk->table[ax0]); close(disk->table[R(AX0)]);
return 0; return 0;
} }
@ -129,7 +129,7 @@ long diskdev_read(ctx_t *ctx, dev_t *dev)
{ {
GETDISK(); 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; return -1;
int ret; int ret;
@ -138,7 +138,7 @@ long diskdev_read(ctx_t *ctx, dev_t *dev)
if (buf == NULL) if (buf == NULL)
return -1; return -1;
ret = read(disk->table[ax0], buf, R(AX2)); ret = read(disk->table[R(AX0)], buf, R(AX2));
if (ret < 0) if (ret < 0)
{ {
@ -146,12 +146,11 @@ long diskdev_read(ctx_t *ctx, dev_t *dev)
return -1; return -1;
} }
rax = ret; R(RAX) = ret;
// Xxx dedicated function & faster copy // Xxx dedicated function & faster copy
for (; ret; ret--, ax1++, buf++) for (; ret; ret--, R(AX1)++, buf++)
writemem(ctx, *buf, ax1, 1); writemem(ctx, *buf, R(AX1), 1);
return 0; return 0;
} }

View File

@ -5,14 +5,14 @@
long memdev_getmemoff(ctx_t *ctx, dev_t *dev) long memdev_getmemoff(ctx_t *ctx, dev_t *dev)
{ {
rax = MEMOFF; R(RAX) = MEMOFF;
return 0; return 0;
} }
long memdev_getmemsize(ctx_t *ctx, dev_t *dev) long memdev_getmemsize(ctx_t *ctx, dev_t *dev)
{ {
rax = ctx->mz; R(RAX) = ctx->mz;
return 0; return 0;
} }

View File

@ -61,7 +61,7 @@ sar r r ri
# #
# CMP Comparison instruction # CMP Comparison instruction
# #
# $1 - $2 # SignExtend($1) - $2
# #
# Sets CF if unsigned integer overflow occur, clears it otherwise # Sets CF if unsigned integer overflow occur, clears it otherwise
# Sets OF is signed integer overflow occur, clears it otherwise # Sets OF is signed integer overflow occur, clears it otherwise

View File

@ -3,7 +3,7 @@
include "SUPER" include "SUPER"
include "ALU" include "ALU"
include "MOV" include "MEM"
include "MISC" include "MISC"
include "STRING" include "STRING"

View File

@ -25,7 +25,7 @@ loop ri
# #
# Conditional absolute jumps (B) # Conditional absolute jumps (B)
# #
# COMPARE($1, $2) # COMPARE(SignExtend($1), $2)
# #
# IF (COND) THEN # IF (COND) THEN
# RIP = $3 # RIP = $3
@ -114,28 +114,28 @@ pop r
lea r m lea r m
# #
# Movement with sign-extension (MOV) instruction # Move data (MOV) instruction
# #
# $1 = $2 # $1 = SignExtend($2)
# #
mov r rim mov r rim
mov m ri 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) # $1 = SignExtend($2 & (2^(8 * sizeof(x)) - 1)
# #
movsxb r r movsxb r r
movsxw r r movsxw r r
movsxl r r movsxd r r
#
# Movement with zero-extension (MOVZX) instruction
#
# $1 = ZeroExtend($2)
#
movzx r m
# #
# Exchange (XCHG) instruction # Exchange (XCHG) instruction

View File

@ -17,7 +17,7 @@
# #
stosb r ri stosb r ri
stosw r ri stosw r ri
stosl r ri stosd r ri
stosq r ri stosq r ri
# #
@ -44,7 +44,7 @@ stosq r ri
# #
scasb r ri scasb r ri
scasw r ri scasw r ri
scasl r ri scasd r ri
scasq r ri scasq r ri
#---------------------------------------------------------------------------# #---------------------------------------------------------------------------#

View File

@ -8,47 +8,66 @@
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
IMPL_START_3(or) { v1 = v2 | v3; } IMPL_OUT; IMPL_START(or) { *r1 = p2->val | p3->val; return 1; }
IMPL_START_3(and) { v1 = v2 & v3; } IMPL_OUT; IMPL_START(and) { *r1 = p2->val & p3->val; return 1; }
IMPL_START_3(xor) { v1 = v2 ^ v3; } IMPL_OUT; IMPL_START(xor) { *r1 = p2->val ^ p3->val; return 1; }
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
IMPL_START_3(shl) { v1 = v2 << v3; } IMPL_OUT; IMPL_START(shl) { *r1 = p2->val << p3->val; return 1; }
IMPL_START_3(shr) { v1 = v2 >> v3; } IMPL_OUT; IMPL_START(shr) { *r1 = p2->val >> p3->val; return 1; }
IMPL_START_3(sal) { v1 = (ulong)((long)v2 << (long)v3); } IMPL_OUT; IMPL_START(sal) { *r1 = (ulong)((long)p2->val << (long)p3->val); return 1; }
IMPL_START_3(sar) { v1 = (ulong)((long)v2 >> (long)v3); } IMPL_OUT; IMPL_START(sar) { *r1 = (ulong)((long)p2->val >> (long)p3->val); return 1; }
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
IMPL_START_3(add) { v1 = v2 + v3; } IMPL_OUT; IMPL_START(add) { *r1 = p2->val + p3->val; return 1; }
IMPL_START_3(addf) { COMPARE_ADD(v2, v3); v1 = v2 + v3; } IMPL_OUT; 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(mul) { *r1 = p2->val * p3->val; return 1; }
IMPL_START_3(sub) { v1 = v2 - v3; } IMPL_OUT; IMPL_START(rem) { *r1 = p2->val % p3->val; return 1; }
IMPL_START_3(subf){ COMPARE_SUB(v2, v3); v1 = v2 - v3; } IMPL_OUT;
//----------------------------------------------------------------------------// IMPL_START(div)
{
IMPL_START_3(adcx) { v3 += !!(R(RFX)&CF); COMPARE_ADD(v2, v3); v1 = v2 + v3; } IMPL_OUT; if (!p3->val)
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)
_except(ctx, E_DIV, "DIV by 0"); _except(ctx, E_DIV, "DIV by 0");
v1 = v2 / v3; *r1 = p2->val / p3->val;
} IMPL_OUT;
IMPL_START_3(idiv) { return 1;
if (!v3) }
IMPL_START(idiv)
{
if (!p3->val)
_except(ctx, E_DIV, "IDIV by 0"); _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; *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; ulong tmp;
__unsigned_multiply128(v2, v3, &tmp, &v1); __unsigned_multiply128(p2->val, p3->val, &tmp, r1);
R(RFX) = v2 ? (R(RFX)|CF|OF) : R(RFX)&~(CF|OF); R(RFX) = p2->val ? (R(RFX)|CF|OF) : R(RFX)&~(CF|OF);
} IMPL_OUT;
return 1;
}
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
@ -78,7 +104,11 @@ static void __signed_multiply128(ulong u, ulong v, ulong *hi, ulong *lo)
*lo = r; *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;
}
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//

View File

@ -5,80 +5,9 @@
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
#define DECV(v, p) \ #define IMPL_START(name) \
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) \
uint i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, acc_t *p3, \ uint i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, acc_t *p3, \
ulong *r1, ulong *r2, ulong *r3) \ 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_ZF(v); \
SET_SF(v) SET_SF(v)
#define SET_ZSPF(v) \
SET_ZF(v); \
SET_SF(v); \
SET_PF(v)
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
#define COMPARE_ADD(v1, v2) \ #define COMPARE_ADD(v1, v2) \

166
vm/in/mem.c Normal file
View 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;
}
//----------------------------------------------------------------------------//

View File

@ -9,12 +9,12 @@
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
IMPL_START_0(into) { INTO(); } IMPL_END; IMPL_START(into) { INTO(); return 0; }
IMPL_START_0(pause) { usleep(5000); } IMPL_END; IMPL_START(pause) { usleep(5000); return 0; }
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
IMPL_START_0(break) IMPL_START(break)
{ {
#ifndef NDEBUG #ifndef NDEBUG
trace("\nExecuting BREAK INSTR\n"); trace("\nExecuting BREAK INSTR\n");
@ -24,107 +24,116 @@ IMPL_START_0(break)
trace("Resuming execution\n"); trace("Resuming execution\n");
#endif #endif
return 0;
} }
IMPL_END;
IMPL_START_0(dump) IMPL_START(dump)
{ {
#ifndef NDEBUG #ifndef NDEBUG
if (ctx->dumpsw) if (ctx->dumpsw)
trace("0x%lX:\t...\n", rpc); trace("0x%lX:\t...\n", ctx->cur_pc);
else if (!ctx->dumpsw) else if (!ctx->dumpsw)
dump_instr(ctx, ctx->cur_in, p1, p2, p3, 0, 0); dump_instr(ctx, ctx->cur_in, p1, p2, p3, 0, 0);
ctx->dumpsw = !ctx->dumpsw; ctx->dumpsw = !ctx->dumpsw;
#endif #endif
return 0;
} }
IMPL_END;
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
IMPL_START_X_NOIN(ytime) IMPL_START(ytime)
{ {
time_t t = time(NULL); time_t t = time(NULL);
struct tm *tm = localtime(&t); 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_hour * 60 * 60
+ tm->tm_mday * 60 * 60 * 24; + tm->tm_mday * 60 * 60 * 24;
v2 = tm->tm_mon; *r2 = tm->tm_mon;
v3 = tm->tm_year + 1900; *r3 = tm->tm_year + 1900;
}
IMPL_OUT_3;
IMPL_START_1(utime) return 3;
}
IMPL_START(utime)
{ {
struct timeval time; struct timeval time;
gettimeofday(&time, NULL); 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; R(RFX) = 0;
for (int i = RAX; i <= R20; i++) R(i) = 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) ulong v = p2->val;
| ((v2 & 0x00FF000000000000) >> 40)
| ((v2 & 0x0000FF0000000000) >> 24)
| ((v2 & 0x000000FF00000000) >> 8)
| ((v2 & 0x00000000FF000000) << 8)
| ((v2 & 0x0000000000FF0000) << 24)
| ((v2 & 0x000000000000FF00) << 40)
| ((v2 & 0x00000000000000FF) << 56);
}
IMPL_OUT;
IMPL_START_2(wswap) *r1 = ((v & 0xFF00000000000000) >> 56)
{ | ((v & 0x00FF000000000000) >> 40)
v1 = ((v2 & 0xFFFF000000000000) >> 48) | ((v & 0x0000FF0000000000) >> 24)
| ((v2 & 0x0000FFFF00000000) >> 16) | ((v & 0x000000FF00000000) >> 8)
| ((v2 & 0x00000000FFFF0000) << 16) | ((v & 0x00000000FF000000) << 8)
| ((v2 & 0x000000000000FFFF) << 48); | ((v & 0x0000000000FF0000) << 24)
} | ((v & 0x000000000000FF00) << 40)
IMPL_OUT; | ((v & 0x00000000000000FF) << 56);
IMPL_START_2(dswap) return 1;
{ }
v1 = ((v2 & 0xFFFFFFFF00000000) >> 32)
| ((v2 & 0x00000000FFFFFFFF) << 32); 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? :) // Magic value? :)
if (__builtin_expect(v1 == 0xC15000AF, 0)) if (__builtin_expect(v == PRN_CLEAR_MAGIC, 0))
console_clear(ctx); console_clear(ctx);
else else if (v > 0)
{ console_putc(ctx, (char)v);
if (p1->mlen > 1) {
trace("prn warning: large access size\n");
}
if (v1 > 0)
console_putc(ctx, (char)v1);
}
}
IMPL_END
IMPL_START_0(prns) return 0;
}
IMPL_START(prns)
{ {
uchar ch = readmemzx(ctx, R(p1->reg), 1); uchar ch = readmemzx(ctx, R(p1->reg), 1);
@ -139,14 +148,16 @@ IMPL_START_0(prns)
else else
R(p1->reg)++; R(p1->reg)++;
} }
}
IMPL_END
IMPL_START_X_NOIN(scan) return 0;
{ }
v1 = console_scankeybuf(ctx);
IMPL_START(scan)
{
*r1 = console_scankeybuf(ctx);
return 1;
} }
IMPL_OUT;
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//

View File

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

View File

@ -13,24 +13,21 @@
static void stos_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len) static void stos_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len)
{ {
DECV(v2, p2); writemem(ctx, p2->val, R(p1->reg), len);
writemem(ctx, v2, R(p1->reg), len);
STR_MOVE(p1->reg, len); STR_MOVE(p1->reg, len);
} }
IMPL_START_0(stosb) { stos_impl(ctx, p1, p2, 1); } IMPL_END; IMPL_START(stosb) { stos_impl(ctx, p1, p2, 1); return 0; }
IMPL_START_0(stosw) { stos_impl(ctx, p1, p2, 2); } IMPL_END; IMPL_START(stosw) { stos_impl(ctx, p1, p2, 2); return 0; }
IMPL_START_0(stosl) { stos_impl(ctx, p1, p2, 4); } IMPL_END; IMPL_START(stosd) { stos_impl(ctx, p1, p2, 4); return 0; }
IMPL_START_0(stosq) { stos_impl(ctx, p1, p2, 8); } IMPL_END; 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) static void scas_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len)
{ {
DECV(v2, p2); ulong x = readmemsx(ctx, R(p1->reg), len);
COMPARE_SUB(x, p2->val);
ulong x = readmem(ctx, R(p1->reg), len);
COMPARE_SUB(x, v2);
if (x == 0) { if (x == 0) {
R(RFX) |= ZF; 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(scasb) { scas_impl(ctx, p1, p2, 1); return 0; }
IMPL_START_0(scasw) { scas_impl(ctx, p1, p2, 2); } IMPL_END; IMPL_START(scasw) { scas_impl(ctx, p1, p2, 2); return 0; }
IMPL_START_0(scasl) { scas_impl(ctx, p1, p2, 4); } IMPL_END; IMPL_START(scasd) { scas_impl(ctx, p1, p2, 4); return 0; }
IMPL_START_0(scasq) { scas_impl(ctx, p1, p2, 8); } IMPL_END; IMPL_START(scasq) { scas_impl(ctx, p1, p2, 8); return 0; }
//----------------------------------------------------------------------------//
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;
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//

View File

@ -31,19 +31,20 @@ void do_hlt(ctx_t *ctx)
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
IMPL_START_0(hlt) { CHK_SUPERV(); do_hlt(ctx); } IMPL_END; IMPL_START(hlt) { CHK_SUPERV(); do_hlt(ctx); return 0; }
IMPL_START_0(stop) { CHK_SUPERV(); _except(ctx, E_SHT, "STOP INSTR"); } IMPL_END; IMPL_START(stop) { CHK_SUPERV(); _except(ctx, E_SHT, "STOP INSTR"); }
IMPL_START_0(crash) { CHK_SUPERV(); _except(ctx, 1023, "CRASH instruction"); } IMPL_END; IMPL_START(crash) { CHK_SUPERV(); _except(ctx, 1023, "CRASH instruction"); }
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
IMPL_START_1(trap) { IMPL_START(trap)
if (v1 > 255) _except(ctx, E_ILL, "TRAP number greater than 255"); {
_except(ctx, v1 + 256, "TRAP instruction"); if (p1->val > 255) _except(ctx, E_ILL, "TRAP number greater than 255");
} IMPL_END; _except(ctx, p1->val + 256, "TRAP instruction");
}
IMPL_START_0(iret) { IMPL_START(iret) {
if (ctx->dumpsw) if (ctx->dumpsw)
trace("\nReturning from exception #%ld\n\n", R(R13)); trace("\nReturning from exception #%ld\n\n", R(R13));
@ -51,66 +52,69 @@ IMPL_START_0(iret) {
R(RIP) = R(R15); R(RIP) = R(R15);
rfs_current_idx = R(R14); rfs_current_idx = R(R14);
ctx->rf = rfs[R(R14)]; ctx->rf = rfs[R(R14)];
}
IMPL_END;
IMPL_START_0(cli) { CHK_SUPERV(); R(CR0) &= ~IF; } IMPL_END; return 0;
IMPL_START_0(sti) { CHK_SUPERV(); R(CR0) |= IF; } IMPL_END; }
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 // 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; if (!dev) R(RAX) = -2;
else if (dev->state == DEVPWOF) rax = -3; else if (dev->state == DEVPWOF) R(RAX) = -3;
else if (dev->state == DEVFERR) rax = -4; else if (dev->state == DEVFERR) R(RAX) = -4;
else if (dev->state == DEVPLUG) rax = -5; else if (dev->state == DEVPLUG) R(RAX) = -5;
else return dev; else return dev;
return NULL; return NULL;
} }
IMPL_START_2(devctl) IMPL_START(devctl)
{ {
CHK_SUPERV(); CHK_SUPERV();
dev_t *dev = devctl_common(ctx, v1, v2); dev_t *dev = devctl_common(ctx, p1->val);
if (dev == NULL) if (dev == NULL)
return 0; return 0;
switch (v2) { switch (p2->val) {
case 0: writestr(ctx, ax0, DEVLEN, dev->type); break; case 0: writestr(ctx, R(AX0), DEVLEN, dev->type); break;
case 1: writestr(ctx, ax0, DEVLEN, dev->name); break; case 1: writestr(ctx, R(AX0), DEVLEN, dev->name); break;
case 2: writestr(ctx, ax0, DEVLEN, dev->modl); break; case 2: writestr(ctx, R(AX0), DEVLEN, dev->modl); break;
case 3: writestr(ctx, ax0, DEVLEN, dev->vend); break; case 3: writestr(ctx, R(AX0), DEVLEN, dev->vend); break;
case 4: rax = dev->major; rdx = dev->minor; break; case 4: R(RAX) = dev->major; R(RDX) = dev->minor; break;
case 5: rax = dev->feats; rdx = dev->revis; break; case 5: R(RAX) = dev->feats; R(RDX) = dev->revis; break;
default: rax = -6; break; default: R(RAX) = -6; break;
} }
}
IMPL_END;
IMPL_START_2(iocall) return 0;
}
IMPL_START(iocall)
{ {
CHK_SUPERV(); CHK_SUPERV();
long rc; long rc;
dev_t *dev = devctl_common(ctx, v1, v2); dev_t *dev = devctl_common(ctx, p1->val);
if (dev == NULL) return 0; 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 { else {
rc = dev->fslots[v2](ctx, dev); rc = dev->fslots[p2->val](ctx, dev);
if (rc < 0) { rax = rc; rdx = 0; } if (rc < 0) { R(RAX) = rc; R(RDX) = 0; }
} }
return 0;
} }
IMPL_END;
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//

View File

@ -3,19 +3,26 @@
Instruction encoding: Instruction encoding:
15 0 15 0 Byte 1: Instruction number
xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx Byte 2:
│││└───────────┘ │└───┘└───┘└───┘ xx0xxxxx
│││ INSTR. │ FT3 FT2 FT1 || └───┘
│││ │ RL CND
LMC R
M No more words Values for ModRMs:
C COND suffix 000xxxxx xxxxx = reg
L LOCK suffix
R REP suffix (for memory accesses, xxxxx = access size)
FT1 First operand format 001xxxxx [reg]
FT2 Second operand format 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: Values for COND:
00000 (none) 00000 (none)
@ -33,19 +40,3 @@ Values for COND:
01100 .DXZ 01100 .DXZ
Highest (6th) bit of COND indicates negation 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

View File

@ -62,12 +62,9 @@ struct ctx_t
ulong cur_pc; ulong cur_pc;
// Memory and memory size // Memory and memory size
ushort *mp; uchar *mp;
ulong mz; ulong mz;
// Read next instruction
ushort (*get)(ctx_t *ctx);
// Devices list head // Devices list head
dev_t *dh; dev_t *dh;

View File

@ -7,24 +7,40 @@
// Read the "DECD" file before reading this code // 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) return v;
ok = (fmt == A_REG); }
else if (prm == P_IMM) static ushort fetchw(ctx_t *ctx)
ok = (fmt == A_IMM64); {
ushort v = *(ushort *)(ctx->mp + R(RIP) + R(CR1) - MEMOFF);
R(RIP) += 2;
else /* if (prm == P_MEM) */ return v;
ok = ACC_FMT_IS_MEM(fmt); }
if (!ok) static uint fetchd(ctx_t *ctx)
_except(ctx, E_ILL, {
"FT%d not matching %s's expected parameter types: " uint v = *(uint *)(ctx->mp + R(RIP) + R(CR1) - MEMOFF);
"fmt=0x%x prm=0x%x", which, in->full, fmt, prm); 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; static const int lentab[9] = { 0, 1, 1, 0, 1, 0, 0, 0, 1 };
ushort temp;
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); checkreg(ctx, p->reg);
p->val = R(p->reg); p->val = R(p->reg);
return; return;
} }
else if (fmt == A_IMM64) //
// Immediates
//
if (hi == 7)
{ {
p->val = ctx->get(ctx); if (prm != P_IMM)
p->val |= (ulong)ctx->get(ctx) << 16; _except(ctx, E_ILL, "Not expecting an immediate: %s",
p->val |= (ulong)ctx->get(ctx) << 32; ctx->cur_in->full);
p->val |= (ulong)ctx->get(ctx) << 48;
return;
}
assert(ACC_FMT_IS_MEM(fmt)); switch (lo)
{
// Handle a memory access case 1:
p->type = A_IMM8;
mlen = fmt & AM_MLEN_MASK; p->val = fetchb(ctx);
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;
break; 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) case 2:
* (long)(short)p->imm1 p->type = A_IMM16;
+ (long)(short)p->imm2; p->val = fetchw(ctx);
break; break;
case 4:
p->type = A_IMM32;
p->val = fetchd(ctx);
break;
case 8:
p->type = A_IMM64;
p->val = fetchq(ctx);
break;
default: 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) void decode(ctx_t *ctx)
{ {
instr_t *in; instr_t *in;
uchar f1 = 0, f2 = 0, f3 = 0; ushort b1, b2, rep = 0, lock;
ushort w1, w2, rep = 0, lock, nomore;
acc_t p1 = { 0 }, p2 = { 0 }, p3 = { 0 }; acc_t p1 = { 0 }, p2 = { 0 }, p3 = { 0 };
rpc = R(RIP); ctx->cur_pc = R(RIP);
// Process the first word of the instruction // Address range check
w1 = ctx->get(ctx); // (assumes max. instruction length is 32 bytes)
lock = !!(w1 & SUFF_LOCK); if (R(RIP) + R(CR1) - MEMOFF >= ctx->mz - 32)
nomore = !!(w1 & SUFF_NOMORE); _except(ctx, E_ACC, "Executing out of memory");
if (w1 & SUFF_COND) // Instruction bytes
ctx->cond = ctx->get(ctx); b1 = fetchb(ctx);
else b2 = fetchb(ctx);
ctx->cond = 0;
w1 &= ~(SUFF_LOCK|SUFF_NOMORE|SUFF_COND); // Renge check
if (b1 >= NINSTRS)
if (w1 >= NINSTRS) _except(ctx, E_ILL, "No such INSTR: 0x%hhX", b1);
_except(ctx, E_ILL, "No such INSTR: 0x%hX", w1);
// Find instruction // Find instruction
in = &ctx->i[w1]; in = &ctx->i[b1];
ctx->cur_in = in; ctx->cur_in = in;
// Second word? // Get flags/etc
if (!nomore) rep = !!(b2 & SUFF_REP);
{ lock = !!(b2 & SUFF_LOCK);
w2 = ctx->get(ctx); ctx->cond = b2 & SUFF_COND;
// REP and COND
rep = !!(w2 & SUFF_REP);
// Fn
f3 = (w2 >> F3_SHIFT) & Fx_MASK;
f2 = (w2 >> F2_SHIFT) & Fx_MASK;
f1 = w2 & Fx_MASK;
}
// Operand 1? // Operand 1?
if (in->prm1 == NOPRM) 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); exec_instr(ctx, in, NULL, NULL, NULL, lock, rep);
return; return;
} }
check_param_type(ctx, in, in->prm1, f1, 1); extract_param(ctx, in->prm1, &p1);
extract_param(ctx, &p1, f1);
// Operand 2? // Operand 2?
if (in->prm2 == NOPRM) 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); exec_instr(ctx, in, &p1, NULL, NULL, lock, rep);
return; return;
} }
check_param_type(ctx, in, in->prm2, f2, 2); extract_param(ctx, in->prm2, &p2);
extract_param(ctx, &p2, f2);
// Operand 1? // Operand 1?
if (in->prm3 == NOPRM) 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); exec_instr(ctx, in, &p1, &p2, NULL, lock, rep);
return; return;
} }
check_param_type(ctx, in, in->prm3, f3, 3); extract_param(ctx, in->prm3, &p3);
extract_param(ctx, &p3, f3);
exec_instr(ctx, in, &p1, &p2, &p3, lock, rep); exec_instr(ctx, in, &p1, &p2, &p3, lock, rep);
} }

View File

@ -20,41 +20,28 @@ enum
enum enum
{ {
SUFF_LOCK = (1 << 15), SUFF_REP = (1 << 7),
SUFF_NOMORE = (1 << 14), SUFF_LOCK = (1 << 6),
SUFF_COND = (1 << 13), SUFF_COND = 0b00011111,
SUFF_REP = (1 << 15),
Fx_MASK = 0x1F,
F3_SHIFT = 10,
F2_SHIFT = 5,
}; };
enum enum
{ {
A_NONE = 0b00000, A_NONE = 0b00000,
A_REG = 0b00001, 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 = 0xF0,
AM_RR = 0b01, AM_RRI = 0xF1,
AM_RRI = 0b10, AM_RRII = 0xF2,
AM_RRII = 0b11,
AM_8ACC = 0b00100,
AM_16ACC = 0b01000,
AM_32ACC = 0b01100,
AM_64ACC = 0b10000,
AM_MLEN_MASK = 0b11100,
AM_MFMT_MASK = 0b00011,
}; };
#define ACC_FMT_IS_MEM(x) ((x) >= AM_START && (x) <= (AM_64ACC|AM_RRII)) #define ACC_FMT_IS_MEM(x) (((x) & 0xF0) != 0)
#define ACC_IS_MEM(p) ACC_FMT_IS_MEM((p)->type)
#define ACC_IS_MEM(x) (ACC_FMT_IS_MEM((x)->type))
struct acc_t struct acc_t
{ {
@ -62,15 +49,16 @@ struct acc_t
ulong val; ulong val;
// A_REG // A_REG
ulong reg; uchar reg;
// AM_... // AM_...
ulong addr; ulong addr;
uint mlen; uint mlen;
// For instruction dumping ONLY // For instruction dumping ONLY
ushort reg1, reg2; uchar reg1, reg2;
short imm1, imm2; char imm1;
long imm2;
}; };
enum { NOPRM, P_REG, P_IMM, P_MEM=4 }; enum { NOPRM, P_REG, P_IMM, P_MEM=4 };
@ -98,10 +86,6 @@ void exec_instr(ctx_t *ctx,
bool lock, bool lock,
bool rep); bool rep);
void extract_param(ctx_t *ctx,
acc_t *p,
uchar fmt);
void dump_instr(ctx_t *ctx, void dump_instr(ctx_t *ctx,
instr_t *in, instr_t *in,
acc_t *p1, acc_t *p1,

View File

@ -26,7 +26,7 @@ void dump_instr(ctx_t *ctx,
{ {
uint cond = ctx->cond; uint cond = ctx->cond;
trace("0x%lX:\t", rpc); trace("0x%lX:\t", ctx->cur_pc);
if (lock) if (lock)
trace("lock"); trace("lock");
@ -41,9 +41,7 @@ void dump_instr(ctx_t *ctx,
trace("."); trace(".");
if (cond & (1 << 4)) if (cond & (1 << 4))
{
trace("n"); trace("n");
}
assert((cond & ~(1 << 4)) <= sizeof(cond_suffixes)/sizeof(char *)); 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); trace("%s", ctx->r[p->reg].name);
else if (p->type == A_IMM64) 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) if (p->val < 0xA)
trace("%lu", p->val); 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 else
{ {
trace("%c[", getmempref(p->mlen)); trace("%c[", getmempref(p->mlen));
mfmt = p->type & AM_MFMT_MASK; mfmt = p->type;
if (mfmt == AM_IMM64)
trace("0x%lX]", p->addr);
else if (mfmt == AM_RR) if (mfmt == AM_RR)
{ {
if (p->reg1 && p->reg2) if (p->reg1 && p->reg2)
trace("%s+%s]", ctx->r[p->reg1].name, ctx->r[p->reg2].name); 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) else if (mfmt == AM_RRI)
{ {
if (p->reg1 && p->reg2) if (p->reg1 && p->reg2)
trace("%s+%s%c%hd]", trace("%s+%s%c%ld]",
ctx->r[p->reg1].name, ctx->r[p->reg1].name,
ctx->r[p->reg2].name, ctx->r[p->reg2].name,
((short)p->imm2 < 0 ? '-' : '+'), (p->imm2 < 0 ? '-' : '+'),
ABS(p->imm2)); ABS(p->imm2));
else trace("%s%c%hd]", else trace("%s%c%ld]",
ctx->r[p->reg1 ? p->reg1 : p->reg2].name, ctx->r[p->reg1 ? p->reg1 : p->reg2].name,
((short)p->imm2 < 0 ? '-' : '+'), (p->imm2 < 0 ? '-' : '+'),
ABS(p->imm2)); ABS(p->imm2));
} }
else if (mfmt == AM_RRII) else if (mfmt == AM_RRII)
{ {
if (p->reg1) if (p->reg1)
trace("%s+%s*%hd%c%hd]", trace("%s+%s*%hhd%c%ld]",
ctx->r[p->reg1].name, ctx->r[p->reg1].name,
ctx->r[p->reg2].name, p->imm1, ctx->r[p->reg2].name, p->imm1,
((short)p->imm2 < 0 ? '-' : '+'), (p->imm2 < 0 ? '-' : '+'),
ABS(p->imm2)); ABS(p->imm2));
else else
trace("%s*%hd%c%hd]", trace("%s*%hhd%c%ld]",
ctx->r[p->reg2].name, p->imm1, ctx->r[p->reg2].name, p->imm1,
((short)p->imm2 < 0 ? '-' : '+'), (p->imm2 < 0 ? '-' : '+'),
ABS(p->imm2)); ABS(p->imm2));
} }
} }

View File

@ -78,7 +78,7 @@ void _except(ctx_t *ctx, int _code, char *fmt, ...)
trace("\nException %u - ", code); trace("\nException %u - ", code);
va_start(ap, fmt); va_start(ap, fmt);
vlog(fmt, ap); vprintf(fmt, ap);
va_end(ap); va_end(ap);
trace("\n\n"); trace("\n\n");
@ -105,7 +105,7 @@ actually_die:
logerr("\nException %u - ", code); logerr("\nException %u - ", code);
va_start(ap, fmt); va_start(ap, fmt);
vlog(fmt, ap); vfprintf(stderr, fmt, ap);
va_end(ap); va_end(ap);
logerr("\n\n"); logerr("\n\n");

View File

@ -63,7 +63,7 @@ void exec_instr(ctx_t *ctx,
ulong r1 = 0, r2 = 0, r3 = 0; ulong r1 = 0, r2 = 0, r3 = 0;
// Global instruction counter // Global instruction counter
fc0++; ctx->ninstrs++;
// //
// For REPs we evaluate the condition AFTER running the instruction, // 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); dump_instr(ctx, in, p1, p2, p3, lock, rep);
do_rep: do_rep:
assert(R(RZX) == 0);
out = in->func(ctx, p1, p2, p3, &r1, &r2, &r3); out = in->func(ctx, p1, p2, p3, &r1, &r2, &r3);
if (out) if (out)
@ -102,7 +100,7 @@ do_rep:
return; return;
// Should we really count REP's in instruction count? // Should we really count REP's in instruction count?
fc0++; ctx->ninstrs++;
#if 0 #if 0
// Show that we're REP'ing // Show that we're REP'ing
if (ctx->dumpsw) if (ctx->dumpsw)

View File

@ -3,17 +3,6 @@
#include <pc/arch.h> #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, ...) void logerr(const char *fmt, ...)
{ {
va_list ap; va_list ap;
@ -23,8 +12,3 @@ void logerr(const char *fmt, ...)
va_end(ap); va_end(ap);
} }
void vlog(const char *fmt, va_list ap)
{
vfprintf(stderr, fmt, ap);
}

View File

@ -11,23 +11,6 @@
static ssize_t fwsize; static ssize_t fwsize;
static ushort *fwprog; 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; ctx_t main_ctx;
void sigcommon(void) void sigcommon(void)
@ -53,9 +36,10 @@ jmp_buf exc_jmp_buf;
// //
void main_loop(void) void main_loop(void)
{ {
/*
if (main_ctx.dumpsw) if (main_ctx.dumpsw)
trace("\n\n\n"); trace("\n\n\n");
*/
setjmp(exc_jmp_buf); setjmp(exc_jmp_buf);
// //
@ -78,7 +62,7 @@ int main(int argc, char **argv)
main_ctx.r = arch_r; main_ctx.r = arch_r;
main_ctx.i = arch_i; main_ctx.i = arch_i;
#if 0 && defined(NDEBUG) #if 1 && !defined(NDEBUG)
main_ctx.dumpsw = 1; main_ctx.dumpsw = 1;
#endif #endif
@ -141,7 +125,6 @@ int main(int argc, char **argv)
main_ctx.mp = malloc(MEMSIZE + 16); main_ctx.mp = malloc(MEMSIZE + 16);
main_ctx.mz = MEMSIZE; main_ctx.mz = MEMSIZE;
main_ctx.get = bget;
main_ctx.rf[RIP] = MEMOFF; main_ctx.rf[RIP] = MEMOFF;
if (main_ctx.mp == 0) { if (main_ctx.mp == 0) {

View File

@ -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) static ulong readmem8(ctx_t *ctx, ulong real, ulong addr)
{ {
if (addr % 2 == 0) return (ulong)ctx->mp[real] & 0xFF; return (ulong)ctx->mp[real];
else return ((ulong)ctx->mp[real] & 0xFF00) >> 8;
} }
static ulong readmem16(ctx_t *ctx, ulong real, ulong addr) static ulong readmem16(ctx_t *ctx, ulong real, ulong addr)
{ {
CHK_ALIGN(ushort); CHK_ALIGN(ushort);
return (ulong)ctx->mp[real]; return (ulong)*(ushort *)(ctx->mp + real);
} }
static ulong readmem32(ctx_t *ctx, ulong real, ulong addr) static ulong readmem32(ctx_t *ctx, ulong real, ulong addr)
{ {
CHK_ALIGN(uint); CHK_ALIGN(uint);
ulong val = ctx->mp[real++]; return (ulong)*(uint *)(ctx->mp + real);
val = val | ((ulong)ctx->mp[real] << 16);
return val;
} }
static ulong readmem64(ctx_t *ctx, ulong real, ulong addr) static ulong readmem64(ctx_t *ctx, ulong real, ulong addr)
{ {
CHK_ALIGN(ulong); CHK_ALIGN(ulong);
ulong val = (ulong)ctx->mp[real++]; return (ulong)*(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;
} }
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
static void writemem8(ctx_t *ctx, ulong val, ulong real, ulong addr) static void writemem8(ctx_t *ctx, ulong val, ulong real, ulong addr)
{ {
ushort v = ctx->mp[real]; ctx->mp[real] = val & 0xFF;
if (!(addr % 2)) {
ctx->mp[real] = (v & 0xFF00) | (val & 0xFF);
}
else {
ctx->mp[real] = (v & 0xFF) | (((val & 0xFF) << 8));
}
} }
static void writemem16(ctx_t *ctx, ulong val, ulong real, ulong addr) static void writemem16(ctx_t *ctx, ulong val, ulong real, ulong addr)
{ {
CHK_ALIGN(ushort); *(ushort*)(ctx->mp + real) = val & 0xFFFF;
ctx->mp[real] = val & 0xFFFF;
} }
static void writemem32(ctx_t *ctx, ulong val, ulong real, ulong addr) static void writemem32(ctx_t *ctx, ulong val, ulong real, ulong addr)
{ {
CHK_ALIGN(uint); CHK_ALIGN(uint);
ctx->mp[real++] = val & 0xFFFF; *(uint*)(ctx->mp + real) = val & 0xFFFFFFFF;
ctx->mp[real] = (val >> 16) & 0xFFFF;
} }
static void writemem64(ctx_t *ctx, ulong val, ulong real, ulong addr) static void writemem64(ctx_t *ctx, ulong val, ulong real, ulong addr)
{ {
CHK_ALIGN(ulong); CHK_ALIGN(ulong);
ctx->mp[real++] = val; *(ulong*)(ctx->mp + real) = val;
ctx->mp[real++] = (val >> 16) & 0xFFFF;
ctx->mp[real++] = (val >> 32) & 0xFFFF;
ctx->mp[real] = (val >> 48) & 0xFFFF;
} }
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
@ -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(); GETREAL();
CHK_RANGE(); CHK_RANGE();
@ -143,23 +135,23 @@ ulong readmem(ctx_t *ctx, ulong addr, uint len)
switch (len) { switch (len) {
case 1: case 1:
val = readmem8(ctx, real, addr); val = readmem8(ctx, real, addr);
val = (ulong)(long)(char)(val & 0xFF); val = (ulong)(long)(char)val;
break; break;
case 2: case 2:
val = readmem16(ctx, real, addr); val = readmem16(ctx, real, addr);
val = (ulong)(long)(short)(val & 0xFFFF); val = (ulong)(long)(short)val;
break; break;
case 4: case 4:
val = readmem32(ctx, real, addr); val = readmem32(ctx, real, addr);
val = (ulong)(long)(int)(val & 0xFFFFFFFF); val = (ulong)(long)(int)val;
break; break;
case 8: case 8:
return readmem64(ctx, real, addr); 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; 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();
}
}
//----------------------------------------------------------------------------//

View File

@ -5,15 +5,15 @@ static inline ushort bswap16(ushort u)
{ return ((u<<8) | (u>>8)); } { return ((u<<8) | (u>>8)); }
static inline char getmempref(ushort len) 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 MEMOFF (1 * 1024 * 1024)
#define MEMSIZE (16 * 1024 * 1024) // 16MB #define MEMSIZE (16 * 1024 * 1024) // 16MB
#define MAXADDR 0x8000000000000 // 2^48 - 1 #define MAXADDR 0x8000000000000 // 2^48 - 1
#define addr2real(p) (((p) - MEMOFF) / 2) #define addr2real(p) ((p) - MEMOFF)
#define real2addr(p) (((p) + MEMOFF) / 2) #define real2addr(p) ((p) + MEMOFF)
// Address of boot firmware stack // Address of boot firmware stack
#define FWSTACK (MEMOFF * 2) // 2MB #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 readstr(ctx_t *ctx, ulong addr, ulong maxn, char *buf);
ulong writestr(ctx_t *ctx, ulong addr, ulong maxn, char *str); 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); 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) \ #define SIGN_EXTEND(val, mask) \
(val & ((mask + 1) >> 1) \ (val & ((mask + 1) >> 1) \

View File

@ -26,9 +26,9 @@ void dumpregs(ctx_t *ctx)
TRACE("Current RFRAME index: #%lu", rfs_current_idx); TRACE("Current RFRAME index: #%lu", rfs_current_idx);
TRACE("\n\nEnviron:"); 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("\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("\n\nArgument:");
TRACE("\nax0=0x%-16lX ax1=0x%-16lX ax2=0x%-16lX", R(AX0), R(AX1), R(AX2)); TRACE("\nax0=0x%-16lX ax1=0x%-16lX ax2=0x%-16lX", R(AX0), R(AX1), R(AX2));

View File

@ -45,12 +45,6 @@ enum
NREGS NREGS
}; };
#define fc0 ctx->ninstrs #define _fc0 ctx->ninstrs
#define rpc ctx->cur_pc #define _rpc ctx->cur_pc
#define rax R(RAX)
#define rdx R(RDX)
#define ax0 R(AX0)
#define ax1 R(AX1)