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