Auto merge of #84732 - DrChat:asm_powerpc, r=Amanieu
Add asm!() support for PowerPC This includes GPRs and FPRs only. Note that this does not include PowerPC64. For my reference, this was mostly duplicated from PR #73214.
This commit is contained in:
commit
72d07257ed
6 changed files with 356 additions and 1 deletions
|
@ -283,6 +283,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
}
|
}
|
||||||
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {}
|
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {}
|
||||||
InlineAsmArch::Nvptx64 => {}
|
InlineAsmArch::Nvptx64 => {}
|
||||||
|
InlineAsmArch::PowerPC => {}
|
||||||
InlineAsmArch::Hexagon => {}
|
InlineAsmArch::Hexagon => {}
|
||||||
InlineAsmArch::Mips | InlineAsmArch::Mips64 => {}
|
InlineAsmArch::Mips | InlineAsmArch::Mips64 => {}
|
||||||
InlineAsmArch::SpirV => {}
|
InlineAsmArch::SpirV => {}
|
||||||
|
@ -540,6 +541,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
|
||||||
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => "h",
|
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => "h",
|
||||||
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => "r",
|
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => "r",
|
||||||
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => "l",
|
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => "l",
|
||||||
|
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => "r",
|
||||||
|
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b",
|
||||||
|
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
|
||||||
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r",
|
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r",
|
||||||
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f",
|
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f",
|
||||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) => "r",
|
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) => "r",
|
||||||
|
@ -590,6 +594,7 @@ fn modifier_to_llvm(
|
||||||
InlineAsmRegClass::Hexagon(_) => None,
|
InlineAsmRegClass::Hexagon(_) => None,
|
||||||
InlineAsmRegClass::Mips(_) => None,
|
InlineAsmRegClass::Mips(_) => None,
|
||||||
InlineAsmRegClass::Nvptx(_) => None,
|
InlineAsmRegClass::Nvptx(_) => None,
|
||||||
|
InlineAsmRegClass::PowerPC(_) => None,
|
||||||
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg)
|
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg)
|
||||||
| InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => None,
|
| InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => None,
|
||||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg)
|
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg)
|
||||||
|
@ -651,6 +656,9 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
|
||||||
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => cx.type_i16(),
|
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => cx.type_i16(),
|
||||||
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => cx.type_i32(),
|
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => cx.type_i32(),
|
||||||
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => cx.type_i64(),
|
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => cx.type_i64(),
|
||||||
|
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => cx.type_i32(),
|
||||||
|
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => cx.type_i32(),
|
||||||
|
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(),
|
||||||
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(),
|
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(),
|
||||||
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => cx.type_f32(),
|
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => cx.type_f32(),
|
||||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg)
|
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg)
|
||||||
|
|
|
@ -948,6 +948,7 @@ symbols! {
|
||||||
reg64,
|
reg64,
|
||||||
reg_abcd,
|
reg_abcd,
|
||||||
reg_byte,
|
reg_byte,
|
||||||
|
reg_nonzero,
|
||||||
reg_thumb,
|
reg_thumb,
|
||||||
register_attr,
|
register_attr,
|
||||||
register_tool,
|
register_tool,
|
||||||
|
|
|
@ -154,6 +154,7 @@ mod arm;
|
||||||
mod hexagon;
|
mod hexagon;
|
||||||
mod mips;
|
mod mips;
|
||||||
mod nvptx;
|
mod nvptx;
|
||||||
|
mod powerpc;
|
||||||
mod riscv;
|
mod riscv;
|
||||||
mod spirv;
|
mod spirv;
|
||||||
mod wasm;
|
mod wasm;
|
||||||
|
@ -164,6 +165,7 @@ pub use arm::{ArmInlineAsmReg, ArmInlineAsmRegClass};
|
||||||
pub use hexagon::{HexagonInlineAsmReg, HexagonInlineAsmRegClass};
|
pub use hexagon::{HexagonInlineAsmReg, HexagonInlineAsmRegClass};
|
||||||
pub use mips::{MipsInlineAsmReg, MipsInlineAsmRegClass};
|
pub use mips::{MipsInlineAsmReg, MipsInlineAsmRegClass};
|
||||||
pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass};
|
pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass};
|
||||||
|
pub use powerpc::{PowerPCInlineAsmReg, PowerPCInlineAsmRegClass};
|
||||||
pub use riscv::{RiscVInlineAsmReg, RiscVInlineAsmRegClass};
|
pub use riscv::{RiscVInlineAsmReg, RiscVInlineAsmRegClass};
|
||||||
pub use spirv::{SpirVInlineAsmReg, SpirVInlineAsmRegClass};
|
pub use spirv::{SpirVInlineAsmReg, SpirVInlineAsmRegClass};
|
||||||
pub use wasm::{WasmInlineAsmReg, WasmInlineAsmRegClass};
|
pub use wasm::{WasmInlineAsmReg, WasmInlineAsmRegClass};
|
||||||
|
@ -181,6 +183,7 @@ pub enum InlineAsmArch {
|
||||||
Hexagon,
|
Hexagon,
|
||||||
Mips,
|
Mips,
|
||||||
Mips64,
|
Mips64,
|
||||||
|
PowerPC,
|
||||||
SpirV,
|
SpirV,
|
||||||
Wasm32,
|
Wasm32,
|
||||||
}
|
}
|
||||||
|
@ -197,6 +200,7 @@ impl FromStr for InlineAsmArch {
|
||||||
"riscv32" => Ok(Self::RiscV32),
|
"riscv32" => Ok(Self::RiscV32),
|
||||||
"riscv64" => Ok(Self::RiscV64),
|
"riscv64" => Ok(Self::RiscV64),
|
||||||
"nvptx64" => Ok(Self::Nvptx64),
|
"nvptx64" => Ok(Self::Nvptx64),
|
||||||
|
"powerpc" => Ok(Self::PowerPC),
|
||||||
"hexagon" => Ok(Self::Hexagon),
|
"hexagon" => Ok(Self::Hexagon),
|
||||||
"mips" => Ok(Self::Mips),
|
"mips" => Ok(Self::Mips),
|
||||||
"mips64" => Ok(Self::Mips64),
|
"mips64" => Ok(Self::Mips64),
|
||||||
|
@ -225,6 +229,7 @@ pub enum InlineAsmReg {
|
||||||
AArch64(AArch64InlineAsmReg),
|
AArch64(AArch64InlineAsmReg),
|
||||||
RiscV(RiscVInlineAsmReg),
|
RiscV(RiscVInlineAsmReg),
|
||||||
Nvptx(NvptxInlineAsmReg),
|
Nvptx(NvptxInlineAsmReg),
|
||||||
|
PowerPC(PowerPCInlineAsmReg),
|
||||||
Hexagon(HexagonInlineAsmReg),
|
Hexagon(HexagonInlineAsmReg),
|
||||||
Mips(MipsInlineAsmReg),
|
Mips(MipsInlineAsmReg),
|
||||||
SpirV(SpirVInlineAsmReg),
|
SpirV(SpirVInlineAsmReg),
|
||||||
|
@ -240,6 +245,7 @@ impl InlineAsmReg {
|
||||||
Self::Arm(r) => r.name(),
|
Self::Arm(r) => r.name(),
|
||||||
Self::AArch64(r) => r.name(),
|
Self::AArch64(r) => r.name(),
|
||||||
Self::RiscV(r) => r.name(),
|
Self::RiscV(r) => r.name(),
|
||||||
|
Self::PowerPC(r) => r.name(),
|
||||||
Self::Hexagon(r) => r.name(),
|
Self::Hexagon(r) => r.name(),
|
||||||
Self::Mips(r) => r.name(),
|
Self::Mips(r) => r.name(),
|
||||||
Self::Err => "<reg>",
|
Self::Err => "<reg>",
|
||||||
|
@ -252,6 +258,7 @@ impl InlineAsmReg {
|
||||||
Self::Arm(r) => InlineAsmRegClass::Arm(r.reg_class()),
|
Self::Arm(r) => InlineAsmRegClass::Arm(r.reg_class()),
|
||||||
Self::AArch64(r) => InlineAsmRegClass::AArch64(r.reg_class()),
|
Self::AArch64(r) => InlineAsmRegClass::AArch64(r.reg_class()),
|
||||||
Self::RiscV(r) => InlineAsmRegClass::RiscV(r.reg_class()),
|
Self::RiscV(r) => InlineAsmRegClass::RiscV(r.reg_class()),
|
||||||
|
Self::PowerPC(r) => InlineAsmRegClass::PowerPC(r.reg_class()),
|
||||||
Self::Hexagon(r) => InlineAsmRegClass::Hexagon(r.reg_class()),
|
Self::Hexagon(r) => InlineAsmRegClass::Hexagon(r.reg_class()),
|
||||||
Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()),
|
Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()),
|
||||||
Self::Err => InlineAsmRegClass::Err,
|
Self::Err => InlineAsmRegClass::Err,
|
||||||
|
@ -283,6 +290,9 @@ impl InlineAsmReg {
|
||||||
InlineAsmArch::Nvptx64 => {
|
InlineAsmArch::Nvptx64 => {
|
||||||
Self::Nvptx(NvptxInlineAsmReg::parse(arch, has_feature, target, &name)?)
|
Self::Nvptx(NvptxInlineAsmReg::parse(arch, has_feature, target, &name)?)
|
||||||
}
|
}
|
||||||
|
InlineAsmArch::PowerPC => {
|
||||||
|
Self::PowerPC(PowerPCInlineAsmReg::parse(arch, has_feature, target, &name)?)
|
||||||
|
}
|
||||||
InlineAsmArch::Hexagon => {
|
InlineAsmArch::Hexagon => {
|
||||||
Self::Hexagon(HexagonInlineAsmReg::parse(arch, has_feature, target, &name)?)
|
Self::Hexagon(HexagonInlineAsmReg::parse(arch, has_feature, target, &name)?)
|
||||||
}
|
}
|
||||||
|
@ -311,6 +321,7 @@ impl InlineAsmReg {
|
||||||
Self::Arm(r) => r.emit(out, arch, modifier),
|
Self::Arm(r) => r.emit(out, arch, modifier),
|
||||||
Self::AArch64(r) => r.emit(out, arch, modifier),
|
Self::AArch64(r) => r.emit(out, arch, modifier),
|
||||||
Self::RiscV(r) => r.emit(out, arch, modifier),
|
Self::RiscV(r) => r.emit(out, arch, modifier),
|
||||||
|
Self::PowerPC(r) => r.emit(out, arch, modifier),
|
||||||
Self::Hexagon(r) => r.emit(out, arch, modifier),
|
Self::Hexagon(r) => r.emit(out, arch, modifier),
|
||||||
Self::Mips(r) => r.emit(out, arch, modifier),
|
Self::Mips(r) => r.emit(out, arch, modifier),
|
||||||
Self::Err => unreachable!("Use of InlineAsmReg::Err"),
|
Self::Err => unreachable!("Use of InlineAsmReg::Err"),
|
||||||
|
@ -323,6 +334,7 @@ impl InlineAsmReg {
|
||||||
Self::Arm(r) => r.overlapping_regs(|r| cb(Self::Arm(r))),
|
Self::Arm(r) => r.overlapping_regs(|r| cb(Self::Arm(r))),
|
||||||
Self::AArch64(_) => cb(self),
|
Self::AArch64(_) => cb(self),
|
||||||
Self::RiscV(_) => cb(self),
|
Self::RiscV(_) => cb(self),
|
||||||
|
Self::PowerPC(_) => cb(self),
|
||||||
Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))),
|
Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))),
|
||||||
Self::Mips(_) => cb(self),
|
Self::Mips(_) => cb(self),
|
||||||
Self::Err => unreachable!("Use of InlineAsmReg::Err"),
|
Self::Err => unreachable!("Use of InlineAsmReg::Err"),
|
||||||
|
@ -348,6 +360,7 @@ pub enum InlineAsmRegClass {
|
||||||
AArch64(AArch64InlineAsmRegClass),
|
AArch64(AArch64InlineAsmRegClass),
|
||||||
RiscV(RiscVInlineAsmRegClass),
|
RiscV(RiscVInlineAsmRegClass),
|
||||||
Nvptx(NvptxInlineAsmRegClass),
|
Nvptx(NvptxInlineAsmRegClass),
|
||||||
|
PowerPC(PowerPCInlineAsmRegClass),
|
||||||
Hexagon(HexagonInlineAsmRegClass),
|
Hexagon(HexagonInlineAsmRegClass),
|
||||||
Mips(MipsInlineAsmRegClass),
|
Mips(MipsInlineAsmRegClass),
|
||||||
SpirV(SpirVInlineAsmRegClass),
|
SpirV(SpirVInlineAsmRegClass),
|
||||||
|
@ -364,6 +377,7 @@ impl InlineAsmRegClass {
|
||||||
Self::AArch64(r) => r.name(),
|
Self::AArch64(r) => r.name(),
|
||||||
Self::RiscV(r) => r.name(),
|
Self::RiscV(r) => r.name(),
|
||||||
Self::Nvptx(r) => r.name(),
|
Self::Nvptx(r) => r.name(),
|
||||||
|
Self::PowerPC(r) => r.name(),
|
||||||
Self::Hexagon(r) => r.name(),
|
Self::Hexagon(r) => r.name(),
|
||||||
Self::Mips(r) => r.name(),
|
Self::Mips(r) => r.name(),
|
||||||
Self::SpirV(r) => r.name(),
|
Self::SpirV(r) => r.name(),
|
||||||
|
@ -382,6 +396,7 @@ impl InlineAsmRegClass {
|
||||||
Self::AArch64(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::AArch64),
|
Self::AArch64(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::AArch64),
|
||||||
Self::RiscV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::RiscV),
|
Self::RiscV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::RiscV),
|
||||||
Self::Nvptx(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Nvptx),
|
Self::Nvptx(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Nvptx),
|
||||||
|
Self::PowerPC(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::PowerPC),
|
||||||
Self::Hexagon(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Hexagon),
|
Self::Hexagon(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Hexagon),
|
||||||
Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips),
|
Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips),
|
||||||
Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV),
|
Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV),
|
||||||
|
@ -407,6 +422,7 @@ impl InlineAsmRegClass {
|
||||||
Self::AArch64(r) => r.suggest_modifier(arch, ty),
|
Self::AArch64(r) => r.suggest_modifier(arch, ty),
|
||||||
Self::RiscV(r) => r.suggest_modifier(arch, ty),
|
Self::RiscV(r) => r.suggest_modifier(arch, ty),
|
||||||
Self::Nvptx(r) => r.suggest_modifier(arch, ty),
|
Self::Nvptx(r) => r.suggest_modifier(arch, ty),
|
||||||
|
Self::PowerPC(r) => r.suggest_modifier(arch, ty),
|
||||||
Self::Hexagon(r) => r.suggest_modifier(arch, ty),
|
Self::Hexagon(r) => r.suggest_modifier(arch, ty),
|
||||||
Self::Mips(r) => r.suggest_modifier(arch, ty),
|
Self::Mips(r) => r.suggest_modifier(arch, ty),
|
||||||
Self::SpirV(r) => r.suggest_modifier(arch, ty),
|
Self::SpirV(r) => r.suggest_modifier(arch, ty),
|
||||||
|
@ -428,6 +444,7 @@ impl InlineAsmRegClass {
|
||||||
Self::AArch64(r) => r.default_modifier(arch),
|
Self::AArch64(r) => r.default_modifier(arch),
|
||||||
Self::RiscV(r) => r.default_modifier(arch),
|
Self::RiscV(r) => r.default_modifier(arch),
|
||||||
Self::Nvptx(r) => r.default_modifier(arch),
|
Self::Nvptx(r) => r.default_modifier(arch),
|
||||||
|
Self::PowerPC(r) => r.default_modifier(arch),
|
||||||
Self::Hexagon(r) => r.default_modifier(arch),
|
Self::Hexagon(r) => r.default_modifier(arch),
|
||||||
Self::Mips(r) => r.default_modifier(arch),
|
Self::Mips(r) => r.default_modifier(arch),
|
||||||
Self::SpirV(r) => r.default_modifier(arch),
|
Self::SpirV(r) => r.default_modifier(arch),
|
||||||
|
@ -448,6 +465,7 @@ impl InlineAsmRegClass {
|
||||||
Self::AArch64(r) => r.supported_types(arch),
|
Self::AArch64(r) => r.supported_types(arch),
|
||||||
Self::RiscV(r) => r.supported_types(arch),
|
Self::RiscV(r) => r.supported_types(arch),
|
||||||
Self::Nvptx(r) => r.supported_types(arch),
|
Self::Nvptx(r) => r.supported_types(arch),
|
||||||
|
Self::PowerPC(r) => r.supported_types(arch),
|
||||||
Self::Hexagon(r) => r.supported_types(arch),
|
Self::Hexagon(r) => r.supported_types(arch),
|
||||||
Self::Mips(r) => r.supported_types(arch),
|
Self::Mips(r) => r.supported_types(arch),
|
||||||
Self::SpirV(r) => r.supported_types(arch),
|
Self::SpirV(r) => r.supported_types(arch),
|
||||||
|
@ -467,6 +485,7 @@ impl InlineAsmRegClass {
|
||||||
Self::RiscV(RiscVInlineAsmRegClass::parse(arch, name)?)
|
Self::RiscV(RiscVInlineAsmRegClass::parse(arch, name)?)
|
||||||
}
|
}
|
||||||
InlineAsmArch::Nvptx64 => Self::Nvptx(NvptxInlineAsmRegClass::parse(arch, name)?),
|
InlineAsmArch::Nvptx64 => Self::Nvptx(NvptxInlineAsmRegClass::parse(arch, name)?),
|
||||||
|
InlineAsmArch::PowerPC => Self::PowerPC(PowerPCInlineAsmRegClass::parse(arch, name)?),
|
||||||
InlineAsmArch::Hexagon => Self::Hexagon(HexagonInlineAsmRegClass::parse(arch, name)?),
|
InlineAsmArch::Hexagon => Self::Hexagon(HexagonInlineAsmRegClass::parse(arch, name)?),
|
||||||
InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
|
InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
|
||||||
Self::Mips(MipsInlineAsmRegClass::parse(arch, name)?)
|
Self::Mips(MipsInlineAsmRegClass::parse(arch, name)?)
|
||||||
|
@ -485,6 +504,7 @@ impl InlineAsmRegClass {
|
||||||
Self::AArch64(r) => r.valid_modifiers(arch),
|
Self::AArch64(r) => r.valid_modifiers(arch),
|
||||||
Self::RiscV(r) => r.valid_modifiers(arch),
|
Self::RiscV(r) => r.valid_modifiers(arch),
|
||||||
Self::Nvptx(r) => r.valid_modifiers(arch),
|
Self::Nvptx(r) => r.valid_modifiers(arch),
|
||||||
|
Self::PowerPC(r) => r.valid_modifiers(arch),
|
||||||
Self::Hexagon(r) => r.valid_modifiers(arch),
|
Self::Hexagon(r) => r.valid_modifiers(arch),
|
||||||
Self::Mips(r) => r.valid_modifiers(arch),
|
Self::Mips(r) => r.valid_modifiers(arch),
|
||||||
Self::SpirV(r) => r.valid_modifiers(arch),
|
Self::SpirV(r) => r.valid_modifiers(arch),
|
||||||
|
@ -633,6 +653,11 @@ pub fn allocatable_registers(
|
||||||
nvptx::fill_reg_map(arch, has_feature, target, &mut map);
|
nvptx::fill_reg_map(arch, has_feature, target, &mut map);
|
||||||
map
|
map
|
||||||
}
|
}
|
||||||
|
InlineAsmArch::PowerPC => {
|
||||||
|
let mut map = powerpc::regclass_map();
|
||||||
|
powerpc::fill_reg_map(arch, has_feature, target, &mut map);
|
||||||
|
map
|
||||||
|
}
|
||||||
InlineAsmArch::Hexagon => {
|
InlineAsmArch::Hexagon => {
|
||||||
let mut map = hexagon::regclass_map();
|
let mut map = hexagon::regclass_map();
|
||||||
hexagon::fill_reg_map(arch, has_feature, target, &mut map);
|
hexagon::fill_reg_map(arch, has_feature, target, &mut map);
|
||||||
|
|
146
compiler/rustc_target/src/asm/powerpc.rs
Normal file
146
compiler/rustc_target/src/asm/powerpc.rs
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
use super::{InlineAsmArch, InlineAsmType};
|
||||||
|
use rustc_macros::HashStable_Generic;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
def_reg_class! {
|
||||||
|
PowerPC PowerPCInlineAsmRegClass {
|
||||||
|
reg,
|
||||||
|
reg_nonzero,
|
||||||
|
freg,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PowerPCInlineAsmRegClass {
|
||||||
|
pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] {
|
||||||
|
&[]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn suggest_modifier(
|
||||||
|
self,
|
||||||
|
_arch: InlineAsmArch,
|
||||||
|
_ty: InlineAsmType,
|
||||||
|
) -> Option<(char, &'static str)> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn supported_types(
|
||||||
|
self,
|
||||||
|
_arch: InlineAsmArch,
|
||||||
|
) -> &'static [(InlineAsmType, Option<&'static str>)] {
|
||||||
|
match self {
|
||||||
|
Self::reg | Self::reg_nonzero => types! { _: I8, I16, I32; },
|
||||||
|
Self::freg => types! { _: F32, F64; },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def_regs! {
|
||||||
|
PowerPC PowerPCInlineAsmReg PowerPCInlineAsmRegClass {
|
||||||
|
r0: reg = ["r0", "0"],
|
||||||
|
r3: reg, reg_nonzero = ["r3", "3"],
|
||||||
|
r4: reg, reg_nonzero = ["r4", "4"],
|
||||||
|
r5: reg, reg_nonzero = ["r5", "5"],
|
||||||
|
r6: reg, reg_nonzero = ["r6", "6"],
|
||||||
|
r7: reg, reg_nonzero = ["r7", "7"],
|
||||||
|
r8: reg, reg_nonzero = ["r8", "8"],
|
||||||
|
r9: reg, reg_nonzero = ["r9", "9"],
|
||||||
|
r10: reg, reg_nonzero = ["r10", "10"],
|
||||||
|
r11: reg, reg_nonzero = ["r11", "11"],
|
||||||
|
r12: reg, reg_nonzero = ["r12", "12"],
|
||||||
|
r14: reg, reg_nonzero = ["r14", "14"],
|
||||||
|
r15: reg, reg_nonzero = ["r15", "15"],
|
||||||
|
r16: reg, reg_nonzero = ["r16", "16"],
|
||||||
|
r17: reg, reg_nonzero = ["r17", "17"],
|
||||||
|
r18: reg, reg_nonzero = ["r18", "18"],
|
||||||
|
r19: reg, reg_nonzero = ["r19", "19"],
|
||||||
|
r20: reg, reg_nonzero = ["r20", "20"],
|
||||||
|
r21: reg, reg_nonzero = ["r21", "21"],
|
||||||
|
r22: reg, reg_nonzero = ["r22", "22"],
|
||||||
|
r23: reg, reg_nonzero = ["r23", "23"],
|
||||||
|
r24: reg, reg_nonzero = ["r24", "24"],
|
||||||
|
r25: reg, reg_nonzero = ["r25", "25"],
|
||||||
|
r26: reg, reg_nonzero = ["r26", "26"],
|
||||||
|
r27: reg, reg_nonzero = ["r27", "27"],
|
||||||
|
r28: reg, reg_nonzero = ["r28", "28"],
|
||||||
|
f0: freg = ["f0", "fr0"],
|
||||||
|
f1: freg = ["f1", "fr1"],
|
||||||
|
f2: freg = ["f2", "fr2"],
|
||||||
|
f3: freg = ["f3", "fr3"],
|
||||||
|
f4: freg = ["f4", "fr4"],
|
||||||
|
f5: freg = ["f5", "fr5"],
|
||||||
|
f6: freg = ["f6", "fr6"],
|
||||||
|
f7: freg = ["f7", "fr7"],
|
||||||
|
f8: freg = ["f8", "fr8"],
|
||||||
|
f9: freg = ["f9", "fr9"],
|
||||||
|
f10: freg = ["f10", "fr10"],
|
||||||
|
f11: freg = ["f11", "fr11"],
|
||||||
|
f12: freg = ["f12", "fr12"],
|
||||||
|
f13: freg = ["f13", "fr13"],
|
||||||
|
f14: freg = ["f14", "fr14"],
|
||||||
|
f15: freg = ["f15", "fr15"],
|
||||||
|
f16: freg = ["f16", "fr16"],
|
||||||
|
f17: freg = ["f17", "fr17"],
|
||||||
|
f18: freg = ["f18", "fr18"],
|
||||||
|
f19: freg = ["f19", "fr19"],
|
||||||
|
f20: freg = ["f20", "fr20"],
|
||||||
|
f21: freg = ["f21", "fr21"],
|
||||||
|
f22: freg = ["f22", "fr22"],
|
||||||
|
f23: freg = ["f23", "fr23"],
|
||||||
|
f24: freg = ["f24", "fr24"],
|
||||||
|
f25: freg = ["f25", "fr25"],
|
||||||
|
f26: freg = ["f26", "fr26"],
|
||||||
|
f27: freg = ["f27", "fr27"],
|
||||||
|
f28: freg = ["f28", "fr28"],
|
||||||
|
f29: freg = ["f29", "fr29"],
|
||||||
|
f30: freg = ["f30", "fr30"],
|
||||||
|
f31: freg = ["f31", "fr31"],
|
||||||
|
#error = ["r1", "1", "sp"] =>
|
||||||
|
"the stack pointer cannot be used as an operand for inline asm",
|
||||||
|
#error = ["r2", "2"] =>
|
||||||
|
"r2 is a system reserved register and cannot be used as an operand for inline asm",
|
||||||
|
#error = ["r13", "13"] =>
|
||||||
|
"r13 is a system reserved register and cannot be used as an operand for inline asm",
|
||||||
|
#error = ["r29", "29"] =>
|
||||||
|
"r29 is used internally by LLVM and cannot be used as an operand for inline asm",
|
||||||
|
#error = ["r30", "30"] =>
|
||||||
|
"r30 is used internally by LLVM and cannot be used as an operand for inline asm",
|
||||||
|
#error = ["r31", "31", "fp"] =>
|
||||||
|
"the frame pointer cannot be used as an operand for inline asm",
|
||||||
|
#error = ["lr"] =>
|
||||||
|
"the link register cannot be used as an operand for inline asm",
|
||||||
|
#error = ["ctr"] =>
|
||||||
|
"the counter register cannot be used as an operand for inline asm",
|
||||||
|
#error = ["vrsave"] =>
|
||||||
|
"the vrsave register cannot be used as an operand for inline asm",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PowerPCInlineAsmReg {
|
||||||
|
pub fn emit(
|
||||||
|
self,
|
||||||
|
out: &mut dyn fmt::Write,
|
||||||
|
_arch: InlineAsmArch,
|
||||||
|
_modifier: Option<char>,
|
||||||
|
) -> fmt::Result {
|
||||||
|
// Strip off the leading prefix.
|
||||||
|
if self as u32 <= Self::r28 as u32 {
|
||||||
|
let index = self as u32 - Self::r28 as u32;
|
||||||
|
write!(out, "{}", index)
|
||||||
|
} else if self as u32 >= Self::f0 as u32 && self as u32 <= Self::f31 as u32 {
|
||||||
|
let index = self as u32 - Self::f31 as u32;
|
||||||
|
write!(out, "{}", index)
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn overlapping_regs(self, mut _cb: impl FnMut(PowerPCInlineAsmReg)) {}
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ Inline assembly is currently supported on the following architectures:
|
||||||
- AArch64
|
- AArch64
|
||||||
- RISC-V
|
- RISC-V
|
||||||
- NVPTX
|
- NVPTX
|
||||||
|
- PowerPC
|
||||||
- Hexagon
|
- Hexagon
|
||||||
- MIPS32r2 and MIPS64r2
|
- MIPS32r2 and MIPS64r2
|
||||||
- wasm32
|
- wasm32
|
||||||
|
@ -459,7 +460,7 @@ options := "options(" option *["," option] [","] ")"
|
||||||
asm := "asm!(" format_string *("," format_string) *("," [ident "="] operand) ["," options] [","] ")"
|
asm := "asm!(" format_string *("," format_string) *("," [ident "="] operand) ["," options] [","] ")"
|
||||||
```
|
```
|
||||||
|
|
||||||
The macro will initially be supported only on ARM, AArch64, Hexagon, x86, x86-64 and RISC-V targets. Support for more targets may be added in the future. The compiler will emit an error if `asm!` is used on an unsupported target.
|
The macro will initially be supported only on ARM, AArch64, Hexagon, PowerPC, x86, x86-64 and RISC-V targets. Support for more targets may be added in the future. The compiler will emit an error if `asm!` is used on an unsupported target.
|
||||||
|
|
||||||
[format-syntax]: https://doc.rust-lang.org/std/fmt/#syntax
|
[format-syntax]: https://doc.rust-lang.org/std/fmt/#syntax
|
||||||
|
|
||||||
|
@ -565,6 +566,9 @@ Here is the list of currently supported register classes:
|
||||||
| RISC-V | `reg` | `x1`, `x[5-7]`, `x[9-15]`, `x[16-31]` (non-RV32E) | `r` |
|
| RISC-V | `reg` | `x1`, `x[5-7]`, `x[9-15]`, `x[16-31]` (non-RV32E) | `r` |
|
||||||
| RISC-V | `freg` | `f[0-31]` | `f` |
|
| RISC-V | `freg` | `f[0-31]` | `f` |
|
||||||
| Hexagon | `reg` | `r[0-28]` | `r` |
|
| Hexagon | `reg` | `r[0-28]` | `r` |
|
||||||
|
| PowerPC | `reg` | `r[0-31]` | `r` |
|
||||||
|
| PowerPC | `reg_nonzero` | | `r[1-31]` | `b` |
|
||||||
|
| PowerPC | `freg` | `f[0-31]` | `f` |
|
||||||
| wasm32 | `local` | None\* | `r` |
|
| wasm32 | `local` | None\* | `r` |
|
||||||
|
|
||||||
> **Note**: On x86 we treat `reg_byte` differently from `reg` because the compiler can allocate `al` and `ah` separately whereas `reg` reserves the whole register.
|
> **Note**: On x86 we treat `reg_byte` differently from `reg` because the compiler can allocate `al` and `ah` separately whereas `reg` reserves the whole register.
|
||||||
|
@ -607,6 +611,9 @@ Each register class has constraints on which value types they can be used with.
|
||||||
| RISC-V | `freg` | `f` | `f32` |
|
| RISC-V | `freg` | `f` | `f32` |
|
||||||
| RISC-V | `freg` | `d` | `f64` |
|
| RISC-V | `freg` | `d` | `f64` |
|
||||||
| Hexagon | `reg` | None | `i8`, `i16`, `i32`, `f32` |
|
| Hexagon | `reg` | None | `i8`, `i16`, `i32`, `f32` |
|
||||||
|
| PowerPC | `reg` | None | `i8`, `i16`, `i32` |
|
||||||
|
| PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32` |
|
||||||
|
| PowerPC | `freg` | None | `f32`, `f64` |
|
||||||
| wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` |
|
| wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` |
|
||||||
|
|
||||||
> **Note**: For the purposes of the above table pointers, function pointers and `isize`/`usize` are treated as the equivalent integer type (`i16`/`i32`/`i64` depending on the target).
|
> **Note**: For the purposes of the above table pointers, function pointers and `isize`/`usize` are treated as the equivalent integer type (`i16`/`i32`/`i64` depending on the target).
|
||||||
|
@ -744,6 +751,9 @@ The supported modifiers are a subset of LLVM's (and GCC's) [asm template argumen
|
||||||
| RISC-V | `reg` | None | `x1` | None |
|
| RISC-V | `reg` | None | `x1` | None |
|
||||||
| RISC-V | `freg` | None | `f0` | None |
|
| RISC-V | `freg` | None | `f0` | None |
|
||||||
| Hexagon | `reg` | None | `r0` | None |
|
| Hexagon | `reg` | None | `r0` | None |
|
||||||
|
| PowerPC | `reg` | None | `0` | None |
|
||||||
|
| PowerPC | `reg_nonzero` | None | `3` | `b` |
|
||||||
|
| PowerPC | `freg` | None | `0` | None |
|
||||||
|
|
||||||
> Notes:
|
> Notes:
|
||||||
> - on ARM `e` / `f`: this prints the low or high doubleword register name of a NEON quad (128-bit) register.
|
> - on ARM `e` / `f`: this prints the low or high doubleword register name of a NEON quad (128-bit) register.
|
||||||
|
|
165
src/test/assembly/asm/powerpc-types.rs
Normal file
165
src/test/assembly/asm/powerpc-types.rs
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
// min-llvm-version: 10.0.1
|
||||||
|
// assembly-output: emit-asm
|
||||||
|
// compile-flags: --target powerpc-unknown-linux-gnu
|
||||||
|
// needs-llvm-components: powerpc
|
||||||
|
|
||||||
|
#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
|
||||||
|
#![crate_type = "rlib"]
|
||||||
|
#![no_core]
|
||||||
|
#![allow(asm_sub_register, non_camel_case_types)]
|
||||||
|
|
||||||
|
#[rustc_builtin_macro]
|
||||||
|
macro_rules! asm {
|
||||||
|
() => {};
|
||||||
|
}
|
||||||
|
#[rustc_builtin_macro]
|
||||||
|
macro_rules! concat {
|
||||||
|
() => {};
|
||||||
|
}
|
||||||
|
#[rustc_builtin_macro]
|
||||||
|
macro_rules! stringify {
|
||||||
|
() => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[lang = "sized"]
|
||||||
|
trait Sized {}
|
||||||
|
#[lang = "copy"]
|
||||||
|
trait Copy {}
|
||||||
|
|
||||||
|
type ptr = *const i32;
|
||||||
|
|
||||||
|
impl Copy for i8 {}
|
||||||
|
impl Copy for u8 {}
|
||||||
|
impl Copy for i16 {}
|
||||||
|
impl Copy for i32 {}
|
||||||
|
impl Copy for i64 {}
|
||||||
|
impl Copy for f32 {}
|
||||||
|
impl Copy for f64 {}
|
||||||
|
impl Copy for ptr {}
|
||||||
|
extern "C" {
|
||||||
|
fn extern_func();
|
||||||
|
static extern_static: u8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hack to avoid function merging
|
||||||
|
extern "Rust" {
|
||||||
|
fn dont_merge(s: &str);
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => {
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe fn $func(x: $ty) -> $ty {
|
||||||
|
dont_merge(stringify!($func));
|
||||||
|
|
||||||
|
let y;
|
||||||
|
asm!(concat!($mov," {}, {}"), out($class) y, in($class) x);
|
||||||
|
y
|
||||||
|
}
|
||||||
|
};}
|
||||||
|
|
||||||
|
macro_rules! check_reg { ($func:ident, $ty:ty, $rego:tt, $regc:tt, $mov:literal) => {
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe fn $func(x: $ty) -> $ty {
|
||||||
|
dont_merge(stringify!($func));
|
||||||
|
|
||||||
|
let y;
|
||||||
|
asm!(concat!($mov, " ", $rego, ", ", $rego), lateout($regc) y, in($regc) x);
|
||||||
|
y
|
||||||
|
}
|
||||||
|
};}
|
||||||
|
|
||||||
|
// CHECK-LABEL: reg_i8:
|
||||||
|
// CHECK: #APP
|
||||||
|
// CHECK: mr {{[0-9]+}}, {{[0-9]+}}
|
||||||
|
// CHECK: #NO_APP
|
||||||
|
check!(reg_i8, i8, reg, "mr");
|
||||||
|
|
||||||
|
// CHECK-LABEL: reg_i16:
|
||||||
|
// CHECK: #APP
|
||||||
|
// CHECK: mr {{[0-9]+}}, {{[0-9]+}}
|
||||||
|
// CHECK: #NO_APP
|
||||||
|
check!(reg_i16, i16, reg, "mr");
|
||||||
|
|
||||||
|
// CHECK-LABEL: reg_i32:
|
||||||
|
// CHECK: #APP
|
||||||
|
// CHECK: mr {{[0-9]+}}, {{[0-9]+}}
|
||||||
|
// CHECK: #NO_APP
|
||||||
|
check!(reg_i32, i32, reg, "mr");
|
||||||
|
|
||||||
|
// CHECK-LABEL: reg_i8_nz:
|
||||||
|
// CHECK: #APP
|
||||||
|
// CHECK: mr {{[0-9]+}}, {{[0-9]+}}
|
||||||
|
// CHECK: #NO_APP
|
||||||
|
check!(reg_i8_nz, i8, reg_nonzero, "mr");
|
||||||
|
|
||||||
|
// CHECK-LABEL: reg_i16_nz:
|
||||||
|
// CHECK: #APP
|
||||||
|
// CHECK: mr {{[0-9]+}}, {{[0-9]+}}
|
||||||
|
// CHECK: #NO_APP
|
||||||
|
check!(reg_i16_nz, i16, reg_nonzero, "mr");
|
||||||
|
|
||||||
|
// CHECK-LABEL: reg_i32_nz:
|
||||||
|
// CHECK: #APP
|
||||||
|
// CHECK: mr {{[0-9]+}}, {{[0-9]+}}
|
||||||
|
// CHECK: #NO_APP
|
||||||
|
check!(reg_i32_nz, i32, reg_nonzero, "mr");
|
||||||
|
|
||||||
|
// CHECK-LABEL: reg_f32:
|
||||||
|
// CHECK: #APP
|
||||||
|
// CHECK: fmr {{[0-9]+}}, {{[0-9]+}}
|
||||||
|
// CHECK: #NO_APP
|
||||||
|
check!(reg_f32, f32, freg, "fmr");
|
||||||
|
|
||||||
|
// CHECK-LABEL: reg_f64:
|
||||||
|
// CHECK: #APP
|
||||||
|
// CHECK: fmr {{[0-9]+}}, {{[0-9]+}}
|
||||||
|
// CHECK: #NO_APP
|
||||||
|
check!(reg_f64, f64, freg, "fmr");
|
||||||
|
|
||||||
|
// CHECK-LABEL: reg_i8_r0:
|
||||||
|
// CHECK: #APP
|
||||||
|
// CHECK: mr 0, 0
|
||||||
|
// CHECK: #NO_APP
|
||||||
|
check_reg!(reg_i8_r0, i8, "0", "0", "mr");
|
||||||
|
|
||||||
|
// CHECK-LABEL: reg_i16_r0:
|
||||||
|
// CHECK: #APP
|
||||||
|
// CHECK: mr 0, 0
|
||||||
|
// CHECK: #NO_APP
|
||||||
|
check_reg!(reg_i16_r0, i16, "0", "0", "mr");
|
||||||
|
|
||||||
|
// CHECK-LABEL: reg_i32_r0:
|
||||||
|
// CHECK: #APP
|
||||||
|
// CHECK: mr 0, 0
|
||||||
|
// CHECK: #NO_APP
|
||||||
|
check_reg!(reg_i32_r0, i32, "0", "0", "mr");
|
||||||
|
|
||||||
|
// CHECK-LABEL: reg_i8_r18:
|
||||||
|
// CHECK: #APP
|
||||||
|
// CHECK: mr 18, 18
|
||||||
|
// CHECK: #NO_APP
|
||||||
|
check_reg!(reg_i8_r18, i8, "18", "18", "mr");
|
||||||
|
|
||||||
|
// CHECK-LABEL: reg_i16_r18:
|
||||||
|
// CHECK: #APP
|
||||||
|
// CHECK: mr 18, 18
|
||||||
|
// CHECK: #NO_APP
|
||||||
|
check_reg!(reg_i16_r18, i16, "18", "18", "mr");
|
||||||
|
|
||||||
|
// CHECK-LABEL: reg_i32_r18:
|
||||||
|
// CHECK: #APP
|
||||||
|
// CHECK: mr 18, 18
|
||||||
|
// CHECK: #NO_APP
|
||||||
|
check_reg!(reg_i32_r18, i32, "18", "18", "mr");
|
||||||
|
|
||||||
|
// CHECK-LABEL: reg_f32_f0:
|
||||||
|
// CHECK: #APP
|
||||||
|
// CHECK: fmr 0, 0
|
||||||
|
// CHECK: #NO_APP
|
||||||
|
check_reg!(reg_f32_f0, f32, "0", "f0", "fmr");
|
||||||
|
|
||||||
|
// CHECK-LABEL: reg_f64_f0:
|
||||||
|
// CHECK: #APP
|
||||||
|
// CHECK: fmr 0, 0
|
||||||
|
// CHECK: #NO_APP
|
||||||
|
check_reg!(reg_f64_f0, f64, "0", "f0", "fmr");
|
Loading…
Add table
Add a link
Reference in a new issue