* Add new port for score.
From-SVN: r117597
This commit is contained in:
parent
07d83dadc4
commit
bdcee4712e
@ -1,3 +1,7 @@
|
||||
2006-10-10 Chen Liqin <liqin@sunnorth.com.cn>
|
||||
|
||||
* MAINTAINERS: Add self as score port maintainer.
|
||||
|
||||
2006-10-04 Brooks Moses <bmoses@stanford.edu>
|
||||
|
||||
* MAINTAINERS (Write After Approval): Add myself.
|
||||
|
@ -309,6 +309,9 @@ powerpc*-*-*)
|
||||
rs6000*-*-*)
|
||||
need_64bit_hwint=yes
|
||||
;;
|
||||
score*-*-*)
|
||||
cpu_type=score
|
||||
;;
|
||||
sparc64*-*-*)
|
||||
cpu_type=sparc
|
||||
need_64bit_hwint=yes
|
||||
@ -1932,6 +1935,11 @@ s390x-ibm-tpf*)
|
||||
thread_file='tpf'
|
||||
extra_options="${extra_options} s390/tpf.opt"
|
||||
;;
|
||||
score-*-elf)
|
||||
tm_file="dbxelf.h elfos.h score/elf.h score/score.h"
|
||||
tmake_file=score/t-score-elf
|
||||
extra_objs="score-mdaux.o"
|
||||
;;
|
||||
sh-*-elf* | sh[12346l]*-*-elf* | sh*-*-kaos* | \
|
||||
sh-*-symbianelf* | sh[12346l]*-*-symbianelf* | \
|
||||
sh-*-linux* | sh[346lbe]*-*-linux* | \
|
||||
|
85
gcc/config/score/crti.asm
Normal file
85
gcc/config/score/crti.asm
Normal file
@ -0,0 +1,85 @@
|
||||
# crti.asm for Sunplus S+CORE
|
||||
#
|
||||
# Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the
|
||||
# Free Software Foundation; either version 2, or (at your option) any
|
||||
# later version.
|
||||
#
|
||||
# In addition to the permissions in the GNU General Public License, the
|
||||
# Free Software Foundation gives you unlimited permission to link the
|
||||
# compiled version of this file with other programs, and to distribute
|
||||
# those programs without any restriction coming from the use of this
|
||||
# file. (The General Public License restrictions do apply in other
|
||||
# respects; for example, they cover modification of the file, and
|
||||
# distribution when not linked into another program.)
|
||||
#
|
||||
# This file is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with GCC; see the file COPYING. If not, write to the Free
|
||||
# Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
#
|
||||
# As a special exception, if you link this library with files
|
||||
# compiled with GCC to produce an executable, this does not cause
|
||||
# the resulting executable to be covered by the GNU General Public License.
|
||||
# This exception does not however invalidate any other reasons why
|
||||
# the executable file might be covered by the GNU General Public License.
|
||||
#
|
||||
|
||||
# This file makes a stack frame for the contents of the .init and
|
||||
# .fini sections.
|
||||
|
||||
.section .init,"ax", @progbits
|
||||
.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
|
||||
jl exit
|
||||
.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]
|
||||
|
||||
|
47
gcc/config/score/crtn.asm
Normal file
47
gcc/config/score/crtn.asm
Normal file
@ -0,0 +1,47 @@
|
||||
# crtn.asm for Sunplus S+CORE
|
||||
|
||||
# Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the
|
||||
# Free Software Foundation; either version 2, or (at your option) any
|
||||
# later version.
|
||||
#
|
||||
# In addition to the permissions in the GNU General Public License, the
|
||||
# Free Software Foundation gives you unlimited permission to link the
|
||||
# compiled version of this file with other programs, and to distribute
|
||||
# those programs without any restriction coming from the use of this
|
||||
# file. (The General Public License restrictions do apply in other
|
||||
# respects; for example, they cover modification of the file, and
|
||||
# distribution when not linked into another program.)
|
||||
#
|
||||
# This file is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with GCC; see the file COPYING. If not, write to the Free
|
||||
# Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
#
|
||||
# As a special exception, if you link this library with files
|
||||
# compiled with GCC to produce an executable, this does not cause
|
||||
# the resulting executable to be covered by the GNU General Public License.
|
||||
# This exception does not however invalidate any other reasons why
|
||||
# the executable file might be covered by the GNU General Public License.
|
||||
#
|
||||
|
||||
# This file makes sure that the .init and .fini sections do in
|
||||
# fact return.
|
||||
|
||||
.section .init, "ax", @progbits
|
||||
lw r3, [r0, 20]
|
||||
addi r0, 32
|
||||
br r3
|
||||
|
||||
.section .fini, "ax", @progbits
|
||||
lw r3, [r0, 20]
|
||||
addi r0, 32
|
||||
br r3
|
||||
|
101
gcc/config/score/elf.h
Normal file
101
gcc/config/score/elf.h
Normal file
@ -0,0 +1,101 @@
|
||||
/* elf.h for Sunplus S+CORE processor
|
||||
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2, or (at your
|
||||
option) any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define OBJECT_FORMAT_ELF
|
||||
|
||||
/* Biggest alignment supported by the object file format of this machine. */
|
||||
#undef MAX_OFILE_ALIGNMENT
|
||||
#define MAX_OFILE_ALIGNMENT (32768 * 8)
|
||||
|
||||
/* Switch into a generic section. */
|
||||
#undef TARGET_ASM_NAMED_SECTION
|
||||
#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section
|
||||
|
||||
/* The following macro defines the format used to output the second
|
||||
operand of the .type assembler directive. */
|
||||
#define TYPE_OPERAND_FMT "@%s"
|
||||
|
||||
#undef TYPE_ASM_OP
|
||||
#define TYPE_ASM_OP "\t.type\t"
|
||||
|
||||
#undef SIZE_ASM_OP
|
||||
#define SIZE_ASM_OP "\t.size\t"
|
||||
|
||||
/* A c expression whose value is a string containing the
|
||||
assembler operation to identify the following data as
|
||||
uninitialized global data. */
|
||||
#ifndef BSS_SECTION_ASM_OP
|
||||
#define BSS_SECTION_ASM_OP "\t.section\t.bss"
|
||||
#endif
|
||||
|
||||
#ifndef ASM_OUTPUT_ALIGNED_BSS
|
||||
#define ASM_OUTPUT_ALIGNED_BSS asm_output_aligned_bss
|
||||
#endif
|
||||
|
||||
#define ASM_OUTPUT_DEF(FILE, LABEL1, LABEL2) \
|
||||
do { \
|
||||
fputc ('\t', FILE); \
|
||||
assemble_name (FILE, LABEL1); \
|
||||
fputs (" = ", FILE); \
|
||||
assemble_name (FILE, LABEL2); \
|
||||
fputc ('\n', FILE); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* This is how we tell the assembler that a symbol is weak. */
|
||||
#undef ASM_WEAKEN_LABEL
|
||||
#define ASM_WEAKEN_LABEL(FILE, NAME) ASM_OUTPUT_WEAK_ALIAS (FILE, NAME, 0)
|
||||
|
||||
#define ASM_OUTPUT_WEAK_ALIAS(FILE, NAME, VALUE) \
|
||||
do { \
|
||||
fputs ("\t.weak\t", FILE); \
|
||||
assemble_name (FILE, NAME); \
|
||||
if (VALUE) \
|
||||
{ \
|
||||
fputc (' ', FILE); \
|
||||
assemble_name (FILE, VALUE); \
|
||||
} \
|
||||
fputc ('\n', FILE); \
|
||||
} while (0)
|
||||
|
||||
#define MAKE_DECL_ONE_ONLY(DECL) (DECL_WEAK (DECL) = 1)
|
||||
|
||||
/* On elf, we *do* have support for the .init and .fini sections, and we
|
||||
can put stuff in there to be executed before and after `main'. We let
|
||||
crtstuff.c and other files know this by defining the following symbols.
|
||||
The definitions say how to change sections to the .init and .fini
|
||||
sections. This is the same for all known elf assemblers. */
|
||||
#undef INIT_SECTION_ASM_OP
|
||||
#define INIT_SECTION_ASM_OP "\t.section\t.init"
|
||||
#undef FINI_SECTION_ASM_OP
|
||||
#define FINI_SECTION_ASM_OP "\t.section\t.fini"
|
||||
|
||||
/* Don't set the target flags, this is done by the linker script */
|
||||
#undef LIB_SPEC
|
||||
#define LIB_SPEC ""
|
||||
|
||||
#undef STARTFILE_SPEC
|
||||
#define STARTFILE_SPEC "crti%O%s crtbegin%O%s"
|
||||
|
||||
#undef ENDFILE_SPEC
|
||||
#define ENDFILE_SPEC "crtend%O%s crtn%O%s"
|
||||
|
||||
/* We support #pragma. */
|
||||
#define HANDLE_SYSV_PRAGMA 1
|
181
gcc/config/score/mac.md
Normal file
181
gcc/config/score/mac.md
Normal file
@ -0,0 +1,181 @@
|
||||
;; Machine description for Sunplus S+CORE
|
||||
;; Copyright (C) 2005
|
||||
;; Free Software Foundation, Inc.
|
||||
;; Contributed by Sunnorth.
|
||||
|
||||
;; This file is part of GCC.
|
||||
|
||||
;; GCC is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation; either version 2, or (at your option)
|
||||
;; any later version.
|
||||
|
||||
;; GCC is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GCC; see the file COPYING. If not, write to
|
||||
;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
;; Boston, MA 02110-1301, USA.
|
||||
|
||||
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
|
||||
|
||||
(define_insn "smaxsi3"
|
||||
[(set (match_operand:SI 0 "register_operand" "=d")
|
||||
(smax:SI (match_operand:SI 1 "register_operand" "d")
|
||||
(match_operand:SI 2 "register_operand" "d")))]
|
||||
"TARGET_MAC"
|
||||
"max %0, %1, %2"
|
||||
[(set_attr "type" "arith")
|
||||
(set_attr "mode" "SI")])
|
||||
|
||||
(define_insn "sminsi3"
|
||||
[(set (match_operand:SI 0 "register_operand" "=d")
|
||||
(smin:SI (match_operand:SI 1 "register_operand" "d")
|
||||
(match_operand:SI 2 "register_operand" "d")))]
|
||||
"TARGET_MAC"
|
||||
"min %0, %1, %2"
|
||||
[(set_attr "type" "arith")
|
||||
(set_attr "mode" "SI")])
|
||||
|
||||
(define_insn "abssi2"
|
||||
[(set (match_operand:SI 0 "register_operand" "=d")
|
||||
(abs:SI (match_operand:SI 1 "register_operand" "d")))]
|
||||
"TARGET_MAC"
|
||||
"abs %0, %1"
|
||||
[(set_attr "type" "arith")
|
||||
(set_attr "mode" "SI")])
|
||||
|
||||
(define_insn "clzsi2"
|
||||
[(set (match_operand:SI 0 "register_operand" "=d")
|
||||
(clz:SI (match_operand:SI 1 "register_operand" "d")))]
|
||||
"TARGET_MAC"
|
||||
"clz %0, %1"
|
||||
[(set_attr "type" "arith")
|
||||
(set_attr "mode" "SI")])
|
||||
|
||||
(define_insn "sffs"
|
||||
[(set (match_operand:SI 0 "register_operand" "=d")
|
||||
(unspec:SI [(match_operand:SI 1 "register_operand" "d")] SFFS))]
|
||||
"TARGET_MAC"
|
||||
"bitrev %0, %1, r0\;clz %0, %0\;addi %0, 0x1"
|
||||
[(set_attr "type" "arith")
|
||||
(set_attr "mode" "SI")])
|
||||
|
||||
(define_expand "ffssi2"
|
||||
[(set (match_operand:SI 0 "register_operand")
|
||||
(ffs:SI (match_operand:SI 1 "register_operand")))]
|
||||
"TARGET_MAC"
|
||||
{
|
||||
emit_insn (gen_sffs (operands[0], operands[1]));
|
||||
emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (CC_NZmode, CC_REGNUM),
|
||||
gen_rtx_COMPARE (CC_NZmode, operands[0],
|
||||
GEN_INT (33))));
|
||||
emit_insn (gen_movsicc_internal (operands[0],
|
||||
gen_rtx_fmt_ee (EQ, VOIDmode, operands[0], GEN_INT (33)),
|
||||
GEN_INT (0),
|
||||
operands[0]));
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_peephole2
|
||||
[(set (match_operand:SI 0 "loreg_operand" "")
|
||||
(match_operand:SI 1 "register_operand" ""))
|
||||
(set (match_operand:SI 2 "hireg_operand" "")
|
||||
(match_operand:SI 3 "register_operand" ""))]
|
||||
"TARGET_MAC"
|
||||
[(parallel
|
||||
[(set (match_dup 0) (match_dup 1))
|
||||
(set (match_dup 2) (match_dup 3))])])
|
||||
|
||||
(define_peephole2
|
||||
[(set (match_operand:SI 0 "hireg_operand" "")
|
||||
(match_operand:SI 1 "register_operand" ""))
|
||||
(set (match_operand:SI 2 "loreg_operand" "")
|
||||
(match_operand:SI 3 "register_operand" ""))]
|
||||
"TARGET_MAC"
|
||||
[(parallel
|
||||
[(set (match_dup 2) (match_dup 3))
|
||||
(set (match_dup 0) (match_dup 1))])])
|
||||
|
||||
(define_insn "movtohilo"
|
||||
[(parallel
|
||||
[(set (match_operand:SI 0 "loreg_operand" "=l")
|
||||
(match_operand:SI 1 "register_operand" "d"))
|
||||
(set (match_operand:SI 2 "hireg_operand" "=h")
|
||||
(match_operand:SI 3 "register_operand" "d"))])]
|
||||
"TARGET_MAC"
|
||||
"mtcehl %3, %1"
|
||||
[(set_attr "type" "fce")
|
||||
(set_attr "mode" "SI")])
|
||||
|
||||
(define_insn "mulsi3addsi"
|
||||
[(set (match_operand:SI 0 "register_operand" "=l,l,d")
|
||||
(plus:SI (mult:SI (match_operand:SI 2 "register_operand" "d,d,d")
|
||||
(match_operand:SI 3 "register_operand" "d,d,d"))
|
||||
(match_operand:SI 1 "register_operand" "0,d,l")))
|
||||
(clobber (reg:SI HI_REGNUM))]
|
||||
"TARGET_MAC"
|
||||
"@
|
||||
mad %2, %3
|
||||
mtcel%S1 %1\;mad %2, %3
|
||||
mad %2, %3\;mfcel%S0 %0"
|
||||
[(set_attr "mode" "SI")])
|
||||
|
||||
(define_insn "mulsi3subsi"
|
||||
[(set (match_operand:SI 0 "register_operand" "=l,l,d")
|
||||
(minus:SI (match_operand:SI 1 "register_operand" "0,d,l")
|
||||
(mult:SI (match_operand:SI 2 "register_operand" "d,d,d")
|
||||
(match_operand:SI 3 "register_operand" "d,d,d"))))
|
||||
(clobber (reg:SI HI_REGNUM))]
|
||||
"TARGET_MAC"
|
||||
"@
|
||||
msb %2, %3
|
||||
mtcel%S1 %1\;msb %2, %3
|
||||
msb %2, %3\;mfcel%S0 %0"
|
||||
[(set_attr "mode" "SI")])
|
||||
|
||||
(define_insn "mulsidi3adddi"
|
||||
[(set (match_operand:DI 0 "register_operand" "=x")
|
||||
(plus:DI (mult:DI
|
||||
(sign_extend:DI (match_operand:SI 2 "register_operand" "%d"))
|
||||
(sign_extend:DI (match_operand:SI 3 "register_operand" "d")))
|
||||
(match_operand:DI 1 "register_operand" "0")))]
|
||||
"TARGET_MAC"
|
||||
"mad %2, %3"
|
||||
[(set_attr "mode" "DI")])
|
||||
|
||||
(define_insn "umulsidi3adddi"
|
||||
[(set (match_operand:DI 0 "register_operand" "=x")
|
||||
(plus:DI (mult:DI
|
||||
(zero_extend:DI (match_operand:SI 2 "register_operand" "%d"))
|
||||
(zero_extend:DI (match_operand:SI 3 "register_operand" "d")))
|
||||
(match_operand:DI 1 "register_operand" "0")))]
|
||||
"TARGET_MAC"
|
||||
"madu %2, %3"
|
||||
[(set_attr "mode" "DI")])
|
||||
|
||||
(define_insn "mulsidi3subdi"
|
||||
[(set (match_operand:DI 0 "register_operand" "=x")
|
||||
(minus:DI
|
||||
(match_operand:DI 1 "register_operand" "0")
|
||||
(mult:DI
|
||||
(sign_extend:DI (match_operand:SI 2 "register_operand" "%d"))
|
||||
(sign_extend:DI (match_operand:SI 3 "register_operand" "d")))))]
|
||||
"TARGET_MAC"
|
||||
"msb %2, %3"
|
||||
[(set_attr "mode" "DI")])
|
||||
|
||||
(define_insn "umulsidi3subdi"
|
||||
[(set (match_operand:DI 0 "register_operand" "=x")
|
||||
(minus:DI
|
||||
(match_operand:DI 1 "register_operand" "0")
|
||||
(mult:DI (zero_extend:DI
|
||||
(match_operand:SI 2 "register_operand" "%d"))
|
||||
(zero_extend:DI
|
||||
(match_operand:SI 3 "register_operand" "d")))))]
|
||||
"TARGET_MAC"
|
||||
"msbu %2, %3"
|
||||
[(set_attr "mode" "DI")])
|
108
gcc/config/score/misc.md
Normal file
108
gcc/config/score/misc.md
Normal file
@ -0,0 +1,108 @@
|
||||
;; Machine description for Sunplus S+CORE
|
||||
;; Copyright (C) 2005
|
||||
;; Free Software Foundation, Inc.
|
||||
;; Contributed by Sunnorth.
|
||||
|
||||
;; This file is part of GCC.
|
||||
|
||||
;; GCC is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation; either version 2, or (at your option)
|
||||
;; any later version.
|
||||
|
||||
;; GCC is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GCC; see the file COPYING. If not, write to
|
||||
;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
;; Boston, MA 02110-1301, USA.
|
||||
|
||||
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
|
||||
|
||||
(define_insn "pushsi"
|
||||
[(set (match_operand:SI 0 "push_operand" "=<")
|
||||
(match_operand:SI 1 "register_operand" "d"))]
|
||||
""
|
||||
"push! %1, [r0]"
|
||||
[(set_attr "type" "store")
|
||||
(set_attr "mode" "SI")])
|
||||
|
||||
(define_insn "popsi"
|
||||
[(set (match_operand:SI 0 "register_operand" "=d")
|
||||
(match_operand:SI 1 "pop_operand" ">"))]
|
||||
""
|
||||
"pop! %0, [r0]"
|
||||
[(set_attr "type" "store")
|
||||
(set_attr "mode" "SI")])
|
||||
|
||||
(define_peephole2
|
||||
[(set (match_operand:SI 0 "g32reg_operand" "")
|
||||
(match_operand:SI 1 "loreg_operand" ""))
|
||||
(set (match_operand:SI 2 "g32reg_operand" "")
|
||||
(match_operand:SI 3 "hireg_operand" ""))]
|
||||
""
|
||||
[(parallel
|
||||
[(set (match_dup 0) (match_dup 1))
|
||||
(set (match_dup 2) (match_dup 3))])])
|
||||
|
||||
(define_peephole2
|
||||
[(set (match_operand:SI 0 "g32reg_operand" "")
|
||||
(match_operand:SI 1 "hireg_operand" ""))
|
||||
(set (match_operand:SI 2 "g32reg_operand" "")
|
||||
(match_operand:SI 3 "loreg_operand" ""))]
|
||||
""
|
||||
[(parallel
|
||||
[(set (match_dup 2) (match_dup 3))
|
||||
(set (match_dup 0) (match_dup 1))])])
|
||||
|
||||
(define_insn "movhilo"
|
||||
[(parallel
|
||||
[(set (match_operand:SI 0 "register_operand" "=d")
|
||||
(match_operand:SI 1 "loreg_operand" ""))
|
||||
(set (match_operand:SI 2 "register_operand" "=d")
|
||||
(match_operand:SI 3 "hireg_operand" ""))])]
|
||||
""
|
||||
"mfcehl %2, %0"
|
||||
[(set_attr "type" "fce")
|
||||
(set_attr "mode" "SI")])
|
||||
|
||||
(define_expand "movsicc"
|
||||
[(set (match_operand:SI 0 "register_operand" "")
|
||||
(if_then_else:SI (match_operator 1 "comparison_operator"
|
||||
[(reg:CC CC_REGNUM) (const_int 0)])
|
||||
(match_operand:SI 2 "register_operand" "")
|
||||
(match_operand:SI 3 "register_operand" "")))]
|
||||
""
|
||||
{
|
||||
mdx_movsicc (operands);
|
||||
})
|
||||
|
||||
(define_insn "movsicc_internal"
|
||||
[(set (match_operand:SI 0 "register_operand" "=d")
|
||||
(if_then_else:SI (match_operator 1 "comparison_operator"
|
||||
[(reg:CC CC_REGNUM) (const_int 0)])
|
||||
(match_operand:SI 2 "register_operand" "d")
|
||||
(match_operand:SI 3 "register_operand" "0")))]
|
||||
""
|
||||
"mv%C1 %0, %2"
|
||||
[(set_attr "type" "cndmv")
|
||||
(set_attr "mode" "SI")])
|
||||
|
||||
(define_insn "zero_extract_bittst"
|
||||
[(set (reg:CC_NZ CC_REGNUM)
|
||||
(compare:CC_NZ (unspec:SI
|
||||
[(match_operand:SI 0 "register_operand" "*e,d")
|
||||
(match_operand:SI 1 "const_bi_operand" "")]
|
||||
BITTST)
|
||||
(const_int 0)))]
|
||||
""
|
||||
"@
|
||||
bittst! %0, %c1
|
||||
bittst.c %0, %c1"
|
||||
[(set_attr "type" "arith")
|
||||
(set_attr "up_c" "yes")
|
||||
(set_attr "mode" "SI")])
|
||||
|
224
gcc/config/score/mul-div.S
Normal file
224
gcc/config/score/mul-div.S
Normal file
@ -0,0 +1,224 @@
|
||||
/* Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
Contributed by Sunnorth
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2, or (at your
|
||||
option) any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define ra r3
|
||||
#define a0 r4
|
||||
#define a1 r5
|
||||
#define a2 r6
|
||||
#define a3 r7
|
||||
#define v0 r23
|
||||
|
||||
#define t0 r8
|
||||
#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
|
||||
|
||||
#if !defined(L_mulsi3) && !defined(L_divsi3)
|
||||
.text
|
||||
.global _flush_cache
|
||||
_flush_cache:
|
||||
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
|
||||
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
|
||||
.text
|
||||
.global __umulsi3
|
||||
.global __mulsi3
|
||||
/* signed multiplication (32x32) */
|
||||
.ent __mulsi3
|
||||
__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 */
|
||||
__mulsi3_loop2:
|
||||
slli a0, a0, 1 /* multiplicand mul 2 */
|
||||
cmpi.c a1, 0
|
||||
bne __mulsi3_loop
|
||||
mv r4, t1
|
||||
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
|
||||
.text
|
||||
.global __udivsi3
|
||||
.global __umodsi3
|
||||
.global __divsi3
|
||||
.global __modsi3
|
||||
|
||||
/* unsigned division */
|
||||
.ent __udivsi3
|
||||
__udivsi3:
|
||||
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
|
||||
br ra
|
||||
.end __udivsi3
|
||||
|
||||
/* unsigned modulus */
|
||||
.ent __umodsi3
|
||||
__umodsi3:
|
||||
mv t3, ra
|
||||
jl __udivsi3
|
||||
mv r4, a1
|
||||
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:
|
||||
mv t3, ra
|
||||
xor t2, a0, a1
|
||||
jl __orgsi3
|
||||
__divsi3_adjust:
|
||||
cmpi.c t2, 0
|
||||
bge __divsi3_exit
|
||||
neg r4, r4
|
||||
__divsi3_exit:
|
||||
br t3
|
||||
.end __divsi3
|
||||
|
||||
/* signed modulus */
|
||||
.ent __modsi3
|
||||
__modsi3:
|
||||
mv t3, ra
|
||||
mv t2, a0
|
||||
jl __orgsi3
|
||||
mv r4, a1
|
||||
b __divsi3_adjust
|
||||
.end __modsi3
|
||||
|
||||
#endif /* L_divsi3 */
|
||||
|
63
gcc/config/score/predicates.md
Normal file
63
gcc/config/score/predicates.md
Normal file
@ -0,0 +1,63 @@
|
||||
;; Predicate definitions for Sunplus S+CORE.
|
||||
;; Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
;;
|
||||
;; This file is part of GCC.
|
||||
;;
|
||||
;; GCC is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation; either version 2, or (at your option)
|
||||
;; any later version.
|
||||
;;
|
||||
;; GCC is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
;;
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GCC; see the file COPYING. If not, write to
|
||||
;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
;; Boston, MA 02110-1301, USA.
|
||||
|
||||
(define_predicate "arith_operand"
|
||||
(ior (match_code "const_int")
|
||||
(match_operand 0 "register_operand")))
|
||||
|
||||
(define_predicate "const_call_insn_operand"
|
||||
(match_code "const,symbol_ref,label_ref")
|
||||
{
|
||||
enum score_symbol_type symbol_type;
|
||||
|
||||
return (mda_symbolic_constant_p (op, &symbol_type)
|
||||
&& (symbol_type == SYMBOL_GENERAL));
|
||||
})
|
||||
|
||||
(define_predicate "call_insn_operand"
|
||||
(ior (match_operand 0 "const_call_insn_operand")
|
||||
(match_operand 0 "register_operand")))
|
||||
|
||||
(define_predicate "const_bi_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "CONST_OK_FOR_LETTER_P (INTVAL (op), 'J')")))
|
||||
|
||||
(define_predicate "pindex_off_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "CONST_OK_FOR_LETTER_P (INTVAL (op), 'P')")))
|
||||
|
||||
(define_predicate "hireg_operand"
|
||||
(and (match_code "reg")
|
||||
(match_test "REGNO (op) == HI_REGNUM")))
|
||||
|
||||
(define_predicate "loreg_operand"
|
||||
(and (match_code "reg")
|
||||
(match_test "REGNO (op) == LO_REGNUM")))
|
||||
|
||||
(define_predicate "g32reg_operand"
|
||||
(and (match_code "reg")
|
||||
(match_test "GP_REG_P (REGNO (op))")))
|
||||
|
||||
(define_predicate "branch_n_operator"
|
||||
(match_code "lt,ge"))
|
||||
|
||||
(define_predicate "branch_nz_operator"
|
||||
(match_code "eq,ne,lt,ge"))
|
||||
|
82
gcc/config/score/score-conv.h
Normal file
82
gcc/config/score/score-conv.h
Normal file
@ -0,0 +1,82 @@
|
||||
/* score-conv.h for Sunplus S+CORE processor
|
||||
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2, or (at your
|
||||
option) any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifndef SCORE_CONV_0601
|
||||
#define SCORE_CONV_0601
|
||||
|
||||
extern int target_flags;
|
||||
|
||||
#define GP_REG_FIRST 0U
|
||||
#define GP_REG_LAST 31U
|
||||
#define GP_REG_NUM (GP_REG_LAST - GP_REG_FIRST + 1U)
|
||||
#define GP_DBX_FIRST 0U
|
||||
|
||||
#define CE_REG_FIRST 48U
|
||||
#define CE_REG_LAST 49U
|
||||
#define CE_REG_NUM (CE_REG_LAST - CE_REG_FIRST + 1U)
|
||||
|
||||
#define ARG_REG_FIRST 4U
|
||||
#define ARG_REG_LAST 7U
|
||||
#define ARG_REG_NUM (ARG_REG_LAST - ARG_REG_FIRST + 1U)
|
||||
|
||||
#define REG_CONTAIN(REGNO, FIRST, NUM) \
|
||||
((unsigned int)((int) (REGNO) - (FIRST)) < (NUM))
|
||||
|
||||
#define GP_REG_P(REGNO) REG_CONTAIN (REGNO, GP_REG_FIRST, GP_REG_NUM)
|
||||
|
||||
#define G16_REG_P(REGNO) REG_CONTAIN (REGNO, GP_REG_FIRST, 16)
|
||||
|
||||
#define CE_REG_P(REGNO) REG_CONTAIN (REGNO, CE_REG_FIRST, CE_REG_NUM)
|
||||
|
||||
#define UIMM_IN_RANGE(V, W) ((V) >= 0 && (V) < ((HOST_WIDE_INT)1 << (W)))
|
||||
|
||||
#define SIMM_IN_RANGE(V, W) \
|
||||
((V) >= (-1 * ((HOST_WIDE_INT) 1 << ((W) - 1))) \
|
||||
&& (V) < (1 * ((HOST_WIDE_INT) 1 << ((W) - 1))))
|
||||
|
||||
#define IMM_IN_RANGE(V, W, S) \
|
||||
((S) ? SIMM_IN_RANGE (V, W) : UIMM_IN_RANGE (V, W))
|
||||
|
||||
#define SCORE_STACK_ALIGN(LOC) (((LOC) + 3) & ~3)
|
||||
|
||||
#define SCORE_MAX_FIRST_STACK_STEP (0x3ff0)
|
||||
|
||||
#define SCORE_SDATA_MAX score_sdata_max ()
|
||||
|
||||
#define DEFAULT_SDATA_MAX 8
|
||||
|
||||
#define CONST_HIGH_PART(VALUE) \
|
||||
(((VALUE) + 0x8000) & ~(unsigned HOST_WIDE_INT) 0xffff)
|
||||
|
||||
#define CONST_LOW_PART(VALUE) ((VALUE) - CONST_HIGH_PART (VALUE))
|
||||
|
||||
#define PROLOGUE_TEMP_REGNUM (GP_REG_FIRST + 8)
|
||||
|
||||
#define EPILOGUE_TEMP_REGNUM (GP_REG_FIRST + 8)
|
||||
|
||||
enum score_symbol_type
|
||||
{
|
||||
SYMBOL_GENERAL,
|
||||
SYMBOL_SMALL_DATA /* The symbol refers to something in a small data section. */
|
||||
};
|
||||
|
||||
int score_sdata_max (void);
|
||||
|
||||
#endif
|
738
gcc/config/score/score-mdaux.c
Normal file
738
gcc/config/score/score-mdaux.c
Normal file
@ -0,0 +1,738 @@
|
||||
/* score-mdaux.c for Sunplus S+CORE processor
|
||||
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
Contributed by Sunnorth
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2, or (at your
|
||||
option) any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tm.h"
|
||||
#include <signal.h>
|
||||
#include "rtl.h"
|
||||
#include "regs.h"
|
||||
#include "hard-reg-set.h"
|
||||
#include "real.h"
|
||||
#include "insn-config.h"
|
||||
#include "conditions.h"
|
||||
#include "insn-attr.h"
|
||||
#include "recog.h"
|
||||
#include "toplev.h"
|
||||
#include "output.h"
|
||||
#include "tree.h"
|
||||
#include "function.h"
|
||||
#include "expr.h"
|
||||
#include "optabs.h"
|
||||
#include "flags.h"
|
||||
#include "reload.h"
|
||||
#include "tm_p.h"
|
||||
#include "ggc.h"
|
||||
#include "gstab.h"
|
||||
#include "hashtab.h"
|
||||
#include "debug.h"
|
||||
#include "target.h"
|
||||
#include "target-def.h"
|
||||
#include "integrate.h"
|
||||
#include "langhooks.h"
|
||||
#include "cfglayout.h"
|
||||
#include "score-mdaux.h"
|
||||
|
||||
#define BITSET_P(VALUE, BIT) (((VALUE) & (1L << (BIT))) != 0)
|
||||
#define INS_BUF_SZ 100
|
||||
|
||||
/* Define the information needed to generate branch insns. This is
|
||||
stored from the compare operation. */
|
||||
rtx cmp_op0, cmp_op1;
|
||||
|
||||
static char ins[INS_BUF_SZ + 8];
|
||||
|
||||
/* Return true if SYMBOL is a SYMBOL_REF and OFFSET + SYMBOL points
|
||||
to the same object as SYMBOL. */
|
||||
static int
|
||||
score_offset_within_object_p (rtx symbol, HOST_WIDE_INT offset)
|
||||
{
|
||||
if (GET_CODE (symbol) != SYMBOL_REF)
|
||||
return 0;
|
||||
|
||||
if (CONSTANT_POOL_ADDRESS_P (symbol)
|
||||
&& offset >= 0
|
||||
&& offset < (int)GET_MODE_SIZE (get_pool_mode (symbol)))
|
||||
return 1;
|
||||
|
||||
if (SYMBOL_REF_DECL (symbol) != 0
|
||||
&& offset >= 0
|
||||
&& offset < int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (symbol))))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Split X into a base and a constant offset, storing them in *BASE
|
||||
and *OFFSET respectively. */
|
||||
static void
|
||||
score_split_const (rtx x, rtx *base, HOST_WIDE_INT *offset)
|
||||
{
|
||||
*offset = 0;
|
||||
|
||||
if (GET_CODE (x) == CONST)
|
||||
x = XEXP (x, 0);
|
||||
|
||||
if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT)
|
||||
{
|
||||
*offset += INTVAL (XEXP (x, 1));
|
||||
x = XEXP (x, 0);
|
||||
}
|
||||
|
||||
*base = x;
|
||||
}
|
||||
|
||||
/* Classify symbol X, which must be a SYMBOL_REF or a LABEL_REF. */
|
||||
static enum
|
||||
score_symbol_type score_classify_symbol (rtx x)
|
||||
{
|
||||
if (GET_CODE (x) == LABEL_REF)
|
||||
return SYMBOL_GENERAL;
|
||||
|
||||
if (GET_CODE (x) != SYMBOL_REF)
|
||||
gcc_unreachable ();
|
||||
|
||||
if (CONSTANT_POOL_ADDRESS_P(x))
|
||||
{
|
||||
if (GET_MODE_SIZE (get_pool_mode (x)) <= SCORE_SDATA_MAX)
|
||||
return SYMBOL_SMALL_DATA;
|
||||
return SYMBOL_GENERAL;
|
||||
}
|
||||
if (SYMBOL_REF_SMALL_P (x))
|
||||
return SYMBOL_SMALL_DATA;
|
||||
return SYMBOL_GENERAL;
|
||||
}
|
||||
|
||||
/* Return true if the current function must save REGNO. */
|
||||
static int
|
||||
score_save_reg_p (unsigned int regno)
|
||||
{
|
||||
/* Check call-saved registers. */
|
||||
if (regs_ever_live[regno] && !call_used_regs[regno])
|
||||
return 1;
|
||||
|
||||
/* We need to save the old frame pointer before setting up a new one. */
|
||||
if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
|
||||
return 1;
|
||||
|
||||
/* We need to save the incoming return address if it is ever clobbered
|
||||
within the function. */
|
||||
if (regno == RA_REGNUM && regs_ever_live[regno])
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return one word of double-word value OP, taking into account the fixed
|
||||
endianness of certain registers. HIGH_P is true to select the high part,
|
||||
false to select the low part. */
|
||||
static rtx
|
||||
subw (rtx op, int high_p)
|
||||
{
|
||||
unsigned int byte;
|
||||
enum machine_mode mode = GET_MODE (op);
|
||||
|
||||
if (mode == VOIDmode)
|
||||
mode = DImode;
|
||||
|
||||
byte = (TARGET_LITTLE_ENDIAN ? high_p : !high_p) ? UNITS_PER_WORD : 0;
|
||||
|
||||
if (GET_CODE (op) == REG && REGNO (op) == HI_REGNUM)
|
||||
return gen_rtx_REG (SImode, high_p ? HI_REGNUM : LO_REGNUM);
|
||||
|
||||
if (GET_CODE (op) == MEM)
|
||||
return adjust_address (op, SImode, byte);
|
||||
|
||||
return simplify_gen_subreg (SImode, op, mode, byte);
|
||||
}
|
||||
|
||||
struct score_frame_info *
|
||||
mda_cached_frame (void)
|
||||
{
|
||||
static struct score_frame_info _frame_info;
|
||||
return &_frame_info;
|
||||
}
|
||||
|
||||
/* Return the bytes needed to compute the frame pointer from the current
|
||||
stack pointer. SIZE is the size (in bytes) of the local variables. */
|
||||
struct score_frame_info *
|
||||
mda_compute_frame_size (HOST_WIDE_INT size)
|
||||
{
|
||||
unsigned int regno;
|
||||
struct score_frame_info *f = mda_cached_frame ();
|
||||
|
||||
memset (f, 0, sizeof (struct score_frame_info));
|
||||
f->gp_reg_size = 0;
|
||||
f->mask = 0;
|
||||
f->var_size = SCORE_STACK_ALIGN (size);
|
||||
f->args_size = current_function_outgoing_args_size;
|
||||
f->cprestore_size = SCORE_STACK_ALIGN (STARTING_FRAME_OFFSET) - f->args_size;
|
||||
if (f->var_size == 0 && current_function_is_leaf)
|
||||
f->args_size = f->cprestore_size = 0;
|
||||
|
||||
if (f->args_size == 0 && current_function_calls_alloca)
|
||||
f->args_size = UNITS_PER_WORD;
|
||||
|
||||
f->total_size = f->var_size + f->args_size;
|
||||
for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
|
||||
{
|
||||
if (score_save_reg_p (regno))
|
||||
{
|
||||
f->gp_reg_size += GET_MODE_SIZE (SImode);
|
||||
f->mask |= 1 << (regno - GP_REG_FIRST);
|
||||
}
|
||||
}
|
||||
|
||||
if (current_function_calls_eh_return)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; ; ++i)
|
||||
{
|
||||
regno = EH_RETURN_DATA_REGNO (i);
|
||||
if (regno == INVALID_REGNUM)
|
||||
break;
|
||||
f->gp_reg_size += GET_MODE_SIZE (SImode);
|
||||
f->mask |= 1 << (regno - GP_REG_FIRST);
|
||||
}
|
||||
}
|
||||
|
||||
f->total_size += SCORE_STACK_ALIGN (f->gp_reg_size);
|
||||
f->num_gp = f->gp_reg_size / UNITS_PER_WORD;
|
||||
|
||||
if (f->mask)
|
||||
{
|
||||
HOST_WIDE_INT offset;
|
||||
offset = (f->args_size + f->cprestore_size + f->var_size
|
||||
+ f->gp_reg_size - GET_MODE_SIZE (SImode));
|
||||
f->gp_sp_offset = offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
f->gp_sp_offset = 0;
|
||||
}
|
||||
|
||||
if ((f->total_size == f->gp_reg_size) && flag_pic)
|
||||
f->total_size += 8;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
/* Generate the prologue instructions for entry into a S+core function. */
|
||||
void
|
||||
mdx_prologue (void)
|
||||
{
|
||||
#define EMIT_PL(_rtx) RTX_FRAME_RELATED_P (_rtx) = 1
|
||||
|
||||
struct score_frame_info *f = mda_compute_frame_size (get_frame_size ());
|
||||
HOST_WIDE_INT size;
|
||||
int regno;
|
||||
|
||||
size = f->total_size - f->gp_reg_size;
|
||||
|
||||
if (flag_pic)
|
||||
emit_insn (gen_cpload ());
|
||||
|
||||
for (regno = (int) GP_REG_LAST; regno >= (int) GP_REG_FIRST; regno--)
|
||||
{
|
||||
if (BITSET_P (f->mask, regno - GP_REG_FIRST))
|
||||
{
|
||||
rtx mem = gen_rtx_MEM (SImode,
|
||||
gen_rtx_PRE_DEC (SImode, stack_pointer_rtx));
|
||||
rtx reg = gen_rtx_REG (SImode, regno);
|
||||
if (!current_function_calls_eh_return)
|
||||
MEM_READONLY_P (mem) = 1;
|
||||
EMIT_PL (emit_insn (gen_pushsi (mem, reg)));
|
||||
}
|
||||
}
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
rtx insn;
|
||||
|
||||
if (CONST_OK_FOR_LETTER_P (-size, 'L'))
|
||||
EMIT_PL (emit_insn (gen_add3_insn (stack_pointer_rtx,
|
||||
stack_pointer_rtx,
|
||||
GEN_INT (-size))));
|
||||
else
|
||||
{
|
||||
EMIT_PL (emit_move_insn (gen_rtx_REG (Pmode, PROLOGUE_TEMP_REGNUM),
|
||||
GEN_INT (size)));
|
||||
EMIT_PL (emit_insn
|
||||
(gen_sub3_insn (stack_pointer_rtx,
|
||||
stack_pointer_rtx,
|
||||
gen_rtx_REG (Pmode,
|
||||
PROLOGUE_TEMP_REGNUM))));
|
||||
}
|
||||
insn = get_last_insn ();
|
||||
REG_NOTES (insn) =
|
||||
alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR,
|
||||
gen_rtx_SET (VOIDmode, stack_pointer_rtx,
|
||||
plus_constant (stack_pointer_rtx,
|
||||
-size)),
|
||||
REG_NOTES (insn));
|
||||
}
|
||||
|
||||
if (frame_pointer_needed)
|
||||
EMIT_PL (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx));
|
||||
|
||||
if (flag_pic)
|
||||
emit_insn (gen_cprestore (GEN_INT (size + 4)));
|
||||
|
||||
#undef EMIT_PL
|
||||
}
|
||||
|
||||
/* Generate the epilogue instructions in a S+core function. */
|
||||
void
|
||||
mdx_epilogue (int sibcall_p)
|
||||
{
|
||||
struct score_frame_info *f = mda_compute_frame_size (get_frame_size ());
|
||||
HOST_WIDE_INT size;
|
||||
int regno;
|
||||
rtx base;
|
||||
|
||||
size = f->total_size - f->gp_reg_size;
|
||||
|
||||
if (!frame_pointer_needed)
|
||||
base = stack_pointer_rtx;
|
||||
else
|
||||
base = hard_frame_pointer_rtx;
|
||||
|
||||
if (size)
|
||||
{
|
||||
if (CONST_OK_FOR_LETTER_P (size, 'L'))
|
||||
emit_insn (gen_add3_insn (base, base, GEN_INT (size)));
|
||||
else
|
||||
{
|
||||
emit_move_insn (gen_rtx_REG (Pmode, EPILOGUE_TEMP_REGNUM),
|
||||
GEN_INT (size));
|
||||
emit_insn (gen_add3_insn (base, base,
|
||||
gen_rtx_REG (Pmode,
|
||||
EPILOGUE_TEMP_REGNUM)));
|
||||
}
|
||||
}
|
||||
|
||||
if (base != stack_pointer_rtx)
|
||||
emit_move_insn (stack_pointer_rtx, base);
|
||||
|
||||
if (current_function_calls_eh_return)
|
||||
emit_insn (gen_add3_insn (stack_pointer_rtx,
|
||||
stack_pointer_rtx,
|
||||
EH_RETURN_STACKADJ_RTX));
|
||||
|
||||
for (regno = (int) GP_REG_FIRST; regno <= (int) GP_REG_LAST; regno++)
|
||||
{
|
||||
if (BITSET_P (f->mask, regno - GP_REG_FIRST))
|
||||
{
|
||||
rtx mem = gen_rtx_MEM (SImode,
|
||||
gen_rtx_POST_INC (SImode, stack_pointer_rtx));
|
||||
rtx reg = gen_rtx_REG (SImode, regno);
|
||||
|
||||
if (!current_function_calls_eh_return)
|
||||
MEM_READONLY_P (mem) = 1;
|
||||
|
||||
emit_insn (gen_popsi (reg, mem));
|
||||
}
|
||||
}
|
||||
|
||||
if (!sibcall_p)
|
||||
emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, RA_REGNUM)));
|
||||
}
|
||||
|
||||
/* Return true if X is a valid base register for the given mode.
|
||||
Allow only hard registers if STRICT. */
|
||||
int
|
||||
mda_valid_base_register_p (rtx x, int strict)
|
||||
{
|
||||
if (!strict && GET_CODE (x) == SUBREG)
|
||||
x = SUBREG_REG (x);
|
||||
|
||||
return (GET_CODE (x) == REG
|
||||
&& score_regno_mode_ok_for_base_p (REGNO (x), strict));
|
||||
}
|
||||
|
||||
/* Return true if X is a valid address for machine mode MODE. If it is,
|
||||
fill in INFO appropriately. STRICT is true if we should only accept
|
||||
hard base registers. */
|
||||
int
|
||||
mda_classify_address (struct score_address_info *info,
|
||||
enum machine_mode mode, rtx x, int strict)
|
||||
{
|
||||
info->code = GET_CODE (x);
|
||||
|
||||
switch (info->code)
|
||||
{
|
||||
case REG:
|
||||
case SUBREG:
|
||||
info->type = ADD_REG;
|
||||
info->reg = x;
|
||||
info->offset = const0_rtx;
|
||||
return mda_valid_base_register_p (info->reg, strict);
|
||||
case PLUS:
|
||||
info->type = ADD_REG;
|
||||
info->reg = XEXP (x, 0);
|
||||
info->offset = XEXP (x, 1);
|
||||
return (mda_valid_base_register_p (info->reg, strict)
|
||||
&& GET_CODE (info->offset) == CONST_INT
|
||||
&& CONST_OK_FOR_LETTER_P (INTVAL (info->offset), 'O'));
|
||||
case PRE_DEC:
|
||||
case POST_DEC:
|
||||
case PRE_INC:
|
||||
case POST_INC:
|
||||
if (TARGET_NOPINDEX || GET_MODE_SIZE (mode) > GET_MODE_SIZE (SImode))
|
||||
return false;
|
||||
info->type = ADD_REG;
|
||||
info->reg = XEXP (x, 0);
|
||||
info->offset = GEN_INT (GET_MODE_SIZE (mode));
|
||||
return mda_valid_base_register_p (info->reg, strict);
|
||||
case CONST_INT:
|
||||
info->type = ADD_CONST_INT;
|
||||
return CONST_OK_FOR_LETTER_P (INTVAL (x), 'O');
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
info->type = ADD_SYMBOLIC;
|
||||
return (mda_symbolic_constant_p (x, &info->symbol_type)
|
||||
&& (info->symbol_type == SYMBOL_GENERAL
|
||||
|| info->symbol_type == SYMBOL_SMALL_DATA));
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mda_gen_cmp (enum machine_mode mode)
|
||||
{
|
||||
emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (mode, CC_REGNUM),
|
||||
gen_rtx_COMPARE (mode, cmp_op0, cmp_op1)));
|
||||
}
|
||||
|
||||
/* Return true if X is a symbolic constant that can be calculated in
|
||||
the same way as a bare symbol. If it is, store the type of the
|
||||
symbol in *SYMBOL_TYPE. */
|
||||
int
|
||||
mda_symbolic_constant_p (rtx x, enum score_symbol_type *symbol_type)
|
||||
{
|
||||
HOST_WIDE_INT offset;
|
||||
|
||||
score_split_const (x, &x, &offset);
|
||||
if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
|
||||
*symbol_type = score_classify_symbol (x);
|
||||
else
|
||||
return 0;
|
||||
|
||||
if (offset == 0)
|
||||
return 1;
|
||||
|
||||
/* if offset > 15bit, must reload */
|
||||
if (!CONST_OK_FOR_LETTER_P (offset, 'O'))
|
||||
return 0;
|
||||
|
||||
switch (*symbol_type)
|
||||
{
|
||||
case SYMBOL_GENERAL:
|
||||
return 1;
|
||||
case SYMBOL_SMALL_DATA:
|
||||
return score_offset_within_object_p (x, offset);
|
||||
}
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
void
|
||||
mdx_movsicc (rtx *ops)
|
||||
{
|
||||
enum machine_mode mode = CCmode;
|
||||
|
||||
if (GET_CODE (ops[1]) == EQ || GET_CODE (ops[1]) == NE)
|
||||
mode = CC_NZmode;
|
||||
|
||||
emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (mode, CC_REGNUM),
|
||||
gen_rtx_COMPARE (mode, cmp_op0, cmp_op1)));
|
||||
}
|
||||
|
||||
/* Call and sibcall pattern all need call this function. */
|
||||
void
|
||||
mdx_call (rtx *ops, bool sib)
|
||||
{
|
||||
rtx addr = XEXP (ops[0], 0);
|
||||
if (!call_insn_operand (addr, VOIDmode))
|
||||
{
|
||||
rtx oaddr = addr;
|
||||
addr = gen_reg_rtx (Pmode);
|
||||
gen_move_insn (addr, oaddr);
|
||||
}
|
||||
|
||||
if (sib)
|
||||
emit_call_insn (gen_sibcall_internal (addr, ops[1]));
|
||||
else
|
||||
emit_call_insn (gen_call_internal (addr, ops[1]));
|
||||
}
|
||||
|
||||
/* Call value and sibcall value pattern all need call this function. */
|
||||
void
|
||||
mdx_call_value (rtx *ops, bool sib)
|
||||
{
|
||||
rtx result = ops[0];
|
||||
rtx addr = XEXP (ops[1], 0);
|
||||
rtx arg = ops[2];
|
||||
|
||||
if (!call_insn_operand (addr, VOIDmode))
|
||||
{
|
||||
rtx oaddr = addr;
|
||||
addr = gen_reg_rtx (Pmode);
|
||||
gen_move_insn (addr, oaddr);
|
||||
}
|
||||
|
||||
if (sib)
|
||||
emit_call_insn (gen_sibcall_value_internal (result, addr, arg));
|
||||
else
|
||||
emit_call_insn (gen_call_value_internal (result, addr, arg));
|
||||
}
|
||||
|
||||
/* Machine Split */
|
||||
void
|
||||
mds_movdi (rtx *ops)
|
||||
{
|
||||
rtx dst = ops[0];
|
||||
rtx src = ops[1];
|
||||
rtx dst0 = subw (dst, 0);
|
||||
rtx dst1 = subw (dst, 1);
|
||||
rtx src0 = subw (src, 0);
|
||||
rtx src1 = subw (src, 1);
|
||||
|
||||
if (GET_CODE (dst0) == REG && reg_overlap_mentioned_p (dst0, src))
|
||||
{
|
||||
emit_move_insn (dst1, src1);
|
||||
emit_move_insn (dst0, src0);
|
||||
}
|
||||
else
|
||||
{
|
||||
emit_move_insn (dst0, src0);
|
||||
emit_move_insn (dst1, src1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mds_zero_extract_andi (rtx *ops)
|
||||
{
|
||||
if (INTVAL (ops[1]) == 1 && const_bi_operand (ops[2], SImode))
|
||||
emit_insn (gen_zero_extract_bittst (ops[0], ops[2]));
|
||||
else
|
||||
{
|
||||
unsigned HOST_WIDE_INT mask;
|
||||
mask = (0xffffffffU & ((1U << INTVAL (ops[1])) - 1U));
|
||||
mask = mask << INTVAL (ops[2]);
|
||||
emit_insn (gen_andsi3_cmp (ops[0], gen_int_mode (mask, SImode)));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check addr could be present as PRE/POST mode. */
|
||||
static bool
|
||||
mda_pindex_mem (rtx addr)
|
||||
{
|
||||
if (GET_CODE (addr) == MEM)
|
||||
{
|
||||
switch (GET_CODE (XEXP (addr, 0)))
|
||||
{
|
||||
case PRE_DEC:
|
||||
case POST_DEC:
|
||||
case PRE_INC:
|
||||
case POST_INC:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Output asm code for ld/sw insn. */
|
||||
static int
|
||||
pr_addr_post (rtx *ops, int idata, int iaddr, char *ip, enum mda_mem_unit unit)
|
||||
{
|
||||
struct score_address_info ai;
|
||||
|
||||
gcc_assert (GET_CODE (ops[idata]) == REG);
|
||||
gcc_assert (mda_classify_address (&ai, SImode, XEXP (ops[iaddr], 0), true));
|
||||
|
||||
if (!mda_pindex_mem (ops[iaddr])
|
||||
&& ai.type == ADD_REG
|
||||
&& GET_CODE (ai.offset) == CONST_INT
|
||||
&& G16_REG_P (REGNO (ops[idata]))
|
||||
&& G16_REG_P (REGNO (ai.reg)))
|
||||
{
|
||||
if (INTVAL (ai.offset) == 0)
|
||||
{
|
||||
ops[iaddr] = ai.reg;
|
||||
return snprintf (ip, INS_BUF_SZ,
|
||||
"! %%%d, [%%%d]", idata, iaddr);
|
||||
}
|
||||
if (REGNO (ai.reg) == HARD_FRAME_POINTER_REGNUM)
|
||||
{
|
||||
HOST_WIDE_INT offset = INTVAL (ai.offset);
|
||||
if (MDA_ALIGN_UNIT (offset, unit)
|
||||
&& CONST_OK_FOR_LETTER_P (offset >> unit, 'J'))
|
||||
{
|
||||
ops[iaddr] = ai.offset;
|
||||
return snprintf (ip, INS_BUF_SZ,
|
||||
"p! %%%d, %%c%d", idata, iaddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
return snprintf (ip, INS_BUF_SZ, " %%%d, %%a%d", idata, iaddr);
|
||||
}
|
||||
|
||||
/* Output asm insn for load. */
|
||||
const char *
|
||||
mdp_linsn (rtx *ops, enum mda_mem_unit unit, bool sign)
|
||||
{
|
||||
const char *pre_ins[] =
|
||||
{"lbu", "lhu", "lw", "??", "lb", "lh", "lw", "??"};
|
||||
char *ip;
|
||||
|
||||
strcpy (ins, pre_ins[(sign ? 4 : 0) + unit]);
|
||||
ip = ins + strlen (ins);
|
||||
|
||||
if ((!sign && unit != MDA_HWORD)
|
||||
|| (sign && unit != MDA_BYTE))
|
||||
pr_addr_post (ops, 0, 1, ip, unit);
|
||||
else
|
||||
snprintf (ip, INS_BUF_SZ, " %%0, %%a1");
|
||||
|
||||
return ins;
|
||||
}
|
||||
|
||||
/* Output asm insn for store. */
|
||||
const char *
|
||||
mdp_sinsn (rtx *ops, enum mda_mem_unit unit)
|
||||
{
|
||||
const char *pre_ins[] = {"sb", "sh", "sw"};
|
||||
char *ip;
|
||||
|
||||
strcpy (ins, pre_ins[unit]);
|
||||
ip = ins + strlen (ins);
|
||||
pr_addr_post (ops, 1, 0, ip, unit);
|
||||
return ins;
|
||||
}
|
||||
|
||||
/* Output asm insn for load immediate. */
|
||||
const char *
|
||||
mdp_limm (rtx *ops)
|
||||
{
|
||||
gcc_assert (GET_CODE (ops[0]) == REG);
|
||||
|
||||
if (G16_REG_P (REGNO (ops[0]))
|
||||
&& CONST_OK_FOR_LETTER_P (INTVAL (ops[1]), 'I'))
|
||||
return "ldiu! %0, %c1";
|
||||
else if (CONST_OK_FOR_LETTER_P (INTVAL (ops[1]), 'L'))
|
||||
return "ldi %0, %c1";
|
||||
else if (EXTRA_CONSTRAINT (ops[1], 'Q'))
|
||||
return "ldis %0, %U1";
|
||||
else
|
||||
return "li %0, %D1";
|
||||
}
|
||||
|
||||
/* Output asm insn for move. */
|
||||
const char *
|
||||
mdp_move (rtx *ops)
|
||||
{
|
||||
gcc_assert (GET_CODE (ops[0]) == REG);
|
||||
gcc_assert (GET_CODE (ops[1]) == REG);
|
||||
|
||||
if (G16_REG_P (REGNO (ops[0])))
|
||||
{
|
||||
if (G16_REG_P (REGNO (ops[1])))
|
||||
return "mv! %0, %1";
|
||||
else
|
||||
return "mlfh! %0, %1";
|
||||
}
|
||||
else if (G16_REG_P (REGNO (ops[1])))
|
||||
return "mhfl! %0, %1";
|
||||
else
|
||||
return "mv %0, %1";
|
||||
}
|
||||
|
||||
/* Score support add/sub with exponent immediate insn,
|
||||
use to judge imm condition. */
|
||||
static unsigned int
|
||||
num_bits1 (unsigned HOST_WIDE_INT v)
|
||||
{
|
||||
int i, n = 0;
|
||||
|
||||
for (i = 0; i < BITS_PER_WORD; i++)
|
||||
n += BITSET_P (v, i) ? 1 : 0;
|
||||
return n;
|
||||
}
|
||||
|
||||
/* Generate add insn, insn will affect condition flag. Optimize used. */
|
||||
const char *
|
||||
mdp_add_imm_ucc (rtx *ops)
|
||||
{
|
||||
HOST_WIDE_INT v = INTVAL (ops[2]);
|
||||
|
||||
gcc_assert (GET_CODE (ops[2]) == CONST_INT);
|
||||
gcc_assert (REGNO (ops[0]) == REGNO (ops[1]));
|
||||
|
||||
if (G16_REG_P (REGNO (ops[0])))
|
||||
{
|
||||
if (v > 0 && num_bits1 (v) == 1 && IMM_IN_RANGE (ffs (v) - 1, 4, 0))
|
||||
{
|
||||
ops[2] = GEN_INT (ffs (v) - 1);
|
||||
return "addei! %0, %c2";
|
||||
}
|
||||
|
||||
if (v < 0 && num_bits1 (-v) == 1 && IMM_IN_RANGE (ffs (-v) - 1, 4, 0))
|
||||
{
|
||||
ops[2] = GEN_INT (ffs (-v) - 1);
|
||||
return "subei! %0, %c2";
|
||||
}
|
||||
}
|
||||
return "addi.c %0, %c2";
|
||||
}
|
||||
|
||||
/* Output arith insn, insn will update condition flag. */
|
||||
const char *
|
||||
mdp_select (rtx *ops, const char *inst_pre, bool commu, const char *let)
|
||||
{
|
||||
gcc_assert (GET_CODE (ops[0]) == REG);
|
||||
gcc_assert (GET_CODE (ops[1]) == REG);
|
||||
|
||||
if (G16_REG_P (REGNO (ops[0]))
|
||||
&& (GET_CODE (ops[2]) == REG ? G16_REG_P (REGNO (ops[2])) : 1)
|
||||
&& REGNO (ops[0]) == REGNO (ops[1]))
|
||||
{
|
||||
snprintf (ins, INS_BUF_SZ, "%s! %%0, %%%s2", inst_pre, let);
|
||||
return ins;
|
||||
}
|
||||
|
||||
if (commu && G16_REG_P (REGNO (ops[0]))
|
||||
&& G16_REG_P (REGNO (ops[1]))
|
||||
&& REGNO (ops[0]) == REGNO (ops[2]))
|
||||
{
|
||||
gcc_assert (GET_CODE (ops[2]) == REG);
|
||||
snprintf (ins, INS_BUF_SZ, "%s! %%0, %%%s1", inst_pre, let);
|
||||
return ins;
|
||||
}
|
||||
|
||||
snprintf (ins, INS_BUF_SZ, "%s.c %%0, %%1, %%%s2", inst_pre, let);
|
||||
return ins;
|
||||
}
|
||||
|
113
gcc/config/score/score-mdaux.h
Normal file
113
gcc/config/score/score-mdaux.h
Normal file
@ -0,0 +1,113 @@
|
||||
/* score-mdaux.h for Sunplus S+CORE processor
|
||||
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
Contributed by Sunnorth
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2, or (at your
|
||||
option) any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifndef SCORE_MDAUX_0621
|
||||
#define SCORE_MDAUX_0621
|
||||
|
||||
/* Machine Auxiliary Functions. */
|
||||
enum score_address_type
|
||||
{
|
||||
ADD_REG,
|
||||
ADD_CONST_INT,
|
||||
ADD_SYMBOLIC
|
||||
};
|
||||
#ifdef RTX_CODE
|
||||
struct score_address_info
|
||||
{
|
||||
enum score_address_type type;
|
||||
rtx reg;
|
||||
rtx offset;
|
||||
enum rtx_code code;
|
||||
enum score_symbol_type symbol_type;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct score_frame_info
|
||||
{
|
||||
HOST_WIDE_INT total_size; /* bytes that the entire frame takes up */
|
||||
HOST_WIDE_INT var_size; /* bytes that variables take up */
|
||||
HOST_WIDE_INT args_size; /* bytes that outgoing arguments take up */
|
||||
HOST_WIDE_INT gp_reg_size; /* bytes needed to store gp regs */
|
||||
HOST_WIDE_INT gp_sp_offset; /* offset from new sp to store gp registers */
|
||||
HOST_WIDE_INT cprestore_size; /* # bytes that the .cprestore slot takes up */
|
||||
unsigned int mask; /* mask of saved gp registers */
|
||||
int num_gp; /* number of gp registers saved */
|
||||
};
|
||||
|
||||
typedef void (*score_save_restore_fn) (rtx, rtx);
|
||||
|
||||
int mda_valid_base_register_p (rtx x, int strict);
|
||||
|
||||
#ifdef RTX_CODE
|
||||
int mda_classify_address (struct score_address_info *info,
|
||||
enum machine_mode mode, rtx x, int strict);
|
||||
|
||||
struct score_frame_info *mda_compute_frame_size (HOST_WIDE_INT size);
|
||||
|
||||
struct score_frame_info *mda_cached_frame (void);
|
||||
|
||||
void mda_gen_cmp (enum machine_mode mode);
|
||||
#endif
|
||||
|
||||
int mda_symbolic_constant_p (rtx x, enum score_symbol_type *symbol_type);
|
||||
|
||||
bool mda_pindex_mem (rtx addr);
|
||||
|
||||
int mda_bp (void);
|
||||
|
||||
/* Machine Expand. */
|
||||
void mdx_prologue (void);
|
||||
|
||||
void mdx_epilogue (int sibcall_p);
|
||||
|
||||
void mdx_movsicc (rtx *ops);
|
||||
|
||||
void mdx_call (rtx *ops, bool sibcall);
|
||||
|
||||
void mdx_call_value (rtx *ops, bool sibcall);
|
||||
|
||||
/* Machine Split. */
|
||||
void mds_movdi (rtx *ops);
|
||||
|
||||
void mds_addsi (rtx *ops);
|
||||
|
||||
void mds_zero_extract_andi (rtx *ops);
|
||||
|
||||
/* Machine Print. */
|
||||
enum mda_mem_unit {MDA_BYTE = 0, MDA_HWORD = 1, MDA_WORD = 2};
|
||||
|
||||
#define MDA_ALIGN_UNIT(V, UNIT) !(V & ((1 << UNIT) - 1))
|
||||
|
||||
const char * mdp_linsn (rtx *ops, enum mda_mem_unit unit, bool sign);
|
||||
|
||||
const char * mdp_sinsn (rtx *ops, enum mda_mem_unit unit);
|
||||
|
||||
const char * mdp_add_imm_ucc (rtx *ops);
|
||||
|
||||
const char * mdp_select (rtx *ops, const char *inst_pre,
|
||||
bool comu, const char *let);
|
||||
|
||||
const char * mdp_limm (rtx *ops);
|
||||
|
||||
const char * mdp_move (rtx *ops);
|
||||
|
||||
#endif
|
||||
|
26
gcc/config/score/score-modes.def
Normal file
26
gcc/config/score/score-modes.def
Normal file
@ -0,0 +1,26 @@
|
||||
/* score-modes.def for Sunplus S+CORE processor
|
||||
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2, or (at your
|
||||
option) any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* CC_NZmode should be used if the N (sign) and Z (zero) flag is set correctly.
|
||||
CC_Nmode should be used if only the N flag is set correctly. */
|
||||
|
||||
CC_MODE (CC_NZ);
|
||||
CC_MODE (CC_N);
|
||||
|
92
gcc/config/score/score-protos.h
Normal file
92
gcc/config/score/score-protos.h
Normal file
@ -0,0 +1,92 @@
|
||||
/* score-protos.h for Sunplus S+CORE processor
|
||||
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2, or (at your
|
||||
option) any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifndef __SCORE_PROTOS_H__
|
||||
#define __SCORE_PROTOS_H__
|
||||
|
||||
extern enum reg_class score_char_to_class[];
|
||||
|
||||
void score_override_options (void);
|
||||
|
||||
void score_init_expanders (void);
|
||||
|
||||
int score_hard_regno_mode_ok (unsigned int, enum machine_mode);
|
||||
|
||||
int score_reg_class (int regno);
|
||||
|
||||
enum reg_class score_preferred_reload_class (rtx x, enum reg_class class);
|
||||
|
||||
enum reg_class score_secondary_reload_class (enum reg_class class,
|
||||
enum machine_mode mode, rtx x);
|
||||
|
||||
int score_const_ok_for_letter_p (int value, char c);
|
||||
|
||||
int score_extra_constraint (rtx op, char c);
|
||||
|
||||
rtx score_return_addr (int count, rtx frame);
|
||||
|
||||
HOST_WIDE_INT score_initial_elimination_offset (int from, int to);
|
||||
|
||||
rtx score_function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
||||
tree type, int named);
|
||||
|
||||
int score_arg_partial_nregs (const CUMULATIVE_ARGS *cum,
|
||||
enum machine_mode mode, tree type, int named);
|
||||
|
||||
void score_init_cumulative_args (CUMULATIVE_ARGS *cum,
|
||||
tree fntype, rtx libname);
|
||||
|
||||
void score_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
||||
tree type, int named);
|
||||
|
||||
rtx score_function_value (tree valtype, tree func, enum machine_mode mode);
|
||||
|
||||
rtx score_va_arg (tree va_list, tree type);
|
||||
|
||||
void score_initialize_trampoline (rtx ADDR, rtx FUNC, rtx CHAIN);
|
||||
|
||||
int score_address_p (enum machine_mode mode, rtx x, int strict);
|
||||
|
||||
int score_legitimize_address (rtx *xloc);
|
||||
|
||||
int score_regno_mode_ok_for_base_p (int regno, int strict);
|
||||
|
||||
int score_register_move_cost (enum machine_mode mode, enum reg_class to,
|
||||
enum reg_class from);
|
||||
|
||||
void score_declare_object (FILE *stream, const char *name,
|
||||
const char *directive, const char *fmt, ...);
|
||||
|
||||
void score_declare_object_name (FILE *stream, const char *name, tree decl);
|
||||
|
||||
int score_output_external (FILE *file, tree decl, const char *name);
|
||||
|
||||
void score_print_operand (FILE *file, rtx op, int letter);
|
||||
|
||||
void score_print_operand_address (FILE *file, rtx addr);
|
||||
|
||||
#ifdef RTX_CODE
|
||||
enum machine_mode score_select_cc_mode (enum rtx_code op, rtx x, rtx y);
|
||||
#endif
|
||||
|
||||
#include "score-mdaux.h"
|
||||
|
||||
#endif /* __SCORE_PROTOS_H__ */
|
||||
|
21
gcc/config/score/score-version.h
Normal file
21
gcc/config/score/score-version.h
Normal file
@ -0,0 +1,21 @@
|
||||
/* score-version.h for Sunplus S+CORE processor
|
||||
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2, or (at your
|
||||
option) any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define SCORE_GCC_VERSION "1.1"
|
1071
gcc/config/score/score.c
Normal file
1071
gcc/config/score/score.c
Normal file
File diff suppressed because it is too large
Load Diff
909
gcc/config/score/score.h
Normal file
909
gcc/config/score/score.h
Normal file
@ -0,0 +1,909 @@
|
||||
/* score.h for Sunplus S+CORE processor
|
||||
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
Contributed by Sunnorth.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2, or (at your
|
||||
option) any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "score-conv.h"
|
||||
#include "score-version.h"
|
||||
|
||||
/* Define the information needed to generate branch insns. This is
|
||||
stored from the compare operation. */
|
||||
extern GTY(()) rtx cmp_op0;
|
||||
extern GTY(()) rtx cmp_op1;
|
||||
|
||||
/* Controlling the Compilation Driver. */
|
||||
#define SWITCH_TAKES_ARG(CHAR) \
|
||||
(DEFAULT_SWITCH_TAKES_ARG (CHAR) || (CHAR) == 'G')
|
||||
|
||||
/* CC1_SPEC is the set of arguments to pass to the compiler proper. */
|
||||
#undef CC1_SPEC
|
||||
#define CC1_SPEC "%{!mel:-meb}"
|
||||
|
||||
#undef ASM_SPEC
|
||||
#define ASM_SPEC \
|
||||
"%{!mel:-EB} %{mel:-EL} %{mSCORE5U:-SCORE5U} %{mSCORE7:-SCORE7} %{G*}"
|
||||
|
||||
#undef LINK_SPEC
|
||||
#define LINK_SPEC "%{!mel:-EB} %{mel:-EL} %{G*}"
|
||||
|
||||
/* Run-time Target Specification. */
|
||||
#define TARGET_CPU_CPP_BUILTINS() \
|
||||
do { \
|
||||
builtin_define ("SUNPLUS"); \
|
||||
builtin_define ("__SCORE__"); \
|
||||
builtin_define ("__score__"); \
|
||||
if (TARGET_LITTLE_ENDIAN) \
|
||||
builtin_define ("__scorele__"); \
|
||||
else \
|
||||
builtin_define ("__scorebe__"); \
|
||||
if (TARGET_SCORE5U) \
|
||||
builtin_define ("__score5u__"); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define TARGET_DEFAULT MASK_SCORE7
|
||||
|
||||
#define TARGET_VERSION \
|
||||
fprintf (stderr, "Sunplus S+CORE %s", SCORE_GCC_VERSION);
|
||||
|
||||
#define OVERRIDE_OPTIONS score_override_options ()
|
||||
|
||||
/* Show we can debug even without a frame pointer. */
|
||||
#define CAN_DEBUG_WITHOUT_FP
|
||||
|
||||
/* Target machine storage layout. */
|
||||
#define BITS_BIG_ENDIAN 0
|
||||
#define BYTES_BIG_ENDIAN (TARGET_LITTLE_ENDIAN == 0)
|
||||
#define WORDS_BIG_ENDIAN (TARGET_LITTLE_ENDIAN == 0)
|
||||
|
||||
/* Define this to set the endianness to use in libgcc2.c, which can
|
||||
not depend on target_flags. */
|
||||
#if defined(__scorele__)
|
||||
#define LIBGCC2_WORDS_BIG_ENDIAN 0
|
||||
#else
|
||||
#define LIBGCC2_WORDS_BIG_ENDIAN 1
|
||||
#endif
|
||||
|
||||
/* Width of a word, in units (bytes). */
|
||||
#define UNITS_PER_WORD 4
|
||||
|
||||
/* Define this macro if it is advisable to hold scalars in registers
|
||||
in a wider mode than that declared by the program. In such cases,
|
||||
the value is constrained to be within the bounds of the declared
|
||||
type, but kept valid in the wider mode. The signedness of the
|
||||
extension may differ from that of the type. */
|
||||
#define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \
|
||||
if (GET_MODE_CLASS (MODE) == MODE_INT \
|
||||
&& GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \
|
||||
(MODE) = SImode;
|
||||
|
||||
/* Allocation boundary (in *bits*) for storing arguments in argument list. */
|
||||
#define PARM_BOUNDARY BITS_PER_WORD
|
||||
#define STACK_BOUNDARY 64
|
||||
|
||||
/* Allocation boundary (in *bits*) for the code of a function. */
|
||||
#define FUNCTION_BOUNDARY BITS_PER_WORD
|
||||
|
||||
/* There is no point aligning anything to a rounder boundary than this. */
|
||||
#define BIGGEST_ALIGNMENT LONG_DOUBLE_TYPE_SIZE
|
||||
|
||||
/* If defined, a C expression to compute the alignment for a static
|
||||
variable. TYPE is the data type, and ALIGN is the alignment that
|
||||
the object would ordinarily have. The value of this macro is used
|
||||
instead of that alignment to align the object.
|
||||
|
||||
If this macro is not defined, then ALIGN is used.
|
||||
|
||||
One use of this macro is to increase alignment of medium-size
|
||||
data to make it all fit in fewer cache lines. Another is to
|
||||
cause character arrays to be word-aligned so that `strcpy' calls
|
||||
that copy constants to character arrays can be done inline. */
|
||||
#define DATA_ALIGNMENT(TYPE, ALIGN) \
|
||||
((((ALIGN) < BITS_PER_WORD) \
|
||||
&& (TREE_CODE (TYPE) == ARRAY_TYPE \
|
||||
|| TREE_CODE (TYPE) == UNION_TYPE \
|
||||
|| TREE_CODE (TYPE) == RECORD_TYPE)) ? BITS_PER_WORD : (ALIGN))
|
||||
|
||||
/* Alignment of field after `int : 0' in a structure. */
|
||||
#define EMPTY_FIELD_BOUNDARY 32
|
||||
|
||||
/* All accesses must be aligned. */
|
||||
#define STRICT_ALIGNMENT 1
|
||||
|
||||
/* Score requires that structure alignment is affected by bitfields. */
|
||||
#define PCC_BITFIELD_TYPE_MATTERS 1
|
||||
|
||||
/* long double is not a fixed mode, but the idea is that, if we
|
||||
support long double, we also want a 128-bit integer type. */
|
||||
#define MAX_FIXED_MODE_SIZE LONG_DOUBLE_TYPE_SIZE
|
||||
|
||||
#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
|
||||
|
||||
/* Layout of Data Type. */
|
||||
/* Set the sizes of the core types. */
|
||||
#define INT_TYPE_SIZE 32
|
||||
#define SHORT_TYPE_SIZE 16
|
||||
#define LONG_TYPE_SIZE 32
|
||||
#define LONG_LONG_TYPE_SIZE 64
|
||||
#define CHAR_TYPE_SIZE 8
|
||||
#define FLOAT_TYPE_SIZE 32
|
||||
#define DOUBLE_TYPE_SIZE 64
|
||||
#define LONG_DOUBLE_TYPE_SIZE 64
|
||||
|
||||
/* Define this as 1 if `char' should by default be signed; else as 0. */
|
||||
#undef DEFAULT_SIGNED_CHAR
|
||||
#define DEFAULT_SIGNED_CHAR 1
|
||||
|
||||
/* Default definitions for size_t and ptrdiff_t. */
|
||||
#define SIZE_TYPE "unsigned int"
|
||||
|
||||
/* Register Usage
|
||||
|
||||
S+core have:
|
||||
- 32 integer registers
|
||||
- 16 control registers (cond)
|
||||
- 16 special registers (ceh/cel/cnt/lcr/scr/arg/fp)
|
||||
- 32 coprocessors 1 registers
|
||||
- 32 coprocessors 2 registers
|
||||
- 32 coprocessors 3 registers. */
|
||||
#define FIRST_PSEUDO_REGISTER 160
|
||||
|
||||
/* By default, fix the kernel registers (r30 and r31), the global
|
||||
pointer (r28) and the stack pointer (r0). This can change
|
||||
depending on the command-line options.
|
||||
|
||||
Regarding coprocessor registers: without evidence to the contrary,
|
||||
it's best to assume that each coprocessor register has a unique
|
||||
use. This can be overridden, in, e.g., override_options() or
|
||||
CONDITIONAL_REGISTER_USAGE should the assumption be inappropriate
|
||||
for a particular target. */
|
||||
|
||||
/* Control Registers, use mfcr/mtcr insn
|
||||
32 cr0 PSR
|
||||
33 cr1 Condition
|
||||
34 cr2 ECR
|
||||
35 cr3 EXCPVec
|
||||
36 cr4 CCR
|
||||
37 cr5 EPC
|
||||
38 cr6 EMA
|
||||
39 cr7 TLBLock
|
||||
40 cr8 TLBPT
|
||||
41 cr8 PEADDR
|
||||
42 cr10 TLBRPT
|
||||
43 cr11 PEVN
|
||||
44 cr12 PECTX
|
||||
45 cr13
|
||||
46 cr14
|
||||
47 cr15
|
||||
|
||||
Custom Engine Register, use mfce/mtce
|
||||
48 CEH CEH
|
||||
49 CEL CEL
|
||||
|
||||
Special-Purpose Register, use mfsr/mtsr
|
||||
50 sr0 CNT
|
||||
51 sr1 LCR
|
||||
52 sr2 SCR
|
||||
|
||||
53 ARG_POINTER_REGNUM
|
||||
54 FRAME_POINTER_REGNUM
|
||||
but Control register have 32 registers, cr16-cr31. */
|
||||
#define FIXED_REGISTERS \
|
||||
{ \
|
||||
/* General Purpose Registers */ \
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, \
|
||||
/* Control Regisers */ \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
/* CEH/ CEL/ CNT/ LCR/ SCR / ARG_POINTER_REGNUM/ FRAME_POINTER_REGNUM */\
|
||||
0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
/* CP 1 Registers */ \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
/* CP 2 Registers */ \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
/* CP 3 Registers*/ \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
}
|
||||
|
||||
#define CALL_USED_REGISTERS \
|
||||
{ \
|
||||
/* General purpose register */ \
|
||||
1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
/* Control Regisers */ \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
/* CP 1 Registers */ \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
/* CP 2 Registers */ \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
/* CP 3 Registers */ \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
}
|
||||
|
||||
#define REG_ALLOC_ORDER \
|
||||
{ 0, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, \
|
||||
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 2, 3, \
|
||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, \
|
||||
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, \
|
||||
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, \
|
||||
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, \
|
||||
96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, \
|
||||
112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, \
|
||||
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, \
|
||||
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159 }
|
||||
|
||||
#define HARD_REGNO_NREGS(REGNO, MODE) \
|
||||
((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
|
||||
|
||||
/* Return true if REGNO is suitable for holding a quantity of type MODE. */
|
||||
#define HARD_REGNO_MODE_OK(REGNO, MODE) score_hard_regno_mode_ok (REGNO, MODE)
|
||||
|
||||
/* Value is 1 if it is a good idea to tie two pseudo registers
|
||||
when one has mode MODE1 and one has mode MODE2.
|
||||
If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
|
||||
for any hard reg, then this must be 0 for correct output. */
|
||||
#define MODES_TIEABLE_P(MODE1, MODE2) \
|
||||
((GET_MODE_CLASS (MODE1) == MODE_FLOAT \
|
||||
|| GET_MODE_CLASS (MODE1) == MODE_COMPLEX_FLOAT) \
|
||||
== (GET_MODE_CLASS (MODE2) == MODE_FLOAT \
|
||||
|| GET_MODE_CLASS (MODE2) == MODE_COMPLEX_FLOAT))
|
||||
|
||||
/* Register Classes. */
|
||||
/* Define the classes of registers for register constraints in the
|
||||
machine description. Also define ranges of constants. */
|
||||
enum reg_class
|
||||
{
|
||||
NO_REGS,
|
||||
G16_REGS, /* r0 ~ r15 */
|
||||
G32_REGS, /* r0 ~ r31 */
|
||||
T32_REGS, /* r8 ~ r11 | r22 ~ r27 */
|
||||
|
||||
HI_REG, /* hi */
|
||||
LO_REG, /* lo */
|
||||
CE_REGS, /* hi + lo */
|
||||
|
||||
CN_REG, /* cnt */
|
||||
LC_REG, /* lcb */
|
||||
SC_REG, /* scb */
|
||||
SP_REGS, /* cnt + lcb + scb */
|
||||
|
||||
CR_REGS, /* cr0 - cr15 */
|
||||
|
||||
CP1_REGS, /* cp1 */
|
||||
CP2_REGS, /* cp2 */
|
||||
CP3_REGS, /* cp3 */
|
||||
CPA_REGS, /* cp1 + cp2 + cp3 */
|
||||
|
||||
ALL_REGS,
|
||||
LIM_REG_CLASSES
|
||||
};
|
||||
|
||||
#define N_REG_CLASSES ((int) LIM_REG_CLASSES)
|
||||
|
||||
#define GENERAL_REGS G32_REGS
|
||||
|
||||
/* Give names of register classes as strings for dump file. */
|
||||
#define REG_CLASS_NAMES \
|
||||
{ \
|
||||
"NO_REGS", \
|
||||
"G16_REGS", \
|
||||
"G32_REGS", \
|
||||
"T32_REGS", \
|
||||
\
|
||||
"HI_REG", \
|
||||
"LO_REG", \
|
||||
"CE_REGS", \
|
||||
\
|
||||
"CN_REG", \
|
||||
"LC_REG", \
|
||||
"SC_REG", \
|
||||
"SP_REGS", \
|
||||
\
|
||||
"CR_REGS", \
|
||||
\
|
||||
"CP1_REGS", \
|
||||
"CP2_REGS", \
|
||||
"CP3_REGS", \
|
||||
"CPA_REGS", \
|
||||
\
|
||||
"ALL_REGS", \
|
||||
}
|
||||
|
||||
/* Define which registers fit in which classes. */
|
||||
#define REG_CLASS_CONTENTS \
|
||||
{ \
|
||||
/* NO_REGS/G16/G32/T32 */ \
|
||||
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, \
|
||||
{ 0x0000ffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, \
|
||||
{ 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, \
|
||||
{ 0x0fc00f00, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, \
|
||||
/* HI/LO/CE */ \
|
||||
{ 0x00000000, 0x00010000, 0x00000000, 0x00000000, 0x00000000}, \
|
||||
{ 0x00000000, 0x00020000, 0x00000000, 0x00000000, 0x00000000}, \
|
||||
{ 0x00000000, 0x00030000, 0x00000000, 0x00000000, 0x00000000}, \
|
||||
/* CN/LC/SC/SP/CR */ \
|
||||
{ 0x00000000, 0x00040000, 0x00000000, 0x00000000, 0x00000000}, \
|
||||
{ 0x00000000, 0x00080000, 0x00000000, 0x00000000, 0x00000000}, \
|
||||
{ 0x00000000, 0x00100000, 0x00000000, 0x00000000, 0x00000000}, \
|
||||
{ 0x00000000, 0x001c0000, 0x00000000, 0x00000000, 0x00000000}, \
|
||||
{ 0x00000000, 0x0000ffff, 0x00000000, 0x00000000, 0x00000000}, \
|
||||
/* CP1/CP2/CP3/CPA */ \
|
||||
{ 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000}, \
|
||||
{ 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000}, \
|
||||
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff}, \
|
||||
{ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff}, \
|
||||
/* ALL_REGS */ \
|
||||
{ 0xffffffff, 0x001fffff, 0xffffffff, 0xffffffff, 0xffffffff}, \
|
||||
}
|
||||
|
||||
/* A C expression whose value is a register class containing hard
|
||||
register REGNO. In general there is more that one such class;
|
||||
choose a class which is "minimal", meaning that no smaller class
|
||||
also contains the register. */
|
||||
#define REGNO_REG_CLASS(REGNO) score_reg_class (REGNO)
|
||||
|
||||
/* A macro whose definition is the name of the class to which a
|
||||
valid base register must belong. A base register is one used in
|
||||
an address which is the register value plus a displacement. */
|
||||
#define BASE_REG_CLASS G16_REGS
|
||||
|
||||
/* The class value for index registers. */
|
||||
#define INDEX_REG_CLASS NO_REGS
|
||||
|
||||
#define REG_CLASS_FROM_LETTER(C) score_char_to_class[(unsigned char) (C)]
|
||||
|
||||
/* Addressing modes, and classification of registers for them. */
|
||||
#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \
|
||||
score_regno_mode_ok_for_base_p (REGNO, 1)
|
||||
|
||||
#define REGNO_OK_FOR_INDEX_P(NUM) 0
|
||||
|
||||
#define PREFERRED_RELOAD_CLASS(X, CLASS) \
|
||||
score_preferred_reload_class (X, CLASS)
|
||||
|
||||
/* If we need to load shorts byte-at-a-time, then we need a scratch. */
|
||||
#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \
|
||||
score_secondary_reload_class (CLASS, MODE, X)
|
||||
|
||||
/* Return the register class of a scratch register needed to copy IN into
|
||||
or out of a register in CLASS in MODE. If it can be done directly,
|
||||
NO_REGS is returned. */
|
||||
#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \
|
||||
score_secondary_reload_class (CLASS, MODE, X)
|
||||
|
||||
/* Return the maximum number of consecutive registers
|
||||
needed to represent mode MODE in a register of class CLASS. */
|
||||
#define CLASS_MAX_NREGS(CLASS, MODE) \
|
||||
((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
|
||||
|
||||
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
|
||||
(GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
|
||||
? reg_classes_intersect_p (HI_REG, (CLASS)) : 0)
|
||||
|
||||
/* The letters I, J, K, L, M, N, O, and P in a register constraint
|
||||
string can be used to stand for particular ranges of immediate
|
||||
operands. This macro defines what the ranges are. C is the
|
||||
letter, and VALUE is a constant value. Return 1 if VALUE is
|
||||
in the range specified by C. */
|
||||
#define CONST_OK_FOR_LETTER_P(VALUE, C) score_const_ok_for_letter_p (VALUE, C)
|
||||
|
||||
/* Similar, but for floating constants, and defining letters G and H.
|
||||
Here VALUE is the CONST_DOUBLE rtx itself. */
|
||||
|
||||
#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
|
||||
((C) == 'G' && (VALUE) == CONST0_RTX (GET_MODE (VALUE)))
|
||||
|
||||
/* Letters in the range `Q' through `U' may be defined in a
|
||||
machine-dependent fashion to stand for arbitrary operand types.
|
||||
The machine description macro `EXTRA_CONSTRAINT' is passed the
|
||||
operand as its first argument and the constraint letter as its
|
||||
second operand. */
|
||||
#define EXTRA_CONSTRAINT(VALUE, C) score_extra_constraint (VALUE, C)
|
||||
|
||||
/* Basic Stack Layout. */
|
||||
/* Stack layout; function entry, exit and calling. */
|
||||
#define STACK_GROWS_DOWNWARD
|
||||
|
||||
#define STACK_PUSH_CODE PRE_DEC
|
||||
#define STACK_POP_CODE POST_INC
|
||||
|
||||
/* The offset of the first local variable from the beginning of the frame.
|
||||
See compute_frame_size for details about the frame layout. */
|
||||
#define STARTING_FRAME_OFFSET current_function_outgoing_args_size
|
||||
|
||||
/* The argument pointer always points to the first argument. */
|
||||
#define FIRST_PARM_OFFSET(FUNDECL) 0
|
||||
|
||||
/* A C expression whose value is RTL representing the value of the return
|
||||
address for the frame COUNT steps up from the current frame. */
|
||||
#define RETURN_ADDR_RTX(count, frame) score_return_addr (count, frame)
|
||||
|
||||
/* Pick up the return address upon entry to a procedure. */
|
||||
#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (VOIDmode, RA_REGNUM)
|
||||
|
||||
/* Exception handling Support. */
|
||||
/* Use r0 to r3 to pass exception handling information. */
|
||||
#define EH_RETURN_DATA_REGNO(N) \
|
||||
((N) < 4 ? (N) + ARG_REG_FIRST : INVALID_REGNUM)
|
||||
|
||||
/* The register that holds the return address in exception handlers. */
|
||||
#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, EH_REGNUM)
|
||||
|
||||
/* Registers That Address the Stack Frame. */
|
||||
/* Register to use for pushing function arguments. */
|
||||
#define STACK_POINTER_REGNUM SP_REGNUM
|
||||
|
||||
/* These two registers don't really exist: they get eliminated to either
|
||||
the stack or hard frame pointer. */
|
||||
#define FRAME_POINTER_REGNUM 53
|
||||
|
||||
/* we use r2 as the frame pointer. */
|
||||
#define HARD_FRAME_POINTER_REGNUM FP_REGNUM
|
||||
|
||||
#define ARG_POINTER_REGNUM 54
|
||||
|
||||
/* Register in which static-chain is passed to a function. */
|
||||
#define STATIC_CHAIN_REGNUM 23
|
||||
|
||||
/* Elimination Frame Pointer and Arg Pointer */
|
||||
/* Value should be nonzero if functions must have frame pointers.
|
||||
Zero means the frame pointer need not be set up (and parms
|
||||
may be accessed via the stack pointer) in functions that seem suitable.
|
||||
This is computed in `reload', in reload1.c. */
|
||||
#define FRAME_POINTER_REQUIRED current_function_calls_alloca
|
||||
|
||||
#define ELIMINABLE_REGS \
|
||||
{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
|
||||
{ ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
|
||||
{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
|
||||
{ FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
|
||||
|
||||
/* We can always eliminate to the hard frame pointer. We can eliminate
|
||||
to the stack pointer unless a frame pointer is needed. */
|
||||
#define CAN_ELIMINATE(FROM, TO) \
|
||||
(((TO) == HARD_FRAME_POINTER_REGNUM) \
|
||||
|| ((TO) == STACK_POINTER_REGNUM \
|
||||
&& !frame_pointer_needed))
|
||||
|
||||
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
|
||||
(OFFSET) = score_initial_elimination_offset ((FROM), (TO))
|
||||
|
||||
/* Passing Function Arguments on the Stack. */
|
||||
/* Allocate stack space for arguments at the beginning of each function. */
|
||||
#define ACCUMULATE_OUTGOING_ARGS 1
|
||||
|
||||
/* reserve stack space for all argument registers. */
|
||||
#define REG_PARM_STACK_SPACE(FNDECL) UNITS_PER_WORD
|
||||
|
||||
/* Define this if it is the responsibility of the caller to
|
||||
allocate the area reserved for arguments passed in registers.
|
||||
If `ACCUMULATE_OUTGOING_ARGS' is also defined, the only effect
|
||||
of this macro is to determine whether the space is included in
|
||||
`current_function_outgoing_args_size'. */
|
||||
#define OUTGOING_REG_PARM_STACK_SPACE
|
||||
|
||||
#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0
|
||||
|
||||
/* Passing Arguments in Registers */
|
||||
/* Determine where to put an argument to a function.
|
||||
Value is zero to push the argument on the stack,
|
||||
or a hard register in which to store the argument.
|
||||
|
||||
MODE is the argument's machine mode.
|
||||
TYPE is the data type of the argument (as a tree).
|
||||
This is null for libcalls where that information may
|
||||
not be available.
|
||||
CUM is a variable of type CUMULATIVE_ARGS which gives info about
|
||||
the preceding args and about the function being called.
|
||||
NAMED is nonzero if this argument is a named parameter
|
||||
(otherwise it is an extra parameter matching an ellipsis). */
|
||||
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
|
||||
score_function_arg (&CUM, MODE, TYPE, NAMED)
|
||||
|
||||
/* A C type for declaring a variable that is used as the first argument of
|
||||
`FUNCTION_ARG' and other related values. For some target machines, the
|
||||
type `int' suffices and can hold the number of bytes of argument so far. */
|
||||
typedef struct score_args
|
||||
{
|
||||
unsigned int arg_number; /* how many arguments have been seen */
|
||||
unsigned int num_gprs; /* number of gprs in use */
|
||||
unsigned int stack_words; /* number of words in stack */
|
||||
} score_args_t;
|
||||
|
||||
#define CUMULATIVE_ARGS score_args_t
|
||||
|
||||
/* Initialize a variable CUM of type CUMULATIVE_ARGS
|
||||
for a call to a function whose data type is FNTYPE.
|
||||
For a library call, FNTYPE is 0. */
|
||||
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, n_named_args) \
|
||||
score_init_cumulative_args (&CUM, FNTYPE, LIBNAME)
|
||||
|
||||
/* Update the data in CUM to advance over an argument
|
||||
of mode MODE and data type TYPE.
|
||||
(TYPE is null for libcalls where that information may not be available.) */
|
||||
#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
|
||||
score_function_arg_advance (&CUM, MODE, TYPE, NAMED)
|
||||
|
||||
/* 1 if N is a possible register number for function argument passing.
|
||||
We have no FP argument registers when soft-float. When FP registers
|
||||
are 32 bits, we can't directly reference the odd numbered ones. */
|
||||
#define FUNCTION_ARG_REGNO_P(REGNO) \
|
||||
REG_CONTAIN (REGNO, ARG_REG_FIRST, ARG_REG_NUM)
|
||||
|
||||
/* How Scalar Function Values Are Returned. */
|
||||
#define FUNCTION_VALUE(VALTYPE, FUNC) \
|
||||
score_function_value ((VALTYPE), (FUNC), VOIDmode)
|
||||
|
||||
#define LIBCALL_VALUE(MODE) score_function_value (NULL_TREE, NULL, (MODE))
|
||||
|
||||
/* 1 if N is a possible register number for a function value. */
|
||||
#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == (ARG_REG_FIRST))
|
||||
|
||||
#define PIC_FUNCTION_ADDR_REGNUM (GP_REG_FIRST + 25)
|
||||
|
||||
/* How Large Values Are Returned. */
|
||||
#define STRUCT_VALUE 0
|
||||
|
||||
/* Function Entry and Exit */
|
||||
/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
|
||||
the stack pointer does not matter. The value is tested only in
|
||||
functions that have frame pointers.
|
||||
No definition is equivalent to always zero. */
|
||||
#define EXIT_IGNORE_STACK 1
|
||||
|
||||
/* Generating Code for Profiling */
|
||||
/* Output assembler code to FILE to increment profiler label # LABELNO
|
||||
for profiling a function entry. */
|
||||
#define FUNCTION_PROFILER(FILE, LABELNO) \
|
||||
{ \
|
||||
fprintf (FILE, " .set r1 \n"); \
|
||||
fprintf (FILE, " mv r%d,r%d \n", AT_REGNUM, RA_REGNUM); \
|
||||
fprintf (FILE, " subi r%d, %d \n", STACK_POINTER_REGNUM, 8); \
|
||||
fprintf (FILE, " jl _mcount \n"); \
|
||||
fprintf (FILE, " .set nor1 \n"); \
|
||||
}
|
||||
|
||||
/* Trampolines for Nested Functions. */
|
||||
#define TRAMPOLINE_INSNS 8
|
||||
|
||||
/* A C expression for the size in bytes of the trampoline, as an integer. */
|
||||
#define TRAMPOLINE_SIZE \
|
||||
(TRAMPOLINE_INSNS * GET_MODE_SIZE (SImode) + GET_MODE_SIZE (ptr_mode) * 2)
|
||||
|
||||
/* A C statement to initialize the variable parts of a trampoline.
|
||||
ADDR is an RTX for the address of the trampoline; FNADDR is an
|
||||
RTX for the address of the nested function; STATIC_CHAIN is an
|
||||
RTX for the static chain value that should be passed to the
|
||||
function when it is called. */
|
||||
|
||||
#define INITIALIZE_TRAMPOLINE(ADDR, FUNC, CHAIN) \
|
||||
score_initialize_trampoline (ADDR, FUNC, CHAIN)
|
||||
|
||||
#define HAVE_PRE_INCREMENT 1
|
||||
#define HAVE_PRE_DECREMENT 1
|
||||
#define HAVE_POST_INCREMENT 1
|
||||
#define HAVE_POST_DECREMENT 1
|
||||
#define HAVE_PRE_MODIFY_DISP 0
|
||||
#define HAVE_POST_MODIFY_DISP 0
|
||||
#define HAVE_PRE_MODIFY_REG 0
|
||||
#define HAVE_POST_MODIFY_REG 0
|
||||
|
||||
/* Recognize any constant value that is a valid address. */
|
||||
#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X)
|
||||
|
||||
/* Maximum number of registers that can appear in a valid memory address. */
|
||||
#define MAX_REGS_PER_ADDRESS 1
|
||||
|
||||
#ifdef REG_OK_STRICT
|
||||
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \
|
||||
if (score_address_p (MODE, X, 1)) \
|
||||
goto LABEL;
|
||||
#else
|
||||
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \
|
||||
if (score_address_p (MODE, X, 0)) \
|
||||
goto LABEL;
|
||||
#endif
|
||||
|
||||
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
|
||||
and check its validity for a certain class.
|
||||
We have two alternate definitions for each of them.
|
||||
The usual definition accepts all pseudo regs; the other rejects them all.
|
||||
The symbol REG_OK_STRICT causes the latter definition to be used.
|
||||
|
||||
Most source files want to accept pseudo regs in the hope that
|
||||
they will get allocated to the class that the insn wants them to be in.
|
||||
Some source files that are used after register allocation
|
||||
need to be strict. */
|
||||
#ifndef REG_OK_STRICT
|
||||
#define REG_MODE_OK_FOR_BASE_P(X, MODE) \
|
||||
score_regno_mode_ok_for_base_p (REGNO (X), 0)
|
||||
#else
|
||||
#define REG_MODE_OK_FOR_BASE_P(X, MODE) \
|
||||
score_regno_mode_ok_for_base_p (REGNO (X), 1)
|
||||
#endif
|
||||
|
||||
#define REG_OK_FOR_INDEX_P(X) 0
|
||||
|
||||
#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
|
||||
do { \
|
||||
if (score_legitimize_address (&(X))) \
|
||||
goto WIN; \
|
||||
} while (0)
|
||||
|
||||
/* Go to LABEL if ADDR (a legitimate address expression)
|
||||
has an effect that depends on the machine mode it is used for. */
|
||||
#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) {}
|
||||
|
||||
#define LEGITIMATE_CONSTANT_P(X) 1
|
||||
|
||||
/* Describing Relative Costs of Operations */
|
||||
/* Compute extra cost of moving data between one register class and another. */
|
||||
#define REGISTER_MOVE_COST(MODE, FROM, TO) \
|
||||
score_register_move_cost (MODE, FROM, TO)
|
||||
|
||||
/* Moves to and from memory are quite expensive */
|
||||
#define MEMORY_MOVE_COST(MODE, CLASS, TO_P) \
|
||||
(4 + memory_move_secondary_cost ((MODE), (CLASS), (TO_P)))
|
||||
|
||||
/* Try to generate sequences that don't involve branches. */
|
||||
#define BRANCH_COST 2
|
||||
|
||||
/* Nonzero if access to memory by bytes is slow and undesirable. */
|
||||
#define SLOW_BYTE_ACCESS 1
|
||||
|
||||
/* Define this macro if it is as good or better to call a constant
|
||||
function address than to call an address kept in a register. */
|
||||
#define NO_FUNCTION_CSE 1
|
||||
|
||||
/* Dividing the Output into Sections (Texts, Data, ...). */
|
||||
/* Define the strings to put out for each section in the object file. */
|
||||
#define TEXT_SECTION_ASM_OP "\t.text"
|
||||
#define DATA_SECTION_ASM_OP "\t.data"
|
||||
#define SDATA_SECTION_ASM_OP "\t.sdata"
|
||||
|
||||
#undef READONLY_DATA_SECTION_ASM_OP
|
||||
#define READONLY_DATA_SECTION_ASM_OP "\t.rdata"
|
||||
|
||||
/* The Overall Framework of an Assembler File */
|
||||
/* How to start an assembler comment.
|
||||
The leading space is important. */
|
||||
#define ASM_COMMENT_START "#"
|
||||
|
||||
/* Output to assembler file text saying following lines
|
||||
may contain character constants, extra white space, comments, etc. */
|
||||
#define ASM_APP_ON "#APP\n\t.set volatile\n"
|
||||
|
||||
/* Output to assembler file text saying following lines
|
||||
no longer contain unusual constructs. */
|
||||
#define ASM_APP_OFF "#NO_APP\n\t.set optimize\n"
|
||||
|
||||
/* Output of Uninitialized Variables. */
|
||||
/* This says how to define a global common symbol. */
|
||||
#define ASM_OUTPUT_ALIGNED_DECL_COMMON(STREAM, DECL, NAME, SIZE, ALIGN) \
|
||||
score_declare_object (STREAM, NAME, "\n\t.comm\t", \
|
||||
","HOST_WIDE_INT_PRINT_UNSIGNED",%u\n", \
|
||||
SIZE, ALIGN / BITS_PER_UNIT);
|
||||
|
||||
/* This says how to define a local common symbol (i.e., not visible to
|
||||
linker). */
|
||||
#undef ASM_OUTPUT_ALIGNED_LOCAL
|
||||
#define ASM_OUTPUT_ALIGNED_LOCAL(STREAM, NAME, SIZE, ALIGN) \
|
||||
score_declare_object (STREAM, NAME, "\n\t.lcomm\t", \
|
||||
","HOST_WIDE_INT_PRINT_UNSIGNED",%u\n", \
|
||||
SIZE, ALIGN / BITS_PER_UNIT);
|
||||
|
||||
/* Globalizing directive for a label. */
|
||||
#define GLOBAL_ASM_OP "\t.globl\t"
|
||||
|
||||
/* Output and Generation of Labels */
|
||||
/* This is how to declare a function name. The actual work of
|
||||
emitting the label is moved to function_prologue, so that we can
|
||||
get the line number correctly emitted before the .ent directive,
|
||||
and after any .file directives. Define as empty so that the function
|
||||
is not declared before the .ent directive elsewhere. */
|
||||
#undef ASM_DECLARE_FUNCTION_NAME
|
||||
#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL)
|
||||
|
||||
#undef ASM_DECLARE_OBJECT_NAME
|
||||
#define ASM_DECLARE_OBJECT_NAME(STREAM, NAME, DECL) \
|
||||
score_declare_object (STREAM, NAME, "", ":\n", 0)
|
||||
|
||||
/* This says how to output an external. It would be possible not to
|
||||
output anything and let undefined symbol become external. However
|
||||
the assembler uses length information on externals to allocate in
|
||||
data/sdata bss/sbss, thereby saving exec time. */
|
||||
#define ASM_OUTPUT_EXTERNAL(STREAM, DECL, NAME) \
|
||||
score_output_external (STREAM, DECL, NAME)
|
||||
|
||||
/* This handles the magic '..CURRENT_FUNCTION' symbol, which means
|
||||
'the start of the function that this code is output in'. */
|
||||
#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
|
||||
fprintf ((STREAM), "%s", (NAME))
|
||||
|
||||
/* Local compiler-generated symbols must have a prefix that the assembler
|
||||
understands. */
|
||||
#define LOCAL_LABEL_PREFIX "."
|
||||
|
||||
#undef ASM_GENERATE_INTERNAL_LABEL
|
||||
#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \
|
||||
sprintf ((LABEL), "*%s%s%ld", (LOCAL_LABEL_PREFIX), (PREFIX), (long) (NUM))
|
||||
|
||||
/* Output of Assembler Instructions. */
|
||||
#define REGISTER_NAMES \
|
||||
{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
|
||||
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \
|
||||
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \
|
||||
"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", \
|
||||
\
|
||||
"cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
|
||||
"cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15", \
|
||||
\
|
||||
"ceh", "cel", "sr0", "sr1", "sr2", "_arg", "_frame", "", \
|
||||
"cr24", "cr25", "cr26", "cr27", "cr28", "cr29", "cr30", "cr31", \
|
||||
\
|
||||
"c1r0", "c1r1", "c1r2", "c1r3", "c1r4", "c1r5", "c1r6", "c1r7", \
|
||||
"c1r8", "c1r9", "c1r10", "c1r11", "c1r12", "c1r13", "c1r14", "c1r15", \
|
||||
"c1r16", "c1r17", "c1r18", "c1r19", "c1r20", "c1r21", "c1r22", "c1r23",\
|
||||
"c1r24", "c1r25", "c1r26", "c1r27", "c1r28", "c1r29", "c1r30", "c1r31",\
|
||||
\
|
||||
"c2r0", "c2r1", "c2r2", "c2r3", "c2r4", "c2r5", "c2r6", "c2r7", \
|
||||
"c2r8", "c2r9", "c2r10", "c2r11", "c2r12", "c2r13", "c2r14", "c2r15", \
|
||||
"c2r16", "c2r17", "c2r18", "c2r19", "c2r20", "c2r21", "c2r22", "c2r23",\
|
||||
"c2r24", "c2r25", "c2r26", "c2r27", "c2r28", "c2r29", "c2r30", "c2r31",\
|
||||
\
|
||||
"c3r0", "c3r1", "c3r2", "c3r3", "c3r4", "c3r5", "c3r6", "c3r7", \
|
||||
"c3r8", "c3r9", "c3r10", "c3r11", "c3r12", "c3r13", "c3r14", "c3r15", \
|
||||
"c3r16", "c3r17", "c3r18", "c3r19", "c3r20", "c3r21", "c3r22", "c3r23",\
|
||||
"c3r24", "c3r25", "c3r26", "c3r27", "c3r28", "c3r29", "c3r30", "c3r31",\
|
||||
}
|
||||
|
||||
/* Print operand X (an rtx) in assembler syntax to file FILE. */
|
||||
#define PRINT_OPERAND(STREAM, X, CODE) score_print_operand (STREAM, X, CODE)
|
||||
|
||||
/* A C expression which evaluates to true if CODE is a valid
|
||||
punctuation character for use in the `PRINT_OPERAND' macro. */
|
||||
#define PRINT_OPERAND_PUNCT_VALID_P(C) ((C) == '[' || (C) == ']')
|
||||
|
||||
/* Print a memory address as an operand to reference that memory location. */
|
||||
#define PRINT_OPERAND_ADDRESS(STREAM, X) \
|
||||
score_print_operand_address (STREAM, X)
|
||||
|
||||
/* By default on the S+core, external symbols do not have an underscore
|
||||
prepended. */
|
||||
#define USER_LABEL_PREFIX ""
|
||||
|
||||
/* This is how to output an insn to push a register on the stack. */
|
||||
#define ASM_OUTPUT_REG_PUSH(STREAM, REGNO) \
|
||||
do { \
|
||||
fprintf (STREAM, "\tpush! %s,[%s]\n", \
|
||||
reg_names[REGNO], \
|
||||
reg_names[STACK_POINTER_REGNUM]); \
|
||||
} while (0)
|
||||
|
||||
/* This is how to output an insn to pop a register from the stack. */
|
||||
#define ASM_OUTPUT_REG_POP(STREAM, REGNO) \
|
||||
do { \
|
||||
fprintf (STREAM, "\tpop! %s,[%s]\n", \
|
||||
reg_names[REGNO], \
|
||||
reg_names[STACK_POINTER_REGNUM]); \
|
||||
} while (0)
|
||||
|
||||
/* Output of Dispatch Tables. */
|
||||
/* This is how to output an element of a case-vector. We can make the
|
||||
entries PC-relative in GP-relative when .gp(d)word is supported. */
|
||||
#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \
|
||||
do { \
|
||||
if (flag_pic) \
|
||||
fprintf (STREAM, "\t.gpword %sL%d\n", LOCAL_LABEL_PREFIX, VALUE); \
|
||||
else \
|
||||
fprintf (STREAM, "\t.word %sL%d\n", LOCAL_LABEL_PREFIX, VALUE); \
|
||||
} while (0)
|
||||
|
||||
/* This is how to output an element of a case-vector that is absolute. */
|
||||
#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
|
||||
fprintf (STREAM, "\t.word %sL%d\n", LOCAL_LABEL_PREFIX, VALUE)
|
||||
|
||||
/* Assembler Commands for Exception Regions */
|
||||
/* Since the S+core is encoded in the least-significant bit
|
||||
of the address, mask it off return addresses for purposes of
|
||||
finding exception handling regions. */
|
||||
#define MASK_RETURN_ADDR constm1_rtx
|
||||
|
||||
/* Assembler Commands for Alignment */
|
||||
/* This is how to output an assembler line to advance the location
|
||||
counter by SIZE bytes. */
|
||||
#undef ASM_OUTPUT_SKIP
|
||||
#define ASM_OUTPUT_SKIP(STREAM, SIZE) \
|
||||
fprintf (STREAM, "\t.space\t"HOST_WIDE_INT_PRINT_UNSIGNED"\n", (SIZE))
|
||||
|
||||
/* This is how to output an assembler line
|
||||
that says to advance the location counter
|
||||
to a multiple of 2**LOG bytes. */
|
||||
#define ASM_OUTPUT_ALIGN(STREAM, LOG) \
|
||||
fprintf (STREAM, "\t.align\t%d\n", (LOG))
|
||||
|
||||
/* Macros Affecting All Debugging Formats. */
|
||||
#ifndef PREFERRED_DEBUGGING_TYPE
|
||||
#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
|
||||
#endif
|
||||
|
||||
/* Specific Options for DBX Output. */
|
||||
#define DBX_DEBUGGING_INFO 1
|
||||
|
||||
/* By default, turn on GDB extensions. */
|
||||
#define DEFAULT_GDB_EXTENSIONS 1
|
||||
|
||||
#define DBX_CONTIN_LENGTH 0
|
||||
|
||||
/* File Names in DBX Format. */
|
||||
#define DWARF2_DEBUGGING_INFO 1
|
||||
|
||||
/* The DWARF 2 CFA column which tracks the return address. */
|
||||
#define DWARF_FRAME_RETURN_COLUMN 3
|
||||
|
||||
/* Specify the machine mode that this machine uses
|
||||
for the index in the tablejump instruction. */
|
||||
#define CASE_VECTOR_MODE SImode
|
||||
|
||||
/* Define if operations between registers always perform the operation
|
||||
on the full register even if a narrower mode is specified. */
|
||||
#define WORD_REGISTER_OPERATIONS
|
||||
|
||||
/* All references are zero extended. */
|
||||
#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND
|
||||
|
||||
/* Define if loading short immediate values into registers sign extends. */
|
||||
#define SHORT_IMMEDIATES_SIGN_EXTEND
|
||||
|
||||
/* Max number of bytes we can move from memory to memory
|
||||
in one reasonably fast instruction. */
|
||||
#define MOVE_MAX 4
|
||||
|
||||
/* Define this to be nonzero if shift instructions ignore all but the low-order
|
||||
few bits. */
|
||||
#define SHIFT_COUNT_TRUNCATED 1
|
||||
|
||||
/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
|
||||
is done just by pretending it is already truncated. */
|
||||
#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
|
||||
|
||||
/* Specify the machine mode that pointers have.
|
||||
After generation of rtl, the compiler makes no further distinction
|
||||
between pointers and any other objects of this machine mode. */
|
||||
#define Pmode SImode
|
||||
|
||||
/* Give call MEMs SImode since it is the "most permissive" mode
|
||||
for 32-bit targets. */
|
||||
#define FUNCTION_MODE Pmode
|
||||
|
||||
struct extern_list GTY ((chain_next ("%h.next")))
|
||||
{
|
||||
struct extern_list *next; /* next external */
|
||||
const char *name; /* name of the external */
|
||||
int size; /* size in bytes */
|
||||
};
|
||||
|
||||
extern GTY (()) struct extern_list *extern_head ;
|
1253
gcc/config/score/score.md
Normal file
1253
gcc/config/score/score.md
Normal file
File diff suppressed because it is too large
Load Diff
53
gcc/config/score/score.opt
Normal file
53
gcc/config/score/score.opt
Normal file
@ -0,0 +1,53 @@
|
||||
; Options for the Sunnorth port of the compiler.
|
||||
|
||||
; Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
;
|
||||
; This file is part of GCC.
|
||||
;
|
||||
; GCC is free software; you can redistribute it and/or modify it under
|
||||
; the terms of the GNU General Public License as published by the Free
|
||||
; Software Foundation; either version 2, or (at your option) any later
|
||||
; version.
|
||||
;
|
||||
; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
; WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
; for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with GCC; see the file COPYING. If not, write to the Free
|
||||
; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
; 02110-1301, USA.
|
||||
|
||||
meb
|
||||
Target RejectNegative Report InverseMask(LITTLE_ENDIAN)
|
||||
Generate big-endian code
|
||||
|
||||
mel
|
||||
Target RejectNegative Report Mask(LITTLE_ENDIAN)
|
||||
Generate little-endian code
|
||||
|
||||
mnpi
|
||||
Target RejectNegative Report Mask(NOPINDEX)
|
||||
Do not use pre/post index
|
||||
|
||||
mnuls
|
||||
Target RejectNegative Report Mask(NOUNALIGNED)
|
||||
Do not use unaligned load/store
|
||||
|
||||
mmac
|
||||
Target RejectNegative Report Mask(MAC)
|
||||
Enable mac instruction
|
||||
|
||||
mSCORE5
|
||||
Target RejectNegative Report Mask(SCORE5)
|
||||
Support SCORE 5 ISA
|
||||
|
||||
mSCORE5U
|
||||
Target RejectNegative Report Mask(SCORE5U)
|
||||
Support SCORE 5U ISA
|
||||
|
||||
mSCORE7
|
||||
Target RejectNegative Report Mask(SCORE7)
|
||||
Support SCORE 7 ISA
|
||||
|
46
gcc/config/score/score7.md
Normal file
46
gcc/config/score/score7.md
Normal file
@ -0,0 +1,46 @@
|
||||
;; Machine description for Sunplus S+CORE
|
||||
;; Sunplus S+CORE 7 Pipeline Description
|
||||
;; Copyright (C) 2005
|
||||
;; Free Software Foundation, Inc.
|
||||
;; Contributed by Sunnorth.
|
||||
|
||||
;; This file is part of GCC.
|
||||
|
||||
;; GCC is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation; either version 2, or (at your option)
|
||||
;; any later version.
|
||||
|
||||
;; GCC is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GCC; see the file COPYING. If not, write to
|
||||
;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
;; Boston, MA 02110-1301, USA.
|
||||
|
||||
(define_automaton "score")
|
||||
|
||||
(define_cpu_unit "core" "score")
|
||||
|
||||
(define_insn_reservation "memory" 3
|
||||
(eq_attr "type" "load")
|
||||
"core")
|
||||
|
||||
(define_insn_reservation "mul" 3
|
||||
(eq_attr "type" "mul,div")
|
||||
"core")
|
||||
|
||||
(define_insn_reservation "fce" 1
|
||||
(eq_attr "type" "fce")
|
||||
"core")
|
||||
|
||||
(define_insn_reservation "tsr" 1
|
||||
(eq_attr "type" "tsr,fsr")
|
||||
"core")
|
||||
|
||||
(define_insn_reservation "up_c" 1
|
||||
(eq_attr "up_c" "yes")
|
||||
"core")
|
44
gcc/config/score/t-score-elf
Normal file
44
gcc/config/score/t-score-elf
Normal file
@ -0,0 +1,44 @@
|
||||
# Additional Backend Files
|
||||
score-mdaux.o: $(srcdir)/config/score/score-mdaux.c $(CONFIG_H) $(SYSTEM_H) \
|
||||
coretypes.h $(TM_H) $(RTL_H) output.h flags.h $(TREE_H) \
|
||||
expr.h toplev.h $(TM_P_H)
|
||||
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
|
||||
$(srcdir)/config/score/score-mdaux.c
|
||||
|
||||
# Assemble startup files.
|
||||
$(T)crti.o: $(srcdir)/config/score/crti.asm $(GCC_PASSES)
|
||||
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
|
||||
-c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/score/crti.asm
|
||||
|
||||
$(T)crtn.o: $(srcdir)/config/score/crtn.asm $(GCC_PASSES)
|
||||
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
|
||||
-c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/score/crtn.asm
|
||||
|
||||
LIB1ASMSRC = score/mul-div.S
|
||||
|
||||
LIB1ASMFUNCS = _mulsi3 _divsi3 _flush_cache
|
||||
|
||||
FPBIT = fp-bit.c
|
||||
DPBIT = dp-bit.c
|
||||
|
||||
# If any special flags are necessary when building libgcc2 put them here.
|
||||
TARGET_LIBGCC2_CFLAGS = -g
|
||||
|
||||
fp-bit.c: $(srcdir)/config/fp-bit.c
|
||||
echo '#define FLOAT' > fp-bit.c
|
||||
cat $(srcdir)/config/fp-bit.c >> fp-bit.c
|
||||
|
||||
dp-bit.c: $(srcdir)/config/fp-bit.c
|
||||
cat $(srcdir)/config/fp-bit.c > dp-bit.c
|
||||
|
||||
# We must build libgcc2.a with -G 0, in case the user wants to link
|
||||
# without the $gp register.
|
||||
TARGET_LIBGCC2_CFLAGS = -G 0
|
||||
|
||||
MULTILIB_OPTIONS = mel mSCORE7
|
||||
EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
|
||||
|
||||
LIBGCC = stmp-multilib
|
||||
INSTALL_LIBGCC = install-multilib
|
||||
|
||||
|
2
gcc/configure
vendored
2
gcc/configure
vendored
@ -15619,7 +15619,7 @@ esac
|
||||
case "$target" in
|
||||
i?86*-*-* | mips*-*-* | alpha*-*-* | powerpc*-*-* | sparc*-*-* | m68*-*-* \
|
||||
| x86_64*-*-* | hppa*-*-* | arm*-*-* | strongarm*-*-* | xscale*-*-* \
|
||||
| xstormy16*-*-* | cris-*-* | xtensa-*-* | bfin-*-*)
|
||||
| xstormy16*-*-* | cris-*-* | xtensa-*-* | bfin-*-* | score*-*-*)
|
||||
insn="nop"
|
||||
;;
|
||||
ia64*-*-* | s390*-*-*)
|
||||
|
Loading…
Reference in New Issue
Block a user