As a 32-bit Instruction Set Architecture, the code density of MIPS32 is not as high as that of MIPS16E. Our practice has shown that if a program is built with MIPS16E instead of MIPS32, the code size will be two third of its original length.
There were some concernings before the whole system is built with MIPS16E:
- Is all functions could be implemented by MIPS16E instructions?
Yes, there are some limitations of MIPS16E instructions:- CP0 registers couldn't be accessed by MIPS16E instructions.
- The instruction "sync" is not available in MIPS16E mode.
- Interrupt/Exception vectors must be MIPS32 code.
- Is the performance of MIPS15E as good as that of MIPS32?
- No material shows that the performance of MIPS16E is poor than MIPS32.
- A document from MIPS indicates that the actual performance of MIPS16E is even better than MIPS32, for the cache could accommodate more 16bit instructions than 32-bits instructions.
We have to make some modules be build with MIPS32 ISA for the following reason:
- the MIPS16E instruction is not full-functional.
- There are some code is written with MIPS32 assemble.
Anyway, most code of Rigel is architecture independent and could be build with MIPS16E.
While compiling a source(C,CPP) file, MIPS16E or MIPS32 could be specified as gcc's option -mips32 or -mips16. In-line asm code couldn't be build with incorrect gcc options. For Rigel there are only MIPS32 in-line asm statements(We are not familiar with MIPS16 instructions), it means some files coudn't be compiled with -mips16 option. A Macro, __MIPS16E__, is defined for avoiding MIPS32 asm code from a .h file which is included by the c files that compiled with MIPS16E ISA.
The options "-mips16 _D__MIPS16E__" are added to the global cflag(src/ecos-2.0-antares/packages/hal/mips/mips324ke/current/cdl/hal_mips_mips32_4ke.cdl).
For the modules that couldn't be compiled with MIPS16E, these options are hidden by defining cdl_option CYGPKG_XXXXXXXX_CFLAGS_REMOVE in their cdl files.
module | reason |
driver_adec | in-line asm code of MIPS32 |
driver_front_panel | in-line asm code of MIPS32 |
hal | Architecture dependent code. Accessing CP0, MIPS32 asm source. |
There are some issues when the whole system is built:
- Function-like macros written in MIPS32 asm code.
There are some funcion-like marcros defined in .h file and be used as functions, such as HAL_ENABLE_INTERRUPT(), they are written in MIPS32 asm code. They are also called in the .c file that is built with MIPS16 ISA. With the help of the macro __MIPS16E__, the macros will will be re-defined as real functions:
#ifndef __MIPS16E__ #define HAL_ENABLE_INTERRUPTS() / { / asm volatile ( / "mfc0 $8,$12; nop;" / "or $8,$8,1;" / "mtc0 $8,$12;" / "nop; nop; nop;" / : / : / : "$8" / ); / } .... #else //if __MIPS16E__ is defined: void hal_enable_interrupts(void); ... #define HAL_ENABLE_INTERRUPTS() hal_enable_interrupts() #endifWhen such functions are actually defined, the code is very interesting:
src/ecos-2.0-antares/packages/hal/mips/mips324ke/current/src/var_misc.c: __ExternC void hal_enable_interrupts(void) { HAL_ENABLE_INTERRUPTS(); }Sure var_misc.c must be compiled with MIPS32, and __MIPS16E__ undefined.
- Switching between MIPS32 and MIPS16E
MIPS CPU can jump between the code of MIPS32 and MIPS16E directly, without any special mode switching operation. But not all of the jumpping /branch instructions could be used for mode switching. Fortunately in most case the switching between MIPS32 and MIPS16E is not a problem, except that when sibling calls is optimizes by gcc, a illegal instruction will be used for jumping from MIPS32 code to MIPS16E code.
Disable the optimization of sibling call for MIPS32 code with gcc option:-fno-optimize-sibling-calls