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