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