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