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