1
0
mirror of https://gitlab.os-k.eu/os-k-team/kvisc.git synced 2023-08-25 14:05:46 +02:00
This commit is contained in:
julianb0 2019-07-17 22:25:50 +02:00
parent 1b5b90fa37
commit 2a610f2d7a
No known key found for this signature in database
GPG Key ID: DDF8325C95299A62
38 changed files with 252 additions and 418 deletions

View File

@ -129,6 +129,7 @@ inc_depth_max = 16
# Quickly goes through source file and resolves "include" directives ONLY
def do_includes(fi):
global inc_depth
global pcurfile
for _, line in enumerate(fi):
line = line.rstrip()
@ -146,10 +147,11 @@ def do_includes(fi):
print("Invalid format for include directive: {}".format(line))
leave(1)
inc = tok[1][1:-1]
old_curf = pcurfile
pcurfile = tok[1][1:-1]
try:
new_fi = open(inc, "r")
new_fi = open(pcurfile, "r")
except:
print("Couldn't open file: {}".format(line))
@ -160,8 +162,11 @@ def do_includes(fi):
print("Maximal include depth reached: {}".format(line))
leave(1)
source.write("$file: {}:\n".format(inc.replace(' ', '')))
source.write("$file: {}:\n".format(pcurfile.replace(' ', '')))
do_includes(new_fi)
pcurfile = old_curf
source.write("$file: {}:\n".format(pcurfile.replace(' ', '')))
else:
source.write("{}\n".format(line))
@ -177,6 +182,7 @@ def parse():
global plastlabel
source.seek(0)
pcurfile = sys.argv[1]
for ln_no, line in enumerate(source):
line = line.rstrip()
@ -563,8 +569,8 @@ def parse_instr(line):
# Offsets
#
if '+' in word:
reg1 = "inv"
reg2 = "inv"
reg1 = "rzx"
reg2 = "rzx"
imm1 = '1'
imm2 = '0'

View File

@ -1,4 +1,4 @@
inv
rzx zero
fc1
cr0 c0
cr1 c1

View File

@ -10,7 +10,7 @@ FILE_LOADP := 0x141000 ; 4KB above stack
start:
mov rsp, 0x140000
xor rbp, rbp
mov rbp, zero
cls
cld

View File

@ -11,17 +11,15 @@ doprnt:
mov q[rbp-8], rbx
mov q[rbp-16], nx0
mov q[rbp-24], nx1
mov q[rbp-32], nx2
mov q[rbp-40], rdi
mov q[rbp-48], rsi
mov q[rbp-56], nx3
mov q[rbp-32], rdi
mov q[rbp-40], rsi
mov q[rbp-48], nx3
mov rbx, ax2 ; fmt
mov nx3, ax0 ; putc
mov nx0, ax1 ; n
xor nx1, nx1 ; return value
xor nx2, nx2 ; index in va_list
mov rsi, ax3 ; ap
mov rsi, ax3 ; va_list
mov nx1, zero ; return value
.main_loop:
; find '%' or null-terminator
@ -46,7 +44,7 @@ doprnt:
; we did find a modifier / '%'
mov rax, b[rbx+1]
add rbx, 2
add rbx, rbx, 2
b.z rax, 's', .modf_s
b.z rax, 'c', .modf_c
@ -62,24 +60,24 @@ doprnt:
.modf_s:
; get string address
mov rdi, q[rsi+nx2*8]
inc nx2
mov rdi, q[rsi]
add rsi, rsi, 8
test rdi, rdi
j.z .nullstring
cmp rdi, zero
jmp.z .nullstring
.print_string:
mov ax0, b[rdi]
test ax0, ax0
j.z .main_loop
cmp ax0, zero
jmp.z .main_loop
inc rdi
call .doput
jmp .print_string
.modf_c:
mov ax0, q[rsi+nx2*8]
inc nx2
mov ax0, q[rsi]
add rsi, rsi, 8
call .doput
jmp .main_loop
@ -108,21 +106,21 @@ doprnt:
.print_number:
; allocate itoa conversion buffer
sub rsp, 80
sub rsp, rsp, 80
mov rdi, rsp
; assume modifier already set up ax2
mov ax0, rsp
mov ax1, q[rsi+nx2*8]
mov ax1, q[rsi]
call itoa
inc nx2
add rsi, rsi, 8
.print_itoa_buf:
mov ax0, b[rdi]
test ax0, ax0
add.z rsp, 80
j.z .main_loop
cmp ax0, zero
add.z rsp, rsp, 80
jmp.z .main_loop
inc rdi
call .doput
@ -170,10 +168,9 @@ doprnt:
mov rbx, q[rbp-8]
mov nx0, q[rbp-16]
mov nx1, q[rbp-24]
mov nx2, q[rbp-32]
mov rdi, q[rbp-40]
mov rsi, q[rbp-48]
mov nx3, q[rbp-56]
mov rdi, q[rbp-32]
mov rsi, q[rbp-40]
mov nx3, q[rbp-48]
leave
ret
;
@ -187,7 +184,7 @@ doprnt:
; we follow the C convention that sprintf()-like functions
; should return the number of characters that would have
; been printed/written if 'n' were big enough
test nx0, nx0
cmp nx0, zero
ret.z
; if n>0, decrement n and print
@ -195,8 +192,8 @@ doprnt:
call nx3
; did putc fail?
test rax, rax
xor.nz nx0, nx0 ; yes, so artificially set n=0
cmp rax, zero
mov.nz nx0, zero ; yes, so artificially set n=0
ret

View File

@ -12,7 +12,7 @@ itoa:
; void utoa(char *buf, int num, int base)
;
utoa:
xor ax3, ax3
mov ax3, zero
jmp ltostr
;
@ -20,20 +20,19 @@ utoa:
;
ltostr:
mov rax, ax0
xor r11, r11
mov r11, zero
; make sure base is in [2, 32]
b.b ax2, 2, .bad
b.a ax2, 36, .bad
; deal with zero
b.z ax1, 0, .zero
b.z ax1, zero, .is_zero
; deal with base 10 signedness
test ax3, ax3
cmp.nz ax2, 10 ; base 10
j.nz .conv
b.z ax3, zero, .conv
b.nz ax2, 10, .conv ; base 10
sgn r11, ax1 ; extract ax1 sign
@ -42,17 +41,17 @@ ltostr:
; main loop
.conv:
b.z ax1, 0, .fini
b.z ax1, zero, .fini
rem r10, ax1, ax2 ; ax1 % base
b.a r10, 9, .nondec ; r10 > 9 ?
add r10, '0'
add r10, r10, '0'
jmp .next
.nondec:
add r10, 55 ; 'A' - 10
add r10, r10, 55 ; 'A' - 10
.next:
mov b[ax0], r10
@ -67,7 +66,7 @@ ltostr:
mov.z b[ax0], '-'
inc.z ax0
mov b[ax0], 0
mov b[ax0], zero
mov ax0, rax
call strrev2
@ -82,7 +81,7 @@ ltostr:
mov b[ax0], 0
ret
.zero:
.is_zero:
mov b[ax0], 48 ; '0'
mov b[ax0+1], 0
ret

View File

@ -6,7 +6,7 @@
;
putc:
prn ax0
xor rax, rax
mov rax, zero
ret
;
@ -16,7 +16,7 @@ printf:
mov ax2, ax0
mov ax0, putc
mov ax1, STRLEN_MAX
lea ax3, b[rsp+8]
add ax3, rsp, 8
jmp doprnt
;
@ -25,7 +25,7 @@ printf:
nprintf:
mov ax2, ax0
mov ax0, putc
lea ax3, b[rsp+8]
add ax3, rsp, 8
jmp doprnt
;
@ -33,7 +33,7 @@ nprintf:
;
print:
mov rcx, STRLEN_MAX
b.z b[ax0], 0, .1
b.z b[ax0], zero, .1
prns.rep.nz ax0
.1:
ret
@ -43,7 +43,7 @@ print:
;
print_n:
mov rcx, ax1
b.z b[ax0], 0, .1
b.z b[ax0], zero, .1
prns.rep.nz ax0
.1:
ret

View File

@ -18,7 +18,7 @@ strtol:
; rdx = pointer to first invalid byte
;
strtoul:
xor ax2, ax2
mov ax2, zero
jmp strtoq
;
@ -27,7 +27,7 @@ strtoul:
; guesses base when 'base'=0
;
strtoq:
xor rax, rax
mov rax, zero
mov rdx, ax0
; make sure base is in [2, 32]
@ -35,7 +35,7 @@ strtoq:
b.a ax1, 36, .bad
; empty string?
b.z b[rdx], 0, .done
b.z b[rdx], zero, .done
.skip_spc:
cmp b[rdx], ' '
@ -47,15 +47,15 @@ strtoq:
inc.z rdx
; signed?
test ax2, ax2
xor.z r10, r10
cmp ax2, zero
mov.z r10, zero
jmp.z .unsigned
; parse '-'
cmp b[rdx], '-'
inc.z rdx
mov.z r10, 1
sub.nz r10, r10
mov.nz r10, zero
.unsigned:
; base 0
@ -68,7 +68,7 @@ strtoq:
movzx rcx, b[rdx]
; "0x"/"0b" prefix
b.z rcx, 0, .done ; "0"
b.z rcx, zero, .done ; "0"
b.z rcx, 'x', .parsed_0x
b.z rcx, 'b', .parsed_0b
@ -119,18 +119,18 @@ strtoq:
cmp r12, '0'
jmp.b .done
cmp.ae r12, '9'
sub.be r12, '0'
sub.be r12, r12, '0'
jmp.be .next
cmp r12, 'A'
cmp.ae r12, 'Z'
sub.be r12, 55 ; 'A' - 10
sub.be r12, r12, 55 ; 'A' - 10
jmp.be .next
cmp r12, 'a'
jmp.b .next
cmp.ae r12, 'z'
sub.be r12, 87 ; 'a' - 10
sub.be r12, r12, 87 ; 'a' - 10
jmp.be .next
.next:
@ -138,12 +138,12 @@ strtoq:
b.ae r12, ax1, .done
mul rax, rax, ax1
add rax, r12
add rax, rax, r12
jmp .main_loop
.done:
; negative?
test r10, r10
cmp r10, zero
ret.z
; yes

View File

@ -25,15 +25,15 @@ DaysInYear:
; divisible by 4?
rem rcx, ax0, 4
b.nz rcx, 0, .end
b.nz rcx, zero, .end
; divisible by 100?
rem rcx, ax0, 100
b.nz rcx, 0, .leap
b.nz rcx, zero, .leap
; divisible by 400?
rem rcx, ax0, 400
b.nz rcx, 0, .end
b.nz rcx, zero, .end
.leap:
inc rax

View File

@ -18,8 +18,8 @@ strchr:
mov rcx, STRLEN_MAX
scasb.rep.nz ax0, ax1
cmp b[ax0], 0
xor.z rax, rax
cmp b[ax0], zero
mov.z rax, zero
ret.z
mov rax, ax0

View File

@ -18,13 +18,14 @@ strcmp:
;
strncmp:
mov rcx, ax2
mov.cxz rax, 0
mov.cxz rax, zero
ret.cxz
cmpzsb.rep.z ax0, ax1
mov rax, b[ax0-1]
sub rax, b[ax1-1]
mov rcx, b[ax1-1]
sub rax, rax, rcx
ret

View File

@ -27,11 +27,11 @@ strnzcpy:
ret.cxz
dec rcx
j.cxz .1
jmp.cxz .1
movsb.rep.nz ax0, ax1
.1:
mov b[ax0], 0
mov b[ax0], zero
ret

View File

@ -6,7 +6,7 @@
;
strnlen:
mov rcx, ax1
scasb.rep.nz ax0, 0
scasb.rep.nz ax0, zero
sub rax, ax1, rcx
ret

View File

@ -7,8 +7,8 @@
; buf and src must NOT overlap
;
strrev:
cmp b[ax1], 0
mov.z b[ax0], 0
cmp b[ax1], zero
mov.z b[ax0], zero
ret.z
; save str's location
@ -17,7 +17,7 @@ strrev:
; go to str's end, just before
; the null terminator
mov rcx, STRLEN_MAX
scasb.rep.nz ax1, 0
scasb.rep.nz ax1, zero
dec ax1
.2:
@ -27,7 +27,7 @@ strrev:
mov b[ax0], rax
cmp ax1, r10
mov.z b[ax0+1], 0
mov.z b[ax0+1], zero
ret.z
inc ax0
@ -41,7 +41,7 @@ strrev:
; Inverses str
;
strrev2:
cmp b[ax0], 0
cmp b[ax0], zero
ret.z
mov ax1, ax0
@ -49,7 +49,7 @@ strrev2:
; go to str's end, just before
; the null terminator
mov rcx, STRLEN_MAX
scasb.rep.nz ax1, 0
scasb.rep.nz ax1, zero
dec ax1
; increase ax0 while decreasing ax1, performing exchanges

View File

@ -24,7 +24,7 @@ CMDCOM_MAXSZ := 0x80000 ; 512KB
;
start:
mov rsp, DOSKRNL_STACK
xor rbp, rbp
mov rbp, zero
call main

View File

@ -2,10 +2,11 @@
; See the LICENSE file in the project root for more information.
TrapHandlers.prolog:
mov rbp, rsp
sub rsp, rsp, 24
mov q[rbp-8], r11
mov q[rbp-16], r12
mov q[rbp-24], r13
sub rsp, rbp, 24
mov rdx, cr2
@ -16,7 +17,7 @@ TrapHandlers.prolog:
mov nx0, cr2
mov cr2, rdx
xor rdx, rdx
mov rdx, zero
jmp rcx

View File

@ -5,7 +5,7 @@ trap0_handler:
.init:
mov rcx, .text
mov rbp, TRAP0_STACK
mov rsp, TRAP0_STACK
jmp TrapHandlers.prolog
.text:
@ -41,7 +41,7 @@ trap0_handler:
call DISK.OpenFile
; Crash on failure
cmp rax, 0
cmp rax, zero
crash.l
; Load at CMDCOM_LOADP
@ -61,23 +61,18 @@ trap0_handler:
call DISK.CloseFile
; Code address
xor ax0, ax0
mov ax0, zero
mov ax1, $rip
mov ax2, 0x100000
call RFS.StoreReg
; No flags set
mov ax1, $rfx
xor ax2, ax2
call RFS.StoreReg
; Usermode
mov ax1, $cr0
mov ax2, 3
call RFS.StoreReg
mov rcx, CMDCOM_LOADP
sub rcx, 0x100000
sub rcx, rcx, 0x100000
; Code offset
mov ax1, $cr1
@ -90,7 +85,7 @@ trap0_handler:
call RFS.StoreReg
; Return frame
mov q[rbp-16], 0
mov q[rbp-16], zero
jmp .fini
@ -100,17 +95,17 @@ trap0_handler:
; Disk API
;
.handle_FindFirst:
add ax0, nx0
add ax0, ax0, nx0
call DISK.FindFirst
jmp .fini
.handle_FindNext:
add ax0, nx0
add ax0, ax0, nx0
call DISK.FindNext
jmp .fini
.handle_OpenFile:
add ax0, nx0
add ax0, ax0, nx0
call DISK.OpenFile
jmp .fini
@ -119,7 +114,7 @@ trap0_handler:
jmp .fini
.handle_ReadFile:
add ax1, nx0
add ax1, ax0, nx0
call DISK.ReadFile
jmp .fini
@ -127,6 +122,7 @@ trap0_handler:
; Misc.
;
.handle_Shutdown:
mov nx0, zero
stop
.handle_HaltMode:
@ -135,7 +131,7 @@ trap0_handler:
xpause
scan rax
b.z rax, 0, .HLT.loop
b.z rax, zero, .HLT.loop
prn rax
jmp .HLT.loop

View File

@ -23,7 +23,7 @@ InitSyscalls:
call RFS.StoreReg
mov ax1, ax0
add ax0, 255 # TRAP no. (ax0 - 1)
add ax0, ax0, 255 # TRAP no. (ax0 - 1)
call IDT.AddHandler
ret

View File

@ -6,7 +6,7 @@ NAME_MAX := 256
builtins.dir:
push nx0
xor nx0, nx0 # no. of files found
mov nx0, zero # no. of files found
mov rcx, STRLEN_MAX
mov rdx, .dirmsg
@ -75,7 +75,7 @@ builtins.dir:
.print_ext.2:
; did we print at least 4 bytes?
j.cxz .print_bytes ; yes, carry on
jmp.cxz .print_bytes ; yes, carry on
prn.rep ' '
@ -86,13 +86,13 @@ builtins.dir:
prn ' '
shr rax, rdx, 10
and rdx, 1023
and rdx, rdx, 1023
mov ax0, .bytesstr
push rdx
push rax
call printf
add rsp, 16
add rsp, rsp, 16
.bytesstr = "%d kilobytes + %d bytes"
@ -105,7 +105,7 @@ builtins.dir:
mov ax0, .endstr1
push nx0
call printf
add rsp, 8
add rsp, rsp, 8
mov rcx, STRLEN_MAX
mov rdx, .endstr2

View File

@ -23,9 +23,9 @@ main:
stosb.rep rdx, 0
; iterator through argbuf
xor rcx, rcx
mov rcx, zero
mov q[argv1pos], 0
mov q[argv1pos], zero
.input_loop:
pause
@ -34,18 +34,18 @@ main:
; Fill .buf with user input
scan rax
b.z rax, 0, .input_loop
b.z rax, zero, .input_loop
; backspace character?
b.nz rax, 8, .handle_input
; anything to delete?
b.z rcx, 0, .input_loop
b.z rcx, zero, .input_loop
; delete it
dec rcx
add rdx, rcx, argbuf
mov b[rdx], 0
mov b[rdx], zero
; update screen
cmp b[stdin_echoing], 1
@ -73,7 +73,7 @@ main:
.extract_argv0:
; did we read anything at all?
; if not, just go back to waiting input
b.z rcx, 0, .print_prompt
b.z rcx, zero, .print_prompt
; find first whitespace or null-terminator
mov rcx, argbuf.size
@ -82,12 +82,12 @@ main:
; argv1 exists? if so, save its position
mov r11, rdx
b.z b[r11], 0, .no_argv1
b.z b[r11], zero, .no_argv1
inc r11
.next_space:
mov r10, b[r11]
b.z r10, 0, .no_argv1
b.z r10, zero, .no_argv1
; skip spaces
cmp r10, ' '
@ -188,7 +188,7 @@ main:
mov ax0, .datefmt
call printf
add rsp, 5*8
add rsp, rsp, 5*8
jmp .print_prompt
@ -216,10 +216,10 @@ main:
.handle_PRINT:
mov rax, Sys.OpenFile
mov ax0, q[argv1pos]
b.z ax0, 0, .need_params
b.z ax0, zero, .need_params
trap 0
b.l rax, 0, .file_not_found
b.l rax, zero, .file_not_found
mov ax0, rax
mov ax1, FILE_LOADP
@ -233,8 +233,8 @@ main:
mov rax, Sys.CloseFile
trap 0
b.l rax, 0, .couldnt_read
b.z rax, 0, .empty_file
b.l rax, zero, .couldnt_read
b.z rax, zero, .empty_file
mov rdx, FILE_LOADP
prns.rep rdx
@ -250,7 +250,7 @@ main:
push b[rax+2]
mov ax0, .timefmt
call printf
add rsp, 3*8
add rsp, rsp, 3*8
jmp .print_prompt
@ -318,7 +318,7 @@ main:
push q[argv1pos]
push argv0
call printf
add rsp, 16
add rsp, rsp, 16
jmp .print_prompt
@ -329,7 +329,7 @@ main:
push q[argv1pos]
push argv0
call printf
add rsp, 16
add rsp, rsp, 16
jmp .print_prompt
@ -340,7 +340,7 @@ main:
push q[argv1pos]
push argv0
call printf
add rsp, 16
add rsp, rsp, 16
jmp .print_prompt

View File

@ -173,8 +173,9 @@ long cpudev_loadreg(ctx_t *ctx, dev_t *dev)
{
CHK_FRAME(ax0);
if ((ushort)ax1 >= NREGS)
_except(ctx, E_UDF, "cpudev: register index out of range: #%u", ax1);
if ((ushort)ax1 >= NREGS || ax1 == RZX)
_except(ctx, E_UDF,
"cpudev: register invalid or index out of range: #%u", ax1);
R(ax1) = rfs[ax0][ax1];

View File

@ -5,16 +5,6 @@
# Logical instructions #
#---------------------------------------------------------------------------#
#
# TEST Comparison instruction
#
# $1 AND $2
#
# Clears OF and CF
# Sets ZF and SF according to the result
#
test r ri
#
# Bitwise NOT operation
#
@ -31,15 +21,10 @@ not r r
#
# Preserves all flags
#
or r ri
or r r ri
or m ri
or m r ri
# $dest = $src1 OR NOT($src2)
orn r ri
orn r r ri
# $dest = NOT($src1 OR $src2)
nor r r ri
@ -50,14 +35,9 @@ nor r r ri
#
# Preserves all flags
#
and r rim
and r r rim
and m ri
and m r ri
and r r ri
# $dest = $src1 AND NOT($src2)
andn r r ri
# $dest = NOT($src1 AND $src2)
nand r r ri
@ -68,14 +48,9 @@ nand r r ri
#
# Preserves all flags
#
xor r rim
xor r r rim
xor m ri
xor m r ri
xor r r ri
# $dest = $src1 XOR NOT($src2)
xorn r r ri
# $dest = NOT($src1 XOR $src2)
xnor r r ri
@ -150,7 +125,7 @@ neg r r
#
# Preserves all flags
#
inc rm
inc r
#
# Arithmetical DEC operation
@ -159,7 +134,7 @@ inc rm
#
# Preserves all flags
#
dec rm
dec r
#
# Arithmetical ADD operation
@ -170,10 +145,7 @@ dec rm
# Sets OF is signed integer overflow occur, clears it otherwise
# Sets ZF and SF according to the result
#
add r rim
add r r ri
add m ri
addf r r ri
addo r r ri
@ -198,15 +170,9 @@ xadd m r
# Sets OF is signed integer overflow occur, clears it otherwise
# Sets ZF and SF according to the result
#
sub r rim
sub r r ri
sub r i r
sub m ri
subf r r ri
subf r i r
subo r r ri
subo r i r
#
# Arithmetical ADD/SUB operation, with carry/overflow

View File

@ -10,7 +10,6 @@
#
# RIP = $1
#
j ri
jmp ri
#
@ -145,27 +144,3 @@ movzx r m
#
xchg r rm
#
# Compare-and-exchange (CMPXCHG) instruction
#
# IF ($1 == RAX) THEN
# $1 = $2
# ZF = 1
# ELSE
# RAX = $1
# ZF = 0
# FI
#
# Preserves CF, OF and SF
#
cmpxchg rm r
#
# 3-operand rotation (ROTd)
#
# $3 -> $2 -> $1 -> $3 (ROTL)
# $1 -> $2 -> $3 -> $1 (ROTR)
#
rotr rm r r
rotl rm r r

View File

@ -9,11 +9,9 @@
//----------------------------------------------------------------------------//
IMPL_START_2(not) { v1 = ~v2; } IMPL_OUT;
IMPL_START_2(test) { rfx &= ~(CF|OF); SET_ZSF(v1 & v2); } IMPL_END;
IMPL_START_2(or) { ALU_GET_SRCS(); v1 = src1 | src2; } IMPL_OUT;
IMPL_START_2(and) { ALU_GET_SRCS(); v1 = src1 & src2; } IMPL_OUT;
IMPL_START_2(xor) { ALU_GET_SRCS(); v1 = src1 ^ src2; } IMPL_OUT;
IMPL_START_3(or) { v1 = v2 | v3; } IMPL_OUT;
IMPL_START_3(and) { v1 = v2 & v3; } IMPL_OUT;
IMPL_START_3(xor) { v1 = v2 ^ v3; } IMPL_OUT;
//----------------------------------------------------------------------------//
@ -40,7 +38,7 @@ IMPL_START_1(dec) { v1--; } IMPL_OUT;
//----------------------------------------------------------------------------//
IMPL_START_2(add) { ALU_GET_SRCS(); v1 = src1 + src2; } IMPL_OUT;
IMPL_START_3(add) { v1 = v2 + v3; } IMPL_OUT;
IMPL_START_2(xadd) { ulong tmp = v1; v1 += v2; v2 = tmp; } IMPL_OUT_2;
IMPL_START_3(addf) { COMPARE(v2, ~v3+1); v1 = v2 + v3; } IMPL_OUT;
IMPL_START_3(addo) { COMPARE(v2, ~v3+1); v1 = v2 + v3; INTO(); } IMPL_OUT;
@ -48,16 +46,16 @@ IMPL_START_3(addo) { COMPARE(v2, ~v3+1); v1 = v2 + v3; INTO(); } IMPL_OUT;
//----------------------------------------------------------------------------//
IMPL_START_2(cmp) { COMPARE(v1, v2); } IMPL_END;
IMPL_START_2(sub) { ALU_GET_SRCS(); v1 = src1 - src2; } IMPL_OUT;
IMPL_START_3(sub) { v1 = v2 - v3; } IMPL_OUT;
IMPL_START_3(subf){ COMPARE(v2, v3); v1 = v2 - v3; } IMPL_OUT;
IMPL_START_3(subo){ COMPARE(v2, v3); v1 = v2 - v3; INTO(); } IMPL_OUT;
//----------------------------------------------------------------------------//
IMPL_START_3(adcx) { v1 = v2 + v3 + !!(rfx&CF); } IMPL_OUT;
IMPL_START_3(adox) { v1 = v2 + v3 + !!(rfx&OF); } IMPL_OUT;
IMPL_START_3(sbbx) { v1 = v2 - v3 - !!(rfx&CF); } IMPL_OUT;
IMPL_START_3(sbox) { v1 = v2 - v3 - !!(rfx&OF); } IMPL_OUT;
IMPL_START_3(adcx) { v1 = v2 + v3 + !!(R(RFX)&CF); } IMPL_OUT;
IMPL_START_3(adox) { v1 = v2 + v3 + !!(R(RFX)&OF); } IMPL_OUT;
IMPL_START_3(sbbx) { v1 = v2 - v3 - !!(R(RFX)&CF); } IMPL_OUT;
IMPL_START_3(sbox) { v1 = v2 - v3 - !!(R(RFX)&OF); } IMPL_OUT;
//----------------------------------------------------------------------------//

View File

@ -35,9 +35,10 @@ uint i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, acc_t *p3, \
IMPL_START_0(name) \
DECV(v1, p1);
#define IMPL_START_1_NOIN(name) \
#define IMPL_START_X_NOIN(name) \
IMPL_START_0(name) \
ulong v1;
ulong v1, v2, v3; \
(void)v1; (void)v2; (void)v3;
#define IMPL_START_2(name) \
IMPL_START_1(name) \
@ -82,6 +83,9 @@ IMPL_START_2(name) \
//----------------------------------------------------------------------------//
#define INTO() \
if (R(RFX) & OF) _except(ctx, E_OVF, "Overflow");
#define PARITY(v) __builtin_parity(v)
#define SET_ZF(v) \
@ -119,21 +123,6 @@ IMPL_START_2(name) \
//----------------------------------------------------------------------------//
#define INTO() \
if (R(RFX) & OF) _except(ctx, E_OVF, "Overflow");
#define ALU_GET_SRCS() \
ulong src1, src2; \
if (p3) { \
src1 = v2; \
GETV(src2, p3); \
} else { \
src1 = v1; \
src2 = v2; \
}
//----------------------------------------------------------------------------//
#define CHK_SUPERV() \
do { \
if ((R(CR0) & UF) > 0) { \

View File

@ -19,12 +19,14 @@ IMPL_START_0(xpause) { CHK_SUPERV(); usleep(25000); } IMPL_END;
IMPL_START_0(break)
{
#ifndef NDEBUG
trace("\nExecuting BREAK INSTR\n");
dumpregs(ctx);
do_hlt(ctx);
trace("Resuming execution\n");
#endif
}
IMPL_END;
@ -47,9 +49,9 @@ IMPL_END;
//----------------------------------------------------------------------------//
IMPL_START_1(time) { v1 = time(NULL); } IMPL_OUT;
IMPL_START_X_NOIN(time) { v1 = time(NULL); } IMPL_OUT;
IMPL_START_3(ytime)
IMPL_START_X_NOIN(ytime)
{
time_t t = time(NULL);
struct tm *tm = localtime(&t);
@ -129,8 +131,10 @@ IMPL_OUT;
//----------------------------------------------------------------------------//
IMPL_START_1(prn)
IMPL_START_0(prn)
{
DECVZX(v1, p1);
// Magic value? :)
if (__builtin_expect(v1 == 0xC15000AF, 0))
console_clear(ctx);
@ -140,7 +144,8 @@ IMPL_START_1(prn)
if (p1->mlen > 1) {
trace("prn warning: large access size\n");
}
console_putc(ctx, (char)v1);
if (v1 > 0)
console_putc(ctx, (char)v1);
}
}
IMPL_END
@ -151,11 +156,11 @@ IMPL_START_0(prns)
COMPARE(ch, 0);
if ((rfx & ZF) == 0)
if ((R(RFX) & ZF) == 0)
{
console_putc(ctx, ch);
if (rfx & DF)
if (R(RFX) & DF)
R(p1->reg)--;
else
R(p1->reg)++;
@ -163,7 +168,7 @@ IMPL_START_0(prns)
}
IMPL_END
IMPL_START_1(scan)
IMPL_START_X_NOIN(scan)
{
v1 = console_scankeybuf(ctx);
}

View File

@ -5,7 +5,6 @@
//----------------------------------------------------------------------------//
IMPL_START_1(j) { R(RIP) = v1; } IMPL_END;
IMPL_START_1(jmp) { R(RIP) = v1; } IMPL_END;
IMPL_START_1(loop) {
if (R(RCX) > 0) {
@ -25,23 +24,16 @@ IMPL_END;
//----------------------------------------------------------------------------//
IMPL_START_1_NOIN(lea) { v1 = p2->addr; } IMPL_OUT;
IMPL_START_X_NOIN(lea) { v1 = p2->addr; } IMPL_OUT;
IMPL_START_2_ONLY(mov) { v1 = v2; } IMPL_OUT;
IMPL_START_2_ONLY(movsxb) { v1 = (ulong)(long)(char)(v2 & 0xFF); }IMPL_OUT;
IMPL_START_2_ONLY(movsxw) { v1 = (ulong)(long)(short)(v2 & 0xFFFF); }IMPL_OUT;
IMPL_START_2_ONLY(movsxl) { v1 = (ulong)(long)(int)(v2 & 0xFFFFFFFF); }IMPL_OUT;
IMPL_START_1_NOIN(movzx) { DECVZX(v2, p2); v1 = v2; } IMPL_OUT;
IMPL_START_X_NOIN(movzx) { DECVZX(v2, p2); v1 = v2; } IMPL_OUT;
IMPL_START_2(xchg) { ulong t = v1; v1 = v2; v2 = t; } IMPL_OUT_2;
IMPL_START_3(rotl) { ulong tmp = v1; v1 = v2; v2 = v3; v3 = tmp; } IMPL_OUT_3;
IMPL_START_3(rotr) { ulong tmp = v3; v3 = v2; v2 = v1; v1 = tmp; } IMPL_OUT_3;
IMPL_START_2(cmpxchg) {
if (R(RAX) == v1) { R(RFX) |= ZF; v1 = v2; }
else { R(RFX) &= ~ZF; R(RAX) = v1; }
} IMPL_OUT;
//----------------------------------------------------------------------------//
@ -69,10 +61,10 @@ IMPL_START_0(ret) {
R(RIP) = readmem(ctx, R(RSP), 8); R(RSP) += 8;
} IMPL_END;
IMPL_START_0(enter) {
IMPL_START_1(enter) {
writemem(ctx, R(RBP), R(RSP) - 8, 8);
R(RBP) = R(RSP) - 8;
R(RSP) -= (p1->val + 1) * 8;
R(RSP) -= (v1 + 1) * 8;
} IMPL_END;
IMPL_START_0(leave) {

View File

@ -6,7 +6,7 @@
//----------------------------------------------------------------------------//
#define STR_MOVE(reg, len) \
if (!(rfx & DF)) R(reg) += len; \
if (!(R(RFX) & DF)) R(reg) += len; \
else R(reg) -= len;
//----------------------------------------------------------------------------//

View File

@ -45,7 +45,8 @@ IMPL_START_1(trap) {
IMPL_START_0(into) { INTO(); } IMPL_END;
IMPL_START_0(iret) {
trace("\nReturning from exception #%ld\n\n", R(R11));
if (ctx->dumpsw)
trace("\nReturning from exception #%ld\n\n", R(R11));
// should do more checks
R(RIP) = R(R13);
@ -63,21 +64,11 @@ dev_t *devctl_common(ctx_t *ctx, ulong v1, ulong v2)
{
dev_t *dev = devget(ctx, v1);
if (!dev)
rax = -2;
else if (dev->state == DEVPWOF)
rax = -3;
else if (dev->state == DEVFERR)
rax = -4;
else if (dev->state == DEVPLUG)
rax = -5;
else
return dev;
if (!dev) rax = -2;
else if (dev->state == DEVPWOF) rax = -3;
else if (dev->state == DEVFERR) rax = -4;
else if (dev->state == DEVPLUG) rax = -5;
else return dev;
return NULL;
}
@ -91,35 +82,13 @@ IMPL_START_2(devctl)
return 0;
switch (v2) {
case 0:
writestr(ctx, ax0, DEVLEN, dev->type);
break;
case 1:
writestr(ctx, ax0, DEVLEN, dev->name);
break;
case 2:
writestr(ctx, ax0, DEVLEN, dev->modl);
break;
case 3:
writestr(ctx, ax0, DEVLEN, dev->vend);
break;
case 4:
rax = dev->major;
rdx = dev->minor;
break;
case 5:
rax = dev->feats;
rdx = dev->revis;
break;
default:
rax = -6;
break;
case 0: writestr(ctx, ax0, DEVLEN, dev->type); break;
case 1: writestr(ctx, ax0, DEVLEN, dev->name); break;
case 2: writestr(ctx, ax0, DEVLEN, dev->modl); break;
case 3: writestr(ctx, ax0, DEVLEN, dev->vend); break;
case 4: rax = dev->major; rdx = dev->minor; break;
case 5: rax = dev->feats; rdx = dev->revis; break;
default: rax = -6; break;
}
}
IMPL_END;
@ -131,18 +100,12 @@ IMPL_START_2(iocall)
long rc;
dev_t *dev = devctl_common(ctx, v1, v2);
if (dev == NULL)
return 0;
if (v2 >= DEVSLOTS)
rax = -6;
else if (dev->fslots[v2] == NULL)
rax = -6;
if (dev == NULL) return 0;
else if (v2 >= DEVSLOTS || dev->fslots[v2] == NULL) rax = -6;
else {
rc = dev->fslots[v2](ctx, dev);
if (rc < 0) rax = rc;
if (rc < 0) { rax = rc; rdx = 0; }
}
}
IMPL_END;

View File

@ -55,8 +55,8 @@
match-empty-string-at-end = "TRUE">
<!-- KVISC -->
<keyword>(inv|flg|[re]pc)</keyword>
<keyword>[re][abcdfg]x</keyword>
<keyword>(inv|flg|zero|[re]pc)</keyword>
<keyword>[re][abcdfgz]x</keyword>
<keyword>[re][sd]i</keyword>
<keyword>[re][sbi]p</keyword>
<keyword>[a-z]x?[0-9]+[bwdlq]?</keyword>

View File

@ -30,21 +30,13 @@ static void check_param_type(ctx_t *ctx, instr_t *in,
//
// Verify that access to a certain register is legal
//
static void checkreg(ctx_t *ctx, uint reg, bool inv_is_ok)
static void checkreg(ctx_t *ctx, uint reg)
{
if (reg >= NREGS)
_except(ctx, E_ILL, "Inexistent register: %u", reg);
if (reg == INV)
{
if (!inv_is_ok)
_except(ctx, E_ILL, "INV dereference");
else
return;
}
if (ctx->r[reg].flags & RES)
//_except(ctx, E_ACC, "Reserved REG: %u", reg);
_except(ctx, E_ACC, "Reserved REG: %u", reg);
if (ctx->r[reg].flags & SYS)
if (R(CR0) & UF)
@ -64,7 +56,7 @@ void extract_param(ctx_t *ctx, acc_t *p, uchar fmt)
if (fmt == A_REG)
{
p->reg = ctx->get(ctx);
checkreg(ctx, p->reg, 0);
checkreg(ctx, p->reg);
p->val = R(p->reg);
@ -83,9 +75,7 @@ void extract_param(ctx_t *ctx, acc_t *p, uchar fmt)
assert(ACC_FMT_IS_MEM(fmt));
//
// Handle a memory access
//
mlen = fmt & AM_MLEN_MASK;
mfmt = fmt & AM_MFMT_MASK;
@ -114,8 +104,8 @@ void extract_param(ctx_t *ctx, acc_t *p, uchar fmt)
p->reg1 = temp >> 8;
p->reg2 = temp & 0xFF;
checkreg(ctx, p->reg1, 1);
checkreg(ctx, p->reg2, 1);
checkreg(ctx, p->reg1);
checkreg(ctx, p->reg2);
if (mfmt == AM_RRI)
{
@ -149,26 +139,14 @@ void extract_param(ctx_t *ctx, acc_t *p, uchar fmt)
void decode(ctx_t *ctx)
{
instr_t *in;
acc_t p1 = { 0 };
acc_t p2 = { 0 };
acc_t p3 = { 0 };
bool rep = 0;
bool lock, nomore;
ushort w1, w2;
uchar f1 = 0, f2 = 0, f3 = 0;
ushort w1, w2, rep = 0, lock, nomore;
acc_t p1 = { 0 }, p2 = { 0 }, p3 = { 0 };
rpc = R(RIP);
//
// Process the first word of the instruction
//
w1 = ctx->get(ctx);
// Extract first word flags
lock = !!(w1 & SUFF_LOCK);
nomore = !!(w1 & SUFF_NOMORE);
@ -179,22 +157,16 @@ void decode(ctx_t *ctx)
w1 &= ~(SUFF_LOCK|SUFF_NOMORE|SUFF_COND);
// Find instruction
if (w1 >= NINSTRS)
{
_except(ctx, E_ILL, "No such INSTR: 0x%hX", w1);
}
// Find instruction
in = &ctx->i[w1];
ctx->cur_in = in;
// Second word?
if (!nomore)
{
//
// Process second word
//
w2 = ctx->get(ctx);
// REP and COND
@ -206,18 +178,13 @@ void decode(ctx_t *ctx)
f1 = w2 & Fx_MASK;
}
//
// Deal with operand 1
//
// Operand 1?
if (in->prm1 == NOPRM)
{
if (f1 || f2 || f3)
{
_except(ctx, E_ILL,
"FTn (%u,%u,%u) filled for 0-param INSTR '%s'",
f1, f2, f3, in->full);
}
exec_instr(ctx, in, NULL, NULL, NULL, lock, rep);
return;
@ -226,18 +193,13 @@ void decode(ctx_t *ctx)
check_param_type(ctx, in, in->prm1, f1, 1);
extract_param(ctx, &p1, f1);
//
// Deal with operand 2
//
// Operand 2?
if (in->prm2 == NOPRM)
{
if (f2 || f3)
{
_except(ctx, E_ILL,
"FT3/FT2 (%u,%u,%u) filled for 1-param INSTR '%s'",
f1, f2, f3, in->full);
}
exec_instr(ctx, in, &p1, NULL, NULL, lock, rep);
return;
@ -246,18 +208,13 @@ void decode(ctx_t *ctx)
check_param_type(ctx, in, in->prm2, f2, 2);
extract_param(ctx, &p2, f2);
//
// Deal with operand 3
//
// Operand 1?
if (in->prm3 == NOPRM)
{
if (f3)
{
_except(ctx, E_ILL,
"FT3 (%u,%u,%u) filled for 2-param INSTR '%s'",
f1, f2, f3, in->full);
}
exec_instr(ctx, in, &p1, &p2, NULL, lock, rep);
return;

View File

@ -8,8 +8,6 @@ void die(int code)
{
dying = 1;
enable_stdin_echoing();
if (main_ctx.mp)
free(main_ctx.mp);

View File

@ -14,14 +14,6 @@ void _except(ctx_t *ctx, int _code, char *fmt, ...)
ulong orig_frame;
trace("\nException %u - ", code);
va_start(ap, fmt);
vlog(fmt, ap);
va_end(ap);
trace("\n\n");
//
// Interrupted earlier?
//
@ -29,7 +21,6 @@ void _except(ctx_t *ctx, int _code, char *fmt, ...)
if (dying)
{
logerr("Exception thrown while dying=1\n");
enable_stdin_echoing();
exit(-12);
}
@ -82,6 +73,17 @@ void _except(ctx_t *ctx, int _code, char *fmt, ...)
// Is this a valid frame?
if (rfs[handler] != NULL)
{
if (ctx->dumpsw)
{
trace("\nException %u - ", code);
va_start(ap, fmt);
vlog(fmt, ap);
va_end(ap);
trace("\n\n");
}
orig_frame = rfs_current_idx;
ctx->rf = rfs[handler];
@ -101,11 +103,18 @@ void _except(ctx_t *ctx, int _code, char *fmt, ...)
}
actually_die:
logerr("\nException %u - ", code);
va_start(ap, fmt);
vlog(fmt, ap);
va_end(ap);
logerr("\n\n");
dying = 1;
dumpregs(ctx);
trace("\n");
logerr("\n");
die(code);
}

View File

@ -4,6 +4,8 @@
#include <pc/arch.h>
#include <in/arch_i.h>
#define rfx R(RFX)
bool eval_cond(ctx_t *ctx, uint cond)
{
bool neg = cond & (1 << 4);
@ -42,6 +44,16 @@ bool eval_cond(ctx_t *ctx, uint cond)
return neg ? !ok : !!ok;
}
#define OUTPUT(p, r) { \
if (p->type == A_REG) \
R(p->reg) = r; \
else if (p1->type == A_IMM64) \
_except(ctx, E_ACC, "Trying to output to an IMM64"); \
else { \
assert(ACC_IS_MEM(p)); \
writemem(ctx, r, p->addr, p->mlen); \
} }
//
// Executes an instruction
//
@ -75,25 +87,16 @@ void exec_instr(ctx_t *ctx,
dump_instr(ctx, in, p1, p2, p3, lock, rep);
do_rep:
assert(R(RZX) == 0);
out = in->func(ctx, p1, p2, p3, &r1, &r2, &r3);
#define OUTPUT(p, r) { \
if (p->type == A_REG) \
R(p->reg) = r; \
else if (p1->type == A_IMM64) \
_except(ctx, E_ACC, "Trying to output to an IMM64"); \
else { \
assert(ACC_IS_MEM(p)); \
writemem(ctx, r, p->addr, p->mlen); \
} }
if (out)
{
OUTPUT(p1, r1);
if (out >= 2) OUTPUT(p2, r2);
if (out >= 3) OUTPUT(p3, r3);
R(RZX) = 0;
}
if (rep)

View File

@ -25,6 +25,6 @@ void logerr(const char *fmt, ...)
void vlog(const char *fmt, va_list ap)
{
vfprintf(stdout, fmt, ap);
vfprintf(stderr, fmt, ap);
}

View File

@ -53,7 +53,8 @@ jmp_buf exc_jmp_buf;
//
void main_loop(void)
{
trace("\n\n\n");
if (main_ctx.dumpsw)
trace("\n\n\n");
setjmp(exc_jmp_buf);
@ -77,7 +78,7 @@ int main(int argc, char **argv)
main_ctx.r = arch_r;
main_ctx.i = arch_i;
#ifndef NDEBUG
#if 0 && defined(NDEBUG)
main_ctx.dumpsw = 1;
#endif
@ -166,7 +167,6 @@ int main(int argc, char **argv)
// To be moved to some screen device
console_init(&main_ctx);
disable_stdin_echoing();
main_loop();
}

View File

@ -5,7 +5,7 @@
reg_t arch_r[] =
{
{ "inv", RES }, { "fc1", RES }, { "cr0", SYS }, { "cr1", SYS },
{ "zero", GPR }, { "fc1", RES }, { "cr0", SYS }, { "cr1", SYS },
{ "cr2", SYS }, { "cr3", SYS }, { "cr4", SYS }, { "trp", GPR },
{ "rax", GPR }, { "rbx", GPR }, { "rcx", GPR }, { "rdx", GPR },
@ -21,34 +21,36 @@ reg_t arch_r[] =
static_assert(sizeof(arch_r)/sizeof(reg_t) == NREGS, "");
#define TRACE logerr
void dumpregs(ctx_t *ctx)
{
trace("Current RFRAME index: #%lu", rfs_current_idx);
TRACE("Current RFRAME index: #%lu", rfs_current_idx);
trace("\n\nEnviron:");
trace("\nrpc=0x%-16lX rip=0x%-16lX rfx=0x%-16lX", rpc, R(RIP), R(RFX));
trace("\nrsp=0x%-16lX rbp=0x%-16lX trp=0x%-16lX", R(RSP), R(RBP), R(TRP));
TRACE("\n\nEnviron:");
TRACE("\nrpc=0x%-16lX rip=0x%-16lX rfx=0x%-16lX", rpc, R(RIP), R(RFX));
TRACE("\nrsp=0x%-16lX rbp=0x%-16lX trp=0x%-16lX", R(RSP), R(RBP), R(TRP));
trace("\n\nControl:");
trace("\ncr0=0x%-16lX cr1=0x%-16lX cr2=0x%-16lX", R(CR0), R(CR1), R(CR2));
trace("\nfc0=0d%-16lu fc1=0d%-16lu fc2=0d%-16lu", fc0, fc1, fc2);
TRACE("\n\nControl:");
TRACE("\ncr0=0x%-16lX cr1=0x%-16lX cr2=0x%-16lX", R(CR0), R(CR1), R(CR2));
TRACE("\nfc0=0d%-16lu fc1=0d%-16lu fc2=0d%-16lu", fc0, fc1, fc2);
trace("\n\nArgument:");
trace("\nax0=0x%-16lX ax1=0x%-16lX ax2=0x%-16lX", R(AX0), R(AX1), R(AX2));
trace("\nax3=0x%-16lX ax4=0x%-16lX ax5=0x%-16lX", R(AX3), R(AX4), R(AX5));
TRACE("\n\nArgument:");
TRACE("\nax0=0x%-16lX ax1=0x%-16lX ax2=0x%-16lX", R(AX0), R(AX1), R(AX2));
TRACE("\nax3=0x%-16lX ax4=0x%-16lX ax5=0x%-16lX", R(AX3), R(AX4), R(AX5));
trace("\n\nVolatile:");
trace("\nrax=0x%-16lX rcx=0x%-16lX rdx=0x%-16lX", R(RAX), R(RCX), R(RDX));
trace("\nr10=0x%-16lX r11=0x%-16lX r12=0x%-16lX", R(R10), R(R11), R(R12));
trace("\nr13=0x%-16lX r14=0x%-16lX r15=0x%-16lX", R(R13), R(R14), R(R15));
TRACE("\n\nVolatile:");
TRACE("\nrax=0x%-16lX rcx=0x%-16lX rdx=0x%-16lX", R(RAX), R(RCX), R(RDX));
TRACE("\nr10=0x%-16lX r11=0x%-16lX r12=0x%-16lX", R(R10), R(R11), R(R12));
TRACE("\nr13=0x%-16lX r14=0x%-16lX r15=0x%-16lX", R(R13), R(R14), R(R15));
trace("\n\nPersistent:");
trace("\nrbx=0x%-16lX rdi=0x%-16lX rsi=0x%-16lX", R(RBX), R(RDI), R(RSI));
trace("\nnx0=0x%-16lX nx1=0x%-16lX nx2=0x%-16lX", R(NX0), R(NX1), R(NX2));
trace("\nnx3=0x%-16lX nx4=0x%-16lX nx5=0x%-16lX", R(NX3), R(NX4), R(NX5));
TRACE("\n\nPersistent:");
TRACE("\nrbx=0x%-16lX rdi=0x%-16lX rsi=0x%-16lX", R(RBX), R(RDI), R(RSI));
TRACE("\nnx0=0x%-16lX nx1=0x%-16lX nx2=0x%-16lX", R(NX0), R(NX1), R(NX2));
TRACE("\nnx3=0x%-16lX nx4=0x%-16lX nx5=0x%-16lX", R(NX3), R(NX4), R(NX5));
trace("\n");
TRACE("\n");
assert(R(INV) == 0);
assert(R(RZX) == 0);
}

View File

@ -37,7 +37,7 @@ struct reg_t
enum
{
INV, FC1, CR0, CR1, CR2, CR3, CR4, TRP,
RZX, FC1, CR0, CR1, CR2, CR3, CR4, TRP,
RAX, RBX, RCX, RDX, RSI, RDI, RBP, RSP,
RFX, RIP, R10, R11, R12, R13, R14, R15,
AX0, AX1, AX2, AX3, AX4, AX5, AX6, AX7,
@ -51,7 +51,6 @@ enum
#define rpc ctx->cur_pc
#define fc1 R(FC1)
#define rfx R(RFX)
#define rax R(RAX)
#define rdx R(RDX)

View File

@ -1,23 +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 <termio.h>
void enable_stdin_echoing(void)
{
struct termios t;
tcgetattr(0, &t);
t.c_lflag |= ECHO;
tcsetattr(0, TCSANOW, &t);
}
void disable_stdin_echoing(void)
{
return;
struct termios t;
tcgetattr(0, &t);
t.c_lflag &= ~ECHO;
tcsetattr(0, TCSANOW, &t);
}