crti.asm: add pic support.

* config/score/crti.asm: add pic support.
        * config/score/crtn.asm: add pic support.
        * config/score/score.h: remove builtin_define("__pic__").
        * config/score/score.c: add TARGET_RTX_COST macro.
        * config/score/score.md: PIC support for call/sibcall pattern.
        * config/score/mul-div.S: add pic support.
        * config/score/t-score-elf: update MULTILIB_OPTIONS.
        * ChangeLog: add shengguo as another score maintainer.
        * config.sub: add score support in it.

From-SVN: r117771
This commit is contained in:
Tan Shengguo 2006-10-16 02:13:06 +00:00 committed by Chen Liqin
parent c05b443868
commit cf723ae82f
9 changed files with 642 additions and 178 deletions

View File

@ -1,3 +1,7 @@
2006-10-16 Tan Shengguo <shengguo@sunnorth.com.cn>
* MAINTAINERS: Add Tan Shengguo as score port maintainer.
2006-10-10 Brooks Moses <bmoses@stanford.edu>
* Makefile.def: Added pdf target handling.

4
config.sub vendored
View File

@ -909,6 +909,10 @@ case $basic_machine in
sb1el)
basic_machine=mipsisa64sb1el-unknown
;;
score | score-*)
basic_machine=score-sunplus
os=-elf
;;
sei)
basic_machine=mips-sei
os=-seiux

View File

@ -35,6 +35,7 @@
# This file makes a stack frame for the contents of the .init and
# .fini sections.
#ifndef __pic__
.section .init, "ax", @progbits
.weak _start
.ent _start
@ -81,5 +82,62 @@ _init:
_fini:
addi r0, -32
sw r3, [r0, 20]
#else
.section .init, "ax", @progbits
.set pic
.weak _start
.ent _start
.frame r0, 0, r3, 0
.mask 0x00000000,0
_start:
la r28, _gp
la r8, __bss_start
la r9, __bss_end__
sub! r9, r8
srli! r9, 2
addi r9, -1
mtsr r9, sr0
li r9, 0
1:
sw r9, [r8]+, 4
bcnz 1b
la r0, _stack
# jl _init
# la r4, _end
# jl _init_argv
ldiu! r4, 0
ldiu! r5, 0
# jl main
la r29, main
brl r29
# jl exit
la r29, exit
brl r29
.end _start
.weak _init_argv
.ent
.frame r0, 0, r3, 0
.mask 0x00000000, 0
_init_argv:
ldiu! r4, 0
ldiu! r5, 0
j main
.end _init_argv
.globl _init
.type _init, %function
_init:
addi r0, -32
sw r3, [r0, 20]
.section .fini, "ax", @progbits
.globl _fini
.type _fini, %function
_fini:
addi r0, -32
sw r3, [r0, 20]
#endif

View File

@ -35,6 +35,7 @@
# This file makes sure that the .init and .fini sections do in
# fact return.
#ifndef __pic__
.section .init, "ax", @progbits
lw r3, [r0, 20]
addi r0, 32
@ -44,4 +45,18 @@
lw r3, [r0, 20]
addi r0, 32
br r3
#else
.set pic
.section .init, "ax", @progbits
lw r3, [r0, 20]
addi r0, 32
br r3
.set pic
.section .fini, "ax", @progbits
lw r3, [r0, 20]
addi r0, 32
br r3
#endif

View File

@ -29,28 +29,9 @@
#define t1 r9
#define t2 r10
#define t3 r11
#define t4 r22
#if defined(__scorebe__)
#define LIBGCC1_BIG_ENDIAN
#define out_H v0
#define out_L v1
#define in0_H a0
#define in0_L a1
#define in1_H a2
#define in1_L a3
#elif defined(__scorele__)
#define out_H v1
#define out_L v0
#define in0_H a1
#define in0_L a0
#define in1_H a3
#define in1_L a2
#else
#err "must specify S+core endian!"
#endif
#ifndef __pic__
#if !defined(L_mulsi3) && !defined(L_divsi3)
.text
.global _flush_cache
@ -110,12 +91,12 @@ __umulsi3:
__mulsi3:
li t1, 0
__mulsi3_loop:
andri.c t0, a1, 1 /* t0 = multiplier[0] */
srli a1, a1, 1 /* a1 /= 2 */
beq __mulsi3_loop2 /* skip if (t0 == 0) */
add t1, t1, a0 /* add multiplicand */
andri.c t0, a1, 1 # t0 = multiplier[0]
srli a1, a1, 1 # a1 /= 2
beq __mulsi3_loop2 # skip if (t0 == 0)
add t1, t1, a0 # add multiplicand
__mulsi3_loop2:
slli a0, a0, 1 /* multiplicand mul 2 */
slli a0, a0, 1 # multiplicand mul 2
cmpi.c a1, 0
bne __mulsi3_loop
mv r4, t1
@ -123,7 +104,6 @@ __mulsi3_loop2:
.end __mulsi3
#endif /* L_mulsi3 */
/* FUNCTION
UINT32 (v0) = __udivsi3 (UINT32 (a0), UINT32 (a1));
INT32 (v0) = __divsi3 (INT32 (a0), INT32 (a1));
@ -193,7 +173,7 @@ __orgsi3_a0p:
cmpi.c a1, 0
bge __udivsi3
neg a1, a1
b __udivsi3 /* goto udivsi3 */
b __udivsi3 # goto udivsi3
.end __orgsi3
/* signed division */
@ -221,4 +201,206 @@ __modsi3:
.end __modsi3
#endif /* L_divsi3 */
#else /* -fPIC */
#if !defined(L_mulsi3) && !defined(L_divsi3)
.set pic
.text
.global _flush_cache
_flush_cache:
addi r0, -8 # pic used
.cpload r29 # pic used
srli r9, r5, 4
mv r8, r4
mtsr r9, sr0
1:
cache 0xe, [r8, 0] # write back invalid dcache
addi r8, 16
bcnz 1b
mfcr r8, cr4
bittst! r8, 0x3 # if LDM is enable, write back LDM
beq! 6f
ldi r10, 0
cache 0xc, [r10, 0]
6:
bittst! r8, 0x2 # if LIM is enable, refill it
beq! 7f
cache 0x4, [r10, 0]
7:
#nop!
#nop!
#nop!
#nop!
#nop!
mv r8, r4
mtsr r9, sr0
2:
cache 0x2, [r8, 0] # invalid unlock icache
#nop!
#nop!
#nop!
#nop!
#nop!
addi r8, 16
bcnz 2b
.cprestore 12 # pic used
addi r0, 8 # pic used
br r3
#endif
/* FUNCTION
(U) INT32 v0 = __mulsi3 ((U) INT32 a0, (U) INT32 a1);
REGISTERS:
use t0
modify a0
a1 -> become 0
NOTE:
this seems to give better performance to just rotate and add. */
#ifdef L_mulsi3
.set pic
.text
.global __umulsi3
.global __mulsi3
/* signed multiplication (32x32) */
.ent __mulsi3
__umulsi3:
__mulsi3:
addi r0, -8 # pic used
.cpload r29 # pic used
li t1, 0
__mulsi3_loop:
andri.c t0, a1, 1 # t0 = multiplier[0]
srli a1, a1, 1 # a1 /= 2
beq __mulsi3_loop2 # skip if (t0 == 0)
add t1, t1, a0 # add multiplicand
__mulsi3_loop2:
slli a0, a0, 1 # multiplicand mul 2
cmpi.c a1, 0
bne __mulsi3_loop
mv r4, t1
.cprestore 12 # pic used
addi r0, 8 # pic used
br ra
.end __mulsi3
#endif /* L_mulsi3 */
/* FUNCTION
UINT32 (v0) = __udivsi3 (UINT32 (a0), UINT32 (a1));
INT32 (v0) = __divsi3 (INT32 (a0), INT32 (a1));
UINT32 (v0) = __umodsi3 (UINT32 (a0), UINT32 (a1));
INT32 (v0) = __modsi3 (INT32 (a0), INT32 (a1));
DESCRIPTION
performs 32-bit division/modulo.
REGISTERS
used t0 bit-index
t1
modify a0 becomes remainer */
#ifdef L_divsi3
.set pic
.text
.global __udivsi3
.global __umodsi3
.global __divsi3
.global __modsi3
/* unsigned division */
.ent __udivsi3
__udivsi3:
addi r0, -8 # pic used
.cpload r29 # pic used
li t4, 0
cmpi.c a1, 0
beq __uds_exit
li t0, 1
blt __uds_ok
__uds_normalize:
cmp.c a0, a1
bcc __uds_ok
slli a1, a1, 1
slli t0, t0, 1
cmpi.c a1, 0
bge __uds_normalize
__uds_ok:
__uds_loop2:
cmp.c a0, a1
bcc __uds_loop3
sub a0, a0, a1
or t4, t4, t0
__uds_loop3:
srli t0, t0, 1
srli a1, a1, 1
cmpi.c t0, 0
bne __uds_loop2
__uds_exit:
mv a1, a0
mv r4, t4
.cprestore 12 # pic used
addi r0, 8 # pic used
br ra
.end __udivsi3
/* unsigned modulus */
.ent __umodsi3
__umodsi3:
addi r0, -8 # pic used
.cpload r29 # pic used
li t1, 0
mv t3, ra
# jl __udivsi3
la r29, __udivsi3
brl r29
mv r4, a1
.cprestore 12 # pic used
addi r0, 8 # pic used
br t3
.end __umodsi3
/* abs and div */
.ent __orgsi3
__orgsi3:
cmpi.c a0, 0
bge __orgsi3_a0p
neg a0, a0
__orgsi3_a0p:
cmpi.c a1, 0
bge __udivsi3
neg a1, a1
b __udivsi3 # goto udivsi3
.end __orgsi3
/* signed division */
.ent __divsi3
__divsi3:
addi r0, -8 # pic used
.cpload r29 # pic used
mv t3, ra
xor t2, a0, a1
# jl __orgsi3
la r29, __orgsi3
brl r29
__divsi3_adjust:
cmpi.c t2, 0
bge __divsi3_exit
neg r4, r4
__divsi3_exit:
.cprestore 12 # pic used
addi r0, 8 # pic used
br t3
.end __divsi3
/* signed modulus */
.ent __modsi3
__modsi3:
addi r0, -8 # pic used
.cpload r29 # pic used
mv t3, ra
mv t2, a0
# jl __orgsi3
la r29, __orgsi3
brl r29
mv r4, a1
b __divsi3_adjust
.end __modsi3
#endif /*L_divsi3 */
#endif

View File

@ -60,9 +60,14 @@
#define CE_REG_CLASS_P(C) \
((C) == HI_REG || (C) == LO_REG || (C) == CE_REGS)
static int score_arg_partial_bytes (const CUMULATIVE_ARGS *cum,
enum machine_mode mode,
tree type, int named);
static int score_arg_partial_bytes (const CUMULATIVE_ARGS *,
enum machine_mode, tree, int);
static int score_symbol_insns (enum score_symbol_type);
static int score_address_insns (rtx, enum machine_mode);
static bool score_rtx_costs (rtx, int, int, int *);
#undef TARGET_ASM_FILE_START
#define TARGET_ASM_FILE_START th_asm_file_start
@ -118,6 +123,9 @@ static int score_arg_partial_bytes (const CUMULATIVE_ARGS *cum,
#undef TARGET_RETURN_IN_MEMORY
#define TARGET_RETURN_IN_MEMORY score_return_in_memory
#undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS score_rtx_costs
/* Implement TARGET_RETURN_IN_MEMORY. In S+core,
small structures are returned in a register.
Objects with varying size must still be returned in memory. */
@ -880,6 +888,160 @@ score_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
return 12;
}
/* Return the number of instructions needed to load a symbol of the
given type into a register. */
static int
score_symbol_insns (enum score_symbol_type type)
{
switch (type)
{
case SYMBOL_GENERAL:
return 2;
case SYMBOL_SMALL_DATA:
return 1;
}
gcc_unreachable ();
}
/* Return the number of instructions needed to load or store a value
of mode MODE at X. Return 0 if X isn't valid for MODE. */
static int
score_address_insns (rtx x, enum machine_mode mode)
{
struct score_address_info addr;
int factor;
if (mode == BLKmode)
/* BLKmode is used for single unaligned loads and stores. */
factor = 1;
else
/* Each word of a multi-word value will be accessed individually. */
factor = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
if (mda_classify_address (&addr, mode, x, false))
switch (addr.type)
{
case ADD_REG:
case ADD_CONST_INT:
return factor;
case ADD_SYMBOLIC:
return factor * score_symbol_insns (addr.symbol_type);
}
return 0;
}
/* Implement TARGET_RTX_COSTS macro. */
static bool
score_rtx_costs (rtx x, int code, int outer_code, int *total)
{
enum machine_mode mode = GET_MODE (x);
switch (code)
{
case CONST_INT:
/* These can be used anywhere. */
*total = 0;
return true;
/* Otherwise fall through to the handling below because
we'll need to construct the constant. */
case CONST:
case SYMBOL_REF:
case LABEL_REF:
case CONST_DOUBLE:
*total = COSTS_N_INSNS (1);
return true;
case MEM:
{
/* If the address is legitimate, return the number of
instructions it needs, otherwise use the default handling. */
int n = score_address_insns (XEXP (x, 0), GET_MODE (x));
if (n > 0)
{
*total = COSTS_N_INSNS (n + 1);
return true;
}
return false;
}
case FFS:
*total = COSTS_N_INSNS (6);
return true;
case NOT:
*total = COSTS_N_INSNS (1);
return true;
case AND:
case IOR:
case XOR:
if (mode == DImode)
{
*total = COSTS_N_INSNS (2);
return true;
}
return false;
case ASHIFT:
case ASHIFTRT:
case LSHIFTRT:
if (mode == DImode)
{
*total = COSTS_N_INSNS ((GET_CODE (XEXP (x, 1)) == CONST_INT)
? 4 : 12);
return true;
}
return false;
case ABS:
*total = COSTS_N_INSNS (4);
return true;
case PLUS:
case MINUS:
if (mode == DImode)
{
*total = COSTS_N_INSNS (4);
return true;
}
return false;
case NEG:
if (mode == DImode)
{
*total = COSTS_N_INSNS (4);
return true;
}
return false;
case MULT:
*total = COSTS_N_INSNS (12);
return true;
case DIV:
case MOD:
case UDIV:
case UMOD:
*total = COSTS_N_INSNS (33);
return true;
case SIGN_EXTEND:
*total = COSTS_N_INSNS (2);
return true;
case ZERO_EXTEND:
*total = COSTS_N_INSNS (1);
return true;
default:
return false;
}
}
/* Implement ASM_OUTPUT_EXTERNAL macro. */
int
score_output_external (FILE *file ATTRIBUTE_UNUSED,

View File

@ -54,9 +54,10 @@ extern GTY(()) rtx cmp_op1;
builtin_define ("__scorebe__"); \
if (TARGET_SCORE5U) \
builtin_define ("__score5u__"); \
else \
builtin_define ("__score7__"); \
} while (0)
#define TARGET_DEFAULT MASK_SCORE7
#define TARGET_VERSION \

View File

@ -1076,10 +1076,23 @@
[(call (mem:SI (match_operand:SI 0 "call_insn_operand" "t,Z"))
(match_operand 1 "" ""))
(clobber (reg:SI RT_REGNUM))]
"SIBLING_CALL_P (insn) && !flag_pic"
"@
br%S0 %0
j %0"
"SIBLING_CALL_P (insn)"
{
if (!flag_pic)
switch (which_alternative)
{
case 0: return \"br%S0 %0\";
case 1: return \"j %0\";
default: gcc_unreachable ();
}
else
switch (which_alternative)
{
case 0: return \"mv r29, %0\;.cpadd r29\;br r29\";
case 1: return \"la r29, %0\;br r29\";
default: gcc_unreachable ();
}
}
[(set_attr "type" "call")])
(define_expand "sibcall_value"
@ -1097,10 +1110,23 @@
(call (mem:SI (match_operand:SI 1 "call_insn_operand" "t,Z"))
(match_operand 2 "" "")))
(clobber (reg:SI RT_REGNUM))]
"SIBLING_CALL_P(insn) && !flag_pic"
"@
br%S1 %1
j %1"
"SIBLING_CALL_P (insn)"
{
if (!flag_pic)
switch (which_alternative)
{
case 0: return \"br%S1 %1\";
case 1: return \"j %1\";
default: gcc_unreachable ();
}
else
switch (which_alternative)
{
case 0: return \"mv r29, %1\;.cpadd r29\;br r29\";
case 1: return \"la r29, %1\;br r29\";
default: gcc_unreachable ();
}
}
[(set_attr "type" "call")])
(define_expand "call"
@ -1126,7 +1152,12 @@
default: gcc_unreachable ();
}
else
return \"la r29, %0\;brl r29\";
switch (which_alternative)
{
case 0: return \"mv r29, %0\;.cpadd r29\;brl r29\";
case 1: return \"la r29, %0\;brl r29\";
default: gcc_unreachable ();
}
}
[(set_attr "type" "call")])
@ -1155,7 +1186,12 @@
default: gcc_unreachable ();
}
else
return \"la r29, %1\;brl r29\";
switch (which_alternative)
{
case 0: return \"mv r29, %1\;.cpadd r29\;brl r29\";
case 1: return \"la r29, %1\;brl r29\";
default: gcc_unreachable ();
}
}
[(set_attr "type" "call")])
@ -1198,7 +1234,7 @@
""
"*
if (flag_pic)
return \"mv! r29, %0\;.cpadd r29\;br%S0 r29\";
return \"mv r29, %0\;.cpadd r29\;br r29\";
else
return \"br%S0 %0\";
"

View File

@ -35,7 +35,9 @@ dp-bit.c: $(srcdir)/config/fp-bit.c
# without the $gp register.
TARGET_LIBGCC2_CFLAGS = -G 0
MULTILIB_OPTIONS = mel mSCORE7
MULTILIB_OPTIONS = fPIC mel mSCORE7
MULTILIB_MATCHES = fPIC=fpic
EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
LIBGCC = stmp-multilib