输出“i8”时,从内联汇编中删除多余的“andi ..., 0xff”指令

Fil*_*ues 7 mips inline-assembly rust

我有以下使用内联汇编的函数,目标mipsel-unknown-linux-gnu

#![feature(asm)]

#[no_mangle]
pub unsafe extern "C" fn f(ptr: u32) {
    let value: i8;
    asm!(
        "lb $v0, ($a0)",
        in("$4") ptr,
        out("$2") value,
    );
    asm!(
        "sb $v0, ($a0)",
        in("$4") ptr,
        in("$2") value,
    );
}
Run Code Online (Sandbox Code Playgroud)

我预计这会编译成以下内容:

lb $v0, ($a0)
sb $v0, ($a0)
jr $ra
nop
Run Code Online (Sandbox Code Playgroud)

注意:在此示例中,编译器可能会在跳转后将存储指令重新排序以使用延迟槽,但在我的实际用例中,我通过块返回asm,因此不必担心。鉴于此,我完全预料到了上面的装配。

相反,我得到的是:

00000000 <f>:
   0:   80820000        lb      v0,0(a0)
   4:   304200ff        andi    v0,v0,0xff
   8:   a0820000        sb      v0,0(a0)
   c:   03e00008        jr      ra
  10:   00000000        nop
Run Code Online (Sandbox Code Playgroud)

编译器似乎不相信我的输出是 ani8andi $v0, 0xff在那里插入了一条指令。

我需要准确地生成上面指定的程序集,因此我想删除该andi指令,同时保留 i8 的类型value

我的用例是,我希望从此函数生成精确的汇编输出,同时能够稍后分叉它并添加与现有汇编代码交互的 Rust 代码以扩展该函数。为此,我希望将value的类型正确地描述为i8in the rust side。

编辑

查看rust生成的llvm-ir,该andi指令似乎是由添加的rustc,而不是llvm。

; Function Attrs: nonlazybind uwtable
define void @f(i32 %ptr) unnamed_addr #0 {
start:
  %0 = tail call i32 asm sideeffect alignstack "lbu $$v0, ($$a0)", "=&{$2},{$4},~{memory}"(i32 %ptr) #1, !srcloc !2
  %1 = and i32 %0, 255   # <--------- Over here
  tail call void asm sideeffect alignstack "sb $$v0, ($$a0)", "{$4},{$2},~{memory}"(i32 %ptr, i32 %1) #1, !srcloc !3
  ret void
}
Run Code Online (Sandbox Code Playgroud)

也没有提到 an i8,所以我不太确定rustc这里在做什么。