Skip to content

Add asm! support for mips64 #77337

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Oct 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion compiler/rustc_codegen_llvm/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {}
InlineAsmArch::Nvptx64 => {}
InlineAsmArch::Hexagon => {}
InlineAsmArch::Mips => {}
InlineAsmArch::Mips | InlineAsmArch::Mips64 => {}
}
}
if !options.contains(InlineAsmOptions::NOMEM) {
Expand Down Expand Up @@ -710,6 +710,7 @@ fn llvm_fixup_input(
// MIPS only supports register-length arithmetics.
Primitive::Int(Integer::I8 | Integer::I16, _) => bx.zext(value, bx.cx.type_i32()),
Primitive::F32 => bx.bitcast(value, bx.cx.type_i32()),
Primitive::F64 => bx.bitcast(value, bx.cx.type_i64()),
_ => value,
},
_ => value,
Expand Down Expand Up @@ -785,6 +786,7 @@ fn llvm_fixup_output(
Primitive::Int(Integer::I8, _) => bx.trunc(value, bx.cx.type_i8()),
Primitive::Int(Integer::I16, _) => bx.trunc(value, bx.cx.type_i16()),
Primitive::F32 => bx.bitcast(value, bx.cx.type_f32()),
Primitive::F64 => bx.bitcast(value, bx.cx.type_f64()),
_ => value,
},
_ => value,
Expand Down Expand Up @@ -854,6 +856,7 @@ fn llvm_fixup_output_type(
// MIPS only supports register-length arithmetics.
Primitive::Int(Integer::I8 | Integer::I16, _) => cx.type_i32(),
Primitive::F32 => cx.type_i32(),
Primitive::F64 => cx.type_i64(),
_ => layout.llvm_type(cx),
},
_ => layout.llvm_type(cx),
Expand Down
73 changes: 37 additions & 36 deletions compiler/rustc_target/src/asm/mips.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,43 +32,44 @@ impl MipsInlineAsmRegClass {

pub fn supported_types(
self,
_arch: InlineAsmArch,
arch: InlineAsmArch,
) -> &'static [(InlineAsmType, Option<&'static str>)] {
match self {
Self::reg => types! { _: I8, I16, I32, F32; },
Self::freg => types! { _: F32; },
match (self, arch) {
(Self::reg, InlineAsmArch::Mips64) => types! { _: I8, I16, I32, I64, F32, F64; },
(Self::reg, _) => types! { _: I8, I16, I32, F32; },
(Self::freg, _) => types! { _: F32, F64; },
}
}
}

// The reserved registers are somewhat taken from <https://git.io/JUR1k#L150>.
def_regs! {
Mips MipsInlineAsmReg MipsInlineAsmRegClass {
v0: reg = ["$2", "$v0"],
v1: reg = ["$3", "$v1"],
a0: reg = ["$4", "$a0"],
a1: reg = ["$5", "$a1"],
a2: reg = ["$6", "$a2"],
a3: reg = ["$7", "$a3"],
r2: reg = ["$2"],
r3: reg = ["$3"],
r4: reg = ["$4"],
r5: reg = ["$5"],
r6: reg = ["$6"],
r7: reg = ["$7"],
// FIXME: Reserve $t0, $t1 if in mips16 mode.
t0: reg = ["$8", "$t0"],
t1: reg = ["$9", "$t1"],
t2: reg = ["$10", "$t2"],
t3: reg = ["$11", "$t3"],
t4: reg = ["$12", "$t4"],
t5: reg = ["$13", "$t5"],
t6: reg = ["$14", "$t6"],
t7: reg = ["$15", "$t7"],
s0: reg = ["$16", "$s0"],
s1: reg = ["$17", "$s1"],
s2: reg = ["$18", "$s2"],
s3: reg = ["$19", "$s3"],
s4: reg = ["$20", "$s4"],
s5: reg = ["$21", "$s5"],
s6: reg = ["$22", "$s6"],
s7: reg = ["$23", "$s7"],
t8: reg = ["$24", "$t8"],
t9: reg = ["$25", "$t9"],
r8: reg = ["$8"],
r9: reg = ["$9"],
r10: reg = ["$10"],
r11: reg = ["$11"],
r12: reg = ["$12"],
r13: reg = ["$13"],
r14: reg = ["$14"],
r15: reg = ["$15"],
r16: reg = ["$16"],
r17: reg = ["$17"],
r18: reg = ["$18"],
r19: reg = ["$19"],
r20: reg = ["$20"],
r21: reg = ["$21"],
r22: reg = ["$22"],
r23: reg = ["$23"],
r24: reg = ["$24"],
r25: reg = ["$25"],
f0: freg = ["$f0"],
f1: freg = ["$f1"],
f2: freg = ["$f2"],
Expand Down Expand Up @@ -101,21 +102,21 @@ def_regs! {
f29: freg = ["$f29"],
f30: freg = ["$f30"],
f31: freg = ["$f31"],
#error = ["$0", "$zero"] =>
#error = ["$0"] =>
"constant zero cannot be used as an operand for inline asm",
#error = ["$1", "$at"] =>
#error = ["$1"] =>
"reserved for assembler (Assembler Temp)",
#error = ["$26", "$k0"] =>
#error = ["$26"] =>
"OS-reserved register cannot be used as an operand for inline asm",
#error = ["$27", "$k1"] =>
#error = ["$27"] =>
"OS-reserved register cannot be used as an operand for inline asm",
#error = ["$28", "$gp"] =>
#error = ["$28"] =>
"the global pointer cannot be used as an operand for inline asm",
#error = ["$29", "$sp"] =>
#error = ["$29"] =>
"the stack pointer cannot be used as an operand for inline asm",
#error = ["$30", "$s8", "$fp"] =>
#error = ["$30"] =>
"the frame pointer cannot be used as an operand for inline asm",
#error = ["$31", "$ra"] =>
#error = ["$31"] =>
"the return address register cannot be used as an operand for inline asm",
}
}
Expand Down
10 changes: 7 additions & 3 deletions compiler/rustc_target/src/asm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ pub enum InlineAsmArch {
Nvptx64,
Hexagon,
Mips,
Mips64,
}

impl FromStr for InlineAsmArch {
Expand All @@ -192,6 +193,7 @@ impl FromStr for InlineAsmArch {
"nvptx64" => Ok(Self::Nvptx64),
"hexagon" => Ok(Self::Hexagon),
"mips" => Ok(Self::Mips),
"mips64" => Ok(Self::Mips64),
_ => Err(()),
}
}
Expand Down Expand Up @@ -259,7 +261,7 @@ impl InlineAsmReg {
InlineAsmArch::Hexagon => {
Self::Hexagon(HexagonInlineAsmReg::parse(arch, has_feature, target, &name)?)
}
InlineAsmArch::Mips => {
InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
Self::Mips(MipsInlineAsmReg::parse(arch, has_feature, target, &name)?)
}
})
Expand Down Expand Up @@ -409,7 +411,9 @@ impl InlineAsmRegClass {
InlineAsmArch::Hexagon => {
Self::Hexagon(HexagonInlineAsmRegClass::parse(arch, name)?)
}
InlineAsmArch::Mips => Self::Mips(MipsInlineAsmRegClass::parse(arch, name)?),
InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
Self::Mips(MipsInlineAsmRegClass::parse(arch, name)?)
}
})
})
}
Expand Down Expand Up @@ -565,7 +569,7 @@ pub fn allocatable_registers(
hexagon::fill_reg_map(arch, has_feature, target, &mut map);
map
}
InlineAsmArch::Mips => {
InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
let mut map = mips::regclass_map();
mips::fill_reg_map(arch, has_feature, target, &mut map);
map
Expand Down
27 changes: 13 additions & 14 deletions src/doc/unstable-book/src/library-features/asm.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Inline assembly is currently supported on the following architectures:
- RISC-V
- NVPTX
- Hexagon
- MIPS32
- MIPS32r2 and MIPS64r2

## Basic usage

Expand Down Expand Up @@ -513,8 +513,8 @@ Here is the list of currently supported register classes:
| ARM | `qreg` | `q[0-15]` | `w` |
| ARM | `qreg_low8` | `q[0-7]` | `t` |
| ARM | `qreg_low4` | `q[0-3]` | `x` |
| MIPS32 | `reg` | `$[2-25]` | `r` |
| MIPS32 | `freg` | `$f[0-31]` | `f` |
| MIPS | `reg` | `$[2-25]` | `r` |
| MIPS | `freg` | `$f[0-31]` | `f` |
| NVPTX | `reg16` | None\* | `h` |
| NVPTX | `reg32` | None\* | `r` |
| NVPTX | `reg64` | None\* | `l` |
Expand Down Expand Up @@ -551,7 +551,9 @@ Each register class has constraints on which value types they can be used with.
| ARM | `dreg` | `vfp2` | `i64`, `f64`, `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2` |
| ARM | `qreg` | `neon` | `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4` |
| MIPS32 | `reg` | None | `i8`, `i16`, `i32`, `f32` |
| MIPS32 | `freg` | None | `f32` |
| MIPS32 | `freg` | None | `f32`, `f64` |
| MIPS64 | `reg` | None | `i8`, `i16`, `i32`, `i64`, `f32`, `f64` |
| MIPS64 | `freg` | None | `f32`, `f64` |
| NVPTX | `reg16` | None | `i8`, `i16` |
| NVPTX | `reg32` | None | `i8`, `i16`, `i32`, `f32` |
| NVPTX | `reg64` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
Expand Down Expand Up @@ -600,7 +602,6 @@ Some registers have multiple names. These are all treated by the compiler as ide
| ARM | `r13` | `sp` |
| ARM | `r14` | `lr` |
| ARM | `r15` | `pc` |
| MIPS32 | `$[2-25]` | Please [see the Wikipedia page][mips-regs] |
| RISC-V | `x0` | `zero` |
| RISC-V | `x1` | `ra` |
| RISC-V | `x2` | `sp` |
Expand All @@ -621,8 +622,6 @@ Some registers have multiple names. These are all treated by the compiler as ide
| Hexagon | `r30` | `fr` |
| Hexagon | `r31` | `lr` |

[mips-regs]: https://en.wikibooks.org/wiki/MIPS_Assembly/Register_File#Registers

Some registers cannot be used for input or output operands:

| Architecture | Unsupported register | Reason |
Expand All @@ -637,11 +636,11 @@ Some registers cannot be used for input or output operands:
| x86 | `st([0-7])` | x87 registers are not currently supported (but may be in the future). |
| AArch64 | `xzr` | This is a constant zero register which can't be modified. |
| ARM | `pc` | This is the program counter, not a real register. |
| MIPS32 | `$0` or `$zero` | This is a constant zero register which can't be modified. |
| MIPS32 | `$1` or `$at` | Reserved for assembler. |
| MIPS32 | `$26`/`$k0`, `$27`/`$k1` | OS-reserved registers. |
| MIPS32 | `$28`/`$gp` | Global pointer cannot be used as inputs or outputs. |
| MIPS32 | `$ra` | Return address cannot be used as inputs or outputs. |
| MIPS | `$0` or `$zero` | This is a constant zero register which can't be modified. |
| MIPS | `$1` or `$at` | Reserved for assembler. |
| MIPS | `$26`/`$k0`, `$27`/`$k1` | OS-reserved registers. |
| MIPS | `$28`/`$gp` | Global pointer cannot be used as inputs or outputs. |
| MIPS | `$ra` | Return address cannot be used as inputs or outputs. |
| RISC-V | `x0` | This is a constant zero register which can't be modified. |
| RISC-V | `gp`, `tp` | These registers are reserved and cannot be used as inputs or outputs. |
| Hexagon | `lr` | This is the link register which cannot be used as an input or output. |
Expand Down Expand Up @@ -689,8 +688,8 @@ The supported modifiers are a subset of LLVM's (and GCC's) [asm template argumen
| ARM | `dreg` | None | `d0` | `P` |
| ARM | `qreg` | None | `q0` | `q` |
| ARM | `qreg` | `e` / `f` | `d0` / `d1` | `e` / `f` |
| MIPS32 | `reg` | None | `$2` | None |
| MIPS32 | `freg` | None | `$f0` | None |
| MIPS | `reg` | None | `$2` | None |
| MIPS | `freg` | None | `$f0` | None |
| NVPTX | `reg16` | None | `rs0` | None |
| NVPTX | `reg32` | None | `r0` | None |
| NVPTX | `reg64` | None | `rd0` | None |
Expand Down
Loading