This is the mail archive of the crossgcc@sources.redhat.com mailing list for the crossgcc project.

See the CrossGCC FAQ for lots more information.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: bit test insns on coldfire.



I'm in the midst of adding the latest coldfire extensions to 2.95.3,
and I'm having a very difficult time convincing gcc to use the 'btst'
instruction in the case where its a branch on a bitfield extract of
only one bit. 

Initially I tried tweaking the conditions on the existing
zero/sign_extract patterns, but noticed that none were being
generated.  After much poking and prodding with gdb, I found that when
the rtl is generated, if the target moachine doesn't support andqi3,
(gcc/optabs.c:830), then gcc replaces the bit extract with a
load/and/tst sequence.

Later in the compilation, it attempts to combines back together an
instruction that includes the zero_extract.  One such is:

(jump_insn 15 14 41 (set (pc)
        (if_then_else (eq (zero_extract:SI (mem/s:QI (plus:SI (reg/v:SI 8 %a0)
                            (const_int 5 [0x5])) 0)
                    (const_int 1 [0x1])
                    (const_int 1 [0x1]))
                (const_int 0 [0x0]))
            (label_ref 28)
            (pc))) 33 {cf_btst} (insn_list 4 (nil))
    (expr_list:REG_DEAD (reg/v:SI 8 %a0)
        (nil)))

In this case I generated a pattern that matches this.  The important
thing to notw is that on the ColdFire, btst with a constant bit number
can *not* use all addressing modes.  In fact its restricted to only
one extension word so the memory addressing modes supported are
2,3,4,5 but not 6(indexed) and not 7.0/1 (word/long absolute).
To get around this I created the extra constraint 'S' which returnes
true of the operand is mode 5(offset addressing) as such:

   (C) == 'S' ? (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == PLUS \
                 && (GET_CODE (XEXP(XEXP(OP, 0),0)) == REG               \
                     && GET_CODE (XEXP(XEXP(OP, 0),1)) == CONST_INT      \
                     || GET_CODE (XEXP(XEXP(OP, 0),0)) == CONST_INT      \
                     && GET_CODE (XEXP(XEXP(OP, 0),0)) == REG)) :        \


Here's the pattern:

(define_insn "cf_btst_eq_fwd"
  [(set (pc)
    (if_then_else
     (eq
      (zero_extract:SI
       (match_operand:QI 0 "memory_operand" "S") 
       (const_int 1)
       (match_operand:SI 1 "const_int_operand" "n"))
      (const_int 0))
     (label_ref (match_operand 2 "" ""))
     (pc)))]
  "TARGET_COLDFIRE"
  "*
{
  operands[0] = adj_offsettable_operand (operands[0],
                                         INTVAL (operands[1]) / 8);
  operands[1] = GEN_INT (7 - INTVAL (operands[1]) % 8);
  output_asm_insn (output_btst(operands, operands[1], operands[0],
                               insn, 7), operands);
  return \"jbeq %2\";
}")

Now this works fine in the case where operand 0 is a memory operand
using mode 5 addressing.  Unfortunately the case I have now is that 
*any* memory operand matches.  I next attempted to create a new
predicate:

/* On ColdFire, btst can only handle addressing modes
   0,2,3,4,5 if the bit number is constant */
int
btst_imm_address_operand(op, mode)
     rtx op;
     enum machine_mode mode;
{
  if (EXTRA_CONSTRAINT(op, 'S'))
    return 1;
  else
    return 0;
}


And modified the pattern to be:

(define_insn "cf_btst_eq_fwd"
  [(set (pc)
    (if_then_else
     (eq
      (zero_extract:SI
       (match_operand:QI 0 "btst_imm_address_operand" "S") 
       (const_int 1)
       (match_operand:SI 1 "const_int_operand" "n"))
      (const_int 0))
     (label_ref (match_operand 2 "" ""))
     (pc)))]
  "TARGET_COLDFIRE"
  "*
{
  operands[0] = adj_offsettable_operand (operands[0],
                                         INTVAL (operands[1]) / 8);
  operands[1] = GEN_INT (7 - INTVAL (operands[1]) % 8);
  output_asm_insn (output_btst(operands, operands[1], operands[0],
                               insn, 7), operands);
  return \"jbeq %2\";
}")


and it *still* wants to use the pattern.

Does anyone have an idea how to convince gcc that this is a good
pattern, but only if the memory reference is mode 5(address register
indirect with displacement)???

Any help or ideas are appreciated.


------
Want more information?  See the CrossGCC FAQ, http://www.objsw.com/CrossGCC/
Want to unsubscribe? Send a note to crossgcc-unsubscribe@sourceware.cygnus.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]