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