Porting lcc |
|||
Home 32-bit RISC CPU >> << Soft cores
Usenet Postings |
Subject: Re: porting a compiler to a new architecture Date: 22 Mar 1999 00:00:00 GMT Newsgroups: comp.compilers mathai-@ecf.toronto.edu wrote ... >I'm designing a RISC CPU for fun, and wanted to know how difficult it >would be to port a compiler like gcc to generate code (non-optimized is >fine) for my machine? I'm ignorant of compilers, but can learn .. I'd just >like to assess how difficult it would be. > >Thanks >[One RISC is pretty much like another for a straightforward code generator, >so I'd think you should be able to get a limping version of lcc in a week >or two. -John] I recently designed another RISC CPU for fun. This one is a 16-bit 16-register classic pipelined RISC, implemented using Xilinx Student Ed., occupying about 60% of a Xilinx XC4005XL-3 FPGA, running at 25 MHz. I targeted lcc 4.1 to this new processor and was quite pleased with the process and the results. Most of the work was done in one long and very pleasant day. However, I had already read Fraser and Hanson [1], and I used to write compilers. So your mileage may vary. (I look forward to trying the same thing with GCC.) Here's what I did. I downloaded lcc4.1 from www.cs.princeton.edu/software/lcc and built it with MS VC++. I read doc/4.html, "The lcc 4.1 Code-Generation Interface". Since I was targeting a classic RISC instruction set architecture, I started with the MIPS machine description, mips.md. I copied that to xr16.md, added xr16.md to the makefile, and added two lines to bind.c for "-target=xr16". Next I designed xr16 register conventions (below) and modified my md to target these registers. Register Use r0 always zero r1 reserved for assembler r2 function return value r3-r5 function arguments r6-r9 temporaries r10-r13 register variables r14 stack pointer (sp) r15 return address At this point I had a C compiler for a 32-bit 16-register RISC. But I needed to target a 16-bit machine with sizeof(int)=sizeof(void*)=2. No problem! Lcc obtains target operand sizes from md tables -- so, change some 4's to 2's: Interface xr16IR = { 1, 1, 0, /* char */ 2, 2, 0, /* short */ 2, 2, 0, /* int */ 4, 4, 0, /* long */ ... 2, 2, 0, /* T * */ ... Next I built and ran the "ops" utility "ops c=1 s=2 i=2 l=4 h=4 f=4 d=4 x=4 p=2" which prints the required primitive dag operator set for a machine with 2-byte ints and pointers. I modified my instruction templates to cover this operator set, and removed some 32-bit int assumptions inherited from mips.md. (This small effort compared extremely favorably with past experience of porting another C/C++ compiler from 16-bit ints/pointers to 32-bit ints/pointers.) I decided to keep long ints in register pairs. This required just four lines of code to introduce a new class of register resource and to target the 4-byte integer types to that resource. Wow. (Although this hasn't had much testing yet.) Compared to the MIPS templates, my xr16 templates reflect * different branch scheme (condition codes, sorry); * logic/shift instructions are (necessarily) two-operand only; * immediate constants are encoded differently; * mul, div, and rem are calls upon helper routines. All totaled, in xr16.md, I replaced the entire dag operator set (entirely generated by ops utility), changed about 200 lines of instruction templates (mostly to reflect 2-byte int/pointer changes in dag operator types), and about 100 lines of miscellaneous code. I have yet to properly diagnose use of floating point (never to be implemented). And except for some test apps, I haven't properly tested the compiler. The resulting code quality? Not superlative, but not too bad. For example, for this source: typedef struct TN { int k; struct TN *left, *right; } *T; T search(int k, T p) { while (p && p->k != k) if (p->k < k) p = p->right; else p = p->left; return p; } my "lcc -S -Wf-target=xr16 search.c" emits this assembler: align 16 search: br L3 L2: lw r9,(r4) cmp r9,r3 bge L5 lw r4,4(r4) br L6 L5: lw r4,2(r4) L6: L3: mov r9,r4 cmp r9,r0 beq L7 lw r9,(r4) cmp r9,r3 bne L2 L7: mov r2,r4 L1: ret which I consider quite acceptable for my purposes. I only wish there was a retargetable assembler as easy to port as is lcc. I looked at gas but it seemed rather large. Any pointers? Instead I wrote a simple two-pass assembler from scratch. This took twice as long as the compiler port... Jan Gray [1] Christopher W. Fraser, David R. Hanson. A Retargetable C Compiler : Design and Implementation. Addison-Wesley. ISBN: 0805316701
Copyright © 2000, Gray Research LLC. All rights reserved. |