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

📄 m32c.c

📁 linux下编程用 编译软件
💻 C
📖 第 1 页 / 共 5 页
字号:
intm32c_extra_address_constraint (char c, const char *str ATTRIBUTE_UNUSED){  return c == 'A';}/* STACK AND CALLING *//* Frame Layout *//* Implements RETURN_ADDR_RTX.  Note that R8C and M16C push 24 bits   (yes, THREE bytes) onto the stack for the return address, but we   don't support pointers bigger than 16 bits on those chips.  This   will likely wreak havoc with exception unwinding.  FIXME.  */rtxm32c_return_addr_rtx (int count){  enum machine_mode mode;  int offset;  rtx ra_mem;  if (count)    return NULL_RTX;  /* we want 2[$fb] */  if (TARGET_A24)    {      mode = SImode;      offset = 4;    }  else    {      /* FIXME: it's really 3 bytes */      mode = HImode;      offset = 2;    }  ra_mem =    gen_rtx_MEM (mode, plus_constant (gen_rtx_REG (Pmode, FP_REGNO), offset));  return copy_to_mode_reg (mode, ra_mem);}/* Implements INCOMING_RETURN_ADDR_RTX.  See comment above.  */rtxm32c_incoming_return_addr_rtx (void){  /* we want [sp] */  return gen_rtx_MEM (PSImode, gen_rtx_REG (PSImode, SP_REGNO));}/* Exception Handling Support *//* Implements EH_RETURN_DATA_REGNO.  Choose registers able to hold   pointers.  */intm32c_eh_return_data_regno (int n){  switch (n)    {    case 0:      return A0_REGNO;    case 1:      return A1_REGNO;    default:      return INVALID_REGNUM;    }}/* Implements EH_RETURN_STACKADJ_RTX.  Saved and used later in   m32c_emit_eh_epilogue.  */rtxm32c_eh_return_stackadj_rtx (void){  if (!cfun->machine->eh_stack_adjust)    {      rtx sa;      sa = gen_reg_rtx (Pmode);      cfun->machine->eh_stack_adjust = sa;    }  return cfun->machine->eh_stack_adjust;}/* Registers That Address the Stack Frame *//* Implements DWARF_FRAME_REGNUM and DBX_REGISTER_NUMBER.  Note that   the original spec called for dwarf numbers to vary with register   width as well, for example, r0l, r0, and r2r0 would each have   different dwarf numbers.  GCC doesn't support this, and we don't do   it, and gdb seems to like it this way anyway.  */unsigned intm32c_dwarf_frame_regnum (int n){  switch (n)    {    case R0_REGNO:      return 5;    case R1_REGNO:      return 6;    case R2_REGNO:      return 7;    case R3_REGNO:      return 8;    case A0_REGNO:      return 9;    case A1_REGNO:      return 10;    case FB_REGNO:      return 11;    case SB_REGNO:      return 19;    case SP_REGNO:      return 12;    case PC_REGNO:      return 13;    default:      return DWARF_FRAME_REGISTERS + 1;    }}/* The frame looks like this:   ap -> +------------------------------         | Return address (3 or 4 bytes)	 | Saved FB (2 or 4 bytes)   fb -> +------------------------------	 | local vars         | register saves fb	 |        through r0 as needed   sp -> +------------------------------*//* We use this to wrap all emitted insns in the prologue.  */static rtxF (rtx x){  RTX_FRAME_RELATED_P (x) = 1;  return x;}/* This maps register numbers to the PUSHM/POPM bitfield, and tells us   how much the stack pointer moves for each, for each cpu family.  */static struct{  int reg1;  int bit;  int a16_bytes;  int a24_bytes;} pushm_info[] ={  /* These are in push order.  */  { FB_REGNO, 0x01, 2, 4 },  { SB_REGNO, 0x02, 2, 4 },  { A1_REGNO, 0x04, 2, 4 },  { A0_REGNO, 0x08, 2, 4 },  { R3_REGNO, 0x10, 2, 2 },  { R2_REGNO, 0x20, 2, 2 },  { R1_REGNO, 0x40, 2, 2 },  { R0_REGNO, 0x80, 2, 2 }};#define PUSHM_N (sizeof(pushm_info)/sizeof(pushm_info[0]))/* Returns TRUE if we need to save/restore the given register.  We   save everything for exception handlers, so that any register can be   unwound.  For interrupt handlers, we save everything if the handler   calls something else (because we don't know what *that* function   might do), but try to be a bit smarter if the handler is a leaf   function.  We always save $a0, though, because we use that in the   epilog to copy $fb to $sp.  */static intneed_to_save (int regno){  if (fixed_regs[regno])    return 0;  if (cfun->calls_eh_return)    return 1;  if (regno == FP_REGNO)    return 0;  if (cfun->machine->is_interrupt      && (!cfun->machine->is_leaf || regno == A0_REGNO))    return 1;  if (regs_ever_live[regno]      && (!call_used_regs[regno] || cfun->machine->is_interrupt))    return 1;  return 0;}/* This function contains all the intelligence about saving and   restoring registers.  It always figures out the register save set.   When called with PP_justcount, it merely returns the size of the   save set (for eliminating the frame pointer, for example).  When   called with PP_pushm or PP_popm, it emits the appropriate   instructions for saving (pushm) or restoring (popm) the   registers.  */static intm32c_pushm_popm (Push_Pop_Type ppt){  int reg_mask = 0;  int byte_count = 0, bytes;  int i;  rtx dwarf_set[PUSHM_N];  int n_dwarfs = 0;  int nosave_mask = 0;  if (cfun->return_rtx      && GET_CODE (cfun->return_rtx) == PARALLEL      && !(cfun->calls_eh_return || cfun->machine->is_interrupt))    {      rtx exp = XVECEXP (cfun->return_rtx, 0, 0);      rtx rv = XEXP (exp, 0);      int rv_bytes = GET_MODE_SIZE (GET_MODE (rv));      if (rv_bytes > 2)	nosave_mask |= 0x20;	/* PSI, SI */      else	nosave_mask |= 0xf0;	/* DF */      if (rv_bytes > 4)	nosave_mask |= 0x50;	/* DI */    }  for (i = 0; i < (int) PUSHM_N; i++)    {      /* Skip if neither register needs saving.  */      if (!need_to_save (pushm_info[i].reg1))	continue;      if (pushm_info[i].bit & nosave_mask)	continue;      reg_mask |= pushm_info[i].bit;      bytes = TARGET_A16 ? pushm_info[i].a16_bytes : pushm_info[i].a24_bytes;      if (ppt == PP_pushm)	{	  enum machine_mode mode = (bytes == 2) ? HImode : SImode;	  rtx addr;	  /* Always use stack_pointer_rtx instead of calling	     rtx_gen_REG ourselves.  Code elsewhere in GCC assumes	     that there is a single rtx representing the stack pointer,	     namely stack_pointer_rtx, and uses == to recognize it.  */	  addr = stack_pointer_rtx;	  if (byte_count != 0)	    addr = gen_rtx_PLUS (GET_MODE (addr), addr, GEN_INT (byte_count));	  dwarf_set[n_dwarfs++] =	    gen_rtx_SET (VOIDmode,			 gen_rtx_MEM (mode, addr),			 gen_rtx_REG (mode, pushm_info[i].reg1));	  F (dwarf_set[n_dwarfs - 1]);	}      byte_count += bytes;    }  if (cfun->machine->is_interrupt)    {      cfun->machine->intr_pushm = reg_mask & 0xfe;      reg_mask = 0;      byte_count = 0;    }  if (cfun->machine->is_interrupt)    for (i = MEM0_REGNO; i <= MEM7_REGNO; i++)      if (need_to_save (i))	{	  byte_count += 2;	  cfun->machine->intr_pushmem[i - MEM0_REGNO] = 1;	}  if (ppt == PP_pushm && byte_count)    {      rtx note = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (n_dwarfs + 1));      rtx pushm;      if (reg_mask)	{	  XVECEXP (note, 0, 0)	    = gen_rtx_SET (VOIDmode,			   stack_pointer_rtx,			   gen_rtx_PLUS (GET_MODE (stack_pointer_rtx),					 stack_pointer_rtx,					 GEN_INT (-byte_count)));	  F (XVECEXP (note, 0, 0));	  for (i = 0; i < n_dwarfs; i++)	    XVECEXP (note, 0, i + 1) = dwarf_set[i];	  pushm = F (emit_insn (gen_pushm (GEN_INT (reg_mask))));	  REG_NOTES (pushm) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, note,						 REG_NOTES (pushm));	}      if (cfun->machine->is_interrupt)	for (i = MEM0_REGNO; i <= MEM7_REGNO; i++)	  if (cfun->machine->intr_pushmem[i - MEM0_REGNO])	    {	      if (TARGET_A16)		pushm = emit_insn (gen_pushhi_16 (gen_rtx_REG (HImode, i)));	      else		pushm = emit_insn (gen_pushhi_24 (gen_rtx_REG (HImode, i)));	      F (pushm);	    }    }  if (ppt == PP_popm && byte_count)    {      if (cfun->machine->is_interrupt)	for (i = MEM7_REGNO; i >= MEM0_REGNO; i--)	  if (cfun->machine->intr_pushmem[i - MEM0_REGNO])	    {	      if (TARGET_A16)		emit_insn (gen_pophi_16 (gen_rtx_REG (HImode, i)));	      else		emit_insn (gen_pophi_24 (gen_rtx_REG (HImode, i)));	    }      if (reg_mask)	emit_insn (gen_popm (GEN_INT (reg_mask)));    }  return byte_count;}/* Implements INITIAL_ELIMINATION_OFFSET.  See the comment above that   diagrams our call frame.  */intm32c_initial_elimination_offset (int from, int to){  int ofs = 0;  if (from == AP_REGNO)    {      if (TARGET_A16)	ofs += 5;      else	ofs += 8;    }  if (to == SP_REGNO)    {      ofs += m32c_pushm_popm (PP_justcount);      ofs += get_frame_size ();    }  /* Account for push rounding.  */  if (TARGET_A24)    ofs = (ofs + 1) & ~1;#if DEBUG0  fprintf (stderr, "initial_elimination_offset from=%d to=%d, ofs=%d\n", from,	   to, ofs);#endif  return ofs;}/* Passing Function Arguments on the Stack */#undef TARGET_PROMOTE_PROTOTYPES#define TARGET_PROMOTE_PROTOTYPES m32c_promote_prototypesstatic boolm32c_promote_prototypes (tree fntype ATTRIBUTE_UNUSED){  return 0;}/* Implements PUSH_ROUNDING.  The R8C and M16C have byte stacks, the   M32C has word stacks.  */intm32c_push_rounding (int n){  if (TARGET_R8C || TARGET_M16C)    return n;  return (n + 1) & ~1;}/* Passing Arguments in Registers *//* Implements FUNCTION_ARG.  Arguments are passed partly in registers,   partly on stack.  If our function returns a struct, a pointer to a   buffer for it is at the top of the stack (last thing pushed).  The   first few real arguments may be in registers as follows:   R8C/M16C:	arg1 in r1 if it's QI or HI (else it's pushed on stack)		arg2 in r2 if it's HI (else pushed on stack)		rest on stack   M32C:        arg1 in r0 if it's QI or HI (else it's pushed on stack)		rest on stack   Structs are not passed in registers, even if they fit.  Only   integer and pointer types are passed in registers.   Note that when arg1 doesn't fit in r1, arg2 may still be passed in   r2 if it fits.  */rtxm32c_function_arg (CUMULATIVE_ARGS * ca,		   enum machine_mode mode, tree type, int named){  /* Can return a reg, parallel, or 0 for stack */  rtx rv = NULL_RTX;#if DEBUG0  fprintf (stderr, "func_arg %d (%s, %d)\n",	   ca->parm_num, mode_name[mode], named);  debug_tree (type);#endif  if (mode == VOIDmode)    return GEN_INT (0);  if (ca->force_mem || !named)    {#if DEBUG0      fprintf (stderr, "func arg: force %d named %d, mem\n", ca->force_mem,	       named);#endif      return NULL_RTX;    }  if (type && INTEGRAL_TYPE_P (type) && POINTER_TYPE_P (type))    return NULL_RTX;  switch (ca->parm_num)    {    case 1:      if (GET_MODE_SIZE (mode) == 1 || GET_MODE_SIZE (mode) == 2)	rv = gen_rtx_REG (mode, TARGET_A16 ? R1_REGNO : R0_REGNO);      break;    case 2:      if (TARGET_A16 && GET_MODE_SIZE (mode) == 2)	rv = gen_rtx_REG (mode, R2_REGNO);      break;    }#if DEBUG0  debug_rtx (rv);#endif  return rv;}#undef TARGET_PASS_BY_REFERENCE#define TARGET_PASS_BY_REFERENCE m32c_pass_by_referencestatic boolm32c_pass_by_reference (CUMULATIVE_ARGS * ca ATTRIBUTE_UNUSED,			enum machine_mode mode ATTRIBUTE_UNUSED,			tree type ATTRIBUTE_UNUSED,			bool named ATTRIBUTE_UNUSED){  return 0;}/* Implements INIT_CUMULATIVE_ARGS.  */voidm32c_init_cumulative_args (CUMULATIVE_ARGS * ca,			   tree fntype ATTRIBUTE_UNUSED,			   rtx libname ATTRIBUTE_UNUSED,			   tree fndecl ATTRIBUTE_UNUSED,			   int n_named_args ATTRIBUTE_UNUSED){  ca->force_mem = 0;  ca->parm_num = 1;}/* Implements FUNCTION_ARG_ADVANCE.  force_mem is set for functions   returning structures, so we always reset that.  Otherwise, we only   need to know the sequence number of the argument to know what to do   with it.  */voidm32c_function_arg_advance (CUMULATIVE_ARGS * ca,			   enum machine_mode mode ATTRIBUTE_UNUSED,			   tree type ATTRIBUTE_UNUSED,			   int named ATTRIBUTE_UNUSED){  if (ca->force_mem)    ca->force_mem = 0;  ca->parm_num++;}/* Implements FUNCTION_ARG_REGNO_P.  */intm32c_function_arg_regno_p (int r){  if (TARGET_A24)    return (r == R0_REGNO);  return (r == R1_REGNO || r == R2_REGNO);}/* HImode and PSImode are the two "native" modes as far as GCC is   concerned, but the chips also support a 32 bit mode which is used   for some opcodes in R8C/M16C and for reset vectors and such.  */#undef TARGET_VALID_POINTER_MODE#define TARGET_VALID_POINTER_MODE m32c_valid_pointer_modeboolm32c_valid_pointer_mode (enum machine_mode mode){  if (mode == HImode      || mode == PSImode      || mode == SImode      )    return 1;  return 0;}/* How Scalar Function Values Are Returned *//* Implements LIBCALL_VALUE.  Most values are returned in $r0, or some

⌨️ 快捷键说明

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