]> git.gag.com Git - fw/sdcc/blob - src/xa51/gen.c
ddadefa85a2c012ca4e9590f1a318b531593540a
[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.w", "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   if (!IC_LEFT(ic)) {
865     printIc ("genRet", ic, 0, 0, 0);
866   } else {
867     printIc ("genRet", ic, 0, 1, 0);
868     aopOp(IC_LEFT(ic), TRUE, TRUE);
869     switch (AOP_SIZE(IC_LEFT(ic)))
870       {
871       case 4:
872         emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
873         emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
874         break;
875       case 3:
876         emitcode ("mov", "r1l,%s", AOP_NAME(IC_LEFT(ic))[1]);
877         // fall through
878       case 2:
879         emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
880         break;
881       case 1:
882         emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
883         break;
884       default:
885         bailOut("genRet");
886       }
887   }
888
889   emitcode ("jmp", "%05d$", returnLabel->key+100);
890 }
891
892 /*-----------------------------------------------------------------*/
893 /* genLabel - generates a label                                    */
894 /*-----------------------------------------------------------------*/
895 static void genLabel (iCode * ic) {
896   /* special case never generate */
897   if (IC_LABEL (ic) == entryLabel)
898     return;
899
900   emitcode (";", "genLabel(%d) %s", ic->lineno, IC_LABEL(ic)->name);
901   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
902 }
903
904 /*-----------------------------------------------------------------*/
905 /* genGoto - generates a jmp                                      */
906 /*-----------------------------------------------------------------*/
907 static void genGoto (iCode * ic) {
908   emitcode (";", "genGoto(%d) %s", ic->lineno, IC_LABEL(ic)->name);
909   emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
910 }
911
912 /*-----------------------------------------------------------------*/
913 /* genPlus - generates code for addition                           */
914 /*-----------------------------------------------------------------*/
915 static void genPlus (iCode * ic) {
916   operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
917   int size;
918   char *instr;
919
920   printIc ("genPlus", ic, 1,1,1);
921
922   size=aopOp(result, TRUE, TRUE);
923
924   /* if left is a literal, then exchange them */
925   if (IS_LITERAL(operandType(left))) {
926     operand *tmp = right;
927     right = left;
928     left = tmp;
929   }
930     
931   if (aopIsBit(result)) {
932     if (IS_LITERAL(operandType(right))) {
933       if (operandLitValue(right)) {
934         emitcode ("setb", AOP_NAME(result)[0]);
935         return;
936       }
937       aopOp(left, TRUE, TRUE);
938       emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
939       return;
940     }
941     bailOut("genPlus: unfinished genPlus bit");
942   }
943   
944   aopOp(left, !aopIsPtr(result), !aopIsDir(result));
945   aopOp(right, !aopIsPtr(result), !aopIsDir(result));
946
947   // special case for * = * + char, needs a closer look
948   // heck, this shouldn't have come here but bug-223113 does
949   if (size==3 && AOP_SIZE(right)==1) {
950     emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
951     emitcode ("mov", "r1h,#0"); // ptr arith unsigned????????????
952     emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
953     emitcode ("add.w", "%s,r1", AOP_NAME(result)[0]);
954     emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
955     return;
956   }
957
958   // special case for (whatever)* = (whatever)** + char, needs a closer look
959   // heck, this shouldn't have come here but bug-441448 does
960   if (size==2 && AOP_SIZE(right)==1) {
961     emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
962     emitcode ("mov", "r1h,#0"); // ptr arith unsigned????????????
963     emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
964     emitcode ("add.w", "%s,r1", AOP_NAME(result)[0]);
965     return;
966   }
967
968   if (size>1) {
969     instr="add.w";
970   } else {
971     instr="add.b";
972   }
973   if (!aopEqual(result->aop, left->aop, 0)) {
974     emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
975   }
976   emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
977   if (size>2) {
978     if (!aopEqual(result->aop, left->aop, 1)) {
979       emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
980     }
981     if (size==3) {
982       // generic pointer
983     } else {
984       emitcode ("addc.w", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
985     }
986   }
987   return;
988 }
989
990 /*-----------------------------------------------------------------*/
991 /* genMinus - generates code for subtraction                       */
992 /*-----------------------------------------------------------------*/
993 static void genMinus (iCode * ic) {
994   printIc ("genMinus", ic, 1,1,1);
995 }
996
997
998 /*-----------------------------------------------------------------*/
999 /* genMult - generates code for multiplication                     */
1000 /*-----------------------------------------------------------------*/
1001 static void genMult (iCode * ic) {
1002   printIc ("genMult", ic, 1,1,1);
1003 }
1004
1005 /*-----------------------------------------------------------------*/
1006 /* genDiv - generates code for division                            */
1007 /*-----------------------------------------------------------------*/
1008 static void genDiv (iCode * ic) {
1009   printIc ("genDiv", ic, 1,1,1);
1010 }
1011
1012 /*-----------------------------------------------------------------*/
1013 /* genMod - generates code for division                            */
1014 /*-----------------------------------------------------------------*/
1015 static void genMod (iCode * ic) {
1016   printIc ("genMod", ic, 1,1,1);
1017 }
1018
1019 /*-----------------------------------------------------------------*/
1020 /* genCmpGt :- greater than comparison                             */
1021 /*-----------------------------------------------------------------*/
1022 static void genCmpGt (iCode * ic) {
1023   printIc ("genCmpGt", ic, 1,1,1);
1024 }
1025 /*-----------------------------------------------------------------*/
1026 /* genCmpGt :- greater than comparison                             */
1027 /*-----------------------------------------------------------------*/
1028 static void genCmpLe (iCode * ic) {
1029   printIc ("genCmpLe", ic, 1,1,1);
1030 }
1031 /*-----------------------------------------------------------------*/
1032 /* genCmpGt :- greater than comparison                             */
1033 /*-----------------------------------------------------------------*/
1034 static void genCmpGe (iCode * ic) {
1035   printIc ("genCmpGe", ic, 1,1,1);
1036 }
1037 /*-----------------------------------------------------------------*/
1038 /* genCmpGt :- greater than comparison                             */
1039 /*-----------------------------------------------------------------*/
1040 static void genCmpNe (iCode * ic) {
1041   printIc ("genCmpNe", ic, 1,1,1);
1042 }
1043 /*-----------------------------------------------------------------*/
1044 /* genCmpLt - less than comparisons                                */
1045 /*-----------------------------------------------------------------*/
1046 static void genCmpLt (iCode * ic) {
1047   printIc ("genCmpLt", ic, 1,1,1);
1048 }
1049 /*-----------------------------------------------------------------*/
1050 /* genCmpEq - generates code for equal to                          */
1051 /*-----------------------------------------------------------------*/
1052 static void genCmpEq (iCode * ic) {
1053   printIc ("genCmpEq", ic, 1,1,1);
1054 }
1055
1056 /*-----------------------------------------------------------------*/
1057 /* ifxForOp - returns the icode containing the ifx for operand     */
1058 /*-----------------------------------------------------------------*/
1059 static iCode *ifxForOp (operand * op, iCode * ic) {
1060   /* if true symbol then needs to be assigned */
1061   if (IS_TRUE_SYMOP (op))
1062     return NULL;
1063   
1064   /* if this has register type condition and
1065      the next instruction is ifx with the same operand
1066      and live to of the operand is upto the ifx only then */
1067   if (ic->next &&
1068       ic->next->op == IFX &&
1069       IC_COND (ic->next)->key == op->key &&
1070       OP_SYMBOL (op)->liveTo <= ic->next->seq)
1071     return ic->next;
1072   
1073   return NULL;
1074 }
1075
1076 /*-----------------------------------------------------------------*/
1077 /* hasInc - operand is incremented before any other use            */
1078 /*-----------------------------------------------------------------*/
1079 static iCode *hasInc (operand *op, iCode *ic, int osize) {
1080   sym_link *type = operandType(op);
1081   sym_link *retype = getSpec (type);
1082   iCode *lic = ic->next;
1083   int isize ;
1084   
1085   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
1086   if (!IS_SYMOP(op)) return NULL;
1087
1088   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
1089   if (IS_AGGREGATE(type->next)) return NULL;
1090   if (osize != (isize = getSize(type->next))) return NULL;
1091
1092   while (lic) {
1093     /* if operand of the form op = op + <sizeof *op> */
1094     if (lic->op == '+') {
1095       if (isOperandEqual(IC_LEFT(lic),op) &&
1096           //isOperandEqual(IC_RESULT(lic),op) && 
1097           isOperandLiteral(IC_RIGHT(lic)) &&
1098           operandLitValue(IC_RIGHT(lic)) == isize) {
1099         emitcode (";", "Found hasInc");
1100         return lic;
1101       }
1102     }
1103     /* if the operand used or deffed */
1104     if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
1105       return NULL;
1106     }
1107     /* if GOTO or IFX */
1108     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
1109     lic = lic->next;
1110   }
1111   return NULL;
1112 }
1113
1114 /*-----------------------------------------------------------------*/
1115 /* genAndOp - for && operation                                     */
1116 /*-----------------------------------------------------------------*/
1117 static void genAndOp (iCode * ic) {
1118   printIc ("genAndOp(&&)", ic, 1,1,1);
1119 }
1120
1121 /*-----------------------------------------------------------------*/
1122 /* genOrOp - for || operation                                      */
1123 /*-----------------------------------------------------------------*/
1124 static void genOrOp (iCode * ic) {
1125   printIc ("genOrOp(||)", ic, 1,1,1);
1126 }
1127
1128 /*-----------------------------------------------------------------*/
1129 /* genAnd  - code for and                                            */
1130 /*-----------------------------------------------------------------*/
1131 static void genAnd (iCode * ic, iCode * ifx) {
1132   printIc ("genAnd", ic, 1,1,1);
1133 }
1134
1135 /*-----------------------------------------------------------------*/
1136 /* genOr  - code for or                                            */
1137 /*-----------------------------------------------------------------*/
1138 static void genOr (iCode * ic, iCode * ifx) {
1139   operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1140   int size;
1141   char *instr;
1142
1143   printIc ("genOr", ic, 1,1,1);
1144
1145   size=aopOp(result, TRUE, TRUE);
1146
1147   /* if left is a literal, then exchange them */
1148   if (IS_LITERAL(operandType(left))) {
1149     operand *tmp = right;
1150     right = left;
1151     left = tmp;
1152   }
1153     
1154   if (aopIsBit(result)) {
1155     if (IS_LITERAL(operandType(right))) {
1156       if (operandLitValue(right)) {
1157         emitcode ("setb", AOP_NAME(result)[0]);
1158         return;
1159       }
1160       aopOp(left, TRUE, TRUE);
1161       emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1162       return;
1163     }
1164   }
1165   
1166   aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1167   aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1168
1169   if (size>1) {
1170     instr="or.w";
1171   } else {
1172     instr="or.b";
1173   }
1174   if (!aopEqual(result->aop, left->aop, 0)) {
1175     emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1176   }
1177   emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1178   if (size>2) {
1179     if (!aopEqual(result->aop, left->aop, 1)) {
1180       emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1181     }
1182     emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1183   }
1184   return;
1185 }
1186
1187 /*-----------------------------------------------------------------*/
1188 /* genXor - code for xclusive or                                   */
1189 /*-----------------------------------------------------------------*/
1190 static void genXor (iCode * ic, iCode * ifx) {
1191   printIc ("genXor", ic, 1,1,1);
1192 }
1193
1194 /*-----------------------------------------------------------------*/
1195 /* genInline - write the inline code out                           */
1196 /*-----------------------------------------------------------------*/
1197 static void genInline (iCode * ic) {
1198
1199   printIc ("genInline", ic, 0,0,0);
1200   
1201   emitcode ("", IC_INLINE(ic));
1202 }
1203
1204 /*-----------------------------------------------------------------*/
1205 /* genRRC - rotate right with carry                                */
1206 /*-----------------------------------------------------------------*/
1207 static void genRRC (iCode * ic) {
1208   printIc ("genRRC", ic, 1,1,0);
1209 }
1210
1211 /*-----------------------------------------------------------------*/
1212 /* genRLC - generate code for rotate left with carry               */
1213 /*-----------------------------------------------------------------*/
1214 static void genRLC (iCode * ic) {
1215   printIc ("genRLC", ic, 1,1,0);
1216 }
1217
1218 /*-----------------------------------------------------------------*/
1219 /* genGetHbit - generates code get highest order bit               */
1220 /*-----------------------------------------------------------------*/
1221 static void genGetHbit (iCode * ic) {
1222   printIc ("genGetHbit", ic, 1,1,0);
1223 }
1224
1225 /*-----------------------------------------------------------------*/
1226 /* genLeftShift - generates code for left shifting                 */
1227 /*-----------------------------------------------------------------*/
1228 static void genLeftShift (iCode * ic) {
1229   printIc ("genLeftShift", ic, 1,1,1);
1230 }
1231
1232 /*-----------------------------------------------------------------*/
1233 /* genRightShift - generate code for right shifting                */
1234 /*-----------------------------------------------------------------*/
1235 static void genRightShift (iCode * ic) {
1236   printIc ("genRightShift", ic, 1,1,1);
1237 }
1238
1239 /*-----------------------------------------------------------------*/
1240 /* genPointerGet - generate code for pointer get                   */
1241 /*-----------------------------------------------------------------*/
1242 static void genPointerGet (iCode * ic, iCode *pi) {
1243   char *instr, *scratchReg;
1244   operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
1245   bool codePointer=IS_CODEPTR(operandType(left));
1246   int size;
1247
1248   if (pi) {
1249     printIc ("genPointerGet pi", ic, 1,1,0);
1250   } else {
1251     printIc ("genPointerGet", ic, 1,1,0);
1252   }
1253
1254   if (!IS_PTR(operandType(left))) {
1255     bailOut ("genPointerGet: pointer required");
1256   }
1257
1258   aopOp(left,FALSE,FALSE);
1259   size=aopOp(result,TRUE,aopIsDir(left));
1260
1261   if (IS_GENPTR(operandType(left))) {
1262     symbol *tlbl1=newiTempLabel(NULL);
1263     symbol *tlbl2=newiTempLabel(NULL);
1264     emitcode ("cmp", "%s,#0x%02x", AOP_NAME(left)[1], CPOINTER);
1265     emitcode ("beq", "%05d$", tlbl1->key+100);
1266     // far/near pointer
1267     if (pi) {
1268       emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1269       pi->generated=1;
1270     } else {
1271       emitcode ("mov", "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1272     }
1273     if (size>2) {
1274       if (pi) {
1275         emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1276       } else {
1277         emitcode ("mov", "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1278       }
1279     }
1280     emitcode ("br", "%05d$", tlbl2->key+100);
1281     emitcode ("", "%05d$:", tlbl1->key+100);
1282     // code pointer
1283     if (pi) {
1284       emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1285       pi->generated=1;
1286     } else {
1287       emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
1288       emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[0]);
1289     }
1290     if (size>2) {
1291       if (pi) {
1292         emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1293       } else {
1294         emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[1]);
1295       }
1296     }
1297     emitcode ("", "%05d$:", tlbl2->key+100);
1298     return;
1299   }
1300
1301   switch (AOP_TYPE(left)) 
1302     {
1303     case AOP_LIT:
1304       emitcode("mov","r1,%s", AOP_NAME(left)[0]);
1305       sprintf (AOP_NAME(left)[0], "r1");
1306       // fall through
1307     case AOP_REG:
1308       if (size>1) {
1309         if (codePointer) {
1310           instr=MOVCW;
1311         } else {
1312           instr=MOVW;
1313         }
1314         scratchReg=R1;
1315       } else {
1316         if (codePointer) {
1317           instr=MOVCB;
1318         } else {
1319           instr=MOVB;
1320         }
1321         scratchReg=R1L;
1322       }
1323       if (AOP_TYPE(result)==AOP_STK) {
1324         emitcode (MOV, "%s,[%s]", scratchReg, AOP_NAME(left)[0]);
1325         emitcode (MOV, "%s,%s", AOP_NAME(result)[0], scratchReg);
1326       } else {
1327         if (pi) {
1328           emitcode (instr, "%s,[%s+]", AOP_NAME(result)[0], 
1329                     AOP_NAME(left)[0]);
1330           pi->generated=1;
1331         } else {
1332           if (codePointer) {
1333             emitcode (MOV, "r1,%s", AOP_NAME(left)[0]);
1334             emitcode (instr, "%s,[r1+]", AOP_NAME(result)[0]);
1335           } else {
1336             emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], 
1337                       AOP_NAME(left)[0]);
1338           }
1339         }
1340       }
1341       if (size > 2) {
1342         if (size==3) {
1343           if (codePointer) {
1344             instr=MOVCB;
1345           } else {
1346             instr=MOVB;
1347           }
1348           scratchReg=R1L;
1349         }
1350         if (AOP_TYPE(result)==AOP_STK) {
1351           emitcode (MOV, "%s,[%s+2]", scratchReg, AOP_NAME(left)[0]);
1352           emitcode (MOV, "%s,%s", AOP_NAME(result)[1], scratchReg);
1353         } else {
1354           if (pi) {
1355             emitcode (instr, "%s,[%s+]", AOP_NAME(result)[1], 
1356                       AOP_NAME(left)[0]);
1357           } else {
1358             if (codePointer) {
1359               emitcode (instr, "%s,[r1]", AOP_NAME(result)[1]);
1360             } else {
1361               emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1], 
1362                         AOP_NAME(left)[0]);
1363             }
1364           }
1365         }
1366       }
1367       return;
1368     }
1369   bailOut ("genPointerGet");
1370 }
1371
1372 /*-----------------------------------------------------------------*/
1373 /* genPointerSet - stores the value into a pointer location        */
1374 /*-----------------------------------------------------------------*/
1375 static void genPointerSet (iCode * ic, iCode *pi) {
1376   char *instr;
1377   operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1378   int size;
1379
1380   printIc ("genPointerSet", ic, 1,0,1);
1381
1382   if (!IS_PTR(operandType(result))) {
1383     bailOut ("genPointerSet: pointer required");
1384   }
1385
1386   aopOp(result,FALSE,FALSE);
1387   size=aopOp(right,FALSE, FALSE);
1388
1389   if (IS_GENPTR(operandType(result))) {
1390     emitcode (";", "INLINE\t_gptrset ; [%s %s] = %s %s", 
1391               AOP_NAME(result)[0], AOP_NAME(result)[1],
1392               AOP_NAME(right)[0], AOP_NAME(right)[1]);
1393     return;
1394   }
1395
1396   switch (AOP_TYPE(right)) 
1397     {
1398     case AOP_LIT:
1399     case AOP_REG:
1400       if (size>1) {
1401         instr=MOVW;
1402       } else {
1403         instr=MOVB;
1404       }
1405       if (pi) {
1406         emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1407         pi->generated=1;
1408       } else {
1409         emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1410       }
1411       if (size > 2) {
1412         if (size==3) {
1413           instr=MOVB;
1414         }
1415         if (pi) {
1416           emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], 
1417                     AOP_NAME(right)[1]);
1418         } else {
1419           emitcode (instr, "[%s+2],%s", AOP_NAME(result)[0], 
1420                     AOP_NAME(right)[1]);
1421         }
1422       }
1423       return;
1424     }
1425   bailOut ("genPointerSet");
1426 }
1427
1428 /*-----------------------------------------------------------------*/
1429 /* genIfx - generate code for Ifx statement                        */
1430 /*-----------------------------------------------------------------*/
1431 static void genIfx (iCode * ic, iCode * popIc) {
1432   int size;
1433   char *instr;
1434   bool trueOrFalse;
1435   symbol *jlbl, *tlbl=newiTempLabel(NULL);
1436   operand *cond=IC_COND(ic);
1437
1438   emitcode (";", "genIfx(%d) cond=%s trueLabel:%s falseLabel:%s", 
1439             ic->lineno, printOp(cond),
1440             IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1441             IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1442
1443   size=aopOp(cond,TRUE,TRUE);
1444
1445   if (IC_TRUE(ic)) {
1446     trueOrFalse=TRUE;
1447     jlbl=IC_TRUE(ic);
1448   } else {
1449     trueOrFalse=FALSE;
1450     jlbl=IC_FALSE(ic);
1451   }
1452
1453   switch (AOP_TYPE(cond) )
1454     {
1455     case AOP_BIT:
1456       emitcode (trueOrFalse ? "jnb" : "jb", "%s,%05d$", 
1457                 AOP_NAME(cond)[0], tlbl->key+100);
1458       emitcode ("jmp", "%05d$", jlbl->key+100);
1459       emitcode ("", "%05d$:", tlbl->key+100);
1460       return;
1461     case AOP_REG:
1462     case AOP_DIR:
1463     case AOP_FAR:
1464     case AOP_STK:
1465       if (size>1) {
1466         instr="cmp.w";
1467       } else {
1468         instr="cmp.b";
1469       }
1470       emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1471       emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1472       if (size > 2) {
1473         if (size==3) {
1474           // generic pointer, forget the generic part
1475         } else {
1476           emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1477           emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1478         }
1479       }
1480       emitcode ("jmp", "%05d$", jlbl->key+100);
1481       emitcode ("", "%05d$:", tlbl->key+100);
1482       return;
1483     }
1484   bailOut ("genIfx");
1485 }
1486
1487 /*-----------------------------------------------------------------*/
1488 /* genAddrOf - generates code for address of                       */
1489 /*-----------------------------------------------------------------*/
1490 static void genAddrOf (iCode * ic) {
1491   int size;
1492   operand *left=IC_LEFT(ic);
1493
1494   printIc ("genAddrOf", ic, 1,1,0);
1495
1496   size=aopOp (IC_RESULT(ic), FALSE, TRUE);
1497
1498   if (isOperandOnStack(left)) {
1499     emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1500               getStackOffset(OP_SYMBOL(left)->stack));
1501     if (size > 2) {
1502       // this must be a generic pointer
1503       emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER);
1504     }
1505     return;
1506   }
1507
1508   if (isOperandInDirSpace(left) ||
1509       isOperandInFarSpace(left) ||
1510       isOperandInCodeSpace(left)) {
1511     emitcode ("mov.w", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1512               OP_SYMBOL(left)->rname);
1513     if (size > 2) {
1514       // this must be a generic pointer
1515       int space=0; // dir space
1516       if (isOperandInFarSpace(left)) {
1517         space=1;
1518       } else if (isOperandInCodeSpace(left)) {
1519         space=2;
1520       }
1521       emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1522     }
1523     return;
1524   }
1525
1526   bailOut("genAddrOf");
1527 }
1528
1529 /*-----------------------------------------------------------------*/
1530 /* genAssign - generate code for assignment                        */
1531 /*-----------------------------------------------------------------*/
1532 static void genAssign (iCode * ic) {
1533   operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1534   int size;
1535   char *instr;
1536
1537   printIc ("genAssign", ic, 1,0,1);
1538   
1539   if (!IS_SYMOP(result)) {
1540     bailOut("genAssign: result is not a symbol");
1541   }
1542   
1543   aopOp(result, TRUE, TRUE);
1544   aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1545   size=AOP_SIZE(result);
1546
1547   /* if result is a bit */
1548   if (AOP_TYPE(result) == AOP_BIT) {
1549     /* if right is literal, we know what the value is */
1550     if (AOP_TYPE(right) == AOP_LIT) {
1551       if (operandLitValue(right)) {
1552         emitcode ("setb", AOP_NAME(result)[0]);
1553       } else {
1554         emitcode ("clr", AOP_NAME(result)[0]);
1555       }
1556       return;
1557     }
1558     /* if right is also a bit */
1559     if (AOP_TYPE(right) == AOP_BIT) {
1560       emitcode ("mov", "c,%s", AOP_NAME(right));
1561       emitcode ("mov", "%s,c", AOP_NAME(result));
1562       return;
1563     }
1564     /* we need to or */
1565     emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1566     return;
1567   }
1568
1569   /* general case */
1570   if (size>1) {
1571     instr=MOVW;
1572   } else {
1573     instr=MOVB;
1574   }
1575   emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1576
1577   if (size > 2) {
1578     if (size==3) {
1579       // generic pointer
1580       instr=MOVB;
1581     }
1582     emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1583     return;
1584   }
1585 }
1586
1587 /*-----------------------------------------------------------------*/
1588 /* genJumpTab - genrates code for jump table                       */
1589 /*-----------------------------------------------------------------*/
1590 static void genJumpTab (iCode * ic) {
1591   printIc ("genJumpTab", ic, 0,0,0);
1592 }
1593
1594 /*-----------------------------------------------------------------*/
1595 /* genCast - gen code for casting                                  */
1596 /*-----------------------------------------------------------------*/
1597 static void genCast (iCode * ic) {
1598   int size;
1599   operand *result=IC_RESULT(ic);
1600   operand *right=IC_RIGHT(ic);
1601   sym_link *ctype=operandType(IC_LEFT(ic));
1602   sym_link *rtype=operandType(IC_RIGHT(ic));
1603   sym_link *etype=getSpec(rtype);
1604   short ptrType, signedness;
1605
1606   printIc ("genCast", ic, 1,1,1);
1607
1608   aopOp(result, TRUE, TRUE);
1609   aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1610   size=AOP_SIZE(result);
1611   
1612   /* if result is a bit */
1613   if (AOP_TYPE(result) == AOP_BIT) {
1614     /* if right is literal, we know what the value is */
1615     if (AOP_TYPE(right) == AOP_LIT) {
1616       if (operandLitValue(right)) {
1617         emitcode ("setb", AOP_NAME(result)[0]);
1618       } else {
1619         emitcode ("clr", AOP_NAME(result)[0]);
1620       }
1621       return;
1622     }
1623     /* if right is also a bit */
1624     if (AOP_TYPE(right) == AOP_BIT) {
1625       emitcode ("mov", "c,%s", AOP_NAME(right));
1626       emitcode ("mov", "%s,c", AOP_NAME(result));
1627       return;
1628     }
1629     /* we need to or */
1630     emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1631     return;
1632   }
1633
1634   /* if right is a bit */
1635   if (AOP_TYPE(right)==AOP_BIT) {
1636     emitcode ("mov", "c,%s", AOP_NAME(right));
1637     emitcode ("mov", "%s,#0", AOP_NAME(result)[0]);
1638     emitcode ("rlc", "%s,#1", AOP_NAME(result)[0]);
1639     if (size>2) {
1640       emitcode ("mov", "%s,#0", AOP_NAME(result)[1]);
1641     }
1642     return;
1643   }
1644
1645   /* if the result is of type pointer */
1646   if (IS_PTR (ctype)) {
1647
1648     if (AOP_SIZE(right)>1) {
1649       emitcode ("mov", "%s,%s",  AOP_NAME(result)[0], AOP_NAME(right)[0]);
1650     } else {
1651       emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
1652       emitcode ("sext", "r1h");
1653       emitcode ("mov", "%s,r1",  AOP_NAME(result)[0]);
1654     }
1655     
1656     /* if pointer to generic pointer */
1657     if (IS_GENPTR (ctype)) {
1658             
1659       if (IS_GENPTR (rtype)) {
1660         bailOut("genCast: gptr -> gptr");
1661       }
1662
1663       if (IS_PTR (rtype)) {
1664         ptrType = DCL_TYPE (rtype);
1665       } else {
1666         /* we have to go by the storage class */
1667         if (!SPEC_OCLS(etype)) {
1668           ptrType=0; // hush the compiler
1669           bailOut("genCast: unknown storage class");
1670         } else {
1671           ptrType = PTR_TYPE (SPEC_OCLS (etype));
1672         }
1673       }
1674       
1675       /* the generic part depends on the type */
1676       switch (ptrType)
1677         {
1678         case POINTER:
1679           emitcode ("mov.b", "%s,#0x00", AOP_NAME(result)[1]);
1680           break;
1681         case FPOINTER:
1682           emitcode ("mov.b", "%s,#0x01", AOP_NAME(result)[1]);
1683           break;
1684         case CPOINTER:
1685           emitcode ("mov.b", "%s,#0x02", AOP_NAME(result)[1]);
1686           break;
1687         default:
1688           bailOut("genCast: got unknown storage class");
1689         }
1690     }
1691     return;
1692   }
1693
1694   /* do we have to sign extend? */
1695   signedness = SPEC_USIGN(rtype);
1696
1697   /* now depending on the size */
1698   switch ((AOP_SIZE(result)<<4) + AOP_SIZE(right))
1699     {
1700     case 0x44:
1701     case 0x33:
1702       emitcode("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1703       // fall through
1704     case 0x24:
1705     case 0x22:
1706     case 0x11:
1707       emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1708       return;
1709     case 0x42:
1710       emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1711       if (signedness) {
1712         emitcode("sext", "%s", AOP_NAME(result)[1]);
1713       } else {
1714         emitcode("mov", "%s,#0", AOP_NAME(result)[1]);
1715       }
1716       return;
1717     case 0x41:
1718     case 0x21:
1719       emitcode("mov", "r1l,%s", AOP_NAME(right)[0]);
1720       if (signedness) {
1721         emitcode("sext", "r1h");
1722       } else {
1723         emitcode("mov", "r1h,#0");
1724       }
1725       emitcode("mov", "%s,r1", AOP_NAME(result)[0]);
1726       if (size==2)
1727         return;
1728       // fall through: case 0x41
1729       if (signedness) {
1730         emitcode("sext", "r1");
1731       } else {
1732         emitcode("mov", "r1,#0");
1733       }
1734       emitcode("mov", "%s,r1", AOP_NAME(result)[1]);
1735       return;
1736     case 0x14:
1737     case 0x12:
1738       emitcode("mov", "r1,%s", AOP_NAME(right)[0]);
1739       emitcode("mov", "%s,r1l", AOP_NAME(result)[0]);
1740       return;
1741     }
1742   fprintf(stderr, "genCast: unknown size: %d:%d\n",
1743           AOP_SIZE(result), AOP_SIZE(right));
1744   bailOut("genCast: unknown size");
1745 }
1746
1747
1748 /*-----------------------------------------------------------------*/
1749 /* genDjnz - generate decrement & jump if not zero instrucion      */
1750 /*-----------------------------------------------------------------*/
1751 static bool genDjnz (iCode * ic, iCode * ifx) {
1752   symbol *lbl, *lbl1;
1753
1754   if (!ifx)
1755     return 0;
1756
1757   /* if the if condition has a false label
1758      then we cannot save */
1759   if (IC_FALSE (ifx))
1760     return 0;
1761
1762   /* if the minus is not of the form
1763      a = a - 1 */
1764   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1765       !IS_OP_LITERAL (IC_RIGHT (ic)))
1766     return 0;
1767
1768   if (operandLitValue (IC_RIGHT (ic)) != 1)
1769     return 0;
1770
1771   /* if the size of this greater than two then no
1772      saving */
1773   if (getSize (operandType (IC_RESULT (ic))) > 2)
1774     return 0;
1775
1776   printIc ("genDjnz", ic, 1,1,1);
1777
1778   /* otherwise we can save BIG */
1779   lbl = newiTempLabel (NULL);
1780   lbl1 = newiTempLabel (NULL);
1781
1782   aopOp (IC_RESULT (ic), FALSE, TRUE);
1783
1784   if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1785     emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1786     emitcode ("br", "%05d$", lbl1->key + 100);
1787     emitcode ("", "%05d$:", lbl->key + 100);
1788     emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1789     emitcode ("", "%05d$:", lbl1->key + 100);
1790     return TRUE;
1791   }
1792
1793   bailOut("genDjnz: aop type");
1794   return FALSE;
1795 }
1796
1797 /*-----------------------------------------------------------------*/
1798 /* genReceive - generate code for a receive iCode                  */
1799 /*-----------------------------------------------------------------*/
1800 static void genReceive (iCode * ic) {
1801   printIc ("genReceive", ic, 1,0,0);
1802 }
1803
1804 /*-----------------------------------------------------------------*/
1805 /* gen51Code - generate code for 8051 based controllers            */
1806 /*-----------------------------------------------------------------*/
1807 void genXA51Code (iCode * lic) {
1808   iCode *ic;
1809   int cln = 0;
1810   
1811   lineHead = lineCurr = NULL;
1812   
1813   /* if debug information required */
1814   if (options.debug && currFunc)
1815     {
1816       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1817       _G.debugLine = 1;
1818       if (IS_STATIC (currFunc->etype))
1819         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1820       else
1821         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1822       _G.debugLine = 0;
1823     }
1824   
1825   for (ic = lic; ic; ic = ic->next) {
1826     if (ic->lineno && cln != ic->lineno) {
1827       if (options.debug) {
1828         _G.debugLine = 1;
1829         emitcode ("", "C$%s$%d$%d$%d ==.",
1830                   FileBaseName (ic->filename), ic->lineno,
1831                   ic->level, ic->block);
1832         _G.debugLine = 0;
1833       }
1834       emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
1835                 printCLine(ic->filename, ic->lineno));
1836       cln = ic->lineno;
1837     }
1838     /* if the result is marked as
1839        spilt and rematerializable or code for
1840        this has already been generated then
1841        do nothing */
1842     if (resultRemat (ic) || ic->generated)
1843       continue;
1844     
1845     /* depending on the operation */
1846     switch (ic->op)
1847       {
1848       case '!':
1849         genNot (ic);
1850         break;
1851         
1852       case '~':
1853         genCpl (ic);
1854         break;
1855         
1856       case UNARYMINUS:
1857         genUminus (ic);
1858         break;
1859         
1860       case IPUSH:
1861         genIpush (ic);
1862         break;
1863         
1864       case IPOP:
1865         /* IPOP happens only when trying to restore a
1866            spilt live range, if there is an ifx statement
1867            following this pop then the if statement might
1868            be using some of the registers being popped which
1869            would destory the contents of the register so
1870            we need to check for this condition and handle it */
1871         if (ic->next &&
1872             ic->next->op == IFX &&
1873             regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1874           genIfx (ic->next, ic);
1875         else
1876           genIpop (ic);
1877         break;
1878         
1879       case CALL:
1880         genCall (ic);
1881         break;
1882         
1883       case PCALL:
1884         genPcall (ic);
1885         break;
1886         
1887       case FUNCTION:
1888         genFunction (ic);
1889         break;
1890         
1891       case ENDFUNCTION:
1892         genEndFunction (ic);
1893         break;
1894         
1895       case RETURN:
1896         genRet (ic);
1897         break;
1898         
1899       case LABEL:
1900         genLabel (ic);
1901         break;
1902         
1903       case GOTO:
1904         genGoto (ic);
1905         break;
1906         
1907       case '+':
1908         genPlus (ic);
1909         break;
1910         
1911       case '-':
1912         if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
1913           genMinus (ic);
1914         break;
1915         
1916       case '*':
1917         genMult (ic);
1918         break;
1919         
1920       case '/':
1921         genDiv (ic);
1922         break;
1923         
1924       case '%':
1925         genMod (ic);
1926         break;
1927         
1928       case '>':
1929         genCmpGt (ic);
1930         break;
1931         
1932       case '<':
1933         genCmpLt (ic);
1934         break;
1935         
1936       case LE_OP:
1937         genCmpLe (ic);
1938         break;
1939
1940       case GE_OP:
1941         genCmpGe (ic);
1942         break;
1943
1944       case NE_OP:
1945         genCmpNe (ic);
1946         break;
1947
1948       case EQ_OP:
1949         genCmpEq (ic);
1950         break;
1951         
1952       case AND_OP:
1953         genAndOp (ic);
1954         break;
1955         
1956       case OR_OP:
1957         genOrOp (ic);
1958         break;
1959         
1960       case '^':
1961         genXor (ic, ifxForOp (IC_RESULT (ic), ic));
1962         break;
1963         
1964       case '|':
1965         genOr (ic, ifxForOp (IC_RESULT (ic), ic));
1966         break;
1967         
1968       case BITWISEAND:
1969         genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
1970         break;
1971         
1972       case INLINEASM:
1973         genInline (ic);
1974         break;
1975         
1976       case RRC:
1977         genRRC (ic);
1978         break;
1979         
1980       case RLC:
1981         genRLC (ic);
1982         break;
1983         
1984       case GETHBIT:
1985         genGetHbit (ic);
1986         break;
1987         
1988       case LEFT_OP:
1989         genLeftShift (ic);
1990         break;
1991         
1992       case RIGHT_OP:
1993         genRightShift (ic);
1994         break;
1995         
1996       case GET_VALUE_AT_ADDRESS:
1997         genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_RESULT(ic)))));
1998         break;
1999         
2000       case '=':
2001         if (POINTER_SET (ic))
2002           genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
2003         else
2004           genAssign (ic);
2005         break;
2006         
2007       case IFX:
2008         genIfx (ic, NULL);
2009         break;
2010         
2011       case ADDRESS_OF:
2012         genAddrOf (ic);
2013         break;
2014         
2015       case JUMPTABLE:
2016         genJumpTab (ic);
2017         break;
2018         
2019       case CAST:
2020         genCast (ic);
2021         break;
2022         
2023       case RECEIVE:
2024         genReceive (ic);
2025         break;
2026         
2027       case SEND:
2028         addSet (&_G.sendSet, ic);
2029         break;
2030         
2031       default:
2032         ic = ic;
2033       }
2034   }
2035   
2036   
2037   /* now we are ready to call the
2038      peep hole optimizer */
2039   if (!options.nopeep)
2040     peepHole (&lineHead);
2041   
2042   /* now do the actual printing */
2043   printLine (lineHead, codeOutFile);
2044   return;
2045 }