///|
priv struct Instruction {
form : Int32 // 0: 0OP, 1: 1OP, 2: 2OP, 3: VAR, 4: EXT
opcode : Int32
args : Array[Int32]
}
///|
fn Machine::operand(self : Machine, kind : Int32) -> Int32 raise Fault {
match kind {
0 => self.fetch() * 256 + self.fetch()
1 => self.fetch()
2 => self.variable(self.fetch())
_ => raise Invalid("invalid operand type")
}
}
///|
fn Machine::decode(self : Machine) -> Instruction raise Fault {
let b = self.fetch()
let args : Array[Int32] = []
if b == 190 && self.version == 5 {
let opcode = self.fetch()
self.decode_types(self.fetch(), args)
{ form: 4, opcode, args, }
} else if b < 128 {
args.push(self.operand(if (b & 64) == 0 { 1 } else { 2 }))
args.push(self.operand(if (b & 32) == 0 { 1 } else { 2 }))
{ form: 2, opcode: b & 31, args, }
} else if b < 192 {
let kind = (b >> 4) & 3
if kind != 3 {
args.push(self.operand(kind))
}
{ form: if kind == 3 { 0 } else { 1 }, opcode: b & 15, args, }
} else {
let form = if (b & 32) == 0 { 2 } else { 3 }
let opcode = b & 31
let types = self.fetch()
let second = if form == 3 && (opcode == 12 || opcode == 26) {
self.fetch()
} else {
255
}
self.decode_types(types, args)
if second != 255 {
for shift in [6, 4, 2, 0] {
if ((types >> shift) & 3) == 3 {
raise Invalid("operand after omitted operand in second type byte")
}
}
self.decode_types(second, args)
}
{ form, opcode, args, }
}
}
///|
fn Machine::decode_types(
self : Machine,
types : Int32,
args : Array[Int32],
) -> Unit raise Fault {
let mut omitted = false
for shift in [6, 4, 2, 0] {
let kind = (types >> shift) & 3
if kind == 3 {
omitted = true
} else {
if omitted {
raise Invalid("operand after omitted operand")
}
args.push(self.operand(kind))
}
}
}