⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stormy16.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
  emit_call_insn (call);}/* Expanders for multiword computational operations.  *//* Expander for arithmetic operations; emit insns to compute   (set DEST (CODE:MODE SRC0 SRC1))      using CARRY as a temporary.  When CODE is COMPARE, a branch   template is generated (this saves duplicating code in   xstormy16_split_cbranch).  */void xstormy16_expand_arith (mode, code, dest, src0, src1, carry)     enum machine_mode mode;     enum rtx_code code;     rtx dest;     rtx src0;     rtx src1;     rtx carry;{  int num_words = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;  int i;  int firstloop = 1;  if (code == NEG)    {      rtx zero_reg = gen_reg_rtx (word_mode);      emit_move_insn (zero_reg, src0);      src0 = zero_reg;    }    for (i = 0; i < num_words; i++)    {      rtx w_src0, w_src1, w_dest;      rtx insn;            if (code == NEG)	w_src0 = src0;      else	w_src0 = simplify_gen_subreg (word_mode, src0, mode, 				      i * UNITS_PER_WORD);      w_src1 = simplify_gen_subreg (word_mode, src1, mode, i * UNITS_PER_WORD);      w_dest = simplify_gen_subreg (word_mode, dest, mode, i * UNITS_PER_WORD);      switch (code)	{	case PLUS:	  if (firstloop	      && GET_CODE (w_src1) == CONST_INT && INTVAL (w_src1) == 0)	    continue;	  	  if (firstloop)	    insn = gen_addchi4 (w_dest, w_src0, w_src1, carry);	  else	    insn = gen_addchi5 (w_dest, w_src0, w_src1, carry, carry);	  break;	case NEG:	case MINUS:	case COMPARE:	  if (code == COMPARE && i == num_words - 1)	    {	      rtx branch, sub, clobber, sub_1;	      	      sub_1 = gen_rtx_MINUS (HImode, w_src0, 				     gen_rtx_ZERO_EXTEND (HImode, carry));	      sub = gen_rtx_SET (VOIDmode, w_dest,				 gen_rtx_MINUS (HImode, sub_1, w_src1));	      clobber = gen_rtx_CLOBBER (VOIDmode, carry);	      branch = gen_rtx_SET (VOIDmode, pc_rtx,				    gen_rtx_IF_THEN_ELSE (VOIDmode,							  gen_rtx_EQ (HImode,								      sub_1,								      w_src1),							  pc_rtx,							  pc_rtx));	      insn = gen_rtx_PARALLEL (VOIDmode,				       gen_rtvec (3, branch, sub, clobber));	    }	  else if (firstloop		   && code != COMPARE		   && GET_CODE (w_src1) == CONST_INT && INTVAL (w_src1) == 0)	    continue;	  else if (firstloop)	    insn = gen_subchi4 (w_dest, w_src0, w_src1, carry);	  else	    insn = gen_subchi5 (w_dest, w_src0, w_src1, carry, carry);	  break;	case IOR:	case XOR:	case AND:	  if (GET_CODE (w_src1) == CONST_INT 	      && INTVAL (w_src1) == -(code == AND))	    continue;	  	  insn = gen_rtx_SET (VOIDmode, w_dest, gen_rtx (code, mode,							 w_src0, w_src1));	  break;	case NOT:	  insn = gen_rtx_SET (VOIDmode, w_dest, gen_rtx_NOT (mode, w_src0));	  break;	default:	  abort ();	}            firstloop = 0;      emit (insn);    }}/* Return 1 if OP is a shift operator.  */intshift_operator (op, mode)     register rtx op;     enum machine_mode mode ATTRIBUTE_UNUSED;{  enum rtx_code code = GET_CODE (op);  return (code == ASHIFT	  || code == ASHIFTRT	  || code == LSHIFTRT);}/* The shift operations are split at output time for constant values;   variable-width shifts get handed off to a library routine.     Generate an output string to do (set X (CODE:MODE X SIZE_R))   SIZE_R will be a CONST_INT, X will be a hard register.  */const char * xstormy16_output_shift (mode, code, x, size_r, temp)     enum machine_mode mode;     enum rtx_code code;     rtx x;     rtx size_r;     rtx temp;{  HOST_WIDE_INT size;  const char *r0, *r1, *rt;  static char r[64];  if (GET_CODE (size_r) != CONST_INT      || GET_CODE (x) != REG      || mode != SImode)    abort ();  size = INTVAL (size_r) & (GET_MODE_BITSIZE (mode) - 1);  if (size == 0)    return "";  r0 = reg_names [REGNO (x)];  r1 = reg_names [REGNO (x) + 1];  /* For shifts of size 1, we can use the rotate instructions.  */  if (size == 1)    {      switch (code)	{	case ASHIFT:	  sprintf (r, "shl %s,#1 | rlc %s,#1", r0, r1);	  break;	case ASHIFTRT:	  sprintf (r, "asr %s,#1 | rrc %s,#1", r1, r0);	  break;	case LSHIFTRT:	  sprintf (r, "shr %s,#1 | rrc %s,#1", r1, r0);	  break;	default:	  abort ();	}      return r;    }    /* For large shifts, there are easy special cases.  */  if (size == 16)    {      switch (code)	{	case ASHIFT:	  sprintf (r, "mov %s,%s | mov %s,#0", r1, r0, r0);	  break;	case ASHIFTRT:	  sprintf (r, "mov %s,%s | asr %s,#15", r0, r1, r1);	  break;	case LSHIFTRT:	  sprintf (r, "mov %s,%s | mov %s,#0", r0, r1, r1);	  break;	default:	  abort ();	}      return r;    }  if (size > 16)    {      switch (code)	{	case ASHIFT:	  sprintf (r, "mov %s,%s | mov %s,#0 | shl %s,#%d", 		   r1, r0, r0, r1, (int) size - 16);	  break;	case ASHIFTRT:	  sprintf (r, "mov %s,%s | asr %s,#15 | asr %s,#%d", 		   r0, r1, r1, r0, (int) size - 16);	  break;	case LSHIFTRT:	  sprintf (r, "mov %s,%s | mov %s,#0 | shr %s,#%d", 		   r0, r1, r1, r0, (int) size - 16);	  break;	default:	  abort ();	}      return r;    }  /* For the rest, we have to do more work.  In particular, we     need a temporary.  */  rt = reg_names [REGNO (temp)];  switch (code)    {    case ASHIFT:      sprintf (r, 	       "mov %s,%s | shl %s,#%d | shl %s,#%d | shr %s,#%d | or %s,%s", 	       rt, r0, r0, (int) size, r1, (int) size, rt, (int) 16-size,	       r1, rt);      break;    case ASHIFTRT:      sprintf (r, 	       "mov %s,%s | asr %s,#%d | shr %s,#%d | shl %s,#%d | or %s,%s", 	       rt, r1, r1, (int) size, r0, (int) size, rt, (int) 16-size,	       r0, rt);      break;    case LSHIFTRT:      sprintf (r, 	       "mov %s,%s | shr %s,#%d | shr %s,#%d | shl %s,#%d | or %s,%s", 	       rt, r1, r1, (int) size, r0, (int) size, rt, (int) 16-size,	       r0, rt);      break;    default:      abort ();    }  return r;}/* Attribute handling.  *//* Return nonzero if the function is an interrupt function.  */intxstormy16_interrupt_function_p (){  tree attributes;    /* The dwarf2 mechanism asks for INCOMING_FRAME_SP_OFFSET before     any functions are declared, which is demonstrably wrong, but     it is worked around here.  FIXME.  */  if (!cfun)    return 0;  attributes = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));  return lookup_attribute ("interrupt", attributes) != NULL_TREE;}#undef TARGET_ATTRIBUTE_TABLE#define TARGET_ATTRIBUTE_TABLE xstormy16_attribute_tablestatic tree xstormy16_handle_interrupt_attribute PARAMS ((tree *, tree, tree, int, bool *));static const struct attribute_spec xstormy16_attribute_table[] ={  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */  { "interrupt", 0, 0, false, true,  true,  xstormy16_handle_interrupt_attribute },  { NULL,        0, 0, false, false, false, NULL }};/* Handle an "interrupt" attribute;   arguments as in struct attribute_spec.handler.  */static treexstormy16_handle_interrupt_attribute (node, name, args, flags, no_add_attrs)     tree *node;     tree name;     tree args ATTRIBUTE_UNUSED;     int flags ATTRIBUTE_UNUSED;     bool *no_add_attrs;{  if (TREE_CODE (*node) != FUNCTION_TYPE)    {      warning ("`%s' attribute only applies to functions",	       IDENTIFIER_POINTER (name));      *no_add_attrs = true;    }  return NULL_TREE;}#undef TARGET_INIT_BUILTINS#define TARGET_INIT_BUILTINS xstormy16_init_builtins#undef TARGET_EXPAND_BUILTIN#define TARGET_EXPAND_BUILTIN xstormy16_expand_builtinstatic struct {  const char *name;  int md_code;  const char *arg_ops; /* 0..9, t for temp register, r for return value */  const char *arg_types; /* s=short,l=long, upper case for unsigned */} s16builtins[] = {  { "__sdivlh", CODE_FOR_sdivlh, "rt01", "sls" },  { "__smodlh", CODE_FOR_sdivlh, "tr01", "sls" },  { "__udivlh", CODE_FOR_udivlh, "rt01", "SLS" },  { "__umodlh", CODE_FOR_udivlh, "tr01", "SLS" },  { 0, 0, 0, 0 }};static voidxstormy16_init_builtins (){  tree args, ret_type, arg;  int i, a;  ret_type = void_type_node;  for (i=0; s16builtins[i].name; i++)    {      args = void_list_node;      for (a=strlen (s16builtins[i].arg_types)-1; a>=0; a--)	{	  switch (s16builtins[i].arg_types[a])	    {	    case 's': arg = short_integer_type_node; break;	    case 'S': arg = short_unsigned_type_node; break;	    case 'l': arg = long_integer_type_node; break;	    case 'L': arg = long_unsigned_type_node; break;	    default: abort();	    }	  if (a == 0)	    ret_type = arg;	  else	    args = tree_cons (NULL_TREE, arg, args);	}      builtin_function (s16builtins[i].name,			build_function_type (ret_type, args),			i, BUILT_IN_MD, NULL, NULL);    }}static rtxxstormy16_expand_builtin(exp, target, subtarget, mode, ignore)     tree exp;     rtx target;     rtx subtarget ATTRIBUTE_UNUSED;     enum machine_mode mode ATTRIBUTE_UNUSED;     int ignore ATTRIBUTE_UNUSED;{  rtx op[10], args[10], pat, copyto[10], retval = 0;  tree fndecl, argtree;  int i, a, o, code;  fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);  argtree = TREE_OPERAND (exp, 1);  i = DECL_FUNCTION_CODE (fndecl);  code = s16builtins[i].md_code;  for (a = 0; a < 10 && argtree; a++)    {      args[a] = expand_expr (TREE_VALUE (argtree), NULL_RTX, VOIDmode, 0);      argtree = TREE_CHAIN (argtree);    }  for (o = 0; s16builtins[i].arg_ops[o]; o++)    {      char ao = s16builtins[i].arg_ops[o];      char c = insn_data[code].operand[o].constraint[0];      int omode;      copyto[o] = 0;      omode = insn_data[code].operand[o].mode;      if (ao == 'r')	op[o] = target ? target : gen_reg_rtx (omode);      else if (ao == 't')	op[o] = gen_reg_rtx (omode);      else	op[o] = args[(int) hex_value (ao)];      if (! (*insn_data[code].operand[o].predicate) (op[o], GET_MODE (op[o])))	{	  if (c == '+' || c == '=')	    {	      copyto[o] = op[o];	      op[o] = gen_reg_rtx (omode);	    }	  else	    op[o] = copy_to_mode_reg (omode, op[o]);	}      if (ao == 'r')	retval = op[o];    }  pat = GEN_FCN (code) (op[0], op[1], op[2], op[3], op[4],			op[5], op[6], op[7], op[8], op[9]);  emit_insn (pat);  for (o = 0; s16builtins[i].arg_ops[o]; o++)    if (copyto[o])      {	emit_move_insn (copyto[o], op[o]);	if (op[o] == retval)	  retval = copyto[o];      }  return retval;}#undef TARGET_ASM_ALIGNED_HI_OP#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"#undef TARGET_ASM_ALIGNED_SI_OP#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"#undef TARGET_ENCODE_SECTION_INFO#define TARGET_ENCODE_SECTION_INFO xstormy16_encode_section_info#undef TARGET_ASM_OUTPUT_MI_THUNK#define TARGET_ASM_OUTPUT_MI_THUNK xstormy16_asm_output_mi_thunk#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcallstruct gcc_target targetm = TARGET_INITIALIZER;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -