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