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

📄 romp.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
  noperands = 1 + (op1 != 0) + (op2 != 0);  /* Compute hash code for entire expression and see if operation block     already exists.  */  hash = ((int) code << 13) + (hash0 << 2) + (hash1 << 1) + hash2;  hash %= FP_HASH_SIZE;  for (fpop = fp_hash_table[hash], last_fpop = 0;       fpop;       last_fpop = fpop, fpop = fpop->next_same_hash)    if (fpop->opcode == code && noperands == fpop->noperands	&& (op0 == 0 || rtx_equal_p (op0, fpop->ops[0]))	&& (op1 == 0 || rtx_equal_p (op1, fpop->ops[1]))	&& (op2 == 0 || rtx_equal_p (op2, fpop->ops[2])))      goto win;  /* We have never seen this operation before.  */  fpop = (struct fp_op *) oballoc (sizeof (struct fp_op));  fpop->mem_offset = data_offset;  fpop->opcode = code;  fpop->noperands = noperands;  fpop->ops[0] = op0;  fpop->ops[1] = op1;  fpop->ops[2] = op2;  /* Compute the size using the rules in Appendix A of the RT Linkage     Convention (4.3/RT-PSD:5) manual.  These rules are a bit ambiguous,     but if we guess wrong, it will effect only efficiency, not correctness. */  /* Size = 24 + 32 for each non-fp (or fr7) */  size = 24;  if (op0 && (GET_CODE (op0) != REG	      || ! FP_REGNO_P (REGNO (op0)) || REGNO (op0) == 23))    size += 32;  if (op1 && (GET_CODE (op1) != REG	      || ! FP_REGNO_P (REGNO (op1)) || REGNO (op1) == 23))    size += 32;  if (op2 && (GET_CODE (op2) != REG	      || ! FP_REGNO_P (REGNO (op2)) || REGNO (op2) == 23))    size += 32;  /* Size + 12 for each conversion.  First get operation mode.  */  if ((op0 && GET_MODE (op0) == DFmode)      || (op1 && GET_MODE (op1) == DFmode)      || (op2 && GET_MODE (op2) == DFmode))    opmode = DFmode;  else    opmode = SFmode;  if (op0 && GET_MODE (op0) != opmode)    size += 12;  if (op1 && GET_MODE (op1) != opmode)    size += 12;  if (op2 && GET_MODE (op2) != opmode)    size += 12;  /* 12 more if first and third operand types not the same. */  if (op2 && GET_MODE (op0) != GET_MODE (op2))    size += 12;  /* CMP and CMPT need additional.  Also, compute size of save/restore here. */  if (code == EQ)    size += 32;  else if (code == GE)    size += 64;  else if (code == USE || code == CLOBBER)    {      /* 34 + 24 for each additional register plus 8 if fr7 saved.  (We         call it 36 because we need to keep the block length a multiple	 of four.  */      size = 36 - 24;      for (i = 0; i <= 7; i++)	if (INTVAL (op0) & (1 << (7-i)))	  size += 24 + 8 * (i == 7);    }  /* We provide no general-purpose scratch registers.  */  size +=16;  /* No floating-point scratch registers are provided.  Compute extra     length due to this.  This logic is that shown in the referenced     appendix.  */  i = 0;  if (op0 && GET_CODE (op0) == REG && FP_REGNO_P (REGNO (op0)))    i++;  if (op1 && GET_CODE (op1) == REG && FP_REGNO_P (REGNO (op1)))    i++;  if (op2 && GET_CODE (op2) == REG && FP_REGNO_P (REGNO (op2)))    i++;  if ((op0 == 0 || GET_CODE (op0) != REG || REGNO(op0) != 17)      && (op1 == 0 || GET_CODE (op1) != REG || REGNO(op1) != 17)      && (op2 == 0 || GET_CODE (op2) != REG || REGNO(op2) != 17))    fr0_avail = 1;  if (dyadic)    {      if (i == 0)	size += fr0_avail ? 64 : 112;      else if (fpop->noperands == 2 && i == 1)	size += fr0_avail ? 0 : 64;      else if (fpop->noperands == 3)	{	  if (GET_CODE (op0) == REG && FP_REGNO_P (REGNO (op0))	      && GET_CODE (op2) == REG && FP_REGNO_P (REGNO (op2)))	    {	      if (REGNO (op0) == REGNO (op2))#if 1		/* This triggers a bug on the RT. */		abort ();#else		size += fr0_avail ? 0 : 64;#endif	    }	  else	    {	      i = 0;	      if (GET_CODE (op0) == REG && FP_REGNO_P (REGNO (op0)))		i++;	      if (GET_CODE (op2) == REG && FP_REGNO_P (REGNO (op2)))		i++;	      if (i == 0)		size += fr0_avail ? 64 : 112;	      else if (i == 1)		size += fr0_avail ? 0 : 64;	    }	}    }  else if (code != USE && code != CLOBBER	   && (GET_CODE (op0) != REG || ! FP_REGNO_P (REGNO (op0))))    size += 64;      if (! TARGET_FULL_FP_BLOCKS)    {      /* If we are not to pad the blocks, just compute its actual length.  */      size = 12;	/* Header + opcode */      if (code == USE || code == CLOBBER)        size += 2;      else        {	  if (op0) size += 2;	  if (op1) size += 2;	  if (op2) size += 2;	}      /* If in the middle of a word, round.  */      if (size % UNITS_PER_WORD)	size += 2;	      /* Handle any immediates.  */      if (code != USE && code != CLOBBER && op0 && GET_CODE (op0) != REG)        size += 4;      if (op1 && GET_CODE (op1) != REG)        size += 4;      if (op2 && GET_CODE (op2) != REG)        size += 4;      if (code != USE && code != CLOBBER && 	  op0 && GET_CODE (op0) == CONST_DOUBLE && GET_MODE (op0) == DFmode)        size += 4;      if (op1 && GET_CODE (op1) == CONST_DOUBLE && GET_MODE (op1) == DFmode)        size += 4;      if (op2 && GET_CODE (op2) == CONST_DOUBLE && GET_MODE (op2) == DFmode)        size += 4;    }  /* Done with size computation!  Chain this in. */  fpop->size = size;  data_offset += size / UNITS_PER_WORD;  fpop->next_in_mem = 0;  fpop->next_same_hash = 0;  if (last_fpop_in_mem)    last_fpop_in_mem->next_in_mem = fpop;  else    first_fpop = fpop;  last_fpop_in_mem = fpop;  if (last_fpop)    last_fpop->next_same_hash = fpop;  else    fp_hash_table[hash] = fpop;win:  /* FPOP describes the operation to be performed.  Return a string to branch     to it.  */  if (fpop->mem_offset < 32768 / UNITS_PER_WORD)    sprintf (outbuf, "cal r15,%d(r14)\n\tbalr%s r15,r15",	     fpop->mem_offset * UNITS_PER_WORD,	     dbr_sequence_length () ? "x" : "");  else    sprintf (outbuf, "get r15,$L%dF%d\n\tbalr%s r15,r15",	     subr_number, fpop->mem_offset * UNITS_PER_WORD,	     dbr_sequence_length () ? "x" : "");  return outbuf;}/* If necessary, output a floating-point operation to save or restore all   floating-point registers.   file is the file to write the operation to, CODE is USE for save, CLOBBER   for restore, and ADDR is the address of the same area, as RTL.  */static voidoutput_loadsave_fpregs (file, code, addr)     FILE *file;     enum rtx_code code;     rtx addr;{  register int i;  register int mask = 0;  for (i = 2 + (TARGET_FP_REGS != 0); i <= 7; i++)    if (regs_ever_live[i + 17])      mask |= 1 << (7 - i);  if (mask)    fprintf (file, "\t%s\n",	     output_fpop (code, gen_rtx (CONST_INT, VOIDmode, mask),				gen_rtx (MEM, Pmode, addr),				0, const0_rtx));}/* Output any floating-point operations at the end of the routine.  */static voidoutput_fpops (file)     FILE *file;{  register struct fp_op *fpop;  register int size_so_far;  register int i;  rtx immed[3];  if (first_fpop == 0)    return;  data_section ();  ASM_OUTPUT_ALIGN (file, 2);  for (fpop = first_fpop; fpop; fpop = fpop->next_in_mem)    {      if (fpop->mem_offset < 32768 / UNITS_PER_WORD)	fprintf (file, "# data area offset = %d\n",		 fpop->mem_offset * UNITS_PER_WORD);      else	fprintf (file, "L%dF%d:\n",		 subr_number, fpop->mem_offset * UNITS_PER_WORD);      fprintf (file, "\tcas r0,r15,r0\n");      fprintf (file, "\t.long FPGLUE\n");      switch (fpop->opcode)	{	case USE:	  fprintf (file, "\t.byte 0x1d\t# STOREM\n");	  break;	case CLOBBER:	  fprintf (file, "\t.byte 0x0f\t# LOADM\n");	  break;	case ABS:	  fprintf (file, "\t.byte 0x00\t# ABS\n");	  break;	case PLUS:	  fprintf (file, "\t.byte 0x02\t# ADD\n");	  break;	case EQ:	  fprintf (file, "\t.byte 0x07\t# CMP\n");	  break;	case GE:	  fprintf (file, "\t.byte 0x08\t# CMPT\n");	  break;	case DIV:	  fprintf (file, "\t.byte 0x0c\t# DIV\n");	  break;	case SET:	  fprintf (file, "\t.byte 0x14\t# MOVE\n");	  break;	case MULT:	  fprintf (file, "\t.byte 0x15\t# MUL\n");	  break;	case NEG:	  fprintf (file, "\t.byte 0x16\t# NEG\n");	  break;	case SQRT:	  fprintf (file, "\t.byte 0x1c\t# SQRT\n");	  break;	case MINUS:	  fprintf (file, "\t.byte 0x1e\t# SUB\n");	  break;	default:	  abort ();	}      fprintf (file, "\t.byte %d\n", fpop->noperands);      fprintf (file, "\t.short 0x8001\n");            if ((fpop->ops[0] == 0	   || GET_CODE (fpop->ops[0]) != REG || REGNO(fpop->ops[0]) != 17)	  && (fpop->ops[1] == 0 || GET_CODE (fpop->ops[1]) != REG	      || REGNO(fpop->ops[1]) != 17)	  && (fpop->ops[2] == 0 || GET_CODE (fpop->ops[2]) != REG	      || REGNO(fpop->ops[2]) != 17))	fprintf (file, "\t.byte %d, 0x80\n", fpop->size);      else	fprintf (file, "\t.byte %d, 0\n", fpop->size);      size_so_far = 12;      for (i = 0; i < fpop->noperands; i++)	{	  register int type;	  register int opbyte;	  register char *desc0;	  char desc1[50];	  immed[i] = 0;	  switch (GET_MODE (fpop->ops[i]))	    {	    case SImode:	    case VOIDmode:	      desc0 = "int";	      type = 0;	      break;	    case SFmode:	      desc0 = "float";	      type = 2;	      break;	    case DFmode:	      desc0 = "double";	      type = 3;	      break;	    default:	      abort ();	    }	  switch (GET_CODE (fpop->ops[i]))	    {	    case REG:	      strcpy(desc1, reg_names[REGNO (fpop->ops[i])]);	      if (FP_REGNO_P (REGNO (fpop->ops[i])))		{		  type += 0x10;		  opbyte = REGNO (fpop->ops[i]) - 17;		}	      else		{		  type += 0x00;		  opbyte = REGNO (fpop->ops[i]);		  if (type == 3)		    opbyte = (opbyte << 4) + opbyte + 1;		}	      break;	    case MEM:	      type += 0x30;	      if (GET_CODE (XEXP (fpop->ops[i], 0)) == PLUS)		{		  immed[i] = XEXP (XEXP (fpop->ops[i], 0), 1);		  opbyte = REGNO (XEXP (XEXP (fpop->ops[i], 0), 0));		  if (GET_CODE (immed[i]) == CONST_INT)		    sprintf (desc1, "%d(%s)", INTVAL (immed[i]),			     reg_names[opbyte]);		  else		    sprintf (desc1, "<memory> (%s)", reg_names[opbyte]);		}	      else if (GET_CODE (XEXP (fpop->ops[i], 0)) == REG)		{		  opbyte = REGNO (XEXP (fpop->ops[i], 0));		  immed[i] = const0_rtx; 		  sprintf (desc1, "(%s)", reg_names[opbyte]);		}	      else		{		  immed[i] = XEXP (fpop->ops[i], 0);		  opbyte = 0;		  sprintf(desc1, "<memory>");		}	      break;	    case CONST_INT:	    case CONST_DOUBLE:	    case CONST:	    case SYMBOL_REF:	    case LABEL_REF:	      type += 0x20;	      opbyte = 0;	      immed[i] = fpop->ops[i];	      desc1[0] = '$';	      desc1[1] = '\0';	      break;	    default:	      abort ();	    }	  /* Save/restore is special.  */	  if (i == 0 && (fpop->opcode == USE || fpop->opcode == CLOBBER))	    type = 0xff, opbyte = INTVAL (fpop->ops[0]), immed[i] = 0;	  fprintf (file, "\t.byte 0x%x,0x%x # (%s) %s\n",		   type, opbyte, desc0, desc1);	  size_so_far += 2;	}      /* If in the middle of a word, round.  */      if (size_so_far % UNITS_PER_WORD)	{	  fprintf (file, "\t.space 2\n");	  size_so_far += 2;	}      for (i = 0; i < fpop->noperands; i++)	if (immed[i])	  switch (GET_MODE (immed[i]))	    {	    case SImode:	    case VOIDmode:	      size_so_far += 4;	      fprintf (file, "\t.long ");	      output_addr_const (file, immed[i]);	      fprintf (file, "\n");	      break;	    case DFmode:	      size_so_far += 4;	    case SFmode:	      size_so_far += 4;	      if (GET_CODE (immed[i]) == CONST_DOUBLE)		{		  union real_extract u;		  bcopy (&CONST_DOUBLE_LOW (immed[i]), &u, sizeof u);		  if (GET_MODE (immed[i]) == DFmode)		    ASM_OUTPUT_DOUBLE (file, u.d);		  else		    ASM_OUTPUT_FLOAT (file, u.d);		}	      else		abort ();	      break;	    default:	      abort ();	    }	      if (size_so_far != fpop->size)        {          if (TARGET_FULL_FP_BLOCKS)	    fprintf (file, "\t.space %d\n", fpop->size - size_so_far);	  else	    abort ();	}    }  /* Update for next subroutine.  */  subr_number++;  text_section ();} /* Initialize floating-point operation table.  */static voidinit_fpops(){  register int i;  first_fpop = last_fpop_in_mem = 0;  for (i = 0; i < FP_HASH_SIZE; i++)    fp_hash_table[i] = 0;}

⌨️ 快捷键说明

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