Support branch prediction bits, more bd mnemonics, more rlwinm mnemonics
This commit is contained in:
parent
20abce13e4
commit
4d8e473331
|
@ -7,7 +7,7 @@ pub struct FormattedIns(pub Ins);
|
||||||
impl Display for FormattedIns {
|
impl Display for FormattedIns {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
let simple = self.0.clone().simplified();
|
let simple = self.0.clone().simplified();
|
||||||
write!(f, "{}{}", simple.mnemonic, simple.ins.suffix())?;
|
write!(f, "{}{}", simple.mnemonic, simple.suffix)?;
|
||||||
let mut writing_offset = false;
|
let mut writing_offset = false;
|
||||||
for (i, arg) in simple.args.iter().enumerate() {
|
for (i, arg) in simple.args.iter().enumerate() {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -215,8 +215,6 @@ impl Display for Bit {
|
||||||
// Unsigned opaque argument.
|
// Unsigned opaque argument.
|
||||||
field_arg!(OpaqueU, u32);
|
field_arg!(OpaqueU, u32);
|
||||||
|
|
||||||
const SPR_LR: usize = 16;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Argument {
|
pub enum Argument {
|
||||||
GPR(GPR),
|
GPR(GPR),
|
||||||
|
@ -373,12 +371,10 @@ impl Ins {
|
||||||
self.branch_offset().and_then(|offset| {
|
self.branch_offset().and_then(|offset| {
|
||||||
if self.field_AA() {
|
if self.field_AA() {
|
||||||
Some(offset as u32)
|
Some(offset as u32)
|
||||||
|
} else if offset < 0 {
|
||||||
|
self.addr.checked_sub((-offset) as u32)
|
||||||
} else {
|
} else {
|
||||||
if offset < 0 {
|
self.addr.checked_add(offset as u32)
|
||||||
self.addr.checked_sub((-offset) as u32)
|
|
||||||
} else {
|
|
||||||
self.addr.checked_add(offset as u32)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -419,12 +415,13 @@ impl Ins {
|
||||||
pub struct SimplifiedIns {
|
pub struct SimplifiedIns {
|
||||||
pub ins: Ins,
|
pub ins: Ins,
|
||||||
pub mnemonic: &'static str,
|
pub mnemonic: &'static str,
|
||||||
|
pub suffix: String,
|
||||||
pub args: Vec<Argument>,
|
pub args: Vec<Argument>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for SimplifiedIns {
|
impl Display for SimplifiedIns {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "{}{} ", self.mnemonic, self.ins.suffix())?;
|
write!(f, "{}{} ", self.mnemonic, self.suffix)?;
|
||||||
let mut writing_offset = false;
|
let mut writing_offset = false;
|
||||||
for (i, argument) in self.args.iter().enumerate() {
|
for (i, argument) in self.args.iter().enumerate() {
|
||||||
write!(f, "{}", argument)?;
|
write!(f, "{}", argument)?;
|
||||||
|
@ -449,6 +446,7 @@ impl SimplifiedIns {
|
||||||
pub(crate) fn basic_form(ins: Ins) -> Self {
|
pub(crate) fn basic_form(ins: Ins) -> Self {
|
||||||
Self {
|
Self {
|
||||||
mnemonic: ins.op.mnemonic(),
|
mnemonic: ins.op.mnemonic(),
|
||||||
|
suffix: ins.suffix(),
|
||||||
args: ins
|
args: ins
|
||||||
.fields()
|
.fields()
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
@ -95,6 +95,7 @@ fn test_ins_b() {
|
||||||
assert_asm!(0x4BE03C99, "bl -0x1fc368");
|
assert_asm!(0x4BE03C99, "bl -0x1fc368");
|
||||||
assert_asm!(0x4BDC1A59, "bl -0x23e5a8");
|
assert_asm!(0x4BDC1A59, "bl -0x23e5a8");
|
||||||
assert_asm!(0x48000063, "bla 0x60");
|
assert_asm!(0x48000063, "bla 0x60");
|
||||||
|
assert_asm!(0x48000002, "ba 0x0");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -121,18 +122,29 @@ fn test_ins_bc() {
|
||||||
assert_asm!(0x418502E4, "bgt cr1, 0x2e4");
|
assert_asm!(0x418502E4, "bgt cr1, 0x2e4");
|
||||||
assert_asm!(0x419A0138, "beq cr6, 0x138");
|
assert_asm!(0x419A0138, "beq cr6, 0x138");
|
||||||
assert_asm!(0x419C0008, "blt cr7, 0x8");
|
assert_asm!(0x419C0008, "blt cr7, 0x8");
|
||||||
|
assert_asm!(0x4240FFF0, "bdz -0x10");
|
||||||
assert_asm!(0x4200F560, "bdnz -0xaa0");
|
assert_asm!(0x4200F560, "bdnz -0xaa0");
|
||||||
|
assert_asm!(0x40010014, "bdnzf gt, 0x14");
|
||||||
|
assert_asm!(0x40410035, "bdzfl gt, 0x34");
|
||||||
|
assert_asm!(0x41430023, "bdztla so, 0x20");
|
||||||
|
assert_asm!(0x4108FFE3, "bdnztla 4*cr2+lt, -0x20");
|
||||||
|
assert_asm!(0x40A20008, "bne+ 0x8");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ins_bcctr() {
|
fn test_ins_bcctr() {
|
||||||
assert_asm!(0x4E800420, "bctr");
|
assert_asm!(0x4E800420, "bctr");
|
||||||
assert_asm!(0x4E800421, "bctrl");
|
assert_asm!(0x4E800421, "bctrl");
|
||||||
|
assert_asm!(0x4D820420, "beqctr");
|
||||||
|
assert_asm!(0x4D8D0421, "bgtctrl cr3");
|
||||||
|
assert_asm!(0x4DA20420, "beqctr+");
|
||||||
|
assert_asm!(0x4DB90421, "bgtctrl+ cr6");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ins_bclr() {
|
fn test_ins_bclr() {
|
||||||
assert_asm!(0x4C800020, "bgelr");
|
assert_asm!(0x4C800020, "bgelr");
|
||||||
|
assert_asm!(0x4CA00020, "bgelr+");
|
||||||
assert_asm!(0x4C810020, "blelr");
|
assert_asm!(0x4C810020, "blelr");
|
||||||
assert_asm!(0x4C820020, "bnelr");
|
assert_asm!(0x4C820020, "bnelr");
|
||||||
assert_asm!(0x4C9E0020, "bnelr cr7");
|
assert_asm!(0x4C9E0020, "bnelr cr7");
|
||||||
|
@ -142,6 +154,8 @@ fn test_ins_bclr() {
|
||||||
assert_asm!(0x4D860020, "beqlr cr1");
|
assert_asm!(0x4D860020, "beqlr cr1");
|
||||||
assert_asm!(0x4E800020, "blr");
|
assert_asm!(0x4E800020, "blr");
|
||||||
assert_asm!(0x4E800021, "blrl");
|
assert_asm!(0x4E800021, "blrl");
|
||||||
|
assert_asm!(0x4D000020, "bdnztlr lt");
|
||||||
|
assert_asm!(0x4C1F0021, "bdnzflrl 4*cr7+so");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -171,9 +185,46 @@ fn test_ins_cntlzw() {
|
||||||
assert_asm!(0x7C030034, "cntlzw r3, r0");
|
assert_asm!(0x7C030034, "cntlzw r3, r0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ins_crand() {
|
||||||
|
assert_asm!(0x4C853202, "crand 4*cr1+lt, 4*cr1+gt, 4*cr1+eq");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ins_crandc() {
|
||||||
|
assert_asm!(0x4C642902, "crandc so, 4*cr1+lt, 4*cr1+gt");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ins_creqv() {
|
||||||
|
assert_asm!(0x4CE00A42, "creqv 4*cr1+so, lt, gt");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ins_crnand() {
|
||||||
|
assert_asm!(0x4C2219C2, "crnand gt, eq, so");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ins_cror() {
|
fn test_ins_cror() {
|
||||||
assert_asm!(0x4C411382, "cror eq, gt, eq");
|
assert_asm!(0x4C411382, "cror eq, gt, eq");
|
||||||
|
assert_asm!(0x4CA63B82, "cror 4*cr1+gt, 4*cr1+eq, 4*cr1+so");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ins_crorc() {
|
||||||
|
assert_asm!(0x4C432342, "crorc eq, so, 4*cr1+lt");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ins_crnor() {
|
||||||
|
assert_asm!(0x4C011042, "crnor lt, gt, eq");
|
||||||
|
assert_asm!(0x4CA63042, "crnot 4*cr1+gt, 4*cr1+eq");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ins_crxor() {
|
||||||
|
assert_asm!(0x4CC70182, "crxor 4*cr1+eq, 4*cr1+so, lt");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -634,7 +685,7 @@ fn test_ins_psq_lx() {
|
||||||
rA(GPR(0)),
|
rA(GPR(0)),
|
||||||
rB(GPR(0)),
|
rB(GPR(0)),
|
||||||
ps_WX(OpaqueU(0)),
|
ps_WX(OpaqueU(0)),
|
||||||
ps_IX(GQR(0))
|
ps_IX(GQR(0)),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
assert_eq!(ins.defs(), vec![frD(FPR(0))]);
|
assert_eq!(ins.defs(), vec![frD(FPR(0))]);
|
||||||
|
@ -802,12 +853,22 @@ fn test_ins_rlwinm() {
|
||||||
|
|
||||||
// mnemonics
|
// mnemonics
|
||||||
assert_asm!(0x57E5103A, "slwi r5, r31, 2");
|
assert_asm!(0x57E5103A, "slwi r5, r31, 2");
|
||||||
|
assert_asm!(0x54832026, "extlwi r3, r4, 20, 4");
|
||||||
|
assert_asm!(0x5483AB3E, "extrwi r3, r4, 20, 1");
|
||||||
|
assert_asm!(0x540027BE, "extrwi r0, r0, 2, 2");
|
||||||
|
assert_asm!(0x54839B3E, "rlwinm r3, r4, 19, 12, 31");
|
||||||
|
assert_asm!(0x5483203E, "rotlwi r3, r4, 4");
|
||||||
|
assert_asm!(0x5483E03E, "rotrwi r3, r4, 4");
|
||||||
|
assert_asm!(0x5464043E, "clrlwi r4, r3, 16");
|
||||||
|
assert_asm!(0x54830036, "clrrwi r3, r4, 4");
|
||||||
|
assert_asm!(0x54640fbc, "clrlslwi r4, r3, 31, 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ins_rlwnm() {
|
fn test_ins_rlwnm() {
|
||||||
assert_asm!(0x5D6A67FE, "rlwnm r10, r11, r12, 31, 31");
|
assert_asm!(0x5D6A67FE, "rlwnm r10, r11, r12, 31, 31");
|
||||||
assert_asm!(0x5FC52EFE, "rlwnm r5, r30, r5, 27, 31");
|
assert_asm!(0x5FC52EFE, "rlwnm r5, r30, r5, 27, 31");
|
||||||
|
assert_asm!(0x5FC5283F, "rotlw. r5, r30, r5");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -205,12 +205,9 @@ impl From<&DolHeaderData> for DolHeader {
|
||||||
|
|
||||||
impl DolHeader {
|
impl DolHeader {
|
||||||
pub fn section_at(&self, addr: u32) -> Option<&DolSection> {
|
pub fn section_at(&self, addr: u32) -> Option<&DolSection> {
|
||||||
for section in &self.sections {
|
self.sections.iter()
|
||||||
if (section.target..(section.target + section.size)).contains(&addr) {
|
.find(|§ion| (section.target..(section.target + section.size))
|
||||||
return Some(section);
|
.contains(&addr))
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ use std::process::{Command, Stdio};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use proc_macro2::{Ident, Literal, Span, TokenStream, TokenTree};
|
use proc_macro2::{Group, Ident, Literal, Span, TokenStream, TokenTree};
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use serde::{Deserialize, Deserializer};
|
use serde::{Deserialize, Deserializer};
|
||||||
use syn::{LitChar, LitInt, LitStr};
|
use syn::{LitChar, LitInt, LitStr};
|
||||||
|
@ -74,8 +74,8 @@ pub(crate) struct BitRange(Range<u8>);
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for BitRange {
|
impl<'de> Deserialize<'de> for BitRange {
|
||||||
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
let range_str: String = Deserialize::deserialize(deserializer)?;
|
let range_str: String = Deserialize::deserialize(deserializer)?;
|
||||||
if let Some((start_str, stop_str)) = range_str.split_once("..") {
|
if let Some((start_str, stop_str)) = range_str.split_once("..") {
|
||||||
|
@ -232,7 +232,8 @@ impl Opcode {
|
||||||
pub(crate) struct Mnemonic {
|
pub(crate) struct Mnemonic {
|
||||||
name: String,
|
name: String,
|
||||||
opcode: String,
|
opcode: String,
|
||||||
modifiers: Vec<String>,
|
// Overrides modifier list from opcode
|
||||||
|
modifiers: Option<Vec<String>>,
|
||||||
args: Vec<String>,
|
args: Vec<String>,
|
||||||
condition: String,
|
condition: String,
|
||||||
}
|
}
|
||||||
|
@ -243,23 +244,31 @@ pub(crate) struct Modifier {
|
||||||
name: String,
|
name: String,
|
||||||
suffix: char,
|
suffix: char,
|
||||||
bit: u8,
|
bit: u8,
|
||||||
|
condition: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Modifier {
|
impl Modifier {
|
||||||
fn express_value_self(&self) -> TokenStream {
|
fn express_value_self(&self, field_by_name: &HashMap<String, &Field>) -> Result<TokenStream> {
|
||||||
let modifier_bit = self.bit as usize;
|
if self.condition.is_empty() {
|
||||||
quote!(self.bit(#modifier_bit))
|
let modifier_bit = self.bit as usize;
|
||||||
|
Ok(quote!(self.bit(#modifier_bit)))
|
||||||
|
} else {
|
||||||
|
compile_mnemonic_condition(
|
||||||
|
field_by_name,
|
||||||
|
&self.condition,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn construct_accessor(&self) -> TokenStream {
|
fn construct_accessor(&self, field_by_name: &HashMap<String, &Field>) -> Result<TokenStream> {
|
||||||
let field_variant = to_rust_ident("field_", &self.name);
|
let field_variant = to_rust_ident("field_", &self.name);
|
||||||
let value = self.express_value_self();
|
let value = self.express_value_self(field_by_name)?;
|
||||||
quote! {
|
Ok(quote! {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn #field_variant(&self) -> bool {
|
pub fn #field_variant(&self) -> bool {
|
||||||
#value
|
#value
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -482,7 +491,7 @@ impl Isa {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Generate modifiers.
|
// Generate modifiers.
|
||||||
let suffix = express_suffix(&modifier_by_name, opcode)?;
|
let suffix = express_suffix(&modifier_by_name, &field_by_name, &opcode.modifiers)?;
|
||||||
suffix_match_arms.push(quote! {
|
suffix_match_arms.push(quote! {
|
||||||
Opcode::#ident => #suffix,
|
Opcode::#ident => #suffix,
|
||||||
});
|
});
|
||||||
|
@ -556,21 +565,29 @@ impl Isa {
|
||||||
)?);
|
)?);
|
||||||
// Emit branch.
|
// Emit branch.
|
||||||
let mnemonic_lit = LitStr::new(&mnemonic.name, Span::call_site());
|
let mnemonic_lit = LitStr::new(&mnemonic.name, Span::call_site());
|
||||||
|
// Emit suffix.
|
||||||
|
let modifiers = mnemonic.modifiers.as_ref().unwrap_or(&opcode.modifiers);
|
||||||
|
let suffix = express_suffix(&modifier_by_name, &field_by_name, modifiers)?;
|
||||||
// Extract arguments.
|
// Extract arguments.
|
||||||
let mut args = Vec::new();
|
let mut args = Vec::new();
|
||||||
for arg in &mnemonic.args {
|
for arg in &mnemonic.args {
|
||||||
|
let (field_name, expression) = arg.split_once('=').unwrap_or((arg, arg));
|
||||||
let field = field_by_name
|
let field = field_by_name
|
||||||
.get(arg)
|
.get(field_name)
|
||||||
.unwrap_or_else(|| panic!("field not found: {}", arg));
|
.unwrap_or_else(|| panic!("field not found: {}", arg));
|
||||||
let variant = Ident::new(field.arg.as_ref().unwrap(), Span::call_site());
|
let variant = Ident::new(field.arg.as_ref().unwrap(), Span::call_site());
|
||||||
let value = field.express_value_self();
|
let value = compile_mnemonic_condition(
|
||||||
args.push(quote!(Argument::#variant(#variant(#value as _)),));
|
&field_by_name,
|
||||||
|
expression,
|
||||||
|
)?;
|
||||||
|
args.push(quote!(Argument::#variant(#variant((#value) as _)),));
|
||||||
}
|
}
|
||||||
let args = token_stream!(args);
|
let args = token_stream!(args);
|
||||||
simplified_conditions.push(quote! {
|
simplified_conditions.push(quote! {
|
||||||
{
|
{
|
||||||
return SimplifiedIns {
|
return SimplifiedIns {
|
||||||
mnemonic: #mnemonic_lit,
|
mnemonic: #mnemonic_lit,
|
||||||
|
suffix: #suffix,
|
||||||
args: vec![#args],
|
args: vec![#args],
|
||||||
ins: self,
|
ins: self,
|
||||||
};
|
};
|
||||||
|
@ -592,11 +609,10 @@ impl Isa {
|
||||||
let simplified_ins_match_arms = token_stream!(simplified_ins_match_arms);
|
let simplified_ins_match_arms = token_stream!(simplified_ins_match_arms);
|
||||||
let field_accessors =
|
let field_accessors =
|
||||||
TokenStream::from_iter(self.fields.iter().map(|field| field.construct_accessor()));
|
TokenStream::from_iter(self.fields.iter().map(|field| field.construct_accessor()));
|
||||||
let modifier_accessors = TokenStream::from_iter(
|
let modifiers: Vec<TokenStream> = self.modifiers
|
||||||
self.modifiers
|
.iter()
|
||||||
.iter()
|
.map(|modifier| modifier.construct_accessor(&field_by_name)).try_collect()?;
|
||||||
.map(|modifier| modifier.construct_accessor()),
|
let modifier_accessors = TokenStream::from_iter(modifiers);
|
||||||
);
|
|
||||||
// Generate final fields function.
|
// Generate final fields function.
|
||||||
let ins_impl = quote! {
|
let ins_impl = quote! {
|
||||||
#[allow(clippy::all, unused_mut)]
|
#[allow(clippy::all, unused_mut)]
|
||||||
|
@ -701,31 +717,41 @@ fn compile_mnemonic_condition(
|
||||||
code: &str,
|
code: &str,
|
||||||
) -> Result<TokenStream> {
|
) -> Result<TokenStream> {
|
||||||
let src_stream = TokenStream::from_str(code)?;
|
let src_stream = TokenStream::from_str(code)?;
|
||||||
let token_iter = src_stream.into_iter().flat_map(|token| {
|
fn map_ident(field_by_name: &HashMap<String, &Field>, token: TokenTree) -> TokenStream {
|
||||||
if let TokenTree::Ident(ref ident) = token {
|
match token {
|
||||||
if let Some(field) = field_by_name.get(&ident.to_string()) {
|
TokenTree::Ident(ref ident) => {
|
||||||
return field.express_value_self();
|
if let Some(field) = field_by_name.get(&ident.to_string()) {
|
||||||
|
return field.express_value_self();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
TokenTree::Group(ref group) => {
|
||||||
|
let iter = group.stream().into_iter().flat_map(|token| map_ident(field_by_name, token));
|
||||||
|
let stream = TokenStream::from_iter(iter);
|
||||||
|
return TokenStream::from(TokenTree::Group(Group::new(group.delimiter(), stream)));
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
token.into()
|
token.into()
|
||||||
});
|
}
|
||||||
|
let token_iter = src_stream.into_iter().flat_map(|token| map_ident(field_by_name, token));
|
||||||
Ok(TokenStream::from_iter(token_iter))
|
Ok(TokenStream::from_iter(token_iter))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn express_suffix(
|
fn express_suffix(
|
||||||
modifier_by_name: &HashMap<String, &Modifier>,
|
modifier_by_name: &HashMap<String, &Modifier>,
|
||||||
opcode: &Opcode,
|
field_by_name: &HashMap<String, &Field>,
|
||||||
|
modifiers: &[String],
|
||||||
) -> Result<TokenStream> {
|
) -> Result<TokenStream> {
|
||||||
Ok(if opcode.modifiers.is_empty() {
|
Ok(if modifiers.is_empty() {
|
||||||
quote!(String::new())
|
quote!(String::new())
|
||||||
} else {
|
} else {
|
||||||
let mut chars = Vec::new();
|
let mut chars = Vec::new();
|
||||||
for mod_name in &opcode.modifiers {
|
for mod_name in modifiers {
|
||||||
let modifier: &Modifier = modifier_by_name
|
let modifier: &Modifier = modifier_by_name
|
||||||
.get(mod_name)
|
.get(mod_name)
|
||||||
.ok_or_else(|| Error::from(format!("undefined modifier {}", mod_name)))?;
|
.ok_or_else(|| Error::from(format!("undefined modifier {}", mod_name)))?;
|
||||||
let lit_char = LitChar::new(modifier.suffix, Span::call_site());
|
let lit_char = LitChar::new(modifier.suffix, Span::call_site());
|
||||||
let modifier_bit = modifier.express_value_self();
|
let modifier_bit = modifier.express_value_self(field_by_name)?;
|
||||||
chars.push(quote! {
|
chars.push(quote! {
|
||||||
if #modifier_bit {
|
if #modifier_bit {
|
||||||
s.push(#lit_char);
|
s.push(#lit_char);
|
||||||
|
|
261
isa.yaml
261
isa.yaml
|
@ -20,7 +20,7 @@ fields:
|
||||||
arg: OpaqueU
|
arg: OpaqueU
|
||||||
bits: 6..11
|
bits: 6..11
|
||||||
- name: BI
|
- name: BI
|
||||||
arg: OpaqueU
|
arg: CRBit
|
||||||
bits: 11..16
|
bits: 11..16
|
||||||
- name: BH
|
- name: BH
|
||||||
arg: OpaqueU
|
arg: OpaqueU
|
||||||
|
@ -175,6 +175,18 @@ modifiers:
|
||||||
- name: AA
|
- name: AA
|
||||||
suffix: a
|
suffix: a
|
||||||
bit: 30
|
bit: 30
|
||||||
|
# Predict branch to be taken
|
||||||
|
- name: BP
|
||||||
|
suffix: +
|
||||||
|
condition: BO & 1 == 1 && BD >= 0
|
||||||
|
# Predict branch not to be taken (fall through)
|
||||||
|
- name: BNP
|
||||||
|
suffix: '-'
|
||||||
|
condition: BO & 1 == 1 && BD < 0
|
||||||
|
# Predict branch to be taken (implicit dest for LR/CTR)
|
||||||
|
- name: BP_ND
|
||||||
|
suffix: +
|
||||||
|
condition: BO & 1 == 1
|
||||||
|
|
||||||
opcodes:
|
opcodes:
|
||||||
- name: add
|
- name: add
|
||||||
|
@ -302,14 +314,14 @@ opcodes:
|
||||||
desc: Branch Conditional
|
desc: Branch Conditional
|
||||||
bitmask: 0xfc000000
|
bitmask: 0xfc000000
|
||||||
pattern: 0x40000000
|
pattern: 0x40000000
|
||||||
modifiers: [ LK, AA ]
|
modifiers: [ LK, AA, BP, BNP ]
|
||||||
args: [ BO, BI, BD ]
|
args: [ BO, BI, BD ]
|
||||||
|
|
||||||
- name: bcctr
|
- name: bcctr
|
||||||
desc: Branch Conditional to Count Register
|
desc: Branch Conditional to Count Register
|
||||||
bitmask: 0xfc007ffe
|
bitmask: 0xfc007ffe
|
||||||
pattern: 0x4c000420
|
pattern: 0x4c000420
|
||||||
modifiers: [ LK ]
|
modifiers: [ LK, BP_ND ]
|
||||||
args: [ BO, BI, BH ]
|
args: [ BO, BI, BH ]
|
||||||
uses: [ ctr ]
|
uses: [ ctr ]
|
||||||
|
|
||||||
|
@ -317,7 +329,7 @@ opcodes:
|
||||||
desc: Branch Conditional to Link Register
|
desc: Branch Conditional to Link Register
|
||||||
bitmask: 0xfc007ffe
|
bitmask: 0xfc007ffe
|
||||||
pattern: 0x4c000020
|
pattern: 0x4c000020
|
||||||
modifiers: [ LK ]
|
modifiers: [ LK, BP_ND ]
|
||||||
args: [ BO, BI, BH ]
|
args: [ BO, BI, BH ]
|
||||||
uses: [ lr ]
|
uses: [ lr ]
|
||||||
|
|
||||||
|
@ -1974,14 +1986,34 @@ mnemonics:
|
||||||
condition: rA == 0 && rS == 0 && uimm == 0
|
condition: rA == 0 && rS == 0 && uimm == 0
|
||||||
|
|
||||||
# Rotates/Shifts
|
# Rotates/Shifts
|
||||||
|
- name: rotlw
|
||||||
|
opcode: rlwnm
|
||||||
|
args: [ rA, rS, rB ]
|
||||||
|
condition: MB == 0 && ME == 31
|
||||||
|
|
||||||
|
# TODO rlwimi: inslwi/insrwi
|
||||||
|
|
||||||
|
# Rotates/Shifts Immediate
|
||||||
|
- name: clrrwi
|
||||||
|
opcode: rlwinm
|
||||||
|
args: [ rA, rS, ME=31-ME ]
|
||||||
|
condition: SH == 0 && MB == 0 && ME < 32
|
||||||
- name: clrlwi
|
- name: clrlwi
|
||||||
opcode: rlwinm
|
opcode: rlwinm
|
||||||
args: [ rA, rS, MB ]
|
args: [ rA, rS, MB ]
|
||||||
condition: SH == 0 && ME == 31
|
condition: SH == 0 && ME == 31
|
||||||
|
- name: clrlslwi
|
||||||
|
opcode: rlwinm
|
||||||
|
args: [ rA, rS, MB=32-SH, SH ]
|
||||||
|
condition: SH < 32 && MB >= SH && ME == 31 - SH
|
||||||
- name: rotlwi
|
- name: rotlwi
|
||||||
opcode: rlwinm
|
opcode: rlwinm
|
||||||
args: [ rA, rS, SH ]
|
args: [ rA, rS, SH ]
|
||||||
condition: MB == 0 && ME == 31
|
condition: MB == 0 && ME == 31 && SH <= 16
|
||||||
|
- name: rotrwi
|
||||||
|
opcode: rlwinm
|
||||||
|
args: [ rA, rS, SH=32-SH ]
|
||||||
|
condition: MB == 0 && ME == 31 && SH > 16
|
||||||
- name: slwi
|
- name: slwi
|
||||||
opcode: rlwinm
|
opcode: rlwinm
|
||||||
args: [ rA, rS, SH ]
|
args: [ rA, rS, SH ]
|
||||||
|
@ -1990,6 +2022,14 @@ mnemonics:
|
||||||
opcode: rlwinm
|
opcode: rlwinm
|
||||||
args: [ rA, rS, MB ]
|
args: [ rA, rS, MB ]
|
||||||
condition: ME == 31 && 32 - MB == SH
|
condition: ME == 31 && 32 - MB == SH
|
||||||
|
- name: extlwi
|
||||||
|
opcode: rlwinm
|
||||||
|
args: [ rA, rS, ME=ME+1, SH ]
|
||||||
|
condition: MB == 0
|
||||||
|
- name: extrwi
|
||||||
|
opcode: rlwinm
|
||||||
|
args: [ rA, rS, MB=32-MB, SH=SH-(32-MB) ]
|
||||||
|
condition: ME == 31 && SH >= 32 - MB
|
||||||
|
|
||||||
# Compares Word
|
# Compares Word
|
||||||
- name: cmpwi
|
- name: cmpwi
|
||||||
|
@ -2070,11 +2110,11 @@ mnemonics:
|
||||||
condition: crbD == crbA && crbD == crbB
|
condition: crbD == crbA && crbD == crbB
|
||||||
- name: crmove
|
- name: crmove
|
||||||
opcode: cror
|
opcode: cror
|
||||||
args: [ crbD, crbA, crbB ]
|
args: [ crbD, crbA ]
|
||||||
condition: crbA == crbB
|
condition: crbA == crbB
|
||||||
- name: crnot
|
- name: crnot
|
||||||
opcode: crnor
|
opcode: crnor
|
||||||
args: [ crbD, crbA, crbB ]
|
args: [ crbD, crbA ]
|
||||||
condition: crbA == crbB
|
condition: crbA == crbB
|
||||||
|
|
||||||
# Misc
|
# Misc
|
||||||
|
@ -2223,111 +2263,109 @@ mnemonics:
|
||||||
condition: spr & 0b1111111001 == 537
|
condition: spr & 0b1111111001 == 537
|
||||||
|
|
||||||
# Branch Conditional
|
# Branch Conditional
|
||||||
# bc branch always
|
|
||||||
- name: b
|
|
||||||
opcode: bc
|
|
||||||
modifiers: [ LK, AA ]
|
|
||||||
condition: BO == 20 && BI == 0
|
|
||||||
# bc branch if negative
|
# bc branch if negative
|
||||||
- name: blt
|
- name: blt
|
||||||
opcode: bc
|
opcode: bc
|
||||||
modifiers: [ LK, AA ]
|
|
||||||
args: [ BD ]
|
args: [ BD ]
|
||||||
condition: BO == 12 && BI & 0b11 == 0b00 && crfS == 0
|
condition: BO & 0b11110 == 12 && BI == 0
|
||||||
- name: blt
|
- name: blt
|
||||||
opcode: bc
|
opcode: bc
|
||||||
modifiers: [ LK, AA ]
|
|
||||||
args: [ crfS, BD ]
|
args: [ crfS, BD ]
|
||||||
condition: BO == 12 && BI & 0b11 == 0b00
|
condition: BO & 0b11110 == 12 && BI & 0b11 == 0
|
||||||
# bc branch if not positive
|
# bc branch if not positive
|
||||||
- name: ble
|
- name: ble
|
||||||
opcode: bc
|
opcode: bc
|
||||||
modifiers: [ LK, AA ]
|
|
||||||
args: [ BD ]
|
args: [ BD ]
|
||||||
condition: BO == 4 && BI & 0b11 == 0b01 && crfS == 0
|
condition: BO & 0b11110 == 4 && BI == 1
|
||||||
- name: ble
|
- name: ble
|
||||||
opcode: bc
|
opcode: bc
|
||||||
modifiers: [ LK, AA ]
|
|
||||||
args: [ crfS, BD ]
|
args: [ crfS, BD ]
|
||||||
condition: BO == 4 && BI & 0b11 == 0b01
|
condition: BO & 0b11110 == 4 && BI & 0b11 == 1
|
||||||
# bc branch if zero
|
# bc branch if zero
|
||||||
- name: beq
|
- name: beq
|
||||||
opcode: bc
|
opcode: bc
|
||||||
modifiers: [ LK, AA ]
|
|
||||||
args: [ BD ]
|
args: [ BD ]
|
||||||
condition: BO == 12 && BI & 0b11 == 0b10 && crfS == 0
|
condition: BO & 0b11110 == 12 && BI == 2
|
||||||
- name: beq
|
- name: beq
|
||||||
opcode: bc
|
opcode: bc
|
||||||
modifiers: [ LK, AA ]
|
|
||||||
args: [ crfS, BD ]
|
args: [ crfS, BD ]
|
||||||
condition: BO == 12 && BI & 0b11 == 0b10
|
condition: BO & 0b11110 == 12 && BI & 0b11 == 2
|
||||||
# bc branch if not negative
|
# bc branch if not negative
|
||||||
- name: bge
|
- name: bge
|
||||||
opcode: bc
|
opcode: bc
|
||||||
modifiers: [ LK, AA ]
|
|
||||||
args: [ BD ]
|
args: [ BD ]
|
||||||
condition: BO == 4 && BI & 0b11 == 0b00 && crfS == 0
|
condition: BO & 0b11110 == 4 && BI == 0
|
||||||
- name: bge
|
- name: bge
|
||||||
opcode: bc
|
opcode: bc
|
||||||
modifiers: [ LK, AA ]
|
|
||||||
args: [ crfS, BD ]
|
args: [ crfS, BD ]
|
||||||
condition: BO == 4 && BI & 0b11 == 0b00
|
condition: BO & 0b11110 == 4 && BI & 0b11 == 0
|
||||||
# bc branch if positive
|
# bc branch if positive
|
||||||
- name: bgt
|
- name: bgt
|
||||||
opcode: bc
|
opcode: bc
|
||||||
modifiers: [ LK, AA ]
|
|
||||||
args: [ BD ]
|
args: [ BD ]
|
||||||
condition: BO == 12 && BI & 0b11 == 0b01 && crfS == 0
|
condition: BO & 0b11110 == 12 && BI == 1
|
||||||
- name: bgt
|
- name: bgt
|
||||||
opcode: bc
|
opcode: bc
|
||||||
modifiers: [ LK, AA ]
|
|
||||||
args: [ crfS, BD ]
|
args: [ crfS, BD ]
|
||||||
condition: BO == 12 && BI & 0b11 == 0b01
|
condition: BO & 0b11110 == 12 && BI & 0b11 == 1
|
||||||
# bc branch if not zero
|
# bc branch if not zero
|
||||||
- name: bne
|
- name: bne
|
||||||
opcode: bc
|
opcode: bc
|
||||||
modifiers: [ LK, AA ]
|
|
||||||
args: [ BD ]
|
args: [ BD ]
|
||||||
condition: BO == 4 && BI & 0b11 == 0b10 && crfS == 0
|
condition: BO & 0b11110 == 4 && BI == 2
|
||||||
- name: bne
|
- name: bne
|
||||||
opcode: bc
|
opcode: bc
|
||||||
modifiers: [ LK, AA ]
|
|
||||||
args: [ crfS, BD ]
|
args: [ crfS, BD ]
|
||||||
condition: BO == 4 && BI & 0b11 == 0b10
|
condition: BO & 0b11110 == 4 && BI & 0b11 == 2
|
||||||
# bc branch if summary overflow
|
# bc branch if summary overflow
|
||||||
- name: bso
|
- name: bso
|
||||||
opcode: bc
|
opcode: bc
|
||||||
modifiers: [ LK, AA ]
|
|
||||||
args: [ BD ]
|
args: [ BD ]
|
||||||
condition: BO == 12 && BI & 0b11 == 0b11 && crfS == 0
|
condition: BO & 0b11110 == 12 && BI == 3
|
||||||
- name: bso
|
- name: bso
|
||||||
opcode: bc
|
opcode: bc
|
||||||
modifiers: [ LK, AA ]
|
|
||||||
args: [ crfS, BD ]
|
args: [ crfS, BD ]
|
||||||
condition: BO == 12 && BI & 0b11 == 0b11
|
condition: BO & 0b11110 == 12 && BI & 0b11 == 3
|
||||||
# bc branch if not summary overflow
|
# bc branch if not summary overflow
|
||||||
- name: bns
|
- name: bns
|
||||||
opcode: bc
|
opcode: bc
|
||||||
modifiers: [ LK, AA ]
|
|
||||||
args: [ BD ]
|
args: [ BD ]
|
||||||
condition: BO == 4 && BI & 0b11 == 0b11 && crfS == 0
|
condition: BO & 0b11110 == 4 && BI == 3
|
||||||
- name: bns
|
- name: bns
|
||||||
opcode: bc
|
opcode: bc
|
||||||
modifiers: [ LK, AA ]
|
|
||||||
args: [ crfS, BD ]
|
args: [ crfS, BD ]
|
||||||
condition: BO == 4 && BI & 0b11 == 0b11
|
condition: BO & 0b11110 == 4 && BI & 0b11 == 3
|
||||||
|
|
||||||
|
# bc decrement CTR, branch if CTR non-zero
|
||||||
- name: bdnz
|
- name: bdnz
|
||||||
opcode: bc
|
opcode: bc
|
||||||
modifiers: [ LK, AA ]
|
|
||||||
args: [ BD ]
|
args: [ BD ]
|
||||||
condition: BO == 16 && BI == 0
|
condition: BO & 0b11110 == 16 && BI == 0
|
||||||
|
# bc decrement CTR, branch if CTR non-zero AND condition true
|
||||||
|
- name: bdnzt
|
||||||
|
opcode: bc
|
||||||
|
args: [ BI, BD ]
|
||||||
|
condition: BO & 0b11110 == 8
|
||||||
|
# bc decrement CTR, branch if CTR non-zero AND condition false
|
||||||
|
- name: bdnzf
|
||||||
|
opcode: bc
|
||||||
|
args: [ BI, BD ]
|
||||||
|
condition: BO & 0b11110 == 0
|
||||||
|
# bc decrement CTR, branch if CTR zero
|
||||||
- name: bdz
|
- name: bdz
|
||||||
opcode: bc
|
opcode: bc
|
||||||
modifiers: [ LK, AA ]
|
|
||||||
args: [ BD ]
|
args: [ BD ]
|
||||||
condition: BO == 18 && BI == 0
|
condition: BO & 0b11110 == 18 && BI == 0
|
||||||
# TODO support conditional bd...
|
# bc decrement CTR, branch if CTR zero AND condition true
|
||||||
|
- name: bdzt
|
||||||
|
opcode: bc
|
||||||
|
args: [ BI, BD ]
|
||||||
|
condition: BO & 0b11110 == 10
|
||||||
|
# bc decrement CTR, branch if CTR zero AND condition false
|
||||||
|
- name: bdzf
|
||||||
|
opcode: bc
|
||||||
|
args: [ BI, BD ]
|
||||||
|
condition: BO & 0b11110 == 2
|
||||||
|
|
||||||
# Branch Conditional to Count Register
|
# Branch Conditional to Count Register
|
||||||
# bcctr branch always
|
# bcctr branch always
|
||||||
|
@ -2338,86 +2376,69 @@ mnemonics:
|
||||||
# bcctr branch if negative
|
# bcctr branch if negative
|
||||||
- name: bltctr
|
- name: bltctr
|
||||||
opcode: bcctr
|
opcode: bcctr
|
||||||
modifiers: [ LK ]
|
condition: BO & 0b11110 == 12 && BI == 0
|
||||||
condition: BO == 12 && BI & 0b11 == 0b00 && crfS == 0
|
|
||||||
- name: bltctr
|
- name: bltctr
|
||||||
opcode: bcctr
|
opcode: bcctr
|
||||||
modifiers: [ LK ]
|
|
||||||
args: [ crfS ]
|
args: [ crfS ]
|
||||||
condition: BO == 12 && BI & 0b11 == 0b00
|
condition: BO & 0b11110 == 12 && BI & 0b11 == 0
|
||||||
# bcctr branch if not positive
|
# bcctr branch if not positive
|
||||||
- name: blectr
|
- name: blectr
|
||||||
opcode: bcctr
|
opcode: bcctr
|
||||||
modifiers: [ LK ]
|
condition: BO & 0b11110 == 4 && BI == 1
|
||||||
condition: BO == 4 && BI & 0b11 == 0b01 && crfS == 0
|
|
||||||
- name: blectr
|
- name: blectr
|
||||||
opcode: bcctr
|
opcode: bcctr
|
||||||
modifiers: [ LK ]
|
|
||||||
args: [ crfS ]
|
args: [ crfS ]
|
||||||
condition: BO == 4 && BI & 0b11 == 0b01
|
condition: BO & 0b11110 == 4 && BI & 0b11 == 1
|
||||||
# bcctr branch if zero
|
# bcctr branch if zero
|
||||||
- name: beqctr
|
- name: beqctr
|
||||||
opcode: bcctr
|
opcode: bcctr
|
||||||
modifiers: [ LK ]
|
condition: BO & 0b11110 == 12 && BI == 2
|
||||||
condition: BO == 12 && BI & 0b11 == 0b10 && crfS == 0
|
|
||||||
- name: beqctr
|
- name: beqctr
|
||||||
opcode: bcctr
|
opcode: bcctr
|
||||||
modifiers: [ LK ]
|
|
||||||
args: [ crfS ]
|
args: [ crfS ]
|
||||||
condition: BO == 12 && BI & 0b11 == 0b10
|
condition: BO & 0b11110 == 12 && BI & 0b11 == 2
|
||||||
# bcctr branch if not negative
|
# bcctr branch if not negative
|
||||||
- name: bgectr
|
- name: bgectr
|
||||||
opcode: bcctr
|
opcode: bcctr
|
||||||
modifiers: [ LK ]
|
condition: BO & 0b11110 == 4 && BI == 0
|
||||||
condition: BO == 4 && BI & 0b11 == 0b00 && crfS == 0
|
|
||||||
- name: bgectr
|
- name: bgectr
|
||||||
opcode: bcctr
|
opcode: bcctr
|
||||||
modifiers: [ LK ]
|
|
||||||
args: [ crfS ]
|
args: [ crfS ]
|
||||||
condition: BO == 4 && BI & 0b11 == 0b00
|
condition: BO & 0b11110 == 4 && BI & 0b11 == 0
|
||||||
# bcctr branch if positive
|
# bcctr branch if positive
|
||||||
- name: bgtctr
|
- name: bgtctr
|
||||||
opcode: bcctr
|
opcode: bcctr
|
||||||
modifiers: [ LK ]
|
condition: BO & 0b11110 == 12 && BI == 1
|
||||||
condition: BO == 12 && BI & 0b11 == 0b01 && crfS == 0
|
|
||||||
- name: bgtctr
|
- name: bgtctr
|
||||||
opcode: bcctr
|
opcode: bcctr
|
||||||
modifiers: [ LK ]
|
|
||||||
args: [ crfS ]
|
args: [ crfS ]
|
||||||
condition: BO == 12 && BI & 0b11 == 0b01
|
condition: BO & 0b11110 == 12 && BI & 0b11 == 1
|
||||||
# bcctr branch if not zero
|
# bcctr branch if not zero
|
||||||
- name: bnectr
|
- name: bnectr
|
||||||
opcode: bcctr
|
opcode: bcctr
|
||||||
modifiers: [ LK ]
|
condition: BO & 0b11110 == 4 && BI == 2
|
||||||
condition: BO == 4 && BI & 0b11 == 0b10 && crfS == 0
|
|
||||||
- name: bnectr
|
- name: bnectr
|
||||||
opcode: bcctr
|
opcode: bcctr
|
||||||
modifiers: [ LK ]
|
|
||||||
args: [ crfS ]
|
args: [ crfS ]
|
||||||
condition: BO == 4 && BI & 0b11 == 0b10
|
condition: BO & 0b11110 == 4 && BI & 0b11 == 2
|
||||||
# bcctr branch if summary overflow
|
# bcctr branch if summary overflow
|
||||||
- name: bsoctr
|
- name: bsoctr
|
||||||
opcode: bcctr
|
opcode: bcctr
|
||||||
modifiers: [ LK ]
|
condition: BO & 0b11110 == 12 && BI == 3
|
||||||
condition: BO == 12 && BI & 0b11 == 0b11 && crfS == 0
|
|
||||||
- name: bsoctr
|
- name: bsoctr
|
||||||
opcode: bcctr
|
opcode: bcctr
|
||||||
modifiers: [ LK ]
|
|
||||||
args: [ crfS ]
|
args: [ crfS ]
|
||||||
condition: BO == 12 && BI & 0b11 == 0b11
|
condition: BO & 0b11110 == 12 && BI & 0b11 == 3
|
||||||
# bcctr branch if not summary overflow
|
# bcctr branch if not summary overflow
|
||||||
- name: bnsctr
|
- name: bnsctr
|
||||||
opcode: bcctr
|
opcode: bcctr
|
||||||
modifiers: [ LK ]
|
condition: BO & 0b11110 == 4 && BI == 3
|
||||||
condition: BO == 4 && BI & 0b11 == 0b11 && crfS == 0
|
|
||||||
- name: bnsctr
|
- name: bnsctr
|
||||||
opcode: bcctr
|
opcode: bcctr
|
||||||
modifiers: [ LK ]
|
|
||||||
args: [ crfS ]
|
args: [ crfS ]
|
||||||
condition: BO == 4 && BI & 0b11 == 0b11
|
condition: BO & 0b11110 == 4 && BI & 0b11 == 3
|
||||||
|
|
||||||
# Branch Conditional to Link Register
|
# Branch Conditional to Link Register
|
||||||
|
|
||||||
# bclr branch always
|
# bclr branch always
|
||||||
- name: blr
|
- name: blr
|
||||||
opcode: bclr
|
opcode: bclr
|
||||||
|
@ -2426,80 +2447,92 @@ mnemonics:
|
||||||
# bclr branch if negative
|
# bclr branch if negative
|
||||||
- name: bltlr
|
- name: bltlr
|
||||||
opcode: bclr
|
opcode: bclr
|
||||||
modifiers: [ LK ]
|
condition: BO & 0b11110 == 12 && BI == 0
|
||||||
condition: BO == 12 && BI & 0b11 == 0b00 && crfS == 0
|
|
||||||
- name: bltlr
|
- name: bltlr
|
||||||
opcode: bclr
|
opcode: bclr
|
||||||
modifiers: [ LK ]
|
|
||||||
args: [ crfS ]
|
args: [ crfS ]
|
||||||
condition: BO == 12 && BI & 0b11 == 0b00
|
condition: BO & 0b11110 == 12 && BI & 0b11 == 0
|
||||||
# bclr branch if not positive
|
# bclr branch if not positive
|
||||||
- name: blelr
|
- name: blelr
|
||||||
opcode: bclr
|
opcode: bclr
|
||||||
modifiers: [ LK ]
|
condition: BO & 0b11110 == 4 && BI == 1
|
||||||
condition: BO == 4 && BI & 0b11 == 0b01 && crfS == 0
|
|
||||||
- name: blelr
|
- name: blelr
|
||||||
opcode: bclr
|
opcode: bclr
|
||||||
modifiers: [ LK ]
|
|
||||||
args: [ crfS ]
|
args: [ crfS ]
|
||||||
condition: BO == 4 && BI & 0b11 == 0b01
|
condition: BO & 0b11110 == 4 && BI & 0b11 == 1
|
||||||
# bclr branch if zero
|
# bclr branch if zero
|
||||||
- name: beqlr
|
- name: beqlr
|
||||||
opcode: bclr
|
opcode: bclr
|
||||||
modifiers: [ LK ]
|
condition: BO & 0b11110 == 12 && BI == 2
|
||||||
condition: BO == 12 && BI & 0b11 == 0b10 && crfS == 0
|
|
||||||
- name: beqlr
|
- name: beqlr
|
||||||
opcode: bclr
|
opcode: bclr
|
||||||
modifiers: [ LK ]
|
|
||||||
args: [ crfS ]
|
args: [ crfS ]
|
||||||
condition: BO == 12 && BI & 0b11 == 0b10
|
condition: BO & 0b11110 == 12 && BI & 0b11 == 2
|
||||||
# bclr branch if not negative
|
# bclr branch if not negative
|
||||||
- name: bgelr
|
- name: bgelr
|
||||||
opcode: bclr
|
opcode: bclr
|
||||||
modifiers: [ LK ]
|
condition: BO & 0b11110 == 4 && BI == 0
|
||||||
condition: BO == 4 && BI & 0b11 == 0b00 && crfS == 0
|
|
||||||
- name: bgelr
|
- name: bgelr
|
||||||
opcode: bclr
|
opcode: bclr
|
||||||
modifiers: [ LK ]
|
|
||||||
args: [ crfS ]
|
args: [ crfS ]
|
||||||
condition: BO == 4 && BI & 0b11 == 0b00
|
condition: BO & 0b11110 == 4 && BI & 0b11 == 0
|
||||||
# bclr branch if positive
|
# bclr branch if positive
|
||||||
- name: bgtlr
|
- name: bgtlr
|
||||||
opcode: bclr
|
opcode: bclr
|
||||||
modifiers: [ LK ]
|
condition: BO & 0b11110 == 12 && BI == 1
|
||||||
condition: BO == 12 && BI & 0b11 == 0b01 && crfS == 0
|
|
||||||
- name: bgtlr
|
- name: bgtlr
|
||||||
opcode: bclr
|
opcode: bclr
|
||||||
modifiers: [ LK ]
|
|
||||||
args: [ crfS ]
|
args: [ crfS ]
|
||||||
condition: BO == 12 && BI & 0b11 == 0b01
|
condition: BO & 0b11110 == 12 && BI & 0b11 == 1
|
||||||
# bclr branch if not zero
|
# bclr branch if not zero
|
||||||
- name: bnelr
|
- name: bnelr
|
||||||
opcode: bclr
|
opcode: bclr
|
||||||
modifiers: [ LK ]
|
condition: BO & 0b11110 == 4 && BI == 2
|
||||||
condition: BO == 4 && BI & 0b11 == 0b10 && crfS == 0
|
|
||||||
- name: bnelr
|
- name: bnelr
|
||||||
opcode: bclr
|
opcode: bclr
|
||||||
modifiers: [ LK ]
|
|
||||||
args: [ crfS ]
|
args: [ crfS ]
|
||||||
condition: BO == 4 && BI & 0b11 == 0b10
|
condition: BO & 0b11110 == 4 && BI & 0b11 == 2
|
||||||
# bclr branch if summary overflow
|
# bclr branch if summary overflow
|
||||||
- name: bsolr
|
- name: bsolr
|
||||||
opcode: bclr
|
opcode: bclr
|
||||||
modifiers: [ LK ]
|
condition: BO & 0b11110 == 12 && BI == 3
|
||||||
condition: BO == 12 && BI & 0b11 == 0b11 && crfS == 0
|
|
||||||
- name: bsolr
|
- name: bsolr
|
||||||
opcode: bclr
|
opcode: bclr
|
||||||
modifiers: [ LK ]
|
|
||||||
args: [ crfS ]
|
args: [ crfS ]
|
||||||
condition: BO == 12 && BI & 0b11 == 0b11
|
condition: BO & 0b11110 == 12 && BI & 0b11 == 3
|
||||||
# bclr branch if not summary overflow
|
# bclr branch if not summary overflow
|
||||||
- name: bnslr
|
- name: bnslr
|
||||||
opcode: bclr
|
opcode: bclr
|
||||||
modifiers: [ LK ]
|
condition: BO & 0b11110 == 4 && BI == 3
|
||||||
condition: BO == 4 && BI & 0b11 == 0b11 && crfS == 0
|
|
||||||
- name: bnslr
|
- name: bnslr
|
||||||
opcode: bclr
|
opcode: bclr
|
||||||
modifiers: [ LK ]
|
|
||||||
args: [ crfS ]
|
args: [ crfS ]
|
||||||
condition: BO == 4 && BI & 0b11 == 0b11
|
condition: BO & 0b11110 == 4 && BI & 0b11 == 3
|
||||||
|
# bclr decrement CTR, branch if CTR non-zero
|
||||||
|
- name: bdnzlr
|
||||||
|
opcode: bclr
|
||||||
|
condition: BO & 0b11110 == 16 && BI == 0
|
||||||
|
# bclr decrement CTR, branch if CTR non-zero AND condition true
|
||||||
|
- name: bdnztlr
|
||||||
|
opcode: bclr
|
||||||
|
args: [ BI ]
|
||||||
|
condition: BO & 0b11110 == 8
|
||||||
|
# bclr decrement CTR, branch if CTR non-zero AND condition false
|
||||||
|
- name: bdnzflr
|
||||||
|
opcode: bclr
|
||||||
|
args: [ BI ]
|
||||||
|
condition: BO & 0b11110 == 0
|
||||||
|
# bclr decrement CTR, branch if CTR zero
|
||||||
|
- name: bdzlr
|
||||||
|
opcode: bclr
|
||||||
|
condition: BO & 0b11110 == 18 && BI == 0
|
||||||
|
# bclr decrement CTR, branch if CTR zero AND condition true
|
||||||
|
- name: bdztlr
|
||||||
|
opcode: bclr
|
||||||
|
args: [ BI ]
|
||||||
|
condition: BO & 0b11110 == 10
|
||||||
|
# bclr decrement CTR, branch if CTR zero AND condition false
|
||||||
|
- name: bdzflr
|
||||||
|
opcode: bclr
|
||||||
|
args: [ BI ]
|
||||||
|
condition: BO & 0b11110 == 0
|
||||||
|
|
Loading…
Reference in New Issue