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