MiPS16e与32汇编代码
对于MIPS CPU而言,减小代码尺寸的一种办法是把代码编译成MIPS16指令。常规的MIPS指令是32位长度的,MIPS16指令的长度则是16位,使用这种办法,通常能够把代码尺寸缩小30%-40%(和ARM CPU的Thumb指令能达到的空间节约程度差不多)。但是,并不是所有代码都能编译成MIPS16位指令,因为MIPS16指令只是MIPS32指令的一个子集,比如,对协处理器CP0的操作就无法用MIPS16指令完成。这就意味着:异常和中断处理都必须编译为MIPS32指令。经过分析发现,和体系结构相关的汇编代码(包括异常和中断处理部分的代码)编译之后所占的空间不是太多,不到100KB的样子在MIPS架构中,为了优化代码空间,引入了MIPS16指令集,这是一种16位的精简指令集,相比于传统的32位MIPS指令,可以显著减少代码大小,通常能节省30%-40%的空间。MIPS16指令集是MIPS32指令集的一个子集,这意味着它不能包含所有MIPS32指令的功能,特别是涉及协处理器如CP0的操作。由于异常和中断处理通常需要完整功能的MIPS32指令,因此这部分代码需要保持为32位格式。在项目实践中,为了平衡代码尺寸和功能,可以将大部分C代码编译为MIPS16指令,而将与系统架构密切相关的汇编代码,包括异常和中断处理,编译为MIPS32指令。然而,这样的混合使用可能导致链接错误,如"jump to stub routine without jal",这是因为MIPS16和MIPS32之间缺乏有效的跳转机制。在这种情况下,当一个MIPS32函数的最后一条指令调用了MIPS16函数时,如果没有使用jal指令进行模式切换,链接器就会报错。解决这个问题的方法之一是利用函数属性`__attribute__((nomips16))`或`__attribute__((mips16))`来明确指定函数应该被编译为哪种模式。例如,如果`bar()`函数是MIPS16模式,那么调用它的`foo()`函数也应该被标记为MIPS16模式,以避免模式切换。这样,就可以避免链接器报错,并确保代码的正确执行。在进行这样的移植工作时,需要手动识别并修改源代码中涉及MIPS16和MIPS32转换的部分,虽然工作量可能较大,但这是保证程序正确运行和优化代码空间的关键步骤。工程师在面对此类问题时,需要有耐心和细心,因为这类任务体现了专业技能和经验的价值,不是任何人都能轻易完成的。 MIPS16指令集提供了一种有效的代码压缩方法,但同时也带来了模式转换的挑战。正确理解和运用MIPS16与MIPS32之间的转换规则,以及适当使用函数属性,是编写高效、兼容的MIPS程序的关键。在实际开发中,应当根据代码的具体需求和系统限制,灵活选择合适的指令集,并处理好模式切换问题,以达到最佳的性能和资源利用率。
下载地址
用户评论