|
|
1.1 root 1: #include <u.h>
2: #include <libc.h>
3: #include <bio.h>
4: #include <ctype.h>
5: #define Extern extern
6: #include "parl.h"
7: #include "globl.h"
8:
9: /* These are machine specific convs which generate no code */
10: ulong
11: nopconv[Ntype] =
12: {
13: 0, /* TXXX */
14: MINT|MUINT|MIND, /* TINT */
15: MINT|MUINT|MIND, /* TUINT */
16: MSINT|MSUINT, /* TSINT */
17: MSINT|MSUINT, /* TSUINT */
18: MCHAR, /* TCHAR */
19: MFLOAT, /* TFLOAT */
20: MINT|MUINT|MIND, /* TIND */
21: 0, /* TCHANNEL */
22: 0, /* TARRAY */
23: MAGGREGATE, /* TAGGREGATE */
24: MUNION, /* TUNION */
25: 0, /* TFUNC */
26: 0, /* TVOID */
27: TADT, /* TADT */
28: };
29:
30: Inst*
31: ai(void)
32: {
33: Inst *i;
34:
35: i = malloc(sizeof(Inst));
36: i->src1.type = A_NONE;
37: i->dst.type = A_NONE;
38: i->reg = Nreg;
39: i->next = 0;
40: i->lineno = iline;
41: return i;
42: }
43:
44: /* Emit an assembler instruction */
45: Inst*
46: instruction(int op, Node *s1, Node *s2, Node *dst)
47: {
48: Inst *i;
49:
50: i = ai();
51: i->op = op;
52: i->pc = pc++;
53:
54: if(s1)
55: mkaddr(s1, &i->src1, 1);
56:
57: if(s2 && s2 != dst) {
58: switch(s2->type) {
59: case OREGISTER:
60: break;
61: case OCONST:
62: if(s2->ival == 0) {
63: s2->reg = 0;
64: break;
65: }
66: /* Fall */
67: default:
68: fatal("inst %s %N,%N,%N", itab[op], s1, s2, dst);
69: }
70: if(s2->t->type == TFLOAT)
71: i->reg = s2->reg - Freg;
72: else
73: i->reg = s2->reg;
74: }
75:
76: if(dst) {
77: mkaddr(dst, &i->dst, 1);
78: if(i->dst.type == A_REG)
79: if(i->reg == i->dst.reg)
80: i->reg = Nreg;
81: }
82: ilink(i);
83: return ipc;
84: }
85:
86: void
87: ilink(Inst *i)
88: {
89: if(opt('c'))
90: print("(%d)%i\n", i->lineno, i);
91:
92: if(proghead)
93: ipc->next = i;
94: else
95: proghead = i;
96:
97: ipc = i;
98: }
99:
100: /* Back patch a branch */
101: void
102: label(Inst *i, ulong pc)
103: {
104: Adres *a;
105:
106: switch(i->op) {
107: case ABA:
108: case ABCC:
109: case ABCS:
110: case ABE:
111: case ABG:
112: case ABGE:
113: case ABGU:
114: case ABL:
115: case ABLE:
116: case ABLEU:
117: case ABN:
118: case ABNE:
119: case ABNEG:
120: case ABPOS:
121: case ABVC:
122: case ABVS:
123: case AJMPL:
124: case AJMP:
125: case AFBA:
126: case AFBE:
127: case AFBG:
128: case AFBGE:
129: case AFBL:
130: case AFBLE:
131: case AFBLG:
132: case AFBN:
133: case AFBNE:
134: case AFBO:
135: case AFBU:
136: case AFBUE:
137: case AFBUG:
138: case AFBUGE:
139: case AFBUL:
140: case AFBULE:
141: break;
142:
143: default:
144: fatal("label not branch");
145: }
146: a = &i->dst;
147: a->type = A_BRANCH;
148: a->ival = pc;
149: }
150:
151: /* Select code for arithmetic operations */
152: void
153: codmop(Node *o, Node *l, Node *r, Node *dst)
154: {
155: int op;
156:
157: op = AGOK;
158: switch(o->type) {
159: case OADD:
160: case OADDEQ:
161: switch(o->t->type) {
162: default:
163: op = AADD;
164: break;
165: case TFLOAT:
166: op = AFADDD;
167: break;
168: }
169: break;
170:
171: case OSUB:
172: case OSUBEQ:
173: switch(o->t->type) {
174: default:
175: op = ASUB;
176: break;
177: case TFLOAT:
178: op = AFSUBD;
179: break;
180: }
181: break;
182:
183: case OMUL:
184: case OMULEQ:
185: switch(o->t->type) {
186: default:
187: op = AMUL;
188: break;
189: case TFLOAT:
190: op = AFMULD;
191: break;
192: }
193: break;
194:
195: case ODIV:
196: case ODIVEQ:
197: switch(o->t->type) {
198: default:
199: op = ADIV;
200: break;
201: case TUINT:
202: case TSUINT:
203: op = ADIVL;
204: break;
205: case TFLOAT:
206: op = AFDIVD;
207: break;
208: }
209: break;
210:
211: case OMOD:
212: case OMODEQ:
213: switch(o->t->type) {
214: default:
215: op = AMOD;
216: break;
217: case TUINT:
218: case TSUINT:
219: op = AMODL;
220: break;
221: }
222: break;
223:
224: case OALSH:
225: case OLSH:
226: case OLSHEQ:
227: op = ASLL;
228: break;
229:
230: case ORSH:
231: case ORSHEQ:
232: op = ASRL;
233: break;
234:
235: case OXOR:
236: case OXOREQ:
237: op = AXOR;
238: break;
239:
240: case OLOR:
241: case OOREQ:
242: op = AOR;
243: break;
244:
245: case OLAND:
246: case OANDEQ:
247: op = AAND;
248: break;
249:
250: case OARSH:
251: op = ASRA;
252: break;
253: }
254: instruction(op, l, r, dst);
255: }
256:
257: int
258: mulcon(Node *n, Node *nn)
259: {
260: int o;
261: long v;
262: Multab *m;
263: Node *l, *r, nod1, nod2, mop;
264: char code[sizeof(m->code)+2], *p;
265:
266: if(n->t->type == TFLOAT)
267: return 0;
268:
269: mop.t = n->t;
270: l = n->left;
271: r = n->right;
272: if(l->type == OCONST) {
273: l = r;
274: r = n->left;
275: }
276: if(r->type != OCONST)
277: return 0;
278:
279: v = r->ival;
280: m = mulcon0(v);
281: if(!m) {
282: if(opt('M'))
283: print("%L multiply table: %lld\n", r->ival);
284: return 0;
285: }
286: if(opt('M'))
287: print("%L multiply: %ld\n", v);
288:
289: memmove(code, m->code, sizeof(m->code));
290: code[sizeof(m->code)] = 0;
291:
292: p = code;
293: if(p[1] == 'i')
294: p += 2;
295: reg(&nod1, n->t, nn);
296: genexp(l, &nod1);
297: if(v < 0) {
298: mop.type = OSUB;
299: codmop(&mop, &nod1, con(0), &nod1);
300: }
301: reg(&nod2, n->t, ZeroN);
302:
303: for(;;) {
304: switch(*p) {
305: case '\0':
306: regfree(&nod2);
307: assign(&nod1, nn);
308: regfree(&nod1);
309: return 1;
310: case '+':
311: o = OADD;
312: goto addsub;
313: case '-':
314: o = OSUB;
315: addsub: /* number is r,n,l */
316: v = p[1] - '0';
317: r = &nod1;
318: if(v&4)
319: r = &nod2;
320: n = &nod1;
321: if(v&2)
322: n = &nod2;
323: l = &nod1;
324: if(v&1)
325: l = &nod2;
326: mop.type = o;
327: codmop(&mop, l, n, r);
328: break;
329: default: /* op is shiftcount, number is r,l */
330: v = p[1] - '0';
331: r = &nod1;
332: if(v&2)
333: r = &nod2;
334: l = &nod1;
335: if(v&1)
336: l = &nod2;
337: v = *p - 'a';
338: if(v < 0 || v >= 32) {
339: diag(n, "mulcon unknown op: %c%c", p[0], p[1]);
340: break;
341: }
342: mop.type = OALSH;
343: codmop(&mop, con(v), l, r);
344: break;
345: }
346: p += 2;
347: }
348: return 0;
349: }
350:
351: int
352: vconst(Node *n)
353: {
354: int i;
355:
356: if(n == ZeroN || n->type != OCONST || n->t == ZeroT)
357: return -159;
358:
359: switch(n->t->type) {
360: case TFLOAT:
361: i = 100;
362: if(n->fval > i || n->fval < -i)
363: return -159;
364: i = n->fval;
365: if(i != n->fval)
366: return -159;
367: return i;
368:
369: case TCHAR:
370: case TSINT:
371: case TSUINT:
372: case TINT:
373: case TUINT:
374: case TIND:
375: i = n->ival;
376: if(i != n->ival)
377: return -159;
378: return i;
379: }
380: }
381:
382: /* Select code for conditional operators */
383: void
384: codcond(int comp, Node *src1, Node *src2)
385: {
386: int a, t;
387:
388: if(src1->type == OCONST)
389: if(src1->ival == 0)
390: if(src1->t->type != TFLOAT)
391: src1 = regn(0);
392:
393: if(src2->type == OCONST)
394: if(src2->ival == 0)
395: if(src2->t->type != TFLOAT)
396: src2 = regn(0);
397:
398: t = src1->t->type;
399: switch(comp) {
400: default:
401: fatal("codcond: %N %s %N", src1, treeop[comp]+1, src2);
402:
403: case OEQ:
404: a = ABE;
405: if(t == TFLOAT)
406: a = AFBE;
407: break;
408:
409: case ONEQ:
410: a = ABNE;
411: if(t == TFLOAT)
412: a = AFBNE;
413: break;
414:
415: case OLT:
416: a = ABL;
417: if(t == TFLOAT)
418: a = AFBL;
419: break;
420:
421: case OGT:
422: a = ABG;
423: if(t == TFLOAT)
424: a = AFBG;
425: break;
426:
427: case OLEQ:
428: a = ABLE;
429: if(t == TFLOAT)
430: a = AFBLE;
431: break;
432:
433: case OGEQ:
434: a = ABGE;
435: if(t == TFLOAT)
436: a = AFBGE;
437: break;
438:
439: case OLO:
440: a = ABCS;
441: break;
442:
443: case OHI:
444: a = ABGU;
445: break;
446:
447: case OLOS:
448: a = ABLEU;
449: break;
450:
451: case OHIS:
452: a = ABCC;
453: break;
454: }
455:
456: if(t == TFLOAT)
457: instruction(AFCMPD,src1, ZeroN, src2);
458: else
459: instruction(ACMP, src1, ZeroN, src2);
460:
461: instruction(a, ZeroN, ZeroN, ZeroN);
462: }
463:
464: void
465: mkdata(Node *n, int off, int size, Inst *i)
466: {
467: Adres *a;
468:
469: if(n->type != ONAME)
470: fatal("mkdata %N\n", n);
471:
472: a = &i->src1;
473:
474: a->reg = Nreg;
475: a->ival = off;
476: a->sym = n->sym;
477: a->type = A_INDREG;
478: a->class = n->t->class;
479: a->etype = n->t->type;
480:
481: i->reg = size;
482: }
483:
484: void
485: mkaddr(Node *n, Adres *a, int ur0)
486: {
487: long o;
488: Tinfo *ti;
489:
490: a->sym = ZeroS;
491: a->reg = Nreg;
492:
493: switch(n->type) {
494: default:
495: fatal("mkaddr: %N\n", n);
496:
497: case ONAME:
498: ti = n->ti;
499:
500: a->type = A_INDREG;
501: a->etype = ti->t->type;
502: a->ival = ti->offset;
503: a->sym = n->sym;
504: if(ti->class == Argument) {
505: a->reg = RegSP;
506: a->class = A_NONE;
507: break;
508: }
509: a->class = ti->class;
510: break;
511:
512: case OCONST:
513: switch(n->t->type) {
514: default:
515: if(ur0 && n->ival == 0) {
516: a->type = A_REG;
517: a->reg = 0;
518: break;
519: }
520: a->type = A_CONST;
521: a->ival = n->ival;
522: break;
523: case TFLOAT:
524: a->type = A_FCONST;
525: a->fval = n->fval;
526: break;
527: }
528: break;
529:
530: case OADD:
531: if(n->left->type == OCONST) {
532: mkaddr(n->left, a, 0);
533: o = a->ival;
534: mkaddr(n->right, a, 1);
535: }
536: else {
537: mkaddr(n->right, a, 0);
538: o = a->ival;
539: mkaddr(n->left, a, 1);
540: }
541: a->ival += o;
542: break;
543:
544: case OINDREG:
545: a->type = A_INDREG;
546: a->reg = n->reg;
547: a->ival = n->ival;
548: break;
549:
550: case OREGISTER:
551: a->type = A_REG;
552: switch(n->t->type) {
553: default:
554: a->reg = n->reg;
555: break;
556:
557: case TFLOAT:
558: a->type = A_FREG;
559: if(n->reg == Retfreg)
560: a->reg = Retfregno;
561: else
562: a->reg = n->reg - Freg;
563: break;
564: }
565: break;
566:
567: case OIND:
568: mkaddr(n->left, a, 1);
569: if(a->type == A_REG || a->type == A_CONST)
570: a->type = A_INDREG;
571: break;
572:
573: case OADDR:
574: mkaddr(n->left, a, 1);
575: a->type = A_CONST;
576: a->ival += n->ival;
577: break;
578: }
579: }
580:
581: /* Generate function preamble and assign parameter offsets */
582: void
583: preamble(Node *name)
584: {
585: Inst *i;
586: Node *n;
587:
588: i = ai();
589: i->op = ATEXT;
590: i->pc = pc++;
591: i->lineno = name->srcline;
592:
593: n = an(0, ZeroN, ZeroN);
594: *n = *name;
595: n->type = ONAME;
596: mkaddr(n, &i->src1, 0);
597: mkaddr(con(0), &i->dst, 0);
598: ilink(i);
599: funentry = i; /* To back patch arg space */
600: becomentry = i;
601: }
602:
603: /* Output accumulated string constants */
604: void
605: strop(void)
606: {
607: String *s;
608: int c, l;
609: Inst *i;
610: char *p;
611:
612: for(s = strdat; s; s = s->next) {
613: i = ai();
614: i->op = AGLOBL;
615: mkaddr(&s->n, &i->src1, 0);
616: mkaddr(con(s->len), &i->dst, 0);
617: ilink(i);
618:
619: c = 0;
620: p = s->string;
621: while(s->len) {
622: l = s->len;
623: if(l > 8)
624: l = 8;
625:
626: iline = s->n.srcline;
627: i = ai();
628: i->op = ADATA;
629: i->dst.type = A_STRING;
630: memset(i->dst.str, 0, sizeof(i->dst.str));
631: memmove(i->dst.str, p, l);
632: s->len -= l;
633: mkdata(&s->n, c, l, i);
634: p += l;
635: c += l;
636: ilink(i);
637: }
638: }
639: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.