如何将 AVR GCC 风格的 C 内联汇编转换为 Rust 内联汇编?
How do I translate AVR GCC-style C inline assembly to Rust inline assembly?
我想将一些最初用 C++ 编写的 Arduino 代码翻译成 Rust,但是这行内联汇编给我带来了麻烦。
asm volatile(
" lds r16, %[timer0] \n\t" //
#if defined(__AVR_ATmega2560__)
" add r16, %[toffset] \n\t" //
#endif
" subi r16, %[tsync] \n\t" //
" andi r16, 7 \n\t" //
" call TL \n\t" //
"TL: \n\t" //
#if defined(__AVR_ATmega2560__)
" pop r17 \n\t" //ATMEGA2560 has a 22bit PC!
#endif
" pop r31 \n\t" //
" pop r30 \n\t" //
" adiw r30, (LW-TL-5) \n\t" //
" add r30, r16 \n\t" //
//" adc r31, __zero_reg__ \n\t" //
" ijmp \n\t" //
"LW: \n\t" //
" nop \n\t" //
" nop \n\t" //
" nop \n\t" //
" nop \n\t" //
" nop \n\t" //
" nop \n\t" //
" nop \n\t" //
//" nop \n\t" //
"LBEND: \n\t" //
:
: [timer0] "i" (&TCNT0),
[toffset] "i" ((uint8_t)DEJITTER_OFFSET),
[tsync] "i" ((uint8_t)DEJITTER_SYNC)
: "r30", "r31", "r16", "r17");
我最好的尝试是:
const TCNT0: *mut u8 = 70 as *mut u8;
const DEJITTER_OFFSET: u8 = 1;
const DEJITTER_SYNC: i8 = -2;
asm!(
" lds r16, %[timer0]
\t subi r16, %[tsync]
\t andi r16, 7
\t call TL
\tTL:
\t pop r31
\t pop r30
\t adiw r30, (LW-TL-5)
\t add r30, r16
\t ijmp
\tLW:
\t nop
\t nop
\t nop
\t nop
\t nop
\t nop
\t nop
\tLBEND:
\t"
:
: "{timer0}"(&TCNT0),
"{toffset}"(DEJITTER_OFFSET),
"{tsync}"(DEJITTER_SYNC)
: "r30", "r31", "r16": "volatile");
我离编译还差得很远。我尝试编译时显示的错误是:
error: couldn't allocate input reg for constraint '{timer0}'
--> /home/kirbylife/Proyectos/rvgax/src/lib.rs:53:9
|
53 | / asm!(
54 | | r" lds r16, ${timer0}
55 | | subi r16, ${tsync}
56 | | andi r16, 7
... |
77 | | "{tsync}"(DEJITTER_SYNC)
78 | | : "r30", "r31", "r16": "volatile");
| |_______________________________________^
我正在使用 Cargo 和 rustc 1.38.0。
您的错误的直接含义是没有名为 timer0
、toffset
和 tsync
的寄存器。根本原因是 Rust 中的 "{}"
语法表示约束的寄存器名称,而不是符号名称。换句话说,它对应于GCC中的""
东西,而不是[]
东西。我看不到使用符号名称的方法,所以只需改用数字名称即可。此外,它使用 $
而不是 %
来替换约束。试试这个:
const TCNT0: *mut u8 = 70 as *mut u8;
const DEJITTER_OFFSET: u8 = 1;
const DEJITTER_SYNC: i8 = -2;
asm!(
" lds r16, [=10=]
\t subi r16,
\t andi r16, 7
\t call TL
\tTL:
\t pop r31
\t pop r30
\t adiw r30, (LW-TL-5)
\t add r30, r16
\t ijmp
\tLW:
\t nop
\t nop
\t nop
\t nop
\t nop
\t nop
\t nop
\tLBEND:
\t"
:
: "i"(&TCNT0),
"i"(DEJITTER_OFFSET),
"i"(DEJITTER_SYNC)
: "r30", "r31", "r16": "volatile");
(注意:未经测试,因为我目前没有安装 AVR-Rust)
我想将一些最初用 C++ 编写的 Arduino 代码翻译成 Rust,但是这行内联汇编给我带来了麻烦。
asm volatile(
" lds r16, %[timer0] \n\t" //
#if defined(__AVR_ATmega2560__)
" add r16, %[toffset] \n\t" //
#endif
" subi r16, %[tsync] \n\t" //
" andi r16, 7 \n\t" //
" call TL \n\t" //
"TL: \n\t" //
#if defined(__AVR_ATmega2560__)
" pop r17 \n\t" //ATMEGA2560 has a 22bit PC!
#endif
" pop r31 \n\t" //
" pop r30 \n\t" //
" adiw r30, (LW-TL-5) \n\t" //
" add r30, r16 \n\t" //
//" adc r31, __zero_reg__ \n\t" //
" ijmp \n\t" //
"LW: \n\t" //
" nop \n\t" //
" nop \n\t" //
" nop \n\t" //
" nop \n\t" //
" nop \n\t" //
" nop \n\t" //
" nop \n\t" //
//" nop \n\t" //
"LBEND: \n\t" //
:
: [timer0] "i" (&TCNT0),
[toffset] "i" ((uint8_t)DEJITTER_OFFSET),
[tsync] "i" ((uint8_t)DEJITTER_SYNC)
: "r30", "r31", "r16", "r17");
我最好的尝试是:
const TCNT0: *mut u8 = 70 as *mut u8;
const DEJITTER_OFFSET: u8 = 1;
const DEJITTER_SYNC: i8 = -2;
asm!(
" lds r16, %[timer0]
\t subi r16, %[tsync]
\t andi r16, 7
\t call TL
\tTL:
\t pop r31
\t pop r30
\t adiw r30, (LW-TL-5)
\t add r30, r16
\t ijmp
\tLW:
\t nop
\t nop
\t nop
\t nop
\t nop
\t nop
\t nop
\tLBEND:
\t"
:
: "{timer0}"(&TCNT0),
"{toffset}"(DEJITTER_OFFSET),
"{tsync}"(DEJITTER_SYNC)
: "r30", "r31", "r16": "volatile");
我离编译还差得很远。我尝试编译时显示的错误是:
error: couldn't allocate input reg for constraint '{timer0}'
--> /home/kirbylife/Proyectos/rvgax/src/lib.rs:53:9
|
53 | / asm!(
54 | | r" lds r16, ${timer0}
55 | | subi r16, ${tsync}
56 | | andi r16, 7
... |
77 | | "{tsync}"(DEJITTER_SYNC)
78 | | : "r30", "r31", "r16": "volatile");
| |_______________________________________^
我正在使用 Cargo 和 rustc 1.38.0。
您的错误的直接含义是没有名为 timer0
、toffset
和 tsync
的寄存器。根本原因是 Rust 中的 "{}"
语法表示约束的寄存器名称,而不是符号名称。换句话说,它对应于GCC中的""
东西,而不是[]
东西。我看不到使用符号名称的方法,所以只需改用数字名称即可。此外,它使用 $
而不是 %
来替换约束。试试这个:
const TCNT0: *mut u8 = 70 as *mut u8;
const DEJITTER_OFFSET: u8 = 1;
const DEJITTER_SYNC: i8 = -2;
asm!(
" lds r16, [=10=]
\t subi r16,
\t andi r16, 7
\t call TL
\tTL:
\t pop r31
\t pop r30
\t adiw r30, (LW-TL-5)
\t add r30, r16
\t ijmp
\tLW:
\t nop
\t nop
\t nop
\t nop
\t nop
\t nop
\t nop
\tLBEND:
\t"
:
: "i"(&TCNT0),
"i"(DEJITTER_OFFSET),
"i"(DEJITTER_SYNC)
: "r30", "r31", "r16": "volatile");
(注意:未经测试,因为我目前没有安装 AVR-Rust)