From 89ed8fdc0dc7a8663e458da82d11d55ff16073b5 Mon Sep 17 00:00:00 2001 From: julianb0 Date: Sat, 3 Aug 2019 17:41:44 +0200 Subject: [PATCH] vm --- as/k-as.py | 16 +++---- ka/crt/fmt/doprnt.k | 40 ++++++++-------- ka/crt/fmt/ltostr.k | 6 +-- ka/crt/fmt/strtol.k | 28 ++++++------ ka/crt/lib/time.k | 2 +- ka/crt/mem/memcpy.k | 6 +-- ka/crt/str/strcmp.k | 10 ++-- ka/crt/str/strcpy.k | 15 +++--- ka/crt/str/strrev.k | 19 ++++---- ka/sys/intr/common.k | 4 +- ka/sys/intr/trap0.k | 16 +++---- ka/sys/main.k | 2 +- ka/usr/cmd/dir.k | 26 +++++------ ka/usr/cmd/main.k | 25 +++++----- vm/in/ALU | 45 +++++++++--------- vm/in/MEM | 33 +++++++------- vm/in/MISC | 16 +++---- vm/in/STRING | 16 +++---- vm/in/SUPER | 6 +-- vm/in/alu.c | 49 ++++++++++++++------ vm/in/arch_i.py | 86 ++++------------------------------- vm/in/instrs.h | 9 ++++ vm/in/mem.c | 106 +++++++++++++++++++------------------------ vm/in/misc.c | 11 +++++ vm/in/string.c | 6 +++ vm/pc/console.c | 23 ++++++---- vm/pc/decode.c | 40 ++++++---------- vm/pc/decode.h | 7 +-- vm/pc/exec.c | 8 ++-- vm/pc/main.c | 2 +- 30 files changed, 305 insertions(+), 373 deletions(-) diff --git a/as/k-as.py b/as/k-as.py index e889bff..45c00c2 100755 --- a/as/k-as.py +++ b/as/k-as.py @@ -13,7 +13,7 @@ from collections import OrderedDict #print("k-as command line: '{}'".format(sys.argv)) -WANT_DISASM = True +WANT_DISASM = False if len(sys.argv) != 5: print("Usage: {} (source file) (memory entry point) (output file) (symbols file)" @@ -449,8 +449,6 @@ def parse_instr(line): else: params = None - fellthrough = False - size = 2 # Byte 2 (rep|lock|0|cond) @@ -486,6 +484,13 @@ def parse_instr(line): tok = params.split(',') + # 'call' special case... temporary + if instr_name == 'call': + if len(tok) == 2: + instr_name = 'xcall2' + elif len(tok) == 3: + instr_name = 'xcall3' + # # Parse operands # @@ -540,8 +545,6 @@ def parse_instr(line): print("Missing access length modifier: {}".format(line)) leave(1) - instr_name += "_m" - # cheap way of getting [reg - imm] to work word = word.replace('-', '+ -') @@ -668,7 +671,6 @@ def parse_instr(line): # immediates if is_number(word): n = int(word, base=0) - instr_name += "_i" if n < 0 or n > 0xFFFFFFFF: size += 9 @@ -695,7 +697,6 @@ def parse_instr(line): # register elif word in pregs: size += 1 - instr_name += "_r" instr_args += word continue @@ -703,7 +704,6 @@ def parse_instr(line): # ModRM + imm size += 5 - instr_name += "_i" instr_args += "%%imm8 {} ".format(fmts["imm32"]) if word[0] == '.': diff --git a/ka/crt/fmt/doprnt.k b/ka/crt/fmt/doprnt.k index b67a4f3..59e2bf6 100644 --- a/ka/crt/fmt/doprnt.k +++ b/ka/crt/fmt/doprnt.k @@ -32,10 +32,9 @@ doprnt: .print_regular: b.z r12, r13, .check_modf - mov ax0, b[r12] - call .doput + call .doput, b[r12] - add r12, r12, 1 + inc r12, 1 jmp .print_regular .check_modf: @@ -45,7 +44,7 @@ doprnt: ; we did find a modifier / '%' mov rax, b[r12+1] - add r12, r12, 2 + inc r12, 2 b.z rax, 's', .modf_s b.z rax, 'c', .modf_c @@ -62,24 +61,23 @@ doprnt: .modf_s: ; get string address mov r13, q[r14] - add r14, r14, 8 + inc r14, 8 - cmp r13, zero - jmp.z .nullstring + b.z r13, zero, .nullstring .print_string: mov ax0, b[r13] - cmp ax0, zero - jmp.z .main_loop + b.z ax0, zero, .main_loop - add r13, r13, 1 + inc r13, 1 call .doput + jmp .print_string .modf_c: - mov ax0, q[r14] - add r14, r14, 8 - call .doput + call .doput, q[r14] + inc r14, 8 + jmp .main_loop .modf_p: @@ -105,23 +103,21 @@ doprnt: .print_number: ; allocate itoa conversion buffer - sub rsp, rsp, 80 + dec rsp, 80 mov r13, rsp ; assume modifier already set up ax2 - mov ax0, rsp - mov ax1, q[r14] - call itoa - add r14, r14, 8 + call itoa, rsp, q[r14] + inc r14, 8 .print_itoa_buf: mov ax0, b[r13] cmp ax0, zero - add.z rsp, rsp, 80 + inc.z rsp, 80 jmp.z .main_loop - add r13, r13, 1 + inc r13, 1 call .doput jmp .print_itoa_buf @@ -164,7 +160,7 @@ doprnt: ; .doput: ; update print count - add r16, r16, 1 + inc r16, 1 ; if n==0, don't print ; we follow the C convention that sprintf()-like functions @@ -174,7 +170,7 @@ doprnt: ret.z ; if n>0, decrement n and print - sub r15, r15, 1 + dec r15, 1 call r17 ; did putc fail? diff --git a/ka/crt/fmt/ltostr.k b/ka/crt/fmt/ltostr.k index dff2785..0763d44 100644 --- a/ka/crt/fmt/ltostr.k +++ b/ka/crt/fmt/ltostr.k @@ -44,15 +44,15 @@ ltostr: b.a rdx, 9, .nondec ; rdx > 9 ? - add rdx, rdx, '0' + inc rdx, '0' jmp .next .nondec: - add rdx, rdx, 55 ; 'A' - 10 + inc rdx, 55 ; 'A' - 10 .next: mov b[ax0], rdx - add ax0, ax0, 1 + inc ax0, 1 div ax1, ax1, ax2 jmp .conv diff --git a/ka/crt/fmt/strtol.k b/ka/crt/fmt/strtol.k index 508502e..487bb8d 100644 --- a/ka/crt/fmt/strtol.k +++ b/ka/crt/fmt/strtol.k @@ -39,12 +39,12 @@ strtoq: .skip_spc: cmp b[rdx], ' ' - add.z rdx, rdx, 1 + inc.z rdx, 1 jmp.z .skip_spc ; skip + cmp b[rdx], '+' - add.z rdx, rdx, 1 + inc.z rdx, 1 ; signed? cmp ax2, zero @@ -53,7 +53,7 @@ strtoq: ; parse '-' cmp b[rdx], '-' - add.z rdx, rdx, 1 + inc.z rdx, 1 mov.z rsi, 1 mov.nz rsi, zero @@ -64,7 +64,7 @@ strtoq: ; base prefix? b.nz b[rdx], '0', .main_loop - add rdx, rdx, 1 + inc rdx, 1 movzx rcx, b[rdx] ; "0x"/"0b" prefix @@ -81,7 +81,7 @@ strtoq: ; if not, leave rax = 0 and *rdx = 'x' b.nz ax1, 16, .done ; else - add rdx, rdx, 1 + inc rdx, 1 jmp .main_loop .parsed_0b: @@ -89,7 +89,7 @@ strtoq: ; if not, leave rax = 0 and *rdx = 'b' b.nz ax1, 2, .done ; else - add rdx, rdx, 1 + inc rdx, 1 jmp .main_loop .base_0: @@ -98,15 +98,15 @@ strtoq: cmp b[rdx], '0' mov.nz ax1, 10 jmp.nz .main_loop - add rdx, rdx, 1 + inc rdx, 1 cmp b[rdx], 'x' - add.z rdx, rdx, 1 + inc.z rdx, 1 mov.z ax1, 16 jmp.z .main_loop cmp b[rdx], 'b' - add.z rdx, rdx, 1 + inc.z rdx, 1 mov.z ax1, 2 jmp.z .main_loop @@ -114,23 +114,23 @@ strtoq: .main_loop: movzx rcx, b[rdx] - add rdx, rdx, 1 + inc rdx, 1 cmp rcx, '0' jmp.b .done cmp.ae rcx, '9' - sub.be rcx, rcx, '0' + dec.be rcx, '0' jmp.be .next cmp rcx, 'A' cmp.ae rcx, 'Z' - sub.be rcx, rcx, 55 ; 'A' - 10 + dec.be rcx, 55 ; 'A' - 10 jmp.be .next cmp rcx, 'a' jmp.b .next cmp.ae rcx, 'z' - sub.be rcx, rcx, 87 ; 'a' - 10 + dec.be rcx, 87 ; 'a' - 10 jmp.be .next .next: @@ -138,7 +138,7 @@ strtoq: b.ae rcx, ax1, .done mul rax, rax, ax1 - add rax, rax, rcx + inc rax, rcx jmp .main_loop .done: diff --git a/ka/crt/lib/time.k b/ka/crt/lib/time.k index bed77ef..9c6ac2c 100644 --- a/ka/crt/lib/time.k +++ b/ka/crt/lib/time.k @@ -36,7 +36,7 @@ DaysInYear: jmp.cxnz .end .leap: - add rax, rax, 1 + inc rax, 1 .end: ret diff --git a/ka/crt/mem/memcpy.k b/ka/crt/mem/memcpy.k index f5e30e1..9056b37 100644 --- a/ka/crt/mem/memcpy.k +++ b/ka/crt/mem/memcpy.k @@ -10,11 +10,7 @@ memcpy: .l: sub rdx, ax2, rcx - - mov rax, b[ax1+rdx] - mov b[ax0+rdx], rax - + mov b[ax0+rdx], b[ax1+rdx] loop .l - ret diff --git a/ka/crt/str/strcmp.k b/ka/crt/str/strcmp.k index edf4eff..a148b13 100644 --- a/ka/crt/str/strcmp.k +++ b/ka/crt/str/strcmp.k @@ -22,11 +22,11 @@ strcmp: add rbx, rax, rdx jmp.bxz .r - add rcx, rcx, 1 + inc rcx, 1 jmp .l .r: - sub rax, rax, rdx + dec rax, rdx ret ; @@ -43,11 +43,11 @@ strncmp: cmp rax, rdx jmp.nz .r - add ax0, ax0, 1 - add ax1, ax1, 1 + inc ax0, 1 + inc ax1, 1 loop .l .r: - sub rax, rax, rdx + dec rax, rdx ret diff --git a/ka/crt/str/strcpy.k b/ka/crt/str/strcpy.k index 67ebcc2..d15d34f 100644 --- a/ka/crt/str/strcpy.k +++ b/ka/crt/str/strcpy.k @@ -11,8 +11,8 @@ strcpy: ret.cxz - add ax0, ax0, 1 - add ax1, ax1, 1 + inc ax0, 1 + inc ax1, 1 jmp .l @@ -24,11 +24,10 @@ strncpy: ret.cxz .l: - mov rax, b[ax1] - mov b[ax0], rax + mov b[ax0], b[ax1] - add ax0, ax0, 1 - add ax1, ax1, 1 + inc ax0, 1 + inc ax1, 1 loop .l ret @@ -46,8 +45,8 @@ strnzcpy: jmp.axz .r - add ax0, ax0, 1 - add ax1, ax1, 1 + inc ax0, 1 + inc ax1, 1 loop .l diff --git a/ka/crt/str/strrev.k b/ka/crt/str/strrev.k index 89752d3..9911319 100644 --- a/ka/crt/str/strrev.k +++ b/ka/crt/str/strrev.k @@ -18,20 +18,19 @@ strrev: ; the null terminator mov rcx, STRLEN_MAX scasb.rep.nz ax1, zero - sub ax1, ax1, 1 + dec ax1, 1 .2: ; copy, going backward though str ; and forward through buf - mov rax, b[ax1] - mov b[ax0], rax + mov b[ax0], b[ax1] cmp ax1, rsi mov.z b[ax0+1], zero ret.z - add ax0, ax0, 1 - sub ax1, ax1, 1 + inc ax0, 1 + dec ax1, 1 jmp .2 @@ -50,18 +49,16 @@ strrev2: ; the null terminator mov rcx, STRLEN_MAX scasb.rep.nz ax1, zero - sub ax1, ax1, 1 + dec ax1, 1 ; increase ax0 while decreasing ax1, performing exchanges .2: b.ae ax0, ax1, .3 - mov rax, b[ax1] - xchg rax, b[ax0] - mov b[ax1], rax + xchg b[ax0], b[ax1] - add ax0, ax0, 1 - sub ax1, ax1, 1 + inc ax0, 1 + dec ax1, 1 jmp .2 .3: diff --git a/ka/sys/intr/common.k b/ka/sys/intr/common.k index 8e48c30..28aecc1 100644 --- a/ka/sys/intr/common.k +++ b/ka/sys/intr/common.k @@ -5,9 +5,7 @@ TrapHandlers.prolog: mov rbp, rsp ; nx0 = caller's cr2 - mov ax0, r14 - mov ax1, $cr2 - call RFS.LoadReg + call RFS.LoadReg, r14, $cr2 ; we don't preserve the r12 we got mov r12, rax diff --git a/ka/sys/intr/trap0.k b/ka/sys/intr/trap0.k index f4f60cb..9e5f45b 100644 --- a/ka/sys/intr/trap0.k +++ b/ka/sys/intr/trap0.k @@ -9,10 +9,8 @@ trap0_handler: jmp TrapHandlers.prolog .text: - mov ax0, r14 - mov ax1, $rax - call RFS.LoadReg - call RFS.LoadArgs + call RFS.LoadReg, r14, $rax + call RFS.LoadArgs, r14 b.z rax, zero, .handle_Shutdown b.z rax, Sys.Exit, .handle_Exit @@ -66,7 +64,7 @@ trap0_handler: call RFS.StoreReg, zero, $cr0 mov rcx, CMDCOM_LOADP - sub rcx, rcx, 0x100000 + dec rcx, 0x100000 ; Code offset mov ax2, rcx @@ -87,17 +85,17 @@ trap0_handler: ; Disk API ; .handle_FindFirst: - add ax0, ax0, r12 + inc ax0, r12 call DISK.FindFirst jmp .fini .handle_FindNext: - add ax0, ax0, r12 + inc ax0, r12 call DISK.FindNext jmp .fini .handle_OpenFile: - add ax0, ax0, r12 + inc ax0, r12 call DISK.OpenFile jmp .fini @@ -106,7 +104,7 @@ trap0_handler: jmp .fini .handle_ReadFile: - add ax1, ax1, r12 + inc ax1, r12 call DISK.ReadFile jmp .fini diff --git a/ka/sys/main.k b/ka/sys/main.k index 31f4f1d..c931f68 100644 --- a/ka/sys/main.k +++ b/ka/sys/main.k @@ -21,7 +21,7 @@ InitSyscalls: call RFS.StoreReg mov ax1, ax0 - add ax0, ax0, 255 # TRAP no. (ax0 - 1) + inc ax0, 255 # TRAP no. (ax0 - 1) call IDT.AddHandler ret diff --git a/ka/usr/cmd/dir.k b/ka/usr/cmd/dir.k index 854a6cb..45440c3 100644 --- a/ka/usr/cmd/dir.k +++ b/ka/usr/cmd/dir.k @@ -10,9 +10,7 @@ builtins.dir: push r12 mov r12, zero # no. of files found - mov rcx, STRLEN_MAX - mov rdx, .dirmsg - prns.rep.nz rdx + call print, .dirmsg .dirmsg = "Directory of C:\\\n\n" @@ -34,7 +32,7 @@ builtins.dir: jmp.axz .end ; found something - add r12, r12, 1 + inc r12, 1 ; separate extension from file name mov rcx, NAME_MAX @@ -48,13 +46,13 @@ builtins.dir: ; calculate where to put extension sub rdi, rsi, .buf - sub rdi, rdi, 1 + dec rdi, 1 .ext_pad: ; print at least 11 non-space characters before extension b.ae rdi, 11, .print_ext prn ' ' - add rdi, rdi, 1 + inc rdi, 1 jmp .ext_pad .print_ext: @@ -69,10 +67,9 @@ builtins.dir: b.z b[rsi], 0, .print_ext.2 ; print and decrease rcx, unless it's already 0 - mov rbx, b[rsi] - prn rbx - add rsi, rsi, 1 - sub.cxnz rcx, rcx, 1 + prn b[rsi] + inc rsi, 1 + dec.cxnz rcx, 1 jmp .print_ext.1 @@ -84,9 +81,8 @@ builtins.dir: .print_bytes: ; print file size in bytes - prn ' ' - prn ' ' - prn ' ' + mov rcx, 3 + prn.rep ' ' shr rax, rdx, 10 and rdx, rdx, 1023 @@ -94,7 +90,7 @@ builtins.dir: push rdx push rax call printf, .bytesstr - add rsp, rsp, 16 + inc rsp, 16 .bytesstr = "%d kilobytes + %d bytes" @@ -106,7 +102,7 @@ builtins.dir: .end: push r12 call printf, .endstr1 - add rsp, rsp, 8 + inc rsp, 8 call print, .endstr2 diff --git a/ka/usr/cmd/main.k b/ka/usr/cmd/main.k index 18bd01f..934a10d 100644 --- a/ka/usr/cmd/main.k +++ b/ka/usr/cmd/main.k @@ -41,7 +41,7 @@ main: jmp.cxz .input_loop ; no ; yes, delete it - sub rcx, rcx, 1 + dec rcx, 1 add rdx, rcx, argbuf mov b[rdx], zero @@ -63,7 +63,7 @@ main: ; add character to buffer and increase iterator (rcx) add rdx, rcx, argbuf mov b[rdx], rax - add rcx, rcx, 1 + inc rcx, 1 ; another one jmp .input_loop @@ -87,7 +87,7 @@ main: ; skip spaces cmp rcx, ' ' - add.z rsi, rsi, 1 + inc.z rsi, 1 jmp.z .next_space ; if we're here, we found a @@ -105,17 +105,16 @@ main: ; how much do we copy? sub rcx, rdx, argbuf jmp.cxz .detect_builtin - sub rcx, rcx, 1 + dec rcx, 1 mov rdi, argbuf mov rsi, argv0 .copy_loop: - mov rax, b[rdi] - mov b[rsi], rax + mov b[rsi], b[rdi] - add rdi, rdi, 1 - add rsi, rsi, 1 + inc rdi, 1 + inc rsi, 1 loop .copy_loop @@ -185,7 +184,7 @@ main: call printf, .datefmt - add rsp, rsp, 40 + inc rsp, 40 jmp .print_prompt @@ -255,7 +254,7 @@ main: push b[rax+1] push b[rax+2] call printf, .timefmt - add rsp, rsp, 24 + inc rsp, 24 jmp .print_prompt @@ -307,7 +306,7 @@ main: push q[argv1pos] push argv0 call printf, .fnf_errmsg - add rsp, rsp, 16 + inc rsp, 16 jmp .print_prompt @@ -317,7 +316,7 @@ main: push q[argv1pos] push argv0 call printf, .ef_errmsg - add rsp, rsp, 16 + inc rsp, 16 jmp .print_prompt @@ -327,7 +326,7 @@ main: push q[argv1pos] push argv0 call printf, .cno_errmsg - add rsp, rsp, 16 + inc rsp, 16 jmp .print_prompt diff --git a/vm/in/ALU b/vm/in/ALU index 765eacc..6553ccc 100644 --- a/vm/in/ALU +++ b/vm/in/ALU @@ -12,7 +12,7 @@ # # Preserves all flags # -or r r ri +or 3 # # Bitwise AND operation @@ -21,7 +21,7 @@ or r r ri # # Preserves all flags # -and r r ri +and 3 # # Bitwise XOR operation @@ -30,7 +30,7 @@ and r r ri # # Preserves all flags # -xor r r ri +xor 3 # # Logical left/right shift (SHL/SHR) @@ -40,8 +40,8 @@ xor r r ri # # Preserves all flags # -shl r r ri -shr r r ri +shl 3 +shr 3 # # Arithmetical left/right shift (SAL/SAR) @@ -51,8 +51,8 @@ shr r r ri # # Preserves all flags # -sal r r ri -sar r r ri +sal 3 +sar 3 #---------------------------------------------------------------------------# # Arithmetic instructions # @@ -67,8 +67,7 @@ sar r r ri # Sets OF is signed integer overflow occur, clears it otherwise # Sets ZF and SF according to the result # -cmp r ri -cmp m ri +cmp 2 # # Arithmetical ADD operation @@ -79,8 +78,9 @@ cmp m ri # Sets OF is signed integer overflow occur, clears it otherwise # Sets ZF and SF according to the result # -add r r ri -addf r r ri +inc 2 +add 3 +addf 3 # # Arithmetical SUB operation @@ -91,8 +91,9 @@ addf r r ri # Sets OF is signed integer overflow occur, clears it otherwise # Sets ZF and SF according to the result # -sub r r ri -subf r r ri +dec 2 +sub 3 +subf 3 # # Arithmetical ADD/SUB operation, with carry/overflow @@ -104,8 +105,8 @@ subf r r ri # Sets OF is signed integer overflow occur, clears it otherwise # Sets ZF and SF according to the result # -adcx r r ri -sbbx r r ri +adcx 3 +sbbx 3 # # Arithmetical MUL operation @@ -115,8 +116,8 @@ sbbx r r ri # Preserves ZF and SF # Sets CF and OF if HI($src1 * $src2) > 0, clears them otherwise # -mul r r ri -mulf r r ri +mul 3 +mulf 3 # Arithmetical unsigned MUL operation # @@ -125,7 +126,7 @@ mulf r r ri # # Preserves all flags # -mulhi r r ri +mulhi 3 # Arithmetical signed MUL operation # @@ -134,7 +135,7 @@ mulhi r r ri # # Preserves all flags # -imulhi r r ri +imulhi 3 # # Arithmetical unsigned DIV operation @@ -143,7 +144,7 @@ imulhi r r ri # # Preserves all flags # -div r r ri +div 3 # # Arithmetical signed DIV operation @@ -152,7 +153,7 @@ div r r ri # # Preserves all flags # -idiv r r ri +idiv 3 # # Arithmetical modulo operation (REM) @@ -161,5 +162,5 @@ idiv r r ri # # Preserves all flags # -rem r r ri +rem 3 diff --git a/vm/in/MEM b/vm/in/MEM index b5bc40e..05779f8 100644 --- a/vm/in/MEM +++ b/vm/in/MEM @@ -10,7 +10,7 @@ # # RIP = $1 # -jmp ri +jmp 1 # # RCX-dependent jump (LOOP) instruction @@ -20,7 +20,7 @@ jmp ri # RIP = $1 # FI # -loop ri +loop 1 # # Conditional absolute jumps (B) @@ -38,7 +38,7 @@ loop ri # # Suffixing B with the REP suffix results in undefined behavior # -b rm ri ri +b 3 #---------------------------------------------------------------------------# @@ -51,9 +51,9 @@ b rm ri ri # PUSH(RIP) # JMP(RIP) # -call ri -call i ri -call i ri ri +call 1 +xcall2 2 +xcall3 3 # # Return to caller (RET) @@ -69,7 +69,7 @@ ret # RBP = RSP # RSP = RSP - $1 # -enter i +enter 1 # # Leave stack frame (LEAVE) @@ -85,7 +85,7 @@ leave # RSP = RSP - 8 # *RSP = $1 # -push rim +push 1 # # POP value from stack @@ -93,7 +93,7 @@ push rim # $1 = *RSP # RSP = RSP + 8 # -pop r +pop 1 #---------------------------------------------------------------------------# # Movement instructions # @@ -111,31 +111,30 @@ pop r # # Preserves all flags # -lea r m +lea 2 # # Move data (MOV) instruction # # $1 = SignExtend($2) # -mov r rim -mov m ri +mov 2 # # Load from memory with zero-extension (MOVSX/MOVZX) instruction # # $1 = ZeroExtend($2) # -movzx r m +movzx 2 # # Move with sign-extension (MOVSXx) instruction # # $1 = SignExtend($2 & (2^(8 * sizeof(x)) - 1) # -movsxb r r -movsxw r r -movsxd r r +movsxb 2 +movsxw 2 +movsxd 2 # # Exchange (XCHG) instruction @@ -144,5 +143,5 @@ movsxd r r # $1 = $2 # $2 = $_ # -xchg r rm +xchg 2 diff --git a/vm/in/MISC b/vm/in/MISC index 7397baf..f4d3760 100644 --- a/vm/in/MISC +++ b/vm/in/MISC @@ -38,14 +38,14 @@ into # # Get timestamp in µseconds # -utime r r +utime 2 # # $1 = seconds since start of month # $2 = current month # $3 = current year # -ytime r r r +ytime 3 # # Clear all GPR registers except RBP/RSP @@ -61,9 +61,9 @@ cls # # Change endianness # -bswap r r -wswap r r -dswap r r +bswap 2 +wswap 2 +dswap 2 #---------------------------------------------------------------------------# # I/O instructions # @@ -72,7 +72,7 @@ dswap r r # # Send a character to standard output (PRN) # -prn ri +prn 1 # # Print a string to standard output (PRN) @@ -89,10 +89,10 @@ prn ri # FI # # -prns r +prns 1 # # Scan a character from standard input (SCAN) # -scan r +scan 1 diff --git a/vm/in/STRING b/vm/in/STRING index f2f7be0..beef788 100644 --- a/vm/in/STRING +++ b/vm/in/STRING @@ -15,10 +15,10 @@ # %str = %str - sizeof(x) # FI # -stosb r ri -stosw r ri -stosd r ri -stosq r ri +stosb 2 +stosw 2 +stosd 2 +stosq 2 # # Scan string for a particular value (SCASx) @@ -42,10 +42,10 @@ stosq r ri # - Does not move past the value when found # - 'SCASB.REP.NZ reg ch' is a short 'strchnul()' # -scasb r ri -scasw r ri -scasd r ri -scasq r ri +scasb 2 +scasw 2 +scasd 2 +scasq 2 #---------------------------------------------------------------------------# diff --git a/vm/in/SUPER b/vm/in/SUPER index 4197855..c78f8b3 100644 --- a/vm/in/SUPER +++ b/vm/in/SUPER @@ -48,7 +48,7 @@ hlt # #ILL if $1 > 255 # #($1+256) otherwise # -trap ri +trap 1 # # Return from exception/interrupt (IRET) @@ -79,7 +79,7 @@ sti # Throws: # #SYS if not in supervisor mode # -devctl r r +devctl 2 # # Call a device-defined function slot of device (IOCALL) @@ -89,5 +89,5 @@ devctl r r # Throws: # #SYS if not in supervisor mode # -iocall ri ri +iocall 2 diff --git a/vm/in/alu.c b/vm/in/alu.c index cd5cd8c..a99d5da 100644 --- a/vm/in/alu.c +++ b/vm/in/alu.c @@ -8,27 +8,32 @@ //----------------------------------------------------------------------------// -IMPL_START(or) { *r1 = p2->val | p3->val; return 1; } -IMPL_START(and) { *r1 = p2->val & p3->val; return 1; } -IMPL_START(xor) { *r1 = p2->val ^ p3->val; return 1; } +IMPL_START(or) { SRCP(p2); SRCP(p3); *r1 = p2->val | p3->val; return 1; } +IMPL_START(and) { SRCP(p2); SRCP(p3); *r1 = p2->val & p3->val; return 1; } +IMPL_START(xor) { SRCP(p2); SRCP(p3); *r1 = p2->val ^ p3->val; return 1; } //----------------------------------------------------------------------------// -IMPL_START(shl) { *r1 = p2->val << p3->val; return 1; } -IMPL_START(shr) { *r1 = p2->val >> p3->val; return 1; } -IMPL_START(sal) { *r1 = (ulong)((long)p2->val << (long)p3->val); return 1; } -IMPL_START(sar) { *r1 = (ulong)((long)p2->val >> (long)p3->val); return 1; } +IMPL_START(shl) { SRCP(p2); SRCP(p3); *r1 = p2->val << p3->val; return 1; } +IMPL_START(shr) { SRCP(p2); SRCP(p3); *r1 = p2->val >> p3->val; return 1; } +IMPL_START(sal) { SRCP(p2); SRCP(p3); *r1 = (ulong)((long)p2->val << (long)p3->val); return 1; } +IMPL_START(sar) { SRCP(p2); SRCP(p3); *r1 = (ulong)((long)p2->val >> (long)p3->val); return 1; } //----------------------------------------------------------------------------// -IMPL_START(add) { *r1 = p2->val + p3->val; return 1; } -IMPL_START(addf) { COMPARE_ADD(p2->val, p3->val); *r1 = p2->val + p3->val; return 1; } +IMPL_START(inc) { SRCP(p1); SRCP(p2); *r1 = p1->val + p2->val; return 1; } +IMPL_START(add) { SRCP(p2); SRCP(p3); *r1 = p2->val + p3->val; return 1; } +IMPL_START(addf) { SRCP(p2); SRCP(p3); COMPARE_ADD(p2->val, p3->val); *r1 = p2->val + p3->val; return 1; } -IMPL_START(sub) { *r1 = p2->val - p3->val; return 1; } -IMPL_START(subf) { COMPARE_SUB(p2->val, p3->val); *r1 = p2->val - p3->val; return 1; } +IMPL_START(dec) { SRCP(p1); SRCP(p2); *r1 = p1->val - p2->val; return 1; } +IMPL_START(sub) { SRCP(p2); SRCP(p3); *r1 = p2->val - p3->val; return 1; } +IMPL_START(subf) { SRCP(p2); SRCP(p3); COMPARE_SUB(p2->val, p3->val); *r1 = p2->val - p3->val; return 1; } IMPL_START(adcx) { + SRCP(p2); + SRCP(p3); + p3->val += !!(R(RFX)&CF); COMPARE_ADD(p2->val, p3->val); *r1 = p2->val + p3->val; @@ -38,6 +43,9 @@ IMPL_START(adcx) IMPL_START(sbbx) { + SRCP(p2); + SRCP(p3); + p3->val += !!(R(RFX)&CF); COMPARE_SUB(p2->val, p3->val); *r1 = p2->val - p3->val; @@ -47,11 +55,14 @@ IMPL_START(sbbx) //----------------------------------------------------------------------------// -IMPL_START(mul) { *r1 = p2->val * p3->val; return 1; } -IMPL_START(rem) { *r1 = p2->val % p3->val; return 1; } +IMPL_START(mul) { SRCP(p2); SRCP(p3); *r1 = p2->val * p3->val; return 1; } +IMPL_START(rem) { SRCP(p2); SRCP(p3); *r1 = p2->val % p3->val; return 1; } IMPL_START(div) { + SRCP(p2); + SRCP(p3); + if (!p3->val) _except(ctx, E_DIV, "DIV by 0"); *r1 = p2->val / p3->val; @@ -61,6 +72,9 @@ IMPL_START(div) IMPL_START(idiv) { + SRCP(p2); + SRCP(p3); + if (!p3->val) _except(ctx, E_DIV, "IDIV by 0"); @@ -81,12 +95,18 @@ static void __unsigned_multiply128(ulong u, ulong v, ulong *hi, ulong *lo) IMPL_START(mulhi) { + SRCP(p2); + SRCP(p3); + __unsigned_multiply128(p2->val, p3->val, r1, r2); return 2; } IMPL_START(mulf) { + SRCP(p2); + SRCP(p3); + ulong tmp; __unsigned_multiply128(p2->val, p3->val, &tmp, r1); R(RFX) = p2->val ? (R(RFX)|CF|OF) : R(RFX)&~(CF|OF); @@ -106,6 +126,9 @@ static void __signed_multiply128(ulong u, ulong v, ulong *hi, ulong *lo) IMPL_START(imulhi) { + SRCP(p2); + SRCP(p3); + __signed_multiply128(p2->val, p3->val, r1, r2); return 2; } diff --git a/vm/in/arch_i.py b/vm/in/arch_i.py index 15f6126..b4f0e7e 100644 --- a/vm/in/arch_i.py +++ b/vm/in/arch_i.py @@ -5,25 +5,6 @@ from tempfile import TemporaryFile -def getflag(s): - if s == "r": - return "P_REG" - - if s == "i": - return "P_IMM" - - if s == "m": - return "P_MEM" - - return "__FLAG_ERROR__" - -def doprnt(fp, i, p1, p2, p3): - for c1 in p1: - for c2 in p2: - for c3 in p3: - fp.write("{} {} {} {}".format(i, c1, c2, c3).strip()) - fp.write('\n') - def parse_1(fi, fp): global count @@ -41,36 +22,7 @@ def parse_1(fi, fp): parse_1(fi2, fp) continue - tok = line.split() - - if len(tok) == 0: - continue - - i = tok[0] - - if len(tok) == 1: - doprnt(fp, i, ' ', ' ', ' ') - continue - - if len(tok) == 2: - p = tok[1] - doprnt(fp, i, p, ' ', ' ') - continue - - if len(tok) == 3: - p1 = tok[1] - p2 = tok[2] - doprnt(fp, i, p1, p2, ' ') - continue - - assert(len(tok) == 4) - p1 = tok[1] - p2 = tok[2] - p3 = tok[3] - - doprnt(fp, i, p1, p2, p3) - - fi.close() + fp.write("{}\n".format(line)) def parse_2(fp): global count @@ -89,41 +41,19 @@ def parse_2(fp): if len(tok) == 1: name = tok[0] - p1 = "NOPRM" - p2 = "NOPRM" - p3 = "NOPRM" - - elif len(tok) == 2: - name = "{}_{}".format(tok[0], tok[1]) - p1 = getflag(tok[1]) - p2 = "NOPRM" - p3 = "NOPRM" - - elif len(tok) == 3: - name = "{}_{}_{}".format(tok[0], tok[1], tok[2]) - p1 = getflag(tok[1]) - p2 = getflag(tok[2]) - p3 = "NOPRM" - - elif len(tok) == 4: - name = "{}_{}_{}_{}".format(tok[0], tok[1], tok[2], tok[3]) - p1 = getflag(tok[1]) - p2 = getflag(tok[2]) - p3 = getflag(tok[3]) + n = 0 else: - name = "__TOK_ERROR__" - p1 = "__TOK_ERROR__" - p2 = "__TOK_ERROR__" - p3 = "__TOK_ERROR__" + assert(len(tok) == 2) + n = tok[1] - ls.write("{}{}\n".format(deprecated, name)) + ls.write("{}{}\n".format(deprecated, tok[0])) hd.write("#ifdef _NEED_ARCH_I\n") - hd.write('{{ "{}{}", "{}{}", {}, {}, {}, i_{} }},\n'\ - .format(deprecated, tok[0], deprecated, name, p1, p2, p3, tok[0])) + hd.write('{{ "{}{}", {}, i_{} }},\n'\ + .format(deprecated, tok[0], n, tok[0])) hd.write("#else\n") - hd.write("#define I_{} {}\n".format(name.upper(), count)) + hd.write("#define I_{} {}\n".format(tok[0].upper(), count)) hd.write("extern bool i_{}(ctx_t *, acc_t *, acc_t *, acc_t *, ulong *, ulong *, ulong *);\n" .format(tok[0])) hd.write("#endif\n\n") diff --git a/vm/in/instrs.h b/vm/in/instrs.h index e21beb5..49e24e0 100644 --- a/vm/in/instrs.h +++ b/vm/in/instrs.h @@ -9,6 +9,15 @@ uint i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, acc_t *p3, \ ulong *r1, ulong *r2, ulong *r3) \ +#define XSRCP(v, p, x) \ + if (ACC_FMT_IS_MEM(p->type)) \ + v = readmem##x(ctx, p->addr, p->mlen); \ + else v = p->val; \ + +#define SRCP(p) \ + if (__builtin_expect(ACC_FMT_IS_MEM(p->type), 0)) \ + p->val = readmemsx(ctx, p->addr, p->mlen); \ + //----------------------------------------------------------------------------// #define INTO() \ diff --git a/vm/in/mem.c b/vm/in/mem.c index 13c1f92..c615d3a 100644 --- a/vm/in/mem.c +++ b/vm/in/mem.c @@ -17,14 +17,10 @@ IMPL_START(loop) { IMPL_START(b) { - ulong v; + SRCP(p1); + SRCP(p2); - if (ACC_FMT_IS_MEM(p1->type)) - v = readmemsx(ctx, p1->addr, p1->mlen); - - else v = p1->val; - - COMPARE_SUB(v, p2->val); + COMPARE_SUB(p1->val, p2->val); if (eval_cond(ctx, ctx->cond)) R(RIP) = p3->val; @@ -34,14 +30,9 @@ IMPL_START(b) IMPL_START(cmp) { - ulong v; + SRCP(p1); - if (ACC_FMT_IS_MEM(p1->type)) - v = readmemsx(ctx, p1->addr, p1->mlen); - - else v = p1->val; - - COMPARE_SUB(v, p2->val); + COMPARE_SUB(p1->val, p2->val); return 0; } @@ -49,44 +40,20 @@ IMPL_START(cmp) //----------------------------------------------------------------------------// IMPL_START(lea) { *r1 = p2->addr; return 1; } +IMPL_START(mov) { XSRCP(*r1, p2, sx); return 1; } +IMPL_START(movzx) { XSRCP(*r1, p2, zx); return 1; } -IMPL_START(mov) -{ - if (ACC_FMT_IS_MEM(p2->type)) - *r1 = readmemsx(ctx, p2->addr, p2->mlen); - - else *r1 = p2->val; - - return 1; -} - -IMPL_START(movzx) -{ - if (ACC_FMT_IS_MEM(p2->type)) - { - if (__builtin_expect(p2->mlen == 8, 0)) - _except(ctx, E_ILL, "MOVZX with qword memory source"); - - *r1 = readmemzx(ctx, p2->addr, p2->mlen); - } - - else *r1 = p2->val; - - return 1; -} - -IMPL_START(movsxb) { *r1 = (ulong)(long)(char)(p2->val & 0xFF); return 1; } -IMPL_START(movsxw) { *r1 = (ulong)(long)(short)(p2->val & 0xFFFF); return 1; } -IMPL_START(movsxd) { *r1 = (ulong)(long)(int)(p2->val & 0xFFFFFFFF); return 1; } +IMPL_START(movsxb) { SRCP(p2); *r1 = (ulong)(long)(char)p2->val; return 1; } +IMPL_START(movsxw) { SRCP(p2); *r1 = (ulong)(long)(short)p2->val; return 1; } +IMPL_START(movsxd) { SRCP(p2); *r1 = (ulong)(long)(int)p2->val; return 1; } IMPL_START(xchg) { + SRCP(p1); + SRCP(p2); + *r2 = p1->val; - - if (ACC_FMT_IS_MEM(p2->type)) - *r1 = readmemsx(ctx, p2->addr, p2->mlen); - - else *r1 = p2->val; + *r1 = p2->val; return 2; } @@ -99,15 +66,10 @@ IMPL_START(xchg) IMPL_START(push) { - ulong v; - - if (ACC_FMT_IS_MEM(p1->type)) - v = readmemzx(ctx, p1->addr, p1->mlen); - - else v = p1->val; + XSRCP(p1->val, p1, zx); R(RSP) -= 8; - writemem(ctx, v, R(RSP), 8); + writemem(ctx, p1->val, R(RSP), 8); return 0; } @@ -122,17 +84,41 @@ IMPL_START(pop) IMPL_START(call) { + SRCP(p1); + R(RSP) -= 8; writemem(ctx, R(RIP), R(RSP), 8); R(RIP) = p1->val; - if (p2) - { - R(AX0) = p2->val; + return 0; +} - if (p3) - R(AX1) = p3->val; - } +IMPL_START(xcall2) +{ + SRCP(p1); + SRCP(p2); + + R(RSP) -= 8; + writemem(ctx, R(RIP), R(RSP), 8); + + R(RIP) = p1->val; + R(AX0) = p2->val; + + return 0; +} + +IMPL_START(xcall3) +{ + SRCP(p1); + SRCP(p2); + SRCP(p3); + + R(RSP) -= 8; + writemem(ctx, R(RIP), R(RSP), 8); + + R(RIP) = p1->val; + R(AX0) = p2->val; + R(AX1) = p3->val; return 0; } diff --git a/vm/in/misc.c b/vm/in/misc.c index 5925472..a35cce7 100644 --- a/vm/in/misc.c +++ b/vm/in/misc.c @@ -81,6 +81,8 @@ IMPL_START(cls) IMPL_START(bswap) { + SRCP(p2); + ulong v = p2->val; *r1 = ((v & 0xFF00000000000000) >> 56) @@ -97,6 +99,8 @@ IMPL_START(bswap) IMPL_START(wswap) { + SRCP(p2); + ulong v = p2->val; *r1 = ((v & 0xFFFF000000000000) >> 48) @@ -109,6 +113,8 @@ IMPL_START(wswap) IMPL_START(dswap) { + SRCP(p2); + *r1 = ((p2->val & 0xFFFFFFFF00000000) >> 32) | ((p2->val & 0x00000000FFFFFFFF) << 32); @@ -121,6 +127,8 @@ IMPL_START(dswap) IMPL_START(prn) { + SRCP(p1); + ulong v = p1->val; // Magic value? :) @@ -135,6 +143,9 @@ IMPL_START(prn) IMPL_START(prns) { + if (p1->type != A_REG) + _except(ctx, E_ILL, "PRNS given a non-REG operand"); + uchar ch = readmemzx(ctx, R(p1->reg), 1); COMPARE_SUB(ch, 0); diff --git a/vm/in/string.c b/vm/in/string.c index ca10056..614352d 100644 --- a/vm/in/string.c +++ b/vm/in/string.c @@ -13,6 +13,9 @@ static void stos_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len) { + if (p1->type != A_REG) + _except(ctx, E_ILL, "STOSX given a non-REG operand"); + writemem(ctx, p2->val, R(p1->reg), len); STR_MOVE(p1->reg, len); } @@ -26,6 +29,9 @@ IMPL_START(stosq) { stos_impl(ctx, p1, p2, 8); return 0; } static void scas_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len) { + if (p1->type != A_REG) + _except(ctx, E_ILL, "SCASX given a non-REG operand"); + ulong x = readmemsx(ctx, R(p1->reg), len); COMPARE_SUB(x, p2->val); diff --git a/vm/pc/console.c b/vm/pc/console.c index 7b99c8b..0e35985 100644 --- a/vm/pc/console.c +++ b/vm/pc/console.c @@ -3,18 +3,23 @@ #include +// FIXME XXX + +//#define _LARGE_SCREEN + #ifndef _LARGE_SCREEN -# define CONSOLE_WIDTH 80 -# define CONSOLE_HEIGHT 25 -# define CONSOLE_FONT_SIZE 16 +# define _MULT 1 #else -# define CONSOLE_WIDTH 160 -# define CONSOLE_HEIGHT 50 -# define CONSOLE_FONT_SIZE 32 +# define _MULT 2 #endif -#define SCREEN_WIDTH (9 * CONSOLE_WIDTH) -#define SCREEN_HEIGHT (16 * CONSOLE_HEIGHT) +#define CONSOLE_WIDTH (80) +#define CONSOLE_HEIGHT (25) +#define CONSOLE_FONT_SIZE (16 * _MULT) +#define SCREEN_WIDTH (9 * CONSOLE_WIDTH * _MULT) +#define SCREEN_HEIGHT (16 * CONSOLE_HEIGHT * _MULT) + +#define _SURF_H CONSOLE_FONT_SIZE SDL_Window *scr_win = NULL; SDL_Renderer *scr_rend = NULL; @@ -281,7 +286,7 @@ void console_putc(ctx_t *ctx, char ch) for (y = 0; y < CONSOLE_HEIGHT-1; y++) if (scr_rects[y] != NULL) { - scr_rects[y]->y -= 16; // surf->h + scr_rects[y]->y -= _SURF_H; // surf->h } console_render(ctx); diff --git a/vm/pc/decode.c b/vm/pc/decode.c index da4aa30..9a368a5 100644 --- a/vm/pc/decode.c +++ b/vm/pc/decode.c @@ -62,34 +62,31 @@ static void checkreg(ctx_t *ctx, uint reg) // // Verify that given access length is that of a byte/word/dword/qword // -static void checklength(ctx_t *ctx, uint len) +static void checklength(ctx_t *ctx, instr_t *in, uint len) { static const int lentab[9] = { 0, 1, 1, 0, 1, 0, 0, 0, 1 }; if (len > 8 || lentab[len] == 0) - _except(ctx, E_ILL, "Invalid memory access length: %u", len); + _except(ctx, E_ILL, "%s: Invalid memory access length: %u", + in->name, len); } // // Extracts one operand // -static void extract_param(ctx_t *ctx, uint prm, acc_t *p) +static void extract_param(ctx_t *ctx, instr_t *in, acc_t *p) { // Get next operand ModRM-like byte uchar fmt = fetchb(ctx); - ulong hi = (fmt & 0b11100000) >> 5; - ulong lo = fmt & 0b00011111; + uchar hi = (fmt & 0b11100000) >> 5; + uchar lo = fmt & 0b00011111; // // Registers // if (hi == 0) { - if (prm != P_REG) - _except(ctx, E_ILL, "Not expecting a register: %s", - ctx->cur_in->full); - p->reg = lo; p->type = A_REG; checkreg(ctx, p->reg); @@ -104,10 +101,6 @@ static void extract_param(ctx_t *ctx, uint prm, acc_t *p) // if (hi == 7) { - if (prm != P_IMM) - _except(ctx, E_ILL, "Not expecting an immediate: %s", - ctx->cur_in->full); - switch (lo) { case 1: @@ -131,7 +124,8 @@ static void extract_param(ctx_t *ctx, uint prm, acc_t *p) break; default: - _except(ctx, E_ILL, "Invalid immediate length: %hhu", lo); + _except(ctx, E_ILL, "%s: Invalid immediate length: %hhu", + in->name, lo); } return; @@ -141,11 +135,7 @@ static void extract_param(ctx_t *ctx, uint prm, acc_t *p) // Memory operands // - if (prm != P_MEM) - _except(ctx, E_ILL, "Not expecting a memory access: %s", - ctx->cur_in->full); - - checklength(ctx, lo); + checklength(ctx, in, lo); p->mlen = lo; switch (hi) @@ -234,31 +224,31 @@ void decode(ctx_t *ctx) ctx->cond = b2 & SUFF_COND; // Operand 1? - if (in->prm1 == NOPRM) + if (in->nprms == 0) { exec_instr(ctx, in, NULL, NULL, NULL, lock, rep); return; } - extract_param(ctx, in->prm1, &p1); + extract_param(ctx, in, &p1); // Operand 2? - if (in->prm2 == NOPRM) + if (in->nprms == 1) { exec_instr(ctx, in, &p1, NULL, NULL, lock, rep); return; } - extract_param(ctx, in->prm2, &p2); + extract_param(ctx, in, &p2); // Operand 1? - if (in->prm3 == NOPRM) + if (in->nprms == 2) { exec_instr(ctx, in, &p1, &p2, NULL, lock, rep); return; } - extract_param(ctx, in->prm3, &p3); + extract_param(ctx, in, &p3); exec_instr(ctx, in, &p1, &p2, &p3, lock, rep); } diff --git a/vm/pc/decode.h b/vm/pc/decode.h index 225c40e..4a1c266 100644 --- a/vm/pc/decode.h +++ b/vm/pc/decode.h @@ -66,12 +66,7 @@ enum { NOPRM, P_REG, P_IMM, P_MEM=4 }; struct instr_t { char *name; - char *full; - - uint prm1; - uint prm2; - uint prm3; - + uint nprms; uint (*func)(ctx_t *, acc_t *, acc_t *, acc_t *, ulong *, ulong *, ulong *); }; diff --git a/vm/pc/exec.c b/vm/pc/exec.c index fa3d468..ce79ebd 100644 --- a/vm/pc/exec.c +++ b/vm/pc/exec.c @@ -41,12 +41,10 @@ bool eval_cond(ctx_t *ctx, uint cond) #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)); \ + else if (ACC_IS_MEM(p)) \ writemem(ctx, r, p->addr, p->mlen); \ - } } + else _except(ctx, E_ACC, "Trying to output to an IMM"); \ + } // // Executes an instruction diff --git a/vm/pc/main.c b/vm/pc/main.c index c67d3a5..9cda77e 100644 --- a/vm/pc/main.c +++ b/vm/pc/main.c @@ -62,7 +62,7 @@ int main(int argc, char **argv) main_ctx.r = arch_r; main_ctx.i = arch_i; -#if 1 && !defined(NDEBUG) +#if 0 && !defined(NDEBUG) main_ctx.dumpsw = 1; #endif