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