workaround for ADCS
This commit is contained in:
parent
dde398ad5f
commit
573541bea7
|
@ -1,3 +1,5 @@
|
|||
use std::mem::size_of;
|
||||
|
||||
use yaxpeax_arm::armv8::a64::{Opcode, Operand, SizeCode, ShiftStyle, Instruction};
|
||||
|
||||
use lightning_sys::{JitWord, JitState, Reg};
|
||||
|
@ -5,13 +7,25 @@ use lightning_sys::{JitWord, JitState, Reg};
|
|||
use crate::ext_lightning::{ExtJitState, OperandHelpers, ToLightning};
|
||||
use crate::Result;
|
||||
|
||||
// baker's 32. need a spare for ARM's barrel shifter. (possibly more later)
|
||||
const GP_REGS: usize = 33;
|
||||
// baker's 32. need spares for:
|
||||
// - ARM's barrel shifter
|
||||
// - intermediate sum in ADCS so we can set status & carry simultaneously (glightning limitation)
|
||||
// (possibly more later)
|
||||
const TEMP_REGS: usize = 2;
|
||||
const GP_REGS: usize = 32;
|
||||
pub(crate) fn make_ext_jitstate<'a>(js: JitState<'a>) -> ExtJitState<'a> {
|
||||
ExtJitState::new(js, GP_REGS)
|
||||
// currently don't know how to support 64-bit data on 32-bit host in GNU Lightning
|
||||
assert_eq!(size_of::<JitWord>(), size_of::<u64>());
|
||||
|
||||
ExtJitState::new(js, GP_REGS + TEMP_REGS)
|
||||
}
|
||||
|
||||
const REG_BARREL_TMP: usize = 32; // index in array
|
||||
// "register number" indeces above the last gp reg in the actual ISA
|
||||
const REG_PSTATE: usize = GP_REGS; // TODO: how to most efficiently represent N/Z/C/V in glightning?
|
||||
const REG_BARREL_TMP: usize = GP_REGS + 1;
|
||||
const REG_CARRY_TMP: usize = GP_REGS + 2;
|
||||
const REG_32_SRC1_TMP: usize = GP_REGS + 3;
|
||||
const REG_32_SRC2_TMP: usize = GP_REGS + 4;
|
||||
|
||||
impl OperandHelpers for Operand {
|
||||
fn reg_id(&self) -> Result<usize> {
|
||||
|
@ -33,18 +47,33 @@ impl OperandHelpers for Operand {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: shift to set carry correctly for 32-bit?
|
||||
// TODO: actually implement to the spec
|
||||
// TODO: support (extended register)
|
||||
fn add(ejs: &mut ExtJitState, operands: &[Operand; 4], carry: bool, status: bool) -> Result<()> {
|
||||
let [dest_orig, src1_orig, src2_orig, _] = operands;
|
||||
let mut add_reg: fn(&mut ExtJitState, Reg, Reg, Reg);
|
||||
let mut add_imm: fn(&mut ExtJitState, Reg, Reg, JitWord);
|
||||
add_reg = |ejs, dest, src1, src2| { ejs.addr(dest, src1, src2); };
|
||||
add_imm = |ejs, dest, src1, src2| { ejs.addi(dest, src1, src2); };
|
||||
if carry {
|
||||
let add_reg: fn(&mut ExtJitState, Reg, Reg, Reg);
|
||||
let add_imm: fn(&mut ExtJitState, Reg, Reg, JitWord);
|
||||
if carry && status {
|
||||
add_reg = |ejs, dest, src1, src2| {
|
||||
let tmp = ejs.reg(REG_CARRY_TMP).unwrap();
|
||||
ejs.addxi(tmp, src1, 0);
|
||||
ejs.addcr(dest, tmp, src2);
|
||||
};
|
||||
add_imm = |ejs, dest, src1, src2| {
|
||||
let tmp = ejs.reg(REG_CARRY_TMP).unwrap();
|
||||
ejs.addxi(tmp, src1, 0);
|
||||
ejs.addci(dest, tmp, src2);
|
||||
};
|
||||
} else if carry {
|
||||
add_reg = |ejs, dest, src1, src2| { ejs.addxr(dest, src1, src2); };
|
||||
add_imm = |ejs, dest, src1, src2| { ejs.addxi(dest, src1, src2); };
|
||||
} else if status {
|
||||
add_reg = |ejs, dest, src1, src2| { ejs.addcr(dest, src1, src2); };
|
||||
add_imm = |ejs, dest, src1, src2| { ejs.addci(dest, src1, src2); };
|
||||
}
|
||||
if status {
|
||||
todo!();
|
||||
} else {
|
||||
add_reg = |ejs, dest, src1, src2| { ejs.addr(dest, src1, src2); };
|
||||
add_imm = |ejs, dest, src1, src2| { ejs.addi(dest, src1, src2); };
|
||||
}
|
||||
let src1 = ejs.reg(src1_orig.reg_id()?)?;
|
||||
// we decode dest last for correctness in super-scarce register situations where
|
||||
|
|
Loading…
Reference in New Issue