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