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>

Reply via email to