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

📄 xtensa.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
}static enum machine_modextensa_find_mode_for_size (item_size)     unsigned item_size;{  enum machine_mode mode, tmode;  while (1)    {      mode = VOIDmode;      /* find mode closest to but not bigger than item_size */      for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);	   tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))	if (GET_MODE_SIZE (tmode) <= item_size)	  mode = tmode;      if (mode == VOIDmode)	abort ();      item_size = GET_MODE_SIZE (mode);      if (xtensa_ld_opcodes[(int) mode]	  && xtensa_st_opcodes[(int) mode])	break;      /* cannot load & store this mode; try something smaller */      item_size -= 1;    }  return mode;}voidxtensa_expand_nonlocal_goto (operands)     rtx *operands;{  rtx goto_handler = operands[1];  rtx containing_fp = operands[3];  /* generate a call to "__xtensa_nonlocal_goto" (in libgcc); the code     is too big to generate in-line */  if (GET_CODE (containing_fp) != REG)    containing_fp = force_reg (Pmode, containing_fp);  goto_handler = replace_rtx (copy_rtx (goto_handler),			      virtual_stack_vars_rtx,			      containing_fp);  emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_nonlocal_goto"),		     0, VOIDmode, 2,		     containing_fp, Pmode,		     goto_handler, Pmode);}static struct machine_function *xtensa_init_machine_status (){  return ggc_alloc_cleared (sizeof (struct machine_function));}voidxtensa_setup_frame_addresses (){  /* Set flag to cause FRAME_POINTER_REQUIRED to be set. */  cfun->machine->accesses_prev_frame = 1;  emit_library_call    (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_libgcc_window_spill"),     0, VOIDmode, 0);}/* Emit the assembly for the end of a zero-cost loop. Normally we just emit   a comment showing where the end of the loop is. However, if there is a   label or a branch at the end of the loop then we need to place a nop   there. If the loop ends with a label we need the nop so that branches   targetting that label will target the nop (and thus remain in the loop),   instead of targetting the instruction after the loop (and thus exiting   the loop). If the loop ends with a branch, we need the nop in case the   branch is targetting a location inside the loop. When the branch   executes it will cause the loop count to be decremented even if it is   taken (because it is the last instruction in the loop), so we need to   nop after the branch to prevent the loop count from being decremented   when the branch is taken. */voidxtensa_emit_loop_end (insn, operands)     rtx insn;     rtx *operands;{  char done = 0;  for (insn = PREV_INSN (insn); insn && !done; insn = PREV_INSN (insn))    {      switch (GET_CODE (insn))	{	case NOTE:	case BARRIER:	  break;	case CODE_LABEL:	  output_asm_insn ("nop.n", operands);	  done = 1;	  break;	default:	  {	    rtx body = PATTERN (insn);	    if (GET_CODE (body) == JUMP_INSN)	      {		output_asm_insn ("nop.n", operands);		done = 1;	      }	    else if ((GET_CODE (body) != USE)		     && (GET_CODE (body) != CLOBBER))	      done = 1;	  }	  break;        }    }  output_asm_insn ("# loop end for %0", operands);}char *xtensa_emit_call (callop, operands)     int callop;     rtx *operands;{  static char result[64];  rtx tgt = operands[callop];  if (GET_CODE (tgt) == CONST_INT)    sprintf (result, "call8\t0x%x", INTVAL (tgt));  else if (register_operand (tgt, VOIDmode))    sprintf (result, "callx8\t%%%d", callop);  else    sprintf (result, "call8\t%%%d", callop);  return result;}/* Return the stabs register number to use for 'regno'. */intxtensa_dbx_register_number (regno)     int regno;{  int first = -1;    if (GP_REG_P (regno)) {    regno -= GP_REG_FIRST;    first = 0;  }  else if (BR_REG_P (regno)) {    regno -= BR_REG_FIRST;    first = 16;  }  else if (FP_REG_P (regno)) {    regno -= FP_REG_FIRST;    /* The current numbering convention is that TIE registers are       numbered in libcc order beginning with 256.  We can't guarantee       that the FP registers will come first, so the following is just       a guess.  It seems like we should make a special case for FP       registers and give them fixed numbers < 256. */    first = 256;  }  else if (ACC_REG_P (regno))    {      first = 0;      regno = -1;    }  /* When optimizing, we sometimes get asked about pseudo-registers     that don't represent hard registers. Return 0 for these. */  if (first == -1)    return 0;  return first + regno;}/* Argument support functions.  *//* Initialize CUMULATIVE_ARGS for a function.  */voidinit_cumulative_args (cum, incoming)     CUMULATIVE_ARGS *cum;	/* argument info to initialize */     int incoming;{  cum->arg_words = 0;  cum->incoming = incoming;}/* Advance the argument to the next argument position.  */voidfunction_arg_advance (cum, mode, type)     CUMULATIVE_ARGS *cum;	/* current arg information */     enum machine_mode mode;	/* current arg mode */     tree type;			/* type of the argument or 0 if lib support */{  int words, max;  int *arg_words;  arg_words = &cum->arg_words;  max = MAX_ARGS_IN_REGISTERS;  words = (((mode != BLKmode)	    ? (int) GET_MODE_SIZE (mode)	    : int_size_in_bytes (type)) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;  if ((*arg_words + words > max) && (*arg_words < max))    *arg_words = max;  *arg_words += words;}/* Return an RTL expression containing the register for the given mode,   or 0 if the argument is to be passed on the stack.  */rtxfunction_arg (cum, mode, type, incoming_p)     CUMULATIVE_ARGS *cum;	/* current arg information */     enum machine_mode mode;	/* current arg mode */     tree type;			/* type of the argument or 0 if lib support */     int incoming_p;		/* computing the incoming registers? */{  int regbase, words, max;  int *arg_words;  int regno;  arg_words = &cum->arg_words;  regbase = (incoming_p ? GP_ARG_FIRST : GP_OUTGOING_ARG_FIRST);  max = MAX_ARGS_IN_REGISTERS;  words = (((mode != BLKmode)	    ? (int) GET_MODE_SIZE (mode)	    : int_size_in_bytes (type)) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;  if (type && (TYPE_ALIGN (type) > BITS_PER_WORD))    *arg_words += (*arg_words & 1);  if (*arg_words + words > max)    return (rtx)0;  regno = regbase + *arg_words;  if (cum->incoming && regno <= A7_REG && regno + words > A7_REG)    cfun->machine->need_a7_copy = true;  return gen_rtx_REG (mode, regno);}voidoverride_options (){  int regno;  enum machine_mode mode;  if (!TARGET_BOOLEANS && TARGET_HARD_FLOAT)    error ("boolean registers required for the floating-point option");  /* set up the tables of ld/st opcode names for block moves */  xtensa_ld_opcodes[(int) SImode] = "l32i";  xtensa_ld_opcodes[(int) HImode] = "l16ui";  xtensa_ld_opcodes[(int) QImode] = "l8ui";  xtensa_st_opcodes[(int) SImode] = "s32i";  xtensa_st_opcodes[(int) HImode] = "s16i";  xtensa_st_opcodes[(int) QImode] = "s8i";  xtensa_char_to_class['q'] = SP_REG;  xtensa_char_to_class['a'] = GR_REGS;  xtensa_char_to_class['b'] = ((TARGET_BOOLEANS) ? BR_REGS : NO_REGS);  xtensa_char_to_class['f'] = ((TARGET_HARD_FLOAT) ? FP_REGS : NO_REGS);  xtensa_char_to_class['A'] = ((TARGET_MAC16) ? ACC_REG : NO_REGS);  xtensa_char_to_class['B'] = ((TARGET_SEXT) ? GR_REGS : NO_REGS);  xtensa_char_to_class['C'] = ((TARGET_MUL16) ? GR_REGS: NO_REGS);  xtensa_char_to_class['D'] = ((TARGET_DENSITY) ? GR_REGS: NO_REGS);  xtensa_char_to_class['d'] = ((TARGET_DENSITY) ? AR_REGS: NO_REGS);  /* Set up array giving whether a given register can hold a given mode. */  for (mode = VOIDmode;       mode != MAX_MACHINE_MODE;       mode = (enum machine_mode) ((int) mode + 1))    {      int size = GET_MODE_SIZE (mode);      enum mode_class class = GET_MODE_CLASS (mode);      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)	{	  int temp;	  if (ACC_REG_P (regno))	    temp = (TARGET_MAC16 &&		    (class == MODE_INT) && (size <= UNITS_PER_WORD));	  else if (GP_REG_P (regno))	    temp = ((regno & 1) == 0 || (size <= UNITS_PER_WORD));	  else if (FP_REG_P (regno))	    temp = (TARGET_HARD_FLOAT && (mode == SFmode));	  else if (BR_REG_P (regno))	    temp = (TARGET_BOOLEANS && (mode == CCmode));	  else	    temp = FALSE;	  xtensa_hard_regno_mode_ok[(int) mode][regno] = temp;	}    }  init_machine_status = xtensa_init_machine_status;  /* Check PIC settings.  There's no need for -fPIC on Xtensa and     some targets need to always use PIC.  */  if (flag_pic > 1 || (XTENSA_ALWAYS_PIC))    flag_pic = 1;}/* A C compound statement to output to stdio stream STREAM the   assembler syntax for an instruction operand X.  X is an RTL   expression.   CODE is a value that can be used to specify one of several ways   of printing the operand.  It is used when identical operands   must be printed differently depending on the context.  CODE   comes from the '%' specification that was used to request   printing of the operand.  If the specification was just '%DIGIT'   then CODE is 0; if the specification was '%LTR DIGIT' then CODE   is the ASCII code for LTR.   If X is a register, this macro should print the register's name.   The names can be found in an array 'reg_names' whose type is   'char *[]'.  'reg_names' is initialized from 'REGISTER_NAMES'.   When the machine description has a specification '%PUNCT' (a '%'   followed by a punctuation character), this macro is called with   a null pointer for X and the punctuation character for CODE.   'a', 'c', 'l', and 'n' are reserved.      The Xtensa specific codes are:   'd'  CONST_INT, print as signed decimal   'x'  CONST_INT, print as signed hexadecimal   'K'  CONST_INT, print number of bits in mask for EXTUI   'R'  CONST_INT, print (X & 0x1f)   'L'  CONST_INT, print ((32 - X) & 0x1f)   'D'  REG, print second register of double-word register operand   'N'  MEM, print address of next word following a memory operand   'v'  MEM, if memory reference is volatile, output a MEMW before it*/static voidprintx (file, val)     FILE *file;     signed int val;{  /* print a hexadecimal value in a nice way */  if ((val > -0xa) && (val < 0xa))    fprintf (file, "%d", val);  else if (val < 0)    fprintf (file, "-0x%x", -val);  else    fprintf (file, "0x%x", val);}voidprint_operand (file, op, letter)     FILE *file;		/* file to write to */     rtx op;		/* operand to print */     int letter;		/* %<letter> or 0 */{  enum rtx_code code;  if (! op)    error ("PRINT_OPERAND null pointer");  code = GET_CODE (op);  switch (code)    {    case REG:    case SUBREG:      {	int regnum = xt_true_regnum (op);	if (letter == 'D')	  regnum++;	fprintf (file, "%s", reg_names[regnum]);	break;      }    case MEM:      /* For a volatile memory reference, emit a MEMW before the	 load or store.  */ 	if (letter == 'v')	  {	    if (MEM_VOLATILE_P (op) && TARGET_SERIALIZE_VOLATILE)	      fprintf (file, "memw\n\t");	    break;	  } 	else if (letter == 'N')	  {	    enum machine_mode mode;	    switch (GET_MODE (op))	      {	      case DFmode: mode = SFmode; break;	      case DImode: mode = SImode; break;	      default: abort ();	      }	    op = adjust_address (op, mode, 4);	  }	output_address (XEXP (op, 0));	break;    case CONST_INT:      switch (letter)	{	case 'K':	  {	    int num_bits = 0;	    unsigned val = INTVAL (op);	    while (val & 1)	      {		num_bits += 1;		val = val >> 1;	      }	    if ((val != 0) || (num_bits == 0) || (num_bits > 16))	      fatal_insn ("invalid mask", op);	    fprintf (file, "%d", num_bits);	    break;	  }	case 'L':	  fprintf (file, "%d", (32 - INTVAL (op)) & 0x1f);	  break;	case 'R':	  fprintf (file, "%d", INTVAL (op) & 0x1f);	  break;	case 'x':	  printx (file, INTVAL (op));	  break;	case 'd':	default:	  fprintf (file, "%d", INTVAL (op));	  break;	}      break;    default:      output_addr_const (file, op);    }}/* A C compound statement to output to stdio stream STREAM the   assembler syntax for an instruction operand that is a memory   reference whose address is ADDR.  ADDR is an RTL expression.  */voidprint_operand_address (file, addr)     FILE *file;     rtx addr;{  if (!addr)    error ("PRINT_OPERAND_ADDRESS, null pointer");  switch (GET_CODE (addr))    {    default:      fatal_insn ("invalid address", addr);      break;    case REG:      fprintf (file, "%s, 0", reg_names [REGNO (addr)]);      break;    case PLUS:      {	rtx reg = (rtx)0;	rtx offset = (rtx)0;	rtx arg0 = XEXP (addr, 0);	rtx arg1 = XEXP (addr, 1);	if (GET_CODE (arg0) == REG)	  {	    reg = arg0;	    offset = arg1;	  }	else if (GET_CODE (arg1) == REG)	  {	    reg = arg1;	    offset = arg0;	  }	else	  fatal_insn ("no register in address", addr);	if (CONSTANT_P (offset))	  {	    fprintf (file, "%s, ", reg_names [REGNO (reg)]);	    output_addr_const (file, offset);	  }	else	  fatal_insn ("address offset not a constant", addr);      }      break;

⌨️ 快捷键说明

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