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 = {
|
fmts = {
|
||||||
"r": 0b00000000,
|
"r": 0b00000000,
|
||||||
"m_r": 0b00100000,
|
"m_r": 0b00100000,
|
||||||
|
@ -456,40 +410,11 @@ def parse_instr(line):
|
||||||
params = None
|
params = None
|
||||||
|
|
||||||
size = 1
|
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_name = instr
|
||||||
instr_args = ''
|
instr_args = ''
|
||||||
|
|
||||||
if params == None or len(params) == 0:
|
if params == None or len(params) == 0:
|
||||||
if b2 == 0:
|
instrs.write("{}_0".format(instr_name))
|
||||||
instrs.write("{}_0".format(instr_name))
|
|
||||||
|
|
||||||
else:
|
|
||||||
size += 1
|
|
||||||
instrs.write("%%suff {}_0 %%imm8 {}".format(instr_name, b2))
|
|
||||||
|
|
||||||
return size
|
return size
|
||||||
|
|
||||||
|
@ -721,19 +646,13 @@ def parse_instr(line):
|
||||||
|
|
||||||
instr_args += word
|
instr_args += word
|
||||||
|
|
||||||
if b2 == 0:
|
instrs.write("{}{}".format(instr_name, instr_args))
|
||||||
instrs.write("{} {}".format(instr_name, instr_args))
|
|
||||||
|
|
||||||
else:
|
|
||||||
size += 1
|
|
||||||
instrs.write("%%suff {} %%imm8 {} {}".format(instr_name, b2, instr_args))
|
|
||||||
|
|
||||||
return size
|
return size
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
special_syms = {
|
special_syms = {
|
||||||
"%%suff",
|
|
||||||
"%%imm8",
|
"%%imm8",
|
||||||
"%%imm16",
|
"%%imm16",
|
||||||
"%%imm32",
|
"%%imm32",
|
||||||
|
@ -749,7 +668,6 @@ def gentext():
|
||||||
data_start += (8 - data_start % 8)
|
data_start += (8 - data_start % 8)
|
||||||
|
|
||||||
instrs.seek(0)
|
instrs.seek(0)
|
||||||
suff_mask = 0
|
|
||||||
|
|
||||||
for _, line in enumerate(instrs):
|
for _, line in enumerate(instrs):
|
||||||
tok = line.strip().split()
|
tok = line.strip().split()
|
||||||
|
@ -769,9 +687,8 @@ def gentext():
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if word in pinstrs:
|
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))
|
b_text.write(idx.to_bytes(1, byteorder='little', signed=False))
|
||||||
suff_mask = 0
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if word in plabels_text:
|
if word in plabels_text:
|
||||||
|
@ -785,9 +702,7 @@ def gentext():
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if word in special_syms:
|
if word in special_syms:
|
||||||
if word == "%%suff":
|
if word == "%%imm8":
|
||||||
suff_mask = 1<<7
|
|
||||||
elif word == "%%imm8":
|
|
||||||
lastimm = 1
|
lastimm = 1
|
||||||
elif word == "%%imm16":
|
elif word == "%%imm16":
|
||||||
lastimm = 2
|
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
|
$rax $r0
|
||||||
$rbx $r1
|
$rbx $r1
|
||||||
$rcx $r2
|
$rcx $r2
|
||||||
$rdx $r3
|
$rdx $r3
|
||||||
$rsi $r4
|
$rsi $r4
|
||||||
$rdi $r5
|
$rdi $r5
|
||||||
|
|
||||||
$ax0 $r6
|
$ax0 $r6
|
||||||
$ax1 $r7
|
$ax1 $r7
|
||||||
$ax2 $r8
|
$ax2 $r8
|
||||||
|
@ -29,6 +21,19 @@ $nx5 $r17
|
||||||
$nx6 $r18
|
$nx6 $r18
|
||||||
$nx7 $r19
|
$nx7 $r19
|
||||||
$nx8 $r20
|
$nx8 $r20
|
||||||
|
|
||||||
$grp $r21
|
$grp $r21
|
||||||
$trp $r22
|
$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
|
; Limits
|
||||||
;
|
;
|
||||||
|
|
||||||
CHAR_MIN := 0x0000000000000080
|
CHAR_MIN := 0x80
|
||||||
SHRT_MIN := 0x0000000000008000
|
SHRT_MIN := 0x8000
|
||||||
INT_MIN := 0x0000000080000000
|
INT_MIN := 0x80000000
|
||||||
LONG_MIN := 0x8000000000000000
|
LONG_MIN := 0x8000000000000000
|
||||||
|
|
||||||
XCHAR_MIN := 0xFFFFFFFFFFFFFF80
|
XCHAR_MIN := 0xFFFFFFFFFFFFFF80
|
||||||
XSHRT_MIN := 0xFFFFFFFFFFFF8000
|
XSHRT_MIN := 0xFFFFFFFFFFFF8000
|
||||||
XINT_MIN := 0xFFFFFFFF80000000
|
XINT_MIN := 0xFFFFFFFF80000000
|
||||||
|
|
||||||
CHAR_MAX := 0x000000000000007F
|
CHAR_MAX := 0x7F
|
||||||
SHRT_MAX := 0x0000000000007FFF
|
SHRT_MAX := 0x7FFF
|
||||||
INT_MAX := 0x000000007FFFFFFF
|
INT_MAX := 0x7FFFFFFF
|
||||||
LONG_MAX := 0x7FFFFFFFFFFFFFFF
|
LONG_MAX := 0x7FFFFFFFFFFFFFFF
|
||||||
|
|
||||||
BYTE_MAX := 0x00000000000000FF
|
BYTE_MAX := 0xFF
|
||||||
WORD_MAX := 0x000000000000FFFF
|
WORD_MAX := 0xFFFF
|
||||||
LWORD_MAX := 0x00000000FFFFFFFF
|
LWORD_MAX := 0xFFFFFFFF
|
||||||
QWORD_MAX := 0xFFFFFFFFFFFFFFFF
|
QWORD_MAX := 0xFFFFFFFFFFFFFFFF
|
||||||
|
|
||||||
FILE_MAXSZ := 0x0000000000008000
|
FNAME_MAX := 0x80
|
||||||
STRLEN_MAX := 0x000000007AFFFFFF
|
FILE_MAXSZ := 0x8000
|
||||||
FNAME_MAX := 0x0000000000000080
|
STRLEN_MAX := 0x7AFFFFFF
|
||||||
|
|
||||||
;
|
;
|
||||||
; Magic numbers
|
; Magic numbers
|
||||||
;
|
;
|
||||||
|
|
||||||
PRN_CLEAR := 0x000000008BF00001
|
PRN_CLEAR := 0x8BF00001
|
||||||
PRN_FLUSH := 0x000000008BF00002
|
PRN_FLUSH := 0x8BF00002
|
||||||
|
|
||||||
;
|
;
|
||||||
; CRT librairies
|
; CRT librairies
|
||||||
;
|
;
|
||||||
|
|
||||||
include "crt/sys.k"
|
include "crt/sys.k"
|
||||||
include "crt/err/errno.k"
|
include "crt/str.k"
|
||||||
include "crt/fmt/format.k"
|
include "crt/mem.k"
|
||||||
include "crt/str/string.k"
|
include "crt/time.k"
|
||||||
include "crt/mem/memory.k"
|
|
||||||
include "crt/lib/time.k"
|
|
||||||
|
|
||||||
|
include "crt/fmt/ltostr.k"
|
||||||
|
include "crt/fmt/strtol.k"
|
||||||
|
include "crt/fmt/doprnt.k"
|
||||||
|
include "crt/fmt/printf.k"
|
||||||
abort:
|
abort:
|
||||||
crash
|
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 r12, ax2 ; fmt
|
||||||
mov r14, ax3 ; va_list
|
mov r14, ax3 ; va_list
|
||||||
mov r15, ax1 ; n
|
mov r15, ax1 ; n
|
||||||
mov r16, zero ; return value
|
|
||||||
mov r17, ax0 ; putc
|
mov r17, ax0 ; putc
|
||||||
|
nul r16 ; return value
|
||||||
|
|
||||||
.main_loop:
|
.main_loop:
|
||||||
; find '%' or null-terminator
|
; find '%' or null-terminator
|
||||||
mov rcx, STRLEN_MAX
|
mov rcx, STRLEN_MAX
|
||||||
mov r13, r12
|
mov r13, r12
|
||||||
scasb.rep.nz r13, '%'
|
scasb r13, '%'
|
||||||
|
|
||||||
; everything below r13 is a regular character; print it
|
; everything below r13 is a regular character; print it
|
||||||
.print_regular:
|
.print_regular:
|
||||||
|
@ -62,7 +62,7 @@ doprnt:
|
||||||
bzr r13, .nullstring
|
bzr r13, .nullstring
|
||||||
|
|
||||||
.print_string:
|
.print_string:
|
||||||
mov ax0, b[r13]
|
movzx ax0, b[r13]
|
||||||
bzr ax0, .main_loop
|
bzr ax0, .main_loop
|
||||||
|
|
||||||
inc r13, 1
|
inc r13, 1
|
||||||
|
@ -107,7 +107,7 @@ doprnt:
|
||||||
inc r14, 8
|
inc r14, 8
|
||||||
|
|
||||||
.print_itoa_buf:
|
.print_itoa_buf:
|
||||||
mov ax0, b[r13]
|
movzx ax0, b[r13]
|
||||||
|
|
||||||
bzr ax0, .pib_end_loop
|
bzr ax0, .pib_end_loop
|
||||||
inc r13, 1
|
inc r13, 1
|
||||||
|
@ -144,8 +144,9 @@ doprnt:
|
||||||
.epilogue:
|
.epilogue:
|
||||||
mov rax, r16
|
mov rax, r16
|
||||||
|
|
||||||
pop r17, r16, r15
|
pop r17, r16
|
||||||
pop r14, r13, r12
|
pop r15, r14
|
||||||
|
pop r13, r12
|
||||||
|
|
||||||
leave
|
leave
|
||||||
ret
|
ret
|
||||||
|
@ -170,7 +171,7 @@ doprnt:
|
||||||
jraxz .r
|
jraxz .r
|
||||||
|
|
||||||
; yes, so artificially set n=0
|
; yes, so artificially set n=0
|
||||||
mov r15, zero
|
nul r15
|
||||||
|
|
||||||
.r:
|
.r:
|
||||||
ret
|
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)
|
; void utoa(char *buf, int num, int base)
|
||||||
;
|
;
|
||||||
utoa:
|
utoa:
|
||||||
mov ax3, zero
|
nul ax3
|
||||||
jmp ltostr
|
jmp ltostr
|
||||||
|
|
||||||
;
|
;
|
||||||
|
@ -20,7 +20,7 @@ utoa:
|
||||||
;
|
;
|
||||||
ltostr:
|
ltostr:
|
||||||
mov rax, ax0
|
mov rax, ax0
|
||||||
mov rcx, zero
|
nul rcx
|
||||||
|
|
||||||
; make sure base is in [2, 32]
|
; make sure base is in [2, 32]
|
||||||
bltu ax2, 2, .bad
|
bltu ax2, 2, .bad
|
||||||
|
@ -37,7 +37,7 @@ ltostr:
|
||||||
shr rcx, ax1, 63 ; extract ax1 sign
|
shr rcx, ax1, 63 ; extract ax1 sign
|
||||||
jrcxz .conv
|
jrcxz .conv
|
||||||
|
|
||||||
sub ax1, zero, ax1 ; NEG if negative
|
neg ax1 ; NEG if negative
|
||||||
|
|
||||||
; main loop
|
; main loop
|
||||||
.conv:
|
.conv:
|
||||||
|
@ -68,7 +68,7 @@ ltostr:
|
||||||
inc ax0, 1
|
inc ax0, 1
|
||||||
|
|
||||||
.cxz:
|
.cxz:
|
||||||
mov b[ax0], zero
|
nul b[ax0]
|
||||||
|
|
||||||
call strrev2, rax
|
call strrev2, rax
|
||||||
ret
|
ret
|
||||||
|
@ -77,7 +77,6 @@ ltostr:
|
||||||
; exceptional cases
|
; exceptional cases
|
||||||
;
|
;
|
||||||
.bad:
|
.bad:
|
||||||
mov q[errno], EINVAL
|
|
||||||
mov b[ax0], 0
|
mov b[ax0], 0
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
;
|
;
|
||||||
putc:
|
putc:
|
||||||
prn ax0
|
prn ax0
|
||||||
mov rax, zero
|
nul rax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
|
@ -18,7 +18,7 @@ strtol:
|
||||||
; rdx = pointer to first invalid byte
|
; rdx = pointer to first invalid byte
|
||||||
;
|
;
|
||||||
strtoul:
|
strtoul:
|
||||||
mov ax2, zero
|
nul ax2
|
||||||
jmp strtoq
|
jmp strtoq
|
||||||
|
|
||||||
;
|
;
|
||||||
|
@ -27,8 +27,7 @@ strtoul:
|
||||||
; guesses base when 'base'=0
|
; guesses base when 'base'=0
|
||||||
;
|
;
|
||||||
strtoq:
|
strtoq:
|
||||||
mov rax, zero
|
nul rax, rsi
|
||||||
mov rsi, zero
|
|
||||||
mov rdx, ax0
|
mov rdx, ax0
|
||||||
|
|
||||||
; make sure base is in [2, 32]
|
; make sure base is in [2, 32]
|
||||||
|
@ -158,12 +157,11 @@ strtoq:
|
||||||
bzr rsi, .r
|
bzr rsi, .r
|
||||||
|
|
||||||
; yes
|
; yes
|
||||||
sub rax, zero, rax
|
neg rax
|
||||||
|
|
||||||
.r:
|
.r:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.bad:
|
.bad:
|
||||||
mov q[errno], EINVAL
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ memzero:
|
||||||
jrcxz .r
|
jrcxz .r
|
||||||
|
|
||||||
.l:
|
.l:
|
||||||
mov b[ax0], zero
|
nul b[ax0]
|
||||||
inc ax0, 1
|
inc ax0, 1
|
||||||
loop .l
|
loop .l
|
||||||
|
|
|
@ -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)
|
; TIME *GetTimeUTC(void)
|
||||||
;
|
;
|
||||||
GetTimeUTC:
|
GetTimeUTC:
|
||||||
ytime ax0, ax1, ax2
|
ytime
|
||||||
mov rdx, .buf
|
|
||||||
|
mov rdi, .buf
|
||||||
|
|
||||||
; seconds
|
; seconds
|
||||||
rem rcx, ax0, 60
|
rem rsi, rax, 60
|
||||||
mov b[rdx], rcx
|
mov b[rdi], rsi
|
||||||
|
|
||||||
; minutes
|
; minutes
|
||||||
div rcx, ax0, 60
|
div rsi, rax, 60
|
||||||
rem rcx, 60
|
rem rsi, 60
|
||||||
mov b[rdx+1], rcx
|
mov b[rdi+1], rsi
|
||||||
|
|
||||||
; hours
|
; hours
|
||||||
div rcx, ax0, 3600
|
div rsi, rax, 3600
|
||||||
rem rcx, 24
|
rem rsi, 24
|
||||||
mov b[rdx+2], rcx
|
mov b[rdi+2], rsi
|
||||||
|
|
||||||
; month days
|
; month days
|
||||||
div rcx, ax0, 3600*24
|
div rsi, rax, 3600*24
|
||||||
mov b[rdx+3], rcx
|
mov b[rdi+3], rsi
|
||||||
|
|
||||||
; month
|
; month
|
||||||
mov b[rdx+4], ax1
|
mov b[rdi+4], rbx
|
||||||
|
|
||||||
; years
|
; years
|
||||||
mov w[rdx+6], ax2
|
mov w[rdi+6], rcx
|
||||||
|
|
||||||
;
|
;
|
||||||
; ydays (TODO)
|
; ydays (TODO)
|
|
@ -26,7 +26,7 @@ start:
|
||||||
mov rsp, DOSKRNL_STACK
|
mov rsp, DOSKRNL_STACK
|
||||||
mov rbp, zero
|
mov rbp, zero
|
||||||
|
|
||||||
; dump
|
;dump
|
||||||
|
|
||||||
call main
|
call main
|
||||||
|
|
||||||
|
|
|
@ -15,15 +15,13 @@ def mkstat(fp):
|
||||||
if len(tok) == 0:
|
if len(tok) == 0:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
i = tok[0].split('.')[0]
|
if len(tok[0]) == 0 or tok[0] in ';#@/':
|
||||||
|
|
||||||
if len(i) == 0 or i in ';#@/':
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if i in instrs:
|
if tok[0] in instrs:
|
||||||
instrs[i] += 1
|
instrs[tok[0]] += 1
|
||||||
else:
|
else:
|
||||||
instrs[i] = 1
|
instrs[tok[0]] = 1
|
||||||
|
|
||||||
for root, _, files in os.walk('.'):
|
for root, _, files in os.walk('.'):
|
||||||
for f in files:
|
for f in files:
|
||||||
|
|
|
@ -9,18 +9,12 @@ dumprf:
|
||||||
mov r12, ax0
|
mov r12, ax0
|
||||||
mov r13, rsp
|
mov r13, rsp
|
||||||
|
|
||||||
call RFS.LoadReg, r12, $cr2
|
|
||||||
push rax
|
|
||||||
|
|
||||||
call RFS.LoadReg, r12, $cr1
|
call RFS.LoadReg, r12, $cr1
|
||||||
push rax
|
push rax
|
||||||
|
|
||||||
call RFS.LoadReg, r12, $cr0
|
call RFS.LoadReg, r12, $cr0
|
||||||
push rax
|
push rax
|
||||||
|
|
||||||
call RFS.LoadReg, r12, $rfx
|
|
||||||
push rax
|
|
||||||
|
|
||||||
call RFS.LoadReg, r12, $rip
|
call RFS.LoadReg, r12, $rip
|
||||||
push rax
|
push rax
|
||||||
|
|
||||||
|
@ -33,7 +27,7 @@ dumprf:
|
||||||
call RFS.LoadReg, r12, $trp
|
call RFS.LoadReg, r12, $trp
|
||||||
push rax
|
push rax
|
||||||
|
|
||||||
push 0 # fixme
|
push zero # fixme
|
||||||
|
|
||||||
call RFS.LoadReg, r12, $rbp
|
call RFS.LoadReg, r12, $rbp
|
||||||
push rax
|
push rax
|
||||||
|
@ -120,7 +114,7 @@ dumprf:
|
||||||
leave
|
leave
|
||||||
ret
|
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"
|
.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"
|
.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"
|
.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
|
push ax1
|
||||||
call printf, .scr1
|
call printf, .scr1
|
||||||
pop zero
|
pop
|
||||||
|
|
||||||
bnz r14, .not_con
|
bnz r14, .not_con
|
||||||
push .scr2_con
|
push .scr2_con
|
||||||
|
|
|
@ -18,7 +18,7 @@ DefaultExceptionHandler:
|
||||||
|
|
||||||
.err_ukn = "Unknown exception number\0\0\0\0\0\0\0"
|
.err_ukn = "Unknown exception number\0\0\0\0\0\0\0"
|
||||||
.err_udf = "Undefined behaviour exception\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_acc = "Invalid memory access exception"
|
||||||
.err_sys = "Supervisor-only exception used\0"
|
.err_sys = "Supervisor-only exception used\0"
|
||||||
.err_dbf = "Double fault exception~~~~~~~~\0"
|
.err_dbf = "Double fault exception~~~~~~~~\0"
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
; See the LICENSE file in the project root for more information.
|
; See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
TrapHandlers.prolog:
|
TrapHandlers.prolog:
|
||||||
mov rbp, zero
|
nul rbp
|
||||||
|
|
||||||
; rax = caller's cr2
|
; rax = caller's cr1
|
||||||
call RFS.LoadReg, r14, $cr2
|
call RFS.LoadReg, r14, $cr1
|
||||||
|
|
||||||
; we don't preserve the r12 we got
|
; we don't preserve the r12 we got
|
||||||
mov r12, rax
|
mov r12, rax
|
||||||
mov rdx, zero
|
nul rdx
|
||||||
|
|
||||||
jmp rcx
|
jmp rcx
|
||||||
|
|
||||||
|
@ -105,12 +105,8 @@ DefaultTrapHandler:
|
||||||
mov ax2, rcx
|
mov ax2, rcx
|
||||||
call RFS.StoreReg, zero, $cr1
|
call RFS.StoreReg, zero, $cr1
|
||||||
|
|
||||||
; Data offset
|
|
||||||
mov ax2, rcx
|
|
||||||
call RFS.StoreReg, zero, $cr2
|
|
||||||
|
|
||||||
; Return frame
|
; Return frame
|
||||||
mov r14, zero
|
nul r14
|
||||||
|
|
||||||
jmp .fini
|
jmp .fini
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,9 @@ builtins.dir:
|
||||||
push r12, r13
|
push r12, r13
|
||||||
push r14, r15
|
push r14, r15
|
||||||
|
|
||||||
mov r12, zero # no. of files found
|
nul r12 # no. of files found
|
||||||
mov r13, zero # no. of directories found
|
nul r13 # no. of directories found
|
||||||
mov r14, zero # total amount of bytes found
|
nul r14 # total amount of bytes found
|
||||||
|
|
||||||
call print, .dirmsg
|
call print, .dirmsg
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ builtins.dir:
|
||||||
mov rcx, FNAME_MAX
|
mov rcx, FNAME_MAX
|
||||||
mov rsi, .buf
|
mov rsi, .buf
|
||||||
mov rdi, rsi
|
mov rdi, rsi
|
||||||
scasb.rep.nz rsi, '.'
|
scasb rsi, '.'
|
||||||
|
|
||||||
; print file name
|
; print file name
|
||||||
sub ax1, rsi, rdi
|
sub ax1, rsi, rdi
|
||||||
|
|
|
@ -21,14 +21,16 @@ main:
|
||||||
.print_prompt:
|
.print_prompt:
|
||||||
call print, prompt
|
call print, prompt
|
||||||
|
|
||||||
; empty argbuf
|
; empty stuff
|
||||||
call memzero, argbuf, argbuf.size
|
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
|
; iterator through argbuf
|
||||||
mov rcx, zero
|
nul rcx
|
||||||
|
|
||||||
mov q[argv1pos], zero
|
|
||||||
|
|
||||||
.input_loop:
|
.input_loop:
|
||||||
pause
|
pause
|
||||||
|
@ -51,7 +53,7 @@ main:
|
||||||
; yes, delete it
|
; yes, delete it
|
||||||
dec rcx, 1
|
dec rcx, 1
|
||||||
add rdx, rcx, argbuf
|
add rdx, rcx, argbuf
|
||||||
mov b[rdx], zero
|
nul b[rdx]
|
||||||
|
|
||||||
; update screen
|
; update screen
|
||||||
bzr b[stdin_echoing], .input_loop
|
bzr b[stdin_echoing], .input_loop
|
||||||
|
@ -86,7 +88,7 @@ main:
|
||||||
; find first whitespace or null-terminator
|
; find first whitespace or null-terminator
|
||||||
mov rcx, argbuf.size
|
mov rcx, argbuf.size
|
||||||
mov rdx, argbuf
|
mov rdx, argbuf
|
||||||
scasb.rep.nz rdx, ' '
|
scasb rdx, ' '
|
||||||
|
|
||||||
; argv1 exists? if so, save its position
|
; argv1 exists? if so, save its position
|
||||||
mov rsi, rdx
|
mov rsi, rdx
|
||||||
|
@ -108,9 +110,6 @@ main:
|
||||||
; fallthrough
|
; fallthrough
|
||||||
|
|
||||||
.do_extract:
|
.do_extract:
|
||||||
; empty argv0
|
|
||||||
call memzero, argv0, argbuf.size
|
|
||||||
|
|
||||||
; how much do we copy?
|
; how much do we copy?
|
||||||
sub rcx, rdx, argbuf
|
sub rcx, rdx, argbuf
|
||||||
jrcxz .detect_builtin
|
jrcxz .detect_builtin
|
||||||
|
|
|
@ -250,6 +250,8 @@ long cpudev_idtdone(dev_t *dev)
|
||||||
if (idt_handling[R(AX0)] == 0)
|
if (idt_handling[R(AX0)] == 0)
|
||||||
_except(E_UDF, "cpudev: idtdone, not handling E/I #%u", R(AX0));
|
_except(E_UDF, "cpudev: idtdone, not handling E/I #%u", R(AX0));
|
||||||
|
|
||||||
|
//trace("IDT.DONE %lu\n", R(AX0));
|
||||||
|
|
||||||
idt_handling[R(AX0)]--;
|
idt_handling[R(AX0)]--;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
102
vm/in/ALU
102
vm/in/ALU
|
@ -5,113 +5,83 @@
|
||||||
# Logical instructions #
|
# Logical instructions #
|
||||||
#---------------------------------------------------------------------------#
|
#---------------------------------------------------------------------------#
|
||||||
|
|
||||||
#
|
# Bitwise NOT
|
||||||
# Bitwise OR operation
|
not 1
|
||||||
#
|
|
||||||
# $dest = $src1 OR $src2
|
# Bitwise OR
|
||||||
#
|
|
||||||
or 2
|
or 2
|
||||||
or 3
|
or 3
|
||||||
|
|
||||||
#
|
# Bitwise AND
|
||||||
# Bitwise AND operation
|
|
||||||
#
|
|
||||||
# $dest = $src1 AND $src2
|
|
||||||
#
|
|
||||||
and 2
|
and 2
|
||||||
and 3
|
and 3
|
||||||
|
|
||||||
#
|
# Bitwise XOR
|
||||||
# Bitwise XOR operation
|
|
||||||
#
|
|
||||||
# $dest = $src1 XOR $src2
|
|
||||||
#
|
|
||||||
xor 2
|
xor 2
|
||||||
xor 3
|
xor 3
|
||||||
|
|
||||||
#
|
# Logical left/right shift
|
||||||
# Logical left/right shift (SHL/SHR)
|
|
||||||
#
|
|
||||||
# $dest = $src1 << $src2 (SHL)
|
|
||||||
# $dest = $src1 >> $src2 (SHR)
|
|
||||||
#
|
|
||||||
shl 2
|
shl 2
|
||||||
shl 3
|
shl 3
|
||||||
shr 2
|
shr 2
|
||||||
shr 3
|
shr 3
|
||||||
|
|
||||||
#
|
# Arithmetical right shift
|
||||||
# Arithmetical right shift (SAR)
|
|
||||||
#
|
|
||||||
# $dest = $src1 >>> $src2 (SAR)
|
|
||||||
#
|
|
||||||
sar 2
|
sar 2
|
||||||
sar 3
|
sar 3
|
||||||
|
|
||||||
#---------------------------------------------------------------------------#
|
#---------------------------------------------------------------------------#
|
||||||
# Arithmetic instructions #
|
# Arithmetic instructions #
|
||||||
#---------------------------------------------------------------------------#
|
#---------------------------------------------------------------------------#
|
||||||
#
|
|
||||||
# Arithmetical ADD operation
|
# Negation
|
||||||
#
|
neg 1
|
||||||
# $dest1 = $src1 + $src2
|
|
||||||
#
|
# Negation but traps on $src == -2^N
|
||||||
|
negv 1
|
||||||
|
|
||||||
|
# Addition
|
||||||
add 2
|
add 2
|
||||||
add 3
|
add 3
|
||||||
|
|
||||||
#
|
# Addition but traps on overflow
|
||||||
# Arithmetical SUB operation
|
addv 2
|
||||||
#
|
addv 3
|
||||||
# $dest = $src1 - $src2
|
|
||||||
#
|
# Substraction
|
||||||
sub 2
|
sub 2
|
||||||
sub 3
|
sub 3
|
||||||
|
|
||||||
#
|
# Substraction but traps on underflow
|
||||||
# Arithmetical MUL operation
|
subv 2
|
||||||
#
|
subv 3
|
||||||
# $dest = LO($src1 * $src2)
|
|
||||||
#
|
# Multiplication
|
||||||
|
# $dest = LO($src1 * $src2)
|
||||||
mul 2
|
mul 2
|
||||||
mul 3
|
mul 3
|
||||||
|
|
||||||
# Arithmetical unsigned MUL operation
|
# Multiplication (unsigned)
|
||||||
#
|
# $dest1 = HI($dest2 * $src)
|
||||||
# $dest1 = HI($dest2 * $src)
|
# $dest2 = LO($dest2 * $src)
|
||||||
# $dest2 = LO($dest2 * $src)
|
|
||||||
#
|
#
|
||||||
mulhi 3
|
mulhi 3
|
||||||
|
|
||||||
# Arithmetical signed MUL operation
|
# Multiplication (signed)
|
||||||
#
|
# $dest1 = HI($dest2 * $src)
|
||||||
# $dest1 = HI($dest2 ** $src)
|
# $dest2 = LO($dest2 * $src)
|
||||||
# $dest2 = LO($dest2 ** $src)
|
|
||||||
#
|
#
|
||||||
imulhi 3
|
imulhi 3
|
||||||
|
|
||||||
#
|
# Division (unsigned)
|
||||||
# Arithmetical unsigned DIV operation
|
|
||||||
#
|
|
||||||
# $dest = $src1 DIV $src2
|
|
||||||
#
|
|
||||||
# Preserves all flags
|
|
||||||
#
|
|
||||||
div 2
|
div 2
|
||||||
div 3
|
div 3
|
||||||
|
|
||||||
#
|
# Division (signed)
|
||||||
# Arithmetical signed DIV operation
|
|
||||||
#
|
|
||||||
# $dest = $src1 IDIV $src2
|
|
||||||
#
|
|
||||||
idiv 2
|
idiv 2
|
||||||
idiv 3
|
idiv 3
|
||||||
|
|
||||||
#
|
# Modulo/remainder
|
||||||
# Arithmetical modulo operation (REM)
|
|
||||||
#
|
|
||||||
# $dest = $src1 MOD $src2
|
|
||||||
#
|
|
||||||
rem 2
|
rem 2
|
||||||
rem 3
|
rem 3
|
||||||
|
|
||||||
|
|
24
vm/in/MEM
24
vm/in/MEM
|
@ -57,14 +57,17 @@ push 3
|
||||||
# $1 = *RSP
|
# $1 = *RSP
|
||||||
# RSP = RSP + 8
|
# RSP = RSP + 8
|
||||||
#
|
#
|
||||||
|
pop 0
|
||||||
pop 1
|
pop 1
|
||||||
pop 2
|
pop 2
|
||||||
pop 3
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------#
|
#---------------------------------------------------------------------------#
|
||||||
# Movement instructions #
|
# Movement instructions #
|
||||||
#---------------------------------------------------------------------------#
|
#---------------------------------------------------------------------------#
|
||||||
|
|
||||||
|
nul 1
|
||||||
|
nul 2
|
||||||
|
|
||||||
#
|
#
|
||||||
# Load Effective Address (LEA) instruction
|
# Load Effective Address (LEA) instruction
|
||||||
#
|
#
|
||||||
|
@ -78,27 +81,22 @@ pop 3
|
||||||
lea 2
|
lea 2
|
||||||
|
|
||||||
#
|
#
|
||||||
# Move data (MOV) instruction
|
# Move data (MOV/MOVU) instructions
|
||||||
#
|
#
|
||||||
# $1 = SignExtend($2)
|
# $1 = SignExtend($2) (MOV)
|
||||||
|
# $1 = ZeroExtend($2) (MOVU)
|
||||||
#
|
#
|
||||||
mov 2
|
mov 2
|
||||||
|
|
||||||
#
|
|
||||||
# Load from memory with zero-extension (MOVSX/MOVZX) instruction
|
|
||||||
#
|
|
||||||
# $1 = ZeroExtend($2)
|
|
||||||
#
|
|
||||||
movzx 2
|
movzx 2
|
||||||
|
|
||||||
#
|
#
|
||||||
# Move with sign-extension (MOVSXx) instruction
|
# Move with sign-extension (MOVx) instruction
|
||||||
#
|
#
|
||||||
# $1 = SignExtend($2 & (2^(8 * sizeof(x)) - 1)
|
# $1 = SignExtend($2 & (2^(8 * sizeof(x)) - 1)
|
||||||
#
|
#
|
||||||
movsxb 2
|
movb 2
|
||||||
movsxw 2
|
movw 2
|
||||||
movsxd 2
|
movd 2
|
||||||
|
|
||||||
#
|
#
|
||||||
# Exchange (XCHG) instruction
|
# Exchange (XCHG) instruction
|
||||||
|
|
|
@ -45,7 +45,7 @@ utime 1
|
||||||
# $2 = current month
|
# $2 = current month
|
||||||
# $3 = current year
|
# $3 = current year
|
||||||
#
|
#
|
||||||
ytime 3
|
ytime 0
|
||||||
|
|
||||||
#
|
#
|
||||||
# Clear all GPR registers except RBP/RSP
|
# 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)
|
# Scan string for a particular value (SCASx)
|
||||||
#
|
#
|
||||||
# CMP([%1], $2)
|
# WHILE RCX > 0 DO
|
||||||
|
# RCX = RCX - 1
|
||||||
#
|
#
|
||||||
# IF ([%1] == 0) THEN
|
# IF ([%1] == 0) OR ([%1] == $2) THEN
|
||||||
# ZF = 1
|
# BREAK
|
||||||
# ELIF (ZF == 0) THEN
|
# ELSE
|
||||||
# IF (DF == 0) THEN
|
# %1 = %1 + sizeof(x)
|
||||||
# %1 = %1 + sizeof(x)
|
|
||||||
# ELSE
|
|
||||||
# %1 = %1 - sizeof(x)
|
|
||||||
# FI
|
|
||||||
# FI
|
# 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:
|
# Note: Does not move past the value when found
|
||||||
# - Does not move past the value when found
|
|
||||||
# - 'SCASB.REP.NZ reg ch' is a short 'strchnul()'
|
|
||||||
#
|
#
|
||||||
scasb 2
|
scasb 2
|
||||||
scasw 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(not, 1) { SRCP(p1); *r1 = ~p1->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(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(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(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(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(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(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(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, 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(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, 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(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);
|
SRCP(p1); SRCP(p2);
|
||||||
|
|
||||||
p2->val += !!(R(RFX)&CF);
|
ulong rs = p1->val - p2->val;
|
||||||
COMPARE_ADD(p1->val, p2->val);
|
|
||||||
*r1 = 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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
IMPL_START(adcx, 3) {
|
IMPL_START(subv, 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) {
|
|
||||||
SRCP(p1); SRCP(p2);
|
SRCP(p1); SRCP(p2);
|
||||||
|
|
||||||
p2->val += !!(R(RFX)&CF);
|
ulong rs = p2->val - p3->val;
|
||||||
COMPARE_SUB(p1->val, p2->val);
|
|
||||||
*r1 = p1->val - p2->val;
|
|
||||||
|
|
||||||
return 1;
|
if (((p2->val ^ rs) & (p2->val ^ p3->val)) >> 63)
|
||||||
}
|
_except(E_OVF, "Signed substraction underflow (SUBV#3)");
|
||||||
|
|
||||||
IMPL_START(sbbx, 3) {
|
|
||||||
SRCP(p2); SRCP(p3);
|
|
||||||
|
|
||||||
p3->val += !!(R(RFX)&CF);
|
|
||||||
COMPARE_SUB(p2->val, p3->val);
|
|
||||||
*r1 = p2->val - p3->val;
|
|
||||||
|
|
||||||
|
*r1 = rs;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ def parse_2(fp):
|
||||||
.format(deprecated, tok[0], n, tok[0], n))
|
.format(deprecated, tok[0], n, tok[0], n))
|
||||||
hd.write("#else\n")
|
hd.write("#else\n")
|
||||||
hd.write("#define I_{}_{} {}\n".format(tok[0].upper(), n, count))
|
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))
|
.format(tok[0], n))
|
||||||
hd.write("#endif\n\n")
|
hd.write("#endif\n\n")
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
#define IMPL_START(name, n) \
|
#define IMPL_START(name, n) \
|
||||||
uint i_##name##_##n(acc_t *p1, acc_t *p2, acc_t *p3, \
|
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) \
|
#define XSRCP(v, p, x) \
|
||||||
if (ACC_FMT_IS_MEM(p->type)) \
|
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() \
|
#define CHK_SUPERV() \
|
||||||
do { \
|
do { \
|
||||||
if ((R(CR0) & UF) > 0) { \
|
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(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(jrcxnz, 1) { if (R(RCX)) R(RIP) = p1->val; return 0; }
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------//
|
||||||
|
|
||||||
IMPL_START(loop, 1) {
|
IMPL_START(loop, 1) {
|
||||||
if (R(RCX) > 0) {
|
if (R(RCX) > 0) {
|
||||||
R(RCX)--;
|
R(RCX)--;
|
||||||
|
@ -21,6 +23,17 @@ IMPL_START(loop, 1) {
|
||||||
return 0;
|
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(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(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; }
|
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(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(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(lea, 2) { *r1 = p2->addr; return 1; }
|
||||||
|
|
||||||
IMPL_START(mov, 2) { XSRCP(*r1, p2, sx); return 1; }
|
IMPL_START(mov, 2) { XSRCP(*r1, p2, sx); return 1; }
|
||||||
IMPL_START(movzx, 2) { XSRCP(*r1, p2, zx); 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(movb, 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(movw, 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(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)
|
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)
|
IMPL_START(pop, 1)
|
||||||
{
|
{
|
||||||
*r1 = readmemzx(R(RSP), 8);
|
*r1 = readmemzx(R(RSP), 8);
|
||||||
|
@ -81,16 +91,6 @@ IMPL_START(pop, 2)
|
||||||
return 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)
|
IMPL_START(call, 1)
|
||||||
|
@ -144,6 +144,14 @@ IMPL_START(ret, 0)
|
||||||
return 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)
|
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(pause, 0) { usleep(5000); return 0; }
|
||||||
IMPL_START(udf, 0) { _except(E_UDF, "UDF instruction"); }
|
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);
|
trace("0x%lX:\t...\n", ctx->cur_pc);
|
||||||
|
|
||||||
else if (!ctx->dumpsw)
|
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;
|
ctx->dumpsw = !ctx->dumpsw;
|
||||||
#endif
|
#endif
|
||||||
|
@ -44,19 +43,19 @@ IMPL_START(dump, 0)
|
||||||
|
|
||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
|
|
||||||
IMPL_START(ytime, 3)
|
IMPL_START(ytime, 0)
|
||||||
{
|
{
|
||||||
time_t t = time(NULL);
|
time_t t = time(NULL);
|
||||||
struct tm *tm = localtime(&t);
|
struct tm *tm = localtime(&t);
|
||||||
|
|
||||||
*r1 = tm->tm_sec + tm->tm_min * 60
|
R(RAX) = tm->tm_sec + tm->tm_min * 60
|
||||||
+ tm->tm_hour * 60 * 60
|
+ tm->tm_hour * 60 * 60
|
||||||
+ tm->tm_mday * 60 * 60 * 24;
|
+ tm->tm_mday * 60 * 60 * 24;
|
||||||
|
|
||||||
*r2 = tm->tm_mon;
|
R(RBX) = tm->tm_mon;
|
||||||
*r3 = tm->tm_year + 1900;
|
R(RCX) = tm->tm_year + 1900;
|
||||||
|
|
||||||
return 3;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
IMPL_START(utime, 1)
|
IMPL_START(utime, 1)
|
||||||
|
@ -72,7 +71,6 @@ IMPL_START(utime, 1)
|
||||||
|
|
||||||
IMPL_START(cls, 0)
|
IMPL_START(cls, 0)
|
||||||
{
|
{
|
||||||
R(RFX) = 0;
|
|
||||||
for (int i = RAX; i <= R20; i++) R(i) = 0;
|
for (int i = RAX; i <= R20; i++) R(i) = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -148,6 +146,8 @@ IMPL_START(prn, 1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
trace("PRN bad magic: %lx\n", v);
|
||||||
|
die(1);
|
||||||
_except(E_ILL, "Bad PRN magic");
|
_except(E_ILL, "Bad PRN magic");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,28 +158,6 @@ IMPL_START(prn, 1)
|
||||||
return 0;
|
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)
|
IMPL_START(scan, 1)
|
||||||
{
|
{
|
||||||
*r1 = console_scankeybuf();
|
*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)
|
static void scas_impl(acc_t *p1, acc_t *p2, uint len)
|
||||||
{
|
{
|
||||||
if (p1->type != A_REG)
|
if (p1->type != A_REG)
|
||||||
_except(E_ILL, "SCASX given a non-REG operand");
|
_except(E_ILL, "SCASX given a non-REG operand");
|
||||||
|
|
||||||
ulong x = readmemsx(R(p1->reg), len);
|
while (R(RCX) > 0)
|
||||||
COMPARE_SUB(x, p2->val);
|
{
|
||||||
|
ulong x = readmemzx(R(p1->reg), len);
|
||||||
|
|
||||||
if (x == 0) {
|
if (x == 0 || x == p2->val)
|
||||||
R(RFX) |= ZF;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
else if (!(R(RFX)&ZF)) {
|
R(p1->reg) += len;
|
||||||
STR_MOVE(p1->reg, len);
|
|
||||||
|
R(RCX)--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
22
vm/pc/DECD
22
vm/pc/DECD
|
@ -3,11 +3,7 @@
|
||||||
|
|
||||||
Instruction encoding:
|
Instruction encoding:
|
||||||
|
|
||||||
Byte 1: Instruction number
|
Byte: Instruction number
|
||||||
Byte 2:
|
|
||||||
xx0xxxxx
|
|
||||||
|| └───┘
|
|
||||||
RL CND
|
|
||||||
|
|
||||||
Values for ModRMs:
|
Values for ModRMs:
|
||||||
000xxxxx xxxxx = reg
|
000xxxxx xxxxx = reg
|
||||||
|
@ -24,19 +20,3 @@ Values for ModRMs:
|
||||||
11100100 imm32 (zero extended)
|
11100100 imm32 (zero extended)
|
||||||
11101000 imm64 (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 ninstrs; // totally
|
||||||
ulong ni_thisfr; // this frame
|
ulong ni_thisfr; // this frame
|
||||||
|
|
||||||
// Last COND field
|
|
||||||
uint cond;
|
|
||||||
|
|
||||||
// Dumpinstr switch
|
// Dumpinstr switch
|
||||||
bool dumpsw;
|
bool dumpsw;
|
||||||
};
|
};
|
||||||
|
|
|
@ -195,8 +195,8 @@ static void extract_param(instr_t *in, acc_t *p)
|
||||||
//
|
//
|
||||||
void decode(void)
|
void decode(void)
|
||||||
{
|
{
|
||||||
|
ushort b;
|
||||||
instr_t *in;
|
instr_t *in;
|
||||||
ushort b1, b2, rep = 0, lock;
|
|
||||||
acc_t p1 = { 0 }, p2 = { 0 }, p3 = { 0 };
|
acc_t p1 = { 0 }, p2 = { 0 }, p3 = { 0 };
|
||||||
|
|
||||||
//logerr("decodin'\n");
|
//logerr("decodin'\n");
|
||||||
|
@ -209,35 +209,20 @@ void decode(void)
|
||||||
_except(E_ACC, "Executing out of memory");
|
_except(E_ACC, "Executing out of memory");
|
||||||
|
|
||||||
// Instruction bytes
|
// Instruction bytes
|
||||||
b1 = fetchb();
|
b = fetchb();
|
||||||
|
|
||||||
// Suffixes?
|
|
||||||
if (b1 & (1 << 7))
|
|
||||||
{
|
|
||||||
b1 &= ~(1 << 7);
|
|
||||||
b2 = fetchb();
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
b2 = 0;
|
|
||||||
|
|
||||||
// Renge check
|
// Renge check
|
||||||
if (b1 >= NINSTRS)
|
if (b >= NINSTRS)
|
||||||
_except(E_ILL, "No such INSTR: 0x%hhX", b1);
|
_except(E_ILL, "No such INSTR: 0x%hhX", b);
|
||||||
|
|
||||||
// Find instruction
|
// Find instruction
|
||||||
in = &ctx->i[b1];
|
in = &ctx->i[b];
|
||||||
ctx->cur_in = in;
|
ctx->cur_in = in;
|
||||||
|
|
||||||
// Get flags/etc
|
|
||||||
rep = !!(b2 & SUFF_REP);
|
|
||||||
lock = !!(b2 & SUFF_LOCK);
|
|
||||||
ctx->cond = b2 & SUFF_COND;
|
|
||||||
|
|
||||||
// Operand 1?
|
// Operand 1?
|
||||||
if (in->nprms == 0)
|
if (in->nprms == 0)
|
||||||
{
|
{
|
||||||
exec_instr(in, NULL, NULL, NULL, lock, rep);
|
exec_instr(in, NULL, NULL, NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,7 +231,7 @@ void decode(void)
|
||||||
// Operand 2?
|
// Operand 2?
|
||||||
if (in->nprms == 1)
|
if (in->nprms == 1)
|
||||||
{
|
{
|
||||||
exec_instr(in, &p1, NULL, NULL, lock, rep);
|
exec_instr(in, &p1, NULL, NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,12 +240,12 @@ void decode(void)
|
||||||
// Operand 1?
|
// Operand 1?
|
||||||
if (in->nprms == 2)
|
if (in->nprms == 2)
|
||||||
{
|
{
|
||||||
exec_instr(in, &p1, &p2, NULL, lock, rep);
|
exec_instr(in, &p1, &p2, NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
extract_param(in, &p3);
|
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.
|
// The OS/K Team licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
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
|
enum
|
||||||
{
|
{
|
||||||
A_NONE = 0,
|
A_NONE = 0,
|
||||||
|
@ -68,22 +44,16 @@ struct instr_t
|
||||||
char *name;
|
char *name;
|
||||||
uint nprms;
|
uint nprms;
|
||||||
uint (*func)(acc_t *, acc_t *, acc_t *,
|
uint (*func)(acc_t *, acc_t *, acc_t *,
|
||||||
ulong *, ulong *, ulong *);
|
ulong *, ulong *);
|
||||||
};
|
};
|
||||||
|
|
||||||
bool eval_cond(uint cond);
|
|
||||||
|
|
||||||
void exec_instr(instr_t *in,
|
void exec_instr(instr_t *in,
|
||||||
acc_t *p1,
|
acc_t *p1,
|
||||||
acc_t *p2,
|
acc_t *p2,
|
||||||
acc_t *p3,
|
acc_t *p3);
|
||||||
bool lock,
|
|
||||||
bool rep);
|
|
||||||
|
|
||||||
void dump_instr(instr_t *in,
|
void dump_instr(instr_t *in,
|
||||||
acc_t *p1,
|
acc_t *p1,
|
||||||
acc_t *p2,
|
acc_t *p2,
|
||||||
acc_t *p3,
|
acc_t *p3);
|
||||||
bool lock,
|
|
||||||
bool rep);
|
|
||||||
|
|
||||||
|
|
42
vm/pc/dump.c
42
vm/pc/dump.c
|
@ -5,53 +5,15 @@
|
||||||
|
|
||||||
#define ABS(x) ((short)(x) < 0 ? -x : x)
|
#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);
|
static void dump_acc(acc_t *p);
|
||||||
|
|
||||||
void dump_instr(instr_t *in,
|
void dump_instr(instr_t *in,
|
||||||
acc_t *p1,
|
acc_t *p1,
|
||||||
acc_t *p2,
|
acc_t *p2,
|
||||||
acc_t *p3,
|
acc_t *p3)
|
||||||
bool lock,
|
|
||||||
bool rep)
|
|
||||||
{
|
{
|
||||||
uint cond = ctx->cond;
|
|
||||||
|
|
||||||
trace("0x%lX:\t", ctx->cur_pc);
|
trace("0x%lX:\t", ctx->cur_pc);
|
||||||
|
trace("%s\t", in->name);
|
||||||
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");
|
|
||||||
|
|
||||||
if (p1)
|
if (p1)
|
||||||
dump_acc(p1);
|
dump_acc(p1);
|
||||||
|
|
|
@ -75,7 +75,7 @@ void _except(int _code, char *fmt, ...)
|
||||||
{
|
{
|
||||||
if (ctx->dumpsw)
|
if (ctx->dumpsw)
|
||||||
{
|
{
|
||||||
trace("\nException %u - ", code);
|
trace("\n(Caught) Exception %u - ", code);
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
vprintf(fmt, ap);
|
vprintf(fmt, ap);
|
||||||
|
|
77
vm/pc/exec.c
77
vm/pc/exec.c
|
@ -3,41 +3,6 @@
|
||||||
|
|
||||||
#include <pc/arch.h>
|
#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) { \
|
#define OUTPUT(p, r) { \
|
||||||
if (p->type == A_REG) \
|
if (p->type == A_REG) \
|
||||||
R(p->reg) = r; \
|
R(p->reg) = r; \
|
||||||
|
@ -52,54 +17,26 @@ bool eval_cond(uint cond)
|
||||||
void exec_instr(instr_t *in,
|
void exec_instr(instr_t *in,
|
||||||
acc_t *p1,
|
acc_t *p1,
|
||||||
acc_t *p2,
|
acc_t *p2,
|
||||||
acc_t *p3,
|
acc_t *p3)
|
||||||
bool lock,
|
|
||||||
bool rep)
|
|
||||||
{
|
{
|
||||||
uint out;
|
uint out;
|
||||||
ulong r1 = 0, r2 = 0, r3 = 0;
|
ulong r1 = 0, r2 = 0;
|
||||||
|
|
||||||
// Global instruction counter
|
// Global instruction counter
|
||||||
ctx->ninstrs++;
|
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)
|
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);
|
||||||
out = in->func(p1, p2, p3, &r1, &r2, &r3);
|
|
||||||
|
|
||||||
if (out)
|
if (out)
|
||||||
{
|
{
|
||||||
OUTPUT(p1, r1);
|
OUTPUT(p1, r1);
|
||||||
if (out >= 2) OUTPUT(p2, r2);
|
if (__builtin_expect(out == 2, 0))
|
||||||
if (out >= 3) OUTPUT(p3, r3);
|
OUTPUT(p2, r2);
|
||||||
|
|
||||||
R(RZX) = 0;
|
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() \
|
#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[] =
|
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 },
|
{ "rax", GPR }, { "rbx", GPR }, { "rcx", GPR }, { "rdx", GPR },
|
||||||
{ "rsi", GPR }, { "rdi", GPR }, { "ax0", GPR }, { "ax1", GPR },
|
{ "rsi", GPR }, { "rdi", GPR }, { "ax0", GPR }, { "ax1", GPR },
|
||||||
{ "ax2", GPR }, { "ax3", GPR }, { "ax4", GPR }, { "ax5", 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 },
|
{ "r12", GPR }, { "r13", GPR }, { "r14", GPR }, { "r15", GPR },
|
||||||
{ "r16", GPR }, { "r17", GPR }, { "r18", GPR }, { "r19", GPR },
|
{ "r16", GPR }, { "r17", GPR }, { "r18", GPR }, { "r19", GPR },
|
||||||
{ "r20", GPR }, { "grp", GPR }, { "trp", GPR }, { "srp", SYS },
|
{ "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, "");
|
static_assert(sizeof(arch_r)/sizeof(reg_t) == NREGS, "");
|
||||||
|
@ -26,8 +26,8 @@ void dumpregs()
|
||||||
TRACE("Current RFRAME index: #%lu", rfs_current_idx);
|
TRACE("Current RFRAME index: #%lu", rfs_current_idx);
|
||||||
|
|
||||||
TRACE("\n\nEnviron #1:");
|
TRACE("\n\nEnviron #1:");
|
||||||
TRACE("\nrpc=0x%-16lX rip=0x%-16lX rfx=0x%-16lX", ctx->cur_pc, R(RIP), R(RFX));
|
TRACE("\nrpc=0x%-16lX rip=0x%-16lX", ctx->cur_pc, R(RIP));
|
||||||
TRACE("\ncr0=0x%-16lX cr1=0x%-16lX cr2=0x%-16lX", R(CR0), R(CR1), R(CR2));
|
TRACE("\ncr0=0x%-16lX cr1=0x%-16lX", R(CR0), R(CR1));
|
||||||
|
|
||||||
TRACE("\n\nEnviron #2:");
|
TRACE("\n\nEnviron #2:");
|
||||||
TRACE("\nrsp=0x%-16lX rbp=0x%-16lX ins=0d%-16lu", R(RSP), R(RBP), ctx->ninstrs);
|
TRACE("\nrsp=0x%-16lX rbp=0x%-16lX ins=0d%-16lu", R(RSP), R(RBP), ctx->ninstrs);
|
||||||
|
|
|
@ -37,10 +37,10 @@ struct reg_t
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
RZX, CR0, CR1, CR2, RFX, RIP, RBP, RSP,
|
|
||||||
RAX, RBX, RCX, RDX, RSI, RDI, AX0, AX1,
|
RAX, RBX, RCX, RDX, RSI, RDI, AX0, AX1,
|
||||||
AX2, AX3, AX4, AX5, R12, R13, R14, R15,
|
AX2, AX3, AX4, AX5, R12, R13, R14, R15,
|
||||||
R16, R17, R18, R19, R20, GRP, TRP, SRP,
|
R16, R17, R18, R19, R20, GRP, TRP, SRP,
|
||||||
|
TMP, RAD, CR0, CR1, RIP, RBP, RSP, RZX,
|
||||||
|
|
||||||
NREGS
|
NREGS
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,9 +18,9 @@ int create_symtab(const char *name)
|
||||||
return -1;
|
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)
|
if (prev_addr > addr)
|
||||||
{
|
{
|
||||||
|
@ -38,7 +38,6 @@ int create_symtab(const char *name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(tab);
|
fclose(tab);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// The OS/K Team licenses this file to you under the MIT license.
|
// The OS/K Team licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
#define SYMLEN_MAX 32
|
#define SYMLEN_MAX 46
|
||||||
#define SYMTAB_LEN 4096
|
#define SYMTAB_LEN 4096
|
||||||
|
|
||||||
typedef struct sym_t sym_t;
|
typedef struct sym_t sym_t;
|
||||||
|
@ -9,7 +9,7 @@ typedef struct sym_t sym_t;
|
||||||
struct sym_t
|
struct sym_t
|
||||||
{
|
{
|
||||||
ulong addr;
|
ulong addr;
|
||||||
char name[SYMLEN_MAX];
|
char name[SYMLEN_MAX+1];
|
||||||
};
|
};
|
||||||
|
|
||||||
extern sym_t symtab[SYMTAB_LEN];
|
extern sym_t symtab[SYMTAB_LEN];
|
||||||
|
|
Loading…
Reference in New Issue