WIP: implement more instructions in unit::alu_branch #14

Draft
programmerjake wants to merge 8 commits from programmerjake/cpu:more-alu-branch into master
5 changed files with 2378 additions and 1229 deletions
Showing only changes of commit 42056ce6b5 - Show all commits

View file

@ -6,7 +6,7 @@ use crate::{
instruction::{
AddSubMOp, AluBranchMOp, AluCommonMOp, BranchMOp, COMMON_MOP_SRC_LEN, CommonMOp,
CommonMOpDefaultImm, CompareMOp, CompareMode, ConditionMode, LogicalFlagsMOp, LogicalMOp,
OutputIntegerMode, PRegNum, ReadSpecialMOp, ShiftRotateDestLogicOp, ShiftRotateMOp,
Lut4, OutputIntegerMode, PRegNum, ReadSpecialMOp, ShiftRotateDestLogicOp, ShiftRotateMOp,
ShiftRotateMOpImm, ShiftRotateMode,
},
next_pc::CallStackOp,
@ -254,29 +254,122 @@ fn logical_flags<C: PhantomConstCpuConfig>(
}
#[hdl]
fn logical<C: PhantomConstCpuConfig>(
fn logical<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
global_state: Expr<GlobalState>,
pc: Expr<UInt<64>>,
mop: Expr<LogicalMOp<PRegNum<C>, PRegNum<C>, ConstUsize<2>>>,
mop: Expr<LogicalMOp<PRegNum<C>, PRegNum<C>, SrcCount>>,
src_values: Expr<Array<TraceAsString<PRegValue>, { COMMON_MOP_SRC_LEN }>>,
) -> Expr<TraceAsString<PRegValue>> {
#[hdl]
let GlobalState { flags_mode } = global_state;
// TODO: finish
PRegValue::zeroed().to_trace_as_string()
}
#[hdl]
fn logical_i<C: PhantomConstCpuConfig>(
global_state: Expr<GlobalState>,
pc: Expr<UInt<64>>,
mop: Expr<LogicalMOp<PRegNum<C>, PRegNum<C>, ConstUsize<1>>>,
src_values: Expr<Array<TraceAsString<PRegValue>, { COMMON_MOP_SRC_LEN }>>,
) -> Expr<TraceAsString<PRegValue>> {
#[hdl]
let GlobalState { flags_mode } = global_state;
// TODO: finish
PRegValue::zeroed().to_trace_as_string()
let LogicalMOp::<_, _, _> { alu_common, lut } = mop;
#[hdl]
let AluCommonMOp::<_, _, _, _> {
common,
output_integer_mode,
} = alu_common;
let (lhs, rhs) = match SrcCount::VALUE {
1 => (
src_values[0],
Expr::into_trace_as_string(
#[hdl]
PRegValue {
int_fp: CommonMOpDefaultImm::as_sint_dyn(common.imm)
.cast_to_static::<UInt<64>>(),
flags: PRegFlags::zeroed(),
},
),
),
2 => (src_values[0], src_values[1]),
_ => todo!(),
};
#[hdl]
let lut4_output = wire();
connect(lut4_output, Lut4::output(lut, lhs.int_fp, rhs.int_fp));
#[hdl]
let logical_result: TraceAsString<PRegValue> = wire();
#[hdl]
let x86_sf = wire();
#[hdl]
match flags_mode {
FlagsMode::PowerISA(_) => {
let PRegFlagsPowerISAView {
unused,
xer_ca,
xer_ca32,
xer_ov,
xer_ov32,
cr_lt,
cr_gt,
cr_eq,
so,
} = PRegFlags::view::<PRegFlagsPowerISA>(logical_result.flags);
unused.clear();
connect(xer_ca, false);
connect(xer_ca32, false);
connect(xer_ov, false);
connect(xer_ov32, false);
let signed_result = logical_result.int_fp.cast_to_static::<SInt<64>>();
connect(cr_lt, signed_result.cmp_lt(0i64));
connect(cr_eq, signed_result.cmp_eq(0i64));
connect(cr_gt, !(cr_lt | cr_eq));
connect(so, false); // TODO: need to set from the global SO
}
FlagsMode::X86(_) => {
let PRegFlagsX86View {
unused,
cf,
zf,
sf,
of,
af,
pf,
df,
} = PRegFlags::view::<PRegFlagsX86>(logical_result.flags);
unused.clear();
connect(cf, false);
connect(zf, logical_result.int_fp.cmp_eq(0u64));
connect(sf, x86_sf);
connect(of, false);
connect(af, false);
connect(pf, logical_result.int_fp[..8].parity_even());
connect(df, false);
}
}
let connect_output = |width, signed| {
connect(x86_sf, logical_result.int_fp[width - 1]);
if signed {
connect(
logical_result.int_fp,
lut4_output
.cast_to(SInt[width])
.cast_to_static::<UInt<64>>(),
);
} else {
connect(
logical_result.int_fp,
lut4_output
.cast_to(UInt[width])
.cast_to_static::<UInt<64>>(),
);
}
};
#[hdl]
match output_integer_mode {
OutputIntegerMode::Full64 => connect_output(64, false),
OutputIntegerMode::DupLow32 => {
connect(x86_sf, logical_result.int_fp[31]);
let v = lut4_output.cast_to_static::<UInt<32>>();
connect_any(logical_result.int_fp, v | (v << 32));
}
OutputIntegerMode::ZeroExt32 => connect_output(32, false),
OutputIntegerMode::SignExt32 => connect_output(32, true),
OutputIntegerMode::ZeroExt16 => connect_output(16, false),
OutputIntegerMode::SignExt16 => connect_output(16, true),
OutputIntegerMode::ZeroExt8 => connect_output(8, false),
OutputIntegerMode::SignExt8 => connect_output(8, true),
}
logical_result
}
#[hdl]
@ -897,16 +990,10 @@ pub fn alu_branch(config: PhantomConst<CpuConfig>, unit_index: usize) {
connect(dest_value, logical_flags(global_state, mop, src_values));
}
AluBranchMOp::<_, _>::Logical(mop) => {
connect(
dest_value,
logical(global_state, mop_instance.pc, mop, src_values),
);
connect(dest_value, logical(global_state, mop, src_values));
}
AluBranchMOp::<_, _>::LogicalI(mop) => {
connect(
dest_value,
logical_i(global_state, mop_instance.pc, mop, src_values),
);
connect(dest_value, logical(global_state, mop, src_values));
}
AluBranchMOp::<_, _>::ShiftRotate(mop) => {
connect(dest_value, shift_rotate(global_state, mop, src_values));
@ -1022,7 +1109,7 @@ impl UnitTrait for AluBranch {
self.module
}
fn cd(&self, this: Expr<Self::Type>) -> Option<Expr<ClockDomain>> {
fn cd(&self, _this: Expr<Self::Type>) -> Option<Expr<ClockDomain>> {
None
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff