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