oops
[fw/sdcc] / src / xa51 / gen.c
1 /*-------------------------------------------------------------------------
2   SDCCgen51.c - source file for code generation for 8051
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7
8   This program is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by the
10   Free Software Foundation; either version 2, or (at your option) any
11   later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22   In other words, you are welcome to use, share and improve this program.
23   You are forbidden to forbid anyone else to use, share and improve
24   what you give them.   Help stamp out software-hoarding!
25
26   Notes:
27   000123 mlh  Moved aopLiteral to SDCCglue.c to help the split
28       Made everything static
29 -------------------------------------------------------------------------*/
30
31 //#define D(x)
32 #define D(x) x
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include "SDCCglobl.h"
39 #include "newalloc.h"
40
41 #ifdef HAVE_SYS_ISA_DEFS_H
42 #include <sys/isa_defs.h>
43 #else
44 #ifdef HAVE_MACHINE_ENDIAN_H
45 #include <machine/endian.h>
46 #else
47 #ifdef HAVE_ENDIAN_H
48 #include <endian.h>
49 #else
50 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
51 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
52 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
53 #endif
54 #endif
55 #endif
56 #endif
57
58 #include "common.h"
59 #include "SDCCpeeph.h"
60 #include "ralloc.h"
61 #include "gen.h"
62
63 #if defined(__BORLANDC__) || defined(_MSC_VER)
64 #define STRCASECMP stricmp
65 #else
66 #define STRCASECMP strcasecmp
67 #endif
68
69 extern int allocInfo;
70
71 /* this is the down and dirty file with all kinds of
72    kludgy & hacky stuff. This is what it is all about
73    CODE GENERATION for a specific MCU . some of the
74    routines may be reusable, will have to see */
75
76 static struct
77   {
78     short inLine;
79     short debugLine;
80     short nRegsSaved;
81     set *sendSet;
82   }
83 _G;
84
85 extern int xa51_ptrRegReq;
86 extern int xa51_nRegs;
87 extern FILE *codeOutFile;
88
89 static lineNode *lineHead = NULL;
90 static lineNode *lineCurr = NULL;
91
92 #define LSB     0
93 #define MSB16   1
94 #define MSB24   2
95 #define MSB32   3
96
97 /*-----------------------------------------------------------------*/
98 /* emitcode - writes the code into a file : for now it is simple    */
99 /*-----------------------------------------------------------------*/
100 static void emitcode (char *inst, char *fmt,...) {
101   va_list ap;
102   char lb[INITIAL_INLINEASM];
103   char *lbp = lb;
104
105   va_start (ap, fmt);
106
107   if (inst && *inst)
108     {
109       if (fmt && *fmt)
110         sprintf (lb, "%s\t", inst);
111       else
112         sprintf (lb, "%s", inst);
113       vsprintf (lb + (strlen (lb)), fmt, ap);
114     }
115   else
116     vsprintf (lb, fmt, ap);
117
118   while (isspace ((int)*lbp))
119     lbp++;
120
121   if (lbp && *lbp)
122     lineCurr = (lineCurr ?
123                 connectLine (lineCurr, newLineNode (lb)) :
124                 (lineHead = newLineNode (lb)));
125   lineCurr->isInline = _G.inLine;
126   lineCurr->isDebug = _G.debugLine;
127   va_end (ap);
128 }
129
130 /*-----------------------------------------------------------------*/
131 /* newAsmop - creates a new asmOp                                  */
132 /*-----------------------------------------------------------------*/
133 static asmop *
134 newAsmop (short type)
135 {
136   asmop *aop;
137
138   aop = Safe_calloc (1, sizeof (asmop));
139   aop->type = type;
140   return aop;
141 }
142
143 char *aopTypeName(asmop *aop) {
144   switch (aop->type)
145     {
146     case AOP_LIT: return "lit";
147     case AOP_REG: return "reg";
148     case AOP_DIR: return "dir";
149     case AOP_FAR: return "far";
150     case AOP_CODE: return "code";
151     case AOP_STK: return "stack";
152     case AOP_IMMD: return "imm";
153     case AOP_CRY: return "bit";
154     }
155   return "unknown";
156 }
157
158 /*-----------------------------------------------------------------*/
159 /* aopForSym - for a true symbol                                   */
160 /*-----------------------------------------------------------------*/
161 static asmop *aopForSym(symbol *sym, bool result) {
162   asmop *aop;
163
164   sym->aop = aop = newAsmop(0);
165   aop->size=getSize(sym->type);
166
167   // if it is in registers
168   if (sym->nRegs && sym->regs[0]) {
169     aop->type=AOP_REG;
170     if (sym->regs[1]) {
171       sprintf (aop->name[1], sym->regs[1]->name);
172     }
173     sprintf (aop->name[0], sym->regs[0]->name);
174     return aop;
175   }
176
177   // if it is on stack
178   if (sym->onStack) {
179     aop->type=AOP_STK;
180     sprintf (aop->name[0], "[r7+%d+0+%d+%d]", sym->stack, 
181              FUNC_ISISR(currFunc->type) ? 6 : 4, _G.nRegsSaved);
182     sprintf (aop->name[1], "[r7+%d+2+%d+%d]", sym->stack,
183              FUNC_ISISR(currFunc->type) ? 6 : 4, _G.nRegsSaved);
184     return aop;
185   }
186
187   // if it has a spillLoc
188   if (sym->usl.spillLoc) {
189     return aopForSym (sym->usl.spillLoc, result);
190   }
191
192   // if in bit space
193   if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
194     aop->type=AOP_CRY;
195     sprintf (aop->name[0], sym->rname);
196     return aop;
197   }
198
199   // if in direct space
200   if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
201     aop->type=AOP_DIR;
202     sprintf (aop->name[0], sym->rname);
203     sprintf (aop->name[1], "#0x%02x", POINTER);
204     return aop;
205   }
206
207   // if in code space
208   if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
209     if (result) {
210       fprintf (stderr, "aopForSym: result can not be in code space\n");
211       exit (1);
212     }
213     aop->type=AOP_CODE;
214     emitcode ("mov", "r0,#%s", sym->rname);
215     sprintf (aop->name[0], "r0");
216     sprintf (aop->name[1], "#0x%02x", CPOINTER);
217     return aop;
218   }
219
220   // if in far space
221   if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
222     aop->type=AOP_FAR;
223     emitcode ("mov", "r0,#%s", sym->rname);
224     sprintf (aop->name[0], "[r0]");
225     if (result) {
226       sprintf (aop->name[1], "[r0+2]");
227     } else {
228       sprintf (aop->name[1], "#0x%02x", FPOINTER);
229     }
230     return aop;
231   }
232
233   // special case for a function
234   if (IS_FUNC (sym->type)) {
235     aop->type=AOP_IMMD;
236     sprintf (aop->name[0], sym->rname);
237     return aop;
238   }
239
240   fprintf (stderr, "aopForSym (%s): What's up?\n", sym->name);
241   exit (1);
242 }
243
244 /*-----------------------------------------------------------------*/
245 /* aopForVal - for a value                                         */
246 /*-----------------------------------------------------------------*/
247 static asmop *aopForVal(operand *op) {
248   asmop *aop;
249   long v=floatFromVal(OP_VALUE(op));
250
251   if (IS_OP_LITERAL(op)) {
252     op->aop = aop = newAsmop (AOP_LIT);
253     switch ((aop->size=getSize(operandType(op))))
254       {
255       case 1:
256         sprintf (aop->name[0], "#0x%02lx", v);
257         break;
258       case 2:
259         sprintf (aop->name[0], "#0x%04lx", v);
260         break;
261       case 4:
262         sprintf (aop->name[0], "#(0x%08lx >> 16)", v);
263         sprintf (aop->name[1], "#(0x%08lx & 0xffff)", v);
264         break;
265       default:
266         fprintf (stderr, "aopForVal (lit): unknown size\n");
267         exit (1);
268       }
269     return aop;
270   }
271
272   // must be immediate
273   if (IS_SYMOP(op)) {
274     op->aop = aop = newAsmop (AOP_IMMD);
275     switch ((aop->size=getSize(OP_SYMBOL(op)->type))) 
276       {
277       case 1:
278       case 2:
279         sprintf (aop->name[0], "#%s", OP_SYMBOL(op)->rname);
280         return aop;
281       case 3: // generic pointer
282         sprintf (aop->name[0], "#0x%02x", DCL_TYPE(operandType(op)));
283         sprintf (aop->name[1], "#%s", OP_SYMBOL(op)->rname);
284         return aop;
285       }
286   }
287   fprintf (stderr, "aopForVal: unknown type\n");
288   exit (1);
289   return NULL;
290 }
291
292 static void aopOp(operand *op, bool result) {
293
294   if (IS_SYMOP(op)) {
295     op->aop=aopForSym (OP_SYMBOL(op), result);
296     return;
297   }
298   if (IS_VALOP(op)) {
299     if (result) {
300       fprintf (stderr, "aopOp: result can not be a value\n");
301       exit (1);
302     }
303     aopForVal (op);
304     return;
305   }
306
307   fprintf (stderr, "aopOp: unexpected operand\n");
308   exit (1);
309 }
310
311 char *opRegName(operand *op, int offset, char *opName) {
312
313   if (IS_SYMOP(op)) {
314     if (OP_SYMBOL(op)->onStack) {
315       sprintf (opName, "[r7+%d+0+%d+%d]", OP_SYMBOL(op)->stack, 
316                FUNC_ISISR(currFunc->type) ? 6 : 4, _G.nRegsSaved);
317       return opName;
318     }
319     if (IS_TRUE_SYMOP(op))
320       return OP_SYMBOL(op)->rname;
321     else if (OP_SYMBOL(op)->regs[offset])
322       return OP_SYMBOL(op)->regs[offset]->name;
323     else
324       return "NULL";
325   }
326
327   if (IS_VALOP(op)) {
328     switch (SPEC_NOUN(OP_VALUE(op)->type)) {
329     case V_BIT:
330       if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
331           SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
332         fprintf (stderr, "opRegName: invalid bit value (%d)\n",
333                  SPEC_CVAL(OP_VALUE(op)->type).v_int);
334         exit (1);
335       }
336       // fall through
337     case V_CHAR:
338       sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
339       break;
340     case V_INT:
341       if (SPEC_LONG(OP_VALUE(op)->type)) {
342         sprintf (opName, "#0x%02lx", SPEC_CVAL(OP_VALUE(op)->type).v_long);
343       } else {
344         sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
345       }
346       break;
347     case V_FLOAT:
348       sprintf (opName, "#0x%02lx", SPEC_CVAL(OP_VALUE(op)->type).v_long);
349       break;
350     default: 
351       fprintf (stderr, "opRegName: unexpected noun\n");
352       exit (1);
353     }
354     return opName;
355   }
356   fprintf (stderr, "opRegName: unexpected operand type\n");
357   exit (1);
358   return NULL; // to keep the compiler happy
359 }
360
361 char * printOp (operand *op) {
362   static char line[132];
363   bool isPtr = op->isPtr | op->isGptr;
364
365   if (IS_SYMOP(op)) {
366     symbol *sym=OP_SYMBOL(op);
367     if (!sym->regs[0] && SYM_SPIL_LOC(sym)) {
368       sym=SYM_SPIL_LOC(sym);
369     }
370     if (isPtr) {
371       sprintf (line, "[%s]:", sym->name);
372     } else {
373       sprintf (line, "%s:", sym->name);
374     }
375     if (sym->regs[0]) {
376       strcat (line, sym->regs[0]->name);
377       if (sym->regs[1]) {
378         strcat (line, ",");
379         strcat (line, sym->regs[1]->name);
380       }
381       return line;
382     }
383     if (sym->onStack) {
384       sprintf (line+strlen(line), "stack+%d", sym->stack);
385       return line;
386     }
387     if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
388       strcat (line, "far");
389       return line;
390     }
391     if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
392       strcat (line, "bit");
393       return line;
394     }
395     if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
396       strcat (line, "dir");
397       return line;
398     }
399     strcat (line, "unknown");
400     return line;
401   } else if (IS_VALOP(op)) {
402     opRegName(op, 0, line);
403   } else if (IS_TYPOP(op)) {
404     sprintf (line, "(");
405     // forget about static, volatile, ... for now
406     if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
407     if (SPEC_LONG(operandType(op))) strcat (line, "long ");
408     strcat (line, nounName(operandType(op)));
409     strcat (line, ")");
410   } else {
411     fprintf (stderr, "printOp: unexpected operand type\n");
412     exit (1);
413   }
414   return line;
415 }
416
417 void printIc (char *op, iCode * ic, bool result, bool left, bool right) {
418   char line[132];
419
420   sprintf (line, "%s", op);
421   if (result) {
422     strcat (line, " result=");
423     strcat (line, printOp (IC_RESULT(ic)));
424   }
425   if (left) {
426     strcat (line, " left=");
427     strcat (line, printOp (IC_LEFT(ic)));
428   }
429   if (right) {
430     strcat (line, " right=");
431     strcat (line, printOp (IC_RIGHT(ic)));
432   }
433   emitcode (";", line);
434 }
435
436 /*-----------------------------------------------------------------*/
437 /* toBoolean - return bit for operand!=0                           */
438 /*-----------------------------------------------------------------*/
439 static char *toBoolean (operand * op) {
440   switch (AOP_SIZE(op)) 
441     {
442     case 1:
443     case 2:
444       emitcode ("cmp", "%s,#0", AOP_NAME(op));
445       return "z";
446     }
447
448   fprintf (stderr, "toBoolean: unknown size %d\n", AOP_SIZE(op));
449   exit (1);
450   return NULL;
451 }
452
453 /*-----------------------------------------------------------------*/
454 /* regsInCommon - two operands have some registers in common       */
455 /*-----------------------------------------------------------------*/
456 static bool regsInCommon (operand * op1, operand * op2) {
457   symbol *sym1, *sym2;
458   int i;
459
460   /* if they have registers in common */
461   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
462     return FALSE;
463
464   sym1 = OP_SYMBOL (op1);
465   sym2 = OP_SYMBOL (op2);
466
467   if (sym1->nRegs == 0 || sym2->nRegs == 0)
468     return FALSE;
469
470   for (i = 0; i < sym1->nRegs; i++)
471     {
472       int j;
473       if (!sym1->regs[i])
474         continue;
475
476       for (j = 0; j < sym2->nRegs; j++)
477         {
478           if (!sym2->regs[j])
479             continue;
480
481           if (sym2->regs[j] == sym1->regs[i])
482             return TRUE;
483         }
484     }
485
486   return FALSE;
487 }
488
489 /*-----------------------------------------------------------------*/
490 /* resultRemat - result  is rematerializable                       */
491 /*-----------------------------------------------------------------*/
492 static int resultRemat (iCode * ic) {
493   if (SKIP_IC (ic) || ic->op == IFX)
494     return 0;
495   
496   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
497     {
498       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
499       if (sym->remat && !POINTER_SET (ic))
500         return 1;
501     }
502   
503   return 0;
504 }
505
506 /*-----------------------------------------------------------------*/
507 /* genNot - generate code for ! operation                          */
508 /*-----------------------------------------------------------------*/
509 static void genNot (iCode * ic) {
510   printIc("genNot:", ic, 1,1,0);
511 }
512
513 /*-----------------------------------------------------------------*/
514 /* genCpl - generate code for complement                           */
515 /*-----------------------------------------------------------------*/
516 static void genCpl (iCode * ic) {
517   printIc("genCpl", ic, 1,1,0);
518 }
519
520 /*-----------------------------------------------------------------*/
521 /* genUminus - unary minus code generation                         */
522 /*-----------------------------------------------------------------*/
523 static void genUminus (iCode * ic) {
524   printIc("genUminus", ic, 1,1,0);
525 }
526
527 /*-----------------------------------------------------------------*/
528 /* genIpush - genrate code for pushing this gets a little complex  */
529 /*-----------------------------------------------------------------*/
530 static void genIpush (iCode * ic) {
531   printIc ("genIpush", ic, 0,1,0);
532 }
533
534 /*-----------------------------------------------------------------*/
535 /* genIpop - recover the registers: can happen only for spilling   */
536 /*-----------------------------------------------------------------*/
537 static void genIpop (iCode * ic) {
538   printIc ("genIpop", ic, 0,1,0);
539 }
540
541 /*-----------------------------------------------------------------*/
542 /* genCall - generates a call statement                            */
543 /*-----------------------------------------------------------------*/
544 static void genCall (iCode * ic) {
545   emitcode (";", "genCall %s", OP_SYMBOL(IC_LEFT(ic))->name);
546 }
547
548 /*-----------------------------------------------------------------*/
549 /* genPcall - generates a call by pointer statement                */
550 /*-----------------------------------------------------------------*/
551 static void
552 genPcall (iCode * ic)
553 {
554   emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
555 }
556
557 /*-----------------------------------------------------------------*/
558 /* genFunction - generated code for function entry                 */
559 /*-----------------------------------------------------------------*/
560 static void genFunction (iCode * ic) {
561   symbol *sym=OP_SYMBOL(IC_LEFT(ic));
562   sym_link *type=sym->type;
563
564   emitcode (";", "-----------------------------------------");
565   emitcode (";", " function %s", sym->name);
566   emitcode (";", "-----------------------------------------");
567   
568   emitcode ("", "%s:", sym->rname);
569
570   if (IFFUNC_ISNAKED(type))
571   {
572       emitcode(";", "naked function: no prologue.");
573       return;
574   }
575
576   /* if critical function then turn interrupts off */
577   if (IFFUNC_ISCRITICAL (type))
578     emitcode ("clr", "ea");
579
580 }
581
582 /*-----------------------------------------------------------------*/
583 /* genEndFunction - generates epilogue for functions               */
584 /*-----------------------------------------------------------------*/
585 static void
586 genEndFunction (iCode * ic)
587 {
588   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
589
590   if (IFFUNC_ISNAKED(sym->type))
591   {
592       emitcode(";", "naked function: no epilogue.");
593       return;
594   }
595
596   printIc ("genEndFunction", ic, 0,0,0);
597 }
598
599 /*-----------------------------------------------------------------*/
600 /* genRet - generate code for return statement                     */
601 /*-----------------------------------------------------------------*/
602 static void genRet (iCode * ic) {
603   emitcode (";", "genRet");
604 }
605
606 /*-----------------------------------------------------------------*/
607 /* genLabel - generates a label                                    */
608 /*-----------------------------------------------------------------*/
609 static void genLabel (iCode * ic) {
610   /* special case never generate */
611   if (IC_LABEL (ic) == entryLabel)
612     return;
613
614   emitcode (";", "genLabel %s", IC_LABEL(ic)->name);
615   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
616 }
617
618 /*-----------------------------------------------------------------*/
619 /* genGoto - generates a ljmp                                      */
620 /*-----------------------------------------------------------------*/
621 static void genGoto (iCode * ic) {
622   emitcode (";", "genGoto %s", IC_LABEL(ic)->name);
623   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
624 }
625
626 /*-----------------------------------------------------------------*/
627 /* genPlus - generates code for addition                           */
628 /*-----------------------------------------------------------------*/
629 static void genPlus (iCode * ic) {
630   printIc ("genPlus", ic, 1,1,1);
631 }
632
633 /*-----------------------------------------------------------------*/
634 /* genMinus - generates code for subtraction                       */
635 /*-----------------------------------------------------------------*/
636 static void genMinus (iCode * ic) {
637   printIc ("genMinus", ic, 1,1,1);
638 }
639
640
641 /*-----------------------------------------------------------------*/
642 /* genMult - generates code for multiplication                     */
643 /*-----------------------------------------------------------------*/
644 static void genMult (iCode * ic) {
645   printIc ("genMult", ic, 1,1,1);
646 }
647
648 /*-----------------------------------------------------------------*/
649 /* genDiv - generates code for division                            */
650 /*-----------------------------------------------------------------*/
651 static void genDiv (iCode * ic) {
652   printIc ("genDiv", ic, 1,1,1);
653 }
654
655 /*-----------------------------------------------------------------*/
656 /* genMod - generates code for division                            */
657 /*-----------------------------------------------------------------*/
658 static void genMod (iCode * ic) {
659   printIc ("genMod", ic, 1,1,1);
660 }
661
662 /*-----------------------------------------------------------------*/
663 /* genCmpGt :- greater than comparison                             */
664 /*-----------------------------------------------------------------*/
665 static void genCmpGt (iCode * ic, iCode * ifx) {
666   printIc ("genCmpGt", ic, 1,1,1);
667 }
668 /*-----------------------------------------------------------------*/
669 /* genCmpLt - less than comparisons                                */
670 /*-----------------------------------------------------------------*/
671 static void genCmpLt (iCode * ic, iCode * ifx) {
672   printIc ("genCmpLt", ic, 1,1,1);
673 }
674 /*-----------------------------------------------------------------*/
675 /* genCmpEq - generates code for equal to                          */
676 /*-----------------------------------------------------------------*/
677 static void genCmpEq (iCode * ic, iCode * ifx) {
678   printIc ("genCmpEq", ic, 1,1,1);
679 }
680
681 /*-----------------------------------------------------------------*/
682 /* ifxForOp - returns the icode containing the ifx for operand     */
683 /*-----------------------------------------------------------------*/
684 static iCode *ifxForOp (operand * op, iCode * ic) {
685   /* if true symbol then needs to be assigned */
686   if (IS_TRUE_SYMOP (op))
687     return NULL;
688   
689   /* if this has register type condition and
690      the next instruction is ifx with the same operand
691      and live to of the operand is upto the ifx only then */
692   if (ic->next &&
693       ic->next->op == IFX &&
694       IC_COND (ic->next)->key == op->key &&
695       OP_SYMBOL (op)->liveTo <= ic->next->seq)
696     return ic->next;
697   
698   return NULL;
699 }
700
701 /*-----------------------------------------------------------------*/
702 /* hasInc - operand is incremented before any other use            */
703 /*-----------------------------------------------------------------*/
704 static iCode *hasInc (operand *op, iCode *ic, int osize) {
705   sym_link *type = operandType(op);
706   sym_link *retype = getSpec (type);
707   iCode *lic = ic->next;
708   int isize ;
709   
710   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
711   if (!IS_SYMOP(op)) return NULL;
712
713   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
714   if (IS_AGGREGATE(type->next)) return NULL;
715   if (osize != (isize = getSize(type->next))) return NULL;
716
717   while (lic) {
718     /* if operand of the form op = op + <sizeof *op> */
719     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
720         isOperandEqual(IC_RESULT(lic),op) && 
721         isOperandLiteral(IC_RIGHT(lic)) &&
722         operandLitValue(IC_RIGHT(lic)) == isize) {
723       return lic;
724     }
725     /* if the operand used or deffed */
726     if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
727       return NULL;
728     }
729     /* if GOTO or IFX */
730     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
731     lic = lic->next;
732   }
733   return NULL;
734 }
735
736 /*-----------------------------------------------------------------*/
737 /* genAndOp - for && operation                                     */
738 /*-----------------------------------------------------------------*/
739 static void genAndOp (iCode * ic) {
740   printIc ("genAndOp(&&)", ic, 1,1,1);
741 }
742
743 /*-----------------------------------------------------------------*/
744 /* genOrOp - for || operation                                      */
745 /*-----------------------------------------------------------------*/
746 static void genOrOp (iCode * ic) {
747   printIc ("genOrOp(||)", ic, 1,1,1);
748 }
749
750 /*-----------------------------------------------------------------*/
751 /* genAnd  - code for and                                            */
752 /*-----------------------------------------------------------------*/
753 static void genAnd (iCode * ic, iCode * ifx) {
754   printIc ("genAnd", ic, 1,1,1);
755 }
756
757 /*-----------------------------------------------------------------*/
758 /* genOr  - code for or                                            */
759 /*-----------------------------------------------------------------*/
760 static void genOr (iCode * ic, iCode * ifx) {
761   printIc ("genOr", ic, 1,1,1);
762 }
763
764 /*-----------------------------------------------------------------*/
765 /* genXor - code for xclusive or                                   */
766 /*-----------------------------------------------------------------*/
767 static void genXor (iCode * ic, iCode * ifx) {
768   printIc ("genXor", ic, 1,1,1);
769 }
770
771 /*-----------------------------------------------------------------*/
772 /* genInline - write the inline code out                           */
773 /*-----------------------------------------------------------------*/
774 static void genInline (iCode * ic) {
775   printIc ("genInline", ic, 0,0,0);
776 }
777
778 /*-----------------------------------------------------------------*/
779 /* genRRC - rotate right with carry                                */
780 /*-----------------------------------------------------------------*/
781 static void genRRC (iCode * ic) {
782   printIc ("genRRC", ic, 1,1,0);
783 }
784
785 /*-----------------------------------------------------------------*/
786 /* genRLC - generate code for rotate left with carry               */
787 /*-----------------------------------------------------------------*/
788 static void genRLC (iCode * ic) {
789   printIc ("genRLC", ic, 1,1,0);
790 }
791
792 /*-----------------------------------------------------------------*/
793 /* genGetHbit - generates code get highest order bit               */
794 /*-----------------------------------------------------------------*/
795 static void genGetHbit (iCode * ic) {
796   printIc ("genGetHbit", ic, 1,1,0);
797 }
798
799 /*-----------------------------------------------------------------*/
800 /* genLeftShift - generates code for left shifting                 */
801 /*-----------------------------------------------------------------*/
802 static void genLeftShift (iCode * ic) {
803   printIc ("genLeftShift", ic, 1,1,1);
804 }
805
806 /*-----------------------------------------------------------------*/
807 /* genRightShift - generate code for right shifting                */
808 /*-----------------------------------------------------------------*/
809 static void genRightShift (iCode * ic) {
810   printIc ("genRightShift", ic, 1,1,1);
811 }
812
813 /*-----------------------------------------------------------------*/
814 /* genPointerGet - generate code for pointer get                   */
815 /*-----------------------------------------------------------------*/
816 static void genPointerGet (iCode * ic, iCode *pi) {
817   printIc ("genPointerGet", ic, 1,1,0);
818 }
819
820 /*-----------------------------------------------------------------*/
821 /* genPointerSet - stores the value into a pointer location        */
822 /*-----------------------------------------------------------------*/
823 static void genPointerSet (iCode * ic, iCode *pi) {
824   printIc ("genPointerSet", ic, 1,0,1);
825 }
826
827 /*-----------------------------------------------------------------*/
828 /* genIfx - generate code for Ifx statement                        */
829 /*-----------------------------------------------------------------*/
830 static void genIfx (iCode * ic, iCode * popIc) {
831   bool trueOrFalse;
832   symbol *jlbl, *tlbl;
833   operand *cond=IC_COND(ic);
834
835   emitcode (";", "genIfx cond=%s trueLabel:%s falseLabel:%s", 
836             printOp(cond),
837             IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
838             IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
839
840   aopOp(cond,FALSE);
841
842   if (IC_TRUE(ic)) {
843     trueOrFalse=TRUE;
844     jlbl=IC_TRUE(ic);
845   } else {
846     trueOrFalse=FALSE;
847     jlbl=IC_FALSE(ic);
848   }
849
850   switch (AOP_TYPE(cond) )
851     {
852     case AOP_CRY:
853       emitcode (trueOrFalse ? "jb" : "jbc", "%s,%05d$", 
854                 AOP_NAME(cond)[0], jlbl->key+100);
855       return;
856     case AOP_REG:
857     case AOP_DIR:
858     case AOP_FAR:
859       tlbl=newiTempLabel(NULL);
860       emitcode ("cmp", "%s,#0", AOP_NAME(cond)[0]);
861       emitcode (trueOrFalse ? "bne" : "beq", "%05d$", tlbl->key+100);
862       if (*AOP_NAME(cond)[1]) {
863         emitcode ("cmp", "%s,#0", AOP_NAME(cond)[1]);
864         emitcode (trueOrFalse ? "bne" : "beq", "%05d$", tlbl->key+100);
865       }
866       emitcode ("jmp", "%05d$", jlbl->key+100);
867       emitcode ("", "%05d$:", tlbl->key+100);
868       return;
869     }
870 }
871
872 /*-----------------------------------------------------------------*/
873 /* genAddrOf - generates code for address of                       */
874 /*-----------------------------------------------------------------*/
875 static void genAddrOf (iCode * ic) {
876   printIc ("genAddrOf", ic, 1,1,0);
877 }
878
879 /*-----------------------------------------------------------------*/
880 /* genAssign - generate code for assignment                        */
881 /*-----------------------------------------------------------------*/
882 static void genAssign (iCode * ic) {
883   operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
884
885   printIc ("genAssign", ic, 1,0,1);
886   
887   if (!IS_SYMOP(result)) {
888     fprintf (stderr, "genAssign: result is not a symbol\n");
889     exit (1);
890   }
891   
892   aopOp(right, FALSE);
893   aopOp(result, TRUE);
894
895   if (result->aop->type==AOP_REG || 
896       right->aop->type==AOP_REG ||
897       right->aop->type==AOP_LIT ||
898       right->aop->type==AOP_IMMD) {
899     // everything will do
900   } else {
901     // they have to match
902     if (result->aop->type != right->aop->type) {
903       fprintf (stderr, "genAssign: types don't match (%s!=%s)\n",
904                aopTypeName(result->aop), aopTypeName(right->aop));
905       exit (1);
906     }
907   }
908
909   /* if result is a bit */
910   if (AOP_TYPE(result) == AOP_CRY) {
911     /* if right is literal, we know what the value is */
912     if (AOP_TYPE(right) == AOP_LIT) {
913       if (operandLitValue(right)) {
914         emitcode ("setb", AOP_NAME(result)[0]);
915       } else {
916         emitcode ("clr", AOP_NAME(result)[0]);
917       }
918       return;
919     }
920     /* if right is also a bit */
921     if (AOP_TYPE(right) == AOP_CRY) {
922       emitcode ("mov", "c,%s", AOP_NAME(right));
923       emitcode ("mov", "%s,c", AOP_NAME(result));
924       return;
925     }
926     /* we need to or */
927     emitcode ("mov", "%s,%s", AOP_NAME(result), toBoolean(right));
928     return;
929   }
930
931   /* general case */
932   emitcode ("mov", "%s,%s", 
933             result->aop->name[0], right->aop->name[0]);
934   if (IS_GENPTR(operandType(result))) {
935     emitcode ("mov", "%s,%s",
936               result->aop->name[1], right->aop->name[1]);
937   }
938   
939 }
940
941 /*-----------------------------------------------------------------*/
942 /* genJumpTab - genrates code for jump table                       */
943 /*-----------------------------------------------------------------*/
944 static void genJumpTab (iCode * ic) {
945   printIc ("genJumpTab", ic, 0,0,0);
946 }
947
948 /*-----------------------------------------------------------------*/
949 /* genCast - gen code for casting                                  */
950 /*-----------------------------------------------------------------*/
951 static void genCast (iCode * ic) {
952   printIc ("genCast", ic, 1,1,1);
953 }
954
955 /*-----------------------------------------------------------------*/
956 /* genDjnz - generate decrement & jump if not zero instrucion      */
957 /*-----------------------------------------------------------------*/
958 static bool genDjnz (iCode * ic, iCode * ifx) {
959   printIc ("genDjnz", ic, 0,0,0);
960   return FALSE;
961 }
962
963 /*-----------------------------------------------------------------*/
964 /* genReceive - generate code for a receive iCode                  */
965 /*-----------------------------------------------------------------*/
966 static void genReceive (iCode * ic) {
967   printIc ("genReceive", ic, 1,0,0);
968 }
969
970 /*-----------------------------------------------------------------*/
971 /* gen51Code - generate code for 8051 based controllers            */
972 /*-----------------------------------------------------------------*/
973 void genXA51Code (iCode * lic) {
974   iCode *ic;
975   int cln = 0;
976   
977   fprintf (stderr, "genXA51Code\n");
978   lineHead = lineCurr = NULL;
979   
980   /* print the allocation information */
981   if (allocInfo)
982     printAllocInfo (currFunc, codeOutFile);
983
984   /* if debug information required */
985   if (options.debug && currFunc)
986     {
987       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
988       _G.debugLine = 1;
989       if (IS_STATIC (currFunc->etype))
990         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
991       else
992         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
993       _G.debugLine = 0;
994     }
995   
996   for (ic = lic; ic; ic = ic->next) {
997     if (cln != ic->lineno) {
998       if (options.debug) {
999         _G.debugLine = 1;
1000         emitcode ("", "C$%s$%d$%d$%d ==.",
1001                   FileBaseName (ic->filename), ic->lineno,
1002                   ic->level, ic->block);
1003         _G.debugLine = 0;
1004       }
1005       emitcode (";", "%s %d", ic->filename, ic->lineno);
1006       cln = ic->lineno;
1007     }
1008     /* if the result is marked as
1009        spilt and rematerializable or code for
1010        this has already been generated then
1011        do nothing */
1012     if (resultRemat (ic) || ic->generated)
1013       continue;
1014     
1015     /* depending on the operation */
1016     switch (ic->op)
1017       {
1018       case '!':
1019         genNot (ic);
1020         break;
1021         
1022       case '~':
1023         genCpl (ic);
1024         break;
1025         
1026       case UNARYMINUS:
1027         genUminus (ic);
1028         break;
1029         
1030       case IPUSH:
1031         genIpush (ic);
1032         break;
1033         
1034       case IPOP:
1035         /* IPOP happens only when trying to restore a
1036            spilt live range, if there is an ifx statement
1037            following this pop then the if statement might
1038            be using some of the registers being popped which
1039            would destory the contents of the register so
1040            we need to check for this condition and handle it */
1041         if (ic->next &&
1042             ic->next->op == IFX &&
1043             regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1044           genIfx (ic->next, ic);
1045         else
1046           genIpop (ic);
1047         break;
1048         
1049       case CALL:
1050         genCall (ic);
1051         break;
1052         
1053       case PCALL:
1054         genPcall (ic);
1055         break;
1056         
1057       case FUNCTION:
1058         genFunction (ic);
1059         break;
1060         
1061       case ENDFUNCTION:
1062         genEndFunction (ic);
1063         break;
1064         
1065       case RETURN:
1066         genRet (ic);
1067         break;
1068         
1069       case LABEL:
1070         genLabel (ic);
1071         break;
1072         
1073       case GOTO:
1074         genGoto (ic);
1075         break;
1076         
1077       case '+':
1078         genPlus (ic);
1079         break;
1080         
1081       case '-':
1082         if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
1083           genMinus (ic);
1084         break;
1085         
1086       case '*':
1087         genMult (ic);
1088         break;
1089         
1090       case '/':
1091         genDiv (ic);
1092         break;
1093         
1094       case '%':
1095         genMod (ic);
1096         break;
1097         
1098       case '>':
1099         genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
1100         break;
1101         
1102       case '<':
1103         genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
1104         break;
1105         
1106       case LE_OP:
1107       case GE_OP:
1108       case NE_OP:
1109         
1110         /* note these two are xlated by algebraic equivalence
1111            during parsing SDCC.y */
1112         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1113                 "got '>=' or '<=' shouldn't have come here");
1114         break;
1115         
1116       case EQ_OP:
1117         genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
1118         break;
1119         
1120       case AND_OP:
1121         genAndOp (ic);
1122         break;
1123         
1124       case OR_OP:
1125         genOrOp (ic);
1126         break;
1127         
1128       case '^':
1129         genXor (ic, ifxForOp (IC_RESULT (ic), ic));
1130         break;
1131         
1132       case '|':
1133         genOr (ic, ifxForOp (IC_RESULT (ic), ic));
1134         break;
1135         
1136       case BITWISEAND:
1137         genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
1138         break;
1139         
1140       case INLINEASM:
1141         genInline (ic);
1142         break;
1143         
1144       case RRC:
1145         genRRC (ic);
1146         break;
1147         
1148       case RLC:
1149         genRLC (ic);
1150         break;
1151         
1152       case GETHBIT:
1153         genGetHbit (ic);
1154         break;
1155         
1156       case LEFT_OP:
1157         genLeftShift (ic);
1158         break;
1159         
1160       case RIGHT_OP:
1161         genRightShift (ic);
1162         break;
1163         
1164       case GET_VALUE_AT_ADDRESS:
1165         genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_LEFT(ic)))));
1166         break;
1167         
1168       case '=':
1169         if (POINTER_SET (ic))
1170           genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
1171         else
1172           genAssign (ic);
1173         break;
1174         
1175       case IFX:
1176         genIfx (ic, NULL);
1177         break;
1178         
1179       case ADDRESS_OF:
1180         genAddrOf (ic);
1181         break;
1182         
1183       case JUMPTABLE:
1184         genJumpTab (ic);
1185         break;
1186         
1187       case CAST:
1188         genCast (ic);
1189         break;
1190         
1191       case RECEIVE:
1192         genReceive (ic);
1193         break;
1194         
1195       case SEND:
1196         addSet (&_G.sendSet, ic);
1197         break;
1198         
1199       default:
1200         ic = ic;
1201       }
1202   }
1203   
1204   
1205   /* now we are ready to call the
1206      peep hole optimizer */
1207   if (!options.nopeep)
1208     peepHole (&lineHead);
1209   
1210   /* now do the actual printing */
1211   printLine (lineHead, codeOutFile);
1212   return;
1213 }