1 /* Id: local2.c,v 1.186 2015/11/17 19:19:40 ragge Exp */
2 /* $NetBSD: local2.c,v 1.1.1.8 2016/02/09 20:28:17 plunky Exp $ */
3 /*
4 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 # include "pass2.h"
31 # include <ctype.h>
32 # include <string.h>
33
34 #if defined(PECOFFABI) || defined(MACHOABI) || defined(AOUTABI)
35 #define EXPREFIX "_"
36 #else
37 #define EXPREFIX ""
38 #endif
39
40 int msettings = MI686;
41 static int stkpos;
42
43 void
deflab(int label)44 deflab(int label)
45 {
46 printf(LABFMT ":\n", label);
47 }
48
49 static int regoff[7];
50 static TWORD ftype;
51
52 /*
53 * Print out the prolog assembler.
54 * addto and regoff are already calculated.
55 */
56 static void
prtprolog(struct interpass_prolog * ipp,int addto)57 prtprolog(struct interpass_prolog *ipp, int addto)
58 {
59 int i;
60
61 #if 1
62 #if defined(MACHOABI)
63 addto += 8;
64 #endif
65 if (addto == 0 || addto > 65535) {
66 printf(" pushl %%ebp\n\tmovl %%esp,%%ebp\n");
67 if (addto)
68 printf(" subl $%d,%%esp\n", addto);
69 } else
70 printf(" enter $%d,$0\n", addto);
71 #endif
72 for (i = 0; i < MAXREGS; i++)
73 if (TESTBIT(ipp->ipp_regs, i))
74 printf(" movl %s,-%d(%s)\n",
75 rnames[i], regoff[i], rnames[FPREG]);
76 }
77
78 /*
79 * calculate stack size and offsets
80 */
81 static int
offcalc(struct interpass_prolog * ipp)82 offcalc(struct interpass_prolog *ipp)
83 {
84 int i, addto;
85
86 addto = p2maxautooff;
87 if (addto >= AUTOINIT/SZCHAR)
88 addto -= AUTOINIT/SZCHAR;
89 for (i = 0; i < MAXREGS; i++)
90 if (TESTBIT(ipp->ipp_regs, i)) {
91 addto += SZINT/SZCHAR;
92 regoff[i] = addto;
93 }
94 return addto;
95 }
96
97 void
prologue(struct interpass_prolog * ipp)98 prologue(struct interpass_prolog *ipp)
99 {
100 int addto;
101
102 ftype = ipp->ipp_type;
103
104 #ifdef LANG_F77
105 if (ipp->ipp_vis)
106 printf(" .globl %s\n", ipp->ipp_name);
107 printf(" .align 4\n");
108 printf("%s:\n", ipp->ipp_name);
109 #endif
110 /*
111 * We here know what register to save and how much to
112 * add to the stack.
113 */
114 addto = offcalc(ipp);
115 #if defined(MACHOABI)
116 addto = (addto + 15) & ~15; /* stack alignment */
117 #endif
118 prtprolog(ipp, addto);
119 }
120
121 void
eoftn(struct interpass_prolog * ipp)122 eoftn(struct interpass_prolog *ipp)
123 {
124 int i;
125
126 if (ipp->ipp_ip.ip_lbl == 0)
127 return; /* no code needs to be generated */
128
129 /* return from function code */
130 for (i = 0; i < MAXREGS; i++)
131 if (TESTBIT(ipp->ipp_regs, i))
132 printf(" movl -%d(%s),%s\n",
133 regoff[i], rnames[FPREG], rnames[i]);
134
135 /* struct return needs special treatment */
136 if (ftype == STRTY || ftype == UNIONTY) {
137 printf(" movl 8(%%ebp),%%eax\n");
138 printf(" leave\n");
139 printf(" ret $%d\n", 4 + ipp->ipp_argstacksize);
140 } else {
141 printf(" leave\n");
142 if (ipp->ipp_argstacksize)
143 printf(" ret $%d\n", ipp->ipp_argstacksize);
144 else
145 printf(" ret\n");
146 }
147
148 #if defined(ELFABI)
149 printf("\t.size " EXPREFIX "%s,.-" EXPREFIX "%s\n", ipp->ipp_name,
150 ipp->ipp_name);
151 #endif
152 }
153
154 /*
155 * add/sub/...
156 *
157 * Param given:
158 */
159 void
hopcode(int f,int o)160 hopcode(int f, int o)
161 {
162 char *str;
163
164 switch (o) {
165 case PLUS:
166 str = "add";
167 break;
168 case MINUS:
169 str = "sub";
170 break;
171 case AND:
172 str = "and";
173 break;
174 case OR:
175 str = "or";
176 break;
177 case ER:
178 str = "xor";
179 break;
180 default:
181 comperr("hopcode2: %d", o);
182 str = 0; /* XXX gcc */
183 }
184 printf("%s%c", str, f);
185 }
186
187 /*
188 * Return type size in bytes. Used by R2REGS, arg 2 to offset().
189 */
190 int
tlen(NODE * p)191 tlen(NODE *p)
192 {
193 switch(p->n_type) {
194 case CHAR:
195 case UCHAR:
196 return(1);
197
198 case SHORT:
199 case USHORT:
200 return(SZSHORT/SZCHAR);
201
202 case DOUBLE:
203 return(SZDOUBLE/SZCHAR);
204
205 case INT:
206 case UNSIGNED:
207 case LONG:
208 case ULONG:
209 return(SZINT/SZCHAR);
210
211 case LONGLONG:
212 case ULONGLONG:
213 return SZLONGLONG/SZCHAR;
214
215 default:
216 if (!ISPTR(p->n_type))
217 comperr("tlen type %d not pointer");
218 return SZPOINT(p->n_type)/SZCHAR;
219 }
220 }
221
222 /*
223 * Emit code to compare two longlong numbers.
224 */
225 static void
twollcomp(NODE * p)226 twollcomp(NODE *p)
227 {
228 int u;
229 int s = getlab2();
230 int e = p->n_label;
231 int cb1, cb2;
232
233 u = p->n_op;
234 switch (p->n_op) {
235 case NE:
236 cb1 = 0;
237 cb2 = NE;
238 break;
239 case EQ:
240 cb1 = NE;
241 cb2 = 0;
242 break;
243 case LE:
244 case LT:
245 u += (ULE-LE);
246 /* FALLTHROUGH */
247 case ULE:
248 case ULT:
249 cb1 = GT;
250 cb2 = LT;
251 break;
252 case GE:
253 case GT:
254 u += (ULE-LE);
255 /* FALLTHROUGH */
256 case UGE:
257 case UGT:
258 cb1 = LT;
259 cb2 = GT;
260 break;
261
262 default:
263 cb1 = cb2 = 0; /* XXX gcc */
264 }
265 if (p->n_op >= ULE)
266 cb1 += 4, cb2 += 4;
267 expand(p, 0, " cmpl UR,UL\n");
268 if (cb1) cbgen(cb1, s);
269 if (cb2) cbgen(cb2, e);
270 expand(p, 0, " cmpl AR,AL\n");
271 cbgen(u, e);
272 deflab(s);
273 }
274
275 int
fldexpand(NODE * p,int cookie,char ** cp)276 fldexpand(NODE *p, int cookie, char **cp)
277 {
278 comperr("fldexpand");
279 return 0;
280 }
281
282 /*
283 * Push a structure on stack as argument.
284 * the scratch registers are already free here
285 */
286 static void
starg(NODE * p)287 starg(NODE *p)
288 {
289 struct attr *ap;
290 NODE *q = p->n_left;
291
292 ap = attr_find(p->n_ap, ATTR_P2STRUCT);
293 printf(" subl $%d,%%esp\n", (ap->iarg(0) + 3) & ~3);
294 p->n_left = mklnode(OREG, 0, ESP, INT);
295 zzzcode(p, 'Q');
296 tfree(p->n_left);
297 p->n_left = q;
298 }
299
300 /*
301 * Compare two floating point numbers.
302 */
303 static void
fcomp(NODE * p)304 fcomp(NODE *p)
305 {
306 static char *fpcb[] = { "jz", "jnz", "jbe", "jc", "jnc", "ja" };
307
308 if (msettings & MI686) {
309 if ((p->n_su & DORIGHT) == 0)
310 expand(p, 0, "\tfxch\n");
311 expand(p, 0, "\tfucomip %st(1),%st\n"); /* emit compare insn */
312 expand(p, 0, "\tfstp %st(0)\n"); /* pop fromstack */
313
314 if (p->n_op == NE || p->n_op == GT || p->n_op == GE)
315 expand(p, 0, "\tjp LC\n");
316 else if (p->n_op == EQ)
317 printf("\tjp 1f\n");
318 printf(" %s ", fpcb[p->n_op - EQ]);
319 expand(p, 0, "LC\n");
320 if (p->n_op == EQ)
321 printf("1:\n");
322 } else {
323 int swap = ((p->n_su & DORIGHT) == 0);
324
325 if (p->n_op == GT || p->n_op == GE)
326 swap ^= 1;
327 if (swap)
328 expand(p, 0, "\tfxch\n");
329
330 /*
331 * Flags for x87:
332 * C3 C2 C0
333 * 0 0 0 st0 > st1
334 * 0 0 1 st0 < st1
335 * 1 0 0 st0 = st1
336 * 1 1 1 unordered
337 */
338
339 /* ax avoided in nspecial() */
340 printf("\tfucompp\n\tfnstsw %%ax\n");
341 if (p->n_op == GE || p->n_op == LE) {
342 printf("\ttestb $0x45,%%ah\n");
343 } else if (p->n_op == GT || p->n_op == LT) {
344 printf("\ttestb $0x05,%%ah\n");
345 } else if (p->n_op == NE) {
346 printf("\tandb $0x45,%%ah\n");
347 printf("\txorb $0x40,%%ah\n");
348 } else if (p->n_op == EQ) {
349 printf("\tandb $0x45,%%ah\n");
350 printf("\tcmpb $0x40,%%ah\n");
351 }
352 if (p->n_op == EQ) {
353 expand(p, 0, "\tje LC\n");
354 } else
355 expand(p, 0, "\tjne LC\n");
356 }
357 }
358
359 /*
360 * Convert an unsigned long long to floating point number.
361 */
362 static void
ulltofp(NODE * p)363 ulltofp(NODE *p)
364 {
365 int jmplab;
366
367 #if defined(ELFABI) || defined(PECOFFABI)
368 static int loadlab;
369
370 if (loadlab == 0) {
371 loadlab = getlab2();
372 expand(p, 0, " .data\n");
373 printf(LABFMT ": .long 0,0x80000000,0x403f\n", loadlab);
374 expand(p, 0, " .text\n");
375 }
376 #endif
377
378 jmplab = getlab2();
379 expand(p, 0, " pushl UL\n pushl AL\n");
380 expand(p, 0, " fildq (%esp)\n");
381 expand(p, 0, " addl $8,%esp\n");
382 expand(p, 0, " cmpl $0,UL\n");
383 printf(" jge " LABFMT "\n", jmplab);
384
385 #if defined(ELFABI)
386 printf(" fldt " LABFMT "%s\n", loadlab, kflag ? "@GOTOFF" : "");
387 #elif defined(MACHOABI)
388 printf("\tpushl 0x5f800000\n");
389 printf("\tfadds (%%esp)\n");
390 printf("\taddl $4,%%esp\n");
391 #else
392 #error incomplete implementation
393 #endif
394
395 printf(" faddp %%st,%%st(1)\n");
396 printf(LABFMT ":\n", jmplab);
397 }
398
399 static int
argsiz(NODE * p)400 argsiz(NODE *p)
401 {
402 TWORD t = p->n_type;
403
404 if (t < LONGLONG || t == FLOAT || t > BTMASK)
405 return 4;
406 if (t == LONGLONG || t == ULONGLONG || t == DOUBLE)
407 return 8;
408 if (t == LDOUBLE)
409 return 12;
410 if (t == STRTY || t == UNIONTY)
411 return attr_find(p->n_ap, ATTR_P2STRUCT)->iarg(0) & ~3;
412 comperr("argsiz");
413 return 0;
414 }
415
416 static void
fcast(NODE * p)417 fcast(NODE *p)
418 {
419 TWORD t = p->n_type;
420 int sz, c;
421
422 if (t >= p->n_left->n_type)
423 return; /* cast to more precision */
424 if (t == FLOAT)
425 sz = 4, c = 's';
426 else
427 sz = 8, c = 'l';
428
429 printf(" sub $%d,%%esp\n", sz);
430 printf(" fstp%c (%%esp)\n", c);
431 printf(" fld%c (%%esp)\n", c);
432 printf(" add $%d,%%esp\n", sz);
433 }
434
435 static void
llshft(NODE * p)436 llshft(NODE *p)
437 {
438 char *d[3];
439
440 if (p->n_op == LS) {
441 d[0] = "l", d[1] = "%eax", d[2] = "%edx";
442 } else
443 d[0] = "r", d[1] = "%edx", d[2] = "%eax";
444
445 printf("\tsh%sdl %s,%s\n",d[0], d[1], d[2]);
446 printf("\ts%s%sl %%cl,%s\n", p->n_op == RS &&
447 p->n_left->n_type == ULONGLONG ? "h" : "a", d[0], d[1]);
448 printf("\ttestb $32,%%cl\n");
449 printf("\tje 1f\n");
450 printf("\tmovl %s,%s\n", d[1], d[2]);
451 if (p->n_op == RS && p->n_left->n_type == LONGLONG)
452 printf("\tsarl $31,%%edx\n");
453 else
454 printf("\txorl %s,%s\n",d[1],d[1]);
455 printf("1:\n");
456 }
457
458 void
zzzcode(NODE * p,int c)459 zzzcode(NODE *p, int c)
460 {
461 struct attr *ap;
462 NODE *l;
463 int pr, lr;
464 char *ch;
465
466 switch (c) {
467 case 'A': /* swap st0 and st1 if right is evaluated second */
468 if ((p->n_su & DORIGHT) == 0) {
469 if (logop(p->n_op))
470 printf(" fxch\n");
471 else
472 printf("r");
473 }
474 break;
475
476 case 'C': /* remove from stack after subroutine call */
477 #ifdef GCC_COMPAT
478 if (attr_find(p->n_left->n_ap, GCC_ATYP_STDCALL))
479 break;
480 #endif
481 pr = p->n_qual;
482 if (attr_find(p->n_ap, ATTR_I386_FPPOP))
483 printf(" fstp %%st(0)\n");
484 if (p->n_op == UCALL)
485 return; /* XXX remove ZC from UCALL */
486 if (pr)
487 printf(" addl $%d, %s\n", pr, rnames[ESP]);
488 #if defined(os_openbsd)
489 ap = attr_find(p->n_ap, ATTR_P2STRUCT);
490 if (p->n_op == STCALL && (ap->iarg(0) == 1 ||
491 ap->iarg(0) == 2 || ap->iarg(0) == 4 ||
492 ap->iarg(0) == 8)) {
493 /* save on stack */
494 printf("\tmovl %%eax,-%d(%%ebp)\n", stkpos);
495 printf("\tmovl %%edx,-%d(%%ebp)\n", stkpos+4);
496 printf("\tleal -%d(%%ebp),%%eax\n", stkpos);
497 }
498 #endif
499 break;
500
501 case 'D': /* Long long comparision */
502 twollcomp(p);
503 break;
504
505 case 'F': /* Structure argument */
506 starg(p);
507 break;
508
509 case 'G': /* Floating point compare */
510 fcomp(p);
511 break;
512
513 case 'H': /* assign of longlong between regs */
514 rmove(DECRA(p->n_right->n_reg, 0),
515 DECRA(p->n_left->n_reg, 0), LONGLONG);
516 break;
517
518 case 'I': /* float casts */
519 fcast(p);
520 break;
521
522 case 'J': /* convert unsigned long long to floating point */
523 ulltofp(p);
524 break;
525
526 case 'K': /* Load longlong reg into another reg */
527 rmove(regno(p), DECRA(p->n_reg, 0), LONGLONG);
528 break;
529
530 case 'M': /* Output sconv move, if needed */
531 l = getlr(p, 'L');
532 /* XXX fixneed: regnum */
533 pr = DECRA(p->n_reg, 0);
534 lr = DECRA(l->n_reg, 0);
535 if ((pr == AL && lr == EAX) || (pr == BL && lr == EBX) ||
536 (pr == CL && lr == ECX) || (pr == DL && lr == EDX))
537 ;
538 else
539 printf(" movb %%%cl,%s\n",
540 rnames[lr][2], rnames[pr]);
541 l->n_rval = l->n_reg = p->n_reg; /* XXX - not pretty */
542 break;
543
544 case 'N': /* output extended reg name */
545 printf("%s", rnames[getlr(p, '1')->n_rval]);
546 break;
547
548 case 'O': /* print out emulated ops */
549 pr = 16;
550 if (p->n_op == RS || p->n_op == LS) {
551 llshft(p);
552 break;
553 } else if (p->n_op == MUL) {
554 printf("\timull %%ecx, %%edx\n");
555 printf("\timull %%eax, %%esi\n");
556 printf("\taddl %%edx, %%esi\n");
557 printf("\tmull %%ecx\n");
558 printf("\taddl %%esi, %%edx\n");
559 break;
560 }
561 expand(p, INCREG, "\tpushl UR\n\tpushl AR\n");
562 expand(p, INCREG, "\tpushl UL\n\tpushl AL\n");
563 if (p->n_op == DIV && p->n_type == ULONGLONG) ch = "udiv";
564 else if (p->n_op == DIV) ch = "div";
565 else if (p->n_op == MOD && p->n_type == ULONGLONG) ch = "umod";
566 else if (p->n_op == MOD) ch = "mod";
567 else ch = 0, comperr("ZO");
568 #ifdef ELFABI
569 printf("\tcall " EXPREFIX "__%sdi3%s\n\taddl $%d,%s\n",
570 ch, (kflag ? "@PLT" : ""), pr, rnames[ESP]);
571 #else
572 printf("\tcall " EXPREFIX "__%sdi3\n\taddl $%d,%s\n",
573 ch, pr, rnames[ESP]);
574 #endif
575 break;
576
577 case 'Q': /* emit struct assign */
578 /*
579 * Put out some combination of movs{b,w,l}
580 * esi/edi/ecx are available.
581 */
582 expand(p, INAREG, " leal AL,%edi\n");
583 ap = attr_find(p->n_ap, ATTR_P2STRUCT);
584 if (ap->iarg(0) < 32) {
585 int i = ap->iarg(0) >> 2;
586 while (i) {
587 expand(p, INAREG, " movsl\n");
588 i--;
589 }
590 } else {
591 printf("\tmovl $%d,%%ecx\n", ap->iarg(0) >> 2);
592 printf(" rep movsl\n");
593 }
594 if (ap->iarg(0) & 2)
595 printf(" movsw\n");
596 if (ap->iarg(0) & 1)
597 printf(" movsb\n");
598 break;
599
600 case 'S': /* emit eventual move after cast from longlong */
601 pr = DECRA(p->n_reg, 0);
602 lr = p->n_left->n_rval;
603 switch (p->n_type) {
604 case CHAR:
605 case UCHAR:
606 if (rnames[pr][2] == 'l' && rnames[lr][2] == 'x' &&
607 rnames[pr][1] == rnames[lr][1])
608 break;
609 if (rnames[lr][2] == 'x') {
610 printf("\tmovb %%%cl,%s\n",
611 rnames[lr][1], rnames[pr]);
612 break;
613 }
614 /* Must go via stack */
615 expand(p, INAREG, "\tmovl AL,A2\n");
616 expand(p, INBREG, "\tmovb A2,A1\n");
617 #ifdef notdef
618 /* cannot use freetemp() in instruction emission */
619 s = freetemp(1);
620 printf("\tmovl %%e%ci,%d(%%ebp)\n", rnames[lr][1], s);
621 printf("\tmovb %d(%%ebp),%s\n", s, rnames[pr]);
622 #endif
623 break;
624
625 case SHORT:
626 case USHORT:
627 if (rnames[lr][1] == rnames[pr][2] &&
628 rnames[lr][2] == rnames[pr][3])
629 break;
630 printf("\tmovw %%%c%c,%%%s\n",
631 rnames[lr][1], rnames[lr][2], rnames[pr]+2);
632 break;
633 case INT:
634 case UNSIGNED:
635 if (rnames[lr][1] == rnames[pr][2] &&
636 rnames[lr][2] == rnames[pr][3])
637 break;
638 printf("\tmovl %%e%c%c,%s\n",
639 rnames[lr][1], rnames[lr][2], rnames[pr]);
640 break;
641
642 default:
643 if (rnames[lr][1] == rnames[pr][2] &&
644 rnames[lr][2] == rnames[pr][3])
645 break;
646 comperr("SCONV2 %s->%s", rnames[lr], rnames[pr]);
647 break;
648 }
649 break;
650
651 default:
652 comperr("zzzcode %c", c);
653 }
654 }
655
656 int canaddr(NODE *);
657 int
canaddr(NODE * p)658 canaddr(NODE *p)
659 {
660 int o = p->n_op;
661
662 if (o==NAME || o==REG || o==ICON || o==OREG ||
663 (o==UMUL && shumul(p->n_left, SOREG)))
664 return(1);
665 return(0);
666 }
667
668 /*
669 * Does the bitfield shape match?
670 */
671 int
flshape(NODE * p)672 flshape(NODE *p)
673 {
674 comperr("flshape");
675 return 0;
676 }
677
678 /* INTEMP shapes must not contain any temporary registers */
679 /* XXX should this go away now? */
680 int
shtemp(NODE * p)681 shtemp(NODE *p)
682 {
683 return 0;
684 #if 0
685 int r;
686
687 if (p->n_op == STARG )
688 p = p->n_left;
689
690 switch (p->n_op) {
691 case REG:
692 return (!istreg(p->n_rval));
693
694 case OREG:
695 r = p->n_rval;
696 if (R2TEST(r)) {
697 if (istreg(R2UPK1(r)))
698 return(0);
699 r = R2UPK2(r);
700 }
701 return (!istreg(r));
702
703 case UMUL:
704 p = p->n_left;
705 return (p->n_op != UMUL && shtemp(p));
706 }
707
708 if (optype(p->n_op) != LTYPE)
709 return(0);
710 return(1);
711 #endif
712 }
713
714 void
adrcon(CONSZ val)715 adrcon(CONSZ val)
716 {
717 printf("$" CONFMT, val);
718 }
719
720 void
conput(FILE * fp,NODE * p)721 conput(FILE *fp, NODE *p)
722 {
723 int val = (int)getlval(p);
724
725 switch (p->n_op) {
726 case ICON:
727 if (p->n_name[0] != '\0') {
728 fprintf(fp, "%s", p->n_name);
729 if (val)
730 fprintf(fp, "+%d", val);
731 } else
732 fprintf(fp, "%d", val);
733 return;
734
735 default:
736 comperr("illegal conput, p %p", p);
737 }
738 }
739
740 /*ARGSUSED*/
741 void
insput(NODE * p)742 insput(NODE *p)
743 {
744 comperr("insput");
745 }
746
747 /*
748 * Write out the upper address, like the upper register of a 2-register
749 * reference, or the next memory location.
750 */
751 void
upput(NODE * p,int size)752 upput(NODE *p, int size)
753 {
754
755 size /= SZCHAR;
756 switch (p->n_op) {
757 case REG:
758 printf("%%%s", &rnames[p->n_rval][3]);
759 break;
760
761 case NAME:
762 case OREG:
763 setlval(p, getlval(p) + size);
764 adrput(stdout, p);
765 setlval(p, getlval(p) - size);
766 break;
767 case ICON:
768 printf("$" CONFMT, getlval(p) >> 32);
769 break;
770 default:
771 comperr("upput bad op %d size %d", p->n_op, size);
772 }
773 }
774
775 void
adrput(FILE * io,NODE * p)776 adrput(FILE *io, NODE *p)
777 {
778 int r;
779 /* output an address, with offsets, from p */
780
781 switch (p->n_op) {
782
783 case NAME:
784 if (p->n_name[0] != '\0') {
785 fputs(p->n_name, io);
786 if (getlval(p) != 0)
787 fprintf(io, "+" CONFMT, getlval(p));
788 } else
789 fprintf(io, CONFMT, getlval(p));
790 return;
791
792 case OREG:
793 r = p->n_rval;
794 if (p->n_name[0])
795 printf("%s%s", p->n_name, getlval(p) ? "+" : "");
796 if (getlval(p))
797 fprintf(io, "%d", (int)getlval(p));
798 if (R2TEST(r)) {
799 fprintf(io, "(%s,%s,4)", rnames[R2UPK1(r)],
800 rnames[R2UPK2(r)]);
801 } else
802 fprintf(io, "(%s)", rnames[p->n_rval]);
803 return;
804 case ICON:
805 #ifdef PCC_DEBUG
806 /* Sanitycheck for PIC, to catch adressable constants */
807 if (kflag && p->n_name[0] && 0) {
808 static int foo;
809
810 if (foo++ == 0) {
811 printf("\nfailing...\n");
812 fwalk(p, e2print, 0);
813 comperr("pass2 conput");
814 }
815 }
816 #endif
817 /* addressable value of the constant */
818 fputc('$', io);
819 conput(io, p);
820 return;
821
822 case REG:
823 switch (p->n_type) {
824 case LONGLONG:
825 case ULONGLONG:
826 fprintf(io, "%%%c%c%c", rnames[p->n_rval][0],
827 rnames[p->n_rval][1], rnames[p->n_rval][2]);
828 break;
829 case SHORT:
830 case USHORT:
831 fprintf(io, "%%%s", &rnames[p->n_rval][2]);
832 break;
833 default:
834 fprintf(io, "%s", rnames[p->n_rval]);
835 }
836 return;
837
838 default:
839 comperr("illegal address, op %d, node %p", p->n_op, p);
840 return;
841
842 }
843 }
844
845 static char *
846 ccbranches[] = {
847 "je", /* jumpe */
848 "jne", /* jumpn */
849 "jle", /* jumple */
850 "jl", /* jumpl */
851 "jge", /* jumpge */
852 "jg", /* jumpg */
853 "jbe", /* jumple (jlequ) */
854 "jb", /* jumpl (jlssu) */
855 "jae", /* jumpge (jgequ) */
856 "ja", /* jumpg (jgtru) */
857 };
858
859
860 /* printf conditional and unconditional branches */
861 void
cbgen(int o,int lab)862 cbgen(int o, int lab)
863 {
864 if (o < EQ || o > UGT)
865 comperr("bad conditional branch: %s", opst[o]);
866 printf(" %s " LABFMT "\n", ccbranches[o-EQ], lab);
867 }
868
869 static void
fixcalls(NODE * p,void * arg)870 fixcalls(NODE *p, void *arg)
871 {
872 struct attr *ap;
873
874 /* Prepare for struct return by allocating bounce space on stack */
875 switch (p->n_op) {
876 case STCALL:
877 case USTCALL:
878 ap = attr_find(p->n_ap, ATTR_P2STRUCT);
879 if (ap->iarg(0)+p2autooff > stkpos)
880 stkpos = ap->iarg(0)+p2autooff;
881 if (8+p2autooff > stkpos)
882 stkpos = ap->iarg(0)+p2autooff;
883 break;
884 case LS:
885 case RS:
886 if (p->n_type != LONGLONG && p->n_type != ULONGLONG)
887 break;
888 if (p->n_right->n_op == ICON) /* constants must be char */
889 p->n_right->n_type = CHAR;
890 break;
891 }
892 }
893
894 /*
895 * Must store floats in memory if there are two function calls involved.
896 */
897 static int
storefloat(struct interpass * ip,NODE * p)898 storefloat(struct interpass *ip, NODE *p)
899 {
900 int l, r;
901
902 switch (optype(p->n_op)) {
903 case BITYPE:
904 l = storefloat(ip, p->n_left);
905 r = storefloat(ip, p->n_right);
906 if (p->n_op == CM)
907 return 0; /* arguments, don't care */
908 if (callop(p->n_op))
909 return 1; /* found one */
910 #define ISF(p) ((p)->n_type == FLOAT || (p)->n_type == DOUBLE || \
911 (p)->n_type == LDOUBLE)
912 if (ISF(p->n_left) && ISF(p->n_right) && l && r) {
913 /* must store one. store left */
914 struct interpass *nip;
915 TWORD t = p->n_left->n_type;
916 NODE *ll;
917 int off;
918
919 off = freetemp(szty(t));
920 ll = mklnode(OREG, off, FPREG, t);
921 nip = ipnode(mkbinode(ASSIGN, ll, p->n_left, t));
922 p->n_left = mklnode(OREG, off, FPREG, t);
923 DLIST_INSERT_BEFORE(ip, nip, qelem);
924 }
925 return l|r;
926
927 case UTYPE:
928 l = storefloat(ip, p->n_left);
929 if (callop(p->n_op))
930 l = 1;
931 return l;
932 default:
933 return 0;
934 }
935 }
936
937 static void
outfargs(struct interpass * ip,NODE ** ary,int num,int * cwp,int c)938 outfargs(struct interpass *ip, NODE **ary, int num, int *cwp, int c)
939 {
940 struct interpass *ip2;
941 NODE *q, *r;
942 int i;
943
944 for (i = 0; i < num; i++)
945 if (XASMVAL(cwp[i]) == c && (cwp[i] & (XASMASG|XASMINOUT)))
946 break;
947 if (i == num)
948 return;
949 q = ary[i]->n_left;
950 r = mklnode(REG, 0, c == 'u' ? 040 : 037, q->n_type);
951 ary[i]->n_left = tcopy(r);
952 ip2 = ipnode(mkbinode(ASSIGN, q, r, q->n_type));
953 DLIST_INSERT_AFTER(ip, ip2, qelem);
954 }
955
956 static void
infargs(struct interpass * ip,NODE ** ary,int num,int * cwp,int c)957 infargs(struct interpass *ip, NODE **ary, int num, int *cwp, int c)
958 {
959 struct interpass *ip2;
960 NODE *q, *r;
961 int i;
962
963 for (i = 0; i < num; i++)
964 if (XASMVAL(cwp[i]) == c && (cwp[i] & XASMASG) == 0)
965 break;
966 if (i == num)
967 return;
968 q = ary[i]->n_left;
969 q = (cwp[i] & XASMINOUT) ? tcopy(q) : q;
970 r = mklnode(REG, 0, c == 'u' ? 040 : 037, q->n_type);
971 if ((cwp[i] & XASMINOUT) == 0)
972 ary[i]->n_left = tcopy(r);
973 ip2 = ipnode(mkbinode(ASSIGN, r, q, q->n_type));
974 DLIST_INSERT_BEFORE(ip, ip2, qelem);
975 }
976
977 /*
978 * Extract float args to XASM and ensure that they are put on the stack
979 * in correct order.
980 * This should be done sow other way.
981 */
982 static void
fixxfloat(struct interpass * ip,NODE * p)983 fixxfloat(struct interpass *ip, NODE *p)
984 {
985 NODE *w, **ary;
986 int nn, i, c, *cwp;
987
988 nn = 1;
989 w = p->n_left;
990 if (w->n_op == ICON && w->n_type == STRTY)
991 return;
992 /* index all xasm args first */
993 for (; w->n_op == CM; w = w->n_left)
994 nn++;
995 ary = tmpcalloc(nn * sizeof(NODE *));
996 cwp = tmpcalloc(nn * sizeof(int));
997 for (i = 0, w = p->n_left; w->n_op == CM; w = w->n_left) {
998 ary[i] = w->n_right;
999 cwp[i] = xasmcode(ary[i]->n_name);
1000 i++;
1001 }
1002 ary[i] = w;
1003 cwp[i] = xasmcode(ary[i]->n_name);
1004 for (i = 0; i < nn; i++)
1005 if (XASMVAL(cwp[i]) == 't' || XASMVAL(cwp[i]) == 'u')
1006 break;
1007 if (i == nn)
1008 return;
1009
1010 for (i = 0; i < nn; i++) {
1011 c = XASMVAL(cwp[i]);
1012 if (c >= '0' && c <= '9')
1013 cwp[i] = (cwp[i] & ~0377) | XASMVAL(cwp[c-'0']);
1014 }
1015 infargs(ip, ary, nn, cwp, 'u');
1016 infargs(ip, ary, nn, cwp, 't');
1017 outfargs(ip, ary, nn, cwp, 't');
1018 outfargs(ip, ary, nn, cwp, 'u');
1019 }
1020
1021 static NODE *
lptr(NODE * p)1022 lptr(NODE *p)
1023 {
1024 if (p->n_op == ASSIGN && p->n_right->n_op == REG &&
1025 regno(p->n_right) == EBP)
1026 return p->n_right;
1027 if (p->n_op == FUNARG && p->n_left->n_op == REG &&
1028 regno(p->n_left) == EBP)
1029 return p->n_left;
1030 return NIL;
1031 }
1032
1033 /*
1034 * Find arg reg that should be struct reference instead.
1035 */
1036 static void
updatereg(NODE * p,void * arg)1037 updatereg(NODE *p, void *arg)
1038 {
1039 NODE *q;
1040
1041 if (p->n_op != STCALL)
1042 return;
1043 #if defined(os_openbsd)
1044 struct attr *ap = attr_find(p->n_ap, ATTR_P2STRUCT);
1045 if (ap->iarg(0) == 1 || ap->iarg(0) == 2 || ap->iarg(0) == 4 ||
1046 ap->iarg(0) == 8)
1047 return;
1048 #endif
1049 if (attr_find(p->n_ap, ATTR_I386_FCMPLRET))
1050 return;
1051
1052 if (p->n_right->n_op != CM)
1053 p = p->n_right;
1054 else for (p = p->n_right;
1055 p->n_op == CM && p->n_left->n_op == CM; p = p->n_left)
1056 ;
1057 if (p->n_op == CM) {
1058 if ((q = lptr(p->n_left)))
1059 ;
1060 else
1061 q = lptr(p->n_right);
1062 } else
1063 q = lptr(p);
1064 if (q == NIL)
1065 comperr("bad STCALL hidden reg");
1066
1067 /* q is now the hidden arg */
1068 q->n_op = MINUS;
1069 q->n_type = INCREF(CHAR);
1070 q->n_left = mklnode(REG, 0, EBP, INCREF(CHAR));
1071 q->n_right = mklnode(ICON, stkpos, 0, INT);
1072 }
1073
1074 void
myreader(struct interpass * ipole)1075 myreader(struct interpass *ipole)
1076 {
1077 struct interpass *ip;
1078
1079 stkpos = p2autooff;
1080 DLIST_FOREACH(ip, ipole, qelem) {
1081 if (ip->type != IP_NODE)
1082 continue;
1083 walkf(ip->ip_node, fixcalls, 0);
1084 storefloat(ip, ip->ip_node);
1085 if (ip->ip_node->n_op == XASM)
1086 fixxfloat(ip, ip->ip_node);
1087 }
1088 if (stkpos != p2autooff) {
1089 DLIST_FOREACH(ip, ipole, qelem) {
1090 if (ip->type != IP_NODE)
1091 continue;
1092 walkf(ip->ip_node, updatereg, 0);
1093 }
1094 }
1095 if (stkpos > p2autooff)
1096 p2autooff = stkpos;
1097 if (stkpos > p2maxautooff)
1098 p2maxautooff = stkpos;
1099 if (x2debug)
1100 printip(ipole);
1101 }
1102
1103 /*
1104 * Remove some PCONVs after OREGs are created.
1105 */
1106 static void
pconv2(NODE * p,void * arg)1107 pconv2(NODE *p, void *arg)
1108 {
1109 NODE *q;
1110
1111 if (p->n_op == PLUS) {
1112 if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) {
1113 if (p->n_right->n_op != ICON)
1114 return;
1115 if (p->n_left->n_op != PCONV)
1116 return;
1117 if (p->n_left->n_left->n_op != OREG)
1118 return;
1119 q = p->n_left->n_left;
1120 nfree(p->n_left);
1121 p->n_left = q;
1122 /*
1123 * This will be converted to another OREG later.
1124 */
1125 }
1126 }
1127 }
1128
1129 void
mycanon(NODE * p)1130 mycanon(NODE *p)
1131 {
1132 walkf(p, pconv2, 0);
1133 }
1134
1135 void
myoptim(struct interpass * ip)1136 myoptim(struct interpass *ip)
1137 {
1138 }
1139
1140 static char rl[] =
1141 { EAX, EAX, EAX, EAX, EAX, EDX, EDX, EDX, EDX, ECX, ECX, ECX, EBX, EBX, ESI };
1142 static char rh[] =
1143 { EDX, ECX, EBX, ESI, EDI, ECX, EBX, ESI, EDI, EBX, ESI, EDI, ESI, EDI, EDI };
1144
1145 void
rmove(int s,int d,TWORD t)1146 rmove(int s, int d, TWORD t)
1147 {
1148 int sl, sh, dl, dh;
1149
1150 switch (t) {
1151 case LONGLONG:
1152 case ULONGLONG:
1153 #if 1
1154 sl = rl[s-EAXEDX];
1155 sh = rh[s-EAXEDX];
1156 dl = rl[d-EAXEDX];
1157 dh = rh[d-EAXEDX];
1158
1159 /* sanity checks, remove when satisfied */
1160 if (memcmp(rnames[s], rnames[sl]+1, 3) != 0 ||
1161 memcmp(rnames[s]+3, rnames[sh]+1, 3) != 0)
1162 comperr("rmove source error");
1163 if (memcmp(rnames[d], rnames[dl]+1, 3) != 0 ||
1164 memcmp(rnames[d]+3, rnames[dh]+1, 3) != 0)
1165 comperr("rmove dest error");
1166 #define SW(x,y) { int i = x; x = y; y = i; }
1167 if (sh == dl) {
1168 /* Swap if overwriting */
1169 SW(sl, sh);
1170 SW(dl, dh);
1171 }
1172 if (sl != dl)
1173 printf(" movl %s,%s\n", rnames[sl], rnames[dl]);
1174 if (sh != dh)
1175 printf(" movl %s,%s\n", rnames[sh], rnames[dh]);
1176 #else
1177 if (memcmp(rnames[s], rnames[d], 3) != 0)
1178 printf(" movl %%%c%c%c,%%%c%c%c\n",
1179 rnames[s][0],rnames[s][1],rnames[s][2],
1180 rnames[d][0],rnames[d][1],rnames[d][2]);
1181 if (memcmp(&rnames[s][3], &rnames[d][3], 3) != 0)
1182 printf(" movl %%%c%c%c,%%%c%c%c\n",
1183 rnames[s][3],rnames[s][4],rnames[s][5],
1184 rnames[d][3],rnames[d][4],rnames[d][5]);
1185 #endif
1186 break;
1187 case CHAR:
1188 case UCHAR:
1189 printf(" movb %s,%s\n", rnames[s], rnames[d]);
1190 break;
1191 case FLOAT:
1192 case DOUBLE:
1193 case LDOUBLE:
1194 #ifdef notdef
1195 /* a=b()*c(); will generate this */
1196 comperr("bad float rmove: %d %d", s, d);
1197 #endif
1198 break;
1199 default:
1200 printf(" movl %s,%s\n", rnames[s], rnames[d]);
1201 }
1202 }
1203
1204 /*
1205 * For class c, find worst-case displacement of the number of
1206 * registers in the array r[] indexed by class.
1207 */
1208 int
COLORMAP(int c,int * r)1209 COLORMAP(int c, int *r)
1210 {
1211 int num;
1212
1213 switch (c) {
1214 case CLASSA:
1215 num = r[CLASSB] > 4 ? 4 : r[CLASSB];
1216 num += 2*r[CLASSC];
1217 num += r[CLASSA];
1218 return num < 6;
1219 case CLASSB:
1220 num = r[CLASSA];
1221 num += 2*r[CLASSC];
1222 num += r[CLASSB];
1223 return num < 4;
1224 case CLASSC:
1225 num = r[CLASSA];
1226 num += r[CLASSB] > 4 ? 4 : r[CLASSB];
1227 num += 2*r[CLASSC];
1228 return num < 5;
1229 case CLASSD:
1230 return r[CLASSD] < DREGCNT;
1231 }
1232 return 0; /* XXX gcc */
1233 }
1234
1235 char *rnames[] = {
1236 "%eax", "%edx", "%ecx", "%ebx", "%esi", "%edi", "%ebp", "%esp",
1237 "%al", "%ah", "%dl", "%dh", "%cl", "%ch", "%bl", "%bh",
1238 "eaxedx", "eaxecx", "eaxebx", "eaxesi", "eaxedi", "edxecx",
1239 "edxebx", "edxesi", "edxedi", "ecxebx", "ecxesi", "ecxedi",
1240 "ebxesi", "ebxedi", "esiedi",
1241 "%st0", "%st1", "%st2", "%st3", "%st4", "%st5", "%st6", "%st7",
1242 };
1243
1244 /*
1245 * Return a class suitable for a specific type.
1246 */
1247 int
gclass(TWORD t)1248 gclass(TWORD t)
1249 {
1250 if (t == CHAR || t == UCHAR)
1251 return CLASSB;
1252 if (t == LONGLONG || t == ULONGLONG)
1253 return CLASSC;
1254 if (t == FLOAT || t == DOUBLE || t == LDOUBLE)
1255 return CLASSD;
1256 return CLASSA;
1257 }
1258
1259 /*
1260 * Calculate argument sizes.
1261 */
1262 void
lastcall(NODE * p)1263 lastcall(NODE *p)
1264 {
1265 NODE *op = p;
1266 int nr = 0, size = 0;
1267
1268 p->n_qual = 0;
1269 if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL)
1270 return;
1271 for (p = p->n_right; p->n_op == CM; p = p->n_left) {
1272 if (p->n_right->n_op != ASSIGN)
1273 size += argsiz(p->n_right);
1274 else
1275 nr = 1;
1276 }
1277 if (p->n_op != ASSIGN)
1278 size += argsiz(p);
1279 else
1280 nr++;
1281 if (op->n_op == STCALL) {
1282 if (kflag)
1283 nr--;
1284 if (nr == 0)
1285 size -= 4; /* XXX OpenBSD? */
1286 }
1287
1288 #if defined(MACHOABI)
1289 int newsize = (size + 15) & ~15; /* stack alignment */
1290 int align = newsize-size;
1291
1292 if (align != 0)
1293 printf(" subl $%d,%%esp\n", align);
1294
1295 size=newsize;
1296 #endif
1297
1298 op->n_qual = size; /* XXX */
1299 }
1300
1301 /*
1302 * Special shapes.
1303 */
1304 int
special(NODE * p,int shape)1305 special(NODE *p, int shape)
1306 {
1307 int o = p->n_op;
1308
1309 switch (shape) {
1310 case SFUNCALL:
1311 if (o == STCALL || o == USTCALL)
1312 return SRREG;
1313 break;
1314 case SPCON:
1315 if (o != ICON || p->n_name[0] ||
1316 getlval(p) < 0 || getlval(p) > 0x7fffffff)
1317 break;
1318 return SRDIR;
1319 case SMIXOR:
1320 return tshape(p, SZERO);
1321 case SMILWXOR:
1322 if (o != ICON || p->n_name[0] ||
1323 getlval(p) == 0 || getlval(p) & 0xffffffff)
1324 break;
1325 return SRDIR;
1326 case SMIHWXOR:
1327 if (o != ICON || p->n_name[0] ||
1328 getlval(p) == 0 || (getlval(p) >> 32) != 0)
1329 break;
1330 return SRDIR;
1331 }
1332 return SRNOPE;
1333 }
1334
1335 /*
1336 * Target-dependent command-line options.
1337 */
1338 void
mflags(char * str)1339 mflags(char *str)
1340 {
1341 #define MSET(s,a) if (strcmp(str, s) == 0) \
1342 msettings = (msettings & ~MCPUMSK) | a
1343
1344 MSET("arch=i386",MI386);
1345 MSET("arch=i486",MI486);
1346 MSET("arch=i586",MI586);
1347 MSET("arch=i686",MI686);
1348 }
1349
1350 /*
1351 * Do something target-dependent for xasm arguments.
1352 */
1353 int
myxasm(struct interpass * ip,NODE * p)1354 myxasm(struct interpass *ip, NODE *p)
1355 {
1356 struct interpass *ip2;
1357 int Cmax[] = { 31, 63, 127, 0xffff, 3, 255 };
1358 NODE *in = 0, *ut = 0;
1359 TWORD t;
1360 char *w;
1361 int reg;
1362 int c, cw;
1363 CONSZ v;
1364
1365 cw = xasmcode(p->n_name);
1366 if (cw & (XASMASG|XASMINOUT))
1367 ut = p->n_left;
1368 if ((cw & XASMASG) == 0)
1369 in = p->n_left;
1370
1371 c = XASMVAL(cw);
1372 switch (c) {
1373 case 'D': reg = EDI; break;
1374 case 'S': reg = ESI; break;
1375 case 'a': reg = EAX; break;
1376 case 'b': reg = EBX; break;
1377 case 'c': reg = ECX; break;
1378 case 'd': reg = EDX; break;
1379
1380 case 't':
1381 case 'u':
1382 p->n_name = tmpstrdup(p->n_name);
1383 w = strchr(p->n_name, XASMVAL(cw));
1384 *w = 'r'; /* now reg */
1385 return 1;
1386
1387 case 'A': reg = EAXEDX; break;
1388 case 'q': {
1389 /* Set edges in MYSETXARG */
1390 if (p->n_left->n_op == REG || p->n_left->n_op == TEMP)
1391 return 1;
1392 t = p->n_left->n_type;
1393 if (in && ut)
1394 in = tcopy(in);
1395 p->n_left = mklnode(TEMP, 0, p2env.epp->ip_tmpnum++, t);
1396 if (ut) {
1397 ip2 = ipnode(mkbinode(ASSIGN, ut, tcopy(p->n_left), t));
1398 DLIST_INSERT_AFTER(ip, ip2, qelem);
1399 }
1400 if (in) {
1401 ip2 = ipnode(mkbinode(ASSIGN, tcopy(p->n_left), in, t));
1402 DLIST_INSERT_BEFORE(ip, ip2, qelem);
1403 }
1404 return 1;
1405 }
1406
1407 case 'I':
1408 case 'J':
1409 case 'K':
1410 case 'L':
1411 case 'M':
1412 case 'N':
1413 if (p->n_left->n_op != ICON) {
1414 if ((c = XASMVAL1(cw)) != 0) {
1415 p->n_name++;
1416 return 0; /* Try again */
1417 }
1418 uerror("xasm arg not constant");
1419 }
1420 v = getlval(p->n_left);
1421 if ((c == 'K' && v < -128) ||
1422 (c == 'L' && v != 0xff && v != 0xffff) ||
1423 (c != 'K' && v < 0) ||
1424 (v > Cmax[c-'I']))
1425 uerror("xasm val out of range");
1426 p->n_name = "i";
1427 return 1;
1428
1429 default:
1430 return 0;
1431 }
1432 /* If there are requested either memory or register, delete memory */
1433 w = p->n_name = tmpstrdup(p->n_name);
1434 if (*w == '=')
1435 w++;
1436 *w++ = 'r';
1437 *w = 0;
1438
1439 t = p->n_left->n_type;
1440 if (reg == EAXEDX) {
1441 ;
1442 } else {
1443 if (t == CHAR || t == UCHAR) {
1444 reg = reg * 2 + 8;
1445 }
1446 }
1447 if (t == FLOAT || t == DOUBLE || t == LDOUBLE) {
1448 reg += 037;
1449 }
1450
1451 if (in && ut)
1452 in = tcopy(in);
1453 p->n_left = mklnode(REG, 0, reg, t);
1454 if (ut) {
1455 ip2 = ipnode(mkbinode(ASSIGN, ut, tcopy(p->n_left), t));
1456 DLIST_INSERT_AFTER(ip, ip2, qelem);
1457 }
1458 if (in) {
1459 ip2 = ipnode(mkbinode(ASSIGN, tcopy(p->n_left), in, t));
1460 DLIST_INSERT_BEFORE(ip, ip2, qelem);
1461 }
1462 return 1;
1463 }
1464
1465 void
targarg(char * w,void * arg)1466 targarg(char *w, void *arg)
1467 {
1468 NODE **ary = arg;
1469 NODE *p, *q;
1470
1471 if (ary[(int)w[1]-'0'] == 0)
1472 p = ary[(int)w[1]-'0'-1]->n_left; /* XXX */
1473 else
1474 p = ary[(int)w[1]-'0']->n_left;
1475 if (optype(p->n_op) != LTYPE)
1476 comperr("bad xarg op %d", p->n_op);
1477 q = tcopy(p);
1478 if (q->n_op == REG) {
1479 if (*w == 'k') {
1480 q->n_type = INT;
1481 } else if (*w != 'w') {
1482 if (q->n_type > UCHAR) {
1483 regno(q) = regno(q)*2+8;
1484 if (*w == 'h')
1485 regno(q)++;
1486 }
1487 q->n_type = INT;
1488 } else
1489 q->n_type = SHORT;
1490 }
1491 adrput(stdout, q);
1492 tfree(q);
1493 }
1494
1495 /*
1496 * target-specific conversion of numeric arguments.
1497 */
1498 int
numconv(void * ip,void * p1,void * q1)1499 numconv(void *ip, void *p1, void *q1)
1500 {
1501 NODE *p = p1, *q = q1;
1502 int cw = xasmcode(q->n_name);
1503
1504 switch (XASMVAL(cw)) {
1505 case 'a':
1506 case 'b':
1507 case 'c':
1508 case 'd':
1509 p->n_name = tmpcalloc(2);
1510 p->n_name[0] = (char)XASMVAL(cw);
1511 return 1;
1512 default:
1513 return 0;
1514 }
1515 }
1516
1517 static struct {
1518 char *name; int num;
1519 } xcr[] = {
1520 { "eax", EAX },
1521 { "ebx", EBX },
1522 { "ecx", ECX },
1523 { "edx", EDX },
1524 { "esi", ESI },
1525 { "edi", EDI },
1526 { "ax", EAX },
1527 { "bx", EBX },
1528 { "cx", ECX },
1529 { "dx", EDX },
1530 { NULL, 0 },
1531 };
1532
1533 /*
1534 * Check for other names of the xasm constraints registers.
1535 */
1536
1537 /*
1538 * Check for other names of the xasm constraints registers.
1539 */
xasmconstregs(char * s)1540 int xasmconstregs(char *s)
1541 {
1542 int i;
1543
1544 if (strncmp(s, "st", 2) == 0) {
1545 int off =0;
1546 if (s[2] == '(' && s[4] == ')')
1547 off = s[3] - '0';
1548 return ESIEDI + 1 + off;
1549 }
1550
1551 for (i = 0; xcr[i].name; i++)
1552 if (strcmp(xcr[i].name, s) == 0)
1553 return xcr[i].num;
1554 return -1;
1555 }
1556
1557