X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fconfig%2Fc4x%2Fc4x.md;h=364457d9347791f31d06c9856d793df587034918;hb=d54b962041ed399305f12f6db7de0c5186db96d4;hp=98b989ab9934bacf78ec79a48be7a76ed2060dd3;hpb=e877bdb9ca2496b883c078676313fe3f9df62136;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/config/c4x/c4x.md b/gcc/config/c4x/c4x.md index 98b989ab993..364457d9347 100644 --- a/gcc/config/c4x/c4x.md +++ b/gcc/config/c4x/c4x.md @@ -1,25 +1,25 @@ -;; Machine description for the TMS320C[34]x for GNU C compiler -;; Copyright (C) 1994-99, 2000 Free Software Foundation, Inc. +;; Machine description for the TMS320C[34]x for GCC +;; Copyright (C) 1994, 1995, 1996, 1997, 1998, +;; 1999, 2000, 2002, 2004, 2005, 2007 Free Software Foundation, Inc. ;; Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz) ;; and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl) -;; This file is part of GNU CC. +;; This file is part of GCC. -;; GNU CC is free software; you can redistribute it and/or modify +;; 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 2, or (at your option) +;; the Free Software Foundation; either version 3, or (at your option) ;; any later version. -;; GNU CC is distributed in the hope that it will be useful, +;; 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 GNU CC; see the file COPYING. If not, write to -;; the Free Software Foundation, 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. +;; along with GCC; see the file COPYING3. If not see +;; . ; ; TODO : @@ -28,14 +28,14 @@ ; for QImode and Pmode, whether Pmode was QImode or PQImode. ; For addresses we wouldn't have to have a clobber of the CC ; associated with each insn and we could use MPYI in address -; calculations without having to synthesise a proper 32 bit multiply. +; calculations without having to synthesize a proper 32-bit multiply. ; Additional C30/C40 instructions not coded: ; CALLcond, IACK, IDLE, LDE, LDFI, LDII, LDM, NORM, RETIcond -; ROLC, RORC, SIGI, STFI, STII, SUBC, SWI, TRAPcond +; ROLC, RORC, SIGI, STFI, STII, SUBC, SWI ; Additional C40 instructions not coded: -; LDEP, LDPE, LWRct, FRIEEE, TOIEEE, LAJcond, LATcond, RETIcondD +; LDEP, LDPE, LWRct, LAJcond, RETIcondD ; ; C4x MODES @@ -122,7 +122,7 @@ ; L unsigned 16-bit ; M unsigned 8-bit (C4x only) ; N ones complement of unsigned 16-bit -; O 16 bit high constant +; O 16-bit high constant ; Q ARx + 9-bit signed disp ; R ARx + 5-bit unsigned disp (C4x only) ; S ARx + 0, 1, IRx disp @@ -153,10 +153,10 @@ ; not for 'c'. ; The 'f' constraint is only for float register operands---when -; a register satisying the 'f' constraint is used as a dst operand, +; a register satisfying the 'f' constraint is used as a dst operand, ; the CC gets clobbered (except for LDFcond). -; The ! in front of the 'b' constaint says to GCC to disparage the +; The ! in front of the 'b' constraint says to GCC to disparage the ; use of this constraint. The 'b' constraint applies only to the SP. ; Note that we deal with the condition code CC like some of the RISC @@ -172,7 +172,7 @@ ; delayed branch slots. ; Since the C[34]x has many instructions that set the CC, we pay the -; price of having to explicity define which insns clobber the CC +; price of having to explicitly define which insns clobber the CC ; (rather than using the macro NOTICE_UPDATE_CC). ; Note that many patterns say that the CC is clobbered when in fact @@ -184,12 +184,12 @@ ; copied about, then we could store the CC in a pseudo register and ; use constructs such as (clobber (match_scratch:CC N "&y,X")) to ; indicate that the 'y' class (ST register) is clobbered for the -; first combination of operands, but not with the second. +; first combination of operands but not with the second. ; I tried this approach for a while but reload got unhappy since I ; didn't allow it to move the CC around. ; Note that fundamental operations, such as moves, must not clobber the -; CC. Thus movqi choses a move instruction that doesn't clobber the CC. +; CC. Thus movqi chooses a move instruction that doesn't clobber the CC. ; If GCC wants to combine a move with a compare, it is smart enough to ; chose the move instruction that sets the CC. @@ -230,7 +230,7 @@ ; a new spill register. ; Note that the floating point representation of 0.0 on the C4x -; is 0x80000000 (-2147483648). This value produces an warning +; is 0x80000000 (-2147483648). This value produces a warning ; message on 32-bit machines about the decimal constant being so large ; that it is unsigned. @@ -319,8 +319,8 @@ ; op3 fetch executed ; This means that we can allow any instruction in the last delay slot ; and only instructions which modify registers in the first two. -; lda can not be executed in the first delay slot -; and ldpk can not be executed in the first two delay slots. +; lda cannot be executed in the first delay slot +; and ldpk cannot be executed in the first two delay slots. (define_attr "onlyreg" "false,true" (cond [(eq_attr "type" "unary,unarycc") @@ -375,9 +375,13 @@ (const_string "true") (const_string "false"))) +/* Disable ldp because the c4x contains a bug. The ldp insn modifies + the dp register when the insn is anulled or not. + Also disable autoincrement insns because of a silicon bug. */ (define_attr "in_annul_slot_3" "false,true" - (if_then_else (and (eq_attr "cpu" "c4x") - (eq_attr "type" "!jump,call,rets,jmpc,db,dbc,repeat,repeat_top,laj,push,pop,multi")) + (if_then_else (and (and (eq_attr "cpu" "c4x") + (eq_attr "type" "!jump,call,rets,jmpc,db,dbc,repeat,repeat_top,laj,push,pop,ldp,multi")) + (eq_attr "onlyreg_nomod" "true")) (const_string "true") (const_string "false"))) @@ -441,70 +445,50 @@ ; ; C4x UNSPEC NUMBERS ; -; 1 BU/BUD -; 2 RPTS -; 3 LSH -; 4 cmphi -; 5 RCPF -; 6 RND -; 7 repeat block filler -; 8 loadhf_int -; 9 storehf_int -; 10 RSQRF -; 11 loadqf_int -; 12 storeqf_int -; 22 rptb_init - -; -; C4x FUNCTIONAL UNITS -; -; Define functional units for instruction scheduling to minimise -; pipeline conflicts. +(define_constants + [ + (UNSPEC_BU 1) + (UNSPEC_RPTS 2) + (UNSPEC_LSH 3) + (UNSPEC_CMPHI 4) + (UNSPEC_RCPF 5) + (UNSPEC_RND 6) + (UNSPEC_RPTB_FILL 7) + (UNSPEC_LOADHF_INT 8) + (UNSPEC_STOREHF_INT 9) + (UNSPEC_RSQRF 10) + (UNSPEC_LOADQF_INT 11) + (UNSPEC_STOREQF_INT 12) + (UNSPEC_LDIV 13) + (UNSPEC_PUSH_ST 14) + (UNSPEC_POP_ST 15) + (UNSPEC_PUSH_DP 16) + (UNSPEC_POP_DP 17) + (UNSPEC_POPQI 18) + (UNSPEC_POPQF 19) + (UNSPEC_ANDN_ST 20) + (UNSPEC_RPTB_INIT 22) + (UNSPEC_TOIEEE 23) + (UNSPEC_FRIEEE 24) + ]) + +; +; C4x PIPELINE MODEL ; ; With the C3x, an external memory write (with no wait states) takes ; two cycles and an external memory read (with no wait states) takes ; one cycle. However, an external read following an external write ; takes two cycles. With internal memory, reads and writes take ; half a cycle. -; ; When a C4x address register is loaded it will not be available for ; an extra machine cycle. Calculating with a C4x address register -; makes it unavailable for 2 machine cycles. To notify GCC of these -; pipeline delays, each of the auxiliary and index registers are declared -; as separate functional units. +; makes it unavailable for 2 machine cycles. ; -; (define_function_unit NAME MULTIPLICITY SIMULTANEITY -; TEST READY-DELAY ISSUE-DELAY [CONFLICT-LIST]) -; -; MULTIPLICITY 1 (C4x has no independent identical function units) -; SIMULTANEITY 0 (C4x is pipelined) -; READY_DELAY 1 (Results usually ready after every cyle) -; ISSUE_DELAY 1 (Can issue insns every cycle) - ; Just some dummy definitions. The real work is done in c4x_adjust_cost. ; These are needed so the min/max READY_DELAY is known. -(define_function_unit "dummy" 1 0 (const_int 0) 1 1) -(define_function_unit "dummy" 1 0 (const_int 0) 2 1) -(define_function_unit "dummy" 1 0 (const_int 0) 3 1) - -;(define_function_unit "ar0" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setar0" "1") -; (eq_attr "usear0" "1"))) -; 3 1 ) - -;(define_function_unit "ar0" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setlda_ar0" "1") -; (eq_attr "usear0" "1"))) -; 2 1 ) - -;(define_function_unit "ar0" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "usear0" "1") -; (eq_attr "readar0" "1"))) -; 2 1 ) +(define_insn_reservation "any_insn" 1 (const_int 1) "nothing") +(define_insn_reservation "slowest_insn" 3 (const_int 0) "nothing") ; The attribute setar0 is set to 1 for insns where ar0 is a dst operand. ; Note that the attributes unarycc and binarycc do not apply @@ -551,24 +535,6 @@ (const_int 1) (const_int 0))] (const_int 0))) -;(define_function_unit "ar1" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setar1" "1") -; (eq_attr "usear1" "1"))) -; 3 1 ) - -;(define_function_unit "ar1" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setlda_ar1" "1") -; (eq_attr "usear1" "1"))) -; 2 1 ) - -;(define_function_unit "ar1" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "usear1" "1") -; (eq_attr "readar1" "1"))) -; 2 1 ) - (define_attr "setar1" "" (cond [(eq_attr "type" "unary,binary") (if_then_else (match_operand 0 "ar1_reg_operand" "") @@ -608,24 +574,6 @@ (const_int 1) (const_int 0))] (const_int 0))) -;(define_function_unit "ar2" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setar2" "1") -; (eq_attr "usear2" "1"))) -; 3 1 ) - -;(define_function_unit "ar2" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setlda_ar2" "1") -; (eq_attr "usear2" "1"))) -; 2 1 ) - -;(define_function_unit "ar2" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "usear2" "1") -; (eq_attr "readar2" "1"))) -; 2 1 ) - (define_attr "setar2" "" (cond [(eq_attr "type" "unary,binary") (if_then_else (match_operand 0 "ar2_reg_operand" "") @@ -665,24 +613,6 @@ (const_int 1) (const_int 0))] (const_int 0))) -;(define_function_unit "ar3" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setar3" "1") -; (eq_attr "usear3" "1"))) -; 3 1 ) - -;(define_function_unit "ar3" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setlda_ar3" "1") -; (eq_attr "usear3" "1"))) -; 2 1 ) - -;(define_function_unit "ar3" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "usear3" "1") -; (eq_attr "readar3" "1"))) -; 2 1 ) - (define_attr "setar3" "" (cond [(eq_attr "type" "unary,binary") (if_then_else (match_operand 0 "ar3_reg_operand" "") @@ -722,24 +652,6 @@ (const_int 1) (const_int 0))] (const_int 0))) -;(define_function_unit "ar4" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setar4" "1") -; (eq_attr "usear4" "1"))) -; 3 1 ) - -;(define_function_unit "ar4" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setlda_ar4" "1") -; (eq_attr "usear4" "1"))) -; 2 1 ) - -;(define_function_unit "ar4" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "usear4" "1") -; (eq_attr "readar4" "1"))) -; 2 1 ) - (define_attr "setar4" "" (cond [(eq_attr "type" "unary,binary") (if_then_else (match_operand 0 "ar4_reg_operand" "") @@ -779,24 +691,6 @@ (const_int 1) (const_int 0))] (const_int 0))) -;(define_function_unit "ar5" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setar5" "1") -; (eq_attr "usear5" "1"))) -; 3 1 ) - -;(define_function_unit "ar5" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setlda_ar5" "1") -; (eq_attr "usear5" "1"))) -; 2 1 ) - -;(define_function_unit "ar5" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "usear5" "1") -; (eq_attr "readar5" "1"))) -; 2 1 ) - (define_attr "setar5" "" (cond [(eq_attr "type" "unary,binary") (if_then_else (match_operand 0 "ar5_reg_operand" "") @@ -836,24 +730,6 @@ (const_int 1) (const_int 0))] (const_int 0))) -;(define_function_unit "ar6" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setar6" "1") -; (eq_attr "usear6" "1"))) -; 3 1 ) - -;(define_function_unit "ar6" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setlda_ar6" "1") -; (eq_attr "usear6" "1"))) -; 2 1 ) - -;(define_function_unit "ar6" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "usear6" "1") -; (eq_attr "readar6" "1"))) -; 2 1 ) - (define_attr "setar6" "" (cond [(eq_attr "type" "unary,binary") (if_then_else (match_operand 0 "ar6_reg_operand" "") @@ -893,24 +769,6 @@ (const_int 1) (const_int 0))] (const_int 0))) -;(define_function_unit "ar7" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setar7" "1") -; (eq_attr "usear7" "1"))) -; 3 1 ) - -;(define_function_unit "ar7" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setlda_ar7" "1") -; (eq_attr "usear7" "1"))) -; 2 1 ) - -;(define_function_unit "ar7" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "usear7" "1") -; (eq_attr "readar7" "1"))) -; 2 1 ) - (define_attr "setar7" "" (cond [(eq_attr "type" "unary,binary") (if_then_else (match_operand 0 "ar7_reg_operand" "") @@ -950,18 +808,6 @@ (const_int 1) (const_int 0))] (const_int 0))) -;(define_function_unit "ir0" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setir0" "1") -; (eq_attr "useir0" "1"))) -; 3 1 ) - -;(define_function_unit "ir0" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setlda_ir0" "1") -; (eq_attr "useir0" "1"))) -; 2 1 ) - (define_attr "setir0" "" (cond [(eq_attr "type" "unary,binary") (if_then_else (match_operand 0 "ir0_reg_operand" "") @@ -986,18 +832,6 @@ (const_int 1) (const_int 0))] (const_int 0))) -;(define_function_unit "ir1" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setir1" "1") -; (eq_attr "useir1" "1"))) -; 3 1 ) - -;(define_function_unit "ir1" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setlda_ir1" "1") -; (eq_attr "useir1" "1"))) -; 2 1 ) - (define_attr "setir1" "" (cond [(eq_attr "type" "unary,binary") (if_then_else (match_operand 0 "ir1_reg_operand" "") @@ -1022,7 +856,7 @@ (const_int 1) (const_int 0))] (const_int 0))) -; With the C3x, things are simpler, but slower, i.e. more pipeline conflicts :( +; With the C3x, things are simpler but slower, i.e. more pipeline conflicts :( ; There are three functional groups: ; (1) AR0-AR7, IR0-IR1, BK ; (2) DP @@ -1039,18 +873,6 @@ ; Let's ignore functional groups 2 and 3 for now, since they are not ; so important. -;(define_function_unit "group1" 1 0 -; (and (eq_attr "cpu" "c3x") -; (and (eq_attr "setgroup1" "1") -; (eq_attr "usegroup1" "1"))) -; 3 1) - -;(define_function_unit "group1" 1 0 -; (and (eq_attr "cpu" "c3x") -; (and (eq_attr "usegroup1" "1") -; (eq_attr "readarx" "1"))) -; 2 1) - (define_attr "setgroup1" "" (cond [(eq_attr "type" "lda,unary,binary") (if_then_else (match_operand 0 "group1_reg_operand" "") @@ -1084,6 +906,7 @@ (const_int 1) (const_int 0))] (const_int 0))) +(include "predicates.md") ; ; C4x INSN PATTERNS: @@ -1106,32 +929,40 @@ "* return (TARGET_C3X) ? \"ldp\\t%A1\" : \"ldpk\\t%A1\";" [(set_attr "type" "ldp")]) +(define_insn "set_ldp_prologue" + [(set (match_operand:QI 0 "dp_reg_operand" "=z") + (high:QI (match_operand:QI 1 "" "")))] + "TARGET_SMALL && TARGET_PARANOID" + "* return (TARGET_C3X) ? \"ldp\\t@data_sec\" : \"ldpk\\t@data_sec\";" + [(set_attr "type" "ldp")]) + (define_insn "set_high" [(set (match_operand:QI 0 "std_reg_operand" "=c") (high:QI (match_operand:QI 1 "symbolic_address_operand" "")))] - "! TARGET_C3X " + "! TARGET_C3X && ! TARGET_TI" "ldhi\\t^%H1,%0" [(set_attr "type" "unary")]) (define_insn "set_lo_sum" - [(set (match_operand:QI 0 "std_reg_operand" "=c") + [(set (match_operand:QI 0 "std_reg_operand" "+c") (lo_sum:QI (match_dup 0) (match_operand:QI 1 "symbolic_address_operand" "")))] - "" + "! TARGET_TI" "or\\t#%H1,%0" [(set_attr "type" "unary")]) (define_split [(set (match_operand:QI 0 "std_reg_operand" "") (match_operand:QI 1 "symbolic_address_operand" ""))] - "! TARGET_C3X" + "reload_completed && ! TARGET_C3X && ! TARGET_TI" [(set (match_dup 0) (high:QI (match_dup 1))) (set (match_dup 0) (lo_sum:QI (match_dup 0) (match_dup 1)))] "") (define_split [(set (match_operand:QI 0 "reg_operand" "") - (match_operand:QI 1 "const_int_operand" ""))] + (match_operand:QI 1 "const_int_operand" "")) + (clobber (reg:QI 16))] "! TARGET_C3X && ! IS_INT16_CONST (INTVAL (operands[1])) && ! IS_HIGH_CONST (INTVAL (operands[1])) @@ -1141,13 +972,30 @@ (set (match_dup 0) (ior:QI (match_dup 0) (match_dup 3)))] " { - operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & ~0xffff); - operands[3] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 0xffff); + operands[2] = GEN_INT (INTVAL (operands[1]) & ~0xffff); + operands[3] = GEN_INT (INTVAL (operands[1]) & 0xffff); }") (define_split [(set (match_operand:QI 0 "reg_operand" "") (match_operand:QI 1 "const_int_operand" ""))] + "! TARGET_C3X + && ! IS_INT16_CONST (INTVAL (operands[1])) + && ! IS_HIGH_CONST (INTVAL (operands[1])) + && reload_completed + && std_reg_operand (operands[0], QImode)" + [(set (match_dup 0) (match_dup 2)) + (set (match_dup 0) (ior:QI (match_dup 0) (match_dup 3)))] + " +{ + operands[2] = GEN_INT (INTVAL (operands[1]) & ~0xffff); + operands[3] = GEN_INT (INTVAL (operands[1]) & 0xffff); +}") + +(define_split + [(set (match_operand:QI 0 "reg_operand" "") + (match_operand:QI 1 "const_int_operand" "")) + (clobber (reg:QI 16))] "TARGET_C3X && ! TARGET_SMALL && ! IS_INT16_CONST (INTVAL (operands[1])) && reload_completed @@ -1159,16 +1007,36 @@ " { /* Generate two's complement value of 16 MSBs. */ - operands[2] = gen_rtx (CONST_INT, VOIDmode, - (((INTVAL (operands[1]) >> 16) & 0xffff) + operands[2] = GEN_INT ((((INTVAL (operands[1]) >> 16) & 0xffff) - 0x8000) ^ ~0x7fff); - operands[3] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 0xffff); - operands[4] = gen_rtx (CONST_INT, VOIDmode, 16); + operands[3] = GEN_INT (INTVAL (operands[1]) & 0xffff); + operands[4] = GEN_INT (16); }") (define_split [(set (match_operand:QI 0 "reg_operand" "") (match_operand:QI 1 "const_int_operand" ""))] + "TARGET_C3X && ! TARGET_SMALL + && ! IS_INT16_CONST (INTVAL (operands[1])) + && reload_completed + && std_reg_operand (operands[0], QImode) + && c4x_shiftable_constant (operands[1]) < 0" + [(set (match_dup 0) (match_dup 2)) + (set (match_dup 0) (ashift:QI (match_dup 0) (match_dup 4))) + (set (match_dup 0) (ior:QI (match_dup 0) (match_dup 3)))] + " +{ + /* Generate two's complement value of 16 MSBs. */ + operands[2] = GEN_INT ((((INTVAL (operands[1]) >> 16) & 0xffff) + - 0x8000) ^ ~0x7fff); + operands[3] = GEN_INT (INTVAL (operands[1]) & 0xffff); + operands[4] = GEN_INT (16); +}") + +(define_split + [(set (match_operand:QI 0 "reg_operand" "") + (match_operand:QI 1 "const_int_operand" "")) + (clobber (reg:QI 16))] "TARGET_C3X && ! IS_INT16_CONST (INTVAL (operands[1])) && reload_completed @@ -1181,15 +1049,35 @@ /* Generate two's complement value of MSBs. */ int shift = c4x_shiftable_constant (operands[1]); - operands[2] = gen_rtx (CONST_INT, VOIDmode, - (((INTVAL (operands[1]) >> shift) & 0xffff) + operands[2] = GEN_INT ((((INTVAL (operands[1]) >> shift) & 0xffff) - 0x8000) ^ ~0x7fff); - operands[3] = gen_rtx (CONST_INT, VOIDmode, shift); + operands[3] = GEN_INT (shift); }") (define_split [(set (match_operand:QI 0 "reg_operand" "") (match_operand:QI 1 "const_int_operand" ""))] + "TARGET_C3X + && ! IS_INT16_CONST (INTVAL (operands[1])) + && reload_completed + && std_reg_operand (operands[0], QImode) + && c4x_shiftable_constant (operands[1]) >= 0" + [(set (match_dup 0) (match_dup 2)) + (set (match_dup 0) (ashift:QI (match_dup 0) (match_dup 3)))] + " +{ + /* Generate two's complement value of MSBs. */ + int shift = c4x_shiftable_constant (operands[1]); + + operands[2] = GEN_INT ((((INTVAL (operands[1]) >> shift) & 0xffff) + - 0x8000) ^ ~0x7fff); + operands[3] = GEN_INT (shift); +}") + +(define_split + [(set (match_operand:QI 0 "reg_operand" "") + (match_operand:QI 1 "const_int_operand" "")) + (clobber (reg:QI 16))] "! TARGET_SMALL && ! IS_INT16_CONST (INTVAL (operands[1])) && ! IS_HIGH_CONST (INTVAL (operands[1])) @@ -1212,6 +1100,49 @@ (define_split [(set (match_operand:QI 0 "reg_operand" "") (match_operand:QI 1 "const_int_operand" ""))] + "! TARGET_SMALL + && ! IS_INT16_CONST (INTVAL (operands[1])) + && ! IS_HIGH_CONST (INTVAL (operands[1])) + && reload_completed + && ! std_reg_operand (operands[0], QImode)" + [(set (match_dup 2) (high:QI (match_dup 3))) + (set (match_dup 0) (match_dup 4)) + (use (match_dup 1))] + " +{ + rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO); + operands[2] = dp_reg; + operands[3] = force_const_mem (Pmode, operands[1]); + operands[4] = change_address (operands[3], QImode, + gen_rtx_LO_SUM (Pmode, dp_reg, + XEXP (operands[3], 0))); + operands[3] = XEXP (operands[3], 0); +}") + +(define_split + [(set (match_operand:QI 0 "reg_operand" "") + (match_operand:QI 1 "const_int_operand" "")) + (clobber (reg:QI 16))] + "TARGET_SMALL + && ! IS_INT16_CONST (INTVAL (operands[1])) + && ! IS_HIGH_CONST (INTVAL (operands[1])) + && reload_completed + && ((TARGET_C3X && c4x_shiftable_constant (operands[1]) < 0) + || ! std_reg_operand (operands[0], QImode))" + [(set (match_dup 0) (match_dup 2)) + (use (match_dup 1))] + " +{ + rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO); + operands[2] = force_const_mem (Pmode, operands[1]); + operands[2] = change_address (operands[2], QImode, + gen_rtx_LO_SUM (Pmode, dp_reg, + XEXP (operands[2], 0))); +}") + +(define_split + [(set (match_operand:QI 0 "reg_operand" "") + (match_operand:QI 1 "const_int_operand" ""))] "TARGET_SMALL && ! IS_INT16_CONST (INTVAL (operands[1])) && ! IS_HIGH_CONST (INTVAL (operands[1])) @@ -1231,7 +1162,8 @@ (define_split [(set (match_operand:HI 0 "reg_operand" "") - (match_operand:HI 1 "const_int_operand" ""))] + (match_operand:HI 1 "const_int_operand" "")) + (clobber (reg:QI 16))] "reload_completed" [(set (match_dup 2) (match_dup 4)) (set (match_dup 3) (match_dup 5))] @@ -1243,16 +1175,38 @@ operands[5] = c4x_operand_subword (operands[1], 1, 1, HImode); }") + +; We need to clobber the DP reg to be safe in case we +; need to load this address from memory +(define_insn "load_immed_address" + [(set (match_operand:QI 0 "reg_operand" "=a?x?c*r") + (match_operand:QI 1 "symbolic_address_operand" "")) + (clobber (reg:QI 16))] + "TARGET_LOAD_ADDRESS" + "#" + [(set_attr "type" "multi")]) + + +(define_split + [(set (match_operand:QI 0 "std_reg_operand" "") + (match_operand:QI 1 "symbolic_address_operand" "")) + (clobber (reg:QI 16))] + "reload_completed && ! TARGET_C3X && ! TARGET_TI" + [(set (match_dup 0) (high:QI (match_dup 1))) + (set (match_dup 0) (lo_sum:QI (match_dup 0) (match_dup 1)))] + "") + ; CC has been selected to load a symbolic address. We force the address ; into memory and then generate LDP and LDIU insns. ; This is also required for the C30 if we pretend that we can ; easily load symbolic addresses into a register. (define_split [(set (match_operand:QI 0 "reg_operand" "") - (match_operand:QI 1 "symbolic_address_operand" ""))] - "! TARGET_SMALL - && (TARGET_C3X || (reload_completed - && ! std_reg_operand (operands[0], QImode)))" + (match_operand:QI 1 "symbolic_address_operand" "")) + (clobber (reg:QI 16))] + "reload_completed + && ! TARGET_SMALL + && (TARGET_C3X || TARGET_TI || ! std_reg_operand (operands[0], QImode))" [(set (match_dup 2) (high:QI (match_dup 3))) (set (match_dup 0) (match_dup 4)) (use (match_dup 1))] @@ -1271,10 +1225,11 @@ ; for the small memory model. (define_split [(set (match_operand:QI 0 "reg_operand" "") - (match_operand:QI 1 "symbolic_address_operand" ""))] - "TARGET_SMALL - && (TARGET_C3X || (reload_completed - && ! std_reg_operand (operands[0], QImode)))" + (match_operand:QI 1 "symbolic_address_operand" "")) + (clobber (reg:QI 16))] + "reload_completed + && TARGET_SMALL + && (TARGET_C3X || TARGET_TI || ! std_reg_operand (operands[0], QImode))" [(set (match_dup 0) (match_dup 2)) (use (match_dup 1))] " @@ -1286,16 +1241,10 @@ XEXP (operands[2], 0))); }") -(define_insn "load_immed_address" - [(set (match_operand:QI 0 "reg_operand" "=a?x?c*r") - (match_operand:QI 1 "symbolic_address_operand" ""))] - "TARGET_LOAD_ADDRESS" - "#" - [(set_attr "type" "multi")]) - (define_insn "loadhi_big_constant" [(set (match_operand:HI 0 "reg_operand" "=c*d") - (match_operand:HI 1 "const_int_operand" ""))] + (match_operand:HI 1 "const_int_operand" "")) + (clobber (reg:QI 16))] "" "#" [(set_attr "type" "multi")]) @@ -1316,7 +1265,8 @@ (define_insn "loadqi_big_constant" [(set (match_operand:QI 0 "reg_operand" "=c*d") - (match_operand:QI 1 "const_int_operand" ""))] + (match_operand:QI 1 "const_int_operand" "")) + (clobber (reg:QI 16))] "! IS_INT16_CONST (INTVAL (operands[1])) && ! IS_HIGH_CONST (INTVAL (operands[1]))" "#" @@ -1365,8 +1315,7 @@ (set (reg:CC 21) (compare:CC (match_dup 0) (const_int 0)))] "" - "@ - ldi\\t%1,%0" + "ldi\\t%1,%0" [(set_attr "type" "unarycc") (set_attr "data" "int16")]) @@ -1377,8 +1326,7 @@ (set (match_operand:QI 0 "ext_reg_operand" "=d") (match_dup 1))] "" - "@ - ldi\\t%1,%0" + "ldi\\t%1,%0" [(set_attr "type" "unarycc") (set_attr "data" "int16")]) @@ -1398,7 +1346,7 @@ ; If one of the operands is not a register, then we should ; emit two insns, using a scratch register. This will produce ; better code in loops if the source operand is invariant, since -; the source reload can be optimised out. During reload we cannot +; the source reload can be optimized out. During reload we cannot ; use change_address or force_reg which will allocate new pseudo regs. ; Unlike most other insns, the move insns can't be split with @@ -1416,6 +1364,18 @@ }") +; As far as GCC is concerned, the moves are performed in parallel +; thus it must be convinced that there is no aliasing. +; It also assumes that the input operands are simultaneously loaded +; and then the output operands are simultaneously stored. +; With the C4x, if there are parallel stores to the same address +; both stores are executed. +; If there is a parallel load and store to the same address, +; the load is performed first. +; The problem with this pattern is that reload can spoil +; the show when it eliminates a reference to the frame pointer. +; This can invalidate the memory addressing mode, i.e., when +; the displacement is greater than 1. (define_insn "movqi_parallel" [(set (match_operand:QI 0 "parallel_operand" "=q,S<>!V,q,S<>!V") (match_operand:QI 1 "parallel_operand" "S<>!V,q,S<>!V,q")) @@ -1432,14 +1392,30 @@ ; ; PUSH/POP ; -(define_insn "*pushqi" +(define_insn "pushqi" [(set (mem:QI (pre_inc:QI (reg:QI 20))) (match_operand:QI 0 "reg_operand" "r"))] "" "push\\t%0" [(set_attr "type" "push")]) -(define_insn "*popqi" +(define_insn "push_st" + [(set (mem:QI (pre_inc:QI (reg:QI 20))) + (unspec:QI [(reg:QI 21)] UNSPEC_PUSH_ST)) + (use (reg:QI 21))] + "" + "push\\tst" + [(set_attr "type" "push")]) + +(define_insn "push_dp" + [(set (mem:QI (pre_inc:QI (reg:QI 20))) + (unspec:QI [(reg:QI 16)] UNSPEC_PUSH_DP)) + (use (reg:QI 16))] + "" + "push\\tdp" + [(set_attr "type" "push")]) + +(define_insn "popqi" [(set (match_operand:QI 0 "reg_operand" "=r") (mem:QI (post_dec:QI (reg:QI 20)))) (clobber (reg:CC 21))] @@ -1447,6 +1423,31 @@ "pop\\t%0" [(set_attr "type" "pop")]) +(define_insn "pop_st" + [(set (unspec:QI [(reg:QI 21)] UNSPEC_POP_ST) + (mem:QI (post_dec:QI (reg:QI 20)))) + (clobber (reg:CC 21))] + "" + "pop\\tst" + [(set_attr "type" "pop")]) + +(define_insn "pop_dp" + [(set (unspec:QI [(reg:QI 16)] UNSPEC_POP_DP) + (mem:QI (post_dec:QI (reg:QI 20)))) + (clobber (reg:CC 16))] + "" + "pop\\tdp" + [(set_attr "type" "pop")]) + +(define_insn "popqi_unspec" + [(set (unspec:QI [(match_operand:QI 0 "reg_operand" "=r")] UNSPEC_POPQI) + (mem:QI (post_dec:QI (reg:QI 20)))) + (clobber (match_dup 0)) + (clobber (reg:CC 21))] + "" + "pop\\t%0" + [(set_attr "type" "pop")]) + ; ; ABSI ; @@ -1769,6 +1770,23 @@ DONE; }") +; This pattern is required primarily for manipulating the stack pointer +; where GCC doesn't expect CC to be clobbered or for calculating +; addresses during reload. Since this is a more specific pattern +; it needs to go first (otherwise we get into problems trying to decide +; to add clobbers). +(define_insn "addqi3_noclobber" + [(set (match_operand:QI 0 "std_reg_operand" "=c,c,c") + (plus:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>") + (match_operand:QI 2 "src_operand" "rIm,JR,rS<>")))] + "valid_operands (PLUS, operands, QImode)" + "@ + addi\\t%2,%0 + addi3\\t%2,%1,%0 + addi3\\t%2,%1,%0" + [(set_attr "type" "binary,binary,binary")]) +; Default to int16 data attr. + (define_insn "*addqi3_clobber" [(set (match_operand:QI 0 "reg_operand" "=d,d,?d,c,c,?c") (plus:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>,0,rR,rS<>") @@ -1852,21 +1870,6 @@ [(set_attr "type" "binarycc,binarycc,binarycc")]) ; Default to int16 data attr. -; This pattern is required primarily for manipulating the stack pointer -; where GCC doesn't expect CC to be clobbered or for calculating -; addresses during reload. -(define_insn "addqi3_noclobber" - [(set (match_operand:QI 0 "std_reg_operand" "=c,c,c") - (plus:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>") - (match_operand:QI 2 "src_operand" "rIm,JR,rS<>")))] - "valid_operands (PLUS, operands, QImode)" - "@ - addi\\t%2,%0 - addi3\\t%2,%1,%0 - addi3\\t%2,%1,%0" - [(set_attr "type" "binary,binary,binary")]) -; Default to int16 data attr. - ; This pattern is required during reload when eliminate_regs_in_insn ; effectively converts a move insn into an add insn when the src @@ -2065,7 +2068,7 @@ { if (GET_CODE (operands[2]) == CONST_INT) { - /* Let GCC try to synthesise the multiplication using shifts + /* Let GCC try to synthesize the multiplication using shifts and adds. In most cases this will be more profitable than using the C3x MPYI. */ FAIL; @@ -2082,7 +2085,8 @@ operands[2])); DONE; } - c4x_emit_libcall3 (MULQI3_LIBCALL, MULT, QImode, operands); + c4x_emit_libcall3 (optab_libfunc (smul_optab, QImode), + MULT, QImode, operands); DONE; } ") @@ -2156,7 +2160,7 @@ ; The C3x multiply instruction assumes 24-bit signed integer operands ; and the 48-bit result is truncated to 32-bits. -(define_insn "*mulqi3_24_clobber" +(define_insn "mulqi3_24_clobber" [(set (match_operand:QI 0 "reg_operand" "=d,d,?d,c,c,?c") (mult:QI (sign_extend:QI @@ -2293,7 +2297,7 @@ "legitimize_operands (MULT, operands, QImode); if (TARGET_C3X) { - c4x_emit_libcall_mulhi (SMULHI3_LIBCALL, SIGN_EXTEND, QImode, operands); + c4x_emit_libcall_mulhi (smulhi3_libfunc, SIGN_EXTEND, QImode, operands); DONE; } ") @@ -2342,15 +2346,17 @@ (truncate:QI (lshiftrt:HI (mult:HI - (zero_extend:HI (match_operand:QI 1 "src_operand" "")) - (zero_extend:HI (match_operand:QI 2 "lsrc_operand" ""))) + (zero_extend:HI (match_operand:QI 1 + "nonimmediate_src_operand" "")) + (zero_extend:HI (match_operand:QI 2 + "nonimmediate_lsrc_operand" ""))) (const_int 32)))) (clobber (reg:CC_NOOV 21))])] "" "legitimize_operands (MULT, operands, QImode); if (TARGET_C3X) { - c4x_emit_libcall_mulhi (UMULHI3_LIBCALL, ZERO_EXTEND, QImode, operands); + c4x_emit_libcall_mulhi (umulhi3_libfunc, ZERO_EXTEND, QImode, operands); DONE; } ") @@ -2360,8 +2366,10 @@ (truncate:QI (lshiftrt:HI (mult:HI - (zero_extend:HI (match_operand:QI 1 "src_operand" "%0,rR,rS<>,0,rR,rS<>")) - (zero_extend:HI (match_operand:QI 2 "lsrc_operand" "rLm,JR,rS<>,rLm,JR,rS<>"))) + (zero_extend:HI (match_operand:QI 1 + "nonimmediate_src_operand" "%0,rR,rS<>,0,rR,rS<>")) + (zero_extend:HI (match_operand:QI 2 + "nonimmediate_lsrc_operand" "rm,R,rS<>,rm,R,rS<>"))) (const_int 32)))) (clobber (reg:CC_NOOV 21))] "! TARGET_C3X && valid_operands (MULT, operands, QImode)" @@ -2380,8 +2388,10 @@ (truncate:QI (lshiftrt:HI (mult:HI - (zero_extend:HI (match_operand:QI 1 "src_operand" "0,rR,rS<>")) - (zero_extend:HI (match_operand:QI 2 "lsrc_operand" "rLm,JR,rS<>"))) + (zero_extend:HI (match_operand:QI 1 + "nonimmediate_src_operand" "0,rR,rS<>")) + (zero_extend:HI (match_operand:QI 2 + "nonimmediate_lsrc_operand" "rm,R,rS<>"))) (const_int 32))))] "! TARGET_C3X && valid_operands (MULT, operands, QImode)" "@ @@ -2469,6 +2479,18 @@ [(set_attr "type" "binary,binary,binary,binary") (set_attr "data" "not_uint16,uint16,int16,uint16")]) +(define_insn "andn_st" + [(set (unspec:QI [(reg:QI 21)] 20) + (and:QI (unspec:QI [(reg:QI 21)] UNSPEC_ANDN_ST) + (match_operand:QI 0 "" "N"))) + (use (match_dup 0)) + (use (reg:CC 21)) + (clobber (reg:CC 21))] + "" + "andn\\t%N0,st" + [(set_attr "type" "misc") + (set_attr "data" "not_uint16")]) + (define_split [(set (match_operand:QI 0 "std_reg_operand" "") (and:QI (match_operand:QI 1 "src_operand" "") @@ -2860,7 +2882,7 @@ (define_insn "*lshlqi3_clobber" [(set (match_operand:QI 0 "reg_operand" "=d,d,?d,c,c,?c") (ashift:QI (match_operand:QI 1 "src_operand" "0,rR,rS<>,0,rR,rS<>") - (unspec:QI [(match_operand:QI 2 "src_operand" "rIm,JR,rS<>,rIm,JR,rS<>")] 3))) + (unspec:QI [(match_operand:QI 2 "src_operand" "rIm,JR,rS<>,rIm,JR,rS<>")] UNSPEC_LSH))) (clobber (reg:CC 21))] "valid_operands (ASHIFT, operands, QImode)" "@ @@ -3090,9 +3112,9 @@ ; Unfortunately the C40 doesn't allow cmpi3 7, *ar0++ so the next best ; thing would be to get the small constant loaded into a register (say r0) ; so that it could be hoisted out of the loop so that we only -; would need to do cmpi3 *ar0++, r0. Now the loop optimisation pass +; would need to do cmpi3 *ar0++, r0. Now the loop optimization pass ; comes before the flow pass (which finds autoincrements) so we're stuck. -; Ideally, GCC requires another loop optimisation pass (preferably after +; Ideally, GCC requires another loop optimization pass (preferably after ; reload) so that it can hoist invariants out of loops. ; The current solution modifies legitimize_operands () so that small ; constants are forced into a pseudo register. @@ -3319,7 +3341,7 @@ ") (define_insn "*insv_clobber" - [(set (zero_extract:QI (match_operand:QI 0 "reg_operand" "=d,c") + [(set (zero_extract:QI (match_operand:QI 0 "reg_operand" "+d,c") (match_operand:QI 1 "const_int_operand" "n,n") (match_operand:QI 2 "const_int_operand" "n,n")) (match_operand:QI 3 "src_operand" "rLm,rLm")) @@ -3348,7 +3370,7 @@ (set_attr "data" "uint16,uint16")]) (define_peephole - [(parallel [(set (zero_extract:QI (match_operand:QI 0 "ext_reg_operand" "=d") + [(parallel [(set (zero_extract:QI (match_operand:QI 0 "ext_reg_operand" "+d") (match_operand:QI 1 "const_int_operand" "n") (match_operand:QI 2 "const_int_operand" "n")) (match_operand:QI 3 "src_operand" "rLm")) @@ -3380,7 +3402,7 @@ ; If one of the operands is not a register, then we should ; emit two insns, using a scratch register. This will produce ; better code in loops if the source operand is invariant, since -; the source reload can be optimised out. During reload we cannot +; the source reload can be optimized out. During reload we cannot ; use change_address or force_reg. (define_expand "movqf" [(set (match_operand:QF 0 "src_operand" "") @@ -3394,8 +3416,8 @@ ; This can generate invalid stack slot displacements (define_split - [(set (match_operand:QI 0 "reg_operand" "=r") - (unspec:QI [(match_operand:QF 1 "reg_operand" "f")] 12))] + [(set (match_operand:QI 0 "reg_operand" "") + (unspec:QI [(match_operand:QF 1 "reg_operand" "")] UNSPEC_STOREQF_INT))] "reload_completed" [(set (match_dup 3) (match_dup 1)) (set (match_dup 0) (match_dup 2))] @@ -3406,14 +3428,14 @@ (define_insn "storeqf_int" [(set (match_operand:QI 0 "reg_operand" "=r") - (unspec:QI [(match_operand:QF 1 "reg_operand" "f")] 12))] + (unspec:QI [(match_operand:QF 1 "reg_operand" "f")] UNSPEC_STOREQF_INT))] "" "#" [(set_attr "type" "multi")]) (define_split - [(parallel [(set (match_operand:QI 0 "reg_operand" "=r") - (unspec:QI [(match_operand:QF 1 "reg_operand" "f")] 12)) + [(parallel [(set (match_operand:QI 0 "reg_operand" "") + (unspec:QI [(match_operand:QF 1 "reg_operand" "")] UNSPEC_STOREQF_INT)) (clobber (reg:CC 21))])] "reload_completed" [(set (mem:QF (pre_inc:QI (reg:QI 20))) @@ -3438,7 +3460,7 @@ (define_insn "storeqf_int_clobber" [(parallel [(set (match_operand:QI 0 "reg_operand" "=r") - (unspec:QI [(match_operand:QF 1 "reg_operand" "f")] 12)) + (unspec:QI [(match_operand:QF 1 "reg_operand" "f")] UNSPEC_STOREQF_INT)) (clobber (reg:CC 21))])] "" "#" @@ -3447,8 +3469,8 @@ ; This can generate invalid stack slot displacements (define_split - [(set (match_operand:QF 0 "reg_operand" "=f") - (unspec:QF [(match_operand:QI 1 "reg_operand" "r")] 11))] + [(set (match_operand:QF 0 "reg_operand" "") + (unspec:QF [(match_operand:QI 1 "reg_operand" "")] UNSPEC_LOADQF_INT))] "reload_completed" [(set (match_dup 2) (match_dup 1)) (set (match_dup 0) (match_dup 3))] @@ -3459,14 +3481,14 @@ (define_insn "loadqf_int" [(set (match_operand:QF 0 "reg_operand" "=f") - (unspec:QF [(match_operand:QI 1 "reg_operand" "r")] 11))] + (unspec:QF [(match_operand:QI 1 "reg_operand" "r")] UNSPEC_LOADQF_INT))] "" "#" [(set_attr "type" "multi")]) (define_split - [(parallel [(set (match_operand:QF 0 "reg_operand" "=f") - (unspec:QF [(match_operand:QI 1 "reg_operand" "r")] 11)) + [(parallel [(set (match_operand:QF 0 "reg_operand" "") + (unspec:QF [(match_operand:QI 1 "reg_operand" "")] UNSPEC_LOADQF_INT)) (clobber (reg:CC 21))])] "reload_completed" [(set (mem:QI (pre_inc:QI (reg:QI 20))) @@ -3478,7 +3500,7 @@ (define_insn "loadqf_int_clobber" [(parallel [(set (match_operand:QF 0 "reg_operand" "=f") - (unspec:QF [(match_operand:QI 1 "reg_operand" "r")] 11)) + (unspec:QF [(match_operand:QI 1 "reg_operand" "r")] UNSPEC_LOADQF_INT)) (clobber (reg:CC 21))])] "" "#" @@ -3540,14 +3562,14 @@ ; ; PUSH/POP ; -(define_insn "*pushqf" +(define_insn "pushqf" [(set (mem:QF (pre_inc:QI (reg:QI 20))) (match_operand:QF 0 "reg_operand" "f"))] "" "pushf\\t%0" [(set_attr "type" "push")]) -(define_insn "*popqf" +(define_insn "popqf" [(set (match_operand:QF 0 "reg_operand" "=f") (mem:QF (post_dec:QI (reg:QI 20)))) (clobber (reg:CC 21))] @@ -3555,6 +3577,14 @@ "popf\\t%0" [(set_attr "type" "pop")]) +(define_insn "popqf_unspec" + [(set (unspec:QF [(match_operand:QF 0 "reg_operand" "=f")] UNSPEC_POPQF) + (mem:QF (post_dec:QI (reg:QI 20)))) + (clobber (match_dup 0)) + (clobber (reg:CC 21))] + "" + "popf\\t%0" + [(set_attr "type" "pop")]) ; ; ABSF @@ -3663,21 +3693,40 @@ (match_dup 3))) (set (match_dup 4) (float:QF (match_dup 1)))]) - (set (match_dup 6) + (set (match_dup 2) (if_then_else:QF (lt (reg:CC 21) (const_int 0)) (match_dup 5) (match_dup 2))) (parallel [(set (match_operand:QF 0 "reg_operand" "") - (plus:QF (match_dup 6) (match_dup 4))) + (plus:QF (match_dup 2) (match_dup 4))) (clobber (reg:CC_NOOV 21))])] "" "operands[2] = gen_reg_rtx (QFmode); operands[3] = CONST0_RTX (QFmode); operands[4] = gen_reg_rtx (QFmode); operands[5] = gen_reg_rtx (QFmode); - operands[6] = gen_reg_rtx (QFmode); - emit_move_insn (operands[5], - immed_real_const_1 (REAL_VALUE_ATOF (\"4294967296.0\", QFmode), QFmode));") + emit_move_insn (operands[5], CONST_DOUBLE_ATOF (\"4294967296.0\", QFmode));") + +(define_expand "floatunsqihf2" + [(set (match_dup 2) (match_dup 3)) + (parallel [(set (reg:CC 21) + (compare:CC (float:HF (match_operand:QI 1 "src_operand" "")) + (match_dup 3))) + (set (match_dup 4) + (float:HF (match_dup 1)))]) + (set (match_dup 2) + (if_then_else:HF (lt (reg:CC 21) (const_int 0)) + (match_dup 5) + (match_dup 2))) + (parallel [(set (match_operand:HF 0 "reg_operand" "") + (plus:HF (match_dup 2) (match_dup 4))) + (clobber (reg:CC_NOOV 21))])] + "" + "operands[2] = gen_reg_rtx (HFmode); + operands[3] = CONST0_RTX (HFmode); + operands[4] = gen_reg_rtx (HFmode); + operands[5] = gen_reg_rtx (HFmode); + emit_move_insn (operands[5], CONST_DOUBLE_ATOF (\"4294967296.0\", HFmode));") (define_insn "floatqihf2" [(set (match_operand:HF 0 "reg_operand" "=h") @@ -3687,6 +3736,16 @@ "float\\t%1,%0" [(set_attr "type" "unarycc")]) +(define_insn "*floatqihf2_set" + [(set (reg:CC 21) + (compare:CC (float:HF (match_operand:QI 1 "src_operand" "rIm")) + (match_operand:QF 2 "fp_zero_operand" "G"))) + (set (match_operand:HF 0 "reg_operand" "=h") + (float:HF (match_dup 1)))] + "" + "float\\t%1,%0" + [(set_attr "type" "unarycc")]) + ; ; FIX ; @@ -3745,39 +3804,46 @@ (fix:HI (match_operand:QF 1 "src_operand" ""))) (clobber (reg:CC 21))])] "" - "c4x_emit_libcall (FIX_TRUNCQFHI2_LIBCALL, FIX, HImode, QFmode, 2, operands); + "c4x_emit_libcall (fix_truncqfhi2_libfunc, FIX, HImode, QFmode, 2, operands); DONE;") -; Is this allowed to be implementation dependent? If so, we can -; omit the conditional load. Otherwise we should emit a split. (define_expand "fixuns_truncqfqi2" - [(parallel [(set (reg:CC 21) - (compare:CC (fix:QI (match_operand:QF 1 "src_operand" "fHm")) - (const_int 0))) - (set (match_dup 2) - (fix:QI (match_dup 1)))]) - (set (match_operand:QI 0 "reg_operand" "=r") - (if_then_else:QI (lt (reg:CC 21) (const_int 0)) - (const_int 0) - (match_dup 2)))] + [(parallel [(set (match_dup 2) + (fix:QI (match_operand:QF 1 "src_operand" "fHm"))) + (clobber (reg:CC 21))]) + (parallel [(set (match_dup 3) + (minus:QF (match_dup 1) (match_dup 5))) + (clobber (reg:CC_NOOV 21))]) + (parallel [(set (reg:CC 21) + (compare:CC (fix:QI (match_dup 3)) + (const_int 0))) + (set (match_dup 4) + (fix:QI (match_dup 3)))]) + (parallel [(set (match_dup 4) (unspec:QI [(match_dup 2)] UNSPEC_LDIV)) + (use (reg:CC 21))]) + (set (match_operand:QI 0 "reg_operand" "=r") (match_dup 4))] "" - "operands[2] = gen_reg_rtx (QImode);") + "operands[2] = gen_reg_rtx (QImode); + operands[3] = gen_reg_rtx (QFmode); + operands[4] = gen_reg_rtx (QImode); + operands[5] = gen_reg_rtx (QFmode); + emit_move_insn (operands[5], CONST_DOUBLE_ATOF (\"4294967296.0\", QFmode));") (define_expand "fixuns_truncqfhi2" [(parallel [(set (match_operand:HI 0 "reg_operand" "") (unsigned_fix:HI (match_operand:QF 1 "src_operand" ""))) (clobber (reg:CC 21))])] "" - "c4x_emit_libcall (FIXUNS_TRUNCQFHI2_LIBCALL, UNSIGNED_FIX, + "c4x_emit_libcall (fixuns_truncqfhi2_libfunc, UNSIGNED_FIX, HImode, QFmode, 2, operands); DONE;") ; ; RCPF ; -(define_insn "*rcpfqf_clobber" +(define_insn "rcpfqf_clobber" [(set (match_operand:QF 0 "reg_operand" "=f") - (unspec:QF [(match_operand:QF 1 "src_operand" "fHm")] 5)) + (unspec:QF [(match_operand:QF 1 "src_operand" "fHm")] UNSPEC_RCPF)) (clobber (reg:CC_NOOV 21))] "! TARGET_C3X" "rcpf\\t%1,%0" @@ -3788,7 +3854,7 @@ ; (define_insn "*rsqrfqf_clobber" [(set (match_operand:QF 0 "reg_operand" "=f") - (unspec:QF [(match_operand:QF 1 "src_operand" "fHm")] 10)) + (unspec:QF [(match_operand:QF 1 "src_operand" "fHm")] UNSPEC_RSQRF)) (clobber (reg:CC_NOOV 21))] "! TARGET_C3X" "rsqrf\\t%1,%0" @@ -3799,7 +3865,7 @@ ; (define_insn "*rndqf_clobber" [(set (match_operand:QF 0 "reg_operand" "=f") - (unspec:QF [(match_operand:QF 1 "src_operand" "fHm")] 6)) + (unspec:QF [(match_operand:QF 1 "src_operand" "fHm")] UNSPEC_RND)) (clobber (reg:CC_NOOV 21))] "! TARGET_C3X" "rnd\\t%1,%0" @@ -3809,7 +3875,7 @@ ; Inlined float square root for C4x (define_expand "sqrtqf2_inline" [(parallel [(set (match_dup 2) - (unspec:QF [(match_operand:QF 1 "src_operand" "")] 10)) + (unspec:QF [(match_operand:QF 1 "src_operand" "")] UNSPEC_RSQRF)) (clobber (reg:CC_NOOV 21))]) (parallel [(set (match_dup 3) (mult:QF (match_dup 5) (match_dup 1))) (clobber (reg:CC_NOOV 21))]) @@ -3832,7 +3898,7 @@ (parallel [(set (match_dup 4) (mult:QF (match_dup 2) (match_dup 1))) (clobber (reg:CC_NOOV 21))]) (parallel [(set (match_operand:QF 0 "reg_operand" "") - (unspec:QF [(match_dup 4)] 6)) + (unspec:QF [(match_dup 4)] UNSPEC_RND)) (clobber (reg:CC_NOOV 21))])] "! TARGET_C3X" "if (! reload_in_progress @@ -3841,10 +3907,8 @@ operands[2] = gen_reg_rtx (QFmode); operands[3] = gen_reg_rtx (QFmode); operands[4] = gen_reg_rtx (QFmode); - operands[5] = immed_real_const_1 (REAL_VALUE_ATOF (\"0.5\", QFmode), - QFmode); - operands[6] = immed_real_const_1 (REAL_VALUE_ATOF (\"1.5\", QFmode), - QFmode);") + operands[5] = CONST_DOUBLE_ATOF (\"0.5\", QFmode); + operands[6] = CONST_DOUBLE_ATOF (\"1.5\", QFmode);") (define_expand "sqrtqf2" [(parallel [(set (match_operand:QF 0 "reg_operand" "") @@ -3855,6 +3919,23 @@ DONE;") ; +; TOIEEE / FRIEEE +; +(define_insn "toieee" + [(set (match_operand:QF 0 "reg_operand" "=f") + (unspec:QF [(match_operand:QF 1 "src_operand" "fHm")] UNSPEC_TOIEEE)) + (clobber (reg:CC 21))] + "" + "toieee\\t%1,%0") + +(define_insn "frieee" + [(set (match_operand:QF 0 "reg_operand" "=f") + (unspec:QF [(match_operand:QF 1 "memory_operand" "m")] UNSPEC_FRIEEE)) + (clobber (reg:CC 21))] + "" + "frieee\\t%1,%0") + +; ; THREE OPERAND FLOAT INSTRUCTIONS ; @@ -4052,7 +4133,7 @@ ; Inlined float divide for C4x (define_expand "divqf3_inline" [(parallel [(set (match_dup 3) - (unspec:QF [(match_operand:QF 2 "src_operand" "")] 5)) + (unspec:QF [(match_operand:QF 2 "src_operand" "")] UNSPEC_RCPF)) (clobber (reg:CC_NOOV 21))]) (parallel [(set (match_dup 4) (mult:QF (match_dup 2) (match_dup 3))) (clobber (reg:CC_NOOV 21))]) @@ -4071,7 +4152,7 @@ (match_dup 3))) (clobber (reg:CC_NOOV 21))]) (parallel [(set (match_operand:QF 0 "reg_operand" "") - (unspec:QF [(match_dup 3)] 6)) + (unspec:QF [(match_dup 3)] UNSPEC_RND)) (clobber (reg:CC_NOOV 21))])] "! TARGET_C3X" "if (! reload_in_progress @@ -4104,7 +4185,7 @@ [(reg:CC 21) (const_int 0)]) (match_operand:QI 2 "src_operand" "rIm,0") (match_operand:QI 3 "src_operand" "0,rIm")))] - "" + "valid_operands (IF_THEN_ELSE, operands, QImode)" "@ ldi%1\\t%2,%0 ldi%I1\\t%3,%0" @@ -4119,12 +4200,21 @@ "GET_CODE (operands[1]) != LE && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != LT - && GET_CODE (operands[1]) != GT" + && GET_CODE (operands[1]) != GT + && valid_operands (IF_THEN_ELSE, operands, QImode)" "@ ldi%1\\t%2,%0 ldi%I1\\t%3,%0" [(set_attr "type" "binary")]) +(define_insn "*ldi_on_overflow" + [(set (match_operand:QI 0 "reg_operand" "=r") + (unspec:QI [(match_operand:QI 1 "src_operand" "rIm")] UNSPEC_LDIV)) + (use (reg:CC 21))] + "" + "ldiv\\t%1,%0" + [(set_attr "type" "unary")]) + ; Move operand 2 to operand 0 if condition (operand 1) is true ; else move operand 3 to operand 0. ; The temporary register is required below because some of the operands @@ -4142,8 +4232,8 @@ if (ccreg == NULL_RTX) FAIL; emit_insn (gen_rtx_SET (QImode, operands[0], gen_rtx_IF_THEN_ELSE (QImode, - gen_rtx (code, VOIDmode, ccreg, const0_rtx), - operands[2], operands[3]))); + gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx), + operands[2], operands[3]))); DONE;}") (define_insn "*ldf_conditional" @@ -4152,7 +4242,7 @@ [(reg:CC 21) (const_int 0)]) (match_operand:QF 2 "src_operand" "fHm,0") (match_operand:QF 3 "src_operand" "0,fHm")))] - "" + "valid_operands (IF_THEN_ELSE, operands, QFmode)" "@ ldf%1\\t%2,%0 ldf%I1\\t%3,%0" @@ -4167,7 +4257,8 @@ "GET_CODE (operands[1]) != LE && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != LT - && GET_CODE (operands[1]) != GT" + && GET_CODE (operands[1]) != GT + && valid_operands (IF_THEN_ELSE, operands, QFmode)" "@ ldf%1\\t%2,%0 ldf%I1\\t%3,%0" @@ -4185,8 +4276,51 @@ if (ccreg == NULL_RTX) FAIL; emit_insn (gen_rtx_SET (QFmode, operands[0], gen_rtx_IF_THEN_ELSE (QFmode, - gen_rtx (code, VOIDmode, ccreg, const0_rtx), - operands[2], operands[3]))); + gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx), + operands[2], operands[3]))); + DONE;}") + +(define_insn "*ldhf_conditional" + [(set (match_operand:HF 0 "reg_operand" "=h,h") + (if_then_else:HF (match_operator 1 "comparison_operator" + [(reg:CC 21) (const_int 0)]) + (match_operand:HF 2 "src_operand" "hH,0") + (match_operand:HF 3 "src_operand" "0,hH")))] + "" + "@ + ldf%1\\t%2,%0 + ldf%I1\\t%3,%0" + [(set_attr "type" "binary")]) + +(define_insn "*ldhf_conditional_noov" + [(set (match_operand:HF 0 "reg_operand" "=h,h") + (if_then_else:HF (match_operator 1 "comparison_operator" + [(reg:CC_NOOV 21) (const_int 0)]) + (match_operand:HF 2 "src_operand" "hH,0") + (match_operand:HF 3 "src_operand" "0,hH")))] + "GET_CODE (operands[1]) != LE + && GET_CODE (operands[1]) != GE + && GET_CODE (operands[1]) != LT + && GET_CODE (operands[1]) != GT" + "@ + ldf%1\\t%2,%0 + ldf%I1\\t%3,%0" + [(set_attr "type" "binary")]) + +(define_expand "movhfcc" + [(set (match_operand:HF 0 "reg_operand" "") + (if_then_else:HF (match_operand 1 "comparison_operator" "") + (match_operand:HF 2 "src_operand" "") + (match_operand:HF 3 "src_operand" "")))] + "" + "{ + enum rtx_code code = GET_CODE (operands[1]); + rtx ccreg = c4x_gen_compare_reg (code, c4x_compare_op0, c4x_compare_op1); + if (ccreg == NULL_RTX) FAIL; + emit_insn (gen_rtx_SET (HFmode, operands[0], + gen_rtx_IF_THEN_ELSE (HFmode, + gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx), + operands[2], operands[3]))); DONE;}") (define_expand "seq" @@ -4317,7 +4451,7 @@ (define_insn "*bu" [(set (pc) - (unspec [(match_operand:QI 0 "reg_operand" "r")] 1))] + (unspec [(match_operand:QI 0 "reg_operand" "r")] UNSPEC_BU))] "" "bu%#\\t%0" [(set_attr "type" "jump")]) @@ -4488,6 +4622,34 @@ [(set_attr "type" "binarycc")]) ; +; TOIEEE/STF +; + +(define_insn "*toieee_movqf_clobber" + [(set (match_operand:QF 0 "ext_low_reg_operand" "=q") + (unspec:QF [(match_operand:QF 1 "par_ind_operand" "S<>")] UNSPEC_TOIEEE)) + (set (match_operand:QF 2 "par_ind_operand" "=S<>") + (match_operand:QF 3 "ext_low_reg_operand" "q")) + (clobber (reg:CC 21))] + "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QFmode)" + "toieee\\t%1,%0\\n||\\tstf\\t%3,%2" + [(set_attr "type" "binarycc")]) + +; +; FRIEEE/STF +; + +(define_insn "*frieee_movqf_clobber" + [(set (match_operand:QF 0 "ext_low_reg_operand" "=q") + (unspec:QF [(match_operand:QF 1 "par_ind_operand" "S<>")] UNSPEC_FRIEEE)) + (set (match_operand:QF 2 "par_ind_operand" "=S<>") + (match_operand:QF 3 "ext_low_reg_operand" "q")) + (clobber (reg:CC 21))] + "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QFmode)" + "frieee\\t%1,%0\\n||\\tstf\\t%3,%2" + [(set_attr "type" "binarycc")]) + +; ; PARALLEL INTEGER INSTRUCTIONS ; @@ -4901,7 +5063,8 @@ "! TARGET_C3X" "* if (final_sequence) - return \"laj%U0\\t%C0\"; + return c4x_check_laj_p (insn) + ? \"nop\\n\\tlaj%U0\\t%C0\" : \"laj%U0\\t%C0\"; else return \"call%U0\\t%C0\";" [(set_attr "type" "laj")]) @@ -4919,6 +5082,13 @@ force_reg (Pmode, XEXP (operands[0], 0))); }") +(define_insn "nodb_call" + [(call (mem:QI (match_operand:QI 0 "call_address_operand" "Ur")) + (const_int 0))] + "" + "call%U0\\t%C0" + [(set_attr "type" "call")]) + (define_insn "*callv_c3x" [(set (match_operand 0 "" "=r") (call (mem:QI (match_operand:QI 1 "call_address_operand" "Ur")) @@ -4942,7 +5112,8 @@ "! TARGET_C3X" "* if (final_sequence) - return \"laj%U1\\t%C1\"; + return c4x_check_laj_p (insn) + ? \"nop\\n\\tlaj%U1\\t%C1\" : \"laj%U1\\t%C1\"; else return \"call%U1\\t%C1\";" [(set_attr "type" "laj")]) @@ -4963,17 +5134,29 @@ (define_insn "return" [(return)] - "c4x_null_epilogue_p ()" + "! c4x_null_epilogue_p ()" + "rets" + [(set_attr "type" "rets")]) + +(define_insn "return_from_epilogue" + [(return)] + "reload_completed && ! c4x_interrupt_function_p ()" "rets" [(set_attr "type" "rets")]) +(define_insn "return_from_interrupt_epilogue" + [(return)] + "reload_completed && c4x_interrupt_function_p ()" + "reti" + [(set_attr "type" "rets")]) + (define_insn "*return_cc" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" [(reg:CC 21) (const_int 0)]) (return) (pc)))] - "c4x_null_epilogue_p ()" + "! c4x_null_epilogue_p ()" "rets%0" [(set_attr "type" "rets")]) @@ -4987,7 +5170,7 @@ && GET_CODE (operands[0]) != GE && GET_CODE (operands[0]) != LT && GET_CODE (operands[0]) != GT - && c4x_null_epilogue_p ()" + && ! c4x_null_epilogue_p ()" "rets%0" [(set_attr "type" "rets")]) @@ -4997,7 +5180,7 @@ [(reg:CC 21) (const_int 0)]) (pc) (return)))] - "c4x_null_epilogue_p ()" + "! c4x_null_epilogue_p ()" "rets%I0" [(set_attr "type" "rets")]) @@ -5011,7 +5194,7 @@ && GET_CODE (operands[0]) != GE && GET_CODE (operands[0]) != LT && GET_CODE (operands[0]) != GT - && c4x_null_epilogue_p ()" + && ! c4x_null_epilogue_p ()" "rets%I0" [(set_attr "type" "rets")]) @@ -5021,13 +5204,52 @@ "br%#\\t%l0" [(set_attr "type" "jump")]) +(define_insn "trap" + [(trap_if (const_int 1) (const_int 31))] + "" + "trapu\\t31" + [(set_attr "type" "call")]) + +(define_expand "conditional_trap" + [(trap_if (match_operand 0 "comparison_operator" "") + (match_operand 1 "const_int_operand" ""))] + "" + "{ + enum rtx_code code = GET_CODE (operands[1]); + rtx ccreg = c4x_gen_compare_reg (code, c4x_compare_op0, c4x_compare_op1); + if (ccreg == NULL_RTX) FAIL; + if (GET_MODE (ccreg) == CCmode) + emit_insn (gen_cond_trap_cc (operands[0], operands[1])); + else + emit_insn (gen_cond_trap_cc_noov (operands[0], operands[1])); + DONE;}") + +(define_insn "cond_trap_cc" + [(trap_if (match_operator 0 "comparison_operator" + [(reg:CC 21) (const_int 0)]) + (match_operand 1 "const_int_operand" ""))] + "" + "trap%0\\t31" + [(set_attr "type" "call")]) + +(define_insn "cond_trap_cc_noov" + [(trap_if (match_operator 0 "comparison_operator" + [(reg:CC_NOOV 21) (const_int 0)]) + (match_operand 1 "const_int_operand" ""))] + "GET_CODE (operands[0]) != LE + && GET_CODE (operands[0]) != GE + && GET_CODE (operands[0]) != LT + && GET_CODE (operands[0]) != GT" + "trap%0\\t31" + [(set_attr "type" "call")]) + ; ; DBcond ; ; Note we have to emit a dbu instruction if there are no delay slots ; to fill. ; Also note that GCC will try to reverse a loop to see if it can -; utilise this instruction. However, if there are more than one +; utilize this instruction. However, if there are more than one ; memory reference in the loop, it cannot guarantee that reversing ; the loop will work :( (see check_dbra_loop() in loop.c) ; Note that the C3x only decrements the 24 LSBs of the address register @@ -5042,6 +5264,7 @@ (set (match_dup 0) (plus:QI (match_dup 0) (const_int -1))) + (use (reg:QI 20)) (clobber (reg:CC_NOOV 21))] "TARGET_DB && TARGET_LOOP_UNSIGNED" "* @@ -5078,6 +5301,7 @@ (set (match_dup 0) (plus:QI (match_dup 0) (const_int -1))) + (use (reg:QI 20)) (clobber (reg:CC_NOOV 21))] "reload_completed && TARGET_DB && TARGET_LOOP_UNSIGNED" [(parallel [(set (pc) @@ -5112,6 +5336,7 @@ (set (match_dup 0) (plus:QI (match_dup 0) (const_int -1))) + (use (reg:QI 20)) (clobber (reg:CC_NOOV 21))] "TARGET_DB && (find_reg_note (insn, REG_NONNEG, 0) || TARGET_LOOP_UNSIGNED)" "* @@ -5150,6 +5375,7 @@ (set (match_dup 0) (plus:QI (match_dup 0) (const_int -1))) + (use (reg:QI 20)) (clobber (reg:CC_NOOV 21))] "reload_completed && TARGET_DB && TARGET_LOOP_UNSIGNED" [(parallel [(set (pc) @@ -5176,6 +5402,22 @@ "nop") ; Default to misc type attr. +(define_insn "return_indirect_internal" + [(return) + (use (match_operand:QI 0 "reg_operand" ""))] + "reload_completed" + "bu%#\\t%0" + [(set_attr "type" "jump")]) + +(define_expand "prologue" + [(const_int 1)] + "" + "c4x_expand_prologue (); DONE;") + +(define_expand "epilogue" + [(const_int 1)] + "" + "c4x_expand_epilogue (); DONE;") ; ; RPTB @@ -5194,7 +5436,7 @@ (define_insn "rpts_top" [(unspec [(use (label_ref (match_operand 0 "" ""))) - (use (label_ref (match_operand 1 "" "")))] 2) + (use (label_ref (match_operand 1 "" "")))] UNSPEC_RPTS) (clobber (reg:QI 25)) (clobber (reg:QI 26))] "" @@ -5207,7 +5449,7 @@ ; This pattern needs to be emitted at the start of the loop to ; say that RS and RE are loaded. (define_insn "rptb_init" - [(unspec [(match_operand:QI 0 "register_operand" "va")] 22) + [(unspec [(match_operand:QI 0 "register_operand" "va")] UNSPEC_RPTB_INIT) (clobber (reg:QI 25)) (clobber (reg:QI 26))] "" @@ -5245,6 +5487,7 @@ (const_int -1))) (use (reg:QI 25)) (use (reg:QI 26)) + (use (reg:QI 20)) (clobber (reg:CC_NOOV 21))] "" "* @@ -5275,6 +5518,7 @@ (use (match_operand:QI 4 "const_int_operand" "")) (use (reg:QI 25)) (use (reg:QI 26)) + (use (reg:QI 20)) (clobber (reg:CC_NOOV 21))] "reload_completed" [(parallel [(set (pc) @@ -5300,7 +5544,7 @@ (use (label_ref (match_operand 4 "" "")))] "" "if (! TARGET_LOOP_UNSIGNED - && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > (1U << 31)) + && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > ((unsigned) 1 << 31)) FAIL; if (INTVAL (operands[3]) > 1 || ! TARGET_RPTB) { @@ -5315,10 +5559,6 @@ DONE; ") -; The current low overhead looping code is naff and is not failsafe -; If you want RTPB instructions to be generated, apply the patches -; from www.elec.canterbury.ac.nz/c4x. This will utilise the -; doloop_begin and doloop_end patterns in this MD. (define_expand "decrement_and_branch_on_count" [(parallel [(set (pc) (if_then_else (ge (match_operand:QI 0 "register_operand" "") @@ -5334,7 +5574,7 @@ "0" "") -(define_expand "movstrqi_small2" +(define_expand "movmemqi_small" [(parallel [(set (mem:BLK (match_operand:BLK 0 "src_operand" "")) (mem:BLK (match_operand:BLK 1 "src_operand" ""))) (use (match_operand:QI 2 "immediate_operand" "")) @@ -5388,80 +5628,60 @@ ; BLOCK MOVE ; We should probably get RC loaded when using RPTB automagically... ; There's probably no need to call _memcpy() if we don't get -; a immediate operand for the size. We could do a better job here +; an immediate operand for the size. We could do a better job here ; than most memcpy() implementations. ; operand 2 is the number of bytes ; operand 3 is the shared alignment ; operand 4 is a scratch register -(define_insn "movstrqi_small" - [(set (mem:BLK (match_operand:QI 0 "addr_reg_operand" "+a")) - (mem:BLK (match_operand:QI 1 "addr_reg_operand" "+a"))) +(define_insn "movmemqi_large" + [(set (mem:BLK (match_operand:QI 0 "addr_reg_operand" "a")) + (mem:BLK (match_operand:QI 1 "addr_reg_operand" "a"))) (use (match_operand:QI 2 "immediate_operand" "i")) (use (match_operand:QI 3 "immediate_operand" "")) (clobber (match_operand:QI 4 "ext_low_reg_operand" "=&q")) - (clobber (match_dup 0)) - (clobber (match_dup 1))] - "" - "* - { - int i; - int len = INTVAL (operands[2]); - int first = 1; - - for (i = 0; i < len; i++) - { - if (first) - output_asm_insn (\"ldiu\\t*%1++,%4\", operands); - else - output_asm_insn (\"|| ldi\\t*%1++,%4\", operands); - output_asm_insn (\"sti\\t%4,*%0++\", operands); - first = 0; - } - return \"\"; - } - " - [(set_attr "type" "multi")]) - -(define_insn "movstrqi_large" - [(set (mem:BLK (match_operand:QI 0 "addr_reg_operand" "+a")) - (mem:BLK (match_operand:QI 1 "addr_reg_operand" "+a"))) - (use (match_operand:QI 2 "immediate_operand" "i")) - (use (match_operand:QI 3 "immediate_operand" "")) - (clobber (match_operand:QI 4 "ext_low_reg_operand" "=&q")) - (clobber (match_dup 0)) - (clobber (match_dup 1)) + (clobber (match_scratch:QI 5 "=0")) + (clobber (match_scratch:QI 6 "=1")) (clobber (reg:QI 25)) (clobber (reg:QI 26)) (clobber (reg:QI 27))] "" "* { + int i; int len = INTVAL (operands[2]); output_asm_insn (\"ldiu\\t*%1++,%4\", operands); - if (TARGET_RPTS_CYCLES (len)) + if (len < 8) { - output_asm_insn (\"rpts\\t%2-2\", operands); - output_asm_insn (\"sti\\t%4,*%0++\", operands); - output_asm_insn (\"|| ldi\\t*%1++,%4\", operands); - return \"sti\\t%4,*%0++\"; + for (i = 1; i < len; i++) + { + output_asm_insn (\"sti\\t%4,*%0++\", operands); + output_asm_insn (\"|| ldi\\t*%1++,%4\", operands); + } } else { - output_asm_insn (\"ldiu\\t%2-2,rc\", operands); - output_asm_insn (\"rptb\\t$+1\", operands); - output_asm_insn (\"sti\\t%4,*%0++\", operands); - output_asm_insn (\"|| ldi\\t*%1++,%4\", operands); - - return \"sti\\t%4,*%0++\"; + if (TARGET_RPTS_CYCLES (len)) + { + output_asm_insn (\"rpts\\t%2-2\", operands); + output_asm_insn (\"sti\\t%4,*%0++\", operands); + output_asm_insn (\"|| ldi\\t*%1++,%4\", operands); + } + else + { + output_asm_insn (\"ldiu\\t%2-2,rc\", operands); + output_asm_insn (\"rptb\\t$+1\", operands); + output_asm_insn (\"sti\\t%4,*%0++\", operands); + output_asm_insn (\"|| ldi\\t*%1++,%4\", operands); + } } - } - " - [(set_attr "type" "multi")]) + return \"sti\\t%4,*%0++\"; + }" + [(set_attr "type" "multi")]) ; Operand 2 is the count, operand 3 is the alignment. -(define_expand "movstrqi" +(define_expand "movmemqi" [(parallel [(set (mem:BLK (match_operand:BLK 0 "src_operand" "")) (mem:BLK (match_operand:BLK 1 "src_operand" ""))) (use (match_operand:QI 2 "immediate_operand" "")) @@ -5480,19 +5700,20 @@ operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); tmp = gen_reg_rtx (QImode); - if (INTVAL (operands[2]) < 8) - emit_insn (gen_movstrqi_small2 (operands[0], operands[1], operands[2], + /* Disabled because of reload problems. */ + if (0 && INTVAL (operands[2]) < 8) + emit_insn (gen_movmemqi_small (operands[0], operands[1], operands[2], operands[3], tmp)); else { - emit_insn (gen_movstrqi_large (operands[0], operands[1], operands[2], + emit_insn (gen_movmemqi_large (operands[0], operands[1], operands[2], operands[3], tmp)); } DONE; }") -(define_insn "*cmpstrqi" +(define_insn "*cmpstrnqi" [(set (match_operand:QI 0 "ext_reg_operand" "=d") (compare:QI (mem:BLK (match_operand:QI 1 "addr_reg_operand" "+a")) (mem:BLK (match_operand:QI 2 "addr_reg_operand" "+a")))) @@ -5509,7 +5730,7 @@ return \"\"; }") -(define_expand "cmpstrqi" +(define_expand "cmpstrnqi" [(parallel [(set (match_operand:QI 0 "reg_operand" "") (compare:QI (match_operand:BLK 1 "general_operand" "") (match_operand:BLK 2 "general_operand" ""))) @@ -5581,7 +5802,7 @@ "reload_completed" [(set (match_dup 0) (float_extend:HF (match_dup 2))) (set (match_dup 0) (unspec:HF [(subreg:QI (match_dup 0) 0) - (match_dup 3)] 8))] + (match_dup 3)] UNSPEC_LOADHF_INT))] "operands[2] = c4x_operand_subword (operands[1], 0, 1, HFmode); operands[3] = c4x_operand_subword (operands[1], 1, 1, HFmode); PUT_MODE (operands[2], QFmode); @@ -5593,7 +5814,7 @@ "reload_completed && 0" [(set (match_dup 0) (float_extend:HF (match_dup 2))) (set (match_dup 0) (unspec:HF [(subreg:QI (match_dup 0) 0) - (match_dup 3)] 8))] + (match_dup 3)] UNSPEC_LOADHF_INT))] "operands[2] = c4x_operand_subword (operands[1], 0, 1, HFmode); operands[3] = c4x_operand_subword (operands[1], 1, 1, HFmode); PUT_MODE (operands[2], QFmode); @@ -5604,7 +5825,7 @@ (match_operand:HF 1 "reg_operand" ""))] "reload_completed" [(set (match_dup 2) (float_truncate:QF (match_dup 1))) - (set (match_dup 3) (unspec:QI [(match_dup 1)] 9))] + (set (match_dup 3) (unspec:QI [(match_dup 1)] UNSPEC_STOREHF_INT))] "operands[2] = c4x_operand_subword (operands[0], 0, 1, HFmode); operands[3] = c4x_operand_subword (operands[0], 1, 1, HFmode); PUT_MODE (operands[2], QFmode); @@ -5614,17 +5835,15 @@ [(set (match_operand:HF 0 "reg_operand" "=h") (float_extend:HF (match_operand:QF 1 "src_operand" "fHm")))] "" - "@ - ldfu\\t%1,%0" + "ldfu\\t%1,%0" [(set_attr "type" "unary")]) (define_insn "*loadhf_int" - [(set (match_operand:HF 0 "reg_operand" "=h") + [(set (match_operand:HF 0 "reg_operand" "+h") (unspec:HF [(subreg:QI (match_dup 0) 0) - (match_operand:QI 1 "src_operand" "rIm")] 8))] + (match_operand:QI 1 "src_operand" "rIm")] UNSPEC_LOADHF_INT))] "" - "@ - ldiu\\t%1,%0" + "ldiu\\t%1,%0" [(set_attr "type" "unary")]) (define_insn "*storehf_float" @@ -5636,10 +5855,9 @@ (define_insn "*storehf_int" [(set (match_operand:QI 0 "memory_operand" "=m") - (unspec:QI [(match_operand:HF 1 "reg_operand" "h")] 9))] + (unspec:QI [(match_operand:HF 1 "reg_operand" "h")] UNSPEC_STOREHF_INT))] "" - "@ - sti\\t%1,%0" + "sti\\t%1,%0" [(set_attr "type" "store")]) (define_insn "extendqfhf2" @@ -5660,7 +5878,7 @@ ; ; PUSH/POP ; -(define_insn "*pushhf" +(define_insn "pushhf" [(set (mem:HF (pre_inc:QI (reg:QI 20))) (match_operand:HF 0 "reg_operand" "h"))] "" @@ -5674,7 +5892,7 @@ [(set (mem:QF (pre_inc:QI (reg:QI 20))) (float_truncate:QF (match_dup 0))) (set (mem:QI (pre_inc:QI (reg:QI 20))) - (unspec:QI [(match_dup 0)] 9))] + (unspec:QI [(match_dup 0)] UNSPEC_STOREHF_INT))] "") (define_insn "pushhf_trunc" @@ -5686,13 +5904,13 @@ (define_insn "pushhf_int" [(set (mem:QI (pre_inc:QI (reg:QI 20))) - (unspec:QI [(match_operand:HF 0 "reg_operand" "h")] 9))] + (unspec:QI [(match_operand:HF 0 "reg_operand" "h")] UNSPEC_STOREHF_INT))] "" "push\\t%0" [(set_attr "type" "push")]) -; we can not use this because the popf will destroy the low 8 bits -;(define_insn "*pophf" +; we cannot use this because the popf will destroy the low 8 bits +;(define_insn "pophf" ; [(set (match_operand:HF 0 "reg_operand" "=h") ; (mem:HF (post_dec:QI (reg:QI 20)))) ; (clobber (reg:CC 21))] @@ -5710,18 +5928,17 @@ (clobber (reg:CC 21))]) (parallel [(set (match_dup 0) (unspec:HF [(subreg:QI (match_dup 0) 0) - (mem:QI (post_dec:QI (reg:QI 20)))] 8)) + (mem:QI (post_dec:QI (reg:QI 20)))] UNSPEC_LOADHF_INT)) (clobber (reg:CC 21))])] "") (define_insn "*pophf_int" - [(set (match_operand:HF 0 "reg_operand" "=h") + [(set (match_operand:HF 0 "reg_operand" "+h") (unspec:HF [(subreg:QI (match_dup 0) 0) - (mem:QI (post_dec:QI (reg:QI 20)))] 8)) + (mem:QI (post_dec:QI (reg:QI 20)))] UNSPEC_LOADHF_INT)) (clobber (reg:CC 21))] "" - "@ - pop\\t%0" + "pop\\t%0" [(set_attr "type" "pop")]) (define_insn "*pophf_float" @@ -5729,13 +5946,72 @@ (float_extend:HF (mem:QF (post_dec:QI (reg:QI 20))))) (clobber (reg:CC 21))] "" - "@ - popf\\t%0" - [(set_attr "type" "unary")]) + "popf\\t%0" + [(set_attr "type" "pop")]) ; ; FIX ; +(define_expand "fixuns_trunchfqi2" + [(parallel [(set (match_dup 2) + (fix:QI (match_operand:HF 1 "reg_or_const_operand" "hH"))) + (clobber (reg:CC 21))]) + (parallel [(set (match_dup 3) + (minus:HF (match_dup 1) (match_dup 5))) + (clobber (reg:CC_NOOV 21))]) + (parallel [(set (reg:CC 21) + (compare:CC (fix:QI (match_dup 3)) + (const_int 0))) + (set (match_dup 4) + (fix:QI (match_dup 3)))]) + (parallel [(set (match_dup 4) (unspec:QI [(match_dup 2)] UNSPEC_LDIV)) + (use (reg:CC 21))]) + (set (match_operand:QI 0 "reg_operand" "=r") (match_dup 4))] + "" + "operands[2] = gen_reg_rtx (QImode); + operands[3] = gen_reg_rtx (HFmode); + operands[4] = gen_reg_rtx (QImode); + operands[5] = gen_reg_rtx (HFmode); + emit_move_insn (operands[5], CONST_DOUBLE_ATOF (\"4294967296.0\", HFmode));") + +(define_expand "fix_trunchfqi2" + [(parallel [(set (match_dup 2) + (fix:QI (match_operand:HF 1 "reg_or_const_operand" ""))) + (clobber (reg:CC 21))]) + (parallel [(set (match_dup 3) (neg:HF (match_dup 1))) + (clobber (reg:CC_NOOV 21))]) + (parallel [(set (match_dup 4) (fix:QI (match_dup 3))) + (clobber (reg:CC 21))]) + (parallel [(set (reg:CC_NOOV 21) + (compare:CC_NOOV (neg:QI (match_dup 4)) (const_int 0))) + (set (match_dup 5) (neg:QI (match_dup 4)))]) + (set (match_dup 2) + (if_then_else:QI (le (reg:CC 21) (const_int 0)) + (match_dup 5) + (match_dup 2))) + (set (match_operand:QI 0 "reg_operand" "=r") (match_dup 2))] + "" + "if (TARGET_FAST_FIX) + { + emit_insn (gen_fixhfqi_clobber (operands[0], operands[1])); + DONE; + } + operands[2] = gen_reg_rtx (QImode); + operands[3] = gen_reg_rtx (HFmode); + operands[4] = gen_reg_rtx (QImode); + operands[5] = gen_reg_rtx (QImode); + ") + +(define_insn "*fixhfqi_set" + [(set (reg:CC 21) + (compare:CC (fix:QI (match_operand:HF 1 "reg_or_const_operand" "hH")) + (const_int 0))) + (set (match_operand:QI 0 "ext_reg_operand" "=d") + (fix:QI (match_dup 1)))] + "" + "fix\\t%1,%0" + [(set_attr "type" "unarycc")]) + (define_insn "fixhfqi_clobber" [(set (match_operand:QI 0 "reg_operand" "=dc") (fix:QI (match_operand:HF 1 "reg_or_const_operand" "hH"))) @@ -5744,6 +6020,23 @@ "fix\\t%1,%0" [(set_attr "type" "unarycc")]) +(define_expand "fix_trunchfhi2" + [(parallel [(set (match_operand:HI 0 "reg_operand" "") + (fix:HI (match_operand:HF 1 "reg_operand" ""))) + (clobber (reg:CC 21))])] + "" + "c4x_emit_libcall (fix_trunchfhi2_libfunc, FIX, HImode, HFmode, 2, operands); + DONE;") + +(define_expand "fixuns_trunchfhi2" + [(parallel [(set (match_operand:HI 0 "reg_operand" "") + (unsigned_fix:HI (match_operand:HF 1 "reg_operand" ""))) + (clobber (reg:CC 21))])] + "" + "c4x_emit_libcall (fixuns_trunchfhi2_libfunc, UNSIGNED_FIX, + HImode, HFmode, 2, operands); + DONE;") + ; ; ABSF ; @@ -5788,31 +6081,31 @@ (define_expand "neghf2" [(parallel [(set (match_operand:HF 0 "reg_operand" "") (neg:HF (match_operand:HF 1 "reg_or_const_operand" ""))) - (clobber (reg:CC 21))])] + (clobber (reg:CC_NOOV 21))])] "" "") (define_insn "*neghf2_clobber" [(set (match_operand:HF 0 "reg_operand" "=h") (neg:HF (match_operand:HF 1 "reg_or_const_operand" "hH"))) - (clobber (reg:CC 21))] + (clobber (reg:CC_NOOV 21))] "" "negf\\t%1,%0" [(set_attr "type" "unarycc")]) (define_insn "*neghf2_test" - [(set (reg:CC 21) - (compare:CC (neg:HF (match_operand:HF 1 "reg_or_const_operand" "hH")) - (match_operand:HF 2 "fp_zero_operand" "G"))) + [(set (reg:CC_NOOV 21) + (compare:CC_NOOV (neg:HF (match_operand:HF 1 "reg_or_const_operand" "hH")) + (match_operand:HF 2 "fp_zero_operand" "G"))) (clobber (match_scratch:HF 0 "=h"))] "" "negf\\t%1,%0" [(set_attr "type" "unarycc")]) (define_insn "*neghf2_set" - [(set (reg:CC 21) - (compare:CC (neg:HF (match_operand:HF 1 "reg_or_const_operand" "hH")) - (match_operand:HF 2 "fp_zero_operand" "G"))) + [(set (reg:CC_NOOV 21) + (compare:CC_NOOV (neg:HF (match_operand:HF 1 "reg_or_const_operand" "hH")) + (match_operand:HF 2 "fp_zero_operand" "G"))) (set (match_operand:HF 0 "reg_operand" "=h") (neg:HF (match_dup 1)))] "" @@ -5824,7 +6117,7 @@ ; (define_insn "*rcpfhf_clobber" [(set (match_operand:HF 0 "reg_operand" "=h") - (unspec:HF [(match_operand:HF 1 "reg_or_const_operand" "hH")] 5)) + (unspec:HF [(match_operand:HF 1 "reg_or_const_operand" "hH")] UNSPEC_RCPF)) (clobber (reg:CC_NOOV 21))] "! TARGET_C3X" "rcpf\\t%1,%0" @@ -5835,7 +6128,7 @@ ; (define_insn "*rsqrfhf_clobber" [(set (match_operand:HF 0 "reg_operand" "=h") - (unspec:HF [(match_operand:HF 1 "reg_or_const_operand" "hH")] 10)) + (unspec:HF [(match_operand:HF 1 "reg_or_const_operand" "hH")] UNSPEC_RSQRF)) (clobber (reg:CC_NOOV 21))] "! TARGET_C3X" "rsqrf\\t%1,%0" @@ -5846,7 +6139,7 @@ ; (define_insn "*rndhf_clobber" [(set (match_operand:HF 0 "reg_operand" "=h") - (unspec:HF [(match_operand:HF 1 "reg_or_const_operand" "hH")] 6)) + (unspec:HF [(match_operand:HF 1 "reg_or_const_operand" "hH")] UNSPEC_RND)) (clobber (reg:CC_NOOV 21))] "! TARGET_C3X" "rnd\\t%1,%0" @@ -5856,7 +6149,7 @@ ; Inlined float square root for C4x (define_expand "sqrthf2_inline" [(parallel [(set (match_dup 2) - (unspec:HF [(match_operand:HF 1 "reg_operand" "")] 10)) + (unspec:HF [(match_operand:HF 1 "reg_operand" "")] UNSPEC_RSQRF)) (clobber (reg:CC_NOOV 21))]) (parallel [(set (match_dup 3) (mult:HF (match_dup 5) (match_dup 1))) (clobber (reg:CC_NOOV 21))]) @@ -5884,8 +6177,8 @@ operands[2] = gen_reg_rtx (HFmode); operands[3] = gen_reg_rtx (HFmode); operands[4] = gen_reg_rtx (HFmode); - operands[5] = immed_real_const_1 (REAL_VALUE_ATOF (\"0.5\", HFmode), HFmode); - operands[6] = immed_real_const_1 (REAL_VALUE_ATOF (\"1.5\", HFmode), HFmode); + operands[5] = CONST_DOUBLE_ATOF (\"0.5\", HFmode); + operands[6] = CONST_DOUBLE_ATOF (\"1.5\", HFmode); ") @@ -5897,24 +6190,6 @@ "emit_insn (gen_sqrthf2_inline (operands[0], operands[1])); DONE;") - -(define_expand "fix_trunchfhi2" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (fix:HI (match_operand:HF 1 "reg_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall (FIX_TRUNCHFHI2_LIBCALL, FIX, HImode, HFmode, 2, operands); - DONE;") - -(define_expand "fixuns_trunchfhi2" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (unsigned_fix:HI (match_operand:HF 1 "reg_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall (FIXUNS_TRUNCHFHI2_LIBCALL, UNSIGNED_FIX, - HImode, HFmode, 2, operands); - DONE;") - ; ; THREE OPERAND LONG DOUBLE INSTRUCTIONS ; @@ -5951,7 +6226,7 @@ ; ; MULF ; -; The C3x MPYF only uses 24 bit precision while the C4x uses 32 bit precison. +; The C3x MPYF only uses 24-bit precision while the C4x uses 32-bit precision. ; (define_expand "mulhf3" [(parallel [(set (match_operand:HF 0 "reg_operand" "=h") @@ -6003,7 +6278,7 @@ ; Inlined float divide for C4x (define_expand "divhf3_inline" [(parallel [(set (match_dup 3) - (unspec:HF [(match_operand:HF 2 "reg_operand" "")] 5)) + (unspec:HF [(match_operand:HF 2 "reg_operand" "")] UNSPEC_RCPF)) (clobber (reg:CC_NOOV 21))]) (parallel [(set (match_dup 4) (mult:HF (match_dup 2) (match_dup 3))) (clobber (reg:CC_NOOV 21))]) @@ -6119,8 +6394,8 @@ [(set_attr "type" "multi")]) (define_split - [(set (match_operand:HI 0 "reg_operand" "=?dc") - (sign_extend:HI (match_operand:QI 1 "src_operand" "rIm"))) + [(set (match_operand:HI 0 "reg_operand" "") + (sign_extend:HI (match_operand:QI 1 "src_operand" ""))) (clobber (reg:CC 21))] "reload_completed && TARGET_C3X" [(set (match_dup 2) (match_dup 1)) @@ -6131,8 +6406,8 @@ operands[3] = c4x_operand_subword (operands[0], 1, 0, HImode);") (define_split - [(set (match_operand:HI 0 "reg_operand" "=?dc") - (sign_extend:HI (match_operand:QI 1 "src_operand" "rIm"))) + [(set (match_operand:HI 0 "reg_operand" "") + (sign_extend:HI (match_operand:QI 1 "src_operand" ""))) (clobber (reg:CC 21))] "reload_completed && ! TARGET_C3X" [(set (match_dup 2) (match_dup 1)) @@ -6143,7 +6418,7 @@ (define_insn "zero_extendqihi2" [(set (match_operand:HI 0 "reg_operand" "=?dc") - (zero_extend:HI (match_operand:QI 1 "src_operand" "rIm"))) + (zero_extend:HI (match_operand:QI 1 "nonimmediate_src_operand" "rm"))) (clobber (reg:CC 21))] "" "#" @@ -6152,8 +6427,8 @@ ; If operand0 and operand1 are the same register we don't need ; the first set. (define_split - [(set (match_operand:HI 0 "reg_operand" "=?dc") - (zero_extend:HI (match_operand:QI 1 "src_operand" "rIm"))) + [(set (match_operand:HI 0 "reg_operand" "") + (zero_extend:HI (match_operand:QI 1 "nonimmediate_src_operand" ""))) (clobber (reg:CC 21))] "reload_completed" [(set (match_dup 2) (match_dup 1)) @@ -6252,7 +6527,7 @@ (float:QF (match_operand:HI 1 "src_operand" ""))) (clobber (reg:CC 21))])] "" - "c4x_emit_libcall (FLOATHIQF2_LIBCALL, FLOAT, QFmode, HImode, 2, operands); + "c4x_emit_libcall (floathiqf2_libfunc, FLOAT, QFmode, HImode, 2, operands); DONE;") (define_expand "floatunshiqf2" @@ -6260,7 +6535,7 @@ (unsigned_float:QF (match_operand:HI 1 "src_operand" ""))) (clobber (reg:CC 21))])] "" - "c4x_emit_libcall (FLOATUNSHIQF2_LIBCALL, UNSIGNED_FLOAT, + "c4x_emit_libcall (floatunshiqf2_libfunc, UNSIGNED_FLOAT, QFmode, HImode, 2, operands); DONE;") @@ -6269,7 +6544,7 @@ (float:HF (match_operand:HI 1 "src_operand" ""))) (clobber (reg:CC 21))])] "" - "c4x_emit_libcall (FLOATHIHF2_LIBCALL, FLOAT, HFmode, HImode, 2, operands); + "c4x_emit_libcall (floathihf2_libfunc, FLOAT, HFmode, HImode, 2, operands); DONE;") (define_expand "floatunshihf2" @@ -6277,7 +6552,7 @@ (unsigned_float:HF (match_operand:HI 1 "src_operand" ""))) (clobber (reg:CC 21))])] "" - "c4x_emit_libcall (FLOATUNSHIHF2_LIBCALL, UNSIGNED_FLOAT, + "c4x_emit_libcall (floatunshihf2_libfunc, UNSIGNED_FLOAT, HFmode, HImode, 2, operands); DONE;") @@ -6579,7 +6854,7 @@ /* If the shift count is greater than 32 this will do an arithmetic right shift. However, we need a logical right shift. */ (parallel [(set (match_dup 9) - (ashift:QI (match_dup 4) (unspec:QI [(match_dup 10)] 3))) + (ashift:QI (match_dup 4) (unspec:QI [(match_dup 10)] UNSPEC_LSH))) (clobber (reg:CC 21))]) (set (match_dup 6) (match_dup 8)) (parallel [(set (match_dup 5) @@ -6678,6 +6953,22 @@ c4x_compare_op1 = operands[1]; DONE;") +(define_insn "*cmphi_cc" + [(set (reg:CC 21) + (compare:CC (match_operand:HI 0 "src_operand" "rR,rS<>") + (match_operand:HI 1 "src_operand" "R,rS<>")))] + "valid_operands (COMPARE, operands, HImode)" + "#" + [(set_attr "type" "multi")]) + +(define_insn "*cmphi_cc_noov" + [(set (reg:CC_NOOV 21) + (compare:CC_NOOV (match_operand:HI 0 "src_operand" "rR,rS<>") + (match_operand:HI 1 "src_operand" "R,rS<>")))] + "valid_operands (COMPARE, operands, HImode)" + "#" + [(set_attr "type" "multi")]) + ; This works only before reload because we need 2 extra registers. ; Use unspec to avoid recursive split. (define_split @@ -6687,7 +6978,7 @@ "! reload_completed" [(parallel [(set (reg:CC 21) (unspec:CC [(compare:CC (match_dup 0) - (match_dup 1))] 4)) + (match_dup 1))] UNSPEC_CMPHI)) (clobber (match_scratch:QI 2 "")) (clobber (match_scratch:QI 3 ""))])] "") @@ -6699,16 +6990,37 @@ "! reload_completed" [(parallel [(set (reg:CC_NOOV 21) (unspec:CC_NOOV [(compare:CC_NOOV (match_dup 0) - (match_dup 1))] 4)) + (match_dup 1))] UNSPEC_CMPHI)) (clobber (match_scratch:QI 2 "")) (clobber (match_scratch:QI 3 ""))])] "") ; This is normally not used. The define splits above are used first. +(define_split + [(set (reg:CC 21) + (compare:CC (match_operand:HI 0 "src_operand" "") + (match_operand:HI 1 "src_operand" "")))] + "reload_completed" + [(parallel [(set (reg:CC 21) + (compare:CC (match_dup 0) (match_dup 1))) + (use (reg:QI 20))])] + "") + +(define_split + [(set (reg:CC_NOOV 21) + (compare:CC_NOOV (match_operand:HI 0 "src_operand" "") + (match_operand:HI 1 "src_operand" "")))] + "reload_completed" + [(parallel [(set (reg:CC_NOOV 21) + (compare:CC_NOOV (match_dup 0) (match_dup 1))) + (use (reg:QI 20))])] + "") + (define_insn "*cmphi" [(set (reg:CC 21) (compare:CC (match_operand:HI 0 "src_operand" "rR,rS<>") - (match_operand:HI 1 "src_operand" "R,rS<>")))] + (match_operand:HI 1 "src_operand" "R,rS<>"))) + (use (reg:QI 20))] "valid_operands (COMPARE, operands, HImode)" "* { @@ -6758,7 +7070,8 @@ (define_insn "*cmphi_noov" [(set (reg:CC_NOOV 21) (compare:CC_NOOV (match_operand:HI 0 "src_operand" "rR,rS<>") - (match_operand:HI 1 "src_operand" "R,rS<>")))] + (match_operand:HI 1 "src_operand" "R,rS<>"))) + (use (reg:QI 20))] "valid_operands (COMPARE, operands, HImode)" "* { @@ -6809,7 +7122,7 @@ (define_insn "cmphi_cc" [(set (reg:CC 21) (unspec:CC [(compare:CC (match_operand:HI 0 "src_operand" "rR,rS<>") - (match_operand:HI 1 "src_operand" "R,rS<>"))] 4)) + (match_operand:HI 1 "src_operand" "R,rS<>"))] UNSPEC_CMPHI)) (clobber (match_scratch:QI 2 "=&d,&d")) (clobber (match_scratch:QI 3 "=&c,&c"))] "valid_operands (COMPARE, operands, HImode)" @@ -6825,7 +7138,7 @@ (define_insn "cmphi_cc_noov" [(set (reg:CC_NOOV 21) (unspec:CC_NOOV [(compare:CC_NOOV (match_operand:HI 0 "src_operand" "rR,rS<>") - (match_operand:HI 1 "src_operand" "R,rS<>"))] 4)) + (match_operand:HI 1 "src_operand" "R,rS<>"))] UNSPEC_CMPHI)) (clobber (match_scratch:QI 2 "=&d,&d")) (clobber (match_scratch:QI 3 "=&c,&c"))] "valid_operands (COMPARE, operands, HImode)" @@ -6844,7 +7157,8 @@ (match_operand:HI 2 "src_operand" ""))) (clobber (reg:CC 21))])] "" - "c4x_emit_libcall3 (MULHI3_LIBCALL, MULT, HImode, operands); + "c4x_emit_libcall3 (optab_libfunc (smul_optab, HImode), + MULT, HImode, operands); DONE;") @@ -6884,6 +7198,7 @@ (set (match_dup 0) (plus:QI (match_dup 0) (const_int -1))) + (use (reg:QI 20)) (clobber (reg:CC_NOOV 21))])] "! c4x_label_conflict (insn, operands[2], operands[1])" "db%I3\\t%0,%l1\\n\\tb%3\\t%l2" @@ -6917,7 +7232,7 @@ (match_operand:QI 1 "general_operand" "")) (clobber (reg:QI 31))]) (return)] - "c4x_null_epilogue_p ()" + "! c4x_null_epilogue_p ()" "* if (REG_P (operands[0])) return \"bu%#\\t%C0\"; @@ -6931,7 +7246,7 @@ (match_operand:QI 2 "general_operand" ""))) (clobber (reg:QI 31))]) (return)] - "c4x_null_epilogue_p ()" + "! c4x_null_epilogue_p ()" "* if (REG_P (operands[1])) return \"bu%#\\t%C1\"; @@ -6966,9 +7281,9 @@ "stf\\t%1,*%0++\\n\\tstf\\t%2,*%0++") -; The following two peepholes remove an unecessary load +; The following two peepholes remove an unnecessary load ; often found at the end of a function. These peepholes -; could be generalised to other binary operators. They shouldn't +; could be generalized to other binary operators. They shouldn't ; be required if we run a post reload mop-up pass. (define_peephole [(parallel [(set (match_operand:QF 0 "ext_reg_operand" "")