refactor asm more
This commit is contained in:
168
src/compiler/arch/riscv/asm.rs
Normal file
168
src/compiler/arch/riscv/asm.rs
Normal file
@@ -0,0 +1,168 @@
|
||||
use crate::{
|
||||
compiler::program::{Addr, Instr, SymTable},
|
||||
ir::Symbol,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum LinkerInstruction {
|
||||
Op {
|
||||
op: Funct3,
|
||||
funct: Funct7,
|
||||
dest: Reg,
|
||||
src1: Reg,
|
||||
src2: Reg,
|
||||
},
|
||||
OpImm {
|
||||
op: Funct3,
|
||||
dest: Reg,
|
||||
src: Reg,
|
||||
imm: i32,
|
||||
},
|
||||
OpImmF7 {
|
||||
op: Funct3,
|
||||
funct: Funct7,
|
||||
dest: Reg,
|
||||
src: Reg,
|
||||
imm: i32,
|
||||
},
|
||||
Store {
|
||||
width: Funct3,
|
||||
src: Reg,
|
||||
offset: i32,
|
||||
base: Reg,
|
||||
},
|
||||
Load {
|
||||
width: Funct3,
|
||||
dest: Reg,
|
||||
offset: i32,
|
||||
base: Reg,
|
||||
},
|
||||
Mv {
|
||||
dest: Reg,
|
||||
src: Reg,
|
||||
},
|
||||
La {
|
||||
dest: Reg,
|
||||
src: Symbol,
|
||||
},
|
||||
Jal {
|
||||
dest: Reg,
|
||||
offset: i32,
|
||||
},
|
||||
Call(Symbol),
|
||||
J(Symbol),
|
||||
Ret,
|
||||
Ecall,
|
||||
Li {
|
||||
dest: Reg,
|
||||
imm: i64,
|
||||
},
|
||||
}
|
||||
|
||||
pub fn addi(dest: Reg, src: Reg, imm: BitsI32<11, 0>) -> RawInstruction {
|
||||
opi(op32i::ADD, dest, src, imm)
|
||||
}
|
||||
|
||||
impl Instr for LinkerInstruction {
|
||||
fn push(
|
||||
&self,
|
||||
data: &mut Vec<u8>,
|
||||
sym_map: &SymTable,
|
||||
pos: Addr,
|
||||
missing: bool,
|
||||
) -> Option<Symbol> {
|
||||
let last = match self {
|
||||
Self::Op {
|
||||
op,
|
||||
funct,
|
||||
dest,
|
||||
src1,
|
||||
src2,
|
||||
} => opr(*op, *funct, *dest, *src1, *src2),
|
||||
Self::OpImm { op, dest, src, imm } => opi(*op, *dest, *src, BitsI32::new(*imm)),
|
||||
Self::OpImmF7 {
|
||||
op,
|
||||
funct,
|
||||
dest,
|
||||
src,
|
||||
imm,
|
||||
} => opif7(*op, *funct, *dest, *src, BitsI32::new(*imm)),
|
||||
Self::Store {
|
||||
width,
|
||||
src,
|
||||
offset,
|
||||
base,
|
||||
} => store(*width, *src, BitsI32::new(*offset), *base),
|
||||
Self::Load {
|
||||
width,
|
||||
dest,
|
||||
offset,
|
||||
base,
|
||||
} => load(*width, *dest, BitsI32::new(*offset), *base),
|
||||
Self::Mv { dest, src } => addi(*dest, *src, BitsI32::new(0)),
|
||||
Self::La { dest, src } => {
|
||||
if let Some(addr) = sym_map.get(*src) {
|
||||
let offset = addr.val() as i32 - pos.val() as i32;
|
||||
data.extend(auipc(*dest, BitsI32::new(0)).to_le_bytes());
|
||||
addi(*dest, *dest, BitsI32::new(offset))
|
||||
} else {
|
||||
data.extend_from_slice(&[0; 2 * 4]);
|
||||
return Some(*src);
|
||||
}
|
||||
}
|
||||
Self::Jal { dest, offset } => jal(*dest, BitsI32::new(*offset)),
|
||||
Self::J(sym) => {
|
||||
if let Some(addr) = sym_map.get(*sym) {
|
||||
let offset = addr.val() as i32 - pos.val() as i32;
|
||||
j(BitsI32::new(offset))
|
||||
} else {
|
||||
data.extend_from_slice(&[0; 4]);
|
||||
return Some(*sym);
|
||||
}
|
||||
}
|
||||
Self::Call(sym) => {
|
||||
if let Some(addr) = sym_map.get(*sym) {
|
||||
let offset = addr.val() as i32 - pos.val() as i32;
|
||||
jal(ra, BitsI32::new(offset))
|
||||
} else {
|
||||
data.extend_from_slice(&[0; 4]);
|
||||
return Some(*sym);
|
||||
}
|
||||
}
|
||||
Self::Ret => ret(),
|
||||
Self::Ecall => ecall(),
|
||||
Self::Li { dest, imm } => addi(*dest, zero, BitsI32::new(*imm as i32)),
|
||||
};
|
||||
data.extend(last.to_le_bytes());
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl LinkerInstruction {
|
||||
pub fn addi(dest: Reg, src: Reg, imm: i32) -> Self {
|
||||
Self::OpImm {
|
||||
op: op32i::ADD,
|
||||
dest,
|
||||
src,
|
||||
imm,
|
||||
}
|
||||
}
|
||||
pub fn sd(src: Reg, offset: i32, base: Reg) -> Self {
|
||||
Self::Store {
|
||||
width: width::D,
|
||||
src,
|
||||
offset,
|
||||
base,
|
||||
}
|
||||
}
|
||||
pub fn ld(dest: Reg, offset: i32, base: Reg) -> Self {
|
||||
Self::Load {
|
||||
width: width::D,
|
||||
dest,
|
||||
offset,
|
||||
base,
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user