AVR-GCCで浮動小数点

AVR-GCCでは浮動小数点も使えてしまいます。実際の計算はGCCが生成するコードによってソフトウエアで実行されますので、あまり使うものではありませんけどね。ところでAVR-GCCにおいてdoubleは倍精度ではありません。 by Y.O

C言語の言語仕様ではビット幅が固定の型にあるように型のサイズが決められていません。浮動小数点型においてもこれは例外ではなく、floatとdoubleも必ず4バイト、8バイトではありません。それではAVR-GCC (avr-gcc (GCC) 4.3.3) での型サイズを見てみましょう。

バイト
char 1
short 2
int 2
long 4
long long 8
double 4
float 4
long double 4

このように実はdoubleとfloatのサイズは同じになっています。floatで精度が足りないからといってdoubleにしても意味がないので注意しましょう。そもそも浮動小数点はあまり使うべきでないので、できれば固定小数点を実装しましょう。

検証に使用したコード
[c]
#include <stdint.h>
#include <stdio.h>

int main(void)
{
volatile uint8_t sizeList[] = {
sizeof(char),
sizeof(short),
sizeof(int),
sizeof(long),
sizeof(long long),
sizeof(double),
sizeof(float),
sizeof(long double),
};

volatile double a = 0.1;
volatile double b = 0.2;
volatile double c = a + b;
}
[/c]

アセンブルしたコード(avr-gcc -O0 -S hello.c -mmcu=atmega88)

[plain]
.file "hello.c"
__SREG__ = 0x3f
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__CCP__ = 0x34
__tmp_reg__ = 0
__zero_reg__ = 1
.data
.type C.0.1373, @object
.size C.0.1373, 8
C.0.1373:
.byte 1
.byte 2
.byte 2
.byte 4
.byte 8
.byte 4
.byte 4
.byte 4
.text
.global main
.type main, @function
main:
push r29
push r28
in r28,__SP_L__
in r29,__SP_H__
sbiw r28,27
in __tmp_reg__,__SREG__
cli
out __SP_H__,r29
out __SREG__,__tmp_reg__
out __SP_L__,r28
/* prologue: function */
/* frame size = 27 */
movw r24,r28
adiw r24,1
std Y+24,r25
std Y+23,r24
ldi r30,lo8(C.0.1373)
ldi r31,hi8(C.0.1373)
std Y+26,r31
std Y+25,r30
ldi r31,lo8(8)
std Y+27,r31
.L2:
ldd r30,Y+25
ldd r31,Y+26
ld r0,Z
ldd r24,Y+25
ldd r25,Y+26
adiw r24,1
std Y+26,r25
std Y+25,r24
ldd r30,Y+23
ldd r31,Y+24
st Z,r0
ldd r24,Y+23
ldd r25,Y+24
adiw r24,1
std Y+24,r25
std Y+23,r24
ldd r25,Y+27
subi r25,lo8(-(-1))
std Y+27,r25
ldd r30,Y+27
tst r30
brne .L2
ldi r24,lo8(0x3dcccccd)
ldi r25,hi8(0x3dcccccd)
ldi r26,hlo8(0x3dcccccd)
ldi r27,hhi8(0x3dcccccd)
std Y+9,r24
std Y+10,r25
std Y+11,r26
std Y+12,r27
ldi r24,lo8(0x3e4ccccd)
ldi r25,hi8(0x3e4ccccd)
ldi r26,hlo8(0x3e4ccccd)
ldi r27,hhi8(0x3e4ccccd)
std Y+13,r24
std Y+14,r25
std Y+15,r26
std Y+16,r27
ldd r24,Y+9
ldd r25,Y+10
ldd r26,Y+11
ldd r27,Y+12
ldd r18,Y+13
ldd r19,Y+14
ldd r20,Y+15
ldd r21,Y+16
movw r22,r24
movw r24,r26
rcall __addsf3
movw r26,r24
movw r24,r22
std Y+17,r24
std Y+18,r25
std Y+19,r26
std Y+20,r27
/* epilogue start */
adiw r28,27
in __tmp_reg__,__SREG__
cli
out __SP_H__,r29
out __SREG__,__tmp_reg__
out __SP_L__,r28
pop r28
pop r29
ret
.size main, .-main
.global __do_copy_data
[/plain]

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です