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