Compare commits
No commits in common. "c48c4261da67c34a0b3a508550cce99289aa0a75" and "75d765c9055987a6a8f37d4c503ecd3a5b73a9da" have entirely different histories.
c48c4261da
...
75d765c905
|
|
@ -8,8 +8,5 @@ as0.o: as0.asm
|
|||
test: test.bin
|
||||
./test.bin
|
||||
|
||||
print_table: as0.o
|
||||
ld -m elf_x86_64 -e _entry_print_table -o print_table as0.o
|
||||
|
||||
clean:
|
||||
rm -f as0.o test.bin
|
||||
|
|
|
|||
2884
stages/as0/as0.asm
2884
stages/as0/as0.asm
File diff suppressed because it is too large
Load diff
|
|
@ -1,409 +1,215 @@
|
|||
unsafe extern "C" {
|
||||
// unsafe fn parse_gpr(src: *mut Source, prefix: u8) -> (u64, u64);
|
||||
// unsafe fn parse_reg(src: *mut Source) -> (u64, u64);
|
||||
|
||||
unsafe fn try_parse_reg(_: *const u8) -> (usize, Register);
|
||||
unsafe fn try_parse_mem(_: *const u8, _: *mut Operand) -> (usize, *const Operand);
|
||||
#[link_name = "try_parse_operand"]
|
||||
unsafe fn try_parse_operand_impl(_: *const u8, _: *mut Operand) -> (usize, *const Operand);
|
||||
|
||||
#[link_name = "try_parse_inst"]
|
||||
unsafe fn try_parse_inst_impl(_: *const u8, _: *mut Instruction)
|
||||
-> (usize, *const Instruction);
|
||||
|
||||
#[link_name = "encode_inst"]
|
||||
unsafe fn encode_inst_impl(_: *mut Instruction) -> usize;
|
||||
|
||||
unsafe fn fasthash(_: *const u8, _: usize) -> u32;
|
||||
|
||||
#[link_name = "buf"]
|
||||
static mut BUF: [u8; 0x100];
|
||||
unsafe fn parse_gpr(src: *mut Source, prefix: u8) -> (u64, u64);
|
||||
unsafe fn parse_reg(src: *mut Source) -> (u64, u64);
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
struct Register {
|
||||
size: u32,
|
||||
num: u32,
|
||||
struct Source<'a> {
|
||||
iter: core::iter::Peekable<core::slice::Iter<'a, u8>>,
|
||||
}
|
||||
|
||||
#[repr(u32)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
enum OperandKind {
|
||||
None = 0,
|
||||
Reg = 1,
|
||||
Mem = 2,
|
||||
Imm = 4,
|
||||
MemLabel = 2 | 8,
|
||||
ImmLabel = 4 | 8,
|
||||
}
|
||||
|
||||
#[repr(C, align(8))]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
struct Operand {
|
||||
kind: OperandKind,
|
||||
size: u32,
|
||||
reg: Register,
|
||||
index: Register,
|
||||
scale: u32,
|
||||
disp: i32,
|
||||
}
|
||||
|
||||
impl Operand {
|
||||
fn parse(bytes: &[u8]) -> Option<(usize, Self)> {
|
||||
let mut op = core::mem::MaybeUninit::<Operand>::uninit();
|
||||
let (n, ptr) = unsafe { try_parse_operand_impl(bytes.as_ptr(), op.as_mut_ptr()) };
|
||||
if n == 0 {
|
||||
None
|
||||
} else {
|
||||
Some((n, unsafe { op.assume_init() }))
|
||||
}
|
||||
}
|
||||
|
||||
fn label(name: &[u8]) -> Self {
|
||||
let mut this = Self {
|
||||
kind: OperandKind::ImmLabel,
|
||||
size: 2,
|
||||
reg: Register::invalid(),
|
||||
index: Register::invalid(),
|
||||
scale: 0,
|
||||
disp: 0,
|
||||
};
|
||||
unsafe {
|
||||
let hash = fasthash(name.as_ptr(), name.len());
|
||||
(&raw mut this).byte_add(8).cast::<u32>().write(hash as u32);
|
||||
}
|
||||
this
|
||||
}
|
||||
|
||||
fn imm(value: i64) -> Self {
|
||||
let size = if value.abs() == 0 {
|
||||
value as u32
|
||||
} else {
|
||||
unsafe {
|
||||
(value.abs() as u64)
|
||||
.checked_ilog2()
|
||||
.unwrap_unchecked()
|
||||
.saturating_sub(1)
|
||||
.checked_ilog2()
|
||||
.unwrap_or(0)
|
||||
+ 1
|
||||
}
|
||||
};
|
||||
|
||||
let mut this = Self {
|
||||
kind: OperandKind::Imm,
|
||||
size,
|
||||
reg: Register::invalid(),
|
||||
index: Register::invalid(),
|
||||
scale: 0,
|
||||
disp: 0,
|
||||
};
|
||||
unsafe {
|
||||
(&raw mut this).byte_add(8).cast::<i64>().write(value);
|
||||
}
|
||||
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
struct Instruction {
|
||||
mnemonic_offset: i32,
|
||||
num_operands: u32,
|
||||
operands: [Operand; 2],
|
||||
}
|
||||
|
||||
impl Instruction {
|
||||
fn parse(bytes: &[u8]) -> Option<(usize, Self)> {
|
||||
let mut inst = core::mem::MaybeUninit::<Instruction>::uninit();
|
||||
let (n, ptr) = unsafe { try_parse_inst_impl(bytes.as_ptr(), inst.as_mut_ptr()) };
|
||||
if n == 0 {
|
||||
None
|
||||
} else {
|
||||
Some((n, unsafe { inst.assume_init() }))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Register {
|
||||
fn new(num: u32, size: u32) -> Self {
|
||||
impl<'a> From<&'a [u8]> for Source<'a> {
|
||||
fn from(value: &'a [u8]) -> Self {
|
||||
Self {
|
||||
num,
|
||||
size: size.ilog2(),
|
||||
iter: value.iter().peekable(),
|
||||
}
|
||||
}
|
||||
fn invalid() -> Self {
|
||||
Self { num: !0, size: !0 }
|
||||
}
|
||||
|
||||
fn rbp() -> Self {
|
||||
Self { num: 5, size: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use core::mem::MaybeUninit;
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn peekc(src: *mut Source) -> u8 {
|
||||
unsafe { (*src).iter.peek().cloned().unwrap_or(&0).clone() }
|
||||
}
|
||||
|
||||
fn write_to_buf(b: &[u8]) {
|
||||
assert!(b.len() <= 0x100, "Buffer overflow");
|
||||
unsafe {
|
||||
core::ptr::copy_nonoverlapping(b.as_ptr(), (&raw mut BUF).cast(), b.len());
|
||||
}
|
||||
}
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn getc(src: *mut Source) -> u8 {
|
||||
unsafe { (*src).iter.next().unwrap_or(&0).clone() }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_inst() {
|
||||
let res = Instruction::parse(b"mov byte [rax], 4\0");
|
||||
// assert_eq!(
|
||||
// res,
|
||||
// Some((
|
||||
// 12,
|
||||
// Instruction {
|
||||
// mnemonic_offset: 0,
|
||||
// num_operands: 2,
|
||||
// operands: [
|
||||
// Operand {
|
||||
// kind: OperandKind::Reg,
|
||||
// size: 3,
|
||||
// reg: Register::new(0, 8),
|
||||
// index: Register::invalid(),
|
||||
// scale: 0,
|
||||
// disp: 0,
|
||||
// },
|
||||
// Operand {
|
||||
// kind: OperandKind::Reg,
|
||||
// size: 3,
|
||||
// reg: Register::new(3, 8),
|
||||
// index: Register::invalid(),
|
||||
// scale: 0,
|
||||
// disp: 0,
|
||||
// },
|
||||
// ],
|
||||
// }
|
||||
// ))
|
||||
// );
|
||||
|
||||
unsafe {
|
||||
let mut inst = res.unwrap().1;
|
||||
encode_inst_impl((&raw mut inst).cast());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_mem() {
|
||||
let mut op = MaybeUninit::<Operand>::uninit();
|
||||
let (n, _) =
|
||||
unsafe { try_parse_mem(b"qword [rax + rbx * 2 + 0x10]\0".as_ptr(), op.as_mut_ptr()) };
|
||||
assert_eq!(
|
||||
(n, unsafe { op.assume_init_ref() }),
|
||||
(
|
||||
28,
|
||||
&Operand {
|
||||
kind: OperandKind::Mem,
|
||||
size: 3,
|
||||
reg: Register::new(0, 8),
|
||||
index: Register::new(3, 8),
|
||||
scale: 2,
|
||||
disp: 0x10,
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
let (n, _) =
|
||||
unsafe { try_parse_mem(b"byte [r12 + r13 * 4 - 0x20]\0".as_ptr(), op.as_mut_ptr()) };
|
||||
assert_eq!(
|
||||
(n, unsafe { op.assume_init_ref() }),
|
||||
(
|
||||
27,
|
||||
&Operand {
|
||||
kind: OperandKind::Mem,
|
||||
size: 0,
|
||||
reg: Register::new(12, 8),
|
||||
index: Register::new(13, 8),
|
||||
scale: 4,
|
||||
disp: -0x20,
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
let (n, _) = unsafe { try_parse_mem(b"word [r8 * 8 + 5]\0".as_ptr(), op.as_mut_ptr()) };
|
||||
assert_eq!(
|
||||
(n, unsafe { op.assume_init_ref() }),
|
||||
(
|
||||
17,
|
||||
&Operand {
|
||||
kind: OperandKind::Mem,
|
||||
size: 1,
|
||||
reg: Register::rbp(),
|
||||
index: Register::new(8, 8),
|
||||
scale: 8,
|
||||
disp: 5,
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_operand() {
|
||||
#[test]
|
||||
fn test_parse_reg() {
|
||||
let cases = [
|
||||
(
|
||||
&b"rax\0"[..],
|
||||
Operand {
|
||||
kind: OperandKind::Reg,
|
||||
size: 3,
|
||||
reg: Register::new(0, 8),
|
||||
index: Register::invalid(),
|
||||
scale: 0,
|
||||
disp: 0,
|
||||
},
|
||||
),
|
||||
(
|
||||
&b"qword [rax + rbx * 2 + 0x10]\0"[..],
|
||||
Operand {
|
||||
kind: OperandKind::Mem,
|
||||
size: 3,
|
||||
reg: Register::new(0, 8),
|
||||
index: Register::new(3, 8),
|
||||
scale: 2,
|
||||
disp: 0x10,
|
||||
},
|
||||
),
|
||||
(
|
||||
&b"byte [r12 + r13 * 4 - 0x20]\0"[..],
|
||||
Operand {
|
||||
kind: OperandKind::Mem,
|
||||
size: 0,
|
||||
reg: Register::new(12, 8),
|
||||
index: Register::new(13, 8),
|
||||
scale: 4,
|
||||
disp: -0x20,
|
||||
},
|
||||
),
|
||||
(
|
||||
&b"word [r8 * 8 + 5]\0"[..],
|
||||
Operand {
|
||||
kind: OperandKind::Mem,
|
||||
size: 1,
|
||||
reg: Register::rbp(),
|
||||
index: Register::new(8, 8),
|
||||
scale: 8,
|
||||
disp: 5,
|
||||
},
|
||||
),
|
||||
(&b"0x12345678\0"[..], Operand::imm(0x12345678)),
|
||||
(&b"-0x12345678\0"[..], Operand::imm(-0x12345678)),
|
||||
(&b"0\0"[..], Operand::imm(0)),
|
||||
(&b"-1\0"[..], Operand::imm(-1)),
|
||||
(&b"1\0"[..], Operand::imm(1)),
|
||||
(&b"255\0"[..], Operand::imm(255)),
|
||||
(&b"-255\0"[..], Operand::imm(-255)),
|
||||
(&b"'wazzaah\0"[..], Operand::label(b"wazzaah")),
|
||||
(
|
||||
&b"qword [rsp + 'hii]"[..],
|
||||
Operand {
|
||||
kind: OperandKind::MemLabel,
|
||||
size: 3,
|
||||
reg: Register::new(4, 8),
|
||||
index: Register::invalid(),
|
||||
scale: 0,
|
||||
disp: unsafe { fasthash(b"hii".as_ptr(), 3) as i32 },
|
||||
},
|
||||
),
|
||||
(&b"rax"[..], (0, 8)),
|
||||
(&b"rbx"[..], (1, 8)),
|
||||
(&b"rcx"[..], (2, 8)),
|
||||
(&b"rdx"[..], (3, 8)),
|
||||
(&b"rsp"[..], (4, 8)),
|
||||
(&b"rbp"[..], (5, 8)),
|
||||
(&b"rsi"[..], (6, 8)),
|
||||
(&b"rdi"[..], (7, 8)),
|
||||
(&b"eax"[..], (0, 4)),
|
||||
(&b"ebx"[..], (1, 4)),
|
||||
(&b"ecx"[..], (2, 4)),
|
||||
(&b"edx"[..], (3, 4)),
|
||||
(&b"esp"[..], (4, 4)),
|
||||
(&b"ebp"[..], (5, 4)),
|
||||
(&b"esi"[..], (6, 4)),
|
||||
(&b"edi"[..], (7, 4)),
|
||||
(&b"r8"[..], (8, 8)),
|
||||
(&b"r9"[..], (9, 8)),
|
||||
(&b"r10"[..], (10, 8)),
|
||||
(&b"r11"[..], (11, 8)),
|
||||
(&b"r12"[..], (12, 8)),
|
||||
(&b"r13"[..], (13, 8)),
|
||||
(&b"r14"[..], (14, 8)),
|
||||
(&b"r15"[..], (15, 8)),
|
||||
(&b"r8d"[..], (8, 4)),
|
||||
(&b"r9d"[..], (9, 4)),
|
||||
(&b"r10d"[..], (10, 4)),
|
||||
(&b"r11d"[..], (11, 4)),
|
||||
(&b"r12d"[..], (12, 4)),
|
||||
(&b"r13d"[..], (13, 4)),
|
||||
(&b"r14d"[..], (14, 4)),
|
||||
(&b"r15d"[..], (15, 4)),
|
||||
(&b"r8w"[..], (8, 2)),
|
||||
(&b"r9w"[..], (9, 2)),
|
||||
(&b"r10w"[..], (10, 2)),
|
||||
(&b"r11w"[..], (11, 2)),
|
||||
(&b"r12w"[..], (12, 2)),
|
||||
(&b"r13w"[..], (13, 2)),
|
||||
(&b"r14w"[..], (14, 2)),
|
||||
(&b"r15w"[..], (15, 2)),
|
||||
(&b"r8b"[..], (8, 1)),
|
||||
(&b"r9b"[..], (9, 1)),
|
||||
(&b"r10b"[..], (10, 1)),
|
||||
(&b"r11b"[..], (11, 1)),
|
||||
(&b"r12b"[..], (12, 1)),
|
||||
(&b"r13b"[..], (13, 1)),
|
||||
(&b"r14b"[..], (14, 1)),
|
||||
(&b"r15b"[..], (15, 1)),
|
||||
(&b"ax"[..], (0, 2)),
|
||||
(&b"bx"[..], (1, 2)),
|
||||
(&b"cx"[..], (2, 2)),
|
||||
(&b"dx"[..], (3, 2)),
|
||||
(&b"sp"[..], (4, 2)),
|
||||
(&b"bp"[..], (5, 2)),
|
||||
(&b"si"[..], (6, 2)),
|
||||
(&b"di"[..], (7, 2)),
|
||||
(&b"al"[..], (0, 1)),
|
||||
(&b"bl"[..], (1, 1)),
|
||||
(&b"cl"[..], (2, 1)),
|
||||
(&b"dl"[..], (3, 1)),
|
||||
(&b"ah"[..], (0, 3)),
|
||||
(&b"bh"[..], (1, 3)),
|
||||
(&b"ch"[..], (2, 3)),
|
||||
(&b"dh"[..], (3, 3)),
|
||||
(&b"sil"[..], (6, 1)),
|
||||
(&b"dil"[..], (7, 1)),
|
||||
(&b"asd"[..], (0, 0)),
|
||||
];
|
||||
|
||||
for (text, expected) in cases {
|
||||
let (n, result) = Operand::parse(text).expect("Failed to parse operand");
|
||||
for (text, result) in cases {
|
||||
let mut src = Source::from(text);
|
||||
unsafe {
|
||||
assert_eq!(
|
||||
parse_reg(&mut src),
|
||||
result,
|
||||
expected,
|
||||
"Failed to parse '{}'",
|
||||
std::str::from_utf8(text).unwrap()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_reg() {
|
||||
#[test]
|
||||
fn test_parse_gpr() {
|
||||
let cases = [
|
||||
(&b"rax\0"[..], (0, 8)),
|
||||
(&b"rcx\0"[..], (1, 8)),
|
||||
(&b"rdx\0"[..], (2, 8)),
|
||||
(&b"rbx\0"[..], (3, 8)),
|
||||
(&b"rsp\0"[..], (4, 8)),
|
||||
(&b"rbp\0"[..], (5, 8)),
|
||||
(&b"rsi\0"[..], (6, 8)),
|
||||
(&b"rdi\0"[..], (7, 8)),
|
||||
(&b"r8\0"[..], (8, 8)),
|
||||
(&b"r9\0"[..], (9, 8)),
|
||||
(&b"r10\0"[..], (10, 8)),
|
||||
(&b"r11\0"[..], (11, 8)),
|
||||
(&b"r12\0"[..], (12, 8)),
|
||||
(&b"r13\0"[..], (13, 8)),
|
||||
(&b"r14\0"[..], (14, 8)),
|
||||
(&b"r15\0"[..], (15, 8)),
|
||||
(&b"rip\0"[..], (!0, 8)),
|
||||
(&b"eax\0"[..], (0, 4)),
|
||||
(&b"ecx\0"[..], (1, 4)),
|
||||
(&b"edx\0"[..], (2, 4)),
|
||||
(&b"ebx\0"[..], (3, 4)),
|
||||
(&b"esp\0"[..], (4, 4)),
|
||||
(&b"ebp\0"[..], (5, 4)),
|
||||
(&b"esi\0"[..], (6, 4)),
|
||||
(&b"edi\0"[..], (7, 4)),
|
||||
(&b"r8d\0"[..], (8, 4)),
|
||||
(&b"r9d\0"[..], (9, 4)),
|
||||
(&b"r10d\0"[..], (10, 4)),
|
||||
(&b"r11d\0"[..], (11, 4)),
|
||||
(&b"r12d\0"[..], (12, 4)),
|
||||
(&b"r13d\0"[..], (13, 4)),
|
||||
(&b"r14d\0"[..], (14, 4)),
|
||||
(&b"r15d\0"[..], (15, 4)),
|
||||
(&b"r8w\0"[..], (8, 2)),
|
||||
(&b"r9w\0"[..], (9, 2)),
|
||||
(&b"r10w\0"[..], (10, 2)),
|
||||
(&b"r11w\0"[..], (11, 2)),
|
||||
(&b"r12w\0"[..], (12, 2)),
|
||||
(&b"r13w\0"[..], (13, 2)),
|
||||
(&b"r14w\0"[..], (14, 2)),
|
||||
(&b"r15w\0"[..], (15, 2)),
|
||||
(&b"r8b\0"[..], (8, 1)),
|
||||
(&b"r9b\0"[..], (9, 1)),
|
||||
(&b"r10b\0"[..], (10, 1)),
|
||||
(&b"r11b\0"[..], (11, 1)),
|
||||
(&b"r12b\0"[..], (12, 1)),
|
||||
(&b"r13b\0"[..], (13, 1)),
|
||||
(&b"r14b\0"[..], (14, 1)),
|
||||
(&b"r15b\0"[..], (15, 1)),
|
||||
(&b"ax\0"[..], (0, 2)),
|
||||
(&b"cx\0"[..], (1, 2)),
|
||||
(&b"dx\0"[..], (2, 2)),
|
||||
(&b"bx\0"[..], (3, 2)),
|
||||
(&b"sp\0"[..], (4, 2)),
|
||||
(&b"bp\0"[..], (5, 2)),
|
||||
(&b"si\0"[..], (6, 2)),
|
||||
(&b"di\0"[..], (7, 2)),
|
||||
(&b"al\0"[..], (0, 1)),
|
||||
(&b"cl\0"[..], (1, 1)),
|
||||
(&b"dl\0"[..], (2, 1)),
|
||||
(&b"bl\0"[..], (3, 1)),
|
||||
(&b"spl\0"[..], (4, 1)),
|
||||
(&b"bpl\0"[..], (5, 1)),
|
||||
(&b"sil\0"[..], (6, 1)),
|
||||
(&b"dil\0"[..], (7, 1)),
|
||||
(&b"ax"[..], (0, 2)),
|
||||
(&b"bx"[..], (1, 2)),
|
||||
(&b"cx"[..], (2, 2)),
|
||||
(&b"dx"[..], (3, 2)),
|
||||
(&b"sp"[..], (4, 2)),
|
||||
(&b"bp"[..], (5, 2)),
|
||||
(&b"si"[..], (6, 2)),
|
||||
(&b"di"[..], (7, 2)),
|
||||
(&b"al"[..], (0, 1)),
|
||||
(&b"bl"[..], (1, 1)),
|
||||
(&b"cl"[..], (2, 1)),
|
||||
(&b"dl"[..], (3, 1)),
|
||||
(&b"ah"[..], (0, 3)),
|
||||
(&b"bh"[..], (1, 3)),
|
||||
(&b"ch"[..], (2, 3)),
|
||||
(&b"dh"[..], (3, 3)),
|
||||
(&b"sil"[..], (6, 1)),
|
||||
(&b"dil"[..], (7, 1)),
|
||||
(&b"asd"[..], (0, 0)),
|
||||
];
|
||||
|
||||
for (text, (reg, size)) in cases {
|
||||
let (n, result) = unsafe { try_parse_reg(text.as_ptr()) };
|
||||
for (text, result) in cases {
|
||||
let mut src = Source::from(text);
|
||||
unsafe {
|
||||
assert_eq!(
|
||||
(n, result),
|
||||
(text.len() - 1, Register::new(reg, size)),
|
||||
"Failed to parse '{}' n={n}",
|
||||
parse_gpr(&mut src, b'r'),
|
||||
result,
|
||||
"Failed to parse '{}'",
|
||||
std::str::from_utf8(text).unwrap()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum Register {
|
||||
A = 0,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
Src,
|
||||
Dst,
|
||||
Sp,
|
||||
Bp,
|
||||
R8,
|
||||
R9,
|
||||
R10,
|
||||
R11,
|
||||
R12,
|
||||
R13,
|
||||
R14,
|
||||
R15,
|
||||
}
|
||||
enum RegisterSize {
|
||||
Byte = 1,
|
||||
Word = 2,
|
||||
Dword = 4,
|
||||
Qword = 8,
|
||||
HighByte = 3,
|
||||
None = 0,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct PackedRegister(u8);
|
||||
impl From<PackedRegister> for Option<(Register, RegisterSize)> {
|
||||
fn from(value: PackedRegister) -> Self {
|
||||
let reg_bits = value.0 & 0x00F;
|
||||
let size_bits = (value.0 >> 4) & 0x0F;
|
||||
let size = match size_bits {
|
||||
1 => RegisterSize::Byte,
|
||||
2 => RegisterSize::Word,
|
||||
4 => RegisterSize::Dword,
|
||||
8 => RegisterSize::Qword,
|
||||
3 => RegisterSize::HighByte,
|
||||
0 => return None,
|
||||
_ => panic!("Invalid register size"),
|
||||
};
|
||||
|
||||
let reg = match reg_bits {
|
||||
0 => Register::A,
|
||||
1 => Register::B,
|
||||
2 => Register::C,
|
||||
3 => Register::D,
|
||||
4 => Register::Sp,
|
||||
5 => Register::Bp,
|
||||
6 => Register::Src,
|
||||
7 => Register::Dst,
|
||||
8 => Register::R8,
|
||||
9 => Register::R9,
|
||||
10 => Register::R10,
|
||||
11 => Register::R11,
|
||||
12 => Register::R12,
|
||||
13 => Register::R13,
|
||||
14 => Register::R14,
|
||||
15 => Register::R15,
|
||||
_ => panic!("Invalid register number"),
|
||||
};
|
||||
|
||||
Some((reg, size))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue