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