From: Ivan Petrushev <ivanatora@gm...>  20080203 20:36:43

Hello, For a few days I'm trying to debug one C source and a sort of a question is are there arithmetics limitations for PIC16? I mean they have no instructions for multiplication, division and floating points, but there are such operators in C. Also data types  int is 2 bytes, right? What happens if I try to assign 8bit number to an int? Lets discuss the following snipplet of code: <code> int x = ADRESH; //after an ADC conversion is done  ADRESH is 8bit, if there is a value like 0xf1, is x == 0xf1? x = x * 4; //this is simple multiplication and I assume the compiler optimizes it with shifting and rotating, but what happens if there were multiplication by 3, or by some fractional number like 0.48 or 0.6666... ? What happens if the result is too big for the int type (more than 2 bytes), and what happens with the result if there is a fractional result? If I have 3 * 0.5 = 1.5 what will x contain? x = x /4; //the same questions x = 11; //after that step will x be equal to 0x000b ? float y; //how the float will be interpreted? </code> Regards, Ivan. 
From: Raphael Neider <rneider@we...>  20080203 22:25:59

Hi Ivan, > For a few days I'm trying to debug one C source and a sort of a > question is are there arithmetics limitations for PIC16? I mean they > have no instructions for multiplication, division and floating points, > but there are such operators in C. Complex arithmetics (everything beyond 8bit addition/subtraction) is emulated in software. Multibyte addtions/subtractions are fairly efficient inline, most others, notably multibyte multiplications and all divisions, are implemented as C routines in the libraries. To my knowledge, even floating point arithmetics (single precision, 32 bits?) is implemented, though I wonder if using it on an 8 bit micro is the best of solutions... Reportedly it works. > Also data types  int is 2 bytes, right? Yep. > What happens if I try to assign 8bit number to an int? Depends... > Lets discuss the following snipplet of code: > <code> > int x = ADRESH; //after an ADC conversion is done  ADRESH is 8bit, if > there is a value like 0xf1, is x == 0xf1? Depends... either ADRESH is considered to be unsigned, in which case x would be 0x00f1, or ADRESH is considered to be signed, in which case x would be 0xfff1. In this case, ADRESH is declared as an sfr, and these are considered to be entities close to 'volatile unsigned char'. For clarity, you could explicitly cast your 8bit value: int x = (unsigned char)ADRESH; This forces the compiler to consider ADRESH as unsigned and to zerofill the upper byte of x. For signextension, use int x = (signed char)ADRESH; // or simply (char)ADRESH > x = x * 4; //this is simple multiplication and I assume the compiler > optimizes it with shifting and rotating, but what happens if there > were multiplication by 3, or by some fractional number like 0.48 or > 0.6666... ? Yep, multiplications by powers of two are optimized, others (including x=3*x or x = x*x with statically unknown x) are turned into function calls to emulate the maths in software. > What happens if the result is too big for the int type > (more than 2 bytes), As usual, the result will be correct modulo the size of the data type, i.e., it wraps around. > and what happens with the result if there is a > fractional result? int x int > int yields truncated results int x int > float yields truncated results, converted to float (or error) int x float > int and float x int > int yield a complex float operation followed by truncating the result to an int (and a warning or even error about loosing precision or invalid implicit cast from float to int) int x float > float and float x float > float and float x float > float yield complex floating point maths with floating point results All of this is plain ANSI C and not specific to SDCC. > If I have 3 * 0.5 = 1.5 what will x contain? Depends on the type of x, see above. > x = x /4; //the same questions Same answer. If x is integral, the result will be truncated. > x = 11; //after that step will x be equal to 0x000b ? Yep, though 11 is implicitly promoted to a 16bit value equalling 11 internally (i.e., 00011 decimal or your 0x000b hex). > float y; //how the float will be interpreted? Well, as a IEEE floating point number. Beware of rather large and slow arithmetics, though... Regards, Raphael 
From: Paul Stoffregen <paul@pj...>  20080204 22:50:16

> even floating point arithmetics (single precision, 32 bits?) > is implemented, though I wonder if using it on an 8 bit micro is the > best of solutions... Reportedly it works. > On mcs51 (8051), most of the float library is implemented in assembly (by me). It's not as fast as integer, of course, but the speed and size aren't that bad. You're not going to do any serious number crunching on an 8 bit 8051, but if you just want to do a few hundred calculations per second, or want to scale some data the "easy" way, it really works pretty well. The hardest part is printing floats. I wrote a printf_fast_f that has limited float printing (can't print great than 2^32 magnitude, precision is limited to 8 digits past the decimal), but it prints them very quickly without using much memory, and it does support format control. There's also an optional "fixed 4 digit" float print that is very small (just a few hundred bytes of code) and fast, though the output format isn't flexible at all. There is complete float support in printf_large, but the code size is much bigger and the speed is much slower. Writing a float library and float capable printf in assembly can seem daunting at first, but it's really not that difficult. If anyone wants to give it a try on the PIC, I'd be happy to help guide you though using the mcs51 code as a starting point. There is also a what appears to be a very nice float library for the PIC already written. Maybe it could be ported/integrated to SDCC? http://picfloat.sourceforge.net/ Paul 