gpt4 book ai didi

c++ - 如何优化 C++ avr 代码

转载 作者:太空狗 更新时间:2023-10-29 22:55:56 25 4
gpt4 key购买 nike

要设置或清除寄存器中的位,我使用以下代码:

template<int... pos, class Int>
static constexpr void write_one(Int& i)
{
using expand = int[];
expand{0,((i |= (Int{1} << pos)), 0)...};
}

template<int... pos, class Int>
static constexpr void write_zero(Int& i)
{
using expand = int[];
expand{0,((i &= ~(Int{1} << pos)), 0)...};
}

它工作正常。为了测试它的效率,我写了 2 个测试函数:

// The most efficiency
while(1){
PORTB |= (1 << PB0);
PORTB &= ~(1 << PB0);
}

// This is the one I want to measure
while(1){
Bit::write_one<PB0>(PORTB);
Bit::write_zero<PB0>(PORTB);
}

当我用示波器测量时间时,第二个需要更多时间,所以我分解代码得到以下内容:

; This is the first one (of course, the most efficient)
000000c8 <_Z12testv>:
ce: 28 9a sbi 0x05, 0 ; 5
d0: 28 98 cbi 0x05, 0 ; 5
d2: fd cf rjmp .-6 ; 0xce <_Z12testv+0x6>

; The second one
000000c8 <_Z12testv>:
; The compiler optimize perfectly write_one<PB0>(PORTB)
ce: 28 9a sbi 0x05, 0 ; 5

; but, look what happens with write_zero<PB0>(PORTB)!!!
; Why the compiler can't write "cbi"???
; Here is the problem:
d0: 85 b1 in r24, 0x05 ; 5
d2: 90 e0 ldi r25, 0x00 ; 0
d4: 8e 7f andi r24, 0xFE ; 254
d6: 85 b9 out 0x05, r24 ; 5

d8: fa cf rjmp .-12 ; 0xce <_Z12testv+0x6>

我正在使用带有 -O3 标志的 avr-g++ 4.9.2。

最佳答案

template<int... pos, class Int>
static constexpr void write_one(Int& i)
{
using expand = int[];
expand{0,((i |= (Int{1} << pos)), 0)...};
}
template<int... pos, class Int>
static constexpr void write_zero(Int& i)
{
using expand = int[];
expand{0,((i &= ~(Int{1} << pos)), 0)...};
}
I

Bit::write_one<PB0>(PORTB);
Bit::write_zero<PB0>(PORTB);

int[2] { 0, ((i |= (Int{1} << pos)), 0) }

int[2] { 0, 0 } // a tmp that is a nop
(i |= (Int{1} << pos))

(i |= (decl_type(PORTB){1} << int { PB0 }))

PORTB 看起来像是一个可变的 uint5_t 可能值 0-31 ( AVR ),值为 0x5

(i |= ( uint5_t{1} << int {0}))

1 和 0 是文字/constexpr,所以它给出 1。

i |= 1

哪些代码生成

sbi 0x5, 0 // set port 5 bit 0


expand{0,((i &= ~(Int{1} << pos)), 0)...};

遵循相同的逻辑给出

(i &= ~(1))

给出代码

d0: 85 b1           in  r24, 0x05   ; 5
d2: 90 e0 ldi r25, 0x00 ; 0 <---------- this value is not used nor set any flags???
d4: 8e 7f andi r24, 0xFE ; 254 (i &= ~(1))
d6: 85 b9 out 0x05, r24 ; 5

因此结论必须是 AVR 的代码生成中存在错误,因为它会生成虚假指令。

ldi的解释

关于c++ - 如何优化 C++ avr 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49828829/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com