1
0
mirror of https://gitlab.os-k.eu/os-k-team/kvisc.git synced 2023-08-25 14:05:46 +02:00
This commit is contained in:
julianb0 2019-06-23 12:40:18 +02:00
parent 4bccea4a9d
commit 49ad38a774
No known key found for this signature in database
GPG Key ID: 9C7ACF0C053FB8A1
25 changed files with 1064 additions and 1033 deletions

View File

@ -19,7 +19,7 @@ $(KODIR)/a.out: $(DOSK) kas
.PHONY: clean .PHONY: clean
clean: clean:
@cd vm && make clean --no-print-directory @cd vm && make clean --no-print-directory
@rm -f $(KODIR)/a.out $(KODIR)/a.out.sym $(KODIR)/k.exe $(KODIR)/stdout.txt as/instrs.lst @rm -f $(KODIR)/a.out $(KODIR)/a.out.sym $(KODIR)/k.exe as/instrs.lst
test: $(KODIR)/a.out test: $(KODIR)/a.out
@vm/k.exe $(KODIR)/a.out $(KODIR)/a.sym @vm/k.exe $(KODIR)/a.out $(KODIR)/a.sym

158
vm/in/ARITH Normal file
View File

@ -0,0 +1,158 @@
# The OS/K Team licenses this file to you under the MIT license.
# See the LICENSE file in the project root for more information.
#---------------------------------------------------------------------------#
# Arithmetic instructions #
#---------------------------------------------------------------------------#
#
# CMP Comparison 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
#
# 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
sgnf rm rim
#
# 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
negf 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
incf 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
decf 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
addf rm rim
#
# Arithmetical ADD operation, with carry
#
# $1 = $1 + $2 + CF
#
# 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
#
adc rm rim
adcf 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
subf 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
mulf rm rim
#
# Arithmetical unsigned DIV operation
#
# $1 = $1 DIV $2
#
# Preserves all flags
#
div rm rim
#
# Arithmetical unsigned modulo operation (REM)
#
# $1 = $1 MOD $2
#
# Preserves all flags
#
rem 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
mul2f rim
#
# Arithmetical unsigned combined DIV and MOD operations
#
# RDX = (RAX MOD $1)
# RAX = (RAX DIV $1)
#
# Preserves all flags
#
div2 rim

26
vm/in/DEBUG Normal file
View File

@ -0,0 +1,26 @@
# The OS/K Team licenses this file to you under the MIT license.
# See the LICENSE file in the project root for more information.
#---------------------------------------------------------------------------#
# 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

45
vm/in/FLAGS Normal file
View File

@ -0,0 +1,45 @@
# The OS/K Team licenses this file to you under the MIT license.
# See the LICENSE file in the project root for more information.
#---------------------------------------------------------------------------#
# Flag manipulation instructions #
#---------------------------------------------------------------------------#
#
# Clear or set interrupt flag (CLI/STI)
#
# Throws:
# #SYS if not in supervisor mode
#
cli
sti
#
# Clear or set direction flag (CLD/STD)
#
cld
std
#
# Complement, clear or set carry flag (CMC/CLC/STC)
#
cmc
clc
stc
#
# Load FLG register (LODF)
#
# $1 = FLG
#
lodf rm
#
# Store FLG register - lower byte only (STOFB)
#
# FLG[7:0] = $1[7:0]
#
# Note: FLG's lower byte contains CF, OF, ZF, SF, PF and DF
#
stofb rm

17
vm/in/INOUT Normal file
View File

@ -0,0 +1,17 @@
# The OS/K Team licenses this file to you under the MIT license.
# See the LICENSE file in the project root for more information.
#---------------------------------------------------------------------------#
# I/O instructions #
#---------------------------------------------------------------------------#
#
# Send a character to standard output (PRN)
#
prn rim
#
# Scan a character from standard input (SCAN)
#
scan rm

View File

@ -5,729 +5,16 @@
# Special instructions # # Special instructions #
#---------------------------------------------------------------------------# #---------------------------------------------------------------------------#
# include "SUPER"
# Initiate machine shutdown (STOP) include "TRAP"
# include "MOV"
# THROW #SHT include "MISC"
# include "LOGIC"
# Throws: include "ARITH"
# #SYS if not in supervisor mode include "JUMPS"
# #ILL if disabled through DV include "STACK"
# #SHT otherwise include "FLAGS"
# include "INOUT"
stop include "DEBUG"
include "STRING"
#---------------------------------------------------------------------------#
# 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
orf rm rim
#
# Bitwise AND operation
#
# $1 = $1 AND $2
#
# Clears OF and CF
# Sets ZF and SF according to the result
#
and rm rim
andf rm rim
#
# Bitwise XOR operation
#
# $1 = $1 XOR $2
#
# Clears OF and CF
# Sets ZF and SF according to the result
#
xor rm rim
xorf rm rim
# To document
shl rm rim
shr rm rim
shlf rm rim
shrf rm rim
#---------------------------------------------------------------------------#
# Arithmetic instructions #
#---------------------------------------------------------------------------#
#
# 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
sgnf rm rim
#
# 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
negf 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
incf 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
decf 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
addf rm rim
#
# Arithmetical ADD operation, with carry
#
# $1 = $1 + $2 + CF
#
# 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
#
adc rm rim
adcf 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
subf 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
mulf rm rim
#
# Arithmetical unsigned DIV operation
#
# $1 = $1 DIV $2
#
# Preserves all flags
#
div rm rim
#
# Arithmetical unsigned modulo operation (REM)
#
# $1 = $1 MOD $2
#
# Preserves all flags
#
rem 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
mul2f rim
#
# Arithmetical unsigned combined DIV and MOD operations
#
# RDX = (RAX MOD $1)
# RAX = (RAX DIV $1)
#
# Preserves all flags
#
div2 rim
#---------------------------------------------------------------------------#
# Comparison instructions #
#---------------------------------------------------------------------------#
#
# TEST Comparison instruction
#
# $1 AND $2
#
# Clears OF and CF
# Sets ZF and SF according to the result
#
test rim rim
#
# CMP Comparison 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 = $1
#
j ri
jmp ri
#
# RCX-dependent jump (LOOP) instruction
#
# IF (RCX > 0) THEN
# RCX = RCX - 1
# RIP = $1
# FI
#
loop ri
#---------------------------------------------------------------------------#
# 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
#
# Movement with zero-extension (MOVZX) instruction
#
# $1 = ZeroExtend($2)
#
movzx rm m
#
# 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
#
# Load argument #N (LDARG)
#
# IF ($2 < 8) THEN
# $1 = AX$2
# ELSE
# $1 = LX($2-8)
# FI
#
# Throws:
# #ILL if $2 ≥ 16
#
ldarg rm rim
#---------------------------------------------------------------------------#
# Stack manipulation instructions #
#---------------------------------------------------------------------------#
#
# Unconditional jump with possible return (CALL)
#
# PUSH(RIP)
# JMP(RIP)
#
call rim
#
# Return to caller (RET)
#
# POP(RIP)
#
ret
#
# Make new stack frame (ENTER)
#
# PUSH(RBP)
# RBP = RSP
# RSP = RSP - $1
#
enter i
#
# Leave stack frame (LEAVE)
#
# RSP = RBP
# POP(RBP)
#
leave
#
# PUSH value onto stack
#
# RSP = RSP - 8
# *RSP = $1
#
push rim
#
# POP value from stack
#
# $1 = *RSP
# RSP = RSP + 8
#
pop rm
#---------------------------------------------------------------------------#
# I/O instructions #
#---------------------------------------------------------------------------#
#
# Send a character to standard output (PRN)
#
prn rim
#
# Scan a character from standard input (SCAN)
#
scan rm
#---------------------------------------------------------------------------#
# Supervisor only instructions #
#---------------------------------------------------------------------------#
#
# Halt the processor until next E/I (HLT)
#
hlt
#
# Pause the CPU for a relatively long time (XPAUSE)
#
xpause
#
# 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
#---------------------------------------------------------------------------#
# E/I handling instructions #
#---------------------------------------------------------------------------#
#
# Trap into exception handler (TRAP)
#
# Throw:
# #ILL if $1 > 255
# #($1+256) otherwise
#
trap rim
#
# Return from exception/interrupt (IRET)
#
iret
#---------------------------------------------------------------------------#
# Misc. instructions #
#---------------------------------------------------------------------------#
#
# Do nothing (NOOP)
#
# (nothing)
#
# Throws:
# (nothing)
#
# Preserves all flags
#
nop
#
# Pause the CPU for a very short amount of time (PAUSE)
# Used in spin-like loops
#
pause
#
# Get timestamp in seconds
#
time rm
#
# Get timestamp in µseconds
#
utime rm
#
# CPU Identification Number
#
# Does nothing (for now)
#
cpuid
#
# Pseudo-random number generation (RAND32/RAND64)
#
# RAND32 generates a 32-bit pseudo-random number using
# a nonlinear additive feedback pseudo-random number generator
# of period 16 * (2^31 - 1).
#
# RAND64 generates two such numbers, and store them in the destination
# operand's higher and lower double words respectively
#
# The running program does not control the seeding and the processor
# may generate numbers from the same generator for other purposes
# than this instruction
#
#rand32 rm
#rand64 rm
#
# Get code/data offset (GCO/GCD)
#
# $1 = CR1 (GCO)
# $1 = CR2 (GCD)
#
gco rm
gcd rm
#---------------------------------------------------------------------------#
# 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
#---------------------------------------------------------------------------#
# Clean-up misc. instructions #
#---------------------------------------------------------------------------#
#
# Clear base volatile registers (CLR)
#
# RAX = RBX = RCX = RDX = 0
# RSX = RBI = RDI = RSI = 0
#
clr
#
# Clear argument registers (CLA)
#
# AX0 = AX1 = AX2 = AX3 = 0
# AX4 = AX5 = AX6 = AX7 = 0
#
cla
#---------------------------------------------------------------------------#
# Flag manipulation instructions #
#---------------------------------------------------------------------------#
#
# Clear or set interrupt flag (CLI/STI)
#
# Throws:
# #SYS if not in supervisor mode
#
cli
sti
#
# Clear or set direction flag (CLD/STD)
#
cld
std
#
# Complement, clear or set carry flag (CMC/CLC/STC)
#
cmc
clc
stc
#
# Load FLG register (LODF)
#
# $1 = FLG
#
lodf rm
#
# Store FLG register - lower byte only (STOFB)
#
# FLG[7:0] = $1[7:0]
#
# Note: FLG's lower byte contains CF, OF, ZF, SF, PF and DF
#
stofb rm
#---------------------------------------------------------------------------#
# Byte-wise / bit-wise manipulation instructions #
#---------------------------------------------------------------------------#
#
# Byte/word/dword swap (xSWAP)
#
# Change endianness
#
bswap rm rim
wswap rm rim
dswap rm rim
#---------------------------------------------------------------------------#
# String manipulation instructions #
#---------------------------------------------------------------------------#
#
# Store value into string (STOSx)
#
# [%1] = $2
# IF (DF == 0) THEN
# %str = %str + sizeof(x)
# ELSE
# %str = %str - sizeof(x)
# FI
#
# When no parameters are given, %str = RDI and $val = RAX
# When one parameter is given, %str = RDI and $val = $1
# When two parameters are given, %str = $1 and $val = $2
#
stosb r rim
stosw r rim
stosl r rim
stosq r rim
#
# Load value from string (LODSx)
#
# $1 = [%2]
# IF (DF == 0) THEN
# %str = %str + sizeof(x)
# ELSE
# %str = %str - sizeof(x)
# FI
#
# Preserves CF, OF and SF
# Sets ZF according to the loaded value
#
lodsb r r
lodsw r r
lodsl r r
lodsq r r
#
# Scan string for a particular value (SCASx)
#
# CMP([%1], $2)
#
# IF ([%1] == 0) THEN
# ZF = 1
# ELIF (ZF == 0) THEN
# IF (DF == 0) THEN
# %1 = %1 + sizeof(x)
# ELSE
# %1 = %1 - sizeof(x)
# FI
# FI
#
# Sets CF, OF and SF according to the result of the comparison
# Sets ZF according to whether [%1] and $2 are equal, OR if [%1] is null
#
# Notes:
# - Does not move past the value when found
# - 'SCASB.REP.NZ reg ch' is a short 'strchnul()'
#
scasb r rim
scasw r rim
scasl r rim
scasq r rim
#
# Compare bytes in strings (CMPSx)
#
# CMP([%1], [%2])
#
# IF (DF == 0) THEN
# %1 = %1 + sizeof(x)
# %2 = %2 + sizeof(x)
# ELSE
# %1 = %1 - sizeof(x)
# %2 = %2 - sizeof(x)
# FI
#
# Sets CF, OF, ZF and SF according to the result of the comparison
#
# Moves past the compared values in any case!
#
cmpsb r r
cmpsw r r
cmpsl r r
cmpsq r r
#
# Safe compare bytes in strings (CMPZSx)
#
# Behaves precisely like CMPSx, except in the following case:
# - If both [%1] and [%2] are zero, clears ZF (indicating NOT EQUAL)
#
# This prevents 'CMPZSx.REP.Z' from looping infinitely when both strings
# have the exact same content; this allows for short strcmp's
#
cmpzsb r r
cmpzsw r r
cmpzsl r r
cmpzsq r r
#
# Move value from string to string (MOVSx)
#
# [%1] = [%1]
# IF (DF == 0) THEN
# %1 = %1 + sizeof(x)
# %2 = %2 + sizeof(x)
# ELSE
# %1 = %1 - sizeof(x)
# %2 = %2 - sizeof(x)
# FI
#
# Preserves CF, OF and SF
# Sets ZF according to the moved value
#
movsb r r
movsw r r
movsl r r
movsq r r
#---------------------------------------------------------------------------#

24
vm/in/JUMPS Normal file
View File

@ -0,0 +1,24 @@
# The OS/K Team licenses this file to you under the MIT license.
# See the LICENSE file in the project root for more information.
#---------------------------------------------------------------------------#
# Jump instructions #
#---------------------------------------------------------------------------#
#
# Unconditional jump (JMP) instruction
#
# RIP = $1
#
j ri
jmp ri
#
# RCX-dependent jump (LOOP) instruction
#
# IF (RCX > 0) THEN
# RCX = RCX - 1
# RIP = $1
# FI
#
loop ri

65
vm/in/LOGIC Normal file
View File

@ -0,0 +1,65 @@
# The OS/K Team licenses this file to you under the MIT license.
# See the LICENSE file in the project root for more information.
#---------------------------------------------------------------------------#
# Logical instructions #
#---------------------------------------------------------------------------#
#
# TEST Comparison instruction
#
# $1 AND $2
#
# Clears OF and CF
# Sets ZF and SF according to the result
#
test rim rim
#
# 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
orf rm rim
#
# Bitwise AND operation
#
# $1 = $1 AND $2
#
# Clears OF and CF
# Sets ZF and SF according to the result
#
and rm rim
andf rm rim
#
# Bitwise XOR operation
#
# $1 = $1 XOR $2
#
# Clears OF and CF
# Sets ZF and SF according to the result
#
xor rm rim
xorf rm rim
# To document
shl rm rim
shr rm rim
shlf rm rim
shrf rm rim

83
vm/in/MISC Normal file
View File

@ -0,0 +1,83 @@
# The OS/K Team licenses this file to you under the MIT license.
# See the LICENSE file in the project root for more information.
#---------------------------------------------------------------------------#
# Misc. instructions #
#---------------------------------------------------------------------------#
#
# Do nothing (NOOP)
#
# (nothing)
#
# Throws:
# (nothing)
#
# Preserves all flags
#
nop
#
# Pause the CPU for a very short amount of time (PAUSE)
# Used in spin-like loops
#
pause
#
# Pause the CPU for a relatively long time (XPAUSE)
#
# Throws:
# #SYS if not in supervisor mode
#
xpause
#
# Get timestamp in seconds
#
time rm
#
# Get timestamp in µseconds
#
utime rm
#
# CPU Identification Number
#
# Does nothing (for now)
#
cpuid
#---------------------------------------------------------------------------#
# Clean-up misc. instructions #
#---------------------------------------------------------------------------#
#
# Clear base volatile registers (CLR)
#
# RAX = RBX = RCX = RDX = 0
# RSX = RBI = RDI = RSI = 0
#
clr
#
# Clear argument registers (CLA)
#
# AX0 = AX1 = AX2 = AX3 = 0
# AX4 = AX5 = AX6 = AX7 = 0
#
cla
#---------------------------------------------------------------------------#
# Byte-wise / bit-wise manipulation instructions #
#---------------------------------------------------------------------------#
#
# Byte/word/dword swap (xSWAP)
#
# Change endianness
#
bswap rm rim
wswap rm rim
dswap rm rim

82
vm/in/MOV Normal file
View File

@ -0,0 +1,82 @@
# The OS/K Team licenses this file to you under the MIT license.
# See the LICENSE file in the project root for more information.
#---------------------------------------------------------------------------#
# 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
#
# Movement with zero-extension (MOVZX) instruction
#
# $1 = ZeroExtend($2)
#
movzx rm m
#
# 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
#
# Load argument #N (LDARG)
#
# IF ($2 < 8) THEN
# $1 = AX$2
# ELSE
# $1 = LX($2-8)
# FI
#
# Throws:
# #ILL if $2 ≥ 16
#
ldarg rm rim
#
# Get code/data offset (GCO/GCD)
#
# $1 = CR1 (GCO)
# $1 = CR2 (GCD)
#
gco rm
gcd rm

55
vm/in/STACK Normal file
View File

@ -0,0 +1,55 @@
# The OS/K Team licenses this file to you under the MIT license.
# See the LICENSE file in the project root for more information.
#---------------------------------------------------------------------------#
# Stack manipulation instructions #
#---------------------------------------------------------------------------#
#
# Unconditional jump with possible return (CALL)
#
# PUSH(RIP)
# JMP(RIP)
#
call rim
#
# Return to caller (RET)
#
# POP(RIP)
#
ret
#
# Make new stack frame (ENTER)
#
# PUSH(RBP)
# RBP = RSP
# RSP = RSP - $1
#
enter i
#
# Leave stack frame (LEAVE)
#
# RSP = RBP
# POP(RBP)
#
leave
#
# PUSH value onto stack
#
# RSP = RSP - 8
# *RSP = $1
#
push rim
#
# POP value from stack
#
# $1 = *RSP
# RSP = RSP + 8
#
pop rm

129
vm/in/STRING Normal file
View File

@ -0,0 +1,129 @@
# The OS/K Team licenses this file to you under the MIT license.
# See the LICENSE file in the project root for more information.
#---------------------------------------------------------------------------#
# String manipulation instructions #
#---------------------------------------------------------------------------#
#
# Store value into string (STOSx)
#
# [%1] = $2
# IF (DF == 0) THEN
# %str = %str + sizeof(x)
# ELSE
# %str = %str - sizeof(x)
# FI
#
# When no parameters are given, %str = RDI and $val = RAX
# When one parameter is given, %str = RDI and $val = $1
# When two parameters are given, %str = $1 and $val = $2
#
stosb r rim
stosw r rim
stosl r rim
stosq r rim
#
# Load value from string (LODSx)
#
# $1 = [%2]
# IF (DF == 0) THEN
# %str = %str + sizeof(x)
# ELSE
# %str = %str - sizeof(x)
# FI
#
# Preserves CF, OF and SF
# Sets ZF according to the loaded value
#
lodsb r r
lodsw r r
lodsl r r
lodsq r r
#
# Scan string for a particular value (SCASx)
#
# CMP([%1], $2)
#
# IF ([%1] == 0) THEN
# ZF = 1
# ELIF (ZF == 0) THEN
# IF (DF == 0) THEN
# %1 = %1 + sizeof(x)
# ELSE
# %1 = %1 - sizeof(x)
# FI
# FI
#
# Sets CF, OF and SF according to the result of the comparison
# Sets ZF according to whether [%1] and $2 are equal, OR if [%1] is null
#
# Notes:
# - Does not move past the value when found
# - 'SCASB.REP.NZ reg ch' is a short 'strchnul()'
#
scasb r rim
scasw r rim
scasl r rim
scasq r rim
#
# Compare bytes in strings (CMPSx)
#
# CMP([%1], [%2])
#
# IF (DF == 0) THEN
# %1 = %1 + sizeof(x)
# %2 = %2 + sizeof(x)
# ELSE
# %1 = %1 - sizeof(x)
# %2 = %2 - sizeof(x)
# FI
#
# Sets CF, OF, ZF and SF according to the result of the comparison
#
# Moves past the compared values in any case!
#
cmpsb r r
cmpsw r r
cmpsl r r
cmpsq r r
#
# Safe compare bytes in strings (CMPZSx)
#
# Behaves precisely like CMPSx, except in the following case:
# - If both [%1] and [%2] are zero, clears ZF (indicating NOT EQUAL)
#
# This prevents 'CMPZSx.REP.Z' from looping infinitely when both strings
# have the exact same content; this allows for short strcmp's
#
cmpzsb r r
cmpzsw r r
cmpzsl r r
cmpzsq r r
#
# Move value from string to string (MOVSx)
#
# [%1] = [%1]
# IF (DF == 0) THEN
# %1 = %1 + sizeof(x)
# %2 = %2 + sizeof(x)
# ELSE
# %1 = %1 - sizeof(x)
# %2 = %2 - sizeof(x)
# FI
#
# Preserves CF, OF and SF
# Sets ZF according to the moved value
#
movsb r r
movsw r r
movsl r r
movsq r r
#---------------------------------------------------------------------------#

37
vm/in/SUPER Normal file
View File

@ -0,0 +1,37 @@
# The OS/K Team licenses this file to you under the MIT license.
# See the LICENSE file in the project root for more information.
#---------------------------------------------------------------------------#
# Supervisor only instructions #
#---------------------------------------------------------------------------#
#
# Initiate machine shutdown (STOP)
#
# THROW #SHT
#
# Throws:
# #SYS if not in supervisor mode
# #ILL if disabled through DV
# #SHT otherwise
#
stop
#
# Halt the processor until next E/I (HLT)
#
hlt
#
# 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

20
vm/in/TRAP Normal file
View File

@ -0,0 +1,20 @@
# The OS/K Team licenses this file to you under the MIT license.
# See the LICENSE file in the project root for more information.
#---------------------------------------------------------------------------#
# E/I handling instructions #
#---------------------------------------------------------------------------#
#
# Trap into exception handler (TRAP)
#
# Throw:
# #ILL if $1 > 255
# #($1+256) otherwise
#
trap rim
#
# Return from exception/interrupt (IRET)
#
iret

7
vm/in/arch_i.c Normal file
View File

@ -0,0 +1,7 @@
// 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 <in/instrs.h>
#define _NEED_ARCH_I
#include <in/arch_i.h>

View File

@ -5,6 +5,114 @@
from tempfile import TemporaryFile 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):
for c1 in p1:
for c2 in p2:
fp.write("{} {} {}".format(i, c1, c2).strip())
fp.write('\n')
def parse_1(fi, fp):
global count
# "instr ri ri" => "instr r r\ninstr r i\ninstr i r..."
# not optimal but will do for now
for _, line in enumerate(fi):
if line[0] == '#' or line[0] == ' ' or line[0] == '\n':
continue
line = line.strip()
if line[:8] == "include ":
_, fn = line.split(' ', 1)
fi2 = open(fn[1:-1])
parse_1(fi2, fp)
continue
tok = line.split(' ')
if len(tok) == 0:
continue
i = tok[0].strip()
if len(tok) == 1:
doprnt(fp, i, ' ', ' ')
continue
if len(tok) == 2:
p = tok[1].strip()
doprnt(fp, i, p, ' ')
continue
assert(len(tok) == 3)
p1 = tok[1].strip()
p2 = tok[2].strip()
doprnt(fp, i, p1, p2)
fi.close()
def parse_2(fp):
global count
fp.seek(0)
for _, line in enumerate(fp):
tok = line.strip().split(' ')
assert(len(tok) > 0)
deprecated = ''
if tok[0][0] == '!':
assert(len(tok[0]) > 1)
deprecated = '__'
tok[0] = tok[0][1:]
if len(tok) == 1:
name = tok[0]
p1 = "NOPRM"
p2 = "NOPRM"
elif len(tok) == 2:
name = "{}_{}".format(tok[0], tok[1].strip())
p1 = getflag(tok[1])
p2 = "NOPRM"
elif len(tok) == 3:
name = "{}_{}_{}".format(tok[0], tok[1], tok[2].strip())
p1 = getflag(tok[1])
p2 = getflag(tok[2])
else:
name = "__TOK_ERROR__"
p1 = "__TOK_ERROR__"
p2 = "__TOK_ERROR__"
ls.write("{}{}\n".format(deprecated, name))
hd.write("#ifdef _NEED_ARCH_I\n")
hd.write('{{ "{}{}", "{}{}", {}, {}, i_{} }},\n'\
.format(deprecated, tok[0], deprecated, name, p1, p2, tok[0]))
hd.write("#else\n")
hd.write("#define I_{} {}\n".format(name.upper(), count))
hd.write("extern bool i_{}(ctx_t *, acc_t *, acc_t *, ulong *, ulong *);\n"
.format(tok[0]))
hd.write("#endif\n\n")
count = count + 1
fi = open("INSTRS") fi = open("INSTRS")
hd = open("arch_i.h", "w") hd = open("arch_i.h", "w")
ls = open("instrs.lst", "w") ls = open("instrs.lst", "w")
@ -18,99 +126,8 @@ hd.write("instr_t arch_i[] =\n{\n\n")
hd.write("#endif\n") hd.write("#endif\n")
fp = TemporaryFile(mode="w+") fp = TemporaryFile(mode="w+")
parse_1(fi, fp)
def getflag(s): parse_2(fp)
if s == "r":
return "P_REG"
if s == "i":
return "P_IMM"
if s == "m":
return "P_MEM"
return "__FLAG_ERROR__"
def doprnt(i, p1, p2):
for c1 in p1:
for c2 in p2:
fp.write("{} {} {}".format(i, c1, c2).strip())
fp.write('\n')
# "instr ri ri" => "instr r r\ninstr r i\ninstr i r..."
# not optimal but will do for now
for _, line in enumerate(fi):
if line[0] == '#' or line[0] == ' ' or line[0] == '\n':
continue
tok = line.strip().split(' ')
if len(tok) == 0:
continue
i = tok[0].strip()
if len(tok) == 1:
doprnt(i, ' ', ' ')
continue
if len(tok) == 2:
p = tok[1].strip()
doprnt(i, p, ' ')
continue
assert(len(tok) == 3)
p1 = tok[1].strip()
p2 = tok[2].strip()
doprnt(i, p1, p2)
fp.seek(0)
for _, line in enumerate(fp):
tok = line.strip().split(' ')
assert(len(tok) > 0)
deprecated = ''
if tok[0][0] == '!':
assert(len(tok[0]) > 1)
deprecated = '__'
tok[0] = tok[0][1:]
if len(tok) == 1:
name = tok[0]
p1 = "NOPRM"
p2 = "NOPRM"
elif len(tok) == 2:
name = "{}_{}".format(tok[0], tok[1].strip())
p1 = getflag(tok[1])
p2 = "NOPRM"
elif len(tok) == 3:
name = "{}_{}_{}".format(tok[0], tok[1], tok[2].strip())
p1 = getflag(tok[1])
p2 = getflag(tok[2])
else:
name = "__TOK_ERROR__"
p1 = "__TOK_ERROR__"
p2 = "__TOK_ERROR__"
ls.write("{}{}\n".format(deprecated, name))
hd.write("#ifdef _NEED_ARCH_I\n")
hd.write('{{ "{}{}", "{}{}", {}, {}, i_{} }},\n'\
.format(deprecated, tok[0], deprecated, name, p1, p2, tok[0]))
hd.write("#else\n")
hd.write("#define I_{} {}\n".format(name.upper(), count))
hd.write("extern bool i_{}(ctx_t *, acc_t *, acc_t *, ulong *, ulong *);\n"
.format(tok[0]))
hd.write("#endif\n\n")
count = count + 1
hd.write("#ifdef _NEED_ARCH_I\n") hd.write("#ifdef _NEED_ARCH_I\n")
hd.write("};\n") hd.write("};\n")
@ -120,5 +137,4 @@ hd.write("#endif\n")
ls.close() ls.close()
hd.close() hd.close()
fi.close()

View File

@ -1,106 +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 <pc/device.h>
#include <in/instrs.h>
//
// code common to devctl and iocall
//
dev_t *devctl_common(ctx_t *ctx, ulong v1, ulong v2)
{
dev_t *dev = devget(ctx, v1);
if (!dev)
rax = -2;
else if (dev->state == DEVPWOF)
rax = -3;
else if (dev->state == DEVFERR)
rax = -4;
else if (dev->state == DEVPLUG)
rax = -5;
else
return dev;
return NULL;
}
void copystr(ctx_t *ctx, ulong addr, ulong maxn, char *str)
{
for (; *str && maxn > 0; str++, addr++, maxn--) {
writemem(ctx, *str, addr, 1);
}
writemem(ctx, 0, addr, 1);
}
IMPL_START_2(devctl)
{
CHK_SUPERV();
dev_t *dev = devctl_common(ctx, v1, v2);
if (dev == NULL)
return 0;
switch (v2) {
case 0:
copystr(ctx, ax0, DEVLEN, dev->type);
break;
case 1:
copystr(ctx, ax0, DEVLEN, dev->name);
break;
case 2:
copystr(ctx, ax0, DEVLEN, dev->modl);
break;
case 3:
copystr(ctx, ax0, DEVLEN, dev->vend);
break;
case 4:
rax = dev->major;
rdx = dev->minor;
break;
case 5:
rax = dev->feats;
rdx = dev->revis;
break;
default:
rax = -6;
break;
}
}
IMPL_END;
IMPL_START_2(iocall)
{
CHK_SUPERV();
long rc;
dev_t *dev = devctl_common(ctx, v1, v2);
if (dev == NULL)
return 0;
if (v2 >= DEVSLOTS)
rax = -6;
else if (dev->fslots[v2] == NULL)
rax = -6;
else {
rc = dev->fslots[v2](ctx, dev);
if (rc < 0) rax = rc;
}
}
IMPL_END;

View File

@ -5,6 +5,22 @@
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
IMPL_START_0(cli)
{
CHK_SUPERV();
cr0 &= ~IF;
}
IMPL_END;
IMPL_START_0(sti)
{
CHK_SUPERV();
cr0 |= IF;
}
IMPL_END;
//----------------------------------------------------------------------------//
IMPL_START_0(cld) IMPL_START_0(cld)
{ {
flg &= ~DF; flg &= ~DF;

View File

@ -1,90 +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 <in/instrs.h>
#include <sys/time.h>
#include <unistd.h>
#include <time.h>
#include <pc/console.h>
#define _NEED_ARCH_I
#include <in/arch_i.h>
//----------------------------------------------------------------------------//
IMPL_START_0(nop)
{
}
IMPL_END;
//----------------------------------------------------------------------------//
IMPL_START_0(pause)
{
usleep(5000);
}
IMPL_END;
IMPL_START_0(xpause)
{
CHK_SUPERV();
usleep(25000);
}
IMPL_END;
//----------------------------------------------------------------------------//
IMPL_START_0(cpuid)
{
rax = rdx = 0;
}
IMPL_END;
//----------------------------------------------------------------------------//
IMPL_START_1(rand32)
{
v1 = (int)random();
}
IMPL_OUT;
IMPL_START_1(rand64)
{
v1 = (random() << 32) | (int)random();
}
IMPL_OUT;
//----------------------------------------------------------------------------//
IMPL_START_1(time)
{
v1 = time(NULL);
}
IMPL_OUT;
IMPL_START_1(utime)
{
struct timeval time;
gettimeofday(&time, NULL);
v1 = (time.tv_sec * 1000) + (time.tv_usec / 1000);
}
IMPL_OUT;
//----------------------------------------------------------------------------//
IMPL_START_0(clr)
{
rax = rbx = rcx = rdx = 0;
rsx = rbi = rdi = rsi = 0;
}
IMPL_END;
IMPL_START_0(cla)
{
ax0 = ax1 = ax2 = ax3 = 0;
ax4 = ax5 = ax6 = ax7 = 0;
}
IMPL_END;
//----------------------------------------------------------------------------//

View File

@ -2,6 +2,71 @@
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
#include <in/instrs.h> #include <in/instrs.h>
#include <sys/time.h>
#include <unistd.h>
#include <time.h>
//----------------------------------------------------------------------------//
IMPL_START_0(nop)
{
}
IMPL_END;
//----------------------------------------------------------------------------//
IMPL_START_0(pause)
{
usleep(5000);
}
IMPL_END;
IMPL_START_0(xpause)
{
CHK_SUPERV();
usleep(25000);
}
IMPL_END;
//----------------------------------------------------------------------------//
IMPL_START_0(cpuid)
{
rax = rdx = 0;
}
IMPL_END;
//----------------------------------------------------------------------------//
IMPL_START_1(time)
{
v1 = time(NULL);
}
IMPL_OUT;
IMPL_START_1(utime)
{
struct timeval time;
gettimeofday(&time, NULL);
v1 = (time.tv_sec * 1000) + (time.tv_usec / 1000);
}
IMPL_OUT;
//----------------------------------------------------------------------------//
IMPL_START_0(clr)
{
rax = rbx = rcx = rdx = 0;
rsx = rbi = rdi = rsi = 0;
}
IMPL_END;
IMPL_START_0(cla)
{
ax0 = ax1 = ax2 = ax3 = 0;
ax4 = ax5 = ax6 = ax7 = 0;
}
IMPL_END;
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//

View File

@ -2,9 +2,17 @@
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
#include <unistd.h> #include <unistd.h>
#include <pc/device.h>
#include <in/instrs.h> #include <in/instrs.h>
#include <pc/console.h> #include <pc/console.h>
IMPL_START_0(stop)
{
CHK_SUPERV();
_except(ctx, E_SHT, "STOP INSTR");
}
IMPL_END;
IMPL_START_0(hlt) IMPL_START_0(hlt)
{ {
CHK_SUPERV(); CHK_SUPERV();
@ -21,24 +29,103 @@ IMPL_START_0(hlt)
} }
IMPL_END; IMPL_END;
IMPL_START_0(cli) //
// code common to devctl and iocall
//
dev_t *devctl_common(ctx_t *ctx, ulong v1, ulong v2)
{
dev_t *dev = devget(ctx, v1);
if (!dev)
rax = -2;
else if (dev->state == DEVPWOF)
rax = -3;
else if (dev->state == DEVFERR)
rax = -4;
else if (dev->state == DEVPLUG)
rax = -5;
else
return dev;
return NULL;
}
void copystr(ctx_t *ctx, ulong addr, ulong maxn, char *str)
{
for (; *str && maxn > 0; str++, addr++, maxn--) {
writemem(ctx, *str, addr, 1);
}
writemem(ctx, 0, addr, 1);
}
IMPL_START_2(devctl)
{ {
CHK_SUPERV(); CHK_SUPERV();
cr0 &= ~IF;
dev_t *dev = devctl_common(ctx, v1, v2);
if (dev == NULL)
return 0;
switch (v2) {
case 0:
copystr(ctx, ax0, DEVLEN, dev->type);
break;
case 1:
copystr(ctx, ax0, DEVLEN, dev->name);
break;
case 2:
copystr(ctx, ax0, DEVLEN, dev->modl);
break;
case 3:
copystr(ctx, ax0, DEVLEN, dev->vend);
break;
case 4:
rax = dev->major;
rdx = dev->minor;
break;
case 5:
rax = dev->feats;
rdx = dev->revis;
break;
default:
rax = -6;
break;
}
} }
IMPL_END; IMPL_END;
IMPL_START_0(sti) IMPL_START_2(iocall)
{ {
CHK_SUPERV(); CHK_SUPERV();
cr0 |= IF;
} long rc;
IMPL_END; dev_t *dev = devctl_common(ctx, v1, v2);
IMPL_START_0(stop) if (dev == NULL)
{ return 0;
CHK_SUPERV();
_except(ctx, E_SHT, "STOP INSTR"); if (v2 >= DEVSLOTS)
rax = -6;
else if (dev->fslots[v2] == NULL)
rax = -6;
else {
rc = dev->fslots[v2](ctx, dev);
if (rc < 0) rax = rc;
}
} }
IMPL_END; IMPL_END;

View File

@ -3,8 +3,6 @@
#include <in/instrs.h> #include <in/instrs.h>
static volatile long *prev_stk;
IMPL_START_1(trap) IMPL_START_1(trap)
{ {
if (v1 > 255) if (v1 > 255)

View File

@ -3,8 +3,15 @@
#include <pc/console.h> #include <pc/console.h>
#define CONSOLE_WIDTH 80 #ifndef _LARGE_SCREEN
#define CONSOLE_HEIGHT 25 # define CONSOLE_WIDTH 80
# define CONSOLE_HEIGHT 25
# define CONSOLE_FONT_SIZE 16
#else
# define CONSOLE_WIDTH 160
# define CONSOLE_HEIGHT 50
# define CONSOLE_FONT_SIZE 32
#endif
#define SCREEN_WIDTH (9 * CONSOLE_WIDTH) #define SCREEN_WIDTH (9 * CONSOLE_WIDTH)
#define SCREEN_HEIGHT (16 * CONSOLE_HEIGHT) #define SCREEN_HEIGHT (16 * CONSOLE_HEIGHT)
@ -43,7 +50,7 @@ void console_init(ctx_t *ctx)
TTF_Init(); TTF_Init();
scr_font = TTF_OpenFont scr_font = TTF_OpenFont
("fn/console_font.ttf", 16); ("fn/console_font.ttf", CONSOLE_FONT_SIZE);
if (scr_font == NULL) if (scr_font == NULL)
{ {

View File

@ -28,7 +28,11 @@ void dump_instr(ctx_t *ctx,
uint cond, uint cond,
ulong pc) ulong pc)
{ {
/*
trace("%03lu 0x%lX:\t", ctx->ninstrs, pc); trace("%03lu 0x%lX:\t", ctx->ninstrs, pc);
*/
trace("0x%lX:\t", pc);
if (lock) if (lock)
trace("lock"); trace("lock");

View File

@ -10,7 +10,6 @@ void _except(ctx_t *ctx, int _code, char *fmt, ...)
va_list ap; va_list ap;
ulong handler; ulong handler;
uint code = _code; uint code = _code;
volatile char ch;
ulong orig_frame; ulong orig_frame;