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