Finished rough draft
This commit is contained in:
parent
e2642ec3ac
commit
c990114723
|
@ -465,7 +465,7 @@ These can be combined to store the entire stack in a new array via: `(w$0 Rt)`
|
||||||
{ |BLEZ| … x| ⇒ | … | branch to immediate if x is less than or equal to zero
|
{ |BLEZ| … x| ⇒ | … | branch to immediate if x is less than or equal to zero
|
||||||
} |BGEZ| … x| ⇒ | … | branch to immediate if x is greater or equal to zero
|
} |BGEZ| … x| ⇒ | … | branch to immediate if x is greater or equal to zero
|
||||||
g |FINV| … f| → | f … | invoke f, saving return address on stack
|
g |FINV| … f| → | f … | invoke f, saving return address on stack
|
||||||
@ |CALL| …| → | f … | call immediate name
|
@ |CALL| …| ⇒ | f … | call immediate name
|
||||||
, |JUMP| …| ⇒ | … | jump to immediate without pushing return address
|
, |JUMP| …| ⇒ | … | jump to immediate without pushing return address
|
||||||
; |RETN| … f| → | … | return from subroutine (jump but for stack)
|
; |RETN| … f| → | … | return from subroutine (jump but for stack)
|
||||||
\:|LABL| … | ↔ | … | label code location
|
\:|LABL| … | ↔ | … | label code location
|
||||||
|
|
|
@ -2,12 +2,9 @@
|
||||||
|
|
||||||
@main
|
@main
|
||||||
|
|
||||||
"with stdio"
|
|
||||||
|
|
||||||
"data"
|
"data"
|
||||||
:message 'Hello, World!'
|
:message '"Hello, World!\x00"'
|
||||||
|
|
||||||
"code"
|
"code"
|
||||||
:main T3 kk # main is called as: &argv[0] argc retaddr
|
:main T3 kk # main is called as: &argv[0] argc retaddr
|
||||||
$message @putstrln $0;
|
$message `putstrln $0 ;
|
||||||
|
|
||||||
|
|
301
src/arctic.nim
301
src/arctic.nim
|
@ -1,4 +1,4 @@
|
||||||
import std/[atomics, bitops, critbits, strformat, strutils, strmisc, tables, math, re]
|
import std/[bitops, critbits, macros, strformat, strutils, strmisc, os, tables, math, re] # atomics
|
||||||
import bio
|
import bio
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
|
@ -14,9 +14,8 @@ type
|
||||||
i: int64
|
i: int64
|
||||||
u: uint64
|
u: uint64
|
||||||
d: float64
|
d: float64
|
||||||
p: ArcticPointer # always positive (null is 0)
|
p: ArcticPointer
|
||||||
f: ArcticPointer # always negative (null is 0)
|
f: ArcticPointer
|
||||||
# TODO: check that appropriate p/f is used (there are a lot of legacy .f's hanging around)
|
|
||||||
|
|
||||||
ArcticVariableIndex = enum
|
ArcticVariableIndex = enum
|
||||||
VARIABLE_A, VARIABLE_B, VARIABLE_C,
|
VARIABLE_A, VARIABLE_B, VARIABLE_C,
|
||||||
|
@ -51,13 +50,13 @@ type
|
||||||
dynmem: Table[ArcticPointer, int] # pointer -> length
|
dynmem: Table[ArcticPointer, int] # pointer -> length
|
||||||
|
|
||||||
ArcticStepResult* = enum
|
ArcticStepResult* = enum
|
||||||
CONTINUE, BREAKPOINT, ERROR
|
CONTINUE, BREAKPOINT, EXIT, ERROR
|
||||||
|
|
||||||
ArcticBuiltin* = proc (state: var ArcticState): ArcticStepResult
|
ArcticBuiltin* = proc (state: var ArcticState): ArcticStepResult {.nimcall.}
|
||||||
|
|
||||||
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', '_', '.', '+', '-', '*', '/', '%', '\\', '|', '&', '^', '!', '?', '(', ')' }
|
||||||
|
|
||||||
proc `$`*(variable: ArcticVariableIndex): string =
|
proc `$`*(variable: ArcticVariableIndex): string =
|
||||||
case variable:
|
case variable:
|
||||||
|
@ -78,9 +77,7 @@ proc `$`*(op: ArcticOperation): string =
|
||||||
of VARIABLE: result &= $op.immediate.v
|
of VARIABLE: result &= $op.immediate.v
|
||||||
of INTEGER: result &= $op.immediate.i
|
of INTEGER: result &= $op.immediate.i
|
||||||
of NUMBER: result &= $op.immediate.n
|
of NUMBER: result &= $op.immediate.n
|
||||||
of SYMBOL: result &= "$" & $op.immediate.s
|
of SYMBOL: result &= $op.immediate.s
|
||||||
|
|
||||||
result &= " "
|
|
||||||
|
|
||||||
proc `$`*(state: ArcticState): string =
|
proc `$`*(state: ArcticState): string =
|
||||||
result &= "Registers:\n"
|
result &= "Registers:\n"
|
||||||
|
@ -92,27 +89,31 @@ proc `$`*(state: ArcticState): string =
|
||||||
for item in state.stack:
|
for item in state.stack:
|
||||||
result &= &" {item}\n"
|
result &= &" {item}\n"
|
||||||
|
|
||||||
|
result &= "Sections:\n"
|
||||||
|
|
||||||
for section in state.code.sections:
|
for section in state.code.sections:
|
||||||
result &= "\n"
|
result &= "\n section "
|
||||||
|
result &= section
|
||||||
|
result &= ":\n"
|
||||||
for (i, m) in state.code.data(section).pairs:
|
for (i, m) in state.code.data(section).pairs:
|
||||||
for (label, location) in state.symbols.pairs:
|
for (label, location) in state.symbols.pairs:
|
||||||
if -location == state.code.address(section, i):
|
if -location == state.code.address(section, i):
|
||||||
result &= &":{label} "
|
result &= &":{label} "
|
||||||
if state.pc == state.code.address(section, i):
|
if state.pc == state.code.address(section, i):
|
||||||
result &= ">"
|
result &= ">"
|
||||||
|
if m.code != ' ':
|
||||||
result &= $m
|
result &= $m
|
||||||
|
|
||||||
for section in state.memory.sections:
|
for section in state.memory.sections:
|
||||||
result &= "\n"
|
result &= "\n section "
|
||||||
|
result &= section
|
||||||
|
result &= ":\n"
|
||||||
for (i, m) in state.memory.data(section).pairs:
|
for (i, m) in state.memory.data(section).pairs:
|
||||||
for (label, location) in state.symbols.pairs:
|
for (label, location) in state.symbols.pairs:
|
||||||
if location == state.memory.address(section, i):
|
if location == state.memory.address(section, i):
|
||||||
result &= &":{label} "
|
result &= &":{label} "
|
||||||
result &= &"{m} "
|
result &= &"{m} "
|
||||||
|
|
||||||
proc op(code: char, immediate: ArcticImmediate = ArcticImmediate(kind: PLAIN)): ArcticOperation =
|
|
||||||
return ArcticOperation(code: code, immediate: immediate)
|
|
||||||
|
|
||||||
proc tovar(code: char): ArcticVariableIndex =
|
proc tovar(code: char): ArcticVariableIndex =
|
||||||
case code.toLowerAscii:
|
case code.toLowerAscii:
|
||||||
of 'a': VARIABLE_A
|
of 'a': VARIABLE_A
|
||||||
|
@ -130,13 +131,13 @@ proc parse_immediate(imm: string, section: string): ArcticImmediate =
|
||||||
return ArcticImmediate(kind: INTEGER, i: imm.parseInt)
|
return ArcticImmediate(kind: INTEGER, i: imm.parseInt)
|
||||||
elif imm.match(re"^[AaBbCcIiNnXxYyZz]$"):
|
elif imm.match(re"^[AaBbCcIiNnXxYyZz]$"):
|
||||||
return ArcticImmediate(kind: VARIABLE, v: imm[0].tovar)
|
return ArcticImmediate(kind: VARIABLE, v: imm[0].tovar)
|
||||||
elif imm[0] == '$':
|
elif imm.len > 0 and imm[0] in "0123456789.":
|
||||||
if imm.len == 1 or imm[1] == '_':
|
return ArcticImmediate(kind: NUMBER, n: imm.parseFloat)
|
||||||
|
else:
|
||||||
|
if imm.len > 0 and imm[0] == '_':
|
||||||
return ArcticImmediate(kind: SYMBOL, s: section & " " & imm)
|
return ArcticImmediate(kind: SYMBOL, s: section & " " & imm)
|
||||||
else:
|
else:
|
||||||
return ArcticImmediate(kind: SYMBOL, s: imm)
|
return ArcticImmediate(kind: SYMBOL, s: imm)
|
||||||
else:
|
|
||||||
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
|
||||||
|
@ -192,7 +193,7 @@ proc parse_data(data: string): seq[uint8] =
|
||||||
result.add parse_data(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, _, rest) = data[1..^1].partition("x")
|
||||||
for pair in hex.chunked(2):
|
for pair in hex.chunked(2):
|
||||||
result.add uint8(parseHexInt(pair.join))
|
result.add uint8(parseHexInt(pair.join))
|
||||||
result.add parse_data(rest)
|
result.add parse_data(rest)
|
||||||
|
@ -200,7 +201,7 @@ proc parse_data(data: string): seq[uint8] =
|
||||||
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
|
assert strlen >= 0
|
||||||
for c in unescape(data[1..strlen]):
|
for c in unescape(data[1..strlen - 2], prefix="", suffix=""):
|
||||||
result.add c.uint8
|
result.add c.uint8
|
||||||
result.add parse_data(data[strlen..^1])
|
result.add parse_data(data[strlen..^1])
|
||||||
|
|
||||||
|
@ -219,7 +220,7 @@ func isbigendian(secname: string): bool =
|
||||||
|
|
||||||
func raw_op(code: char): ArcticOperation =
|
func raw_op(code: char): ArcticOperation =
|
||||||
result.code = code
|
result.code = code
|
||||||
result.immediate.kind = PLAIN
|
result.immediate = ArcticImmediate(kind: PLAIN)
|
||||||
|
|
||||||
func load*(code: string): ArcticState =
|
func load*(code: string): ArcticState =
|
||||||
var
|
var
|
||||||
|
@ -229,7 +230,6 @@ func load*(code: string): ArcticState =
|
||||||
result.pc = 1
|
result.pc = 1
|
||||||
|
|
||||||
for next in code:
|
for next in code:
|
||||||
debug_echo "token: ", token, ", next: ", next
|
|
||||||
if token.len == 0: # initial state
|
if token.len == 0: # initial state
|
||||||
case next:
|
case next:
|
||||||
of ImmediateOps, '#', ':', '\"', '\'':
|
of ImmediateOps, '#', ':', '\"', '\'':
|
||||||
|
@ -256,7 +256,7 @@ func load*(code: string): ArcticState =
|
||||||
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]
|
||||||
if section.iscode:
|
if section.iscode:
|
||||||
result.symbols[idx] = -result.code.current(section)
|
result.symbols[idx] = result.code.current(section)
|
||||||
else:
|
else:
|
||||||
result.symbols[idx] = result.code.current(section)
|
result.symbols[idx] = result.code.current(section)
|
||||||
token = ""
|
token = ""
|
||||||
|
@ -287,7 +287,7 @@ func load*(code: string): ArcticState =
|
||||||
token.add next
|
token.add next
|
||||||
|
|
||||||
of ImmediateOps:
|
of ImmediateOps:
|
||||||
if next == ' ':
|
if next in " \n":
|
||||||
result.code.add(section, ArcticOperation(
|
result.code.add(section, ArcticOperation(
|
||||||
code: token[0],
|
code: token[0],
|
||||||
immediate: parse_immediate(token[1..^1], section),
|
immediate: parse_immediate(token[1..^1], section),
|
||||||
|
@ -299,7 +299,40 @@ func load*(code: string): ArcticState =
|
||||||
else:
|
else:
|
||||||
discard
|
discard
|
||||||
|
|
||||||
|
proc branch(state: var ArcticState, count: int) =
|
||||||
|
var n = 0
|
||||||
|
if count > 0:
|
||||||
|
while n < count:
|
||||||
|
state.pc.inc
|
||||||
|
if state.code[state.pc].code == '\n':
|
||||||
|
n.inc
|
||||||
|
else:
|
||||||
|
while n > count:
|
||||||
|
state.pc.dec
|
||||||
|
if state.code[state.pc].code == '\n':
|
||||||
|
n.dec
|
||||||
|
|
||||||
|
var DefaultBuiltins {.compileTime.}: CritBitTree[ArcticBuiltin]
|
||||||
|
|
||||||
|
macro arctic_builtin(builtin: typed): untyped =
|
||||||
|
let nameid = builtin.name
|
||||||
|
let namestr = newLit(nameid.strVal)
|
||||||
|
|
||||||
|
result = quote do:
|
||||||
|
`builtin`
|
||||||
|
DefaultBuiltins[`namestr`] = `nameid`
|
||||||
|
|
||||||
|
proc putstrln(state: var ArcticState): ArcticStepResult {.arctic_builtin.} =
|
||||||
|
var p = state.stack.pop.p
|
||||||
|
while state.memory[p] != 0:
|
||||||
|
stdout.write(state.memory[p])
|
||||||
|
stdout.write('\n')
|
||||||
|
return CONTINUE
|
||||||
|
|
||||||
proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): ArcticStepResult =
|
proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): ArcticStepResult =
|
||||||
|
if not (state.pc in state.code):
|
||||||
|
return EXIT
|
||||||
|
|
||||||
let op = state.code[state.pc]
|
let op = state.code[state.pc]
|
||||||
state.pc.inc
|
state.pc.inc
|
||||||
|
|
||||||
|
@ -311,7 +344,7 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic
|
||||||
|
|
||||||
of '2': # LDAS
|
of '2': # LDAS
|
||||||
let
|
let
|
||||||
p = state.stack.pop.f
|
p = state.stack.pop.p
|
||||||
a = state.memory[p].int64
|
a = state.memory[p].int64
|
||||||
b = state.memory[p+1].int64
|
b = state.memory[p+1].int64
|
||||||
if op.bigendian:
|
if op.bigendian:
|
||||||
|
@ -321,7 +354,7 @@ 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.p
|
||||||
a = state.memory[p].int64
|
a = state.memory[p].int64
|
||||||
b = state.memory[p+1].int64
|
b = state.memory[p+1].int64
|
||||||
c = state.memory[p+2].int64
|
c = state.memory[p+2].int64
|
||||||
|
@ -333,7 +366,7 @@ 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.p
|
||||||
a = state.memory[p].int64
|
a = state.memory[p].int64
|
||||||
b = state.memory[p+1].int64
|
b = state.memory[p+1].int64
|
||||||
c = state.memory[p+2].int64
|
c = state.memory[p+2].int64
|
||||||
|
@ -349,13 +382,13 @@ 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.p
|
||||||
state.stack.add ArcticType(i: state.memory[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.p + op.immediate.i
|
||||||
a = state.memory[p].int64
|
a = state.memory[p].int64
|
||||||
b = state.memory[p+1].int64
|
b = state.memory[p+1].int64
|
||||||
if op.bigendian:
|
if op.bigendian:
|
||||||
|
@ -365,7 +398,7 @@ 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.p + op.immediate.i
|
||||||
a = state.memory[p].int64
|
a = state.memory[p].int64
|
||||||
b = state.memory[p+1].int64
|
b = state.memory[p+1].int64
|
||||||
c = state.memory[p+2].int64
|
c = state.memory[p+2].int64
|
||||||
|
@ -377,7 +410,7 @@ 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.p
|
||||||
a = state.memory[p].int64
|
a = state.memory[p].int64
|
||||||
b = state.memory[p+1].int64
|
b = state.memory[p+1].int64
|
||||||
c = state.memory[p+2].int64
|
c = state.memory[p+2].int64
|
||||||
|
@ -394,13 +427,13 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic
|
||||||
of '5': # STAB
|
of '5': # STAB
|
||||||
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.p
|
||||||
state.memory[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.p
|
||||||
if op.bigendian:
|
if op.bigendian:
|
||||||
state.memory[p] = uint8(x and 0xFF)
|
state.memory[p] = uint8(x and 0xFF)
|
||||||
state.memory[p+1] = uint8(x shr 8)
|
state.memory[p+1] = uint8(x shr 8)
|
||||||
|
@ -411,7 +444,7 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic
|
||||||
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.p
|
||||||
if op.bigendian:
|
if op.bigendian:
|
||||||
state.memory[p] = uint8(x and 0xFF)
|
state.memory[p] = uint8(x and 0xFF)
|
||||||
state.memory[p+1] = uint8((x shr 8) and 0xFF)
|
state.memory[p+1] = uint8((x shr 8) and 0xFF)
|
||||||
|
@ -426,7 +459,7 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic
|
||||||
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.p
|
||||||
if op.bigendian:
|
if op.bigendian:
|
||||||
state.memory[p] = uint8(x and 0xFF)
|
state.memory[p] = uint8(x and 0xFF)
|
||||||
state.memory[p+1] = uint8((x shr 8) and 0xFF)
|
state.memory[p+1] = uint8((x shr 8) and 0xFF)
|
||||||
|
@ -449,7 +482,7 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic
|
||||||
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.p
|
||||||
for i in 0 .. x:
|
for i in 0 .. x:
|
||||||
state.memory[p+i] = 0
|
state.memory[p+i] = 0
|
||||||
|
|
||||||
|
@ -457,7 +490,7 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic
|
||||||
assert op.immediate.kind == INTEGER
|
assert op.immediate.kind == INTEGER
|
||||||
let
|
let
|
||||||
x = state.stack.pop.i
|
x = state.stack.pop.i
|
||||||
p = state.stack.pop.f
|
p = state.stack.pop.p
|
||||||
b = op.immediate.i.uint8
|
b = op.immediate.i.uint8
|
||||||
for i in 0 .. x:
|
for i in 0 .. x:
|
||||||
state.memory[p+i] = b
|
state.memory[p+i] = b
|
||||||
|
@ -465,8 +498,8 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic
|
||||||
of 'K': # MCPY
|
of 'K': # MCPY
|
||||||
let
|
let
|
||||||
x = state.stack.pop.i
|
x = state.stack.pop.i
|
||||||
q = state.stack.pop.f
|
q = state.stack.pop.p
|
||||||
p = state.stack.pop.f
|
p = state.stack.pop.p
|
||||||
for i in 0 .. x:
|
for i in 0 .. x:
|
||||||
state.memory[q+i] = state.memory[p+i]
|
state.memory[q+i] = state.memory[p+i]
|
||||||
|
|
||||||
|
@ -518,7 +551,7 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic
|
||||||
let
|
let
|
||||||
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.p
|
||||||
a = state.memory[p].int64
|
a = state.memory[p].int64
|
||||||
b = state.memory[p+1].int64
|
b = state.memory[p+1].int64
|
||||||
c = state.memory[p+2].int64
|
c = state.memory[p+2].int64
|
||||||
|
@ -706,6 +739,7 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic
|
||||||
let v = op.immediate.v
|
let v = op.immediate.v
|
||||||
i = state.registers[v].i
|
i = state.registers[v].i
|
||||||
else:
|
else:
|
||||||
|
echo "Unexpected immediate: ", op
|
||||||
assert false
|
assert false
|
||||||
|
|
||||||
if i > 0:
|
if i > 0:
|
||||||
|
@ -859,18 +893,185 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic
|
||||||
state.stack.add ArcticType(i: state.stack.len)
|
state.stack.add ArcticType(i: state.stack.len)
|
||||||
|
|
||||||
of ')': # PACK
|
of ')': # PACK
|
||||||
let
|
let x = state.stack.pop.i
|
||||||
x = state.stack.pop.i
|
var p = state.stack.pop.p
|
||||||
p = state.stack.pop.f
|
|
||||||
# TODO: Can't implement this until we have unified addresses
|
for i in countdown(x - 1, 0):
|
||||||
# Once we have the addresses, can pack x items of stack at p+...
|
var n = state.stack[^i].u
|
||||||
|
for _ in 0 .. 8:
|
||||||
|
state.memory[p] = uint8(n and 0xFF)
|
||||||
|
n = n shr 8
|
||||||
|
inc p
|
||||||
|
|
||||||
# Control Ops ----------------------------------------------------------
|
# Control Ops ----------------------------------------------------------
|
||||||
# TODO
|
of '=': # BEQZ
|
||||||
|
assert op.immediate.kind == INTEGER
|
||||||
|
let cond = state.stack.pop.i
|
||||||
|
|
||||||
# TODO
|
if cond == 0:
|
||||||
|
state.branch op.immediate.i
|
||||||
|
|
||||||
|
of '0': # BNEZ
|
||||||
|
assert op.immediate.kind == INTEGER
|
||||||
|
let cond = state.stack.pop.i
|
||||||
|
|
||||||
|
if cond != 0:
|
||||||
|
state.branch op.immediate.i
|
||||||
|
|
||||||
|
of '<': # BLTZ
|
||||||
|
assert op.immediate.kind == INTEGER
|
||||||
|
let cond = state.stack.pop.i
|
||||||
|
|
||||||
|
if cond < 0:
|
||||||
|
state.branch op.immediate.i
|
||||||
|
|
||||||
|
of '>': # BGTZ
|
||||||
|
assert op.immediate.kind == INTEGER
|
||||||
|
let cond = state.stack.pop.i
|
||||||
|
|
||||||
|
if cond > 0:
|
||||||
|
state.branch op.immediate.i
|
||||||
|
|
||||||
|
of '{': # BLEZ
|
||||||
|
assert op.immediate.kind == INTEGER
|
||||||
|
let cond = state.stack.pop.i
|
||||||
|
|
||||||
|
if cond <= 0:
|
||||||
|
state.branch op.immediate.i
|
||||||
|
|
||||||
|
of '}': # BGEZ
|
||||||
|
assert op.immediate.kind == INTEGER
|
||||||
|
let cond = state.stack.pop.i
|
||||||
|
|
||||||
|
if cond >= 0:
|
||||||
|
state.branch op.immediate.i
|
||||||
|
|
||||||
|
of 'g': # FINV
|
||||||
|
let f = state.stack.pop.f
|
||||||
|
state.stack.add ArcticType(f: state.pc)
|
||||||
|
state.pc = f
|
||||||
|
|
||||||
|
of '@': # CALL
|
||||||
|
assert op.immediate.kind == SYMBOL
|
||||||
|
let f = state.symbols[op.immediate.s]
|
||||||
|
state.stack.add ArcticType(f: state.pc)
|
||||||
|
state.pc = f
|
||||||
|
|
||||||
|
of ',': # JUMP
|
||||||
|
assert op.immediate.kind == SYMBOL
|
||||||
|
let f = state.symbols[op.immediate.s]
|
||||||
|
state.pc = f
|
||||||
|
|
||||||
|
of ';': # RETN
|
||||||
|
let f = state.stack.pop.f
|
||||||
|
state.pc = f
|
||||||
|
|
||||||
|
# Variable Ops ---------------------------------------------------------
|
||||||
|
of 'A': # PUTA
|
||||||
|
state.registers[VARIABLE_A] = state.stack.pop
|
||||||
|
|
||||||
|
of 'B': # PUTB
|
||||||
|
state.registers[VARIABLE_B] = state.stack.pop
|
||||||
|
|
||||||
|
of 'C': # PUTC
|
||||||
|
state.registers[VARIABLE_C] = state.stack.pop
|
||||||
|
|
||||||
|
of 'I': # PUTI
|
||||||
|
state.registers[VARIABLE_I] = state.stack.pop
|
||||||
|
|
||||||
|
of 'N': # PUTN
|
||||||
|
state.registers[VARIABLE_N] = state.stack.pop
|
||||||
|
|
||||||
|
of 'X': # PUTX
|
||||||
|
state.registers[VARIABLE_X] = state.stack.pop
|
||||||
|
|
||||||
|
of 'Y': # PUTY
|
||||||
|
state.registers[VARIABLE_Y] = state.stack.pop
|
||||||
|
|
||||||
|
of 'Z': # PUTZ
|
||||||
|
state.registers[VARIABLE_Z] = state.stack.pop
|
||||||
|
|
||||||
|
of 'a': # GETA
|
||||||
|
state.stack.add state.registers[VARIABLE_A]
|
||||||
|
|
||||||
|
of 'b': # GETB
|
||||||
|
state.stack.add state.registers[VARIABLE_B]
|
||||||
|
|
||||||
|
of 'c': # GETC
|
||||||
|
state.stack.add state.registers[VARIABLE_C]
|
||||||
|
|
||||||
|
of 'i': # GETI
|
||||||
|
state.stack.add state.registers[VARIABLE_I]
|
||||||
|
|
||||||
|
of 'n': # GETN
|
||||||
|
state.stack.add state.registers[VARIABLE_N]
|
||||||
|
|
||||||
|
of 'x': # GETX
|
||||||
|
state.stack.add state.registers[VARIABLE_X]
|
||||||
|
|
||||||
|
of 'y': # GETY
|
||||||
|
state.stack.add state.registers[VARIABLE_Y]
|
||||||
|
|
||||||
|
of 'z': # GETZ
|
||||||
|
state.stack.add state.registers[VARIABLE_Z]
|
||||||
|
|
||||||
|
# Miscellaneous Ops ----------------------------------------------------
|
||||||
|
of '$': # VALU
|
||||||
|
case op.immediate.kind:
|
||||||
|
of PLAIN:
|
||||||
|
state.stack.add ArcticType(i: 0)
|
||||||
|
of VARIABLE:
|
||||||
|
state.stack.add state.registers[op.immediate.v]
|
||||||
|
of INTEGER:
|
||||||
|
state.stack.add ArcticType(i: op.immediate.i)
|
||||||
|
of NUMBER:
|
||||||
|
state.stack.add ArcticType(d: op.immediate.n)
|
||||||
|
of SYMBOL:
|
||||||
|
state.stack.add ArcticType(p: state.symbols[op.immediate.s])
|
||||||
|
|
||||||
|
of '`': # BIFC
|
||||||
|
case op.immediate.kind:
|
||||||
|
of PLAIN:
|
||||||
|
discard
|
||||||
|
of VARIABLE:
|
||||||
|
discard
|
||||||
|
of INTEGER:
|
||||||
|
discard # TODO: integer "syscalls" (probably just syscall(n, ...)
|
||||||
|
of NUMBER:
|
||||||
|
discard
|
||||||
|
of SYMBOL:
|
||||||
|
let callback = builtins[op.immediate.s]
|
||||||
|
return callback(state)
|
||||||
|
|
||||||
|
of ' ': # NOOP
|
||||||
|
discard
|
||||||
|
|
||||||
|
of '\n': # BEAT
|
||||||
|
discard
|
||||||
|
|
||||||
|
else: # Unknown opcode
|
||||||
|
discard
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
let state = stdin.readAll.load
|
for fname in DefaultBuiltins.keys:
|
||||||
|
echo fname
|
||||||
|
var state = stdin.readAll.load
|
||||||
|
let builtins = DefaultBuiltins
|
||||||
|
|
||||||
|
# TODO: Actually allocate memory and push pointers to cli args
|
||||||
|
state.stack.add ArcticType(i: 0)
|
||||||
|
state.stack.add ArcticType(i: 0)
|
||||||
|
|
||||||
echo state
|
echo state
|
||||||
|
|
||||||
|
while true:
|
||||||
|
case state.step(builtins):
|
||||||
|
of CONTINUE:
|
||||||
|
continue
|
||||||
|
of BREAKPOINT:
|
||||||
|
echo state
|
||||||
|
of EXIT:
|
||||||
|
break
|
||||||
|
of ERROR:
|
||||||
|
break
|
||||||
|
|
||||||
|
|
303
src/memory.nim
Normal file
303
src/memory.nim
Normal file
|
@ -0,0 +1,303 @@
|
||||||
|
import std/[critbits, math, tables]
|
||||||
|
|
||||||
|
type
|
||||||
|
Memory*[T] = object
|
||||||
|
## Memory holds a set of sections and maps addresses in those sections
|
||||||
|
## to the range (0, int.high) via a low discrepancy sequence (in this
|
||||||
|
## case, the van der corput sequence)
|
||||||
|
chunks: seq[seq[T]]
|
||||||
|
sects: CritBitTree[int] # which chunk is the section
|
||||||
|
# TODO: keep track of lengths and "skip" vdc indices that would overlap
|
||||||
|
# (only an issue where e.g. section 0 is huge and there are lots
|
||||||
|
# of sections)
|
||||||
|
smlmem: Table[int, seq[T]] # index -> buffer
|
||||||
|
midmem: Table[int, seq[T]] # index -> buffer
|
||||||
|
bigmem: Table[int, seq[T]] # index -> buffer
|
||||||
|
hugmem: Table[int, seq[T]] # index -> buffer
|
||||||
|
# dynamic addresses are:
|
||||||
|
# (1 shl 18)-element blocks x (1 shl 42) starting from (int.high shr 1)
|
||||||
|
# (1 shl 26)-element blocks x (1 shl 34) starting from (int.high shr 1) + (1 shl 60)
|
||||||
|
# (1 shl 34)-element blocks x (1 shl 26) starting from (int.high shr 1) + 2 * (1 shl 60)
|
||||||
|
# (1 shl 42)-element blocks x (1 shl 18) starting from (int.high shr 1) + 3 * (1 shl 60)
|
||||||
|
|
||||||
|
const
|
||||||
|
HUG_BLOCK_SIZE = 1 shl 42
|
||||||
|
BIG_BLOCK_SIZE = 1 shl 34
|
||||||
|
MID_BLOCK_SIZE = 1 shl 26
|
||||||
|
SML_BLOCK_SIZE = 1 shl 18
|
||||||
|
|
||||||
|
HUG_BLOCK_COUNT = 1 shl 18
|
||||||
|
BIG_BLOCK_COUNT = 1 shl 26
|
||||||
|
MID_BLOCK_COUNT = 1 shl 34
|
||||||
|
SML_BLOCK_COUNT = 1 shl 42
|
||||||
|
|
||||||
|
SML_BLOCK_START = int.high shr 1
|
||||||
|
MID_BLOCK_START = SML_BLOCK_START + (1 shl 60)
|
||||||
|
BIG_BLOCK_START = MID_BLOCK_START + (1 shl 60)
|
||||||
|
HUG_BLOCK_START = BIG_BLOCK_START + (1 shl 60)
|
||||||
|
|
||||||
|
proc van_der_corput(n: int): int =
|
||||||
|
var
|
||||||
|
q = 1 # 0 is reserved for null
|
||||||
|
i = n
|
||||||
|
b = int.high shr 2 # int.high/2 .. int.high is reserved for dynmem
|
||||||
|
|
||||||
|
while i > 0:
|
||||||
|
q += (i and 1) * b
|
||||||
|
i = i shr 1
|
||||||
|
b = b shr 1
|
||||||
|
|
||||||
|
return q
|
||||||
|
|
||||||
|
proc add*[T](memory: var Memory[T], section: string, value: T) =
|
||||||
|
## Adds value to the end of memory in section.
|
||||||
|
if not (section in memory.sects):
|
||||||
|
memory.sects[section] = memory.chunks.len
|
||||||
|
memory.chunks.add @[]
|
||||||
|
|
||||||
|
memory.chunks[memory.sects[section]].add value
|
||||||
|
|
||||||
|
proc add*[T](memory: var Memory[T], section: string, values: openarray[T]) =
|
||||||
|
## Adds value to the end of memory in section.
|
||||||
|
if not (section in memory.sects):
|
||||||
|
memory.sects[section] = memory.chunks.len
|
||||||
|
memory.chunks.add @[]
|
||||||
|
|
||||||
|
memory.chunks[memory.sects[section]].add values
|
||||||
|
|
||||||
|
proc address*[T](memory: Memory[T], section: string, offset: int): int =
|
||||||
|
## Computes the "real" address of a given section and offset
|
||||||
|
return van_der_corput(memory.sects[section]) + offset
|
||||||
|
|
||||||
|
proc current*[T](memory: Memory[T], section: string): int =
|
||||||
|
## Computes the "real" address of the "next" element in the section
|
||||||
|
let i = memory.sects[section]
|
||||||
|
return van_der_corput(i) + len(memory.chunks[i])
|
||||||
|
|
||||||
|
proc addrinfo[T](memory: Memory[T], address: int): (int, int) =
|
||||||
|
## Calculates which section index an address points to and the offset in it
|
||||||
|
var
|
||||||
|
index = 0
|
||||||
|
start = van_der_corput(index)
|
||||||
|
|
||||||
|
for i in 1 .. memory.chunks.len:
|
||||||
|
let corput = van_der_corput(i)
|
||||||
|
if (corput < address) and (corput > start):
|
||||||
|
index = i
|
||||||
|
start = corput
|
||||||
|
|
||||||
|
return (index, address - start)
|
||||||
|
|
||||||
|
proc contains*[T](memory: Memory[T], address: int): bool =
|
||||||
|
## Checks if the given address is a valid allocated address
|
||||||
|
if address < SML_BLOCK_START:
|
||||||
|
let (idx, off) = memory.addrinfo(address)
|
||||||
|
return memory.chunks[idx].len >= off
|
||||||
|
elif address < MID_BLOCK_START:
|
||||||
|
let (blkid, offset) = divmod(address - SML_BLOCK_START, SML_BLOCK_SIZE)
|
||||||
|
return memory.smlmem[blkid].len >= offset
|
||||||
|
elif address < BIG_BLOCK_START:
|
||||||
|
let (blkid, offset) = divmod(address - MID_BLOCK_START, MID_BLOCK_SIZE)
|
||||||
|
return memory.midmem[blkid].len >= offset
|
||||||
|
elif address < HUG_BLOCK_START:
|
||||||
|
let (blkid, offset) = divmod(address - BIG_BLOCK_START, BIG_BLOCK_SIZE)
|
||||||
|
return memory.bigmem[blkid].len >= offset
|
||||||
|
else:
|
||||||
|
let (blkid, offset) = divmod(address - HUG_BLOCK_START, HUG_BLOCK_SIZE)
|
||||||
|
return memory.hugmem[blkid].len >= offset
|
||||||
|
|
||||||
|
proc `[]`*[T](memory: Memory[T], address: int): T =
|
||||||
|
## Accesses the underlying memory item for the given address, failing if it
|
||||||
|
## does not exist
|
||||||
|
if address < SML_BLOCK_START:
|
||||||
|
let (idx, off) = memory.addrinfo(address)
|
||||||
|
return memory.chunks[idx][off]
|
||||||
|
elif address < MID_BLOCK_START:
|
||||||
|
let (blkid, offset) = divmod(address - SML_BLOCK_START, SML_BLOCK_SIZE)
|
||||||
|
return memory.smlmem[blkid][offset]
|
||||||
|
elif address < BIG_BLOCK_START:
|
||||||
|
let (blkid, offset) = divmod(address - MID_BLOCK_START, MID_BLOCK_SIZE)
|
||||||
|
return memory.midmem[blkid][offset]
|
||||||
|
elif address < HUG_BLOCK_START:
|
||||||
|
let (blkid, offset) = divmod(address - BIG_BLOCK_START, BIG_BLOCK_SIZE)
|
||||||
|
return memory.bigmem[blkid][offset]
|
||||||
|
else:
|
||||||
|
let (blkid, offset) = divmod(address - HUG_BLOCK_START, HUG_BLOCK_SIZE)
|
||||||
|
return memory.hugmem[blkid][offset]
|
||||||
|
|
||||||
|
proc `[]`*[T](memory: var Memory[T], address: int): var T =
|
||||||
|
## Accesses the underlying memory item for the given address, failing if it
|
||||||
|
## does not exist
|
||||||
|
if address < SML_BLOCK_START:
|
||||||
|
let (idx, off) = memory.addrinfo(address)
|
||||||
|
return memory.chunks[idx][off]
|
||||||
|
elif address < MID_BLOCK_START:
|
||||||
|
let (blkid, offset) = divmod(address - SML_BLOCK_START, SML_BLOCK_SIZE)
|
||||||
|
return memory.smlmem[blkid][offset]
|
||||||
|
elif address < BIG_BLOCK_START:
|
||||||
|
let (blkid, offset) = divmod(address - MID_BLOCK_START, MID_BLOCK_SIZE)
|
||||||
|
return memory.midmem[blkid][offset]
|
||||||
|
elif address < HUG_BLOCK_START:
|
||||||
|
let (blkid, offset) = divmod(address - BIG_BLOCK_START, BIG_BLOCK_SIZE)
|
||||||
|
return memory.bigmem[blkid][offset]
|
||||||
|
else:
|
||||||
|
let (blkid, offset) = divmod(address - HUG_BLOCK_START, HUG_BLOCK_SIZE)
|
||||||
|
return memory.hugmem[blkid][offset]
|
||||||
|
|
||||||
|
proc `[]=`*[T](memory: var Memory[T], address: int, value: T) =
|
||||||
|
## Writes to the underlying memory item for a given address, failing if it
|
||||||
|
## does not exist
|
||||||
|
if address < SML_BLOCK_START:
|
||||||
|
let (idx, off) = memory.addrinfo(address)
|
||||||
|
memory.chunks[idx][off] = value
|
||||||
|
elif address < MID_BLOCK_START:
|
||||||
|
let (blkid, offset) = divmod(address - SML_BLOCK_START, SML_BLOCK_SIZE)
|
||||||
|
memory.smlmem[blkid][offset] = value
|
||||||
|
elif address < BIG_BLOCK_START:
|
||||||
|
let (blkid, offset) = divmod(address - MID_BLOCK_START, MID_BLOCK_SIZE)
|
||||||
|
memory.midmem[blkid][offset] = value
|
||||||
|
elif address < HUG_BLOCK_START:
|
||||||
|
let (blkid, offset) = divmod(address - BIG_BLOCK_START, BIG_BLOCK_SIZE)
|
||||||
|
memory.bigmem[blkid][offset] = value
|
||||||
|
else:
|
||||||
|
let (blkid, offset) = divmod(address - HUG_BLOCK_START, HUG_BLOCK_SIZE)
|
||||||
|
memory.hugmem[blkid][offset] = value
|
||||||
|
|
||||||
|
proc section*[T](memory: Memory[T], address: int): string =
|
||||||
|
## Calculates which section a given address points to (warning: slow)
|
||||||
|
let (idx, off) = memory.addrinfo(address)
|
||||||
|
|
||||||
|
for (section, index) in memory.sects.pairs:
|
||||||
|
if index == idx:
|
||||||
|
return section
|
||||||
|
|
||||||
|
return ""
|
||||||
|
|
||||||
|
iterator sections*[T](memory: Memory[T]): string =
|
||||||
|
for section in memory.sects.keys:
|
||||||
|
yield section
|
||||||
|
|
||||||
|
proc data*[T](memory: Memory[T], section: string): seq[T] =
|
||||||
|
return memory.chunks[memory.sects[section]]
|
||||||
|
|
||||||
|
proc allocate*[T](memory: var Memory[T], count: int): int =
|
||||||
|
## Allocates a block of count values that can be addressed starting from the
|
||||||
|
## returned value
|
||||||
|
if count < SML_BLOCK_SIZE:
|
||||||
|
var i = 0
|
||||||
|
while i in memory.smlmem:
|
||||||
|
inc i
|
||||||
|
if i > SML_BLOCK_COUNT:
|
||||||
|
raise new ResourceExhaustedError
|
||||||
|
memory.smlmem[i] = newSeq[T](count)
|
||||||
|
return SML_BLOCK_START + SML_BLOCK_SIZE * i
|
||||||
|
elif count < MID_BLOCK_SIZE:
|
||||||
|
var i = 0
|
||||||
|
while i in memory.smlmem:
|
||||||
|
inc i
|
||||||
|
if i > MID_BLOCK_COUNT:
|
||||||
|
raise new ResourceExhaustedError
|
||||||
|
memory.smlmem[i] = newSeq[T](count)
|
||||||
|
return MID_BLOCK_START + MID_BLOCK_SIZE * i
|
||||||
|
elif count < BIG_BLOCK_SIZE:
|
||||||
|
var i: int = 0
|
||||||
|
while i in memory.smlmem:
|
||||||
|
inc i
|
||||||
|
if i > BIG_BLOCK_COUNT:
|
||||||
|
raise new ResourceExhaustedError
|
||||||
|
memory.smlmem[i] = newSeq[T](count)
|
||||||
|
return BIG_BLOCK_START + BIG_BLOCK_SIZE * i
|
||||||
|
else:
|
||||||
|
var i = 0
|
||||||
|
while i in memory.smlmem:
|
||||||
|
inc i
|
||||||
|
if i > HUG_BLOCK_COUNT:
|
||||||
|
raise new ResourceExhaustedError
|
||||||
|
memory.smlmem[i] = newSeq[T](count)
|
||||||
|
return HUG_BLOCK_START + HUG_BLOCK_SIZE * i
|
||||||
|
|
||||||
|
proc deallocate*[T](memory: var Memory[T], address: int) =
|
||||||
|
## Deallocates the block containing address
|
||||||
|
if address < SML_BLOCK_START:
|
||||||
|
discard # Can't deallocate static memory
|
||||||
|
elif address < MID_BLOCK_START:
|
||||||
|
let blkid = (address - SML_BLOCK_START) div SML_BLOCK_SIZE
|
||||||
|
memory.smlmem[blkid].setLen(0)
|
||||||
|
memory.smlmem.del(blkid)
|
||||||
|
elif address < BIG_BLOCK_START:
|
||||||
|
let blkid = (address - MID_BLOCK_START) div MID_BLOCK_SIZE
|
||||||
|
memory.midmem[blkid].setLen(0)
|
||||||
|
memory.midmem.del(blkid)
|
||||||
|
elif address < HUG_BLOCK_START:
|
||||||
|
let blkid = (address - BIG_BLOCK_START) div BIG_BLOCK_SIZE
|
||||||
|
memory.bigmem[blkid].setLen(0)
|
||||||
|
memory.bigmem.del(blkid)
|
||||||
|
else:
|
||||||
|
let blkid = (address - HUG_BLOCK_START) div HUG_BLOCK_SIZE
|
||||||
|
memory.hugmem[blkid].setLen(0)
|
||||||
|
memory.hugmem.del(blkid)
|
||||||
|
|
||||||
|
proc reallocate*[T](memory: var Memory[T], address: int, count: int): int =
|
||||||
|
## Reallocates the block containing address to store up to count items
|
||||||
|
var theseq: seq[T]
|
||||||
|
if address < SML_BLOCK_START:
|
||||||
|
return address # Can't reallocate static memory
|
||||||
|
elif address < MID_BLOCK_START:
|
||||||
|
let blkid = (address - SML_BLOCK_START) div SML_BLOCK_SIZE
|
||||||
|
if count <= SML_BLOCK_SIZE:
|
||||||
|
memory.smlmem[blkid].setLen(count)
|
||||||
|
return address
|
||||||
|
assert memory.smlmem.pop(blkid, theseq)
|
||||||
|
elif address < BIG_BLOCK_START:
|
||||||
|
let blkid = (address - MID_BLOCK_START) div MID_BLOCK_SIZE
|
||||||
|
if count <= MID_BLOCK_SIZE:
|
||||||
|
memory.midmem[blkid].setLen(count)
|
||||||
|
return address
|
||||||
|
assert memory.midmem.pop(blkid, theseq)
|
||||||
|
elif address < HUG_BLOCK_START:
|
||||||
|
let blkid = (address - BIG_BLOCK_START) div BIG_BLOCK_SIZE
|
||||||
|
if count <= BIG_BLOCK_SIZE:
|
||||||
|
memory.bigmem[blkid].setLen(count)
|
||||||
|
return address
|
||||||
|
assert memory.bigmem.pop(blkid, theseq)
|
||||||
|
else:
|
||||||
|
let blkid = (address - HUG_BLOCK_START) div HUG_BLOCK_SIZE
|
||||||
|
if count <= HUG_BLOCK_SIZE:
|
||||||
|
memory.hugmem[blkid].setLen(count)
|
||||||
|
return address
|
||||||
|
assert memory.hugmem.pop(blkid, theseq)
|
||||||
|
|
||||||
|
theseq.setLen(count)
|
||||||
|
|
||||||
|
if count < SML_BLOCK_SIZE:
|
||||||
|
var i = 0
|
||||||
|
while i in memory.smlmem:
|
||||||
|
inc i
|
||||||
|
if i > SML_BLOCK_COUNT:
|
||||||
|
raise new ResourceExhaustedError
|
||||||
|
memory.smlmem[i] = theseq
|
||||||
|
return SML_BLOCK_START + SML_BLOCK_SIZE * i
|
||||||
|
elif count < MID_BLOCK_SIZE:
|
||||||
|
var i = 0
|
||||||
|
while i in memory.smlmem:
|
||||||
|
inc i
|
||||||
|
if i > MID_BLOCK_COUNT:
|
||||||
|
raise new ResourceExhaustedError
|
||||||
|
memory.smlmem[i] = theseq
|
||||||
|
return MID_BLOCK_START + MID_BLOCK_SIZE * i
|
||||||
|
elif count < BIG_BLOCK_SIZE:
|
||||||
|
var i = 0
|
||||||
|
while i in memory.smlmem:
|
||||||
|
inc i
|
||||||
|
if i > BIG_BLOCK_COUNT:
|
||||||
|
raise new ResourceExhaustedError
|
||||||
|
memory.smlmem[i] = theseq
|
||||||
|
return BIG_BLOCK_START + BIG_BLOCK_SIZE * i
|
||||||
|
else:
|
||||||
|
var i = 0
|
||||||
|
while i in memory.smlmem:
|
||||||
|
inc i
|
||||||
|
if i > HUG_BLOCK_COUNT:
|
||||||
|
raise new ResourceExhaustedError
|
||||||
|
memory.smlmem[i] = theseq
|
||||||
|
return HUG_BLOCK_START + HUG_BLOCK_SIZE * i
|
Loading…
Reference in a new issue