CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

address calculation problem with new compiler version

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
freddy_mp



Joined: 07 Jun 2013
Posts: 1

View user's profile Send private message

address calculation problem with new compiler version
PostPosted: Fri Jun 07, 2013 7:59 am     Reply with quote

Hi
I used the version V3 for a lot of projects.
Now I change to Version5. (V5.005 )
And I have some unexpected failures.

I use this to split a long int to lo and hi byte:

Code:
#define hi(x)  (*(&x+1))
#define lo(x)  (*(&x))
 
long int h;
h=0x1122;
lo(h) gives 0x22 (correct)
hi(h) gives 0x22 (incorrect, expect 0x11 )
 

It works fine with later versions of the compiler.
But with the actual compiler I got the low-byte every time.
What is changed and what is the solution for this problem??
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Fri Jun 07, 2013 8:48 am     Reply with quote

do you know about the make8() function?

it is VERY code efficient and works in all compiler versions.
drh



Joined: 12 Jul 2004
Posts: 192
Location: Hemet, California USA

View user's profile Send private message

PostPosted: Fri Jun 07, 2013 8:53 am     Reply with quote

There was a change in one of the 4.xxx versions. This is from the V4.139 readme file:

Quote:
Users that have old code with expresions of the form:
*(&data + i)
need to change them to:
*((int8 *)(&data) + i)
A compiler change was made to be ANSI compliant.


Jumping from V3.xxx to V5.005, you have missed about 141 "versions"
_________________
David
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Fri Jun 07, 2013 1:07 pm     Reply with quote

Quote:
Users that have old code with expresions of the form:
*(&data + i)
need to change them to:
*((int8 *)(&data) + i)
A compiler change was made to be ANSI compliant.


The change is regarding the pointer type assumed in address arithmetic. The ANSI standard expect
an address increment according to the type of the variable. To address the high byte, you need a typecast to
int8 pointer type.

Although the suggested change does "work" (= gives correct result) in CCS V4.xxx, it produces ridiculous long
winded code, as you can see below. compare with make8() code.

Code:
                    00531 .................... b = lo(h);
010C 6A03           00532 CLRF   03
010E 0E4B           00533 MOVLW  4B
0110 6EE9           00534 MOVWF  FE9
0112 C003 FFEA      00535 MOVFF  03,FEA
0116 CFEF F048      00536 MOVFF  FEF,48
                    00537 .................... b = hi(h);
011A 6A4E           00538 CLRF   4E
011C 0E4B           00539 MOVLW  4B
011E 6E4D           00540 MOVWF  4D
0120 0E01           00541 MOVLW  01
0122 244D           00542 ADDWF  4D,W
0124 6E01           00543 MOVWF  01
0126 0E00           00544 MOVLW  00
0128 204E           00545 ADDWFC 4E,W
012A C001 FFE9      00546 MOVFF  01,FE9
012E 6EEA           00547 MOVWF  FEA
0130 CFEF F048      00548 MOVFF  FEF,48


Code:
                    00550 .................... b=make8(h,0);
0134 C04B F048      00551 MOVFF  4B,48
                    00552 .................... b=make8(h,1);
0138 C04C F048      00553 MOVFF  4C,48


The original hi(x) code accesses the byte at offset +2, thus it does not return the low byte. Either the
respective byte holds the value 0x22 by chance, or there's a new bug in CCS V5.005.

I was assuming PCH (PIC18 code).

P.S.: I checked with PCH V5.006, the code is working as with recent V4.xxx versions.
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Fri Jun 07, 2013 1:45 pm     Reply with quote

and, I should point out that it is not just ANSI, but the original K&R definitions that require a pointer to increment by the object size.
It was a major bug in the earlier CCS versions, in terms of 'C' as a whole...

Best Wishes
drh



Joined: 12 Jul 2004
Posts: 192
Location: Hemet, California USA

View user's profile Send private message

PostPosted: Fri Jun 07, 2013 3:13 pm     Reply with quote

And we can probably expect and should be prepared for the standard "first 50 versions are buggy" feature in version 5. Sad
_________________
David
drh



Joined: 12 Jul 2004
Posts: 192
Location: Hemet, California USA

View user's profile Send private message

PostPosted: Fri Jun 07, 2013 3:15 pm     Reply with quote

asmboy wrote:
do you know about the make8() function?

it is VERY code efficient and works in all compiler versions.


This is what I did.
_________________
David
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Fri Jun 07, 2013 3:56 pm     Reply with quote

i almost forgot . this is just as efficient as make8() and for
some situations - perhaps more notationally compact ?

Code:

typedef struct {
    int8 lowb;
    int8 highb;
}ezmake;

ezmake myvar;
//  myvar becomes effectively an unsigned int16
//  low byte ,   int8  myvar.lowb
//  high  byte , int8  myvar.highb

Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Fri Jun 07, 2013 11:35 pm     Reply with quote

The slightly more 'complete' version, is using a union:

Code:

   typedef struct {
      int8 lowb;
      int8 highb;
   }ezmake;

   union {
      ezmake b;
      int16 word;
   } val;

   int bval;
   val.word=0x1122;
   bval = val.b.lowb;
   //reads 0x22
   bval = val.b.highb;
   //reads 0x11
   
   val.b.lowb=0x44;
   val.b.highb=0x22;
   //val.word, is now 0x2244


Now the nice thing is the assembler.
Code:

....................    val.word=0x1122;
0114:  MOVLW  11
0116:  MOVWF  1A
0118:  MOVLW  22
011A:  MOVWF  19
....................    index = val.b.lowb;
011C:  MOVFF  19,1B
....................    index = val.b.highb;
0120:  MOVFF  1A,1B
....................     
....................    val.b.lowb=0x44;
0124:  MOVLW  44
0126:  MOVWF  19
....................    val.b.highb=0x22;
0128:  MOVLW  22
012A:  MOVWF  1A


As efficient as possible, and the code looks nice too. Smile

Best Wishes
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Sat Jun 08, 2013 3:26 am     Reply with quote

Quote:
And we can probably expect and should be prepared for the standard "first 50 versions are buggy" feature in version 5.

This was my first thought when hearing about CCS C V5 release. But hopefully it isn't the case. It depends
on how much the compiler core design has been touched with the implementation of new features.

I ought a comment on the CCS way of translating (*(&x)) in my previous post. Experienced CCS users
avoid such constructs because they know about the limited compiler capabilities to understand it's meaning.
But why is it so? CCS C seems to evaluate these constructs stepwise like a school starter reads a sentence,
(creating a pointer and dereferencing it), so it manages to blow up 2 instructions cycles to 7 or even 13.

Poorly supported standard C constructs like (*(&x)) are an issue when software components or full projects
are ported between processor platforms or different tools and involve a lot of manual rework.
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Sat Jun 08, 2013 1:14 pm     Reply with quote

Quote:

seems to evaluate these constructs stepwise like a school starter reads a sentence


I have noticed this in other instances too -
but could it be that this is simply an unavoidable consequence
of being a single pass compiler?

You can chalk it up to my paranoia - but i confess openly that i may tend to over-specify nested math to insure correct OoO prioritization and casting
to avoid any potential for ambiguity in the compilation process.

such as :

Code:

unsigned int8 whatever; // even though unsigned IS the default
unsigned int32 thatone;

// and then

thatone= (unsigned int32) whatever * (33L /( (7L*thatone) * (unsigned int32) (whatever-7)));
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group