forked from libre-chip/cpu
decode exts[bhw][.] and pnop
This commit is contained in:
parent
aa85ecab01
commit
1fc56e02f9
3 changed files with 7586 additions and 54709 deletions
|
|
@ -1121,6 +1121,44 @@ impl DecodeState {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
/// for `extsb[.]/extsh[.]/extsw[.]`
|
||||||
|
#[hdl]
|
||||||
|
fn decode_extsb_extsh_extsw(&mut self) {
|
||||||
|
assert_eq!(self.arguments, Some("RA,RS"));
|
||||||
|
let output_integer_mode = match self.mnemonic.trim_end_matches('.') {
|
||||||
|
"extsb" => OutputIntegerMode.SignExt8(),
|
||||||
|
"extsh" => OutputIntegerMode.SignExt16(),
|
||||||
|
"extsw" => OutputIntegerMode.SignExt32(),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
self.decode_scope(|this, (FieldRA(ra), FieldRS(rs), FieldRc(rc))| {
|
||||||
|
// TODO: handle SO propagation
|
||||||
|
connect(
|
||||||
|
ArrayVec::len(this.output),
|
||||||
|
1usize.cast_to_static::<Length<_>>(),
|
||||||
|
);
|
||||||
|
connect(
|
||||||
|
this.output[0],
|
||||||
|
LogicalMOp::logical_i(
|
||||||
|
MOpDestReg::new([gpr(ra)], [(MOpRegNum::POWER_ISA_CR_0_REG_NUM, rc)]),
|
||||||
|
[gpr(rs).value],
|
||||||
|
0.cast_to_static::<SInt<_>>(),
|
||||||
|
output_integer_mode,
|
||||||
|
LogicalMOp::lut_from_fn(|[a, b]| a | b),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/// for `pnop`
|
||||||
|
#[hdl]
|
||||||
|
fn decode_pnop(&mut self) {
|
||||||
|
self.decode_scope(|this, ()| {
|
||||||
|
connect(
|
||||||
|
ArrayVec::len(this.output),
|
||||||
|
0usize.cast_to_static::<Length<_>>(),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type DecodeFn = fn(&mut DecodeState);
|
type DecodeFn = fn(&mut DecodeState);
|
||||||
|
|
@ -1287,9 +1325,10 @@ const DECODE_FNS: &[(&[&str], DecodeFn)] = &[
|
||||||
],
|
],
|
||||||
DecodeState::decode_and_xor_nand_or_orc_nor_eqv_andc,
|
DecodeState::decode_and_xor_nand_or_orc_nor_eqv_andc,
|
||||||
),
|
),
|
||||||
(&["extsb", "extsb.", "extsh", "extsh."], |_state| {
|
(
|
||||||
// TODO
|
&["extsb", "extsb.", "extsh", "extsh.", "extsw", "extsw."],
|
||||||
}),
|
DecodeState::decode_extsb_extsh_extsw,
|
||||||
|
),
|
||||||
(&["cmpb"], |_state| {
|
(&["cmpb"], |_state| {
|
||||||
// TODO
|
// TODO
|
||||||
}),
|
}),
|
||||||
|
|
@ -1303,9 +1342,6 @@ const DECODE_FNS: &[(&[&str], DecodeFn)] = &[
|
||||||
// TODO
|
// TODO
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
(&["extsw", "extsw."], |_state| {
|
|
||||||
// TODO
|
|
||||||
}),
|
|
||||||
(
|
(
|
||||||
&[
|
&[
|
||||||
"rlwinm", "rlwinm.", "rlwnm", "rlwnm.", "rlwimi", "rlwimi.", "rldicl", "rldicl.",
|
"rlwinm", "rlwinm.", "rlwnm", "rlwnm.", "rlwimi", "rlwimi.", "rldicl", "rldicl.",
|
||||||
|
|
@ -1360,9 +1396,7 @@ const DECODE_FNS: &[(&[&str], DecodeFn)] = &[
|
||||||
// TODO
|
// TODO
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
(&["pnop"], |_state| {
|
(&["pnop"], DecodeState::decode_pnop),
|
||||||
// TODO
|
|
||||||
}),
|
|
||||||
(FP_MNEMONICS, |_state| {
|
(FP_MNEMONICS, |_state| {
|
||||||
// TODO(FP)
|
// TODO(FP)
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -842,6 +842,71 @@ fn test_cases() -> Vec<TestCase> {
|
||||||
0x7c832879;
|
0x7c832879;
|
||||||
|[a, b]| a & !b;
|
|[a, b]| a & !b;
|
||||||
}
|
}
|
||||||
|
macro_rules! insn_exts {
|
||||||
|
(
|
||||||
|
$mnemonic:literal $dest:literal, $src:literal;
|
||||||
|
$encoding:literal;
|
||||||
|
$OutputIntegerMode:ident;
|
||||||
|
) => {
|
||||||
|
retval.push(insn_single(
|
||||||
|
concat!($mnemonic, " ", stringify!($dest), ", ", stringify!($src)),
|
||||||
|
$encoding,
|
||||||
|
None,
|
||||||
|
LogicalMOp::logical_i(
|
||||||
|
MOpDestReg::new_sim(
|
||||||
|
&[MOpRegNum::power_isa_gpr_reg_num($dest)],
|
||||||
|
if $mnemonic.contains('.') {
|
||||||
|
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM]
|
||||||
|
} else {
|
||||||
|
&[]
|
||||||
|
},
|
||||||
|
),
|
||||||
|
[MOpRegNum::power_isa_gpr_reg_imm($src).value],
|
||||||
|
0.cast_to_static::<SInt<_>>(),
|
||||||
|
OutputIntegerMode.$OutputIntegerMode(),
|
||||||
|
LogicalMOp::lut_from_fn(|[a, b]| a | b),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
insn_exts! {
|
||||||
|
"extsb" 3, 4;
|
||||||
|
0x7c830774;
|
||||||
|
SignExt8;
|
||||||
|
}
|
||||||
|
insn_exts! {
|
||||||
|
"extsb." 3, 4;
|
||||||
|
0x7c830775;
|
||||||
|
SignExt8;
|
||||||
|
}
|
||||||
|
insn_exts! {
|
||||||
|
"extsh" 3, 4;
|
||||||
|
0x7c830734;
|
||||||
|
SignExt16;
|
||||||
|
}
|
||||||
|
insn_exts! {
|
||||||
|
"extsh." 3, 4;
|
||||||
|
0x7c830735;
|
||||||
|
SignExt16;
|
||||||
|
}
|
||||||
|
insn_exts! {
|
||||||
|
"extsw" 3, 4;
|
||||||
|
0x7c8307b4;
|
||||||
|
SignExt32;
|
||||||
|
}
|
||||||
|
insn_exts! {
|
||||||
|
"extsw." 3, 4;
|
||||||
|
0x7c8307b5;
|
||||||
|
SignExt32;
|
||||||
|
}
|
||||||
|
// ensure pnop decodes to zero instructions
|
||||||
|
retval.push(insn_empty(
|
||||||
|
// LLVM doesn't support the pnop instruction:
|
||||||
|
// https://github.com/llvm/llvm-project/issues/176831
|
||||||
|
".long 0x07000000, 0 # pnop",
|
||||||
|
0x07000000,
|
||||||
|
Some(0),
|
||||||
|
));
|
||||||
retval
|
retval
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -900,6 +965,24 @@ fn test_test_cases_assembly() -> std::io::Result<()> {
|
||||||
let Some(line) = lines.next() else {
|
let Some(line) = lines.next() else {
|
||||||
panic!("output missing line for: {test_case:?}");
|
panic!("output missing line for: {test_case:?}");
|
||||||
};
|
};
|
||||||
|
if line.starts_with("\t.long") {
|
||||||
|
assert_eq!(
|
||||||
|
line,
|
||||||
|
format!("\t.long\t{first_input}"),
|
||||||
|
"test_case={test_case:?}\nline:\n{line}"
|
||||||
|
);
|
||||||
|
if let Some(second_input) = second_input {
|
||||||
|
let Some(line) = lines.next() else {
|
||||||
|
panic!("output missing line for: {test_case:?}");
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
line,
|
||||||
|
format!("\t.long\t{second_input}"),
|
||||||
|
"test_case={test_case:?}\nline:\n{line}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let Some((_, comment)) = line.split_once('#') else {
|
let Some((_, comment)) = line.split_once('#') else {
|
||||||
panic!("output line missing comment. test_case={test_case:?}\nline:\n{line}");
|
panic!("output line missing comment. test_case={test_case:?}\nline:\n{line}");
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue