URL
https://opencores.org/ocsvn/hf-risc/hf-risc/trunk
Subversion Repositories hf-risc
Compare Revisions
- This comparison shows the changes necessary to convert path
/hf-risc
- from Rev 11 to Rev 12
- ↔ Reverse comparison
Rev 11 → Rev 12
/trunk/ucore/control.vhd
File deleted
/trunk/ucore/peripherals_busmux.vhd
File deleted
/trunk/ucore/alu.vhd
File deleted
/trunk/ucore/bshifter.vhd
File deleted
/trunk/ucore/datapath.vhd
File deleted
/trunk/ucore/reg_bank.vhd
File deleted
/trunk/ucore/uart.vhd
File deleted
/trunk/software/app/interrupt_test.c
File deleted
/trunk/software/app/xtea_hw.c
File deleted
/trunk/software/app/fib.c
File deleted
/trunk/software/app/buzzer.c
File deleted
/trunk/software/app/xtea.c
File deleted
/trunk/software/app/buzzer2.c
File deleted
/trunk/software/app/exp_io.c
File deleted
/trunk/software/app/hello.c
File deleted
/trunk/software/app/test_crc.c
File deleted
/trunk/software/app/sort.c
File deleted
/trunk/software/app/leds.c
File deleted
/trunk/software/app/test64.c
File deleted
/trunk/software/app/test_spi.c
File deleted
/trunk/software/include/libc.h
File deleted
/trunk/software/include/hf_risc.h
File deleted
/trunk/software/include/mcp23s17.h
File deleted
/trunk/software/boot/monitor.c
File deleted
/trunk/software/lib/crt0.s
File deleted
/trunk/software/lib/libc.c
File deleted
/trunk/software/lib/hf_risc.ld
File deleted
/trunk/software/lib/spi.c
File deleted
/trunk/software/lib/mcp23s17.c
File deleted
/trunk/software/makefile
File deleted
/trunk/sim/ram.vhd
File deleted
/trunk/sim/hf-risc_tb.vhd
File deleted
/trunk/sim/boot.txt
File deleted
/trunk/sim/boot_ram.vhd
File deleted
/trunk/peripherals/xtea/xtea.vhd
File deleted
/trunk/peripherals/xtea/xtea_tb.vhd
File deleted
/trunk/tools/hf_risc_sim/hf_risc_sim.c
File deleted
/trunk/tools/build_mips_toolchain/hello.c
File deleted
trunk/tools/build_mips_toolchain/build_mips_toolchain
Property changes :
Deleted: svn:executable
## -1 +0,0 ##
-*
\ No newline at end of property
Index: trunk/tools/build_mips_toolchain/mips.md
===================================================================
--- trunk/tools/build_mips_toolchain/mips.md (revision 11)
+++ trunk/tools/build_mips_toolchain/mips.md (nonexistent)
@@ -1,7190 +0,0 @@
-;; Mips.md Machine Description for MIPS based processors
-;; Copyright (C) 1989-2014 Free Software Foundation, Inc.
-;; Contributed by A. Lichnewsky, lich@inria.inria.fr
-;; Changes by Michael Meissner, meissner@osf.org
-;; 64-bit r4000 support by Ian Lance Taylor, ian@cygnus.com, and
-;; Brendan Eich, brendan@microunity.com.
-
-;; 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
-;; .
-
-(define_enum "processor" [
- r3000
- 4kc
- 4kp
- 5kc
- 5kf
- 20kc
- 24kc
- 24kf2_1
- 24kf1_1
- 74kc
- 74kf2_1
- 74kf1_1
- 74kf3_2
- loongson_2e
- loongson_2f
- loongson_3a
- m4k
- octeon
- octeon2
- r3900
- r6000
- r4000
- r4100
- r4111
- r4120
- r4130
- r4300
- r4600
- r4650
- r4700
- r5000
- r5400
- r5500
- r5900
- r7000
- r8000
- r9000
- r10000
- sb1
- sb1a
- sr71000
- xlr
- xlp
-])
-
-(define_c_enum "unspec" [
- ;; Unaligned accesses.
- UNSPEC_LOAD_LEFT
- UNSPEC_LOAD_RIGHT
- UNSPEC_STORE_LEFT
- UNSPEC_STORE_RIGHT
-
- ;; Integer operations that are too cumbersome to describe directly.
- UNSPEC_WSBH
- UNSPEC_DSBH
- UNSPEC_DSHD
-
- ;; Floating-point moves.
- UNSPEC_LOAD_LOW
- UNSPEC_LOAD_HIGH
- UNSPEC_STORE_WORD
- UNSPEC_MFHC1
- UNSPEC_MTHC1
-
- ;; Floating-point environment.
- UNSPEC_GET_FCSR
- UNSPEC_SET_FCSR
-
- ;; HI/LO moves.
- UNSPEC_MFHI
- UNSPEC_MTHI
- UNSPEC_SET_HILO
-
- ;; GP manipulation.
- UNSPEC_LOADGP
- UNSPEC_COPYGP
- UNSPEC_MOVE_GP
- UNSPEC_POTENTIAL_CPRESTORE
- UNSPEC_CPRESTORE
- UNSPEC_RESTORE_GP
- UNSPEC_EH_RETURN
- UNSPEC_GP
- UNSPEC_SET_GOT_VERSION
- UNSPEC_UPDATE_GOT_VERSION
-
- ;; Symbolic accesses.
- UNSPEC_LOAD_CALL
- UNSPEC_LOAD_GOT
- UNSPEC_TLS_LDM
- UNSPEC_TLS_GET_TP
- UNSPEC_UNSHIFTED_HIGH
-
- ;; MIPS16 constant pools.
- UNSPEC_ALIGN
- UNSPEC_CONSTTABLE_INT
- UNSPEC_CONSTTABLE_FLOAT
-
- ;; Blockage and synchronisation.
- UNSPEC_BLOCKAGE
- UNSPEC_CLEAR_HAZARD
- UNSPEC_RDHWR
- UNSPEC_SYNCI
- UNSPEC_SYNC
-
- ;; Cache manipulation.
- UNSPEC_MIPS_CACHE
- UNSPEC_R10K_CACHE_BARRIER
-
- ;; Interrupt handling.
- UNSPEC_ERET
- UNSPEC_DERET
- UNSPEC_DI
- UNSPEC_EHB
- UNSPEC_RDPGPR
- UNSPEC_COP0
-
- ;; Used in a call expression in place of args_size. It's present for PIC
- ;; indirect calls where it contains args_size and the function symbol.
- UNSPEC_CALL_ATTR
-
- ;; MIPS16 casesi jump table dispatch.
- UNSPEC_CASESI_DISPATCH
-
- ;; Stack checking.
- UNSPEC_PROBE_STACK_RANGE
-])
-
-(define_constants
- [(TLS_GET_TP_REGNUM 3)
- (GET_FCSR_REGNUM 2)
- (SET_FCSR_REGNUM 4)
- (MIPS16_T_REGNUM 24)
- (PIC_FUNCTION_ADDR_REGNUM 25)
- (RETURN_ADDR_REGNUM 31)
- (CPRESTORE_SLOT_REGNUM 76)
- (GOT_VERSION_REGNUM 79)
-
- ;; PIC long branch sequences are never longer than 100 bytes.
- (MAX_PIC_BRANCH_LENGTH 100)
- ]
-)
-
-(include "predicates.md")
-(include "constraints.md")
-
-;; ....................
-;;
-;; Attributes
-;;
-;; ....................
-
-(define_attr "got" "unset,xgot_high,load"
- (const_string "unset"))
-
-;; For jal instructions, this attribute is DIRECT when the target address
-;; is symbolic and INDIRECT when it is a register.
-(define_attr "jal" "unset,direct,indirect"
- (const_string "unset"))
-
-;; This attribute is YES if the instruction is a jal macro (not a
-;; real jal instruction).
-;;
-;; jal is always a macro for TARGET_CALL_CLOBBERED_GP because it includes
-;; an instruction to restore $gp. Direct jals are also macros for
-;; !TARGET_ABSOLUTE_JUMPS because they first load the target address
-;; into a register.
-(define_attr "jal_macro" "no,yes"
- (cond [(eq_attr "jal" "direct")
- (symbol_ref "(TARGET_CALL_CLOBBERED_GP || !TARGET_ABSOLUTE_JUMPS
- ? JAL_MACRO_YES : JAL_MACRO_NO)")
- (eq_attr "jal" "indirect")
- (symbol_ref "(TARGET_CALL_CLOBBERED_GP
- ? JAL_MACRO_YES : JAL_MACRO_NO)")]
- (const_string "no")))
-
-;; Classification of moves, extensions and truncations. Most values
-;; are as for "type" (see below) but there are also the following
-;; move-specific values:
-;;
-;; constN move an N-constraint integer into a MIPS16 register
-;; sll0 "sll DEST,SRC,0", which on 64-bit targets is guaranteed
-;; to produce a sign-extended DEST, even if SRC is not
-;; properly sign-extended
-;; ext_ins EXT, DEXT, INS or DINS instruction
-;; andi a single ANDI instruction
-;; loadpool move a constant into a MIPS16 register by loading it
-;; from the pool
-;; shift_shift a shift left followed by a shift right
-;;
-;; This attribute is used to determine the instruction's length and
-;; scheduling type. For doubleword moves, the attribute always describes
-;; the split instructions; in some cases, it is more appropriate for the
-;; scheduling type to be "multi" instead.
-(define_attr "move_type"
- "unknown,load,fpload,store,fpstore,mtc,mfc,mtlo,mflo,imul,move,fmove,
- const,constN,signext,ext_ins,logical,arith,sll0,andi,loadpool,
- shift_shift"
- (const_string "unknown"))
-
-(define_attr "alu_type" "unknown,add,sub,not,nor,and,or,xor"
- (const_string "unknown"))
-
-;; Main data type used by the insn
-(define_attr "mode" "unknown,none,QI,HI,SI,DI,TI,SF,DF,TF,FPSW"
- (const_string "unknown"))
-
-;; True if the main data type is twice the size of a word.
-(define_attr "dword_mode" "no,yes"
- (cond [(and (eq_attr "mode" "DI,DF")
- (not (match_test "TARGET_64BIT")))
- (const_string "yes")
-
- (and (eq_attr "mode" "TI,TF")
- (match_test "TARGET_64BIT"))
- (const_string "yes")]
- (const_string "no")))
-
-;; Attributes describing a sync loop. These loops have the form:
-;;
-;; if (RELEASE_BARRIER == YES) sync
-;; 1: OLDVAL = *MEM
-;; if ((OLDVAL & INCLUSIVE_MASK) != REQUIRED_OLDVAL) goto 2
-;; CMP = 0 [delay slot]
-;; $TMP1 = OLDVAL & EXCLUSIVE_MASK
-;; $TMP2 = INSN1 (OLDVAL, INSN1_OP2)
-;; $TMP3 = INSN2 ($TMP2, INCLUSIVE_MASK)
-;; $AT |= $TMP1 | $TMP3
-;; if (!commit (*MEM = $AT)) goto 1.
-;; if (INSN1 != MOVE && INSN1 != LI) NEWVAL = $TMP3 [delay slot]
-;; CMP = 1
-;; if (ACQUIRE_BARRIER == YES) sync
-;; 2:
-;;
-;; where "$" values are temporaries and where the other values are
-;; specified by the attributes below. Values are specified as operand
-;; numbers and insns are specified as enums. If no operand number is
-;; specified, the following values are used instead:
-;;
-;; - OLDVAL: $AT
-;; - CMP: NONE
-;; - NEWVAL: $AT
-;; - INCLUSIVE_MASK: -1
-;; - REQUIRED_OLDVAL: OLDVAL & INCLUSIVE_MASK
-;; - EXCLUSIVE_MASK: 0
-;;
-;; MEM and INSN1_OP2 are required.
-;;
-;; Ideally, the operand attributes would be integers, with -1 meaning "none",
-;; but the gen* programs don't yet support that.
-(define_attr "sync_mem" "none,0,1,2,3,4,5" (const_string "none"))
-(define_attr "sync_oldval" "none,0,1,2,3,4,5" (const_string "none"))
-(define_attr "sync_cmp" "none,0,1,2,3,4,5" (const_string "none"))
-(define_attr "sync_newval" "none,0,1,2,3,4,5" (const_string "none"))
-(define_attr "sync_inclusive_mask" "none,0,1,2,3,4,5" (const_string "none"))
-(define_attr "sync_exclusive_mask" "none,0,1,2,3,4,5" (const_string "none"))
-(define_attr "sync_required_oldval" "none,0,1,2,3,4,5" (const_string "none"))
-(define_attr "sync_insn1_op2" "none,0,1,2,3,4,5" (const_string "none"))
-(define_attr "sync_insn1" "move,li,addu,addiu,subu,and,andi,or,ori,xor,xori"
- (const_string "move"))
-(define_attr "sync_insn2" "nop,and,xor,not"
- (const_string "nop"))
-;; Memory model specifier.
-;; "0"-"9" values specify the operand that stores the memory model value.
-;; "10" specifies MEMMODEL_ACQ_REL,
-;; "11" specifies MEMMODEL_ACQUIRE.
-(define_attr "sync_memmodel" "" (const_int 10))
-
-;; Accumulator operand for madd patterns.
-(define_attr "accum_in" "none,0,1,2,3,4,5" (const_string "none"))
-
-;; Classification of each insn.
-;; branch conditional branch
-;; jump unconditional jump
-;; call unconditional call
-;; load load instruction(s)
-;; fpload floating point load
-;; fpidxload floating point indexed load
-;; store store instruction(s)
-;; fpstore floating point store
-;; fpidxstore floating point indexed store
-;; prefetch memory prefetch (register + offset)
-;; prefetchx memory indexed prefetch (register + register)
-;; condmove conditional moves
-;; mtc transfer to coprocessor
-;; mfc transfer from coprocessor
-;; mthi transfer to a hi register
-;; mtlo transfer to a lo register
-;; mfhi transfer from a hi register
-;; mflo transfer from a lo register
-;; const load constant
-;; arith integer arithmetic instructions
-;; logical integer logical instructions
-;; shift integer shift instructions
-;; slt set less than instructions
-;; signext sign extend instructions
-;; clz the clz and clo instructions
-;; pop the pop instruction
-;; trap trap if instructions
-;; imul integer multiply 2 operands
-;; imul3 integer multiply 3 operands
-;; imul3nc integer multiply 3 operands without clobbering HI/LO
-;; imadd integer multiply-add
-;; idiv integer divide 2 operands
-;; idiv3 integer divide 3 operands
-;; move integer register move ({,D}ADD{,U} with rt = 0)
-;; fmove floating point register move
-;; fadd floating point add/subtract
-;; fmul floating point multiply
-;; fmadd floating point multiply-add
-;; fdiv floating point divide
-;; frdiv floating point reciprocal divide
-;; frdiv1 floating point reciprocal divide step 1
-;; frdiv2 floating point reciprocal divide step 2
-;; fabs floating point absolute value
-;; fneg floating point negation
-;; fcmp floating point compare
-;; fcvt floating point convert
-;; fsqrt floating point square root
-;; frsqrt floating point reciprocal square root
-;; frsqrt1 floating point reciprocal square root step1
-;; frsqrt2 floating point reciprocal square root step2
-;; dspmac DSP MAC instructions not saturating the accumulator
-;; dspmacsat DSP MAC instructions that saturate the accumulator
-;; accext DSP accumulator extract instructions
-;; accmod DSP accumulator modify instructions
-;; dspalu DSP ALU instructions not saturating the result
-;; dspalusat DSP ALU instructions that saturate the result
-;; multi multiword sequence (or user asm statements)
-;; atomic atomic memory update instruction
-;; syncloop memory atomic operation implemented as a sync loop
-;; nop no operation
-;; ghost an instruction that produces no real code
-;; multimem microMIPS multiword load and store
-(define_attr "type"
- "unknown,branch,jump,call,load,fpload,fpidxload,store,fpstore,fpidxstore,
- prefetch,prefetchx,condmove,mtc,mfc,mthi,mtlo,mfhi,mflo,const,arith,logical,
- shift,slt,signext,clz,pop,trap,imul,imul3,imul3nc,imadd,idiv,idiv3,move,
- fmove,fadd,fmul,fmadd,fdiv,frdiv,frdiv1,frdiv2,fabs,fneg,fcmp,fcvt,fsqrt,
- frsqrt,frsqrt1,frsqrt2,dspmac,dspmacsat,accext,accmod,dspalu,dspalusat,
- multi,atomic,syncloop,nop,ghost,multimem"
- (cond [(eq_attr "jal" "!unset") (const_string "call")
- (eq_attr "got" "load") (const_string "load")
-
- (eq_attr "alu_type" "add,sub") (const_string "arith")
-
- (eq_attr "alu_type" "not,nor,and,or,xor") (const_string "logical")
-
- ;; If a doubleword move uses these expensive instructions,
- ;; it is usually better to schedule them in the same way
- ;; as the singleword form, rather than as "multi".
- (eq_attr "move_type" "load") (const_string "load")
- (eq_attr "move_type" "fpload") (const_string "fpload")
- (eq_attr "move_type" "store") (const_string "store")
- (eq_attr "move_type" "fpstore") (const_string "fpstore")
- (eq_attr "move_type" "mtc") (const_string "mtc")
- (eq_attr "move_type" "mfc") (const_string "mfc")
- (eq_attr "move_type" "mtlo") (const_string "mtlo")
- (eq_attr "move_type" "mflo") (const_string "mflo")
-
- ;; These types of move are always single insns.
- (eq_attr "move_type" "imul") (const_string "imul")
- (eq_attr "move_type" "fmove") (const_string "fmove")
- (eq_attr "move_type" "loadpool") (const_string "load")
- (eq_attr "move_type" "signext") (const_string "signext")
- (eq_attr "move_type" "ext_ins") (const_string "arith")
- (eq_attr "move_type" "arith") (const_string "arith")
- (eq_attr "move_type" "logical") (const_string "logical")
- (eq_attr "move_type" "sll0") (const_string "shift")
- (eq_attr "move_type" "andi") (const_string "logical")
-
- ;; These types of move are always split.
- (eq_attr "move_type" "constN,shift_shift")
- (const_string "multi")
-
- ;; These types of move are split for doubleword modes only.
- (and (eq_attr "move_type" "move,const")
- (eq_attr "dword_mode" "yes"))
- (const_string "multi")
- (eq_attr "move_type" "move") (const_string "move")
- (eq_attr "move_type" "const") (const_string "const")
- (eq_attr "sync_mem" "!none") (const_string "syncloop")]
- (const_string "unknown")))
-
-;; Mode for conversion types (fcvt)
-;; I2S integer to float single (SI/DI to SF)
-;; I2D integer to float double (SI/DI to DF)
-;; S2I float to integer (SF to SI/DI)
-;; D2I float to integer (DF to SI/DI)
-;; D2S double to float single
-;; S2D float single to double
-
-(define_attr "cnv_mode" "unknown,I2S,I2D,S2I,D2I,D2S,S2D"
- (const_string "unknown"))
-
-;; Is this an extended instruction in mips16 mode?
-(define_attr "extended_mips16" "no,yes"
- (if_then_else (ior ;; In general, constant-pool loads are extended
- ;; instructions. We don't yet optimize for 16-bit
- ;; PC-relative references.
- (eq_attr "move_type" "sll0,loadpool")
- (eq_attr "jal" "direct")
- (eq_attr "got" "load"))
- (const_string "yes")
- (const_string "no")))
-
-(define_attr "compression" "none,all,micromips"
- (const_string "none"))
-
-(define_attr "enabled" "no,yes"
- (if_then_else (ior (eq_attr "compression" "all,none")
- (and (eq_attr "compression" "micromips")
- (match_test "TARGET_MICROMIPS")))
- (const_string "yes")
- (const_string "no")))
-
-;; The number of individual instructions that a non-branch pattern generates,
-;; using units of BASE_INSN_LENGTH.
-(define_attr "insn_count" ""
- (cond [;; "Ghost" instructions occupy no space.
- (eq_attr "type" "ghost")
- (const_int 0)
-
- ;; Extended instructions count as 2.
- (and (eq_attr "extended_mips16" "yes")
- (match_test "TARGET_MIPS16"))
- (const_int 2)
-
- ;; A GOT load followed by an add of $gp. This is not used for MIPS16.
- (eq_attr "got" "xgot_high")
- (const_int 2)
-
- ;; SHIFT_SHIFTs are decomposed into two separate instructions.
- ;; They are extended instructions on MIPS16 targets.
- (eq_attr "move_type" "shift_shift")
- (if_then_else (match_test "TARGET_MIPS16")
- (const_int 4)
- (const_int 2))
-
- ;; Check for doubleword moves that are decomposed into two
- ;; instructions. The individual instructions are unextended
- ;; MIPS16 ones.
- (and (eq_attr "move_type" "mtc,mfc,mtlo,mflo,move")
- (eq_attr "dword_mode" "yes"))
- (const_int 2)
-
- ;; Constants, loads and stores are handled by external routines.
- (and (eq_attr "move_type" "const,constN")
- (eq_attr "dword_mode" "yes"))
- (symbol_ref "mips_split_const_insns (operands[1])")
- (eq_attr "move_type" "const,constN")
- (symbol_ref "mips_const_insns (operands[1])")
- (eq_attr "move_type" "load,fpload")
- (symbol_ref "mips_load_store_insns (operands[1], insn)")
- (eq_attr "move_type" "store,fpstore")
- (symbol_ref "mips_load_store_insns (operands[0], insn)
- + (TARGET_FIX_24K ? 1 : 0)")
-
- ;; In the worst case, a call macro will take 8 instructions:
- ;;
- ;; lui $25,%call_hi(FOO)
- ;; addu $25,$25,$28
- ;; lw $25,%call_lo(FOO)($25)
- ;; nop
- ;; jalr $25
- ;; nop
- ;; lw $gp,X($sp)
- ;; nop
- (eq_attr "jal_macro" "yes")
- (const_int 8)
-
- ;; Various VR4120 errata require a nop to be inserted after a macc
- ;; instruction. The assembler does this for us, so account for
- ;; the worst-case length here.
- (and (eq_attr "type" "imadd")
- (match_test "TARGET_FIX_VR4120"))
- (const_int 2)
-
- ;; VR4120 errata MD(4): if there are consecutive dmult instructions,
- ;; the result of the second one is missed. The assembler should work
- ;; around this by inserting a nop after the first dmult.
- (and (eq_attr "type" "imul,imul3")
- (eq_attr "mode" "DI")
- (match_test "TARGET_FIX_VR4120"))
- (const_int 2)
-
- (eq_attr "type" "idiv,idiv3")
- (symbol_ref "mips_idiv_insns ()")
-
- (not (eq_attr "sync_mem" "none"))
- (symbol_ref "mips_sync_loop_insns (insn, operands)")]
- (const_int 1)))
-
-;; Length of instruction in bytes. The default is derived from "insn_count",
-;; but there are special cases for branches (which must be handled here)
-;; and for compressed single instructions.
-(define_attr "length" ""
- (cond [(and (eq_attr "compression" "micromips,all")
- (eq_attr "dword_mode" "no")
- (match_test "TARGET_MICROMIPS"))
- (const_int 2)
-
- ;; Direct microMIPS branch instructions have a range of
- ;; [-0x10000,0xfffe], otherwise the range is [-0x20000,0x1fffc].
- ;; If a branch is outside this range, we have a choice of two
- ;; sequences.
- ;;
- ;; For PIC, an out-of-range branch like:
- ;;
- ;; bne r1,r2,target
- ;; dslot
- ;;
- ;; becomes the equivalent of:
- ;;
- ;; beq r1,r2,1f
- ;; dslot
- ;; la $at,target
- ;; jr $at
- ;; nop
- ;; 1:
- ;;
- ;; The non-PIC case is similar except that we use a direct
- ;; jump instead of an la/jr pair. Since the target of this
- ;; jump is an absolute 28-bit bit address (the other bits
- ;; coming from the address of the delay slot) this form cannot
- ;; cross a 256MB boundary. We could provide the option of
- ;; using la/jr in this case too, but we do not do so at
- ;; present.
- ;;
- ;; The value we specify here does not account for the delay slot
- ;; instruction, whose length is added separately. If the RTL
- ;; pattern has no explicit delay slot, mips_adjust_insn_length
- ;; will add the length of the implicit nop. The range of
- ;; [-0x20000, 0x1fffc] from the address of the delay slot
- ;; therefore translates to a range of:
- ;;
- ;; [-(0x20000 - sizeof (branch)), 0x1fffc - sizeof (slot)]
- ;; == [-0x1fffc, 0x1fff8]
- ;;
- ;; from the shorten_branches reference address.
- (and (eq_attr "type" "branch")
- (not (match_test "TARGET_MIPS16")))
- (cond [;; Any variant can handle the 17-bit range.
- (and (le (minus (match_dup 0) (pc)) (const_int 65532))
- (le (minus (pc) (match_dup 0)) (const_int 65534)))
- (const_int 4)
-
- ;; The 18-bit range is OK other than for microMIPS.
- (and (not (match_test "TARGET_MICROMIPS"))
- (and (le (minus (match_dup 0) (pc)) (const_int 131064))
- (le (minus (pc) (match_dup 0)) (const_int 131068))))
- (const_int 4)
-
- ;; The non-PIC case: branch, first delay slot, and J.
- (match_test "TARGET_ABSOLUTE_JUMPS")
- (const_int 12)]
-
- ;; Use MAX_PIC_BRANCH_LENGTH as a (gross) overestimate.
- ;; mips_adjust_insn_length substitutes the correct length.
- ;;
- ;; Note that we can't simply use (symbol_ref ...) here
- ;; because genattrtab needs to know the maximum length
- ;; of an insn.
- (const_int MAX_PIC_BRANCH_LENGTH))
-
- ;; An unextended MIPS16 branch has a range of [-0x100, 0xfe]
- ;; from the address of the following instruction, which leads
- ;; to a range of:
- ;;
- ;; [-(0x100 - sizeof (branch)), 0xfe]
- ;; == [-0xfe, 0xfe]
- ;;
- ;; from the shorten_branches reference address. Extended branches
- ;; likewise have a range of [-0x10000, 0xfffe] from the address
- ;; of the following instruction, which leads to a range of:
- ;;
- ;; [-(0x10000 - sizeof (branch)), 0xfffe]
- ;; == [-0xfffc, 0xfffe]
- ;;
- ;; from the reference address.
- ;;
- ;; When a branch is out of range, mips_reorg splits it into a form
- ;; that uses in-range branches. There are four basic sequences:
- ;;
- ;; (1) Absolute addressing with a readable text segment
- ;; (32-bit addresses):
- ;;
- ;; b... foo 2 bytes
- ;; move $1,$2 2 bytes
- ;; lw $2,label 2 bytes
- ;; jr $2 2 bytes
- ;; move $2,$1 2 bytes
- ;; .align 2 0 or 2 bytes
- ;; label:
- ;; .word target 4 bytes
- ;; foo:
- ;; (16 bytes in the worst case)
- ;;
- ;; (2) Absolute addressing with a readable text segment
- ;; (64-bit addresses):
- ;;
- ;; b... foo 2 bytes
- ;; move $1,$2 2 bytes
- ;; ld $2,label 2 bytes
- ;; jr $2 2 bytes
- ;; move $2,$1 2 bytes
- ;; .align 3 0 to 6 bytes
- ;; label:
- ;; .dword target 8 bytes
- ;; foo:
- ;; (24 bytes in the worst case)
- ;;
- ;; (3) Absolute addressing without a readable text segment
- ;; (which requires 32-bit addresses at present):
- ;;
- ;; b... foo 2 bytes
- ;; move $1,$2 2 bytes
- ;; lui $2,%hi(target) 4 bytes
- ;; sll $2,8 2 bytes
- ;; sll $2,8 2 bytes
- ;; addiu $2,%lo(target) 4 bytes
- ;; jr $2 2 bytes
- ;; move $2,$1 2 bytes
- ;; foo:
- ;; (20 bytes)
- ;;
- ;; (4) PIC addressing (which requires 32-bit addresses at present):
- ;;
- ;; b... foo 2 bytes
- ;; move $1,$2 2 bytes
- ;; lw $2,cprestore 0, 2 or 4 bytes
- ;; lw $2,%got(target)($2) 4 bytes
- ;; addiu $2,%lo(target) 4 bytes
- ;; jr $2 2 bytes
- ;; move $2,$1 2 bytes
- ;; foo:
- ;; (20 bytes in the worst case)
- (and (eq_attr "type" "branch")
- (match_test "TARGET_MIPS16"))
- (cond [(and (le (minus (match_dup 0) (pc)) (const_int 254))
- (le (minus (pc) (match_dup 0)) (const_int 254)))
- (const_int 2)
- (and (le (minus (match_dup 0) (pc)) (const_int 65534))
- (le (minus (pc) (match_dup 0)) (const_int 65532)))
- (const_int 4)
- (and (match_test "TARGET_ABICALLS")
- (not (match_test "TARGET_ABSOLUTE_ABICALLS")))
- (const_int 20)
- (match_test "Pmode == SImode")
- (const_int 16)
- ] (const_int 24))]
- (symbol_ref "get_attr_insn_count (insn) * BASE_INSN_LENGTH")))
-
-;; Attribute describing the processor.
-(define_enum_attr "cpu" "processor"
- (const (symbol_ref "mips_tune")))
-
-;; The type of hardware hazard associated with this instruction.
-;; DELAY means that the next instruction cannot read the result
-;; of this one. HILO means that the next two instructions cannot
-;; write to HI or LO.
-(define_attr "hazard" "none,delay,hilo"
- (cond [(and (eq_attr "type" "load,fpload,fpidxload")
- (match_test "ISA_HAS_LOAD_DELAY"))
- (const_string "delay")
-
- (and (eq_attr "type" "mfc,mtc")
- (match_test "ISA_HAS_XFER_DELAY"))
- (const_string "delay")
-
- (and (eq_attr "type" "fcmp")
- (match_test "ISA_HAS_FCMP_DELAY"))
- (const_string "delay")
-
- ;; The r4000 multiplication patterns include an mflo instruction.
- (and (eq_attr "type" "imul")
- (match_test "TARGET_FIX_R4000"))
- (const_string "hilo")
-
- (and (eq_attr "type" "mfhi,mflo")
- (not (match_test "ISA_HAS_HILO_INTERLOCKS")))
- (const_string "hilo")]
- (const_string "none")))
-
-;; Can the instruction be put into a delay slot?
-(define_attr "can_delay" "no,yes"
- (if_then_else (and (eq_attr "type" "!branch,call,jump")
- (eq_attr "hazard" "none")
- (match_test "get_attr_insn_count (insn) == 1"))
- (const_string "yes")
- (const_string "no")))
-
-;; Attribute defining whether or not we can use the branch-likely
-;; instructions.
-(define_attr "branch_likely" "no,yes"
- (if_then_else (match_test "GENERATE_BRANCHLIKELY")
- (const_string "yes")
- (const_string "no")))
-
-;; True if an instruction might assign to hi or lo when reloaded.
-;; This is used by the TUNE_MACC_CHAINS code.
-(define_attr "may_clobber_hilo" "no,yes"
- (if_then_else (eq_attr "type" "imul,imul3,imadd,idiv,mthi,mtlo")
- (const_string "yes")
- (const_string "no")))
-
-;; Describe a user's asm statement.
-(define_asm_attributes
- [(set_attr "type" "multi")
- (set_attr "can_delay" "no")])
-
-;; This mode iterator allows 32-bit and 64-bit GPR patterns to be generated
-;; from the same template.
-(define_mode_iterator GPR [SI (DI "TARGET_64BIT")])
-
-;; A copy of GPR that can be used when a pattern has two independent
-;; modes.
-(define_mode_iterator GPR2 [SI (DI "TARGET_64BIT")])
-
-(define_mode_iterator MOVEP1 [SI SF])
-(define_mode_iterator MOVEP2 [SI SF])
-
-;; This mode iterator allows :HILO to be used as the mode of the
-;; concatenated HI and LO registers.
-(define_mode_iterator HILO [(DI "!TARGET_64BIT") (TI "TARGET_64BIT")])
-
-;; This mode iterator allows :P to be used for patterns that operate on
-;; pointer-sized quantities. Exactly one of the two alternatives will match.
-(define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")])
-
-;; This mode iterator allows :MOVECC to be used anywhere that a
-;; conditional-move-type condition is needed.
-(define_mode_iterator MOVECC [SI (DI "TARGET_64BIT")
- (CC "TARGET_HARD_FLOAT
- && !TARGET_LOONGSON_2EF
- && !TARGET_MIPS5900")])
-
-;; 32-bit integer moves for which we provide move patterns.
-(define_mode_iterator IMOVE32
- [SI
- (V2HI "TARGET_DSP")
- (V4QI "TARGET_DSP")
- (V2HQ "TARGET_DSP")
- (V2UHQ "TARGET_DSP")
- (V2HA "TARGET_DSP")
- (V2UHA "TARGET_DSP")
- (V4QQ "TARGET_DSP")
- (V4UQQ "TARGET_DSP")])
-
-;; 64-bit modes for which we provide move patterns.
-(define_mode_iterator MOVE64
- [DI DF
- (V2SF "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT")
- (V2SI "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS")
- (V4HI "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS")
- (V8QI "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS")])
-
-;; 128-bit modes for which we provide move patterns on 64-bit targets.
-(define_mode_iterator MOVE128 [TI TF])
-
-;; This mode iterator allows the QI and HI extension patterns to be
-;; defined from the same template.
-(define_mode_iterator SHORT [QI HI])
-
-;; Likewise the 64-bit truncate-and-shift patterns.
-(define_mode_iterator SUBDI [QI HI SI])
-
-;; This mode iterator allows :ANYF to be used wherever a scalar or vector
-;; floating-point mode is allowed.
-(define_mode_iterator ANYF [(SF "TARGET_HARD_FLOAT")
- (DF "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT")
- (V2SF "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT")])
-
-;; Like ANYF, but only applies to scalar modes.
-(define_mode_iterator SCALARF [(SF "TARGET_HARD_FLOAT")
- (DF "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT")])
-
-;; A floating-point mode for which moves involving FPRs may need to be split.
-(define_mode_iterator SPLITF
- [(DF "!TARGET_64BIT && TARGET_DOUBLE_FLOAT")
- (DI "!TARGET_64BIT && TARGET_DOUBLE_FLOAT")
- (V2SF "!TARGET_64BIT && TARGET_PAIRED_SINGLE_FLOAT")
- (V2SI "!TARGET_64BIT && TARGET_LOONGSON_VECTORS")
- (V4HI "!TARGET_64BIT && TARGET_LOONGSON_VECTORS")
- (V8QI "!TARGET_64BIT && TARGET_LOONGSON_VECTORS")
- (TF "TARGET_64BIT && TARGET_FLOAT64")])
-
-;; In GPR templates, a string like "subu" will expand to "subu" in the
-;; 32-bit version and "dsubu" in the 64-bit version.
-(define_mode_attr d [(SI "") (DI "d")
- (QQ "") (HQ "") (SQ "") (DQ "d")
- (UQQ "") (UHQ "") (USQ "") (UDQ "d")
- (HA "") (SA "") (DA "d")
- (UHA "") (USA "") (UDA "d")])
-
-;; Same as d but upper-case.
-(define_mode_attr D [(SI "") (DI "D")
- (QQ "") (HQ "") (SQ "") (DQ "D")
- (UQQ "") (UHQ "") (USQ "") (UDQ "D")
- (HA "") (SA "") (DA "D")
- (UHA "") (USA "") (UDA "D")])
-
-;; This attribute gives the length suffix for a load or store instruction.
-;; The same suffixes work for zero and sign extensions.
-(define_mode_attr size [(QI "b") (HI "h") (SI "w") (DI "d")])
-(define_mode_attr SIZE [(QI "B") (HI "H") (SI "W") (DI "D")])
-
-;; This attributes gives the mode mask of a SHORT.
-(define_mode_attr mask [(QI "0x00ff") (HI "0xffff")])
-
-;; Mode attributes for GPR loads.
-(define_mode_attr load [(SI "lw") (DI "ld")])
-;; Instruction names for stores.
-(define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd")])
-
-;; Similarly for MIPS IV indexed FPR loads and stores.
-(define_mode_attr loadx [(SF "lwxc1") (DF "ldxc1") (V2SF "ldxc1")])
-(define_mode_attr storex [(SF "swxc1") (DF "sdxc1") (V2SF "sdxc1")])
-
-;; The unextended ranges of the MIPS16 addiu and daddiu instructions
-;; are different. Some forms of unextended addiu have an 8-bit immediate
-;; field but the equivalent daddiu has only a 5-bit field.
-(define_mode_attr si8_di5 [(SI "8") (DI "5")])
-
-;; This attribute gives the best constraint to use for registers of
-;; a given mode.
-(define_mode_attr reg [(SI "d") (DI "d") (CC "z")])
-
-;; This attribute gives the format suffix for floating-point operations.
-(define_mode_attr fmt [(SF "s") (DF "d") (V2SF "ps")])
-
-;; This attribute gives the upper-case mode name for one unit of a
-;; floating-point mode.
-(define_mode_attr UNITMODE [(SF "SF") (DF "DF") (V2SF "SF")])
-
-;; This attribute gives the integer mode that has the same size as a
-;; fixed-point mode.
-(define_mode_attr IMODE [(QQ "QI") (HQ "HI") (SQ "SI") (DQ "DI")
- (UQQ "QI") (UHQ "HI") (USQ "SI") (UDQ "DI")
- (HA "HI") (SA "SI") (DA "DI")
- (UHA "HI") (USA "SI") (UDA "DI")
- (V4UQQ "SI") (V2UHQ "SI") (V2UHA "SI")
- (V2HQ "SI") (V2HA "SI")])
-
-;; This attribute gives the integer mode that has half the size of
-;; the controlling mode.
-(define_mode_attr HALFMODE [(DF "SI") (DI "SI") (V2SF "SI")
- (V2SI "SI") (V4HI "SI") (V8QI "SI")
- (TF "DI")])
-
-;; This attribute works around the early SB-1 rev2 core "F2" erratum:
-;;
-;; In certain cases, div.s and div.ps may have a rounding error
-;; and/or wrong inexact flag.
-;;
-;; Therefore, we only allow div.s if not working around SB-1 rev2
-;; errata or if a slight loss of precision is OK.
-(define_mode_attr divide_condition
- [DF (SF "!TARGET_FIX_SB1 || flag_unsafe_math_optimizations")
- (V2SF "TARGET_SB1 && (!TARGET_FIX_SB1 || flag_unsafe_math_optimizations)")])
-
-;; This attribute gives the conditions under which SQRT.fmt instructions
-;; can be used.
-(define_mode_attr sqrt_condition
- [(SF "!ISA_MIPS1") (DF "!ISA_MIPS1") (V2SF "TARGET_SB1")])
-
-;; This code iterator allows signed and unsigned widening multiplications
-;; to use the same template.
-(define_code_iterator any_extend [sign_extend zero_extend])
-
-;; This code iterator allows the two right shift instructions to be
-;; generated from the same template.
-(define_code_iterator any_shiftrt [ashiftrt lshiftrt])
-
-;; This code iterator allows the three shift instructions to be generated
-;; from the same template.
-(define_code_iterator any_shift [ashift ashiftrt lshiftrt])
-
-;; This code iterator allows unsigned and signed division to be generated
-;; from the same template.
-(define_code_iterator any_div [div udiv])
-
-;; This code iterator allows unsigned and signed modulus to be generated
-;; from the same template.
-(define_code_iterator any_mod [mod umod])
-
-;; This code iterator allows all native floating-point comparisons to be
-;; generated from the same template.
-(define_code_iterator fcond [unordered uneq unlt unle eq lt le])
-
-;; This code iterator is used for comparisons that can be implemented
-;; by swapping the operands.
-(define_code_iterator swapped_fcond [ge gt unge ungt])
-
-;; Equality operators.
-(define_code_iterator equality_op [eq ne])
-
-;; These code iterators allow the signed and unsigned scc operations to use
-;; the same template.
-(define_code_iterator any_gt [gt gtu])
-(define_code_iterator any_ge [ge geu])
-(define_code_iterator any_lt [lt ltu])
-(define_code_iterator any_le [le leu])
-
-(define_code_iterator any_return [return simple_return])
-
-;; expands to an empty string when doing a signed operation and
-;; "u" when doing an unsigned operation.
-(define_code_attr u [(sign_extend "") (zero_extend "u")
- (div "") (udiv "u")
- (mod "") (umod "u")
- (gt "") (gtu "u")
- (ge "") (geu "u")
- (lt "") (ltu "u")
- (le "") (leu "u")])
-
-;; is like except uppercase.
-(define_code_attr U [(sign_extend "") (zero_extend "U")])
-
-;; is like , but the signed form expands to "s" rather than "".
-(define_code_attr su [(sign_extend "s") (zero_extend "u")])
-
-;; expands to the name of the optab for a particular code.
-(define_code_attr optab [(ashift "ashl")
- (ashiftrt "ashr")
- (lshiftrt "lshr")
- (ior "ior")
- (xor "xor")
- (and "and")
- (plus "add")
- (minus "sub")
- (return "return")
- (simple_return "simple_return")])
-
-;; expands to the name of the insn that implements a particular code.
-(define_code_attr insn [(ashift "sll")
- (ashiftrt "sra")
- (lshiftrt "srl")
- (ior "or")
- (xor "xor")
- (and "and")
- (plus "addu")
- (minus "subu")])
-
-;; expands to the name of the insn that implements
-;; a particular code to operate on immediate values.
-(define_code_attr immediate_insn [(ior "ori")
- (xor "xori")
- (and "andi")])
-
-(define_code_attr shift_compression [(ashift "micromips")
- (lshiftrt "micromips")
- (ashiftrt "none")])
-
-;; is the c.cond.fmt condition associated with a particular code.
-(define_code_attr fcond [(unordered "un")
- (uneq "ueq")
- (unlt "ult")
- (unle "ule")
- (eq "eq")
- (lt "lt")
- (le "le")])
-
-;; Similar, but for swapped conditions.
-(define_code_attr swapped_fcond [(ge "le")
- (gt "lt")
- (unge "ule")
- (ungt "ult")])
-
-;; The value of the bit when the branch is taken for branch_bit patterns.
-;; Comparison is always against zero so this depends on the operator.
-(define_code_attr bbv [(eq "0") (ne "1")])
-
-;; This is the inverse value of bbv.
-(define_code_attr bbinv [(eq "1") (ne "0")])
-
-;; .........................
-;;
-;; Branch, call and jump delay slots
-;;
-;; .........................
-
-(define_delay (and (eq_attr "type" "branch")
- (not (match_test "TARGET_MIPS16"))
- (eq_attr "branch_likely" "yes"))
- [(eq_attr "can_delay" "yes")
- (nil)
- (eq_attr "can_delay" "yes")])
-
-;; Branches that don't have likely variants do not annul on false.
-(define_delay (and (eq_attr "type" "branch")
- (not (match_test "TARGET_MIPS16"))
- (eq_attr "branch_likely" "no"))
- [(eq_attr "can_delay" "yes")
- (nil)
- (nil)])
-
-(define_delay (eq_attr "type" "jump")
- [(eq_attr "can_delay" "yes")
- (nil)
- (nil)])
-
-(define_delay (and (eq_attr "type" "call")
- (eq_attr "jal_macro" "no"))
- [(eq_attr "can_delay" "yes")
- (nil)
- (nil)])
-
-;; Pipeline descriptions.
-;;
-;; generic.md provides a fallback for processors without a specific
-;; pipeline description. It is derived from the old define_function_unit
-;; version and uses the "alu" and "imuldiv" units declared below.
-;;
-;; Some of the processor-specific files are also derived from old
-;; define_function_unit descriptions and simply override the parts of
-;; generic.md that don't apply. The other processor-specific files
-;; are self-contained.
-(define_automaton "alu,imuldiv")
-
-(define_cpu_unit "alu" "alu")
-(define_cpu_unit "imuldiv" "imuldiv")
-
-;; Ghost instructions produce no real code and introduce no hazards.
-;; They exist purely to express an effect on dataflow.
-(define_insn_reservation "ghost" 0
- (eq_attr "type" "ghost")
- "nothing")
-
-(include "4k.md")
-(include "5k.md")
-(include "20kc.md")
-(include "24k.md")
-(include "74k.md")
-(include "3000.md")
-(include "4000.md")
-(include "4100.md")
-(include "4130.md")
-(include "4300.md")
-(include "4600.md")
-(include "5000.md")
-(include "5400.md")
-(include "5500.md")
-(include "6000.md")
-(include "7000.md")
-(include "9000.md")
-(include "10000.md")
-(include "loongson2ef.md")
-(include "loongson3a.md")
-(include "octeon.md")
-(include "sb1.md")
-(include "sr71k.md")
-(include "xlr.md")
-(include "xlp.md")
-(include "generic.md")
-
-;;
-;; ....................
-;;
-;; CONDITIONAL TRAPS
-;;
-;; ....................
-;;
-
-(define_insn "trap"
- [(trap_if (const_int 1) (const_int 0))]
- ""
-{
- if (ISA_HAS_COND_TRAP)
- return "teq\t$0,$0";
- else if (TARGET_MIPS16)
- return "break 0";
- else
- return "break";
-}
- [(set_attr "type" "trap")])
-
-(define_expand "ctrap4"
- [(trap_if (match_operator 0 "comparison_operator"
- [(match_operand:GPR 1 "reg_or_0_operand")
- (match_operand:GPR 2 "arith_operand")])
- (match_operand 3 "const_0_operand"))]
- "ISA_HAS_COND_TRAP"
-{
- mips_expand_conditional_trap (operands[0]);
- DONE;
-})
-
-(define_insn "*conditional_trap"
- [(trap_if (match_operator:GPR 0 "trap_comparison_operator"
- [(match_operand:GPR 1 "reg_or_0_operand" "dJ")
- (match_operand:GPR 2 "arith_operand" "dI")])
- (const_int 0))]
- "ISA_HAS_COND_TRAP"
- "t%C0\t%z1,%2"
- [(set_attr "type" "trap")])
-
-;;
-;; ....................
-;;
-;; ADDITION
-;;
-;; ....................
-;;
-
-(define_insn "add3"
- [(set (match_operand:ANYF 0 "register_operand" "=f")
- (plus:ANYF (match_operand:ANYF 1 "register_operand" "f")
- (match_operand:ANYF 2 "register_operand" "f")))]
- ""
- "add.\t%0,%1,%2"
- [(set_attr "type" "fadd")
- (set_attr "mode" "")])
-
-(define_expand "add3"
- [(set (match_operand:GPR 0 "register_operand")
- (plus:GPR (match_operand:GPR 1 "register_operand")
- (match_operand:GPR 2 "arith_operand")))]
- "")
-
-(define_insn "*add3"
- [(set (match_operand:GPR 0 "register_operand" "=!u,d,!u,!u,!ks,!d,d")
- (plus:GPR (match_operand:GPR 1 "register_operand" "!u,d,!u,!ks,!ks,0,d")
- (match_operand:GPR 2 "arith_operand" "!u,d,Uead,Uuw6,Uesp,Usb4,Q")))]
- "!TARGET_MIPS16"
-{
- if (which_alternative == 0
- || which_alternative == 1)
- return "addu\t%0,%1,%2";
- else
- return "addiu\t%0,%1,%2";
-}
- [(set_attr "alu_type" "add")
- (set_attr "compression" "micromips,*,micromips,micromips,micromips,micromips,*")
- (set_attr "mode" "")])
-
-(define_insn "*add3_mips16"
- [(set (match_operand:GPR 0 "register_operand" "=ks,ks,d,d,d,d,d,d,d")
- (plus:GPR (match_operand:GPR 1 "register_operand" "ks,ks,ks,ks,0,0,d,d,d")
- (match_operand:GPR 2 "arith_operand" "Usd8,Q,Uuw,Q,Usb,Q,Usb4,O,d")))]
- "TARGET_MIPS16"
- "@
- addiu\t%0,%2
- addiu\t%0,%2
- addiu\t%0,%1,%2
- addiu\t%0,%1,%2
- addiu\t%0,%2
- addiu\t%0,%2
- addiu\t%0,%1,%2
- addiu\t%0,%1,%2
- addu\t%0,%1,%2"
- [(set_attr "alu_type" "add")
- (set_attr "mode" "")
- (set_attr "extended_mips16" "no,yes,no,yes,no,yes,no,yes,no")])
-
-;; On the mips16, we can sometimes split an add of a constant which is
-;; a 4 byte instruction into two adds which are both 2 byte
-;; instructions. There are two cases: one where we are adding a
-;; constant plus a register to another register, and one where we are
-;; simply adding a constant to a register.
-
-(define_split
- [(set (match_operand:SI 0 "d_operand")
- (plus:SI (match_dup 0)
- (match_operand:SI 1 "const_int_operand")))]
- "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE
- && ((INTVAL (operands[1]) > 0x7f
- && INTVAL (operands[1]) <= 0x7f + 0x7f)
- || (INTVAL (operands[1]) < - 0x80
- && INTVAL (operands[1]) >= - 0x80 - 0x80))"
- [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))
- (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))]
-{
- HOST_WIDE_INT val = INTVAL (operands[1]);
-
- if (val >= 0)
- {
- operands[1] = GEN_INT (0x7f);
- operands[2] = GEN_INT (val - 0x7f);
- }
- else
- {
- operands[1] = GEN_INT (- 0x80);
- operands[2] = GEN_INT (val + 0x80);
- }
-})
-
-(define_split
- [(set (match_operand:SI 0 "d_operand")
- (plus:SI (match_operand:SI 1 "d_operand")
- (match_operand:SI 2 "const_int_operand")))]
- "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE
- && REGNO (operands[0]) != REGNO (operands[1])
- && ((INTVAL (operands[2]) > 0x7
- && INTVAL (operands[2]) <= 0x7 + 0x7f)
- || (INTVAL (operands[2]) < - 0x8
- && INTVAL (operands[2]) >= - 0x8 - 0x80))"
- [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
- (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
-{
- HOST_WIDE_INT val = INTVAL (operands[2]);
-
- if (val >= 0)
- {
- operands[2] = GEN_INT (0x7);
- operands[3] = GEN_INT (val - 0x7);
- }
- else
- {
- operands[2] = GEN_INT (- 0x8);
- operands[3] = GEN_INT (val + 0x8);
- }
-})
-
-(define_split
- [(set (match_operand:DI 0 "d_operand")
- (plus:DI (match_dup 0)
- (match_operand:DI 1 "const_int_operand")))]
- "TARGET_MIPS16 && TARGET_64BIT && reload_completed && !TARGET_DEBUG_D_MODE
- && ((INTVAL (operands[1]) > 0xf
- && INTVAL (operands[1]) <= 0xf + 0xf)
- || (INTVAL (operands[1]) < - 0x10
- && INTVAL (operands[1]) >= - 0x10 - 0x10))"
- [(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 1)))
- (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 2)))]
-{
- HOST_WIDE_INT val = INTVAL (operands[1]);
-
- if (val >= 0)
- {
- operands[1] = GEN_INT (0xf);
- operands[2] = GEN_INT (val - 0xf);
- }
- else
- {
- operands[1] = GEN_INT (- 0x10);
- operands[2] = GEN_INT (val + 0x10);
- }
-})
-
-(define_split
- [(set (match_operand:DI 0 "d_operand")
- (plus:DI (match_operand:DI 1 "d_operand")
- (match_operand:DI 2 "const_int_operand")))]
- "TARGET_MIPS16 && TARGET_64BIT && reload_completed && !TARGET_DEBUG_D_MODE
- && REGNO (operands[0]) != REGNO (operands[1])
- && ((INTVAL (operands[2]) > 0x7
- && INTVAL (operands[2]) <= 0x7 + 0xf)
- || (INTVAL (operands[2]) < - 0x8
- && INTVAL (operands[2]) >= - 0x8 - 0x10))"
- [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))
- (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))]
-{
- HOST_WIDE_INT val = INTVAL (operands[2]);
-
- if (val >= 0)
- {
- operands[2] = GEN_INT (0x7);
- operands[3] = GEN_INT (val - 0x7);
- }
- else
- {
- operands[2] = GEN_INT (- 0x8);
- operands[3] = GEN_INT (val + 0x8);
- }
-})
-
-(define_insn "*addsi3_extended"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (sign_extend:DI
- (plus:SI (match_operand:SI 1 "register_operand" "d,d")
- (match_operand:SI 2 "arith_operand" "d,Q"))))]
- "TARGET_64BIT && !TARGET_MIPS16"
- "@
- addu\t%0,%1,%2
- addiu\t%0,%1,%2"
- [(set_attr "alu_type" "add")
- (set_attr "mode" "SI")])
-
-;; Split this insn so that the addiu splitters can have a crack at it.
-;; Use a conservative length estimate until the split.
-(define_insn_and_split "*addsi3_extended_mips16"
- [(set (match_operand:DI 0 "register_operand" "=d,d,d")
- (sign_extend:DI
- (plus:SI (match_operand:SI 1 "register_operand" "0,d,d")
- (match_operand:SI 2 "arith_operand" "Q,O,d"))))]
- "TARGET_64BIT && TARGET_MIPS16"
- "#"
- "&& reload_completed"
- [(set (match_dup 3) (plus:SI (match_dup 1) (match_dup 2)))]
- { operands[3] = gen_lowpart (SImode, operands[0]); }
- [(set_attr "alu_type" "add")
- (set_attr "mode" "SI")
- (set_attr "extended_mips16" "yes")])
-
-;; Combiner patterns for unsigned byte-add.
-
-(define_insn "*baddu_si_eb"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (zero_extend:SI
- (subreg:QI
- (plus:SI (match_operand:SI 1 "register_operand" "d")
- (match_operand:SI 2 "register_operand" "d")) 3)))]
- "ISA_HAS_BADDU && BYTES_BIG_ENDIAN"
- "baddu\\t%0,%1,%2"
- [(set_attr "alu_type" "add")])
-
-(define_insn "*baddu_si_el"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (zero_extend:SI
- (subreg:QI
- (plus:SI (match_operand:SI 1 "register_operand" "d")
- (match_operand:SI 2 "register_operand" "d")) 0)))]
- "ISA_HAS_BADDU && !BYTES_BIG_ENDIAN"
- "baddu\\t%0,%1,%2"
- [(set_attr "alu_type" "add")])
-
-(define_insn "*baddu_di"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (zero_extend:GPR
- (truncate:QI
- (plus:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "register_operand" "d")))))]
- "ISA_HAS_BADDU && TARGET_64BIT"
- "baddu\\t%0,%1,%2"
- [(set_attr "alu_type" "add")])
-
-;;
-;; ....................
-;;
-;; SUBTRACTION
-;;
-;; ....................
-;;
-
-(define_insn "sub3"
- [(set (match_operand:ANYF 0 "register_operand" "=f")
- (minus:ANYF (match_operand:ANYF 1 "register_operand" "f")
- (match_operand:ANYF 2 "register_operand" "f")))]
- ""
- "sub.\t%0,%1,%2"
- [(set_attr "type" "fadd")
- (set_attr "mode" "")])
-
-(define_insn "sub3"
- [(set (match_operand:GPR 0 "register_operand" "=!u,d")
- (minus:GPR (match_operand:GPR 1 "register_operand" "!u,d")
- (match_operand:GPR 2 "register_operand" "!u,d")))]
- ""
- "subu\t%0,%1,%2"
- [(set_attr "alu_type" "sub")
- (set_attr "compression" "micromips,*")
- (set_attr "mode" "")])
-
-(define_insn "*subsi3_extended"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (sign_extend:DI
- (minus:SI (match_operand:SI 1 "register_operand" "d")
- (match_operand:SI 2 "register_operand" "d"))))]
- "TARGET_64BIT"
- "subu\t%0,%1,%2"
- [(set_attr "alu_type" "sub")
- (set_attr "mode" "DI")])
-
-;;
-;; ....................
-;;
-;; MULTIPLICATION
-;;
-;; ....................
-;;
-
-(define_expand "mul3"
- [(set (match_operand:SCALARF 0 "register_operand")
- (mult:SCALARF (match_operand:SCALARF 1 "register_operand")
- (match_operand:SCALARF 2 "register_operand")))]
- "!TARGET_NO_HW_MULT"
- "")
-
-(define_insn "*mul3"
- [(set (match_operand:SCALARF 0 "register_operand" "=f")
- (mult:SCALARF (match_operand:SCALARF 1 "register_operand" "f")
- (match_operand:SCALARF 2 "register_operand" "f")))]
- "!TARGET_4300_MUL_FIX"
- "mul.\t%0,%1,%2"
- [(set_attr "type" "fmul")
- (set_attr "mode" "")])
-
-;; Early VR4300 silicon has a CPU bug where multiplies with certain
-;; operands may corrupt immediately following multiplies. This is a
-;; simple fix to insert NOPs.
-
-(define_insn "*mul3_r4300"
- [(set (match_operand:SCALARF 0 "register_operand" "=f")
- (mult:SCALARF (match_operand:SCALARF 1 "register_operand" "f")
- (match_operand:SCALARF 2 "register_operand" "f")))]
- "TARGET_4300_MUL_FIX"
- "mul.\t%0,%1,%2\;nop"
- [(set_attr "type" "fmul")
- (set_attr "mode" "")
- (set_attr "insn_count" "2")])
-
-(define_insn "mulv2sf3"
- [(set (match_operand:V2SF 0 "register_operand" "=f")
- (mult:V2SF (match_operand:V2SF 1 "register_operand" "f")
- (match_operand:V2SF 2 "register_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
- "mul.ps\t%0,%1,%2"
- [(set_attr "type" "fmul")
- (set_attr "mode" "SF")])
-
-;; The original R4000 has a cpu bug. If a double-word or a variable
-;; shift executes while an integer multiplication is in progress, the
-;; shift may give an incorrect result. Avoid this by keeping the mflo
-;; with the mult on the R4000.
-;;
-;; From "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0"
-;; (also valid for MIPS R4000MC processors):
-;;
-;; "16. R4000PC, R4000SC: Please refer to errata 28 for an update to
-;; this errata description.
-;; The following code sequence causes the R4000 to incorrectly
-;; execute the Double Shift Right Arithmetic 32 (dsra32)
-;; instruction. If the dsra32 instruction is executed during an
-;; integer multiply, the dsra32 will only shift by the amount in
-;; specified in the instruction rather than the amount plus 32
-;; bits.
-;; instruction 1: mult rs,rt integer multiply
-;; instruction 2-12: dsra32 rd,rt,rs doubleword shift
-;; right arithmetic + 32
-;; Workaround: A dsra32 instruction placed after an integer
-;; multiply should not be one of the 11 instructions after the
-;; multiply instruction."
-;;
-;; and:
-;;
-;; "28. R4000PC, R4000SC: The text from errata 16 should be replaced by
-;; the following description.
-;; All extended shifts (shift by n+32) and variable shifts (32 and
-;; 64-bit versions) may produce incorrect results under the
-;; following conditions:
-;; 1) An integer multiply is currently executing
-;; 2) These types of shift instructions are executed immediately
-;; following an integer divide instruction.
-;; Workaround:
-;; 1) Make sure no integer multiply is running wihen these
-;; instruction are executed. If this cannot be predicted at
-;; compile time, then insert a "mfhi" to R0 instruction
-;; immediately after the integer multiply instruction. This
-;; will cause the integer multiply to complete before the shift
-;; is executed.
-;; 2) Separate integer divide and these two classes of shift
-;; instructions by another instruction or a noop."
-;;
-;; These processors have PRId values of 0x00004220 and 0x00004300,
-;; respectively.
-
-(define_expand "mul3"
- [(set (match_operand:GPR 0 "register_operand")
- (mult:GPR (match_operand:GPR 1 "register_operand")
- (match_operand:GPR 2 "register_operand")))]
- "ISA_HAS_MULT && !TARGET_NO_HW_MULT"
-{
- rtx lo;
-
- if (TARGET_LOONGSON_2EF || TARGET_LOONGSON_3A)
- emit_insn (gen_mul3_mul3_loongson (operands[0], operands[1],
- operands[2]));
- else if (ISA_HAS_MUL3)
- emit_insn (gen_mul3_mul3 (operands[0], operands[1], operands[2]));
- else if (TARGET_MIPS16)
- {
- lo = gen_rtx_REG (mode, LO_REGNUM);
- emit_insn (gen_mul3_internal (lo, operands[1], operands[2]));
- emit_move_insn (operands[0], lo);
- }
- else if (TARGET_FIX_R4000)
- emit_insn (gen_mul3_r4000 (operands[0], operands[1], operands[2]));
- else
- emit_insn
- (gen_mul3_internal (operands[0], operands[1], operands[2]));
- DONE;
-})
-
-(define_insn "mul3_mul3_loongson"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (mult:GPR (match_operand:GPR 1 "register_operand" "d")
- (match_operand:GPR 2 "register_operand" "d")))]
- "TARGET_LOONGSON_2EF || TARGET_LOONGSON_3A"
-{
- if (TARGET_LOONGSON_2EF)
- return "multu.g\t%0,%1,%2";
- else
- return "gsmultu\t%0,%1,%2";
-}
- [(set_attr "type" "imul3nc")
- (set_attr "mode" "")])
-
-(define_insn "mul3_mul3"
- [(set (match_operand:GPR 0 "register_operand" "=d,l")
- (mult:GPR (match_operand:GPR 1 "register_operand" "d,d")
- (match_operand:GPR 2 "register_operand" "d,d")))
- (clobber (match_scratch:GPR 3 "=l,X"))]
- "ISA_HAS_MUL3"
-{
- if (which_alternative == 1)
- return "mult\t%1,%2";
- if (mode == SImode && (TARGET_MIPS3900 || TARGET_MIPS5900))
- return "mult\t%0,%1,%2";
- return "mul\t%0,%1,%2";
-}
- [(set_attr "type" "imul3,imul")
- (set_attr "mode" "")])
-
-;; If a register gets allocated to LO, and we spill to memory, the reload
-;; will include a move from LO to a GPR. Merge it into the multiplication
-;; if it can set the GPR directly.
-;;
-;; Operand 0: LO
-;; Operand 1: GPR (1st multiplication operand)
-;; Operand 2: GPR (2nd multiplication operand)
-;; Operand 3: GPR (destination)
-(define_peephole2
- [(parallel
- [(set (match_operand:SI 0 "lo_operand")
- (mult:SI (match_operand:SI 1 "d_operand")
- (match_operand:SI 2 "d_operand")))
- (clobber (scratch:SI))])
- (set (match_operand:SI 3 "d_operand")
- (match_dup 0))]
- "ISA_HAS_MUL3 && peep2_reg_dead_p (2, operands[0])"
- [(parallel
- [(set (match_dup 3)
- (mult:SI (match_dup 1)
- (match_dup 2)))
- (clobber (match_dup 0))])])
-
-(define_insn "mul3_internal"
- [(set (match_operand:GPR 0 "muldiv_target_operand" "=l")
- (mult:GPR (match_operand:GPR 1 "register_operand" "d")
- (match_operand:GPR 2 "register_operand" "d")))]
- "ISA_HAS_MULT && !TARGET_FIX_R4000"
- "mult\t%1,%2"
- [(set_attr "type" "imul")
- (set_attr "mode" "")])
-
-(define_insn "mul3_r4000"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (mult:GPR (match_operand:GPR 1 "register_operand" "d")
- (match_operand:GPR 2 "register_operand" "d")))
- (clobber (match_scratch:GPR 3 "=l"))]
- "ISA_HAS_MULT && TARGET_FIX_R4000"
- "mult\t%1,%2\;mflo\t%0"
- [(set_attr "type" "imul")
- (set_attr "mode" "")
- (set_attr "insn_count" "2")])
-
-;; On the VR4120 and VR4130, it is better to use "mtlo $0; macc" instead
-;; of "mult; mflo". They have the same latency, but the first form gives
-;; us an extra cycle to compute the operands.
-
-;; Operand 0: LO
-;; Operand 1: GPR (1st multiplication operand)
-;; Operand 2: GPR (2nd multiplication operand)
-;; Operand 3: GPR (destination)
-(define_peephole2
- [(set (match_operand:SI 0 "lo_operand")
- (mult:SI (match_operand:SI 1 "d_operand")
- (match_operand:SI 2 "d_operand")))
- (set (match_operand:SI 3 "d_operand")
- (match_dup 0))]
- "ISA_HAS_MACC && !ISA_HAS_MUL3"
- [(set (match_dup 0)
- (const_int 0))
- (parallel
- [(set (match_dup 0)
- (plus:SI (mult:SI (match_dup 1)
- (match_dup 2))
- (match_dup 0)))
- (set (match_dup 3)
- (plus:SI (mult:SI (match_dup 1)
- (match_dup 2))
- (match_dup 0)))])])
-
-;; Multiply-accumulate patterns
-
-;; This pattern is first matched by combine, which tries to use the
-;; pattern wherever it can. We don't know until later whether it
-;; is actually profitable to use MADD over a "MUL; ADDIU" sequence,
-;; so we need to keep both options open.
-;;
-;; The second alternative has a "?" marker because it is generally
-;; one instruction more costly than the first alternative. This "?"
-;; marker is enough to convey the relative costs to the register
-;; allocator.
-;;
-;; However, reload counts reloads of operands 4 and 5 in the same way as
-;; reloads of the other operands, even though operands 4 and 5 need no
-;; copy instructions. Reload therefore thinks that the second alternative
-;; is two reloads more costly than the first. We add "*?*?" to the first
-;; alternative as a counterweight.
-(define_insn "*mul_acc_si"
- [(set (match_operand:SI 0 "register_operand" "=l*?*?,d?")
- (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d")
- (match_operand:SI 2 "register_operand" "d,d"))
- (match_operand:SI 3 "register_operand" "0,d")))
- (clobber (match_scratch:SI 4 "=X,l"))
- (clobber (match_scratch:SI 5 "=X,&d"))]
- "GENERATE_MADD_MSUB && !TARGET_MIPS16"
- "@
- madd\t%1,%2
- #"
- [(set_attr "type" "imadd")
- (set_attr "accum_in" "3")
- (set_attr "mode" "SI")
- (set_attr "insn_count" "1,2")])
-
-;; The same idea applies here. The middle alternative needs one less
-;; clobber than the final alternative, so we add "*?" as a counterweight.
-(define_insn "*mul_acc_si_r3900"
- [(set (match_operand:SI 0 "register_operand" "=l*?*?,d*?,d?")
- (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d,d")
- (match_operand:SI 2 "register_operand" "d,d,d"))
- (match_operand:SI 3 "register_operand" "0,l,d")))
- (clobber (match_scratch:SI 4 "=X,3,l"))
- (clobber (match_scratch:SI 5 "=X,X,&d"))]
- "TARGET_MIPS3900 && !TARGET_MIPS16"
- "@
- madd\t%1,%2
- madd\t%0,%1,%2
- #"
- [(set_attr "type" "imadd")
- (set_attr "accum_in" "3")
- (set_attr "mode" "SI")
- (set_attr "insn_count" "1,1,2")])
-
-;; Split *mul_acc_si if both the source and destination accumulator
-;; values are GPRs.
-(define_split
- [(set (match_operand:SI 0 "d_operand")
- (plus:SI (mult:SI (match_operand:SI 1 "d_operand")
- (match_operand:SI 2 "d_operand"))
- (match_operand:SI 3 "d_operand")))
- (clobber (match_operand:SI 4 "lo_operand"))
- (clobber (match_operand:SI 5 "d_operand"))]
- "reload_completed"
- [(parallel [(set (match_dup 5)
- (mult:SI (match_dup 1) (match_dup 2)))
- (clobber (match_dup 4))])
- (set (match_dup 0) (plus:SI (match_dup 5) (match_dup 3)))]
- "")
-
-(define_insn "*macc"
- [(set (match_operand:SI 0 "register_operand" "=l,d")
- (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d")
- (match_operand:SI 2 "register_operand" "d,d"))
- (match_operand:SI 3 "register_operand" "0,l")))
- (clobber (match_scratch:SI 4 "=X,3"))]
- "ISA_HAS_MACC"
-{
- if (which_alternative == 1)
- return "macc\t%0,%1,%2";
- else if (TARGET_MIPS5500)
- return "madd\t%1,%2";
- else
- /* The VR4130 assumes that there is a two-cycle latency between a macc
- that "writes" to $0 and an instruction that reads from it. We avoid
- this by assigning to $1 instead. */
- return "%[macc\t%@,%1,%2%]";
-}
- [(set_attr "type" "imadd")
- (set_attr "accum_in" "3")
- (set_attr "mode" "SI")])
-
-(define_insn "*msac"
- [(set (match_operand:SI 0 "register_operand" "=l,d")
- (minus:SI (match_operand:SI 1 "register_operand" "0,l")
- (mult:SI (match_operand:SI 2 "register_operand" "d,d")
- (match_operand:SI 3 "register_operand" "d,d"))))
- (clobber (match_scratch:SI 4 "=X,1"))]
- "ISA_HAS_MSAC"
-{
- if (which_alternative == 1)
- return "msac\t%0,%2,%3";
- else if (TARGET_MIPS5500)
- return "msub\t%2,%3";
- else
- return "msac\t$0,%2,%3";
-}
- [(set_attr "type" "imadd")
- (set_attr "accum_in" "1")
- (set_attr "mode" "SI")])
-
-;; An msac-like instruction implemented using negation and a macc.
-(define_insn_and_split "*msac_using_macc"
- [(set (match_operand:SI 0 "register_operand" "=l,d")
- (minus:SI (match_operand:SI 1 "register_operand" "0,l")
- (mult:SI (match_operand:SI 2 "register_operand" "d,d")
- (match_operand:SI 3 "register_operand" "d,d"))))
- (clobber (match_scratch:SI 4 "=X,1"))
- (clobber (match_scratch:SI 5 "=d,d"))]
- "ISA_HAS_MACC && !ISA_HAS_MSAC"
- "#"
- "&& reload_completed"
- [(set (match_dup 5)
- (neg:SI (match_dup 3)))
- (parallel
- [(set (match_dup 0)
- (plus:SI (mult:SI (match_dup 2)
- (match_dup 5))
- (match_dup 1)))
- (clobber (match_dup 4))])]
- ""
- [(set_attr "type" "imadd")
- (set_attr "accum_in" "1")
- (set_attr "insn_count" "2")])
-
-;; Patterns generated by the define_peephole2 below.
-
-(define_insn "*macc2"
- [(set (match_operand:SI 0 "muldiv_target_operand" "=l")
- (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d")
- (match_operand:SI 2 "register_operand" "d"))
- (match_dup 0)))
- (set (match_operand:SI 3 "register_operand" "=d")
- (plus:SI (mult:SI (match_dup 1)
- (match_dup 2))
- (match_dup 0)))]
- "ISA_HAS_MACC && reload_completed"
- "macc\t%3,%1,%2"
- [(set_attr "type" "imadd")
- (set_attr "accum_in" "0")
- (set_attr "mode" "SI")])
-
-(define_insn "*msac2"
- [(set (match_operand:SI 0 "muldiv_target_operand" "=l")
- (minus:SI (match_dup 0)
- (mult:SI (match_operand:SI 1 "register_operand" "d")
- (match_operand:SI 2 "register_operand" "d"))))
- (set (match_operand:SI 3 "register_operand" "=d")
- (minus:SI (match_dup 0)
- (mult:SI (match_dup 1)
- (match_dup 2))))]
- "ISA_HAS_MSAC && reload_completed"
- "msac\t%3,%1,%2"
- [(set_attr "type" "imadd")
- (set_attr "accum_in" "0")
- (set_attr "mode" "SI")])
-
-;; Convert macc $0,, & mflo into macc ,,
-;; Similarly msac.
-;;
-;; Operand 0: LO
-;; Operand 1: macc/msac
-;; Operand 2: GPR (destination)
-(define_peephole2
- [(parallel
- [(set (match_operand:SI 0 "lo_operand")
- (match_operand:SI 1 "macc_msac_operand"))
- (clobber (scratch:SI))])
- (set (match_operand:SI 2 "d_operand")
- (match_dup 0))]
- ""
- [(parallel [(set (match_dup 0)
- (match_dup 1))
- (set (match_dup 2)
- (match_dup 1))])])
-
-;; When we have a three-address multiplication instruction, it should
-;; be faster to do a separate multiply and add, rather than moving
-;; something into LO in order to use a macc instruction.
-;;
-;; This peephole needs a scratch register to cater for the case when one
-;; of the multiplication operands is the same as the destination.
-;;
-;; Operand 0: GPR (scratch)
-;; Operand 1: LO
-;; Operand 2: GPR (addend)
-;; Operand 3: GPR (destination)
-;; Operand 4: macc/msac
-;; Operand 5: new multiplication
-;; Operand 6: new addition/subtraction
-(define_peephole2
- [(match_scratch:SI 0 "d")
- (set (match_operand:SI 1 "lo_operand")
- (match_operand:SI 2 "d_operand"))
- (match_dup 0)
- (parallel
- [(set (match_operand:SI 3 "d_operand")
- (match_operand:SI 4 "macc_msac_operand"))
- (clobber (match_dup 1))])]
- "ISA_HAS_MUL3 && peep2_reg_dead_p (2, operands[1])"
- [(parallel [(set (match_dup 0)
- (match_dup 5))
- (clobber (match_dup 1))])
- (set (match_dup 3)
- (match_dup 6))]
-{
- operands[5] = XEXP (operands[4], GET_CODE (operands[4]) == PLUS ? 0 : 1);
- operands[6] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode,
- operands[2], operands[0]);
-})
-
-;; Same as above, except LO is the initial target of the macc.
-;;
-;; Operand 0: GPR (scratch)
-;; Operand 1: LO
-;; Operand 2: GPR (addend)
-;; Operand 3: macc/msac
-;; Operand 4: GPR (destination)
-;; Operand 5: new multiplication
-;; Operand 6: new addition/subtraction
-(define_peephole2
- [(match_scratch:SI 0 "d")
- (set (match_operand:SI 1 "lo_operand")
- (match_operand:SI 2 "d_operand"))
- (match_dup 0)
- (parallel
- [(set (match_dup 1)
- (match_operand:SI 3 "macc_msac_operand"))
- (clobber (scratch:SI))])
- (match_dup 0)
- (set (match_operand:SI 4 "d_operand")
- (match_dup 1))]
- "ISA_HAS_MUL3 && peep2_reg_dead_p (3, operands[1])"
- [(parallel [(set (match_dup 0)
- (match_dup 5))
- (clobber (match_dup 1))])
- (set (match_dup 4)
- (match_dup 6))]
-{
- operands[5] = XEXP (operands[3], GET_CODE (operands[3]) == PLUS ? 0 : 1);
- operands[6] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SImode,
- operands[2], operands[0]);
-})
-
-;; See the comment above *mul_add_si for details.
-(define_insn "*mul_sub_si"
- [(set (match_operand:SI 0 "register_operand" "=l*?*?,d?")
- (minus:SI (match_operand:SI 1 "register_operand" "0,d")
- (mult:SI (match_operand:SI 2 "register_operand" "d,d")
- (match_operand:SI 3 "register_operand" "d,d"))))
- (clobber (match_scratch:SI 4 "=X,l"))
- (clobber (match_scratch:SI 5 "=X,&d"))]
- "GENERATE_MADD_MSUB"
- "@
- msub\t%2,%3
- #"
- [(set_attr "type" "imadd")
- (set_attr "accum_in" "1")
- (set_attr "mode" "SI")
- (set_attr "insn_count" "1,2")])
-
-;; Split *mul_sub_si if both the source and destination accumulator
-;; values are GPRs.
-(define_split
- [(set (match_operand:SI 0 "d_operand")
- (minus:SI (match_operand:SI 1 "d_operand")
- (mult:SI (match_operand:SI 2 "d_operand")
- (match_operand:SI 3 "d_operand"))))
- (clobber (match_operand:SI 4 "lo_operand"))
- (clobber (match_operand:SI 5 "d_operand"))]
- "reload_completed"
- [(parallel [(set (match_dup 5)
- (mult:SI (match_dup 2) (match_dup 3)))
- (clobber (match_dup 4))])
- (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 5)))]
- "")
-
-(define_insn "*muls"
- [(set (match_operand:SI 0 "register_operand" "=l,d")
- (neg:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d")
- (match_operand:SI 2 "register_operand" "d,d"))))
- (clobber (match_scratch:SI 3 "=X,l"))]
- "ISA_HAS_MULS"
- "@
- muls\t$0,%1,%2
- muls\t%0,%1,%2"
- [(set_attr "type" "imul,imul3")
- (set_attr "mode" "SI")])
-
-(define_expand "mulsidi3"
- [(set (match_operand:DI 0 "register_operand")
- (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand"))
- (any_extend:DI (match_operand:SI 2 "register_operand"))))]
- "mips_mulsidi3_gen_fn (
) != NULL && !TARGET_NO_HW_MULT"
-{
- mulsidi3_gen_fn fn = mips_mulsidi3_gen_fn ();
- emit_insn (fn (operands[0], operands[1], operands[2]));
- DONE;
-})
-
-(define_expand "mulsidi3_32bit_mips16"
- [(set (match_operand:DI 0 "register_operand")
- (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand"))
- (any_extend:DI (match_operand:SI 2 "register_operand"))))]
- "!TARGET_64BIT && TARGET_MIPS16"
-{
- rtx hilo;
-
- hilo = gen_rtx_REG (DImode, MD_REG_FIRST);
- emit_insn (gen_mulsidi3_32bit (hilo, operands[1], operands[2]));
- emit_move_insn (operands[0], hilo);
- DONE;
-})
-
-;; As well as being named patterns, these instructions are used by the
-;; __builtin_mips_mult() functions. We must always make those functions
-;; available if !TARGET_64BIT && ISA_HAS_DSP.
-(define_insn "mulsidi3_32bit"
- [(set (match_operand:DI 0 "muldiv_target_operand" "=ka")
- (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
- (any_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
- "!TARGET_64BIT && (!TARGET_FIX_R4000 || ISA_HAS_DSP) && !TARGET_NO_HW_MULT"
-{
- if (ISA_HAS_DSP_MULT)
- return "mult\t%q0,%1,%2";
- else
- return "mult\t%1,%2";
-}
- [(set_attr "type" "imul")
- (set_attr "mode" "SI")])
-
-(define_insn "mulsidi3_32bit_r4000"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
- (any_extend:DI (match_operand:SI 2 "register_operand" "d"))))
- (clobber (match_scratch:DI 3 "=x"))]
- "!TARGET_64BIT && TARGET_FIX_R4000 && !ISA_HAS_DSP"
- "mult\t%1,%2\;mflo\t%L0\;mfhi\t%M0"
- [(set_attr "type" "imul")
- (set_attr "mode" "SI")
- (set_attr "insn_count" "3")])
-
-(define_insn_and_split "mulsidi3_64bit"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
- (any_extend:DI (match_operand:SI 2 "register_operand" "d"))))
- (clobber (match_scratch:TI 3 "=x"))
- (clobber (match_scratch:DI 4 "=d"))]
- "TARGET_64BIT && !TARGET_FIX_R4000 && !ISA_HAS_DMUL3 && !TARGET_MIPS16"
- "#"
- "&& reload_completed"
- [(const_int 0)]
-{
- emit_insn (gen_mulsidi3_64bit_split (operands[0], operands[1],
- operands[2], operands[4]));
- DONE;
-}
- [(set_attr "type" "imul")
- (set_attr "mode" "SI")
- (set (attr "insn_count")
- (if_then_else (match_test "ISA_HAS_EXT_INS")
- (const_int 4)
- (const_int 7)))])
-
-(define_expand "mulsidi3_64bit_mips16"
- [(set (match_operand:DI 0 "register_operand")
- (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand"))
- (any_extend:DI (match_operand:SI 2 "register_operand"))))]
- "TARGET_64BIT && TARGET_MIPS16"
-{
- emit_insn (gen_mulsidi3_64bit_split (operands[0], operands[1],
- operands[2], gen_reg_rtx (DImode)));
- DONE;
-})
-
-(define_expand "mulsidi3_64bit_split"
- [(set (match_operand:DI 0 "register_operand")
- (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand"))
- (any_extend:DI (match_operand:SI 2 "register_operand"))))
- (clobber (match_operand:DI 3 "register_operand"))]
- ""
-{
- rtx hilo;
-
- hilo = gen_rtx_REG (TImode, MD_REG_FIRST);
- emit_insn (gen_mulsidi3_64bit_hilo (hilo, operands[1], operands[2]));
-
- emit_move_insn (operands[0], gen_rtx_REG (DImode, LO_REGNUM));
- emit_insn (gen_mfhidi_ti (operands[3], hilo));
-
- if (ISA_HAS_EXT_INS)
- emit_insn (gen_insvdi (operands[0], GEN_INT (32), GEN_INT (32),
- operands[3]));
- else
- {
- /* Zero-extend the low part. */
- mips_emit_binary (ASHIFT, operands[0], operands[0], GEN_INT (32));
- mips_emit_binary (LSHIFTRT, operands[0], operands[0], GEN_INT (32));
-
- /* Shift the high part into place. */
- mips_emit_binary (ASHIFT, operands[3], operands[3], GEN_INT (32));
-
- /* OR the two halves together. */
- mips_emit_binary (IOR, operands[0], operands[0], operands[3]);
- }
- DONE;
-})
-
-(define_insn "mulsidi3_64bit_hilo"
- [(set (match_operand:TI 0 "muldiv_target_operand" "=x")
- (unspec:TI
- [(mult:DI
- (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
- (any_extend:DI (match_operand:SI 2 "register_operand" "d")))]
- UNSPEC_SET_HILO))]
- "TARGET_64BIT && !TARGET_FIX_R4000"
- "mult\t%1,%2"
- [(set_attr "type" "imul")
- (set_attr "mode" "SI")])
-
-;; See comment before the ISA_HAS_DMUL3 case in mips_mulsidi3_gen_fn.
-(define_insn "mulsidi3_64bit_dmul"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
- (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))
- (clobber (match_scratch:DI 3 "=l"))]
- "ISA_HAS_DMUL3"
- "dmul\t%0,%1,%2"
- [(set_attr "type" "imul3")
- (set_attr "mode" "DI")])
-
-;; Widening multiply with negation.
-(define_insn "*muls_di"
- [(set (match_operand:DI 0 "muldiv_target_operand" "=x")
- (neg:DI
- (mult:DI
- (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
- (any_extend:DI (match_operand:SI 2 "register_operand" "d")))))]
- "!TARGET_64BIT && ISA_HAS_MULS"
- "muls\t$0,%1,%2"
- [(set_attr "type" "imul")
- (set_attr "mode" "SI")])
-
-;; As well as being named patterns, these instructions are used by the
-;; __builtin_mips_msub() functions. We must always make those functions
-;; available if !TARGET_64BIT && ISA_HAS_DSP.
-;;
-;; This leads to a slight inconsistency. We honor any tuning overrides
-;; in GENERATE_MADD_MSUB for -mno-dsp, but always ignore them for -mdsp,
-;; even if !ISA_HAS_DSP_MULT.
-(define_insn "msubsidi4"
- [(set (match_operand:DI 0 "muldiv_target_operand" "=ka")
- (minus:DI
- (match_operand:DI 3 "muldiv_target_operand" "0")
- (mult:DI
- (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
- (any_extend:DI (match_operand:SI 2 "register_operand" "d")))))]
- "!TARGET_64BIT && (ISA_HAS_MSAC || GENERATE_MADD_MSUB || ISA_HAS_DSP)"
-{
- if (ISA_HAS_DSP_MULT)
- return "msub\t%q0,%1,%2";
- else if (TARGET_MIPS5500 || GENERATE_MADD_MSUB)
- return "msub\t%1,%2";
- else
- return "msac\t$0,%1,%2";
-}
- [(set_attr "type" "imadd")
- (set_attr "accum_in" "3")
- (set_attr "mode" "SI")])
-
-;; _highpart patterns
-
-(define_expand "mulsi3_highpart"
- [(set (match_operand:SI 0 "register_operand")
- (truncate:SI
- (lshiftrt:DI
- (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand"))
- (any_extend:DI (match_operand:SI 2 "register_operand")))
- (const_int 32))))]
- "!TARGET_NO_HW_MULT"
-{
- if (ISA_HAS_MULHI)
- emit_insn (gen_mulsi3_highpart_mulhi_internal (operands[0],
- operands[1],
- operands[2]));
- else if (TARGET_MIPS16)
- emit_insn (gen_mulsi3_highpart_split (operands[0], operands[1],
- operands[2]));
- else
- emit_insn (gen_mulsi3_highpart_internal (operands[0], operands[1],
- operands[2]));
- DONE;
-})
-
-(define_insn_and_split "mulsi3_highpart_internal"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (truncate:SI
- (lshiftrt:DI
- (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
- (any_extend:DI (match_operand:SI 2 "register_operand" "d")))
- (const_int 32))))
- (clobber (match_scratch:SI 3 "=l"))]
- "!ISA_HAS_MULHI && !TARGET_MIPS16 && !TARGET_NO_HW_MULT"
- { return TARGET_FIX_R4000 ? "mult\t%1,%2\n\tmfhi\t%0" : "#"; }
- "&& reload_completed && !TARGET_FIX_R4000 && !TARGET_NO_HW_MULT"
- [(const_int 0)]
-{
- emit_insn (gen_mulsi3_highpart_split (operands[0], operands[1],
- operands[2]));
- DONE;
-}
- [(set_attr "type" "imul")
- (set_attr "mode" "SI")
- (set_attr "insn_count" "2")])
-
-(define_expand "mulsi3_highpart_split"
- [(set (match_operand:SI 0 "register_operand")
- (truncate:SI
- (lshiftrt:DI
- (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand"))
- (any_extend:DI (match_operand:SI 2 "register_operand")))
- (const_int 32))))]
- ""
-{
- rtx hilo;
-
- if (TARGET_64BIT)
- {
- hilo = gen_rtx_REG (TImode, MD_REG_FIRST);
- emit_insn (gen_mulsidi3_64bit_hilo (hilo, operands[1], operands[2]));
- emit_insn (gen_mfhisi_ti (operands[0], hilo));
- }
- else
- {
- hilo = gen_rtx_REG (DImode, MD_REG_FIRST);
- emit_insn (gen_mulsidi3_32bit (hilo, operands[1], operands[2]));
- emit_insn (gen_mfhisi_di (operands[0], hilo));
- }
- DONE;
-})
-
-(define_insn "mulsi3_highpart_mulhi_internal"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (truncate:SI
- (lshiftrt:DI
- (mult:DI
- (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
- (any_extend:DI (match_operand:SI 2 "register_operand" "d")))
- (const_int 32))))
- (clobber (match_scratch:SI 3 "=l"))]
- "ISA_HAS_MULHI"
- "mulhi\t%0,%1,%2"
- [(set_attr "type" "imul3")
- (set_attr "mode" "SI")])
-
-(define_insn "*mulsi3_highpart_neg_mulhi_internal"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (truncate:SI
- (lshiftrt:DI
- (neg:DI
- (mult:DI
- (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
- (any_extend:DI (match_operand:SI 2 "register_operand" "d"))))
- (const_int 32))))
- (clobber (match_scratch:SI 3 "=l"))]
- "ISA_HAS_MULHI"
- "mulshi\t%0,%1,%2"
- [(set_attr "type" "imul3")
- (set_attr "mode" "SI")])
-
-;; Disable unsigned multiplication for -mfix-vr4120. This is for VR4120
-;; errata MD(0), which says that dmultu does not always produce the
-;; correct result.
-(define_expand "muldi3_highpart"
- [(set (match_operand:DI 0 "register_operand")
- (truncate:DI
- (lshiftrt:TI
- (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand"))
- (any_extend:TI (match_operand:DI 2 "register_operand")))
- (const_int 64))))]
- "ISA_HAS_DMULT && !( == ZERO_EXTEND && TARGET_FIX_VR4120)"
-{
- if (TARGET_MIPS16)
- emit_insn (gen_muldi3_highpart_split (operands[0], operands[1],
- operands[2]));
- else
- emit_insn (gen_muldi3_highpart_internal (operands[0], operands[1],
- operands[2]));
- DONE;
-})
-
-(define_insn_and_split "muldi3_highpart_internal"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (truncate:DI
- (lshiftrt:TI
- (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand" "d"))
- (any_extend:TI (match_operand:DI 2 "register_operand" "d")))
- (const_int 64))))
- (clobber (match_scratch:DI 3 "=l"))]
- "ISA_HAS_DMULT
- && !TARGET_MIPS16
- && !( == ZERO_EXTEND && TARGET_FIX_VR4120)"
- { return TARGET_FIX_R4000 ? "dmult\t%1,%2\n\tmfhi\t%0" : "#"; }
- "&& reload_completed && !TARGET_FIX_R4000"
- [(const_int 0)]
-{
- emit_insn (gen_muldi3_highpart_split (operands[0], operands[1],
- operands[2]));
- DONE;
-}
- [(set_attr "type" "imul")
- (set_attr "mode" "DI")
- (set_attr "insn_count" "2")])
-
-(define_expand "muldi3_highpart_split"
- [(set (match_operand:DI 0 "register_operand")
- (truncate:DI
- (lshiftrt:TI
- (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand"))
- (any_extend:TI (match_operand:DI 2 "register_operand")))
- (const_int 64))))]
- ""
-{
- rtx hilo;
-
- hilo = gen_rtx_REG (TImode, MD_REG_FIRST);
- emit_insn (gen_mulditi3_internal (hilo, operands[1], operands[2]));
- emit_insn (gen_mfhidi_ti (operands[0], hilo));
- DONE;
-})
-
-(define_expand "mulditi3"
- [(set (match_operand:TI 0 "register_operand")
- (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand"))
- (any_extend:TI (match_operand:DI 2 "register_operand"))))]
- "ISA_HAS_DMULT && !( == ZERO_EXTEND && TARGET_FIX_VR4120)"
-{
- rtx hilo;
-
- if (TARGET_MIPS16)
- {
- hilo = gen_rtx_REG (TImode, MD_REG_FIRST);
- emit_insn (gen_mulditi3_internal (hilo, operands[1], operands[2]));
- emit_move_insn (operands[0], hilo);
- }
- else if (TARGET_FIX_R4000)
- emit_insn (gen_mulditi3_r4000 (operands[0], operands[1], operands[2]));
- else
- emit_insn (gen_mulditi3_internal (operands[0], operands[1],
- operands[2]));
- DONE;
-})
-
-(define_insn "mulditi3_internal"
- [(set (match_operand:TI 0 "muldiv_target_operand" "=x")
- (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand" "d"))
- (any_extend:TI (match_operand:DI 2 "register_operand" "d"))))]
- "ISA_HAS_DMULT
- && !TARGET_FIX_R4000
- && !( == ZERO_EXTEND && TARGET_FIX_VR4120)"
- "dmult\t%1,%2"
- [(set_attr "type" "imul")
- (set_attr "mode" "DI")])
-
-(define_insn "mulditi3_r4000"
- [(set (match_operand:TI 0 "register_operand" "=d")
- (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand" "d"))
- (any_extend:TI (match_operand:DI 2 "register_operand" "d"))))
- (clobber (match_scratch:TI 3 "=x"))]
- "ISA_HAS_DMULT
- && TARGET_FIX_R4000
- && !( == ZERO_EXTEND && TARGET_FIX_VR4120)"
- "dmult\t%1,%2\;mflo\t%L0\;mfhi\t%M0"
- [(set_attr "type" "imul")
- (set_attr "mode" "DI")
- (set_attr "insn_count" "3")])
-
-;; The R4650 supports a 32-bit multiply/ 64-bit accumulate
-;; instruction. The HI/LO registers are used as a 64-bit accumulator.
-
-(define_insn "madsi"
- [(set (match_operand:SI 0 "register_operand" "+l")
- (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d")
- (match_operand:SI 2 "register_operand" "d"))
- (match_dup 0)))]
- "TARGET_MAD"
- "mad\t%1,%2"
- [(set_attr "type" "imadd")
- (set_attr "accum_in" "0")
- (set_attr "mode" "SI")])
-
-;; See the comment above msubsidi4 for the relationship between
-;; ISA_HAS_DSP and ISA_HAS_DSP_MULT.
-(define_insn "maddsidi4"
- [(set (match_operand:DI 0 "muldiv_target_operand" "=ka")
- (plus:DI
- (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
- (any_extend:DI (match_operand:SI 2 "register_operand" "d")))
- (match_operand:DI 3 "muldiv_target_operand" "0")))]
- "(TARGET_MAD || ISA_HAS_MACC || GENERATE_MADD_MSUB || ISA_HAS_DSP)
- && !TARGET_64BIT"
-{
- if (TARGET_MAD)
- return "mad\t%1,%2";
- else if (ISA_HAS_DSP_MULT)
- return "madd\t%q0,%1,%2";
- else if (GENERATE_MADD_MSUB || TARGET_MIPS5500)
- return "madd\t%1,%2";
- else
- /* See comment in *macc. */
- return "%[macc\t%@,%1,%2%]";
-}
- [(set_attr "type" "imadd")
- (set_attr "accum_in" "3")
- (set_attr "mode" "SI")])
-
-;; Floating point multiply accumulate instructions.
-
-(define_insn "*madd4"
- [(set (match_operand:ANYF 0 "register_operand" "=f")
- (plus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
- (match_operand:ANYF 2 "register_operand" "f"))
- (match_operand:ANYF 3 "register_operand" "f")))]
- "ISA_HAS_FP_MADD4_MSUB4 && TARGET_FUSED_MADD"
- "madd.\t%0,%3,%1,%2"
- [(set_attr "type" "fmadd")
- (set_attr "accum_in" "3")
- (set_attr "mode" "")])
-
-(define_insn "*madd3"
- [(set (match_operand:ANYF 0 "register_operand" "=f")
- (plus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
- (match_operand:ANYF 2 "register_operand" "f"))
- (match_operand:ANYF 3 "register_operand" "0")))]
- "ISA_HAS_FP_MADD3_MSUB3 && TARGET_FUSED_MADD"
- "madd.\t%0,%1,%2"
- [(set_attr "type" "fmadd")
- (set_attr "accum_in" "3")
- (set_attr "mode" "")])
-
-(define_insn "*msub4"
- [(set (match_operand:ANYF 0 "register_operand" "=f")
- (minus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
- (match_operand:ANYF 2 "register_operand" "f"))
- (match_operand:ANYF 3 "register_operand" "f")))]
- "ISA_HAS_FP_MADD4_MSUB4 && TARGET_FUSED_MADD"
- "msub.\t%0,%3,%1,%2"
- [(set_attr "type" "fmadd")
- (set_attr "accum_in" "3")
- (set_attr "mode" "")])
-
-(define_insn "*msub3"
- [(set (match_operand:ANYF 0 "register_operand" "=f")
- (minus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
- (match_operand:ANYF 2 "register_operand" "f"))
- (match_operand:ANYF 3 "register_operand" "0")))]
- "ISA_HAS_FP_MADD3_MSUB3 && TARGET_FUSED_MADD"
- "msub.\t%0,%1,%2"
- [(set_attr "type" "fmadd")
- (set_attr "accum_in" "3")
- (set_attr "mode" "")])
-
-(define_insn "*nmadd4"
- [(set (match_operand:ANYF 0 "register_operand" "=f")
- (neg:ANYF (plus:ANYF
- (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
- (match_operand:ANYF 2 "register_operand" "f"))
- (match_operand:ANYF 3 "register_operand" "f"))))]
- "ISA_HAS_NMADD4_NMSUB4
- && TARGET_FUSED_MADD
- && HONOR_SIGNED_ZEROS (mode)
- && !HONOR_NANS (mode)"
- "nmadd.\t%0,%3,%1,%2"
- [(set_attr "type" "fmadd")
- (set_attr "accum_in" "3")
- (set_attr "mode" "")])
-
-(define_insn "*nmadd3"
- [(set (match_operand:ANYF 0 "register_operand" "=f")
- (neg:ANYF (plus:ANYF
- (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
- (match_operand:ANYF 2 "register_operand" "f"))
- (match_operand:ANYF 3 "register_operand" "0"))))]
- "ISA_HAS_NMADD3_NMSUB3
- && TARGET_FUSED_MADD
- && HONOR_SIGNED_ZEROS (mode)
- && !HONOR_NANS (mode)"
- "nmadd.\t%0,%1,%2"
- [(set_attr "type" "fmadd")
- (set_attr "accum_in" "3")
- (set_attr "mode" "")])
-
-(define_insn "*nmadd4_fastmath"
- [(set (match_operand:ANYF 0 "register_operand" "=f")
- (minus:ANYF
- (mult:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand" "f"))
- (match_operand:ANYF 2 "register_operand" "f"))
- (match_operand:ANYF 3 "register_operand" "f")))]
- "ISA_HAS_NMADD4_NMSUB4
- && TARGET_FUSED_MADD
- && !HONOR_SIGNED_ZEROS (mode)
- && !HONOR_NANS (mode)"
- "nmadd.\t%0,%3,%1,%2"
- [(set_attr "type" "fmadd")
- (set_attr "accum_in" "3")
- (set_attr "mode" "")])
-
-(define_insn "*nmadd3_fastmath"
- [(set (match_operand:ANYF 0 "register_operand" "=f")
- (minus:ANYF
- (mult:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand" "f"))
- (match_operand:ANYF 2 "register_operand" "f"))
- (match_operand:ANYF 3 "register_operand" "0")))]
- "ISA_HAS_NMADD3_NMSUB3
- && TARGET_FUSED_MADD
- && !HONOR_SIGNED_ZEROS (mode)
- && !HONOR_NANS (mode)"
- "nmadd.\t%0,%1,%2"
- [(set_attr "type" "fmadd")
- (set_attr "accum_in" "3")
- (set_attr "mode" "")])
-
-(define_insn "*nmsub4"
- [(set (match_operand:ANYF 0 "register_operand" "=f")
- (neg:ANYF (minus:ANYF
- (mult:ANYF (match_operand:ANYF 2 "register_operand" "f")
- (match_operand:ANYF 3 "register_operand" "f"))
- (match_operand:ANYF 1 "register_operand" "f"))))]
- "ISA_HAS_NMADD4_NMSUB4
- && TARGET_FUSED_MADD
- && HONOR_SIGNED_ZEROS (mode)
- && !HONOR_NANS (mode)"
- "nmsub.\t%0,%1,%2,%3"
- [(set_attr "type" "fmadd")
- (set_attr "accum_in" "1")
- (set_attr "mode" "")])
-
-(define_insn "*nmsub3"
- [(set (match_operand:ANYF 0 "register_operand" "=f")
- (neg:ANYF (minus:ANYF
- (mult:ANYF (match_operand:ANYF 2 "register_operand" "f")
- (match_operand:ANYF 3 "register_operand" "f"))
- (match_operand:ANYF 1 "register_operand" "0"))))]
- "ISA_HAS_NMADD3_NMSUB3
- && TARGET_FUSED_MADD
- && HONOR_SIGNED_ZEROS (mode)
- && !HONOR_NANS (mode)"
- "nmsub.\t%0,%1,%2"
- [(set_attr "type" "fmadd")
- (set_attr "accum_in" "1")
- (set_attr "mode" "")])
-
-(define_insn "*nmsub4_fastmath"
- [(set (match_operand:ANYF 0 "register_operand" "=f")
- (minus:ANYF
- (match_operand:ANYF 1 "register_operand" "f")
- (mult:ANYF (match_operand:ANYF 2 "register_operand" "f")
- (match_operand:ANYF 3 "register_operand" "f"))))]
- "ISA_HAS_NMADD4_NMSUB4
- && TARGET_FUSED_MADD
- && !HONOR_SIGNED_ZEROS (mode)
- && !HONOR_NANS (mode)"
- "nmsub.\t%0,%1,%2,%3"
- [(set_attr "type" "fmadd")
- (set_attr "accum_in" "1")
- (set_attr "mode" "")])
-
-(define_insn "*nmsub3_fastmath"
- [(set (match_operand:ANYF 0 "register_operand" "=f")
- (minus:ANYF
- (match_operand:ANYF 1 "register_operand" "f")
- (mult:ANYF (match_operand:ANYF 2 "register_operand" "f")
- (match_operand:ANYF 3 "register_operand" "0"))))]
- "ISA_HAS_NMADD3_NMSUB3
- && TARGET_FUSED_MADD
- && !HONOR_SIGNED_ZEROS (mode)
- && !HONOR_NANS (mode)"
- "nmsub.\t%0,%1,%2"
- [(set_attr "type" "fmadd")
- (set_attr "accum_in" "1")
- (set_attr "mode" "")])
-
-;;
-;; ....................
-;;
-;; DIVISION and REMAINDER
-;;
-;; ....................
-;;
-
-(define_expand "div3"
- [(set (match_operand:ANYF 0 "register_operand")
- (div:ANYF (match_operand:ANYF 1 "reg_or_1_operand")
- (match_operand:ANYF 2 "register_operand")))]
- ""
-{
- if (const_1_operand (operands[1], mode))
- if (!(ISA_HAS_FP_RECIP_RSQRT (mode)
- && flag_unsafe_math_optimizations))
- operands[1] = force_reg (mode, operands[1]);
-})
-
-;; These patterns work around the early SB-1 rev2 core "F1" erratum:
-;;
-;; If an mfc1 or dmfc1 happens to access the floating point register
-;; file at the same time a long latency operation (div, sqrt, recip,
-;; sqrt) iterates an intermediate result back through the floating
-;; point register file bypass, then instead returning the correct
-;; register value the mfc1 or dmfc1 operation returns the intermediate
-;; result of the long latency operation.
-;;
-;; The workaround is to insert an unconditional 'mov' from/to the
-;; long latency op destination register.
-
-(define_insn "*div3"
- [(set (match_operand:ANYF 0 "register_operand" "=f")
- (div:ANYF (match_operand:ANYF 1 "register_operand" "f")
- (match_operand:ANYF 2 "register_operand" "f")))]
- ""
-{
- if (TARGET_FIX_SB1)
- return "div.\t%0,%1,%2\;mov.\t%0,%0";
- else
- return "div.\t%0,%1,%2";
-}
- [(set_attr "type" "fdiv")
- (set_attr "mode" "")
- (set (attr "insn_count")
- (if_then_else (match_test "TARGET_FIX_SB1")
- (const_int 2)
- (const_int 1)))])
-
-(define_insn "*recip3"
- [(set (match_operand:ANYF 0 "register_operand" "=f")
- (div:ANYF (match_operand:ANYF 1 "const_1_operand" "")
- (match_operand:ANYF 2 "register_operand" "f")))]
- "ISA_HAS_FP_RECIP_RSQRT (mode) && flag_unsafe_math_optimizations"
-{
- if (TARGET_FIX_SB1)
- return "recip.\t%0,%2\;mov.\t%0,%0";
- else
- return "recip.\t%0,%2";
-}
- [(set_attr "type" "frdiv")
- (set_attr "mode" "")
- (set (attr "insn_count")
- (if_then_else (match_test "TARGET_FIX_SB1")
- (const_int 2)
- (const_int 1)))])
-
-;; VR4120 errata MD(A1): signed division instructions do not work correctly
-;; with negative operands. We use special libgcc functions instead.
-(define_expand "divmod4"
- [(parallel
- [(set (match_operand:GPR 0 "register_operand")
- (div:GPR (match_operand:GPR 1 "register_operand")
- (match_operand:GPR 2 "register_operand")))
- (set (match_operand:GPR 3 "register_operand")
- (mod:GPR (match_dup 1)
- (match_dup 2)))])]
- "ISA_HAS_DIV && !TARGET_FIX_VR4120 && !TARGET_NO_HW_DIV"
-{
- if (TARGET_MIPS16)
- {
- rtx lo = gen_rtx_REG (mode, LO_REGNUM);
- emit_insn (gen_divmod4_mips16 (operands[0], operands[1],
- operands[2], operands[3], lo));
- DONE;
- }
-})
-
-(define_insn_and_split "*divmod4"
- [(set (match_operand:GPR 0 "register_operand" "=l")
- (div:GPR (match_operand:GPR 1 "register_operand" "d")
- (match_operand:GPR 2 "register_operand" "d")))
- (set (match_operand:GPR 3 "register_operand" "=d")
- (mod:GPR (match_dup 1)
- (match_dup 2)))]
- "ISA_HAS_DIV && !TARGET_FIX_VR4120 && !TARGET_MIPS16 && !TARGET_NO_HW_DIV"
- "#"
- "&& reload_completed"
- [(const_int 0)]
-{
- emit_insn (gen_divmod4_split (operands[3], operands[1], operands[2]));
- DONE;
-}
- [(set_attr "type" "idiv")
- (set_attr "mode" "")
- (set_attr "insn_count" "2")])
-
-;; Expand generates divmod instructions for individual division and modulus
-;; operations. We then rely on CSE to reuse earlier divmods where possible.
-;; This means that, when generating MIPS16 code, it is better not to expose
-;; the fixed LO register until after CSE has finished. However, it's still
-;; better to split before register allocation, so that we don't allocate
-;; one of the scarce MIPS16 registers to an unused result.
-(define_insn_and_split "divmod4_mips16"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (div:GPR (match_operand:GPR 1 "register_operand" "d")
- (match_operand:GPR 2 "register_operand" "d")))
- (set (match_operand:GPR 3 "register_operand" "=d")
- (mod:GPR (match_dup 1)
- (match_dup 2)))
- (clobber (match_operand:GPR 4 "lo_operand" "=l"))]
- "ISA_HAS_DIV && !TARGET_FIX_VR4120 && TARGET_MIPS16"
- "#"
- "&& cse_not_expected"
- [(const_int 0)]
-{
- emit_insn (gen_divmod4_split (operands[3], operands[1], operands[2]));
- emit_move_insn (operands[0], operands[4]);
- DONE;
-}
- [(set_attr "type" "idiv")
- (set_attr "mode" "")
- (set_attr "insn_count" "3")])
-
-(define_expand "udivmod4"
- [(parallel
- [(set (match_operand:GPR 0 "register_operand")
- (udiv:GPR (match_operand:GPR 1 "register_operand")
- (match_operand:GPR 2 "register_operand")))
- (set (match_operand:GPR 3 "register_operand")
- (umod:GPR (match_dup 1)
- (match_dup 2)))])]
- "ISA_HAS_DIV && !TARGET_FIX_VR4120 && !TARGET_NO_HW_DIV"
-{
- if (TARGET_MIPS16)
- {
- rtx lo = gen_rtx_REG (mode, LO_REGNUM);
- emit_insn (gen_udivmod4_mips16 (operands[0], operands[1],
- operands[2], operands[3], lo));
- DONE;
- }
-})
-
-(define_insn_and_split "*udivmod4"
- [(set (match_operand:GPR 0 "register_operand" "=l")
- (udiv:GPR (match_operand:GPR 1 "register_operand" "d")
- (match_operand:GPR 2 "register_operand" "d")))
- (set (match_operand:GPR 3 "register_operand" "=d")
- (umod:GPR (match_dup 1)
- (match_dup 2)))]
- "ISA_HAS_DIV && !TARGET_MIPS16 && !TARGET_NO_HW_DIV"
- "#"
- "reload_completed"
- [(const_int 0)]
-{
- emit_insn (gen_udivmod4_split (operands[3], operands[1], operands[2]));
- DONE;
-}
- [(set_attr "type" "idiv")
- (set_attr "mode" "")
- (set_attr "insn_count" "2")])
-
-;; See the comment above "divmod4_mips16" for the split timing.
-(define_insn_and_split "udivmod4_mips16"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (udiv:GPR (match_operand:GPR 1 "register_operand" "d")
- (match_operand:GPR 2 "register_operand" "d")))
- (set (match_operand:GPR 3 "register_operand" "=d")
- (umod:GPR (match_dup 1)
- (match_dup 2)))
- (clobber (match_operand:GPR 4 "lo_operand" "=l"))]
- "ISA_HAS_DIV && TARGET_MIPS16"
- "#"
- "cse_not_expected"
- [(const_int 0)]
-{
- emit_insn (gen_udivmod4_split (operands[3], operands[1], operands[2]));
- emit_move_insn (operands[0], operands[4]);
- DONE;
-}
- [(set_attr "type" "idiv")
- (set_attr "mode" "")
- (set_attr "insn_count" "3")])
-
-(define_expand "divmod4_split"
- [(set (match_operand:GPR 0 "register_operand")
- (any_mod:GPR (match_operand:GPR 1 "register_operand")
- (match_operand:GPR 2 "register_operand")))]
- ""
-{
- rtx hilo;
-
- if (TARGET_64BIT)
- {
- hilo = gen_rtx_REG (TImode, MD_REG_FIRST);
- emit_insn (gen_divmod4_hilo_ti (hilo, operands[1],
- operands[2]));
- emit_insn (gen_mfhi_ti (operands[0], hilo));
- }
- else
- {
- hilo = gen_rtx_REG (DImode, MD_REG_FIRST);
- emit_insn (gen_divmod4_hilo_di (hilo, operands[1],
- operands[2]));
- emit_insn (gen_mfhi_di (operands[0], hilo));
- }
- DONE;
-})
-
-(define_insn "