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
Comments(0)