UNDER CONSTRUCTION
This article describes some notes about MIPS with a focus on GCC,binutils, and LLVM/Clang.
Earlier ISAs, such as MIPS I, MIPS II, MIPS III, and MIPS IV, can beselected by gcc -march=mips[1-4]
. MIPS V has noimplementation and GCC doesn't support -march=mips5
.
Successive versions are split into MIPS32 and MIPS64, which can beselected by -march=mips{32,64}
and-march=mips{32,64}r{2,3,5,6}
.-march=mips{32,64}r4
is not supported.
Release 6 is very different from prior releases.
-march=mips{32,64}r2
define __mips_isa_rev
to 2.-march=mips{32,64}r3
define __mips_isa_rev
to 3.-march=mips{32,64}r5
define __mips_isa_rev
to 5.-march=mips{32,64}r6
define __mips_isa_rev
to 6.__mips_isa_rev
.The ISA revisions of GCC supported -march=
values can befound at gcc/config/mips/mips-cpus.def
.
The EF_MIPS_ARCH
(0xf0000000) part ofe_flags
indicates the ISA.
When a 64-bit capable CPU is used with o32, assemblers set theEF_MIPS_32BITMODE
flag in e_flags
.
https://refspecs.linuxfoundation.org/elf/mipsabi.pdf
This is an ILP32 ABI designed for the 32-bit CPU MIPS R3000 thatimplements the MIPS I ISA. It is the original System V ProcessorSupplement ABI for MIPS.
In GCC, -mabi=32
selects this ABI, which is identifiedas ABI_32
.
Assemblers set the EF_MIPS_ABI_O32
flag ine_flags
.
There are some major flaws:
MIPS I has 32 floating-point registers. Two registers are paired forholding a double precision number.
For o32, -mfp64
selects a variant that enables 64-bitfloating-point registers. This requires at least-march=mips32r2
and GCC will emit.module fp=64; .module oddspreg
.
This is an LP64 ABI designed for 64-bit CPUs (MIPS III andnewer).
In GCC, -mabi=64
selects this ABI, which is identifiedas ABI_64
.
Assemblers don't set a particular bit in e_flags
.
This is an ILP32 ABI for 64-bit CPUs (MIPS III and newer), oftennamed n32.
In GCC, -mabi=n32
selects this ABI, which is identifiedas ABI_N32
. -march=
values such asmips3, mips64
are compatible.
Assemblers set the EF_MIPS_ABI2
bit ine_flags
.
This is o32 extended for 64-bit CPUs. https://gcc.gnu.org/projects/mipso64-abi.html
In GCC, -mabi=o64
selects this ABI, which is identifiedas ABI_O64
.
Assemblers set the EF_MIPS_ABI_O64
flag ine_flags
.
Assemblers set the EF_MIPS_ABI_EABI32
flag ine_flags
.
o32 and o64 are called TARGET_OLDABI
in GCC. n32 and n64are called TARGET_NEWABI
in GCC.
In the old ABIs, the local label prefix for assembly is$
, which is strange.
GCC emits a special section to indicate the ABI for GDB.
.mdebug.abi32
.mdebug.abiN32
.mdebug.abi64
mdebug.abiO64
.mdebug.eabi32
.mdebug.eabi32
See NaNencodings.
IEEE 754-2008 says
A quiet NaN bit string should be encoded with the first bit (d1) ofthe trailing significand field T being 1.
-mnan=2008
instructs GCC to emit a.nan 2008
directive, which causes GNU assembler to set theEF_MIPS_NAN2008
bit in e_flags
.
MIPS32/MIPS64 Release 6 defaults to -mnan=2008
whileprior ISAs default to -mnan=legacy
.
-modd-spreg
When 64-bit floating-point registers are available (implied byELFCLASS64) or MIPS32/MIPS64 Release 1 or above, odd-numberedsingle-precision floating-point registers can be used. 1
2
3
4
5/* ISA has 32 single-precision registers. */
#define ISA_HAS_ODD_SPREG ((mips_isa_rev >= 1 \
&& !TARGET_GS464) \
|| TARGET_FLOAT64 \
|| TARGET_MIPS5900)
However, these registers are disabled for the o32 ABI by default.Specifying -mabi=32 -mfp64
uses a variant where floating-point registers are 64 rather than 32 bitswide.
1 | % grep DT_MIPS_ include/elf/mips.h |
Among these dynamic tags, DT_MIPS_LOCAL_GOTNO
,DT_MIPS_GOTSYM
, DT_MIPS_SYMTABNO
, andDT_MIPS_PLTGOT
have significant uses in glibc rtld.
For executable output, DT_MIPS_RLD_MAP_REL
holds theoffset to the linker synthesized .rld_map
. IfDT_MIPS_RLD_MAP_REL
is unavailable, glibc rtld looks forDT_MIPS_RLD_MAP
, which is emitted for ET_EXEC
executables.
There are many special sections. Let me just quote a comment frombinutils/readelf.c:process_mips_specific
: 1
/* We have a lot of special sections. Thanks SGI! */
There are many sections from other vendors. Anyway, this remark setsup the mood.
.MIPS.options
sectionMips N32 and N64 ABIs use .MIPS.options
.
.MIPS.abiflags
sectionIn 2014, [MIPS]Implement O32 FPXX, FP64 and FP64A ABI extensions introduced.MIPS.abiflags
(type SHT_MIPS_ABIFLAGS
) andPT_MIPS_ABIFLAGS
.
1 | A new implicitly generated section will be present on all new modules. The section contains a versioned data structure which represents essential information to allow a program loader to determine the requirements of the application. ELF e_flags currently contain some of this information but space is limited and e_flags are not available after loading an application. |
GNU ld has quite involved merging strategy for this section.
The little-endian n64 ABI messed up the r_info
field inrelocations.
The n64 ABI can pack up to 3 relocations with the same offset intoone record.
R_MIPS_PC64
This relocation type does not exist, but we can emulate a 64-bitPC-relative relocation withR_MIPS_PC32 + R_MIPS_64 + R_MIPS_NONE
. LLVM implementedthis relocation in https://reviews.llvm.org/D80390 while binutils doesn'tsupport it yet.
1 | .globl foo |
TODO
Here is an incomplete list.
FreeBSD 14 discontinued MIPS. MIPS code was removed startingsince 2021-12.
E_MIPS_*
macros are considereddeprecated.