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

📄 pdp11.c

📁 gcc编译工具没有什么特别
💻 C
📖 第 1 页 / 共 3 页
字号:
    optype0 = RNDOP;  if (REG_P (operands[1]))    optype1 = REGOP;  else if (CONSTANT_P (operands[1])	   || GET_CODE (operands[1]) == CONST_DOUBLE)    optype1 = CNSTOP;  else if (offsettable_memref_p (operands[1]))    optype1 = OFFSOP;  else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)    optype1 = POPOP;  else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)    optype1 = PUSHOP;  else if (GET_CODE (operands[1]) == MEM)    optype1 = MEMOP;  else    optype1 = RNDOP;  /* Check for the cases that the operand constraints are not     supposed to allow to happen.  Abort if we get one,     because generating code for these cases is painful.  */  if (optype0 == RNDOP || optype1 == RNDOP)    abort ();    /* check if we move a CPU reg to an FPU reg, or vice versa! */  if (optype0 == REGOP && optype1 == REGOP)      /* bogus - 64 bit cannot reside in CPU! */      if (CPU_REG_P(REGNO(operands[0]))	  || CPU_REG_P (REGNO(operands[1])))	  abort();    if (optype0 == REGOP || optype1 == REGOP)  {      /* check for use of clrd????          if you ever allow ac4 and ac5 (now we require secondary load) 	 you must check whether 	 you want to load into them or store from them - 	 then dump ac0 into $help$ movce ac4/5 to ac0, do the 	 store from ac0, and restore ac0 - if you can find 	 an unused ac[0-3], use that and you save a store and a load!*/      if (FPU_REG_P(REGNO(operands[0])))      {	  if (GET_CODE(operands[1]) == CONST_DOUBLE)	  {	      union { double d; int i[2]; } u;	      u.i[0] = CONST_DOUBLE_LOW (operands[1]); 	      u.i[1] = CONST_DOUBLE_HIGH (operands[1]); 	      	      if (u.d == 0.0)		  return "{clrd|clrf} %0";	  }	      	  return "{ldd|movf} %1, %0";      }            if (FPU_REG_P(REGNO(operands[1])))	  return "{std|movf} %1, %0";  }        /* If one operand is decrementing and one is incrementing     decrement the former register explicitly     and change that operand into ordinary indexing.  */  if (optype0 == PUSHOP && optype1 == POPOP)    {      operands[0] = XEXP (XEXP (operands[0], 0), 0);      output_asm_insn ("sub $8,%0", operands);      operands[0] = gen_rtx (MEM, DImode, operands[0]);      optype0 = OFFSOP;    }  if (optype0 == POPOP && optype1 == PUSHOP)    {      operands[1] = XEXP (XEXP (operands[1], 0), 0);      output_asm_insn ("sub $8,%1", operands);      operands[1] = gen_rtx (MEM, SImode, operands[1]);      optype1 = OFFSOP;    }  /* If an operand is an unoffsettable memory ref, find a register     we can increment temporarily to make it refer to the second word.  */  if (optype0 == MEMOP)    addreg0 = find_addr_reg (XEXP (operands[0], 0));  if (optype1 == MEMOP)    addreg1 = find_addr_reg (XEXP (operands[1], 0));  /* Ok, we can do one word at a time.     Normally we do the low-numbered word first,     but if either operand is autodecrementing then we     do the high-numbered word first.     In either case, set up in LATEHALF the operands to use     for the high-numbered word and in some cases alter the     operands in OPERANDS to be suitable for the low-numbered word.  */  if (optype0 == REGOP)    latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2);  else if (optype0 == OFFSOP)    latehalf[0] = adj_offsettable_operand (operands[0], 4);  else    latehalf[0] = operands[0];  if (optype1 == REGOP)    latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);  else if (optype1 == OFFSOP)    latehalf[1] = adj_offsettable_operand (operands[1], 4);  else if (optype1 == CNSTOP)    {      if (GET_CODE (operands[1]) == CONST_DOUBLE)	{	    /* floats only. not yet supported!	     -- compute it into PDP float format, - internally,	     just use IEEE and ignore possible problems ;-)	     we might get away with it !!!! */	    abort();	    #ifndef HOST_WORDS_BIG_ENDIAN	  latehalf[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));	  operands[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));#else /* HOST_WORDS_BIG_ENDIAN */	  latehalf[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));	  operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));#endif /* HOST_WORDS_BIG_ENDIAN */	}      else if (GET_CODE(operands[1]) == CONST_INT)      {	  latehalf[1] = GEN_INT (0);      }      else	  abort();          }  else    latehalf[1] = operands[1];  /* If insn is effectively movd N(sp),-(sp) then we will do the     high word first.  We should use the adjusted operand 1 (which is N+4(sp))     for the low word as well, to compensate for the first decrement of sp.  */  if (optype0 == PUSHOP      && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM      && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))    operands[1] = latehalf[1];  /* If one or both operands autodecrementing,     do the two words, high-numbered first.  */  /* Likewise,  the first move would clobber the source of the second one,     do them in the other order.  This happens only for registers;     such overlap can't happen in memory unless the user explicitly     sets it up, and that is an undefined circumstance.  */  if (optype0 == PUSHOP || optype1 == PUSHOP      || (optype0 == REGOP && optype1 == REGOP	  && REGNO (operands[0]) == REGNO (latehalf[1])))    {      /* Make any unoffsettable addresses point at high-numbered word.  */      if (addreg0)	output_asm_insn ("add $4,%0", &addreg0);      if (addreg1)	output_asm_insn ("add $4,%0", &addreg1);      /* Do that word.  */      output_asm_insn(output_move_double(latehalf), latehalf);      /* Undo the adds we just did.  */      if (addreg0)	output_asm_insn ("sub $4,%0", &addreg0);      if (addreg1)	output_asm_insn ("sub $4,%0", &addreg1);      /* Do low-numbered word.  */      return output_move_double (operands);    }  /* Normal case: do the two words, low-numbered first.  */  output_asm_insn (output_move_double (operands), operands);  /* Make any unoffsettable addresses point at high-numbered word.  */  if (addreg0)    output_asm_insn ("add $4,%0", &addreg0);  if (addreg1)    output_asm_insn ("add $4,%0", &addreg1);  /* Do that word.  */  output_asm_insn (output_move_double (latehalf), latehalf);  /* Undo the adds we just did.  */  if (addreg0)    output_asm_insn ("sub $4,%0", &addreg0);  if (addreg1)    output_asm_insn ("sub $4,%0", &addreg1);  return "";}/* Return a REG that occurs in ADDR with coefficient 1.   ADDR can be effectively incremented by incrementing REG.  */static rtxfind_addr_reg (addr)     rtx addr;{  while (GET_CODE (addr) == PLUS)    {      if (GET_CODE (XEXP (addr, 0)) == REG)	addr = XEXP (addr, 0);      if (GET_CODE (XEXP (addr, 1)) == REG)	addr = XEXP (addr, 1);      if (CONSTANT_P (XEXP (addr, 0)))	addr = XEXP (addr, 1);      if (CONSTANT_P (XEXP (addr, 1)))	addr = XEXP (addr, 0);    }  if (GET_CODE (addr) == REG)    return addr;  return 0;}/* Output an ascii string.  */voidoutput_ascii (file, p, size)     FILE *file;     char *p;     int size;{  int i;  /* This used to output .byte "string", which doesn't work with the UNIX     assembler and I think not with DEC ones either.  */  fprintf (file, "\t.byte ");  for (i = 0; i < size; i++)    {      register int c = p[i];      if (c < 0)	c += 256;      fprintf (file, "%o", c);      if (i < size - 1)	putc (',', file);    }  putc ('\n', file);}/* --- stole from out-vax, needs changes */voidprint_operand_address (file, addr)     FILE *file;     register rtx addr;{  register rtx reg1, reg2, breg, ireg;  rtx offset; retry:  switch (GET_CODE (addr))    {    case MEM:      if (TARGET_UNIX_ASM)	fprintf (file, "*");      else	fprintf (file, "@");      addr = XEXP (addr, 0);      goto retry;    case REG:      fprintf (file, "(%s)", reg_names[REGNO (addr)]);      break;    case PRE_DEC:      fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);      break;    case POST_INC:      fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);      break;    case PLUS:      reg1 = 0;	reg2 = 0;      ireg = 0;	breg = 0;      offset = 0;      if (CONSTANT_ADDRESS_P (XEXP (addr, 0))	  || GET_CODE (XEXP (addr, 0)) == MEM)	{	  offset = XEXP (addr, 0);	  addr = XEXP (addr, 1);	}      else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))	       || GET_CODE (XEXP (addr, 1)) == MEM)	{	  offset = XEXP (addr, 1);	  addr = XEXP (addr, 0);	}      if (GET_CODE (addr) != PLUS)	;      else if (GET_CODE (XEXP (addr, 0)) == MULT)	{	  reg1 = XEXP (addr, 0);	  addr = XEXP (addr, 1);	}      else if (GET_CODE (XEXP (addr, 1)) == MULT)	{	  reg1 = XEXP (addr, 1);	  addr = XEXP (addr, 0);	}      else if (GET_CODE (XEXP (addr, 0)) == REG)	{	  reg1 = XEXP (addr, 0);	  addr = XEXP (addr, 1);	}      else if (GET_CODE (XEXP (addr, 1)) == REG)	{	  reg1 = XEXP (addr, 1);	  addr = XEXP (addr, 0);	}      if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)	{	  if (reg1 == 0)	    reg1 = addr;	  else	    reg2 = addr;	  addr = 0;	}      if (offset != 0)	{	  if (addr != 0) abort ();	  addr = offset;	}      if (reg1 != 0 && GET_CODE (reg1) == MULT)	{	  breg = reg2;	  ireg = reg1;	}      else if (reg2 != 0 && GET_CODE (reg2) == MULT)	{	  breg = reg1;	  ireg = reg2;	}      else if (reg2 != 0 || GET_CODE (addr) == MEM)	{	  breg = reg2;	  ireg = reg1;	}      else	{	  breg = reg1;	  ireg = reg2;	}      if (addr != 0)	output_address (addr);      if (breg != 0)	{	  if (GET_CODE (breg) != REG)	    abort ();	  fprintf (file, "(%s)", reg_names[REGNO (breg)]);	}      if (ireg != 0)	{	  if (GET_CODE (ireg) == MULT)	    ireg = XEXP (ireg, 0);	  if (GET_CODE (ireg) != REG)	    abort ();	  abort();	  fprintf (file, "[%s]", reg_names[REGNO (ireg)]);	}      break;    default:      output_addr_const_pdp11 (file, addr);    }}/* register move costs, indexed by regs */static int move_costs[N_REG_CLASSES][N_REG_CLASSES] = {             /* NO  MUL  GEN  LFPU  NLFPU FPU ALL *//* NO */     {  0,   0,   0,    0,    0,    0,   0},/* MUL */    {  0,   2,   2,   10,   22,   22,  22},/* GEN */    {  0,   2,   2,   10,   22,   22,  22},/* LFPU */   {  0,  10,  10,    2,    2,    2,  10},/* NLFPU */  {  0,  22,  22,    2,    2,    2,  22},/* FPU */    {  0,  22,  22,    2,    2,    2,  22},/* ALL */    {  0,  22,  22,   10,   22,   22,  22}}  ;/* -- note that some moves are tremendously expensive,    because they require lots of tricks! do we have to    charge the costs incurred by secondary reload class    -- as we do here with 22 -- or not ? */int register_move_cost(c1, c2)  enum reg_class c1, c2;{    return move_costs[(int)c1][(int)c2];}char *output_jump(pos, neg, length)  int length;  char *pos, *neg;{    static int x = 0;        static char buf[1000];#if 0/* currently we don't need this, because the tstdf and cmpdf    copy the condition code immediately, and other float operations are not    yet recognized as changing the FCC - if so, then the length-cost of all   jump insns increases by one, because we have to potentially copy the    FCC! */    if (cc_status.flags & CC_IN_FPU)	output_asm_insn("cfcc", NULL);#endif	    switch (length)    {      case 1:		strcpy(buf, pos);	strcat(buf, " %l0");		return buf;	      case 3:		sprintf(buf, "%s JMP_%d\n\tjmp %%l0\nJMP_%d:", neg, x, x);		x++;		return buf;	      default:		abort();    }    }voidnotice_update_cc_on_set(exp, insn)  rtx exp;  rtx insn;{    if (GET_CODE (SET_DEST (exp)) == CC0)    { 	cc_status.flags = 0;						cc_status.value1 = SET_DEST (exp);				cc_status.value2 = SET_SRC (exp);			/*	if (GET_MODE(SET_SRC(exp)) == DFmode)	    cc_status.flags |= CC_IN_FPU;*/	    }							    else if ((GET_CODE (SET_DEST (exp)) == REG			      || GET_CODE (SET_DEST (exp)) == MEM)			     && GET_CODE (SET_SRC (exp)) != PC			     && (GET_MODE (SET_DEST(exp)) == HImode				 || GET_MODE (SET_DEST(exp)) == QImode)			&& (GET_CODE (SET_SRC(exp)) == PLUS				    || GET_CODE (SET_SRC(exp)) == MINUS			    || GET_CODE (SET_SRC(exp)) == AND			    || GET_CODE (SET_SRC(exp)) == IOR			    || GET_CODE (SET_SRC(exp)) == XOR			    || GET_CODE (SET_SRC(exp)) == NOT			    || GET_CODE (SET_SRC(exp)) == NEG				|| GET_CODE (SET_SRC(exp)) == REG			    || GET_CODE (SET_SRC(exp)) == MEM))	    { 	cc_status.flags = 0;						cc_status.value1 = SET_SRC (exp);   				cc_status.value2 = SET_DEST (exp);					if (cc_status.value1 && GET_CODE (cc_status.value1) == REG		    && cc_status.value2						    && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))    	    cc_status.value2 = 0;						if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM		    && cc_status.value2						    && GET_CODE (cc_status.value2) == MEM)				    cc_status.value2 = 0; 					    }							    else if (GET_CODE (SET_SRC (exp)) == CALL)		    { 	CC_STATUS_INIT;     }    else if (GET_CODE (SET_DEST (exp)) == REG)       			/* what's this ? */					    { 	if ((cc_status.value1						     && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)))	    cc_status.value1 = 0;					if ((cc_status.value2						     && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)))

⌨️ 快捷键说明

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