|
|
|
use crate::data::{
|
|
|
|
Wr, Rd,
|
|
|
|
literal::Label,
|
|
|
|
literal::RoutineName,
|
|
|
|
literal::DebugMsg,
|
|
|
|
};
|
|
|
|
use crate::instr::{Cond};
|
|
|
|
|
|
|
|
/// A higher level simple opration
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
|
|
pub enum HLOp {
|
|
|
|
/// Mark a jump target.
|
|
|
|
Label(Label),
|
|
|
|
/// Jump to a label
|
|
|
|
Jump(Label),
|
|
|
|
/// Jump to a label if a flag is set
|
|
|
|
JumpIf(Cond, Label),
|
|
|
|
/// Low level op
|
|
|
|
L(Op),
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A low level instruction
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
|
|
pub enum Op {
|
|
|
|
/// Do nothing
|
|
|
|
Nop,
|
|
|
|
/// Mark a far jump target (can be jumped to from another routine).
|
|
|
|
/// This label is preserved in optimized code.
|
|
|
|
FarLabel(Label),
|
|
|
|
/// Jump to a label that can be in another function
|
|
|
|
FarJump(Label),
|
|
|
|
/// Call a routine with arguments.
|
|
|
|
/// The arguments are passed as argX. Return values are stored in resX registers.
|
|
|
|
Call(RoutineName, Vec<Rd>),
|
|
|
|
/// Exit the current routine with return values
|
|
|
|
Ret(Vec<Rd>),
|
|
|
|
/// Mark a routine entry point (call target).
|
|
|
|
/// Kept in the low level instruction file for position-independent code
|
|
|
|
Routine(RoutineName),
|
|
|
|
/// Skip backward or forward
|
|
|
|
Skip(Rd),
|
|
|
|
/// Skip if a flag is set
|
|
|
|
SkipIf(Cond, Rd),
|
|
|
|
/// Deny jumps, skips and run across this address, producing a run-time fault with a message.
|
|
|
|
Barrier(Option<DebugMsg>),
|
|
|
|
/// Generate a run-time fault with a debugger message
|
|
|
|
Fault(Option<DebugMsg>),
|
|
|
|
|
|
|
|
Move { dst: Wr, src: Rd },
|
|
|
|
Test { a: Rd },
|
|
|
|
Compare { a: Rd, b: Rd },
|
|
|
|
StoreStatus { dst: Wr },
|
|
|
|
LoadStatus { src: Rd },
|
|
|
|
|
|
|
|
Add { dst: Wr, a: Rd, b: Rd },
|
|
|
|
Sub { dst: Wr, a: Rd, b: Rd },
|
|
|
|
Mul { dst: Wr, a: Rd, b: Rd },
|
|
|
|
Div { dst: Wr, rem: Wr, a: Rd, div: Rd },
|
|
|
|
// "Mod" is functionally equivalent to "Div" with the result discarded,
|
|
|
|
// but status flags are updated by the remainder
|
|
|
|
Mod { dst: Wr, a: Rd, div: Rd },
|
|
|
|
|
|
|
|
And { dst: Wr, a: Rd, b: Rd },
|
|
|
|
Or { dst: Wr, a: Rd, b: Rd },
|
|
|
|
Xor { dst: Wr, a: Rd, b: Rd },
|
|
|
|
Cpl { dst: Wr, a: Rd },
|
|
|
|
Rol { dst: Wr, a: Rd, n: Rd }, // Rotate (with wrap-around)
|
|
|
|
Ror { dst: Wr, a: Rd, n: Rd },
|
|
|
|
Lsl { dst: Wr, a: Rd, n: Rd }, // Shift
|
|
|
|
Lsr { dst: Wr, a: Rd, n: Rd },
|
|
|
|
Asr { dst: Wr, a: Rd, n: Rd },
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Make "into" work
|
|
|
|
impl From<Op> for HLOp {
|
|
|
|
fn from(op: Op) -> Self {
|
|
|
|
HLOp::L(op)
|
|
|
|
}
|
|
|
|
}
|