mirror of
https://gitlab.os-k.eu/os-k-team/kvisc.git
synced 2023-08-25 14:05:46 +02:00
vm
This commit is contained in:
parent
3d002108a4
commit
cbd079d2a0
93
as/k-as.py
93
as/k-as.py
@ -369,52 +369,6 @@ def parse_preproc(line):
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
pconds = {
|
||||
'c': 0b00001,
|
||||
'o': 0b00010,
|
||||
'z': 0b00011,
|
||||
'e': 0b00011,
|
||||
's': 0b00100,
|
||||
|
||||
'pe': 0b00101,
|
||||
'po': 0b10101,
|
||||
|
||||
'b': 0b00001,
|
||||
'be': 0b00110,
|
||||
'l': 0b00111,
|
||||
'le': 0b01000,
|
||||
|
||||
'a': 0b10110, # nbe
|
||||
'ae': 0b10001, # nb
|
||||
'g': 0b11000, # nle
|
||||
'ge': 0b10111, # nl
|
||||
|
||||
'axz': 0b01001,
|
||||
'bxz': 0b01010,
|
||||
'cxz': 0b01011,
|
||||
'dxz': 0b01100,
|
||||
|
||||
'axnz': 0b11001,
|
||||
'bxnz': 0b11010,
|
||||
'cxnz': 0b11011,
|
||||
'dxnz': 0b11100,
|
||||
}
|
||||
|
||||
def get_cond_mask(cond, line):
|
||||
mask = 0
|
||||
|
||||
if cond[0] == 'n':
|
||||
cond = cond[1:]
|
||||
mask = 0b10000
|
||||
|
||||
if cond not in pconds:
|
||||
print("Invalid condition suffix: {}".format(line))
|
||||
leave(1)
|
||||
|
||||
return (mask | pconds[cond])
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
fmts = {
|
||||
"r": 0b00000000,
|
||||
"m_r": 0b00100000,
|
||||
@ -456,40 +410,11 @@ def parse_instr(line):
|
||||
params = None
|
||||
|
||||
size = 1
|
||||
|
||||
# Byte 2 (rep|lock|0|cond)
|
||||
b2 = 0
|
||||
|
||||
if len(instr) > 2 and '.' in instr:
|
||||
instr, suf = instr.split('.', 1)
|
||||
|
||||
if len(instr) == 0:
|
||||
print("Missing instruction name before suffixes: {}".format(line))
|
||||
|
||||
if len(suf) > 2 and suf[:3] == "rep":
|
||||
if len(suf) > 3:
|
||||
suf = suf[3:]
|
||||
|
||||
if len(suf) > 0 and suf[0] == '.':
|
||||
suf = suf[1:]
|
||||
else:
|
||||
suf = ''
|
||||
|
||||
b2 |= 1<<7 # REP
|
||||
|
||||
if len(suf) > 0:
|
||||
b2 |= get_cond_mask(suf, line)
|
||||
|
||||
instr_name = instr
|
||||
instr_args = ''
|
||||
|
||||
if params == None or len(params) == 0:
|
||||
if b2 == 0:
|
||||
instrs.write("{}_0".format(instr_name))
|
||||
|
||||
else:
|
||||
size += 1
|
||||
instrs.write("%%suff {}_0 %%imm8 {}".format(instr_name, b2))
|
||||
instrs.write("{}_0".format(instr_name))
|
||||
|
||||
return size
|
||||
|
||||
@ -721,19 +646,13 @@ def parse_instr(line):
|
||||
|
||||
instr_args += word
|
||||
|
||||
if b2 == 0:
|
||||
instrs.write("{} {}".format(instr_name, instr_args))
|
||||
|
||||
else:
|
||||
size += 1
|
||||
instrs.write("%%suff {} %%imm8 {} {}".format(instr_name, b2, instr_args))
|
||||
instrs.write("{}{}".format(instr_name, instr_args))
|
||||
|
||||
return size
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
special_syms = {
|
||||
"%%suff",
|
||||
"%%imm8",
|
||||
"%%imm16",
|
||||
"%%imm32",
|
||||
@ -749,7 +668,6 @@ def gentext():
|
||||
data_start += (8 - data_start % 8)
|
||||
|
||||
instrs.seek(0)
|
||||
suff_mask = 0
|
||||
|
||||
for _, line in enumerate(instrs):
|
||||
tok = line.strip().split()
|
||||
@ -769,9 +687,8 @@ def gentext():
|
||||
continue
|
||||
|
||||
if word in pinstrs:
|
||||
idx = pinstrs.index(word) | suff_mask
|
||||
idx = pinstrs.index(word)
|
||||
b_text.write(idx.to_bytes(1, byteorder='little', signed=False))
|
||||
suff_mask = 0
|
||||
continue
|
||||
|
||||
if word in plabels_text:
|
||||
@ -785,9 +702,7 @@ def gentext():
|
||||
continue
|
||||
|
||||
if word in special_syms:
|
||||
if word == "%%suff":
|
||||
suff_mask = 1<<7
|
||||
elif word == "%%imm8":
|
||||
if word == "%%imm8":
|
||||
lastimm = 1
|
||||
elif word == "%%imm16":
|
||||
lastimm = 2
|
||||
|
25
as/regs.lst
25
as/regs.lst
@ -1,18 +1,10 @@
|
||||
$rzx $zero
|
||||
$cr0
|
||||
$cr1
|
||||
$cr2
|
||||
$rfx
|
||||
$rip
|
||||
$rbp
|
||||
$rsp
|
||||
|
||||
$rax $r0
|
||||
$rbx $r1
|
||||
$rcx $r2
|
||||
$rdx $r3
|
||||
$rsi $r4
|
||||
$rdi $r5
|
||||
|
||||
$ax0 $r6
|
||||
$ax1 $r7
|
||||
$ax2 $r8
|
||||
@ -29,6 +21,19 @@ $nx5 $r17
|
||||
$nx6 $r18
|
||||
$nx7 $r19
|
||||
$nx8 $r20
|
||||
|
||||
$grp $r21
|
||||
$trp $r22
|
||||
$srp $r22
|
||||
$srp $r23
|
||||
|
||||
$tmp $r24
|
||||
$rad $r25
|
||||
|
||||
$cr0 $r26
|
||||
$cr1 $r27
|
||||
|
||||
$rip $r28
|
||||
$rbp $r29
|
||||
$rsp $r30
|
||||
|
||||
$zero $r31
|
||||
|
40
ka/crt/crt.k
40
ka/crt/crt.k
@ -5,47 +5,49 @@
|
||||
; Limits
|
||||
;
|
||||
|
||||
CHAR_MIN := 0x0000000000000080
|
||||
SHRT_MIN := 0x0000000000008000
|
||||
INT_MIN := 0x0000000080000000
|
||||
CHAR_MIN := 0x80
|
||||
SHRT_MIN := 0x8000
|
||||
INT_MIN := 0x80000000
|
||||
LONG_MIN := 0x8000000000000000
|
||||
|
||||
XCHAR_MIN := 0xFFFFFFFFFFFFFF80
|
||||
XSHRT_MIN := 0xFFFFFFFFFFFF8000
|
||||
XINT_MIN := 0xFFFFFFFF80000000
|
||||
|
||||
CHAR_MAX := 0x000000000000007F
|
||||
SHRT_MAX := 0x0000000000007FFF
|
||||
INT_MAX := 0x000000007FFFFFFF
|
||||
CHAR_MAX := 0x7F
|
||||
SHRT_MAX := 0x7FFF
|
||||
INT_MAX := 0x7FFFFFFF
|
||||
LONG_MAX := 0x7FFFFFFFFFFFFFFF
|
||||
|
||||
BYTE_MAX := 0x00000000000000FF
|
||||
WORD_MAX := 0x000000000000FFFF
|
||||
LWORD_MAX := 0x00000000FFFFFFFF
|
||||
BYTE_MAX := 0xFF
|
||||
WORD_MAX := 0xFFFF
|
||||
LWORD_MAX := 0xFFFFFFFF
|
||||
QWORD_MAX := 0xFFFFFFFFFFFFFFFF
|
||||
|
||||
FILE_MAXSZ := 0x0000000000008000
|
||||
STRLEN_MAX := 0x000000007AFFFFFF
|
||||
FNAME_MAX := 0x0000000000000080
|
||||
FNAME_MAX := 0x80
|
||||
FILE_MAXSZ := 0x8000
|
||||
STRLEN_MAX := 0x7AFFFFFF
|
||||
|
||||
;
|
||||
; Magic numbers
|
||||
;
|
||||
|
||||
PRN_CLEAR := 0x000000008BF00001
|
||||
PRN_FLUSH := 0x000000008BF00002
|
||||
PRN_CLEAR := 0x8BF00001
|
||||
PRN_FLUSH := 0x8BF00002
|
||||
|
||||
;
|
||||
; CRT librairies
|
||||
;
|
||||
|
||||
include "crt/sys.k"
|
||||
include "crt/err/errno.k"
|
||||
include "crt/fmt/format.k"
|
||||
include "crt/str/string.k"
|
||||
include "crt/mem/memory.k"
|
||||
include "crt/lib/time.k"
|
||||
include "crt/str.k"
|
||||
include "crt/mem.k"
|
||||
include "crt/time.k"
|
||||
|
||||
include "crt/fmt/ltostr.k"
|
||||
include "crt/fmt/strtol.k"
|
||||
include "crt/fmt/doprnt.k"
|
||||
include "crt/fmt/printf.k"
|
||||
abort:
|
||||
crash
|
||||
|
||||
|
@ -1,7 +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.
|
||||
|
||||
EINVAL := 1
|
||||
errno = 0
|
||||
|
||||
EOK := 0
|
@ -15,14 +15,14 @@ doprnt:
|
||||
mov r12, ax2 ; fmt
|
||||
mov r14, ax3 ; va_list
|
||||
mov r15, ax1 ; n
|
||||
mov r16, zero ; return value
|
||||
mov r17, ax0 ; putc
|
||||
nul r16 ; return value
|
||||
|
||||
.main_loop:
|
||||
; find '%' or null-terminator
|
||||
mov rcx, STRLEN_MAX
|
||||
mov r13, r12
|
||||
scasb.rep.nz r13, '%'
|
||||
scasb r13, '%'
|
||||
|
||||
; everything below r13 is a regular character; print it
|
||||
.print_regular:
|
||||
@ -62,7 +62,7 @@ doprnt:
|
||||
bzr r13, .nullstring
|
||||
|
||||
.print_string:
|
||||
mov ax0, b[r13]
|
||||
movzx ax0, b[r13]
|
||||
bzr ax0, .main_loop
|
||||
|
||||
inc r13, 1
|
||||
@ -107,7 +107,7 @@ doprnt:
|
||||
inc r14, 8
|
||||
|
||||
.print_itoa_buf:
|
||||
mov ax0, b[r13]
|
||||
movzx ax0, b[r13]
|
||||
|
||||
bzr ax0, .pib_end_loop
|
||||
inc r13, 1
|
||||
@ -144,8 +144,9 @@ doprnt:
|
||||
.epilogue:
|
||||
mov rax, r16
|
||||
|
||||
pop r17, r16, r15
|
||||
pop r14, r13, r12
|
||||
pop r17, r16
|
||||
pop r15, r14
|
||||
pop r13, r12
|
||||
|
||||
leave
|
||||
ret
|
||||
@ -170,7 +171,7 @@ doprnt:
|
||||
jraxz .r
|
||||
|
||||
; yes, so artificially set n=0
|
||||
mov r15, zero
|
||||
nul r15
|
||||
|
||||
.r:
|
||||
ret
|
||||
|
@ -1,8 +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 "crt/fmt/ltostr.k"
|
||||
include "crt/fmt/strtol.k"
|
||||
include "crt/fmt/doprnt.k"
|
||||
include "crt/fmt/printf.k"
|
||||
|
@ -12,7 +12,7 @@ itoa:
|
||||
; void utoa(char *buf, int num, int base)
|
||||
;
|
||||
utoa:
|
||||
mov ax3, zero
|
||||
nul ax3
|
||||
jmp ltostr
|
||||
|
||||
;
|
||||
@ -20,7 +20,7 @@ utoa:
|
||||
;
|
||||
ltostr:
|
||||
mov rax, ax0
|
||||
mov rcx, zero
|
||||
nul rcx
|
||||
|
||||
; make sure base is in [2, 32]
|
||||
bltu ax2, 2, .bad
|
||||
@ -37,7 +37,7 @@ ltostr:
|
||||
shr rcx, ax1, 63 ; extract ax1 sign
|
||||
jrcxz .conv
|
||||
|
||||
sub ax1, zero, ax1 ; NEG if negative
|
||||
neg ax1 ; NEG if negative
|
||||
|
||||
; main loop
|
||||
.conv:
|
||||
@ -68,7 +68,7 @@ ltostr:
|
||||
inc ax0, 1
|
||||
|
||||
.cxz:
|
||||
mov b[ax0], zero
|
||||
nul b[ax0]
|
||||
|
||||
call strrev2, rax
|
||||
ret
|
||||
@ -77,7 +77,6 @@ ltostr:
|
||||
; exceptional cases
|
||||
;
|
||||
.bad:
|
||||
mov q[errno], EINVAL
|
||||
mov b[ax0], 0
|
||||
ret
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
;
|
||||
putc:
|
||||
prn ax0
|
||||
mov rax, zero
|
||||
nul rax
|
||||
ret
|
||||
|
||||
;
|
||||
|
@ -18,7 +18,7 @@ strtol:
|
||||
; rdx = pointer to first invalid byte
|
||||
;
|
||||
strtoul:
|
||||
mov ax2, zero
|
||||
nul ax2
|
||||
jmp strtoq
|
||||
|
||||
;
|
||||
@ -27,8 +27,7 @@ strtoul:
|
||||
; guesses base when 'base'=0
|
||||
;
|
||||
strtoq:
|
||||
mov rax, zero
|
||||
mov rsi, zero
|
||||
nul rax, rsi
|
||||
mov rdx, ax0
|
||||
|
||||
; make sure base is in [2, 32]
|
||||
@ -158,12 +157,11 @@ strtoq:
|
||||
bzr rsi, .r
|
||||
|
||||
; yes
|
||||
sub rax, zero, rax
|
||||
neg rax
|
||||
|
||||
.r:
|
||||
ret
|
||||
|
||||
.bad:
|
||||
mov q[errno], EINVAL
|
||||
ret
|
||||
|
||||
|
@ -24,7 +24,7 @@ memzero:
|
||||
jrcxz .r
|
||||
|
||||
.l:
|
||||
mov b[ax0], zero
|
||||
nul b[ax0]
|
||||
inc ax0, 1
|
||||
loop .l
|
||||
|
222
ka/crt/str.k
Normal file
222
ka/crt/str.k
Normal file
@ -0,0 +1,222 @@
|
||||
; The OS/K Team licenses this file to you under the MIT license.
|
||||
; See the LICENSE file in the project root for more information.
|
||||
|
||||
;
|
||||
; int strnlen(char *, int)
|
||||
;
|
||||
strnlen:
|
||||
mov rcx, ax1
|
||||
scasb ax0, zero
|
||||
|
||||
sub rax, ax1, rcx
|
||||
ret
|
||||
|
||||
;
|
||||
; int strlen(char *)
|
||||
;
|
||||
strlen:
|
||||
mov rcx, STRLEN_MAX
|
||||
mov rdx, rcx
|
||||
scasb ax0, zero
|
||||
|
||||
sub rax, rdx, rcx
|
||||
ret
|
||||
|
||||
;
|
||||
; void strcpy(char *, const char *)
|
||||
;
|
||||
strcpy:
|
||||
.l:
|
||||
mov rcx, b[ax1]
|
||||
mov b[ax0], rcx
|
||||
|
||||
jrcxz .r
|
||||
|
||||
inc ax0, 1
|
||||
inc ax1, 1
|
||||
|
||||
jmp .l
|
||||
|
||||
.r:
|
||||
ret
|
||||
|
||||
;
|
||||
; void strncpy(char *, const char *, int)
|
||||
;
|
||||
strncpy:
|
||||
mov rcx, ax2
|
||||
jrcxz .r
|
||||
|
||||
.l:
|
||||
mov b[ax0], b[ax1]
|
||||
|
||||
inc ax0, 1
|
||||
inc ax1, 1
|
||||
|
||||
loop .l
|
||||
|
||||
.r:
|
||||
ret
|
||||
|
||||
;
|
||||
; void strnzcpy(char *, const char *, int)
|
||||
;
|
||||
strnzcpy:
|
||||
mov rcx, ax2
|
||||
jrcxz .r
|
||||
|
||||
.l:
|
||||
mov rax, b[ax1]
|
||||
mov b[ax0], rax
|
||||
|
||||
jraxz .r
|
||||
|
||||
inc ax0, 1
|
||||
inc ax1, 1
|
||||
|
||||
loop .l
|
||||
|
||||
.z:
|
||||
nul b[ax0]
|
||||
|
||||
.r:
|
||||
ret
|
||||
|
||||
;
|
||||
; int strcmp(const char *str1, const char *str2)
|
||||
;
|
||||
; Returns:
|
||||
; 0 if the contents of both strings are equal
|
||||
; >0 if the first character that does not match has a greater 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:
|
||||
nul rsi
|
||||
.l:
|
||||
movzx rax, b[ax0+rsi]
|
||||
movzx rdx, b[ax1+rsi]
|
||||
|
||||
bne rax, rdx, .r
|
||||
|
||||
; both zero?
|
||||
add rcx, rax, rdx
|
||||
jrcxz .r
|
||||
|
||||
inc rsi, 1
|
||||
jmp .l
|
||||
|
||||
.r:
|
||||
dec rax, rdx
|
||||
ret
|
||||
|
||||
;
|
||||
; int strncmp(const char *str1, const char *str2, int maxn)
|
||||
;
|
||||
strncmp:
|
||||
mov rcx, ax2
|
||||
jrcxz .r
|
||||
|
||||
.l:
|
||||
movzx rax, b[ax0]
|
||||
movzx rdx, b[ax1]
|
||||
|
||||
bne rax, rdx, .r
|
||||
|
||||
inc ax0, 1
|
||||
inc ax1, 1
|
||||
loop .l
|
||||
|
||||
.r:
|
||||
dec rax, rdx
|
||||
ret
|
||||
|
||||
;
|
||||
; char *strchrnul(const char *str, int ch)
|
||||
;
|
||||
strchrnul:
|
||||
mov rcx, STRLEN_MAX
|
||||
scasb ax0, ax1
|
||||
|
||||
mov rax, ax0
|
||||
ret
|
||||
|
||||
;
|
||||
; char *strchr(const char *str, int ch)
|
||||
;
|
||||
strchr:
|
||||
mov rcx, STRLEN_MAX
|
||||
scasb ax0, ax1
|
||||
|
||||
bnz b[ax0], .r
|
||||
nul rax
|
||||
ret
|
||||
|
||||
.r:
|
||||
mov rax, ax0
|
||||
ret
|
||||
|
||||
;
|
||||
; void strrev(char *buf, const char *str)
|
||||
;
|
||||
; buf and src must NOT overlap
|
||||
;
|
||||
strrev:
|
||||
bzr b[ax1], .z
|
||||
|
||||
; save str's location
|
||||
mov rsi, ax1
|
||||
|
||||
; go to str's end, just before
|
||||
; the null terminator
|
||||
mov rcx, STRLEN_MAX
|
||||
scasb ax1, zero
|
||||
dec ax1, 1
|
||||
|
||||
.l:
|
||||
; copy, going backward though str
|
||||
; and forward through buf
|
||||
mov b[ax0], b[ax1]
|
||||
|
||||
beq ax1, rsi, .r
|
||||
|
||||
inc ax0, 1
|
||||
dec ax1, 1
|
||||
jmp .l
|
||||
|
||||
.r:
|
||||
nul b[ax0+1]
|
||||
ret
|
||||
|
||||
.z:
|
||||
nul b[ax0]
|
||||
ret
|
||||
|
||||
;
|
||||
; void strrev2(char *str)
|
||||
;
|
||||
; Inverses str
|
||||
;
|
||||
strrev2:
|
||||
bzr b[ax0], .r
|
||||
|
||||
mov ax1, ax0
|
||||
|
||||
; go to str's end, just before
|
||||
; the null terminator
|
||||
mov rcx, STRLEN_MAX
|
||||
scasb ax1, zero
|
||||
dec ax1, 1
|
||||
|
||||
; increase ax0 while decreasing ax1, performing exchanges
|
||||
.l:
|
||||
blteu ax1, ax0, .r
|
||||
|
||||
xchg b[ax0], b[ax1]
|
||||
|
||||
inc ax0, 1
|
||||
dec ax1, 1
|
||||
jmp .l
|
||||
|
||||
.r:
|
||||
ret
|
||||
|
@ -1,27 +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 *strchrnul(const char *str, int ch)
|
||||
;
|
||||
strchrnul:
|
||||
mov rcx, STRLEN_MAX
|
||||
scasb.rep.nz ax0, ax1
|
||||
|
||||
mov rax, ax0
|
||||
ret
|
||||
|
||||
;
|
||||
; char *strchr(const char *str, int ch)
|
||||
;
|
||||
strchr:
|
||||
mov rcx, STRLEN_MAX
|
||||
scasb.rep.nz ax0, ax1
|
||||
|
||||
bnz b[ax0], .r
|
||||
mov rax, zero
|
||||
ret
|
||||
|
||||
.r:
|
||||
mov rax, ax0
|
||||
ret
|
@ -1,51 +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.
|
||||
|
||||
;
|
||||
; int strcmp(const char *str1, const char *str2)
|
||||
;
|
||||
; Returns:
|
||||
; 0 if the contents of both strings are equal
|
||||
; >0 if the first character that does not match has a greater 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:
|
||||
mov rsi, zero
|
||||
.l:
|
||||
movzx rax, b[ax0+rsi]
|
||||
movzx rdx, b[ax1+rsi]
|
||||
|
||||
bne rax, rdx, .r
|
||||
|
||||
; both zero?
|
||||
add rcx, rax, rdx
|
||||
jrcxz .r
|
||||
|
||||
inc rsi, 1
|
||||
jmp .l
|
||||
|
||||
.r:
|
||||
dec rax, rdx
|
||||
ret
|
||||
|
||||
;
|
||||
; int strncmp(const char *str1, const char *str2, int maxn)
|
||||
;
|
||||
strncmp:
|
||||
mov rcx, ax2
|
||||
jrcxz .r
|
||||
|
||||
.l:
|
||||
movzx rax, b[ax0]
|
||||
movzx rdx, b[ax1]
|
||||
|
||||
bne rax, rdx, .r
|
||||
|
||||
inc ax0, 1
|
||||
inc ax1, 1
|
||||
loop .l
|
||||
|
||||
.r:
|
||||
dec rax, rdx
|
||||
ret
|
||||
|
@ -1,63 +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.
|
||||
|
||||
;
|
||||
; void strcpy(char *, const char *)
|
||||
;
|
||||
strcpy:
|
||||
.l:
|
||||
mov rcx, b[ax1]
|
||||
mov b[ax0], rcx
|
||||
|
||||
jrcxz .r
|
||||
|
||||
inc ax0, 1
|
||||
inc ax1, 1
|
||||
|
||||
jmp .l
|
||||
|
||||
.r:
|
||||
ret
|
||||
|
||||
;
|
||||
; void strncpy(char *, const char *, int)
|
||||
;
|
||||
strncpy:
|
||||
mov rcx, ax2
|
||||
jrcxz .r
|
||||
|
||||
.l:
|
||||
mov b[ax0], b[ax1]
|
||||
|
||||
inc ax0, 1
|
||||
inc ax1, 1
|
||||
|
||||
loop .l
|
||||
|
||||
.r:
|
||||
ret
|
||||
|
||||
;
|
||||
; void strnzcpy(char *, const char *, int)
|
||||
;
|
||||
strnzcpy:
|
||||
mov rcx, ax2
|
||||
jrcxz .r
|
||||
|
||||
.l:
|
||||
mov rax, b[ax1]
|
||||
mov b[ax0], rax
|
||||
|
||||
jraxz .r
|
||||
|
||||
inc ax0, 1
|
||||
inc ax1, 1
|
||||
|
||||
loop .l
|
||||
|
||||
.z:
|
||||
mov b[ax0], zero
|
||||
|
||||
.r:
|
||||
ret
|
||||
|
@ -1,9 +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 "crt/str/strlen.k"
|
||||
include "crt/str/strrev.k"
|
||||
include "crt/str/strcpy.k"
|
||||
include "crt/str/strcmp.k"
|
||||
include "crt/str/strchr.k"
|
||||
|
@ -1,24 +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.
|
||||
|
||||
;
|
||||
; int strnlen(char *, int)
|
||||
;
|
||||
strnlen:
|
||||
mov rcx, ax1
|
||||
scasb.rep.nz ax0, zero
|
||||
|
||||
sub rax, ax1, rcx
|
||||
ret
|
||||
|
||||
;
|
||||
; int strlen(char *)
|
||||
;
|
||||
strlen:
|
||||
mov rcx, STRLEN_MAX
|
||||
mov rdx, rcx
|
||||
scasb.rep.nz ax0, zero
|
||||
|
||||
sub rax, rdx, rcx
|
||||
ret
|
||||
|
@ -1,72 +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.
|
||||
|
||||
;
|
||||
; void strrev(char *buf, const char *str)
|
||||
;
|
||||
; buf and src must NOT overlap
|
||||
;
|
||||
strrev:
|
||||
bzr b[ax1], .z
|
||||
|
||||
; save str's location
|
||||
mov rsi, ax1
|
||||
|
||||
; go to str's end, just before
|
||||
; the null terminator
|
||||
mov rcx, STRLEN_MAX
|
||||
scasb.rep.nz ax1, zero
|
||||
dec ax1, 1
|
||||
|
||||
.l:
|
||||
; copy, going backward though str
|
||||
; and forward through buf
|
||||
mov b[ax0], b[ax1]
|
||||
|
||||
beq ax1, rsi, .r
|
||||
|
||||
inc ax0, 1
|
||||
dec ax1, 1
|
||||
jmp .l
|
||||
|
||||
.r:
|
||||
mov b[ax0+1], zero
|
||||
ret
|
||||
|
||||
.z:
|
||||
mov b[ax0], zero
|
||||
ret
|
||||
|
||||
;
|
||||
; void strrev2(char *str)
|
||||
;
|
||||
; Inverses str
|
||||
;
|
||||
strrev2:
|
||||
bzr b[ax0], .r
|
||||
|
||||
mov ax1, ax0
|
||||
|
||||
; go to str's end, just before
|
||||
; the null terminator
|
||||
mov rcx, STRLEN_MAX
|
||||
scasb.rep.nz ax1, zero
|
||||
dec ax1, 1
|
||||
|
||||
; increase ax0 while decreasing ax1, performing exchanges
|
||||
.l:
|
||||
blteu ax1, ax0, .r
|
||||
|
||||
xchg b[ax0], b[ax1]
|
||||
|
||||
inc ax0, 1
|
||||
dec ax1, 1
|
||||
jmp .l
|
||||
|
||||
.r:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -45,32 +45,33 @@ DaysInYear:
|
||||
; TIME *GetTimeUTC(void)
|
||||
;
|
||||
GetTimeUTC:
|
||||
ytime ax0, ax1, ax2
|
||||
mov rdx, .buf
|
||||
ytime
|
||||
|
||||
mov rdi, .buf
|
||||
|
||||
; seconds
|
||||
rem rcx, ax0, 60
|
||||
mov b[rdx], rcx
|
||||
rem rsi, rax, 60
|
||||
mov b[rdi], rsi
|
||||
|
||||
; minutes
|
||||
div rcx, ax0, 60
|
||||
rem rcx, 60
|
||||
mov b[rdx+1], rcx
|
||||
div rsi, rax, 60
|
||||
rem rsi, 60
|
||||
mov b[rdi+1], rsi
|
||||
|
||||
; hours
|
||||
div rcx, ax0, 3600
|
||||
rem rcx, 24
|
||||
mov b[rdx+2], rcx
|
||||
div rsi, rax, 3600
|
||||
rem rsi, 24
|
||||
mov b[rdi+2], rsi
|
||||
|
||||
; month days
|
||||
div rcx, ax0, 3600*24
|
||||
mov b[rdx+3], rcx
|
||||
div rsi, rax, 3600*24
|
||||
mov b[rdi+3], rsi
|
||||
|
||||
; month
|
||||
mov b[rdx+4], ax1
|
||||
mov b[rdi+4], rbx
|
||||
|
||||
; years
|
||||
mov w[rdx+6], ax2
|
||||
mov w[rdi+6], rcx
|
||||
|
||||
;
|
||||
; ydays (TODO)
|
@ -26,7 +26,7 @@ start:
|
||||
mov rsp, DOSKRNL_STACK
|
||||
mov rbp, zero
|
||||
|
||||
; dump
|
||||
;dump
|
||||
|
||||
call main
|
||||
|
||||
|
@ -15,15 +15,13 @@ def mkstat(fp):
|
||||
if len(tok) == 0:
|
||||
continue
|
||||
|
||||
i = tok[0].split('.')[0]
|
||||
|
||||
if len(i) == 0 or i in ';#@/':
|
||||
if len(tok[0]) == 0 or tok[0] in ';#@/':
|
||||
continue
|
||||
|
||||
if i in instrs:
|
||||
instrs[i] += 1
|
||||
if tok[0] in instrs:
|
||||
instrs[tok[0]] += 1
|
||||
else:
|
||||
instrs[i] = 1
|
||||
instrs[tok[0]] = 1
|
||||
|
||||
for root, _, files in os.walk('.'):
|
||||
for f in files:
|
||||
|
@ -9,18 +9,12 @@ dumprf:
|
||||
mov r12, ax0
|
||||
mov r13, rsp
|
||||
|
||||
call RFS.LoadReg, r12, $cr2
|
||||
push rax
|
||||
|
||||
call RFS.LoadReg, r12, $cr1
|
||||
push rax
|
||||
|
||||
call RFS.LoadReg, r12, $cr0
|
||||
push rax
|
||||
|
||||
call RFS.LoadReg, r12, $rfx
|
||||
push rax
|
||||
|
||||
call RFS.LoadReg, r12, $rip
|
||||
push rax
|
||||
|
||||
@ -33,7 +27,7 @@ dumprf:
|
||||
call RFS.LoadReg, r12, $trp
|
||||
push rax
|
||||
|
||||
push 0 # fixme
|
||||
push zero # fixme
|
||||
|
||||
call RFS.LoadReg, r12, $rbp
|
||||
push rax
|
||||
@ -120,7 +114,7 @@ dumprf:
|
||||
leave
|
||||
ret
|
||||
|
||||
.dmp1 = "Environ #1:\nfrm=0d%d rip=0x%x rfx=0x%x\ncr0=0x%x cr1=0x%x cr2=0x%x\n\n"
|
||||
.dmp1 = "Environ #1:\nfrm=0d%d rip=0x%x\ncr0=0x%x cr1=0x%x\n\n"
|
||||
.dmp2 = "Environ #2:\nrsp=0x%x rbp=0x%x ind=0d%d\ngrp=0x%x trp=0x%x srp=0x%x\n\n"
|
||||
.dmp3 = "Argument:\nax0=0x%x ax1=0x%x ax2=0x%x\nax3=0x%x ax4=0x%x ax5=0x%x\n\n"
|
||||
.dmp4 = "Volatile:\nrax=0x%x rbx=0x%x rcx=0x%x\nrdx=0x%x rsi=0x%x rdi=0x%x\n\n"
|
||||
|
@ -11,7 +11,7 @@ ScreenOfDeath:
|
||||
|
||||
push ax1
|
||||
call printf, .scr1
|
||||
pop zero
|
||||
pop
|
||||
|
||||
bnz r14, .not_con
|
||||
push .scr2_con
|
||||
|
@ -18,7 +18,7 @@ DefaultExceptionHandler:
|
||||
|
||||
.err_ukn = "Unknown exception number\0\0\0\0\0\0\0"
|
||||
.err_udf = "Undefined behaviour exception\0\0"
|
||||
.err_ill = "Ill-formed exception exception\0"
|
||||
.err_ill = "Illformed instruction exception"
|
||||
.err_acc = "Invalid memory access exception"
|
||||
.err_sys = "Supervisor-only exception used\0"
|
||||
.err_dbf = "Double fault exception~~~~~~~~\0"
|
||||
|
@ -2,14 +2,14 @@
|
||||
; See the LICENSE file in the project root for more information.
|
||||
|
||||
TrapHandlers.prolog:
|
||||
mov rbp, zero
|
||||
nul rbp
|
||||
|
||||
; rax = caller's cr2
|
||||
call RFS.LoadReg, r14, $cr2
|
||||
; rax = caller's cr1
|
||||
call RFS.LoadReg, r14, $cr1
|
||||
|
||||
; we don't preserve the r12 we got
|
||||
mov r12, rax
|
||||
mov rdx, zero
|
||||
nul rdx
|
||||
|
||||
jmp rcx
|
||||
|
||||
@ -105,12 +105,8 @@ DefaultTrapHandler:
|
||||
mov ax2, rcx
|
||||
call RFS.StoreReg, zero, $cr1
|
||||
|
||||
; Data offset
|
||||
mov ax2, rcx
|
||||
call RFS.StoreReg, zero, $cr2
|
||||
|
||||
; Return frame
|
||||
mov r14, zero
|
||||
nul r14
|
||||
|
||||
jmp .fini
|
||||
|
||||
|
@ -10,9 +10,9 @@ builtins.dir:
|
||||
push r12, r13
|
||||
push r14, r15
|
||||
|
||||
mov r12, zero # no. of files found
|
||||
mov r13, zero # no. of directories found
|
||||
mov r14, zero # total amount of bytes found
|
||||
nul r12 # no. of files found
|
||||
nul r13 # no. of directories found
|
||||
nul r14 # total amount of bytes found
|
||||
|
||||
call print, .dirmsg
|
||||
|
||||
@ -46,7 +46,7 @@ builtins.dir:
|
||||
mov rcx, FNAME_MAX
|
||||
mov rsi, .buf
|
||||
mov rdi, rsi
|
||||
scasb.rep.nz rsi, '.'
|
||||
scasb rsi, '.'
|
||||
|
||||
; print file name
|
||||
sub ax1, rsi, rdi
|
||||
|
@ -21,14 +21,16 @@ main:
|
||||
.print_prompt:
|
||||
call print, prompt
|
||||
|
||||
; empty argbuf
|
||||
; empty stuff
|
||||
call memzero, argbuf, argbuf.size
|
||||
call nprint, argbuf, argbuf.size
|
||||
call memzero, argv0, argbuf.size
|
||||
nul q[argv1pos]
|
||||
|
||||
# call nprint, argv0, argbuf.size
|
||||
|
||||
; iterator through argbuf
|
||||
mov rcx, zero
|
||||
nul rcx
|
||||
|
||||
mov q[argv1pos], zero
|
||||
|
||||
.input_loop:
|
||||
pause
|
||||
@ -51,7 +53,7 @@ main:
|
||||
; yes, delete it
|
||||
dec rcx, 1
|
||||
add rdx, rcx, argbuf
|
||||
mov b[rdx], zero
|
||||
nul b[rdx]
|
||||
|
||||
; update screen
|
||||
bzr b[stdin_echoing], .input_loop
|
||||
@ -86,7 +88,7 @@ main:
|
||||
; find first whitespace or null-terminator
|
||||
mov rcx, argbuf.size
|
||||
mov rdx, argbuf
|
||||
scasb.rep.nz rdx, ' '
|
||||
scasb rdx, ' '
|
||||
|
||||
; argv1 exists? if so, save its position
|
||||
mov rsi, rdx
|
||||
@ -108,9 +110,6 @@ main:
|
||||
; fallthrough
|
||||
|
||||
.do_extract:
|
||||
; empty argv0
|
||||
call memzero, argv0, argbuf.size
|
||||
|
||||
; how much do we copy?
|
||||
sub rcx, rdx, argbuf
|
||||
jrcxz .detect_builtin
|
||||
|
@ -250,6 +250,8 @@ long cpudev_idtdone(dev_t *dev)
|
||||
if (idt_handling[R(AX0)] == 0)
|
||||
_except(E_UDF, "cpudev: idtdone, not handling E/I #%u", R(AX0));
|
||||
|
||||
//trace("IDT.DONE %lu\n", R(AX0));
|
||||
|
||||
idt_handling[R(AX0)]--;
|
||||
|
||||
return 0;
|
||||
|
102
vm/in/ALU
102
vm/in/ALU
@ -5,113 +5,83 @@
|
||||
# Logical instructions #
|
||||
#---------------------------------------------------------------------------#
|
||||
|
||||
#
|
||||
# Bitwise OR operation
|
||||
#
|
||||
# $dest = $src1 OR $src2
|
||||
#
|
||||
# Bitwise NOT
|
||||
not 1
|
||||
|
||||
# Bitwise OR
|
||||
or 2
|
||||
or 3
|
||||
|
||||
#
|
||||
# Bitwise AND operation
|
||||
#
|
||||
# $dest = $src1 AND $src2
|
||||
#
|
||||
# Bitwise AND
|
||||
and 2
|
||||
and 3
|
||||
|
||||
#
|
||||
# Bitwise XOR operation
|
||||
#
|
||||
# $dest = $src1 XOR $src2
|
||||
#
|
||||
# Bitwise XOR
|
||||
xor 2
|
||||
xor 3
|
||||
|
||||
#
|
||||
# Logical left/right shift (SHL/SHR)
|
||||
#
|
||||
# $dest = $src1 << $src2 (SHL)
|
||||
# $dest = $src1 >> $src2 (SHR)
|
||||
#
|
||||
# Logical left/right shift
|
||||
shl 2
|
||||
shl 3
|
||||
shr 2
|
||||
shr 3
|
||||
|
||||
#
|
||||
# Arithmetical right shift (SAR)
|
||||
#
|
||||
# $dest = $src1 >>> $src2 (SAR)
|
||||
#
|
||||
# Arithmetical right shift
|
||||
sar 2
|
||||
sar 3
|
||||
|
||||
#---------------------------------------------------------------------------#
|
||||
# Arithmetic instructions #
|
||||
#---------------------------------------------------------------------------#
|
||||
#
|
||||
# Arithmetical ADD operation
|
||||
#
|
||||
# $dest1 = $src1 + $src2
|
||||
#
|
||||
|
||||
# Negation
|
||||
neg 1
|
||||
|
||||
# Negation but traps on $src == -2^N
|
||||
negv 1
|
||||
|
||||
# Addition
|
||||
add 2
|
||||
add 3
|
||||
|
||||
#
|
||||
# Arithmetical SUB operation
|
||||
#
|
||||
# $dest = $src1 - $src2
|
||||
#
|
||||
# Addition but traps on overflow
|
||||
addv 2
|
||||
addv 3
|
||||
|
||||
# Substraction
|
||||
sub 2
|
||||
sub 3
|
||||
|
||||
#
|
||||
# Arithmetical MUL operation
|
||||
#
|
||||
# $dest = LO($src1 * $src2)
|
||||
#
|
||||
# Substraction but traps on underflow
|
||||
subv 2
|
||||
subv 3
|
||||
|
||||
# Multiplication
|
||||
# $dest = LO($src1 * $src2)
|
||||
mul 2
|
||||
mul 3
|
||||
|
||||
# Arithmetical unsigned MUL operation
|
||||
#
|
||||
# $dest1 = HI($dest2 * $src)
|
||||
# $dest2 = LO($dest2 * $src)
|
||||
# Multiplication (unsigned)
|
||||
# $dest1 = HI($dest2 * $src)
|
||||
# $dest2 = LO($dest2 * $src)
|
||||
#
|
||||
mulhi 3
|
||||
|
||||
# Arithmetical signed MUL operation
|
||||
#
|
||||
# $dest1 = HI($dest2 ** $src)
|
||||
# $dest2 = LO($dest2 ** $src)
|
||||
# Multiplication (signed)
|
||||
# $dest1 = HI($dest2 * $src)
|
||||
# $dest2 = LO($dest2 * $src)
|
||||
#
|
||||
imulhi 3
|
||||
|
||||
#
|
||||
# Arithmetical unsigned DIV operation
|
||||
#
|
||||
# $dest = $src1 DIV $src2
|
||||
#
|
||||
# Preserves all flags
|
||||
#
|
||||
# Division (unsigned)
|
||||
div 2
|
||||
div 3
|
||||
|
||||
#
|
||||
# Arithmetical signed DIV operation
|
||||
#
|
||||
# $dest = $src1 IDIV $src2
|
||||
#
|
||||
# Division (signed)
|
||||
idiv 2
|
||||
idiv 3
|
||||
|
||||
#
|
||||
# Arithmetical modulo operation (REM)
|
||||
#
|
||||
# $dest = $src1 MOD $src2
|
||||
#
|
||||
# Modulo/remainder
|
||||
rem 2
|
||||
rem 3
|
||||
|
||||
|
24
vm/in/MEM
24
vm/in/MEM
@ -57,14 +57,17 @@ push 3
|
||||
# $1 = *RSP
|
||||
# RSP = RSP + 8
|
||||
#
|
||||
pop 0
|
||||
pop 1
|
||||
pop 2
|
||||
pop 3
|
||||
|
||||
#---------------------------------------------------------------------------#
|
||||
# Movement instructions #
|
||||
#---------------------------------------------------------------------------#
|
||||
|
||||
nul 1
|
||||
nul 2
|
||||
|
||||
#
|
||||
# Load Effective Address (LEA) instruction
|
||||
#
|
||||
@ -78,27 +81,22 @@ pop 3
|
||||
lea 2
|
||||
|
||||
#
|
||||
# Move data (MOV) instruction
|
||||
# Move data (MOV/MOVU) instructions
|
||||
#
|
||||
# $1 = SignExtend($2)
|
||||
# $1 = SignExtend($2) (MOV)
|
||||
# $1 = ZeroExtend($2) (MOVU)
|
||||
#
|
||||
mov 2
|
||||
|
||||
#
|
||||
# Load from memory with zero-extension (MOVSX/MOVZX) instruction
|
||||
#
|
||||
# $1 = ZeroExtend($2)
|
||||
#
|
||||
movzx 2
|
||||
|
||||
#
|
||||
# Move with sign-extension (MOVSXx) instruction
|
||||
# Move with sign-extension (MOVx) instruction
|
||||
#
|
||||
# $1 = SignExtend($2 & (2^(8 * sizeof(x)) - 1)
|
||||
#
|
||||
movsxb 2
|
||||
movsxw 2
|
||||
movsxd 2
|
||||
movb 2
|
||||
movw 2
|
||||
movd 2
|
||||
|
||||
#
|
||||
# Exchange (XCHG) instruction
|
||||
|
@ -45,7 +45,7 @@ utime 1
|
||||
# $2 = current month
|
||||
# $3 = current year
|
||||
#
|
||||
ytime 3
|
||||
ytime 0
|
||||
|
||||
#
|
||||
# Clear all GPR registers except RBP/RSP
|
||||
|
22
vm/in/STRING
22
vm/in/STRING
@ -8,24 +8,18 @@
|
||||
#
|
||||
# Scan string for a particular value (SCASx)
|
||||
#
|
||||
# CMP([%1], $2)
|
||||
# WHILE RCX > 0 DO
|
||||
# RCX = RCX - 1
|
||||
#
|
||||
# IF ([%1] == 0) THEN
|
||||
# ZF = 1
|
||||
# ELIF (ZF == 0) THEN
|
||||
# IF (DF == 0) THEN
|
||||
# %1 = %1 + sizeof(x)
|
||||
# ELSE
|
||||
# %1 = %1 - sizeof(x)
|
||||
# FI
|
||||
# IF ([%1] == 0) OR ([%1] == $2) THEN
|
||||
# BREAK
|
||||
# ELSE
|
||||
# %1 = %1 + sizeof(x)
|
||||
# FI
|
||||
# DONE
|
||||
#
|
||||
# Sets CF, OF and SF according to the result of the comparison
|
||||
# Sets ZF according to whether [%1] and $2 are equal, OR if [%1] is null
|
||||
#
|
||||
# Notes:
|
||||
# - Does not move past the value when found
|
||||
# - 'SCASB.REP.NZ reg ch' is a short 'strchnul()'
|
||||
# Note: Does not move past the value when found
|
||||
#
|
||||
scasb 2
|
||||
scasw 2
|
||||
|
104
vm/in/alu.c
104
vm/in/alu.c
@ -8,71 +8,103 @@
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START(or, 2) { SRCP(p1); SRCP(p2); *r1 = p1->val | p2->val; return 1; }
|
||||
IMPL_START(and, 2) { SRCP(p1); SRCP(p2); *r1 = p1->val & p2->val; return 1; }
|
||||
IMPL_START(xor, 2) { SRCP(p1); SRCP(p2); *r1 = p1->val ^ p2->val; return 1; }
|
||||
IMPL_START(not, 1) { SRCP(p1); *r1 = ~p1->val; return 1; }
|
||||
|
||||
IMPL_START(or, 2) { SRCP(p1); SRCP(p2); *r1 = p1->val | p2->val; return 1; }
|
||||
IMPL_START(or, 3) { SRCP(p2); SRCP(p3); *r1 = p2->val | p3->val; return 1; }
|
||||
|
||||
IMPL_START(and, 2) { SRCP(p1); SRCP(p2); *r1 = p1->val & p2->val; return 1; }
|
||||
IMPL_START(and, 3) { SRCP(p2); SRCP(p3); *r1 = p2->val & p3->val; return 1; }
|
||||
|
||||
IMPL_START(xor, 2) { SRCP(p1); SRCP(p2); *r1 = p1->val ^ p2->val; return 1; }
|
||||
IMPL_START(xor, 3) { SRCP(p2); SRCP(p3); *r1 = p2->val ^ p3->val; return 1; }
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START(shl, 2) { SRCP(p1); SRCP(p2); *r1 = p1->val << p2->val; return 1; }
|
||||
IMPL_START(shr, 2) { SRCP(p1); SRCP(p2); *r1 = p1->val >> p2->val; return 1; }
|
||||
IMPL_START(sar, 2) { SRCP(p1); SRCP(p2); *r1 = (ulong)((long)p1->val >> (long)p2->val); return 1; }
|
||||
|
||||
IMPL_START(shl, 3) { SRCP(p2); SRCP(p3); *r1 = p2->val << p3->val; return 1; }
|
||||
|
||||
IMPL_START(shr, 2) { SRCP(p1); SRCP(p2); *r1 = p1->val >> p2->val; return 1; }
|
||||
IMPL_START(shr, 3) { SRCP(p2); SRCP(p3); *r1 = p2->val >> p3->val; return 1; }
|
||||
IMPL_START(sar, 3) { SRCP(p2); SRCP(p3); *r1 = (ulong)((long)p2->val >> (long)p3->val); return 1; }
|
||||
|
||||
IMPL_START(sar, 2) {
|
||||
SRCP(p1); SRCP(p2);
|
||||
*r1 = (ulong)((long)p1->val >> (long)p2->val);
|
||||
return 1;
|
||||
}
|
||||
IMPL_START(sar, 3) {
|
||||
SRCP(p2); SRCP(p3);
|
||||
*r1 = (ulong)((long)p2->val >> (long)p3->val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START(neg, 1) { SRCP(p1); *r1 = ~p1->val + 1; return 1; }
|
||||
IMPL_START(negv, 1) {
|
||||
SRCP(p1);
|
||||
|
||||
if (p1->val == (1ul<<63))
|
||||
_except(E_OVF, "Ineffective NEG operation (NEGV)");
|
||||
|
||||
*r1 = ~p1->val + 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
IMPL_START(add, 2) { SRCP(p1); SRCP(p2); *r1 = p1->val + p2->val; return 1; }
|
||||
IMPL_START(add, 3) { SRCP(p2); SRCP(p3); *r1 = p2->val + p3->val; return 1; }
|
||||
IMPL_START(addf, 3) { SRCP(p2); SRCP(p3); COMPARE_ADD(p2->val, p3->val); *r1 = p2->val + p3->val; return 1; }
|
||||
|
||||
IMPL_START(addv, 2) {
|
||||
SRCP(p1); SRCP(p2);
|
||||
|
||||
ulong rs = p1->val + p2->val;
|
||||
|
||||
if (((p1->val ^ rs) & (p2->val ^ rs)) >> 63)
|
||||
_except(E_OVF, "Signed addition overflow (ADDV#2)");
|
||||
|
||||
*r1 = rs;
|
||||
return 1;
|
||||
}
|
||||
|
||||
IMPL_START(addv, 3) {
|
||||
SRCP(p2); SRCP(p3);
|
||||
|
||||
ulong rs = p2->val + p3->val;
|
||||
|
||||
if (((p2->val ^ rs) & (p3->val ^ rs)) >> 63)
|
||||
_except(E_OVF, "Signed addition overflow (ADDV#3)");
|
||||
|
||||
*r1 = rs;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START(sub, 2) { SRCP(p1); SRCP(p2); *r1 = p1->val - p2->val; return 1; }
|
||||
IMPL_START(sub, 3) { SRCP(p2); SRCP(p3); *r1 = p2->val - p3->val; return 1; }
|
||||
IMPL_START(subf, 3) { SRCP(p2); SRCP(p3); COMPARE_SUB(p2->val, p3->val); *r1 = p2->val - p3->val; return 1; }
|
||||
|
||||
IMPL_START(adcx, 2) {
|
||||
IMPL_START(subv, 2) {
|
||||
SRCP(p1); SRCP(p2);
|
||||
|
||||
p2->val += !!(R(RFX)&CF);
|
||||
COMPARE_ADD(p1->val, p2->val);
|
||||
*r1 = p1->val + p2->val;
|
||||
ulong rs = p1->val - p2->val;
|
||||
|
||||
if (((p1->val ^ rs) & (p1->val ^ p2->val)) >> 63)
|
||||
_except(E_OVF, "Signed substraction underflow (SUBV#2)");
|
||||
|
||||
*r1 = rs;
|
||||
return 1;
|
||||
}
|
||||
|
||||
IMPL_START(adcx, 3) {
|
||||
SRCP(p2); SRCP(p3);
|
||||
|
||||
p3->val += !!(R(RFX)&CF);
|
||||
COMPARE_ADD(p2->val, p3->val);
|
||||
*r1 = p2->val + p3->val;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
IMPL_START(sbbx, 2) {
|
||||
IMPL_START(subv, 3) {
|
||||
SRCP(p1); SRCP(p2);
|
||||
|
||||
p2->val += !!(R(RFX)&CF);
|
||||
COMPARE_SUB(p1->val, p2->val);
|
||||
*r1 = p1->val - p2->val;
|
||||
ulong rs = p2->val - p3->val;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
IMPL_START(sbbx, 3) {
|
||||
SRCP(p2); SRCP(p3);
|
||||
|
||||
p3->val += !!(R(RFX)&CF);
|
||||
COMPARE_SUB(p2->val, p3->val);
|
||||
*r1 = p2->val - p3->val;
|
||||
if (((p2->val ^ rs) & (p2->val ^ p3->val)) >> 63)
|
||||
_except(E_OVF, "Signed substraction underflow (SUBV#3)");
|
||||
|
||||
*r1 = rs;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ def parse_2(fp):
|
||||
.format(deprecated, tok[0], n, tok[0], n))
|
||||
hd.write("#else\n")
|
||||
hd.write("#define I_{}_{} {}\n".format(tok[0].upper(), n, count))
|
||||
hd.write("extern bool i_{}_{}(acc_t *, acc_t *, acc_t *, ulong *, ulong *, ulong *);\n"
|
||||
hd.write("extern bool i_{}_{}(acc_t *, acc_t *, acc_t *, ulong *, ulong *);\n"
|
||||
.format(tok[0], n))
|
||||
hd.write("#endif\n\n")
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
#define IMPL_START(name, n) \
|
||||
uint i_##name##_##n(acc_t *p1, acc_t *p2, acc_t *p3, \
|
||||
ulong *r1, ulong *r2, ulong *r3) \
|
||||
ulong *r1, ulong *r2) \
|
||||
|
||||
#define XSRCP(v, p, x) \
|
||||
if (ACC_FMT_IS_MEM(p->type)) \
|
||||
@ -20,52 +20,6 @@ uint i_##name##_##n(acc_t *p1, acc_t *p2, acc_t *p3, \
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#define INTO() \
|
||||
if (R(RFX) & OF) _except(E_OVF, "Overflow");
|
||||
|
||||
#define PARITY(v) __builtin_parity(v)
|
||||
|
||||
#define SET_ZF(v) \
|
||||
R(RFX) = ((v) == 0 ? (R(RFX)|ZF) : (R(RFX)&~ZF))
|
||||
|
||||
#define SET_SF(v) \
|
||||
R(RFX) = ((long)(v) < 0 ? (R(RFX)|SF) : (R(RFX)&~SF))
|
||||
|
||||
#define SET_PF(v) \
|
||||
R(RFX) = (PARITY(v) == 1 ? (R(RFX)|PF) : (R(RFX)&~PF))
|
||||
|
||||
#define SET_ZSF(v) \
|
||||
SET_ZF(v); \
|
||||
SET_SF(v)
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#define COMPARE_ADD(v1, v2) \
|
||||
ulong _u1 = (ulong)v1, _u2 = (ulong)v2, _u3 = (_u1 + _u2); \
|
||||
\
|
||||
if (_u1 + _u2 < _u2) R(RFX) |= CF; \
|
||||
else R(RFX) &= ~CF; \
|
||||
\
|
||||
if (((_u1 ^ _u3) & (_u2 ^ _u3)) >> 63) \
|
||||
R(RFX) |= OF; \
|
||||
else R(RFX) &= ~OF; \
|
||||
\
|
||||
SET_ZSF(_u3);
|
||||
|
||||
#define COMPARE_SUB(v1, v2) \
|
||||
ulong _u1 = (ulong)v1, _u2 = (ulong)v2, _u3 = (_u1 - _u2); \
|
||||
\
|
||||
if (_u1 < _u2) R(RFX) |= CF; \
|
||||
else R(RFX) &= ~CF; \
|
||||
\
|
||||
if (((_u1 ^ _u3) & (_u1 ^ _u2)) >> 63) \
|
||||
R(RFX) |= OF; \
|
||||
else R(RFX) &= ~OF; \
|
||||
\
|
||||
SET_ZSF(_u3);
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#define CHK_SUPERV() \
|
||||
do { \
|
||||
if ((R(CR0) & UF) > 0) { \
|
||||
|
34
vm/in/jmp.c
34
vm/in/jmp.c
@ -13,6 +13,8 @@ IMPL_START(jrcxz, 1) { if (!R(RCX)) R(RIP) = p1->val; return 0; }
|
||||
IMPL_START(jraxnz, 1) { if (R(RAX)) R(RIP) = p1->val; return 0; }
|
||||
IMPL_START(jrcxnz, 1) { if (R(RCX)) R(RIP) = p1->val; return 0; }
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START(loop, 1) {
|
||||
if (R(RCX) > 0) {
|
||||
R(RCX)--;
|
||||
@ -21,6 +23,17 @@ IMPL_START(loop, 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
IMPL_START(loop, 2) {
|
||||
SRCP(p1);
|
||||
if (p1->val > 0) {
|
||||
*r1 = p1->val-1;
|
||||
R(RIP) = p2->val;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START(bzr, 2) { SRCP(p1); if (p1->val == 0) R(RIP) = p2->val; return 0; }
|
||||
IMPL_START(bnz, 2) { SRCP(p1); if (p1->val != 0) R(RIP) = p2->val; return 0; }
|
||||
IMPL_START(bltz, 2) { SRCP(p1); if ((long)p1->val < 0) R(RIP) = p2->val; return 0; }
|
||||
@ -34,24 +47,5 @@ IMPL_START(bltu, 3) { SRCP(p1); if (p1->val < p2->val) R(RIP) = p3->val; return
|
||||
IMPL_START(blte, 3) { SRCP(p1); if ((long)p1->val <= (long)p2->val) R(RIP) = p3->val; return 0; }
|
||||
IMPL_START(blteu, 3) { SRCP(p1); if (p1->val <= p2->val) R(RIP) = p3->val; return 0; }
|
||||
|
||||
IMPL_START(bch, 3)
|
||||
{
|
||||
SRCP(p1);
|
||||
SRCP(p2);
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
COMPARE_SUB(p1->val, p2->val);
|
||||
|
||||
if (eval_cond(ctx->cond))
|
||||
R(RIP) = p3->val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
IMPL_START(cmp, 2)
|
||||
{
|
||||
SRCP(p1);
|
||||
|
||||
COMPARE_SUB(p1->val, p2->val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
34
vm/in/mem.c
34
vm/in/mem.c
@ -6,12 +6,16 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START(lea, 2) { *r1 = p2->addr; return 1; }
|
||||
|
||||
IMPL_START(mov, 2) { XSRCP(*r1, p2, sx); return 1; }
|
||||
IMPL_START(movzx, 2) { XSRCP(*r1, p2, zx); return 1; }
|
||||
|
||||
IMPL_START(movsxb, 2) { SRCP(p2); *r1 = (ulong)(long)(char)p2->val; return 1; }
|
||||
IMPL_START(movsxw, 2) { SRCP(p2); *r1 = (ulong)(long)(short)p2->val; return 1; }
|
||||
IMPL_START(movsxd, 2) { SRCP(p2); *r1 = (ulong)(long)(int)p2->val; return 1; }
|
||||
IMPL_START(movb, 2) { SRCP(p2); *r1 = (ulong)(long)(char)p2->val; return 1; }
|
||||
IMPL_START(movw, 2) { SRCP(p2); *r1 = (ulong)(long)(short)p2->val; return 1; }
|
||||
IMPL_START(movd, 2) { SRCP(p2); *r1 = (ulong)(long)(int)p2->val; return 1; }
|
||||
|
||||
IMPL_START(nul, 1) { *r1 = 0; return 1; }
|
||||
IMPL_START(nul, 2) { *r1 = 0; *r2 = 0; return 2; }
|
||||
|
||||
IMPL_START(xchg, 2)
|
||||
{
|
||||
@ -64,6 +68,12 @@ IMPL_START(push, 3)
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START(pop, 0)
|
||||
{
|
||||
R(RSP) += 8;
|
||||
return 0;
|
||||
}
|
||||
|
||||
IMPL_START(pop, 1)
|
||||
{
|
||||
*r1 = readmemzx(R(RSP), 8);
|
||||
@ -81,16 +91,6 @@ IMPL_START(pop, 2)
|
||||
return 2;
|
||||
}
|
||||
|
||||
IMPL_START(pop, 3)
|
||||
{
|
||||
*r1 = readmemzx(R(RSP) + 0, 8);
|
||||
*r2 = readmemzx(R(RSP) + 8, 8);
|
||||
*r3 = readmemzx(R(RSP) + 16, 8);
|
||||
R(RSP) += 24;
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START(call, 1)
|
||||
@ -144,6 +144,14 @@ IMPL_START(ret, 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
IMPL_START(ret, 1)
|
||||
{
|
||||
R(RIP) = readmemzx(R(RSP), 8);
|
||||
R(RSP) += 8 + (p1->val * 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START(enter, 0)
|
||||
|
42
vm/in/misc.c
42
vm/in/misc.c
@ -9,7 +9,6 @@
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START(into, 0) { INTO(); return 0; }
|
||||
IMPL_START(pause, 0) { usleep(5000); return 0; }
|
||||
IMPL_START(udf, 0) { _except(E_UDF, "UDF instruction"); }
|
||||
|
||||
@ -35,7 +34,7 @@ IMPL_START(dump, 0)
|
||||
trace("0x%lX:\t...\n", ctx->cur_pc);
|
||||
|
||||
else if (!ctx->dumpsw)
|
||||
dump_instr(ctx->cur_in, p1, p2, p3, 0, 0);
|
||||
dump_instr(ctx->cur_in, p1, p2, p3);
|
||||
|
||||
ctx->dumpsw = !ctx->dumpsw;
|
||||
#endif
|
||||
@ -44,19 +43,19 @@ IMPL_START(dump, 0)
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START(ytime, 3)
|
||||
IMPL_START(ytime, 0)
|
||||
{
|
||||
time_t t = time(NULL);
|
||||
struct tm *tm = localtime(&t);
|
||||
|
||||
*r1 = tm->tm_sec + tm->tm_min * 60
|
||||
+ tm->tm_hour * 60 * 60
|
||||
+ tm->tm_mday * 60 * 60 * 24;
|
||||
R(RAX) = tm->tm_sec + tm->tm_min * 60
|
||||
+ tm->tm_hour * 60 * 60
|
||||
+ tm->tm_mday * 60 * 60 * 24;
|
||||
|
||||
*r2 = tm->tm_mon;
|
||||
*r3 = tm->tm_year + 1900;
|
||||
R(RBX) = tm->tm_mon;
|
||||
R(RCX) = tm->tm_year + 1900;
|
||||
|
||||
return 3;
|
||||
return 0;
|
||||
}
|
||||
|
||||
IMPL_START(utime, 1)
|
||||
@ -72,7 +71,6 @@ IMPL_START(utime, 1)
|
||||
|
||||
IMPL_START(cls, 0)
|
||||
{
|
||||
R(RFX) = 0;
|
||||
for (int i = RAX; i <= R20; i++) R(i) = 0;
|
||||
|
||||
return 0;
|
||||
@ -148,6 +146,8 @@ IMPL_START(prn, 1)
|
||||
break;
|
||||
|
||||
default:
|
||||
trace("PRN bad magic: %lx\n", v);
|
||||
die(1);
|
||||
_except(E_ILL, "Bad PRN magic");
|
||||
}
|
||||
}
|
||||
@ -158,28 +158,6 @@ IMPL_START(prn, 1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
IMPL_START(prns, 1)
|
||||
{
|
||||
if (p1->type != A_REG)
|
||||
_except(E_ILL, "PRNS given a non-REG operand");
|
||||
|
||||
uchar ch = readmemzx(R(p1->reg), 1);
|
||||
|
||||
COMPARE_SUB(ch, 0);
|
||||
|
||||
if ((R(RFX) & ZF) == 0)
|
||||
{
|
||||
console_putc(ch);
|
||||
|
||||
if (R(RFX) & DF)
|
||||
R(p1->reg)--;
|
||||
else
|
||||
R(p1->reg)++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
IMPL_START(scan, 1)
|
||||
{
|
||||
*r1 = console_scankeybuf();
|
||||
|
@ -11,36 +11,21 @@
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
static void stos_impl(acc_t *p1, acc_t *p2, uint len)
|
||||
{
|
||||
if (p1->type != A_REG)
|
||||
_except(E_ILL, "STOSX given a non-REG operand");
|
||||
|
||||
writemem(p2->val, R(p1->reg), len);
|
||||
STR_MOVE(p1->reg, len);
|
||||
}
|
||||
|
||||
IMPL_START(stosb, 2) { stos_impl(p1, p2, 1); return 0; }
|
||||
IMPL_START(stosw, 2) { stos_impl(p1, p2, 2); return 0; }
|
||||
IMPL_START(stosd, 2) { stos_impl(p1, p2, 4); return 0; }
|
||||
IMPL_START(stosq, 2) { stos_impl(p1, p2, 8); return 0; }
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
static void scas_impl(acc_t *p1, acc_t *p2, uint len)
|
||||
{
|
||||
if (p1->type != A_REG)
|
||||
_except(E_ILL, "SCASX given a non-REG operand");
|
||||
|
||||
ulong x = readmemsx(R(p1->reg), len);
|
||||
COMPARE_SUB(x, p2->val);
|
||||
while (R(RCX) > 0)
|
||||
{
|
||||
ulong x = readmemzx(R(p1->reg), len);
|
||||
|
||||
if (x == 0) {
|
||||
R(RFX) |= ZF;
|
||||
}
|
||||
if (x == 0 || x == p2->val)
|
||||
break;
|
||||
|
||||
else if (!(R(RFX)&ZF)) {
|
||||
STR_MOVE(p1->reg, len);
|
||||
R(p1->reg) += len;
|
||||
|
||||
R(RCX)--;
|
||||
}
|
||||
}
|
||||
|
||||
|
22
vm/pc/DECD
22
vm/pc/DECD
@ -3,11 +3,7 @@
|
||||
|
||||
Instruction encoding:
|
||||
|
||||
Byte 1: Instruction number
|
||||
Byte 2:
|
||||
xx0xxxxx
|
||||
|| └───┘
|
||||
RL CND
|
||||
Byte: Instruction number
|
||||
|
||||
Values for ModRMs:
|
||||
000xxxxx xxxxx = reg
|
||||
@ -24,19 +20,3 @@ Values for ModRMs:
|
||||
11100100 imm32 (zero extended)
|
||||
11101000 imm64 (zero extended)
|
||||
|
||||
Values for COND:
|
||||
00000 (none)
|
||||
00001 .C .B
|
||||
00010 .O
|
||||
00011 .Z .E
|
||||
00100 .S
|
||||
00101 .P
|
||||
00110 .BE
|
||||
00111 .L
|
||||
01000 .LE
|
||||
01001 .AXZ
|
||||
01010 .BXZ
|
||||
01011 .CXZ
|
||||
01100 .DXZ
|
||||
Highest (6th) bit of COND indicates negation
|
||||
|
||||
|
@ -72,9 +72,6 @@ struct ctx_t
|
||||
ulong ninstrs; // totally
|
||||
ulong ni_thisfr; // this frame
|
||||
|
||||
// Last COND field
|
||||
uint cond;
|
||||
|
||||
// Dumpinstr switch
|
||||
bool dumpsw;
|
||||
};
|
||||
|
@ -195,8 +195,8 @@ static void extract_param(instr_t *in, acc_t *p)
|
||||
//
|
||||
void decode(void)
|
||||
{
|
||||
ushort b;
|
||||
instr_t *in;
|
||||
ushort b1, b2, rep = 0, lock;
|
||||
acc_t p1 = { 0 }, p2 = { 0 }, p3 = { 0 };
|
||||
|
||||
//logerr("decodin'\n");
|
||||
@ -209,35 +209,20 @@ void decode(void)
|
||||
_except(E_ACC, "Executing out of memory");
|
||||
|
||||
// Instruction bytes
|
||||
b1 = fetchb();
|
||||
|
||||
// Suffixes?
|
||||
if (b1 & (1 << 7))
|
||||
{
|
||||
b1 &= ~(1 << 7);
|
||||
b2 = fetchb();
|
||||
}
|
||||
|
||||
else
|
||||
b2 = 0;
|
||||
b = fetchb();
|
||||
|
||||
// Renge check
|
||||
if (b1 >= NINSTRS)
|
||||
_except(E_ILL, "No such INSTR: 0x%hhX", b1);
|
||||
if (b >= NINSTRS)
|
||||
_except(E_ILL, "No such INSTR: 0x%hhX", b);
|
||||
|
||||
// Find instruction
|
||||
in = &ctx->i[b1];
|
||||
in = &ctx->i[b];
|
||||
ctx->cur_in = in;
|
||||
|
||||
// Get flags/etc
|
||||
rep = !!(b2 & SUFF_REP);
|
||||
lock = !!(b2 & SUFF_LOCK);
|
||||
ctx->cond = b2 & SUFF_COND;
|
||||
|
||||
// Operand 1?
|
||||
if (in->nprms == 0)
|
||||
{
|
||||
exec_instr(in, NULL, NULL, NULL, lock, rep);
|
||||
exec_instr(in, NULL, NULL, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -246,7 +231,7 @@ void decode(void)
|
||||
// Operand 2?
|
||||
if (in->nprms == 1)
|
||||
{
|
||||
exec_instr(in, &p1, NULL, NULL, lock, rep);
|
||||
exec_instr(in, &p1, NULL, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -255,12 +240,12 @@ void decode(void)
|
||||
// Operand 1?
|
||||
if (in->nprms == 2)
|
||||
{
|
||||
exec_instr(in, &p1, &p2, NULL, lock, rep);
|
||||
exec_instr(in, &p1, &p2, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
extract_param(in, &p3);
|
||||
|
||||
exec_instr(in, &p1, &p2, &p3, lock, rep);
|
||||
exec_instr(in, &p1, &p2, &p3);
|
||||
}
|
||||
|
||||
|
@ -1,30 +1,6 @@
|
||||
// The OS/K Team licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
enum
|
||||
{
|
||||
CD_NONE,
|
||||
CD_C,
|
||||
CD_O,
|
||||
CD_Z,
|
||||
CD_S,
|
||||
CD_P,
|
||||
CD_BE,
|
||||
CD_L,
|
||||
CD_LE,
|
||||
CD_AXZ,
|
||||
CD_BXZ,
|
||||
CD_CXZ,
|
||||
CD_DXZ,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SUFF_REP = (1 << 7),
|
||||
SUFF_LOCK = (1 << 6),
|
||||
SUFF_COND = 0b00011111,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
A_NONE = 0,
|
||||
@ -68,22 +44,16 @@ struct instr_t
|
||||
char *name;
|
||||
uint nprms;
|
||||
uint (*func)(acc_t *, acc_t *, acc_t *,
|
||||
ulong *, ulong *, ulong *);
|
||||
ulong *, ulong *);
|
||||
};
|
||||
|
||||
bool eval_cond(uint cond);
|
||||
|
||||
void exec_instr(instr_t *in,
|
||||
acc_t *p1,
|
||||
acc_t *p2,
|
||||
acc_t *p3,
|
||||
bool lock,
|
||||
bool rep);
|
||||
acc_t *p3);
|
||||
|
||||
void dump_instr(instr_t *in,
|
||||
acc_t *p1,
|
||||
acc_t *p2,
|
||||
acc_t *p3,
|
||||
bool lock,
|
||||
bool rep);
|
||||
acc_t *p3);
|
||||
|
||||
|
42
vm/pc/dump.c
42
vm/pc/dump.c
@ -5,53 +5,15 @@
|
||||
|
||||
#define ABS(x) ((short)(x) < 0 ? -x : x)
|
||||
|
||||
static const char *cond_suffixes[] =
|
||||
{
|
||||
"-",
|
||||
"c", "o", "z", "s", "p",
|
||||
"be", "l", "le", "axz",
|
||||
"bxz", "cxz",
|
||||
"?"
|
||||
};
|
||||
|
||||
static void dump_acc(acc_t *p);
|
||||
|
||||
void dump_instr(instr_t *in,
|
||||
acc_t *p1,
|
||||
acc_t *p2,
|
||||
acc_t *p3,
|
||||
bool lock,
|
||||
bool rep)
|
||||
acc_t *p3)
|
||||
{
|
||||
uint cond = ctx->cond;
|
||||
|
||||
trace("0x%lX:\t", ctx->cur_pc);
|
||||
|
||||
if (lock)
|
||||
trace("lock");
|
||||
|
||||
trace("%s", in->name);
|
||||
|
||||
if (rep)
|
||||
trace(".rep");
|
||||
|
||||
if (cond)
|
||||
{
|
||||
trace(".");
|
||||
|
||||
if (cond & (1 << 4))
|
||||
trace("n");
|
||||
|
||||
assert((cond & ~(1 << 4)) <= sizeof(cond_suffixes)/sizeof(char *));
|
||||
|
||||
trace("%s", cond_suffixes[cond & ~(1 << 4)]);
|
||||
}
|
||||
|
||||
if (!rep && cond != ((1 << 4) | CD_CXZ))
|
||||
trace("\t\t");
|
||||
|
||||
else
|
||||
trace("\t");
|
||||
trace("%s\t", in->name);
|
||||
|
||||
if (p1)
|
||||
dump_acc(p1);
|
||||
|
@ -75,7 +75,7 @@ void _except(int _code, char *fmt, ...)
|
||||
{
|
||||
if (ctx->dumpsw)
|
||||
{
|
||||
trace("\nException %u - ", code);
|
||||
trace("\n(Caught) Exception %u - ", code);
|
||||
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
|
77
vm/pc/exec.c
77
vm/pc/exec.c
@ -3,41 +3,6 @@
|
||||
|
||||
#include <pc/arch.h>
|
||||
|
||||
#define rfx R(RFX)
|
||||
|
||||
bool eval_cond(uint cond)
|
||||
{
|
||||
bool neg = cond & (1 << 4);
|
||||
bool ok;
|
||||
|
||||
cond &= ~(1 << 4);
|
||||
|
||||
switch (cond)
|
||||
{
|
||||
case CD_NONE: ok = 1; break;
|
||||
|
||||
case CD_C: ok = rfx&CF; break;
|
||||
case CD_O: ok = rfx&OF; break;
|
||||
case CD_Z: ok = rfx&ZF; break;
|
||||
case CD_S: ok = rfx&SF; break;
|
||||
case CD_P: ok = rfx&PF; break;
|
||||
|
||||
case CD_BE: ok = rfx&CF || rfx&ZF; break;
|
||||
case CD_L: ok = !(rfx&SF) != !(rfx&OF); break;
|
||||
case CD_LE: ok = rfx&ZF || (!(rfx&SF) != !(rfx&OF)); break;
|
||||
|
||||
case CD_AXZ: ok = !R(RAX); break;
|
||||
case CD_BXZ: ok = !R(RBX); break;
|
||||
case CD_CXZ: ok = !R(RCX); break;
|
||||
case CD_DXZ: ok = !R(RDX); break;
|
||||
|
||||
default:
|
||||
_except(E_ILL, "Invalid COND value: 0x%x", (neg?cond|(1<<4):cond));
|
||||
}
|
||||
|
||||
return neg ? !ok : !!ok;
|
||||
}
|
||||
|
||||
#define OUTPUT(p, r) { \
|
||||
if (p->type == A_REG) \
|
||||
R(p->reg) = r; \
|
||||
@ -52,54 +17,26 @@ bool eval_cond(uint cond)
|
||||
void exec_instr(instr_t *in,
|
||||
acc_t *p1,
|
||||
acc_t *p2,
|
||||
acc_t *p3,
|
||||
bool lock,
|
||||
bool rep)
|
||||
acc_t *p3)
|
||||
{
|
||||
uint out;
|
||||
ulong r1 = 0, r2 = 0, r3 = 0;
|
||||
ulong r1 = 0, r2 = 0;
|
||||
|
||||
// Global instruction counter
|
||||
ctx->ninstrs++;
|
||||
|
||||
//
|
||||
// For REPs we evaluate the condition AFTER running the instruction,
|
||||
// in a do ... while(cond) fashion
|
||||
//
|
||||
if (ctx->cond)
|
||||
if (!rep && !eval_cond(ctx->cond))
|
||||
return;
|
||||
|
||||
if (ctx->dumpsw)
|
||||
dump_instr(in, p1, p2, p3, lock, rep);
|
||||
dump_instr(in, p1, p2, p3);
|
||||
|
||||
do_rep:
|
||||
out = in->func(p1, p2, p3, &r1, &r2, &r3);
|
||||
out = in->func(p1, p2, p3, &r1, &r2);
|
||||
|
||||
if (out)
|
||||
{
|
||||
OUTPUT(p1, r1);
|
||||
if (out >= 2) OUTPUT(p2, r2);
|
||||
if (out >= 3) OUTPUT(p3, r3);
|
||||
if (__builtin_expect(out == 2, 0))
|
||||
OUTPUT(p2, r2);
|
||||
|
||||
R(RZX) = 0;
|
||||
}
|
||||
|
||||
if (rep)
|
||||
{
|
||||
// RCX remains untouched when condition fails
|
||||
if (!eval_cond(ctx->cond))
|
||||
return;
|
||||
|
||||
if (R(RCX) > 0)
|
||||
R(RCX)--;
|
||||
|
||||
if (R(RCX) == 0)
|
||||
return;
|
||||
|
||||
// Should we really count REP's in instruction count?
|
||||
ctx->ninstrs++;
|
||||
|
||||
goto do_rep;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ static void writemem64(ulong val, ulong real, ulong addr)
|
||||
}
|
||||
|
||||
#define GETREAL() \
|
||||
ulong real = addr2real(addr + R(CR2))
|
||||
ulong real = addr2real(addr + R(CR1))
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
|
10
vm/pc/regs.c
10
vm/pc/regs.c
@ -5,9 +5,6 @@
|
||||
|
||||
reg_t arch_r[] =
|
||||
{
|
||||
{ "zero", GPR }, { "cr0", SYS }, { "cr1", SYS }, { "cr2", SYS },
|
||||
{ "rfx", GPR }, { "rip", GPR }, { "rbp", GPR }, { "rsp", GPR },
|
||||
|
||||
{ "rax", GPR }, { "rbx", GPR }, { "rcx", GPR }, { "rdx", GPR },
|
||||
{ "rsi", GPR }, { "rdi", GPR }, { "ax0", GPR }, { "ax1", GPR },
|
||||
{ "ax2", GPR }, { "ax3", GPR }, { "ax4", GPR }, { "ax5", GPR },
|
||||
@ -15,6 +12,9 @@ reg_t arch_r[] =
|
||||
{ "r12", GPR }, { "r13", GPR }, { "r14", GPR }, { "r15", GPR },
|
||||
{ "r16", GPR }, { "r17", GPR }, { "r18", GPR }, { "r19", GPR },
|
||||
{ "r20", GPR }, { "grp", GPR }, { "trp", GPR }, { "srp", SYS },
|
||||
|
||||
{ "tmp", GPR }, { "rad", GPR }, { "cr0", SYS }, { "cr1", SYS },
|
||||
{ "rip", GPR }, { "rbp", GPR }, { "rsp", GPR }, { "zero", GPR },
|
||||
};
|
||||
|
||||
static_assert(sizeof(arch_r)/sizeof(reg_t) == NREGS, "");
|
||||
@ -26,8 +26,8 @@ void dumpregs()
|
||||
TRACE("Current RFRAME index: #%lu", rfs_current_idx);
|
||||
|
||||
TRACE("\n\nEnviron #1:");
|
||||
TRACE("\nrpc=0x%-16lX rip=0x%-16lX rfx=0x%-16lX", ctx->cur_pc, R(RIP), R(RFX));
|
||||
TRACE("\ncr0=0x%-16lX cr1=0x%-16lX cr2=0x%-16lX", R(CR0), R(CR1), R(CR2));
|
||||
TRACE("\nrpc=0x%-16lX rip=0x%-16lX", ctx->cur_pc, R(RIP));
|
||||
TRACE("\ncr0=0x%-16lX cr1=0x%-16lX", R(CR0), R(CR1));
|
||||
|
||||
TRACE("\n\nEnviron #2:");
|
||||
TRACE("\nrsp=0x%-16lX rbp=0x%-16lX ins=0d%-16lu", R(RSP), R(RBP), ctx->ninstrs);
|
||||
|
@ -37,10 +37,10 @@ struct reg_t
|
||||
|
||||
enum
|
||||
{
|
||||
RZX, CR0, CR1, CR2, RFX, RIP, RBP, RSP,
|
||||
RAX, RBX, RCX, RDX, RSI, RDI, AX0, AX1,
|
||||
AX2, AX3, AX4, AX5, R12, R13, R14, R15,
|
||||
R16, R17, R18, R19, R20, GRP, TRP, SRP,
|
||||
TMP, RAD, CR0, CR1, RIP, RBP, RSP, RZX,
|
||||
|
||||
NREGS
|
||||
};
|
||||
|
@ -18,9 +18,9 @@ int create_symtab(const char *name)
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (fscanf(tab, "%s %lu\n", buf, &addr) > 0 && it < SYMTAB_LEN)
|
||||
while (fscanf(tab, "%45s%*s %lu\n", buf, &addr) > 0 && it < SYMTAB_LEN)
|
||||
{
|
||||
// log("SYM: '%.*s' '%lu'\n", SYMLEN_MAX, buf, addr);
|
||||
//trace("SYM: '%.*s' '%lu'\n", SYMLEN_MAX, buf, addr);
|
||||
|
||||
if (prev_addr > addr)
|
||||
{
|
||||
@ -38,7 +38,6 @@ int create_symtab(const char *name)
|
||||
}
|
||||
|
||||
fclose(tab);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
// The OS/K Team licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
#define SYMLEN_MAX 32
|
||||
#define SYMLEN_MAX 46
|
||||
#define SYMTAB_LEN 4096
|
||||
|
||||
typedef struct sym_t sym_t;
|
||||
@ -9,7 +9,7 @@ typedef struct sym_t sym_t;
|
||||
struct sym_t
|
||||
{
|
||||
ulong addr;
|
||||
char name[SYMLEN_MAX];
|
||||
char name[SYMLEN_MAX+1];
|
||||
};
|
||||
|
||||
extern sym_t symtab[SYMTAB_LEN];
|
||||
|
Loading…
x
Reference in New Issue
Block a user