aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Sandiford <richard@codesourcery.com>2007-09-13 12:44:10 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2007-09-13 12:44:10 +0000
commit9a6dfb473994b6bfb33bfb7d0c8c3a6a5775ca34 (patch)
tree7ea310d5401715a64606a38ee1ab5e463b04c0cd /gcc
parent0ad7e054218ed4a8df8843a96bf59e2c8c4b4f9b (diff)
downloadgcc-9a6dfb473994b6bfb33bfb7d0c8c3a6a5775ca34.zip
gcc-9a6dfb473994b6bfb33bfb7d0c8c3a6a5775ca34.tar.gz
gcc-9a6dfb473994b6bfb33bfb7d0c8c3a6a5775ca34.tar.bz2
mips.h (SYMBOL_FLAG_MIPS16_FUNC): Delete.
gcc/ 2007-09-13 Richard Sandiford <richard@codesourcery.com> Sandra Loosemore <sandra@codesourcery.com> * config/mips/mips.h (SYMBOL_FLAG_MIPS16_FUNC): Delete. (SYMBOL_REF_MIPS16_FUNC_P): Delete. * config/mips/mips.c (mips_attribute_table): Turn mips16 and nomips16 into decl attributes. (TARGET_INSERT_ATTRIBUTES): Override. (TARGET_MERGE_DECL_ATTRIBUTES): Likewise. (TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P): Always return true. (mips_mips16_type_p, mips_nomips16_type_p): Delete in favor of... (mips_mips16_decl_p, mips_nomips16_decl_p): ...these new functions. (mips_comp_type_attributes): Remove mips16 and nomips16 handling. (mips_use_mips16_mode_p): Reimplement as a function that takes a decl and considers only decl attributes. If the decl is nested function, use its parent attributes. (mips_function_ok_for_sibcall): Use mips_use_mips16_mode_p instead of SYMBOL_REF_MIPS16_FUNC_P. (mips_set_mips16_mode): Move call to sorry here from old mips_use_mips16_mode_p. (mflip_mips16_entry): New structure. (mflip_mips16_htab): New variable. (mflip_mips16_htab_hash, mflip_mips16_htab_eq): New functions. (mflip_mips16_use_mips16_p, mips_insert_attributes): Likewise. (mips_merge_decl_attributes): New function. (mips_set_current_function): Reinstate call to mips_set_mips16_mode. Use mips_use_mips16_mode_p. (mips_output_mi_thunk): Use mips_use_mips16_mode_p instead of SYMBOL_REF_MIPS16_FUNC_P. (mips_encode_section_info): Don't set SYMBOL_FLAG_MIPS16_FUNC. gcc/testsuite/ * gcc.dg/gcc-have-sync-compare-and-swap.c: Skip for -mflip-mips16. * gcc.target/mips/mips16-attributes-2.c: New test. * gcc.target/mips/mips16-attributes-3.c: Likewise. * gcc.target/mips/args-3.c: Skip for -mflip-mips16. Do not use the hard-float asm when __mips16 is defined. * gcc.target/mips/atomic-memory-1.c (main): Add a nomips16 attribute. * gcc.target/mips/atomic-memory-2.c (main): Likewise. * gcc.target/mips/fpcmp-1.c (f1, f2): Likewise. * gcc.target/mips/fpcmp-2.c (f1, f2): Likewise. * gcc.target/mips/neg-abs-1.c (f1, f2, d1, f2): Likewise. * gcc.target/mips/pr26765.c (foo): Likewise. * gcc.target/mips/gcc-have-sync-compare-and-swap-1.c: Run for all targets, use dg-mips-options instead of dg-options, and use -mgp32 to force 32-bit mode. * gcc.target/mips/gcc-have-sync-compare-and-swap-2.c: Likewise -mgp64 and 64-bit mode. * gcc.target/mips/mips.exp (is_gp32_flag): Return true for -mips32*. Co-Authored-By: Sandra Loosemore <sandra@codesourcery.com> From-SVN: r128460
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog31
-rw-r--r--gcc/config/mips/mips.c226
-rw-r--r--gcc/config/mips/mips.h5
-rw-r--r--gcc/testsuite/ChangeLog20
-rw-r--r--gcc/testsuite/gcc.dg/gcc-have-sync-compare-and-swap.c4
-rw-r--r--gcc/testsuite/gcc.target/mips/args-3.c3
-rw-r--r--gcc/testsuite/gcc.target/mips/atomic-memory-1.c4
-rw-r--r--gcc/testsuite/gcc.target/mips/atomic-memory-2.c4
-rw-r--r--gcc/testsuite/gcc.target/mips/fpcmp-1.c6
-rw-r--r--gcc/testsuite/gcc.target/mips/fpcmp-2.c6
-rw-r--r--gcc/testsuite/gcc.target/mips/gcc-have-sync-compare-and-swap-1.c2
-rw-r--r--gcc/testsuite/gcc.target/mips/gcc-have-sync-compare-and-swap-2.c4
-rw-r--r--gcc/testsuite/gcc.target/mips/mips.exp1
-rw-r--r--gcc/testsuite/gcc.target/mips/mips16-attributes-2.c15
-rw-r--r--gcc/testsuite/gcc.target/mips/mips16-attributes-3.c6
-rw-r--r--gcc/testsuite/gcc.target/mips/neg-abs-1.c10
-rw-r--r--gcc/testsuite/gcc.target/mips/pr26765.c4
17 files changed, 271 insertions, 80 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c9facbd..cad07c6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,4 +1,35 @@
2007-09-13 Richard Sandiford <richard@codesourcery.com>
+ Sandra Loosemore <sandra@codesourcery.com>
+
+ * config/mips/mips.h (SYMBOL_FLAG_MIPS16_FUNC): Delete.
+ (SYMBOL_REF_MIPS16_FUNC_P): Delete.
+ * config/mips/mips.c (mips_attribute_table): Turn mips16 and
+ nomips16 into decl attributes.
+ (TARGET_INSERT_ATTRIBUTES): Override.
+ (TARGET_MERGE_DECL_ATTRIBUTES): Likewise.
+ (TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P): Always return true.
+ (mips_mips16_type_p, mips_nomips16_type_p): Delete in favor of...
+ (mips_mips16_decl_p, mips_nomips16_decl_p): ...these new functions.
+ (mips_comp_type_attributes): Remove mips16 and nomips16 handling.
+ (mips_use_mips16_mode_p): Reimplement as a function that takes
+ a decl and considers only decl attributes. If the decl is nested
+ function, use its parent attributes.
+ (mips_function_ok_for_sibcall): Use mips_use_mips16_mode_p
+ instead of SYMBOL_REF_MIPS16_FUNC_P.
+ (mips_set_mips16_mode): Move call to sorry here from old
+ mips_use_mips16_mode_p.
+ (mflip_mips16_entry): New structure.
+ (mflip_mips16_htab): New variable.
+ (mflip_mips16_htab_hash, mflip_mips16_htab_eq): New functions.
+ (mflip_mips16_use_mips16_p, mips_insert_attributes): Likewise.
+ (mips_merge_decl_attributes): New function.
+ (mips_set_current_function): Reinstate call to mips_set_mips16_mode.
+ Use mips_use_mips16_mode_p.
+ (mips_output_mi_thunk): Use mips_use_mips16_mode_p instead of
+ SYMBOL_REF_MIPS16_FUNC_P.
+ (mips_encode_section_info): Don't set SYMBOL_FLAG_MIPS16_FUNC.
+
+2007-09-13 Richard Sandiford <richard@codesourcery.com>
* c-parser.c (c_parser_struct_declaration): Check for a null return.
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 1a2cc06..410f7d7 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -426,6 +426,8 @@ static void mips_encode_section_info (tree, rtx, int);
static void mips_extra_live_on_entry (bitmap);
static int mips_comp_type_attributes (const_tree, const_tree);
static void mips_set_mips16_mode (int);
+static void mips_insert_attributes (tree, tree *);
+static tree mips_merge_decl_attributes (tree, tree);
static void mips_set_current_function (tree);
static int mips_mode_rep_extended (enum machine_mode, enum machine_mode);
static bool mips_offset_within_alignment_p (rtx, HOST_WIDE_INT);
@@ -734,9 +736,13 @@ const struct attribute_spec mips_attribute_table[] =
{ "long_call", 0, 0, false, true, true, NULL },
{ "far", 0, 0, false, true, true, NULL },
{ "near", 0, 0, false, true, true, NULL },
- /* Switch MIPS16 ASE on and off per-function. */
- { "mips16", 0, 0, false, true, true, NULL },
- { "nomips16", 0, 0, false, true, true, NULL },
+ /* Switch MIPS16 ASE on and off per-function. We would really like
+ to make these type attributes, but GCC doesn't provide the hooks
+ we need to support the right conversion rules. As declaration
+ attributes, they affect code generation but don't carry other
+ semantics. */
+ { "mips16", 0, 0, true, false, false, NULL },
+ { "nomips16", 0, 0, true, false, false, NULL },
{ NULL, 0, 0, false, false, false, NULL }
};
@@ -1268,6 +1274,10 @@ static const unsigned char mips16e_save_restore_regs[] = {
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
#define TARGET_FUNCTION_OK_FOR_SIBCALL mips_function_ok_for_sibcall
+#undef TARGET_INSERT_ATTRIBUTES
+#define TARGET_INSERT_ATTRIBUTES mips_insert_attributes
+#undef TARGET_MERGE_DECL_ATTRIBUTES
+#define TARGET_MERGE_DECL_ATTRIBUTES mips_merge_decl_attributes
#undef TARGET_SET_CURRENT_FUNCTION
#define TARGET_SET_CURRENT_FUNCTION mips_set_current_function
@@ -1352,6 +1362,10 @@ static const unsigned char mips16e_save_restore_regs[] = {
#undef TARGET_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE mips_attribute_table
+/* All our function attributes are related to how out-of-line copies should
+ be compiled or called. They don't in themselves prevent inlining. */
+#undef TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P
+#define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P hook_bool_const_tree_true
#undef TARGET_EXTRA_LIVE_ON_ENTRY
#define TARGET_EXTRA_LIVE_ON_ENTRY mips_extra_live_on_entry
@@ -1395,15 +1409,15 @@ mips_far_type_p (const_tree type)
/* Similar predicates for "mips16"/"nomips16" attributes. */
static bool
-mips_mips16_type_p (const_tree type)
+mips_mips16_decl_p (const_tree decl)
{
- return lookup_attribute ("mips16", TYPE_ATTRIBUTES (type)) != NULL;
+ return lookup_attribute ("mips16", DECL_ATTRIBUTES (decl)) != NULL;
}
static bool
-mips_nomips16_type_p (const_tree type)
+mips_nomips16_decl_p (const_tree decl)
{
- return lookup_attribute ("nomips16", TYPE_ATTRIBUTES (type)) != NULL;
+ return lookup_attribute ("nomips16", DECL_ATTRIBUTES (decl)) != NULL;
}
/* Return 0 if the attributes for two types are incompatible, 1 if they
@@ -1423,11 +1437,6 @@ mips_comp_type_attributes (const_tree type1, const_tree type2)
if (mips_near_type_p (type1) && mips_far_type_p (type2))
return 0;
- /* Mips16/nomips16 attributes must match exactly. */
- if (mips_nomips16_type_p (type1) != mips_nomips16_type_p (type2)
- || mips_mips16_type_p (type1) != mips_mips16_type_p (type2))
- return 0;
-
return 1;
}
@@ -4120,6 +4129,27 @@ mips_gen_conditional_trap (rtx *operands)
operands[1]));
}
+/* Return true if function DECL is a MIPS16 function. Return the ambient
+ setting if DECL is null. */
+
+static bool
+mips_use_mips16_mode_p (tree decl)
+{
+ if (decl)
+ {
+ /* Nested functions must use the same frame pointer as their
+ parent and must therefore use the same ISA mode. */
+ 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;
+ }
+ return mips_base_mips16;
+}
+
/* Return true if calls to X can use R_MIPS_CALL* relocations. */
static bool
@@ -4223,7 +4253,7 @@ mips_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
/* 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. */
- if (decl && SYMBOL_REF_MIPS16_FUNC_P (XEXP (DECL_RTL (decl), 0)))
+ if (mips_use_mips16_mode_p (decl))
return false;
/* Otherwise OK. */
@@ -5666,6 +5696,9 @@ mips_set_mips16_mode (int mips16_p)
of lw and sw instead. */
targetm.min_anchor_offset = 0;
targetm.max_anchor_offset = 127;
+
+ if (flag_pic || TARGET_ABICALLS)
+ sorry ("MIPS16 PIC");
}
else
{
@@ -5703,12 +5736,130 @@ mips_set_mips16_mode (int mips16_p)
was_mips16_p = TARGET_MIPS16;
}
+/* Use a hash table to keep track of implicit mips16/nomips16 attributes
+ for -mflip_mips16. It maps decl names onto a boolean mode setting. */
+
+struct mflip_mips16_entry GTY (()) {
+ const char *name;
+ bool mips16_p;
+};
+static GTY ((param_is (struct mflip_mips16_entry))) htab_t mflip_mips16_htab;
+
+/* Hash table callbacks for mflip_mips16_htab. */
+
+static hashval_t
+mflip_mips16_htab_hash (const void *entry)
+{
+ return htab_hash_string (((const struct mflip_mips16_entry *) entry)->name);
+}
+
+static int
+mflip_mips16_htab_eq (const void *entry, const void *name)
+{
+ return strcmp (((const struct mflip_mips16_entry *) entry)->name,
+ (const char *) name) == 0;
+}
+
+/* DECL is a function that needs a default "mips16" or "nomips16" attribute
+ for -mflip-mips16. Return true if it should use "mips16" and false if
+ it should use "nomips16". */
+
+static bool
+mflip_mips16_use_mips16_p (tree decl)
+{
+ struct mflip_mips16_entry *entry;
+ const char *name;
+ hashval_t hash;
+ void **slot;
+
+ /* Use the opposite of the command-line setting for anonymous decls. */
+ if (!DECL_NAME (decl))
+ return !mips_base_mips16;
+
+ if (!mflip_mips16_htab)
+ mflip_mips16_htab = htab_create_ggc (37, mflip_mips16_htab_hash,
+ mflip_mips16_htab_eq, NULL);
+
+ name = IDENTIFIER_POINTER (DECL_NAME (decl));
+ hash = htab_hash_string (name);
+ slot = htab_find_slot_with_hash (mflip_mips16_htab, name, hash, INSERT);
+ entry = (struct mflip_mips16_entry *) *slot;
+ if (!entry)
+ {
+ mips16_flipper = !mips16_flipper;
+ entry = GGC_NEW (struct mflip_mips16_entry);
+ entry->name = name;
+ entry->mips16_p = mips16_flipper ? !mips_base_mips16 : mips_base_mips16;
+ *slot = entry;
+ }
+ return entry->mips16_p;
+}
+
+/* Implement TARGET_INSERT_ATTRIBUTES. */
+
+static void
+mips_insert_attributes (tree decl, tree *attributes)
+{
+ const char *name;
+ bool mips16_p, nomips16_p;
+
+ /* Check for "mips16" and "nomips16" attributes. */
+ mips16_p = lookup_attribute ("mips16", *attributes) != NULL;
+ nomips16_p = lookup_attribute ("nomips16", *attributes) != NULL;
+ 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");
+ }
+ 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 ("%qs cannot have both %<mips16%> and "
+ "%<nomips16%> attributes",
+ IDENTIFIER_POINTER (DECL_NAME (decl)));
+ }
+ else if (TARGET_FLIP_MIPS16 && !DECL_ARTIFICIAL (decl))
+ {
+ /* 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);
+ }
+ }
+}
+
+/* Implement TARGET_MERGE_DECL_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))
+ error ("%qs redeclared with conflicting %qs attributes",
+ IDENTIFIER_POINTER (DECL_NAME (newdecl)), "mips16");
+ if (mips_nomips16_decl_p (olddecl) != mips_nomips16_decl_p (newdecl))
+ error ("%qs redeclared with conflicting %qs attributes",
+ IDENTIFIER_POINTER (DECL_NAME (newdecl)), "nomips16");
+
+ return merge_attributes (DECL_ATTRIBUTES (olddecl),
+ DECL_ATTRIBUTES (newdecl));
+}
+
/* Implement TARGET_SET_CURRENT_FUNCTION. Decide whether the current
function should use the MIPS16 ISA and switch modes accordingly. */
static void
-mips_set_current_function (tree fndecl ATTRIBUTE_UNUSED)
+mips_set_current_function (tree fndecl)
{
+ mips_set_mips16_mode (mips_use_mips16_mode_p (fndecl));
}
/* Implement TARGET_HANDLE_OPTION. */
@@ -8783,7 +8934,7 @@ mips_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
allowed, otherwise load the address into a register first. */
fnaddr = XEXP (DECL_RTL (function), 0);
if (TARGET_MIPS16 || TARGET_USE_GOT || SYMBOL_REF_LONG_CALL_P (fnaddr)
- || SYMBOL_REF_MIPS16_FUNC_P (fnaddr))
+ || mips_use_mips16_mode_p (function))
{
/* This is messy. gas treats "la $25,foo" as part of a call
sequence and may allow a global "foo" to be lazily bound.
@@ -12724,43 +12875,6 @@ mips_expand_builtin_bposge (enum mips_builtin_type builtin_type, rtx target)
const1_rtx, const0_rtx);
}
-/* Return true if we should force MIPS16 mode for the function named by
- the SYMBOL_REF SYMBOL, which belongs to DECL and has type TYPE.
- FIRST is true if this is the first time handling this decl. */
-
-static bool
-mips_use_mips16_mode_p (rtx symbol, tree decl, int first, tree type)
-{
- tree parent;
-
- /* Explicit function attributes take precedence. */
- if (mips_mips16_type_p (type))
- return true;
- if (mips_nomips16_type_p (type))
- return false;
-
- /* A nested function should inherit the MIPS16 setting from its parent. */
- parent = decl_function_context (decl);
- if (parent)
- return SYMBOL_REF_MIPS16_FUNC_P (XEXP (DECL_RTL (parent), 0));
-
- /* Handle -mflip-mips16. */
- if (TARGET_FLIP_MIPS16
- && !DECL_BUILT_IN (decl)
- && !DECL_ARTIFICIAL (decl))
- {
- if (!first)
- /* Use the setting we picked first time around. */
- return SYMBOL_REF_MIPS16_FUNC_P (symbol);
-
- mips16_flipper = !mips16_flipper;
- if (mips16_flipper)
- return !mips_base_mips16;
- }
-
- return mips_base_mips16;
-}
-
/* Set SYMBOL_REF_FLAGS for the SYMBOL_REF inside RTL, which belongs to DECL.
FIRST is true if this is the first time handling this decl. */
@@ -12777,14 +12891,6 @@ mips_encode_section_info (tree decl, rtx rtl, int first)
if ((TARGET_LONG_CALLS && !mips_near_type_p (type))
|| mips_far_type_p (type))
SYMBOL_REF_FLAGS (symbol) |= SYMBOL_FLAG_LONG_CALL;
-
- if (mips_use_mips16_mode_p (symbol, decl, first, type))
- {
- if (flag_pic || TARGET_ABICALLS)
- sorry ("MIPS16 PIC");
- else
- SYMBOL_REF_FLAGS (symbol) |= SYMBOL_FLAG_MIPS16_FUNC;
- }
}
}
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 7aa6aa8..c9d2742 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -2338,11 +2338,6 @@ typedef struct mips_args {
#define SYMBOL_REF_LONG_CALL_P(X) \
((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_LONG_CALL) != 0)
-/* Flag to mark a function decl symbol a "mips16" function. */
-#define SYMBOL_FLAG_MIPS16_FUNC (SYMBOL_FLAG_MACH_DEP << 1)
-#define SYMBOL_REF_MIPS16_FUNC_P(RTX) \
- ((SYMBOL_REF_FLAGS (RTX) & SYMBOL_FLAG_MIPS16_FUNC) != 0)
-
/* 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,
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 35894f0..34af18c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,23 @@
+2007-09-13 Richard Sandiford <richard@codesourcery.com>
+
+ * gcc.dg/gcc-have-sync-compare-and-swap.c: Skip for -mflip-mips16.
+ * gcc.target/mips/mips16-attributes-2.c: New test.
+ * gcc.target/mips/mips16-attributes-3.c: Likewise.
+ * gcc.target/mips/args-3.c: Skip for -mflip-mips16. Do not use the
+ hard-float asm when __mips16 is defined.
+ * gcc.target/mips/atomic-memory-1.c (main): Add a nomips16 attribute.
+ * gcc.target/mips/atomic-memory-2.c (main): Likewise.
+ * gcc.target/mips/fpcmp-1.c (f1, f2): Likewise.
+ * gcc.target/mips/fpcmp-2.c (f1, f2): Likewise.
+ * gcc.target/mips/neg-abs-1.c (f1, f2, d1, f2): Likewise.
+ * gcc.target/mips/pr26765.c (foo): Likewise.
+ * gcc.target/mips/gcc-have-sync-compare-and-swap-1.c: Run for all
+ targets, use dg-mips-options instead of dg-options, and use -mgp32
+ to force 32-bit mode.
+ * gcc.target/mips/gcc-have-sync-compare-and-swap-2.c: Likewise -mgp64
+ and 64-bit mode.
+ * gcc.target/mips/mips.exp (is_gp32_flag): Return true for -mips32*.
+
2007-09-12 Dwarakanath Rajagopal <dwarak.rajagopal@amd.com>
Michael Meissner <michael.meissner@amd.com>
diff --git a/gcc/testsuite/gcc.dg/gcc-have-sync-compare-and-swap.c b/gcc/testsuite/gcc.dg/gcc-have-sync-compare-and-swap.c
index 89527f6..faed818 100644
--- a/gcc/testsuite/gcc.dg/gcc-have-sync-compare-and-swap.c
+++ b/gcc/testsuite/gcc.dg/gcc-have-sync-compare-and-swap.c
@@ -1,4 +1,8 @@
/* { dg-do link } */
+/* MIPS only supports these built-in functions for non-MIPS16 mode, and
+ -mflip-mips16 will change the mode of some functions to be different
+ from the command-line setting. */
+/* { dg-skip-if "" { mips*-*-* } { "-mflip-mips16" } { "" } } */
void f1()
{
diff --git a/gcc/testsuite/gcc.target/mips/args-3.c b/gcc/testsuite/gcc.target/mips/args-3.c
index e91816f..6a79ce6 100644
--- a/gcc/testsuite/gcc.target/mips/args-3.c
+++ b/gcc/testsuite/gcc.target/mips/args-3.c
@@ -1,6 +1,7 @@
/* __mips, and related defines, guarantee that certain assembly
instructions can be used. Check a few examples. */
/* { dg-do run } */
+/* { dg-skip-if "" { *-*-* } { "-mflip-mips16" } { "" } } */
extern void abort (void);
extern void exit (int);
@@ -11,7 +12,7 @@ int foo (float inf, int64 in64, int32 in32)
int64 res64;
int32 res32;
-#if __mips != 1 && defined (__mips_hard_float)
+#if __mips != 1 && defined (__mips_hard_float) && !defined (__mips16)
__asm__ ("trunc.w.s %0, %1" : "=f" (res32) : "f" (inf));
if (res32 != 11)
abort ();
diff --git a/gcc/testsuite/gcc.target/mips/atomic-memory-1.c b/gcc/testsuite/gcc.target/mips/atomic-memory-1.c
index 1664daa..b44bd46 100644
--- a/gcc/testsuite/gcc.target/mips/atomic-memory-1.c
+++ b/gcc/testsuite/gcc.target/mips/atomic-memory-1.c
@@ -2,7 +2,9 @@
extern void abort (void);
extern void exit (int);
-int main ()
+#define NOMIPS16 __attribute__ ((nomips16))
+
+NOMIPS16 int main ()
{
#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
unsigned v = 0;
diff --git a/gcc/testsuite/gcc.target/mips/atomic-memory-2.c b/gcc/testsuite/gcc.target/mips/atomic-memory-2.c
index b0492be..18ec64d 100644
--- a/gcc/testsuite/gcc.target/mips/atomic-memory-2.c
+++ b/gcc/testsuite/gcc.target/mips/atomic-memory-2.c
@@ -3,7 +3,9 @@
/* { dg-final { scan-assembler "addiu" } } */
/* { dg-final { scan-assembler-not "subu" } } */
-unsigned long
+#define NOMIPS16 __attribute__ ((nomips16))
+
+NOMIPS16 unsigned long
f(unsigned long *p)
{
return __sync_fetch_and_sub (p, 5);
diff --git a/gcc/testsuite/gcc.target/mips/fpcmp-1.c b/gcc/testsuite/gcc.target/mips/fpcmp-1.c
index 144a6d1..e3206a5 100644
--- a/gcc/testsuite/gcc.target/mips/fpcmp-1.c
+++ b/gcc/testsuite/gcc.target/mips/fpcmp-1.c
@@ -1,6 +1,8 @@
/* We used to use c.lt.fmt instead of c.ule.fmt here. */
/* { dg-mips-options "-mhard-float -O2" } */
-int f1 (float x, float y) { return __builtin_isless (x, y); }
-int f2 (double x, double y) { return __builtin_isless (x, y); }
+#define NOMIPS16 __attribute__ ((nomips16))
+
+NOMIPS16 int f1 (float x, float y) { return __builtin_isless (x, y); }
+NOMIPS16 int f2 (double x, double y) { return __builtin_isless (x, y); }
/* { dg-final { scan-assembler "c\\.ule\\.s" } } */
/* { dg-final { scan-assembler "c\\.ule\\.d" } } */
diff --git a/gcc/testsuite/gcc.target/mips/fpcmp-2.c b/gcc/testsuite/gcc.target/mips/fpcmp-2.c
index 4a9bbaa..9f89417 100644
--- a/gcc/testsuite/gcc.target/mips/fpcmp-2.c
+++ b/gcc/testsuite/gcc.target/mips/fpcmp-2.c
@@ -1,6 +1,8 @@
/* We used to use c.le.fmt instead of c.ult.fmt here. */
/* { dg-mips-options "-mhard-float -O2" } */
-int f1 (float x, float y) { return __builtin_islessequal (x, y); }
-int f2 (double x, double y) { return __builtin_islessequal (x, y); }
+#define NOMIPS16 __attribute__ ((nomips16))
+
+NOMIPS16 int f1 (float x, float y) { return __builtin_islessequal (x, y); }
+NOMIPS16 int f2 (double x, double y) { return __builtin_islessequal (x, y); }
/* { dg-final { scan-assembler "c\\.ult\\.s" } } */
/* { dg-final { scan-assembler "c\\.ult\\.d" } } */
diff --git a/gcc/testsuite/gcc.target/mips/gcc-have-sync-compare-and-swap-1.c b/gcc/testsuite/gcc.target/mips/gcc-have-sync-compare-and-swap-1.c
index 315aa46..b1c524b 100644
--- a/gcc/testsuite/gcc.target/mips/gcc-have-sync-compare-and-swap-1.c
+++ b/gcc/testsuite/gcc.target/mips/gcc-have-sync-compare-and-swap-1.c
@@ -1,5 +1,5 @@
/* { dg-do preprocess } */
-/* { dg-options "-mips32 -mabi=32" } */
+/* { dg-mips-options "-mips2" } */
#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
#error nonono
diff --git a/gcc/testsuite/gcc.target/mips/gcc-have-sync-compare-and-swap-2.c b/gcc/testsuite/gcc.target/mips/gcc-have-sync-compare-and-swap-2.c
index f07ebe7..25cd673 100644
--- a/gcc/testsuite/gcc.target/mips/gcc-have-sync-compare-and-swap-2.c
+++ b/gcc/testsuite/gcc.target/mips/gcc-have-sync-compare-and-swap-2.c
@@ -1,5 +1,5 @@
-/* { dg-do preprocess { target { mips64*-*-* } } } */
-/* { dg-options "-mips64 -mabi=64" } */
+/* { dg-do preprocess } */
+/* { dg-mips-options "-mgp64" } */
#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
#error nonono
diff --git a/gcc/testsuite/gcc.target/mips/mips.exp b/gcc/testsuite/gcc.target/mips/mips.exp
index c88edc0..3e10eba 100644
--- a/gcc/testsuite/gcc.target/mips/mips.exp
+++ b/gcc/testsuite/gcc.target/mips/mips.exp
@@ -103,6 +103,7 @@ proc is_gp32_flag {flag} {
switch -glob -- $flag {
-msmartmips -
-mips[12] -
+ -mips32* -
-march=mips32* -
-mgp32 { return 1 }
default { return 0 }
diff --git a/gcc/testsuite/gcc.target/mips/mips16-attributes-2.c b/gcc/testsuite/gcc.target/mips/mips16-attributes-2.c
new file mode 100644
index 0000000..eeadf81
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mips16-attributes-2.c
@@ -0,0 +1,15 @@
+/* { dg-skip-if "" { *-*-* } { "-mflip-mips16" } { "" } } */
+
+void f1 (void);
+void __attribute__((mips16)) f1 (void) {} /* { dg-error "conflicting" } */
+
+void __attribute__((mips16)) f2 (void);
+void f2 (void) {} /* { dg-error "conflicting" } */
+
+void f3 (void);
+void __attribute__((nomips16)) f3 (void) {} /* { dg-error "conflicting" } */
+
+void __attribute__((nomips16)) f4 (void);
+void f4 (void) {} /* { dg-error "conflicting" } */
+
+void __attribute__((mips16, nomips16)) f5 (void) {} /* { dg-error "cannot have both" } */
diff --git a/gcc/testsuite/gcc.target/mips/mips16-attributes-3.c b/gcc/testsuite/gcc.target/mips/mips16-attributes-3.c
new file mode 100644
index 0000000..3b4e107
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mips16-attributes-3.c
@@ -0,0 +1,6 @@
+/* We should be able to assign mips16 and nomips16 functions to a pointer. */
+void __attribute__((mips16)) f1 (void);
+void (*ptr1) (void) = f1;
+
+void __attribute__((nomips16)) f2 (void);
+void (*ptr2) (void) = f2;
diff --git a/gcc/testsuite/gcc.target/mips/neg-abs-1.c b/gcc/testsuite/gcc.target/mips/neg-abs-1.c
index 038b8983..6c1d1ba 100644
--- a/gcc/testsuite/gcc.target/mips/neg-abs-1.c
+++ b/gcc/testsuite/gcc.target/mips/neg-abs-1.c
@@ -7,7 +7,9 @@
/* { dg-final { scan-assembler "abs.s" } } */
/* { dg-final { scan-assembler "abs.d" } } */
-float f1 (float f) { return -f; }
-float f2 (float f) { return __builtin_fabsf (f); }
-double d1 (double d) { return -d; }
-double d2 (double d) { return __builtin_fabs (d); }
+#define NOMIPS16 __attribute__ ((nomips16))
+
+NOMIPS16 float f1 (float f) { return -f; }
+NOMIPS16 float f2 (float f) { return __builtin_fabsf (f); }
+NOMIPS16 double d1 (double d) { return -d; }
+NOMIPS16 double d2 (double d) { return __builtin_fabs (d); }
diff --git a/gcc/testsuite/gcc.target/mips/pr26765.c b/gcc/testsuite/gcc.target/mips/pr26765.c
index 6c4fbc4..cd1d9fe 100644
--- a/gcc/testsuite/gcc.target/mips/pr26765.c
+++ b/gcc/testsuite/gcc.target/mips/pr26765.c
@@ -6,7 +6,9 @@
__thread int *a = 0;
-void foo (void)
+#define NOMIPS16 __attribute__ ((nomips16))
+
+NOMIPS16 void foo (void)
{
extern int *b;
b = (int *) ((*a));