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