diff --git a/src/arctic.nim b/src/arctic.nim index e8b3cd8..22fe8ec 100644 --- a/src/arctic.nim +++ b/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 itertools +import memory + type - BitShiftType = range[0 .. 64] - ArcticTypeKind* = enum - BYTE, SHORT, INT, WORD, DOUBLE + ArcticPointer = int64 ArcticType* {.union.} = object b: int8 @@ -14,25 +14,19 @@ type i: int64 u: uint64 d: float64 - f: ArcticSymbol # also used for pointers - # TODO: Eventually replace f with p/f and each is just a uint64 - # Then load all memory into one long seq instead of 1 seq per - # section. Probably actually have +ve be data memory, and -ve be - # code memory (with sections mapping to ranges) + p: ArcticPointer # always positive (null is 0) + f: ArcticPointer # always negative (null is 0) + # 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_I, VARIABLE_N, VARIABLE_X, VARIABLE_Y, VARIABLE_Z - ArcticSymbol* = tuple - section: string - index: int - - ArcticImmediateKind* = enum + ArcticImmediateKind = enum PLAIN, VARIABLE, INTEGER, NUMBER, SYMBOL - ArcticImmediate* = object + ArcticImmediate = object case kind: ArcticImmediateKind of PLAIN: nil of VARIABLE: v: ArcticVariableIndex @@ -40,34 +34,27 @@ type of NUMBER: n: float64 of SYMBOL: s: string - ArcticOperation* = object + ArcticOperation = object code: char immediate: ArcticImmediate + bigendian: bool - ArcticCode* = seq[ArcticOperation] - ArcticMemory* = seq[uint8] - - ArcticSection* = object - case iscode: bool - of true: code: ArcticCode - of false: data: ArcticMemory - ArcticStack* = seq[ArcticType] + ArcticStack = seq[ArcticType] ArcticState* = object - symbols: CritBitTree[ArcticSymbol] # as name or section _name - sections: CritBitTree[ArcticSection] + memory: Memory[uint8] + code: Memory[ArcticOperation] + symbols: CritBitTree[ArcticPointer] # as name or section _name stack: ArcticStack - pc: ArcticSymbol + pc: ArcticPointer # NOT negative! registers: array[ArcticVariableIndex, ArcticType] + dynmem: Table[ArcticPointer, int] # pointer -> length ArcticStepResult* = enum CONTINUE, BREAKPOINT, ERROR ArcticBuiltin* = proc (state: var ArcticState): ArcticStepResult -var - next_malloc_id: int = 1 - const 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', '_', '.', '+', '-', '*', '/', '%', '\\', '|', '&', '^', '!', '?', '(', ')', '`' } @@ -105,34 +92,27 @@ proc `$`*(state: ArcticState): string = for item in state.stack: result &= &" {item}\n" - for (name, section) in state.sections.pairs: - result &= &"\n\"{name}\": " - if section.iscode: - result &= "code \n" - for (i, m) in section.code.pairs: - for (label, location) in state.symbols.pairs: - if location.section == name and location.index == i: - result &= &":{label} " - if state.pc.section == name and state.pc.index == i: + for section in state.code.sections: + result &= "\n" + for (i, m) in state.code.data(section).pairs: + for (label, location) in state.symbols.pairs: + if -location == state.code.address(section, i): + result &= &":{label} " + if state.pc == state.code.address(section, i): result &= ">" result &= $m - else: - result &= "\n" - for (i, m) in section.data.pairs: - for (label, location) in state.symbols.pairs: - if location.section == name and location.index == i: - result &= &":{label} " - result &= &"{m} " + + for section in state.memory.sections: + result &= "\n" + for (i, m) in state.memory.data(section).pairs: + for (label, location) in state.symbols.pairs: + if location == state.memory.address(section, i): + result &= &":{label} " + result &= &"{m} " proc op(code: char, immediate: ArcticImmediate = ArcticImmediate(kind: PLAIN)): ArcticOperation = 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 = case code.toLowerAscii: of 'a': VARIABLE_A @@ -145,25 +125,18 @@ proc tovar(code: char): ArcticVariableIndex = of 'z': VARIABLE_Z else: raise new ValueError -proc add(section: var ArcticSection, code: char, immstr: string, secname: string) = - if section.iscode: - if immstr.match(re"^\d+$"): - section.code.add code.op(ArcticImmediate(kind: INTEGER, i: immstr.parseInt)) - elif immstr.match(re"^[AaBbCcIiNnXxYyZz]$"): - section.code.add code.op(ArcticImmediate(kind: VARIABLE, v: immstr[0].tovar)) - elif immstr[0] == '$': - if immstr.len == 1 or immstr[1] == '_': - section.code.add code.op(ArcticImmediate(kind: SYMBOL, s: secname & " " & immstr)) - else: - section.code.add code.op(ArcticImmediate(kind: SYMBOL, s: immstr)) +proc parse_immediate(imm: string, section: string): ArcticImmediate = + if imm.match(re"^\d+$"): + return ArcticImmediate(kind: INTEGER, i: imm.parseInt) + elif imm.match(re"^[AaBbCcIiNnXxYyZz]$"): + return ArcticImmediate(kind: VARIABLE, v: imm[0].tovar) + elif imm[0] == '$': + if imm.len == 1 or imm[1] == '_': + return ArcticImmediate(kind: SYMBOL, s: section & " " & imm) else: - section.code.add code.op(ArcticImmediate(kind: NUMBER, n: immstr.parseFloat)) - -proc len(section: ArcticSection): int = - if section.iscode: - return section.code.len + return ArcticImmediate(kind: SYMBOL, s: imm) else: - return section.data.len + return ArcticImmediate(kind: NUMBER, n: imm.parseFloat) func grabnum(data: string): (string, string) = ## 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] -proc insert(section: var ArcticSection, data: string) = +proc parse_data(data: string): seq[uint8] = if data.len == 0: return - if section.iscode: - return - template insertInt(itype, utype, endianness) = let (text, rest) = data[1..^1].grabnum if text[0] == '-': let val: itype = itype(-text[1..^1].parseBiggestInt) - section.data.add cast[utype](val).serialize(endianness) + result.add cast[utype](val).serialize(endianness) else: 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]: of 'i': insertInt(int64, uint64, littleEndian) @@ -204,48 +174,59 @@ proc insert(section: var ArcticSection, data: string) = let (text, rest) = data[1..^1].grabnum if text[0] == '-': - let val: int8 = int8(text[1..^1].parseBiggestInt) - section.data.add cast[uint8](val) + let val: int8 = int8(-text[1..^1].parseBiggestInt) + result.add cast[uint8](val) else: let val: uint8 = uint8(text.parseBiggestUInt) - section.data.add val + result.add val + result.add parse_data(rest) of 'f': let (text, rest) = data[1..^1].grabnum - section.data.add cast[uint64](text.parseFloat).serialize(littleEndian) - section.insert(rest) + result.add cast[uint64](text.parseFloat).serialize(littleEndian) + result.add parse_data(rest) + of 'F': let (text, rest) = data[1..^1].grabnum - section.data.add cast[uint64](text.parseFloat).serialize(bigEndian) - section.insert(rest) + result.add cast[uint64](text.parseFloat).serialize(bigEndian) + result.add parse_data(rest) of 'x': # hexadecimal byte constant let (hex, x, rest) = data[1..^1].partition("x") for pair in hex.chunked(2): - section.data.add uint8(parseHexInt(pair.join)) - section.insert(rest) + result.add uint8(parseHexInt(pair.join)) + result.add parse_data(rest) of '"': # utf-8 string constant with escapes let strlen = data.matchLen(re"^""([^""]|\\"")*""") - - if strlen < 0: - return # TODO: couldn't find a string, what to do? - - for c in data[1..^(strlen-2)]: - section.data.add c.uint8 - - section.insert(data[strlen..^1]) + assert strlen >= 0 + for c in unescape(data[1..strlen]): + result.add c.uint8 + result.add parse_data(data[strlen..^1]) 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 = var section: string = "" token: string = "" - result.pc = ("", 0) - result.sections[section] = ArcticSection(iscode: true, code: @[]) + result.pc = 1 for next in code: debug_echo "token: ", token, ", next: ", next @@ -254,7 +235,7 @@ func load*(code: string): ArcticState = of ImmediateOps, '#', ':', '\"', '\'': token &= next of PlainOps, '\n': - result.sections[section].add next + result.code.add(section, raw_op(next)) else: discard else: @@ -262,16 +243,11 @@ func load*(code: string): ArcticState = of '#': # comment if next == '\n': token = "" - result.sections[section].add next + result.code.add(section, raw_op(next)) of '"': # section switch if next == '"' and token[^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 = "" else: token.add next @@ -279,7 +255,10 @@ func load*(code: string): ArcticState = of ':': # label name if next == ' ' or next == '\n': 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 = "" else: token.add next @@ -302,14 +281,17 @@ func load*(code: string): ArcticState = if quoted or escaped: token.add next else: - result.sections[section].insert token[1..^1] + result.memory.add(section, parse_data(token[1..^1])) token = "" else: token.add next of ImmediateOps: 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 = "" else: token.add next @@ -317,54 +299,22 @@ func load*(code: string): ArcticState = else: 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 = - let codesec = state.sections[state.pc.section] - - 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 + let op = state.code[state.pc] + state.pc.inc case op.code: # Memory Ops ----------------------------------------------------------- of '1': # LDAB - let p = state.stack.pop.f - state.stack.add ArcticType(i: state[p].int64) + let p = state.stack.pop.p + state.stack.add ArcticType(i: state.memory[p].int64) of '2': # LDAS let p = state.stack.pop.f - a = state[p].int64 - b = state[p+1].int64 - if state.pc.section == "CODE": # bigendian + a = state.memory[p].int64 + b = state.memory[p+1].int64 + if op.bigendian: state.stack.add ArcticType(i: a or b shl 8) else: 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 let p = state.stack.pop.f - a = state[p].int64 - b = state[p+1].int64 - c = state[p+2].int64 - d = state[p+3].int64 - if state.pc.section == "CODE": # bigendian + a = state.memory[p].int64 + b = state.memory[p+1].int64 + c = state.memory[p+2].int64 + d = state.memory[p+3].int64 + if op.bigendian: state.stack.add ArcticType(i: d or c shl 8 or b shl 16 or a shl 24) else: 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 let p = state.stack.pop.f - a = state[p].int64 - b = state[p+1].int64 - c = state[p+2].int64 - d = state[p+3].int64 - e = state[p+4].int64 - f = state[p+5].int64 - g = state[p+6].int64 - h = state[p+7].int64 - if state.pc.section == "CODE": # bigendian + a = state.memory[p].int64 + b = state.memory[p+1].int64 + c = state.memory[p+2].int64 + d = state.memory[p+3].int64 + e = state.memory[p+4].int64 + f = state.memory[p+5].int64 + g = state.memory[p+6].int64 + h = state.memory[p+7].int64 + 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) 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) @@ -400,15 +350,15 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic of 'o': # LDOB assert op.immediate.kind == INTEGER 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 assert op.immediate.kind == INTEGER let p = state.stack.pop.f + op.immediate.i - a = state[p].int64 - b = state[p+1].int64 - if state.pc.section == "CODE": # bigendian + a = state.memory[p].int64 + b = state.memory[p+1].int64 + if op.bigendian: state.stack.add ArcticType(i: a or b shl 8) else: 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 let p = state.stack.pop.f + op.immediate.i - a = state[p].int64 - b = state[p+1].int64 - c = state[p+2].int64 - d = state[p+3].int64 - if state.pc.section == "CODE": # bigendian + a = state.memory[p].int64 + b = state.memory[p+1].int64 + c = state.memory[p+2].int64 + d = state.memory[p+3].int64 + if op.bigendian: state.stack.add ArcticType(i: d or c shl 8 or b shl 16 or a shl 24) else: 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 let p = state.stack.pop.f - a = state[p].int64 - b = state[p+1].int64 - c = state[p+2].int64 - d = state[p+3].int64 - e = state[p+4].int64 - f = state[p+5].int64 - g = state[p+6].int64 - h = state[p+7].int64 - if state.pc.section == "CODE": # bigendian + a = state.memory[p].int64 + b = state.memory[p+1].int64 + c = state.memory[p+2].int64 + d = state.memory[p+3].int64 + e = state.memory[p+4].int64 + f = state.memory[p+5].int64 + g = state.memory[p+6].int64 + h = state.memory[p+7].int64 + 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) 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) @@ -445,63 +395,63 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic let x = cast[uint8](state.stack.pop.b) p = state.stack.pop.f - state[p] = x + state.memory[p] = x of '6': # STAS let x = cast[uint16](state.stack.pop.s) p = state.stack.pop.f - if state.pc.section == "CODE": # bigendian - state[p] = uint8(x and 0xFF) - state[p+1] = uint8(x shr 8) + if op.bigendian: + state.memory[p] = uint8(x and 0xFF) + state.memory[p+1] = uint8(x shr 8) else: - state[p] = uint8(x shr 8) - state[p+1] = uint8(x and 0xFF) + state.memory[p] = uint8(x shr 8) + state.memory[p+1] = uint8(x and 0xFF) of '7': # STAI let x = cast[uint32](state.stack.pop.i) p = state.stack.pop.f - if state.pc.section == "CODE": # bigendian - state[p] = uint8(x and 0xFF) - state[p+1] = uint8((x shr 8) and 0xFF) - state[p+2] = uint8((x shr 16) and 0xFF) - state[p+3] = uint8((x shr 24) and 0xFF) + if op.bigendian: + state.memory[p] = uint8(x and 0xFF) + state.memory[p+1] = uint8((x shr 8) and 0xFF) + state.memory[p+2] = uint8((x shr 16) and 0xFF) + state.memory[p+3] = uint8((x shr 24) and 0xFF) else: - state[p] = uint8((x shr 24) and 0xFF) - state[p+1] = uint8((x shr 16) and 0xFF) - state[p+2] = uint8((x shr 8) and 0xFF) - state[p+3] = uint8(x and 0xFF) + state.memory[p] = uint8((x shr 24) and 0xFF) + state.memory[p+1] = uint8((x shr 16) and 0xFF) + state.memory[p+2] = uint8((x shr 8) and 0xFF) + state.memory[p+3] = uint8(x and 0xFF) of '8': # STAW let x = cast[uint64](state.stack.pop.i) p = state.stack.pop.f - if state.pc.section == "CODE": # bigendian - state[p] = uint8(x and 0xFF) - state[p+1] = uint8((x shr 8) and 0xFF) - state[p+2] = uint8((x shr 16) and 0xFF) - state[p+3] = uint8((x shr 24) and 0xFF) - state[p+4] = uint8((x shr 32) and 0xFF) - state[p+5] = uint8((x shr 40) and 0xFF) - state[p+6] = uint8((x shr 48) and 0xFF) - state[p+7] = uint8((x shr 56) and 0xFF) + if op.bigendian: + state.memory[p] = uint8(x and 0xFF) + state.memory[p+1] = uint8((x shr 8) and 0xFF) + state.memory[p+2] = uint8((x shr 16) and 0xFF) + state.memory[p+3] = uint8((x shr 24) and 0xFF) + state.memory[p+4] = uint8((x shr 32) and 0xFF) + state.memory[p+5] = uint8((x shr 40) and 0xFF) + state.memory[p+6] = uint8((x shr 48) and 0xFF) + state.memory[p+7] = uint8((x shr 56) and 0xFF) else: - state[p] = uint8((x shr 56) and 0xFF) - state[p+1] = uint8((x shr 48) and 0xFF) - state[p+2] = uint8((x shr 40) and 0xFF) - state[p+3] = uint8((x shr 32) and 0xFF) - state[p+4] = uint8((x shr 24) and 0xFF) - state[p+5] = uint8((x shr 16) and 0xFF) - state[p+6] = uint8((x shr 8) and 0xFF) - state[p+7] = uint8(x and 0xFF) + state.memory[p] = uint8((x shr 56) and 0xFF) + state.memory[p+1] = uint8((x shr 48) and 0xFF) + state.memory[p+2] = uint8((x shr 40) and 0xFF) + state.memory[p+3] = uint8((x shr 32) and 0xFF) + state.memory[p+4] = uint8((x shr 24) and 0xFF) + state.memory[p+5] = uint8((x shr 16) and 0xFF) + state.memory[p+6] = uint8((x shr 8) and 0xFF) + state.memory[p+7] = uint8(x and 0xFF) of 'D': # MCLR let x = state.stack.pop.i p = state.stack.pop.f for i in 0 .. x: - state[p+i] = 0 + state.memory[p+i] = 0 of 'd': # MSET assert op.immediate.kind == INTEGER @@ -510,7 +460,7 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic p = state.stack.pop.f b = op.immediate.i.uint8 for i in 0 .. x: - state[p+i] = b + state.memory[p+i] = b of 'K': # MCPY let @@ -518,13 +468,13 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic q = state.stack.pop.f p = state.stack.pop.f for i in 0 .. x: - state[q+i] = state[p+i] + state.memory[q+i] = state.memory[p+i] of 'J': # MOFF let x = state.stack.pop.i - p = state.stack.pop.f - state.stack.add ArcticType(f: (section: p.section, index: p.index + 1)) + p = state.stack.pop.p + state.stack.add ArcticType(p: p + x) of 'M': # MALL assert op.immediate.kind == INTEGER @@ -534,18 +484,16 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic if n == 0: if top.i != 0: - state.sections.excl top.f.section + state.memory.deallocate(top.p) state.stack.add ArcticType(i: 0) elif n > 0: if top.i == 0: - state.sections.incl("allocated " & $next_malloc_id, ArcticSection(iscode: false, data: @[])) - inc next_malloc_id + state.stack.add ArcticType(p: state.memory.allocate(n)) else: - discard # we use dynamic memory, realloc is a no-op + state.stack.add ArcticType(p: state.memory.reallocate(top.p, n)) else: discard # realloc negative is a nop - of 'R': # REAL let top = state.stack.pop @@ -553,18 +501,16 @@ proc step*(state: var ArcticState, builtins: CritBitTree[ArcticBuiltin]): Arctic if x == 0: if top.i != 0: - state.sections.excl top.f.section + state.memory.deallocate(top.p) state.stack.add ArcticType(i: 0) elif x > 0: if top.i == 0: - state.sections.incl("allocated " & $next_malloc_id, ArcticSection(iscode: false, data: @[])) - inc next_malloc_id + state.stack.add ArcticType(p: state.memory.allocate(x)) else: - discard # we use dynamic memory, realloc is a no-op + state.stack.add ArcticType(p: state.memory.reallocate(top.p, x)) else: discard # realloc negative is a nop - of '9': # CASS # TODO: Actually CAS? need to use Atomic[T] for that... # 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 x = state.stack.pop.i p = state.stack.pop.f - a = state[p].int64 - b = state[p+1].int64 - c = state[p+2].int64 - d = state[p+3].int64 - e = state[p+4].int64 - f = state[p+5].int64 - g = state[p+6].int64 - h = state[p+7].int64 + a = state.memory[p].int64 + b = state.memory[p+1].int64 + c = state.memory[p+2].int64 + d = state.memory[p+3].int64 + e = state.memory[p+4].int64 + f = state.memory[p+5].int64 + g = state.memory[p+6].int64 + h = state.memory[p+7].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 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 if x == old: state.stack.add ArcticType(i: 1) - if state.pc.section == "CODE": # bigendian - state[p] = uint8(y and 0xFF) - state[p+1] = uint8((y shr 8) and 0xFF) - state[p+2] = uint8((y shr 16) and 0xFF) - state[p+3] = uint8((y shr 24) and 0xFF) - state[p+4] = uint8((y shr 32) and 0xFF) - state[p+5] = uint8((y shr 40) and 0xFF) - state[p+6] = uint8((y shr 48) and 0xFF) - state[p+7] = uint8((y shr 56) and 0xFF) + if op.bigendian: + state.memory[p] = uint8(y and 0xFF) + state.memory[p+1] = uint8((y shr 8) and 0xFF) + state.memory[p+2] = uint8((y shr 16) and 0xFF) + state.memory[p+3] = uint8((y shr 24) and 0xFF) + state.memory[p+4] = uint8((y shr 32) and 0xFF) + state.memory[p+5] = uint8((y shr 40) and 0xFF) + state.memory[p+6] = uint8((y shr 48) and 0xFF) + state.memory[p+7] = uint8((y shr 56) and 0xFF) else: - state[p] = uint8((y shr 56) and 0xFF) - state[p+1] = uint8((y shr 48) and 0xFF) - state[p+2] = uint8((y shr 40) and 0xFF) - state[p+3] = uint8((y shr 32) and 0xFF) - state[p+4] = uint8((y shr 24) and 0xFF) - state[p+5] = uint8((y shr 16) and 0xFF) - state[p+6] = uint8((y shr 8) and 0xFF) - state[p+7] = uint8(y and 0xFF) + state.memory[p] = uint8((y shr 56) and 0xFF) + state.memory[p+1] = uint8((y shr 48) and 0xFF) + state.memory[p+2] = uint8((y shr 40) and 0xFF) + state.memory[p+3] = uint8((y shr 32) and 0xFF) + state.memory[p+4] = uint8((y shr 24) and 0xFF) + state.memory[p+5] = uint8((y shr 16) and 0xFF) + state.memory[p+6] = uint8((y shr 8) and 0xFF) + state.memory[p+7] = uint8(y and 0xFF) else: 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+... # Control Ops ---------------------------------------------------------- - ## TODO + # TODO - ## TODO + # TODO when isMainModule: