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にしても意味がないので注意しましょう。そもそも浮動小数点はあまり使うべきでないので、できれば固定小数点を実装しましょう。

検証に使用したコード

#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;
}

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

	.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

No Comment

No comments yet

Leave a reply