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