3 #define NODEPTR_TYPE Node
4 #define OP_LABEL(p) ((p)->op)
5 #define LEFT_CHILD(p) ((p)->kids[0])
6 #define RIGHT_CHILD(p) ((p)->kids[1])
7 #define STATE_LABEL(p) ((p)->x.state)
8 static void address ARGS((Symbol, Symbol, int));
9 static void blkfetch ARGS((int, int, int, int));
10 static void blkloop ARGS((int, int, int, int, int, int[]));
11 static void blkstore ARGS((int, int, int, int));
12 static void defaddress ARGS((Symbol));
13 static void defconst ARGS((int, Value));
14 static void defstring ARGS((int, char *));
15 static void defsymbol ARGS((Symbol));
16 static void doarg ARGS((Node));
17 static void emit2 ARGS((Node));
18 static void export ARGS((Symbol));
19 static void clobber ARGS((Node));
20 static void function ARGS((Symbol, Symbol [], Symbol [], int));
21 static void global ARGS((Symbol));
22 static void import ARGS((Symbol));
23 static void local ARGS((Symbol));
24 static void progbeg ARGS((int, char **));
25 static void progend ARGS((void));
26 static void segment ARGS((int));
27 static void space ARGS((int));
28 static void target ARGS((Node));
29 static int imm ARGS((Node));
30 static void rename ARGS((void));
31 static void defsymbol2 ARGS((Symbol));
32 static void global2 ARGS((Symbol));
33 static void segment2 ARGS((int));
35 static Symbol greg[32];
36 static Symbol *oreg = &greg[8], *ireg = &greg[24];
37 static Symbol freg[32], freg2[32];
47 %term ADDD=306 ADDF=305 ADDI=309 ADDP=311 ADDU=310
51 %term ARGB=41 ARGD=34 ARGF=33 ARGI=37 ARGP=39
52 %term ASGNB=57 ASGNC=51 ASGND=50 ASGNF=49 ASGNI=53 ASGNP=55 ASGNS=52
57 %term CALLB=217 CALLD=210 CALLF=209 CALLI=213 CALLV=216
58 %term CNSTC=19 CNSTD=18 CNSTF=17 CNSTI=21 CNSTP=23 CNSTS=20 CNSTU=22
60 %term CVDF=97 CVDI=101
62 %term CVIC=131 CVID=130 CVIS=132 CVIU=134
64 %term CVSI=165 CVSU=166
65 %term CVUC=179 CVUI=181 CVUP=183 CVUS=180
66 %term DIVD=450 DIVF=449 DIVI=453 DIVU=454
67 %term EQD=482 EQF=481 EQI=485
68 %term GED=498 GEF=497 GEI=501 GEU=502
69 %term GTD=514 GTF=513 GTI=517 GTU=518
70 %term INDIRB=73 INDIRC=67 INDIRD=66 INDIRF=65 INDIRI=69 INDIRP=71 INDIRS=68
73 %term LED=530 LEF=529 LEI=533 LEU=534
74 %term LOADB=233 LOADC=227 LOADD=226 LOADF=225 LOADI=229 LOADP=231 LOADS=228 LOADU=230
75 %term LSHI=341 LSHU=342
76 %term LTD=546 LTF=545 LTI=549 LTU=550
77 %term MODI=357 MODU=358
78 %term MULD=466 MULF=465 MULI=469 MULU=470
79 %term NED=562 NEF=561 NEI=565
80 %term NEGD=194 NEGF=193 NEGI=197
81 %term RETD=242 RETF=241 RETI=245
82 %term RSHI=373 RSHU=374
83 %term SUBD=322 SUBF=321 SUBI=325 SUBP=327 SUBU=326
86 reg: INDIRC(VREGP) "# read register\n"
87 reg: INDIRD(VREGP) "# read register\n"
88 reg: INDIRF(VREGP) "# read register\n"
89 reg: INDIRI(VREGP) "# read register\n"
90 reg: INDIRP(VREGP) "# read register\n"
91 reg: INDIRS(VREGP) "# read register\n"
92 stmt: ASGNC(VREGP,reg) "# write register\n"
93 stmt: ASGND(VREGP,reg) "# write register\n"
94 stmt: ASGNF(VREGP,reg) "# write register\n"
95 stmt: ASGNI(VREGP,reg) "# write register\n"
96 stmt: ASGNP(VREGP,reg) "# write register\n"
97 stmt: ASGNS(VREGP,reg) "# write register\n"
104 reg: CVIU(reg) "%0" notarget(a)
105 reg: CVPU(reg) "%0" notarget(a)
106 reg: CVUI(reg) "%0" notarget(a)
107 reg: CVUP(reg) "%0" notarget(a)
108 reg: ADDRGP "set %a,%%%c\n" 1
109 stk13: ADDRFP "%a" imm(a)
110 stk13: ADDRLP "%a" imm(a)
111 reg: stk13 "add %0,%%fp,%%%c\n" 1
112 stk: ADDRFP "set %a,%%%c\n" 2
113 stk: ADDRLP "set %a,%%%c\n" 2
114 reg: ADDRFP "set %a,%%%c\nadd %%%c,%%fp,%%%c\n" 3
115 reg: ADDRLP "set %a,%%%c\nadd %%%c,%%fp,%%%c\n" 3
116 con13: CNSTC "%a" imm(a)
117 con13: CNSTI "%a" imm(a)
118 con13: CNSTP "%a" imm(a)
119 con13: CNSTS "%a" imm(a)
120 con13: CNSTU "%a" imm(a)
121 base: ADDI(reg,con13) "%%%0+%1"
122 base: ADDP(reg,con13) "%%%0+%1"
123 base: ADDU(reg,con13) "%%%0+%1"
126 base: stk13 "%%fp+%0"
128 addr: ADDI(reg,reg) "%%%0+%%%1"
129 addr: ADDP(reg,reg) "%%%0+%%%1"
130 addr: ADDU(reg,reg) "%%%0+%%%1"
131 addr: stk "%%fp+%%%0"
132 reg: INDIRC(addr) "ldsb [%0],%%%c\n" 1
133 reg: INDIRS(addr) "ldsh [%0],%%%c\n" 1
134 reg: INDIRI(addr) "ld [%0],%%%c\n" 1
135 reg: INDIRP(addr) "ld [%0],%%%c\n" 1
136 reg: INDIRF(addr) "ld [%0],%%f%c\n" 1
137 stmt: ASGNC(addr,reg) "stb %%%1,[%0]\n" 1
138 stmt: ASGNS(addr,reg) "sth %%%1,[%0]\n" 1
139 stmt: ASGNI(addr,reg) "st %%%1,[%0]\n" 1
140 stmt: ASGNP(addr,reg) "st %%%1,[%0]\n" 1
141 stmt: ASGNF(addr,reg) "st %%f%1,[%0]\n" 1
142 addrl: ADDRLP "%%%fp+%a" imm(a)
144 reg: INDIRD(addrl) "ldd [%0],%%f%c\n" 1
145 stmt: ASGND(addrl,reg) "std %%f%1,[%0]\n" 1
146 reg: INDIRD(base) "ld2 [%0],%%f%c\n" 2
147 stmt: ASGND(base,reg) "st2 %%f%1,[%0]\n" 2
148 spill: ADDRLP "%a" !imm(a)
150 stmt: ASGNC(spill,reg) "set %0,%%g1\nstb %%%1,[%%fp+%%g1]\n"
151 stmt: ASGNS(spill,reg) "set %0,%%g1\nsth %%%1,[%%fp+%%g1]\n"
152 stmt: ASGNI(spill,reg) "set %0,%%g1\nst %%%1,[%%fp+%%g1]\n"
153 stmt: ASGNP(spill,reg) "set %0,%%g1\nst %%%1,[%%fp+%%g1]\n"
154 stmt: ASGNF(spill,reg) "set %0,%%g1\nst %%f%1,[%%fp+%%g1]\n"
155 stmt: ASGND(spill,reg) "set %0,%%g1\nstd %%f%1,[%%fp+%%g1]\n"
156 reg: CVCI(INDIRC(addr)) "ldsb [%0],%%%c\n" 1
157 reg: CVSI(INDIRS(addr)) "ldsh [%0],%%%c\n" 1
158 reg: CVCU(INDIRC(addr)) "ldub [%0],%%%c\n" 1
159 reg: CVSU(INDIRS(addr)) "lduh [%0],%%%c\n" 1
160 reg: CVIC(reg) "mov %%%0,%%%c\n" move(a)
161 reg: CVIS(reg) "mov %%%0,%%%c\n" move(a)
162 reg: CVIU(reg) "mov %%%0,%%%c\n" move(a)
163 reg: CVPU(reg) "mov %%%0,%%%c\n" move(a)
164 reg: CVUC(reg) "mov %%%0,%%%c\n" move(a)
165 reg: CVUI(reg) "mov %%%0,%%%c\n" move(a)
166 reg: CVUP(reg) "mov %%%0,%%%c\n" move(a)
167 reg: CVUS(reg) "mov %%%0,%%%c\n" move(a)
168 reg: CVIC(reg) "%0" notarget(a)
169 reg: CVIS(reg) "%0" notarget(a)
170 reg: CVUC(reg) "%0" notarget(a)
171 reg: CVUS(reg) "%0" notarget(a)
172 reg: LOADC(reg) "mov %%%0,%%%c\n" move(a)
173 reg: LOADI(reg) "mov %%%0,%%%c\n" move(a)
174 reg: LOADP(reg) "mov %%%0,%%%c\n" move(a)
175 reg: LOADS(reg) "mov %%%0,%%%c\n" move(a)
176 reg: LOADU(reg) "mov %%%0,%%%c\n" move(a)
177 reg: CNSTC "# reg\n" range(a, 0, 0)
178 reg: CNSTI "# reg\n" range(a, 0, 0)
179 reg: CNSTP "# reg\n" range(a, 0, 0)
180 reg: CNSTS "# reg\n" range(a, 0, 0)
181 reg: CNSTU "# reg\n" range(a, 0, 0)
182 reg: con "set %0,%%%c\n" 1
185 reg: ADDI(reg,rc) "add %%%0,%1,%%%c\n" 1
186 reg: ADDP(reg,rc) "add %%%0,%1,%%%c\n" 1
187 reg: ADDU(reg,rc) "add %%%0,%1,%%%c\n" 1
188 reg: BANDU(reg,rc) "and %%%0,%1,%%%c\n" 1
189 reg: BORU(reg,rc) "or %%%0,%1,%%%c\n" 1
190 reg: BXORU(reg,rc) "xor %%%0,%1,%%%c\n" 1
191 reg: SUBI(reg,rc) "sub %%%0,%1,%%%c\n" 1
192 reg: SUBP(reg,rc) "sub %%%0,%1,%%%c\n" 1
193 reg: SUBU(reg,rc) "sub %%%0,%1,%%%c\n" 1
194 rc5: CNSTI "%a" range(a, 0, 31)
196 reg: LSHI(reg,rc5) "sll %%%0,%1,%%%c\n" 1
197 reg: LSHU(reg,rc5) "sll %%%0,%1,%%%c\n" 1
198 reg: RSHI(reg,rc5) "sra %%%0,%1,%%%c\n" 1
199 reg: RSHU(reg,rc5) "srl %%%0,%1,%%%c\n" 1
200 reg: BANDU(reg,BCOMU(rc)) "andn %%%0,%1,%%%c\n" 1
201 reg: BORU(reg,BCOMU(rc)) "orn %%%0,%1,%%%c\n" 1
202 reg: BXORU(reg,BCOMU(rc)) "xnor %%%0,%1,%%%c\n" 1
203 reg: NEGI(reg) "neg %%%0,%%%c\n" 1
204 reg: BCOMU(reg) "not %%%0,%%%c\n" 1
205 reg: CVCI(reg) "sll %%%0,24,%%%c; sra %%%c,24,%%%c\n" 2
206 reg: CVSI(reg) "sll %%%0,16,%%%c; sra %%%c,16,%%%c\n" 2
207 reg: CVCU(reg) "and %%%0,0xff,%%%c\n" 1
208 reg: CVSU(reg) "set 0xffff,%%g1; and %%%0,%%g1,%%%c\n" 2
210 stmt: JUMPV(addrg) "ba %0; nop\n" 2
211 stmt: JUMPV(addr) "jmp %0; nop\n" 2
213 stmt: EQI(reg,rc) "cmp %%%0,%1; be %a; nop\n" 3
214 stmt: GEI(reg,rc) "cmp %%%0,%1; bge %a; nop\n" 3
215 stmt: GEU(reg,rc) "cmp %%%0,%1; bgeu %a; nop\n" 3
216 stmt: GTI(reg,rc) "cmp %%%0,%1; bg %a; nop\n" 3
217 stmt: GTU(reg,rc) "cmp %%%0,%1; bgu %a; nop\n" 3
218 stmt: LEI(reg,rc) "cmp %%%0,%1; ble %a; nop\n" 3
219 stmt: LEU(reg,rc) "cmp %%%0,%1; bleu %a; nop\n" 3
220 stmt: LTI(reg,rc) "cmp %%%0,%1; bl %a; nop\n" 3
221 stmt: LTU(reg,rc) "cmp %%%0,%1; blu %a; nop\n" 3
222 stmt: NEI(reg,rc) "cmp %%%0,%1; bne %a; nop\n" 3
225 reg: CALLD(call) "call %0; nop\n" 2
226 reg: CALLF(call) "call %0; nop\n" 2
227 reg: CALLI(call) "call %0; nop\n" 2
228 stmt: CALLV(call) "call %0; nop\n" 2
229 stmt: CALLB(call,reg) "call %0; st %%%1,[%%sp+64]\n" 2
230 stmt: RETD(reg) "# ret\n" 1
231 stmt: RETF(reg) "# ret\n" 1
232 stmt: RETI(reg) "# ret\n" 1
233 stmt: ARGI(reg) "st %%%0,[%%sp+4*%c+68]\n" 1
234 stmt: ARGP(reg) "st %%%0,[%%sp+4*%c+68]\n" 1
235 stmt: ARGD(reg) "# ARGD\n" 1
236 stmt: ARGF(reg) "# ARGF\n" 1
238 reg: DIVI(reg,reg) "call .div,2; nop\n" 2
239 reg: DIVU(reg,reg) "call .udiv,2; nop\n" 2
240 reg: MODI(reg,reg) "call .rem,2; nop\n" 2
241 reg: MODU(reg,reg) "call .urem,2; nop\n" 2
242 reg: MULI(reg,reg) "call .mul,2; nop\n" 2
243 reg: MULU(reg,reg) "call .umul,2; nop\n" 2
244 reg: ADDD(reg,reg) "faddd %%f%0,%%f%1,%%f%c\n" 1
245 reg: ADDF(reg,reg) "fadds %%f%0,%%f%1,%%f%c\n" 1
246 reg: DIVD(reg,reg) "fdivd %%f%0,%%f%1,%%f%c\n" 1
247 reg: DIVF(reg,reg) "fdivs %%f%0,%%f%1,%%f%c\n" 1
248 reg: MULD(reg,reg) "fmuld %%f%0,%%f%1,%%f%c\n" 1
249 reg: MULF(reg,reg) "fmuls %%f%0,%%f%1,%%f%c\n" 1
250 reg: SUBD(reg,reg) "fsubd %%f%0,%%f%1,%%f%c\n" 1
251 reg: SUBF(reg,reg) "fsubs %%f%0,%%f%1,%%f%c\n" 1
252 reg: NEGF(reg) "fnegs %%f%0,%%f%c\n" 1
253 reg: LOADF(reg) "fmovs %%f%0,%%f%c\n" 1
254 reg: CVDF(reg) "fdtos %%f%0,%%f%c\n" 1
255 reg: CVFD(reg) "fstod %%f%0,%%f%c\n" 1
256 reg: CVDI(reg) "fdtoi %%f%0,%%f0; st %%f0,[%%sp+64]; ld [%%sp+64],%%%c\n" 3
258 reg: CVID(reg) "st %%%0,[%%sp+64]; ld [%%sp+64],%%f%c; fitod %%f%c,%%f%c\n" 3
260 rel: EQD(reg,reg) "fcmped %%f%0,%%f%1; nop; fbue"
261 rel: EQF(reg,reg) "fcmpes %%f%0,%%f%1; nop; fbue"
262 rel: GED(reg,reg) "fcmped %%f%0,%%f%1; nop; fbuge"
263 rel: GEF(reg,reg) "fcmpes %%f%0,%%f%1; nop; fbuge"
264 rel: GTD(reg,reg) "fcmped %%f%0,%%f%1; nop; fbug"
265 rel: GTF(reg,reg) "fcmpes %%f%0,%%f%1; nop; fbug"
266 rel: LED(reg,reg) "fcmped %%f%0,%%f%1; nop; fbule"
267 rel: LEF(reg,reg) "fcmpes %%f%0,%%f%1; nop; fbule"
268 rel: LTD(reg,reg) "fcmped %%f%0,%%f%1; nop; fbul"
269 rel: LTF(reg,reg) "fcmpes %%f%0,%%f%1; nop; fbul"
270 rel: NED(reg,reg) "fcmped %%f%0,%%f%1; nop; fbne"
271 rel: NEF(reg,reg) "fcmpes %%f%0,%%f%1; nop; fbne"
273 stmt: rel "%0 %a; nop\n" 4
274 reg: LOADD(reg) "# LOADD\n" 2
276 reg: NEGD(reg) "# NEGD\n" 2
278 stmt: ASGNB(reg,INDIRB(reg)) "# ASGNB\n"
281 static void progend(){}
282 static void progbeg(argc, argv) int argc; char *argv[]; {
292 swap = (u.i == 1) != IR->little_endian;
294 parseflags(argc, argv);
295 for (i = 0; i < argc; i++)
296 if (strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "-pg") == 0)
298 for (i = 0; i < 8; i++) {
299 greg[i + 0] = mkreg(stringf("g%d", i), i + 0, 1, IREG);
300 greg[i + 8] = mkreg(stringf("o%d", i), i + 8, 1, IREG);
301 greg[i + 16] = mkreg(stringf("l%d", i), i + 16, 1, IREG);
302 greg[i + 24] = mkreg(stringf("i%d", i), i + 24, 1, IREG);
304 for (i = 0; i < 32; i++)
305 freg[i] = mkreg("%d", i, 1, FREG);
306 for (i = 0; i < 31; i += 2)
307 freg2[i] = mkreg("%d", i, 3, FREG);
308 rmap[C] = rmap[S] = rmap[P] = rmap[B] = rmap[U] = rmap[I] =
310 rmap[F] = mkwildcard(freg);
311 rmap[D] = mkwildcard(freg2);
312 tmask[IREG] = 0x3fff3e00;
313 vmask[IREG] = 0x3ff00000;
314 tmask[FREG] = ~(unsigned)0;
317 static void target(p) Node p; {
320 case CNSTC: case CNSTI: case CNSTS: case CNSTU: case CNSTP:
321 if (range(p, 0, 0) == 0) {
326 case CALLD: setreg(p, freg2[0]); break;
327 case CALLF: setreg(p, freg[0]); break;
329 case CALLV: setreg(p, oreg[0]); break;
330 case RETD: rtarget(p, 0, freg2[0]); break;
331 case RETF: rtarget(p, 0, freg[0]); break;
333 rtarget(p, 0, ireg[0]);
334 p->kids[0]->x.registered = 1;
336 case ARGI: case ARGP:
337 if (p->syms[RX]->u.c.v.i < 6) {
338 rtarget(p, 0, oreg[p->syms[RX]->u.c.v.i]);
339 p->op = LOAD+optype(p->op);
340 setreg(p, oreg[p->syms[RX]->u.c.v.i]);
343 case DIVI: case MODI: case MULI:
344 case DIVU: case MODU: case MULU:
346 rtarget(p, 0, oreg[0]);
347 rtarget(p, 1, oreg[1]);
351 static void clobber(p) Node p; {
354 case CALLB: case CALLD: case CALLF: case CALLI:
355 spill(~(unsigned)3, FREG, p);
358 spill(oreg[0]->x.regnode->mask, IREG, p);
359 spill(~(unsigned)3, FREG, p);
362 if (p->syms[2]->u.c.v.i <= 6)
363 spill((1<<(p->syms[2]->u.c.v.i + 8)), IREG, p);
366 if (p->syms[2]->u.c.v.i <= 5)
367 spill((3<<(p->syms[2]->u.c.v.i + 8))&0xff00, IREG, p);
369 case DIVI: case MODI: case MULI:
370 case DIVU: case MODU: case MULU:
371 spill(0x00003e00, IREG, p); break;
374 static int imm(p) Node p; {
375 return range(p, -4096, 4095);
377 static void doarg(p) Node p; {
378 assert(p && p->syms[0] && p->op != ARG+B);
379 p->syms[RX] = intconst(mkactual(4,
380 p->syms[0]->u.c.v.i)/4);
382 static void emit2(p) Node p; {
385 int n = p->syms[RX]->u.c.v.i;
386 print("st %%f%d,[%%sp+4*%d+68]\n",
387 getregnum(p->x.kids[0]), n);
389 print("ld [%%sp+4*%d+68],%%o%d\n", n, n);
393 int n = p->syms[RX]->u.c.v.i;
394 int src = getregnum(p->x.kids[0]);
395 print("st %%f%d,[%%sp+4*%d+68]\n", src, n);
396 print("st %%f%d,[%%sp+4*%d+68]\n", src+1, n+1);
398 print("ld [%%sp+4*%d+68],%%o%d\n", n, n);
400 print("ld [%%sp+4*%d+68],%%o%d\n", n+1, n+1);
404 int dst = getregnum(p);
405 int src = getregnum(p->x.kids[0]);
406 print("fmovs %%f%d,%%f%d; ", src, dst);
407 print("fmovs %%f%d,%%f%d\n", src+1, dst+1);
411 int dst = getregnum(p);
412 int src = getregnum(p->x.kids[0]);
413 print("fnegs %%f%d,%%f%d; ", src, dst);
414 print("fmovs %%f%d,%%f%d\n", src+1, dst+1);
418 static int tmpregs[] = { 1, 2, 3 };
419 dalign = salign = p->syms[1]->u.c.v.i;
420 blkcopy(getregnum(p->x.kids[0]), 0,
421 getregnum(p->x.kids[1]), 0,
422 p->syms[0]->u.c.v.i, tmpregs);
427 static void local(p) Symbol p; {
429 p->x.name = stringd(4*16);
434 if (isscalar(p->type) && !p->addressed && !isfloat(p->type))
435 p->sclass = REGISTER;
436 if (glevel && glevel != 3) p->sclass = AUTO; /* glevel!=3 is for Norman's debugger */
437 if (askregvar(p, rmap[ttob(p->type)]) == 0)
440 static void function(f, caller, callee, ncalls)
441 Symbol f, callee[], caller[]; int ncalls; {
442 int autos = 0, i, leaf, reg, varargs;
444 for (i = 0; callee[i]; i++)
446 varargs = variadic(f->type)
447 || i > 0 && strcmp(callee[i-1]->name,
448 "__builtin_va_alist") == 0;
449 usedmask[0] = usedmask[1] = 0;
450 freemask[0] = freemask[1] = ~(unsigned)0;
451 for (i = 0; i < 8; i++)
452 ireg[i]->x.regnode->vbl = NULL;
456 for (i = 0; callee[i]; i++) {
457 Symbol p = callee[i], q = caller[i];
458 int size = roundup(q->type->size, 4);
460 if (isfloat(p->type) || reg >= 6) {
461 p->x.offset = q->x.offset = offset;
462 p->x.name = q->x.name = stringd(offset);
463 p->sclass = q->sclass = AUTO;
466 else if (p->addressed || varargs)
468 p->x.offset = offset;
469 p->x.name = stringd(p->x.offset);
471 q->sclass = REGISTER;
472 askregvar(q, ireg[reg]);
473 assert(q->x.regnode);
476 else if (glevel && glevel != 3) {
477 p->x.offset = offset;
478 p->x.name = stringd(p->x.offset);
480 q->sclass = REGISTER;
481 askregvar(q, ireg[reg]);
482 assert(q->x.regnode);
487 p->sclass = q->sclass = REGISTER;
488 askregvar(p, ireg[reg]);
489 assert(p->x.regnode);
490 q->x.name = p->x.name;
493 reg += isstruct(p->type) ? 1 : size/4;
495 assert(caller[i] == 0);
496 offset = maxoffset = 0;
497 retstruct = isstruct(freturn(f->type));
498 gencode(caller, callee);
499 maxargoffset = roundup(maxargoffset, 4);
500 framesize = roundup(maxoffset + maxargoffset + 4*(16+1), 8);
501 assert(!varargs || autos);
503 && !maxoffset && !autos
504 && !isstruct(freturn(f->type))
505 && !(usedmask[IREG]&0x00ffff01)
506 && !(usedmask[FREG]&~(unsigned)3)
507 && !pflag && !glevel);
508 print(".align 4\n.proc 4\n%s:\n", f->x.name);
510 for (i = 0; caller[i] && callee[i]; i++) {
511 Symbol p = caller[i], q = callee[i];
512 if (p->sclass == REGISTER && q->sclass == REGISTER)
513 assert(q->x.regnode),
514 assert(q->x.regnode->set == IREG),
515 assert(q->x.regnode->number >= 24),
516 assert(q->x.regnode->number <= 31),
517 p->x.name = greg[q->x.regnode->number - 16]->x.name;
520 } else if (framesize <= 4095)
521 print("save %%sp,%d,%%sp\n", -framesize);
523 print("set %d,%%g1; save %%sp,%%g1,%%sp\n", -framesize);
525 for (; reg < 6; reg++)
526 print("st %%i%d,[%%fp+%d]\n", reg, 4*reg + 68);
530 for (i = 0; caller[i]; i++) {
531 Symbol p = caller[i];
532 if (isdouble(p->type) && reg <= 4) {
533 print("st %%r%d,[%%fp+%d]\n",
534 ireg[reg++]->x.regnode->number, offset);
535 print("st %%r%d,[%%fp+%d]\n",
536 ireg[reg++]->x.regnode->number, offset + 4);
537 } else if (isfloat(p->type) && reg <= 5)
538 print("st %%r%d,[%%fp+%d]\n",
539 ireg[reg++]->x.regnode->number, offset);
542 offset += roundup(p->type->size, 4);
545 int lab = genlabel(1);
546 print("set L%d,%%o0; call mcount; nop\n", lab);
547 print(".seg \"data\"\n.align 4; L%d:.word 0\n.seg \"text\"\n", lab);
551 print("ret; restore\n");
554 print("retl; nop\n");
557 #define exch(x, y, t) (((t) = x), ((x) = (y)), ((y) = (t)))
559 static void rename() {
562 for (i = 0; i < 8; i++) {
565 if (ireg[i]->x.regnode->vbl)
566 ireg[i]->x.regnode->vbl->x.name = oreg[i]->x.name;
567 exch(ireg[i]->x.name, oreg[i]->x.name, ptmp);
568 exch(ireg[i]->x.regnode->number,
569 oreg[i]->x.regnode->number, itmp);
572 static void defconst(ty, v) int ty; Value v; {
574 case C: print(".byte %d\n", v.uc); return;
575 case S: print(".half %d\n", v.ss); return;
576 case I: print(".word %d\n", v.i ); return;
577 case U: print(".word 0x%x\n", v.u ); return;
578 case P: print(".word 0x%x\n", v.p ); return;
580 print(".word 0x%x\n", *(unsigned *)&v.f);
583 unsigned *p = (unsigned *)&v.d;
584 print(".word 0x%x\n.word 0x%x\n", p[swap], p[!swap]);
591 static void defaddress(p) Symbol p; {
592 print(".word %s\n", p->x.name);
595 static void defstring(n, str) int n; char *str; {
598 for (s = str; s < str + n; s++)
599 print(".byte %d\n", (*s)&0377);
602 static void address(q, p, n) Symbol q, p; int n; {
603 q->x.offset = p->x.offset + n;
604 if (p->scope == GLOBAL || p->sclass == STATIC || p->sclass == EXTERN)
605 q->x.name = stringf("%s%s%d", p->x.name, n >= 0 ? "+" : "", n);
607 q->x.name = stringd(q->x.offset);
609 static void export(p) Symbol p; {
610 print(".global %s\n", p->x.name);
612 static void import(p) Symbol p; {}
613 static void defsymbol(p) Symbol p; {
614 if (p->scope >= LOCAL && p->sclass == STATIC)
615 p->x.name = stringf("%d", genlabel(1));
617 assert(p->scope != CONSTANTS || isint(p->type) || isptr(p->type)),
619 if (p->scope >= LABELS)
620 p->x.name = stringf(p->generated ? "L%s" : "_%s",
623 static void segment(n) int n; {
626 case CODE: print(".seg \"text\"\n"); break;
627 case BSS: print(".seg \"bss\"\n"); break;
628 case DATA: print(".seg \"data\"\n"); break;
629 case LIT: print(".seg \"text\"\n"); break;
632 static void space(n) int n; {
634 print(".skip %d\n", n);
636 static void global(p) Symbol p; {
637 print(".align %d\n", p->type->align);
640 && (p->sclass == STATIC || Aflag >= 2))
641 print(".reserve %s,%d\n", p->x.name, p->type->size);
642 else if (p->u.seg == BSS)
643 print(".common %s,%d\n", p->x.name, p->type->size);
645 print("%s:\n", p->x.name);
647 static void blkfetch(k, off, reg, tmp)
648 int k, off, reg, tmp; {
649 assert(k == 1 || k == 2 || k == 4);
652 print("ldub [%%r%d+%d],%%r%d\n", reg, off, tmp);
654 print("lduh [%%r%d+%d],%%r%d\n", reg, off, tmp);
656 print("ld [%%r%d+%d],%%r%d\n", reg, off, tmp);
658 static void blkstore(k, off, reg, tmp)
659 int k, off, reg, tmp; {
660 assert(k == 1 || k == 2 || k == 4);
663 print("stb %%r%d,[%%r%d+%d]\n", tmp, reg, off);
665 print("sth %%r%d,[%%r%d+%d]\n", tmp, reg, off);
667 print("st %%r%d,[%%r%d+%d]\n", tmp, reg, off);
669 static void blkloop(dreg, doff, sreg, soff, size, tmps)
670 int dreg, doff, sreg, soff, size, tmps[]; {
671 if ((size&~7) < 4096) {
672 print("add %%r%d,%d,%%r%d\n", sreg, size&~7, sreg);
673 print("add %%r%d,%d,%%r%d\n", dreg, size&~7, tmps[2]);
675 print("set %d,%%r%d\n", size&~7, tmps[2]);
676 print("add %%r%d,%%r%d,%%r%d\n", sreg, tmps[2], sreg);
677 print("add %%r%d,%%r%d,%%r%d\n", dreg, tmps[2], tmps[2]);
679 blkcopy(tmps[2], doff, sreg, soff, size&7, tmps);
680 print("1: dec 8,%%r%d\n", tmps[2]);
681 blkcopy(tmps[2], doff, sreg, soff - 8, 8, tmps);
682 print("cmp %%r%d,%%r%d; ", tmps[2], dreg);
684 print("dec 8,%%r%d\n", sreg);
686 static void defsymbol2(p) Symbol p; {
687 if (p->scope >= LOCAL && p->sclass == STATIC)
688 p->x.name = stringf(".%d", genlabel(1));
690 assert(p->scope != CONSTANTS || isint(p->type) || isptr(p->type)),
692 if (p->scope >= LABELS)
693 p->x.name = stringf(p->generated ? ".L%s" : "%s",
697 static void global2(p) Symbol p; {
699 if (p->sclass != STATIC && !p->generated)
700 print(".type %s,#%s\n", p->x.name,
701 isfunc(p->type) ? "function" : "object");
702 if (p->u.seg == BSS && p->sclass == STATIC)
703 print(".local %s\n.common %s,%d,%d\n", p->x.name, p->x.name,
704 p->type->size, p->type->align);
705 else if (p->u.seg == BSS && Aflag >= 2)
706 print(".align %d\n%s:.skip %d\n", p->type->align, p->x.name,
708 else if (p->u.seg == BSS)
709 print(".common %s,%d,%d\n", p->x.name, p->type->size, p->type->align);
711 print(".align %d\n%s:\n", p->type->align, p->x.name);
714 static void segment2(n) int n; {
717 case CODE: print(".section \".text\"\n"); break;
718 case BSS: print(".section \".bss\"\n"); break;
719 case DATA: print(".section \".data\"\n"); break;
720 case LIT: print(".section \".rodata\"\n"); break;
725 static char *currentfile; /* current file name */
728 static void stabblock ARGS((int, int, Symbol*));
729 static void stabfend ARGS((Symbol, int));
730 static void stabinit ARGS((char *, int, char *[]));
731 static void stabline ARGS((Coordinate *));
732 static void stabsym ARGS((Symbol));
733 static void stabtype ARGS((Symbol));
735 static void asgncode ARGS((Type, int));
736 static void dbxout ARGS((Type));
737 static int dbxtype ARGS((Type));
738 static int emittype ARGS((Type, int, int));
740 /* asgncode - assign type code to ty */
741 static void asgncode(ty, lev) Type ty; int lev; {
742 if (ty->x.marked || ty->x.typeno)
746 case VOLATILE: case CONST: case VOLATILE+CONST:
747 asgncode(ty->type, lev);
748 ty->x.typeno = ty->type->x.typeno;
750 case POINTER: case FUNCTION: case ARRAY:
751 asgncode(ty->type, lev + 1);
753 case VOID: case CHAR: case SHORT: case INT: case UNSIGNED:
754 case FLOAT: case DOUBLE:
756 case STRUCT: case UNION: {
758 for (p = fieldlist(ty); p; p = p->link)
759 asgncode(p->type, lev + 1);
762 if (ty->x.typeno == 0)
763 ty->x.typeno = ++ntypes;
764 if (lev > 0 && (*ty->u.sym->name < '0' || *ty->u.sym->name > '9'))
773 /* dbxout - output .stabs entry for type ty */
774 static void dbxout(ty) Type ty; {
776 if (!ty->x.printed) {
778 print(".stabs \""), col += 8;
779 if (ty->u.sym && !(isfunc(ty) || isarray(ty) || isptr(ty)))
780 print("%s", ty->u.sym->name), col += strlen(ty->u.sym->name);
781 print(":%c", isstruct(ty) || isenum(ty) ? 'T' : 't'), col += 2;
782 emittype(ty, 0, col);
783 print("\",%d,0,0,0\n", N_LSYM);
787 /* dbxtype - emit a stabs entry for type ty, return type code */
788 static int dbxtype(ty) Type ty; {
795 * emittype - emit ty's type number, emitting its definition if necessary.
796 * Returns the output column number after emission; col is the approximate
797 * output column before emission and is used to emit continuation lines for long
798 * struct, union, and enum types. Continuations are not emitted for other types,
799 * even if the definition is long. lev is the depth of calls to emittype.
801 static int emittype(ty, lev, col) Type ty; int lev, col; {
802 int tc = ty->x.typeno;
804 if (isconst(ty) || isvolatile(ty)) {
805 col = emittype(ty->type, lev, col);
806 ty->x.typeno = ty->type->x.typeno;
811 ty->x.typeno = tc = ++ntypes;
812 /* fprint(2,"`%t'=%d\n", ty, tc); */
814 print("%d", tc), col += 3;
819 case VOID: /* void is defined as itself */
820 print("=%d", tc), col += 1+3;
822 case CHAR: /* unsigned char is a subrange of int */
823 if (ty == unsignedchar)
824 print("=r1;0;255;"), col += 10;
825 else /* following pcc, char is a subrange of itself */
826 print("=r%d;-128;127;", tc), col += 2+3+10;
828 case SHORT: /* short is a subrange of int */
829 if (ty == unsignedshort)
830 print("=r1;0;65535;"), col += 12;
832 print("=r1;-32768;32767;"), col += 17;
834 case INT: /* int is a subrange of itself */
835 print("=r1;%d;%d;", INT_MIN, INT_MAX), col += 4+11+1+10+1;
837 case UNSIGNED: /* unsigned is a subrange of int */
838 print("=r1;0;-1;"), col += 9;
840 case FLOAT: case DOUBLE: /* float, double get sizes instead of ranges */
841 print("=r1;%d;0;", ty->size), col += 4+1+3;
844 print("=*"), col += 2;
845 col = emittype(ty->type, lev + 1, col);
848 print("=f"), col += 2;
849 col = emittype(ty->type, lev + 1, col);
851 case ARRAY: /* array includes subscript as an int range */
852 if (ty->size && ty->type->size)
853 print("=ar1;0;%d;", ty->size/ty->type->size - 1), col += 7+3+1;
855 print("=ar1;0;-1;"), col += 10;
856 col = emittype(ty->type, lev + 1, col);
858 case STRUCT: case UNION: {
860 if (!ty->u.sym->defined) {
861 print("=x%c%s:", ty->op == STRUCT ? 's' : 'u', ty->u.sym->name);
862 col += 2+1+strlen(ty->u.sym->name)+1;
865 if (lev > 0 && (*ty->u.sym->name < '0' || *ty->u.sym->name > '9')) {
869 print("=%c%d", ty->op == STRUCT ? 's' : 'u', ty->size), col += 1+1+3;
870 for (p = fieldlist(ty); p; p = p->link) {
872 print("%s:", p->name), col += strlen(p->name)+1;
874 print(":"), col += 1;
875 col = emittype(p->type, lev + 1, col);
877 print(",%d,%d;", 8*p->offset +
878 (IR->little_endian ? fieldright(p) : fieldleft(p)),
881 print(",%d,%d;", 8*p->offset, 8*p->type->size);
882 col += 1+3+1+3+1; /* accounts for ,%d,%d; */
883 if (col >= 80 && p->link) {
884 print("\\\\\",%d,0,0,0\n.stabs \"", N_LSYM);
888 print(";"), col += 1;
893 if (lev > 0 && (*ty->u.sym->name < '0' || *ty->u.sym->name > '9')) {
897 print("=e"), col += 2;
898 for (p = ty->u.sym->u.idlist; *p; p++) {
899 print("%s:%d,", (*p)->name, (*p)->u.value), col += strlen((*p)->name)+3;
900 if (col >= 80 && p[1]) {
901 print("\\\\\",%d,0,0,0\n.stabs \"", N_LSYM);
905 print(";"), col += 1;
914 /* stabblock - output a stab entry for '{' or '}' at level lev */
915 static void stabblock(brace, lev, p) int brace, lev; Symbol *p; {
919 print(".stabd 0x%x,0,%d\n", brace == '{' ? N_LBRAC : N_RBRAC, lev);
922 /* stabfend - end of function p */
923 static void stabfend(p, line) Symbol p; int line; {}
925 /* stabinit - initialize stab output */
926 static void stabinit(file, argc, argv) int argc; char *file, *argv[]; {
927 typedef void (*Closure) ARGS((Symbol, void *));
930 (*IR->segment)(CODE);
931 print("Ltext:.stabs \"%s\",0x%x,0,0,Ltext\n", file, N_SO);
942 dbxtype(unsignedchar);
943 dbxtype(unsignedlong);
944 dbxtype(unsignedshort);
945 dbxtype(unsignedtype);
947 foreach(types, GLOBAL, (Closure)stabtype, NULL);
950 /* stabline - emit stab entry for source coordinate *cp */
951 static void stabline(cp) Coordinate *cp; {
952 if (cp->file && cp->file != currentfile) {
953 int lab = genlabel(1);
954 print("L%d: .stabs \"%s\",0x%x,0,0,L%d\n", lab,
955 cp->file, N_SOL, lab);
956 currentfile = cp->file;
958 print(".stabd 0x%x,0,%d\n", N_SLINE, cp->y);
961 /* stabsym - output a stab entry for symbol p */
962 static void stabsym(p) Symbol p; {
963 int code, tc, sz = p->type->size;
965 if (p->generated || p->computed)
967 if (isfunc(p->type)) {
968 print(".stabs \"%s:%c%d\",%d,0,0,%s\n", p->name,
969 p->sclass == STATIC ? 'f' : 'F', dbxtype(freturn(p->type)),
973 if (!IR->wants_argb && p->scope == PARAM && p->structarg) {
974 assert(isptr(p->type) && isstruct(p->type->type));
975 tc = dbxtype(p->type->type);
976 sz = p->type->type->size;
978 tc = dbxtype(p->type);
979 if (p->sclass == AUTO && p->scope == GLOBAL || p->sclass == EXTERN) {
980 print(".stabs \"%s:G", p->name);
982 } else if (p->sclass == STATIC) {
983 print(".stabs \"%s:%c%d\",%d,0,0,%s\n", p->name, p->scope == GLOBAL ? 'S' : 'V',
984 tc, p->u.seg == BSS ? N_LCSYM : N_STSYM, p->x.name);
986 } else if (p->sclass == REGISTER) {
987 if (p->scope > PARAM) {
988 int r = p->x.regnode->number;
989 if (p->x.regnode->set == FREG)
990 r += 32; /* floating point */
991 print(".stabs \"%s:r%d\",%d,0,", p->name, tc, N_RSYM);
992 print("%d,%d\n", sz, r);
995 } else if (p->scope == PARAM) {
996 print(".stabs \"%s:p", p->name);
998 } else if (p->scope >= LOCAL) {
999 print(".stabs \"%s:", p->name);
1003 print("%d\",%d,0,0,%s\n", tc, code,
1004 p->scope >= PARAM && p->sclass != EXTERN ? p->x.name : "0");
1007 /* stabtype - output a stab entry for type *p */
1008 static void stabtype(p) Symbol p; {
1012 else if (p->sclass == TYPEDEF)
1013 print(".stabs \"%s:t%d\",%d,0,0,0\n", p->name, dbxtype(p->type), N_LSYM);
1023 Interface sparcIR = {
1025 2, 2, 0, /* short */
1027 4, 4, 1, /* float */
1028 8, 8, 1, /* double */
1030 0, 1, 0, /* struct */
1031 0, /* little_endian */
1032 1, /* mulops_calls */
1033 1, /* wants_callb */
1035 1, /* left_to_right */
1055 stabblock, 0, 0, stabinit, stabline, stabsym, stabtype,
1057 1, /* max_unaligned_load */
1058 blkfetch, blkstore, blkloop,
1077 Interface solarisIR = {
1079 2, 2, 0, /* short */
1081 4, 4, 1, /* float */
1082 8, 8, 1, /* double */
1084 0, 1, 0, /* struct */
1085 0, /* little_endian */
1086 1, /* mulops_calls */
1087 1, /* wants_callb */
1089 1, /* left_to_right */
1109 stabblock, 0, 0, stabinit, stabline, stabsym, stabtype,
1111 1, /* max_unaligned_load */
1112 blkfetch, blkstore, blkloop,