xa51, work in progress
[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 -------------------------------------------------------------------------*/
27
28 //#define D(x)
29 #define D(x) x
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "SDCCglobl.h"
36 #include "newalloc.h"
37
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
40 #else
41 #ifdef HAVE_MACHINE_ENDIAN_H
42 #include <machine/endian.h>
43 #else
44 #ifdef HAVE_ENDIAN_H
45 #include <endian.h>
46 #else
47 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
48 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
49 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
50 #endif
51 #endif
52 #endif
53 #endif
54
55 #include "common.h"
56 #include "SDCCpeeph.h"
57 #include "ralloc.h"
58 #include "gen.h"
59
60 #if defined(__BORLANDC__) || defined(_MSC_VER)
61 #define STRCASECMP stricmp
62 #else
63 #define STRCASECMP strcasecmp
64 #endif
65
66 extern int allocInfo;
67
68 /* this is the down and dirty file with all kinds of
69    kludgy & hacky stuff. This is what it is all about
70    CODE GENERATION for a specific MCU . some of the
71    routines may be reusable, will have to see */
72
73 static struct
74   {
75     short inLine;
76     short debugLine;
77     short nRegsSaved;
78     set *sendSet;
79   }
80 _G;
81
82 extern int xa51_ptrRegReq;
83 extern int xa51_nRegs;
84 extern FILE *codeOutFile;
85
86 static lineNode *lineHead = NULL;
87 static lineNode *lineCurr = NULL;
88
89 #define LSB     0
90 #define MSB16   1
91 #define MSB24   2
92 #define MSB32   3
93
94 static char *MOV="mov";
95 static char *MOVB="mov.b";
96 static char *MOVW="mov.w";
97 static char *MOVC="movc";
98
99 static char *R1L="r1l";
100 static char *R1="r1";
101
102 void bailOut (char *mesg) {
103   fprintf (stderr, "%s: bailing out\n", mesg);
104   exit (1);
105 }
106
107 /*-----------------------------------------------------------------*/
108 /* emitcode - writes the code into a file : for now it is simple    */
109 /*-----------------------------------------------------------------*/
110 static void emitcode (char *inst, char *fmt,...) {
111   va_list ap;
112   char lb[INITIAL_INLINEASM];
113   char *lbp = lb;
114
115   va_start (ap, fmt);
116
117   if (inst && *inst)
118     {
119       if (fmt && *fmt)
120         sprintf (lb, "%s\t", inst);
121       else
122         sprintf (lb, "%s", inst);
123       vsprintf (lb + (strlen (lb)), fmt, ap);
124     }
125   else
126     vsprintf (lb, fmt, ap);
127
128   while (isspace ((int)*lbp))
129     lbp++;
130
131   if (lbp && *lbp)
132     lineCurr = (lineCurr ?
133                 connectLine (lineCurr, newLineNode (lb)) :
134                 (lineHead = newLineNode (lb)));
135   lineCurr->isInline = _G.inLine;
136   lineCurr->isDebug = _G.debugLine;
137   va_end (ap);
138 }
139
140 char *getStackOffset(int stack) {
141   static char gsoBuf[1024];
142   sprintf (gsoBuf, "r7+(%d%+d%+d)", stack,
143            FUNC_ISISR(currFunc->type) ? 
144              port->stack.isr_overhead : port->stack.call_overhead,
145            _G.nRegsSaved);
146   return gsoBuf;
147 }
148
149 /*-----------------------------------------------------------------*/
150 /* newAsmop - creates a new asmOp                                  */
151 /*-----------------------------------------------------------------*/
152 static asmop *
153 newAsmop (short type)
154 {
155   asmop *aop;
156
157   aop = Safe_calloc (1, sizeof (asmop));
158   aop->type = type;
159   return aop;
160 }
161
162 char *aopTypeName(asmop *aop) {
163   switch (aop->type)
164     {
165     case AOP_LIT: return "lit";
166     case AOP_REG: return "reg";
167     case AOP_DIR: return "dir";
168     case AOP_FAR: return "far";
169     case AOP_CODE: return "code";
170     case AOP_GPTR: return "gptr";
171     case AOP_STK: return "stack";
172     case AOP_IMMD: return "imm";
173     case AOP_BIT: return "bit";
174     }
175   return "unknown";
176 }
177
178 /*-----------------------------------------------------------------*/
179 /* aopForSym - for a true symbol                                   */
180 /*-----------------------------------------------------------------*/
181 static asmop *aopForSym(symbol *sym, 
182                         bool canUsePointer, bool canUseOffset) {
183   int size;
184   asmop *aop;
185
186   sym->aop = aop = newAsmop(0);
187   size=aop->size=getSize(sym->type);
188
189   // if the sym has registers
190   if (sym->nRegs && sym->regs[0]) {
191     aop->type=AOP_REG;
192     sprintf (aop->name[0], sym->regs[0]->name);
193     if (size > 2) {
194       sprintf (aop->name[1], sym->regs[1]->name);
195     }
196     return aop;
197   }
198
199   // if it is on stack
200   if (sym->onStack) {
201     if (!canUsePointer || !canUseOffset) {
202       aop->type=AOP_REG;
203       switch (size) 
204         {
205         case 1:
206           emitcode ("mov.b", "r0l,[%s]", getStackOffset(sym->stack));
207           sprintf (aop->name[0], "r0l");
208           return aop;
209         case 2:
210           emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
211           sprintf (aop->name[0], "r0");
212           return aop;
213         case 3:
214           emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
215           sprintf (aop->name[0], "r0");
216           emitcode ("mov.b", "r1l,[%s]", getStackOffset(sym->stack+2));
217           sprintf (aop->name[1], "r1l");
218           return aop;
219         case 4:
220           emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
221           sprintf (aop->name[0], "r0");
222           emitcode ("mov.w", "r1,[%s]", getStackOffset(sym->stack+2));
223           sprintf (aop->name[1], "r1");
224           return aop;
225         }
226     }
227     aop->type=AOP_STK;
228     sprintf (aop->name[0], "[%s]", getStackOffset(sym->stack));
229     if (size > 2) {
230       sprintf (aop->name[1], "[%s]", getStackOffset(sym->stack+2));
231     }
232     return aop;
233   }
234
235   // if it has a spillLoc
236   if (sym->usl.spillLoc) {
237     return aopForSym (sym->usl.spillLoc, canUsePointer, canUseOffset);
238   }
239
240   // if in bit space
241   if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
242     aop->type=AOP_BIT;
243     sprintf (aop->name[0], sym->rname);
244     return aop;
245   }
246
247   // if in direct space
248   if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
249     aop->type=AOP_DIR;
250     sprintf (aop->name[0], sym->rname);
251     if (size>2) {
252       sprintf (aop->name[1], "%s+2", sym->rname);
253     }
254     return aop;
255   }
256
257   // if in code space
258   if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
259     if (!canUsePointer) {
260       aop->type=AOP_REG;
261       switch (size) 
262         {
263         case 1:
264           emitcode (MOV, "r0,#%s", sym->rname);
265           emitcode (MOVC, "r0l,[r0]");
266           sprintf (aop->name[0], "r0l");
267           return aop;
268         case 2:
269           emitcode (MOV, "r0,#%s", sym->rname);
270           emitcode (MOVC, "r0,[r0]");
271           sprintf (aop->name[0], "r0");
272           return aop;
273         case 3:
274           emitcode (MOV, "r0,#%s", sym->rname);
275           emitcode (MOVC, "r1l,[r0+2]");
276           sprintf (aop->name[1], "r1l");
277           emitcode (MOV, "r0,[r0]");
278           sprintf (aop->name[0], "r0");
279           return aop;
280         case 4:
281           emitcode (MOV, "r0,#%s", sym->rname);
282           emitcode (MOVC, "r1,[r0+2]");
283           sprintf (aop->name[1], "r1");
284           emitcode (MOVC, "r0,[r0]");
285           sprintf (aop->name[0], "r0");
286           return aop;
287         }
288       
289     } else {
290       aop->type=AOP_CODE;
291       emitcode ("mov", "r0,#%s ; aopForSym:code", sym->rname);
292       sprintf (aop->name[0], "[r0]");
293       if (size>2) {
294         sprintf (aop->name[1], "[r0+2]");
295       }
296     }
297     return aop;
298   }
299
300   // if in far space
301   if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
302     if (!canUsePointer) {
303       aop->type=AOP_REG;
304       switch (size) 
305         {
306         case 1:
307           emitcode (MOV, "r0,#%s", sym->rname);
308           emitcode (MOV, "r0l,[r0]");
309           sprintf (aop->name[0], "r0l");
310           return aop;
311         case 2:
312           emitcode (MOV, "r0,#%s", sym->rname);
313           emitcode (MOV, "r0,[r0]");
314           sprintf (aop->name[0], "r0");
315           return aop;
316         case 3:
317           emitcode (MOV, "r0,#%s", sym->rname);
318           emitcode (MOV, "r1l,[r0+2]");
319           sprintf (aop->name[1], "r1l");
320           emitcode (MOV, "r0,[r0]");
321           sprintf (aop->name[0], "r0");
322           return aop;
323         case 4:
324           emitcode (MOV, "r0,#%s", sym->rname);
325           emitcode (MOV, "r1,[r0+2]");
326           sprintf (aop->name[1], "r1");
327           emitcode (MOV, "r0,[r0]");
328           sprintf (aop->name[0], "r0");
329           return aop;
330         }
331     } else {
332       aop->type=AOP_FAR;
333       emitcode ("mov", "r0,#%s ; aopForSym:far", sym->rname);
334       sprintf (aop->name[0], "[r0]");
335       if (size>2) {
336         sprintf (aop->name[1], "[r0+2]");
337       }
338       return aop;
339     }
340   }
341   
342   bailOut("aopForSym");
343   return NULL;
344 }
345
346 /*-----------------------------------------------------------------*/
347 /* aopForVal - for a value                                         */
348 /*-----------------------------------------------------------------*/
349 static asmop *aopForVal(operand *op) {
350   asmop *aop;
351
352   if (IS_OP_LITERAL(op)) {
353     op->aop = aop = newAsmop (AOP_LIT);
354     switch ((aop->size=getSize(operandType(op))))
355       {
356       case 1:
357         sprintf (aop->name[0], "#0x%02x", 
358                  SPEC_CVAL(operandType(op)).v_int & 0xff);
359         sprintf (aop->name[1], "#0");
360         break;
361       case 2:
362         sprintf (aop->name[0], "#0x%04x", 
363                  SPEC_CVAL(operandType(op)).v_int & 0xffff);
364         sprintf (aop->name[1], "#0");
365         break;
366       case 3:
367         // must be a generic pointer, can only be zero
368         // ?? if (v!=0) fprintf (stderr, "invalid val op for gptr\n"); exit(1);
369         sprintf (aop->name[0], "#0x%04x", 
370                  SPEC_CVAL(operandType(op)).v_uint & 0xffff);
371         sprintf (aop->name[1], "#0");
372         break;
373       case 4:
374         sprintf (aop->name[0], "#0x%04lx",
375                  SPEC_CVAL(operandType(op)).v_ulong >> 16);
376         sprintf (aop->name[1], "#0x%04x", 
377                  SPEC_CVAL(operandType(op)).v_ulong && 0xffff);
378         break;
379       default:
380         bailOut("aopForVal");
381       }
382     return aop;
383   }
384
385   // must be immediate
386   if (IS_SYMOP(op)) {
387     op->aop = aop = newAsmop (AOP_IMMD);
388     switch ((aop->size=getSize(OP_SYMBOL(op)->type))) 
389       {
390       case 1:
391       case 2:
392         sprintf (aop->name[0], "#%s", OP_SYMBOL(op)->rname);
393         return aop;
394       case 3: // generic pointer
395         sprintf (aop->name[0], "#0x%02x", DCL_TYPE(operandType(op)));
396         sprintf (aop->name[1], "#%s", OP_SYMBOL(op)->rname);
397         return aop;
398       }
399   }
400
401   bailOut ("aopForVal: unknown type");
402   return NULL;
403 }
404
405 static int aopOp(operand *op, 
406                   bool canUsePointer, bool canUseOffset) {
407
408   if (IS_SYMOP(op)) {
409     op->aop=aopForSym (OP_SYMBOL(op), canUsePointer, canUseOffset);
410     return AOP_SIZE(op);
411   }
412   if (IS_VALOP(op)) {
413     op->aop=aopForVal (op);
414     return AOP_SIZE(op);
415   }
416
417   bailOut("aopOp: unexpected operand");
418   return 0;
419 }
420
421 bool aopEqual(asmop *aop1, asmop *aop2, int offset) {
422   if (strcmp(aop1->name[offset], aop2->name[offset])) {
423     return FALSE;
424   }
425   return TRUE;
426 }
427
428 bool aopIsDir(operand *op) {
429   return AOP_TYPE(op)==AOP_DIR;
430 }
431
432 bool aopIsBit(operand *op) {
433   return AOP_TYPE(op)==AOP_BIT;
434 }
435
436 bool aopIsPtr(operand *op) {
437   if (AOP_TYPE(op)==AOP_STK ||
438       AOP_TYPE(op)==AOP_CODE ||
439       AOP_TYPE(op)==AOP_FAR) {
440     return TRUE;
441   } else {
442     return FALSE;
443   }
444 }
445       
446 char *opRegName(operand *op, int offset, char *opName) {
447
448   if (IS_SYMOP(op)) {
449     if (OP_SYMBOL(op)->onStack) {
450       sprintf (opName, "[%s]", getStackOffset(OP_SYMBOL(op)->stack));
451       return opName;
452     }
453     if (IS_TRUE_SYMOP(op))
454       return OP_SYMBOL(op)->rname;
455     else if (OP_SYMBOL(op)->regs[offset])
456       return OP_SYMBOL(op)->regs[offset]->name;
457     else
458       bailOut("opRegName: unknown regs");
459   }
460
461   if (IS_VALOP(op)) {
462     switch (SPEC_NOUN(OP_VALUE(op)->type)) {
463     case V_SBIT:
464     case V_BIT:
465       if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
466           SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
467         bailOut("opRegName: invalid bit value");
468       }
469       // fall through
470     case V_CHAR:
471       sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
472       break;
473     case V_INT:
474       if (SPEC_LONG(OP_VALUE(op)->type)) {
475         sprintf (opName, "#0x%02lx", SPEC_CVAL(OP_VALUE(op)->type).v_long);
476       } else {
477         sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
478       }
479       break;
480     case V_FLOAT:
481       sprintf (opName, "#%f", SPEC_CVAL(OP_VALUE(op)->type).v_float);
482       break;
483     default: 
484       bailOut("opRegName: unexpected noun");
485     }
486     return opName;
487   }
488   bailOut("opRegName: unexpected operand type");
489   return NULL;
490 }
491
492 char * printOp (operand *op) {
493   static char line[132];
494   sym_link *optype=operandType(op);
495   bool isPtr = IS_PTR(optype);
496
497   if (IS_SYMOP(op)) {
498     symbol *sym=OP_SYMBOL(op);
499     if (!sym->regs[0] && SYM_SPIL_LOC(sym)) {
500       sym=SYM_SPIL_LOC(sym);
501     }
502     if (isPtr) {
503       sprintf (line, "[");
504       if (DCL_TYPE(optype)==FPOINTER)
505         strcat (line, "far * ");
506       else if (DCL_TYPE(optype)==CPOINTER)
507         strcat (line, "code * ");
508       else if (DCL_TYPE(optype)==GPOINTER)
509         strcat (line, "gen * ");
510       else if (DCL_TYPE(optype)==POINTER)
511         strcat (line, "near * ");
512       else
513         strcat (line, "unknown * ");
514       strcat (line, "(");
515       strcat (line, nounName(sym->etype));
516       strcat (line, ")");
517       strcat (line, sym->name);
518       strcat (line, "]:");
519     } else {
520       sprintf (line, "(%s)%s:", nounName(sym->etype), sym->name);
521     }
522     if (sym->regs[0]) {
523       strcat (line, sym->regs[0]->name);
524       if (sym->regs[1]) {
525         strcat (line, ",");
526         strcat (line, sym->regs[1]->name);
527       }
528       return line;
529     }
530     if (sym->onStack) {
531       sprintf (line+strlen(line), "stack%+d", sym->stack);
532       return line;
533     }
534     if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
535       strcat (line, "code");
536       return line;
537     }
538     if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
539       strcat (line, "far");
540       return line;
541     }
542     if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
543       strcat (line, "bit");
544       return line;
545     }
546     if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
547       strcat (line, "dir");
548       return line;
549     }
550     strcat (line, "unknown");
551     return line;
552   } else if (IS_VALOP(op)) {
553     opRegName(op, 0, line);
554   } else if (IS_TYPOP(op)) {
555     sprintf (line, "[");
556     if (isPtr) {
557       if (DCL_TYPE(optype)==FPOINTER)
558         strcat (line, "far * ");
559       else if (DCL_TYPE(optype)==CPOINTER)
560         strcat (line, "code * ");
561       else if (DCL_TYPE(optype)==GPOINTER)
562         strcat (line, "gen * ");
563       else if (DCL_TYPE(optype)==POINTER)
564         strcat (line, "near * ");
565       else
566         strcat (line, "unknown * ");
567     }
568     // forget about static, volatile, ... for now
569     if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
570     if (SPEC_LONG(operandType(op))) strcat (line, "long ");
571     strcat (line, nounName(operandType(op)));
572     strcat (line, "]");
573   } else {
574     bailOut("printOp: unexpected operand type");
575   }
576   return line;
577 }
578
579 void printIc (char *op, iCode * ic, bool result, bool left, bool right) {
580   char line[132];
581
582   sprintf (line, "%s(%d)", op, ic->lineno);
583   if (result) {
584     strcat (line, " result=");
585     strcat (line, printOp (IC_RESULT(ic)));
586   }
587   if (left) {
588     strcat (line, " left=");
589     strcat (line, printOp (IC_LEFT(ic)));
590   }
591   if (right) {
592     strcat (line, " right=");
593     strcat (line, printOp (IC_RIGHT(ic)));
594   }
595   emitcode (";", line);
596 }
597
598 /*-----------------------------------------------------------------*/
599 /* toBoolean - return carry for operand!=0                           */
600 /*-----------------------------------------------------------------*/
601 static char *toBoolean (operand * op) {
602   switch (AOP_SIZE(op)) 
603     {
604     case 1:
605     case 2:
606       emitcode ("cmp", "%s,#0", AOP_NAME(op));
607       emitcode ("mov", "c,z");
608       return "c";
609     }
610
611   bailOut("toBoolean: unknown size");
612   return NULL;
613 }
614
615 /*-----------------------------------------------------------------*/
616 /* regsInCommon - two operands have some registers in common       */
617 /*-----------------------------------------------------------------*/
618 static bool regsInCommon (operand * op1, operand * op2) {
619   symbol *sym1, *sym2;
620   int i;
621
622   /* if they have registers in common */
623   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
624     return FALSE;
625
626   sym1 = OP_SYMBOL (op1);
627   sym2 = OP_SYMBOL (op2);
628
629   if (sym1->nRegs == 0 || sym2->nRegs == 0)
630     return FALSE;
631
632   for (i = 0; i < sym1->nRegs; i++)
633     {
634       int j;
635       if (!sym1->regs[i])
636         continue;
637
638       for (j = 0; j < sym2->nRegs; j++)
639         {
640           if (!sym2->regs[j])
641             continue;
642
643           if (sym2->regs[j] == sym1->regs[i])
644             return TRUE;
645         }
646     }
647
648   return FALSE;
649 }
650
651 /*-----------------------------------------------------------------*/
652 /* resultRemat - result  is rematerializable                       */
653 /*-----------------------------------------------------------------*/
654 static int resultRemat (iCode * ic) {
655   if (SKIP_IC (ic) || ic->op == IFX)
656     return 0;
657   
658   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
659     {
660       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
661       if (sym->remat && !POINTER_SET (ic))
662         return 1;
663     }
664   
665   return 0;
666 }
667
668 /*-----------------------------------------------------------------*/
669 /* genNot - generate code for ! operation                          */
670 /*-----------------------------------------------------------------*/
671 static void genNot (iCode * ic) {
672   printIc("genNot:", ic, 1,1,0);
673 }
674
675 /*-----------------------------------------------------------------*/
676 /* genCpl - generate code for complement                           */
677 /*-----------------------------------------------------------------*/
678 static void genCpl (iCode * ic) {
679   printIc("genCpl", ic, 1,1,0);
680 }
681
682 /*-----------------------------------------------------------------*/
683 /* genUminus - unary minus code generation                         */
684 /*-----------------------------------------------------------------*/
685 static void genUminus (iCode * ic) {
686   printIc("genUminus", ic, 1,1,0);
687 }
688
689 /*-----------------------------------------------------------------*/
690 /* genIpush - genrate code for pushing this gets a little complex  */
691 /*-----------------------------------------------------------------*/
692 static void genIpush (iCode * ic) {
693   printIc ("genIpush", ic, 0,1,0);
694 }
695
696 /*-----------------------------------------------------------------*/
697 /* genIpop - recover the registers: can happen only for spilling   */
698 /*-----------------------------------------------------------------*/
699 static void genIpop (iCode * ic) {
700   printIc ("genIpop", ic, 0,1,0);
701 }
702
703 /*-----------------------------------------------------------------*/
704 /* genCall - generates a call statement                            */
705 /*-----------------------------------------------------------------*/
706 static void genCall (iCode * ic) {
707   emitcode (";", "genCall %s result=%s", OP_SYMBOL(IC_LEFT(ic))->name,
708             printOp (IC_RESULT(ic)));
709 }
710
711 /*-----------------------------------------------------------------*/
712 /* genPcall - generates a call by pointer statement                */
713 /*-----------------------------------------------------------------*/
714 static void
715 genPcall (iCode * ic)
716 {
717   emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
718 }
719
720 /*-----------------------------------------------------------------*/
721 /* genFunction - generated code for function entry                 */
722 /*-----------------------------------------------------------------*/
723 static void genFunction (iCode * ic) {
724   symbol *sym=OP_SYMBOL(IC_LEFT(ic));
725   sym_link *type=sym->type;
726
727   emitcode (";", "-----------------------------------------");
728   emitcode (";", " function %s", sym->name);
729   emitcode (";", "-----------------------------------------");
730   
731   emitcode ("", "%s:", sym->rname);
732
733   if (IFFUNC_ISNAKED(type))
734   {
735       emitcode(";", "naked function: no prologue.");
736       return;
737   }
738
739   /* if critical function then turn interrupts off */
740   if (IFFUNC_ISCRITICAL (type))
741     emitcode ("clr", "ea");
742
743 }
744
745 /*-----------------------------------------------------------------*/
746 /* genEndFunction - generates epilogue for functions               */
747 /*-----------------------------------------------------------------*/
748 static void
749 genEndFunction (iCode * ic)
750 {
751   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
752
753   if (IFFUNC_ISNAKED(sym->type))
754   {
755       emitcode(";", "naked function: no epilogue.");
756       return;
757   }
758
759   printIc ("genEndFunction", ic, 0,0,0);
760 }
761
762 /*-----------------------------------------------------------------*/
763 /* genRet - generate code for return statement                     */
764 /*-----------------------------------------------------------------*/
765 static void genRet (iCode * ic) {
766
767   printIc ("genRet", ic, 0,1,0);
768
769   aopOp(IC_LEFT(ic), TRUE, TRUE);
770
771   switch (AOP_SIZE(IC_LEFT(ic)))
772     {
773     case 4:
774       emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
775       emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
776       return;
777     case 3:
778       emitcode ("mov", "r1l,%s", AOP_NAME(IC_LEFT(ic))[1]);
779       // fall through
780     case 2:
781       emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
782       return;
783     case 1:
784       emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
785       return;
786     }
787   bailOut("genRet");
788 }
789
790 /*-----------------------------------------------------------------*/
791 /* genLabel - generates a label                                    */
792 /*-----------------------------------------------------------------*/
793 static void genLabel (iCode * ic) {
794   /* special case never generate */
795   if (IC_LABEL (ic) == entryLabel)
796     return;
797
798   emitcode (";", "genLabel %s", IC_LABEL(ic)->name);
799   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
800 }
801
802 /*-----------------------------------------------------------------*/
803 /* genGoto - generates a jmp                                      */
804 /*-----------------------------------------------------------------*/
805 static void genGoto (iCode * ic) {
806   emitcode (";", "genGoto %s", IC_LABEL(ic)->name);
807   emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
808 }
809
810 /*-----------------------------------------------------------------*/
811 /* genPlus - generates code for addition                           */
812 /*-----------------------------------------------------------------*/
813 static void genPlus (iCode * ic) {
814   printIc ("genPlus", ic, 1,1,1);
815 }
816
817 /*-----------------------------------------------------------------*/
818 /* genMinus - generates code for subtraction                       */
819 /*-----------------------------------------------------------------*/
820 static void genMinus (iCode * ic) {
821   printIc ("genMinus", ic, 1,1,1);
822 }
823
824
825 /*-----------------------------------------------------------------*/
826 /* genMult - generates code for multiplication                     */
827 /*-----------------------------------------------------------------*/
828 static void genMult (iCode * ic) {
829   printIc ("genMult", ic, 1,1,1);
830 }
831
832 /*-----------------------------------------------------------------*/
833 /* genDiv - generates code for division                            */
834 /*-----------------------------------------------------------------*/
835 static void genDiv (iCode * ic) {
836   printIc ("genDiv", ic, 1,1,1);
837 }
838
839 /*-----------------------------------------------------------------*/
840 /* genMod - generates code for division                            */
841 /*-----------------------------------------------------------------*/
842 static void genMod (iCode * ic) {
843   printIc ("genMod", ic, 1,1,1);
844 }
845
846 /*-----------------------------------------------------------------*/
847 /* genCmpGt :- greater than comparison                             */
848 /*-----------------------------------------------------------------*/
849 static void genCmpGt (iCode * ic) {
850   printIc ("genCmpGt", ic, 1,1,1);
851 }
852 /*-----------------------------------------------------------------*/
853 /* genCmpGt :- greater than comparison                             */
854 /*-----------------------------------------------------------------*/
855 static void genCmpLe (iCode * ic) {
856   printIc ("genCmpLe", ic, 1,1,1);
857 }
858 /*-----------------------------------------------------------------*/
859 /* genCmpGt :- greater than comparison                             */
860 /*-----------------------------------------------------------------*/
861 static void genCmpGe (iCode * ic) {
862   printIc ("genCmpGe", ic, 1,1,1);
863 }
864 /*-----------------------------------------------------------------*/
865 /* genCmpGt :- greater than comparison                             */
866 /*-----------------------------------------------------------------*/
867 static void genCmpNe (iCode * ic) {
868   printIc ("genCmpNe", ic, 1,1,1);
869 }
870 /*-----------------------------------------------------------------*/
871 /* genCmpLt - less than comparisons                                */
872 /*-----------------------------------------------------------------*/
873 static void genCmpLt (iCode * ic) {
874   printIc ("genCmpLt", ic, 1,1,1);
875 }
876 /*-----------------------------------------------------------------*/
877 /* genCmpEq - generates code for equal to                          */
878 /*-----------------------------------------------------------------*/
879 static void genCmpEq (iCode * ic) {
880   printIc ("genCmpEq", ic, 1,1,1);
881 }
882
883 /*-----------------------------------------------------------------*/
884 /* ifxForOp - returns the icode containing the ifx for operand     */
885 /*-----------------------------------------------------------------*/
886 static iCode *ifxForOp (operand * op, iCode * ic) {
887   /* if true symbol then needs to be assigned */
888   if (IS_TRUE_SYMOP (op))
889     return NULL;
890   
891   /* if this has register type condition and
892      the next instruction is ifx with the same operand
893      and live to of the operand is upto the ifx only then */
894   if (ic->next &&
895       ic->next->op == IFX &&
896       IC_COND (ic->next)->key == op->key &&
897       OP_SYMBOL (op)->liveTo <= ic->next->seq)
898     return ic->next;
899   
900   return NULL;
901 }
902
903 /*-----------------------------------------------------------------*/
904 /* hasInc - operand is incremented before any other use            */
905 /*-----------------------------------------------------------------*/
906 static iCode *hasInc (operand *op, iCode *ic, int osize) {
907   sym_link *type = operandType(op);
908   sym_link *retype = getSpec (type);
909   iCode *lic = ic->next;
910   int isize ;
911   
912   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
913   if (!IS_SYMOP(op)) return NULL;
914
915   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
916   if (IS_AGGREGATE(type->next)) return NULL;
917   if (osize != (isize = getSize(type->next))) return NULL;
918
919   while (lic) {
920     /* if operand of the form op = op + <sizeof *op> */
921     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
922         isOperandEqual(IC_RESULT(lic),op) && 
923         isOperandLiteral(IC_RIGHT(lic)) &&
924         operandLitValue(IC_RIGHT(lic)) == isize) {
925       return lic;
926     }
927     /* if the operand used or deffed */
928     if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
929       return NULL;
930     }
931     /* if GOTO or IFX */
932     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
933     lic = lic->next;
934   }
935   return NULL;
936 }
937
938 /*-----------------------------------------------------------------*/
939 /* genAndOp - for && operation                                     */
940 /*-----------------------------------------------------------------*/
941 static void genAndOp (iCode * ic) {
942   printIc ("genAndOp(&&)", ic, 1,1,1);
943 }
944
945 /*-----------------------------------------------------------------*/
946 /* genOrOp - for || operation                                      */
947 /*-----------------------------------------------------------------*/
948 static void genOrOp (iCode * ic) {
949   printIc ("genOrOp(||)", ic, 1,1,1);
950 }
951
952 /*-----------------------------------------------------------------*/
953 /* genAnd  - code for and                                            */
954 /*-----------------------------------------------------------------*/
955 static void genAnd (iCode * ic, iCode * ifx) {
956   printIc ("genAnd", ic, 1,1,1);
957 }
958
959 /*-----------------------------------------------------------------*/
960 /* genOr  - code for or                                            */
961 /*-----------------------------------------------------------------*/
962 static void genOr (iCode * ic, iCode * ifx) {
963   operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
964   int size=aopOp(result, TRUE, TRUE);
965   char *instr;
966
967   printIc ("genOr", ic, 1,1,1);
968
969   /* if left is a literal, then exchange them */
970   if (IS_LITERAL(operandType(left))) {
971     operand *tmp = right;
972     right = left;
973     left = tmp;
974   }
975     
976   if (aopIsBit(result)) {
977     if (IS_LITERAL(operandType(right))) {
978       if (operandLitValue(right)) {
979         emitcode ("setb", AOP_NAME(result)[0]);
980         return;
981       }
982       aopOp(left, TRUE, TRUE);
983       emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
984       return;
985     }
986   }
987   
988   aopOp(left, !aopIsPtr(result), !aopIsDir(result));
989   aopOp(right, !aopIsPtr(result), !aopIsDir(result));
990
991   if (size>1) {
992     instr="or.w";
993   } else {
994     instr="or.b";
995   }
996   if (!aopEqual(result->aop, left->aop, 0)) {
997     emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
998   }
999   emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1000   if (size>2) {
1001     if (!aopEqual(result->aop, left->aop, 1)) {
1002       emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1003     }
1004     emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1005   }
1006   return;
1007 }
1008
1009 /*-----------------------------------------------------------------*/
1010 /* genXor - code for xclusive or                                   */
1011 /*-----------------------------------------------------------------*/
1012 static void genXor (iCode * ic, iCode * ifx) {
1013   printIc ("genXor", ic, 1,1,1);
1014 }
1015
1016 /*-----------------------------------------------------------------*/
1017 /* genInline - write the inline code out                           */
1018 /*-----------------------------------------------------------------*/
1019 static void genInline (iCode * ic) {
1020
1021   printIc ("genInline", ic, 0,0,0);
1022   
1023   emitcode ("", IC_INLINE(ic));
1024 }
1025
1026 /*-----------------------------------------------------------------*/
1027 /* genRRC - rotate right with carry                                */
1028 /*-----------------------------------------------------------------*/
1029 static void genRRC (iCode * ic) {
1030   printIc ("genRRC", ic, 1,1,0);
1031 }
1032
1033 /*-----------------------------------------------------------------*/
1034 /* genRLC - generate code for rotate left with carry               */
1035 /*-----------------------------------------------------------------*/
1036 static void genRLC (iCode * ic) {
1037   printIc ("genRLC", ic, 1,1,0);
1038 }
1039
1040 /*-----------------------------------------------------------------*/
1041 /* genGetHbit - generates code get highest order bit               */
1042 /*-----------------------------------------------------------------*/
1043 static void genGetHbit (iCode * ic) {
1044   printIc ("genGetHbit", ic, 1,1,0);
1045 }
1046
1047 /*-----------------------------------------------------------------*/
1048 /* genLeftShift - generates code for left shifting                 */
1049 /*-----------------------------------------------------------------*/
1050 static void genLeftShift (iCode * ic) {
1051   printIc ("genLeftShift", ic, 1,1,1);
1052 }
1053
1054 /*-----------------------------------------------------------------*/
1055 /* genRightShift - generate code for right shifting                */
1056 /*-----------------------------------------------------------------*/
1057 static void genRightShift (iCode * ic) {
1058   printIc ("genRightShift", ic, 1,1,1);
1059 }
1060
1061 /*-----------------------------------------------------------------*/
1062 /* genPointerGet - generate code for pointer get                   */
1063 /*-----------------------------------------------------------------*/
1064 static void genPointerGet (iCode * ic, iCode *pi) {
1065   char *instr, *scratchReg;
1066   operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
1067   int size;
1068
1069   printIc ("genPointerGet", ic, 1,1,0);
1070
1071   if (!IS_PTR(operandType(left))) {
1072     bailOut ("genPointerGet: pointer required");
1073   }
1074
1075   aopOp(left,FALSE,FALSE);
1076   size=aopOp(result,TRUE,aopIsDir(left));
1077
1078   if (IS_GENPTR(operandType(left))) {
1079     emitcode (";", "INLINE\t_gptrget ; %s %s = [%s %s]", 
1080               AOP_NAME(result)[0], AOP_NAME(result)[1],
1081               AOP_NAME(left)[0], AOP_NAME(left)[1]);
1082     return;
1083   }
1084
1085   switch (AOP_TYPE(left)) 
1086     {
1087     case AOP_REG:
1088       if (size>1) {
1089         instr=MOVW;
1090         scratchReg=R1;
1091       } else {
1092         instr=MOVB;
1093         scratchReg=R1L;
1094       }
1095       if (AOP_TYPE(result)==AOP_STK) {
1096         emitcode (MOV, "%s,[%s]", scratchReg, AOP_NAME(left)[0]);
1097         emitcode (MOV, "%s,%s", AOP_NAME(result)[0], scratchReg);
1098       } else {
1099         emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1100       }
1101       if (size > 2) {
1102         if (size==3) {
1103           instr=MOVB;
1104           scratchReg=R1L;
1105         }
1106         if (AOP_TYPE(result)==AOP_STK) {
1107           emitcode (MOV, "%s,[%s+2]", scratchReg, AOP_NAME(left)[0]);
1108           emitcode (MOV, "%s,%s", AOP_NAME(result)[1], scratchReg);
1109         } else {
1110           emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1], 
1111                     AOP_NAME(left)[0]);
1112         }
1113       }
1114       return;
1115     }
1116   bailOut ("genPointerGet");
1117 }
1118
1119 /*-----------------------------------------------------------------*/
1120 /* genPointerSet - stores the value into a pointer location        */
1121 /*-----------------------------------------------------------------*/
1122 static void genPointerSet (iCode * ic, iCode *pi) {
1123   char *instr;
1124   operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1125   int size;
1126
1127   printIc ("genPointerSet", ic, 1,0,1);
1128
1129   if (!IS_PTR(operandType(result))) {
1130     bailOut ("genPointerSet: pointer required");
1131   }
1132
1133   aopOp(result,FALSE,FALSE);
1134   size=aopOp(right,FALSE, FALSE);
1135
1136   if (IS_GENPTR(operandType(result))) {
1137     emitcode (";", "INLINE\t_gptrset ; [%s %s] = %s %s", 
1138               AOP_NAME(result)[0], AOP_NAME(result)[1],
1139               AOP_NAME(right)[0], AOP_NAME(right)[1]);
1140     return;
1141   }
1142
1143   switch (AOP_TYPE(right)) 
1144     {
1145     case AOP_LIT:
1146     case AOP_REG:
1147       if (size>1) {
1148         instr=MOVW;
1149       } else {
1150         instr=MOVB;
1151       }
1152       emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1153       if (size > 2) {
1154         if (size==3) {
1155           instr=MOVB;
1156         }
1157         emitcode (instr, "[%s+2],%s", AOP_NAME(result)[0], AOP_NAME(right)[1]);
1158       }
1159       return;
1160     }
1161   bailOut ("genPointerSet");
1162 }
1163
1164 /*-----------------------------------------------------------------*/
1165 /* genIfx - generate code for Ifx statement                        */
1166 /*-----------------------------------------------------------------*/
1167 static void genIfx (iCode * ic, iCode * popIc) {
1168   int size;
1169   char *instr;
1170   bool trueOrFalse;
1171   symbol *jlbl, *tlbl;
1172   operand *cond=IC_COND(ic);
1173
1174   emitcode (";", "genIfx cond=%s trueLabel:%s falseLabel:%s", 
1175             printOp(cond),
1176             IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1177             IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1178
1179   size=aopOp(cond,TRUE,TRUE);
1180
1181   if (IC_TRUE(ic)) {
1182     trueOrFalse=TRUE;
1183     jlbl=IC_TRUE(ic);
1184   } else {
1185     trueOrFalse=FALSE;
1186     jlbl=IC_FALSE(ic);
1187   }
1188
1189   switch (AOP_TYPE(cond) )
1190     {
1191     case AOP_BIT:
1192       emitcode (trueOrFalse ? "jb" : "jbc", "%s,%05d$", 
1193                 AOP_NAME(cond)[0], jlbl->key+100);
1194       return;
1195     case AOP_REG:
1196     case AOP_DIR:
1197     case AOP_FAR:
1198     case AOP_STK:
1199       tlbl=newiTempLabel(NULL);
1200       if (size>1) {
1201         instr="cmp.w";
1202       } else {
1203         instr="cmp.b";
1204       }
1205       emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1206       emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1207       if (size > 2) {
1208         if (size==3) {
1209           // generic pointer, just consider the pointer part
1210         } else {
1211           emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1212           emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1213         }
1214       }
1215       emitcode ("jmp", "%05d$", jlbl->key+100);
1216       emitcode ("", "%05d$:", tlbl->key+100);
1217       return;
1218     }
1219   bailOut ("genIfx");
1220 }
1221
1222 /*-----------------------------------------------------------------*/
1223 /* genAddrOf - generates code for address of                       */
1224 /*-----------------------------------------------------------------*/
1225 static void genAddrOf (iCode * ic) {
1226   int size;
1227   operand *left=IC_LEFT(ic);
1228
1229   printIc ("genAddrOf", ic, 1,1,0);
1230
1231   size=aopOp (IC_RESULT(ic), FALSE, TRUE);
1232
1233   if (isOperandOnStack(left)) {
1234     emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1235               getStackOffset(OP_SYMBOL(left)->stack));
1236     if (size > 2) {
1237       // this must be a generic pointer
1238       emitcode ("mov", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER);
1239     }
1240     return;
1241   }
1242
1243   if (isOperandInDirSpace(left) ||
1244       isOperandInFarSpace(left) ||
1245       isOperandInCodeSpace(left)) {
1246     emitcode ("mov.w", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1247               OP_SYMBOL(left)->rname);
1248     if (size > 2) {
1249       // this must be a generic pointer
1250       int space=0; // dir space
1251       if (isOperandInFarSpace(left)) {
1252         space=1;
1253       } else if (isOperandInCodeSpace(left)) {
1254         space=2;
1255       }
1256       emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1257     }
1258     return;
1259   }
1260
1261   bailOut("genAddrOf");
1262 }
1263
1264 /*-----------------------------------------------------------------*/
1265 /* genAssign - generate code for assignment                        */
1266 /*-----------------------------------------------------------------*/
1267 static void genAssign (iCode * ic) {
1268   operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1269   int size;
1270   char *instr;
1271
1272   printIc ("genAssign", ic, 1,0,1);
1273   
1274   if (!IS_SYMOP(result)) {
1275     bailOut("genAssign: result is not a symbol");
1276   }
1277   
1278   aopOp(result, TRUE, TRUE);
1279   aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1280   size=AOP_SIZE(result);
1281
1282   /* if result is a bit */
1283   if (AOP_TYPE(result) == AOP_BIT) {
1284     /* if right is literal, we know what the value is */
1285     if (AOP_TYPE(right) == AOP_LIT) {
1286       if (operandLitValue(right)) {
1287         emitcode ("setb", AOP_NAME(result)[0]);
1288       } else {
1289         emitcode ("clr", AOP_NAME(result)[0]);
1290       }
1291       return;
1292     }
1293     /* if right is also a bit */
1294     if (AOP_TYPE(right) == AOP_BIT) {
1295       emitcode ("mov", "c,%s", AOP_NAME(right));
1296       emitcode ("mov", "%s,c", AOP_NAME(result));
1297       return;
1298     }
1299     /* we need to or */
1300     emitcode ("mov", "%s,%s", AOP_NAME(result), toBoolean(right));
1301     return;
1302   }
1303
1304   /* general case */
1305   if (size>1) {
1306     instr=MOVW;
1307   } else {
1308     instr=MOVB;
1309   }
1310   emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1311
1312   if (size > 2) {
1313     if (size==3) {
1314       // generic pointer
1315       instr=MOVB;
1316     }
1317     emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1318     return;
1319   }
1320 }
1321
1322 /*-----------------------------------------------------------------*/
1323 /* genJumpTab - genrates code for jump table                       */
1324 /*-----------------------------------------------------------------*/
1325 static void genJumpTab (iCode * ic) {
1326   printIc ("genJumpTab", ic, 0,0,0);
1327 }
1328
1329 /*-----------------------------------------------------------------*/
1330 /* genCast - gen code for casting                                  */
1331 /*-----------------------------------------------------------------*/
1332 static void genCast (iCode * ic) {
1333   printIc ("genCast", ic, 1,1,1);
1334 }
1335
1336 /*-----------------------------------------------------------------*/
1337 /* genDjnz - generate decrement & jump if not zero instrucion      */
1338 /*-----------------------------------------------------------------*/
1339 static bool genDjnz (iCode * ic, iCode * ifx) {
1340   symbol *lbl, *lbl1;
1341
1342   if (!ifx)
1343     return 0;
1344
1345   /* if the if condition has a false label
1346      then we cannot save */
1347   if (IC_FALSE (ifx))
1348     return 0;
1349
1350   /* if the minus is not of the form
1351      a = a - 1 */
1352   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1353       !IS_OP_LITERAL (IC_RIGHT (ic)))
1354     return 0;
1355
1356   if (operandLitValue (IC_RIGHT (ic)) != 1)
1357     return 0;
1358
1359   /* if the size of this greater than two then no
1360      saving */
1361   if (getSize (operandType (IC_RESULT (ic))) > 2)
1362     return 0;
1363
1364   printIc ("genDjnz", ic, 1,1,1);
1365
1366   /* otherwise we can save BIG */
1367   lbl = newiTempLabel (NULL);
1368   lbl1 = newiTempLabel (NULL);
1369
1370   aopOp (IC_RESULT (ic), FALSE, TRUE);
1371
1372   if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1373     emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1374     emitcode ("br", "%05d$", lbl1->key + 100);
1375     emitcode ("", "%05d$:", lbl->key + 100);
1376     emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1377     emitcode ("", "%05d$:", lbl1->key + 100);
1378     return TRUE;
1379   }
1380
1381   bailOut("genDjnz: aop type");
1382   return FALSE;
1383 }
1384
1385 /*-----------------------------------------------------------------*/
1386 /* genReceive - generate code for a receive iCode                  */
1387 /*-----------------------------------------------------------------*/
1388 static void genReceive (iCode * ic) {
1389   printIc ("genReceive", ic, 1,0,0);
1390 }
1391
1392 /*-----------------------------------------------------------------*/
1393 /* gen51Code - generate code for 8051 based controllers            */
1394 /*-----------------------------------------------------------------*/
1395 void genXA51Code (iCode * lic) {
1396   iCode *ic;
1397   int cln = 0;
1398   
1399   lineHead = lineCurr = NULL;
1400   
1401   /* print the allocation information */
1402   if (allocInfo)
1403     printAllocInfo (currFunc, codeOutFile);
1404
1405   /* if debug information required */
1406   if (options.debug && currFunc)
1407     {
1408       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1409       _G.debugLine = 1;
1410       if (IS_STATIC (currFunc->etype))
1411         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1412       else
1413         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1414       _G.debugLine = 0;
1415     }
1416   
1417   for (ic = lic; ic; ic = ic->next) {
1418     if (ic->lineno && cln != ic->lineno) {
1419       if (options.debug) {
1420         _G.debugLine = 1;
1421         emitcode ("", "C$%s$%d$%d$%d ==.",
1422                   FileBaseName (ic->filename), ic->lineno,
1423                   ic->level, ic->block);
1424         _G.debugLine = 0;
1425       }
1426       emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
1427                 printCLine(ic->filename, ic->lineno));
1428       cln = ic->lineno;
1429     }
1430     /* if the result is marked as
1431        spilt and rematerializable or code for
1432        this has already been generated then
1433        do nothing */
1434     if (resultRemat (ic) || ic->generated)
1435       continue;
1436     
1437     /* depending on the operation */
1438     switch (ic->op)
1439       {
1440       case '!':
1441         genNot (ic);
1442         break;
1443         
1444       case '~':
1445         genCpl (ic);
1446         break;
1447         
1448       case UNARYMINUS:
1449         genUminus (ic);
1450         break;
1451         
1452       case IPUSH:
1453         genIpush (ic);
1454         break;
1455         
1456       case IPOP:
1457         /* IPOP happens only when trying to restore a
1458            spilt live range, if there is an ifx statement
1459            following this pop then the if statement might
1460            be using some of the registers being popped which
1461            would destory the contents of the register so
1462            we need to check for this condition and handle it */
1463         if (ic->next &&
1464             ic->next->op == IFX &&
1465             regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1466           genIfx (ic->next, ic);
1467         else
1468           genIpop (ic);
1469         break;
1470         
1471       case CALL:
1472         genCall (ic);
1473         break;
1474         
1475       case PCALL:
1476         genPcall (ic);
1477         break;
1478         
1479       case FUNCTION:
1480         genFunction (ic);
1481         break;
1482         
1483       case ENDFUNCTION:
1484         genEndFunction (ic);
1485         break;
1486         
1487       case RETURN:
1488         genRet (ic);
1489         break;
1490         
1491       case LABEL:
1492         genLabel (ic);
1493         break;
1494         
1495       case GOTO:
1496         genGoto (ic);
1497         break;
1498         
1499       case '+':
1500         genPlus (ic);
1501         break;
1502         
1503       case '-':
1504         if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
1505           genMinus (ic);
1506         break;
1507         
1508       case '*':
1509         genMult (ic);
1510         break;
1511         
1512       case '/':
1513         genDiv (ic);
1514         break;
1515         
1516       case '%':
1517         genMod (ic);
1518         break;
1519         
1520       case '>':
1521         genCmpGt (ic);
1522         break;
1523         
1524       case '<':
1525         genCmpLt (ic);
1526         break;
1527         
1528       case LE_OP:
1529         genCmpLe (ic);
1530         break;
1531
1532       case GE_OP:
1533         genCmpGe (ic);
1534         break;
1535
1536       case NE_OP:
1537         genCmpNe (ic);
1538         break;
1539
1540       case EQ_OP:
1541         genCmpEq (ic);
1542         break;
1543         
1544       case AND_OP:
1545         genAndOp (ic);
1546         break;
1547         
1548       case OR_OP:
1549         genOrOp (ic);
1550         break;
1551         
1552       case '^':
1553         genXor (ic, ifxForOp (IC_RESULT (ic), ic));
1554         break;
1555         
1556       case '|':
1557         genOr (ic, ifxForOp (IC_RESULT (ic), ic));
1558         break;
1559         
1560       case BITWISEAND:
1561         genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
1562         break;
1563         
1564       case INLINEASM:
1565         genInline (ic);
1566         break;
1567         
1568       case RRC:
1569         genRRC (ic);
1570         break;
1571         
1572       case RLC:
1573         genRLC (ic);
1574         break;
1575         
1576       case GETHBIT:
1577         genGetHbit (ic);
1578         break;
1579         
1580       case LEFT_OP:
1581         genLeftShift (ic);
1582         break;
1583         
1584       case RIGHT_OP:
1585         genRightShift (ic);
1586         break;
1587         
1588       case GET_VALUE_AT_ADDRESS:
1589         genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_LEFT(ic)))));
1590         break;
1591         
1592       case '=':
1593         if (POINTER_SET (ic))
1594           genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
1595         else
1596           genAssign (ic);
1597         break;
1598         
1599       case IFX:
1600         genIfx (ic, NULL);
1601         break;
1602         
1603       case ADDRESS_OF:
1604         genAddrOf (ic);
1605         break;
1606         
1607       case JUMPTABLE:
1608         genJumpTab (ic);
1609         break;
1610         
1611       case CAST:
1612         genCast (ic);
1613         break;
1614         
1615       case RECEIVE:
1616         genReceive (ic);
1617         break;
1618         
1619       case SEND:
1620         addSet (&_G.sendSet, ic);
1621         break;
1622         
1623       default:
1624         ic = ic;
1625       }
1626   }
1627   
1628   
1629   /* now we are ready to call the
1630      peep hole optimizer */
1631   if (!options.nopeep)
1632     peepHole (&lineHead);
1633   
1634   /* now do the actual printing */
1635   printLine (lineHead, codeOutFile);
1636   return;
1637 }