From e83951315661284f9edeaba682b3f0e14773c60d Mon Sep 17 00:00:00 2001 From: Qiwei Yang Date: Mon, 20 Jan 2025 17:10:26 +0800 Subject: [PATCH 1/2] 0.5.4 updates (#266) * instructions update * host call updates --- .../RuntimeProtocols/AccumulateFunction.swift | 6 +- .../RuntimeProtocols/Accumulation.swift | 6 +- .../Blockchain/RuntimeProtocols/Runtime.swift | 2 +- .../Blockchain/Types/ServiceAccount.swift | 4 +- .../VMInvocations/HostCall/HostCalls.swift | 178 ++++-- .../AccumulateContext.swift | 15 +- .../Invocations/AccumulateInvocation.swift | 8 +- .../Sources/PolkaVM/InstructionTable.swift | 23 + .../PolkaVM/Instructions/Instructions.swift | 594 +++++++++++++++--- PolkaVM/Sources/PolkaVM/invokePVM.swift | 2 +- 10 files changed, 688 insertions(+), 150 deletions(-) diff --git a/Blockchain/Sources/Blockchain/RuntimeProtocols/AccumulateFunction.swift b/Blockchain/Sources/Blockchain/RuntimeProtocols/AccumulateFunction.swift index 061d1146..48af8f04 100644 --- a/Blockchain/Sources/Blockchain/RuntimeProtocols/AccumulateFunction.swift +++ b/Blockchain/Sources/Blockchain/RuntimeProtocols/AccumulateFunction.swift @@ -44,7 +44,7 @@ public struct DeferredTransfers: Codable { /// which are both needed and mutable by the accumulation process. public struct AccumulateState { /// d - public var serviceAccounts: [ServiceIndex: ServiceAccount] + public var newServiceAccounts: [ServiceIndex: ServiceAccount] /// i public var validatorQueue: ConfigFixedSizeArray< ValidatorKey, ProtocolConfig.TotalNumberOfValidators @@ -63,7 +63,7 @@ public struct AccumulateState { /// X public struct AccumlateResultContext { - /// d + /// d: all existing service accounts public var serviceAccounts: ServiceAccounts /// s: the accumulating service account index public var serviceIndex: ServiceIndex @@ -73,6 +73,8 @@ public struct AccumlateResultContext { public var nextAccountIndex: ServiceIndex /// t: deferred transfers public var transfers: [DeferredTransfers] + /// y + public var yield: Data32? } public protocol AccumulateFunction { diff --git a/Blockchain/Sources/Blockchain/RuntimeProtocols/Accumulation.swift b/Blockchain/Sources/Blockchain/RuntimeProtocols/Accumulation.swift index 9885d90d..c00ca268 100644 --- a/Blockchain/Sources/Blockchain/RuntimeProtocols/Accumulation.swift +++ b/Blockchain/Sources/Blockchain/RuntimeProtocols/Accumulation.swift @@ -179,7 +179,7 @@ extension Accumulation { } // new service accounts - for (service, account) in singleOutput.state.serviceAccounts { + for (service, account) in singleOutput.state.newServiceAccounts { guard newServiceAccounts[service] == nil, try await get(serviceAccount: service) == nil else { throw AccumulationError.duplicatedServiceIndex } @@ -201,7 +201,7 @@ extension Accumulation { return ParallelAccumulationOutput( gasUsed: gasUsed, state: AccumulateState( - serviceAccounts: newServiceAccounts, + newServiceAccounts: newServiceAccounts, validatorQueue: newValidatorQueue ?? validatorQueue, authorizationQueue: newAuthorizationQueue ?? authorizationQueue, privilegedServices: newPrivilegedServices ?? privilegedServices @@ -339,7 +339,7 @@ extension Accumulation { config: config, block: block, state: AccumulateState( - serviceAccounts: [:], + newServiceAccounts: [:], validatorQueue: validatorQueue, authorizationQueue: authorizationQueue, privilegedServices: privilegedServices diff --git a/Blockchain/Sources/Blockchain/RuntimeProtocols/Runtime.swift b/Blockchain/Sources/Blockchain/RuntimeProtocols/Runtime.swift index 4a4f4554..f86d5333 100644 --- a/Blockchain/Sources/Blockchain/RuntimeProtocols/Runtime.swift +++ b/Blockchain/Sources/Blockchain/RuntimeProtocols/Runtime.swift @@ -235,7 +235,7 @@ public final class Runtime { state.authorizationQueue = accumulateState.authorizationQueue state.validatorQueue = accumulateState.validatorQueue state.privilegedServices = accumulateState.privilegedServices - for (service, account) in accumulateState.serviceAccounts { + for (service, account) in accumulateState.newServiceAccounts { state[serviceAccount: service] = account.toDetails() for (hash, value) in account.storage { state[serviceAccount: service, storageKey: hash] = value diff --git a/Blockchain/Sources/Blockchain/Types/ServiceAccount.swift b/Blockchain/Sources/Blockchain/Types/ServiceAccount.swift index 92d0516a..c6dd12cb 100644 --- a/Blockchain/Sources/Blockchain/Types/ServiceAccount.swift +++ b/Blockchain/Sources/Blockchain/Types/ServiceAccount.swift @@ -14,7 +14,7 @@ public struct ServiceAccountDetails: Sendable, Equatable, Codable { // m public var minOnTransferGas: Gas - // l: the total number of octets used in storage + // o: the total number of octets used in storage public var totalByteLength: UInt64 // i: number of items in storage @@ -104,7 +104,7 @@ extension ServiceAccount { UInt32(2 * preimageInfos.count + storage.count) } - // l: the total number of octets used in storage + // o: the total number of octets used in storage public var totalByteLength: UInt64 { let preimageInfosBytes = preimageInfos.keys.reduce(into: 0) { $0 += 81 + $1.length } let storageBytes = storage.values.reduce(into: 0) { $0 += 32 + $1.count } diff --git a/Blockchain/Sources/Blockchain/VMInvocations/HostCall/HostCalls.swift b/Blockchain/Sources/Blockchain/VMInvocations/HostCall/HostCalls.swift index 5267f74b..9cae7709 100644 --- a/Blockchain/Sources/Blockchain/VMInvocations/HostCall/HostCalls.swift +++ b/Blockchain/Sources/Blockchain/VMInvocations/HostCall/HostCalls.swift @@ -382,8 +382,11 @@ public class New: HostCall { x.serviceAccounts.set(serviceAccount: x.serviceIndex, account: acc) state.writeRegister(Registers.Index(raw: 7), x.nextAccountIndex) - x.accumulateState.serviceAccounts.merge([x.nextAccountIndex: newAccount]) { _, new in new } - x.nextAccountIndex = AccumulateContext.check(i: bump(i: x.nextAccountIndex), serviceAccounts: x.accumulateState.serviceAccounts) + x.accumulateState.newServiceAccounts.merge([x.nextAccountIndex: newAccount]) { _, new in new } + x.nextAccountIndex = AccumulateContext.check( + i: bump(i: x.nextAccountIndex), + serviceAccounts: x.accumulateState.newServiceAccounts + ) } else if codeHash == nil { state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.OOB.rawValue) } else { @@ -445,8 +448,8 @@ public class Transfer: HostCall { let destAcc: ServiceAccountDetails? = if try await x.serviceAccounts.get(serviceAccount: dest) != nil { try await x.serviceAccounts.get(serviceAccount: dest) - } else if x.accumulateState.serviceAccounts[dest] != nil { - x.accumulateState.serviceAccounts[dest]?.toDetails() + } else if x.accumulateState.newServiceAccounts[dest] != nil { + x.accumulateState.newServiceAccounts[dest]?.toDetails() } else { nil } @@ -474,64 +477,107 @@ public class Transfer: HostCall { } } -/// Quit (remove) a service account -public class Quit: HostCall { +/// Eject (remove) a service account +public class Eject: HostCall { public static var identifier: UInt8 { 12 } public var x: AccumlateResultContext + public let timeslot: TimeslotIndex - public init(x: inout AccumlateResultContext) { + public init(x: inout AccumlateResultContext, timeslot: TimeslotIndex) { self.x = x + self.timeslot = timeslot } public func _callImpl(config: ProtocolConfigRef, state: VMState) async throws { - let (dest, startAddr): (UInt64, UInt64) = state.readRegister(Registers.Index(raw: 7), Registers.Index(raw: 8)) - let acc = try await x.serviceAccounts.get(serviceAccount: x.serviceIndex).expect("service account not found") - let amount = acc.balance - acc.thresholdBalance(config: config) + Balance(config.value.serviceMinBalance) - let gasLimit = Gas(state.getGas()) - - let isValidDest = dest == x.serviceIndex || dest == UInt64.max - let memoData = try? state.readMemory(address: startAddr, length: config.value.transferMemoSize) - let memo = memoData != nil ? try JamDecoder.decode(Data128.self, from: memoData!) : nil - let destination = ServiceIndex(truncatingIfNeeded: dest) - - let destAcc: ServiceAccountDetails? = if try await x.serviceAccounts.get(serviceAccount: destination) != nil { - try await x.serviceAccounts.get(serviceAccount: destination) - } else if x.accumulateState.serviceAccounts[destination] != nil { - x.accumulateState.serviceAccounts[destination]?.toDetails() + let (reg7, reg8): (UInt64, UInt64) = state.readRegister(Registers.Index(raw: 7), Registers.Index(raw: 8)) + let ejectIndex = ServiceIndex(truncatingIfNeeded: reg7) + let preimageHash = try? state.readMemory(address: reg8, length: 32) + let ejectAccount: ServiceAccountDetails? = if ejectIndex == x.serviceIndex { + nil + } else if try await x.serviceAccounts.get(serviceAccount: ejectIndex) != nil { + try await x.serviceAccounts.get(serviceAccount: ejectIndex) + } else if x.accumulateState.newServiceAccounts[ejectIndex] != nil { + x.accumulateState.newServiceAccounts[ejectIndex]?.toDetails() } else { nil } + let minHoldPeriod = TimeslotIndex(config.value.preimagePurgePeriod) - if isValidDest { - state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.OK.rawValue) - x.serviceAccounts.set(serviceAccount: x.serviceIndex, account: nil) - throw VMInvocationsError.forceHalt - } else if memo == nil { + if preimageHash == nil { state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.OOB.rawValue) - } else if destAcc == nil { + } else if ejectAccount == nil || ejectAccount?.codeHash.data != Data(x.serviceIndex.encode(method: .fixedWidth(32))) { state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.WHO.rawValue) - } else if gasLimit < destAcc!.minOnTransferGas { - state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.LOW.rawValue) - } else { + } + + let preimageInfo = try await x.serviceAccounts.get( + serviceAccount: ejectIndex, + preimageHash: Data32(preimageHash!)!, + length: max(81, UInt32(ejectAccount!.totalByteLength)) - 81 + ) + + if ejectAccount!.itemsCount != 2 || preimageInfo == nil { + state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.HUH.rawValue) + } else if preimageInfo!.count == 2, preimageInfo![1] < timeslot - minHoldPeriod { + var destAccount = try await x.serviceAccounts.get(serviceAccount: x.serviceIndex) + destAccount?.balance += ejectAccount!.balance + x.serviceAccounts.set(serviceAccount: ejectIndex, account: nil) + x.serviceAccounts.set(serviceAccount: x.serviceIndex, account: destAccount) state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.OK.rawValue) - // TODO: need to remove all storage and preimages? - x.serviceAccounts.set(serviceAccount: x.serviceIndex, account: nil) - x.transfers.append(DeferredTransfers( - sender: x.serviceIndex, - destination: destination, - amount: amount, - memo: memo!, - gasLimit: gasLimit - )) - throw VMInvocationsError.forceHalt + } else { + state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.HUH.rawValue) + } + } +} + +/// Query preimage info +public class Query: HostCall { + public static var identifier: UInt8 { 13 } + + public var x: AccumlateResultContext + + public init(x: inout AccumlateResultContext) { + self.x = x + } + + public func _callImpl(config _: ProtocolConfigRef, state: VMState) async throws { + let (startAddr, length): (UInt32, UInt32) = state.readRegister(Registers.Index(raw: 7), Registers.Index(raw: 8)) + let preimageHash = try? state.readMemory(address: startAddr, length: 32) + if preimageHash == nil { + state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.OOB.rawValue) + return + } + + let preimageInfo = try await x.serviceAccounts.get( + serviceAccount: x.serviceIndex, + preimageHash: Data32(preimageHash!)!, + length: length + ) + if preimageInfo == nil { + state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.NONE.rawValue) + state.writeRegister(Registers.Index(raw: 8), 0) + return + } + + if preimageInfo!.isEmpty { + state.writeRegister(Registers.Index(raw: 7), 0) + state.writeRegister(Registers.Index(raw: 8), 0) + } else if preimageInfo!.count == 1 { + state.writeRegister(Registers.Index(raw: 7), 1 + (1 << 32) * preimageInfo![0]) + state.writeRegister(Registers.Index(raw: 8), 0) + } else if preimageInfo!.count == 2 { + state.writeRegister(Registers.Index(raw: 7), 2 + (1 << 32) * preimageInfo![0]) + state.writeRegister(Registers.Index(raw: 8), preimageInfo![1]) + } else if preimageInfo!.count == 3 { + state.writeRegister(Registers.Index(raw: 7), 3 + (1 << 32) * preimageInfo![0]) + state.writeRegister(Registers.Index(raw: 8), preimageInfo![1] + (1 << 32) * preimageInfo![2]) } } } /// Solicit data to be made available in-core (through preimage lookups) public class Solicit: HostCall { - public static var identifier: UInt8 { 13 } + public static var identifier: UInt8 { 14 } public var x: AccumlateResultContext public let timeslot: TimeslotIndex @@ -571,7 +617,7 @@ public class Solicit: HostCall { /// Forget data made available in-core (through preimage lookups) public class Forget: HostCall { - public static var identifier: UInt8 { 14 } + public static var identifier: UInt8 { 15 } public var x: AccumlateResultContext public let timeslot: TimeslotIndex @@ -613,9 +659,31 @@ public class Forget: HostCall { } } +/// Yield accumulation hash +public class Yield: HostCall { + public static var identifier: UInt8 { 16 } + + public var x: AccumlateResultContext + + public init(x: inout AccumlateResultContext) { + self.x = x + } + + public func _callImpl(config _: ProtocolConfigRef, state: VMState) async throws { + let startAddr: UInt32 = state.readRegister(Registers.Index(raw: 7)) + let hash = try? state.readMemory(address: startAddr, length: 32) + if hash == nil { + state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.OOB.rawValue) + } else { + state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.OK.rawValue) + x.yield = Data32(hash!)! + } + } +} + /// Historical lookup public class HistoricalLookup: HostCall { - public static var identifier: UInt8 { 15 } + public static var identifier: UInt8 { 17 } public let context: RefineContext.ContextType public let service: ServiceIndex @@ -672,7 +740,7 @@ public class HistoricalLookup: HostCall { /// Import a segment to memory public class Import: HostCall { - public static var identifier: UInt8 { 16 } + public static var identifier: UInt8 { 18 } public let context: RefineContext.ContextType public let importSegments: [Data] @@ -709,7 +777,7 @@ public class Import: HostCall { /// Export a segment from memory public class Export: HostCall { - public static var identifier: UInt8 { 17 } + public static var identifier: UInt8 { 19 } public var context: RefineContext.ContextType public let exportSegmentOffset: UInt64 @@ -748,7 +816,7 @@ public class Export: HostCall { /// Create an inner PVM public class Machine: HostCall { - public static var identifier: UInt8 { 18 } + public static var identifier: UInt8 { 20 } public var context: RefineContext.ContextType @@ -777,7 +845,7 @@ public class Machine: HostCall { /// Peek (read inner memory into outer memory) public class Peek: HostCall { - public static var identifier: UInt8 { 19 } + public static var identifier: UInt8 { 21 } public let context: RefineContext.ContextType @@ -811,7 +879,7 @@ public class Peek: HostCall { /// Poke (write outer memory into inner memory) public class Poke: HostCall { - public static var identifier: UInt8 { 20 } + public static var identifier: UInt8 { 22 } public var context: RefineContext.ContextType @@ -845,7 +913,7 @@ public class Poke: HostCall { /// Make some pages zero and writable in the inner PVM public class Zero: HostCall { - public static var identifier: UInt8 { 21 } + public static var identifier: UInt8 { 23 } public var context: RefineContext.ContextType @@ -872,7 +940,7 @@ public class Zero: HostCall { /// Make some pages zero and inaccessible in the inner PVM public class VoidFn: HostCall { - public static var identifier: UInt8 { 22 } + public static var identifier: UInt8 { 24 } public var context: RefineContext.ContextType @@ -901,7 +969,7 @@ public class VoidFn: HostCall { /// Invoke an inner PVM public class Invoke: HostCall { - public static var identifier: UInt8 { 23 } + public static var identifier: UInt8 { 25 } public var context: RefineContext.ContextType @@ -960,7 +1028,7 @@ public class Invoke: HostCall { /// Expunge an inner PVM public class Expunge: HostCall { - public static var identifier: UInt8 { 24 } + public static var identifier: UInt8 { 26 } public var context: RefineContext.ContextType @@ -1050,8 +1118,8 @@ public class Log: HostCall { public func _callImpl(config _: ProtocolConfigRef, state: VMState) async throws { let regs: [UInt32] = state.readRegisters(in: 7 ..< 12) let level = regs[0] - let target = regs[1] == 0 && regs[2] == 0 ? nil : try state.readMemory(address: regs[1], length: Int(regs[2])) - let message = try state.readMemory(address: regs[3], length: Int(regs[4])) + let target = regs[1] == 0 && regs[2] == 0 ? nil : try? state.readMemory(address: regs[1], length: Int(regs[2])) + let message = try? state.readMemory(address: regs[3], length: Int(regs[4])) let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd HH-mm-ss" @@ -1061,7 +1129,7 @@ public class Log: HostCall { time: time, level: Level(rawValue: level) ?? .debug, target: target, - message: message, + message: message ?? Data(), core: core, service: service ) diff --git a/Blockchain/Sources/Blockchain/VMInvocations/InvocationContexts/AccumulateContext.swift b/Blockchain/Sources/Blockchain/VMInvocations/InvocationContexts/AccumulateContext.swift index af17db85..a1bf0b07 100644 --- a/Blockchain/Sources/Blockchain/VMInvocations/InvocationContexts/AccumulateContext.swift +++ b/Blockchain/Sources/Blockchain/VMInvocations/InvocationContexts/AccumulateContext.swift @@ -49,18 +49,19 @@ public class AccumulateContext: InvocationContext { case New.identifier: return await New(x: &context.x).call(config: config, state: state) case Upgrade.identifier: - return await Upgrade(x: &context.x) - .call(config: config, state: state) + return await Upgrade(x: &context.x).call(config: config, state: state) case Transfer.identifier: - return await Transfer(x: &context.x) - .call(config: config, state: state) - case Quit.identifier: - return await Quit(x: &context.x) - .call(config: config, state: state) + return await Transfer(x: &context.x).call(config: config, state: state) + case Eject.identifier: + return await Eject(x: &context.x, timeslot: timeslot).call(config: config, state: state) + case Query.identifier: + return await Query(x: &context.x).call(config: config, state: state) case Solicit.identifier: return await Solicit(x: &context.x, timeslot: timeslot).call(config: config, state: state) case Forget.identifier: return await Forget(x: &context.x, timeslot: timeslot).call(config: config, state: state) + case Yield.identifier: + return await Yield(x: &context.x).call(config: config, state: state) case Log.identifier: return await Log(service: context.x.serviceIndex).call(config: config, state: state) default: diff --git a/Blockchain/Sources/Blockchain/VMInvocations/Invocations/AccumulateInvocation.swift b/Blockchain/Sources/Blockchain/VMInvocations/Invocations/AccumulateInvocation.swift index 0b35c913..00921c63 100644 --- a/Blockchain/Sources/Blockchain/VMInvocations/Invocations/AccumulateInvocation.swift +++ b/Blockchain/Sources/Blockchain/VMInvocations/Invocations/AccumulateInvocation.swift @@ -54,14 +54,14 @@ extension AccumulateFunction { exitReason: ExitReason, output: Data?, context: AccumulateContext.ContextType, gas: Gas ) throws -> (state: AccumulateState, transfers: [DeferredTransfers], result: Data32?, gas: Gas) { switch exitReason { - case .halt: + case .panic, .outOfGas: + (context.y.accumulateState, context.y.transfers, context.y.yield, gas) + default: if let output, let o = Data32(output) { (context.x.accumulateState, context.x.transfers, o, gas) } else { - (context.x.accumulateState, context.x.transfers, nil, gas) + (context.x.accumulateState, context.x.transfers, context.x.yield, gas) } - default: - (context.y.accumulateState, context.y.transfers, nil, gas) } } } diff --git a/PolkaVM/Sources/PolkaVM/InstructionTable.swift b/PolkaVM/Sources/PolkaVM/InstructionTable.swift index 13d1b4c3..70d9db36 100644 --- a/PolkaVM/Sources/PolkaVM/InstructionTable.swift +++ b/PolkaVM/Sources/PolkaVM/InstructionTable.swift @@ -40,6 +40,14 @@ public class InstructionTable { Instructions.BranchGtSImm.self, Instructions.MoveReg.self, Instructions.Sbrk.self, + Instructions.CountSetBits64.self, + Instructions.CountSetBits32.self, + Instructions.LeadingZeroBits64.self, + Instructions.LeadingZeroBits32.self, + Instructions.SignExtend8.self, + Instructions.SignExtend16.self, + Instructions.ZeroExtend16.self, + Instructions.ReverseBytes.self, Instructions.StoreIndU8.self, Instructions.StoreIndU16.self, Instructions.StoreIndU32.self, @@ -75,6 +83,10 @@ public class InstructionTable { Instructions.SharRImmAlt64.self, Instructions.CmovIzImm.self, Instructions.CmovNzImm.self, + Instructions.RotR64Imm.self, + Instructions.RotR64ImmAlt.self, + Instructions.RotR32Imm.self, + Instructions.RotR32ImmAlt.self, Instructions.BranchEq.self, Instructions.BranchNe.self, Instructions.BranchLtU.self, @@ -112,6 +124,17 @@ public class InstructionTable { Instructions.SharR64.self, Instructions.CmovIz.self, Instructions.CmovNz.self, + Instructions.RotL64.self, + Instructions.RotL32.self, + Instructions.RotR64.self, + Instructions.RotR32.self, + Instructions.AndInv.self, + Instructions.OrInv.self, + Instructions.Xnor.self, + Instructions.Max.self, + Instructions.MaxU.self, + Instructions.Min.self, + Instructions.MinU.self, ] var table: [Instruction.Type?] = Array(repeating: nil, count: 256) for i in 0 ..< insts.count { diff --git a/PolkaVM/Sources/PolkaVM/Instructions/Instructions.swift b/PolkaVM/Sources/PolkaVM/Instructions/Instructions.swift index 163f0222..54175c83 100644 --- a/PolkaVM/Sources/PolkaVM/Instructions/Instructions.swift +++ b/PolkaVM/Sources/PolkaVM/Instructions/Instructions.swift @@ -660,10 +660,180 @@ public enum Instructions { } } + public struct CountSetBits64: Instruction { + public static var opcode: UInt8 { 102 } + + public let ra: Registers.Index + public let dest: Registers.Index + + public init(data: Data) throws { + (ra, dest) = try Instructions.deocdeRegisters(data) + } + + public func _executeImpl(context: ExecutionContext) throws -> ExecOutcome { + let regVal: UInt64 = context.state.readRegister(ra) + context.state.writeRegister(dest, regVal.nonzeroBitCount) + return .continued + } + } + + public struct CountSetBits32: Instruction { + public static var opcode: UInt8 { 103 } + + public let ra: Registers.Index + public let dest: Registers.Index + + public init(data: Data) throws { + (ra, dest) = try Instructions.deocdeRegisters(data) + } + + public func _executeImpl(context: ExecutionContext) throws -> ExecOutcome { + let regVal: UInt32 = context.state.readRegister(ra) + context.state.writeRegister(dest, regVal.nonzeroBitCount) + return .continued + } + } + + public struct LeadingZeroBits64: Instruction { + public static var opcode: UInt8 { 104 } + + public let ra: Registers.Index + public let dest: Registers.Index + + public init(data: Data) throws { + (ra, dest) = try Instructions.deocdeRegisters(data) + } + + public func _executeImpl(context: ExecutionContext) throws -> ExecOutcome { + let regVal: UInt64 = context.state.readRegister(ra) + context.state.writeRegister(dest, regVal.leadingZeroBitCount) + return .continued + } + } + + public struct LeadingZeroBits32: Instruction { + public static var opcode: UInt8 { 105 } + + public let ra: Registers.Index + public let dest: Registers.Index + + public init(data: Data) throws { + (ra, dest) = try Instructions.deocdeRegisters(data) + } + + public func _executeImpl(context: ExecutionContext) throws -> ExecOutcome { + let regVal: UInt32 = context.state.readRegister(ra) + context.state.writeRegister(dest, regVal.leadingZeroBitCount) + return .continued + } + } + + public struct TrailingZeroBits64: Instruction { + public static var opcode: UInt8 { 106 } + + public let ra: Registers.Index + public let dest: Registers.Index + + public init(data: Data) throws { + (ra, dest) = try Instructions.deocdeRegisters(data) + } + + public func _executeImpl(context: ExecutionContext) throws -> ExecOutcome { + let regVal: UInt64 = context.state.readRegister(ra) + context.state.writeRegister(dest, regVal.trailingZeroBitCount) + return .continued + } + } + + public struct TrailingZeroBits32: Instruction { + public static var opcode: UInt8 { 107 } + + public let ra: Registers.Index + public let dest: Registers.Index + + public init(data: Data) throws { + (ra, dest) = try Instructions.deocdeRegisters(data) + } + + public func _executeImpl(context: ExecutionContext) throws -> ExecOutcome { + let regVal: UInt32 = context.state.readRegister(ra) + context.state.writeRegister(dest, regVal.trailingZeroBitCount) + return .continued + } + } + + public struct SignExtend8: Instruction { + public static var opcode: UInt8 { 108 } + + public let ra: Registers.Index + public let dest: Registers.Index + + public init(data: Data) throws { + (ra, dest) = try Instructions.deocdeRegisters(data) + } + + public func _executeImpl(context: ExecutionContext) throws -> ExecOutcome { + let regVal: UInt8 = context.state.readRegister(ra) + context.state.writeRegister(dest, UInt64(bitPattern: Int64(Int8(bitPattern: regVal)))) + return .continued + } + } + + public struct SignExtend16: Instruction { + public static var opcode: UInt8 { 109 } + + public let ra: Registers.Index + public let dest: Registers.Index + + public init(data: Data) throws { + (ra, dest) = try Instructions.deocdeRegisters(data) + } + + public func _executeImpl(context: ExecutionContext) throws -> ExecOutcome { + let regVal: UInt16 = context.state.readRegister(ra) + context.state.writeRegister(dest, UInt64(bitPattern: Int64(Int16(bitPattern: regVal)))) + return .continued + } + } + + public struct ZeroExtend16: Instruction { + public static var opcode: UInt8 { 110 } + + public let ra: Registers.Index + public let dest: Registers.Index + + public init(data: Data) throws { + (ra, dest) = try Instructions.deocdeRegisters(data) + } + + public func _executeImpl(context: ExecutionContext) throws -> ExecOutcome { + let regVal: UInt16 = context.state.readRegister(ra) + context.state.writeRegister(dest, regVal) + return .continued + } + } + + public struct ReverseBytes: Instruction { + public static var opcode: UInt8 { 111 } + + public let ra: Registers.Index + public let dest: Registers.Index + + public init(data: Data) throws { + (ra, dest) = try Instructions.deocdeRegisters(data) + } + + public func _executeImpl(context: ExecutionContext) throws -> ExecOutcome { + let regVal: UInt64 = context.state.readRegister(ra) + context.state.writeRegister(dest, regVal.byteSwapped) + return .continued + } + } + // MARK: Instructions with Arguments of Two Registers & One Immediate (5.10) public struct StoreIndU8: Instruction { - public static var opcode: UInt8 { 110 } + public static var opcode: UInt8 { 120 } public let src: Registers.Index public let dest: Registers.Index @@ -682,7 +852,7 @@ public enum Instructions { } public struct StoreIndU16: Instruction { - public static var opcode: UInt8 { 111 } + public static var opcode: UInt8 { 121 } public let src: Registers.Index public let dest: Registers.Index @@ -701,7 +871,7 @@ public enum Instructions { } public struct StoreIndU32: Instruction { - public static var opcode: UInt8 { 112 } + public static var opcode: UInt8 { 122 } public let src: Registers.Index public let dest: Registers.Index @@ -720,7 +890,7 @@ public enum Instructions { } public struct StoreIndU64: Instruction { - public static var opcode: UInt8 { 113 } + public static var opcode: UInt8 { 123 } public let src: Registers.Index public let dest: Registers.Index @@ -739,7 +909,7 @@ public enum Instructions { } public struct LoadIndU8: Instruction { - public static var opcode: UInt8 { 114 } + public static var opcode: UInt8 { 124 } public let src: Registers.Index public let dest: Registers.Index @@ -758,7 +928,7 @@ public enum Instructions { } public struct LoadIndI8: Instruction { - public static var opcode: UInt8 { 115 } + public static var opcode: UInt8 { 125 } public let src: Registers.Index public let dest: Registers.Index @@ -777,7 +947,7 @@ public enum Instructions { } public struct LoadIndU16: Instruction { - public static var opcode: UInt8 { 116 } + public static var opcode: UInt8 { 126 } public let src: Registers.Index public let dest: Registers.Index @@ -797,7 +967,7 @@ public enum Instructions { } public struct LoadIndI16: Instruction { - public static var opcode: UInt8 { 117 } + public static var opcode: UInt8 { 127 } public let src: Registers.Index public let dest: Registers.Index @@ -817,7 +987,7 @@ public enum Instructions { } public struct LoadIndU32: Instruction { - public static var opcode: UInt8 { 118 } + public static var opcode: UInt8 { 128 } public let src: Registers.Index public let dest: Registers.Index @@ -837,7 +1007,7 @@ public enum Instructions { } public struct LoadIndI32: Instruction { - public static var opcode: UInt8 { 119 } + public static var opcode: UInt8 { 129 } public let src: Registers.Index public let dest: Registers.Index @@ -857,7 +1027,7 @@ public enum Instructions { } public struct LoadIndU64: Instruction { - public static var opcode: UInt8 { 120 } + public static var opcode: UInt8 { 130 } public let src: Registers.Index public let dest: Registers.Index @@ -877,7 +1047,7 @@ public enum Instructions { } public struct AddImm32: Instruction { - public static var opcode: UInt8 { 121 } + public static var opcode: UInt8 { 131 } public let ra: Registers.Index public let rb: Registers.Index @@ -896,7 +1066,7 @@ public enum Instructions { } public struct AndImm: Instruction { - public static var opcode: UInt8 { 122 } + public static var opcode: UInt8 { 132 } public let ra: Registers.Index public let rb: Registers.Index @@ -915,7 +1085,7 @@ public enum Instructions { } public struct XorImm: Instruction { - public static var opcode: UInt8 { 123 } + public static var opcode: UInt8 { 133 } public let ra: Registers.Index public let rb: Registers.Index @@ -934,7 +1104,7 @@ public enum Instructions { } public struct OrImm: Instruction { - public static var opcode: UInt8 { 124 } + public static var opcode: UInt8 { 134 } public let ra: Registers.Index public let rb: Registers.Index @@ -953,7 +1123,7 @@ public enum Instructions { } public struct MulImm32: Instruction { - public static var opcode: UInt8 { 125 } + public static var opcode: UInt8 { 135 } public let ra: Registers.Index public let rb: Registers.Index @@ -972,7 +1142,7 @@ public enum Instructions { } public struct SetLtUImm: Instruction { - public static var opcode: UInt8 { 126 } + public static var opcode: UInt8 { 136 } public let ra: Registers.Index public let rb: Registers.Index @@ -991,7 +1161,7 @@ public enum Instructions { } public struct SetLtSImm: Instruction { - public static var opcode: UInt8 { 127 } + public static var opcode: UInt8 { 137 } public let ra: Registers.Index public let rb: Registers.Index @@ -1010,7 +1180,7 @@ public enum Instructions { } public struct ShloLImm32: Instruction { - public static var opcode: UInt8 { 128 } + public static var opcode: UInt8 { 138 } public let ra: Registers.Index public let rb: Registers.Index @@ -1030,7 +1200,7 @@ public enum Instructions { } public struct ShloRImm32: Instruction { - public static var opcode: UInt8 { 129 } + public static var opcode: UInt8 { 139 } public let ra: Registers.Index public let rb: Registers.Index @@ -1050,7 +1220,7 @@ public enum Instructions { } public struct SharRImm32: Instruction { - public static var opcode: UInt8 { 130 } + public static var opcode: UInt8 { 140 } public let ra: Registers.Index public let rb: Registers.Index @@ -1070,7 +1240,7 @@ public enum Instructions { } public struct NegAddImm32: Instruction { - public static var opcode: UInt8 { 131 } + public static var opcode: UInt8 { 141 } public let ra: Registers.Index public let rb: Registers.Index @@ -1089,7 +1259,7 @@ public enum Instructions { } public struct SetGtUImm: Instruction { - public static var opcode: UInt8 { 132 } + public static var opcode: UInt8 { 142 } public let ra: Registers.Index public let rb: Registers.Index @@ -1108,7 +1278,7 @@ public enum Instructions { } public struct SetGtSImm: Instruction { - public static var opcode: UInt8 { 133 } + public static var opcode: UInt8 { 143 } public let ra: Registers.Index public let rb: Registers.Index @@ -1127,7 +1297,7 @@ public enum Instructions { } public struct ShloLImmAlt32: Instruction { - public static var opcode: UInt8 { 134 } + public static var opcode: UInt8 { 144 } public let ra: Registers.Index public let rb: Registers.Index @@ -1147,7 +1317,7 @@ public enum Instructions { } public struct ShloRImmAlt32: Instruction { - public static var opcode: UInt8 { 135 } + public static var opcode: UInt8 { 145 } public let ra: Registers.Index public let rb: Registers.Index @@ -1167,7 +1337,7 @@ public enum Instructions { } public struct SharRImmAlt32: Instruction { - public static var opcode: UInt8 { 136 } + public static var opcode: UInt8 { 146 } public let ra: Registers.Index public let rb: Registers.Index @@ -1187,7 +1357,7 @@ public enum Instructions { } public struct CmovIzImm: Instruction { - public static var opcode: UInt8 { 137 } + public static var opcode: UInt8 { 147 } public let ra: Registers.Index public let rb: Registers.Index @@ -1208,7 +1378,7 @@ public enum Instructions { } public struct CmovNzImm: Instruction { - public static var opcode: UInt8 { 86 } + public static var opcode: UInt8 { 148 } public let ra: Registers.Index public let rb: Registers.Index @@ -1227,7 +1397,7 @@ public enum Instructions { } public struct AddImm64: Instruction { - public static var opcode: UInt8 { 139 } + public static var opcode: UInt8 { 149 } public let ra: Registers.Index public let rb: Registers.Index @@ -1246,7 +1416,7 @@ public enum Instructions { } public struct MulImm64: Instruction { - public static var opcode: UInt8 { 140 } + public static var opcode: UInt8 { 150 } public let ra: Registers.Index public let rb: Registers.Index @@ -1265,7 +1435,7 @@ public enum Instructions { } public struct ShloLImm64: Instruction { - public static var opcode: UInt8 { 141 } + public static var opcode: UInt8 { 151 } public let ra: Registers.Index public let rb: Registers.Index @@ -1285,7 +1455,7 @@ public enum Instructions { } public struct ShloRImm64: Instruction { - public static var opcode: UInt8 { 142 } + public static var opcode: UInt8 { 152 } public let ra: Registers.Index public let rb: Registers.Index @@ -1305,7 +1475,7 @@ public enum Instructions { } public struct SharRImm64: Instruction { - public static var opcode: UInt8 { 143 } + public static var opcode: UInt8 { 153 } public let ra: Registers.Index public let rb: Registers.Index @@ -1325,7 +1495,7 @@ public enum Instructions { } public struct NegAddImm64: Instruction { - public static var opcode: UInt8 { 144 } + public static var opcode: UInt8 { 154 } public let ra: Registers.Index public let rb: Registers.Index @@ -1344,7 +1514,7 @@ public enum Instructions { } public struct ShloLImmAlt64: Instruction { - public static var opcode: UInt8 { 145 } + public static var opcode: UInt8 { 155 } public let ra: Registers.Index public let rb: Registers.Index @@ -1364,7 +1534,7 @@ public enum Instructions { } public struct ShloRImmAlt64: Instruction { - public static var opcode: UInt8 { 146 } + public static var opcode: UInt8 { 156 } public let ra: Registers.Index public let rb: Registers.Index @@ -1384,7 +1554,7 @@ public enum Instructions { } public struct SharRImmAlt64: Instruction { - public static var opcode: UInt8 { 147 } + public static var opcode: UInt8 { 157 } public let ra: Registers.Index public let rb: Registers.Index @@ -1403,10 +1573,86 @@ public enum Instructions { } } + public struct RotR64Imm: Instruction { + public static var opcode: UInt8 { 158 } + + public let ra: Registers.Index + public let rb: Registers.Index + public let value: UInt64 + + public init(data: Data) throws { + (ra, rb) = try Instructions.deocdeRegisters(data) + value = Instructions.decodeImmediate((try? data.at(relative: 1...)) ?? Data()) + } + + public func _executeImpl(context: ExecutionContext) -> ExecOutcome { + let rbVal: UInt64 = context.state.readRegister(rb) + context.state.writeRegister(ra, rbVal.rotated(right: value)) + return .continued + } + } + + public struct RotR64ImmAlt: Instruction { + public static var opcode: UInt8 { 159 } + + public let ra: Registers.Index + public let rb: Registers.Index + public let value: UInt64 + + public init(data: Data) throws { + (ra, rb) = try Instructions.deocdeRegisters(data) + value = Instructions.decodeImmediate((try? data.at(relative: 1...)) ?? Data()) + } + + public func _executeImpl(context: ExecutionContext) -> ExecOutcome { + let rbVal: UInt64 = context.state.readRegister(rb) + context.state.writeRegister(ra, value.rotated(right: rbVal)) + return .continued + } + } + + public struct RotR32Imm: Instruction { + public static var opcode: UInt8 { 160 } + + public let ra: Registers.Index + public let rb: Registers.Index + public let value: UInt32 + + public init(data: Data) throws { + (ra, rb) = try Instructions.deocdeRegisters(data) + value = Instructions.decodeImmediate((try? data.at(relative: 1...)) ?? Data()) + } + + public func _executeImpl(context: ExecutionContext) -> ExecOutcome { + let rbVal: UInt32 = context.state.readRegister(rb) + context.state.writeRegister(ra, Int32(bitPattern: rbVal.rotated(right: value))) + return .continued + } + } + + public struct RotR32ImmAlt: Instruction { + public static var opcode: UInt8 { 161 } + + public let ra: Registers.Index + public let rb: Registers.Index + public let value: UInt32 + + public init(data: Data) throws { + (ra, rb) = try Instructions.deocdeRegisters(data) + value = Instructions.decodeImmediate((try? data.at(relative: 1...)) ?? Data()) + } + + public func _executeImpl(context: ExecutionContext) -> ExecOutcome { + let rbVal: UInt32 = context.state.readRegister(rb) + context.state.writeRegister(ra, Int32(bitPattern: value.rotated(right: rbVal))) + return .continued + } + } + // MARK: Instructions with Arguments of Two Registers & One Offset (5.11) public struct BranchEq: BranchInstructionBase2 { - public static var opcode: UInt8 { 150 } + public static var opcode: UInt8 { 170 } typealias Compare = CompareEq var r1: Registers.Index @@ -1416,7 +1662,7 @@ public enum Instructions { } public struct BranchNe: BranchInstructionBase2 { - public static var opcode: UInt8 { 151 } + public static var opcode: UInt8 { 171 } typealias Compare = CompareNe var r1: Registers.Index @@ -1426,7 +1672,7 @@ public enum Instructions { } public struct BranchLtU: BranchInstructionBase2 { - public static var opcode: UInt8 { 152 } + public static var opcode: UInt8 { 172 } typealias Compare = CompareLtU var r1: Registers.Index @@ -1436,7 +1682,7 @@ public enum Instructions { } public struct BranchLtS: BranchInstructionBase2 { - public static var opcode: UInt8 { 153 } + public static var opcode: UInt8 { 173 } typealias Compare = CompareLtS var r1: Registers.Index @@ -1446,7 +1692,7 @@ public enum Instructions { } public struct BranchGeU: BranchInstructionBase2 { - public static var opcode: UInt8 { 154 } + public static var opcode: UInt8 { 174 } typealias Compare = CompareGeU var r1: Registers.Index @@ -1456,7 +1702,7 @@ public enum Instructions { } public struct BranchGeS: BranchInstructionBase2 { - public static var opcode: UInt8 { 155 } + public static var opcode: UInt8 { 175 } typealias Compare = CompareGeS var r1: Registers.Index @@ -1468,7 +1714,7 @@ public enum Instructions { // MARK: Instruction with Arguments of Two Registers and Two Immediates (5.12) public struct LoadImmJumpInd: Instruction { - public static var opcode: UInt8 { 160 } + public static var opcode: UInt8 { 180 } public let ra: Registers.Index public let rb: Registers.Index @@ -1494,7 +1740,7 @@ public enum Instructions { // MARK: Instructions with Arguments of Three Registers (5.13) public struct Add32: Instruction { - public static var opcode: UInt8 { 170 } + public static var opcode: UInt8 { 190 } public let ra: Registers.Index public let rb: Registers.Index @@ -1512,7 +1758,7 @@ public enum Instructions { } public struct Sub32: Instruction { - public static var opcode: UInt8 { 171 } + public static var opcode: UInt8 { 191 } public let ra: Registers.Index public let rb: Registers.Index @@ -1530,7 +1776,7 @@ public enum Instructions { } public struct Mul32: Instruction { - public static var opcode: UInt8 { 172 } + public static var opcode: UInt8 { 192 } public let ra: Registers.Index public let rb: Registers.Index @@ -1548,7 +1794,7 @@ public enum Instructions { } public struct DivU32: Instruction { - public static var opcode: UInt8 { 173 } + public static var opcode: UInt8 { 193 } public let ra: Registers.Index public let rb: Registers.Index @@ -1570,7 +1816,7 @@ public enum Instructions { } public struct DivS32: Instruction { - public static var opcode: UInt8 { 174 } + public static var opcode: UInt8 { 194 } public let ra: Registers.Index public let rb: Registers.Index @@ -1596,7 +1842,7 @@ public enum Instructions { } public struct RemU32: Instruction { - public static var opcode: UInt8 { 175 } + public static var opcode: UInt8 { 195 } public let ra: Registers.Index public let rb: Registers.Index @@ -1618,7 +1864,7 @@ public enum Instructions { } public struct RemS32: Instruction { - public static var opcode: UInt8 { 176 } + public static var opcode: UInt8 { 196 } public let ra: Registers.Index public let rb: Registers.Index @@ -1644,7 +1890,7 @@ public enum Instructions { } public struct ShloL32: Instruction { - public static var opcode: UInt8 { 177 } + public static var opcode: UInt8 { 197 } public let ra: Registers.Index public let rb: Registers.Index @@ -1663,7 +1909,7 @@ public enum Instructions { } public struct ShloR32: Instruction { - public static var opcode: UInt8 { 178 } + public static var opcode: UInt8 { 198 } public let ra: Registers.Index public let rb: Registers.Index @@ -1682,7 +1928,7 @@ public enum Instructions { } public struct SharR32: Instruction { - public static var opcode: UInt8 { 179 } + public static var opcode: UInt8 { 199 } public let ra: Registers.Index public let rb: Registers.Index @@ -1701,7 +1947,7 @@ public enum Instructions { } public struct Add64: Instruction { - public static var opcode: UInt8 { 180 } + public static var opcode: UInt8 { 200 } public let ra: Registers.Index public let rb: Registers.Index @@ -1719,7 +1965,7 @@ public enum Instructions { } public struct Sub64: Instruction { - public static var opcode: UInt8 { 181 } + public static var opcode: UInt8 { 201 } public let ra: Registers.Index public let rb: Registers.Index @@ -1737,7 +1983,7 @@ public enum Instructions { } public struct Mul64: Instruction { - public static var opcode: UInt8 { 182 } + public static var opcode: UInt8 { 202 } public let ra: Registers.Index public let rb: Registers.Index @@ -1755,7 +2001,7 @@ public enum Instructions { } public struct DivU64: Instruction { - public static var opcode: UInt8 { 183 } + public static var opcode: UInt8 { 203 } public let ra: Registers.Index public let rb: Registers.Index @@ -1777,7 +2023,7 @@ public enum Instructions { } public struct DivS64: Instruction { - public static var opcode: UInt8 { 184 } + public static var opcode: UInt8 { 204 } public let ra: Registers.Index public let rb: Registers.Index @@ -1803,7 +2049,7 @@ public enum Instructions { } public struct RemU64: Instruction { - public static var opcode: UInt8 { 185 } + public static var opcode: UInt8 { 205 } public let ra: Registers.Index public let rb: Registers.Index @@ -1825,7 +2071,7 @@ public enum Instructions { } public struct RemS64: Instruction { - public static var opcode: UInt8 { 186 } + public static var opcode: UInt8 { 206 } public let ra: Registers.Index public let rb: Registers.Index @@ -1851,7 +2097,7 @@ public enum Instructions { } public struct ShloL64: Instruction { - public static var opcode: UInt8 { 187 } + public static var opcode: UInt8 { 207 } public let ra: Registers.Index public let rb: Registers.Index @@ -1870,7 +2116,7 @@ public enum Instructions { } public struct ShloR64: Instruction { - public static var opcode: UInt8 { 188 } + public static var opcode: UInt8 { 208 } public let ra: Registers.Index public let rb: Registers.Index @@ -1889,7 +2135,7 @@ public enum Instructions { } public struct SharR64: Instruction { - public static var opcode: UInt8 { 189 } + public static var opcode: UInt8 { 209 } public let ra: Registers.Index public let rb: Registers.Index @@ -1908,7 +2154,7 @@ public enum Instructions { } public struct And: Instruction { - public static var opcode: UInt8 { 190 } + public static var opcode: UInt8 { 210 } public let ra: Registers.Index public let rb: Registers.Index @@ -1926,7 +2172,7 @@ public enum Instructions { } public struct Xor: Instruction { - public static var opcode: UInt8 { 191 } + public static var opcode: UInt8 { 211 } public let ra: Registers.Index public let rb: Registers.Index @@ -1944,7 +2190,7 @@ public enum Instructions { } public struct Or: Instruction { - public static var opcode: UInt8 { 192 } + public static var opcode: UInt8 { 212 } public let ra: Registers.Index public let rb: Registers.Index @@ -1962,7 +2208,7 @@ public enum Instructions { } public struct MulUpperSS: Instruction { - public static var opcode: UInt8 { 193 } + public static var opcode: UInt8 { 213 } public let ra: Registers.Index public let rb: Registers.Index @@ -1983,7 +2229,7 @@ public enum Instructions { } public struct MulUpperUU: Instruction { - public static var opcode: UInt8 { 194 } + public static var opcode: UInt8 { 214 } public let ra: Registers.Index public let rb: Registers.Index @@ -2001,7 +2247,7 @@ public enum Instructions { } public struct MulUpperSU: Instruction { - public static var opcode: UInt8 { 195 } + public static var opcode: UInt8 { 215 } public let ra: Registers.Index public let rb: Registers.Index @@ -2022,7 +2268,7 @@ public enum Instructions { } public struct SetLtU: Instruction { - public static var opcode: UInt8 { 196 } + public static var opcode: UInt8 { 216 } public let ra: Registers.Index public let rb: Registers.Index @@ -2040,7 +2286,7 @@ public enum Instructions { } public struct SetLtS: Instruction { - public static var opcode: UInt8 { 197 } + public static var opcode: UInt8 { 217 } public let ra: Registers.Index public let rb: Registers.Index @@ -2058,7 +2304,7 @@ public enum Instructions { } public struct CmovIz: Instruction { - public static var opcode: UInt8 { 198 } + public static var opcode: UInt8 { 218 } public let ra: Registers.Index public let rb: Registers.Index @@ -2078,7 +2324,7 @@ public enum Instructions { } public struct CmovNz: Instruction { - public static var opcode: UInt8 { 199 } + public static var opcode: UInt8 { 219 } public let ra: Registers.Index public let rb: Registers.Index @@ -2096,4 +2342,202 @@ public enum Instructions { return .continued } } + + public struct RotL64: Instruction { + public static var opcode: UInt8 { 220 } + + public let ra: Registers.Index + public let rb: Registers.Index + public let rd: Registers.Index + + public init(data: Data) throws { + (ra, rb, rd) = try Instructions.deocdeRegisters(data) + } + + public func _executeImpl(context: ExecutionContext) -> ExecOutcome { + let (raVal, rbVal): (UInt64, UInt64) = context.state.readRegister(ra, rb) + context.state.writeRegister(rd, raVal.rotated(left: rbVal)) + return .continued + } + } + + public struct RotL32: Instruction { + public static var opcode: UInt8 { 221 } + + public let ra: Registers.Index + public let rb: Registers.Index + public let rd: Registers.Index + + public init(data: Data) throws { + (ra, rb, rd) = try Instructions.deocdeRegisters(data) + } + + public func _executeImpl(context: ExecutionContext) -> ExecOutcome { + let (raVal, rbVal): (UInt32, UInt32) = context.state.readRegister(ra, rb) + context.state.writeRegister(rd, Int32(bitPattern: raVal.rotated(left: rbVal))) + return .continued + } + } + + public struct RotR64: Instruction { + public static var opcode: UInt8 { 222 } + + public let ra: Registers.Index + public let rb: Registers.Index + public let rd: Registers.Index + + public init(data: Data) throws { + (ra, rb, rd) = try Instructions.deocdeRegisters(data) + } + + public func _executeImpl(context: ExecutionContext) -> ExecOutcome { + let (raVal, rbVal): (UInt64, UInt64) = context.state.readRegister(ra, rb) + context.state.writeRegister(rd, raVal.rotated(right: rbVal)) + return .continued + } + } + + public struct RotR32: Instruction { + public static var opcode: UInt8 { 223 } + + public let ra: Registers.Index + public let rb: Registers.Index + public let rd: Registers.Index + + public init(data: Data) throws { + (ra, rb, rd) = try Instructions.deocdeRegisters(data) + } + + public func _executeImpl(context: ExecutionContext) -> ExecOutcome { + let (raVal, rbVal): (UInt32, UInt32) = context.state.readRegister(ra, rb) + context.state.writeRegister(rd, Int32(bitPattern: raVal.rotated(right: rbVal))) + return .continued + } + } + + public struct AndInv: Instruction { + public static var opcode: UInt8 { 224 } + + public let ra: Registers.Index + public let rb: Registers.Index + public let rd: Registers.Index + + public init(data: Data) throws { + (ra, rb, rd) = try Instructions.deocdeRegisters(data) + } + + public func _executeImpl(context: ExecutionContext) -> ExecOutcome { + let (raVal, rbVal): (UInt64, UInt64) = context.state.readRegister(ra, rb) + context.state.writeRegister(rd, raVal & ~rbVal) + return .continued + } + } + + public struct OrInv: Instruction { + public static var opcode: UInt8 { 225 } + + public let ra: Registers.Index + public let rb: Registers.Index + public let rd: Registers.Index + + public init(data: Data) throws { + (ra, rb, rd) = try Instructions.deocdeRegisters(data) + } + + public func _executeImpl(context: ExecutionContext) -> ExecOutcome { + let (raVal, rbVal): (UInt64, UInt64) = context.state.readRegister(ra, rb) + context.state.writeRegister(rd, raVal | ~rbVal) + return .continued + } + } + + public struct Xnor: Instruction { + public static var opcode: UInt8 { 226 } + + public let ra: Registers.Index + public let rb: Registers.Index + public let rd: Registers.Index + + public init(data: Data) throws { + (ra, rb, rd) = try Instructions.deocdeRegisters(data) + } + + public func _executeImpl(context: ExecutionContext) -> ExecOutcome { + let (raVal, rbVal): (UInt64, UInt64) = context.state.readRegister(ra, rb) + context.state.writeRegister(rd, ~(raVal ^ rbVal)) + return .continued + } + } + + public struct Max: Instruction { + public static var opcode: UInt8 { 227 } + + public let ra: Registers.Index + public let rb: Registers.Index + public let rd: Registers.Index + + public init(data: Data) throws { + (ra, rb, rd) = try Instructions.deocdeRegisters(data) + } + + public func _executeImpl(context: ExecutionContext) -> ExecOutcome { + let (raVal, rbVal): (UInt64, UInt64) = context.state.readRegister(ra, rb) + context.state.writeRegister(rd, max(Int64(bitPattern: raVal), Int64(bitPattern: rbVal))) + return .continued + } + } + + public struct MaxU: Instruction { + public static var opcode: UInt8 { 228 } + + public let ra: Registers.Index + public let rb: Registers.Index + public let rd: Registers.Index + + public init(data: Data) throws { + (ra, rb, rd) = try Instructions.deocdeRegisters(data) + } + + public func _executeImpl(context: ExecutionContext) -> ExecOutcome { + let (raVal, rbVal): (UInt64, UInt64) = context.state.readRegister(ra, rb) + context.state.writeRegister(rd, max(raVal, rbVal)) + return .continued + } + } + + public struct Min: Instruction { + public static var opcode: UInt8 { 229 } + + public let ra: Registers.Index + public let rb: Registers.Index + public let rd: Registers.Index + + public init(data: Data) throws { + (ra, rb, rd) = try Instructions.deocdeRegisters(data) + } + + public func _executeImpl(context: ExecutionContext) -> ExecOutcome { + let (raVal, rbVal): (UInt64, UInt64) = context.state.readRegister(ra, rb) + context.state.writeRegister(rd, min(Int64(bitPattern: raVal), Int64(bitPattern: rbVal))) + return .continued + } + } + + public struct MinU: Instruction { + public static var opcode: UInt8 { 230 } + + public let ra: Registers.Index + public let rb: Registers.Index + public let rd: Registers.Index + + public init(data: Data) throws { + (ra, rb, rd) = try Instructions.deocdeRegisters(data) + } + + public func _executeImpl(context: ExecutionContext) -> ExecOutcome { + let (raVal, rbVal): (UInt64, UInt64) = context.state.readRegister(ra, rb) + context.state.writeRegister(rd, min(raVal, rbVal)) + return .continued + } + } } diff --git a/PolkaVM/Sources/PolkaVM/invokePVM.swift b/PolkaVM/Sources/PolkaVM/invokePVM.swift index 55201ea7..a57d8326 100644 --- a/PolkaVM/Sources/PolkaVM/invokePVM.swift +++ b/PolkaVM/Sources/PolkaVM/invokePVM.swift @@ -22,7 +22,7 @@ public func invokePVM( case .outOfGas: return (.outOfGas, Gas(0), nil) case .halt: - let (addr, len): (UInt32, UInt32) = state.readRegister(Registers.Index(raw: 10), Registers.Index(raw: 11)) + let (addr, len): (UInt32, UInt32) = state.readRegister(Registers.Index(raw: 7), Registers.Index(raw: 8)) let output = try? state.readMemory(address: addr, length: Int(len)) return (.halt, Gas(state.getGas()), output ?? Data()) default: From 65a0f4677407bc5cd4542a331013bfc83dec7bd3 Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Tue, 21 Jan 2025 15:23:05 +1300 Subject: [PATCH 2/2] fix typo (#267) --- RPC/Sources/RPC/Handlers/ChainHandlers.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/RPC/Sources/RPC/Handlers/ChainHandlers.swift b/RPC/Sources/RPC/Handlers/ChainHandlers.swift index 64282939..5733f8ec 100644 --- a/RPC/Sources/RPC/Handlers/ChainHandlers.swift +++ b/RPC/Sources/RPC/Handlers/ChainHandlers.swift @@ -7,7 +7,7 @@ public enum ChainHandlers { public static let handlers: [any RPCHandler.Type] = [ GetBlock.self, GetBlockHash.self, - GetFinalziedHead.self, + GetFinalizedHead.self, GetHeader.self, ] @@ -15,7 +15,7 @@ public enum ChainHandlers { [ GetBlock(source: source), GetBlockHash(source: source), - GetFinalziedHead(source: source), + GetFinalizedHead(source: source), GetHeader(source: source), ] } @@ -64,11 +64,11 @@ public enum ChainHandlers { } } - public struct GetFinalziedHead: RPCHandler { + public struct GetFinalizedHead: RPCHandler { public typealias Request = VoidRequest public typealias Response = Data32? - public static var method: String { "chain_getFinalziedHead" } + public static var method: String { "chain_getFinalizedHead" } public static var summary: String? { "Get hash of the last finalized block in the canon chain." } private let source: ChainDataSource