diff --git a/as/k-as.py b/as/k-as.py index 9fe2449..3f24334 100755 --- a/as/k-as.py +++ b/as/k-as.py @@ -213,7 +213,7 @@ def parse(): if line[0] == ' ' or line[0] == '\t': line = line.lstrip() - instrs.write(pcurfile + ' ') + instrs.write(pcurfile + ' ' + hex(ptext) + ' ') ptext += parse_instr(line) instrs.write("\n") @@ -411,43 +411,31 @@ def get_cond_mask(cond, line): leave(1) return (mask | pconds[cond]) - -#------------------------------------------------------------------------------- - -pfts = { - "reg": 0b00001, - "imm64": 0b00010, - - "bimm64": 0b00100, - "brr": 0b00101, - "brri": 0b00110, - "brrii": 0b00111, - - "wimm64": 0b01000, - "wrr": 0b01001, - "wrri": 0b01010, - "wrrii": 0b01011, - - "limm64": 0b01100, - "lrr": 0b01101, - "lrri": 0b01110, - "lrrii": 0b01111, - - "qimm64": 0b10000, - "qrr": 0b10001, - "qrri": 0b10010, - "qrrii": 0b10011, -} - -def get_fts_mask(ft, line): - if ft not in pfts: - print("Invalid operand format ({}): {}".format(ft, line)) - - else: - return pfts[ft] #------------------------------------------------------------------------------- +fmts = { + "r": 0b00000000, + "m_r": 0b00100000, + "m_rr": 0b01000000, + "m_rriw": 0b01100000, + "m_rrid": 0b10000000, + "m_rrii": 0b10100000, + "m_riq": 0b11000000, + "imm8": 0b11100001, + "imm16": 0b11100010, + "imm32": 0b11100100, + "imm64": 0b11101000, +} + +pref2len = { + "b" : 1, + "w" : 2, + "d" : 4, + "l" : 4, + "q" : 8, +} + def parse_instr(line): if line == None or len(line) == 0: return 0 @@ -463,12 +451,10 @@ def parse_instr(line): fellthrough = False - size = 4 + size = 2 - # Word 2 (rep|ft3|ft2|ft1) - w2 = 0 - - cond = None + # Byte 2 (rep|lock|0|cond) + b2 = 0 if len(instr) > 2 and '.' in instr: instr, suf = instr.split('.', 1) @@ -485,42 +471,30 @@ def parse_instr(line): else: suf = '' - w2 |= 0x8000 # REP - + b2 |= 1<<7 # REP + if len(suf) > 0: - instrs.write("%%cond ") - cond = "%%imm16 {}".format(get_cond_mask(suf, line)) + b2 |= get_cond_mask(suf, line) instr_name = instr instr_args = '' if params == None or len(params) == 0: - instrs.write("{} ".format(instr_name)) - - if cond != None: - size += 2 - instrs.write("{} ".format(cond)) - - instrs.write("%%imm16 {}".format(w2)) + instrs.write("{} %%imm8 {}".format(instr_name, b2)) return size tok = params.split(',') - - # FTn - fts = '' # - # Parse operands, generating fts along the way + # Parse operands # for word in tok: word = word.strip() instr_args += ' ' - gotPref = False - if len(fts) != 0: - fts += ' ' + mlen = 0 if len(word) == 0: print("Wrong syntax in line: '{}'".format(line)) @@ -540,9 +514,8 @@ def parse_instr(line): # memory length prefixes if len(word) > 2 and '[' in word: - if word[0] in 'bwlq': - fts += word[0] - gotPref = True + if word[0] in 'bwldq': + mlen = pref2len[word[0]] else: print("Bad memory length prefix: {}".format(line)) leave(1) @@ -551,7 +524,7 @@ def parse_instr(line): assert(word[0] == '[') # - # Determine memory format and save it into fts + # Determine memory format # if word[0] == '[': assert(word[-1] == ']') @@ -562,10 +535,8 @@ def parse_instr(line): word = pdefs[word] # Fall through - # # Make sure we got an access length prefix - # - if not gotPref: + if mlen == 0: print("Missing access length modifier: {}".format(line)) leave(1) @@ -581,15 +552,15 @@ def parse_instr(line): # Offsets # if '+' in word: - reg1 = "rzx" - reg2 = "rzx" + reg1 = "zero" + reg2 = "zero" imm1 = '1' imm2 = '0' wtok = word.split('+') # - # [reg] and [reg*imm16] + # [reg] and [reg*imm] # if len(wtok) == 1: @@ -602,10 +573,10 @@ def parse_instr(line): reg1 = wtok[0] # - # [reg+reg], [reg+imm16], [reg*imm16+imm16], [reg+reg*imm16] + # [reg+reg], [reg+imm], [reg*imm+imm], [reg+reg*imm] # elif len(wtok) == 2: - # Must be [reg*imm16+imm16] + # Must be [reg*imm+imm] if '*' in wtok[0]: assert(len(wtok[0].split('*')) == 2) assert(is_number(wtok[1].strip())) @@ -614,7 +585,7 @@ def parse_instr(line): reg2, imm1 = wtok[0].split('*', 1) imm2 = wtok[1] - # Must be [reg+reg*imm16] + # Must be [reg+reg*imm] elif '*' in wtok[1]: assert(len(wtok[1].split('*')) == 2) @@ -631,7 +602,7 @@ def parse_instr(line): reg2 = wtok[1] # - # [reg+reg+imm16], [reg+reg*imm16+imm16] + # [reg+reg+imm], [reg+reg*imm8+imm] # else: assert(len(wtok) == 3) @@ -647,129 +618,91 @@ def parse_instr(line): reg2 = wtok[1] # - # Update fts and instr_args + # Update instr_args # - instr_args += "{}:{} ".format(reg2, reg1) + if imm1 == '1': + # [reg+reg] + if imm2 == '0': + instr_args += "%%imm8 {} {} {}".format(fmts["m_rr"]|mlen, reg1, reg2) + size += 3 + + # [reg+reg+imm] + else: + instr_args += "%%imm8 {} {} {} %%imm16 {}".format(fmts["m_rriw"]|mlen, reg1, reg2, imm2) + size += 5 + + # [reg+reg*imm+imm] + else: + instr_args += "%%imm8 {} {} {} %%imm8 {} %%imm32 {}".format(fmts["m_rriw"]|mlen, reg1, reg2, imm1, imm2) + size += 8 + + # [reg] + elif word in pregs: + instr_args += "%%imm8 {} {}".format(fmts["m_r"]|mlen, word) size += 2 - if imm1 == '1': - if imm2 == '0': - fts += 'rr' - else: - fts += 'rri' - size += 2 - instr_args += "%%imm16 {}".format(imm2) - - else: - size += 4 - fts += 'rrii' - instr_args += "%%imm16 {} %%imm16 {}".format(imm1, imm2) - - continue - - # - # [imm64] or [reg] - # + # [imm], converted to [zero+imm] else: - fellthrough = True - # FALLTHROUGH + instr_args += "%%imm8 {} zero zero %%imm32 {}".format(fmts["m_rrid"]|mlen, word) + size += 7 + + continue # preprocessor, yet again if word in pdefs: word = pdefs[word] - # Fall through + # fallthrough # characters 'c' if len(word) == 3 and word[0] == word[-1] == "'": word = str(ord(word[1])) + # fallthrough # register index $reg if len(word) == 4 and word[0] == '$': if word[1:] in pregs: word = str(pregs[word[1:]]) + # fallthrough # for now every immediate is 64-bit if is_number(word): - # +8 for immediate - size += 8 + size += 9 # ModRM + imm - if not fellthrough: - instr_name += "_i" - - fts += "imm64" - - instr_args += "%%imm64 " - instr_args += word + instr_name += "_i" + instr_args += "%%imm8 {} ".format(fmts["imm64"]) + instr_args += "%%imm64 {}".format(word) fellthrough = False continue # register - if word in pregs: - size += 2 - - if not fellthrough: - instr_name += "_r" - fts += "reg" - - else: - fts += "rr" - + elif word in pregs: + size += 1 + instr_name += "_r" instr_args += word - fellthrough = False continue - # it's a label (a 64-bit immediate) - # +8 for immediate - size += 8 + # it's a label (a 32-bit immediate) + # ModRM + imm + size += 5 - if not fellthrough: - instr_name += "_i" - - fts += "imm64" - instr_args += "%%imm64 " + instr_name += "_i" + instr_args += "%%imm8 {} ".format(fmts["imm32"]) if word[0] == '.': instr_args += plastlabel instr_args += word - fellthrough = False - # - # Compute FTn - # - l = len(fts.split()) - - if l == 3: - ft1, ft2, ft3 = fts.split() - - w2 |= get_fts_mask(ft3, line) << 10 - w2 |= get_fts_mask(ft2, line) << 5 - w2 |= get_fts_mask(ft1, line) - - elif l == 2: - ft1, ft2 = fts.split() - - w2 |= get_fts_mask(ft2, line) << 5 - w2 |= get_fts_mask(ft1, line) - - else: - assert(l == 1) - w2 |= get_fts_mask(fts, line) - - if cond == None: - instrs.write("{} %%imm16 {}{}".format(instr_name, w2, instr_args)) - else: - size += 2 - instrs.write("{} {} %%imm16 {}{}".format(instr_name, cond, w2, instr_args)) + instrs.write("{} %%imm8 {} {}".format(instr_name, b2, instr_args)) return size #------------------------------------------------------------------------------- special_syms = { - "%%cond", + "%%imm8", "%%imm16", "%%imm32", "%%imm64", @@ -785,15 +718,13 @@ def gentext(): instrs.seek(0) - cond_mask = 0 - for _, line in enumerate(instrs): tok = line.strip().split() if WANT_DISASM: print(tok) - tok = tok[1:] + tok = tok[2:] for word in tok: if len(word) == 0: @@ -801,45 +732,33 @@ def gentext(): if word in pregs: idx = pregs[word] - b_text.write(idx.to_bytes(2, byteorder='little', signed=False)) - continue - - if ':' in word: - if len(word.split(':')) < 2: - print("Stray ':' in line: {}".format(line)) - leave(1) - - reg2, reg1 = word.split(':', 1) - idx1 = pregs[reg1] - idx2 = pregs[reg2] - b_text.write(((idx1 << 8) | idx2).to_bytes(2, byteorder='little', signed=False)) + b_text.write(idx.to_bytes(1, byteorder='little', signed=False)) continue if word in pinstrs: - idx = pinstrs.index(word) | cond_mask - cond_mask = 0 - b_text.write(idx.to_bytes(2, byteorder='little', signed=False)) + idx = pinstrs.index(word) + b_text.write(idx.to_bytes(1, byteorder='little', signed=False)) continue if word in plabels_text: addr = text_start + plabels_text[word] - b_text.write(addr.to_bytes(8, byteorder='little', signed=False)) + b_text.write(addr.to_bytes(4, byteorder='little', signed=False)) continue if word in plabels_data: addr = data_start + plabels_data[word] - b_text.write(addr.to_bytes(8, byteorder='little', signed=False)) + b_text.write(addr.to_bytes(4, byteorder='little', signed=False)) continue if word in special_syms: - if word == "%%imm16": + if word == "%%imm8": + lastimm = 1 + elif word == "%%imm16": lastimm = 2 elif word == "%%imm32": lastimm = 4 elif word == "%%imm64": lastimm = 8 - elif word == "%%cond": - cond_mask = (1 << 13) elif word == "%%signed": lastimm = 2 isSigned = True diff --git a/ka/crt/crt.k b/ka/crt/crt.k index bd91421..e5f5c3c 100644 --- a/ka/crt/crt.k +++ b/ka/crt/crt.k @@ -2,10 +2,42 @@ ; See the LICENSE file in the project root for more information. ; -; Include CRT librairies +; Limits ; + +CHAR_MIN := 0x0000000000000080 +SHRT_MIN := 0x0000000000008000 +INT_MIN := 0x0000000080000000 +LONG_MIN := 0x8000000000000000 + +XCHAR_MIN := 0xFFFFFFFFFFFFFF80 +XSHRT_MIN := 0xFFFFFFFFFFFF8000 +XINT_MIN := 0xFFFFFFFF80000000 + +CHAR_MAX := 0x000000000000007F +SHRT_MAX := 0x0000000000007FFF +INT_MAX := 0x000000007FFFFFFF +LONG_MAX := 0x7FFFFFFFFFFFFFFF + +BYTE_MAX := 0x00000000000000FF +WORD_MAX := 0x000000000000FFFF +LWORD_MAX := 0x00000000FFFFFFFF +QWORD_MAX := 0xFFFFFFFFFFFFFFFF + +STRLEN_MAX := 0x000000007AFFFFFF +FILE_MAXSZ := 0x0000000000008000 + +; +; Magic numbers +; + +PRN_CLEAR := 0x000000008BF00001 + +; +; CRT librairies +; + include "crt/sys.k" -include "crt/limits.k" include "crt/err/errno.k" include "crt/fmt/format.k" include "crt/str/string.k" diff --git a/ka/crt/limits.k b/ka/crt/limits.k deleted file mode 100644 index 1ef0edb..0000000 --- a/ka/crt/limits.k +++ /dev/null @@ -1,25 +0,0 @@ -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -CHAR_MIN := 0x80 -SHRT_MIN := 0x8000 -INT_MIN := 0x80000000 -LONG_MIN := 0x8000000000000000 - -XCHAR_MIN := 0xFFFFFFFFFFFFFF80 -XSHRT_MIN := 0xFFFFFFFFFFFF8000 -XINT_MIN := 0xFFFFFFFF80000000 - -CHAR_MAX := 0x7F -SHRT_MAX := 0x7FFF -INT_MAX := 0x7FFFFFFF -LONG_MAX := 0x7FFFFFFFFFFFFFFF - -BYTE_MAX := 0xFF -WORD_MAX := 0xFFFF -LWORD_MAX := 0xFFFFFFFF -QWORD_MAX := 0xFFFFFFFFFFFFFFFF - -STRLEN_MAX := 0xFFFFFFFF - -FILE_MAXSZ := 0x8000 ; 512KB diff --git a/ka/crt/str/strcmp.k b/ka/crt/str/strcmp.k index c979238..edf4eff 100644 --- a/ka/crt/str/strcmp.k +++ b/ka/crt/str/strcmp.k @@ -10,9 +10,10 @@ ; <0 if the first character that does not match has a lower value in str1 than in str2 ; strcmp: + mov rcx, zero .l: - movzx rax, b[ax0] - movzx rdx, b[ax1] + movzx rax, b[ax0+rcx] + movzx rdx, b[ax1+rcx] cmp rax, rdx jmp.nz .r @@ -21,8 +22,7 @@ strcmp: add rbx, rax, rdx jmp.bxz .r - add ax0, ax0, 1 - add ax1, ax1, 1 + add rcx, rcx, 1 jmp .l .r: @@ -37,8 +37,8 @@ strncmp: jmp.cxz .r .l: - mov rax, b[ax0] - mov rdx, b[ax1] + movzx rax, b[ax0] + movzx rdx, b[ax1] cmp rax, rdx jmp.nz .r diff --git a/ka/crt/sys.k b/ka/crt/sys.k index 25d08ef..614e000 100644 --- a/ka/crt/sys.k +++ b/ka/crt/sys.k @@ -1,19 +1,19 @@ ; The OS/K Team licenses this file to you under the MIT license. ; See the LICENSE file in the project root for more information. -; -; EXIT syscall -; -; Return to COMMAND.COM -; -Sys.Exit := 0x00 - ; ; SHUTDOWN syscall ; ; End virtual machine ; -Sys.Shutdown := 0x01 +Sys.Shutdown := 0x00 + +; +; EXIT syscall +; +; Return to COMMAND.COM +; +Sys.Exit := 0x01 ; FIND syscalls ; diff --git a/ka/doskrnl.k b/ka/doskrnl.k index dad77e9..c70775b 100644 --- a/ka/doskrnl.k +++ b/ka/doskrnl.k @@ -2,6 +2,11 @@ ; See the LICENSE file in the project root for more information. __sysmain: + pause + add rax, rax, 1 + jmp .1 + +.1: jmp start @@ -26,8 +31,7 @@ start: mov rsp, DOSKRNL_STACK mov rbp, zero - dump - mov rcx, 44 + mov rcx, 1 crash.cxz call main diff --git a/ka/sys/intr/common.k b/ka/sys/intr/common.k index f838406..8e48c30 100644 --- a/ka/sys/intr/common.k +++ b/ka/sys/intr/common.k @@ -3,25 +3,19 @@ TrapHandlers.prolog: mov rbp, rsp - sub rsp, rsp, 24 - mov q[rbp-8], r13 - mov q[rbp-16], r14 - mov q[rbp-24], r15 ; nx0 = caller's cr2 mov ax0, r14 mov ax1, $cr2 call RFS.LoadReg + ; we don't preserve the r12 we got mov r12, rax mov rdx, zero jmp rcx TrapHandlers.epilog: - mov r15, q[rbp-24] - mov r14, q[rbp-16] - mov r13, q[rbp-8] ; TRAP return values: RAX-RDX diff --git a/ka/sys/intr/trap0.k b/ka/sys/intr/trap0.k index 01dee86..f4f60cb 100644 --- a/ka/sys/intr/trap0.k +++ b/ka/sys/intr/trap0.k @@ -14,8 +14,8 @@ trap0_handler: call RFS.LoadReg call RFS.LoadArgs + b.z rax, zero, .handle_Shutdown b.z rax, Sys.Exit, .handle_Exit - b.z rax, Sys.Shutdown, .handle_Shutdown b.z rax, Sys.FindNext, .handle_FindNext b.z rax, Sys.FindFirst, .handle_FindFirst b.z rax, Sys.OpenFile, .handle_OpenFile @@ -114,19 +114,10 @@ trap0_handler: ; Misc. ; .handle_Shutdown: - mov r12, zero stop .handle_HaltMode: - hlt -.HLT.loop: - pause - pause - pause - - scan rax - b.z rax, zero, .HLT.loop - - prn rax - jmp .HLT.loop + mov rcx, -1 + hlt.rep + stop diff --git a/ka/sys/main.k b/ka/sys/main.k index c445a79..31f4f1d 100644 --- a/ka/sys/main.k +++ b/ka/sys/main.k @@ -2,9 +2,7 @@ ; See the LICENSE file in the project root for more information. PrintBootMsg: - mov rcx, STRLEN_MAX - mov rdx, .bootmsg - prns.rep.nz rdx + call print, .bootmsg ret .bootmsg = "Starting DOS...\n\n" diff --git a/ka/usr/cmd/main.k b/ka/usr/cmd/main.k index e7672c9..18bd01f 100644 --- a/ka/usr/cmd/main.k +++ b/ka/usr/cmd/main.k @@ -123,43 +123,47 @@ main: .builtin_cls = "cls" call strcmp, argv0, .builtin_cls - b.z rax, 0, .handle_CLS + b.z rax, zero, .handle_CLS .builtin_date = "date" call strcmp, argv0, .builtin_date - b.z rax, 0, .handle_DATE + b.z rax, zero, .handle_DATE .builtin_dir = "dir" call strcmp, argv0, .builtin_dir - b.z rax, 0, .handle_DIR + b.z rax, zero, .handle_DIR .builtin_dump = "dump" call strcmp, argv0, .builtin_dump - b.z rax, 0, .handle_DUMP + b.z rax, zero, .handle_DUMP .builtin_echo = "echo" call strcmp, argv0, .builtin_echo - b.z rax, 0, .handle_ECHO + b.z rax, zero, .handle_ECHO .builtin_exit = "exit" call strcmp, argv0, .builtin_exit - b.z rax, 0, .handle_EXIT + b.z rax, zero, .handle_EXIT .builtin_help = "help" call strcmp, argv0, .builtin_help - b.z rax, 0, .handle_HELP + b.z rax, zero, .handle_HELP + +.builtin_halt = "halt" + call strcmp, argv0, .builtin_halt + b.z rax, zero, .handle_HALT .builtin_print = "print" call strcmp, argv0, .builtin_print - b.z rax, 0, .handle_PRINT + b.z rax, zero, .handle_PRINT .builtin_time = "time" call strcmp, argv0, .builtin_time - b.z rax, 0, .handle_TIME + b.z rax, zero, .handle_TIME .builtin_ver = "ver" call strcmp, argv0, .builtin_ver - b.z rax, 0, .handle_VER + b.z rax, zero, .handle_VER jmp .command_not_found @@ -167,7 +171,7 @@ main: ; call builtins ; .handle_CLS: - prn 0xC15000AF + prn PRN_CLEAR jmp .print_prompt .handle_DATE: @@ -209,6 +213,12 @@ main: .handle_EXIT: mov rax, Sys.Shutdown trap 0 + jmp .print_prompt + +.handle_HALT: + mov rax, Sys.EnterHaltMode + trap 0 + jmp .print_prompt .handle_PRINT: mov rax, Sys.OpenFile @@ -266,6 +276,7 @@ main: call print, .helpmsg.echo call print, .helpmsg.exit call print, .helpmsg.help + call print, .helpmsg.halt call print, .helpmsg.print call print, .helpmsg.time call print, .helpmsg.ver @@ -280,6 +291,7 @@ main: .helpmsg.echo = " ECHO Write arguments to standard output\n" .helpmsg.exit = " EXIT Initiate machine shutdown\n" .helpmsg.help = " HELP Display these messages\n" +.helpmsg.halt = " HALT Put processor in halt mode\n" .helpmsg.print = " PRINT Display contents of text file\n" .helpmsg.time = " TIME Display current time of day\n" .helpmsg.ver = " VER Display current COMMAND.COM and DOS kernel versions\n" diff --git a/vm/Makefile b/vm/Makefile index 6aee436..428a06e 100644 --- a/vm/Makefile +++ b/vm/Makefile @@ -6,7 +6,7 @@ verbose ?= yes OBJDIR = ob -FLAGS=-O2 -Wall -fno-builtin-log -I. -Werror=implicit-function-declaration +FLAGS=-O2 -Wall -fno-builtin-log -I. -Werror=implicit-function-declaration -Werror dv_src = $(shell ls dv/*.c) in_src = $(shell ls in/*.c) diff --git a/vm/dv/cpudev.c b/vm/dv/cpudev.c index 66101a2..7377488 100644 --- a/vm/dv/cpudev.c +++ b/vm/dv/cpudev.c @@ -29,19 +29,19 @@ size_t rfs_current_idx = 0; long cpudev_getmaxidx(ctx_t *ctx, dev_t *dev) { - rax = MAX_RFRAME_IDX; + R(RAX) = MAX_RFRAME_IDX; return 0; } long cpudev_getrfusage(ctx_t *ctx, dev_t *dev) { - rax = rfs_used; + R(RAX) = rfs_used; return 0; } long cpudev_getcuridx(ctx_t *ctx, dev_t *dev) { - rax = rfs_current_idx; + R(RAX) = rfs_current_idx; return 0; } @@ -53,12 +53,12 @@ long cpudev_leastavail(ctx_t *ctx, dev_t *dev) { if (rfs[it] == NULL) { - rax = it; + R(RAX) = it; return 0; } } - rax = -1; + R(RAX) = -1; return 0; } @@ -66,24 +66,24 @@ long cpudev_leastavail(ctx_t *ctx, dev_t *dev) long cpudev_isactive(ctx_t *ctx, dev_t *dev) { - CHK_INDEX(ax0); + CHK_INDEX(R(AX0)); - rax = (rfs[ax0] != NULL); + R(RAX) = (rfs[R(AX0)] != NULL); return 0; } long cpudev_activate(ctx_t *ctx, dev_t *dev) { - CHK_INDEX(ax0); + CHK_INDEX(R(AX0)); - if (rfs[ax0] != NULL) + if (rfs[R(AX0)] != NULL) _except(ctx, E_UDF, - "cpudev: activating already activated rframe: #%u", ax0); + "cpudev: activating already activated rframe: #%u", R(AX0)); - rfs[ax0] = calloc(NREGS, sizeof(ulong)); + rfs[R(AX0)] = calloc(NREGS, sizeof(ulong)); - if (rfs[ax0] == 0) + if (rfs[R(AX0)] == 0) return -1; rfs_used++; @@ -93,13 +93,13 @@ long cpudev_activate(ctx_t *ctx, dev_t *dev) long cpudev_deactivate(ctx_t *ctx, dev_t *dev) { - CHK_FRAME(ax0); + CHK_FRAME(R(AX0)); - if (ax0 == 0) + if (R(AX0) == 0) _except(ctx, E_UDF, "cpudev: deactivating rframe #0"); - free(rfs[ax0]); - rfs[ax0] = NULL; + free(rfs[R(AX0)]); + rfs[R(AX0)] = NULL; rfs_used--; assert(rfs_used > 0); @@ -111,41 +111,41 @@ long cpudev_deactivate(ctx_t *ctx, dev_t *dev) long cpudev_copyframe(ctx_t *ctx, dev_t *dev) { - CHK_FRAME(ax0); - CHK_FRAME(ax1); + CHK_FRAME(R(AX0)); + CHK_FRAME(R(AX1)); - if (ax0 == ax1) + if (R(AX0) == R(AX1)) return -1; - memcpy(rfs[ax0], rfs[ax1], NREGS * sizeof(ulong)); + memcpy(rfs[R(AX0)], rfs[R(AX1)], NREGS * sizeof(ulong)); return 0; } long cpudev_moveframe(ctx_t *ctx, dev_t *dev) { - CHK_INDEX(ax0); - CHK_FRAME(ax1); + CHK_INDEX(R(AX0)); + CHK_FRAME(R(AX1)); - if (ax1 == 0) + if (R(AX1) == 0) _except(ctx, E_UDF, "cpudev: trying to move frame #0"); - if (rfs[ax0] != NULL) + if (rfs[R(AX0)] != NULL) _except(ctx, E_UDF, "cpudev: trying to move frame #%u " - "active frame #%u", ax1, ax0); + "active frame #%u", R(AX1), R(AX0)); - rfs[ax0] = rfs[ax1]; - rfs[ax1] = NULL; + rfs[R(AX0)] = rfs[R(AX1)]; + rfs[R(AX1)] = NULL; return 0; } long cpudev_switchframe(ctx_t *ctx, dev_t *dev) { - CHK_FRAME(ax0); + CHK_FRAME(R(AX0)); - rfs_current_idx = ax0; - ctx->rf = rfs[ax0]; + rfs_current_idx = R(AX0); + ctx->rf = rfs[R(AX0)]; return 0; } @@ -154,39 +154,39 @@ long cpudev_switchframe(ctx_t *ctx, dev_t *dev) long cpudev_loadargs(ctx_t *ctx, dev_t *dev) { - CHK_FRAME(ax0); + CHK_FRAME(R(AX0)); - R(AX5) = rfs[ax0][AX5]; - R(AX4) = rfs[ax0][AX4]; - R(AX3) = rfs[ax0][AX3]; - R(AX2) = rfs[ax0][AX2]; - R(AX1) = rfs[ax0][AX1]; - R(AX0) = rfs[ax0][AX0]; + R(AX5) = rfs[R(AX0)][AX5]; + R(AX4) = rfs[R(AX0)][AX4]; + R(AX3) = rfs[R(AX0)][AX3]; + R(AX2) = rfs[R(AX0)][AX2]; + R(AX1) = rfs[R(AX0)][AX1]; + R(AX0) = rfs[R(AX0)][AX0]; return 0; } long cpudev_loadreg(ctx_t *ctx, dev_t *dev) { - CHK_FRAME(ax0); + CHK_FRAME(R(AX0)); - if ((ushort)ax1 >= NREGS || ax1 == RZX) + if ((ushort)R(AX1) >= NREGS || R(AX1) == RZX) _except(ctx, E_UDF, - "cpudev: register invalid or index out of range: #%u", ax1); + "cpudev: register invalid or index out of range: #%u", R(AX1)); - R(RAX) = rfs[ax0][ax1]; + R(RAX) = rfs[R(AX0)][R(AX1)]; return 0; } long cpudev_storereg(ctx_t *ctx, dev_t *dev) { - CHK_FRAME(ax0); + CHK_FRAME(R(AX0)); - if ((ushort)ax1 >= NREGS) - _except(ctx, E_UDF, "cpudev: register index out of range: #%u", ax1); + if ((ushort)R(AX1) >= NREGS) + _except(ctx, E_UDF, "cpudev: register index out of range: #%u", R(AX1)); - rfs[ax0][ax1] = R(AX2); + rfs[R(AX0)][R(AX1)] = R(AX2); return 0; } @@ -204,40 +204,40 @@ bool idt_handling[IDT_SLOTS] = { 0 }; // a handler is already running long cpudev_idtadd(ctx_t *ctx, dev_t *dev) { - CHK_FRAME(ax1); - CHK_IDT_INDEX(ax0); + CHK_FRAME(R(AX1)); + CHK_IDT_INDEX(R(AX0)); - if (idt[ax0] != 0) - _except(ctx, E_UDF, "cpudev: IDT slot index already in use: #%u", ax0); + if (idt[R(AX0)] != 0) + _except(ctx, E_UDF, "cpudev: IDT slot index already in use: #%u", R(AX0)); - assert(idt_handling[ax0] == 0); + assert(idt_handling[R(AX0)] == 0); - idt[ax0] = ax1; + idt[R(AX0)] = R(AX1); return 0; } long cpudev_idtdel(ctx_t *ctx, dev_t *dev) { - CHK_IDT_INDEX(ax0); + CHK_IDT_INDEX(R(AX0)); - if (idt[ax0] == 0) - _except(ctx, E_UDF, "cpudev: IDT slot index not in use: #%u", ax0); + if (idt[R(AX0)] == 0) + _except(ctx, E_UDF, "cpudev: IDT slot index not in use: #%u", R(AX0)); - idt[ax0] = 0; - idt_handling[ax0] = 0; + idt[R(AX0)] = 0; + idt_handling[R(AX0)] = 0; return 0; } long cpudev_idtquery(ctx_t *ctx, dev_t *dev) { - if (ax0 >= IDT_SLOTS || idt[ax0] == 0) - rax = rdx = 0; + if (R(AX0) >= IDT_SLOTS || idt[R(AX0)] == 0) + R(RAX) = R(RDX) = 0; else { - rax = 1; - rdx = idt[ax0]; + R(RAX) = 1; + R(RDX) = idt[R(AX0)]; } return 0; @@ -245,12 +245,12 @@ long cpudev_idtquery(ctx_t *ctx, dev_t *dev) long cpudev_idtdone(ctx_t *ctx, dev_t *dev) { - CHK_IDT_INDEX(ax0); + CHK_IDT_INDEX(R(AX0)); - if (idt_handling[ax0] == 0) - _except(ctx, E_UDF, "cpudev: idtdone, not handling E/I #%u", ax0); + if (idt_handling[R(AX0)] == 0) + _except(ctx, E_UDF, "cpudev: idtdone, not handling E/I #%u", R(AX0)); - idt_handling[ax0]--; + idt_handling[R(AX0)]--; return 0; } diff --git a/vm/dv/diskdev.c b/vm/dv/diskdev.c index 1dbfaa0..ba5e88f 100644 --- a/vm/dv/diskdev.c +++ b/vm/dv/diskdev.c @@ -41,7 +41,7 @@ long diskdev_findnext(ctx_t *ctx, dev_t *dev) if (ent == NULL) { - rax = 0; + R(RAX) = 0; return 0; } @@ -51,18 +51,18 @@ long diskdev_findnext(ctx_t *ctx, dev_t *dev) break; } - rax = writestr(ctx, ax0, ax1, ent->d_name); + R(RAX) = writestr(ctx, R(AX0), R(AX1), ent->d_name); snprintf(name, NAME_MAX+4, "fs/%s", ent->d_name); if (stat(name, &st) < 0) { perror("diskdev: couldn't stat file in directory: "); - rdx = -1; + R(RDX) = -1; } else - rdx = st.st_size; + R(RDX) = st.st_size; return 0; } @@ -85,7 +85,7 @@ long diskdev_open(ctx_t *ctx, dev_t *dev) int fd, tmp; char buf[NAME_MAX+4] = { 'f', 's', '/', 0 }; - readstr(ctx, ax0, NAME_MAX, buf+3); + readstr(ctx, R(AX0), NAME_MAX, buf+3); for (fd = 0; fd < MAXOPEN; fd++) if (disk->table[fd] == 0) @@ -103,7 +103,7 @@ long diskdev_open(ctx_t *ctx, dev_t *dev) } disk->table[fd] = tmp; - rax = fd; + R(RAX) = fd; return 0; } @@ -112,13 +112,13 @@ long diskdev_close(ctx_t *ctx, dev_t *dev) { GETDISK(); - if (ax0 >= MAXOPEN) + if (R(AX0) >= MAXOPEN) return -1; - if (disk->table[ax0] <= 0) + if (disk->table[R(AX0)] <= 0) return -1; - close(disk->table[ax0]); + close(disk->table[R(AX0)]); return 0; } @@ -129,7 +129,7 @@ long diskdev_read(ctx_t *ctx, dev_t *dev) { GETDISK(); - if (ax0 >= MAXOPEN || disk->table[ax0] <= 0 || R(AX2) >= MAXRW) + if (R(AX0) >= MAXOPEN || disk->table[R(AX0)] <= 0 || R(AX2) >= MAXRW) return -1; int ret; @@ -138,7 +138,7 @@ long diskdev_read(ctx_t *ctx, dev_t *dev) if (buf == NULL) return -1; - ret = read(disk->table[ax0], buf, R(AX2)); + ret = read(disk->table[R(AX0)], buf, R(AX2)); if (ret < 0) { @@ -146,12 +146,11 @@ long diskdev_read(ctx_t *ctx, dev_t *dev) return -1; } - rax = ret; + R(RAX) = ret; // Xxx dedicated function & faster copy - for (; ret; ret--, ax1++, buf++) - writemem(ctx, *buf, ax1, 1); - + for (; ret; ret--, R(AX1)++, buf++) + writemem(ctx, *buf, R(AX1), 1); return 0; } diff --git a/vm/dv/memdev.c b/vm/dv/memdev.c index 6b5d510..39625e6 100644 --- a/vm/dv/memdev.c +++ b/vm/dv/memdev.c @@ -5,14 +5,14 @@ long memdev_getmemoff(ctx_t *ctx, dev_t *dev) { - rax = MEMOFF; + R(RAX) = MEMOFF; return 0; } long memdev_getmemsize(ctx_t *ctx, dev_t *dev) { - rax = ctx->mz; + R(RAX) = ctx->mz; return 0; } diff --git a/vm/in/ALU b/vm/in/ALU index 9282191..765eacc 100644 --- a/vm/in/ALU +++ b/vm/in/ALU @@ -61,7 +61,7 @@ sar r r ri # # CMP Comparison instruction # -# $1 - $2 +# SignExtend($1) - $2 # # Sets CF if unsigned integer overflow occur, clears it otherwise # Sets OF is signed integer overflow occur, clears it otherwise diff --git a/vm/in/INSTRS b/vm/in/INSTRS index 29e4089..899bbe3 100644 --- a/vm/in/INSTRS +++ b/vm/in/INSTRS @@ -3,7 +3,7 @@ include "SUPER" include "ALU" -include "MOV" +include "MEM" include "MISC" include "STRING" diff --git a/vm/in/MOV b/vm/in/MEM similarity index 91% rename from vm/in/MOV rename to vm/in/MEM index 9d94547..b5bc40e 100644 --- a/vm/in/MOV +++ b/vm/in/MEM @@ -25,7 +25,7 @@ loop ri # # Conditional absolute jumps (B) # -# COMPARE($1, $2) +# COMPARE(SignExtend($1), $2) # # IF (COND) THEN # RIP = $3 @@ -114,28 +114,28 @@ pop r lea r m # -# Movement with sign-extension (MOV) instruction +# Move data (MOV) instruction # -# $1 = $2 +# $1 = SignExtend($2) # mov r rim mov m ri # -# Movement with sign-extension (MOVSXx) instruction +# Load from memory with zero-extension (MOVSX/MOVZX) instruction +# +# $1 = ZeroExtend($2) +# +movzx r m + +# +# Move with sign-extension (MOVSXx) instruction # # $1 = SignExtend($2 & (2^(8 * sizeof(x)) - 1) # movsxb r r movsxw r r -movsxl r r - -# -# Movement with zero-extension (MOVZX) instruction -# -# $1 = ZeroExtend($2) -# -movzx r m +movsxd r r # # Exchange (XCHG) instruction diff --git a/vm/in/STRING b/vm/in/STRING index 3fa33ff..f2f7be0 100644 --- a/vm/in/STRING +++ b/vm/in/STRING @@ -17,7 +17,7 @@ # stosb r ri stosw r ri -stosl r ri +stosd r ri stosq r ri # @@ -44,7 +44,7 @@ stosq r ri # scasb r ri scasw r ri -scasl r ri +scasd r ri scasq r ri #---------------------------------------------------------------------------# diff --git a/vm/in/alu.c b/vm/in/alu.c index d68db41..cd5cd8c 100644 --- a/vm/in/alu.c +++ b/vm/in/alu.c @@ -8,47 +8,66 @@ //----------------------------------------------------------------------------// -IMPL_START_3(or) { v1 = v2 | v3; } IMPL_OUT; -IMPL_START_3(and) { v1 = v2 & v3; } IMPL_OUT; -IMPL_START_3(xor) { v1 = v2 ^ v3; } IMPL_OUT; +IMPL_START(or) { *r1 = p2->val | p3->val; return 1; } +IMPL_START(and) { *r1 = p2->val & p3->val; return 1; } +IMPL_START(xor) { *r1 = p2->val ^ p3->val; return 1; } //----------------------------------------------------------------------------// -IMPL_START_3(shl) { v1 = v2 << v3; } IMPL_OUT; -IMPL_START_3(shr) { v1 = v2 >> v3; } IMPL_OUT; -IMPL_START_3(sal) { v1 = (ulong)((long)v2 << (long)v3); } IMPL_OUT; -IMPL_START_3(sar) { v1 = (ulong)((long)v2 >> (long)v3); } IMPL_OUT; +IMPL_START(shl) { *r1 = p2->val << p3->val; return 1; } +IMPL_START(shr) { *r1 = p2->val >> p3->val; return 1; } +IMPL_START(sal) { *r1 = (ulong)((long)p2->val << (long)p3->val); return 1; } +IMPL_START(sar) { *r1 = (ulong)((long)p2->val >> (long)p3->val); return 1; } //----------------------------------------------------------------------------// -IMPL_START_3(add) { v1 = v2 + v3; } IMPL_OUT; -IMPL_START_3(addf) { COMPARE_ADD(v2, v3); v1 = v2 + v3; } IMPL_OUT; +IMPL_START(add) { *r1 = p2->val + p3->val; return 1; } +IMPL_START(addf) { COMPARE_ADD(p2->val, p3->val); *r1 = p2->val + p3->val; return 1; } + +IMPL_START(sub) { *r1 = p2->val - p3->val; return 1; } +IMPL_START(subf) { COMPARE_SUB(p2->val, p3->val); *r1 = p2->val - p3->val; return 1; } + +IMPL_START(adcx) +{ + p3->val += !!(R(RFX)&CF); + COMPARE_ADD(p2->val, p3->val); + *r1 = p2->val + p3->val; + + return 1; +} + +IMPL_START(sbbx) +{ + p3->val += !!(R(RFX)&CF); + COMPARE_SUB(p2->val, p3->val); + *r1 = p2->val - p3->val; + + return 1; +} //----------------------------------------------------------------------------// -IMPL_START_2(cmp) { COMPARE_SUB(v1, v2); } IMPL_END; -IMPL_START_3(sub) { v1 = v2 - v3; } IMPL_OUT; -IMPL_START_3(subf){ COMPARE_SUB(v2, v3); v1 = v2 - v3; } IMPL_OUT; +IMPL_START(mul) { *r1 = p2->val * p3->val; return 1; } +IMPL_START(rem) { *r1 = p2->val % p3->val; return 1; } -//----------------------------------------------------------------------------// - -IMPL_START_3(adcx) { v3 += !!(R(RFX)&CF); COMPARE_ADD(v2, v3); v1 = v2 + v3; } IMPL_OUT; -IMPL_START_3(sbbx) { v3 += !!(R(RFX)&CF); COMPARE_SUB(v2, v3); v1 = v2 - v3; } IMPL_OUT; - -//----------------------------------------------------------------------------// - -IMPL_START_3(mul) { v1 = v2 * v3; } IMPL_OUT; -IMPL_START_3(rem) { v1 = v2 % v3; } IMPL_OUT; -IMPL_START_3(div) { - if (!v3) +IMPL_START(div) +{ + if (!p3->val) _except(ctx, E_DIV, "DIV by 0"); - v1 = v2 / v3; -} IMPL_OUT; -IMPL_START_3(idiv) { - if (!v3) + *r1 = p2->val / p3->val; + + return 1; +} + +IMPL_START(idiv) +{ + if (!p3->val) _except(ctx, E_DIV, "IDIV by 0"); - v1 = (ulong)((long)v2/(long)v3); -} IMPL_OUT; + + *r1 = (ulong)((long)p2->val/(long)p3->val); + + return 1; +} //----------------------------------------------------------------------------// @@ -60,13 +79,20 @@ static void __unsigned_multiply128(ulong u, ulong v, ulong *hi, ulong *lo) *lo = r; } -IMPL_START_3(mulhi) { __unsigned_multiply128(v2, v3, &v1, &v2); } IMPL_OUT_2; +IMPL_START(mulhi) +{ + __unsigned_multiply128(p2->val, p3->val, r1, r2); + return 2; +} -IMPL_START_3(mulf) { +IMPL_START(mulf) +{ ulong tmp; - __unsigned_multiply128(v2, v3, &tmp, &v1); - R(RFX) = v2 ? (R(RFX)|CF|OF) : R(RFX)&~(CF|OF); -} IMPL_OUT; + __unsigned_multiply128(p2->val, p3->val, &tmp, r1); + R(RFX) = p2->val ? (R(RFX)|CF|OF) : R(RFX)&~(CF|OF); + + return 1; +} //----------------------------------------------------------------------------// @@ -78,7 +104,11 @@ static void __signed_multiply128(ulong u, ulong v, ulong *hi, ulong *lo) *lo = r; } -IMPL_START_3(imulhi) { __signed_multiply128(v2, v3, &v1, &v2); } IMPL_OUT_2; +IMPL_START(imulhi) +{ + __signed_multiply128(p2->val, p3->val, r1, r2); + return 2; +} //----------------------------------------------------------------------------// diff --git a/vm/in/instrs.h b/vm/in/instrs.h index c52e564..e21beb5 100644 --- a/vm/in/instrs.h +++ b/vm/in/instrs.h @@ -5,80 +5,9 @@ //----------------------------------------------------------------------------// -#define DECV(v, p) \ - ulong v; \ - GETV(v, p) - -#define GETV(v, p) \ - if (ACC_FMT_IS_MEM(p->type)) \ - v = readmem(ctx, p->addr, p->mlen); \ - else v = p->val - -#define DECVZX(v, p) \ - ulong v; \ - GETVZX(v, p) - -#define GETVZX(v, p) \ - if (ACC_FMT_IS_MEM(p->type)) \ - v = readmemzx(ctx, p->addr, p->mlen); \ - else v = p->val - -//----------------------------------------------------------------------------// - -#define IMPL_START_0(name) \ +#define IMPL_START(name) \ uint i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, acc_t *p3, \ ulong *r1, ulong *r2, ulong *r3) \ -{ - -#define IMPL_START_1(name) \ -IMPL_START_0(name) \ - DECV(v1, p1); - -#define IMPL_START_X_NOIN(name) \ -IMPL_START_0(name) \ - ulong v1, v2, v3; \ - (void)v1; (void)v2; (void)v3; - -#define IMPL_START_2(name) \ -IMPL_START_1(name) \ - DECV(v2, p2); - -#define IMPL_START_2_ONLY(name) \ -IMPL_START_0(name) \ - ulong v1; \ - DECV(v2, p2); - -#define IMPL_START_3(name) \ -IMPL_START_2(name) \ - DECV(v3, p3); - -//----------------------------------------------------------------------------// - -#define IMPL_END \ - return 0; \ -} - -#define IMPL_OUT \ - *r1 = v1; \ - return 1; \ -} - -#define IMPL_OUT_ZSF \ - SET_ZSF(v1); \ - IMPL_OUT - -#define IMPL_OUT_2 \ - *r1 = v1; \ - *r2 = v2; \ - return 2; \ -} - -#define IMPL_OUT_3 \ - *r1 = v1; \ - *r2 = v2; \ - *r3 = v3; \ - return 3; \ -} //----------------------------------------------------------------------------// @@ -100,11 +29,6 @@ IMPL_START_2(name) \ SET_ZF(v); \ SET_SF(v) -#define SET_ZSPF(v) \ - SET_ZF(v); \ - SET_SF(v); \ - SET_PF(v) - //----------------------------------------------------------------------------// #define COMPARE_ADD(v1, v2) \ diff --git a/vm/in/mem.c b/vm/in/mem.c new file mode 100644 index 0000000..13c1f92 --- /dev/null +++ b/vm/in/mem.c @@ -0,0 +1,166 @@ +// The OS/K Team licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include + +//----------------------------------------------------------------------------// + +IMPL_START(jmp) { R(RIP) = p1->val; return 0; } + +IMPL_START(loop) { + if (R(RCX) > 0) { + R(RCX)--; + R(RIP) = p1->val; + } + return 0; +} + +IMPL_START(b) +{ + ulong v; + + if (ACC_FMT_IS_MEM(p1->type)) + v = readmemsx(ctx, p1->addr, p1->mlen); + + else v = p1->val; + + COMPARE_SUB(v, p2->val); + + if (eval_cond(ctx, ctx->cond)) + R(RIP) = p3->val; + + return 0; +} + +IMPL_START(cmp) +{ + ulong v; + + if (ACC_FMT_IS_MEM(p1->type)) + v = readmemsx(ctx, p1->addr, p1->mlen); + + else v = p1->val; + + COMPARE_SUB(v, p2->val); + + return 0; +} + +//----------------------------------------------------------------------------// + +IMPL_START(lea) { *r1 = p2->addr; return 1; } + +IMPL_START(mov) +{ + if (ACC_FMT_IS_MEM(p2->type)) + *r1 = readmemsx(ctx, p2->addr, p2->mlen); + + else *r1 = p2->val; + + return 1; +} + +IMPL_START(movzx) +{ + if (ACC_FMT_IS_MEM(p2->type)) + { + if (__builtin_expect(p2->mlen == 8, 0)) + _except(ctx, E_ILL, "MOVZX with qword memory source"); + + *r1 = readmemzx(ctx, p2->addr, p2->mlen); + } + + else *r1 = p2->val; + + return 1; +} + +IMPL_START(movsxb) { *r1 = (ulong)(long)(char)(p2->val & 0xFF); return 1; } +IMPL_START(movsxw) { *r1 = (ulong)(long)(short)(p2->val & 0xFFFF); return 1; } +IMPL_START(movsxd) { *r1 = (ulong)(long)(int)(p2->val & 0xFFFFFFFF); return 1; } + +IMPL_START(xchg) +{ + *r2 = p1->val; + + if (ACC_FMT_IS_MEM(p2->type)) + *r1 = readmemsx(ctx, p2->addr, p2->mlen); + + else *r1 = p2->val; + + return 2; +} + +//----------------------------------------------------------------------------// + +// +// Stack manipulation instructions +// + +IMPL_START(push) +{ + ulong v; + + if (ACC_FMT_IS_MEM(p1->type)) + v = readmemzx(ctx, p1->addr, p1->mlen); + + else v = p1->val; + + R(RSP) -= 8; + writemem(ctx, v, R(RSP), 8); + + return 0; +} + +IMPL_START(pop) +{ + *r1 = readmemzx(ctx, R(RSP), 8); + R(RSP) += 8; + + return 1; +} + +IMPL_START(call) +{ + R(RSP) -= 8; + writemem(ctx, R(RIP), R(RSP), 8); + R(RIP) = p1->val; + + if (p2) + { + R(AX0) = p2->val; + + if (p3) + R(AX1) = p3->val; + } + + return 0; +} + +IMPL_START(ret) +{ + R(RIP) = readmemzx(ctx, R(RSP), 8); + R(RSP) += 8; + + return 0; +} + +IMPL_START(enter) +{ + writemem(ctx, R(RBP), R(RSP) - 8, 8); + R(RBP) = R(RSP) - 8; + R(RSP) -= (p1->val + 1) * 8; + + return 0; +} + +IMPL_START(leave) +{ + R(RSP) = R(RBP) + 8; + R(RBP) = readmemzx(ctx, R(RBP), 8); + + return 0; +} + +//----------------------------------------------------------------------------// + diff --git a/vm/in/misc.c b/vm/in/misc.c index a06fde6..5925472 100644 --- a/vm/in/misc.c +++ b/vm/in/misc.c @@ -9,12 +9,12 @@ //----------------------------------------------------------------------------// -IMPL_START_0(into) { INTO(); } IMPL_END; -IMPL_START_0(pause) { usleep(5000); } IMPL_END; +IMPL_START(into) { INTO(); return 0; } +IMPL_START(pause) { usleep(5000); return 0; } //----------------------------------------------------------------------------// -IMPL_START_0(break) +IMPL_START(break) { #ifndef NDEBUG trace("\nExecuting BREAK INSTR\n"); @@ -24,107 +24,116 @@ IMPL_START_0(break) trace("Resuming execution\n"); #endif + return 0; } -IMPL_END; -IMPL_START_0(dump) +IMPL_START(dump) { #ifndef NDEBUG if (ctx->dumpsw) - trace("0x%lX:\t...\n", rpc); + trace("0x%lX:\t...\n", ctx->cur_pc); else if (!ctx->dumpsw) dump_instr(ctx, ctx->cur_in, p1, p2, p3, 0, 0); ctx->dumpsw = !ctx->dumpsw; #endif + return 0; } -IMPL_END; //----------------------------------------------------------------------------// -IMPL_START_X_NOIN(ytime) +IMPL_START(ytime) { time_t t = time(NULL); struct tm *tm = localtime(&t); - v1 = tm->tm_sec + tm->tm_min * 60 + *r1 = tm->tm_sec + tm->tm_min * 60 + tm->tm_hour * 60 * 60 + tm->tm_mday * 60 * 60 * 24; - v2 = tm->tm_mon; - v3 = tm->tm_year + 1900; -} -IMPL_OUT_3; + *r2 = tm->tm_mon; + *r3 = tm->tm_year + 1900; -IMPL_START_1(utime) + return 3; +} + +IMPL_START(utime) { struct timeval time; gettimeofday(&time, NULL); - v1 = (time.tv_sec * 1000) + (time.tv_usec / 1000); + *r1 = (time.tv_sec * 1000) + (time.tv_usec / 1000); + + return 1; } -IMPL_OUT; //----------------------------------------------------------------------------// -IMPL_START_0(cls) { +IMPL_START(cls) +{ R(RFX) = 0; for (int i = RAX; i <= R20; i++) R(i) = 0; -} IMPL_END; + + return 0; +} //----------------------------------------------------------------------------// -IMPL_START_2(bswap) +IMPL_START(bswap) { - v1 = ((v2 & 0xFF00000000000000) >> 56) - | ((v2 & 0x00FF000000000000) >> 40) - | ((v2 & 0x0000FF0000000000) >> 24) - | ((v2 & 0x000000FF00000000) >> 8) - | ((v2 & 0x00000000FF000000) << 8) - | ((v2 & 0x0000000000FF0000) << 24) - | ((v2 & 0x000000000000FF00) << 40) - | ((v2 & 0x00000000000000FF) << 56); -} -IMPL_OUT; + ulong v = p2->val; -IMPL_START_2(wswap) -{ - v1 = ((v2 & 0xFFFF000000000000) >> 48) - | ((v2 & 0x0000FFFF00000000) >> 16) - | ((v2 & 0x00000000FFFF0000) << 16) - | ((v2 & 0x000000000000FFFF) << 48); -} -IMPL_OUT; + *r1 = ((v & 0xFF00000000000000) >> 56) + | ((v & 0x00FF000000000000) >> 40) + | ((v & 0x0000FF0000000000) >> 24) + | ((v & 0x000000FF00000000) >> 8) + | ((v & 0x00000000FF000000) << 8) + | ((v & 0x0000000000FF0000) << 24) + | ((v & 0x000000000000FF00) << 40) + | ((v & 0x00000000000000FF) << 56); -IMPL_START_2(dswap) -{ - v1 = ((v2 & 0xFFFFFFFF00000000) >> 32) - | ((v2 & 0x00000000FFFFFFFF) << 32); + return 1; +} + +IMPL_START(wswap) +{ + ulong v = p2->val; + + *r1 = ((v & 0xFFFF000000000000) >> 48) + | ((v & 0x0000FFFF00000000) >> 16) + | ((v & 0x00000000FFFF0000) << 16) + | ((v & 0x000000000000FFFF) << 48); + + return 1; +} + +IMPL_START(dswap) +{ + *r1 = ((p2->val & 0xFFFFFFFF00000000) >> 32) + | ((p2->val & 0x00000000FFFFFFFF) << 32); + + return 1; } -IMPL_OUT; //----------------------------------------------------------------------------// -IMPL_START_0(prn) +#define PRN_CLEAR_MAGIC 0x8BF00001 + +IMPL_START(prn) { - DECVZX(v1, p1); + ulong v = p1->val; // Magic value? :) - if (__builtin_expect(v1 == 0xC15000AF, 0)) + if (__builtin_expect(v == PRN_CLEAR_MAGIC, 0)) console_clear(ctx); - else - { - if (p1->mlen > 1) { - trace("prn warning: large access size\n"); - } - if (v1 > 0) - console_putc(ctx, (char)v1); - } -} -IMPL_END + else if (v > 0) + console_putc(ctx, (char)v); -IMPL_START_0(prns) + return 0; +} + +IMPL_START(prns) { uchar ch = readmemzx(ctx, R(p1->reg), 1); @@ -139,14 +148,16 @@ IMPL_START_0(prns) else R(p1->reg)++; } -} -IMPL_END -IMPL_START_X_NOIN(scan) -{ - v1 = console_scankeybuf(ctx); + return 0; +} + +IMPL_START(scan) +{ + *r1 = console_scankeybuf(ctx); + + return 1; } -IMPL_OUT; //----------------------------------------------------------------------------// diff --git a/vm/in/mov.c b/vm/in/mov.c deleted file mode 100644 index 10b524b..0000000 --- a/vm/in/mov.c +++ /dev/null @@ -1,97 +0,0 @@ -// The OS/K Team licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -#include - -//----------------------------------------------------------------------------// - -IMPL_START_1(jmp) { R(RIP) = v1; } IMPL_END; -IMPL_START_1(loop) { - if (R(RCX) > 0) { - R(RCX)--; - R(RIP) = v1; - } -} -IMPL_END; - -IMPL_START_3(b) { - COMPARE_SUB(v1, v2); - - if (eval_cond(ctx, ctx->cond)) - R(RIP) = v3; -} -IMPL_END; - -//----------------------------------------------------------------------------// - -IMPL_START_X_NOIN(lea) { v1 = p2->addr; } IMPL_OUT; -IMPL_START_2_ONLY(mov) { v1 = v2; } IMPL_OUT; - -IMPL_START_2_ONLY(movsxb) { v1 = (ulong)(long)(char)(v2 & 0xFF); }IMPL_OUT; -IMPL_START_2_ONLY(movsxw) { v1 = (ulong)(long)(short)(v2 & 0xFFFF); }IMPL_OUT; -IMPL_START_2_ONLY(movsxl) { v1 = (ulong)(long)(int)(v2 & 0xFFFFFFFF); }IMPL_OUT; - -IMPL_START_X_NOIN(movzx) { DECVZX(v2, p2); v1 = v2; } IMPL_OUT; - -IMPL_START_2(xchg) { ulong t = v1; v1 = v2; v2 = t; } IMPL_OUT_2; - -//----------------------------------------------------------------------------// - -// -// Stack manipulation instructions -// - -IMPL_START_1(push) { - R(RSP) -= 8; - writemem(ctx, v1, R(RSP), 8); -} IMPL_END; - -IMPL_START_1(pop) { - v1 = readmem(ctx, R(RSP), 8); - R(RSP) += 8; -} IMPL_OUT; - -/* -IMPL_START_1(call) { - R(RSP) -= 8; - writemem(ctx, R(RIP), R(RSP), 8); - R(RIP) = v1; -} IMPL_END; -*/ - -IMPL_START_1(call) { - R(RSP) -= 8; - writemem(ctx, R(RIP), R(RSP), 8); - R(RIP) = v1; - - if (p2) - { - DECV(v2, p2); - ax0 = v2; - - if (p3) - { - DECV(v3, p3); - ax1 = v3; - } - } - -} IMPL_END; - -IMPL_START_0(ret) { - R(RIP) = readmem(ctx, R(RSP), 8); R(RSP) += 8; -} IMPL_END; - -IMPL_START_1(enter) { - writemem(ctx, R(RBP), R(RSP) - 8, 8); - R(RBP) = R(RSP) - 8; - R(RSP) -= (v1 + 1) * 8; -} IMPL_END; - -IMPL_START_0(leave) { - R(RSP) = R(RBP) + 8; - R(RBP) = readmem(ctx, R(RBP), 8); -} IMPL_END; - -//----------------------------------------------------------------------------// - diff --git a/vm/in/string.c b/vm/in/string.c index edc850d..ca10056 100644 --- a/vm/in/string.c +++ b/vm/in/string.c @@ -13,24 +13,21 @@ static void stos_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len) { - DECV(v2, p2); - writemem(ctx, v2, R(p1->reg), len); + writemem(ctx, p2->val, R(p1->reg), len); STR_MOVE(p1->reg, len); } -IMPL_START_0(stosb) { stos_impl(ctx, p1, p2, 1); } IMPL_END; -IMPL_START_0(stosw) { stos_impl(ctx, p1, p2, 2); } IMPL_END; -IMPL_START_0(stosl) { stos_impl(ctx, p1, p2, 4); } IMPL_END; -IMPL_START_0(stosq) { stos_impl(ctx, p1, p2, 8); } IMPL_END; +IMPL_START(stosb) { stos_impl(ctx, p1, p2, 1); return 0; } +IMPL_START(stosw) { stos_impl(ctx, p1, p2, 2); return 0; } +IMPL_START(stosd) { stos_impl(ctx, p1, p2, 4); return 0; } +IMPL_START(stosq) { stos_impl(ctx, p1, p2, 8); return 0; } //----------------------------------------------------------------------------// static void scas_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len) { - DECV(v2, p2); - - ulong x = readmem(ctx, R(p1->reg), len); - COMPARE_SUB(x, v2); + ulong x = readmemsx(ctx, R(p1->reg), len); + COMPARE_SUB(x, p2->val); if (x == 0) { R(RFX) |= ZF; @@ -41,28 +38,10 @@ static void scas_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len) } } -IMPL_START_0(scasb) { scas_impl(ctx, p1, p2, 1); } IMPL_END; -IMPL_START_0(scasw) { scas_impl(ctx, p1, p2, 2); } IMPL_END; -IMPL_START_0(scasl) { scas_impl(ctx, p1, p2, 4); } IMPL_END; -IMPL_START_0(scasq) { scas_impl(ctx, p1, p2, 8); } IMPL_END; - -//----------------------------------------------------------------------------// - -static void movs_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len) -{ - ulong x = readmem(ctx, R(p2->reg), len); - writemem(ctx, x, R(p1->reg), len); - - R(RFX) = (x == 0 ? R(RFX)|ZF : R(RFX)&~ZF); - - STR_MOVE(p1->reg, len); - STR_MOVE(p2->reg, len); -} - -IMPL_START_0(movsb) { movs_impl(ctx, p1, p2, 1); } IMPL_END; -IMPL_START_0(movsw) { movs_impl(ctx, p1, p2, 2); } IMPL_END; -IMPL_START_0(movsl) { movs_impl(ctx, p1, p2, 4); } IMPL_END; -IMPL_START_0(movsq) { movs_impl(ctx, p1, p2, 8); } IMPL_END; +IMPL_START(scasb) { scas_impl(ctx, p1, p2, 1); return 0; } +IMPL_START(scasw) { scas_impl(ctx, p1, p2, 2); return 0; } +IMPL_START(scasd) { scas_impl(ctx, p1, p2, 4); return 0; } +IMPL_START(scasq) { scas_impl(ctx, p1, p2, 8); return 0; } //----------------------------------------------------------------------------// diff --git a/vm/in/super.c b/vm/in/super.c index a44b0dc..5b6576d 100644 --- a/vm/in/super.c +++ b/vm/in/super.c @@ -31,19 +31,20 @@ void do_hlt(ctx_t *ctx) //----------------------------------------------------------------------------// -IMPL_START_0(hlt) { CHK_SUPERV(); do_hlt(ctx); } IMPL_END; -IMPL_START_0(stop) { CHK_SUPERV(); _except(ctx, E_SHT, "STOP INSTR"); } IMPL_END; -IMPL_START_0(crash) { CHK_SUPERV(); _except(ctx, 1023, "CRASH instruction"); } IMPL_END; +IMPL_START(hlt) { CHK_SUPERV(); do_hlt(ctx); return 0; } +IMPL_START(stop) { CHK_SUPERV(); _except(ctx, E_SHT, "STOP INSTR"); } +IMPL_START(crash) { CHK_SUPERV(); _except(ctx, 1023, "CRASH instruction"); } //----------------------------------------------------------------------------// -IMPL_START_1(trap) { - if (v1 > 255) _except(ctx, E_ILL, "TRAP number greater than 255"); - _except(ctx, v1 + 256, "TRAP instruction"); -} IMPL_END; +IMPL_START(trap) +{ + if (p1->val > 255) _except(ctx, E_ILL, "TRAP number greater than 255"); + _except(ctx, p1->val + 256, "TRAP instruction"); +} -IMPL_START_0(iret) { +IMPL_START(iret) { if (ctx->dumpsw) trace("\nReturning from exception #%ld\n\n", R(R13)); @@ -51,66 +52,69 @@ IMPL_START_0(iret) { R(RIP) = R(R15); rfs_current_idx = R(R14); ctx->rf = rfs[R(R14)]; -} -IMPL_END; -IMPL_START_0(cli) { CHK_SUPERV(); R(CR0) &= ~IF; } IMPL_END; -IMPL_START_0(sti) { CHK_SUPERV(); R(CR0) |= IF; } IMPL_END; + return 0; +} + +IMPL_START(cli) { CHK_SUPERV(); R(CR0) &= ~IF; return 0; } +IMPL_START(sti) { CHK_SUPERV(); R(CR0) |= IF; return 0; } //----------------------------------------------------------------------------// // // code common to devctl and iocall // -dev_t *devctl_common(ctx_t *ctx, ulong v1, ulong v2) +dev_t *devctl_common(ctx_t *ctx, ulong idx) { - dev_t *dev = devget(ctx, v1); + dev_t *dev = devget(ctx, idx); - if (!dev) rax = -2; - else if (dev->state == DEVPWOF) rax = -3; - else if (dev->state == DEVFERR) rax = -4; - else if (dev->state == DEVPLUG) rax = -5; + if (!dev) R(RAX) = -2; + else if (dev->state == DEVPWOF) R(RAX) = -3; + else if (dev->state == DEVFERR) R(RAX) = -4; + else if (dev->state == DEVPLUG) R(RAX) = -5; else return dev; return NULL; } -IMPL_START_2(devctl) +IMPL_START(devctl) { CHK_SUPERV(); - dev_t *dev = devctl_common(ctx, v1, v2); + dev_t *dev = devctl_common(ctx, p1->val); if (dev == NULL) return 0; - switch (v2) { - case 0: writestr(ctx, ax0, DEVLEN, dev->type); break; - case 1: writestr(ctx, ax0, DEVLEN, dev->name); break; - case 2: writestr(ctx, ax0, DEVLEN, dev->modl); break; - case 3: writestr(ctx, ax0, DEVLEN, dev->vend); break; - case 4: rax = dev->major; rdx = dev->minor; break; - case 5: rax = dev->feats; rdx = dev->revis; break; - default: rax = -6; break; + switch (p2->val) { + case 0: writestr(ctx, R(AX0), DEVLEN, dev->type); break; + case 1: writestr(ctx, R(AX0), DEVLEN, dev->name); break; + case 2: writestr(ctx, R(AX0), DEVLEN, dev->modl); break; + case 3: writestr(ctx, R(AX0), DEVLEN, dev->vend); break; + case 4: R(RAX) = dev->major; R(RDX) = dev->minor; break; + case 5: R(RAX) = dev->feats; R(RDX) = dev->revis; break; + default: R(RAX) = -6; break; } -} -IMPL_END; -IMPL_START_2(iocall) + return 0; +} + +IMPL_START(iocall) { CHK_SUPERV(); long rc; - dev_t *dev = devctl_common(ctx, v1, v2); + dev_t *dev = devctl_common(ctx, p1->val); if (dev == NULL) return 0; - else if (v2 >= DEVSLOTS || dev->fslots[v2] == NULL) rax = -6; + else if (p2->val >= DEVSLOTS || dev->fslots[p2->val] == NULL) R(RAX) = -6; else { - rc = dev->fslots[v2](ctx, dev); - if (rc < 0) { rax = rc; rdx = 0; } + rc = dev->fslots[p2->val](ctx, dev); + if (rc < 0) { R(RAX) = rc; R(RDX) = 0; } } + + return 0; } -IMPL_END; //----------------------------------------------------------------------------// diff --git a/vm/pc/DECD b/vm/pc/DECD index 8080f41..a2d0979 100644 --- a/vm/pc/DECD +++ b/vm/pc/DECD @@ -3,19 +3,26 @@ Instruction encoding: -15 0 15 0 -xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx -│││└───────────┘ │└───┘└───┘└───┘ -│││ INSTR. │ FT3 FT2 FT1 -│││ │ -LMC R +Byte 1: Instruction number +Byte 2: +xx0xxxxx +|| └───┘ +RL CND -M No more words -C COND suffix -L LOCK suffix -R REP suffix -FT1 First operand format -FT2 Second operand format +Values for ModRMs: +000xxxxx xxxxx = reg + +(for memory accesses, xxxxx = access size) +001xxxxx [reg] +010xxxxx [reg+reg] +011xxxxx [reg+reg+imm16] +100xxxxx [reg+reg+imm32] +101xxxxx [reg+reg*imm8+imm32] +110xxxxx [reg+imm64] +11100001 imm8 (zero extended) +11100010 imm16 (zero extended) +11100100 imm32 (zero extended) +11101000 imm64 (zero extended) Values for COND: 00000 (none) @@ -33,19 +40,3 @@ Values for COND: 01100 .DXZ Highest (6th) bit of COND indicates negation -Fx values: -00000 (none) -00001 reg -00010 imm64 - -xxx00 [imm64] -xxx01 [reg+reg] code(reg)|code(reg) -xxx10 [reg+reg+imm16] code(reg)|code(reg) imm16 -xxx11 [reg+reg*imm16+imm16] code(reg)|code(reg) imm16 imm16 - -Where xxx is: -001 8-bit access -010 16-bit access -011 32-bit access -100 64-bit access - diff --git a/vm/pc/arch.h b/vm/pc/arch.h index 6ab9981..78310bd 100644 --- a/vm/pc/arch.h +++ b/vm/pc/arch.h @@ -62,12 +62,9 @@ struct ctx_t ulong cur_pc; // Memory and memory size - ushort *mp; + uchar *mp; ulong mz; - // Read next instruction - ushort (*get)(ctx_t *ctx); - // Devices list head dev_t *dh; diff --git a/vm/pc/decode.c b/vm/pc/decode.c index 4b0c383..98c6dbd 100644 --- a/vm/pc/decode.c +++ b/vm/pc/decode.c @@ -7,24 +7,40 @@ // Read the "DECD" file before reading this code // -static void check_param_type(ctx_t *ctx, instr_t *in, - uint prm, uchar fmt, int which) +// +// Instruction fetch +// + +static uchar fetchb(ctx_t *ctx) { - bool ok; + uchar v = *(ctx->mp + R(RIP) + R(CR1) - MEMOFF); + R(RIP) += 1; - if (prm == P_REG) - ok = (fmt == A_REG); + return v; +} - else if (prm == P_IMM) - ok = (fmt == A_IMM64); +static ushort fetchw(ctx_t *ctx) +{ + ushort v = *(ushort *)(ctx->mp + R(RIP) + R(CR1) - MEMOFF); + R(RIP) += 2; - else /* if (prm == P_MEM) */ - ok = ACC_FMT_IS_MEM(fmt); + return v; +} - if (!ok) - _except(ctx, E_ILL, - "FT%d not matching %s's expected parameter types: " - "fmt=0x%x prm=0x%x", which, in->full, fmt, prm); +static uint fetchd(ctx_t *ctx) +{ + uint v = *(uint *)(ctx->mp + R(RIP) + R(CR1) - MEMOFF); + R(RIP) += 4; + + return v; +} + +static ulong fetchq(ctx_t *ctx) +{ + ulong v = *(ulong *)(ctx->mp + R(RIP) + R(CR1) - MEMOFF); + R(RIP) += 8; + + return v; } // @@ -44,184 +60,205 @@ static void checkreg(ctx_t *ctx, uint reg) } // -// Extract operand according to fmt +// Verify that given access length is that of a byte/word/dword/qword // -void extract_param(ctx_t *ctx, acc_t *p, uchar fmt) +static void checklength(ctx_t *ctx, uint len) { - uint mlen, mfmt; - ushort temp; + static const int lentab[9] = { 0, 1, 1, 0, 1, 0, 0, 0, 1 }; - p->type = fmt; + if (len > 8 || lentab[len] == 0) + _except(ctx, E_ILL, "Invalid memory access length: %u", len); +} - if (fmt == A_REG) +// +// Extracts one operand +// +static void extract_param(ctx_t *ctx, uint prm, acc_t *p) +{ + // Get next operand ModRM-like byte + uchar fmt = fetchb(ctx); + + ulong hi = (fmt & 0b11100000) >> 5; + ulong lo = fmt & 0b00011111; + + // + // Registers + // + if (hi == 0) { - p->reg = ctx->get(ctx); + if (prm != P_REG) + _except(ctx, E_ILL, "Not expecting a register: %s", + ctx->cur_in->full); + + p->reg = lo; + p->type = A_REG; checkreg(ctx, p->reg); p->val = R(p->reg); - + return; } - else if (fmt == A_IMM64) + // + // Immediates + // + if (hi == 7) { - p->val = ctx->get(ctx); - p->val |= (ulong)ctx->get(ctx) << 16; - p->val |= (ulong)ctx->get(ctx) << 32; - p->val |= (ulong)ctx->get(ctx) << 48; - - return; - } + if (prm != P_IMM) + _except(ctx, E_ILL, "Not expecting an immediate: %s", + ctx->cur_in->full); - assert(ACC_FMT_IS_MEM(fmt)); - - // Handle a memory access - - mlen = fmt & AM_MLEN_MASK; - mfmt = fmt & AM_MFMT_MASK; - - p->mlen = (mlen == AM_8ACC ? 1 - : (mlen == AM_16ACC ? 2 - : (mlen == AM_32ACC ? 4 - : (mlen == AM_64ACC ? 8 : 0)))); - - if (p->mlen == 0) - _except(ctx, E_ILL, "Invalid MLEN for access: %x", fmt); - - switch (mfmt) - { - case AM_IMM64: - p->addr = ctx->get(ctx); - p->addr |= (ulong)ctx->get(ctx) << 16; - p->addr |= (ulong)ctx->get(ctx) << 32; - p->addr |= (ulong)ctx->get(ctx) << 48; + switch (lo) + { + case 1: + p->type = A_IMM8; + p->val = fetchb(ctx); break; - - case AM_RR: - case AM_RRI: - case AM_RRII: - temp = ctx->get(ctx); - p->reg1 = temp >> 8; - p->reg2 = temp & 0xFF; - - checkreg(ctx, p->reg1); - checkreg(ctx, p->reg2); - - if (mfmt == AM_RRI) - { - p->imm1 = 1; - p->imm2 = ctx->get(ctx); - } - - else if (mfmt == AM_RRII) - { - p->imm1 = ctx->get(ctx); - p->imm2 = ctx->get(ctx); - } - - else - { - p->imm1 = 1; - p->imm2 = 0; - } - p->addr = R(p->reg1) + R(p->reg2) - * (long)(short)p->imm1 - + (long)(short)p->imm2; - + case 2: + p->type = A_IMM16; + p->val = fetchw(ctx); break; - + + case 4: + p->type = A_IMM32; + p->val = fetchd(ctx); + break; + + case 8: + p->type = A_IMM64; + p->val = fetchq(ctx); + break; + default: - _except(ctx, E_ILL, "Invalid MFMT for access: %x", fmt); + _except(ctx, E_ILL, "Invalid immediate length: %hhu", lo); + } + + return; } + + // + // Memory operands + // + + if (prm != P_MEM) + _except(ctx, E_ILL, "Not expecting a memory access: %s", + ctx->cur_in->full); + + checklength(ctx, lo); + p->mlen = lo; + + switch (hi) + { + case 1: + p->type = AM_RR; + p->reg1 = fetchb(ctx); + p->reg2 = p->imm1 = p->imm2 = 0; + break; + + case 2: + p->type = AM_RR; + p->reg1 = fetchb(ctx); + p->reg2 = fetchb(ctx); + p->imm1 = 1; + p->imm2 = 0; + break; + + case 3: + p->type = AM_RRI; + p->reg1 = fetchb(ctx); + p->reg2 = fetchb(ctx); + p->imm2 = (short)fetchw(ctx); + p->imm1 = 1; + break; + + case 4: + p->type = AM_RRI; + p->reg1 = fetchb(ctx); + p->reg2 = fetchb(ctx); + p->imm2 = (int)fetchd(ctx); + p->imm1 = 1; + break; + + case 5: + p->type = AM_RRII; + p->reg1 = fetchb(ctx); + p->reg2 = fetchb(ctx); + p->imm1 = fetchb(ctx); + p->imm2 = (short)fetchw(ctx); + break; + + case 6: + p->type = AM_RRI; + p->reg1 = fetchb(ctx); + p->imm2 = fetchq(ctx); + p->reg2 = RZX; + p->imm1 = 1; + break; + } + + p->addr = R(p->reg1) + R(p->reg2) * (long)p->imm1 + p->imm2; } +// +// Instruction fetch & decode +// void decode(ctx_t *ctx) { instr_t *in; - uchar f1 = 0, f2 = 0, f3 = 0; - ushort w1, w2, rep = 0, lock, nomore; + ushort b1, b2, rep = 0, lock; acc_t p1 = { 0 }, p2 = { 0 }, p3 = { 0 }; - rpc = R(RIP); + ctx->cur_pc = R(RIP); - // Process the first word of the instruction - w1 = ctx->get(ctx); - lock = !!(w1 & SUFF_LOCK); - nomore = !!(w1 & SUFF_NOMORE); + // Address range check + // (assumes max. instruction length is 32 bytes) + if (R(RIP) + R(CR1) - MEMOFF >= ctx->mz - 32) + _except(ctx, E_ACC, "Executing out of memory"); - if (w1 & SUFF_COND) - ctx->cond = ctx->get(ctx); - else - ctx->cond = 0; + // Instruction bytes + b1 = fetchb(ctx); + b2 = fetchb(ctx); - w1 &= ~(SUFF_LOCK|SUFF_NOMORE|SUFF_COND); - - if (w1 >= NINSTRS) - _except(ctx, E_ILL, "No such INSTR: 0x%hX", w1); + // Renge check + if (b1 >= NINSTRS) + _except(ctx, E_ILL, "No such INSTR: 0x%hhX", b1); // Find instruction - in = &ctx->i[w1]; + in = &ctx->i[b1]; ctx->cur_in = in; - // Second word? - if (!nomore) - { - w2 = ctx->get(ctx); - - // REP and COND - rep = !!(w2 & SUFF_REP); - - // Fn - f3 = (w2 >> F3_SHIFT) & Fx_MASK; - f2 = (w2 >> F2_SHIFT) & Fx_MASK; - f1 = w2 & Fx_MASK; - } + // Get flags/etc + rep = !!(b2 & SUFF_REP); + lock = !!(b2 & SUFF_LOCK); + ctx->cond = b2 & SUFF_COND; // Operand 1? if (in->prm1 == NOPRM) { - if (f1 || f2 || f3) - _except(ctx, E_ILL, - "FTn (%u,%u,%u) filled for 0-param INSTR '%s'", - f1, f2, f3, in->full); - exec_instr(ctx, in, NULL, NULL, NULL, lock, rep); return; } - check_param_type(ctx, in, in->prm1, f1, 1); - extract_param(ctx, &p1, f1); + extract_param(ctx, in->prm1, &p1); // Operand 2? if (in->prm2 == NOPRM) { - if (f2 || f3) - _except(ctx, E_ILL, - "FT3/FT2 (%u,%u,%u) filled for 1-param INSTR '%s'", - f1, f2, f3, in->full); - exec_instr(ctx, in, &p1, NULL, NULL, lock, rep); return; } - check_param_type(ctx, in, in->prm2, f2, 2); - extract_param(ctx, &p2, f2); + extract_param(ctx, in->prm2, &p2); // Operand 1? if (in->prm3 == NOPRM) { - if (f3) - _except(ctx, E_ILL, - "FT3 (%u,%u,%u) filled for 2-param INSTR '%s'", - f1, f2, f3, in->full); - exec_instr(ctx, in, &p1, &p2, NULL, lock, rep); return; } - check_param_type(ctx, in, in->prm3, f3, 3); - extract_param(ctx, &p3, f3); + extract_param(ctx, in->prm3, &p3); exec_instr(ctx, in, &p1, &p2, &p3, lock, rep); } diff --git a/vm/pc/decode.h b/vm/pc/decode.h index 7c35247..61d1d65 100644 --- a/vm/pc/decode.h +++ b/vm/pc/decode.h @@ -20,41 +20,28 @@ enum enum { - SUFF_LOCK = (1 << 15), - SUFF_NOMORE = (1 << 14), - SUFF_COND = (1 << 13), - SUFF_REP = (1 << 15), - - Fx_MASK = 0x1F, - F3_SHIFT = 10, - F2_SHIFT = 5, + SUFF_REP = (1 << 7), + SUFF_LOCK = (1 << 6), + SUFF_COND = 0b00011111, }; enum { A_NONE = 0b00000, A_REG = 0b00001, - A_IMM64 = 0b00010, - AM_START = 0b00100, + A_IMM8 = 1, + A_IMM16 = 2, + A_IMM32 = 4, + A_IMM64 = 8, - AM_IMM64 = 0b00, - AM_RR = 0b01, - AM_RRI = 0b10, - AM_RRII = 0b11, - - AM_8ACC = 0b00100, - AM_16ACC = 0b01000, - AM_32ACC = 0b01100, - AM_64ACC = 0b10000, - - AM_MLEN_MASK = 0b11100, - AM_MFMT_MASK = 0b00011, + AM_RR = 0xF0, + AM_RRI = 0xF1, + AM_RRII = 0xF2, }; -#define ACC_FMT_IS_MEM(x) ((x) >= AM_START && (x) <= (AM_64ACC|AM_RRII)) - -#define ACC_IS_MEM(x) (ACC_FMT_IS_MEM((x)->type)) +#define ACC_FMT_IS_MEM(x) (((x) & 0xF0) != 0) +#define ACC_IS_MEM(p) ACC_FMT_IS_MEM((p)->type) struct acc_t { @@ -62,15 +49,16 @@ struct acc_t ulong val; // A_REG - ulong reg; + uchar reg; // AM_... ulong addr; uint mlen; // For instruction dumping ONLY - ushort reg1, reg2; - short imm1, imm2; + uchar reg1, reg2; + char imm1; + long imm2; }; enum { NOPRM, P_REG, P_IMM, P_MEM=4 }; @@ -98,10 +86,6 @@ void exec_instr(ctx_t *ctx, bool lock, bool rep); -void extract_param(ctx_t *ctx, - acc_t *p, - uchar fmt); - void dump_instr(ctx_t *ctx, instr_t *in, acc_t *p1, diff --git a/vm/pc/dump.c b/vm/pc/dump.c index 19700f8..3f23408 100644 --- a/vm/pc/dump.c +++ b/vm/pc/dump.c @@ -26,7 +26,7 @@ void dump_instr(ctx_t *ctx, { uint cond = ctx->cond; - trace("0x%lX:\t", rpc); + trace("0x%lX:\t", ctx->cur_pc); if (lock) trace("lock"); @@ -41,9 +41,7 @@ void dump_instr(ctx_t *ctx, trace("."); if (cond & (1 << 4)) - { trace("n"); - } assert((cond & ~(1 << 4)) <= sizeof(cond_suffixes)/sizeof(char *)); @@ -81,6 +79,12 @@ void dump_acc(ctx_t *ctx, acc_t *p) trace("%s", ctx->r[p->reg].name); else if (p->type == A_IMM64) + { + if (p->val < 0xA) trace("%lu", p->val); + else trace("0x%lX", p->val); + } + + else if (p->type == A_IMM32) { if (p->val < 0xA) trace("%lu", p->val); @@ -96,16 +100,25 @@ void dump_acc(ctx_t *ctx, acc_t *p) } } + else if (p->type == A_IMM16) + { + if (p->val < 0xA) trace("%lu", p->val); + else trace("0x%hX", (ushort)p->val); + } + + else if (p->type == A_IMM8) + { + if (p->val < 0xA) trace("%lu", p->val); + else trace("0x%hhX", (uchar)p->val); + } + else { trace("%c[", getmempref(p->mlen)); - mfmt = p->type & AM_MFMT_MASK; - - if (mfmt == AM_IMM64) - trace("0x%lX]", p->addr); + mfmt = p->type; - else if (mfmt == AM_RR) + if (mfmt == AM_RR) { if (p->reg1 && p->reg2) trace("%s+%s]", ctx->r[p->reg1].name, ctx->r[p->reg2].name); @@ -116,30 +129,30 @@ void dump_acc(ctx_t *ctx, acc_t *p) else if (mfmt == AM_RRI) { if (p->reg1 && p->reg2) - trace("%s+%s%c%hd]", + trace("%s+%s%c%ld]", ctx->r[p->reg1].name, ctx->r[p->reg2].name, - ((short)p->imm2 < 0 ? '-' : '+'), + (p->imm2 < 0 ? '-' : '+'), ABS(p->imm2)); - else trace("%s%c%hd]", + else trace("%s%c%ld]", ctx->r[p->reg1 ? p->reg1 : p->reg2].name, - ((short)p->imm2 < 0 ? '-' : '+'), + (p->imm2 < 0 ? '-' : '+'), ABS(p->imm2)); } else if (mfmt == AM_RRII) { if (p->reg1) - trace("%s+%s*%hd%c%hd]", + trace("%s+%s*%hhd%c%ld]", ctx->r[p->reg1].name, ctx->r[p->reg2].name, p->imm1, - ((short)p->imm2 < 0 ? '-' : '+'), + (p->imm2 < 0 ? '-' : '+'), ABS(p->imm2)); else - trace("%s*%hd%c%hd]", + trace("%s*%hhd%c%ld]", ctx->r[p->reg2].name, p->imm1, - ((short)p->imm2 < 0 ? '-' : '+'), + (p->imm2 < 0 ? '-' : '+'), ABS(p->imm2)); } } diff --git a/vm/pc/except.c b/vm/pc/except.c index 519ccbc..f47b392 100644 --- a/vm/pc/except.c +++ b/vm/pc/except.c @@ -78,7 +78,7 @@ void _except(ctx_t *ctx, int _code, char *fmt, ...) trace("\nException %u - ", code); va_start(ap, fmt); - vlog(fmt, ap); + vprintf(fmt, ap); va_end(ap); trace("\n\n"); @@ -105,7 +105,7 @@ actually_die: logerr("\nException %u - ", code); va_start(ap, fmt); - vlog(fmt, ap); + vfprintf(stderr, fmt, ap); va_end(ap); logerr("\n\n"); diff --git a/vm/pc/exec.c b/vm/pc/exec.c index 2ee9a26..fa3d468 100644 --- a/vm/pc/exec.c +++ b/vm/pc/exec.c @@ -63,7 +63,7 @@ void exec_instr(ctx_t *ctx, ulong r1 = 0, r2 = 0, r3 = 0; // Global instruction counter - fc0++; + ctx->ninstrs++; // // For REPs we evaluate the condition AFTER running the instruction, @@ -77,8 +77,6 @@ void exec_instr(ctx_t *ctx, dump_instr(ctx, in, p1, p2, p3, lock, rep); do_rep: - assert(R(RZX) == 0); - out = in->func(ctx, p1, p2, p3, &r1, &r2, &r3); if (out) @@ -102,7 +100,7 @@ do_rep: return; // Should we really count REP's in instruction count? - fc0++; + ctx->ninstrs++; #if 0 // Show that we're REP'ing if (ctx->dumpsw) diff --git a/vm/pc/log.c b/vm/pc/log.c index fdd28bb..f795d1f 100644 --- a/vm/pc/log.c +++ b/vm/pc/log.c @@ -3,17 +3,6 @@ #include -/* -void trace(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); -} -*/ - void logerr(const char *fmt, ...) { va_list ap; @@ -23,8 +12,3 @@ void logerr(const char *fmt, ...) va_end(ap); } -void vlog(const char *fmt, va_list ap) -{ - vfprintf(stderr, fmt, ap); -} - diff --git a/vm/pc/main.c b/vm/pc/main.c index f4e2e40..c67d3a5 100644 --- a/vm/pc/main.c +++ b/vm/pc/main.c @@ -11,23 +11,6 @@ static ssize_t fwsize; static ushort *fwprog; -ushort bget(ctx_t *ctx) -{ - ulong addr = R(RIP) + R(CR1); - - if (addr2real(addr) >= ctx->mz) { - _except(ctx, E_ACC, "Executing out of memory: " - "rip=0x%lX cr1=0x%lX", - R(RIP), R(RIP)); - } - - ushort c = ctx->mp[addr2real(addr)]; - - R(RIP) += 2; - - return c; -} - ctx_t main_ctx; void sigcommon(void) @@ -53,9 +36,10 @@ jmp_buf exc_jmp_buf; // void main_loop(void) { +/* if (main_ctx.dumpsw) trace("\n\n\n"); - +*/ setjmp(exc_jmp_buf); // @@ -78,7 +62,7 @@ int main(int argc, char **argv) main_ctx.r = arch_r; main_ctx.i = arch_i; -#if 0 && defined(NDEBUG) +#if 1 && !defined(NDEBUG) main_ctx.dumpsw = 1; #endif @@ -141,7 +125,6 @@ int main(int argc, char **argv) main_ctx.mp = malloc(MEMSIZE + 16); main_ctx.mz = MEMSIZE; - main_ctx.get = bget; main_ctx.rf[RIP] = MEMOFF; if (main_ctx.mp == 0) { diff --git a/vm/pc/mem.c b/vm/pc/mem.c index 6fea9b4..bac40d5 100644 --- a/vm/pc/mem.c +++ b/vm/pc/mem.c @@ -47,77 +47,54 @@ ulong writestr(ctx_t *ctx, ulong addr, ulong maxn, char *str) static ulong readmem8(ctx_t *ctx, ulong real, ulong addr) { - if (addr % 2 == 0) return (ulong)ctx->mp[real] & 0xFF; - else return ((ulong)ctx->mp[real] & 0xFF00) >> 8; + return (ulong)ctx->mp[real]; } static ulong readmem16(ctx_t *ctx, ulong real, ulong addr) { CHK_ALIGN(ushort); - return (ulong)ctx->mp[real]; + return (ulong)*(ushort *)(ctx->mp + real); } static ulong readmem32(ctx_t *ctx, ulong real, ulong addr) { CHK_ALIGN(uint); - ulong val = ctx->mp[real++]; - val = val | ((ulong)ctx->mp[real] << 16); - - return val; + return (ulong)*(uint *)(ctx->mp + real); } static ulong readmem64(ctx_t *ctx, ulong real, ulong addr) { CHK_ALIGN(ulong); - ulong val = (ulong)ctx->mp[real++]; - val = val | ((ulong)ctx->mp[real++] << 16); - val = val | ((ulong)ctx->mp[real++] << 32); - val = val | ((ulong)ctx->mp[real] << 48); - - return val; + return (ulong)*(ulong *)(ctx->mp + real); } //----------------------------------------------------------------------------// static void writemem8(ctx_t *ctx, ulong val, ulong real, ulong addr) { - ushort v = ctx->mp[real]; - - if (!(addr % 2)) { - ctx->mp[real] = (v & 0xFF00) | (val & 0xFF); - } - - else { - ctx->mp[real] = (v & 0xFF) | (((val & 0xFF) << 8)); - } + ctx->mp[real] = val & 0xFF; } static void writemem16(ctx_t *ctx, ulong val, ulong real, ulong addr) { - CHK_ALIGN(ushort); - - ctx->mp[real] = val & 0xFFFF; + *(ushort*)(ctx->mp + real) = val & 0xFFFF; } static void writemem32(ctx_t *ctx, ulong val, ulong real, ulong addr) { CHK_ALIGN(uint); - ctx->mp[real++] = val & 0xFFFF; - ctx->mp[real] = (val >> 16) & 0xFFFF; + *(uint*)(ctx->mp + real) = val & 0xFFFFFFFF; } static void writemem64(ctx_t *ctx, ulong val, ulong real, ulong addr) { CHK_ALIGN(ulong); - ctx->mp[real++] = val; - ctx->mp[real++] = (val >> 16) & 0xFFFF; - ctx->mp[real++] = (val >> 32) & 0xFFFF; - ctx->mp[real] = (val >> 48) & 0xFFFF; + *(ulong*)(ctx->mp + real) = val; } //----------------------------------------------------------------------------// @@ -133,7 +110,22 @@ static void writemem64(ctx_t *ctx, ulong val, ulong real, ulong addr) //----------------------------------------------------------------------------// -ulong readmem(ctx_t *ctx, ulong addr, uint len) +ulong readmemzx(ctx_t *ctx, ulong addr, uint len) +{ + GETREAL(); + CHK_RANGE(); + + switch (len) { + case 1: return readmem8(ctx, real, addr); break; + case 2: return readmem16(ctx, real, addr); break; + case 4: return readmem32(ctx, real, addr); break; + case 8: return readmem64(ctx, real, addr); break; + + default: logerr("readmemzx() bad length %d!\n", len); abort(); + } +} + +ulong readmemsx(ctx_t *ctx, ulong addr, uint len) { GETREAL(); CHK_RANGE(); @@ -143,23 +135,23 @@ ulong readmem(ctx_t *ctx, ulong addr, uint len) switch (len) { case 1: val = readmem8(ctx, real, addr); - val = (ulong)(long)(char)(val & 0xFF); + val = (ulong)(long)(char)val; break; case 2: val = readmem16(ctx, real, addr); - val = (ulong)(long)(short)(val & 0xFFFF); + val = (ulong)(long)(short)val; break; case 4: val = readmem32(ctx, real, addr); - val = (ulong)(long)(int)(val & 0xFFFFFFFF); + val = (ulong)(long)(int)val; break; case 8: return readmem64(ctx, real, addr); - default: logerr("readmem() bad length %d!\n", len); abort(); + default: logerr("readmemsx() bad length %d!\n", len); abort(); } return val; @@ -183,24 +175,3 @@ void writemem(ctx_t *ctx, ulong val, ulong addr, uint len) //----------------------------------------------------------------------------// -// -// The following function zero-extend rather than sign-extend -// - -ulong readmemzx(ctx_t *ctx, ulong addr, uint len) -{ - GETREAL(); - CHK_RANGE(); - - switch (len) { - case 1: return readmem8(ctx, real, addr); break; - case 2: return readmem16(ctx, real, addr); break; - case 4: return readmem32(ctx, real, addr); break; - case 8: return readmem64(ctx, real, addr); break; - - default: logerr("readmemzx() bad length %d!\n", len); abort(); - } -} - -//----------------------------------------------------------------------------// - diff --git a/vm/pc/mem.h b/vm/pc/mem.h index a158e8b..deb5eb1 100644 --- a/vm/pc/mem.h +++ b/vm/pc/mem.h @@ -5,15 +5,15 @@ static inline ushort bswap16(ushort u) { return ((u<<8) | (u>>8)); } static inline char getmempref(ushort len) -{ return (len==1?'b':(len==2?'w':(len==4?'l':(len==8?'q':'x')))); } +{ return (len==1?'b':(len==2?'w':(len==4?'d':(len==8?'q':'x')))); } #define MEMOFF (1 * 1024 * 1024) #define MEMSIZE (16 * 1024 * 1024) // 16MB #define MAXADDR 0x8000000000000 // 2^48 - 1 -#define addr2real(p) (((p) - MEMOFF) / 2) -#define real2addr(p) (((p) + MEMOFF) / 2) +#define addr2real(p) ((p) - MEMOFF) +#define real2addr(p) ((p) + MEMOFF) // Address of boot firmware stack #define FWSTACK (MEMOFF * 2) // 2MB @@ -21,11 +21,10 @@ static inline char getmempref(ushort len) ulong readstr(ctx_t *ctx, ulong addr, ulong maxn, char *buf); ulong writestr(ctx_t *ctx, ulong addr, ulong maxn, char *str); -ulong readmem(ctx_t *c, ulong addr, uint len); +ulong readmemzx(ctx_t *c, ulong addr, uint len); +ulong readmemsx(ctx_t *c, ulong addr, uint len); void writemem(ctx_t *, ulong val, ulong addr, uint len); -ulong readmemzx(ctx_t *c, ulong addr, uint len); -void writememzx(ctx_t *, ulong val, ulong addr, uint len); #define SIGN_EXTEND(val, mask) \ (val & ((mask + 1) >> 1) \ diff --git a/vm/pc/regs.c b/vm/pc/regs.c index 5f80e36..b7aa1eb 100644 --- a/vm/pc/regs.c +++ b/vm/pc/regs.c @@ -26,9 +26,9 @@ void dumpregs(ctx_t *ctx) TRACE("Current RFRAME index: #%lu", rfs_current_idx); TRACE("\n\nEnviron:"); - TRACE("\nrpc=0x%-16lX rip=0x%-16lX rfx=0x%-16lX", rpc, R(RIP), R(RFX)); + TRACE("\nrpc=0x%-16lX rip=0x%-16lX rfx=0x%-16lX", ctx->cur_pc, R(RIP), R(RFX)); TRACE("\nrsp=0x%-16lX rbp=0x%-16lX trp=0x%-16lX", R(RSP), R(RBP), R(TRP)); - TRACE("\nfc0=0x%-16lu cr0=0x%-16lX cr1=0x%-16lX", fc0, R(CR0), R(CR1)); + TRACE("\nfc0=0x%-16lu cr0=0x%-16lX cr1=0x%-16lX", ctx->ninstrs, R(CR0), R(CR1)); TRACE("\n\nArgument:"); TRACE("\nax0=0x%-16lX ax1=0x%-16lX ax2=0x%-16lX", R(AX0), R(AX1), R(AX2)); diff --git a/vm/pc/regs.h b/vm/pc/regs.h index 3a81f86..a7de68f 100644 --- a/vm/pc/regs.h +++ b/vm/pc/regs.h @@ -45,12 +45,6 @@ enum NREGS }; -#define fc0 ctx->ninstrs -#define rpc ctx->cur_pc - -#define rax R(RAX) -#define rdx R(RDX) - -#define ax0 R(AX0) -#define ax1 R(AX1) +#define _fc0 ctx->ninstrs +#define _rpc ctx->cur_pc