2

I need to implement a 32-bit Fixed-point on a 16-bit system. My compiler seems to be giving me an "warning: integer overflow in expression". I'm not sure what I'm missing anything :S . I'll provide a dumbed down version of my code below. Any advice would be appreciate :)

#include <stdint.h>
typedef int32_t Q22;

#define Q22base     512
#define Q22_Convert(_a) ((Q22)(_a*Q22base))

int main (){
    // a bunch of code that does stuff goes here
    Q22 variable1=0;

    variable1 = Q22_Convert(some_value1) - Q22_Convert(some_value1);      
    return 0;
}

3 Answers 3

2

There is existing code freely available for implementing 32-bit operations in software. This might be adequate for your purposes.

PIC C code for the 32bit math functions.

////////////////////////////////////////////////////////////////////////////
//                                                                        //
// This code is based on code by Vadim Gerasimov ([email protected]),   //
// and extended skillfully by Mark Newman ([email protected]) for the  //
// Robotic F.A.C.E. project                                               //
//                                                                        //
// Copyright (C) 2001-2004 MIT Media Laboratory                           //
//                                                                        //
////////////////////////////////////////////////////////////////////////////


// 32-bit arithmetic
#define move32(to,from) {to[0]=from[0];to[1]=from[1];to[2]=from[2];to[3]=from[3];}
#define zero32(n) {n[0]=0;n[1]=0;n[2]=0;n[3]=0;}
#define is_zero32(n) ((n[0]|n[1]|n[2]|n[3])==0)
#define inc32(n) {if(++n[0]==0)if(++n[1]==0)if(++n[2]==0)++n[3];}

void dec32 (char* n) {
  if (n[0]--==0) if(n[1]--==0) if (n[2]--==0) --n[3];
}

void add32 (char* a, char* b)
{
   byte r[4];

   r[0] = *(b);
   r[1] = *(b + 1);
   r[2] = *(b + 2);
   r[3] = *(b + 3);

#asm
   movf    a,w
   movwf   4
   movf    r[0],w
   addwf   0,f
   movf    r[1],w
   incf    4,f
   btfsc   3,0
   incfsz  r[1],w
   addwf   0,f
   movf    r[2],w
   incf    4,f
   btfsc   3,0
   incfsz  r[2],w
   addwf   0,f
   movf    r[3],w
   incf    4,f
   btfsc   3,0
   incfsz  r[3],w
   addwf   0,f
#endasm
}

void sub32(char* a, char* b) { // a = a - b
   byte r[4];
   r[0] = *(b);
   r[1] = *(b + 1);
   r[2] = *(b + 2);
   r[3] = *(b + 3);
#asm
   movf    a,w
   movwf   4
   movf    r[0],w
   subwf   0,f
   movf    r[1],w
   incf    4,f
   btfss   3,0
   incfsz  r[1],w
   subwf   0,f
   movf    r[2],w
   incf    4,f
   btfss   3,0
   incfsz  r[2],w
   subwf   0,f
   movf    r[3],w
   incf    4,f
   btfss   3,0
   incfsz  r[3],w
   subwf   0,f
#endasm
}

int lt32(char *a, char *b) {
    int i;
    for (i = 3; i >= 0; i--) {
        if (a[i] > b[i])
            return 0;
        if (a[i] < b[i])
            return 1;
    }
    return 0;
}
int le32(char *a, char *b) {
    int i;
    for (i = 3; i >= 0; i--) {
        if (a[i] < b[i])
            return 1;
        if (a[i] > b[i])
            return 0;
    }
    return 1;
}
int gt32(char *a, char *b) {
    int i;
    for (i = 3; i >= 0; i--) {
        if (a[i] < b[i])
            return 0;
        if (a[i] > b[i])
            return 1;
    }
    return 0;
}
int ge32(char *a, char *b) {
    int i;
    for (i = 3; i >= 0; i--) {
        if (a[i] > b[i])
            return 1;
        if (a[i] < b[i])
            return 0;
    }
    return 1;
}

void shift32(char *n) {
    char i, in, out;
    in = 0;
    for (i = 0; i < 4; i++) {
        out = n[i] >> 7;
        n[i] = in + (n[i] << 1);
        in = out;
    }
}

void mult32byte(char *a, char b) {
    char i;
    char r[4];
    move32(r, a);
    zero32(a);

    for (i = 0; i < 8; i++) {
        if (b & 1)
            add32(a, r);
        b = b >> 1;
        shift32(r);
    }
    a[0] = a[1];
    a[1] = a[2];
    a[2] = a[3];
    a[3] = 0;
}

References


  1. "PIC C code for the 32bit math functions." http://web.media.mit.edu/~stefanm/yano/picc_Math32.html Accessed 2013-11-07
Sign up to request clarification or add additional context in comments.

3 Comments

Quick question. How does this differ from using the defined int32_t which is a signed long int ?
Int32_t may not even be defined on the system, or if it is, the system likely has a library that already handles 32-bit integer arithmetic in software and hides if from you. My example above is in place in the event you want more control and want to manually implement the logic.
Hmm I'll check it out. Learning is fun ^.^
1

Your Q22base is 16-bit on a 16-bit int system, you need to cast it to Q22 so your * expression is done in at least a 32-bit type.

#define Q22_Convert(_a) ((Q22)(_a * (Q22) Q22base))

3 Comments

Thanks a lot that fixed it. Note to self pay attention to data-types.
And the safe way to write a macro is to always put parentheses of parameters in a macro definition, e.g., here replace _a by (_a).
I haven't coded in C, for a while, so I'm really rusty :S scripting languages have ruined me :P thanks for advice I've fixed all my macros.
0

You don't need to cast the constant You can simply write #define Q22base 512L or #define Q22base 512UL

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.