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