Commit 907dd0c7 by Richard Earnshaw Committed by Richard Earnshaw

arm.c (thumb1_output_casesi): New function.

	* arm.c (thumb1_output_casesi): New function.
	* arm.h (CASE_VECTOR_PC_RELATIVE): Thumb-1 code is also relative if
	optimizing for size or PIC.
	(CASE_VECTOR_SHORTEN_MODE): Handle thumb-1.
	* arm.md (UNSPEC_THUMB1_CASESI): New constant.
	(casesi): Handle Thumb-1 when optimizing for size or PIC.
	(thumb1_casesi_internal_pic): New expand rule.
	(thumb1_casesi_dispatch): New pattern.
	* aout.h (ASM_OUTPUT_ADDR_DIFF_ELT): Use shortened vectors for
	thumb-1 mode.
	* coff.h (JUMP_TABLES_IN_TEXT_SECTION): Thumb-1 jump tables are now
	in the text seciton when PIC or optimizing for size.
	* elf.h (JUMP_TABLES_IN_TEXT_SECTION): Likewise.
	* lib1funcs.asm ([__ARM_EABI__]): Add an attribute describing stack
	preservation properties of code.
	(__gnu_thumb1_case_sqi, __gnu_thumb1_case_uqi): New functions.
	(__gnu_thumb1_case_shi, __gnu_thumb1_case_uhi): New functions.
	(__gnu_thumb1_case_si): New function.
	* t-arm (LIB1ASMSRC): Define here.
	(LIB1ASMFUNCS): Add some common functions.
	* t-arm-elf (LIB1ASMSRC): Delete.
	(LIB1ASMFUNCS): Append to existing set.
	* t-pe (LIB1ASMSRC, LIB1ASMFUNCS): Likewise.
	* t-strongarm-elf (LIB1ASMSRC, LIB1ASMFUNCS): Likewise.
	* t-symbian (LIB1ASMFUNCS): Likewise.
	* t-vxworks (LIB1ASMSRC, LIB1ASMFUNCS): Likewise.
	* t-wince-pe (LIB1ASMSRC, LIB1ASMFUNCS): Likewise.

From-SVN: r148770
parent dfb55fdc
2009-06-21 Richard Earnshaw <rearnsha@arm.com>
* arm.c (thumb1_output_casesi): New function.
* arm.h (CASE_VECTOR_PC_RELATIVE): Thumb-1 code is also relative if
optimizing for size or PIC.
(CASE_VECTOR_SHORTEN_MODE): Handle thumb-1.
* arm.md (UNSPEC_THUMB1_CASESI): New constant.
(casesi): Handle Thumb-1 when optimizing for size or PIC.
(thumb1_casesi_internal_pic): New expand rule.
(thumb1_casesi_dispatch): New pattern.
* aout.h (ASM_OUTPUT_ADDR_DIFF_ELT): Use shortened vectors for
thumb-1 mode.
* coff.h (JUMP_TABLES_IN_TEXT_SECTION): Thumb-1 jump tables are now
in the text seciton when PIC or optimizing for size.
* elf.h (JUMP_TABLES_IN_TEXT_SECTION): Likewise.
* lib1funcs.asm ([__ARM_EABI__]): Add an attribute describing stack
preservation properties of code.
(__gnu_thumb1_case_sqi, __gnu_thumb1_case_uqi): New functions.
(__gnu_thumb1_case_shi, __gnu_thumb1_case_uhi): New functions.
(__gnu_thumb1_case_si): New function.
* t-arm (LIB1ASMSRC): Define here.
(LIB1ASMFUNCS): Add some common functions.
* t-arm-elf (LIB1ASMSRC): Delete.
(LIB1ASMFUNCS): Append to existing set.
* t-pe (LIB1ASMSRC, LIB1ASMFUNCS): Likewise.
* t-strongarm-elf (LIB1ASMSRC, LIB1ASMFUNCS): Likewise.
* t-symbian (LIB1ASMFUNCS): Likewise.
* t-vxworks (LIB1ASMSRC, LIB1ASMFUNCS): Likewise.
* t-wince-pe (LIB1ASMSRC, LIB1ASMFUNCS): Likewise.
2009-06-21 Richard Guenther <rguenther@suse.de>
PR tree-optimization/38729
......
......@@ -243,7 +243,30 @@
if (TARGET_ARM) \
asm_fprintf (STREAM, "\tb\t%LL%d\n", VALUE); \
else if (TARGET_THUMB1) \
asm_fprintf (STREAM, "\t.word\t%LL%d-%LL%d\n", VALUE, REL); \
{ \
if (flag_pic || optimize_size) \
{ \
switch (GET_MODE(body)) \
{ \
case QImode: \
asm_fprintf (STREAM, "\t.byte\t(%LL%d-%LL%d)/2\n", \
VALUE, REL); \
break; \
case HImode: /* TBH */ \
asm_fprintf (STREAM, "\t.2byte\t(%LL%d-%LL%d)/2\n", \
VALUE, REL); \
break; \
case SImode: \
asm_fprintf (STREAM, "\t.word\t%LL%d-%LL%d\n", \
VALUE, REL); \
break; \
default: \
gcc_unreachable(); \
} \
} \
else \
asm_fprintf (STREAM, "\t.word\t%LL%d+1\n", VALUE); \
} \
else /* Thumb-2 */ \
{ \
switch (GET_MODE(body)) \
......
......@@ -183,7 +183,8 @@ extern rtx arm_return_addr (int, rtx);
extern void thumb_reload_out_hi (rtx *);
extern void thumb_reload_in_hi (rtx *);
extern void thumb_set_return_address (rtx, rtx);
extern const char *thumb2_output_casesi(rtx *);
extern const char *thumb1_output_casesi (rtx *);
extern const char *thumb2_output_casesi (rtx *);
#endif
/* Defined in pe.c. */
......
......@@ -19860,6 +19860,32 @@ arm_output_shift(rtx * operands, int set_flags)
return "";
}
/* Output a Thumb-1 casesi dispatch sequence. */
const char *
thumb1_output_casesi (rtx *operands)
{
rtx diff_vec = PATTERN (next_real_insn (operands[0]));
addr_diff_vec_flags flags;
gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
flags = ADDR_DIFF_VEC_FLAGS (diff_vec);
switch (GET_MODE(diff_vec))
{
case QImode:
return (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned ?
"bl\t%___gnu_thumb1_case_uqi" : "bl\t%___gnu_thumb1_case_sqi");
case HImode:
return (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned ?
"bl\t%___gnu_thumb1_case_uhi" : "bl\t%___gnu_thumb1_case_shi");
case SImode:
return "bl\t%___gnu_thumb1_case_si";
default:
gcc_unreachable ();
}
}
/* Output a Thumb-2 casesi instruction. */
const char *
thumb2_output_casesi (rtx *operands)
......
......@@ -2196,12 +2196,24 @@ typedef struct
for the index in the tablejump instruction. */
#define CASE_VECTOR_MODE Pmode
#define CASE_VECTOR_PC_RELATIVE TARGET_THUMB2
#define CASE_VECTOR_SHORTEN_MODE(min, max, body) \
((min < 0 || max >= 0x2000 || !TARGET_THUMB2) ? SImode \
: (max >= 0x200) ? HImode \
: QImode)
#define CASE_VECTOR_PC_RELATIVE (TARGET_THUMB2 \
|| (TARGET_THUMB \
&& (optimize_size || flag_pic)))
#define CASE_VECTOR_SHORTEN_MODE(min, max, body) \
(TARGET_THUMB \
? (min >= 0 && max < 512 \
? (ADDR_DIFF_VEC_FLAGS (body).offset_unsigned = 1, QImode) \
: min >= -256 && max < 256 \
? (ADDR_DIFF_VEC_FLAGS (body).offset_unsigned = 0, QImode) \
: min >= 0 && max < 8192 \
? (ADDR_DIFF_VEC_FLAGS (body).offset_unsigned = 1, HImode) \
: min >= -4096 && max < 4096 \
? (ADDR_DIFF_VEC_FLAGS (body).offset_unsigned = 0, HImode) \
: SImode) \
: ((min < 0 || max >= 0x2000 || !TARGET_THUMB2) ? SImode \
: (max >= 0x200) ? HImode \
: QImode))
/* signed 'char' is most compatible, but RISC OS wants it unsigned.
unsigned is probably best, but may break some code. */
......
......@@ -99,6 +99,7 @@
; correctly for PIC usage.
(UNSPEC_GOTSYM_OFF 24) ; The offset of the start of the the GOT from a
; a given symbolic address.
(UNSPEC_THUMB1_CASESI 25) ; A Thumb1 compressed dispatch-table call.
]
)
......@@ -8901,37 +8902,33 @@
(match_operand:SI 2 "const_int_operand" "") ; total range
(match_operand:SI 3 "" "") ; table label
(match_operand:SI 4 "" "")] ; Out of range label
"TARGET_32BIT"
"TARGET_32BIT || optimize_size || flag_pic"
"
{
rtx reg;
enum insn_code code;
if (operands[1] != const0_rtx)
{
reg = gen_reg_rtx (SImode);
rtx reg = gen_reg_rtx (SImode);
emit_insn (gen_addsi3 (reg, operands[0],
GEN_INT (-INTVAL (operands[1]))));
operands[0] = reg;
}
if (!const_ok_for_arm (INTVAL (operands[2])))
operands[2] = force_reg (SImode, operands[2]);
if (TARGET_ARM)
{
emit_jump_insn (gen_arm_casesi_internal (operands[0], operands[2],
operands[3], operands[4]));
}
code = CODE_FOR_arm_casesi_internal;
else if (TARGET_THUMB)
code = CODE_FOR_thumb1_casesi_internal_pic;
else if (flag_pic)
{
emit_jump_insn (gen_thumb2_casesi_internal_pic (operands[0],
operands[2], operands[3], operands[4]));
}
code = CODE_FOR_thumb2_casesi_internal_pic;
else
{
emit_jump_insn (gen_thumb2_casesi_internal (operands[0], operands[2],
operands[3], operands[4]));
}
code = CODE_FOR_thumb2_casesi_internal;
if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
operands[2] = force_reg (SImode, operands[2]);
emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
operands[3], operands[4]));
DONE;
}"
)
......@@ -8958,6 +8955,37 @@
(set_attr "length" "12")]
)
(define_expand "thumb1_casesi_internal_pic"
[(match_operand:SI 0 "s_register_operand" "")
(match_operand:SI 1 "thumb1_cmp_operand" "")
(match_operand 2 "" "")
(match_operand 3 "" "")]
"TARGET_THUMB"
{
rtx reg0;
rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
operands[3]));
reg0 = gen_rtx_REG (SImode, 0);
emit_move_insn (reg0, operands[0]);
emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
DONE;
}
)
(define_insn "thumb1_casesi_dispatch"
[(parallel [(set (pc) (unspec [(reg:SI 0)
(label_ref (match_operand 0 "" ""))
;; (label_ref (match_operand 1 "" ""))
]
UNSPEC_THUMB1_CASESI))
(clobber (reg:SI IP_REGNUM))
(clobber (reg:SI LR_REGNUM))])]
"TARGET_THUMB"
"* return thumb1_output_casesi(operands);"
[(set_attr "length" "4")]
)
(define_expand "indirect_jump"
[(set (pc)
(match_operand:SI 0 "s_register_operand" ""))]
......
......@@ -60,8 +60,9 @@
Otherwise, the readonly data section is used. */
/* We put ARM and Thumb-2 jump tables in the text section, because it makes
the code more efficient, but for Thumb-1 it's better to put them out of
band. */
#define JUMP_TABLES_IN_TEXT_SECTION (TARGET_32BIT)
band unless we are generating compressed tables. */
#define JUMP_TABLES_IN_TEXT_SECTION \
(TARGET_32BIT || (TARGET_THUMB && (optimize_size || flag_pic)))
#undef READONLY_DATA_SECTION_ASM_OP
#define READONLY_DATA_SECTION_ASM_OP "\t.section .rdata"
......
......@@ -100,8 +100,9 @@
Otherwise, the readonly data section is used. */
/* We put ARM and Thumb-2 jump tables in the text section, because it makes
the code more efficient, but for Thumb-1 it's better to put them out of
band. */
#define JUMP_TABLES_IN_TEXT_SECTION (TARGET_32BIT)
band unless we are generating compressed tables. */
#define JUMP_TABLES_IN_TEXT_SECTION \
(TARGET_32BIT || (TARGET_THUMB && (optimize_size || flag_pic)))
#ifndef LINK_SPEC
#define LINK_SPEC "%{mbig-endian:-EB} %{mlittle-endian:-EL} -X"
......
......@@ -27,8 +27,17 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#if defined(__ELF__) && defined(__linux__)
.section .note.GNU-stack,"",%progbits
.previous
#endif
#endif /* __ELF__ and __linux__ */
#ifdef __ARM_EABI__
/* Some attributes that are common to all routines in this file. */
/* Tag_ABI_align8_needed: This code does not require 8-byte
alignment from the caller. */
/* .eabi_attribute 24, 0 -- default setting. */
/* Tag_ABI_align8_preserved: This code preserves 8-byte
alignment in any callee. */
.eabi_attribute 25, 1
#endif /* __ARM_EABI__ */
/* ------------------------------------------------------------------------ */
/* We need to know what prefix to add to function names. */
......@@ -1533,6 +1542,111 @@ LSYM(Lchange_\register):
#endif /* L_interwork_call_via_rX */
#endif /* !__thumb2__ */
/* Functions to support compact pic switch tables in thumb1 state.
All these routines take an index into the table in r0. The
table is at LR & ~1 (but this must be rounded up in the case
of 32-bit entires). They are only permitted to clobber r12
and r14 and r0 must be preserved on exit. */
#ifdef L_thumb1_case_sqi
.text
.align 0
.force_thumb
.syntax unified
THUMB_FUNC_START __gnu_thumb1_case_sqi
push {r1}
mov r1, lr
lsrs r1, r1, #1
lsls r1, r1, #1
ldrsb r1, [r1, r0]
lsls r1, r1, #1
add lr, lr, r1
pop {r1}
bx lr
SIZE (__gnu_thumb1_case_sqi)
#endif
#ifdef L_thumb1_case_uqi
.text
.align 0
.force_thumb
.syntax unified
THUMB_FUNC_START __gnu_thumb1_case_uqi
push {r1}
mov r1, lr
lsrs r1, r1, #1
lsls r1, r1, #1
ldrb r1, [r1, r0]
lsls r1, r1, #1
add lr, lr, r1
pop {r1}
bx lr
SIZE (__gnu_thumb1_case_uqi)
#endif
#ifdef L_thumb1_case_shi
.text
.align 0
.force_thumb
.syntax unified
THUMB_FUNC_START __gnu_thumb1_case_shi
push {r0, r1}
mov r1, lr
lsrs r1, r1, #1
lsls r0, r0, #1
lsls r1, r1, #1
ldrsh r1, [r1, r0]
lsls r1, r1, #1
add lr, lr, r1
pop {r0, r1}
bx lr
SIZE (__gnu_thumb1_case_shi)
#endif
#ifdef L_thumb1_case_uhi
.text
.align 0
.force_thumb
.syntax unified
THUMB_FUNC_START __gnu_thumb1_case_uhi
push {r0, r1}
mov r1, lr
lsrs r1, r1, #1
lsls r0, r0, #1
lsls r1, r1, #1
ldrh r1, [r1, r0]
lsls r1, r1, #1
add lr, lr, r1
pop {r0, r1}
bx lr
SIZE (__gnu_thumb1_case_uhi)
#endif
#ifdef L_thumb1_case_si
.text
.align 0
.force_thumb
.syntax unified
THUMB_FUNC_START __gnu_thumb1_case_si
push {r0, r1}
mov r1, lr
adds.n r1, r1, #2 /* Align to word. */
lsrs r1, r1, #2
lsls r0, r0, #2
lsls r1, r1, #2
ldr r0, [r1, r0]
adds r0, r0, r1
mov lr, r0
pop {r0, r1}
mov pc, lr /* We know we were called from thumb code. */
SIZE (__gnu_thumb1_case_si)
#endif
#endif /* Arch supports thumb. */
#ifndef __symbian__
......
......@@ -33,6 +33,9 @@ MD_INCLUDES= $(srcdir)/config/arm/arm-tune.md \
$(srcdir)/config/arm/neon.md \
$(srcdir)/config/arm/thumb2.md
LIB1ASMSRC = arm/lib1funcs.asm
LIB1ASMFUNCS = _thumb1_case_sqi _thumb1_case_uqi _thumb1_case_shi \
_thumb1_case_uhi _thumb1_case_si
s-config s-conditions s-flags s-codes s-constants s-emit s-recog s-preds \
s-opinit s-extract s-peep s-attr s-attrtab s-output: $(MD_INCLUDES)
......
......@@ -17,12 +17,11 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
LIB1ASMSRC = arm/lib1funcs.asm
# For most CPUs we have an assembly soft-float implementations.
# However this is not true for ARMv6M. Here we want to use the soft-fp C
# implementation. The soft-fp code is only build for ARMv6M. This pulls
# in the asm implementation for other CPUs.
LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func \
LIB1ASMFUNCS += _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func \
_call_via_rX _interwork_call_via_rX \
_lshrdi3 _ashrdi3 _ashldi3 \
_arm_negdf2 _arm_addsubdf3 _arm_muldivdf3 _arm_cmpdf2 _arm_unorddf2 \
......@@ -30,7 +29,7 @@ LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func \
_arm_truncdfsf2 _arm_negsf2 _arm_addsubsf3 _arm_muldivsf3 \
_arm_cmpsf2 _arm_unordsf2 _arm_fixsfsi _arm_fixunssfsi \
_arm_floatdidf _arm_floatdisf _arm_floatundidf _arm_floatundisf \
_clzsi2 _clzdi2
_clzsi2 _clzdi2
MULTILIB_OPTIONS = marm/mthumb
MULTILIB_DIRNAMES = arm thumb
......
......@@ -17,8 +17,7 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
LIB1ASMSRC = arm/lib1funcs.asm
LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _call_via_rX _interwork_call_via_rX _clzsi2 _clzdi2
LIB1ASMFUNCS += _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _call_via_rX _interwork_call_via_rX _clzsi2 _clzdi2
# We want fine grained libraries, so use the new code to build the
# floating point emulation libraries.
......
......@@ -16,8 +16,7 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
LIB1ASMSRC = arm/lib1funcs.asm
LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func _clzsi2 _clzdi2
LIB1ASMFUNCS += _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func _clzsi2 _clzdi2
# We want fine grained libraries, so use the new code to build the
# floating point emulation libraries.
......
......@@ -16,7 +16,7 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
LIB1ASMFUNCS = _bb_init_func _call_via_rX _interwork_call_via_rX _clzsi2 _clzdi2
LIB1ASMFUNCS += _bb_init_func _call_via_rX _interwork_call_via_rX _clzsi2 _clzdi2
# These functions have __aeabi equivalents and will never be called by GCC.
# By putting them in LIB1ASMFUNCS, we avoid the standard libgcc2.c code being
......
......@@ -16,8 +16,7 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
LIB1ASMSRC = arm/lib1funcs.asm
LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func _call_via_rX _interwork_call_via_rX _clzsi2 _clzdi2
LIB1ASMFUNCS += _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func _call_via_rX _interwork_call_via_rX _clzsi2 _clzdi2
# We want fine grained libraries, so use the new code to build the
# floating point emulation libraries.
......
......@@ -16,8 +16,7 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
LIB1ASMSRC = arm/lib1funcs.asm
LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _call_via_rX _interwork_call_via_rX _clzsi2 _clzdi2
LIB1ASMFUNCS += _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _call_via_rX _interwork_call_via_rX _clzsi2 _clzdi2
# We want fine grained libraries, so use the new code to build the
# floating point emulation libraries.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment