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

📄 pdp11.c

📁 gcc-you can use this code to learn something about gcc, and inquire further into linux,
💻 C
📖 第 1 页 / 共 3 页
字号:
    output_asm_insn ("add $2,%0", &addreg1);  /* Do that word.  */  output_asm_insn (singlemove_string (latehalf), latehalf);  /* Undo the adds we just did.  */  if (addreg0)    output_asm_insn ("sub $2,%0", &addreg0);  if (addreg1)    output_asm_insn ("sub $2,%0", &addreg1);  return "";}/* Output assembler code to perform a quadword move insn   with operands OPERANDS.  */const char *output_move_quad (operands)     rtx *operands;{  enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;  rtx latehalf[2];  rtx addreg0 = 0, addreg1 = 0;  output_asm_insn(";/* movdi/df: %1 -> %0 */", operands);    if (REG_P (operands[0]))    optype0 = REGOP;  else if (offsettable_memref_p (operands[0]))    optype0 = OFFSOP;  else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)    optype0 = POPOP;  else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)    optype0 = PUSHOP;  else if (GET_CODE (operands[0]) == MEM)    optype0 = MEMOP;  else    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)	  {	      REAL_VALUE_TYPE r;	      REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);	      if (REAL_VALUES_EQUAL (r, dconst0))		  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] = adjust_address (operands[0], SImode, 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] = adjust_address (operands[1], SImode, 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;     const 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_MODIFY:    case PRE_DEC:      fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);      break;    case POST_MODIFY:    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);    }}/* Target hook to assemble integer objects.  We need to use the   pdp-specific version of output_addr_const.  */static boolpdp11_assemble_integer (x, size, aligned_p)     rtx x;     unsigned int size;     int aligned_p;{  if (aligned_p)    switch (size)      {      case 1:	fprintf (asm_out_file, "\t.byte\t");	output_addr_const_pdp11 (asm_out_file, x);	fprintf (asm_out_file, " /* char */\n");	return true;      case 2:	fprintf (asm_out_file, TARGET_UNIX_ASM ? "\t" : "\t.word\t");	output_addr_const_pdp11 (asm_out_file, x);	fprintf (asm_out_file, " /* short */\n");	return true;      }  return default_assemble_integer (x, size, aligned_p);}/* register move costs, indexed by regs */static const 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];}const char *output_jump(pos, neg, length)  const char *pos, *neg;  int length;{    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 ATTRIBUTE_UNUSED;{    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	

⌨️ 快捷键说明

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