+
+unsigned int
+mips_hard_regno_nregs (regno, mode)
+ int regno;
+ enum machine_mode mode;
+{
+ if (! FP_REG_P (regno))
+ return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
+ else
+ return ((GET_MODE_SIZE (mode) + UNITS_PER_FPREG - 1) / UNITS_PER_FPREG);
+}
+
+int
+mips_return_in_memory (type)
+ tree type;
+{
+ /* Under the old (i.e., 32 and O64 ABIs) all BLKmode objects are
+ returned in memory. Under the new (N32 and 64-bit MIPS ABIs) small
+ structures are returned in a register. Objects with varying size
+ must still be returned in memory, of course. */
+
+ if (mips_abi == ABI_32 || mips_abi == ABI_O64)
+ return (TYPE_MODE (type) == BLKmode);
+ else
+ return ((int_size_in_bytes (type) > (2 * UNITS_PER_WORD))
+ || (int_size_in_bytes (type) == -1));
+}
+
+static int
+mips_issue_rate ()
+{
+ int rate;
+
+ switch (mips_tune)
+ {
+ case PROCESSOR_R3000:
+ rate = 1;
+ break;
+
+ default:
+ rate = 1;
+ break;
+ }
+
+ return rate;
+}
+
+\f
+#ifdef TARGET_IRIX6
+/* Output assembly to switch to section NAME with attribute FLAGS. */
+
+static void
+iris6_asm_named_section_1 (name, flags, align)
+ const char *name;
+ unsigned int flags;
+ unsigned int align;
+{
+ unsigned int sh_type, sh_flags, sh_entsize;
+
+ sh_flags = 0;
+ if (!(flags & SECTION_DEBUG))
+ sh_flags |= 2; /* SHF_ALLOC */
+ if (flags & SECTION_WRITE)
+ sh_flags |= 1; /* SHF_WRITE */
+ if (flags & SECTION_CODE)
+ sh_flags |= 4; /* SHF_EXECINSTR */
+ if (flags & SECTION_SMALL)
+ sh_flags |= 0x10000000; /* SHF_MIPS_GPREL */
+ if (strcmp (name, ".debug_frame") == 0)
+ sh_flags |= 0x08000000; /* SHF_MIPS_NOSTRIP */
+ if (flags & SECTION_DEBUG)
+ sh_type = 0x7000001e; /* SHT_MIPS_DWARF */
+ else if (flags & SECTION_BSS)
+ sh_type = 8; /* SHT_NOBITS */
+ else
+ sh_type = 1; /* SHT_PROGBITS */
+
+ if (flags & SECTION_CODE)
+ sh_entsize = 4;
+ else
+ sh_entsize = 0;
+
+ fprintf (asm_out_file, "\t.section %s,%#x,%#x,%u,%u\n",
+ name, sh_type, sh_flags, sh_entsize, align);
+}
+
+static void
+iris6_asm_named_section (name, flags)
+ const char *name;
+ unsigned int flags;
+{
+ if (TARGET_FILE_SWITCHING && (flags & SECTION_CODE))
+ asm_out_file = asm_out_text_file;
+ iris6_asm_named_section_1 (name, flags, 0);
+}
+
+/* In addition to emitting a .align directive, record the maximum
+ alignment requested for the current section. */
+
+struct iris_section_align_entry
+{
+ const char *name;
+ unsigned int log;
+ unsigned int flags;
+};
+
+static htab_t iris_section_align_htab;
+static FILE *iris_orig_asm_out_file;
+
+static int
+iris_section_align_entry_eq (p1, p2)
+ const PTR p1;
+ const PTR p2;
+{
+ const struct iris_section_align_entry *old = p1;
+ const char *new = p2;
+
+ return strcmp (old->name, new) == 0;
+}
+
+static hashval_t
+iris_section_align_entry_hash (p)
+ const PTR p;
+{
+ const struct iris_section_align_entry *old = p;
+ return htab_hash_string (old->name);
+}
+
+void
+iris6_asm_output_align (file, log)
+ FILE *file;
+ unsigned int log;
+{
+ const char *section = current_section_name ();
+ struct iris_section_align_entry **slot, *entry;
+
+ if (! section)
+ abort ();
+
+ slot = (struct iris_section_align_entry **)
+ htab_find_slot_with_hash (iris_section_align_htab, section,
+ htab_hash_string (section), INSERT);
+ entry = *slot;
+ if (! entry)
+ {
+ entry = (struct iris_section_align_entry *)
+ xmalloc (sizeof (struct iris_section_align_entry));
+ *slot = entry;
+ entry->name = section;
+ entry->log = log;
+ entry->flags = current_section_flags ();
+ }
+ else if (entry->log < log)
+ entry->log = log;
+
+ fprintf (file, "\t.align\t%u\n", log);
+}
+
+/* The Iris assembler does not record alignment from .align directives,
+ but takes it from the first .section directive seen. Play yet more
+ file switching games so that we can emit a .section directive at the
+ beginning of the file with the proper alignment attached. */
+
+void
+iris6_asm_file_start (stream)
+ FILE *stream;
+{
+ mips_asm_file_start (stream);
+
+ iris_orig_asm_out_file = asm_out_file;
+ stream = tmpfile ();
+ asm_out_file = stream;
+ asm_out_data_file = stream;
+ if (! TARGET_FILE_SWITCHING)
+ asm_out_text_file = stream;
+
+ iris_section_align_htab = htab_create (31, iris_section_align_entry_hash,
+ iris_section_align_entry_eq, NULL);
+}
+
+static int
+iris6_section_align_1 (slot, data)
+ void **slot;
+ void *data ATTRIBUTE_UNUSED;
+{
+ const struct iris_section_align_entry *entry
+ = *(const struct iris_section_align_entry **) slot;
+
+ iris6_asm_named_section_1 (entry->name, entry->flags, 1 << entry->log);
+ return 1;
+}
+
+void
+iris6_asm_file_end (stream)
+ FILE *stream;
+{
+ /* Emit section directives with the proper alignment at the top of the
+ real output file. */
+ asm_out_file = iris_orig_asm_out_file;
+ htab_traverse (iris_section_align_htab, iris6_section_align_1, NULL);
+
+ /* Copy the data emitted to the temp file to the real output file. */
+ copy_file_data (asm_out_file, stream);
+
+ mips_asm_file_end (stream);
+}
+#endif /* TARGET_IRIX6 */