URL
https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk
Subversion Repositories openrisc_2011-10-31
Compare Revisions
- This comparison shows the changes necessary to convert path
/openrisc/tags/gnu-src/gcc-4.5.1/gcc-4.5.1-or32-1.0rc2/gcc/config/score
- from Rev 282 to Rev 384
- ↔ Reverse comparison
Rev 282 → Rev 384
/score3.c
0,0 → 1,1959
/* score3.c for Sunplus S+CORE processor |
Copyright (C) 2005, 2007, 2008 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 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 "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 "score3.h" |
#include "df.h" |
|
#define BITSET_P(VALUE, BIT) (((VALUE) & (1L << (BIT))) != 0) |
#define INS_BUF_SZ 128 |
|
extern enum reg_class score_char_to_class[256]; |
|
static int score3_sdata_max; |
static char score3_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 |
score3_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 |
score3_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 |
score3_classify_symbol (rtx x) |
{ |
if (GET_CODE (x) == LABEL_REF) |
return SYMBOL_GENERAL; |
|
gcc_assert (GET_CODE (x) == SYMBOL_REF); |
|
if (CONSTANT_POOL_ADDRESS_P (x)) |
{ |
if (GET_MODE_SIZE (get_pool_mode (x)) <= SCORE3_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 |
score3_save_reg_p (unsigned int regno) |
{ |
/* Check call-saved registers. */ |
if (df_regs_ever_live_p (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 && df_regs_ever_live_p (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 |
score3_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); |
} |
|
static struct score3_frame_info * |
score3_cached_frame (void) |
{ |
static struct score3_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. */ |
static struct score3_frame_info * |
score3_compute_frame_size (HOST_WIDE_INT size) |
{ |
unsigned int regno; |
struct score3_frame_info *f = score3_cached_frame (); |
|
memset (f, 0, sizeof (struct score3_frame_info)); |
f->gp_reg_size = 0; |
f->mask = 0; |
f->var_size = SCORE3_STACK_ALIGN (size); |
f->args_size = crtl->outgoing_args_size; |
f->cprestore_size = flag_pic ? UNITS_PER_WORD : 0; |
|
if (f->var_size == 0 && current_function_is_leaf) |
f->args_size = f->cprestore_size = 0; |
|
if (f->args_size == 0 && cfun->calls_alloca) |
f->args_size = UNITS_PER_WORD; |
|
f->total_size = f->var_size + f->args_size + f->cprestore_size; |
for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) |
{ |
if (score3_save_reg_p (regno)) |
{ |
f->gp_reg_size += GET_MODE_SIZE (SImode); |
f->mask |= 1 << (regno - GP_REG_FIRST); |
} |
} |
|
if (crtl->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 += 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; |
|
return f; |
} |
|
/* Return true if X is a valid base register for the given mode. |
Allow only hard registers if STRICT. */ |
static int |
score3_valid_base_register_p (rtx x, int strict) |
{ |
if (!strict && GET_CODE (x) == SUBREG) |
x = SUBREG_REG (x); |
|
return (GET_CODE (x) == REG |
&& score3_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. */ |
static int |
score3_classify_address (struct score3_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 = SCORE3_ADD_REG; |
info->reg = x; |
info->offset = const0_rtx; |
return score3_valid_base_register_p (info->reg, strict); |
case PLUS: |
info->type = SCORE3_ADD_REG; |
info->reg = XEXP (x, 0); |
info->offset = XEXP (x, 1); |
return (score3_valid_base_register_p (info->reg, strict) |
&& GET_CODE (info->offset) == CONST_INT |
&& IMM_IN_RANGE (INTVAL (info->offset), 15, 1)); |
case PRE_DEC: |
case POST_DEC: |
case PRE_INC: |
case POST_INC: |
if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (SImode)) |
return false; |
info->type = SCORE3_ADD_REG; |
info->reg = XEXP (x, 0); |
info->offset = GEN_INT (GET_MODE_SIZE (mode)); |
return score3_valid_base_register_p (info->reg, strict); |
case CONST_INT: |
info->type = SCORE3_ADD_CONST_INT; |
return 1; |
case CONST: |
case LABEL_REF: |
case SYMBOL_REF: |
info->type = SCORE3_ADD_SYMBOLIC; |
return (score3_symbolic_constant_p (x, &info->symbol_type) |
&& (info->symbol_type == SYMBOL_GENERAL |
|| info->symbol_type == SYMBOL_SMALL_DATA)); |
default: |
return 0; |
} |
} |
|
bool |
score3_return_in_memory (tree type, tree fndecl ATTRIBUTE_UNUSED) |
{ |
return ((TYPE_MODE (type) == BLKmode) |
|| (int_size_in_bytes (type) > 2 * UNITS_PER_WORD) |
|| (int_size_in_bytes (type) == -1)); |
} |
|
/* Return a legitimate address for REG + OFFSET. */ |
static rtx |
score3_add_offset (rtx reg, HOST_WIDE_INT offset) |
{ |
if (!IMM_IN_RANGE (offset, 15, 1)) |
{ |
reg = expand_simple_binop (GET_MODE (reg), PLUS, |
gen_int_mode (offset & 0xffffc000, |
GET_MODE (reg)), |
reg, NULL, 0, OPTAB_WIDEN); |
offset &= 0x3fff; |
} |
|
return plus_constant (reg, offset); |
} |
|
/* Implement TARGET_ASM_OUTPUT_MI_THUNK. Generate rtl rather than asm text |
in order to avoid duplicating too much logic from elsewhere. */ |
void |
score3_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, |
HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset, |
tree function) |
{ |
rtx this_rtx, temp1, insn, fnaddr; |
|
/* Pretend to be a post-reload pass while generating rtl. */ |
reload_completed = 1; |
|
/* Mark the end of the (empty) prologue. */ |
emit_note (NOTE_INSN_PROLOGUE_END); |
|
/* We need two temporary registers in some cases. */ |
temp1 = gen_rtx_REG (Pmode, 8); |
|
/* Find out which register contains the "this" pointer. */ |
if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)) |
this_rtx = gen_rtx_REG (Pmode, ARG_REG_FIRST + 1); |
else |
this_rtx = gen_rtx_REG (Pmode, ARG_REG_FIRST); |
|
/* Add DELTA to THIS_RTX. */ |
if (delta != 0) |
{ |
rtx offset = GEN_INT (delta); |
if (!CONST_OK_FOR_LETTER_P (delta, 'L')) |
{ |
emit_move_insn (temp1, offset); |
offset = temp1; |
} |
emit_insn (gen_add3_insn (this_rtx, this_rtx, offset)); |
} |
|
/* If needed, add *(*THIS_RTX + VCALL_OFFSET) to THIS_RTX. */ |
if (vcall_offset != 0) |
{ |
rtx addr; |
|
/* Set TEMP1 to *THIS_RTX. */ |
emit_move_insn (temp1, gen_rtx_MEM (Pmode, this_rtx)); |
|
/* Set ADDR to a legitimate address for *THIS_RTX + VCALL_OFFSET. */ |
addr = score3_add_offset (temp1, vcall_offset); |
|
/* Load the offset and add it to THIS_RTX. */ |
emit_move_insn (temp1, gen_rtx_MEM (Pmode, addr)); |
emit_insn (gen_add3_insn (this_rtx, this_rtx, temp1)); |
} |
|
/* Jump to the target function. */ |
fnaddr = XEXP (DECL_RTL (function), 0); |
insn = emit_call_insn (gen_sibcall_internal_score3 (fnaddr, const0_rtx)); |
SIBLING_CALL_P (insn) = 1; |
|
/* Run just enough of rest_of_compilation. This sequence was |
"borrowed" from alpha.c. */ |
insn = get_insns (); |
insn_locators_alloc (); |
split_all_insns_noflow (); |
shorten_branches (insn); |
final_start_function (insn, file, 1); |
final (insn, file, 1); |
final_end_function (); |
|
/* Clean up the vars set above. Note that final_end_function resets |
the global pointer for us. */ |
reload_completed = 0; |
} |
|
/* Copy VALUE to a register and return that register. If new psuedos |
are allowed, copy it into a new register, otherwise use DEST. */ |
static rtx |
score3_force_temporary (rtx dest, rtx value) |
{ |
if (can_create_pseudo_p ()) |
return force_reg (Pmode, value); |
else |
{ |
emit_move_insn (copy_rtx (dest), value); |
return dest; |
} |
} |
|
/* Return a LO_SUM expression for ADDR. TEMP is as for score_force_temporary |
and is used to load the high part into a register. */ |
static rtx |
score3_split_symbol (rtx temp, rtx addr) |
{ |
rtx high = score3_force_temporary (temp, |
gen_rtx_HIGH (Pmode, copy_rtx (addr))); |
return gen_rtx_LO_SUM (Pmode, high, addr); |
} |
|
/* This function is used to implement LEGITIMIZE_ADDRESS. If X can |
be legitimized in a way that the generic machinery might not expect, |
return the new address. */ |
rtx |
score3_legitimize_address (rtx x) |
{ |
enum score_symbol_type symbol_type; |
|
if (score3_symbolic_constant_p (x, &symbol_type) |
&& symbol_type == SYMBOL_GENERAL) |
return score3_split_symbol (0, x); |
|
if (GET_CODE (x) == PLUS |
&& GET_CODE (XEXP (x, 1)) == CONST_INT) |
{ |
rtx reg = XEXP (x, 0); |
if (!score3_valid_base_register_p (reg, 0)) |
reg = copy_to_mode_reg (Pmode, reg); |
return score3_add_offset (reg, INTVAL (XEXP (x, 1))); |
} |
|
return x; |
} |
|
/* Fill INFO with information about a single argument. CUM is the |
cumulative state for earlier arguments. MODE is the mode of this |
argument and TYPE is its type (if known). NAMED is true if this |
is a named (fixed) argument rather than a variable one. */ |
static void |
score3_classify_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode, |
tree type, int named, struct score3_arg_info *info) |
{ |
int even_reg_p; |
unsigned int num_words, max_regs; |
|
even_reg_p = 0; |
if (GET_MODE_CLASS (mode) == MODE_INT |
|| GET_MODE_CLASS (mode) == MODE_FLOAT) |
even_reg_p = (GET_MODE_SIZE (mode) > UNITS_PER_WORD); |
else |
if (type != NULL_TREE && TYPE_ALIGN (type) > BITS_PER_WORD && named) |
even_reg_p = 1; |
|
if (TARGET_MUST_PASS_IN_STACK (mode, type)) |
info->reg_offset = ARG_REG_NUM; |
else |
{ |
info->reg_offset = cum->num_gprs; |
if (even_reg_p) |
info->reg_offset += info->reg_offset & 1; |
} |
|
if (mode == BLKmode) |
info->num_bytes = int_size_in_bytes (type); |
else |
info->num_bytes = GET_MODE_SIZE (mode); |
|
num_words = (info->num_bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; |
max_regs = ARG_REG_NUM - info->reg_offset; |
|
/* Partition the argument between registers and stack. */ |
info->reg_words = MIN (num_words, max_regs); |
info->stack_words = num_words - info->reg_words; |
|
/* The alignment applied to registers is also applied to stack arguments. */ |
if (info->stack_words) |
{ |
info->stack_offset = cum->stack_words; |
if (even_reg_p) |
info->stack_offset += info->stack_offset & 1; |
} |
} |
|
/* Set up the stack and frame (if desired) for the function. */ |
void |
score3_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED) |
{ |
const char *fnname; |
struct score3_frame_info *f = score3_cached_frame (); |
HOST_WIDE_INT tsize = f->total_size; |
|
fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0); |
if (!flag_inhibit_size_directive) |
{ |
fputs ("\t.ent\t", file); |
assemble_name (file, fnname); |
fputs ("\n", file); |
} |
assemble_name (file, fnname); |
fputs (":\n", file); |
|
if (!flag_inhibit_size_directive) |
{ |
fprintf (file, |
"\t.frame\t%s," HOST_WIDE_INT_PRINT_DEC ",%s, %d\t\t" |
"# vars= " HOST_WIDE_INT_PRINT_DEC ", regs= %d" |
", args= " HOST_WIDE_INT_PRINT_DEC |
", gp= " HOST_WIDE_INT_PRINT_DEC "\n", |
(reg_names[(frame_pointer_needed) |
? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM]), |
tsize, |
reg_names[RA_REGNUM], |
current_function_is_leaf ? 1 : 0, |
f->var_size, |
f->num_gp, |
f->args_size, |
f->cprestore_size); |
|
fprintf(file, "\t.mask\t0x%08x," HOST_WIDE_INT_PRINT_DEC "\n", |
f->mask, |
(f->gp_sp_offset - f->total_size)); |
} |
} |
|
/* Do any necessary cleanup after a function to restore stack, frame, |
and regs. */ |
void |
score3_function_epilogue (FILE *file, |
HOST_WIDE_INT size ATTRIBUTE_UNUSED) |
{ |
if (!flag_inhibit_size_directive) |
{ |
const char *fnname; |
fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0); |
fputs ("\t.end\t", file); |
assemble_name (file, fnname); |
fputs ("\n", file); |
} |
} |
|
/* Returns true if X contains a SYMBOL_REF. */ |
static bool |
score3_symbolic_expression_p (rtx x) |
{ |
if (GET_CODE (x) == SYMBOL_REF) |
return true; |
|
if (GET_CODE (x) == CONST) |
return score3_symbolic_expression_p (XEXP (x, 0)); |
|
if (UNARY_P (x)) |
return score3_symbolic_expression_p (XEXP (x, 0)); |
|
if (ARITHMETIC_P (x)) |
return (score3_symbolic_expression_p (XEXP (x, 0)) |
|| score3_symbolic_expression_p (XEXP (x, 1))); |
|
return false; |
} |
|
/* Choose the section to use for the constant rtx expression X that has |
mode MODE. */ |
section * |
score3_select_rtx_section (enum machine_mode mode, rtx x, |
unsigned HOST_WIDE_INT align) |
{ |
if (GET_MODE_SIZE (mode) <= SCORE3_SDATA_MAX) |
return get_named_section (0, ".sdata", 0); |
else if (flag_pic && score3_symbolic_expression_p (x)) |
return get_named_section (0, ".data.rel.ro", 3); |
else |
return mergeable_constant_section (mode, align, 0); |
} |
|
/* Implement TARGET_IN_SMALL_DATA_P. */ |
bool |
score3_in_small_data_p (tree decl) |
{ |
HOST_WIDE_INT size; |
|
if (TREE_CODE (decl) == STRING_CST |
|| TREE_CODE (decl) == FUNCTION_DECL) |
return false; |
|
if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl) != 0) |
{ |
const char *name; |
name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl)); |
if (strcmp (name, ".sdata") != 0 |
&& strcmp (name, ".sbss") != 0) |
return true; |
if (!DECL_EXTERNAL (decl)) |
return false; |
} |
size = int_size_in_bytes (TREE_TYPE (decl)); |
return (size > 0 && size <= SCORE3_SDATA_MAX); |
} |
|
/* Implement TARGET_ASM_FILE_START. */ |
void |
score3_asm_file_start (void) |
{ |
default_file_start (); |
fprintf (asm_out_file, ASM_COMMENT_START |
"GCC for S+core %s \n", SCORE_GCC_VERSION); |
|
if (flag_pic) |
fprintf (asm_out_file, "\t.set pic\n"); |
} |
|
/* Implement TARGET_ASM_FILE_END. When using assembler macros, emit |
.externs for any small-data variables that turned out to be external. */ |
void |
score3_asm_file_end (void) |
{ |
tree name_tree; |
struct extern_list *p; |
if (extern_head) |
{ |
fputs ("\n", asm_out_file); |
for (p = extern_head; p != 0; p = p->next) |
{ |
name_tree = get_identifier (p->name); |
if (!TREE_ASM_WRITTEN (name_tree) |
&& TREE_SYMBOL_REFERENCED (name_tree)) |
{ |
TREE_ASM_WRITTEN (name_tree) = 1; |
fputs ("\t.extern\t", asm_out_file); |
assemble_name (asm_out_file, p->name); |
fprintf (asm_out_file, ", %d\n", p->size); |
} |
} |
} |
} |
|
/* Implement OVERRIDE_OPTIONS macro. */ |
void |
score3_override_options (void) |
{ |
flag_pic = false; |
if (!flag_pic) |
score3_sdata_max = g_switch_set ? g_switch_value : SCORE3_DEFAULT_SDATA_MAX; |
else |
{ |
score3_sdata_max = 0; |
if (g_switch_set && (g_switch_value != 0)) |
warning (0, "-fPIC and -G are incompatible"); |
} |
|
score_char_to_class['d'] = G32_REGS; |
score_char_to_class['e'] = G16_REGS; |
score_char_to_class['t'] = T32_REGS; |
|
score_char_to_class['h'] = HI_REG; |
score_char_to_class['l'] = LO_REG; |
score_char_to_class['x'] = CE_REGS; |
|
score_char_to_class['q'] = CN_REG; |
score_char_to_class['y'] = LC_REG; |
score_char_to_class['z'] = SC_REG; |
score_char_to_class['a'] = SP_REGS; |
|
score_char_to_class['c'] = CR_REGS; |
} |
|
/* Implement REGNO_REG_CLASS macro. */ |
int |
score3_reg_class (int regno) |
{ |
int c; |
gcc_assert (regno >= 0 && regno < FIRST_PSEUDO_REGISTER); |
|
if (regno == FRAME_POINTER_REGNUM |
|| regno == ARG_POINTER_REGNUM) |
return ALL_REGS; |
|
for (c = 0; c < N_REG_CLASSES; c++) |
if (TEST_HARD_REG_BIT (reg_class_contents[c], regno)) |
return c; |
|
return NO_REGS; |
} |
|
/* Implement PREFERRED_RELOAD_CLASS macro. */ |
enum reg_class |
score3_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, enum reg_class rclass) |
{ |
if (reg_class_subset_p (G16_REGS, rclass)) |
return G16_REGS; |
if (reg_class_subset_p (G32_REGS, rclass)) |
return G32_REGS; |
return rclass; |
} |
|
/* Implement SECONDARY_INPUT_RELOAD_CLASS |
and SECONDARY_OUTPUT_RELOAD_CLASS macro. */ |
enum reg_class |
score3_secondary_reload_class (enum reg_class rclass, |
enum machine_mode mode ATTRIBUTE_UNUSED, |
rtx x) |
{ |
int regno = -1; |
if (GET_CODE (x) == REG || GET_CODE(x) == SUBREG) |
regno = true_regnum (x); |
|
if (!GR_REG_CLASS_P (rclass)) |
return GP_REG_P (regno) ? NO_REGS : G32_REGS; |
return NO_REGS; |
} |
|
/* Implement CONST_OK_FOR_LETTER_P macro. */ |
/* imm constraints |
I imm16 << 16 |
J uimm5 |
K uimm16 |
L simm16 |
M uimm14 |
N simm14 |
O simm14 |
P simm5 |
Q uimm32 */ |
int |
score3_const_ok_for_letter_p (HOST_WIDE_INT value, char c) |
{ |
switch (c) |
{ |
case 'I': return ((value & 0xffff) == 0); |
case 'J': return IMM_IN_RANGE (value, 5, 0); |
case 'K': return IMM_IN_RANGE (value, 16, 0); |
case 'L': return IMM_IN_RANGE (value, 16, 1); |
case 'M': return IMM_IN_RANGE (value, 14, 0); |
case 'N': return IMM_IN_RANGE (value, 14, 1); |
case 'O': return IMM_IN_RANGE (value, 5, 1); |
case 'P': return IMM_IN_RANGE (value, 6, 1); |
case 'Q': return score_extra_constraint (GEN_INT(value), c); |
default : return 0; |
} |
} |
|
/* Implement EXTRA_CONSTRAINT macro. */ |
/* |
Q uimm32 |
Z symbol_ref */ |
int |
score3_extra_constraint (rtx op, char c) |
{ |
switch (c) |
{ |
case 'Q': return IMM_IN_RANGE (INTVAL(op), 32, 0); |
case 'Z': |
return GET_CODE (op) == SYMBOL_REF; |
default: |
gcc_unreachable (); |
} |
} |
|
/* Return truth value on whether or not a given hard register |
can support a given mode. */ |
int |
score3_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode) |
{ |
int size = GET_MODE_SIZE (mode); |
enum mode_class mclass = GET_MODE_CLASS (mode); |
|
if (mclass == MODE_CC) |
return regno == CC_REGNUM; |
else if (regno == FRAME_POINTER_REGNUM |
|| regno == ARG_POINTER_REGNUM) |
return mclass == MODE_INT; |
else if (GP_REG_P (regno)) |
return !(regno & 1) || (size <= UNITS_PER_WORD); |
else if (CE_REG_P (regno)) |
return (mclass == MODE_INT |
&& ((size <= UNITS_PER_WORD) |
|| (regno == CE_REG_FIRST && size == 2 * UNITS_PER_WORD))); |
else |
return (mclass == MODE_INT) && (size <= UNITS_PER_WORD); |
} |
|
/* Implement INITIAL_ELIMINATION_OFFSET. FROM is either the frame |
pointer or argument pointer. TO is either the stack pointer or |
hard frame pointer. */ |
HOST_WIDE_INT |
score3_initial_elimination_offset (int from, |
int to ATTRIBUTE_UNUSED) |
{ |
struct score3_frame_info *f = score3_compute_frame_size (get_frame_size ()); |
switch (from) |
{ |
case ARG_POINTER_REGNUM: |
return f->total_size; |
case FRAME_POINTER_REGNUM: |
return 0; |
default: |
gcc_unreachable (); |
} |
} |
|
/* Implement FUNCTION_ARG_ADVANCE macro. */ |
void |
score3_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, |
tree type, int named) |
{ |
struct score3_arg_info info; |
score3_classify_arg (cum, mode, type, named, &info); |
cum->num_gprs = info.reg_offset + info.reg_words; |
if (info.stack_words > 0) |
cum->stack_words = info.stack_offset + info.stack_words; |
cum->arg_number++; |
} |
|
/* Implement TARGET_ARG_PARTIAL_BYTES macro. */ |
int |
score3_arg_partial_bytes (CUMULATIVE_ARGS *cum, |
enum machine_mode mode, tree type, bool named) |
{ |
struct score3_arg_info info; |
score3_classify_arg (cum, mode, type, named, &info); |
return info.stack_words > 0 ? info.reg_words * UNITS_PER_WORD : 0; |
} |
|
/* Implement FUNCTION_ARG macro. */ |
rtx |
score3_function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode, |
tree type, int named) |
{ |
struct score3_arg_info info; |
|
if (mode == VOIDmode || !named) |
return 0; |
|
score3_classify_arg (cum, mode, type, named, &info); |
|
if (info.reg_offset == ARG_REG_NUM) |
return 0; |
|
if (!info.stack_words) |
return gen_rtx_REG (mode, ARG_REG_FIRST + info.reg_offset); |
else |
{ |
rtx ret = gen_rtx_PARALLEL (mode, rtvec_alloc (info.reg_words)); |
unsigned int i, part_offset = 0; |
for (i = 0; i < info.reg_words; i++) |
{ |
rtx reg; |
reg = gen_rtx_REG (SImode, ARG_REG_FIRST + info.reg_offset + i); |
XVECEXP (ret, 0, i) = gen_rtx_EXPR_LIST (SImode, reg, |
GEN_INT (part_offset)); |
part_offset += UNITS_PER_WORD; |
} |
return ret; |
} |
} |
|
/* Implement FUNCTION_VALUE and LIBCALL_VALUE. For normal calls, |
VALTYPE is the return type and MODE is VOIDmode. For libcalls, |
VALTYPE is null and MODE is the mode of the return value. */ |
rtx |
score3_function_value (tree valtype, tree func, enum machine_mode mode) |
{ |
if (valtype) |
{ |
int unsignedp; |
mode = TYPE_MODE (valtype); |
unsignedp = TYPE_UNSIGNED (valtype); |
mode = promote_function_mode (valtype, mode, &unsignedp, func, 1); |
} |
return gen_rtx_REG (mode, RT_REGNUM); |
} |
|
/* Implement TARGET_ASM_TRAMPOLINE_TEMPLATE. */ |
|
void |
score3_asm_trampoline_template (FILE *f) |
{ |
fprintf (f, "\t.set r1\n"); |
fprintf (f, "\tmv! r31, r3\n"); |
fprintf (f, "\tnop!\n"); |
fprintf (f, "\tbl nextinsn\n"); |
fprintf (f, "nextinsn:\n"); |
fprintf (f, "\tlw! r1, [r3, 6*4-8]\n"); |
fprintf (f, "\tnop!\n"); |
fprintf (f, "\tlw r23, [r3, 6*4-4]\n"); |
fprintf (f, "\tmv! r3, r31\n"); |
fprintf (f, "\tnop!\n"); |
fprintf (f, "\tbr! r1\n"); |
fprintf (f, "\tnop!\n"); |
fprintf (f, "\t.set nor1\n"); |
} |
|
/* Implement TARGET_TRAMPOLINE_INIT. */ |
void |
score3_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) |
{ |
#define FFCACHE "_flush_cache" |
#define CODE_SIZE (TRAMPOLINE_INSNS * UNITS_PER_WORD) |
|
rtx fnaddr = XEXP (DECL_RTL (fndecl), 0); |
rtx addr = XEXP (m_tramp, 0); |
rtx mem; |
|
emit_block_move (m_tramp, assemble_trampoline_template (), |
GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL); |
|
mem = adjust_address (m_tramp, SImode, CODE_SIZE); |
emit_move_insn (mem, fnaddr); |
mem = adjust_address (m_tramp, SImode, CODE_SIZE + GET_MODE_SIZE (SImode)); |
emit_move_insn (mem, chain_value); |
|
emit_library_call (gen_rtx_SYMBOL_REF (Pmode, FFCACHE), |
0, VOIDmode, 2, |
addr, Pmode, |
GEN_INT (TRAMPOLINE_SIZE), SImode); |
#undef FFCACHE |
#undef CODE_SIZE |
} |
|
/* This function is used to implement REG_MODE_OK_FOR_BASE_P macro. */ |
int |
score3_regno_mode_ok_for_base_p (int regno, int strict) |
{ |
if (regno >= FIRST_PSEUDO_REGISTER) |
{ |
if (!strict) |
return 1; |
regno = reg_renumber[regno]; |
} |
if (regno == ARG_POINTER_REGNUM |
|| regno == FRAME_POINTER_REGNUM) |
return 1; |
return GP_REG_P (regno); |
} |
|
/* Implement TARGET_LEGITIMATE_ADDRESS_P macro. */ |
bool |
score3_legitimate_address_p (enum machine_mode mode, rtx x, bool strict) |
{ |
struct score3_address_info addr; |
|
return score3_classify_address (&addr, mode, x, strict); |
} |
|
/* Return a number assessing the cost of moving a register in class |
FROM to class TO. */ |
int |
score3_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED, |
enum reg_class from, enum reg_class to) |
{ |
if (GR_REG_CLASS_P (from)) |
{ |
if (GR_REG_CLASS_P (to)) |
return 2; |
else if (SP_REG_CLASS_P (to)) |
return 4; |
else if (CP_REG_CLASS_P (to)) |
return 5; |
else if (CE_REG_CLASS_P (to)) |
return 6; |
} |
if (GR_REG_CLASS_P (to)) |
{ |
if (GR_REG_CLASS_P (from)) |
return 2; |
else if (SP_REG_CLASS_P (from)) |
return 4; |
else if (CP_REG_CLASS_P (from)) |
return 5; |
else if (CE_REG_CLASS_P (from)) |
return 6; |
} |
return 12; |
} |
|
/* Return the number of instructions needed to load a symbol of the |
given type into a register. */ |
static int |
score3_symbol_insns (enum score_symbol_type type) |
{ |
switch (type) |
{ |
case SYMBOL_GENERAL: |
return 2; |
|
case SYMBOL_SMALL_DATA: |
return 1; |
} |
|
gcc_unreachable (); |
} |
|
/* Return the number of instructions needed to load or store a value |
of mode MODE at X. Return 0 if X isn't valid for MODE. */ |
static int |
score3_address_insns (rtx x, enum machine_mode mode) |
{ |
struct score3_address_info addr; |
int factor; |
|
if (mode == BLKmode) |
factor = 1; |
else |
factor = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; |
|
if (score3_classify_address (&addr, mode, x, false)) |
switch (addr.type) |
{ |
case SCORE3_ADD_REG: |
case SCORE3_ADD_CONST_INT: |
return factor; |
|
case SCORE3_ADD_SYMBOLIC: |
return factor * score3_symbol_insns (addr.symbol_type); |
} |
return 0; |
} |
|
/* Implement TARGET_RTX_COSTS macro. */ |
bool |
score3_rtx_costs (rtx x, int code, int outer_code, int *total, |
bool speed ATTRIBUTE_UNUSED) |
{ |
enum machine_mode mode = GET_MODE (x); |
|
switch (code) |
{ |
case CONST_INT: |
if (outer_code == SET) |
{ |
if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I') |
|| CONST_OK_FOR_LETTER_P (INTVAL (x), 'L')) |
*total = COSTS_N_INSNS (1); |
else |
*total = COSTS_N_INSNS (2); |
} |
else if (outer_code == PLUS || outer_code == MINUS) |
{ |
if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'N')) |
*total = 0; |
else if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I') |
|| CONST_OK_FOR_LETTER_P (INTVAL (x), 'L')) |
*total = 1; |
else |
*total = COSTS_N_INSNS (2); |
} |
else if (outer_code == AND || outer_code == IOR) |
{ |
if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'M')) |
*total = 0; |
else if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I') |
|| CONST_OK_FOR_LETTER_P (INTVAL (x), 'K')) |
*total = 1; |
else |
*total = COSTS_N_INSNS (2); |
} |
else |
{ |
*total = 0; |
} |
return true; |
|
case CONST: |
case SYMBOL_REF: |
case LABEL_REF: |
case CONST_DOUBLE: |
*total = COSTS_N_INSNS (2); |
return true; |
|
case MEM: |
{ |
/* If the address is legitimate, return the number of |
instructions it needs, otherwise use the default handling. */ |
int n = score3_address_insns (XEXP (x, 0), GET_MODE (x)); |
if (n > 0) |
{ |
*total = COSTS_N_INSNS (n + 1); |
return true; |
} |
return false; |
} |
|
case FFS: |
*total = COSTS_N_INSNS (6); |
return true; |
|
case NOT: |
*total = COSTS_N_INSNS (1); |
return true; |
|
case AND: |
case IOR: |
case XOR: |
if (mode == DImode) |
{ |
*total = COSTS_N_INSNS (2); |
return true; |
} |
return false; |
|
case ASHIFT: |
case ASHIFTRT: |
case LSHIFTRT: |
if (mode == DImode) |
{ |
*total = COSTS_N_INSNS ((GET_CODE (XEXP (x, 1)) == CONST_INT) |
? 4 : 12); |
return true; |
} |
return false; |
|
case ABS: |
*total = COSTS_N_INSNS (4); |
return true; |
|
case PLUS: |
case MINUS: |
if (mode == DImode) |
{ |
*total = COSTS_N_INSNS (4); |
return true; |
} |
*total = COSTS_N_INSNS (1); |
return true; |
|
case NEG: |
if (mode == DImode) |
{ |
*total = COSTS_N_INSNS (4); |
return true; |
} |
return false; |
|
case MULT: |
*total = optimize_size ? COSTS_N_INSNS (2) : COSTS_N_INSNS (12); |
return true; |
|
case DIV: |
case MOD: |
case UDIV: |
case UMOD: |
*total = optimize_size ? COSTS_N_INSNS (2) : COSTS_N_INSNS (33); |
return true; |
|
case SIGN_EXTEND: |
case ZERO_EXTEND: |
switch (GET_MODE (XEXP (x, 0))) |
{ |
case QImode: |
case HImode: |
if (GET_CODE (XEXP (x, 0)) == MEM) |
{ |
*total = COSTS_N_INSNS (2); |
|
if (!TARGET_LITTLE_ENDIAN && |
side_effects_p (XEXP (XEXP (x, 0), 0))) |
*total = 100; |
} |
else |
*total = COSTS_N_INSNS (1); |
break; |
|
default: |
*total = COSTS_N_INSNS (1); |
break; |
} |
return true; |
|
default: |
return false; |
} |
} |
|
/* Implement TARGET_ADDRESS_COST macro. */ |
int |
score3_address_cost (rtx addr) |
{ |
return score3_address_insns (addr, SImode); |
} |
|
/* Implement ASM_OUTPUT_EXTERNAL macro. */ |
int |
score3_output_external (FILE *file ATTRIBUTE_UNUSED, |
tree decl, const char *name) |
{ |
register struct extern_list *p; |
|
if (score3_in_small_data_p (decl)) |
{ |
p = (struct extern_list *) ggc_alloc (sizeof (struct extern_list)); |
p->next = extern_head; |
p->name = name; |
p->size = int_size_in_bytes (TREE_TYPE (decl)); |
extern_head = p; |
} |
return 0; |
} |
|
/* Implement RETURN_ADDR_RTX. Note, we do not support moving |
back to a previous frame. */ |
rtx |
score3_return_addr (int count, rtx frame ATTRIBUTE_UNUSED) |
{ |
if (count != 0) |
return const0_rtx; |
return get_hard_reg_initial_val (Pmode, RA_REGNUM); |
} |
|
/* Implement PRINT_OPERAND macro. */ |
/* Score-specific operand codes: |
'[' print .set nor1 directive |
']' print .set r1 directive |
'U' print hi part of a CONST_INT rtx |
'E' print log2(v) |
'F' print log2(~v) |
'D' print SFmode const double |
'S' selectively print "!" if operand is 15bit instruction accessible |
'V' print "v!" if operand is 15bit instruction accessible, or "lfh!" |
'L' low part of DImode reg operand |
'H' high part of DImode reg operand |
'C' print part of opcode for a branch condition. */ |
void |
score3_print_operand (FILE *file, rtx op, int c) |
{ |
enum rtx_code code = -1; |
if (!PRINT_OPERAND_PUNCT_VALID_P (c)) |
code = GET_CODE (op); |
|
if (c == '[') |
{ |
fprintf (file, ".set r1\n"); |
} |
else if (c == ']') |
{ |
fprintf (file, "\n\t.set nor1"); |
} |
else if (c == 'U') |
{ |
gcc_assert (code == CONST_INT); |
fprintf (file, HOST_WIDE_INT_PRINT_HEX, |
(INTVAL (op) >> 16) & 0xffff); |
} |
else if (c == 'D') |
{ |
if (GET_CODE (op) == CONST_DOUBLE) |
{ |
rtx temp = gen_lowpart (SImode, op); |
gcc_assert (GET_MODE (op) == SFmode); |
fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (temp) & 0xffffffff); |
} |
else |
output_addr_const (file, op); |
} |
else if (c == 'S') |
{ |
gcc_assert (code == REG); |
if (G16_REG_P (REGNO (op))) |
fprintf (file, "!"); |
} |
else if (c == 'V') |
{ |
gcc_assert (code == REG); |
fprintf (file, G16_REG_P (REGNO (op)) ? "v!" : "lfh!"); |
} |
else if (c == 'C') |
{ |
enum machine_mode mode = GET_MODE (XEXP (op, 0)); |
|
switch (code) |
{ |
case EQ: fputs ("eq!", file); break; |
case NE: fputs ("ne!", file); break; |
case GT: fputs ("gt!", file); break; |
case GE: fputs (mode != CCmode ? "pl" : "ge", file); break; |
case LT: fputs (mode != CCmode ? "mi" : "lt", file); break; |
case LE: fputs ("le!", file); break; |
case GTU: fputs ("gtu!", file); break; |
case GEU: fputs ("cs", file); break; |
case LTU: fputs ("cc", file); break; |
case LEU: fputs ("leu!", file); break; |
default: |
output_operand_lossage ("invalid operand for code: '%c'", code); |
} |
} |
else if (c == 'G') /* Seperate from b<cond>, use for mv<cond>. */ |
{ |
enum machine_mode mode = GET_MODE (XEXP (op, 0)); |
|
switch (code) |
{ |
case EQ: fputs ("eq", file); break; |
case NE: fputs ("ne", file); break; |
case GT: fputs ("gt", file); break; |
case GE: fputs (mode != CCmode ? "pl" : "ge", file); break; |
case LT: fputs (mode != CCmode ? "mi" : "lt", file); break; |
case LE: fputs ("le", file); break; |
case GTU: fputs ("gtu", file); break; |
case GEU: fputs ("cs", file); break; |
case LTU: fputs ("cc", file); break; |
case LEU: fputs ("leu", file); break; |
default: |
output_operand_lossage ("invalid operand for code: '%c'", code); |
} |
} |
else if (c == 'E') |
{ |
unsigned HOST_WIDE_INT i; |
unsigned HOST_WIDE_INT pow2mask = 1; |
unsigned HOST_WIDE_INT val; |
|
val = INTVAL (op); |
for (i = 0; i < 32; i++) |
{ |
if (val == pow2mask) |
break; |
pow2mask <<= 1; |
} |
gcc_assert (i < 32); |
fprintf (file, HOST_WIDE_INT_PRINT_HEX, i); |
} |
else if (c == 'F') |
{ |
unsigned HOST_WIDE_INT i; |
unsigned HOST_WIDE_INT pow2mask = 1; |
unsigned HOST_WIDE_INT val; |
|
val = ~INTVAL (op); |
for (i = 0; i < 32; i++) |
{ |
if (val == pow2mask) |
break; |
pow2mask <<= 1; |
} |
gcc_assert (i < 32); |
fprintf (file, HOST_WIDE_INT_PRINT_HEX, i); |
} |
else if (code == REG) |
{ |
int regnum = REGNO (op); |
if ((c == 'H' && !WORDS_BIG_ENDIAN) |
|| (c == 'L' && WORDS_BIG_ENDIAN)) |
regnum ++; |
fprintf (file, "%s", reg_names[regnum]); |
} |
else |
{ |
switch (code) |
{ |
case MEM: |
score3_print_operand_address (file, op); |
break; |
default: |
output_addr_const (file, op); |
} |
} |
} |
|
/* Implement PRINT_OPERAND_ADDRESS macro. */ |
void |
score3_print_operand_address (FILE *file, rtx x) |
{ |
struct score3_address_info addr; |
enum rtx_code code = GET_CODE (x); |
enum machine_mode mode = GET_MODE (x); |
|
if (code == MEM) |
x = XEXP (x, 0); |
|
if (score3_classify_address (&addr, mode, x, true)) |
{ |
switch (addr.type) |
{ |
case SCORE3_ADD_REG: |
{ |
switch (addr.code) |
{ |
case PRE_DEC: |
fprintf (file, "[%s,-%ld]+", reg_names[REGNO (addr.reg)], |
INTVAL (addr.offset)); |
break; |
case POST_DEC: |
fprintf (file, "[%s]+,-%ld", reg_names[REGNO (addr.reg)], |
INTVAL (addr.offset)); |
break; |
case PRE_INC: |
fprintf (file, "[%s, %ld]+", reg_names[REGNO (addr.reg)], |
INTVAL (addr.offset)); |
break; |
case POST_INC: |
fprintf (file, "[%s]+, %ld", reg_names[REGNO (addr.reg)], |
INTVAL (addr.offset)); |
break; |
default: |
if (INTVAL(addr.offset) == 0) |
fprintf(file, "[%s]", reg_names[REGNO (addr.reg)]); |
else |
fprintf(file, "[%s, %ld]", reg_names[REGNO (addr.reg)], |
INTVAL(addr.offset)); |
break; |
} |
} |
return; |
case SCORE3_ADD_CONST_INT: |
case SCORE3_ADD_SYMBOLIC: |
output_addr_const (file, x); |
return; |
} |
} |
print_rtl (stderr, x); |
gcc_unreachable (); |
} |
|
/* Implement SELECT_CC_MODE macro. */ |
enum machine_mode |
score3_select_cc_mode (enum rtx_code op, rtx x, rtx y) |
{ |
if ((op == EQ || op == NE || op == LT || op == GE) |
&& y == const0_rtx |
&& GET_MODE (x) == SImode) |
{ |
switch (GET_CODE (x)) |
{ |
case PLUS: |
case MINUS: |
case NEG: |
case AND: |
case IOR: |
case XOR: |
case NOT: |
case ASHIFT: |
case LSHIFTRT: |
case ASHIFTRT: |
return CC_NZmode; |
|
case SIGN_EXTEND: |
case ZERO_EXTEND: |
case ROTATE: |
case ROTATERT: |
return (op == LT || op == GE) ? CC_Nmode : CCmode; |
|
default: |
return CCmode; |
} |
} |
|
if ((op == EQ || op == NE) |
&& (GET_CODE (y) == NEG) |
&& register_operand (XEXP (y, 0), SImode) |
&& register_operand (x, SImode)) |
{ |
return CC_NZmode; |
} |
|
return CCmode; |
} |
|
#define EMIT_PL(_rtx) RTX_FRAME_RELATED_P (_rtx) = 1 |
/* return 0, no more bit set in mask. */ |
static int rpush_first (int mask, int sb, int *rd) |
{ |
int i, cnt = 1; |
|
if ((mask & (1 << sb)) == 0) |
return 0; |
|
*rd = sb; |
|
for (i = sb-1; i >= 0; i--) |
{ |
if (mask & (1 << i)) |
{ |
cnt ++; |
continue; |
} |
|
*rd = i+1; |
break;; |
} |
|
return cnt; |
} |
|
static void |
rpush (int rd, int cnt) |
{ |
rtx mem = gen_rtx_MEM (SImode, gen_rtx_PRE_DEC (SImode, stack_pointer_rtx)); |
rtx reg = gen_rtx_REG (SImode, rd); |
|
if (!crtl->calls_eh_return) |
MEM_READONLY_P (mem) = 1; |
|
if (cnt == 1) |
EMIT_PL (emit_insn (gen_pushsi_score3 (mem, reg))); |
else |
{ |
int i; |
rtx insn = gen_store_multiple (gen_rtx_MEM (SImode, stack_pointer_rtx), |
gen_rtx_REG (SImode, rd), |
GEN_INT (cnt)); |
|
rtx pat = PATTERN (insn); |
|
for (i = 0; i < XVECLEN (pat, 0); i++) |
if (GET_CODE (XVECEXP (pat, 0, i)) == SET) |
RTX_FRAME_RELATED_P (XVECEXP (pat, 0, i)) = 1; |
|
EMIT_PL (emit_insn (insn)); |
} |
} |
|
/* Generate the prologue instructions for entry into a S+core function. */ |
void |
score3_prologue (void) |
{ |
struct score3_frame_info *f = score3_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_score3 ()); |
|
{ |
int cnt, rd; |
|
for (regno = (int) GP_REG_LAST; regno >= (int) GP_REG_FIRST; regno--) |
{ |
cnt = rpush_first (f->mask, regno, &rd); |
if (cnt != 0) |
{ |
rpush (rd, cnt); |
regno = regno - cnt; |
} |
} |
} |
|
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, SCORE3_PROLOGUE_TEMP_REGNUM), |
GEN_INT (size))); |
EMIT_PL (emit_insn |
(gen_sub3_insn (stack_pointer_rtx, |
stack_pointer_rtx, |
gen_rtx_REG (Pmode, |
SCORE3_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 && f->cprestore_size) |
{ |
if (frame_pointer_needed) |
emit_insn (gen_cprestore_use_fp_score3 (GEN_INT (size - f->cprestore_size))); |
else |
emit_insn (gen_cprestore_use_sp_score3 (GEN_INT (size - f->cprestore_size))); |
} |
} |
|
/* return 0, no more bit set in mask. */ |
static int |
rpop_first (int mask, int sb, int *rd) |
{ |
int i, cnt = 1; |
|
if ((mask & (1 << sb)) == 0) |
return 0; |
|
*rd = sb; |
|
for (i = sb+1; i < 32; i++) |
if (mask & (1 << i)) |
cnt++; |
else |
break;; |
|
return cnt; |
} |
|
static void |
rpop (int rd, int cnt) |
{ |
rtx mem = gen_rtx_MEM (SImode, gen_rtx_POST_INC (SImode, stack_pointer_rtx)); |
rtx reg = gen_rtx_REG (SImode, rd); |
|
if (!crtl->calls_eh_return) |
MEM_READONLY_P (mem) = 1; |
|
if (cnt == 1) |
emit_insn (gen_popsi_score3 (reg, mem)); |
else |
emit_insn (gen_load_multiple (reg, |
gen_rtx_MEM (SImode, stack_pointer_rtx), |
GEN_INT (cnt))); |
} |
|
/* Generate the epilogue instructions in a S+core function. */ |
void |
score3_epilogue (int sibcall_p) |
{ |
struct score3_frame_info *f = score3_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, SCORE3_EPILOGUE_TEMP_REGNUM), |
GEN_INT (size)); |
emit_insn (gen_add3_insn (base, base, |
gen_rtx_REG (Pmode, |
SCORE3_EPILOGUE_TEMP_REGNUM))); |
} |
} |
|
if (base != stack_pointer_rtx) |
emit_move_insn (stack_pointer_rtx, base); |
|
if (crtl->calls_eh_return) |
emit_insn (gen_add3_insn (stack_pointer_rtx, |
stack_pointer_rtx, |
EH_RETURN_STACKADJ_RTX)); |
|
{ |
int cnt, rd; |
|
for (regno = (int) GP_REG_FIRST; regno <= (int) GP_REG_LAST; regno++) |
{ |
cnt = rpop_first (f->mask, regno, &rd); |
if (cnt != 0) |
{ |
rpop (rd, cnt); |
regno = regno + cnt; |
} |
} |
} |
|
if (!sibcall_p) |
emit_jump_insn (gen_return_internal_score3 (gen_rtx_REG (Pmode, RA_REGNUM))); |
} |
|
/* 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 |
score3_symbolic_constant_p (rtx x, enum score_symbol_type *symbol_type) |
{ |
HOST_WIDE_INT offset; |
|
score3_split_const (x, &x, &offset); |
if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF) |
*symbol_type = score3_classify_symbol (x); |
else |
return 0; |
|
if (offset == 0) |
return 1; |
|
/* if offset > 15bit, must reload */ |
if (!IMM_IN_RANGE (offset, 15, 1)) |
return 0; |
|
switch (*symbol_type) |
{ |
case SYMBOL_GENERAL: |
return 1; |
case SYMBOL_SMALL_DATA: |
return score3_offset_within_object_p (x, offset); |
} |
gcc_unreachable (); |
} |
|
void |
score3_movsicc (rtx *ops) |
{ |
enum machine_mode mode; |
|
mode = score3_select_cc_mode (GET_CODE (ops[1]), ops[2], ops[3]); |
emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (mode, CC_REGNUM), |
gen_rtx_COMPARE (mode, XEXP (ops[1], 0), |
XEXP (ops[1], 1)))); |
} |
|
/* Call and sibcall pattern all need call this function. */ |
void |
score3_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_score3 (addr, ops[1])); |
else |
emit_call_insn (gen_call_internal_score3 (addr, ops[1])); |
} |
|
/* Call value and sibcall value pattern all need call this function. */ |
void |
score3_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_score3 (result, addr, arg)); |
else |
emit_call_insn (gen_call_value_internal_score3 (result, addr, arg)); |
} |
|
/* Machine Split */ |
void |
score3_movdi (rtx *ops) |
{ |
rtx dst = ops[0]; |
rtx src = ops[1]; |
rtx dst0 = score3_subw (dst, 0); |
rtx dst1 = score3_subw (dst, 1); |
rtx src0 = score3_subw (src, 0); |
rtx src1 = score3_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 |
score3_zero_extract_andi (rtx *ops) |
{ |
if (INTVAL (ops[1]) == 1 && const_uimm5 (ops[2], SImode)) |
emit_insn (gen_zero_extract_bittst_score3 (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_score3 (ops[3], ops[0], |
gen_int_mode (mask, SImode))); |
} |
} |
|
const char * |
score3_rpush (rtx *ops) |
{ |
snprintf (score3_ins, INS_BUF_SZ, "rpush!\t%%1, %d", XVECLEN (ops[0], 0)); |
return score3_ins; |
} |
|
const char * |
score3_rpop (rtx *ops) |
{ |
snprintf (score3_ins, INS_BUF_SZ, "rpop!\t%%1, %d", XVECLEN (ops[0], 0)); |
return score3_ins; |
} |
|
/* Output asm code for ld/sw insn. */ |
static int |
score3_pr_addr_post (rtx *ops, int idata, int iaddr, char *ip, |
enum score_mem_unit unit ATTRIBUTE_UNUSED) |
{ |
struct score3_address_info ai; |
|
gcc_assert (GET_CODE (ops[idata]) == REG); |
gcc_assert (score3_classify_address (&ai, SImode, XEXP (ops[iaddr], 0), true)); |
|
if (ai.type == SCORE3_ADD_REG |
&& ai.code == REG |
&& GET_CODE (ai.offset) == CONST_INT |
&& G16_REG_P (REGNO (ops[idata])) |
&& G8_REG_P (REGNO (ai.reg)) |
&& ((INTVAL (ai.offset) & 3) == 0) |
&& (IMM_IN_RANGE (INTVAL (ai.offset), 7, 0))) |
{ |
ops[iaddr] = ai.reg; |
return snprintf (ip, INS_BUF_SZ, "!\t%%%d, [%%%d, " |
HOST_WIDE_INT_PRINT_DEC "]", |
idata, iaddr, INTVAL (ai.offset)); |
} |
|
if (ai.type == SCORE3_ADD_SYMBOLIC) |
return snprintf (ip, INS_BUF_SZ, "48\t%%%d, %%a%d", idata, iaddr); |
|
return snprintf (ip, INS_BUF_SZ, "\t%%%d, %%a%d", idata, iaddr); |
} |
|
/* Output asm insn for load. */ |
const char * |
score3_linsn (rtx *ops, enum score_mem_unit unit, bool sign) |
{ |
const char *pre_ins[] = |
{"lbu", "lhu", "lw", "??", "lb", "lh", "lw", "??"}; |
char *ip; |
|
strcpy (score3_ins, pre_ins[(sign ? 4 : 0) + unit]); |
ip = score3_ins + strlen (score3_ins); |
|
if (unit == SCORE_WORD) |
score3_pr_addr_post (ops, 0, 1, ip, unit); |
else |
snprintf (ip, INS_BUF_SZ, "\t%%0, %%a1"); |
|
return score3_ins; |
} |
|
/* Output asm insn for store. */ |
const char * |
score3_sinsn (rtx *ops, enum score_mem_unit unit) |
{ |
const char *pre_ins[] = {"sb", "sh", "sw"}; |
char *ip; |
|
strcpy (score3_ins, pre_ins[unit]); |
ip = score3_ins + strlen (score3_ins); |
|
if (unit == SCORE_WORD) |
score3_pr_addr_post (ops, 1, 0, ip, unit); |
else |
snprintf (ip, INS_BUF_SZ, "\t%%1, %%a0"); |
|
return score3_ins; |
} |
|
/* Output asm insn for load immediate. */ |
const char * |
score3_limm (rtx *ops) |
{ |
HOST_WIDE_INT v; |
|
gcc_assert (GET_CODE (ops[0]) == REG); |
gcc_assert (GET_CODE (ops[1]) == CONST_INT); |
|
v = INTVAL (ops[1]); |
if (G16_REG_P (REGNO (ops[0])) && IMM_IN_RANGE (v, 5, 0)) |
return "ldiu!\t%0, %c1"; |
else if (IMM_IN_RANGE (v, 16, 1)) |
return "ldi\t%0, %c1"; |
else if ((v & 0xffff) == 0) |
return "ldis\t%0, %U1"; |
else |
return "li\t%0, %c1"; |
} |
|
/* Output asm insn for move. */ |
const char * |
score3_move (rtx *ops) |
{ |
gcc_assert (GET_CODE (ops[0]) == REG); |
gcc_assert (GET_CODE (ops[1]) == REG); |
|
return "mv!\t%0, %1"; |
} |
|
/* Generate add insn. */ |
const char * |
score3_select_add_imm (rtx *ops, bool set_cc) |
{ |
HOST_WIDE_INT v = INTVAL (ops[2]); |
|
gcc_assert (GET_CODE (ops[2]) == CONST_INT); |
gcc_assert (REGNO (ops[0]) == REGNO (ops[1])); |
|
if (set_cc) |
return "addi.c\t%0, %c2"; |
else |
if (IMM_IN_RANGE (v, 6, 1) && G16_REG_P (REGNO (ops[0]))) |
return "addi!\t%0, %c2"; |
else |
return "addi\t%0, %c2"; |
} |
|
/* Output arith insn. */ |
const char * |
score3_select (rtx *ops, const char *inst_pre, bool commu ATTRIBUTE_UNUSED, |
const char *letter, bool set_cc) |
{ |
gcc_assert (GET_CODE (ops[0]) == REG); |
gcc_assert (GET_CODE (ops[1]) == REG); |
|
if (set_cc) |
snprintf (score3_ins, INS_BUF_SZ, "%s.c\t%%0, %%1, %%%s2", inst_pre, letter); |
else |
snprintf (score3_ins, INS_BUF_SZ, "%s\t%%0, %%1, %%%s2", inst_pre, letter); |
return score3_ins; |
} |
|
/* Output a Score3 casesi instruction. */ |
const char * |
score3_output_casesi (rtx *operands) |
{ |
rtx diff_vec = PATTERN (next_real_insn (operands[2])); |
gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC); |
|
output_asm_insn ("cmpi.c\t%0, %1", operands); |
output_asm_insn ("bgtu\t%3", operands); |
switch (GET_MODE(diff_vec)) |
{ |
case QImode: |
output_asm_insn ("ldi48\t%4, %2", operands); |
output_asm_insn ("ltbb\t%4, [%4, %0]\n%2_tbb:", operands); |
return "brr!\t%4"; |
case HImode: |
output_asm_insn ("ldi48\t%4, %2", operands); |
output_asm_insn ("ltbh\t%4, [%4, %0]\n%2_tbb:", operands); |
return "brr!\t%4"; |
case SImode: |
output_asm_insn ("ldi48\t%4, %2", operands); |
output_asm_insn ("ltbw\t%4, [%4, %0]", operands); |
return "br!\t%4"; |
default: |
gcc_unreachable (); |
} |
} |
score3.c
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: t-score-elf
===================================================================
--- t-score-elf (nonexistent)
+++ t-score-elf (revision 384)
@@ -0,0 +1,70 @@
+# Copyright (C) 2006, 2007, 2008, 2009 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 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
+# .
+
+# Additional Backend Files
+score7.o: $(srcdir)/config/score/score7.c $(CONFIG_H) $(SYSTEM_H) \
+ coretypes.h $(TM_H) $(RTL_H) output.h flags.h $(TREE_H) \
+ expr.h toplev.h $(TM_P_H)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/score/score7.c
+
+score3.o: $(srcdir)/config/score/score3.c $(CONFIG_H) $(SYSTEM_H) \
+ coretypes.h $(TM_H) $(RTL_H) output.h flags.h $(TREE_H) \
+ expr.h toplev.h $(TM_P_H)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/score/score3.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 = mscore3 mel
+MULTILIB_MATCHES = mscore3=march?score3
+
+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
Index: crti.asm
===================================================================
--- crti.asm (nonexistent)
+++ crti.asm (revision 384)
@@ -0,0 +1,131 @@
+# crti.asm for Sunplus S+CORE
+#
+# Copyright (C) 2005, 2009 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 3, or (at your option) any
+# later version.
+#
+# 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.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# .
+
+# This file makes a stack frame for the contents of the .init and
+# .fini sections.
+.extern _stack
+
+#ifndef __pic__
+.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]
+#else
+.section .init, "ax", @progbits
+ .set pic
+ .weak _start
+ .ent _start
+ .frame r0, 0, r3, 0
+ .mask 0x00000000, 0
+_start:
+ mv r29, r3
+ bl 0f
+0:
+ .cpload r3
+ mv r3, r29
+ 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
+ bl _init
+ la r4, _end
+ la r29, _init_argv
+ brl r29
+ la r29, exit
+ brl r29
+ .end _start
+
+ .weak _init_argv
+ .ent _init_argv
+ .frame r0, 0, r3, 0
+ .mask 0x00000000, 0
+_init_argv:
+ ldiu! r4, 0
+ ldiu! r5, 0
+ la r29, main
+ brl r29
+ .end _init_argv
+
+ .globl _init
+ .type _init, %function
+_init:
+ addi r0, -32
+ sw r3, [r0, 20]
+
+ .section .fini, "ax", @progbits
+ .globl _fini
+ .type _fini, %function
+_fini:
+ addi r0, -32
+ sw r3, [r0, 20]
+
+#endif
Index: predicates.md
===================================================================
--- predicates.md (nonexistent)
+++ predicates.md (revision 384)
@@ -0,0 +1,156 @@
+;; Predicate definitions for Sunplus S+CORE.
+;; Copyright (C) 2005, 2007 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 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
+;; .
+
+(define_predicate "const_uimm5"
+ (match_code "const_int")
+{
+ return IMM_IN_RANGE (INTVAL (op), 5, 0);
+})
+
+(define_predicate "const_simm12"
+ (match_code "const_int")
+{
+ return IMM_IN_RANGE (INTVAL (op), 12, 1);
+})
+
+(define_predicate "const_simm15"
+ (match_code "const_int")
+{
+ return IMM_IN_RANGE (INTVAL (op), 15, 1);
+})
+
+(define_predicate "arith_operand"
+ (ior (match_code "const_int")
+ (match_operand 0 "register_operand")))
+
+(define_predicate "score_register_operand"
+ (match_code "reg,subreg")
+{
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ return (GET_CODE (op) == REG)
+ && (REGNO (op) != CC_REGNUM);
+})
+
+(define_predicate "const_call_insn_operand"
+ (match_code "const,symbol_ref,label_ref")
+{
+ enum score_symbol_type symbol_type;
+
+ return (score_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 "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 "sr0_operand"
+ (and (match_code "reg")
+ (match_test "REGNO (op) == CN_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"))
+
+(define_predicate "score_load_multiple_operation"
+ (match_code "parallel")
+{
+ int count = XVECLEN (op, 0);
+ int dest_regno;
+ rtx src_addr;
+ int i;
+
+ /* Perform a quick check so we don't blow up below. */
+ if (count <= 1
+ || GET_CODE (XVECEXP (op, 0, 0)) != SET
+ || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
+ || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)
+ return 0;
+
+ dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
+ src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
+
+ for (i = 1; i < count; i++)
+ {
+ rtx elt = XVECEXP (op, 0, i);
+
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_DEST (elt)) != REG
+ || GET_MODE (SET_DEST (elt)) != SImode
+ || REGNO (SET_DEST (elt)) != (unsigned) (dest_regno + i)
+ || GET_CODE (SET_SRC (elt)) != MEM
+ || GET_MODE (SET_SRC (elt)) != SImode
+ || GET_CODE (XEXP (SET_SRC (elt), 0)) != POST_INC)
+ return 0;
+ }
+
+ return 1;
+})
+
+(define_predicate "score_store_multiple_operation"
+ (match_code "parallel")
+{
+ int count = XVECLEN (op, 0);
+ int src_regno;
+ rtx dest_addr;
+ int i;
+
+ /* Perform a quick check so we don't blow up below. */
+ if (count <= 1
+ || GET_CODE (XVECEXP (op, 0, 0)) != SET
+ || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
+ || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
+ return 0;
+
+ src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
+ dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
+
+ for (i = 1; i < count; i++)
+ {
+ rtx elt = XVECEXP (op, 0, i);
+
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_SRC (elt)) != REG
+ || GET_MODE (SET_SRC (elt)) != SImode
+ || REGNO (SET_SRC (elt)) != (unsigned) (src_regno + i)
+ || GET_CODE (SET_DEST (elt)) != MEM
+ || GET_MODE (SET_DEST (elt)) != SImode
+ || GET_CODE (XEXP (SET_DEST (elt), 0)) != PRE_DEC)
+ return 0;
+ }
+
+ return 1;
+})
+
Index: score7.c
===================================================================
--- score7.c (nonexistent)
+++ score7.c (revision 384)
@@ -0,0 +1,1860 @@
+/* score7.c for Sunplus S+CORE processor
+ Copyright (C) 2005, 2007, 2008 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 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
+ . */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.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 "score7.h"
+#include "df.h"
+
+#define BITSET_P(VALUE, BIT) (((VALUE) & (1L << (BIT))) != 0)
+#define INS_BUF_SZ 128
+
+extern enum reg_class score_char_to_class[256];
+
+static int score7_sdata_max;
+static char score7_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
+score7_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
+score7_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
+score7_classify_symbol (rtx x)
+{
+ if (GET_CODE (x) == LABEL_REF)
+ return SYMBOL_GENERAL;
+
+ gcc_assert (GET_CODE (x) == SYMBOL_REF);
+
+ if (CONSTANT_POOL_ADDRESS_P (x))
+ {
+ if (GET_MODE_SIZE (get_pool_mode (x)) <= SCORE7_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
+score7_save_reg_p (unsigned int regno)
+{
+ /* Check call-saved registers. */
+ if (df_regs_ever_live_p (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 && df_regs_ever_live_p (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
+score7_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);
+}
+
+static struct score7_frame_info *
+score7_cached_frame (void)
+{
+ static struct score7_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. */
+static struct score7_frame_info *
+score7_compute_frame_size (HOST_WIDE_INT size)
+{
+ unsigned int regno;
+ struct score7_frame_info *f = score7_cached_frame ();
+
+ memset (f, 0, sizeof (struct score7_frame_info));
+ f->gp_reg_size = 0;
+ f->mask = 0;
+ f->var_size = SCORE7_STACK_ALIGN (size);
+ f->args_size = crtl->outgoing_args_size;
+ f->cprestore_size = flag_pic ? UNITS_PER_WORD : 0;
+ if (f->var_size == 0 && current_function_is_leaf)
+ f->args_size = f->cprestore_size = 0;
+
+ if (f->args_size == 0 && cfun->calls_alloca)
+ f->args_size = UNITS_PER_WORD;
+
+ f->total_size = f->var_size + f->args_size + f->cprestore_size;
+ for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
+ {
+ if (score7_save_reg_p (regno))
+ {
+ f->gp_reg_size += GET_MODE_SIZE (SImode);
+ f->mask |= 1 << (regno - GP_REG_FIRST);
+ }
+ }
+
+ if (crtl->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 += 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;
+
+ return f;
+}
+
+/* Return true if X is a valid base register for the given mode.
+ Allow only hard registers if STRICT. */
+static int
+score7_valid_base_register_p (rtx x, int strict)
+{
+ if (!strict && GET_CODE (x) == SUBREG)
+ x = SUBREG_REG (x);
+
+ return (GET_CODE (x) == REG
+ && score7_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. */
+static int
+score7_classify_address (struct score7_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 = SCORE7_ADD_REG;
+ info->reg = x;
+ info->offset = const0_rtx;
+ return score7_valid_base_register_p (info->reg, strict);
+ case PLUS:
+ info->type = SCORE7_ADD_REG;
+ info->reg = XEXP (x, 0);
+ info->offset = XEXP (x, 1);
+ return (score7_valid_base_register_p (info->reg, strict)
+ && GET_CODE (info->offset) == CONST_INT
+ && IMM_IN_RANGE (INTVAL (info->offset), 15, 1));
+ case PRE_DEC:
+ case POST_DEC:
+ case PRE_INC:
+ case POST_INC:
+ if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (SImode))
+ return false;
+ info->type = SCORE7_ADD_REG;
+ info->reg = XEXP (x, 0);
+ info->offset = GEN_INT (GET_MODE_SIZE (mode));
+ return score7_valid_base_register_p (info->reg, strict);
+ case CONST_INT:
+ info->type = SCORE7_ADD_CONST_INT;
+ return IMM_IN_RANGE (INTVAL (x), 15, 1);
+ case CONST:
+ case LABEL_REF:
+ case SYMBOL_REF:
+ info->type = SCORE7_ADD_SYMBOLIC;
+ return (score7_symbolic_constant_p (x, &info->symbol_type)
+ && (info->symbol_type == SYMBOL_GENERAL
+ || info->symbol_type == SYMBOL_SMALL_DATA));
+ default:
+ return 0;
+ }
+}
+
+bool
+score7_return_in_memory (tree type, tree fndecl ATTRIBUTE_UNUSED)
+{
+ return ((TYPE_MODE (type) == BLKmode)
+ || (int_size_in_bytes (type) > 2 * UNITS_PER_WORD)
+ || (int_size_in_bytes (type) == -1));
+}
+
+/* Return a legitimate address for REG + OFFSET. */
+static rtx
+score7_add_offset (rtx reg, HOST_WIDE_INT offset)
+{
+ if (!IMM_IN_RANGE (offset, 15, 1))
+ {
+ reg = expand_simple_binop (GET_MODE (reg), PLUS,
+ gen_int_mode (offset & 0xffffc000,
+ GET_MODE (reg)),
+ reg, NULL, 0, OPTAB_WIDEN);
+ offset &= 0x3fff;
+ }
+
+ return plus_constant (reg, offset);
+}
+
+/* Implement TARGET_ASM_OUTPUT_MI_THUNK. Generate rtl rather than asm text
+ in order to avoid duplicating too much logic from elsewhere. */
+void
+score7_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
+ HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
+ tree function)
+{
+ rtx this_rtx, temp1, insn, fnaddr;
+
+ /* Pretend to be a post-reload pass while generating rtl. */
+ reload_completed = 1;
+
+ /* Mark the end of the (empty) prologue. */
+ emit_note (NOTE_INSN_PROLOGUE_END);
+
+ /* We need two temporary registers in some cases. */
+ temp1 = gen_rtx_REG (Pmode, 8);
+
+ /* Find out which register contains the "this" pointer. */
+ if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
+ this_rtx = gen_rtx_REG (Pmode, ARG_REG_FIRST + 1);
+ else
+ this_rtx = gen_rtx_REG (Pmode, ARG_REG_FIRST);
+
+ /* Add DELTA to THIS_RTX. */
+ if (delta != 0)
+ {
+ rtx offset = GEN_INT (delta);
+ if (!CONST_OK_FOR_LETTER_P (delta, 'L'))
+ {
+ emit_move_insn (temp1, offset);
+ offset = temp1;
+ }
+ emit_insn (gen_add3_insn (this_rtx, this_rtx, offset));
+ }
+
+ /* If needed, add *(*THIS_RTX + VCALL_OFFSET) to THIS_RTX. */
+ if (vcall_offset != 0)
+ {
+ rtx addr;
+
+ /* Set TEMP1 to *THIS_RTX. */
+ emit_move_insn (temp1, gen_rtx_MEM (Pmode, this_rtx));
+
+ /* Set ADDR to a legitimate address for *THIS_RTX + VCALL_OFFSET. */
+ addr = score7_add_offset (temp1, vcall_offset);
+
+ /* Load the offset and add it to THIS_RTX. */
+ emit_move_insn (temp1, gen_rtx_MEM (Pmode, addr));
+ emit_insn (gen_add3_insn (this_rtx, this_rtx, temp1));
+ }
+
+ /* Jump to the target function. */
+ fnaddr = XEXP (DECL_RTL (function), 0);
+ insn = emit_call_insn (gen_sibcall_internal_score7 (fnaddr, const0_rtx));
+ SIBLING_CALL_P (insn) = 1;
+
+ /* Run just enough of rest_of_compilation. This sequence was
+ "borrowed" from alpha.c. */
+ insn = get_insns ();
+ insn_locators_alloc ();
+ split_all_insns_noflow ();
+ shorten_branches (insn);
+ final_start_function (insn, file, 1);
+ final (insn, file, 1);
+ final_end_function ();
+
+ /* Clean up the vars set above. Note that final_end_function resets
+ the global pointer for us. */
+ reload_completed = 0;
+}
+
+/* Copy VALUE to a register and return that register. If new psuedos
+ are allowed, copy it into a new register, otherwise use DEST. */
+static rtx
+score7_force_temporary (rtx dest, rtx value)
+{
+ if (can_create_pseudo_p ())
+ return force_reg (Pmode, value);
+ else
+ {
+ emit_move_insn (copy_rtx (dest), value);
+ return dest;
+ }
+}
+
+/* Return a LO_SUM expression for ADDR. TEMP is as for score_force_temporary
+ and is used to load the high part into a register. */
+static rtx
+score7_split_symbol (rtx temp, rtx addr)
+{
+ rtx high = score7_force_temporary (temp,
+ gen_rtx_HIGH (Pmode, copy_rtx (addr)));
+ return gen_rtx_LO_SUM (Pmode, high, addr);
+}
+
+/* This function is used to implement LEGITIMIZE_ADDRESS. If X can
+ be legitimized in a way that the generic machinery might not expect,
+ return the new address. */
+rtx
+score7_legitimize_address (rtx x)
+{
+ enum score_symbol_type symbol_type;
+
+ if (score7_symbolic_constant_p (x, &symbol_type)
+ && symbol_type == SYMBOL_GENERAL)
+ return score7_split_symbol (0, x);
+
+ if (GET_CODE (x) == PLUS
+ && GET_CODE (XEXP (x, 1)) == CONST_INT)
+ {
+ rtx reg = XEXP (x, 0);
+ if (!score7_valid_base_register_p (reg, 0))
+ reg = copy_to_mode_reg (Pmode, reg);
+ return score7_add_offset (reg, INTVAL (XEXP (x, 1)));
+ }
+
+ return x;
+}
+
+/* Fill INFO with information about a single argument. CUM is the
+ cumulative state for earlier arguments. MODE is the mode of this
+ argument and TYPE is its type (if known). NAMED is true if this
+ is a named (fixed) argument rather than a variable one. */
+static void
+score7_classify_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ tree type, int named, struct score7_arg_info *info)
+{
+ int even_reg_p;
+ unsigned int num_words, max_regs;
+
+ even_reg_p = 0;
+ if (GET_MODE_CLASS (mode) == MODE_INT
+ || GET_MODE_CLASS (mode) == MODE_FLOAT)
+ even_reg_p = (GET_MODE_SIZE (mode) > UNITS_PER_WORD);
+ else
+ if (type != NULL_TREE && TYPE_ALIGN (type) > BITS_PER_WORD && named)
+ even_reg_p = 1;
+
+ if (TARGET_MUST_PASS_IN_STACK (mode, type))
+ info->reg_offset = ARG_REG_NUM;
+ else
+ {
+ info->reg_offset = cum->num_gprs;
+ if (even_reg_p)
+ info->reg_offset += info->reg_offset & 1;
+ }
+
+ if (mode == BLKmode)
+ info->num_bytes = int_size_in_bytes (type);
+ else
+ info->num_bytes = GET_MODE_SIZE (mode);
+
+ num_words = (info->num_bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+ max_regs = ARG_REG_NUM - info->reg_offset;
+
+ /* Partition the argument between registers and stack. */
+ info->reg_words = MIN (num_words, max_regs);
+ info->stack_words = num_words - info->reg_words;
+
+ /* The alignment applied to registers is also applied to stack arguments. */
+ if (info->stack_words)
+ {
+ info->stack_offset = cum->stack_words;
+ if (even_reg_p)
+ info->stack_offset += info->stack_offset & 1;
+ }
+}
+
+/* Set up the stack and frame (if desired) for the function. */
+void
+score7_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
+{
+ const char *fnname;
+ struct score7_frame_info *f = score7_cached_frame ();
+ HOST_WIDE_INT tsize = f->total_size;
+
+ fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
+ if (!flag_inhibit_size_directive)
+ {
+ fputs ("\t.ent\t", file);
+ assemble_name (file, fnname);
+ fputs ("\n", file);
+ }
+ assemble_name (file, fnname);
+ fputs (":\n", file);
+
+ if (!flag_inhibit_size_directive)
+ {
+ fprintf (file,
+ "\t.frame\t%s," HOST_WIDE_INT_PRINT_DEC ",%s, %d\t\t"
+ "# vars= " HOST_WIDE_INT_PRINT_DEC ", regs= %d"
+ ", args= " HOST_WIDE_INT_PRINT_DEC
+ ", gp= " HOST_WIDE_INT_PRINT_DEC "\n",
+ (reg_names[(frame_pointer_needed)
+ ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM]),
+ tsize,
+ reg_names[RA_REGNUM],
+ current_function_is_leaf ? 1 : 0,
+ f->var_size,
+ f->num_gp,
+ f->args_size,
+ f->cprestore_size);
+
+ fprintf(file, "\t.mask\t0x%08x," HOST_WIDE_INT_PRINT_DEC "\n",
+ f->mask,
+ (f->gp_sp_offset - f->total_size));
+ }
+}
+
+/* Do any necessary cleanup after a function to restore stack, frame,
+ and regs. */
+void
+score7_function_epilogue (FILE *file,
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED)
+{
+ if (!flag_inhibit_size_directive)
+ {
+ const char *fnname;
+ fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
+ fputs ("\t.end\t", file);
+ assemble_name (file, fnname);
+ fputs ("\n", file);
+ }
+}
+
+/* Returns true if X contains a SYMBOL_REF. */
+static bool
+score7_symbolic_expression_p (rtx x)
+{
+ if (GET_CODE (x) == SYMBOL_REF)
+ return true;
+
+ if (GET_CODE (x) == CONST)
+ return score7_symbolic_expression_p (XEXP (x, 0));
+
+ if (UNARY_P (x))
+ return score7_symbolic_expression_p (XEXP (x, 0));
+
+ if (ARITHMETIC_P (x))
+ return (score7_symbolic_expression_p (XEXP (x, 0))
+ || score7_symbolic_expression_p (XEXP (x, 1)));
+
+ return false;
+}
+
+/* Choose the section to use for the constant rtx expression X that has
+ mode MODE. */
+section *
+score7_select_rtx_section (enum machine_mode mode, rtx x,
+ unsigned HOST_WIDE_INT align)
+{
+ if (GET_MODE_SIZE (mode) <= SCORE7_SDATA_MAX)
+ return get_named_section (0, ".sdata", 0);
+ else if (flag_pic && score7_symbolic_expression_p (x))
+ return get_named_section (0, ".data.rel.ro", 3);
+ else
+ return mergeable_constant_section (mode, align, 0);
+}
+
+/* Implement TARGET_IN_SMALL_DATA_P. */
+bool
+score7_in_small_data_p (tree decl)
+{
+ HOST_WIDE_INT size;
+
+ if (TREE_CODE (decl) == STRING_CST
+ || TREE_CODE (decl) == FUNCTION_DECL)
+ return false;
+
+ if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl) != 0)
+ {
+ const char *name;
+ name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
+ if (strcmp (name, ".sdata") != 0
+ && strcmp (name, ".sbss") != 0)
+ return true;
+ if (!DECL_EXTERNAL (decl))
+ return false;
+ }
+ size = int_size_in_bytes (TREE_TYPE (decl));
+ return (size > 0 && size <= SCORE7_SDATA_MAX);
+}
+
+/* Implement TARGET_ASM_FILE_START. */
+void
+score7_asm_file_start (void)
+{
+ default_file_start ();
+ fprintf (asm_out_file, ASM_COMMENT_START
+ "GCC for S+core %s \n", SCORE_GCC_VERSION);
+
+ if (flag_pic)
+ fprintf (asm_out_file, "\t.set pic\n");
+}
+
+/* Implement TARGET_ASM_FILE_END. When using assembler macros, emit
+ .externs for any small-data variables that turned out to be external. */
+void
+score7_asm_file_end (void)
+{
+ tree name_tree;
+ struct extern_list *p;
+ if (extern_head)
+ {
+ fputs ("\n", asm_out_file);
+ for (p = extern_head; p != 0; p = p->next)
+ {
+ name_tree = get_identifier (p->name);
+ if (!TREE_ASM_WRITTEN (name_tree)
+ && TREE_SYMBOL_REFERENCED (name_tree))
+ {
+ TREE_ASM_WRITTEN (name_tree) = 1;
+ fputs ("\t.extern\t", asm_out_file);
+ assemble_name (asm_out_file, p->name);
+ fprintf (asm_out_file, ", %d\n", p->size);
+ }
+ }
+ }
+}
+
+/* Implement OVERRIDE_OPTIONS macro. */
+void
+score7_override_options (void)
+{
+ flag_pic = false;
+ if (!flag_pic)
+ score7_sdata_max = g_switch_set ? g_switch_value : SCORE7_DEFAULT_SDATA_MAX;
+ else
+ {
+ score7_sdata_max = 0;
+ if (g_switch_set && (g_switch_value != 0))
+ warning (0, "-fPIC and -G are incompatible");
+ }
+
+ score_char_to_class['d'] = G32_REGS;
+ score_char_to_class['e'] = G16_REGS;
+ score_char_to_class['t'] = T32_REGS;
+
+ score_char_to_class['h'] = HI_REG;
+ score_char_to_class['l'] = LO_REG;
+ score_char_to_class['x'] = CE_REGS;
+
+ score_char_to_class['q'] = CN_REG;
+ score_char_to_class['y'] = LC_REG;
+ score_char_to_class['z'] = SC_REG;
+ score_char_to_class['a'] = SP_REGS;
+
+ score_char_to_class['c'] = CR_REGS;
+}
+
+/* Implement REGNO_REG_CLASS macro. */
+int
+score7_reg_class (int regno)
+{
+ int c;
+ gcc_assert (regno >= 0 && regno < FIRST_PSEUDO_REGISTER);
+
+ if (regno == FRAME_POINTER_REGNUM
+ || regno == ARG_POINTER_REGNUM)
+ return ALL_REGS;
+
+ for (c = 0; c < N_REG_CLASSES; c++)
+ if (TEST_HARD_REG_BIT (reg_class_contents[c], regno))
+ return c;
+
+ return NO_REGS;
+}
+
+/* Implement PREFERRED_RELOAD_CLASS macro. */
+enum reg_class
+score7_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, enum reg_class rclass)
+{
+ if (reg_class_subset_p (G16_REGS, rclass))
+ return G16_REGS;
+ if (reg_class_subset_p (G32_REGS, rclass))
+ return G32_REGS;
+ return rclass;
+}
+
+/* Implement SECONDARY_INPUT_RELOAD_CLASS
+ and SECONDARY_OUTPUT_RELOAD_CLASS macro. */
+enum reg_class
+score7_secondary_reload_class (enum reg_class rclass,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ rtx x)
+{
+ int regno = -1;
+ if (GET_CODE (x) == REG || GET_CODE(x) == SUBREG)
+ regno = true_regnum (x);
+
+ if (!GR_REG_CLASS_P (rclass))
+ return GP_REG_P (regno) ? NO_REGS : G32_REGS;
+ return NO_REGS;
+}
+
+/* Implement CONST_OK_FOR_LETTER_P macro. */
+/* imm constraints
+ I imm16 << 16
+ J uimm5
+ K uimm16
+ L simm16
+ M uimm14
+ N simm14 */
+int
+score7_const_ok_for_letter_p (HOST_WIDE_INT value, char c)
+{
+ switch (c)
+ {
+ case 'I': return ((value & 0xffff) == 0);
+ case 'J': return IMM_IN_RANGE (value, 5, 0);
+ case 'K': return IMM_IN_RANGE (value, 16, 0);
+ case 'L': return IMM_IN_RANGE (value, 16, 1);
+ case 'M': return IMM_IN_RANGE (value, 14, 0);
+ case 'N': return IMM_IN_RANGE (value, 14, 1);
+ default : return 0;
+ }
+}
+
+/* Implement EXTRA_CONSTRAINT macro. */
+/* Z symbol_ref */
+int
+score7_extra_constraint (rtx op, char c)
+{
+ switch (c)
+ {
+ case 'Z':
+ return GET_CODE (op) == SYMBOL_REF;
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Return truth value on whether or not a given hard register
+ can support a given mode. */
+int
+score7_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
+{
+ int size = GET_MODE_SIZE (mode);
+ enum mode_class mclass = GET_MODE_CLASS (mode);
+
+ if (mclass == MODE_CC)
+ return regno == CC_REGNUM;
+ else if (regno == FRAME_POINTER_REGNUM
+ || regno == ARG_POINTER_REGNUM)
+ return mclass == MODE_INT;
+ else if (GP_REG_P (regno))
+ /* ((regno <= (GP_REG_LAST- HARD_REGNO_NREGS (dummy, mode)) + 1) */
+ return !(regno & 1) || (size <= UNITS_PER_WORD);
+ else if (CE_REG_P (regno))
+ return (mclass == MODE_INT
+ && ((size <= UNITS_PER_WORD)
+ || (regno == CE_REG_FIRST && size == 2 * UNITS_PER_WORD)));
+ else
+ return (mclass == MODE_INT) && (size <= UNITS_PER_WORD);
+}
+
+/* Implement INITIAL_ELIMINATION_OFFSET. FROM is either the frame
+ pointer or argument pointer. TO is either the stack pointer or
+ hard frame pointer. */
+HOST_WIDE_INT
+score7_initial_elimination_offset (int from,
+ int to ATTRIBUTE_UNUSED)
+{
+ struct score7_frame_info *f = score7_compute_frame_size (get_frame_size ());
+ switch (from)
+ {
+ case ARG_POINTER_REGNUM:
+ return f->total_size;
+ case FRAME_POINTER_REGNUM:
+ return 0;
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Implement FUNCTION_ARG_ADVANCE macro. */
+void
+score7_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ tree type, int named)
+{
+ struct score7_arg_info info;
+ score7_classify_arg (cum, mode, type, named, &info);
+ cum->num_gprs = info.reg_offset + info.reg_words;
+ if (info.stack_words > 0)
+ cum->stack_words = info.stack_offset + info.stack_words;
+ cum->arg_number++;
+}
+
+/* Implement TARGET_ARG_PARTIAL_BYTES macro. */
+int
+score7_arg_partial_bytes (CUMULATIVE_ARGS *cum,
+ enum machine_mode mode, tree type, bool named)
+{
+ struct score7_arg_info info;
+ score7_classify_arg (cum, mode, type, named, &info);
+ return info.stack_words > 0 ? info.reg_words * UNITS_PER_WORD : 0;
+}
+
+/* Implement FUNCTION_ARG macro. */
+rtx
+score7_function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ tree type, int named)
+{
+ struct score7_arg_info info;
+
+ if (mode == VOIDmode || !named)
+ return 0;
+
+ score7_classify_arg (cum, mode, type, named, &info);
+
+ if (info.reg_offset == ARG_REG_NUM)
+ return 0;
+
+ if (!info.stack_words)
+ return gen_rtx_REG (mode, ARG_REG_FIRST + info.reg_offset);
+ else
+ {
+ rtx ret = gen_rtx_PARALLEL (mode, rtvec_alloc (info.reg_words));
+ unsigned int i, part_offset = 0;
+ for (i = 0; i < info.reg_words; i++)
+ {
+ rtx reg;
+ reg = gen_rtx_REG (SImode, ARG_REG_FIRST + info.reg_offset + i);
+ XVECEXP (ret, 0, i) = gen_rtx_EXPR_LIST (SImode, reg,
+ GEN_INT (part_offset));
+ part_offset += UNITS_PER_WORD;
+ }
+ return ret;
+ }
+}
+
+/* Implement FUNCTION_VALUE and LIBCALL_VALUE. For normal calls,
+ VALTYPE is the return type and MODE is VOIDmode. For libcalls,
+ VALTYPE is null and MODE is the mode of the return value. */
+rtx
+score7_function_value (tree valtype, tree func, enum machine_mode mode)
+{
+ if (valtype)
+ {
+ int unsignedp;
+ mode = TYPE_MODE (valtype);
+ unsignedp = TYPE_UNSIGNED (valtype);
+ mode = promote_function_mode (valtype, mode, &unsignedp, func, 1);
+ }
+ return gen_rtx_REG (mode, RT_REGNUM);
+}
+
+/* Implement TARGET_ASM_TRAMPOLINE_TEMPLATE. */
+
+void
+score7_asm_trampoline_template (FILE *f)
+{
+ fprintf (f, "\t.set r1\n");
+ fprintf (f, "\tmv r31, r3\n");
+ fprintf (f, "\tbl nextinsn\n");
+ fprintf (f, "nextinsn:\n");
+ fprintf (f, "\tlw r1, [r3, 6*4-8]\n");
+ fprintf (f, "\tlw r23, [r3, 6*4-4]\n");
+ fprintf (f, "\tmv r3, r31\n");
+ fprintf (f, "\tbr! r1\n");
+ fprintf (f, "\tnop!\n");
+ fprintf (f, "\t.set nor1\n");
+}
+
+/* Implement TARGET_TRAMPOLINE_INIT. */
+void
+score7_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
+{
+#define FFCACHE "_flush_cache"
+#define CODE_SIZE (TRAMPOLINE_INSNS * UNITS_PER_WORD)
+
+ rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
+ rtx addr = XEXP (m_tramp, 0);
+ rtx mem;
+
+ emit_block_move (m_tramp, assemble_trampoline_template (),
+ GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
+
+ mem = adjust_address (m_tramp, SImode, CODE_SIZE);
+ emit_move_insn (mem, fnaddr);
+ mem = adjust_address (m_tramp, SImode, CODE_SIZE + GET_MODE_SIZE (SImode));
+ emit_move_insn (mem, chain_value);
+
+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, FFCACHE),
+ 0, VOIDmode, 2,
+ addr, Pmode,
+ GEN_INT (TRAMPOLINE_SIZE), SImode);
+#undef FFCACHE
+#undef CODE_SIZE
+}
+
+/* This function is used to implement REG_MODE_OK_FOR_BASE_P macro. */
+int
+score7_regno_mode_ok_for_base_p (int regno, int strict)
+{
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ {
+ if (!strict)
+ return 1;
+ regno = reg_renumber[regno];
+ }
+ if (regno == ARG_POINTER_REGNUM
+ || regno == FRAME_POINTER_REGNUM)
+ return 1;
+ return GP_REG_P (regno);
+}
+
+/* Implement TARGET_LEGITIMATE_ADDRESS_P macro. */
+bool
+score7_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
+{
+ struct score7_address_info addr;
+
+ return score7_classify_address (&addr, mode, x, strict);
+}
+
+/* Return a number assessing the cost of moving a register in class
+ FROM to class TO. */
+int
+score7_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+ enum reg_class from, enum reg_class to)
+{
+ if (GR_REG_CLASS_P (from))
+ {
+ if (GR_REG_CLASS_P (to))
+ return 2;
+ else if (SP_REG_CLASS_P (to))
+ return 4;
+ else if (CP_REG_CLASS_P (to))
+ return 5;
+ else if (CE_REG_CLASS_P (to))
+ return 6;
+ }
+ if (GR_REG_CLASS_P (to))
+ {
+ if (GR_REG_CLASS_P (from))
+ return 2;
+ else if (SP_REG_CLASS_P (from))
+ return 4;
+ else if (CP_REG_CLASS_P (from))
+ return 5;
+ else if (CE_REG_CLASS_P (from))
+ return 6;
+ }
+ return 12;
+}
+
+/* Return the number of instructions needed to load a symbol of the
+ given type into a register. */
+static int
+score7_symbol_insns (enum score_symbol_type type)
+{
+ switch (type)
+ {
+ case SYMBOL_GENERAL:
+ return 2;
+
+ case SYMBOL_SMALL_DATA:
+ return 1;
+ }
+
+ gcc_unreachable ();
+}
+
+/* Return the number of instructions needed to load or store a value
+ of mode MODE at X. Return 0 if X isn't valid for MODE. */
+static int
+score7_address_insns (rtx x, enum machine_mode mode)
+{
+ struct score7_address_info addr;
+ int factor;
+
+ if (mode == BLKmode)
+ factor = 1;
+ else
+ factor = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+
+ if (score7_classify_address (&addr, mode, x, false))
+ switch (addr.type)
+ {
+ case SCORE7_ADD_REG:
+ case SCORE7_ADD_CONST_INT:
+ return factor;
+
+ case SCORE7_ADD_SYMBOLIC:
+ return factor * score7_symbol_insns (addr.symbol_type);
+ }
+ return 0;
+}
+
+/* Implement TARGET_RTX_COSTS macro. */
+bool
+score7_rtx_costs (rtx x, int code, int outer_code, int *total,
+ bool speed ATTRIBUTE_UNUSED)
+{
+ enum machine_mode mode = GET_MODE (x);
+
+ switch (code)
+ {
+ case CONST_INT:
+ if (outer_code == SET)
+ {
+ if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I')
+ || CONST_OK_FOR_LETTER_P (INTVAL (x), 'L'))
+ *total = COSTS_N_INSNS (1);
+ else
+ *total = COSTS_N_INSNS (2);
+ }
+ else if (outer_code == PLUS || outer_code == MINUS)
+ {
+ if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'N'))
+ *total = 0;
+ else if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I')
+ || CONST_OK_FOR_LETTER_P (INTVAL (x), 'L'))
+ *total = 1;
+ else
+ *total = COSTS_N_INSNS (2);
+ }
+ else if (outer_code == AND || outer_code == IOR)
+ {
+ if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'M'))
+ *total = 0;
+ else if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I')
+ || CONST_OK_FOR_LETTER_P (INTVAL (x), 'K'))
+ *total = 1;
+ else
+ *total = COSTS_N_INSNS (2);
+ }
+ else
+ {
+ *total = 0;
+ }
+ return true;
+
+ case CONST:
+ case SYMBOL_REF:
+ case LABEL_REF:
+ case CONST_DOUBLE:
+ *total = COSTS_N_INSNS (2);
+ return true;
+
+ case MEM:
+ {
+ /* If the address is legitimate, return the number of
+ instructions it needs, otherwise use the default handling. */
+ int n = score7_address_insns (XEXP (x, 0), GET_MODE (x));
+ if (n > 0)
+ {
+ *total = COSTS_N_INSNS (n + 1);
+ return true;
+ }
+ return false;
+ }
+
+ case FFS:
+ *total = COSTS_N_INSNS (6);
+ return true;
+
+ case NOT:
+ *total = COSTS_N_INSNS (1);
+ return true;
+
+ case AND:
+ case IOR:
+ case XOR:
+ if (mode == DImode)
+ {
+ *total = COSTS_N_INSNS (2);
+ return true;
+ }
+ return false;
+
+ case ASHIFT:
+ case ASHIFTRT:
+ case LSHIFTRT:
+ if (mode == DImode)
+ {
+ *total = COSTS_N_INSNS ((GET_CODE (XEXP (x, 1)) == CONST_INT)
+ ? 4 : 12);
+ return true;
+ }
+ return false;
+
+ case ABS:
+ *total = COSTS_N_INSNS (4);
+ return true;
+
+ case PLUS:
+ case MINUS:
+ if (mode == DImode)
+ {
+ *total = COSTS_N_INSNS (4);
+ return true;
+ }
+ *total = COSTS_N_INSNS (1);
+ return true;
+
+ case NEG:
+ if (mode == DImode)
+ {
+ *total = COSTS_N_INSNS (4);
+ return true;
+ }
+ return false;
+
+ case MULT:
+ *total = optimize_size ? COSTS_N_INSNS (2) : COSTS_N_INSNS (12);
+ return true;
+
+ case DIV:
+ case MOD:
+ case UDIV:
+ case UMOD:
+ *total = optimize_size ? COSTS_N_INSNS (2) : COSTS_N_INSNS (33);
+ return true;
+
+ case SIGN_EXTEND:
+ case ZERO_EXTEND:
+ switch (GET_MODE (XEXP (x, 0)))
+ {
+ case QImode:
+ case HImode:
+ if (GET_CODE (XEXP (x, 0)) == MEM)
+ {
+ *total = COSTS_N_INSNS (2);
+
+ if (!TARGET_LITTLE_ENDIAN &&
+ side_effects_p (XEXP (XEXP (x, 0), 0)))
+ *total = 100;
+ }
+ else
+ *total = COSTS_N_INSNS (1);
+ break;
+
+ default:
+ *total = COSTS_N_INSNS (1);
+ break;
+ }
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+/* Implement TARGET_ADDRESS_COST macro. */
+int
+score7_address_cost (rtx addr)
+{
+ return score7_address_insns (addr, SImode);
+}
+
+/* Implement ASM_OUTPUT_EXTERNAL macro. */
+int
+score7_output_external (FILE *file ATTRIBUTE_UNUSED,
+ tree decl, const char *name)
+{
+ register struct extern_list *p;
+
+ if (score7_in_small_data_p (decl))
+ {
+ p = (struct extern_list *) ggc_alloc (sizeof (struct extern_list));
+ p->next = extern_head;
+ p->name = name;
+ p->size = int_size_in_bytes (TREE_TYPE (decl));
+ extern_head = p;
+ }
+ return 0;
+}
+
+/* Implement RETURN_ADDR_RTX. Note, we do not support moving
+ back to a previous frame. */
+rtx
+score7_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
+{
+ if (count != 0)
+ return const0_rtx;
+ return get_hard_reg_initial_val (Pmode, RA_REGNUM);
+}
+
+/* Implement PRINT_OPERAND macro. */
+/* Score-specific operand codes:
+ '[' print .set nor1 directive
+ ']' print .set r1 directive
+ 'U' print hi part of a CONST_INT rtx
+ 'E' print log2(v)
+ 'F' print log2(~v)
+ 'D' print SFmode const double
+ 'S' selectively print "!" if operand is 15bit instruction accessible
+ 'V' print "v!" if operand is 15bit instruction accessible, or "lfh!"
+ 'L' low part of DImode reg operand
+ 'H' high part of DImode reg operand
+ 'C' print part of opcode for a branch condition. */
+void
+score7_print_operand (FILE *file, rtx op, int c)
+{
+ enum rtx_code code = -1;
+ if (!PRINT_OPERAND_PUNCT_VALID_P (c))
+ code = GET_CODE (op);
+
+ if (c == '[')
+ {
+ fprintf (file, ".set r1\n");
+ }
+ else if (c == ']')
+ {
+ fprintf (file, "\n\t.set nor1");
+ }
+ else if (c == 'U')
+ {
+ gcc_assert (code == CONST_INT);
+ fprintf (file, HOST_WIDE_INT_PRINT_HEX,
+ (INTVAL (op) >> 16) & 0xffff);
+ }
+ else if (c == 'D')
+ {
+ if (GET_CODE (op) == CONST_DOUBLE)
+ {
+ rtx temp = gen_lowpart (SImode, op);
+ gcc_assert (GET_MODE (op) == SFmode);
+ fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (temp) & 0xffffffff);
+ }
+ else
+ output_addr_const (file, op);
+ }
+ else if (c == 'S')
+ {
+ gcc_assert (code == REG);
+ if (G16_REG_P (REGNO (op)))
+ fprintf (file, "!");
+ }
+ else if (c == 'V')
+ {
+ gcc_assert (code == REG);
+ fprintf (file, G16_REG_P (REGNO (op)) ? "v!" : "lfh!");
+ }
+ else if (c == 'C')
+ {
+ enum machine_mode mode = GET_MODE (XEXP (op, 0));
+
+ switch (code)
+ {
+ case EQ: fputs ("eq", file); break;
+ case NE: fputs ("ne", file); break;
+ case GT: fputs ("gt", file); break;
+ case GE: fputs (mode != CCmode ? "pl" : "ge", file); break;
+ case LT: fputs (mode != CCmode ? "mi" : "lt", file); break;
+ case LE: fputs ("le", file); break;
+ case GTU: fputs ("gtu", file); break;
+ case GEU: fputs ("cs", file); break;
+ case LTU: fputs ("cc", file); break;
+ case LEU: fputs ("leu", file); break;
+ default:
+ output_operand_lossage ("invalid operand for code: '%c'", code);
+ }
+ }
+ else if (c == 'E')
+ {
+ unsigned HOST_WIDE_INT i;
+ unsigned HOST_WIDE_INT pow2mask = 1;
+ unsigned HOST_WIDE_INT val;
+
+ val = INTVAL (op);
+ for (i = 0; i < 32; i++)
+ {
+ if (val == pow2mask)
+ break;
+ pow2mask <<= 1;
+ }
+ gcc_assert (i < 32);
+ fprintf (file, HOST_WIDE_INT_PRINT_HEX, i);
+ }
+ else if (c == 'F')
+ {
+ unsigned HOST_WIDE_INT i;
+ unsigned HOST_WIDE_INT pow2mask = 1;
+ unsigned HOST_WIDE_INT val;
+
+ val = ~INTVAL (op);
+ for (i = 0; i < 32; i++)
+ {
+ if (val == pow2mask)
+ break;
+ pow2mask <<= 1;
+ }
+ gcc_assert (i < 32);
+ fprintf (file, HOST_WIDE_INT_PRINT_HEX, i);
+ }
+ else if (code == REG)
+ {
+ int regnum = REGNO (op);
+ if ((c == 'H' && !WORDS_BIG_ENDIAN)
+ || (c == 'L' && WORDS_BIG_ENDIAN))
+ regnum ++;
+ fprintf (file, "%s", reg_names[regnum]);
+ }
+ else
+ {
+ switch (code)
+ {
+ case MEM:
+ score7_print_operand_address (file, op);
+ break;
+ default:
+ output_addr_const (file, op);
+ }
+ }
+}
+
+/* Implement PRINT_OPERAND_ADDRESS macro. */
+void
+score7_print_operand_address (FILE *file, rtx x)
+{
+ struct score7_address_info addr;
+ enum rtx_code code = GET_CODE (x);
+ enum machine_mode mode = GET_MODE (x);
+
+ if (code == MEM)
+ x = XEXP (x, 0);
+
+ if (score7_classify_address (&addr, mode, x, true))
+ {
+ switch (addr.type)
+ {
+ case SCORE7_ADD_REG:
+ {
+ switch (addr.code)
+ {
+ case PRE_DEC:
+ fprintf (file, "[%s,-%ld]+", reg_names[REGNO (addr.reg)],
+ INTVAL (addr.offset));
+ break;
+ case POST_DEC:
+ fprintf (file, "[%s]+,-%ld", reg_names[REGNO (addr.reg)],
+ INTVAL (addr.offset));
+ break;
+ case PRE_INC:
+ fprintf (file, "[%s, %ld]+", reg_names[REGNO (addr.reg)],
+ INTVAL (addr.offset));
+ break;
+ case POST_INC:
+ fprintf (file, "[%s]+, %ld", reg_names[REGNO (addr.reg)],
+ INTVAL (addr.offset));
+ break;
+ default:
+ if (INTVAL(addr.offset) == 0)
+ fprintf(file, "[%s]", reg_names[REGNO (addr.reg)]);
+ else
+ fprintf(file, "[%s, %ld]", reg_names[REGNO (addr.reg)],
+ INTVAL(addr.offset));
+ break;
+ }
+ }
+ return;
+ case SCORE7_ADD_CONST_INT:
+ case SCORE7_ADD_SYMBOLIC:
+ output_addr_const (file, x);
+ return;
+ }
+ }
+ print_rtl (stderr, x);
+ gcc_unreachable ();
+}
+
+/* Implement SELECT_CC_MODE macro. */
+enum machine_mode
+score7_select_cc_mode (enum rtx_code op, rtx x, rtx y)
+{
+ if ((op == EQ || op == NE || op == LT || op == GE)
+ && y == const0_rtx
+ && GET_MODE (x) == SImode)
+ {
+ switch (GET_CODE (x))
+ {
+ case PLUS:
+ case MINUS:
+ case NEG:
+ case AND:
+ case IOR:
+ case XOR:
+ case NOT:
+ case ASHIFT:
+ case LSHIFTRT:
+ case ASHIFTRT:
+ return CC_NZmode;
+
+ case SIGN_EXTEND:
+ case ZERO_EXTEND:
+ case ROTATE:
+ case ROTATERT:
+ return (op == LT || op == GE) ? CC_Nmode : CCmode;
+
+ default:
+ return CCmode;
+ }
+ }
+
+ if ((op == EQ || op == NE)
+ && (GET_CODE (y) == NEG)
+ && register_operand (XEXP (y, 0), SImode)
+ && register_operand (x, SImode))
+ {
+ return CC_NZmode;
+ }
+
+ return CCmode;
+}
+
+/* Generate the prologue instructions for entry into a S+core function. */
+void
+score7_prologue (void)
+{
+#define EMIT_PL(_rtx) RTX_FRAME_RELATED_P (_rtx) = 1
+
+ struct score7_frame_info *f = score7_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_score7 ());
+
+ 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 (!crtl->calls_eh_return)
+ MEM_READONLY_P (mem) = 1;
+ EMIT_PL (emit_insn (gen_pushsi_score7 (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, SCORE7_PROLOGUE_TEMP_REGNUM),
+ GEN_INT (size)));
+ EMIT_PL (emit_insn
+ (gen_sub3_insn (stack_pointer_rtx,
+ stack_pointer_rtx,
+ gen_rtx_REG (Pmode,
+ SCORE7_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 && f->cprestore_size)
+ {
+ if (frame_pointer_needed)
+ emit_insn (gen_cprestore_use_fp_score7 (GEN_INT (size - f->cprestore_size)));
+ else
+ emit_insn (gen_cprestore_use_sp_score7 (GEN_INT (size - f->cprestore_size)));
+ }
+
+#undef EMIT_PL
+}
+
+/* Generate the epilogue instructions in a S+core function. */
+void
+score7_epilogue (int sibcall_p)
+{
+ struct score7_frame_info *f = score7_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, SCORE7_EPILOGUE_TEMP_REGNUM),
+ GEN_INT (size));
+ emit_insn (gen_add3_insn (base, base,
+ gen_rtx_REG (Pmode,
+ SCORE7_EPILOGUE_TEMP_REGNUM)));
+ }
+ }
+
+ if (base != stack_pointer_rtx)
+ emit_move_insn (stack_pointer_rtx, base);
+
+ if (crtl->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 (!crtl->calls_eh_return)
+ MEM_READONLY_P (mem) = 1;
+
+ emit_insn (gen_popsi_score7 (reg, mem));
+ }
+ }
+
+ if (!sibcall_p)
+ emit_jump_insn (gen_return_internal_score7 (gen_rtx_REG (Pmode, RA_REGNUM)));
+}
+
+/* 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
+score7_symbolic_constant_p (rtx x, enum score_symbol_type *symbol_type)
+{
+ HOST_WIDE_INT offset;
+
+ score7_split_const (x, &x, &offset);
+ if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
+ *symbol_type = score7_classify_symbol (x);
+ else
+ return 0;
+
+ if (offset == 0)
+ return 1;
+
+ /* if offset > 15bit, must reload */
+ if (!IMM_IN_RANGE (offset, 15, 1))
+ return 0;
+
+ switch (*symbol_type)
+ {
+ case SYMBOL_GENERAL:
+ return 1;
+ case SYMBOL_SMALL_DATA:
+ return score7_offset_within_object_p (x, offset);
+ }
+ gcc_unreachable ();
+}
+
+void
+score7_movsicc (rtx *ops)
+{
+ enum machine_mode mode;
+
+ mode = score7_select_cc_mode (GET_CODE (ops[1]), ops[2], ops[3]);
+ emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (mode, CC_REGNUM),
+ gen_rtx_COMPARE (mode, XEXP (ops[1], 0),
+ XEXP (ops[1], 1))));
+}
+
+/* Call and sibcall pattern all need call this function. */
+void
+score7_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_score7 (addr, ops[1]));
+ else
+ emit_call_insn (gen_call_internal_score7 (addr, ops[1]));
+}
+
+/* Call value and sibcall value pattern all need call this function. */
+void
+score7_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_score7 (result, addr, arg));
+ else
+ emit_call_insn (gen_call_value_internal_score7 (result, addr, arg));
+}
+
+/* Machine Split */
+void
+score7_movdi (rtx *ops)
+{
+ rtx dst = ops[0];
+ rtx src = ops[1];
+ rtx dst0 = score7_subw (dst, 0);
+ rtx dst1 = score7_subw (dst, 1);
+ rtx src0 = score7_subw (src, 0);
+ rtx src1 = score7_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
+score7_zero_extract_andi (rtx *ops)
+{
+ if (INTVAL (ops[1]) == 1 && const_uimm5 (ops[2], SImode))
+ emit_insn (gen_zero_extract_bittst_score7 (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_score7 (ops[3], ops[0],
+ gen_int_mode (mask, SImode)));
+ }
+}
+
+/* Check addr could be present as PRE/POST mode. */
+static bool
+score7_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
+score7_pr_addr_post (rtx *ops, int idata, int iaddr, char *ip, enum score_mem_unit unit)
+{
+ struct score7_address_info ai;
+
+ gcc_assert (GET_CODE (ops[idata]) == REG);
+ gcc_assert (score7_classify_address (&ai, SImode, XEXP (ops[iaddr], 0), true));
+
+ if (!score7_pindex_mem (ops[iaddr])
+ && ai.type == SCORE7_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,
+ "!\t%%%d, [%%%d]", idata, iaddr);
+ }
+ if (REGNO (ai.reg) == HARD_FRAME_POINTER_REGNUM)
+ {
+ HOST_WIDE_INT offset = INTVAL (ai.offset);
+ if (SCORE_ALIGN_UNIT (offset, unit)
+ && CONST_OK_FOR_LETTER_P (offset >> unit, 'J'))
+ {
+ ops[iaddr] = ai.offset;
+ return snprintf (ip, INS_BUF_SZ,
+ "p!\t%%%d, %%c%d", idata, iaddr);
+ }
+ }
+ }
+ return snprintf (ip, INS_BUF_SZ, "\t%%%d, %%a%d", idata, iaddr);
+}
+
+/* Output asm insn for load. */
+const char *
+score7_linsn (rtx *ops, enum score_mem_unit unit, bool sign)
+{
+ const char *pre_ins[] =
+ {"lbu", "lhu", "lw", "??", "lb", "lh", "lw", "??"};
+ char *ip;
+
+ strcpy (score7_ins, pre_ins[(sign ? 4 : 0) + unit]);
+ ip = score7_ins + strlen (score7_ins);
+
+ if ((!sign && unit != SCORE_HWORD)
+ || (sign && unit != SCORE_BYTE))
+ score7_pr_addr_post (ops, 0, 1, ip, unit);
+ else
+ snprintf (ip, INS_BUF_SZ, "\t%%0, %%a1");
+
+ return score7_ins;
+}
+
+/* Output asm insn for store. */
+const char *
+score7_sinsn (rtx *ops, enum score_mem_unit unit)
+{
+ const char *pre_ins[] = {"sb", "sh", "sw"};
+ char *ip;
+
+ strcpy (score7_ins, pre_ins[unit]);
+ ip = score7_ins + strlen (score7_ins);
+ score7_pr_addr_post (ops, 1, 0, ip, unit);
+ return score7_ins;
+}
+
+/* Output asm insn for load immediate. */
+const char *
+score7_limm (rtx *ops)
+{
+ HOST_WIDE_INT v;
+
+ gcc_assert (GET_CODE (ops[0]) == REG);
+ gcc_assert (GET_CODE (ops[1]) == CONST_INT);
+
+ v = INTVAL (ops[1]);
+ if (G16_REG_P (REGNO (ops[0])) && IMM_IN_RANGE (v, 8, 0))
+ return "ldiu!\t%0, %c1";
+ else if (IMM_IN_RANGE (v, 16, 1))
+ return "ldi\t%0, %c1";
+ else if ((v & 0xffff) == 0)
+ return "ldis\t%0, %U1";
+ else
+ return "li\t%0, %c1";
+}
+
+/* Output asm insn for move. */
+const char *
+score7_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!\t%0, %1";
+ else
+ return "mlfh!\t%0, %1";
+ }
+ else if (G16_REG_P (REGNO (ops[1])))
+ return "mhfl!\t%0, %1";
+ else
+ return "mv\t%0, %1";
+}
+
+/* Generate add insn. */
+const char *
+score7_select_add_imm (rtx *ops, bool set_cc)
+{
+ HOST_WIDE_INT v = INTVAL (ops[2]);
+
+ gcc_assert (GET_CODE (ops[2]) == CONST_INT);
+ gcc_assert (REGNO (ops[0]) == REGNO (ops[1]));
+
+ if (set_cc && G16_REG_P (REGNO (ops[0])))
+ {
+ if (v > 0 && IMM_IS_POW_OF_2 ((unsigned HOST_WIDE_INT) v, 0, 15))
+ {
+ ops[2] = GEN_INT (ffs (v) - 1);
+ return "addei!\t%0, %c2";
+ }
+
+ if (v < 0 && IMM_IS_POW_OF_2 ((unsigned HOST_WIDE_INT) (-v), 0, 15))
+ {
+ ops[2] = GEN_INT (ffs (-v) - 1);
+ return "subei!\t%0, %c2";
+ }
+ }
+
+ if (set_cc)
+ return "addi.c\t%0, %c2";
+ else
+ return "addi\t%0, %c2";
+}
+
+/* Output arith insn. */
+const char *
+score7_select (rtx *ops, const char *inst_pre,
+ bool commu, const char *letter, bool set_cc)
+{
+ gcc_assert (GET_CODE (ops[0]) == REG);
+ gcc_assert (GET_CODE (ops[1]) == REG);
+
+ if (set_cc && 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 (score7_ins, INS_BUF_SZ, "%s!\t%%0, %%%s2", inst_pre, letter);
+ return score7_ins;
+ }
+
+ if (commu && set_cc && 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 (score7_ins, INS_BUF_SZ, "%s!\t%%0, %%%s1", inst_pre, letter);
+ return score7_ins;
+ }
+
+ if (set_cc)
+ snprintf (score7_ins, INS_BUF_SZ, "%s.c\t%%0, %%1, %%%s2", inst_pre, letter);
+ else
+ snprintf (score7_ins, INS_BUF_SZ, "%s\t%%0, %%1, %%%s2", inst_pre, letter);
+ return score7_ins;
+}
+
score7.c
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: score-generic.md
===================================================================
--- score-generic.md (nonexistent)
+++ score-generic.md (revision 384)
@@ -0,0 +1,45 @@
+;; Machine description for Sunplus S+CORE
+;; Sunplus S+CORE Pipeline Description
+;; Copyright (C) 2005, 2007
+;; 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 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
+;; .
+
+(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")
Index: score3.h
===================================================================
--- score3.h (nonexistent)
+++ score3.h (revision 384)
@@ -0,0 +1,160 @@
+/* score3.h for Sunplus S+CORE processor
+ Copyright (C) 2005, 2007, 2008 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 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
+ . */
+
+#ifndef GCC_SCORE3_H
+#define GCC_SCORE3_H
+
+enum score3_address_type
+{
+ SCORE3_ADD_REG,
+ SCORE3_ADD_CONST_INT,
+ SCORE3_ADD_SYMBOLIC
+};
+
+struct score3_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 */
+};
+
+struct score3_arg_info
+{
+ unsigned int num_bytes; /* The argument's size in bytes */
+ unsigned int reg_words; /* The number of words passed in registers */
+ unsigned int reg_offset; /* The offset of the first register from */
+ /* GP_ARG_FIRST or FP_ARG_FIRST etc */
+ unsigned int stack_words; /* The number of words that must be passed */
+ /* on the stack */
+ unsigned int stack_offset; /* The offset from the start of the stack */
+ /* overflow area */
+};
+
+#ifdef RTX_CODE
+struct score3_address_info
+{
+ enum score3_address_type type;
+ rtx reg;
+ rtx offset;
+ enum rtx_code code;
+ enum score_symbol_type symbol_type;
+};
+#endif
+
+#define SCORE3_SDATA_MAX score3_sdata_max
+#define SCORE3_STACK_ALIGN(LOC) (((LOC) + 3) & ~3)
+#define SCORE3_PROLOGUE_TEMP_REGNUM (GP_REG_FIRST + 8)
+#define SCORE3_EPILOGUE_TEMP_REGNUM (GP_REG_FIRST + 8)
+#define SCORE3_DEFAULT_SDATA_MAX 8
+
+extern int score3_symbolic_constant_p (rtx x,
+ enum score_symbol_type *symbol_type);
+extern bool score3_return_in_memory (tree type,
+ tree fndecl ATTRIBUTE_UNUSED);
+extern void score3_output_mi_thunk (FILE *file,
+ tree thunk_fndecl ATTRIBUTE_UNUSED,
+ HOST_WIDE_INT delta,
+ HOST_WIDE_INT vcall_offset,
+ tree function);
+extern rtx score3_legitimize_address (rtx x);
+extern void
+score3_function_prologue (FILE *file,
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED);
+extern void
+score3_function_epilogue (FILE *file,
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED);
+extern section *score3_select_rtx_section (enum machine_mode mode, rtx x,
+ unsigned HOST_WIDE_INT align);
+extern bool score3_in_small_data_p (tree decl);
+extern void score3_asm_file_start (void);
+extern void score3_asm_file_end (void);
+extern void score3_override_options (void);
+extern int score3_reg_class (int regno);
+extern enum reg_class score3_preferred_reload_class (rtx x ATTRIBUTE_UNUSED,
+ enum reg_class rclass);
+extern enum reg_class
+score3_secondary_reload_class (enum reg_class rclass,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ rtx x);
+extern int score3_const_ok_for_letter_p (HOST_WIDE_INT value, char c);
+extern int score3_extra_constraint (rtx op, char c);
+extern int score3_hard_regno_mode_ok (unsigned int regno,
+ enum machine_mode mode);
+extern HOST_WIDE_INT
+score3_initial_elimination_offset (int from,
+ int to ATTRIBUTE_UNUSED);
+extern void score3_function_arg_advance (CUMULATIVE_ARGS *cum,
+ enum machine_mode mode,
+ tree type,
+ int named);
+extern int score3_arg_partial_bytes (CUMULATIVE_ARGS *cum,
+ enum machine_mode mode,
+ tree type,
+ bool named);
+extern rtx score3_function_arg (const CUMULATIVE_ARGS *cum,
+ enum machine_mode mode,
+ tree type,
+ int named);
+extern rtx score3_function_value (tree valtype,
+ tree func ATTRIBUTE_UNUSED,
+ enum machine_mode mode);
+extern void score3_asm_trampoline_template (FILE *);
+extern void score3_trampoline_init (rtx, tree, rtx);
+extern int score3_regno_mode_ok_for_base_p (int regno, int strict);
+extern bool score3_legitimate_address_p (enum machine_mode mode, rtx x,
+ bool strict);
+extern int score3_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+ enum reg_class from,
+ enum reg_class to);
+extern bool score3_rtx_costs (rtx x, int code, int outer_code, int *total, bool speed);
+extern int score3_address_cost (rtx addr);
+extern int score3_output_external (FILE *file ATTRIBUTE_UNUSED,
+ tree decl,
+ const char *name);
+extern rtx score3_return_addr (int count, rtx frame ATTRIBUTE_UNUSED);
+extern void score3_print_operand (FILE *file, rtx op, int c);
+extern void score3_print_operand_address (FILE *file, rtx x);
+extern enum machine_mode
+score3_select_cc_mode (enum rtx_code op, rtx x, rtx y);
+extern void score3_prologue (void);
+extern void score3_epilogue (int sibcall_p);
+extern void score3_call (rtx *ops, bool sib);
+extern void score3_call_value (rtx *ops, bool sib);
+extern void score3_movsicc (rtx *ops);
+extern void score3_movdi (rtx *ops);
+extern void score3_zero_extract_andi (rtx *ops);
+extern const char * score3_select_add_imm (rtx *ops, bool set_cc);
+extern const char * score3_select (rtx *ops, const char *inst_pre, bool commu,
+ const char *letter, bool set_cc);
+extern const char * score3_move (rtx *ops);
+extern const char * score3_limm (rtx *ops);
+extern const char *
+score3_linsn (rtx *ops, enum score_mem_unit unit, bool sign);
+extern const char *
+score3_sinsn (rtx *ops, enum score_mem_unit unit);
+extern const char * score3_output_casesi (rtx *operands);
+extern const char * score3_rpush (rtx *ops);
+extern const char * score3_rpop (rtx *ops);
+#endif
score3.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: crtn.asm
===================================================================
--- crtn.asm (nonexistent)
+++ crtn.asm (revision 384)
@@ -0,0 +1,50 @@
+# crtn.asm for Sunplus S+CORE
+
+# Copyright (C) 2005, 2009 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 3, or (at your option) any
+# later version.
+#
+# 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.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# .
+
+# This file makes sure that the .init and .fini sections do in
+# fact return.
+
+#ifndef __pic__
+.section .init, "ax", @progbits
+ lw r3, [r0, 20]
+ addi r0, 32
+ br r3
+
+.section .fini, "ax", @progbits
+ lw r3, [r0, 20]
+ addi r0, 32
+ br r3
+#else
+ .set pic
+.section .init, "ax", @progbits
+ lw r3, [r0, 20]
+ addi r0, 32
+ br r3
+
+ .set pic
+.section .fini, "ax", @progbits
+ lw r3, [r0, 20]
+ addi r0, 32
+ br r3
+#endif
+
Index: score-protos.h
===================================================================
--- score-protos.h (nonexistent)
+++ score-protos.h (revision 384)
@@ -0,0 +1,93 @@
+/* score-protos.h for Sunplus S+CORE processor
+ Copyright (C) 2005, 2007, 2008 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 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
+ . */
+
+#ifndef GCC_SCORE_PROTOS_H
+#define GCC_SCORE_PROTOS_H
+
+/* Machine Print. */
+enum score_mem_unit {SCORE_BYTE = 0, SCORE_HWORD = 1, SCORE_WORD = 2};
+
+#define SCORE_ALIGN_UNIT(V, UNIT) !(V & ((1 << UNIT) - 1))
+
+extern void score_prologue (void);
+extern void score_epilogue (int sibcall_p);
+extern void score_call (rtx *ops, bool sib);
+extern void score_call_value (rtx *ops, bool sib);
+extern void score_movdi (rtx *ops);
+extern void score_zero_extract_andi (rtx *ops);
+extern const char * score_linsn (rtx *ops, enum score_mem_unit unit, bool sign);
+extern const char * score_sinsn (rtx *ops, enum score_mem_unit unit);
+extern const char * score_limm (rtx *ops);
+extern const char * score_move (rtx *ops);
+extern bool score_unaligned_load (rtx* ops);
+extern bool score_unaligned_store (rtx* ops);
+extern bool score_block_move (rtx* ops);
+extern int score_address_cost (rtx addr, bool speed);
+extern rtx score_function_arg (const CUMULATIVE_ARGS *cum,
+ enum machine_mode mode,
+ tree type, int named);
+extern int score_address_p (enum machine_mode mode, rtx x, int strict);
+extern int score_reg_class (int regno);
+extern int score_register_move_cost (enum machine_mode mode, enum reg_class to,
+ enum reg_class from);
+extern int score_hard_regno_mode_ok (unsigned int, enum machine_mode);
+extern int score_const_ok_for_letter_p (HOST_WIDE_INT value, char c);
+extern int score_extra_constraint (rtx op, char c);
+extern rtx score_return_addr (int count, rtx frame);
+extern int score_regno_mode_ok_for_base_p (int regno, int strict);
+extern void score_function_arg_advance (CUMULATIVE_ARGS *cum,
+ enum machine_mode mode,
+ tree type, int named);
+extern void score_init_cumulative_args (CUMULATIVE_ARGS *cum,
+ tree fntype, rtx libname);
+extern void score_declare_object (FILE *stream, const char *name,
+ const char *directive, const char *fmt, ...);
+extern int score_output_external (FILE *file, tree decl, const char *name);
+extern void score_override_options (void);
+extern enum reg_class score_secondary_reload_class (enum reg_class rclass,
+ enum machine_mode mode,
+ rtx x);
+extern rtx score_function_value (tree valtype, tree func,
+ enum machine_mode mode);
+extern enum reg_class score_preferred_reload_class (rtx x,
+ enum reg_class rclass);
+extern HOST_WIDE_INT score_initial_elimination_offset (int from, int to);
+extern void score_print_operand (FILE *file, rtx op, int letter);
+extern void score_print_operand_address (FILE *file, rtx addr);
+extern int score_arg_partial_bytes (CUMULATIVE_ARGS *cum,
+ enum machine_mode mode,
+ tree type, bool named);
+extern int score_symbolic_constant_p (rtx x,
+ enum score_symbol_type *symbol_type);
+extern void score_movsicc (rtx *ops);
+extern const char * score_select_add_imm (rtx *ops, bool set_cc);
+extern const char * score_select (rtx *ops, const char *inst_pre, bool commu,
+ const char *letter, bool set_cc);
+extern const char * score_output_casesi (rtx *operands);
+extern const char * score_rpush (rtx *ops);
+extern const char * score_rpop (rtx *ops);
+extern bool score_rtx_costs (rtx x, int code, int outer_code, int *total, bool speed);
+
+#ifdef RTX_CODE
+extern enum machine_mode score_select_cc_mode (enum rtx_code op, rtx x, rtx y);
+#endif
+
+extern struct extern_list *extern_head;
+
+#endif /* GCC_SCORE_PROTOS_H */
score-protos.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: score7.h
===================================================================
--- score7.h (nonexistent)
+++ score7.h (revision 384)
@@ -0,0 +1,158 @@
+/* score7.h for Sunplus S+CORE processor
+ Copyright (C) 2005, 2007, 2008 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 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
+ . */
+
+#ifndef GCC_SCORE7_H
+#define GCC_SCORE7_H
+
+enum score7_address_type
+{
+ SCORE7_ADD_REG,
+ SCORE7_ADD_CONST_INT,
+ SCORE7_ADD_SYMBOLIC
+};
+
+struct score7_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 */
+};
+
+struct score7_arg_info
+{
+ unsigned int num_bytes; /* The argument's size in bytes */
+ unsigned int reg_words; /* The number of words passed in registers */
+ unsigned int reg_offset; /* The offset of the first register from */
+ /* GP_ARG_FIRST or FP_ARG_FIRST etc */
+ unsigned int stack_words; /* The number of words that must be passed */
+ /* on the stack */
+ unsigned int stack_offset; /* The offset from the start of the stack */
+ /* overflow area */
+};
+
+#ifdef RTX_CODE
+struct score7_address_info
+{
+ enum score7_address_type type;
+ rtx reg;
+ rtx offset;
+ enum rtx_code code;
+ enum score_symbol_type symbol_type;
+};
+#endif
+
+#define SCORE7_SDATA_MAX score7_sdata_max
+#define SCORE7_STACK_ALIGN(LOC) (((LOC) + 3) & ~3)
+#define SCORE7_PROLOGUE_TEMP_REGNUM (GP_REG_FIRST + 8)
+#define SCORE7_EPILOGUE_TEMP_REGNUM (GP_REG_FIRST + 8)
+#define SCORE7_DEFAULT_SDATA_MAX 8
+
+extern int score7_symbolic_constant_p (rtx x,
+ enum score_symbol_type *symbol_type);
+extern bool score7_return_in_memory (tree type,
+ tree fndecl ATTRIBUTE_UNUSED);
+extern void score7_output_mi_thunk (FILE *file,
+ tree thunk_fndecl ATTRIBUTE_UNUSED,
+ HOST_WIDE_INT delta,
+ HOST_WIDE_INT vcall_offset,
+ tree function);
+extern rtx score7_legitimize_address (rtx x);
+extern void
+score7_function_prologue (FILE *file,
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED);
+extern void
+score7_function_epilogue (FILE *file,
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED);
+extern section *score7_select_rtx_section (enum machine_mode mode, rtx x,
+ unsigned HOST_WIDE_INT align);
+extern bool score7_in_small_data_p (tree decl);
+extern void score7_asm_file_start (void);
+extern void score7_asm_file_end (void);
+extern void score7_override_options (void);
+extern int score7_reg_class (int regno);
+extern enum reg_class score7_preferred_reload_class (rtx x ATTRIBUTE_UNUSED,
+ enum reg_class rclass);
+extern enum
+reg_class score7_secondary_reload_class (enum reg_class rclass,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ rtx x);
+extern int score7_const_ok_for_letter_p (HOST_WIDE_INT value, char c);
+extern int score7_extra_constraint (rtx op, char c);
+extern int score7_hard_regno_mode_ok (unsigned int regno,
+ enum machine_mode mode);
+extern HOST_WIDE_INT
+score7_initial_elimination_offset (int from,
+ int to ATTRIBUTE_UNUSED);
+extern void score7_function_arg_advance (CUMULATIVE_ARGS *cum,
+ enum machine_mode mode,
+ tree type,
+ int named);
+extern int score7_arg_partial_bytes (CUMULATIVE_ARGS *cum,
+ enum machine_mode mode,
+ tree type,
+ bool named);
+extern rtx score7_function_arg (const CUMULATIVE_ARGS *cum,
+ enum machine_mode mode,
+ tree type,
+ int named);
+extern rtx score7_function_value (tree valtype,
+ tree func ATTRIBUTE_UNUSED,
+ enum machine_mode mode);
+extern void score7_asm_trampoline_template (FILE *);
+extern void score7_trampoline_init (rtx, tree, rtx);
+extern int score7_regno_mode_ok_for_base_p (int regno, int strict);
+extern bool score7_legitimate_address_p (enum machine_mode mode, rtx x,
+ bool strict);
+extern int score7_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+ enum reg_class from,
+ enum reg_class to);
+extern bool score7_rtx_costs (rtx x, int code, int outer_code, int *total, bool speed);
+extern int score7_address_cost (rtx addr);
+extern int score7_output_external (FILE *file ATTRIBUTE_UNUSED,
+ tree decl,
+ const char *name);
+extern rtx score7_return_addr (int count, rtx frame ATTRIBUTE_UNUSED);
+extern void score7_print_operand (FILE *file, rtx op, int c);
+extern void score7_print_operand_address (FILE *file, rtx x);
+extern enum machine_mode score7_select_cc_mode (enum rtx_code op,
+ rtx x,
+ rtx y);
+extern void score7_prologue (void);
+extern void score7_epilogue (int sibcall_p);
+extern void score7_call (rtx *ops, bool sib);
+extern void score7_call_value (rtx *ops, bool sib);
+extern void score7_movsicc (rtx *ops);
+extern void score7_movdi (rtx *ops);
+extern void score7_zero_extract_andi (rtx *ops);
+extern const char * score7_select_add_imm (rtx *ops, bool set_cc);
+extern const char * score7_select (rtx *ops, const char *inst_pre, bool commu,
+ const char *letter, bool set_cc);
+extern const char * score7_move (rtx *ops);
+extern const char * score7_limm (rtx *ops);
+extern const char *
+score7_linsn (rtx *ops, enum score_mem_unit unit, bool sign);
+extern const char *
+score7_sinsn (rtx *ops, enum score_mem_unit unit);
+#endif
score7.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: elf.h
===================================================================
--- elf.h (nonexistent)
+++ elf.h (revision 384)
@@ -0,0 +1,100 @@
+/* elf.h for Sunplus S+CORE processor
+ Copyright (C) 2005, 2007 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 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
+ . */
+
+#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
elf.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: score.c
===================================================================
--- score.c (nonexistent)
+++ score.c (revision 384)
@@ -0,0 +1,1217 @@
+/* Output routines for Sunplus S+CORE processor
+ Copyright (C) 2005, 2007, 2008, 2009 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 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
+ . */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.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 "score7.h"
+#include "score3.h"
+#include "df.h"
+
+#undef TARGET_ASM_FILE_START
+#define TARGET_ASM_FILE_START score_asm_file_start
+
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END score_asm_file_end
+
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE score_function_prologue
+
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE score_function_epilogue
+
+#undef TARGET_DEFAULT_TARGET_FLAGS
+#define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
+#undef TARGET_HANDLE_OPTION
+#define TARGET_HANDLE_OPTION score_handle_option
+
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS score_legitimize_address
+
+#undef TARGET_SCHED_ISSUE_RATE
+#define TARGET_SCHED_ISSUE_RATE score_issue_rate
+
+#undef TARGET_ASM_SELECT_RTX_SECTION
+#define TARGET_ASM_SELECT_RTX_SECTION score_select_rtx_section
+
+#undef TARGET_IN_SMALL_DATA_P
+#define TARGET_IN_SMALL_DATA_P score_in_small_data_p
+
+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
+#define TARGET_FUNCTION_OK_FOR_SIBCALL score_function_ok_for_sibcall
+
+#undef TARGET_STRICT_ARGUMENT_NAMING
+#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
+
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK score_output_mi_thunk
+
+#undef TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
+
+#undef TARGET_PROMOTE_PROTOTYPES
+#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
+
+#undef TARGET_MUST_PASS_IN_STACK
+#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
+
+#undef TARGET_ARG_PARTIAL_BYTES
+#define TARGET_ARG_PARTIAL_BYTES score_arg_partial_bytes
+
+#undef TARGET_PASS_BY_REFERENCE
+#define TARGET_PASS_BY_REFERENCE score_pass_by_reference
+
+#undef TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY score_return_in_memory
+
+#undef TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS score_rtx_costs
+
+#undef TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST score_address_cost
+
+#undef TARGET_LEGITIMATE_ADDRESS_P
+#define TARGET_LEGITIMATE_ADDRESS_P score_legitimate_address_p
+
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE score_can_eliminate
+
+#undef TARGET_ASM_TRAMPOLINE_TEMPLATE
+#define TARGET_ASM_TRAMPOLINE_TEMPLATE score_asm_trampoline_template
+#undef TARGET_TRAMPOLINE_INIT
+#define TARGET_TRAMPOLINE_INIT score_trampoline_init
+
+struct extern_list *extern_head = 0;
+
+/* default 0 = NO_REGS */
+enum reg_class score_char_to_class[256];
+
+/* Implement TARGET_RETURN_IN_MEMORY. In S+core,
+ small structures are returned in a register.
+ Objects with varying size must still be returned in memory. */
+static bool
+score_return_in_memory (tree type, tree fndecl ATTRIBUTE_UNUSED)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_return_in_memory (type, fndecl);
+ else if (TARGET_SCORE3)
+ return score3_return_in_memory (type, fndecl);
+
+ gcc_unreachable ();
+}
+
+/* Return nonzero when an argument must be passed by reference. */
+static bool
+score_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
+ enum machine_mode mode, tree type,
+ bool named ATTRIBUTE_UNUSED)
+{
+ /* If we have a variable-sized parameter, we have no choice. */
+ return targetm.calls.must_pass_in_stack (mode, type);
+}
+
+/* Implement TARGET_ASM_OUTPUT_MI_THUNK. Generate rtl rather than asm text
+ in order to avoid duplicating too much logic from elsewhere. */
+static void
+score_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
+ HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
+ tree function)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_output_mi_thunk (file, thunk_fndecl, delta,
+ vcall_offset, function);
+ else if (TARGET_SCORE3)
+ return score3_output_mi_thunk (file, thunk_fndecl, delta,
+ vcall_offset, function);
+ gcc_unreachable ();
+}
+
+/* Implement TARGET_FUNCTION_OK_FOR_SIBCALL. */
+static bool
+score_function_ok_for_sibcall (ATTRIBUTE_UNUSED tree decl,
+ ATTRIBUTE_UNUSED tree exp)
+{
+ return true;
+}
+
+/* Set up the stack and frame (if desired) for the function. */
+static void
+score_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_function_prologue (file, size);
+ else if (TARGET_SCORE3)
+ return score3_function_prologue (file, size);
+
+ gcc_unreachable ();
+}
+
+/* Do any necessary cleanup after a function to restore stack, frame,
+ and regs. */
+static void
+score_function_epilogue (FILE *file,
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_function_epilogue (file, size);
+ else if (TARGET_SCORE3)
+ return score3_function_epilogue (file, size);
+
+ gcc_unreachable ();
+}
+
+/* Implement TARGET_SCHED_ISSUE_RATE. */
+static int
+score_issue_rate (void)
+{
+ return 1;
+}
+
+/* Choose the section to use for the constant rtx expression X that has
+ mode MODE. */
+static section *
+score_select_rtx_section (enum machine_mode mode, rtx x,
+ unsigned HOST_WIDE_INT align)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_select_rtx_section (mode, x, align);
+ else if (TARGET_SCORE3)
+ return score3_select_rtx_section (mode, x, align);
+
+ gcc_unreachable ();
+}
+
+/* Implement TARGET_IN_SMALL_DATA_P. */
+static bool
+score_in_small_data_p (tree decl)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_in_small_data_p (decl);
+ else if (TARGET_SCORE3)
+ return score3_in_small_data_p (decl);
+
+ gcc_unreachable ();
+}
+
+/* Implement TARGET_ASM_FILE_START. */
+static void
+score_asm_file_start (void)
+{
+ if (TARGET_SCORE5)
+ fprintf (asm_out_file, "# Sunplus S+core5 %s rev=%s\n",
+ TARGET_LITTLE_ENDIAN ? "el" : "eb", SCORE_GCC_VERSION);
+ else if (TARGET_SCORE5U)
+ fprintf (asm_out_file, "# Sunplus S+core5u %s rev=%s\n",
+ TARGET_LITTLE_ENDIAN ? "el" : "eb", SCORE_GCC_VERSION);
+ else if (TARGET_SCORE7D)
+ fprintf (asm_out_file, "# Sunplus S+core7d %s rev=%s\n",
+ TARGET_LITTLE_ENDIAN ? "el" : "eb", SCORE_GCC_VERSION);
+ else if (TARGET_SCORE7)
+ fprintf (asm_out_file, "# Sunplus S+core7 %s rev=%s\n",
+ TARGET_LITTLE_ENDIAN ? "el" : "eb", SCORE_GCC_VERSION);
+ else if (TARGET_SCORE3D)
+ fprintf (asm_out_file, "# Sunplus S+core3d %s rev=%s\n",
+ TARGET_LITTLE_ENDIAN ? "el" : "eb", SCORE_GCC_VERSION);
+ else if (TARGET_SCORE3)
+ fprintf (asm_out_file, "# Sunplus S+core3 %s rev=%s\n",
+ TARGET_LITTLE_ENDIAN ? "el" : "eb", SCORE_GCC_VERSION);
+ else
+ fprintf (asm_out_file, "# Sunplus S+core unknown %s rev=%s\n",
+ TARGET_LITTLE_ENDIAN ? "el" : "eb", SCORE_GCC_VERSION);
+
+ default_file_start ();
+
+ if (flag_pic)
+ fprintf (asm_out_file, "\t.set pic\n");
+}
+
+/* Implement TARGET_ASM_FILE_END. When using assembler macros, emit
+ .externs for any small-data variables that turned out to be external. */
+static void
+score_asm_file_end (void)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_asm_file_end ();
+ else if (TARGET_SCORE3)
+ return score3_asm_file_end ();
+
+ gcc_unreachable ();
+}
+
+#define MASK_ALL_CPU_BITS \
+ (MASK_SCORE5 | MASK_SCORE5U | MASK_SCORE7 | MASK_SCORE7D \
+ | MASK_SCORE3 | MASK_SCORE3D)
+
+/* Implement TARGET_HANDLE_OPTION. */
+static bool
+score_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
+{
+ switch (code)
+ {
+ case OPT_mscore7d:
+ target_flags &= ~(MASK_ALL_CPU_BITS);
+ target_flags |= MASK_SCORE7 | MASK_SCORE7D;
+ return true;
+
+ case OPT_mscore3d:
+ target_flags &= ~(MASK_ALL_CPU_BITS);
+ target_flags |= MASK_SCORE3 | MASK_SCORE3D;
+ return true;
+
+ case OPT_march_:
+ if (strcmp (arg, "score5") == 0)
+ {
+ target_flags &= ~(MASK_ALL_CPU_BITS);
+ target_flags |= MASK_SCORE5;
+ return true;
+ }
+ else if (strcmp (arg, "score5u") == 0)
+ {
+ target_flags &= ~(MASK_ALL_CPU_BITS);
+ target_flags |= MASK_SCORE5U;
+ return true;
+ }
+ else if (strcmp (arg, "score7") == 0)
+ {
+ target_flags &= ~(MASK_ALL_CPU_BITS);
+ target_flags |= MASK_SCORE7;
+ return true;
+ }
+ else if (strcmp (arg, "score7d") == 0)
+ {
+ target_flags &= ~(MASK_ALL_CPU_BITS);
+ target_flags |= MASK_SCORE7 | MASK_SCORE7D;
+ return true;
+ }
+ else if (strcmp (arg, "score3") == 0)
+ {
+ target_flags &= ~(MASK_ALL_CPU_BITS);
+ target_flags |= MASK_SCORE3;
+ return true;
+ }
+ else if (strcmp (arg, "score3d") == 0)
+ {
+ target_flags &= ~(MASK_ALL_CPU_BITS);
+ target_flags |= MASK_SCORE3 | MASK_SCORE3D;
+ return true;
+ }
+ else
+ return false;
+
+ default:
+ return true;
+ }
+}
+
+/* Implement OVERRIDE_OPTIONS macro. */
+void
+score_override_options (void)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_override_options ();
+ else if (TARGET_SCORE3)
+ return score3_override_options ();
+
+ return score7_override_options ();
+}
+
+/* Implement REGNO_REG_CLASS macro. */
+int
+score_reg_class (int regno)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_reg_class (regno);
+ else if (TARGET_SCORE3)
+ return score3_reg_class (regno);
+
+ gcc_unreachable ();
+}
+
+/* Implement PREFERRED_RELOAD_CLASS macro. */
+enum reg_class
+score_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, enum reg_class rclass)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_preferred_reload_class (x, rclass);
+ else if (TARGET_SCORE3)
+ return score3_preferred_reload_class (x, rclass);
+
+ gcc_unreachable ();
+}
+
+/* Implement SECONDARY_INPUT_RELOAD_CLASS
+ and SECONDARY_OUTPUT_RELOAD_CLASS macro. */
+enum reg_class
+score_secondary_reload_class (enum reg_class rclass,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ rtx x)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_secondary_reload_class (rclass, mode, x);
+ else if (TARGET_SCORE3)
+ return score3_secondary_reload_class (rclass, mode, x);
+
+ gcc_unreachable ();
+}
+
+/* Implement CONST_OK_FOR_LETTER_P macro. */
+int
+score_const_ok_for_letter_p (HOST_WIDE_INT value, char c)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_const_ok_for_letter_p (value, c);
+ else if (TARGET_SCORE3)
+ return score3_const_ok_for_letter_p (value, c);
+
+ gcc_unreachable ();
+}
+
+/* Implement EXTRA_CONSTRAINT macro. */
+int
+score_extra_constraint (rtx op, char c)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_extra_constraint (op, c);
+ else if (TARGET_SCORE3)
+ return score3_extra_constraint (op, c);
+
+ gcc_unreachable ();
+}
+
+/* Return truth value on whether or not a given hard register
+ can support a given mode. */
+int
+score_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_hard_regno_mode_ok (regno, mode);
+ else if (TARGET_SCORE3)
+ return score3_hard_regno_mode_ok (regno, mode);
+
+ gcc_unreachable ();
+}
+
+/* We can always eliminate to the hard frame pointer. We can eliminate
+ to the stack pointer unless a frame pointer is needed. */
+
+static bool
+score_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+ return (to == HARD_FRAME_POINTER_REGNUM
+ || (to == STACK_POINTER_REGNUM && !frame_pointer_needed));
+}
+
+/* Implement INITIAL_ELIMINATION_OFFSET. FROM is either the frame
+ pointer or argument pointer. TO is either the stack pointer or
+ hard frame pointer. */
+HOST_WIDE_INT
+score_initial_elimination_offset (int from,
+ int to ATTRIBUTE_UNUSED)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_initial_elimination_offset (from, to);
+ else if (TARGET_SCORE3)
+ return score3_initial_elimination_offset (from, to);
+
+ gcc_unreachable ();
+}
+
+/* Argument support functions. */
+
+/* Initialize CUMULATIVE_ARGS for a function. */
+void
+score_init_cumulative_args (CUMULATIVE_ARGS *cum,
+ tree fntype ATTRIBUTE_UNUSED,
+ rtx libname ATTRIBUTE_UNUSED)
+{
+ memset (cum, 0, sizeof (CUMULATIVE_ARGS));
+}
+
+/* Implement FUNCTION_ARG_ADVANCE macro. */
+void
+score_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ tree type, int named)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_function_arg_advance (cum, mode, type, named);
+ else if (TARGET_SCORE3)
+ return score3_function_arg_advance (cum, mode, type, named);
+
+ gcc_unreachable ();
+}
+
+/* Implement TARGET_ARG_PARTIAL_BYTES macro. */
+int
+score_arg_partial_bytes (CUMULATIVE_ARGS *cum,
+ enum machine_mode mode, tree type, bool named)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_arg_partial_bytes (cum, mode, type, named);
+ else if (TARGET_SCORE3)
+ return score3_arg_partial_bytes (cum, mode, type, named);
+
+ gcc_unreachable ();
+}
+
+/* Implement FUNCTION_ARG macro. */
+rtx
+score_function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ tree type, int named)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_function_arg (cum, mode, type, named);
+ else if (TARGET_SCORE3)
+ return score3_function_arg (cum, mode, type, named);
+
+ gcc_unreachable ();
+}
+
+/* Implement FUNCTION_VALUE and LIBCALL_VALUE. For normal calls,
+ VALTYPE is the return type and MODE is VOIDmode. For libcalls,
+ VALTYPE is null and MODE is the mode of the return value. */
+rtx
+score_function_value (tree valtype, tree func ATTRIBUTE_UNUSED,
+ enum machine_mode mode)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_function_value (valtype, func, mode);
+ else if (TARGET_SCORE3)
+ return score3_function_value (valtype, func, mode);
+
+ gcc_unreachable ();
+}
+
+/* Implement TARGET_ASM_TRAMPOLINE_TEMPLATE. */
+static void
+score_asm_trampoline_template (FILE *f)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_asm_trampoline_template (f);
+ else if (TARGET_SCORE3)
+ return score3_asm_trampoline_template (f);
+
+ gcc_unreachable ();
+}
+
+/* Implement TARGET_TRAMPOLINE_INIT. */
+static void
+score_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
+{
+ /* ??? These two routines are identical. */
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_trampoline_init (m_tramp, fndecl, chain_value);
+ else if (TARGET_SCORE3)
+ return score3_trampoline_init (m_tramp, fndecl, chain_value);
+
+ gcc_unreachable ();
+}
+
+/* This function is used to implement REG_MODE_OK_FOR_BASE_P macro. */
+int
+score_regno_mode_ok_for_base_p (int regno, int strict)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_regno_mode_ok_for_base_p (regno, strict);
+ else if (TARGET_SCORE3)
+ return score3_regno_mode_ok_for_base_p (regno, strict);
+
+ gcc_unreachable ();
+}
+
+/* Implement TARGET_LEGITIMIZE_ADDRESS_P. */
+bool
+score_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_legitimate_address_p (mode, x, strict);
+ else if (TARGET_SCORE3)
+ return score3_legitimate_address_p (mode, x, strict);
+
+ gcc_unreachable ();
+}
+
+/* This function is used to implement LEGITIMIZE_ADDRESS. If X can
+ be legitimized in a way that the generic machinery might not expect,
+ return the new address, else return X. */
+static rtx
+score_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_legitimize_address (x);
+ else if (TARGET_SCORE3)
+ return score3_legitimize_address (x);
+
+ gcc_unreachable ();
+}
+
+/* Return a number assessing the cost of moving a register in class
+ FROM to class TO. */
+int
+score_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+ enum reg_class from, enum reg_class to)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_register_move_cost (mode, from, to);
+ else if (TARGET_SCORE3)
+ return score3_register_move_cost (mode, from, to);
+
+ gcc_unreachable ();
+}
+
+/* Implement TARGET_RTX_COSTS macro. */
+bool
+score_rtx_costs (rtx x, int code, int outer_code, int *total,
+ bool speed ATTRIBUTE_UNUSED)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_rtx_costs (x, code, outer_code, total, speed);
+ else if (TARGET_SCORE3)
+ return score3_rtx_costs (x, code, outer_code, total, speed);
+
+ gcc_unreachable ();
+}
+
+/* Implement TARGET_ADDRESS_COST macro. */
+int
+score_address_cost (rtx addr,
+ bool speed ATTRIBUTE_UNUSED)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_address_cost (addr);
+ else if (TARGET_SCORE3)
+ return score3_address_cost (addr);
+
+ gcc_unreachable ();
+}
+
+/* Implement ASM_OUTPUT_EXTERNAL macro. */
+int
+score_output_external (FILE *file ATTRIBUTE_UNUSED,
+ tree decl, const char *name)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_output_external (file, decl, name);
+ else if (TARGET_SCORE3)
+ return score3_output_external (file, decl, name);
+
+ gcc_unreachable ();
+}
+
+/* Implement RETURN_ADDR_RTX. Note, we do not support moving
+ back to a previous frame. */
+rtx
+score_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_return_addr (count, frame);
+ else if (TARGET_SCORE3)
+ return score3_return_addr (count, frame);
+
+ gcc_unreachable ();
+}
+
+/* Implement PRINT_OPERAND macro. */
+void
+score_print_operand (FILE *file, rtx op, int c)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_print_operand (file, op, c);
+ else if (TARGET_SCORE3)
+ return score3_print_operand (file, op, c);
+
+ gcc_unreachable ();
+}
+
+/* Implement PRINT_OPERAND_ADDRESS macro. */
+void
+score_print_operand_address (FILE *file, rtx x)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_print_operand_address (file, x);
+ else if (TARGET_SCORE3)
+ return score3_print_operand_address (file, x);
+
+ gcc_unreachable ();
+}
+
+/* Implement SELECT_CC_MODE macro. */
+enum machine_mode
+score_select_cc_mode (enum rtx_code op, rtx x, rtx y)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_select_cc_mode (op, x, y);
+ else if (TARGET_SCORE3)
+ return score3_select_cc_mode (op, x, y);
+
+ gcc_unreachable ();
+}
+
+/* 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
+score_symbolic_constant_p (rtx x, enum score_symbol_type *symbol_type)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_symbolic_constant_p (x, symbol_type);
+ else if (TARGET_SCORE3)
+ return score3_symbolic_constant_p (x, symbol_type);
+
+ gcc_unreachable ();
+}
+
+/* Generate the prologue instructions for entry into a S+core function. */
+void
+score_prologue (void)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_prologue ();
+ else if (TARGET_SCORE3)
+ return score3_prologue ();
+
+ gcc_unreachable ();
+}
+
+/* Generate the epilogue instructions in a S+core function. */
+void
+score_epilogue (int sibcall_p)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_epilogue (sibcall_p);
+ else if (TARGET_SCORE3)
+ return score3_epilogue (sibcall_p);
+
+ gcc_unreachable ();
+}
+
+/* Call and sibcall pattern all need call this function. */
+void
+score_call (rtx *ops, bool sib)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_call (ops, sib);
+ else if (TARGET_SCORE3)
+ return score3_call (ops, sib);
+
+ gcc_unreachable ();
+}
+
+/* Call value and sibcall value pattern all need call this function. */
+void
+score_call_value (rtx *ops, bool sib)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_call_value (ops, sib);
+ else if (TARGET_SCORE3)
+ return score3_call_value (ops, sib);
+
+ gcc_unreachable ();
+}
+
+void
+score_movsicc (rtx *ops)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_movsicc (ops);
+ else if (TARGET_SCORE3)
+ return score3_movsicc (ops);
+
+ gcc_unreachable ();
+}
+
+/* Machine Split */
+void
+score_movdi (rtx *ops)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_movdi (ops);
+ else if (TARGET_SCORE3)
+ return score3_movdi (ops);
+
+ gcc_unreachable ();
+}
+
+void
+score_zero_extract_andi (rtx *ops)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_zero_extract_andi (ops);
+ else if (TARGET_SCORE3)
+ return score3_zero_extract_andi (ops);
+
+ gcc_unreachable ();
+}
+
+/* Output asm insn for move. */
+const char *
+score_move (rtx *ops)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_move (ops);
+ else if (TARGET_SCORE3)
+ return score3_move (ops);
+
+ gcc_unreachable ();
+}
+
+/* Output asm insn for load. */
+const char *
+score_linsn (rtx *ops, enum score_mem_unit unit, bool sign)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_linsn (ops, unit, sign);
+ else if (TARGET_SCORE3)
+ return score3_linsn (ops, unit, sign);
+
+ gcc_unreachable ();
+}
+
+/* Output asm insn for store. */
+const char *
+score_sinsn (rtx *ops, enum score_mem_unit unit)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_sinsn (ops, unit);
+ else if (TARGET_SCORE3)
+ return score3_sinsn (ops, unit);
+
+ gcc_unreachable ();
+}
+
+/* Output asm insn for load immediate. */
+const char *
+score_limm (rtx *ops)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_limm (ops);
+ else if (TARGET_SCORE3)
+ return score3_limm (ops);
+
+ gcc_unreachable ();
+}
+
+
+/* Generate add insn. */
+const char *
+score_select_add_imm (rtx *ops, bool set_cc)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_select_add_imm (ops, set_cc);
+ else if (TARGET_SCORE3)
+ return score3_select_add_imm (ops, set_cc);
+
+ gcc_unreachable ();
+}
+
+/* Output arith insn. */
+const char *
+score_select (rtx *ops, const char *inst_pre,
+ bool commu, const char *letter, bool set_cc)
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ return score7_select (ops, inst_pre, commu, letter, set_cc);
+ else if (TARGET_SCORE3)
+ return score3_select (ops, inst_pre, commu, letter, set_cc);
+
+ gcc_unreachable ();
+}
+
+/* Output switch case insn, only supported in score3. */
+const char *
+score_output_casesi (rtx *operands)
+{
+ if (TARGET_SCORE3)
+ return score3_output_casesi (operands);
+
+ gcc_unreachable ();
+}
+
+/* Output rpush insn, only supported in score3. */
+const char *
+score_rpush (rtx *operands)
+{
+ if (TARGET_SCORE3)
+ return score3_rpush (operands);
+
+ gcc_unreachable ();
+}
+
+/* Output rpop insn, only supported in score3. */
+const char *
+score_rpop (rtx *operands)
+{
+ if (TARGET_SCORE3)
+ return score3_rpop (operands);
+
+ gcc_unreachable ();
+}
+
+/* Emit lcb/lce insns. */
+bool
+score_unaligned_load (rtx *ops)
+{
+ rtx dst = ops[0];
+ rtx src = ops[1];
+ rtx len = ops[2];
+ rtx off = ops[3];
+ rtx addr_reg;
+
+ if (INTVAL (len) != BITS_PER_WORD
+ || (INTVAL (off) % BITS_PER_UNIT) != 0)
+ return false;
+
+ gcc_assert (GET_MODE_SIZE (GET_MODE (dst)) == GET_MODE_SIZE (SImode));
+
+ addr_reg = copy_addr_to_reg (XEXP (src, 0));
+ emit_insn (gen_move_lcb (addr_reg, addr_reg));
+ emit_insn (gen_move_lce (addr_reg, addr_reg, dst));
+
+ return true;
+}
+
+/* Emit scb/sce insns. */
+bool
+score_unaligned_store (rtx *ops)
+{
+ rtx dst = ops[0];
+ rtx len = ops[1];
+ rtx off = ops[2];
+ rtx src = ops[3];
+ rtx addr_reg;
+
+ if (INTVAL(len) != BITS_PER_WORD
+ || (INTVAL(off) % BITS_PER_UNIT) != 0)
+ return false;
+
+ gcc_assert (GET_MODE_SIZE (GET_MODE (src)) == GET_MODE_SIZE (SImode));
+
+ addr_reg = copy_addr_to_reg (XEXP (dst, 0));
+ emit_insn (gen_move_scb (addr_reg, addr_reg, src));
+ emit_insn (gen_move_sce (addr_reg, addr_reg));
+
+ return true;
+}
+
+/* If length is short, generate move insns straight. */
+static void
+score_block_move_straight (rtx dst, rtx src, HOST_WIDE_INT length)
+{
+ HOST_WIDE_INT leftover;
+ int i, reg_count;
+ rtx *regs;
+
+ leftover = length % UNITS_PER_WORD;
+ length -= leftover;
+ reg_count = length / UNITS_PER_WORD;
+
+ regs = XALLOCAVEC (rtx, reg_count);
+ for (i = 0; i < reg_count; i++)
+ regs[i] = gen_reg_rtx (SImode);
+
+ /* Load from src to regs. */
+ if (MEM_ALIGN (src) >= BITS_PER_WORD)
+ {
+ HOST_WIDE_INT offset = 0;
+ for (i = 0; i < reg_count; offset += UNITS_PER_WORD, i++)
+ emit_move_insn (regs[i], adjust_address (src, SImode, offset));
+ }
+ else if (reg_count >= 1)
+ {
+ rtx src_reg = copy_addr_to_reg (XEXP (src, 0));
+
+ emit_insn (gen_move_lcb (src_reg, src_reg));
+ for (i = 0; i < (reg_count - 1); i++)
+ emit_insn (gen_move_lcw (src_reg, src_reg, regs[i]));
+ emit_insn (gen_move_lce (src_reg, src_reg, regs[i]));
+ }
+
+ /* Store regs to dest. */
+ if (MEM_ALIGN (dst) >= BITS_PER_WORD)
+ {
+ HOST_WIDE_INT offset = 0;
+ for (i = 0; i < reg_count; offset += UNITS_PER_WORD, i++)
+ emit_move_insn (adjust_address (dst, SImode, offset), regs[i]);
+ }
+ else if (reg_count >= 1)
+ {
+ rtx dst_reg = copy_addr_to_reg (XEXP (dst, 0));
+
+ emit_insn (gen_move_scb (dst_reg, dst_reg, regs[0]));
+ for (i = 1; i < reg_count; i++)
+ emit_insn (gen_move_scw (dst_reg, dst_reg, regs[i]));
+ emit_insn (gen_move_sce (dst_reg, dst_reg));
+ }
+
+ /* Mop up any left-over bytes. */
+ if (leftover > 0)
+ {
+ src = adjust_address (src, BLKmode, length);
+ dst = adjust_address (dst, BLKmode, length);
+ move_by_pieces (dst, src, leftover,
+ MIN (MEM_ALIGN (src), MEM_ALIGN (dst)), 0);
+ }
+}
+
+/* Generate loop head when dst or src is unaligned. */
+static void
+score_block_move_loop_head (rtx dst_reg, HOST_WIDE_INT dst_align,
+ rtx src_reg, HOST_WIDE_INT src_align,
+ HOST_WIDE_INT length)
+{
+ bool src_unaligned = (src_align < BITS_PER_WORD);
+ bool dst_unaligned = (dst_align < BITS_PER_WORD);
+
+ rtx temp = gen_reg_rtx (SImode);
+
+ gcc_assert (length == UNITS_PER_WORD);
+
+ if (src_unaligned)
+ {
+ emit_insn (gen_move_lcb (src_reg, src_reg));
+ emit_insn (gen_move_lcw (src_reg, src_reg, temp));
+ }
+ else
+ emit_insn (gen_move_lw_a (src_reg,
+ src_reg, gen_int_mode (4, SImode), temp));
+
+ if (dst_unaligned)
+ emit_insn (gen_move_scb (dst_reg, dst_reg, temp));
+ else
+ emit_insn (gen_move_sw_a (dst_reg,
+ dst_reg, gen_int_mode (4, SImode), temp));
+}
+
+/* Generate loop body, copy length bytes per iteration. */
+static void
+score_block_move_loop_body (rtx dst_reg, HOST_WIDE_INT dst_align,
+ rtx src_reg, HOST_WIDE_INT src_align,
+ HOST_WIDE_INT length)
+{
+ int reg_count = length / UNITS_PER_WORD;
+ rtx *regs = XALLOCAVEC (rtx, reg_count);
+ int i;
+ bool src_unaligned = (src_align < BITS_PER_WORD);
+ bool dst_unaligned = (dst_align < BITS_PER_WORD);
+
+ for (i = 0; i < reg_count; i++)
+ regs[i] = gen_reg_rtx (SImode);
+
+ if (src_unaligned)
+ {
+ for (i = 0; i < reg_count; i++)
+ emit_insn (gen_move_lcw (src_reg, src_reg, regs[i]));
+ }
+ else
+ {
+ for (i = 0; i < reg_count; i++)
+ emit_insn (gen_move_lw_a (src_reg,
+ src_reg, gen_int_mode (4, SImode), regs[i]));
+ }
+
+ if (dst_unaligned)
+ {
+ for (i = 0; i < reg_count; i++)
+ emit_insn (gen_move_scw (dst_reg, dst_reg, regs[i]));
+ }
+ else
+ {
+ for (i = 0; i < reg_count; i++)
+ emit_insn (gen_move_sw_a (dst_reg,
+ dst_reg, gen_int_mode (4, SImode), regs[i]));
+ }
+}
+
+/* Generate loop foot, copy the leftover bytes. */
+static void
+score_block_move_loop_foot (rtx dst_reg, HOST_WIDE_INT dst_align,
+ rtx src_reg, HOST_WIDE_INT src_align,
+ HOST_WIDE_INT length)
+{
+ bool src_unaligned = (src_align < BITS_PER_WORD);
+ bool dst_unaligned = (dst_align < BITS_PER_WORD);
+
+ HOST_WIDE_INT leftover;
+
+ leftover = length % UNITS_PER_WORD;
+ length -= leftover;
+
+ if (length > 0)
+ score_block_move_loop_body (dst_reg, dst_align,
+ src_reg, src_align, length);
+
+ if (dst_unaligned)
+ emit_insn (gen_move_sce (dst_reg, dst_reg));
+
+ if (leftover > 0)
+ {
+ HOST_WIDE_INT src_adj = src_unaligned ? -4 : 0;
+ HOST_WIDE_INT dst_adj = dst_unaligned ? -4 : 0;
+ rtx temp;
+
+ gcc_assert (leftover < UNITS_PER_WORD);
+
+ if (leftover >= UNITS_PER_WORD / 2
+ && src_align >= BITS_PER_WORD / 2
+ && dst_align >= BITS_PER_WORD / 2)
+ {
+ temp = gen_reg_rtx (HImode);
+ emit_insn (gen_move_lhu_b (src_reg, src_reg,
+ gen_int_mode (src_adj, SImode), temp));
+ emit_insn (gen_move_sh_b (dst_reg, dst_reg,
+ gen_int_mode (dst_adj, SImode), temp));
+ leftover -= UNITS_PER_WORD / 2;
+ src_adj = UNITS_PER_WORD / 2;
+ dst_adj = UNITS_PER_WORD / 2;
+ }
+
+ while (leftover > 0)
+ {
+ temp = gen_reg_rtx (QImode);
+ emit_insn (gen_move_lbu_b (src_reg, src_reg,
+ gen_int_mode (src_adj, SImode), temp));
+ emit_insn (gen_move_sb_b (dst_reg, dst_reg,
+ gen_int_mode (dst_adj, SImode), temp));
+ leftover--;
+ src_adj = 1;
+ dst_adj = 1;
+ }
+ }
+}
+
+#define MIN_MOVE_REGS 3
+#define MIN_MOVE_BYTES (MIN_MOVE_REGS * UNITS_PER_WORD)
+#define MAX_MOVE_REGS 4
+#define MAX_MOVE_BYTES (MAX_MOVE_REGS * UNITS_PER_WORD)
+
+/* The length is large, generate a loop if necessary.
+ The loop is consisted by loop head/body/foot. */
+static void
+score_block_move_loop (rtx dst, rtx src, HOST_WIDE_INT length)
+{
+ HOST_WIDE_INT src_align = MEM_ALIGN (src);
+ HOST_WIDE_INT dst_align = MEM_ALIGN (dst);
+ HOST_WIDE_INT loop_mov_bytes;
+ HOST_WIDE_INT iteration = 0;
+ HOST_WIDE_INT head_length = 0, leftover;
+ rtx label, src_reg, dst_reg, final_dst, test;
+
+ bool gen_loop_head = (src_align < BITS_PER_WORD
+ || dst_align < BITS_PER_WORD);
+
+ if (gen_loop_head)
+ head_length += UNITS_PER_WORD;
+
+ for (loop_mov_bytes = MAX_MOVE_BYTES;
+ loop_mov_bytes >= MIN_MOVE_BYTES;
+ loop_mov_bytes -= UNITS_PER_WORD)
+ {
+ iteration = (length - head_length) / loop_mov_bytes;
+ if (iteration > 1)
+ break;
+ }
+ if (iteration <= 1)
+ {
+ score_block_move_straight (dst, src, length);
+ return;
+ }
+
+ leftover = (length - head_length) % loop_mov_bytes;
+ length -= leftover;
+
+ src_reg = copy_addr_to_reg (XEXP (src, 0));
+ dst_reg = copy_addr_to_reg (XEXP (dst, 0));
+ final_dst = expand_simple_binop (Pmode, PLUS, dst_reg, GEN_INT (length),
+ 0, 0, OPTAB_WIDEN);
+
+ if (gen_loop_head)
+ score_block_move_loop_head (dst_reg, dst_align,
+ src_reg, src_align, head_length);
+
+ label = gen_label_rtx ();
+ emit_label (label);
+
+ score_block_move_loop_body (dst_reg, dst_align,
+ src_reg, src_align, loop_mov_bytes);
+
+ test = gen_rtx_NE (VOIDmode, dst_reg, final_dst);
+ emit_jump_insn (gen_cbranchsi4 (test, dst_reg, final_dst, label));
+
+ score_block_move_loop_foot (dst_reg, dst_align,
+ src_reg, src_align, leftover);
+}
+
+/* Generate block move, for misc.md: "movmemsi". */
+bool
+score_block_move (rtx *ops)
+{
+ rtx dst = ops[0];
+ rtx src = ops[1];
+ rtx length = ops[2];
+
+ if (TARGET_LITTLE_ENDIAN
+ && (MEM_ALIGN (src) < BITS_PER_WORD || MEM_ALIGN (dst) < BITS_PER_WORD)
+ && INTVAL (length) >= UNITS_PER_WORD)
+ return false;
+
+ if (GET_CODE (length) == CONST_INT)
+ {
+ if (INTVAL (length) <= 2 * MAX_MOVE_BYTES)
+ {
+ score_block_move_straight (dst, src, INTVAL (length));
+ return true;
+ }
+ else if (optimize &&
+ !(flag_unroll_loops || flag_unroll_all_loops))
+ {
+ score_block_move_loop (dst, src, INTVAL (length));
+ return true;
+ }
+ }
+ return false;
+}
+
+struct gcc_target targetm = TARGET_INITIALIZER;
score.c
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: score.h
===================================================================
--- score.h (nonexistent)
+++ score.h (revision 384)
@@ -0,0 +1,1032 @@
+/* score.h for Sunplus S+CORE processor
+ Copyright (C) 2005, 2007, 2008, 2009 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 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
+ . */
+
+#include "score-conv.h"
+
+/* Controlling the Compilation Driver. */
+#undef SWITCH_TAKES_ARG
+#define SWITCH_TAKES_ARG(CHAR) \
+ (DEFAULT_SWITCH_TAKES_ARG (CHAR) || (CHAR) == 'G')
+
+#undef CPP_SPEC
+#define CPP_SPEC "%{mscore3:-D__score3__} %{G*}"
+
+#undef CC1_SPEC
+#define CC1_SPEC "%{!mel:-meb} %{mel:-mel } \
+%{!mscore*:-mscore7} \
+%{mscore3:-mscore3} \
+%{mscore3d:-mscore3d} \
+%{mscore7:-mscore7} \
+%{mscore7d:-mscore7d} \
+%{G*}"
+
+#undef ASM_SPEC
+#define ASM_SPEC "%{!mel:-EB} %{mel:-EL} \
+%{!mscore*:-march=score7} \
+%{mscore7:-march=score7} \
+%{mscore7d:-march=score7} \
+%{mscore3:-march=score3} \
+%{mscore3d:-march=score3} \
+%{march=score5:-march=score7} \
+%{march=score5u:-march=score7} \
+%{march=score7:-march=score7} \
+%{march=score7d:-march=score7} \
+%{march=score3:-march=score3} \
+%{march=score3d:-march=score3} \
+%{G*}"
+
+#undef LINK_SPEC
+#define LINK_SPEC "%{!mel:-EB} %{mel:-EL} \
+%{!mscore*:-mscore7_elf} \
+%{mscore7:-mscore7_elf} \
+%{mscore7d:-mscore7_elf} \
+%{mscore3:-mscore3_elf} \
+%{mscore3d:-mscore3_elf} \
+%{march=score5:-mscore7_elf} \
+%{march=score5u:-mscore7_elf} \
+%{march=score7:-mscore7_elf} \
+%{march=score7d:-mscore7_elf} \
+%{march=score3:-mscore3_elf} \
+%{march=score3d:-mscore3_elf} \
+%{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_SCORE5) \
+ builtin_define ("__score5__"); \
+ if (TARGET_SCORE5U) \
+ builtin_define ("__score5u__"); \
+ if (TARGET_SCORE7) \
+ builtin_define ("__score7__"); \
+ if (TARGET_SCORE7D) \
+ builtin_define ("__score7d__"); \
+ if (TARGET_SCORE3) \
+ builtin_define ("__score3__"); \
+ if (TARGET_SCORE3D) \
+ builtin_define ("__score3d__"); \
+ } while (0)
+
+#define TARGET_DEFAULT 0
+
+#define SCORE_GCC_VERSION "1.6"
+
+#define TARGET_VERSION \
+ fprintf (stderr, "Sunplus S+core rev=%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 BITS_PER_WORD
+
+/* 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))
+
+/* If defined, a C expression to compute the alignment given to a
+ constant that is being placed in memory. EXP is the constant
+ 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.
+
+ The typical use of this macro is to increase alignment for string
+ constants to be word aligned so that `strcpy' calls that copy
+ constants can be done inline. */
+#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
+ ((TREE_CODE (EXP) == STRING_CST || TREE_CODE (EXP) == CONSTRUCTOR) \
+ && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
+
+/* If defined, a C expression to compute the alignment for a local
+ 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. */
+#define LOCAL_ALIGNMENT(TYPE, ALIGN) \
+ ((TREE_CODE (TYPE) == ARRAY_TYPE \
+ && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \
+ && (ALIGN) < BITS_PER_WORD) ? 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
+
+/* 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"
+
+#define UINTPTR_TYPE "long 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, 1, 1, 1, \
+ /* Control Registers */ \
+ 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 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 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, 6, 7, 8, 9, 10, 11, 4, 5, 22, 23, 24, 25, 26, 27, \
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 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 }
+
+/* Macro to conditionally modify fixed_regs/call_used_regs. */
+#define PIC_OFFSET_TABLE_REGNUM 29
+
+#define CONDITIONAL_REGISTER_USAGE \
+{ \
+ if (!flag_pic) \
+ fixed_regs[PIC_OFFSET_TABLE_REGNUM] = \
+ call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 0; \
+}
+
+#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)
+
+/* The following macro defines cover classes for Integrated Register
+ Allocator. Cover classes is a set of non-intersected register
+ classes covering all hard registers used for register allocation
+ purpose. Any move between two registers of a cover class should be
+ cheaper than load or store of the registers. The macro value is
+ array of register classes with LIM_REG_CLASSES used as the end
+ marker. */
+#define IRA_COVER_CLASSES \
+{ \
+ G32_REGS, CE_REGS, SP_REGS, LIM_REG_CLASSES \
+}
+
+/* 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
+
+extern enum reg_class score_char_to_class[256];
+#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 crtl->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 */
+
+#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}}
+
+#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
+ `crtl->outgoing_args_size'. */
+#define OUTGOING_REG_PARM_STACK_SPACE(FNTYPE) 1
+
+#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) \
+ do { \
+ if (TARGET_SCORE7) \
+ { \
+ 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"); \
+ } \
+ else if (TARGET_SCORE3) \
+ { \
+ fprintf (FILE, " .set r1 \n"); \
+ fprintf (FILE, " mv! r%d,r%d \n", AT_REGNUM, RA_REGNUM); \
+ fprintf (FILE, " addi! r%d, %d \n", STACK_POINTER_REGNUM, -8);\
+ fprintf (FILE, " jl _mcount \n"); \
+ fprintf (FILE, " .set nor1 \n"); \
+ } \
+ } while (0)
+
+/* Trampolines for Nested Functions. */
+#define TRAMPOLINE_INSNS 6
+
+/* A C expression for the size in bytes of the trampoline, as an integer. */
+#define TRAMPOLINE_SIZE (24 + GET_MODE_SIZE (ptr_mode) * 2)
+
+#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 1
+#define HAVE_POST_MODIFY_DISP 1
+#define HAVE_PRE_MODIFY_REG 0
+#define HAVE_POST_MODIFY_REG 0
+
+/* Maximum number of registers that can appear in a valid memory address. */
+#define MAX_REGS_PER_ADDRESS 1
+
+/* 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 LEGITIMATE_CONSTANT_P(X) 1
+
+/* Condition Code Status. */
+#define SELECT_CC_MODE(OP, X, Y) score_select_cc_mode (OP, X, Y)
+
+/* Return nonzero if SELECT_CC_MODE will never return MODE for a
+ floating point inequality comparison. */
+#define REVERSIBLE_CC_MODE(MODE) 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(speed_p, predictable_p) 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) \
+ do { \
+ fputs ("\n\t.comm\t", STREAM); \
+ assemble_name (STREAM, NAME); \
+ fprintf (STREAM, " , " HOST_WIDE_INT_PRINT_UNSIGNED ", %u\n", \
+ SIZE, ALIGN / BITS_PER_UNIT); \
+ } while (0)
+
+/* 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) \
+ do { \
+ fputs ("\n\t.lcomm\t", STREAM); \
+ assemble_name (STREAM, NAME); \
+ fprintf (STREAM, " , " HOST_WIDE_INT_PRINT_UNSIGNED ", %u\n", \
+ SIZE, ALIGN / BITS_PER_UNIT); \
+ } while (0)
+
+/* 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) \
+ do { \
+ assemble_name (STREAM, NAME); \
+ fprintf (STREAM, ":\n"); \
+ } while (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. */
+#undef ASM_OUTPUT_EXTERNAL
+#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 (TARGET_SCORE7 ? "." : "$")
+
+#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 { \
+ if (TARGET_SCORE7) \
+ fprintf (STREAM, "\tpush! %s,[%s]\n", \
+ reg_names[REGNO], \
+ reg_names[STACK_POINTER_REGNUM]); \
+ else if (TARGET_SCORE3) \
+ fprintf (STREAM, "\tpush!\t%s\n", \
+ reg_names[REGNO]); \
+ } while (0)
+
+/* This is how to output an insn to pop a register from the stack. */
+#define ASM_OUTPUT_REG_POP(STREAM, REGNO) \
+ do { \
+ if (TARGET_SCORE7) \
+ fprintf (STREAM, "\tpop! %s,[%s]\n", \
+ reg_names[REGNO], \
+ reg_names[STACK_POINTER_REGNUM]); \
+ else if (TARGET_SCORE3) \
+ fprintf (STREAM, "\tpop!\t%s\n", \
+ reg_names[REGNO]); \
+ } 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 (TARGET_SCORE7) \
+ 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); \
+ else if (TARGET_SCORE3) \
+ { \
+ switch (GET_MODE(BODY)) \
+ { \
+ case QImode: /* TBB */ \
+ asm_fprintf (STREAM, "\t.byte\t(%LL%d-%LL%d_tbb)/2\n", \
+ VALUE, REL); \
+ break; \
+ case HImode: /* TBH */ \
+ asm_fprintf (STREAM, "\t.2byte\t(%LL%d-%LL%d_tbb)/2\n", \
+ VALUE, REL); \
+ break; \
+ case SImode: \
+ 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); \
+ break; \
+ default: \
+ gcc_unreachable(); \
+ } \
+ } \
+ } while (0)
+
+/* Jump table alignment is explicit in ASM_OUTPUT_CASE_LABEL. */
+#define ADDR_VEC_ALIGN(JUMPTABLE) (GET_MODE (PATTERN (JUMPTABLE)) == SImode ? 2 \
+ : GET_MODE (PATTERN (JUMPTABLE)) == HImode ? 1 : 0)
+
+/* This is how to output a label which precedes a jumptable. Since
+ Score3 instructions are 2 bytes, we may need explicit alignment here. */
+#undef ASM_OUTPUT_CASE_LABEL
+#define ASM_OUTPUT_CASE_LABEL(FILE, PREFIX, NUM, JUMPTABLE) \
+ do { \
+ if ((TARGET_SCORE7) && GET_MODE (PATTERN (JUMPTABLE)) == SImode) \
+ ASM_OUTPUT_ALIGN (FILE, 2); \
+ (*targetm.asm_out.internal_label) (FILE, PREFIX, NUM); \
+ } while (0)
+
+/* Specify the machine mode that this machine uses
+ for the index in the tablejump instruction. */
+#define CASE_VECTOR_MODE SImode
+
+#define CASE_VECTOR_PC_RELATIVE (TARGET_SCORE3)
+
+#define CASE_VECTOR_SHORTEN_MODE(min, max, body) \
+ ((min < 0 || max >= 0x2000 || TARGET_SCORE7) ? SImode \
+ : (max >= 0x200) ? HImode \
+ : QImode)
+
+/* 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
+
+/* 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 GTY ((chain_next ("%h.next"))) extern_list
+{
+ 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;
score.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: score-conv.h
===================================================================
--- score-conv.h (nonexistent)
+++ score-conv.h (revision 384)
@@ -0,0 +1,77 @@
+/* score-conv.h for Sunplus S+CORE processor
+ Copyright (C) 2005, 2007 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 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
+ . */
+
+#ifndef GCC_SCORE_CONV_H
+#define GCC_SCORE_CONV_H
+
+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 G8_REG_P(REGNO) REG_CONTAIN (REGNO, GP_REG_FIRST, 8)
+
+#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 GR_REG_CLASS_P(C) ((C) == G16_REGS || (C) == G32_REGS)
+#define SP_REG_CLASS_P(C) \
+ ((C) == CN_REG || (C) == LC_REG || (C) == SC_REG || (C) == SP_REGS)
+#define CP_REG_CLASS_P(C) \
+ ((C) == CP1_REGS || (C) == CP2_REGS || (C) == CP3_REGS || (C) == CPA_REGS)
+#define CE_REG_CLASS_P(C) \
+ ((C) == HI_REG || (C) == LO_REG || (C) == CE_REGS)
+
+#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 IMM_IS_POW_OF_2(V, E1, E2) \
+ ((V) >= ((unsigned HOST_WIDE_INT) 1 << (E1)) \
+ && (V) <= ((unsigned HOST_WIDE_INT) 1 << (E2)) \
+ && ((V) & ((V) - 1)) == 0)
+
+enum score_symbol_type
+{
+ SYMBOL_GENERAL,
+ SYMBOL_SMALL_DATA /* The symbol refers to something in a small data section */
+};
+
+#endif
score-conv.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: score.md
===================================================================
--- score.md (nonexistent)
+++ score.md (revision 384)
@@ -0,0 +1,3614 @@
+;; Machine description for Sunplus S+CORE
+;; Copyright (C) 2005, 2007
+;; 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 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
+;; .
+
+;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
+
+; branch conditional branch
+; jump unconditional jump
+; call unconditional call
+; load load instruction(s)
+; store store instruction(s)
+; cmp integer compare
+; arith integer arithmetic instruction
+; move data movement within same register set
+; const load constant
+; nop no operation
+; mul integer multiply
+; div integer divide
+; cndmv conditional moves
+; fce transfer from hi/lo registers
+; tce transfer to hi/lo registers
+; fsr transfer from special registers
+; tsr transfer to special registers
+
+(define_constants
+ [(CC_REGNUM 33)
+ (T_REGNUM 34)
+ (RA_REGNUM 3)
+ (SP_REGNUM 0)
+ (AT_REGNUM 1)
+ (FP_REGNUM 2)
+ (RT_REGNUM 4)
+ (GP_REGNUM 28)
+ (EH_REGNUM 29)
+ (HI_REGNUM 48)
+ (LO_REGNUM 49)
+ (CN_REGNUM 50)
+ (LC_REGNUM 51)
+ (SC_REGNUM 52)])
+
+(define_constants
+ [(BITTST 0)
+ (CPLOAD 1)
+ (CPRESTORE 2)
+
+ (SCB 3)
+ (SCW 4)
+ (SCE 5)
+ (SCLC 6)
+
+ (LCB 7)
+ (LCW 8)
+ (LCE 9)
+
+ (SFFS 10)])
+
+(define_attr "type"
+ "unknown,branch,jump,call,load,store,cmp,arith,move,const,nop,mul,div,cndmv,fce,tce,fsr,tsr,fcr,tcr"
+ (const_string "unknown"))
+
+(define_attr "mode" "unknown,QI,HI,SI,DI"
+ (const_string "unknown"))
+
+(define_attr "length" "" (const_int 4))
+
+(define_attr "up_c" "yes,no"
+ (const_string "no"))
+
+(include "score-generic.md")
+(include "predicates.md")
+
+(define_expand "movqi"
+ [(set (match_operand:QI 0 "nonimmediate_operand")
+ (match_operand:QI 1 "general_operand"))]
+ ""
+{
+ if (MEM_P (operands[0])
+ && !register_operand (operands[1], QImode))
+ {
+ operands[1] = force_reg (QImode, operands[1]);
+ }
+})
+
+(define_insn "*movqi_insns_score7"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,d,*x,d,*a")
+ (match_operand:QI 1 "general_operand" "i,d,m,d,*x,d,*a,d"))]
+ "(!MEM_P (operands[0]) || register_operand (operands[1], QImode))
+ && (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ switch (which_alternative)
+ {
+ case 0: return score_limm (operands);
+ case 1: return score_move (operands);
+ case 2: return score_linsn (operands, SCORE_BYTE, false);
+ case 3: return score_sinsn (operands, SCORE_BYTE);
+ case 4: return TARGET_SCORE7D ? \"mf%1%S0 %0\" : \"mf%1 %0\";
+ case 5: return TARGET_SCORE7D ? \"mt%0%S1 %1\" : \"mt%0 %1\";
+ case 6: return \"mfsr\t%0, %1\";
+ case 7: return \"mtsr\t%1, %0\";
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith,move,load,store,fce,tce,fsr,tsr")
+ (set_attr "mode" "QI")])
+
+(define_insn "*movqi_insns_score3"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,d,*x,d,*a")
+ (match_operand:QI 1 "general_operand" "i,d,m,d,*x,d,*a,d"))]
+ "(!MEM_P (operands[0]) || register_operand (operands[1], QImode))
+ && (TARGET_SCORE3)"
+{
+ switch (which_alternative)
+ {
+ case 0: return score_limm (operands);
+ case 1: return \"mv!\t%0, %1\";
+ case 2: return score_linsn (operands, SCORE_BYTE, false);
+ case 3: return score_sinsn (operands, SCORE_BYTE);
+ case 4: return TARGET_SCORE3D ? \"mf%1%S0\t%0\" : \"mf%1\t%0\";
+ case 5: return TARGET_SCORE3D ? \"mt%0%S1\t%1\" : \"mt%0\t%1\";
+ case 6: return \"mfsr\t%0, %1\";
+ case 7: return \"mtsr\t%1, %0\";
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith,move,load,store,fce,tce,fsr,tsr")
+ (set_attr "length" "6,2,6,6,4,4,4,4")
+ (set_attr "mode" "QI")])
+
+(define_expand "movhi"
+ [(set (match_operand:HI 0 "nonimmediate_operand")
+ (match_operand:HI 1 "general_operand"))]
+ ""
+{
+ if (MEM_P (operands[0])
+ && !register_operand (operands[1], HImode))
+ {
+ operands[1] = force_reg (HImode, operands[1]);
+ }
+})
+
+(define_insn "*movhi_insns_score7"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,m,d,*x,d,*a")
+ (match_operand:HI 1 "general_operand" "i,d,m,d,*x,d,*a,d"))]
+ "(!MEM_P (operands[0]) || register_operand (operands[1], HImode))
+ && (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ switch (which_alternative)
+ {
+ case 0: return score_limm (operands);
+ case 1: return score_move (operands);
+ case 2: return score_linsn (operands, SCORE_HWORD, false);
+ case 3: return score_sinsn (operands, SCORE_HWORD);
+ case 4: return TARGET_SCORE7D ? \"mf%1%S0 %0\" : \"mf%1 %0\";
+ case 5: return TARGET_SCORE7D ? \"mt%0%S1 %1\" : \"mt%0 %1\";
+ case 6: return \"mfsr\t%0, %1\";
+ case 7: return \"mtsr\t%1, %0\";
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith,move,load,store,fce,tce,fsr,tsr")
+ (set_attr "mode" "HI")])
+
+(define_insn "*movhi_insns_score3"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,m,d,*x,d,*a")
+ (match_operand:HI 1 "general_operand" "i,d,m,d,*x,d,*a,d"))]
+ "(!MEM_P (operands[0]) || register_operand (operands[1], HImode))
+ && (TARGET_SCORE3)"
+{
+ switch (which_alternative)
+ {
+ case 0: return score_limm (operands);
+ case 1: return \"mv!\t%0, %1\";
+ case 2: return score_linsn (operands, SCORE_HWORD, false);
+ case 3: return score_sinsn (operands, SCORE_HWORD);
+ case 4: return TARGET_SCORE3D ? \"mf%1%S0\t%0\" : \"mf%1\t%0\";
+ case 5: return TARGET_SCORE3D ? \"mt%0%S1\t%1\" : \"mt%0\t%1\";
+ case 6: return \"mfsr\t%0, %1\";
+ case 7: return \"mtsr\t%1, %0\";
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith,move,load,store,fce,tce,fsr,tsr")
+ (set_attr "length" "6,2,6,6,4,4,4,4")
+ (set_attr "mode" "HI")])
+
+(define_expand "movsi"
+ [(set (match_operand:SI 0 "nonimmediate_operand")
+ (match_operand:SI 1 "general_operand"))]
+ ""
+{
+ if (MEM_P (operands[0])
+ && !register_operand (operands[1], SImode))
+ {
+ operands[1] = force_reg (SImode, operands[1]);
+ }
+})
+
+(define_insn "*movsi_insns_score7"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,m,d,*x,d,*a,d,*c")
+ (match_operand:SI 1 "general_operand" "i,d,m,d,*x,d,*a,d,*c,d"))]
+ "(!MEM_P (operands[0]) || register_operand (operands[1], SImode))
+ && (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ switch (which_alternative)
+ {
+ case 0:
+ if (GET_CODE (operands[1]) != CONST_INT)
+ return \"la\t%0, %1\";
+ else
+ return score_limm (operands);
+ case 1: return score_move (operands);
+ case 2: return score_linsn (operands, SCORE_WORD, false);
+ case 3: return score_sinsn (operands, SCORE_WORD);
+ case 4: return TARGET_SCORE7D ? \"mf%1%S0 %0\" : \"mf%1 %0\";
+ case 5: return TARGET_SCORE7D ? \"mt%0%S1 %1\" : \"mt%0 %1\";
+ case 6: return \"mfsr\t%0, %1\";
+ case 7: return \"mtsr\t%1, %0\";
+ case 8: return \"mfcr\t%0, %1\";
+ case 9: return \"mtcr\t%1, %0\";
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith,move,load,store,fce,tce,fsr,tsr,fcr,tcr")
+ (set_attr "mode" "SI")])
+
+(define_insn "*movsi_insns_score3"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=ed,e,d,d,m,d,*x,d,*a")
+ (match_operand:SI 1 "general_operand" "i,e,d,m,d,*x,d,*a,d"))]
+ "(!MEM_P (operands[0]) || register_operand (operands[1], SImode))
+ && (TARGET_SCORE3)"
+{
+ switch (which_alternative)
+ {
+ case 0:
+ if (GET_CODE (operands[1]) != CONST_INT)
+ return \"ldi48\t%0, %1\";
+ else
+ return score_limm (operands);
+ case 1: return \"mv!\t%0, %1\";
+ case 2: return \"mv!\t%0, %1\";
+ case 3: return score_linsn (operands, SCORE_WORD, false);
+ case 4: return score_sinsn (operands, SCORE_WORD);
+ case 5: return TARGET_SCORE3D ? \"mf%1%S0\t%0\" : \"mf%1\t%0\";
+ case 6: return TARGET_SCORE3D ? \"mt%0%S1\t%1\" : \"mt%0\t%1\";
+ case 7: return \"mfsr\t%0, %1\";
+ case 8: return \"mtsr\t%1, %0\";
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith,move,move,load,store,fce,tce,fsr,tsr")
+ (set_attr "length" "6,2,2,6,6,4,4,4,4")
+ (set_attr "mode" "SI")])
+
+(define_insn_and_split "movdi"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,m,d,*x")
+ (match_operand:DI 1 "general_operand" "i,d,m,d,*x,d"))]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ score_movdi (operands);
+ DONE;
+})
+
+(define_expand "movsf"
+ [(set (match_operand:SF 0 "nonimmediate_operand")
+ (match_operand:SF 1 "general_operand"))]
+ ""
+{
+ if (MEM_P (operands[0])
+ && !register_operand (operands[1], SFmode))
+ {
+ operands[1] = force_reg (SFmode, operands[1]);
+ }
+})
+
+(define_insn "*movsf_insns_score7"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,d,m")
+ (match_operand:SF 1 "general_operand" "i,d,m,d"))]
+ "(!MEM_P (operands[0]) || register_operand (operands[1], SFmode))
+ && (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"li\t%0, %D1\";;
+ case 1: return score_move (operands);
+ case 2: return score_linsn (operands, SCORE_WORD, false);
+ case 3: return score_sinsn (operands, SCORE_WORD);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith,move,load,store")
+ (set_attr "mode" "SI")])
+
+(define_insn "*movsf_insns_score3"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,d,m")
+ (match_operand:SF 1 "general_operand" "i,d,m,d"))]
+ "(!MEM_P (operands[0]) || register_operand (operands[1], SFmode))
+ && (TARGET_SCORE3)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"li\t%0, %D1\";
+ case 1: return \"mv!\t%0, %1\";
+ case 2: return score_linsn (operands, SCORE_WORD, false);
+ case 3: return score_sinsn (operands, SCORE_WORD);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith,move,load,store")
+ (set_attr "length" "4,2,6,6")
+ (set_attr "mode" "SI")])
+
+(define_insn_and_split "movdf"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,d,m")
+ (match_operand:DF 1 "general_operand" "i,d,m,d"))]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ score_movdi (operands);
+ DONE;
+})
+
+(define_expand "addsi3"
+ [(set (match_operand:SI 0 "score_register_operand" )
+ (plus:SI (match_operand:SI 1 "score_register_operand")
+ (match_operand:SI 2 "arith_operand")))]
+ ""
+ ""
+)
+
+(define_insn "*addsi3_score7"
+ [(set (match_operand:SI 0 "register_operand" "=d,d,d,d")
+ (plus:SI (match_operand:SI 1 "register_operand" "0,0,d,d")
+ (match_operand:SI 2 "arith_operand" "I,L,N,d")))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"addis\t%0, %U2\";
+ case 1: return score_select_add_imm (operands, false);
+ case 2: return \"addri\t%0, %1, %c2\";
+ case 3: return score_select (operands, "add", true, "", false);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "*addsi3_score3"
+ [(set (match_operand:SI 0 "score_register_operand" "=d,d,d,d")
+ (plus:SI (match_operand:SI 1 "score_register_operand" "%0,0,d,d")
+ (match_operand:SI 2 "arith_operand" "I,L,N,d")))]
+ "(TARGET_SCORE3)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"addis\t%0, %U2\";
+ case 1: return score_select_add_imm (operands, false);
+ case 2: return \"addri\t%0, %1, %c2\";
+ case 3: return score_select (operands, "add", true, "", false);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "length" "4,4,4,4")
+ (set_attr "mode" "SI")])
+
+(define_insn "*addsi3_cmp_score7"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (plus:SI
+ (match_operand:SI 1 "register_operand" "0,0,d,d")
+ (match_operand:SI 2 "arith_operand" "I,L,N,d"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d,d,d,d"))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"addis.c\t%0, %U2\";
+ case 1: return score_select_add_imm (operands, true);
+ case 2: return \"addri.c\t%0, %1, %c2\";
+ case 3: return score_select (operands, "add", true, "", true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*addsi3_cmp_score3"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (plus:SI
+ (match_operand:SI 1 "score_register_operand" "0,0,d,d")
+ (match_operand:SI 2 "arith_operand" "I,L,N,d"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d,d,d,d"))]
+ "(TARGET_SCORE3)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"addis.c\t%0, %U2\";
+ case 1: return score_select_add_imm (operands, true);
+ case 2: return \"addri.c\t%0, %1, %c2\";
+ case 3: return score_select (operands, "add", true, "", true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "length" "4,4,4,4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*addsi3_ucc_score7"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (plus:SI
+ (match_operand:SI 1 "register_operand" "0,0,d,d")
+ (match_operand:SI 2 "arith_operand" "I,L,N,d"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=d,d,d,d")
+ (plus:SI (match_dup 1) (match_dup 2)))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"addis.c\t%0, %U2\";
+ case 1: return score_select_add_imm (operands, true);
+ case 2: return \"addri.c\t%0, %1, %c2\";
+ case 3: return score_select (operands, "add", true, "", true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*addsi3_ucc_score3"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (plus:SI
+ (match_operand:SI 1 "score_register_operand" "0,0,d,d")
+ (match_operand:SI 2 "arith_operand" "I,L,N,d"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "score_register_operand" "=d,d,d,d")
+ (plus:SI (match_dup 1) (match_dup 2)))]
+ "(TARGET_SCORE3)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"addis.c\t%0, %U2\";
+ case 1: return score_select_add_imm (operands, true);
+ case 2: return \"addri.c\t%0, %1, %c2\";
+ case 3: return score_select (operands, "add", true, "", true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "length" "4,4,4,4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_expand "adddi3"
+ [(parallel
+ [(set (match_operand:DI 0 "score_register_operand")
+ (plus:DI (match_operand:DI 1 "score_register_operand")
+ (match_operand:DI 2 "score_register_operand")))
+ (clobber (reg:CC CC_REGNUM))])]
+ ""
+ ""
+)
+
+(define_insn "*adddi3_score7"
+ [(set (match_operand:DI 0 "register_operand" "=e,d")
+ (plus:DI (match_operand:DI 1 "register_operand" "0,d")
+ (match_operand:DI 2 "register_operand" "e,d")))
+ (clobber (reg:CC CC_REGNUM))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "@
+ add! %L0, %L2\;addc! %H0, %H2
+ add.c %L0, %L1, %L2\;addc %H0, %H1, %H2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "DI")])
+
+(define_insn "*adddi3_score3"
+ [(set (match_operand:DI 0 "score_register_operand" "=d")
+ (plus:DI (match_operand:DI 1 "score_register_operand" "d")
+ (match_operand:DI 2 "score_register_operand" "d")))
+ (clobber (reg:CC CC_REGNUM))]
+ "(TARGET_SCORE3)"
+ "add.c\t%L0, %L1, %L2\;addc\t%H0, %H1, %H2"
+ [(set_attr "type" "arith")
+ (set_attr "length" "8")
+ (set_attr "mode" "DI")])
+
+(define_expand "subsi3"
+ [(set (match_operand:SI 0 "score_register_operand")
+ (minus:SI (match_operand:SI 1 "score_register_operand")
+ (match_operand:SI 2 "score_register_operand")))]
+ ""
+ ""
+)
+
+(define_insn "*subsi3_score7"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (minus:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ return score_select (operands, "sub", false, "", false);
+}
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "*subsi3_score3"
+ [(set (match_operand:SI 0 "score_register_operand" "=e,d")
+ (minus:SI (match_operand:SI 1 "score_register_operand" "0,d")
+ (match_operand:SI 2 "score_register_operand" "e,d")))]
+ "(TARGET_SCORE3)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"sub!\t%0, %2\";
+ case 1: return score_select (operands, "sub", false, "", false);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "length" "2,4")
+ (set_attr "mode" "SI")])
+
+(define_insn "*subsi3_cmp_score7"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d"))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ return score_select (operands, "sub", false, "", true);
+}
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*subsi3_cmp_score3"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (minus:SI (match_operand:SI 1 "score_register_operand" "d")
+ (match_operand:SI 2 "score_register_operand" "d"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d"))]
+ "(TARGET_SCORE3)"
+{
+ return score_select (operands, "sub", false, "", true);
+}
+ [(set_attr "type" "arith")
+ (set_attr "length" "4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_peephole2
+ [(set (match_operand:SI 0 "g32reg_operand" "")
+ (minus:SI (match_operand:SI 1 "g32reg_operand" "")
+ (match_operand:SI 2 "g32reg_operand" "")))
+ (set (reg:CC CC_REGNUM)
+ (compare:CC (match_dup 1) (match_dup 2)))]
+ ""
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC (match_dup 1) (match_dup 2)))
+ (set (match_dup 0)
+ (minus:SI (match_dup 1) (match_dup 2)))])
+
+(define_insn "subsi3_ucc_pcmp"
+ [(parallel
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC (match_operand:SI 1 "score_register_operand" "d")
+ (match_operand:SI 2 "score_register_operand" "d")))
+ (set (match_operand:SI 0 "score_register_operand" "=d")
+ (minus:SI (match_dup 1) (match_dup 2)))])]
+ ""
+{
+ return score_select (operands, "sub", false, "", true);
+}
+ [(set_attr "type" "arith")
+ (set_attr "length" "4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "subsi3_ucc"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (minus:SI (match_operand:SI 1 "score_register_operand" "d")
+ (match_operand:SI 2 "score_register_operand" "d"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "score_register_operand" "=d")
+ (minus:SI (match_dup 1) (match_dup 2)))]
+ ""
+{
+ return score_select (operands, "sub", false, "", true);
+}
+ [(set_attr "type" "arith")
+ (set_attr "length" "4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_expand "subdi3"
+ [(parallel
+ [(set (match_operand:DI 0 "score_register_operand")
+ (minus:DI (match_operand:DI 1 "score_register_operand")
+ (match_operand:DI 2 "score_register_operand")))
+ (clobber (reg:CC CC_REGNUM))])]
+ ""
+ ""
+)
+
+(define_insn "*subdi3_score7"
+ [(set (match_operand:DI 0 "register_operand" "=e,d")
+ (minus:DI (match_operand:DI 1 "register_operand" "0,d")
+ (match_operand:DI 2 "register_operand" "e,d")))
+ (clobber (reg:CC CC_REGNUM))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "@
+ sub! %L0, %L2\;subc %H0, %H1, %H2
+ sub.c %L0, %L1, %L2\;subc %H0, %H1, %H2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "DI")])
+
+(define_insn "*subdi3_score3"
+ [(set (match_operand:DI 0 "score_register_operand" "=d")
+ (minus:DI (match_operand:DI 1 "score_register_operand" "d")
+ (match_operand:DI 2 "score_register_operand" "d")))
+ (clobber (reg:CC CC_REGNUM))]
+ "(TARGET_SCORE3)"
+ "sub.c\t%L0, %L1, %L2\;subc\t%H0, %H1, %H2"
+ [(set_attr "type" "arith")
+ (set_attr "length" "8")
+ (set_attr "mode" "DI")])
+
+(define_expand "andsi3"
+ [(set (match_operand:SI 0 "score_register_operand")
+ (and:SI (match_operand:SI 1 "score_register_operand")
+ (match_operand:SI 2 "arith_operand")))]
+ ""
+ ""
+)
+
+(define_insn "*andsi3_score7"
+ [(set (match_operand:SI 0 "register_operand" "=d,d,d,d")
+ (and:SI (match_operand:SI 1 "register_operand" "0,0,d,d")
+ (match_operand:SI 2 "arith_operand" "I,K,M,d")))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"andis\t%0, %U2\";
+ case 1: return \"andi\t%0, %c2";
+ case 2: return \"andri\t%0, %1, %c2\";
+ case 3: return score_select (operands, "and", true, "", false);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "*andsi3_score3"
+ [(set (match_operand:SI 0 "score_register_operand" "=e,d,d,d,d")
+ (and:SI (match_operand:SI 1 "score_register_operand" "%0,0,0,d,d")
+ (match_operand:SI 2 "arith_operand" "e,I,K,M,d")))]
+ "(TARGET_SCORE3)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"and!\t%0, %2\";
+ case 1: return \"andis\t%0, %U2\";
+ case 2: return \"andi\t%0, %c2";
+ case 3: return \"andri\t%0, %1, %c2\";
+ case 4: return score_select (operands, "and", true, "", false);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "length" "2,4,4,4,4")
+ (set_attr "mode" "SI")])
+
+(define_insn "andsi3_cmp_score7"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (and:SI (match_operand:SI 1 "register_operand" "0,0,0,d")
+ (match_operand:SI 2 "arith_operand" "I,K,M,d"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d,d,d,d"))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"andis.c\t%0, %U2\";
+ case 1: return \"andi.c\t%0, %c2";
+ case 2: return \"andri.c\t%0, %1, %c2\";
+ case 3: return score_select (operands, "and", true, "", true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "andsi3_cmp_score3"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (and:SI (match_operand:SI 1 "score_register_operand" "0,0,0,d")
+ (match_operand:SI 2 "arith_operand" "I,K,M,d"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d,d,d,d"))]
+ ""
+{
+ switch (which_alternative)
+ {
+ case 0: return \"andis.c\t%0, %U2\";
+ case 1: return \"andi.c\t%0, %c2";
+ case 2: return \"andri.c\t%0, %1, %c2\";
+ case 3: return score_select (operands, "and", true, "", true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "length" "4,4,4,4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*andsi3_ucc_score7"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (and:SI
+ (match_operand:SI 1 "register_operand" "0,0,d,d")
+ (match_operand:SI 2 "arith_operand" "I,K,M,d"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=d,d,d,d")
+ (and:SI (match_dup 1) (match_dup 2)))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"andis.c\t%0, %U2\";
+ case 1: return \"andi.c\t%0, %c2";
+ case 2: return \"andri.c\t%0, %1, %c2\";
+ case 3: return score_select (operands, "and", true, "", true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*andsi3_ucc_score3"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (and:SI
+ (match_operand:SI 1 "score_register_operand" "0,0,d,d")
+ (match_operand:SI 2 "arith_operand" "I,K,M,d"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "score_register_operand" "=d,d,d,d")
+ (and:SI (match_dup 1) (match_dup 2)))]
+ "(TARGET_SCORE3)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"andis.c\t%0, %U2\";
+ case 1: return \"andi.c\t%0, %c2";
+ case 2: return \"andri.c\t%0, %1, %c2\";
+ case 3: return score_select (operands, "and", true, "", true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "length" "4,4,4,4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+
+(define_insn_and_split "*zero_extract_andi"
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC (zero_extract:SI
+ (match_operand:SI 0 "score_register_operand" "d")
+ (match_operand:SI 1 "const_uimm5" "")
+ (match_operand:SI 2 "const_uimm5" ""))
+ (const_int 0)))]
+ ""
+ "#"
+ ""
+ [(const_int 1)]
+{
+ score_zero_extract_andi (operands);
+ DONE;
+})
+
+(define_expand "iorsi3"
+ [(set (match_operand:SI 0 "score_register_operand")
+ (ior:SI (match_operand:SI 1 "score_register_operand")
+ (match_operand:SI 2 "arith_operand")))]
+ ""
+ ""
+)
+
+(define_insn "*iorsi3_score7"
+ [(set (match_operand:SI 0 "register_operand" "=d,d,d,d")
+ (ior:SI (match_operand:SI 1 "register_operand" "0,0,d,d")
+ (match_operand:SI 2 "arith_operand" "I,K,M,d")))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"oris\t%0, %U2\";
+ case 1: return \"ori\t%0, %c2\";
+ case 2: return \"orri\t%0, %1, %c2\";
+ case 3: return score_select (operands, "or", true, "", false);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "*iorsi3_score3"
+ [(set (match_operand:SI 0 "score_register_operand" "=e,d,d,d,d")
+ (ior:SI (match_operand:SI 1 "score_register_operand" "%0,0,0,d,d")
+ (match_operand:SI 2 "arith_operand" "e,I,K,M,d")))]
+ "(TARGET_SCORE3)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"or!\t%0, %2\";
+ case 1: return \"oris\t%0, %U2\";
+ case 2: return \"ori\t%0, %c2\";
+ case 3: return \"orri\t%0, %1, %c2\";
+ case 4: return score_select (operands, "or", true, "", false);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "length" "2,4,4,4,4")
+ (set_attr "mode" "SI")])
+
+(define_insn "*iorsi3_ucc_score7"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (ior:SI
+ (match_operand:SI 1 "register_operand" "0,0,d,d")
+ (match_operand:SI 2 "arith_operand" "I,K,M,d"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=d,d,d,d")
+ (ior:SI (match_dup 1) (match_dup 2)))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"oris.c\t%0, %U2\";
+ case 1: return \"ori.c\t%0, %c2\";
+ case 2: return \"orri.c\t%0, %1, %c2\";
+ case 3: return score_select (operands, "or", true, "", true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*iorsi3_ucc_score3"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (ior:SI
+ (match_operand:SI 1 "score_register_operand" "0,0,d,d")
+ (match_operand:SI 2 "arith_operand" "I,K,M,d"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "score_register_operand" "=d,d,d,d")
+ (ior:SI (match_dup 1) (match_dup 2)))]
+ "(TARGET_SCORE3)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"oris.c\t%0, %U2\";
+ case 1: return \"ori.c\t%0, %c2\";
+ case 2: return \"orri.c\t%0, %1, %c2\";
+ case 3: return score_select (operands, "or", true, "", true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "length" "4,4,4,4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*iorsi3_cmp_score7"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (ior:SI
+ (match_operand:SI 1 "register_operand" "0,0,d,d")
+ (match_operand:SI 2 "arith_operand" "I,K,M,d"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d,d,d,d"))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"oris.c\t%0, %U2\";
+ case 1: return \"ori.c\t%0, %c2\";
+ case 2: return \"orri.c\t%0, %1, %c2\";
+ case 3: return score_select (operands, "or", true, "", true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*iorsi3_cmp_score3"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (ior:SI
+ (match_operand:SI 1 "score_register_operand" "0,0,d,d")
+ (match_operand:SI 2 "arith_operand" "I,K,M,d"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d,d,d,d"))]
+ "(TARGET_SCORE3)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"oris.c\t%0, %U2\";
+ case 1: return \"ori.c\t%0, %c2\";
+ case 2: return \"orri.c\t%0, %1, %c2\";
+ case 3: return score_select (operands, "or", true, "", true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "length" "4,4,4,4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_expand "xorsi3"
+ [(set (match_operand:SI 0 "score_register_operand")
+ (xor:SI (match_operand:SI 1 "score_register_operand")
+ (match_operand:SI 2 "score_register_operand")))]
+ ""
+ ""
+)
+
+(define_insn "*xorsi3_score7"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (xor:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ return score_select (operands, "xor", true, "", false);
+}
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "*xorsi3_score3"
+ [(set (match_operand:SI 0 "score_register_operand" "=d")
+ (xor:SI (match_operand:SI 1 "score_register_operand" "d")
+ (match_operand:SI 2 "score_register_operand" "d")))]
+ "(TARGET_SCORE3)"
+{
+ return score_select (operands, "xor", true, "", false);
+}
+ [(set_attr "type" "arith")
+ (set_attr "length" "4")
+ (set_attr "mode" "SI")])
+
+
+(define_insn "*xorsi3_ucc_score7"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (xor:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=d")
+ (xor:SI (match_dup 1) (match_dup 2)))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ return score_select (operands, "xor", true, "", true);
+}
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*xorsi3_ucc_score3"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (xor:SI (match_operand:SI 1 "score_register_operand" "d")
+ (match_operand:SI 2 "score_register_operand" "d"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "score_register_operand" "=d")
+ (xor:SI (match_dup 1) (match_dup 2)))]
+ "(TARGET_SCORE3)"
+{
+ return score_select (operands, "xor", true, "", true);
+}
+ [(set_attr "type" "arith")
+ (set_attr "length" "4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+
+(define_insn "*xorsi3_cmp_score7"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (xor:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d"))]
+ ""
+{
+ return score_select (operands, "xor", true, "", true);
+}
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*xorsi3_cmp_score3"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (xor:SI (match_operand:SI 1 "score_register_operand" "d")
+ (match_operand:SI 2 "score_register_operand" "d"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d"))]
+ ""
+{
+ return score_select (operands, "xor", true, "", true);
+}
+ [(set_attr "type" "arith")
+ (set_attr "length" "4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_expand "extendqisi2"
+ [(set (match_operand:SI 0 "score_register_operand")
+ (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand")))]
+ ""
+ ""
+)
+
+(define_insn "*extendqisi2_score7"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,m")))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"extsb\t%0, %1\";
+ case 1: return score_linsn (operands, SCORE_BYTE, true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith,load")
+ (set_attr "mode" "SI")])
+
+(define_insn "*extendqisi2_score3"
+ [(set (match_operand:SI 0 "score_register_operand" "=d,d")
+ (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,m")))]
+ "(TARGET_SCORE3)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"extsb\t%0, %1\";
+ case 1: return score_linsn (operands, SCORE_BYTE, true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith,load")
+ (set_attr "length" "4,4")
+ (set_attr "mode" "SI")])
+
+(define_insn "*extendqisi2_ucc_score7"
+ [(set (reg:CC_N CC_REGNUM)
+ (compare:CC_N (ashiftrt:SI
+ (ashift:SI (match_operand:SI 1 "register_operand" "d")
+ (const_int 24))
+ (const_int 24))
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=d")
+ (sign_extend:SI (match_operand:QI 2 "register_operand" "0")))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "extsb.c %0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*extendqisi2_ucc_score3"
+ [(set (reg:CC_N CC_REGNUM)
+ (compare:CC_N (ashiftrt:SI
+ (ashift:SI (match_operand:SI 1 "score_register_operand" "d")
+ (const_int 24))
+ (const_int 24))
+ (const_int 0)))
+ (set (match_operand:SI 0 "score_register_operand" "=d")
+ (sign_extend:SI (match_operand:QI 2 "score_register_operand" "0")))]
+ "(TARGET_SCORE3)"
+ "extsb.c\t%0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "length" "4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*extendqisi2_cmp_score7"
+ [(set (reg:CC_N CC_REGNUM)
+ (compare:CC_N (ashiftrt:SI
+ (ashift:SI (match_operand:SI 1 "register_operand" "d")
+ (const_int 24))
+ (const_int 24))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d"))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "extsb.c %0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*extendqisi2_cmp_score3"
+ [(set (reg:CC_N CC_REGNUM)
+ (compare:CC_N (ashiftrt:SI
+ (ashift:SI (match_operand:SI 1 "score_register_operand" "d")
+ (const_int 24))
+ (const_int 24))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d"))]
+ "(TARGET_SCORE3)"
+ "extsb.c\t%0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "length" "4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_expand "extendhisi2"
+ [(set (match_operand:SI 0 "score_register_operand")
+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand")))]
+ ""
+ ""
+)
+
+(define_insn "*extendhisi2_score7"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d,m")))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"extsh\t%0, %1\";
+ case 1: return score_linsn (operands, SCORE_HWORD, true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith, load")
+ (set_attr "mode" "SI")])
+
+(define_insn "*extendhisi2_score3"
+ [(set (match_operand:SI 0 "score_register_operand" "=d,d")
+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d,m")))]
+ "(TARGET_SCORE3)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"extsh\t%0, %1\";
+ case 1: return score_linsn (operands, SCORE_HWORD, true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith, load")
+ (set_attr "length" "4,4")
+ (set_attr "mode" "SI")])
+
+(define_insn "*extendhisi2_ucc_score7"
+ [(set (reg:CC_N CC_REGNUM)
+ (compare:CC_N (ashiftrt:SI
+ (ashift:SI (match_operand:SI 1 "register_operand" "d")
+ (const_int 16))
+ (const_int 16))
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=d")
+ (sign_extend:SI (match_operand:HI 2 "register_operand" "0")))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "extsh.c %0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*extendhisi2_ucc_score3"
+ [(set (reg:CC_N CC_REGNUM)
+ (compare:CC_N (ashiftrt:SI
+ (ashift:SI (match_operand:SI 1 "score_register_operand" "d")
+ (const_int 16))
+ (const_int 16))
+ (const_int 0)))
+ (set (match_operand:SI 0 "score_register_operand" "=d")
+ (sign_extend:SI (match_operand:HI 2 "score_register_operand" "0")))]
+ "(TARGET_SCORE3)"
+ "extsh.c\t%0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "length" "4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*extendhisi2_cmp_score7"
+ [(set (reg:CC_N CC_REGNUM)
+ (compare:CC_N (ashiftrt:SI
+ (ashift:SI (match_operand:SI 1 "register_operand" "d")
+ (const_int 16))
+ (const_int 16))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d"))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "extsh.c %0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*extendhisi2_cmp_score3"
+ [(set (reg:CC_N CC_REGNUM)
+ (compare:CC_N (ashiftrt:SI
+ (ashift:SI (match_operand:SI 1 "score_register_operand" "d")
+ (const_int 16))
+ (const_int 16))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d"))]
+ "(TARGET_SCORE3)"
+ "extsh.c\t%0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "length" "4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_expand "zero_extendqisi2"
+ [(set (match_operand:SI 0 "score_register_operand")
+ (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand")))]
+ ""
+ ""
+)
+
+(define_insn "*zero_extendqisi2_score7"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,m")))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"extzb\t%0, %1\";
+ case 1: return score_linsn (operands, SCORE_BYTE, false);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith, load")
+ (set_attr "mode" "SI")])
+
+(define_insn "*zero_extendqisi2_score3"
+ [(set (match_operand:SI 0 "score_register_operand" "=d,d")
+ (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,m")))]
+ "(TARGET_SCORE3)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"extzb\t%0, %1\";
+ case 1: return score_linsn (operands, SCORE_BYTE, false);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith, load")
+ (set_attr "length" "4,4")
+ (set_attr "mode" "SI")])
+
+(define_insn "*zero_extendqisi2_ucc_score7"
+ [(set (reg:CC_N CC_REGNUM)
+ (compare:CC_N (lshiftrt:SI
+ (ashift:SI (match_operand:SI 1 "register_operand" "d")
+ (const_int 24))
+ (const_int 24))
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=d")
+ (zero_extend:SI (match_operand:QI 2 "register_operand" "0")))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "extzb.c %0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*zero_extendqisi2_ucc_score3"
+ [(set (reg:CC_N CC_REGNUM)
+ (compare:CC_N (lshiftrt:SI
+ (ashift:SI (match_operand:SI 1 "score_register_operand" "d")
+ (const_int 24))
+ (const_int 24))
+ (const_int 0)))
+ (set (match_operand:SI 0 "score_register_operand" "=d")
+ (zero_extend:SI (match_operand:QI 2 "score_register_operand" "0")))]
+ "(TARGET_SCORE3)"
+ "extzb.c\t%0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "length" "4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*zero_extendqisi2_cmp_score7"
+ [(set (reg:CC_N CC_REGNUM)
+ (compare:CC_N (lshiftrt:SI
+ (ashift:SI (match_operand:SI 1 "register_operand" "d")
+ (const_int 24))
+ (const_int 24))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d"))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "extzb.c %0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*zero_extendqisi2_cmp_score3"
+ [(set (reg:CC_N CC_REGNUM)
+ (compare:CC_N (lshiftrt:SI
+ (ashift:SI (match_operand:SI 1 "score_register_operand" "d")
+ (const_int 24))
+ (const_int 24))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d"))]
+ "(TARGET_SCORE3)"
+ "extzb.c\t%0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "length" "4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_expand "zero_extendhisi2"
+ [(set (match_operand:SI 0 "score_register_operand")
+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand")))]
+ ""
+ ""
+)
+
+(define_insn "*zero_extendhisi2_score7"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d,m")))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"extzh\t%0, %1\";
+ case 1: return score_linsn (operands, SCORE_HWORD, false);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith, load")
+ (set_attr "mode" "SI")])
+
+(define_insn "*zero_extendhisi2_score3"
+ [(set (match_operand:SI 0 "score_register_operand" "=d,d")
+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d,m")))]
+ "(TARGET_SCORE3)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"extzh\t%0, %1\";
+ case 1: return score_linsn (operands, SCORE_HWORD, false);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith, load")
+ (set_attr "length" "4,4")
+ (set_attr "mode" "SI")])
+
+(define_insn "*zero_extendhisi2_ucc_score7"
+ [(set (reg:CC_N CC_REGNUM)
+ (compare:CC_N (lshiftrt:SI
+ (ashift:SI (match_operand:SI 1 "register_operand" "d")
+ (const_int 16))
+ (const_int 16))
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=d")
+ (zero_extend:SI (match_operand:HI 2 "register_operand" "0")))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "extzh.c %0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*zero_extendhisi2_ucc_score3"
+ [(set (reg:CC_N CC_REGNUM)
+ (compare:CC_N (lshiftrt:SI
+ (ashift:SI (match_operand:SI 1 "score_register_operand" "d")
+ (const_int 16))
+ (const_int 16))
+ (const_int 0)))
+ (set (match_operand:SI 0 "score_register_operand" "=d")
+ (zero_extend:SI (match_operand:HI 2 "score_register_operand" "0")))]
+ "(TARGET_SCORE3)"
+ "extzh.c\t%0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "length" "4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*zero_extendhisi2_cmp_score7"
+ [(set (reg:CC_N CC_REGNUM)
+ (compare:CC_N (lshiftrt:SI
+ (ashift:SI (match_operand:SI 1 "register_operand" "d")
+ (const_int 16))
+ (const_int 16))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d"))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "extzh.c %0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*zero_extendhisi2_cmp_score3"
+ [(set (reg:CC_N CC_REGNUM)
+ (compare:CC_N (lshiftrt:SI
+ (ashift:SI (match_operand:SI 1 "score_register_operand" "d")
+ (const_int 16))
+ (const_int 16))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d"))]
+ "(TARGET_SCORE3)"
+ "extzh.c\t%0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "length" "4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_expand "mulsi3"
+ [(set (match_operand:SI 0 "score_register_operand")
+ (mult:SI (match_operand:SI 1 "score_register_operand")
+ (match_operand:SI 2 "score_register_operand")))]
+ ""
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ emit_insn (gen_mulsi3_score7 (operands[0], operands[1], operands[2]));
+ else if (TARGET_SCORE3)
+ emit_insn (gen_mulsi3_score3 (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_insn "mulsi3_score7"
+ [(set (match_operand:SI 0 "register_operand" "=l")
+ (mult:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")))
+ (clobber (reg:SI HI_REGNUM))]
+ "(TARGET_SCORE5 || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "mul %1, %2"
+ [(set_attr "type" "mul")
+ (set_attr "mode" "SI")])
+
+(define_insn "mulsi3_score3"
+ [(set (match_operand:SI 0 "score_register_operand" "=d")
+ (mult:SI (match_operand:SI 1 "score_register_operand" "d")
+ (match_operand:SI 2 "score_register_operand" "d")))]
+ "(TARGET_SCORE3)"
+ "mulr.l\t%0, %1, %2"
+ [(set_attr "type" "mul")
+ (set_attr "length" "4")
+ (set_attr "mode" "SI")])
+
+(define_expand "mulsidi3"
+ [(set (match_operand:DI 0 "score_register_operand")
+ (mult:DI (sign_extend:DI
+ (match_operand:SI 1 "score_register_operand"))
+ (sign_extend:DI
+ (match_operand:SI 2 "score_register_operand"))))]
+ ""
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ emit_insn (gen_mulsidi3_score7 (operands[0], operands[1], operands[2]));
+ else if (TARGET_SCORE3)
+ emit_insn (gen_mulsidi3_score3 (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_insn "mulsidi3_score7"
+ [(set (match_operand:DI 0 "register_operand" "=x")
+ (mult:DI (sign_extend:DI
+ (match_operand:SI 1 "register_operand" "d"))
+ (sign_extend:DI
+ (match_operand:SI 2 "register_operand" "d"))))]
+ "(TARGET_SCORE5 || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "mul %1, %2"
+ [(set_attr "type" "mul")
+ (set_attr "mode" "DI")])
+
+(define_insn "mulsidi3_score3"
+ [(set (match_operand:DI 0 "score_register_operand" "=d")
+ (mult:DI (sign_extend:DI
+ (match_operand:SI 1 "score_register_operand" "d"))
+ (sign_extend:DI
+ (match_operand:SI 2 "score_register_operand" "d"))))]
+ "(TARGET_SCORE3)"
+ "mulr\t%0, %1, %2"
+ [(set_attr "type" "mul")
+ (set_attr "length" "4")
+ (set_attr "mode" "DI")])
+
+(define_expand "umulsidi3"
+ [(set (match_operand:DI 0 "score_register_operand")
+ (mult:DI (zero_extend:DI
+ (match_operand:SI 1 "score_register_operand"))
+ (zero_extend:DI
+ (match_operand:SI 2 "score_register_operand"))))]
+ ""
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ emit_insn (gen_umulsidi3_score7 (operands[0], operands[1], operands[2]));
+ else if (TARGET_SCORE3)
+ emit_insn (gen_umulsidi3_score3 (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_insn "umulsidi3_score7"
+ [(set (match_operand:DI 0 "register_operand" "=x")
+ (mult:DI (zero_extend:DI
+ (match_operand:SI 1 "register_operand" "d"))
+ (zero_extend:DI
+ (match_operand:SI 2 "register_operand" "d"))))]
+ "(TARGET_SCORE5 || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "mulu %1, %2"
+ [(set_attr "type" "mul")
+ (set_attr "mode" "DI")])
+
+(define_insn "umulsidi3_score3"
+ [(set (match_operand:DI 0 "score_register_operand" "=d")
+ (mult:DI (zero_extend:DI
+ (match_operand:SI 1 "score_register_operand" "d"))
+ (zero_extend:DI
+ (match_operand:SI 2 "score_register_operand" "d"))))]
+ "(TARGET_SCORE3)"
+ "mulur\t%0, %1, %2"
+ [(set_attr "type" "mul")
+ (set_attr "length" "4")
+ (set_attr "mode" "DI")])
+
+(define_expand "divmodsi4"
+ [(parallel
+ [(set (match_operand:SI 0 "score_register_operand")
+ (div:SI (match_operand:SI 1 "score_register_operand")
+ (match_operand:SI 2 "score_register_operand")))
+ (set (match_operand:SI 3 "score_register_operand")
+ (mod:SI (match_dup 1) (match_dup 2)))])]
+ ""
+ ""
+)
+
+(define_insn "*divmodsi4_score7"
+ [(set (match_operand:SI 0 "register_operand" "=l")
+ (div:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")))
+ (set (match_operand:SI 3 "register_operand" "=h")
+ (mod:SI (match_dup 1) (match_dup 2)))]
+ "(TARGET_SCORE5 || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "div %1, %2"
+ [(set_attr "type" "div")
+ (set_attr "mode" "SI")])
+
+(define_insn "*divmodsi4_score3"
+ [(set (match_operand:SI 0 "score_register_operand" "=l")
+ (div:SI (match_operand:SI 1 "score_register_operand" "d")
+ (match_operand:SI 2 "score_register_operand" "d")))
+ (set (match_operand:SI 3 "score_register_operand" "=h")
+ (mod:SI (match_dup 1) (match_dup 2)))]
+ "(TARGET_SCORE3)"
+ "div\t%1, %2"
+ [(set_attr "type" "div")
+ (set_attr "mode" "SI")])
+
+(define_expand "udivmodsi4"
+ [(parallel
+ [(set (match_operand:SI 0 "score_register_operand")
+ (udiv:SI (match_operand:SI 1 "score_register_operand")
+ (match_operand:SI 2 "score_register_operand")))
+ (set (match_operand:SI 3 "score_register_operand")
+ (umod:SI (match_dup 1) (match_dup 2)))])]
+ ""
+ ""
+)
+
+(define_insn "*udivmodsi4_score7"
+ [(set (match_operand:SI 0 "register_operand" "=l")
+ (udiv:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")))
+ (set (match_operand:SI 3 "register_operand" "=h")
+ (umod:SI (match_dup 1) (match_dup 2)))]
+ "(TARGET_SCORE5 || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "divu %1, %2"
+ [(set_attr "type" "div")
+ (set_attr "mode" "SI")])
+
+(define_insn "*udivmodsi4_score3"
+ [(set (match_operand:SI 0 "score_register_operand" "=l")
+ (udiv:SI (match_operand:SI 1 "score_register_operand" "d")
+ (match_operand:SI 2 "score_register_operand" "d")))
+ (set (match_operand:SI 3 "score_register_operand" "=h")
+ (umod:SI (match_dup 1) (match_dup 2)))]
+ "(TARGET_SCORE3)"
+ "divu\t%1, %2"
+ [(set_attr "type" "div")
+ (set_attr "mode" "SI")])
+
+(define_expand "ashlsi3"
+ [(set (match_operand:SI 0 "score_register_operand")
+ (ashift:SI (match_operand:SI 1 "score_register_operand")
+ (match_operand:SI 2 "arith_operand")))]
+ ""
+ ""
+)
+
+(define_insn "*ashlsi3_score7"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (ashift:SI (match_operand:SI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "J,d")))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "@
+ slli %0, %1, %c2
+ sll %0, %1, %2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "*ashlsi3_score3"
+ [(set (match_operand:SI 0 "score_register_operand" "=e,d,d")
+ (ashift:SI (match_operand:SI 1 "score_register_operand" "0,d,d")
+ (match_operand:SI 2 "arith_operand" "J,J,d")))]
+ "(TARGET_SCORE3)"
+ "@
+ slli!\t%0, %c2
+ slli\t%0, %1, %c2
+ sll\t%0, %1, %2"
+ [(set_attr "type" "arith")
+ (set_attr "length" "2,4,4")
+ (set_attr "mode" "SI")])
+
+(define_insn "*ashlsi3_ucc_score7"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (ashift:SI
+ (match_operand:SI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "J,d"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=d,d")
+ (ashift:SI (match_dup 1) (match_dup 2)))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ switch (which_alternative)
+ {
+ case 0: return score_select (operands, "slli", false, "c", true);
+ case 1: return score_select (operands, "sll", false, "", true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*ashlsi3_ucc_score3"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (ashift:SI
+ (match_operand:SI 1 "score_register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "J,d"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "score_register_operand" "=d,d")
+ (ashift:SI (match_dup 1) (match_dup 2)))]
+ "(TARGET_SCORE3)"
+{
+ switch (which_alternative)
+ {
+ case 0: return score_select (operands, "slli", false, "c", true);
+ case 1: return score_select (operands, "sll", false, "", true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "length" "4,4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*ashlsi3_cmp_score7"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (ashift:SI
+ (match_operand:SI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "J,d"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d,d"))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ switch (which_alternative)
+ {
+ case 0: return score_select (operands, "slli", false, "c", true);
+ case 1: return score_select (operands, "sll", false, "", true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*ashlsi3_cmp_score3"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (ashift:SI
+ (match_operand:SI 1 "score_register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "J,d"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d,d"))]
+ "(TARGET_SCORE3)"
+{
+ switch (which_alternative)
+ {
+ case 0: return score_select (operands, "slli", false, "c", true);
+ case 1: return score_select (operands, "sll", false, "", true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "length" "4,4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+
+(define_expand "ashrsi3"
+ [(set (match_operand:SI 0 "score_register_operand")
+ (ashiftrt:SI (match_operand:SI 1 "score_register_operand")
+ (match_operand:SI 2 "arith_operand")))]
+ ""
+ ""
+)
+
+(define_insn "*ashrsi3_score7"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "J,d")))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "@
+ srai %0, %1, %c2
+ sra %0, %1, %2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "*ashrsi3_score3"
+ [(set (match_operand:SI 0 "score_register_operand" "=d,d")
+ (ashiftrt:SI (match_operand:SI 1 "score_register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "J,d")))]
+ "(TARGET_SCORE3)"
+ "@
+ srai\t%0, %1, %c2
+ sra\t%0, %1, %2"
+ [(set_attr "type" "arith")
+ (set_attr "length" "4,4")
+ (set_attr "mode" "SI")])
+
+(define_insn "*ashrsi3_ucc_score7"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (ashiftrt:SI
+ (match_operand:SI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "J,d"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=d,d")
+ (ashiftrt:SI (match_dup 1) (match_dup 2)))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"srai.c\t%0, %1, %c2\";
+ case 1: return score_select (operands, "sra", false, "", true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*ashrsi3_ucc_score3"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (ashiftrt:SI
+ (match_operand:SI 1 "score_register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "J,d"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "score_register_operand" "=d,d")
+ (ashiftrt:SI (match_dup 1) (match_dup 2)))]
+ "(TARGET_SCORE3)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"srai.c\t%0, %1, %c2\";
+ case 1: return score_select (operands, "sra", false, "", true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "length" "4,4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*ashrsi3_cmp_score7"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (ashiftrt:SI
+ (match_operand:SI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "J,d"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d,d"))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"srai.c\t%0, %1, %c2\";
+ case 1: return score_select (operands, "sra", false, "", true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "ashrsi3_cmp_score3"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (ashiftrt:SI
+ (match_operand:SI 1 "score_register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "J,d"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d,d"))]
+ "(TARGET_SCORE3)"
+{
+ switch (which_alternative)
+ {
+ case 0: return \"srai.c\t%0, %1, %c2\";
+ case 1: return score_select (operands, "sra", false, "", true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "length" "4,4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_expand "lshrsi3"
+ [(set (match_operand:SI 0 "score_register_operand")
+ (lshiftrt:SI (match_operand:SI 1 "score_register_operand")
+ (match_operand:SI 2 "arith_operand")))]
+ ""
+ ""
+)
+
+(define_insn "*lshrsi3_score7"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "J,d")))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "@
+ srli %0, %1, %c2
+ srl %0, %1, %2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "*lshrsi3_score3"
+ [(set (match_operand:SI 0 "score_register_operand" "=e,d,d")
+ (lshiftrt:SI (match_operand:SI 1 "score_register_operand" "0,d,d")
+ (match_operand:SI 2 "arith_operand" "J,J,d")))]
+ "(TARGET_SCORE3)"
+ "@
+ srli!\t%0, %c2
+ srli\t%0, %1, %c2
+ srl\t%0, %1, %2"
+ [(set_attr "type" "arith")
+ (set_attr "length" "2,4,4")
+ (set_attr "mode" "SI")])
+
+(define_insn "*lshrsi3_ucc_score7"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (lshiftrt:SI
+ (match_operand:SI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "J,d"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=d,d")
+ (lshiftrt:SI (match_dup 1) (match_dup 2)))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ switch (which_alternative)
+ {
+ case 0: return score_select (operands, "srli", false, "c", true);
+ case 1: return score_select (operands, "srl", false, "", true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*lshrsi3_ucc_score3"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (lshiftrt:SI
+ (match_operand:SI 1 "score_register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "J,d"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "score_register_operand" "=d,d")
+ (lshiftrt:SI (match_dup 1) (match_dup 2)))]
+ "(TARGET_SCORE3)"
+{
+ switch (which_alternative)
+ {
+ case 0: return score_select (operands, "srli", false, "c", true);
+ case 1: return score_select (operands, "srl", false, "", true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "length" "4,4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*lshrsi3_cmp_score7"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (lshiftrt:SI
+ (match_operand:SI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "J,d"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d,d"))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ switch (which_alternative)
+ {
+ case 0: return score_select (operands, "srli", false, "c", true);
+ case 1: return score_select (operands, "srl", false, "", true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*lshrsi3_cmp_score3"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (lshiftrt:SI
+ (match_operand:SI 1 "score_register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "J,d"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d,d"))]
+ "(TARGET_SCORE3)"
+{
+ switch (which_alternative)
+ {
+ case 0: return score_select (operands, "srli", false, "c", true);
+ case 1: return score_select (operands, "srl", false, "", true);
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith")
+ (set_attr "length" "4,4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_expand "negsi2"
+ [(set (match_operand:SI 0 "score_register_operand")
+ (neg:SI (match_operand:SI 1 "score_register_operand")))]
+ ""
+ ""
+)
+
+(define_insn "*negsi2_score7"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (neg:SI (match_operand:SI 1 "register_operand" "d")))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "neg %0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "*negsi2_score3"
+ [(set (match_operand:SI 0 "score_register_operand" "=d")
+ (neg:SI (match_operand:SI 1 "score_register_operand" "d")))]
+ "(TARGET_SCORE3)"
+ "neg\t%0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "length" "4")
+ (set_attr "mode" "SI")])
+
+(define_insn "*negsi2_cmp_score7"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "e,d"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=e,d"))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "@
+ neg! %0, %1
+ neg.c %0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*negsi2_cmp_score3"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (neg:SI (match_operand:SI 1 "score_register_operand" "d"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d"))]
+ "(TARGET_SCORE3)"
+ "neg.c\t%0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "length" "4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*negsi2_ucc_score7"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "e,d"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=e,d")
+ (neg:SI (match_dup 1)))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "@
+ neg! %0, %1
+ neg.c %0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*negsi2_ucc_score3"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (neg:SI (match_operand:SI 1 "score_register_operand" "d"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "score_register_operand" "=d")
+ (neg:SI (match_dup 1)))]
+ "(TARGET_SCORE3)"
+ "neg.c\t%0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "length" "4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+
+(define_expand "one_cmplsi2"
+ [(set (match_operand:SI 0 "score_register_operand")
+ (not:SI (match_operand:SI 1 "score_register_operand")))]
+ ""
+ ""
+)
+
+(define_insn "*one_cmplsi2_score7"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (not:SI (match_operand:SI 1 "register_operand" "d")))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "not\t%0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "*one_cmplsi2_score3"
+ [(set (match_operand:SI 0 "score_register_operand" "=d")
+ (not:SI (match_operand:SI 1 "score_register_operand" "d")))]
+ "(TARGET_SCORE3)"
+ "not\t%0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "length" "4")
+ (set_attr "mode" "SI")])
+
+(define_insn "*one_cmplsi2_ucc_score7"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (not:SI (match_operand:SI 1 "register_operand" "e,d"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=e,d")
+ (not:SI (match_dup 1)))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "@
+ not! %0, %1
+ not.c %0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*one_cmplsi2_ucc_score3"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (not:SI (match_operand:SI 1 "score_register_operand" "d"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "score_register_operand" "=d")
+ (not:SI (match_dup 1)))]
+ "(TARGET_SCORE3)"
+ "not.c\t%0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "length" "4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*one_cmplsi2_cmp_score7"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (not:SI (match_operand:SI 1 "register_operand" "e,d"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=e,d"))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "@
+ not! %0, %1
+ not.c %0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*one_cmplsi2_cmp_score3"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (not:SI (match_operand:SI 1 "score_register_operand" "d"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d"))]
+ "(TARGET_SCORE3)"
+ "not.c\t%0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "length" "4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_expand "rotlsi3"
+ [(parallel
+ [(set (match_operand:SI 0 "score_register_operand")
+ (rotate:SI (match_operand:SI 1 "score_register_operand")
+ (match_operand:SI 2 "arith_operand")))
+ (clobber (reg:CC CC_REGNUM))])]
+ ""
+ ""
+)
+
+(define_insn "*rotlsi3_score7"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (rotate:SI (match_operand:SI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "J,d")))
+ (clobber (reg:CC CC_REGNUM))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "@
+ roli.c %0, %1, %c2
+ rol.c %0, %1, %2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "*rotlsi3_score3"
+ [(set (match_operand:SI 0 "score_register_operand" "=d,d")
+ (rotate:SI (match_operand:SI 1 "score_register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "J,d")))
+ (clobber (reg:CC CC_REGNUM))]
+ "(TARGET_SCORE3)"
+ "@
+ roli.c\t%0, %1, %c2
+ rol.c\t%0, %1, %2"
+ [(set_attr "type" "arith")
+ (set_attr "length" "4,4")
+ (set_attr "mode" "SI")])
+
+(define_expand "rotrsi3"
+ [(parallel
+ [(set (match_operand:SI 0 "score_register_operand")
+ (rotatert:SI (match_operand:SI 1 "score_register_operand")
+ (match_operand:SI 2 "arith_operand")))
+ (clobber (reg:CC CC_REGNUM))])]
+ ""
+ ""
+)
+
+(define_insn "*rotrsi3_score7"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (rotatert:SI (match_operand:SI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "J,d")))
+ (clobber (reg:CC CC_REGNUM))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "@
+ rori.c %0, %1, %c2
+ ror.c %0, %1, %2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "*rotrsi3_score3"
+ [(set (match_operand:SI 0 "score_register_operand" "=d,d")
+ (rotatert:SI (match_operand:SI 1 "score_register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "J,d")))
+ (clobber (reg:CC CC_REGNUM))]
+ "(TARGET_SCORE3)"
+ "@
+ rori.c\t%0, %1, %c2
+ ror.c\t%0, %1, %2"
+ [(set_attr "type" "arith")
+ (set_attr "length" "4,4")
+ (set_attr "mode" "SI")])
+
+(define_expand "cbranchsi4"
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC (match_operand:SI 1 "score_register_operand" "")
+ (match_operand:SI 2 "arith_operand" "")))
+ (set (pc)
+ (if_then_else
+ (match_operator 0 "ordered_comparison_operator"
+ [(reg:CC CC_REGNUM)
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ ""
+ "")
+
+(define_insn "cbrancheqz"
+ [(set (pc) (if_then_else
+ (eq (match_operand:SI 0 "score_register_operand" "d")
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (clobber (reg:CC CC_REGNUM))]
+ "(TARGET_SCORE3)"
+{
+ if (get_attr_length (insn) == 4)
+ return \"bcmpeqz\t%0, %1\";
+ else
+ return \"cmpi!\t%0, 0\;beq!\t%1\";
+}
+ [(set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 1) (pc)) (const_int -504))
+ (le (minus (match_dup 1) (pc)) (const_int 502)))
+ (const_int 4)
+ (const_int 6)))])
+
+(define_insn "cbrancheq"
+ [(set (pc) (if_then_else
+ (eq (match_operand:SI 0 "score_register_operand" "d")
+ (match_operand:SI 1 "score_register_operand" "d"))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))
+ (clobber (reg:CC CC_REGNUM))]
+ "(TARGET_SCORE3)"
+{
+ if (get_attr_length (insn) == 4)
+ return \"bcmpeq\t%0, %1, %2\";
+ else
+ return \"cmp!\t%0, %1\;beq!\t%2\";
+}
+ [(set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 2) (pc)) (const_int -504))
+ (le (minus (match_dup 2) (pc)) (const_int 502)))
+ (const_int 4)
+ (const_int 6)))])
+
+(define_insn "cbranchnez"
+ [(set (pc) (if_then_else
+ (ne (match_operand:SI 0 "score_register_operand" "d")
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (clobber (reg:CC CC_REGNUM))]
+ "(TARGET_SCORE3)"
+{
+ if (get_attr_length (insn) == 4)
+ return \"bcmpnez\t%0, %1\";
+ else
+ return \"cmpi!\t%0, 0\;bne\t%1\";
+}
+ [(set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 1) (pc)) (const_int -504))
+ (le (minus (match_dup 1) (pc)) (const_int 502)))
+ (const_int 4)
+ (const_int 6)))])
+
+(define_insn "cbranchne"
+ [(set (pc) (if_then_else
+ (ne (match_operand:SI 0 "score_register_operand" "d")
+ (match_operand:SI 1 "score_register_operand" "d"))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))
+ (clobber (reg:CC CC_REGNUM))]
+ "(TARGET_SCORE3)"
+{
+ if (get_attr_length (insn) == 4)
+ return \"bcmpne\t%0, %1, %2\";
+ else
+ return \"cmp!\t%0, %1\;bne\t%2\";
+}
+ [(set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 2) (pc)) (const_int -504))
+ (le (minus (match_dup 2) (pc)) (const_int 502)))
+ (const_int 4)
+ (const_int 6)))])
+
+(define_insn "cmpsi_nz_score7"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (match_operand:SI 0 "register_operand" "d,e,d")
+ (match_operand:SI 1 "arith_operand" "L,e,d")))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "@
+ cmpi.c %0, %c1
+ cmp! %0, %1
+ cmp.c %0, %1"
+ [(set_attr "type" "cmp")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "cmpsi_nz_score3"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (match_operand:SI 0 "score_register_operand" "d,d,d")
+ (match_operand:SI 1 "arith_operand" "O,L,d")))]
+ "(TARGET_SCORE3)"
+ "@
+ cmpi!\t%0, %c1
+ cmpi.c\t%0, %c1
+ cmp!\t %0, %1"
+ [(set_attr "type" "cmp")
+ (set_attr "length" "2,4,2")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "cmpsi_n_score7"
+ [(set (reg:CC_N CC_REGNUM)
+ (compare:CC_N (match_operand:SI 0 "register_operand" "d,e,d")
+ (match_operand:SI 1 "arith_operand" "L,e,d")))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "@
+ cmpi.c %0, %c1
+ cmp! %0, %1
+ cmp.c %0, %1"
+ [(set_attr "type" "cmp")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "cmpsi_n_score3"
+ [(set (reg:CC_N CC_REGNUM)
+ (compare:CC_N (match_operand:SI 0 "score_register_operand" "d,d,d")
+ (match_operand:SI 1 "arith_operand" "O,L,d")))]
+ "(TARGET_SCORE3)"
+ "@
+ cmpi!\t%0, %c1
+ cmpi.c\t%0, %c1
+ cmp!\t%0, %1"
+ [(set_attr "type" "cmp")
+ (set_attr "length" "2,4,2")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*cmpsi_to_addsi_score7"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (match_operand:SI 1 "register_operand" "0,d")
+ (neg:SI (match_operand:SI 2 "register_operand" "e,d"))))
+ (clobber (match_scratch:SI 0 "=e,d"))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "@
+ add! %0, %2
+ add.c %0, %1, %2"
+ [(set_attr "type" "cmp")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*cmpsi_to_addsi_score3"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (match_operand:SI 1 "score_register_operand" "d")
+ (neg:SI (match_operand:SI 2 "score_register_operand" "d"))))
+ (clobber (match_scratch:SI 0 "=d"))]
+ "(TARGET_SCORE3)"
+ "add.c\t%0, %1, %2"
+ [(set_attr "type" "cmp")
+ (set_attr "length" "4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "cmpsi_cc_score7"
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC (match_operand:SI 0 "register_operand" "d,e,d")
+ (match_operand:SI 1 "arith_operand" "L,e,d")))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "@
+ cmpi.c %0, %c1
+ cmp! %0, %1
+ cmp.c %0, %1"
+ [(set_attr "type" "cmp")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "cmpsi_cc_score3"
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC (match_operand:SI 0 "score_register_operand" "d,d,d")
+ (match_operand:SI 1 "arith_operand" "O,L,d")))]
+ "(TARGET_SCORE3)"
+ "@
+ cmpi!\t%0, %c1
+ cmpi.c\t%0, %c1
+ cmp!\t%0, %1"
+ [(set_attr "type" "cmp")
+ (set_attr "length" "2,4,2")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "*branch_n_score7"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "branch_n_operator"
+ [(reg:CC_N CC_REGNUM)
+ (const_int 0)])
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "b%C0 %1"
+ [(set_attr "type" "branch")])
+
+(define_insn "*branch_n_score3"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "branch_n_operator"
+ [(reg:CC_N CC_REGNUM)
+ (const_int 0)])
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ "(TARGET_SCORE3)"
+ "b%C0\t%1"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
+(define_insn "*branch_nz_score7"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "branch_nz_operator"
+ [(reg:CC_NZ CC_REGNUM)
+ (const_int 0)])
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "b%C0 %1"
+ [(set_attr "type" "branch")])
+
+(define_insn "*branch_nz_score3"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "branch_nz_operator"
+ [(reg:CC_NZ CC_REGNUM)
+ (const_int 0)])
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ "(TARGET_SCORE3)"
+ "b%C0\t%1"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
+
+(define_insn "*branch_cc_score7"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "comparison_operator"
+ [(reg:CC CC_REGNUM)
+ (const_int 0)])
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "b%C0 %1"
+ [(set_attr "type" "branch")])
+
+(define_insn "*branch_cc_score3"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "comparison_operator"
+ [(reg:CC CC_REGNUM)
+ (const_int 0)])
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ "(TARGET_SCORE3)"
+ "b%C0\t%1"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
+(define_insn "jump"
+ [(set (pc)
+ (label_ref (match_operand 0 "" "")))]
+ ""
+{
+ if (!flag_pic)
+ return \"j\t%0\";
+ else
+ return \"b\t%0\";
+}
+ [(set_attr "type" "jump")
+ (set_attr "length" "4")])
+
+(define_expand "sibcall"
+ [(parallel [(call (match_operand 0 "" "")
+ (match_operand 1 "" ""))
+ (use (match_operand 2 "" ""))])]
+ ""
+{
+ score_call (operands, true);
+ DONE;
+})
+
+(define_insn "sibcall_internal_score7"
+ [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "t,Z"))
+ (match_operand 1 "" ""))
+ (clobber (reg:SI RT_REGNUM))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ && SIBLING_CALL_P (insn)"
+{
+ if (!flag_pic)
+ switch (which_alternative)
+ {
+ case 0: return \"br%S0\t%0\";
+ case 1: return \"j\t%0\";
+ default: gcc_unreachable ();
+ }
+ else
+ switch (which_alternative)
+ {
+ case 0: return \"mv\tr29, %0\;br\tr29\";
+ case 1: return \"la\tr29, %0\;br\tr29\";
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "call")])
+
+(define_insn "sibcall_internal_score3"
+ [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "t,Z"))
+ (match_operand 1 "" ""))
+ (clobber (reg:SI RT_REGNUM))]
+ "(TARGET_SCORE3) && (SIBLING_CALL_P (insn))"
+{
+ if (!flag_pic)
+ switch (which_alternative)
+ {
+ case 0: return \"br%S0\t%0\";
+ case 1: return \"j\t%0\";
+ default: gcc_unreachable ();
+ }
+ else
+ switch (which_alternative)
+ {
+ case 0: return \"mv!\tr29, %0\;br!\tr29\";
+ case 1: return \"ldi48\tr29, %0\;br!\tr29\";
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "call")
+ (set_attr "length" "4,8")])
+
+(define_expand "sibcall_value"
+ [(parallel [(set (match_operand 0 "" "")
+ (call (match_operand 1 "" "") (match_operand 2 "" "")))
+ (use (match_operand 3 "" ""))])]
+ ""
+{
+ score_call_value (operands, true);
+ DONE;
+})
+
+(define_insn "sibcall_value_internal_score7"
+ [(set (match_operand 0 "register_operand" "=d,d")
+ (call (mem:SI (match_operand:SI 1 "call_insn_operand" "t,Z"))
+ (match_operand 2 "" "")))
+ (clobber (reg:SI RT_REGNUM))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ && SIBLING_CALL_P (insn)"
+{
+ if (!flag_pic)
+ switch (which_alternative)
+ {
+ case 0: return \"br%S1\t%1\";
+ case 1: return \"j\t%1\";
+ default: gcc_unreachable ();
+ }
+ else
+ switch (which_alternative)
+ {
+ case 0: return \"mv\tr29, %1\;br\tr29\";
+ case 1: return \"la\tr29, %1\;br\tr29\";
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "call")])
+
+(define_insn "sibcall_value_internal_score3"
+ [(set (match_operand 0 "score_register_operand" "=d,d")
+ (call (mem:SI (match_operand:SI 1 "call_insn_operand" "t,Z"))
+ (match_operand 2 "" "")))
+ (clobber (reg:SI RT_REGNUM))]
+ "(TARGET_SCORE3) && (SIBLING_CALL_P (insn))"
+{
+ if (!flag_pic)
+ switch (which_alternative)
+ {
+ case 0: return \"br%S1\t%1\";
+ case 1: return \"j\t%1\";
+ default: gcc_unreachable ();
+ }
+ else
+ switch (which_alternative)
+ {
+ case 0: return \"mv!\tr29, %1\;br!\tr29\";
+ case 1: return \"ldi48\tr29, %1\;br!\tr29\";
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "length" "4,8")
+ (set_attr "type" "call")])
+
+(define_expand "call"
+ [(parallel [(call (match_operand 0 "" "") (match_operand 1 "" ""))
+ (use (match_operand 2 "" ""))])]
+ ""
+{
+ score_call (operands, false);
+ DONE;
+})
+
+(define_insn "call_internal_score7"
+ [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "d,Z"))
+ (match_operand 1 "" ""))
+ (clobber (reg:SI RA_REGNUM))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ if (!flag_pic)
+ switch (which_alternative)
+ {
+ case 0: return \"brl%S0\t%0\";
+ case 1: return \"jl\t%0\";
+ default: gcc_unreachable ();
+ }
+ else
+ switch (which_alternative)
+ {
+ case 0: return \"mv\tr29, %0\;brl\tr29\";
+ case 1: return \"la\tr29, %0\;brl\tr29\";
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "call")])
+
+(define_insn "call_internal_score3"
+ [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "d,Z"))
+ (match_operand 1 "" ""))
+ (clobber (reg:SI RA_REGNUM))]
+ "(TARGET_SCORE3)"
+{
+ if (!flag_pic)
+ switch (which_alternative)
+ {
+ case 0: return \"brl!\t%0\";
+ case 1: return \"jl\t%0\";
+ default: gcc_unreachable ();
+ }
+ else
+ switch (which_alternative)
+ {
+ case 0: return \"mv!\tr29, %0\;brl!\tr29\";
+ case 1: return \"ldi48\tr29, %0\;brl!\tr29\";
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "length" "4,8")
+ (set_attr "type" "call")])
+
+(define_expand "call_value"
+ [(parallel [(set (match_operand 0 "" "")
+ (call (match_operand 1 "" "") (match_operand 2 "" "")))
+ (use (match_operand 3 "" ""))])]
+ ""
+{
+ score_call_value (operands, false);
+ DONE;
+})
+
+(define_insn "call_value_internal_score7"
+ [(set (match_operand 0 "register_operand" "=d,d")
+ (call (mem:SI (match_operand:SI 1 "call_insn_operand" "d,Z"))
+ (match_operand 2 "" "")))
+ (clobber (reg:SI RA_REGNUM))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ if (!flag_pic)
+ switch (which_alternative)
+ {
+ case 0: return \"brl%S1\t%1\";
+ case 1: return \"jl\t%1\";
+ default: gcc_unreachable ();
+ }
+ else
+ switch (which_alternative)
+ {
+ case 0: return \"mv\tr29, %1\;brl\tr29\";
+ case 1: return \"la\tr29, %1\;brl\tr29\";
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "call")])
+
+(define_insn "call_value_internal_score3"
+ [(set (match_operand 0 "score_register_operand" "=d,d")
+ (call (mem:SI (match_operand:SI 1 "call_insn_operand" "d,Z"))
+ (match_operand 2 "" "")))
+ (clobber (reg:SI RA_REGNUM))]
+ "(TARGET_SCORE3)"
+{
+ if (!flag_pic)
+ switch (which_alternative)
+ {
+ case 0: return \"brl!\t%1\";
+ case 1: return \"jl\t%1\";
+ default: gcc_unreachable ();
+ }
+ else
+ switch (which_alternative)
+ {
+ case 0: return \"mv!\tr29, %1\;brl!\tr29\";
+ case 1: return \"ldi48\tr29, %1\;brl!\tr29\";
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "length" "4,8")
+ (set_attr "type" "call")])
+
+(define_expand "indirect_jump"
+ [(set (pc) (match_operand 0 "score_register_operand" "d"))]
+ ""
+{
+ rtx dest;
+ dest = operands[0];
+ if (GET_CODE (dest) != REG
+ || GET_MODE (dest) != Pmode)
+ operands[0] = copy_to_mode_reg (Pmode, dest);
+
+ emit_jump_insn (gen_indirect_jump_internal_score (operands[0]));
+ DONE;
+})
+
+(define_insn "indirect_jump_internal_score"
+ [(set (pc) (match_operand:SI 0 "score_register_operand" "d"))]
+ ""
+ "br%S0 %0"
+ [(set_attr "type" "jump")])
+
+(define_expand "casesi"
+ [(match_operand:SI 0 "score_register_operand" "") ; index to jump on
+ (match_operand:SI 1 "const_int_operand" "") ; lower bound
+ (match_operand:SI 2 "const_int_operand" "") ; total range
+ (match_operand:SI 3 "" "") ; table label
+ (match_operand:SI 4 "" "")] ; Out of range label
+ "TARGET_SCORE3"
+{
+ rtx reg;
+ if (operands[1] != const0_rtx)
+ {
+ reg = gen_reg_rtx (SImode);
+ emit_insn (gen_addsi3 (reg, operands[0],
+ GEN_INT (-INTVAL (operands[1]))));
+ operands[0] = reg;
+ }
+
+ if (!CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'L'))
+ operands[2] = force_reg (SImode, operands[2]);
+
+ reg = gen_reg_rtx (SImode);
+ emit_jump_insn (gen_score3_casesi_internal (operands[0], operands[2],
+ operands[3], operands[4], reg));
+ DONE;
+})
+
+(define_insn "score3_casesi_internal"
+ [(parallel [(set (pc)
+ (if_then_else
+ (leu (match_operand:SI 0 "score_register_operand" "e")
+ (match_operand:SI 1 "arith_operand" "dL"))
+ (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
+ (label_ref (match_operand 2 "" ""))))
+ (label_ref (match_operand 3 "" ""))))
+ (clobber (reg:CC CC_REGNUM))
+ (clobber (match_operand:SI 4 "score_register_operand" "=e"))
+ (use (label_ref (match_dup 2)))])]
+ "TARGET_SCORE3 && !flag_pic"
+ "*
+ return score_output_casesi(operands);
+ "
+ [(set_attr "length" "20")])
+
+(define_expand "tablejump"
+ [(set (pc)
+ (match_operand 0 "score_register_operand" "d"))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+{
+ if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ emit_jump_insn (gen_tablejump_internal_score7 (operands[0], operands[1]));
+ else if (TARGET_SCORE3)
+ emit_jump_insn (gen_tablejump_internal_score3 (operands[0], operands[1]));
+
+ DONE;
+})
+
+(define_insn "tablejump_internal_score7"
+ [(set (pc)
+ (match_operand:SI 0 "register_operand" "d"))
+ (use (label_ref (match_operand 1 "" "")))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+{
+ if (flag_pic)
+ return \"mv\tr29, %0\;.cpadd\tr29\;br\tr29\";
+ else
+ return \"br%S0\t%0\";
+}
+ [(set_attr "type" "jump")])
+
+(define_insn "tablejump_internal_score3"
+ [(set (pc)
+ (match_operand:SI 0 "score_register_operand" "d"))
+ (use (label_ref (match_operand 1 "" "")))]
+ "(TARGET_SCORE3)"
+{
+ if (flag_pic)
+ return \"mv!\tr29, %0\;.cpadd\tr29\;br!\tr29\";
+ else
+ return \"br%S0\t%0\";
+}
+ [(set_attr "type" "jump")
+ (set_attr "length" "8")])
+
+(define_expand "prologue"
+ [(const_int 1)]
+ ""
+{
+ score_prologue ();
+ DONE;
+})
+
+(define_expand "epilogue"
+ [(const_int 2)]
+ ""
+{
+ score_epilogue (false);
+ DONE;
+})
+
+(define_expand "sibcall_epilogue"
+ [(const_int 2)]
+ ""
+{
+ score_epilogue (true);
+ DONE;
+})
+
+(define_insn "return_internal_score7"
+ [(return)
+ (use (match_operand 0 "pmode_register_operand" "d"))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "br%S0\t%0")
+
+(define_insn "return_internal_score3"
+ [(return)
+ (use (match_operand 0 "pmode_register_operand" "d"))]
+ "(TARGET_SCORE3)"
+ "br%S0\t%0"
+ [(set_attr "length" "4")])
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "#nop!"
+)
+
+(define_insn "cpload_score7"
+ [(unspec_volatile:SI [(const_int 1)] CPLOAD)]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ && flag_pic"
+ ".cpload\tr29"
+)
+
+(define_insn "cpload_score3"
+ [(unspec_volatile:SI [(const_int 1)] CPLOAD)]
+ "(TARGET_SCORE3) && flag_pic"
+ ".cpload\tr29"
+ [(set_attr "length" "4")])
+
+(define_insn "cprestore_use_fp_score7"
+ [(unspec_volatile:SI [(match_operand:SI 0 "" "")] CPRESTORE)
+ (use (reg:SI FP_REGNUM))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ && flag_pic"
+ ".cprestore\tr2, %0"
+)
+
+(define_insn "cprestore_use_fp_score3"
+ [(unspec_volatile:SI [(match_operand:SI 0 "" "")] CPRESTORE)
+ (use (reg:SI FP_REGNUM))]
+ "(TARGET_SCORE3) && flag_pic"
+ ".cprestore\tr2, %0"
+ [(set_attr "length" "4")])
+
+(define_insn "cprestore_use_sp_score7"
+ [(unspec_volatile:SI [(match_operand:SI 0 "" "")] CPRESTORE)
+ (use (reg:SI SP_REGNUM))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
+ && flag_pic"
+ ".cprestore\tr0, %0"
+)
+
+(define_insn "cprestore_use_sp_score3"
+ [(unspec_volatile:SI [(match_operand:SI 0 "" "")] CPRESTORE)
+ (use (reg:SI SP_REGNUM))]
+ "(TARGET_SCORE3) && flag_pic"
+ ".cprestore\tr0, %0"
+ [(set_attr "length" "4")])
+
+(define_expand "doloop_end"
+ [(use (match_operand 0 "" "")) ; loop pseudo
+ (use (match_operand 1 "" "")) ; iterations; zero if unknown
+ (use (match_operand 2 "" "")) ; max iterations
+ (use (match_operand 3 "" "")) ; loop level
+ (use (match_operand 4 "" ""))] ; label
+ "!TARGET_NHWLOOP"
+{
+ if (INTVAL (operands[3]) > 1)
+ FAIL;
+
+ if (GET_MODE (operands[0]) == SImode)
+ {
+ rtx sr0 = gen_rtx_REG (SImode, CN_REGNUM);
+ emit_jump_insn (gen_doloop_end_si (sr0, operands[4]));
+ }
+ else
+ FAIL;
+
+ DONE;
+})
+
+(define_insn "doloop_end_si"
+ [(set (pc)
+ (if_then_else
+ (ne (match_operand:SI 0 "sr0_operand" "")
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int -1)))
+ (clobber (reg:CC CC_REGNUM))]
+ "!TARGET_NHWLOOP"
+ "bcnz %1"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
+(define_insn "pushsi_score7"
+ [(set (match_operand:SI 0 "push_operand" "=<")
+ (match_operand:SI 1 "register_operand" "d"))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "push!\t%1, [r0]"
+ [(set_attr "type" "store")
+ (set_attr "mode" "SI")])
+
+(define_insn "pushsi_score3"
+ [(set (match_operand:SI 0 "push_operand" "=<")
+ (match_operand:SI 1 "register_operand" "d"))]
+ "(TARGET_SCORE3)"
+ "push!\t%1"
+ [(set_attr "type" "store")
+ (set_attr "length" "2")
+ (set_attr "mode" "SI")])
+
+(define_insn "popsi_score7"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (match_operand:SI 1 "pop_operand" ">"))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "pop!\t%0, [r0]"
+ [(set_attr "type" "store")
+ (set_attr "mode" "SI")])
+
+(define_insn "popsi_score3"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (match_operand:SI 1 "pop_operand" ">"))]
+ "(TARGET_SCORE3)"
+ "pop!\t%0"
+ [(set_attr "type" "store")
+ (set_attr "length" "2")
+ (set_attr "mode" "SI")])
+
+(define_expand "load_multiple"
+ [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
+ (match_operand:SI 1 "" ""))
+ (use (match_operand:SI 2 "" ""))
+ (clobber (reg:SI 0))])]
+ "(TARGET_SCORE3)"
+{
+ int regno, count, i;
+
+ if (GET_CODE (operands[2]) != CONST_INT
+ || INTVAL (operands[2]) < 2
+ || GET_CODE (operands[1]) != MEM
+ || XEXP (operands[1], 0) != stack_pointer_rtx
+ || GET_CODE (operands[0]) != REG)
+ FAIL;
+
+ count = INTVAL (operands[2]);
+ regno = REGNO (operands[0]);
+
+ operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
+
+ for (i = 0; i < count; i++)
+ XVECEXP (operands[3], 0, i)
+ = gen_rtx_SET (VOIDmode,
+ gen_rtx_REG (SImode, regno + i),
+ gen_rtx_MEM (SImode, gen_rtx_POST_INC (SImode, stack_pointer_rtx)));
+})
+
+(define_insn ""
+ [(match_parallel 0 "score_load_multiple_operation"
+ [(set (match_operand:SI 1 "register_operand" "=d")
+ (mem:SI (post_inc:SI (reg:SI SP_REGNUM))))])]
+ "(TARGET_SCORE3)"
+{
+ return score_rpop (operands);
+}
+ [(set_attr "length" "2")])
+
+(define_expand "store_multiple"
+ [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
+ (match_operand:SI 1 "" ""))
+ (use (match_operand:SI 2 "" ""))
+ (clobber (reg:SI 0))])]
+ "(TARGET_SCORE3)"
+{
+ int regno, count, i;
+
+ if (GET_CODE (operands[2]) != CONST_INT
+ || INTVAL (operands[2]) < 2
+ || GET_CODE (operands[0]) != MEM
+ || XEXP (operands[0], 0) != stack_pointer_rtx
+ || GET_CODE (operands[1]) != REG)
+ FAIL;
+
+ count = INTVAL (operands[2]);
+ regno = REGNO (operands[1]);
+
+ operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
+
+ for (i = 0; i < count; i++)
+ XVECEXP (operands[3], 0, i)
+ = gen_rtx_SET (VOIDmode,
+ gen_rtx_MEM (SImode, gen_rtx_PRE_DEC (SImode, stack_pointer_rtx)),
+ gen_rtx_REG (SImode, regno + i));
+})
+
+(define_insn ""
+ [(match_parallel 0 "score_store_multiple_operation"
+ [(set (mem:SI (pre_dec:SI (reg:SI SP_REGNUM)))
+ (match_operand:SI 1 "register_operand" "d"))])]
+ "(TARGET_SCORE3)"
+{
+ return score_rpush (operands);
+}
+ [(set_attr "length" "2")])
+
+(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\t%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" "")))]
+ ""
+{
+ score_movsicc (operands);
+})
+
+(define_insn "movsicc_internal_score7"
+ [(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 "arith_operand" "d")
+ (match_operand:SI 3 "arith_operand" "0")))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "mv%C1\t%0, %2"
+ [(set_attr "type" "cndmv")
+ (set_attr "mode" "SI")])
+
+(define_insn "movsicc_internal_score3"
+ [(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 "arith_operand" "d")
+ (match_operand:SI 3 "arith_operand" "0")))]
+ "(TARGET_SCORE3)"
+ "mv%G1\t%0, %2"
+ [(set_attr "type" "cndmv")
+ (set_attr "length" "4")
+ (set_attr "mode" "SI")])
+
+(define_insn "zero_extract_bittst_score7"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (unspec:SI
+ [(match_operand:SI 0 "register_operand" "*e,d")
+ (match_operand:SI 1 "const_uimm5" "")]
+ BITTST)
+ (const_int 0)))]
+ "(TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)"
+ "@
+ bittst!\t%0, %c1
+ bittst.c\t%0, %c1"
+ [(set_attr "type" "arith")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_insn "zero_extract_bittst_score3"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ (unspec:SI
+ [(match_operand:SI 0 "register_operand" "e,d")
+ (match_operand:SI 1 "const_uimm5" "")]
+ BITTST)
+ (const_int 0)))]
+ "(TARGET_SCORE3)"
+ "@
+ bittst!\t%0, %c1
+ bittst.c\t%0, %c1"
+ [(set_attr "type" "arith")
+ (set_attr "length" "2,4")
+ (set_attr "up_c" "yes")
+ (set_attr "mode" "SI")])
+
+(define_expand "extzv"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (zero_extract (match_operand:SI 1 "memory_operand" "")
+ (match_operand:SI 2 "immediate_operand" "")
+ (match_operand:SI 3 "immediate_operand" "")))]
+ "((TARGET_SCORE5 || TARGET_SCORE7 || TARGET_SCORE7D)
+ && (!TARGET_LITTLE_ENDIAN) && (TARGET_ULS))
+ || (TARGET_SCORE3 && TARGET_ULS)"
+{
+ if (score_unaligned_load (operands))
+ DONE;
+ else
+ FAIL;
+})
+
+(define_expand "insv"
+ [(set (zero_extract (match_operand:SI 0 "memory_operand" "")
+ (match_operand:SI 1 "immediate_operand" "")
+ (match_operand:SI 2 "immediate_operand" ""))
+ (match_operand:SI 3 "register_operand" ""))]
+ "((TARGET_SCORE5 || TARGET_SCORE7 || TARGET_SCORE7D)
+ && (!TARGET_LITTLE_ENDIAN) && (TARGET_ULS))
+ || (TARGET_SCORE3 && TARGET_ULS)"
+{
+ if (score_unaligned_store (operands))
+ DONE;
+ else
+ FAIL;
+})
+
+(define_expand "extv"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (sign_extract (match_operand:SI 1 "memory_operand" "")
+ (match_operand:SI 2 "immediate_operand" "")
+ (match_operand:SI 3 "immediate_operand" "")))]
+ "((TARGET_SCORE5 || TARGET_SCORE7 || TARGET_SCORE7D)
+ && (!TARGET_LITTLE_ENDIAN) && (TARGET_ULS))
+ || (TARGET_SCORE3 && TARGET_ULS)"
+{
+ if (score_unaligned_load (operands))
+ DONE;
+ else
+ FAIL;
+})
+
+(define_expand "movmemsi"
+ [(parallel [(set (match_operand:BLK 0 "general_operand")
+ (match_operand:BLK 1 "general_operand"))
+ (use (match_operand:SI 2 ""))
+ (use (match_operand:SI 3 "const_int_operand"))])]
+ "((TARGET_SCORE5 || TARGET_SCORE7 || TARGET_SCORE7D)
+ && (TARGET_ULS))
+ || (TARGET_SCORE3 && TARGET_ULS)"
+{
+ if (score_block_move (operands))
+ DONE;
+ else
+ FAIL;
+})
+
+(define_insn "move_lbu_a"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "const_simm12" "")))
+ (set (match_operand:QI 3 "register_operand" "=d")
+ (mem:QI (match_dup 1)))]
+ ""
+ "lbu\t%3, [%1]+, %2"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")
+ (set_attr "mode" "QI")])
+
+(define_insn "move_lhu_a"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "const_simm12" "")))
+ (set (match_operand:HI 3 "register_operand" "=d")
+ (mem:HI (match_dup 1)))]
+ ""
+ "lhu\t%3, [%1]+, %2"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")
+ (set_attr "mode" "HI")])
+
+(define_insn "move_lw_a"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "const_simm12" "")))
+ (set (match_operand:SI 3 "register_operand" "=d")
+ (mem:SI (match_dup 1)))]
+ ""
+ "lw\t%3, [%1]+, %2"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")
+ (set_attr "mode" "SI")])
+
+(define_insn "move_sb_a"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "const_simm12" "")))
+ (set (mem:QI (match_dup 1))
+ (match_operand:QI 3 "register_operand" "d"))]
+ ""
+ "sb\t%3, [%1]+, %2"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")
+ (set_attr "mode" "QI")])
+
+(define_insn "move_sh_a"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "const_simm12" "")))
+ (set (mem:HI (match_dup 1))
+ (match_operand:HI 3 "register_operand" "d"))]
+ ""
+ "sh\t%3, [%1]+, %2"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")
+ (set_attr "mode" "HI")])
+
+(define_insn "move_sw_a"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "const_simm12" "")))
+ (set (mem:SI (match_dup 1))
+ (match_operand:SI 3 "register_operand" "d"))]
+ ""
+ "sw\t%3, [%1]+, %2"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")
+ (set_attr "mode" "SI")])
+
+(define_insn "move_lbu_b"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "const_simm12" "")))
+ (set (match_operand:QI 3 "register_operand" "=d")
+ (mem:QI (plus:SI (match_dup 1)
+ (match_dup 2))))]
+ ""
+ "lbu\t%3, [%1, %2]+"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")
+ (set_attr "mode" "QI")])
+
+(define_insn "move_lhu_b"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "const_simm12" "")))
+ (set (match_operand:HI 3 "register_operand" "=d")
+ (mem:HI (plus:SI (match_dup 1)
+ (match_dup 2))))]
+ ""
+ "lhu\t%3, [%1, %2]+"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")
+ (set_attr "mode" "HI")])
+
+(define_insn "move_lw_b"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "const_simm12" "")))
+ (set (match_operand:SI 3 "register_operand" "=d")
+ (mem:SI (plus:SI (match_dup 1)
+ (match_dup 2))))]
+ ""
+ "lw\t%3, [%1, %2]+"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")
+ (set_attr "mode" "SI")])
+
+(define_insn "move_sb_b"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "const_simm12" "")))
+ (set (mem:QI (plus:SI (match_dup 1)
+ (match_dup 2)))
+ (match_operand:QI 3 "register_operand" "d"))]
+ ""
+ "sb\t%3, [%1, %2]+"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")
+ (set_attr "mode" "QI")])
+
+(define_insn "move_sh_b"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "const_simm12" "")))
+ (set (mem:HI (plus:SI (match_dup 1)
+ (match_dup 2)))
+ (match_operand:HI 3 "register_operand" "d"))]
+ ""
+ "sh\t%3, [%1, %2]+"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")
+ (set_attr "mode" "HI")])
+
+(define_insn "move_sw_b"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "const_simm12" "")))
+ (set (mem:SI (plus:SI (match_dup 1)
+ (match_dup 2)))
+ (match_operand:SI 3 "register_operand" "d"))]
+ ""
+ "sw\t%3, [%1, %2]+"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")
+ (set_attr "mode" "SI")])
+
+(define_insn "move_lcb"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "register_operand" "0")
+ (const_int 4)))
+ (set (reg:SI LC_REGNUM)
+ (unspec:SI [(mem:BLK (match_dup 1))] LCB))]
+ "((TARGET_SCORE5 || TARGET_SCORE7 || TARGET_SCORE7D)
+ && (!TARGET_LITTLE_ENDIAN) && (TARGET_ULS))
+ || (TARGET_SCORE3 && TARGET_ULS)"
+ "lcb\t[%1]+"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")
+ (set_attr "mode" "SI")])
+
+(define_insn "move_lcw"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "register_operand" "0")
+ (const_int 4)))
+ (set (match_operand:SI 2 "register_operand" "=d")
+ (unspec:SI [(mem:BLK (match_dup 1))
+ (reg:SI LC_REGNUM)] LCW))
+ (set (reg:SI LC_REGNUM)
+ (unspec:SI [(mem:BLK (match_dup 1))] LCB))]
+ "((TARGET_SCORE5 || TARGET_SCORE7 || TARGET_SCORE7D)
+ && (!TARGET_LITTLE_ENDIAN) && (TARGET_ULS))
+ || (TARGET_SCORE3 && TARGET_ULS)"
+ "lcw\t%2, [%1]+"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")
+ (set_attr "mode" "SI")])
+
+(define_insn "move_lce"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "register_operand" "0")
+ (const_int 4)))
+ (set (match_operand:SI 2 "register_operand" "=d")
+ (unspec:SI [(mem:BLK (match_dup 1))
+ (reg:SI LC_REGNUM)] LCE))]
+ "((TARGET_SCORE5 || TARGET_SCORE7 || TARGET_SCORE7D)
+ && (!TARGET_LITTLE_ENDIAN) && (TARGET_ULS))
+ || (TARGET_SCORE3 && TARGET_ULS)"
+ "lce\t%2, [%1]+"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")
+ (set_attr "mode" "SI")])
+
+(define_insn "move_scb"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "register_operand" "0")
+ (const_int 4)))
+ (set (mem:BLK (match_dup 1))
+ (unspec:BLK [(match_operand:SI 2 "register_operand" "d")] SCB))
+ (set (reg:SI SC_REGNUM)
+ (unspec:SI [(match_dup 2)] SCLC))]
+ "((TARGET_SCORE5 || TARGET_SCORE7 || TARGET_SCORE7D)
+ && (!TARGET_LITTLE_ENDIAN) && (TARGET_ULS))
+ || (TARGET_SCORE3 && TARGET_ULS)"
+ "scb\t%2, [%1]+"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")
+ (set_attr "mode" "SI")])
+
+(define_insn "move_scw"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "register_operand" "0")
+ (const_int 4)))
+ (set (mem:BLK (match_dup 1))
+ (unspec:BLK [(match_operand:SI 2 "register_operand" "d")
+ (reg:SI SC_REGNUM)] SCW))
+ (set (reg:SI SC_REGNUM)
+ (unspec:SI [(match_dup 2)] SCLC))]
+ "((TARGET_SCORE5 || TARGET_SCORE7 || TARGET_SCORE7D)
+ && (!TARGET_LITTLE_ENDIAN) && (TARGET_ULS))
+ || (TARGET_SCORE3 && TARGET_ULS)"
+ "scw\t%2, [%1]+"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")
+ (set_attr "mode" "SI")])
+
+(define_insn "move_sce"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "register_operand" "0")
+ (const_int 4)))
+ (set (mem:BLK (match_dup 1))
+ (unspec:BLK [(reg:SI SC_REGNUM)] SCE))]
+ "((TARGET_SCORE5 || TARGET_SCORE7 || TARGET_SCORE7D)
+ && (!TARGET_LITTLE_ENDIAN) && (TARGET_ULS))
+ || (TARGET_SCORE3 && TARGET_ULS)"
+ "sce [%1]+"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")
+ (set_attr "mode" "SI")])
+
+(define_insn "andsi3_extzh"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (and:SI (match_operand:SI 1 "register_operand" "d")
+ (const_int 65535)))]
+ ""
+ "extzh\t%0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "length" "4")
+ (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_SCORE7D || TARGET_SCORE3)"
+ "clz\t%0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(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_SCORE7D || TARGET_SCORE3D)"
+ "max\t%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_SCORE7D || TARGET_SCORE3D)"
+ "min\t%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_SCORE7D || TARGET_SCORE3D)"
+ "abs\t%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_SCORE7D || TARGET_SCORE3D)"
+ "bitrev\t%0, %1, r0\;clz\t%0, %0\;addi\t%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_SCORE7D || TARGET_SCORE3D)"
+{
+ 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))));
+ if (TARGET_SCORE7D)
+ emit_insn (gen_movsicc_internal_score7 (operands[0],
+ gen_rtx_fmt_ee (EQ, VOIDmode, operands[0], GEN_INT (33)),
+ GEN_INT (0),
+ operands[0]));
+ else
+ emit_insn (gen_movsicc_internal_score3 (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_SCORE7D || TARGET_SCORE3D)"
+ [(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_SCORE7D || TARGET_SCORE3D)"
+ [(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_SCORE7D || TARGET_SCORE3D)"
+ "mtcehl\t%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_SCORE7D || TARGET_SCORE3D)"
+ "@
+ mad\t%2, %3
+ mtcel%S1\t%1\;mad\t%2, %3
+ mad\t%2, %3\;mfcel%S0\t%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_SCORE7D || TARGET_SCORE3D)"
+ "@
+ msb\t%2, %3
+ mtcel%S1\t%1\;msb\t%2, %3
+ msb\t%2, %3\;mfcel%S0\t%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_SCORE7D || TARGET_SCORE3D)"
+ "mad\t%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_SCORE7D || TARGET_SCORE3D)"
+ "madu\t%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_SCORE7D || TARGET_SCORE3D)"
+ "msb\t%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_SCORE7D || TARGET_SCORE3D)"
+ "msbu\t%2, %3"
+ [(set_attr "mode" "DI")])
+
Index: score.opt
===================================================================
--- score.opt (nonexistent)
+++ score.opt (revision 384)
@@ -0,0 +1,63 @@
+; Options for the Sunnorth port of the compiler.
+
+; Copyright (C) 2005, 2007 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 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
+; .
+
+meb
+Target RejectNegative Report InverseMask(LITTLE_ENDIAN)
+Generate big-endian code
+
+mel
+Target RejectNegative Report Mask(LITTLE_ENDIAN)
+Generate little-endian code
+
+mnhwloop
+Target RejectNegative Report Mask(NHWLOOP)
+Disable bcnz instruction
+
+muls
+Target RejectNegative Report Mask(ULS)
+Enable unaligned load/store 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
+
+mscore7d
+Target RejectNegative Report Mask(SCORE7D)
+Support SCORE 7D ISA
+
+mscore3
+Target RejectNegative Report Mask(SCORE3)
+Support SCORE 3 ISA
+
+mscore3d
+Target RejectNegative Report Mask(SCORE3D)
+Support SCORE 3d ISA
+
+march=
+Target RejectNegative Joined
+Specify the name of the target architecture
Index: score-modes.def
===================================================================
--- score-modes.def (nonexistent)
+++ score-modes.def (revision 384)
@@ -0,0 +1,24 @@
+/* score-modes.def for Sunplus S+CORE processor
+ Copyright (C) 2005, 2007 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 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
+ . */
+
+/* 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_N);
+CC_MODE (CC_NZ);
Index: mul-div.S
===================================================================
--- mul-div.S (nonexistent)
+++ mul-div.S (revision 384)
@@ -0,0 +1,412 @@
+/* Copyright (C) 2005, 2007 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 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
+ . */
+
+#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
+
+#ifndef __pic__
+#if !defined(L_mulsi3) && !defined(L_divsi3)
+ .text
+ .global _flush_cache
+#ifdef __score3__
+_flush_cache:
+ br r3
+#else
+_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
+#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 */
+#else /* -fPIC */
+#if !defined(L_mulsi3) && !defined(L_divsi3)
+ .set pic
+ .text
+ .global _flush_cache
+#ifdef __score3__
+_flush_cache:
+ br r3
+#else
+_flush_cache:
+ addi r0, -8 # pic used
+ .cpload r29 # pic used
+ srli r9, r5, 4
+ mv r8, r4
+ mtsr r9, sr0
+1:
+ cache 0xe, [r8, 0] # write back invalid dcache
+ addi r8, 16
+ bcnz 1b
+ mfcr r8, cr4
+ bittst! r8, 0x3 # if LDM is enable, write back LDM
+ beq! 6f
+ ldi r10, 0
+ cache 0xc, [r10, 0]
+6:
+ bittst! r8, 0x2 # if LIM is enable, refill it
+ beq! 7f
+ cache 0x4, [r10, 0]
+7:
+ #nop!
+ #nop!
+ #nop!
+ #nop!
+ #nop!
+ mv r8, r4
+ mtsr r9, sr0
+2:
+ cache 0x2, [r8, 0] # invalid unlock icache
+ #nop!
+ #nop!
+ #nop!
+ #nop!
+ #nop!
+ addi r8, 16
+ bcnz 2b
+ .cprestore r0, 12 # pic used
+ addi r0, 8 # pic used
+ br r3
+#endif
+#endif
+
+/* FUNCTION
+ (U) INT32 v0 = __mulsi3 ((U) INT32 a0, (U) INT32 a1);
+ REGISTERS:
+ use t0
+ modify a0
+ a1 -> become 0
+ NOTE:
+ this seems to give better performance to just rotate and add. */
+
+#ifdef L_mulsi3
+ .set pic
+ .text
+ .global __umulsi3
+ .global __mulsi3
+ /* signed multiplication (32x32) */
+ .ent __mulsi3
+__umulsi3:
+__mulsi3:
+ addi r0, -8 # pic used
+ .cpload r29 # pic used
+ li t1, 0
+__mulsi3_loop:
+ andri.c t0, a1, 1 # t0 = multiplier[0]
+ srli a1, a1, 1 # a1 /= 2
+ beq __mulsi3_loop2 # skip if (t0 == 0)
+ add t1, t1, a0 # add multiplicand
+__mulsi3_loop2:
+ slli a0, a0, 1 # multiplicand mul 2
+ cmpi.c a1, 0
+ bne __mulsi3_loop
+ mv r4, t1
+ .cprestore r0, 12 # pic used
+ addi r0, 8 # pic used
+ br ra
+ .end __mulsi3
+#endif /* L_mulsi3 */
+
+/* FUNCTION
+ UINT32 (v0) = __udivsi3 (UINT32 (a0), UINT32 (a1));
+ INT32 (v0) = __divsi3 (INT32 (a0), INT32 (a1));
+ UINT32 (v0) = __umodsi3 (UINT32 (a0), UINT32 (a1));
+ INT32 (v0) = __modsi3 (INT32 (a0), INT32 (a1));
+ DESCRIPTION
+ performs 32-bit division/modulo.
+ REGISTERS
+ used t0 bit-index
+ t1
+ modify a0 becomes remainer */
+#ifdef L_divsi3
+ .set pic
+ .text
+ .global __udivsi3
+ .global __umodsi3
+ .global __divsi3
+ .global __modsi3
+
+ /* unsigned division */
+ .ent __udivsi3
+__udivsi3:
+ addi r0, -8 # pic used
+ .cpload r29 # pic used
+ li t4, 0
+ cmpi.c a1, 0
+ beq __uds_exit
+ li t0, 1
+ blt __uds_ok
+__uds_normalize:
+ cmp.c a0, a1
+ bcc __uds_ok
+ slli a1, a1, 1
+ slli t0, t0, 1
+ cmpi.c a1, 0
+ bge __uds_normalize
+__uds_ok:
+__uds_loop2:
+ cmp.c a0, a1
+ bcc __uds_loop3
+ sub a0, a0, a1
+ or t4, t4, t0
+__uds_loop3:
+ srli t0, t0, 1
+ srli a1, a1, 1
+ cmpi.c t0, 0
+ bne __uds_loop2
+__uds_exit:
+ mv a1, a0
+ mv r4, t4
+ .cprestore r0, 12 # pic used
+ addi r0, 8 # pic used
+ br ra
+ .end __udivsi3
+
+ /* unsigned modulus */
+ .ent __umodsi3
+__umodsi3:
+ addi r0, -8 # pic used
+ .cpload r29 # pic used
+ li t1, 0
+ mv t3, ra
+ la r29, __udivsi3
+ brl r29
+ mv r4, a1
+ .cprestore r0, 12 # pic used
+ addi r0, 8 # pic used
+ br t3
+ .end __umodsi3
+
+ /* abs and div */
+ .ent __orgsi3
+__orgsi3:
+ cmpi.c a0, 0
+ bge __orgsi3_a0p
+ neg a0, a0
+__orgsi3_a0p:
+ cmpi.c a1, 0
+ bge __udivsi3
+ neg a1, a1
+ b __udivsi3 # goto udivsi3
+ .end __orgsi3
+
+ /* signed division */
+ .ent __divsi3
+__divsi3:
+ addi r0, -8 # pic used
+ .cpload r29 # pic used
+ mv t3, ra
+ xor t2, a0, a1
+ la r29, __orgsi3
+ brl r29
+__divsi3_adjust:
+ cmpi.c t2, 0
+ bge __divsi3_exit
+ neg r4, r4
+__divsi3_exit:
+ .cprestore r0, 12 # pic used
+ addi r0, 8 # pic used
+ br t3
+ .end __divsi3
+
+ /* signed modulus */
+ .ent __modsi3
+__modsi3:
+ addi r0, -8 # pic used
+ .cpload r29 # pic used
+ mv t3, ra
+ mv t2, a0
+ la r29, __orgsi3
+ brl r29
+ mv r4, a1
+ b __divsi3_adjust
+ .end __modsi3
+
+#endif /*L_divsi3 */
+#endif
mul-div.S
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property