URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [config/] [cr16/] [cr16.md] - Rev 709
Compare with Previous | Blame | View Log
;; GCC machine description for CR16.;; Copyright (C) 2012 Free Software Foundation, Inc.;; Contributed by KPIT Cummins Infosystems Limited.;; This file is part of GCC.;; GCC 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 3, or (at your option);; any later version.;; GCC 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 GCC; see the file COPYING3. If not see;; <http://www.gnu.org/licenses/>.;; Register numbers(define_constants[(SP_REGNUM 15); Stack pointer(RA_REGNUM 14); Return address]);; Predicates & Constraints(include "predicates.md")(include "constraints.md");; UNSPEC usage(define_constants[(UNSPEC_PIC_ADDR 0)(UNSPEC_PIC_LOAD_ADDR 1)(UNSPEC_LIBRARY_OFFSET 2)(UNSPEC_SH_LIB_PUSH_R12 3)(UNSPEC_SH_LIB_POP_R12 4)(UNSPEC_RETURN_ADDR 5)]);; Attributes(define_attr "length" "" (const_int 2))(define_asm_attributes[(set_attr "length" "2")]);; Mode Macro Definitions(define_mode_iterator CR16IM [QI HI SI])(define_mode_iterator LONG [SI SF])(define_mode_iterator ALLMTD [QI HI SI SF DI DF])(define_mode_iterator DOUBLE [DI DF])(define_mode_iterator SHORT [QI HI])(define_mode_attr tIsa [(QI "b") (HI "w") (SI "d") (SF "d")])(define_mode_attr lImmArith [(QI "4") (HI "4") (SI "6") (SF "6")])(define_mode_attr lImmArithD [(QI "4") (HI "4") (SI "6") (SF "6") (DI "12") (DF "12")])(define_mode_attr iF [(QI "i") (HI "i") (SI "i") (SF "F")])(define_mode_attr iFD [(DI "i") (DF "F")])(define_mode_attr LL [(QI "L") (HI "L")])(define_mode_attr shImmBits [(QI "3") (HI "4") (SI "5")]); In QI mode we push 2 bytes instead of 1 byte.(define_mode_attr pushCnstr [(QI "X") (HI "<") (SI "<") (SF "<") (DI "<") (DF "<")]); tpush will be used to generate the 'number of registers to push' in the; push instruction.(define_mode_attr tpush [(QI "1") (HI "1") (SI "2") (SF "2") (DI "4") (DF "4")]);; Code Macro Definitions(define_code_attr sIsa [(sign_extend "") (zero_extend "u")])(define_code_attr sPat [(sign_extend "s") (zero_extend "u")])(define_code_attr szPat [(sign_extend "") (zero_extend "zero_")])(define_code_attr szIsa [(sign_extend "x") (zero_extend "z")])(define_code_iterator sz_xtnd [ sign_extend zero_extend])(define_code_iterator any_cond [eq ne gt gtu lt ltu ge geu le leu])(define_code_iterator plusminus [plus minus])(define_code_attr plusminus_insn [(plus "add") (minus "sub")])(define_code_attr plusminus_flag [(plus "PLUS") (minus "MINUS")])(define_code_attr comm [(plus "%") (minus "")])(define_code_iterator any_logic [and ior xor])(define_code_attr logic [(and "and") (ior "or") (xor "xor")])(define_code_attr any_logic_insn [(and "and") (ior "ior") (xor "xor")])(define_code_attr any_logic_flag [(and "AND") (ior "IOR") (xor "XOR")])(define_mode_iterator QH [QI HI])(define_mode_attr qh [(QI "qi") (HI "hi")])(define_mode_attr QHsz [(QI "2,2,2") (HI "2,2,4")])(define_mode_attr QHsuffix [(QI "b") (HI "w")]);; Function Prologue and Epilogue(define_expand "prologue"[(const_int 0)]""{cr16_expand_prologue ();DONE;})(define_insn "push_for_prologue"[(set (reg:SI SP_REGNUM)(minus:SI (reg:SI SP_REGNUM)(match_operand:SI 0 "immediate_operand" "i")))]"reload_completed"{return cr16_prepare_push_pop_string (0);}[(set_attr "length" "4")])(define_expand "epilogue"[(return)]""{cr16_expand_epilogue ();DONE;})(define_insn "pop_and_popret_return"[(set (reg:SI SP_REGNUM)(plus:SI (reg:SI SP_REGNUM)(match_operand:SI 0 "immediate_operand" "i")))(use (reg:SI RA_REGNUM))(return)]"reload_completed"{return cr16_prepare_push_pop_string (1);}[(set_attr "length" "4")])(define_insn "popret_RA_return"[(use (reg:SI RA_REGNUM))(return)]"reload_completed""popret\tra"[(set_attr "length" "2")]);; Arithmetic Instuction Patterns;; Addition-Subtraction "adddi3/subdi3" insns.(define_insn "<plusminus_insn>di3"[(set (match_operand:DI 0 "register_operand" "=r")(plusminus:DI (match_operand:DI 1 "register_operand" "<comm>0")(match_operand:DI 2 "register_operand" "r")))]""{return cr16_emit_add_sub_di (operands, <plusminus_flag>);})(define_insn "addsi3"[(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")(plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0")(match_operand:SI 2 "reg_si_int_operand" "r,M,N,O,i")))]"""addd\t%2, %0"[(set_attr "length" "2,2,4,4,6")]);; Addition-Subtraction "addhi3/subhi3" insns.(define_insn "<plusminus_insn>hi3"[(set (match_operand:HI 0 "register_operand" "=c,c,c")(plusminus:HI (match_operand:HI 1 "register_operand" "<comm>0,0,0")(match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]"""<plusminus_insn>w\t%2, %0"[(set_attr "length" "2,2,4")]);; Addition-Subtraction "addqi3/subqi3" insns.(define_insn "<plusminus_insn>qi3"[(set (match_operand:QI 0 "register_operand" "=c,c")(plusminus:QI (match_operand:QI 1 "register_operand" "<comm>0,0")(match_operand:QI 2 "reg_qi_int_operand" "c,M")))]"""<plusminus_insn>b\t%2, %0"[(set_attr "length" "2,2")]);; Subtract Instruction(define_insn "subsi3"[(set (match_operand:SI 0 "register_operand" "=r,r")(minus:SI (match_operand:SI 1 "register_operand" "0,0")(match_operand:SI 2 "reg_si_int_operand" "r,i")))]"""subd\t%2, %0"[(set_attr "length" "4,6")]);; Multiply and Accumulate Instructions "smachisi3/umachisi3"(define_insn "<sPat>maddhisi4"[(set (match_operand:SI 0 "register_operand" "=r")(plus:SI(mult:SI (sz_xtnd:SI (match_operand:HI 1 "register_operand" "r"))(sz_xtnd:SI (match_operand:HI 2 "register_operand" "r")))(match_operand:SI 3 "register_operand" "0")))]"TARGET_MAC""mac<sPat>w\t%1, %2, %0"[(set_attr "length" "2")]);; Multiply Instructions(define_insn "mulhi3"[(set (match_operand:HI 0 "register_operand" "=c,c,c")(mult:HI (match_operand:HI 1 "register_operand" "%0,0,0")(match_operand:HI 2 "reg_or_int_operand" "c,M,N")))]"""mulw\t%2, %0"[(set_attr "length" "2,2,4")])(define_insn "mulqihi3"[(set (match_operand:HI 0 "register_operand" "=c")(mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0"))(sign_extend:HI (match_operand:QI 2 "register_operand" "c"))))]"""mulsb\t%2, %0"[(set_attr "length" "2")]);; Bit Set/Clear Instructions(define_expand "insv"[(set (zero_extract (match_operand 0 "memory_operand" "")(match_operand 1 "immediate_operand" "")(match_operand 2 "immediate_operand" ""))(match_operand 3 "immediate_operand" ""))]"TARGET_BIT_OPS"{if (INTVAL (operands[1]) != 1)FAIL;if (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) > 15)FAIL;if (INTVAL (operands[3]) == 1){if (GET_MODE (operands[0]) == QImode){emit_insn (gen_set_bitqi (operands[0], operands[2]));DONE;}else if (GET_MODE (operands[0]) == HImode){emit_insn (gen_set_bithi (operands[0], operands[2]));DONE;}}if (INTVAL (operands[3]) == 0){if (GET_MODE (operands[0]) == QImode){emit_insn (gen_clr_bitqi (operands[0], operands[2]));DONE;}else if (GET_MODE (operands[0]) == HImode){emit_insn (gen_clr_bithi (operands[0], operands[2]));DONE;}}})(define_insn "set_bit<mode>"[(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m")(const_int 1)(match_operand 1 "immediate_operand" "i"))(const_int 1))]"TARGET_BIT_OPS""sbit<tIsa>\t%1,%0"[(set_attr "length" "2")])(define_insn "clr_bit<mode>"[(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m")(const_int 1)(match_operand 1 "immediate_operand" "i"))(const_int 0))]"TARGET_BIT_OPS""cbit<tIsa>\t%1,%0"[(set_attr "length" "2")])(define_insn "set_bit<mode>_mem"[(set (match_operand:SHORT 0 "bit_operand" "=m")(ior:SHORT (match_dup 0)(match_operand:SHORT 1 "one_bit_operand" "i")))]"TARGET_BIT_OPS""sbit<tIsa>\t$%s1,%0"[(set_attr "length" "2")])(define_insn "clear_bit<mode>_mem"[(set (match_operand:SHORT 0 "bit_operand" "=m")(and:SHORT (match_dup 0)(match_operand:SHORT 1 "rev_one_bit_operand" "i")))]"TARGET_BIT_OPS""cbit<tIsa>\t$%r1,%0"[(set_attr "length" "2")]);; Logical Instructions - and/ior/xor "anddi3/iordi3/xordi3"(define_insn "<any_logic_insn>di3"[(set (match_operand:DI 0 "register_operand" "=r")(any_logic:DI (match_operand:DI 1 "register_operand" "%0")(match_operand:DI 2 "register_operand" "r")))]""{return cr16_emit_logical_di (operands, <any_logic_flag>);}); Logical and/ior/xor "andsi3/iorsi3/xorsi3"(define_insn "<any_logic_insn>si3"[(set (match_operand:SI 0 "register_operand" "=r,r,r,r")(any_logic:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")(match_operand:SI 2 "reg_si_int_operand" "r,M,N,i")))]"""<logic>d\t%2, %0"[(set_attr "length" "2,2,4,6")]); Logical and/ior/xor in HImode "andhi3/iorhi3/xorhi3"; Logical and/ior/xor in QImode "andqi3/iorqi3/xorqi3"(define_insn "<any_logic_insn><qh>3"[(set (match_operand:QH 0 "register_operand" "=c,c,c")(any_logic:QH (match_operand:QH 1 "register_operand" "%0,0,0")(match_operand:QH 2 "reg_hi_int_operand" "c,M,N")))]"""<logic><QHsuffix>\t%2, %0"[(set_attr "length" "<QHsz>")]);; Sign and Zero Extend Instructions(define_insn "<szPat>extendhisi2"[(set (match_operand:SI 0 "register_operand" "=r")(sz_xtnd:SI (match_operand:HI 1 "register_operand" "r")))]"""mov<szIsa>w\t%1, %0"[(set_attr "length" "4")])(define_insn "<szPat>extendqihi2"[(set (match_operand:HI 0 "register_operand" "=r")(sz_xtnd:HI (match_operand:QI 1 "register_operand" "r")))]"""mov<szIsa>b\t%1, %0"[(set_attr "length" "4")]);; One's Complement(define_insn "one_cmpldi2"[(set (match_operand:DI 0 "register_operand" "=r")(not:DI (match_operand:DI 1 "register_operand" "0")))]""{rtx xoperand ;int reg0 = REGNO (operands[0]);xoperand = gen_rtx_REG (SImode, reg0 + 2);output_asm_insn ("xord\t$-1, %0", operands);output_asm_insn ("xord\t$-1, %0", &xoperand);return "" ;}[(set_attr "length" "12")])(define_insn "one_cmpl<mode>2"[(set (match_operand:CR16IM 0 "register_operand" "=r")(not:CR16IM (match_operand:CR16IM 1 "register_operand" "0")))]"""xor<tIsa>\t$-1, %0"[(set_attr "length" "2")]);; Arithmetic Left and Right Shift Instructions(define_insn "ashlqi3"[(set (match_operand:QI 0 "register_operand" "=c,c")(ashift:QI (match_operand:QI 1 "register_operand" "0,0")(match_operand:QI 2 "nonmemory_operand" "c,I")))]"""ashub\t%2, %0"[(set_attr "length" "2,2")])(define_insn "ashlhi3"[(set (match_operand:HI 0 "register_operand" "=c,c")(ashift:HI (match_operand:HI 1 "register_operand" "0,0")(match_operand:QI 2 "nonmemory_operand" "c,J")))]"""ashuw\t%2, %0"[(set_attr "length" "2,2")])(define_insn "ashlsi3"[(set (match_operand:SI 0 "register_operand" "=r,r")(ashift:SI (match_operand:SI 1 "register_operand" "0,0")(match_operand:QI 2 "nonmemory_operand" "r,K")))]"""ashud\t%2, %0"[(set_attr "length" "2,2")])(define_expand "ashr<mode>3"[(set (match_operand:CR16IM 0 "register_operand" "")(ashiftrt:CR16IM (match_operand:CR16IM 1 "register_operand" "")(match_operand:QI 2 "nonmemory_operand" "")))]""{if (GET_CODE (operands[2]) == CONST_INT){/* If the constant is not in range, try placing it in a reg */if (!UNSIGNED_INT_FITS_N_BITS(INTVAL (operands[2]),<shImmBits>))operands[2] = copy_to_mode_reg(QImode, operands[2]);}if (GET_CODE (operands[2]) != CONST_INT)operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));})(define_insn "ashrqi3_imm_insn"[(set (match_operand:QI 0 "register_operand" "=c")(ashiftrt:QI (match_operand:QI 1 "register_operand" "0")(match_operand:QI 2 "shift_qi_imm_operand" "i")))]"""ashub\t$%n2, %0"[(set_attr "length" "2")])(define_insn "ashrhi3_imm_insn"[(set (match_operand:HI 0 "register_operand" "=c")(ashiftrt:HI (match_operand:HI 1 "register_operand" "0")(match_operand:QI 2 "shift_hi_imm_operand" "i")))]"""ashuw\t$%n2, %0"[(set_attr "length" "2")])(define_insn "ashrsi3_imm_insn"[(set (match_operand:SI 0 "register_operand" "=r")(ashiftrt:SI (match_operand:SI 1 "register_operand" "0")(match_operand:QI 2 "shift_si_imm_operand" "i")))]"""ashud\t$%n2, %0"[(set_attr "length" "2")])(define_insn "ashrqi3_neg_insn"[(set (match_operand:QI 0 "register_operand" "=c")(ashiftrt:QI (match_operand:QI 1 "register_operand" "0")(neg:QI (match_operand:QI 2 "register_operand" "c"))))]"""ashub\t%2,%0"[(set_attr "length" "2")])(define_insn "ashrhi3_neg_insn"[(set (match_operand:HI 0 "register_operand" "=c")(ashiftrt:HI (match_operand:HI 1 "register_operand" "0")(neg:QI (match_operand:QI 2 "register_operand" "c"))))]"""ashuw\t%2,%0"[(set_attr "length" "2")])(define_insn "ashrdi3_neg_insn"[(set (match_operand:SI 0 "register_operand" "=r")(ashiftrt:SI (match_operand:SI 1 "register_operand" "0")(neg:QI (match_operand:QI 2 "register_operand" "r"))))]"""ashud\t%2,%0"[(set_attr "length" "2")])(define_expand "lshr<mode>3"[(set (match_operand:CR16IM 0 "register_operand" "")(lshiftrt:CR16IM (match_operand:CR16IM 1 "register_operand" "")(match_operand:QI 2 "reg_or_int_operand" "")))]""{if (GET_CODE (operands[2]) == CONST_INT){/* If the constant is not in range, try placing it in a reg */if (!UNSIGNED_INT_FITS_N_BITS(INTVAL (operands[2]),<shImmBits>))operands[2] = copy_to_mode_reg(QImode, operands[2]);}if (GET_CODE (operands[2]) != CONST_INT)operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));})(define_insn "lshrqi3_imm_insn"[(set (match_operand:QI 0 "register_operand" "=c")(lshiftrt:QI (match_operand:QI 1 "register_operand" "0")(match_operand:QI 2 "shift_qi_operand" "Q")))]"""lshb\t$%n2, %0"[(set_attr "length" "2")])(define_insn "lshrhi3_imm_insn"[(set (match_operand:HI 0 "register_operand" "=c")(lshiftrt:HI (match_operand:HI 1 "register_operand" "0")(match_operand:QI 2 "shift_hi_operand" "R")))]"""lshw\t$%n2, %0"[(set_attr "length" "2")])(define_insn "lshrsi3_imm_insn"[(set (match_operand:SI 0 "register_operand" "=r")(lshiftrt:SI (match_operand:SI 1 "register_operand" "0")(match_operand:QI 2 "shift_si_operand" "S")))]"""lshd\t$%n2, %0"[(set_attr "length" "2")])(define_insn "lshrqi3_neg_insn"[(set (match_operand:QI 0 "register_operand" "=c")(lshiftrt:QI (match_operand:QI 1 "register_operand" "0")(neg:QI (match_operand:QI 2 "register_operand" "c"))))]"""lshb\t%2,%0"[(set_attr "length" "2")])(define_insn "lshrhi3_neg_insn"[(set (match_operand:HI 0 "register_operand" "=c")(lshiftrt:HI (match_operand:HI 1 "register_operand" "0")(neg:QI (match_operand:QI 2 "register_operand" "c"))))]"""lshw\t%2,%0"[(set_attr "length" "2")])(define_insn "lshrsi3_neg_insn"[(set (match_operand:SI 0 "register_operand" "=r")(lshiftrt:SI (match_operand:SI 1 "register_operand" "0")(neg:QI (match_operand:QI 2 "register_operand" "r"))))]"""lshd\t%2,%0"[(set_attr "length" "2")]);; Move Instructions;; Move any non-immediate operand 0 to a general operand 1.;; This applies only before starting the reload process;; Operand 0 is not a register operand of type mode MODE;; If Operand 0 is a push operand of type mode MODE;; then, if Operand 1 is a non-SP register;; then, Operand 1 = copy_to_mode_reg (<MODE>mode, Operand 1);; endif;; else;; if Operand 1 is either register or 4-bit immediate constant;; then, Operand 1 = copy_to_mode_reg (<MODE>mode, Operand 1);; endif;; endif;;;; What does copy_to_mode_reg (mode, rtx val) do?;; Copy the value into new temp reg and return the reg where the;; mode of the new reg is always mode MODE when value is constant;;;; Why should copy_to_mode_reg be called?;; All sorts of move are nor supported by CR16. Therefore,;; when unsupported move is encountered, the additional instructions;; will be introduced for the purpose.;;;; A new move insn is inserted for Op 1 when one of the following;; conditions is met.;; Case 1: Op 0 is push_operand;; Op 1 is SP register;;;; Case 2: Op 0 is not push_operand;; Op 1 is neither register nor unsigned 4-bit immediate(define_expand "mov<mode>"[(set (match_operand:ALLMTD 0 "nonimmediate_operand" "")(match_operand:ALLMTD 1 "general_operand" ""))]""{if (!(reload_in_progress || reload_completed)){/* Only if Op0 is a register operand. */if (!register_operand (operands[0], <MODE>mode)){if (push_operand (operands[0], <MODE>mode)){/* Use copy_to_mode_reg only if the register needsto be pushed is SP as CR16 does not support pushing SP. */if (!nosp_reg_operand (operands[1], <MODE>mode))operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);}else{/* Use copy_to_mode_reg if op1 is not register operandsubject to conditions inside. */if (!register_operand (operands[1], <MODE>mode)){/* CR16 does not support moving immediate to SI or SFtype memory. */if (<MODE>mode == SImode || <MODE>mode == SFmode ||<MODE>mode == DImode || <MODE>mode == DFmode)operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);else/* moving imm4 is supported by CR16 instruction. */if (!u4bits_operand (operands[1], <MODE>mode))operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);}}}/* If operand-1 is a symbol, convert it into a BRO or GOT Format. */if (flag_pic && ! legitimate_pic_operand_p (operands[1])){operands[1] = legitimize_pic_address (operands[1], <MODE>mode, 0);}}}); ALLMT : QI,HI,SI,SF; pushCnstr : Push constraints; QI : X; HI,SI,SF,DI,DF : <; b : All non-sp registers; tpush : Push count; QI,HI : 1; SI,SF : 2; DI,DF : 4(define_insn "push<mode>_internal"[(set (match_operand:ALLMTD 0 "push_operand" "=<pushCnstr>")(match_operand:ALLMTD 1 "nosp_reg_operand" "b"))]"""push\t$<tpush>,%p1"[(set_attr "length" "2")]); (DI, DF) move(define_insn "*mov<mode>_double"[(set (match_operand:DOUBLE 0 "nonimmediate_operand" "=r, r, r, m")(match_operand:DOUBLE 1 "general_operand" "r, <iFD>, m, r"))]"register_operand (operands[0], DImode)|| register_operand (operands[0], DFmode)|| register_operand (operands[1], DImode)|| register_operand (operands[1], DFmode)"{if (0 == which_alternative) {rtx xoperands[2] ;int reg0 = REGNO (operands[0]);int reg1 = REGNO (operands[1]);xoperands[0] = gen_rtx_REG (SImode, reg0 + 2);xoperands[1] = gen_rtx_REG (SImode, reg1 + 2);if ((reg1 + 2) != reg0){output_asm_insn ("movd\t%1, %0", operands);output_asm_insn ("movd\t%1, %0", xoperands);}else{output_asm_insn ("movd\t%1, %0", xoperands);output_asm_insn ("movd\t%1, %0", operands);}}else if (1 == which_alternative) {rtx lo_operands[2] ;rtx hi_operands[2] ;lo_operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));hi_operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);lo_operands[1] = simplify_gen_subreg (SImode, operands[1],VOIDmode == GET_MODE (operands[1])? DImode : GET_MODE (operands[1]), 0);hi_operands[1] = simplify_gen_subreg (SImode, operands[1],VOIDmode == GET_MODE (operands[1])? DImode : GET_MODE (operands[1]), 4);output_asm_insn ("movd\t%1, %0", lo_operands);output_asm_insn ("movd\t%1, %0", hi_operands);}else if (2 == which_alternative) {rtx xoperands[2] ;int reg0 = REGNO (operands[0]), reg1 = -2 ;rtx addr ;if (MEM_P (operands[1]))addr = XEXP (operands[1], 0);elseaddr = NULL_RTX ;switch (GET_CODE (addr)){case REG:case SUBREG:reg1 = REGNO (addr);break ;case PLUS:switch (GET_CODE (XEXP (addr, 0))) {case REG:case SUBREG:reg1 = REGNO (XEXP (addr, 0));break ;case PLUS:reg1 = REGNO (XEXP (XEXP (addr, 0), 0));break ;default:inform (DECL_SOURCE_LOCATION (cfun->decl), "unexpected expression; addr:");debug_rtx (addr);inform (DECL_SOURCE_LOCATION (cfun->decl), "operands[1]:");debug_rtx (operands[1]);inform (DECL_SOURCE_LOCATION (cfun->decl), "generated code might now work\n");break ;}break ;default:break ;}xoperands[0] = gen_rtx_REG (SImode, reg0 + 2);xoperands[1] = offset_address (operands[1], GEN_INT (4), 2);gcc_assert ((reg0 + 1) != reg1);if (reg0 != reg1 && (reg1 + 1) != reg0){output_asm_insn ("loadd\t%1, %0", operands);output_asm_insn ("loadd\t%1, %0", xoperands);}else{output_asm_insn ("loadd\t%1, %0", xoperands);output_asm_insn ("loadd\t%1, %0", operands);}}else{rtx xoperands[2] ;xoperands[0] = offset_address (operands[0], GEN_INT (4), 2);xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);output_asm_insn ("stord\t%1, %0", operands);output_asm_insn ("stord\t%1, %0", xoperands);}return "" ;}[(set_attr "length" "4, <lImmArithD>, <lImmArithD>, <lImmArithD>")]); All long (SI, SF) register move, load and store operations; The print_operand will take care of printing the register pair; when mode is SI/SF and register is in SHORT_REGS(define_insn "*mov<mode>_long"[(set (match_operand:LONG 0 "nonimmediate_operand" "=r, r, r, m")(match_operand:LONG 1 "general_operand" "r, <iF>, m, r"))]"register_operand (operands[0], <MODE>mode)|| register_operand (operands[1], <MODE>mode)""@mov<tIsa>\t%1, %0mov<tIsa>\t%1, %0load<tIsa>\t%1, %0stor<tIsa>\t%1, %0"[(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>")]);; All short (QI, HI) register move, load and store operations(define_insn "*mov<mode>_short"[(set (match_operand:SHORT 0 "nonimmediate_operand" "=r, r, r, m, m")(match_operand:SHORT 1 "general_operand" "r, <iF>, m, r, <LL>"))]"(register_operand (operands[0], <MODE>mode))|| (store_operand (operands[0], <MODE>mode)&& (register_operand (operands[1], <MODE>mode)|| u4bits_operand (operands[1], <MODE>mode)))""@mov<tIsa>\t%1, %0mov<tIsa>\t%1, %0load<tIsa>\t%1, %0stor<tIsa>\t%1, %0stor<tIsa>\t%1, %0"[(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>,<lImmArith>")]);; Compare Instructions; Instruction generated compares the operands in reverse order; Therefore, while printing the asm, the reverse of the; compare condition shall be printed.(define_insn "cbranch<mode>4"[(set (pc)(if_then_else (match_operator 0 "ordered_comparison_operator"[(match_operand:CR16IM 1 "register_operand" "r,r")(match_operand:CR16IM 2 "nonmemory_operand" "r,n")])(label_ref (match_operand 3 "" ""))(pc)))(clobber (cc0))]"""cmp<tIsa>\t%2, %1\;b%d0\t%l3"[(set_attr "length" "6,6")])(define_expand "cmp<mode>"[(parallel [(set (cc0)(compare (match_operand:CR16IM 0 "register_operand" "")(match_operand:CR16IM 1 "nonmemory_operand" "")))(clobber (match_scratch:HI 2 "=r"))] ) ]"""");; Scond Instructions(define_expand "cstore<mode>4"[(set (cc0)(compare (match_operand:CR16IM 2 "register_operand" "")(match_operand:CR16IM 3 "nonmemory_operand" "")))(set (match_operand:HI 0 "register_operand")(match_operator:HI 1 "ordered_comparison_operator"[(cc0) (const_int 0)]))]"""")(define_insn "*cmp<mode>_insn"[(set (cc0)(compare (match_operand:CR16IM 0 "register_operand" "r,r")(match_operand:CR16IM 1 "nonmemory_operand" "r,n")))]"""cmp<tIsa>\t%1, %0"[(set_attr "length" "2,4")])(define_insn "sCOND_internal"[(set (match_operand:HI 0 "register_operand" "=r")(match_operator:HI 1 "ordered_comparison_operator"[(cc0) (const_int 0)]))]"""s%d1\t%0"[(set_attr "length" "2")]);; Jumps and Branches(define_insn "indirect_jump_return"[(set (pc)(reg:SI RA_REGNUM))(return)]"reload_completed""jump\t (ra)"[(set_attr "length" "2")])(define_insn "jump_return"[(unspec:SI [(const_int 0)] UNSPEC_RETURN_ADDR)(return)]"reload_completed""jump\t(ra)"[(set_attr "length" "2")])(define_insn "indirect_jump"[(set (pc)(match_operand:SI 0 "reg_or_sym_operand" "r,i"))]"""@jump\t%0br\t%a0"[(set_attr "length" "2,6")])(define_insn "interrupt_return"[(unspec_volatile [(const_int 0)] 0)(return)]""{return cr16_prepare_push_pop_string (1);}[(set_attr "length" "14")])(define_insn "jump_to_imm"[(set (pc)(match_operand 0 "jump_imm_operand" "i"))]"""br\t%c0"[(set_attr "length" "6")])(define_insn "jump"[(set (pc)(label_ref (match_operand 0 "" "")))]"""br\t%l0"[(set_attr "length" "6")]);; Table Jump(define_insn "tablejump"[(set (pc)(match_operand:SI 0 "register_operand" "r"))(use (label_ref:SI (match_operand 1 "" "")))]"!flag_pic""jump\t%0"[(set_attr "length" "2")]);; Call Instructions(define_expand "call"[(call (match_operand:QI 0 "memory_operand" "")(match_operand 1 "" ""))]""{if (flag_pic && ! legitimate_pic_operand_p (operands[0])){operands[0] = gen_const_mem (QImode,legitimize_pic_address (XEXP (operands[0], 0), Pmode, 0));emit_call_insn (gen_cr16_call (operands[0], operands[1]));}elseemit_call_insn (gen_cr16_call (operands[0], operands[1]));DONE;})(define_expand "cr16_call"[(parallel[(call (match_operand:QI 0 "memory_operand" "")(match_operand 1 "" ""))(clobber (reg:SI RA_REGNUM))])]"""")(define_insn "cr16_call_insn_branch_pic"[(call (mem:QI (match_operand:SI 0 "call_imm_operand" "i"))(match_operand 1 "" ""))(clobber (match_operand:SI 2 "register_operand" "+r"))]"flag_pic == FAR_PIC"{if (GET_CODE (operands[0]) != CONST_INT)return "loadd\t%g0, %2 \n\tjal %2";elsereturn "jal %2";}[(set_attr "length" "8")])(define_insn "cr16_call_insn_branch"[(call (mem:QI (match_operand:SI 0 "call_imm_operand" "i"))(match_operand 1 "" ""))(clobber (match_operand:SI 2 "register_operand" "+r"))]"flag_pic == 0 || flag_pic == NEAR_PIC"{/* Print the immediate address for bal'b' is used instead of 'a' to avoid compiler callingthe GO_IF_LEGITIMATE_ADDRESS which cannotperform checks on const_int code addresses as itassumes all const_int are data addresses.*/if (GET_CODE (operands[0]) != CONST_INT)return "bal (ra), %a0";elseoperands[4] = GEN_INT ((INTVAL (operands[0]))>>1);return "movd\t%g4,\t(r1,r0)\n\tjal\t(r1,r0)";}[(set_attr "length" "6")])(define_insn "cr16_call_insn_jump"[(call (mem:QI (match_operand:SI 0 "register_operand" "r"))(match_operand 1 "" ""))(clobber (match_operand:SI 2 "register_operand" "+r"))]"""jal\t%0"[(set_attr "length" "2")]);; Call Value Instructions(define_expand "call_value"[(set (match_operand 0 "general_operand" "")(call (match_operand:QI 1 "memory_operand" "")(match_operand 2 "" "")))]""{if (flag_pic && !legitimate_pic_operand_p (operands[1])){operands[1] = gen_const_mem (QImode,legitimize_pic_address (XEXP (operands[1], 0), Pmode, 0));emit_call_insn (gen_cr16_call_value (operands[0], operands[1], operands[2]));}elseemit_call_insn (gen_cr16_call_value (operands[0], operands[1], operands[2]));DONE;})(define_expand "cr16_call_value"[(parallel[(set (match_operand 0 "general_operand" "")(call (match_operand 1 "memory_operand" "")(match_operand 2 "" "")))(clobber (reg:SI RA_REGNUM))])]"""")(define_insn "cr16_call_value_insn_branch_pic"[(set (match_operand 0 "" "=g")(call (mem:QI (match_operand:SI 1 "call_imm_operand" "i"))(match_operand 2 "" "")))(clobber (match_operand:SI 3 "register_operand" "+r"))]"flag_pic == FAR_PIC"{if (GET_CODE (operands[1]) != CONST_INT)return "loadd\t%g1, %3 \n\tjal %3";elsereturn "jal %3";}[(set_attr "length" "8")])(define_insn "cr16_call_value_insn_branch"[(set (match_operand 0 "" "=g")(call (mem:QI (match_operand:SI 1 "call_imm_operand" "i"))(match_operand 2 "" "")))(clobber (match_operand:SI 3 "register_operand" "+r"))]"flag_pic == 0 || flag_pic == NEAR_PIC"{/* Print the immediate address for bal'b' is used instead of 'a' to avoid compiler callingthe GO_IF_LEGITIMATE_ADDRESS which cannotperform checks on const_int code addresses as itassumes all const_int are data addresses.*/if (GET_CODE (operands[1]) != CONST_INT)return "bal (ra), %a1";else{operands[4] = GEN_INT ((INTVAL (operands[1]))>>1);return "movd\t%g4,\t(r1,r0)\n\tjal\t(r1,r0)";}}[(set_attr "length" "6")])(define_insn "cr16_call_value_insn_jump"[(set (match_operand 0 "" "=g")(call (mem:QI (match_operand:SI 1 "register_operand" "r"))(match_operand 2 "" "")))(clobber (match_operand:SI 3 "register_operand" "+r"))]"""jal\t%1"[(set_attr "length" "2")]);; Nop(define_insn "nop"[(const_int 0)]"""nop\t");; PIC/* When generating pic, we need to load the symbol offset into a register.So that the optimizer does not confuse this with a normal symbol loadwe use an unspec. The offset will be loaded from a constant pool entry,since that is the only type of relocation we can use. */(define_insn "unspec_bro_addr"[(set (match_operand:SI 0 "register_operand" "=r")(unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_ADDR))]"""movd \t%f1, %0"[(set_attr "length" "4")])(define_insn "unspec_got_addr"[(set (match_operand:SI 0 "register_operand" "=r")(unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_LOAD_ADDR))]"""loadd \t%g1, %0"[(set_attr "length" "6")])
