3f5075bd183dc55ba4dc0e5975924080447b69fb
[fw/sdcc] / src / z80 / 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   
7          This program is free software; you can redistribute it and/or modify it
8          under the terms of the GNU General Public License as published by the
9          Free Software Foundation; either version 2, or (at your option) any
10          later version.
11          
12          This program is distributed in the hope that it will be useful,
13          but WITHOUT ANY WARRANTY; without even the implied warranty of
14          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15          GNU General Public License for more details.
16          
17          You should have received a copy of the GNU General Public License
18          along with this program; if not, write to the Free Software
19          Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20          
21          In other words, you are welcome to use, share and improve this program.
22          You are forbidden to forbid anyone else to use, share and improve
23          what you give them.   Help stamp out software-hoarding!
24
25 -------------------------------------------------------------------------*/
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <ctype.h>
31 #include "SDCCglobl.h"
32
33 #ifdef HAVE_SYS_ISA_DEFS_H
34 #include <sys/isa_defs.h>
35 #endif
36
37 #include "SDCCast.h"
38 #include "SDCCmem.h"
39 #include "SDCCy.h"
40 #include "SDCChasht.h"
41 #include "SDCCbitv.h"
42 #include "SDCCset.h"
43 #include "SDCCicode.h"
44 #include "SDCClabel.h"
45 #include "SDCCBBlock.h"
46 #include "SDCCloop.h"
47 #include "SDCCcse.h"
48 #include "SDCCcflow.h"
49 #include "SDCCdflow.h"
50 #include "SDCClrange.h"
51 #include "ralloc.h"
52 #include "gen.h"
53 #include "SDCCpeeph.h"
54
55 /* this is the down and dirty file with all kinds of kludgy & hacky
56    stuff. This is what it is all about CODE GENERATION for a specific MCU.
57    Some of the routines may be reusable, will have to see */
58
59 static char *zero = "#0x00";
60 static char *one  = "#0x01";
61 static char *spname ;
62 static char *fReturn[] = {"l", "h", "e", "d" };
63 static char *accUse[] = {"a" };
64 short rbank = -1;
65 short accInUse = 0 ;
66 short inLine = 0;
67 short debugLine = 0;
68 short nregssaved = 0;
69 extern int ptrRegReq ;
70 extern int nRegs;
71 extern FILE *codeOutFile;
72 set *sendSet = NULL;
73 #define RESULTONSTACK(x) \
74                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
75                          IC_RESULT(x)->aop->type == AOP_STK )
76
77 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
78 #define CLRC    emitcode("xor","a,a");
79
80 #define LABEL_STR       "%05d$"
81
82 lineNode *lineHead = NULL;
83 lineNode *lineCurr = NULL;
84
85 unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
86 0xE0, 0xC0, 0x80, 0x00};
87 unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
88 0x07, 0x03, 0x01, 0x00};
89
90 static int _lastStack = 0;
91
92 #define LSB     0
93 #define MSB16   1
94 #define MSB24   2
95 #define MSB32   3
96
97 /* Stack frame:
98
99    IX+4         param0  LH
100    IX+2         ret     LH
101    IX+0         ix      LH
102    IX-2         temp0   LH
103 */
104
105 /*-----------------------------------------------------------------*/
106 /* emitcode - writes the code into a file : for now it is simple    */
107 /*-----------------------------------------------------------------*/
108 void emitcode (const char *inst, const char *fmt, ...)
109 {
110     va_list ap;
111     char lb[MAX_INLINEASM];  
112     char *lbp = lb;
113
114     va_start(ap,fmt);   
115
116     if (*inst != '\0') {
117         sprintf(lb,"%s\t",inst);
118         vsprintf(lb+(strlen(lb)),fmt,ap);
119     }  else 
120         vsprintf(lb,fmt,ap);
121
122     while (isspace(*lbp)) lbp++;
123
124     if (lbp && *lbp) 
125         lineCurr = (lineCurr ?
126                     connectLine(lineCurr,newLineNode(lb)) :
127                     (lineHead = newLineNode(lb)));
128     lineCurr->isInline = inLine;
129     lineCurr->isDebug  = debugLine;
130     va_end(ap);
131 }
132
133 const char *getPairName(asmop *aop)
134 {
135     if (aop->type == AOP_REG) {
136         switch (aop->aopu.aop_reg[0]->rIdx) {
137         case C_IDX:
138             return "bc";
139             break;
140         case E_IDX:
141             return "de";
142             break;
143         case L_IDX:
144             return "hl";
145             break;
146         }
147     }
148     else if (aop->type == AOP_STR) {
149         switch (*aop->aopu.aop_str[0]) {
150         case 'c':
151             return "bc";
152             break;
153         case 'e':
154             return "de";
155             break;
156         case 'l':
157             return "hl";
158             break;
159         }
160     }
161     assert(0);
162     return NULL;
163 }
164
165 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
166 bool isPair(asmop *aop)
167 {
168     if (aop->size == 2) {
169         if (aop->type == AOP_REG) {
170             if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
171                 return TRUE;
172             }
173             if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
174                 return TRUE;
175             }
176             if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
177                 return TRUE;
178             }
179         }
180         if (aop->type == AOP_STR) {
181             if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
182                 return TRUE;
183             }
184             if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
185                 return TRUE;
186             }
187             if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
188                 return TRUE;
189             }
190         }
191     }
192     return FALSE;
193 }
194
195 /** Push a register pair onto the stack */
196 void genPairPush(asmop *aop)
197 {
198     emitcode("push", "%s", getPairName(aop));
199 }
200
201 /*-----------------------------------------------------------------*/
202 /* newAsmop - creates a new asmOp                                  */
203 /*-----------------------------------------------------------------*/
204 static asmop *newAsmop (short type)
205 {
206     asmop *aop;
207
208     ALLOC(aop,sizeof(asmop));
209     aop->type = type;
210     return aop;
211 }
212
213 /*-----------------------------------------------------------------*/
214 /* aopForSym - for a true symbol                                   */
215 /*-----------------------------------------------------------------*/
216 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
217 {
218     asmop *aop;
219     memmap *space= SPEC_OCLS(sym->etype);
220
221     /* if already has one */
222     if (sym->aop)
223         return sym->aop;
224
225     /* Assign depending on the storage class */
226     if (sym->onStack || sym->iaccess) {
227         sym->aop = aop = newAsmop(AOP_STK);
228         aop->size = getSize(sym->type);
229
230         aop->aopu.aop_stk = sym->stack;
231         return aop;
232     }
233
234     /* special case for a function */
235     if (IS_FUNC(sym->type)) {   
236         sym->aop = aop = newAsmop(AOP_IMMD);    
237         ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
238         strcpy(aop->aopu.aop_immd,sym->rname);
239         aop->size = 2;
240         return aop;
241     }
242
243     /* only remaining is far space */
244     /* in which case DPTR gets the address */
245     sym->aop = aop = newAsmop(AOP_IY);
246     emitcode ("ld","iy,#%s", sym->rname);
247     aop->size = getSize(sym->type);
248     aop->aopu.aop_dir = sym->rname;
249
250     /* if it is in code space */
251     if (IN_CODESPACE(space))
252         aop->code = 1;
253
254     return aop;     
255 }
256
257 /*-----------------------------------------------------------------*/
258 /* aopForRemat - rematerialzes an object                           */
259 /*-----------------------------------------------------------------*/
260 static asmop *aopForRemat (symbol *sym)
261 {
262     char *s = buffer;   
263     iCode *ic = sym->rematiCode;
264     asmop *aop = newAsmop(AOP_IMMD);
265
266     while (1) {
267         /* if plus or minus print the right hand side */
268         if (ic->op == '+' || ic->op == '-') {
269             sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
270                     ic->op );
271             s += strlen(s);
272             ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
273             continue ;
274         }
275         /* we reached the end */
276         sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
277         break;
278     }
279
280     ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
281     strcpy(aop->aopu.aop_immd,buffer);    
282     return aop;        
283 }
284
285 /*-----------------------------------------------------------------*/
286 /* regsInCommon - two operands have some registers in common       */
287 /*-----------------------------------------------------------------*/
288 bool regsInCommon (operand *op1, operand *op2)
289 {
290     symbol *sym1, *sym2;
291     int i;
292
293     /* if they have registers in common */
294     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
295         return FALSE ;
296
297     sym1 = OP_SYMBOL(op1);
298     sym2 = OP_SYMBOL(op2);
299
300     if (sym1->nRegs == 0 || sym2->nRegs == 0)
301         return FALSE ;
302
303     for (i = 0 ; i < sym1->nRegs ; i++) {
304         int j;
305         if (!sym1->regs[i])
306             continue ;
307
308         for (j = 0 ; j < sym2->nRegs ;j++ ) {
309             if (!sym2->regs[j])
310                 continue ;
311
312             if (sym2->regs[j] == sym1->regs[i])
313                 return TRUE ;
314         }
315     }
316
317     return FALSE ;
318 }
319
320 /*-----------------------------------------------------------------*/
321 /* operandsEqu - equivalent                                        */
322 /*-----------------------------------------------------------------*/
323 bool operandsEqu ( operand *op1, operand *op2)
324 {
325     symbol *sym1, *sym2;
326
327     /* if they not symbols */
328     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
329         return FALSE;
330
331     sym1 = OP_SYMBOL(op1);
332     sym2 = OP_SYMBOL(op2);
333
334     /* if both are itemps & one is spilt
335        and the other is not then false */
336     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
337         sym1->isspilt != sym2->isspilt )
338         return FALSE ;
339
340     /* if they are the same */
341     if (sym1 == sym2)
342         return TRUE ;
343
344     if (strcmp(sym1->rname,sym2->rname) == 0)
345         return TRUE;
346
347
348     /* if left is a tmp & right is not */
349     if (IS_ITEMP(op1)  && 
350         !IS_ITEMP(op2) &&
351         sym1->isspilt  &&
352         (sym1->usl.spillLoc == sym2))
353         return TRUE;
354
355     if (IS_ITEMP(op2)  && 
356         !IS_ITEMP(op1) &&
357         sym2->isspilt  &&
358         (sym2->usl.spillLoc == sym1))
359         return TRUE ;
360
361     return FALSE ;
362 }
363
364 /*-----------------------------------------------------------------*/
365 /* sameRegs - two asmops have the same registers                   */
366 /*-----------------------------------------------------------------*/
367 bool sameRegs (asmop *aop1, asmop *aop2 )
368 {
369     int i;
370
371     if (aop1 == aop2)
372         return TRUE ;
373
374     if (aop1->type != AOP_REG ||
375         aop2->type != AOP_REG )
376         return FALSE ;
377
378     if (aop1->size != aop2->size)
379         return FALSE ;
380
381     for (i = 0 ; i < aop1->size ; i++ )
382         if (aop1->aopu.aop_reg[i] !=
383             aop2->aopu.aop_reg[i] )
384             return FALSE ;
385
386     return TRUE ;
387 }
388
389 /*-----------------------------------------------------------------*/
390 /* aopOp - allocates an asmop for an operand  :                    */
391 /*-----------------------------------------------------------------*/
392 static void aopOp (operand *op, iCode *ic, bool result)
393 {
394     asmop *aop;
395     symbol *sym;
396     int i;
397
398     if (!op)
399         return ;
400
401     /* if this a literal */
402     if (IS_OP_LITERAL(op)) {
403         op->aop = aop = newAsmop(AOP_LIT);
404         aop->aopu.aop_lit = op->operand.valOperand;
405         aop->size = getSize(operandType(op));
406         return;
407     }
408
409     /* if already has a asmop then continue */
410     if (op->aop)
411         return ;
412
413     /* if the underlying symbol has a aop */
414     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
415         op->aop = OP_SYMBOL(op)->aop;
416         return;
417     }
418
419     /* if this is a true symbol */
420     if (IS_TRUE_SYMOP(op)) {    
421         op->aop = aopForSym(ic,OP_SYMBOL(op),result);
422         return ;
423     }
424
425     /* this is a temporary : this has
426     only four choices :
427     a) register
428     b) spillocation
429     c) rematerialize 
430     d) conditional   
431     e) can be a return use only */
432
433     sym = OP_SYMBOL(op);
434
435     /* if the type is a conditional */
436     if (sym->regType == REG_CND) {
437         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
438         aop->size = 0;
439         return;
440     }
441
442     /* if it is spilt then two situations
443     a) is rematerialize 
444     b) has a spill location */
445     if (sym->isspilt || sym->nRegs == 0) {
446         /* rematerialize it NOW */
447         if (sym->remat) {
448             sym->aop = op->aop = aop =
449                                       aopForRemat (sym);
450             aop->size = getSize(sym->type);
451             return;
452         }
453
454         if (sym->accuse) {
455             int i;
456             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
457             aop->size = getSize(sym->type);
458             for ( i = 0 ; i < 2 ; i++ )
459                 aop->aopu.aop_str[i] = accUse[i];
460             return;  
461         }
462
463         if (sym->ruonly ) {
464             int i;
465             aop = op->aop = sym->aop = newAsmop(AOP_STR);
466             aop->size = getSize(sym->type);
467             for ( i = 0 ; i < 4 ; i++ )
468                 aop->aopu.aop_str[i] = fReturn[i];
469             return;
470         }
471
472         /* else spill location  */
473         sym->aop = op->aop = aop = 
474                                   aopForSym(ic,sym->usl.spillLoc,result);
475         aop->size = getSize(sym->type);
476         return;
477     }
478
479     /* must be in a register */
480     sym->aop = op->aop = aop = newAsmop(AOP_REG);
481     aop->size = sym->nRegs;
482     for ( i = 0 ; i < sym->nRegs ;i++)
483         aop->aopu.aop_reg[i] = sym->regs[i];
484 }
485
486 /*-----------------------------------------------------------------*/
487 /* freeAsmop - free up the asmop given to an operand               */
488 /*----------------------------------------------------------------*/
489 static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
490 {   
491     asmop *aop ;
492
493     if (!op)
494         aop = aaop;
495     else 
496         aop = op->aop;
497
498     if (!aop)
499         return ;
500
501     if (aop->freed)
502         goto dealloc; 
503
504     aop->freed = 1;
505
506     switch (aop->type) {
507     case AOP_STK :
508         break;
509     }
510
511 dealloc:
512     /* all other cases just dealloc */
513     if (op ) {
514         op->aop = NULL;
515         if (IS_SYMOP(op)) {
516             OP_SYMBOL(op)->aop = NULL;    
517             /* if the symbol has a spill */
518             if (SPIL_LOC(op))
519                 SPIL_LOC(op)->aop = NULL;
520         }
521     }
522 }
523
524 char *aopGetWord(asmop *aop, int offset)
525 {
526     char *s = buffer ;
527     char *rs;
528
529     assert(aop->size == 2);
530     assert(offset == 0);
531
532     /* depending on type */
533     switch (aop->type) {
534     case AOP_IMMD:
535         sprintf (s,"#%s",aop->aopu.aop_immd);
536         ALLOC_ATOMIC(rs,strlen(s)+1);
537         strcpy(rs,s);   
538         return rs;
539         
540     case AOP_LIT: {
541         value * val = aop->aopu.aop_lit;
542         /* if it is a float then it gets tricky */
543         /* otherwise it is fairly simple */
544         if (!IS_FLOAT(val->type)) {
545             unsigned long v = floatFromVal(val);
546
547             sprintf(buffer,"#0x%04lx", v);
548             ALLOC_ATOMIC(rs,strlen(buffer)+1);
549             return strcpy (rs,buffer);
550         }
551         assert(0);
552         return NULL;
553     }
554     }
555     return NULL;
556 }
557
558 /*-----------------------------------------------------------------*/
559 /* aopGet - for fetching value of the aop                          */
560 /*-----------------------------------------------------------------*/
561 static char *aopGet (asmop *aop, int offset, bool bit16)
562 {
563     char *s = buffer ;
564     char *rs;
565
566     /* offset is greater than size then zero */
567     if (offset > (aop->size - 1) &&
568         aop->type != AOP_LIT)
569         return zero;
570
571     /* depending on type */
572     switch (aop->type) {
573     case AOP_IMMD:
574         if (bit16) 
575             sprintf (s,"#%s",aop->aopu.aop_immd);
576         else
577             if (offset) {
578                 assert(offset == 1);
579                 sprintf(s,"#>%s",
580                         aop->aopu.aop_immd);
581             }
582             else
583                 sprintf(s,"#<%s",
584                         aop->aopu.aop_immd);
585         ALLOC_ATOMIC(rs,strlen(s)+1);
586         strcpy(rs,s);   
587         return rs;
588         
589     case AOP_DIR:
590         assert(0);
591         emitcode("ld", "a,(%s+%d)", aop->aopu.aop_dir, offset);
592         sprintf(s, "a");
593         ALLOC_ATOMIC(rs,strlen(s)+1);
594         strcpy(rs,s);   
595         return rs;
596         
597     case AOP_REG:
598         return aop->aopu.aop_reg[offset]->name;
599
600     case AOP_IY:
601         sprintf(s,"%d(iy)", offset);
602         ALLOC_ATOMIC(rs,strlen(s)+1);
603         strcpy(rs,s);   
604         return rs;
605
606     case AOP_STK:
607         sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
608         ALLOC_ATOMIC(rs,strlen(s)+1);
609         strcpy(rs,s);   
610         return rs;
611         
612     case AOP_CRY:
613         assert(0);
614         
615     case AOP_ACC:
616         if (!offset) {
617             return "a";
618         }
619         return "#0x00";
620
621     case AOP_LIT:
622         return aopLiteral (aop->aopu.aop_lit,offset);
623         
624     case AOP_STR:
625         aop->coff = offset;
626         return aop->aopu.aop_str[offset];
627     }
628
629     fprintf(stderr, "Type %u\n", aop->type);
630
631     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
632            "aopget got unsupported aop->type");
633     exit(0);
634 }
635
636 bool isRegString(char *s)
637 {
638     if (!strcmp(s, "b") ||
639         !strcmp(s, "c") ||
640         !strcmp(s, "d") ||
641         !strcmp(s, "e") ||
642         !strcmp(s, "a") ||
643         !strcmp(s, "h") ||
644         !strcmp(s, "l"))
645         return TRUE;
646     return FALSE;
647 }
648
649 bool isConstant(char *s)
650 {
651     return  (*s == '#');
652 }
653
654 bool canAssignToPtr(char *s)
655 {
656     if (isRegString(s))
657         return TRUE;
658     if (isConstant(s))
659         return TRUE;
660     return FALSE;
661 }
662
663 /*-----------------------------------------------------------------*/
664 /* aopPut - puts a string for a aop                                */
665 /*-----------------------------------------------------------------*/
666 static void aopPut (asmop *aop, char *s, int offset)
667 {
668     char *d = buffer ;
669
670     if (aop->size && offset > ( aop->size - 1)) {
671         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
672                "aopPut got offset > aop->size");
673         exit(0);
674     }
675
676     /* will assign value to value */
677     /* depending on where it is ofcourse */
678     switch (aop->type) {
679     case AOP_DIR:
680         assert(0);
681         /* Direct.  Hmmm. */
682         emitcode("ld", "a,%s", s);
683         emitcode("ld", "(%s+%d),a", d, offset);
684         break;
685         
686     case AOP_REG:
687         /* Dont bother if it's a ld x,x */
688         if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
689             emitcode("ld","%s,%s",
690                      aop->aopu.aop_reg[offset]->name,s);
691         }
692         break;
693         
694     case AOP_IY:
695         if (!canAssignToPtr(s)) {
696             emitcode("ld", "a,%s", s);
697             emitcode("ld", "%d(iy),a", offset);
698         }
699         else
700             emitcode("ld", "%d(iy),%s", offset, s);
701         break;
702         
703     case AOP_STK:
704         if (!canAssignToPtr(s)) {
705             emitcode("ld", "a,%s", s);
706             emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
707         }
708         else
709             emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
710         break;
711         
712     case AOP_CRY:
713         /* if bit variable */
714         if (!aop->aopu.aop_dir) {
715             emitcode("ld", "a,#0");
716             emitcode("rla", "");
717         } else {
718             /* In bit space but not in C - cant happen */
719             assert(0);
720         }
721         break;
722         
723     case AOP_STR:
724         aop->coff = offset;
725         if (strcmp(aop->aopu.aop_str[offset],s)) {
726             emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
727         }
728         break;
729         
730     case AOP_ACC:
731         aop->coff = offset;
732         if (!offset && (strcmp(s,"acc") == 0))
733             break;
734         if (offset>0) {
735             emitcode("", "; Error aopPut AOP_ACC");
736         }
737         else {
738             if (strcmp(aop->aopu.aop_str[offset],s))
739                 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
740         }
741         break;
742
743     default :
744         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
745                "aopPut got unsupported aop->type");
746         exit(0);    
747     }    
748 }
749
750 #define AOP(op) op->aop
751 #define AOP_TYPE(op) AOP(op)->type
752 #define AOP_SIZE(op) AOP(op)->size
753 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
754
755 /*-----------------------------------------------------------------*/
756 /* getDataSize - get the operand data size                         */
757 /*-----------------------------------------------------------------*/
758 int getDataSize(operand *op)
759 {
760     int size;
761     size = AOP_SIZE(op);
762     if(size == 3) {
763         /* pointer */
764         assert(0);
765     }
766     return size;
767 }
768
769 /*-----------------------------------------------------------------*/
770 /* movLeft2Result - move byte from left to result                  */
771 /*-----------------------------------------------------------------*/
772 static void movLeft2Result (operand *left, int offl,
773                             operand *result, int offr, int sign)
774 {
775     char *l;
776     if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
777         l = aopGet(AOP(left),offl,FALSE);
778
779         if (!sign) {
780             aopPut(AOP(result),l,offr);
781         }
782         else {
783             assert(0);
784         }
785     }
786 }
787
788
789 /** Put Acc into a register set 
790  */
791 void outAcc(operand *result)
792 {
793     int size, offset;
794     size = getDataSize(result);
795     if (size){
796         aopPut(AOP(result),"a",0);
797         size--;
798         offset = 1;
799         /* unsigned or positive */
800         while (size--){
801             aopPut(AOP(result),zero,offset++);
802         }
803     }
804 }
805
806 /** Take the value in carry and put it into a register
807  */
808 void outBitC(operand *result)
809 {
810     /* if the result is bit */
811     if (AOP_TYPE(result) == AOP_CRY) {
812         emitcode("", "; Note: outBitC form 1");
813         aopPut(AOP(result),"blah",0);
814     }
815     else {
816         emitcode("ld", "a,#0");
817         emitcode("rla", "");
818         outAcc(result);
819     }
820 }
821
822 /*-----------------------------------------------------------------*/
823 /* toBoolean - emit code for orl a,operator(sizeop)                */
824 /*-----------------------------------------------------------------*/
825 void toBoolean(operand *oper)
826 {
827     int size = AOP_SIZE(oper);
828     int offset = 0;
829     if (size>1) {
830         emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
831         size--;
832         while (size--) 
833             emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
834     }
835     else {
836         CLRC;
837         emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
838     }
839 }
840
841 /*-----------------------------------------------------------------*/
842 /* genNot - generate code for ! operation                          */
843 /*-----------------------------------------------------------------*/
844 static void genNot (iCode *ic)
845 {
846     link *optype = operandType(IC_LEFT(ic));
847
848     /* assign asmOps to operand & result */
849     aopOp (IC_LEFT(ic),ic,FALSE);
850     aopOp (IC_RESULT(ic),ic,TRUE);
851
852     /* if in bit space then a special case */
853     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
854         assert(0);
855     }
856
857     /* if type float then do float */
858     if (IS_FLOAT(optype)) {
859         assert(0);
860     }
861
862     toBoolean(IC_LEFT(ic));
863
864     /* Not of A:
865        If A == 0, !A = 1
866        else A = 0
867        So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
868     emitcode("sub", "a,#0x01");
869     outBitC(IC_RESULT(ic));
870
871     /* release the aops */
872     freeAsmop(IC_LEFT(ic),NULL,ic);
873     freeAsmop(IC_RESULT(ic),NULL,ic);
874 }
875
876 /*-----------------------------------------------------------------*/
877 /* genCpl - generate code for complement                           */
878 /*-----------------------------------------------------------------*/
879 static void genCpl (iCode *ic)
880 {
881     int offset = 0;
882     int size ;
883
884
885     /* assign asmOps to operand & result */
886     aopOp (IC_LEFT(ic),ic,FALSE);
887     aopOp (IC_RESULT(ic),ic,TRUE);
888
889     /* if both are in bit space then 
890     a special case */
891     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
892         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
893         assert(0);
894     } 
895
896     size = AOP_SIZE(IC_RESULT(ic));
897     while (size--) {
898         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
899         MOVA(l);       
900         emitcode("cpl","");
901         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
902     }
903
904     /* release the aops */
905     freeAsmop(IC_LEFT(ic),NULL,ic);
906     freeAsmop(IC_RESULT(ic),NULL,ic);
907 }
908
909 /*-----------------------------------------------------------------*/
910 /* genUminus - unary minus code generation                         */
911 /*-----------------------------------------------------------------*/
912 static void genUminus (iCode *ic)
913 {
914     assert(0);
915 }
916
917
918 /*-----------------------------------------------------------------*/
919 /* assignResultValue -                                             */
920 /*-----------------------------------------------------------------*/
921 void assignResultValue(operand * oper)
922 {
923     int offset = 0;
924     int size = AOP_SIZE(oper);
925     while (size--) {
926         aopPut(AOP(oper),fReturn[offset],offset);
927         offset++;
928     }
929 }
930
931 /*-----------------------------------------------------------------*/
932 /* genIpush - genrate code for pushing this gets a little complex  */
933 /*-----------------------------------------------------------------*/
934 static void genIpush (iCode *ic)
935 {
936     int size, offset = 0 ;
937     char *l;
938
939
940     /* if this is not a parm push : ie. it is spill push 
941        and spill push is always done on the local stack */
942     if (!ic->parmPush) {
943         /* and the item is spilt then do nothing */
944         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
945             return ;
946
947         aopOp(IC_LEFT(ic),ic,FALSE);
948         size = AOP_SIZE(IC_LEFT(ic));
949         /* push it on the stack */
950         if (isPair(AOP(IC_LEFT(ic)))) {
951             emitcode("push", getPairName(AOP(IC_LEFT(ic))));
952         }
953         else {
954             offset = size;
955             while (size--) {
956                 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
957                 /* Simple for now - load into A and PUSH AF */
958                 emitcode("ld", "a,%s", l);
959                 emitcode("push", "af");
960                 emitcode("inc", "sp");
961             }
962         }
963         return ;        
964     }
965
966     /* Hmmm... what about saving the currently used registers
967        at this point? */
968
969     /* then do the push */
970     aopOp(IC_LEFT(ic),ic,FALSE);
971
972     size = AOP_SIZE(IC_LEFT(ic));
973
974     if (isPair(AOP(IC_LEFT(ic)))) {
975         emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
976     }
977     else {
978         if (size == 2) {
979             char *s = aopGetWord(AOP(IC_LEFT(ic)), 0);
980             if (s) {
981                 emitcode("ld", "hl,%s", s);
982                 emitcode("push", "hl");
983                 goto release;
984             }
985         }
986         offset = size;
987         while (size--) {
988             l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
989             emitcode("ld", "a,%s", l);
990             emitcode("push", "af");
991             emitcode("inc", "sp");
992         }       
993     }
994  release:
995     freeAsmop(IC_LEFT(ic),NULL,ic);
996 }
997
998 /*-----------------------------------------------------------------*/
999 /* genIpop - recover the registers: can happen only for spilling   */
1000 /*-----------------------------------------------------------------*/
1001 static void genIpop (iCode *ic)
1002 {
1003     int size,offset ;
1004
1005
1006     /* if the temp was not pushed then */
1007     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1008         return ;
1009
1010     aopOp(IC_LEFT(ic),ic,FALSE);
1011     size = AOP_SIZE(IC_LEFT(ic));
1012     offset = (size-1);
1013     if (isPair(AOP(IC_LEFT(ic)))) {
1014         emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1015     }
1016     else {
1017         while (size--) {
1018             emitcode("dec", "sp");
1019             emitcode("pop", "hl");
1020             aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1021         }
1022     }
1023
1024     freeAsmop(IC_LEFT(ic),NULL,ic);
1025 }
1026
1027 /** Emit the code for a call statement 
1028  */
1029 static void emitCall (iCode *ic, bool ispcall)
1030 {
1031     /* if caller saves & we have not saved then */
1032     if (!ic->regsSaved) {
1033         /* PENDING */
1034     }
1035
1036     /* if send set is not empty then assign */
1037     if (sendSet) {
1038         iCode *sic ;
1039
1040         for (sic = setFirstItem(sendSet) ; sic ; 
1041              sic = setNextItem(sendSet)) {
1042             int size, offset = 0;
1043             aopOp(IC_LEFT(sic),sic,FALSE);
1044             size = AOP_SIZE(IC_LEFT(sic));
1045             while (size--) {
1046                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1047                                 FALSE);
1048                 if (strcmp(l,fReturn[offset]))
1049                     emitcode("ld","%s,%s",
1050                              fReturn[offset],
1051                              l);
1052                 offset++;
1053             }
1054             freeAsmop (IC_LEFT(sic),NULL,sic);
1055         }
1056         sendSet = NULL;
1057     }
1058
1059     if (ispcall) {
1060         symbol *rlbl = newiTempLabel(NULL);
1061
1062         emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
1063         emitcode("push", "hl");
1064
1065         aopOp(IC_LEFT(ic),ic,FALSE);
1066         emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0,FALSE));
1067         emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1,FALSE));
1068         freeAsmop(IC_LEFT(ic),NULL,ic); 
1069         
1070         emitcode("jp", "(hl)");
1071         emitcode("","%05d$:",(rlbl->key+100));
1072     }
1073     else {
1074         /* make the call */
1075         emitcode("call", "%s", (OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1076                                 OP_SYMBOL(IC_LEFT(ic))->rname :
1077                                 OP_SYMBOL(IC_LEFT(ic))->name));
1078     }
1079
1080     /* if we need assign a result value */
1081     if ((IS_ITEMP(IC_RESULT(ic)) && 
1082          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1083           OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1084         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1085
1086         accInUse++;
1087         aopOp(IC_RESULT(ic),ic,FALSE);
1088         accInUse--;
1089
1090         assignResultValue(IC_RESULT(ic));
1091                 
1092         freeAsmop(IC_RESULT(ic),NULL, ic);
1093     }
1094
1095     /* adjust the stack for parameters if required */
1096     if (IC_LEFT(ic)->parmBytes) {
1097         int i = IC_LEFT(ic)->parmBytes;
1098         /* PENDING: do better */
1099         while (i>1) {
1100             emitcode("pop", "hl");
1101             i-=2;
1102         }
1103         if (i) 
1104             emitcode("inc", "sp");
1105     }
1106
1107 }
1108
1109 /*-----------------------------------------------------------------*/
1110 /* genCall - generates a call statement                            */
1111 /*-----------------------------------------------------------------*/
1112 static void genCall (iCode *ic)
1113 {
1114     emitCall(ic, FALSE);
1115 }
1116
1117 /*-----------------------------------------------------------------*/
1118 /* genPcall - generates a call by pointer statement                */
1119 /*-----------------------------------------------------------------*/
1120 static void genPcall (iCode *ic)
1121 {
1122     emitCall(ic, TRUE);
1123 }
1124
1125 /*-----------------------------------------------------------------*/
1126 /* resultRemat - result  is rematerializable                       */
1127 /*-----------------------------------------------------------------*/
1128 static int resultRemat (iCode *ic)
1129 {
1130     if (SKIP_IC(ic) || ic->op == IFX)
1131         return 0;
1132
1133     if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1134         symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1135         if (sym->remat && !POINTER_SET(ic)) 
1136             return 1;
1137     }
1138
1139     return 0;
1140 }
1141
1142 /*-----------------------------------------------------------------*/
1143 /* genFunction - generated code for function entry                 */
1144 /*-----------------------------------------------------------------*/
1145 static void genFunction (iCode *ic)
1146 {
1147     symbol *sym;
1148     link *fetype;
1149
1150     nregssaved = 0;
1151     /* create the function header */
1152     emitcode(";","-----------------------------------------");
1153     emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1154     emitcode(";","-----------------------------------------");
1155
1156     emitcode("","%s:",sym->rname);
1157     fetype = getSpec(operandType(IC_LEFT(ic)));
1158
1159     /* if critical function then turn interrupts off */
1160     if (SPEC_CRTCL(fetype))
1161         emitcode("di","");
1162
1163     /* if this is an interrupt service routine then
1164     save acc, b, dpl, dph  */
1165     if (IS_ISR(sym->etype)) {
1166         emitcode("push", "af");
1167         emitcode("push", "bc");
1168         emitcode("push", "de");
1169         emitcode("push", "hl");
1170     }
1171     /* PENDING: callee-save etc */
1172
1173     /* adjust the stack for the function */
1174     emitcode("push", "de"); 
1175     emitcode("push", "bc");
1176     emitcode("push", "ix");
1177     emitcode("ld", "ix,#0");
1178     emitcode("add", "ix,sp");
1179
1180     _lastStack = sym->stack;
1181
1182     if (sym->stack) {
1183         emitcode("ld", "hl,#-%d", sym->stack);
1184         emitcode("add", "hl,sp");
1185         emitcode("ld", "sp,hl");
1186     }    
1187 }
1188
1189 /*-----------------------------------------------------------------*/
1190 /* genEndFunction - generates epilogue for functions               */
1191 /*-----------------------------------------------------------------*/
1192 static void genEndFunction (iCode *ic)
1193 {
1194     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1195
1196     if (IS_ISR(sym->etype)) {
1197         assert(0);
1198     }
1199     else {
1200         if (SPEC_CRTCL(sym->etype))
1201             emitcode("ei", "");
1202         
1203         /* PENDING: calleeSave */
1204
1205         /* if debug then send end of function */
1206         if (options.debug && currFunc) { 
1207             debugLine = 1;
1208             emitcode("","C$%s$%d$%d$%d ==.",
1209                      ic->filename,currFunc->lastLine,
1210                      ic->level,ic->block); 
1211             if (IS_STATIC(currFunc->etype))         
1212                 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
1213             else
1214                 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1215             debugLine = 0;
1216         }
1217         emitcode("ld", "sp,ix");
1218         emitcode("pop", "ix");
1219         emitcode("pop", "bc");
1220         emitcode("pop", "de");
1221         emitcode("ret", "");
1222     }
1223
1224 }
1225
1226 /*-----------------------------------------------------------------*/
1227 /* genRet - generate code for return statement                     */
1228 /*-----------------------------------------------------------------*/
1229 static void genRet (iCode *ic)
1230 {
1231     char *l;
1232     /* Errk.  This is a hack until I can figure out how
1233        to cause dehl to spill on a call */
1234     int size,offset = 0;
1235     
1236     /* if we have no return value then
1237        just generate the "ret" */
1238     if (!IC_LEFT(ic)) 
1239         goto jumpret;       
1240     
1241     /* we have something to return then
1242        move the return value into place */
1243     aopOp(IC_LEFT(ic),ic,FALSE);
1244     size = AOP_SIZE(IC_LEFT(ic));
1245     
1246     if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1247             emitcode("ld", "hl,%s", l);
1248     }
1249     else {
1250         while (size--) {
1251             l = aopGet(AOP(IC_LEFT(ic)),offset,
1252                        FALSE);
1253             if (strcmp(fReturn[offset],l))
1254                 emitcode("ld","%s,%s",fReturn[offset++],l);
1255         }
1256     }
1257     freeAsmop (IC_LEFT(ic),NULL,ic);
1258     
1259  jumpret:
1260         /* generate a jump to the return label
1261            if the next is not the return statement */
1262     if (!(ic->next && ic->next->op == LABEL &&
1263           IC_LABEL(ic->next) == returnLabel))
1264         
1265         emitcode("jp",  LABEL_STR ,(returnLabel->key+100));
1266 }
1267
1268 /*-----------------------------------------------------------------*/
1269 /* genLabel - generates a label                                    */
1270 /*-----------------------------------------------------------------*/
1271 static void genLabel (iCode *ic)
1272 {
1273     /* special case never generate */
1274     if (IC_LABEL(ic) == entryLabel)
1275         return ;
1276
1277     emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100));
1278 }
1279
1280 /*-----------------------------------------------------------------*/
1281 /* genGoto - generates a ljmp                                      */
1282 /*-----------------------------------------------------------------*/
1283 static void genGoto (iCode *ic)
1284 {
1285     emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
1286 }
1287
1288 /*-----------------------------------------------------------------*/
1289 /* genPlusIncr :- does addition with increment if possible         */
1290 /*-----------------------------------------------------------------*/
1291 static bool genPlusIncr (iCode *ic)
1292 {
1293     unsigned int icount ;
1294     unsigned int size = getDataSize(IC_RESULT(ic));
1295     
1296     /* will try to generate an increment */
1297     /* if the right side is not a literal 
1298        we cannot */
1299     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1300         return FALSE;
1301     
1302     /* if the literal value of the right hand side
1303        is greater than 4 then it is not worth it */
1304     if ((icount =  floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
1305         return FALSE ;
1306
1307     /* Inc a pair */
1308     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1309         isPair(AOP(IC_RESULT(ic)))) {
1310         while (icount--) {
1311             emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1312         }
1313         return TRUE;
1314     }
1315     /* if increment 16 bits in register */
1316     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1317         (size > 1) &&
1318         (icount == 1)) {
1319         symbol *tlbl = newiTempLabel(NULL);
1320         emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1321         emitcode("jp", "nz," LABEL_STR ,tlbl->key+100);
1322     
1323         emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1324         if(size == 4) {
1325             assert(0);
1326         }
1327         emitcode("", LABEL_STR ":",tlbl->key+100);
1328         return TRUE;
1329     }
1330
1331     /* If result is a pair */
1332     if (isPair(AOP(IC_RESULT(ic)))) {
1333         movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1334         movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1335         while (icount--)
1336             emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1337         return TRUE;
1338     }
1339
1340     /* if the sizes are greater than 1 then we cannot */
1341     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1342         AOP_SIZE(IC_LEFT(ic)) > 1   )
1343         return FALSE ;
1344     
1345     /* we can if the aops of the left & result match or
1346        if they are in registers and the registers are the
1347        same */
1348     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1349         while (icount--)
1350             emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1351         
1352         return TRUE ;
1353     }
1354     
1355     return FALSE ;
1356 }
1357
1358 /*-----------------------------------------------------------------*/
1359 /* outBitAcc - output a bit in acc                                 */
1360 /*-----------------------------------------------------------------*/
1361 void outBitAcc(operand *result)
1362 {
1363     symbol *tlbl = newiTempLabel(NULL);
1364     /* if the result is a bit */
1365     if (AOP_TYPE(result) == AOP_CRY){
1366         assert(0);
1367     }
1368     else {
1369         emitcode("jp","z," LABEL_STR ,tlbl->key+100);
1370         emitcode("ld","a,%s",one);
1371         emitcode("", LABEL_STR ":",tlbl->key+100);
1372         outAcc(result);
1373     }
1374 }
1375
1376 /*-----------------------------------------------------------------*/
1377 /* genPlus - generates code for addition                           */
1378 /*-----------------------------------------------------------------*/
1379 static void genPlus (iCode *ic)
1380 {
1381     int size, offset = 0;
1382
1383     /* special cases :- */
1384
1385     aopOp (IC_LEFT(ic),ic,FALSE);
1386     aopOp (IC_RIGHT(ic),ic,FALSE);
1387     aopOp (IC_RESULT(ic),ic,TRUE);
1388
1389     /* Swap the left and right operands if:
1390
1391        if literal, literal on the right or
1392        if left requires ACC or right is already
1393        in ACC */
1394
1395     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1396         (AOP_NEEDSACC(IC_LEFT(ic))) ||
1397         AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1398         operand *t = IC_RIGHT(ic);
1399         IC_RIGHT(ic) = IC_LEFT(ic);
1400         IC_LEFT(ic) = t;
1401     }
1402
1403     /* if both left & right are in bit
1404     space */
1405     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1406         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1407         /* Cant happen */
1408         assert(0);
1409     }
1410
1411     /* if left in bit space & right literal */
1412     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1413         AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1414         /* Can happen I guess */
1415         assert(0);
1416     }
1417
1418     /* if I can do an increment instead
1419     of add then GOOD for ME */
1420     if (genPlusIncr (ic) == TRUE)
1421         goto release;   
1422
1423     size = getDataSize(IC_RESULT(ic));
1424
1425     while(size--) {
1426         if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1427             MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1428             if(offset == 0)
1429                 emitcode("add","a,%s",
1430                          aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1431             else
1432                 emitcode("adc","a,%s",
1433                          aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1434         } else {
1435             MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1436             if(offset == 0)
1437                 emitcode("add","a,%s",
1438                          aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1439             else
1440                 emitcode("adc","a,%s",
1441                          aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1442         }
1443         aopPut(AOP(IC_RESULT(ic)),"a",offset++);      
1444     }
1445
1446     /* Some kind of pointer arith. */
1447     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
1448         AOP_SIZE(IC_LEFT(ic)) == 3   &&
1449         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1450         assert(0);
1451
1452      if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
1453         AOP_SIZE(IC_RIGHT(ic)) == 3   &&
1454         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1455          assert(0);
1456
1457    
1458 release:
1459     freeAsmop(IC_LEFT(ic),NULL,ic);
1460     freeAsmop(IC_RIGHT(ic),NULL,ic);
1461     freeAsmop(IC_RESULT(ic),NULL,ic);
1462     
1463 }
1464
1465 /*-----------------------------------------------------------------*/
1466 /* genMinusDec :- does subtraction with deccrement if possible     */
1467 /*-----------------------------------------------------------------*/
1468 static bool genMinusDec (iCode *ic)
1469 {
1470     unsigned int icount ;
1471     unsigned int size = getDataSize(IC_RESULT(ic));
1472
1473     /* will try to generate an increment */
1474     /* if the right side is not a literal we cannot */
1475     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1476         return FALSE ;
1477
1478     /* if the literal value of the right hand side
1479     is greater than 4 then it is not worth it */
1480     if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1481         return FALSE;
1482
1483     size = getDataSize(IC_RESULT(ic));
1484     /* if decrement 16 bits in register */
1485     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1486         (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1487         while (icount--)
1488             emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1489         return TRUE;
1490     }
1491
1492     /* If result is a pair */
1493     if (isPair(AOP(IC_RESULT(ic)))) {
1494         movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1495         movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1496         while (icount--)
1497             emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1498         return TRUE;
1499     }
1500
1501     /* if the sizes are greater than 1 then we cannot */
1502     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1503         AOP_SIZE(IC_LEFT(ic)) > 1   )
1504         return FALSE ;
1505
1506     /* we can if the aops of the left & result match or if they are in
1507        registers and the registers are the same */
1508     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1509         while (icount--) 
1510             emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
1511         return TRUE ;
1512     }
1513
1514     return FALSE ;
1515 }
1516
1517 /*-----------------------------------------------------------------*/
1518 /* genMinus - generates code for subtraction                       */
1519 /*-----------------------------------------------------------------*/
1520 static void genMinus (iCode *ic)
1521 {
1522     int size, offset = 0;
1523     unsigned long lit = 0L;
1524
1525     aopOp (IC_LEFT(ic),ic,FALSE);
1526     aopOp (IC_RIGHT(ic),ic,FALSE);
1527     aopOp (IC_RESULT(ic),ic,TRUE);
1528
1529     /* special cases :- */
1530     /* if both left & right are in bit space */
1531     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1532         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1533         assert(0);
1534         goto release ;
1535     }
1536
1537     /* if I can do an decrement instead of subtract then GOOD for ME */
1538     if (genMinusDec (ic) == TRUE)
1539         goto release;   
1540
1541     size = getDataSize(IC_RESULT(ic));   
1542
1543     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
1544         CLRC;
1545     }
1546     else{
1547         lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1548         lit = - (long)lit;
1549     }
1550
1551
1552     /* if literal, add a,#-lit, else normal subb */
1553     while (size--) {
1554         MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));    
1555         if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)  
1556             emitcode("sbc","a,%s",
1557                      aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1558         else{
1559             /* first add without previous c */
1560             if (!offset)
1561                 emitcode("add","a,#0x%02x",
1562                          (unsigned int)(lit & 0x0FFL));
1563             else
1564                 emitcode("adc","a,#0x%02x",
1565                          (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1566         }
1567         aopPut(AOP(IC_RESULT(ic)),"a",offset++);      
1568     }
1569     
1570     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
1571         AOP_SIZE(IC_LEFT(ic)) == 3   &&
1572         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1573         assert(0);
1574
1575 release:
1576     freeAsmop(IC_LEFT(ic),NULL,ic);
1577     freeAsmop(IC_RIGHT(ic),NULL,ic);
1578     freeAsmop(IC_RESULT(ic),NULL,ic);
1579 }
1580
1581 /*-----------------------------------------------------------------*/
1582 /* genMult - generates code for multiplication                     */
1583 /*-----------------------------------------------------------------*/
1584 static void genMult (iCode *ic)
1585 {
1586     /* Shouldn't occur - all done through function calls */
1587     assert(0);
1588 }
1589
1590 /*-----------------------------------------------------------------*/
1591 /* genDiv - generates code for division                            */
1592 /*-----------------------------------------------------------------*/
1593 static void genDiv (iCode *ic)
1594 {
1595     /* Shouldn't occur - all done through function calls */
1596     assert(0);
1597 }
1598
1599 /*-----------------------------------------------------------------*/
1600 /* genMod - generates code for division                            */
1601 /*-----------------------------------------------------------------*/
1602 static void genMod (iCode *ic)
1603 {
1604     /* Shouldn't occur - all done through function calls */
1605     assert(0);
1606 }
1607
1608 /*-----------------------------------------------------------------*/
1609 /* genIfxJump :- will create a jump depending on the ifx           */
1610 /*-----------------------------------------------------------------*/
1611 static void genIfxJump (iCode *ic, char *jval)
1612 {
1613     symbol *jlbl ;
1614     const char *inst;
1615
1616     /* if true label then we jump if condition
1617     supplied is true */
1618     if ( IC_TRUE(ic) ) {
1619         jlbl = IC_TRUE(ic);
1620         if (!strcmp(jval, "a")) {
1621             inst = "nz";
1622         }
1623         else if (!strcmp(jval, "c")) {
1624             inst = "c";
1625         }
1626         else {
1627             /* The buffer contains the bit on A that we should test */
1628             inst = "nz";
1629         }
1630     }
1631     else {
1632         /* false label is present */
1633         jlbl = IC_FALSE(ic) ;
1634         if (!strcmp(jval, "a")) {
1635             inst = "z";
1636         }
1637         else if (!strcmp(jval, "c")) {
1638             inst = "nc";
1639         }
1640         else {
1641             /* The buffer contains the bit on A that we should test */
1642             inst = "z";
1643         }
1644     }
1645     /* Z80 can do a conditional long jump */
1646     if (!strcmp(jval, "a")) {
1647         emitcode("or", "a,a");
1648     }
1649     else if (!strcmp(jval, "c")) {
1650     }
1651     else {
1652         emitcode("bit", "%s,a", jval);
1653     }
1654     emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
1655
1656     /* mark the icode as generated */
1657     ic->generated = 1;
1658 }
1659
1660 /** Generic compare for > or <
1661  */
1662 static void genCmp (operand *left,operand *right,
1663                     operand *result, iCode *ifx, int sign)
1664 {
1665     int size, offset = 0 ;
1666     unsigned long lit = 0L;
1667
1668     /* if left & right are bit variables */
1669     if (AOP_TYPE(left) == AOP_CRY &&
1670         AOP_TYPE(right) == AOP_CRY ) {
1671         /* Cant happen on the Z80 */
1672         assert(0);
1673     } else {
1674         /* subtract right from left if at the
1675         end the carry flag is set then we know that
1676         left is greater than right */
1677         size = max(AOP_SIZE(left),AOP_SIZE(right));
1678
1679         /* if unsigned char cmp with lit, just compare */
1680         if((size == 1) && !sign &&
1681            (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
1682             emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
1683             emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
1684         } 
1685         else {
1686             if(AOP_TYPE(right) == AOP_LIT) {
1687                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1688                 /* optimize if(x < 0) or if(x >= 0) */
1689                 if (lit == 0L){
1690                     if (!sign) {
1691                         /* No sign so it's always false */
1692                         CLRC;
1693                     }
1694                     else{
1695                         /* Just load in the top most bit */
1696                         MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
1697                         if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
1698                             assert(0);
1699                             genIfxJump (ifx,"acc.7");
1700                             return;
1701                         }
1702                         else    
1703                             emitcode("rlc","a");
1704                     }
1705                     goto release;
1706                 }
1707             }
1708             while (size--) {
1709                 /* Do a long subtract */
1710                 MOVA(aopGet(AOP(left),offset,FALSE));
1711                 if (sign && size == 0) {
1712                     /* Case where it's signed and we've hit the end */
1713                     assert(0);
1714                 } else {
1715                     /* Subtract through, propagating the carry */
1716                     if (offset==0) {
1717                         emitcode("sub","a,%s",aopGet(AOP(right),offset++,FALSE));
1718                     }
1719                     else
1720                         emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
1721                 }
1722             }
1723         }
1724     }
1725
1726 release:
1727     if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
1728         outBitC(result);
1729     } else {
1730         /* if the result is used in the next
1731         ifx conditional branch then generate
1732         code a little differently */
1733         if (ifx )
1734             genIfxJump (ifx,"c");
1735         else
1736             outBitC(result);
1737         /* leave the result in acc */
1738     }
1739 }
1740
1741 /*-----------------------------------------------------------------*/
1742 /* genCmpGt :- greater than comparison                             */
1743 /*-----------------------------------------------------------------*/
1744 static void genCmpGt (iCode *ic, iCode *ifx)
1745 {
1746     operand *left, *right, *result;
1747     link *letype , *retype;
1748     int sign ;
1749
1750     left = IC_LEFT(ic);
1751     right= IC_RIGHT(ic);
1752     result = IC_RESULT(ic);
1753
1754     letype = getSpec(operandType(left));
1755     retype =getSpec(operandType(right));
1756     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1757     /* assign the amsops */
1758     aopOp (left,ic,FALSE);
1759     aopOp (right,ic,FALSE);
1760     aopOp (result,ic,TRUE);
1761
1762     genCmp(right, left, result, ifx, sign);
1763
1764     freeAsmop(left,NULL,ic);
1765     freeAsmop(right,NULL,ic);
1766     freeAsmop(result,NULL,ic);
1767 }
1768
1769 /*-----------------------------------------------------------------*/
1770 /* genCmpLt - less than comparisons                                */
1771 /*-----------------------------------------------------------------*/
1772 static void genCmpLt (iCode *ic, iCode *ifx)
1773 {
1774     operand *left, *right, *result;
1775     link *letype , *retype;
1776     int sign ;
1777
1778     left = IC_LEFT(ic);
1779     right= IC_RIGHT(ic);
1780     result = IC_RESULT(ic);
1781
1782     letype = getSpec(operandType(left));
1783     retype =getSpec(operandType(right));
1784     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1785
1786     /* assign the amsops */
1787     aopOp (left,ic,FALSE);
1788     aopOp (right,ic,FALSE);
1789     aopOp (result,ic,TRUE);
1790
1791     genCmp(left, right, result, ifx, sign);
1792
1793     freeAsmop(left,NULL,ic);
1794     freeAsmop(right,NULL,ic);
1795     freeAsmop(result,NULL,ic);
1796 }
1797
1798 /*-----------------------------------------------------------------*/
1799 /* gencjneshort - compare and jump if not equal                    */
1800 /*-----------------------------------------------------------------*/
1801 static void gencjneshort(operand *left, operand *right, symbol *lbl)
1802 {
1803     int size = max(AOP_SIZE(left),AOP_SIZE(right));
1804     int offset = 0;
1805     unsigned long lit = 0L;
1806
1807     /* Swap the left and right if it makes the computation easier */
1808     if (AOP_TYPE(left) == AOP_LIT) {
1809         operand *t = right;
1810         right = left;
1811         left = t;
1812     }
1813
1814     if(AOP_TYPE(right) == AOP_LIT)
1815         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1816
1817     /* if the right side is a literal then anything goes */
1818     if (AOP_TYPE(right) == AOP_LIT &&
1819         AOP_TYPE(left) != AOP_DIR ) {
1820         while (size--) {
1821             emitcode("ld", "a,%s", aopGet(AOP(left),offset,FALSE));
1822             emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
1823             emitcode("jp", "nz," LABEL_STR , lbl->key+100);
1824             offset++;
1825         }
1826     }
1827     /* if the right side is in a register or in direct space or
1828     if the left is a pointer register & right is not */    
1829     else if (AOP_TYPE(right) == AOP_REG ||
1830              AOP_TYPE(right) == AOP_DIR || 
1831              (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
1832         while (size--) {
1833             MOVA(aopGet(AOP(left),offset,FALSE));
1834             if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
1835                ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
1836                 /* PENDING */
1837                 emitcode("jp","nz," LABEL_STR ,lbl->key+100);
1838             else {
1839                 emitcode("cp", "%s", aopGet(AOP(right),offset,FALSE));
1840                 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
1841             }
1842             offset++;
1843         }
1844     } else {
1845         assert(0);
1846     }
1847 }
1848
1849 /*-----------------------------------------------------------------*/
1850 /* gencjne - compare and jump if not equal                         */
1851 /*-----------------------------------------------------------------*/
1852 static void gencjne(operand *left, operand *right, symbol *lbl)
1853 {
1854     symbol *tlbl  = newiTempLabel(NULL);
1855
1856     gencjneshort(left, right, lbl);
1857
1858     /* PENDING: ?? */
1859     emitcode("ld","a,%s",one);
1860     emitcode("jp", LABEL_STR ,tlbl->key+100);
1861     emitcode("", LABEL_STR ":",lbl->key+100);
1862     emitcode("xor","a,a");
1863     emitcode("", LABEL_STR ":",tlbl->key+100);
1864 }
1865
1866 /*-----------------------------------------------------------------*/
1867 /* genCmpEq - generates code for equal to                          */
1868 /*-----------------------------------------------------------------*/
1869 static void genCmpEq (iCode *ic, iCode *ifx)
1870 {
1871     operand *left, *right, *result;
1872
1873     aopOp((left=IC_LEFT(ic)),ic,FALSE);
1874     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
1875     aopOp((result=IC_RESULT(ic)),ic,TRUE);
1876
1877     /* Swap operands if it makes the operation easier. ie if:
1878        1.  Left is a literal.
1879     */
1880     if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
1881         operand *t = IC_RIGHT(ic);
1882         IC_RIGHT(ic) = IC_LEFT(ic);
1883         IC_LEFT(ic) = t;
1884     }
1885
1886     if (ifx && !AOP_SIZE(result)){
1887         symbol *tlbl;
1888         /* if they are both bit variables */
1889         if (AOP_TYPE(left) == AOP_CRY &&
1890             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
1891             assert(0);
1892         } else {
1893             tlbl = newiTempLabel(NULL);
1894             gencjneshort(left, right, tlbl);
1895             if ( IC_TRUE(ifx) ) {
1896                 emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
1897                 emitcode("", LABEL_STR ":",tlbl->key+100);                
1898             } else {
1899                 /* PENDING: do this better */
1900                 symbol *lbl = newiTempLabel(NULL);
1901                 emitcode("jp", LABEL_STR ,lbl->key+100);
1902                 emitcode("", LABEL_STR ":",tlbl->key+100);                
1903                 emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
1904                 emitcode("", LABEL_STR ":",lbl->key+100);             
1905             }
1906         }
1907         /* mark the icode as generated */
1908         ifx->generated = 1;
1909         goto release ;
1910     }
1911
1912     /* if they are both bit variables */
1913     if (AOP_TYPE(left) == AOP_CRY &&
1914         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
1915         assert(0);
1916     } else {
1917         gencjne(left,right,newiTempLabel(NULL));    
1918         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
1919             assert(0);
1920         }
1921         if (ifx) {
1922             genIfxJump(ifx,"a");
1923             goto release;
1924         }
1925         /* if the result is used in an arithmetic operation
1926         then put the result in place */
1927         if (AOP_TYPE(result) != AOP_CRY) {
1928             outAcc(result);
1929         }
1930         /* leave the result in acc */
1931     }
1932
1933 release:
1934     freeAsmop(left,NULL,ic);
1935     freeAsmop(right,NULL,ic);
1936     freeAsmop(result,NULL,ic);
1937 }
1938
1939 /*-----------------------------------------------------------------*/
1940 /* ifxForOp - returns the icode containing the ifx for operand     */
1941 /*-----------------------------------------------------------------*/
1942 static iCode *ifxForOp ( operand *op, iCode *ic )
1943 {
1944     /* if true symbol then needs to be assigned */
1945     if (IS_TRUE_SYMOP(op))
1946         return NULL ;
1947
1948     /* if this has register type condition and
1949     the next instruction is ifx with the same operand
1950     and live to of the operand is upto the ifx only then */
1951     if (ic->next &&
1952         ic->next->op == IFX &&
1953         IC_COND(ic->next)->key == op->key &&
1954         OP_SYMBOL(op)->liveTo <= ic->next->seq )
1955         return ic->next;
1956
1957     return NULL;
1958 }
1959
1960 /*-----------------------------------------------------------------*/
1961 /* genAndOp - for && operation                                     */
1962 /*-----------------------------------------------------------------*/
1963 static void genAndOp (iCode *ic)
1964 {
1965     operand *left,*right, *result;
1966     symbol *tlbl;
1967
1968     /* note here that && operations that are in an if statement are
1969        taken away by backPatchLabels only those used in arthmetic
1970        operations remain */
1971     aopOp((left=IC_LEFT(ic)),ic,FALSE);
1972     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
1973     aopOp((result=IC_RESULT(ic)),ic,FALSE);
1974
1975     /* if both are bit variables */
1976     if (AOP_TYPE(left) == AOP_CRY &&
1977         AOP_TYPE(right) == AOP_CRY ) {
1978         assert(0);
1979     } else {
1980         tlbl = newiTempLabel(NULL);
1981         toBoolean(left);    
1982         emitcode("jp","z," LABEL_STR ,tlbl->key+100);
1983         toBoolean(right);
1984         emitcode("", LABEL_STR ":",tlbl->key+100);
1985         outBitAcc(result);
1986     }
1987
1988     freeAsmop(left,NULL,ic);
1989     freeAsmop(right,NULL,ic);
1990     freeAsmop(result,NULL,ic);
1991 }
1992
1993 /*-----------------------------------------------------------------*/
1994 /* genOrOp - for || operation                                      */
1995 /*-----------------------------------------------------------------*/
1996 static void genOrOp (iCode *ic)
1997 {
1998     operand *left,*right, *result;
1999     symbol *tlbl;
2000
2001     /* note here that || operations that are in an
2002        if statement are taken away by backPatchLabels
2003        only those used in arthmetic operations remain */
2004     aopOp((left=IC_LEFT(ic)),ic,FALSE);
2005     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2006     aopOp((result=IC_RESULT(ic)),ic,FALSE);
2007
2008     /* if both are bit variables */
2009     if (AOP_TYPE(left) == AOP_CRY &&
2010         AOP_TYPE(right) == AOP_CRY ) {
2011         assert(0);
2012     } else {
2013         tlbl = newiTempLabel(NULL);
2014         toBoolean(left);
2015         emitcode("jp","nz," LABEL_STR,tlbl->key+100);
2016         toBoolean(right);
2017         emitcode("", LABEL_STR,tlbl->key+100);
2018         outBitAcc(result);
2019     }
2020
2021     freeAsmop(left,NULL,ic);
2022     freeAsmop(right,NULL,ic);
2023     freeAsmop(result,NULL,ic);
2024 }
2025
2026 /*-----------------------------------------------------------------*/
2027 /* isLiteralBit - test if lit == 2^n                               */
2028 /*-----------------------------------------------------------------*/
2029 int isLiteralBit(unsigned long lit)
2030 {
2031     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2032     0x100L,0x200L,0x400L,0x800L,
2033     0x1000L,0x2000L,0x4000L,0x8000L,
2034     0x10000L,0x20000L,0x40000L,0x80000L,
2035     0x100000L,0x200000L,0x400000L,0x800000L,
2036     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2037     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2038     int idx;
2039     
2040     for(idx = 0; idx < 32; idx++)
2041         if(lit == pw[idx])
2042             return idx+1;
2043     return 0;
2044 }
2045
2046 /*-----------------------------------------------------------------*/
2047 /* genAnd  - code for and                                          */
2048 /*-----------------------------------------------------------------*/
2049 static void genAnd (iCode *ic, iCode *ifx)
2050 {
2051     operand *left, *right, *result;
2052     int size, offset=0;  
2053     unsigned long lit = 0L;
2054     int bytelit = 0;
2055
2056     aopOp((left = IC_LEFT(ic)),ic,FALSE);
2057     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2058     aopOp((result=IC_RESULT(ic)),ic,TRUE);
2059
2060 #ifdef DEBUG_TYPE
2061     emitcode("","; Type res[%d] = l[%d]&r[%d]",
2062              AOP_TYPE(result),
2063              AOP_TYPE(left), AOP_TYPE(right));
2064     emitcode("","; Size res[%d] = l[%d]&r[%d]",
2065              AOP_SIZE(result),
2066              AOP_SIZE(left), AOP_SIZE(right));
2067 #endif
2068
2069     /* if left is a literal & right is not then exchange them */
2070     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2071         AOP_NEEDSACC(left)) {
2072         operand *tmp = right ;
2073         right = left;
2074         left = tmp;
2075     }
2076
2077     /* if result = right then exchange them */
2078     if(sameRegs(AOP(result),AOP(right))){
2079         operand *tmp = right ;
2080         right = left;
2081         left = tmp;
2082     }
2083
2084     /* if right is bit then exchange them */
2085     if (AOP_TYPE(right) == AOP_CRY &&
2086         AOP_TYPE(left) != AOP_CRY){
2087         operand *tmp = right ;
2088         right = left;
2089         left = tmp;
2090     }
2091     if(AOP_TYPE(right) == AOP_LIT)
2092         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2093
2094     size = AOP_SIZE(result);
2095
2096     if (AOP_TYPE(left) == AOP_CRY){
2097         assert(0);
2098         goto release ;
2099     }
2100
2101     // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
2102     // bit = val & 0xZZ     - size = 1, ifx = FALSE -
2103     if((AOP_TYPE(right) == AOP_LIT) &&
2104        (AOP_TYPE(result) == AOP_CRY) &&
2105        (AOP_TYPE(left) != AOP_CRY)) {
2106         int posbit = isLiteralBit(lit);
2107         /* left &  2^n */
2108         if(posbit){
2109             posbit--;
2110             MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2111             // bit = left & 2^n
2112             if(size) {
2113                 assert(0);
2114                 emitcode("mov","c,acc.%d",posbit&0x07);
2115             }
2116             // if(left &  2^n)
2117             else{
2118                 if (ifx) {
2119                     sprintf(buffer, "%d", posbit&0x07);
2120                     genIfxJump(ifx, buffer);
2121                 }
2122                 else {
2123                     assert(0);
2124                 }
2125                 goto release;
2126             }
2127         } else {
2128             symbol *tlbl = newiTempLabel(NULL);
2129             int sizel = AOP_SIZE(left);
2130             if(size) {
2131                 assert(0);
2132                 emitcode("setb","c");
2133             }
2134             while(sizel--){
2135                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2136                     MOVA( aopGet(AOP(left),offset,FALSE));
2137                     // byte ==  2^n ?
2138                     if((posbit = isLiteralBit(bytelit)) != 0) {
2139                         assert(0);
2140                         emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2141                     }
2142                     else{
2143                         if(bytelit != 0x0FFL)
2144                             emitcode("and","a,%s",
2145                                      aopGet(AOP(right),offset,FALSE));
2146                         emitcode("jr","nz, %05d$",tlbl->key+100);
2147                     }
2148                 }
2149                 offset++;
2150             }
2151             // bit = left & literal
2152             if (size){
2153                 emitcode("clr","c");
2154                 emitcode("","%05d$:",tlbl->key+100);
2155             }
2156             // if(left & literal)
2157             else{
2158                 if(ifx)
2159 #if 0
2160                     jmpTrueOrFalse(ifx, tlbl);
2161 #else
2162                 assert(0);
2163 #endif
2164                 goto release ;
2165             }
2166         }
2167         outBitC(result);
2168         goto release ;
2169     }
2170
2171     /* if left is same as result */
2172     if(sameRegs(AOP(result),AOP(left))){
2173         for(;size--; offset++) {
2174             if(AOP_TYPE(right) == AOP_LIT){
2175                 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2176                     continue;
2177                 else {
2178                     if (bytelit == 0)
2179                         aopPut(AOP(result),zero,offset);
2180                     else {
2181                         MOVA(aopGet(AOP(left),offset,FALSE));
2182                         emitcode("and","a,%s",
2183                                  aopGet(AOP(right),offset,FALSE));
2184                         emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2185                     }
2186                 }
2187
2188             } else {
2189                 if (AOP_TYPE(left) == AOP_ACC) {
2190                     assert(0);
2191                 }
2192                 else {
2193                     MOVA(aopGet(AOP(right),offset,FALSE));
2194                     emitcode("and","%s,a",
2195                              aopGet(AOP(left),offset,FALSE));
2196                 }
2197             }
2198         }
2199     } else {
2200         // left & result in different registers
2201         if(AOP_TYPE(result) == AOP_CRY){
2202             assert(0);
2203         } else {
2204             for(;(size--);offset++) {
2205                 // normal case
2206                 // result = left & right
2207                 if(AOP_TYPE(right) == AOP_LIT){
2208                     if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2209                         aopPut(AOP(result),
2210                                aopGet(AOP(left),offset,FALSE),
2211                                offset);
2212                         continue;
2213                     } else if(bytelit == 0){
2214                         aopPut(AOP(result),zero,offset);
2215                         continue;
2216                     }
2217                 }
2218                 // faster than result <- left, anl result,right
2219                 // and better if result is SFR
2220                 if (AOP_TYPE(left) == AOP_ACC) 
2221                     emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2222                 else {
2223                     MOVA(aopGet(AOP(right),offset,FALSE));
2224                     emitcode("and","a,%s",
2225                              aopGet(AOP(left),offset,FALSE));
2226                 }
2227                 aopPut(AOP(result),"a",offset);
2228             }
2229         }
2230
2231     }
2232
2233 release :
2234     freeAsmop(left,NULL,ic);
2235     freeAsmop(right,NULL,ic);
2236     freeAsmop(result,NULL,ic);
2237 }
2238
2239 /*-----------------------------------------------------------------*/
2240 /* genOr  - code for or                                            */
2241 /*-----------------------------------------------------------------*/
2242 static void genOr (iCode *ic, iCode *ifx)
2243 {
2244     operand *left, *right, *result;
2245     int size, offset=0;
2246     unsigned long lit = 0L;
2247
2248     aopOp((left = IC_LEFT(ic)),ic,FALSE);
2249     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2250     aopOp((result=IC_RESULT(ic)),ic,TRUE);
2251
2252 #ifdef DEBUG_TYPE
2253     emitcode("","; Type res[%d] = l[%d]&r[%d]",
2254              AOP_TYPE(result),
2255              AOP_TYPE(left), AOP_TYPE(right));
2256     emitcode("","; Size res[%d] = l[%d]&r[%d]",
2257              AOP_SIZE(result),
2258              AOP_SIZE(left), AOP_SIZE(right));
2259 #endif
2260
2261     /* if left is a literal & right is not then exchange them */
2262     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2263         AOP_NEEDSACC(left)) {
2264         operand *tmp = right ;
2265         right = left;
2266         left = tmp;
2267     }
2268
2269     /* if result = right then exchange them */
2270     if(sameRegs(AOP(result),AOP(right))){
2271         operand *tmp = right ;
2272         right = left;
2273         left = tmp;
2274     }
2275
2276     /* if right is bit then exchange them */
2277     if (AOP_TYPE(right) == AOP_CRY &&
2278         AOP_TYPE(left) != AOP_CRY){
2279         operand *tmp = right ;
2280         right = left;
2281         left = tmp;
2282     }
2283     if(AOP_TYPE(right) == AOP_LIT)
2284         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2285
2286     size = AOP_SIZE(result);
2287
2288     if (AOP_TYPE(left) == AOP_CRY){
2289         assert(0);
2290         goto release ;
2291     }
2292
2293     if((AOP_TYPE(right) == AOP_LIT) &&
2294        (AOP_TYPE(result) == AOP_CRY) &&
2295        (AOP_TYPE(left) != AOP_CRY)){
2296         assert(0);
2297         goto release ;
2298     }
2299
2300     /* if left is same as result */
2301     if(sameRegs(AOP(result),AOP(left))){
2302         for(;size--; offset++) {
2303             if(AOP_TYPE(right) == AOP_LIT){
2304                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2305                     continue;
2306                 else 
2307                     emitcode("or","%s,%s",
2308                              aopGet(AOP(left),offset,FALSE),
2309                              aopGet(AOP(right),offset,FALSE));
2310             } else {
2311                 if (AOP_TYPE(left) == AOP_ACC) 
2312                     emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2313                 else {              
2314                     MOVA(aopGet(AOP(right),offset,FALSE));
2315                     emitcode("or","a,%s",
2316                              aopGet(AOP(left),offset,FALSE));
2317                     aopPut(AOP(result),"a",0);
2318                 }
2319             }
2320         }
2321     } else {
2322         // left & result in different registers
2323         if(AOP_TYPE(result) == AOP_CRY){
2324             assert(0);
2325         } else for(;(size--);offset++){
2326             // normal case
2327             // result = left & right
2328             if(AOP_TYPE(right) == AOP_LIT){
2329                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2330                     aopPut(AOP(result),
2331                            aopGet(AOP(left),offset,FALSE),
2332                            offset);
2333                     continue;
2334                 }
2335             }
2336             // faster than result <- left, anl result,right
2337             // and better if result is SFR
2338             if (AOP_TYPE(left) == AOP_ACC) 
2339                 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2340             else {
2341                 MOVA(aopGet(AOP(right),offset,FALSE));
2342                 emitcode("or","a,%s",
2343                          aopGet(AOP(left),offset,FALSE));
2344                 aopPut(AOP(result),"a",0);
2345             }
2346             aopPut(AOP(result),"a",offset);                     
2347         }
2348     }
2349
2350 release :
2351     freeAsmop(left,NULL,ic);
2352     freeAsmop(right,NULL,ic);
2353     freeAsmop(result,NULL,ic);
2354 }
2355
2356 /*-----------------------------------------------------------------*/
2357 /* genXor - code for xclusive or                                   */
2358 /*-----------------------------------------------------------------*/
2359 static void genXor (iCode *ic, iCode *ifx)
2360 {
2361     operand *left, *right, *result;
2362     int size, offset=0;
2363     unsigned long lit = 0L;
2364
2365     aopOp((left = IC_LEFT(ic)),ic,FALSE);
2366     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2367     aopOp((result=IC_RESULT(ic)),ic,TRUE);
2368
2369     /* if left is a literal & right is not then exchange them */
2370     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2371         AOP_NEEDSACC(left)) {
2372         operand *tmp = right ;
2373         right = left;
2374         left = tmp;
2375     }
2376
2377     /* if result = right then exchange them */
2378     if(sameRegs(AOP(result),AOP(right))){
2379         operand *tmp = right ;
2380         right = left;
2381         left = tmp;
2382     }
2383
2384     /* if right is bit then exchange them */
2385     if (AOP_TYPE(right) == AOP_CRY &&
2386         AOP_TYPE(left) != AOP_CRY){
2387         operand *tmp = right ;
2388         right = left;
2389         left = tmp;
2390     }
2391     if(AOP_TYPE(right) == AOP_LIT)
2392         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2393
2394     size = AOP_SIZE(result);
2395
2396     if (AOP_TYPE(left) == AOP_CRY){
2397         assert(0);
2398         goto release ;
2399     }
2400
2401     if((AOP_TYPE(right) == AOP_LIT) &&
2402        (AOP_TYPE(result) == AOP_CRY) &&
2403        (AOP_TYPE(left) != AOP_CRY)){
2404         assert(0);
2405         goto release ;
2406     }
2407
2408     /* if left is same as result */
2409     if(sameRegs(AOP(result),AOP(left))){
2410         for(;size--; offset++) {
2411             if(AOP_TYPE(right) == AOP_LIT){
2412                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2413                     continue;
2414                 else {
2415                     MOVA(aopGet(AOP(right),offset,FALSE));
2416                     emitcode("xor","a,%s",
2417                              aopGet(AOP(left),offset,FALSE));
2418                     aopPut(AOP(result),"a",0);
2419                 }
2420             } else {
2421                 if (AOP_TYPE(left) == AOP_ACC) 
2422                     emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2423                 else {              
2424                     MOVA(aopGet(AOP(right),offset,FALSE));
2425                     emitcode("xor","a,%s",
2426                              aopGet(AOP(left),offset,FALSE));
2427                     aopPut(AOP(result),"a",0);
2428                 }
2429             }
2430         }
2431     } else {
2432         // left & result in different registers
2433         if(AOP_TYPE(result) == AOP_CRY){
2434             assert(0);
2435         } else for(;(size--);offset++){
2436             // normal case
2437             // result = left & right
2438             if(AOP_TYPE(right) == AOP_LIT){
2439                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2440                     aopPut(AOP(result),
2441                            aopGet(AOP(left),offset,FALSE),
2442                            offset);
2443                     continue;
2444                 }
2445             }
2446             // faster than result <- left, anl result,right
2447             // and better if result is SFR
2448             if (AOP_TYPE(left) == AOP_ACC) 
2449                 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2450             else {
2451                 MOVA(aopGet(AOP(right),offset,FALSE));
2452                 emitcode("xor","a,%s",
2453                          aopGet(AOP(left),offset,FALSE));
2454                 aopPut(AOP(result),"a",0);
2455             }
2456             aopPut(AOP(result),"a",offset);                     
2457         }
2458     }
2459
2460 release :
2461     freeAsmop(left,NULL,ic);
2462     freeAsmop(right,NULL,ic);
2463     freeAsmop(result,NULL,ic);
2464 }
2465
2466 /*-----------------------------------------------------------------*/
2467 /* genInline - write the inline code out                           */
2468 /*-----------------------------------------------------------------*/
2469 static void genInline (iCode *ic)
2470 {
2471     char buffer[MAX_INLINEASM];
2472     char *bp = buffer;
2473     char *bp1= buffer;
2474     
2475     inLine += (!options.asmpeep);
2476     strcpy(buffer,IC_INLINE(ic));
2477
2478     /* emit each line as a code */
2479     while (*bp) {
2480         if (*bp == '\n') {
2481             *bp++ = '\0';
2482             emitcode(bp1,"");
2483             bp1 = bp;
2484         } else {
2485             if (*bp == ':') {
2486                 bp++;
2487                 *bp = '\0';
2488                 bp++;
2489                 emitcode(bp1,"");
2490                 bp1 = bp;
2491             } else
2492                 bp++;
2493         }
2494     }
2495     if (bp1 != bp)
2496         emitcode(bp1,"");
2497     /*     emitcode("",buffer); */
2498     inLine -= (!options.asmpeep);
2499 }
2500
2501 /*-----------------------------------------------------------------*/
2502 /* genRRC - rotate right with carry                                */
2503 /*-----------------------------------------------------------------*/
2504 static void genRRC (iCode *ic)
2505 {
2506     assert(0);
2507 }
2508
2509 /*-----------------------------------------------------------------*/
2510 /* genRLC - generate code for rotate left with carry               */
2511 /*-----------------------------------------------------------------*/
2512 static void genRLC (iCode *ic)
2513 {    
2514     assert(0);
2515 }
2516
2517 /*-----------------------------------------------------------------*/
2518 /* shiftR2Left2Result - shift right two bytes from left to result  */
2519 /*-----------------------------------------------------------------*/
2520 static void shiftR2Left2Result (operand *left, int offl,
2521                                 operand *result, int offr,
2522                                 int shCount, int sign)
2523 {
2524     if(sameRegs(AOP(result), AOP(left)) &&
2525        ((offl + MSB16) == offr)){
2526         assert(0);
2527     } else {
2528         movLeft2Result(left, offl, result, offr, 0);
2529         movLeft2Result(left, offl+1, result, offr+1, 0);
2530     }
2531
2532     if (sign) {
2533         assert(0);
2534     }
2535     else {
2536         /*      if (AOP(result)->type == AOP_REG) {*/
2537             int size = 2;
2538             int offset = 0;
2539             symbol *tlbl , *tlbl1;
2540             char *l;
2541
2542             /* Left is already in result - so now do the shift */
2543             if (shCount>1) {
2544                 emitcode("ld","a,#%u+1", shCount);
2545                 tlbl = newiTempLabel(NULL);
2546                 tlbl1 = newiTempLabel(NULL);
2547                 emitcode("jp", LABEL_STR ,tlbl1->key+100); 
2548                 emitcode("", LABEL_STR ":",tlbl->key+100);    
2549             }
2550
2551             emitcode("or", "a,a");
2552             offset = size;
2553             while (size--) {
2554                 l = aopGet(AOP(result), --offset, FALSE);
2555                 emitcode("rr","%s", l);         
2556             }
2557             if (shCount>1) {
2558                 emitcode("", LABEL_STR ":",tlbl1->key+100);
2559                 emitcode("dec", "a");
2560                 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2561             }
2562     }
2563 }
2564
2565 /*-----------------------------------------------------------------*/
2566 /* shiftL2Left2Result - shift left two bytes from left to result   */
2567 /*-----------------------------------------------------------------*/
2568 static void shiftL2Left2Result (operand *left, int offl,
2569                                 operand *result, int offr, int shCount)
2570 {
2571     if(sameRegs(AOP(result), AOP(left)) &&
2572        ((offl + MSB16) == offr)){
2573         assert(0);
2574     } else {
2575         /* Copy left into result */
2576         movLeft2Result(left,offl, result, offr, 0);
2577     }
2578     if (AOP(result)->type == AOP_REG) {
2579         int size = 2;
2580         int offset = 0;
2581         symbol *tlbl , *tlbl1;
2582         char *l;
2583
2584         /* Left is already in result - so now do the shift */
2585         if (shCount>1) {
2586             emitcode("ld","a,#%u+1", shCount);
2587             tlbl = newiTempLabel(NULL);
2588             tlbl1 = newiTempLabel(NULL);
2589             emitcode("jp", LABEL_STR ,tlbl1->key+100); 
2590             emitcode("", LABEL_STR ":",tlbl->key+100);    
2591         }
2592
2593         emitcode("or", "a,a");
2594         while (size--) {
2595             l = aopGet(AOP(result),offset++,FALSE);
2596             emitcode("rl","%s", l);         
2597         }
2598         if (shCount>1) {
2599             emitcode("", LABEL_STR ":",tlbl1->key+100);
2600             emitcode("dec", "a");
2601             emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2602         }
2603     }
2604     else {
2605         /* PENDING: do something */
2606         assert(0);
2607     }
2608 }
2609
2610 /*-----------------------------------------------------------------*/
2611 /* AccRol - rotate left accumulator by known count                 */
2612 /*-----------------------------------------------------------------*/
2613 static void AccRol (int shCount)
2614 {
2615     shCount &= 0x0007;              // shCount : 0..7
2616     switch(shCount){
2617         case 0 :
2618             break;
2619         case 1 :
2620             emitcode("rl","a");
2621             break;
2622         case 2 :
2623             emitcode("rl","a");
2624             emitcode("rl","a");
2625             break;
2626         case 3 :
2627             emitcode("rl","a");
2628             emitcode("rl","a");
2629             emitcode("rl","a");
2630             break;
2631         case 4 :
2632             emitcode("rl","a");
2633             emitcode("rl","a");
2634             emitcode("rl","a");
2635             emitcode("rl","a");
2636             break;
2637         case 5 :
2638             emitcode("rr","a");
2639             emitcode("rr","a");
2640             emitcode("rr","a");
2641             break;
2642         case 6 :
2643             emitcode("rr","a");
2644             emitcode("rr","a");
2645             break;
2646         case 7 :
2647             emitcode("rr","a");
2648             break;
2649     }
2650 }
2651
2652 /*-----------------------------------------------------------------*/
2653 /* AccLsh - left shift accumulator by known count                  */
2654 /*-----------------------------------------------------------------*/
2655 static void AccLsh (int shCount)
2656 {
2657     if(shCount != 0){
2658         if(shCount == 1)
2659             emitcode("add","a,a");
2660         else 
2661             if(shCount == 2) {
2662             emitcode("add","a,a");
2663             emitcode("add","a,a");
2664         } else {
2665             /* rotate left accumulator */
2666             AccRol(shCount);
2667             /* and kill the lower order bits */
2668             emitcode("and","a,#0x%02x", SLMask[shCount]);
2669         }
2670     }
2671 }
2672
2673 /*-----------------------------------------------------------------*/
2674 /* shiftL1Left2Result - shift left one byte from left to result    */
2675 /*-----------------------------------------------------------------*/
2676 static void shiftL1Left2Result (operand *left, int offl,
2677                                 operand *result, int offr, int shCount)
2678 {
2679     char *l;
2680     l = aopGet(AOP(left),offl,FALSE);
2681     MOVA(l);
2682     /* shift left accumulator */
2683     AccLsh(shCount);
2684     aopPut(AOP(result),"a",offr);
2685 }
2686
2687
2688 /*-----------------------------------------------------------------*/
2689 /* genlshTwo - left shift two bytes by known amount != 0           */
2690 /*-----------------------------------------------------------------*/
2691 static void genlshTwo (operand *result,operand *left, int shCount)
2692 {
2693     int size = AOP_SIZE(result);
2694
2695     assert(size==2);
2696
2697     /* if shCount >= 8 */
2698     if (shCount >= 8) {
2699         shCount -= 8 ;
2700
2701         if (size > 1){
2702             if (shCount) {
2703                 movLeft2Result(left, LSB, result, MSB16, 0);
2704                 aopPut(AOP(result),zero, 0);   
2705                 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
2706             }
2707             else {
2708                 movLeft2Result(left, LSB, result, MSB16, 0);
2709                 aopPut(AOP(result),zero, 0);   
2710             }
2711         }
2712         aopPut(AOP(result),zero,LSB);   
2713     }
2714     /*  1 <= shCount <= 7 */
2715     else {  
2716         if(size == 1) {
2717             assert(0);
2718         }
2719         else {
2720             shiftL2Left2Result(left, LSB, result, LSB, shCount);
2721         }
2722     }
2723 }
2724
2725 /*-----------------------------------------------------------------*/
2726 /* genlshOne - left shift a one byte quantity by known count       */
2727 /*-----------------------------------------------------------------*/
2728 static void genlshOne (operand *result, operand *left, int shCount)
2729 {       
2730     shiftL1Left2Result(left, LSB, result, LSB, shCount);
2731 }
2732
2733 /*-----------------------------------------------------------------*/
2734 /* genLeftShiftLiteral - left shifting by known count              */
2735 /*-----------------------------------------------------------------*/
2736 static void genLeftShiftLiteral (operand *left,
2737                                  operand *right,
2738                                  operand *result,
2739                                  iCode *ic)
2740 {    
2741     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2742     int size;
2743
2744     freeAsmop(right,NULL,ic);
2745
2746     aopOp(left,ic,FALSE);
2747     aopOp(result,ic,FALSE);
2748
2749     size = getSize(operandType(result));
2750
2751 #if VIEW_SIZE
2752     emitcode("; shift left ","result %d, left %d",size,
2753              AOP_SIZE(left));
2754 #endif
2755
2756     /* I suppose that the left size >= result size */
2757     if (shCount == 0) {
2758         assert(0);
2759     }
2760
2761     else if(shCount >= (size * 8))
2762         while(size--)
2763             aopPut(AOP(result),zero,size);
2764     else{
2765         switch (size) {
2766         case 1:
2767             genlshOne (result,left,shCount);
2768             break;
2769         case 2:
2770             genlshTwo (result,left,shCount);
2771             break;
2772         case 4:
2773             assert(0);
2774             break;
2775         default:
2776             assert(0);
2777         }
2778     }
2779     freeAsmop(left,NULL,ic);
2780     freeAsmop(result,NULL,ic);
2781 }
2782
2783 /*-----------------------------------------------------------------*/
2784 /* genLeftShift - generates code for left shifting                 */
2785 /*-----------------------------------------------------------------*/
2786 static void genLeftShift (iCode *ic)
2787 {
2788     int size, offset;
2789     char *l;
2790     symbol *tlbl , *tlbl1;
2791     operand *left,*right, *result;
2792
2793     right = IC_RIGHT(ic);
2794     left  = IC_LEFT(ic);
2795     result = IC_RESULT(ic);
2796
2797     aopOp(right,ic,FALSE);
2798
2799     /* if the shift count is known then do it 
2800     as efficiently as possible */
2801     if (AOP_TYPE(right) == AOP_LIT) {
2802         genLeftShiftLiteral (left,right,result,ic);
2803         return ;
2804     }
2805
2806     /* shift count is unknown then we have to form a loop get the loop
2807        count in B : Note: we take only the lower order byte since
2808        shifting more that 32 bits make no sense anyway, ( the largest
2809        size of an object can be only 32 bits ) */
2810     emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
2811     emitcode("inc","a");
2812     freeAsmop (right,NULL,ic);
2813     aopOp(left,ic,FALSE);
2814     aopOp(result,ic,FALSE);
2815
2816     /* now move the left to the result if they are not the
2817        same */
2818 #if 1
2819     if (!sameRegs(AOP(left),AOP(result))) {
2820
2821         size = AOP_SIZE(result);
2822         offset = 0;
2823         while (size--) {
2824             l = aopGet(AOP(left),offset,FALSE);
2825             aopPut(AOP(result),l,offset);
2826             offset++;
2827         }
2828     }
2829 #else
2830     size = AOP_SIZE(result);
2831     offset = 0;
2832     while (size--) {
2833         l = aopGet(AOP(left),offset,FALSE);
2834         aopPut(AOP(result),l,offset);
2835         offset++;
2836     }
2837 #endif
2838
2839
2840     tlbl = newiTempLabel(NULL);
2841     size = AOP_SIZE(result);
2842     offset = 0 ;   
2843     tlbl1 = newiTempLabel(NULL);
2844
2845     emitcode("jp", LABEL_STR ,tlbl1->key+100); 
2846     emitcode("", LABEL_STR ":",tlbl->key+100);    
2847     l = aopGet(AOP(result),offset,FALSE);
2848     emitcode("or", "a,a");
2849     while (size--) {
2850         l = aopGet(AOP(result),offset++,FALSE);
2851         emitcode("rl","%s", l);         
2852     }
2853     emitcode("", LABEL_STR ":",tlbl1->key+100);
2854     emitcode("dec", "a");
2855     emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2856
2857     freeAsmop(left,NULL,ic);
2858     freeAsmop(result,NULL,ic);
2859 }
2860
2861 /* genlshTwo - left shift two bytes by known amount != 0           */
2862 /*-----------------------------------------------------------------*/
2863 static void genrshOne (operand *result,operand *left, int shCount)
2864 {
2865     /* Errk */
2866     int size = AOP_SIZE(result);
2867     char *l;
2868
2869     assert(size==1);
2870     assert(shCount<8);
2871
2872     l = aopGet(AOP(left),0,FALSE);
2873     if (AOP(result)->type == AOP_REG) {
2874         aopPut(AOP(result), l, 0);
2875         l = aopGet(AOP(result), 0, FALSE);
2876         while (shCount--) 
2877             emitcode("srl", "%s", l);
2878     }
2879     else {
2880         MOVA(l);
2881         while (shCount--) {
2882             emitcode("srl", "a");
2883         }
2884         aopPut(AOP(result),"a",0);
2885     }
2886 }
2887
2888 /*-----------------------------------------------------------------*/
2889 /* AccRsh - right shift accumulator by known count                 */
2890 /*-----------------------------------------------------------------*/
2891 static void AccRsh (int shCount)
2892 {
2893     if(shCount != 0){
2894         if(shCount == 1){
2895             CLRC;
2896             emitcode("rr","a");
2897         } else {
2898             /* rotate right accumulator */
2899             AccRol(8 - shCount);
2900             /* and kill the higher order bits */
2901             emitcode("and","a,#0x%02x", SRMask[shCount]);
2902         }
2903     }
2904 }
2905
2906 /*-----------------------------------------------------------------*/
2907 /* shiftR1Left2Result - shift right one byte from left to result   */
2908 /*-----------------------------------------------------------------*/
2909 static void shiftR1Left2Result (operand *left, int offl,
2910                                 operand *result, int offr,
2911                                 int shCount, int sign)
2912 {
2913     MOVA(aopGet(AOP(left),offl,FALSE));
2914     if (sign) {
2915         assert(0);
2916     }
2917     else {
2918         AccRsh(shCount);
2919     }
2920     aopPut(AOP(result),"a",offr);
2921 }
2922
2923 /*-----------------------------------------------------------------*/
2924 /* genrshTwo - right shift two bytes by known amount != 0          */
2925 /*-----------------------------------------------------------------*/
2926 static void genrshTwo (operand *result,operand *left,
2927                        int shCount, int sign)
2928 {
2929     /* if shCount >= 8 */
2930     if (shCount >= 8) {
2931         shCount -= 8 ;
2932         if (shCount) {
2933             assert(0);
2934             shiftR1Left2Result(left, MSB16, result, LSB,
2935                                shCount, sign);
2936         }
2937         else {
2938             movLeft2Result(left, MSB16, result, LSB, sign);
2939             aopPut(AOP(result),zero,1);
2940         }
2941     }
2942     /*  1 <= shCount <= 7 */
2943     else {
2944         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
2945     }
2946 }
2947
2948 /*-----------------------------------------------------------------*/
2949 /* genRightShiftLiteral - left shifting by known count              */
2950 /*-----------------------------------------------------------------*/
2951 static void genRightShiftLiteral (operand *left,
2952                                  operand *right,
2953                                  operand *result,
2954                                  iCode *ic)
2955 {    
2956     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2957     int size;
2958
2959     freeAsmop(right,NULL,ic);
2960
2961     aopOp(left,ic,FALSE);
2962     aopOp(result,ic,FALSE);
2963
2964     size = getSize(operandType(result));
2965
2966     emitcode("; shift right ","result %d, left %d",size,
2967              AOP_SIZE(left));
2968
2969     /* I suppose that the left size >= result size */
2970     if (shCount == 0) {
2971         assert(0);
2972     }
2973
2974     else if(shCount >= (size * 8))
2975         while(size--)
2976             aopPut(AOP(result),zero,size);
2977     else{
2978         switch (size) {
2979         case 1:
2980             genrshOne(result, left, shCount);
2981             break;
2982         case 2:
2983             /* PENDING: sign support */
2984             genrshTwo(result, left, shCount, FALSE);
2985             break;
2986         case 4:
2987             assert(0);
2988             break;
2989         default:
2990             assert(0);
2991         }
2992     }
2993     freeAsmop(left,NULL,ic);
2994     freeAsmop(result,NULL,ic);
2995 }
2996
2997 /*-----------------------------------------------------------------*/
2998 /* genRightShift - generate code for right shifting                */
2999 /*-----------------------------------------------------------------*/
3000 static void genRightShift (iCode *ic)
3001 {
3002     operand *left,*right, *result;
3003
3004     right = IC_RIGHT(ic);
3005     left  = IC_LEFT(ic);
3006     result = IC_RESULT(ic);
3007
3008     aopOp(right,ic,FALSE);
3009
3010     /* if the shift count is known then do it 
3011     as efficiently as possible */
3012     if (AOP_TYPE(right) == AOP_LIT) {
3013         genRightShiftLiteral (left,right,result,ic);
3014         return ;
3015     }
3016     else {
3017         assert(0);
3018     }
3019 }
3020
3021 /*-----------------------------------------------------------------*/
3022 /* genGenPointerGet - gget value from generic pointer space        */
3023 /*-----------------------------------------------------------------*/
3024 static void genGenPointerGet (operand *left,
3025                               operand *result, iCode *ic)
3026 {
3027     int size, offset ;
3028     link *retype = getSpec(operandType(result));
3029
3030     aopOp(left,ic,FALSE);
3031     aopOp(result,ic,FALSE);
3032
3033     if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
3034         /* Just do it */
3035         emitcode("ld", "a,(%s)", getPairName(AOP(left)));
3036         aopPut(AOP(result),"a", 0);
3037         freeAsmop(left,NULL,ic);
3038         goto release;
3039     }
3040
3041     /* For now we always load into IY */
3042     /* if this is remateriazable */
3043     if (AOP_TYPE(left) == AOP_IMMD)
3044         emitcode("ld","hl,%s",aopGet(AOP(left),0,TRUE));
3045     else { /* we need to get it byte by byte */
3046         emitcode("ld", "l,%s", aopGet(AOP(left), 0, FALSE));
3047         emitcode("ld", "h,%s", aopGet(AOP(left), 1, FALSE));
3048     }
3049     /* so iy now contains the address */
3050     freeAsmop(left,NULL,ic);
3051
3052     /* if bit then unpack */
3053     if (IS_BITVAR(retype)) {
3054         assert(0);
3055     }
3056     else {
3057         size = AOP_SIZE(result);
3058         offset = 0 ;
3059
3060         while (size--) {
3061             /* PENDING: make this better */
3062             if (AOP(result)->type == AOP_REG) {
3063                 aopPut(AOP(result),"(hl)",offset++);
3064             }
3065             else {
3066                 emitcode("ld", "a,(hl)", offset);
3067                 aopPut(AOP(result),"a",offset++);
3068             }
3069             if (size) {
3070                 emitcode("inc", "hl");
3071             }
3072         }
3073     }
3074
3075  release:
3076     freeAsmop(result,NULL,ic);
3077 }
3078
3079 /*-----------------------------------------------------------------*/
3080 /* genPointerGet - generate code for pointer get                   */
3081 /*-----------------------------------------------------------------*/
3082 static void genPointerGet (iCode *ic)
3083 {
3084     operand *left, *result ;
3085     link *type, *etype;
3086
3087     left = IC_LEFT(ic);
3088     result = IC_RESULT(ic) ;
3089
3090     /* depending on the type of pointer we need to
3091     move it to the correct pointer register */
3092     type = operandType(left);
3093     etype = getSpec(type);
3094
3095     genGenPointerGet (left,result,ic);
3096 }
3097
3098 bool isRegOrLit(asmop *aop)
3099 {
3100     if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3101         return TRUE;
3102     return FALSE;
3103 }
3104
3105 /*-----------------------------------------------------------------*/
3106 /* genGenPointerSet - stores the value into a pointer location        */
3107 /*-----------------------------------------------------------------*/
3108 static void genGenPointerSet (operand *right,
3109                               operand *result, iCode *ic)
3110 {    
3111     int size, offset ;
3112     link *retype = getSpec(operandType(right));
3113
3114     aopOp(result,ic,FALSE);
3115     aopOp(right,ic,FALSE);
3116
3117     /* Handle the exceptions first */
3118     if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3119         /* Just do it */
3120         char *l = aopGet(AOP(right), 0, FALSE);
3121         MOVA(l);
3122         emitcode("ld", "(%s),a", getPairName(AOP(result)));
3123         freeAsmop(result,NULL,ic);
3124         goto release;
3125     }
3126         
3127     /* if the operand is already in dptr 
3128        then we do nothing else we move the value to dptr */
3129     if (AOP_TYPE(result) != AOP_STR) {
3130         /* if this is remateriazable */
3131         if (AOP_TYPE(result) == AOP_IMMD) {
3132             emitcode("", "; Error 2");
3133             emitcode("ld", "hl,%s", aopGet(AOP(result), 0, TRUE));
3134         }
3135         else { /* we need to get it byte by byte */
3136             /* PENDING: do this better */
3137             emitcode("ld", "l,%s", aopGet(AOP(result), 0, FALSE));
3138             emitcode("ld", "h,%s", aopGet(AOP(result), 1, FALSE));
3139         }
3140     }
3141     /* so hl know contains the address */
3142     freeAsmop(result,NULL,ic);
3143
3144     /* if bit then unpack */
3145     if (IS_BITVAR(retype)) {
3146         assert(0);
3147     }
3148     else {
3149         size = AOP_SIZE(right);
3150         offset = 0 ;
3151
3152         while (size--) {
3153             char *l = aopGet(AOP(right),offset,FALSE);
3154
3155             if (isRegOrLit(AOP(right))) {
3156                 emitcode("ld", "(hl),%s", l);
3157             }
3158             else {
3159                 MOVA(l);
3160                 emitcode("ld", "(hl),a", offset);
3161             }
3162             if (size) {
3163                 emitcode("inc", "hl");
3164             }
3165             offset++;
3166         }
3167     }
3168     release:
3169     freeAsmop(right,NULL,ic);
3170 }
3171
3172 /*-----------------------------------------------------------------*/
3173 /* genPointerSet - stores the value into a pointer location        */
3174 /*-----------------------------------------------------------------*/
3175 static void genPointerSet (iCode *ic)
3176 {    
3177     operand *right, *result ;
3178     link *type, *etype;
3179
3180     right = IC_RIGHT(ic);
3181     result = IC_RESULT(ic) ;
3182
3183     /* depending on the type of pointer we need to
3184     move it to the correct pointer register */
3185     type = operandType(result);
3186     etype = getSpec(type);
3187     
3188     genGenPointerSet (right,result,ic);
3189 }
3190
3191 /*-----------------------------------------------------------------*/
3192 /* genIfx - generate code for Ifx statement                        */
3193 /*-----------------------------------------------------------------*/
3194 static void genIfx (iCode *ic, iCode *popIc)
3195 {
3196     operand *cond = IC_COND(ic);
3197     int isbit =0;
3198
3199     aopOp(cond,ic,FALSE);
3200
3201     /* get the value into acc */
3202     if (AOP_TYPE(cond) != AOP_CRY)
3203         toBoolean(cond);
3204     else
3205         isbit = 1;
3206     /* the result is now in the accumulator */
3207     freeAsmop(cond,NULL,ic);
3208
3209     /* if there was something to be popped then do it */
3210     if (popIc)
3211         genIpop(popIc);
3212
3213     /* if the condition is  a bit variable */
3214     if (isbit && IS_ITEMP(cond) && 
3215         SPIL_LOC(cond))
3216         genIfxJump(ic,SPIL_LOC(cond)->rname);
3217     else
3218         if (isbit && !IS_ITEMP(cond))
3219             genIfxJump(ic,OP_SYMBOL(cond)->rname);
3220         else
3221             genIfxJump(ic,"a");
3222
3223     ic->generated = 1;
3224 }
3225
3226 /*-----------------------------------------------------------------*/
3227 /* genAddrOf - generates code for address of                       */
3228 /*-----------------------------------------------------------------*/
3229 static void genAddrOf (iCode *ic)
3230 {
3231     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3232
3233     aopOp(IC_RESULT(ic),ic,FALSE);
3234
3235     /* if the operand is on the stack then we 
3236     need to get the stack offset of this
3237     variable */
3238     if (sym->onStack) {
3239         /* if it has an offset  then we need to compute it */
3240         emitcode("push", "de");
3241         emitcode("push", "ix");
3242         emitcode("pop", "hl");
3243         emitcode("ld", "de,#%d", sym->stack);
3244         emitcode("add", "hl,de");
3245         emitcode("pop", "de");
3246     }
3247     else {
3248         emitcode("ld", "hl,#%s", sym->rname);
3249     }
3250     aopPut(AOP(IC_RESULT(ic)), "l", 0);
3251     aopPut(AOP(IC_RESULT(ic)), "h", 1);
3252
3253     freeAsmop(IC_RESULT(ic),NULL,ic);
3254 }
3255
3256 /*-----------------------------------------------------------------*/
3257 /* genAssign - generate code for assignment                        */
3258 /*-----------------------------------------------------------------*/
3259 static void genAssign (iCode *ic)
3260 {
3261     operand *result, *right;
3262     int size, offset ;
3263     unsigned long lit = 0L;
3264
3265     result = IC_RESULT(ic);
3266     right  = IC_RIGHT(ic) ;
3267
3268     /* Dont bother assigning if they are the same */
3269     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3270         emitcode("", "; (operands are equal)");
3271         return;
3272     }
3273
3274     aopOp(right,ic,FALSE);
3275     aopOp(result,ic,TRUE);
3276
3277     /* if they are the same registers */
3278     if (sameRegs(AOP(right),AOP(result))) {
3279         emitcode("", "; (registers are the same)");
3280         goto release;
3281     }
3282
3283     /* if the result is a bit */
3284     if (AOP_TYPE(result) == AOP_CRY) {
3285         assert(0);
3286     }
3287
3288     /* general case */
3289     size = AOP_SIZE(result);
3290     offset = 0;
3291
3292     if(AOP_TYPE(right) == AOP_LIT)
3293         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3294     if((size > 1) &&
3295        (AOP_TYPE(result) != AOP_REG) &&
3296        (AOP_TYPE(right) == AOP_LIT) &&
3297        !IS_FLOAT(operandType(right)) &&
3298        (lit < 256L)){
3299         emitcode("xor","a,a");
3300         /* Work from the top down.
3301            Done this way so that we can use the cached copy of 0
3302            in A for a fast clear */
3303         while (size--) {
3304             if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
3305                 aopPut(AOP(result),"a",size);
3306             else
3307                 aopPut(AOP(result),
3308                        aopGet(AOP(right),size,FALSE),
3309                        size);
3310         }
3311     } else {
3312         while (size--) {
3313             aopPut(AOP(result),
3314                    aopGet(AOP(right),offset,FALSE),
3315                    offset);
3316             offset++;
3317         }
3318     }
3319     
3320 release:
3321     freeAsmop(right,NULL,ic);
3322     freeAsmop(result,NULL,ic);
3323 }   
3324
3325 /*-----------------------------------------------------------------*/
3326 /* genJumpTab - genrates code for jump table                       */
3327 /*-----------------------------------------------------------------*/
3328 static void genJumpTab (iCode *ic)
3329 {
3330     assert(0);
3331 }
3332
3333 /*-----------------------------------------------------------------*/
3334 /* genCast - gen code for casting                                  */
3335 /*-----------------------------------------------------------------*/
3336 static void genCast (iCode *ic)
3337 {
3338     operand *result = IC_RESULT(ic);
3339     link *ctype = operandType(IC_LEFT(ic));
3340     operand *right = IC_RIGHT(ic);
3341     int size, offset ;
3342
3343     /* if they are equivalent then do nothing */
3344     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
3345         return ;
3346
3347     aopOp(right,ic,FALSE) ;
3348     aopOp(result,ic,FALSE);
3349
3350     /* if the result is a bit */
3351     if (AOP_TYPE(result) == AOP_CRY) {
3352         assert(0);
3353     }
3354
3355     /* if they are the same size : or less */
3356     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
3357
3358         /* if they are in the same place */
3359         if (sameRegs(AOP(right),AOP(result)))
3360             goto release;
3361
3362         /* if they in different places then copy */
3363         size = AOP_SIZE(result);
3364         offset = 0 ;
3365         while (size--) {
3366             aopPut(AOP(result),
3367                    aopGet(AOP(right),offset,FALSE),
3368                    offset);
3369             offset++;
3370         }
3371         goto release;
3372     }
3373
3374     /* if the result is of type pointer */
3375     if (IS_PTR(ctype)) {
3376         assert(0);
3377     }
3378     
3379     /* so we now know that the size of destination is greater
3380     than the size of the source */
3381     /* we move to result for the size of source */
3382     size = AOP_SIZE(right);
3383     offset = 0 ;
3384     while (size--) {
3385         aopPut(AOP(result),
3386                aopGet(AOP(right),offset,FALSE),
3387                offset);
3388         offset++;
3389     }
3390
3391     /* now depending on the sign of the destination */
3392     size = AOP_SIZE(result) - AOP_SIZE(right);
3393     /* Unsigned or not an integral type - right fill with zeros */
3394     if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
3395         while (size--)
3396             aopPut(AOP(result),zero,offset++);
3397     } else {
3398         /* we need to extend the sign :{ */
3399         char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
3400                          FALSE);
3401         MOVA(l);
3402         emitcode("", "; genCast: sign extend untested.");
3403         emitcode("rla", "");
3404         emitcode("sbc", "a,a");
3405         while (size--)
3406             aopPut(AOP(result),"a",offset++);   
3407     }
3408
3409 release:
3410     freeAsmop(right, NULL, ic);
3411     freeAsmop(result, NULL, ic);
3412 }
3413
3414 /*-----------------------------------------------------------------*/
3415 /* genReceive - generate code for a receive iCode                  */
3416 /*-----------------------------------------------------------------*/
3417 static void genReceive (iCode *ic)
3418 {    
3419     if (isOperandInFarSpace(IC_RESULT(ic)) && 
3420         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
3421           IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
3422         assert(0);
3423     } else {
3424         accInUse++;
3425         aopOp(IC_RESULT(ic),ic,FALSE);  
3426         accInUse--;
3427         assignResultValue(IC_RESULT(ic));       
3428     }
3429
3430     freeAsmop(IC_RESULT(ic),NULL,ic);
3431 }
3432
3433 /*-----------------------------------------------------------------*/
3434 /* genZ80Code - generate code for Z80 based controllers            */
3435 /*-----------------------------------------------------------------*/
3436 void genZ80Code (iCode *lic)
3437 {
3438     iCode *ic;
3439     int cln = 0;
3440
3441     lineHead = lineCurr = NULL;
3442
3443     /* if debug information required */
3444     if (options.debug && currFunc) { 
3445         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
3446         debugLine = 1;
3447         if (IS_STATIC(currFunc->etype))
3448             emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name); 
3449         else
3450             emitcode("","G$%s$0$0 ==.",currFunc->name);
3451         debugLine = 0;
3452     }
3453     /* stack pointer name */
3454     spname = "sp";
3455     
3456  
3457     for (ic = lic ; ic ; ic = ic->next ) {
3458         
3459         if ( cln != ic->lineno ) {
3460             if ( options.debug ) {
3461                 debugLine = 1;
3462                 emitcode("","C$%s$%d$%d$%d ==.",
3463                          ic->filename,ic->lineno,
3464                          ic->level,ic->block);
3465                 debugLine = 0;
3466             }
3467             emitcode(";","%s %d",ic->filename,ic->lineno);
3468             cln = ic->lineno ;
3469         }
3470         /* if the result is marked as
3471            spilt and rematerializable or code for
3472            this has already been generated then
3473            do nothing */
3474         if (resultRemat(ic) || ic->generated ) 
3475             continue ;
3476         
3477         /* depending on the operation */
3478         switch (ic->op) {
3479         case '!' :
3480             emitcode("", "; genNot");
3481             genNot(ic);
3482             break;
3483             
3484         case '~' :
3485             emitcode("", "; genCpl");
3486             genCpl(ic);
3487             break;
3488             
3489         case UNARYMINUS:
3490             emitcode("", "; genUminus");
3491             genUminus (ic);
3492             break;
3493             
3494         case IPUSH:
3495             emitcode("", "; genIpush");
3496             genIpush (ic);
3497             break;
3498             
3499         case IPOP:
3500             /* IPOP happens only when trying to restore a 
3501                spilt live range, if there is an ifx statement
3502                following this pop then the if statement might
3503                be using some of the registers being popped which
3504                would destory the contents of the register so
3505                we need to check for this condition and handle it */
3506             if (ic->next            && 
3507                 ic->next->op == IFX &&
3508                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
3509                 emitcode("", "; genIfx");
3510                 genIfx (ic->next,ic);
3511             }
3512             else {
3513                 emitcode("", "; genIpop");
3514                 genIpop (ic);
3515             }
3516             break; 
3517             
3518         case CALL:
3519             emitcode("", "; genCall");
3520             genCall (ic);
3521             break;
3522             
3523         case PCALL:
3524             emitcode("", "; genPcall");
3525             genPcall (ic);
3526             break;
3527             
3528         case FUNCTION:
3529             emitcode("", "; genFunction");
3530             genFunction (ic);
3531             break;
3532             
3533         case ENDFUNCTION:
3534             emitcode("", "; genEndFunction");
3535             genEndFunction (ic);
3536             break;
3537             
3538         case RETURN:
3539             emitcode("", "; genRet");
3540             genRet (ic);
3541             break;
3542             
3543         case LABEL:
3544             emitcode("", "; genLabel");
3545             genLabel (ic);
3546             break;
3547             
3548         case GOTO:
3549             emitcode("", "; genGoto");
3550             genGoto (ic);
3551             break;
3552             
3553         case '+' :
3554             emitcode("", "; genPlus");
3555             genPlus (ic) ;
3556             break;
3557             
3558         case '-' :
3559             emitcode("", "; genMinus");
3560             genMinus (ic);
3561             break;
3562             
3563         case '*' :
3564             emitcode("", "; genMult");
3565             genMult (ic);
3566             break;
3567             
3568         case '/' :
3569             emitcode("", "; genDiv");
3570             genDiv (ic) ;
3571             break;
3572             
3573         case '%' :
3574             emitcode("", "; genMod");
3575             genMod (ic);
3576             break;
3577             
3578         case '>' :
3579             emitcode("", "; genCmpGt");
3580             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
3581             break;
3582             
3583         case '<' :
3584             emitcode("", "; genCmpLt");
3585             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
3586             break;
3587             
3588         case LE_OP:
3589         case GE_OP:
3590         case NE_OP:
3591             
3592             /* note these two are xlated by algebraic equivalence
3593                during parsing SDCC.y */
3594             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3595                    "got '>=' or '<=' shouldn't have come here");
3596             break;      
3597             
3598         case EQ_OP:
3599             emitcode("", "; genCmpEq");
3600             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
3601             break;          
3602             
3603         case AND_OP:
3604             emitcode("", "; genAndOp");
3605             genAndOp (ic);
3606             break;
3607             
3608         case OR_OP:
3609             emitcode("", "; genOrOp");
3610             genOrOp (ic);
3611             break;
3612             
3613         case '^' :
3614             emitcode("", "; genXor");
3615             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
3616             break;
3617             
3618         case '|' :
3619             emitcode("", "; genOr");
3620             genOr (ic,ifxForOp(IC_RESULT(ic),ic));
3621             break;
3622             
3623         case BITWISEAND:
3624             emitcode("", "; genAnd");
3625             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
3626             break;
3627             
3628         case INLINEASM:
3629             emitcode("", "; genInline");
3630             genInline (ic);
3631             break;
3632             
3633         case RRC:
3634             emitcode("", "; genRRC");
3635             genRRC (ic);
3636             break;
3637             
3638         case RLC:
3639             emitcode("", "; genRLC");
3640             genRLC (ic);
3641             break;
3642             
3643         case GETHBIT:
3644             emitcode("", "; genHBIT");
3645             assert(0);
3646             
3647         case LEFT_OP:
3648             emitcode("", "; genLeftShift");
3649             genLeftShift (ic);
3650             break;
3651             
3652         case RIGHT_OP:
3653             emitcode("", "; genRightShift");
3654             genRightShift (ic);
3655             break;
3656             
3657         case GET_VALUE_AT_ADDRESS:
3658             emitcode("", "; genPointerGet");
3659             genPointerGet(ic);
3660             break;
3661             
3662         case '=' :
3663
3664             if (POINTER_SET(ic)) {
3665                 emitcode("", "; genAssign (pointer)");
3666                 genPointerSet(ic);
3667             }
3668             else {
3669                 emitcode("", "; genAssign");
3670                 genAssign(ic);
3671             }
3672             break;
3673             
3674         case IFX:
3675             emitcode("", "; genIfx");
3676             genIfx (ic,NULL);
3677             break;
3678             
3679         case ADDRESS_OF:
3680             emitcode("", "; genAddrOf");
3681             genAddrOf (ic);
3682             break;
3683             
3684         case JUMPTABLE:
3685             emitcode("", "; genJumpTab");
3686             genJumpTab (ic);
3687             break;
3688             
3689         case CAST:
3690             emitcode("", "; genCast");
3691             genCast (ic);
3692             break;
3693             
3694         case RECEIVE:
3695             emitcode("", "; genReceive");
3696             genReceive(ic);
3697             break;
3698             
3699         case SEND:
3700             emitcode("", "; addSet");
3701             addSet(&sendSet,ic);
3702             break;
3703
3704         default :
3705             ic = ic;
3706             /*      piCode(ic,stdout); */
3707             
3708         }
3709     }
3710     
3711
3712     /* now we are ready to call the 
3713        peep hole optimizer */
3714     /*    if (!options.nopeep)
3715           peepHole (&lineHead); */
3716
3717     /* now do the actual printing */
3718     printLine (lineHead,codeOutFile);
3719     return;
3720 }