use proc_macro2::Span;
use crate::common::JumpTarget;
use super::riscvdata::Opdata;
use std::fmt;
#[derive(Debug, Clone)]
pub enum Register {
Static(RegId),
Dynamic(RegFamily, syn::Expr)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum RegId {
X0 = 0x00, X1 = 0x01, X2 = 0x02, X3 = 0x03, X4 = 0x04, X5 = 0x05, X6 = 0x06, X7 = 0x07, X8 = 0x08, X9 = 0x09, X10= 0x0A, X11= 0x0B, X12= 0x0C, X13= 0x0D, X14= 0x0E, X15= 0x0F, X16= 0x10, X17= 0x11, X18= 0x12, X19= 0x13, X20= 0x14, X21= 0x15, X22= 0x16, X23= 0x17, X24= 0x18, X25= 0x19, X26= 0x1A, X27= 0x1B, X28= 0x1C, X29= 0x1D, X30= 0x1E, X31= 0x1F,
F0 = 0x20, F1 = 0x21, F2 = 0x22, F3 = 0x23,
F4 = 0x24, F5 = 0x25, F6 = 0x26, F7 = 0x27,
F8 = 0x28, F9 = 0x29, F10= 0x2A, F11= 0x2B,
F12= 0x2C, F13= 0x2D, F14= 0x2E, F15= 0x2F,
F16= 0x30, F17= 0x31, F18= 0x32, F19= 0x33,
F20= 0x34, F21= 0x35, F22= 0x36, F23= 0x37,
F24= 0x38, F25= 0x39, F26= 0x3A, F27= 0x3B,
F28= 0x3C, F29= 0x3D, F30= 0x3E, F31= 0x3F,
V0 = 0x40, V1 = 0x41, V2 = 0x42, V3 = 0x43,
V4 = 0x44, V5 = 0x45, V6 = 0x46, V7 = 0x47,
V8 = 0x48, V9 = 0x49, V10= 0x4A, V11= 0x4B,
V12= 0x4C, V13= 0x4D, V14= 0x4E, V15= 0x4F,
V16= 0x50, V17= 0x51, V18= 0x52, V19= 0x53,
V20= 0x54, V21= 0x55, V22= 0x56, V23= 0x57,
V24= 0x58, V25= 0x59, V26= 0x5A, V27= 0x5B,
V28= 0x5C, V29= 0x5D, V30= 0x5E, V31= 0x5F,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum RegFamily {
INTEGER = 0,
FP = 1,
VECTOR = 2,
}
impl RegId {
pub fn code(self) -> u8 {
self as u8 & 0x1F
}
pub fn family(self) -> RegFamily {
match self as u8 >> 5 {
0 => RegFamily::INTEGER,
1 => RegFamily::FP,
2 => RegFamily::VECTOR,
_ => unreachable!(),
}
}
}
impl fmt::Display for RegId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.family() {
RegFamily::INTEGER => write!(f, "x{}", self.code()),
RegFamily::FP => write!(f, "f{}", self.code()),
RegFamily::VECTOR => write!(f, "v{}", self.code()),
}
}
}
impl Register {
pub fn code(&self) -> Option<u8> {
match self {
Register::Static(code) => Some(code.code()),
Register::Dynamic(_, _) => None
}
}
pub fn family(&self) -> RegFamily {
match self {
Register::Static(code) => code.family(),
Register::Dynamic(family, _) => *family
}
}
pub fn is_dynamic(&self) -> bool {
match self {
Register::Static(_) => false,
Register::Dynamic(_, _) => true
}
}
pub fn as_id(&self) -> Option<RegId> {
match self {
Register::Static(id) => Some(*id),
Register::Dynamic(_, _) => None
}
}
}
#[derive(Debug)]
pub enum RegListCount {
Static(u8),
Dynamic(syn::Expr),
Single(Register),
Double(Register, Register)
}
#[derive(Debug)]
pub enum RawArg {
Immediate {
value: syn::Expr
},
JumpTarget {
jump: JumpTarget
},
Register {
span: Span,
reg: Register
},
Reference {
span: Span,
offset: Option<syn::Expr>,
base: Register,
},
LabelReference {
span: Span,
jump: JumpTarget,
base: Register
},
RegisterList {
span: Span,
first: Register, count: RegListCount
},
}
#[derive(Debug)]
pub struct ParsedInstruction {
pub name: String,
pub span: Span,
pub args: Vec<RawArg>
}
#[derive(Debug)]
pub enum RegListFlat {
Static(u8),
Dynamic(syn::Expr)
}
#[derive(Debug)]
pub enum FlatArg {
Immediate {
value: syn::Expr
},
JumpTarget {
jump: JumpTarget
},
Register {
span: Span,
reg: Register
},
RegisterList {
span: Span,
count: RegListFlat
},
Default
}
#[derive(Debug)]
pub struct MatchData {
pub data: &'static Opdata,
pub args: Vec<FlatArg>
}