#![allow(clippy::cast_ptr_alignment)]
use crate::common::PhysAddr;
use crate::isa::instruction::{InstSize, is_compressed};
use crate::isa::privileged::Trap;
use crate::isa::rvc::expand;
use crate::uarch::ctx::StageCtx;
use crate::uarch::pipeline::exception::ExceptionStage;
use crate::uarch::pipeline::frontend::read_inst_half;
use crate::uarch::pipeline::latches::{Fetch1Fetch2Entry, IfIdEntry};
use crate::{trace_fetch, trace_trap};
pub fn fetch2_stage(
state: &StageCtx<'_>,
input: &mut Vec<Fetch1Fetch2Entry>,
output: &mut Vec<IfIdEntry>,
) {
output.clear();
if input.is_empty() {
return;
}
let entries = std::mem::take(input);
for f1 in entries {
if let Some(ref trap) = f1.trap {
trace_trap!(state.trace_trap_enabled(trap);
event = "propagate",
stage = "F2",
pc = %crate::common::trace::Hex(f1.pc),
trap = ?trap,
"F2: trap propagated from F1"
);
output.push(IfIdEntry {
pc: f1.pc,
inst: 0,
inst_size: InstSize::Standard,
pred_taken: f1.pred_taken,
pred_target: f1.pred_target,
trap: f1.trap,
exception_stage: f1.exception_stage,
seq: f1.seq,
});
break;
}
let phys_addr = f1.paddr.val();
let half_word = read_inst_half(state, phys_addr);
let is_compressed = is_compressed(half_word);
let (inst, step, inst_trap) = if is_compressed {
let expanded = expand(half_word);
if expanded == 0 {
(0, InstSize::Compressed, Some(Trap::IllegalInstruction(half_word as u32)))
} else {
(expanded, InstSize::Compressed, None)
}
} else {
let upper_paddr = f1.upper_paddr.unwrap_or_else(|| PhysAddr::new(phys_addr + 2));
let upper_half = read_inst_half(state, upper_paddr.val());
let full_inst = (upper_half as u32) << 16 | (half_word as u32);
(full_inst, InstSize::Standard, None)
};
if let Some(t) = inst_trap {
trace_trap!(state.trace_trap_enabled(&t);
event = "decode-trap",
stage = "F2",
pc = %crate::common::trace::Hex(f1.pc),
trap = ?t,
"F2: instruction decode trap"
);
output.push(IfIdEntry {
pc: f1.pc,
inst: 0,
inst_size: step,
pred_taken: f1.pred_taken,
pred_target: f1.pred_target,
trap: Some(t),
exception_stage: Some(ExceptionStage::Fetch),
seq: f1.seq,
});
break;
}
trace_fetch!(state.config.general.trace_instructions;
pc = %crate::common::trace::Hex(f1.pc),
inst = inst,
inst_size = step.as_u64(),
compressed = is_compressed,
"F2: decoded instruction"
);
output.push(IfIdEntry {
pc: f1.pc,
inst,
inst_size: step,
pred_taken: f1.pred_taken,
pred_target: f1.pred_target,
trap: None,
exception_stage: None,
seq: f1.seq,
});
}
}