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