use super::sparc_instr_info::SparcOpcode;
use super::sparc_register_info::{SPARC_FPR_BASE, SPARC_GPR_BASE};
use crate::codegen::{MachineFunction, MachineInstr, MachineOperand};
const FMT1_CALL: u32 = 0x01;
const FMT2_SETHI: u32 = 0x00; const FMT2_BICC: u32 = 0x00; const FMT2_FBFCC: u32 = 0x00;
const FMT3_OP: u32 = 0x02; const FMT3_OP2: u32 = 0x03;
const OP3_ADD: u32 = 0x00;
const OP3_ADDcc: u32 = 0x10;
const OP3_ADDC: u32 = 0x08;
const OP3_ADDCcc: u32 = 0x18;
const OP3_SUB: u32 = 0x04;
const OP3_SUBcc: u32 = 0x14;
const OP3_SUBC: u32 = 0x0C;
const OP3_SUBCcc: u32 = 0x1C;
const OP3_AND: u32 = 0x01;
const OP3_ANDcc: u32 = 0x11;
const OP3_ANDN: u32 = 0x05;
const OP3_ANDNcc: u32 = 0x15;
const OP3_OR: u32 = 0x02;
const OP3_ORcc: u32 = 0x12;
const OP3_ORN: u32 = 0x06;
const OP3_ORNcc: u32 = 0x16;
const OP3_XOR: u32 = 0x03;
const OP3_XORcc: u32 = 0x13;
const OP3_XNOR: u32 = 0x07;
const OP3_XNORcc: u32 = 0x17;
const OP3_SLL: u32 = 0x25;
const OP3_SRL: u32 = 0x26;
const OP3_SRA: u32 = 0x27;
const OP3_LD: u32 = 0x00;
const OP3_LDUB: u32 = 0x01;
const OP3_LDUH: u32 = 0x02;
const OP3_LDSB: u32 = 0x09;
const OP3_LDSH: u32 = 0x0A;
const OP3_LDD: u32 = 0x03;
const OP3_ST: u32 = 0x04;
const OP3_STB: u32 = 0x05;
const OP3_STH: u32 = 0x06;
const OP3_STD: u32 = 0x07;
const OP3_JMPL: u32 = 0x38;
const OP3_SAVE: u32 = 0x3C;
const OP3_RESTORE: u32 = 0x3D;
const OP3_RETT: u32 = 0x39;
const OP3_FPop1: u32 = 0x34;
const OP3_FPop2: u32 = 0x35;
const COND_BA: u32 = 0x08;
const COND_BN: u32 = 0x00;
const COND_BNE: u32 = 0x09;
const COND_BE: u32 = 0x01;
const COND_BG: u32 = 0x0A;
const COND_BLE: u32 = 0x02;
const COND_BGE: u32 = 0x0B;
const COND_BL: u32 = 0x03;
const COND_BGU: u32 = 0x0C;
const COND_BLEU: u32 = 0x04;
const COND_BCC: u32 = 0x0D;
const COND_BCS: u32 = 0x05;
const COND_BPOS: u32 = 0x0E;
const COND_BNEG: u32 = 0x06;
const COND_BVC: u32 = 0x0F;
const COND_BVS: u32 = 0x07;
const FPop_S: u32 = 0x41; const FPop_D: u32 = 0x42;
fn u32_to_be_bytes(word: u32) -> Vec<u8> {
word.to_be_bytes().to_vec()
}
pub struct SparcMCEncoder {
pub is_64bit: bool,
pub output: Vec<u8>,
}
impl SparcMCEncoder {
pub fn new(is_64bit: bool) -> Self {
Self {
is_64bit,
output: Vec::with_capacity(256),
}
}
pub fn encode_instruction(&mut self, mi: &MachineInstr) -> Vec<u8> {
let bytes = self.instruction_to_bytes(mi);
self.output.extend_from_slice(&bytes);
bytes
}
pub fn encode_function(&mut self, mf: &MachineFunction) -> Vec<u8> {
for block in &mf.blocks {
for instr in &block.instructions {
self.encode_instruction(instr);
}
}
std::mem::take(&mut self.output)
}
fn instruction_to_bytes(&self, mi: &MachineInstr) -> Vec<u8> {
let word = self.encode_by_opcode(mi);
u32_to_be_bytes(word)
}
fn encode_by_opcode(&self, mi: &MachineInstr) -> u32 {
match get_sparc_opcode(mi.opcode) {
SparcOpcode::ADD => self.encode_fmt3_reg(OP3_ADD, mi),
SparcOpcode::ADDcc => self.encode_fmt3_reg(OP3_ADDcc, mi),
SparcOpcode::SUB => self.encode_fmt3_reg(OP3_SUB, mi),
SparcOpcode::SUBcc => self.encode_fmt3_reg(OP3_SUBcc, mi),
SparcOpcode::AND => self.encode_fmt3_reg(OP3_AND, mi),
SparcOpcode::ANDN => self.encode_fmt3_reg(OP3_ANDN, mi),
SparcOpcode::OR => self.encode_fmt3_reg(OP3_OR, mi),
SparcOpcode::ORN => self.encode_fmt3_reg(OP3_ORN, mi),
SparcOpcode::XOR => self.encode_fmt3_reg(OP3_XOR, mi),
SparcOpcode::XNOR => self.encode_fmt3_reg(OP3_XNOR, mi),
SparcOpcode::SLL => self.encode_fmt3_reg(OP3_SLL, mi),
SparcOpcode::SRL => self.encode_fmt3_reg(OP3_SRL, mi),
SparcOpcode::SRA => self.encode_fmt3_reg(OP3_SRA, mi),
SparcOpcode::LD => self.encode_fmt3_mem(OP3_LD, mi),
SparcOpcode::LDUB => self.encode_fmt3_mem(OP3_LDUB, mi),
SparcOpcode::LDUH => self.encode_fmt3_mem(OP3_LDUH, mi),
SparcOpcode::LDSB => self.encode_fmt3_mem(OP3_LDSB, mi),
SparcOpcode::LDSH => self.encode_fmt3_mem(OP3_LDSH, mi),
SparcOpcode::LDD => self.encode_fmt3_mem(OP3_LDD, mi),
SparcOpcode::ST => self.encode_fmt3_mem(OP3_ST, mi),
SparcOpcode::STB => self.encode_fmt3_mem(OP3_STB, mi),
SparcOpcode::STH => self.encode_fmt3_mem(OP3_STH, mi),
SparcOpcode::STD => self.encode_fmt3_mem(OP3_STD, mi),
SparcOpcode::BA => self.encode_fmt2_branch(COND_BA, mi),
SparcOpcode::BN => self.encode_fmt2_branch(COND_BN, mi),
SparcOpcode::BNE => self.encode_fmt2_branch(COND_BNE, mi),
SparcOpcode::BE => self.encode_fmt2_branch(COND_BE, mi),
SparcOpcode::BG => self.encode_fmt2_branch(COND_BG, mi),
SparcOpcode::BLE => self.encode_fmt2_branch(COND_BLE, mi),
SparcOpcode::BGE => self.encode_fmt2_branch(COND_BGE, mi),
SparcOpcode::BL => self.encode_fmt2_branch(COND_BL, mi),
SparcOpcode::BGU => self.encode_fmt2_branch(COND_BGU, mi),
SparcOpcode::BLEU => self.encode_fmt2_branch(COND_BLEU, mi),
SparcOpcode::BCC => self.encode_fmt2_branch(COND_BCC, mi),
SparcOpcode::BCS => self.encode_fmt2_branch(COND_BCS, mi),
SparcOpcode::BPOS => self.encode_fmt2_branch(COND_BPOS, mi),
SparcOpcode::BNEG => self.encode_fmt2_branch(COND_BNEG, mi),
SparcOpcode::BVC => self.encode_fmt2_branch(COND_BVC, mi),
SparcOpcode::BVS => self.encode_fmt2_branch(COND_BVS, mi),
SparcOpcode::CALL => self.encode_fmt1_call(mi),
SparcOpcode::JMPL => self.encode_fmt3_reg(OP3_JMPL, mi),
SparcOpcode::SAVE => self.encode_fmt3_reg(OP3_SAVE, mi),
SparcOpcode::RESTORE => self.encode_fmt3_reg(OP3_RESTORE, mi),
SparcOpcode::SETHI => self.encode_fmt2_sethi(mi),
SparcOpcode::NOP => 0x01000000, SparcOpcode::FADDS => self.encode_fpu_fmt3(FPop_S, 0x41, mi),
SparcOpcode::FADDD => self.encode_fpu_fmt3(FPop_D, 0x42, mi),
SparcOpcode::FSUBS => self.encode_fpu_fmt3(FPop_S, 0x45, mi),
SparcOpcode::FSUBD => self.encode_fpu_fmt3(FPop_D, 0x46, mi),
SparcOpcode::FMULS => self.encode_fpu_fmt3(FPop_S, 0x49, mi),
SparcOpcode::FMULD => self.encode_fpu_fmt3(FPop_D, 0x4A, mi),
SparcOpcode::FDIVS => self.encode_fpu_fmt3(FPop_S, 0x4D, mi),
SparcOpcode::FDIVD => self.encode_fpu_fmt3(FPop_D, 0x4E, mi),
SparcOpcode::FSQRTS => self.encode_fpu_fmt3(FPop_S, 0x29, mi),
SparcOpcode::FSQRTD => self.encode_fpu_fmt3(FPop_D, 0x2A, mi),
SparcOpcode::FITOS => self.encode_fpu_fmt3(FPop_S, 0xC4, mi),
SparcOpcode::FITOD => self.encode_fpu_fmt3(FPop_S, 0xC8, mi),
SparcOpcode::FSTOI => self.encode_fpu_fmt3(FPop_S, 0xD1, mi),
SparcOpcode::FDTOI => self.encode_fpu_fmt3(FPop_D, 0xD2, mi),
SparcOpcode::FMOVS => self.encode_fpu_fmt3(FPop_S, 0x01, mi),
SparcOpcode::FMOVD => self.encode_fpu_fmt3(FPop_D, 0x02, mi),
SparcOpcode::FCMPS => self.encode_fpu_cmp(FPop_S, 0x51, mi),
SparcOpcode::FCMPD => self.encode_fpu_cmp(FPop_D, 0x52, mi),
SparcOpcode::FCMPES => self.encode_fpu_cmp(FPop_S, 0x55, mi),
SparcOpcode::FCMPED => self.encode_fpu_cmp(FPop_D, 0x56, mi),
SparcOpcode::RET => self.encode_fmt3_ret(),
SparcOpcode::RETL => self.encode_fmt3_retl(),
_ => 0x01000000, }
}
fn encode_fmt1_call(&self, mi: &MachineInstr) -> u32 {
let disp30: u32 = 0; (FMT1_CALL << 30) | (disp30 & 0x3FFFFFFF)
}
fn encode_fmt2_sethi(&self, mi: &MachineInstr) -> u32 {
let rd = Self::get_reg_field(mi, 0);
let imm22: u32 = Self::get_imm(mi, 1) as u32 & 0x3FFFFF;
(FMT2_SETHI << 30) | (rd << 25) | (0x04 << 22) | imm22
}
fn encode_fmt2_branch(&self, cond: u32, mi: &MachineInstr) -> u32 {
let a = 0; let disp22: u32 = 0; (FMT2_BICC << 30) | (a << 29) | (cond << 25) | (0x02 << 22) | (disp22 & 0x3FFFFF)
}
fn encode_fmt3_reg(&self, op3: u32, mi: &MachineInstr) -> u32 {
let rd = Self::get_reg_field(mi, 0);
let rs1 = Self::get_reg_field(mi, 1);
let rs2 = Self::get_reg_field(mi, 2);
let i = 0; (FMT3_OP << 30) | (rd << 25) | (op3 << 19) | (rs1 << 14) | (i << 13) | rs2
}
fn encode_fmt3_mem(&self, op3: u32, mi: &MachineInstr) -> u32 {
let rd = Self::get_reg_field(mi, 0);
let rs1 = Self::get_reg_field(mi, 1);
let offset = Self::get_imm(mi, 2) as i32;
let simm13: u32 = (offset & 0x1FFF) as u32;
let i = 1; (FMT3_OP << 30) | (rd << 25) | (op3 << 19) | (rs1 << 14) | (i << 13) | simm13
}
fn encode_fmt3_ret(&self) -> u32 {
let rd: u32 = 0; let rs1: u32 = 31; (FMT3_OP << 30) | (rd << 25) | (OP3_JMPL << 19) | (rs1 << 14) | (1 << 13) | 8
}
fn encode_fmt3_retl(&self) -> u32 {
let rd: u32 = 0; let rs1: u32 = 15; (FMT3_OP << 30) | (rd << 25) | (OP3_JMPL << 19) | (rs1 << 14) | (1 << 13) | 8
}
fn encode_fpu_fmt3(&self, fpop_type: u32, fpop_func: u32, mi: &MachineInstr) -> u32 {
let rd = Self::get_reg_field(mi, 0);
let rs1 = Self::get_reg_field(mi, 1);
let rs2 = Self::get_reg_field(mi, 2);
(FMT3_OP << 30) | (rd << 25) | (OP3_FPop1 << 19) | (rs1 << 14) | (fpop_type << 5) | rs2
}
fn encode_fpu_cmp(&self, _fpop_type: u32, _fpop_func: u32, mi: &MachineInstr) -> u32 {
let rs1 = Self::get_reg_field(mi, 0);
let rs2 = Self::get_reg_field(mi, 1);
(FMT3_OP << 30) | (0x35 << 19) | (rs1 << 14) | (1 << 5) | rs2
}
fn get_reg_field(mi: &MachineInstr, index: usize) -> u32 {
mi.operands
.get(index)
.map(|op| match op {
MachineOperand::Reg(vr) => *vr & 0x1F,
MachineOperand::PhysReg(pr) => *pr & 0x1F,
MachineOperand::Imm(_) => 0,
_ => 0,
})
.unwrap_or(0) as u32
}
fn get_imm(mi: &MachineInstr, index: usize) -> i64 {
mi.operands
.get(index)
.map(|op| match op {
MachineOperand::Imm(imm) => *imm,
_ => 0,
})
.unwrap_or(0)
}
}
fn get_sparc_opcode(opcode: u32) -> SparcOpcode {
match opcode {
0 => SparcOpcode::ADD,
1 => SparcOpcode::ADDcc,
2 => SparcOpcode::ADDC,
3 => SparcOpcode::ADDCcc,
4 => SparcOpcode::SUB,
5 => SparcOpcode::SUBcc,
6 => SparcOpcode::SUBC,
7 => SparcOpcode::SUBCcc,
8 => SparcOpcode::MULX,
9 => SparcOpcode::SDIVX,
10 => SparcOpcode::UDIVX,
11 => SparcOpcode::SMUL,
12 => SparcOpcode::UMUL,
13 => SparcOpcode::SDIV,
14 => SparcOpcode::UDIV,
20 => SparcOpcode::AND,
21 => SparcOpcode::ANDcc,
22 => SparcOpcode::ANDN,
23 => SparcOpcode::ANDNcc,
24 => SparcOpcode::OR,
25 => SparcOpcode::ORcc,
26 => SparcOpcode::ORN,
27 => SparcOpcode::ORNcc,
28 => SparcOpcode::XOR,
29 => SparcOpcode::XORcc,
30 => SparcOpcode::XNOR,
31 => SparcOpcode::XNORcc,
40 => SparcOpcode::SLL,
41 => SparcOpcode::SRL,
42 => SparcOpcode::SRA,
50 => SparcOpcode::LD,
51 => SparcOpcode::LDUB,
52 => SparcOpcode::LDUH,
53 => SparcOpcode::LDSB,
54 => SparcOpcode::LDSH,
55 => SparcOpcode::LDD,
60 => SparcOpcode::ST,
61 => SparcOpcode::STB,
62 => SparcOpcode::STH,
63 => SparcOpcode::STD,
70 => SparcOpcode::BA,
71 => SparcOpcode::BN,
72 => SparcOpcode::BNE,
73 => SparcOpcode::BE,
74 => SparcOpcode::BG,
75 => SparcOpcode::BLE,
76 => SparcOpcode::BGE,
77 => SparcOpcode::BL,
78 => SparcOpcode::BGU,
79 => SparcOpcode::BLEU,
80 => SparcOpcode::BCC,
81 => SparcOpcode::BCS,
82 => SparcOpcode::BPOS,
83 => SparcOpcode::BNEG,
84 => SparcOpcode::BVC,
85 => SparcOpcode::BVS,
120 => SparcOpcode::CALL,
121 => SparcOpcode::JMPL,
122 => SparcOpcode::RET,
123 => SparcOpcode::RETL,
124 => SparcOpcode::SAVE,
125 => SparcOpcode::RESTORE,
130 => SparcOpcode::SETHI,
131 => SparcOpcode::NOP,
150 => SparcOpcode::FADDS,
151 => SparcOpcode::FADDD,
152 => SparcOpcode::FSUBS,
153 => SparcOpcode::FSUBD,
154 => SparcOpcode::FMULS,
155 => SparcOpcode::FMULD,
156 => SparcOpcode::FDIVS,
157 => SparcOpcode::FDIVD,
158 => SparcOpcode::FSQRTS,
159 => SparcOpcode::FSQRTD,
160 => SparcOpcode::FITOS,
161 => SparcOpcode::FITOD,
162 => SparcOpcode::FSTOI,
163 => SparcOpcode::FDTOI,
164 => SparcOpcode::FMOVS,
165 => SparcOpcode::FMOVD,
170 => SparcOpcode::FCMPS,
171 => SparcOpcode::FCMPD,
172 => SparcOpcode::FCMPES,
173 => SparcOpcode::FCMPED,
_ => SparcOpcode::NOP,
}
}