use crate::AsReg;
use alloc::string::String;
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Gpr<R: AsReg = u8>(pub(crate) R);
impl<R: AsReg> Gpr<R> {
pub fn new(reg: R) -> Self {
Self(reg)
}
pub fn enc(&self) -> u8 {
let enc = self.0.enc();
assert!(enc < 16, "invalid register: {enc}");
enc
}
pub fn to_string(&self, size: Size) -> String {
self.0.to_string(Some(size))
}
}
impl<R: AsReg> AsRef<R> for Gpr<R> {
fn as_ref(&self) -> &R {
&self.0
}
}
impl<R: AsReg> AsMut<R> for Gpr<R> {
fn as_mut(&mut self) -> &mut R {
&mut self.0
}
}
impl<R: AsReg> From<R> for Gpr<R> {
fn from(reg: R) -> Gpr<R> {
Gpr(reg)
}
}
#[derive(Copy, Clone, Debug)]
pub enum Size {
Byte,
Word,
Doubleword,
Quadword,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct NonRspGpr<R: AsReg>(R);
impl<R: AsReg> NonRspGpr<R> {
pub fn new(reg: R) -> Self {
Self(reg)
}
pub fn to_string(&self, size: Size) -> String {
self.0.to_string(Some(size))
}
pub fn enc(&self) -> u8 {
let enc = self.0.enc();
assert!(enc < 16, "invalid register: {enc}");
assert_ne!(enc, enc::RSP, "invalid register: %rsp");
enc
}
}
impl<R: AsReg> AsRef<R> for NonRspGpr<R> {
fn as_ref(&self) -> &R {
&self.0
}
}
impl<R: AsReg> AsMut<R> for NonRspGpr<R> {
fn as_mut(&mut self) -> &mut R {
&mut self.0
}
}
impl<R: AsReg> From<R> for NonRspGpr<R> {
fn from(reg: R) -> NonRspGpr<R> {
NonRspGpr(reg)
}
}
pub mod enc {
use super::Size;
pub const RAX: u8 = 0;
pub const RCX: u8 = 1;
pub const RDX: u8 = 2;
pub const RBX: u8 = 3;
pub const RSP: u8 = 4;
pub const RBP: u8 = 5;
pub const RSI: u8 = 6;
pub const RDI: u8 = 7;
pub const R8: u8 = 8;
pub const R9: u8 = 9;
pub const R10: u8 = 10;
pub const R11: u8 = 11;
pub const R12: u8 = 12;
pub const R13: u8 = 13;
pub const R14: u8 = 14;
pub const R15: u8 = 15;
pub fn to_string(enc: u8, size: Size) -> &'static str {
use Size::{Byte, Doubleword, Quadword, Word};
match enc {
RAX => match size {
Byte => "%al",
Word => "%ax",
Doubleword => "%eax",
Quadword => "%rax",
},
RBX => match size {
Byte => "%bl",
Word => "%bx",
Doubleword => "%ebx",
Quadword => "%rbx",
},
RCX => match size {
Byte => "%cl",
Word => "%cx",
Doubleword => "%ecx",
Quadword => "%rcx",
},
RDX => match size {
Byte => "%dl",
Word => "%dx",
Doubleword => "%edx",
Quadword => "%rdx",
},
RSI => match size {
Byte => "%sil",
Word => "%si",
Doubleword => "%esi",
Quadword => "%rsi",
},
RDI => match size {
Byte => "%dil",
Word => "%di",
Doubleword => "%edi",
Quadword => "%rdi",
},
RBP => match size {
Byte => "%bpl",
Word => "%bp",
Doubleword => "%ebp",
Quadword => "%rbp",
},
RSP => match size {
Byte => "%spl",
Word => "%sp",
Doubleword => "%esp",
Quadword => "%rsp",
},
R8 => match size {
Byte => "%r8b",
Word => "%r8w",
Doubleword => "%r8d",
Quadword => "%r8",
},
R9 => match size {
Byte => "%r9b",
Word => "%r9w",
Doubleword => "%r9d",
Quadword => "%r9",
},
R10 => match size {
Byte => "%r10b",
Word => "%r10w",
Doubleword => "%r10d",
Quadword => "%r10",
},
R11 => match size {
Byte => "%r11b",
Word => "%r11w",
Doubleword => "%r11d",
Quadword => "%r11",
},
R12 => match size {
Byte => "%r12b",
Word => "%r12w",
Doubleword => "%r12d",
Quadword => "%r12",
},
R13 => match size {
Byte => "%r13b",
Word => "%r13w",
Doubleword => "%r13d",
Quadword => "%r13",
},
R14 => match size {
Byte => "%r14b",
Word => "%r14w",
Doubleword => "%r14d",
Quadword => "%r14",
},
R15 => match size {
Byte => "%r15b",
Word => "%r15w",
Doubleword => "%r15d",
Quadword => "%r15",
},
_ => panic!("%invalid{enc}"),
}
}
}