xa 51, 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   int size;
1568   operand *result=IC_RESULT(ic);
1569   operand *right=IC_RIGHT(ic);
1570   sym_link *ctype=operandType(IC_LEFT(ic));
1571   sym_link *rtype=operandType(IC_RIGHT(ic));
1572   sym_link *etype=getSpec(rtype);
1573   short ptrType, signedness;
1574
1575   printIc ("genCast", ic, 1,1,1);
1576
1577   aopOp(result, TRUE, TRUE);
1578   aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1579   size=AOP_SIZE(result);
1580   
1581   /* if result is a bit */
1582   if (AOP_TYPE(result) == AOP_BIT) {
1583     /* if right is literal, we know what the value is */
1584     if (AOP_TYPE(right) == AOP_LIT) {
1585       if (operandLitValue(right)) {
1586         emitcode ("setb", AOP_NAME(result)[0]);
1587       } else {
1588         emitcode ("clr", AOP_NAME(result)[0]);
1589       }
1590       return;
1591     }
1592     /* if right is also a bit */
1593     if (AOP_TYPE(right) == AOP_BIT) {
1594       emitcode ("mov", "c,%s", AOP_NAME(right));
1595       emitcode ("mov", "%s,c", AOP_NAME(result));
1596       return;
1597     }
1598     /* we need to or */
1599     emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1600     return;
1601   }
1602
1603   /* if right is a bit */
1604   if (AOP_TYPE(right)==AOP_BIT) {
1605     emitcode ("mov", "c,%s", AOP_NAME(right));
1606     emitcode ("mov", "%s,#0", AOP_NAME(result)[0]);
1607     emitcode ("rlc", "%s,#1", AOP_NAME(result)[0]);
1608     if (size>2) {
1609       emitcode ("mov", "%s,#0", AOP_NAME(result)[1]);
1610     }
1611     return;
1612   }
1613
1614   /* if the result is of type pointer */
1615   if (IS_PTR (ctype)) {
1616
1617     if (AOP_SIZE(right)>1) {
1618       emitcode ("mov", "%s,%s",  AOP_NAME(result)[0], AOP_NAME(right)[0]);
1619     } else {
1620       emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
1621       emitcode ("sext", "r1h");
1622       emitcode ("mov", "%s,r1",  AOP_NAME(result)[0]);
1623     }
1624     
1625     /* if pointer to generic pointer */
1626     if (IS_GENPTR (ctype)) {
1627             
1628       if (IS_GENPTR (rtype)) {
1629         bailOut("genCast: gptr -> gptr");
1630       }
1631
1632       if (IS_PTR (rtype)) {
1633         ptrType = DCL_TYPE (rtype);
1634       } else {
1635         /* we have to go by the storage class */
1636         if (!SPEC_OCLS(etype)) {
1637           bailOut("genCast: unknown storage class");
1638         } else {
1639           ptrType = PTR_TYPE (SPEC_OCLS (etype));
1640         }
1641       }
1642       
1643       /* the generic part depends on the type */
1644       switch (ptrType)
1645         {
1646         case POINTER:
1647           emitcode ("mov", "%s,#0x00", AOP_NAME(result)[1]);
1648           break;
1649         case FPOINTER:
1650           emitcode ("mov", "%s,#0x01", AOP_NAME(result)[1]);
1651           break;
1652         case CPOINTER:
1653           emitcode ("mov", "%s,#0x02", AOP_NAME(result)[1]);
1654           break;
1655         default:
1656           bailOut("genCast: got unknown storage class");
1657         }
1658     }
1659     return;
1660   }
1661
1662   /* do we have to sign extend? */
1663   signedness = SPEC_USIGN(rtype);
1664
1665   /* now depending on the size */
1666   switch ((AOP_SIZE(result)<<4) + AOP_SIZE(right))
1667     {
1668     case 0x44:
1669     case 0x33:
1670       emitcode("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1671       // fall through
1672     case 0x24:
1673     case 0x22:
1674     case 0x11:
1675       emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1676       return;
1677     case 0x41:
1678     case 0x21:
1679       emitcode("mov", "r1l,%s", AOP_NAME(right)[0]);
1680       if (signedness) {
1681         emitcode("sext", "r1h");
1682       } else {
1683         emitcode("mov", "rlh,#0");
1684       }
1685       emitcode("mov", "%s,r1", AOP_NAME(result)[0]);
1686       if (size==2)
1687         return;
1688       // fall through: case 0x41
1689       emitcode("sext", AOP_NAME(result)[1]);
1690       return;
1691     case 14:
1692     case 12:
1693       emitcode("mov", "r1,%s", AOP_NAME(right)[0]);
1694       emitcode("mov", "%s,r1l", AOP_NAME(result)[0]);
1695       return;
1696     case 24:
1697       emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1698       return;
1699     }
1700   bailOut("genCast: unknown size");
1701 }
1702
1703
1704 /*-----------------------------------------------------------------*/
1705 /* genDjnz - generate decrement & jump if not zero instrucion      */
1706 /*-----------------------------------------------------------------*/
1707 static bool genDjnz (iCode * ic, iCode * ifx) {
1708   symbol *lbl, *lbl1;
1709
1710   if (!ifx)
1711     return 0;
1712
1713   /* if the if condition has a false label
1714      then we cannot save */
1715   if (IC_FALSE (ifx))
1716     return 0;
1717
1718   /* if the minus is not of the form
1719      a = a - 1 */
1720   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1721       !IS_OP_LITERAL (IC_RIGHT (ic)))
1722     return 0;
1723
1724   if (operandLitValue (IC_RIGHT (ic)) != 1)
1725     return 0;
1726
1727   /* if the size of this greater than two then no
1728      saving */
1729   if (getSize (operandType (IC_RESULT (ic))) > 2)
1730     return 0;
1731
1732   printIc ("genDjnz", ic, 1,1,1);
1733
1734   /* otherwise we can save BIG */
1735   lbl = newiTempLabel (NULL);
1736   lbl1 = newiTempLabel (NULL);
1737
1738   aopOp (IC_RESULT (ic), FALSE, TRUE);
1739
1740   if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1741     emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1742     emitcode ("br", "%05d$", lbl1->key + 100);
1743     emitcode ("", "%05d$:", lbl->key + 100);
1744     emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1745     emitcode ("", "%05d$:", lbl1->key + 100);
1746     return TRUE;
1747   }
1748
1749   bailOut("genDjnz: aop type");
1750   return FALSE;
1751 }
1752
1753 /*-----------------------------------------------------------------*/
1754 /* genReceive - generate code for a receive iCode                  */
1755 /*-----------------------------------------------------------------*/
1756 static void genReceive (iCode * ic) {
1757   printIc ("genReceive", ic, 1,0,0);
1758 }
1759
1760 /*-----------------------------------------------------------------*/
1761 /* gen51Code - generate code for 8051 based controllers            */
1762 /*-----------------------------------------------------------------*/
1763 void genXA51Code (iCode * lic) {
1764   iCode *ic;
1765   int cln = 0;
1766   
1767   lineHead = lineCurr = NULL;
1768   
1769   /* if debug information required */
1770   if (options.debug && currFunc)
1771     {
1772       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1773       _G.debugLine = 1;
1774       if (IS_STATIC (currFunc->etype))
1775         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1776       else
1777         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1778       _G.debugLine = 0;
1779     }
1780   
1781   for (ic = lic; ic; ic = ic->next) {
1782     if (ic->lineno && cln != ic->lineno) {
1783       if (options.debug) {
1784         _G.debugLine = 1;
1785         emitcode ("", "C$%s$%d$%d$%d ==.",
1786                   FileBaseName (ic->filename), ic->lineno,
1787                   ic->level, ic->block);
1788         _G.debugLine = 0;
1789       }
1790       emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
1791                 printCLine(ic->filename, ic->lineno));
1792       cln = ic->lineno;
1793     }
1794     /* if the result is marked as
1795        spilt and rematerializable or code for
1796        this has already been generated then
1797        do nothing */
1798     if (resultRemat (ic) || ic->generated)
1799       continue;
1800     
1801     /* depending on the operation */
1802     switch (ic->op)
1803       {
1804       case '!':
1805         genNot (ic);
1806         break;
1807         
1808       case '~':
1809         genCpl (ic);
1810         break;
1811         
1812       case UNARYMINUS:
1813         genUminus (ic);
1814         break;
1815         
1816       case IPUSH:
1817         genIpush (ic);
1818         break;
1819         
1820       case IPOP:
1821         /* IPOP happens only when trying to restore a
1822            spilt live range, if there is an ifx statement
1823            following this pop then the if statement might
1824            be using some of the registers being popped which
1825            would destory the contents of the register so
1826            we need to check for this condition and handle it */
1827         if (ic->next &&
1828             ic->next->op == IFX &&
1829             regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1830           genIfx (ic->next, ic);
1831         else
1832           genIpop (ic);
1833         break;
1834         
1835       case CALL:
1836         genCall (ic);
1837         break;
1838         
1839       case PCALL:
1840         genPcall (ic);
1841         break;
1842         
1843       case FUNCTION:
1844         genFunction (ic);
1845         break;
1846         
1847       case ENDFUNCTION:
1848         genEndFunction (ic);
1849         break;
1850         
1851       case RETURN:
1852         genRet (ic);
1853         break;
1854         
1855       case LABEL:
1856         genLabel (ic);
1857         break;
1858         
1859       case GOTO:
1860         genGoto (ic);
1861         break;
1862         
1863       case '+':
1864         genPlus (ic);
1865         break;
1866         
1867       case '-':
1868         if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
1869           genMinus (ic);
1870         break;
1871         
1872       case '*':
1873         genMult (ic);
1874         break;
1875         
1876       case '/':
1877         genDiv (ic);
1878         break;
1879         
1880       case '%':
1881         genMod (ic);
1882         break;
1883         
1884       case '>':
1885         genCmpGt (ic);
1886         break;
1887         
1888       case '<':
1889         genCmpLt (ic);
1890         break;
1891         
1892       case LE_OP:
1893         genCmpLe (ic);
1894         break;
1895
1896       case GE_OP:
1897         genCmpGe (ic);
1898         break;
1899
1900       case NE_OP:
1901         genCmpNe (ic);
1902         break;
1903
1904       case EQ_OP:
1905         genCmpEq (ic);
1906         break;
1907         
1908       case AND_OP:
1909         genAndOp (ic);
1910         break;
1911         
1912       case OR_OP:
1913         genOrOp (ic);
1914         break;
1915         
1916       case '^':
1917         genXor (ic, ifxForOp (IC_RESULT (ic), ic));
1918         break;
1919         
1920       case '|':
1921         genOr (ic, ifxForOp (IC_RESULT (ic), ic));
1922         break;
1923         
1924       case BITWISEAND:
1925         genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
1926         break;
1927         
1928       case INLINEASM:
1929         genInline (ic);
1930         break;
1931         
1932       case RRC:
1933         genRRC (ic);
1934         break;
1935         
1936       case RLC:
1937         genRLC (ic);
1938         break;
1939         
1940       case GETHBIT:
1941         genGetHbit (ic);
1942         break;
1943         
1944       case LEFT_OP:
1945         genLeftShift (ic);
1946         break;
1947         
1948       case RIGHT_OP:
1949         genRightShift (ic);
1950         break;
1951         
1952       case GET_VALUE_AT_ADDRESS:
1953         genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_RESULT(ic)))));
1954         break;
1955         
1956       case '=':
1957         if (POINTER_SET (ic))
1958           genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
1959         else
1960           genAssign (ic);
1961         break;
1962         
1963       case IFX:
1964         genIfx (ic, NULL);
1965         break;
1966         
1967       case ADDRESS_OF:
1968         genAddrOf (ic);
1969         break;
1970         
1971       case JUMPTABLE:
1972         genJumpTab (ic);
1973         break;
1974         
1975       case CAST:
1976         genCast (ic);
1977         break;
1978         
1979       case RECEIVE:
1980         genReceive (ic);
1981         break;
1982         
1983       case SEND:
1984         addSet (&_G.sendSet, ic);
1985         break;
1986         
1987       default:
1988         ic = ic;
1989       }
1990   }
1991   
1992   
1993   /* now we are ready to call the
1994      peep hole optimizer */
1995   if (!options.nopeep)
1996     peepHole (&lineHead);
1997   
1998   /* now do the actual printing */
1999   printLine (lineHead, codeOutFile);
2000   return;
2001 }