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