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':
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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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)
{
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; }
//----------------------------------------------------------------------------//

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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)
{
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();
}
}
//----------------------------------------------------------------------------//

View File

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

View File

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

View File

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