Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add A.5.8 Instructions #75

Merged
merged 2 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 54 additions & 15 deletions PolkaVM/Sources/PolkaVM/Instructions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ public enum Instructions {
public let offset: UInt32

public init(data: Data) throws {
register = try Registers.Index(data.at(relative: 0))
register = try Registers.Index(ra: data.at(relative: 0))
offset = try Instructions.decodeImmediate(data.at(relative: 1...))
}

Expand All @@ -207,7 +207,7 @@ public enum Instructions {
public let value: UInt32

public init(data: Data) throws {
register = try Registers.Index(data.at(relative: 0))
register = try Registers.Index(ra: data.at(relative: 0))
value = try Instructions.decodeImmediate(data.at(relative: 1...))
}

Expand All @@ -224,7 +224,7 @@ public enum Instructions {
public let address: UInt32

public init(data: Data) throws {
register = try Registers.Index(data.at(relative: 0))
register = try Registers.Index(ra: data.at(relative: 0))
address = try Instructions.decodeImmediate(data.at(relative: 1...))
}

Expand All @@ -242,7 +242,7 @@ public enum Instructions {
public let address: UInt32

public init(data: Data) throws {
register = try Registers.Index(data.at(relative: 0))
register = try Registers.Index(ra: data.at(relative: 0))
address = try Instructions.decodeImmediate(data.at(relative: 1...))
}

Expand All @@ -260,7 +260,7 @@ public enum Instructions {
public let address: UInt32

public init(data: Data) throws {
register = try Registers.Index(data.at(relative: 0))
register = try Registers.Index(ra: data.at(relative: 0))
address = try Instructions.decodeImmediate(data.at(relative: 1...))
}

Expand All @@ -281,7 +281,7 @@ public enum Instructions {
public let address: UInt32

public init(data: Data) throws {
register = try Registers.Index(data.at(relative: 0))
register = try Registers.Index(ra: data.at(relative: 0))
address = try Instructions.decodeImmediate(data.at(relative: 1...))
}

Expand All @@ -302,7 +302,7 @@ public enum Instructions {
public let address: UInt32

public init(data: Data) throws {
register = try Registers.Index(data.at(relative: 0))
register = try Registers.Index(ra: data.at(relative: 0))
address = try Instructions.decodeImmediate(data.at(relative: 1...))
}

Expand All @@ -323,7 +323,7 @@ public enum Instructions {
public let address: UInt32

public init(data: Data) throws {
register = try Registers.Index(data.at(relative: 0))
register = try Registers.Index(ra: data.at(relative: 0))
address = try Instructions.decodeImmediate(data.at(relative: 1...))
}

Expand All @@ -341,7 +341,7 @@ public enum Instructions {
public let address: UInt32

public init(data: Data) throws {
register = try Registers.Index(data.at(relative: 0))
register = try Registers.Index(ra: data.at(relative: 0))
address = try Instructions.decodeImmediate(data.at(relative: 1...))
}

Expand All @@ -359,7 +359,7 @@ public enum Instructions {
public let address: UInt32

public init(data: Data) throws {
register = try Registers.Index(data.at(relative: 0))
register = try Registers.Index(ra: data.at(relative: 0))
address = try Instructions.decodeImmediate(data.at(relative: 1...))
}

Expand All @@ -380,7 +380,7 @@ public enum Instructions {
public let value: UInt8

public init(data: Data) throws {
register = try Registers.Index(data.at(relative: 0))
register = try Registers.Index(ra: data.at(relative: 0))
let (x, y) = try Instructions.decodeImmediate2(data, divideBy: 16)
address = x
value = UInt8(truncatingIfNeeded: y)
Expand All @@ -400,7 +400,7 @@ public enum Instructions {
public let value: UInt16

public init(data: Data) throws {
register = try Registers.Index(data.at(relative: 0))
register = try Registers.Index(ra: data.at(relative: 0))
let (x, y) = try Instructions.decodeImmediate2(data, divideBy: 16)
address = x
value = UInt16(truncatingIfNeeded: y)
Expand All @@ -420,7 +420,7 @@ public enum Instructions {
public let value: UInt32

public init(data: Data) throws {
register = try Registers.Index(data.at(relative: 0))
register = try Registers.Index(ra: data.at(relative: 0))
let (x, y) = try Instructions.decodeImmediate2(data, divideBy: 16)
address = x
value = y
Expand All @@ -442,7 +442,7 @@ public enum Instructions {
public let offset: UInt32

public init(data: Data) throws {
register = try Registers.Index(data.at(relative: 0))
register = try Registers.Index(ra: data.at(relative: 0))
(value, offset) = try Instructions.decodeImmediate2(data, divideBy: 16)
}

Expand Down Expand Up @@ -559,6 +559,45 @@ public enum Instructions {
var offset: UInt32
public init(data: Data) throws { (register, value, offset) = try Self.parse(data: data) }
}

// MARK: Instructions with Arguments of Two Registers (5.8)

public struct MoveReg: Instruction {
public static var opcode: UInt8 { 82 }

public let src: Registers.Index
public let dest: Registers.Index

public init(data: Data) throws {
dest = try Registers.Index(ra: data.at(relative: 0))
src = try Registers.Index(rb: data.at(relative: 0))
}

public func _executeImpl(state: VMState) -> ExecOutcome {
state.writeRegister(dest, state.readRegister(src))
return .continued
}
}

public struct Sbrk: Instruction {
public static var opcode: UInt8 { 87 }

public let src: Registers.Index
public let dest: Registers.Index

public init(data: Data) throws {
dest = try Registers.Index(ra: data.at(relative: 0))
src = try Registers.Index(rb: data.at(relative: 0))
}

public func _executeImpl(state: VMState) throws -> ExecOutcome {
let increment = state.readRegister(src)
let startAddr = try state.sbrk(increment)
state.writeRegister(dest, startAddr)

return .continued
}
}
}

// MARK: Branch Helpers
Expand All @@ -584,7 +623,7 @@ protocol BranchInstructionBase<Compare>: Instruction {

extension BranchInstructionBase {
public static func parse(data: Data) throws -> (Registers.Index, UInt32, UInt32) {
let register = try Registers.Index(data.at(relative: 0))
let register = try Registers.Index(ra: data.at(relative: 0))
let (value, offset) = try Instructions.decodeImmediate2(data, divideBy: 16)
return (register, value, offset)
}
Expand Down
24 changes: 24 additions & 0 deletions PolkaVM/Sources/PolkaVM/Memory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ public class Memory {
public enum Error: Swift.Error {
case pageFault(UInt32)
case notWritable(UInt32)
case outOfMemory(UInt32)

public var address: UInt32 {
switch self {
case let .pageFault(address):
address
case let .notWritable(address):
address
case let .outOfMemory(address):
address
}
}
}
Expand Down Expand Up @@ -129,6 +132,27 @@ public class Memory {
}
throw Error.notWritable(address)
}

public func sbrk(_ increment: UInt32) throws -> UInt32 {
// TODO: update after memory layout details are implemented
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: need equation 246 to be impl, so we can have correct sbrk

var curHeapEnd: UInt32 = 0

if let lastChunk = chunks.last {
curHeapEnd = lastChunk.address + UInt32(lastChunk.data.count)
}

for page in pageMap {
let pageEnd = page.address + page.length
if page.writable, curHeapEnd >= page.address, curHeapEnd + increment < pageEnd {
let newChunk = (address: curHeapEnd, data: Data(repeating: 0, count: Int(increment)))
chunks.append(newChunk)

return curHeapEnd
}
}

throw Error.outOfMemory(curHeapEnd)
}
}

extension Memory {
Expand Down
8 changes: 6 additions & 2 deletions PolkaVM/Sources/PolkaVM/Registers.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
public struct Registers: Equatable {
public struct Index {
public let value: UInt8
public init(_ value: UInt8) {
self.value = min(value & 0b1111, 12)
public init(ra: UInt8) {
value = min(ra & 0b1111, 12)
}

public init(rb: UInt8) {
value = min(rb >> 4, 12)
}
}

Expand Down
4 changes: 4 additions & 0 deletions PolkaVM/Sources/PolkaVM/VMState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ public class VMState {
try memory.write(address: address, values: values)
}

public func sbrk(_ increment: UInt32) throws -> UInt32 {
try memory.sbrk(increment)
}

public func consumeGas(_ amount: UInt64) {
// TODO: use saturating subtraction
gas -= Int64(amount)
Expand Down
Loading