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

📄 thumb.md

📁 gcc-2.95.3 Linux下最常用的C编译器
💻 MD
📖 第 1 页 / 共 3 页
字号:
;; thumb.md	Machine description for ARM/Thumb processors;; Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.;; The basis of this contribution was generated by;;		Richard Earnshaw, Advanced RISC Machines Ltd;; This file is part of GNU CC.;; GNU CC is free software; you can redistribute it and/or modify;; it under the terms of the GNU General Public License as published by;; the Free Software Foundation; either version 2, or (at your option);; any later version.;; GNU CC is distributed in the hope that it will be useful,;; but WITHOUT ANY WARRANTY; without even the implied warranty of;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the;; GNU General Public License for more details.;; You should have received a copy of the GNU General Public License;; along with GNU CC; see the file COPYING.  If not, write to;; the Free Software Foundation, 59 Temple Place - Suite 330,;; Boston, MA 02111-1307, USA.;; LENGTH of an instruction is 2 bytes(define_attr "length" "" (const_int 2));; CONDS is set to UNCHANGED when an insn does not affect the condition codes;; Most insns change the condition codes(define_attr "conds" "changed,unchanged" (const_string "changed"));; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a;; distant label.(define_attr "far_jump" "yes,no" (const_string "no"));; Start with move insns(define_expand "movsi"  [(set (match_operand:SI 0 "general_operand" "")	(match_operand:SI 1 "general_operand" ""))]  ""  "  if (! (reload_in_progress || reload_completed))    {      if (GET_CODE (operands[0]) != REG)	operands[1] = force_reg (SImode, operands[1]);    }")(define_insn "*movsi_insn"  [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l,m,*r,*h")	(match_operand:SI 1 "general_operand" "l,I,J,K,>,l,mi,l,*h,*r"))]  "register_operand (operands[0], SImode)    || register_operand (operands[1], SImode)"  "@   add\\t%0, %1, #0   mov\\t%0, %1   #   #   ldmia\\t%1, {%0}   stmia\\t%0, {%1}   ldr\\t%0, %1   str\\t%1, %0   mov\\t%0, %1   mov\\t%0, %1"[(set_attr "length" "2,2,4,4,2,2,2,2,2,2")])(define_split   [(set (match_operand:SI 0 "register_operand" "")	(match_operand:SI 1 "const_int_operand" ""))]  "thumb_shiftable_const (INTVAL (operands[1]))"  [(set (match_dup 0) (match_dup 1))   (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]  "{  unsigned HOST_WIDE_INT val = INTVAL (operands[1]);  unsigned HOST_WIDE_INT mask = 0xff;  int i;  for (i = 0; i < 25; i++)    if ((val & (mask << i)) == val)      break;  if (i == 0)    FAIL;  operands[1] = GEN_INT (val >> i);  operands[2] = GEN_INT (i);}")(define_split   [(set (match_operand:SI 0 "register_operand" "")	(match_operand:SI 1 "const_int_operand" ""))]  "INTVAL (operands[1]) < 0 && INTVAL (operands[1]) > -256"  [(set (match_dup 0) (match_dup 1))   (set (match_dup 0) (neg:SI (match_dup 0)))]  "  operands[1] = GEN_INT (- INTVAL (operands[1]));");;(define_expand "reload_outsi";;  [(set (match_operand:SI 2 "register_operand" "=&l");;	(match_operand:SI 1 "register_operand" "h"));;   (set (match_operand:SI 0 "reload_memory_operand" "=o");;	(match_dup 2))];;  "";;  ";;/*  thumb_reload_out_si (operands);;;  DONE; */;;")(define_expand "movhi"  [(set (match_operand:HI 0 "general_operand" "")	(match_operand:HI 1 "general_operand" ""))]  ""  "{  if (! (reload_in_progress || reload_completed))    {      if (GET_CODE (operands[0]) != REG)	operands[1] = force_reg (HImode, operands[1]);      /* ??? We shouldn't really get invalid addresses here, but this can	 happen if we are passed a SP (never OK for HImode/QImode) or virtual	register (rejected by GO_IF_LEGITIMATE_ADDRESS for HImode/QImode)	relative address.  */      /* ??? This should perhaps be fixed elsewhere, for instance, in	 fixup_stack_1, by checking for other kinds of invalid addresses,	 e.g. a bare reference to a virtual register.  This may confuse the	 alpha though, which must handle this case differently.  */      if (GET_CODE (operands[0]) == MEM	  && ! memory_address_p (GET_MODE (operands[0]),				 XEXP (operands[0], 0)))	{	  rtx temp = copy_to_reg (XEXP (operands[0], 0));	  operands[0] = change_address (operands[0], VOIDmode, temp);	}      if (GET_CODE (operands[1]) == MEM	  && ! memory_address_p (GET_MODE (operands[1]),				 XEXP (operands[1], 0)))	{	  rtx temp = copy_to_reg (XEXP (operands[1], 0));	  operands[1] = change_address (operands[1], VOIDmode, temp);	}    }  /* Handle loading a large integer during reload */  else if (GET_CODE (operands[1]) == CONST_INT	   && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))    {      /* Writing a constant to memory needs a scratch, which should	 be handled with SECONDARY_RELOADs.  */      if (GET_CODE (operands[0]) != REG)	abort ();      operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);      emit_insn (gen_movsi (operands[0], operands[1]));      DONE;    }}")(define_insn "*movhi_insn"  [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")	(match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]  "register_operand (operands[0], HImode)   || register_operand (operands[1], HImode)"  "@   add\\t%0, %1, #0   ldrh\\t%0, %1   strh\\t%1, %0   mov\\t%0, %1   mov\\t%0, %1   mov\\t%0, %1")(define_expand "movqi"  [(set (match_operand:QI 0 "general_operand" "")	(match_operand:QI 1 "general_operand" ""))]  ""  "{  if (! (reload_in_progress || reload_completed))    {      if (GET_CODE (operands[0]) != REG)	operands[1] = force_reg (QImode, operands[1]);      /* ??? We shouldn't really get invalid addresses here, but this can	 happen if we are passed a SP (never OK for HImode/QImode) or virtual	register (rejected by GO_IF_LEGITIMATE_ADDRESS for HImode/QImode)	relative address.  */      /* ??? This should perhaps be fixed elsewhere, for instance, in	 fixup_stack_1, by checking for other kinds of invalid addresses,	 e.g. a bare reference to a virtual register.  This may confuse the	 alpha though, which must handle this case differently.  */      if (GET_CODE (operands[0]) == MEM	  && ! memory_address_p (GET_MODE (operands[0]),				 XEXP (operands[0], 0)))	{	  rtx temp = copy_to_reg (XEXP (operands[0], 0));	  operands[0] = change_address (operands[0], VOIDmode, temp);	}      if (GET_CODE (operands[1]) == MEM	  && ! memory_address_p (GET_MODE (operands[1]),				 XEXP (operands[1], 0)))	{	  rtx temp = copy_to_reg (XEXP (operands[1], 0));	  operands[1] = change_address (operands[1], VOIDmode, temp);	}    }  /* Handle loading a large integer during reload */  else if (GET_CODE (operands[1]) == CONST_INT	   && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))    {      /* Writing a constant to memory needs a scratch, which should	 be handled with SECONDARY_RELOADs.  */      if (GET_CODE (operands[0]) != REG)	abort ();      operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);      emit_insn (gen_movsi (operands[0], operands[1]));      DONE;    }}")(define_insn "*movqi_insn"  [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")	(match_operand:QI 1 "general_operand" "l,m,l,*h,*r,I"))]  "register_operand (operands[0], QImode)   || register_operand (operands[1], QImode)"  "@   add\\t%0, %1, #0   ldrb\\t%0, %1   strb\\t%1, %0   mov\\t%0, %1   mov\\t%0, %1   mov\\t%0, %1")(define_expand "movdi"  [(set (match_operand:DI 0 "general_operand" "")	(match_operand:DI 1 "general_operand" ""))]  ""  "  if (! (reload_in_progress || reload_completed))    {      if (GET_CODE (operands[0]) != REG)	operands[1] = force_reg (DImode, operands[1]);    }");;; ??? This should have alternatives for constants.;;; ??? This was originally identical to the movdf_insn pattern.;;; ??? The 'i' constraint looks funny, but it should always be replaced by;;; thumb_reorg with a memory reference.(define_insn "*movdi_insn"  [(set (match_operand:DI 0 "general_operand" "=l,l,l,l,>,l,m,*r")	(match_operand:DI 1 "general_operand" "l,I,J,>,l,mi,l,*r"))]  "register_operand (operands[0], DImode)   || register_operand (operands[1], DImode)"  "*{  switch (which_alternative)    {    case 0:      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)	return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";      return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";    case 1:      return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";    case 2:      operands[1] = GEN_INT (- INTVAL (operands[1]));      return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";    case 3:      return \"ldmia\\t%1, {%0, %H0}\";    case 4:      return \"stmia\\t%0, {%1, %H1}\";    case 5:      return thumb_load_double_from_address (operands);    case 6:      operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[0], 0), 4));      output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);      return \"\";    case 7:      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)	return \"mov\\t%0, %1\;mov\\t%H0, %H1\";      return \"mov\\t%H0, %H1\;mov\\t%0, %1\";    }}"[(set_attr "length" "4,4,6,2,2,6,4,4")])(define_expand "movdf"  [(set (match_operand:DF 0 "general_operand" "")	(match_operand:DF 1 "general_operand" ""))]  ""  "  if (! (reload_in_progress || reload_completed))    {      if (GET_CODE (operands[0]) != REG)	operands[1] = force_reg (DFmode, operands[1]);    }");;; ??? This should have alternatives for constants.;;; ??? This was originally identical to the movdi_insn pattern.;;; ??? The 'F' constraint looks funny, but it should always be replaced by;;; thumb_reorg with a memory reference.(define_insn "*movdf_insn"  [(set (match_operand:DF 0 "general_operand" "=l,l,>,l,m,*r")	(match_operand:DF 1 "general_operand"  "l,>,l,mF,l,*r"))]  "register_operand (operands[0], DFmode)   || register_operand (operands[1], DFmode)"  "*  switch (which_alternative)    {    case 0:      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)	return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";      return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";    case 1:      return \"ldmia\\t%1, {%0, %H0}\";    case 2:      return \"stmia\\t%0, {%1, %H1}\";    case 3:      return thumb_load_double_from_address (operands);    case 4:      operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[0], 0), 4));      output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);      return \"\";    case 5:      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)	return \"mov\\t%0, %1\;mov\\t%H0, %H1\";      return \"mov\\t%H0, %H1\;mov\\t%0, %1\";    }"[(set_attr "length" "4,2,2,6,4,4")])(define_expand "movsf"  [(set (match_operand:SF 0 "general_operand" "")	(match_operand:SF 1 "general_operand" ""))]  ""  "  if (! (reload_in_progress || reload_completed))    {      if (GET_CODE (operands[0]) != REG)	operands[1] = force_reg (SFmode, operands[1]);    }");;; ??? This should have alternatives for constants.(define_insn "*movsf_insn"  [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l,m,*r,*h")	(match_operand:SF 1 "general_operand"       "l,>,l,mF,l,*h,*r"))]  "register_operand (operands[0], SFmode)    || register_operand (operands[1], SFmode)"  "@   add\\t%0, %1, #0   ldmia\\t%1, {%0}   stmia\\t%0, {%1}   ldr\\t%0, %1   str\\t%1, %0   mov\\t%0, %1   mov\\t%0, %1");; Widening move insns(define_expand "zero_extendhisi2"  [(set (match_operand:SI 0 "register_operand" "")	(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]  ""  "  if (GET_CODE (operands[1]) != MEM)    {      rtx temp = gen_reg_rtx (SImode);            operands[1] = force_reg (HImode, operands[1]);      operands[1] = gen_lowpart (SImode, operands[1]);      emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (16)));      emit_insn (gen_lshrsi3 (operands[0], temp, GEN_INT (16)));      DONE;    }")(define_insn "*zero_extendhisi2_insn"  [(set (match_operand:SI 0 "register_operand" "=l")	(zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]  ""  "ldrh\\t%0, %1")(define_expand "zero_extendqisi2"  [(set (match_operand:SI 0 "register_operand" "")	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]  ""  "  if (GET_CODE (operands[1]) != MEM)    {      rtx temp = gen_reg_rtx (SImode);

⌨️ 快捷键说明

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