Dmitry,

Quite right, you are. I As you suggest, I get similar results on i386 when using pointers that involve the sign bit. I find that a bit troubling for i386 as well. It would seem that subtracting pointers can in general be unsafe. I suppose it would be prudent to cast them to unsigned types and go from there.
Thanks for your insight.

Walt

Dmitry wrote:

Well,
this problem is more 'general C' than msp430 I think...
Agree, this is not documented (yet), however:

Well, pointers usually have to same size as 'int'. In case of msp430 this is 2 bytes. Usually, compilers operate with pointers as with 'unsigned int' variable. (at least in case of mspgcc unless you pass -mint8).
However, when you 'diff' two pointers gcc considers this to be 'signed int'
(still 2 bytes). Then divides this 'diff' by type size in order 'diff' to be equial the number of 'type' elements between two pointers.

So, the thing you see in your example:
(0x7000 - 0x1000) >> 2 == 0x1800; 2 bytes. Extend to 4 byte var gives 0x00001800

(0xf000-0x1000) >> 2 == 0xe000>>2 == 0xf800; 2 bytes. Extend to 4 bytes gives 0xfffff800


In case you're play with i368, the last numbers are:
(0x0000f0000 - 0x000010000) >>2 == 0x0000e000 >> 2 == 0x00003800
To prove this, try 0x10000000 and 0xf0000000 on i368 and check.


Hope this helps.
~d




On Tuesday 31 December 2002 05:17, Walt Spicker wrote:
David,

Your point is well taken.  I guess this could be considered
inconsequential given the memory layout of the MSP430s.  I stumbled
across it in an application that transmits large chunks of data stored
in an external memory.  I don't have the external memory available at
present, so I was just dumping the contents of flash in order to have
something to send.  I then noticed that my pointers did not have the
expected values when I started walking through memory.   So I contrived
a simple example to demonstrate the problem, and here we are.

I don't really think that I need to see this get fixed, but it does seem
to expose a weakness in the generated code that may have more important
side affects elsewhere.

Thanks again,

Walt

David Dyck wrote:
Your initial test program should get people thinking,
but perhaps it is now time to go back to the mailing
list with the assembly language pointer divide by 4.

maybe post a simplified program, although the list
may argue that the result is undefined since at this
time you can have an array of longs that are this big
in the msp430, but a "long" checksum routine with
60k of flash may be a contrived example.

perhaps even a const long array in the code section
that just happens to cross the 32k byte boundary
would also experience this size failure.

On Mon, 30 Dec 2002 at 17:14 -0500, walt spicker
<[email protected]...:
From: walt spicker <[email protected]>
To: David Dyck <[email protected]>
Date: Mon, 30 Dec 2002 17:14:09 -0500
Subject: Re: [Mspgcc-users] Pointer Arithmetic Error

David,

As you suggest, I took a peek at the assembly, and it appears to me that
there is a problem with the instruction used to do the divide by 4.
Indeed the compiler is using "rra" to divide the pointer value "0xf000"
by 4. with the resulting value being "0xf800", probably not what was
intended.

Is there a mechanism to report a "bug", or do we just hope this bubbles
up and and gets the attention of somone with the ability to fix it?

Thanks for your help,

Walt

David Dyck wrote:


Walt,

perhaps it is time to look at the assembly code generated, perhaps

the msp code is treating the number as signed.



Another thing to try would be to check out the same code with

pointers to characters instead of longs, so the compiler wouldn't

have to do divisions by 4 (maybe right shift).



Also, what optimizations are the compiler generating - perhaps

it can pre-compute some of the math - so there are a couple
opportunities

for errors here...









On Mon, 30 Dec 2002 at 15:27 -0500, walt spicker <
[email protected]...: <mailto:[email protected]...:>





Thanks for your reply.  I sort of see what you are getting at, but that

does not appear to be the problem.



Here is a modified test, first on the 430:



unsigned long *p1=(void*)0x1000LU, *p2=(void*)0x7000LU,
*p3=(void*)0xf000LU;

unsigned long p2p1 = p2-p1;

unsigned long p3p1 = p3-p1;

static char buf[80];

snprintf (buf, sizeof(buf), "%8.8lx %8.8lx %p %p %p %i",

  p2p1, p3p1, p1, p2, p3, sizeof(p3));

PrintLine (buf);





Output from 430 test:



00001800 fffff800 0x1000 0x7000 0xf000 2





Here is the modified test, on the 386/Linux



main(){

unsigned long *p1=(void*)0x1000LU, *p2=(void*)0x7000LU,
*p3=(void*)0xf000LU;

unsigned long p2p1 = p2-p1;

unsigned long p3p1 = p3-p1;



printf ("%8.8lx %8.8lx %p %p %p %i \n", p2p1, p3p1, p1, p2, p3,
sizeof(p3));



}



Output 386/Linux



00001800 00003800 0x1000 0x7000 0xf000 4





OK, so the size of the pointer on the 430 is two bytes vs. 4 bytes on
the I386. I do not see what role that plays here.



My expectation is that the difference between two pointers of the same
type will yield the number of those items that would fit in memory
between the two addresses.  This seems to be true on the 430 only when
the MSB of the pointers is zero.



Please let me know if you still think that I'm missing something here.



Reply via email to