sparc.md

来自「GCC编译器源代码」· Markdown 代码 · 共 2,069 行 · 第 1/5 页

MD
2,069
字号
  else if (GET_CODE (operands[2]) == CONST_INT	   && HOST_BITS_PER_WIDE_INT > 32	   && INTVAL (operands[2]) > 0xffffffff)    operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffffffff);  /* Note that we use add here.  This is important because Medium/Anywhere     code model support depends on it.  */  return \"add %1,%%lo(%a2),%0\";}"  ;; Need to set length for this arith insn because operand2  ;; is not an "arith_operand".  [(set_attr "length" "1")])(define_insn "*sethi_di_sp32"  [(set (match_operand:DI 0 "register_operand" "=r")	(high:DI (match_operand 1 "" "")))]  "! TARGET_ARCH64 && check_pic (1)"  "*{  rtx op0 = operands[0];  rtx op1 = operands[1];  if (GET_CODE (op1) == CONST_INT)    {      operands[0] = operand_subword (op0, 1, 0, DImode);      output_asm_insn (\"sethi %%hi(%a1),%0\", operands);      operands[0] = operand_subword (op0, 0, 0, DImode);      if (INTVAL (op1) < 0)	return \"mov -1,%0\";      else	return \"mov 0,%0\";    }  else if (GET_CODE (op1) == CONST_DOUBLE)    {      operands[0] = operand_subword (op0, 1, 0, DImode);      operands[1] = GEN_INT (CONST_DOUBLE_LOW (op1));      output_asm_insn (\"sethi %%hi(%a1),%0\", operands);      operands[0] = operand_subword (op0, 0, 0, DImode);      operands[1] = GEN_INT (CONST_DOUBLE_HIGH (op1));      return singlemove_string (operands);    }  else    abort ();  return \"\";}"  [(set_attr "type" "move")   (set_attr "length" "2")]);;; ??? This pattern originally clobbered a scratch register.  However, this;;; is invalid, the movdi pattern may not use a temp register because it;;; may be called from reload to reload a DImode value.  In that case, we;;; end up with a scratch register that never gets allocated.  To avoid this,;;; we use global register 1 which is never otherwise used by gcc as a temp.;;; The correct solution here might be to force DImode constants to memory,;;; e.g. by using a toc like the romp and rs6000 ports do for addresses, reg;;; 1 will then no longer need to be considered a fixed reg.(define_expand "sethi_di_sp64"  [(parallel     [(set (match_operand:DI 0 "register_operand" "")	   (high:DI (match_operand 1 "general_operand" "")))      (clobber (reg:DI 1))])]  "TARGET_ARCH64"  "")(define_insn "*sethi_di_sp64_const"  [(set (match_operand:DI 0 "register_operand" "=r")	(high:DI (match_operand 1 "const_double_operand" "")))   (clobber (reg:DI 1))]  "TARGET_ARCH64 && check_pic (1)"  "*{#if HOST_BITS_PER_WIDE_INT == 32  rtx high, low;    split_double (operands[1], &high, &low);  if (high == const0_rtx)    {      operands[1] = low;      output_asm_insn (\"sethi %%hi(%a1),%0\", operands);    }  else    {      operands[1] = high;      output_asm_insn (singlemove_string (operands), operands);      operands[1] = low;      output_asm_insn (\"sllx %0,32,%0\", operands);      if (low != const0_rtx)	output_asm_insn (\"sethi %%hi(%a1),%%g1; or %0,%%g1,%0\", operands);    }#else  rtx op = operands[1];  if (! SPARC_SETHI_P (INTVAL(op)))    {      operands[1] = GEN_INT (INTVAL (op) >> 32);      output_asm_insn (singlemove_string (operands), operands);      output_asm_insn (\"sllx %0,32,%0\", operands);      if (INTVAL (op) & 0xffffffff)	{	  operands[1] = GEN_INT (INTVAL (op) & 0xffffffff);	  output_asm_insn (\"sethi %%hi(%a1),%%g1; or %0,%%g1,%0\", operands);	}    }  else    {      output_asm_insn (\"sethi %%hi(%a1),%0\", operands);    }#endif  return \"\";}"  [(set_attr "type" "move")   (set_attr "length" "5")]);; Most of the required support for the various code models is here.;; We can do this because sparcs need the high insn to load the address.  We;; just need to get high to do the right thing for each code model.  Then each;; uses the same "%X+%lo(...)" in the load/store insn, though in the case of;; the medium/middle code model "%lo" is written "%l44".;; When TARGET_CM_MEDLOW, assume that the upper 32 bits of symbol addresses are;; always 0.;; When TARGET_CM_MEDMID, the executable must be in the low 16 TB of memory.;; This corresponds to the low 44 bits, and the %[hml]44 relocs are used.;; ??? Not implemented yet.;; When TARGET_CM_EMBMEDANY, the text and data segments have a maximum size of;; 31 bits and may be located anywhere.  EMBMEDANY_BASE_REG contains the start;; address of the data segment, currently %g4.;; When TARGET_CM_MEDANY, the text and data segments have a maximum size of 31;; bits and may be located anywhere.  The maximum offset from any instruction;; to the label _GLOBAL_OFFSET_TABLE_ is 31 bits.(define_insn "*sethi_di_medlow"  [(set (match_operand:DI 0 "register_operand" "=r")	(high:DI (match_operand 1 "" "")))  ;; The clobber is here because emit_move_sequence assumes the worst case.   (clobber (reg:DI 1))]  "TARGET_CM_MEDLOW && check_pic (1)"  "sethi %%hi(%a1),%0"  [(set_attr "type" "move")   (set_attr "length" "1")])(define_insn "*sethi_di_medium_pic"  [(set (match_operand:DI 0 "register_operand" "=r")	(high:DI (match_operand 1 "sp64_medium_pic_operand" "")))]  "(TARGET_CM_MEDLOW || TARGET_CM_EMBMEDANY) && check_pic (1)"  "sethi %%hi(%a1),%0"  [(set_attr "type" "move")   (set_attr "length" "1")]);; WARNING: %0 gets %hi(%1)+%g4.;;          You cannot OR in %lo(%1), it must be added in.(define_insn "*sethi_di_embmedany_data"  [(set (match_operand:DI 0 "register_operand" "=r")	(high:DI (match_operand 1 "data_segment_operand" "")))  ;; The clobber is here because emit_move_sequence assumes the worst case.   (clobber (reg:DI 1))]  "TARGET_CM_EMBMEDANY && check_pic (1)"  "sethi %%hi(%a1),%0; add %0,%_,%0"  [(set_attr "type" "move")   (set_attr "length" "2")])(define_insn "*sethi_di_embmedany_text"  [(set (match_operand:DI 0 "register_operand" "=r")	(high:DI (match_operand 1 "text_segment_operand" "")))  ;; The clobber is here because emit_move_sequence assumes the worst case.   (clobber (reg:DI 1))]  "TARGET_CM_EMBMEDANY && check_pic (1)"  "sethi %%uhi(%a1),%%g1; or %%g1,%%ulo(%a1),%%g1; sllx %%g1,32,%%g1; sethi %%hi(%a1),%0; or %0,%%g1,%0"  [(set_attr "type" "move")   (set_attr "length" "5")]);; Move instructions(define_expand "movqi"  [(set (match_operand:QI 0 "general_operand" "")	(match_operand:QI 1 "general_operand" ""))]  ""  "{  if (emit_move_sequence (operands, QImode))    DONE;}")(define_insn "*movqi_insn"  [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")	(match_operand:QI 1 "move_operand" "rI,K,Q,rJ"))]  "! TARGET_LIVE_G0   && (register_operand (operands[0], QImode)       || register_operand (operands[1], QImode)       || operands[1] == const0_rtx)"  "@   mov %1,%0   sethi %%hi(%a1),%0   ldub %1,%0   stb %r1,%0"  [(set_attr "type" "move,move,load,store")   (set_attr "length" "1")])(define_insn "*movqi_insn_liveg0"  [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q")	(match_operand:QI 1 "move_operand" "r,J,I,K,Q,r"))]  "TARGET_LIVE_G0   && (register_operand (operands[0], QImode)       || register_operand (operands[1], QImode))"  "@   mov %1,%0   and %0,0,%0   and %0,0,%0\;or %0,%1,%0   sethi %%hi(%a1),%0   ldub %1,%0   stb %1,%0"  [(set_attr "type" "move,move,move,move,load,store")   (set_attr "length" "1,1,2,1,1,1")])(define_insn "*lo_sum_qi"  [(set (match_operand:QI 0 "register_operand" "=r")	(subreg:QI (lo_sum:SI (match_operand:QI 1 "register_operand" "r")			      (match_operand 2 "immediate_operand" "in")) 0))]  ""  "or %1,%%lo(%a2),%0"  [(set_attr "length" "1")])(define_insn "*store_qi"  [(set (mem:QI (match_operand:SI 0 "symbolic_operand" ""))	(match_operand:QI 1 "reg_or_0_operand" "rJ"))   (clobber (match_scratch:SI 2 "=&r"))]  "(reload_completed || reload_in_progress)   && ! TARGET_PTR64"  "sethi %%hi(%a0),%2\;stb %r1,[%2+%%lo(%a0)]"  [(set_attr "type" "store")   (set_attr "length" "2")])(define_expand "movhi"  [(set (match_operand:HI 0 "general_operand" "")	(match_operand:HI 1 "general_operand" ""))]  ""  "{  if (emit_move_sequence (operands, HImode))    DONE;}")(define_insn "*movhi_insn"  [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")	(match_operand:HI 1 "move_operand" "rI,K,Q,rJ"))]  "! TARGET_LIVE_G0   && (register_operand (operands[0], HImode)       || register_operand (operands[1], HImode)       || operands[1] == const0_rtx)"  "@   mov %1,%0   sethi %%hi(%a1),%0   lduh %1,%0   sth %r1,%0"  [(set_attr "type" "move,move,load,store")   (set_attr "length" "1")])(define_insn "*movhi_insn_liveg0"  [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q")	(match_operand:HI 1 "move_operand" "r,J,I,K,Q,r"))]  "TARGET_LIVE_G0   && (register_operand (operands[0], HImode)       || register_operand (operands[1], HImode))"  "@   mov %1,%0   and %0,0,%0   and %0,0,%0\;or %0,%1,%0   sethi %%hi(%a1),%0   lduh %1,%0   sth %1,%0"  [(set_attr "type" "move,move,move,move,load,store")   (set_attr "length" "1,1,2,1,1,1")])(define_insn "*lo_sum_hi"  [(set (match_operand:HI 0 "register_operand" "=r")	(lo_sum:HI (match_operand:HI 1 "register_operand" "r")		   (match_operand 2 "immediate_operand" "in")))]  ""  "or %1,%%lo(%a2),%0"  [(set_attr "length" "1")])(define_insn "*store_hi"  [(set (mem:HI (match_operand:SI 0 "symbolic_operand" ""))	(match_operand:HI 1 "reg_or_0_operand" "rJ"))   (clobber (match_scratch:SI 2 "=&r"))]  "(reload_completed || reload_in_progress)   && ! TARGET_PTR64"  "sethi %%hi(%a0),%2\;sth %r1,[%2+%%lo(%a0)]"  [(set_attr "type" "store")   (set_attr "length" "2")])(define_expand "movsi"  [(set (match_operand:SI 0 "general_operand" "")	(match_operand:SI 1 "general_operand" ""))]  ""  "{  if (emit_move_sequence (operands, SImode))    DONE;}");; We must support both 'r' and 'f' registers here, because combine may;; convert SFmode hard registers to SImode hard registers when simplifying;; subreg sets.;; We cannot combine the similar 'r' and 'f' constraints, because it causes;; problems with register allocation.  Reload might try to put an integer;; in an fp register, or an fp number is an integer register.(define_insn "*movsi_insn"  [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,f,r,r,f,Q,Q")	(match_operand:SI 1 "move_operand" "rI,!f,K,Q,!Q,rJ,!f"))]  "! TARGET_LIVE_G0   && (register_operand (operands[0], SImode)       || register_operand (operands[1], SImode)       || operands[1] == const0_rtx)"  "@   mov %1,%0   fmovs %1,%0   sethi %%hi(%a1),%0   ld %1,%0   ld %1,%0   st %r1,%0   st %1,%0"  [(set_attr "type" "move,fp,move,load,fpload,store,fpstore")   (set_attr "length" "1")])(define_insn "*movsi_insn_liveg0"  [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,f,r,r,f,Q,Q")	(match_operand:SI 1 "move_operand" "r,J,I,!f,K,Q,!Q,r,!f"))]  "TARGET_LIVE_G0   && (register_operand (operands[0], SImode)       || register_operand (operands[1], SImode))"  "@   mov %1,%0   and %0,0,%0   and %0,0,%0\;or %0,%1,%0   fmovs %1,%0   sethi %%hi(%a1),%0   ld %1,%0   ld %1,%0   st %1,%0   st %1,%0"  [(set_attr "type" "move,move,move,fp,move,load,fpload,store,fpstore")   (set_attr "length" "1,1,2,1,1,1,1,1,1")])(define_insn "*store_si"  [(set (mem:SI (match_operand:SI 0 "symbolic_operand" ""))	(match_operand:SI 1 "reg_or_0_operand" "rJ"))   (clobber (match_scratch:SI 2 "=&r"))]  "(reload_completed || reload_in_progress)   && ! TARGET_PTR64"  "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]"  [(set_attr "type" "store")   (set_attr "length" "2")])(define_expand "movdi"  [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "")	(match_operand:DI 1 "general_operand" ""))]  ""  "{  if (emit_move_sequence (operands, DImode))    DONE;}")(define_insn "*movdi_sp32_insn"  [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,T,U,Q,r,r,?f,?f,?Q")	(match_operand:DI 1 "general_operand" "r,U,T,r,Q,i,f,Q,f"))]  "! TARGET_ARCH64   && (register_operand (operands[0], DImode)       || register_operand (operands[1], DImode)       || operands[1] == const0_rtx)"  "*{  if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))    return output_fp_move_double (operands);  return output_move_double (operands);}"  [(set_attr "type" "move,store,load,store,load,multi,fp,fpload,fpstore")   (set_attr "length" "2,1,1,3,3,3,2,3,3")]);;; ??? The trick used below can be extended to load any negative 32 bit;;; constant in two instructions.  Currently the compiler will use HIGH/LO_SUM;;; for anything not matching the HIK constraints, which results in 5;;; instructions.  Positive 32 bit constants can be loaded in the obvious way;;; with sethi/ori.  To extend the trick, in the xor instruction, use ;;; xor %o0, ((op1 & 0x3ff) | -0x400), %o0;;; This needs the original value of operands[1], not the inverted value.(define_insn "*movdi_sp64_insn"  [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q,?f,?f,?Q")	(match_operand:DI 1 "move_operand" "rI,K,Q,rJ,f,Q,f"))]  "TARGET_ARCH64   && (register_operand (operands[0], DImode)       || register_operand (operands[1], DImode)       || operands[1] == const0_rtx)"  "*{  switch (which_alternative)    {    case 0:      return \"mov %1,%0\";    case 1:      /* Sethi does not sign extend, so we must use a little

⌨️ 快捷键说明

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