#define CPP_SPEC "\
%(cpp_cpu_arch) %(cpp_apcs_pc) %(cpp_float) \
-%(cpp_endian) %(subtarget_cpp_spec) %(cpp_isa)"
+%(cpp_endian) %(subtarget_cpp_spec) %(cpp_isa) %(cpp_interwork)"
#define CPP_ISA_SPEC "%{mthumb:-Dthumb -D__thumb__} %{!mthumb:-Darm -D__arm__}"
/* Default is little endian. */
#define CPP_ENDIAN_DEFAULT_SPEC "-D__ARMEL__ %{mthumb:-D__THUMBEL__}"
+/* Add a define for interworking. Needed when building libgcc.a.
+ This must define __THUMB_INTERWORK__ to the pre-processor if
+ interworking is enabled by default. */
+#ifndef CPP_INTERWORK_DEFAULT_SPEC
+#define CPP_INTERWORK_DEFAULT_SPEC ""
+#endif
+
+#define CPP_INTERWORK_SPEC " \
+%{mthumb-interwork: \
+ %{mno-thumb-interwork: %eIncompatible interworking options} \
+ -D__THUMB_INTERWORK__} \
+%{!mthumb-interwork:%{!mno-thumb-interwork:%(cpp_interwork_default)}} \
+"
+
#define CC1_SPEC ""
/* This macro defines names of additional specifications to put in the specs
{ "cpp_endian", CPP_ENDIAN_SPEC }, \
{ "cpp_endian_default", CPP_ENDIAN_DEFAULT_SPEC }, \
{ "cpp_isa", CPP_ISA_SPEC }, \
+ { "cpp_interwork", CPP_INTERWORK_SPEC }, \
+ { "cpp_interwork_default", CPP_INTERWORK_DEFAULT_SPEC }, \
{ "subtarget_cpp_spec", SUBTARGET_CPP_SPEC }, \
SUBTARGET_EXTRA_SPECS
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-
-#ifdef __APCS_26__
-#define RET movs pc, lr
-#define RETc(x) mov##x##s pc, lr
-#define RETCOND ^
-#else
-#define RET mov pc, lr
-#define RETc(x) mov##x pc, lr
-#define RETCOND
-#endif
-
+/* ------------------------------------------------------------------------ */
#ifndef __USER_LABEL_PREFIX__
#error __USER_LABEL_PREFIX__ not defined
#endif
#ifdef __ELF__
#ifdef __thumb__
-#define __PLT__ /* Not supported in thumb assembler (for now). */
+#define __PLT__ /* Not supported in Thumb assembler (for now). */
#else
#define __PLT__ (PLT)
#endif
#define SIZE(x)
#endif
+/* Function end macros. Variants for 26 bit APCS and interworking. */
+#ifdef __APCS_26__
+# define RET movs pc, lr
+# define RETc(x) mov##x##s pc, lr
+# define RETCOND ^
+.macro ARM_LDIV0
+Ldiv0:
+ str lr, [sp, #-4]!
+ bl SYM (__div0) __PLT__
+ mov r0, #0 @ About as wrong as it could be.
+ ldmia sp!, {pc}^
+.endm
+#else
+# ifdef __THUMB_INTERWORK__
+# define RET bx lr
+# define RETc(x) bx##x lr
+.macro THUMB_LDIV0
+ push { lr }
+ bl SYM (__div0)
+ mov r0, #0 @ About as wrong as it could be.
+ pop { r1 }
+ bx r1
+.endm
+.macro ARM_LDIV0
+ str lr, [sp, #-4]!
+ bl SYM (__div0) __PLT__
+ mov r0, #0 @ About as wrong as it could be.
+ ldr lr, [sp], #4
+ bx lr
+.endm
+# else
+# define RET mov pc, lr
+# define RETc(x) mov##x pc, lr
+.macro THUMB_LDIV0
+ push { lr }
+ bl SYM (__div0)
+ mov r0, #0 @ About as wrong as it could be.
+ pop { pc }
+.endm
+.macro ARM_LDIV0
+ str lr, [sp, #-4]!
+ bl SYM (__div0) __PLT__
+ mov r0, #0 @ About as wrong as it could be.
+ ldmia sp!, {pc}
+.endm
+# endif
+# define RETCOND
+#endif
+
#ifdef __thumb__
#define THUMB_FUNC .thumb_func
#define THUMB_CODE .force_thumb
SYM (__\name):
.endm
+.macro FUNC_END name
+Ldiv0:
+#ifdef __thumb__
+ THUMB_LDIV0
+#else
+ ARM_LDIV0
+#endif
+ SIZE (__\name)
+.endm
+
+.macro THUMB_FUNC_START name
+ .globl SYM (\name)
+ TYPE (\name)
+ .thumb_func
+SYM (\name):
+.endm
+
/* Used for Thumb code. */
work .req r4 @ XXXX is this safe ?
+/* ------------------------------------------------------------------------ */
#ifdef L_udivsi3
dividend .req r0
lr .req r14
pc .req r15
- FUNC_START udivsi3
+ FUNC_START udivsi3
#ifdef __thumb__
mov r0, result
pop { work }
RET
-
-Ldiv0:
- push { lr }
- bl SYM (__div0) __PLT__
- mov r0, #0 @ about as wrong as it could be
- pop { pc }
-
-#else /* arm version */
+
+#else /* ARM version. */
cmp divisor, #0
beq Ldiv0
mov r0, result
RET
-Ldiv0:
- str lr, [sp, #-4]!
- bl SYM (__div0) __PLT__
- mov r0, #0 @ about as wrong as it could be
- ldmia sp!, {pc}RETCOND
+#endif /* ARM version */
-#endif /* arm version */
-
- SIZE (__udivsi3)
+ FUNC_END udivsi3
#endif /* L_udivsi3 */
-
+/* ------------------------------------------------------------------------ */
#ifdef L_umodsi3
dividend .req r0
lr .req r14
pc .req r15
- FUNC_START umodsi3
+ FUNC_START umodsi3
#ifdef __thumb__
add dividend, dividend, work
Over10:
pop { work }
- RET
-Ldiv0:
- push { lr }
- bl SYM (__div0) __PLT__
- mov r0, #0 @ about as wrong as it could be
- pop { pc }
-
-#else /* arm version */
+
+#else /* ARM version. */
cmp divisor, #0
beq Ldiv0
addne dividend, dividend, divisor, lsr #1
RET
-Ldiv0:
- str lr, [sp, #-4]!
- bl SYM (__div0) __PLT__
- mov r0, #0 @ about as wrong as it could be
- ldmia sp!, {pc}RETCOND
-
#endif /* arm version */
- SIZE (__umodsi3)
+ FUNC_END umodsi3
#endif /* L_umodsi3 */
-
+/* ------------------------------------------------------------------------ */
#ifdef L_divsi3
dividend .req r0
lr .req r14
pc .req r15
- FUNC_START divsi3
+ FUNC_START divsi3
#ifdef __thumb__
cmp divisor, #0
pop { work }
RET
-Ldiv0:
- push { lr }
- bl SYM (__div0) __PLT__
- mov r0, #0 @ about as wrong as it could be
- pop { pc }
-
-#else /* arm version */
+#else /* ARM version. */
eor ip, dividend, divisor @ Save the sign of the result.
mov curbit, #1
rsbmi r0, r0, #0
RET
-Ldiv0:
- str lr, [sp, #-4]!
- bl SYM (__div0) __PLT__
- mov r0, #0 @ about as wrong as it could be
- ldmia sp!, {pc}RETCOND
-
-#endif /* arm version */
+#endif /* ARM version */
- SIZE (__divsi3)
+ FUNC_END divsi3
#endif /* L_divsi3 */
-
+/* ------------------------------------------------------------------------ */
#ifdef L_modsi3
dividend .req r0
lr .req r14
pc .req r15
- FUNC_START modsi3
+ FUNC_START modsi3
#ifdef __thumb__
Over10:
pop { work }
RET
-
-Ldiv0:
- push { lr }
- bl SYM (__div0) __PLT__
- mov r0, #0 @ about as wrong as it could be
- pop { pc }
-
-#else /* arm version */
+
+#else /* ARM version. */
mov curbit, #1
cmp divisor, #0
cmp ip, #0
rsbmi dividend, dividend, #0
RET
-
-Ldiv0:
- str lr, [sp, #-4]!
- bl SYM (__div0) __PLT__
- mov r0, #0 @ about as wrong as it could be
- ldmia sp!, {pc}RETCOND
-
-#endif /* arm version */
- SIZE (__modsi3)
+#endif /* ARM version */
+
+ FUNC_END modsi3
#endif /* L_modsi3 */
-
+/* ------------------------------------------------------------------------ */
#ifdef L_dvmd_tls
- FUNC_START div0
+ FUNC_START div0
RET
- SIZE (__div0)
+ SIZE (__div0)
#endif /* L_divmodsi_tools */
-
+/* ------------------------------------------------------------------------ */
#ifdef L_dvmd_lnx
@ GNU/Linux division-by zero handler. Used in place of L_dvmd_tls
#define SIGFPE 8 @ cant use <asm/signal.h> as it
@ contains too much C rubbish
- FUNC_START div0
+ FUNC_START div0
stmfd sp!, {r1, lr}
swi __NR_getpid
ldmhsfd sp!, {r1, pc}RETCOND @ not much we can do
mov r1, #SIGFPE
swi __NR_kill
+#ifdef __THUMB_INTERWORK__
+ ldmfd sp!, {r1, lr}
+ bx lr
+#else
ldmfd sp!, {r1, pc}RETCOND
-
- SIZE (__div0)
+#endif
+
+ SIZE (__div0)
#endif /* L_dvmd_lnx */
-
+/* ------------------------------------------------------------------------ */
/* These next two sections are here despite the fact that they contain Thumb
assembler because their presence allows interworked code to be linked even
when the GCC library is this one. */
.text
.align 0
.force_thumb
+
.macro call_via register
- .globl SYM (_call_via_\register)
- TYPE (_call_via_\register)
- .thumb_func
-SYM (_call_via_\register):
+ THUMB_FUNC_START _call_via_\register
+
bx \register
nop
call_via lr
#endif /* L_call_via_rX */
-
+/* ------------------------------------------------------------------------ */
/* Do not build the interworking functions when the target cpu
is the arm v3 architecture. (This is one of the multilib
options). */
.macro interwork register
.code 16
- .globl SYM (_interwork_call_via_\register)
- TYPE (_interwork_call_via_\register)
- .thumb_func
-SYM (_interwork_call_via_\register):
+
+ THUMB_FUNC_START _interwork_call_via_\register
+
bx pc
nop
interwork ip
interwork sp
- /* The lr case has to be handled a little differently...*/
+ /* The LR case has to be handled a little differently... */
.code 16
- .globl SYM (_interwork_call_via_lr)
- TYPE (_interwork_call_via_lr)
- .thumb_func
-SYM (_interwork_call_via_lr):
+
+ THUMB_FUNC_START _interwork_call_via_lr
+
bx pc
nop
SIZE (_interwork_call_via_lr)
#endif /* L_interwork_call_via_rX */
+