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