Problem with init of structure bit fields

2009-06-03 Thread Stelian Pop
Hi,

I'm doing a port of gcc 4.3.3 on a custom architecture and I'm having trouble
when initializing the bit fields of  a structure.

The testcase is based on a modified gcc torture testcase, the natural
registers are 16 bits, and long long is defined to be 64 bit wide:

struct itmp
{
  long long int pad :   30; 
  long long int field : 34; 
};

struct itmp itmp = {0x123LL, 0x123456LL};

int main(void)
{
  itmp.field = 0x42;
  return 1;
}

Running the above example gives (compiled with -O0...):

12itmp.field = 0x42;
(gdb) p/x itmp
$1 = {pad = 0x123, field = 0x123456}
(gdb) n
13return 1;
(gdb) p/x itmp
$2 = {pad = 0x123, field = 0x0}

If I use 32 bits for pad and 32 bits for field, the result is correct.
Also, if I use 'long' instead of 'long long' (and change the bit lengths
of course), it works too.

Looking at the RTL shows the problem right from the beginning, in the
expand pass (there is no reference to the constant 66 = 0x42 in the RTL
below):

;; itmp.field = 66
(insn 5 4 6 991118-1.c:12 (set (reg/f:HI 25) 
(symbol_ref:HI (itmp) [flags 0x2] var_decl 0xb7c460b0 itmp)) -1
(nil))

(insn 6 5 7 991118-1.c:12 (set (reg:HI 26) 
(reg/f:HI 25)) -1 (nil))

(insn 7 6 8 991118-1.c:12 (set (reg/f:HI 27) 
(plus:HI (reg/f:HI 25) 
(const_int 6 [0x6]))) -1 (nil))

(insn 8 7 9 991118-1.c:12 (set (reg:HI 28) 
(const_int 0 [0x0])) -1 (nil))

(insn 9 8 10 991118-1.c:12 (set (mem/s/j/c:HI (reg/f:HI 27) [0+6 S2 A16])
(reg:HI 28)) -1 (nil))

(insn 10 9 11 991118-1.c:12 (set (reg:HI 29)
(reg/f:HI 25)) -1 (nil))

(insn 11 10 12 991118-1.c:12 (set (reg/f:HI 30)
(plus:HI (reg/f:HI 25)
(const_int 4 [0x4]))) -1 (nil))

(insn 12 11 13 991118-1.c:12 (set (reg:HI 31)
(const_int 0 [0x0])) -1 (nil))

(insn 13 12 14 991118-1.c:12 (set (mem/s/j/c:HI (reg/f:HI 30) [0+4 S2 A16])
(reg:HI 31)) -1 (nil))

(insn 14 13 15 991118-1.c:12 (set (reg:HI 32)
(reg/f:HI 25)) -1 (nil))

(insn 15 14 16 991118-1.c:12 (set (reg/f:HI 33)
(plus:HI (reg/f:HI 25)
(const_int 2 [0x2]))) -1 (nil))

(insn 16 15 17 991118-1.c:12 (set (reg:HI 34)
(mem/s/j/c:HI (reg/f:HI 33) [0+2 S2 A16])) -1 (nil))

(insn 17 16 18 991118-1.c:12 (set (reg:HI 36)
(const_int -4 [0xfffc])) -1 (nil))

(insn 18 17 19 991118-1.c:12 (set (reg:HI 35)
(and:HI (reg:HI 34)
(reg:HI 36))) -1 (nil))

(insn 19 18 0 991118-1.c:12 (set (mem/s/j/c:HI (reg/f:HI 33) [0+2 S2 A16])
(reg:HI 35)) -1 (nil))


Any idea on what is happenning here ? Am I missing some standard
patterns in my .md file ?

Thanks !

-- 
Stelian Pop stel...@popies.net


Re: Problem with init of structure bit fields

2009-06-03 Thread Stelian Pop
On Wed, Jun 03, 2009 at 07:49:29PM +0200, Stelian Pop wrote:

 I'm doing a port of gcc 4.3.3 on a custom architecture and I'm having trouble
 when initializing the bit fields of  a structure.

Ok, after further analysis, it looks like a genuine bug in gcc,
in store_bit_field_1(): when a field is bigger than a word, the
rvalue is splitted in several words, after being placed in a
smallest_mode_for_size() operand.

But the logic for adressing the words of this operand is buggy
in the WORDS_BIG_ENDIAN case, the most signficant words being
used instead of the least significant ones.

The following patch corrects this, and makes the
gcc.c-torture/execute/991118-1.c testcase work correctly on my platform.

Stelian.

diff --git a/gcc/expmed.c b/gcc/expmed.c
index dc61de7..03c60a8 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -582,7 +582,10 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT 
bitsize,
{
  /* If I is 0, use the low-order word in both field and target;
 if I is 1, use the next to lowest word; and so on.  */
- unsigned int wordnum = (backwards ? nwords - i - 1 : i);
+ unsigned int wordnum = (backwards
+ ? GET_MODE_SIZE(fieldmode) / UNITS_PER_WORD
+   - i - 1
+ : i);
  unsigned int bit_offset = (backwards
 ? MAX ((int) bitsize - ((int) i + 1)
* BITS_PER_WORD,
-- 
Stelian Pop stel...@popies.net


Re: Problem with init of structure bit fields

2009-06-03 Thread Stelian Pop
On Wed, Jun 03, 2009 at 01:07:08PM -0700, Ian Lance Taylor wrote:

  - unsigned int wordnum = (backwards ? nwords - i - 1 : i);
  + unsigned int wordnum = (backwards
  + ? GET_MODE_SIZE(fieldmode) / UNITS_PER_WORD
  +   - i - 1
  + : i);
unsigned int bit_offset = (backwards
   ? MAX ((int) bitsize - ((int) i + 1)
  * BITS_PER_WORD,
 
 Your patch looks correct.  However, it makes me wonder how the test case
 passes on existing big-endian platforms, such as the PowerPC.  Can you
 explain how that works?

I'm not sure, but it is related to the smaller word size on my platform
and the size of the field (a 64 bit long long).

The 991118-1.c test case passes ok on my platform when the word
size is 32 or 16 bits (my processor has configurable word sizes). The only
configuration that fails is when the word size is 8 bits...

When I tried to simplify the testcase I obtained the simple assignment
problem I posted in the original mail. And that problem was visible in
both 8 and 16 bits configurations.

So I suspect the problem won't be seen on PowerPC unless someone does
TI or OI bit fields...

-- 
Stelian Pop stel...@popies.net


Issues with testsuite on constant pointer arithmetics

2009-05-06 Thread Stelian Pop
Hi all,

I'm reaching the final stages of my port of gcc to a custom microcontroller
and at this point real world examples seem to work, I only have a few dozen
tests of the testsuite which give me trouble.

All those tests involve arithmetics on pointers (or labels), and I'm not
sure if the tests show a real problem in my port or if the tests are not
relevant given the specifics of my microcontroller (size of pointers not
being a long, int not being a natural register etc).

Before going further, a bit of background: this microcontroller is special
in that it can be configured to work in 4 different modes: 8 bit wide,
16 bit, 16 bit wide and 32 bits.

The code below speaks for itself:

#define BITS_PER_UNIT   8
#define UNITS_PER_WORD  (TARGET_8W ? 1 : (TARGET_16 || TARGET_16W) ? 2 
: 4)
#define SHORT_TYPE_SIZE 16
#define INT_TYPE_SIZE   16
#define LONG_TYPE_SIZE  32
#define LONG_LONG_TYPE_SIZE 64
#define FLOAT_TYPE_SIZE 32
#define DOUBLE_TYPE_SIZE64
#define LONG_DOUBLE_TYPE_SIZE   64
#define SIZE_TYPE   unsigned int
#define PTRDIFF_TYPE_SIZE   ((TARGET_8W || TARGET_16) ? int : long int)
#define Pmode   ((TARGET_8W || TARGET_16) ? HImode : SImode)
#define POINTER_SIZE((TARGET_8W || TARGET_16) ? 16 : 32)

Now, back to my problems: the following tests fail with
error: initializer element is not constant:

on TARGET_8W and TARGET_16:
920928-1.c:
1 struct{int c;}v;
2 static long i=((char*)(v.c)-(char*)v)
930326-1.c:
1 struct
2 {
3   char a, b, f[3];
4 } s;
5
6 long i = s.f-s.b;
labels-3.c:
 9 int foo (int a)
10 {
11   static const short ar[] = { l1 - l1, l2 - l1 };
12   void *p = l1 + ar[a];
13   goto *p;
14  l1:
15   return 1;
16  l2:
17   return 2;
18 }

on TARGET_16W and TARGET_32: 2004-1.c:
1 extern void _text;
2 static __SIZE_TYPE__ x = (__SIZE_TYPE__) _text - 0x1000L - 1;

Are those tests expected to fail on my port or is that something I've
obviously done wrong ?

Thanks.

Stelian.
-- 
Stelian Pop stel...@popies.net


Re: Issues with testsuite on constant pointer arithmetics

2009-05-06 Thread Stelian Pop
On Wed, May 06, 2009 at 12:19:55PM -0700, Ian Lance Taylor wrote:

 Stelian Pop stel...@popies.net writes:
 
  on TARGET_8W and TARGET_16:
  920928-1.c:
  1 struct{int c;}v;
  2 static long i=((char*)(v.c)-(char*)v)
  930326-1.c:
  1 struct
  2 {
  3   char a, b, f[3];
  4 } s;
  5
  6 long i = s.f-s.b;
  labels-3.c:
   9 int foo (int a)
  10 {
  11   static const short ar[] = { l1 - l1, l2 - l1 };
  12   void *p = l1 + ar[a];
  13   goto *p;
  14  l1:
  15   return 1;
  16  l2:
  17   return 2;
  18 }
 
  on TARGET_16W and TARGET_32: 2004-1.c:
  1 extern void _text;
  2 static __SIZE_TYPE__ x = (__SIZE_TYPE__) _text - 0x1000L - 1;
 
  Are those tests expected to fail on my port or is that something I've
  obviously done wrong ?
 
 I don't see any particular reason that these tests should fail.  I
 hasten to add that these tests are not very important and it is unlikely
 that a failure to pass these tests will affect any actual program.
 
 You didn't mention which version of gcc you are based on.  Do you have
 these patches?  If not, that may be your problem.

Sorry, fergot to say that I was using gcc 4.3.3, so yes, the patches
you mention are already in.

 Even if you do have those patches, that code is where I would start
 looking.  Your initializers are constant, but something in that area
 thinks that they are not constant.

I did spent a few hours looking but haven't had much luck.

I tried tracing this one:
  6 long i = s.f-s.b;
and noticed that the pointers gets casted to 'long' (so they become integers
and no longer pointers) before the actual substraction is made.

Of course, replacing the 'long' with 'int' (on the incriminated targets,
where the real size of the pointer is 16 bit, the size of an 'int') makes
the code compile as a charm.

Stelian.
-- 
Stelian Pop stel...@popies.net


Re: Issues with testsuite on constant pointer arithmetics

2009-05-06 Thread Stelian Pop
On Wed, May 06, 2009 at 01:23:57PM -0700, Ian Lance Taylor wrote:

 Stelian Pop stel...@popies.net writes:
 
  I did spent a few hours looking but haven't had much luck.
 
  I tried tracing this one:
6 long i = s.f-s.b;
  and noticed that the pointers gets casted to 'long' (so they become integers
  and no longer pointers) before the actual substraction is made.
 
  Of course, replacing the 'long' with 'int' (on the incriminated targets,
  where the real size of the pointer is 16 bit, the size of an 'int') makes
  the code compile as a charm.
 
 I took a quick look at a similar case for x86, and the key step seems to
 be a call to ptr_difference_const.  It converts the difference of two
 ADDR_EXPRs to a constant.

in my case ptr_difference_const doesn't get called at all, because
the operands are no longer ADDR_EXPRs:

(gdb) p debug_tree(op0)
 nop_expr 0xb7cfd120
type integer_type 0xb7c9d3a8 long int public SI
size integer_cst 0xb7c904b4 constant invariant 32
unit size integer_cst 0xb7c90230 constant invariant 4
align 8 symtab 0 alias set -1 canonical type 0xb7c9d3a8 precision 32 min
integer_cst 0xb7c90460 -2147483648 max integer_cst 0xb7c9047c 2147483647
pointer_to_this pointer_type 0xb7ca7478
constant invariant
arg 0 convert_expr 0xb7cfd100
type integer_type 0xb7c9d2d8 int public HI
size integer_cst 0xb7c9039c constant invariant 16
unit size integer_cst 0xb7c903b8 constant invariant 2
align 8 symtab 0 alias set -1 canonical type 0xb7c9d2d8 precision 16
min integer_cst 0xb7c903f0 -32768 max integer_cst 0xb7c9040c 32767
pointer_to_this pointer_type 0xb7ca4680
constant invariant
arg 0 addr_expr 0xb7cfd080 type pointer_type 0xb7cfa7b8
constant invariant
arg 0 component_ref 0xb7c99050 type array_type 0xb7cfa750
arg 0 var_decl 0xb7c980b0 s arg 1 field_decl 0xb7d050b8 
f

(gdb) p debug_tree(op1)
 nop_expr 0xb7cfd0e0
type integer_type 0xb7c9d3a8 long int public SI
size integer_cst 0xb7c904b4 constant invariant 32
unit size integer_cst 0xb7c90230 constant invariant 4
align 8 symtab 0 alias set -1 canonical type 0xb7c9d3a8 precision 32 min
integer_cst 0xb7c90460 -2147483648 max integer_cst 0xb7c9047c 2147483647
pointer_to_this pointer_type 0xb7ca7478
constant invariant
arg 0 convert_expr 0xb7cfd0c0
type integer_type 0xb7c9d2d8 int public HI
size integer_cst 0xb7c9039c constant invariant 16
unit size integer_cst 0xb7c903b8 constant invariant 2
align 8 symtab 0 alias set -1 canonical type 0xb7c9d2d8 precision 16
min integer_cst 0xb7c903f0 -32768 max integer_cst 0xb7c9040c 32767
pointer_to_this pointer_type 0xb7ca4680
constant invariant
arg 0 addr_expr 0xb7cfd060 type pointer_type 0xb7ca6f70
constant invariant
arg 0 component_ref 0xb7c99078 type integer_type 0xb7c9d1a0 char
arg 0 var_decl 0xb7c980b0 s arg 1 field_decl 0xb7d0505c 
b

-- 
Stelian Pop stel...@popies.net


Re: Issues with testsuite on constant pointer arithmetics

2009-05-06 Thread Stelian Pop
On Wed, May 06, 2009 at 03:42:47PM -0700, Ian Lance Taylor wrote:

 Stelian Pop stel...@popies.net writes:
 
 There is something strange in your trees.  Why did it convert the
 pointers to long int?  Why did it not simply convert them to int?
 The fact that they are going to be assigned to a long int variable
 should not have caused them to convert to long int.
 
 Oh, I see it comes from PTRDIFF_TYPE, which defaults to long int.  Try
 doing #define PTRDIFF_TYPE int in your CPU.h file.

Of course, and I thought I did:

On Wed, May 06, 2009 at 06:15:40PM +0200, Stelian Pop wrote:
 #define PTRDIFF_TYPE_SIZE   ((TARGET_8W || TARGET_16) ? int : long 
 int)

... except that there's a typo in there.

Once corrected, all things are back to normal. Thanks, and sorry for the
noise.

Now, where's that brown paper bag...

Stelian.
-- 
Stelian Pop stel...@popies.net


question on 16 bit registers with 32 bit pointers

2009-04-10 Thread Stelian Pop
Hi,

I'm (still) porting GCC to a 16 bit microcontroller, and I'm having a few issues
with the way it handles memory accesses: this microcontroller can function in
two modes: in one of them the pointers are on 16 bit (a full register), in the
second one the pointers are on 32 bit and are stored in two following registers
(N and N+1).

I did implement a GCC option to select between the two modes, and I'm using this
option to select the size of the pointers and Pmode:

#define Pmode   ((TARGET_16) ? HImode : SImode)
#define POINTER_SIZE((TARGET_16) ? 16 : 32)

Do I need to define movsi3(), addsi3() etc. patterns manually or should GCC 
figure
those by itself ?

Is there something special I need to do to express the relationship between the
two registers N and N+1 composing a pointer, or does GCC automatically allocate
two subsequent HI registers when it needs a SI one ?

Thanks.

-- 
Stelian Pop stel...@popies.net


Re: question on 16 bit registers with 32 bit pointers

2009-04-10 Thread Stelian Pop
On Fri, Apr 10, 2009 at 06:29:06PM +0100, Dave Korn wrote:

 Stelian Pop wrote:
  Hi,
  
  I'm (still) porting GCC to a 16 bit microcontroller, and I'm having a few
  issues with the way it handles memory accesses: this microcontroller can
  function in two modes: in one of them the pointers are on 16 bit (a full
  register), in the second one the pointers are on 32 bit and are stored in
  two following registers (N and N+1).
  
  I did implement a GCC option to select between the two modes, and I'm using
  this option to select the size of the pointers and Pmode:
  
  #define Pmode   ((TARGET_16) ? HImode : SImode) #define 
  POINTER_SIZE
  ((TARGET_16) ? 16 : 32)
  
  Do I need to define movsi3(), addsi3() etc. patterns manually or should GCC
  figure those by itself ?
 
   Not sure I understand you.  You always need to define movMM3 etc.  GCC will
 correctly select between movhi3 and movsi3 based on your Pmode macro when
 handling pointers, but you still need to write the patterns.

The thing is that this CPU does not have any real 32 bit registers, or
instructions to do assignments/additions/etc to 32 bit registers. So the 32 bit
operations (on pointers) need to be emulated using the 16 bit components, and I
thought that GCC can do this automatically for me ...

  Is there something special I need to do to express the relationship between
  the two registers N and N+1 composing a pointer, or does GCC automatically
  allocate two subsequent HI registers when it needs a SI one ?
 
   GCC always uses consecutive hard regs when doing multi-reg data sizes.  See
 HARD_REGNO_MODE_OK in the internals docs.

Great, thanks !

Stelian.
-- 
Stelian Pop stel...@popies.net


Re: How to use a scratch register in jump pattern ?

2009-03-12 Thread Stelian Pop
On Wed, Mar 11, 2009 at 03:33:28PM +0100, Ulrich Weigand wrote:

  It doesn't work. It causes a loop somewhere in gcc. I can get a gdb
  trace if needed.
 
 Yes, this does not work.  Jumps are special; the CFG logic makes
 a lot of assumptions how jump patterns look.
[...]
 The s390 back-end globally reserves a register for the purpose of
 holding the target of long branches (well, the register is also 
 used as link register for calls).

Ok, so I'll reserve a register for indirect jumps too then. I was hoping
to be able to avoid this.

Thanks !

Stelian.
-- 
Stelian Pop stel...@popies.net


Re: How to use a scratch register in jump pattern ?

2009-03-11 Thread Stelian Pop
On Wed, Mar 11, 2009 at 08:33:34AM +0100, Georg-Johann Lay wrote:

 Stelian Pop schrieb:
 On Tue, Mar 10, 2009 at 10:18:10PM +0100, Georg-Johann Lay wrote:


 Note that no one is generating an insn that looks like *jump. Maybe 
  insn combine and peep2 would try to build such a pattern, but that 
 is  not what helpd you out here. Write the expander as parallel of a 
 (set  (pc) ...) and a (clobber (match_scratch ...)) so that an 
 appropriate  insn is expanded.


 Like this ?

 (define_expand jump
   [(parallel [(set (pc) (label_ref (match_operand 0  )))
   (clobber (match_scratch:QI 1 =r))])]
   
   
 )

 Constraints are useless in expanders.

Of course, copy'n'paste error.

 You really need a QI scratch? Your  
 insn looks as if HI was needed as you load hi and lo part of the scratch.

Yes, QI is correct: my microcontroller is a bit special in that in has
16 bit bytes (BITS_PER_UNIT=16).

[...]

 So you have just one alternative =r, and in the case of rjmp the  
 scratch is unused.

Ok, so I ended up with (omitting the jump lengths for now):

(define_insn *jump
  [(set (pc)
(label_ref (match_operand 0  )))
   (clobber (match_scratch:QI 1 =r))]
  
  {
return ldih %1,hi(%l0)\n\t\n\tldil %1,lo(%l0)\n\tijmp (%1);
  }
)

(define_expand jump
  [(parallel [(set (pc) (label_ref (match_operand 0  )))
  (clobber (match_scratch:QI 1 ))])]
  
  
)

It doesn't work. It causes a loop somewhere in gcc. I can get a gdb
trace if needed.

 Note that you emit up to three instructions, so the  
 -2048/2047 may crash in corner cases.

Right, thanks !

 You can have a look at avr, it computes jump lengths as well but afaIr  
 without needing a scratch for long jumps.

I'll do. I'm trying now first to get the indirect jump to work, and I'll
put the test for the jumps lenghts later.

Thanks,

-- 
Stelian Pop stel...@popies.net


How to use a scratch register in jump pattern ?

2009-03-10 Thread Stelian Pop
Hi,

I need to use a scratch register in the jump pattern and I can't
figure out how to do it properly.

My problem is that the microcontroller I'm porting gcc onto does not
permit far jumps, those must be done using an indirect adressing.

So I wrote this:

-8--8-
(define_attr length  (const_int 2))

(define_insn *jump
  [(set (pc)
(label_ref (match_operand 0  )))
   (clobber (match_scratch:QI 1 =r))]
  
  {
if (get_attr_length (insn) == 1)
return rjmp %0;
else
return ldih %1,hi(%l0)\n\t\n\tldil %%1,lo(%l0)\n\tijmp %(%1);
  }
  [(set (attr length) (if_then_else
(and (ge (minus (match_dup 0) (pc)) (const_int -2048))
 (le (minus (match_dup 0) (pc)) (const_int 2047)))
(const_int 1)
(const_int 2)))]
)

(define_expand jump
  [(set (pc)
   (label_ref (match_operand 0  )))]
  
  
)
-8--8-

But it doesn't work:

...
(jump_insn 44 266 45 6 /tmp/src/gcc-4.3.1/libgcc/../gcc/libgcov.c:137
(set (pc)
(label_ref 119)) -1 (nil))
/tmp/src/gcc-4.3.1/libgcc/../gcc/libgcov.c:577: internal compiler error: in 
extract_insn, at recog.c:1990
Please submit a full bug report, with preprocessed source if appropriate.

Any idea ?

Side question regarding the length attribute. It seems to work ok, but
if I change the default value (first line in my example) to be 'const_int 1',
I later get 'operand out of range' from the assembler because the 'rjmp'
instruction was used for deplacements bigger than 2048. How can this happen,
since my '(set (attr length)' code explicitly sets the correct value
each time ?

Thanks,

-- 
Stelian Pop stel...@popies.net


Re: How to use a scratch register in jump pattern ?

2009-03-10 Thread Stelian Pop
On Tue, Mar 10, 2009 at 05:20:28PM +, Dave Korn wrote:

 Stelian Pop wrote:
 
  I need to use a scratch register in the jump pattern and I can't
  figure out how to do it properly.
  
  My problem is that the microcontroller I'm porting gcc onto does not
  permit far jumps, those must be done using an indirect adressing.
 
  (define_insn *jump
 
  Any idea ?
 
   You should be able to define/use the indirect_jump pattern instead?  Take
 a look at the last paragraph of the the docs for the call pattern as well.
 

I already do have an indirect_jump pattern in my md file:

(define_insn indirect_jump
  [(set (pc)
(match_operand:QI 0 register_operand r))]

  ijmp (%0)
  [(set_attr cc none)]
)

However, I didn't find a way to say to gcc that it cannot use the direct
jump in some cases, and force it to use the indirect_jump instead.

   I don't think it'll work to have a jump insn that is sometimes direct,
 sometimes indirect.

   Looking at how the rs6000 backend handles direct and indirect calls and
 jumps might give you some inspiration too.

Well, I already did look at all the backends, but didn't find the answer
(although the answer probably is hidden somewhere inside those files...).

As for the rs6000 backend I see a simple direct call pattern, not sure what
you want me to look at:

in rs6000.md:

(define_insn jump
  [(set (pc)
(label_ref (match_operand 0  )))]
  
  b %l0
  [(set_attr type branch)])


Thanks,

Stelian.
-- 
Stelian Pop stel...@popies.net


Re: How to use a scratch register in jump pattern ?

2009-03-10 Thread Stelian Pop
On Tue, Mar 10, 2009 at 10:18:10PM +0100, Georg-Johann Lay wrote:

 Note that no one is generating an insn that looks like *jump. Maybe  
 insn combine and peep2 would try to build such a pattern, but that is  
 not what helpd you out here. Write the expander as parallel of a (set  
 (pc) ...) and a (clobber (match_scratch ...)) so that an appropriate  
 insn is expanded.

Like this ?

(define_expand jump
  [(parallel [(set (pc) (label_ref (match_operand 0  )))
  (clobber (match_scratch:QI 1 =r))])]
  
  
)

 Also note that *jump is an (implicit) parallel. As  
 constraint for the *jump insn use an X in the case you do not need  
 the clobber reg and sth. like =r in the case you really need it.

Ok, but the decision on if I need the clobber reg or not is based
on the 'length' attribute. So if I could write the following, but where
I can put the calculation and the test of the 'length' attribute:

(define_insn *jump_internal
   [(set (pc)
 (label_ref (match_operand 0  )))
(clobber (match_scratch:QI 1 X,=r))]
   
   @
   rjmp %0
   ldih %1,hi(%l0)\n\t\n\tldil %1,lo(%l0)\n\tijmp (%1)
)


 Side question regarding the length attribute. It seems to work ok, but
 if I change the default value (first line in my example) to be 'const_int 1',
 I later get 'operand out of range' from the assembler because the 'rjmp'
 instruction was used for deplacements bigger than 2048. How can this happen,
 since my '(set (attr length)' code explicitly sets the correct value
 each time ?

 You set the length explicitely, so the default does not matter.

Yes, this was exactly my point. It shouldn't matter, but it does, because
it does different things when I change the default value.

Stelian.

-- 
Stelian Pop stel...@popies.net


Re: Scratch register in jump instruction ?

2008-07-24 Thread Stelian Pop
Le lundi 21 juillet 2008 à 15:37 +0200, Stelian Pop a écrit :

 I have a problem with the jump instructions: my direct jumps are very
 limited in displacements, and I want to always generate indirect jumps
 instead.

Ok, no answer yet.

Does this mean that my question is really dumb ?

Or does this mean that it should work just fine and I need to debug
deeper to see what happens here ?

Thanks,

-- 
Stelian Pop [EMAIL PROTECTED]



Scratch register in jump instruction ?

2008-07-21 Thread Stelian Pop
Hi,

(I finally resumed the work on my microcontroller I posted about 3
months ago...)

I have a problem with the jump instructions: my direct jumps are very
limited in displacements, and I want to always generate indirect jumps
instead.

So I wrote this:

(define_insn jump
  [(set (pc)
(label_ref (match_operand 0  )))
   (clobber (match_scratch:QI 1 =w))]

  ldih %1,hi(%l0)\n\tldil %1,lo(%l0)\n\tijmp (%1)
  [(set_attr cc none)]
)

gcc and libgcc get compiled ok, but several testsuite tests fail because
gcc is eating all the virtual memory when compiling the file. One of
those is for example gcc.c-torture/compile/2120-2.c .

The problem is coming from the usage of 'match_scratch' here, because
removing it makes the problem go away.

Before going deeper and trying to see if I'm hitting a bug in gcc, can
someone please advice whether my define_insn is correct ? I'm using
gcc-4.3.1.

A stack trace from gdb seems to show that gcc is looping around here:

#0  0x080f70df in df_insn_rescan (insn=0x80951c08)
at /wip/src/gcc-4.3.1/gcc/df-scan.c:1078
#1  0x0811b5ad in add_insn_after (insn=0x80951c08, after=0x80951be0, 
bb=0xb7c17924)
at /wip/src/gcc-4.3.1/gcc/emit-rtl.c:3495
#2  0x0811b870 in emit_jump_insn_after_noloc (x=0x80950c58,
after=0x80951be0)
at /wip/src/gcc-4.3.1/gcc/emit-rtl.c:4085
#3  0x080da84c in try_redirect_by_replacing_jump (e=0xb7c26460, 
target=0xb7c179d8, in_cfglayout=0 '\0')
at /wip/src/gcc-4.3.1/gcc/cfgrtl.c:822
#4  0x08360a08 in cleanup_cfg (mode=1)
[...]

Thanks,

-- 
Stelian Pop [EMAIL PROTECTED]



Re: Problem with reloading in a new backend...

2008-04-15 Thread Stelian Pop

Le lundi 14 avril 2008 à 18:27 -0700, Jim Wilson a écrit :
 On Tue, 2008-04-15 at 00:06 +0200, Stelian Pop wrote:
  - I had to add a PLUS case in PREFERRED_RELOAD_CLASS() or else reload
  kept generating incorrect insn (putting constants into EVEN_REGS for
  example). I'm not sure this is correct or if it hides something else...
 
 It does sound odd, but I can't really say it is wrong, as you have an
 odd set of requirements here.  At least it is working which is good.

Ok, thanks again.

Stelian.

-- 
Stelian Pop [EMAIL PROTECTED]



Re: Problem with reloading in a new backend...

2008-04-14 Thread Stelian Pop

Le vendredi 11 avril 2008 à 11:14 -0700, Jim Wilson a écrit :
 Stelian Pop wrote:
  #define PREFERRED_RELOAD_CLASS(X, CLASS)\
((CONSTANT_P(X)) ? EIGHT_REGS :   \
 (MEM_P(X)) ? EVEN_REGS : CLASS)
  
  #define PREFERRED_OUTPUT_RELOAD_CLASS(X, CLASS) \
((CONSTANT_P(X)) ? EIGHT_REGS :   \
 (MEM_P(X)) ? EVEN_REGS : CLASS)
 
 I think most of your trouble is here.  Suppose we are trying to reload a 
 constant into an even-reg.  We call PREFERRED_RELOAD_CLASS, which says 
 to use eight_regs instead, and you get a fatal_insn error because you 
 didn't get the even-reg that the instruction needed.
[...]

I've tried the suggestion above and it did indeed help. However, I had a
few additional issues:
- the stack pointer and the frame pointer MUST be placed into an
even-reg, or else reload will generate (mem (plus (reg) (const))) insn
(when eliminating the pointers).
- I had to add a PLUS case in PREFERRED_RELOAD_CLASS() or else reload
kept generating incorrect insn (putting constants into EVEN_REGS for
example). I'm not sure this is correct or if it hides something else...

#define STACK_POINTER_REGNUM 30

#define FRAME_POINTER_REGNUM 28

#define PREFERRED_RELOAD_CLASS(X, CLASS) ardac_preferred_reload_class(X, CLASS)

#define PREFERRED_OUTPUT_RELOAD_CLASS(X, CLASS) ardac_preferred_reload_class(X, 
CLASS)

enum reg_class
ardac_preferred_reload_class(rtx x, enum reg_class class)
{
if (CONSTANT_P(x)) {
switch (class) {
case NO_REGS:
case STACK_REGS:
return NO_REGS;
case EVEN_REGS:
case EIGHTEVEN_REGS:
return EIGHTEVEN_REGS;
case EIGHT_REGS:
case GENERAL_REGS:
return EIGHT_REGS;
default:
gcc_unreachable ();
}
}
else if (MEM_P(x)) {
switch (class) {
case NO_REGS:
case STACK_REGS:
return NO_REGS;
case EIGHT_REGS:
case EIGHTEVEN_REGS:
return EIGHTEVEN_REGS;
case EVEN_REGS:
case GENERAL_REGS:
return EVEN_REGS;
default:
gcc_unreachable ();
}
}
else {
if (GET_CODE (x) == PLUS
 GET_CODE (XEXP (x, 0)) == REG
 GET_CODE (XEXP (x, 1)) == CONST_INT) {
  return EIGHTEVEN_REGS;
}
return class;
}
}

Now it compiler 100+ files from libgcc without error so I guess the
register assignment problem is solved. It now fails later:

/home/tiniou/LTD/LTD/aRDAC/wip/src/gcc-4.3.0/libgcc/../gcc/unwind-dw2-fde.c: In 
function ‘frame_heapsort’:
/home/tiniou/LTD/LTD/aRDAC/wip/src/gcc-4.3.0/libgcc/../gcc/unwind-dw2-fde.c:521:
 internal compiler error: in expand_call, at calls.c:3149

I haven't investigated why yet, but this is probably not related to the above.

Thanks,

-- 
Stelian Pop [EMAIL PROTECTED]



Re: Problem with reloading in a new backend...

2008-04-11 Thread Stelian Pop

Le vendredi 11 avril 2008 à 11:14 -0700, Jim Wilson a écrit :
 Stelian Pop wrote:
  #define PREFERRED_RELOAD_CLASS(X, CLASS)\
((CONSTANT_P(X)) ? EIGHT_REGS :   \
 (MEM_P(X)) ? EVEN_REGS : CLASS)
  
  #define PREFERRED_OUTPUT_RELOAD_CLASS(X, CLASS) \
((CONSTANT_P(X)) ? EIGHT_REGS :   \
 (MEM_P(X)) ? EVEN_REGS : CLASS)
 
 I think most of your trouble is here.  Suppose we are trying to reload a 
 constant into an even-reg.  We call PREFERRED_RELOAD_CLASS, which says 
 to use eight_regs instead, and you get a fatal_insn error because you 
 didn't get the even-reg that the instruction needed.
 
 PREFERRED_RELOAD_CLASS must always return a class that is a strict 
 subset of the class that was passed in.
 
 So define another register class which is the intersection of eight regs 
 and even regs, and when we call PREFERRED_RELOAD_CLASS with a constant 
 and even regs, then return the eight/even intersection class.

Ah thanks, this does indeed seem to solve a lot of problems I had !

 Likewise in all of the other cases you are trying to handle.
 
 Fix this problem, and you probably don't need most of the other changes 
 you have made recently.

I will still have the problems with the fact that my indirect addressing
doesn't allow displacements, no ? (so I would need to implement
LEGITIMIZE_RELOAD_ADDRESS, in which I'll need a special reserved
register to compute the full address by adding the base and the
displacement). Or do you imply that I won't need this anymore ?

Thanks,

-- 
Stelian Pop [EMAIL PROTECTED]



Re: Problem with reloading in a new backend...

2008-04-10 Thread Stelian Pop

Le mercredi 09 avril 2008 à 18:21 -0400, DJ Delorie a écrit :
  Maybe I should reserve a special register for this usage (say r0).
 
 That might be the only way, yes.

Ok, I reserved r0 (BP_REGNUM) for such reloads, and I'm generating new
instructions in LEGITIMIZE_RELOAD_ADDRESS to calculate the memory
address:

if (GET_CODE (*x) == PLUS
 GET_CODE (XEXP (*x, 0)) == REG
 GET_CODE (XEXP (*x, 1)) == CONST_INT) {
rtx reginsn, setinsn, plusinsn;
reginsn = gen_rtx_REG(Pmode, BP_REGNUM);
setinsn = gen_rtx_SET(Pmode, reginsn, XEXP (*x, 1));
plusinsn = gen_rtx_SET(Pmode, reginsn, gen_rtx_PLUS(Pmode, 
reginsn, XEXP (*x, 0)));

emit_insn_before(setinsn, insn);
emit_insn_before(plusinsn, insn);
*x = reginsn;

return 1;
}

Does this sound ok ?

Note that I needed to use emit_insn_before() in order to insert the
instructions, and emit_insn_before() needs the current 'insn', which
is not passed by LEGITIMIZE_RELOAD_ADDRESS(), so I needed to modify the
macro. Is there something I miss here ?

 Note that reload also assumes that such adds don't change the flags
 (i.e.  a compare/jump pair must not have a flag-modifying add between
 them).

I think this won't happen because I emit the compare/conditional branch
insn at the same time, in beq/bne/bgt... etc define_insn() (like many
other targets).

Thanks.
-- 
Stelian Pop [EMAIL PROTECTED]



Re: Problem with reloading in a new backend...

2008-04-10 Thread Stelian Pop

Le jeudi 10 avril 2008 à 15:48 +0200, Stelian Pop a écrit :
 Le mercredi 09 avril 2008 à 18:21 -0400, DJ Delorie a écrit :
   Maybe I should reserve a special register for this usage (say r0).
  
  That might be the only way, yes.
 
 Ok, I reserved r0 (BP_REGNUM) for such reloads, and I'm generating new
 instructions in LEGITIMIZE_RELOAD_ADDRESS to calculate the memory
 address:
[...]

Now it seems that the register moves are correctly dealt with, but I'm
still having the same problem on calls: just like indirect addressing,
indirect calls are allowed only on even registers.

My patterns look like:

(define_insn *icall_value
  [(set (match_operand 0 register_operand =r)
(call (mem:QI (match_operand:QI 1 register_operand z))
  (match_operand:QI 2  )))]
 
   icall (%1)
  [(set_attr cc none)]
)

(define_expand call_value
  [(set (match_operand 0 register_operand =r)
(call (match_operand:QI 1 memory_operand m)
  (match_operand:QI 2 general_operand )))]
 
   {   
if (GET_CODE (XEXP(operands[1], 0)) != REG)
XEXP(operands[1], 0) = force_reg (QImode, XEXP 
(operands[1], 0));
   }
)

This gives:

(insn 27 26 29 2 ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:564 
(set (reg/f:QI 114)
(symbol_ref:QI (__lshrqi3) [flags 0x41])) 1 {*movqi} 
(expr_list:REG_EQUIV (symbol_ref:QI (__lshrqi3) [flags 0x41])
(nil)))

...

(call_insn/u 30 29 31 2 
../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:564 (set (reg:QI 4 r4) 
(call (mem:QI (reg/f:QI 114) [0 S1 A16])
(const_int 0 [0x0]))) 37 {*icall_value} (expr_list:REG_DEAD 
(reg:QI 5 r5) 
(expr_list:REG_EH_REGION (const_int -1 [0x])
(nil)))
(expr_list:REG_DEP_TRUE (use (reg:QI 5 r5))
(expr_list:REG_DEP_TRUE (use (reg:QI 4 r4 [ D.2373 ])) 
(nil

And r114 gets reloaded into r1:

Reloads for insn # 30
Reload 0: reload_in (QI) = (symbol_ref:QI (__lshrqi3) [flags 0x41])
 EIGHT_REGS, RELOAD_FOR_INPUT (opnum = 1), can't combine
 reload_in_reg: (reg/f:QI 114)
 reload_reg_rtx: (reg:QI 1 r1)

Which does not satisfy the *icall_value constraints:

../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c: In function 
‘__mulhi3’:
../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:570: error: insn does 
not satisfy its constraints:
(call_insn/u 30 195 162 2 
../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:564 (set (reg:QI 4 r4)
(call (mem:QI (reg:QI 1 r1) [0 S1 A16])
(const_int 0 [0x0]))) 37 {*icall_value} 
(expr_list:REG_EH_REGION (const_int -1 [0x])
(nil))
(expr_list:REG_DEP_TRUE (use (reg:QI 5 r5))
(expr_list:REG_DEP_TRUE (use (reg:QI 4 r4 [ D.2373 ]))
(nil

It seems that this reload doesn't pass through LEGITIMIZE_ADDRESS or
LEGITIMIZE_RELOAD_ADDRESS... How can I specify here to choose an EVEN_REGS
in place of the EIGHT_REGS (in fact it should choose one register in the 
intersection of EIGHT and EVEN_REGS) ?
 
Thanks,

-- 
Stelian Pop [EMAIL PROTECTED]



Re: Problem with reloading in a new backend...

2008-04-10 Thread Stelian Pop

Le jeudi 10 avril 2008 à 15:30 -0400, DJ Delorie a écrit :
  (call (mem:QI (match_operand:QI 1 register_operand z))
 
 Are you sure your z constraint only matches even numbered hard
 registers?

Well, I think so:

enum reg_class
{
  NO_REGS,
  BP_REGS,
  STACK_REGS,
  EIGHT_REGS,
  EVEN_REGS,
  GENERAL_REGS,
  ALL_REGS,
  LIM_REG_CLASSES
};

#define N_REG_CLASSES ((int) LIM_REG_CLASSES)

#define REG_CLASS_CONTENTS  \
{   \
  { 0x },   \
  { 0x0001 },   \
  { 0x8000 },   \
  { 0x00FF },   \
  { 0x },   \
  { 0x7FFE },   \
  { (1LL  FIRST_PSEUDO_REGISTER) - 1 }\
}

...

(define_register_constraint z EVEN_REGS
  Even registers (r0,r2,r4, @dots{} r30))


-- 
Stelian Pop [EMAIL PROTECTED]



Re: Problem with reloading in a new backend...

2008-04-10 Thread Stelian Pop

Le jeudi 10 avril 2008 à 15:56 -0400, [EMAIL PROTECTED] a écrit :
 I noticed
 
 
 Stack register is missing from ALL_REGS.

No, it is not. It is missing from GENERAL_REGS but not from ALL_REGS.

 Are registers 16bit? 

Yes.

 Is just one required for pointer?

For now, yes, I chose to support only 2^16 RAM addresses.

In fact, this microcontroller is able to address 2^24, and two registers
are used for indirect accesses (Rx and Rx+1, where x is even), this is
the reason why only even registers are allowed in indirect addressing...

-- 
Stelian Pop [EMAIL PROTECTED]



Re: Problem with reloading in a new backend...

2008-04-09 Thread Stelian Pop
[Putting the gcc-list back in CC:, ]

Le mardi 08 avril 2008 à 18:24 -0400, DJ Delorie a écrit :

 Do you have one insn for each pair of src/dest that movqi supports?
 If so, this isn't the best way to do it - you should have one insn
 with multiple constraint alternativess, not multiple insns.
[...]
 reload deals with selecting among constraint
 options, it doesn't usually have the choice about which pattern to
 choose - the first that matches is used.  If you have a list of
 patterns that all match, only the first is available to reload.  Plus,
 reload gets confused when the predicates are used to choose among
 otherwise identical patterns.  So, it's best to have a more general
 predicate (like general_operand) and use the constraints to tell
 reload how to implement that insn in hardware.

Thanks to your suggestion, I changed my movqi pattern to look like:

(define_insn *movqi
  [(set (match_operand:QI 0 nonimmediate_operand =r,y,y,m,r)
(match_operand:QI 1 general_operand r,n,s,r,m))]

  {
switch (which_alternative) {
case 0: /* register to register */
return tfr %0,%1;
case 1: /* immediate to register */
output_asm_insn (ldih %0, hi(%1), operands);
output_asm_insn (ldil %0, lo(%1), operands);
return ;
case 2: /* immediate symbol to register */
output_asm_insn (ldih %0, hi(%c1), operands);
output_asm_insn (ldil %0, lo(%c1), operands);
return ;
case 3: /* register to memory */
if (GET_CODE (XEXP(operands[0], 0)) == REG) {
operands[0] = XEXP(operands[0], 0);
return st %1,(%0);
}
fatal_insn (Incorrect operand:, operands[0]);
case 4: /* memory to register */
if (GET_CODE (XEXP(operands[1], 0)) == REG) {
operands[1] = XEXP(operands[1], 0);
return ld %0,(%1);
}
fatal_insn (Incorrect operand:, operands[1]);
}
return ; 
  }
  [(set_attr cc none)]
)

Does this look ok ? The 'fatal_insn' should not happen, because if I see
such a pattern in the define_expand movqi I force the use of a register:

(define_expand movqi
  [(set (match_operand:QI 0 nonimmediate_operand )
(match_operand:QI 1 general_operand ))]
  
  {
if (!reload_in_progress
 !reload_completed) {

if (GET_CODE (operands[0]) == MEM
 (GET_CODE (operands[1]) != REG)) {
operands[1] = force_reg (QImode, operands[1]);
}
else if (GET_CODE(operands[1]) == MEM
 GET_CODE(XEXP(operands[1], 0)) == PLUS
 GET_CODE(XEXP(XEXP(operands[1], 0), 0)) == REG
 GET_CODE(XEXP(XEXP(operands[1], 0), 1)) == 
CONST_INT) {
  /* indirect load */
  XEXP(operands[1], 0) = force_reg (QImode, XEXP 
(operands[1], 0));
}
else if (GET_CODE(operands[0]) == MEM
 GET_CODE(XEXP(operands[0], 0)) == PLUS
 GET_CODE(XEXP(XEXP(operands[0], 0), 0)) == REG
 GET_CODE(XEXP(XEXP(operands[0], 0), 1)) == 
CONST_INT) {
  /* indirect store */
  XEXP(operands[0], 0) = force_reg (QImode, XEXP 
(operands[0], 0));
}
}
  }
)

This seems to work ok, but I still have issues at reload time, because
of the base register addressing mode: in the reload pass gcc generates
moves from/to the stack:

Reloads for insn # 3
Reload 0: reload_in (QI) = (reg/f:QI 31 r31) 
EVEN_REGS, RELOAD_FOR_OPERAND_ADDRESS (opnum = 0) 
reload_in_reg: (reg/f:QI 31 r31) 
reload_reg_rtx: (reg:QI 0 r0)
Reload 1: reload_out (QI) = (mem/c:QI (plus:QI (reg/f:QI 31 r31) 
   (const_int -3 
[0xfffd])) [10 S1 A16])
EVEN_REGS, RELOAD_FOR_OUTPUT (opnum = 0), optional
reload_out_reg: (reg:QI 109 [ u ]) 

But those moves are illegal because there is no offset allowed in the
base register addressing mode (see the definition of my 
GO_IF_LEGITIMATE_ADDRESS() ),
so gcc crashes with 'unrecognizable insn'.

So what's the proper way to tell that indirect addressing is allowed,
but not with an offset ? Should I define an extra define_expand to deal
with those insns ?

Thanks again,

Stelian.
-- 
Stelian Pop [EMAIL PROTECTED]



Re: Problem with reloading in a new backend...

2008-04-09 Thread Stelian Pop

Le mercredi 09 avril 2008 à 12:41 -0400, DJ Delorie a écrit :
  switch (which_alternative) {
  case 0: /* register to register */
 
 Better to just use the @ syntax that gcc offers, to provide multiple
 patterns:
 
   @
   tfr %0,%1
   ldih %0, hi(%1); ldil %0, lo(%1)
   ldih %0, hi(%1); ldil %0, lo(%1)
   st %1,(%0)
   ld %0,(%1)
 
 Everything else should have been sorted out by the constraints.

Right.

  This seems to work ok, but I still have issues at reload time, because
  of the base register addressing mode: in the reload pass gcc generates
  moves from/to the stack:
 
 You might need to define LEGITIMIZE_RELOAD_ADDRESS, or at least
 LEGITIMIZE_ADDRESS.  I don't know if reload has assumptions about such
 offsets, but the m32c port has a limit on the offset range so it might
 help you figure out your port.

Ah, this looks exactly like what I needed, thanks!

I'll try this and come back afterwards.

-- 
Stelian Pop [EMAIL PROTECTED]



Re: Problem with reloading in a new backend...

2008-04-09 Thread Stelian Pop

Le mercredi 09 avril 2008 à 21:19 +0200, Stelian Pop a écrit :

  You might need to define LEGITIMIZE_RELOAD_ADDRESS, or at least
  LEGITIMIZE_ADDRESS.  I don't know if reload has assumptions about such
  offsets, but the m32c port has a limit on the offset range so it might
  help you figure out your port.
 
 Ah, this looks exactly like what I needed, thanks!
 
 I'll try this and come back afterwards.

Ok, I tried.

Since displacements are not allowed in my addressing mode, I need to
replace:
(mem (plus (reg X) (const_int Y)))
into
(set (reg Z) (const_int Y))
(set (reg Z) (plus (reg Z) (reg X)))
(mem (reg Z)

This means I need to create a new pseodo register. This is allowed in
LEGITIMIZE_ADDRESS but not in LEGITIMIZE_RELOAD_ADDRESS...

Is there a way to do this ?

Maybe I should reserve a special register for this usage (say r0). But
maybe there is a better solution...

Thanks,
-- 
Stelian Pop [EMAIL PROTECTED]



Problem with reloading in a new backend...

2008-04-08 Thread Stelian Pop
 EVEN_REGS:0 ALL_REGS:0 MEM:4175
Register 466 costs: EIGHT_REGS:600 EVEN_REGS:600 ALL_REGS:600 MEM:5200
...
Register 453 pref EVEN_REGS
Register 466 pref EVEN_REGS
...
(insn 16 15 21 2 ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1090 
(set (reg:QI 453 [ uu+1 ])
(reg:QI 466 [ v ])) 0 {*movqi_reg} (nil))

In libgcc2.c.176.greg I see:

Reloads for insn # 16
Reload 0: reload_in (QI) = (plus:QI (reg/f:QI 30 r30)
(const_int 24 
[0x18]))
EVEN_REGS, RELOAD_FOR_OUTPUT_ADDRESS (opnum = 0), can't combine 
reload_in_reg: (plus:QI (reg/f:QI 30 r30)
(const_int 24 [0x18]))
reload_reg_rtx: (reg:QI 10 r10)
Reload 1: reload_out (QI) = (mem/c:QI (plus:QI (reg/f:QI 30 r30)
(const_int 24 
[0x18])) [31 S1 A16])
EVEN_REGS, RELOAD_FOR_OUTPUT (opnum = 0)
reload_out_reg: (reg:QI 453 [ uu+1 ])
reload_reg_rtx: (reg:QI 14 r14)


...

(insn 16 1115 1117 2 
../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1090 (set (reg:QI 14 r14)
(reg:QI 2 r2 [orig:466 v ] [466])) 0 {*movqi_reg} (nil))

(insn 1117 16 1118 2 
../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1090 (set (reg:QI 10 r10)
(const_int 24 [0x18])) 1 {*movqi_imm} (nil))

(insn 1118 1117 1119 2 
../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1090 (set (reg:QI 10 r10)
(plus:QI (reg:QI 10 r10)
(reg/f:QI 30 r30))) 13 {addqi3} (expr_list:REG_EQUIV 
(plus:QI (reg/f:QI 30 r30)
(const_int 24 [0x18]))
(nil)))

(insn 1119 1118 21 2 
../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1090 (set (mem/c:QI (reg:QI 
10 r10) [31 S1 A16])
(reg:QI 14 r14)) 8 {*movqi_tomem} (nil))

I tried playing with different definitions for PREFERRED_RELOAD_CLASS,
PREFERRED_OUTPUT_RELOAD_CLASS, TARGET_SECONDARY_RELOAD, with no luck.

Thanks to anybody who can explain to me what's wrong here, and give a clue
on what I must do to fix it.

Stelian.
-- 
Stelian Pop [EMAIL PROTECTED]