Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20080622152459

Diff

Diff from 1.16 to:

Annotations

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

Annotated File View

ragge
1.16
1 /*      $Id: local2.c,v 1.16 2008/06/22 15:25:00 ragge Exp $    */
gmcgarry
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 #include <assert.h>
30
31 #include "pass1.h" // for exname()
32 #include "pass2.h"
33 #include <ctype.h>
34 #include <string.h>
35 #include <stdlib.h>
36
gmcgarry
1.12
37 #define LOWREG          0
38 #define HIREG           1
gmcgarry
1.1
39
gmcgarry
1.12
40 char *rnames[] = {
41         REGPREFIX "r0"REGPREFIX "r1",
42         REGPREFIX "r2"REGPREFIX "r3",
43         REGPREFIX "r4"REGPREFIX "r5",
44         REGPREFIX "r6"REGPREFIX "r7",
45         REGPREFIX "r8"REGPREFIX "r9",
46         REGPREFIX "r10"REGPREFIX "r11",
47         REGPREFIX "r12"REGPREFIX "r13",
48         REGPREFIX "r14"REGPREFIX "r15",
49         REGPREFIX "r16"REGPREFIX "r17",
50         REGPREFIX "r18"REGPREFIX "r19",
51         REGPREFIX "r20"REGPREFIX "r21",
52         REGPREFIX "r22"REGPREFIX "r23",
53         REGPREFIX "r24"REGPREFIX "r25",
54         REGPREFIX "r26"REGPREFIX "r27",
55         REGPREFIX "r28"REGPREFIX "r29",
56         REGPREFIX "r30"REGPREFIX "r31",
57         "r4\0r3\0""r5\0r4\0""r6\0r5\0""r7\0r6\0",
58         "r8\0r7\0""r9\0r8\0""r10r9\0""r15r14""r17r16",
59         "r19r18""r21r20""r23r22""r25r24""r27r26",
60         "r29r28""r31r30",
61         REGPREFIX "f0"REGPREFIX "f1",
62         REGPREFIX "f2"REGPREFIX "f3",
63         REGPREFIX "f4"REGPREFIX "f5",
64         REGPREFIX "f6"REGPREFIX "f7",
65         REGPREFIX "f8"REGPREFIX "f9",
66         REGPREFIX "f10"REGPREFIX "f11",
67         REGPREFIX "f12"REGPREFIX "f13",
68         REGPREFIX "f14"REGPREFIX "f15",
69         REGPREFIX "f16"REGPREFIX "f17",
70         REGPREFIX "f18"REGPREFIX "f19",
71         REGPREFIX "f20"REGPREFIX "f21",
72         REGPREFIX "f22"REGPREFIX "f23",
73         REGPREFIX "f24"REGPREFIX "f25",
74         REGPREFIX "f26"REGPREFIX "f27",
75         REGPREFIX "f28"REGPREFIX "f29",
76         REGPREFIX "f30"REGPREFIX "f31",
77 };
gmcgarry
1.1
78
gmcgarry
1.12
79 static int argsize(NODE *p);
gmcgarry
1.1
80
gmcgarry
1.12
81 static int p2calls;
82 static int p2temps;             /* TEMPs which aren't autos yet */
83 static int p2framesize;
84 static int p2maxstacksize;
gmcgarry
1.1
85
86 void
87 deflab(int label)
88 {
89         printf(LABFMT ":\n"label);
90 }
91
92 static TWORD ftype;
93
94 /*
95  * Print out the prolog assembler.
96  */
97 void
98 prologue(struct interpass_prolog *ipp)
99 {
100         int addto;
101
102 #ifdef PCC_DEBUG
103         if (x2debug)
104                 printf("prologue: type=%d, lineno=%d, name=%s, vis=%d, ipptype=%d, regs=0x%x, autos=%d, tmpnum=%d, lblnum=%d\n",
105                         ipp->ipp_ip.type,
106                         ipp->ipp_ip.lineno,
107                         ipp->ipp_name,
108                         ipp->ipp_vis,
109                         ipp->ipp_type,
110                         ipp->ipp_regs,
111                         ipp->ipp_autos,
112                         ipp->ip_tmpnum,
113                         ipp->ip_lblnum);
114 #endif
115
116         ftype = ipp->ipp_type;
gmcgarry
1.12
117
118         addto = p2framesize;
119
120         if (p2calls != 0 || kflag) {
121                 // get return address (not required for leaf function)
122                 printf("\tmflr %s\n"rnames[R0]);
123                 printf("\tstw %s,8(%s)\n"rnames[R0], rnames[R1]);
124         }
125         // save registers R30 and R31
126         printf("\tstmw %s,-8(%s)\n"rnames[R30], rnames[R1]);
127 #ifdef FPREG
128         printf("\tmr %s,%s\n"rnames[FPREG], rnames[R1]);
129 #endif
130         // create the new stack frame
131         if (addto > 65535) {
132                 printf("\tlis %s,%d\n"rnames[R0], (-addto) >> 16);
133                 printf("\tori %s,%s,%d\n"rnames[R0],
134                     rnames[R0], (-addto) & 0xffff);
135                 printf("\tstwux %s,%s,%s\n"rnames[R1],
136                     rnames[R1], rnames[R0]);
137         } else {
138                 printf("\tstwu %s,-%d(%s)\n"rnames[R1], addtornames[R1]);
139         }
140
141         if (kflag) {
142 #if defined(ELFABI)
143                 printf("\tbl _GLOBAL_OFFSET_TABLE_@local-4\n");
144                 printf("\tmflr %s\n"rnames[GOTREG]);
145 #elif defined(MACHOABI)
146                 printf("\tbcl 20,31,L%s$pb\n"ipp->ipp_name);
147                 printf("L%s$pb:\n"ipp->ipp_name);
148                 printf("\tmflr %s\n"rnames[GOTREG]);
ragge
1.10
149 #endif
gmcgarry
1.12
150         }
151
gmcgarry
1.1
152 }
153
gmcgarry
1.12
154
gmcgarry
1.1
155 void
156 eoftn(struct interpass_prolog *ipp)
157 {
158
159 #ifdef PCC_DEBUG
160         if (x2debug)
161                 printf("eoftn:\n");
162 #endif
163
164         if (ipp->ipp_ip.ip_lbl == 0)
165                 return/* no code needs to be generated */
166
gmcgarry
1.12
167         /* struct return needs special treatment */
168         if (ftype == STRTY || ftype == UNIONTY
169                 cerror("eoftn");
gmcgarry
1.1
170
gmcgarry
1.12
171         /* unwind stack frame */
172         printf("\tlwz %s,0(%s)\n"rnames[R1], rnames[R1]);
173         if (p2calls != 0 || kflag) {
gmcgarry
1.3
174                 printf("\tlwz %s,8(%s)\n"rnames[R0], rnames[R1]);
175                 printf("\tmtlr %s\n"rnames[R0]);
gmcgarry
1.1
176         }
gmcgarry
1.12
177         printf("\tlmw %s,-8(%s)\n"rnames[R30], rnames[R1]);
178         printf("\tblr\n");
gmcgarry
1.1
179 }
180
181 /*
182  * add/sub/...
183  *
184  * Param given:
185  */
186 void
187 hopcode(int fint o)
188 {
189         char *str;
190
191         switch (o) {
192         case PLUS:
193                 str = "addw";
194                 break;
195         case MINUS:
196                 str = "subw";
197                 break;
198         case AND:
199                 str = "and";
200                 break;
201         case OR:
202                 str = "or";
203                 break;
204         case ER:
205                 str = "xor";
206                 break;
207         default:
208                 comperr("hopcode2: %d"o);
209                 str = 0/* XXX gcc */
210         }
211         printf("%s%c"strf);
212 }
213
214 /*
215  * Return type size in bytes.  Used by R2REGS, arg 2 to offset().
216  */
217 int
gmcgarry
1.3
218 tlen(NODE *p)
gmcgarry
1.1
219 {
220         switch(p->n_type) {
221                 case CHAR:
222                 case UCHAR:
223                         return(1);
224
225                 case SHORT:
226                 case USHORT:
227                         return(SZSHORT/SZCHAR);
228
229                 case DOUBLE:
230                         return(SZDOUBLE/SZCHAR);
231
232                 case INT:
233                 case UNSIGNED:
234                 case LONG:
235                 case ULONG:
236                         return(SZINT/SZCHAR);
237
238                 case LONGLONG:
239                 case ULONGLONG:
240                         return SZLONGLONG/SZCHAR;
241
242                 default:
243                         if (!ISPTR(p->n_type))
244                                 comperr("tlen type %d not pointer");
245                         return SZPOINT(p->n_type)/SZCHAR;
246                 }
247 }
248
249 /*
250  * Emit code to compare two longlong numbers.
251  */
252 static void
253 twollcomp(NODE *p)
254 {
255         int o = p->n_op;
256         int s = getlab();
257         int e = p->n_label;
258         int cb1cb2;
259
260         if (o >= ULE)
261                 o -= (ULE-LE);
262         switch (o) {
263         case NE:
264                 cb1 = 0;
265                 cb2 = NE;
266                 break;
267         case EQ:
268                 cb1 = NE;
269                 cb2 = 0;
270                 break;
271         case LE:
272         case LT:
273                 cb1 = GT;
274                 cb2 = LT;
275                 break;
276         case GE:
277         case GT:
278                 cb1 = LT;
279                 cb2 = GT;
280                 break;
281         
282         default:
283                 cb1 = cb2 = 0/* XXX gcc */
284         }
285         if (p->n_op >= ULE)
286                 cb1 += 4cb2 += 4;
gmcgarry
1.12
287         if (p->n_op >= ULE)
288                 expand(p0"\tcmplw UL,UR" COM "compare 64-bit values (upper)\n");
289         else
290                 expand(p0"\tcmpw UL,UR" COM "compare 64-bit values (upper)\n");
gmcgarry
1.1
291         if (cb1cbgen(cb1s);
292         if (cb2cbgen(cb2e);
gmcgarry
1.12
293         if (p->n_op >= ULE)
294                 expand(p0"\tcmplw AL,AR" COM "(and lower)\n");
295         else
296                 expand(p0"\tcmpw AL,AR" COM "(and lower)\n");
gmcgarry
1.1
297         cbgen(p->n_ope);
298         deflab(s);
299 }
300
gmcgarry
1.12
301 static void
302 shiftop(NODE *p)
303 {
304         NODE *r = p->n_right;
305         TWORD ty = p->n_type;
306
307         if (p->n_op == LS && r->n_op == ICON && r->n_lval < 32) {
308                 expand(pINBREG"\tsrwi A1,AL,32-AR" COM "64-bit left-shift\n");
309                 expand(pINBREG"\tslwi U1,UL,AR\n");
310                 expand(pINBREG"\tor U1,U1,A1\n");
311                 expand(pINBREG"\tslwi A1,AL,AR\n");
312         } else if (p->n_op == LS && r->n_op == ICON && r->n_lval < 64) {
313                 expand(pINBREG"\tli A1,0" COM "64-bit left-shift\n");
314                 if (r->n_lval == 32)
315                         expand(pINBREG"\tmr U1,AL\n");
316                 else
317                         expand(pINBREG"\tslwi U1,AL,AR-32\n");
318         } else if (p->n_op == LS && r->n_op == ICON) {
319                 expand(pINBREG"\tli A1,0" COM "64-bit left-shift\n");
320                 expand(pINBREG"\tli U1,0\n");
321         } else if (p->n_op == RS && r->n_op == ICON && r->n_lval < 32) {
322                 expand(pINBREG"\tslwi U1,UL,32-AR" COM "64-bit right-shift\n");
323                 expand(pINBREG"\tsrwi A1,AL,AR\n");
324                 expand(pINBREG"\tor A1,A1,U1\n");
325                 if (ty == LONGLONG)
326                         expand(pINBREG"\tsrawi U1,UL,AR\n");
327                 else
328                         expand(pINBREG"\tsrwi U1,UL,AR\n");
329         } else if (p->n_op == RS && r->n_op == ICON && r->n_lval < 64) {
330                 if (ty == LONGLONG)
331                         expand(pINBREG"\tli U1,-1" COM "64-bit right-shift\n");
332                 else
333                         expand(pINBREG"\tli U1,0" COM "64-bit right-shift\n");
334                 if (r->n_lval == 32)
335                         expand(pINBREG"\tmr A1,UL\n");
336                 else if (ty == LONGLONG)
337                         expand(pINBREG"\tsrawi A1,UL,AR-32\n");
338                 else
339                         expand(pINBREG"\tsrwi A1,UL,AR-32\n");
340         } else if (p->n_op == RS && r->n_op == ICON) {
341                 expand(pINBREG"\tli A1,0" COM "64-bit right-shift\n");
342                 expand(pINBREG"\tli U1,0\n");
343         }
344 }
345
gmcgarry
1.1
346 /*
gmcgarry
1.12
347  * Structure assignment.
gmcgarry
1.1
348  */
349 static void
gmcgarry
1.12
350 stasg(NODE *p)
gmcgarry
1.1
351 {
gmcgarry
1.13
352         NODE *l = p->n_left;
353         int val = l->n_lval;
354
gmcgarry
1.12
355         /* R3 = dest, R4 = src, R5 = len */
356         printf("\tli %s,%d\n"rnames[R5], p->n_stsize);
gmcgarry
1.13
357         if (l->n_op == OREG) {
gmcgarry
1.14
358                 printf("\taddi %s,%s,%d\n"rnames[R3], rnames[regno(l)], val);
gmcgarry
1.13
359         } else if (l->n_op == NAME) {
gmcgarry
1.12
360 #if defined(ELFABI)
361                 printf("\tli %s,"rnames[R3]);
gmcgarry
1.13
362                 adrput(stdoutl);
gmcgarry
1.12
363                 printf("@ha\n");
364                 printf("\taddi %s,%s,"rnames[R3], rnames[R3]);
gmcgarry
1.13
365                 adrput(stdoutl);
gmcgarry
1.12
366                 printf("@l\n");
367 #elif defined(MACHOABI)
368                 printf("\tli %s,ha16("rnames[R3]);
gmcgarry
1.13
369                 adrput(stdoutl);
gmcgarry
1.12
370                 printf(")\n");
371                 printf("\taddi %s,%s,lo16("rnames[R3], rnames[R3]);
gmcgarry
1.13
372                 adrput(stdoutl);
gmcgarry
1.12
373                 printf(")\n");
374 #endif
375         }
376         if (kflag) {
377 #if defined(ELFABI)
378                 printf("\tbl %s@got(30)\n"exname("memcpy"));
379 #elif defined(MACHOABI)
380                 printf("\tbl L%s$stub\n""memcpy");
381                 addstub(&stublist"memcpy");
382 #endif
383         } else {
384                 printf("\tbl %s\n"exname("memcpy"));
385         }
gmcgarry
1.1
386 }
gmcgarry
1.12
387
388 static void
389 fpemul(NODE *p)
390 {
391         NODE *l = p->n_left;
392         char *ch = NULL;
393
394         if (p->n_op == PLUS && p->n_type == FLOATch = "addsf3";
395         else if (p->n_op == PLUS && p->n_type == DOUBLEch = "adddf3";
396         else if (p->n_op == PLUS && p->n_type == LDOUBLEch = "addtf3";
397
398         else if (p->n_op == MINUS && p->n_type == FLOATch = "subsf3";
399         else if (p->n_op == MINUS && p->n_type == DOUBLEch = "subdf3";
400         else if (p->n_op == MINUS && p->n_type == LDOUBLEch = "subtf3";
401
402         else if (p->n_op == MUL && p->n_type == FLOATch = "mulsf3";
403         else if (p->n_op == MUL && p->n_type == DOUBLEch = "muldf3";
404         else if (p->n_op == MUL && p->n_type == LDOUBLEch = "multf3";
405
406         else if (p->n_op == DIV && p->n_type == FLOATch = "divsf3";
407         else if (p->n_op == DIV && p->n_type == DOUBLEch = "divdf3";
408         else if (p->n_op == DIV && p->n_type == LDOUBLEch = "divtf3";
409
410         else if (p->n_op == UMINUS && p->n_type == FLOATch = "negsf2";
411         else if (p->n_op == UMINUS && p->n_type == DOUBLEch = "negdf2";
412         else if (p->n_op == UMINUS && p->n_type == LDOUBLEch = "negtf2";
413
414         else if (p->n_op == EQ && l->n_type == FLOATch = "eqsf2";
415         else if (p->n_op == EQ && l->n_type == DOUBLEch = "eqdf2";
416         else if (p->n_op == EQ && l->n_type == LDOUBLEch = "eqtf2";
417
418         else if (p->n_op == NE && l->n_type == FLOATch = "nesf2";
419         else if (p->n_op == NE && l->n_type == DOUBLEch = "nedf2";
420         else if (p->n_op == NE && l->n_type == LDOUBLEch = "netf2";
421
422         else if (p->n_op == GE && l->n_type == FLOATch = "gesf2";
423         else if (p->n_op == GE && l->n_type == DOUBLEch = "gedf2";
424         else if (p->n_op == GE && l->n_type == LDOUBLEch = "getf2";
425
426         else if (p->n_op == LE && l->n_type == FLOATch = "lesf2";
427         else if (p->n_op == LE && l->n_type == DOUBLEch = "ledf2";
428         else if (p->n_op == LE && l->n_type == LDOUBLEch = "letf2";
429
430         else if (p->n_op == GT && l->n_type == FLOATch = "gtsf2";
431         else if (p->n_op == GT && l->n_type == DOUBLEch = "gtdf2";
432         else if (p->n_op == GT && l->n_type == LDOUBLEch = "gttf2";
433
434         else if (p->n_op == LT && l->n_type == FLOATch = "ltsf2";
435         else if (p->n_op == LT && l->n_type == DOUBLEch = "ltdf2";
436         else if (p->n_op == LT && l->n_type == LDOUBLEch = "lttf2";
437
438         else if (p->n_op == SCONV && p->n_type == FLOAT) {
439                 if (l->n_type == DOUBLEch = "truncdfsf2";
440                 else if (l->n_type == LDOUBLEch = "truncdfsf2";
441                 else if (l->n_type == ULONGLONGch = "floatunsdisf";
442                 else if (l->n_type == LONGLONGch = "floatdisf";
443                 else if (l->n_type == LONGch = "floatsisf";
444                 else if (l->n_type == ULONGch = "floatunsisf";
445                 else if (l->n_type == INTch = "floatsisf";
446                 else if (l->n_type == UNSIGNEDch = "floatunsisf";
447         } else if (p->n_op == SCONV && p->n_type == DOUBLE) {
448                 if (l->n_type == FLOATch = "extendsfdf2";
449                 else if (l->n_type == LDOUBLEch = "truncdfdf2";
450                 else if (l->n_type == ULONGLONGch = "floatunsdidf";
451                 else if (l->n_type == LONGLONGch = "floatdidf";
452                 else if (l->n_type == LONGch = "floatsidf";
453                 else if (l->n_type == ULONGch = "floatunssidf";
454                 else if (l->n_type == INTch = "floatsidf";
455                 else if (l->n_type == UNSIGNEDch = "floatunssidf";
456         } else if (p->n_op == SCONV && p->n_type == LDOUBLE) {
457                 if (l->n_type == FLOATch = "extendsfdf2";
458                 else if (l->n_type == DOUBLEch = "extenddfdf2";
459                 else if (l->n_type == ULONGLONGch = "floatunsdidf";
460                 else if (l->n_type == LONGLONGch = "floatdidf";
461                 else if (l->n_type == LONGch = "floatsidf";
462                 else if (l->n_type == ULONGch = "floatunssidf";
463                 else if (l->n_type == INTch = "floatsidf";
464                 else if (l->n_type == UNSIGNEDch = "floatunsidf";
465         } else if (p->n_op == SCONV && p->n_type == ULONGLONG) {
466                 if (l->n_type == FLOATch = "fixunssfdi";
467                 else if (l->n_type == DOUBLEch = "fixunsdfdi";
468                 else if (l->n_type == LDOUBLEch = "fixunsdfdi";
469         } else if (p->n_op == SCONV && p->n_type == LONGLONG) {
470                 if (l->n_type == FLOATch = "fixsfdi";
471                 else if (l->n_type == DOUBLEch = "fixdfdi";
472                 else if (l->n_type == LDOUBLEch = "fixtfdi";
473         } else if (p->n_op == SCONV && p->n_type == LONG) {
474                 if (l->n_type == FLOATch = "fixsfdi";
475                 else if (l->n_type == DOUBLEch = "fixdfdi";
476                 else if (l->n_type == LDOUBLEch = "fixtfdi";
477         } else if (p->n_op == SCONV && p->n_type == ULONG) {
478                 if (l->n_type == FLOATch = "fixunssfdi";
479                 else if (l->n_type == DOUBLEch = "fixunsdfdi";
480                 else if (l->n_type == LDOUBLEch = "fixunstfdi";
481         } else if (p->n_op == SCONV && p->n_type == INT) {
482                 if (l->n_type == FLOATch = "fixsfsi";
483                 else if (l->n_type == DOUBLEch = "fixdfsi";
484                 else if (l->n_type == LDOUBLEch = "fixdfsi";
485         } else if (p->n_op == SCONV && p->n_type == UNSIGNED) {
486                 if (l->n_type == FLOATch = "fixunssfsi";
487                 else if (l->n_type == DOUBLEch = "fixunsdfsi";
488                 else if (l->n_type == LDOUBLEch = "fixunsdfsi";
489         }
490
491         if (ch == NULLcomperr("ZF: op=0x%x (%d)\n"p->n_opp->n_op);
492
493         if (kflag) {
494 #if defined(ELFABI)
495                 printf("\tbl __%s@got(30)" COM "soft-float\n"exname(ch));
496 #elif defined(MACHOABI)
497                 char buf[32];
498                 printf("\tbl L__%s$stub" COM "soft-float\n"ch);
499                 snprintf(buf32"__%s"ch);
500                 addstub(&stublistbuf);
gmcgarry
1.1
501 #endif
gmcgarry
1.12
502         } else {
503                 printf("\tbl __%s" COM "soft-float\n"exname(ch));
504         }
505
506         if (p->n_op >= EQ && p->n_op <= GT)
507                 printf("\tcmpwi %s,0\n"rnames[R3]);
508 }
gmcgarry
1.1
509
510 /*
gmcgarry
1.12
511  * http://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html#Integer-library-routines
gmcgarry
1.1
512  */
gmcgarry
1.12
513
gmcgarry
1.1
514 static void
gmcgarry
1.12
515 emul(NODE *p)
gmcgarry
1.1
516 {
gmcgarry
1.12
517         char *ch = NULL;
gmcgarry
1.1
518
gmcgarry
1.12
519         if (p->n_op == LS && DEUNSIGN(p->n_type) == LONGLONGch = "ashldi3";
520         else if (p->n_op == LS && (DEUNSIGN(p->n_type) == LONG ||
521             DEUNSIGN(p->n_type) == INT))
522                 ch = "ashlsi3";
523
524         else if (p->n_op == RS && p->n_type == ULONGLONGch = "lshrdi3";
525         else if (p->n_op == RS && (p->n_type == ULONG || p->n_type == INT))
526                 ch = "lshrsi3";
527
528         else if (p->n_op == RS && p->n_type == LONGLONGch = "ashrdi3";
529         else if (p->n_op == RS && (p->n_type == LONG || p->n_type == INT))
530                 ch = "ashrsi3";
531         
532         else if (p->n_op == DIV && p->n_type == LONGLONGch = "divdi3";
533         else if (p->n_op == DIV && (p->n_type == LONG || p->n_type == INT))
534                 ch = "divsi3";
535
536         else if (p->n_op == DIV && p->n_type == ULONGLONGch = "udivdi3";
537         else if (p->n_op == DIV && (p->n_type == ULONG ||
538             p->n_type == UNSIGNED))
539                 ch = "udivsi3";
540
541         else if (p->n_op == MOD && p->n_type == LONGLONGch = "moddi3";
542         else if (p->n_op == MOD && (p->n_type == LONG || p->n_type == INT))
543                 ch = "modsi3";
544
545         else if (p->n_op == MOD && p->n_type == ULONGLONGch = "umoddi3";
546         else if (p->n_op == MOD && (p->n_type == ULONG ||
547             p->n_type == UNSIGNED))
548                 ch = "umodsi3";
549
550         else if (p->n_op == MUL && p->n_type == LONGLONGch = "muldi3";
551         else if (p->n_op == MUL && (p->n_type == LONG || p->n_type == INT))
552                 ch = "mulsi3";
553
554         else if (p->n_op == UMINUS && p->n_type == LONGLONGch = "negdi2";
555         else if (p->n_op == UMINUS && p->n_type == LONGch = "negsi2";
556
557         else ch = 0comperr("ZE");
558         if (kflag) {
559 #if defined(ELFABI)
560                 printf("\tbl __%s@got(30)" COM "emulated op\n"exname(ch));
561 #elif defined(MACHOABI)
562                 char buf[32];
563                 printf("\tbl L__%s$stub" COM "emulated op\n"ch);
564                 snprintf(buf32"__%s"ch);
565                 addstub(&stublistbuf);
566 #endif
567         } else {
568                 printf("\tbl __%s" COM "emulated operation\n"exname(ch));
569         }
gmcgarry
1.1
570 }
571
572 /*
gmcgarry
1.12
573  *  Floating-point conversions (int -> float/double & float/double -> int)
gmcgarry
1.1
574  */
gmcgarry
1.12
575
gmcgarry
1.1
576 static void
gmcgarry
1.12
577 ftoi(NODE *p)
gmcgarry
1.1
578 {
gmcgarry
1.12
579         NODE *l = p->n_left;
580
581         printf(COM "start conversion float/(l)double to int\n");
582
583         if (l->n_op != OREG) {
584                 expand(p0"\tstw AL,-4");
585                 printf("(%s)\n"rnames[SPREG]);
586                 if (l->n_type == FLOAT)
587                         expand(p0"\tlfs A2,");
588                 else
589                         expand(p0"\tlfd A2,\n");
590                 printf("-4(%s)\n"rnames[SPREG]);
591         } else {
592                 if (l->n_type == FLOAT)
593                         expand(p0"\tlfs A2,AL\n");
594                 else
595                         expand(p0"\tlfd A2,AL\n");
gmcgarry
1.1
596         }
gmcgarry
1.12
597
598         expand(p0"\tfctiwz A2,A2\n");
599         expand(p0"\tstfd A2,");
600         printf("-8(%s)\n"rnames[SPREG]);
601         expand(p0"\tlwz A1,");
602         printf("-4(%s)\n"rnames[SPREG]);
603
604         printf(COM "end conversion\n");
gmcgarry
1.1
605 }
606
607 static void
gmcgarry
1.12
608 ftou(NODE *p)
gmcgarry
1.1
609 {
gmcgarry
1.12
610         static int lab = 0;
611         NODE *l = p->n_left;
612         int lab1 = getlab();
613         int lab2 = getlab();
614
615         printf(COM "start conversion of float/(l)double to unsigned\n");
616
617         if (lab == 0) {
618                 lab = getlab();
619                 expand(p0"\t.data\n");
620                 printf(LABFMT ":\t.long 0x41e00000\n\t.long 0\n"lab);
621                 expand(p0"\t.text\n");
622         }
623
624         if (l->n_op != OREG) {
625                 expand(p0"\tstw AL,");
626                 printf("-4(%s)\n"rnames[SPREG]);
627                 if (l->n_type == FLOAT)
628                         expand(p0"\tlfs A3,");
629                 else
630                         expand(p0"\tlfd A3,");
631                 printf("-4(%s)\n"rnames[SPREG]);
632                 
633         } else {
634                 if (l->n_type == FLOAT)
635                         expand(p0"\tlfs A3,AL\n");
636                 else
637                         expand(p0"\tlfd A3,AL\n");
638         }
639
640 #if 0
641         if (kflag) {
642                 expand(p0"\taddis A1,");
643                 printf("%s,ha16("rnames[R31]);
644                 printf(LABFMTlab);
645                 printf("-L%s$pb)\n"cftnsp->soname);
646                 expand(p0"\tlfd A2,lo16(");
647                 printf(LABFMTlab);
648                 printf("-L%s$pb)"cftnsp->soname);
649                 expand(p0"(A1)\n");
650         } else {
651                 expand(p0"\tlfd A2,");
652                 printf(LABFMT "\n"lab);
653         }
654 #endif
655
656 #if defined(ELFABI)
657
658         expand(p0"\taddis A1,");
659         printf("%s," LABFMT "@ha\n"rnames[R31], lab);
660         expand(p0"\tlfd A2,");
661         printf(LABFMT "@l"lab);
662         expand(p0"(A1)\n");
663
664 #elif defined(MACHOABI)
665
666         expand(p0"\taddis A1,");
667         printf("%s,ha16("rnames[R31]);
668         printf(LABFMTlab);
669         if (kflag)
670                 printf("-L%s$pb"cftnsp->soname);
671         printf(")\n");
672         expand(p0"\tlfd A2,lo16(");
673         printf(LABFMTlab);
674         if (kflag)
675                 printf("-L%s$pb"cftnsp->soname);
676         expand(p0")(A1)\n");
gmcgarry
1.1
677
678 #endif
679
gmcgarry
1.12
680         expand(p0"\tfcmpu cr7,A3,A2\n");
681         printf("\tcror 30,29,30\n");
682         printf("\tbeq cr7,"LABFMT "\n"lab1);
683
684         expand(p0"\tfctiwz A2,A3\n");
685         expand(p0"\tstfd A2,");
686         printf("-8(%s)\n"rnames[SPREG]);
687         expand(p0"\tlwz A1,");
688         printf("-4(%s)\n"rnames[SPREG]);
689         printf("\tba " LABFMT "\n"lab2);
690
691         deflab(lab1);
692
693         expand(p0"\tfsub A2,A3,A2\n");
694         expand(p0"\tfctiwz A2,A2\n");
695         expand(p0"\tstfd A2,");
696         printf("-8(%s)\n"rnames[SPREG]);
697         expand(p0"\tlwz A1,");
698         printf("-4(%s)\n"rnames[SPREG]);
699         expand(p0"\txoris A1,A1,0x8000\n");
700
701         deflab(lab2);
gmcgarry
1.1
702
gmcgarry
1.12
703         printf(COM "end conversion\n");
gmcgarry
1.1
704 }
705
gmcgarry
1.12
706 static void
707 itof(NODE *p)
gmcgarry
1.1
708 {
gmcgarry
1.12
709         static int labu = 0;
710         static int labi = 0;
711         int lab;
712         NODE *l = p->n_left;
713
714         printf(COM "start conversion (u)int to float/(l)double\n");
715
716         if (labi == 0 && l->n_type == INT) {
717                 labi = getlab();
718                 expand(p0"\t.data\n");
719                 printf(LABFMT ":\t.long 0x43300000\n\t.long 0x80000000\n"labi);
720                 expand(p0"\t.text\n");
721         } else if (labu == 0 && l->n_type == UNSIGNED) {
722                 labu = getlab();
723                 expand(p0"\t.data\n");
724                 printf(LABFMT ":\t.long 0x43300000\n\t.long 0x00000000\n"labu);
725                 expand(p0"\t.text\n");
726         }
727
728         if (l->n_type == INT) {
729                 expand(p0"\txoris A1,AL,0x8000\n");
730                 lab = labi;
731         } else {
732                 lab = labu;
733         }
734         expand(p0"\tstw A1,");
735         printf("-4(%s)\n"rnames[SPREG]);
736         expand(p0"\tlis A1,0x4330\n");
737         expand(p0"\tstw A1,");
738         printf("-8(%s)\n"rnames[SPREG]);
739         expand(p0"\tlfd A3,");
740         printf("-8(%s)\n"rnames[SPREG]);
741
gmcgarry
1.1
742 #if 0
gmcgarry
1.12
743         if (kflag) {
744                 expand(p0"\taddis A1,");
745                 printf("%s,ha16("rnames[R31]);
746                 printf(LABFMTlab);
747                 printf("-L%s$pb)\n"cftnsp->soname);
748                 expand(p0"\tlfd A2,lo16(");
749                 printf(LABFMTlab);
750                 printf("-L%s$pb)"cftnsp->soname);
751                 expand(p0"(A1)\n");
752         } else {
753                 expand(p0"\tlfd A2,");
754                 printf(LABFMT "\n"lab);
755         }
gmcgarry
1.1
756 #endif
757
gmcgarry
1.12
758 #if defined(ELFABI)
759
760         expand(p0"\taddis A1,");
761         printf("%s," LABFMT "@ha\n"rnames[R31], lab);
762         expand(p0"\tlfd A2,");
763         printf(LABFMT "@l"lab);
764         expand(p0"(A1)\n");
765
766 #elif defined(MACHOABI)
767
768         expand(p0"\taddis A1,");
769         printf("%s,ha16("rnames[R31]);
770         printf(LABFMTlab);
771         if (kflag)
772                 printf("-L%s$pb"cftnsp->soname);
773         printf(")\n");
774         expand(p0"\tlfd A2,lo16(");
775         printf(LABFMTlab);
776         if (kflag)
777                 printf("-L%s$pb"cftnsp->soname);
778         expand(p0")(A1)\n");
779
780 #endif
781
782         expand(p0"\tfsub A3,A3,A2\n");
783         if (p->n_type == FLOAT)
784                 expand(p0"\tfrsp A3,A3\n");
785
786         printf(COM "end conversion\n");
787 }
788
789
790 static void
791 fpconv(NODE *p)
792 {
793         NODE *l = p->n_left;
794
795 #ifdef PCC_DEBUG
796         if (p->n_op != SCONV)
797                 cerror("fpconv 1");
gmcgarry
1.1
798 #endif
799
gmcgarry
1.12
800         if (DEUNSIGN(l->n_type) == INT)
801                 itof(p);
802         else if (p->n_type == INT)
803                 ftoi(p);
804         else if (p->n_type == UNSIGNED)
805                 ftou(p);
806         else
807                 cerror("unhandled floating-point conversion");
808
809 }
gmcgarry
1.1
810
gmcgarry
1.12
811 void
812 zzzcode(NODE *pint c)
813 {
814         switch (c) {
gmcgarry
1.1
815
gmcgarry
1.12
816         case 'C'/* floating-point conversions */
817                 fpconv(p);
gmcgarry
1.1
818                 break;
819
gmcgarry
1.12
820         case 'D'/* long long comparision */
821                 twollcomp(p);
gmcgarry
1.1
822                 break;
823
gmcgarry
1.12
824         case 'E'/* print out emulated ops */
825                 emul(p);
gmcgarry
1.1
826                 break;
827
gmcgarry
1.12
828         case 'F'/* print out emulate floating-point ops */
829                 fpemul(p);
gmcgarry
1.1
830                 break;
831
832         case 'O'/* 64-bit left and right shift operators */
gmcgarry
1.12
833                 shiftop(p);
gmcgarry
1.1
834                 break;
835
836         case 'Q'/* emit struct assign */
gmcgarry
1.12
837                 stasg(p);
gmcgarry
1.1
838                 break;
839
840         default:
841                 comperr("zzzcode %c"c);
842         }
843 }
844
845 /*ARGSUSED*/
846 int
847 rewfld(NODE *p)
848 {
849         return(1);
850 }
851
852 int canaddr(NODE *);
853 int
854 canaddr(NODE *p)
855 {
856         int o = p->n_op;
857
gmcgarry
1.12
858         if (o == NAME || o == REG || o == ICON || o == OREG ||
859             (o == UMUL && shumul(p->n_left)))
gmcgarry
1.1
860                 return(1);
gmcgarry
1.12
861         return 0;
gmcgarry
1.1
862 }
863
stefan
1.9
864 int
865 fldexpand(NODE *pint cookiechar **cp)
866 {
gmcgarry
1.12
867         CONSZ val;
868         int shft;
869
870         if (p->n_op == ASSIGN)
871                 p = p->n_left;
872
gmcgarry
1.13
873         if (features(FEATURE_BIGENDIAN))
874                 shft = SZINT - UPKFSZ(p->n_rval) - UPKFOFF(p->n_rval);
875         else
876                 shft = UPKFOFF(p->n_rval);
gmcgarry
1.12
877
878         switch (**cp) {
879         case 'S':
880                 printf("%d"UPKFSZ(p->n_rval));
881                 break;
882         case 'H':
883                 printf("%d"shft);
884                 break;
885         case 'M':
886         case 'N':
887                 val = (CONSZ)1 << UPKFSZ(p->n_rval);
888                 --val;
889                 val <<= shft;
890                 printf(CONFMT, (**cp == 'M' ? val : ~val)  & 0xffffffff);
891                 break;
892         default:
893                 comperr("fldexpand");
894         }
895         return 1;
stefan
1.9
896 }
897
gmcgarry
1.1
898 /*
899  * Does the bitfield shape match?
900  */
901 int
902 flshape(NODE *p)
903 {
904         int o = p->n_op;
905
906         if (o == OREG || o == REG || o == NAME)
907                 return SRDIR/* Direct match */
908         if (o == UMUL && shumul(p->n_left))
909                 return SROREG/* Convert into oreg */
910         return SRREG/* put it into a register */
911 }
912
913 /* INTEMP shapes must not contain any temporary registers */
914 /* XXX should this go away now? */
915 int
916 shtemp(NODE *p)
917 {
918         printf("; shtemp\n");
919         return 0;
920 #if 0
921         int r;
922
923         if (p->n_op == STARG )
924                 p = p->n_left;
925
926         switch (p->n_op) {
927         case REG:
gmcgarry
1.12
928                 return (!istreg(regno(p)));
gmcgarry
1.1
929
930         case OREG:
gmcgarry
1.12
931                 r = regno(p);
gmcgarry
1.1
932                 if (R2TEST(r)) {
933                         if (istreg(R2UPK1(r)))
934                                 return(0);
935                         r = R2UPK2(r);
936                 }
937                 return (!istreg(r));
938
939         case UMUL:
940                 p = p->n_left;
941                 return (p->n_op != UMUL && shtemp(p));
942         }
943
944         if (optype(p->n_op) != LTYPE)
945                 return(0);
946         return(1);
947 #endif
948 }
949
950 void
951 adrcon(CONSZ val)
952 {
953         printfCONFMTval);
954 }
955
956 void
957 conput(FILE *fpNODE *p)
958 {
959         int val = p->n_lval;
960
961         switch (p->n_op) {
962         case ICON:
gmcgarry
1.12
963                 if (p->n_name[0] != '\0') {
964                         fprintf(fp"%s"p->n_name);
965                         if (val)
gmcgarry
1.1
966                                 fprintf(fp"+%d"val);
gmcgarry
1.12
967                 } else {
968                         if (GCLASS(p->n_type) == CLASSB)
969                                 fprintf(fpCONFMTp->n_lval >> 32);
970                         else
971                                 fprintf(fp"%d"val);
972                 }
gmcgarry
1.1
973                 return;
974
975         default:
976                 comperr("illegal conput, p %p"p);
977         }
978 }
979
980 /*ARGSUSED*/
981 void
982 insput(NODE *p)
983 {
984         comperr("insput");
985 }
986
987 /*
stefan
1.5
988  * Print lower or upper name of 64-bit register.
989  */
990 static void
gmcgarry
1.12
991 reg64name(int regint hi)
stefan
1.5
992 {
gmcgarry
1.12
993         int idx;
994         int off = 0;
995
996         assert(GCLASS(reg) == CLASSB);
stefan
1.5
997
gmcgarry
1.12
998         idx = (reg > R14R15 ? (2*(reg - R14R15) + R14) : (reg - R3R4 + R3));
stefan
1.5
999
gmcgarry
1.12
1000         if ((hi == HIREG && !features(FEATURE_BIGENDIAN)) ||
1001             (hi == LOWREG && features(FEATURE_BIGENDIAN)))
1002                 off = 1;
1003                 
1004         fprintf(stdout"%s" , rnames[idx + off]);
stefan
1.5
1005 }
1006
1007 /*
gmcgarry
1.1
1008  * Write out the upper address, like the upper register of a 2-register
1009  * reference, or the next memory location.
1010  */
1011 void
1012 upput(NODE *pint size)
1013 {
1014         size /= SZCHAR;
1015         switch (p->n_op) {
1016         case REG:
gmcgarry
1.12
1017                 reg64name(regno(p), HIREG);
gmcgarry
1.1
1018                 break;
1019
1020         case NAME:
1021         case OREG:
gmcgarry
1.12
1022                 if (features(FEATURE_BIGENDIAN))
1023                         fprintf(stdout"%d", (int)p->n_lval);
1024                 else
1025                         fprintf(stdout"%d", (int)(p->n_lval + 4));
1026                 fprintf(stdout"(%s)"rnames[regno(p)]);
gmcgarry
1.1
1027                 break;
gmcgarry
1.12
1028
gmcgarry
1.1
1029         case ICON:
1030                 fprintf(stdoutCONFMTp->n_lval >> 32);
1031                 break;
gmcgarry
1.12
1032
gmcgarry
1.1
1033         default:
1034                 comperr("upput bad op %d size %d"p->n_opsize);
1035         }
1036 }
1037
1038 void
1039 adrput(FILE *ioNODE *p)
1040 {
1041         /* output an address, with offsets, from p */
1042
1043         if (p->n_op == FLD)
1044                 p = p->n_left;
1045
1046         switch (p->n_op) {
1047
1048         case NAME:
1049                 if (p->n_name[0] != '\0') {
gmcgarry
1.12
1050                         fputs(p->n_nameio);
gmcgarry
1.1
1051                         if (p->n_lval != 0)
1052                                 fprintf(io"+" CONFMTp->n_lval);
1053                 } else
1054                         fprintf(ioCONFMTp->n_lval);
1055                 return;
1056
1057         case OREG:
gmcgarry
1.12
1058                 if (DEUNSIGN(p->n_type) == LONGLONG &&
1059                     features(FEATURE_BIGENDIAN))
1060                         fprintf(io"%d", (int)(p->n_lval + 4));
1061                 else
1062                         fprintf(io"%d", (int)p->n_lval);
1063                 fprintf(io"(%s)"rnames[regno(p)]);
gmcgarry
1.1
1064                 return;
1065
1066         case ICON:
1067                 /* addressable value of the constant */
1068                 conput(iop);
1069                 return;
1070
1071         case REG:
gmcgarry
1.12
1072                 if (GCLASS(regno(p)) == CLASSB)
1073                         reg64name(regno(p), LOWREG);
1074                 else
1075                         fprintf(io"%s"rnames[regno(p)]);
1076 #if 0
gmcgarry
1.1
1077                 switch (p->n_type) {
gmcgarry
1.12
1078                 case DOUBLE:
1079                 case LDOUBLE:
1080                         if (features(FEATURE_HARDFLOAT)) {
1081                                 fprintf(io"%s"rnames[regno(p)]);
1082                                 break;
1083                         }
1084                         /* FALL-THROUGH */
gmcgarry
1.1
1085                 case LONGLONG:
1086                 case ULONGLONG:
gmcgarry
1.12
1087                         reg64name(regno(p), LOWREG);
gmcgarry
1.1
1088                         break;
1089                 default:
gmcgarry
1.12
1090                         fprintf(io"%s"rnames[regno(p)]);
gmcgarry
1.1
1091                 }
gmcgarry
1.12
1092 #endif
gmcgarry
1.1
1093                 return;
1094
1095         default:
1096                 comperr("illegal address, op %d, node %p"p->n_opp);
1097                 return;
1098
1099         }
1100 }
1101
1102 /*
1103  * these mnemonics match the order of the preprocessor decls
1104  * EQ, NE, LE, LT, GE, GT, ULE, ULT, UGE, UGT
1105  */
1106
1107