【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
gcc作为一款工业级的软件,在前端和后端接口上面分的很清楚。它的前端对接各种编程语言,包括fortan、c、cpp、objc、java之类,而它的后端则适配各种体系的cpu。今天说到的这款or1k呢,本身是一款开源的cpu。那么,我们就可以通过or1k,学习一下gcc是如何适配一款cpu的?注意,如果但从编译器来说,gcc只负责生成汇编,as才负责生成二进制。
1、or1k-gcc的地址
https://github.com/pgavin/or1k-gcc
2、如果在or1k-gcc寻找和or1k相关的信息
只需要在‘this repository’输入‘or1k’即可
3、和or1k关联的目录
a,gcc/config/or1k
b,libgcc/config/or1k
c,gcc/common/config/or1k
4、后端移植的主要目录
gcc/config/or1k,目录中包含了主要的md文件和c文件
md文件完成rtl语言到assemble语言的翻译
c文件完成后端体系的函数接口
5、新的cpu,除了gcc还要做哪些适配
除了gcc,还要适配binutils、gdb、uclibc、linux kernel、busybox,这些几乎是标配
6、md的格式是什么样的
(define_insn "addsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(plus:SI (match_operand:SI 1 "register_operand" "%r,r")
(match_operand:SI 2 "nonmemory_operand" "r,I")))]
""
"@
l.add \t%0,%1,%2 # addsi3
l.addi \t%0,%1,%2 # addsi3"
[(set_attr "type" "add,add")
(set_attr "length" "1,1")])
其中,define_insn表明这是一个指令生成结构,addsi3表示指令名称,plus:SI表明这是寄存器和立即数的相加操作,3个match_operand表示指令需要的三个参数,“%r,r”和“r,I”表示两种参数形式,l.add和l.addi表示具体指令内容,type和add表明这个指令用来做叫法,length表示指令的长度。
7、后端的c函数接口是什么样的
#undef TARGET_PRINT_OPERAND_ADDRESS
#define TARGET_PRINT_OPERAND_ADDRESS or1k_print_operand_address
8、rtl基本适配的指令有哪些
a,运算类,比如加减乘除
b,逻辑类,比如与或非
c,移位类,比如左右移动
d,赋值类,比如move
e,比较类,比如大小比较、和0比较
f、访存类,比如load、store
g、跳转类,比如jmp
h、调用类,比如call
9、头文件包括了哪些内容
寄存器个数、函数调用约定、寻址、调试、输出格式约定等等
ps:
a,事实上,重新开发一款cpu的机会对于大多数人来说,还是很少的。但是,为一个cpu添加自定义指令,这个工作却很常见。尤其是mips这样的cpu,几乎每个厂家都要做一些定制化的私有工作。
b,gcc后端移植完了,还要移植as、link,这样程序才能编译出来。
c,clang+llvm也是不错的编译器开发模式。在llvm上也有类似的目录,它的地址如下,大家可以好好参考一下,
https://github.com/llvm-mirror/llvm/tree/master/lib/Target
d,open64也是不错的编译,它的后端移植也可以参考一下,链接如下,https://github.com/open64-compiler/open64/tree/master/osprey/cygnus/opcodes