decode some more add instructions

This commit is contained in:
Jacob Lifshay 2026-01-15 16:10:03 -08:00
parent b7b6a02777
commit 62512960c3
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
5 changed files with 1028 additions and 77 deletions

View file

@ -166,7 +166,10 @@ macro_rules! impl_fields {
impl FieldSet for $Struct {
#[track_caller]
fn get(fields: &mut BTreeMap<&str, Expr<UInt>>) -> Self {
Self(fields[$name].cast_bits_to(StaticType::TYPE))
let Some(v) = fields.get($name) else {
panic!("field {:?} not found", $name);
};
Self(v.cast_bits_to(StaticType::TYPE))
}
}
)*
@ -175,31 +178,36 @@ macro_rules! impl_fields {
impl_fields! {
#[name = "RA"]
struct FieldRA(UInt<5>);
struct FieldRA(FieldGpr);
#[name = "RB"]
struct FieldRB(FieldGpr);
#[name = "RT"]
struct FieldRT(UInt<5>);
struct FieldRT(FieldGpr);
#[name = "SI"]
struct FieldSI(SInt<16>);
#[name = "d0"]
struct FieldAddPcISD0(SInt<10>);
#[name = "d1"]
struct FieldAddPcISD1(UInt<5>);
#[name = "d2"]
struct FieldAddPcISD2(UInt<1>);
#[name = "OE"]
struct FieldOE(Bool);
#[name = "Rc"]
struct FieldRc(Bool);
}
#[hdl]
fn translate_gpr(v: Expr<UInt<5>>) -> Expr<MOpRegNum> {
#[hdl]
MOpRegNum {
value: (v + MOpRegNum::POWER_ISA_GPR_REG_NUMS.start).cast_to_static::<UInt<_>>(),
}
struct FieldGpr {
reg_num: UInt<5>,
}
#[hdl]
fn translate_gpr_or_zero(v: Expr<UInt<5>>) -> Expr<MOpRegNum> {
#[hdl]
let translate_gpr_or_zero = wire();
connect(translate_gpr_or_zero, translate_gpr(v));
#[hdl]
if v.cmp_eq(0u8) {
connect(translate_gpr_or_zero, MOpRegNum::const_zero());
}
translate_gpr_or_zero
fn gpr(this: impl ToExpr<Type = FieldGpr>) -> Expr<MOpRegNum> {
MOpRegNum::power_isa_gpr_reg(this.to_expr().reg_num)
}
fn gpr_or_zero(this: impl ToExpr<Type = FieldGpr>) -> Expr<MOpRegNum> {
MOpRegNum::power_isa_gpr_or_zero_reg(this.to_expr().reg_num)
}
impl DecodeState {
@ -318,6 +326,7 @@ impl DecodeState {
last_start = *msb0_bit_range.start();
let field = Self::msb0_bit_range(word, msb0_bit_range);
let mut name = Self::bit_field_name(bit_field.name());
let orig_name = name;
if name.contains(char::is_alphabetic) {
for (cond_name, cond_value) in self.conditions() {
if name == cond_name {
@ -342,6 +351,14 @@ impl DecodeState {
} else {
let value: u32 = name.parse().expect("bit field name must have at least one letter, be all `/`, or be a valid decimal number");
*matches = *matches & field.cmp_eq(value);
if orig_name.contains(char::is_alphabetic) {
if fields
.insert(orig_name, value.cast_to(field.ty()).to_expr())
.is_some()
{
panic!("duplicate field name: {name:?}\nheader: {:#?}", self.header);
}
}
}
}
}
@ -351,18 +368,24 @@ impl DecodeState {
let mut fields = BTreeMap::new();
let mut matches = true.to_expr();
let mut f = Some(f);
let mut run =
|this: &mut Self, matches: Expr<Bool>, fields: &mut BTreeMap<&str, Expr<UInt>>| {
#[hdl]
if matches {
connect(
this.second_input_used,
this.header.bit_fields().prefix().is_some(),
);
connect(this.is_illegal, false);
f.take().expect("known to be Some")(this, FS::get(fields));
}
};
#[hdl]
#[track_caller]
fn run<FS: FieldSet, F: FnOnce(&mut DecodeState, FS)>(
this: &mut DecodeState,
matches: Expr<Bool>,
fields: &mut BTreeMap<&str, Expr<UInt>>,
f: &mut Option<F>,
) {
#[hdl]
if matches {
connect(
this.second_input_used,
this.header.bit_fields().prefix().is_some(),
);
connect(this.is_illegal, false);
f.take().expect("known to be Some")(this, FS::get(fields));
}
}
if let Some(prefix) = self.header.bit_fields().prefix() {
#[hdl]
if let HdlSome(prefix_word) = self.second_input {
@ -378,7 +401,7 @@ impl DecodeState {
self.first_input,
self.header.bit_fields().fields_inner(),
);
run(self, matches, &mut fields);
run(self, matches, &mut fields, &mut f);
}
} else {
self.decode_word(
@ -387,7 +410,7 @@ impl DecodeState {
self.first_input,
self.header.bit_fields().fields_inner(),
);
run(self, matches, &mut fields);
run(self, matches, &mut fields, &mut f);
}
}
fn decode_b_ba_bl_bla(&mut self) {
@ -405,16 +428,9 @@ impl DecodeState {
connect(
this.output[0],
AddSubMOp::add_sub_i(
MOpDestReg::new([gpr(rt)], []),
#[hdl]
MOpDestReg {
normal_regs: [translate_gpr(rt), MOpRegNum::const_zero()],
flag_regs: [HdlNone(); _],
},
#[hdl]
[
translate_gpr_or_zero(ra).value,
MOpRegNum::const_zero().value,
],
[gpr_or_zero(ra).value, MOpRegNum::const_zero().value],
si.cast_to_static(),
OutputIntegerMode.Full64(),
false,
@ -431,6 +447,204 @@ impl DecodeState {
_ => unreachable!("{:?}", self.mnemonic),
}
}
#[hdl]
fn decode_addis(&mut self) {
self.decode_scope(|this, (FieldRT(rt), FieldRA(ra), FieldSI(si))| {
connect(
ArrayVec::len(this.output),
1usize.cast_to_static::<Length<_>>(),
);
connect(
this.output[0],
AddSubMOp::add_sub_i(
MOpDestReg::new([gpr(rt)], []),
#[hdl]
[gpr_or_zero(ra).value, MOpRegNum::const_zero().value],
(si << 16).cast_to_static(),
OutputIntegerMode.Full64(),
false,
false,
false,
false,
),
);
});
}
#[hdl]
fn decode_addpcis(&mut self) {
self.decode_scope(
|this, (FieldRT(rt), FieldAddPcISD0(d0), FieldAddPcISD1(d1), FieldAddPcISD2(d2))| {
connect(
ArrayVec::len(this.output),
1usize.cast_to_static::<Length<_>>(),
);
let d = (d0 << 6)
+ (d1 << 1).cast_to_static::<SInt<16>>()
+ d2.cast_to_static::<SInt<16>>();
connect(
this.output[0],
AddSubMOp::add_sub_i(
MOpDestReg::new([gpr(rt)], []),
#[hdl]
[MOpRegNum::const_zero().value; 2],
(4i8 + (d << 16)).cast_to_static(),
OutputIntegerMode.Full64(),
false,
false,
false,
true,
),
);
},
);
}
/// for `add[o][.]`
#[hdl]
fn decode_add(&mut self) {
self.decode_scope(
|this, (FieldRT(rt), FieldRA(ra), FieldRB(rb), FieldOE(oe), FieldRc(rc))| {
// TODO: handle SO propagation
connect(
ArrayVec::len(this.output),
1usize.cast_to_static::<Length<_>>(),
);
connect(
this.output[0],
AddSubMOp::add_sub(
MOpDestReg::new(
[gpr(rt)],
[
(MOpRegNum::POWER_ISA_XER_SO_OV_OV32_REG_NUM, oe),
(MOpRegNum::POWER_ISA_CR_0_REG_NUM, rc),
],
),
#[hdl]
[gpr(ra).value, gpr(rb).value, MOpRegNum::const_zero().value],
0i8.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
false,
false,
false,
false,
),
);
},
);
}
/// for `addic[.]`
#[hdl]
fn decode_addic(&mut self) {
self.decode_scope(|this, (FieldRT(rt), FieldRA(ra), FieldSI(si))| {
connect(
ArrayVec::len(this.output),
1usize.cast_to_static::<Length<_>>(),
);
connect(
this.output[0],
AddSubMOp::add_sub_i(
MOpDestReg::new(
[gpr(rt), MOpRegNum::power_isa_xer_ca_ca32_reg()],
[(
MOpRegNum::POWER_ISA_CR_0_REG_NUM,
self.mnemonic.ends_with('.').to_expr(),
)],
),
#[hdl]
[gpr(ra).value, MOpRegNum::const_zero().value],
si.cast_to_static(),
OutputIntegerMode.Full64(),
false,
false,
false,
false,
),
);
});
}
/// for `subf[o][.]`
#[hdl]
fn decode_subf(&mut self) {
// TODO
}
#[hdl]
fn decode_subfic(&mut self) {
// TODO
}
/// for `addc[o][.]`
#[hdl]
fn decode_addc(&mut self) {
self.decode_scope(
|this, (FieldRT(rt), FieldRA(ra), FieldRB(rb), FieldOE(oe), FieldRc(rc))| {
// TODO: handle SO propagation
connect(
ArrayVec::len(this.output),
1usize.cast_to_static::<Length<_>>(),
);
connect(
this.output[0],
AddSubMOp::add_sub(
MOpDestReg::new(
[gpr(rt), MOpRegNum::power_isa_xer_ca_ca32_reg()],
[
(MOpRegNum::POWER_ISA_XER_SO_OV_OV32_REG_NUM, oe),
(MOpRegNum::POWER_ISA_CR_0_REG_NUM, rc),
],
),
#[hdl]
[gpr(ra).value, gpr(rb).value, MOpRegNum::const_zero().value],
0i8.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
false,
false,
false,
false,
),
);
},
);
}
/// for `subfc[o][.]`
#[hdl]
fn decode_subfc(&mut self) {
// TODO
}
/// for `adde[o][.]`
#[hdl]
fn decode_adde(&mut self) {
self.decode_scope(
|this, (FieldRT(rt), FieldRA(ra), FieldRB(rb), FieldOE(oe), FieldRc(rc))| {
// TODO: handle SO propagation
connect(
ArrayVec::len(this.output),
1usize.cast_to_static::<Length<_>>(),
);
connect(
this.output[0],
AddSubMOp::add_sub(
MOpDestReg::new(
[gpr(rt), MOpRegNum::power_isa_xer_ca_ca32_reg()],
[
(MOpRegNum::POWER_ISA_XER_SO_OV_OV32_REG_NUM, oe),
(MOpRegNum::POWER_ISA_CR_0_REG_NUM, rc),
],
),
#[hdl]
[
gpr(ra).value,
MOpRegNum::power_isa_xer_ca_ca32_reg().value,
gpr(rb).value,
],
0i8.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
false,
true,
false,
false,
),
);
},
);
}
}
type DecodeFn = fn(&mut DecodeState);
@ -498,33 +712,27 @@ const DECODE_FNS: &[(&[&str], DecodeFn)] = &[
// load/store string are intentionally not implemented
}),
(&["addi", "paddi"], DecodeState::decode_addi_paddi),
(&["addis"], |_state| {
// TODO
}),
(&["addpcis"], |_state| {
// TODO
}),
(&["add", "add.", "addo", "addo."], |_state| {
// TODO
}),
(&["addic", "addic."], |_state| {
// TODO
}),
(&["subf", "subf.", "subfo", "subfo."], |_state| {
// TODO
}),
(&["subfic"], |_state| {
// TODO
}),
(&["addc", "addc.", "addco", "addco."], |_state| {
// TODO
}),
(&["subfc", "subfc.", "subfco", "subfco."], |_state| {
// TODO
}),
(&["adde", "adde.", "addeo", "addeo."], |_state| {
// TODO
}),
(&["addis"], DecodeState::decode_addis),
(&["addpcis"], DecodeState::decode_addpcis),
(&["add", "add.", "addo", "addo."], DecodeState::decode_add),
(&["addic", "addic."], DecodeState::decode_addic),
(
&["subf", "subf.", "subfo", "subfo."],
DecodeState::decode_subf,
),
(&["subfic"], DecodeState::decode_subfic),
(
&["addc", "addc.", "addco", "addco."],
DecodeState::decode_addc,
),
(
&["subfc", "subfc.", "subfco", "subfco."],
DecodeState::decode_subfc,
),
(
&["adde", "adde.", "addeo", "addeo."],
DecodeState::decode_adde,
),
(&["subfe", "subfe.", "subfeo", "subfeo."], |_state| {
// TODO
}),

View file

@ -4,6 +4,7 @@ use crate::{unit::UnitMOp, util::range_u32_len};
use fayalite::{
expr::{HdlPartialEqImpl, ops::ArrayLiteral},
intern::Interned,
module::wire_with_loc,
prelude::*,
ty::StaticType,
};
@ -983,6 +984,50 @@ impl MOpDestReg {
flag_regs: flag_regs_sim,
}
}
#[hdl]
#[track_caller]
pub fn new(
normal_regs: impl IntoIterator<Item = Expr<MOpRegNum>>,
flag_regs: impl IntoIterator<Item = (u32, Expr<Bool>)>,
) -> Expr<Self> {
let mut normal_regs_array = [MOpRegNum::const_zero(); Self::NORMAL_REG_COUNT];
const FLAG_REG_COUNT: usize = range_u32_len(&MOpRegNum::FLAG_REG_NUMS);
let mut used_flag_regs = [false; FLAG_REG_COUNT];
let mut flag_regs_array = [HdlNone(); FLAG_REG_COUNT];
for (i, normal_reg) in normal_regs.into_iter().enumerate() {
assert!(i < Self::NORMAL_REG_COUNT, "too many normal regs");
normal_regs_array[i] = normal_reg;
}
for (flag_reg_num, flag_reg_enabled) in flag_regs {
let Some(index) = { MOpRegNum::FLAG_REG_NUMS }.position(|v| flag_reg_num == v) else {
panic!(
"flag reg number {flag_reg_num} is out of range, supported range is: {:?}",
MOpRegNum::FLAG_REG_NUMS
);
};
assert!(
!used_flag_regs[index],
"duplicate flag reg number {flag_reg_num}"
);
used_flag_regs[index] = true;
let wire = wire_with_loc(
&format!("flag_reg_{index}"),
SourceLocation::caller(),
StaticType::TYPE,
);
connect(wire, HdlNone());
#[hdl]
if flag_reg_enabled {
connect(wire, HdlSome(()));
}
flag_regs_array[index] = wire;
}
#[hdl]
Self {
normal_regs: normal_regs_array,
flag_regs: flag_regs_array,
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]

View file

@ -29,24 +29,150 @@ impl MOpRegNum {
pub const POWER_ISA_LR_REG_NUM: u32 = 1;
pub const POWER_ISA_CTR_REG_NUM: u32 = 2;
pub const POWER_ISA_TAR_REG_NUM: u32 = 3;
/// XER bits are stored in [`PRegValue.flags`], bits that don't exist in [`PRegValue.flags`] are stored in [`PRegValue.int_fp`]
/// SO, OV, and OV32 XER bits -- in [`PRegValue.flags`]
///
/// [`PRegValue.flags`]: struct@crate::register::PRegValue
/// [`PRegValue.int_fp`]: struct@crate::register::PRegValue
pub const POWER_ISA_XER_REG_NUM: u32 = 4;
pub const POWER_ISA_XER_SO_OV_OV32_REG_NUM: u32 =
range_u32_nth_or_panic(&Self::FLAG_REG_NUMS, 0);
/// CA and CA32 XER bits -- in [`PRegValue.flags`]
///
/// [`PRegValue.flags`]: struct@crate::register::PRegValue
pub const POWER_ISA_XER_CA_CA32_REG_NUM: u32 = 4;
/// only the XER bits that don't exist in [`PRegValue.flags`]
///
/// [`PRegValue.flags`]: struct@crate::register::PRegValue
pub const POWER_ISA_XER_OTHER_REG_NUM: u32 = 5;
pub const POWER_ISA_CR_REG_NUMS: Range<u32> = 8..16;
/// SO, OV, and OV32 XER bits -- in [`PRegValue.flags`]
///
/// [`PRegValue.flags`]: struct@crate::register::PRegValue
#[hdl]
pub fn power_isa_xer_so_ov_ov32_reg() -> Expr<Self> {
#[hdl]
Self {
value: Self::POWER_ISA_XER_SO_OV_OV32_REG_NUM.cast_to_static::<UInt<_>>(),
}
}
/// CA and CA32 XER bits -- in [`PRegValue.flags`]
///
/// [`PRegValue.flags`]: struct@crate::register::PRegValue
#[hdl]
pub fn power_isa_xer_ca_ca32_reg() -> Expr<Self> {
#[hdl]
Self {
value: Self::POWER_ISA_XER_CA_CA32_REG_NUM.cast_to_static::<UInt<_>>(),
}
}
/// only the XER bits that don't exist in [`PRegValue.flags`]
///
/// [`PRegValue.flags`]: struct@crate::register::PRegValue
#[hdl]
pub fn power_isa_xer_other_reg() -> Expr<Self> {
#[hdl]
Self {
value: Self::POWER_ISA_XER_OTHER_REG_NUM.cast_to_static::<UInt<_>>(),
}
}
pub const POWER_ISA_CR_0_REG_NUM: u32 = range_u32_nth_or_panic(&Self::FLAG_REG_NUMS, 1);
pub const POWER_ISA_CR_1_THRU_7_REG_NUMS: Range<u32> = 9..16;
pub const fn power_isa_cr_reg_num(index: usize) -> u32 {
range_u32_nth_or_panic(&Self::POWER_ISA_CR_REG_NUMS, index)
if index == 0 {
Self::POWER_ISA_CR_0_REG_NUM
} else {
range_u32_nth_or_panic(&Self::POWER_ISA_CR_1_THRU_7_REG_NUMS, index - 1)
}
}
#[hdl]
pub fn power_isa_cr_reg(field_num: Expr<UInt<3>>) -> Expr<Self> {
#[hdl]
let power_isa_cr_reg: Self = wire();
#[hdl]
if field_num.cmp_eq(0u8) {
connect_any(power_isa_cr_reg.value, Self::POWER_ISA_CR_0_REG_NUM);
} else {
connect_any(
power_isa_cr_reg.value,
Self::POWER_ISA_CR_1_THRU_7_REG_NUMS.start + field_num,
);
}
power_isa_cr_reg
}
#[hdl]
pub fn power_isa_cr_reg_sim(field_num: &SimValue<UInt<3>>) -> SimValue<Self> {
#[hdl(sim)]
Self {
value: Self::power_isa_cr_reg_num(
field_num.cast_to_static::<UInt<8>>().as_int() as usize
)
.cast_to_static::<UInt<_>>(),
}
}
pub const POWER_ISA_GPR_REG_NUMS: Range<u32> = 32..64;
pub const fn power_isa_gpr_reg_num(index: usize) -> u32 {
range_u32_nth_or_panic(&Self::POWER_ISA_GPR_REG_NUMS, index)
}
#[hdl]
pub fn power_isa_gpr_reg(reg_num: Expr<UInt<5>>) -> Expr<Self> {
#[hdl]
Self {
value: (Self::POWER_ISA_GPR_REG_NUMS.start + reg_num).cast_to_static::<UInt<_>>(),
}
}
#[hdl]
pub fn power_isa_gpr_reg_sim(reg_num: &SimValue<UInt<5>>) -> SimValue<Self> {
#[hdl(sim)]
Self {
value: (Self::POWER_ISA_GPR_REG_NUMS.start + reg_num).cast_to_static::<UInt<_>>(),
}
}
pub const fn power_isa_gpr_or_zero_reg_num(index: usize) -> u32 {
if index == 0 {
Self::CONST_ZERO_REG_NUM
} else {
Self::power_isa_gpr_reg_num(index)
}
}
#[hdl]
pub fn power_isa_gpr_or_zero_reg(reg_num: Expr<UInt<5>>) -> Expr<Self> {
#[hdl]
let power_isa_gpr_or_zero_reg: Self = wire();
connect(power_isa_gpr_or_zero_reg, Self::power_isa_gpr_reg(reg_num));
#[hdl]
if reg_num.cmp_eq(0u8) {
connect(power_isa_gpr_or_zero_reg, Self::const_zero());
}
power_isa_gpr_or_zero_reg
}
#[hdl]
pub fn power_isa_gpr_or_zero_reg_sim(reg_num: &SimValue<UInt<5>>) -> SimValue<Self> {
#[hdl(sim)]
Self {
value: Self::power_isa_gpr_or_zero_reg_num(
reg_num.cast_to_static::<UInt<8>>().as_int() as usize,
)
.cast_to_static::<UInt<_>>(),
}
}
pub const POWER_ISA_FPR_REG_NUMS: Range<u32> = 64..96;
pub const fn power_isa_fpr_reg_num(index: usize) -> u32 {
range_u32_nth_or_panic(&Self::POWER_ISA_FPR_REG_NUMS, index)
}
#[hdl]
pub fn power_isa_fpr_reg(reg_num: Expr<UInt<5>>) -> Expr<Self> {
#[hdl]
Self {
value: (Self::POWER_ISA_FPR_REG_NUMS.start + reg_num).cast_to_static::<UInt<_>>(),
}
}
#[hdl]
pub fn power_isa_fpr_reg_sim(reg_num: &SimValue<UInt<5>>) -> SimValue<Self> {
#[hdl(sim)]
Self {
value: (Self::POWER_ISA_FPR_REG_NUMS.start + reg_num).cast_to_static::<UInt<_>>(),
}
}
}

View file

@ -496,9 +496,191 @@ $var wire 1 _" second_input_used $end
$var wire 16 `" addi_SI $end
$var wire 5 a" addi_RA $end
$var wire 5 b" addi_RT $end
$scope struct translate_gpr_or_zero $end
$scope struct power_isa_gpr_or_zero_reg $end
$var wire 8 c" value $end
$upscope $end
$var wire 16 d" addis_SI $end
$var wire 5 e" addis_RA $end
$var wire 5 f" addis_RT $end
$scope struct power_isa_gpr_or_zero_reg_2 $end
$var wire 8 g" value $end
$upscope $end
$var wire 1 h" addpcis_d2 $end
$var wire 10 i" addpcis_d0 $end
$var wire 5 j" addpcis_d1 $end
$var wire 5 k" addpcis_RT $end
$var wire 5 l" add_RB $end
$var wire 5 m" add_RA $end
$var wire 5 n" add_RT $end
$scope struct flag_reg_0 $end
$var string 1 o" \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$scope struct flag_reg_1 $end
$var string 1 p" \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$var wire 5 q" add__RB $end
$var wire 5 r" add__RA $end
$var wire 5 s" add__RT $end
$scope struct flag_reg_0_2 $end
$var string 1 t" \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$scope struct flag_reg_1_2 $end
$var string 1 u" \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$var wire 5 v" addo_RB $end
$var wire 5 w" addo_RA $end
$var wire 5 x" addo_RT $end
$scope struct flag_reg_0_3 $end
$var string 1 y" \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$scope struct flag_reg_1_3 $end
$var string 1 z" \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$var wire 5 {" addo__RB $end
$var wire 5 |" addo__RA $end
$var wire 5 }" addo__RT $end
$scope struct flag_reg_0_4 $end
$var string 1 ~" \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$scope struct flag_reg_1_4 $end
$var string 1 !# \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$var wire 16 "# addic_SI $end
$var wire 5 ## addic_RA $end
$var wire 5 $# addic_RT $end
$scope struct flag_reg_1_5 $end
$var string 1 %# \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$var wire 16 &# addic__SI $end
$var wire 5 '# addic__RA $end
$var wire 5 (# addic__RT $end
$scope struct flag_reg_1_6 $end
$var string 1 )# \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$var wire 5 *# addc_RB $end
$var wire 5 +# addc_RA $end
$var wire 5 ,# addc_RT $end
$scope struct flag_reg_0_5 $end
$var string 1 -# \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$scope struct flag_reg_1_7 $end
$var string 1 .# \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$var wire 5 /# addc__RB $end
$var wire 5 0# addc__RA $end
$var wire 5 1# addc__RT $end
$scope struct flag_reg_0_6 $end
$var string 1 2# \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$scope struct flag_reg_1_8 $end
$var string 1 3# \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$var wire 5 4# addco_RB $end
$var wire 5 5# addco_RA $end
$var wire 5 6# addco_RT $end
$scope struct flag_reg_0_7 $end
$var string 1 7# \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$scope struct flag_reg_1_9 $end
$var string 1 8# \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$var wire 5 9# addco__RB $end
$var wire 5 :# addco__RA $end
$var wire 5 ;# addco__RT $end
$scope struct flag_reg_0_8 $end
$var string 1 <# \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$scope struct flag_reg_1_10 $end
$var string 1 =# \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$var wire 5 ># adde_RB $end
$var wire 5 ?# adde_RA $end
$var wire 5 @# adde_RT $end
$scope struct flag_reg_0_9 $end
$var string 1 A# \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$scope struct flag_reg_1_11 $end
$var string 1 B# \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$var wire 5 C# adde__RB $end
$var wire 5 D# adde__RA $end
$var wire 5 E# adde__RT $end
$scope struct flag_reg_0_10 $end
$var string 1 F# \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$scope struct flag_reg_1_12 $end
$var string 1 G# \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$var wire 5 H# addeo_RB $end
$var wire 5 I# addeo_RA $end
$var wire 5 J# addeo_RT $end
$scope struct flag_reg_0_11 $end
$var string 1 K# \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$scope struct flag_reg_1_13 $end
$var string 1 L# \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$var wire 5 M# addeo__RB $end
$var wire 5 N# addeo__RA $end
$var wire 5 O# addeo__RT $end
$scope struct flag_reg_0_12 $end
$var string 1 P# \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$scope struct flag_reg_1_14 $end
$var string 1 Q# \$tag $end
$scope struct HdlSome $end
$upscope $end
$upscope $end
$upscope $end
$enddefinitions $end
$dumpvars
@ -663,5 +845,286 @@ b1001000110100 `"
b100 a"
b11 b"
b100100 c"
b1001000110100 d"
b100 e"
b11 f"
b100100 g"
0h"
b1001000 i"
b100 j"
b11 k"
b10 l"
b100 m"
b11 n"
sHdlNone\x20(0) o"
sHdlNone\x20(0) p"
b10 q"
b100 r"
b11 s"
sHdlNone\x20(0) t"
sHdlSome\x20(1) u"
b10 v"
b100 w"
b11 x"
sHdlSome\x20(1) y"
sHdlNone\x20(0) z"
b10 {"
b100 |"
b11 }"
sHdlSome\x20(1) ~"
sHdlSome\x20(1) !#
b1001000110100 "#
b100 ##
b11 $#
sHdlNone\x20(0) %#
b1001000110100 &#
b100 '#
b11 (#
sHdlSome\x20(1) )#
b10 *#
b100 +#
b11 ,#
sHdlNone\x20(0) -#
sHdlNone\x20(0) .#
b10 /#
b100 0#
b11 1#
sHdlNone\x20(0) 2#
sHdlSome\x20(1) 3#
b10 4#
b100 5#
b11 6#
sHdlSome\x20(1) 7#
sHdlNone\x20(0) 8#
b10 9#
b100 :#
b11 ;#
sHdlSome\x20(1) <#
sHdlSome\x20(1) =#
b10 >#
b100 ?#
b11 @#
sHdlNone\x20(0) A#
sHdlNone\x20(0) B#
b10 C#
b100 D#
b11 E#
sHdlNone\x20(0) F#
sHdlSome\x20(1) G#
b10 H#
b100 I#
b11 J#
sHdlSome\x20(1) K#
sHdlNone\x20(0) L#
b10 M#
b100 N#
b11 O#
sHdlSome\x20(1) P#
sHdlSome\x20(1) Q#
$end
#1000000
b1001 *
b1101000000000000000000 +
b1001 9
b1101000000000000000000 :
b1001 H
b1101000000000000000000 I
b1001 T
b1101000000000000000000 U
b1001 _
b1101000000000000000000 `
b1001 i
b1101000000000000000000 j
b111100011001000001001000110100 \"
#2000000
b0 (
b1101000000000000000100 +
11
b0 7
b1101000000000000000100 :
1@
b0 F
b1101000000000000000100 I
b1000 L
b0 R
b1101000000000000000100 U
b0 ]
b1101000000000000000100 `
b0 g
b1101000000000000000100 j
b1001100011110100001001000000100 \"
b1001000000100 `"
b11010 a"
b111010 c"
b1001000000100 d"
b11010 e"
b111010 g"
b11010 j"
b11010 m"
b11010 r"
b11010 w"
b11010 |"
b1001000000100 "#
b11010 ##
b1001000000100 &#
b11010 '#
b11010 +#
b11010 0#
b11010 5#
b11010 :#
b11010 ?#
b11010 D#
b11010 I#
b11010 N#
#3000000
sAddSub\x20(0) "
sHdlSome\x20(1) '
b100100 (
b100101 )
b0 *
b0 +
01
sHdlSome\x20(1) 6
b100100 7
b100101 8
b0 9
b0 :
0@
sHdlSome\x20(1) E
b100100 F
b100101 G
b0 H
b0 I
b0 L
b0 M
sHdlSome\x20(1) Q
b100100 R
b100101 S
b0 T
b0 U
sLoad\x20(0) W
sHdlSome\x20(1) \
b100100 ]
b100101 ^
b0 _
b0 `
sHdlSome\x20(1) f
b100100 g
b100101 h
b0 i
b0 j
b1111100011001000010101000010101 \"
b10101000010101 `"
b100 a"
b100100 c"
b10101000010101 d"
b100 e"
b100100 g"
1h"
b10101000 i"
b100 j"
b101 l"
b100 m"
b101 q"
b100 r"
b101 v"
b100 w"
b101 {"
b100 |"
b10101000010101 "#
b100 ##
b10101000010101 &#
b100 '#
b101 *#
b100 +#
b101 /#
b100 0#
b101 4#
b100 5#
b101 9#
b100 :#
b101 >#
b100 ?#
b101 C#
b100 D#
b101 H#
b100 I#
b101 M#
b100 N#
#4000000
sAddSubI\x20(1) "
b100 %
b0 )
b1001000110100 +
b100 4
b0 8
b1001000110100 :
b100 C
b0 G
b1001000110100 I
b1 M
b100 O
b0 S
b1001000110100 U
sStore\x20(1) W
b100 Z
b0 ^
b1001000110100 `
b100 d
b0 h
b1001000110100 j
b110100011001000001001000110100 \"
b1001000110100 `"
b1001000110100 d"
0h"
b1001000 i"
b10 l"
b10 q"
b10 v"
b10 {"
b1001000110100 "#
b1001000110100 &#
b10 *#
b10 /#
b10 4#
b10 9#
b10 >#
b10 C#
b10 H#
b10 M#
#5000000
sAddSub\x20(0) "
b100101 )
b0 +
b100101 8
b0 :
b100101 G
b0 I
b0 M
b100101 S
b0 U
sLoad\x20(0) W
b100101 ^
b0 `
b100101 h
b0 j
b1111100011001000010100000010101 \"
b10100000010101 `"
b10100000010101 d"
1h"
b10100000 i"
b101 l"
b101 q"
b101 v"
b101 {"
b10100000010101 "#
b10100000010101 &#
b101 *#
b101 /#
b101 4#
b101 9#
b101 >#
b101 C#
b101 H#
b101 M#
#6000000

View file

@ -75,10 +75,10 @@ fn test_cases() -> Vec<TestCase> {
0x38641234,
None,
AddSubMOp::add_sub_i(
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_GPR_REG_NUMS.start + 3], &[]),
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
[
(MOpRegNum::POWER_ISA_GPR_REG_NUMS.start + 4).cast_to_static::<UInt<_>>(),
MOpRegNum::CONST_ZERO_REG_NUM.cast_to_static::<UInt<_>>(),
MOpRegNum::power_isa_gpr_reg(4_hdl_u5).value,
MOpRegNum::const_zero().value,
],
0x1234.cast_to_static::<SInt<_>>(),
#[hdl(sim)]
@ -89,6 +89,115 @@ fn test_cases() -> Vec<TestCase> {
false,
),
));
retval.push(insn_single(
"addis 3, 4, 0x1234",
0x3C641234,
None,
AddSubMOp::add_sub_i(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
[
MOpRegNum::power_isa_gpr_reg(4_hdl_u5).value,
MOpRegNum::const_zero().value,
],
0x12340000.cast_to_static::<SInt<_>>(),
#[hdl(sim)]
OutputIntegerMode::Full64(),
false,
false,
false,
false,
),
));
retval.push(insn_single(
"addpcis 3, 0x1234",
0x4c7a1204,
None,
AddSubMOp::add_sub_i(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
[MOpRegNum::const_zero().value; _],
0x12340004.cast_to_static::<SInt<_>>(),
#[hdl(sim)]
OutputIntegerMode::Full64(),
false,
false,
false,
true,
),
));
retval.push(insn_single(
"add. 3, 4, 5",
0x7c642a15,
None,
AddSubMOp::add_sub(
MOpDestReg::new_sim(
&[MOpRegNum::power_isa_gpr_reg_num(3)],
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
),
[
MOpRegNum::power_isa_gpr_reg(4_hdl_u5).value,
MOpRegNum::power_isa_gpr_reg(5_hdl_u5).value,
MOpRegNum::const_zero().value,
],
0.cast_to_static::<SInt<_>>(),
#[hdl(sim)]
OutputIntegerMode::Full64(),
false,
false,
false,
false,
),
));
retval.push(insn_single(
"addic. 3, 4, 0x1234",
0x34641234,
None,
AddSubMOp::add_sub_i(
MOpDestReg::new_sim(
&[
MOpRegNum::power_isa_gpr_reg_num(3),
MOpRegNum::POWER_ISA_XER_CA_CA32_REG_NUM,
],
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
),
[
MOpRegNum::power_isa_gpr_reg(4_hdl_u5).value,
MOpRegNum::const_zero().value,
],
0x1234.cast_to_static::<SInt<_>>(),
#[hdl(sim)]
OutputIntegerMode::Full64(),
false,
false,
false,
false,
),
));
retval.push(insn_single(
"addc. 3, 4, 5",
0x7c642815,
None,
AddSubMOp::add_sub(
MOpDestReg::new_sim(
&[
MOpRegNum::power_isa_gpr_reg_num(3),
MOpRegNum::POWER_ISA_XER_CA_CA32_REG_NUM,
],
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
),
[
MOpRegNum::power_isa_gpr_reg(4_hdl_u5).value,
MOpRegNum::power_isa_gpr_reg(5_hdl_u5).value,
MOpRegNum::const_zero().value,
],
0.cast_to_static::<SInt<_>>(),
#[hdl(sim)]
OutputIntegerMode::Full64(),
false,
false,
false,
false,
),
));
retval
}