Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20080622152459

Diff

Diff from 1.20 to:

Annotations

Annotate by Age | Author | Mixed | None
/fisheye/browse/pcc/pcc/arch/mips/local2.c

Annotated File View

ragge
1.20
1 /*      $Id: local2.c,v 1.20 2008/06/22 15:24:59 ragge Exp $     */
ragge
1.1
2 /*
3  * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 /*
30  * MIPS port by Jan Enoksson (janeno-1@student.ltu.se) and
31  * Simon Olsson (simols-1@student.ltu.se) 2005.
32  */
33
gmcgarry
1.4
34 #include <ctype.h>
gmcgarry
1.7
35 #include <string.h>
gmcgarry
1.19
36 #include <stdlib.h>
gmcgarry
1.4
37 #include <assert.h>
ragge
1.1
38
gmcgarry
1.4
39 #include "pass1.h"
40 #include "pass2.h"
41
gmcgarry
1.7
42 #ifdef TARGET_BIG_ENDIAN
43 int bigendian = 1;
44 #else
45 int bigendian = 0;
46 #endif
47
48 int nargregs = MIPS_O32_NARGREGS;
49
gmcgarry
1.15
50 static int argsiz(NODE *p);
ragge
1.1
51
52 void
53 deflab(int label)
54 {
gmcgarry
1.4
55         printf(LABFMT ":\n"label);
ragge
1.1
56 }
57
58 static int regoff[32];
59 static TWORD ftype;
60
61 /*
gmcgarry
1.4
62  * calculate stack size and offsets
ragge
1.1
63  */
gmcgarry
1.4
64 static int
65 offcalc(struct interpass_prolog * ipp)
ragge
1.1
66 {
gmcgarry
1.4
67         int ijaddto;
68
69         addto = p2maxautooff;
70
71         for (i = ipp->ipp_regsj = 0ii >>= 1j++) {
72                 if (i & 1) {
73                         addto += SZINT / SZCHAR;
74                         regoff[j] = addto;
75                 }
76         }
gmcgarry
1.13
77
78         /* round to 8-byte boundary */
79         addto += 7;
80         addto &= ~7;
81
gmcgarry
1.4
82         return addto;
ragge
1.1
83 }
84
85 /*
gmcgarry
1.4
86  * Print out the prolog assembler.
ragge
1.1
87  */
gmcgarry
1.4
88 void
89 prologue(struct interpass_prolog * ipp)
ragge
1.1
90 {
gmcgarry
1.4
91         int addto;
92         int ij;
ragge
1.1
93
gmcgarry
1.4
94         ftype = ipp->ipp_type;
95         printf("\t.align 2\n");
96         if (ipp->ipp_vis)
97                 printf("\t.globl %s\n"ipp->ipp_name);
98         printf("\t.ent %s\n"ipp->ipp_name);
99         printf("%s:\n"ipp->ipp_name);
100
101         addto = offcalc(ipp);
gmcgarry
1.13
102
gmcgarry
1.10
103         /* for the moment, just emit this PIC stuff - NetBSD does it */
gmcgarry
1.13
104         printf("\t.frame %s,%d,%s\n"rnames[FP], ARGINIT/SZCHARrnames[RA]);
gmcgarry
1.10
105         printf("\t.set noreorder\n");
106         printf("\t.cpload $25\t# pseudo-op to load GOT ptr into $25\n");
107         printf("\t.set reorder\n");
108
gmcgarry
1.13
109         printf("\tsubu %s,%s,%d\n"rnames[SP], rnames[SP], ARGINIT/SZCHAR);
gmcgarry
1.10
110         /* for the moment, just emit PIC stuff - NetBSD does it */
111         printf("\t.cprestore 8\t# pseudo-op to store GOT ptr at 8(sp)\n");
112
gmcgarry
1.13
113         printf("\tsw %s,4(%s)\n"rnames[RA], rnames[SP]);
114         printf("\tsw %s,(%s)\n"rnames[FP], rnames[SP]);
gmcgarry
1.4
115         printf("\tmove %s,%s\n"rnames[FP], rnames[SP]);
gmcgarry
1.15
116
117 #ifdef notyet
118         /* profiling */
119         if (pflag) {
120                 printf("\t.set noat\n");
121                 printf("\tmove %s,%s\t# save current return address\n",
122                     rnames[AT], rnames[RA]);
123                 printf("\tsubu %s,%s,8\t# _mcount pops 2 words from stack\n",
124                     rnames[SP], rnames[SP]);
125                 printf("\tjal %s\n"exname("_mcount"));
126                 printf("\tnop\n");
127                 printf("\t.set at\n");
128         }
129 #endif
130
gmcgarry
1.13
131         if (addto)
gmcgarry
1.8
132                 printf("\tsubu %s,%s,%d\n"rnames[SP], rnames[SP], addto);
ragge
1.1
133
gmcgarry
1.4
134         for (i = ipp->ipp_regsj = 0ii >>= 1j++)
135                 if (i & 1)
gmcgarry
1.13
136                         fprintf(stdout"\tsw %s,-%d(%s) # save permanent\n",
gmcgarry
1.4
137                                 rnames[j], regoff[j], rnames[FP]);
gmcgarry
1.15
138
ragge
1.1
139 }
140
141 void
gmcgarry
1.4
142 eoftn(struct interpass_prolog * ipp)
143 {
144         int ij;
145         int addto;
146
147         addto = offcalc(ipp);
148
149         if (ipp->ipp_ip.ip_lbl == 0)
150                 return;         /* no code needs to be generated */
151
152         /* return from function code */
153         for (i = ipp->ipp_regsj = 0ii >>= 1j++) {
154                 if (i & 1)
gmcgarry
1.13
155                         fprintf(stdout"\tlw %s,-%d(%s)\n\tnop\n",
gmcgarry
1.4
156                                 rnames[j], regoff[j], rnames[FP]);
157         }
ragge
1.1
158
gmcgarry
1.18
159         printf("\taddiu %s,%s,%d\n"rnames[SP], rnames[FP], ARGINIT/SZCHAR);
gmcgarry
1.13
160         printf("\tlw %s,%d(%s)\n"rnames[RA], 4-ARGINIT/SZCHAR,  rnames[SP]);
161         printf("\tlw %s,%d(%s)\n"rnames[FP], 0-ARGINIT/SZCHAR,  rnames[SP]);
gmcgarry
1.8
162
163         printf("\tjr %s\n"rnames[RA]);
164         printf("\tnop\n");
gmcgarry
1.4
165
166 #ifdef USE_GAS
167         printf("\t.end %s\n"ipp->ipp_name);
168         printf("\t.size %s,.-%s\n"ipp->ipp_nameipp->ipp_name);
169 #endif
ragge
1.1
170 }
171
172 /*
173  * add/sub/...
174  *
175  * Param given:
176  */
177 void
178 hopcode(int fint o)
179 {
gmcgarry
1.4
180         char *str;
ragge
1.1
181
gmcgarry
1.4
182         switch (o) {
183         case EQ:
184                 str = "beqz";   /* pseudo-op */
185                 break;
186         case NE:
187                 str = "bnez";   /* pseudo-op */
188                 break;
gmcgarry
1.11
189         case ULE:
gmcgarry
1.4
190         case LE:
191                 str = "blez";
192                 break;
gmcgarry
1.11
193         case ULT:
gmcgarry
1.4
194         case LT:
195                 str = "bltz";
196                 break;
gmcgarry
1.11
197         case UGE:
gmcgarry
1.4
198         case GE:
199                 str = "bgez";
200                 break;
gmcgarry
1.11
201         case UGT:
gmcgarry
1.4
202         case GT:
203                 str = "bgtz";
204                 break;
205         case PLUS:
gmcgarry
1.12
206                 str = "add";
gmcgarry
1.4
207                 break;
208         case MINUS:
gmcgarry
1.12
209                 str = "sub";
gmcgarry
1.4
210                 break;
211         case AND:
212                 str = "and";
213                 break;
214         case OR:
215                 str = "or";
216                 break;
217         case ER:
218                 str = "xor";
219                 break;
220         default:
221                 comperr("hopcode2: %d"o);
222                 str = 0;        /* XXX gcc */
223         }
ragge
1.1
224
gmcgarry
1.4
225         printf("%s%c"strf);
ragge
1.1
226 }
227
228 char *
gmcgarry
1.7
229 rnames[] = {
gmcgarry
1.4
230 #ifdef USE_GAS
231         /* gnu assembler */
232         "$zero""$at""$2""$3""$4""$5""$6""$7",
233         "$8""$9""$10""$11""$12""$13""$14""$15",
234         "$16""$17""$18""$19""$20""$21""$22""$23",
235         "$24""$25",
236         "$kt0""$kt1""$gp""$sp""$fp""$ra",
gmcgarry
1.8
237         "$2!!$3!!",
238         "$4!!$5!!""$5!!$6!!""$6!!$7!!""$7!!$8!!",
239         "$8!!$9!!""$9!!$10!""$10!$11!""$11!$12!",
gmcgarry
1.13
240         "$12!$13!""$13!$14!""$14!$15!""$15!$24!""$24!$25!",
gmcgarry
1.8
241         "$16!$17!""$17!$18!""$18!$19!""$19!$20!",
242         "$20!$21!""$21!$22!""$22!$23!",
gmcgarry
1.4
243 #else
244         /* mips assembler */
245          "$zero""$at""$v0""$v1""$a0""$a1""$a2""$a3",
246         "$t0""$t1""$t2""$t3""$t4""$t5""$t6""$t7",
gmcgarry
1.7
247         "$s0""$s1""$s2""$s3""$s4""$s5""$s6""$s7",
248         "$t8""$t9",
249         "$k0""$k1""$gp""$sp""$fp""$ra",
gmcgarry
1.8
250         "$v0!$v1!",
251         "$a0!$a1!""$a1!$a2!""$a2!$a3!""$a3!$t0!",
252         "$t0!$t1!""$t1!$t2!""$t2!$t3!""$t3!$t4!",
gmcgarry
1.13
253         "$t4!$t5!""$t5!$t6!""$t6!$t7!""$t7!$t8!""$t8!$t9!",
gmcgarry
1.8
254         "$s0!$s1!""$s1!$s2!""$s2!$s3!""$s3!$s4!",
255         "$s4!$s5!""$s5!$s6!""$s6!$s7!",
gmcgarry
1.4
256 #endif
gmcgarry
1.8
257         "$f0!$f1!""$f2!$f3!""$f4!$f5!""$f6!$f7!",
258         "$f8!$f9!""$f10$f11""$f12$f13""$f14$f15",
259         "$f16$f17""$f18$f19""$f20$f21""$f22$f23",
260         "$f24$f25""$f26$f27""$f28$f29""$f30$f31",
gmcgarry
1.7
261 };
262
263 char *
264 rnames_n32[] = {
265         /* mips assembler */
266         "$zero""$at""$v0""$v1""$a0""$a1""$a2""$a3",
267         "$a4""$a5""$a6""$a7""$t0""$t1""$t2""$t3",
gmcgarry
1.4
268         "$s0""$s1""$s2""$s3""$s4""$s5""$s6""$s7",
269         "$t8""$t9",
270         "$k0""$k1""$gp""$sp""$fp""$ra",
gmcgarry
1.8
271         "$v0!$v1!",
gmcgarry
1.13
272         "$a0!$a1!""$a1!$a2!""$a2!$a3!""$a3!$a4!",
273         "$a4!$a5!""$a5!$a6!""$a6!$a7!""$a7!$t0!",
274         "$t0!$t1!""$t1!$t2!""$t2!$t3!""$t3!$t8!""$t8!$t9!",
275         "$s0!$s1!""$s1!$s2!""$s2!$s3!""$s3!$s4!",
gmcgarry
1.8
276         "$s4!$s5!""$s5!$s6!""$s6!$s7!",
277         "$f0!$f1!""$f2!$f3!""$f4!$f5!""$f6!$f7!",
278         "$f8!$f9!""$f10$f11""$f12$f13""$f14$f15",
279         "$f16$f17""$f18$f19""$f20$f21""$f22$f23",
280         "$f24$f25""$f26$f27""$f28$f29""$f30$f31",
ragge
1.1
281 };
282
283 int
gmcgarry
1.4
284 tlen(NODE *p)
ragge
1.1
285 {
gmcgarry
1.4
286         switch (p->n_type) {
287         case CHAR:
288         case UCHAR:
289                 return (1);
290
291         case SHORT:
292         case USHORT:
293                 return (SZSHORT / SZCHAR);
294
295         case DOUBLE:
296                 return (SZDOUBLE / SZCHAR);
297
298         case INT:
299         case UNSIGNED:
300         case LONG:
301         case ULONG:
302                 return (SZINT / SZCHAR);
303
304         case LONGLONG:
305         case ULONGLONG:
306                 return SZLONGLONG / SZCHAR;
307
308         default:
309                 if (!ISPTR(p->n_type))
310                         comperr("tlen type %d not pointer");
311                 return SZPOINT(p->n_type) / SZCHAR;
312         }
ragge
1.1
313 }
314
315
316 /*
317  * Push a structure on stack as argument.
318  */
319 static void
gmcgarry
1.8
320 starg(NODE *p)
ragge
1.1
321 {
gmcgarry
1.8
322         //assert(p->n_rval == A1);
323         printf("\tsubu %s,%s,%d\n"rnames[SP], rnames[SP], p->n_stsize);
324         /* A0 = dest, A1 = src, A2 = len */
325         printf("\tmove %s,%s\n"rnames[A0], rnames[SP]);
326         printf("\tli %s,%d\t# structure size\n"rnames[A2], p->n_stsize);
327         printf("\tsubu %s,%s,16\n"rnames[SP], rnames[SP]);
gmcgarry
1.11
328         printf("\tjal %s\t# structure copy\n"exname("memcpy"));
gmcgarry
1.8
329         printf("\tnop\n");
330         printf("\taddiu %s,%s,16\n"rnames[SP], rnames[SP]);
ragge
1.1
331 }
332
gmcgarry
1.4
333 /*
334  * Structure assignment.
335  */
336 static void
337 stasg(NODE *p)
ragge
1.1
338 {
gmcgarry
1.4
339         assert(p->n_right->n_rval == A1);
340         /* A0 = dest, A1 = src, A2 = len */
gmcgarry
1.8
341         printf("\tli %s,%d\t# structure size\n"rnames[A2], p->n_stsize);
gmcgarry
1.4
342         if (p->n_left->n_op == OREG) {
gmcgarry
1.18
343                 printf("\taddiu %s,%s," CONFMT "\t# dest address\n",
gmcgarry
1.4
344                     rnames[A0], rnames[p->n_left->n_rval],
345                     p->n_left->n_lval);
346         } else if (p->n_left->n_op == NAME) {
347                 printf("\tla %s,"rnames[A0]);
348                 adrput(stdoutp->n_left);
349                 printf("\n");
350         }
gmcgarry
1.8
351         printf("\tsubu %s,%s,16\n"rnames[SP], rnames[SP]);
gmcgarry
1.11
352         printf("\tjal %s\t# structure copy\n"exname("memcpy"));
gmcgarry
1.4
353         printf("\tnop\n");
gmcgarry
1.8
354         printf("\taddiu %s,%s,16\n"rnames[SP], rnames[SP]);
gmcgarry
1.4
355 }
ragge
1.1
356
gmcgarry
1.4
357 static void
gmcgarry
1.8
358 shiftop(NODE *p)
ragge
1.1
359 {
gmcgarry
1.8
360         NODE *r = p->n_right;
361         TWORD ty = p->n_type;
gmcgarry
1.4
362
gmcgarry
1.8
363         if (p->n_op == LS && r->n_op == ICON && r->n_lval < 32) {
364                 expand(pINBREG"\tsrl A1,AL,");
gmcgarry
1.11
365                 printf(CONFMT "\t# 64-bit left-shift\n"32 - r->n_lval);
gmcgarry
1.13
366                 expand(pINBREG"\tsll U1,UL,AR\n");
gmcgarry
1.4
367                 expand(pINBREG"\tor U1,U1,A1\n");
gmcgarry
1.11
368                 expand(pINBREG"\tsll A1,AL,AR\n");
gmcgarry
1.8
369         } else if (p->n_op == LS && r->n_op == ICON && r->n_lval < 64) {
gmcgarry
1.13
370                 expand(pINBREG"\tli A1,0\t# 64-bit left-shift\n");
gmcgarry
1.11
371                 expand(pINBREG"\tsll U1,AL,");
gmcgarry
1.8
372                 printf(CONFMT "\n"r->n_lval - 32);
373         } else if (p->n_op == LS && r->n_op == ICON) {
gmcgarry
1.13
374                 expand(pINBREG"\tli A1,0\t# 64-bit left-shift\n");
gmcgarry
1.8
375                 expand(pINBREG"\tli U1,0\n");
376         } else if (p->n_op == RS && r->n_op == ICON && r->n_lval < 32) {
gmcgarry
1.11
377                 expand(pINBREG"\tsll U1,UL,");
378                 printf(CONFMT "\t# 64-bit right-shift\n"32 - r->n_lval);
gmcgarry
1.13
379                 expand(pINBREG"\tsrl A1,AL,AR\n");
gmcgarry
1.4
380                 expand(pINBREG"\tor A1,A1,U1\n");
gmcgarry
1.8
381                 if (ty == LONGLONG)
382                         expand(pINBREG"\tsra U1,UL,AR\n");
383                 else
384                         expand(pINBREG"\tsrl U1,UL,AR\n");
385         } else if (p->n_op == RS && r->n_op == ICON && r->n_lval < 64) {
386                 if (ty == LONGLONG) {
gmcgarry
1.15
387                         expand(pINBREG"\tsra U1,UL,31\t# 64-bit right-shift\n");
gmcgarry
1.8
388                         expand(pINBREG"\tsra A1,UL,");
389                 }else {
gmcgarry
1.11
390                         expand(pINBREG"\tli U1,0\t# 64-bit right-shift\n");
gmcgarry
1.13
391                         expand(pINBREG"\tsrl A1,UL,");
gmcgarry
1.8
392                 }
393                 printf(CONFMT "\n"r->n_lval - 32);
394         } else if (p->n_op == LS && r->n_op == ICON) {
gmcgarry
1.11
395                 expand(pINBREG"\tli A1,0\t# 64-bit right-shift\n");
gmcgarry
1.8
396                 expand(pINBREG"\tli U1,0\n");
gmcgarry
1.15
397         } else {
398                 comperr("shiftop");
gmcgarry
1.8
399         }
400 }
401
402 /*
403  * http://gcc.gnu.org/onlinedocs/gccint/Soft-float-library-routines.html#Soft-float-library-routines
404  */
405 static void
406 fpemulop(NODE *p)
407 {
408         NODE *l = p->n_left;
409         char *ch = NULL;
410
411         if (p->n_op == PLUS && p->n_type == FLOATch = "addsf3";
412         else if (p->n_op == PLUS && p->n_type == DOUBLEch = "adddf3";
413         else if (p->n_op == PLUS && p->n_type == LDOUBLEch = "addtf3";
414
415         else if (p->n_op == MINUS && p->n_type == FLOATch = "subsf3";
416         else if (p->n_op == MINUS && p->n_type == DOUBLEch = "subdf3";
417         else if (p->n_op == MINUS && p->n_type == LDOUBLEch = "subtf3";
418
419         else if (p->n_op == MUL && p->n_type == FLOATch = "mulsf3";
420         else if (p->n_op == MUL && p->n_type == DOUBLEch = "muldf3";
421         else if (p->n_op == MUL && p->n_type == LDOUBLEch = "multf3";
422
423         else if (p->n_op == DIV && p->n_type == FLOATch = "divsf3";
424         else if (p->n_op == DIV && p->n_type == DOUBLEch = "divdf3";
425         else if (p->n_op == DIV && p->n_type == LDOUBLEch = "divtf3";
426
427         else if (p->n_op == UMINUS && p->n_type == FLOATch = "negsf2";
428         else if (p->n_op == UMINUS && p->n_type == DOUBLEch = "negdf2";
429         else if (p->n_op == UMINUS && p->n_type == LDOUBLEch = "negtf2";
430
431         else if (p->n_op == EQ && l->n_type == FLOATch = "eqsf2";
432         else if (p->n_op == EQ && l->n_type == DOUBLEch = "eqdf2";
433         else if (p->n_op == EQ && l->n_type == LDOUBLEch = "eqtf2";
434
435         else if (p->n_op == NE && l->n_type == FLOATch = "nesf2";
436         else if (p->n_op == NE && l->n_type == DOUBLEch = "nedf2";
437         else if (p->n_op == NE && l->n_type == LDOUBLEch = "netf2";
438
439         else if (p->n_op == GE && l->n_type == FLOATch = "gesf2";
440         else if (p->n_op == GE && l->n_type == DOUBLEch = "gedf2";
441         else if (p->n_op == GE && l->n_type == LDOUBLEch = "getf2";
442
443         else if (p->n_op == LE && l->n_type == FLOATch = "lesf2";
444         else if (p->n_op == LE && l->n_type == DOUBLEch = "ledf2";
445         else if (p->n_op == LE && l->n_type == LDOUBLEch = "letf2";
446
447         else if (p->n_op == GT && l->n_type == FLOATch = "gtsf2";
448         else if (p->n_op == GT && l->n_type == DOUBLEch = "gtdf2";
449         else if (p->n_op == GT && l->n_type == LDOUBLEch = "gttf2";
450
451         else if (p->n_op == LT && l->n_type == FLOATch = "ltsf2";
452         else if (p->n_op == LT && l->n_type == DOUBLEch = "ltdf2";
453         else if (p->n_op == LT && l->n_type == LDOUBLEch = "lttf2";
454
455         else if (p->n_op == SCONV && p->n_type == FLOAT) {
456                 if (l->n_type == DOUBLEch = "truncdfsf2";
457                 else if (l->n_type == LDOUBLEch = "trunctfsf2";
gmcgarry
1.13
458                 else if (l->n_type == ULONGLONGch = "floatdisf"/**/
gmcgarry
1.12
459                 else if (l->n_type == LONGLONGch = "floatdisf";
460                 else if (l->n_type == LONGch = "floatsisf";
461                 else if (l->n_type == ULONGch = "floatunsisf";
gmcgarry
1.8
462                 else if (l->n_type == INTch = "floatsisf";
463                 else if (l->n_type == UNSIGNEDch = "floatunsisf";
464         } else if (p->n_op == SCONV && p->n_type == DOUBLE) {
465                 if (l->n_type == FLOATch = "extendsfdf2";
466                 else if (l->n_type == LDOUBLEch = "trunctfdf2";
gmcgarry
1.12
467                 else if (l->n_type == ULONGLONGch = "floatunsdidf";
468                 else if (l->n_type == LONGLONGch = "floatdidf";
469                 else if (l->n_type == LONGch = "floatsidf";
470                 else if (l->n_type == ULONGch = "floatunsidf";
gmcgarry
1.8
471                 else if (l->n_type == INTch = "floatsidf";
472                 else if (l->n_type == UNSIGNEDch = "floatunsidf";
473         } else if (p->n_op == SCONV && p->n_type == LDOUBLE) {
474                 if (l->n_type == FLOATch = "extendsftf2";
gmcgarry
1.12
475                 else if (l->n_type == DOUBLEch = "extenddfdf2";
476                 else if (l->n_type == ULONGLONGch = "floatunsdidf";
477                 else if (l->n_type == LONGLONGch = "floatdidf";
478                 else if (l->n_type == LONGch = "floatsidf";
479                 else if (l->n_type == ULONGch = "floatunssidf";
480                 else if (l->n_type == INTch = "floatsidf";
481                 else if (l->n_type == UNSIGNEDch = "floatunsidf";
gmcgarry
1.8
482         } else if (p->n_op == SCONV && p->n_type == ULONGLONG) {
gmcgarry
1.12
483                 if (l->n_type == FLOATch = "fixunssfdi";
484                 else if (l->n_type == DOUBLEch = "fixunsdfdi";
gmcgarry
1.13
485                 else if (l->n_type == LDOUBLEch = "fixunsdfdi";
gmcgarry
1.8
486         } else if (p->n_op == SCONV && p->n_type == LONGLONG) {
487                 if (l->n_type == FLOATch = "fixsfdi";
488                 else if (l->n_type == DOUBLEch = "fixdfdi";
gmcgarry
1.13
489                 else if (l->n_type == LDOUBLEch = "fixdfdi";
gmcgarry
1.12
490         } else if (p->n_op == SCONV && p->n_type == LONG) {
491                 if (l->n_type == FLOATch = "fixsfsi";
492                 else if (l->n_type == DOUBLEch = "fixdfsi";
gmcgarry
1.13
493                 else if (l->n_type == LDOUBLEch = "fixdfsi";
gmcgarry
1.8
494         } else if (p->n_op == SCONV && p->n_type == ULONG) {
gmcgarry
1.12
495                 if (l->n_type == FLOATch = "fixunssfsi";
496                 else if (l->n_type == DOUBLEch = "fixunsdfsi";
gmcgarry
1.13
497                 else if (l->n_type == LDOUBLEch = "fixunsdfsi";
gmcgarry
1.8
498         } else if (p->n_op == SCONV && p->n_type == INT) {
499                 if (l->n_type == FLOATch = "fixsfsi";
500                 else if (l->n_type == DOUBLEch = "fixdfsi";
gmcgarry
1.13
501                 else if (l->n_type == LDOUBLEch = "fixdfsi";
gmcgarry
1.8
502         } else if (p->n_op == SCONV && p->n_type == UNSIGNED) {
503                 if (l->n_type == FLOATch = "fixunssfsi";
504                 else if (l->n_type == DOUBLEch = "fixunsdfsi";
gmcgarry
1.13
505                 else if (l->n_type == LDOUBLEch = "fixunsdfsi";
gmcgarry
1.4
506         }
gmcgarry
1.8
507
508         if (ch == NULLcomperr("ZF: op=0x%x (%d)\n"p->n_opp->n_op);
509
gmcgarry
1.18
510         if (p->n_op == SCONV) {
511                 if (l->n_type == FLOAT) {
512                         printf("\tmfc1 %s,"rnames[A0]);
513                         adrput(stdoutl);
514                         printf("\n\tnop\n");
515                 }  else if (l->n_type == DOUBLE || l->n_type == LDOUBLE) {
516                         printf("\tmfc1 %s,"rnames[A1]);
517                         upput(l0);
518                         printf("\n\tnop\n");
519                         printf("\tmfc1 %s,"rnames[A0]);
520                         adrput(stdoutl);
521                         printf("\n\tnop\n");
522                 }
523         } else {
524                 comperr("ZF: incomplete softfloat - put args in registers");
525         }
526
gmcgarry
1.12
527         printf("\tjal __%s\t# softfloat operation\n"exname(ch));
gmcgarry
1.13
528         printf("\tnop\n");
gmcgarry
1.8
529
530         if (p->n_op >= EQ && p->n_op <= GT)
531                 printf("\tcmp %s,0\n"rnames[V0]);
ragge
1.1
532 }
533
gmcgarry
1.4
534 /*
gmcgarry
1.8
535  * http://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html#Integer-library-routines
gmcgarry
1.4
536  */
537 static void
538 emulop(NODE *p)
539 {
gmcgarry
1.8
540         char *ch = NULL;
541
gmcgarry
1.11
542         if (p->n_op == LS && DEUNSIGN(p->n_type) == LONGLONGch = "ashldi3";
543         else if (p->n_op == LS && (DEUNSIGN(p->n_type) == LONG ||
544             DEUNSIGN(p->n_type) == INT))
545                 ch = "ashlsi3";
546
547         else if (p->n_op == RS && p->n_type == ULONGLONGch = "lshrdi3";
548         else if (p->n_op == RS && (p->n_type == ULONG || p->n_type == INT))
549                 ch = "lshrsi3";
550
551         else if (p->n_op == RS && p->n_type == LONGLONGch = "ashrdi3";
552         else if (p->n_op == RS && (p->n_type == LONG || p->n_type == INT))
553                 ch = "ashrsi3";
gmcgarry
1.8
554         
gmcgarry
1.11
555         else if (p->n_op == DIV && p->n_type == LONGLONGch = "divdi3";
556         else if (p->n_op == DIV && (p->n_type == LONG || p->n_type == INT))
557                 ch = "divsi3";
558
559         else if (p->n_op == DIV && p->n_type == ULONGLONGch = "udivdi3";
560         else if (p->n_op == DIV && (p->n_type == ULONG ||
561             p->n_type == UNSIGNED))
562                 ch = "udivsi3";
563
564         else if (p->n_op == MOD && p->n_type == LONGLONGch = "moddi3";
565         else if (p->n_op == MOD && (p->n_type == LONG || p->n_type == INT))
566                 ch = "modsi3";
567
568         else if (p->n_op == MOD && p->n_type == ULONGLONGch = "umoddi3";
569         else if (p->n_op == MOD && (p->n_type == ULONG ||
570             p->n_type == UNSIGNED))
571                 ch = "umodsi3";
572
573         else if (p->n_op == MUL && p->n_type == LONGLONGch = "muldi3";
574         else if (p->n_op == MUL && (p->n_type == LONG || p->n_type == INT))
575                 ch = "mulsi3";
gmcgarry
1.8
576
gmcgarry
1.11
577         else if (p->n_op == UMINUS && p->n_type == LONGLONGch = "negdi2";
578         else if (p->n_op == UMINUS && p->n_type == LONGch = "negsi2";
gmcgarry
1.4
579
580         else ch = 0comperr("ZE");
gmcgarry
1.8
581         printf("\tsubu %s,%s,16\n"rnames[SP], rnames[SP]);
gmcgarry
1.11
582         printf("\tjal __%s\t# emulated operation\n"exname(ch));
gmcgarry
1.4
583         printf("\tnop\n");
gmcgarry
1.8
584         printf("\taddiu %s,%s,16\n"rnames[SP], rnames[SP]);
585 }
586
gmcgarry
1.11
587 /*
588  * Emit code to compare two longlong numbers.
589  */
590 static void
591 twollcomp(NODE *p)
592 {
593         int o = p->n_op;
594         int s = getlab();
595         int e = p->n_label;
596         int cb1cb2;
597
598         if (o >= ULE)
599                 o -= (ULE-LE);
600         switch (o) {
601         case NE:
602                 cb1 = 0;
603                 cb2 = NE;
604                 break;
605         case EQ:
606                 cb1 = NE;
607                 cb2 = 0;
608                 break;
609         case LE:
610         case LT:
611                 cb1 = GT;
612                 cb2 = LT;
613                 break;
614         case GE:
615         case GT:
616                 cb1 = LT;
617                 cb2 = GT;
618                 break;
619         
620         default:
621                 cb1 = cb2 = 0/* XXX gcc */
622         }
623         if (p->n_op >= ULE)
624                 cb1 += 4cb2 += 4;
625         expand(p0"\tsub A1,UL,UR\t# compare 64-bit values (upper)\n");
626         if (cb1) {
627                 printf("\t");
628                 hopcode(' 'cb1);
629                 expand(p0"A1");
630                 printf("," LABFMT "\n"s);
gmcgarry
1.13
631                 printf("\tnop\n");
gmcgarry
1.11
632         }
633         if (cb2) {
634                 printf("\t");
635                 hopcode(' 'cb2);
636                 expand(p0"A1");
637                 printf("," LABFMT "\n"e);
gmcgarry
1.13
638                 printf("\tnop\n");
gmcgarry
1.11
639         }
640         expand(p0"\tsub A1,AL,AR\t# (and lower)\n");
641         printf("\t");
642         hopcode(' 'o);
643         expand(p0"A1");
644         printf("," LABFMT "\n"e);
gmcgarry
1.13
645         printf("\tnop\n");
gmcgarry
1.11
646         deflab(s);
647 }
648
gmcgarry
1.8
649 static void
650 fpcmpops(NODE *p)
651 {
gmcgarry
1.13
652         NODE *l = p->n_left;
653
gmcgarry
1.8
654         switch (p->n_op) {
655         case EQ:
gmcgarry
1.13
656                 if (l->n_type == FLOAT)
657                         expand(p0"\tc.eq.s AL,AR\n");
gmcgarry
1.8
658                 else
gmcgarry
1.13
659                         expand(p0"\tc.eq.d AL,AR\n");
660                 expand(p0"\tnop\n\tbc1t LC\n");
gmcgarry
1.8
661                 break;
662         case NE:
gmcgarry
1.13
663                 if (l->n_type == FLOAT)
664                         expand(p0"\tc.eq.s AL,AR\n");
gmcgarry
1.8
665                 else
gmcgarry
1.13
666                         expand(p0"\tc.eq.d AL,AR\n");
667                 expand(p0"\tnop\n\tbc1f LC\n");
gmcgarry
1.8
668                 break;
669         case LT:
gmcgarry
1.13
670                 if (l->n_type == FLOAT)
671                         expand(p0"\tc.lt.s AL,AR\n");
gmcgarry
1.8
672                 else
gmcgarry
1.13
673                         expand(p0"\tc.lt.d AL,AR\n");
674                 expand(p0"\tnop\n\tbc1t LC\n");
gmcgarry
1.8
675                 break;
676         case GE:
gmcgarry
1.13
677                 if (l->n_type == FLOAT)
678                         expand(p0"\tc.lt.s AL,AR\n");
gmcgarry
1.8
679                 else
gmcgarry
1.13
680                         expand(p0"\tc.lt.d AL,AR\n");
681                 expand(p0"\tnop\n\tbc1f LC\n");
gmcgarry
1.8
682                 break;
683         case LE:
gmcgarry
1.13
684                 if (l->n_type == FLOAT)
685                         expand(p0"\tc.le.s AL,AR\n");
gmcgarry
1.8
686                 else
gmcgarry
1.13
687                         expand(p0"\tc.le.d AL,AR\n");
688                 expand(p0"\tnop\n\tbc1t LC\n");
gmcgarry
1.8
689                 break;
690         case GT:
gmcgarry
1.13
691                 if (l->n_type == FLOAT)
692                         expand(p0"\tc.le.s AL,AR\n");
gmcgarry
1.8
693                 else
gmcgarry
1.13
694                         expand(p0"\tc.le.d AL,AR\n");
695                 expand(p0"\tnop\n\tbc1f LC\n");
gmcgarry
1.8
696                 break;
697         }
gmcgarry
1.13
698         printf("\tnop\n\tnop\n");
gmcgarry
1.4
699 }
700
701 void
702 zzzcode(NODE * pint c)
ragge
1.1
703 {
gmcgarry
1.4
704         int sz;
705
706         switch (c) {
707
708         case 'C':       /* remove arguments from stack after subroutine call */
709                 sz = p->n_qual > 16 ? p->n_qual : 16;
gmcgarry
1.18
710                 printf("\taddiu %s,%s,%d\n"rnames[SP], rnames[SP], sz);
gmcgarry
1.8
711                 break;
712
gmcgarry
1.11
713         case 'D':       /* long long comparison */
714                 twollcomp(p);
715                 break;
716
gmcgarry
1.8
717         case 'E':       /* emit emulated ops */
718                 emulop(p);
719                 break;
720
721         case 'F':       /* emit emulate floating point ops */
722                 fpemulop(p);
723                 break;
724
725         case 'G':       /* emit hardware floating-point compare op */
726                 fpcmpops(p);
727                 break;
728
729         case 'H':       /* structure argument */
730                 starg(p);
gmcgarry
1.4
731                 break;
732
733         case 'I':               /* high part of init constant */
734                 if (p->n_name[0] != '\0')
735                         comperr("named highword");
736                 fprintf(stdoutCONFMT, (p->n_lval >> 32) & 0xffffffff);
737                 break;
738
739         case 'O'/* 64-bit left and right shift operators */
gmcgarry
1.8
740                 shiftop(p);
gmcgarry
1.4
741                 break;
742
gmcgarry
1.8
743         case 'Q':               /* emit struct assign */
744                 stasg(p);
gmcgarry
1.4
745                 break;
746
747         default:
748                 comperr("zzzcode %c"c);
749         }
ragge
1.1
750 }
751
gmcgarry
1.4
752 /* ARGSUSED */
ragge
1.1
753 int
gmcgarry
1.4
754 rewfld(NODE * p)
ragge
1.1
755 {
gmcgarry
1.4
756         return (1);
ragge
1.1
757 }
758
stefan
1.14
759 int
760 fldexpand(NODE *pint cookiechar **cp)
761 {
gmcgarry
1.15
762         CONSZ val;
763
764         if (p->n_op == ASSIGN)
765                 p = p->n_left;
766         switch (**cp) {
767         case 'S':
768                 printf("%d"UPKFSZ(p->n_rval));
769                 break;
770         case 'H':
771                 printf("%d"UPKFOFF(p->n_rval));
772                 break;
773         case 'M':
774         case 'N':
stefan
1.16
775                 val = (CONSZ)1 << UPKFSZ(p->n_rval);
gmcgarry
1.15
776                 --val;
777                 val <<= UPKFOFF(p->n_rval);
778                 printf("0x%llx", (**cp == 'M' ? val : ~val)  & 0xffffffff);
779                 break;
780         default:
781                 comperr("fldexpand");
782         }
783         return 1;
stefan
1.14
784 }
785
ragge
1.1
786 /*
787  * Does the bitfield shape match?
788  */
789 int
gmcgarry
1.4
790 flshape(NODE * p)
ragge
1.1
791 {
gmcgarry
1.4
792         int o = p->n_op;
ragge
1.1
793
gmcgarry
1.4
794         if (o == OREG || o == REG || o == NAME)
795                 return SRDIR;   /* Direct match */
796         if (o == UMUL && shumul(p->n_left))
797                 return SROREG;  /* Convert into oreg */
798         return SRREG;           /* put it into a register */
ragge
1.1
799 }
800
801 /* INTEMP shapes must not contain any temporary registers */
802 /* XXX should this go away now? */
803 int
gmcgarry
1.4
804 shtemp(NODE * p)
ragge
1.1
805 {
gmcgarry
1.4
806         return 0;
ragge
1.1
807 #if 0
gmcgarry
1.4
808         int r;
ragge
1.1
809
gmcgarry
1.4
810         if (p->n_op == STARG)
811                 p = p->n_left;
812
813         switch (p->n_op) {
814         case REG:
815                 return (!istreg(p->n_rval));
816
817         case OREG:
818                 r = p->n_rval;
819                 if (R2TEST(r)) {
820                         if (istreg(R2UPK1(r)))
821                                 return (0);
822                         r = R2UPK2(r);
823                 }
824                 return (!istreg(r));
825
826         case UMUL:
827                 p = p->n_left;
828                 return (p->n_op != UMUL && shtemp(p));
829         }
ragge
1.1
830
gmcgarry
1.4
831         if (optype(p->n_op) != LTYPE)
832                 return (0);
833         return (1);
ragge
1.1
834 #endif
835 }
836
837 void
838 adrcon(CONSZ val)
839 {
gmcgarry
1.4
840         printf(CONFMTval);
ragge
1.1
841 }
842
843 void
gmcgarry
1.18
844 conput(FILE *fpNODE *p)
ragge
1.1
845 {
gmcgarry
1.18
846         int val = p->n_lval;
847
gmcgarry
1.4
848         switch (p->n_op) {
849         case ICON:
850                 if (p->n_name[0] != '\0') {
851                         fprintf(fp"%s"p->n_name);
gmcgarry
1.13
852                         if (p->n_lval)
gmcgarry
1.18
853                                 fprintf(fp"+%d"val);
gmcgarry
1.4
854                 } else
gmcgarry
1.18
855                         fprintf(fp"%d"val);
gmcgarry
1.4
856                 return;
ragge
1.1
857
gmcgarry
1.4
858         default:
859                 comperr("illegal conput");
860         }
ragge
1.1
861 }
862
gmcgarry
1.4
863 /* ARGSUSED */
ragge
1.1
864 void
gmcgarry
1.4
865 insput(NODE * p)
ragge
1.1
866 {
gmcgarry
1.4
867         comperr("insput");
868 }
869
870 /*
871  * Print lower or upper name of 64-bit register.
872  */
873 static void
874 print_reg64name(FILE *fpint rvalint hi)
875 {
gmcgarry
1.8
876         int off = 4 * (hi != 0);
gmcgarry
1.7
877         char *regname = rnames[rval];
gmcgarry
1.4
878
879         fprintf(fp"%c%c",
gmcgarry
1.7
880                  regname[off],
881                  regname[off + 1]);
882         if (regname[off + 2] != '!')
883                 fputc(regname[off + 2], fp);
gmcgarry
1.8
884         if (regname[off + 3] != '!')
885                 fputc(regname[off + 3], fp);
ragge
1.1
886 }
887
888 /*
889  * Write out the upper address, like the upper register of a 2-register
890  * reference, or the next memory location.
891  */
892 void
gmcgarry
1.4
893 upput(NODE * pint size)
ragge
1.1
894 {
895
gmcgarry
1.4
896         size /= SZCHAR;
897         switch (p->n_op) {
898         case REG:
gmcgarry
1.11
899                 if (GCLASS(p->n_rval) == CLASSB || GCLASS(p->n_rval) == CLASSC)
gmcgarry
1.7
900                         print_reg64name(stdoutp->n_rval1);
901                 else
902                         fputs(rnames[p->n_rval], stdout);
gmcgarry
1.4
903                 break;
904
905         case NAME:
906         case OREG:
907                 p->n_lval += size;
908                 adrput(stdoutp);
909                 p->n_lval -= size;
910                 break;
911         case ICON:
912                 fprintf(stdoutCONFMTp->n_lval >> 32);
913                 break;
914         default:
915                 comperr("upput bad op %d size %d"p->n_opsize);
916         }
ragge
1.1
917 }
918
919 void
gmcgarry
1.4
920 adrput(FILE * ioNODE * p)
ragge
1.1
921 {
gmcgarry
1.4
922         int r;
923         /* output an address, with offsets, from p */
924
925         if (p->n_op == FLD)
926                 p = p->n_left;
927
928         switch (p->n_op) {
929
930         case NAME:
931                 if (p->n_name[0] != '\0')
932                         fputs(p->n_nameio);
933                 if (p->n_lval != 0)
934                         fprintf(io"+" CONFMTp->n_lval);
935                 return;
936
937         case OREG:
938                 r = p->n_rval;
ragge
1.1
939
gmcgarry
1.4
940                 if (p->n_lval)
941                         fprintf(io"%d", (intp->n_lval);
ragge
1.1
942
gmcgarry
1.4
943                 fprintf(io"(%s)"rnames[p->n_rval]);
944                 return;
945         case ICON:
946                 /* addressable value of the constant */
947                 conput(iop);
948                 return;
ragge
1.1
949
gmcgarry
1.4
950         case REG:
gmcgarry
1.11
951                 if (GCLASS(p->n_rval) == CLASSB || GCLASS(p->n_rval) == CLASSC)
gmcgarry
1.4
952                         print_reg64name(iop->n_rval0);
953                 else
954                         fputs(rnames[p->n_rval], io);
955                 return;
ragge
1.1
956
gmcgarry
1.4
957         default:
958                 comperr("illegal address, op %d, node %p"p->n_opp);
959                 return;
ragge
1.1
960
gmcgarry
1.4
961         }
ragge
1.1
962 }
963
gmcgarry
1.4
964 /* printf conditional and unconditional branches */
965 void
966 cbgen(int oint lab)
ragge
1.1
967 {
968 }
969
970 void
gmcgarry
1.4
971 myreader(struct interpass * ipole)
ragge
1.1
972 {
973 }
974
gmcgarry
1.18
9