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

📄 m68k.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			 fsize_with_regs);	}      else if (fsize_with_regs <= 16 && TARGET_CPU32)	{	  /* On the CPU32 it is faster to use two addqw instructions to	     add a small integer (8 < N <= 16) to a register.  */	  asm_fprintf (stream, "\taddq" ASM_DOT "w %I8,%Rsp\n"	  		       "\taddq" ASM_DOT "w %I%wd,%Rsp\n",		       fsize_with_regs - 8);	}      else if (fsize_with_regs < 0x8000)	{	  if (TARGET_68040)	    asm_fprintf (stream, "\tadd" ASM_DOT "w %I%wd,%Rsp\n",			 fsize_with_regs);	  else	    asm_fprintf (stream, MOTOROLA ?				   "\tlea (%wd,%Rsp),%Rsp\n" :				   "\tlea %Rsp@(%wd),%Rsp\n",			 fsize_with_regs);	}      else	asm_fprintf (stream, "\tadd" ASM_DOT "l %I%wd,%Rsp\n", fsize_with_regs);    }  if (current_function_calls_eh_return)    asm_fprintf (stream, "\tadd" ASM_DOT"l %Ra0,%Rsp\n");  if (m68k_interrupt_function_p (current_function_decl))    fprintf (stream, "\trte\n");  else if (current_function_pops_args)    asm_fprintf (stream, "\trtd %I%d\n", current_function_pops_args);  else    fprintf (stream, "\trts\n");}/* Similar to general_operand, but exclude stack_pointer_rtx.  */intnot_sp_operand (rtx op, enum machine_mode mode){  return op != stack_pointer_rtx && nonimmediate_operand (op, mode);}/* Return true if X is a valid comparison operator for the dbcc    instruction.     Note it rejects floating point comparison operators.   (In the future we could use Fdbcc).   It also rejects some comparisons when CC_NO_OVERFLOW is set.  */   intvalid_dbcc_comparison_p (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED){  switch (GET_CODE (x))    {      case EQ: case NE: case GTU: case LTU:      case GEU: case LEU:        return 1;      /* Reject some when CC_NO_OVERFLOW is set.  This may be over         conservative */      case GT: case LT: case GE: case LE:        return ! (cc_prev_status.flags & CC_NO_OVERFLOW);      default:        return 0;    }}/* Return nonzero if flags are currently in the 68881 flag register.  */intflags_in_68881 (void){  /* We could add support for these in the future */  return cc_status.flags & CC_IN_68881;}/* Output a BSR instruction suitable for PIC code.  */voidm68k_output_pic_call(rtx dest){  const char *out;  if (!(GET_CODE (dest) == MEM && GET_CODE (XEXP (dest, 0)) == SYMBOL_REF))    out = "jsr %0";      /* We output a BSR instruction if we're using -fpic or we're building for       * a target that supports long branches.  If we're building -fPIC on the       * 68000, 68010 or ColdFire we generate one of two sequences:       * a shorter one that uses a GOT entry or a longer one that doesn't.       * We'll use the -Os command-line flag to decide which to generate.       * Both sequences take the same time to execute on the ColdFire.       */  else if (TARGET_PCREL)    out = "bsr.l %o0";  else if ((flag_pic == 1) || TARGET_68020)#if defined(USE_GAS)    out = "bsr.l %0@PLTPC";#else    out = "bsr %0@PLTPC";#endif  else if (optimize_size || TARGET_ID_SHARED_LIBRARY)    out = "move.l %0@GOT(%%a5), %%a1\n\tjsr (%%a1)";  else    out = "lea %0-.-8,%%a1\n\tjsr 0(%%pc,%%a1)";  output_asm_insn(out, &dest);}/* Output a dbCC; jCC sequence.  Note we do not handle the    floating point version of this sequence (Fdbcc).  We also   do not handle alternative conditions when CC_NO_OVERFLOW is   set.  It is assumed that valid_dbcc_comparison_p and flags_in_68881 will   kick those out before we get here.  */voidoutput_dbcc_and_branch (rtx *operands){  switch (GET_CODE (operands[3]))    {      case EQ:	output_asm_insn (MOTOROLA ?			   "dbeq %0,%l1\n\tjbeq %l2" :			   "dbeq %0,%l1\n\tjeq %l2",			 operands);	break;      case NE:	output_asm_insn (MOTOROLA ?			   "dbne %0,%l1\n\tjbne %l2" :			   "dbne %0,%l1\n\tjne %l2",			 operands);	break;      case GT:	output_asm_insn (MOTOROLA ?			   "dbgt %0,%l1\n\tjbgt %l2" :			   "dbgt %0,%l1\n\tjgt %l2",			 operands);	break;      case GTU:	output_asm_insn (MOTOROLA ?			   "dbhi %0,%l1\n\tjbhi %l2" :			   "dbhi %0,%l1\n\tjhi %l2",			 operands);	break;      case LT:	output_asm_insn (MOTOROLA ?			   "dblt %0,%l1\n\tjblt %l2" :			   "dblt %0,%l1\n\tjlt %l2",			 operands);	break;      case LTU:	output_asm_insn (MOTOROLA ?			   "dbcs %0,%l1\n\tjbcs %l2" :			   "dbcs %0,%l1\n\tjcs %l2",			 operands);	break;      case GE:	output_asm_insn (MOTOROLA ?			   "dbge %0,%l1\n\tjbge %l2" :			   "dbge %0,%l1\n\tjge %l2",			 operands);	break;      case GEU:	output_asm_insn (MOTOROLA ?			   "dbcc %0,%l1\n\tjbcc %l2" :			   "dbcc %0,%l1\n\tjcc %l2",			 operands);	break;      case LE:	output_asm_insn (MOTOROLA ?			   "dble %0,%l1\n\tjble %l2" :			   "dble %0,%l1\n\tjle %l2",			 operands);	break;      case LEU:	output_asm_insn (MOTOROLA ?			   "dbls %0,%l1\n\tjbls %l2" : 			   "dbls %0,%l1\n\tjls %l2",			 operands);	break;      default:	abort ();    }  /* If the decrement is to be done in SImode, then we have     to compensate for the fact that dbcc decrements in HImode.  */  switch (GET_MODE (operands[0]))    {      case SImode:        output_asm_insn (MOTOROLA ?			   "clr%.w %0\n\tsubq%.l #1,%0\n\tjbpl %l1" :			   "clr%.w %0\n\tsubq%.l #1,%0\n\tjpl %l1",			 operands);        break;      case HImode:        break;      default:        abort ();    }}const char *output_scc_di(rtx op, rtx operand1, rtx operand2, rtx dest){  rtx loperands[7];  enum rtx_code op_code = GET_CODE (op);  /* This does not produce a useful cc.  */  CC_STATUS_INIT;  /* The m68k cmp.l instruction requires operand1 to be a reg as used     below.  Swap the operands and change the op if these requirements     are not fulfilled.  */  if (GET_CODE (operand2) == REG && GET_CODE (operand1) != REG)    {      rtx tmp = operand1;      operand1 = operand2;      operand2 = tmp;      op_code = swap_condition (op_code);    }  loperands[0] = operand1;  if (GET_CODE (operand1) == REG)    loperands[1] = gen_rtx_REG (SImode, REGNO (operand1) + 1);  else    loperands[1] = adjust_address (operand1, SImode, 4);  if (operand2 != const0_rtx)    {      loperands[2] = operand2;      if (GET_CODE (operand2) == REG)	loperands[3] = gen_rtx_REG (SImode, REGNO (operand2) + 1);      else	loperands[3] = adjust_address (operand2, SImode, 4);    }  loperands[4] = gen_label_rtx ();  if (operand2 != const0_rtx)    {      output_asm_insn (MOTOROLA ?	  "cmp%.l %2,%0\n\tjbne %l4\n\tcmp%.l %3,%1" :          "cmp%.l %2,%0\n\tjne %l4\n\tcmp%.l %3,%1",	loperands);    }  else    {      if (TARGET_68020 || TARGET_COLDFIRE || ! ADDRESS_REG_P (loperands[0]))	output_asm_insn ("tst%.l %0", loperands);      else	{	  output_asm_insn ("cmp%.w #0,%0", loperands);	}      output_asm_insn (MOTOROLA ? "jbne %l4" : "jne %l4", loperands);      if (TARGET_68020 || TARGET_COLDFIRE || ! ADDRESS_REG_P (loperands[1]))	output_asm_insn ("tst%.l %1", loperands);      else	output_asm_insn ("cmp%.w #0,%1", loperands);    }  loperands[5] = dest;  switch (op_code)    {      case EQ:        (*targetm.asm_out.internal_label) (asm_out_file, "L",				    CODE_LABEL_NUMBER (loperands[4]));        output_asm_insn ("seq %5", loperands);        break;      case NE:        (*targetm.asm_out.internal_label) (asm_out_file, "L",				    CODE_LABEL_NUMBER (loperands[4]));        output_asm_insn ("sne %5", loperands);        break;      case GT:        loperands[6] = gen_label_rtx ();        output_asm_insn (MOTOROLA ?			   "shi %5\n\tjbra %l6" :			   "shi %5\n\tjra %l6",			 loperands);        (*targetm.asm_out.internal_label) (asm_out_file, "L",				    CODE_LABEL_NUMBER (loperands[4]));        output_asm_insn ("sgt %5", loperands);        (*targetm.asm_out.internal_label) (asm_out_file, "L",				    CODE_LABEL_NUMBER (loperands[6]));        break;      case GTU:        (*targetm.asm_out.internal_label) (asm_out_file, "L",				    CODE_LABEL_NUMBER (loperands[4]));        output_asm_insn ("shi %5", loperands);        break;      case LT:        loperands[6] = gen_label_rtx ();        output_asm_insn (MOTOROLA ?			   "scs %5\n\tjbra %l6" :			   "scs %5\n\tjra %l6",			 loperands);        (*targetm.asm_out.internal_label) (asm_out_file, "L",				    CODE_LABEL_NUMBER (loperands[4]));        output_asm_insn ("slt %5", loperands);        (*targetm.asm_out.internal_label) (asm_out_file, "L",				    CODE_LABEL_NUMBER (loperands[6]));        break;      case LTU:        (*targetm.asm_out.internal_label) (asm_out_file, "L",				    CODE_LABEL_NUMBER (loperands[4]));        output_asm_insn ("scs %5", loperands);        break;      case GE:        loperands[6] = gen_label_rtx ();        output_asm_insn (MOTOROLA ?			   "scc %5\n\tjbra %l6" :			   "scc %5\n\tjra %l6",			   loperands);        (*targetm.asm_out.internal_label) (asm_out_file, "L",				    CODE_LABEL_NUMBER (loperands[4]));        output_asm_insn ("sge %5", loperands);        (*targetm.asm_out.internal_label) (asm_out_file, "L",				    CODE_LABEL_NUMBER (loperands[6]));        break;      case GEU:        (*targetm.asm_out.internal_label) (asm_out_file, "L",				    CODE_LABEL_NUMBER (loperands[4]));        output_asm_insn ("scc %5", loperands);        break;      case LE:        loperands[6] = gen_label_rtx ();        output_asm_insn (MOTOROLA ?			   "sls %5\n\tjbra %l6" :			   "sls %5\n\tjra %l6",			 loperands);        (*targetm.asm_out.internal_label) (asm_out_file, "L",				    CODE_LABEL_NUMBER (loperands[4]));        output_asm_insn ("sle %5", loperands);        (*targetm.asm_out.internal_label) (asm_out_file, "L",				    CODE_LABEL_NUMBER (loperands[6]));        break;      case LEU:        (*targetm.asm_out.internal_label) (asm_out_file, "L",				    CODE_LABEL_NUMBER (loperands[4]));        output_asm_insn ("sls %5", loperands);        break;      default:	abort ();    }  return "";}const char *output_btst (rtx *operands, rtx countop, rtx dataop, rtx insn, int signpos){  operands[0] = countop;  operands[1] = dataop;  if (GET_CODE (countop) == CONST_INT)    {      register int count = INTVAL (countop);      /* If COUNT is bigger than size of storage unit in use,	 advance to the containing unit of same size.  */      if (count > signpos)	{	  int offset = (count & ~signpos) / 8;	  count = count & signpos;	  operands[1] = dataop = adjust_address (dataop, QImode, offset);	}      if (count == signpos)	cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N;      else	cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N;      /* These three statements used to use next_insns_test_no...	 but it appears that this should do the same job.  */      if (count == 31	  && next_insn_tests_no_inequality (insn))	return "tst%.l %1";      if (count == 15	  && next_insn_tests_no_inequality (insn))	return "tst%.w %1";      if (count == 7	  && next_insn_tests_no_inequality (insn))	return "tst%.b %1";      cc_status.flags = CC_NOT_NEGATIVE;    }  return "btst %0,%1";}/* Returns true if OP is either a symbol reference or a sum of a symbol   reference and a constant.  */intsymbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){  switch (GET_CODE (op))    {    case SYMBOL_REF:    case LABEL_REF:      return true;    case CONST:      op = XEXP (op, 0);      return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF	       || GET_CODE (XEXP (op, 0)) == LABEL_REF)	      && GET_CODE (XEXP (op, 1)) == CONST_INT);#if 0 /* Deleted, with corresponding change in m68k.h,	 so as to fit the specs.  No CONST_DOUBLE is ever symbolic.  */    case CONST_DOUBLE:      return GET_MODE (op) == mode;#endif    default:      return false;    }}/* Check for sign_extend or zero_extend.  Used for bit-count operands.  */intextend_operator(rtx x, enum machine_mode mode){

⌨️ 快捷键说明

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