*** empty log message ***
[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 stackExtend;
78     short nRegsSaved;
79     short parmsPushed;
80     set *sendSet;
81   }
82 _G;
83
84 extern int xa51_ptrRegReq;
85 extern int xa51_nRegs;
86 extern FILE *codeOutFile;
87
88 static lineNode *lineHead = NULL;
89 static lineNode *lineCurr = NULL;
90
91 #define LSB     0
92 #define MSB16   1
93 #define MSB24   2
94 #define MSB32   3
95
96 static char *MOV="mov";
97 static char *MOVB="mov.b";
98 static char *MOVW="mov.w";
99 static char *MOVC="movc";
100 static char *MOVCB="movc.b";
101 static char *MOVCW="movc.w";
102
103 static char *R1L="r1l";
104 static char *R1="r1";
105
106 void bailOut (char *mesg) {
107   fprintf (stderr, "%s: bailing out\n", mesg);
108   exit (1);
109 }
110
111 /*-----------------------------------------------------------------*/
112 /* emitcode - writes the code into a file : for now it is simple    */
113 /*-----------------------------------------------------------------*/
114 static void emitcode (char *inst, char *fmt,...) {
115   va_list ap;
116   char lb[INITIAL_INLINEASM];
117   char *lbp = lb;
118
119   va_start (ap, fmt);
120
121   if (inst && *inst)
122     {
123       if (fmt && *fmt)
124         sprintf (lb, "%s\t", inst);
125       else
126         sprintf (lb, "%s", inst);
127       vsprintf (lb + (strlen (lb)), fmt, ap);
128     }
129   else
130     vsprintf (lb, fmt, ap);
131
132   while (isspace ((int)*lbp))
133     lbp++;
134
135   if (lbp && *lbp)
136     lineCurr = (lineCurr ?
137                 connectLine (lineCurr, newLineNode (lb)) :
138                 (lineHead = newLineNode (lb)));
139   lineCurr->isInline = _G.inLine;
140   lineCurr->isDebug = _G.debugLine;
141   va_end (ap);
142 }
143
144 char *getStackOffset(int stack) {
145   static char gsoBuf[1024];
146   sprintf (gsoBuf, "r7+(%d%+d%+d)", stack,
147            currFunc->stack, _G.nRegsSaved);
148   return gsoBuf;
149 }
150
151 /*-----------------------------------------------------------------*/
152 /* newAsmop - creates a new asmOp                                  */
153 /*-----------------------------------------------------------------*/
154 static asmop *
155 newAsmop (short type)
156 {
157   asmop *aop;
158
159   aop = Safe_calloc (1, sizeof (asmop));
160   aop->type = type;
161   return aop;
162 }
163
164 char *aopTypeName(asmop *aop) {
165   switch (aop->type)
166     {
167     case AOP_LIT: return "lit";
168     case AOP_REG: return "reg";
169     case AOP_DIR: return "dir";
170     case AOP_FAR: return "far";
171     case AOP_CODE: return "code";
172     case AOP_GPTR: return "gptr";
173     case AOP_STK: return "stack";
174     case AOP_IMMD: return "imm";
175     case AOP_BIT: return "bit";
176     }
177   return "unknown";
178 }
179
180 /*-----------------------------------------------------------------*/
181 /* aopForSym - for a true symbol                                   */
182 /*-----------------------------------------------------------------*/
183 static asmop *aopForSym(symbol *sym, 
184                         bool canUsePointer, bool canUseOffset) {
185   int size;
186   asmop *aop;
187
188   sym->aop = aop = newAsmop(0);
189   size=aop->size=getSize(sym->type);
190
191   // if the sym has registers
192   if (sym->nRegs && sym->regs[0]) {
193     aop->type=AOP_REG;
194     sprintf (aop->name[0], sym->regs[0]->name);
195     if (size > 2) {
196       sprintf (aop->name[1], sym->regs[1]->name);
197     }
198     return aop;
199   }
200
201   // if it is on stack
202   if (sym->onStack) {
203     if (!canUsePointer || !canUseOffset) {
204       aop->type=AOP_REG;
205       switch (size) 
206         {
207         case 1:
208           emitcode ("mov.b", "r0l,[%s]", getStackOffset(sym->stack));
209           sprintf (aop->name[0], "r0l");
210           return aop;
211         case 2:
212           emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
213           sprintf (aop->name[0], "r0");
214           return aop;
215         case 3:
216           emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
217           sprintf (aop->name[0], "r0");
218           emitcode ("mov.b", "r1l,[%s]", getStackOffset(sym->stack+2));
219           sprintf (aop->name[1], "r1l");
220           return aop;
221         case 4:
222           emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
223           sprintf (aop->name[0], "r0");
224           emitcode ("mov.w", "r1,[%s]", getStackOffset(sym->stack+2));
225           sprintf (aop->name[1], "r1");
226           return aop;
227         }
228     }
229     aop->type=AOP_STK;
230     sprintf (aop->name[0], "[%s]", getStackOffset(sym->stack));
231     if (size > 2) {
232       sprintf (aop->name[1], "[%s]", getStackOffset(sym->stack+2));
233     }
234     return aop;
235   }
236
237   // if it has a spillLoc
238   if (sym->usl.spillLoc) {
239     return aopForSym (sym->usl.spillLoc, canUsePointer, canUseOffset);
240   }
241
242   // if in bit space
243   if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
244     aop->type=AOP_BIT;
245     sprintf (aop->name[0], sym->rname);
246     return aop;
247   }
248
249   // if in direct space
250   if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
251     aop->type=AOP_DIR;
252     sprintf (aop->name[0], sym->rname);
253     if (size>2) {
254       sprintf (aop->name[1], "%s+2", sym->rname);
255     }
256     return aop;
257   }
258
259   // if in code space
260   if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
261     if (!canUsePointer) {
262       aop->type=AOP_REG;
263       switch (size) 
264         {
265         case 1:
266           emitcode (MOV, "r0,#%s", sym->rname);
267           emitcode (MOVC, "r0l,[r0+]");
268           sprintf (aop->name[0], "r0l");
269           return aop;
270         case 2:
271           emitcode (MOV, "r0,#%s", sym->rname);
272           emitcode (MOVC, "r0,[r0+]");
273           sprintf (aop->name[0], "r0");
274           return aop;
275         case 3:
276           emitcode (MOV, "r0,#%s", sym->rname);
277           emitcode (MOVC, "r0,[r0+]");
278           sprintf (aop->name[1], "r0");
279           emitcode (MOV, "r1l,[r0+]");
280           sprintf (aop->name[0], "r1l");
281           return aop;
282         case 4:
283           emitcode (MOV, "r0,#%s", sym->rname);
284           emitcode (MOVC, "r1,[r0+]");
285           emitcode (MOVC, "r0,[r0+]");
286           emitcode ("xch", "r0,r1");
287           sprintf (aop->name[0], "r0");
288           sprintf (aop->name[1], "r1");
289           return aop;
290         }
291       
292     } else {
293       aop->type=AOP_CODE;
294       emitcode ("mov", "r0,#%s ; aopForSym:code", sym->rname);
295       sprintf (aop->name[0], "[r0]");
296       if (size>2) {
297         sprintf (aop->name[1], "[r0+2]");
298       }
299     }
300     return aop;
301   }
302
303   // if in far space
304   if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
305     if (!canUsePointer) {
306       aop->type=AOP_REG;
307       switch (size) 
308         {
309         case 1:
310           emitcode (MOV, "r0,#%s", sym->rname);
311           emitcode (MOV, "r0l,[r0]");
312           sprintf (aop->name[0], "r0l");
313           return aop;
314         case 2:
315           emitcode (MOV, "r0,#%s", sym->rname);
316           emitcode (MOV, "r0,[r0]");
317           sprintf (aop->name[0], "r0");
318           return aop;
319         case 3:
320           emitcode (MOV, "r0,#%s", sym->rname);
321           emitcode (MOV, "r1l,[r0+2]");
322           sprintf (aop->name[1], "r1l");
323           emitcode (MOV, "r0,[r0]");
324           sprintf (aop->name[0], "r0");
325           return aop;
326         case 4:
327           emitcode (MOV, "r0,#%s", sym->rname);
328           emitcode (MOV, "r1,[r0+2]");
329           sprintf (aop->name[1], "r1");
330           emitcode (MOV, "r0,[r0]");
331           sprintf (aop->name[0], "r0");
332           return aop;
333         }
334     } else {
335       aop->type=AOP_FAR;
336       emitcode ("mov.w", "r0,#%s ; aopForSym:far", sym->rname);
337       sprintf (aop->name[0], "[r0]");
338       if (size>2) {
339         sprintf (aop->name[1], "[r0+2]");
340       }
341       return aop;
342     }
343   }
344   
345   bailOut("aopForSym");
346   return NULL;
347 }
348
349 /*-----------------------------------------------------------------*/
350 /* aopForVal - for a value                                         */
351 /*-----------------------------------------------------------------*/
352 static asmop *aopForVal(operand *op) {
353   asmop *aop;
354
355   if (IS_OP_LITERAL(op)) {
356     op->aop = aop = newAsmop (AOP_LIT);
357     switch ((aop->size=getSize(operandType(op))))
358       {
359       case 1:
360         sprintf (aop->name[0], "#0x%02x", 
361                  SPEC_CVAL(operandType(op)).v_int & 0xff);
362         sprintf (aop->name[1], "#0");
363         break;
364       case 2:
365         sprintf (aop->name[0], "#0x%04x", 
366                  SPEC_CVAL(operandType(op)).v_int & 0xffff);
367         sprintf (aop->name[1], "#0");
368         break;
369       case 3:
370         // must be a generic pointer, can only be zero
371         // ?? if (v!=0) fprintf (stderr, "invalid val op for gptr\n"); exit(1);
372         sprintf (aop->name[0], "#0x%04x", 
373                  SPEC_CVAL(operandType(op)).v_uint & 0xffff);
374         sprintf (aop->name[1], "#0");
375         break;
376       case 4:
377         sprintf (aop->name[0], "#0x%04lx",
378                  SPEC_CVAL(operandType(op)).v_ulong & 0xffff);
379         sprintf (aop->name[1], "#0x%04lx", 
380                  SPEC_CVAL(operandType(op)).v_ulong >> 16);
381         break;
382       default:
383         bailOut("aopForVal");
384       }
385     return aop;
386   }
387
388   // must be immediate
389   if (IS_SYMOP(op)) {
390     op->aop = aop = newAsmop (AOP_IMMD);
391     switch ((aop->size=getSize(OP_SYMBOL(op)->type))) 
392       {
393       case 1:
394       case 2:
395         sprintf (aop->name[0], "#%s", OP_SYMBOL(op)->rname);
396         return aop;
397       case 3: // generic pointer
398         sprintf (aop->name[0], "#0x%02x", DCL_TYPE(operandType(op)));
399         sprintf (aop->name[1], "#%s", OP_SYMBOL(op)->rname);
400         return aop;
401       }
402   }
403
404   bailOut ("aopForVal: unknown type");
405   return NULL;
406 }
407
408 static int aopOp(operand *op, 
409                   bool canUsePointer, bool canUseOffset) {
410
411   if (IS_SYMOP(op)) {
412     op->aop=aopForSym (OP_SYMBOL(op), canUsePointer, canUseOffset);
413     return AOP_SIZE(op);
414   }
415   if (IS_VALOP(op)) {
416     op->aop=aopForVal (op);
417     return AOP_SIZE(op);
418   }
419
420   bailOut("aopOp: unexpected operand");
421   return 0;
422 }
423
424 bool aopEqual(asmop *aop1, asmop *aop2, int offset) {
425   if (strcmp(aop1->name[offset], aop2->name[offset])) {
426     return FALSE;
427   }
428   return TRUE;
429 }
430
431 bool aopIsDir(operand *op) {
432   return AOP_TYPE(op)==AOP_DIR;
433 }
434
435 bool aopIsBit(operand *op) {
436   return AOP_TYPE(op)==AOP_BIT;
437 }
438
439 bool aopIsPtr(operand *op) {
440   if (AOP_TYPE(op)==AOP_STK ||
441       AOP_TYPE(op)==AOP_CODE ||
442       AOP_TYPE(op)==AOP_FAR) {
443     return TRUE;
444   } else {
445     return FALSE;
446   }
447 }
448       
449 char *opRegName(operand *op, int offset, char *opName, bool decorate) {
450
451   if (IS_SYMOP(op)) {
452     if (OP_SYMBOL(op)->onStack) {
453       sprintf (opName, "[%s]", getStackOffset(OP_SYMBOL(op)->stack));
454       return opName;
455     }
456     if (IS_TRUE_SYMOP(op))
457       return OP_SYMBOL(op)->rname;
458     else if (OP_SYMBOL(op)->regs[offset])
459       return OP_SYMBOL(op)->regs[offset]->name;
460     else
461       bailOut("opRegName: unknown regs");
462   }
463
464   if (IS_VALOP(op)) {
465     switch (SPEC_NOUN(OP_VALUE(op)->type)) {
466     case V_SBIT:
467     case V_BIT:
468       if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
469           SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
470         bailOut("opRegName: invalid bit value");
471       }
472       // fall through
473     case V_CHAR:
474       sprintf (opName, "#%s0x%02x", decorate?"(char)":"", 
475                SPEC_CVAL(OP_VALUE(op)->type).v_int);
476       break;
477     case V_INT:
478       if (SPEC_LONG(OP_VALUE(op)->type)) {
479         sprintf (opName, "#%s0x%02lx", decorate?"(long)":"",
480                  SPEC_CVAL(OP_VALUE(op)->type).v_long);
481       } else {
482         sprintf (opName, "#%s0x%02x", decorate?"(int)":"",
483                  SPEC_CVAL(OP_VALUE(op)->type).v_int);
484       }
485       break;
486     case V_FLOAT:
487       sprintf (opName, "#%s%f", decorate?"(float)":"",
488                SPEC_CVAL(OP_VALUE(op)->type).v_float);
489       break;
490     default: 
491       bailOut("opRegName: unexpected noun");
492     }
493     return opName;
494   }
495   bailOut("opRegName: unexpected operand type");
496   return NULL;
497 }
498
499 char * printOp (operand *op) {
500   static char line[132];
501   sym_link *optype=operandType(op);
502   bool isPtr = IS_PTR(optype);
503
504   if (IS_SYMOP(op)) {
505     symbol *sym=OP_SYMBOL(op);
506     if (!sym->regs[0] && SYM_SPIL_LOC(sym)) {
507       sym=SYM_SPIL_LOC(sym);
508     }
509     if (isPtr) {
510       sprintf (line, "[");
511       if (DCL_TYPE(optype)==FPOINTER)
512         strcat (line, "far * ");
513       else if (DCL_TYPE(optype)==CPOINTER)
514         strcat (line, "code * ");
515       else if (DCL_TYPE(optype)==GPOINTER)
516         strcat (line, "gen * ");
517       else if (DCL_TYPE(optype)==POINTER)
518         strcat (line, "near * ");
519       else
520         strcat (line, "unknown * ");
521       strcat (line, "(");
522       strcat (line, nounName(sym->etype));
523       strcat (line, ")");
524       strcat (line, sym->name);
525       strcat (line, "]:");
526     } else {
527       sprintf (line, "(%s)%s:", nounName(sym->etype), sym->name);
528     }
529     if (sym->regs[0]) {
530       strcat (line, sym->regs[0]->name);
531       if (sym->regs[1]) {
532         strcat (line, ",");
533         strcat (line, sym->regs[1]->name);
534       }
535       return line;
536     }
537     if (sym->onStack) {
538       sprintf (line+strlen(line), "stack%+d", sym->stack);
539       return line;
540     }
541     if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
542       strcat (line, "code");
543       return line;
544     }
545     if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
546       strcat (line, "far");
547       return line;
548     }
549     if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
550       strcat (line, "bit");
551       return line;
552     }
553     if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
554       strcat (line, "dir");
555       return line;
556     }
557     strcat (line, "unknown");
558     return line;
559   } else if (IS_VALOP(op)) {
560     opRegName(op, 0, line, 1);
561   } else if (IS_TYPOP(op)) {
562     sprintf (line, "(");
563     if (isPtr) {
564       if (DCL_TYPE(optype)==FPOINTER)
565         strcat (line, "far * ");
566       else if (DCL_TYPE(optype)==CPOINTER)
567         strcat (line, "code * ");
568       else if (DCL_TYPE(optype)==GPOINTER)
569         strcat (line, "gen * ");
570       else if (DCL_TYPE(optype)==POINTER)
571         strcat (line, "near * ");
572       else
573         strcat (line, "unknown * ");
574     }
575     // forget about static, volatile, ... for now
576     if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
577     if (SPEC_LONG(operandType(op))) strcat (line, "long ");
578     strcat (line, nounName(operandType(op)));
579     strcat (line, ")");
580   } else {
581     bailOut("printOp: unexpected operand type");
582   }
583   return line;
584 }
585
586 void printIc (char *op, iCode * ic, bool result, bool left, bool right) {
587   char line[132];
588
589   sprintf (line, "%s(%d)", op, ic->lineno);
590   if (result) {
591     strcat (line, " result=");
592     strcat (line, printOp (IC_RESULT(ic)));
593   }
594   if (left) {
595     strcat (line, " left=");
596     strcat (line, printOp (IC_LEFT(ic)));
597   }
598   if (right) {
599     strcat (line, " right=");
600     strcat (line, printOp (IC_RIGHT(ic)));
601   }
602   emitcode (";", line);
603 }
604
605 /*-----------------------------------------------------------------*/
606 /* toBoolean - return carry for operand!=0                           */
607 /*-----------------------------------------------------------------*/
608 static char *toBoolean (operand * op) {
609   symbol *tlbl=newiTempLabel(NULL);
610
611   switch (AOP_SIZE(op)) 
612     {
613     case 1:
614     case 2:
615       emitcode ("cjne", "%s,#1,%05d$; %s", AOP_NAME(op), tlbl->key+100,
616                 "This needs a second thought");
617       
618       emitcode ("", "%05d$:", tlbl->key+100);
619       return "c";
620     }
621
622   bailOut("toBoolean: unknown size");
623   return NULL;
624 }
625
626 /*-----------------------------------------------------------------*/
627 /* regsInCommon - two operands have some registers in common       */
628 /*-----------------------------------------------------------------*/
629 static bool regsInCommon (operand * op1, operand * op2) {
630   symbol *sym1, *sym2;
631   int i;
632
633   /* if they have registers in common */
634   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
635     return FALSE;
636
637   sym1 = OP_SYMBOL (op1);
638   sym2 = OP_SYMBOL (op2);
639
640   if (sym1->nRegs == 0 || sym2->nRegs == 0)
641     return FALSE;
642
643   for (i = 0; i < sym1->nRegs; i++)
644     {
645       int j;
646       if (!sym1->regs[i])
647         continue;
648
649       for (j = 0; j < sym2->nRegs; j++)
650         {
651           if (!sym2->regs[j])
652             continue;
653
654           if (sym2->regs[j] == sym1->regs[i])
655             return TRUE;
656         }
657     }
658
659   return FALSE;
660 }
661
662 /*-----------------------------------------------------------------*/
663 /* resultRemat - result  is rematerializable                       */
664 /*-----------------------------------------------------------------*/
665 static int resultRemat (iCode * ic) {
666   if (SKIP_IC (ic) || ic->op == IFX)
667     return 0;
668   
669   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
670     {
671       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
672       if (sym->remat && !POINTER_SET (ic))
673         return 1;
674     }
675   
676   return 0;
677 }
678
679 /*-----------------------------------------------------------------*/
680 /* genNot - generate code for ! operation                          */
681 /*-----------------------------------------------------------------*/
682 static void genNot (iCode * ic) {
683   printIc("genNot:", ic, 1,1,0);
684 }
685
686 /*-----------------------------------------------------------------*/
687 /* genCpl - generate code for complement                           */
688 /*-----------------------------------------------------------------*/
689 static void genCpl (iCode * ic) {
690   printIc("genCpl", ic, 1,1,0);
691 }
692
693 /*-----------------------------------------------------------------*/
694 /* genUminus - unary minus code generation                         */
695 /*-----------------------------------------------------------------*/
696 static void genUminus (iCode * ic) {
697   printIc("genUminus", ic, 1,1,0);
698 }
699
700 /*-----------------------------------------------------------------*/
701 /* genIpush - generate code for pushing                            */
702 /*-----------------------------------------------------------------*/
703 static void genIpush (iCode * ic) {
704   operand *left=IC_LEFT(ic);
705
706   printIc ("genIpush", ic, 0,1,0);
707   aopOp(left,FALSE,FALSE);
708
709
710   if (AOP_TYPE(left)==AOP_LIT) {
711     switch (AOP_SIZE(left)) 
712       {
713       case 1:
714         emitcode ("mov", "r1l,%s", AOP_NAME(left)[0]);
715         emitcode ("push", "r1l");
716         _G.parmsPushed++;
717         return;
718       case 2:
719         emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
720         emitcode ("push", "r1");
721         _G.parmsPushed++;
722         return;
723       case 3:
724         emitcode ("mov", "r1l,%s", AOP_NAME(left)[1]);
725         emitcode ("push", "r1l");
726         emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
727         emitcode ("push", "r1");
728         _G.parmsPushed += 2;
729         return;
730       case 4:
731         emitcode ("mov", "r1,%s", AOP_NAME(left)[1]);
732         emitcode ("push", "r1");
733         emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
734         emitcode ("push", "r1");
735         _G.parmsPushed += 2;
736         return;
737       }
738   } else {
739     if (AOP_SIZE(left)>2) {
740       emitcode ("push", "%s", AOP_NAME(left)[1]);
741       _G.parmsPushed++;
742     }
743     emitcode ("push", "%s", AOP_NAME(left)[0]);
744     _G.parmsPushed++;
745   }
746 }
747
748 /*-----------------------------------------------------------------*/
749 /* genIpop - recover the registers: can happen only for spilling   */
750 /*-----------------------------------------------------------------*/
751 static void genIpop (iCode * ic) {
752   printIc ("genIpop", ic, 0,1,0);
753 }
754
755 /*-----------------------------------------------------------------*/
756 /* genCall - generates a call statement                            */
757 /*-----------------------------------------------------------------*/
758 static void genCall (iCode * ic) {
759   operand *result=IC_RESULT(ic);
760
761   emitcode (";", "genCall(%d) %s result=%s", ic->lineno,
762             OP_SYMBOL(IC_LEFT(ic))->name,
763             printOp (IC_RESULT(ic)));
764   emitcode ("call", "%s", OP_SYMBOL(IC_LEFT(ic))->rname);
765
766   /* readjust the stack if we have pushed some parms */
767   if (_G.parmsPushed) {
768     emitcode ("add", "r7,#0x%02x", _G.parmsPushed*2);
769     _G.parmsPushed=0;
770   }
771
772   /* if we need to assign a result value */
773   if (IS_ITEMP (IC_RESULT(ic)) &&
774       OP_SYMBOL (IC_RESULT (ic))->nRegs) {
775     aopOp(result,FALSE,FALSE);
776     switch (AOP_SIZE(result))
777       {
778       case 1:
779         emitcode ("mov", "%s,r0l", AOP_NAME(result)[0]);
780         return;
781       case 2:
782         emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
783         return;
784       case 3:
785         // generic pointer
786         emitcode ("mov", "%s,r1l", AOP_NAME(result)[1]);
787         emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
788         return;
789       case 4:
790         emitcode ("mov", "%s,r1", AOP_NAME(result)[1]);
791         emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
792         return;
793       }
794     bailOut("genCall");
795   }
796 }
797
798 /*-----------------------------------------------------------------*/
799 /* genPcall - generates a call by pointer statement                */
800 /*-----------------------------------------------------------------*/
801 static void
802 genPcall (iCode * ic)
803 {
804   emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
805 }
806
807 /*-----------------------------------------------------------------*/
808 /* genFunction - generated code for function entry                 */
809 /*-----------------------------------------------------------------*/
810 static void genFunction (iCode * ic) {
811   symbol *sym=OP_SYMBOL(IC_LEFT(ic));
812   sym_link *type=sym->type;
813
814   emitcode (";", "genFunction %s", sym->rname);
815
816   /* print the allocation information */
817   printAllocInfo (currFunc, codeOutFile);
818
819   emitcode ("", "%s:", sym->rname);
820
821   if (IFFUNC_ISNAKED(type))
822   {
823       emitcode(";", "naked function: no prologue.");
824       return;
825   }
826
827   /* adjust the stack for locals used in this function */
828   if (sym->stack) {
829     emitcode ("sub", "r7,#%d\t; create stack space for locals", sym->stack);
830   }
831 }
832
833 /*-----------------------------------------------------------------*/
834 /* genEndFunction - generates epilogue for functions               */
835 /*-----------------------------------------------------------------*/
836 static void
837 genEndFunction (iCode * ic)
838 {
839   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
840
841   printIc ("genEndFunction", ic, 0,0,0);
842
843   if (IFFUNC_ISNAKED(sym->type)) {
844       emitcode(";", "naked function: no epilogue.");
845       return;
846   }
847
848   /* readjust the stock for locals used in this function */
849   if (sym->stack) {
850     emitcode ("add", "r7,#%d\t; release stack space for locals", sym->stack);
851   }
852
853   if (IFFUNC_ISISR(sym->type)) {
854     emitcode ("reti", "");
855   } else {
856     emitcode ("ret", "");
857   }
858 }
859
860 /*-----------------------------------------------------------------*/
861 /* genRet - generate code for return statement                     */
862 /*-----------------------------------------------------------------*/
863 static void genRet (iCode * ic) {
864
865   if (!IC_LEFT(ic)) {
866     printIc ("genRet", ic, 0, 0, 0);
867   } else {
868     printIc ("genRet", ic, 0, 1, 0);
869     aopOp(IC_LEFT(ic), TRUE, TRUE);
870     switch (AOP_SIZE(IC_LEFT(ic)))
871       {
872       case 4:
873         emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
874         emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
875         break;
876       case 3:
877         emitcode ("mov", "r1l,%s", AOP_NAME(IC_LEFT(ic))[1]);
878         // fall through
879       case 2:
880         emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
881         break;
882       case 1:
883         emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
884         break;
885       default:
886         bailOut("genRet");
887       }
888   }
889
890   emitcode ("jmp", "%05d$", returnLabel->key+100);
891 }
892
893 /*-----------------------------------------------------------------*/
894 /* genLabel - generates a label                                    */
895 /*-----------------------------------------------------------------*/
896 static void genLabel (iCode * ic) {
897   /* special case never generate */
898   if (IC_LABEL (ic) == entryLabel)
899     return;
900
901   emitcode (";", "genLabel(%d) %s", ic->lineno, IC_LABEL(ic)->name);
902   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
903 }
904
905 /*-----------------------------------------------------------------*/
906 /* genGoto - generates a jmp                                      */
907 /*-----------------------------------------------------------------*/
908 static void genGoto (iCode * ic) {
909   emitcode (";", "genGoto(%d) %s", ic->lineno, IC_LABEL(ic)->name);
910   emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
911 }
912
913 /*-----------------------------------------------------------------*/
914 /* genPlus - generates code for addition                           */
915 /*-----------------------------------------------------------------*/
916 static void genPlus (iCode * ic) {
917   operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
918   int size;
919   char *instr;
920
921   printIc ("genPlus", ic, 1,1,1);
922
923   size=aopOp(result, TRUE, TRUE);
924
925   /* if left is a literal, then exchange them */
926   if (IS_LITERAL(operandType(left))) {
927     operand *tmp = right;
928     right = left;
929     left = tmp;
930   }
931     
932   if (aopIsBit(result)) {
933     if (IS_LITERAL(operandType(right))) {
934       if (operandLitValue(right)) {
935         emitcode ("setb", AOP_NAME(result)[0]);
936         return;
937       }
938       aopOp(left, TRUE, TRUE);
939       emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
940       return;
941     }
942     bailOut("genPlus: unfinished genPlus bit");
943   }
944   
945   aopOp(left, !aopIsPtr(result), !aopIsDir(result));
946   aopOp(right, !aopIsPtr(result), !aopIsDir(result));
947
948   // special case for * = * + char, needs a closer look
949   // heck, this shouldn't have come here but bug-223113 does
950   if (size==3 && AOP_SIZE(right)==1) {
951     emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
952     emitcode ("mov", "r1h,#0"); // ptr arith unsigned????????????
953     emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
954     emitcode ("add.w", "%s,r1", AOP_NAME(result)[0]);
955     emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
956     return;
957   }
958
959   // special case for (whatever)* = (whatever)** + char, needs a closer look
960   // heck, this shouldn't have come here but bug-441448 does
961   if (size==2 && AOP_SIZE(right)==1) {
962     emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
963     emitcode ("mov", "r1h,#0"); // ptr arith unsigned????????????
964     emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
965     emitcode ("add.w", "%s,r1", AOP_NAME(result)[0]);
966     return;
967   }
968
969   if (size>1) {
970     instr="add.w";
971   } else {
972     instr="add.b";
973   }
974   if (!aopEqual(result->aop, left->aop, 0)) {
975     emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
976   }
977   emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
978   if (size>2) {
979     if (!aopEqual(result->aop, left->aop, 1)) {
980       emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
981     }
982     if (size==3) {
983       // generic pointer
984     } else {
985       emitcode ("addc.w", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
986     }
987   }
988   return;
989 }
990
991 /*-----------------------------------------------------------------*/
992 /* genMinus - generates code for subtraction                       */
993 /*-----------------------------------------------------------------*/
994 static void genMinus (iCode * ic) {
995   printIc ("genMinus", ic, 1,1,1);
996 }
997
998
999 /*-----------------------------------------------------------------*/
1000 /* genMult - generates code for multiplication                     */
1001 /*-----------------------------------------------------------------*/
1002 static void genMult (iCode * ic) {
1003   printIc ("genMult", ic, 1,1,1);
1004 }
1005
1006 /*-----------------------------------------------------------------*/
1007 /* genDiv - generates code for division                            */
1008 /*-----------------------------------------------------------------*/
1009 static void genDiv (iCode * ic) {
1010   printIc ("genDiv", ic, 1,1,1);
1011 }
1012
1013 /*-----------------------------------------------------------------*/
1014 /* genMod - generates code for division                            */
1015 /*-----------------------------------------------------------------*/
1016 static void genMod (iCode * ic) {
1017   printIc ("genMod", ic, 1,1,1);
1018 }
1019
1020  /*-----------------------------------------------------------------*/
1021 /* genCmpGt :- greater than comparison                             */
1022 /*-----------------------------------------------------------------*/
1023 static void genCmpGt (iCode * ic) {
1024   printIc ("genCmpGt", ic, 1,1,1);
1025 }
1026 /*-----------------------------------------------------------------*/
1027 /* genCmpLt - less than comparisons                                */
1028 /*-----------------------------------------------------------------*/
1029 static void genCmpLt (iCode * ic) {
1030   printIc ("genCmpLt", ic, 1,1,1);
1031 }
1032 /*-----------------------------------------------------------------*/
1033 /* genCmpEq - generates code for equal to                          */
1034 /*-----------------------------------------------------------------*/
1035 static void genCmpEq (iCode * ic) {
1036   printIc ("genCmpEq", ic, 1,1,1);
1037 }
1038
1039 /*-----------------------------------------------------------------*/
1040 /* ifxForOp - returns the icode containing the ifx for operand     */
1041 /*-----------------------------------------------------------------*/
1042 static iCode *ifxForOp (operand * op, iCode * ic) {
1043   /* if true symbol then needs to be assigned */
1044   if (IS_TRUE_SYMOP (op))
1045     return NULL;
1046   
1047   /* if this has register type condition and
1048      the next instruction is ifx with the same operand
1049      and live to of the operand is upto the ifx only then */
1050   if (ic->next &&
1051       ic->next->op == IFX &&
1052       IC_COND (ic->next)->key == op->key &&
1053       OP_SYMBOL (op)->liveTo <= ic->next->seq)
1054     return ic->next;
1055   
1056   return NULL;
1057 }
1058
1059 /*-----------------------------------------------------------------*/
1060 /* hasInc - operand is incremented before any other use            */
1061 /*-----------------------------------------------------------------*/
1062 static iCode *hasInc (operand *op, iCode *ic, int osize) {
1063   sym_link *type = operandType(op);
1064   sym_link *retype = getSpec (type);
1065   iCode *lic = ic->next;
1066   int isize ;
1067   
1068   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
1069   if (!IS_SYMOP(op)) return NULL;
1070
1071   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
1072   if (IS_AGGREGATE(type->next)) return NULL;
1073   if (osize != (isize = getSize(type->next))) return NULL;
1074
1075   while (lic) {
1076     /* if operand of the form op = op + <sizeof *op> */
1077     if (lic->op == '+') {
1078       if (isOperandEqual(IC_LEFT(lic),op) &&
1079           //isOperandEqual(IC_RESULT(lic),op) && 
1080           isOperandLiteral(IC_RIGHT(lic)) &&
1081           operandLitValue(IC_RIGHT(lic)) == isize) {
1082         emitcode (";", "Found hasInc");
1083         return lic;
1084       }
1085     }
1086     /* if the operand used or deffed */
1087     if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
1088       return NULL;
1089     }
1090     /* if GOTO or IFX */
1091     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
1092     lic = lic->next;
1093   }
1094   return NULL;
1095 }
1096
1097 /*-----------------------------------------------------------------*/
1098 /* genAndOp - for && operation                                     */
1099 /*-----------------------------------------------------------------*/
1100 static void genAndOp (iCode * ic) {
1101   printIc ("genAndOp(&&)", ic, 1,1,1);
1102 }
1103
1104 /*-----------------------------------------------------------------*/
1105 /* genOrOp - for || operation                                      */
1106 /*-----------------------------------------------------------------*/
1107 static void genOrOp (iCode * ic) {
1108   printIc ("genOrOp(||)", ic, 1,1,1);
1109 }
1110
1111 /*-----------------------------------------------------------------*/
1112 /* genAnd  - code for and                                            */
1113 /*-----------------------------------------------------------------*/
1114 static void genAnd (iCode * ic, iCode * ifx) {
1115   printIc ("genAnd", ic, 1,1,1);
1116 }
1117
1118 /*-----------------------------------------------------------------*/
1119 /* genOr  - code for or                                            */
1120 /*-----------------------------------------------------------------*/
1121 static void genOr (iCode * ic, iCode * ifx) {
1122   operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1123   int size;
1124   char *instr;
1125
1126   printIc ("genOr", ic, 1,1,1);
1127
1128   size=aopOp(result, TRUE, TRUE);
1129
1130   /* if left is a literal, then exchange them */
1131   if (IS_LITERAL(operandType(left))) {
1132     operand *tmp = right;
1133     right = left;
1134     left = tmp;
1135   }
1136     
1137   if (aopIsBit(result)) {
1138     if (IS_LITERAL(operandType(right))) {
1139       if (operandLitValue(right)) {
1140         emitcode ("setb", AOP_NAME(result)[0]);
1141         return;
1142       }
1143       aopOp(left, TRUE, TRUE);
1144       emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1145       return;
1146     }
1147   }
1148   
1149   aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1150   aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1151
1152   if (size>1) {
1153     instr="or.w";
1154   } else {
1155     instr="or.b";
1156   }
1157   if (!aopEqual(result->aop, left->aop, 0)) {
1158     emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1159   }
1160   emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1161   if (size>2) {
1162     if (!aopEqual(result->aop, left->aop, 1)) {
1163       emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1164     }
1165     emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1166   }
1167   return;
1168 }
1169
1170 /*-----------------------------------------------------------------*/
1171 /* genXor - code for xclusive or                                   */
1172 /*-----------------------------------------------------------------*/
1173 static void genXor (iCode * ic, iCode * ifx) {
1174   printIc ("genXor", ic, 1,1,1);
1175 }
1176
1177 /*-----------------------------------------------------------------*/
1178 /* genInline - write the inline code out                           */
1179 /*-----------------------------------------------------------------*/
1180 static void genInline (iCode * ic) {
1181
1182   printIc ("genInline", ic, 0,0,0);
1183   
1184   emitcode ("", IC_INLINE(ic));
1185 }
1186
1187 /*-----------------------------------------------------------------*/
1188 /* genRRC - rotate right with carry                                */
1189 /*-----------------------------------------------------------------*/
1190 static void genRRC (iCode * ic) {
1191   printIc ("genRRC", ic, 1,1,0);
1192 }
1193
1194 /*-----------------------------------------------------------------*/
1195 /* genRLC - generate code for rotate left with carry               */
1196 /*-----------------------------------------------------------------*/
1197 static void genRLC (iCode * ic) {
1198   printIc ("genRLC", ic, 1,1,0);
1199 }
1200
1201 /*-----------------------------------------------------------------*/
1202 /* genGetHbit - generates code get highest order bit               */
1203 /*-----------------------------------------------------------------*/
1204 static void genGetHbit (iCode * ic) {
1205   printIc ("genGetHbit", ic, 1,1,0);
1206 }
1207
1208 /*-----------------------------------------------------------------*/
1209 /* genLeftShift - generates code for left shifting                 */
1210 /*-----------------------------------------------------------------*/
1211 static void genLeftShift (iCode * ic) {
1212   printIc ("genLeftShift", ic, 1,1,1);
1213 }
1214
1215 /*-----------------------------------------------------------------*/
1216 /* genRightShift - generate code for right shifting                */
1217 /*-----------------------------------------------------------------*/
1218 static void genRightShift (iCode * ic) {
1219   printIc ("genRightShift", ic, 1,1,1);
1220 }
1221
1222 /*-----------------------------------------------------------------*/
1223 /* genPointerGet - generate code for pointer get                   */
1224 /*-----------------------------------------------------------------*/
1225 static void genPointerGet (iCode * ic, iCode *pi) {
1226   char *instr, *scratchReg;
1227   operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
1228   bool codePointer=IS_CODEPTR(operandType(left));
1229   int size;
1230
1231   if (pi) {
1232     printIc ("genPointerGet pi", ic, 1,1,0);
1233   } else {
1234     printIc ("genPointerGet", ic, 1,1,0);
1235   }
1236
1237   if (!IS_PTR(operandType(left))) {
1238     bailOut ("genPointerGet: pointer required");
1239   }
1240
1241   aopOp(left,FALSE,FALSE);
1242   size=aopOp(result,TRUE,aopIsDir(left));
1243
1244   if (IS_GENPTR(operandType(left))) {
1245     symbol *tlbl1=newiTempLabel(NULL);
1246     symbol *tlbl2=newiTempLabel(NULL);
1247     emitcode ("cmp", "%s,#0x%02x", AOP_NAME(left)[1], CPOINTER);
1248     emitcode ("beq", "%05d$", tlbl1->key+100);
1249     // far/near pointer
1250     if (pi) {
1251       emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1252       pi->generated=1;
1253     } else {
1254       emitcode ("mov", "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1255     }
1256     if (size>2) {
1257       if (pi) {
1258         emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1259       } else {
1260         emitcode ("mov", "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1261       }
1262     }
1263     emitcode ("br", "%05d$", tlbl2->key+100);
1264     emitcode ("", "%05d$:", tlbl1->key+100);
1265     // code pointer
1266     if (pi) {
1267       emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1268       pi->generated=1;
1269     } else {
1270       emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
1271       emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[0]);
1272     }
1273     if (size>2) {
1274       if (pi) {
1275         emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1276       } else {
1277         emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[1]);
1278       }
1279     }
1280     emitcode ("", "%05d$:", tlbl2->key+100);
1281     return;
1282   }
1283
1284   switch (AOP_TYPE(left)) 
1285     {
1286     case AOP_LIT:
1287       emitcode("mov","r1,%s", AOP_NAME(left)[0]);
1288       sprintf (AOP_NAME(left)[0], "r1");
1289       // fall through
1290     case AOP_REG:
1291       if (size>1) {
1292         if (codePointer) {
1293           instr=MOVCW;
1294         } else {
1295           instr=MOVW;
1296         }
1297         scratchReg=R1;
1298       } else {
1299         if (codePointer) {
1300           instr=MOVCB;
1301         } else {
1302           instr=MOVB;
1303         }
1304         scratchReg=R1L;
1305       }
1306       if (AOP_TYPE(result)==AOP_STK) {
1307         emitcode (MOV, "%s,[%s]", scratchReg, AOP_NAME(left)[0]);
1308         emitcode (MOV, "%s,%s", AOP_NAME(result)[0], scratchReg);
1309       } else {
1310         if (pi) {
1311           emitcode (instr, "%s,[%s+]", AOP_NAME(result)[0], 
1312                     AOP_NAME(left)[0]);
1313           pi->generated=1;
1314         } else {
1315           if (codePointer) {
1316             emitcode (MOV, "r1,%s", AOP_NAME(left)[0]);
1317             emitcode (instr, "%s,[r1+]", AOP_NAME(result)[0]);
1318           } else {
1319             emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], 
1320                       AOP_NAME(left)[0]);
1321           }
1322         }
1323       }
1324       if (size > 2) {
1325         if (size==3) {
1326           if (codePointer) {
1327             instr=MOVCB;
1328           } else {
1329             instr=MOVB;
1330           }
1331           scratchReg=R1L;
1332         }
1333         if (AOP_TYPE(result)==AOP_STK) {
1334           emitcode (MOV, "%s,[%s+2]", scratchReg, AOP_NAME(left)[0]);
1335           emitcode (MOV, "%s,%s", AOP_NAME(result)[1], scratchReg);
1336         } else {
1337           if (pi) {
1338             emitcode (instr, "%s,[%s+]", AOP_NAME(result)[1], 
1339                       AOP_NAME(left)[0]);
1340           } else {
1341             if (codePointer) {
1342               emitcode (instr, "%s,[r1]", AOP_NAME(result)[1]);
1343             } else {
1344               emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1], 
1345                         AOP_NAME(left)[0]);
1346             }
1347           }
1348         }
1349       }
1350       return;
1351     }
1352   bailOut ("genPointerGet");
1353 }
1354
1355 /*-----------------------------------------------------------------*/
1356 /* genPointerSet - stores the value into a pointer location        */
1357 /*-----------------------------------------------------------------*/
1358 static void genPointerSet (iCode * ic, iCode *pi) {
1359   char *instr;
1360   operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1361   int size;
1362
1363   printIc ("genPointerSet", ic, 1,0,1);
1364
1365   if (!IS_PTR(operandType(result))) {
1366     bailOut ("genPointerSet: pointer required");
1367   }
1368
1369   aopOp(result,FALSE,FALSE);
1370   size=aopOp(right,FALSE, FALSE);
1371
1372   if (IS_GENPTR(operandType(result))) {
1373     emitcode (";", "INLINE\t_gptrset ; [%s %s] = %s %s", 
1374               AOP_NAME(result)[0], AOP_NAME(result)[1],
1375               AOP_NAME(right)[0], AOP_NAME(right)[1]);
1376     return;
1377   }
1378
1379   switch (AOP_TYPE(right)) 
1380     {
1381     case AOP_LIT:
1382     case AOP_REG:
1383       if (size>1) {
1384         instr=MOVW;
1385       } else {
1386         instr=MOVB;
1387       }
1388       if (pi) {
1389         emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1390         pi->generated=1;
1391       } else {
1392         emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1393       }
1394       if (size > 2) {
1395         if (size==3) {
1396           instr=MOVB;
1397         }
1398         if (pi) {
1399           emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], 
1400                     AOP_NAME(right)[1]);
1401         } else {
1402           emitcode (instr, "[%s+2],%s", AOP_NAME(result)[0], 
1403                     AOP_NAME(right)[1]);
1404         }
1405       }
1406       return;
1407     }
1408   bailOut ("genPointerSet");
1409 }
1410
1411 /*-----------------------------------------------------------------*/
1412 /* genIfx - generate code for Ifx statement                        */
1413 /*-----------------------------------------------------------------*/
1414 static void genIfx (iCode * ic, iCode * popIc) {
1415   int size;
1416   char *instr;
1417   bool trueOrFalse;
1418   symbol *jlbl, *tlbl=newiTempLabel(NULL);
1419   operand *cond=IC_COND(ic);
1420
1421   emitcode (";", "genIfx(%d) cond=%s trueLabel:%s falseLabel:%s", 
1422             ic->lineno, printOp(cond),
1423             IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1424             IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1425
1426   size=aopOp(cond,TRUE,TRUE);
1427
1428   if (IC_TRUE(ic)) {
1429     trueOrFalse=TRUE;
1430     jlbl=IC_TRUE(ic);
1431   } else {
1432     trueOrFalse=FALSE;
1433     jlbl=IC_FALSE(ic);
1434   }
1435
1436   switch (AOP_TYPE(cond) )
1437     {
1438     case AOP_BIT:
1439       emitcode (trueOrFalse ? "jnb" : "jb", "%s,%05d$", 
1440                 AOP_NAME(cond)[0], tlbl->key+100);
1441       emitcode ("jmp", "%05d$", jlbl->key+100);
1442       emitcode ("", "%05d$:", tlbl->key+100);
1443       return;
1444     case AOP_REG:
1445     case AOP_DIR:
1446     case AOP_FAR:
1447     case AOP_STK:
1448       if (size>1) {
1449         instr="cmp.w";
1450       } else {
1451         instr="cmp.b";
1452       }
1453       emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1454       emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1455       if (size > 2) {
1456         if (size==3) {
1457           // generic pointer, forget the generic part
1458         } else {
1459           emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1460           emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1461         }
1462       }
1463       emitcode ("jmp", "%05d$", jlbl->key+100);
1464       emitcode ("", "%05d$:", tlbl->key+100);
1465       return;
1466     }
1467   bailOut ("genIfx");
1468 }
1469
1470 /*-----------------------------------------------------------------*/
1471 /* genAddrOf - generates code for address of                       */
1472 /*-----------------------------------------------------------------*/
1473 static void genAddrOf (iCode * ic) {
1474   int size;
1475   operand *left=IC_LEFT(ic);
1476
1477   printIc ("genAddrOf", ic, 1,1,0);
1478
1479   size=aopOp (IC_RESULT(ic), FALSE, TRUE);
1480
1481   if (isOperandOnStack(left)) {
1482     emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1483               getStackOffset(OP_SYMBOL(left)->stack));
1484     if (size > 2) {
1485       // this must be a generic pointer
1486       emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER);
1487     }
1488     return;
1489   }
1490
1491   if (isOperandInDirSpace(left) ||
1492       isOperandInFarSpace(left) ||
1493       isOperandInCodeSpace(left)) {
1494     emitcode ("mov.w", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1495               OP_SYMBOL(left)->rname);
1496     if (size > 2) {
1497       // this must be a generic pointer
1498       int space=0; // dir space
1499       if (isOperandInFarSpace(left)) {
1500         space=1;
1501       } else if (isOperandInCodeSpace(left)) {
1502         space=2;
1503       }
1504       emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1505     }
1506     return;
1507   }
1508
1509   bailOut("genAddrOf");
1510 }
1511
1512 /*-----------------------------------------------------------------*/
1513 /* genAssign - generate code for assignment                        */
1514 /*-----------------------------------------------------------------*/
1515 static void genAssign (iCode * ic) {
1516   operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1517   int size;
1518   char *instr;
1519
1520   printIc ("genAssign", ic, 1,0,1);
1521   
1522   if (!IS_SYMOP(result)) {
1523     bailOut("genAssign: result is not a symbol");
1524   }
1525   
1526   aopOp(result, TRUE, TRUE);
1527   aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1528   size=AOP_SIZE(result);
1529
1530   /* if result is a bit */
1531   if (AOP_TYPE(result) == AOP_BIT) {
1532     /* if right is literal, we know what the value is */
1533     if (AOP_TYPE(right) == AOP_LIT) {
1534       if (operandLitValue(right)) {
1535         emitcode ("setb", AOP_NAME(result)[0]);
1536       } else {
1537         emitcode ("clr", AOP_NAME(result)[0]);
1538       }
1539       return;
1540     }
1541     /* if right is also a bit */
1542     if (AOP_TYPE(right) == AOP_BIT) {
1543       emitcode ("mov", "c,%s", AOP_NAME(right));
1544       emitcode ("mov", "%s,c", AOP_NAME(result));
1545       return;
1546     }
1547     /* we need to or */
1548     emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1549     return;
1550   }
1551
1552   /* general case */
1553   if (size>1) {
1554     instr=MOVW;
1555   } else {
1556     instr=MOVB;
1557   }
1558   emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1559
1560   if (size > 2) {
1561     if (size==3) {
1562       // generic pointer
1563       instr=MOVB;
1564     }
1565     emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1566     return;
1567   }
1568 }
1569
1570 /*-----------------------------------------------------------------*/
1571 /* genJumpTab - genrates code for jump table                       */
1572 /*-----------------------------------------------------------------*/
1573 static void genJumpTab (iCode * ic) {
1574   printIc ("genJumpTab", ic, 0,0,0);
1575 }
1576
1577 /*-----------------------------------------------------------------*/
1578 /* genCast - gen code for casting                                  */
1579 /*-----------------------------------------------------------------*/
1580 static void genCast (iCode * ic) {
1581   int size;
1582   operand *result=IC_RESULT(ic);
1583   operand *right=IC_RIGHT(ic);
1584   sym_link *ctype=operandType(IC_LEFT(ic));
1585   sym_link *rtype=operandType(IC_RIGHT(ic));
1586   sym_link *etype=getSpec(rtype);
1587   short ptrType, signedness;
1588
1589   printIc ("genCast", ic, 1,1,1);
1590
1591   aopOp(result, TRUE, TRUE);
1592   aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1593   size=AOP_SIZE(result);
1594   
1595   /* if result is a bit */
1596   if (AOP_TYPE(result) == AOP_BIT) {
1597     /* if right is literal, we know what the value is */
1598     if (AOP_TYPE(right) == AOP_LIT) {
1599       if (operandLitValue(right)) {
1600         emitcode ("setb", AOP_NAME(result)[0]);
1601       } else {
1602         emitcode ("clr", AOP_NAME(result)[0]);
1603       }
1604       return;
1605     }
1606     /* if right is also a bit */
1607     if (AOP_TYPE(right) == AOP_BIT) {
1608       emitcode ("mov", "c,%s", AOP_NAME(right));
1609       emitcode ("mov", "%s,c", AOP_NAME(result));
1610       return;
1611     }
1612     /* we need to or */
1613     emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1614     return;
1615   }
1616
1617   /* if right is a bit */
1618   if (AOP_TYPE(right)==AOP_BIT) {
1619     emitcode ("mov", "c,%s", AOP_NAME(right));
1620     emitcode ("mov", "%s,#0", AOP_NAME(result)[0]);
1621     emitcode ("rlc", "%s,#1", AOP_NAME(result)[0]);
1622     if (size>2) {
1623       emitcode ("mov", "%s,#0", AOP_NAME(result)[1]);
1624     }
1625     return;
1626   }
1627
1628   /* if the result is of type pointer */
1629   if (IS_PTR (ctype)) {
1630
1631     if (AOP_SIZE(right)>1) {
1632       emitcode ("mov", "%s,%s",  AOP_NAME(result)[0], AOP_NAME(right)[0]);
1633     } else {
1634       emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
1635       emitcode ("sext", "r1h");
1636       emitcode ("mov", "%s,r1",  AOP_NAME(result)[0]);
1637     }
1638     
1639     /* if pointer to generic pointer */
1640     if (IS_GENPTR (ctype)) {
1641             
1642       if (IS_GENPTR (rtype)) {
1643         bailOut("genCast: gptr -> gptr");
1644       }
1645
1646       if (IS_PTR (rtype)) {
1647         ptrType = DCL_TYPE (rtype);
1648       } else {
1649         /* we have to go by the storage class */
1650         if (!SPEC_OCLS(etype)) {
1651           ptrType=0; // hush the compiler
1652           bailOut("genCast: unknown storage class");
1653         } else {
1654           ptrType = PTR_TYPE (SPEC_OCLS (etype));
1655         }
1656       }
1657       
1658       /* the generic part depends on the type */
1659       switch (ptrType)
1660         {
1661         case POINTER:
1662           emitcode ("mov.b", "%s,#0x00", AOP_NAME(result)[1]);
1663           break;
1664         case FPOINTER:
1665           emitcode ("mov.b", "%s,#0x01", AOP_NAME(result)[1]);
1666           break;
1667         case CPOINTER:
1668           emitcode ("mov.b", "%s,#0x02", AOP_NAME(result)[1]);
1669           break;
1670         default:
1671           bailOut("genCast: got unknown storage class");
1672         }
1673     }
1674     return;
1675   }
1676
1677   /* do we have to sign extend? */
1678   signedness = SPEC_USIGN(rtype);
1679
1680   /* now depending on the size */
1681   switch ((AOP_SIZE(result)<<4) + AOP_SIZE(right))
1682     {
1683     case 0x44:
1684     case 0x33:
1685       emitcode("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1686       // fall through
1687     case 0x24:
1688     case 0x22:
1689     case 0x11:
1690       emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1691       return;
1692     case 0x42:
1693       emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1694       if (signedness) {
1695         emitcode("sext", "%s", AOP_NAME(result)[1]);
1696       } else {
1697         emitcode("mov", "%s,#0", AOP_NAME(result)[1]);
1698       }
1699       return;
1700     case 0x41:
1701     case 0x21:
1702       emitcode("mov", "r1l,%s", AOP_NAME(right)[0]);
1703       if (signedness) {
1704         emitcode("sext", "r1h");
1705       } else {
1706         emitcode("mov", "r1h,#0");
1707       }
1708       emitcode("mov", "%s,r1", AOP_NAME(result)[0]);
1709       if (size==2)
1710         return;
1711       // fall through: case 0x41
1712       if (signedness) {
1713         emitcode("sext", "r1");
1714       } else {
1715         emitcode("mov", "r1,#0");
1716       }
1717       emitcode("mov", "%s,r1", AOP_NAME(result)[1]);
1718       return;
1719     case 0x14:
1720     case 0x12:
1721       emitcode("mov", "r1,%s", AOP_NAME(right)[0]);
1722       emitcode("mov", "%s,r1l", AOP_NAME(result)[0]);
1723       return;
1724     }
1725   fprintf(stderr, "genCast: unknown size: %d:%d\n",
1726           AOP_SIZE(result), AOP_SIZE(right));
1727   bailOut("genCast: unknown size");
1728 }
1729
1730
1731 /*-----------------------------------------------------------------*/
1732 /* genDjnz - generate decrement & jump if not zero instrucion      */
1733 /*-----------------------------------------------------------------*/
1734 static bool genDjnz (iCode * ic, iCode * ifx) {
1735   symbol *lbl, *lbl1;
1736
1737   if (!ifx)
1738     return 0;
1739
1740   /* if the if condition has a false label
1741      then we cannot save */
1742   if (IC_FALSE (ifx))
1743     return 0;
1744
1745   /* if the minus is not of the form
1746      a = a - 1 */
1747   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1748       !IS_OP_LITERAL (IC_RIGHT (ic)))
1749     return 0;
1750
1751   if (operandLitValue (IC_RIGHT (ic)) != 1)
1752     return 0;
1753
1754   /* if the size of this greater than two then no
1755      saving */
1756   if (getSize (operandType (IC_RESULT (ic))) > 2)
1757     return 0;
1758
1759   printIc ("genDjnz", ic, 1,1,1);
1760
1761   /* otherwise we can save BIG */
1762   lbl = newiTempLabel (NULL);
1763   lbl1 = newiTempLabel (NULL);
1764
1765   aopOp (IC_RESULT (ic), FALSE, TRUE);
1766
1767   if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1768     emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1769     emitcode ("br", "%05d$", lbl1->key + 100);
1770     emitcode ("", "%05d$:", lbl->key + 100);
1771     emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1772     emitcode ("", "%05d$:", lbl1->key + 100);
1773     return TRUE;
1774   }
1775
1776   bailOut("genDjnz: aop type");
1777   return FALSE;
1778 }
1779
1780 /*-----------------------------------------------------------------*/
1781 /* genReceive - generate code for a receive iCode                  */
1782 /*-----------------------------------------------------------------*/
1783 static void genReceive (iCode * ic) {
1784   printIc ("genReceive", ic, 1,0,0);
1785 }
1786
1787 /*-----------------------------------------------------------------*/
1788 /* gen51Code - generate code for 8051 based controllers            */
1789 /*-----------------------------------------------------------------*/
1790 void genXA51Code (iCode * lic) {
1791   iCode *ic;
1792   int cln = 0;
1793   
1794   lineHead = lineCurr = NULL;
1795   
1796   /* if debug information required */
1797   if (options.debug && currFunc)
1798     {
1799       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1800       _G.debugLine = 1;
1801       if (IS_STATIC (currFunc->etype))
1802         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1803       else
1804         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1805       _G.debugLine = 0;
1806     }
1807   
1808   for (ic = lic; ic; ic = ic->next) {
1809     if (ic->lineno && cln != ic->lineno) {
1810       if (options.debug) {
1811         _G.debugLine = 1;
1812         emitcode ("", "C$%s$%d$%d$%d ==.",
1813                   FileBaseName (ic->filename), ic->lineno,
1814                   ic->level, ic->block);
1815         _G.debugLine = 0;
1816       }
1817       emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
1818                 printCLine(ic->filename, ic->lineno));
1819       cln = ic->lineno;
1820     }
1821     /* if the result is marked as
1822        spilt and rematerializable or code for
1823        this has already been generated then
1824        do nothing */
1825     if (resultRemat (ic) || ic->generated)
1826       continue;
1827     
1828     /* depending on the operation */
1829     switch (ic->op)
1830       {
1831       case '!':
1832         genNot (ic);
1833         break;
1834         
1835       case '~':
1836         genCpl (ic);
1837         break;
1838         
1839       case UNARYMINUS:
1840         genUminus (ic);
1841         break;
1842         
1843       case IPUSH:
1844         genIpush (ic);
1845         break;
1846         
1847       case IPOP:
1848         /* IPOP happens only when trying to restore a
1849            spilt live range, if there is an ifx statement
1850            following this pop then the if statement might
1851            be using some of the registers being popped which
1852            would destory the contents of the register so
1853            we need to check for this condition and handle it */
1854         if (ic->next &&
1855             ic->next->op == IFX &&
1856             regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1857           genIfx (ic->next, ic);
1858         else
1859           genIpop (ic);
1860         break;
1861         
1862       case CALL:
1863         genCall (ic);
1864         break;
1865         
1866       case PCALL:
1867         genPcall (ic);
1868         break;
1869         
1870       case FUNCTION:
1871         genFunction (ic);
1872         break;
1873         
1874       case ENDFUNCTION:
1875         genEndFunction (ic);
1876         break;
1877         
1878       case RETURN:
1879         genRet (ic);
1880         break;
1881         
1882       case LABEL:
1883         genLabel (ic);
1884         break;
1885         
1886       case GOTO:
1887         genGoto (ic);
1888         break;
1889         
1890       case '+':
1891         genPlus (ic);
1892         break;
1893         
1894       case '-':
1895         if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
1896           genMinus (ic);
1897         break;
1898         
1899       case '*':
1900         genMult (ic);
1901         break;
1902         
1903       case '/':
1904         genDiv (ic);
1905         break;
1906         
1907       case '%':
1908         genMod (ic);
1909         break;
1910         
1911       case '>':
1912         genCmpGt (ic);
1913         break;
1914         
1915       case '<':
1916         genCmpLt (ic);
1917         break;
1918         
1919       case LE_OP:
1920       case GE_OP:
1921       case NE_OP:
1922
1923         /* note these two are xlated by algebraic equivalence
1924            during parsing SDCC.y */
1925         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1926                 "got '>=' or '<=' shouldn't have come here");
1927         break;
1928
1929       case EQ_OP:
1930         genCmpEq (ic);
1931         break;
1932         
1933       case AND_OP:
1934         genAndOp (ic);
1935         break;
1936         
1937       case OR_OP:
1938         genOrOp (ic);
1939         break;
1940         
1941       case '^':
1942         genXor (ic, ifxForOp (IC_RESULT (ic), ic));
1943         break;
1944         
1945       case '|':
1946         genOr (ic, ifxForOp (IC_RESULT (ic), ic));
1947         break;
1948         
1949       case BITWISEAND:
1950         genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
1951         break;
1952         
1953       case INLINEASM:
1954         genInline (ic);
1955         break;
1956         
1957       case RRC:
1958         genRRC (ic);
1959         break;
1960         
1961       case RLC:
1962         genRLC (ic);
1963         break;
1964         
1965       case GETHBIT:
1966         genGetHbit (ic);
1967         break;
1968         
1969       case LEFT_OP:
1970         genLeftShift (ic);
1971         break;
1972         
1973       case RIGHT_OP:
1974         genRightShift (ic);
1975         break;
1976         
1977       case GET_VALUE_AT_ADDRESS:
1978         genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_RESULT(ic)))));
1979         break;
1980         
1981       case '=':
1982         if (POINTER_SET (ic))
1983           genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
1984         else
1985           genAssign (ic);
1986         break;
1987         
1988       case IFX:
1989         genIfx (ic, NULL);
1990         break;
1991         
1992       case ADDRESS_OF:
1993         genAddrOf (ic);
1994         break;
1995         
1996       case JUMPTABLE:
1997         genJumpTab (ic);
1998         break;
1999         
2000       case CAST:
2001         genCast (ic);
2002         break;
2003         
2004       case RECEIVE:
2005         genReceive (ic);
2006         break;
2007         
2008       case SEND:
2009         addSet (&_G.sendSet, ic);
2010         break;
2011         
2012       default:
2013         ic = ic;
2014       }
2015   }
2016   
2017   
2018   /* now we are ready to call the
2019      peep hole optimizer */
2020   if (!options.nopeep)
2021     peepHole (&lineHead);
2022   
2023   /* now do the actual printing */
2024   printLine (lineHead, codeOutFile);
2025   return;
2026 }