From 504b41317eeb05cd6e07578d8ab00fc088426fce Mon Sep 17 00:00:00 2001 From: julianb0 Date: Fri, 7 Jun 2019 13:38:34 +0200 Subject: [PATCH] vm --- vm/in/INSTRS | 440 ++++++++++++++++++++++++++++++++++++++++++------- vm/in/arith.c | 123 ++++++++------ vm/in/flags.h | 4 +- vm/in/instrs.h | 12 +- vm/in/mov.c | 28 ++-- vm/pc/arch.h | 3 +- 6 files changed, 480 insertions(+), 130 deletions(-) diff --git a/vm/in/INSTRS b/vm/in/INSTRS index 78c645c..ae3cb1a 100644 --- a/vm/in/INSTRS +++ b/vm/in/INSTRS @@ -4,127 +4,449 @@ stop nop -# -# Logical instructions -# +#---------------------------------------------------------------------------# +# Logical instructions # +#---------------------------------------------------------------------------# +# +# Bitwise NOT operation +# +# $1 = NOT($1) +# +# Preserves all flags +# !not rm + +# +# Bitwise OR operation +# +# $1 = $1 OR $2 +# +# Clears OF and CF +# Sets ZF and SF according to the result +# !or rm rim + +# +# Bitwise AND operation +# +# $1 = $1 AND $2 +# +# Clears OF and CF +# Sets ZF and SF according to the result +# !and rm rim + +# +# Bitwise XOR operation +# +# $1 = $1 XOR $2 +# +# Clears OF and CF +# Sets ZF and SF according to the result +# !xor rm rim + + !shl rm rim !shr rm rim -# -# Unsigned arithmetic instructions -# +#---------------------------------------------------------------------------# +# Arithmetic instructions # +#---------------------------------------------------------------------------# -!neg rm -!inc rm -!dec rm -!add rm rim -!sub rm rim -!mul rm rim -!div rm rim -!mod rm rim +# +# Arithmetical SGN operation +# +# IF ($1 == 0) THEN +# $2 = 0 +# ELIF ($1 GT 0) THEN +# $2 = 1 +# ELSE +# $2 = LONG_MIN +# FI +# +# Treats $1 and $2 as signed values +# Sets ZF and SF according to the result +# !sgn rm rim -# rdx = hi(rax * $0) -# rax = lo(rax * $0) +# +# Arithmetical NEG operation +# +# $1 = NOT($1) + 1 +# +# Sets CF if $1 == 0; clears it otherwise +# Sets OF if $1 == $LONG_MIN; clears it otherwise +# Sets ZF and SF according to the result +# +!neg rm + +# +# Arithmetical INC operation +# +# $1 = $1 + 1 +# +# Preserves CF +# Sets OF if $1 == $LONG_MAX, clears it otherwise +# Sets ZF and SF according to the result +# +!inc rm + +# +# Arithmetical DEC operation +# +# $1 = $1 - 1 +# +# Preserves CF +# Sets OF if $1 == $LONG_MIN, clears it otherwise +# Sets ZF and SF according to the result +# +!dec rm + +# +# Arithmetical ADD operation +# +# $1 = $1 + $2 +# +# Sets CF if unsigned integer overflow occur, clears it otherwise +# Sets OF is signed integer overflow occur, clears it otherwise +# Sets ZF and SF according to the result +# +!add rm rim + +# +# Arithmetical SUB operation +# +# $1 = $1 - $2 +# +# Sets CF if unsigned integer overflow occur, clears it otherwise +# Sets OF is signed integer overflow occur, clears it otherwise +# Sets ZF and SF according to the result +# +!sub rm rim + +# +# Arithmetical unsigned MUL operation +# +# $1 = LO($1 * $2) +# +# Sets CF and OF if HI($1 * $2) > 0, clears them otherwise +# Preserves ZF and SF +# +!mul rm rim + +# +# Arithmetical unsigned DIV operation +# +# $1 = $1 DIV $2 +# +# Preserves all flags +# +!div rm rim + +# +# Arithmetical unsigned MOD operation +# +# $1 = $1 MOD $2 +# +# Preserves all flags +# +!mod rm rim + +# +# Arithmetical unsigned 128-bit MUL operation +# +# RDX = HI(RAX * $1) +# RAX = LO(RAX * $1) +# +# Sets CF and OF if HI($1 * $2) > 0, clears them otherwise +# Preserves ZF and SF +# mul2 rim -# rdx = rax % $0 -# rax = rax / $0 +# +# Arithmetical unsigned combined DIV and MOD operations +# +# RDX = (RAX MOD $1) +# RAX = (RAX DIV $1) +# +# Preserves all flags +# div2 rim -# -# Comparison instruction -# - -cmp rim rim -#cmpb rim rim -#cmpw rim rim -#cmpl rim rim -#cmpt rim rim +#---------------------------------------------------------------------------# +# Comparison instructions # +#---------------------------------------------------------------------------# +# +# TEST Comparaison instruction +# +# $1 AND $2 +# +# Clears OF and CF +# Sets ZF and SF according to the result +# test rim rim -#testb rim rim -#testw rim rim -#testl rim rim -#testt rim rim # -# Jump instructions +# CMP Comparaison instruction # +# $1 - $2 +# +# Sets CF if unsigned integer overflow occur, clears it otherwise +# Sets OF is signed integer overflow occur, clears it otherwise +# Sets ZF and SF according to the result +# +cmp rim rim +#---------------------------------------------------------------------------# +# Jump instructions # +#---------------------------------------------------------------------------# + +# +# Unconditional jump (JMP) instruction +# +# RIP = CR1 + $1 +# !j ri !jmp ri + +# +# RCX-dependent jump (LOOP) instruction +# +# IF (RCX > 0) THEN +# RCX = RCX - 1 +# RIP = CR1 + $1 +# FI +# !loop ri -# -# Movement instructions -# +#---------------------------------------------------------------------------# +# Movement instructions # +#---------------------------------------------------------------------------# +# +# Load Effective Address (LEA) instruction +# +# $1 = ADDR($2) +# +# For instance: +# LEA RAX, [RBX + RCX + 4] +# will result in: +# RAX = RBX + RCX + 4 +# +# Preserves all flags +# !lea rm m + +# +# Movement (MOV) instruction +# +# $1 = $2 +# !mov rm rim + +# +# Exchange (XCHG) instruction +# +# $_ = $1 +# $1 = $2 +# $2 = $_ +# !xchg rm rim + +# +# Compare-and-exchange (CMPXCHG) instruction +# +# IF ($1 == RAX) THEN +# $1 = $2 +# ZF = 1 +# ELSE +# RAX = $1 +# ZF = 0 +# FI +# +# Preserves CF, OF and SF +# cmpxchg rm rim -movb rm rim -movw rm rim -movl rm rim -movt rm rim +# Undocumented +# movb rm rim +# movw rm rim +# movl rm rim +# movt rm rim + +#---------------------------------------------------------------------------# +# Stack manipulation instructions # +#---------------------------------------------------------------------------# # -# Stack manipulation instructions +# PUSH value onto stack +# +# RSP = RSP - 8 +# *RSP = $1 +# +# Throws: +# #STA if RBP MOD 8 > 0 +# #STA if RSP MOD 8 > 0 +# #STU if RSP > RBP # - !push rim -!call rim + +# +# POP value from stack +# +# $1 = *RSP +# RSP = RSP + 8 +# +# Throws: +# #STA if RBP MOD 8 > 0 +# #STA if RSP MOD 8 > 0 +# #STU if RSP >= RBP +# !pop rm + +# +# Unconditional jump with possible return (CALL) +# +# PUSH(RIP) +# JMP(RIP) +# +# Throws: +# See PUSH and JMP +# +!call rim + +# +# Return to caller (RET) +# +# POP(RIP) +# +# Throws: +# See POP +# !ret -# push rbp -# mov rbp, rsp +# +# Make new stack frame (ENTER) +# +# PUSH(RBP) +# RBP = RSP +# +# Throws: +# See PUSH +# enter -# add rsp, 8 -# mov rbp, [rsp] +# +# Leave stack frame (LEAVE) +# +# RBP = *RSP +# RSP = RSP + 8 +# !leave +#---------------------------------------------------------------------------# +# Supervisor only instructions # +#---------------------------------------------------------------------------# + + pushf popf # -# Supervisor only instructions +# Clear or set interrupt flag (CLI/STI) +# +# Throws: +# #SYS if not in supervisor mode # - cli sti +# +# Call an architecture-reserved function slot of device (DEVCTL) +# +# See dv/DEVAPI +# devctl rim rim + +# +# Call a device-defined function slot of device (IOCALL) +# +# See dv/DEVAPI +# iocall rim rim -# -# Misc. instructions -# +#---------------------------------------------------------------------------# +# Misc. instructions # +#---------------------------------------------------------------------------# -# Clear rax...rsi +# +# Get code/date offset (GCO/GCD) +# +# $1 = CR1 (GCO) +# $1 = CR2 (GCD) +# +gco rm +gcd rm + +# +# Clear base volatile registers (CLR) +# +# RAX = RBX = RCX = RDX = 0 +# RSX = RBI = RDI = RSI = 0 +# clr -# Clear ax0...ax7 +# +# Clear argument registers (CLA) +# +# AX0 = AX1 = AX2 = AX3 = 0 +# AX4 = AX5 = AX6 = AX7 = 0 +# cla -# Clear nx0...nx7 -cln - -# Print a character on the screen -prn rim # -# Debugging instructions +# Clear base non-volatile registers (CLN) +# +# NX0 = NX1 = NX2 = NX3 = 0 +# NX4 = NX5 = NX6 = NX7 = 0 +# +cln + +# +# Send a character to standard output +# +# Throws: +# #PRN if DV text mode enabled +# #PRN if graphic mode enabled +# +prn rim + +#---------------------------------------------------------------------------# +# Debugging instructions # +#---------------------------------------------------------------------------# + +# +# Breakpoint instruction (BREAK) +# +# (cause register dump on standard error) +# (wait for user input before proceeeding) # !break +# +# Step-by-step execution (STEP) +# +# IF $1 == 0 THEN +# (disable step-by-step execution) +# ELSE +# (enable step-by-step execution) +# FI +# step rim +#---------------------------------------------------------------------------# + diff --git a/vm/in/arith.c b/vm/in/arith.c index 0b8aeec..655dcfc 100644 --- a/vm/in/arith.c +++ b/vm/in/arith.c @@ -4,6 +4,7 @@ #include IMPL_COND(sgn); +IMPL_COND(neg); IMPL_COND(inc); IMPL_COND(dec); IMPL_COND(add); @@ -16,6 +17,29 @@ IMPL_COND(div2); //-------------------------------------------------------------------------- +IMPL_START_2(sgn) +{ + v1 = (long)v2 < 0 ? (ulong)-1L : 1; +} +IMPL_OUT_ZSF; + +IMPL_START_1(neg) +{ + if (v1 == 0) flg |= CF; + + else { + flg &= ~CF; + + if (v1 == LONG_MIN) flg |= OF; + else flg &= ~OF; + } + + v1 = ~v1 + 1; +} +IMPL_OUT_ZSF; + +//-------------------------------------------------------------------------- + IMPL_START_1(inc) { if (v1 == LONG_MAX) flg |= OF; @@ -83,35 +107,61 @@ IMPL_END; //-------------------------------------------------------------------------- +// +// www.codeproject.com/Tips/618570/UInt-Multiplication-Squaring +// +static void multiply(ulong u, ulong v, ulong *hi, ulong *lo) +{ + ulong u1 = (u & 0xffffffff); + ulong v1 = (v & 0xffffffff); + ulong t = (u1 * v1); + ulong w3 = (t & 0xffffffff); + ulong k = (t >> 32); + + u >>= 32; + t = (u * v1) + k; + k = (t & 0xffffffff); + ulong w1 = (t >> 32); + + v >>= 32; + t = (u1 * v) + k; + k = (t >> 32); + + *hi = (u * v) + w1 + k; + *lo = (t << 32) + w3; +} + IMPL_START_2(mul) { - v1 *= v2; + ulong hi; + + multiply(v1, v2, &hi, &v1); + + if (hi > 0) { + flg |= CF; + flg |= OF; + } + + else { + flg &= ~CF; + flg &= ~OF; + } } IMPL_OUT; IMPL_START_1(mul2) { - // Adapted from www.codeproject.com/Tips/618570/UInt-Multiplication-Squaring - ulong v2 = v1; - v1 = rax; + multiply(rax, v1, &rdx, &rax); - ulong u1 = (v1 & 0xffffffff); - ulong u2 = (v2 & 0xffffffff); - ulong t = (u1 * u2); - ulong w3 = (t & 0xffffffff); - ulong k = (t >> 32); + if (rdx > 0) { + flg |= CF; + flg |= OF; + } - v1 >>= 32; - t = (v1 * u2) + k; - k = (t & 0xffffffff); - ulong w1 = (t >> 32); - - v2 >>= 32; - t = (u1 * v2) + k; - k = (t >> 32); - - rdx = (v1 * v2) + w1 + k; - rax = (t << 32) + w3; + else { + flg &= ~CF; + flg &= ~OF; + } } IMPL_END; @@ -136,36 +186,3 @@ IMPL_START_1(div2) } IMPL_END; -//-------------------------------------------------------------------------- - -IMPL_START_2(sgn) -{ - if (v2 == 0) v1 = 0; - - else if ((long)v2 > 0) { - flg &= ~CF; - v1 = 1; - } - - else { - flg |= CF; - v1 = (ulong)-1L; - } -} -IMPL_OUT_ZSF; - -IMPL_START_1(neg) -{ - if (v1 == 0) flg |= CF; - - else { - flg &= ~CF; - - if (v1 == LONG_MIN) flg |= OF; - else flg &= ~OF; - } - - v1 = ~v1 + 1; -} -IMPL_OUT_ZSF; - diff --git a/vm/in/flags.h b/vm/in/flags.h index da1d2eb..667bfc0 100644 --- a/vm/in/flags.h +++ b/vm/in/flags.h @@ -1,6 +1,8 @@ // The OS/K Team licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#define PARITY(v) __builtin_parity(v) + #define SET_ZF(v) \ flg = ((v) == 0 ? (flg|ZF) : (flg&~ZF)) @@ -8,7 +10,7 @@ flg = ((long)(v) < 0 ? (flg|SF) : (flg&~SF)) #define SET_PF(v) \ - flg = (__builtin_parity(v) == 1 ? (flg|PF) : (flg&~PF)) + flg = (PARITY(v) == 1 ? (flg|PF) : (flg&~PF)) #define SET_ZSF(v) \ SET_ZF(v); \ diff --git a/vm/in/instrs.h b/vm/in/instrs.h index 8de0d5d..27de10e 100644 --- a/vm/in/instrs.h +++ b/vm/in/instrs.h @@ -78,10 +78,10 @@ void i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2) \ #define CHK_STACK(op) \ if (rsp % 8 > 0 || rbp % 8 > 0) { \ - _except(ctx, E_STK, "Misaligned stack REGS"); \ + _except(ctx, E_STA, "Misaligned stack REGS"); \ } \ if (rbp op rsp) { \ - _except(ctx, E_STK, "RSP above RBP"); \ + _except(ctx, E_STU, "Stack underflow"); \ } // @@ -89,12 +89,12 @@ void i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2) \ // #define PUSH(v) \ - writemem64(ctx, v, rsp); \ - rsp -= 8; + rsp -= 8; \ + writemem64(ctx, v, rsp); #define POP(v) \ - rsp += 8; \ - v = readmem64(ctx, rsp); + v = readmem64(ctx, rsp); \ + rsp += 8; #define JUMP(v) \ rip = v + cr1 diff --git a/vm/in/mov.c b/vm/in/mov.c index c147004..660e4ea 100644 --- a/vm/in/mov.c +++ b/vm/in/mov.c @@ -5,10 +5,6 @@ IMPL_COND(lea); IMPL_COND(mov); -IMPL_COND(movb); -IMPL_COND(movw); -IMPL_COND(movl); -IMPL_COND(movt); IMPL_COND(xchg); IMPL_COND(cmpxchg); @@ -57,6 +53,11 @@ IMPL_START_2(movt) } IMPL_OUT; +IMPL_COND(movb); +IMPL_COND(movw); +IMPL_COND(movl); +IMPL_COND(movt); + IMPL_START_2(xchg) { ulong t = v1; @@ -77,12 +78,6 @@ IMPL_START_1(lea) } IMPL_OUT; -IMPL_START_1(gcs) -{ - v1 = cr1; -} -IMPL_OUT; - IMPL_START_2(cmpxchg) { if (rax == v1) { @@ -97,3 +92,16 @@ IMPL_START_2(cmpxchg) } IMPL_OUT; +IMPL_START_1(gco) +{ + v1 = cr1; +} +IMPL_OUT; + +IMPL_START_1(gcd) +{ + v1 = cr2; +} +IMPL_OUT; + + diff --git a/vm/pc/arch.h b/vm/pc/arch.h index f897521..0a47fb7 100644 --- a/vm/pc/arch.h +++ b/vm/pc/arch.h @@ -134,7 +134,8 @@ enum E_ACC, // Invalid access E_SYS, // Supervisor only E_ALI, // Alignment error - E_STK, // Stack error + E_STA, // Stack misalignment + E_STU, // Stack underflow NEXCPTS };