This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[csl-arm-branch] Add sign/zero extend instructions.
- From: Paul Brook <paul at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Mark Mitchell <mark at codesourcery dot com>,Richard Earnshaw <rearnsha at arm dot com>
- Date: Tue, 23 Dec 2003 23:34:53 +0000
- Subject: [csl-arm-branch] Add sign/zero extend instructions.
- Organization: CodeSourcery
The attached patch adds patterns for the armv6 sign/zero extend instructions,
including the extend and add insns.
It currently only implements the unrotated variants.
Tested with cross-compiler to arm-none-elf/mcpu=arm1136js.
Ok?
Paul
2003-12-23 Paul Brook <paul@codesourcery.com>
* config/arm/arm.c (arm_arch6j): New variable.
(arm_override_options): Set it.
(arm_emit_extendsi): New function.
* config/arm/arm-protos.h (arm_emit_extendsi): Add prototype.
* config/arm/arm.h (arm_arch6j): Declare.
* config/arm/arm.md: Add sign/zero extend insns.
Index: gcc/config/arm/arm-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm-protos.h,v
retrieving revision 1.60.4.3
diff -u -p -r1.60.4.3 arm-protos.h
--- gcc/config/arm/arm-protos.h 23 Dec 2003 22:08:30 -0000 1.60.4.3
+++ gcc/config/arm/arm-protos.h 23 Dec 2003 23:16:03 -0000
@@ -140,6 +140,7 @@ extern void arm_final_prescan_insn (rtx)
extern int arm_go_if_legitimate_address (enum machine_mode, rtx);
extern int arm_debugger_arg_offset (int, rtx);
extern int arm_is_longcall_p (rtx, int, int);
+extern int arm_emit_extendsi (enum rtx_code, rtx, rtx);
extern int arm_emit_vector_const (FILE *, rtx);
extern const char * arm_output_load_gr (rtx *);
Index: gcc/config/arm/arm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.c,v
retrieving revision 1.303.2.8
diff -u -p -r1.303.2.8 arm.c
--- gcc/config/arm/arm.c 23 Dec 2003 23:03:27 -0000 1.303.2.8
+++ gcc/config/arm/arm.c 23 Dec 2003 23:16:06 -0000
@@ -325,6 +325,9 @@ int arm_arch5 = 0;
/* Nonzero if this chip supports the ARM Architecture 5E extensions. */
int arm_arch5e = 0;
+/* Nonzero if this chip supports the ARM Architecture 6 extensions. */
+int arm_arch6j = 0;
+
/* Nonzero if this chip can benefit from load scheduling. */
int arm_ld_sched = 0;
@@ -779,6 +782,7 @@ arm_override_options (void)
arm_arch4 = (insn_flags & FL_ARCH4) != 0;
arm_arch5 = (insn_flags & FL_ARCH5) != 0;
arm_arch5e = (insn_flags & FL_ARCH5E) != 0;
+ arm_arch6j = (insn_flags & FL_ARCH6J) != 0;
arm_arch_xscale = (insn_flags & FL_XSCALE) != 0;
arm_ld_sched = (tune_flags & FL_LDSCHED) != 0;
@@ -13270,6 +13274,40 @@ arm_output_mi_thunk (FILE *file, tree th
fputc ('\n', file);
}
}
+
+/* Emit RTL for a sign/zero extend insn. */
+int
+arm_emit_extendsi (enum rtx_code code, rtx op0, rtx op1)
+{
+ rtx tmp;
+ rtx *p;
+
+ if (GET_CODE (op1) != SUBREG
+ || !arm_arch6j)
+ return 0;
+
+ p = &XEXP (op1, 0);
+ if (GET_CODE (*p) != REG)
+ return 0;
+
+ if (XINT (op1, 1) != 0)
+ return 0;
+
+ /* Put the low part of multiword regs into an SImode reg so we only
+ have to deal with subregs of SImode regs. */
+ if (GET_MODE (*p) != SImode)
+ {
+ tmp = gen_reg_rtx (SImode);
+ emit_insn (gen_rtx_SET (VOIDmode, tmp,
+ gen_lowpart (SImode, *p)));
+ *p = tmp;
+ }
+
+ emit_insn (gen_rtx_SET (VOIDmode, op0,
+ gen_rtx_fmt_e (code, SImode, op1)));
+ return 1;
+}
+
int
arm_emit_vector_const (FILE *file, rtx x)
Index: gcc/config/arm/arm.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.h,v
retrieving revision 1.210.2.4
diff -u -p -r1.210.2.4 arm.h
--- gcc/config/arm/arm.h 23 Dec 2003 22:08:30 -0000 1.210.2.4
+++ gcc/config/arm/arm.h 23 Dec 2003 23:16:07 -0000
@@ -692,6 +692,9 @@ extern int arm_arch5;
/* Nonzero if this chip supports the ARM Architecture 5E extensions */
extern int arm_arch5e;
+
+/* Nonzero if this chip supports the ARM Architecture 6 extensions */
+extern int arm_arch6j;
/* Nonzero if this chip can benefit from load scheduling. */
extern int arm_ld_sched;
Index: gcc/config/arm/arm.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.md,v
retrieving revision 1.145.2.7
diff -u -p -r1.145.2.7 arm.md
--- gcc/config/arm/arm.md 23 Dec 2003 22:08:31 -0000 1.145.2.7
+++ gcc/config/arm/arm.md 23 Dec 2003 23:16:08 -0000
@@ -3132,63 +3132,47 @@
"TARGET_EITHER"
"
{
- if (TARGET_ARM)
+ if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
{
- if (arm_arch4 && GET_CODE (operands[1]) == MEM)
- {
- /* Note: We do not have to worry about TARGET_MMU_TRAPS
- here because the insn below will generate an LDRH instruction
- rather than an LDR instruction, so we cannot get an unaligned
- word access. */
- emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_ZERO_EXTEND (SImode,
- operands[1])));
- DONE;
- }
- if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
- {
- emit_insn (gen_movhi_bytes (operands[0], operands[1]));
- DONE;
- }
- if (!s_register_operand (operands[1], HImode))
- operands[1] = copy_to_mode_reg (HImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = gen_reg_rtx (SImode);
- }
- else /* TARGET_THUMB */
- {
- if (GET_CODE (operands[1]) == MEM)
- {
- rtx tmp;
-
- tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
- tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
- emit_insn (tmp);
- }
- else
- {
- rtx ops[3];
-
- if (!s_register_operand (operands[1], HImode))
- operands[1] = copy_to_mode_reg (HImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = gen_reg_rtx (SImode);
-
- ops[0] = operands[2];
- ops[1] = operands[1];
- ops[2] = GEN_INT (16);
+ /* Note: We do not have to worry about TARGET_MMU_TRAPS
+ here because the insn below will generate an LDRH instruction
+ rather than an LDR instruction, so we cannot get an unaligned
+ word access. */
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_ZERO_EXTEND (SImode,
+ operands[1])));
+ DONE;
+ }
+ if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
+ {
+ emit_insn (gen_movhi_bytes (operands[0], operands[1]));
+ DONE;
+ }
+ if (arm_emit_extendsi (ZERO_EXTEND, operands[0], operands[1]))
+ DONE;
+ if (!s_register_operand (operands[1], HImode))
+ operands[1] = copy_to_mode_reg (HImode, operands[1]);
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ operands[2] = gen_reg_rtx (SImode);
- emit_insn (gen_rtx_SET (VOIDmode, ops[0],
- gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
+ if (TARGET_THUMB)
+ {
+ rtx ops[3];
+
+ ops[0] = operands[2];
+ ops[1] = operands[1];
+ ops[2] = GEN_INT (16);
+
+ emit_insn (gen_rtx_SET (VOIDmode, ops[0],
+ gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
+
+ ops[0] = operands[0];
+ ops[1] = operands[2];
+ ops[2] = GEN_INT (16);
- ops[0] = operands[0];
- ops[1] = operands[2];
- ops[2] = GEN_INT (16);
-
- emit_insn (gen_rtx_SET (VOIDmode, ops[0],
- gen_rtx_LSHIFTRT (SImode, ops[1],
- ops[2])));
- }
+ emit_insn (gen_rtx_SET (VOIDmode, ops[0],
+ gen_rtx_LSHIFTRT (SImode, ops[1],
+ ops[2])));
DONE;
}
}"
@@ -3247,6 +3231,23 @@
(set_attr "neg_pool_range" "244")]
)
+(define_insn "*arm_zero_extendhisi2_reg"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (zero_extend:SI (subreg:HI
+ (match_operand:SI 1 "s_register_operand" "r") 0)))]
+ "TARGET_EITHER && arm_arch6j"
+ "uxth%?\\t%0, %1"
+)
+
+(define_insn "*arm_zero_extendhisi2addsi"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (plus:SI (zero_extend:SI (subreg:HI
+ (match_operand:SI 1 "s_register_operand" "r") 0))
+ (match_operand:SI 2 "s_register_operand" "r")))]
+ "TARGET_ARM && arm_arch6j"
+ "uxtah%?\\t%0, %2, %1"
+)
+
(define_split
[(set (match_operand:SI 0 "s_register_operand" "")
(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
@@ -3282,6 +3283,8 @@
(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
"TARGET_EITHER"
"
+ if (arm_emit_extendsi (ZERO_EXTEND, operands[0], operands[1]))
+ DONE;
if (GET_CODE (operands[1]) != MEM)
{
if (TARGET_ARM)
@@ -3338,6 +3341,23 @@
(set_attr "neg_pool_range" "4084")]
)
+(define_insn "*arm_zero_extendqisi2_reg"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (zero_extend:SI (subreg:QI
+ (match_operand:SI 1 "s_register_operand" "r") 0)))]
+ "TARGET_EITHER && arm_arch6j"
+ "uxtb%?\\t%0, %1"
+)
+
+(define_insn "*arm_zero_extendqisi2addsi"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (plus:SI (zero_extend:SI (subreg:QI
+ (match_operand:SI 1 "s_register_operand" "r") 0))
+ (match_operand:SI 2 "s_register_operand" "r")))]
+ "TARGET_ARM && arm_arch6j"
+ "uxtab%?\\t%0, %2, %1"
+)
+
(define_split
[(set (match_operand:SI 0 "s_register_operand" "")
(zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
@@ -3383,6 +3403,8 @@
emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
DONE;
}
+ if (arm_emit_extendsi (SIGN_EXTEND, operands[0], operands[1]))
+ DONE;
if (!s_register_operand (operands[1], HImode))
operands[1] = copy_to_mode_reg (HImode, operands[1]);
operands[1] = gen_lowpart (SImode, operands[1]);
@@ -3517,6 +3539,23 @@
(set_attr "neg_pool_range" "244")]
)
+(define_insn "*arm_extendhisi2_reg"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (sign_extend:SI (subreg:HI
+ (match_operand:SI 1 "s_register_operand" "r") 0)))]
+ "TARGET_EITHER && arm_arch6j"
+ "sxth%?\\t%0, %1"
+)
+
+(define_insn "*arm_extendhisi2addsi"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (plus:SI (sign_extend:SI (subreg:HI
+ (match_operand:SI 1 "s_register_operand" "r") 0))
+ (match_operand:SI 2 "s_register_operand" "r")))]
+ "TARGET_ARM && arm_arch6j"
+ "sxtah%?\\t%0, %2, %1"
+)
+
(define_split
[(set (match_operand:SI 0 "s_register_operand" "")
(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
@@ -3641,6 +3680,8 @@
gen_rtx_SIGN_EXTEND (SImode, operands[1])));
DONE;
}
+ if (arm_emit_extendsi (SIGN_EXTEND, operands[0], operands[1]))
+ DONE;
if (!s_register_operand (operands[1], QImode))
operands[1] = copy_to_mode_reg (QImode, operands[1]);
operands[1] = gen_lowpart (SImode, operands[1]);
@@ -3686,6 +3727,23 @@
(set_attr "length" "8")
(set_attr "pool_range" "256")
(set_attr "neg_pool_range" "244")]
+)
+
+(define_insn "*arm_extendqisi2_reg"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (sign_extend:SI (subreg:QI
+ (match_operand:SI 1 "s_register_operand" "r") 0)))]
+ "TARGET_EITHER && arm_arch6j"
+ "sxtb%?\\t%0, %1"
+)
+
+(define_insn "*arm_extendqisi2addsi"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (plus:SI (sign_extend:SI (subreg:QI
+ (match_operand:SI 1 "s_register_operand" "r") 0))
+ (match_operand:SI 2 "s_register_operand" "r")))]
+ "TARGET_ARM && arm_arch6j"
+ "sxtab%?\\t%0, %2, %1"
)
(define_split