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