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