Re: [avr-gcc-list] (no subject)

2008-01-28 Thread Andrew Hutchinson
Try casting the expression (foo +1) to a function pointer. This may 
prove the point and correct the code in table - and elsewhere.


Arithmetic with function pointers is probably not well standardized - if 
at all.


Andy


Wouter van Gulik wrote:

http://gcc.gnu.org/onlinedocs/gcc-4.2.2/gcc/Pointer-Arith.html#Pointer-
Arith

The elements to which function (and void) pointer refer are assumed to
be size 1 byte.

So if you really want to mess with these pointers, you must treat as
byte address.




Exactly what I thought. If I do nasty things I should know what I am doing. 

  

That does not explain the other problems reported directly. However
given  foo is a function pointer, what is the type of the expression foo
+ 1.? Perhaps gcc treats such an expression as void?




Exactly the table is still messed up by gcc.
Any idea how I/we can test this? I looked at the -da output but I could not
find anything related to the table.

Is the avr backend involved in generating the correct function pointer
addresses? Where is this gs() coming from? I searched through the as
documentation but I could not find it. Is it from ld?

Are there other platforms supported by gcc having the same strange non equal
data/program space?
I know that the TI C54x series have a 8 bit program space, and a 16 bit data
space. sizeof(char) == sizeof(int), both 16-bit!, but instructions and
function addresses are in bytes 
Maybe we can find some hints there?

HTH

Wouter

  

Andy



Andrew Hutchinson wrote:


I think you highlight the problem for gcc.

We are have to treat program memory as byte addressable to support LPM.

Direct, function calls only want word address to form the correct
opcode. But we use byte address labels  and assembler removes the
redundant bit to form the correct opcode.

Indirect (icall) functions show up the anomaly as these are formed
outside of the assembler.

Gcc is assuming that the item that a function pointer points to is
size 1. When in fact it is size 2.

This is similar as having pointer to some other object such as long:

long *ptr;
   x = ptr+1;  /* x will be assinged byte address potr+4 */

So if we can correct that mistake, I believe the problem is resolved.
Now, I am not sure how gcc determines that size! So I will look.

Andy



Wouter van Gulik wrote:
  

Compiling the following program ends up in main.c:(.text+0x2):
warning: internal error: out of range error

= main.c 

//Dummy func
void foo(void) {}

//Table with address manipulation
void (* const pFuncTable[]) (void) = {
foo + 0,
foo + 1, //need odd offset
};  int main(int argc, char* argv[]) {
//Call table
pFuncTable[1]();
return 1;
}
Looking into the generated assembler gives:

pFuncTable:
.word   gs(foo)
.word   foo+1

Which is wrong. It should have been gs(foo + 1) or perhaps gs(foo)+1

But the true wrong thing is that gcc out smarts the table (since it's
const)
and directly does: call foo+1. This gives the internal error.
Even worse is that the compiler does not stop!! IMHO it should stop
here,
instead it generates this final assembly: 00a6 main:
  a6:   0e 94 00 00 call0   ; 0x0 __vectors
  aa:   81 e0   ldi r24, 0x01   ; 1
  ac:   90 e0   ldi r25, 0x00   ; 0
  ae:   08 95   ret


Before I post a note to the existing bug report (it's probably
related with
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27192 ) I want to know
what foo
+ 1 is supposed to do. GCC seems to mix up byte address (for lpm) and
word
addresses (for ijmp/jmp//icall/call).
Is it supposed to increment the byte address or the word address?
I guess byte addresses are what it's supposed to be, since calling
foo + 2
ends up in calling foo + 2 bytes. Leaving foo + 1 as illegal address.

And I just found another nasty error:

//Dummy func
void foo(void) {}

//Table with address manipulation
void (* const pFuncTable[]) (void) = {
foo + 4, //need odd offset
};  int main(int argc, char* argv[]) {
//Call table
pFuncTable[0]();
return 1;
}
This will generate a correct call (4 bytes after foo) but the value
in the
table is not left shifted! Meaning that a call via the table will
generate a
call to the wrong address, while the original call is ok.

Wouter



___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list



___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list
  



  



___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


RE: [avr-gcc-list] (no subject)

2008-01-28 Thread Wouter van Gulik
 
 Try casting the expression (foo +1) to a function pointer. This may
 prove the point and correct the code in table - and elsewhere.
 
 Arithmetic with function pointers is probably not well standardized - if
 at all.
 

I agree. Although giving different results for the same statement is very
nasty.

I tried casting but I could not get any difference. When I tried to cast
both operands to a function pointer I got a message that + is not a legal
operation. Which seems ok and logical to me.

Is there anyway we can make this warning an error (by default)?
main.c:14: warning: internal error: out of range error

So the user knows something is broken in his code.

Thanks for the help

Wouter

 Andy
 
 
 Wouter van Gulik wrote:
  http://gcc.gnu.org/onlinedocs/gcc-4.2.2/gcc/Pointer-Arith.html#Pointer-
  Arith
 
  The elements to which function (and void) pointer refer are assumed to
  be size 1 byte.
 
  So if you really want to mess with these pointers, you must treat as
  byte address.
 
 
 
  Exactly what I thought. If I do nasty things I should know what I am
 doing.
 
 
  That does not explain the other problems reported directly. However
  given  foo is a function pointer, what is the type of the expression
 foo
  + 1.? Perhaps gcc treats such an expression as void?
 
 
 
  Exactly the table is still messed up by gcc.
  Any idea how I/we can test this? I looked at the -da output but I could
 not
  find anything related to the table.
 
  Is the avr backend involved in generating the correct function pointer
  addresses? Where is this gs() coming from? I searched through the as
  documentation but I could not find it. Is it from ld?
 
  Are there other platforms supported by gcc having the same strange non
 equal
  data/program space?
  I know that the TI C54x series have a 8 bit program space, and a 16 bit
 data
  space. sizeof(char) == sizeof(int), both 16-bit!, but instructions and
  function addresses are in bytes 
  Maybe we can find some hints there?
 
  HTH
 
  Wouter
 
 
  Andy
 
 
 
  Andrew Hutchinson wrote:
 
  I think you highlight the problem for gcc.
 
  We are have to treat program memory as byte addressable to support
 LPM.
 
  Direct, function calls only want word address to form the correct
  opcode. But we use byte address labels  and assembler removes the
  redundant bit to form the correct opcode.
 
  Indirect (icall) functions show up the anomaly as these are formed
  outside of the assembler.
 
  Gcc is assuming that the item that a function pointer points to is
  size 1. When in fact it is size 2.
 
  This is similar as having pointer to some other object such as long:
 
  long *ptr;
 x = ptr+1;  /* x will be assinged byte address potr+4 */
 
  So if we can correct that mistake, I believe the problem is resolved.
  Now, I am not sure how gcc determines that size! So I will look.
 
  Andy
 
 
 
  Wouter van Gulik wrote:
 
  Compiling the following program ends up in main.c:(.text+0x2):
  warning: internal error: out of range error
 
  = main.c 
 
  //Dummy func
  void foo(void) {}
 
  //Table with address manipulation
  void (* const pFuncTable[]) (void) = {
  foo + 0,
  foo + 1, //need odd offset
  };  int main(int argc, char* argv[]) {
  //Call table
  pFuncTable[1]();
  return 1;
  }
  Looking into the generated assembler gives:
 
  pFuncTable:
  .word   gs(foo)
  .word   foo+1
 
  Which is wrong. It should have been gs(foo + 1) or perhaps gs(foo)+1
 
  But the true wrong thing is that gcc out smarts the table (since it's
  const)
  and directly does: call foo+1. This gives the internal error.
  Even worse is that the compiler does not stop!! IMHO it should stop
  here,
  instead it generates this final assembly: 00a6 main:
a6:   0e 94 00 00 call0   ; 0x0 __vectors
aa:   81 e0   ldi r24, 0x01   ; 1
ac:   90 e0   ldi r25, 0x00   ; 0
ae:   08 95   ret
 
 
  Before I post a note to the existing bug report (it's probably
  related with
  http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27192 ) I want to know
  what foo
  + 1 is supposed to do. GCC seems to mix up byte address (for lpm) and
  word
  addresses (for ijmp/jmp//icall/call).
  Is it supposed to increment the byte address or the word address?
  I guess byte addresses are what it's supposed to be, since calling
  foo + 2
  ends up in calling foo + 2 bytes. Leaving foo + 1 as illegal address.
 
  And I just found another nasty error:
 
  //Dummy func
  void foo(void) {}
 
  //Table with address manipulation
  void (* const pFuncTable[]) (void) = {
  foo + 4, //need odd offset
  };  int main(int argc, char* argv[]) {
  //Call table
  pFuncTable[0]();
  return 1;
  }
  This will generate a correct call (4 bytes after foo) but the value
  in the
  table is not left shifted! Meaning that a call via the table will
  generate a
  call to the wrong address, while the 

Re: [avr-gcc-list] (no subject)

2008-01-28 Thread Andrew Hutchinson

There is a bug!

Backend (avr part) creates special pm() annotation by looking at RTL. 
This is done in avr.c by this function:


static bool
avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
{
debug_rtx(x); /*ADDED TO DEBUG*/
fprintf(stderr,size=%d align=%d\n\n,size,aligned_p); /*ADDED TO DEBUG*/
 if (size == POINTER_SIZE / BITS_PER_UNIT  aligned_p
  ((GET_CODE (x) == SYMBOL_REF  SYMBOL_REF_FUNCTION_P (x))
 || GET_CODE (x) == LABEL_REF))
   {
 fputs (\t.word\tpm(, asm_out_file);
 output_addr_const (asm_out_file, x);
 fputs ()\n, asm_out_file);
 return true;
   }
 return default_assemble_integer (x, size, aligned_p);
}

(I added 2 lines to debug it)

You will see it looks symbol_ref or label_ref - otherwise it does not 
use pm.


So I ran it with following testcase to see what argument get sent:

//Dummy func
int table[]= {1,2};
char ctable[]= {3,4};
void foo(void) {}
 
//Table with address manipulation

void (* const pFuncTable[]) (void) = {
  foo + 0,
  (foo + 1),
  foo +2
};

and we get the following:

(const_int 1 [0x1])
size=2 align=1

(const_int 2 [0x2])
size=2 align=1

(const_int 3 [0x3])
size=1 align=1

(const_int 4 [0x4])
size=1 align=1

(symbol_ref:HI (foo) [flags 0x3] function_decl 0x7fdcf030 foo)
size=2 align=1

(const:HI (plus:HI (symbol_ref:HI (foo) [flags 0x3] function_decl 
0x7fdcf030 foo)

   (const_int 1 [0x1])))
size=2 align=1

(const:HI (plus:HI (symbol_ref:HI (foo) [flags 0x3] function_decl 
0x7fdcf030 foo)

   (const_int 2 [0x2])))
size=2 align=1

You will see last two cases are an expression with outer code as 
const:HI so it will not match, it does not add pm().


Please report as bug. Other may suggest the correct way of fixing this. 
I am not sure why the test is so specific.


Andy










___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] C code calling ASM functions

2008-01-28 Thread Erik Christiansen
On Fri, Jan 25, 2008 at 10:40:51AM -0200, Gabriel Ortiz Lour wrote:
 
 I would like to call functions coded in ASM from C code and was wondering if
 someone could give me some pointers on that.

The vital bit is observing the ABI, so you're not in dispute with
avr-gcc over register allocation in the calling convention. This url
informed my first steps in this direction:

http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_reg_usage

(Using this is quicker than reading the assembler generated from trial
compilation of C function calls. :-)

If there's anything that blows up when you try it, we may be able to
help, if you can't figure it out. (The gas info page is great, ... as
far as it goes.)

Erik


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] [FIX] _clz and friends not found (test builtin-bitops-1)

2008-01-28 Thread Dmitry K.
On Friday 25 January 2008 22:35, Wouter van Gulik wrote:
 __clzqi2:
 clr r_count ; load with 0
 com r_count ; invert (load with -1) + set carry
 __clzqi2_loop:
 rol r_arg1L ; Rotate through carry
 inc r_count ; Carry not touch by inc
 brcc__clzqi2_loop   ; Branch on no carry

That is splendid!

After a superficial view:
. A short rcall/rjmp is not safe with unknown (big) library
for intermodule link. Also a conditional branch.
. Are this function intended for math functions? If so,
the strong size optimization is not a best solution (IMHO).
An addition of few words may speed up in few times for
some 32/16-bit functions.

Regards,
Dmitry.



___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


RE: [avr-gcc-list] (no subject)

2008-01-28 Thread Wouter van Gulik
 http://gcc.gnu.org/onlinedocs/gcc-4.2.2/gcc/Pointer-Arith.html#Pointer-
 Arith
 
 The elements to which function (and void) pointer refer are assumed to
 be size 1 byte.
 
 So if you really want to mess with these pointers, you must treat as
 byte address.
 

Exactly what I thought. If I do nasty things I should know what I am doing. 

 That does not explain the other problems reported directly. However
 given  foo is a function pointer, what is the type of the expression foo
 + 1.? Perhaps gcc treats such an expression as void?
 

Exactly the table is still messed up by gcc.
Any idea how I/we can test this? I looked at the -da output but I could not
find anything related to the table.

Is the avr backend involved in generating the correct function pointer
addresses? Where is this gs() coming from? I searched through the as
documentation but I could not find it. Is it from ld?

Are there other platforms supported by gcc having the same strange non equal
data/program space?
I know that the TI C54x series have a 8 bit program space, and a 16 bit data
space. sizeof(char) == sizeof(int), both 16-bit!, but instructions and
function addresses are in bytes 
Maybe we can find some hints there?

HTH

Wouter

 Andy
 
 
 
 Andrew Hutchinson wrote:
  I think you highlight the problem for gcc.
 
  We are have to treat program memory as byte addressable to support LPM.
 
  Direct, function calls only want word address to form the correct
  opcode. But we use byte address labels  and assembler removes the
  redundant bit to form the correct opcode.
 
  Indirect (icall) functions show up the anomaly as these are formed
  outside of the assembler.
 
  Gcc is assuming that the item that a function pointer points to is
  size 1. When in fact it is size 2.
 
  This is similar as having pointer to some other object such as long:
 
  long *ptr;
 x = ptr+1;  /* x will be assinged byte address potr+4 */
 
  So if we can correct that mistake, I believe the problem is resolved.
  Now, I am not sure how gcc determines that size! So I will look.
 
  Andy
 
 
 
  Wouter van Gulik wrote:
  Compiling the following program ends up in main.c:(.text+0x2):
  warning: internal error: out of range error
 
  = main.c 
 
  //Dummy func
  void foo(void) {}
 
  //Table with address manipulation
  void (* const pFuncTable[]) (void) = {
  foo + 0,
  foo + 1, //need odd offset
  };  int main(int argc, char* argv[]) {
  //Call table
  pFuncTable[1]();
  return 1;
  }
  Looking into the generated assembler gives:
 
  pFuncTable:
  .word   gs(foo)
  .word   foo+1
 
  Which is wrong. It should have been gs(foo + 1) or perhaps gs(foo)+1
 
  But the true wrong thing is that gcc out smarts the table (since it's
  const)
  and directly does: call foo+1. This gives the internal error.
  Even worse is that the compiler does not stop!! IMHO it should stop
  here,
  instead it generates this final assembly: 00a6 main:
a6:   0e 94 00 00 call0   ; 0x0 __vectors
aa:   81 e0   ldi r24, 0x01   ; 1
ac:   90 e0   ldi r25, 0x00   ; 0
ae:   08 95   ret
 
 
  Before I post a note to the existing bug report (it's probably
  related with
  http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27192 ) I want to know
  what foo
  + 1 is supposed to do. GCC seems to mix up byte address (for lpm) and
  word
  addresses (for ijmp/jmp//icall/call).
  Is it supposed to increment the byte address or the word address?
  I guess byte addresses are what it's supposed to be, since calling
  foo + 2
  ends up in calling foo + 2 bytes. Leaving foo + 1 as illegal address.
 
  And I just found another nasty error:
 
  //Dummy func
  void foo(void) {}
 
  //Table with address manipulation
  void (* const pFuncTable[]) (void) = {
  foo + 4, //need odd offset
  };  int main(int argc, char* argv[]) {
  //Call table
  pFuncTable[0]();
  return 1;
  }
  This will generate a correct call (4 bytes after foo) but the value
  in the
  table is not left shifted! Meaning that a call via the table will
  generate a
  call to the wrong address, while the original call is ok.
 
  Wouter
 
 
 
  ___
  AVR-GCC-list mailing list
  AVR-GCC-list@nongnu.org
  http://lists.nongnu.org/mailman/listinfo/avr-gcc-list
 
 
 
  ___
  AVR-GCC-list mailing list
  AVR-GCC-list@nongnu.org
  http://lists.nongnu.org/mailman/listinfo/avr-gcc-list



___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list