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

📄 arm.c

📁 GUN开源阻止下的编译器GCC
💻 C
📖 第 1 页 / 共 5 页
字号:
     rtx to;     int up;     int write_back;{  int i = 0, j;  rtx result;  int sign = up ? 1 : -1;  result = gen_rtx (PARALLEL, VOIDmode,                    rtvec_alloc (count + (write_back ? 2 : 0)));  if (write_back)    {      XVECEXP (result, 0, 0)	= gen_rtx (SET, GET_MODE (to), to,		   plus_constant (to, count * 4 * sign));      i = 1;      count++;    }  for (j = 0; i < count; i++, j++)    {      XVECEXP (result, 0, i)	= gen_rtx (SET, VOIDmode,		   gen_rtx (MEM, SImode, plus_constant (to, j * 4 * sign)),		   gen_rtx (REG, SImode, base_regno + j));    }  if (write_back)    XVECEXP (result, 0, i) = gen_rtx (CLOBBER, SImode, to);  return result;}intarm_gen_movstrqi (operands)     rtx *operands;{  HOST_WIDE_INT in_words_to_go, out_words_to_go, last_bytes;  int i, r;  rtx src, dst;  rtx st_src, st_dst, end_src, end_dst, fin_src, fin_dst;  rtx part_bytes_reg = NULL;  extern int optimize;  if (GET_CODE (operands[2]) != CONST_INT      || GET_CODE (operands[3]) != CONST_INT      || INTVAL (operands[2]) > 64      || INTVAL (operands[3]) & 3)    return 0;  st_dst = XEXP (operands[0], 0);  st_src = XEXP (operands[1], 0);  fin_dst = dst = copy_to_mode_reg (SImode, st_dst);  fin_src = src = copy_to_mode_reg (SImode, st_src);  in_words_to_go = (INTVAL (operands[2]) + 3) / 4;  out_words_to_go = INTVAL (operands[2]) / 4;  last_bytes = INTVAL (operands[2]) & 3;  if (out_words_to_go != in_words_to_go && ((in_words_to_go - 1) & 3) != 0)    part_bytes_reg = gen_rtx (REG, SImode, (in_words_to_go - 1) & 3);  for (i = 0; in_words_to_go >= 2; i+=4)    {      emit_insn (arm_gen_load_multiple (0, (in_words_to_go > 4 					    ? 4 : in_words_to_go),                                        src, TRUE, TRUE));      if (out_words_to_go)	{	  if (out_words_to_go != 1)	    emit_insn (arm_gen_store_multiple (0, (out_words_to_go > 4						   ? 4 : out_words_to_go),					       dst, TRUE, TRUE));	  else	    {	      emit_move_insn (gen_rtx (MEM, SImode, dst),			      gen_rtx (REG, SImode, 0));	      emit_insn (gen_addsi3 (dst, dst, GEN_INT (4)));	    }	}      in_words_to_go -= in_words_to_go < 4 ? in_words_to_go : 4;      out_words_to_go -= out_words_to_go < 4 ? out_words_to_go : 4;    }  /* OUT_WORDS_TO_GO will be zero here if there are byte stores to do.  */  if (out_words_to_go)  {    rtx sreg;    emit_move_insn (sreg = gen_reg_rtx (SImode), gen_rtx (MEM, SImode, src));    emit_move_insn (fin_src = gen_reg_rtx (SImode), plus_constant (src, 4));    emit_move_insn (gen_rtx (MEM, SImode, dst), sreg);    emit_move_insn (fin_dst = gen_reg_rtx (SImode), plus_constant (dst, 4));    in_words_to_go--;    if (in_words_to_go)	/* Sanity check */      abort ();  }  if (in_words_to_go)    {      if (in_words_to_go < 0)	abort ();      part_bytes_reg = copy_to_mode_reg (SImode, gen_rtx (MEM, SImode, src));      emit_insn (gen_addsi3 (src, src, GEN_INT (4)));    }  if (BYTES_BIG_ENDIAN && last_bytes)    {      rtx tmp = gen_reg_rtx (SImode);      if (part_bytes_reg == NULL)	abort ();      /* The bytes we want are in the top end of the word */      emit_insn (gen_lshrsi3 (tmp, part_bytes_reg,			      GEN_INT (8 * (4 - last_bytes))));      part_bytes_reg = tmp;            while (last_bytes)	{	  emit_move_insn (gen_rtx (MEM, QImode, 				   plus_constant (dst, last_bytes - 1)),			  gen_rtx (SUBREG, QImode, part_bytes_reg, 0));	  if (--last_bytes)	    {	      tmp = gen_reg_rtx (SImode);	      emit_insn (gen_lshrsi3 (tmp, part_bytes_reg, GEN_INT (8)));	      part_bytes_reg = tmp;	    }	}	      }  else    {      while (last_bytes)	{	  if (part_bytes_reg == NULL)	    abort ();	  emit_move_insn (gen_rtx (MEM, QImode, dst),			  gen_rtx (SUBREG, QImode, part_bytes_reg, 0));	  emit_insn (gen_addsi3 (dst, dst, const1_rtx));	  if (--last_bytes)	    {	      rtx tmp = gen_reg_rtx (SImode);	      emit_insn (gen_lshrsi3 (tmp, part_bytes_reg, GEN_INT (8)));	      part_bytes_reg = tmp;	    }	}    }  return 1;}/* X and Y are two things to compare using CODE.  Emit the compare insn and   return the rtx for register 0 in the proper mode.  FP means this is a   floating point compare: I don't think that it is needed on the arm.  */rtxgen_compare_reg (code, x, y, fp)     enum rtx_code code;     rtx x, y;{  enum machine_mode mode = SELECT_CC_MODE (code, x, y);  rtx cc_reg = gen_rtx (REG, mode, 24);  emit_insn (gen_rtx (SET, VOIDmode, cc_reg,                      gen_rtx (COMPARE, mode, x, y)));  return cc_reg;}voidarm_reload_in_hi (operands)     rtx *operands;{  rtx base = find_replacement (&XEXP (operands[1], 0));  emit_insn (gen_zero_extendqisi2 (operands[2], gen_rtx (MEM, QImode, base)));  emit_insn (gen_zero_extendqisi2 (gen_rtx (SUBREG, SImode, operands[0], 0),				   gen_rtx (MEM, QImode, 					    plus_constant (base, 1))));  if (BYTES_BIG_ENDIAN)    emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (SUBREG, SImode, 						operands[0], 0),			gen_rtx (IOR, SImode, 				 gen_rtx (ASHIFT, SImode,					  gen_rtx (SUBREG, SImode,						   operands[0], 0),					  GEN_INT (8)),				 operands[2])));  else    emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (SUBREG, SImode, 						operands[0], 0),			gen_rtx (IOR, SImode, 				 gen_rtx (ASHIFT, SImode,					  operands[2],					  GEN_INT (8)),				 gen_rtx (SUBREG, SImode, operands[0], 0))));}voidarm_reload_out_hi (operands)     rtx *operands;{  rtx base = find_replacement (&XEXP (operands[0], 0));  if (BYTES_BIG_ENDIAN)    {      emit_insn (gen_movqi (gen_rtx (MEM, QImode, plus_constant (base, 1)),			    gen_rtx (SUBREG, QImode, operands[1], 0)));      emit_insn (gen_lshrsi3 (operands[2],			      gen_rtx (SUBREG, SImode, operands[1], 0),			      GEN_INT (8)));      emit_insn (gen_movqi (gen_rtx (MEM, QImode, base),			    gen_rtx (SUBREG, QImode, operands[2], 0)));    }  else    {      emit_insn (gen_movqi (gen_rtx (MEM, QImode, base),			    gen_rtx (SUBREG, QImode, operands[1], 0)));      emit_insn (gen_lshrsi3 (operands[2],			      gen_rtx (SUBREG, SImode, operands[1], 0),			      GEN_INT (8)));      emit_insn (gen_movqi (gen_rtx (MEM, QImode, plus_constant (base, 1)),			    gen_rtx (SUBREG, QImode, operands[2], 0)));    }}/* Check to see if a branch is forwards or backwards.  Return TRUE if it   is backwards.  */intarm_backwards_branch (from, to)     int from, to;{  return insn_addresses[to] <= insn_addresses[from];}/* Check to see if a branch is within the distance that can be done using   an arithmetic expression. */intshort_branch (from, to)     int from, to;{  int delta = insn_addresses[from] + 8 - insn_addresses[to];  return abs (delta) < 980;	/* A small margin for safety */}/* Check to see that the insn isn't the target of the conditionalizing   code */intarm_insn_not_targeted (insn)     rtx insn;{  return insn != arm_target_insn;}/* Routines to output assembly language.  *//* If the rtx is the correct value then return the string of the number.   In this way we can ensure that valid double constants are generated even   when cross compiling. */char *fp_immediate_constant (x)     rtx x;{  REAL_VALUE_TYPE r;  int i;    if (!fpa_consts_inited)    init_fpa_table ();    REAL_VALUE_FROM_CONST_DOUBLE (r, x);  for (i = 0; i < 8; i++)    if (REAL_VALUES_EQUAL (r, values_fpa[i]))      return strings_fpa[i];  abort ();}/* As for fp_immediate_constant, but value is passed directly, not in rtx.  */static char *fp_const_from_val (r)     REAL_VALUE_TYPE *r;{  int i;  if (! fpa_consts_inited)    init_fpa_table ();  for (i = 0; i < 8; i++)    if (REAL_VALUES_EQUAL (*r, values_fpa[i]))      return strings_fpa[i];  abort ();}/* Output the operands of a LDM/STM instruction to STREAM.   MASK is the ARM register set mask of which only bits 0-15 are important.   INSTR is the possibly suffixed base register.  HAT unequals zero if a hat   must follow the register list.  */voidprint_multi_reg (stream, instr, mask, hat)     FILE *stream;     char *instr;     int mask, hat;{  int i;  int not_first = FALSE;  fputc ('\t', stream);  fprintf (stream, instr, REGISTER_PREFIX);  fputs (", {", stream);  for (i = 0; i < 16; i++)    if (mask & (1 << i))      {	if (not_first)	  fprintf (stream, ", ");	fprintf (stream, "%s%s", REGISTER_PREFIX, reg_names[i]);	not_first = TRUE;      }  fprintf (stream, "}%s\n", hat ? "^" : "");}/* Output a 'call' insn. */char *output_call (operands)     rtx *operands;{  /* Handle calls to lr using ip (which may be clobbered in subr anyway). */  if (REGNO (operands[0]) == 14)    {      operands[0] = gen_rtx (REG, SImode, 12);      output_asm_insn ("mov%?\t%0, %|lr", operands);    }  output_asm_insn ("mov%?\t%|lr, %|pc", operands);  output_asm_insn ("mov%?\t%|pc, %0", operands);  return "";}static inteliminate_lr2ip (x)     rtx *x;{  int something_changed = 0;  rtx x0 = *x;  int code = GET_CODE (x0);  register int i, j;  register char *fmt;    switch (code)    {    case REG:      if (REGNO (x0) == 14)        {	  *x = gen_rtx (REG, SImode, 12);	  return 1;        }      return 0;    default:      /* Scan through the sub-elements and change any references there */      fmt = GET_RTX_FORMAT (code);      for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)	if (fmt[i] == 'e')	  something_changed |= eliminate_lr2ip (&XEXP (x0, i));	else if (fmt[i] == 'E')	  for (j = 0; j < XVECLEN (x0, i); j++)	    something_changed |= eliminate_lr2ip (&XVECEXP (x0, i, j));      return something_changed;    }}  /* Output a 'call' insn that is a reference in memory. */char *output_call_mem (operands)     rtx *operands;{  operands[0] = copy_rtx (operands[0]); /* Be ultra careful */  /* Handle calls using lr by using ip (which may be clobbered in subr anyway).   */  if (eliminate_lr2ip (&operands[0]))    output_asm_insn ("mov%?\t%|ip, %|lr", operands);  output_asm_insn ("mov%?\t%|lr, %|pc", operands);  output_asm_insn ("ldr%?\t%|pc, %0", operands);  return "";}/* Output a move from arm registers to an fpu registers.   OPERANDS[0] is an fpu register.   OPERANDS[1] is the first registers of an arm register pair.  */char *output_mov_long_double_fpu_from_arm (operands)     rtx *operands;{  int arm_reg0 = REGNO (operands[1]);  rtx ops[3];  if (arm_reg0 == 12)    abort();  ops[0] = gen_rtx (REG, SImode, arm_reg0);  ops[1] = gen_rtx (REG, SImode, 1 + arm_reg0);  ops[2] = gen_rtx (REG, SImode, 2 + arm_reg0);    output_asm_insn ("stm%?fd\t%|sp!, {%0, %1, %2}", ops);  output_asm_insn ("ldf%?e\t%0, [%|sp], #12", operands);  return "";}/* Output a move from an fpu register to arm registers.   OPERANDS[0] is the first registers of an arm register pair.   OPERANDS[1] is an fpu register.  */char *output_mov_long_double_arm_from_fpu (operands)     rtx *operands;{  int arm_reg0 = REGNO (operands[0]);  rtx ops[3];  if (arm_reg0 == 12)    abort();  ops[0] = gen_rtx (REG, SImode, arm_reg0);  ops[1] = gen_rtx (REG, SImode, 1 + arm_reg0);  ops[2] = gen_rtx (REG, SImode, 2 + arm_reg0);  output_asm_insn ("stf%?e\t%1, [%|sp, #-12]!", operands);  output_asm_insn ("ldm%?fd\t%|sp!, {%0, %1, %2}", ops);  return "";}/* Output a move from arm registers to arm registers of a long double   OPERANDS[0] is the destination.   OPERANDS[1] is the source.  */char *output_mov_long_double_arm_from_arm (operands)     rtx *operands;{  /* We have to be careful here because the two might overlap */  int dest_start = REGNO (operands[0]);  int src_start = REGNO (operands[1]);  rtx ops[2];  int i;  if (dest_start < src_start)    {      for (i = 0; i < 3; i++)	{	  ops[0] = gen_rtx (REG, SImode, dest_start + i);	  ops[1] = gen_rtx (REG, SImode, src_start + i);	  output_asm_insn ("mov%?\t%0, %1", ops);	}    }  else    {      for (i = 2; i >= 0; i--)	{	  ops[0] = gen_rtx (REG, SImode, dest_start + i);	  ops[1] = gen_rtx (REG, SImode, src_start + i);	  output_asm_insn ("mov%?\t%0, %1", ops);	}    }  return "";}/* Output a move from arm registers to an fpu registers.   OPERANDS[0] is an fpu register.   OPERANDS[1] is the first registers of an arm register pair.  */char *output_mov_double_fpu_from_arm (operands)     rtx *operands;{  int arm_reg0 = REGNO (operands[1]);  rtx ops[2];  if (arm_reg0 == 12)    abort();  ops[0] = gen_rtx (REG, SImode, arm_reg0);  ops[1] = gen_rtx (REG, SImode, 1 + arm_reg0);  output_asm_insn ("stm%?fd\t%|sp!, {%0, %1}", ops);  output_asm_insn ("ldf%?d\t%0, [%|sp], #8", operands);  return "";}/* Output a move from an fpu register to arm registers.   OPERANDS[0] is the first registers of an arm register pair.   OPERANDS[1] is an fpu register.  */char *output_mov_double_arm_from_fpu (operands)     rtx *operands;{  int arm_reg0 = REGNO (operands[0]);  rtx ops[2];  if (arm_reg0 == 12)    abort();  ops[0] = gen_rtx (REG, SImode, arm_reg0);  ops[1] = gen_rtx (REG, SImode, 1 + arm_reg0);  output_asm_insn ("stf%?d\t%1, [%|sp, #-8]!", operands);  output_asm_insn ("ldm%?fd\t%|sp!, {%0, %1}", ops);  return "";}

⌨️ 快捷键说明

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