mirror of git://gcc.gnu.org/git/gcc.git
258 lines
7.6 KiB
C
258 lines
7.6 KiB
C
/* Intrinsic functions of Andes NDS32 cpu for GNU compiler
|
|
Copyright (C) 2012-2014 Free Software Foundation, Inc.
|
|
Contributed by Andes Technology Corporation.
|
|
|
|
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 3, 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 COPYING3. If not see
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
#include "config.h"
|
|
#include "system.h"
|
|
#include "coretypes.h"
|
|
#include "tm.h"
|
|
#include "tree.h"
|
|
#include "stor-layout.h"
|
|
#include "varasm.h"
|
|
#include "calls.h"
|
|
#include "rtl.h"
|
|
#include "regs.h"
|
|
#include "hard-reg-set.h"
|
|
#include "insn-config.h" /* Required by recog.h. */
|
|
#include "conditions.h"
|
|
#include "output.h"
|
|
#include "insn-attr.h" /* For DFA state_t. */
|
|
#include "insn-codes.h" /* For CODE_FOR_xxx. */
|
|
#include "reload.h" /* For push_reload(). */
|
|
#include "flags.h"
|
|
#include "hashtab.h"
|
|
#include "hash-set.h"
|
|
#include "vec.h"
|
|
#include "machmode.h"
|
|
#include "input.h"
|
|
#include "function.h"
|
|
#include "expr.h"
|
|
#include "recog.h"
|
|
#include "diagnostic-core.h"
|
|
#include "df.h"
|
|
#include "tm_p.h"
|
|
#include "tm-constrs.h"
|
|
#include "optabs.h" /* For GEN_FCN. */
|
|
#include "target.h"
|
|
#include "target-def.h"
|
|
#include "langhooks.h" /* For add_builtin_function(). */
|
|
#include "ggc.h"
|
|
#include "builtins.h"
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
/* Function to expand builtin function for
|
|
'[(unspec_volatile [(reg)])]'. */
|
|
static rtx
|
|
nds32_expand_builtin_null_ftype_reg (enum insn_code icode,
|
|
tree exp, rtx target)
|
|
{
|
|
/* Mapping:
|
|
ops[0] <--> value0 <--> arg0 */
|
|
struct expand_operand ops[1];
|
|
tree arg0;
|
|
rtx value0;
|
|
|
|
/* Grab the incoming arguments and extract its rtx. */
|
|
arg0 = CALL_EXPR_ARG (exp, 0);
|
|
value0 = expand_normal (arg0);
|
|
|
|
/* Create operands. */
|
|
create_input_operand (&ops[0], value0, TYPE_MODE (TREE_TYPE (arg0)));
|
|
|
|
/* Emit new instruction. */
|
|
if (!maybe_expand_insn (icode, 1, ops))
|
|
error ("invalid argument to built-in function");
|
|
|
|
return target;
|
|
}
|
|
|
|
/* Function to expand builtin function for
|
|
'[(set (reg) (unspec_volatile [(imm)]))]'. */
|
|
static rtx
|
|
nds32_expand_builtin_reg_ftype_imm (enum insn_code icode,
|
|
tree exp, rtx target)
|
|
{
|
|
/* Mapping:
|
|
ops[0] <--> target <--> exp
|
|
ops[1] <--> value0 <--> arg0 */
|
|
struct expand_operand ops[2];
|
|
tree arg0;
|
|
rtx value0;
|
|
|
|
/* Grab the incoming arguments and extract its rtx. */
|
|
arg0 = CALL_EXPR_ARG (exp, 0);
|
|
value0 = expand_normal (arg0);
|
|
|
|
/* Create operands. */
|
|
create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (exp)));
|
|
create_input_operand (&ops[1], value0, TYPE_MODE (TREE_TYPE (arg0)));
|
|
|
|
/* Emit new instruction. */
|
|
if (!maybe_expand_insn (icode, 2, ops))
|
|
error ("invalid argument to built-in function");
|
|
|
|
return target;
|
|
}
|
|
|
|
/* Function to expand builtin function for
|
|
'[(unspec_volatile [(reg) (imm)])]' pattern. */
|
|
static rtx
|
|
nds32_expand_builtin_null_ftype_reg_imm (enum insn_code icode,
|
|
tree exp, rtx target)
|
|
{
|
|
/* Mapping:
|
|
ops[0] <--> value0 <--> arg0
|
|
ops[1] <--> value1 <--> arg1 */
|
|
struct expand_operand ops[2];
|
|
tree arg0, arg1;
|
|
rtx value0, value1;
|
|
|
|
/* Grab the incoming arguments and extract its rtx. */
|
|
arg0 = CALL_EXPR_ARG (exp, 0);
|
|
arg1 = CALL_EXPR_ARG (exp, 1);
|
|
value0 = expand_normal (arg0);
|
|
value1 = expand_normal (arg1);
|
|
|
|
/* Create operands. */
|
|
create_input_operand (&ops[0], value0, TYPE_MODE (TREE_TYPE (arg0)));
|
|
create_input_operand (&ops[1], value1, TYPE_MODE (TREE_TYPE (arg1)));
|
|
|
|
/* Emit new instruction. */
|
|
if (!maybe_expand_insn (icode, 2, ops))
|
|
error ("invalid argument to built-in function");
|
|
|
|
return target;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
void
|
|
nds32_init_builtins_impl (void)
|
|
{
|
|
tree pointer_type_node = build_pointer_type (integer_type_node);
|
|
|
|
tree void_ftype_void = build_function_type (void_type_node,
|
|
void_list_node);
|
|
|
|
tree void_ftype_pint = build_function_type_list (void_type_node,
|
|
pointer_type_node,
|
|
NULL_TREE);
|
|
|
|
tree int_ftype_int = build_function_type_list (integer_type_node,
|
|
integer_type_node,
|
|
NULL_TREE);
|
|
|
|
tree void_ftype_int_int = build_function_type_list (void_type_node,
|
|
integer_type_node,
|
|
integer_type_node,
|
|
NULL_TREE);
|
|
|
|
/* Cache. */
|
|
add_builtin_function ("__builtin_nds32_isync", void_ftype_pint,
|
|
NDS32_BUILTIN_ISYNC,
|
|
BUILT_IN_MD, NULL, NULL_TREE);
|
|
add_builtin_function ("__builtin_nds32_isb", void_ftype_void,
|
|
NDS32_BUILTIN_ISB,
|
|
BUILT_IN_MD, NULL, NULL_TREE);
|
|
|
|
/* Register Transfer. */
|
|
add_builtin_function ("__builtin_nds32_mfsr", int_ftype_int,
|
|
NDS32_BUILTIN_MFSR,
|
|
BUILT_IN_MD, NULL, NULL_TREE);
|
|
add_builtin_function ("__builtin_nds32_mfusr", int_ftype_int,
|
|
NDS32_BUILTIN_MFUSR,
|
|
BUILT_IN_MD, NULL, NULL_TREE);
|
|
add_builtin_function ("__builtin_nds32_mtsr", void_ftype_int_int,
|
|
NDS32_BUILTIN_MTSR,
|
|
BUILT_IN_MD, NULL, NULL_TREE);
|
|
add_builtin_function ("__builtin_nds32_mtusr", void_ftype_int_int,
|
|
NDS32_BUILTIN_MTUSR,
|
|
BUILT_IN_MD, NULL, NULL_TREE);
|
|
|
|
/* Interrupt. */
|
|
add_builtin_function ("__builtin_nds32_setgie_en", void_ftype_void,
|
|
NDS32_BUILTIN_SETGIE_EN,
|
|
BUILT_IN_MD, NULL, NULL_TREE);
|
|
add_builtin_function ("__builtin_nds32_setgie_dis", void_ftype_void,
|
|
NDS32_BUILTIN_SETGIE_DIS,
|
|
BUILT_IN_MD, NULL, NULL_TREE);
|
|
}
|
|
|
|
|
|
rtx
|
|
nds32_expand_builtin_impl (tree exp,
|
|
rtx target,
|
|
rtx subtarget ATTRIBUTE_UNUSED,
|
|
enum machine_mode mode ATTRIBUTE_UNUSED,
|
|
int ignore ATTRIBUTE_UNUSED)
|
|
{
|
|
tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
|
|
|
|
int fcode = DECL_FUNCTION_CODE (fndecl);
|
|
|
|
switch (fcode)
|
|
{
|
|
/* Cache. */
|
|
case NDS32_BUILTIN_ISYNC:
|
|
return nds32_expand_builtin_null_ftype_reg
|
|
(CODE_FOR_unspec_volatile_isync, exp, target);
|
|
case NDS32_BUILTIN_ISB:
|
|
/* Since there are no result and operands for isb instruciton,
|
|
we can simply emit this rtx. */
|
|
emit_insn (gen_unspec_volatile_isb ());
|
|
return target;
|
|
|
|
/* Register Transfer. */
|
|
case NDS32_BUILTIN_MFSR:
|
|
return nds32_expand_builtin_reg_ftype_imm
|
|
(CODE_FOR_unspec_volatile_mfsr, exp, target);
|
|
case NDS32_BUILTIN_MFUSR:
|
|
return nds32_expand_builtin_reg_ftype_imm
|
|
(CODE_FOR_unspec_volatile_mfusr, exp, target);
|
|
case NDS32_BUILTIN_MTSR:
|
|
return nds32_expand_builtin_null_ftype_reg_imm
|
|
(CODE_FOR_unspec_volatile_mtsr, exp, target);
|
|
case NDS32_BUILTIN_MTUSR:
|
|
return nds32_expand_builtin_null_ftype_reg_imm
|
|
(CODE_FOR_unspec_volatile_mtusr, exp, target);
|
|
|
|
/* Interrupt. */
|
|
case NDS32_BUILTIN_SETGIE_EN:
|
|
/* Since there are no result and operands for setgie.e instruciton,
|
|
we can simply emit this rtx. */
|
|
emit_insn (gen_unspec_volatile_setgie_en ());
|
|
return target;
|
|
case NDS32_BUILTIN_SETGIE_DIS:
|
|
/* Since there are no result and operands for setgie.d instruciton,
|
|
we can simply emit this rtx. */
|
|
emit_insn (gen_unspec_volatile_setgie_dis ());
|
|
return target;
|
|
|
|
default:
|
|
gcc_unreachable ();
|
|
}
|
|
|
|
return NULL_RTX;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------ */
|