Stelian Pop schrieb:
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 ?
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. 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.
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.
Georg-Johann