bit test insns on coldfire.
Peter Barada
pbarada@mail.wm.sps.mot.com
Sun Nov 11 11:23:00 GMT 2001
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
More information about the crossgcc
mailing list