Converted addressing to simple 64-bit integers
This commit is contained in:
parent
d234d5180d
commit
e2642ec3ac
452
src/arctic.nim
452
src/arctic.nim
|
@ -1,11 +1,11 @@
|
||||||
import std/[atomics, bitops, critbits, strformat, strutils, strmisc, math, re]
|
import std/[atomics, bitops, critbits, strformat, strutils, strmisc, tables, math, re]
|
||||||
import bio
|
import bio
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
|
import memory
|
||||||
|
|
||||||
type
|
type
|
||||||
BitShiftType = range[0 .. 64]
|
ArcticPointer = int64
|
||||||
ArcticTypeKind* = enum
|
|
||||||
BYTE, SHORT, INT, WORD, DOUBLE
|
|
||||||
|
|
||||||
ArcticType* {.union.} = object
|
ArcticType* {.union.} = object
|
||||||
b: int8
|
b: int8
|
||||||
|
@ -14,25 +14,19 @@ type
|
||||||
i: int64
|
i: int64
|
||||||
u: uint64
|
u: uint64
|
||||||
d: float64
|
d: float64
|
||||||
f: ArcticSymbol # also used for pointers
|
p: ArcticPointer # always positive (null is 0)
|
||||||
# TODO: Eventually replace f with p/f and each is just a uint64
|
f: ArcticPointer # always negative (null is 0)
|
||||||
# Then load all memory into one long seq instead of 1 seq per
|
# TODO: check that appropriate p/f is used (there are a lot of legacy .f's hanging around)
|
||||||
# section. Probably actually have +ve be data memory, and -ve be
|
|
||||||
# code memory (with sections mapping to ranges)
|
|
||||||
|
|
||||||
ArcticVariableIndex* = enum
|
ArcticVariableIndex = enum
|
||||||
VARIABLE_A, VARIABLE_B, VARIABLE_C,
|
VARIABLE_A, VARIABLE_B, VARIABLE_C,
|
||||||
VARIABLE_I, VARIABLE_N,
|
VARIABLE_I, VARIABLE_N,
|
||||||
VARIABLE_X, VARIABLE_Y, VARIABLE_Z
|
VARIABLE_X, VARIABLE_Y, VARIABLE_Z
|
||||||
|
|
||||||
ArcticSymbol* = tuple
|
ArcticImmediateKind = enum
|
||||||
section: string
|
|
||||||
index: int
|
|
||||||
|
|
||||||
ArcticImmediateKind* = enum
|
|
||||||
PLAIN, VARIABLE, INTEGER, NUMBER, SYMBOL
|
PLAIN, VARIABLE, INTEGER, NUMBER, SYMBOL
|
||||||
|
|
||||||
ArcticImmediate* = object
|
ArcticImmediate = object
|
||||||
case kind: ArcticImmediateKind
|
case kind: ArcticImmediateKind
|
||||||
of PLAIN: nil
|
of PLAIN: nil
|
||||||
of VARIABLE: v: ArcticVariableIndex
|
of VARIABLE: v: ArcticVariableIndex
|
||||||
|
@ -40,34 +34,27 @@ type
|
||||||
of NUMBER: n: float64
|
of NUMBER: n: float64
|
||||||
of SYMBOL: s: string
|
of SYMBOL: s: string
|
||||||
|
|
||||||
ArcticOperation* = object
|
ArcticOperation = object
|
||||||
code: char
|
code: char
|
||||||
immediate: ArcticImmediate
|
immediate: ArcticImmediate
|
||||||
|
bigendian: bool
|
||||||
|
|
||||||
ArcticCode* = seq[ArcticOperation]
|
ArcticStack = seq[ArcticType]
|
||||||
ArcticMemory* = seq[uint8]
|
|
||||||
|
|
||||||
ArcticSection* = object
|
|
||||||
case iscode: bool
|
|
||||||
of true: code: ArcticCode
|
|
||||||
of false: data: ArcticMemory
|
|
||||||
ArcticStack* = seq[ArcticType]
|
|
||||||
|
|
||||||
ArcticState* = object
|
ArcticState* = object
|
||||||
symbols: CritBitTree[ArcticSymbol] # as name or section _name
|
memory: Memory[uint8]
|
||||||
sections: CritBitTree[ArcticSection]
|
code: Memory[ArcticOperation]
|
||||||
|
symbols: CritBitTree[ArcticPointer] # as name or section _name
|
||||||
stack: ArcticStack
|
stack: ArcticStack
|
||||||
pc: ArcticSymbol
|
pc: ArcticPointer # NOT negative!
|
||||||
registers: array[ArcticVariableIndex, ArcticType]
|
registers: array[ArcticVariableIndex, ArcticType]
|
||||||
|
dynmem: Table[ArcticPointer, int] # pointer -> length
|
||||||
|
|
||||||
ArcticStepResult* = enum
|
ArcticStepResult* = enum
|
||||||
CONTINUE, BREAKPOINT, ERROR
|
CONTINUE, BREAKPOINT, ERROR
|
||||||
|
|
||||||
ArcticBuiltin* = proc (state: var ArcticState): ArcticStepResult
|
ArcticBuiltin* = proc (state: var ArcticState): ArcticStepResult
|
||||||
|
|
||||||
var
|
|
||||||
next_malloc_id: int = 1
|
|
||||||
|
|
||||||
const
|
const
|
||||||
ImmediateOps: set[char] = {'0', 'E', 'F', 'G', 'H', 'L', 'M', 'P', 'Q', 'd', 'o', 'u', '<', '{', '=', '}', '>', ',', ';', '[', ']'}
|
ImmediateOps: set[char] = {'0', 'E', 'F', 'G', 'H', 'L', 'M', 'P', 'Q', 'd', 'o', 'u', '<', '{', '=', '}', '>', ',', ';', '[', ']'}
|
||||||
PlainOps : set[char] = { '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'I', 'J', 'K', 'N', 'O', 'R', 'S', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z', '_', '.', '+', '-', '*', '/', '%', '\\', '|', '&', '^', '!', '?', '(', ')', '`' }
|
PlainOps : set[char] = { '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'I', 'J', 'K', 'N', 'O', 'R', 'S', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z', '_', '.', '+', '-', '*', '/', '%', '\\', '|', '&', '^', '!', '?', '(', ')', '`' }
|
||||||
|
@ -105,34 +92,27 @@ proc `$`*(state: ArcticState): string =
|
||||||
for item in state.stack:
|
for item in state.stack:
|
||||||
result &= &" {item}\n"
|
result &= &" {item}\n"
|
||||||
|
|
||||||
for (name, section) in state.sections.pairs:
|
for section in state.code.sections:
|
||||||
result &= &"\n\"{name}\": "
|
result &= "\n"
|
||||||
if section.iscode:
|
for (i, m) in state.code.data(section).pairs:
|
||||||
result &= "code \n"
|
for (label, location) in state.symbols.pairs:
|
||||||
for (i, m) in section.code.pairs:
|
if -location == state.code.address(section, i):
|
||||||
for (label, location) in state.symbols.pairs:
|
result &= &":{label} "
|
||||||
if location.section == name and location.index == i:
|
if state.pc == state.code.address(section, i):
|
||||||
result &= &":{label} "
|
|
||||||
if state.pc.section == name and state.pc.index == i:
|
|
||||||
result &= ">"
|
result &= ">"
|
||||||
result &= $m
|
result &= $m
|
||||||
else:
|
|
||||||
result &= "\n"
|
for section in state.memory.sections:
|
||||||
for (i, m) in section.data.pairs:
|
result &= "\n"
|
||||||
for (label, location) in state.symbols.pairs:
|
for (i, m) in state.memory.data(section).pairs:
|
||||||
if location.section == name and location.index == i:
|
for (label, location) in state.symbols.pairs:
|
||||||
result &= &":{label} "
|
if location == state.memory.address(section, i):
|
||||||
result &= &"{m} "
|
result &= &":{label} "
|
||||||
|
result &= &"{m} "
|
||||||
|
|
||||||
proc op(code: char, immediate: ArcticImmediate = ArcticImmediate(kind: PLAIN)): ArcticOperation =
|
proc op(code: char, immediate: ArcticImmediate = ArcticImmediate(kind: PLAIN)): ArcticOperation =
|
||||||
return ArcticOperation(code: code, immediate: immediate)
|
return ArcticOperation(code: code, immediate: immediate)
|
||||||
|
|
||||||
proc add(section: var ArcticSection, code: char) =
|
|
||||||
if section.iscode:
|
|
||||||
section.code.add code.op
|
|
||||||
else:
|
|
||||||
section.data.add code.uint8
|
|
||||||
|
|
||||||
proc tovar(code: char): ArcticVariableIndex =
|
proc tovar(code: char): ArcticVariableIndex =
|
||||||
case code.toLowerAscii:
|
case code.toLowerAscii:
|
||||||
of 'a': VARIABLE_A
|
of 'a': VARIABLE_A
|
||||||
|
@ -145,25 +125,18 @@ proc tovar(code: char): ArcticVariableIndex =
|
||||||
of 'z': VARIABLE_Z
|
of 'z': VARIABLE_Z
|
||||||
else: raise new ValueError
|
else: raise new ValueError
|
||||||
|
|
||||||
proc add(section: var ArcticSection, code: char, immstr: string, secname: string) =
|
proc parse_immediate(imm: string, section: string): ArcticImmediate =
|
||||||
if section.iscode:
|
if imm.match(re"^\d+$"):
|
||||||
if immstr.match(re"^\d+$"):
|
return ArcticImmediate(kind: INTEGER, i: imm.parseInt)
|
||||||
section.code.add code.op(ArcticImmediate(kind: INTEGER, i: immstr.parseInt))
|
elif imm.match(re"^[AaBbCcIiNnXxYyZz]$"):
|
||||||
elif immstr.match(re"^[AaBbCcIiNnXxYyZz]$"):
|
return ArcticImmediate(kind: VARIABLE, v: imm[0].tovar)
|
||||||
section.code.add code.op(ArcticImmediate(kind: VARIABLE, v: immstr[0].tovar))
|
elif imm[0] == '$':
|
||||||
elif immstr[0] == '$':
|
if imm.len == 1 or imm[1] == '_':
|
||||||
if immstr.len == 1 or immstr[1] == '_':
|
return ArcticImmediate(kind: SYMBOL, s: section & " " & imm)
|
||||||
section.code.add code.op(ArcticImmediate(kind: SYMBOL, s: secname & " " & immstr))
|
|
||||||
else:
|
|
||||||
section.code.add code.op(ArcticImmediate(kind: SYMBOL, s: immstr))
|
|
||||||
else:
|
else:
|
||||||
section.code.add code.op(ArcticImmediate(kind: NUMBER, n: immstr.parseFloat))
|
return ArcticImmediate(kind: SYMBOL, s: imm)
|
||||||
|
|
||||||
proc len(section: ArcticSection): int =
|
|
||||||
if section.iscode:
|
|
||||||
return section.code.len
|
|
||||||
else:
|
else:
|
||||||
return section.data.len
|
return ArcticImmediate(kind: NUMBER, n: imm.parseFloat)
|
||||||
|
|
||||||
func grabnum(data: string): (string, string) =
|
func grabnum(data: string): (string, string) =
|
||||||
## Returns the numeric literal at the start of data, then the rest of data
|
## Returns the numeric literal at the start of data, then the rest of data
|
||||||
|
@ -174,24 +147,21 @@ func grabnum(data: string): (string, string) =
|
||||||
|
|
||||||
result[1] = data[i..^1]
|
result[1] = data[i..^1]
|
||||||
|
|
||||||
proc insert(section: var ArcticSection, data: string) =
|
proc parse_data(data: string): seq[uint8] =
|
||||||
if data.len == 0:
|
if data.len == 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
if section.iscode:
|
|
||||||
return
|
|
||||||
|
|
||||||
template insertInt(itype, utype, endianness) =
|
template insertInt(itype, utype, endianness) =
|
||||||
let (text, rest) = data[1..^1].grabnum
|
let (text, rest) = data[1..^1].grabnum
|
||||||
|
|
||||||
if text[0] == '-':
|
if text[0] == '-':
|
||||||
let val: itype = itype(-text[1..^1].parseBiggestInt)
|
let val: itype = itype(-text[1..^1].parseBiggestInt)
|
||||||
section.data.add cast[utype](val).serialize(endianness)
|
result.add cast[utype](val).serialize(endianness)
|
||||||
else:
|
else:
|
||||||
let val: utype = utype(text.parseBiggestUInt)
|
let val: utype = utype(text.parseBiggestUInt)
|
||||||
section.data.add val.serialize(endianness)
|
result.add val.serialize(endianness)
|
||||||
|
|
||||||
section.insert(rest)
|
result.add parse_data(rest)
|
||||||
|
|
||||||
case data[0]:
|
case data[0]:
|
||||||
of 'i': insertInt(int64, uint64, littleEndian)
|
of 'i': insertInt(int64, uint64, littleEndian)
|
||||||
|
@ -204,48 +174,59 @@ proc insert(section: var ArcticSection, data: string) =
|
||||||
let (text, rest) = data[1..^1].grabnum
|
let (text, rest) = data[1..^1].grabnum
|
||||||
|
|
||||||
if text[0] == '-':
|
if text[0] == '-':
|
||||||
let val: int8 = int8(text[1..^1].parseBiggestInt)
|
let val: int8 = int8(-text[1..^1].parseBiggestInt)
|
||||||
section.data.add cast[uint8](val)
|
result.add cast[uint8](val)
|
||||||
else:
|
else:
|
||||||
let val: uint8 = uint8(text.parseBiggestUInt)
|
let val: uint8 = uint8(text.parseBiggestUInt)
|
||||||
section.data.add val
|
result.add val
|
||||||
|
result.add parse_data(rest)
|
||||||
|
|
||||||
of 'f':
|
of 'f':
|
||||||
let (text, rest) = data[1..^1].grabnum
|
let (text, rest) = data[1..^1].grabnum
|
||||||
section.data.add cast[uint64](text.parseFloat).serialize(littleEndian)
|
result.add cast[uint64](text.parseFloat).serialize(littleEndian)
|
||||||
section.insert(rest)
|
result.add parse_data(rest)
|
||||||
|
|
||||||
of 'F':
|
of 'F':
|
||||||
let (text, rest) = data[1..^1].grabnum
|
let (text, rest) = data[1..^1].grabnum
|
||||||
section.data.add cast[uint64](text.parseFloat).serialize(bigEndian)
|
result.add cast[uint64](text.parseFloat).serialize(bigEndian)
|
||||||
section.insert(rest)
|
result.add parse_data(rest)
|
||||||
|
|
||||||
of 'x': # hexadecimal byte constant
|
of 'x': # hexadecimal byte constant
|
||||||
let (hex, x, rest) = data[1..^1].partition("x")
|
let (hex, x, rest) = data[1..^1].partition("x")
|
||||||
for pair in hex.chunked(2):
|
for pair in hex.chunked(2):
|
||||||
section.data.add uint8(parseHexInt(pair.join))
|
result.add uint8(parseHexInt(pair.join))
|
||||||
section.insert(rest)
|
result.add parse_data(rest)
|
||||||
|
|
||||||
of '"': # utf-8 string constant with escapes
|
of '"': # utf-8 string constant with escapes
|
||||||
let strlen = data.matchLen(re"^""([^""]|\\"")*""")
|
let strlen = data.matchLen(re"^""([^""]|\\"")*""")
|
||||||
|
assert strlen >= 0
|
||||||
if strlen < 0:
|
for c in unescape(data[1..strlen]):
|
||||||
return # TODO: couldn't find a string, what to do?
|
result.add c.uint8
|
||||||
|
result.add parse_data(data[strlen..^1])
|
||||||
for c in data[1..^(strlen-2)]:
|
|
||||||
section.data.add c.uint8
|
|
||||||
|
|
||||||
section.insert(data[strlen..^1])
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
section.insert(data[1..^1])
|
result.add parse_data(data[1..^1])
|
||||||
|
|
||||||
|
func iscode(secname: string): bool =
|
||||||
|
if secname.len == 0:
|
||||||
|
return true
|
||||||
|
return secname[0] in "cC"
|
||||||
|
|
||||||
|
func isbigendian(secname: string): bool =
|
||||||
|
if secname.len == 0:
|
||||||
|
return false
|
||||||
|
return secname[0] in "C"
|
||||||
|
|
||||||
|
func raw_op(code: char): ArcticOperation =
|
||||||
|
result.code = code
|
||||||
|
result.immediate.kind = PLAIN
|
||||||
|
|
||||||
func load*(code: string): ArcticState =
|
func load*(code: string): ArcticState =
|
||||||
var
|
var
|
||||||
section: string = ""
|
section: string = ""
|
||||||
token: string = ""
|
token: string = ""
|
||||||
|
|
||||||
result.pc = ("", 0)
|
result.pc = 1
|
||||||
result.sections[section] = ArcticSection(iscode: true, code: @[])
|
|
||||||
|
|
||||||
for next in code:
|
for next in code:
|
||||||
debug_echo "token: ", token, ", next: ", next
|
debug_echo "token: ", token, ", next: ", next
|
||||||
|
@ -254,7 +235,7 @@ func load*(code: string): ArcticState =
|
||||||
of ImmediateOps, '#', ':', '\"', '\'':
|
of ImmediateOps, '#', ':', '\"', '\'':
|
||||||
token &= next
|
token &= next
|
||||||
of PlainOps, '\n':
|
of PlainOps, '\n':
|
||||||
result.sections[section].add next
|
result.code.add(section, raw_op(next))
|
||||||
else:
|
else:
|
||||||
discard
|
discard
|
||||||
else:
|
else:
|
||||||
|
@ -262,16 +243,11 @@ func load*(code: string): ArcticState =
|
||||||
of '#': # comment
|
of '#': # comment
|
||||||
if next == '\n':
|
if next == '\n':
|
||||||
token = ""
|
token = ""
|
||||||
result.sections[section].add next
|
result.code.add(section, raw_op(next))
|
||||||
|
|
||||||
of '"': # section switch
|
of '"': # section switch
|
||||||
if next == '"' and token[^1] != '\\':
|
if next == '"' and token[^1] != '\\':
|
||||||
section = token[1..^1]
|
section = token[1..^1]
|
||||||
if section notin result.sections:
|
|
||||||
if section.toLowerAscii in @["code", "macros", ""]:
|
|
||||||
result.sections[section] = ArcticSection(iscode: true, code: @[])
|
|
||||||
else:
|
|
||||||
result.sections[section] = ArcticSection(iscode: false, data: @[])
|
|
||||||
token = ""
|
token = ""
|
||||||
else:
|
else:
|
||||||
token.add next
|
token.add next
|
||||||
|
@ -279,7 +255,10 @@ func load*(code: string): ArcticState =
|
||||||
of ':': # label name
|
of ':': # label name
|
||||||
if next == ' ' or next == '\n':
|
if next == ' ' or next == '\n':
|
||||||
let idx = if token[1] == '_': section & " " & token[1..^1] else: token[1..^1]
|
let idx = if token[1] == '_': section & " " & token[1..^1] else: token[1..^1]
|
||||||
result.symbols[idx] = (section: section, index: result.sections[section].len)
|
if section.iscode:
|
||||||
|
result.symbols[idx] = -result.code.current(section)
|
||||||
|
else:
|
||||||
|
result.symbols[idx] = result.code.current(section)
|
||||||
token = ""
|
token = ""
|
||||||
else:
|
else:
|
||||||
token.add next
|
token.add next
|
||||||
|
@ -302,14 +281,17 @@ func load*(code: string): ArcticState =
|
||||||
if quoted or escaped:
|
if quoted or escaped:
|
||||||
token.add next
|
token.add next
|
||||||
else:
|
else:
|
||||||
result.sections[section].insert token[1..^1]
|
result.memory.add(section, parse_data(token[1..^1]))
|
||||||
token = ""
|
token = ""
|
||||||
else:
|
else:
|
||||||
token.add next
|
token.add next
|
||||||
|
|
||||||
of ImmediateOps:
|
of ImmediateOps:
|
||||||
if next == ' ':
|
if next == ' ':
|
||||||
result.sections[section].add(token[0], token[1..^1], section)
|
result.code.add(section, ArcticOperation(
|
||||||
|
code: token[0],
|
||||||
|
immediate: parse_immediate(token[1..^1], section),
|
||||||
|
bigendian: isbigendian(section)))
|
||||||
token = ""
|
token = ""
|
||||||
else:
|
else:
|
||||||
token.add next
|
token.add next
|
||||||
|
@ -317,54 +299,22 @@ func load*(code: string): ArcticState =
|
||||||
else:
|
else:
|
||||||
discard
|
discard
|
||||||
|
|
||||||
proc `[]`(state: ArcticState, symbol: ArcticSymbol): uint8 =
|
|
||||||
assert symbol.section in state.sections
|
|
||||||
let section = state.sections[symbol.section]
|
|
||||||
|
|
||||||
if section.iscode:
|
|
||||||
return section.code[symbol.index].code.uint8
|
|
||||||
else:
|
|
||||||
return section.data[symbol.index]
|
|
||||||
|
|
||||||
proc `[]=`(state: var ArcticState, symbol: ArcticSymbol, value: uint8) =
|
|
||||||
if not (symbol.section in state.sections):
|
|
||||||
state.sections[symbol.section] = ArcticSection(iscode: false, data: @[])
|
|
||||||
while state.sections[symbol.section].len <= symbol.index:
|
|
||||||
state.sections[symbol.section].data.add 0
|
|
||||||
state.sections[symbol.section].data[symbol.index] = value
|
|
||||||
else:
|
|
||||||
let section = state.sections[symbol.section]
|
|
||||||
|
|
||||||
while state.sections[symbol.section].data.len <= symbol.index:
|
|
||||||
state.sections[symbol.section].data.add 0
|
|
||||||
state.sections[symbol.section].data[symbol.index] = value
|
|
||||||
|
|
||||||
proc `+`(left: ArcticSymbol, offset: int): ArcticSymbol = (left.section, left.index + offset)
|
|
||||||
|
|
||||||
proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): ArcticStepResult =
|
proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): ArcticStepResult =
|
||||||
let codesec = state.sections[state.pc.section]
|
let op = state.code[state.pc]
|
||||||
|
state.pc.inc
|
||||||
if not codesec.iscode:
|
|
||||||
return ERROR
|
|
||||||
|
|
||||||
if state.pc.index >= codesec.code.len:
|
|
||||||
return ERROR
|
|
||||||
|
|
||||||
let op = codesec.code[state.pc.index]
|
|
||||||
state.pc.index.inc
|
|
||||||
|
|
||||||
case op.code:
|
case op.code:
|
||||||
# Memory Ops -----------------------------------------------------------
|
# Memory Ops -----------------------------------------------------------
|
||||||
of '1': # LDAB
|
of '1': # LDAB
|
||||||
let p = state.stack.pop.f
|
let p = state.stack.pop.p
|
||||||
state.stack.add ArcticType(i: state[p].int64)
|
state.stack.add ArcticType(i: state.memory[p].int64)
|
||||||
|
|
||||||
of '2': # LDAS
|
of '2': # LDAS
|
||||||
let
|
let
|
||||||
p = state.stack.pop.f
|
p = state.stack.pop.f
|
||||||
a = state[p].int64
|
a = state.memory[p].int64
|
||||||
b = state[p+1].int64
|
b = state.memory[p+1].int64
|
||||||
if state.pc.section == "CODE": # bigendian
|
if op.bigendian:
|
||||||
state.stack.add ArcticType(i: a or b shl 8)
|
state.stack.add ArcticType(i: a or b shl 8)
|
||||||
else:
|
else:
|
||||||
state.stack.add ArcticType(i: b or a shl 8)
|
state.stack.add ArcticType(i: b or a shl 8)
|
||||||
|
@ -372,11 +322,11 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic
|
||||||
of '3': # LDAI
|
of '3': # LDAI
|
||||||
let
|
let
|
||||||
p = state.stack.pop.f
|
p = state.stack.pop.f
|
||||||
a = state[p].int64
|
a = state.memory[p].int64
|
||||||
b = state[p+1].int64
|
b = state.memory[p+1].int64
|
||||||
c = state[p+2].int64
|
c = state.memory[p+2].int64
|
||||||
d = state[p+3].int64
|
d = state.memory[p+3].int64
|
||||||
if state.pc.section == "CODE": # bigendian
|
if op.bigendian:
|
||||||
state.stack.add ArcticType(i: d or c shl 8 or b shl 16 or a shl 24)
|
state.stack.add ArcticType(i: d or c shl 8 or b shl 16 or a shl 24)
|
||||||
else:
|
else:
|
||||||
state.stack.add ArcticType(i: a or b shl 8 or c shl 16 or d shl 24)
|
state.stack.add ArcticType(i: a or b shl 8 or c shl 16 or d shl 24)
|
||||||
|
@ -384,15 +334,15 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic
|
||||||
of '4': # LDAW
|
of '4': # LDAW
|
||||||
let
|
let
|
||||||
p = state.stack.pop.f
|
p = state.stack.pop.f
|
||||||
a = state[p].int64
|
a = state.memory[p].int64
|
||||||
b = state[p+1].int64
|
b = state.memory[p+1].int64
|
||||||
c = state[p+2].int64
|
c = state.memory[p+2].int64
|
||||||
d = state[p+3].int64
|
d = state.memory[p+3].int64
|
||||||
e = state[p+4].int64
|
e = state.memory[p+4].int64
|
||||||
f = state[p+5].int64
|
f = state.memory[p+5].int64
|
||||||
g = state[p+6].int64
|
g = state.memory[p+6].int64
|
||||||
h = state[p+7].int64
|
h = state.memory[p+7].int64
|
||||||
if state.pc.section == "CODE": # bigendian
|
if op.bigendian:
|
||||||
state.stack.add ArcticType(i: h or g shl 8 or f shl 16 or e shl 24 or d shl 32 or c shl 40 or b shl 48 or a shl 56)
|
state.stack.add ArcticType(i: h or g shl 8 or f shl 16 or e shl 24 or d shl 32 or c shl 40 or b shl 48 or a shl 56)
|
||||||
else:
|
else:
|
||||||
state.stack.add ArcticType(i: a or b shl 8 or c shl 16 or d shl 24 or e shl 32 or f shl 40 or g shl 48 or h shl 56)
|
state.stack.add ArcticType(i: a or b shl 8 or c shl 16 or d shl 24 or e shl 32 or f shl 40 or g shl 48 or h shl 56)
|
||||||
|
@ -400,15 +350,15 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic
|
||||||
of 'o': # LDOB
|
of 'o': # LDOB
|
||||||
assert op.immediate.kind == INTEGER
|
assert op.immediate.kind == INTEGER
|
||||||
let p = state.stack.pop.f
|
let p = state.stack.pop.f
|
||||||
state.stack.add ArcticType(i: state[p+op.immediate.i].int64)
|
state.stack.add ArcticType(i: state.memory[p+op.immediate.i].int64)
|
||||||
|
|
||||||
of 'H': # LDOS
|
of 'H': # LDOS
|
||||||
assert op.immediate.kind == INTEGER
|
assert op.immediate.kind == INTEGER
|
||||||
let
|
let
|
||||||
p = state.stack.pop.f + op.immediate.i
|
p = state.stack.pop.f + op.immediate.i
|
||||||
a = state[p].int64
|
a = state.memory[p].int64
|
||||||
b = state[p+1].int64
|
b = state.memory[p+1].int64
|
||||||
if state.pc.section == "CODE": # bigendian
|
if op.bigendian:
|
||||||
state.stack.add ArcticType(i: a or b shl 8)
|
state.stack.add ArcticType(i: a or b shl 8)
|
||||||
else:
|
else:
|
||||||
state.stack.add ArcticType(i: b or a shl 8)
|
state.stack.add ArcticType(i: b or a shl 8)
|
||||||
|
@ -416,11 +366,11 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic
|
||||||
of 'G': # LDOI
|
of 'G': # LDOI
|
||||||
let
|
let
|
||||||
p = state.stack.pop.f + op.immediate.i
|
p = state.stack.pop.f + op.immediate.i
|
||||||
a = state[p].int64
|
a = state.memory[p].int64
|
||||||
b = state[p+1].int64
|
b = state.memory[p+1].int64
|
||||||
c = state[p+2].int64
|
c = state.memory[p+2].int64
|
||||||
d = state[p+3].int64
|
d = state.memory[p+3].int64
|
||||||
if state.pc.section == "CODE": # bigendian
|
if op.bigendian:
|
||||||
state.stack.add ArcticType(i: d or c shl 8 or b shl 16 or a shl 24)
|
state.stack.add ArcticType(i: d or c shl 8 or b shl 16 or a shl 24)
|
||||||
else:
|
else:
|
||||||
state.stack.add ArcticType(i: a or b shl 8 or c shl 16 or d shl 24)
|
state.stack.add ArcticType(i: a or b shl 8 or c shl 16 or d shl 24)
|
||||||
|
@ -428,15 +378,15 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic
|
||||||
of 'Q': # LDOW
|
of 'Q': # LDOW
|
||||||
let
|
let
|
||||||
p = state.stack.pop.f
|
p = state.stack.pop.f
|
||||||
a = state[p].int64
|
a = state.memory[p].int64
|
||||||
b = state[p+1].int64
|
b = state.memory[p+1].int64
|
||||||
c = state[p+2].int64
|
c = state.memory[p+2].int64
|
||||||
d = state[p+3].int64
|
d = state.memory[p+3].int64
|
||||||
e = state[p+4].int64
|
e = state.memory[p+4].int64
|
||||||
f = state[p+5].int64
|
f = state.memory[p+5].int64
|
||||||
g = state[p+6].int64
|
g = state.memory[p+6].int64
|
||||||
h = state[p+7].int64
|
h = state.memory[p+7].int64
|
||||||
if state.pc.section == "CODE": # bigendian
|
if op.bigendian:
|
||||||
state.stack.add ArcticType(i: h or g shl 8 or f shl 16 or e shl 24 or d shl 32 or c shl 40 or b shl 48 or a shl 56)
|
state.stack.add ArcticType(i: h or g shl 8 or f shl 16 or e shl 24 or d shl 32 or c shl 40 or b shl 48 or a shl 56)
|
||||||
else:
|
else:
|
||||||
state.stack.add ArcticType(i: a or b shl 8 or c shl 16 or d shl 24 or e shl 32 or f shl 40 or g shl 48 or h shl 56)
|
state.stack.add ArcticType(i: a or b shl 8 or c shl 16 or d shl 24 or e shl 32 or f shl 40 or g shl 48 or h shl 56)
|
||||||
|
@ -445,63 +395,63 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic
|
||||||
let
|
let
|
||||||
x = cast[uint8](state.stack.pop.b)
|
x = cast[uint8](state.stack.pop.b)
|
||||||
p = state.stack.pop.f
|
p = state.stack.pop.f
|
||||||
state[p] = x
|
state.memory[p] = x
|
||||||
|
|
||||||
of '6': # STAS
|
of '6': # STAS
|
||||||
let
|
let
|
||||||
x = cast[uint16](state.stack.pop.s)
|
x = cast[uint16](state.stack.pop.s)
|
||||||
p = state.stack.pop.f
|
p = state.stack.pop.f
|
||||||
if state.pc.section == "CODE": # bigendian
|
if op.bigendian:
|
||||||
state[p] = uint8(x and 0xFF)
|
state.memory[p] = uint8(x and 0xFF)
|
||||||
state[p+1] = uint8(x shr 8)
|
state.memory[p+1] = uint8(x shr 8)
|
||||||
else:
|
else:
|
||||||
state[p] = uint8(x shr 8)
|
state.memory[p] = uint8(x shr 8)
|
||||||
state[p+1] = uint8(x and 0xFF)
|
state.memory[p+1] = uint8(x and 0xFF)
|
||||||
|
|
||||||
of '7': # STAI
|
of '7': # STAI
|
||||||
let
|
let
|
||||||
x = cast[uint32](state.stack.pop.i)
|
x = cast[uint32](state.stack.pop.i)
|
||||||
p = state.stack.pop.f
|
p = state.stack.pop.f
|
||||||
if state.pc.section == "CODE": # bigendian
|
if op.bigendian:
|
||||||
state[p] = uint8(x and 0xFF)
|
state.memory[p] = uint8(x and 0xFF)
|
||||||
state[p+1] = uint8((x shr 8) and 0xFF)
|
state.memory[p+1] = uint8((x shr 8) and 0xFF)
|
||||||
state[p+2] = uint8((x shr 16) and 0xFF)
|
state.memory[p+2] = uint8((x shr 16) and 0xFF)
|
||||||
state[p+3] = uint8((x shr 24) and 0xFF)
|
state.memory[p+3] = uint8((x shr 24) and 0xFF)
|
||||||
else:
|
else:
|
||||||
state[p] = uint8((x shr 24) and 0xFF)
|
state.memory[p] = uint8((x shr 24) and 0xFF)
|
||||||
state[p+1] = uint8((x shr 16) and 0xFF)
|
state.memory[p+1] = uint8((x shr 16) and 0xFF)
|
||||||
state[p+2] = uint8((x shr 8) and 0xFF)
|
state.memory[p+2] = uint8((x shr 8) and 0xFF)
|
||||||
state[p+3] = uint8(x and 0xFF)
|
state.memory[p+3] = uint8(x and 0xFF)
|
||||||
|
|
||||||
of '8': # STAW
|
of '8': # STAW
|
||||||
let
|
let
|
||||||
x = cast[uint64](state.stack.pop.i)
|
x = cast[uint64](state.stack.pop.i)
|
||||||
p = state.stack.pop.f
|
p = state.stack.pop.f
|
||||||
if state.pc.section == "CODE": # bigendian
|
if op.bigendian:
|
||||||
state[p] = uint8(x and 0xFF)
|
state.memory[p] = uint8(x and 0xFF)
|
||||||
state[p+1] = uint8((x shr 8) and 0xFF)
|
state.memory[p+1] = uint8((x shr 8) and 0xFF)
|
||||||
state[p+2] = uint8((x shr 16) and 0xFF)
|
state.memory[p+2] = uint8((x shr 16) and 0xFF)
|
||||||
state[p+3] = uint8((x shr 24) and 0xFF)
|
state.memory[p+3] = uint8((x shr 24) and 0xFF)
|
||||||
state[p+4] = uint8((x shr 32) and 0xFF)
|
state.memory[p+4] = uint8((x shr 32) and 0xFF)
|
||||||
state[p+5] = uint8((x shr 40) and 0xFF)
|
state.memory[p+5] = uint8((x shr 40) and 0xFF)
|
||||||
state[p+6] = uint8((x shr 48) and 0xFF)
|
state.memory[p+6] = uint8((x shr 48) and 0xFF)
|
||||||
state[p+7] = uint8((x shr 56) and 0xFF)
|
state.memory[p+7] = uint8((x shr 56) and 0xFF)
|
||||||
else:
|
else:
|
||||||
state[p] = uint8((x shr 56) and 0xFF)
|
state.memory[p] = uint8((x shr 56) and 0xFF)
|
||||||
state[p+1] = uint8((x shr 48) and 0xFF)
|
state.memory[p+1] = uint8((x shr 48) and 0xFF)
|
||||||
state[p+2] = uint8((x shr 40) and 0xFF)
|
state.memory[p+2] = uint8((x shr 40) and 0xFF)
|
||||||
state[p+3] = uint8((x shr 32) and 0xFF)
|
state.memory[p+3] = uint8((x shr 32) and 0xFF)
|
||||||
state[p+4] = uint8((x shr 24) and 0xFF)
|
state.memory[p+4] = uint8((x shr 24) and 0xFF)
|
||||||
state[p+5] = uint8((x shr 16) and 0xFF)
|
state.memory[p+5] = uint8((x shr 16) and 0xFF)
|
||||||
state[p+6] = uint8((x shr 8) and 0xFF)
|
state.memory[p+6] = uint8((x shr 8) and 0xFF)
|
||||||
state[p+7] = uint8(x and 0xFF)
|
state.memory[p+7] = uint8(x and 0xFF)
|
||||||
|
|
||||||
of 'D': # MCLR
|
of 'D': # MCLR
|
||||||
let
|
let
|
||||||
x = state.stack.pop.i
|
x = state.stack.pop.i
|
||||||
p = state.stack.pop.f
|
p = state.stack.pop.f
|
||||||
for i in 0 .. x:
|
for i in 0 .. x:
|
||||||
state[p+i] = 0
|
state.memory[p+i] = 0
|
||||||
|
|
||||||
of 'd': # MSET
|
of 'd': # MSET
|
||||||
assert op.immediate.kind == INTEGER
|
assert op.immediate.kind == INTEGER
|
||||||
|
@ -510,7 +460,7 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic
|
||||||
p = state.stack.pop.f
|
p = state.stack.pop.f
|
||||||
b = op.immediate.i.uint8
|
b = op.immediate.i.uint8
|
||||||
for i in 0 .. x:
|
for i in 0 .. x:
|
||||||
state[p+i] = b
|
state.memory[p+i] = b
|
||||||
|
|
||||||
of 'K': # MCPY
|
of 'K': # MCPY
|
||||||
let
|
let
|
||||||
|
@ -518,13 +468,13 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic
|
||||||
q = state.stack.pop.f
|
q = state.stack.pop.f
|
||||||
p = state.stack.pop.f
|
p = state.stack.pop.f
|
||||||
for i in 0 .. x:
|
for i in 0 .. x:
|
||||||
state[q+i] = state[p+i]
|
state.memory[q+i] = state.memory[p+i]
|
||||||
|
|
||||||
of 'J': # MOFF
|
of 'J': # MOFF
|
||||||
let
|
let
|
||||||
x = state.stack.pop.i
|
x = state.stack.pop.i
|
||||||
p = state.stack.pop.f
|
p = state.stack.pop.p
|
||||||
state.stack.add ArcticType(f: (section: p.section, index: p.index + 1))
|
state.stack.add ArcticType(p: p + x)
|
||||||
|
|
||||||
of 'M': # MALL
|
of 'M': # MALL
|
||||||
assert op.immediate.kind == INTEGER
|
assert op.immediate.kind == INTEGER
|
||||||
|
@ -534,18 +484,16 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic
|
||||||
|
|
||||||
if n == 0:
|
if n == 0:
|
||||||
if top.i != 0:
|
if top.i != 0:
|
||||||
state.sections.excl top.f.section
|
state.memory.deallocate(top.p)
|
||||||
state.stack.add ArcticType(i: 0)
|
state.stack.add ArcticType(i: 0)
|
||||||
elif n > 0:
|
elif n > 0:
|
||||||
if top.i == 0:
|
if top.i == 0:
|
||||||
state.sections.incl("allocated " & $next_malloc_id, ArcticSection(iscode: false, data: @[]))
|
state.stack.add ArcticType(p: state.memory.allocate(n))
|
||||||
inc next_malloc_id
|
|
||||||
else:
|
else:
|
||||||
discard # we use dynamic memory, realloc is a no-op
|
state.stack.add ArcticType(p: state.memory.reallocate(top.p, n))
|
||||||
else:
|
else:
|
||||||
discard # realloc negative is a nop
|
discard # realloc negative is a nop
|
||||||
|
|
||||||
|
|
||||||
of 'R': # REAL
|
of 'R': # REAL
|
||||||
let
|
let
|
||||||
top = state.stack.pop
|
top = state.stack.pop
|
||||||
|
@ -553,18 +501,16 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic
|
||||||
|
|
||||||
if x == 0:
|
if x == 0:
|
||||||
if top.i != 0:
|
if top.i != 0:
|
||||||
state.sections.excl top.f.section
|
state.memory.deallocate(top.p)
|
||||||
state.stack.add ArcticType(i: 0)
|
state.stack.add ArcticType(i: 0)
|
||||||
elif x > 0:
|
elif x > 0:
|
||||||
if top.i == 0:
|
if top.i == 0:
|
||||||
state.sections.incl("allocated " & $next_malloc_id, ArcticSection(iscode: false, data: @[]))
|
state.stack.add ArcticType(p: state.memory.allocate(x))
|
||||||
inc next_malloc_id
|
|
||||||
else:
|
else:
|
||||||
discard # we use dynamic memory, realloc is a no-op
|
state.stack.add ArcticType(p: state.memory.reallocate(top.p, x))
|
||||||
else:
|
else:
|
||||||
discard # realloc negative is a nop
|
discard # realloc negative is a nop
|
||||||
|
|
||||||
|
|
||||||
of '9': # CASS
|
of '9': # CASS
|
||||||
# TODO: Actually CAS? need to use Atomic[T] for that...
|
# TODO: Actually CAS? need to use Atomic[T] for that...
|
||||||
# implementation would probably require an "atomic" memory
|
# implementation would probably require an "atomic" memory
|
||||||
|
@ -573,41 +519,41 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic
|
||||||
y = state.stack.pop.i
|
y = state.stack.pop.i
|
||||||
x = state.stack.pop.i
|
x = state.stack.pop.i
|
||||||
p = state.stack.pop.f
|
p = state.stack.pop.f
|
||||||
a = state[p].int64
|
a = state.memory[p].int64
|
||||||
b = state[p+1].int64
|
b = state.memory[p+1].int64
|
||||||
c = state[p+2].int64
|
c = state.memory[p+2].int64
|
||||||
d = state[p+3].int64
|
d = state.memory[p+3].int64
|
||||||
e = state[p+4].int64
|
e = state.memory[p+4].int64
|
||||||
f = state[p+5].int64
|
f = state.memory[p+5].int64
|
||||||
g = state[p+6].int64
|
g = state.memory[p+6].int64
|
||||||
h = state[p+7].int64
|
h = state.memory[p+7].int64
|
||||||
|
|
||||||
var old: int64
|
var old: int64
|
||||||
if state.pc.section == "CODE": # bigendian
|
if op.bigendian:
|
||||||
old = h or g shl 8 or f shl 16 or e shl 24 or d shl 32 or c shl 40 or b shl 48 or a shl 56
|
old = h or g shl 8 or f shl 16 or e shl 24 or d shl 32 or c shl 40 or b shl 48 or a shl 56
|
||||||
else:
|
else:
|
||||||
old = a or b shl 8 or c shl 16 or d shl 24 or e shl 32 or f shl 40 or g shl 48 or h shl 56
|
old = a or b shl 8 or c shl 16 or d shl 24 or e shl 32 or f shl 40 or g shl 48 or h shl 56
|
||||||
|
|
||||||
if x == old:
|
if x == old:
|
||||||
state.stack.add ArcticType(i: 1)
|
state.stack.add ArcticType(i: 1)
|
||||||
if state.pc.section == "CODE": # bigendian
|
if op.bigendian:
|
||||||
state[p] = uint8(y and 0xFF)
|
state.memory[p] = uint8(y and 0xFF)
|
||||||
state[p+1] = uint8((y shr 8) and 0xFF)
|
state.memory[p+1] = uint8((y shr 8) and 0xFF)
|
||||||
state[p+2] = uint8((y shr 16) and 0xFF)
|
state.memory[p+2] = uint8((y shr 16) and 0xFF)
|
||||||
state[p+3] = uint8((y shr 24) and 0xFF)
|
state.memory[p+3] = uint8((y shr 24) and 0xFF)
|
||||||
state[p+4] = uint8((y shr 32) and 0xFF)
|
state.memory[p+4] = uint8((y shr 32) and 0xFF)
|
||||||
state[p+5] = uint8((y shr 40) and 0xFF)
|
state.memory[p+5] = uint8((y shr 40) and 0xFF)
|
||||||
state[p+6] = uint8((y shr 48) and 0xFF)
|
state.memory[p+6] = uint8((y shr 48) and 0xFF)
|
||||||
state[p+7] = uint8((y shr 56) and 0xFF)
|
state.memory[p+7] = uint8((y shr 56) and 0xFF)
|
||||||
else:
|
else:
|
||||||
state[p] = uint8((y shr 56) and 0xFF)
|
state.memory[p] = uint8((y shr 56) and 0xFF)
|
||||||
state[p+1] = uint8((y shr 48) and 0xFF)
|
state.memory[p+1] = uint8((y shr 48) and 0xFF)
|
||||||
state[p+2] = uint8((y shr 40) and 0xFF)
|
state.memory[p+2] = uint8((y shr 40) and 0xFF)
|
||||||
state[p+3] = uint8((y shr 32) and 0xFF)
|
state.memory[p+3] = uint8((y shr 32) and 0xFF)
|
||||||
state[p+4] = uint8((y shr 24) and 0xFF)
|
state.memory[p+4] = uint8((y shr 24) and 0xFF)
|
||||||
state[p+5] = uint8((y shr 16) and 0xFF)
|
state.memory[p+5] = uint8((y shr 16) and 0xFF)
|
||||||
state[p+6] = uint8((y shr 8) and 0xFF)
|
state.memory[p+6] = uint8((y shr 8) and 0xFF)
|
||||||
state[p+7] = uint8(y and 0xFF)
|
state.memory[p+7] = uint8(y and 0xFF)
|
||||||
else:
|
else:
|
||||||
state.stack.add ArcticType(i: 0)
|
state.stack.add ArcticType(i: 0)
|
||||||
|
|
||||||
|
@ -920,9 +866,9 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic
|
||||||
# Once we have the addresses, can pack x items of stack at p+...
|
# Once we have the addresses, can pack x items of stack at p+...
|
||||||
|
|
||||||
# Control Ops ----------------------------------------------------------
|
# Control Ops ----------------------------------------------------------
|
||||||
## TODO
|
# TODO
|
||||||
|
|
||||||
## TODO
|
# TODO
|
||||||
|
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
|
|
Loading…
Reference in a new issue