summaryrefslogtreecommitdiff
path: root/gcc/config/mips
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2014-10-30 09:35:42 +0000
committer <>2015-01-09 11:51:27 +0000
commitc27a97d04853380f1e80525391b3f0d156ed4c84 (patch)
tree68ffaade7c605bc80cffa18360799c98a810976f /gcc/config/mips
parent6af3fdec2262dd94954acc5e426ef71cbd4521d3 (diff)
downloadgcc-tarball-c27a97d04853380f1e80525391b3f0d156ed4c84.tar.gz
Imported from /home/lorry/working-area/delta_gcc-tarball/gcc-4.9.2.tar.bz2.gcc-4.9.2
Diffstat (limited to 'gcc/config/mips')
-rw-r--r--gcc/config/mips/10000.md12
-rw-r--r--gcc/config/mips/20kc.md8
-rw-r--r--gcc/config/mips/24k.md140
-rw-r--r--gcc/config/mips/3000.md2
-rw-r--r--gcc/config/mips/4000.md2
-rw-r--r--gcc/config/mips/4100.md2
-rw-r--r--gcc/config/mips/4130.md10
-rw-r--r--gcc/config/mips/4300.md2
-rw-r--r--gcc/config/mips/4600.md71
-rw-r--r--gcc/config/mips/4k.md8
-rw-r--r--gcc/config/mips/5000.md2
-rw-r--r--gcc/config/mips/5400.md6
-rw-r--r--gcc/config/mips/5500.md8
-rw-r--r--gcc/config/mips/5k.md8
-rw-r--r--gcc/config/mips/6000.md2
-rw-r--r--gcc/config/mips/7000.md8
-rw-r--r--gcc/config/mips/74k.md103
-rw-r--r--gcc/config/mips/9000.md8
-rw-r--r--gcc/config/mips/constraints.md156
-rw-r--r--gcc/config/mips/driver-native.c71
-rw-r--r--gcc/config/mips/elf.h3
-rw-r--r--gcc/config/mips/elfoabi.h3
-rw-r--r--gcc/config/mips/elforion.h2
-rw-r--r--gcc/config/mips/generic.md20
-rwxr-xr-xgcc/config/mips/genopt.sh4
-rw-r--r--gcc/config/mips/gnu-user.h27
-rw-r--r--gcc/config/mips/gnu-user64.h30
-rw-r--r--gcc/config/mips/iris6.h372
-rw-r--r--gcc/config/mips/iris6.opt45
-rw-r--r--gcc/config/mips/irix6-c.c38
-rw-r--r--gcc/config/mips/linux-common.h64
-rw-r--r--gcc/config/mips/linux.h10
-rw-r--r--gcc/config/mips/linux64.h23
-rw-r--r--gcc/config/mips/loongson.h2
-rw-r--r--gcc/config/mips/loongson.md2
-rw-r--r--gcc/config/mips/loongson2ef.md8
-rw-r--r--gcc/config/mips/loongson3a.md6
-rw-r--r--gcc/config/mips/micromips.md138
-rw-r--r--gcc/config/mips/mips-cpus.def33
-rw-r--r--gcc/config/mips/mips-dsp.md151
-rw-r--r--gcc/config/mips/mips-dspr2.md87
-rw-r--r--gcc/config/mips/mips-fixed.md2
-rw-r--r--gcc/config/mips/mips-ftypes.def6
-rw-r--r--gcc/config/mips/mips-modes.def10
-rw-r--r--gcc/config/mips/mips-opts.h11
-rw-r--r--gcc/config/mips/mips-protos.h67
-rw-r--r--gcc/config/mips/mips-ps-3d.md6
-rw-r--r--gcc/config/mips/mips-tables.opt307
-rw-r--r--gcc/config/mips/mips.c2732
-rw-r--r--gcc/config/mips/mips.h445
-rw-r--r--gcc/config/mips/mips.md1675
-rw-r--r--gcc/config/mips/mips.opt66
-rw-r--r--gcc/config/mips/mti-elf.h42
-rw-r--r--gcc/config/mips/mti-linux.h46
-rw-r--r--gcc/config/mips/n32-elf.h35
-rw-r--r--gcc/config/mips/netbsd.h7
-rw-r--r--gcc/config/mips/octeon.md13
-rw-r--r--gcc/config/mips/openbsd.h101
-rw-r--r--gcc/config/mips/predicates.md130
-rw-r--r--gcc/config/mips/r3900.h3
-rw-r--r--gcc/config/mips/rtems.h3
-rw-r--r--gcc/config/mips/sb1.md12
-rw-r--r--gcc/config/mips/sdb.h87
-rw-r--r--gcc/config/mips/sde.h34
-rw-r--r--gcc/config/mips/sde.opt2
-rw-r--r--gcc/config/mips/sdemtk.h3
-rw-r--r--gcc/config/mips/sr71k.md6
-rw-r--r--gcc/config/mips/st.h3
-rw-r--r--gcc/config/mips/sync.md208
-rw-r--r--gcc/config/mips/t-elf3
-rw-r--r--gcc/config/mips/t-irix64
-rw-r--r--gcc/config/mips/t-isa32643
-rw-r--r--gcc/config/mips/t-linux642
-rw-r--r--gcc/config/mips/t-mips2
-rw-r--r--gcc/config/mips/t-mti-elf50
-rw-r--r--gcc/config/mips/t-mti-linux50
-rw-r--r--gcc/config/mips/t-r39003
-rw-r--r--gcc/config/mips/t-rtems2
-rw-r--r--gcc/config/mips/t-sb12
-rw-r--r--gcc/config/mips/t-sde10
-rw-r--r--gcc/config/mips/t-sdemtk2
-rw-r--r--gcc/config/mips/t-sr71k2
-rw-r--r--gcc/config/mips/t-st2
-rw-r--r--gcc/config/mips/t-vr2
-rw-r--r--gcc/config/mips/t-vxworks4
-rw-r--r--gcc/config/mips/vr.h2
-rw-r--r--gcc/config/mips/vxworks.h3
-rw-r--r--gcc/config/mips/xlp.md213
-rw-r--r--gcc/config/mips/xlr.md11
89 files changed, 5470 insertions, 2661 deletions
diff --git a/gcc/config/mips/10000.md b/gcc/config/mips/10000.md
index ad21e9e936..74dd3eca03 100644
--- a/gcc/config/mips/10000.md
+++ b/gcc/config/mips/10000.md
@@ -1,5 +1,5 @@
;; DFA-based pipeline description for the VR1x000.
-;; Copyright (C) 2005, 2006, 2008 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
@@ -68,21 +68,19 @@
;; Miscellaneous arith goes here too (this is a guess).
(define_insn_reservation "r10k_arith" 1
(and (eq_attr "cpu" "r10000")
- (eq_attr "type" "arith,mthilo,slt,clz,const,nop,trap,logical"))
+ (eq_attr "type" "arith,mthi,mtlo,slt,clz,const,nop,trap,logical"))
"r10k_alu1 | r10k_alu2")
;; We treat mfhilo differently, because we need to know when
;; it's HI and when it's LO.
(define_insn_reservation "r10k_mfhi" 1
(and (eq_attr "cpu" "r10000")
- (and (eq_attr "type" "mfhilo")
- (not (match_operand 1 "lo_operand"))))
+ (eq_attr "type" "mfhi"))
"r10k_alu1 | r10k_alu2")
(define_insn_reservation "r10k_mflo" 1
(and (eq_attr "cpu" "r10000")
- (and (eq_attr "type" "mfhilo")
- (match_operand 1 "lo_operand")))
+ (eq_attr "type" "mflo"))
"r10k_alu1 | r10k_alu2")
@@ -249,5 +247,5 @@
;; Handle unknown/multi insns here (this is a guess).
(define_insn_reservation "r10k_unknown" 1
(and (eq_attr "cpu" "r10000")
- (eq_attr "type" "unknown,multi"))
+ (eq_attr "type" "unknown,multi,atomic,syncloop"))
"r10k_alu1 + r10k_alu2")
diff --git a/gcc/config/mips/20kc.md b/gcc/config/mips/20kc.md
index 1d3aadf69a..c0c3feb359 100644
--- a/gcc/config/mips/20kc.md
+++ b/gcc/config/mips/20kc.md
@@ -1,4 +1,4 @@
-;; Copyright (C) 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
@@ -195,12 +195,12 @@
;; cycle latency. Repeat rate is 3 for both.
(define_insn_reservation "r20kc_imthilo" 3
(and (eq_attr "cpu" "20kc")
- (eq_attr "type" "mthilo"))
+ (eq_attr "type" "mthi,mtlo"))
"r20kc_impydiv+(r20kc_impydiv_iter*3)")
(define_insn_reservation "r20kc_imfhilo" 1
(and (eq_attr "cpu" "20kc")
- (eq_attr "type" "mfhilo"))
+ (eq_attr "type" "mfhi,mflo"))
"r20kc_impydiv+(r20kc_impydiv_iter*3)")
;; Move to fp coprocessor.
@@ -280,5 +280,5 @@
;; Force single-dispatch for unknown or multi.
(define_insn_reservation "r20kc_unknown" 1
(and (eq_attr "cpu" "20kc")
- (eq_attr "type" "unknown,multi"))
+ (eq_attr "type" "unknown,multi,atomic,syncloop"))
"r20kc_single_dispatch")
diff --git a/gcc/config/mips/24k.md b/gcc/config/mips/24k.md
index 5df8a32dc5..9ed83dd964 100644
--- a/gcc/config/mips/24k.md
+++ b/gcc/config/mips/24k.md
@@ -8,7 +8,7 @@
;; References:
;; "MIPS32 24K Processor Core Family Software User's Manual, Rev 3.04."
;;
-;; Copyright (C) 2005, 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
@@ -94,13 +94,13 @@
;; mfhi, mflo, mflhxu - deliver result to gpr in 5 cycles
(define_insn_reservation "r24k_int_mfhilo" 5
(and (eq_attr "cpu" "24kc,24kf2_1,24kf1_1")
- (eq_attr "type" "mfhilo"))
+ (eq_attr "type" "mfhi,mflo"))
"r24k_iss+(r24k_mul3a|r24k_mul3b|r24k_mul3c)")
;; mthi, mtlo, mtlhx - deliver result to hi/lo, thence madd, handled as bypass
(define_insn_reservation "r24k_int_mthilo" 1
(and (eq_attr "cpu" "24kc,24kf2_1,24kf1_1")
- (eq_attr "type" "mthilo"))
+ (eq_attr "type" "mthi,mtlo"))
"r24k_iss+(r24k_mul3a|r24k_mul3b|r24k_mul3c)")
;; div - default to 36 cycles for 32bit operands. Faster for 24bit, 16bit and
@@ -122,18 +122,7 @@
;; 6. Store
(define_insn_reservation "r24k_int_store" 1
(and (eq_attr "cpu" "24kc,24kf2_1,24kf1_1")
- (and (eq_attr "type" "store")
- (eq_attr "mode" "!unknown")))
- "r24k_iss+r24k_ixu_arith")
-
-;; 6.1 Special case - matches the cprestore pattern which don't set the mode
-;; attrib. This avoids being set as r24k_int_store and have it checked
-;; against store_data_bypass_p, which would then fail because cprestore
-;; does not have a normal SET pattern.
-(define_insn_reservation "r24k_unknown_store" 1
- (and (eq_attr "cpu" "24kc,24kf2_1,24kf1_1")
- (and (eq_attr "type" "store")
- (eq_attr "mode" "unknown")))
+ (eq_attr "type" "store"))
"r24k_iss+r24k_ixu_arith")
@@ -149,7 +138,7 @@
;; scheduling via log links, but not used here).
(define_insn_reservation "r24k_int_unknown" 0
(and (eq_attr "cpu" "24kc,24kf2_1,24kf1_1")
- (eq_attr "type" "unknown"))
+ (eq_attr "type" "unknown,atomic,syncloop"))
"r24k_iss")
@@ -169,7 +158,7 @@
;; load->store base: 3 cycles
;; load->prefetch: 3 cycles
(define_bypass 3 "r24k_int_load" "r24k_int_load")
-(define_bypass 3 "r24k_int_load" "r24k_int_store" "!store_data_bypass_p")
+(define_bypass 3 "r24k_int_load" "r24k_int_store" "!mips_store_data_bypass_p")
(define_bypass 3 "r24k_int_load" "r24k_int_prefetch")
;; arith->next use : 1 cycles (Default)
@@ -177,14 +166,14 @@
;; arith->store base: 2 cycles
;; arith->prefetch: 2 cycles
(define_bypass 2 "r24k_int_arith" "r24k_int_load")
-(define_bypass 2 "r24k_int_arith" "r24k_int_store" "!store_data_bypass_p")
+(define_bypass 2 "r24k_int_arith" "r24k_int_store" "!mips_store_data_bypass_p")
(define_bypass 2 "r24k_int_arith" "r24k_int_prefetch")
;; mul3->next use : 5 cycles (default)
;; mul3->l/s base : 6 cycles
;; mul3->prefetch : 6 cycles
(define_bypass 6 "r24k_int_mul3" "r24k_int_load")
-(define_bypass 6 "r24k_int_mul3" "r24k_int_store" "!store_data_bypass_p")
+(define_bypass 6 "r24k_int_mul3" "r24k_int_store" "!mips_store_data_bypass_p")
(define_bypass 6 "r24k_int_mul3" "r24k_int_prefetch")
;; mul3->madd/msub : 1 cycle
@@ -195,24 +184,121 @@
;; mfhilo->prefetch : 6 cycles
;; mthilo->madd/msub : 2 cycle (only for mthi/lo not mfhi/lo)
(define_bypass 6 "r24k_int_mfhilo" "r24k_int_load")
-(define_bypass 6 "r24k_int_mfhilo" "r24k_int_store" "!store_data_bypass_p")
+(define_bypass 6 "r24k_int_mfhilo" "r24k_int_store"
+ "!mips_store_data_bypass_p")
(define_bypass 6 "r24k_int_mfhilo" "r24k_int_prefetch")
(define_bypass 2 "r24k_int_mthilo" "r24k_int_madd")
;; cop->next use : 3 cycles (Default)
;; cop->l/s base : 4 cycles
;; (define_bypass 4 "r24k_int_cop" "r24k_int_load")
-;; (define_bypass 4 "r24k_int_cop" "r24k_int_store" "!store_data_bypass_p")
+;; (define_bypass 4 "r24k_int_cop" "r24k_int_store"
+;; "!mips_store_data_bypass_p")
;; multi->next use : 1 cycles (Default)
;; multi->l/s base : 2 cycles
;; multi->prefetch : 2 cycles
(define_bypass 2 "r24k_int_multi" "r24k_int_load")
-(define_bypass 2 "r24k_int_multi" "r24k_int_store" "!store_data_bypass_p")
+(define_bypass 2 "r24k_int_multi" "r24k_int_store" "!mips_store_data_bypass_p")
(define_bypass 2 "r24k_int_multi" "r24k_int_prefetch")
;; --------------------------------------------------------------
+;; DSP instructions
+;; --------------------------------------------------------------
+
+;; absq, addq, addsc, addu, addwc, bitrev, cmp, cmpgu, cmpu, insv, modsub,
+;; packrl, pick, preceq, preceu, precequ, precrq, precrqu, raddu, rddsp, repl,
+;; replv, shll, shllv, shra, shrav, shrl, shrlv, subq, subu, wrdsp
+(define_insn_reservation "r24k_dsp_alu" 2
+ (and (eq_attr "cpu" "24kc,24kf2_1,24kf1_1")
+ (eq_attr "type" "dspalu,dspalusat"))
+ "r24k_iss+r24k_ixu_arith")
+
+;; dpaq_s, dpau, dpsq_s, dpsu, maq_s, mulsaq
+(define_insn_reservation "r24k_dsp_mac" 1
+ (and (eq_attr "cpu" "24kc,24kf2_1,24kf1_1")
+ (eq_attr "type" "dspmac"))
+ "r24k_iss+(r24k_mul3a|r24k_mul3b|r24k_mul3c)")
+
+;; dpaq_sa, dpsq_sa, maq_sa
+(define_insn_reservation "r24k_dsp_mac_sat" 1
+ (and (eq_attr "cpu" "24kc,24kf2_1,24kf1_1")
+ (eq_attr "type" "dspmacsat"))
+ "r24k_iss+(r24k_mul3a|r24k_mul3b|r24k_mul3c)")
+
+;; extp, extpdp, extpdpv, extpv, extr, extrv
+(define_insn_reservation "r24k_dsp_acc_ext" 5
+ (and (eq_attr "cpu" "24kc,24kf2_1,24kf1_1")
+ (eq_attr "type" "accext"))
+ "r24k_iss+(r24k_mul3a|r24k_mul3b|r24k_mul3c)")
+
+;; mthlip, shilo, shilov
+(define_insn_reservation "r24k_dsp_acc_mod" 1
+ (and (eq_attr "cpu" "24kc,24kf2_1,24kf1_1")
+ (eq_attr "type" "accmod"))
+ "r24k_iss+(r24k_mul3a|r24k_mul3b|r24k_mul3c)")
+
+
+;; mult/madd->dsp_acc_ext : 4 cycles
+;; mult/madd->dsp_acc_mod : 4 cycles
+(define_bypass 4 "r24k_int_mult" "r24k_dsp_acc_ext")
+(define_bypass 4 "r24k_int_mult" "r24k_dsp_acc_mod")
+
+;; mthilo->dsp_acc_ext : 4 cycles
+;; mthilo->dsp_acc_ext : 4 cycles
+(define_bypass 4 "r24k_int_mthilo" "r24k_dsp_acc_ext")
+(define_bypass 4 "r24k_int_mthilo" "r24k_dsp_acc_mod")
+
+;; dsp_mac->next use : 1 cycles (default)
+;; dsp_mac->dsp_acc_ext : 4 cycles
+;; dsp_mac->dsp_acc_mod : 4 cycles
+(define_bypass 4 "r24k_dsp_mac" "r24k_dsp_acc_ext")
+(define_bypass 4 "r24k_dsp_mac" "r24k_dsp_acc_mod")
+
+;; dsp_mac_sat->next use : 1 cycles (default)
+;; dsp_mac_sat->mult/madd : 2 cycles
+;; dsp_mac_sat->dsp_mac : 2 cycles
+;; dsp_mac_sat->dsp_mac_sat : 2 cycles
+;; dsp_mac_sat->dsp_acc_ext : 4 cycles
+;; dsp_mac_sat->dsp_acc_mod : 4 cycles
+(define_bypass 2 "r24k_dsp_mac_sat" "r24k_int_mult")
+(define_bypass 2 "r24k_dsp_mac_sat" "r24k_dsp_mac")
+(define_bypass 2 "r24k_dsp_mac_sat" "r24k_dsp_mac_sat")
+(define_bypass 4 "r24k_dsp_mac_sat" "r24k_dsp_acc_ext")
+(define_bypass 4 "r24k_dsp_mac_sat" "r24k_dsp_acc_mod")
+
+;; dsp_acc_ext->next use : 5 cycles (default)
+;; dsp_acc_ext->l/s base : 6 cycles
+;; dsp_acc_ext->prefetch : 6 cycles
+(define_bypass 6 "r24k_dsp_acc_ext" "r24k_int_load")
+(define_bypass 6 "r24k_dsp_acc_ext" "r24k_int_store"
+ "!mips_store_data_bypass_p")
+(define_bypass 6 "r24k_dsp_acc_ext" "r24k_int_prefetch")
+
+;; dsp_acc_mod->next use : 1 cycles (default)
+;; dsp_acc_mod->mult/madd : 2 cycles
+;; dsp_acc_mod->dsp_mac : 2 cycles
+;; dsp_acc_mod->dsp_mac_sat : 2 cycles
+;; dsp_acc_mod->dsp_acc_ext : 4 cycles
+;; dsp_acc_mod->dsp_acc_mod : 4 cycles
+(define_bypass 2 "r24k_dsp_acc_mod" "r24k_int_mult")
+(define_bypass 2 "r24k_dsp_acc_mod" "r24k_dsp_mac")
+(define_bypass 2 "r24k_dsp_acc_mod" "r24k_dsp_mac_sat")
+(define_bypass 4 "r24k_dsp_acc_mod" "r24k_dsp_acc_ext")
+(define_bypass 4 "r24k_dsp_acc_mod" "r24k_dsp_acc_mod")
+
+;; dspalu->next use : 2 cycles (default)
+;; dspalu->l/s base : 3 cycles
+;; dspalu->prefetch : 3 cycles
+;; some pairs of dspalu (addsc/addwc, cmp/pick, wrdsp/insv) : 1 cycle
+(define_bypass 3 "r24k_dsp_alu" "r24k_int_load")
+(define_bypass 3 "r24k_dsp_alu" "r24k_int_store" "!mips_store_data_bypass_p")
+(define_bypass 3 "r24k_dsp_alu" "r24k_int_prefetch")
+(define_bypass 1 "r24k_dsp_alu" "r24k_dsp_alu" "mips_dspalu_bypass_p")
+
+
+;; --------------------------------------------------------------
;; Floating Point Instructions
;; --------------------------------------------------------------
@@ -330,13 +416,14 @@
;; r24kf2_1_fcvt_f2i->l/s base : 11 cycles
;; r24kf2_1_fcvt_f2i->prefetch : 11 cycles
(define_bypass 11 "r24kf2_1_fcvt_f2i" "r24k_int_load")
-(define_bypass 11 "r24kf2_1_fcvt_f2i" "r24k_int_store" "!store_data_bypass_p")
+(define_bypass 11 "r24kf2_1_fcvt_f2i" "r24k_int_store"
+ "!mips_store_data_bypass_p")
(define_bypass 11 "r24kf2_1_fcvt_f2i" "r24k_int_prefetch")
;; r24kf2_1_fxfer->l/s base : 5 cycles
;; r24kf2_1_fxfer->prefetch : 5 cycles
(define_bypass 5 "r24kf2_1_fxfer" "r24k_int_load")
-(define_bypass 5 "r24kf2_1_fxfer" "r24k_int_store" "!store_data_bypass_p")
+(define_bypass 5 "r24kf2_1_fxfer" "r24k_int_store" "!mips_store_data_bypass_p")
(define_bypass 5 "r24kf2_1_fxfer" "r24k_int_prefetch")
;; --------------------------------------------------------------
@@ -446,12 +533,13 @@
;; r24kf1_1_fcvt_f2i->l/s base : 6 cycles
;; r24kf1_1_fcvt_f2i->prefetch : 6 cycles
(define_bypass 6 "r24kf1_1_fcvt_f2i" "r24k_int_load")
-(define_bypass 6 "r24kf1_1_fcvt_f2i" "r24k_int_store" "!store_data_bypass_p")
+(define_bypass 6 "r24kf1_1_fcvt_f2i" "r24k_int_store"
+ "!mips_store_data_bypass_p")
(define_bypass 6 "r24kf1_1_fcvt_f2i" "r24k_int_prefetch")
;; r24kf1_1_fxfer->l/s base : 3 cycles
;; r24kf1_1_fxfer->prefetch : 3 cycles
(define_bypass 3 "r24kf1_1_fxfer" "r24k_int_load")
-(define_bypass 3 "r24kf1_1_fxfer" "r24k_int_store" "!store_data_bypass_p")
+(define_bypass 3 "r24kf1_1_fxfer" "r24k_int_store" "!mips_store_data_bypass_p")
(define_bypass 3 "r24kf1_1_fxfer" "r24k_int_prefetch")
diff --git a/gcc/config/mips/3000.md b/gcc/config/mips/3000.md
index 64bdfe113c..2d42503851 100644
--- a/gcc/config/mips/3000.md
+++ b/gcc/config/mips/3000.md
@@ -1,5 +1,5 @@
;; R3000 and TX39 pipeline description.
-;; Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
diff --git a/gcc/config/mips/4000.md b/gcc/config/mips/4000.md
index e6e23289fd..1851d831b6 100644
--- a/gcc/config/mips/4000.md
+++ b/gcc/config/mips/4000.md
@@ -1,5 +1,5 @@
;; R4000 pipeline description.
-;; Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
diff --git a/gcc/config/mips/4100.md b/gcc/config/mips/4100.md
index dc36384c9e..c816ef086b 100644
--- a/gcc/config/mips/4100.md
+++ b/gcc/config/mips/4100.md
@@ -1,5 +1,5 @@
;; VR4100 and VR4120 pipeline description.
-;; Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
diff --git a/gcc/config/mips/4130.md b/gcc/config/mips/4130.md
index 6de814fc7c..14197acf5b 100644
--- a/gcc/config/mips/4130.md
+++ b/gcc/config/mips/4130.md
@@ -1,4 +1,4 @@
-;; Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
@@ -72,13 +72,13 @@
(cond [(eq_attr "type" "load,store")
(const_string "mem")
- (eq_attr "type" "mfhilo,mthilo,imul,imul3,imadd,idiv")
+ (eq_attr "type" "mfhi,mflo,mthi,mtlo,imul,imul3,imadd,idiv")
(const_string "mul")]
(const_string "alu")))
(define_insn_reservation "vr4130_multi" 1
(and (eq_attr "cpu" "r4130")
- (eq_attr "type" "multi,unknown"))
+ (eq_attr "type" "multi,unknown,atomic,syncloop"))
"vr4130_alu1 + vr4130_alu2 + vr4130_dcache + vr4130_muldiv")
(define_insn_reservation "vr4130_int" 1
@@ -98,12 +98,12 @@
(define_insn_reservation "vr4130_mfhilo" 3
(and (eq_attr "cpu" "r4130")
- (eq_attr "type" "mfhilo"))
+ (eq_attr "type" "mfhi,mflo"))
"vr4130_muldiv")
(define_insn_reservation "vr4130_mthilo" 1
(and (eq_attr "cpu" "r4130")
- (eq_attr "type" "mthilo"))
+ (eq_attr "type" "mthi,mtlo"))
"vr4130_muldiv")
;; The product is available in LO & HI after one cycle. Moving the result
diff --git a/gcc/config/mips/4300.md b/gcc/config/mips/4300.md
index b55180b0c1..04a25c360f 100644
--- a/gcc/config/mips/4300.md
+++ b/gcc/config/mips/4300.md
@@ -1,5 +1,5 @@
;; VR4300 pipeline description.
-;; Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
diff --git a/gcc/config/mips/4600.md b/gcc/config/mips/4600.md
index c645cbc5d8..29ec0eacd4 100644
--- a/gcc/config/mips/4600.md
+++ b/gcc/config/mips/4600.md
@@ -1,5 +1,5 @@
-;; R4600 and R4650 pipeline description.
-;; Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
+;; R4600, R4650, and R4700 pipeline description.
+;; Copyright (C) 2004-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
@@ -21,19 +21,35 @@
;; This file overrides parts of generic.md. It is derived from the
;; old define_function_unit description.
;;
-;; We handle the R4600 and R4650 in much the same way. The only difference
-;; is in the integer multiplication and division costs.
+;; We handle the R4600, R4650, and R4700 in much the same way. The only
+;; differences between R4600 and R4650 are the integer multiplication and
+;; division costs. The only differences between R4600 and R4700 are the
+;; integer and floating-point multiplication costs.
-(define_insn_reservation "r4600_imul" 10
+(define_insn_reservation "r4600_imul_si" 10
(and (eq_attr "cpu" "r4600")
- (eq_attr "type" "imul,imul3,imadd"))
+ (eq_attr "type" "imul,imul3,imadd")
+ (eq_attr "mode" "SI"))
"imuldiv*10")
-(define_insn_reservation "r4600_idiv" 42
+(define_insn_reservation "r4600_imul_di" 12
(and (eq_attr "cpu" "r4600")
- (eq_attr "type" "idiv"))
+ (eq_attr "type" "imul,imul3,imadd")
+ (eq_attr "mode" "DI"))
+ "imuldiv*12")
+
+(define_insn_reservation "r4600_idiv_si" 42
+ (and (eq_attr "cpu" "r4600,r4700")
+ (eq_attr "type" "idiv")
+ (eq_attr "mode" "SI"))
"imuldiv*42")
+(define_insn_reservation "r4600_idiv_di" 74
+ (and (eq_attr "cpu" "r4600,r4700")
+ (eq_attr "type" "idiv")
+ (eq_attr "mode" "DI"))
+ "imuldiv*74")
+
(define_insn_reservation "r4650_imul" 4
(and (eq_attr "cpu" "r4650")
@@ -46,13 +62,26 @@
"imuldiv*36")
+(define_insn_reservation "r4700_imul_si" 8
+ (and (eq_attr "cpu" "r4700")
+ (eq_attr "type" "imul,imul3,imadd")
+ (eq_attr "mode" "SI"))
+ "imuldiv*8")
+
+(define_insn_reservation "r4700_imul_di" 10
+ (and (eq_attr "cpu" "r4700")
+ (eq_attr "type" "imul,imul3,imadd")
+ (eq_attr "mode" "DI"))
+ "imuldiv*10")
+
+
(define_insn_reservation "r4600_load" 2
- (and (eq_attr "cpu" "r4600,r4650")
+ (and (eq_attr "cpu" "r4600,r4650,r4700")
(eq_attr "type" "load,fpload,fpidxload"))
"alu")
(define_insn_reservation "r4600_fmove" 1
- (and (eq_attr "cpu" "r4600,r4650")
+ (and (eq_attr "cpu" "r4600,r4650,r4700")
(eq_attr "type" "fabs,fneg,fmove"))
"alu")
@@ -62,26 +91,40 @@
(eq_attr "mode" "SF")))
"alu")
+
+(define_insn_reservation "r4700_fmul_single" 4
+ (and (eq_attr "cpu" "r4700")
+ (and (eq_attr "type" "fmul,fmadd")
+ (eq_attr "mode" "SF")))
+ "alu")
+
+(define_insn_reservation "r4700_fmul_double" 5
+ (and (eq_attr "cpu" "r4700")
+ (and (eq_attr "type" "fmul,fmadd")
+ (eq_attr "mode" "DF")))
+ "alu")
+
+
(define_insn_reservation "r4600_fdiv_single" 32
- (and (eq_attr "cpu" "r4600,r4650")
+ (and (eq_attr "cpu" "r4600,r4650,r4700")
(and (eq_attr "type" "fdiv,frdiv")
(eq_attr "mode" "SF")))
"alu")
(define_insn_reservation "r4600_fdiv_double" 61
- (and (eq_attr "cpu" "r4600,r4650")
+ (and (eq_attr "cpu" "r4600,r4650,r4700")
(and (eq_attr "type" "fdiv,frdiv")
(eq_attr "mode" "DF")))
"alu")
(define_insn_reservation "r4600_fsqrt_single" 31
- (and (eq_attr "cpu" "r4600,r4650")
+ (and (eq_attr "cpu" "r4600,r4650,r4700")
(and (eq_attr "type" "fsqrt,frsqrt")
(eq_attr "mode" "SF")))
"alu")
(define_insn_reservation "r4600_fsqrt_double" 60
- (and (eq_attr "cpu" "r4600,r4650")
+ (and (eq_attr "cpu" "r4600,r4650,r4700")
(and (eq_attr "type" "fsqrt,frsqrt")
(eq_attr "mode" "DF")))
"alu")
diff --git a/gcc/config/mips/4k.md b/gcc/config/mips/4k.md
index 88cdbd195a..9d4304b180 100644
--- a/gcc/config/mips/4k.md
+++ b/gcc/config/mips/4k.md
@@ -10,7 +10,7 @@
;; 4km - pipelined multiplier and block address translator (BAT)
;; 4kp - non-pipelined multiplier and block address translator (BAT)
;;
-;; Copyright (C) 2005, 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
@@ -114,13 +114,13 @@
;; Move to HI/LO -> MADD/MSUB,MFHI/MFLO has a 1 cycle latency.
(define_insn_reservation "r4k_int_mthilo" 1
(and (eq_attr "cpu" "4kc,4kp")
- (eq_attr "type" "mthilo"))
+ (eq_attr "type" "mthi,mtlo"))
"r4k_ixu_arith+r4k_ixu_mpydiv")
;; Move from HI/LO -> integer operation has a 2 cycle latency.
(define_insn_reservation "r4k_int_mfhilo" 2
(and (eq_attr "cpu" "4kc,4kp")
- (eq_attr "type" "mfhilo"))
+ (eq_attr "type" "mfhi,mflo"))
"r4k_ixu_arith+r4k_ixu_mpydiv")
;; All other integer insns.
@@ -149,5 +149,5 @@
;; Unknown or multi - single issue
(define_insn_reservation "r4k_unknown" 1
(and (eq_attr "cpu" "4kc,4kp")
- (eq_attr "type" "unknown,multi"))
+ (eq_attr "type" "unknown,multi,atomic,syncloop"))
"r4k_ixu_arith+r4k_ixu_mpydiv")
diff --git a/gcc/config/mips/5000.md b/gcc/config/mips/5000.md
index 0ad12ba7e4..611749620f 100644
--- a/gcc/config/mips/5000.md
+++ b/gcc/config/mips/5000.md
@@ -1,5 +1,5 @@
;; VR5000 pipeline description.
-;; Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
diff --git a/gcc/config/mips/5400.md b/gcc/config/mips/5400.md
index 362999d7b5..f54bacef2e 100644
--- a/gcc/config/mips/5400.md
+++ b/gcc/config/mips/5400.md
@@ -1,4 +1,4 @@
-;; Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
@@ -33,7 +33,7 @@
(define_insn_reservation "ir_vr54_unknown" 1
(and (eq_attr "cpu" "r5400")
- (eq_attr "type" "unknown"))
+ (eq_attr "type" "unknown,atomic,syncloop"))
"vr54_dp0+vr54_dp1+vr54_mem+vr54_mac")
;; Assume prediction fails.
@@ -73,7 +73,7 @@
(define_insn_reservation "ir_vr54_hilo" 1
(and (eq_attr "cpu" "r5400")
- (eq_attr "type" "mthilo,mfhilo"))
+ (eq_attr "type" "mthi,mtlo,mfhi,mflo"))
"vr54_dp0|vr54_dp1")
(define_insn_reservation "ir_vr54_arith" 1
diff --git a/gcc/config/mips/5500.md b/gcc/config/mips/5500.md
index 0b59af15d1..23cab21a50 100644
--- a/gcc/config/mips/5500.md
+++ b/gcc/config/mips/5500.md
@@ -1,4 +1,4 @@
-;; Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
@@ -35,7 +35,7 @@
(define_insn_reservation "ir_vr55_unknown" 1
(and (eq_attr "cpu" "r5500")
- (eq_attr "type" "unknown"))
+ (eq_attr "type" "unknown,atomic,syncloop"))
"vr55_dp0+vr55_dp1+vr55_mem+vr55_mac+vr55_fp+vr55_bru")
;; Assume prediction fails.
@@ -84,12 +84,12 @@
(define_insn_reservation "ir_vr55_mthilo" 1
(and (eq_attr "cpu" "r5500")
- (eq_attr "type" "mthilo"))
+ (eq_attr "type" "mthi,mtlo"))
"vr55_mac")
(define_insn_reservation "ir_vr55_mfhilo" 5
(and (eq_attr "cpu" "r5500")
- (eq_attr "type" "mfhilo"))
+ (eq_attr "type" "mfhi,mflo"))
"vr55_mac")
;; The default latency is for the GPR result of a mul. Bypasses handle the
diff --git a/gcc/config/mips/5k.md b/gcc/config/mips/5k.md
index ade06ec448..397c74c93a 100644
--- a/gcc/config/mips/5k.md
+++ b/gcc/config/mips/5k.md
@@ -10,7 +10,7 @@
;; 5kf - Separate floating point pipe which can dual-issue with the
;; integer pipe.
;;
-;; Copyright (C) 2005, 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
@@ -88,13 +88,13 @@
;; Move to HI/LO -> MADD/MSUB,MFHI/MFLO has a 1 cycle latency.
(define_insn_reservation "r5k_int_mthilo" 1
(and (eq_attr "cpu" "5kc,5kf")
- (eq_attr "type" "mthilo"))
+ (eq_attr "type" "mthi,mtlo"))
"r5k_ixu_arith+r5k_ixu_mpydiv")
;; Move from HI/LO -> integer operation has a 2 cycle latency.
(define_insn_reservation "r5k_int_mfhilo" 2
(and (eq_attr "cpu" "5kc,5kf")
- (eq_attr "type" "mfhilo"))
+ (eq_attr "type" "mfhi,mflo"))
"r5k_ixu_arith+r5k_ixu_mpydiv")
;; All other integer insns.
@@ -127,7 +127,7 @@
;; Unknown or multi - single issue
(define_insn_reservation "r5k_int_unknown" 1
(and (eq_attr "cpu" "5kc,5kf")
- (eq_attr "type" "unknown,multi"))
+ (eq_attr "type" "unknown,multi,atomic,syncloop"))
"r5k_ixu_arith+r5k_ixu_mpydiv")
diff --git a/gcc/config/mips/6000.md b/gcc/config/mips/6000.md
index 51730fb089..32bc31601a 100644
--- a/gcc/config/mips/6000.md
+++ b/gcc/config/mips/6000.md
@@ -1,5 +1,5 @@
;; R6000 pipeline description.
-;; Copyright (C) 2004, 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
diff --git a/gcc/config/mips/7000.md b/gcc/config/mips/7000.md
index 6c91d0472d..6f020c58ad 100644
--- a/gcc/config/mips/7000.md
+++ b/gcc/config/mips/7000.md
@@ -1,5 +1,5 @@
;; DFA-based pipeline description for the RM7000.
-;; Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
@@ -134,12 +134,12 @@
;; Move to/from HI/LO.
(define_insn_reservation "rm7_mthilo" 3
(and (eq_attr "cpu" "r7000")
- (eq_attr "type" "mthilo"))
+ (eq_attr "type" "mthi,mtlo"))
"rm7_impydiv")
(define_insn_reservation "rm7_mfhilo" 1
(and (eq_attr "cpu" "r7000")
- (eq_attr "type" "mfhilo"))
+ (eq_attr "type" "mfhi,mflo"))
"rm7_impydiv")
;; Move to/from fp coprocessor.
@@ -210,5 +210,5 @@
;; Force single-dispatch for unknown or multi.
(define_insn_reservation "rm7_unknown" 1
(and (eq_attr "cpu" "r7000")
- (eq_attr "type" "unknown,multi"))
+ (eq_attr "type" "unknown,multi,atomic,syncloop"))
"rm7_single_dispatch")
diff --git a/gcc/config/mips/74k.md b/gcc/config/mips/74k.md
index b75bfc4b91..e07c190dbf 100644
--- a/gcc/config/mips/74k.md
+++ b/gcc/config/mips/74k.md
@@ -5,7 +5,7 @@
;; "MIPS32 74K Microarchitecure Specification Rev. 01.02 Jun 15, 2006"
;; "MIPS32 74Kf Processor Core Datasheet Jun 2, 2006"
;;
-;; Copyright (C) 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
@@ -80,13 +80,13 @@
;; mfhi, mflo, mflhxu - deliver result to gpr in 7 cycles
(define_insn_reservation "r74k_int_mfhilo" 7
(and (eq_attr "cpu" "74kc,74kf2_1,74kf1_1,74kf3_2")
- (eq_attr "type" "mfhilo"))
+ (eq_attr "type" "mfhi,mflo"))
"r74k_alu+r74k_mul")
;; mthi, mtlo, mtlhx - deliver result to hi/lo, thence madd, handled as bypass
(define_insn_reservation "r74k_int_mthilo" 7
(and (eq_attr "cpu" "74kc,74kf2_1,74kf1_1,74kf3_2")
- (eq_attr "type" "mthilo"))
+ (eq_attr "type" "mthi,mtlo"))
"r74k_alu+r74k_mul")
;; div - default to 50 cycles for 32bit operands. Faster for 8 bit,
@@ -118,8 +118,7 @@
;; stores
(define_insn_reservation "r74k_int_store" 1
(and (eq_attr "cpu" "74kc,74kf2_1,74kf1_1,74kf3_2")
- (and (eq_attr "type" "store")
- (eq_attr "mode" "!unknown")))
+ (eq_attr "type" "store"))
"r74k_agen")
@@ -129,7 +128,7 @@
;;
(define_insn_reservation "r74k_unknown" 1
(and (eq_attr "cpu" "74kc,74kf2_1,74kf1_1,74kf3_2")
- (eq_attr "type" "unknown"))
+ (eq_attr "type" "unknown,atomic,syncloop"))
"r74k_alu")
(define_insn_reservation "r74k_multi" 10
@@ -145,25 +144,27 @@
;; load->load base: 4 cycles
;; load->store base: 4 cycles
(define_bypass 4 "r74k_int_load" "r74k_int_load")
-(define_bypass 4 "r74k_int_load" "r74k_int_store" "!store_data_bypass_p")
+(define_bypass 4 "r74k_int_load" "r74k_int_store" "!mips_store_data_bypass_p")
;; logical/move/slt/signext->next use : 1 cycles (Default)
;; logical/move/slt/signext->load base: 2 cycles
;; logical/move/slt/signext->store base: 2 cycles
(define_bypass 2 "r74k_int_logical" "r74k_int_load")
-(define_bypass 2 "r74k_int_logical" "r74k_int_store" "!store_data_bypass_p")
+(define_bypass 2 "r74k_int_logical" "r74k_int_store"
+ "!mips_store_data_bypass_p")
;; arith->next use : 2 cycles (Default)
;; arith->load base: 3 cycles
;; arith->store base: 3 cycles
(define_bypass 3 "r74k_int_arith" "r74k_int_load")
-(define_bypass 3 "r74k_int_arith" "r74k_int_store" "!store_data_bypass_p")
+(define_bypass 3 "r74k_int_arith" "r74k_int_store" "!mips_store_data_bypass_p")
;; cmove->next use : 4 cycles (Default)
;; cmove->load base: 5 cycles
;; cmove->store base: 5 cycles
(define_bypass 5 "r74k_int_cmove" "r74k_int_load")
-(define_bypass 5 "r74k_int_cmove" "r74k_int_store" "!store_data_bypass_p")
+(define_bypass 5 "r74k_int_cmove" "r74k_int_store"
+ "!mips_store_data_bypass_p")
;; mult/madd/msub->int_mfhilo : 4 cycles (default)
;; mult->madd/msub : 1 cycles
@@ -173,6 +174,88 @@
(define_bypass 1 "r74k_int_madd" "r74k_int_madd"
"mips_linked_madd_p")
+
+;; --------------------------------------------------------------
+;; DSP instructions
+;; --------------------------------------------------------------
+
+;; Non-saturating insn have the same latency as normal ALU operations,
+(define_insn_reservation "r74k_dsp_alu" 2
+ (and (eq_attr "cpu" "74kc,74kf2_1,74kf1_1,74kf3_2")
+ (eq_attr "type" "dspalu"))
+ "r74k_alu")
+
+;; Saturating insn takes an extra cycle.
+(define_insn_reservation "r74k_dsp_alu_sat" 3
+ (and (eq_attr "cpu" "74kc,74kf2_1,74kf1_1,74kf3_2")
+ (eq_attr "type" "dspalusat"))
+ "r74k_alu")
+
+;; dpaq_s, dpau, dpsq_s, dpsu, maq_s, mulsaq
+;; - delivers result to hi/lo in 6 cycle (bypass at M4)
+(define_insn_reservation "r74k_dsp_mac" 6
+ (and (eq_attr "cpu" "74kc,74kf2_1,74kf1_1,74kf3_2")
+ (eq_attr "type" "dspmac"))
+ "r74k_alu+r74k_mul")
+
+;; dpaq_sa, dpsq_sa, maq_sa
+;; - delivers result to hi/lo in 7 cycle (bypass at WB)
+(define_insn_reservation "r74k_dsp_mac_sat" 7
+ (and (eq_attr "cpu" "74kc,74kf2_1,74kf1_1,74kf3_2")
+ (eq_attr "type" "dspmacsat"))
+ "r74k_alu+r74k_mul")
+
+;; extp, extpdp, extpdpv, extpv, extr, extrv
+;; - same latency as "mul"
+(define_insn_reservation "r74k_dsp_acc_ext" 7
+ (and (eq_attr "cpu" "74kc,74kf2_1,74kf1_1,74kf3_2")
+ (eq_attr "type" "accext"))
+ "r74k_alu+r74k_mul")
+
+;; mthlip, shilo, shilov
+;; - same latency as "mul"
+(define_insn_reservation "r74k_dsp_acc_mod" 7
+ (and (eq_attr "cpu" "74kc,74kf2_1,74kf1_1,74kf3_2")
+ (eq_attr "type" "accmod"))
+ "r74k_alu+r74k_mul")
+
+;; dspalu ->load/store base
+;; dspalusat->load/store base
+;; - we should never see these in real life.
+
+;; dsp_mac->dsp_mac : 1 cycles (repeat rate of 1)
+;; dsp_mac->dsp_mac_sat : 1 cycles (repeat rate of 1)
+(define_bypass 1 "r74k_dsp_mac" "r74k_dsp_mac")
+(define_bypass 1 "r74k_dsp_mac" "r74k_dsp_mac_sat")
+
+;; dsp_mac_sat->dsp_mac_sat : 2 cycles (repeat rate of 2)
+;; dsp_mac_sat->dsp_mac : 2 cycles (repeat rate of 2)
+(define_bypass 2 "r74k_dsp_mac_sat" "r74k_dsp_mac_sat")
+(define_bypass 2 "r74k_dsp_mac_sat" "r74k_dsp_mac")
+
+(define_bypass 1 "r74k_int_mult" "r74k_dsp_mac")
+(define_bypass 1 "r74k_int_mult" "r74k_dsp_mac_sat")
+
+(define_bypass 1 "r74k_int_mul3" "r74k_dsp_mac" "mips_linked_madd_p")
+(define_bypass 1 "r74k_int_mul3" "r74k_dsp_mac_sat" "mips_linked_madd_p")
+
+;; Assuming the following is true (bypass at M4)
+;; AP AF AM MB M1 M2 M3 M4 WB GR GC
+;; AP AF AM MB M1 M2 M3 M4 WB GR GC
+;; dsp_mac->dsp_acc_ext : 4 cycles
+;; dsp_mac->dsp_acc_mod : 4 cycles
+(define_bypass 4 "r74k_dsp_mac" "r74k_dsp_acc_ext")
+(define_bypass 4 "r74k_dsp_mac" "r74k_dsp_acc_mod")
+
+;; Assuming the following is true (bypass at WB)
+;; AP AF AM MB M1 M2 M3 M4 WB GR GC
+;; AP AF AM MB M1 M2 M3 M4 WB GR GC
+;; dsp_mac_sat->dsp_acc_ext : 5 cycles
+;; dsp_mac_sat->dsp_acc_mod : 5 cycles
+(define_bypass 5 "r74k_dsp_mac_sat" "r74k_dsp_acc_ext")
+(define_bypass 5 "r74k_dsp_mac_sat" "r74k_dsp_acc_mod")
+
+
;; --------------------------------------------------------------
;; Floating Point Instructions
;; --------------------------------------------------------------
diff --git a/gcc/config/mips/9000.md b/gcc/config/mips/9000.md
index c0c8d3ac82..efc646f5a3 100644
--- a/gcc/config/mips/9000.md
+++ b/gcc/config/mips/9000.md
@@ -1,5 +1,5 @@
;; DFA-based pipeline description for the RM9000.
-;; Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
@@ -87,12 +87,12 @@
(define_insn_reservation "rm9k_mfhilo" 1
(and (eq_attr "cpu" "r9000")
- (eq_attr "type" "mfhilo"))
+ (eq_attr "type" "mfhi,mflo"))
"rm9k_f_int")
(define_insn_reservation "rm9k_mthilo" 5
(and (eq_attr "cpu" "r9000")
- (eq_attr "type" "mthilo"))
+ (eq_attr "type" "mthi,mtlo"))
"rm9k_f_int")
(define_insn_reservation "rm9k_xfer" 2
@@ -147,5 +147,5 @@
(define_insn_reservation "rm9k_unknown" 1
(and (eq_attr "cpu" "r9000")
- (eq_attr "type" "unknown,multi"))
+ (eq_attr "type" "unknown,multi,atomic,syncloop"))
"rm9k_m + rm9k_f_int + rm9k_any1 + rm9k_any2")
diff --git a/gcc/config/mips/constraints.md b/gcc/config/mips/constraints.md
index 2bfb2aaf2c..49e48954f5 100644
--- a/gcc/config/mips/constraints.md
+++ b/gcc/config/mips/constraints.md
@@ -1,5 +1,5 @@
;; Constraint definitions for MIPS.
-;; Copyright (C) 2006, 2007, 2008, 2010 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
@@ -43,6 +43,9 @@
(define_register_constraint "b" "ALL_REGS"
"@internal")
+(define_register_constraint "u" "M16_REGS"
+ "@internal")
+
;; MIPS16 code always calls through a MIPS16 register; see mips_emit_call_insn
;; for details.
(define_register_constraint "c" "TARGET_MIPS16 ? M16_REGS
@@ -170,21 +173,75 @@
(and (match_operand 0 "call_insn_operand")
(match_test "CONSTANT_P (op)")))
-(define_constraint "T"
+(define_constraint "Udb7"
"@internal
- A constant @code{move_operand} that cannot be safely loaded into @code{$25}
- using @code{la}."
- (and (match_operand 0 "move_operand")
- (match_test "CONSTANT_P (op)")
- (match_test "mips_dangerous_for_la25_p (op)")))
+ A decremented unsigned constant of 7 bits."
+ (match_operand 0 "db7_operand"))
-(define_constraint "U"
+(define_constraint "Udb8"
"@internal
- A constant @code{move_operand} that can be safely loaded into @code{$25}
- using @code{la}."
- (and (match_operand 0 "move_operand")
- (match_test "CONSTANT_P (op)")
- (not (match_test "mips_dangerous_for_la25_p (op)"))))
+ A decremented unsigned constant of 8 bits."
+ (match_operand 0 "db8_operand"))
+
+(define_constraint "Uead"
+ "@internal
+ A microMIPS encoded ADDIUR2 immediate operand."
+ (match_operand 0 "addiur2_operand"))
+
+(define_constraint "Uean"
+ "@internal
+ A microMIPS encoded ANDI operand."
+ (match_operand 0 "andi16_operand"))
+
+(define_constraint "Uesp"
+ "@internal
+ A microMIPS encoded ADDIUSP operand."
+ (match_operand 0 "addiusp_operand"))
+
+(define_constraint "Uib3"
+ "@internal
+ An unsigned, incremented constant of 3 bits."
+ (match_operand 0 "ib3_operand"))
+
+(define_constraint "Usb4"
+ "@internal
+ A signed constant of 4 bits."
+ (match_operand 0 "sb4_operand"))
+
+(define_constraint "Usb5"
+ "@internal
+ A signed constant of 5 bits."
+ (match_operand 0 "sb5_operand"))
+
+(define_constraint "Usb8"
+ "@internal
+ A signed constant of 8 bits."
+ (match_operand 0 "sb8_operand"))
+
+(define_constraint "Usd8"
+ "@internal
+ A signed constant of 8 bits, shifted left three places."
+ (match_operand 0 "sd8_operand"))
+
+(define_constraint "Uub8"
+ "@internal
+ An unsigned constant of 8 bits."
+ (match_operand 0 "ub8_operand"))
+
+(define_constraint "Uuw5"
+ "@internal
+ An unsigned constant of 5 bits, shifted left two places."
+ (match_operand 0 "uw5_operand"))
+
+(define_constraint "Uuw6"
+ "@internal
+ An unsigned constant of 6 bits, shifted left two places."
+ (match_operand 0 "uw6_operand"))
+
+(define_constraint "Uuw8"
+ "@internal
+ An unsigned constant of 8 bits, shifted left two places."
+ (match_operand 0 "uw8_operand"))
(define_memory_constraint "W"
"@internal
@@ -220,6 +277,22 @@
"@internal"
(match_operand 0 "qi_mask_operand"))
+(define_constraint "Yd"
+ "@internal
+ A constant @code{move_operand} that can be safely loaded into @code{$25}
+ using @code{la}."
+ (and (match_operand 0 "move_operand")
+ (match_test "CONSTANT_P (op)")
+ (not (match_test "mips_dangerous_for_la25_p (op)"))))
+
+(define_constraint "Yf"
+ "@internal
+ A constant @code{move_operand} that cannot be safely loaded into @code{$25}
+ using @code{la}."
+ (and (match_operand 0 "move_operand")
+ (match_test "CONSTANT_P (op)")
+ (match_test "mips_dangerous_for_la25_p (op)")))
+
(define_constraint "Yh"
"@internal"
(match_operand 0 "hi_mask_operand"))
@@ -231,3 +304,60 @@
(define_constraint "Yx"
"@internal"
(match_operand 0 "low_bitmask_operand"))
+
+(define_memory_constraint "ZC"
+ "When compiling microMIPS code, this constraint matches a memory operand
+ whose address is formed from a base register and a 12-bit offset. These
+ operands can be used for microMIPS instructions such as @code{ll} and
+ @code{sc}. When not compiling for microMIPS code, @code{ZC} is
+ equivalent to @code{R}."
+ (and (match_code "mem")
+ (if_then_else
+ (match_test "TARGET_MICROMIPS")
+ (match_test "umips_12bit_offset_address_p (XEXP (op, 0), mode)")
+ (match_test "mips_address_insns (XEXP (op, 0), mode, false)"))))
+
+(define_address_constraint "ZD"
+ "When compiling microMIPS code, this constraint matches an address operand
+ that is formed from a base register and a 12-bit offset. These operands
+ can be used for microMIPS instructions such as @code{prefetch}. When
+ not compiling for microMIPS code, @code{ZD} is equivalent to @code{p}."
+ (if_then_else (match_test "TARGET_MICROMIPS")
+ (match_test "umips_12bit_offset_address_p (op, mode)")
+ (match_test "mips_address_insns (op, mode, false)")))
+
+(define_memory_constraint "ZR"
+ "@internal
+ An address valid for loading/storing register exclusive"
+ (match_operand 0 "mem_noofs_operand"))
+
+(define_memory_constraint "ZS"
+ "@internal
+ A microMIPS memory operand for use with the LWSP/SWSP insns."
+ (and (match_code "mem")
+ (match_operand 0 "lwsp_swsp_operand")))
+
+(define_memory_constraint "ZT"
+ "@internal
+ A microMIPS memory operand for use with the LW16/SW16 insns."
+ (and (match_code "mem")
+ (match_operand 0 "lw16_sw16_operand")))
+
+(define_memory_constraint "ZU"
+ "@internal
+ A microMIPS memory operand for use with the LHU16/SH16 insns."
+ (and (match_code "mem")
+ (match_operand 0 "lhu16_sh16_operand")))
+
+(define_memory_constraint "ZV"
+ "@internal
+ A microMIPS memory operand for use with the SB16 insn."
+ (and (match_code "mem")
+ (match_operand 0 "sb16_operand")))
+
+(define_memory_constraint "ZW"
+ "@internal
+ A microMIPS memory operand for use with the LBU16 insn."
+ (and (match_code "mem")
+ (match_operand 0 "lbu16_operand")))
+
diff --git a/gcc/config/mips/driver-native.c b/gcc/config/mips/driver-native.c
index f565c572e5..4c2a658c77 100644
--- a/gcc/config/mips/driver-native.c
+++ b/gcc/config/mips/driver-native.c
@@ -1,5 +1,5 @@
/* Subroutines for the gcc driver.
- Copyright (C) 2008, 2011 Free Software Foundation, Inc.
+ Copyright (C) 2008-2014 Free Software Foundation, Inc.
This file is part of GCC.
@@ -22,59 +22,6 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
-#ifdef __sgi__
-#include <invent.h>
-#include <sys/sbd.h>
-
-/* Cf. MIPS R10000 Microprocessor User Guide, Version 2.0, 14.13 Processor
- Revision Identifier (PRId) Register (15).
-
- http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi/hdwr/bks/SGI_Developer/books/R10K_UM/sgi_html/t5.Ver.2.0.book_279.html */
-
-static const struct cpu_types {
- int impl;
- const char *cpu;
-} cpu_types[] = {
- { C0_IMP_R2000, "r2000" },
- { C0_IMP_R3000, "r3000" },
- { C0_IMP_R6000, "r6000" },
- { C0_IMP_R4000, "r4000" },
- { C0_IMP_R6000A, "r6000" },
- { C0_IMP_R10000, "r10000" },
- { C0_IMP_R12000, "r12000" },
- { C0_IMP_R14000, "r14000" },
- { C0_IMP_R8000, "r8000" },
- { C0_IMP_R4600, "r4600" },
- { C0_IMP_R4700, "r4600" },
- { C0_IMP_R4650, "r4650" },
- { C0_IMP_R5000, "vr5000" },
- { C0_IMP_RM7000, "rm7000" },
- { C0_IMP_RM5271, "vr5000" },
- { 0, 0 }
-};
-
-static int
-cputype (inventory_t *inv, void *arg)
-{
- if (inv != NULL
- && inv->inv_class == INV_PROCESSOR
- && inv->inv_type == INV_CPUCHIP)
- {
- int i;
- /* inv_state is the cpu revision number. */
- int impl = (inv->inv_state & C0_IMPMASK) >> C0_IMPSHIFT;
-
- for (i = 0; cpu_types[i].cpu != NULL; i++)
- if (cpu_types[i].impl == impl)
- {
- *((const char **) arg) = cpu_types[i].cpu;
- break;
- }
- }
- return 0;
-}
-#endif
-
/* This will be called by the spec parser in gcc.c when it sees
a %:local_cpu_detect(args) construct. Currently it will be called
with either "arch" or "tune" as argument depending on if -march=native
@@ -92,10 +39,8 @@ const char *
host_detect_local_cpu (int argc, const char **argv)
{
const char *cpu = NULL;
-#ifndef __sgi__
char buf[128];
FILE *f;
-#endif
bool arch;
if (argc < 1)
@@ -105,9 +50,6 @@ host_detect_local_cpu (int argc, const char **argv)
if (!arch && strcmp (argv[0], "tune"))
return NULL;
-#ifdef __sgi__
- scaninvent (cputype, &cpu);
-#else
f = fopen ("/proc/cpuinfo", "r");
if (f == NULL)
return NULL;
@@ -116,11 +58,17 @@ host_detect_local_cpu (int argc, const char **argv)
if (strncmp (buf, "cpu model", sizeof ("cpu model") - 1) == 0)
{
if (strstr (buf, "Godson2 V0.2") != NULL
- || strstr (buf, "Loongson-2 V0.2") != NULL)
+ || strstr (buf, "Loongson-2 V0.2") != NULL
+ || strstr (buf, "Loongson-2E") != NULL)
cpu = "loongson2e";
else if (strstr (buf, "Godson2 V0.3") != NULL
- || strstr (buf, "Loongson-2 V0.3") != NULL)
+ || strstr (buf, "Loongson-2 V0.3") != NULL
+ || strstr (buf, "Loongson-2F") != NULL)
cpu = "loongson2f";
+ else if (strstr (buf, "Godson3 V0.5") != NULL
+ || strstr (buf, "Loongson-3 V0.5") != NULL
+ || strstr (buf, "Loongson-3A") != NULL)
+ cpu = "loongson3a";
else if (strstr (buf, "SiByte SB1") != NULL)
cpu = "sb1";
else if (strstr (buf, "R5000") != NULL)
@@ -133,7 +81,6 @@ host_detect_local_cpu (int argc, const char **argv)
}
fclose (f);
-#endif
if (cpu == NULL)
return NULL;
diff --git a/gcc/config/mips/elf.h b/gcc/config/mips/elf.h
index 572553742f..95f107d5e2 100644
--- a/gcc/config/mips/elf.h
+++ b/gcc/config/mips/elf.h
@@ -1,6 +1,5 @@
/* Target macros for mips*-elf targets.
- Copyright (C) 1994, 1997, 1999, 2000, 2002, 2003, 2004, 2007, 2010
- Free Software Foundation, Inc.
+ Copyright (C) 1994-2014 Free Software Foundation, Inc.
This file is part of GCC.
diff --git a/gcc/config/mips/elfoabi.h b/gcc/config/mips/elfoabi.h
index a3d92bf872..d88a79c0b7 100644
--- a/gcc/config/mips/elfoabi.h
+++ b/gcc/config/mips/elfoabi.h
@@ -1,7 +1,6 @@
/* Target macros for mips*-elf targets that selected between o32 and o64
based on the target architecture.
- Copyright (C) 1994, 1997, 1999, 2000, 2002, 2003, 2004, 2007, 2008
- Free Software Foundation, Inc.
+ Copyright (C) 1994-2014 Free Software Foundation, Inc.
This file is part of GCC.
diff --git a/gcc/config/mips/elforion.h b/gcc/config/mips/elforion.h
index 5560580c27..4ba39af6e6 100644
--- a/gcc/config/mips/elforion.h
+++ b/gcc/config/mips/elforion.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. MIPS ORION version.
- Copyright (C) 1994, 1998, 2007, 2010 Free Software Foundation, Inc.
+ Copyright (C) 1994-2014 Free Software Foundation, Inc.
This file is part of GCC.
diff --git a/gcc/config/mips/generic.md b/gcc/config/mips/generic.md
index d61511f33d..b5e2840e2e 100644
--- a/gcc/config/mips/generic.md
+++ b/gcc/config/mips/generic.md
@@ -1,5 +1,5 @@
;; Generic DFA-based pipeline description for MIPS targets
-;; Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
@@ -43,7 +43,7 @@
"alu")
(define_insn_reservation "generic_hilo" 1
- (eq_attr "type" "mfhilo,mthilo")
+ (eq_attr "type" "mfhi,mflo,mthi,mtlo")
"imuldiv*3")
(define_insn_reservation "generic_imul" 17
@@ -103,3 +103,19 @@
(define_insn_reservation "generic_frecip_fsqrt_step" 5
(eq_attr "type" "frdiv1,frdiv2,frsqrt1,frsqrt2")
"alu")
+
+(define_insn_reservation "generic_atomic" 10
+ (eq_attr "type" "atomic")
+ "alu")
+
+;; Sync loop consists of (in order)
+;; (1) optional sync,
+;; (2) LL instruction,
+;; (3) branch and 1-2 ALU instructions,
+;; (4) SC instruction,
+;; (5) branch and ALU instruction.
+;; The net result of this reservation is a big delay with a flush of
+;; ALU pipeline.
+(define_insn_reservation "generic_sync_loop" 40
+ (eq_attr "type" "syncloop")
+ "alu*39")
diff --git a/gcc/config/mips/genopt.sh b/gcc/config/mips/genopt.sh
index a72ed1c343..457d5bb824 100755
--- a/gcc/config/mips/genopt.sh
+++ b/gcc/config/mips/genopt.sh
@@ -1,6 +1,6 @@
#!/bin/sh
# Generate mips-tables.opt from the list of CPUs in mips-cpus.def.
-# Copyright (C) 2011 Free Software Foundation, Inc.
+# Copyright (C) 2011-2014 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -22,7 +22,7 @@ cat <<EOF
; -*- buffer-read-only: t -*-
; Generated automatically by genopt.sh from mips-cpus.def.
-; Copyright (C) 2011 Free Software Foundation, Inc.
+; Copyright (C) 2011-2014 Free Software Foundation, Inc.
;
; This file is part of GCC.
;
diff --git a/gcc/config/mips/gnu-user.h b/gcc/config/mips/gnu-user.h
index 49c459bc74..638d7f0f5c 100644
--- a/gcc/config/mips/gnu-user.h
+++ b/gcc/config/mips/gnu-user.h
@@ -1,6 +1,5 @@
/* Definitions for MIPS systems using GNU userspace.
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
- 2007, 2008, 2010, 2011 Free Software Foundation, Inc.
+ Copyright (C) 1998-2014 Free Software Foundation, Inc.
This file is part of GCC.
@@ -46,17 +45,16 @@ along with GCC; see the file COPYING3. If not see
CC1_SPEC itself by config/linux.h, but mips.h overrides CC1_SPEC
and provides this hook instead. */
#undef SUBTARGET_CC1_SPEC
-#define SUBTARGET_CC1_SPEC "%{profile:-p}"
+#define SUBTARGET_CC1_SPEC GNU_USER_TARGET_CC1_SPEC
-/* From iris5.h */
/* -G is incompatible with -KPIC which is the default, so only allow objects
in the small data section if the user explicitly asks for it. */
#undef MIPS_DEFAULT_GVALUE
#define MIPS_DEFAULT_GVALUE 0
/* Borrowed from sparc/linux.h */
-#undef LINK_SPEC
-#define LINK_SPEC \
+#undef GNU_USER_TARGET_LINK_SPEC
+#define GNU_USER_TARGET_LINK_SPEC \
"%(endian_spec) \
%{shared:-shared} \
%{!shared: \
@@ -64,6 +62,8 @@ along with GCC; see the file COPYING3. If not see
%{rdynamic:-export-dynamic} \
-dynamic-linker " GNU_USER_DYNAMIC_LINKER "} \
%{static:-static}}"
+#undef LINK_SPEC
+#define LINK_SPEC GNU_USER_TARGET_LINK_SPEC
#undef SUBTARGET_ASM_SPEC
#define SUBTARGET_ASM_SPEC \
@@ -91,16 +91,12 @@ along with GCC; see the file COPYING3. If not see
#undef ASM_OUTPUT_REG_POP
#undef LIB_SPEC
-#define LIB_SPEC "\
-%{pthread:-lpthread} \
-%{shared:-lc} \
-%{!shared: \
- %{profile:-lc_p} %{!profile:-lc}}"
+#define LIB_SPEC GNU_USER_TARGET_LIB_SPEC
#ifdef HAVE_AS_NO_SHARED
/* Default to -mno-shared for non-PIC. */
# define NO_SHARED_SPECS \
- "%{mshared|mno-shared|fpic|fPIC|fpie|fPIE:;:-mno-shared}"
+ " %{mshared|mno-shared|fpic|fPIC|fpie|fPIE:;:-mno-shared}"
#else
# define NO_SHARED_SPECS ""
#endif
@@ -134,7 +130,10 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
LINUX_DRIVER_SELF_SPECS
/* Similar to standard Linux, but adding -ffast-math support. */
+#undef GNU_USER_TARGET_MATHFILE_SPEC
+#define GNU_USER_TARGET_MATHFILE_SPEC \
+ "%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s}"
#undef ENDFILE_SPEC
#define ENDFILE_SPEC \
- "%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s} \
- %{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s"
+ GNU_USER_TARGET_MATHFILE_SPEC " " \
+ GNU_USER_TARGET_ENDFILE_SPEC
diff --git a/gcc/config/mips/gnu-user64.h b/gcc/config/mips/gnu-user64.h
index 91b021d1ca..b97b4a7684 100644
--- a/gcc/config/mips/gnu-user64.h
+++ b/gcc/config/mips/gnu-user64.h
@@ -1,6 +1,5 @@
/* Definitions for MIPS systems using GNU userspace and n32/64 abi.
- Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011
- Free Software Foundation, Inc.
+ Copyright (C) 2002-2014 Free Software Foundation, Inc.
This file is part of GCC.
@@ -20,22 +19,19 @@ along with GCC; see the file COPYING3. If not see
/* Force the default endianness and ABI flags onto the command line
in order to make the other specs easier to write. */
-#undef DRIVER_SELF_SPECS
-#define DRIVER_SELF_SPECS \
- BASE_DRIVER_SELF_SPECS, \
+
+#define LINUX64_DRIVER_SELF_SPECS \
LINUX_DRIVER_SELF_SPECS \
" %{!EB:%{!EL:%(endian_spec)}}" \
" %{!mabi=*: -" MULTILIB_ABI_DEFAULT "}"
-#undef LIB_SPEC
-#define LIB_SPEC "\
-%{pthread:-lpthread} \
-%{shared:-lc} \
-%{!shared: \
- %{profile:-lc_p} %{!profile:-lc}}"
+#undef DRIVER_SELF_SPECS
+#define DRIVER_SELF_SPECS \
+ BASE_DRIVER_SELF_SPECS, \
+ LINUX64_DRIVER_SELF_SPECS
-#undef LINK_SPEC
-#define LINK_SPEC "\
+#undef GNU_USER_TARGET_LINK_SPEC
+#define GNU_USER_TARGET_LINK_SPEC "\
%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} %{mips4} \
%{shared} \
%(endian_spec) \
@@ -49,12 +45,8 @@ along with GCC; see the file COPYING3. If not see
%{mabi=n32:-m" GNU_USER_LINK_EMULATIONN32 "} \
%{mabi=64:-m" GNU_USER_LINK_EMULATION64 "} \
%{mabi=32:-m" GNU_USER_LINK_EMULATION32 "}"
+#undef LINK_SPEC
+#define LINK_SPEC GNU_USER_TARGET_LINK_SPEC
#undef LOCAL_LABEL_PREFIX
#define LOCAL_LABEL_PREFIX (TARGET_OLDABI ? "$" : ".")
-
-/* GNU/Linux doesn't use the same floating-point format that IRIX uses
- for long double. There's no need to override this here, since
- ieee_quad_format is the default, but let's put this here to make
- sure nobody thinks we just forgot to set it to something else. */
-#define MIPS_TFMODE_FORMAT mips_quad_format
diff --git a/gcc/config/mips/iris6.h b/gcc/config/mips/iris6.h
deleted file mode 100644
index 7eb9f55f4f..0000000000
--- a/gcc/config/mips/iris6.h
+++ /dev/null
@@ -1,372 +0,0 @@
-/* Definitions of target machine for GNU compiler. IRIX 6.5 version.
- Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
- Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-/* We are compiling for IRIX 6 now. */
-#undef TARGET_IRIX6
-#define TARGET_IRIX6 1
-
-/* Default to -mabi=n32 and -mips3. */
-#undef MULTILIB_DEFAULTS
-#define MULTILIB_DEFAULTS { "mabi=n32" }
-
-/* -march=native handling only makes sense with compiler running on
- a MIPS chip. */
-#if defined(__mips__)
-extern const char *host_detect_local_cpu (int argc, const char **argv);
-# define EXTRA_SPEC_FUNCTIONS \
- { "local_cpu_detect", host_detect_local_cpu },
-
-# define MARCH_MTUNE_NATIVE_SPECS \
- " %{march=native:%<march=native %:local_cpu_detect(arch)}" \
- " %{mtune=native:%<mtune=native %:local_cpu_detect(tune)}"
-#else
-# define MARCH_MTUNE_NATIVE_SPECS ""
-#endif
-
-/* Force the default ABI onto the command line in order to make the specs
- easier to write. */
-#undef DRIVER_SELF_SPECS
-#define DRIVER_SELF_SPECS \
- "%{!mabi=*: -mabi=n32}", \
- /* Configuration-independent MIPS rules. */ \
- BASE_DRIVER_SELF_SPECS, \
- MARCH_MTUNE_NATIVE_SPECS
-
-/* IRIX 6.5 has the float and long double forms of math functions. */
-#define TARGET_C99_FUNCTIONS 1
-
-/* MIPS specific debugging info */
-#define MIPS_DEBUGGING_INFO 1
-
-/* Force the generation of dwarf .debug_frame sections even if not
- compiling -g. This guarantees that we can unwind the stack. */
-#define DWARF2_FRAME_INFO 1
-
-/* The system unwinder in libexc requires a specific dwarf return address
- column to work. */
-#undef DWARF_FRAME_RETURN_COLUMN
-#define DWARF_FRAME_RETURN_COLUMN (FP_REG_LAST + 1)
-
-/* The size in bytes of a DWARF field indicating an offset or length
- relative to a debug info section, specified to be 4 bytes in the DWARF-2
- specification. The SGI/MIPS ABI defines it to be the same as PTR_SIZE. */
-#define DWARF_OFFSET_SIZE PTR_SIZE
-
-/* The size in bytes of the initial length field in a debug info
- section. The DWARF 3 (draft) specification defines this to be
- either 4 or 12 (with a 4-byte "escape" word when it's 12), but the
- SGI/MIPS ABI predates this standard and defines it to be the same
- as DWARF_OFFSET_SIZE. */
-#define DWARF_INITIAL_LENGTH_SIZE DWARF_OFFSET_SIZE
-
-/* MIPS assemblers don't have the usual .set foo,bar construct;
- .set is used for assembler options instead. */
-#undef SET_ASM_OP
-#define ASM_OUTPUT_DEF(FILE, LABEL1, LABEL2) \
- do \
- { \
- fputc ('\t', FILE); \
- assemble_name (FILE, LABEL1); \
- fputs (" = ", FILE); \
- assemble_name (FILE, LABEL2); \
- fputc ('\n', FILE); \
- } \
- while (0)
-
-#undef LOCAL_LABEL_PREFIX
-#define LOCAL_LABEL_PREFIX "."
-
-#undef ASM_DECLARE_OBJECT_NAME
-#define ASM_DECLARE_OBJECT_NAME mips_declare_object_name
-
-#undef ASM_FINISH_DECLARE_OBJECT
-#define ASM_FINISH_DECLARE_OBJECT mips_finish_declare_object
-
-/* The native IRIX 6 linker does not support merging without a special
- elspec(5) file. */
-#ifndef IRIX_USING_GNU_LD
-#undef HAVE_GAS_SHF_MERGE
-#define HAVE_GAS_SHF_MERGE 0
-#endif
-
-/* Specify wchar_t types. */
-#undef WCHAR_TYPE
-#define WCHAR_TYPE (Pmode == DImode ? "int" : "long int")
-
-#undef WCHAR_TYPE_SIZE
-#define WCHAR_TYPE_SIZE INT_TYPE_SIZE
-
-/* Same for wint_t. */
-#undef WINT_TYPE
-#define WINT_TYPE (Pmode == DImode ? "int" : "long int")
-
-#undef WINT_TYPE_SIZE
-#define WINT_TYPE_SIZE INT_TYPE_SIZE
-
-#ifndef USED_FOR_TARGET
-/* Use long for intmax_t, uintmax_t? */
-extern int long_intmax;
-#endif
-
-/* C99 stdint.h types. */
-#define INT8_TYPE "signed char"
-#define INT16_TYPE "short int"
-#define INT32_TYPE "int"
-#define INT64_TYPE "long long int"
-#define UINT8_TYPE "unsigned char"
-#define UINT16_TYPE "short unsigned int"
-#define UINT32_TYPE "unsigned int"
-#define UINT64_TYPE "long long unsigned int"
-
-#define INT_LEAST8_TYPE "signed char"
-#define INT_LEAST16_TYPE "short int"
-#define INT_LEAST32_TYPE "int"
-#define INT_LEAST64_TYPE "long long int"
-#define UINT_LEAST8_TYPE "unsigned char"
-#define UINT_LEAST16_TYPE "short unsigned int"
-#define UINT_LEAST32_TYPE "unsigned int"
-#define UINT_LEAST64_TYPE "long long unsigned int"
-
-#define INT_FAST8_TYPE "signed char"
-#define INT_FAST16_TYPE "short int"
-#define INT_FAST32_TYPE "int"
-#define INT_FAST64_TYPE "long long int"
-#define UINT_FAST8_TYPE "unsigned char"
-#define UINT_FAST16_TYPE "short unsigned int"
-#define UINT_FAST32_TYPE "unsigned int"
-#define UINT_FAST64_TYPE "long long unsigned int"
-
-#define INTMAX_TYPE (long_intmax ? "long int" : "long long int")
-#define UINTMAX_TYPE (long_intmax ? "long unsigned int" : "long long unsigned int")
-
-#define INTPTR_TYPE "long int"
-#define UINTPTR_TYPE "long unsigned int"
-
-#define SIG_ATOMIC_TYPE "int"
-
-/* Plain char is unsigned in the SGI compiler. */
-#undef DEFAULT_SIGNED_CHAR
-#define DEFAULT_SIGNED_CHAR 0
-
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- builtin_define_std ("host_mips"); \
- builtin_define_std ("sgi"); \
- builtin_define_std ("unix"); \
- builtin_define_std ("SYSTYPE_SVR4"); \
- builtin_define ("_MODERN_C"); \
- builtin_define ("_SVR4_SOURCE"); \
- builtin_define ("__DSO__"); \
- builtin_assert ("system=unix"); \
- builtin_assert ("system=svr4"); \
- builtin_assert ("machine=sgi"); \
- \
- if (!ISA_MIPS1 && !ISA_MIPS2) \
- builtin_define ("_COMPILER_VERSION=601"); \
- \
- /* We must always define _LONGLONG, even when -ansi is \
- used, because IRIX 5 system header files require it. \
- This is OK, because gcc never warns when long long \
- is used in system header files. \
- \
- An alternative would be to support the SGI builtin \
- type __long_long. */ \
- builtin_define ("_LONGLONG"); \
- \
- /* IRIX 6.5.18 and above provide many ISO C99 \
- features protected by the __c99 macro. \
- libstdc++ v3 needs them as well. */ \
- if (flag_isoc99 || c_dialect_cxx ()) \
- builtin_define ("__c99"); \
- \
- /* The GNU C++ standard library requires that \
- __EXTENSIONS__ and _SGI_SOURCE be defined on at \
- least IRIX 6.2 and probably all IRIX 6 prior to 6.5. \
- We don't need this on IRIX 6.5 itself, but it \
- shouldn't hurt other than the namespace pollution. */ \
- if (!flag_iso || c_dialect_cxx ()) \
- { \
- builtin_define ("__EXTENSIONS__"); \
- builtin_define ("_SGI_SOURCE"); \
- } \
- } \
- while (0)
-
-/* SUBTARGET_OVERRIDE_OPTIONS is run after C_COMMON_OVERRIDE_OPTIONS, so
- only set long_intmax if uninitialized. */
-#undef SUBTARGET_OVERRIDE_OPTIONS
-#define SUBTARGET_OVERRIDE_OPTIONS \
- do \
- { \
- if (long_intmax == -1) \
- long_intmax = mips_abi == ABI_64; \
- } \
- while (0)
-
-extern void irix6_c_common_override_options (void);
-#define C_COMMON_OVERRIDE_OPTIONS irix6_c_common_override_options()
-
-#undef SUBTARGET_CC1_SPEC
-#define SUBTARGET_CC1_SPEC "%{static: -mno-abicalls}"
-
-#undef SUBTARGET_CPP_SPEC
-#define SUBTARGET_CPP_SPEC "%{pthread:-D_REENTRANT}"
-
-#undef INIT_SECTION_ASM_OP
-#define INIT_SECTION_ASM_OP "\t.section\t.gcc_init,\"ax\",@progbits"
-
-#undef FINI_SECTION_ASM_OP
-#define FINI_SECTION_ASM_OP "\t.section\t.gcc_fini,\"ax\",@progbits"
-
-#ifdef IRIX_USING_GNU_LD
-#define IRIX_NO_UNRESOLVED ""
-#else
-#define IRIX_NO_UNRESOLVED "-no_unresolved"
-#endif
-
-#ifdef IRIX_USING_GNU_LD
-#define SUBTARGET_DONT_WARN_UNUSED_SPEC ""
-#define SUBTARGET_WARN_UNUSED_SPEC ""
-#else
-#define SUBTARGET_DONT_WARN_UNUSED_SPEC "-dont_warn_unused"
-#define SUBTARGET_WARN_UNUSED_SPEC "-warn_unused"
-#endif
-
-/* Profiling is supported via libprof1.a not -lc_p as in IRIX 3. */
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC \
- "%{!shared: \
- %{mabi=n32: \
- %{mips4:%{pg:/usr/lib32/mips4/gcrt1.o%s} \
- %{!pg:%{p:/usr/lib32/mips4/mcrt1.o%s /usr/lib32/mips4/libprof1.a%s} \
- %{!p:/usr/lib32/mips4/crt1.o%s}}} \
- %{!mips4:%{pg:/usr/lib32/mips3/gcrt1.o%s} \
- %{!pg:%{p:/usr/lib32/mips3/mcrt1.o%s /usr/lib32/mips3/libprof1.a%s} \
- %{!p:/usr/lib32/mips3/crt1.o%s}}}} \
- %{mabi=64: \
- %{mips4:%{pg:/usr/lib64/mips4/gcrt1.o} \
- %{!pg:%{p:/usr/lib64/mips4/mcrt1.o /usr/lib64/mips4/libprof1.a} \
- %{!p:/usr/lib64/mips4/crt1.o}}} \
- %{!mips4:%{pg:/usr/lib64/mips3/gcrt1.o} \
- %{!pg:%{p:/usr/lib64/mips3/mcrt1.o /usr/lib64/mips3/libprof1.a} \
- %{!p:/usr/lib64/mips3/crt1.o}}}}} \
- irix-crti.o%s crtbegin.o%s"
-
-#undef LIB_SPEC
-#define LIB_SPEC \
- "%{mabi=n32: %{mips4:-L/usr/lib32/mips4} %{!mips4:-L/usr/lib32/mips3} \
- -L/usr/lib32} \
- %{mabi=64: %{mips4:-L/usr/lib64/mips4} %{!mips4:-L/usr/lib64/mips3} \
- -L/usr/lib64} \
- %{!shared:" \
- SUBTARGET_DONT_WARN_UNUSED_SPEC \
- " %{pthread:-lpthread} %{p:libprof1.a%s}%{pg:libprof1.a%s} -lc " \
- SUBTARGET_WARN_UNUSED_SPEC "}"
-
-/* Avoid getting two warnings for libgcc.a everytime we link. libgcc.a
- contains references to copysignl, so link with libm to resolve them. */
-#undef LIBGCC_SPEC
-#define LIBGCC_SPEC \
- SUBTARGET_DONT_WARN_UNUSED_SPEC " -lgcc -lm " SUBTARGET_WARN_UNUSED_SPEC
-
-#undef ENDFILE_SPEC
-#define ENDFILE_SPEC \
- "%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s} \
- crtend.o%s irix-crtn.o%s \
- %{!shared: \
- %{mabi=n32:%{mips4:/usr/lib32/mips4/crtn.o%s}\
- %{!mips4:/usr/lib32/mips3/crtn.o%s}}\
- %{mabi=64:%{mips4:/usr/lib64/mips4/crtn.o%s}\
- %{!mips4:/usr/lib64/mips3/crtn.o%s}}}"
-
-/* Generic part of the LINK_SPEC. */
-#undef LINK_SPEC
-#define LINK_SPEC "\
-%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} %{mips4} \
-%{bestGnum} %{shared} %{non_shared} \
-%{call_shared} %{no_archive} %{exact_version} \
-%{!shared: \
- %{!non_shared: %{!call_shared:%{!r: -call_shared " IRIX_NO_UNRESOLVED "}}}} \
-%{rpath} %{!r: -init __gcc_init -fini __gcc_fini} " IRIX_SUBTARGET_LINK_SPEC
-
-#ifdef IRIX_USING_GNU_LD
-#define IRIX_SUBTARGET_LINK_SPEC \
- "%{mabi=n32: -melf32bmipn32}%{mabi=64: -melf64bmip}"
-#else
- /* Explicitly hide crt symbols that would normally be marked with
- a "hidden" visibility attribute.
-
- We have traditionally disabled this attribute when using the
- native linker because the native linker's visibility support is
- not fully-compatible with the GNU linker's. In particular, the
- native linker does not pull in archive objects purely to resolve
- references to the object's hidden symbols, whereas the GNU
- linker does.
-
- The gcc build system currently hides symbols in some static
- libraries (typically libgcov.a or libgcc.a) whenever visibility
- attributes are supported. On targets with GNU semantics, this
- makes sure that uses of libx.so symbols in one dynamic object are
- not resolved to libx.a symbols in another dynamic object. But
- on targets with IRIX semantics, hiding the symbols prevents the
- static archive from working at all.
-
- It would probably be better to enable visiblity attributes for
- IRIX ld and disable the static archives versioning. It shouldn't
- make anything worse, since libx.a symbols are global by default
- anyway. However, no-one has volunteered to do this yet. */
-
-#define IRIX_SUBTARGET_LINK_SPEC \
- "%{w} -_SYSTYPE_SVR4 -woff 131 \
- %{shared:-hidden_symbol __dso_handle} \
- %{mabi=n32: -n32}%{mabi=64: -64}%{!mabi*: -n32}"
-#endif
-
-/* A linker error can empirically be avoided by removing duplicate
- library search directories. */
-#define LINK_ELIMINATE_DUPLICATE_LDIRECTORIES 1
-
-/* The SGI linker doesn't understand constructor priorities. */
-#ifndef IRIX_USING_GNU_LD
-#define SUPPORTS_INIT_PRIORITY 0
-#endif
-
-/* Add -g to mips.h default to avoid confusing gas with local symbols
- generated from stabs info. */
-#undef NM_FLAGS
-#define NM_FLAGS "-Bng"
-
-/* The system header files are C++ aware. */
-/* ??? Unfortunately, most but not all of the headers are C++ aware.
- Specifically, curses.h is not, and as a consequence, defining this
- used to prevent libg++ building. This is no longer the case so
- define it again to prevent other problems, e.g. with getopt in
- unistd.h. We still need some way to fix just those files that need
- fixing. */
-#define NO_IMPLICIT_EXTERN_C 1
-
-/* -G is incompatible with -KPIC which is the default, so only allow objects
- in the small data section if the user explicitly asks for it. */
-#undef MIPS_DEFAULT_GVALUE
-#define MIPS_DEFAULT_GVALUE 0
-
-#define MIPS_TFMODE_FORMAT mips_extended_format
diff --git a/gcc/config/mips/iris6.opt b/gcc/config/mips/iris6.opt
deleted file mode 100644
index 05fc378c56..0000000000
--- a/gcc/config/mips/iris6.opt
+++ /dev/null
@@ -1,45 +0,0 @@
-; IRIX 6.5 options.
-
-; Copyright (C) 2011
-; Free Software Foundation, Inc.
-;
-; This file is part of GCC.
-;
-; GCC is free software; you can redistribute it and/or modify it under
-; the terms of the GNU General Public License as published by the Free
-; Software Foundation; either version 3, or (at your option) any later
-; version.
-;
-; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-; WARRANTY; without even the implied warranty of MERCHANTABILITY or
-; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-; for more details.
-;
-; You should have received a copy of the GNU General Public License
-; along with GCC; see the file COPYING3. If not see
-; <http://www.gnu.org/licenses/>.
-
-; See the GCC internals manual (options.texi) for a description of
-; this file's format.
-
-; Please try to keep this file in ASCII collating order.
-
-bestGnum
-Driver
-
-call_shared
-Driver
-
-exact_version
-Driver
-
-no_archive
-Driver
-
-non_shared
-Driver
-
-pthread
-Driver
-
-; This comment is to ensure we retain the blank line above.
diff --git a/gcc/config/mips/irix6-c.c b/gcc/config/mips/irix6-c.c
deleted file mode 100644
index a62bc883e9..0000000000
--- a/gcc/config/mips/irix6-c.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/* IRIX 6 support needed only by C/C++ frontends.
- Copyright (C) 2012 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tree.h"
-#include "tm.h"
-#include "c-family/c-common.h"
-
-/* For C99, intmax_t, uintmax_t are always long long int, otherwise the
- type differs between 32-bit and 64-bit compilations. */
-void
-irix6_c_common_override_options (void)
-{
- if (flag_isoc99 || c_dialect_cxx ())
- long_intmax = 0;
- else
- /* Cannot use LONG_TYPE_SIZE == 64. LONG_TYPE_SIZE is only set in
- mips_option_override after C_COMMON_OVERRIDE_OPTIONS. */
- long_intmax = mips_abi == ABI_64;
-}
diff --git a/gcc/config/mips/linux-common.h b/gcc/config/mips/linux-common.h
new file mode 100644
index 0000000000..e1e977eb9b
--- /dev/null
+++ b/gcc/config/mips/linux-common.h
@@ -0,0 +1,64 @@
+/* Definitions for MIPS running Linux-based GNU systems with ELF format.
+ Copyright (C) 2012-2014 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ GNU_USER_TARGET_OS_CPP_BUILTINS(); \
+ /* The GNU C++ standard library requires this. */ \
+ if (c_dialect_cxx ()) \
+ builtin_define ("_GNU_SOURCE"); \
+ ANDROID_TARGET_OS_CPP_BUILTINS(); \
+ } while (0)
+
+#undef LINK_SPEC
+#define LINK_SPEC \
+ LINUX_OR_ANDROID_LD (GNU_USER_TARGET_LINK_SPEC, \
+ GNU_USER_TARGET_LINK_SPEC " " ANDROID_LINK_SPEC)
+
+#undef SUBTARGET_CC1_SPEC
+#define SUBTARGET_CC1_SPEC \
+ LINUX_OR_ANDROID_CC (GNU_USER_TARGET_CC1_SPEC, \
+ GNU_USER_TARGET_CC1_SPEC " " ANDROID_CC1_SPEC)
+
+#undef CC1PLUS_SPEC
+#define CC1PLUS_SPEC \
+ LINUX_OR_ANDROID_CC ("", ANDROID_CC1PLUS_SPEC)
+
+#undef LIB_SPEC
+#define LIB_SPEC \
+ LINUX_OR_ANDROID_LD (GNU_USER_TARGET_LIB_SPEC, \
+ GNU_USER_TARGET_NO_PTHREADS_LIB_SPEC " " ANDROID_LIB_SPEC)
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ LINUX_OR_ANDROID_LD (GNU_USER_TARGET_STARTFILE_SPEC, ANDROID_STARTFILE_SPEC)
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC \
+ LINUX_OR_ANDROID_LD (GNU_USER_TARGET_MATHFILE_SPEC " " \
+ GNU_USER_TARGET_ENDFILE_SPEC, \
+ GNU_USER_TARGET_MATHFILE_SPEC " " \
+ ANDROID_ENDFILE_SPEC)
+
+/* Define this to be nonzero if static stack checking is supported. */
+#define STACK_CHECK_STATIC_BUILTIN 1
+
+/* The default value isn't sufficient in 64-bit mode. */
+#define STACK_CHECK_PROTECT (TARGET_64BIT ? 16 * 1024 : 12 * 1024)
diff --git a/gcc/config/mips/linux.h b/gcc/config/mips/linux.h
index bce9c1793f..e539422d48 100644
--- a/gcc/config/mips/linux.h
+++ b/gcc/config/mips/linux.h
@@ -1,6 +1,5 @@
/* Definitions for MIPS running Linux-based GNU systems with ELF format.
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
- 2007, 2008, 2010, 2011 Free Software Foundation, Inc.
+ Copyright (C) 1998-2014 Free Software Foundation, Inc.
This file is part of GCC.
@@ -18,4 +17,9 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
-#define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1"
+#define GLIBC_DYNAMIC_LINKER \
+ "%{mnan=2008:/lib/ld-linux-mipsn8.so.1;:/lib/ld.so.1}"
+
+#undef UCLIBC_DYNAMIC_LINKER
+#define UCLIBC_DYNAMIC_LINKER \
+ "%{mnan=2008:/lib/ld-uClibc-mipsn8.so.0;:/lib/ld-uClibc.so.0}"
diff --git a/gcc/config/mips/linux64.h b/gcc/config/mips/linux64.h
index 6e92719881..7ad3b2af2b 100644
--- a/gcc/config/mips/linux64.h
+++ b/gcc/config/mips/linux64.h
@@ -1,7 +1,6 @@
/* Definitions for MIPS running Linux-based GNU systems with ELF format
using n32/64 abi.
- Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011
- Free Software Foundation, Inc.
+ Copyright (C) 2002-2014 Free Software Foundation, Inc.
This file is part of GCC.
@@ -23,10 +22,22 @@ along with GCC; see the file COPYING3. If not see
#define GNU_USER_LINK_EMULATION64 "elf64%{EB:b}%{EL:l}tsmip"
#define GNU_USER_LINK_EMULATIONN32 "elf32%{EB:b}%{EL:l}tsmipn32"
-#define GLIBC_DYNAMIC_LINKER32 "/lib/ld.so.1"
-#define GLIBC_DYNAMIC_LINKER64 "/lib64/ld.so.1"
-#define GLIBC_DYNAMIC_LINKERN32 "/lib32/ld.so.1"
-#define UCLIBC_DYNAMIC_LINKERN32 "/lib32/ld-uClibc.so.0"
+#define GLIBC_DYNAMIC_LINKER32 \
+ "%{mnan=2008:/lib/ld-linux-mipsn8.so.1;:/lib/ld.so.1}"
+#define GLIBC_DYNAMIC_LINKER64 \
+ "%{mnan=2008:/lib64/ld-linux-mipsn8.so.1;:/lib64/ld.so.1}"
+#define GLIBC_DYNAMIC_LINKERN32 \
+ "%{mnan=2008:/lib32/ld-linux-mipsn8.so.1;:/lib32/ld.so.1}"
+
+#undef UCLIBC_DYNAMIC_LINKER32
+#define UCLIBC_DYNAMIC_LINKER32 \
+ "%{mnan=2008:/lib/ld-uClibc-mipsn8.so.0;:/lib/ld-uClibc.so.0}"
+#undef UCLIBC_DYNAMIC_LINKER64
+#define UCLIBC_DYNAMIC_LINKER64 \
+ "%{mnan=2008:/lib/ld64-uClibc-mipsn8.so.0;:/lib/ld64-uClibc.so.0}"
+#define UCLIBC_DYNAMIC_LINKERN32 \
+ "%{mnan=2008:/lib32/ld-uClibc-mipsn8.so.0;:/lib32/ld-uClibc.so.0}"
+
#define BIONIC_DYNAMIC_LINKERN32 "/system/bin/linker32"
#define GNU_USER_DYNAMIC_LINKERN32 \
CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKERN32, UCLIBC_DYNAMIC_LINKERN32, \
diff --git a/gcc/config/mips/loongson.h b/gcc/config/mips/loongson.h
index fcaf55366f..6e3de0d1d3 100644
--- a/gcc/config/mips/loongson.h
+++ b/gcc/config/mips/loongson.h
@@ -1,6 +1,6 @@
/* Intrinsics for ST Microelectronics Loongson-2E/2F SIMD operations.
- Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2008-2014 Free Software Foundation, Inc.
Contributed by CodeSourcery.
This file is part of GCC.
diff --git a/gcc/config/mips/loongson.md b/gcc/config/mips/loongson.md
index 4f9cc7396c..474033d1e2 100644
--- a/gcc/config/mips/loongson.md
+++ b/gcc/config/mips/loongson.md
@@ -1,6 +1,6 @@
;; Machine description for Loongson-specific patterns, such as
;; ST Microelectronics Loongson-2E/2F etc.
-;; Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2014 Free Software Foundation, Inc.
;; Contributed by CodeSourcery.
;;
;; This file is part of GCC.
diff --git a/gcc/config/mips/loongson2ef.md b/gcc/config/mips/loongson2ef.md
index fa5ae7e9fe..0f71d0bb62 100644
--- a/gcc/config/mips/loongson2ef.md
+++ b/gcc/config/mips/loongson2ef.md
@@ -1,6 +1,6 @@
;; Pipeline model for ST Microelectronics Loongson-2E/2F cores.
-;; Copyright (C) 2008, 2010 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2014 Free Software Foundation, Inc.
;; Contributed by CodeSourcery.
;;
;; GCC is free software; you can redistribute it and/or modify
@@ -98,7 +98,7 @@
;; ls2_[f]alu{1,2}_turn_enabled units according to this attribute.
;; These instructions are used in mips.c: sched_ls2_dfa_post_advance_cycle.
-(define_attr "ls2_turn_type" "alu1,alu2,falu1,falu2,unknown"
+(define_attr "ls2_turn_type" "alu1,alu2,falu1,falu2,unknown,atomic,syncloop"
(const_string "unknown"))
;; Subscribe ls2_alu1_turn_enabled.
@@ -154,8 +154,8 @@
;; Reservation for integer instructions.
(define_insn_reservation "ls2_alu" 2
(and (eq_attr "cpu" "loongson_2e,loongson_2f")
- (eq_attr "type" "arith,condmove,const,logical,mfhilo,move,
- mthilo,nop,shift,signext,slt"))
+ (eq_attr "type" "arith,condmove,const,logical,mfhi,mflo,move,
+ mthi,mtlo,nop,shift,signext,slt"))
"ls2_alu")
;; Reservation for branch instructions.
diff --git a/gcc/config/mips/loongson3a.md b/gcc/config/mips/loongson3a.md
index c584f42f0e..6fc3d3c340 100644
--- a/gcc/config/mips/loongson3a.md
+++ b/gcc/config/mips/loongson3a.md
@@ -1,6 +1,6 @@
;; Pipeline model for Loongson-3A cores.
-;; Copyright (C) 2011 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
@@ -53,7 +53,7 @@
(define_insn_reservation "ls3a_mfhilo" 1
(and (eq_attr "cpu" "loongson_3a")
- (eq_attr "type" "mfhilo,mthilo"))
+ (eq_attr "type" "mfhi,mflo,mthi,mtlo"))
"ls3a_alu2")
;; Operation imul3nc is fully pipelined.
@@ -131,7 +131,7 @@
;; Force single-dispatch for unknown or multi.
(define_insn_reservation "ls3a_unknown" 1
(and (eq_attr "cpu" "loongson_3a")
- (eq_attr "type" "unknown,multi"))
+ (eq_attr "type" "unknown,multi,atomic,syncloop"))
"ls3a_alu1 + ls3a_alu2 + ls3a_falu1 + ls3a_falu2 + ls3a_mem")
;; End of DFA-based pipeline description for loongson_3a
diff --git a/gcc/config/mips/micromips.md b/gcc/config/mips/micromips.md
new file mode 100644
index 0000000000..3504044f98
--- /dev/null
+++ b/gcc/config/mips/micromips.md
@@ -0,0 +1,138 @@
+;; Copyright (C) 2013-2014 Free Software Foundation, Inc.
+;;
+;; micromips.md Machine Description for the microMIPS instruction set
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3. If not see
+;; <http://www.gnu.org/licenses/>.
+
+(define_insn "*store_word_multiple"
+ [(match_parallel 0 ""
+ [(set (match_operand:SI 1 "memory_operand")
+ (match_operand:SI 2 "register_operand"))])]
+ "TARGET_MICROMIPS
+ && umips_save_restore_pattern_p (true, operands[0])"
+ { return umips_output_save_restore (true, operands[0]); }
+ [(set_attr "type" "multimem")
+ (set_attr "mode" "SI")
+ (set_attr "can_delay" "no")])
+
+(define_insn "*load_word_multiple"
+ [(match_parallel 0 ""
+ [(set (match_operand:SI 1 "register_operand")
+ (match_operand:SI 2 "memory_operand"))])]
+ "TARGET_MICROMIPS
+ && umips_save_restore_pattern_p (false, operands[0])"
+ { return umips_output_save_restore (false, operands[0]); }
+ [(set_attr "type" "multimem")
+ (set_attr "mode" "SI")
+ (set_attr "can_delay" "no")])
+
+;; For LWP.
+(define_peephole2
+ [(set (match_operand:SI 0 "d_operand" "")
+ (match_operand:SI 1 "non_volatile_mem_operand" ""))
+ (set (match_operand:SI 2 "d_operand" "")
+ (match_operand:SI 3 "non_volatile_mem_operand" ""))]
+ "TARGET_MICROMIPS
+ && umips_load_store_pair_p (true, operands)"
+ [(parallel [(set (match_dup 0) (match_dup 1))
+ (set (match_dup 2) (match_dup 3))])])
+
+;; The behavior of the LWP insn is undefined if placed in a delay slot.
+(define_insn "*lwp"
+ [(parallel [(set (match_operand:SI 0 "d_operand")
+ (match_operand:SI 1 "non_volatile_mem_operand"))
+ (set (match_operand:SI 2 "d_operand")
+ (match_operand:SI 3 "non_volatile_mem_operand"))])]
+
+ "TARGET_MICROMIPS
+ && umips_load_store_pair_p (true, operands)"
+{
+ umips_output_load_store_pair (true, operands);
+ return "";
+}
+ [(set_attr "type" "load")
+ (set_attr "mode" "SI")
+ (set_attr "can_delay" "no")])
+
+;; For SWP.
+(define_peephole2
+ [(set (match_operand:SI 0 "non_volatile_mem_operand" "")
+ (match_operand:SI 1 "d_operand" ""))
+ (set (match_operand:SI 2 "non_volatile_mem_operand" "")
+ (match_operand:SI 3 "d_operand" ""))]
+ "TARGET_MICROMIPS
+ && umips_load_store_pair_p (false, operands)"
+ [(parallel [(set (match_dup 0) (match_dup 1))
+ (set (match_dup 2) (match_dup 3))])])
+
+;; The behavior of the SWP insn is undefined if placed in a delay slot.
+(define_insn "*swp"
+ [(parallel [(set (match_operand:SI 0 "non_volatile_mem_operand")
+ (match_operand:SI 1 "d_operand"))
+ (set (match_operand:SI 2 "non_volatile_mem_operand")
+ (match_operand:SI 3 "d_operand"))])]
+
+ "TARGET_MICROMIPS
+ && umips_load_store_pair_p (false, operands)"
+{
+ umips_output_load_store_pair (false, operands);
+ return "";
+}
+ [(set_attr "type" "store")
+ (set_attr "mode" "SI")
+ (set_attr "can_delay" "no")])
+
+;; For JRADDIUSP.
+(define_insn "jraddiusp"
+ [(parallel [(return)
+ (use (reg:SI 31))
+ (set (reg:SI 29)
+ (plus:SI (reg:SI 29)
+ (match_operand 0 "uw5_operand")))])]
+ "TARGET_MICROMIPS"
+ "jraddiusp\t%0"
+ [(set_attr "type" "trap")
+ (set_attr "can_delay" "no")
+ (set_attr "mode" "SI")])
+
+;; For MOVEP.
+(define_peephole2
+ [(set (match_operand:MOVEP1 0 "register_operand" "")
+ (match_operand:MOVEP1 1 "movep_src_operand" ""))
+ (set (match_operand:MOVEP2 2 "register_operand" "")
+ (match_operand:MOVEP2 3 "movep_src_operand" ""))]
+ "TARGET_MICROMIPS
+ && umips_movep_target_p (operands[0], operands[2])"
+ [(parallel [(set (match_dup 0) (match_dup 1))
+ (set (match_dup 2) (match_dup 3))])])
+
+;; The behavior of the MOVEP insn is undefined if placed in a delay slot.
+(define_insn "*movep<MOVEP1:mode><MOVEP2:mode>"
+ [(parallel [(set (match_operand:MOVEP1 0 "register_operand")
+ (match_operand:MOVEP1 1 "movep_src_operand"))
+ (set (match_operand:MOVEP2 2 "register_operand")
+ (match_operand:MOVEP2 3 "movep_src_operand"))])]
+ "TARGET_MICROMIPS
+ && umips_movep_target_p (operands[0], operands[2])"
+{
+ if (REGNO (operands[0]) < REGNO (operands[2]))
+ return "movep\t%0,%2,%z1,%z3";
+ else
+ return "movep\t%2,%0,%z3,%z1";
+}
+ [(set_attr "type" "move")
+ (set_attr "mode" "<MODE>")
+ (set_attr "can_delay" "no")])
diff --git a/gcc/config/mips/mips-cpus.def b/gcc/config/mips/mips-cpus.def
index 98b915a1bd..07fbf9c7ef 100644
--- a/gcc/config/mips/mips-cpus.def
+++ b/gcc/config/mips/mips-cpus.def
@@ -1,8 +1,5 @@
/* MIPS CPU names.
- Copyright (C) 1989, 1990, 1991, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- 2011
- Free Software Foundation, Inc.
+ Copyright (C) 1989-2014 Free Software Foundation, Inc.
This file is part of GCC.
@@ -46,7 +43,7 @@ MIPS_CPU ("mips4", PROCESSOR_R8000, 4, 0)
that to a recommendation to avoid the instructions in code that
isn't tuned to a specific processor. */
MIPS_CPU ("mips32", PROCESSOR_4KC, 32, PTF_AVOID_BRANCHLIKELY)
-MIPS_CPU ("mips32r2", PROCESSOR_M4K, 33, PTF_AVOID_BRANCHLIKELY)
+MIPS_CPU ("mips32r2", PROCESSOR_74KF2_1, 33, PTF_AVOID_BRANCHLIKELY)
MIPS_CPU ("mips64", PROCESSOR_5KC, 64, PTF_AVOID_BRANCHLIKELY)
/* ??? For now just tune the generic MIPS64r2 for 5KC as well. */
MIPS_CPU ("mips64r2", PROCESSOR_5KC, 65, PTF_AVOID_BRANCHLIKELY)
@@ -70,6 +67,8 @@ MIPS_CPU ("r4400", PROCESSOR_R4000, 3, 0)
MIPS_CPU ("r4600", PROCESSOR_R4600, 3, 0)
MIPS_CPU ("orion", PROCESSOR_R4600, 3, 0)
MIPS_CPU ("r4650", PROCESSOR_R4650, 3, 0)
+MIPS_CPU ("r4700", PROCESSOR_R4700, 3, 0)
+MIPS_CPU ("r5900", PROCESSOR_R5900, 3, 0)
/* ST Loongson 2E/2F processors. */
MIPS_CPU ("loongson2e", PROCESSOR_LOONGSON_2E, 3, PTF_AVOID_BRANCHLIKELY)
MIPS_CPU ("loongson2f", PROCESSOR_LOONGSON_2F, 3, PTF_AVOID_BRANCHLIKELY)
@@ -94,6 +93,10 @@ MIPS_CPU ("4ksc", PROCESSOR_4KC, 32, 0)
/* MIPS32 Release 2 processors. */
MIPS_CPU ("m4k", PROCESSOR_M4K, 33, 0)
+MIPS_CPU ("m14kc", PROCESSOR_M4K, 33, 0)
+MIPS_CPU ("m14k", PROCESSOR_M4K, 33, 0)
+MIPS_CPU ("m14ke", PROCESSOR_M4K, 33, 0)
+MIPS_CPU ("m14kec", PROCESSOR_M4K, 33, 0)
MIPS_CPU ("4kec", PROCESSOR_4KC, 33, 0)
MIPS_CPU ("4kem", PROCESSOR_4KC, 33, 0)
MIPS_CPU ("4kep", PROCESSOR_4KP, 33, 0)
@@ -119,14 +122,15 @@ MIPS_CPU ("34kf", PROCESSOR_24KF2_1, 33, 0)
MIPS_CPU ("34kf1_1", PROCESSOR_24KF1_1, 33, 0)
MIPS_CPU ("34kfx", PROCESSOR_24KF1_1, 33, 0)
MIPS_CPU ("34kx", PROCESSOR_24KF1_1, 33, 0)
+MIPS_CPU ("34kn", PROCESSOR_24KC, 33, 0) /* 34K with MT but no DSP. */
-MIPS_CPU ("74kc", PROCESSOR_74KC, 33, 0) /* 74K with DSPr2. */
-MIPS_CPU ("74kf2_1", PROCESSOR_74KF2_1, 33, 0)
-MIPS_CPU ("74kf", PROCESSOR_74KF2_1, 33, 0)
-MIPS_CPU ("74kf1_1", PROCESSOR_74KF1_1, 33, 0)
-MIPS_CPU ("74kfx", PROCESSOR_74KF1_1, 33, 0)
-MIPS_CPU ("74kx", PROCESSOR_74KF1_1, 33, 0)
-MIPS_CPU ("74kf3_2", PROCESSOR_74KF3_2, 33, 0)
+MIPS_CPU ("74kc", PROCESSOR_74KC, 33, PTF_AVOID_IMADD) /* 74K with DSPr2. */
+MIPS_CPU ("74kf2_1", PROCESSOR_74KF2_1, 33, PTF_AVOID_IMADD)
+MIPS_CPU ("74kf", PROCESSOR_74KF2_1, 33, PTF_AVOID_IMADD)
+MIPS_CPU ("74kf1_1", PROCESSOR_74KF1_1, 33, PTF_AVOID_IMADD)
+MIPS_CPU ("74kfx", PROCESSOR_74KF1_1, 33, PTF_AVOID_IMADD)
+MIPS_CPU ("74kx", PROCESSOR_74KF1_1, 33, PTF_AVOID_IMADD)
+MIPS_CPU ("74kf3_2", PROCESSOR_74KF3_2, 33, PTF_AVOID_IMADD)
MIPS_CPU ("1004kc", PROCESSOR_24KC, 33, 0) /* 1004K with MT/DSP. */
MIPS_CPU ("1004kf2_1", PROCESSOR_24KF2_1, 33, 0)
@@ -140,10 +144,11 @@ MIPS_CPU ("20kc", PROCESSOR_20KC, 64, PTF_AVOID_BRANCHLIKELY)
MIPS_CPU ("sb1", PROCESSOR_SB1, 64, PTF_AVOID_BRANCHLIKELY)
MIPS_CPU ("sb1a", PROCESSOR_SB1A, 64, PTF_AVOID_BRANCHLIKELY)
MIPS_CPU ("sr71000", PROCESSOR_SR71000, 64, PTF_AVOID_BRANCHLIKELY)
-MIPS_CPU ("xlr", PROCESSOR_XLR, 64, 0)
-MIPS_CPU ("loongson3a", PROCESSOR_LOONGSON_3A, 64, PTF_AVOID_BRANCHLIKELY)
+MIPS_CPU ("xlr", PROCESSOR_XLR, 64, PTF_AVOID_BRANCHLIKELY)
/* MIPS64 Release 2 processors. */
+MIPS_CPU ("loongson3a", PROCESSOR_LOONGSON_3A, 65, PTF_AVOID_BRANCHLIKELY)
MIPS_CPU ("octeon", PROCESSOR_OCTEON, 65, PTF_AVOID_BRANCHLIKELY)
MIPS_CPU ("octeon+", PROCESSOR_OCTEON, 65, PTF_AVOID_BRANCHLIKELY)
MIPS_CPU ("octeon2", PROCESSOR_OCTEON2, 65, PTF_AVOID_BRANCHLIKELY)
+MIPS_CPU ("xlp", PROCESSOR_XLP, 65, PTF_AVOID_BRANCHLIKELY)
diff --git a/gcc/config/mips/mips-dsp.md b/gcc/config/mips/mips-dsp.md
index 1b60ad23c5..58c11fe9af 100644
--- a/gcc/config/mips/mips-dsp.md
+++ b/gcc/config/mips/mips-dsp.md
@@ -1,5 +1,4 @@
-;; Copyright (C) 2005, 2006, 2007, 2008, 2010, 2011, 2012
-;; Free Software Foundation, Inc.
+;; Copyright (C) 2005-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
@@ -135,7 +134,7 @@
(unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_ADDQ))])]
"ISA_HAS_DSP"
"add<DSPV:dspfmt1>.<DSPV:dspfmt2>\t%0,%1,%2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_add<DSP:dspfmt1>_s_<DSP:dspfmt2>"
@@ -148,7 +147,7 @@
(unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_ADDQ_S))])]
"ISA_HAS_DSP"
"add<DSP:dspfmt1>_s.<DSP:dspfmt2>\t%0,%1,%2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalusat")
(set_attr "mode" "SI")])
;; SUBQ*
@@ -161,7 +160,7 @@
(unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_SUBQ))])]
"ISA_HAS_DSP"
"sub<DSPV:dspfmt1>.<DSPV:dspfmt2>\t%0,%1,%2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_sub<DSP:dspfmt1>_s_<DSP:dspfmt2>"
@@ -174,7 +173,7 @@
(unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_SUBQ_S))])]
"ISA_HAS_DSP"
"sub<DSP:dspfmt1>_s.<DSP:dspfmt2>\t%0,%1,%2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalusat")
(set_attr "mode" "SI")])
;; ADDSC
@@ -188,7 +187,7 @@
(unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_ADDSC))])]
"ISA_HAS_DSP"
"addsc\t%0,%1,%2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
;; ADDWC
@@ -203,7 +202,7 @@
(unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_ADDWC))])]
"ISA_HAS_DSP"
"addwc\t%0,%1,%2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
;; MODSUB
@@ -214,7 +213,7 @@
UNSPEC_MODSUB))]
"ISA_HAS_DSP"
"modsub\t%0,%1,%2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
;; RADDU*
@@ -224,7 +223,7 @@
UNSPEC_RADDU_W_QB))]
"ISA_HAS_DSP"
"raddu.w.qb\t%0,%1"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
;; ABSQ*
@@ -237,7 +236,7 @@
(unspec:CCDSP [(match_dup 1)] UNSPEC_ABSQ_S))])]
"ISA_HAS_DSP"
"absq_s.<DSPQ:dspfmt2>\t%0,%1"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalusat")
(set_attr "mode" "SI")])
;; PRECRQ*
@@ -248,7 +247,7 @@
UNSPEC_PRECRQ_QB_PH))]
"ISA_HAS_DSP"
"precrq.qb.ph\t%0,%1,%2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_precrq_ph_w"
@@ -258,7 +257,7 @@
UNSPEC_PRECRQ_PH_W))]
"ISA_HAS_DSP"
"precrq.ph.w\t%0,%1,%2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_precrq_rs_ph_w"
@@ -272,7 +271,7 @@
UNSPEC_PRECRQ_RS_PH_W))])]
"ISA_HAS_DSP"
"precrq_rs.ph.w\t%0,%1,%2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
;; PRECRQU*
@@ -287,7 +286,7 @@
UNSPEC_PRECRQU_S_QB_PH))])]
"ISA_HAS_DSP"
"precrqu_s.qb.ph\t%0,%1,%2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalusat")
(set_attr "mode" "SI")])
;; PRECEQ*
@@ -297,7 +296,7 @@
UNSPEC_PRECEQ_W_PHL))]
"ISA_HAS_DSP"
"preceq.w.phl\t%0,%1"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_preceq_w_phr"
@@ -306,7 +305,7 @@
UNSPEC_PRECEQ_W_PHR))]
"ISA_HAS_DSP"
"preceq.w.phr\t%0,%1"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
;; PRECEQU*
@@ -316,7 +315,7 @@
UNSPEC_PRECEQU_PH_QBL))]
"ISA_HAS_DSP"
"precequ.ph.qbl\t%0,%1"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_precequ_ph_qbr"
@@ -325,7 +324,7 @@
UNSPEC_PRECEQU_PH_QBR))]
"ISA_HAS_DSP"
"precequ.ph.qbr\t%0,%1"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_precequ_ph_qbla"
@@ -334,7 +333,7 @@
UNSPEC_PRECEQU_PH_QBLA))]
"ISA_HAS_DSP"
"precequ.ph.qbla\t%0,%1"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_precequ_ph_qbra"
@@ -343,7 +342,7 @@
UNSPEC_PRECEQU_PH_QBRA))]
"ISA_HAS_DSP"
"precequ.ph.qbra\t%0,%1"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
;; PRECEU*
@@ -353,7 +352,7 @@
UNSPEC_PRECEU_PH_QBL))]
"ISA_HAS_DSP"
"preceu.ph.qbl\t%0,%1"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_preceu_ph_qbr"
@@ -362,7 +361,7 @@
UNSPEC_PRECEU_PH_QBR))]
"ISA_HAS_DSP"
"preceu.ph.qbr\t%0,%1"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_preceu_ph_qbla"
@@ -371,7 +370,7 @@
UNSPEC_PRECEU_PH_QBLA))]
"ISA_HAS_DSP"
"preceu.ph.qbla\t%0,%1"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_preceu_ph_qbra"
@@ -380,7 +379,7 @@
UNSPEC_PRECEU_PH_QBRA))]
"ISA_HAS_DSP"
"preceu.ph.qbra\t%0,%1"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
;; Table 2-2. MIPS DSP ASE Instructions: Shift
@@ -404,7 +403,7 @@
}
return "shllv.<DSPV:dspfmt2>\t%0,%1,%2";
}
- [(set_attr "type" "shift")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_shll_s_<DSPQ:dspfmt2>"
@@ -426,7 +425,7 @@
}
return "shllv_s.<DSPQ:dspfmt2>\t%0,%1,%2";
}
- [(set_attr "type" "shift")
+ [(set_attr "type" "dspalusat")
(set_attr "mode" "SI")])
;; SHRL*
@@ -445,7 +444,7 @@
}
return "shrlv.qb\t%0,%1,%2";
}
- [(set_attr "type" "shift")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
;; SHRA*
@@ -464,7 +463,7 @@
}
return "shrav.ph\t%0,%1,%2";
}
- [(set_attr "type" "shift")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_shra_r_<DSPQ:dspfmt2>"
@@ -483,7 +482,7 @@
}
return "shrav_r.<DSPQ:dspfmt2>\t%0,%1,%2";
}
- [(set_attr "type" "shift")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
;; Table 2-3. MIPS DSP ASE Instructions: Multiply
@@ -569,7 +568,8 @@
UNSPEC_DPAU_H_QBL))]
"ISA_HAS_DSP && !TARGET_64BIT"
"dpau.h.qbl\t%q0,%2,%3"
- [(set_attr "type" "imadd")
+ [(set_attr "type" "dspmac")
+ (set_attr "accum_in" "1")
(set_attr "mode" "SI")])
(define_insn "mips_dpau_h_qbr"
@@ -580,7 +580,8 @@
UNSPEC_DPAU_H_QBR))]
"ISA_HAS_DSP && !TARGET_64BIT"
"dpau.h.qbr\t%q0,%2,%3"
- [(set_attr "type" "imadd")
+ [(set_attr "type" "dspmac")
+ (set_attr "accum_in" "1")
(set_attr "mode" "SI")])
;; DPSU*
@@ -592,7 +593,8 @@
UNSPEC_DPSU_H_QBL))]
"ISA_HAS_DSP && !TARGET_64BIT"
"dpsu.h.qbl\t%q0,%2,%3"
- [(set_attr "type" "imadd")
+ [(set_attr "type" "dspmac")
+ (set_attr "accum_in" "1")
(set_attr "mode" "SI")])
(define_insn "mips_dpsu_h_qbr"
@@ -603,7 +605,8 @@
UNSPEC_DPSU_H_QBR))]
"ISA_HAS_DSP && !TARGET_64BIT"
"dpsu.h.qbr\t%q0,%2,%3"
- [(set_attr "type" "imadd")
+ [(set_attr "type" "dspmac")
+ (set_attr "accum_in" "1")
(set_attr "mode" "SI")])
;; DPAQ*
@@ -619,7 +622,8 @@
UNSPEC_DPAQ_S_W_PH))])]
"ISA_HAS_DSP && !TARGET_64BIT"
"dpaq_s.w.ph\t%q0,%2,%3"
- [(set_attr "type" "imadd")
+ [(set_attr "type" "dspmac")
+ (set_attr "accum_in" "1")
(set_attr "mode" "SI")])
;; DPSQ*
@@ -635,7 +639,8 @@
UNSPEC_DPSQ_S_W_PH))])]
"ISA_HAS_DSP && !TARGET_64BIT"
"dpsq_s.w.ph\t%q0,%2,%3"
- [(set_attr "type" "imadd")
+ [(set_attr "type" "dspmac")
+ (set_attr "accum_in" "1")
(set_attr "mode" "SI")])
;; MULSAQ*
@@ -651,7 +656,8 @@
UNSPEC_MULSAQ_S_W_PH))])]
"ISA_HAS_DSP && !TARGET_64BIT"
"mulsaq_s.w.ph\t%q0,%2,%3"
- [(set_attr "type" "imadd")
+ [(set_attr "type" "dspmac")
+ (set_attr "accum_in" "1")
(set_attr "mode" "SI")])
;; DPAQ*
@@ -667,7 +673,8 @@
UNSPEC_DPAQ_SA_L_W))])]
"ISA_HAS_DSP && !TARGET_64BIT"
"dpaq_sa.l.w\t%q0,%2,%3"
- [(set_attr "type" "imadd")
+ [(set_attr "type" "dspmacsat")
+ (set_attr "accum_in" "1")
(set_attr "mode" "SI")])
;; DPSQ*
@@ -683,7 +690,8 @@
UNSPEC_DPSQ_SA_L_W))])]
"ISA_HAS_DSP && !TARGET_64BIT"
"dpsq_sa.l.w\t%q0,%2,%3"
- [(set_attr "type" "imadd")
+ [(set_attr "type" "dspmacsat")
+ (set_attr "accum_in" "1")
(set_attr "mode" "SI")])
;; MAQ*
@@ -699,7 +707,8 @@
UNSPEC_MAQ_S_W_PHL))])]
"ISA_HAS_DSP && !TARGET_64BIT"
"maq_s.w.phl\t%q0,%2,%3"
- [(set_attr "type" "imadd")
+ [(set_attr "type" "dspmac")
+ (set_attr "accum_in" "1")
(set_attr "mode" "SI")])
(define_insn "mips_maq_s_w_phr"
@@ -714,7 +723,8 @@
UNSPEC_MAQ_S_W_PHR))])]
"ISA_HAS_DSP && !TARGET_64BIT"
"maq_s.w.phr\t%q0,%2,%3"
- [(set_attr "type" "imadd")
+ [(set_attr "type" "dspmac")
+ (set_attr "accum_in" "1")
(set_attr "mode" "SI")])
;; MAQ_SA*
@@ -730,7 +740,8 @@
UNSPEC_MAQ_SA_W_PHL))])]
"ISA_HAS_DSP && !TARGET_64BIT"
"maq_sa.w.phl\t%q0,%2,%3"
- [(set_attr "type" "imadd")
+ [(set_attr "type" "dspmacsat")
+ (set_attr "accum_in" "1")
(set_attr "mode" "SI")])
(define_insn "mips_maq_sa_w_phr"
@@ -745,7 +756,8 @@
UNSPEC_MAQ_SA_W_PHR))])]
"ISA_HAS_DSP && !TARGET_64BIT"
"maq_sa.w.phr\t%q0,%2,%3"
- [(set_attr "type" "imadd")
+ [(set_attr "type" "dspmacsat")
+ (set_attr "accum_in" "1")
(set_attr "mode" "SI")])
;; Table 2-4. MIPS DSP ASE Instructions: General Bit/Manipulation
@@ -756,7 +768,7 @@
UNSPEC_BITREV))]
"ISA_HAS_DSP"
"bitrev\t%0,%1"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
;; INSV
@@ -769,7 +781,7 @@
UNSPEC_INSV))]
"ISA_HAS_DSP"
"insv\t%0,%2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
;; REPL*
@@ -787,7 +799,7 @@
}
return "replv.qb\t%0,%1";
}
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_repl_ph"
@@ -798,7 +810,7 @@
"@
repl.ph\t%0,%1
replv.ph\t%0,%1"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
;; Table 2-5. MIPS DSP ASE Instructions: Compare-Pick
@@ -811,7 +823,7 @@
UNSPEC_CMP_EQ))]
"ISA_HAS_DSP"
"cmp<DSPV:dspfmt1_1>.eq.<DSPV:dspfmt2>\t%0,%1"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_cmp<DSPV:dspfmt1_1>_lt_<DSPV:dspfmt2>"
@@ -822,7 +834,7 @@
UNSPEC_CMP_LT))]
"ISA_HAS_DSP"
"cmp<DSPV:dspfmt1_1>.lt.<DSPV:dspfmt2>\t%0,%1"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_cmp<DSPV:dspfmt1_1>_le_<DSPV:dspfmt2>"
@@ -833,7 +845,7 @@
UNSPEC_CMP_LE))]
"ISA_HAS_DSP"
"cmp<DSPV:dspfmt1_1>.le.<DSPV:dspfmt2>\t%0,%1"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_cmpgu_eq_qb"
@@ -843,7 +855,7 @@
UNSPEC_CMPGU_EQ_QB))]
"ISA_HAS_DSP"
"cmpgu.eq.qb\t%0,%1,%2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_cmpgu_lt_qb"
@@ -853,7 +865,7 @@
UNSPEC_CMPGU_LT_QB))]
"ISA_HAS_DSP"
"cmpgu.lt.qb\t%0,%1,%2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_cmpgu_le_qb"
@@ -863,7 +875,7 @@
UNSPEC_CMPGU_LE_QB))]
"ISA_HAS_DSP"
"cmpgu.le.qb\t%0,%1,%2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
;; PICK*
@@ -875,7 +887,7 @@
UNSPEC_PICK))]
"ISA_HAS_DSP"
"pick.<DSPV:dspfmt2>\t%0,%1,%2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
;; PACKRL*
@@ -886,7 +898,7 @@
UNSPEC_PACKRL_PH))]
"ISA_HAS_DSP"
"packrl.ph\t%0,%1,%2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
;; Table 2-6. MIPS DSP ASE Instructions: Accumulator and DSPControl Access
@@ -909,7 +921,7 @@
}
return "extrv.w\t%0,%q1,%2";
}
- [(set_attr "type" "mfhilo")
+ [(set_attr "type" "accext")
(set_attr "mode" "SI")])
(define_insn "mips_extr_r_w"
@@ -930,7 +942,7 @@
}
return "extrv_r.w\t%0,%q1,%2";
}
- [(set_attr "type" "mfhilo")
+ [(set_attr "type" "accext")
(set_attr "mode" "SI")])
(define_insn "mips_extr_rs_w"
@@ -951,7 +963,7 @@
}
return "extrv_rs.w\t%0,%q1,%2";
}
- [(set_attr "type" "mfhilo")
+ [(set_attr "type" "accext")
(set_attr "mode" "SI")])
;; EXTR*_S.H
@@ -973,7 +985,7 @@
}
return "extrv_s.h\t%0,%q1,%2";
}
- [(set_attr "type" "mfhilo")
+ [(set_attr "type" "accext")
(set_attr "mode" "SI")])
;; EXTP*
@@ -996,7 +1008,7 @@
}
return "extpv\t%0,%q1,%2";
}
- [(set_attr "type" "mfhilo")
+ [(set_attr "type" "accext")
(set_attr "mode" "SI")])
(define_insn "mips_extpdp"
@@ -1021,7 +1033,7 @@
}
return "extpdpv\t%0,%q1,%2";
}
- [(set_attr "type" "mfhilo")
+ [(set_attr "type" "accext")
(set_attr "mode" "SI")])
;; SHILO*
@@ -1040,7 +1052,7 @@
}
return "shilov\t%q0,%2";
}
- [(set_attr "type" "mfhilo")
+ [(set_attr "type" "accmod")
(set_attr "mode" "SI")])
;; MTHLIP*
@@ -1056,7 +1068,7 @@
(reg:CCDSP CCDSP_PO_REGNUM)] UNSPEC_MTHLIP))])]
"ISA_HAS_DSP && !TARGET_64BIT"
"mthlip\t%2,%q0"
- [(set_attr "type" "mfhilo")
+ [(set_attr "type" "accmod")
(set_attr "mode" "SI")])
;; WRDSP
@@ -1078,7 +1090,7 @@
(unspec:CCDSP [(match_dup 0) (match_dup 1)] UNSPEC_WRDSP))])]
"ISA_HAS_DSP"
"wrdsp\t%0,%1"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
;; RDDSP
@@ -1094,7 +1106,7 @@
UNSPEC_RDDSP))]
"ISA_HAS_DSP"
"rddsp\t%0,%1"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
;; Table 2-7. MIPS DSP ASE Instructions: Indexed-Load
@@ -1119,8 +1131,7 @@
"ISA_HAS_L<SHORT:SIZE><U>X"
"l<SHORT:size><u>x\t%0,%2(%1)"
[(set_attr "type" "load")
- (set_attr "mode" "<GPR:MODE>")
- (set_attr "length" "4")])
+ (set_attr "mode" "<GPR:MODE>")])
(define_expand "mips_lhx"
[(match_operand:SI 0 "register_operand")
@@ -1153,8 +1164,7 @@
"ISA_HAS_L<GPR:SIZE>X"
"l<GPR:size>x\t%0,%2(%1)"
[(set_attr "type" "load")
- (set_attr "mode" "<GPR:MODE>")
- (set_attr "length" "4")])
+ (set_attr "mode" "<GPR:MODE>")])
(define_insn "*mips_lw<u>x_<P:mode>_ext"
[(set (match_operand:DI 0 "register_operand" "=d")
@@ -1164,8 +1174,7 @@
"ISA_HAS_LW<U>X && TARGET_64BIT"
"lw<u>x\t%0,%2(%1)"
[(set_attr "type" "load")
- (set_attr "mode" "DI")
- (set_attr "length" "4")])
+ (set_attr "mode" "DI")])
;; Table 2-8. MIPS DSP ASE Instructions: Branch
;; BPOSGE32
diff --git a/gcc/config/mips/mips-dspr2.md b/gcc/config/mips/mips-dspr2.md
index 108f51be6c..3fe401f9f7 100644
--- a/gcc/config/mips/mips-dspr2.md
+++ b/gcc/config/mips/mips-dspr2.md
@@ -1,4 +1,4 @@
-;; Copyright (C) 2007, 2010 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
@@ -79,7 +79,7 @@
(unspec:CCDSP [(match_dup 1)] UNSPEC_ABSQ_S_QB))])]
"ISA_HAS_DSPR2"
"absq_s.qb\t%0,%z1"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalusat")
(set_attr "mode" "SI")])
(define_insn "mips_addu_ph"
@@ -91,7 +91,7 @@
(unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_ADDU_PH))])]
"ISA_HAS_DSPR2"
"addu.ph\t%0,%z1,%z2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_addu_s_ph"
@@ -104,7 +104,7 @@
(unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_ADDU_S_PH))])]
"ISA_HAS_DSPR2"
"addu_s.ph\t%0,%z1,%z2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalusat")
(set_attr "mode" "SI")])
(define_insn "mips_adduh_qb"
@@ -114,7 +114,7 @@
UNSPEC_ADDUH_QB))]
"ISA_HAS_DSPR2"
"adduh.qb\t%0,%z1,%z2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_adduh_r_qb"
@@ -124,7 +124,7 @@
UNSPEC_ADDUH_R_QB))]
"ISA_HAS_DSPR2"
"adduh_r.qb\t%0,%z1,%z2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalusat")
(set_attr "mode" "SI")])
(define_insn "mips_append"
@@ -139,7 +139,7 @@
operands[2] = GEN_INT (INTVAL (operands[2]) & 31);
return "append\t%0,%z2,%3";
}
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_balign"
@@ -154,7 +154,7 @@
operands[2] = GEN_INT (INTVAL (operands[2]) & 3);
return "balign\t%0,%z2,%3";
}
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_cmpgdu_eq_qb"
@@ -169,7 +169,7 @@
UNSPEC_CMPGDU_EQ_QB))])]
"ISA_HAS_DSPR2"
"cmpgdu.eq.qb\t%0,%z1,%z2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_cmpgdu_lt_qb"
@@ -184,7 +184,7 @@
UNSPEC_CMPGDU_LT_QB))])]
"ISA_HAS_DSPR2"
"cmpgdu.lt.qb\t%0,%z1,%z2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_cmpgdu_le_qb"
@@ -199,7 +199,7 @@
UNSPEC_CMPGDU_LE_QB))])]
"ISA_HAS_DSPR2"
"cmpgdu.le.qb\t%0,%z1,%z2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_dpa_w_ph"
@@ -210,7 +210,8 @@
UNSPEC_DPA_W_PH))]
"ISA_HAS_DSPR2 && !TARGET_64BIT"
"dpa.w.ph\t%q0,%z2,%z3"
- [(set_attr "type" "imadd")
+ [(set_attr "type" "dspmac")
+ (set_attr "accum_in" "1")
(set_attr "mode" "SI")])
(define_insn "mips_dps_w_ph"
@@ -221,7 +222,8 @@
UNSPEC_DPS_W_PH))]
"ISA_HAS_DSPR2 && !TARGET_64BIT"
"dps.w.ph\t%q0,%z2,%z3"
- [(set_attr "type" "imadd")
+ [(set_attr "type" "dspmac")
+ (set_attr "accum_in" "1")
(set_attr "mode" "SI")])
(define_insn "mulv2hi3"
@@ -301,7 +303,8 @@
UNSPEC_MULSA_W_PH))]
"ISA_HAS_DSPR2 && !TARGET_64BIT"
"mulsa.w.ph\t%q0,%z2,%z3"
- [(set_attr "type" "imadd")
+ [(set_attr "type" "dspmac")
+ (set_attr "accum_in" "1")
(set_attr "mode" "SI")])
(define_insn "mips_precr_qb_ph"
@@ -311,7 +314,7 @@
UNSPEC_PRECR_QB_PH))]
"ISA_HAS_DSPR2"
"precr.qb.ph\t%0,%z1,%z2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_precr_sra_ph_w"
@@ -326,7 +329,7 @@
operands[2] = GEN_INT (INTVAL (operands[2]) & 31);
return "precr_sra.ph.w\t%0,%z2,%3";
}
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_precr_sra_r_ph_w"
@@ -341,7 +344,7 @@
operands[2] = GEN_INT (INTVAL (operands[2]) & 31);
return "precr_sra_r.ph.w\t%0,%z2,%3";
}
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_prepend"
@@ -356,7 +359,7 @@
operands[3] = GEN_INT (INTVAL (operands[3]) & 31);
return "prepend\t%0,%z2,%3";
}
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_shra_qb"
@@ -374,7 +377,7 @@
}
return "shrav.qb\t%0,%z1,%2";
}
- [(set_attr "type" "shift")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
@@ -393,7 +396,7 @@
}
return "shrav_r.qb\t%0,%z1,%2";
}
- [(set_attr "type" "shift")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_shrl_ph"
@@ -411,7 +414,7 @@
}
return "shrlv.ph\t%0,%z1,%2";
}
- [(set_attr "type" "shift")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_subu_ph"
@@ -424,7 +427,7 @@
(unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_SUBU_PH))])]
"ISA_HAS_DSPR2"
"subu.ph\t%0,%z1,%z2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_subu_s_ph"
@@ -437,7 +440,7 @@
(unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_SUBU_S_PH))])]
"ISA_HAS_DSPR2"
"subu_s.ph\t%0,%z1,%z2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalusat")
(set_attr "mode" "SI")])
(define_insn "mips_subuh_qb"
@@ -447,7 +450,7 @@
UNSPEC_SUBUH_QB))]
"ISA_HAS_DSPR2"
"subuh.qb\t%0,%z1,%z2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_subuh_r_qb"
@@ -457,7 +460,7 @@
UNSPEC_SUBUH_R_QB))]
"ISA_HAS_DSPR2"
"subuh_r.qb\t%0,%z1,%z2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_addqh_ph"
@@ -467,7 +470,7 @@
UNSPEC_ADDQH_PH))]
"ISA_HAS_DSPR2"
"addqh.ph\t%0,%z1,%z2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_addqh_r_ph"
@@ -477,7 +480,7 @@
UNSPEC_ADDQH_R_PH))]
"ISA_HAS_DSPR2"
"addqh_r.ph\t%0,%z1,%z2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_addqh_w"
@@ -487,7 +490,7 @@
UNSPEC_ADDQH_W))]
"ISA_HAS_DSPR2"
"addqh.w\t%0,%z1,%z2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_addqh_r_w"
@@ -497,7 +500,7 @@
UNSPEC_ADDQH_R_W))]
"ISA_HAS_DSPR2"
"addqh_r.w\t%0,%z1,%z2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_subqh_ph"
@@ -507,7 +510,7 @@
UNSPEC_SUBQH_PH))]
"ISA_HAS_DSPR2"
"subqh.ph\t%0,%z1,%z2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_subqh_r_ph"
@@ -517,7 +520,7 @@
UNSPEC_SUBQH_R_PH))]
"ISA_HAS_DSPR2"
"subqh_r.ph\t%0,%z1,%z2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_subqh_w"
@@ -527,7 +530,7 @@
UNSPEC_SUBQH_W))]
"ISA_HAS_DSPR2"
"subqh.w\t%0,%z1,%z2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_subqh_r_w"
@@ -537,7 +540,7 @@
UNSPEC_SUBQH_R_W))]
"ISA_HAS_DSPR2"
"subqh_r.w\t%0,%z1,%z2"
- [(set_attr "type" "arith")
+ [(set_attr "type" "dspalu")
(set_attr "mode" "SI")])
(define_insn "mips_dpax_w_ph"
@@ -548,7 +551,8 @@
UNSPEC_DPAX_W_PH))]
"ISA_HAS_DSPR2 && !TARGET_64BIT"
"dpax.w.ph\t%q0,%z2,%z3"
- [(set_attr "type" "imadd")
+ [(set_attr "type" "dspmac")
+ (set_attr "accum_in" "1")
(set_attr "mode" "SI")])
(define_insn "mips_dpsx_w_ph"
@@ -559,7 +563,8 @@
UNSPEC_DPSX_W_PH))]
"ISA_HAS_DSPR2 && !TARGET_64BIT"
"dpsx.w.ph\t%q0,%z2,%z3"
- [(set_attr "type" "imadd")
+ [(set_attr "type" "dspmac")
+ (set_attr "accum_in" "1")
(set_attr "mode" "SI")])
(define_insn "mips_dpaqx_s_w_ph"
@@ -574,7 +579,8 @@
UNSPEC_DPAQX_S_W_PH))])]
"ISA_HAS_DSPR2 && !TARGET_64BIT"
"dpaqx_s.w.ph\t%q0,%z2,%z3"
- [(set_attr "type" "imadd")
+ [(set_attr "type" "dspmac")
+ (set_attr "accum_in" "1")
(set_attr "mode" "SI")])
(define_insn "mips_dpaqx_sa_w_ph"
@@ -589,7 +595,8 @@
UNSPEC_DPAQX_SA_W_PH))])]
"ISA_HAS_DSPR2 && !TARGET_64BIT"
"dpaqx_sa.w.ph\t%q0,%z2,%z3"
- [(set_attr "type" "imadd")
+ [(set_attr "type" "dspmacsat")
+ (set_attr "accum_in" "1")
(set_attr "mode" "SI")])
(define_insn "mips_dpsqx_s_w_ph"
@@ -604,7 +611,8 @@
UNSPEC_DPSQX_S_W_PH))])]
"ISA_HAS_DSPR2 && !TARGET_64BIT"
"dpsqx_s.w.ph\t%q0,%z2,%z3"
- [(set_attr "type" "imadd")
+ [(set_attr "type" "dspmac")
+ (set_attr "accum_in" "1")
(set_attr "mode" "SI")])
(define_insn "mips_dpsqx_sa_w_ph"
@@ -619,5 +627,6 @@
UNSPEC_DPSQX_SA_W_PH))])]
"ISA_HAS_DSPR2 && !TARGET_64BIT"
"dpsqx_sa.w.ph\t%q0,%z2,%z3"
- [(set_attr "type" "imadd")
+ [(set_attr "type" "dspmacsat")
+ (set_attr "accum_in" "1")
(set_attr "mode" "SI")])
diff --git a/gcc/config/mips/mips-fixed.md b/gcc/config/mips/mips-fixed.md
index d5dd909b1f..dbb60f4cab 100644
--- a/gcc/config/mips/mips-fixed.md
+++ b/gcc/config/mips/mips-fixed.md
@@ -1,4 +1,4 @@
-;; Copyright (C) 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
diff --git a/gcc/config/mips/mips-ftypes.def b/gcc/config/mips/mips-ftypes.def
index cd1d1da7a9..078a595a8b 100644
--- a/gcc/config/mips/mips-ftypes.def
+++ b/gcc/config/mips/mips-ftypes.def
@@ -1,6 +1,5 @@
/* Definitions of prototypes for MIPS built-in functions. -*- C -*-
- Copyright (C) 2007, 2008, 2012
- Free Software Foundation, Inc.
+ Copyright (C) 2007-2014 Free Software Foundation, Inc.
This file is part of GCC.
@@ -70,6 +69,8 @@ DEF_MIPS_FTYPE (1, (SF, V2SF))
DEF_MIPS_FTYPE (2, (UDI, UDI, UDI))
DEF_MIPS_FTYPE (2, (UDI, UV2SI, UV2SI))
+DEF_MIPS_FTYPE (1, (USI, VOID))
+
DEF_MIPS_FTYPE (2, (UV2SI, UV2SI, UQI))
DEF_MIPS_FTYPE (2, (UV2SI, UV2SI, UV2SI))
@@ -123,5 +124,6 @@ DEF_MIPS_FTYPE (2, (V8QI, V8QI, V8QI))
DEF_MIPS_FTYPE (2, (VOID, SI, CVPOINTER))
DEF_MIPS_FTYPE (2, (VOID, SI, SI))
+DEF_MIPS_FTYPE (1, (VOID, USI))
DEF_MIPS_FTYPE (2, (VOID, V2HI, V2HI))
DEF_MIPS_FTYPE (2, (VOID, V4QI, V4QI))
diff --git a/gcc/config/mips/mips-modes.def b/gcc/config/mips/mips-modes.def
index 187c651bbb..fa1d1e7d68 100644
--- a/gcc/config/mips/mips-modes.def
+++ b/gcc/config/mips/mips-modes.def
@@ -1,5 +1,5 @@
/* MIPS extra machine modes.
- Copyright (C) 2003, 2004, 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2003-2014 Free Software Foundation, Inc.
This file is part of GCC.
@@ -17,13 +17,7 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
-/* MIPS has a quirky almost-IEEE format for all its
- floating point. */
-RESET_FLOAT_FORMAT (SF, mips_single_format);
-RESET_FLOAT_FORMAT (DF, mips_double_format);
-
-/* Irix6 will override this via MIPS_TFMODE_FORMAT. */
-FLOAT_MODE (TF, 16, mips_quad_format);
+FLOAT_MODE (TF, 16, ieee_quad_format);
/* Vector modes. */
VECTOR_MODES (INT, 4); /* V4QI V2HI */
diff --git a/gcc/config/mips/mips-opts.h b/gcc/config/mips/mips-opts.h
index d2537d3122..be288d64c0 100644
--- a/gcc/config/mips/mips-opts.h
+++ b/gcc/config/mips/mips-opts.h
@@ -1,7 +1,5 @@
/* Definitions for option handling for MIPS.
- Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
- Free Software Foundation, Inc.
+ Copyright (C) 1989-2014 Free Software Foundation, Inc.
This file is part of GCC.
@@ -29,6 +27,13 @@ enum mips_code_readable_setting {
CODE_READABLE_YES
};
+/* Enumerates the setting of the -mabs and -mnan options. */
+enum mips_ieee_754_setting {
+ MIPS_IEEE_754_DEFAULT,
+ MIPS_IEEE_754_LEGACY,
+ MIPS_IEEE_754_2008
+};
+
/* Enumerates the setting of the -mr10k-cache-barrier option. */
enum mips_r10k_cache_barrier_setting {
R10K_CACHE_BARRIER_NONE,
diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h
index 45d2537cab..3d59b7b51e 100644
--- a/gcc/config/mips/mips-protos.h
+++ b/gcc/config/mips/mips-protos.h
@@ -1,7 +1,5 @@
/* Prototypes of target machine for GNU compiler. MIPS version.
- Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
- Free Software Foundation, Inc.
+ Copyright (C) 1989-2014 Free Software Foundation, Inc.
Contributed by A. Lichnewsky (lich@inria.inria.fr).
Changed by Michael Meissner (meissner@osf.org).
64-bit r4000 support by Ian Lance Taylor (ian@cygnus.com) and
@@ -173,6 +171,25 @@ enum mips_call_type {
MIPS_CALL_EPILOGUE
};
+/* Controls the conditions under which certain instructions are split.
+
+ SPLIT_IF_NECESSARY
+ Only perform splits that are necessary for correctness
+ (because no unsplit version exists).
+
+ SPLIT_FOR_SPEED
+ Perform splits that are necessary for correctness or
+ beneficial for code speed.
+
+ SPLIT_FOR_SIZE
+ Perform splits that are necessary for correctness or
+ beneficial for code size. */
+enum mips_split_type {
+ SPLIT_IF_NECESSARY,
+ SPLIT_FOR_SPEED,
+ SPLIT_FOR_SIZE
+};
+
extern bool mips_symbolic_constant_p (rtx, enum mips_symbol_context,
enum mips_symbol_type *);
extern int mips_regno_mode_ok_for_base_p (int, enum machine_mode, bool);
@@ -190,29 +207,15 @@ extern rtx mips_pic_base_register (rtx);
extern rtx mips_got_load (rtx, rtx, enum mips_symbol_type);
extern bool mips_split_symbol (rtx, rtx, enum machine_mode, rtx *);
extern rtx mips_unspec_address (rtx, enum mips_symbol_type);
+extern rtx mips_strip_unspec_address (rtx);
extern void mips_move_integer (rtx, rtx, unsigned HOST_WIDE_INT);
extern bool mips_legitimize_move (enum machine_mode, rtx, rtx);
-extern int m16_uimm3_b (rtx, enum machine_mode);
-extern int m16_simm4_1 (rtx, enum machine_mode);
-extern int m16_nsimm4_1 (rtx, enum machine_mode);
-extern int m16_simm5_1 (rtx, enum machine_mode);
-extern int m16_nsimm5_1 (rtx, enum machine_mode);
-extern int m16_uimm5_4 (rtx, enum machine_mode);
-extern int m16_nuimm5_4 (rtx, enum machine_mode);
-extern int m16_simm8_1 (rtx, enum machine_mode);
-extern int m16_nsimm8_1 (rtx, enum machine_mode);
-extern int m16_uimm8_1 (rtx, enum machine_mode);
-extern int m16_nuimm8_1 (rtx, enum machine_mode);
-extern int m16_uimm8_m1_1 (rtx, enum machine_mode);
-extern int m16_uimm8_4 (rtx, enum machine_mode);
-extern int m16_nuimm8_4 (rtx, enum machine_mode);
-extern int m16_simm8_8 (rtx, enum machine_mode);
-extern int m16_nsimm8_8 (rtx, enum machine_mode);
-
extern rtx mips_subword (rtx, bool);
-extern bool mips_split_64bit_move_p (rtx, rtx);
-extern void mips_split_doubleword_move (rtx, rtx);
+extern bool mips_split_move_p (rtx, rtx, enum mips_split_type);
+extern void mips_split_move (rtx, rtx, enum mips_split_type);
+extern bool mips_split_move_insn_p (rtx, rtx, rtx);
+extern void mips_split_move_insn (rtx, rtx, rtx);
extern const char *mips_output_move (rtx, rtx);
extern bool mips_cfun_has_cprestore_slot_p (void);
extern bool mips_cprestore_address_p (rtx, bool);
@@ -241,7 +244,7 @@ extern bool mips_pad_arg_upward (enum machine_mode, const_tree);
extern bool mips_pad_reg_upward (enum machine_mode, tree);
extern bool mips_expand_ext_as_unaligned_load (rtx, rtx, HOST_WIDE_INT,
- HOST_WIDE_INT);
+ HOST_WIDE_INT, bool);
extern bool mips_expand_ins_as_unaligned_store (rtx, rtx, HOST_WIDE_INT,
HOST_WIDE_INT);
extern bool mips_mem_fits_mode_p (enum machine_mode mode, rtx x);
@@ -294,12 +297,13 @@ extern const char *mips_output_sync (void);
extern const char *mips_output_sync_loop (rtx, rtx *);
extern unsigned int mips_sync_loop_insns (rtx, rtx *);
extern const char *mips_output_division (const char *, rtx *);
+extern const char *mips_output_probe_stack_range (rtx, rtx);
extern unsigned int mips_hard_regno_nregs (int, enum machine_mode);
extern bool mips_linked_madd_p (rtx, rtx);
extern bool mips_store_data_bypass_p (rtx, rtx);
+extern int mips_dspalu_bypass_p (rtx, rtx);
extern rtx mips_prefetch_cookie (rtx, rtx);
-extern void irix_asm_output_align (FILE *, unsigned);
extern const char *current_section_name (void);
extern unsigned int current_section_flags (void);
extern bool mips_use_ins_ext_p (rtx, HOST_WIDE_INT, HOST_WIDE_INT);
@@ -329,6 +333,21 @@ extern void mips_expand_vec_reduc (rtx, rtx, rtx (*)(rtx, rtx, rtx));
extern void mips_expand_vec_minmax (rtx, rtx, rtx,
rtx (*) (rtx, rtx, rtx), bool);
+extern bool mips_signed_immediate_p (unsigned HOST_WIDE_INT, int, int);
+extern bool mips_unsigned_immediate_p (unsigned HOST_WIDE_INT, int, int);
+extern const char *umips_output_save_restore (bool, rtx);
+extern bool umips_save_restore_pattern_p (bool, rtx);
+extern bool umips_load_store_pair_p (bool, rtx *);
+extern void umips_output_load_store_pair (bool, rtx *);
+extern bool umips_movep_target_p (rtx, rtx);
+extern bool umips_12bit_offset_address_p (rtx, enum machine_mode);
+extern bool lwsp_swsp_address_p (rtx, enum machine_mode);
+extern bool m16_based_address_p (rtx, enum machine_mode,
+ int (*)(rtx_def*, machine_mode));
+extern rtx mips_expand_thread_pointer (rtx);
+extern void mips16_expand_get_fcsr (rtx);
+extern void mips16_expand_set_fcsr (rtx);
+
extern bool mips_eh_uses (unsigned int);
extern bool mips_epilogue_uses (unsigned int);
extern void mips_final_prescan_insn (rtx, rtx *, int);
diff --git a/gcc/config/mips/mips-ps-3d.md b/gcc/config/mips/mips-ps-3d.md
index 30ca7cd4a7..549080b88b 100644
--- a/gcc/config/mips/mips-ps-3d.md
+++ b/gcc/config/mips/mips-ps-3d.md
@@ -1,5 +1,5 @@
;; MIPS Paired-Single Floating and MIPS-3D Instructions.
-;; Copyright (C) 2004, 2007, 2010 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
@@ -481,7 +481,7 @@
operands[7] = simplify_gen_subreg (CCV2mode, operands[0], CCV4mode, 8);
}
[(set_attr "type" "fcmp")
- (set_attr "length" "8")
+ (set_attr "insn_count" "2")
(set_attr "mode" "FPSW")])
(define_insn_and_split "mips_cabs_cond_4s"
@@ -510,7 +510,7 @@
operands[7] = simplify_gen_subreg (CCV2mode, operands[0], CCV4mode, 8);
}
[(set_attr "type" "fcmp")
- (set_attr "length" "8")
+ (set_attr "insn_count" "2")
(set_attr "mode" "FPSW")])
diff --git a/gcc/config/mips/mips-tables.opt b/gcc/config/mips/mips-tables.opt
index 2d2c7f668f..760b764e3e 100644
--- a/gcc/config/mips/mips-tables.opt
+++ b/gcc/config/mips/mips-tables.opt
@@ -1,7 +1,7 @@
; -*- buffer-read-only: t -*-
; Generated automatically by genopt.sh from mips-cpus.def.
-; Copyright (C) 2011 Free Software Foundation, Inc.
+; Copyright (C) 2011-2014 Free Software Foundation, Inc.
;
; This file is part of GCC.
;
@@ -202,410 +202,443 @@ EnumValue
Enum(mips_arch_opt_value) String(4650) Value(21)
EnumValue
-Enum(mips_arch_opt_value) String(loongson2e) Value(22) Canonical
+Enum(mips_arch_opt_value) String(r4700) Value(22) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(loongson2f) Value(23) Canonical
+Enum(mips_arch_opt_value) String(4700) Value(22)
EnumValue
-Enum(mips_arch_opt_value) String(r8000) Value(24) Canonical
+Enum(mips_arch_opt_value) String(r5900) Value(23) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r8k) Value(24)
+Enum(mips_arch_opt_value) String(5900) Value(23)
EnumValue
-Enum(mips_arch_opt_value) String(8000) Value(24)
+Enum(mips_arch_opt_value) String(loongson2e) Value(24) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(8k) Value(24)
+Enum(mips_arch_opt_value) String(loongson2f) Value(25) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r10000) Value(25) Canonical
+Enum(mips_arch_opt_value) String(r8000) Value(26) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r10k) Value(25)
+Enum(mips_arch_opt_value) String(r8k) Value(26)
EnumValue
-Enum(mips_arch_opt_value) String(10000) Value(25)
+Enum(mips_arch_opt_value) String(8000) Value(26)
EnumValue
-Enum(mips_arch_opt_value) String(10k) Value(25)
+Enum(mips_arch_opt_value) String(8k) Value(26)
EnumValue
-Enum(mips_arch_opt_value) String(r12000) Value(26) Canonical
+Enum(mips_arch_opt_value) String(r10000) Value(27) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r12k) Value(26)
+Enum(mips_arch_opt_value) String(r10k) Value(27)
EnumValue
-Enum(mips_arch_opt_value) String(12000) Value(26)
+Enum(mips_arch_opt_value) String(10000) Value(27)
EnumValue
-Enum(mips_arch_opt_value) String(12k) Value(26)
+Enum(mips_arch_opt_value) String(10k) Value(27)
EnumValue
-Enum(mips_arch_opt_value) String(r14000) Value(27) Canonical
+Enum(mips_arch_opt_value) String(r12000) Value(28) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r14k) Value(27)
+Enum(mips_arch_opt_value) String(r12k) Value(28)
EnumValue
-Enum(mips_arch_opt_value) String(14000) Value(27)
+Enum(mips_arch_opt_value) String(12000) Value(28)
EnumValue
-Enum(mips_arch_opt_value) String(14k) Value(27)
+Enum(mips_arch_opt_value) String(12k) Value(28)
EnumValue
-Enum(mips_arch_opt_value) String(r16000) Value(28) Canonical
+Enum(mips_arch_opt_value) String(r14000) Value(29) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r16k) Value(28)
+Enum(mips_arch_opt_value) String(r14k) Value(29)
EnumValue
-Enum(mips_arch_opt_value) String(16000) Value(28)
+Enum(mips_arch_opt_value) String(14000) Value(29)
EnumValue
-Enum(mips_arch_opt_value) String(16k) Value(28)
+Enum(mips_arch_opt_value) String(14k) Value(29)
EnumValue
-Enum(mips_arch_opt_value) String(vr5000) Value(29) Canonical
+Enum(mips_arch_opt_value) String(r16000) Value(30) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(vr5k) Value(29)
+Enum(mips_arch_opt_value) String(r16k) Value(30)
EnumValue
-Enum(mips_arch_opt_value) String(5000) Value(29)
+Enum(mips_arch_opt_value) String(16000) Value(30)
EnumValue
-Enum(mips_arch_opt_value) String(5k) Value(29)
+Enum(mips_arch_opt_value) String(16k) Value(30)
EnumValue
-Enum(mips_arch_opt_value) String(r5000) Value(29)
+Enum(mips_arch_opt_value) String(vr5000) Value(31) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r5k) Value(29)
+Enum(mips_arch_opt_value) String(vr5k) Value(31)
EnumValue
-Enum(mips_arch_opt_value) String(vr5400) Value(30) Canonical
+Enum(mips_arch_opt_value) String(5000) Value(31)
EnumValue
-Enum(mips_arch_opt_value) String(5400) Value(30)
+Enum(mips_arch_opt_value) String(5k) Value(31)
EnumValue
-Enum(mips_arch_opt_value) String(r5400) Value(30)
+Enum(mips_arch_opt_value) String(r5000) Value(31)
EnumValue
-Enum(mips_arch_opt_value) String(vr5500) Value(31) Canonical
+Enum(mips_arch_opt_value) String(r5k) Value(31)
EnumValue
-Enum(mips_arch_opt_value) String(5500) Value(31)
+Enum(mips_arch_opt_value) String(vr5400) Value(32) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r5500) Value(31)
+Enum(mips_arch_opt_value) String(5400) Value(32)
EnumValue
-Enum(mips_arch_opt_value) String(rm7000) Value(32) Canonical
+Enum(mips_arch_opt_value) String(r5400) Value(32)
EnumValue
-Enum(mips_arch_opt_value) String(rm7k) Value(32)
+Enum(mips_arch_opt_value) String(vr5500) Value(33) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(7000) Value(32)
+Enum(mips_arch_opt_value) String(5500) Value(33)
EnumValue
-Enum(mips_arch_opt_value) String(7k) Value(32)
+Enum(mips_arch_opt_value) String(r5500) Value(33)
EnumValue
-Enum(mips_arch_opt_value) String(r7000) Value(32)
+Enum(mips_arch_opt_value) String(rm7000) Value(34) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r7k) Value(32)
+Enum(mips_arch_opt_value) String(rm7k) Value(34)
EnumValue
-Enum(mips_arch_opt_value) String(rm9000) Value(33) Canonical
+Enum(mips_arch_opt_value) String(7000) Value(34)
EnumValue
-Enum(mips_arch_opt_value) String(rm9k) Value(33)
+Enum(mips_arch_opt_value) String(7k) Value(34)
EnumValue
-Enum(mips_arch_opt_value) String(9000) Value(33)
+Enum(mips_arch_opt_value) String(r7000) Value(34)
EnumValue
-Enum(mips_arch_opt_value) String(9k) Value(33)
+Enum(mips_arch_opt_value) String(r7k) Value(34)
EnumValue
-Enum(mips_arch_opt_value) String(r9000) Value(33)
+Enum(mips_arch_opt_value) String(rm9000) Value(35) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r9k) Value(33)
+Enum(mips_arch_opt_value) String(rm9k) Value(35)
EnumValue
-Enum(mips_arch_opt_value) String(4kc) Value(34) Canonical
+Enum(mips_arch_opt_value) String(9000) Value(35)
EnumValue
-Enum(mips_arch_opt_value) String(r4kc) Value(34)
+Enum(mips_arch_opt_value) String(9k) Value(35)
EnumValue
-Enum(mips_arch_opt_value) String(4km) Value(35) Canonical
+Enum(mips_arch_opt_value) String(r9000) Value(35)
EnumValue
-Enum(mips_arch_opt_value) String(r4km) Value(35)
+Enum(mips_arch_opt_value) String(r9k) Value(35)
EnumValue
-Enum(mips_arch_opt_value) String(4kp) Value(36) Canonical
+Enum(mips_arch_opt_value) String(4kc) Value(36) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r4kp) Value(36)
+Enum(mips_arch_opt_value) String(r4kc) Value(36)
EnumValue
-Enum(mips_arch_opt_value) String(4ksc) Value(37) Canonical
+Enum(mips_arch_opt_value) String(4km) Value(37) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r4ksc) Value(37)
+Enum(mips_arch_opt_value) String(r4km) Value(37)
EnumValue
-Enum(mips_arch_opt_value) String(m4k) Value(38) Canonical
+Enum(mips_arch_opt_value) String(4kp) Value(38) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(4kec) Value(39) Canonical
+Enum(mips_arch_opt_value) String(r4kp) Value(38)
EnumValue
-Enum(mips_arch_opt_value) String(r4kec) Value(39)
+Enum(mips_arch_opt_value) String(4ksc) Value(39) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(4kem) Value(40) Canonical
+Enum(mips_arch_opt_value) String(r4ksc) Value(39)
EnumValue
-Enum(mips_arch_opt_value) String(r4kem) Value(40)
+Enum(mips_arch_opt_value) String(m4k) Value(40) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(4kep) Value(41) Canonical
+Enum(mips_arch_opt_value) String(m14kc) Value(41) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r4kep) Value(41)
+Enum(mips_arch_opt_value) String(m14k) Value(42) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(4ksd) Value(42) Canonical
+Enum(mips_arch_opt_value) String(m14ke) Value(43) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r4ksd) Value(42)
+Enum(mips_arch_opt_value) String(m14kec) Value(44) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(24kc) Value(43) Canonical
+Enum(mips_arch_opt_value) String(4kec) Value(45) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r24kc) Value(43)
+Enum(mips_arch_opt_value) String(r4kec) Value(45)
EnumValue
-Enum(mips_arch_opt_value) String(24kf2_1) Value(44) Canonical
+Enum(mips_arch_opt_value) String(4kem) Value(46) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r24kf2_1) Value(44)
+Enum(mips_arch_opt_value) String(r4kem) Value(46)
EnumValue
-Enum(mips_arch_opt_value) String(24kf) Value(45) Canonical
+Enum(mips_arch_opt_value) String(4kep) Value(47) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r24kf) Value(45)
+Enum(mips_arch_opt_value) String(r4kep) Value(47)
EnumValue
-Enum(mips_arch_opt_value) String(24kf1_1) Value(46) Canonical
+Enum(mips_arch_opt_value) String(4ksd) Value(48) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r24kf1_1) Value(46)
+Enum(mips_arch_opt_value) String(r4ksd) Value(48)
EnumValue
-Enum(mips_arch_opt_value) String(24kfx) Value(47) Canonical
+Enum(mips_arch_opt_value) String(24kc) Value(49) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r24kfx) Value(47)
+Enum(mips_arch_opt_value) String(r24kc) Value(49)
EnumValue
-Enum(mips_arch_opt_value) String(24kx) Value(48) Canonical
+Enum(mips_arch_opt_value) String(24kf2_1) Value(50) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r24kx) Value(48)
+Enum(mips_arch_opt_value) String(r24kf2_1) Value(50)
EnumValue
-Enum(mips_arch_opt_value) String(24kec) Value(49) Canonical
+Enum(mips_arch_opt_value) String(24kf) Value(51) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r24kec) Value(49)
+Enum(mips_arch_opt_value) String(r24kf) Value(51)
EnumValue
-Enum(mips_arch_opt_value) String(24kef2_1) Value(50) Canonical
+Enum(mips_arch_opt_value) String(24kf1_1) Value(52) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r24kef2_1) Value(50)
+Enum(mips_arch_opt_value) String(r24kf1_1) Value(52)
EnumValue
-Enum(mips_arch_opt_value) String(24kef) Value(51) Canonical
+Enum(mips_arch_opt_value) String(24kfx) Value(53) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r24kef) Value(51)
+Enum(mips_arch_opt_value) String(r24kfx) Value(53)
EnumValue
-Enum(mips_arch_opt_value) String(24kef1_1) Value(52) Canonical
+Enum(mips_arch_opt_value) String(24kx) Value(54) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r24kef1_1) Value(52)
+Enum(mips_arch_opt_value) String(r24kx) Value(54)
EnumValue
-Enum(mips_arch_opt_value) String(24kefx) Value(53) Canonical
+Enum(mips_arch_opt_value) String(24kec) Value(55) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r24kefx) Value(53)
+Enum(mips_arch_opt_value) String(r24kec) Value(55)
EnumValue
-Enum(mips_arch_opt_value) String(24kex) Value(54) Canonical
+Enum(mips_arch_opt_value) String(24kef2_1) Value(56) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r24kex) Value(54)
+Enum(mips_arch_opt_value) String(r24kef2_1) Value(56)
EnumValue
-Enum(mips_arch_opt_value) String(34kc) Value(55) Canonical
+Enum(mips_arch_opt_value) String(24kef) Value(57) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r34kc) Value(55)
+Enum(mips_arch_opt_value) String(r24kef) Value(57)
EnumValue
-Enum(mips_arch_opt_value) String(34kf2_1) Value(56) Canonical
+Enum(mips_arch_opt_value) String(24kef1_1) Value(58) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r34kf2_1) Value(56)
+Enum(mips_arch_opt_value) String(r24kef1_1) Value(58)
EnumValue
-Enum(mips_arch_opt_value) String(34kf) Value(57) Canonical
+Enum(mips_arch_opt_value) String(24kefx) Value(59) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r34kf) Value(57)
+Enum(mips_arch_opt_value) String(r24kefx) Value(59)
EnumValue
-Enum(mips_arch_opt_value) String(34kf1_1) Value(58) Canonical
+Enum(mips_arch_opt_value) String(24kex) Value(60) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r34kf1_1) Value(58)
+Enum(mips_arch_opt_value) String(r24kex) Value(60)
EnumValue
-Enum(mips_arch_opt_value) String(34kfx) Value(59) Canonical
+Enum(mips_arch_opt_value) String(34kc) Value(61) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r34kfx) Value(59)
+Enum(mips_arch_opt_value) String(r34kc) Value(61)
EnumValue
-Enum(mips_arch_opt_value) String(34kx) Value(60) Canonical
+Enum(mips_arch_opt_value) String(34kf2_1) Value(62) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r34kx) Value(60)
+Enum(mips_arch_opt_value) String(r34kf2_1) Value(62)
EnumValue
-Enum(mips_arch_opt_value) String(74kc) Value(61) Canonical
+Enum(mips_arch_opt_value) String(34kf) Value(63) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r74kc) Value(61)
+Enum(mips_arch_opt_value) String(r34kf) Value(63)
EnumValue
-Enum(mips_arch_opt_value) String(74kf2_1) Value(62) Canonical
+Enum(mips_arch_opt_value) String(34kf1_1) Value(64) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r74kf2_1) Value(62)
+Enum(mips_arch_opt_value) String(r34kf1_1) Value(64)
EnumValue
-Enum(mips_arch_opt_value) String(74kf) Value(63) Canonical
+Enum(mips_arch_opt_value) String(34kfx) Value(65) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r74kf) Value(63)
+Enum(mips_arch_opt_value) String(r34kfx) Value(65)
EnumValue
-Enum(mips_arch_opt_value) String(74kf1_1) Value(64) Canonical
+Enum(mips_arch_opt_value) String(34kx) Value(66) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r74kf1_1) Value(64)
+Enum(mips_arch_opt_value) String(r34kx) Value(66)
EnumValue
-Enum(mips_arch_opt_value) String(74kfx) Value(65) Canonical
+Enum(mips_arch_opt_value) String(34kn) Value(67) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r74kfx) Value(65)
+Enum(mips_arch_opt_value) String(r34kn) Value(67)
EnumValue
-Enum(mips_arch_opt_value) String(74kx) Value(66) Canonical
+Enum(mips_arch_opt_value) String(74kc) Value(68) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r74kx) Value(66)
+Enum(mips_arch_opt_value) String(r74kc) Value(68)
EnumValue
-Enum(mips_arch_opt_value) String(74kf3_2) Value(67) Canonical
+Enum(mips_arch_opt_value) String(74kf2_1) Value(69) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r74kf3_2) Value(67)
+Enum(mips_arch_opt_value) String(r74kf2_1) Value(69)
EnumValue
-Enum(mips_arch_opt_value) String(1004kc) Value(68) Canonical
+Enum(mips_arch_opt_value) String(74kf) Value(70) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r1004kc) Value(68)
+Enum(mips_arch_opt_value) String(r74kf) Value(70)
EnumValue
-Enum(mips_arch_opt_value) String(1004kf2_1) Value(69) Canonical
+Enum(mips_arch_opt_value) String(74kf1_1) Value(71) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r1004kf2_1) Value(69)
+Enum(mips_arch_opt_value) String(r74kf1_1) Value(71)
EnumValue
-Enum(mips_arch_opt_value) String(1004kf) Value(70) Canonical
+Enum(mips_arch_opt_value) String(74kfx) Value(72) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r1004kf) Value(70)
+Enum(mips_arch_opt_value) String(r74kfx) Value(72)
EnumValue
-Enum(mips_arch_opt_value) String(1004kf1_1) Value(71) Canonical
+Enum(mips_arch_opt_value) String(74kx) Value(73) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r1004kf1_1) Value(71)
+Enum(mips_arch_opt_value) String(r74kx) Value(73)
EnumValue
-Enum(mips_arch_opt_value) String(5kc) Value(72) Canonical
+Enum(mips_arch_opt_value) String(74kf3_2) Value(74) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r5kc) Value(72)
+Enum(mips_arch_opt_value) String(r74kf3_2) Value(74)
EnumValue
-Enum(mips_arch_opt_value) String(5kf) Value(73) Canonical
+Enum(mips_arch_opt_value) String(1004kc) Value(75) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r5kf) Value(73)
+Enum(mips_arch_opt_value) String(r1004kc) Value(75)
EnumValue
-Enum(mips_arch_opt_value) String(20kc) Value(74) Canonical
+Enum(mips_arch_opt_value) String(1004kf2_1) Value(76) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(r20kc) Value(74)
+Enum(mips_arch_opt_value) String(r1004kf2_1) Value(76)
EnumValue
-Enum(mips_arch_opt_value) String(sb1) Value(75) Canonical
+Enum(mips_arch_opt_value) String(1004kf) Value(77) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(sb1a) Value(76) Canonical
+Enum(mips_arch_opt_value) String(r1004kf) Value(77)
EnumValue
-Enum(mips_arch_opt_value) String(sr71000) Value(77) Canonical
+Enum(mips_arch_opt_value) String(1004kf1_1) Value(78) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(sr71k) Value(77)
+Enum(mips_arch_opt_value) String(r1004kf1_1) Value(78)
EnumValue
-Enum(mips_arch_opt_value) String(xlr) Value(78) Canonical
+Enum(mips_arch_opt_value) String(5kc) Value(79) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(loongson3a) Value(79) Canonical
+Enum(mips_arch_opt_value) String(r5kc) Value(79)
EnumValue
-Enum(mips_arch_opt_value) String(octeon) Value(80) Canonical
+Enum(mips_arch_opt_value) String(5kf) Value(80) Canonical
EnumValue
-Enum(mips_arch_opt_value) String(octeon+) Value(81) Canonical
+Enum(mips_arch_opt_value) String(r5kf) Value(80)
EnumValue
-Enum(mips_arch_opt_value) String(octeon2) Value(82) Canonical
+Enum(mips_arch_opt_value) String(20kc) Value(81) Canonical
+
+EnumValue
+Enum(mips_arch_opt_value) String(r20kc) Value(81)
+
+EnumValue
+Enum(mips_arch_opt_value) String(sb1) Value(82) Canonical
+
+EnumValue
+Enum(mips_arch_opt_value) String(sb1a) Value(83) Canonical
+
+EnumValue
+Enum(mips_arch_opt_value) String(sr71000) Value(84) Canonical
+
+EnumValue
+Enum(mips_arch_opt_value) String(sr71k) Value(84)
+
+EnumValue
+Enum(mips_arch_opt_value) String(xlr) Value(85) Canonical
+
+EnumValue
+Enum(mips_arch_opt_value) String(loongson3a) Value(86) Canonical
+
+EnumValue
+Enum(mips_arch_opt_value) String(octeon) Value(87) Canonical
+
+EnumValue
+Enum(mips_arch_opt_value) String(octeon+) Value(88) Canonical
+
+EnumValue
+Enum(mips_arch_opt_value) String(octeon2) Value(89) Canonical
+
+EnumValue
+Enum(mips_arch_opt_value) String(xlp) Value(90) Canonical
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 02e757b5b4..143169bc15 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -1,8 +1,5 @@
/* Subroutines used for MIPS code generation.
- Copyright (C) 1989, 1990, 1991, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- 2011, 2012
- Free Software Foundation, Inc.
+ 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
@@ -37,6 +34,10 @@ along with GCC; see the file COPYING3. If not see
#include "recog.h"
#include "output.h"
#include "tree.h"
+#include "varasm.h"
+#include "stringpool.h"
+#include "stor-layout.h"
+#include "calls.h"
#include "function.h"
#include "expr.h"
#include "optabs.h"
@@ -46,19 +47,30 @@ along with GCC; see the file COPYING3. If not see
#include "tm_p.h"
#include "ggc.h"
#include "gstab.h"
-#include "hashtab.h"
+#include "hash-table.h"
#include "debug.h"
#include "target.h"
#include "target-def.h"
-#include "integrate.h"
+#include "common/common-target.h"
#include "langhooks.h"
-#include "cfglayout.h"
#include "sched-int.h"
+#include "pointer-set.h"
+#include "vec.h"
+#include "basic-block.h"
+#include "tree-ssa-alias.h"
+#include "internal-fn.h"
+#include "gimple-fold.h"
+#include "tree-eh.h"
+#include "gimple-expr.h"
+#include "is-a.h"
#include "gimple.h"
+#include "gimplify.h"
#include "bitmap.h"
#include "diagnostic.h"
#include "target-globals.h"
#include "opts.h"
+#include "tree-pass.h"
+#include "context.h"
/* True if X is an UNSPEC wrapper around a SYMBOL_REF or LABEL_REF. */
#define UNSPEC_ADDRESS_P(X) \
@@ -81,6 +93,9 @@ along with GCC; see the file COPYING3. If not see
preserve the maximum stack alignment. We therefore use a value
of 0x7ff0 in this case.
+ microMIPS LWM and SWM support 12-bit offsets (from -0x800 to 0x7ff),
+ so we use a maximum of 0x7f0 for TARGET_MICROMIPS.
+
MIPS16e SAVE and RESTORE instructions can adjust the stack pointer by
up to 0x7f8 bytes and can usually save or restore all the registers
that we need to save or restore. (Note that we can only use these
@@ -91,17 +106,17 @@ along with GCC; see the file COPYING3. If not see
to save and restore registers, and to allocate and deallocate the top
part of the frame. */
#define MIPS_MAX_FIRST_STACK_STEP \
- (!TARGET_MIPS16 ? 0x7ff0 \
- : GENERATE_MIPS16E_SAVE_RESTORE ? 0x7f8 \
+ (!TARGET_COMPRESSION ? 0x7ff0 \
+ : TARGET_MICROMIPS || GENERATE_MIPS16E_SAVE_RESTORE ? 0x7f8 \
: TARGET_64BIT ? 0x100 : 0x400)
/* True if INSN is a mips.md pattern or asm statement. */
+/* ??? This test exists through the compiler, perhaps it should be
+ moved to rtl.h. */
#define USEFUL_INSN_P(INSN) \
(NONDEBUG_INSN_P (INSN) \
&& GET_CODE (PATTERN (INSN)) != USE \
- && GET_CODE (PATTERN (INSN)) != CLOBBER \
- && GET_CODE (PATTERN (INSN)) != ADDR_VEC \
- && GET_CODE (PATTERN (INSN)) != ADDR_DIFF_VEC)
+ && GET_CODE (PATTERN (INSN)) != CLOBBER)
/* If INSN is a delayed branch sequence, return the first instruction
in the sequence, otherwise return INSN itself. */
@@ -260,12 +275,45 @@ enum mips_builtin_type {
enum mips_fp_condition {
MIPS_FP_CONDITIONS (DECLARE_MIPS_COND)
};
+#undef DECLARE_MIPS_COND
/* Index X provides the string representation of MIPS_FP_COND_<X>. */
#define STRINGIFY(X) #X
static const char *const mips_fp_conditions[] = {
MIPS_FP_CONDITIONS (STRINGIFY)
};
+#undef STRINGIFY
+
+/* A class used to control a comdat-style stub that we output in each
+ translation unit that needs it. */
+class mips_one_only_stub {
+public:
+ virtual ~mips_one_only_stub () {}
+
+ /* Return the name of the stub. */
+ virtual const char *get_name () = 0;
+
+ /* Output the body of the function to asm_out_file. */
+ virtual void output_body () = 0;
+};
+
+/* Tuning information that is automatically derived from other sources
+ (such as the scheduler). */
+static struct {
+ /* The architecture and tuning settings that this structure describes. */
+ enum processor arch;
+ enum processor tune;
+
+ /* True if this structure describes MIPS16 settings. */
+ bool mips16_p;
+
+ /* True if the structure has been initialized. */
+ bool initialized_p;
+
+ /* True if "MULT $0, $0" is preferable to "MTLO $0; MTHI $0"
+ when optimizing for speed. */
+ bool fast_mult_zero_zero_p;
+} mips_tuning_info;
/* Information about a function's frame layout. */
struct GTY(()) mips_frame_info {
@@ -323,6 +371,10 @@ struct GTY(()) mips_frame_info {
};
struct GTY(()) machine_function {
+ /* The next floating-point condition-code register to allocate
+ for ISA_HAS_8CC targets, relative to ST_REG_FIRST. */
+ unsigned int next_fcc;
+
/* The register returned by mips16_gp_pseudo_reg; see there for details. */
rtx mips16_gp_pseudo_rtx;
@@ -494,9 +546,6 @@ int num_source_filenames;
written anything yet. */
const char *current_function_file = "";
-/* A label counter used by PUT_SDB_BLOCK_START and PUT_SDB_BLOCK_END. */
-int sdb_label_count;
-
/* Arrays that map GCC register numbers to debugger register numbers. */
int mips_dbx_regno[FIRST_PSEUDO_REGISTER];
int mips_dwarf_regno[FIRST_PSEUDO_REGISTER];
@@ -539,20 +588,14 @@ int mips_isa;
/* The architecture selected by -mipsN, or null if -mipsN wasn't used. */
static const struct mips_cpu_info *mips_isa_option_info;
-#if TARGET_IRIX6
-/* On IRIX 6, intmax_t and uintmax_t depend on __c99, which is only
- available in C-family compilers. See irix6_c_common_override_options. */
-int long_intmax = -1;
-#endif
-
/* Which cost information to use. */
static const struct mips_rtx_cost_data *mips_cost;
/* The ambient target flags, excluding MASK_MIPS16. */
static int mips_base_target_flags;
-/* True if MIPS16 is the default mode. */
-bool mips_base_mips16;
+/* The default compression mode. */
+unsigned int mips_base_compression_flags;
/* The ambient values of other global variables. */
static int mips_base_schedule_insns; /* flag_schedule_insns */
@@ -598,8 +641,10 @@ struct target_globals *mips16_globals;
and returned from mips_sched_reorder2. */
static int cached_can_issue_more;
-/* True if the output uses __mips16_rdhwr. */
-static bool mips_need_mips16_rdhwr_p;
+/* The stubs for various MIPS16 support functions, if used. */
+static mips_one_only_stub *mips16_rdhwr_stub;
+static mips_one_only_stub *mips16_get_fcsr_stub;
+static mips_one_only_stub *mips16_set_fcsr_stub;
/* Index R is the smallest register class that contains register R. */
const enum reg_class mips_regno_to_class[FIRST_PSEUDO_REGISTER] = {
@@ -665,6 +710,9 @@ static const struct attribute_spec mips_attribute_table[] = {
code generation but don't carry other semantics. */
{ "mips16", 0, 0, true, false, false, NULL, false },
{ "nomips16", 0, 0, true, false, false, NULL, false },
+ { "micromips", 0, 0, true, false, false, NULL, false },
+ { "nomicromips", 0, 0, true, false, false, NULL, false },
+ { "nocompression", 0, 0, true, false, false, NULL, false },
/* Allow functions to be specified as interrupt handlers */
{ "interrupt", 0, 0, false, true, true, NULL, false },
{ "use_shadow_register_set", 0, 0, false, true, true, NULL, false },
@@ -971,6 +1019,9 @@ static const struct mips_rtx_cost_data
{ /* R4650 */
DEFAULT_COSTS
},
+ { /* R4700 */
+ DEFAULT_COSTS
+ },
{ /* R5000 */
COSTS_N_INSNS (6), /* fp_add */
COSTS_N_INSNS (4), /* fp_mult_sf */
@@ -1010,6 +1061,19 @@ static const struct mips_rtx_cost_data
1, /* branch_cost */
4 /* memory_latency */
},
+ { /* R5900 */
+ COSTS_N_INSNS (4), /* fp_add */
+ COSTS_N_INSNS (4), /* fp_mult_sf */
+ COSTS_N_INSNS (256), /* fp_mult_df */
+ COSTS_N_INSNS (8), /* fp_div_sf */
+ COSTS_N_INSNS (256), /* fp_div_df */
+ COSTS_N_INSNS (4), /* int_mult_si */
+ COSTS_N_INSNS (256), /* int_mult_di */
+ COSTS_N_INSNS (37), /* int_div_si */
+ COSTS_N_INSNS (256), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
{ /* R7000 */
/* The only costs that are changed here are
integer multiplication. */
@@ -1095,6 +1159,20 @@ static const struct mips_rtx_cost_data
COSTS_N_INSNS (72), /* int_div_di */
1, /* branch_cost */
4 /* memory_latency */
+ },
+ { /* XLP */
+ /* These costs are the same as 5KF above. */
+ COSTS_N_INSNS (4), /* fp_add */
+ COSTS_N_INSNS (4), /* fp_mult_sf */
+ COSTS_N_INSNS (5), /* fp_mult_df */
+ COSTS_N_INSNS (17), /* fp_div_sf */
+ COSTS_N_INSNS (32), /* fp_div_df */
+ COSTS_N_INSNS (4), /* int_mult_si */
+ COSTS_N_INSNS (11), /* int_mult_di */
+ COSTS_N_INSNS (36), /* int_div_si */
+ COSTS_N_INSNS (68), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
}
};
@@ -1141,10 +1219,11 @@ mflip_mips16_use_mips16_p (tree decl)
const char *name;
hashval_t hash;
void **slot;
+ bool base_is_mips16 = (mips_base_compression_flags & MASK_MIPS16) != 0;
/* Use the opposite of the command-line setting for anonymous decls. */
if (!DECL_NAME (decl))
- return !mips_base_mips16;
+ return !base_is_mips16;
if (!mflip_mips16_htab)
mflip_mips16_htab = htab_create_ggc (37, mflip_mips16_htab_hash,
@@ -1159,7 +1238,7 @@ mflip_mips16_use_mips16_p (tree decl)
mips16_flipper = !mips16_flipper;
entry = ggc_alloc_mflip_mips16_entry ();
entry->name = name;
- entry->mips16_p = mips16_flipper ? !mips_base_mips16 : mips_base_mips16;
+ entry->mips16_p = mips16_flipper ? !base_is_mips16 : base_is_mips16;
*slot = entry;
}
return entry->mips16_p;
@@ -1181,19 +1260,6 @@ mips_far_type_p (const_tree type)
|| lookup_attribute ("far", TYPE_ATTRIBUTES (type)) != NULL);
}
-/* Similar predicates for "mips16"/"nomips16" function attributes. */
-
-static bool
-mips_mips16_decl_p (const_tree decl)
-{
- return lookup_attribute ("mips16", DECL_ATTRIBUTES (decl)) != NULL;
-}
-
-static bool
-mips_nomips16_decl_p (const_tree decl)
-{
- return lookup_attribute ("nomips16", DECL_ATTRIBUTES (decl)) != NULL;
-}
/* Check if the interrupt attribute is set for a function. */
@@ -1231,12 +1297,52 @@ mips_use_debug_exception_return_p (tree type)
TYPE_ATTRIBUTES (type)) != NULL;
}
-/* Return true if function DECL is a MIPS16 function. Return the ambient
- setting if DECL is null. */
+/* Return the set of compression modes that are explicitly required
+ by the attributes in ATTRIBUTES. */
-static bool
-mips_use_mips16_mode_p (tree decl)
+static unsigned int
+mips_get_compress_on_flags (tree attributes)
{
+ unsigned int flags = 0;
+
+ if (lookup_attribute ("mips16", attributes) != NULL)
+ flags |= MASK_MIPS16;
+
+ if (lookup_attribute ("micromips", attributes) != NULL)
+ flags |= MASK_MICROMIPS;
+
+ return flags;
+}
+
+/* Return the set of compression modes that are explicitly forbidden
+ by the attributes in ATTRIBUTES. */
+
+static unsigned int
+mips_get_compress_off_flags (tree attributes)
+{
+ unsigned int flags = 0;
+
+ if (lookup_attribute ("nocompression", attributes) != NULL)
+ flags |= MASK_MIPS16 | MASK_MICROMIPS;
+
+ if (lookup_attribute ("nomips16", attributes) != NULL)
+ flags |= MASK_MIPS16;
+
+ if (lookup_attribute ("nomicromips", attributes) != NULL)
+ flags |= MASK_MICROMIPS;
+
+ return flags;
+}
+
+/* Return the compression mode that should be used for function DECL.
+ Return the ambient setting if DECL is null. */
+
+static unsigned int
+mips_get_compress_mode (tree decl)
+{
+ unsigned int flags, force_on;
+
+ flags = mips_base_compression_flags;
if (decl)
{
/* Nested functions must use the same frame pointer as their
@@ -1244,12 +1350,36 @@ mips_use_mips16_mode_p (tree decl)
tree parent = decl_function_context (decl);
if (parent)
decl = parent;
- if (mips_mips16_decl_p (decl))
- return true;
- if (mips_nomips16_decl_p (decl))
- return false;
+ force_on = mips_get_compress_on_flags (DECL_ATTRIBUTES (decl));
+ if (force_on)
+ return force_on;
+ flags &= ~mips_get_compress_off_flags (DECL_ATTRIBUTES (decl));
}
- return mips_base_mips16;
+ return flags;
+}
+
+/* Return the attribute name associated with MASK_MIPS16 and MASK_MICROMIPS
+ flags FLAGS. */
+
+static const char *
+mips_get_compress_on_name (unsigned int flags)
+{
+ if (flags == MASK_MIPS16)
+ return "mips16";
+ return "micromips";
+}
+
+/* Return the attribute name that forbids MASK_MIPS16 and MASK_MICROMIPS
+ flags FLAGS. */
+
+static const char *
+mips_get_compress_off_name (unsigned int flags)
+{
+ if (flags == MASK_MIPS16)
+ return "nomips16";
+ if (flags == MASK_MICROMIPS)
+ return "nomicromips";
+ return "nocompression";
}
/* Implement TARGET_COMP_TYPE_ATTRIBUTES. */
@@ -1271,37 +1401,50 @@ static void
mips_insert_attributes (tree decl, tree *attributes)
{
const char *name;
- bool mips16_p, nomips16_p;
+ unsigned int compression_flags, nocompression_flags;
/* Check for "mips16" and "nomips16" attributes. */
- mips16_p = lookup_attribute ("mips16", *attributes) != NULL;
- nomips16_p = lookup_attribute ("nomips16", *attributes) != NULL;
+ compression_flags = mips_get_compress_on_flags (*attributes);
+ nocompression_flags = mips_get_compress_off_flags (*attributes);
+
if (TREE_CODE (decl) != FUNCTION_DECL)
{
- if (mips16_p)
- error ("%qs attribute only applies to functions", "mips16");
- if (nomips16_p)
- error ("%qs attribute only applies to functions", "nomips16");
+ if (nocompression_flags)
+ error ("%qs attribute only applies to functions",
+ mips_get_compress_off_name (nocompression_flags));
+
+ if (compression_flags)
+ error ("%qs attribute only applies to functions",
+ mips_get_compress_on_name (nocompression_flags));
}
else
{
- mips16_p |= mips_mips16_decl_p (decl);
- nomips16_p |= mips_nomips16_decl_p (decl);
- if (mips16_p || nomips16_p)
- {
- /* DECL cannot be simultaneously "mips16" and "nomips16". */
- if (mips16_p && nomips16_p)
- error ("%qE cannot have both %<mips16%> and "
- "%<nomips16%> attributes",
- DECL_NAME (decl));
- }
- else if (TARGET_FLIP_MIPS16 && !DECL_ARTIFICIAL (decl))
+ compression_flags |= mips_get_compress_on_flags (DECL_ATTRIBUTES (decl));
+ nocompression_flags |=
+ mips_get_compress_off_flags (DECL_ATTRIBUTES (decl));
+
+ if (compression_flags && nocompression_flags)
+ error ("%qE cannot have both %qs and %qs attributes",
+ DECL_NAME (decl), mips_get_compress_on_name (compression_flags),
+ mips_get_compress_off_name (nocompression_flags));
+
+ if (compression_flags & MASK_MIPS16
+ && compression_flags & MASK_MICROMIPS)
+ error ("%qE cannot have both %qs and %qs attributes",
+ DECL_NAME (decl), "mips16", "micromips");
+
+ if (TARGET_FLIP_MIPS16
+ && !DECL_ARTIFICIAL (decl)
+ && compression_flags == 0
+ && nocompression_flags == 0)
{
/* Implement -mflip-mips16. If DECL has neither a "nomips16" nor a
"mips16" attribute, arbitrarily pick one. We must pick the same
setting for duplicate declarations of a function. */
name = mflip_mips16_use_mips16_p (decl) ? "mips16" : "nomips16";
*attributes = tree_cons (get_identifier (name), NULL, *attributes);
+ name = "nomicromips";
+ *attributes = tree_cons (get_identifier (name), NULL, *attributes);
}
}
}
@@ -1311,17 +1454,33 @@ mips_insert_attributes (tree decl, tree *attributes)
static tree
mips_merge_decl_attributes (tree olddecl, tree newdecl)
{
- /* The decls' "mips16" and "nomips16" attributes must match exactly. */
- if (mips_mips16_decl_p (olddecl) != mips_mips16_decl_p (newdecl))
+ unsigned int diff;
+
+ diff = (mips_get_compress_on_flags (DECL_ATTRIBUTES (olddecl))
+ ^ mips_get_compress_on_flags (DECL_ATTRIBUTES (newdecl)));
+ if (diff)
error ("%qE redeclared with conflicting %qs attributes",
- DECL_NAME (newdecl), "mips16");
- if (mips_nomips16_decl_p (olddecl) != mips_nomips16_decl_p (newdecl))
+ DECL_NAME (newdecl), mips_get_compress_on_name (diff));
+
+ diff = (mips_get_compress_off_flags (DECL_ATTRIBUTES (olddecl))
+ ^ mips_get_compress_off_flags (DECL_ATTRIBUTES (newdecl)));
+ if (diff)
error ("%qE redeclared with conflicting %qs attributes",
- DECL_NAME (newdecl), "nomips16");
+ DECL_NAME (newdecl), mips_get_compress_off_name (diff));
return merge_attributes (DECL_ATTRIBUTES (olddecl),
DECL_ATTRIBUTES (newdecl));
}
+
+/* Implement TARGET_CAN_INLINE_P. */
+
+static bool
+mips_can_inline_p (tree caller, tree callee)
+{
+ if (mips_get_compress_mode (callee) != mips_get_compress_mode (caller))
+ return false;
+ return default_target_can_inline_p (caller, callee);
+}
/* If X is a PLUS of a CONST_INT, return the two terms in *BASE_PTR
and *OFFSET_PTR. Return X in *BASE_PTR and 0 in *OFFSET_PTR otherwise. */
@@ -1464,6 +1623,87 @@ mips16_stub_function (const char *name)
SYMBOL_REF_FLAGS (x) |= (SYMBOL_FLAG_EXTERNAL | SYMBOL_FLAG_FUNCTION);
return x;
}
+
+/* Return a legitimate call address for STUB, given that STUB is a MIPS16
+ support function. */
+
+static rtx
+mips16_stub_call_address (mips_one_only_stub *stub)
+{
+ rtx fn = mips16_stub_function (stub->get_name ());
+ SYMBOL_REF_FLAGS (fn) |= SYMBOL_FLAG_LOCAL;
+ if (!call_insn_operand (fn, VOIDmode))
+ fn = force_reg (Pmode, fn);
+ return fn;
+}
+
+/* A stub for moving the thread pointer into TLS_GET_TP_REGNUM. */
+
+class mips16_rdhwr_one_only_stub : public mips_one_only_stub
+{
+ virtual const char *get_name ();
+ virtual void output_body ();
+};
+
+const char *
+mips16_rdhwr_one_only_stub::get_name ()
+{
+ return "__mips16_rdhwr";
+}
+
+void
+mips16_rdhwr_one_only_stub::output_body ()
+{
+ fprintf (asm_out_file,
+ "\t.set\tpush\n"
+ "\t.set\tmips32r2\n"
+ "\t.set\tnoreorder\n"
+ "\trdhwr\t$3,$29\n"
+ "\t.set\tpop\n"
+ "\tj\t$31\n");
+}
+
+/* A stub for moving the FCSR into GET_FCSR_REGNUM. */
+class mips16_get_fcsr_one_only_stub : public mips_one_only_stub
+{
+ virtual const char *get_name ();
+ virtual void output_body ();
+};
+
+const char *
+mips16_get_fcsr_one_only_stub::get_name ()
+{
+ return "__mips16_get_fcsr";
+}
+
+void
+mips16_get_fcsr_one_only_stub::output_body ()
+{
+ fprintf (asm_out_file,
+ "\tcfc1\t%s,$31\n"
+ "\tj\t$31\n", reg_names[GET_FCSR_REGNUM]);
+}
+
+/* A stub for moving SET_FCSR_REGNUM into the FCSR. */
+class mips16_set_fcsr_one_only_stub : public mips_one_only_stub
+{
+ virtual const char *get_name ();
+ virtual void output_body ();
+};
+
+const char *
+mips16_set_fcsr_one_only_stub::get_name ()
+{
+ return "__mips16_set_fcsr";
+}
+
+void
+mips16_set_fcsr_one_only_stub::output_body ()
+{
+ fprintf (asm_out_file,
+ "\tctc1\t%s,$31\n"
+ "\tj\t$31\n", reg_names[SET_FCSR_REGNUM]);
+}
/* Return true if symbols of type TYPE require a GOT access. */
@@ -1524,7 +1764,7 @@ mips16_local_function_p (const_rtx x)
return (GET_CODE (x) == SYMBOL_REF
&& SYMBOL_REF_LOCAL_P (x)
&& !SYMBOL_REF_EXTERNAL_P (x)
- && mips_use_mips16_mode_p (SYMBOL_REF_DECL (x)));
+ && (mips_get_compress_mode (SYMBOL_REF_DECL (x)) & MASK_MIPS16));
}
/* Return true if SYMBOL_REF X binds locally. */
@@ -1903,7 +2143,7 @@ mips_symbol_insns_1 (enum mips_symbol_type type, enum machine_mode mode)
values of mode MODE to or from addresses of type TYPE. Return 0 if
the given type of symbol is not valid in addresses.
- In both cases, treat extended MIPS16 instructions as two instructions. */
+ In both cases, instruction counts are based off BASE_INSN_LENGTH. */
static int
mips_symbol_insns (enum mips_symbol_type type, enum machine_mode mode)
@@ -2230,12 +2470,11 @@ mips16_unextended_reference_p (enum machine_mode mode, rtx base,
}
/* Return the number of instructions needed to load or store a value
- of mode MODE at address X. Return 0 if X isn't valid for MODE.
+ of mode MODE at address X, assuming that BASE_INSN_LENGTH is the
+ length of one instruction. Return 0 if X isn't valid for MODE.
Assume that multiword moves may need to be split into word moves
if MIGHT_SPLIT_P, otherwise assume that a single load or store is
- enough.
-
- For MIPS16 code, count extended instructions as two instructions. */
+ enough. */
int
mips_address_insns (rtx x, enum machine_mode mode, bool might_split_p)
@@ -2274,7 +2513,71 @@ mips_address_insns (rtx x, enum machine_mode mode, bool might_split_p)
return 0;
}
-/* Return the number of instructions needed to load constant X.
+/* Return true if X fits within an unsigned field of BITS bits that is
+ shifted left SHIFT bits before being used. */
+
+bool
+mips_unsigned_immediate_p (unsigned HOST_WIDE_INT x, int bits, int shift = 0)
+{
+ return (x & ((1 << shift) - 1)) == 0 && x < ((unsigned) 1 << (shift + bits));
+}
+
+/* Return true if X fits within a signed field of BITS bits that is
+ shifted left SHIFT bits before being used. */
+
+bool
+mips_signed_immediate_p (unsigned HOST_WIDE_INT x, int bits, int shift = 0)
+{
+ x += 1 << (bits + shift - 1);
+ return mips_unsigned_immediate_p (x, bits, shift);
+}
+
+/* Return true if X is legitimate for accessing values of mode MODE,
+ if it is based on a MIPS16 register, and if the offset satisfies
+ OFFSET_PREDICATE. */
+
+bool
+m16_based_address_p (rtx x, enum machine_mode mode,
+ insn_operand_predicate_fn offset_predicate)
+{
+ struct mips_address_info addr;
+
+ return (mips_classify_address (&addr, x, mode, false)
+ && addr.type == ADDRESS_REG
+ && M16_REG_P (REGNO (addr.reg))
+ && offset_predicate (addr.offset, mode));
+}
+
+/* Return true if X is a legitimate address that conforms to the requirements
+ for a microMIPS LWSP or SWSP insn. */
+
+bool
+lwsp_swsp_address_p (rtx x, enum machine_mode mode)
+{
+ struct mips_address_info addr;
+
+ return (mips_classify_address (&addr, x, mode, false)
+ && addr.type == ADDRESS_REG
+ && REGNO (addr.reg) == STACK_POINTER_REGNUM
+ && uw5_operand (addr.offset, mode));
+}
+
+/* Return true if X is a legitimate address with a 12-bit offset.
+ MODE is the mode of the value being accessed. */
+
+bool
+umips_12bit_offset_address_p (rtx x, enum machine_mode mode)
+{
+ struct mips_address_info addr;
+
+ return (mips_classify_address (&addr, x, mode, false)
+ && addr.type == ADDRESS_REG
+ && CONST_INT_P (addr.offset)
+ && UMIPS_12BIT_OFFSET_P (INTVAL (addr.offset)));
+}
+
+/* Return the number of instructions needed to load constant X,
+ assuming that BASE_INSN_LENGTH is the length of one instruction.
Return 0 if X isn't a valid constant. */
int
@@ -2357,7 +2660,8 @@ mips_const_insns (rtx x)
/* X is a doubleword constant that can be handled by splitting it into
two words and loading each word separately. Return the number of
- instructions required to do this. */
+ instructions required to do this, assuming that BASE_INSN_LENGTH
+ is the length of one instruction. */
int
mips_split_const_insns (rtx x)
@@ -2371,8 +2675,8 @@ mips_split_const_insns (rtx x)
}
/* Return the number of instructions needed to implement INSN,
- given that it loads from or stores to MEM. Count extended
- MIPS16 instructions as two instructions. */
+ given that it loads from or stores to MEM. Assume that
+ BASE_INSN_LENGTH is the length of one instruction. */
int
mips_load_store_insns (rtx mem, rtx insn)
@@ -2385,18 +2689,19 @@ mips_load_store_insns (rtx mem, rtx insn)
mode = GET_MODE (mem);
/* Try to prove that INSN does not need to be split. */
- might_split_p = true;
- if (GET_MODE_BITSIZE (mode) == 64)
+ might_split_p = GET_MODE_SIZE (mode) > UNITS_PER_WORD;
+ if (might_split_p)
{
set = single_set (insn);
- if (set && !mips_split_64bit_move_p (SET_DEST (set), SET_SRC (set)))
+ if (set && !mips_split_move_insn_p (SET_DEST (set), SET_SRC (set), insn))
might_split_p = false;
}
return mips_address_insns (XEXP (mem, 0), mode, might_split_p);
}
-/* Return the number of instructions needed for an integer division. */
+/* Return the number of instructions needed for an integer division,
+ assuming that BASE_INSN_LENGTH is the length of one instruction. */
int
mips_idiv_insns (void)
@@ -2431,6 +2736,18 @@ mips_emit_move (rtx dest, rtx src)
: emit_move_insn_1 (dest, src));
}
+/* Emit a move from SRC to DEST, splitting compound moves into individual
+ instructions. SPLIT_TYPE is the type of split to perform. */
+
+static void
+mips_emit_move_or_split (rtx dest, rtx src, enum mips_split_type split_type)
+{
+ if (mips_split_move_p (dest, src, split_type))
+ mips_split_move (dest, src, split_type);
+ else
+ mips_emit_move (dest, src);
+}
+
/* Emit an instruction of the form (set TARGET (CODE OP0)). */
static void
@@ -2557,14 +2874,14 @@ mips_unspec_address (rtx address, enum mips_symbol_type symbol_type)
/* If OP is an UNSPEC address, return the address to which it refers,
otherwise return OP itself. */
-static rtx
+rtx
mips_strip_unspec_address (rtx op)
{
rtx base, offset;
split_const (op, &base, &offset);
if (UNSPEC_ADDRESS_P (base))
- op = plus_constant (UNSPEC_ADDRESS (base), INTVAL (offset));
+ op = plus_constant (Pmode, UNSPEC_ADDRESS (base), INTVAL (offset));
return op;
}
@@ -2617,7 +2934,8 @@ mips16_gp_pseudo_reg (void)
scan = NEXT_INSN (scan);
insn = gen_load_const_gp (cfun->machine->mips16_gp_pseudo_rtx);
- emit_insn_after (insn, scan);
+ insn = emit_insn_after (insn, scan);
+ INSN_LOCATION (insn) = 0;
pop_topmost_sequence ();
}
@@ -2803,7 +3121,7 @@ mips_add_offset (rtx temp, rtx reg, HOST_WIDE_INT offset)
high = mips_force_temporary (temp, high);
reg = mips_force_temporary (temp, gen_rtx_PLUS (Pmode, high, reg));
}
- return plus_constant (reg, offset);
+ return plus_constant (Pmode, reg, offset);
}
/* The __tls_get_attr symbol. */
@@ -2843,19 +3161,16 @@ mips_call_tls_get_addr (rtx sym, enum mips_symbol_type type, rtx v0)
/* Return a pseudo register that contains the current thread pointer. */
-static rtx
-mips_get_tp (void)
+rtx
+mips_expand_thread_pointer (rtx tp)
{
- rtx tp, fn;
+ rtx fn;
- tp = gen_reg_rtx (Pmode);
if (TARGET_MIPS16)
{
- mips_need_mips16_rdhwr_p = true;
- fn = mips16_stub_function ("__mips16_rdhwr");
- SYMBOL_REF_FLAGS (fn) |= SYMBOL_FLAG_LOCAL;
- if (!call_insn_operand (fn, VOIDmode))
- fn = force_reg (Pmode, fn);
+ if (!mips16_rdhwr_stub)
+ mips16_rdhwr_stub = new mips16_rdhwr_one_only_stub ();
+ fn = mips16_stub_call_address (mips16_rdhwr_stub);
emit_insn (PMODE_INSN (gen_tls_get_tp_mips16, (tp, fn)));
}
else
@@ -2863,6 +3178,12 @@ mips_get_tp (void)
return tp;
}
+static rtx
+mips_get_tp (void)
+{
+ return mips_expand_thread_pointer (gen_reg_rtx (Pmode));
+}
+
/* Generate the code to access LOC, a thread-local SYMBOL_REF, and return
its address. The return value will be both a valid address and a valid
SET_SRC (either a REG or a LO_SUM). */
@@ -2942,6 +3263,31 @@ mips_legitimize_tls_address (rtx loc)
return dest;
}
+/* Implement "TARGET = __builtin_mips_get_fcsr ()" for MIPS16,
+ using a stub. */
+
+void
+mips16_expand_get_fcsr (rtx target)
+{
+ if (!mips16_get_fcsr_stub)
+ mips16_get_fcsr_stub = new mips16_get_fcsr_one_only_stub ();
+ rtx fn = mips16_stub_call_address (mips16_get_fcsr_stub);
+ emit_insn (PMODE_INSN (gen_mips_get_fcsr_mips16, (fn)));
+ emit_move_insn (target, gen_rtx_REG (SImode, GET_FCSR_REGNUM));
+}
+
+/* Implement __builtin_mips_set_fcsr (TARGET) for MIPS16, using a stub. */
+
+void
+mips16_expand_set_fcsr (rtx newval)
+{
+ if (!mips16_set_fcsr_stub)
+ mips16_set_fcsr_stub = new mips16_set_fcsr_one_only_stub ();
+ rtx fn = mips16_stub_call_address (mips16_set_fcsr_stub);
+ emit_move_insn (gen_rtx_REG (SImode, SET_FCSR_REGNUM), newval);
+ emit_insn (PMODE_INSN (gen_mips_set_fcsr_mips16, (fn)));
+}
+
/* If X is not a valid address for mode MODE, force it into a register. */
static rtx
@@ -3173,113 +3519,6 @@ mips_rewrite_small_data (rtx pattern)
return pattern;
}
-/* We need a lot of little routines to check the range of MIPS16 immediate
- operands. */
-
-static int
-m16_check_op (rtx op, int low, int high, int mask)
-{
- return (CONST_INT_P (op)
- && IN_RANGE (INTVAL (op), low, high)
- && (INTVAL (op) & mask) == 0);
-}
-
-int
-m16_uimm3_b (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return m16_check_op (op, 0x1, 0x8, 0);
-}
-
-int
-m16_simm4_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return m16_check_op (op, -0x8, 0x7, 0);
-}
-
-int
-m16_nsimm4_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return m16_check_op (op, -0x7, 0x8, 0);
-}
-
-int
-m16_simm5_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return m16_check_op (op, -0x10, 0xf, 0);
-}
-
-int
-m16_nsimm5_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return m16_check_op (op, -0xf, 0x10, 0);
-}
-
-int
-m16_uimm5_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return m16_check_op (op, -0x10 << 2, 0xf << 2, 3);
-}
-
-int
-m16_nuimm5_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return m16_check_op (op, -0xf << 2, 0x10 << 2, 3);
-}
-
-int
-m16_simm8_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return m16_check_op (op, -0x80, 0x7f, 0);
-}
-
-int
-m16_nsimm8_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return m16_check_op (op, -0x7f, 0x80, 0);
-}
-
-int
-m16_uimm8_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return m16_check_op (op, 0x0, 0xff, 0);
-}
-
-int
-m16_nuimm8_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return m16_check_op (op, -0xff, 0x0, 0);
-}
-
-int
-m16_uimm8_m1_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return m16_check_op (op, -0x1, 0xfe, 0);
-}
-
-int
-m16_uimm8_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return m16_check_op (op, 0x0, 0xff << 2, 3);
-}
-
-int
-m16_nuimm8_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return m16_check_op (op, -0xff << 2, 0x0, 3);
-}
-
-int
-m16_simm8_8 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return m16_check_op (op, -0x80 << 3, 0x7f << 3, 7);
-}
-
-int
-m16_nsimm8_8 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return m16_check_op (op, -0x7f << 3, 0x80 << 3, 7);
-}
-
/* The cost of loading values from the constant pool. It should be
larger than the cost of any constant we want to synthesize inline. */
#define CONSTANT_POOL_COST COSTS_N_INSNS (TARGET_MIPS16 ? 4 : 8)
@@ -3485,6 +3724,37 @@ mips_zero_extend_cost (enum machine_mode mode, rtx op)
return COSTS_N_INSNS (1);
}
+/* Return the cost of moving between two registers of mode MODE,
+ assuming that the move will be in pieces of at most UNITS bytes. */
+
+static int
+mips_set_reg_reg_piece_cost (enum machine_mode mode, unsigned int units)
+{
+ return COSTS_N_INSNS ((GET_MODE_SIZE (mode) + units - 1) / units);
+}
+
+/* Return the cost of moving between two registers of mode MODE. */
+
+static int
+mips_set_reg_reg_cost (enum machine_mode mode)
+{
+ switch (GET_MODE_CLASS (mode))
+ {
+ case MODE_CC:
+ return mips_set_reg_reg_piece_cost (mode, GET_MODE_SIZE (CCmode));
+
+ case MODE_FLOAT:
+ case MODE_COMPLEX_FLOAT:
+ case MODE_VECTOR_FLOAT:
+ if (TARGET_HARD_FLOAT)
+ return mips_set_reg_reg_piece_cost (mode, UNITS_PER_HWFPVALUE);
+ /* Fall through */
+
+ default:
+ return mips_set_reg_reg_piece_cost (mode, UNITS_PER_WORD);
+ }
+}
+
/* Implement TARGET_RTX_COSTS. */
static bool
@@ -3639,6 +3909,30 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+ set_src_cost (XEXP (x, 0), speed));
return true;
}
+ if (ISA_HAS_CINS && CONST_INT_P (XEXP (x, 1)))
+ {
+ rtx op = XEXP (x, 0);
+ if (GET_CODE (op) == ASHIFT
+ && CONST_INT_P (XEXP (op, 1))
+ && mask_low_and_shift_p (mode, XEXP (x, 1), XEXP (op, 1), 32))
+ {
+ *total = COSTS_N_INSNS (1) + set_src_cost (XEXP (op, 0), speed);
+ return true;
+ }
+ }
+ /* (AND (NOT op0) (NOT op1) is a nor operation that can be done in
+ a single instruction. */
+ if (!TARGET_MIPS16
+ && GET_CODE (XEXP (x, 0)) == NOT
+ && GET_CODE (XEXP (x, 1)) == NOT)
+ {
+ cost = GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 2 : 1;
+ *total = (COSTS_N_INSNS (cost)
+ + set_src_cost (XEXP (XEXP (x, 0), 0), speed)
+ + set_src_cost (XEXP (XEXP (x, 1), 0), speed));
+ return true;
+ }
+
/* Fall through. */
case IOR:
@@ -3700,7 +3994,7 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
case MINUS:
if (float_mode_p
- && (ISA_HAS_NMADD4_NMSUB4 (mode) || ISA_HAS_NMADD3_NMSUB3 (mode))
+ && (ISA_HAS_NMADD4_NMSUB4 || ISA_HAS_NMADD3_NMSUB3)
&& TARGET_FUSED_MADD
&& !HONOR_NANS (mode)
&& !HONOR_SIGNED_ZEROS (mode))
@@ -3733,7 +4027,7 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
{
/* If this is part of a MADD or MSUB, treat the PLUS as
being free. */
- if (ISA_HAS_FP4
+ if ((ISA_HAS_FP_MADD4_MSUB4 || ISA_HAS_FP_MADD3_MSUB3)
&& TARGET_FUSED_MADD
&& GET_CODE (XEXP (x, 0)) == MULT)
*total = 0;
@@ -3752,7 +4046,7 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
case NEG:
if (float_mode_p
- && (ISA_HAS_NMADD4_NMSUB4 (mode) || ISA_HAS_NMADD3_NMSUB3 (mode))
+ && (ISA_HAS_NMADD4_NMSUB4 || ISA_HAS_NMADD3_NMSUB3)
&& TARGET_FUSED_MADD
&& !HONOR_NANS (mode)
&& HONOR_SIGNED_ZEROS (mode))
@@ -3787,7 +4081,7 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
? mips_cost->int_mult_si * 3 + 6
: COSTS_N_INSNS (ISA_HAS_MUL3 ? 7 : 9));
else if (!speed)
- *total = (ISA_HAS_MUL3 ? 1 : 2);
+ *total = COSTS_N_INSNS (ISA_HAS_MUL3 ? 1 : 2) + 1;
else if (mode == DImode)
*total = mips_cost->int_mult_di;
else
@@ -3797,7 +4091,7 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
case DIV:
/* Check for a reciprocal. */
if (float_mode_p
- && ISA_HAS_FP4
+ && ISA_HAS_FP_RECIP_RSQRT (mode)
&& flag_unsafe_math_optimizations
&& XEXP (x, 0) == CONST1_RTX (mode))
{
@@ -3872,6 +4166,15 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
*total = mips_cost->fp_add;
return false;
+ case SET:
+ if (register_operand (SET_DEST (x), VOIDmode)
+ && reg_or_0_operand (SET_SRC (x), VOIDmode))
+ {
+ *total = mips_set_reg_reg_cost (GET_MODE (SET_DEST (x)));
+ return true;
+ }
+ return false;
+
default:
return false;
}
@@ -3880,9 +4183,11 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
/* Implement TARGET_ADDRESS_COST. */
static int
-mips_address_cost (rtx addr, bool speed ATTRIBUTE_UNUSED)
+mips_address_cost (rtx addr, enum machine_mode mode,
+ addr_space_t as ATTRIBUTE_UNUSED,
+ bool speed ATTRIBUTE_UNUSED)
{
- return mips_address_insns (addr, SImode, false);
+ return mips_address_insns (addr, mode, false);
}
/* Information about a single instruction in a multi-instruction
@@ -3899,12 +4204,8 @@ struct mips_multi_member {
};
typedef struct mips_multi_member mips_multi_member;
-/* Vector definitions for the above. */
-DEF_VEC_O(mips_multi_member);
-DEF_VEC_ALLOC_O(mips_multi_member, heap);
-
/* The instructions that make up the current multi-insn sequence. */
-static VEC (mips_multi_member, heap) *mips_multi_members;
+static vec<mips_multi_member> mips_multi_members;
/* How many instructions (as opposed to labels) are in the current
multi-insn sequence. */
@@ -3915,7 +4216,7 @@ static unsigned int mips_multi_num_insns;
static void
mips_multi_start (void)
{
- VEC_truncate (mips_multi_member, mips_multi_members, 0);
+ mips_multi_members.truncate (0);
mips_multi_num_insns = 0;
}
@@ -3924,7 +4225,8 @@ mips_multi_start (void)
static struct mips_multi_member *
mips_multi_add (void)
{
- return VEC_safe_push (mips_multi_member, heap, mips_multi_members, 0);
+ mips_multi_member empty;
+ return mips_multi_members.safe_push (empty);
}
/* Add a normal insn with the given asm format to the current multi-insn
@@ -3967,7 +4269,7 @@ mips_multi_add_label (const char *label)
static unsigned int
mips_multi_last_index (void)
{
- return VEC_length (mips_multi_member, mips_multi_members) - 1;
+ return mips_multi_members.length () - 1;
}
/* Add a copy of an existing instruction to the current multi-insn
@@ -3979,8 +4281,7 @@ mips_multi_copy_insn (unsigned int i)
struct mips_multi_member *member;
member = mips_multi_add ();
- memcpy (member, VEC_index (mips_multi_member, mips_multi_members, i),
- sizeof (*member));
+ memcpy (member, &mips_multi_members[i], sizeof (*member));
gcc_assert (!member->is_label_p);
}
@@ -3991,7 +4292,7 @@ mips_multi_copy_insn (unsigned int i)
static void
mips_multi_set_operand (unsigned int i, unsigned int op, rtx x)
{
- VEC_index (mips_multi_member, mips_multi_members, i)->operands[op] = x;
+ mips_multi_members[i].operands[op] = x;
}
/* Write out the asm code for the current multi-insn sequence. */
@@ -4002,7 +4303,7 @@ mips_multi_write (void)
struct mips_multi_member *member;
unsigned int i;
- FOR_EACH_VEC_ELT (mips_multi_member, mips_multi_members, i, member)
+ FOR_EACH_VEC_ELT (mips_multi_members, i, member)
if (member->is_label_p)
fprintf (asm_out_file, "%s\n", member->format);
else
@@ -4041,39 +4342,60 @@ mips_subword (rtx op, bool high_p)
return simplify_gen_subreg (word_mode, op, mode, byte);
}
-/* Return true if a 64-bit move from SRC to DEST should be split into two. */
+/* Return true if SRC should be moved into DEST using "MULT $0, $0".
+ SPLIT_TYPE is the condition under which moves should be split. */
+
+static bool
+mips_mult_move_p (rtx dest, rtx src, enum mips_split_type split_type)
+{
+ return ((split_type != SPLIT_FOR_SPEED
+ || mips_tuning_info.fast_mult_zero_zero_p)
+ && src == const0_rtx
+ && REG_P (dest)
+ && GET_MODE_SIZE (GET_MODE (dest)) == 2 * UNITS_PER_WORD
+ && (ISA_HAS_DSP_MULT
+ ? ACC_REG_P (REGNO (dest))
+ : MD_REG_P (REGNO (dest))));
+}
+
+/* Return true if a move from SRC to DEST should be split into two.
+ SPLIT_TYPE describes the split condition. */
bool
-mips_split_64bit_move_p (rtx dest, rtx src)
+mips_split_move_p (rtx dest, rtx src, enum mips_split_type split_type)
{
- if (TARGET_64BIT)
+ /* Check whether the move can be done using some variant of MULT $0,$0. */
+ if (mips_mult_move_p (dest, src, split_type))
return false;
/* FPR-to-FPR moves can be done in a single instruction, if they're
allowed at all. */
- if (FP_REG_RTX_P (src) && FP_REG_RTX_P (dest))
+ unsigned int size = GET_MODE_SIZE (GET_MODE (dest));
+ if (size == 8 && FP_REG_RTX_P (src) && FP_REG_RTX_P (dest))
return false;
/* Check for floating-point loads and stores. */
- if (ISA_HAS_LDC1_SDC1)
+ if (size == 8 && ISA_HAS_LDC1_SDC1)
{
if (FP_REG_RTX_P (dest) && MEM_P (src))
return false;
if (FP_REG_RTX_P (src) && MEM_P (dest))
return false;
}
- return true;
+
+ /* Otherwise split all multiword moves. */
+ return size > UNITS_PER_WORD;
}
-/* Split a doubleword move from SRC to DEST. On 32-bit targets,
- this function handles 64-bit moves for which mips_split_64bit_move_p
- holds. For 64-bit targets, this function handles 128-bit moves. */
+/* Split a move from SRC to DEST, given that mips_split_move_p holds.
+ SPLIT_TYPE describes the split condition. */
void
-mips_split_doubleword_move (rtx dest, rtx src)
+mips_split_move (rtx dest, rtx src, enum mips_split_type split_type)
{
rtx low_dest;
+ gcc_checking_assert (mips_split_move_p (dest, src, split_type));
if (FP_REG_RTX_P (dest) || FP_REG_RTX_P (src))
{
if (!TARGET_64BIT && GET_MODE (dest) == DImode)
@@ -4128,6 +4450,41 @@ mips_split_doubleword_move (rtx dest, rtx src)
}
}
}
+
+/* Return the split type for instruction INSN. */
+
+static enum mips_split_type
+mips_insn_split_type (rtx insn)
+{
+ basic_block bb = BLOCK_FOR_INSN (insn);
+ if (bb)
+ {
+ if (optimize_bb_for_speed_p (bb))
+ return SPLIT_FOR_SPEED;
+ else
+ return SPLIT_FOR_SIZE;
+ }
+ /* Once CFG information has been removed, we should trust the optimization
+ decisions made by previous passes and only split where necessary. */
+ return SPLIT_IF_NECESSARY;
+}
+
+/* Return true if a move from SRC to DEST in INSN should be split. */
+
+bool
+mips_split_move_insn_p (rtx dest, rtx src, rtx insn)
+{
+ return mips_split_move_p (dest, src, mips_insn_split_type (insn));
+}
+
+/* Split a move from SRC to DEST in INSN, given that mips_split_move_insn_p
+ holds. */
+
+void
+mips_split_move_insn (rtx dest, rtx src, rtx insn)
+{
+ mips_split_move (dest, src, mips_insn_split_type (insn));
+}
/* Return the appropriate instructions to move SRC into DEST. Assume
that SRC is operand 1 and DEST is operand 0. */
@@ -4145,7 +4502,7 @@ mips_output_move (rtx dest, rtx src)
mode = GET_MODE (dest);
dbl_p = (GET_MODE_SIZE (mode) == 8);
- if (dbl_p && mips_split_64bit_move_p (dest, src))
+ if (mips_split_move_p (dest, src, SPLIT_IF_NECESSARY))
return "#";
if ((src_code == REG && GP_REG_P (REGNO (src)))
@@ -4156,6 +4513,14 @@ mips_output_move (rtx dest, rtx src)
if (GP_REG_P (REGNO (dest)))
return "move\t%0,%z1";
+ if (mips_mult_move_p (dest, src, SPLIT_IF_NECESSARY))
+ {
+ if (ISA_HAS_DSP_MULT)
+ return "mult\t%q0,%.,%.";
+ else
+ return "mult\t%.,%.";
+ }
+
/* Moves to HI are handled by special .md insns. */
if (REGNO (dest) == LO_REGNUM)
return "mtlo\t%z1";
@@ -4224,9 +4589,6 @@ mips_output_move (rtx dest, rtx src)
retval[4] = COPNUM_AS_CHAR_FROM_REGNUM (REGNO (src));
return dbl_p ? retval : retval + 1;
}
-
- if (ST_REG_P (REGNO (src)) && ISA_HAS_8CC)
- return "lui\t%0,0x3f80\n\tmovf\t%0,%.,%1";
}
if (src_code == MEM)
@@ -4467,6 +4829,63 @@ mips_reversed_fp_cond (enum rtx_code *code)
}
}
+/* Allocate a floating-point condition-code register of mode MODE.
+
+ These condition code registers are used for certain kinds
+ of compound operation, such as compare and branches, vconds,
+ and built-in functions. At expand time, their use is entirely
+ controlled by MIPS-specific code and is entirely internal
+ to these compound operations.
+
+ We could (and did in the past) expose condition-code values
+ as pseudo registers and leave the register allocator to pick
+ appropriate registers. The problem is that it is not practically
+ possible for the rtl optimizers to guarantee that no spills will
+ be needed, even when AVOID_CCMODE_COPIES is defined. We would
+ therefore need spill and reload sequences to handle the worst case.
+
+ Although such sequences do exist, they are very expensive and are
+ not something we'd want to use. This is especially true of CCV2 and
+ CCV4, where all the shuffling would greatly outweigh whatever benefit
+ the vectorization itself provides.
+
+ The main benefit of having more than one condition-code register
+ is to allow the pipelining of operations, especially those involving
+ comparisons and conditional moves. We don't really expect the
+ registers to be live for long periods, and certainly never want
+ them to be live across calls.
+
+ Also, there should be no penalty attached to using all the available
+ registers. They are simply bits in the same underlying FPU control
+ register.
+
+ We therefore expose the hardware registers from the outset and use
+ a simple round-robin allocation scheme. */
+
+static rtx
+mips_allocate_fcc (enum machine_mode mode)
+{
+ unsigned int regno, count;
+
+ gcc_assert (TARGET_HARD_FLOAT && ISA_HAS_8CC);
+
+ if (mode == CCmode)
+ count = 1;
+ else if (mode == CCV2mode)
+ count = 2;
+ else if (mode == CCV4mode)
+ count = 4;
+ else
+ gcc_unreachable ();
+
+ cfun->machine->next_fcc += -cfun->machine->next_fcc & (count - 1);
+ if (cfun->machine->next_fcc > ST_REG_LAST - ST_REG_FIRST)
+ cfun->machine->next_fcc = 0;
+ regno = ST_REG_FIRST + cfun->machine->next_fcc;
+ cfun->machine->next_fcc += count;
+ return gen_rtx_REG (mode, regno);
+}
+
/* Convert a comparison into something that can be used in a branch or
conditional move. On entry, *OP0 and *OP1 are the values being
compared and *CODE is the code used to compare them.
@@ -4530,7 +4949,7 @@ mips_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1, bool need_eq_ne_p)
cmp_code = *code;
*code = mips_reversed_fp_cond (&cmp_code) ? EQ : NE;
*op0 = (ISA_HAS_8CC
- ? gen_reg_rtx (CCmode)
+ ? mips_allocate_fcc (CCmode)
: gen_rtx_REG (CCmode, FPSW_REGNUM));
*op1 = const0_rtx;
mips_emit_binary (cmp_code, *op0, cmp_op0, cmp_op1);
@@ -4597,7 +5016,7 @@ mips_expand_vcondv2sf (rtx dest, rtx true_src, rtx false_src,
bool reversed_p;
reversed_p = mips_reversed_fp_cond (&cond);
- cmp_result = gen_reg_rtx (CCV2mode);
+ cmp_result = mips_allocate_fcc (CCV2mode);
emit_insn (gen_scc_ps (cmp_result,
gen_rtx_fmt_ee (cond, VOIDmode, cmp_op0, cmp_op1)));
if (reversed_p)
@@ -4852,7 +5271,7 @@ mips_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
&& type != 0
&& TREE_CODE (type) == RECORD_TYPE
&& TYPE_SIZE_UNIT (type)
- && host_integerp (TYPE_SIZE_UNIT (type), 1))
+ && tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)))
{
tree field;
@@ -4861,7 +5280,7 @@ mips_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
if (TREE_CODE (field) == FIELD_DECL
&& SCALAR_FLOAT_TYPE_P (TREE_TYPE (field))
&& TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD
- && host_integerp (bit_position (field), 0)
+ && tree_fits_shwi_p (bit_position (field))
&& int_bit_position (field) % BITS_PER_WORD == 0)
break;
@@ -5387,7 +5806,7 @@ mips_setup_incoming_varargs (cumulative_args_t cum, enum machine_mode mode,
{
rtx ptr, mem;
- ptr = plus_constant (virtual_incoming_args_rtx,
+ ptr = plus_constant (Pmode, virtual_incoming_args_rtx,
REG_PARM_STACK_SPACE (cfun->decl)
- gp_saved * UNITS_PER_WORD);
mem = gen_frame_mem (BLKmode, ptr);
@@ -5416,7 +5835,7 @@ mips_setup_incoming_varargs (cumulative_args_t cum, enum machine_mode mode,
{
rtx ptr, mem;
- ptr = plus_constant (virtual_incoming_args_rtx, off);
+ ptr = plus_constant (Pmode, virtual_incoming_args_rtx, off);
mem = gen_frame_mem (mode, ptr);
set_mem_alias_set (mem, get_varargs_alias_set ());
mips_emit_move (mem, gen_rtx_REG (mode, FP_ARG_FIRST + i));
@@ -5497,9 +5916,6 @@ mips_build_builtin_va_list (void)
layout_type (record);
return record;
}
- else if (TARGET_IRIX6)
- /* On IRIX 6, this type is 'char *'. */
- return build_pointer_type (char_type_node);
else
/* Otherwise, we use 'void *'. */
return ptr_type_node;
@@ -5582,7 +5998,7 @@ mips_va_start (tree valist, rtx nextarg)
}
else
{
- nextarg = plus_constant (nextarg, -cfun->machine->varargs_size);
+ nextarg = plus_constant (Pmode, nextarg, -cfun->machine->varargs_size);
std_expand_builtin_va_start (valist, nextarg);
}
}
@@ -5876,6 +6292,13 @@ mips_start_function_definition (const char *name, bool mips16_p)
else
fprintf (asm_out_file, "\t.set\tnomips16\n");
+ if (TARGET_MICROMIPS)
+ fprintf (asm_out_file, "\t.set\tmicromips\n");
+#ifdef HAVE_GAS_MICROMIPS
+ else
+ fprintf (asm_out_file, "\t.set\tnomicromips\n");
+#endif
+
if (!flag_inhibit_size_directive)
{
fputs ("\t.ent\t", asm_out_file);
@@ -5902,25 +6325,24 @@ mips_end_function_definition (const char *name)
fputs ("\n", asm_out_file);
}
}
-
-/* Output a definition of the __mips16_rdhwr function. */
+
+/* If *STUB_PTR points to a stub, output a comdat-style definition for it,
+ then free *STUB_PTR. */
static void
-mips_output_mips16_rdhwr (void)
+mips_finish_stub (mips_one_only_stub **stub_ptr)
{
- const char *name;
+ mips_one_only_stub *stub = *stub_ptr;
+ if (!stub)
+ return;
- name = "__mips16_rdhwr";
+ const char *name = stub->get_name ();
mips_start_unique_function (name);
mips_start_function_definition (name, false);
- fprintf (asm_out_file,
- "\t.set\tpush\n"
- "\t.set\tmips32r2\n"
- "\t.set\tnoreorder\n"
- "\trdhwr\t$3,$29\n"
- "\t.set\tpop\n"
- "\tj\t$31\n");
+ stub->output_body ();
mips_end_function_definition (name);
+ delete stub;
+ *stub_ptr = 0;
}
/* Return true if calls to X can use R_MIPS_CALL* relocations. */
@@ -6612,7 +7034,7 @@ mips_expand_call (enum mips_call_type type, rtx result, rtx addr,
gcc_assert (!lazy_p && type == MIPS_CALL_NORMAL);
return insn;
}
- ;
+
orig_addr = addr;
if (!call_insn_operand (addr, VOIDmode))
{
@@ -6682,6 +7104,37 @@ mips_split_call (rtx insn, rtx call_pattern)
mips_restore_gp_from_cprestore_slot (gen_rtx_REG (Pmode, GP_ARG_FIRST + 2));
}
+/* Return true if a call to DECL may need to use JALX. */
+
+static bool
+mips_call_may_need_jalx_p (tree decl)
+{
+ /* If the current translation unit would use a different mode for DECL,
+ assume that the call needs JALX. */
+ if (mips_get_compress_mode (decl) != TARGET_COMPRESSION)
+ return true;
+
+ /* mips_get_compress_mode is always accurate for locally-binding
+ functions in the current translation unit. */
+ if (!DECL_EXTERNAL (decl) && targetm.binds_local_p (decl))
+ return false;
+
+ /* When -minterlink-compressed is in effect, assume that functions
+ could use a different encoding mode unless an attribute explicitly
+ tells us otherwise. */
+ if (TARGET_INTERLINK_COMPRESSED)
+ {
+ if (!TARGET_COMPRESSION
+ && mips_get_compress_off_flags (DECL_ATTRIBUTES (decl)) ==0)
+ return true;
+ if (TARGET_COMPRESSION
+ && mips_get_compress_on_flags (DECL_ATTRIBUTES (decl)) == 0)
+ return true;
+ }
+
+ return false;
+}
+
/* Implement TARGET_FUNCTION_OK_FOR_SIBCALL. */
static bool
@@ -6695,23 +7148,20 @@ mips_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
if (mips_interrupt_type_p (TREE_TYPE (current_function_decl)))
return false;
- /* We can't do a sibcall if the called function is a MIPS16 function
- because there is no direct "jx" instruction equivalent to "jalx" to
- switch the ISA mode. We only care about cases where the sibling
- and normal calls would both be direct. */
+ /* Direct Js are only possible to functions that use the same ISA encoding.
+ There is no JX counterpoart of JALX. */
if (decl
- && mips_use_mips16_mode_p (decl)
- && const_call_insn_operand (XEXP (DECL_RTL (decl), 0), VOIDmode))
+ && const_call_insn_operand (XEXP (DECL_RTL (decl), 0), VOIDmode)
+ && mips_call_may_need_jalx_p (decl))
return false;
- /* When -minterlink-mips16 is in effect, assume that non-locally-binding
- functions could be MIPS16 ones unless an attribute explicitly tells
- us otherwise. */
- if (TARGET_INTERLINK_MIPS16
- && decl
- && (DECL_EXTERNAL (decl) || !targetm.binds_local_p (decl))
- && !mips_nomips16_decl_p (decl)
- && const_call_insn_operand (XEXP (DECL_RTL (decl), 0), VOIDmode))
+ /* Sibling calls should not prevent lazy binding. Lazy-binding stubs
+ require $gp to be valid on entry, so sibcalls can only use stubs
+ if $gp is call-clobbered. */
+ if (decl
+ && TARGET_CALL_SAVED_GP
+ && !TARGET_ABICALLS_PIC0
+ && !targetm.binds_local_p (decl))
return false;
/* Otherwise OK. */
@@ -6872,7 +7322,8 @@ mips_block_move_straight (rtx dest, rtx src, HOST_WIDE_INT length)
else
{
rtx part = adjust_address (src, BLKmode, offset);
- if (!mips_expand_ext_as_unaligned_load (regs[i], part, bits, 0))
+ set_mem_size (part, delta);
+ if (!mips_expand_ext_as_unaligned_load (regs[i], part, bits, 0, 0))
gcc_unreachable ();
}
}
@@ -6884,6 +7335,7 @@ mips_block_move_straight (rtx dest, rtx src, HOST_WIDE_INT length)
else
{
rtx part = adjust_address (dest, BLKmode, offset);
+ set_mem_size (part, delta);
if (!mips_expand_ins_as_unaligned_store (part, regs[i], bits, 0))
gcc_unreachable ();
}
@@ -6949,8 +7401,8 @@ mips_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length,
mips_block_move_straight (dest, src, bytes_per_iter);
/* Move on to the next block. */
- mips_emit_move (src_reg, plus_constant (src_reg, bytes_per_iter));
- mips_emit_move (dest_reg, plus_constant (dest_reg, bytes_per_iter));
+ mips_emit_move (src_reg, plus_constant (Pmode, src_reg, bytes_per_iter));
+ mips_emit_move (dest_reg, plus_constant (Pmode, dest_reg, bytes_per_iter));
/* Emit the loop condition. */
test = gen_rtx_NE (VOIDmode, src_reg, final_src);
@@ -7135,10 +7587,8 @@ mips_expand_atomic_qihi (union mips_gen_fn_ptrs generator,
}
/* Return true if it is possible to use left/right accesses for a
- bitfield of WIDTH bits starting BITPOS bits into *OP. When
- returning true, update *OP, *LEFT and *RIGHT as follows:
-
- *OP is a BLKmode reference to the whole field.
+ bitfield of WIDTH bits starting BITPOS bits into BLKmode memory OP.
+ When returning true, update *LEFT and *RIGHT as follows:
*LEFT is a QImode reference to the first byte if big endian or
the last byte if little endian. This address can be used in the
@@ -7148,16 +7598,11 @@ mips_expand_atomic_qihi (union mips_gen_fn_ptrs generator,
can be used in the patterning right-side instruction. */
static bool
-mips_get_unaligned_mem (rtx *op, HOST_WIDE_INT width, HOST_WIDE_INT bitpos,
+mips_get_unaligned_mem (rtx op, HOST_WIDE_INT width, HOST_WIDE_INT bitpos,
rtx *left, rtx *right)
{
rtx first, last;
- /* Check that the operand really is a MEM. Not all the extv and
- extzv predicates are checked. */
- if (!MEM_P (*op))
- return false;
-
/* Check that the size is valid. */
if (width != 32 && (!TARGET_64BIT || width != 64))
return false;
@@ -7170,19 +7615,12 @@ mips_get_unaligned_mem (rtx *op, HOST_WIDE_INT width, HOST_WIDE_INT bitpos,
/* Reject aligned bitfields: we want to use a normal load or store
instead of a left/right pair. */
- if (MEM_ALIGN (*op) >= width)
+ if (MEM_ALIGN (op) >= width)
return false;
- /* Adjust *OP to refer to the whole field. This also has the effect
- of legitimizing *OP's address for BLKmode, possibly simplifying it. */
- *op = adjust_address (*op, BLKmode, 0);
- set_mem_size (*op, width / BITS_PER_UNIT);
-
- /* Get references to both ends of the field. We deliberately don't
- use the original QImode *OP for FIRST since the new BLKmode one
- might have a simpler address. */
- first = adjust_address (*op, QImode, 0);
- last = adjust_address (*op, QImode, width / BITS_PER_UNIT - 1);
+ /* Get references to both ends of the field. */
+ first = adjust_address (op, QImode, 0);
+ last = adjust_address (op, QImode, width / BITS_PER_UNIT - 1);
/* Allocate to LEFT and RIGHT according to endianness. LEFT should
correspond to the MSB and RIGHT to the LSB. */
@@ -7204,24 +7642,22 @@ mips_get_unaligned_mem (rtx *op, HOST_WIDE_INT width, HOST_WIDE_INT bitpos,
bool
mips_expand_ext_as_unaligned_load (rtx dest, rtx src, HOST_WIDE_INT width,
- HOST_WIDE_INT bitpos)
+ HOST_WIDE_INT bitpos, bool unsigned_p)
{
rtx left, right, temp;
+ rtx dest1 = NULL_RTX;
/* If TARGET_64BIT, the destination of a 32-bit "extz" or "extzv" will
- be a paradoxical word_mode subreg. This is the only case in which
- we allow the destination to be larger than the source. */
- if (GET_CODE (dest) == SUBREG
- && GET_MODE (dest) == DImode
- && GET_MODE (SUBREG_REG (dest)) == SImode)
- dest = SUBREG_REG (dest);
-
- /* After the above adjustment, the destination must be the same
- width as the source. */
- if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
- return false;
+ be a DImode, create a new temp and emit a zero extend at the end. */
+ if (GET_MODE (dest) == DImode
+ && REG_P (dest)
+ && GET_MODE_BITSIZE (SImode) == width)
+ {
+ dest1 = dest;
+ dest = gen_reg_rtx (SImode);
+ }
- if (!mips_get_unaligned_mem (&src, width, bitpos, &left, &right))
+ if (!mips_get_unaligned_mem (src, width, bitpos, &left, &right))
return false;
temp = gen_reg_rtx (GET_MODE (dest));
@@ -7235,6 +7671,16 @@ mips_expand_ext_as_unaligned_load (rtx dest, rtx src, HOST_WIDE_INT width,
emit_insn (gen_mov_lwl (temp, src, left));
emit_insn (gen_mov_lwr (dest, copy_rtx (src), right, temp));
}
+
+ /* If we were loading 32bits and the original register was DI then
+ sign/zero extend into the orignal dest. */
+ if (dest1)
+ {
+ if (unsigned_p)
+ emit_insn (gen_zero_extendsidi2 (dest1, dest));
+ else
+ emit_insn (gen_extendsidi2 (dest1, dest));
+ }
return true;
}
@@ -7253,7 +7699,7 @@ mips_expand_ins_as_unaligned_store (rtx dest, rtx src, HOST_WIDE_INT width,
rtx left, right;
enum machine_mode mode;
- if (!mips_get_unaligned_mem (&dest, width, bitpos, &left, &right))
+ if (!mips_get_unaligned_mem (dest, width, bitpos, &left, &right))
return false;
mode = mode_for_size (width, MODE_INT, 0);
@@ -7581,6 +8027,9 @@ mips_pop_asm_switch (struct mips_asm_switch *asm_switch)
'^' Print the name of the pic call-through register (t9 or $25).
'+' Print the name of the gp register (usually gp or $28).
'$' Print the name of the stack pointer register (sp or $29).
+ ':' Print "c" to use the compact version if the delay slot is a nop.
+ '!' Print "s" to use the short version if the delay slot contains a
+ 16-bit instruction.
See also mips_init_print_operand_pucnt. */
@@ -7664,6 +8113,21 @@ mips_print_operand_punctuation (FILE *file, int ch)
fputs (reg_names[STACK_POINTER_REGNUM], file);
break;
+ case ':':
+ /* When final_sequence is 0, the delay slot will be a nop. We can
+ use the compact version for microMIPS. */
+ if (final_sequence == 0)
+ putc ('c', file);
+ break;
+
+ case '!':
+ /* If the delay slot instruction is short, then use the
+ compact version. */
+ if (final_sequence == 0
+ || get_attr_length (XVECEXP (final_sequence, 0, 1)) == 2)
+ putc ('s', file);
+ break;
+
default:
gcc_unreachable ();
break;
@@ -7677,7 +8141,7 @@ mips_init_print_operand_punct (void)
{
const char *p;
- for (p = "()[]<>*#/?~.@^+$"; *p; p++)
+ for (p = "()[]<>*#/?~.@^+$:!"; *p; p++)
mips_print_operand_punct[(unsigned char) *p] = true;
}
@@ -7762,7 +8226,8 @@ mips_print_operand_punct_valid_p (unsigned char code)
'D' Print the second part of a double-word register or memory operand.
'L' Print the low-order register in a double-word register operand.
'M' Print high-order register in a double-word register operand.
- 'z' Print $0 if OP is zero, otherwise print OP normally. */
+ 'z' Print $0 if OP is zero, otherwise print OP normally.
+ 'b' Print the address of a memory operand, without offset. */
static void
mips_print_operand (FILE *file, rtx op, int letter)
@@ -7839,7 +8304,7 @@ mips_print_operand (FILE *file, rtx op, int letter)
case 't':
{
int truth = (code == NE) == (letter == 'T');
- fputc ("zfnt"[truth * 2 + (GET_MODE (op) == CCmode)], file);
+ fputc ("zfnt"[truth * 2 + ST_REG_P (REGNO (XEXP (op, 0)))], file);
}
break;
@@ -7890,7 +8355,12 @@ mips_print_operand (FILE *file, rtx op, int letter)
case MEM:
if (letter == 'D')
- output_address (plus_constant (XEXP (op, 0), 4));
+ output_address (plus_constant (Pmode, XEXP (op, 0), 4));
+ else if (letter == 'b')
+ {
+ gcc_assert (REG_P (XEXP (op, 0)));
+ mips_print_operand (file, XEXP (op, 0), 0);
+ }
else if (letter && letter != 'z')
output_operand_lossage ("invalid use of '%%%c'", letter);
else
@@ -8120,13 +8590,6 @@ mips_debugger_offset (rtx addr, HOST_WIDE_INT offset)
offset += cfun->machine->frame.hard_frame_pointer_offset;
}
- /* sdbout_parms does not want this to crash for unrecognized cases. */
-#if 0
- else if (reg != arg_pointer_rtx)
- fatal_insn ("mips_debugger_offset called with non stack/frame/arg pointer",
- addr);
-#endif
-
return offset;
}
@@ -8241,6 +8704,36 @@ mips_dwarf_register_span (rtx reg)
return NULL_RTX;
}
+/* DSP ALU can bypass data with no delays for the following pairs. */
+enum insn_code dspalu_bypass_table[][2] =
+{
+ {CODE_FOR_mips_addsc, CODE_FOR_mips_addwc},
+ {CODE_FOR_mips_cmpu_eq_qb, CODE_FOR_mips_pick_qb},
+ {CODE_FOR_mips_cmpu_lt_qb, CODE_FOR_mips_pick_qb},
+ {CODE_FOR_mips_cmpu_le_qb, CODE_FOR_mips_pick_qb},
+ {CODE_FOR_mips_cmp_eq_ph, CODE_FOR_mips_pick_ph},
+ {CODE_FOR_mips_cmp_lt_ph, CODE_FOR_mips_pick_ph},
+ {CODE_FOR_mips_cmp_le_ph, CODE_FOR_mips_pick_ph},
+ {CODE_FOR_mips_wrdsp, CODE_FOR_mips_insv}
+};
+
+int
+mips_dspalu_bypass_p (rtx out_insn, rtx in_insn)
+{
+ int i;
+ int num_bypass = ARRAY_SIZE (dspalu_bypass_table);
+ enum insn_code out_icode = (enum insn_code) INSN_CODE (out_insn);
+ enum insn_code in_icode = (enum insn_code) INSN_CODE (in_insn);
+
+ for (i = 0; i < num_bypass; i++)
+ {
+ if (out_icode == dspalu_bypass_table[i][0]
+ && in_icode == dspalu_bypass_table[i][1])
+ return true;
+ }
+
+ return false;
+}
/* Implement ASM_OUTPUT_ASCII. */
void
@@ -8467,50 +8960,52 @@ mips_file_start (void)
default_file_start ();
/* Generate a special section to describe the ABI switches used to
- produce the resultant binary. This is unnecessary on IRIX and
- causes unwanted warnings from the native linker. */
- if (!TARGET_IRIX6)
- {
- /* Record the ABI itself. Modern versions of binutils encode
- this information in the ELF header flags, but GDB needs the
- information in order to correctly debug binaries produced by
- older binutils. See the function mips_gdbarch_init in
- gdb/mips-tdep.c. */
- fprintf (asm_out_file, "\t.section .mdebug.%s\n\t.previous\n",
- mips_mdebug_abi_name ());
-
- /* There is no ELF header flag to distinguish long32 forms of the
- EABI from long64 forms. Emit a special section to help tools
- such as GDB. Do the same for o64, which is sometimes used with
- -mlong64. */
- if (mips_abi == ABI_EABI || mips_abi == ABI_O64)
- fprintf (asm_out_file, "\t.section .gcc_compiled_long%d\n"
- "\t.previous\n", TARGET_LONG64 ? 64 : 32);
+ produce the resultant binary. */
+
+ /* Record the ABI itself. Modern versions of binutils encode
+ this information in the ELF header flags, but GDB needs the
+ information in order to correctly debug binaries produced by
+ older binutils. See the function mips_gdbarch_init in
+ gdb/mips-tdep.c. */
+ fprintf (asm_out_file, "\t.section .mdebug.%s\n\t.previous\n",
+ mips_mdebug_abi_name ());
+
+ /* There is no ELF header flag to distinguish long32 forms of the
+ EABI from long64 forms. Emit a special section to help tools
+ such as GDB. Do the same for o64, which is sometimes used with
+ -mlong64. */
+ if (mips_abi == ABI_EABI || mips_abi == ABI_O64)
+ fprintf (asm_out_file, "\t.section .gcc_compiled_long%d\n"
+ "\t.previous\n", TARGET_LONG64 ? 64 : 32);
+
+ /* Record the NaN encoding. */
+ if (HAVE_AS_NAN || mips_nan != MIPS_IEEE_754_DEFAULT)
+ fprintf (asm_out_file, "\t.nan\t%s\n",
+ mips_nan == MIPS_IEEE_754_2008 ? "2008" : "legacy");
#ifdef HAVE_AS_GNU_ATTRIBUTE
- {
- int attr;
-
- /* No floating-point operations, -mno-float. */
- if (TARGET_NO_FLOAT)
- attr = 0;
- /* Soft-float code, -msoft-float. */
- else if (!TARGET_HARD_FLOAT_ABI)
- attr = 3;
- /* Single-float code, -msingle-float. */
- else if (!TARGET_DOUBLE_FLOAT)
- attr = 2;
- /* 64-bit FP registers on a 32-bit target, -mips32r2 -mfp64. */
- else if (!TARGET_64BIT && TARGET_FLOAT64)
- attr = 4;
- /* Regular FP code, FP regs same size as GP regs, -mdouble-float. */
- else
- attr = 1;
-
- fprintf (asm_out_file, "\t.gnu_attribute 4, %d\n", attr);
- }
+ {
+ int attr;
+
+ /* No floating-point operations, -mno-float. */
+ if (TARGET_NO_FLOAT)
+ attr = 0;
+ /* Soft-float code, -msoft-float. */
+ else if (!TARGET_HARD_FLOAT_ABI)
+ attr = 3;
+ /* Single-float code, -msingle-float. */
+ else if (!TARGET_DOUBLE_FLOAT)
+ attr = 2;
+ /* 64-bit FP registers on a 32-bit target, -mips32r2 -mfp64. */
+ else if (!TARGET_64BIT && TARGET_FLOAT64)
+ attr = 4;
+ /* Regular FP code, FP regs same size as GP regs, -mdouble-float. */
+ else
+ attr = 1;
+
+ fprintf (asm_out_file, "\t.gnu_attribute 4, %d\n", attr);
+ }
#endif
- }
/* If TARGET_ABICALLS, tell GAS to generate -KPIC code. */
if (TARGET_ABICALLS)
@@ -8531,8 +9026,9 @@ mips_file_start (void)
static void
mips_code_end (void)
{
- if (mips_need_mips16_rdhwr_p)
- mips_output_mips16_rdhwr ();
+ mips_finish_stub (&mips16_rdhwr_stub);
+ mips_finish_stub (&mips16_get_fcsr_stub);
+ mips_finish_stub (&mips16_set_fcsr_stub);
}
/* Make the last instruction frame-related and note that it performs
@@ -8759,7 +9255,8 @@ mips16e_save_restore_reg (bool restore_p, bool reg_parm_p,
{
rtx reg, mem;
- mem = gen_frame_mem (SImode, plus_constant (stack_pointer_rtx, offset));
+ mem = gen_frame_mem (SImode, plus_constant (Pmode, stack_pointer_rtx,
+ offset));
reg = gen_rtx_REG (SImode, regno);
if (restore_p)
{
@@ -8818,7 +9315,7 @@ mips16e_build_save_restore (bool restore_p, unsigned int *mask_ptr,
/* Add the stack pointer adjustment. */
set = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
- plus_constant (stack_pointer_rtx,
+ plus_constant (Pmode, stack_pointer_rtx,
restore_p ? size : -size));
RTX_FRAME_RELATED_P (set) = 1;
XVECEXP (pattern, 0, n++) = set;
@@ -9178,7 +9675,7 @@ mips_global_pointer (void)
/* If the global pointer is call-saved, try to use a call-clobbered
alternative. */
- if (TARGET_CALL_SAVED_GP && current_function_is_leaf)
+ if (TARGET_CALL_SAVED_GP && crtl->is_leaf)
for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
if (!df_regs_ever_live_p (regno)
&& call_really_used_regs[regno]
@@ -9405,7 +9902,7 @@ mips_cfun_might_clobber_call_saved_reg_p (unsigned int regno)
/* If REGNO is ordinarily call-clobbered, we must assume that any
called function could modify it. */
if (cfun->machine->interrupt_handler_p
- && !current_function_is_leaf
+ && !crtl->is_leaf
&& mips_interrupt_extra_call_saved_reg_p (regno))
return true;
@@ -9548,7 +10045,7 @@ mips_compute_frame_info (void)
slot. This area isn't needed in leaf functions, but if the
target-independent frame size is nonzero, we have already committed to
allocating these in STARTING_FRAME_OFFSET for !FRAME_GROWS_DOWNWARD. */
- if ((size == 0 || FRAME_GROWS_DOWNWARD) && current_function_is_leaf)
+ if ((size == 0 || FRAME_GROWS_DOWNWARD) && crtl->is_leaf)
{
/* The MIPS 3.0 linker does not like functions that dynamically
allocate the stack and have 0 for STACK_DYNAMIC_OFFSET, since it
@@ -9959,7 +10456,8 @@ mips_save_restore_reg (enum machine_mode mode, int regno,
{
rtx mem;
- mem = gen_frame_mem (mode, plus_constant (stack_pointer_rtx, offset));
+ mem = gen_frame_mem (mode, plus_constant (Pmode, stack_pointer_rtx,
+ offset));
fn (gen_rtx_REG (mode, regno), mem);
}
@@ -9991,6 +10489,126 @@ mips_for_each_saved_acc (HOST_WIDE_INT sp_offset, mips_save_restore_fn fn)
}
}
+/* Save register REG to MEM. Make the instruction frame-related. */
+
+static void
+mips_save_reg (rtx reg, rtx mem)
+{
+ if (GET_MODE (reg) == DFmode && !TARGET_FLOAT64)
+ {
+ rtx x1, x2;
+
+ mips_emit_move_or_split (mem, reg, SPLIT_IF_NECESSARY);
+
+ x1 = mips_frame_set (mips_subword (mem, false),
+ mips_subword (reg, false));
+ x2 = mips_frame_set (mips_subword (mem, true),
+ mips_subword (reg, true));
+ mips_set_frame_expr (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, x1, x2)));
+ }
+ else
+ mips_emit_save_slot_move (mem, reg, MIPS_PROLOGUE_TEMP (GET_MODE (reg)));
+}
+
+/* Capture the register combinations that are allowed in a SWM or LWM
+ instruction. The entries are ordered by number of registers set in
+ the mask. We also ignore the single register encodings because a
+ normal SW/LW is preferred. */
+
+static const unsigned int umips_swm_mask[17] = {
+ 0xc0ff0000, 0x80ff0000, 0x40ff0000, 0x807f0000,
+ 0x00ff0000, 0x803f0000, 0x007f0000, 0x801f0000,
+ 0x003f0000, 0x800f0000, 0x001f0000, 0x80070000,
+ 0x000f0000, 0x80030000, 0x00070000, 0x80010000,
+ 0x00030000
+};
+
+static const unsigned int umips_swm_encoding[17] = {
+ 25, 24, 9, 23, 8, 22, 7, 21, 6, 20, 5, 19, 4, 18, 3, 17, 2
+};
+
+/* Try to use a microMIPS LWM or SWM instruction to save or restore
+ as many GPRs in *MASK as possible. *OFFSET is the offset from the
+ stack pointer of the topmost save slot.
+
+ Remove from *MASK all registers that were handled using LWM and SWM.
+ Update *OFFSET so that it points to the first unused save slot. */
+
+static bool
+umips_build_save_restore (mips_save_restore_fn fn,
+ unsigned *mask, HOST_WIDE_INT *offset)
+{
+ int nregs;
+ unsigned int i, j;
+ rtx pattern, set, reg, mem;
+ HOST_WIDE_INT this_offset;
+ rtx this_base;
+
+ /* Try matching $16 to $31 (s0 to ra). */
+ for (i = 0; i < ARRAY_SIZE (umips_swm_mask); i++)
+ if ((*mask & 0xffff0000) == umips_swm_mask[i])
+ break;
+
+ if (i == ARRAY_SIZE (umips_swm_mask))
+ return false;
+
+ /* Get the offset of the lowest save slot. */
+ nregs = (umips_swm_encoding[i] & 0xf) + (umips_swm_encoding[i] >> 4);
+ this_offset = *offset - UNITS_PER_WORD * (nregs - 1);
+
+ /* LWM/SWM can only support offsets from -2048 to 2047. */
+ if (!UMIPS_12BIT_OFFSET_P (this_offset))
+ return false;
+
+ /* Create the final PARALLEL. */
+ pattern = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nregs));
+ this_base = stack_pointer_rtx;
+
+ /* For registers $16-$23 and $30. */
+ for (j = 0; j < (umips_swm_encoding[i] & 0xf); j++)
+ {
+ HOST_WIDE_INT offset = this_offset + j * UNITS_PER_WORD;
+ mem = gen_frame_mem (SImode, plus_constant (Pmode, this_base, offset));
+ unsigned int regno = (j != 8) ? 16 + j : 30;
+ *mask &= ~(1 << regno);
+ reg = gen_rtx_REG (SImode, regno);
+ if (fn == mips_save_reg)
+ set = mips_frame_set (mem, reg);
+ else
+ {
+ set = gen_rtx_SET (VOIDmode, reg, mem);
+ mips_add_cfa_restore (reg);
+ }
+ XVECEXP (pattern, 0, j) = set;
+ }
+
+ /* For register $31. */
+ if (umips_swm_encoding[i] >> 4)
+ {
+ HOST_WIDE_INT offset = this_offset + j * UNITS_PER_WORD;
+ *mask &= ~(1 << 31);
+ mem = gen_frame_mem (SImode, plus_constant (Pmode, this_base, offset));
+ reg = gen_rtx_REG (SImode, 31);
+ if (fn == mips_save_reg)
+ set = mips_frame_set (mem, reg);
+ else
+ {
+ set = gen_rtx_SET (VOIDmode, reg, mem);
+ mips_add_cfa_restore (reg);
+ }
+ XVECEXP (pattern, 0, j) = set;
+ }
+
+ pattern = emit_insn (pattern);
+ if (fn == mips_save_reg)
+ RTX_FRAME_RELATED_P (pattern) = 1;
+
+ /* Adjust the last offset. */
+ *offset -= UNITS_PER_WORD * nregs;
+
+ return true;
+}
+
/* Call FN for each register that is saved by the current function.
SP_OFFSET is the offset of the current stack pointer from the start
of the frame. */
@@ -10000,16 +10618,23 @@ mips_for_each_saved_gpr_and_fpr (HOST_WIDE_INT sp_offset,
mips_save_restore_fn fn)
{
enum machine_mode fpr_mode;
- HOST_WIDE_INT offset;
int regno;
+ const struct mips_frame_info *frame = &cfun->machine->frame;
+ HOST_WIDE_INT offset;
+ unsigned int mask;
/* Save registers starting from high to low. The debuggers prefer at least
the return register be stored at func+4, and also it allows us not to
need a nop in the epilogue if at least one register is reloaded in
addition to return address. */
- offset = cfun->machine->frame.gp_sp_offset - sp_offset;
+ offset = frame->gp_sp_offset - sp_offset;
+ mask = frame->mask;
+
+ if (TARGET_MICROMIPS)
+ umips_build_save_restore (fn, &mask, &offset);
+
for (regno = GP_REG_LAST; regno >= GP_REG_FIRST; regno--)
- if (BITSET_P (cfun->machine->frame.mask, regno - GP_REG_FIRST))
+ if (BITSET_P (mask, regno - GP_REG_FIRST))
{
/* Record the ra offset for use by mips_function_profiler. */
if (regno == RETURN_ADDR_REGNUM)
@@ -10135,11 +10760,6 @@ mips_output_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
{
const char *fnname;
-#ifdef SDB_DEBUGGING_INFO
- if (debug_info_level != DINFO_LEVEL_TERSE && write_symbols == SDB_DEBUG)
- SDB_OUTPUT_SOURCE_LINE (file, DECL_SOURCE_LINE (current_function_decl));
-#endif
-
/* In MIPS16 mode, we may need to generate a non-MIPS16 stub to handle
floating-point arguments. */
if (TARGET_MIPS16
@@ -10261,29 +10881,6 @@ mips_frame_barrier (void)
emit_clobber (gen_frame_mem (BLKmode, stack_pointer_rtx));
}
-/* Save register REG to MEM. Make the instruction frame-related. */
-
-static void
-mips_save_reg (rtx reg, rtx mem)
-{
- if (GET_MODE (reg) == DFmode && !TARGET_FLOAT64)
- {
- rtx x1, x2;
-
- if (mips_split_64bit_move_p (mem, reg))
- mips_split_doubleword_move (mem, reg);
- else
- mips_emit_move (mem, reg);
-
- x1 = mips_frame_set (mips_subword (mem, false),
- mips_subword (reg, false));
- x2 = mips_frame_set (mips_subword (mem, true),
- mips_subword (reg, true));
- mips_set_frame_expr (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, x1, x2)));
- }
- else
- mips_emit_save_slot_move (mem, reg, MIPS_PROLOGUE_TEMP (GET_MODE (reg)));
-}
/* The __gnu_local_gp symbol. */
@@ -10343,6 +10940,144 @@ mips_emit_loadgp (void)
emit_insn (gen_loadgp_blockage ());
}
+#define PROBE_INTERVAL (1 << STACK_CHECK_PROBE_INTERVAL_EXP)
+
+#if PROBE_INTERVAL > 32768
+#error Cannot use indexed addressing mode for stack probing
+#endif
+
+/* Emit code to probe a range of stack addresses from FIRST to FIRST+SIZE,
+ inclusive. These are offsets from the current stack pointer. */
+
+static void
+mips_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size)
+{
+ if (TARGET_MIPS16)
+ sorry ("-fstack-check=specific not implemented for MIPS16");
+
+ /* See if we have a constant small number of probes to generate. If so,
+ that's the easy case. */
+ if (first + size <= 32768)
+ {
+ HOST_WIDE_INT i;
+
+ /* Probe at FIRST + N * PROBE_INTERVAL for values of N from 1 until
+ it exceeds SIZE. If only one probe is needed, this will not
+ generate any code. Then probe at FIRST + SIZE. */
+ for (i = PROBE_INTERVAL; i < size; i += PROBE_INTERVAL)
+ emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
+ -(first + i)));
+
+ emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
+ -(first + size)));
+ }
+
+ /* Otherwise, do the same as above, but in a loop. Note that we must be
+ extra careful with variables wrapping around because we might be at
+ the very top (or the very bottom) of the address space and we have
+ to be able to handle this case properly; in particular, we use an
+ equality test for the loop condition. */
+ else
+ {
+ HOST_WIDE_INT rounded_size;
+ rtx r3 = MIPS_PROLOGUE_TEMP (Pmode);
+ rtx r12 = MIPS_PROLOGUE_TEMP2 (Pmode);
+
+ /* Sanity check for the addressing mode we're going to use. */
+ gcc_assert (first <= 32768);
+
+
+ /* Step 1: round SIZE to the previous multiple of the interval. */
+
+ rounded_size = size & -PROBE_INTERVAL;
+
+
+ /* Step 2: compute initial and final value of the loop counter. */
+
+ /* TEST_ADDR = SP + FIRST. */
+ emit_insn (gen_rtx_SET (VOIDmode, r3,
+ plus_constant (Pmode, stack_pointer_rtx,
+ -first)));
+
+ /* LAST_ADDR = SP + FIRST + ROUNDED_SIZE. */
+ if (rounded_size > 32768)
+ {
+ emit_move_insn (r12, GEN_INT (rounded_size));
+ emit_insn (gen_rtx_SET (VOIDmode, r12,
+ gen_rtx_MINUS (Pmode, r3, r12)));
+ }
+ else
+ emit_insn (gen_rtx_SET (VOIDmode, r12,
+ plus_constant (Pmode, r3, -rounded_size)));
+
+
+ /* Step 3: the loop
+
+ while (TEST_ADDR != LAST_ADDR)
+ {
+ TEST_ADDR = TEST_ADDR + PROBE_INTERVAL
+ probe at TEST_ADDR
+ }
+
+ probes at FIRST + N * PROBE_INTERVAL for values of N from 1
+ until it is equal to ROUNDED_SIZE. */
+
+ emit_insn (PMODE_INSN (gen_probe_stack_range, (r3, r3, r12)));
+
+
+ /* Step 4: probe at FIRST + SIZE if we cannot assert at compile-time
+ that SIZE is equal to ROUNDED_SIZE. */
+
+ if (size != rounded_size)
+ emit_stack_probe (plus_constant (Pmode, r12, rounded_size - size));
+ }
+
+ /* Make sure nothing is scheduled before we are done. */
+ emit_insn (gen_blockage ());
+}
+
+/* Probe a range of stack addresses from REG1 to REG2 inclusive. These are
+ absolute addresses. */
+
+const char *
+mips_output_probe_stack_range (rtx reg1, rtx reg2)
+{
+ static int labelno = 0;
+ char loop_lab[32], end_lab[32], tmp[64];
+ rtx xops[2];
+
+ ASM_GENERATE_INTERNAL_LABEL (loop_lab, "LPSRL", labelno);
+ ASM_GENERATE_INTERNAL_LABEL (end_lab, "LPSRE", labelno++);
+
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, loop_lab);
+
+ /* Jump to END_LAB if TEST_ADDR == LAST_ADDR. */
+ xops[0] = reg1;
+ xops[1] = reg2;
+ strcpy (tmp, "%(%<beq\t%0,%1,");
+ output_asm_insn (strcat (tmp, &end_lab[1]), xops);
+
+ /* TEST_ADDR = TEST_ADDR + PROBE_INTERVAL. */
+ xops[1] = GEN_INT (-PROBE_INTERVAL);
+ if (TARGET_64BIT && TARGET_LONG64)
+ output_asm_insn ("daddiu\t%0,%0,%1", xops);
+ else
+ output_asm_insn ("addiu\t%0,%0,%1", xops);
+
+ /* Probe at TEST_ADDR and branch. */
+ fprintf (asm_out_file, "\tb\t");
+ assemble_name_raw (asm_out_file, loop_lab);
+ fputc ('\n', asm_out_file);
+ if (TARGET_64BIT)
+ output_asm_insn ("sd\t$0,0(%0)%)", xops);
+ else
+ output_asm_insn ("sw\t$0,0(%0)%)", xops);
+
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, end_lab);
+
+ return "";
+}
+
/* A for_each_rtx callback. Stop the search if *X is a kernel register. */
static int
@@ -10382,6 +11117,18 @@ mips_expand_prologue (void)
if (flag_stack_usage_info)
current_function_static_stack_size = size;
+ if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
+ {
+ if (crtl->is_leaf && !cfun->calls_alloca)
+ {
+ if (size > PROBE_INTERVAL && size > STACK_CHECK_PROTECT)
+ mips_emit_probe_stack_range (STACK_CHECK_PROTECT,
+ size - STACK_CHECK_PROTECT);
+ }
+ else if (size > 0)
+ mips_emit_probe_stack_range (STACK_CHECK_PROTECT, size);
+ }
+
/* Save the registers. Allocate up to MIPS_MAX_FIRST_STACK_STEP
bytes beforehand; this is enough to cover the register save area
without going out of range. */
@@ -10454,7 +11201,7 @@ mips_expand_prologue (void)
{
/* Push EPC into its stack slot. */
mem = gen_frame_mem (word_mode,
- plus_constant (stack_pointer_rtx,
+ plus_constant (Pmode, stack_pointer_rtx,
offset));
mips_emit_move (mem, gen_rtx_REG (word_mode, K1_REG_NUM));
offset -= UNITS_PER_WORD;
@@ -10473,7 +11220,8 @@ mips_expand_prologue (void)
/* Push Status into its stack slot. */
mem = gen_frame_mem (word_mode,
- plus_constant (stack_pointer_rtx, offset));
+ plus_constant (Pmode, stack_pointer_rtx,
+ offset));
mips_emit_move (mem, gen_rtx_REG (word_mode, K1_REG_NUM));
offset -= UNITS_PER_WORD;
@@ -10545,7 +11293,7 @@ mips_expand_prologue (void)
/* Describe the combined effect of the previous instructions. */
mips_set_frame_expr
(gen_rtx_SET (VOIDmode, stack_pointer_rtx,
- plus_constant (stack_pointer_rtx, -size)));
+ plus_constant (Pmode, stack_pointer_rtx, -size)));
}
mips_frame_barrier ();
}
@@ -10576,7 +11324,7 @@ mips_expand_prologue (void)
MIPS_PROLOGUE_TEMP (Pmode)));
mips_set_frame_expr
(gen_rtx_SET (VOIDmode, hard_frame_pointer_rtx,
- plus_constant (stack_pointer_rtx, offset)));
+ plus_constant (Pmode, stack_pointer_rtx, offset)));
}
}
@@ -10589,7 +11337,7 @@ mips_expand_prologue (void)
HOST_WIDE_INT offset;
mips_get_cprestore_base_and_offset (&base, &offset, false);
- mem = gen_frame_mem (Pmode, plus_constant (base, offset));
+ mem = gen_frame_mem (Pmode, plus_constant (Pmode, base, offset));
gp = TARGET_MIPS16 ? MIPS16_PIC_TEMP : pic_offset_table_rtx;
temp = (SMALL_OPERAND (offset)
? gen_rtx_SCRATCH (Pmode)
@@ -10598,7 +11346,7 @@ mips_expand_prologue (void)
(mem, GEN_INT (offset), gp, temp)));
mips_get_cprestore_base_and_offset (&base, &offset, true);
- mem = gen_frame_mem (Pmode, plus_constant (base, offset));
+ mem = gen_frame_mem (Pmode, plus_constant (Pmode, base, offset));
emit_insn (PMODE_INSN (gen_use_cprestore, (mem)));
}
@@ -10654,7 +11402,7 @@ mips_epilogue_set_cfa (rtx reg, HOST_WIDE_INT offset)
{
RTX_FRAME_RELATED_P (insn) = 1;
REG_NOTES (insn) = alloc_reg_note (REG_CFA_DEF_CFA,
- plus_constant (reg, offset),
+ plus_constant (Pmode, reg, offset),
REG_NOTES (insn));
mips_epilogue.cfa_reg = reg;
mips_epilogue.cfa_offset = offset;
@@ -10744,6 +11492,7 @@ mips_expand_epilogue (bool sibcall_p)
const struct mips_frame_info *frame;
HOST_WIDE_INT step1, step2;
rtx base, adjust, insn;
+ bool use_jraddiusp_p = false;
if (!sibcall_p && mips_can_use_return_insn ())
{
@@ -10843,7 +11592,8 @@ mips_expand_epilogue (bool sibcall_p)
{
/* Restore the original EPC. */
mem = gen_frame_mem (word_mode,
- plus_constant (stack_pointer_rtx, offset));
+ plus_constant (Pmode, stack_pointer_rtx,
+ offset));
mips_emit_move (gen_rtx_REG (word_mode, K0_REG_NUM), mem);
offset -= UNITS_PER_WORD;
@@ -10854,11 +11604,12 @@ mips_expand_epilogue (bool sibcall_p)
/* Restore the original Status. */
mem = gen_frame_mem (word_mode,
- plus_constant (stack_pointer_rtx, offset));
+ plus_constant (Pmode, stack_pointer_rtx,
+ offset));
mips_emit_move (gen_rtx_REG (word_mode, K0_REG_NUM), mem);
offset -= UNITS_PER_WORD;
- /* If we don't use shoadow register set, we need to update SP. */
+ /* If we don't use shadow register set, we need to update SP. */
if (!cfun->machine->use_shadow_register_set_p)
mips_deallocate_stack (stack_pointer_rtx, GEN_INT (step2), 0);
else
@@ -10869,11 +11620,19 @@ mips_expand_epilogue (bool sibcall_p)
emit_insn (gen_cop0_move (gen_rtx_REG (SImode, COP0_STATUS_REG_NUM),
gen_rtx_REG (SImode, K0_REG_NUM)));
}
+ else if (TARGET_MICROMIPS
+ && !crtl->calls_eh_return
+ && !sibcall_p
+ && step2 > 0
+ && mips_unsigned_immediate_p (step2, 5, 2))
+ use_jraddiusp_p = true;
else
/* Deallocate the final bit of the frame. */
mips_deallocate_stack (stack_pointer_rtx, GEN_INT (step2), 0);
}
- gcc_assert (!mips_epilogue.cfa_restores);
+
+ if (!use_jraddiusp_p)
+ gcc_assert (!mips_epilogue.cfa_restores);
/* Add in the __builtin_eh_return stack adjustment. We need to
use a temporary in MIPS16 code. */
@@ -10923,12 +11682,16 @@ mips_expand_epilogue (bool sibcall_p)
rtx reg = gen_rtx_REG (Pmode, GP_REG_FIRST + 7);
pat = gen_return_internal (reg);
}
+ else if (use_jraddiusp_p)
+ pat = gen_jraddiusp (GEN_INT (step2));
else
{
rtx reg = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
pat = gen_simple_return_internal (reg);
}
emit_jump_insn (pat);
+ if (use_jraddiusp_p)
+ mips_epilogue_set_cfa (stack_pointer_rtx, step2);
}
}
@@ -10993,14 +11756,7 @@ mips_hard_regno_mode_ok_p (unsigned int regno, enum machine_mode mode)
&& (regno - ST_REG_FIRST) % 4 == 0);
if (mode == CCmode)
- {
- if (!ISA_HAS_8CC)
- return regno == FPSW_REGNUM;
-
- return (ST_REG_P (regno)
- || GP_REG_P (regno)
- || FP_REG_P (regno));
- }
+ return ISA_HAS_8CC ? ST_REG_P (regno) : regno == FPSW_REGNUM;
size = GET_MODE_SIZE (mode);
mclass = GET_MODE_CLASS (mode);
@@ -11012,10 +11768,6 @@ mips_hard_regno_mode_ok_p (unsigned int regno, enum machine_mode mode)
&& (((regno - FP_REG_FIRST) % MAX_FPRS_PER_FMT) == 0
|| (MIN_FPRS_PER_FMT == 1 && size <= UNITS_PER_FPREG)))
{
- /* Allow TFmode for CCmode reloads. */
- if (mode == TFmode && ISA_HAS_8CC)
- return true;
-
/* Allow 64-bit vector modes for Loongson-2E/2F. */
if (TARGET_LOONGSON_VECTORS
&& (mode == V2SImode
@@ -11252,6 +12004,7 @@ mips_move_to_gpr_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
{
switch (from)
{
+ case M16_REGS:
case GENERAL_REGS:
/* A MIPS16 MOVE instruction, or a non-MIPS16 MOVE macro. */
return 2;
@@ -11288,6 +12041,7 @@ mips_move_from_gpr_cost (enum machine_mode mode, reg_class_t to)
{
switch (to)
{
+ case M16_REGS:
case GENERAL_REGS:
/* A MIPS16 MOVE instruction, or a non-MIPS16 MOVE macro. */
return 2;
@@ -11689,6 +12443,7 @@ mips_adjust_insn_length (rtx insn, int length)
/* mips.md uses MAX_PIC_BRANCH_LENGTH as a placeholder for the length
of a PIC long-branch sequence. Substitute the correct value. */
if (length == MAX_PIC_BRANCH_LENGTH
+ && JUMP_P (insn)
&& INSN_CODE (insn) >= 0
&& get_attr_type (insn) == TYPE_BRANCH)
{
@@ -11696,39 +12451,37 @@ mips_adjust_insn_length (rtx insn, int length)
is a conditional branch. */
length = simplejump_p (insn) ? 0 : 8;
- /* Load the label into $AT and jump to it. Ignore the delay
- slot of the jump. */
- length += 4 * mips_load_label_num_insns() + 4;
+ /* Add the size of a load into $AT. */
+ length += BASE_INSN_LENGTH * mips_load_label_num_insns ();
+
+ /* Add the length of an indirect jump, ignoring the delay slot. */
+ length += TARGET_COMPRESSION ? 2 : 4;
}
/* A unconditional jump has an unfilled delay slot if it is not part
of a sequence. A conditional jump normally has a delay slot, but
does not on MIPS16. */
if (CALL_P (insn) || (TARGET_MIPS16 ? simplejump_p (insn) : JUMP_P (insn)))
- length += 4;
+ length += TARGET_MIPS16 ? 2 : 4;
/* See how many nops might be needed to avoid hardware hazards. */
- if (!cfun->machine->ignore_hazard_length_p && INSN_CODE (insn) >= 0)
+ if (!cfun->machine->ignore_hazard_length_p
+ && INSN_P (insn)
+ && INSN_CODE (insn) >= 0)
switch (get_attr_hazard (insn))
{
case HAZARD_NONE:
break;
case HAZARD_DELAY:
- length += 4;
+ length += NOP_INSN_LENGTH;
break;
case HAZARD_HILO:
- length += 8;
+ length += NOP_INSN_LENGTH * 2;
break;
}
- /* In order to make it easier to share MIPS16 and non-MIPS16 patterns,
- the .md file length attributes are 4-based for both modes.
- Adjust the MIPS16 ones here. */
- if (TARGET_MIPS16)
- length /= 2;
-
return length;
}
@@ -11865,7 +12618,10 @@ mips_start_ll_sc_sync_block (void)
if (!ISA_HAS_LL_SC)
{
output_asm_insn (".set\tpush", 0);
- output_asm_insn (".set\tmips2", 0);
+ if (TARGET_64BIT)
+ output_asm_insn (".set\tmips3", 0);
+ else
+ output_asm_insn (".set\tmips2", 0);
}
}
@@ -11962,11 +12718,13 @@ static void
mips_process_sync_loop (rtx insn, rtx *operands)
{
rtx at, mem, oldval, newval, inclusive_mask, exclusive_mask;
- rtx required_oldval, insn1_op2, tmp1, tmp2, tmp3;
+ rtx required_oldval, insn1_op2, tmp1, tmp2, tmp3, cmp;
unsigned int tmp3_insn;
enum attr_sync_insn1 insn1;
enum attr_sync_insn2 insn2;
bool is_64bit_p;
+ int memmodel_attr;
+ enum memmodel model;
/* Read an operand from the sync_WHAT attribute and store it in
variable WHAT. DEFAULT is the default value if no attribute
@@ -11983,6 +12741,7 @@ mips_process_sync_loop (rtx insn, rtx *operands)
/* Read the other attributes. */
at = gen_rtx_REG (GET_MODE (mem), AT_REGNUM);
READ_OPERAND (oldval, at);
+ READ_OPERAND (cmp, 0);
READ_OPERAND (newval, at);
READ_OPERAND (inclusive_mask, 0);
READ_OPERAND (exclusive_mask, 0);
@@ -11991,10 +12750,27 @@ mips_process_sync_loop (rtx insn, rtx *operands)
insn1 = get_attr_sync_insn1 (insn);
insn2 = get_attr_sync_insn2 (insn);
+ /* Don't bother setting CMP result that is never used. */
+ if (cmp && find_reg_note (insn, REG_UNUSED, cmp))
+ cmp = 0;
+
+ memmodel_attr = get_attr_sync_memmodel (insn);
+ switch (memmodel_attr)
+ {
+ case 10:
+ model = MEMMODEL_ACQ_REL;
+ break;
+ case 11:
+ model = MEMMODEL_ACQUIRE;
+ break;
+ default:
+ model = (enum memmodel) INTVAL (operands[memmodel_attr]);
+ }
+
mips_multi_start ();
/* Output the release side of the memory barrier. */
- if (get_attr_sync_release_barrier (insn) == SYNC_RELEASE_BARRIER_YES)
+ if (need_atomic_barrier_p (model, true))
{
if (required_oldval == 0 && TARGET_OCTEON)
{
@@ -12032,6 +12808,10 @@ mips_process_sync_loop (rtx insn, rtx *operands)
tmp1 = at;
}
mips_multi_add_insn ("bne\t%0,%z1,2f", tmp1, required_oldval, NULL);
+
+ /* CMP = 0 [delay slot]. */
+ if (cmp)
+ mips_multi_add_insn ("li\t%0,0", cmp, NULL);
}
/* $TMP1 = OLDVAL & EXCLUSIVE_MASK. */
@@ -12095,11 +12875,15 @@ mips_process_sync_loop (rtx insn, rtx *operands)
mips_multi_copy_insn (tmp3_insn);
mips_multi_set_operand (mips_multi_last_index (), 0, newval);
}
- else
+ else if (!(required_oldval && cmp))
mips_multi_add_insn ("nop", NULL);
+ /* CMP = 1 -- either standalone or in a delay slot. */
+ if (required_oldval && cmp)
+ mips_multi_add_insn ("li\t%0,1", cmp, NULL);
+
/* Output the acquire side of the memory barrier. */
- if (TARGET_SYNC_AFTER_SC)
+ if (TARGET_SYNC_AFTER_SC && need_atomic_barrier_p (model, false))
mips_multi_add_insn ("sync", NULL);
/* Output the exit label, if needed. */
@@ -12281,25 +13065,24 @@ mips_output_division (const char *division, rtx *operands)
bool
mips_linked_madd_p (rtx out_insn, rtx in_insn)
{
- rtx x;
+ enum attr_accum_in accum_in;
+ int accum_in_opnum;
+ rtx accum_in_op;
- x = single_set (in_insn);
- if (x == 0)
+ if (recog_memoized (in_insn) < 0)
return false;
- x = SET_SRC (x);
+ accum_in = get_attr_accum_in (in_insn);
+ if (accum_in == ACCUM_IN_NONE)
+ return false;
- if (GET_CODE (x) == PLUS
- && GET_CODE (XEXP (x, 0)) == MULT
- && reg_set_p (XEXP (x, 1), out_insn))
- return true;
+ accum_in_opnum = accum_in - ACCUM_IN_0;
- if (GET_CODE (x) == MINUS
- && GET_CODE (XEXP (x, 1)) == MULT
- && reg_set_p (XEXP (x, 0), out_insn))
- return true;
+ extract_insn (in_insn);
+ gcc_assert (accum_in_opnum < recog_data.n_operands);
+ accum_in_op = recog_data.operand[accum_in_opnum];
- return false;
+ return reg_set_p (accum_in_op, out_insn);
}
/* True if the dependency between OUT_INSN and IN_INSN is on the store
@@ -12393,6 +13176,7 @@ mips_issue_rate (void)
case PROCESSOR_R4130:
case PROCESSOR_R5400:
case PROCESSOR_R5500:
+ case PROCESSOR_R5900:
case PROCESSOR_R7000:
case PROCESSOR_R9000:
case PROCESSOR_OCTEON:
@@ -12412,6 +13196,9 @@ mips_issue_rate (void)
case PROCESSOR_LOONGSON_3A:
return 4;
+ case PROCESSOR_XLP:
+ return (reload_completed ? 4 : 3);
+
default:
return 1;
}
@@ -12933,9 +13720,12 @@ mips_prefetch_cookie (rtx write, rtx locality)
/* Flags that indicate when a built-in function is available.
BUILTIN_AVAIL_NON_MIPS16
- The function is available on the current target, but only
- in non-MIPS16 mode. */
+ The function is available on the current target if !TARGET_MIPS16.
+
+ BUILTIN_AVAIL_MIPS16
+ The function is available on the current target if TARGET_MIPS16. */
#define BUILTIN_AVAIL_NON_MIPS16 1
+#define BUILTIN_AVAIL_MIPS16 2
/* Declare an availability predicate for built-in functions that
require non-MIPS16 mode and also require COND to be true.
@@ -12947,6 +13737,16 @@ mips_prefetch_cookie (rtx write, rtx locality)
return (COND) ? BUILTIN_AVAIL_NON_MIPS16 : 0; \
}
+/* Declare an availability predicate for built-in functions that
+ support both MIPS16 and non-MIPS16 code and also require COND
+ to be true. NAME is the main part of the predicate's name. */
+#define AVAIL_ALL(NAME, COND) \
+ static unsigned int \
+ mips_builtin_avail_##NAME (void) \
+ { \
+ return (COND) ? BUILTIN_AVAIL_NON_MIPS16 | BUILTIN_AVAIL_MIPS16 : 0; \
+ }
+
/* This structure describes a single built-in function. */
struct mips_builtin_description {
/* The code of the main .md file instruction. See mips_builtin_type
@@ -12969,6 +13769,7 @@ struct mips_builtin_description {
unsigned int (*avail) (void);
};
+AVAIL_ALL (hard_float, TARGET_HARD_FLOAT_ABI)
AVAIL_NON_MIPS16 (paired_single, TARGET_PAIRED_SINGLE_FLOAT)
AVAIL_NON_MIPS16 (sb1_paired_single, TARGET_SB1 && TARGET_PAIRED_SINGLE_FLOAT)
AVAIL_NON_MIPS16 (mips3d, TARGET_MIPS3D)
@@ -13136,6 +13937,11 @@ AVAIL_NON_MIPS16 (cache, TARGET_CACHE_BUILTIN)
#define CODE_FOR_loongson_psubusb CODE_FOR_ussubv8qi3
static const struct mips_builtin_description mips_builtins[] = {
+#define MIPS_GET_FCSR 0
+ DIRECT_BUILTIN (get_fcsr, MIPS_USI_FTYPE_VOID, hard_float),
+#define MIPS_SET_FCSR 1
+ DIRECT_NO_TARGET_BUILTIN (set_fcsr, MIPS_VOID_FTYPE_USI, hard_float),
+
DIRECT_BUILTIN (pll_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, paired_single),
DIRECT_BUILTIN (pul_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, paired_single),
DIRECT_BUILTIN (plu_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, paired_single),
@@ -13603,15 +14409,16 @@ mips_expand_builtin_compare_1 (enum insn_code icode,
tree exp, int nargs)
{
struct expand_operand ops[MAX_RECOG_OPERANDS];
+ rtx output;
int opno, argno;
/* The instruction should have a target operand, an operand for each
argument, and an operand for COND. */
gcc_assert (nargs + 2 == insn_data[(int) icode].n_generator_args);
+ output = mips_allocate_fcc (insn_data[(int) icode].operand[0].mode);
opno = 0;
- create_output_operand (&ops[opno++], NULL_RTX,
- insn_data[(int) icode].operand[0].mode);
+ create_fixed_operand (&ops[opno++], output);
for (argno = 0; argno < nargs; argno++)
mips_prepare_builtin_arg (&ops[opno++], exp, argno);
create_integer_operand (&ops[opno++], (int) cond);
@@ -13784,7 +14591,7 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
d = &mips_builtins[fcode];
avail = d->avail ();
gcc_assert (avail != 0);
- if (TARGET_MIPS16)
+ if (TARGET_MIPS16 && !(avail & BUILTIN_AVAIL_MIPS16))
{
error ("built-in function %qE not supported for MIPS16",
DECL_NAME (fndecl));
@@ -13955,13 +14762,15 @@ mips16_emit_constants (struct mips16_constant *constants, rtx insn)
static int
mips16_insn_length (rtx insn)
{
- if (JUMP_P (insn))
+ if (JUMP_TABLE_DATA_P (insn))
{
rtx body = PATTERN (insn);
if (GET_CODE (body) == ADDR_VEC)
return GET_MODE_SIZE (GET_MODE (body)) * XVECLEN (body, 0);
- if (GET_CODE (body) == ADDR_DIFF_VEC)
+ else if (GET_CODE (body) == ADDR_DIFF_VEC)
return GET_MODE_SIZE (GET_MODE (body)) * XVECLEN (body, 1);
+ else
+ gcc_unreachable ();
}
return get_attr_length (insn);
}
@@ -13977,7 +14786,7 @@ mips16_rewrite_pool_constant (struct mips16_constant_pool *pool, rtx *x)
split_const (*x, &base, &offset);
if (GET_CODE (base) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (base))
{
- label = mips16_add_constant (pool, get_pool_constant (base),
+ label = mips16_add_constant (pool, copy_rtx (get_pool_constant (base)),
get_pool_mode (base));
base = gen_rtx_LABEL_REF (Pmode, label);
*x = mips_unspec_address_offset (base, offset, SYMBOL_PC_RELATIVE);
@@ -14033,10 +14842,11 @@ mips_cfg_in_reorg (void)
|| TARGET_RELAX_PIC_CALLS);
}
-/* Build MIPS16 constant pools. */
+/* Build MIPS16 constant pools. Split the instructions if SPLIT_P,
+ otherwise assume that they are already split. */
static void
-mips16_lay_out_constants (void)
+mips16_lay_out_constants (bool split_p)
{
struct mips16_constant_pool pool;
struct mips16_rewrite_pool_refs_info info;
@@ -14045,10 +14855,13 @@ mips16_lay_out_constants (void)
if (!TARGET_MIPS16_PCREL_LOADS)
return;
- if (mips_cfg_in_reorg ())
- split_all_insns ();
- else
- split_all_insns_noflow ();
+ if (split_p)
+ {
+ if (mips_cfg_in_reorg ())
+ split_all_insns ();
+ else
+ split_all_insns_noflow ();
+ }
barrier = 0;
memset (&pool, 0, sizeof (pool));
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
@@ -14168,7 +14981,7 @@ r10k_simplify_address (rtx x, rtx insn)
/* Replace the incoming value of $sp with
virtual_incoming_args_rtx. */
if (x == stack_pointer_rtx
- && DF_REF_BB (def) == ENTRY_BLOCK_PTR)
+ && DF_REF_BB (def) == ENTRY_BLOCK_PTR_FOR_FN (cfun))
newx = virtual_incoming_args_rtx;
}
else if (dominated_by_p (CDI_DOMINATORS, DF_REF_BB (use),
@@ -14257,19 +15070,20 @@ r10k_safe_address_p (rtx x, rtx insn)
a link-time-constant address. */
static bool
-r10k_safe_mem_expr_p (tree expr, HOST_WIDE_INT offset)
+r10k_safe_mem_expr_p (tree expr, unsigned HOST_WIDE_INT offset)
{
- if (offset < 0 || offset >= int_size_in_bytes (TREE_TYPE (expr)))
- return false;
+ HOST_WIDE_INT bitoffset, bitsize;
+ tree inner, var_offset;
+ enum machine_mode mode;
+ int unsigned_p, volatile_p;
- while (TREE_CODE (expr) == COMPONENT_REF)
- {
- expr = TREE_OPERAND (expr, 0);
- if (expr == NULL_TREE)
- return false;
- }
+ inner = get_inner_reference (expr, &bitsize, &bitoffset, &var_offset, &mode,
+ &unsigned_p, &volatile_p, false);
+ if (!DECL_P (inner) || !DECL_SIZE_UNIT (inner) || var_offset)
+ return false;
- return DECL_P (expr);
+ offset += bitoffset / BITS_PER_UNIT;
+ return offset < tree_to_uhwi (DECL_SIZE_UNIT (inner));
}
/* A for_each_rtx callback for which DATA points to the instruction
@@ -14359,7 +15173,7 @@ r10k_protected_bb_p (basic_block bb, sbitmap protected_bbs)
FOR_EACH_EDGE (e, ei, bb->preds)
if (!single_succ_p (e->src)
- || !TEST_BIT (protected_bbs, e->src->index)
+ || !bitmap_bit_p (protected_bbs, e->src->index)
|| (e->flags & EDGE_COMPLEX) != 0)
return false;
return true;
@@ -14387,15 +15201,15 @@ r10k_insert_cache_barriers (void)
/* Bit X of PROTECTED_BBS is set if the last operation in basic block
X is protected by a cache barrier. */
- protected_bbs = sbitmap_alloc (last_basic_block);
- sbitmap_zero (protected_bbs);
+ protected_bbs = sbitmap_alloc (last_basic_block_for_fn (cfun));
+ bitmap_clear (protected_bbs);
/* Iterate over the basic blocks in reverse post-order. */
- rev_post_order = XNEWVEC (int, last_basic_block);
+ rev_post_order = XNEWVEC (int, last_basic_block_for_fn (cfun));
n = pre_and_rev_post_order_compute (NULL, rev_post_order, false);
for (i = 0; i < n; i++)
{
- bb = BASIC_BLOCK (rev_post_order[i]);
+ bb = BASIC_BLOCK_FOR_FN (cfun, rev_post_order[i]);
/* If this block is only reached by unconditional edges, and if the
source of every edge is protected, the beginning of the block is
@@ -14453,7 +15267,7 @@ r10k_insert_cache_barriers (void)
/* Record whether the end of this block is protected. */
if (unprotected_region == NULL_RTX)
- SET_BIT (protected_bbs, bb->index);
+ bitmap_set_bit (protected_bbs, bb->index);
}
XDELETEVEC (rev_post_order);
@@ -14518,13 +15332,13 @@ mips_pic_call_symbol_from_set (df_ref def, rtx reg, bool recurse_p)
{
rtx note, src, symbol;
- /* First, look at REG_EQUAL/EQUIV notes. */
- note = find_reg_equal_equiv_note (def_insn);
- if (note && GET_CODE (XEXP (note, 0)) == SYMBOL_REF)
- return XEXP (note, 0);
-
- /* For %call16 references we don't have REG_EQUAL. */
+ /* First see whether the source is a plain symbol. This is used
+ when calling symbols that are not lazily bound. */
src = SET_SRC (set);
+ if (GET_CODE (src) == SYMBOL_REF)
+ return src;
+
+ /* Handle %call16 references. */
symbol = mips_strip_unspec_call (src);
if (symbol)
{
@@ -14532,6 +15346,12 @@ mips_pic_call_symbol_from_set (df_ref def, rtx reg, bool recurse_p)
return symbol;
}
+ /* If we have something more complicated, look for a
+ REG_EQUAL or REG_EQUIV note. */
+ note = find_reg_equal_equiv_note (def_insn);
+ if (note && GET_CODE (XEXP (note, 0)) == SYMBOL_REF)
+ return XEXP (note, 0);
+
/* Follow at most one simple register copy. Such copies are
interesting in cases like:
@@ -14642,7 +15462,7 @@ mips_annotate_pic_calls (void)
basic_block bb;
rtx insn;
- FOR_EACH_BB (bb)
+ FOR_EACH_BB_FN (bb, cfun)
FOR_BB_INSNS (bb, insn)
{
rtx call, reg, symbol, second_call;
@@ -14699,10 +15519,15 @@ struct mips_sim {
static void
mips_sim_reset (struct mips_sim *state)
{
+ curr_state = state->dfa_state;
+
state->time = 0;
state->insns_left = state->issue_rate;
memset (&state->last_set, 0, sizeof (state->last_set));
- state_reset (state->dfa_state);
+ state_reset (curr_state);
+
+ targetm.sched.init (0, false, 0);
+ advance_state (curr_state);
}
/* Initialize STATE before its first use. DFA_STATE points to an
@@ -14711,6 +15536,12 @@ mips_sim_reset (struct mips_sim *state)
static void
mips_sim_init (struct mips_sim *state, state_t dfa_state)
{
+ if (targetm.sched.init_dfa_pre_cycle_insn)
+ targetm.sched.init_dfa_pre_cycle_insn ();
+
+ if (targetm.sched.init_dfa_post_cycle_insn)
+ targetm.sched.init_dfa_post_cycle_insn ();
+
state->issue_rate = mips_issue_rate ();
state->dfa_state = dfa_state;
mips_sim_reset (state);
@@ -14721,9 +15552,11 @@ mips_sim_init (struct mips_sim *state, state_t dfa_state)
static void
mips_sim_next_cycle (struct mips_sim *state)
{
+ curr_state = state->dfa_state;
+
state->time++;
state->insns_left = state->issue_rate;
- state_transition (state->dfa_state, 0);
+ advance_state (curr_state);
}
/* Advance simulation state STATE until instruction INSN can read
@@ -14829,8 +15662,11 @@ mips_sim_record_set (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data)
static void
mips_sim_issue_insn (struct mips_sim *state, rtx insn)
{
- state_transition (state->dfa_state, insn);
- state->insns_left--;
+ curr_state = state->dfa_state;
+
+ state_transition (curr_state, insn);
+ state->insns_left = targetm.sched.variable_issue (0, false, insn,
+ state->insns_left);
mips_sim_insn = insn;
note_stores (PATTERN (insn), mips_sim_record_set, state);
@@ -14881,6 +15717,109 @@ mips_sim_finish_insn (struct mips_sim *state, rtx insn)
break;
}
}
+
+/* Use simulator state STATE to calculate the execution time of
+ instruction sequence SEQ. */
+
+static unsigned int
+mips_seq_time (struct mips_sim *state, rtx seq)
+{
+ mips_sim_reset (state);
+ for (rtx insn = seq; insn; insn = NEXT_INSN (insn))
+ {
+ mips_sim_wait_insn (state, insn);
+ mips_sim_issue_insn (state, insn);
+ }
+ return state->time;
+}
+
+/* Return the execution-time cost of mips_tuning_info.fast_mult_zero_zero_p
+ setting SETTING, using STATE to simulate instruction sequences. */
+
+static unsigned int
+mips_mult_zero_zero_cost (struct mips_sim *state, bool setting)
+{
+ mips_tuning_info.fast_mult_zero_zero_p = setting;
+ start_sequence ();
+
+ enum machine_mode dword_mode = TARGET_64BIT ? TImode : DImode;
+ rtx hilo = gen_rtx_REG (dword_mode, MD_REG_FIRST);
+ mips_emit_move_or_split (hilo, const0_rtx, SPLIT_FOR_SPEED);
+
+ /* If the target provides mulsidi3_32bit then that's the most likely
+ consumer of the result. Test for bypasses. */
+ if (dword_mode == DImode && HAVE_maddsidi4)
+ {
+ rtx gpr = gen_rtx_REG (SImode, GP_REG_FIRST + 4);
+ emit_insn (gen_maddsidi4 (hilo, gpr, gpr, hilo));
+ }
+
+ unsigned int time = mips_seq_time (state, get_insns ());
+ end_sequence ();
+ return time;
+}
+
+/* Check the relative speeds of "MULT $0,$0" and "MTLO $0; MTHI $0"
+ and set up mips_tuning_info.fast_mult_zero_zero_p accordingly.
+ Prefer MULT -- which is shorter -- in the event of a tie. */
+
+static void
+mips_set_fast_mult_zero_zero_p (struct mips_sim *state)
+{
+ if (TARGET_MIPS16)
+ /* No MTLO or MTHI available. */
+ mips_tuning_info.fast_mult_zero_zero_p = true;
+ else
+ {
+ unsigned int true_time = mips_mult_zero_zero_cost (state, true);
+ unsigned int false_time = mips_mult_zero_zero_cost (state, false);
+ mips_tuning_info.fast_mult_zero_zero_p = (true_time <= false_time);
+ }
+}
+
+/* Set up costs based on the current architecture and tuning settings. */
+
+static void
+mips_set_tuning_info (void)
+{
+ if (mips_tuning_info.initialized_p
+ && mips_tuning_info.arch == mips_arch
+ && mips_tuning_info.tune == mips_tune
+ && mips_tuning_info.mips16_p == TARGET_MIPS16)
+ return;
+
+ mips_tuning_info.arch = mips_arch;
+ mips_tuning_info.tune = mips_tune;
+ mips_tuning_info.mips16_p = TARGET_MIPS16;
+ mips_tuning_info.initialized_p = true;
+
+ dfa_start ();
+
+ struct mips_sim state;
+ mips_sim_init (&state, alloca (state_size ()));
+
+ mips_set_fast_mult_zero_zero_p (&state);
+
+ dfa_finish ();
+}
+
+/* Implement TARGET_EXPAND_TO_RTL_HOOK. */
+
+static void
+mips_expand_to_rtl_hook (void)
+{
+ /* We need to call this at a point where we can safely create sequences
+ of instructions, so TARGET_OVERRIDE_OPTIONS is too early. We also
+ need to call it at a point where the DFA infrastructure is not
+ already in use, so we can't just call it lazily on demand.
+
+ At present, mips_tuning_info is only needed during post-expand
+ RTL passes such as split_insns, so this hook should be early enough.
+ We may need to move the call elsewhere if mips_tuning_info starts
+ to be used for other things (such as rtx_costs, or expanders that
+ could be called during gimple optimization). */
+ mips_set_tuning_info ();
+}
/* The VR4130 pipeline issues aligned pairs of instructions together,
but it stalls the second instruction if it depends on the first.
@@ -14957,7 +15896,8 @@ vr4130_align_insns (void)
the fly to avoid a separate instruction walk. */
vr4130_avoid_branch_rt_conflict (insn);
- if (USEFUL_INSN_P (insn))
+ length = get_attr_length (insn);
+ if (length > 0 && USEFUL_INSN_P (insn))
FOR_EACH_SUBINSN (subinsn, insn)
{
mips_sim_wait_insn (&state, subinsn);
@@ -14992,6 +15932,7 @@ vr4130_align_insns (void)
issuing at the same time as the branch. We therefore
insert a nop before the branch in order to align its
delay slot. */
+ gcc_assert (last2);
emit_insn_after (gen_nop (), last2);
aligned_p = false;
}
@@ -15000,6 +15941,7 @@ vr4130_align_insns (void)
/* SUBINSN is the delay slot of INSN, but INSN is
currently unaligned. Insert a nop between
LAST and INSN to align it. */
+ gcc_assert (last);
emit_insn_after (gen_nop (), last);
aligned_p = true;
}
@@ -15055,30 +15997,43 @@ mips_hash_base (rtx base)
return hash_rtx (base, GET_MODE (base), &do_not_record_p, NULL, false);
}
+/* Hashtable helpers. */
+
+struct mips_lo_sum_offset_hasher : typed_free_remove <mips_lo_sum_offset>
+{
+ typedef mips_lo_sum_offset value_type;
+ typedef rtx_def compare_type;
+ static inline hashval_t hash (const value_type *);
+ static inline bool equal (const value_type *, const compare_type *);
+};
+
/* Hash-table callbacks for mips_lo_sum_offsets. */
-static hashval_t
-mips_lo_sum_offset_hash (const void *entry)
+inline hashval_t
+mips_lo_sum_offset_hasher::hash (const value_type *entry)
{
- return mips_hash_base (((const struct mips_lo_sum_offset *) entry)->base);
+ return mips_hash_base (entry->base);
}
-static int
-mips_lo_sum_offset_eq (const void *entry, const void *value)
+inline bool
+mips_lo_sum_offset_hasher::equal (const value_type *entry,
+ const compare_type *value)
{
- return rtx_equal_p (((const struct mips_lo_sum_offset *) entry)->base,
- (const_rtx) value);
+ return rtx_equal_p (entry->base, value);
}
+typedef hash_table <mips_lo_sum_offset_hasher> mips_offset_table;
+
/* Look up symbolic constant X in HTAB, which is a hash table of
mips_lo_sum_offsets. If OPTION is NO_INSERT, return true if X can be
paired with a recorded LO_SUM, otherwise record X in the table. */
static bool
-mips_lo_sum_offset_lookup (htab_t htab, rtx x, enum insert_option option)
+mips_lo_sum_offset_lookup (mips_offset_table htab, rtx x,
+ enum insert_option option)
{
rtx base, offset;
- void **slot;
+ mips_lo_sum_offset **slot;
struct mips_lo_sum_offset *entry;
/* Split X into a base and offset. */
@@ -15087,7 +16042,7 @@ mips_lo_sum_offset_lookup (htab_t htab, rtx x, enum insert_option option)
base = UNSPEC_ADDRESS (base);
/* Look up the base in the hash table. */
- slot = htab_find_slot_with_hash (htab, base, mips_hash_base (base), option);
+ slot = htab.find_slot_with_hash (base, mips_hash_base (base), option);
if (slot == NULL)
return false;
@@ -15117,7 +16072,8 @@ static int
mips_record_lo_sum (rtx *loc, void *data)
{
if (GET_CODE (*loc) == LO_SUM)
- mips_lo_sum_offset_lookup ((htab_t) data, XEXP (*loc, 1), INSERT);
+ mips_lo_sum_offset_lookup (*(mips_offset_table*) data,
+ XEXP (*loc, 1), INSERT);
return 0;
}
@@ -15126,7 +16082,7 @@ mips_record_lo_sum (rtx *loc, void *data)
LO_SUMs in the current function. */
static bool
-mips_orphaned_high_part_p (htab_t htab, rtx insn)
+mips_orphaned_high_part_p (mips_offset_table htab, rtx insn)
{
enum mips_symbol_type type;
rtx x, set;
@@ -15234,7 +16190,7 @@ mips_reorg_process_insns (void)
{
rtx insn, last_insn, subinsn, next_insn, lo_reg, delayed_reg;
int hilo_delay;
- htab_t htab;
+ mips_offset_table htab;
/* Force all instructions to be split into their final form. */
split_all_insns_noflow ();
@@ -15259,9 +16215,13 @@ mips_reorg_process_insns (void)
if (crtl->profile)
cfun->machine->all_noreorder_p = false;
- /* Code compiled with -mfix-vr4120 or -mfix-24k can't be all noreorder
- because we rely on the assembler to work around some errata. */
- if (TARGET_FIX_VR4120 || TARGET_FIX_24K)
+ /* Code compiled with -mfix-vr4120, -mfix-rm7000 or -mfix-24k can't be
+ all noreorder because we rely on the assembler to work around some
+ errata. The R5900 too has several bugs. */
+ if (TARGET_FIX_VR4120
+ || TARGET_FIX_RM7000
+ || TARGET_FIX_24K
+ || TARGET_MIPS5900)
cfun->machine->all_noreorder_p = false;
/* The same is true for -mfix-vr4130 if we might generate MFLO or
@@ -15271,14 +16231,29 @@ mips_reorg_process_insns (void)
if (TARGET_FIX_VR4130 && !ISA_HAS_MACCHI)
cfun->machine->all_noreorder_p = false;
- htab = htab_create (37, mips_lo_sum_offset_hash,
- mips_lo_sum_offset_eq, free);
+ htab.create (37);
/* Make a first pass over the instructions, recording all the LO_SUMs. */
for (insn = get_insns (); insn != 0; insn = NEXT_INSN (insn))
FOR_EACH_SUBINSN (subinsn, insn)
if (USEFUL_INSN_P (subinsn))
- for_each_rtx (&PATTERN (subinsn), mips_record_lo_sum, htab);
+ {
+ rtx body = PATTERN (insn);
+ int noperands = asm_noperands (body);
+ if (noperands >= 0)
+ {
+ rtx *ops = XALLOCAVEC (rtx, noperands);
+ bool *used = XALLOCAVEC (bool, noperands);
+ const char *string = decode_asm_operands (body, ops, NULL, NULL,
+ NULL, NULL);
+ get_referenced_operands (string, used, noperands);
+ for (int i = 0; i < noperands; ++i)
+ if (used[i])
+ for_each_rtx (&ops[i], mips_record_lo_sum, &htab);
+ }
+ else
+ for_each_rtx (&PATTERN (subinsn), mips_record_lo_sum, &htab);
+ }
last_insn = 0;
hilo_delay = 2;
@@ -15335,26 +16310,18 @@ mips_reorg_process_insns (void)
}
}
- htab_delete (htab);
+ htab.dispose ();
}
-/* If we are using a GOT, but have not decided to use a global pointer yet,
- see whether we need one to implement long branches. Convert the ghost
- global-pointer instructions into real ones if so. */
+/* Return true if the function has a long branch instruction. */
static bool
-mips_expand_ghost_gp_insns (void)
+mips_has_long_branch_p (void)
{
- rtx insn;
+ rtx insn, subinsn;
int normal_length;
- /* Quick exit if we already know that we will or won't need a
- global pointer. */
- if (!TARGET_USE_GOT
- || cfun->machine->global_pointer == INVALID_REGNUM
- || mips_must_initialize_gp_p ())
- return false;
-
+ /* We need up-to-date instruction lengths. */
shorten_branches (get_insns ());
/* Look for a branch that is longer than normal. The normal length for
@@ -15363,12 +16330,31 @@ mips_expand_ghost_gp_insns (void)
but they have no delay slot. */
normal_length = (TARGET_MIPS16 ? 4 : 8);
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- if (JUMP_P (insn)
- && USEFUL_INSN_P (insn)
- && get_attr_length (insn) > normal_length)
- break;
+ FOR_EACH_SUBINSN (subinsn, insn)
+ if (JUMP_P (subinsn)
+ && get_attr_length (subinsn) > normal_length
+ && (any_condjump_p (subinsn) || any_uncondjump_p (subinsn)))
+ return true;
+
+ return false;
+}
- if (insn == NULL_RTX)
+/* If we are using a GOT, but have not decided to use a global pointer yet,
+ see whether we need one to implement long branches. Convert the ghost
+ global-pointer instructions into real ones if so. */
+
+static bool
+mips_expand_ghost_gp_insns (void)
+{
+ /* Quick exit if we already know that we will or won't need a
+ global pointer. */
+ if (!TARGET_USE_GOT
+ || cfun->machine->global_pointer == INVALID_REGNUM
+ || mips_must_initialize_gp_p ())
+ return false;
+
+ /* Run a full check for long branches. */
+ if (!mips_has_long_branch_p ())
return false;
/* We've now established that we need $gp. */
@@ -15397,6 +16383,110 @@ mips_df_reorg (void)
df_finish_pass (false);
}
+/* Emit code to load LABEL_REF SRC into MIPS16 register DEST. This is
+ called very late in mips_reorg, but the caller is required to run
+ mips16_lay_out_constants on the result. */
+
+static void
+mips16_load_branch_target (rtx dest, rtx src)
+{
+ if (TARGET_ABICALLS && !TARGET_ABSOLUTE_ABICALLS)
+ {
+ rtx page, low;
+
+ if (mips_cfun_has_cprestore_slot_p ())
+ mips_emit_move (dest, mips_cprestore_slot (dest, true));
+ else
+ mips_emit_move (dest, pic_offset_table_rtx);
+ page = mips_unspec_address (src, SYMBOL_GOTOFF_PAGE);
+ low = mips_unspec_address (src, SYMBOL_GOT_PAGE_OFST);
+ emit_insn (gen_rtx_SET (VOIDmode, dest,
+ PMODE_INSN (gen_unspec_got, (dest, page))));
+ emit_insn (gen_rtx_SET (VOIDmode, dest,
+ gen_rtx_LO_SUM (Pmode, dest, low)));
+ }
+ else
+ {
+ src = mips_unspec_address (src, SYMBOL_ABSOLUTE);
+ mips_emit_move (dest, src);
+ }
+}
+
+/* If we're compiling a MIPS16 function, look for and split any long branches.
+ This must be called after all other instruction modifications in
+ mips_reorg. */
+
+static void
+mips16_split_long_branches (void)
+{
+ bool something_changed;
+
+ if (!TARGET_MIPS16)
+ return;
+
+ /* Loop until the alignments for all targets are sufficient. */
+ do
+ {
+ rtx insn;
+
+ shorten_branches (get_insns ());
+ something_changed = false;
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (JUMP_P (insn)
+ && get_attr_length (insn) > 4
+ && (any_condjump_p (insn) || any_uncondjump_p (insn)))
+ {
+ rtx old_label, new_label, temp, saved_temp;
+ rtx target, jump, jump_sequence;
+
+ start_sequence ();
+
+ /* Free up a MIPS16 register by saving it in $1. */
+ saved_temp = gen_rtx_REG (Pmode, AT_REGNUM);
+ temp = gen_rtx_REG (Pmode, GP_REG_FIRST + 2);
+ emit_move_insn (saved_temp, temp);
+
+ /* Load the branch target into TEMP. */
+ old_label = JUMP_LABEL (insn);
+ target = gen_rtx_LABEL_REF (Pmode, old_label);
+ mips16_load_branch_target (temp, target);
+
+ /* Jump to the target and restore the register's
+ original value. */
+ jump = emit_jump_insn (PMODE_INSN (gen_indirect_jump_and_restore,
+ (temp, temp, saved_temp)));
+ JUMP_LABEL (jump) = old_label;
+ LABEL_NUSES (old_label)++;
+
+ /* Rewrite any symbolic references that are supposed to use
+ a PC-relative constant pool. */
+ mips16_lay_out_constants (false);
+
+ if (simplejump_p (insn))
+ /* We're going to replace INSN with a longer form. */
+ new_label = NULL_RTX;
+ else
+ {
+ /* Create a branch-around label for the original
+ instruction. */
+ new_label = gen_label_rtx ();
+ emit_label (new_label);
+ }
+
+ jump_sequence = get_insns ();
+ end_sequence ();
+
+ emit_insn_after (jump_sequence, insn);
+ if (new_label)
+ invert_jump (insn, new_label, false);
+ else
+ delete_insn (insn);
+ something_changed = true;
+ }
+ }
+ while (something_changed);
+}
+
/* Implement TARGET_MACHINE_DEPENDENT_REORG. */
static void
@@ -15407,18 +16497,20 @@ mips_reorg (void)
to date if the CFG is available. */
if (mips_cfg_in_reorg ())
compute_bb_for_insn ();
- mips16_lay_out_constants ();
+ mips16_lay_out_constants (true);
if (mips_cfg_in_reorg ())
{
mips_df_reorg ();
free_bb_for_insn ();
}
+}
- if (optimize > 0 && flag_delayed_branch)
- {
- cleanup_barriers ();
- dbr_schedule (get_insns ());
- }
+/* We use a machine specific pass to do a second machine dependent reorg
+ pass after delay branch scheduling. */
+
+static unsigned int
+mips_machine_reorg2 (void)
+{
mips_reorg_process_insns ();
if (!TARGET_MIPS16
&& TARGET_EXPLICIT_RELOCS
@@ -15429,7 +16521,47 @@ mips_reorg (void)
/* The expansion could invalidate some of the VR4130 alignment
optimizations, but this should be an extremely rare case anyhow. */
mips_reorg_process_insns ();
+ mips16_split_long_branches ();
+ return 0;
}
+
+namespace {
+
+const pass_data pass_data_mips_machine_reorg2 =
+{
+ RTL_PASS, /* type */
+ "mach2", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ false, /* has_gate */
+ true, /* has_execute */
+ TV_MACH_DEP, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_verify_rtl_sharing, /* todo_flags_finish */
+};
+
+class pass_mips_machine_reorg2 : public rtl_opt_pass
+{
+public:
+ pass_mips_machine_reorg2(gcc::context *ctxt)
+ : rtl_opt_pass(pass_data_mips_machine_reorg2, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ unsigned int execute () { return mips_machine_reorg2 (); }
+
+}; // class pass_mips_machine_reorg2
+
+} // anon namespace
+
+rtl_opt_pass *
+make_pass_mips_machine_reorg2 (gcc::context *ctxt)
+{
+ return new pass_mips_machine_reorg2 (ctxt);
+}
+
/* Implement TARGET_ASM_OUTPUT_MI_THUNK. Generate rtl rather than asm text
in order to avoid duplicating too much logic from elsewhere. */
@@ -15547,9 +16679,8 @@ mips_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
/* Run just enough of rest_of_compilation. This sequence was
"borrowed" from alpha.c. */
insn = get_insns ();
- insn_locators_alloc ();
split_all_insns_noflow ();
- mips16_lay_out_constants ();
+ mips16_lay_out_constants (true);
shorten_branches (insn);
final_start_function (insn, file, 1);
final (insn, file, 1);
@@ -15560,17 +16691,19 @@ mips_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
reload_completed = 0;
}
-/* The last argument passed to mips_set_mips16_mode, or negative if the
- function hasn't been called yet. */
-static int was_mips16_p = -1;
-/* Set up the target-dependent global state so that it matches the
- current function's ISA mode. */
+/* The last argument passed to mips_set_compression_mode,
+ or negative if the function hasn't been called yet. */
+static unsigned int old_compression_mode = -1;
+
+/* Set up the target-dependent global state for ISA mode COMPRESSION_MODE,
+ which is either MASK_MIPS16 or MASK_MICROMIPS. */
static void
-mips_set_mips16_mode (int mips16_p)
+mips_set_compression_mode (unsigned int compression_mode)
{
- if (mips16_p == was_mips16_p)
+
+ if (compression_mode == old_compression_mode)
return;
/* Restore base settings of various flags. */
@@ -15581,8 +16714,10 @@ mips_set_mips16_mode (int mips16_p)
align_loops = mips_base_align_loops;
align_jumps = mips_base_align_jumps;
align_functions = mips_base_align_functions;
+ target_flags &= ~(MASK_MIPS16 | MASK_MICROMIPS);
+ target_flags |= compression_mode;
- if (mips16_p)
+ if (compression_mode & MASK_MIPS16)
{
/* Switch to MIPS16 mode. */
target_flags |= MASK_MIPS16;
@@ -15636,8 +16771,11 @@ mips_set_mips16_mode (int mips16_p)
}
else
{
- /* Switch to normal (non-MIPS16) mode. */
- target_flags &= ~MASK_MIPS16;
+ /* Switch to microMIPS or the standard encoding. */
+
+ if (TARGET_MICROMIPS)
+ /* Avoid branch likely. */
+ target_flags &= ~MASK_BRANCHLIKELY;
/* Provide default values for align_* for 64-bit targets. */
if (TARGET_64BIT)
@@ -15659,26 +16797,27 @@ mips_set_mips16_mode (int mips16_p)
/* (Re)initialize MIPS target internals for new ISA. */
mips_init_relocs ();
- if (mips16_p)
+ if (compression_mode & MASK_MIPS16)
{
if (!mips16_globals)
- mips16_globals = save_target_globals ();
+ mips16_globals = save_target_globals_default_opts ();
else
restore_target_globals (mips16_globals);
}
else
restore_target_globals (&default_target_globals);
- was_mips16_p = mips16_p;
+ old_compression_mode = compression_mode;
}
/* Implement TARGET_SET_CURRENT_FUNCTION. Decide whether the current
- function should use the MIPS16 ISA and switch modes accordingly. */
+ function should use the MIPS16 or microMIPS ISA and switch modes
+ accordingly. */
static void
mips_set_current_function (tree fndecl)
{
- mips_set_mips16_mode (mips_use_mips16_mode_p (fndecl));
+ mips_set_compression_mode (mips_get_compress_mode (fndecl));
}
/* Allocate a chunk of memory for per-function machine-dependent data. */
@@ -15786,14 +16925,19 @@ mips_option_override (void)
if (global_options_set.x_mips_isa_option)
mips_isa_option_info = &mips_cpu_info_table[mips_isa_option];
- /* Process flags as though we were generating non-MIPS16 code. */
- mips_base_mips16 = TARGET_MIPS16;
- target_flags &= ~MASK_MIPS16;
-
#ifdef SUBTARGET_OVERRIDE_OPTIONS
SUBTARGET_OVERRIDE_OPTIONS;
#endif
+ /* MIPS16 and microMIPS cannot coexist. */
+ if (TARGET_MICROMIPS && TARGET_MIPS16)
+ error ("unsupported combination: %s", "-mips16 -mmicromips");
+
+ /* Save the base compression state and process flags as though we
+ were generating uncompressed code. */
+ mips_base_compression_flags = TARGET_COMPRESSION;
+ target_flags &= ~TARGET_COMPRESSION;
+
/* -mno-float overrides -mhard-float and -msoft-float. */
if (TARGET_NO_FLOAT)
{
@@ -15802,7 +16946,7 @@ mips_option_override (void)
}
if (TARGET_FLIP_MIPS16)
- TARGET_INTERLINK_MIPS16 = 1;
+ TARGET_INTERLINK_COMPRESSED = 1;
/* Set the small data limit. */
mips_small_data_threshold = (global_options_set.x_g_switch_value
@@ -15891,6 +17035,11 @@ mips_option_override (void)
/* End of code shared with GAS. */
+ /* The R5900 FPU only supports single precision. */
+ if (TARGET_MIPS5900 && TARGET_HARD_FLOAT_ABI && TARGET_DOUBLE_FLOAT)
+ error ("unsupported combination: %s",
+ "-march=r5900 -mhard-float -mdouble-float");
+
/* If a -mlong* option was given, check that it matches the ABI,
otherwise infer the -mlong* setting from the other options. */
if ((target_flags_explicit & MASK_LONG64) != 0)
@@ -15956,6 +17105,21 @@ mips_option_override (void)
warning (0, "the %qs architecture does not support branch-likely"
" instructions", mips_arch_info->name);
+ /* If the user hasn't specified -mimadd or -mno-imadd set
+ MASK_IMADD based on the target architecture and tuning
+ flags. */
+ if ((target_flags_explicit & MASK_IMADD) == 0)
+ {
+ if (ISA_HAS_MADD_MSUB &&
+ (mips_tune_info->tune_flags & PTF_AVOID_IMADD) == 0)
+ target_flags |= MASK_IMADD;
+ else
+ target_flags &= ~MASK_IMADD;
+ }
+ else if (TARGET_IMADD && !ISA_HAS_MADD_MSUB)
+ warning (0, "the %qs architecture does not support madd or msub"
+ " instructions", mips_arch_info->name);
+
/* The effect of -mabicalls isn't defined for the EABI. */
if (mips_abi == ABI_EABI && TARGET_ABICALLS)
{
@@ -15963,6 +17127,16 @@ mips_option_override (void)
target_flags &= ~MASK_ABICALLS;
}
+ /* PIC requires -mabicalls. */
+ if (flag_pic)
+ {
+ if (mips_abi == ABI_EABI)
+ error ("cannot generate position-independent code for %qs",
+ "-mabi=eabi");
+ else if (!TARGET_ABICALLS)
+ error ("position-independent code requires %qs", "-mabicalls");
+ }
+
if (TARGET_ABICALLS_PIC2)
/* We need to set flag_pic for executables as well as DSOs
because we may reference symbols that are not defined in
@@ -16009,9 +17183,14 @@ mips_option_override (void)
}
}
-#ifdef MIPS_TFMODE_FORMAT
- REAL_MODE_FORMAT (TFmode) = &MIPS_TFMODE_FORMAT;
-#endif
+ /* Pre-IEEE 754-2008 MIPS hardware has a quirky almost-IEEE format
+ for all its floating point. */
+ if (mips_nan != MIPS_IEEE_754_2008)
+ {
+ REAL_MODE_FORMAT (SFmode) = &mips_single_format;
+ REAL_MODE_FORMAT (DFmode) = &mips_double_format;
+ REAL_MODE_FORMAT (TFmode) = &mips_quad_format;
+ }
/* Make sure that the user didn't turn off paired single support when
MIPS-3D support is requested. */
@@ -16027,15 +17206,24 @@ mips_option_override (void)
/* Make sure that when TARGET_PAIRED_SINGLE_FLOAT is true, TARGET_FLOAT64
and TARGET_HARD_FLOAT_ABI are both true. */
if (TARGET_PAIRED_SINGLE_FLOAT && !(TARGET_FLOAT64 && TARGET_HARD_FLOAT_ABI))
- error ("%qs must be used with %qs",
- TARGET_MIPS3D ? "-mips3d" : "-mpaired-single",
- TARGET_HARD_FLOAT_ABI ? "-mfp64" : "-mhard-float");
+ {
+ error ("%qs must be used with %qs",
+ TARGET_MIPS3D ? "-mips3d" : "-mpaired-single",
+ TARGET_HARD_FLOAT_ABI ? "-mfp64" : "-mhard-float");
+ target_flags &= ~MASK_PAIRED_SINGLE_FLOAT;
+ TARGET_MIPS3D = 0;
+ }
- /* Make sure that the ISA supports TARGET_PAIRED_SINGLE_FLOAT when it is
- enabled. */
+ /* Make sure that -mpaired-single is only used on ISAs that support it.
+ We must disable it otherwise since it relies on other ISA properties
+ like ISA_HAS_8CC having their normal values. */
if (TARGET_PAIRED_SINGLE_FLOAT && !ISA_HAS_PAIRED_SINGLE)
- warning (0, "the %qs architecture does not support paired-single"
+ {
+ error ("the %qs architecture does not support paired-single"
" instructions", mips_arch_info->name);
+ target_flags &= ~MASK_PAIRED_SINGLE_FLOAT;
+ TARGET_MIPS3D = 0;
+ }
if (mips_r10k_cache_barrier != R10K_CACHE_BARRIER_NONE
&& !TARGET_CACHE_BUILTIN)
@@ -16045,9 +17233,9 @@ mips_option_override (void)
mips_r10k_cache_barrier = R10K_CACHE_BARRIER_NONE;
}
- /* If TARGET_DSPR2, enable MASK_DSP. */
+ /* If TARGET_DSPR2, enable TARGET_DSP. */
if (TARGET_DSPR2)
- target_flags |= MASK_DSP;
+ TARGET_DSP = true;
/* .eh_frame addresses should be the same width as a C pointer.
Most MIPS ABIs support only one pointer size, so the assembler
@@ -16082,7 +17270,7 @@ mips_option_override (void)
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
- mips_dbx_regno[i] = INVALID_REGNUM;
+ mips_dbx_regno[i] = IGNORED_DWARF_REGNUM;
if (GP_REG_P (i) || FP_REG_P (i) || ALL_COP_REG_P (i))
mips_dwarf_regno[i] = i;
else
@@ -16169,9 +17357,25 @@ mips_option_override (void)
/* Now select the ISA mode.
- Do all CPP-sensitive stuff in non-MIPS16 mode; we'll switch to
- MIPS16 mode afterwards if need be. */
- mips_set_mips16_mode (false);
+ Do all CPP-sensitive stuff in uncompressed mode; we'll switch modes
+ later if required. */
+ mips_set_compression_mode (0);
+
+ /* We register a second machine specific reorg pass after delay slot
+ filling. Registering the pass must be done at start up. It's
+ convenient to do it here. */
+ opt_pass *new_pass = make_pass_mips_machine_reorg2 (g);
+ struct register_pass_info insert_pass_mips_machine_reorg2 =
+ {
+ new_pass, /* pass */
+ "dbr", /* reference_pass_name */
+ 1, /* ref_pass_instance_number */
+ PASS_POS_INSERT_AFTER /* po_op */
+ };
+ register_pass (&insert_pass_mips_machine_reorg2);
+
+ if (TARGET_HARD_FLOAT_ABI && TARGET_MIPS5900)
+ REAL_MODE_FORMAT (SFmode) = &spu_single_format;
}
/* Swap the register information for registers I and I + 1, which
@@ -16232,10 +17436,17 @@ mips_conditional_register_usage (void)
}
if (TARGET_MIPS16)
{
- /* In MIPS16 mode, we permit the $t temporary registers to be used
- for reload. We prohibit the unused $s registers, since they
+ /* In MIPS16 mode, we prohibit the unused $s registers, since they
are call-saved, and saving them via a MIPS16 register would
- probably waste more time than just reloading the value. */
+ probably waste more time than just reloading the value.
+
+ We permit the $t temporary registers when optimizing for speed
+ but not when optimizing for space because using them results in
+ code that is larger (but faster) then not using them. We do
+ allow $24 (t8) because it is used in CMP and CMPI instructions
+ and $25 (t9) because it is used as the function call address in
+ SVR4 PIC code. */
+
fixed_regs[18] = call_used_regs[18] = 1;
fixed_regs[19] = call_used_regs[19] = 1;
fixed_regs[20] = call_used_regs[20] = 1;
@@ -16245,6 +17456,17 @@ mips_conditional_register_usage (void)
fixed_regs[26] = call_used_regs[26] = 1;
fixed_regs[27] = call_used_regs[27] = 1;
fixed_regs[30] = call_used_regs[30] = 1;
+ if (optimize_size)
+ {
+ fixed_regs[8] = call_used_regs[8] = 1;
+ fixed_regs[9] = call_used_regs[9] = 1;
+ fixed_regs[10] = call_used_regs[10] = 1;
+ fixed_regs[11] = call_used_regs[11] = 1;
+ fixed_regs[12] = call_used_regs[12] = 1;
+ fixed_regs[13] = call_used_regs[13] = 1;
+ fixed_regs[14] = call_used_regs[14] = 1;
+ fixed_regs[15] = call_used_regs[15] = 1;
+ }
/* Do not allow HI and LO to be treated as register operands.
There are no MTHI or MTLO instructions (or any real need
@@ -16431,6 +17653,277 @@ mips_mulsidi3_gen_fn (enum rtx_code ext_code)
return signed_p ? gen_mulsidi3_32bit : gen_umulsidi3_32bit;
}
}
+
+/* Return true if PATTERN matches the kind of instruction generated by
+ umips_build_save_restore. SAVE_P is true for store. */
+
+bool
+umips_save_restore_pattern_p (bool save_p, rtx pattern)
+{
+ int n;
+ unsigned int i;
+ HOST_WIDE_INT first_offset = 0;
+ rtx first_base = 0;
+ unsigned int regmask = 0;
+
+ for (n = 0; n < XVECLEN (pattern, 0); n++)
+ {
+ rtx set, reg, mem, this_base;
+ HOST_WIDE_INT this_offset;
+
+ /* Check that we have a SET. */
+ set = XVECEXP (pattern, 0, n);
+ if (GET_CODE (set) != SET)
+ return false;
+
+ /* Check that the SET is a load (if restoring) or a store
+ (if saving). */
+ mem = save_p ? SET_DEST (set) : SET_SRC (set);
+ if (!MEM_P (mem) || MEM_VOLATILE_P (mem))
+ return false;
+
+ /* Check that the address is the sum of base and a possibly-zero
+ constant offset. Determine if the offset is in range. */
+ mips_split_plus (XEXP (mem, 0), &this_base, &this_offset);
+ if (!REG_P (this_base))
+ return false;
+
+ if (n == 0)
+ {
+ if (!UMIPS_12BIT_OFFSET_P (this_offset))
+ return false;
+ first_base = this_base;
+ first_offset = this_offset;
+ }
+ else
+ {
+ /* Check that the save slots are consecutive. */
+ if (REGNO (this_base) != REGNO (first_base)
+ || this_offset != first_offset + UNITS_PER_WORD * n)
+ return false;
+ }
+
+ /* Check that SET's other operand is a register. */
+ reg = save_p ? SET_SRC (set) : SET_DEST (set);
+ if (!REG_P (reg))
+ return false;
+
+ regmask |= 1 << REGNO (reg);
+ }
+
+ for (i = 0; i < ARRAY_SIZE (umips_swm_mask); i++)
+ if (regmask == umips_swm_mask[i])
+ return true;
+
+ return false;
+}
+
+/* Return the assembly instruction for microMIPS LWM or SWM.
+ SAVE_P and PATTERN are as for umips_save_restore_pattern_p. */
+
+const char *
+umips_output_save_restore (bool save_p, rtx pattern)
+{
+ static char buffer[300];
+ char *s;
+ int n;
+ HOST_WIDE_INT offset;
+ rtx base, mem, set, last_set, last_reg;
+
+ /* Parse the pattern. */
+ gcc_assert (umips_save_restore_pattern_p (save_p, pattern));
+
+ s = strcpy (buffer, save_p ? "swm\t" : "lwm\t");
+ s += strlen (s);
+ n = XVECLEN (pattern, 0);
+
+ set = XVECEXP (pattern, 0, 0);
+ mem = save_p ? SET_DEST (set) : SET_SRC (set);
+ mips_split_plus (XEXP (mem, 0), &base, &offset);
+
+ last_set = XVECEXP (pattern, 0, n - 1);
+ last_reg = save_p ? SET_SRC (last_set) : SET_DEST (last_set);
+
+ if (REGNO (last_reg) == 31)
+ n--;
+
+ gcc_assert (n <= 9);
+ if (n == 0)
+ ;
+ else if (n == 1)
+ s += sprintf (s, "%s,", reg_names[16]);
+ else if (n < 9)
+ s += sprintf (s, "%s-%s,", reg_names[16], reg_names[15 + n]);
+ else if (n == 9)
+ s += sprintf (s, "%s-%s,%s,", reg_names[16], reg_names[23],
+ reg_names[30]);
+
+ if (REGNO (last_reg) == 31)
+ s += sprintf (s, "%s,", reg_names[31]);
+
+ s += sprintf (s, "%d(%s)", (int)offset, reg_names[REGNO (base)]);
+ return buffer;
+}
+
+/* Return true if MEM1 and MEM2 use the same base register, and the
+ offset of MEM2 equals the offset of MEM1 plus 4. FIRST_REG is the
+ register into (from) which the contents of MEM1 will be loaded
+ (stored), depending on the value of LOAD_P.
+ SWAP_P is true when the 1st and 2nd instructions are swapped. */
+
+static bool
+umips_load_store_pair_p_1 (bool load_p, bool swap_p,
+ rtx first_reg, rtx mem1, rtx mem2)
+{
+ rtx base1, base2;
+ HOST_WIDE_INT offset1, offset2;
+
+ if (!MEM_P (mem1) || !MEM_P (mem2))
+ return false;
+
+ mips_split_plus (XEXP (mem1, 0), &base1, &offset1);
+ mips_split_plus (XEXP (mem2, 0), &base2, &offset2);
+
+ if (!REG_P (base1) || !rtx_equal_p (base1, base2))
+ return false;
+
+ /* Avoid invalid load pair instructions. */
+ if (load_p && REGNO (first_reg) == REGNO (base1))
+ return false;
+
+ /* We must avoid this case for anti-dependence.
+ Ex: lw $3, 4($3)
+ lw $2, 0($3)
+ first_reg is $2, but the base is $3. */
+ if (load_p
+ && swap_p
+ && REGNO (first_reg) + 1 == REGNO (base1))
+ return false;
+
+ if (offset2 != offset1 + 4)
+ return false;
+
+ if (!UMIPS_12BIT_OFFSET_P (offset1))
+ return false;
+
+ return true;
+}
+
+/* OPERANDS describes the operands to a pair of SETs, in the order
+ dest1, src1, dest2, src2. Return true if the operands can be used
+ in an LWP or SWP instruction; LOAD_P says which. */
+
+bool
+umips_load_store_pair_p (bool load_p, rtx *operands)
+{
+ rtx reg1, reg2, mem1, mem2;
+
+ if (load_p)
+ {
+ reg1 = operands[0];
+ reg2 = operands[2];
+ mem1 = operands[1];
+ mem2 = operands[3];
+ }
+ else
+ {
+ reg1 = operands[1];
+ reg2 = operands[3];
+ mem1 = operands[0];
+ mem2 = operands[2];
+ }
+
+ if (REGNO (reg2) == REGNO (reg1) + 1)
+ return umips_load_store_pair_p_1 (load_p, false, reg1, mem1, mem2);
+
+ if (REGNO (reg1) == REGNO (reg2) + 1)
+ return umips_load_store_pair_p_1 (load_p, true, reg2, mem2, mem1);
+
+ return false;
+}
+
+/* Return the assembly instruction for a microMIPS LWP or SWP in which
+ the first register is REG and the first memory slot is MEM.
+ LOAD_P is true for LWP. */
+
+static void
+umips_output_load_store_pair_1 (bool load_p, rtx reg, rtx mem)
+{
+ rtx ops[] = {reg, mem};
+
+ if (load_p)
+ output_asm_insn ("lwp\t%0,%1", ops);
+ else
+ output_asm_insn ("swp\t%0,%1", ops);
+}
+
+/* Output the assembly instruction for a microMIPS LWP or SWP instruction.
+ LOAD_P and OPERANDS are as for umips_load_store_pair_p. */
+
+void
+umips_output_load_store_pair (bool load_p, rtx *operands)
+{
+ rtx reg1, reg2, mem1, mem2;
+ if (load_p)
+ {
+ reg1 = operands[0];
+ reg2 = operands[2];
+ mem1 = operands[1];
+ mem2 = operands[3];
+ }
+ else
+ {
+ reg1 = operands[1];
+ reg2 = operands[3];
+ mem1 = operands[0];
+ mem2 = operands[2];
+ }
+
+ if (REGNO (reg2) == REGNO (reg1) + 1)
+ {
+ umips_output_load_store_pair_1 (load_p, reg1, mem1);
+ return;
+ }
+
+ gcc_assert (REGNO (reg1) == REGNO (reg2) + 1);
+ umips_output_load_store_pair_1 (load_p, reg2, mem2);
+}
+
+/* Return true if REG1 and REG2 match the criteria for a movep insn. */
+
+bool
+umips_movep_target_p (rtx reg1, rtx reg2)
+{
+ int regno1, regno2, pair;
+ unsigned int i;
+ static const int match[8] = {
+ 0x00000060, /* 5, 6 */
+ 0x000000a0, /* 5, 7 */
+ 0x000000c0, /* 6, 7 */
+ 0x00200010, /* 4, 21 */
+ 0x00400010, /* 4, 22 */
+ 0x00000030, /* 4, 5 */
+ 0x00000050, /* 4, 6 */
+ 0x00000090 /* 4, 7 */
+ };
+
+ if (!REG_P (reg1) || !REG_P (reg2))
+ return false;
+
+ regno1 = REGNO (reg1);
+ regno2 = REGNO (reg2);
+
+ if (!GP_REG_P (regno1) || !GP_REG_P (regno2))
+ return false;
+
+ pair = (1 << regno1) | (1 << regno2);
+
+ for (i = 0; i < ARRAY_SIZE (match); i++)
+ if (pair == match[i])
+ return true;
+
+ return false;
+}
/* Return the size in bytes of the trampoline code, padded to
TRAMPOLINE_ALIGNMENT bits. The static chain pointer and target
@@ -16685,7 +18178,7 @@ mips_prepare_pch_save (void)
It therefore seems best to switch back to non-MIPS16 mode at
save time, and to ensure that mips16_globals remains null after
a PCH load. */
- mips_set_mips16_mode (false);
+ mips_set_compression_mode (0);
mips16_globals = 0;
}
@@ -17178,7 +18671,7 @@ static void
mips_expand_vi_general (enum machine_mode vmode, enum machine_mode imode,
unsigned nelt, unsigned nvar, rtx target, rtx vals)
{
- rtx mem = assign_stack_temp (vmode, GET_MODE_SIZE (vmode), 0);
+ rtx mem = assign_stack_temp (vmode, GET_MODE_SIZE (vmode));
unsigned int i, isize = GET_MODE_SIZE (imode);
if (nvar < nelt)
@@ -17349,6 +18842,61 @@ mips_expand_vec_minmax (rtx target, rtx op0, rtx op1,
x = gen_rtx_IOR (vmode, t0, t1);
emit_insn (gen_rtx_SET (VOIDmode, target, x));
}
+
+/* Implement TARGET_CASE_VALUES_THRESHOLD. */
+
+unsigned int
+mips_case_values_threshold (void)
+{
+ /* In MIPS16 mode using a larger case threshold generates smaller code. */
+ if (TARGET_MIPS16 && optimize_size)
+ return 10;
+ else
+ return default_case_values_threshold ();
+}
+
+/* Implement TARGET_ATOMIC_ASSIGN_EXPAND_FENV. */
+
+static void
+mips_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
+{
+ if (!TARGET_HARD_FLOAT_ABI)
+ return;
+ tree exceptions_var = create_tmp_var (MIPS_ATYPE_USI, NULL);
+ tree fcsr_orig_var = create_tmp_var (MIPS_ATYPE_USI, NULL);
+ tree fcsr_mod_var = create_tmp_var (MIPS_ATYPE_USI, NULL);
+ tree get_fcsr = mips_builtin_decls[MIPS_GET_FCSR];
+ tree set_fcsr = mips_builtin_decls[MIPS_SET_FCSR];
+ tree get_fcsr_hold_call = build_call_expr (get_fcsr, 0);
+ tree hold_assign_orig = build2 (MODIFY_EXPR, MIPS_ATYPE_USI,
+ fcsr_orig_var, get_fcsr_hold_call);
+ tree hold_mod_val = build2 (BIT_AND_EXPR, MIPS_ATYPE_USI, fcsr_orig_var,
+ build_int_cst (MIPS_ATYPE_USI, 0xfffff003));
+ tree hold_assign_mod = build2 (MODIFY_EXPR, MIPS_ATYPE_USI,
+ fcsr_mod_var, hold_mod_val);
+ tree set_fcsr_hold_call = build_call_expr (set_fcsr, 1, fcsr_mod_var);
+ tree hold_all = build2 (COMPOUND_EXPR, MIPS_ATYPE_USI,
+ hold_assign_orig, hold_assign_mod);
+ *hold = build2 (COMPOUND_EXPR, void_type_node, hold_all,
+ set_fcsr_hold_call);
+
+ *clear = build_call_expr (set_fcsr, 1, fcsr_mod_var);
+
+ tree get_fcsr_update_call = build_call_expr (get_fcsr, 0);
+ *update = build2 (MODIFY_EXPR, MIPS_ATYPE_USI,
+ exceptions_var, get_fcsr_update_call);
+ tree set_fcsr_update_call = build_call_expr (set_fcsr, 1, fcsr_orig_var);
+ *update = build2 (COMPOUND_EXPR, void_type_node, *update,
+ set_fcsr_update_call);
+ tree atomic_feraiseexcept
+ = builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT);
+ tree int_exceptions_var = fold_convert (integer_type_node,
+ exceptions_var);
+ tree atomic_feraiseexcept_call = build_call_expr (atomic_feraiseexcept,
+ 1, int_exceptions_var);
+ *update = build2 (COMPOUND_EXPR, void_type_node, *update,
+ atomic_feraiseexcept_call);
+}
/* Initialize the GCC target structure. */
#undef TARGET_ASM_ALIGNED_HI_OP
@@ -17403,6 +18951,8 @@ mips_expand_vec_minmax (rtx target, rtx op0, rtx op1,
#define TARGET_INSERT_ATTRIBUTES mips_insert_attributes
#undef TARGET_MERGE_DECL_ATTRIBUTES
#define TARGET_MERGE_DECL_ATTRIBUTES mips_merge_decl_attributes
+#undef TARGET_CAN_INLINE_P
+#define TARGET_CAN_INLINE_P mips_can_inline_p
#undef TARGET_SET_CURRENT_FUNCTION
#define TARGET_SET_CURRENT_FUNCTION mips_set_current_function
@@ -17426,6 +18976,8 @@ mips_expand_vec_minmax (rtx target, rtx op0, rtx op1,
#undef TARGET_PREFERRED_RELOAD_CLASS
#define TARGET_PREFERRED_RELOAD_CLASS mips_preferred_reload_class
+#undef TARGET_EXPAND_TO_RTL_HOOK
+#define TARGET_EXPAND_TO_RTL_HOOK mips_expand_to_rtl_hook
#undef TARGET_ASM_FILE_START
#define TARGET_ASM_FILE_START mips_file_start
#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
@@ -17576,6 +19128,12 @@ mips_expand_vec_minmax (rtx target, rtx op0, rtx op1,
#undef TARGET_VECTORIZE_VEC_PERM_CONST_OK
#define TARGET_VECTORIZE_VEC_PERM_CONST_OK mips_vectorize_vec_perm_const_ok
+#undef TARGET_CASE_VALUES_THRESHOLD
+#define TARGET_CASE_VALUES_THRESHOLD mips_case_values_threshold
+
+#undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV
+#define TARGET_ATOMIC_ASSIGN_EXPAND_FENV mips_atomic_assign_expand_fenv
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-mips.h"
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 1c19f8b2df..a786d4ce30 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -1,8 +1,5 @@
/* Definitions of target machine for GNU compiler. MIPS version.
- Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
- 2012
- Free Software Foundation, Inc.
+ Copyright (C) 1989-2014 Free Software Foundation, Inc.
Contributed by A. Lichnewsky (lich@inria.inria.fr).
Changed by Michael Meissner (meissner@osf.org).
64-bit r4000 support by Ian Lance Taylor (ian@cygnus.com) and
@@ -50,8 +47,15 @@ extern int target_flags_explicit;
PTF_AVOID_BRANCHLIKELY
Set if it is usually not profitable to use branch-likely instructions
for this target, typically because the branches are always predicted
- taken and so incur a large overhead when not taken. */
-#define PTF_AVOID_BRANCHLIKELY 0x1
+ taken and so incur a large overhead when not taken.
+
+ PTF_AVOID_IMADD
+ Set if it is usually not profitable to use the integer MADD or MSUB
+ instructions because of the overhead of getting the result out of
+ the HI/LO registers. */
+
+#define PTF_AVOID_BRANCHLIKELY 0x1
+#define PTF_AVOID_IMADD 0x2
/* Information about one recognized processor. Defined here for the
benefit of TARGET_CPU_CPP_BUILTINS. */
@@ -158,15 +162,9 @@ struct mips_cpu_info {
This is true for both the PIC and non-PIC VxWorks RTP modes. */
#define TARGET_USE_PIC_FN_ADDR_REG (TARGET_ABICALLS || TARGET_VXWORKS_RTP)
-/* True if .gpword or .gpdword should be used for switch tables.
-
- Although GAS does understand .gpdword, the SGI linker mishandles
- the relocations GAS generates (R_MIPS_GPREL32 followed by R_MIPS_64).
- We therefore disable GP-relative switch tables for n64 on IRIX targets. */
+/* True if .gpword or .gpdword should be used for switch tables. */
#define TARGET_GPWORD \
- (TARGET_ABICALLS \
- && !TARGET_ABSOLUTE_ABICALLS \
- && !(mips_abi == ABI_64 && TARGET_IRIX6))
+ (TARGET_ABICALLS && !TARGET_ABSOLUTE_ABICALLS)
/* True if the output must have a writable .eh_frame.
See ASM_PREFERRED_EH_DATA_FORMAT for details. */
@@ -183,6 +181,9 @@ struct mips_cpu_info {
#define ISA_HAS_DSP_MULT ISA_HAS_DSPR2
#endif
+/* The ISA compression flags that are currently in effect. */
+#define TARGET_COMPRESSION (target_flags & (MASK_MIPS16 | MASK_MICROMIPS))
+
/* Generate mips16 code */
#define TARGET_MIPS16 ((target_flags & MASK_MIPS16) != 0)
/* Generate mips16e code. Default 16bit ASE for mips32* and mips64* */
@@ -221,6 +222,7 @@ struct mips_cpu_info {
#define TARGET_MIPS4130 (mips_arch == PROCESSOR_R4130)
#define TARGET_MIPS5400 (mips_arch == PROCESSOR_R5400)
#define TARGET_MIPS5500 (mips_arch == PROCESSOR_R5500)
+#define TARGET_MIPS5900 (mips_arch == PROCESSOR_R5900)
#define TARGET_MIPS7000 (mips_arch == PROCESSOR_R7000)
#define TARGET_MIPS9000 (mips_arch == PROCESSOR_R9000)
#define TARGET_OCTEON (mips_arch == PROCESSOR_OCTEON \
@@ -229,6 +231,7 @@ struct mips_cpu_info {
#define TARGET_SB1 (mips_arch == PROCESSOR_SB1 \
|| mips_arch == PROCESSOR_SB1A)
#define TARGET_SR71K (mips_arch == PROCESSOR_SR71000)
+#define TARGET_XLP (mips_arch == PROCESSOR_XLP)
/* Scheduling target defines. */
#define TUNE_20KC (mips_tune == PROCESSOR_20KC)
@@ -317,10 +320,7 @@ struct mips_cpu_info {
stores. It does not tell anything about ordering of loads and
stores prior to and following the SC, only about the SC itself and
those loads and stores follow it. */
-#define TARGET_SYNC_AFTER_SC (!TARGET_OCTEON)
-
-/* IRIX specific stuff. */
-#define TARGET_IRIX6 0
+#define TARGET_SYNC_AFTER_SC (!TARGET_OCTEON && !TARGET_XLP)
/* Define preprocessor macros for the -march and -mtune options.
PREFIX is either _MIPS_ARCH or _MIPS_TUNE, INFO is the selected
@@ -348,10 +348,7 @@ struct mips_cpu_info {
#define TARGET_CPU_CPP_BUILTINS() \
do \
{ \
- /* Everyone but IRIX defines this to mips. */ \
- if (!TARGET_IRIX6) \
- builtin_assert ("machine=mips"); \
- \
+ builtin_assert ("machine=mips"); \
builtin_assert ("cpu=mips"); \
builtin_define ("__mips__"); \
builtin_define ("_mips"); \
@@ -369,28 +366,26 @@ struct mips_cpu_info {
if (TARGET_64BIT) \
builtin_define ("__mips64"); \
\
- if (!TARGET_IRIX6) \
+ /* Treat _R3000 and _R4000 like register-size \
+ defines, which is how they've historically \
+ been used. */ \
+ if (TARGET_64BIT) \
{ \
- /* Treat _R3000 and _R4000 like register-size \
- defines, which is how they've historically \
- been used. */ \
- if (TARGET_64BIT) \
- { \
- builtin_define_std ("R4000"); \
- builtin_define ("_R4000"); \
- } \
- else \
- { \
- builtin_define_std ("R3000"); \
- builtin_define ("_R3000"); \
- } \
+ builtin_define_std ("R4000"); \
+ builtin_define ("_R4000"); \
+ } \
+ else \
+ { \
+ builtin_define_std ("R3000"); \
+ builtin_define ("_R3000"); \
} \
+ \
if (TARGET_FLOAT64) \
builtin_define ("__mips_fpr=64"); \
else \
builtin_define ("__mips_fpr=32"); \
\
- if (mips_base_mips16) \
+ if (mips_base_compression_flags & MASK_MIPS16) \
builtin_define ("__mips16"); \
\
if (TARGET_MIPS3D) \
@@ -399,6 +394,15 @@ struct mips_cpu_info {
if (TARGET_SMARTMIPS) \
builtin_define ("__mips_smartmips"); \
\
+ if (mips_base_compression_flags & MASK_MICROMIPS) \
+ builtin_define ("__mips_micromips"); \
+ \
+ if (TARGET_MCU) \
+ builtin_define ("__mips_mcu"); \
+ \
+ if (TARGET_EVA) \
+ builtin_define ("__mips_eva"); \
+ \
if (TARGET_DSP) \
{ \
builtin_define ("__mips_dsp"); \
@@ -503,6 +507,12 @@ struct mips_cpu_info {
if (TARGET_PAIRED_SINGLE_FLOAT) \
builtin_define ("__mips_paired_single_float"); \
\
+ if (mips_abs == MIPS_IEEE_754_2008) \
+ builtin_define ("__mips_abs2008"); \
+ \
+ if (mips_nan == MIPS_IEEE_754_2008) \
+ builtin_define ("__mips_nan2008"); \
+ \
if (TARGET_BIG_ENDIAN) \
{ \
builtin_define_std ("MIPSEB"); \
@@ -527,6 +537,9 @@ struct mips_cpu_info {
if (TARGET_OCTEON) \
builtin_define ("__OCTEON__"); \
\
+ if (TARGET_SYNCI) \
+ builtin_define ("__mips_synci"); \
+ \
/* Macros dependent on the C dialect. */ \
if (preprocessing_asm_p ()) \
{ \
@@ -548,7 +561,7 @@ struct mips_cpu_info {
{ \
builtin_define ("_LANGUAGE_OBJECTIVE_C"); \
builtin_define ("__LANGUAGE_OBJECTIVE_C"); \
- /* Bizarre, but needed at least for Irix. */ \
+ /* Bizarre, but retained for backwards compatibility. */ \
builtin_define_std ("LANGUAGE_C"); \
builtin_define ("_LANGUAGE_C"); \
} \
@@ -575,10 +588,6 @@ struct mips_cpu_info {
#define TARGET_ENDIAN_DEFAULT MASK_BIG_ENDIAN
#endif
-#ifndef TARGET_FP_EXCEPTIONS_DEFAULT
-#define TARGET_FP_EXCEPTIONS_DEFAULT MASK_FP_EXCEPTIONS
-#endif
-
#ifdef IN_LIBGCC2
#undef TARGET_64BIT
/* Make this compile time constant for libgcc2 */
@@ -611,39 +620,25 @@ struct mips_cpu_info {
#endif
#ifndef MULTILIB_ISA_DEFAULT
-# if MIPS_ISA_DEFAULT == 1
-# define MULTILIB_ISA_DEFAULT "mips1"
-# else
-# if MIPS_ISA_DEFAULT == 2
-# define MULTILIB_ISA_DEFAULT "mips2"
-# else
-# if MIPS_ISA_DEFAULT == 3
-# define MULTILIB_ISA_DEFAULT "mips3"
-# else
-# if MIPS_ISA_DEFAULT == 4
-# define MULTILIB_ISA_DEFAULT "mips4"
-# else
-# if MIPS_ISA_DEFAULT == 32
-# define MULTILIB_ISA_DEFAULT "mips32"
-# else
-# if MIPS_ISA_DEFAULT == 33
-# define MULTILIB_ISA_DEFAULT "mips32r2"
-# else
-# if MIPS_ISA_DEFAULT == 64
-# define MULTILIB_ISA_DEFAULT "mips64"
-# else
-# if MIPS_ISA_DEFAULT == 65
-# define MULTILIB_ISA_DEFAULT "mips64r2"
-# else
-# define MULTILIB_ISA_DEFAULT "mips1"
-# endif
-# endif
-# endif
-# endif
-# endif
-# endif
-# endif
-# endif
+#if MIPS_ISA_DEFAULT == 1
+#define MULTILIB_ISA_DEFAULT "mips1"
+#elif MIPS_ISA_DEFAULT == 2
+#define MULTILIB_ISA_DEFAULT "mips2"
+#elif MIPS_ISA_DEFAULT == 3
+#define MULTILIB_ISA_DEFAULT "mips3"
+#elif MIPS_ISA_DEFAULT == 4
+#define MULTILIB_ISA_DEFAULT "mips4"
+#elif MIPS_ISA_DEFAULT == 32
+#define MULTILIB_ISA_DEFAULT "mips32"
+#elif MIPS_ISA_DEFAULT == 33
+#define MULTILIB_ISA_DEFAULT "mips32r2"
+#elif MIPS_ISA_DEFAULT == 64
+#define MULTILIB_ISA_DEFAULT "mips64"
+#elif MIPS_ISA_DEFAULT == 65
+#define MULTILIB_ISA_DEFAULT "mips64r2"
+#else
+#define MULTILIB_ISA_DEFAULT "mips1"
+#endif
#endif
#ifndef MIPS_ABI_DEFAULT
@@ -654,21 +649,13 @@ struct mips_cpu_info {
#if MIPS_ABI_DEFAULT == ABI_32
#define MULTILIB_ABI_DEFAULT "mabi=32"
-#endif
-
-#if MIPS_ABI_DEFAULT == ABI_O64
+#elif MIPS_ABI_DEFAULT == ABI_O64
#define MULTILIB_ABI_DEFAULT "mabi=o64"
-#endif
-
-#if MIPS_ABI_DEFAULT == ABI_N32
+#elif MIPS_ABI_DEFAULT == ABI_N32
#define MULTILIB_ABI_DEFAULT "mabi=n32"
-#endif
-
-#if MIPS_ABI_DEFAULT == ABI_64
+#elif MIPS_ABI_DEFAULT == ABI_64
#define MULTILIB_ABI_DEFAULT "mabi=64"
-#endif
-
-#if MIPS_ABI_DEFAULT == ABI_EABI
+#elif MIPS_ABI_DEFAULT == ABI_EABI
#define MULTILIB_ABI_DEFAULT "mabi=eabi"
#endif
@@ -712,10 +699,10 @@ struct mips_cpu_info {
|march=r10000|march=r12000|march=r14000|march=r16000:-mips4} \
%{march=mips32|march=4kc|march=4km|march=4kp|march=4ksc:-mips32} \
%{march=mips32r2|march=m4k|march=4ke*|march=4ksd|march=24k* \
- |march=34k*|march=74k*|march=1004k*: -mips32r2} \
+ |march=34k*|march=74k*|march=m14k*|march=1004k*: -mips32r2} \
%{march=mips64|march=5k*|march=20k*|march=sb1*|march=sr71000 \
- |march=xlr|march=loongson3a: -mips64} \
- %{march=mips64r2|march=octeon: -mips64r2} \
+ |march=xlr: -mips64} \
+ %{march=mips64r2|march=loongson3a|march=octeon|march=xlp: -mips64r2} \
%{!march=*: -" MULTILIB_ISA_DEFAULT "}}"
/* A spec that infers a -mhard-float or -msoft-float setting from an
@@ -723,10 +710,10 @@ struct mips_cpu_info {
link-compatible. */
#define MIPS_ARCH_FLOAT_SPEC \
- "%{mhard-float|msoft-float|march=mips*:; \
+ "%{mhard-float|msoft-float|mno-float|march=mips*:; \
march=vr41*|march=m4k|march=4k*|march=24kc|march=24kec \
- |march=34kc|march=74kc|march=1004kc|march=5kc \
- |march=octeon|march=xlr: -msoft-float; \
+ |march=34kc|march=34kn|march=74kc|march=1004kc|march=5kc \
+ |march=m14k*|march=octeon|march=xlr: -msoft-float; \
march=*: -mhard-float}"
/* A spec condition that matches 32-bit options. It only works if
@@ -735,9 +722,14 @@ struct mips_cpu_info {
#define MIPS_32BIT_OPTION_SPEC \
"mips1|mips2|mips32*|mgp32"
-#if MIPS_ABI_DEFAULT == ABI_O64 \
- || MIPS_ABI_DEFAULT == ABI_N32 \
- || MIPS_ABI_DEFAULT == ABI_64
+/* Infer a -msynci setting from a -mips argument, on the assumption that
+ -msynci is desired where possible. */
+#define MIPS_ISA_SYNCI_SPEC \
+ "%{msynci|mno-synci:;:%{mips32r2|mips64r2:-msynci;:-mno-synci}}"
+
+#if (MIPS_ABI_DEFAULT == ABI_O64 \
+ || MIPS_ABI_DEFAULT == ABI_N32 \
+ || MIPS_ABI_DEFAULT == ABI_64)
#define OPT_ARCH64 "mabi=32|mgp32:;"
#define OPT_ARCH32 "mabi=32|mgp32"
#else
@@ -753,6 +745,7 @@ struct mips_cpu_info {
--with-abi is ignored if -mabi is specified.
--with-float is ignored if -mhard-float or -msoft-float are
specified.
+ --with-nan is ignored if -mnan is specified.
--with-divide is ignored if -mdivide-traps or -mdivide-breaks are
specified. */
#define OPTION_DEFAULT_SPECS \
@@ -764,17 +757,18 @@ struct mips_cpu_info {
{"tune_64", "%{" OPT_ARCH64 ":%{!mtune=*:-mtune=%(VALUE)}}" }, \
{"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \
{"float", "%{!msoft-float:%{!mhard-float:-m%(VALUE)-float}}" }, \
+ {"fpu", "%{!msingle-float:%{!mdouble-float:-m%(VALUE)-float}}" }, \
+ {"nan", "%{!mnan=*:-mnan=%(VALUE)}" }, \
{"divide", "%{!mdivide-traps:%{!mdivide-breaks:-mdivide-%(VALUE)}}" }, \
{"llsc", "%{!mllsc:%{!mno-llsc:-m%(VALUE)}}" }, \
{"mips-plt", "%{!mplt:%{!mno-plt:-m%(VALUE)}}" }, \
{"synci", "%{!msynci:%{!mno-synci:-m%(VALUE)}}" }
-
/* A spec that infers the -mdsp setting from an -march argument. */
#define BASE_DRIVER_SELF_SPECS \
"%{!mno-dsp: \
- %{march=24ke*|march=34k*|march=1004k*: -mdsp} \
- %{march=74k*:%{!mno-dspr2: -mdspr2 -mdsp}}}"
+ %{march=24ke*|march=34kc*|march=34kf*|march=34kx*|march=1004k*: -mdsp} \
+ %{march=74k*|march=m14ke*: %{!mno-dspr2: -mdspr2 -mdsp}}}"
#define DRIVER_SELF_SPECS BASE_DRIVER_SELF_SPECS
@@ -818,6 +812,7 @@ struct mips_cpu_info {
#define ISA_HAS_MUL3 ((TARGET_MIPS3900 \
|| TARGET_MIPS5400 \
|| TARGET_MIPS5500 \
+ || TARGET_MIPS5900 \
|| TARGET_MIPS7000 \
|| TARGET_MIPS9000 \
|| TARGET_MAD \
@@ -832,6 +827,26 @@ struct mips_cpu_info {
&& TARGET_OCTEON \
&& !TARGET_MIPS16)
+/* ISA supports instructions DMULT and DMULTU. */
+#define ISA_HAS_DMULT (TARGET_64BIT && !TARGET_MIPS5900)
+
+/* ISA supports instructions MULT and MULTU.
+ This is always true, but the macro is needed for ISA_HAS_<D>MULT
+ in mips.md. */
+#define ISA_HAS_MULT (1)
+
+/* ISA supports instructions DDIV and DDIVU. */
+#define ISA_HAS_DDIV (TARGET_64BIT && !TARGET_MIPS5900)
+
+/* ISA supports instructions DIV and DIVU.
+ This is always true, but the macro is needed for ISA_HAS_<D>DIV
+ in mips.md. */
+#define ISA_HAS_DIV (1)
+
+#define ISA_HAS_DIV3 ((TARGET_LOONGSON_2EF \
+ || TARGET_LOONGSON_3A) \
+ && !TARGET_MIPS16)
+
/* ISA has the floating-point conditional move instructions introduced
in mips4. */
#define ISA_HAS_FP_CONDMOVE ((ISA_MIPS4 \
@@ -844,10 +859,14 @@ struct mips_cpu_info {
/* ISA has the integer conditional move instructions introduced in mips4 and
ST Loongson 2E/2F. */
-#define ISA_HAS_CONDMOVE (ISA_HAS_FP_CONDMOVE || TARGET_LOONGSON_2EF)
+#define ISA_HAS_CONDMOVE (ISA_HAS_FP_CONDMOVE \
+ || TARGET_MIPS5900 \
+ || TARGET_LOONGSON_2EF)
/* ISA has LDC1 and SDC1. */
-#define ISA_HAS_LDC1_SDC1 (!ISA_MIPS1 && !TARGET_MIPS16)
+#define ISA_HAS_LDC1_SDC1 (!ISA_MIPS1 \
+ && !TARGET_MIPS5900 \
+ && !TARGET_MIPS16)
/* ISA has the mips4 FP condition code instructions: FP-compare to CC,
branch on CC, and move (both FP and non-FP) on CC. */
@@ -859,13 +878,18 @@ struct mips_cpu_info {
/* This is a catch all for other mips4 instructions: indexed load, the
FP madd and msub instructions, and the FP recip and recip sqrt
- instructions. */
+ instructions. Note that this macro should only be used by other
+ ISA_HAS_* macros. */
#define ISA_HAS_FP4 ((ISA_MIPS4 \
- || (ISA_MIPS32R2 && TARGET_FLOAT64) \
+ || ISA_MIPS32R2 \
|| ISA_MIPS64 \
|| ISA_MIPS64R2) \
&& !TARGET_MIPS16)
+/* ISA has floating-point indexed load and store instructions
+ (LWXC1, LDXC1, SWXC1 and SDXC1). */
+#define ISA_HAS_LXC1_SXC1 ISA_HAS_FP4
+
/* ISA has paired-single instructions. */
#define ISA_HAS_PAIRED_SINGLE (ISA_MIPS32R2 || ISA_MIPS64 || ISA_MIPS64R2)
@@ -874,14 +898,13 @@ struct mips_cpu_info {
&& !TARGET_MIPS16)
/* ISA has integer multiply-accumulate instructions, madd and msub. */
-#define ISA_HAS_MADD_MSUB ((ISA_MIPS32 \
- || ISA_MIPS32R2 \
- || ISA_MIPS64 \
- || ISA_MIPS64R2) \
- && !TARGET_MIPS16)
+#define ISA_HAS_MADD_MSUB (ISA_MIPS32 \
+ || ISA_MIPS32R2 \
+ || ISA_MIPS64 \
+ || ISA_MIPS64R2)
/* Integer multiply-accumulate instructions should be generated. */
-#define GENERATE_MADD_MSUB (ISA_HAS_MADD_MSUB && !TUNE_74K)
+#define GENERATE_MADD_MSUB (TARGET_IMADD && !TARGET_MIPS16)
/* ISA has floating-point madd and msub instructions 'd = a * b [+-] c'. */
#define ISA_HAS_FP_MADD4_MSUB4 ISA_HAS_FP4
@@ -891,18 +914,26 @@ struct mips_cpu_info {
/* ISA has floating-point nmadd and nmsub instructions
'd = -((a * b) [+-] c)'. */
-#define ISA_HAS_NMADD4_NMSUB4(MODE) \
- ((ISA_MIPS4 \
- || (ISA_MIPS32R2 && (MODE) == V2SFmode) \
- || ISA_MIPS64 \
- || ISA_MIPS64R2) \
- && (!TARGET_MIPS5400 || TARGET_MAD) \
- && !TARGET_MIPS16)
+#define ISA_HAS_NMADD4_NMSUB4 ISA_HAS_FP4
/* ISA has floating-point nmadd and nmsub instructions
'c = -((a * b) [+-] c)'. */
-#define ISA_HAS_NMADD3_NMSUB3(MODE) \
- TARGET_LOONGSON_2EF
+#define ISA_HAS_NMADD3_NMSUB3 TARGET_LOONGSON_2EF
+
+/* ISA has floating-point RECIP.fmt and RSQRT.fmt instructions. The
+ MIPS64 rev. 1 ISA says that RECIP.D and RSQRT.D are unpredictable when
+ doubles are stored in pairs of FPRs, so for safety's sake, we apply
+ this restriction to the MIPS IV ISA too. */
+#define ISA_HAS_FP_RECIP_RSQRT(MODE) \
+ (((ISA_HAS_FP4 \
+ && ((MODE) == SFmode \
+ || ((TARGET_FLOAT64 \
+ || ISA_MIPS32R2 \
+ || ISA_MIPS64R2) \
+ && (MODE) == DFmode))) \
+ || (TARGET_SB1 \
+ && (MODE) == V2SFmode)) \
+ && !TARGET_MIPS16)
/* ISA has count leading zeroes/ones instruction (not implemented). */
#define ISA_HAS_CLZ_CLO ((ISA_MIPS32 \
@@ -918,22 +949,22 @@ struct mips_cpu_info {
|| TARGET_SR71K) \
&& !TARGET_MIPS16)
-/* ISA has three operand multiply instructions that
- negates the result and puts the result in an accumulator. */
+/* ISA has three operand multiply instructions that negate the
+ result and put the result in an accumulator. */
#define ISA_HAS_MULS ((TARGET_MIPS5400 \
|| TARGET_MIPS5500 \
|| TARGET_SR71K) \
&& !TARGET_MIPS16)
-/* ISA has three operand multiply instructions that subtracts the
- result from a 4th operand and puts the result in an accumulator. */
+/* ISA has three operand multiply instructions that subtract the
+ result from a 4th operand and put the result in an accumulator. */
#define ISA_HAS_MSAC ((TARGET_MIPS5400 \
|| TARGET_MIPS5500 \
|| TARGET_SR71K) \
&& !TARGET_MIPS16)
-/* ISA has three operand multiply instructions that the result
- from a 4th operand and puts the result in an accumulator. */
+/* ISA has three operand multiply instructions that add the result
+ to a 4th operand and put the result in an accumulator. */
#define ISA_HAS_MACC ((TARGET_MIPS4120 \
|| TARGET_MIPS4130 \
|| TARGET_MIPS5400 \
@@ -955,9 +986,15 @@ struct mips_cpu_info {
|| TARGET_SMARTMIPS) \
&& !TARGET_MIPS16)
+/* ISA has the WSBH (word swap bytes within halfwords) instruction.
+ 64-bit targets also provide DSBH and DSHD. */
+#define ISA_HAS_WSBH ((ISA_MIPS32R2 || ISA_MIPS64R2) \
+ && !TARGET_MIPS16)
+
/* ISA has data prefetch instructions. This controls use of 'pref'. */
#define ISA_HAS_PREFETCH ((ISA_MIPS4 \
|| TARGET_LOONGSON_2EF \
+ || TARGET_MIPS5900 \
|| ISA_MIPS32 \
|| ISA_MIPS32R2 \
|| ISA_MIPS64 \
@@ -968,11 +1005,7 @@ struct mips_cpu_info {
'prefx', along with TARGET_HARD_FLOAT and TARGET_DOUBLE_FLOAT.
(prefx is a cop1x instruction, so can only be used if FP is
enabled.) */
-#define ISA_HAS_PREFETCHX ((ISA_MIPS4 \
- || ISA_MIPS32R2 \
- || ISA_MIPS64 \
- || ISA_MIPS64R2) \
- && !TARGET_MIPS16)
+#define ISA_HAS_PREFETCHX ISA_HAS_FP4
/* True if trunc.w.s and trunc.w.d are real (not synthetic)
instructions. Both require TARGET_HARD_FLOAT, and trunc.w.d
@@ -995,7 +1028,8 @@ struct mips_cpu_info {
|| ISA_MIPS64R2))
/* ISA has lwxs instruction (load w/scaled index address. */
-#define ISA_HAS_LWXS (TARGET_SMARTMIPS && !TARGET_MIPS16)
+#define ISA_HAS_LWXS ((TARGET_SMARTMIPS || TARGET_MICROMIPS) \
+ && !TARGET_MIPS16)
/* ISA has lbx, lbux, lhx, lhx, lhux, lwx, lwux, or ldx instruction. */
#define ISA_HAS_LBX (TARGET_OCTEON2)
@@ -1018,14 +1052,18 @@ struct mips_cpu_info {
and "addiu $4,$4,1". */
#define ISA_HAS_LOAD_DELAY (ISA_MIPS1 \
&& !TARGET_MIPS3900 \
- && !TARGET_MIPS16)
+ && !TARGET_MIPS5900 \
+ && !TARGET_MIPS16 \
+ && !TARGET_MICROMIPS)
/* Likewise mtc1 and mfc1. */
#define ISA_HAS_XFER_DELAY (mips_isa <= 3 \
+ && !TARGET_MIPS5900 \
&& !TARGET_LOONGSON_2EF)
/* Likewise floating-point comparisons. */
#define ISA_HAS_FCMP_DELAY (mips_isa <= 3 \
+ && !TARGET_MIPS5900 \
&& !TARGET_LOONGSON_2EF)
/* True if mflo and mfhi can be immediately followed by instructions
@@ -1045,6 +1083,7 @@ struct mips_cpu_info {
|| ISA_MIPS64 \
|| ISA_MIPS64R2 \
|| TARGET_MIPS5500 \
+ || TARGET_MIPS5900 \
|| TARGET_LOONGSON_2EF)
/* ISA includes synci, jr.hb and jalr.hb. */
@@ -1062,12 +1101,15 @@ struct mips_cpu_info {
/* ISA includes ll and sc. Note that this implies ISA_HAS_SYNC
because the expanders use both ISA_HAS_SYNC and ISA_HAS_LL_SC
instructions. */
-#define ISA_HAS_LL_SC (mips_isa >= 2 && !TARGET_MIPS16)
+#define ISA_HAS_LL_SC (mips_isa >= 2 && !TARGET_MIPS5900 && !TARGET_MIPS16)
#define GENERATE_LL_SC \
(target_flags_explicit & MASK_LLSC \
? TARGET_LLSC && !TARGET_MIPS16 \
: ISA_HAS_LL_SC)
+#define ISA_HAS_SWAP (TARGET_XLP)
+#define ISA_HAS_LDADD (TARGET_XLP)
+
/* ISA includes the baddu instruction. */
#define ISA_HAS_BADDU (TARGET_OCTEON && !TARGET_MIPS16)
@@ -1126,19 +1168,24 @@ struct mips_cpu_info {
%{G*} %(endian_spec) %{mips1} %{mips2} %{mips3} %{mips4} \
%{mips32*} %{mips64*} \
%{mips16} %{mno-mips16:-no-mips16} \
+%{mmicromips} %{mno-micromips} \
%{mips3d} %{mno-mips3d:-no-mips3d} \
%{mdmx} %{mno-mdmx:-no-mdmx} \
%{mdsp} %{mno-dsp} \
%{mdspr2} %{mno-dspr2} \
+%{mmcu} %{mno-mcu} \
+%{meva} %{mno-eva} \
+%{mvirt} %{mno-virt} \
%{msmartmips} %{mno-smartmips} \
%{mmt} %{mno-mt} \
+%{mfix-rm7000} %{mno-fix-rm7000} \
%{mfix-vr4120} %{mfix-vr4130} \
%{mfix-24k} \
%{noasmopt:-O0; O0|fno-delayed-branch:-O1; O*:-O2; :-O1} \
%(subtarget_asm_debugging_spec) \
%{mabi=*} %{!mabi=*: %(asm_abi_default_spec)} \
%{mgp32} %{mgp64} %{march=*} %{mxgot:-xgot} \
-%{mfp32} %{mfp64} \
+%{mfp32} %{mfp64} %{mnan=*} \
%{mshared} %{mno-shared} \
%{msym32} %{mno-sym32} \
%{mtune=*} \
@@ -1348,8 +1395,8 @@ struct mips_cpu_info {
#define MAX_FIXED_MODE_SIZE LONG_DOUBLE_TYPE_SIZE
#ifdef IN_LIBGCC2
-#if (defined _ABIN32 && _MIPS_SIM == _ABIN32) \
- || (defined _ABI64 && _MIPS_SIM == _ABI64)
+#if ((defined _ABIN32 && _MIPS_SIM == _ABIN32) \
+ || (defined _ABI64 && _MIPS_SIM == _ABI64))
# define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128
# else
# define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
@@ -1640,8 +1687,11 @@ struct mips_cpu_info {
#define COP3_REG_FIRST 144
#define COP3_REG_LAST 175
#define COP3_REG_NUM (COP3_REG_LAST - COP3_REG_FIRST + 1)
-/* ALL_COP_REG_NUM assumes that COP0,2,and 3 are numbered consecutively. */
-#define ALL_COP_REG_NUM (COP3_REG_LAST - COP0_REG_FIRST + 1)
+
+/* These definitions assume that COP0, 2 and 3 are numbered consecutively. */
+#define ALL_COP_REG_FIRST COP0_REG_FIRST
+#define ALL_COP_REG_LAST COP3_REG_LAST
+#define ALL_COP_REG_NUM (ALL_COP_REG_LAST - ALL_COP_REG_FIRST + 1)
#define DSP_ACC_REG_FIRST 176
#define DSP_ACC_REG_LAST 181
@@ -1671,6 +1721,8 @@ struct mips_cpu_info {
((unsigned int) ((int) (REGNO) - GP_REG_FIRST) < GP_REG_NUM)
#define M16_REG_P(REGNO) \
(((REGNO) >= 2 && (REGNO) <= 7) || (REGNO) == 16 || (REGNO) == 17)
+#define M16STORE_REG_P(REGNO) \
+ (((REGNO) >= 2 && (REGNO) <= 7) || (REGNO) == 0 || (REGNO) == 17)
#define FP_REG_P(REGNO) \
((unsigned int) ((int) (REGNO) - FP_REG_FIRST) < FP_REG_NUM)
#define MD_REG_P(REGNO) \
@@ -1742,6 +1794,9 @@ struct mips_cpu_info {
- The prologue can use MIPS_PROLOGUE_TEMP as a general temporary
register. The register must not conflict with MIPS16_PIC_TEMP.
+ - If we aren't generating MIPS16 code, the prologue can also use
+ MIPS_PROLOGUE_TEMP2 as a general temporary register.
+
- The epilogue can use MIPS_EPILOGUE_TEMP as a general temporary
register.
@@ -1758,6 +1813,10 @@ struct mips_cpu_info {
#define MIPS16_PIC_TEMP_REGNUM (GP_REG_FIRST + 2)
#define MIPS_PROLOGUE_TEMP_REGNUM \
(cfun->machine->interrupt_handler_p ? K0_REG_NUM : GP_REG_FIRST + 3)
+#define MIPS_PROLOGUE_TEMP2_REGNUM \
+ (TARGET_MIPS16 \
+ ? (gcc_unreachable (), INVALID_REGNUM) \
+ : cfun->machine->interrupt_handler_p ? K1_REG_NUM : GP_REG_FIRST + 12)
#define MIPS_EPILOGUE_TEMP_REGNUM \
(cfun->machine->interrupt_handler_p \
? K0_REG_NUM \
@@ -1765,6 +1824,8 @@ struct mips_cpu_info {
#define MIPS16_PIC_TEMP gen_rtx_REG (Pmode, MIPS16_PIC_TEMP_REGNUM)
#define MIPS_PROLOGUE_TEMP(MODE) gen_rtx_REG (MODE, MIPS_PROLOGUE_TEMP_REGNUM)
+#define MIPS_PROLOGUE_TEMP2(MODE) \
+ gen_rtx_REG (MODE, MIPS_PROLOGUE_TEMP2_REGNUM)
#define MIPS_EPILOGUE_TEMP(MODE) gen_rtx_REG (MODE, MIPS_EPILOGUE_TEMP_REGNUM)
/* Define this macro if it is as good or better to call a constant
@@ -2024,6 +2085,7 @@ enum reg_class
#define SMALL_INT(X) SMALL_OPERAND (INTVAL (X))
#define SMALL_INT_UNSIGNED(X) SMALL_OPERAND_UNSIGNED (INTVAL (X))
#define LUI_INT(X) LUI_OPERAND (INTVAL (X))
+#define UMIPS_12BIT_OFFSET_P(OFFSET) (IN_RANGE (OFFSET, -2048, 2047))
/* The HI and LO registers can only be reloaded via the general
registers. Condition code registers can only be loaded to the
@@ -2336,13 +2398,19 @@ typedef struct mips_args {
/* True if we're generating a form of MIPS16 code in which jump tables
are stored in the text section and encoded as 16-bit PC-relative
offsets. This is only possible when general text loads are allowed,
- since the table access itself will be an "lh" instruction. */
-/* ??? 16-bit offsets can overflow in large functions. */
+ since the table access itself will be an "lh" instruction. If the
+ PC-relative offsets grow too large, 32-bit offsets are used instead. */
#define TARGET_MIPS16_SHORT_JUMP_TABLES TARGET_MIPS16_TEXT_LOADS
#define JUMP_TABLES_IN_TEXT_SECTION TARGET_MIPS16_SHORT_JUMP_TABLES
-#define CASE_VECTOR_MODE (TARGET_MIPS16_SHORT_JUMP_TABLES ? HImode : ptr_mode)
+#define CASE_VECTOR_MODE (TARGET_MIPS16_SHORT_JUMP_TABLES ? SImode : ptr_mode)
+
+/* Only use short offsets if their range will not overflow. */
+#define CASE_VECTOR_SHORTEN_MODE(MIN, MAX, BODY) \
+ (!TARGET_MIPS16_SHORT_JUMP_TABLES ? ptr_mode \
+ : ((MIN) >= -32768 && (MAX) < 32768) ? HImode \
+ : SImode)
#define CASE_VECTOR_PC_RELATIVE TARGET_MIPS16_SHORT_JUMP_TABLES
@@ -2395,12 +2463,8 @@ typedef struct mips_args {
#define FUNCTION_MODE SImode
-
-/* Define if copies to/from condition code registers should be avoided.
-
- This is needed for the MIPS because reload_outcc is not complete;
- it needs to handle cases where the source is a general or another
- condition code register. */
+/* We allocate $fcc registers by hand and can't cope with moves of
+ CCmode registers to and from pseudos (or memory). */
#define AVOID_CCMODE_COPIES
/* A C expression for the cost of a branch instruction. A value of
@@ -2409,6 +2473,14 @@ typedef struct mips_args {
#define BRANCH_COST(speed_p, predictable_p) mips_branch_cost
#define LOGICAL_OP_NON_SHORT_CIRCUIT 0
+/* The MIPS port has several functions that return an instruction count.
+ Multiplying the count by this value gives the number of bytes that
+ the instructions occupy. */
+#define BASE_INSN_LENGTH (TARGET_MIPS16 ? 2 : 4)
+
+/* The length of a NOP in bytes. */
+#define NOP_INSN_LENGTH (TARGET_COMPRESSION ? 2 : 4)
+
/* If defined, modifies the length assigned to instruction INSN as a
function of the context in which it is used. LENGTH is an lvalue
that contains the initially computed length of the insn and should
@@ -2440,17 +2512,34 @@ typedef struct mips_args {
all calls should use assembly macros. Otherwise, all indirect
calls should use "jr" or "jalr"; we will arrange to restore $gp
afterwards if necessary. Finally, we can only generate direct
- calls for -mabicalls by temporarily switching to non-PIC mode. */
+ calls for -mabicalls by temporarily switching to non-PIC mode.
+
+ For microMIPS jal(r), we try to generate jal(r)s when a 16-bit
+ instruction is in the delay slot of jal(r). */
#define MIPS_CALL(INSN, OPERANDS, TARGET_OPNO, SIZE_OPNO) \
(TARGET_USE_GOT && !TARGET_EXPLICIT_RELOCS \
? "%*" INSN "\t%" #TARGET_OPNO "%/" \
- : (REG_P (OPERANDS[TARGET_OPNO]) \
- && mips_get_pic_call_symbol (OPERANDS, SIZE_OPNO)) \
- ? ("%*.reloc\t1f,R_MIPS_JALR,%" #SIZE_OPNO "\n" \
- "1:\t" INSN "r\t%" #TARGET_OPNO "%/") \
: REG_P (OPERANDS[TARGET_OPNO]) \
- ? "%*" INSN "r\t%" #TARGET_OPNO "%/" \
- : MIPS_ABSOLUTE_JUMP ("%*" INSN "\t%" #TARGET_OPNO "%/"))
+ ? (mips_get_pic_call_symbol (OPERANDS, SIZE_OPNO) \
+ ? ("%*.reloc\t1f,R_MIPS_JALR,%" #SIZE_OPNO "\n" \
+ "1:\t" INSN "r\t%" #TARGET_OPNO "%/") \
+ : TARGET_MICROMIPS && !TARGET_INTERLINK_COMPRESSED \
+ ? "%*" INSN "r%!\t%" #TARGET_OPNO "%/" \
+ : "%*" INSN "r\t%" #TARGET_OPNO "%/") \
+ : TARGET_MICROMIPS && !TARGET_INTERLINK_COMPRESSED \
+ ? MIPS_ABSOLUTE_JUMP ("%*" INSN "%!\t%" #TARGET_OPNO "%/") \
+ : MIPS_ABSOLUTE_JUMP ("%*" INSN "\t%" #TARGET_OPNO "%/")) \
+
+/* Similar to MIPS_CALL, but this is for MICROMIPS "j" to generate
+ "jrc" when nop is in the delay slot of "jr". */
+
+#define MICROMIPS_J(INSN, OPERANDS, OPNO) \
+ (TARGET_USE_GOT && !TARGET_EXPLICIT_RELOCS \
+ ? "%*j\t%" #OPNO "%/" \
+ : REG_P (OPERANDS[OPNO]) \
+ ? "%*jr%:\t%" #OPNO \
+ : MIPS_ABSOLUTE_JUMP ("%*" INSN "\t%" #OPNO "%/"))
+
/* Control the assembler format that we output. */
@@ -2531,15 +2620,9 @@ typedef struct mips_args {
{ "gp", 28 + GP_REG_FIRST }, \
{ "sp", 29 + GP_REG_FIRST }, \
{ "fp", 30 + GP_REG_FIRST }, \
- { "ra", 31 + GP_REG_FIRST }, \
- ALL_COP_ADDITIONAL_REGISTER_NAMES \
+ { "ra", 31 + GP_REG_FIRST } \
}
-/* This is meant to be redefined in the host dependent files. It is a
- set of alternative names and regnums for mips coprocessors. */
-
-#define ALL_COP_ADDITIONAL_REGISTER_NAMES
-
#define DBR_OUTPUT_SEQEND(STREAM) \
do \
{ \
@@ -2551,10 +2634,6 @@ do \
} \
while (0)
-/* Use .loc directives for SDB line numbers. */
-#define SDB_OUTPUT_SOURCE_LINE(STREAM, LINE) \
- fprintf (STREAM, "\t.loc\t%d %d\n", num_source_filenames, LINE)
-
/* The MIPS implementation uses some labels for its own purpose. The
following lists what labels are created, and are all formed by the
pattern $L[a-z].*. The machine independent portion of GCC creates
@@ -2652,8 +2731,14 @@ while (0)
#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \
do { \
if (TARGET_MIPS16_SHORT_JUMP_TABLES) \
- fprintf (STREAM, "\t.half\t%sL%d-%sL%d\n", \
- LOCAL_LABEL_PREFIX, VALUE, LOCAL_LABEL_PREFIX, REL); \
+ { \
+ if (GET_MODE (BODY) == HImode) \
+ fprintf (STREAM, "\t.half\t%sL%d-%sL%d\n", \
+ LOCAL_LABEL_PREFIX, VALUE, LOCAL_LABEL_PREFIX, REL); \
+ else \
+ fprintf (STREAM, "\t.word\t%sL%d-%sL%d\n", \
+ LOCAL_LABEL_PREFIX, VALUE, LOCAL_LABEL_PREFIX, REL); \
+ } \
else if (TARGET_GPWORD) \
fprintf (STREAM, "\t%s\t%sL%d\n", \
ptr_mode == DImode ? ".gpdword" : ".gpword", \
@@ -2692,15 +2777,6 @@ do { \
#undef ASM_OUTPUT_ASCII
#define ASM_OUTPUT_ASCII mips_output_ascii
-/* Output #ident as a in the read-only data section. */
-#undef ASM_OUTPUT_IDENT
-#define ASM_OUTPUT_IDENT(FILE, STRING) \
-{ \
- const char *p = STRING; \
- int size = strlen (p) + 1; \
- switch_to_section (readonly_data_section); \
- assemble_string (p, size); \
-}
/* Default to -G 8 */
#ifndef MIPS_DEFAULT_GVALUE
@@ -2810,7 +2886,6 @@ while (0)
#define STORE_BY_PIECES_P(SIZE, ALIGN) \
mips_store_by_pieces_p (SIZE, ALIGN)
-#ifndef __mips16
/* Since the bits of the _init and _fini function is spread across
many object files, each potentially with its own GP, we must assume
we need to load our GP. We don't preserve $gp or $ra, since each
@@ -2819,32 +2894,40 @@ while (0)
#if (defined _ABIO32 && _MIPS_SIM == _ABIO32)
#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
asm (SECTION_OP "\n\
+ .set push\n\
+ .set nomips16\n\
.set noreorder\n\
bal 1f\n\
nop\n\
1: .cpload $31\n\
.set reorder\n\
jal " USER_LABEL_PREFIX #FUNC "\n\
+ .set pop\n\
" TEXT_SECTION_ASM_OP);
-#endif /* Switch to #elif when we're no longer limited by K&R C. */
-#if (defined _ABIN32 && _MIPS_SIM == _ABIN32) \
- || (defined _ABI64 && _MIPS_SIM == _ABI64)
+#elif ((defined _ABIN32 && _MIPS_SIM == _ABIN32) \
+ || (defined _ABI64 && _MIPS_SIM == _ABI64))
#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
asm (SECTION_OP "\n\
+ .set push\n\
+ .set nomips16\n\
.set noreorder\n\
bal 1f\n\
nop\n\
1: .set reorder\n\
.cpsetup $31, $2, 1b\n\
jal " USER_LABEL_PREFIX #FUNC "\n\
+ .set pop\n\
" TEXT_SECTION_ASM_OP);
#endif
-#endif
#ifndef HAVE_AS_TLS
#define HAVE_AS_TLS 0
#endif
+#ifndef HAVE_AS_NAN
+#define HAVE_AS_NAN 0
+#endif
+
#ifndef USED_FOR_TARGET
/* Information about ".set noFOO; ...; .set FOO" blocks. */
struct mips_asm_switch {
@@ -2874,7 +2957,7 @@ extern enum processor mips_tune; /* which cpu to schedule for */
extern int mips_isa; /* architectural level */
extern const struct mips_cpu_info *mips_arch_info;
extern const struct mips_cpu_info *mips_tune_info;
-extern bool mips_base_mips16;
+extern unsigned int mips_base_compression_flags;
extern GTY(()) struct target_globals *mips16_globals;
#endif
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index e5d716dfa4..1e3e9e6595 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -1,8 +1,5 @@
;; Mips.md Machine Description for MIPS based processors
-;; Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-;; 2011, 2012
-;; Free Software Foundation, Inc.
+;; 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
@@ -54,9 +51,11 @@
r4300
r4600
r4650
+ r4700
r5000
r5400
r5500
+ r5900
r7000
r8000
r9000
@@ -65,6 +64,7 @@
sb1a
sr71000
xlr
+ xlp
])
(define_c_enum "unspec" [
@@ -74,6 +74,11 @@
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
@@ -81,6 +86,10 @@
UNSPEC_MFHC1
UNSPEC_MTHC1
+ ;; Floating-point environment.
+ UNSPEC_GET_FCSR
+ UNSPEC_SET_FCSR
+
;; HI/LO moves.
UNSPEC_MFHI
UNSPEC_MTHI
@@ -132,10 +141,19 @@
;; 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)
@@ -192,16 +210,15 @@
;; loadpool move a constant into a MIPS16 register by loading it
;; from the pool
;; shift_shift a shift left followed by a shift right
-;; lui_movf an LUI followed by a MOVF (for d<-z CC moves)
;;
;; 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,mthilo,mfhilo,move,fmove,
+ "unknown,load,fpload,store,fpstore,mtc,mfc,mtlo,mflo,imul,move,fmove,
const,constN,signext,ext_ins,logical,arith,sll0,andi,loadpool,
- shift_shift,lui_movf"
+ shift_shift"
(const_string "unknown"))
(define_attr "alu_type" "unknown,add,sub,not,nor,and,or,xor"
@@ -222,6 +239,59 @@
(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
@@ -237,8 +307,10 @@
;; condmove conditional moves
;; mtc transfer to coprocessor
;; mfc transfer from coprocessor
-;; mthilo transfer to hi/lo registers
-;; mfhilo transfer from hi/lo registers
+;; 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
@@ -271,15 +343,25 @@
;; 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,mthilo,mfhilo,const,arith,logical,
+ 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,multi,nop,ghost"
+ 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")
@@ -296,10 +378,11 @@
(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" "mthilo") (const_string "mthilo")
- (eq_attr "move_type" "mfhilo") (const_string "mfhilo")
+ (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")
@@ -318,9 +401,8 @@
(eq_attr "dword_mode" "yes"))
(const_string "multi")
(eq_attr "move_type" "move") (const_string "move")
- (eq_attr "move_type" "const") (const_string "const")]
- ;; We classify "lui_movf" as "unknown" rather than "multi"
- ;; because we don't split it. FIXME: we should split instead.
+ (eq_attr "move_type" "const") (const_string "const")
+ (eq_attr "sync_mem" "!none") (const_string "syncloop")]
(const_string "unknown")))
;; Mode for conversion types (fcvt)
@@ -336,64 +418,116 @@
;; Is this an extended instruction in mips16 mode?
(define_attr "extended_mips16" "no,yes"
- (if_then_else (ior (eq_attr "move_type" "sll0")
- (eq_attr "type" "branch")
- (eq_attr "jal" "direct"))
+ (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")))
-;; 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
-;; $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]
-;; 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
-;; - 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_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"))
-(define_attr "sync_release_barrier" "yes,no"
- (const_string "yes"))
+(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)
-;; Length of instruction in bytes.
+ ;; 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 "extended_mips16" "yes")
- (match_test "TARGET_MIPS16"))
- (const_int 8)
-
- ;; Direct branch instructions have a range of [-0x20000,0x1fffc],
- ;; relative to the address of the delay slot. If a branch is
- ;; outside this range, we have a choice of two sequences.
+ (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
@@ -416,14 +550,28 @@
;; using la/jr in this case too, but we do not do so at
;; present.
;;
- ;; Note that this value does not account for the delay slot
+ ;; 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 values for
- ;; forward and backward branches will be different as well.
- (eq_attr "type" "branch")
- (cond [(and (le (minus (match_dup 0) (pc)) (const_int 131064))
- (le (minus (pc) (match_dup 0)) (const_int 131068)))
+ ;; 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.
@@ -438,89 +586,93 @@
;; of an insn.
(const_int MAX_PIC_BRANCH_LENGTH))
- ;; "Ghost" instructions occupy no space.
- (eq_attr "type" "ghost")
- (const_int 0)
-
- (eq_attr "got" "load")
- (if_then_else (match_test "TARGET_MIPS16")
- (const_int 8)
- (const_int 4))
- (eq_attr "got" "xgot_high")
- (const_int 8)
-
- ;; In general, constant-pool loads are extended instructions.
- (eq_attr "move_type" "loadpool")
- (const_int 8)
-
- ;; LUI_MOVFs are decomposed into two separate instructions.
- (eq_attr "move_type" "lui_movf")
- (const_int 8)
-
- ;; 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 16)
- (const_int 8))
-
- ;; Check for doubleword moves that are decomposed into two
- ;; instructions.
- (and (eq_attr "move_type" "mtc,mfc,mthilo,mfhilo,move")
- (eq_attr "dword_mode" "yes"))
- (const_int 8)
-
- ;; Doubleword CONST{,N} moves are split into two word
- ;; CONST{,N} moves.
- (and (eq_attr "move_type" "const,constN")
- (eq_attr "dword_mode" "yes"))
- (symbol_ref "mips_split_const_insns (operands[1]) * 4")
-
- ;; Otherwise, constants, loads and stores are handled by external
- ;; routines.
- (eq_attr "move_type" "const,constN")
- (symbol_ref "mips_const_insns (operands[1]) * 4")
- (eq_attr "move_type" "load,fpload")
- (symbol_ref "mips_load_store_insns (operands[1], insn) * 4")
- (eq_attr "move_type" "store,fpstore")
- (cond [(not (match_test "TARGET_FIX_24K"))
- (symbol_ref "mips_load_store_insns (operands[0], insn) * 4")]
- (symbol_ref "mips_load_store_insns (operands[0], insn) * 4 + 4"))
-
- ;; In the worst case, a call macro will take 8 instructions:
+ ;; 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):
;;
- ;; 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 32)
-
- ;; 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 8)
-
- ;; 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")
- (and (eq_attr "mode" "DI")
- (match_test "TARGET_FIX_VR4120")))
- (const_int 8)
-
- (eq_attr "type" "idiv,idiv3")
- (symbol_ref "mips_idiv_insns () * 4")
-
- (not (eq_attr "sync_mem" "none"))
- (symbol_ref "mips_sync_loop_insns (insn, operands) * 4")
- ] (const_int 4)))
+ ;; 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"
@@ -548,21 +700,16 @@
(match_test "TARGET_FIX_R4000"))
(const_string "hilo")
- (and (eq_attr "type" "mfhilo")
+ (and (eq_attr "type" "mfhi,mflo")
(not (match_test "ISA_HAS_HILO_INTERLOCKS")))
(const_string "hilo")]
(const_string "none")))
-;; Is it a single instruction?
-(define_attr "single_insn" "no,yes"
- (symbol_ref "(get_attr_length (insn) == (TARGET_MIPS16 ? 2 : 4)
- ? SINGLE_INSN_YES : SINGLE_INSN_NO)"))
-
;; 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")
- (and (eq_attr "hazard" "none")
- (eq_attr "single_insn" "yes")))
+ (eq_attr "hazard" "none")
+ (match_test "get_attr_insn_count (insn) == 1"))
(const_string "yes")
(const_string "no")))
@@ -576,7 +723,7 @@
;; 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,mthilo")
+ (if_then_else (eq_attr "type" "imul,imul3,imadd,idiv,mthi,mtlo")
(const_string "yes")
(const_string "no")))
@@ -593,6 +740,9 @@
;; 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")])
@@ -604,7 +754,9 @@
;; 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")])
+ (CC "TARGET_HARD_FLOAT
+ && !TARGET_LOONGSON_2EF
+ && !TARGET_MIPS5900")])
;; 32-bit integer moves for which we provide move patterns.
(define_mode_iterator IMOVE32
@@ -735,15 +887,6 @@
(define_mode_attr sqrt_condition
[(SF "!ISA_MIPS1") (DF "!ISA_MIPS1") (V2SF "TARGET_SB1")])
-;; This attribute gives the conditions under which RECIP.fmt and RSQRT.fmt
-;; instructions can be used. The MIPS32 and MIPS64 ISAs say that RECIP.D
-;; and RSQRT.D are unpredictable when doubles are stored in pairs of FPRs,
-;; so for safety's sake, we apply this restriction to all targets.
-(define_mode_attr recip_condition
- [(SF "ISA_HAS_FP4")
- (DF "ISA_HAS_FP4 && TARGET_FLOAT64")
- (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])
@@ -828,6 +971,10 @@
(xor "xori")
(and "andi")])
+(define_code_attr shift_compression [(ashift "micromips")
+ (lshiftrt "micromips")
+ (ashiftrt "none")])
+
;; <fcond> is the c.cond.fmt condition associated with a particular code.
(define_code_attr fcond [(unordered "un")
(uneq "ueq")
@@ -927,6 +1074,7 @@
(include "sb1.md")
(include "sr71k.md")
(include "xlr.md")
+(include "xlp.md")
(include "generic.md")
;;
@@ -994,43 +1142,39 @@
"")
(define_insn "*add<mode>3"
- [(set (match_operand:GPR 0 "register_operand" "=d,d")
- (plus:GPR (match_operand:GPR 1 "register_operand" "d,d")
- (match_operand:GPR 2 "arith_operand" "d,Q")))]
+ [(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"
- "@
- <d>addu\t%0,%1,%2
- <d>addiu\t%0,%1,%2"
+{
+ if (which_alternative == 0
+ || which_alternative == 1)
+ return "<d>addu\t%0,%1,%2";
+ else
+ return "<d>addiu\t%0,%1,%2";
+}
[(set_attr "alu_type" "add")
+ (set_attr "compression" "micromips,*,micromips,micromips,micromips,micromips,*")
(set_attr "mode" "<MODE>")])
(define_insn "*add<mode>3_mips16"
- [(set (match_operand:GPR 0 "register_operand" "=ks,d,d,d,d")
- (plus:GPR (match_operand:GPR 1 "register_operand" "ks,ks,0,d,d")
- (match_operand:GPR 2 "arith_operand" "Q,Q,Q,O,d")))]
+ [(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<si8_di5>,Q,Usb<si8_di5>,Q,Usb4,O,d")))]
"TARGET_MIPS16"
"@
<d>addiu\t%0,%2
+ <d>addiu\t%0,%2
<d>addiu\t%0,%1,%2
+ <d>addiu\t%0,%1,%2
+ <d>addiu\t%0,%2
<d>addiu\t%0,%2
<d>addiu\t%0,%1,%2
+ <d>addiu\t%0,%1,%2
<d>addu\t%0,%1,%2"
[(set_attr "alu_type" "add")
(set_attr "mode" "<MODE>")
- (set_attr_alternative "length"
- [(if_then_else (match_operand 2 "m16_simm8_8")
- (const_int 4)
- (const_int 8))
- (if_then_else (match_operand 2 "m16_uimm<si8_di5>_4")
- (const_int 4)
- (const_int 8))
- (if_then_else (match_operand 2 "m16_simm<si8_di5>_1")
- (const_int 4)
- (const_int 8))
- (if_then_else (match_operand 2 "m16_simm4_1")
- (const_int 4)
- (const_int 8))
- (const_int 4)])])
+ (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
@@ -1222,12 +1366,13 @@
(set_attr "mode" "<UNITMODE>")])
(define_insn "sub<mode>3"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (minus:GPR (match_operand:GPR 1 "register_operand" "d")
- (match_operand:GPR 2 "register_operand" "d")))]
+ [(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")))]
""
"<d>subu\t%0,%1,%2"
[(set_attr "alu_type" "sub")
+ (set_attr "compression" "micromips,*")
(set_attr "mode" "<MODE>")])
(define_insn "*subsi3_extended"
@@ -1276,7 +1421,7 @@
"mul.<fmt>\t%0,%1,%2\;nop"
[(set_attr "type" "fmul")
(set_attr "mode" "<MODE>")
- (set_attr "length" "8")])
+ (set_attr "insn_count" "2")])
(define_insn "mulv2sf3"
[(set (match_operand:V2SF 0 "register_operand" "=f")
@@ -1337,7 +1482,7 @@
[(set (match_operand:GPR 0 "register_operand")
(mult:GPR (match_operand:GPR 1 "register_operand")
(match_operand:GPR 2 "register_operand")))]
- ""
+ "ISA_HAS_<D>MULT"
{
rtx lo;
@@ -1383,7 +1528,7 @@
{
if (which_alternative == 1)
return "<d>mult\t%1,%2";
- if (<MODE>mode == SImode && TARGET_MIPS3900)
+ if (<MODE>mode == SImode && (TARGET_MIPS3900 || TARGET_MIPS5900))
return "mult\t%0,%1,%2";
return "<d>mul\t%0,%1,%2";
}
@@ -1417,7 +1562,7 @@
[(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")))]
- "!TARGET_FIX_R4000"
+ "ISA_HAS_<D>MULT && !TARGET_FIX_R4000"
"<d>mult\t%1,%2"
[(set_attr "type" "imul")
(set_attr "mode" "<MODE>")])
@@ -1427,11 +1572,11 @@
(mult:GPR (match_operand:GPR 1 "register_operand" "d")
(match_operand:GPR 2 "register_operand" "d")))
(clobber (match_scratch:GPR 3 "=l"))]
- "TARGET_FIX_R4000"
+ "ISA_HAS_<D>MULT && TARGET_FIX_R4000"
"<d>mult\t%1,%2\;mflo\t%0"
[(set_attr "type" "imul")
(set_attr "mode" "<MODE>")
- (set_attr "length" "8")])
+ (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
@@ -1489,8 +1634,9 @@
madd\t%1,%2
#"
[(set_attr "type" "imadd")
+ (set_attr "accum_in" "3")
(set_attr "mode" "SI")
- (set_attr "length" "4,8")])
+ (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.
@@ -1507,8 +1653,9 @@
madd\t%0,%1,%2
#"
[(set_attr "type" "imadd")
+ (set_attr "accum_in" "3")
(set_attr "mode" "SI")
- (set_attr "length" "4,4,8")])
+ (set_attr "insn_count" "1,1,2")])
;; Split *mul_acc_si if both the source and destination accumulator
;; values are GPRs.
@@ -1545,6 +1692,7 @@
return "%[macc\t%@,%1,%2%]";
}
[(set_attr "type" "imadd")
+ (set_attr "accum_in" "3")
(set_attr "mode" "SI")])
(define_insn "*msac"
@@ -1563,6 +1711,7 @@
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.
@@ -1586,7 +1735,8 @@
(clobber (match_dup 4))])]
""
[(set_attr "type" "imadd")
- (set_attr "length" "8")])
+ (set_attr "accum_in" "1")
+ (set_attr "insn_count" "2")])
;; Patterns generated by the define_peephole2 below.
@@ -1602,6 +1752,7 @@
"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"
@@ -1616,6 +1767,7 @@
"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,<r1>,<r2> & mflo <r3> into macc <r3>,<r1>,<r2>
@@ -1718,8 +1870,9 @@
msub\t%2,%3
#"
[(set_attr "type" "imadd")
+ (set_attr "accum_in" "1")
(set_attr "mode" "SI")
- (set_attr "length" "4,8")])
+ (set_attr "insn_count" "1,2")])
;; Split *mul_sub_si if both the source and destination accumulator
;; values are GPRs.
@@ -1800,7 +1953,7 @@
"mult<u>\t%1,%2\;mflo\t%L0\;mfhi\t%M0"
[(set_attr "type" "imul")
(set_attr "mode" "SI")
- (set_attr "length" "12")])
+ (set_attr "insn_count" "3")])
(define_insn_and_split "<u>mulsidi3_64bit"
[(set (match_operand:DI 0 "register_operand" "=d")
@@ -1819,10 +1972,10 @@
}
[(set_attr "type" "imul")
(set_attr "mode" "SI")
- (set (attr "length")
+ (set (attr "insn_count")
(if_then_else (match_test "ISA_HAS_EXT_INS")
- (const_int 16)
- (const_int 28)))])
+ (const_int 4)
+ (const_int 7)))])
(define_expand "<u>mulsidi3_64bit_mips16"
[(set (match_operand:DI 0 "register_operand")
@@ -1886,7 +2039,7 @@
(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"))]
- "TARGET_64BIT && ISA_HAS_DMUL3"
+ "ISA_HAS_DMUL3"
"dmul\t%0,%1,%2"
[(set_attr "type" "imul3")
(set_attr "mode" "DI")])
@@ -1927,6 +2080,7 @@
return "msac<u>\t$0,%1,%2";
}
[(set_attr "type" "imadd")
+ (set_attr "accum_in" "3")
(set_attr "mode" "SI")])
;; _highpart patterns
@@ -1972,7 +2126,7 @@
}
[(set_attr "type" "imul")
(set_attr "mode" "SI")
- (set_attr "length" "8")])
+ (set_attr "insn_count" "2")])
(define_expand "<su>mulsi3_highpart_split"
[(set (match_operand:SI 0 "register_operand")
@@ -2039,7 +2193,7 @@
(mult:TI (any_extend:TI (match_operand:DI 1 "register_operand"))
(any_extend:TI (match_operand:DI 2 "register_operand")))
(const_int 64))))]
- "TARGET_64BIT && !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)"
+ "ISA_HAS_DMULT && !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)"
{
if (TARGET_MIPS16)
emit_insn (gen_<su>muldi3_highpart_split (operands[0], operands[1],
@@ -2058,7 +2212,7 @@
(any_extend:TI (match_operand:DI 2 "register_operand" "d")))
(const_int 64))))
(clobber (match_scratch:DI 3 "=l"))]
- "TARGET_64BIT
+ "ISA_HAS_DMULT
&& !TARGET_MIPS16
&& !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)"
{ return TARGET_FIX_R4000 ? "dmult<u>\t%1,%2\n\tmfhi\t%0" : "#"; }
@@ -2071,7 +2225,7 @@
}
[(set_attr "type" "imul")
(set_attr "mode" "DI")
- (set_attr "length" "8")])
+ (set_attr "insn_count" "2")])
(define_expand "<su>muldi3_highpart_split"
[(set (match_operand:DI 0 "register_operand")
@@ -2094,7 +2248,7 @@
[(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"))))]
- "TARGET_64BIT && !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)"
+ "ISA_HAS_DMULT && !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)"
{
rtx hilo;
@@ -2116,7 +2270,7 @@
[(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"))))]
- "TARGET_64BIT
+ "ISA_HAS_DMULT
&& !TARGET_FIX_R4000
&& !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)"
"dmult<u>\t%1,%2"
@@ -2128,13 +2282,13 @@
(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"))]
- "TARGET_64BIT
+ "ISA_HAS_DMULT
&& TARGET_FIX_R4000
&& !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)"
"dmult<u>\t%1,%2\;mflo\t%L0\;mfhi\t%M0"
[(set_attr "type" "imul")
(set_attr "mode" "DI")
- (set_attr "length" "12")])
+ (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.
@@ -2147,6 +2301,7 @@
"TARGET_MAD"
"mad\t%1,%2"
[(set_attr "type" "imadd")
+ (set_attr "accum_in" "0")
(set_attr "mode" "SI")])
;; See the comment above <u>msubsidi4 for the relationship between
@@ -2171,6 +2326,7 @@
return "%[macc<u>\t%@,%1,%2%]";
}
[(set_attr "type" "imadd")
+ (set_attr "accum_in" "3")
(set_attr "mode" "SI")])
;; Floating point multiply accumulate instructions.
@@ -2183,6 +2339,7 @@
"ISA_HAS_FP_MADD4_MSUB4 && TARGET_FUSED_MADD"
"madd.<fmt>\t%0,%3,%1,%2"
[(set_attr "type" "fmadd")
+ (set_attr "accum_in" "3")
(set_attr "mode" "<UNITMODE>")])
(define_insn "*madd3<mode>"
@@ -2193,6 +2350,7 @@
"ISA_HAS_FP_MADD3_MSUB3 && TARGET_FUSED_MADD"
"madd.<fmt>\t%0,%1,%2"
[(set_attr "type" "fmadd")
+ (set_attr "accum_in" "3")
(set_attr "mode" "<UNITMODE>")])
(define_insn "*msub4<mode>"
@@ -2203,6 +2361,7 @@
"ISA_HAS_FP_MADD4_MSUB4 && TARGET_FUSED_MADD"
"msub.<fmt>\t%0,%3,%1,%2"
[(set_attr "type" "fmadd")
+ (set_attr "accum_in" "3")
(set_attr "mode" "<UNITMODE>")])
(define_insn "*msub3<mode>"
@@ -2213,6 +2372,7 @@
"ISA_HAS_FP_MADD3_MSUB3 && TARGET_FUSED_MADD"
"msub.<fmt>\t%0,%1,%2"
[(set_attr "type" "fmadd")
+ (set_attr "accum_in" "3")
(set_attr "mode" "<UNITMODE>")])
(define_insn "*nmadd4<mode>"
@@ -2221,12 +2381,13 @@
(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 (<MODE>mode)
+ "ISA_HAS_NMADD4_NMSUB4
&& TARGET_FUSED_MADD
&& HONOR_SIGNED_ZEROS (<MODE>mode)
&& !HONOR_NANS (<MODE>mode)"
"nmadd.<fmt>\t%0,%3,%1,%2"
[(set_attr "type" "fmadd")
+ (set_attr "accum_in" "3")
(set_attr "mode" "<UNITMODE>")])
(define_insn "*nmadd3<mode>"
@@ -2235,12 +2396,13 @@
(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 (<MODE>mode)
+ "ISA_HAS_NMADD3_NMSUB3
&& TARGET_FUSED_MADD
&& HONOR_SIGNED_ZEROS (<MODE>mode)
&& !HONOR_NANS (<MODE>mode)"
"nmadd.<fmt>\t%0,%1,%2"
[(set_attr "type" "fmadd")
+ (set_attr "accum_in" "3")
(set_attr "mode" "<UNITMODE>")])
(define_insn "*nmadd4<mode>_fastmath"
@@ -2249,12 +2411,13 @@
(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 (<MODE>mode)
+ "ISA_HAS_NMADD4_NMSUB4
&& TARGET_FUSED_MADD
&& !HONOR_SIGNED_ZEROS (<MODE>mode)
&& !HONOR_NANS (<MODE>mode)"
"nmadd.<fmt>\t%0,%3,%1,%2"
[(set_attr "type" "fmadd")
+ (set_attr "accum_in" "3")
(set_attr "mode" "<UNITMODE>")])
(define_insn "*nmadd3<mode>_fastmath"
@@ -2263,12 +2426,13 @@
(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 (<MODE>mode)
+ "ISA_HAS_NMADD3_NMSUB3
&& TARGET_FUSED_MADD
&& !HONOR_SIGNED_ZEROS (<MODE>mode)
&& !HONOR_NANS (<MODE>mode)"
"nmadd.<fmt>\t%0,%1,%2"
[(set_attr "type" "fmadd")
+ (set_attr "accum_in" "3")
(set_attr "mode" "<UNITMODE>")])
(define_insn "*nmsub4<mode>"
@@ -2277,12 +2441,13 @@
(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 (<MODE>mode)
+ "ISA_HAS_NMADD4_NMSUB4
&& TARGET_FUSED_MADD
&& HONOR_SIGNED_ZEROS (<MODE>mode)
&& !HONOR_NANS (<MODE>mode)"
"nmsub.<fmt>\t%0,%1,%2,%3"
[(set_attr "type" "fmadd")
+ (set_attr "accum_in" "1")
(set_attr "mode" "<UNITMODE>")])
(define_insn "*nmsub3<mode>"
@@ -2291,12 +2456,13 @@
(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 (<MODE>mode)
+ "ISA_HAS_NMADD3_NMSUB3
&& TARGET_FUSED_MADD
&& HONOR_SIGNED_ZEROS (<MODE>mode)
&& !HONOR_NANS (<MODE>mode)"
"nmsub.<fmt>\t%0,%1,%2"
[(set_attr "type" "fmadd")
+ (set_attr "accum_in" "1")
(set_attr "mode" "<UNITMODE>")])
(define_insn "*nmsub4<mode>_fastmath"
@@ -2305,12 +2471,13 @@
(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 (<MODE>mode)
+ "ISA_HAS_NMADD4_NMSUB4
&& TARGET_FUSED_MADD
&& !HONOR_SIGNED_ZEROS (<MODE>mode)
&& !HONOR_NANS (<MODE>mode)"
"nmsub.<fmt>\t%0,%1,%2,%3"
[(set_attr "type" "fmadd")
+ (set_attr "accum_in" "1")
(set_attr "mode" "<UNITMODE>")])
(define_insn "*nmsub3<mode>_fastmath"
@@ -2319,12 +2486,13 @@
(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 (<MODE>mode)
+ "ISA_HAS_NMADD3_NMSUB3
&& TARGET_FUSED_MADD
&& !HONOR_SIGNED_ZEROS (<MODE>mode)
&& !HONOR_NANS (<MODE>mode)"
"nmsub.<fmt>\t%0,%1,%2"
[(set_attr "type" "fmadd")
+ (set_attr "accum_in" "1")
(set_attr "mode" "<UNITMODE>")])
;;
@@ -2342,7 +2510,8 @@
"<divide_condition>"
{
if (const_1_operand (operands[1], <MODE>mode))
- if (!(<recip_condition> && flag_unsafe_math_optimizations))
+ if (!(ISA_HAS_FP_RECIP_RSQRT (<MODE>mode)
+ && flag_unsafe_math_optimizations))
operands[1] = force_reg (<MODE>mode, operands[1]);
})
@@ -2371,16 +2540,16 @@
}
[(set_attr "type" "fdiv")
(set_attr "mode" "<UNITMODE>")
- (set (attr "length")
+ (set (attr "insn_count")
(if_then_else (match_test "TARGET_FIX_SB1")
- (const_int 8)
- (const_int 4)))])
+ (const_int 2)
+ (const_int 1)))])
(define_insn "*recip<mode>3"
[(set (match_operand:ANYF 0 "register_operand" "=f")
(div:ANYF (match_operand:ANYF 1 "const_1_operand" "")
(match_operand:ANYF 2 "register_operand" "f")))]
- "<recip_condition> && flag_unsafe_math_optimizations"
+ "ISA_HAS_FP_RECIP_RSQRT (<MODE>mode) && flag_unsafe_math_optimizations"
{
if (TARGET_FIX_SB1)
return "recip.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0";
@@ -2389,42 +2558,40 @@
}
[(set_attr "type" "frdiv")
(set_attr "mode" "<UNITMODE>")
- (set (attr "length")
+ (set (attr "insn_count")
(if_then_else (match_test "TARGET_FIX_SB1")
- (const_int 8)
- (const_int 4)))])
+ (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 "divmod<mode>4"
- [(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)))]
- "!TARGET_FIX_VR4120"
+ [(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_<D>DIV && !TARGET_FIX_VR4120"
{
if (TARGET_MIPS16)
{
- emit_insn (gen_divmod<mode>4_split (operands[3], operands[1],
- operands[2]));
- emit_move_insn (operands[0], gen_rtx_REG (<MODE>mode, LO_REGNUM));
+ rtx lo = gen_rtx_REG (<MODE>mode, LO_REGNUM);
+ emit_insn (gen_divmod<mode>4_mips16 (operands[0], operands[1],
+ operands[2], operands[3], lo));
+ DONE;
}
- else
- emit_insn (gen_divmod<mode>4_internal (operands[0], operands[1],
- operands[2], operands[3]));
- DONE;
})
-(define_insn_and_split "divmod<mode>4_internal"
- [(set (match_operand:GPR 0 "muldiv_target_operand" "=l")
+(define_insn_and_split "*divmod<mode>4"
+ [(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)))]
- "!TARGET_FIX_VR4120 && !TARGET_MIPS16"
+ "ISA_HAS_<D>DIV && !TARGET_FIX_VR4120 && !TARGET_MIPS16"
"#"
"&& reload_completed"
[(const_int 0)]
@@ -2434,37 +2601,62 @@
}
[(set_attr "type" "idiv")
(set_attr "mode" "<MODE>")
- (set_attr "length" "8")])
+ (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 "divmod<mode>4_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_<D>DIV && !TARGET_FIX_VR4120 && TARGET_MIPS16"
+ "#"
+ "&& cse_not_expected"
+ [(const_int 0)]
+{
+ emit_insn (gen_divmod<mode>4_split (operands[3], operands[1], operands[2]));
+ emit_move_insn (operands[0], operands[4]);
+ DONE;
+}
+ [(set_attr "type" "idiv")
+ (set_attr "mode" "<MODE>")
+ (set_attr "insn_count" "3")])
(define_expand "udivmod<mode>4"
- [(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)))]
- ""
+ [(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_<D>DIV && !TARGET_FIX_VR4120"
{
if (TARGET_MIPS16)
{
- emit_insn (gen_udivmod<mode>4_split (operands[3], operands[1],
- operands[2]));
- emit_move_insn (operands[0], gen_rtx_REG (<MODE>mode, LO_REGNUM));
+ rtx lo = gen_rtx_REG (<MODE>mode, LO_REGNUM);
+ emit_insn (gen_udivmod<mode>4_mips16 (operands[0], operands[1],
+ operands[2], operands[3], lo));
+ DONE;
}
- else
- emit_insn (gen_udivmod<mode>4_internal (operands[0], operands[1],
- operands[2], operands[3]));
- DONE;
})
-(define_insn_and_split "udivmod<mode>4_internal"
- [(set (match_operand:GPR 0 "muldiv_target_operand" "=l")
+(define_insn_and_split "*udivmod<mode>4"
+ [(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)))]
- "!TARGET_MIPS16"
+ "ISA_HAS_<D>DIV && !TARGET_MIPS16"
"#"
"reload_completed"
[(const_int 0)]
@@ -2472,9 +2664,31 @@
emit_insn (gen_udivmod<mode>4_split (operands[3], operands[1], operands[2]));
DONE;
}
- [(set_attr "type" "idiv")
- (set_attr "mode" "<MODE>")
- (set_attr "length" "8")])
+ [(set_attr "type" "idiv")
+ (set_attr "mode" "<MODE>")
+ (set_attr "insn_count" "2")])
+
+;; See the comment above "divmod<mode>4_mips16" for the split timing.
+(define_insn_and_split "udivmod<mode>4_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_<D>DIV && TARGET_MIPS16"
+ "#"
+ "cse_not_expected"
+ [(const_int 0)]
+{
+ emit_insn (gen_udivmod<mode>4_split (operands[3], operands[1], operands[2]));
+ emit_move_insn (operands[0], operands[4]);
+ DONE;
+}
+ [(set_attr "type" "idiv")
+ (set_attr "mode" "<MODE>")
+ (set_attr "insn_count" "3")])
(define_expand "<u>divmod<mode>4_split"
[(set (match_operand:GPR 0 "register_operand")
@@ -2507,7 +2721,7 @@
[(any_div:GPR (match_operand:GPR 1 "register_operand" "d")
(match_operand:GPR 2 "register_operand" "d"))]
UNSPEC_SET_HILO))]
- ""
+ "ISA_HAS_<GPR:D>DIV"
{ return mips_output_division ("<GPR:d>div<u>\t%.,%1,%2", operands); }
[(set_attr "type" "idiv")
(set_attr "mode" "<GPR:MODE>")])
@@ -2534,16 +2748,16 @@
}
[(set_attr "type" "fsqrt")
(set_attr "mode" "<UNITMODE>")
- (set (attr "length")
+ (set (attr "insn_count")
(if_then_else (match_test "TARGET_FIX_SB1")
- (const_int 8)
- (const_int 4)))])
+ (const_int 2)
+ (const_int 1)))])
(define_insn "*rsqrt<mode>a"
[(set (match_operand:ANYF 0 "register_operand" "=f")
(div:ANYF (match_operand:ANYF 1 "const_1_operand" "")
(sqrt:ANYF (match_operand:ANYF 2 "register_operand" "f"))))]
- "<recip_condition> && flag_unsafe_math_optimizations"
+ "ISA_HAS_FP_RECIP_RSQRT (<MODE>mode) && flag_unsafe_math_optimizations"
{
if (TARGET_FIX_SB1)
return "rsqrt.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0";
@@ -2552,16 +2766,16 @@
}
[(set_attr "type" "frsqrt")
(set_attr "mode" "<UNITMODE>")
- (set (attr "length")
+ (set (attr "insn_count")
(if_then_else (match_test "TARGET_FIX_SB1")
- (const_int 8)
- (const_int 4)))])
+ (const_int 2)
+ (const_int 1)))])
(define_insn "*rsqrt<mode>b"
[(set (match_operand:ANYF 0 "register_operand" "=f")
(sqrt:ANYF (div:ANYF (match_operand:ANYF 1 "const_1_operand" "")
(match_operand:ANYF 2 "register_operand" "f"))))]
- "<recip_condition> && flag_unsafe_math_optimizations"
+ "ISA_HAS_FP_RECIP_RSQRT (<MODE>mode) && flag_unsafe_math_optimizations"
{
if (TARGET_FIX_SB1)
return "rsqrt.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0";
@@ -2570,10 +2784,10 @@
}
[(set_attr "type" "frsqrt")
(set_attr "mode" "<UNITMODE>")
- (set (attr "length")
+ (set (attr "insn_count")
(if_then_else (match_test "TARGET_FIX_SB1")
- (const_int 8)
- (const_int 4)))])
+ (const_int 2)
+ (const_int 1)))])
;;
;; ....................
@@ -2585,14 +2799,15 @@
;; Do not use the integer abs macro instruction, since that signals an
;; exception on -2147483648 (sigh).
-;; abs.fmt is an arithmetic instruction and treats all NaN inputs as
-;; invalid; it does not clear their sign bits. We therefore can't use
-;; abs.fmt if the signs of NaNs matter.
+;; The "legacy" (as opposed to "2008") form of ABS.fmt is an arithmetic
+;; instruction that treats all NaN inputs as invalid; it does not clear
+;; their sign bit. We therefore can't use that form if the signs of
+;; NaNs matter.
(define_insn "abs<mode>2"
[(set (match_operand:ANYF 0 "register_operand" "=f")
(abs:ANYF (match_operand:ANYF 1 "register_operand" "f")))]
- "!HONOR_NANS (<MODE>mode)"
+ "mips_abs == MIPS_IEEE_754_2008 || !HONOR_NANS (<MODE>mode)"
"abs.<fmt>\t%0,%1"
[(set_attr "type" "fabs")
(set_attr "mode" "<UNITMODE>")])
@@ -2628,6 +2843,16 @@
"<d>pop\t%0,%1"
[(set_attr "type" "pop")
(set_attr "mode" "<MODE>")])
+
+;; The POP instruction is special as it does not take into account the upper
+;; 32bits and is documented that way.
+(define_insn "*popcountdi2_trunc"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (popcount:SI (truncate:SI (match_operand:DI 1 "register_operand" "d"))))]
+ "ISA_HAS_POP && TARGET_64BIT"
+ "pop\t%0,%1"
+ [(set_attr "type" "pop")
+ (set_attr "mode" "SI")])
;;
;; ....................
@@ -2657,21 +2882,22 @@
[(set_attr "alu_type" "sub")
(set_attr "mode" "DI")])
-;; neg.fmt is an arithmetic instruction and treats all NaN inputs as
-;; invalid; it does not flip their sign bit. We therefore can't use
-;; neg.fmt if the signs of NaNs matter.
+;; The "legacy" (as opposed to "2008") form of NEG.fmt is an arithmetic
+;; instruction that treats all NaN inputs as invalid; it does not flip
+;; their sign bit. We therefore can't use that form if the signs of
+;; NaNs matter.
(define_insn "neg<mode>2"
[(set (match_operand:ANYF 0 "register_operand" "=f")
(neg:ANYF (match_operand:ANYF 1 "register_operand" "f")))]
- "!HONOR_NANS (<MODE>mode)"
+ "mips_abs == MIPS_IEEE_754_2008 || !HONOR_NANS (<MODE>mode)"
"neg.<fmt>\t%0,%1"
[(set_attr "type" "fneg")
(set_attr "mode" "<UNITMODE>")])
(define_insn "one_cmpl<mode>2"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (not:GPR (match_operand:GPR 1 "register_operand" "d")))]
+ [(set (match_operand:GPR 0 "register_operand" "=!u,d")
+ (not:GPR (match_operand:GPR 1 "register_operand" "!u,d")))]
""
{
if (TARGET_MIPS16)
@@ -2680,6 +2906,7 @@
return "nor\t%0,%.,%1";
}
[(set_attr "alu_type" "not")
+ (set_attr "compression" "micromips,*")
(set_attr "mode" "<MODE>")])
;;
@@ -2720,9 +2947,9 @@
;; register =op1 x
(define_insn "*and<mode>3"
- [(set (match_operand:GPR 0 "register_operand" "=d,d,d,d,d,d,d")
- (and:GPR (match_operand:GPR 1 "nonimmediate_operand" "o,o,W,d,d,d,d")
- (match_operand:GPR 2 "and_operand" "Yb,Yh,Yw,K,Yx,Yw,d")))]
+ [(set (match_operand:GPR 0 "register_operand" "=d,d,d,!u,d,d,d,!u,d")
+ (and:GPR (match_operand:GPR 1 "nonimmediate_operand" "o,o,W,!u,d,d,d,0,d")
+ (match_operand:GPR 2 "and_operand" "Yb,Yh,Yw,Uean,K,Yx,Yw,!u,d")))]
"!TARGET_MIPS16 && and_operands_ok (<MODE>mode, operands[1], operands[2])"
{
int len;
@@ -2739,25 +2966,28 @@
operands[1] = gen_lowpart (SImode, operands[1]);
return "lwu\t%0,%1";
case 3:
- return "andi\t%0,%1,%x2";
case 4:
+ return "andi\t%0,%1,%x2";
+ case 5:
len = low_bitmask_len (<MODE>mode, INTVAL (operands[2]));
operands[2] = GEN_INT (len);
return "<d>ext\t%0,%1,0,%2";
- case 5:
- return "#";
case 6:
+ return "#";
+ case 7:
+ case 8:
return "and\t%0,%1,%2";
default:
gcc_unreachable ();
}
}
- [(set_attr "move_type" "load,load,load,andi,ext_ins,shift_shift,logical")
+ [(set_attr "move_type" "load,load,load,andi,andi,ext_ins,shift_shift,logical,logical")
+ (set_attr "compression" "*,*,*,micromips,*,*,*,micromips,*")
(set_attr "mode" "<MODE>")])
(define_insn "*and<mode>3_mips16"
[(set (match_operand:GPR 0 "register_operand" "=d,d,d,d,d")
- (and:GPR (match_operand:GPR 1 "nonimmediate_operand" "%o,o,W,d,0")
+ (and:GPR (match_operand:GPR 1 "nonimmediate_operand" "%W,W,W,d,0")
(match_operand:GPR 2 "and_operand" "Yb,Yh,Yw,Yw,d")))]
"TARGET_MIPS16 && and_operands_ok (<MODE>mode, operands[1], operands[2])"
{
@@ -2794,14 +3024,16 @@
})
(define_insn "*ior<mode>3"
- [(set (match_operand:GPR 0 "register_operand" "=d,d")
- (ior:GPR (match_operand:GPR 1 "register_operand" "%d,d")
- (match_operand:GPR 2 "uns_arith_operand" "d,K")))]
+ [(set (match_operand:GPR 0 "register_operand" "=!u,d,d")
+ (ior:GPR (match_operand:GPR 1 "register_operand" "%0,d,d")
+ (match_operand:GPR 2 "uns_arith_operand" "!u,d,K")))]
"!TARGET_MIPS16"
"@
or\t%0,%1,%2
+ or\t%0,%1,%2
ori\t%0,%1,%x2"
[(set_attr "alu_type" "or")
+ (set_attr "compression" "micromips,*,*")
(set_attr "mode" "<MODE>")])
(define_insn "*ior<mode>3_mips16"
@@ -2820,34 +3052,32 @@
""
"")
-(define_insn ""
- [(set (match_operand:GPR 0 "register_operand" "=d,d")
- (xor:GPR (match_operand:GPR 1 "register_operand" "%d,d")
- (match_operand:GPR 2 "uns_arith_operand" "d,K")))]
+(define_insn "*xor<mode>3"
+ [(set (match_operand:GPR 0 "register_operand" "=!u,d,d")
+ (xor:GPR (match_operand:GPR 1 "register_operand" "%0,d,d")
+ (match_operand:GPR 2 "uns_arith_operand" "!u,d,K")))]
"!TARGET_MIPS16"
"@
xor\t%0,%1,%2
+ xor\t%0,%1,%2
xori\t%0,%1,%x2"
[(set_attr "alu_type" "xor")
+ (set_attr "compression" "micromips,*,*")
(set_attr "mode" "<MODE>")])
-(define_insn ""
- [(set (match_operand:GPR 0 "register_operand" "=d,t,t")
- (xor:GPR (match_operand:GPR 1 "register_operand" "%0,d,d")
- (match_operand:GPR 2 "uns_arith_operand" "d,K,d")))]
+(define_insn "*xor<mode>3_mips16"
+ [(set (match_operand:GPR 0 "register_operand" "=d,t,t,t")
+ (xor:GPR (match_operand:GPR 1 "register_operand" "%0,d,d,d")
+ (match_operand:GPR 2 "uns_arith_operand" "d,Uub8,K,d")))]
"TARGET_MIPS16"
"@
xor\t%0,%2
cmpi\t%1,%2
+ cmpi\t%1,%2
cmp\t%1,%2"
[(set_attr "alu_type" "xor")
(set_attr "mode" "<MODE>")
- (set_attr_alternative "length"
- [(const_int 4)
- (if_then_else (match_operand:VOID 2 "m16_uimm8_1")
- (const_int 4)
- (const_int 8))
- (const_int 4)])])
+ (set_attr "extended_mips16" "no,no,yes,no")])
(define_insn "*nor<mode>3"
[(set (match_operand:GPR 0 "register_operand" "=d")
@@ -3004,14 +3234,16 @@
})
(define_insn "*zero_extend<SHORT:mode><GPR:mode>2"
- [(set (match_operand:GPR 0 "register_operand" "=d,d")
+ [(set (match_operand:GPR 0 "register_operand" "=!u,d,d")
(zero_extend:GPR
- (match_operand:SHORT 1 "nonimmediate_operand" "d,m")))]
+ (match_operand:SHORT 1 "nonimmediate_operand" "!u,d,m")))]
"!TARGET_MIPS16"
"@
andi\t%0,%1,<SHORT:mask>
+ andi\t%0,%1,<SHORT:mask>
l<SHORT:size>u\t%0,%1"
- [(set_attr "move_type" "andi,load")
+ [(set_attr "move_type" "andi,andi,load")
+ (set_attr "compression" "micromips,*,*")
(set_attr "mode" "<GPR:MODE>")])
(define_insn "*zero_extend<SHORT:mode><GPR:mode>2_mips16e"
@@ -3350,7 +3582,7 @@
[(set_attr "type" "fcvt")
(set_attr "mode" "DF")
(set_attr "cnv_mode" "D2I")
- (set_attr "length" "36")])
+ (set_attr "insn_count" "9")])
(define_expand "fix_truncsfsi2"
[(set (match_operand:SI 0 "register_operand")
@@ -3387,7 +3619,7 @@
[(set_attr "type" "fcvt")
(set_attr "mode" "SF")
(set_attr "cnv_mode" "S2I")
- (set_attr "length" "36")])
+ (set_attr "insn_count" "9")])
(define_insn "fix_truncdfdi2"
@@ -3633,33 +3865,34 @@
;; Bit field extract patterns which use lwl/lwr or ldl/ldr.
-(define_expand "extv"
- [(set (match_operand 0 "register_operand")
- (sign_extract (match_operand 1 "nonimmediate_operand")
- (match_operand 2 "const_int_operand")
- (match_operand 3 "const_int_operand")))]
+(define_expand "extvmisalign<mode>"
+ [(set (match_operand:GPR 0 "register_operand")
+ (sign_extract:GPR (match_operand:BLK 1 "memory_operand")
+ (match_operand 2 "const_int_operand")
+ (match_operand 3 "const_int_operand")))]
"!TARGET_MIPS16"
{
if (mips_expand_ext_as_unaligned_load (operands[0], operands[1],
INTVAL (operands[2]),
- INTVAL (operands[3])))
+ INTVAL (operands[3]),
+ /*unsigned=*/ false))
DONE;
- else if (register_operand (operands[1], GET_MODE (operands[0]))
- && ISA_HAS_EXTS && UINTVAL (operands[2]) <= 32)
- {
- if (GET_MODE (operands[0]) == DImode)
- emit_insn (gen_extvdi (operands[0], operands[1], operands[2],
- operands[3]));
- else
- emit_insn (gen_extvsi (operands[0], operands[1], operands[2],
- operands[3]));
- DONE;
- }
else
FAIL;
})
-(define_insn "extv<mode>"
+(define_expand "extv<mode>"
+ [(set (match_operand:GPR 0 "register_operand")
+ (sign_extract:GPR (match_operand:GPR 1 "register_operand")
+ (match_operand 2 "const_int_operand")
+ (match_operand 3 "const_int_operand")))]
+ "ISA_HAS_EXTS"
+{
+ if (UINTVAL (operands[2]) > 32)
+ FAIL;
+})
+
+(define_insn "*extv<mode>"
[(set (match_operand:GPR 0 "register_operand" "=d")
(sign_extract:GPR (match_operand:GPR 1 "register_operand" "d")
(match_operand 2 "const_int_operand" "")
@@ -3669,34 +3902,35 @@
[(set_attr "type" "arith")
(set_attr "mode" "<MODE>")])
-
-(define_expand "extzv"
- [(set (match_operand 0 "register_operand")
- (zero_extract (match_operand 1 "nonimmediate_operand")
- (match_operand 2 "const_int_operand")
- (match_operand 3 "const_int_operand")))]
+(define_expand "extzvmisalign<mode>"
+ [(set (match_operand:GPR 0 "register_operand")
+ (zero_extract:GPR (match_operand:BLK 1 "memory_operand")
+ (match_operand 2 "const_int_operand")
+ (match_operand 3 "const_int_operand")))]
"!TARGET_MIPS16"
{
if (mips_expand_ext_as_unaligned_load (operands[0], operands[1],
INTVAL (operands[2]),
- INTVAL (operands[3])))
+ INTVAL (operands[3]),
+ /*unsigned=*/ true))
DONE;
- else if (mips_use_ins_ext_p (operands[1], INTVAL (operands[2]),
- INTVAL (operands[3])))
- {
- if (GET_MODE (operands[0]) == DImode)
- emit_insn (gen_extzvdi (operands[0], operands[1], operands[2],
- operands[3]));
- else
- emit_insn (gen_extzvsi (operands[0], operands[1], operands[2],
- operands[3]));
- DONE;
- }
else
FAIL;
})
-(define_insn "extzv<mode>"
+(define_expand "extzv<mode>"
+ [(set (match_operand:GPR 0 "register_operand")
+ (zero_extract:GPR (match_operand:GPR 1 "register_operand")
+ (match_operand 2 "const_int_operand")
+ (match_operand 3 "const_int_operand")))]
+ ""
+{
+ if (!mips_use_ins_ext_p (operands[1], INTVAL (operands[2]),
+ INTVAL (operands[3])))
+ FAIL;
+})
+
+(define_insn "*extzv<mode>"
[(set (match_operand:GPR 0 "register_operand" "=d")
(zero_extract:GPR (match_operand:GPR 1 "register_operand" "d")
(match_operand 2 "const_int_operand" "")
@@ -3719,36 +3953,37 @@
(set_attr "mode" "SI")])
-(define_expand "insv"
- [(set (zero_extract (match_operand 0 "nonimmediate_operand")
- (match_operand 1 "immediate_operand")
- (match_operand 2 "immediate_operand"))
- (match_operand 3 "reg_or_0_operand"))]
+(define_expand "insvmisalign<mode>"
+ [(set (zero_extract:GPR (match_operand:BLK 0 "memory_operand")
+ (match_operand 1 "const_int_operand")
+ (match_operand 2 "const_int_operand"))
+ (match_operand:GPR 3 "reg_or_0_operand"))]
"!TARGET_MIPS16"
{
if (mips_expand_ins_as_unaligned_store (operands[0], operands[3],
INTVAL (operands[1]),
INTVAL (operands[2])))
DONE;
- else if (mips_use_ins_ext_p (operands[0], INTVAL (operands[1]),
- INTVAL (operands[2])))
- {
- if (GET_MODE (operands[0]) == DImode)
- emit_insn (gen_insvdi (operands[0], operands[1], operands[2],
- operands[3]));
- else
- emit_insn (gen_insvsi (operands[0], operands[1], operands[2],
- operands[3]));
- DONE;
- }
- else
- FAIL;
+ else
+ FAIL;
+})
+
+(define_expand "insv<mode>"
+ [(set (zero_extract:GPR (match_operand:GPR 0 "register_operand")
+ (match_operand 1 "const_int_operand")
+ (match_operand 2 "const_int_operand"))
+ (match_operand:GPR 3 "reg_or_0_operand"))]
+ ""
+{
+ if (!mips_use_ins_ext_p (operands[0], INTVAL (operands[1]),
+ INTVAL (operands[2])))
+ FAIL;
})
-(define_insn "insv<mode>"
+(define_insn "*insv<mode>"
[(set (zero_extract:GPR (match_operand:GPR 0 "register_operand" "+d")
- (match_operand:SI 1 "immediate_operand" "I")
- (match_operand:SI 2 "immediate_operand" "I"))
+ (match_operand:SI 1 "const_int_operand" "")
+ (match_operand:SI 2 "const_int_operand" ""))
(match_operand:GPR 3 "reg_or_0_operand" "dJ"))]
"mips_use_ins_ext_p (operands[0], INTVAL (operands[1]),
INTVAL (operands[2]))"
@@ -3793,7 +4028,7 @@
(define_insn "mov_<load>l"
[(set (match_operand:GPR 0 "register_operand" "=d")
(unspec:GPR [(match_operand:BLK 1 "memory_operand" "m")
- (match_operand:QI 2 "memory_operand" "m")]
+ (match_operand:QI 2 "memory_operand" "ZC")]
UNSPEC_LOAD_LEFT))]
"!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[1])"
"<load>l\t%0,%2"
@@ -3803,7 +4038,7 @@
(define_insn "mov_<load>r"
[(set (match_operand:GPR 0 "register_operand" "=d")
(unspec:GPR [(match_operand:BLK 1 "memory_operand" "m")
- (match_operand:QI 2 "memory_operand" "m")
+ (match_operand:QI 2 "memory_operand" "ZC")
(match_operand:GPR 3 "register_operand" "0")]
UNSPEC_LOAD_RIGHT))]
"!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[1])"
@@ -3814,7 +4049,7 @@
(define_insn "mov_<store>l"
[(set (match_operand:BLK 0 "memory_operand" "=m")
(unspec:BLK [(match_operand:GPR 1 "reg_or_0_operand" "dJ")
- (match_operand:QI 2 "memory_operand" "m")]
+ (match_operand:QI 2 "memory_operand" "ZC")]
UNSPEC_STORE_LEFT))]
"!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[0])"
"<store>l\t%z1,%2"
@@ -3824,7 +4059,7 @@
(define_insn "mov_<store>r"
[(set (match_operand:BLK 0 "memory_operand" "+m")
(unspec:BLK [(match_operand:GPR 1 "reg_or_0_operand" "dJ")
- (match_operand:QI 2 "memory_operand" "m")
+ (match_operand:QI 2 "memory_operand" "ZC")
(match_dup 0)]
UNSPEC_STORE_RIGHT))]
"!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[0])"
@@ -3862,7 +4097,7 @@
operands[2] = mips_unspec_address (operands[1], SYMBOL_64_HIGH);
operands[3] = mips_unspec_address (operands[1], SYMBOL_64_MID);
}
- [(set_attr "length" "20")])
+ [(set_attr "insn_count" "5")])
;; Use a scratch register to reduce the latency of the above pattern
;; on superscalar machines. The optimized sequence is:
@@ -3917,7 +4152,7 @@
operands[3] = mips_unspec_address (operands[1], SYMBOL_64_HIGH);
operands[4] = mips_unspec_address (operands[1], SYMBOL_64_LOW);
}
- [(set_attr "length" "24")])
+ [(set_attr "insn_count" "6")])
;; Split HIGHs into:
;;
@@ -4100,14 +4335,17 @@
(set_attr "mode" "<MODE>")])
(define_insn "*movdi_32bit"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,m,*a,*d,*f,*f,*d,*m,*B*C*D,*B*C*D,*d,*m")
- (match_operand:DI 1 "move_operand" "d,i,m,d,*J*d,*a,*J*d,*m,*f,*f,*d,*m,*B*C*D,*B*C*D"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,m,*a,*a,*d,*f,*f,*d,*m,*B*C*D,*B*C*D,*d,*m")
+ (match_operand:DI 1 "move_operand" "d,i,m,d,*J,*d,*a,*J*d,*m,*f,*f,*d,*m,*B*C*D,*B*C*D"))]
"!TARGET_64BIT && !TARGET_MIPS16
&& (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
{ return mips_output_move (operands[0], operands[1]); }
- [(set_attr "move_type" "move,const,load,store,mthilo,mfhilo,mtc,fpload,mfc,fpstore,mtc,fpload,mfc,fpstore")
- (set_attr "mode" "DI")])
+ [(set_attr "move_type" "move,const,load,store,imul,mtlo,mflo,mtc,fpload,mfc,fpstore,mtc,fpload,mfc,fpstore")
+ (set (attr "mode")
+ (if_then_else (eq_attr "move_type" "imul")
+ (const_string "SI")
+ (const_string "DI")))])
(define_insn "*movdi_32bit_mips16"
[(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m,*d")
@@ -4116,27 +4354,27 @@
&& (register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode))"
{ return mips_output_move (operands[0], operands[1]); }
- [(set_attr "move_type" "move,move,move,const,constN,load,store,mfhilo")
+ [(set_attr "move_type" "move,move,move,const,constN,load,store,mflo")
(set_attr "mode" "DI")])
(define_insn "*movdi_64bit"
[(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*d,*m,*a,*d,*B*C*D,*B*C*D,*d,*m")
- (match_operand:DI 1 "move_operand" "d,U,T,m,dJ,*d*J,*m,*f,*f,*J*d,*a,*d,*m,*B*C*D,*B*C*D"))]
+ (match_operand:DI 1 "move_operand" "d,Yd,Yf,m,dJ,*d*J,*m,*f,*f,*J*d,*a,*d,*m,*B*C*D,*B*C*D"))]
"TARGET_64BIT && !TARGET_MIPS16
&& (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
{ return mips_output_move (operands[0], operands[1]); }
- [(set_attr "move_type" "move,const,const,load,store,mtc,fpload,mfc,fpstore,mthilo,mfhilo,mtc,fpload,mfc,fpstore")
+ [(set_attr "move_type" "move,const,const,load,store,mtc,fpload,mfc,fpstore,mtlo,mflo,mtc,fpload,mfc,fpstore")
(set_attr "mode" "DI")])
(define_insn "*movdi_64bit_mips16"
[(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,d,m,*d")
- (match_operand:DI 1 "move_operand" "d,d,y,K,N,U,kf,m,d,*a"))]
+ (match_operand:DI 1 "move_operand" "d,d,y,K,N,Yd,kf,m,d,*a"))]
"TARGET_64BIT && TARGET_MIPS16
&& (register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode))"
{ return mips_output_move (operands[0], operands[1]); }
- [(set_attr "move_type" "move,move,move,const,constN,const,loadpool,load,store,mfhilo")
+ [(set_attr "move_type" "move,move,move,const,constN,const,loadpool,load,store,mflo")
(set_attr "mode" "DI")])
;; On the mips16, we can split ld $r,N($r) into an add and a load,
@@ -4198,23 +4436,24 @@
;; in FP registers (off by default, use -mdebugh to enable).
(define_insn "*mov<mode>_internal"
- [(set (match_operand:IMOVE32 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*d,*m,*d,*z,*a,*d,*B*C*D,*B*C*D,*d,*m")
- (match_operand:IMOVE32 1 "move_operand" "d,U,T,m,dJ,*d*J,*m,*f,*f,*z,*d,*J*d,*a,*d,*m,*B*C*D,*B*C*D"))]
+ [(set (match_operand:IMOVE32 0 "nonimmediate_operand" "=d,!u,!u,d,e,!u,!ks,d,ZS,ZT,m,*f,*f,*d,*m,*d,*z,*a,*d,*B*C*D,*B*C*D,*d,*m")
+ (match_operand:IMOVE32 1 "move_operand" "d,J,Udb7,Yd,Yf,ZT,ZS,m,!ks,!u,dJ,*d*J,*m,*f,*f,*z,*d,*J*d,*a,*d,*m,*B*C*D,*B*C*D"))]
"!TARGET_MIPS16
&& (register_operand (operands[0], <MODE>mode)
|| reg_or_0_operand (operands[1], <MODE>mode))"
{ return mips_output_move (operands[0], operands[1]); }
- [(set_attr "move_type" "move,const,const,load,store,mtc,fpload,mfc,fpstore,mfc,mtc,mthilo,mfhilo,mtc,fpload,mfc,fpstore")
+ [(set_attr "move_type" "move,move,const,const,const,load,load,load,store,store,store,mtc,fpload,mfc,fpstore,mfc,mtc,mtlo,mflo,mtc,fpload,mfc,fpstore")
+ (set_attr "compression" "all,micromips,micromips,*,*,micromips,micromips,*,micromips,micromips,*,*,*,*,*,*,*,*,*,*,*,*,*")
(set_attr "mode" "SI")])
(define_insn "*mov<mode>_mips16"
[(set (match_operand:IMOVE32 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,d,m,*d")
- (match_operand:IMOVE32 1 "move_operand" "d,d,y,K,N,U,kf,m,d,*a"))]
+ (match_operand:IMOVE32 1 "move_operand" "d,d,y,K,N,Yd,kf,m,d,*a"))]
"TARGET_MIPS16
&& (register_operand (operands[0], <MODE>mode)
|| register_operand (operands[1], <MODE>mode))"
{ return mips_output_move (operands[0], operands[1]); }
- [(set_attr "move_type" "move,move,move,const,constN,const,loadpool,load,store,mfhilo")
+ [(set_attr "move_type" "move,move,move,const,constN,const,loadpool,load,store,mflo")
(set_attr "mode" "SI")])
;; On the mips16, we can split lw $r,N($r) into an add and a load,
@@ -4275,53 +4514,6 @@
operands[2] = GEN_INT (val - 0xff);
})
-;; This insn handles moving CCmode values. It's really just a
-;; slightly simplified copy of movsi_internal2, with additional cases
-;; to move a condition register to a general register and to move
-;; between the general registers and the floating point registers.
-
-(define_insn "movcc"
- [(set (match_operand:CC 0 "nonimmediate_operand" "=d,*d,*d,*m,*d,*f,*f,*f,*m")
- (match_operand:CC 1 "general_operand" "z,*d,*m,*d,*f,*d,*f,*m,*f"))]
- "ISA_HAS_8CC && TARGET_HARD_FLOAT"
- { return mips_output_move (operands[0], operands[1]); }
- [(set_attr "move_type" "lui_movf,move,load,store,mfc,mtc,fmove,fpload,fpstore")
- (set_attr "mode" "SI")])
-
-;; Reload condition code registers. reload_incc and reload_outcc
-;; both handle moves from arbitrary operands into condition code
-;; registers. reload_incc handles the more common case in which
-;; a source operand is constrained to be in a condition-code
-;; register, but has not been allocated to one.
-;;
-;; Sometimes, such as in movcc, we have a CCmode destination whose
-;; constraints do not include 'z'. reload_outcc handles the case
-;; when such an operand is allocated to a condition-code register.
-;;
-;; Note that reloads from a condition code register to some
-;; other location can be done using ordinary moves. Moving
-;; into a GPR takes a single movcc, moving elsewhere takes
-;; two. We can leave these cases to the generic reload code.
-(define_expand "reload_incc"
- [(set (match_operand:CC 0 "fcc_reload_operand" "=z")
- (match_operand:CC 1 "general_operand" ""))
- (clobber (match_operand:TF 2 "register_operand" "=&f"))]
- "ISA_HAS_8CC && TARGET_HARD_FLOAT"
-{
- mips_expand_fcc_reload (operands[0], operands[1], operands[2]);
- DONE;
-})
-
-(define_expand "reload_outcc"
- [(set (match_operand:CC 0 "fcc_reload_operand" "=z")
- (match_operand:CC 1 "register_operand" ""))
- (clobber (match_operand:TF 2 "register_operand" "=&f"))]
- "ISA_HAS_8CC && TARGET_HARD_FLOAT"
-{
- mips_expand_fcc_reload (operands[0], operands[1], operands[2]);
- DONE;
-})
-
;; MIPS4 supports loading and storing a floating point register from
;; the sum of two general registers. We use two versions for each of
;; these four instructions: one where the two general registers are
@@ -4339,7 +4531,7 @@
[(set (match_operand:ANYF 0 "register_operand" "=f")
(mem:ANYF (plus:P (match_operand:P 1 "register_operand" "d")
(match_operand:P 2 "register_operand" "d"))))]
- "ISA_HAS_FP4"
+ "ISA_HAS_LXC1_SXC1"
"<ANYF:loadx>\t%0,%1(%2)"
[(set_attr "type" "fpidxload")
(set_attr "mode" "<ANYF:UNITMODE>")])
@@ -4348,7 +4540,7 @@
[(set (mem:ANYF (plus:P (match_operand:P 1 "register_operand" "d")
(match_operand:P 2 "register_operand" "d")))
(match_operand:ANYF 0 "register_operand" "f"))]
- "ISA_HAS_FP4"
+ "ISA_HAS_LXC1_SXC1"
"<ANYF:storex>\t%0,%1(%2)"
[(set_attr "type" "fpidxstore")
(set_attr "mode" "<ANYF:UNITMODE>")])
@@ -4385,13 +4577,14 @@
})
(define_insn "*movhi_internal"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,m,*a,*d")
- (match_operand:HI 1 "move_operand" "d,I,m,dJ,*d*J,*a"))]
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=d,!u,d,!u,d,ZU,m,*a,*d")
+ (match_operand:HI 1 "move_operand" "d,J,I,ZU,m,!u,dJ,*d*J,*a"))]
"!TARGET_MIPS16
&& (register_operand (operands[0], HImode)
|| reg_or_0_operand (operands[1], HImode))"
{ return mips_output_move (operands[0], operands[1]); }
- [(set_attr "move_type" "move,const,load,store,mthilo,mfhilo")
+ [(set_attr "move_type" "move,const,const,load,load,store,store,mtlo,mflo")
+ (set_attr "compression" "all,micromips,*,micromips,*,micromips,*,*,*")
(set_attr "mode" "HI")])
(define_insn "*movhi_mips16"
@@ -4401,7 +4594,7 @@
&& (register_operand (operands[0], HImode)
|| register_operand (operands[1], HImode))"
{ return mips_output_move (operands[0], operands[1]); }
- [(set_attr "move_type" "move,move,move,const,constN,load,store,mfhilo")
+ [(set_attr "move_type" "move,move,move,const,constN,load,store,mflo")
(set_attr "mode" "HI")])
;; On the mips16, we can split lh $r,N($r) into an add and a load,
@@ -4460,13 +4653,14 @@
})
(define_insn "*movqi_internal"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,*a,*d")
- (match_operand:QI 1 "move_operand" "d,I,m,dJ,*d*J,*a"))]
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=d,!u,d,!u,d,ZV,m,*a,*d")
+ (match_operand:QI 1 "move_operand" "d,J,I,ZW,m,!u,dJ,*d*J,*a"))]
"!TARGET_MIPS16
&& (register_operand (operands[0], QImode)
|| reg_or_0_operand (operands[1], QImode))"
{ return mips_output_move (operands[0], operands[1]); }
- [(set_attr "move_type" "move,const,load,store,mthilo,mfhilo")
+ [(set_attr "move_type" "move,const,const,load,load,store,store,mtlo,mflo")
+ (set_attr "compression" "all,micromips,*,micromips,*,micromips,*,*,*")
(set_attr "mode" "QI")])
(define_insn "*movqi_mips16"
@@ -4476,7 +4670,7 @@
&& (register_operand (operands[0], QImode)
|| register_operand (operands[1], QImode))"
{ return mips_output_move (operands[0], operands[1]); }
- [(set_attr "move_type" "move,move,move,const,constN,load,store,mfhilo")
+ [(set_attr "move_type" "move,move,move,const,constN,load,store,mflo")
(set_attr "mode" "QI")])
;; On the mips16, we can split lb $r,N($r) into an add and a load,
@@ -4600,15 +4794,18 @@
})
(define_insn "*movti"
- [(set (match_operand:TI 0 "nonimmediate_operand" "=d,d,d,m,*a,*d")
- (match_operand:TI 1 "move_operand" "d,i,m,dJ,*d*J,*a"))]
+ [(set (match_operand:TI 0 "nonimmediate_operand" "=d,d,d,m,*a,*a,*d")
+ (match_operand:TI 1 "move_operand" "d,i,m,dJ,*J,*d,*a"))]
"TARGET_64BIT
&& !TARGET_MIPS16
&& (register_operand (operands[0], TImode)
|| reg_or_0_operand (operands[1], TImode))"
- "#"
- [(set_attr "move_type" "move,const,load,store,mthilo,mfhilo")
- (set_attr "mode" "TI")])
+ { return mips_output_move (operands[0], operands[1]); }
+ [(set_attr "move_type" "move,const,load,store,imul,mtlo,mflo")
+ (set (attr "mode")
+ (if_then_else (eq_attr "move_type" "imul")
+ (const_string "SI")
+ (const_string "TI")))])
(define_insn "*movti_mips16"
[(set (match_operand:TI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m,*d")
@@ -4618,7 +4815,7 @@
&& (register_operand (operands[0], TImode)
|| register_operand (operands[1], TImode))"
"#"
- [(set_attr "move_type" "move,move,move,const,constN,load,store,mfhilo")
+ [(set_attr "move_type" "move,move,move,const,constN,load,store,mflo")
(set_attr "mode" "TI")])
;; 128-bit floating point moves
@@ -4658,21 +4855,20 @@
(define_split
[(set (match_operand:MOVE64 0 "nonimmediate_operand")
(match_operand:MOVE64 1 "move_operand"))]
- "reload_completed && !TARGET_64BIT
- && mips_split_64bit_move_p (operands[0], operands[1])"
+ "reload_completed && mips_split_move_insn_p (operands[0], operands[1], insn)"
[(const_int 0)]
{
- mips_split_doubleword_move (operands[0], operands[1]);
+ mips_split_move_insn (operands[0], operands[1], curr_insn);
DONE;
})
(define_split
[(set (match_operand:MOVE128 0 "nonimmediate_operand")
(match_operand:MOVE128 1 "move_operand"))]
- "TARGET_64BIT && reload_completed"
+ "reload_completed && mips_split_move_insn_p (operands[0], operands[1], insn)"
[(const_int 0)]
{
- mips_split_doubleword_move (operands[0], operands[1]);
+ mips_split_move_insn (operands[0], operands[1], curr_insn);
DONE;
})
@@ -4725,7 +4921,7 @@
UNSPEC_MFHI))]
""
{ return ISA_HAS_MACCHI ? "<GPR:d>macchi\t%0,%.,%." : "mfhi\t%0"; }
- [(set_attr "move_type" "mfhilo")
+ [(set_attr "type" "mfhi")
(set_attr "mode" "<GPR:MODE>")])
;; Set the high part of a HI/LO value, given that the low part has
@@ -4738,7 +4934,7 @@
UNSPEC_MTHI))]
""
"mthi\t%z1"
- [(set_attr "move_type" "mthilo")
+ [(set_attr "type" "mthi")
(set_attr "mode" "SI")])
;; Emit a doubleword move in which exactly one of the operands is
@@ -4966,7 +5162,7 @@
return ".cprestore\t%1";
}
[(set_attr "type" "store")
- (set_attr "length" "4,12")])
+ (set_attr "insn_count" "1,3")])
(define_insn "use_cprestore_<mode>"
[(set (reg:P CPRESTORE_SLOT_REGNUM)
@@ -5027,7 +5223,7 @@
"\tjr.hb\t$31\n"
"\tnop%>%)";
}
- [(set_attr "length" "20")])
+ [(set_attr "insn_count" "5")])
;; Cache operations for R4000-style caches.
(define_insn "mips_cache"
@@ -5106,9 +5302,9 @@
})
(define_insn "*<optab><mode>3"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (any_shift:GPR (match_operand:GPR 1 "register_operand" "d")
- (match_operand:SI 2 "arith_operand" "dI")))]
+ [(set (match_operand:GPR 0 "register_operand" "=!u,d")
+ (any_shift:GPR (match_operand:GPR 1 "register_operand" "!u,d")
+ (match_operand:SI 2 "arith_operand" "Uib3,dI")))]
"!TARGET_MIPS16"
{
if (CONST_INT_P (operands[2]))
@@ -5118,6 +5314,7 @@
return "<d><insn>\t%0,%1,%2";
}
[(set_attr "type" "shift")
+ (set_attr "compression" "<shift_compression>,none")
(set_attr "mode" "<MODE>")])
(define_insn "*<optab>si3_extend"
@@ -5136,9 +5333,9 @@
(set_attr "mode" "SI")])
(define_insn "*<optab>si3_mips16"
- [(set (match_operand:SI 0 "register_operand" "=d,d")
- (any_shift:SI (match_operand:SI 1 "register_operand" "0,d")
- (match_operand:SI 2 "arith_operand" "d,I")))]
+ [(set (match_operand:SI 0 "register_operand" "=d,d,d")
+ (any_shift:SI (match_operand:SI 1 "register_operand" "0,d,d")
+ (match_operand:SI 2 "arith_operand" "d,Uib3,I")))]
"TARGET_MIPS16"
{
if (which_alternative == 0)
@@ -5149,18 +5346,14 @@
}
[(set_attr "type" "shift")
(set_attr "mode" "SI")
- (set_attr_alternative "length"
- [(const_int 4)
- (if_then_else (match_operand 2 "m16_uimm3_b")
- (const_int 4)
- (const_int 8))])])
+ (set_attr "extended_mips16" "no,no,yes")])
;; We need separate DImode MIPS16 patterns because of the irregularity
;; of right shifts.
(define_insn "*ashldi3_mips16"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (ashift:DI (match_operand:DI 1 "register_operand" "0,d")
- (match_operand:SI 2 "arith_operand" "d,I")))]
+ [(set (match_operand:DI 0 "register_operand" "=d,d,d")
+ (ashift:DI (match_operand:DI 1 "register_operand" "0,d,d")
+ (match_operand:SI 2 "arith_operand" "d,Uib3,I")))]
"TARGET_64BIT && TARGET_MIPS16"
{
if (which_alternative == 0)
@@ -5171,16 +5364,12 @@
}
[(set_attr "type" "shift")
(set_attr "mode" "DI")
- (set_attr_alternative "length"
- [(const_int 4)
- (if_then_else (match_operand 2 "m16_uimm3_b")
- (const_int 4)
- (const_int 8))])])
+ (set_attr "extended_mips16" "no,no,yes")])
(define_insn "*ashrdi3_mips16"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (ashiftrt:DI (match_operand:DI 1 "register_operand" "0,0")
- (match_operand:SI 2 "arith_operand" "d,I")))]
+ [(set (match_operand:DI 0 "register_operand" "=d,d,d")
+ (ashiftrt:DI (match_operand:DI 1 "register_operand" "0,0,0")
+ (match_operand:SI 2 "arith_operand" "d,Uib3,I")))]
"TARGET_64BIT && TARGET_MIPS16"
{
if (CONST_INT_P (operands[2]))
@@ -5190,16 +5379,12 @@
}
[(set_attr "type" "shift")
(set_attr "mode" "DI")
- (set_attr_alternative "length"
- [(const_int 4)
- (if_then_else (match_operand 2 "m16_uimm3_b")
- (const_int 4)
- (const_int 8))])])
+ (set_attr "extended_mips16" "no,no,yes")])
(define_insn "*lshrdi3_mips16"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (lshiftrt:DI (match_operand:DI 1 "register_operand" "0,0")
- (match_operand:SI 2 "arith_operand" "d,I")))]
+ [(set (match_operand:DI 0 "register_operand" "=d,d,d")
+ (lshiftrt:DI (match_operand:DI 1 "register_operand" "0,0,0")
+ (match_operand:SI 2 "arith_operand" "d,Uib3,I")))]
"TARGET_64BIT && TARGET_MIPS16"
{
if (CONST_INT_P (operands[2]))
@@ -5209,11 +5394,7 @@
}
[(set_attr "type" "shift")
(set_attr "mode" "DI")
- (set_attr_alternative "length"
- [(const_int 4)
- (if_then_else (match_operand 2 "m16_uimm3_b")
- (const_int 4)
- (const_int 8))])])
+ (set_attr "extended_mips16" "no,no,yes")])
;; On the mips16, we can split a 4 byte shift into 2 2 byte shifts.
@@ -5235,8 +5416,7 @@
;; not have and immediate). We recognize a shift of a load in order
;; to make it simple enough for combine to understand.
;;
-;; The length here is the worst case: the length of the split version
-;; will be more accurate.
+;; The instruction count here is the worst case.
(define_insn_and_split ""
[(set (match_operand:SI 0 "register_operand" "=d")
(lshiftrt:SI (match_operand:SI 1 "memory_operand" "m")
@@ -5249,7 +5429,8 @@
""
[(set_attr "type" "load")
(set_attr "mode" "SI")
- (set_attr "length" "16")])
+ (set (attr "insn_count")
+ (symbol_ref "mips_load_store_insns (operands[1], insn) + 2"))])
(define_insn "rotr<mode>3"
[(set (match_operand:GPR 0 "register_operand" "=d")
@@ -5265,6 +5446,56 @@
}
[(set_attr "type" "shift")
(set_attr "mode" "<MODE>")])
+
+(define_insn "bswaphi2"
+ [(set (match_operand:HI 0 "register_operand" "=d")
+ (bswap:HI (match_operand:HI 1 "register_operand" "d")))]
+ "ISA_HAS_WSBH"
+ "wsbh\t%0,%1"
+ [(set_attr "type" "shift")])
+
+(define_insn_and_split "bswapsi2"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (bswap:SI (match_operand:SI 1 "register_operand" "d")))]
+ "ISA_HAS_WSBH && ISA_HAS_ROR"
+ "#"
+ ""
+ [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_WSBH))
+ (set (match_dup 0) (rotatert:SI (match_dup 0) (const_int 16)))]
+ ""
+ [(set_attr "insn_count" "2")])
+
+(define_insn_and_split "bswapdi2"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (bswap:DI (match_operand:DI 1 "register_operand" "d")))]
+ "TARGET_64BIT && ISA_HAS_WSBH"
+ "#"
+ ""
+ [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_DSBH))
+ (set (match_dup 0) (unspec:DI [(match_dup 0)] UNSPEC_DSHD))]
+ ""
+ [(set_attr "insn_count" "2")])
+
+(define_insn "wsbh"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "d")] UNSPEC_WSBH))]
+ "ISA_HAS_WSBH"
+ "wsbh\t%0,%1"
+ [(set_attr "type" "shift")])
+
+(define_insn "dsbh"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "d")] UNSPEC_DSBH))]
+ "TARGET_64BIT && ISA_HAS_WSBH"
+ "dsbh\t%0,%1"
+ [(set_attr "type" "shift")])
+
+(define_insn "dshd"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "d")] UNSPEC_DSHD))]
+ "TARGET_64BIT && ISA_HAS_WSBH"
+ "dshd\t%0,%1"
+ [(set_attr "type" "shift")])
;;
;; ....................
@@ -5345,6 +5576,14 @@
(pc)))]
"!TARGET_MIPS16"
{
+ /* For a simple BNEZ or BEQZ microMIPS branch. */
+ if (TARGET_MICROMIPS
+ && operands[3] == const0_rtx
+ && get_attr_length (insn) <= 8)
+ return mips_output_conditional_branch (insn, operands,
+ "%*b%C1z%:\t%2,%0",
+ "%*b%N1z%:\t%2,%0");
+
return mips_output_conditional_branch (insn, operands,
MIPS_BRANCH ("b%C1", "%2,%z3,%0"),
MIPS_BRANCH ("b%N1", "%2,%z3,%0"));
@@ -5361,6 +5600,14 @@
(label_ref (match_operand 0 "" ""))))]
"!TARGET_MIPS16"
{
+ /* For a simple BNEZ or BEQZ microMIPS branch. */
+ if (TARGET_MICROMIPS
+ && operands[3] == const0_rtx
+ && get_attr_length (insn) <= 8)
+ return mips_output_conditional_branch (insn, operands,
+ "%*b%N0z%:\t%2,%1",
+ "%*b%C0z%:\t%2,%1");
+
return mips_output_conditional_branch (insn, operands,
MIPS_BRANCH ("b%N1", "%2,%z3,%0"),
MIPS_BRANCH ("b%C1", "%2,%z3,%0"));
@@ -5372,28 +5619,29 @@
(define_insn "*branch_equality<mode>_mips16"
[(set (pc)
(if_then_else
- (match_operator 0 "equality_operator"
- [(match_operand:GPR 1 "register_operand" "d,t")
+ (match_operator 1 "equality_operator"
+ [(match_operand:GPR 2 "register_operand" "d,t")
(const_int 0)])
- (match_operand 2 "pc_or_label_operand" "")
- (match_operand 3 "pc_or_label_operand" "")))]
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
"TARGET_MIPS16"
-{
- if (operands[2] != pc_rtx)
- {
- if (which_alternative == 0)
- return "b%C0z\t%1,%2";
- else
- return "bt%C0z\t%2";
- }
- else
- {
- if (which_alternative == 0)
- return "b%N0z\t%1,%3";
- else
- return "bt%N0z\t%3";
- }
-}
+ "@
+ b%C1z\t%2,%0
+ bt%C1z\t%0"
+ [(set_attr "type" "branch")])
+
+(define_insn "*branch_equality<mode>_mips16_inverted"
+ [(set (pc)
+ (if_then_else
+ (match_operator 1 "equality_operator"
+ [(match_operand:GPR 2 "register_operand" "d,t")
+ (const_int 0)])
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ "TARGET_MIPS16"
+ "@
+ b%N1z\t%2,%0
+ bt%N1z\t%0"
[(set_attr "type" "branch")])
(define_expand "cbranch<mode>4"
@@ -5581,18 +5829,14 @@
(set_attr "mode" "<GPR:MODE>")])
(define_insn "*slt<u>_<GPR:mode><GPR2:mode>_mips16"
- [(set (match_operand:GPR2 0 "register_operand" "=t,t")
- (any_lt:GPR2 (match_operand:GPR 1 "register_operand" "d,d")
- (match_operand:GPR 2 "arith_operand" "d,I")))]
+ [(set (match_operand:GPR2 0 "register_operand" "=t,t,t")
+ (any_lt:GPR2 (match_operand:GPR 1 "register_operand" "d,d,d")
+ (match_operand:GPR 2 "arith_operand" "d,Uub8,I")))]
"TARGET_MIPS16"
"slt<u>\t%1,%2"
[(set_attr "type" "slt")
(set_attr "mode" "<GPR:MODE>")
- (set_attr_alternative "length"
- [(const_int 4)
- (if_then_else (match_operand 2 "m16_uimm8_1")
- (const_int 4)
- (const_int 8))])])
+ (set_attr "extended_mips16" "no,no,yes")])
(define_insn "*sle<u>_<GPR:mode><GPR2:mode>"
[(set (match_operand:GPR2 0 "register_operand" "=d")
@@ -5607,9 +5851,9 @@
(set_attr "mode" "<GPR:MODE>")])
(define_insn "*sle<u>_<GPR:mode><GPR2:mode>_mips16"
- [(set (match_operand:GPR2 0 "register_operand" "=t")
- (any_le:GPR2 (match_operand:GPR 1 "register_operand" "d")
- (match_operand:GPR 2 "sle_operand" "")))]
+ [(set (match_operand:GPR2 0 "register_operand" "=t,t")
+ (any_le:GPR2 (match_operand:GPR 1 "register_operand" "d,d")
+ (match_operand:GPR 2 "sle_operand" "Udb8,i")))]
"TARGET_MIPS16"
{
operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
@@ -5617,9 +5861,7 @@
}
[(set_attr "type" "slt")
(set_attr "mode" "<GPR:MODE>")
- (set (attr "length") (if_then_else (match_operand 2 "m16_uimm8_m1_1")
- (const_int 4)
- (const_int 8)))])
+ (set_attr "extended_mips16" "no,yes")])
;;
;; ....................
@@ -5663,7 +5905,14 @@
[(set (pc)
(label_ref (match_operand 0)))]
"!TARGET_MIPS16 && TARGET_ABSOLUTE_JUMPS"
- { return MIPS_ABSOLUTE_JUMP ("%*j\t%l0%/"); }
+{
+ /* Use a branch for microMIPS. The assembler will choose
+ a 16-bit branch, a 32-bit branch, or a 32-bit jump. */
+ if (TARGET_MICROMIPS && !TARGET_ABICALLS_PIC2)
+ return "%*b\t%l0%/";
+ else
+ return MIPS_ABSOLUTE_JUMP ("%*j\t%l0%/");
+}
[(set_attr "type" "jump")])
(define_insn "*jump_pic"
@@ -5689,7 +5938,30 @@
(label_ref (match_operand 0 "" "")))]
"TARGET_MIPS16"
"b\t%l0"
- [(set_attr "type" "branch")])
+ [(set_attr "type" "branch")
+ (set (attr "length")
+ ;; This calculation is like the normal branch one, but the
+ ;; range of the unextended instruction is [-0x800, 0x7fe] rather
+ ;; than [-0x100, 0xfe]. This translates to a range of:
+ ;;
+ ;; [-(0x800 - sizeof (branch)), 0x7fe]
+ ;; == [-0x7fe, 0x7fe]
+ ;;
+ ;; from the shorten_branches reference address. Long-branch
+ ;; sequences will replace this one, so the minimum length
+ ;; is one instruction shorter than for conditional branches.
+ (cond [(and (le (minus (match_dup 0) (pc)) (const_int 2046))
+ (le (minus (pc) (match_dup 0)) (const_int 2046)))
+ (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 18)
+ (match_test "Pmode == SImode")
+ (const_int 14)
+ ] (const_int 22)))])
(define_expand "indirect_jump"
[(set (pc) (match_operand 0 "register_operand"))]
@@ -5703,22 +5975,34 @@
(define_insn "indirect_jump_<mode>"
[(set (pc) (match_operand:P 0 "register_operand" "d"))]
""
- "%*j\t%0%/"
+{
+ if (TARGET_MICROMIPS)
+ return "%*jr%:\t%0";
+ else
+ return "%*j\t%0%/";
+}
[(set_attr "type" "jump")
(set_attr "mode" "none")])
+;; A combined jump-and-move instruction, used for MIPS16 long-branch
+;; sequences. Having a dedicated pattern is more convenient than
+;; creating a SEQUENCE for this special case.
+(define_insn "indirect_jump_and_restore_<mode>"
+ [(set (pc) (match_operand:P 1 "register_operand" "d"))
+ (set (match_operand:P 0 "register_operand" "=d")
+ (match_operand:P 2 "register_operand" "y"))]
+ ""
+ "%(%<jr\t%1\;move\t%0,%2%>%)"
+ [(set_attr "type" "multi")
+ (set_attr "extended_mips16" "yes")])
+
(define_expand "tablejump"
[(set (pc)
(match_operand 0 "register_operand"))
(use (label_ref (match_operand 1 "")))]
- ""
+ "!TARGET_MIPS16_SHORT_JUMP_TABLES"
{
- if (TARGET_MIPS16_SHORT_JUMP_TABLES)
- operands[0] = expand_binop (Pmode, add_optab,
- convert_to_mode (Pmode, operands[0], false),
- gen_rtx_LABEL_REF (Pmode, operands[1]),
- 0, 0, OPTAB_WIDEN);
- else if (TARGET_GPWORD)
+ if (TARGET_GPWORD)
operands[0] = expand_binop (Pmode, add_optab, operands[0],
pic_offset_table_rtx, 0, 0, OPTAB_WIDEN);
else if (TARGET_RTP_PIC)
@@ -5740,10 +6024,103 @@
(match_operand:P 0 "register_operand" "d"))
(use (label_ref (match_operand 1 "" "")))]
""
- "%*j\t%0%/"
+{
+ if (TARGET_MICROMIPS)
+ return "%*jr%:\t%0";
+ else
+ return "%*j\t%0%/";
+}
[(set_attr "type" "jump")
(set_attr "mode" "none")])
+;; For MIPS16, we don't know whether a given jump table will use short or
+;; word-sized offsets until late in compilation, when we are able to determine
+;; the sizes of the insns which comprise the containing function. This
+;; necessitates the use of the casesi rather than the tablejump pattern, since
+;; the latter tries to calculate the index of the offset to jump through early
+;; in compilation, i.e. at expand time, when nothing is known about the
+;; eventual function layout.
+
+(define_expand "casesi"
+ [(match_operand:SI 0 "register_operand" "") ; index to jump on
+ (match_operand:SI 1 "const_int_operand" "") ; lower bound
+ (match_operand:SI 2 "const_int_operand" "") ; total range
+ (match_operand 3 "" "") ; table label
+ (match_operand 4 "" "")] ; out of range label
+ "TARGET_MIPS16_SHORT_JUMP_TABLES"
+{
+ if (operands[1] != const0_rtx)
+ {
+ rtx reg = gen_reg_rtx (SImode);
+ rtx offset = gen_int_mode (-INTVAL (operands[1]), SImode);
+
+ if (!arith_operand (offset, SImode))
+ offset = force_reg (SImode, offset);
+
+ emit_insn (gen_addsi3 (reg, operands[0], offset));
+ operands[0] = reg;
+ }
+
+ if (!arith_operand (operands[0], SImode))
+ operands[0] = force_reg (SImode, operands[0]);
+
+ operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
+
+ emit_jump_insn (PMODE_INSN (gen_casesi_internal_mips16,
+ (operands[0], operands[2],
+ operands[3], operands[4])));
+
+ DONE;
+})
+
+(define_insn "casesi_internal_mips16_<mode>"
+ [(set (pc)
+ (if_then_else
+ (leu (match_operand:SI 0 "register_operand" "d")
+ (match_operand:SI 1 "arith_operand" "dI"))
+ (unspec:P
+ [(match_dup 0)
+ (label_ref (match_operand 2 "" ""))]
+ UNSPEC_CASESI_DISPATCH)
+ (label_ref (match_operand 3 "" ""))))
+ (clobber (match_scratch:P 4 "=d"))
+ (clobber (match_scratch:P 5 "=d"))
+ (clobber (reg:SI MIPS16_T_REGNUM))]
+ "TARGET_MIPS16_SHORT_JUMP_TABLES"
+{
+ rtx diff_vec = PATTERN (NEXT_INSN (operands[2]));
+
+ gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
+
+ output_asm_insn ("sltu\t%0, %1", operands);
+ output_asm_insn ("bteqz\t%3", operands);
+
+ switch (GET_MODE (diff_vec))
+ {
+ case HImode:
+ output_asm_insn ("sll\t%5, %0, 1", operands);
+ output_asm_insn ("la\t%4, %2", operands);
+ output_asm_insn ("<d>addu\t%5, %4, %5", operands);
+ output_asm_insn ("lh\t%5, 0(%5)", operands);
+ break;
+
+ case SImode:
+ output_asm_insn ("sll\t%5, %0, 2", operands);
+ output_asm_insn ("la\t%4, %2", operands);
+ output_asm_insn ("<d>addu\t%5, %4, %5", operands);
+ output_asm_insn ("lw\t%5, 0(%5)", operands);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ output_asm_insn ("addu\t%4, %4, %5", operands);
+
+ return "j\t%4";
+}
+ [(set_attr "insn_count" "16")])
+
;; For TARGET_USE_GOT, we save the gp in the jmp_buf as well.
;; While it is possible to either pull it off the stack (in the
;; o32 case) or recalculate it given t9 and our target label,
@@ -5755,7 +6132,7 @@
{
rtx addr;
- addr = plus_constant (operands[0], GET_MODE_SIZE (Pmode) * 3);
+ addr = plus_constant (Pmode, operands[0], GET_MODE_SIZE (Pmode) * 3);
mips_emit_move (gen_rtx_MEM (Pmode, addr), pic_offset_table_rtx);
DONE;
})
@@ -5771,9 +6148,9 @@
/* The elements of the buffer are, in order: */
int W = GET_MODE_SIZE (Pmode);
rtx fp = gen_rtx_MEM (Pmode, operands[0]);
- rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], 1*W));
- rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 2*W));
- rtx gpv = gen_rtx_MEM (Pmode, plus_constant (operands[0], 3*W));
+ rtx lab = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0], 1*W));
+ rtx stack = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0], 2*W));
+ rtx gpv = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0], 3*W));
rtx pv = gen_rtx_REG (Pmode, PIC_FUNCTION_ADDR_REGNUM);
/* Use gen_raw_REG to avoid being given pic_offset_table_rtx.
The target is bound to be using $28 as the global pointer
@@ -5820,6 +6197,17 @@
[(set_attr "type" "ghost")
(set_attr "mode" "none")])
+(define_insn "probe_stack_range_<P:mode>"
+ [(set (match_operand:P 0 "register_operand" "=d")
+ (unspec_volatile:P [(match_operand:P 1 "register_operand" "0")
+ (match_operand:P 2 "register_operand" "d")]
+ UNSPEC_PROBE_STACK_RANGE))]
+ ""
+ { return mips_output_probe_stack_range (operands[0], operands[2]); }
+ [(set_attr "type" "unknown")
+ (set_attr "can_delay" "no")
+ (set_attr "mode" "<MODE>")])
+
(define_expand "epilogue"
[(const_int 2)]
""
@@ -5852,7 +6240,12 @@
(define_insn "*<optab>"
[(any_return)]
""
- "%*j\t$31%/"
+ {
+ if (TARGET_MICROMIPS)
+ return "%*jr%:\t$31";
+ else
+ return "%*j\t$31%/";
+ }
[(set_attr "type" "jump")
(set_attr "mode" "none")])
@@ -5862,7 +6255,12 @@
[(any_return)
(use (match_operand 0 "pmode_register_operand" ""))]
""
- "%*j\t%0%/"
+{
+ if (TARGET_MICROMIPS)
+ return "%*jr%:\t%0";
+ else
+ return "%*j\t%0%/";
+}
[(set_attr "type" "jump")
(set_attr "mode" "none")])
@@ -6118,7 +6516,12 @@
[(call (mem:SI (match_operand 0 "call_insn_operand" "j,S"))
(match_operand 1 "" ""))]
"TARGET_SIBCALLS && SIBLING_CALL_P (insn)"
- { return MIPS_CALL ("j", operands, 0, 1); }
+{
+ if (TARGET_MICROMIPS)
+ return MICROMIPS_J ("j", operands, 0);
+ else
+ return MIPS_CALL ("j", operands, 0, 1);
+}
[(set_attr "jal" "indirect,direct")
(set_attr "jal_macro" "no")])
@@ -6139,7 +6542,12 @@
(call (mem:SI (match_operand 1 "call_insn_operand" "j,S"))
(match_operand 2 "" "")))]
"TARGET_SIBCALLS && SIBLING_CALL_P (insn)"
- { return MIPS_CALL ("j", operands, 1, 2); }
+{
+ if (TARGET_MICROMIPS)
+ return MICROMIPS_J ("j", operands, 1);
+ else
+ return MIPS_CALL ("j", operands, 1, 2);
+}
[(set_attr "jal" "indirect,direct")
(set_attr "jal_macro" "no")])
@@ -6151,7 +6559,12 @@
(call (mem:SI (match_dup 1))
(match_dup 2)))]
"TARGET_SIBCALLS && SIBLING_CALL_P (insn)"
- { return MIPS_CALL ("j", operands, 1, 2); }
+{
+ if (TARGET_MICROMIPS)
+ return MICROMIPS_J ("j", operands, 1);
+ else
+ return MIPS_CALL ("j", operands, 1, 2);
+}
[(set_attr "jal" "indirect,direct")
(set_attr "jal_macro" "no")])
@@ -6397,14 +6810,19 @@
(define_insn "prefetch"
- [(prefetch (match_operand:QI 0 "address_operand" "p")
+ [(prefetch (match_operand:QI 0 "address_operand" "ZD")
(match_operand 1 "const_int_operand" "n")
(match_operand 2 "const_int_operand" "n"))]
"ISA_HAS_PREFETCH && TARGET_EXPLICIT_RELOCS"
{
if (TARGET_LOONGSON_2EF || TARGET_LOONGSON_3A)
- /* Loongson 2[ef] and Loongson 3a use load to $0 to perform prefetching. */
- return "ld\t$0,%a0";
+ {
+ /* Loongson 2[ef] and Loongson 3a use load to $0 for prefetching. */
+ if (TARGET_64BIT)
+ return "ld\t$0,%a0";
+ else
+ return "lw\t$0,%a0";
+ }
operands[1] = mips_prefetch_cookie (operands[1], operands[2]);
return "pref\t%1,%a0";
}
@@ -6446,7 +6864,7 @@
(define_insn "*mov<GPR:mode>_on_<MOVECC:mode>"
[(set (match_operand:GPR 0 "register_operand" "=d,d")
(if_then_else:GPR
- (match_operator:MOVECC 4 "equality_operator"
+ (match_operator 4 "equality_operator"
[(match_operand:MOVECC 1 "register_operand" "<MOVECC:reg>,<MOVECC:reg>")
(const_int 0)])
(match_operand:GPR 2 "reg_or_0_operand" "dJ,0")
@@ -6458,10 +6876,23 @@
[(set_attr "type" "condmove")
(set_attr "mode" "<GPR:MODE>")])
+(define_insn "*mov<GPR:mode>_on_<GPR2:mode>_ne"
+ [(set (match_operand:GPR 0 "register_operand" "=d,d")
+ (if_then_else:GPR
+ (match_operand:GPR2 1 "register_operand" "<GPR2:reg>,<GPR2:reg>")
+ (match_operand:GPR 2 "reg_or_0_operand" "dJ,0")
+ (match_operand:GPR 3 "reg_or_0_operand" "0,dJ")))]
+ "ISA_HAS_CONDMOVE"
+ "@
+ movn\t%0,%z2,%1
+ movz\t%0,%z3,%1"
+ [(set_attr "type" "condmove")
+ (set_attr "mode" "<GPR:MODE>")])
+
(define_insn "*mov<SCALARF:mode>_on_<MOVECC:mode>"
[(set (match_operand:SCALARF 0 "register_operand" "=f,f")
(if_then_else:SCALARF
- (match_operator:MOVECC 4 "equality_operator"
+ (match_operator 4 "equality_operator"
[(match_operand:MOVECC 1 "register_operand" "<MOVECC:reg>,<MOVECC:reg>")
(const_int 0)])
(match_operand:SCALARF 2 "register_operand" "f,0")
@@ -6521,7 +6952,8 @@
UNSPEC_CONSTTABLE_INT)]
"TARGET_MIPS16"
{
- assemble_integer (operands[0], INTVAL (operands[1]),
+ assemble_integer (mips_strip_unspec_address (operands[0]),
+ INTVAL (operands[1]),
BITS_PER_UNIT * INTVAL (operands[1]), 1);
return "";
}
@@ -6601,11 +7033,8 @@
(set (match_dup 0) (reg:P TLS_GET_TP_REGNUM))]
""
[(set_attr "type" "unknown")
- ; Since rdhwr always generates a trap for now, putting it in a delay
- ; slot would make the kernel's emulation of it much slower.
- (set_attr "can_delay" "no")
(set_attr "mode" "<MODE>")
- (set_attr "length" "8")])
+ (set_attr "insn_count" "2")])
(define_insn "*tls_get_tp_<mode>_split"
[(set (reg:P TLS_GET_TP_REGNUM)
@@ -6613,7 +7042,8 @@
"HAVE_AS_TLS && !TARGET_MIPS16"
".set\tpush\;.set\tmips32r2\t\;rdhwr\t$3,$29\;.set\tpop"
[(set_attr "type" "unknown")
- ; See tls_get_tp_<mode>
+ ; Since rdhwr always generates a trap for now, putting it in a delay
+ ; slot would make the kernel's emulation of it much slower.
(set_attr "can_delay" "no")
(set_attr "mode" "<MODE>")])
@@ -6645,7 +7075,7 @@
(set (match_dup 0) (reg:P TLS_GET_TP_REGNUM))]
""
[(set_attr "type" "multi")
- (set_attr "length" "16")
+ (set_attr "insn_count" "4")
(set_attr "mode" "<MODE>")])
(define_insn "*tls_get_tp_mips16_call_<mode>"
@@ -6657,8 +7087,78 @@
"HAVE_AS_TLS && TARGET_MIPS16"
{ return MIPS_CALL ("jal", operands, 0, -1); }
[(set_attr "type" "call")
- (set_attr "length" "12")
+ (set_attr "insn_count" "3")
(set_attr "mode" "<MODE>")])
+
+;; Named pattern for expanding thread pointer reference.
+(define_expand "get_thread_pointer<mode>"
+ [(match_operand:P 0 "register_operand" "=d")]
+ "HAVE_AS_TLS"
+{
+ mips_expand_thread_pointer (operands[0]);
+ DONE;
+})
+
+;; __builtin_mips_get_fcsr: move the FCSR into operand 0.
+(define_expand "mips_get_fcsr"
+ [(set (match_operand:SI 0 "register_operand")
+ (unspec_volatile [(const_int 0)] UNSPEC_GET_FCSR))]
+ "TARGET_HARD_FLOAT_ABI"
+{
+ if (TARGET_MIPS16)
+ {
+ mips16_expand_get_fcsr (operands[0]);
+ DONE;
+ }
+})
+
+(define_insn "*mips_get_fcsr"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec_volatile [(const_int 0)] UNSPEC_GET_FCSR))]
+ "TARGET_HARD_FLOAT"
+ "cfc1\t%0,$31")
+
+;; See tls_get_tp_mips16_<mode> for why this form is used.
+(define_insn "mips_get_fcsr_mips16_<mode>"
+ [(set (reg:SI GET_FCSR_REGNUM)
+ (unspec:SI [(match_operand:P 0 "call_insn_operand" "dS")]
+ UNSPEC_GET_FCSR))
+ (clobber (reg:P PIC_FUNCTION_ADDR_REGNUM))
+ (clobber (reg:P RETURN_ADDR_REGNUM))]
+ "TARGET_HARD_FLOAT_ABI && TARGET_MIPS16"
+ { return MIPS_CALL ("jal", operands, 0, -1); }
+ [(set_attr "type" "call")
+ (set_attr "insn_count" "3")])
+
+;; __builtin_mips_set_fcsr: move operand 0 into the FCSR.
+(define_expand "mips_set_fcsr"
+ [(unspec_volatile [(match_operand:SI 0 "register_operand")]
+ UNSPEC_SET_FCSR)]
+ "TARGET_HARD_FLOAT_ABI"
+{
+ if (TARGET_MIPS16)
+ {
+ mips16_expand_set_fcsr (operands[0]);
+ DONE;
+ }
+})
+
+(define_insn "*mips_set_fcsr"
+ [(unspec_volatile [(match_operand:SI 0 "register_operand" "d")]
+ UNSPEC_SET_FCSR)]
+ "TARGET_HARD_FLOAT"
+ "ctc1\t%0,$31")
+
+;; See tls_get_tp_mips16_<mode> for why this form is used.
+(define_insn "mips_set_fcsr_mips16_<mode>"
+ [(unspec_volatile:SI [(match_operand:P 0 "call_insn_operand" "dS")
+ (reg:SI SET_FCSR_REGNUM)] UNSPEC_SET_FCSR)
+ (clobber (reg:P PIC_FUNCTION_ADDR_REGNUM))
+ (clobber (reg:P RETURN_ADDR_REGNUM))]
+ "TARGET_HARD_FLOAT_ABI && TARGET_MIPS16"
+ { return MIPS_CALL ("jal", operands, 0, -1); }
+ [(set_attr "type" "call")
+ (set_attr "insn_count" "3")])
;; Synchronization instructions.
@@ -6679,6 +7179,9 @@
; MIPS fixed-point instructions.
(include "mips-fixed.md")
+; microMIPS patterns.
+(include "micromips.md")
+
; ST-Microelectronics Loongson-2E/2F-specific patterns.
(include "loongson.md")
diff --git a/gcc/config/mips/mips.opt b/gcc/config/mips/mips.opt
index e3294a7f7f..6ee539837b 100644
--- a/gcc/config/mips/mips.opt
+++ b/gcc/config/mips/mips.opt
@@ -1,6 +1,6 @@
; Options for the MIPS port of the compiler
;
-; Copyright (C) 2005, 2007, 2008, 2010, 2011 Free Software Foundation, Inc.
+; Copyright (C) 2005-2014 Free Software Foundation, Inc.
;
; This file is part of GCC.
;
@@ -54,10 +54,14 @@ mabicalls
Target Report Mask(ABICALLS)
Generate code that can be used in SVR4-style dynamic objects
-mad
+mmad
Target Report Var(TARGET_MAD)
Use PMC-style 'mad' instructions
+mimadd
+Target Report Mask(IMADD)
+Use integer madd/msub instructions
+
march=
Target RejectNegative Joined Var(mips_arch_option) ToLower Enum(mips_arch_opt_value)
-march=ISA Generate code for the given ISA
@@ -112,11 +116,11 @@ Target Report RejectNegative InverseMask(SINGLE_FLOAT, DOUBLE_FLOAT)
Allow hardware floating-point instructions to cover both 32-bit and 64-bit operations
mdsp
-Target Report Mask(DSP)
+Target Report Var(TARGET_DSP)
Use MIPS-DSP instructions
mdspr2
-Target Report Mask(DSPR2)
+Target Report Var(TARGET_DSPR2)
Use MIPS-DSP REV 2 instructions
mdebug
@@ -137,6 +141,10 @@ membedded-data
Target Report Var(TARGET_EMBEDDED_DATA)
Use ROM instead of RAM
+meva
+Target Report Var(TARGET_EVA)
+Use Enhanced Virtual Addressing instructions
+
mexplicit-relocs
Target Report Mask(EXPLICIT_RELOCS)
Use NewABI-style %reloc() assembly operators
@@ -157,6 +165,10 @@ mfix-r4400
Target Report Mask(FIX_R4400)
Work around certain R4400 errata
+mfix-rm7000
+Target Report Var(TARGET_FIX_RM7000)
+Work around certain RM7000 errata
+
mfix-r10000
Target Report Mask(FIX_R10000)
Work around certain R10000 errata
@@ -178,7 +190,7 @@ Target Report Var(TARGET_4300_MUL_FIX)
Work around an early 4300 hardware bug
mfp-exceptions
-Target Report Mask(FP_EXCEPTIONS)
+Target Report Var(TARGET_FP_EXCEPTIONS) Init(1)
FP exceptions are enabled
mfp32
@@ -194,9 +206,27 @@ Target RejectNegative Joined Var(mips_cache_flush_func) Init(CACHE_FLUSH_FUNC)
-mflush-func=FUNC Use FUNC to flush the cache before calling stack trampolines
mfused-madd
-Target Report Mask(FUSED_MADD)
+Target Report Var(TARGET_FUSED_MADD) Init(1)
Generate floating-point multiply-add instructions
+mabs=
+Target RejectNegative Joined Enum(mips_ieee_754_value) Var(mips_abs) Init(MIPS_IEEE_754_DEFAULT)
+-mabs=MODE Select the IEEE 754 ABS/NEG instruction execution mode
+
+mnan=
+Target RejectNegative Joined Enum(mips_ieee_754_value) Var(mips_nan) Init(MIPS_IEEE_754_DEFAULT)
+-mnan=ENCODING Select the IEEE 754 NaN data encoding
+
+Enum
+Name(mips_ieee_754_value) Type(int)
+Known MIPS IEEE 754 settings (for use with the -mabs= and -mnan= options):
+
+EnumValue
+Enum(mips_ieee_754_value) String(2008) Value(MIPS_IEEE_754_2008)
+
+EnumValue
+Enum(mips_ieee_754_value) String(legacy) Value(MIPS_IEEE_754_LEGACY)
+
mgp32
Target Report RejectNegative InverseMask(64BIT)
Use 32-bit general registers
@@ -217,9 +247,13 @@ mhard-float
Target Report RejectNegative InverseMask(SOFT_FLOAT_ABI, HARD_FLOAT_ABI)
Allow the use of hardware floating-point ABI and instructions
+minterlink-compressed
+Target Report Var(TARGET_INTERLINK_COMPRESSED) Init(0)
+Generate code that is link-compatible with MIPS16 and microMIPS code.
+
minterlink-mips16
-Target Report Var(TARGET_INTERLINK_MIPS16) Init(0)
-Generate code that can be safely linked with MIPS16 code.
+Target Report Var(TARGET_INTERLINK_COMPRESSED) Init(0)
+An alias for minterlink-compressed provided for backward-compatibility.
mips
Target RejectNegative Joined ToLower Enum(mips_mips_opt_value) Var(mips_isa_option)
@@ -230,7 +264,7 @@ Target Report RejectNegative Mask(MIPS16)
Generate MIPS16 code
mips3d
-Target Report RejectNegative Mask(MIPS3D)
+Target Report RejectNegative Var(TARGET_MIPS3D)
Use MIPS-3D instructions
mllsc
@@ -261,6 +295,10 @@ mmemcpy
Target Report Mask(MEMCPY)
Don't optimize block moves
+mmicromips
+Target Report Mask(MICROMIPS)
+Use microMIPS instructions
+
mmt
Target Report Var(TARGET_MT)
Allow the use of MT instructions
@@ -269,6 +307,10 @@ mno-float
Target Report RejectNegative Var(TARGET_NO_FLOAT) Condition(TARGET_SUPPORTS_NO_FLOAT)
Prevent the use of all floating-point operations
+mmcu
+Target Report Var(TARGET_MCU)
+Use MCU instructions
+
mno-flush-func
Target RejectNegative
Do not use a cache-flushing function before calling stack trampolines
@@ -282,7 +324,7 @@ Target Report RejectNegative InverseMask(MIPS16)
Generate normal-mode code
mno-mips3d
-Target Report RejectNegative InverseMask(MIPS3D)
+Target Report RejectNegative Var(TARGET_MIPS3D, 0)
Do not use MIPS-3D instructions
mpaired-single
@@ -346,6 +388,10 @@ muninit-const-in-rodata
Target Report Var(TARGET_UNINIT_CONST_IN_RODATA)
Put uninitialized constants in ROM (needs -membedded-data)
+mvirt
+Target Report Var(TARGET_VIRT)
+Use Virtualization Application Specific instructions
+
mvr4130-align
Target Report Mask(VR4130_ALIGN)
Perform VR4130-specific alignment optimizations
diff --git a/gcc/config/mips/mti-elf.h b/gcc/config/mips/mti-elf.h
new file mode 100644
index 0000000000..76d289eaee
--- /dev/null
+++ b/gcc/config/mips/mti-elf.h
@@ -0,0 +1,42 @@
+/* Target macros for mips*-mti-elf targets.
+ Copyright (C) 2012-2014 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#undef DRIVER_SELF_SPECS
+#define DRIVER_SELF_SPECS \
+ /* Make sure a -mips option is present. This helps us to pick \
+ the right multilib, and also makes the later specs easier \
+ to write. */ \
+ MIPS_ISA_LEVEL_SPEC, \
+ \
+ /* Infer the default float setting from -march. */ \
+ MIPS_ARCH_FLOAT_SPEC, \
+ \
+ /* Infer the -msynci setting from -march if not explicitly set. */ \
+ MIPS_ISA_SYNCI_SPEC, \
+ \
+ /* If no ABI option is specified, infer one from the ISA level \
+ or -mgp setting. */ \
+ "%{!mabi=*: %{" MIPS_32BIT_OPTION_SPEC ": -mabi=32;: -mabi=n32}}", \
+ \
+ /* Make sure that an endian option is always present. This makes \
+ things like LINK_SPEC easier to write. */ \
+ "%{!EB:%{!EL:%(endian_spec)}}", \
+ \
+ /* Configuration-independent MIPS rules. */ \
+ BASE_DRIVER_SELF_SPECS
diff --git a/gcc/config/mips/mti-linux.h b/gcc/config/mips/mti-linux.h
new file mode 100644
index 0000000000..db9896b404
--- /dev/null
+++ b/gcc/config/mips/mti-linux.h
@@ -0,0 +1,46 @@
+/* Target macros for mips*-mti-linux* targets.
+ Copyright (C) 2012-2014 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+/* This target is a multilib target, specify the sysroot paths. */
+#undef SYSROOT_SUFFIX_SPEC
+#define SYSROOT_SUFFIX_SPEC \
+ "%{mips32:/mips32}%{mips64:/mips64}%{mips64r2:/mips64r2}%{mips16:/mips16}%{mmicromips:/micromips}%{mabi=64:/64}%{mel|EL:/el}%{msoft-float:/sof}%{mfp64:/fp64}%{mnan=2008:/nan2008}"
+
+#undef DRIVER_SELF_SPECS
+#define DRIVER_SELF_SPECS \
+ /* Make sure a -mips option is present. This helps us to pick \
+ the right multilib, and also makes the later specs easier \
+ to write. */ \
+ MIPS_ISA_LEVEL_SPEC, \
+ \
+ /* Infer the default float setting from -march. */ \
+ MIPS_ARCH_FLOAT_SPEC, \
+ \
+ /* Infer the -msynci setting from -march if not explicitly set. */ \
+ MIPS_ISA_SYNCI_SPEC, \
+ \
+ /* If no ABI option is specified, infer one from the ISA level \
+ or -mgp setting. */ \
+ "%{!mabi=*: %{" MIPS_32BIT_OPTION_SPEC ": -mabi=32;: -mabi=n32}}", \
+ \
+ /* Base SPECs. */ \
+ BASE_DRIVER_SELF_SPECS \
+ \
+ /* Use the standard linux specs for everything else. */ \
+ LINUX64_DRIVER_SELF_SPECS
diff --git a/gcc/config/mips/n32-elf.h b/gcc/config/mips/n32-elf.h
new file mode 100644
index 0000000000..cb0cbbf956
--- /dev/null
+++ b/gcc/config/mips/n32-elf.h
@@ -0,0 +1,35 @@
+/* Definitions of target machine for GNU compiler.
+ n32 for embedded systems.
+ Copyright (C) 2003-2014 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+/* Use standard ELF-style local labels (not '$' as on early Irix). */
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX "."
+
+/* Use periods rather than dollar signs in special g++ assembler names. */
+#define NO_DOLLAR_IN_LABEL
+
+/* Force n32 to use 64-bit long doubles. */
+#undef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE 64
+
+#ifdef IN_LIBGCC2
+#undef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
+#endif
diff --git a/gcc/config/mips/netbsd.h b/gcc/config/mips/netbsd.h
index 4a9bd152fc..efa28869b1 100644
--- a/gcc/config/mips/netbsd.h
+++ b/gcc/config/mips/netbsd.h
@@ -1,6 +1,5 @@
/* Definitions of target machine for GNU compiler, for MIPS NetBSD systems.
- Copyright (C) 1993, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004,
- 2007, 2010, 2011 Free Software Foundation, Inc.
+ Copyright (C) 1993-2014 Free Software Foundation, Inc.
This file is part of GCC.
@@ -33,7 +32,9 @@ along with GCC; see the file COPYING3. If not see
if (TARGET_ABICALLS) \
builtin_define ("__ABICALLS__"); \
\
- if (mips_abi == ABI_EABI) \
+ if (mips_abi == ABI_32) \
+ builtin_define ("__mips_o32"); \
+ else if (mips_abi == ABI_EABI) \
builtin_define ("__mips_eabi"); \
else if (mips_abi == ABI_N32) \
builtin_define ("__mips_n32"); \
diff --git a/gcc/config/mips/octeon.md b/gcc/config/mips/octeon.md
index 566beea26d..1d6251c40a 100644
--- a/gcc/config/mips/octeon.md
+++ b/gcc/config/mips/octeon.md
@@ -1,6 +1,5 @@
;; Octeon pipeline description.
-;; Copyright (C) 2008
-;; Free Software Foundation, Inc.
+;; Copyright (C) 2008-2014 Free Software Foundation, Inc.
;; This file is part of GCC.
@@ -83,22 +82,22 @@
(define_insn_reservation "octeon_imul_o1" 2
(and (eq_attr "cpu" "octeon")
- (eq_attr "type" "imul,mthilo"))
+ (eq_attr "type" "imul,mthi,mtlo"))
"(octeon_pipe0 | octeon_pipe1) + octeon_mult, octeon_mult")
(define_insn_reservation "octeon_imul_o2" 1
(and (eq_attr "cpu" "octeon2")
- (eq_attr "type" "imul,mthilo"))
+ (eq_attr "type" "imul,mthi,mtlo"))
"octeon_pipe1 + octeon_mult")
(define_insn_reservation "octeon_mfhilo_o1" 5
(and (eq_attr "cpu" "octeon")
- (eq_attr "type" "mfhilo"))
+ (eq_attr "type" "mfhi,mflo"))
"(octeon_pipe0 | octeon_pipe1) + octeon_mult")
(define_insn_reservation "octeon_mfhilo_o2" 6
(and (eq_attr "cpu" "octeon2")
- (eq_attr "type" "mfhilo"))
+ (eq_attr "type" "mfhi,mflo"))
"octeon_pipe1 + octeon_mult")
(define_insn_reservation "octeon_imadd_o1" 4
@@ -133,5 +132,5 @@
(define_insn_reservation "octeon_unknown" 1
(and (eq_attr "cpu" "octeon,octeon2")
- (eq_attr "type" "unknown,multi"))
+ (eq_attr "type" "unknown,multi,atomic,syncloop"))
"octeon_pipe0 + octeon_pipe1")
diff --git a/gcc/config/mips/openbsd.h b/gcc/config/mips/openbsd.h
deleted file mode 100644
index a392ca4701..0000000000
--- a/gcc/config/mips/openbsd.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* Configuration for a MIPS ABI32 OpenBSD target.
- Copyright (C) 1999, 2003, 2004, 2007, 2008, 2009, 2010, 2011
- Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-/* Definitions needed for OpenBSD, to avoid picking mips 'defaults'. */
-
-/* GAS must know this. */
-#undef SUBTARGET_ASM_SPEC
-#define SUBTARGET_ASM_SPEC "%{fPIC|fPIE:-KPIC}"
-
-/* CPP specific OpenBSD specs. */
-#undef SUBTARGET_CPP_SPEC
-#define SUBTARGET_CPP_SPEC OBSD_CPP_SPEC
-
-/* Needed for ELF (inspired by netbsd-elf). */
-#undef LOCAL_LABEL_PREFIX
-#define LOCAL_LABEL_PREFIX "."
-
-/* The profiling lib spec here is not really correct but we leave
- it as it is until we have some kind of profiling working. */
-#define LIB_SPEC OBSD_LIB_SPEC
-
-/* mips assembler uses .set for arcane purposes. __attribute__((alias))
- and friends won't work until we get recent binutils with .weakext
- support. */
-#undef SET_ASM_OP
-
-#define TARGET_OS_CPP_BUILTINS() \
- do { \
- builtin_define ("__unix__"); \
- builtin_define ("__SYSTYPE_BSD__"); \
- builtin_define ("__NO_LEADING_UNDERSCORES__"); \
- builtin_define ("__GP_SUPPORT__"); \
- builtin_define ("__OpenBSD__"); \
- builtin_assert ("system=unix"); \
- builtin_assert ("system=OpenBSD"); \
-} while (0)
-
-/* Layout of source language data types. */
-
-/* This must agree with <machine/ansi.h>. */
-#undef SIZE_TYPE
-#define SIZE_TYPE "long unsigned int"
-
-#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "long int"
-
-#undef WCHAR_TYPE
-#define WCHAR_TYPE "int"
-
-#undef WCHAR_TYPE_SIZE
-#define WCHAR_TYPE_SIZE 32
-
-#undef WINT_TYPE
-#define WINT_TYPE "int"
-
-/* Controlling the compilation driver. */
-
-/* LINK_SPEC appropriate for OpenBSD: support for GCC options
- -static, -assert, and -nostdlib. Dynamic loader control. */
-#undef LINK_SPEC
-#define LINK_SPEC \
- "%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} \
- %{shared} \
- %{!shared: -non_shared} \
- -dynamic-linker /usr/libexec/ld.so \
- %{!nostdlib:%{!r:%{!e*:-e __start}}} -dc -dp \
- %{static:-Bstatic} %{!static:-Bdynamic} %{assert*}"
-
-/* -G is incompatible with -KPIC which is the default, so only allow objects
- in the small data section if the user explicitly asks for it. */
-#undef MIPS_DEFAULT_GVALUE
-#define MIPS_DEFAULT_GVALUE 0
-
-
-/* Since gas and gld are standard on OpenBSD, we don't need these. */
-#undef ASM_FINAL_SPEC
-#undef STARTFILE_SPEC
-
-/* Switch into a generic section. */
-#undef TARGET_ASM_NAMED_SECTION
-#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section
-
-/* MIPS specific debugging info */
-#define MIPS_DEBUGGING_INFO 1
diff --git a/gcc/config/mips/predicates.md b/gcc/config/mips/predicates.md
index 57b1af2de3..8ac8e0b6a5 100644
--- a/gcc/config/mips/predicates.md
+++ b/gcc/config/mips/predicates.md
@@ -1,5 +1,5 @@
;; Predicate definitions for MIPS.
-;; Copyright (C) 2004, 2007, 2008 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
@@ -122,6 +122,122 @@
? M16_REG_P (REGNO (op))
: GP_REG_P (REGNO (op))")))
+(define_predicate "lwsp_swsp_operand"
+ (and (match_code "mem")
+ (match_test "lwsp_swsp_address_p (XEXP (op, 0), mode)")))
+
+(define_predicate "lw16_sw16_operand"
+ (and (match_code "mem")
+ (match_test "m16_based_address_p (XEXP (op, 0), mode, uw4_operand)")))
+
+(define_predicate "lhu16_sh16_operand"
+ (and (match_code "mem")
+ (match_test "m16_based_address_p (XEXP (op, 0), mode, uh4_operand)")))
+
+(define_predicate "lbu16_operand"
+ (and (match_code "mem")
+ (match_test "m16_based_address_p (XEXP (op, 0), mode, db4_operand)")))
+
+(define_predicate "sb16_operand"
+ (and (match_code "mem")
+ (match_test "m16_based_address_p (XEXP (op, 0), mode, ub4_operand)")))
+
+(define_predicate "db4_operand"
+ (and (match_code "const_int")
+ (match_test "mips_unsigned_immediate_p (INTVAL (op) + 1, 4, 0)")))
+
+(define_predicate "db7_operand"
+ (and (match_code "const_int")
+ (match_test "mips_unsigned_immediate_p (INTVAL (op) + 1, 7, 0)")))
+
+(define_predicate "db8_operand"
+ (and (match_code "const_int")
+ (match_test "mips_unsigned_immediate_p (INTVAL (op) + 1, 8, 0)")))
+
+(define_predicate "ib3_operand"
+ (and (match_code "const_int")
+ (match_test "mips_unsigned_immediate_p (INTVAL (op) - 1, 3, 0)")))
+
+(define_predicate "sb4_operand"
+ (and (match_code "const_int")
+ (match_test "mips_signed_immediate_p (INTVAL (op), 4, 0)")))
+
+(define_predicate "sb5_operand"
+ (and (match_code "const_int")
+ (match_test "mips_signed_immediate_p (INTVAL (op), 5, 0)")))
+
+(define_predicate "sb8_operand"
+ (and (match_code "const_int")
+ (match_test "mips_signed_immediate_p (INTVAL (op), 8, 0)")))
+
+(define_predicate "sd8_operand"
+ (and (match_code "const_int")
+ (match_test "mips_signed_immediate_p (INTVAL (op), 8, 3)")))
+
+(define_predicate "ub4_operand"
+ (and (match_code "const_int")
+ (match_test "mips_unsigned_immediate_p (INTVAL (op), 4, 0)")))
+
+(define_predicate "ub8_operand"
+ (and (match_code "const_int")
+ (match_test "mips_unsigned_immediate_p (INTVAL (op), 8, 0)")))
+
+(define_predicate "uh4_operand"
+ (and (match_code "const_int")
+ (match_test "mips_unsigned_immediate_p (INTVAL (op), 4, 1)")))
+
+(define_predicate "uw4_operand"
+ (and (match_code "const_int")
+ (match_test "mips_unsigned_immediate_p (INTVAL (op), 4, 2)")))
+
+(define_predicate "uw5_operand"
+ (and (match_code "const_int")
+ (match_test "mips_unsigned_immediate_p (INTVAL (op), 5, 2)")))
+
+(define_predicate "uw6_operand"
+ (and (match_code "const_int")
+ (match_test "mips_unsigned_immediate_p (INTVAL (op), 6, 2)")))
+
+(define_predicate "uw8_operand"
+ (and (match_code "const_int")
+ (match_test "mips_unsigned_immediate_p (INTVAL (op), 8, 2)")))
+
+(define_predicate "addiur2_operand"
+ (and (match_code "const_int")
+ (ior (match_test "INTVAL (op) == -1")
+ (match_test "INTVAL (op) == 1")
+ (match_test "INTVAL (op) == 4")
+ (match_test "INTVAL (op) == 8")
+ (match_test "INTVAL (op) == 12")
+ (match_test "INTVAL (op) == 16")
+ (match_test "INTVAL (op) == 20")
+ (match_test "INTVAL (op) == 24"))))
+
+(define_predicate "addiusp_operand"
+ (and (match_code "const_int")
+ (ior (match_test "(IN_RANGE (INTVAL (op), 2, 257))")
+ (match_test "(IN_RANGE (INTVAL (op), -258, -3))"))))
+
+(define_predicate "andi16_operand"
+ (and (match_code "const_int")
+ (ior (match_test "IN_RANGE (INTVAL (op), 1, 4)")
+ (match_test "IN_RANGE (INTVAL (op), 7, 8)")
+ (match_test "IN_RANGE (INTVAL (op), 15, 16)")
+ (match_test "IN_RANGE (INTVAL (op), 31, 32)")
+ (match_test "IN_RANGE (INTVAL (op), 63, 64)")
+ (match_test "INTVAL (op) == 255")
+ (match_test "INTVAL (op) == 32768")
+ (match_test "INTVAL (op) == 65535"))))
+
+(define_predicate "movep_src_register"
+ (and (match_code "reg")
+ (ior (match_test ("IN_RANGE (REGNO (op), 2, 3)"))
+ (match_test ("IN_RANGE (REGNO (op), 16, 20)")))))
+
+(define_predicate "movep_src_operand"
+ (ior (match_operand 0 "const_0_operand")
+ (match_operand 0 "movep_src_register")))
+
(define_predicate "lo_operand"
(and (match_code "reg")
(match_test "REGNO (op) == LO_REGNUM")))
@@ -139,9 +255,6 @@
(match_operand 0 "hilo_operand")
(match_operand 0 "register_operand")))
-(define_special_predicate "pc_or_label_operand"
- (match_code "pc,label_ref"))
-
(define_predicate "const_call_insn_operand"
(match_code "const,symbol_ref,label_ref")
{
@@ -370,3 +483,12 @@
(define_predicate "small_data_pattern"
(and (match_code "set,parallel,unspec,unspec_volatile,prefetch")
(match_test "mips_small_data_pattern_p (op)")))
+
+(define_predicate "mem_noofs_operand"
+ (and (match_code "mem")
+ (match_code "reg" "0")))
+
+;; Return 1 if the operand is in non-volatile memory.
+(define_predicate "non_volatile_mem_operand"
+ (and (match_operand 0 "memory_operand")
+ (not (match_test "MEM_VOLATILE_P (op)"))))
diff --git a/gcc/config/mips/r3900.h b/gcc/config/mips/r3900.h
index 557ca3e47f..d5b191264c 100644
--- a/gcc/config/mips/r3900.h
+++ b/gcc/config/mips/r3900.h
@@ -1,8 +1,7 @@
/* Definitions of MIPS sub target machine for GNU compiler.
Toshiba r3900. You should include mips.h after this.
- Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2004,
- 2007, 2010 Free Software Foundation, Inc.
+ Copyright (C) 1989-2014 Free Software Foundation, Inc.
Contributed by Gavin Koch (gavin@cygnus.com).
This file is part of GCC.
diff --git a/gcc/config/mips/rtems.h b/gcc/config/mips/rtems.h
index 74da4f7064..09b46b875c 100644
--- a/gcc/config/mips/rtems.h
+++ b/gcc/config/mips/rtems.h
@@ -1,6 +1,5 @@
/* Definitions for rtems targeting a MIPS using ELF.
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2005, 2007
- Free Software Foundation, Inc.
+ Copyright (C) 1996-2014 Free Software Foundation, Inc.
Contributed by Joel Sherrill (joel@OARcorp.com).
This file is part of GCC.
diff --git a/gcc/config/mips/sb1.md b/gcc/config/mips/sb1.md
index 2d36c2212f..311300e505 100644
--- a/gcc/config/mips/sb1.md
+++ b/gcc/config/mips/sb1.md
@@ -1,4 +1,4 @@
-;; Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
@@ -108,7 +108,7 @@
(define_insn_reservation "ir_sb1_unknown" 1
(and (eq_attr "cpu" "sb1,sb1a")
- (eq_attr "type" "unknown,multi"))
+ (eq_attr "type" "unknown,multi,atomic,syncloop"))
"sb1_ls0+sb1_ls1+sb1_ex0+sb1_ex1+sb1_fp0+sb1_fp1")
;; predicted taken branch causes 2 cycle ifetch bubble. predicted not
@@ -295,21 +295,19 @@
(define_insn_reservation "ir_sb1_mfhi" 1
(and (eq_attr "cpu" "sb1,sb1a")
- (and (eq_attr "type" "mfhilo")
- (not (match_operand 1 "lo_operand"))))
+ (eq_attr "type" "mfhi"))
"sb1_ex1")
(define_insn_reservation "ir_sb1_mflo" 1
(and (eq_attr "cpu" "sb1,sb1a")
- (and (eq_attr "type" "mfhilo")
- (match_operand 1 "lo_operand")))
+ (eq_attr "type" "mflo"))
"sb1_ex1")
;; mt{hi,lo} to mul/div is 4 cycles.
(define_insn_reservation "ir_sb1_mthilo" 4
(and (eq_attr "cpu" "sb1,sb1a")
- (eq_attr "type" "mthilo"))
+ (eq_attr "type" "mthi,mtlo"))
"sb1_ex1")
;; mt{hi,lo} to mf{hi,lo} is 3 cycles.
diff --git a/gcc/config/mips/sdb.h b/gcc/config/mips/sdb.h
deleted file mode 100644
index 27a42df7ab..0000000000
--- a/gcc/config/mips/sdb.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* Generate SDB debugging info.
- Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-/* Note that no configuration uses sdb as its preferred format. */
-
-#define SDB_DEBUGGING_INFO 1
-
-/* Forward references to tags are allowed. */
-#define SDB_ALLOW_FORWARD_REFERENCES
-
-/* Unknown tags are also allowed. */
-#define SDB_ALLOW_UNKNOWN_REFERENCES
-
-/* Block start/end next label #. */
-extern int sdb_label_count;
-
-/* Starting line of current function. */
-extern int sdb_begin_function_line;
-
-/* For block start and end, we create labels, so that
- later we can figure out where the correct offset is.
- The normal .ent/.end serve well enough for functions,
- so those are just commented out. */
-
-#define PUT_SDB_BLOCK_START(LINE) \
-do { \
- fprintf (asm_out_file, \
- "%sLb%d:\n\t.begin\t%sLb%d\t%d\n", \
- LOCAL_LABEL_PREFIX, \
- sdb_label_count, \
- LOCAL_LABEL_PREFIX, \
- sdb_label_count, \
- (LINE)); \
- sdb_label_count++; \
-} while (0)
-
-#define PUT_SDB_BLOCK_END(LINE) \
-do { \
- fprintf (asm_out_file, \
- "%sLe%d:\n\t.bend\t%sLe%d\t%d\n", \
- LOCAL_LABEL_PREFIX, \
- sdb_label_count, \
- LOCAL_LABEL_PREFIX, \
- sdb_label_count, \
- (LINE)); \
- sdb_label_count++; \
-} while (0)
-
-#define PUT_SDB_FUNCTION_START(LINE)
-
-#define PUT_SDB_FUNCTION_END(LINE) \
-do { \
- SDB_OUTPUT_SOURCE_LINE (asm_out_file, LINE + sdb_begin_function_line); \
-} while (0)
-
-#define PUT_SDB_EPILOGUE_END(NAME)
-
-/* We need to use .esize and .etype instead of .size and .type to
- avoid conflicting with ELF directives. */
-#undef PUT_SDB_SIZE
-#define PUT_SDB_SIZE(a) \
-do { \
- fprintf (asm_out_file, "\t.esize\t" HOST_WIDE_INT_PRINT_DEC ";", \
- (HOST_WIDE_INT) (a)); \
-} while (0)
-
-#undef PUT_SDB_TYPE
-#define PUT_SDB_TYPE(a) \
-do { \
- fprintf (asm_out_file, "\t.etype\t0x%x;", (a)); \
-} while (0)
diff --git a/gcc/config/mips/sde.h b/gcc/config/mips/sde.h
index 7194c1e542..c138949c2a 100644
--- a/gcc/config/mips/sde.h
+++ b/gcc/config/mips/sde.h
@@ -1,7 +1,6 @@
/* Definitions of target machine for GNU compiler.
MIPS SDE version.
- Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010, 2011
- Free Software Foundation, Inc.
+ Copyright (C) 2003-2014 Free Software Foundation, Inc.
This file is part of GCC.
@@ -67,9 +66,6 @@ along with GCC; see the file COPYING3. If not see
#undef DEFAULT_SIGNED_CHAR
#define DEFAULT_SIGNED_CHAR 0
-/* SDE-MIPS won't ever support SDB debugging info. */
-#undef SDB_DEBUGGING_INFO
-
/* Describe how we implement __builtin_eh_return. */
/* At the moment, nothing appears to use more than 2 EH data registers.
@@ -93,34 +89,6 @@ along with GCC; see the file COPYING3. If not see
#undef PTRDIFF_TYPE
#define PTRDIFF_TYPE "long int"
-/* Use standard ELF-style local labels (not '$' as on early Irix). */
-#undef LOCAL_LABEL_PREFIX
-#define LOCAL_LABEL_PREFIX "."
-
-/* Use periods rather than dollar signs in special g++ assembler names. */
-#define NO_DOLLAR_IN_LABEL
-
-/* Attach a special .ident directive to the end of the file to identify
- the version of GCC which compiled this code. */
-#undef IDENT_ASM_OP
-#define IDENT_ASM_OP "\t.ident\t"
-
-/* Output #ident string into the ELF .comment section, so it doesn't
- form part of the load image, and so that it can be stripped. */
-#undef ASM_OUTPUT_IDENT
-#define ASM_OUTPUT_IDENT(STREAM, STRING) \
- fprintf (STREAM, "%s\"%s\"\n", IDENT_ASM_OP, STRING);
-
-/* Currently we don't support 128bit long doubles, so for now we force
- n32 to be 64bit. */
-#undef LONG_DOUBLE_TYPE_SIZE
-#define LONG_DOUBLE_TYPE_SIZE 64
-
-#ifdef IN_LIBGCC2
-#undef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
-#endif
-
/* Force all .init and .fini entries to be 32-bit, not mips16, so that
in a mixed environment they are all the same mode. The crti.asm and
crtn.asm files will also be compiled as 32-bit due to the
diff --git a/gcc/config/mips/sde.opt b/gcc/config/mips/sde.opt
index 61b0ebedd1..4cf43b6cc3 100644
--- a/gcc/config/mips/sde.opt
+++ b/gcc/config/mips/sde.opt
@@ -1,6 +1,6 @@
; MIPS SDE options.
;
-; Copyright (C) 2010 Free Software Foundation, Inc.
+; Copyright (C) 2010-2014 Free Software Foundation, Inc.
;
; This file is part of GCC.
;
diff --git a/gcc/config/mips/sdemtk.h b/gcc/config/mips/sdemtk.h
index 16c3a6cba2..15dbf16536 100644
--- a/gcc/config/mips/sdemtk.h
+++ b/gcc/config/mips/sdemtk.h
@@ -1,7 +1,6 @@
/* Definitions of target machine for GNU compiler.
MIPS SDE version, for use with the SDE C library rather than newlib.
- Copyright (C) 2007, 2008, 2009, 2010
- Free Software Foundation, Inc.
+ Copyright (C) 2007-2014 Free Software Foundation, Inc.
This file is part of GCC.
diff --git a/gcc/config/mips/sr71k.md b/gcc/config/mips/sr71k.md
index 9b2a784b1c..e669276557 100644
--- a/gcc/config/mips/sr71k.md
+++ b/gcc/config/mips/sr71k.md
@@ -1,4 +1,4 @@
-;; Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2014 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
@@ -144,7 +144,7 @@
(define_insn_reservation "ir_sr70_unknown" 1
(and (eq_attr "cpu" "sr71000")
- (eq_attr "type" "unknown"))
+ (eq_attr "type" "unknown,atomic,syncloop"))
"serial_dispatch")
@@ -201,7 +201,7 @@
(define_insn_reservation "ir_sr70_hilo" 1
(and (eq_attr "cpu" "sr71000")
- (eq_attr "type" "mthilo,mfhilo"))
+ (eq_attr "type" "mthi,mtlo,mfhi,mflo"))
"ri_insns")
(define_insn_reservation "ir_sr70_arith" 1
diff --git a/gcc/config/mips/st.h b/gcc/config/mips/st.h
index 363e797a96..6e99074d08 100644
--- a/gcc/config/mips/st.h
+++ b/gcc/config/mips/st.h
@@ -1,6 +1,5 @@
/* ST 2e / 2f GNU/Linux Configuration.
- Copyright (C) 2008
- Free Software Foundation, Inc.
+ Copyright (C) 2008-2014 Free Software Foundation, Inc.
This file is part of GCC.
diff --git a/gcc/config/mips/sync.md b/gcc/config/mips/sync.md
index 1b4097ec22..cf6c05be27 100644
--- a/gcc/config/mips/sync.md
+++ b/gcc/config/mips/sync.md
@@ -1,7 +1,6 @@
;; Machine Description for MIPS based processor synchronization
;; instructions.
-;; Copyright (C) 2007, 2008, 2009, 2010
-;; Free Software Foundation, Inc.
+;; Copyright (C) 2007-2014 Free Software Foundation, Inc.
;; This file is part of GCC.
@@ -29,6 +28,9 @@
UNSPEC_SYNC_EXCHANGE
UNSPEC_SYNC_EXCHANGE_12
UNSPEC_MEMORY_BARRIER
+ UNSPEC_ATOMIC_COMPARE_AND_SWAP
+ UNSPEC_ATOMIC_EXCHANGE
+ UNSPEC_ATOMIC_FETCH_OP
])
;; Atomic fetch bitwise operations.
@@ -54,9 +56,10 @@
"GENERATE_SYNC"
{ return mips_output_sync (); })
+;; Can be removed in favor of atomic_compare_and_swap below.
(define_insn "sync_compare_and_swap<mode>"
[(set (match_operand:GPR 0 "register_operand" "=&d,&d")
- (match_operand:GPR 1 "memory_operand" "+R,R"))
+ (match_operand:GPR 1 "memory_operand" "+ZR,ZR"))
(set (match_dup 1)
(unspec_volatile:GPR [(match_operand:GPR 2 "reg_or_0_operand" "dJ,dJ")
(match_operand:GPR 3 "arith_operand" "I,d")]
@@ -86,7 +89,7 @@
;; Helper insn for mips_expand_atomic_qihi.
(define_insn "compare_and_swap_12"
[(set (match_operand:SI 0 "register_operand" "=&d,&d")
- (match_operand:SI 1 "memory_operand" "+R,R"))
+ (match_operand:SI 1 "memory_operand" "+ZR,ZR"))
(set (match_dup 1)
(unspec_volatile:SI [(match_operand:SI 2 "register_operand" "d,d")
(match_operand:SI 3 "register_operand" "d,d")
@@ -103,7 +106,7 @@
(set_attr "sync_insn1_op2" "5")])
(define_insn "sync_add<mode>"
- [(set (match_operand:GPR 0 "memory_operand" "+R,R")
+ [(set (match_operand:GPR 0 "memory_operand" "+ZR,ZR")
(unspec_volatile:GPR
[(plus:GPR (match_dup 0)
(match_operand:GPR 1 "arith_operand" "I,d"))]
@@ -131,7 +134,7 @@
;; Helper insn for sync_<optab><mode>
(define_insn "sync_<optab>_12"
- [(set (match_operand:SI 0 "memory_operand" "+R")
+ [(set (match_operand:SI 0 "memory_operand" "+ZR")
(unspec_volatile:SI
[(match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "register_operand" "d")
@@ -171,7 +174,7 @@
;; Helper insn for sync_old_<optab><mode>
(define_insn "sync_old_<optab>_12"
[(set (match_operand:SI 0 "register_operand" "=&d")
- (match_operand:SI 1 "memory_operand" "+R"))
+ (match_operand:SI 1 "memory_operand" "+ZR"))
(set (match_dup 1)
(unspec_volatile:SI
[(match_operand:SI 2 "register_operand" "d")
@@ -214,7 +217,7 @@
(define_insn "sync_new_<optab>_12"
[(set (match_operand:SI 0 "register_operand" "=&d")
(unspec_volatile:SI
- [(match_operand:SI 1 "memory_operand" "+R")
+ [(match_operand:SI 1 "memory_operand" "+ZR")
(match_operand:SI 2 "register_operand" "d")
(match_operand:SI 3 "register_operand" "d")
(atomic_hiqi_op:SI (match_dup 0)
@@ -254,7 +257,7 @@
;; Helper insn for sync_nand<mode>
(define_insn "sync_nand_12"
- [(set (match_operand:SI 0 "memory_operand" "+R")
+ [(set (match_operand:SI 0 "memory_operand" "+ZR")
(unspec_volatile:SI
[(match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "register_operand" "d")
@@ -293,7 +296,7 @@
;; Helper insn for sync_old_nand<mode>
(define_insn "sync_old_nand_12"
[(set (match_operand:SI 0 "register_operand" "=&d")
- (match_operand:SI 1 "memory_operand" "+R"))
+ (match_operand:SI 1 "memory_operand" "+ZR"))
(set (match_dup 1)
(unspec_volatile:SI
[(match_operand:SI 2 "register_operand" "d")
@@ -334,7 +337,7 @@
(define_insn "sync_new_nand_12"
[(set (match_operand:SI 0 "register_operand" "=&d")
(unspec_volatile:SI
- [(match_operand:SI 1 "memory_operand" "+R")
+ [(match_operand:SI 1 "memory_operand" "+ZR")
(match_operand:SI 2 "register_operand" "d")
(match_operand:SI 3 "register_operand" "d")
(match_operand:SI 4 "reg_or_0_operand" "dJ")]
@@ -357,7 +360,7 @@
(set_attr "sync_insn1_op2" "4")])
(define_insn "sync_sub<mode>"
- [(set (match_operand:GPR 0 "memory_operand" "+R")
+ [(set (match_operand:GPR 0 "memory_operand" "+ZR")
(unspec_volatile:GPR
[(minus:GPR (match_dup 0)
(match_operand:GPR 1 "register_operand" "d"))]
@@ -368,9 +371,10 @@
(set_attr "sync_mem" "0")
(set_attr "sync_insn1_op2" "1")])
+;; Can be removed in favor of atomic_fetch_add below.
(define_insn "sync_old_add<mode>"
[(set (match_operand:GPR 0 "register_operand" "=&d,&d")
- (match_operand:GPR 1 "memory_operand" "+R,R"))
+ (match_operand:GPR 1 "memory_operand" "+ZR,ZR"))
(set (match_dup 1)
(unspec_volatile:GPR
[(plus:GPR (match_dup 1)
@@ -385,7 +389,7 @@
(define_insn "sync_old_sub<mode>"
[(set (match_operand:GPR 0 "register_operand" "=&d")
- (match_operand:GPR 1 "memory_operand" "+R"))
+ (match_operand:GPR 1 "memory_operand" "+ZR"))
(set (match_dup 1)
(unspec_volatile:GPR
[(minus:GPR (match_dup 1)
@@ -400,7 +404,7 @@
(define_insn "sync_new_add<mode>"
[(set (match_operand:GPR 0 "register_operand" "=&d,&d")
- (plus:GPR (match_operand:GPR 1 "memory_operand" "+R,R")
+ (plus:GPR (match_operand:GPR 1 "memory_operand" "+ZR,ZR")
(match_operand:GPR 2 "arith_operand" "I,d")))
(set (match_dup 1)
(unspec_volatile:GPR
@@ -416,7 +420,7 @@
(define_insn "sync_new_sub<mode>"
[(set (match_operand:GPR 0 "register_operand" "=&d")
- (minus:GPR (match_operand:GPR 1 "memory_operand" "+R")
+ (minus:GPR (match_operand:GPR 1 "memory_operand" "+ZR")
(match_operand:GPR 2 "register_operand" "d")))
(set (match_dup 1)
(unspec_volatile:GPR
@@ -431,7 +435,7 @@
(set_attr "sync_insn1_op2" "2")])
(define_insn "sync_<optab><mode>"
- [(set (match_operand:GPR 0 "memory_operand" "+R,R")
+ [(set (match_operand:GPR 0 "memory_operand" "+ZR,ZR")
(unspec_volatile:GPR
[(fetchop_bit:GPR (match_operand:GPR 1 "uns_arith_operand" "K,d")
(match_dup 0))]
@@ -444,7 +448,7 @@
(define_insn "sync_old_<optab><mode>"
[(set (match_operand:GPR 0 "register_operand" "=&d,&d")
- (match_operand:GPR 1 "memory_operand" "+R,R"))
+ (match_operand:GPR 1 "memory_operand" "+ZR,ZR"))
(set (match_dup 1)
(unspec_volatile:GPR
[(fetchop_bit:GPR (match_operand:GPR 2 "uns_arith_operand" "K,d")
@@ -459,7 +463,7 @@
(define_insn "sync_new_<optab><mode>"
[(set (match_operand:GPR 0 "register_operand" "=&d,&d")
- (match_operand:GPR 1 "memory_operand" "+R,R"))
+ (match_operand:GPR 1 "memory_operand" "+ZR,ZR"))
(set (match_dup 1)
(unspec_volatile:GPR
[(fetchop_bit:GPR (match_operand:GPR 2 "uns_arith_operand" "K,d")
@@ -474,7 +478,7 @@
(set_attr "sync_insn1_op2" "2")])
(define_insn "sync_nand<mode>"
- [(set (match_operand:GPR 0 "memory_operand" "+R,R")
+ [(set (match_operand:GPR 0 "memory_operand" "+ZR,ZR")
(unspec_volatile:GPR [(match_operand:GPR 1 "uns_arith_operand" "K,d")]
UNSPEC_SYNC_OLD_OP))]
"GENERATE_LL_SC"
@@ -486,7 +490,7 @@
(define_insn "sync_old_nand<mode>"
[(set (match_operand:GPR 0 "register_operand" "=&d,&d")
- (match_operand:GPR 1 "memory_operand" "+R,R"))
+ (match_operand:GPR 1 "memory_operand" "+ZR,ZR"))
(set (match_dup 1)
(unspec_volatile:GPR [(match_operand:GPR 2 "uns_arith_operand" "K,d")]
UNSPEC_SYNC_OLD_OP))]
@@ -500,7 +504,7 @@
(define_insn "sync_new_nand<mode>"
[(set (match_operand:GPR 0 "register_operand" "=&d,&d")
- (match_operand:GPR 1 "memory_operand" "+R,R"))
+ (match_operand:GPR 1 "memory_operand" "+ZR,ZR"))
(set (match_dup 1)
(unspec_volatile:GPR [(match_operand:GPR 2 "uns_arith_operand" "K,d")]
UNSPEC_SYNC_NEW_OP))]
@@ -515,13 +519,13 @@
(define_insn "sync_lock_test_and_set<mode>"
[(set (match_operand:GPR 0 "register_operand" "=&d,&d")
- (match_operand:GPR 1 "memory_operand" "+R,R"))
+ (match_operand:GPR 1 "memory_operand" "+ZR,ZR"))
(set (match_dup 1)
(unspec_volatile:GPR [(match_operand:GPR 2 "arith_operand" "I,d")]
UNSPEC_SYNC_EXCHANGE))]
"GENERATE_LL_SC"
{ return mips_output_sync_loop (insn, operands); }
- [(set_attr "sync_release_barrier" "no")
+ [(set_attr "sync_memmodel" "11")
(set_attr "sync_insn1" "li,move")
(set_attr "sync_oldval" "0")
(set_attr "sync_mem" "1")
@@ -542,7 +546,7 @@
(define_insn "test_and_set_12"
[(set (match_operand:SI 0 "register_operand" "=&d")
- (match_operand:SI 1 "memory_operand" "+R"))
+ (match_operand:SI 1 "memory_operand" "+ZR"))
(set (match_dup 1)
(unspec_volatile:SI [(match_operand:SI 2 "register_operand" "d")
(match_operand:SI 3 "register_operand" "d")
@@ -550,7 +554,7 @@
UNSPEC_SYNC_EXCHANGE_12))]
"GENERATE_LL_SC"
{ return mips_output_sync_loop (insn, operands); }
- [(set_attr "sync_release_barrier" "no")
+ [(set_attr "sync_memmodel" "11")
(set_attr "sync_oldval" "0")
(set_attr "sync_mem" "1")
;; Unused, but needed to give the number of operands expected by
@@ -558,3 +562,155 @@
(set_attr "sync_inclusive_mask" "2")
(set_attr "sync_exclusive_mask" "3")
(set_attr "sync_insn1_op2" "4")])
+
+(define_insn "atomic_compare_and_swap<mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
+ ;; Logically this unspec is an "eq" operator, but we need to obscure
+ ;; reads and writes from/to memory with an unspec to prevent
+ ;; optimizations on shared memory locations. Otherwise, comparison in
+ ;; { mem = 2; if (atomic_cmp_swap(mem,...) == 2) ...; }
+ ;; would be optimized away. In addition to that we need to use
+ ;; unspec_volatile, not just plain unspec -- for the sake of other
+ ;; threads -- to make sure we don't remove the entirety of the pattern
+ ;; just because current thread doesn't observe any effect from it.
+ ;; TODO: the obscuring unspec can be relaxed for permissive memory
+ ;; models.
+ ;; Same applies to other atomic_* patterns.
+ (unspec_volatile:GPR [(match_operand:GPR 2 "memory_operand" "+ZR,ZR")
+ (match_operand:GPR 3 "reg_or_0_operand" "dJ,dJ")]
+ UNSPEC_ATOMIC_COMPARE_AND_SWAP))
+ (set (match_operand:GPR 1 "register_operand" "=&d,&d")
+ (unspec_volatile:GPR [(match_dup 2)]
+ UNSPEC_ATOMIC_COMPARE_AND_SWAP))
+ (set (match_dup 2)
+ (unspec_volatile:GPR [(match_dup 2)
+ (match_dup 3)
+ (match_operand:GPR 4 "arith_operand" "I,d")]
+ UNSPEC_ATOMIC_COMPARE_AND_SWAP))
+ (unspec_volatile:GPR [(match_operand:SI 5 "const_int_operand")
+ (match_operand:SI 6 "const_int_operand")
+ (match_operand:SI 7 "const_int_operand")]
+ UNSPEC_ATOMIC_COMPARE_AND_SWAP)]
+ "GENERATE_LL_SC"
+ { return mips_output_sync_loop (insn, operands); }
+ [(set_attr "sync_insn1" "li,move")
+ (set_attr "sync_oldval" "1")
+ (set_attr "sync_cmp" "0")
+ (set_attr "sync_mem" "2")
+ (set_attr "sync_required_oldval" "3")
+ (set_attr "sync_insn1_op2" "4")
+ (set_attr "sync_memmodel" "6")])
+
+(define_expand "atomic_exchange<mode>"
+ [(match_operand:GPR 0 "register_operand")
+ (match_operand:GPR 1 "memory_operand")
+ (match_operand:GPR 2 "arith_operand")
+ (match_operand:SI 3 "const_int_operand")]
+ "GENERATE_LL_SC || ISA_HAS_SWAP"
+{
+ if (ISA_HAS_SWAP)
+ {
+ if (!mem_noofs_operand (operands[1], <MODE>mode))
+ {
+ rtx addr;
+
+ addr = force_reg (Pmode, XEXP (operands[1], 0));
+ operands[1] = replace_equiv_address (operands[1], addr);
+ }
+ operands[2] = force_reg (<MODE>mode, operands[2]);
+ emit_insn (gen_atomic_exchange<mode>_swap (operands[0], operands[1],
+ operands[2]));
+ }
+ else
+ emit_insn (gen_atomic_exchange<mode>_llsc (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+})
+
+(define_insn "atomic_exchange<mode>_llsc"
+ [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
+ (unspec_volatile:GPR [(match_operand:GPR 1 "memory_operand" "+ZR,ZR")]
+ UNSPEC_ATOMIC_EXCHANGE))
+ (set (match_dup 1)
+ (unspec_volatile:GPR [(match_operand:GPR 2 "arith_operand" "I,d")]
+ UNSPEC_ATOMIC_EXCHANGE))
+ (unspec_volatile:GPR [(match_operand:SI 3 "const_int_operand")]
+ UNSPEC_ATOMIC_EXCHANGE)]
+ "GENERATE_LL_SC && !ISA_HAS_SWAP"
+ { return mips_output_sync_loop (insn, operands); }
+ [(set_attr "sync_insn1" "li,move")
+ (set_attr "sync_oldval" "0")
+ (set_attr "sync_mem" "1")
+ (set_attr "sync_insn1_op2" "2")
+ (set_attr "sync_memmodel" "3")])
+
+;; XLP issues implicit sync for SWAP/LDADD, so no need for an explicit one.
+(define_insn "atomic_exchange<mode>_swap"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (unspec_volatile:GPR [(match_operand:GPR 1 "mem_noofs_operand" "+ZR")]
+ UNSPEC_ATOMIC_EXCHANGE))
+ (set (match_dup 1)
+ (unspec_volatile:GPR [(match_operand:GPR 2 "register_operand" "0")]
+ UNSPEC_ATOMIC_EXCHANGE))]
+ "ISA_HAS_SWAP"
+ "swap<size>\t%0,%b1"
+ [(set_attr "type" "atomic")])
+
+(define_expand "atomic_fetch_add<mode>"
+ [(match_operand:GPR 0 "register_operand")
+ (match_operand:GPR 1 "memory_operand")
+ (match_operand:GPR 2 "arith_operand")
+ (match_operand:SI 3 "const_int_operand")]
+ "GENERATE_LL_SC || ISA_HAS_LDADD"
+{
+ if (ISA_HAS_LDADD)
+ {
+ if (!mem_noofs_operand (operands[1], <MODE>mode))
+ {
+ rtx addr;
+
+ addr = force_reg (Pmode, XEXP (operands[1], 0));
+ operands[1] = replace_equiv_address (operands[1], addr);
+ }
+ operands[2] = force_reg (<MODE>mode, operands[2]);
+ emit_insn (gen_atomic_fetch_add<mode>_ldadd (operands[0], operands[1],
+ operands[2]));
+ }
+ else
+ emit_insn (gen_atomic_fetch_add<mode>_llsc (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+})
+
+(define_insn "atomic_fetch_add<mode>_llsc"
+ [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
+ (unspec_volatile:GPR [(match_operand:GPR 1 "memory_operand" "+ZR,ZR")]
+ UNSPEC_ATOMIC_FETCH_OP))
+ (set (match_dup 1)
+ (unspec_volatile:GPR
+ [(plus:GPR (match_dup 1)
+ (match_operand:GPR 2 "arith_operand" "I,d"))]
+ UNSPEC_ATOMIC_FETCH_OP))
+ (unspec_volatile:GPR [(match_operand:SI 3 "const_int_operand")]
+ UNSPEC_ATOMIC_FETCH_OP)]
+ "GENERATE_LL_SC && !ISA_HAS_LDADD"
+ { return mips_output_sync_loop (insn, operands); }
+ [(set_attr "sync_insn1" "addiu,addu")
+ (set_attr "sync_oldval" "0")
+ (set_attr "sync_mem" "1")
+ (set_attr "sync_insn1_op2" "2")
+ (set_attr "sync_memmodel" "3")])
+
+;; XLP issues implicit sync for SWAP/LDADD, so no need for an explicit one.
+(define_insn "atomic_fetch_add<mode>_ldadd"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (unspec_volatile:GPR [(match_operand:GPR 1 "mem_noofs_operand" "+ZR")]
+ UNSPEC_ATOMIC_FETCH_OP))
+ (set (match_dup 1)
+ (unspec_volatile:GPR
+ [(plus:GPR (match_dup 1)
+ (match_operand:GPR 2 "register_operand" "0"))]
+ UNSPEC_ATOMIC_FETCH_OP))]
+ "ISA_HAS_LDADD"
+ "ldadd<size>\t%0,%b1"
+ [(set_attr "type" "atomic")])
diff --git a/gcc/config/mips/t-elf b/gcc/config/mips/t-elf
index b4535d28fc..4e44a9f935 100644
--- a/gcc/config/mips/t-elf
+++ b/gcc/config/mips/t-elf
@@ -1,5 +1,4 @@
-# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2006,
-# 2007, 2011 Free Software Foundation, Inc.
+# Copyright (C) 1999-2014 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
diff --git a/gcc/config/mips/t-irix6 b/gcc/config/mips/t-irix6
index 40782752a3..6c76a4ad97 100644
--- a/gcc/config/mips/t-irix6
+++ b/gcc/config/mips/t-irix6
@@ -2,7 +2,3 @@ MULTILIB_OPTIONS=mabi=n32/mabi=64
MULTILIB_DIRNAMES=n32 64
MULTILIB_MATCHES=
MULTILIB_OSDIRNAMES=../lib32 ../lib64
-
-irix6-c.o: $(srcdir)/config/mips/irix6-c.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- tree.h $(TM_H) $(C_COMMON_H)
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
diff --git a/gcc/config/mips/t-isa3264 b/gcc/config/mips/t-isa3264
index 7291193f8a..a5e001ef74 100644
--- a/gcc/config/mips/t-isa3264
+++ b/gcc/config/mips/t-isa3264
@@ -1,5 +1,4 @@
-# Copyright (C) 2001, 2002, 2003, 2004, 2007,
-# 2008, 2011 Free Software Foundation, Inc.
+# Copyright (C) 2001-2014 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
diff --git a/gcc/config/mips/t-linux64 b/gcc/config/mips/t-linux64
index 20136cdbe9..4b28ad03d5 100644
--- a/gcc/config/mips/t-linux64
+++ b/gcc/config/mips/t-linux64
@@ -1,4 +1,4 @@
-# Copyright (C) 2003, 2004, 2005, 2006, 2011 Free Software Foundation, Inc.
+# Copyright (C) 2003-2014 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
diff --git a/gcc/config/mips/t-mips b/gcc/config/mips/t-mips
index 46c5ebcb1e..6e048f951f 100644
--- a/gcc/config/mips/t-mips
+++ b/gcc/config/mips/t-mips
@@ -1,4 +1,4 @@
-# Copyright (C) 2002, 2003, 2006, 2011 Free Software Foundation, Inc.
+# Copyright (C) 2002-2014 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
diff --git a/gcc/config/mips/t-mti-elf b/gcc/config/mips/t-mti-elf
new file mode 100644
index 0000000000..1109ea7166
--- /dev/null
+++ b/gcc/config/mips/t-mti-elf
@@ -0,0 +1,50 @@
+# Copyright (C) 2012-2014 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# The default build is mips32r2, hard-float big-endian. Add mips32,
+# soft-float, and little-endian variations.
+
+MULTILIB_OPTIONS = mips32/mips64/mips64r2 mips16/mmicromips mabi=64 EL msoft-float/mfp64 mnan=2008
+MULTILIB_DIRNAMES = mips32 mips64 mips64r2 mips16 micromips 64 el sof fp64 nan2008
+MULTILIB_MATCHES = EL=mel EB=meb
+
+# The 64 bit ABI is not supported on the mips32 architecture.
+MULTILIB_EXCEPTIONS += *mips32*/*mabi=64*
+
+# The 64 bit ABI is not supported on the mips32r2 architecture.
+# Because mips32r2 is the default we can't use that flag to trigger
+# the exception so we check for mabi=64 with no specific mips
+# architecture flag instead.
+MULTILIB_EXCEPTIONS += mabi=64*
+
+# We do not want to build mips16 versions of mips64* architectures.
+MULTILIB_EXCEPTIONS += *mips64*/*mips16*
+MULTILIB_EXCEPTIONS += *mips16/mabi=64*
+
+# We only want micromips for mips32r2 architecture.
+MULTILIB_EXCEPTIONS += *mips32/mmicromips*
+MULTILIB_EXCEPTIONS += *mips64*/mmicromips*
+MULTILIB_EXCEPTIONS += *mmicromips/mabi=64*
+
+# We do not want nan2008 libraries for soft-float.
+MULTILIB_EXCEPTIONS += *msoft-float*/*mnan=2008*
+
+# -mfp64 libraries are only built for mips32r2 and not in mips16 mode.
+MULTILIB_EXCEPTIONS += *mips32/*mfp64*
+MULTILIB_EXCEPTIONS += *mips64*/*mfp64*
+MULTILIB_EXCEPTIONS += *mips16*/*mfp64*
diff --git a/gcc/config/mips/t-mti-linux b/gcc/config/mips/t-mti-linux
new file mode 100644
index 0000000000..1109ea7166
--- /dev/null
+++ b/gcc/config/mips/t-mti-linux
@@ -0,0 +1,50 @@
+# Copyright (C) 2012-2014 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# The default build is mips32r2, hard-float big-endian. Add mips32,
+# soft-float, and little-endian variations.
+
+MULTILIB_OPTIONS = mips32/mips64/mips64r2 mips16/mmicromips mabi=64 EL msoft-float/mfp64 mnan=2008
+MULTILIB_DIRNAMES = mips32 mips64 mips64r2 mips16 micromips 64 el sof fp64 nan2008
+MULTILIB_MATCHES = EL=mel EB=meb
+
+# The 64 bit ABI is not supported on the mips32 architecture.
+MULTILIB_EXCEPTIONS += *mips32*/*mabi=64*
+
+# The 64 bit ABI is not supported on the mips32r2 architecture.
+# Because mips32r2 is the default we can't use that flag to trigger
+# the exception so we check for mabi=64 with no specific mips
+# architecture flag instead.
+MULTILIB_EXCEPTIONS += mabi=64*
+
+# We do not want to build mips16 versions of mips64* architectures.
+MULTILIB_EXCEPTIONS += *mips64*/*mips16*
+MULTILIB_EXCEPTIONS += *mips16/mabi=64*
+
+# We only want micromips for mips32r2 architecture.
+MULTILIB_EXCEPTIONS += *mips32/mmicromips*
+MULTILIB_EXCEPTIONS += *mips64*/mmicromips*
+MULTILIB_EXCEPTIONS += *mmicromips/mabi=64*
+
+# We do not want nan2008 libraries for soft-float.
+MULTILIB_EXCEPTIONS += *msoft-float*/*mnan=2008*
+
+# -mfp64 libraries are only built for mips32r2 and not in mips16 mode.
+MULTILIB_EXCEPTIONS += *mips32/*mfp64*
+MULTILIB_EXCEPTIONS += *mips64*/*mfp64*
+MULTILIB_EXCEPTIONS += *mips16*/*mfp64*
diff --git a/gcc/config/mips/t-r3900 b/gcc/config/mips/t-r3900
index d542df36ed..fcd9c25b57 100644
--- a/gcc/config/mips/t-r3900
+++ b/gcc/config/mips/t-r3900
@@ -1,5 +1,4 @@
-# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-# 2007, 2011 Free Software Foundation, Inc.
+# Copyright (C) 1998-2014 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
diff --git a/gcc/config/mips/t-rtems b/gcc/config/mips/t-rtems
index a2a1857256..4019f946bb 100644
--- a/gcc/config/mips/t-rtems
+++ b/gcc/config/mips/t-rtems
@@ -1,6 +1,6 @@
# Custom multilibs for RTEMS
#
-# Copyright (C) 2003, 2005, 2006 Free Software Foundation, Inc.
+# Copyright (C) 2003-2014 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
diff --git a/gcc/config/mips/t-sb1 b/gcc/config/mips/t-sb1
index 6c4acb320e..99214be4fe 100644
--- a/gcc/config/mips/t-sb1
+++ b/gcc/config/mips/t-sb1
@@ -1,4 +1,4 @@
-# Copyright (C) 2006 Free Software Foundation, Inc.
+# Copyright (C) 2006-2014 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
diff --git a/gcc/config/mips/t-sde b/gcc/config/mips/t-sde
index d9c229ab4e..229e3d6442 100644
--- a/gcc/config/mips/t-sde
+++ b/gcc/config/mips/t-sde
@@ -1,4 +1,4 @@
-# Copyright (C) 2007, 2008, 2011 Free Software Foundation, Inc.
+# Copyright (C) 2007-2014 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -16,8 +16,8 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-MULTILIB_OPTIONS = EL/EB mips32/mips32r2/mips64/mips64r2 mips16 msoft-float/mfp64 mcode-readable=no
-MULTILIB_DIRNAMES = el eb mips32 mips32r2 mips64 mips64r2 mips16 sof f64 spram
+MULTILIB_OPTIONS = EL/EB mips32/mips32r2/mips64/mips64r2 mips16/mmicromips msoft-float/mfp64 mcode-readable=no
+MULTILIB_DIRNAMES = el eb mips32 mips32r2 mips64 mips64r2 mips16 micromips sof f64 spram
MULTILIB_MATCHES = EL=mel EB=meb
# The -mfp64 option is only valid in conjunction with -mips32r2.
@@ -27,9 +27,11 @@ else
MULTILIB_EXCLUSIONS := !mips32r2/mfp64
endif
-# Don't build 64-bit MIPS16 multilibs.
+# Don't build 64-bit MIPS16 and microMIPS multilibs.
ifneq ($(filter MIPS_ISA_DEFAULT=6%,$(tm_defines)),)
MULTILIB_EXCLUSIONS += !mips32/!mips32r2/mips16
+MULTILIB_EXCLUSIONS += !mips32/!mips32r2/mmicromips
else
MULTILIB_EXCLUSIONS += mips64/mips16 mips64r2/mips16
+MULTILIB_EXCLUSIONS += mips64/mmicromips mips64r2/mmicromips
endif
diff --git a/gcc/config/mips/t-sdemtk b/gcc/config/mips/t-sdemtk
index decbcf3101..820faa305e 100644
--- a/gcc/config/mips/t-sdemtk
+++ b/gcc/config/mips/t-sdemtk
@@ -1,4 +1,4 @@
-# Copyright (C) 2007, 2008, 2011 Free Software Foundation, Inc.
+# Copyright (C) 2007-2014 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
diff --git a/gcc/config/mips/t-sr71k b/gcc/config/mips/t-sr71k
index 309eec6a65..3346c914cd 100644
--- a/gcc/config/mips/t-sr71k
+++ b/gcc/config/mips/t-sr71k
@@ -1,4 +1,4 @@
-# Copyright (C) 2002, 2003, 2010, 2011 Free Software Foundation, Inc.
+# Copyright (C) 2002-2014 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
diff --git a/gcc/config/mips/t-st b/gcc/config/mips/t-st
index b0a8933c32..57daa9f0c9 100644
--- a/gcc/config/mips/t-st
+++ b/gcc/config/mips/t-st
@@ -1,4 +1,4 @@
-# Copyright (C) 2008, 2011 Free Software Foundation, Inc.
+# Copyright (C) 2008-2014 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
diff --git a/gcc/config/mips/t-vr b/gcc/config/mips/t-vr
index de5ca706fa..ccc5d24e20 100644
--- a/gcc/config/mips/t-vr
+++ b/gcc/config/mips/t-vr
@@ -1,4 +1,4 @@
-# Copyright (C) 2002, 2004, 2005, 2011 Free Software Foundation, Inc.
+# Copyright (C) 2002-2014 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
diff --git a/gcc/config/mips/t-vxworks b/gcc/config/mips/t-vxworks
index ac2fa9d9f3..97c1e782b5 100644
--- a/gcc/config/mips/t-vxworks
+++ b/gcc/config/mips/t-vxworks
@@ -1,4 +1,4 @@
-# Copyright (C) 2003, 2007 Free Software Foundation, Inc.
+# Copyright (C) 2003-2014 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -32,4 +32,4 @@ MULTILIB_EXCEPTIONS = mips3* mabi=o64 fPIC \
$(addprefix mabi=o64/, EL* msoft-float* mrtp* fPIC*) \
$(addsuffix /fPIC, *mabi=o64 *mips3 *EL *msoft-float)
-MUTLILIB_EXTRA_OPTS = -G 0 -mno-branch-likely
+MULTILIB_EXTRA_OPTS = -G 0 -mno-branch-likely
diff --git a/gcc/config/mips/vr.h b/gcc/config/mips/vr.h
index 3a89e69ce1..bbbefd64d1 100644
--- a/gcc/config/mips/vr.h
+++ b/gcc/config/mips/vr.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler.
NEC VR Series Processors
- Copyright (c) 2002, 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2002-2014 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of GCC.
diff --git a/gcc/config/mips/vxworks.h b/gcc/config/mips/vxworks.h
index f742f97a8f..7771076d07 100644
--- a/gcc/config/mips/vxworks.h
+++ b/gcc/config/mips/vxworks.h
@@ -1,5 +1,4 @@
-/* Copyright (C) 1999, 2003, 2004, 2007, 2008, 2010, 2011
- Free Software Foundation, Inc.
+/* Copyright (C) 1999-2014 Free Software Foundation, Inc.
This file is part of GCC.
diff --git a/gcc/config/mips/xlp.md b/gcc/config/mips/xlp.md
new file mode 100644
index 0000000000..905808dd78
--- /dev/null
+++ b/gcc/config/mips/xlp.md
@@ -0,0 +1,213 @@
+;; DFA-based pipeline description for the XLP.
+;; Copyright (C) 2012-2014 Free Software Foundation, Inc.
+;;
+;; xlp.md Machine Description for the Broadcom XLP Microprocessor
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3. If not see
+;; <http://www.gnu.org/licenses/>.
+
+(define_automaton "xlp_cpu")
+
+;; CPU function units.
+(define_cpu_unit "xlp_ex0" "xlp_cpu")
+(define_cpu_unit "xlp_ex1" "xlp_cpu")
+(define_cpu_unit "xlp_ex2" "xlp_cpu")
+(define_cpu_unit "xlp_ex3" "xlp_cpu")
+
+;; Integer Multiply Unit
+(define_cpu_unit "xlp_div" "xlp_cpu")
+
+;; ALU2 completion port.
+(define_cpu_unit "xlp_ex2_wrb" "xlp_cpu")
+
+(define_automaton "xlp_fpu")
+
+;; Floating-point units.
+(define_cpu_unit "xlp_fp" "xlp_fpu")
+
+;; Floating Point Sqrt/Divide
+(define_cpu_unit "xlp_divsq" "xlp_fpu")
+
+;; FPU completion port.
+(define_cpu_unit "xlp_fp_wrb" "xlp_fpu")
+
+;; Define reservations for common combinations.
+
+;;
+;; The ordering of the instruction-execution-path/resource-usage
+;; descriptions (also known as reservation RTL) is roughly ordered
+;; based on the define attribute RTL for the "type" classification.
+;; When modifying, remember that the first test that matches is the
+;; reservation used!
+;;
+(define_insn_reservation "ir_xlp_unknown" 1
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "type" "unknown,multi"))
+ "xlp_ex0+xlp_ex1+xlp_ex2+xlp_ex3")
+
+(define_insn_reservation "ir_xlp_branch" 1
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "type" "branch,jump,call"))
+ "xlp_ex3")
+
+(define_insn_reservation "ir_xlp_prefetch" 1
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "type" "prefetch,prefetchx"))
+ "xlp_ex0|xlp_ex1")
+
+(define_insn_reservation "ir_xlp_load" 4
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "type" "load"))
+ "xlp_ex0|xlp_ex1")
+
+(define_insn_reservation "ir_xlp_fpload" 5
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "type" "fpload,fpidxload"))
+ "xlp_ex0|xlp_ex1")
+
+(define_insn_reservation "ir_xlp_alu" 1
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "type" "const,arith,shift,slt,clz,signext,logical,move,trap,nop"))
+ "xlp_ex0|xlp_ex1|(xlp_ex2,xlp_ex2_wrb)|xlp_ex3")
+
+(define_insn_reservation "ir_xlp_condmov" 1
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "type" "condmove")
+ (eq_attr "mode" "SI,DI"))
+ "xlp_ex2,xlp_ex2_wrb")
+
+(define_insn_reservation "ir_xlp_mul" 5
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "type" "imul,imadd"))
+ "xlp_ex2,nothing*4,xlp_ex2_wrb")
+
+(define_insn_reservation "ir_xlp_mul3" 3
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "type" "imul3"))
+ "xlp_ex2,nothing*2,xlp_ex2_wrb")
+
+(define_insn_reservation "ir_xlp_div" 24
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "mode" "SI")
+ (eq_attr "type" "idiv"))
+ "xlp_ex2+xlp_div,xlp_div*23,xlp_ex2_wrb")
+
+(define_insn_reservation "ir_xlp_ddiv" 48
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "mode" "DI")
+ (eq_attr "type" "idiv"))
+ "xlp_ex2+xlp_div,xlp_div*47,xlp_ex2_wrb")
+
+(define_insn_reservation "ir_xlp_store" 1
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "type" "store,fpstore,fpidxstore"))
+ "xlp_ex0|xlp_ex1")
+
+(define_insn_reservation "ir_xlp_fpmove" 2
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "type" "mfc"))
+ "xlp_ex3,xlp_fp,xlp_fp_wrb")
+
+(define_insn_reservation "ir_xlp_mfhi" 1
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "type" "mfhi"))
+ "xlp_ex2,xlp_ex2_wrb")
+
+(define_insn_reservation "ir_xlp_mflo" 1
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "type" "mflo"))
+ "xlp_ex2,xlp_ex2_wrb")
+
+(define_insn_reservation "ir_xlp_mthi" 1
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "type" "mthi"))
+ "xlp_ex2,xlp_ex2_wrb")
+
+(define_insn_reservation "ir_xlp_mtlo" 3
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "type" "mtlo"))
+ "xlp_ex2,nothing*2,xlp_ex2_wrb")
+
+(define_insn_reservation "ir_xlp_fp2" 2
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "type" "fmove,fneg,fabs,condmove"))
+ "xlp_fp,nothing,xlp_fp_wrb")
+
+(define_insn_reservation "ir_xlp_fp3" 3
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "type" "fcmp"))
+ "xlp_fp,nothing*2,xlp_fp_wrb")
+
+(define_insn_reservation "ir_xlp_fp4" 4
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "type" "fcvt"))
+ "xlp_fp,nothing*3,xlp_fp_wrb")
+
+(define_insn_reservation "ir_xlp_fp5" 5
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "mode" "SF")
+ (eq_attr "type" "fadd,fmul"))
+ "xlp_fp,nothing*4,xlp_fp_wrb")
+
+(define_insn_reservation "ir_xlp_fp6" 6
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "mode" "DF")
+ (eq_attr "type" "fadd,fmul"))
+ "xlp_fp,nothing*5,xlp_fp_wrb")
+
+(define_insn_reservation "ir_xlp_fp9" 9
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "mode" "SF")
+ (eq_attr "type" "fmadd"))
+ "xlp_fp,nothing*3,xlp_fp,nothing*3,xlp_fp_wrb")
+
+(define_insn_reservation "ir_xlp_fp11" 11
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "mode" "DF")
+ (eq_attr "type" "fmadd"))
+ "xlp_fp,nothing*4,xlp_fp,nothing*4,xlp_fp_wrb")
+
+(define_insn_reservation "ir_xlp_fpcomplex_s" 23
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "mode" "SF")
+ (eq_attr "type" "fdiv,frdiv,frdiv1,frdiv2,fsqrt,frsqrt,frsqrt1,frsqrt2"))
+ "xlp_fp+xlp_divsq,xlp_divsq*22,xlp_fp_wrb")
+
+(define_insn_reservation "ir_xlp_fpcomplex_d" 38
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "mode" "DF")
+ (eq_attr "type" "fdiv,frdiv,frdiv1,frdiv2,fsqrt,frsqrt,frsqrt1,frsqrt2"))
+ "xlp_fp+xlp_divsq,xlp_divsq*37,xlp_fp_wrb")
+
+(define_bypass 3 "ir_xlp_mul" "ir_xlp_mfhi")
+
+(define_insn_reservation "ir_xlp_atomic" 15
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "type" "atomic"))
+ "xlp_ex0|xlp_ex1")
+
+;; Sync loop consists of (in order)
+;; (1) optional sync,
+;; (2) LL instruction,
+;; (3) branch and 1-2 ALU instructions,
+;; (4) SC instruction,
+;; (5) optional sync,
+;; (6) branch and ALU instruction.
+;; The net result of this reservation is a big delay with flush of
+;; ALU pipeline and outgoing reservations discouraging use of EX3.
+(define_insn_reservation "ir_xlp_sync_loop" 40
+ (and (eq_attr "cpu" "xlp")
+ (eq_attr "type" "syncloop"))
+ "(xlp_ex0+xlp_ex1+xlp_ex2+xlp_ex3)*39,xlp_ex3+(xlp_ex0|xlp_ex1|(xlp_ex2,xlp_ex2_wrb))")
diff --git a/gcc/config/mips/xlr.md b/gcc/config/mips/xlr.md
index 69913b7b2f..a8d1a12c1b 100644
--- a/gcc/config/mips/xlr.md
+++ b/gcc/config/mips/xlr.md
@@ -1,5 +1,5 @@
;; DFA-based pipeline description for the XLR.
-;; Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2014 Free Software Foundation, Inc.
;;
;; xlr.md Machine Description for the RMI XLR Microprocessor
;; This file is part of GCC.
@@ -28,10 +28,15 @@
(eq_attr "type" "slt"))
"xlr_main_pipe")
+(define_insn_reservation "ir_xlr_alu_clz" 2
+ (and (eq_attr "cpu" "xlr")
+ (eq_attr "type" "clz"))
+ "xlr_main_pipe")
+
;; Integer arithmetic instructions.
(define_insn_reservation "ir_xlr_alu" 1
(and (eq_attr "cpu" "xlr")
- (eq_attr "type" "move,arith,shift,clz,logical,signext,const,unknown,multi,nop,trap"))
+ (eq_attr "type" "move,arith,shift,logical,signext,const,unknown,multi,nop,trap,atomic,syncloop"))
"xlr_main_pipe")
;; Integer arithmetic instructions.
@@ -85,5 +90,5 @@
(define_insn_reservation "xlr_hilo" 2
(and (eq_attr "cpu" "xlr")
- (eq_attr "type" "mfhilo,mthilo"))
+ (eq_attr "type" "mfhi,mflo,mthi,mtlo"))
"xlr_imuldiv_nopipe")