aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorTorbjorn Granlund <tege@gnu.org>1992-09-13 15:39:59 +0000
committerTorbjorn Granlund <tege@gnu.org>1992-09-13 15:39:59 +0000
commit0e7f4c1941fff8d4a48a85b3757c29680b8071d5 (patch)
treed2f2ddae83815ca7d9addeaae7791355b1bebbe4 /gcc
parent7254dbd49778f0842a6ed26cfb92fd5c0d60e7a7 (diff)
downloadgcc-0e7f4c1941fff8d4a48a85b3757c29680b8071d5.zip
gcc-0e7f4c1941fff8d4a48a85b3757c29680b8071d5.tar.gz
gcc-0e7f4c1941fff8d4a48a85b3757c29680b8071d5.tar.bz2
(compute_xdepi_operands_from_integer): New function.
Some code come from output_zdepi. (output_zdepi): Removed. (depi_cint_operand): New name for zdepi_operand. (consec_zeros_p, and_operand, ior_mask_p, ior_operand, output_and, output_ior): New functions. (output_load_address): Removed. Nothing uses it. From-SVN: r2115
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/pa/pa.c249
1 files changed, 146 insertions, 103 deletions
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 71e644b..1e18a14 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -316,7 +316,8 @@ arith5_operand (op, mode)
}
/* True iff zdepi can be used to generate this CONST_INT. */
-zdepi_operand (op, mode)
+int
+depi_cint_operand (op, mode)
rtx op;
enum machine_mode mode;
{
@@ -334,6 +335,45 @@ zdepi_operand (op, mode)
return ((t & (t - 1)) == 0);
}
+/* True iff depi or extru can be used to compute (reg & mask). */
+int
+consec_zeros_p (mask)
+ unsigned mask;
+{
+ mask = ~mask;
+ mask += mask & -mask;
+ return (mask & (mask - 1)) == 0;
+}
+
+/* True iff depi or extru can be used to compute (reg & OP). */
+int
+and_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (register_operand (op, mode)
+ || (GET_CODE (op) == CONST_INT && consec_zeros_p (INTVAL (op))));
+}
+
+/* True iff depi can be used to compute (reg | MASK). */
+int
+ior_mask_p (mask)
+ unsigned mask;
+{
+ mask += mask & -mask;
+ return (mask & (mask - 1)) == 0;
+}
+
+/* True iff depi can be used to compute (reg | OP). */
+int
+ior_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (register_operand (op, mode)
+ || (GET_CODE (op) == CONST_INT && ior_mask_p (INTVAL (op))));
+}
+
int
arith32_operand (op, mode)
rtx op;
@@ -648,7 +688,7 @@ emit_move_sequence (operands, mode)
return 1;
}
}
- else if (zdepi_operand (operand1, VOIDmode))
+ else if (depi_cint_operand (operand1, VOIDmode))
return 0;
else if (GET_CODE (operand1) == CONST_INT
? (! SMALL_INT (operand1)
@@ -699,43 +739,43 @@ singlemove_string (operands)
}
-char *
-output_zdepi (operands)
+/* Compute position (in OPERANDS[2]) and width (in OPERANDS[3])
+ useful for copying or or'ing IMM to a register using bit field
+ instructions. Store the immediate value to insert in OPERANDS[1]. */
+void
+compute_xdepi_operands_from_integer (imm, operands)
+ unsigned imm;
rtx *operands;
{
- unsigned long x = INTVAL (operands[1]);
- int i;
+ int lsb, len;
- for (i = 0; i < 32; i++)
+ /* Find the least significant set bit in IMM. */
+ for (lsb = 0; lsb < 32; lsb++)
{
- if ((x & 1) != 0)
+ if ((imm & 1) != 0)
break;
- x >>= 1;
+ imm >>= 1;
}
- if ((x & 0x10) == 0)
- {
- operands[1] = gen_rtx (CONST_INT, VOIDmode, x);
- operands[2] = gen_rtx (CONST_INT, VOIDmode, 31 - i);
- operands[3] = gen_rtx (CONST_INT, VOIDmode, 32 - i < 4 ? 32 - i : 4);
- }
+ /* Choose variants based on *sign* of the 5-bit field. */
+ if ((imm & 0x10) == 0)
+ len = (lsb <= 28) ? 4 : 32 - lsb;
else
{
- operands[1] = gen_rtx (CONST_INT, VOIDmode, (x & 0xf) - 0x10);
- operands[2] = gen_rtx (CONST_INT, VOIDmode, 31 - i);
-
- x >>= 5;
- for (i = 0; i < 32; i++)
+ /* Find the width of the bitstring in IMM. */
+ for (len = 5; len < 32; len++)
{
- if ((x & 1) == 0)
+ if ((imm & (1 << len)) == 0)
break;
- x >>= 1;
}
- operands[3] = gen_rtx (CONST_INT, VOIDmode, i + 5);
+ /* Sign extend IMM as a 5-bit value. */
+ imm = (imm & 0xf) - 0x10;
}
- return "zdepi %1,%2,%3,%0";
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, imm);
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, 31 - lsb);
+ operands[3] = gen_rtx (CONST_INT, VOIDmode, len);
}
/* Output assembler code to perform a doubleword move insn
@@ -1011,85 +1051,6 @@ find_addr_reg (addr)
abort ();
}
-/* Load the address specified by OPERANDS[3] into the register
- specified by OPERANDS[0].
-
- OPERANDS[3] may be the result of a sum, hence it could either be:
-
- (1) CONST
- (2) REG
- (2) REG + CONST_INT
- (3) REG + REG + CONST_INT
- (4) REG + REG (special case of 3).
-
- Note that (3) is not a legitimate address.
- All cases are handled here. */
-
-void
-output_load_address (operands)
- rtx *operands;
-{
- rtx base, offset;
-
- if (CONSTANT_P (operands[3]))
- {
- output_asm_insn ("ldi %3,%0", operands);
- return;
- }
-
- if (REG_P (operands[3]))
- {
- if (REGNO (operands[0]) != REGNO (operands[3]))
- output_asm_insn ("copy %3,%0", operands);
- return;
- }
-
- if (GET_CODE (operands[3]) != PLUS)
- abort ();
-
- base = XEXP (operands[3], 0);
- offset = XEXP (operands[3], 1);
-
- if (GET_CODE (base) == CONST_INT)
- {
- rtx tmp = base;
- base = offset;
- offset = tmp;
- }
-
- if (GET_CODE (offset) != CONST_INT)
- {
- /* Operand is (PLUS (REG) (REG)). */
- base = operands[3];
- offset = const0_rtx;
- }
-
- if (REG_P (base))
- {
- operands[6] = base;
- operands[7] = offset;
- if (INT_14_BITS (offset))
- output_asm_insn ("ldo %7(%6),%0", operands);
- else
- output_asm_insn ("addil L'%7,%6\n\tldo R'%7(1),%0", operands);
- }
- else if (GET_CODE (base) == PLUS)
- {
- operands[6] = XEXP (base, 0);
- operands[7] = XEXP (base, 1);
- operands[8] = offset;
-
- if (offset == const0_rtx)
- output_asm_insn ("add %6,%7,%0", operands);
- else if (INT_14_BITS (offset))
- output_asm_insn ("add %6,%7,%0\n\tldo %8(%0),%0", operands);
- else
- output_asm_insn ("addil L'%8,%6\n\tldo R'%8(1),%0\n\tadd %0,%7,%0", operands);
- }
- else
- abort ();
-}
-
/* Emit code to perform a block move.
Restriction: If the length argument is non-constant, alignment
@@ -1262,6 +1223,88 @@ output_block_move (operands, size_is_constant)
}
+char *
+output_and (operands)
+ rtx *operands;
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ unsigned mask = INTVAL (operands[2]);
+ int ls0, ls1, ms0, p, len;
+
+ for (ls0 = 0; ls0 < 32; ls0++)
+ if ((mask & (1 << ls0)) == 0)
+ break;
+
+ for (ls1 = ls0; ls1 < 32; ls1++)
+ if ((mask & (1 << ls1)) != 0)
+ break;
+
+ for (ms0 = ls1; ms0 < 32; ms0++)
+ if ((mask & (1 << ms0)) == 0)
+ break;
+
+ if (ms0 != 32)
+ abort();
+
+ if (ls1 == 32)
+ {
+ len = ls0;
+
+ if (len == 0)
+ abort ();
+
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, len);
+ return "extru %1,31,%2,%0";
+ }
+ else
+ {
+ /* We could use this `depi' for the case above as well, but `depi'
+ requires one more register file access than an `extru'. */
+
+ p = 31 - ls0;
+ len = ls1 - ls0;
+
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, p);
+ operands[3] = gen_rtx (CONST_INT, VOIDmode, len);
+ return "depi 0,%2,%3,%0";
+ }
+ }
+ else
+ return "and %1,%2,%0";
+}
+
+char *
+output_ior (operands)
+ rtx *operands;
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ unsigned mask = INTVAL (operands[2]);
+ int bs0, bs1, bs2, p, len;
+
+ for (bs0 = 0; bs0 < 32; bs0++)
+ if ((mask & (1 << bs0)) != 0)
+ break;
+
+ for (bs1 = bs0; bs1 < 32; bs1++)
+ if ((mask & (1 << bs1)) == 0)
+ break;
+
+ if (bs1 != 32 && ((unsigned) 1 << bs1) <= mask)
+ abort();
+
+ p = 31 - bs0;
+ len = bs1 - bs0;
+
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, p);
+ operands[3] = gen_rtx (CONST_INT, VOIDmode, len);
+ return "depi -1,%2,%3,%0";
+ }
+ else
+ return "or %1,%2,%0";
+}
+
/* Output an ascii string. */
output_ascii (file, p, size)
FILE *file;