* added compilers lcc and bcc (linux86)
[mascara-docs.git] / compilers / lcc-4.2 / src / mips.md
blob4c86923c9ac967455b91c295ce2b0aa9e8db2bf7
1 %{
2 #define INTTMP 0x0100ff00
3 #define INTVAR 0x40ff0000
4 #define FLTTMP 0x000f0ff0
5 #define FLTVAR 0xfff00000
7 #define INTRET 0x00000004
8 #define FLTRET 0x00000003
10 #define readsreg(p) \
11         (generic((p)->op)==INDIR && (p)->kids[0]->op==VREG+P)
12 #define setsrc(d) ((d) && (d)->x.regnode && \
13         (d)->x.regnode->set == src->x.regnode->set && \
14         (d)->x.regnode->mask&src->x.regnode->mask)
16 #define relink(a, b) ((b)->x.prev = (a), (a)->x.next = (b))
18 #include "c.h"
19 #define NODEPTR_TYPE Node
20 #define OP_LABEL(p) ((p)->op)
21 #define LEFT_CHILD(p) ((p)->kids[0])
22 #define RIGHT_CHILD(p) ((p)->kids[1])
23 #define STATE_LABEL(p) ((p)->x.state)
24 static void address(Symbol, Symbol, long);
25 static void blkfetch(int, int, int, int);
26 static void blkloop(int, int, int, int, int, int[]);
27 static void blkstore(int, int, int, int);
28 static void defaddress(Symbol);
29 static void defconst(int, int, Value);
30 static void defstring(int, char *);
31 static void defsymbol(Symbol);
32 static void doarg(Node);
33 static void emit2(Node);
34 static void export(Symbol);
35 static void clobber(Node);
36 static void function(Symbol, Symbol [], Symbol [], int);
37 static void global(Symbol);
38 static void import(Symbol);
39 static void local(Symbol);
40 static void progbeg(int, char **);
41 static void progend(void);
42 static void segment(int);
43 static void space(int);
44 static void target(Node);
45 static int      bitcount       (unsigned);
46 static Symbol   argreg         (int, int, int, int, int);
48 static Symbol ireg[32], freg2[32], d6;
49 static Symbol iregw, freg2w;
50 static int tmpregs[] = {3, 9, 10};
51 static Symbol blkreg;
53 static int gnum = 8;
54 static int pic;
56 static int cseg;
58 %start stmt
59 %term CNSTF4=4113
60 %term CNSTF8=8209
61 %term CNSTF16=16401
62 %term CNSTI1=1045
63 %term CNSTI2=2069
64 %term CNSTI4=4117
65 %term CNSTI8=8213
66 %term CNSTP4=4119
67 %term CNSTP8=8215
68 %term CNSTU1=1046
69 %term CNSTU2=2070
70 %term CNSTU4=4118
71 %term CNSTU8=8214
73 %term ARGB=41
74 %term ARGF4=4129
75 %term ARGF8=8225
76 %term ARGF16=16417
77 %term ARGI4=4133
78 %term ARGI8=8229
79 %term ARGP4=4135
80 %term ARGP8=8231
81 %term ARGU4=4134
82 %term ARGU8=8230
84 %term ASGNB=57
85 %term ASGNF4=4145
86 %term ASGNF8=8241
87 %term ASGNF16=16433
88 %term ASGNI1=1077
89 %term ASGNI2=2101
90 %term ASGNI4=4149
91 %term ASGNI8=8245
92 %term ASGNP4=4151
93 %term ASGNP8=8247
94 %term ASGNU1=1078
95 %term ASGNU2=2102
96 %term ASGNU4=4150
97 %term ASGNU8=8246
99 %term INDIRB=73
100 %term INDIRF4=4161
101 %term INDIRF8=8257
102 %term INDIRF16=16449
103 %term INDIRI1=1093
104 %term INDIRI2=2117
105 %term INDIRI4=4165
106 %term INDIRI8=8261
107 %term INDIRP4=4167
108 %term INDIRP8=8263
109 %term INDIRU1=1094
110 %term INDIRU2=2118
111 %term INDIRU4=4166
112 %term INDIRU8=8262
114 %term CVFF4=4209
115 %term CVFF8=8305
116 %term CVFF16=16497
117 %term CVFI4=4213
118 %term CVFI8=8309
120 %term CVIF4=4225
121 %term CVIF8=8321
122 %term CVIF16=16513
123 %term CVII1=1157
124 %term CVII2=2181
125 %term CVII4=4229
126 %term CVII8=8325
127 %term CVIU1=1158
128 %term CVIU2=2182
129 %term CVIU4=4230
130 %term CVIU8=8326
132 %term CVPP4=4247
133 %term CVPP8=8343
134 %term CVPP16=16535
135 %term CVPU4=4246
136 %term CVPU8=8342
138 %term CVUI1=1205
139 %term CVUI2=2229
140 %term CVUI4=4277
141 %term CVUI8=8373
142 %term CVUP4=4279
143 %term CVUP8=8375
144 %term CVUP16=16567
145 %term CVUU1=1206
146 %term CVUU2=2230
147 %term CVUU4=4278
148 %term CVUU8=8374
150 %term NEGF4=4289
151 %term NEGF8=8385
152 %term NEGF16=16577
153 %term NEGI4=4293
154 %term NEGI8=8389
156 %term CALLB=217
157 %term CALLF4=4305
158 %term CALLF8=8401
159 %term CALLF16=16593
160 %term CALLI4=4309
161 %term CALLI8=8405
162 %term CALLP4=4311
163 %term CALLP8=8407
164 %term CALLU4=4310
165 %term CALLU8=8406
166 %term CALLV=216
168 %term RETF4=4337
169 %term RETF8=8433
170 %term RETF16=16625
171 %term RETI4=4341
172 %term RETI8=8437
173 %term RETP4=4343
174 %term RETP8=8439
175 %term RETU4=4342
176 %term RETU8=8438
177 %term RETV=248
179 %term ADDRGP4=4359
180 %term ADDRGP8=8455
182 %term ADDRFP4=4375
183 %term ADDRFP8=8471
185 %term ADDRLP4=4391
186 %term ADDRLP8=8487
188 %term ADDF4=4401
189 %term ADDF8=8497
190 %term ADDF16=16689
191 %term ADDI4=4405
192 %term ADDI8=8501
193 %term ADDP4=4407
194 %term ADDP8=8503
195 %term ADDU4=4406
196 %term ADDU8=8502
198 %term SUBF4=4417
199 %term SUBF8=8513
200 %term SUBF16=16705
201 %term SUBI4=4421
202 %term SUBI8=8517
203 %term SUBP4=4423
204 %term SUBP8=8519
205 %term SUBU4=4422
206 %term SUBU8=8518
208 %term LSHI4=4437
209 %term LSHI8=8533
210 %term LSHU4=4438
211 %term LSHU8=8534
213 %term MODI4=4453
214 %term MODI8=8549
215 %term MODU4=4454
216 %term MODU8=8550
218 %term RSHI4=4469
219 %term RSHI8=8565
220 %term RSHU4=4470
221 %term RSHU8=8566
223 %term BANDI4=4485
224 %term BANDI8=8581
225 %term BANDU4=4486
226 %term BANDU8=8582
228 %term BCOMI4=4501
229 %term BCOMI8=8597
230 %term BCOMU4=4502
231 %term BCOMU8=8598
233 %term BORI4=4517
234 %term BORI8=8613
235 %term BORU4=4518
236 %term BORU8=8614
238 %term BXORI4=4533
239 %term BXORI8=8629
240 %term BXORU4=4534
241 %term BXORU8=8630
243 %term DIVF4=4545
244 %term DIVF8=8641
245 %term DIVF16=16833
246 %term DIVI4=4549
247 %term DIVI8=8645
248 %term DIVU4=4550
249 %term DIVU8=8646
251 %term MULF4=4561
252 %term MULF8=8657
253 %term MULF16=16849
254 %term MULI4=4565
255 %term MULI8=8661
256 %term MULU4=4566
257 %term MULU8=8662
259 %term EQF4=4577
260 %term EQF8=8673
261 %term EQF16=16865
262 %term EQI4=4581
263 %term EQI8=8677
264 %term EQU4=4582
265 %term EQU8=8678
267 %term GEF4=4593
268 %term GEF8=8689
269 %term GEI4=4597
270 %term GEI8=8693
271 %term GEI16=16885
272 %term GEU4=4598
273 %term GEU8=8694
275 %term GTF4=4609
276 %term GTF8=8705
277 %term GTF16=16897
278 %term GTI4=4613
279 %term GTI8=8709
280 %term GTU4=4614
281 %term GTU8=8710
283 %term LEF4=4625
284 %term LEF8=8721
285 %term LEF16=16913
286 %term LEI4=4629
287 %term LEI8=8725
288 %term LEU4=4630
289 %term LEU8=8726
291 %term LTF4=4641
292 %term LTF8=8737
293 %term LTF16=16929
294 %term LTI4=4645
295 %term LTI8=8741
296 %term LTU4=4646
297 %term LTU8=8742
299 %term NEF4=4657
300 %term NEF8=8753
301 %term NEF16=16945
302 %term NEI4=4661
303 %term NEI8=8757
304 %term NEU4=4662
305 %term NEU8=8758
307 %term JUMPV=584
309 %term LABELV=600
311 %term LOADB=233
312 %term LOADF4=4321
313 %term LOADF8=8417
314 %term LOADF16=16609
315 %term LOADI1=1253
316 %term LOADI2=2277
317 %term LOADI4=4325
318 %term LOADI8=8421
319 %term LOADP4=4327
320 %term LOADP8=8423
321 %term LOADU1=1254
322 %term LOADU2=2278
323 %term LOADU4=4326
324 %term LOADU8=8422
326 %term VREGP=711
328 reg:  INDIRI1(VREGP)     "# read register\n"
329 reg:  INDIRU1(VREGP)     "# read register\n"
331 reg:  INDIRI2(VREGP)     "# read register\n"
332 reg:  INDIRU2(VREGP)     "# read register\n"
334 reg:  INDIRF4(VREGP)     "# read register\n"
335 reg:  INDIRI4(VREGP)     "# read register\n"
336 reg:  INDIRP4(VREGP)     "# read register\n"
337 reg:  INDIRU4(VREGP)     "# read register\n"
339 reg:  INDIRF8(VREGP)     "# read register\n"
340 reg:  INDIRI8(VREGP)     "# read register\n"
341 reg:  INDIRP8(VREGP)     "# read register\n"
342 reg:  INDIRU8(VREGP)     "# read register\n"
344 stmt: ASGNI1(VREGP,reg)  "# write register\n"
345 stmt: ASGNU1(VREGP,reg)  "# write register\n"
347 stmt: ASGNI2(VREGP,reg)  "# write register\n"
348 stmt: ASGNU2(VREGP,reg)  "# write register\n"
350 stmt: ASGNF4(VREGP,reg)  "# write register\n"
351 stmt: ASGNI4(VREGP,reg)  "# write register\n"
352 stmt: ASGNP4(VREGP,reg)  "# write register\n"
353 stmt: ASGNU4(VREGP,reg)  "# write register\n"
355 stmt: ASGNF8(VREGP,reg)  "# write register\n"
356 stmt: ASGNI8(VREGP,reg)  "# write register\n"
357 stmt: ASGNP8(VREGP,reg)  "# write register\n"
358 stmt: ASGNU8(VREGP,reg)  "# write register\n"
359 con: CNSTI1  "%a"
360 con: CNSTU1  "%a"
362 con: CNSTI2  "%a"
363 con: CNSTU2  "%a"
365 con: CNSTI4  "%a"
366 con: CNSTU4  "%a"
367 con: CNSTP4  "%a"
369 con: CNSTI8  "%a"
370 con: CNSTU8  "%a"
371 con: CNSTP8  "%a"
372 stmt: reg  ""
373 acon: con     "%0"
374 acon: ADDRGP4  "%a"
375 addr: ADDI4(reg,acon)  "%1($%0)"
376 addr: ADDU4(reg,acon)  "%1($%0)"
377 addr: ADDP4(reg,acon)  "%1($%0)"
378 addr: acon  "%0"
379 addr: reg   "($%0)"
380 addr: ADDRFP4  "%a+%F($sp)"
381 addr: ADDRLP4  "%a+%F($sp)"
382 reg: addr  "la $%c,%0\n"  1
383 reg: CNSTI1  "# reg\n"  range(a, 0, 0)
384 reg: CNSTI2  "# reg\n"  range(a, 0, 0)
385 reg: CNSTI4  "# reg\n"  range(a, 0, 0)
386 reg: CNSTU1  "# reg\n"  range(a, 0, 0)
387 reg: CNSTU2  "# reg\n"  range(a, 0, 0)
388 reg: CNSTU4  "# reg\n"  range(a, 0, 0)
389 reg: CNSTP4  "# reg\n"  range(a, 0, 0)
390 stmt: ASGNI1(addr,reg)  "sb $%1,%0\n"  1
391 stmt: ASGNU1(addr,reg)  "sb $%1,%0\n"  1
392 stmt: ASGNI2(addr,reg)  "sh $%1,%0\n"  1
393 stmt: ASGNU2(addr,reg)  "sh $%1,%0\n"  1
394 stmt: ASGNI4(addr,reg)  "sw $%1,%0\n"  1
395 stmt: ASGNU4(addr,reg)  "sw $%1,%0\n"  1
396 stmt: ASGNP4(addr,reg)  "sw $%1,%0\n"  1
397 reg:  INDIRI1(addr)     "lb $%c,%0\n"  1
398 reg:  INDIRU1(addr)     "lbu $%c,%0\n"  1
399 reg:  INDIRI2(addr)     "lh $%c,%0\n"  1
400 reg:  INDIRU2(addr)     "lhu $%c,%0\n"  1
401 reg:  INDIRI4(addr)     "lw $%c,%0\n"  1
402 reg:  INDIRU4(addr)     "lw $%c,%0\n"  1
403 reg:  INDIRP4(addr)     "lw $%c,%0\n"  1
405 reg:  CVII4(INDIRI1(addr))     "lb $%c,%0\n"  1
406 reg:  CVII4(INDIRI2(addr))     "lh $%c,%0\n"  1
407 reg:  CVUU4(INDIRU1(addr))     "lbu $%c,%0\n"  1
408 reg:  CVUU4(INDIRU2(addr))     "lhu $%c,%0\n"  1
409 reg:  CVUI4(INDIRU1(addr))     "lbu $%c,%0\n"  1
410 reg:  CVUI4(INDIRU2(addr))     "lhu $%c,%0\n"  1
411 reg:  INDIRF4(addr)     "l.s $f%c,%0\n"  1
412 reg:  INDIRF8(addr)     "l.d $f%c,%0\n"  1
413 stmt: ASGNF4(addr,reg)  "s.s $f%1,%0\n"  1
414 stmt: ASGNF8(addr,reg)  "s.d $f%1,%0\n"  1
415 reg: DIVI4(reg,reg)  "div $%c,$%0,$%1\n"   1
416 reg: DIVU4(reg,reg)  "divu $%c,$%0,$%1\n"  1
417 reg: MODI4(reg,reg)  "rem $%c,$%0,$%1\n"   1
418 reg: MODU4(reg,reg)  "remu $%c,$%0,$%1\n"  1
419 reg: MULI4(reg,reg)  "mul $%c,$%0,$%1\n"   1
420 reg: MULU4(reg,reg)  "mul $%c,$%0,$%1\n"   1
421 rc:  con            "%0"
422 rc:  reg            "$%0"
424 reg: ADDI4(reg,rc)   "addu $%c,$%0,%1\n"  1
425 reg: ADDP4(reg,rc)   "addu $%c,$%0,%1\n"  1
426 reg: ADDU4(reg,rc)   "addu $%c,$%0,%1\n"  1
427 reg: BANDI4(reg,rc)  "and $%c,$%0,%1\n"   1
428 reg: BORI4(reg,rc)   "or $%c,$%0,%1\n"    1
429 reg: BXORI4(reg,rc)  "xor $%c,$%0,%1\n"   1
430 reg: BANDU4(reg,rc)  "and $%c,$%0,%1\n"   1
431 reg: BORU4(reg,rc)   "or $%c,$%0,%1\n"    1
432 reg: BXORU4(reg,rc)  "xor $%c,$%0,%1\n"   1
433 reg: SUBI4(reg,rc)   "subu $%c,$%0,%1\n"  1
434 reg: SUBP4(reg,rc)   "subu $%c,$%0,%1\n"  1
435 reg: SUBU4(reg,rc)   "subu $%c,$%0,%1\n"  1
436 rc5: CNSTI4         "%a"                range(a,0,31)
437 rc5: reg            "$%0"
439 reg: LSHI4(reg,rc5)  "sll $%c,$%0,%1\n"  1
440 reg: LSHU4(reg,rc5)  "sll $%c,$%0,%1\n"  1
441 reg: RSHI4(reg,rc5)  "sra $%c,$%0,%1\n"  1
442 reg: RSHU4(reg,rc5)  "srl $%c,$%0,%1\n"  1
443 reg: BCOMI4(reg)  "not $%c,$%0\n"   1
444 reg: BCOMU4(reg)  "not $%c,$%0\n"   1
445 reg: NEGI4(reg)   "negu $%c,$%0\n"  1
446 reg: LOADI1(reg)  "move $%c,$%0\n"  move(a)
447 reg: LOADU1(reg)  "move $%c,$%0\n"  move(a)
448 reg: LOADI2(reg)  "move $%c,$%0\n"  move(a)
449 reg: LOADU2(reg)  "move $%c,$%0\n"  move(a)
450 reg: LOADI4(reg)  "move $%c,$%0\n"  move(a)
451 reg: LOADP4(reg)  "move $%c,$%0\n"  move(a)
452 reg: LOADU4(reg)  "move $%c,$%0\n"  move(a)
453 reg: ADDF4(reg,reg)  "add.s $f%c,$f%0,$f%1\n"  1
454 reg: ADDF8(reg,reg)  "add.d $f%c,$f%0,$f%1\n"  1
455 reg: DIVF4(reg,reg)  "div.s $f%c,$f%0,$f%1\n"  1
456 reg: DIVF8(reg,reg)  "div.d $f%c,$f%0,$f%1\n"  1
457 reg: MULF4(reg,reg)  "mul.s $f%c,$f%0,$f%1\n"  1
458 reg: MULF8(reg,reg)  "mul.d $f%c,$f%0,$f%1\n"  1
459 reg: SUBF4(reg,reg)  "sub.s $f%c,$f%0,$f%1\n"  1
460 reg: SUBF8(reg,reg)  "sub.d $f%c,$f%0,$f%1\n"  1
461 reg: LOADF4(reg)     "mov.s $f%c,$f%0\n"       move(a)
462 reg: LOADF8(reg)     "mov.d $f%c,$f%0\n"       move(a)
463 reg: NEGF4(reg)      "neg.s $f%c,$f%0\n"       1
464 reg: NEGF8(reg)      "neg.d $f%c,$f%0\n"       1
465 reg: CVII4(reg)  "sll $%c,$%0,8*(4-%a); sra $%c,$%c,8*(4-%a)\n"  2
466 reg: CVUI4(reg)  "and $%c,$%0,(1<<(8*%a))-1\n"  1
467 reg: CVUU4(reg)  "and $%c,$%0,(1<<(8*%a))-1\n"  1
468 reg: CVFF4(reg)  "cvt.s.d $f%c,$f%0\n"  1
469 reg: CVFF8(reg)  "cvt.d.s $f%c,$f%0\n"  1
470 reg: CVIF4(reg)  "mtc1 $%0,$f%c; cvt.s.w $f%c,$f%c\n"  2
471 reg: CVIF8(reg)  "mtc1 $%0,$f%c; cvt.d.w $f%c,$f%c\n"  2
472 reg: CVFI4(reg)  "trunc.w.s $f2,$f%0,$%c; mfc1 $%c,$f2\n"  (a->syms[0]->u.c.v.i==4?2:LBURG_MAX)
473 reg: CVFI4(reg)  "trunc.w.d $f2,$f%0,$%c; mfc1 $%c,$f2\n"  (a->syms[0]->u.c.v.i==8?2:LBURG_MAX)
474 stmt: LABELV  "%a:\n"
475 stmt: JUMPV(acon)  "b %0\n"   1
476 stmt: JUMPV(reg)   ".cpadd $%0\nj $%0\n"  !pic
477 stmt: JUMPV(reg)   "j $%0\n"  pic
478 stmt: EQI4(reg,reg)  "beq $%0,$%1,%a\n"   1
479 stmt: EQU4(reg,reg)  "beq $%0,$%1,%a\n"   1
480 stmt: GEI4(reg,reg)  "bge $%0,$%1,%a\n"   1
481 stmt: GEU4(reg,reg)  "bgeu $%0,$%1,%a\n"  1
482 stmt: GTI4(reg,reg)  "bgt $%0,$%1,%a\n"   1
483 stmt: GTU4(reg,reg)  "bgtu $%0,$%1,%a\n"  1
484 stmt: LEI4(reg,reg)  "ble $%0,$%1,%a\n"   1
485 stmt: LEU4(reg,reg)  "bleu $%0,$%1,%a\n"  1
486 stmt: LTI4(reg,reg)  "blt $%0,$%1,%a\n"   1
487 stmt: LTU4(reg,reg)  "bltu $%0,$%1,%a\n"  1
488 stmt: NEI4(reg,reg)  "bne $%0,$%1,%a\n"   1
489 stmt: NEU4(reg,reg)  "bne $%0,$%1,%a\n"   1
490 stmt: EQF4(reg,reg)  "c.eq.s $f%0,$f%1; bc1t %a\n"  2
491 stmt: EQF8(reg,reg)  "c.eq.d $f%0,$f%1; bc1t %a\n"  2
492 stmt: LEF4(reg,reg)  "c.ule.s $f%0,$f%1; bc1t %a\n"  2
493 stmt: LEF8(reg,reg)  "c.ule.d $f%0,$f%1; bc1t %a\n"  2
494 stmt: LTF4(reg,reg)  "c.ult.s $f%0,$f%1; bc1t %a\n"  2
495 stmt: LTF8(reg,reg)  "c.ult.d $f%0,$f%1; bc1t %a\n"  2
496 stmt: GEF4(reg,reg)  "c.lt.s $f%0,$f%1; bc1f %a\n"  2
497 stmt: GEF8(reg,reg)  "c.lt.d $f%0,$f%1; bc1f %a\n"  2
498 stmt: GTF4(reg,reg)  "c.le.s $f%0,$f%1; bc1f %a\n"  2
499 stmt: GTF8(reg,reg)  "c.le.d $f%0,$f%1; bc1f %a\n"  2
500 stmt: NEF4(reg,reg)  "c.eq.s $f%0,$f%1; bc1f %a\n"  2
501 stmt: NEF8(reg,reg)  "c.eq.d $f%0,$f%1; bc1f %a\n"  2
502 ar:   ADDRGP4     "%a"
504 reg:  CALLF4(ar)  "jal %0\n"  1
505 reg:  CALLF8(ar)  "jal %0\n"  1
506 reg:  CALLI4(ar)  "jal %0\n"  1
507 reg:  CALLP4(ar)  "jal %0\n"  1
508 reg:  CALLU4(ar)  "jal %0\n"  1
509 stmt: CALLV(ar)  "jal %0\n"  1
510 ar: reg    "$%0"
511 ar: CNSTP4  "%a"   range(a, 0, 0x0fffffff)
512 stmt: RETF4(reg)  "# ret\n"  1
513 stmt: RETF8(reg)  "# ret\n"  1
514 stmt: RETI4(reg)  "# ret\n"  1
515 stmt: RETU4(reg)  "# ret\n"  1
516 stmt: RETP4(reg)  "# ret\n"  1
517 stmt: RETV(reg)   "# ret\n"  1
518 stmt: ARGF4(reg)  "# arg\n"  1
519 stmt: ARGF8(reg)  "# arg\n"  1
520 stmt: ARGI4(reg)  "# arg\n"  1
521 stmt: ARGP4(reg)  "# arg\n"  1
522 stmt: ARGU4(reg)  "# arg\n"  1
524 stmt: ARGB(INDIRB(reg))       "# argb %0\n"      1
525 stmt: ASGNB(reg,INDIRB(reg))  "# asgnb %0 %1\n"  1
527 static void progend(void){}
528 static void progbeg(int argc, char *argv[]) {
529         int i;
531         {
532                 union {
533                         char c;
534                         int i;
535                 } u;
536                 u.i = 0;
537                 u.c = 1;
538                 swap = ((int)(u.i == 1)) != IR->little_endian;
539         }
540         print(".set reorder\n");
541         pic = !IR->little_endian;
542         parseflags(argc, argv);
543         for (i = 0; i < argc; i++)
544                 if (strncmp(argv[i], "-G", 2) == 0)
545                         gnum = atoi(argv[i] + 2);
546                 else if (strcmp(argv[i], "-pic=1") == 0
547                 ||       strcmp(argv[i], "-pic=0") == 0)
548                         pic = argv[i][5]-'0';
549         for (i = 0; i < 31; i += 2)
550                 freg2[i] = mkreg("%d", i, 3, FREG);
551         for (i = 0; i < 32; i++)
552                 ireg[i]  = mkreg("%d", i, 1, IREG);
553         ireg[29]->x.name = "sp";
554         d6 = mkreg("6", 6, 3, IREG);
555         freg2w = mkwildcard(freg2);
556         iregw = mkwildcard(ireg);
557         tmask[IREG] = INTTMP; tmask[FREG] = FLTTMP;
558         vmask[IREG] = INTVAR; vmask[FREG] = FLTVAR;
559         blkreg = mkreg("8", 8, 7, IREG);
561 static Symbol rmap(int opk) {
562         switch (optype(opk)) {
563         case I: case U: case P: case B:
564                 return iregw;
565         case F:
566                 return freg2w;
567         default:
568                 return 0;
569         }
571 static void target(Node p) {
572         assert(p);
573         switch (specific(p->op)) {
574         case CNST+I: case CNST+U: case CNST+P:
575                 if (range(p, 0, 0) == 0) {
576                         setreg(p, ireg[0]);
577                         p->x.registered = 1;
578                 }
579                 break;
580         case CALL+V:
581                 rtarget(p, 0, ireg[25]);
582                 break;
583         case CALL+F:
584                 rtarget(p, 0, ireg[25]);
585                 setreg(p, freg2[0]);
586                 break;
587         case CALL+I: case CALL+P: case CALL+U:
588                 rtarget(p, 0, ireg[25]);
589                 setreg(p, ireg[2]);
590                 break;
591         case RET+F:
592                 rtarget(p, 0, freg2[0]);
593                 break;
594         case RET+I: case RET+U: case RET+P:
595                 rtarget(p, 0, ireg[2]);
596                 break;
597         case ARG+F: case ARG+I: case ARG+P: case ARG+U: {
598                 static int ty0;
599                 int ty = optype(p->op);
600                 Symbol q;
602                 q = argreg(p->x.argno, p->syms[2]->u.c.v.i, ty, opsize(p->op), ty0);
603                 if (p->x.argno == 0)
604                         ty0 = ty;
605                 if (q &&
606                 !(ty == F && q->x.regnode->set == IREG))
607                         rtarget(p, 0, q);
608                 break;
609                 }
610         case ASGN+B: rtarget(p->kids[1], 0, blkreg); break;
611         case ARG+B:  rtarget(p->kids[0], 0, blkreg); break;
612         }
614 static void clobber(Node p) {
615         assert(p);
616         switch (specific(p->op)) {
617         case CALL+F:
618                 spill(INTTMP | INTRET, IREG, p);
619                 spill(FLTTMP,          FREG, p);
620                 break;
621         case CALL+I: case CALL+P: case CALL+U:
622                 spill(INTTMP,          IREG, p);
623                 spill(FLTTMP | FLTRET, FREG, p);
624                 break;
625         case CALL+V:
626                 spill(INTTMP | INTRET, IREG, p);
627                 spill(FLTTMP | FLTRET, FREG, p);
628                 break;
629         }
631 static void emit2(Node p) {
632         int dst, n, src, sz, ty;
633         static int ty0;
634         Symbol q;
636         switch (specific(p->op)) {
637         case ARG+F: case ARG+I: case ARG+P: case ARG+U:
638                 ty = optype(p->op);
639                 sz = opsize(p->op);
640                 if (p->x.argno == 0)
641                         ty0 = ty;
642                 q = argreg(p->x.argno, p->syms[2]->u.c.v.i, ty, sz, ty0);
643                 src = getregnum(p->x.kids[0]);
644                 if (q == NULL && ty == F && sz == 4)
645                         print("s.s $f%d,%d($sp)\n", src, p->syms[2]->u.c.v.i);
646                 else if (q == NULL && ty == F)
647                         print("s.d $f%d,%d($sp)\n", src, p->syms[2]->u.c.v.i);
648                 else if (q == NULL)
649                         print("sw $%d,%d($sp)\n", src, p->syms[2]->u.c.v.i);
650                 else if (ty == F && sz == 4 && q->x.regnode->set == IREG)
651                         print("mfc1 $%d,$f%d\n", q->x.regnode->number, src);
652                 else if (ty == F && q->x.regnode->set == IREG)
653                         print("mfc1.d $%d,$f%d\n", q->x.regnode->number, src);
654                 break;
655         case ASGN+B:
656                 dalign = salign = p->syms[1]->u.c.v.i;
657                 blkcopy(getregnum(p->x.kids[0]), 0,
658                         getregnum(p->x.kids[1]), 0,
659                         p->syms[0]->u.c.v.i, tmpregs);
660                 break;
661         case ARG+B:
662                 dalign = 4;
663                 salign = p->syms[1]->u.c.v.i;
664                 blkcopy(29, p->syms[2]->u.c.v.i,
665                         getregnum(p->x.kids[0]), 0,
666                         p->syms[0]->u.c.v.i, tmpregs);
667                 n   = p->syms[2]->u.c.v.i + p->syms[0]->u.c.v.i;
668                 dst = p->syms[2]->u.c.v.i;
669                 for ( ; dst <= 12 && dst < n; dst += 4)
670                         print("lw $%d,%d($sp)\n", (dst/4)+4, dst);
671                 break;
672         }
674 static Symbol argreg(int argno, int offset, int ty, int sz, int ty0) {
675         assert((offset&3) == 0);
676         if (offset > 12)
677                 return NULL;
678         else if (argno == 0 && ty == F)
679                 return freg2[12];
680         else if (argno == 1 && ty == F && ty0 == F)
681                 return freg2[14];
682         else if (argno == 1 && ty == F && sz == 8)
683                 return d6;  /* Pair! */
684         else
685                 return ireg[(offset/4) + 4];
687 static void doarg(Node p) {
688         static int argno;
689         int align;
691         if (argoffset == 0)
692                 argno = 0;
693         p->x.argno = argno++;
694         align = p->syms[1]->u.c.v.i < 4 ? 4 : p->syms[1]->u.c.v.i;
695         p->syms[2] = intconst(mkactual(align,
696                 p->syms[0]->u.c.v.i));
698 static void local(Symbol p) {
699         if (askregvar(p, rmap(ttob(p->type))) == 0)
700                 mkauto(p);
702 static void function(Symbol f, Symbol caller[], Symbol callee[], int ncalls) {
703         int i, saved, sizefsave, sizeisave, varargs;
704         Symbol r, argregs[4];
706         usedmask[0] = usedmask[1] = 0;
707         freemask[0] = freemask[1] = ~(unsigned)0;
708         offset = maxoffset = maxargoffset = 0;
709         for (i = 0; callee[i]; i++)
710                 ;
711         varargs = variadic(f->type)
712                 || i > 0 && strcmp(callee[i-1]->name, "va_alist") == 0;
713         for (i = 0; callee[i]; i++) {
714                 Symbol p = callee[i];
715                 Symbol q = caller[i];
716                 assert(q);
717                 offset = roundup(offset, q->type->align);
718                 p->x.offset = q->x.offset = offset;
719                 p->x.name = q->x.name = stringd(offset);
720                 r = argreg(i, offset, optype(ttob(q->type)), q->type->size, optype(ttob(caller[0]->type)));
721                 if (i < 4)
722                         argregs[i] = r;
723                 offset = roundup(offset + q->type->size, 4);
724                 if (varargs)
725                         p->sclass = AUTO;
726                 else if (r && ncalls == 0 &&
727                          !isstruct(q->type) && !p->addressed &&
728                          !(isfloat(q->type) && r->x.regnode->set == IREG)
729 ) {
730                         p->sclass = q->sclass = REGISTER;
731                         askregvar(p, r);
732                         assert(p->x.regnode && p->x.regnode->vbl == p);
733                         q->x = p->x;
734                         q->type = p->type;
735                 }
736                 else if (askregvar(p, rmap(ttob(p->type)))
737                          && r != NULL
738                          && (isint(p->type) || p->type == q->type)) {
739                         assert(q->sclass != REGISTER);
740                         p->sclass = q->sclass = REGISTER;
741                         q->type = p->type;
742                 }
743         }
744         assert(!caller[i]);
745         offset = 0;
746         gencode(caller, callee);
747         if (ncalls)
748                 usedmask[IREG] |= ((unsigned)1)<<31;
749         usedmask[IREG] &= 0xc0ff0000;
750         usedmask[FREG] &= 0xfff00000;
751         if (pic && ncalls)
752                 usedmask[IREG] |= 1<<25;
753         maxargoffset = roundup(maxargoffset, usedmask[FREG] ? 8 : 4);
754         if (ncalls && maxargoffset < 16)
755                 maxargoffset = 16;
756         sizefsave = 4*bitcount(usedmask[FREG]);
757         sizeisave = 4*bitcount(usedmask[IREG]);
758         framesize = roundup(maxargoffset + sizefsave
759                 + sizeisave + maxoffset, 16);
760         segment(CODE);
761         print(".align 2\n");
762         print(".ent %s\n", f->x.name);
763         print("%s:\n", f->x.name);
764         i = maxargoffset + sizefsave - framesize;
765         print(".frame $sp,%d,$31\n", framesize);
766         if (pic)
767                 print(".set noreorder\n.cpload $25\n.set reorder\n");
768         if (framesize > 0)
769                 print("addu $sp,$sp,%d\n", -framesize);
770         if (usedmask[FREG])
771                 print(".fmask 0x%x,%d\n", usedmask[FREG], i - 8);
772         if (usedmask[IREG])
773                 print(".mask 0x%x,%d\n",  usedmask[IREG],
774                         i + sizeisave - 4);
775         saved = maxargoffset;
776         for (i = 20; i <= 30; i += 2)
777                 if (usedmask[FREG]&(3<<i)) {
778                         print("s.d $f%d,%d($sp)\n", i, saved);
779                         saved += 8;
780                 }
782         for (i = 16; i <= 31; i++)
783                 if (usedmask[IREG]&(1<<i)) {
784                         if (i == 25)
785                                 print(".cprestore %d\n", saved);
786                         else
787                                 print("sw $%d,%d($sp)\n", i, saved);
788                         saved += 4;
789                 }
790         for (i = 0; i < 4 && callee[i]; i++) {
791                 r = argregs[i];
792                 if (r && r->x.regnode != callee[i]->x.regnode) {
793                         Symbol out = callee[i];
794                         Symbol in  = caller[i];
795                         int rn = r->x.regnode->number;
796                         int rs = r->x.regnode->set;
797                         int tyin = ttob(in->type);
799                         assert(out && in && r && r->x.regnode);
800                         assert(out->sclass != REGISTER || out->x.regnode);
801                         if (out->sclass == REGISTER
802                         && (isint(out->type) || out->type == in->type)) {
803                                 int outn = out->x.regnode->number;
804                                 if (rs == FREG && tyin == F+sizeop(8))
805                                         print("mov.d $f%d,$f%d\n", outn, rn);
806                                 else if (rs == FREG && tyin == F+sizeop(4))
807                                         print("mov.s $f%d,$f%d\n", outn, rn);
808                                 else if (rs == IREG && tyin == F+sizeop(8))
809                                         print("mtc1.d $%d,$f%d\n", rn,   outn);
810                                 else if (rs == IREG && tyin == F+sizeop(4))
811                                         print("mtc1 $%d,$f%d\n",   rn,   outn);
812                                 else
813                                         print("move $%d,$%d\n",    outn, rn);
814                         } else {
815                                 int off = in->x.offset + framesize;
816                                 if (rs == FREG && tyin == F+sizeop(8))
817                                         print("s.d $f%d,%d($sp)\n", rn, off);
818                                 else if (rs == FREG && tyin == F+sizeop(4))
819                                         print("s.s $f%d,%d($sp)\n", rn, off);
820                                 else {
821                                         int i, n = (in->type->size + 3)/4;
822                                         for (i = rn; i < rn+n && i <= 7; i++)
823                                                 print("sw $%d,%d($sp)\n", i, off + (i-rn)*4);
824                                 }
825                         }
826                 }
827         }
828         if (varargs && callee[i-1]) {
829                 i = callee[i-1]->x.offset + callee[i-1]->type->size;
830                 for (i = roundup(i, 4)/4; i <= 3; i++)
831                         print("sw $%d,%d($sp)\n", i + 4, framesize + 4*i);
832                 }
833         emitcode();
834         saved = maxargoffset;
835         for (i = 20; i <= 30; i += 2)
836                 if (usedmask[FREG]&(3<<i)) {
837                         print("l.d $f%d,%d($sp)\n", i, saved);
838                         saved += 8;
839                 }
840         for (i = 16; i <= 31; i++)
841                 if (usedmask[IREG]&(1<<i)) {
842                         print("lw $%d,%d($sp)\n", i, saved);
843                         saved += 4;
844                 }
845         if (framesize > 0)
846                 print("addu $sp,$sp,%d\n", framesize);
847         print("j $31\n");
848         print(".end %s\n", f->x.name);
850 static void defconst(int suffix, int size, Value v) {
851         if (suffix == F && size == 4) {
852                 float f = v.d;
853                 print(".word 0x%x\n", *(unsigned *)&f);
854         }
855         else if (suffix == F && size == 8) {
856                 double d = v.d;
857                 unsigned *p = (unsigned *)&d;
858                 print(".word 0x%x\n.word 0x%x\n", p[swap], p[!swap]);
859         }
860         else if (suffix == P)
861                 print(".word 0x%x\n", (unsigned)v.p);
862         else if (size == 1)
863                 print(".byte 0x%x\n", (unsigned)((unsigned char)(suffix == I ? v.i : v.u)));
864         else if (size == 2)
865                 print(".half 0x%x\n", (unsigned)((unsigned short)(suffix == I ? v.i : v.u)));
866         else if (size == 4)
867                 print(".word 0x%x\n", (unsigned)(suffix == I ? v.i : v.u));
869 static void defaddress(Symbol p) {
870         if (pic && p->scope == LABELS)
871                 print(".gpword %s\n", p->x.name);
872         else
873                 print(".word %s\n", p->x.name);
875 static void defstring(int n, char *str) {
876         char *s;
878         for (s = str; s < str + n; s++)
879                 print(".byte %d\n", (*s)&0377);
881 static void export(Symbol p) {
882         print(".globl %s\n", p->x.name);
884 static void import(Symbol p) {
885         if (!isfunc(p->type))
886                 print(".extern %s %d\n", p->name, p->type->size);
888 static void defsymbol(Symbol p) {
889         if (p->scope >= LOCAL && p->sclass == STATIC)
890                 p->x.name = stringf("L.%d", genlabel(1));
891         else if (p->generated)
892                 p->x.name = stringf("L.%s", p->name);
893         else
894                 assert(p->scope != CONSTANTS || isint(p->type) || isptr(p->type)),
895                 p->x.name = p->name;
897 static void address(Symbol q, Symbol p, long n) {
898         if (p->scope == GLOBAL
899         || p->sclass == STATIC || p->sclass == EXTERN)
900                 q->x.name = stringf("%s%s%D", p->x.name,
901                         n >= 0 ? "+" : "", n);
902         else {
903                 assert(n <= INT_MAX && n >= INT_MIN);
904                 q->x.offset = p->x.offset + n;
905                 q->x.name = stringd(q->x.offset);
906         }
908 static void global(Symbol p) {
909         if (p->u.seg == BSS) {
910                 if (p->sclass == STATIC || Aflag >= 2)
911                         print(".lcomm %s,%d\n", p->x.name, p->type->size);
912                 else
913                         print( ".comm %s,%d\n", p->x.name, p->type->size);
914         } else {
915                 if (p->u.seg == DATA
916                 && (p->type->size == 0 || p->type->size > gnum))
917                         print(".data\n");
918                 else if (p->u.seg == DATA)
919                         print(".sdata\n");
920                 print(".align %c\n", ".01.2...3"[p->type->align]);
921                 print("%s:\n", p->x.name);
922         }
924 static void segment(int n) {
925         cseg = n;
926         switch (n) {
927         case CODE: print(".text\n");  break;
928         case LIT:  print(".rdata\n"); break;
929         }
931 static void space(int n) {
932         if (cseg != BSS)
933                 print(".space %d\n", n);
935 static void blkloop(int dreg, int doff, int sreg, int soff, int size, int tmps[]) {
936         int lab = genlabel(1);
938         print("addu $%d,$%d,%d\n", sreg, sreg, size&~7);
939         print("addu $%d,$%d,%d\n", tmps[2], dreg, size&~7);
940         blkcopy(tmps[2], doff, sreg, soff, size&7, tmps);
941         print("L.%d:\n", lab);
942         print("addu $%d,$%d,%d\n", sreg, sreg, -8);
943         print("addu $%d,$%d,%d\n", tmps[2], tmps[2], -8);
944         blkcopy(tmps[2], doff, sreg, soff, 8, tmps);
945         print("bltu $%d,$%d,L.%d\n", dreg, tmps[2], lab);
947 static void blkfetch(int size, int off, int reg, int tmp) {
948         assert(size == 1 || size == 2 || size == 4);
949         if (size == 1)
950                 print("lbu $%d,%d($%d)\n",  tmp, off, reg);
951         else if (salign >= size && size == 2)
952                 print("lhu $%d,%d($%d)\n",  tmp, off, reg);
953         else if (salign >= size)
954                 print("lw $%d,%d($%d)\n",   tmp, off, reg);
955         else if (size == 2)
956                 print("ulhu $%d,%d($%d)\n", tmp, off, reg);
957         else
958                 print("ulw $%d,%d($%d)\n",  tmp, off, reg);
960 static void blkstore(int size, int off, int reg, int tmp) {
961         if (size == 1)
962                 print("sb $%d,%d($%d)\n",  tmp, off, reg);
963         else if (dalign >= size && size == 2)
964                 print("sh $%d,%d($%d)\n",  tmp, off, reg);
965         else if (dalign >= size)
966                 print("sw $%d,%d($%d)\n",  tmp, off, reg);
967         else if (size == 2)
968                 print("ush $%d,%d($%d)\n", tmp, off, reg);
969         else
970                 print("usw $%d,%d($%d)\n", tmp, off, reg);
972 static void stabinit(char *, int, char *[]);
973 static void stabline(Coordinate *);
974 static void stabsym(Symbol);
976 static char *currentfile;
978 static int bitcount(unsigned mask) {
979         unsigned i, n = 0;
981         for (i = 1; i; i <<= 1)
982                 if (mask&i)
983                         n++;
984         return n;
987 /* stabinit - initialize stab output */
988 static void stabinit(char *file, int argc, char *argv[]) {
989         if (file) {
990                 print(".file 2,\"%s\"\n", file);
991                 currentfile = file;
992         }
995 /* stabline - emit stab entry for source coordinate *cp */
996 static void stabline(Coordinate *cp) {
997         if (cp->file && cp->file != currentfile) {
998                 print(".file 2,\"%s\"\n", cp->file);
999                 currentfile = cp->file;
1000         }
1001         print(".loc 2,%d\n", cp->y);
1004 /* stabsym - output a stab entry for symbol p */
1005 static void stabsym(Symbol p) {
1006         if (p == cfunc && IR->stabline)
1007                 (*IR->stabline)(&p->src);
1009 Interface mipsebIR = {
1010         1, 1, 0,  /* char */
1011         2, 2, 0,  /* short */
1012         4, 4, 0,  /* int */
1013         4, 4, 0,  /* long */
1014         4, 4, 0,  /* long long */
1015         4, 4, 1,  /* float */
1016         8, 8, 1,  /* double */
1017         8, 8, 1,  /* long double */
1018         4, 4, 0,  /* T * */
1019         0, 1, 0,  /* struct */
1020         0,      /* little_endian */
1021         0,  /* mulops_calls */
1022         0,  /* wants_callb */
1023         1,  /* wants_argb */
1024         1,  /* left_to_right */
1025         0,  /* wants_dag */
1026         0,  /* unsigned_char */
1027         address,
1028         blockbeg,
1029         blockend,
1030         defaddress,
1031         defconst,
1032         defstring,
1033         defsymbol,
1034         emit,
1035         export,
1036         function,
1037         gen,
1038         global,
1039         import,
1040         local,
1041         progbeg,
1042         progend,
1043         segment,
1044         space,
1045         0, 0, 0, stabinit, stabline, stabsym, 0,
1046         {
1047                 4,      /* max_unaligned_load */
1048                 rmap,
1049                 blkfetch, blkstore, blkloop,
1050                 _label,
1051                 _rule,
1052                 _nts,
1053                 _kids,
1054                 _string,
1055                 _templates,
1056                 _isinstruction,
1057                 _ntname,
1058                 emit2,
1059                 doarg,
1060                 target,
1061                 clobber,
1063         }
1064 }, mipselIR = {
1065         1, 1, 0,  /* char */
1066         2, 2, 0,  /* short */
1067         4, 4, 0,  /* int */
1068         4, 4, 0,  /* long */
1069         4, 4, 0,  /* long long */
1070         4, 4, 1,  /* float */
1071         8, 8, 1,  /* double */
1072         8, 8, 1,  /* long double */
1073         4, 4, 0,  /* T * */
1074         0, 1, 0,  /* struct */
1075         1,      /* little_endian */
1076         0,  /* mulops_calls */
1077         0,  /* wants_callb */
1078         1,  /* wants_argb */
1079         1,  /* left_to_right */
1080         0,  /* wants_dag */
1081         0,  /* unsigned_char */
1082         address,
1083         blockbeg,
1084         blockend,
1085         defaddress,
1086         defconst,
1087         defstring,
1088         defsymbol,
1089         emit,
1090         export,
1091         function,
1092         gen,
1093         global,
1094         import,
1095         local,
1096         progbeg,
1097         progend,
1098         segment,
1099         space,
1100         0, 0, 0, stabinit, stabline, stabsym, 0,
1101         {
1102                 4,      /* max_unaligned_load */
1103                 rmap,
1104                 blkfetch, blkstore, blkloop,
1105                 _label,
1106                 _rule,
1107                 _nts,
1108                 _kids,
1109                 _string,
1110                 _templates,
1111                 _isinstruction,
1112                 _ntname,
1113                 emit2,
1114                 doarg,
1115                 target,
1116                 clobber,
1118         }
1120 static char rcsid[] = "$Id$";