0874fbe5ad561a9e914b552854427de49eb71c66
[fw/sdcc] / src / z80 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - Z80 specific code generator.
3
4   Michael Hope <michaelh@juju.net.nz> 2000
5   Based on the mcs51 generator -
6       Sandeep Dutta . sandeep.dutta@usa.net (1998)
7    and -  Jean-Louis VERN.jlvern@writeme.com (1999)
8
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24   In other words, you are welcome to use, share and improve this program.
25   You are forbidden to forbid anyone else to use, share and improve
26   what you give them.   Help stamp out software-hoarding!
27
28 -------------------------------------------------------------------------*/
29
30 /*
31   Benchmarks on dhry.c 2.1 with 32766 loops and a 10ms clock:
32                                        ticks dhry  size
33   Base with asm strcpy / strcmp / memcpy: 23198 141 1A14
34   Improved WORD push                    22784 144 19AE
35   With label1 on                        22694 144 197E
36   With label2 on                        22743 144 198A
37   With label3 on                        22776 144 1999
38   With label4 on                        22776 144 1999
39   With all 'label' on                   22661 144 196F
40   With loopInvariant on                 20919 156 19AB
41   With loopInduction on                 Breaks    198B
42   With all working on                   20796 158 196C
43   Slightly better genCmp(signed)        20597 159 195B
44   Better reg packing, first peephole    20038 163 1873
45   With assign packing                   19281 165 1849
46   5/3/00                                17741 185 17B6
47   With reg params for mul and div       16234 202 162D
48
49   1. Starting again at 3 Aug 01         34965  93 219C
50    No asm strings
51    Includes long mul/div in code
52   2. Optimised memcpy for acc use       32102 102 226B
53   3. Optimised strcpy for acc use       27819 117 2237
54   3a Optimised memcpy fun
55   4. Optimised strcmp fun               21999 149 2294
56   5. Optimised strcmp further           21660 151 228C
57   6. Optimised memcpy by unroling       20885 157 2201
58   7. After turning loop induction on    19862 165 236D
59   8. Same as 7 but with more info
60   9. With asm optimised strings         17030 192 2223
61
62   10 and below are with asm strings off.
63
64   10 Mucho optimisations                13562 201 1FCC
65
66   Apparent advantage of turning on regparams:
67   1.  Cost of push
68         Decent case is push of a constant
69           - ld hl,#n; push hl: (10+11)*nargs
70   2.  Cost of pull from stack
71         Using asm with ld hl, etc
72           - ld hl,#2; add hl,sp; (ld bc,(hl); hl+=2)*nargs
73             10+11+(7+6+7+6)*nargs
74   3.  Cost of fixing stack
75           - pop hl*nargs
76             10*nargs
77
78   So cost is (10+11+7+6+7+10)*nargs+10+11
79       = 51*nargs+21
80       = 123 for mul, div, strcmp, strcpy
81   Saving of (98298+32766+32766+32766)*123 = 24181308
82   At 192 d/s for 682411768t, speed up to 199.  Hmm.
83 */
84
85 #include <stdio.h>
86 #include <stdlib.h>
87 #include <string.h>
88 #include <ctype.h>
89
90 #include "z80.h"
91 #include "SDCCglobl.h"
92 #include "SDCCpeeph.h"
93 #include "gen.h"
94 #include "SDCCglue.h"
95 #include "newalloc.h"
96
97 /* This is the down and dirty file with all kinds of kludgy & hacky
98    stuff. This is what it is all about CODE GENERATION for a specific MCU.
99    Some of the routines may be reusable, will have to see */
100
101 /* Z80 calling convention description.
102    Parameters are passed right to left.  As the stack grows downwards,
103    the parameters are arranged in left to right in memory.
104    Parameters may be passed in the HL and DE registers with one
105    parameter per pair.
106    PENDING: What if the parameter is a long?
107    Everything is caller saves. i.e. the caller must save any registers
108    that it wants to preserve over the call.
109    GB: The return value is returned in DEHL.  DE is normally used as a
110    working register pair.  Caller saves allows it to be used for a
111    return value.
112    va args functions do not use register parameters.  All arguments
113    are passed on the stack.
114    IX is used as an index register to the top of the local variable
115    area.  ix-0 is the top most local variable.
116 */
117
118 enum
119 {
120   /* Set to enable debugging trace statements in the output assembly code. */
121   DISABLE_DEBUG = 0
122 };
123
124 static char *_z80_return[] =
125   {"l", "h", "e", "d"};
126 static char *_gbz80_return[] =
127   {"e", "d", "l", "h"};
128 static char *_fReceive[] =
129   { "c", "b", "e", "d" };
130
131 static char **_fReturn;
132 static char **_fTmp;
133
134 extern struct dbuf_s *codeOutBuf;
135
136 enum
137   {
138     INT8MIN = -128,
139     INT8MAX = 127
140   };
141
142 /** Enum covering all the possible register pairs.
143  */
144 typedef enum
145   {
146     PAIR_INVALID,
147     PAIR_AF,
148     PAIR_BC,
149     PAIR_DE,
150     PAIR_HL,
151     PAIR_IY,
152     PAIR_IX,
153     NUM_PAIRS
154   } PAIR_ID;
155
156 static struct
157 {
158   const char *name;
159   const char *l;
160   const char *h;
161 } _pairs[NUM_PAIRS] = {
162   {    "??1", "?2", "?3" },
163   {    "af", "f", "a" },
164   {    "bc", "c", "b" },
165   {    "de", "e", "d" },
166   {    "hl", "l", "h" },
167   {    "iy", "iyl", "iyh" },
168   {    "ix", "ixl", "ixh" }
169 };
170
171 // PENDING
172 #define ACC_NAME        _pairs[PAIR_AF].h
173
174 enum
175   {
176     LSB,
177     MSB16,
178     MSB24,
179     MSB32
180   };
181
182 /** Code generator persistent data.
183  */
184 static struct
185 {
186   /** Used to optimised setting up of a pair by remebering what it
187       contains and adjusting instead of reloading where possible.
188   */
189   struct
190   {
191     AOP_TYPE last_type;
192     const char *base;
193     int offset;
194   } pairs[NUM_PAIRS];
195   struct
196   {
197     int last;
198     int pushed;
199     int param_offset;
200     int offset;
201     int pushedBC;
202     int pushedDE;
203   } stack;
204
205   struct
206   {
207     int pushedBC;
208     int pushedDE;
209   } calleeSaves;
210
211   bool omitFramePtr;
212   int frameId;
213   int receiveOffset;
214   bool flushStatics;
215   bool in_home;
216   const char *lastFunctionName;
217   iCode *current_iCode;
218   bool preserveCarry;
219
220   set *sendSet;
221
222   struct
223   {
224     /** TRUE if the registers have already been saved. */
225     bool saved;
226   } saves;
227
228   struct
229   {
230     lineNode *head;
231     lineNode *current;
232     int isInline;
233     int isDebug;
234     allocTrace trace;
235   } lines;
236
237   struct
238   {
239     allocTrace aops;
240   } trace;
241 } _G;
242
243 static const char *aopGet (asmop * aop, int offset, bool bit16);
244
245 static const char *aopNames[] = {
246   "AOP_INVALID",
247   "AOP_LIT",
248   "AOP_REG",
249   "AOP_DIR",
250   "AOP_SFR",
251   "AOP_STK",
252   "AOP_IMMD",
253   "AOP_STR",
254   "AOP_CRY",
255   "AOP_IY",
256   "AOP_HL",
257   "AOP_ACC",
258   "AOP_HLREG",
259   "AOP_SIMPLELIT",
260   "AOP_EXSTK",
261   "AOP_PAIRPT",
262   "AOP_DUMMY"
263 };
264
265 static bool
266 isLastUse (iCode *ic, operand *op)
267 {
268   bitVect *uses = bitVectCopy (OP_USES (op));
269
270   while (!bitVectIsZero (uses))
271     {
272       if (bitVectFirstBit (uses) == ic->key)
273         {
274           if (bitVectnBitsOn (uses) == 1)
275             {
276               return TRUE;
277             }
278           else
279             {
280               return FALSE;
281             }
282         }
283       bitVectUnSetBit (uses, bitVectFirstBit (uses));
284     }
285
286   return FALSE;
287 }
288
289 static PAIR_ID
290 _getTempPairId(void)
291 {
292   if (IS_GB)
293     {
294       return PAIR_DE;
295     }
296   else
297     {
298       return PAIR_HL;
299     }
300 }
301
302 static const char *
303 _getTempPairName(void)
304 {
305   return _pairs[_getTempPairId()].name;
306 }
307
308 static bool
309 isPairInUse (PAIR_ID id, iCode *ic)
310 {
311   if (id == PAIR_DE)
312     {
313       return bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX);
314     }
315   else if (id == PAIR_BC)
316     {
317       return bitVectBitValue (ic->rMask, B_IDX) || bitVectBitValue(ic->rMask, C_IDX);
318     }
319   else
320     {
321       wassertl (0, "Only implemented for DE and BC");
322       return TRUE;
323     }
324 }
325
326 static bool
327 isPairInUseNotInRet(PAIR_ID id, iCode *ic)
328 {
329   bitVect *rInUse;
330
331   rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
332
333   if (id == PAIR_DE)
334     {
335       return bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX);
336     }
337   else
338     {
339       wassertl (0, "Only implemented for DE");
340       return TRUE;
341     }
342 }
343
344 static PAIR_ID
345 getFreePairId (iCode *ic)
346 {
347   if (!isPairInUse (PAIR_BC, ic))
348     {
349       return PAIR_BC;
350     }
351   else if (IS_Z80 && !isPairInUse (PAIR_DE, ic))
352     {
353       return PAIR_DE;
354     }
355   else
356     {
357       return PAIR_INVALID;
358     }
359 }
360
361 static void
362 _tidyUp (char *buf)
363 {
364   /* Clean up the line so that it is 'prettier' */
365   if (strchr (buf, ':'))
366     {
367       /* Is a label - cant do anything */
368       return;
369     }
370   /* Change the first (and probably only) ' ' to a tab so
371      everything lines up.
372   */
373   while (*buf)
374     {
375       if (*buf == ' ')
376         {
377           *buf = '\t';
378           break;
379         }
380       buf++;
381     }
382 }
383
384 static lineNode *
385 _newLineNode (const char *line)
386 {
387   lineNode *pl;
388
389   pl = traceAlloc(&_G.lines.trace, Safe_alloc ( sizeof (lineNode)));
390   pl->line = traceAlloc(&_G.lines.trace, Safe_strdup (line));
391
392   return pl;
393 }
394
395 static void
396 _vemit2 (const char *szFormat, va_list ap)
397 {
398   struct dbuf_s dbuf;
399   const char *buffer;
400
401   dbuf_init(&dbuf, INITIAL_INLINEASM);
402
403   dbuf_tvprintf (&dbuf, szFormat, ap);
404
405   buffer = dbuf_c_str(&dbuf);
406
407   _tidyUp ((char *)buffer);
408   _G.lines.current = (_G.lines.current ?
409               connectLine (_G.lines.current, _newLineNode (buffer)) :
410               (_G.lines.head = _newLineNode (buffer)));
411
412   _G.lines.current->isInline = _G.lines.isInline;
413   _G.lines.current->isDebug = _G.lines.isDebug;
414   _G.lines.current->ic = _G.current_iCode;
415   _G.lines.current->isComment = (*buffer == ';');
416
417   dbuf_destroy(&dbuf);
418 }
419
420 static void
421 emit2 (const char *szFormat,...)
422 {
423   va_list ap;
424
425   va_start (ap, szFormat);
426
427   _vemit2 (szFormat, ap);
428
429   va_end (ap);
430 }
431
432 static void
433 emitDebug (const char *szFormat,...)
434 {
435   if (!DISABLE_DEBUG)
436     {
437       va_list ap;
438
439       va_start (ap, szFormat);
440
441       _vemit2 (szFormat, ap);
442
443       va_end (ap);
444     }
445 }
446
447 /*-----------------------------------------------------------------*/
448 /* z80_emitDebuggerSymbol - associate the current code location    */
449 /*   with a debugger symbol                                        */
450 /*-----------------------------------------------------------------*/
451 void
452 z80_emitDebuggerSymbol (char * debugSym)
453 {
454   _G.lines.isDebug = 1;
455   emit2 ("%s !equ .", debugSym);
456   emit2 ("!global", debugSym);
457   _G.lines.isDebug = 0;
458 }
459
460 /*-----------------------------------------------------------------*/
461 /* emit2 - writes the code into a file : for now it is simple    */
462 /*-----------------------------------------------------------------*/
463 void
464 _emit2 (const char *inst, const char *fmt,...)
465 {
466   va_list ap;
467   char lb[INITIAL_INLINEASM];
468   char *lbp = lb;
469
470   va_start (ap, fmt);
471
472   if (*inst != '\0')
473     {
474       sprintf (lb, "%s\t", inst);
475       vsprintf (lb + (strlen (lb)), fmt, ap);
476     }
477   else
478     vsprintf (lb, fmt, ap);
479
480   while (isspace (*lbp))
481     lbp++;
482
483   if (lbp && *lbp)
484     {
485       _G.lines.current = (_G.lines.current ?
486                   connectLine (_G.lines.current, _newLineNode (lb)) :
487                   (_G.lines.head = _newLineNode (lb)));
488     }
489   _G.lines.current->isInline = _G.lines.isInline;
490   _G.lines.current->ic = _G.current_iCode;
491   va_end (ap);
492 }
493
494 static void
495 _emitMove(const char *to, const char *from)
496 {
497   if (STRCASECMP(to, from) != 0)
498     {
499       emit2("ld %s,%s", to, from);
500     }
501   else
502     {
503       // Optimise it out.
504       // Could leave this to the peephole, but sometimes the peephole is inhibited.
505     }
506 }
507
508 void
509 aopDump(const char *plabel, asmop *aop)
510 {
511   int i;
512   char regbuf[9];
513   char *rbp = regbuf;
514
515   emitDebug("; Dump of %s: type %s size %u", plabel, aopNames[aop->type], aop->size);
516   switch (aop->type)
517     {
518     case AOP_EXSTK:
519     case AOP_STK:
520       emitDebug(";  aop_stk %d", aop->aopu.aop_stk);
521       break;
522     case AOP_REG:
523       for (i=aop->size-1;i>=0;i--)
524         *rbp++ = *(aop->aopu.aop_reg[i]->name);
525       *rbp = '\0';
526       emitDebug(";  reg = %s", regbuf);
527       break;
528     case AOP_PAIRPTR:
529       emitDebug(";  pairptr = (%s)", _pairs[aop->aopu.aop_pairId].name);
530
531     default:
532       /* No information. */
533       break;
534     }
535 }
536
537 static void
538 _moveA(const char *moveFrom)
539 {
540     // Let the peephole optimiser take care of redundent loads
541     _emitMove(ACC_NAME, moveFrom);
542 }
543
544 static void
545 _clearCarry(void)
546 {
547     emit2("xor a,a");
548 }
549
550 const char *
551 getPairName (asmop * aop)
552 {
553   if (aop->type == AOP_REG)
554     {
555       switch (aop->aopu.aop_reg[0]->rIdx)
556         {
557         case C_IDX:
558           return "bc";
559           break;
560         case E_IDX:
561           return "de";
562           break;
563         case L_IDX:
564           return "hl";
565           break;
566         }
567     }
568   else if (aop->type == AOP_STR || aop->type == AOP_HLREG)
569     {
570       int i;
571       for (i = 0; i < NUM_PAIRS; i++)
572         {
573           if (strcmp(aop->aopu.aop_str[0], _pairs[i].l) == 0)
574             {
575               return _pairs[i].name;
576             }
577         }
578     }
579   wassertl (0, "Tried to get the pair name of something that isn't a pair");
580   return NULL;
581 }
582
583 static PAIR_ID
584 getPairId (asmop * aop)
585 {
586   if (aop->size == 2)
587     {
588       if (aop->type == AOP_REG)
589         {
590           if ((aop->aopu.aop_reg[0]->rIdx == C_IDX) && (aop->aopu.aop_reg[1]->rIdx == B_IDX))
591             {
592               return PAIR_BC;
593             }
594           if ((aop->aopu.aop_reg[0]->rIdx == E_IDX) && (aop->aopu.aop_reg[1]->rIdx == D_IDX))
595             {
596               return PAIR_DE;
597             }
598           if ((aop->aopu.aop_reg[0]->rIdx == L_IDX) && (aop->aopu.aop_reg[1]->rIdx == H_IDX))
599             {
600               return PAIR_HL;
601             }
602         }
603       else if (aop->type == AOP_STR || aop->type == AOP_HLREG)
604         {
605           int i;
606           for (i = 0; i < NUM_PAIRS; i++)
607             {
608               if (!strcmp (aop->aopu.aop_str[0], _pairs[i].l) && !strcmp (aop->aopu.aop_str[1], _pairs[i].h))
609                 {
610                   return i;
611                 }
612             }
613         }
614     }
615   return PAIR_INVALID;
616 }
617
618 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
619 bool
620 isPair (asmop * aop)
621 {
622   return (getPairId (aop) != PAIR_INVALID);
623 }
624
625 /** Returns TRUE if the registers used in aop cannot be split into high
626     and low halves */
627 bool
628 isUnsplitable (asmop * aop)
629 {
630   switch (getPairId (aop))
631     {
632     case PAIR_IX:
633     case PAIR_IY:
634       return TRUE;
635     default:
636       return FALSE;
637     }
638   return FALSE;
639 }
640
641 bool
642 isPtrPair (asmop * aop)
643 {
644   PAIR_ID pairId = getPairId (aop);
645   switch (pairId)
646     {
647     case PAIR_HL:
648     case PAIR_IY:
649     case PAIR_IX:
650       return TRUE;
651     default:
652       return FALSE;
653     }
654 }
655
656 static void
657 spillPair (PAIR_ID pairId)
658 {
659   _G.pairs[pairId].last_type = AOP_INVALID;
660   _G.pairs[pairId].base = NULL;
661 }
662
663 /* Given a register name, spill the pair (if any) the register is part of */
664 static void
665 spillPairReg (const char *regname)
666 {
667   if (strlen(regname)==1)
668     {
669       switch (*regname)
670         {
671         case 'h':
672         case 'l':
673           spillPair(PAIR_HL);
674           break;
675         case 'd':
676         case 'e':
677           spillPair(PAIR_DE);
678           break;
679         case 'b':
680         case 'c':
681           spillPair(PAIR_BC);
682           break;
683         }
684     }
685 }
686
687 /** Push a register pair onto the stack */
688 void
689 genPairPush (asmop * aop)
690 {
691   emit2 ("push %s", getPairName (aop));
692 }
693
694 static void
695 _push (PAIR_ID pairId)
696 {
697   emit2 ("push %s", _pairs[pairId].name);
698   _G.stack.pushed += 2;
699 }
700
701 static void
702 _pop (PAIR_ID pairId)
703 {
704   if (pairId != PAIR_INVALID)
705     {
706       emit2 ("pop %s", _pairs[pairId].name);
707       _G.stack.pushed -= 2;
708       spillPair (pairId);
709     }
710 }
711
712 void
713 genMovePairPair (PAIR_ID srcPair, PAIR_ID dstPair)
714 {
715   switch (dstPair)
716     {
717     case PAIR_IX:
718     case PAIR_IY:
719     case PAIR_AF:
720       _push(srcPair);
721       _pop(dstPair);
722       break;
723     case PAIR_BC:
724     case PAIR_DE:
725     case PAIR_HL:
726       if (srcPair == PAIR_IX || srcPair == PAIR_IY)
727         {
728           _push(srcPair);
729           _pop(dstPair);
730         }
731       else
732         {
733           emit2("ld %s,%s",_pairs[dstPair].l,_pairs[srcPair].l);
734           emit2("ld %s,%s",_pairs[dstPair].h,_pairs[srcPair].h);
735         }
736      default:
737        wassertl (0, "Tried to move a nonphysical pair");
738     }
739   _G.pairs[dstPair].last_type = _G.pairs[srcPair].last_type;
740   _G.pairs[dstPair].base = _G.pairs[srcPair].base;
741   _G.pairs[dstPair].offset = _G.pairs[srcPair].offset;
742 }
743
744
745 /*-----------------------------------------------------------------*/
746 /* newAsmop - creates a new asmOp                                  */
747 /*-----------------------------------------------------------------*/
748 static asmop *
749 newAsmop (short type)
750 {
751   asmop *aop;
752
753   aop = traceAlloc(&_G.trace.aops, Safe_alloc (sizeof (asmop)));
754   aop->type = type;
755   return aop;
756 }
757
758 /*-----------------------------------------------------------------*/
759 /* aopForSym - for a true symbol                                   */
760 /*-----------------------------------------------------------------*/
761 static asmop *
762 aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a)
763 {
764   asmop *aop;
765   memmap *space;
766
767   wassert (ic);
768   wassert (sym);
769   wassert (sym->etype);
770
771   space = SPEC_OCLS (sym->etype);
772
773   /* if already has one */
774   if (sym->aop)
775     {
776       return sym->aop;
777     }
778
779   /* Assign depending on the storage class */
780   if (sym->onStack || sym->iaccess)
781     {
782       /* The pointer that is used depends on how big the offset is.
783          Normally everything is AOP_STK, but for offsets of < -128 or
784          > 127 on the Z80 an extended stack pointer is used.
785       */
786       if (IS_Z80 && (_G.omitFramePtr || sym->stack < INT8MIN || sym->stack > (int)(INT8MAX-getSize (sym->type))))
787         {
788           emitDebug ("; AOP_EXSTK for %s", sym->rname);
789           sym->aop = aop = newAsmop (AOP_EXSTK);
790         }
791       else
792         {
793           emitDebug ("; AOP_STK for %s", sym->rname);
794           sym->aop = aop = newAsmop (AOP_STK);
795         }
796
797       aop->size = getSize (sym->type);
798       aop->aopu.aop_stk = sym->stack;
799       return aop;
800     }
801
802   /* special case for a function */
803   if (IS_FUNC (sym->type))
804     {
805       sym->aop = aop = newAsmop (AOP_IMMD);
806       aop->aopu.aop_immd = traceAlloc(&_G.trace.aops, Safe_strdup (sym->rname));
807       aop->size = 2;
808       return aop;
809     }
810
811   if( IN_REGSP( space ))
812   { /*.p.t.20030716 minor restructure to add SFR support to the Z80 */
813     if (IS_GB)
814     {
815       /* if it is in direct space */
816       if( !requires_a )
817       {
818         sym->aop = aop = newAsmop (AOP_SFR);
819         aop->aopu.aop_dir = sym->rname;
820         aop->size = getSize (sym->type);
821           emitDebug ("; AOP_SFR for %s", sym->rname);
822         return aop;
823       }
824     }
825     else
826     { /*.p.t.20030716 adding SFR support to the Z80 port */
827       aop = newAsmop (AOP_SFR);
828       sym->aop          = aop;
829       aop->aopu.aop_dir = sym->rname;
830       aop->size         = getSize( sym->type );
831       aop->paged        = FUNC_REGBANK(sym->type);
832       aop->bcInUse      = isPairInUse( PAIR_BC, ic );
833       aop->deInUse      = isPairInUse( PAIR_DE, ic );
834       emitDebug( ";Z80 AOP_SFR for %s banked:%d bc:%d de:%d", sym->rname, FUNC_REGBANK(sym->type), aop->bcInUse, aop->deInUse );
835
836       return( aop );
837     }
838   }
839
840   /* only remaining is far space */
841   /* in which case DPTR gets the address */
842   if (IS_GB)
843     {
844       emitDebug ("; AOP_HL for %s", sym->rname);
845       sym->aop = aop = newAsmop (AOP_HL);
846     }
847   else
848     {
849       sym->aop = aop = newAsmop (AOP_IY);
850     }
851   aop->size = getSize (sym->type);
852   aop->aopu.aop_dir = sym->rname;
853
854   /* if it is in code space */
855   if (IN_CODESPACE (space))
856     aop->code = 1;
857
858   return aop;
859 }
860
861 /*-----------------------------------------------------------------*/
862 /* aopForRemat - rematerialzes an object                           */
863 /*-----------------------------------------------------------------*/
864 static asmop *
865 aopForRemat (symbol * sym)
866 {
867   char *s = buffer;
868   iCode *ic = sym->rematiCode;
869   asmop *aop = newAsmop (AOP_IMMD);
870
871   while (1)
872     {
873       /* if plus or minus print the right hand side */
874       if (ic->op == '+' || ic->op == '-')
875         {
876           /* PENDING: for re-target */
877           sprintf (s, "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)),
878                    ic->op);
879           s += strlen (s);
880           ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
881           continue;
882         }
883       /* we reached the end */
884       sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
885       break;
886     }
887
888   aop->aopu.aop_immd = traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
889   return aop;
890 }
891
892 /*-----------------------------------------------------------------*/
893 /* regsInCommon - two operands have some registers in common       */
894 /*-----------------------------------------------------------------*/
895 bool
896 regsInCommon (operand * op1, operand * op2)
897 {
898   symbol *sym1, *sym2;
899   int i;
900
901   /* if they have registers in common */
902   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
903     return FALSE;
904
905   sym1 = OP_SYMBOL (op1);
906   sym2 = OP_SYMBOL (op2);
907
908   if (sym1->nRegs == 0 || sym2->nRegs == 0)
909     return FALSE;
910
911   for (i = 0; i < sym1->nRegs; i++)
912     {
913       int j;
914       if (!sym1->regs[i])
915         continue;
916
917       for (j = 0; j < sym2->nRegs; j++)
918         {
919           if (!sym2->regs[j])
920             continue;
921
922           if (sym2->regs[j] == sym1->regs[i])
923             return TRUE;
924         }
925     }
926
927   return FALSE;
928 }
929
930 /*-----------------------------------------------------------------*/
931 /* operandsEqu - equivalent                                        */
932 /*-----------------------------------------------------------------*/
933 bool
934 operandsEqu (operand * op1, operand * op2)
935 {
936   symbol *sym1, *sym2;
937
938   /* if they not symbols */
939   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
940     return FALSE;
941
942   sym1 = OP_SYMBOL (op1);
943   sym2 = OP_SYMBOL (op2);
944
945   /* if both are itemps & one is spilt
946      and the other is not then false */
947   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
948       sym1->isspilt != sym2->isspilt)
949     return FALSE;
950
951   /* if they are the same */
952   if (sym1 == sym2)
953     return 1;
954
955   if (sym1->rname[0] && sym2->rname[0]
956       && strcmp (sym1->rname, sym2->rname) == 0)
957     return 2;
958
959   /* if left is a tmp & right is not */
960   if (IS_ITEMP (op1) &&
961       !IS_ITEMP (op2) &&
962       sym1->isspilt &&
963       (sym1->usl.spillLoc == sym2))
964     return 3;
965
966   if (IS_ITEMP (op2) &&
967       !IS_ITEMP (op1) &&
968       sym2->isspilt &&
969       sym1->level > 0 &&
970       (sym2->usl.spillLoc == sym1))
971     return 4;
972
973   return FALSE;
974 }
975
976 /*-----------------------------------------------------------------*/
977 /* sameRegs - two asmops have the same registers                   */
978 /*-----------------------------------------------------------------*/
979 bool
980 sameRegs (asmop * aop1, asmop * aop2)
981 {
982   int i;
983
984   if (aop1->type == AOP_SFR ||
985       aop2->type == AOP_SFR)
986     return FALSE;
987
988   if (aop1 == aop2)
989     return TRUE;
990
991   if (aop1->type != AOP_REG ||
992       aop2->type != AOP_REG)
993     return FALSE;
994
995   if (aop1->size != aop2->size)
996     return FALSE;
997
998   for (i = 0; i < aop1->size; i++)
999     if (aop1->aopu.aop_reg[i] !=
1000         aop2->aopu.aop_reg[i])
1001       return FALSE;
1002
1003   return TRUE;
1004 }
1005
1006 /*-----------------------------------------------------------------*/
1007 /* aopOp - allocates an asmop for an operand  :                    */
1008 /*-----------------------------------------------------------------*/
1009 static void
1010 aopOp (operand * op, iCode * ic, bool result, bool requires_a)
1011 {
1012   asmop *aop;
1013   symbol *sym;
1014   int i;
1015
1016   if (!op)
1017     return;
1018
1019   /* if this a literal */
1020   if (IS_OP_LITERAL (op))
1021     {
1022       op->aop = aop = newAsmop (AOP_LIT);
1023       aop->aopu.aop_lit = op->operand.valOperand;
1024       aop->size = getSize (operandType (op));
1025       return;
1026     }
1027
1028   /* if already has a asmop then continue */
1029   if (op->aop)
1030     {
1031       if (op->aop->type == AOP_SFR)
1032         {
1033           op->aop->bcInUse = isPairInUse( PAIR_BC, ic );
1034           op->aop->deInUse = isPairInUse( PAIR_DE, ic );
1035         }
1036       return;
1037     }
1038
1039   /* if the underlying symbol has a aop */
1040   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1041     {
1042       op->aop = OP_SYMBOL (op)->aop;
1043       if (op->aop->type == AOP_SFR)
1044         {
1045           op->aop->bcInUse = isPairInUse( PAIR_BC, ic );
1046           op->aop->deInUse = isPairInUse( PAIR_DE, ic );
1047         }
1048       return;
1049     }
1050
1051   /* if this is a true symbol */
1052   if (IS_TRUE_SYMOP (op))
1053     {
1054       op->aop = aopForSym (ic, OP_SYMBOL (op), result, requires_a);
1055       return;
1056     }
1057
1058   /* this is a temporary : this has
1059      only four choices :
1060      a) register
1061      b) spillocation
1062      c) rematerialize
1063      d) conditional
1064      e) can be a return use only */
1065
1066   sym = OP_SYMBOL (op);
1067
1068   /* if the type is a conditional */
1069   if (sym->regType == REG_CND)
1070     {
1071       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1072       aop->size = 0;
1073       return;
1074     }
1075
1076   /* if it is spilt then two situations
1077      a) is rematerialize
1078      b) has a spill location */
1079   if (sym->isspilt || sym->nRegs == 0)
1080     {
1081       /* rematerialize it NOW */
1082       if (sym->remat)
1083         {
1084           sym->aop = op->aop = aop =
1085             aopForRemat (sym);
1086           aop->size = getSize (sym->type);
1087           return;
1088         }
1089
1090       if (sym->ruonly)
1091         {
1092           int i;
1093           aop = op->aop = sym->aop = newAsmop (AOP_STR);
1094           aop->size = getSize (sym->type);
1095           for (i = 0; i < 4; i++)
1096             aop->aopu.aop_str[i] = _fReturn[i];
1097           return;
1098         }
1099
1100       if (sym->accuse)
1101         {
1102           if (sym->accuse == ACCUSE_A)
1103             {
1104               aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1105               aop->size = getSize (sym->type);
1106               wassertl(aop->size == 1, "Internal error: Caching in A, but too big to fit in A");
1107
1108               aop->aopu.aop_str[0] = _pairs[PAIR_AF].h;
1109             }
1110           else if (sym->accuse == ACCUSE_SCRATCH)
1111             {
1112               aop = op->aop = sym->aop = newAsmop (AOP_HLREG);
1113               aop->size = getSize (sym->type);
1114               wassertl(aop->size <= 2, "Internal error: Caching in HL, but too big to fit in HL");
1115               aop->aopu.aop_str[0] = _pairs[PAIR_HL].l;
1116               aop->aopu.aop_str[1] = _pairs[PAIR_HL].h;
1117             }
1118           else if (sym->accuse == ACCUSE_IY)
1119             {
1120               aop = op->aop = sym->aop = newAsmop (AOP_HLREG);
1121               aop->size = getSize (sym->type);
1122               wassertl(aop->size <= 2, "Internal error: Caching in IY, but too big to fit in IY");
1123               aop->aopu.aop_str[0] = _pairs[PAIR_IY].l;
1124               aop->aopu.aop_str[1] = _pairs[PAIR_IY].h;
1125             }
1126           else
1127               {
1128                   wassertl (0, "Marked as being allocated into A or HL but is actually in neither");
1129               }
1130           return;
1131         }
1132
1133       if (sym->usl.spillLoc)
1134         {
1135           asmop *oldAsmOp = NULL;
1136
1137           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1138             {
1139               /* force a new aop if sizes differ */
1140               oldAsmOp = sym->usl.spillLoc->aop;
1141               sym->usl.spillLoc->aop = NULL;
1142             }
1143           sym->aop = op->aop = aop =
1144                      aopForSym (ic, sym->usl.spillLoc, result, requires_a);
1145           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1146             {
1147               /* Don't reuse the new aop, go with the last one */
1148               sym->usl.spillLoc->aop = oldAsmOp;
1149             }
1150           aop->size = getSize (sym->type);
1151           return;
1152         }
1153
1154       /* else must be a dummy iTemp */
1155       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1156       aop->size = getSize (sym->type);
1157       return;
1158     }
1159
1160   /* must be in a register */
1161   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1162   aop->size = sym->nRegs;
1163   for (i = 0; i < sym->nRegs; i++)
1164     aop->aopu.aop_reg[i] = sym->regs[i];
1165 }
1166
1167 /*-----------------------------------------------------------------*/
1168 /* freeAsmop - free up the asmop given to an operand               */
1169 /*----------------------------------------------------------------*/
1170 static void
1171 freeAsmop (operand * op, asmop * aaop, iCode * ic)
1172 {
1173   asmop *aop;
1174
1175   if (!op)
1176     aop = aaop;
1177   else
1178     aop = op->aop;
1179
1180   if (!aop)
1181     return;
1182
1183   if (aop->freed)
1184     goto dealloc;
1185
1186   aop->freed = 1;
1187
1188   if (aop->type == AOP_PAIRPTR && IS_Z80 && aop->aopu.aop_pairId == PAIR_DE)
1189     {
1190       _pop (aop->aopu.aop_pairId);
1191     }
1192
1193   if (getPairId (aop) == PAIR_HL)
1194     {
1195       spillPair (PAIR_HL);
1196     }
1197
1198 dealloc:
1199   /* all other cases just dealloc */
1200   if (op)
1201     {
1202       op->aop = NULL;
1203       if (IS_SYMOP (op))
1204         {
1205           OP_SYMBOL (op)->aop = NULL;
1206           /* if the symbol has a spill */
1207           if (SPIL_LOC (op))
1208             SPIL_LOC (op)->aop = NULL;
1209         }
1210     }
1211
1212 }
1213
1214 bool
1215 isLitWord (asmop * aop)
1216 {
1217   /*    if (aop->size != 2)
1218      return FALSE; */
1219   switch (aop->type)
1220     {
1221     case AOP_IMMD:
1222     case AOP_LIT:
1223       return TRUE;
1224     default:
1225       return FALSE;
1226     }
1227 }
1228
1229 char *
1230 aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
1231 {
1232   /* depending on type */
1233   switch (aop->type)
1234     {
1235     case AOP_HL:
1236     case AOP_IY:
1237     case AOP_IMMD:
1238       /* PENDING: for re-target */
1239       if (with_hash)
1240         {
1241           tsprintf (buffer, sizeof(buffer),
1242                     "!hashedstr + %d", aop->aopu.aop_immd, offset);
1243         }
1244       else if (offset == 0)
1245         {
1246           tsprintf (buffer, sizeof(buffer),
1247                     "%s", aop->aopu.aop_immd);
1248         }
1249       else
1250         {
1251           tsprintf (buffer, sizeof(buffer),
1252                     "%s + %d", aop->aopu.aop_immd, offset);
1253         }
1254       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1255
1256     case AOP_LIT:
1257       {
1258         value *val = aop->aopu.aop_lit;
1259         /* if it is a float then it gets tricky */
1260         /* otherwise it is fairly simple */
1261         if (!IS_FLOAT (val->type))
1262           {
1263             unsigned long v = (unsigned long) floatFromVal (val);
1264
1265             if (offset == 2)
1266               {
1267                 v >>= 16;
1268               }
1269             else if (offset == 0)
1270               {
1271                 // OK
1272               }
1273             else
1274               {
1275                 wassertl(0, "Encountered an invalid offset while fetching a literal");
1276               }
1277
1278             if (with_hash)
1279               tsprintf (buffer, sizeof(buffer), "!immedword", v);
1280             else
1281               tsprintf (buffer, sizeof(buffer), "!constword", v);
1282
1283             return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1284           }
1285         else
1286           {
1287             union {
1288               float f;
1289               unsigned char c[4];
1290             }
1291             fl;
1292             unsigned int i;
1293
1294             /* it is type float */
1295             fl.f = (float) floatFromVal (val);
1296
1297 #ifdef WORDS_BIGENDIAN
1298             i = fl.c[3-offset] | (fl.c[3-offset-1]<<8);
1299 #else
1300             i = fl.c[offset] | (fl.c[offset+1]<<8);
1301 #endif
1302             if (with_hash)
1303               tsprintf (buffer, sizeof(buffer), "!immedword", i);
1304             else
1305               tsprintf (buffer, sizeof(buffer), "!constword", i);
1306
1307             return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1308           }
1309       }
1310     default:
1311       return NULL;
1312     }
1313 }
1314
1315 char *
1316 aopGetWord (asmop * aop, int offset)
1317 {
1318   return aopGetLitWordLong (aop, offset, TRUE);
1319 }
1320
1321 bool
1322 isPtr (const char *s)
1323 {
1324   if (!strcmp (s, "hl"))
1325     return TRUE;
1326   if (!strcmp (s, "ix"))
1327     return TRUE;
1328   if (!strcmp (s, "iy"))
1329     return TRUE;
1330   return FALSE;
1331 }
1332
1333 static void
1334 adjustPair (const char *pair, int *pold, int new)
1335 {
1336   wassert (pair);
1337
1338   while (*pold < new)
1339     {
1340       emit2 ("inc %s", pair);
1341       (*pold)++;
1342     }
1343   while (*pold > new)
1344     {
1345       emit2 ("dec %s", pair);
1346       (*pold)--;
1347     }
1348 }
1349
1350 static void
1351 spillCached (void)
1352 {
1353   spillPair (PAIR_HL);
1354   spillPair (PAIR_IY);
1355 }
1356
1357 static bool
1358 requiresHL (asmop * aop)
1359 {
1360   switch (aop->type)
1361     {
1362     case AOP_IY:
1363     case AOP_HL:
1364     case AOP_STK:
1365     case AOP_EXSTK:
1366     case AOP_HLREG:
1367       return TRUE;
1368     default:
1369       return FALSE;
1370     }
1371 }
1372
1373 static void
1374 fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
1375 {
1376   const char *l, *base;
1377   const char *pair = _pairs[pairId].name;
1378   l = aopGetLitWordLong (left, offset, FALSE);
1379   base = aopGetLitWordLong (left, 0, FALSE);
1380   wassert (l && pair && base);
1381
1382   if (isPtr (pair))
1383     {
1384       if (pairId == PAIR_HL || pairId == PAIR_IY)
1385         {
1386           if (_G.pairs[pairId].last_type == left->type)
1387             {
1388               if (_G.pairs[pairId].base && !strcmp (_G.pairs[pairId].base, base))
1389                 {
1390                   if (pairId == PAIR_HL && abs (_G.pairs[pairId].offset - offset) < 3)
1391                     {
1392                       adjustPair (pair, &_G.pairs[pairId].offset, offset);
1393                       return;
1394                     }
1395                   if (pairId == PAIR_IY && (offset >= INT8MIN && offset <= INT8MAX))
1396                     {
1397                       return;
1398                     }
1399                 }
1400             }
1401         }
1402       _G.pairs[pairId].last_type = left->type;
1403       _G.pairs[pairId].base = traceAlloc(&_G.trace.aops, Safe_strdup (base));
1404       _G.pairs[pairId].offset = offset;
1405     }
1406   /* Both a lit on the right and a true symbol on the left */
1407   emit2 ("ld %s,!hashedstr", pair, l);
1408 }
1409
1410 static PAIR_ID
1411 makeFreePairId (iCode *ic, bool *pisUsed)
1412 {
1413   *pisUsed = FALSE;
1414
1415   if (ic != NULL)
1416     {
1417       if (!bitVectBitValue (ic->rMask, B_IDX) && !bitVectBitValue(ic->rMask, C_IDX))
1418         {
1419           return PAIR_BC;
1420         }
1421       else if (IS_Z80 && !bitVectBitValue (ic->rMask, D_IDX) && !bitVectBitValue(ic->rMask, E_IDX))
1422         {
1423           return PAIR_DE;
1424         }
1425       else
1426         {
1427           *pisUsed = TRUE;
1428           return PAIR_HL;
1429         }
1430     }
1431   else
1432     {
1433       *pisUsed = TRUE;
1434       return PAIR_HL;
1435     }
1436 }
1437
1438 static void
1439 fetchPairLong (PAIR_ID pairId, asmop * aop, iCode *ic, int offset)
1440 {
1441     /* if this is remateriazable */
1442     if (isLitWord (aop)) {
1443         fetchLitPair (pairId, aop, offset);
1444     }
1445     else
1446       {
1447         if (getPairId (aop) == pairId)
1448           {
1449             /* Do nothing */
1450           }
1451         /* we need to get it byte by byte */
1452         else if (pairId == PAIR_HL && IS_GB && requiresHL (aop)) {
1453             aopGet (aop, offset, FALSE);
1454             switch (aop->size - offset) {
1455             case 1:
1456                 emit2 ("ld l,!*hl");
1457                 emit2 ("ld h,!immedbyte", 0);
1458                             break;
1459             case 2:
1460               // PENDING: Requires that you are only fetching two bytes.
1461             case 4:
1462                 emit2 ("!ldahli");
1463                 emit2 ("ld h,!*hl");
1464                 emit2 ("ld l,a");
1465                 break;
1466             default:
1467               wassertl (0, "Attempted to fetch too much data into HL");
1468               break;
1469             }
1470         }
1471         else if (IS_Z80 && aop->type == AOP_IY) {
1472             /* Instead of fetching relative to IY, just grab directly
1473                from the address IY refers to */
1474             char *l = aopGetLitWordLong (aop, offset, FALSE);
1475             wassert (l);
1476             emit2 ("ld %s,(%s)", _pairs[pairId].name, l);
1477
1478             if (aop->size < 2) {
1479                 emit2("ld %s,!zero", _pairs[pairId].h);
1480             }
1481         }
1482         else if (pairId == PAIR_IY)
1483           {
1484             if (isPair (aop))
1485               {
1486                 emit2 ("push %s", _pairs[getPairId(aop)].name);
1487                 emit2 ("pop iy");
1488               }
1489             else
1490               {
1491                 bool isUsed;
1492                 PAIR_ID id = makeFreePairId (ic, &isUsed);
1493                 if (isUsed)
1494                   _push (id);
1495                 /* Can't load into parts, so load into HL then exchange. */
1496                 emit2 ("ld %s,%s", _pairs[id].l, aopGet (aop, offset, FALSE));
1497                 emit2 ("ld %s,%s", _pairs[id].h, aopGet (aop, offset + 1, FALSE));
1498                 emit2 ("push %s", _pairs[id].name);
1499                 emit2 ("pop iy");
1500                 if (isUsed)
1501                   _pop (id);
1502               }
1503           }
1504         else if (isUnsplitable(aop))
1505           {
1506             emit2("push %s", _pairs[getPairId(aop)].name);
1507             emit2("pop %s", _pairs[pairId].name);
1508           }
1509         else
1510           {
1511             emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
1512             emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
1513           }
1514         /* PENDING: check? */
1515         if (pairId == PAIR_HL)
1516             spillPair (PAIR_HL);
1517     }
1518 }
1519
1520 static void
1521 fetchPair (PAIR_ID pairId, asmop * aop)
1522 {
1523   fetchPairLong (pairId, aop, NULL, 0);
1524 }
1525
1526 static void
1527 fetchHL (asmop * aop)
1528 {
1529   fetchPair (PAIR_HL, aop);
1530 }
1531
1532 static void
1533 setupPairFromSP (PAIR_ID id, int offset)
1534 {
1535   wassertl (id == PAIR_HL, "Setup relative to SP only implemented for HL");
1536
1537   if (_G.preserveCarry)
1538     {
1539       _push (PAIR_AF);
1540       offset += 2;
1541     }
1542
1543   if (offset < INT8MIN || offset > INT8MAX)
1544     {
1545       emit2 ("ld hl,!immedword", offset);
1546       emit2 ("add hl,sp");
1547     }
1548   else
1549     {
1550           emit2 ("!ldahlsp", offset);
1551     }
1552
1553   if (_G.preserveCarry)
1554     {
1555       _pop (PAIR_AF);
1556       offset -= 2;
1557     }
1558 }
1559
1560 static void
1561 setupPair (PAIR_ID pairId, asmop * aop, int offset)
1562 {
1563   switch (aop->type)
1564     {
1565     case AOP_IY:
1566       wassertl (pairId == PAIR_IY || pairId == PAIR_HL, "AOP_IY must be in IY or HL");
1567       fetchLitPair (pairId, aop, 0);
1568       break;
1569
1570     case AOP_HL:
1571       wassertl (pairId == PAIR_HL, "AOP_HL must be in HL");
1572
1573       fetchLitPair (pairId, aop, offset);
1574       _G.pairs[pairId].offset = offset;
1575       break;
1576
1577     case AOP_EXSTK:
1578       wassertl (IS_Z80, "Only the Z80 has an extended stack");
1579       wassertl (pairId == PAIR_IY || pairId == PAIR_HL, "The Z80 extended stack must be in IY or HL");
1580
1581       {
1582         int offset = aop->aopu.aop_stk + _G.stack.offset;
1583
1584         if (_G.pairs[pairId].last_type == aop->type &&
1585             _G.pairs[pairId].offset == offset)
1586           {
1587             /* Already setup */
1588           }
1589         else
1590           {
1591             /* PENDING: Do this better. */
1592             if (_G.preserveCarry)
1593               _push (PAIR_AF);
1594             sprintf (buffer, "%d", offset + _G.stack.pushed);
1595             emit2 ("ld %s,!hashedstr", _pairs[pairId].name, buffer);
1596             emit2 ("add %s,sp", _pairs[pairId].name);
1597             _G.pairs[pairId].last_type = aop->type;
1598             _G.pairs[pairId].offset = offset;
1599             if (_G.preserveCarry)
1600               _pop (PAIR_AF);
1601           }
1602       }
1603       break;
1604
1605     case AOP_STK:
1606       {
1607         /* Doesnt include _G.stack.pushed */
1608         int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
1609
1610         if (aop->aopu.aop_stk > 0)
1611           {
1612             abso += _G.stack.param_offset;
1613           }
1614         assert (pairId == PAIR_HL);
1615         /* In some cases we can still inc or dec hl */
1616         if (_G.pairs[pairId].last_type == AOP_STK && abs (_G.pairs[pairId].offset - abso) < 3)
1617           {
1618             adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
1619           }
1620         else
1621           {
1622             setupPairFromSP (PAIR_HL, abso + _G.stack.pushed);
1623           }
1624         _G.pairs[pairId].offset = abso;
1625         break;
1626       }
1627
1628     case AOP_PAIRPTR:
1629       if (pairId != aop->aopu.aop_pairId)
1630         genMovePairPair(aop->aopu.aop_pairId, pairId);
1631       adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, offset);
1632       break;
1633
1634     default:
1635       wassert (0);
1636     }
1637   _G.pairs[pairId].last_type = aop->type;
1638 }
1639
1640 static void
1641 emitLabel (int key)
1642 {
1643   emit2 ("!tlabeldef", key);
1644   _G.lines.current->isLabel = 1;
1645   spillCached ();
1646 }
1647
1648 /*-----------------------------------------------------------------*/
1649 /* aopGet - for fetching value of the aop                          */
1650 /*-----------------------------------------------------------------*/
1651 static const char *
1652 aopGet (asmop * aop, int offset, bool bit16)
1653 {
1654   // char *s = buffer;
1655
1656   /* offset is greater than size then zero */
1657   /* PENDING: this seems a bit screwed in some pointer cases. */
1658   if (offset > (aop->size - 1) &&
1659       aop->type != AOP_LIT)
1660     {
1661       tsprintf (buffer, sizeof(buffer), "!zero");
1662       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1663     }
1664
1665   /* depending on type */
1666   switch (aop->type)
1667     {
1668     case AOP_DUMMY:
1669       tsprintf (buffer, sizeof(buffer), "!zero");
1670       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1671
1672     case AOP_IMMD:
1673       /* PENDING: re-target */
1674       if (bit16)
1675         tsprintf (buffer, sizeof(buffer), "!immedwords", aop->aopu.aop_immd);
1676       else
1677         switch (offset)
1678           {
1679           case 2:
1680             tsprintf (buffer, sizeof(buffer), "!bankimmeds", aop->aopu.aop_immd);
1681             break;
1682           case 1:
1683             tsprintf (buffer, sizeof(buffer), "!msbimmeds", aop->aopu.aop_immd);
1684             break;
1685           case 0:
1686             tsprintf (buffer, sizeof(buffer), "!lsbimmeds", aop->aopu.aop_immd);
1687             break;
1688           default:
1689             wassertl (0, "Fetching from beyond the limits of an immediate value.");
1690           }
1691
1692       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1693
1694     case AOP_DIR:
1695       wassert (IS_GB);
1696       emit2 ("ld a,(%s+%d)", aop->aopu.aop_dir, offset);
1697       SNPRINTF (buffer, sizeof(buffer), "a");
1698
1699       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1700
1701     case AOP_SFR:
1702       if( IS_GB )
1703       {
1704         // wassert (IS_GB);
1705         emit2 ("ldh a,(%s+%d)", aop->aopu.aop_dir, offset);
1706         SNPRINTF (buffer, sizeof(buffer), "a");
1707
1708         return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1709       }
1710       else
1711       { /*.p.t.20030716 handling for i/o port read access for Z80 */
1712         if( aop->paged )
1713         { /* banked mode */
1714           /* reg A goes to address bits 15-8 during "in a,(x)" instruction */
1715           emit2( "ld a,!msbimmeds", aop->aopu.aop_dir);
1716           emit2( "in a,(!lsbimmeds)", aop->aopu.aop_dir);
1717         }
1718         else if( z80_opts.port_mode == 180 )
1719         { /* z180 in0/out0 mode */
1720           emit2( "in0 a,(%s)", aop->aopu.aop_dir );
1721         }
1722         else
1723         { /* 8 bit mode */
1724           emit2( "in a,(%s)", aop->aopu.aop_dir );
1725         }
1726
1727         SNPRINTF (buffer, sizeof(buffer), "a");
1728
1729         return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1730       }
1731
1732     case AOP_REG:
1733       return aop->aopu.aop_reg[offset]->name;
1734
1735     case AOP_HL:
1736       wassert (IS_GB);
1737       setupPair (PAIR_HL, aop, offset);
1738       tsprintf (buffer, sizeof(buffer), "!*hl");
1739
1740       return traceAlloc(&_G.trace.aops, Safe_strdup (buffer));
1741
1742     case AOP_IY:
1743       wassert (IS_Z80);
1744       setupPair (PAIR_IY, aop, offset);
1745       tsprintf (buffer, sizeof(buffer), "!*iyx", offset);
1746
1747       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1748
1749     case AOP_EXSTK:
1750       wassert (IS_Z80);
1751       setupPair (PAIR_IY, aop, offset);
1752       tsprintf (buffer, sizeof(buffer), "!*iyx", offset, offset);
1753
1754       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1755
1756     case AOP_STK:
1757       if (IS_GB)
1758         {
1759           setupPair (PAIR_HL, aop, offset);
1760           tsprintf (buffer, sizeof(buffer), "!*hl");
1761         }
1762       else
1763         {
1764           if (aop->aopu.aop_stk >= 0)
1765             offset += _G.stack.param_offset;
1766           tsprintf (buffer, sizeof(buffer),
1767                     "!*ixx", aop->aopu.aop_stk + offset);
1768         }
1769
1770       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1771
1772     case AOP_CRY:
1773       wassertl (0, "Tried to fetch from a bit variable");
1774
1775     case AOP_ACC:
1776       if (!offset)
1777         {
1778           return "a";
1779         }
1780       else
1781         {
1782           tsprintf(buffer, sizeof(buffer), "!zero");
1783           return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1784         }
1785
1786     case AOP_HLREG:
1787       wassert (offset < 2);
1788       return aop->aopu.aop_str[offset];
1789
1790     case AOP_LIT:
1791       return aopLiteral (aop->aopu.aop_lit, offset);
1792
1793     case AOP_SIMPLELIT:
1794       {
1795         unsigned long v = aop->aopu.aop_simplelit;
1796
1797         v >>= (offset * 8);
1798         tsprintf (buffer, sizeof(buffer),
1799                   "!immedbyte", (unsigned int) v & 0xff);
1800
1801         return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1802       }
1803     case AOP_STR:
1804       aop->coff = offset;
1805       return aop->aopu.aop_str[offset];
1806
1807     case AOP_PAIRPTR:
1808       setupPair (aop->aopu.aop_pairId, aop, offset);
1809       if (aop->aopu.aop_pairId==PAIR_IX)
1810         SNPRINTF (buffer, sizeof(buffer),
1811                   "!*ixx", 0);
1812       else if (aop->aopu.aop_pairId==PAIR_IY)
1813         SNPRINTF (buffer, sizeof(buffer),
1814                   "!*iyx", 0);
1815       else
1816         SNPRINTF (buffer, sizeof(buffer),
1817                   "(%s)", _pairs[aop->aopu.aop_pairId].name);
1818
1819       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1820
1821     default:
1822       break;
1823     }
1824   wassertl (0, "aopget got unsupported aop->type");
1825   exit (0);
1826 }
1827
1828 bool
1829 isRegString (const char *s)
1830 {
1831   if (!strcmp (s, "b") ||
1832       !strcmp (s, "c") ||
1833       !strcmp (s, "d") ||
1834       !strcmp (s, "e") ||
1835       !strcmp (s, "a") ||
1836       !strcmp (s, "h") ||
1837       !strcmp (s, "l"))
1838     return TRUE;
1839   return FALSE;
1840 }
1841
1842 bool
1843 isConstant (const char *s)
1844 {
1845   /* This is a bit of a hack... */
1846   return (*s == '#' || *s == '$');
1847 }
1848
1849 bool
1850 canAssignToPtr (const char *s)
1851 {
1852   if (isRegString (s))
1853     return TRUE;
1854   if (isConstant (s))
1855     return TRUE;
1856   return FALSE;
1857 }
1858
1859 /*-----------------------------------------------------------------*/
1860 /* aopPut - puts a string for a aop                                */
1861 /*-----------------------------------------------------------------*/
1862 static void
1863 aopPut (asmop * aop, const char *s, int offset)
1864 {
1865   char buffer2[256];
1866
1867   if (aop->size && offset > (aop->size - 1))
1868     {
1869       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1870               "aopPut got offset > aop->size");
1871       exit (0);
1872     }
1873
1874   // PENDING
1875   tsprintf(buffer2, sizeof(buffer2), s);
1876   s = buffer2;
1877
1878   /* will assign value to value */
1879   /* depending on where it is ofcourse */
1880   switch (aop->type)
1881     {
1882     case AOP_DUMMY:
1883       _moveA (s);  /* in case s is volatile */
1884       break;
1885
1886     case AOP_DIR:
1887       /* Direct.  Hmmm. */
1888       wassert (IS_GB);
1889       if (strcmp (s, "a"))
1890         emit2 ("ld a,%s", s);
1891       emit2 ("ld (%s+%d),a", aop->aopu.aop_dir, offset);
1892       break;
1893
1894     case AOP_SFR:
1895       if( IS_GB )
1896         {
1897           //  wassert (IS_GB);
1898           if (strcmp (s, "a"))
1899             emit2 ("ld a,%s", s);
1900           emit2 ("ldh (%s+%d),a", aop->aopu.aop_dir, offset);
1901         }
1902       else
1903         { /*.p.t.20030716 handling for i/o port read access for Z80 */
1904           if (aop->paged)
1905             { /* banked mode */
1906               if (aop->bcInUse)
1907                 emit2( "push bc" );
1908
1909               if (strlen(s) != 1
1910                   || (s[0] != 'a' && s[0] != 'd' && s[0] != 'e'
1911                       && s[0] != 'h' && s[0] != 'l'))
1912                 {
1913                   emit2( "ld a,%s", s );
1914                   s = "a";
1915                 }
1916
1917               emit2( "ld bc,#%s", aop->aopu.aop_dir );
1918               emit2( "out (c),%s", s );
1919
1920               if( aop->bcInUse )
1921                 emit2( "pop bc"    );
1922               else
1923                 spillPair (PAIR_BC);
1924             }
1925           else if( z80_opts.port_mode == 180 )
1926             { /* z180 in0/out0 mode */
1927               emit2( "ld a,%s", s );
1928               emit2( "out0 (%s),a", aop->aopu.aop_dir );
1929             }
1930           else
1931             { /* 8 bit mode */
1932               emit2( "ld a,%s", s );
1933               emit2( "out (%s),a", aop->aopu.aop_dir );
1934             }
1935         }
1936       break;
1937
1938     case AOP_REG:
1939       if (!strcmp (s, "!*hl"))
1940         emit2 ("ld %s,!*hl", aop->aopu.aop_reg[offset]->name);
1941       else
1942         emit2 ("ld %s,%s",
1943                aop->aopu.aop_reg[offset]->name, s);
1944       spillPairReg(aop->aopu.aop_reg[offset]->name);
1945       break;
1946
1947     case AOP_IY:
1948       wassert (!IS_GB);
1949       if (!canAssignToPtr (s))
1950         {
1951           emit2 ("ld a,%s", s);
1952           setupPair (PAIR_IY, aop, offset);
1953           emit2 ("ld !*iyx,a", offset);
1954         }
1955       else
1956         {
1957           setupPair (PAIR_IY, aop, offset);
1958           emit2 ("ld !*iyx,%s", offset, s);
1959         }
1960       break;
1961
1962     case AOP_HL:
1963       wassert (IS_GB);
1964       /* PENDING: for re-target */
1965       if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1966         {
1967           emit2 ("ld a,!*hl");
1968           s = "a";
1969         }
1970       setupPair (PAIR_HL, aop, offset);
1971
1972       emit2 ("ld !*hl,%s", s);
1973       break;
1974
1975     case AOP_EXSTK:
1976       wassert (!IS_GB);
1977       if (!canAssignToPtr (s))
1978         {
1979           emit2 ("ld a,%s", s);
1980           setupPair (PAIR_IY, aop, offset);
1981           emit2 ("ld !*iyx,a", offset);
1982         }
1983       else
1984         {
1985           setupPair (PAIR_IY, aop, offset);
1986           emit2 ("ld !*iyx,%s", offset, s);
1987         }
1988       break;
1989
1990     case AOP_STK:
1991       if (IS_GB)
1992         {
1993           /* PENDING: re-target */
1994           if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1995             {
1996               emit2 ("ld a,!*hl");
1997               s = "a";
1998             }
1999           setupPair (PAIR_HL, aop, offset);
2000           if (!canAssignToPtr (s))
2001             {
2002               emit2 ("ld a,%s", s);
2003               emit2 ("ld !*hl,a");
2004             }
2005           else
2006             emit2 ("ld !*hl,%s", s);
2007         }
2008       else
2009         {
2010           if (aop->aopu.aop_stk >= 0)
2011             offset += _G.stack.param_offset;
2012           if (!canAssignToPtr (s))
2013             {
2014               emit2 ("ld a,%s", s);
2015               emit2 ("ld !*ixx,a", aop->aopu.aop_stk + offset);
2016             }
2017           else
2018             {
2019               emit2 ("ld !*ixx,%s", aop->aopu.aop_stk + offset, s);
2020             }
2021         }
2022       break;
2023
2024     case AOP_CRY:
2025       /* if bit variable */
2026       if (!aop->aopu.aop_dir)
2027         {
2028           emit2 ("ld a,!zero");
2029           emit2 ("rla");
2030         }
2031       else
2032         {
2033           /* In bit space but not in C - cant happen */
2034           wassertl (0, "Tried to write into a bit variable");
2035         }
2036       break;
2037
2038     case AOP_STR:
2039       aop->coff = offset;
2040       if (strcmp (aop->aopu.aop_str[offset], s))
2041         {
2042           emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
2043         }
2044       spillPairReg(aop->aopu.aop_str[offset]);
2045       break;
2046
2047     case AOP_ACC:
2048       aop->coff = offset;
2049       if (!offset && (strcmp (s, "acc") == 0))
2050         break;
2051       if (offset > 0)
2052         {
2053           wassertl (0, "Tried to access past the end of A");
2054         }
2055       else
2056         {
2057           if (strcmp (aop->aopu.aop_str[offset], s))
2058             {
2059               emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
2060               spillPairReg(aop->aopu.aop_str[offset]);
2061             }
2062         }
2063       break;
2064
2065     case AOP_HLREG:
2066       wassert (offset < 2);
2067       emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
2068       spillPairReg(aop->aopu.aop_str[offset]);
2069       break;
2070
2071     case AOP_PAIRPTR:
2072       setupPair (aop->aopu.aop_pairId, aop, offset);
2073       if (aop->aopu.aop_pairId==PAIR_IX)
2074         emit2 ("ld !*ixx,%s", 0, s);
2075       else if (aop->aopu.aop_pairId==PAIR_IY)
2076         emit2 ("ld !*iyx,%s", 0, s);
2077       else
2078         emit2 ("ld (%s),%s", _pairs[aop->aopu.aop_pairId].name, s);
2079       break;
2080
2081     default:
2082       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2083               "aopPut got unsupported aop->type");
2084       exit (0);
2085     }
2086 }
2087
2088 #define AOP(op) op->aop
2089 #define AOP_TYPE(op) AOP(op)->type
2090 #define AOP_SIZE(op) AOP(op)->size
2091 #define AOP_NEEDSACC(x) (AOP(x) && ((AOP_TYPE(x) == AOP_CRY) || (AOP_TYPE(x) == AOP_SFR)))
2092 #define AOP_IS_PAIRPTR(x, p) (AOP_TYPE (x) == AOP_PAIRPTR && AOP (x)->aopu.aop_pairId == p)
2093
2094 static void
2095 commitPair (asmop * aop, PAIR_ID id)
2096 {
2097   /* PENDING: Verify this. */
2098   if (id == PAIR_HL && requiresHL (aop) && IS_GB)
2099     {
2100       emit2 ("ld a,l");
2101       emit2 ("ld d,h");
2102       aopPut (aop, "a", 0);
2103       aopPut (aop, "d", 1);
2104     }
2105   else
2106     {
2107       /* Special cases */
2108       if (id == PAIR_HL && aop->type == AOP_IY && aop->size == 2)
2109         {
2110           char *l = aopGetLitWordLong (aop, 0, FALSE);
2111           wassert (l);
2112
2113           emit2 ("ld (%s),%s", l, _pairs[id].name);
2114         }
2115       else
2116         {
2117           aopPut (aop, _pairs[id].l, 0);
2118           aopPut (aop, _pairs[id].h, 1);
2119         }
2120     }
2121 }
2122
2123 /*-----------------------------------------------------------------*/
2124 /* getDataSize - get the operand data size                         */
2125 /*-----------------------------------------------------------------*/
2126 int
2127 getDataSize (operand * op)
2128 {
2129   int size;
2130   size = AOP_SIZE (op);
2131   if (size == 3)
2132     {
2133       /* pointer */
2134       wassertl (0, "Somehow got a three byte data pointer");
2135     }
2136   return size;
2137 }
2138
2139 /*-----------------------------------------------------------------*/
2140 /* movLeft2Result - move byte from left to result                  */
2141 /*-----------------------------------------------------------------*/
2142 static void
2143 movLeft2Result (operand * left, int offl,
2144                 operand * result, int offr, int sign)
2145 {
2146   const char *l;
2147
2148   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
2149     {
2150       l = aopGet (AOP (left), offl, FALSE);
2151
2152       if (!sign)
2153         {
2154           aopPut (AOP (result), l, offr);
2155         }
2156       else
2157         {
2158           if (getDataSize (left) == offl + 1)
2159             {
2160               emit2 ("ld a,%s", l);
2161               aopPut (AOP (result), "a", offr);
2162             }
2163         }
2164     }
2165 }
2166
2167 static void
2168 movLeft2ResultLong (operand * left, int offl,
2169                 operand * result, int offr, int sign,
2170                 int size)
2171 {
2172   if (size == 1)
2173     {
2174       movLeft2Result (left, offl, result, offr, sign);
2175     }
2176   else
2177     {
2178       wassertl (offl == 0 && offr == 0, "Only implemented for zero offset");
2179       wassertl (size == 2, "Only implemented for two bytes or one");
2180
2181       if ( IS_GB && requiresHL ( AOP (left)) && getPairId ( AOP (result)) == PAIR_HL)
2182         {
2183           emit2 ("ld a,%s", aopGet (AOP (left), LSB, FALSE));
2184           emit2 ("ld h,%s", aopGet (AOP (left), MSB16, FALSE));
2185           emit2 ("ld l,a");
2186           spillPair (PAIR_HL);
2187         }
2188       else if ( getPairId ( AOP (result)) == PAIR_IY)
2189         {
2190           PAIR_ID id = getPairId (AOP (left));
2191           if (id != PAIR_INVALID)
2192             {
2193               emit2("push %s", _pairs[id].name);
2194               emit2("pop iy");
2195             }
2196           else
2197             {
2198               /* PENDING */
2199               emitDebug("Error");
2200             }
2201         }
2202       else
2203         {
2204           movLeft2Result (left, offl, result, offr, sign);
2205           movLeft2Result (left, offl+1, result, offr+1, sign);
2206         }
2207     }
2208 }
2209
2210 /** Put Acc into a register set
2211  */
2212 void
2213 outAcc (operand * result)
2214 {
2215   int size, offset;
2216   size = getDataSize (result);
2217   if (size)
2218     {
2219       aopPut (AOP (result), "a", 0);
2220       size--;
2221       offset = 1;
2222       /* unsigned or positive */
2223       while (size--)
2224         {
2225           aopPut (AOP (result), "!zero", offset++);
2226         }
2227     }
2228 }
2229
2230 /** Take the value in carry and put it into a register
2231  */
2232 void
2233 outBitC (operand * result)
2234 {
2235   /* if the result is bit */
2236   if (AOP_TYPE (result) == AOP_CRY)
2237     {
2238       if (!IS_OP_RUONLY (result))
2239         aopPut (AOP (result), "c", 0);
2240     }
2241   else
2242     {
2243       emit2 ("ld a,!zero");
2244       emit2 ("rla");
2245       outAcc (result);
2246     }
2247 }
2248
2249 /*-----------------------------------------------------------------*/
2250 /* toBoolean - emit code for orl a,operator(sizeop)                */
2251 /*-----------------------------------------------------------------*/
2252 void
2253 _toBoolean (operand * oper)
2254 {
2255   int size = AOP_SIZE (oper);
2256   int offset = 0;
2257   if (size > 1)
2258     {
2259       emit2 ("ld a,%s", aopGet (AOP (oper), offset++, FALSE));
2260       size--;
2261       while (size--)
2262         emit2 ("or a,%s", aopGet (AOP (oper), offset++, FALSE));
2263     }
2264   else
2265     {
2266       if (AOP (oper)->type != AOP_ACC)
2267         {
2268           _clearCarry();
2269           emit2 ("or a,%s", aopGet (AOP (oper), 0, FALSE));
2270         }
2271     }
2272 }
2273
2274
2275 /*-----------------------------------------------------------------*/
2276 /* genNot - generate code for ! operation                          */
2277 /*-----------------------------------------------------------------*/
2278 static void
2279 genNot (iCode * ic)
2280 {
2281
2282   /* assign asmOps to operand & result */
2283   aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2284   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2285
2286   /* if in bit space then a special case */
2287   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2288     {
2289       wassertl (0, "Tried to negate a bit");
2290     }
2291
2292   _toBoolean (IC_LEFT (ic));
2293
2294   /* Not of A:
2295      If A == 0, !A = 1
2296      else A = 0
2297      So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
2298   emit2 ("sub a,!one");
2299   outBitC (IC_RESULT (ic));
2300
2301   /* release the aops */
2302   freeAsmop (IC_LEFT (ic), NULL, ic);
2303   freeAsmop (IC_RESULT (ic), NULL, ic);
2304 }
2305
2306 /*-----------------------------------------------------------------*/
2307 /* genCpl - generate code for complement                           */
2308 /*-----------------------------------------------------------------*/
2309 static void
2310 genCpl (iCode * ic)
2311 {
2312   int offset = 0;
2313   int size;
2314
2315
2316   /* assign asmOps to operand & result */
2317   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2318   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2319
2320   /* if both are in bit space then
2321      a special case */
2322   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2323       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2324     {
2325       wassertl (0, "Left and the result are in bit space");
2326     }
2327
2328   size = AOP_SIZE (IC_RESULT (ic));
2329   while (size--)
2330     {
2331       const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
2332       _moveA (l);
2333       emit2("cpl");
2334       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2335     }
2336
2337   /* release the aops */
2338   freeAsmop (IC_LEFT (ic), NULL, ic);
2339   freeAsmop (IC_RESULT (ic), NULL, ic);
2340 }
2341
2342 static void
2343 _gbz80_emitAddSubLongLong (iCode *ic, asmop *left, asmop *right, bool isAdd)
2344 {
2345   /* Logic:
2346        ld de,right.lw
2347        setup hl to left
2348        de = hl - de
2349        push flags
2350        store de into result
2351        pop flags
2352        ld de,right.hw
2353        setup hl
2354        de = hl -de
2355        store de into result
2356   */
2357   const char *first = isAdd ? "add" : "sub";
2358   const char *later = isAdd ? "adc" : "sbc";
2359
2360   wassertl (IS_GB, "Code is only relevent to the gbz80");
2361   wassertl (AOP( IC_RESULT (ic))->size == 4, "Only works for four bytes");
2362
2363   fetchPair (PAIR_DE, left);
2364
2365   emit2 ("ld a,e");
2366   emit2 ("%s a,%s", first, aopGet( right, LSB, FALSE));
2367   emit2 ("ld e,a");
2368   emit2 ("ld a,d");
2369   emit2 ("%s a,%s", later, aopGet( right, MSB16, FALSE));
2370
2371   _push (PAIR_AF);
2372   aopPut ( AOP (IC_RESULT (ic)), "a", MSB16);
2373   aopPut ( AOP (IC_RESULT (ic)), "e", LSB);
2374
2375   fetchPairLong (PAIR_DE, left, NULL, MSB24);
2376   aopGet (right, MSB24, FALSE);
2377
2378   _pop (PAIR_AF);
2379   emit2 ("ld a,e");
2380   emit2 ("%s a,%s", later, aopGet( right, MSB24, FALSE));
2381   emit2 ("ld e,a");
2382   emit2 ("ld a,d");
2383   emit2 ("%s a,%s", later, aopGet( right, MSB32, FALSE));
2384
2385   aopPut ( AOP (IC_RESULT (ic)), "a", MSB32);
2386   aopPut ( AOP (IC_RESULT (ic)), "e", MSB24);
2387 }
2388
2389 static void
2390 _gbz80_emitAddSubLong (iCode *ic, bool isAdd)
2391 {
2392   _gbz80_emitAddSubLongLong (ic, AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)), isAdd);
2393 }
2394
2395 /*-----------------------------------------------------------------*/
2396 /* genUminusFloat - unary minus for floating points                */
2397 /*-----------------------------------------------------------------*/
2398 static void
2399 genUminusFloat (operand * op, operand * result)
2400 {
2401   int size, offset = 0;
2402
2403   emitDebug("; genUminusFloat");
2404
2405   /* for this we just need to flip the
2406      first bit then copy the rest in place */
2407   size = AOP_SIZE (op) - 1;
2408
2409   _moveA(aopGet (AOP (op), MSB32, FALSE));
2410
2411   emit2("xor a,!immedbyte", 0x80);
2412   aopPut (AOP (result), "a", MSB32);
2413
2414   while (size--)
2415     {
2416       aopPut (AOP (result), aopGet (AOP (op), offset, FALSE), offset);
2417       offset++;
2418     }
2419 }
2420
2421 /*-----------------------------------------------------------------*/
2422 /* genUminus - unary minus code generation                         */
2423 /*-----------------------------------------------------------------*/
2424 static void
2425 genUminus (iCode * ic)
2426 {
2427   int offset, size;
2428   sym_link *optype, *rtype;
2429
2430   /* assign asmops */
2431   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2432   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2433
2434   /* if both in bit space then special
2435      case */
2436   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2437       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2438     {
2439       wassertl (0, "Left and right are in bit space");
2440       goto release;
2441     }
2442
2443   optype = operandType (IC_LEFT (ic));
2444   rtype = operandType (IC_RESULT (ic));
2445
2446   /* if float then do float stuff */
2447   if (IS_FLOAT (optype))
2448     {
2449       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2450       goto release;
2451     }
2452
2453   /* otherwise subtract from zero */
2454   size = AOP_SIZE (IC_LEFT (ic));
2455
2456   if (AOP_SIZE (IC_RESULT (ic)) == 4 && IS_GB)
2457     {
2458       /* Create a new asmop with value zero */
2459       asmop *azero = newAsmop (AOP_SIMPLELIT);
2460       azero->aopu.aop_simplelit = 0;
2461       azero->size = size;
2462       _gbz80_emitAddSubLongLong (ic, azero, AOP (IC_LEFT (ic)), FALSE);
2463       goto release;
2464     }
2465
2466   offset = 0;
2467   _clearCarry();
2468   while (size--)
2469     {
2470       const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
2471       emit2 ("ld a,!zero");
2472       emit2 ("sbc a,%s", l);
2473       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2474     }
2475
2476   /* if any remaining bytes in the result */
2477   /* we just need to propagate the sign   */
2478   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2479     {
2480       emit2 ("rlc a");
2481       emit2 ("sbc a,a");
2482       while (size--)
2483         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2484     }
2485
2486 release:
2487   /* release the aops */
2488   freeAsmop (IC_LEFT (ic), NULL, ic);
2489   freeAsmop (IC_RESULT (ic), NULL, ic);
2490 }
2491
2492 /*-----------------------------------------------------------------*/
2493 /* assignResultValue -               */
2494 /*-----------------------------------------------------------------*/
2495 void
2496 assignResultValue (operand * oper)
2497 {
2498   int size = AOP_SIZE (oper);
2499   bool topInA = 0;
2500
2501   wassertl (size <= 4, "Got a result that is bigger than four bytes");
2502   topInA = requiresHL (AOP (oper));
2503
2504   if (IS_GB && size == 4 && requiresHL (AOP (oper)))
2505     {
2506       /* We do it the hard way here. */
2507       _push (PAIR_HL);
2508       aopPut (AOP (oper), _fReturn[0], 0);
2509       aopPut (AOP (oper), _fReturn[1], 1);
2510       _pop (PAIR_DE);
2511       aopPut (AOP (oper), _fReturn[0], 2);
2512       aopPut (AOP (oper), _fReturn[1], 3);
2513     }
2514   else
2515     {
2516       if ((AOP_TYPE (oper) == AOP_REG) && (AOP_SIZE (oper) == 4) &&
2517           !strcmp (AOP (oper)->aopu.aop_reg[size-1]->name, _fReturn[size-2]))
2518         {
2519           size--;
2520           _emitMove ("a", _fReturn[size-1]);
2521           _emitMove (_fReturn[size-1], _fReturn[size]);
2522           _emitMove (_fReturn[size], "a");
2523           aopPut (AOP (oper), _fReturn[size], size-1);
2524           size--;
2525         }
2526       while (size--)
2527         {
2528           aopPut (AOP (oper), _fReturn[size], size);
2529         }
2530     }
2531 }
2532
2533 /** Simple restore that doesn't take into account what is used in the
2534     return.
2535 */
2536 static void
2537 _restoreRegsAfterCall(void)
2538 {
2539   if (_G.stack.pushedDE)
2540     {
2541       _pop ( PAIR_DE);
2542       _G.stack.pushedDE = FALSE;
2543     }
2544   if (_G.stack.pushedBC)
2545     {
2546       _pop ( PAIR_BC);
2547       _G.stack.pushedBC = FALSE;
2548     }
2549   _G.saves.saved = FALSE;
2550 }
2551
2552 static void
2553 _saveRegsForCall(iCode *ic, int sendSetSize)
2554 {
2555   /* Rules:
2556       o Stack parameters are pushed before this function enters
2557       o DE and BC may be used in this function.
2558       o HL and DE may be used to return the result.
2559       o HL and DE may be used to send variables.
2560       o DE and BC may be used to store the result value.
2561       o HL may be used in computing the sent value of DE
2562       o The iPushes for other parameters occur before any addSets
2563
2564      Logic: (to be run inside the first iPush or if none, before sending)
2565       o Compute if DE and/or BC are in use over the call
2566       o Compute if DE is used in the send set
2567       o Compute if DE and/or BC are used to hold the result value
2568       o If (DE is used, or in the send set) and is not used in the result, push.
2569       o If BC is used and is not in the result, push
2570       o
2571       o If DE is used in the send set, fetch
2572       o If HL is used in the send set, fetch
2573       o Call
2574       o ...
2575   */
2576   if (_G.saves.saved == FALSE) {
2577     bool deInUse, bcInUse;
2578     bool deSending;
2579     bool bcInRet = FALSE, deInRet = FALSE;
2580     bitVect *rInUse;
2581
2582     rInUse = bitVectCplAnd (bitVectCopy (ic->rMask),
2583                             z80_rUmaskForOp (IC_RESULT(ic)));
2584
2585     deInUse = bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX);
2586     bcInUse = bitVectBitValue (rInUse, B_IDX) || bitVectBitValue(rInUse, C_IDX);
2587
2588     deSending = (sendSetSize > 1);
2589
2590     emitDebug ("; _saveRegsForCall: sendSetSize: %u deInUse: %u bcInUse: %u deSending: %u", sendSetSize, deInUse, bcInUse, deSending);
2591
2592     if (bcInUse && bcInRet == FALSE) {
2593       _push(PAIR_BC);
2594       _G.stack.pushedBC = TRUE;
2595     }
2596     if (deInUse && deInRet == FALSE) {
2597       _push(PAIR_DE);
2598       _G.stack.pushedDE = TRUE;
2599     }
2600
2601     _G.saves.saved = TRUE;
2602   }
2603   else {
2604     /* Already saved. */
2605   }
2606 }
2607
2608 /*-----------------------------------------------------------------*/
2609 /* genIpush - genrate code for pushing this gets a little complex  */
2610 /*-----------------------------------------------------------------*/
2611 static void
2612 genIpush (iCode * ic)
2613 {
2614   int size, offset = 0;
2615   const char *l;
2616
2617   /* if this is not a parm push : ie. it is spill push
2618      and spill push is always done on the local stack */
2619   if (!ic->parmPush)
2620     {
2621       wassertl(0, "Encountered an unsupported spill push.");
2622       return;
2623     }
2624
2625   if (_G.saves.saved == FALSE) {
2626     /* Caller saves, and this is the first iPush. */
2627     /* Scan ahead until we find the function that we are pushing parameters to.
2628        Count the number of addSets on the way to figure out what registers
2629        are used in the send set.
2630     */
2631     int nAddSets = 0;
2632     iCode *walk = ic->next;
2633
2634     while (walk) {
2635       if (walk->op == SEND) {
2636         nAddSets++;
2637       }
2638       else if (walk->op == CALL || walk->op == PCALL) {
2639         /* Found it. */
2640         break;
2641       }
2642       else {
2643         /* Keep looking. */
2644       }
2645       walk = walk->next;
2646     }
2647     _saveRegsForCall(walk, nAddSets);
2648   }
2649   else {
2650     /* Already saved by another iPush. */
2651   }
2652
2653   /* then do the push */
2654   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2655
2656   size = AOP_SIZE (IC_LEFT (ic));
2657
2658   if (isPair (AOP (IC_LEFT (ic))) && size == 2)
2659     {
2660       _G.stack.pushed += 2;
2661       emit2 ("push %s", getPairName (AOP (IC_LEFT (ic))));
2662     }
2663   else
2664     {
2665       if (size == 2)
2666         {
2667           fetchHL (AOP (IC_LEFT (ic)));
2668           emit2 ("push hl");
2669           spillPair (PAIR_HL);
2670           _G.stack.pushed += 2;
2671           goto release;
2672         }
2673       if (size == 4)
2674         {
2675           fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 2);
2676           emit2 ("push hl");
2677           spillPair (PAIR_HL);
2678           _G.stack.pushed += 2;
2679           fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 0);
2680           emit2 ("push hl");
2681           spillPair (PAIR_HL);
2682           _G.stack.pushed += 2;
2683           goto release;
2684         }
2685       offset = size;
2686       while (size--)
2687         {
2688           if (AOP (IC_LEFT (ic))->type == AOP_IY)
2689             {
2690               char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
2691               wassert (l);
2692               emit2 ("ld a,(%s)", l);
2693               emit2 ("push af");
2694             }
2695           else
2696             {
2697               l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
2698               if (!strcmp(l, "b"))
2699                 emit2 ("push bc");
2700               else if (!strcmp(l, "d"))
2701                 emit2 ("push de");
2702               else if (!strcmp(l, "h"))
2703                 emit2 ("push hl");
2704               else
2705                 {
2706                   emit2 ("ld a,%s", l);
2707                   emit2 ("push af");
2708                 }
2709             }
2710           emit2 ("inc sp");
2711           _G.stack.pushed++;
2712         }
2713     }
2714 release:
2715   freeAsmop (IC_LEFT (ic), NULL, ic);
2716 }
2717
2718 /*-----------------------------------------------------------------*/
2719 /* genIpop - recover the registers: can happen only for spilling   */
2720 /*-----------------------------------------------------------------*/
2721 static void
2722 genIpop (iCode * ic)
2723 {
2724   int size, offset;
2725
2726
2727   /* if the temp was not pushed then */
2728   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2729     return;
2730
2731   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2732   size = AOP_SIZE (IC_LEFT (ic));
2733   offset = (size - 1);
2734   if (isPair (AOP (IC_LEFT (ic))))
2735     {
2736       emit2 ("pop %s", getPairName (AOP (IC_LEFT (ic))));
2737     }
2738   else
2739     {
2740       while (size--)
2741         {
2742           emit2 ("dec sp");
2743           emit2 ("pop hl");
2744           spillPair (PAIR_HL);
2745           aopPut (AOP (IC_LEFT (ic)), "l", offset--);
2746         }
2747     }
2748
2749   freeAsmop (IC_LEFT (ic), NULL, ic);
2750 }
2751
2752 /* This is quite unfortunate */
2753 static void
2754 setArea (int inHome)
2755 {
2756   /*
2757     static int lastArea = 0;
2758
2759      if (_G.in_home != inHome) {
2760      if (inHome) {
2761      const char *sz = port->mem.code_name;
2762      port->mem.code_name = "HOME";
2763      emit2("!area", CODE_NAME);
2764      port->mem.code_name = sz;
2765      }
2766      else
2767      emit2("!area", CODE_NAME); */
2768   _G.in_home = inHome;
2769   //    }
2770 }
2771
2772 static bool
2773 isInHome (void)
2774 {
2775   return _G.in_home;
2776 }
2777
2778 static int
2779 _opUsesPair (operand * op, iCode * ic, PAIR_ID pairId)
2780 {
2781   int ret = 0;
2782   asmop *aop;
2783   symbol *sym = OP_SYMBOL (op);
2784
2785   if (sym->isspilt || sym->nRegs == 0)
2786     return 0;
2787
2788   aopOp (op, ic, FALSE, FALSE);
2789
2790   aop = AOP (op);
2791   if (aop->type == AOP_REG)
2792     {
2793       int i;
2794       for (i = 0; i < aop->size; i++)
2795         {
2796           if (pairId == PAIR_DE)
2797             {
2798               emitDebug ("; name %s", aop->aopu.aop_reg[i]->name);
2799               if (!strcmp (aop->aopu.aop_reg[i]->name, "e"))
2800                 ret++;
2801               if (!strcmp (aop->aopu.aop_reg[i]->name, "d"))
2802                 ret++;
2803             }
2804           else if (pairId == PAIR_BC)
2805             {
2806               emitDebug ("; name %s", aop->aopu.aop_reg[i]->name);
2807               if (!strcmp (aop->aopu.aop_reg[i]->name, "c"))
2808                 ret++;
2809               if (!strcmp (aop->aopu.aop_reg[i]->name, "b"))
2810                 ret++;
2811             }
2812           else
2813             {
2814               wassert (0);
2815             }
2816         }
2817     }
2818
2819   freeAsmop (IC_LEFT (ic), NULL, ic);
2820   return ret;
2821 }
2822
2823 /** Emit the code for a call statement
2824  */
2825 static void
2826 emitCall (iCode * ic, bool ispcall)
2827 {
2828   bool bInRet, cInRet, dInRet, eInRet;
2829   sym_link *dtype = operandType (IC_LEFT (ic));
2830
2831   /* if caller saves & we have not saved then */
2832   if (!ic->regsSaved)
2833     {
2834       /* PENDING */
2835     }
2836
2837   _saveRegsForCall(ic, _G.sendSet ? elementsInSet(_G.sendSet) : 0);
2838
2839   /* if send set is not empty then assign */
2840   if (_G.sendSet)
2841     {
2842       iCode *sic;
2843       int send = 0;
2844       int nSend = elementsInSet(_G.sendSet);
2845       bool swapped = FALSE;
2846
2847       int _z80_sendOrder[] = {
2848         PAIR_BC, PAIR_DE
2849       };
2850
2851       if (nSend > 1) {
2852         /* Check if the parameters are swapped.  If so route through hl instead. */
2853         wassertl (nSend == 2, "Pedantic check.  Code only checks for the two send items case.");
2854
2855         sic = setFirstItem(_G.sendSet);
2856         sic = setNextItem(_G.sendSet);
2857
2858         if (_opUsesPair (IC_LEFT(sic), sic, _z80_sendOrder[0])) {
2859           /* The second send value is loaded from one the one that holds the first
2860              send, i.e. it is overwritten. */
2861           /* Cache the first in HL, and load the second from HL instead. */
2862           emit2 ("ld h,%s", _pairs[_z80_sendOrder[0]].h);
2863           emit2 ("ld l,%s", _pairs[_z80_sendOrder[0]].l);
2864
2865           swapped = TRUE;
2866         }
2867       }
2868
2869       for (sic = setFirstItem (_G.sendSet); sic;
2870            sic = setNextItem (_G.sendSet))
2871         {
2872           int size;
2873           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2874
2875           size = AOP_SIZE (IC_LEFT (sic));
2876           wassertl (size <= 2, "Tried to send a parameter that is bigger than two bytes");
2877           wassertl (_z80_sendOrder[send] != PAIR_INVALID, "Tried to send more parameters than we have registers for");
2878
2879           // PENDING: Mild hack
2880           if (swapped == TRUE && send == 1) {
2881             if (size > 1) {
2882               emit2 ("ld %s,h", _pairs[_z80_sendOrder[send]].h);
2883             }
2884             else {
2885               emit2 ("ld %s,!zero", _pairs[_z80_sendOrder[send]].h);
2886             }
2887             emit2 ("ld %s,l", _pairs[_z80_sendOrder[send]].l);
2888           }
2889           else {
2890             fetchPair(_z80_sendOrder[send], AOP (IC_LEFT (sic)));
2891           }
2892
2893           send++;
2894           freeAsmop (IC_LEFT (sic), NULL, sic);
2895         }
2896       _G.sendSet = NULL;
2897     }
2898
2899   if (ispcall)
2900     {
2901       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2902         {
2903           werror (W_INDIR_BANKED);
2904         }
2905       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2906
2907       if (isLitWord (AOP (IC_LEFT (ic))))
2908         {
2909           emit2 ("call %s", aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE));
2910         }
2911       else
2912         {
2913           symbol *rlbl = newiTempLabel (NULL);
2914           spillPair (PAIR_HL);
2915           emit2 ("ld hl,!immed!tlabel", (rlbl->key + 100));
2916           emit2 ("push hl");
2917           _G.stack.pushed += 2;
2918
2919           fetchHL (AOP (IC_LEFT (ic)));
2920           emit2 ("jp !*hl");
2921           emit2 ("!tlabeldef", (rlbl->key + 100));
2922           _G.lines.current->isLabel = 1;
2923           _G.stack.pushed -= 2;
2924         }
2925       freeAsmop (IC_LEFT (ic), NULL, ic);
2926     }
2927   else
2928     {
2929       char *name = OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2930       OP_SYMBOL (IC_LEFT (ic))->rname :
2931       OP_SYMBOL (IC_LEFT (ic))->name;
2932       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2933         {
2934           emit2 ("call banked_call");
2935           emit2 ("!dws", name);
2936           emit2 ("!dw !bankimmeds", name);
2937         }
2938       else
2939         {
2940           /* make the call */
2941           emit2 ("call %s", name);
2942         }
2943     }
2944   spillCached ();
2945
2946   /* Mark the registers as restored. */
2947   _G.saves.saved = FALSE;
2948
2949   /* if we need assign a result value */
2950   if ((IS_ITEMP (IC_RESULT (ic)) &&
2951        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2952         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2953       IS_TRUE_SYMOP (IC_RESULT (ic)))
2954     {
2955       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2956
2957       assignResultValue (IC_RESULT (ic));
2958
2959       freeAsmop (IC_RESULT (ic), NULL, ic);
2960     }
2961
2962   /* adjust the stack for parameters if required */
2963   if (ic->parmBytes)
2964     {
2965       int i = ic->parmBytes;
2966
2967       _G.stack.pushed -= i;
2968       if (IS_GB)
2969         {
2970           emit2 ("!ldaspsp", i);
2971         }
2972       else
2973         {
2974           spillCached ();
2975           if (i > 8)
2976             {
2977               emit2 ("ld iy,!immedword", i);
2978               emit2 ("add iy,sp");
2979               emit2 ("ld sp,iy");
2980             }
2981           else
2982             {
2983               while (i > 1)
2984                 {
2985                   emit2 ("pop af");
2986                   i -= 2;
2987                 }
2988               if (i)
2989                 {
2990                   emit2 ("inc sp");
2991                 }
2992             }
2993         }
2994     }
2995
2996   spillCached ();
2997   if (IC_RESULT (ic))
2998     {
2999       bitVect *result = z80_rUmaskForOp (IC_RESULT (ic));
3000       bInRet = bitVectBitValue(result, B_IDX);
3001       cInRet = bitVectBitValue(result, C_IDX);
3002       dInRet = bitVectBitValue(result, D_IDX);
3003       eInRet = bitVectBitValue(result, E_IDX);
3004     }
3005   else
3006     {
3007       bInRet = FALSE;
3008       cInRet = FALSE;
3009       dInRet = FALSE;
3010       eInRet = FALSE;
3011     }
3012
3013   if (_G.stack.pushedDE)
3014     {
3015       if (dInRet && eInRet)
3016         {
3017           wassertl (0, "Shouldn't push DE if it's wiped out by the return");
3018         }
3019       else if (dInRet)
3020         {
3021           /* Only restore E */
3022           emit2 ("ld a,d");
3023           _pop (PAIR_DE);
3024           emit2 ("ld d,a");
3025         }
3026       else if (eInRet)
3027         {
3028           /* Only restore D */
3029           _pop (PAIR_AF);
3030           emit2 ("ld d,a");
3031         }
3032       else
3033         {
3034           _pop (PAIR_DE);
3035         }
3036       _G.stack.pushedDE = FALSE;
3037     }
3038
3039   if (_G.stack.pushedBC)
3040     {
3041       if (bInRet && cInRet)
3042         {
3043           wassertl (0, "Shouldn't push BC if it's wiped out by the return");
3044         }
3045       else if (bInRet)
3046         {
3047           /* Only restore C */
3048           emit2 ("ld a,b");
3049           _pop (PAIR_BC);
3050           emit2 ("ld b,a");
3051         }
3052       else if (cInRet)
3053         {
3054           /* Only restore B */
3055           _pop (PAIR_AF);
3056           emit2 ("ld b,a");
3057         }
3058       else
3059         {
3060           _pop (PAIR_BC);
3061         }
3062       _G.stack.pushedBC = FALSE;
3063     }
3064 }
3065
3066 /*-----------------------------------------------------------------*/
3067 /* genCall - generates a call statement                            */
3068 /*-----------------------------------------------------------------*/
3069 static void
3070 genCall (iCode * ic)
3071 {
3072   emitCall (ic, FALSE);
3073 }
3074
3075 /*-----------------------------------------------------------------*/
3076 /* genPcall - generates a call by pointer statement                */
3077 /*-----------------------------------------------------------------*/
3078 static void
3079 genPcall (iCode * ic)
3080 {
3081   emitCall (ic, TRUE);
3082 }
3083
3084 /*-----------------------------------------------------------------*/
3085 /* resultRemat - result  is rematerializable                       */
3086 /*-----------------------------------------------------------------*/
3087 static int
3088 resultRemat (iCode * ic)
3089 {
3090   if (SKIP_IC (ic) || ic->op == IFX)
3091     return 0;
3092
3093   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3094     {
3095       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3096       if (sym->remat && !POINTER_SET (ic))
3097         return 1;
3098     }
3099
3100   return 0;
3101 }
3102
3103 extern set *publics;
3104
3105 /*-----------------------------------------------------------------*/
3106 /* genFunction - generated code for function entry                 */
3107 /*-----------------------------------------------------------------*/
3108 static void
3109 genFunction (iCode * ic)
3110 {
3111   bool stackParm;
3112
3113   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3114   sym_link *ftype;
3115
3116   bool bcInUse = FALSE;
3117   bool deInUse = FALSE;
3118
3119   setArea (IFFUNC_NONBANKED (sym->type));
3120
3121   /* PENDING: Reset the receive offset as it
3122      doesn't seem to get reset anywhere else.
3123   */
3124   _G.receiveOffset = 0;
3125
3126   /* Record the last function name for debugging. */
3127   _G.lastFunctionName = sym->rname;
3128
3129   /* Create the function header */
3130   emit2 ("!functionheader", sym->name);
3131   if (!IS_STATIC(sym->etype))
3132     {
3133       sprintf (buffer, "%s_start", sym->rname);
3134       emit2 ("!labeldef", buffer);
3135       _G.lines.current->isLabel = 1;
3136     }
3137   emit2 ("!functionlabeldef", sym->rname);
3138   _G.lines.current->isLabel = 1;
3139
3140   ftype = operandType (IC_LEFT (ic));
3141
3142   if (IFFUNC_ISNAKED(ftype))
3143     {
3144       emitDebug("; naked function: no prologue.");
3145       return;
3146     }
3147
3148   /* if this is an interrupt service routine
3149      then save all potentially used registers. */
3150   if (IFFUNC_ISISR (sym->type))
3151     {
3152       /* If critical function then turn interrupts off */
3153       /* except when no interrupt number is given then it implies the NMI handler */
3154       if (IFFUNC_ISCRITICAL (sym->type) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC))
3155         {
3156           emit2 ("!di");
3157         }
3158
3159       emit2 ("!pusha");
3160     }
3161   else
3162     {
3163       /* This is a non-ISR function.
3164          If critical function then turn interrupts off */
3165       if (IFFUNC_ISCRITICAL (sym->type))
3166         {
3167           if (IS_GB)
3168             {
3169               emit2 ("!di");
3170             }
3171           else
3172             {
3173               //get interrupt enable flag IFF2 into P/O
3174               emit2 ("ld a,i");
3175               emit2 ("!di");
3176               //save P/O flag
3177               emit2 ("push af");
3178             }
3179         }
3180     }
3181
3182   if (options.profile)
3183     {
3184       emit2 ("!profileenter");
3185     }
3186
3187   /* PENDING: callee-save etc */
3188
3189   _G.stack.param_offset = 0;
3190
3191   if (z80_opts.calleeSavesBC)
3192     {
3193       bcInUse = TRUE;
3194     }
3195
3196   /* Detect which registers are used. */
3197   if (IFFUNC_CALLEESAVES(sym->type) && sym->regsUsed)
3198     {
3199       int i;
3200       for (i = 0; i < sym->regsUsed->size; i++)
3201         {
3202           if (bitVectBitValue (sym->regsUsed, i))
3203             {
3204               switch (i)
3205                 {
3206                 case C_IDX:
3207                 case B_IDX:
3208                   bcInUse = TRUE;
3209                   break;
3210                 case D_IDX:
3211                 case E_IDX:
3212                   if (IS_Z80) {
3213                     deInUse = TRUE;
3214                   }
3215                   else {
3216                     /* Other systems use DE as a temporary. */
3217                   }
3218                   break;
3219                 }
3220             }
3221         }
3222     }
3223
3224   if (bcInUse)
3225     {
3226       emit2 ("push bc");
3227       _G.stack.param_offset += 2;
3228     }
3229
3230   _G.calleeSaves.pushedBC = bcInUse;
3231
3232   if (deInUse)
3233     {
3234       emit2 ("push de");
3235       _G.stack.param_offset += 2;
3236     }
3237
3238   _G.calleeSaves.pushedDE = deInUse;
3239
3240   /* adjust the stack for the function */
3241   _G.stack.last = sym->stack;
3242
3243   stackParm = FALSE;
3244   for (sym = setFirstItem (istack->syms); sym;
3245        sym = setNextItem (istack->syms))
3246     {
3247       if (sym->_isparm && !IS_REGPARM (sym->etype))
3248         {
3249           stackParm = TRUE;
3250           break;
3251         }
3252     }
3253   sym = OP_SYMBOL (IC_LEFT (ic));
3254
3255   _G.omitFramePtr = options.ommitFramePtr;
3256   if (IS_Z80 && !stackParm && !sym->stack)
3257     {
3258       /* When the conflicts between AOP_EXSTK && AOP_HLREG are fixed, */
3259       /* the above !sym->stack condition can be removed. -- EEP       */
3260       if (sym->stack)
3261         emit2 ("!ldaspsp", -sym->stack);
3262       _G.omitFramePtr = TRUE;
3263     }
3264   else if (sym->stack && IS_GB && sym->stack > -INT8MIN)
3265     emit2 ("!enterxl", sym->stack);
3266   else if (sym->stack)
3267     emit2 ("!enterx", sym->stack);
3268   else
3269     emit2 ("!enter");
3270
3271   _G.stack.offset = sym->stack;
3272 }
3273
3274 /*-----------------------------------------------------------------*/
3275 /* genEndFunction - generates epilogue for functions               */
3276 /*-----------------------------------------------------------------*/
3277 static void
3278 genEndFunction (iCode * ic)
3279 {
3280   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3281
3282   if (IFFUNC_ISNAKED(sym->type))
3283   {
3284       emitDebug("; naked function: no epilogue.");
3285       return;
3286   }
3287
3288   /* PENDING: calleeSave */
3289   if (IS_Z80 && _G.omitFramePtr)
3290     {
3291       if (_G.stack.offset)
3292         emit2 ("!ldaspsp", _G.stack.offset);
3293     }
3294   else if (_G.stack.offset && IS_GB && _G.stack.offset > INT8MAX)
3295     {
3296       emit2 ("!leavexl", _G.stack.offset);
3297     }
3298   else if (_G.stack.offset)
3299     {
3300       emit2 ("!leavex", _G.stack.offset);
3301     }
3302   else
3303     {
3304       emit2 ("!leave");
3305     }
3306
3307   if (_G.calleeSaves.pushedDE)
3308     {
3309       emit2 ("pop de");
3310       _G.calleeSaves.pushedDE = FALSE;
3311     }
3312
3313   if (_G.calleeSaves.pushedBC)
3314     {
3315       emit2 ("pop bc");
3316       _G.calleeSaves.pushedBC = FALSE;
3317     }
3318
3319   if (options.profile)
3320     {
3321       emit2 ("!profileexit");
3322     }
3323
3324   /* if this is an interrupt service routine
3325      then save all potentially used registers. */
3326   if (IFFUNC_ISISR (sym->type))
3327     {
3328       emit2 ("!popa");
3329
3330       /* If critical function then turn interrupts back on */
3331       /* except when no interrupt number is given then it implies the NMI handler */
3332       if (IFFUNC_ISCRITICAL (sym->type) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC))
3333         {
3334           emit2 ("!ei");
3335         }
3336     }
3337   else
3338     {
3339       /* This is a non-ISR function.
3340          If critical function then turn interrupts back on */
3341       if (IFFUNC_ISCRITICAL (sym->type))
3342         {
3343           if (IS_GB)
3344             {
3345               emit2 ("!ei");
3346             }
3347           else
3348             {
3349               symbol *tlbl = newiTempLabel (NULL);
3350               //restore P/O flag
3351               emit2 ("pop af");
3352               //parity odd <==> P/O=0 <==> interrupt enable flag IFF2 was 0 <==>
3353               //don't enable interrupts as they were off before
3354               emit2 ("jp PO,!tlabel", tlbl->key + 100);
3355               emit2 ("!ei");
3356               emit2 ("!tlabeldef", (tlbl->key + 100));
3357               _G.lines.current->isLabel = 1;
3358             }
3359         }
3360     }
3361
3362   if (options.debug && currFunc)
3363     {
3364       debugFile->writeEndFunction (currFunc, ic, 1);
3365     }
3366
3367   if (IFFUNC_ISISR (sym->type))
3368     {
3369       /* "critical interrupt" is used to imply NMI handler */
3370       if (IS_Z80 && IFFUNC_ISCRITICAL (sym->type) && FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3371         emit2 ("retn");
3372       else
3373         emit2 ("reti");
3374     }
3375   else
3376     {
3377       /* Both banked and non-banked just ret */
3378       emit2 ("ret");
3379     }
3380
3381   if (!IS_STATIC(sym->etype))
3382     {
3383       sprintf (buffer, "%s_end", sym->rname);
3384       emit2 ("!labeldef", buffer);
3385       _G.lines.current->isLabel = 1;
3386     }
3387
3388   _G.flushStatics = 1;
3389   _G.stack.pushed = 0;
3390   _G.stack.offset = 0;
3391 }
3392
3393 /*-----------------------------------------------------------------*/
3394 /* genRet - generate code for return statement                     */
3395 /*-----------------------------------------------------------------*/
3396 static void
3397 genRet (iCode * ic)
3398 {
3399     const char *l;
3400   /* Errk.  This is a hack until I can figure out how
3401      to cause dehl to spill on a call */
3402   int size, offset = 0;
3403
3404   /* if we have no return value then
3405      just generate the "ret" */
3406   if (!IC_LEFT (ic))
3407     goto jumpret;
3408
3409   /* we have something to return then
3410      move the return value into place */
3411   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3412   size = AOP_SIZE (IC_LEFT (ic));
3413
3414   aopDump("IC_LEFT", AOP(IC_LEFT(ic)));
3415
3416   #if 0
3417   if ((size == 2) && ((l = aopGetWord (AOP (IC_LEFT (ic)), 0))))
3418     {
3419       if (IS_GB)
3420         {
3421           emit2 ("ld de,%s", l);
3422         }
3423       else
3424         {
3425           emit2 ("ld hl,%s", l);
3426         }
3427     }
3428   #endif
3429   if (size==2)
3430     {
3431       fetchPair(IS_GB ? PAIR_DE : PAIR_HL, AOP (IC_LEFT (ic)));
3432     }
3433   else
3434     {
3435       if (IS_GB && size == 4 && requiresHL (AOP (IC_LEFT (ic))))
3436         {
3437           fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
3438           fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 2);
3439         }
3440       else
3441         {
3442           while (size--)
3443             {
3444               l = aopGet (AOP (IC_LEFT (ic)), offset,
3445                           FALSE);
3446               if (strcmp (_fReturn[offset], l))
3447                 emit2 ("ld %s,%s", _fReturn[offset], l);
3448               offset++;
3449             }
3450         }
3451     }
3452   freeAsmop (IC_LEFT (ic), NULL, ic);
3453
3454 jumpret:
3455   /* generate a jump to the return label
3456      if the next is not the return statement */
3457   if (!(ic->next && ic->next->op == LABEL &&
3458         IC_LABEL (ic->next) == returnLabel))
3459
3460     emit2 ("jp !tlabel", returnLabel->key + 100);
3461 }
3462
3463 /*-----------------------------------------------------------------*/
3464 /* genLabel - generates a label                                    */
3465 /*-----------------------------------------------------------------*/
3466 static void
3467 genLabel (iCode * ic)
3468 {
3469   /* special case never generate */
3470   if (IC_LABEL (ic) == entryLabel)
3471     return;
3472
3473   emitLabel (IC_LABEL (ic)->key + 100);
3474 }
3475
3476 /*-----------------------------------------------------------------*/
3477 /* genGoto - generates a ljmp                                      */
3478 /*-----------------------------------------------------------------*/
3479 static void
3480 genGoto (iCode * ic)
3481 {
3482   emit2 ("jp !tlabel", IC_LABEL (ic)->key + 100);
3483 }
3484
3485 /*-----------------------------------------------------------------*/
3486 /* genPlusIncr :- does addition with increment if possible         */
3487 /*-----------------------------------------------------------------*/
3488 static bool
3489 genPlusIncr (iCode * ic)
3490 {
3491   unsigned int icount;
3492   unsigned int size = getDataSize (IC_RESULT (ic));
3493   PAIR_ID resultId = getPairId (AOP (IC_RESULT (ic)));
3494
3495   /* will try to generate an increment */
3496   /* if the right side is not a literal
3497      we cannot */
3498   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3499     return FALSE;
3500
3501   emitDebug ("; genPlusIncr");
3502
3503   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3504
3505   /* If result is a pair */
3506   if (resultId != PAIR_INVALID)
3507     {
3508       if (isLitWord (AOP (IC_LEFT (ic))))
3509         {
3510           fetchLitPair (getPairId (AOP (IC_RESULT (ic))), AOP (IC_LEFT (ic)), icount);
3511           return TRUE;
3512         }
3513       if (isPair (AOP (IC_LEFT (ic))) && resultId == PAIR_HL && icount > 2)
3514         {
3515           if (getPairId (AOP (IC_LEFT (ic))) == PAIR_HL)
3516             {
3517               PAIR_ID freep = getFreePairId (ic);
3518               if (freep != PAIR_INVALID)
3519                 {
3520                   fetchPair (freep, AOP (IC_RIGHT (ic)));
3521                   emit2 ("add hl,%s", _pairs[freep].name);
3522                   return TRUE;
3523                 }
3524             }
3525           else
3526             {
3527               fetchPair (resultId, AOP (IC_RIGHT (ic)));
3528               emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
3529               return TRUE;
3530             }
3531         }
3532       if (icount > 5)
3533         return FALSE;
3534       /* Inc a pair */
3535       if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3536         {
3537           if (icount > 2)
3538             return FALSE;
3539           movLeft2ResultLong (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0, 2);
3540         }
3541       while (icount--)
3542         {
3543           emit2 ("inc %s", getPairName (AOP (IC_RESULT (ic))));
3544         }
3545       return TRUE;
3546     }
3547
3548   if (IS_Z80 && isLitWord (AOP (IC_LEFT (ic))) && size == 2)
3549     {
3550       fetchLitPair (PAIR_HL, AOP (IC_LEFT (ic)), icount);
3551       commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
3552       return TRUE;
3553     }
3554
3555   /* if the literal value of the right hand side
3556      is greater than 4 then it is not worth it */
3557   if (icount > 4)
3558     return FALSE;
3559
3560   /* if increment 16 bits in register */
3561   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3562       size > 1 &&
3563       icount == 1
3564     )
3565     {
3566       int offset = 0;
3567       symbol *tlbl = NULL;
3568       tlbl = newiTempLabel (NULL);
3569       while (size--)
3570         {
3571           emit2 ("inc %s", aopGet (AOP (IC_RESULT (ic)), offset++, FALSE));
3572           if (size)
3573             {
3574               emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
3575             }
3576         }
3577       emitLabel (tlbl->key + 100);
3578       return TRUE;
3579     }
3580
3581   /* if the sizes are greater than 1 then we cannot */
3582   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3583       AOP_SIZE (IC_LEFT (ic)) > 1)
3584     return FALSE;
3585
3586   /* If the result is in a register then we can load then increment.
3587    */
3588   if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG)
3589     {
3590       aopPut (AOP (IC_RESULT (ic)), aopGet (AOP (IC_LEFT (ic)), LSB, FALSE), LSB);
3591       while (icount--)
3592         {
3593           emit2 ("inc %s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE));
3594         }
3595       return TRUE;
3596     }
3597
3598   /* we can if the aops of the left & result match or
3599      if they are in registers and the registers are the
3600      same */
3601   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3602     {
3603       while (icount--)
3604         {
3605           emit2 ("inc %s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE));
3606         }
3607       return TRUE;
3608     }
3609
3610   return FALSE;
3611 }
3612
3613 /*-----------------------------------------------------------------*/
3614 /* outBitAcc - output a bit in acc                                 */
3615 /*-----------------------------------------------------------------*/
3616 void
3617 outBitAcc (operand * result)
3618 {
3619   symbol *tlbl = newiTempLabel (NULL);
3620   /* if the result is a bit */
3621   if (AOP_TYPE (result) == AOP_CRY)
3622     {
3623       wassertl (0, "Tried to write A into a bit");
3624     }
3625   else
3626     {
3627       emit2 ("!shortjp Z,!tlabel", tlbl->key + 100);
3628       emit2 ("ld a,!one");
3629       emitLabel (tlbl->key + 100);
3630       outAcc (result);
3631     }
3632 }
3633
3634 bool
3635 couldDestroyCarry (asmop *aop)
3636 {
3637   if (aop)
3638     {
3639       if (aop->type == AOP_EXSTK || aop->type == AOP_IY)
3640         {
3641           return TRUE;
3642         }
3643     }
3644   return FALSE;
3645 }
3646
3647 static void
3648 shiftIntoPair (int idx, asmop *aop)
3649 {
3650   PAIR_ID id = PAIR_INVALID;
3651
3652   wassertl (IS_Z80, "Only implemented for the Z80");
3653   //  wassertl (aop->type == AOP_EXSTK, "Only implemented for EXSTK");
3654
3655   emitDebug ("; Shift into pair idx %u", idx);
3656
3657   switch (idx)
3658     {
3659     case 0:
3660       id = PAIR_HL;
3661       setupPair (PAIR_HL, aop, 0);
3662       break;
3663     case 1:
3664       id = PAIR_DE;
3665       _push (PAIR_DE);
3666       setupPair (PAIR_IY, aop, 0);
3667       emit2 ("push iy");
3668       emit2 ("pop %s", _pairs[id].name);
3669       break;
3670     case 2:
3671       id = PAIR_IY;
3672       setupPair (PAIR_IY, aop, 0);
3673       break;
3674     default:
3675       wassertl (0, "Internal error - hit default case");
3676     }
3677
3678   aop->type = AOP_PAIRPTR;
3679   aop->aopu.aop_pairId = id;
3680   _G.pairs[id].offset = 0;
3681   _G.pairs[id].last_type = aop->type;
3682 }
3683
3684 static void
3685 setupToPreserveCarry (iCode * ic)
3686 {
3687   asmop *left   = AOP (IC_LEFT (ic));
3688   asmop *right  = AOP (IC_RIGHT (ic));
3689   asmop *result = AOP (IC_RESULT (ic));
3690
3691   wassert (left && right);
3692
3693   if (IS_Z80)
3694     {
3695       if (couldDestroyCarry (right) && couldDestroyCarry (result))
3696         {
3697           shiftIntoPair (0, right);
3698           /* check result again, in case right == result */
3699           if (couldDestroyCarry (result))
3700             {
3701               if (!isPairInUse (PAIR_DE, ic))
3702                 shiftIntoPair (1, result);
3703               else
3704                 shiftIntoPair (2, result);
3705             }
3706         }
3707       else if (couldDestroyCarry (right))
3708         {
3709           if (getPairId (result) == PAIR_HL)
3710             _G.preserveCarry = TRUE;
3711           else
3712             shiftIntoPair (0, right);
3713         }
3714       else if (couldDestroyCarry (result))
3715         {
3716           shiftIntoPair (0, result);
3717         }
3718       else
3719         {
3720           /* Fine */
3721         }
3722     }
3723 }
3724
3725 /*-----------------------------------------------------------------*/
3726 /* genPlus - generates code for addition                           */
3727 /*-----------------------------------------------------------------*/
3728 static void
3729 genPlus (iCode * ic)
3730 {
3731   int size, offset = 0;
3732
3733   /* special cases :- */
3734
3735   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3736   aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
3737   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3738
3739   /* Swap the left and right operands if:
3740
3741      if literal, literal on the right or
3742      if left requires ACC or right is already
3743      in ACC */
3744
3745   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3746       (AOP_NEEDSACC (IC_RIGHT (ic))) ||
3747       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3748     {
3749       operand *t = IC_RIGHT (ic);
3750       IC_RIGHT (ic) = IC_LEFT (ic);
3751       IC_LEFT (ic) = t;
3752     }
3753
3754   /* if both left & right are in bit
3755      space */
3756   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3757       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3758     {
3759       /* Cant happen */
3760       wassertl (0, "Tried to add two bits");
3761     }
3762
3763   /* if left in bit space & right literal */
3764   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3765       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3766     {
3767       /* Can happen I guess */
3768       wassertl (0, "Tried to add a bit to a literal");
3769     }
3770
3771   /* if I can do an increment instead
3772      of add then GOOD for ME */
3773   if (genPlusIncr (ic) == TRUE)
3774     goto release;
3775
3776   size = getDataSize (IC_RESULT (ic));
3777
3778   /* Special case when left and right are constant */
3779   if (isPair (AOP (IC_RESULT (ic))))
3780     {
3781       char *left, *right;
3782       left = aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE);
3783       right = aopGetLitWordLong (AOP (IC_RIGHT (ic)), 0, FALSE);
3784
3785       if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT && AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT &&
3786           left && right)
3787         {
3788           /* It's a pair */
3789           /* PENDING: fix */
3790           char buffer[100];
3791           sprintf (buffer, "#(%s + %s)", left, right);
3792           emit2 ("ld %s,%s", getPairName (AOP (IC_RESULT (ic))), buffer);
3793           goto release;
3794         }
3795     }
3796
3797   if ((isPair (AOP (IC_RIGHT (ic))) || isPair (AOP (IC_LEFT (ic)))) && getPairId (AOP (IC_RESULT (ic))) == PAIR_HL)
3798     {
3799       /* Fetch into HL then do the add */
3800       PAIR_ID left = getPairId (AOP (IC_LEFT (ic)));
3801       PAIR_ID right = getPairId (AOP (IC_RIGHT (ic)));
3802
3803       spillPair (PAIR_HL);
3804
3805       if (left == PAIR_HL && right != PAIR_INVALID)
3806         {
3807           emit2 ("add hl,%s", _pairs[right].name);
3808           goto release;
3809         }
3810       else if (right == PAIR_HL && left != PAIR_INVALID)
3811         {
3812           emit2 ("add hl,%s", _pairs[left].name);
3813           goto release;
3814         }
3815       else if (right != PAIR_INVALID && right != PAIR_HL)
3816         {
3817           fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
3818           emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
3819           goto release;
3820         }
3821       else if (left != PAIR_INVALID && left != PAIR_HL)
3822         {
3823           fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
3824           emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
3825           goto release;
3826         }
3827       else
3828         {
3829           /* Can't do it */
3830         }
3831     }
3832
3833   if (isPair (AOP (IC_RIGHT (ic))) && AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD && getPairId (AOP (IC_RIGHT (ic))) != PAIR_HL)
3834     {
3835       fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
3836       emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
3837       spillCached();
3838       commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
3839       goto release;
3840     }
3841
3842   /* Special case:
3843      ld hl,sp+n trashes C so we can't afford to do it during an
3844      add with stack based variables.  Worst case is:
3845      ld  hl,sp+left
3846      ld  a,(hl)
3847      ld  hl,sp+right
3848      add (hl)
3849      ld  hl,sp+result
3850      ld  (hl),a
3851      ld  hl,sp+left+1
3852      ld  a,(hl)
3853      ld  hl,sp+right+1
3854      adc (hl)
3855      ld  hl,sp+result+1
3856      ld  (hl),a
3857      So you can't afford to load up hl if either left, right, or result
3858      is on the stack (*sigh*)  The alt is:
3859      ld  hl,sp+left
3860      ld  de,(hl)
3861      ld  hl,sp+right
3862      ld  hl,(hl)
3863      add hl,de
3864      ld  hl,sp+result
3865      ld  (hl),hl
3866      Combinations in here are:
3867      * If left or right are in bc then the loss is small - trap later
3868      * If the result is in bc then the loss is also small
3869    */
3870   if (IS_GB)
3871     {
3872       if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
3873           AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
3874           AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
3875         {
3876           if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
3877                AOP_SIZE (IC_RIGHT (ic)) == 2) &&
3878               (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
3879                AOP_SIZE (IC_RIGHT (ic)) <= 2))
3880             {
3881               if (getPairId (AOP (IC_RIGHT (ic))) == PAIR_BC)
3882                 {
3883                   /* Swap left and right */
3884                   operand *t = IC_RIGHT (ic);
3885                   IC_RIGHT (ic) = IC_LEFT (ic);
3886                   IC_LEFT (ic) = t;
3887                 }
3888               if (getPairId (AOP (IC_LEFT (ic))) == PAIR_BC)
3889                 {
3890                   fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
3891                   emit2 ("add hl,bc");
3892                 }
3893               else
3894                 {
3895                   fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
3896                   fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
3897                   emit2 ("add hl,de");
3898                 }
3899               commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
3900               goto release;
3901             }
3902         }
3903       if (size == 4)
3904         {
3905           /* Be paranoid on the GB with 4 byte variables due to how C
3906              can be trashed by lda hl,n(sp).
3907           */
3908           _gbz80_emitAddSubLong (ic, TRUE);
3909           goto release;
3910         }
3911     }
3912
3913   setupToPreserveCarry (ic);
3914
3915   while (size--)
3916     {
3917       if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3918         {
3919           _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
3920           if (offset == 0)
3921             emit2 ("add a,%s",
3922                    aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3923           else
3924             emit2 ("adc a,%s",
3925                    aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3926         }
3927       else
3928         {
3929           _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
3930           if (offset == 0)
3931             emit2 ("add a,%s",
3932                    aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3933           else
3934             emit2 ("adc a,%s",
3935                    aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3936         }
3937       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3938     }
3939
3940 release:
3941   _G.preserveCarry = FALSE;
3942   freeAsmop (IC_LEFT (ic), NULL, ic);
3943   freeAsmop (IC_RIGHT (ic), NULL, ic);
3944   freeAsmop (IC_RESULT (ic), NULL, ic);
3945 }
3946
3947 /*-----------------------------------------------------------------*/
3948 /* genMinusDec :- does subtraction with deccrement if possible     */
3949 /*-----------------------------------------------------------------*/
3950 static bool
3951 genMinusDec (iCode * ic)
3952 {
3953   unsigned int icount;
3954   unsigned int size = getDataSize (IC_RESULT (ic));
3955
3956   /* will try to generate an increment */
3957   /* if the right side is not a literal we cannot */
3958   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3959     return FALSE;
3960
3961   /* if the literal value of the right hand side
3962      is greater than 4 then it is not worth it */
3963   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 2)
3964     return FALSE;
3965
3966   size = getDataSize (IC_RESULT (ic));
3967
3968   /* if decrement 16 bits in register */
3969   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3970       (size > 1) && isPair (AOP (IC_RESULT (ic))))
3971     {
3972       while (icount--)
3973         emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
3974       return TRUE;
3975     }
3976
3977   /* If result is a pair */
3978   if (isPair (AOP (IC_RESULT (ic))))
3979     {
3980       movLeft2ResultLong (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0, 2);
3981       while (icount--)
3982         emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
3983       return TRUE;
3984     }
3985
3986   /* if increment 16 bits in register */
3987   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3988       (size == 2)
3989       )
3990     {
3991       fetchPair (_getTempPairId(), AOP (IC_RESULT (ic)));
3992
3993       while (icount--) {
3994         emit2 ("dec %s", _getTempPairName());
3995       }
3996
3997       commitPair (AOP (IC_RESULT (ic)), _getTempPairId());
3998
3999       return TRUE;
4000     }
4001
4002
4003   /* if the sizes are greater than 1 then we cannot */
4004   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4005       AOP_SIZE (IC_LEFT (ic)) > 1)
4006     return FALSE;
4007
4008   /* we can if the aops of the left & result match or if they are in
4009      registers and the registers are the same */
4010   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4011     {
4012       while (icount--)
4013         emit2 ("dec %s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE));
4014       return TRUE;
4015     }
4016
4017   return FALSE;
4018 }
4019
4020 /*-----------------------------------------------------------------*/
4021 /* genMinus - generates code for subtraction                       */
4022 /*-----------------------------------------------------------------*/
4023 static void
4024 genMinus (iCode * ic)
4025 {
4026   int size, offset = 0;
4027   unsigned long lit = 0L;
4028
4029   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
4030   aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
4031   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4032
4033   /* special cases :- */
4034   /* if both left & right are in bit space */
4035   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4036       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4037     {
4038       wassertl (0, "Tried to subtract two bits");
4039       goto release;
4040     }
4041
4042   /* if I can do an decrement instead of subtract then GOOD for ME */
4043   if (genMinusDec (ic) == TRUE)
4044     goto release;
4045
4046   size = getDataSize (IC_RESULT (ic));
4047
4048   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4049     {
4050     }
4051   else
4052     {
4053       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4054       lit = -(long) lit;
4055     }
4056
4057   /* Same logic as genPlus */
4058   if (IS_GB)
4059     {
4060       if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
4061           AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
4062           AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
4063         {
4064           if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
4065                AOP_SIZE (IC_RIGHT (ic)) == 2) &&
4066               (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
4067                AOP_SIZE (IC_RIGHT (ic)) <= 2))
4068             {
4069               PAIR_ID left = getPairId (AOP (IC_LEFT (ic)));
4070               PAIR_ID right = getPairId (AOP (IC_RIGHT (ic)));
4071
4072               if (left == PAIR_INVALID && right == PAIR_INVALID)
4073                 {
4074                   left = PAIR_DE;
4075                   right = PAIR_HL;
4076                 }
4077               else if (right == PAIR_INVALID)
4078                 right = PAIR_DE;
4079               else if (left == PAIR_INVALID)
4080                 left = PAIR_DE;
4081
4082               fetchPair (left, AOP (IC_LEFT (ic)));
4083               /* Order is important.  Right may be HL */
4084               fetchPair (right, AOP (IC_RIGHT (ic)));
4085
4086               emit2 ("ld a,%s", _pairs[left].l);
4087               emit2 ("sub a,%s", _pairs[right].l);
4088               emit2 ("ld e,a");
4089               emit2 ("ld a,%s", _pairs[left].h);
4090               emit2 ("sbc a,%s", _pairs[right].h);
4091
4092               if ( AOP_SIZE (IC_RESULT (ic)) > 1)
4093                 {
4094                   aopPut (AOP (IC_RESULT (ic)), "a", 1);
4095                 }
4096               aopPut (AOP (IC_RESULT (ic)), "e", 0);
4097               goto release;
4098             }
4099         }
4100       if (size == 4)
4101         {
4102           /* Be paranoid on the GB with 4 byte variables due to how C
4103              can be trashed by lda hl,n(sp).
4104           */
4105           _gbz80_emitAddSubLong (ic, FALSE);
4106           goto release;
4107         }
4108     }
4109
4110   setupToPreserveCarry (ic);
4111
4112   /* if literal, add a,#-lit, else normal subb */
4113   while (size--)
4114     {
4115       _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
4116       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4117         {
4118           if (!offset)
4119             emit2 ("sub a,%s",
4120                       aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
4121           else
4122             emit2 ("sbc a,%s",
4123                       aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
4124         }
4125       else
4126         {
4127           /* first add without previous c */
4128           if (!offset)
4129             emit2 ("add a,!immedbyte", (unsigned int) (lit & 0x0FFL));
4130           else
4131             emit2 ("adc a,!immedbyte", (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4132         }
4133       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4134     }
4135
4136   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4137       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4138       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4139     {
4140       wassertl (0, "Tried to subtract on a long pointer");
4141     }
4142
4143 release:
4144   _G.preserveCarry = FALSE;
4145   freeAsmop (IC_LEFT (ic), NULL, ic);
4146   freeAsmop (IC_RIGHT (ic), NULL, ic);
4147   freeAsmop (IC_RESULT (ic), NULL, ic);
4148 }
4149
4150 /*-----------------------------------------------------------------*/
4151 /* genMult - generates code for multiplication                     */
4152 /*-----------------------------------------------------------------*/
4153 static void
4154 genMult (iCode * ic)
4155 {
4156   int val;
4157   int count, i;
4158   /* If true then the final operation should be a subtract */
4159   bool active = FALSE;
4160   bool byteResult;
4161
4162   /* Shouldn't occur - all done through function calls */
4163   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
4164   aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
4165   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4166
4167   byteResult =  (AOP_SIZE (IC_RESULT (ic)) == 1);
4168
4169   if (AOP_SIZE (IC_LEFT (ic)) > 2 ||
4170       AOP_SIZE (IC_RIGHT (ic)) > 2 ||
4171       AOP_SIZE (IC_RESULT (ic)) > 2)
4172     {
4173       wassertl (0, "Multiplication is handled through support function calls");
4174     }
4175
4176   /* Swap left and right such that right is a literal */
4177   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT))
4178     {
4179       operand *t = IC_RIGHT (ic);
4180       IC_RIGHT (ic) = IC_LEFT (ic);
4181       IC_LEFT (ic) = t;
4182     }
4183
4184   wassertl (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT, "Right must be a literal");
4185
4186   val = (int)floatFromVal ( AOP (IC_RIGHT (ic))->aopu.aop_lit);
4187   //  wassertl (val > 0, "Multiply must be positive");
4188   wassertl (val != 1, "Can't multiply by 1");
4189
4190   if (IS_Z80 && isPairInUseNotInRet (PAIR_DE, ic)) {
4191     _push (PAIR_DE);
4192     _G.stack.pushedDE = TRUE;
4193   }
4194
4195   if ( AOP_SIZE (IC_LEFT (ic)) == 1 && !SPEC_USIGN (getSpec (operandType ( IC_LEFT (ic)))))
4196     {
4197       emit2 ("ld e,%s", aopGet (AOP (IC_LEFT (ic)), LSB, FALSE));
4198       if (!byteResult)
4199         {
4200           emit2 ("ld a,e");
4201           emit2 ("rlc a");
4202           emit2 ("sbc a,a");
4203           emit2 ("ld d,a");
4204         }
4205     }
4206   else
4207     {
4208       fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
4209     }
4210
4211   i = val;
4212
4213   /* Fully unroled version of mul.s.  Not the most efficient.
4214    */
4215   for (count = 0; count < 16; count++)
4216     {
4217       if (count != 0 && active)
4218         {
4219           emit2 ("add hl,hl");
4220         }
4221       if (i & 0x8000U)
4222         {
4223           if (active == FALSE)
4224             {
4225               emit2 ("ld l,e");
4226               if (!byteResult)
4227                 emit2 ("ld h,d");
4228             }
4229           else
4230             {
4231               emit2 ("add hl,de");
4232             }
4233           active = TRUE;
4234         }
4235       i <<= 1;
4236     }
4237
4238   spillCached();
4239
4240   if (IS_Z80 && _G.stack.pushedDE)
4241     {
4242       _pop (PAIR_DE);
4243       _G.stack.pushedDE = FALSE;
4244     }
4245
4246   if (byteResult)
4247     aopPut (AOP (IC_RESULT (ic)), _pairs[PAIR_HL].l, 0);
4248   else
4249     commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
4250
4251   freeAsmop (IC_LEFT (ic), NULL, ic);
4252   freeAsmop (IC_RIGHT (ic), NULL, ic);
4253   freeAsmop (IC_RESULT (ic), NULL, ic);
4254 }
4255
4256 /*-----------------------------------------------------------------*/
4257 /* genDiv - generates code for division                            */
4258 /*-----------------------------------------------------------------*/
4259 static void
4260 genDiv (iCode * ic)
4261 {
4262   /* Shouldn't occur - all done through function calls */
4263   wassertl (0, "Division is handled through support function calls");
4264 }
4265
4266 /*-----------------------------------------------------------------*/
4267 /* genMod - generates code for division                            */
4268 /*-----------------------------------------------------------------*/
4269 static void
4270 genMod (iCode * ic)
4271 {
4272   /* Shouldn't occur - all done through function calls */
4273   wassert (0);
4274 }
4275
4276 /*-----------------------------------------------------------------*/
4277 /* genIfxJump :- will create a jump depending on the ifx           */
4278 /*-----------------------------------------------------------------*/
4279 static void
4280 genIfxJump (iCode * ic, char *jval)
4281 {
4282   symbol *jlbl;
4283   const char *inst;
4284
4285   /* if true label then we jump if condition
4286      supplied is true */
4287   if (IC_TRUE (ic))
4288     {
4289       jlbl = IC_TRUE (ic);
4290       if (!strcmp (jval, "a"))
4291         {
4292           inst = "NZ";
4293         }
4294       else if (!strcmp (jval, "c"))
4295         {
4296           inst = "C";
4297         }
4298       else if (!strcmp (jval, "nc"))
4299         {
4300           inst = "NC";
4301         }
4302       else if (!strcmp (jval, "m"))
4303         {
4304           inst = "M";
4305         }
4306       else if (!strcmp (jval, "p"))
4307         {
4308           inst = "P";
4309         }
4310       else
4311         {
4312           /* The buffer contains the bit on A that we should test */
4313           inst = "NZ";
4314         }
4315     }
4316   else
4317     {
4318       /* false label is present */
4319       jlbl = IC_FALSE (ic);
4320       if (!strcmp (jval, "a"))
4321         {
4322           inst = "Z";
4323         }
4324       else if (!strcmp (jval, "c"))
4325         {
4326           inst = "NC";
4327         }
4328       else if (!strcmp (jval, "nc"))
4329         {
4330           inst = "C";
4331         }
4332       else if (!strcmp (jval, "m"))
4333         {
4334           inst = "P";
4335         }
4336       else if (!strcmp (jval, "p"))
4337         {
4338           inst = "M";
4339         }
4340       else
4341         {
4342           /* The buffer contains the bit on A that we should test */
4343           inst = "Z";
4344         }
4345     }
4346   /* Z80 can do a conditional long jump */
4347   if (!strcmp (jval, "a"))
4348     {
4349       emit2 ("or a,a");
4350     }
4351   else if (!strcmp (jval, "c"))
4352     {
4353     }
4354   else if (!strcmp (jval, "nc"))
4355     {
4356     }
4357   else if (!strcmp (jval, "m"))
4358     {
4359     }
4360   else if (!strcmp (jval, "p"))
4361     {
4362     }
4363   else
4364     {
4365       emit2 ("bit %s,a", jval);
4366     }
4367   emit2 ("jp %s,!tlabel", inst, jlbl->key + 100);
4368
4369   /* mark the icode as generated */
4370   ic->generated = 1;
4371 }
4372
4373 #if DISABLED
4374 static const char *
4375 _getPairIdName (PAIR_ID id)
4376 {
4377   return _pairs[id].name;
4378 }
4379 #endif
4380
4381 #if OLD
4382       /* if unsigned char cmp with lit, just compare */
4383       if ((size == 1) &&
4384           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4385         {
4386           emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
4387           if (sign)
4388             {
4389               emit2 ("xor a,!immedbyte", 0x80);
4390               emit2 ("cp %s^!constbyte", aopGet (AOP (right), offset, FALSE), 0x80);
4391             }
4392           else
4393             emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
4394         }
4395       else if (size == 4 && IS_GB && requiresHL(AOP(right)) && requiresHL(AOP(left)))
4396         {
4397           // On the Gameboy we can't afford to adjust HL as it may trash the carry.
4398           // Pull left into DE and right into HL
4399           aopGet (AOP(left), LSB, FALSE);
4400           emit2 ("ld d,h");
4401           emit2 ("ld e,l");
4402           aopGet (AOP(right), LSB, FALSE);
4403
4404           while (size--)
4405             {
4406               if (size == 0 && sign)
4407                 {
4408                   // Highest byte when signed needs the bits flipped
4409                   // Save the flags
4410                   emit2 ("push af");
4411                   emit2 ("ld a,(de)");
4412                   emit2 ("xor !immedbyte", 0x80);
4413                   emit2 ("ld e,a");
4414                   emit2 ("ld a,(hl)");
4415                   emit2 ("xor !immedbyte", 0x80);
4416                   emit2 ("ld d,a");
4417                   emit2 ("pop af");
4418                   emit2 ("ld a,e");
4419                   emit2 ("%s a,d", offset == 0 ? "sub" : "sbc");
4420                 }
4421               else
4422                 {
4423                   emit2 ("ld a,(de)");
4424                   emit2 ("%s a,(hl)", offset == 0 ? "sub" : "sbc");
4425                 }
4426
4427               if (size != 0)
4428                 {
4429                   emit2 ("inc hl");
4430                   emit2 ("inc de");
4431                 }
4432               offset++;
4433             }
4434           spillPair (PAIR_HL);
4435         }
4436       else if (size == 4 && IS_Z80 && couldDestroyCarry(AOP(right)) && couldDestroyCarry(AOP(left)))
4437         {
4438           setupPair (PAIR_HL, AOP (left), 0);
4439           aopGet (AOP(right), LSB, FALSE);
4440
4441           while (size--)
4442             {
4443               if (size == 0 && sign)
4444                 {
4445                   // Highest byte when signed needs the bits flipped
4446                   // Save the flags
4447                   emit2 ("push af");
4448                   emit2 ("ld a,(hl)");
4449                   emit2 ("xor !immedbyte", 0x80);
4450                   emit2 ("ld l,a");
4451                   emit2 ("ld a,%d(iy)", offset);
4452                   emit2 ("xor !immedbyte", 0x80);
4453                   emit2 ("ld h,a");
4454                   emit2 ("pop af");
4455                   emit2 ("ld a,l");
4456                   emit2 ("%s a,h", offset == 0 ? "sub" : "sbc");
4457                 }
4458               else
4459                 {
4460                   emit2 ("ld a,(hl)");
4461                   emit2 ("%s a,%d(iy)", offset == 0 ? "sub" : "sbc", offset);
4462                 }
4463
4464               if (size != 0)
4465                 {
4466                   emit2 ("inc hl");
4467                 }
4468               offset++;
4469             }
4470           spillPair (PAIR_HL);
4471           spillPair (PAIR_IY);
4472         }
4473       else
4474         {
4475           if (AOP_TYPE (right) == AOP_LIT)
4476             {
4477               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4478               /* optimize if(x < 0) or if(x >= 0) */
4479               if (lit == 0L)
4480                 {
4481                   if (!sign)
4482                     {
4483                       /* No sign so it's always false */
4484                       _clearCarry();
4485                     }
4486                   else
4487                     {
4488                       /* Just load in the top most bit */
4489                       _moveA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
4490                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4491                         {
4492                           genIfxJump (ifx, "7");
4493                           return;
4494                         }
4495                       else
4496                         emit2 ("rlc a");
4497                     }
4498                   goto release;
4499                 }
4500             }
4501
4502           if (sign)
4503             {
4504               /* First setup h and l contaning the top most bytes XORed */
4505               bool fDidXor = FALSE;
4506               if (AOP_TYPE (left) == AOP_LIT)
4507                 {
4508                   unsigned long lit = (unsigned long)
4509                   floatFromVal (AOP (left)->aopu.aop_lit);
4510                   emit2 ("ld %s,!immedbyte", _fTmp[0],
4511                          0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
4512                 }
4513               else
4514                 {
4515                   emit2 ("ld a,%s", aopGet (AOP (left), size - 1, FALSE));
4516                   emit2 ("xor a,!immedbyte", 0x80);
4517                   emit2 ("ld %s,a", _fTmp[0]);
4518                   fDidXor = TRUE;
4519                 }
4520               if (AOP_TYPE (right) == AOP_LIT)
4521                 {
4522                   unsigned long lit = (unsigned long)
4523                   floatFromVal (AOP (right)->aopu.aop_lit);
4524                   emit2 ("ld %s,!immedbyte", _fTmp[1],
4525                          0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
4526                 }
4527               else
4528                 {
4529                   emit2 ("ld a,%s", aopGet (AOP (right), size - 1, FALSE));
4530                   emit2 ("xor a,!immedbyte", 0x80);
4531                   emit2 ("ld %s,a", _fTmp[1]);
4532                   fDidXor = TRUE;
4533                 }
4534             }
4535           while (size--)
4536             {
4537               /* Do a long subtract */
4538               if (!sign || size)
4539                 {
4540                   _moveA (aopGet (AOP (left), offset, FALSE));
4541                 }
4542               if (sign && size == 0)
4543                 {
4544                   emit2 ("ld a,%s", _fTmp[0]);
4545                   emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", _fTmp[1]);
4546                 }
4547               else
4548                 {
4549                   /* Subtract through, propagating the carry */
4550                   emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", aopGet (AOP (right), offset, FALSE));
4551                   offset++;
4552                 }
4553             }
4554         }
4555     }
4556 #endif
4557
4558 /** Generic compare for > or <
4559  */
4560 static void
4561 genCmp (operand * left, operand * right,
4562         operand * result, iCode * ifx, int sign)
4563 {
4564   int size, offset = 0;
4565   unsigned long lit = 0L;
4566
4567   /* if left & right are bit variables */
4568   if (AOP_TYPE (left) == AOP_CRY &&
4569       AOP_TYPE (right) == AOP_CRY)
4570     {
4571       /* Cant happen on the Z80 */
4572       wassertl (0, "Tried to compare two bits");
4573     }
4574   else
4575     {
4576       /* Do a long subtract of right from left. */
4577       size = max (AOP_SIZE (left), AOP_SIZE (right));
4578
4579       if (size > 1 && IS_GB && requiresHL(AOP(right)) && requiresHL(AOP(left)))
4580         {
4581           // On the Gameboy we can't afford to adjust HL as it may trash the carry.
4582           // Pull left into DE and right into HL
4583           aopGet (AOP(left), LSB, FALSE);
4584           emit2 ("ld d,h");
4585           emit2 ("ld e,l");
4586           aopGet (AOP(right), LSB, FALSE);
4587
4588           while (size--)
4589             {
4590               emit2 ("ld a,(de)");
4591               emit2 ("%s a,(hl)", offset == 0 ? "sub" : "sbc");
4592
4593               if (size != 0)
4594                 {
4595                   emit2 ("inc hl");
4596                   emit2 ("inc de");
4597                 }
4598               offset++;
4599             }
4600           spillPair (PAIR_HL);
4601           goto release;
4602         }
4603
4604       if (AOP_TYPE (right) == AOP_LIT)
4605         {
4606           lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4607           /* optimize if(x < 0) or if(x >= 0) */
4608           if (lit == 0)
4609             {
4610               if (!sign)
4611                 {
4612                   /* No sign so it's always false */
4613                   _clearCarry();
4614                 }
4615               else
4616                 {
4617                   /* Just load in the top most bit */
4618                   _moveA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
4619                   if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4620                     {
4621                       genIfxJump (ifx, "7");
4622                       return;
4623                     }
4624                   else
4625                     {
4626                       if (!sign)
4627                         {
4628                           emit2 ("rlc a");
4629                         }
4630                       if (ifx)
4631                         {
4632                           genIfxJump (ifx, "nc");
4633                           return;
4634                         }
4635                     }
4636                 }
4637               goto release;
4638             }
4639         }
4640
4641       while (size--)
4642         {
4643           _moveA (aopGet (AOP (left), offset, FALSE));
4644           /* Subtract through, propagating the carry */
4645           emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", aopGet (AOP (right), offset, FALSE));
4646           offset++;
4647         }
4648     }
4649
4650 release:
4651   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4652     {
4653       if (sign)
4654         {
4655           /* Shift the sign bit up into carry */
4656           emit2 ("rlca");
4657         }
4658       outBitC (result);
4659     }
4660   else
4661     {
4662       /* if the result is used in the next
4663          ifx conditional branch then generate
4664          code a little differently */
4665       if (ifx)
4666         {
4667           if (sign)
4668             {
4669               if (IS_GB)
4670                 {
4671                   emit2 ("rlca");
4672                   genIfxJump (ifx, "c");
4673                 }
4674               else
4675                 {
4676                   genIfxJump (ifx, "m");
4677                 }
4678             }
4679           else
4680             {
4681               genIfxJump (ifx, "c");
4682             }
4683         }
4684       else
4685         {
4686           if (sign)
4687             {
4688               /* Shift the sign bit up into carry */
4689               emit2 ("rlca");
4690             }
4691           outBitC (result);
4692         }
4693       /* leave the result in acc */
4694     }
4695 }
4696
4697 /*-----------------------------------------------------------------*/
4698 /* genCmpGt :- greater than comparison                             */
4699 /*-----------------------------------------------------------------*/
4700 static void
4701 genCmpGt (iCode * ic, iCode * ifx)
4702 {
4703   operand *left, *right, *result;
4704   sym_link *letype, *retype;
4705   int sign;
4706
4707   left = IC_LEFT (ic);
4708   right = IC_RIGHT (ic);
4709   result = IC_RESULT (ic);
4710
4711   letype = getSpec (operandType (left));
4712   retype = getSpec (operandType (right));
4713   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4714   /* assign the amsops */
4715   aopOp (left, ic, FALSE, FALSE);
4716   aopOp (right, ic, FALSE, FALSE);
4717   aopOp (result, ic, TRUE, FALSE);
4718
4719   genCmp (right, left, result, ifx, sign);
4720
4721   freeAsmop (left, NULL, ic);
4722   freeAsmop (right, NULL, ic);
4723   freeAsmop (result, NULL, ic);
4724 }
4725
4726 /*-----------------------------------------------------------------*/
4727 /* genCmpLt - less than comparisons                                */
4728 /*-----------------------------------------------------------------*/
4729 static void
4730 genCmpLt (iCode * ic, iCode * ifx)
4731 {
4732   operand *left, *right, *result;
4733   sym_link *letype, *retype;
4734   int sign;
4735
4736   left = IC_LEFT (ic);
4737   right = IC_RIGHT (ic);
4738   result = IC_RESULT (ic);
4739
4740   letype = getSpec (operandType (left));
4741   retype = getSpec (operandType (right));
4742   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4743
4744   /* assign the amsops */
4745   aopOp (left, ic, FALSE, FALSE);
4746   aopOp (right, ic, FALSE, FALSE);
4747   aopOp (result, ic, TRUE, FALSE);
4748
4749   genCmp (left, right, result, ifx, sign);
4750
4751   freeAsmop (left, NULL, ic);
4752   freeAsmop (right, NULL, ic);
4753   freeAsmop (result, NULL, ic);
4754 }
4755
4756 /*-----------------------------------------------------------------*/
4757 /* gencjneshort - compare and jump if not equal                    */
4758 /* returns pair that still needs to be popped                      */
4759 /*-----------------------------------------------------------------*/
4760 static PAIR_ID
4761 gencjneshort (operand * left, operand * right, symbol * lbl)
4762 {
4763   int size = max (AOP_SIZE (left), AOP_SIZE (right));
4764   int offset = 0;
4765   unsigned long lit = 0L;
4766
4767   /* Swap the left and right if it makes the computation easier */
4768   if (AOP_TYPE (left) == AOP_LIT)
4769     {
4770       operand *t = right;
4771       right = left;
4772       left = t;
4773     }
4774
4775   /* if the right side is a literal then anything goes */
4776   if (AOP_TYPE (right) == AOP_LIT)
4777     {
4778       lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4779       if (lit == 0)
4780         {
4781           _moveA (aopGet (AOP (left), offset, FALSE));
4782           if (size > 1)
4783             {
4784               while (--size)
4785                 {
4786                   emit2 ("or a,%s", aopGet (AOP (left), ++offset, FALSE));
4787                 }
4788             }
4789           else
4790             {
4791               emit2 ("or a,a");
4792             }
4793           emit2 ("jp NZ,!tlabel", lbl->key + 100);
4794         }
4795       else
4796         {
4797           while (size--)
4798             {
4799               _moveA (aopGet (AOP (left), offset, FALSE));
4800               if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)
4801                 emit2 ("or a,a");
4802               else
4803                 emit2 ("sub a,%s", aopGet (AOP (right), offset, FALSE));
4804               emit2 ("jp NZ,!tlabel", lbl->key + 100);
4805               offset++;
4806             }
4807         }
4808     }
4809   /* if the right side is in a register or
4810      pointed to by HL, IX or IY */
4811   else if (AOP_TYPE (right) == AOP_REG ||
4812            AOP_TYPE (right) == AOP_HL  ||
4813            AOP_TYPE (right) == AOP_IY  ||
4814            AOP_TYPE (right) == AOP_STK ||
4815            AOP_IS_PAIRPTR (right, PAIR_HL) ||
4816            AOP_IS_PAIRPTR (right, PAIR_IX) ||
4817            AOP_IS_PAIRPTR (right, PAIR_IY))
4818     {
4819       while (size--)
4820         {
4821           _moveA (aopGet (AOP (left), offset, FALSE));
4822           if (AOP_TYPE (right) == AOP_LIT &&
4823               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4824             {
4825               emit2 ("or a,a");
4826               emit2 ("jp NZ,!tlabel", lbl->key + 100);
4827             }
4828           else
4829             {
4830               emit2 ("sub %s", aopGet (AOP (right), offset, FALSE));
4831               emit2 ("jp NZ,!tlabel", lbl->key + 100);
4832             }
4833           offset++;
4834         }
4835     }
4836   /* right is in direct space or a pointer reg, need both a & b */
4837   else
4838     {
4839       PAIR_ID pair;
4840       for (pair = PAIR_BC; pair <= PAIR_HL; pair++)
4841         {
4842           if (((AOP_TYPE (left)  != AOP_PAIRPTR) || (AOP (left)->aopu.aop_pairId  != pair)) &&
4843               ((AOP_TYPE (right) != AOP_PAIRPTR) || (AOP (right)->aopu.aop_pairId != pair)))
4844             {
4845               break;
4846             }
4847         }
4848       _push (pair);
4849       while (size--)
4850         {
4851           emit2 ("; direct compare");
4852           _emitMove (_pairs[pair].l, aopGet (AOP (left), offset, FALSE));
4853           _moveA (aopGet (AOP (right), offset, FALSE));
4854           emit2 ("sub %s", _pairs[pair].l);
4855           emit2 ("!shortjp NZ,!tlabel", lbl->key + 100);
4856           offset++;
4857         }
4858       return pair;
4859     }
4860   return PAIR_INVALID;
4861 }
4862
4863 /*-----------------------------------------------------------------*/
4864 /* gencjne - compare and jump if not equal                         */
4865 /*-----------------------------------------------------------------*/
4866 static void
4867 gencjne (operand * left, operand * right, symbol * lbl)
4868 {
4869   symbol *tlbl = newiTempLabel (NULL);
4870
4871   PAIR_ID pop = gencjneshort (left, right, lbl);
4872
4873   /* PENDING: ?? */
4874   emit2 ("ld a,!one");
4875   emit2 ("!shortjp !tlabel", tlbl->key + 100);
4876   emitLabel (lbl->key + 100);
4877   emit2 ("xor a,a");
4878   emitLabel (tlbl->key + 100);
4879   _pop (pop);
4880 }
4881
4882 /*-----------------------------------------------------------------*/
4883 /* genCmpEq - generates code for equal to                          */
4884 /*-----------------------------------------------------------------*/
4885 static void
4886 genCmpEq (iCode * ic, iCode * ifx)
4887 {
4888   operand *left, *right, *result;
4889
4890   aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
4891   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
4892   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
4893
4894   emitDebug ("; genCmpEq: left %u, right %u, result %u", AOP_SIZE(IC_LEFT(ic)), AOP_SIZE(IC_RIGHT(ic)), AOP_SIZE(IC_RESULT(ic)));
4895
4896   /* Swap operands if it makes the operation easier. ie if:
4897      1.  Left is a literal.
4898    */
4899   if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4900     {
4901       operand *t = IC_RIGHT (ic);
4902       IC_RIGHT (ic) = IC_LEFT (ic);
4903       IC_LEFT (ic) = t;
4904     }
4905
4906   if (ifx && !AOP_SIZE (result))
4907     {
4908       symbol *tlbl;
4909       /* if they are both bit variables */
4910       if (AOP_TYPE (left) == AOP_CRY &&
4911           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4912         {
4913           wassertl (0, "Tried to compare two bits");
4914         }
4915       else
4916         {
4917           PAIR_ID pop;
4918           tlbl = newiTempLabel (NULL);
4919           pop = gencjneshort (left, right, tlbl);
4920           if (IC_TRUE (ifx))
4921             {
4922               _pop (pop);
4923               emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
4924               emitLabel (tlbl->key + 100);
4925               _pop (pop);
4926             }
4927           else
4928             {
4929               /* PENDING: do this better */
4930               symbol *lbl = newiTempLabel (NULL);
4931               _pop (pop);
4932               emit2 ("!shortjp !tlabel", lbl->key + 100);
4933               emitLabel (tlbl->key + 100);
4934               _pop (pop);
4935               emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
4936               emitLabel (lbl->key + 100);
4937             }
4938         }
4939       /* mark the icode as generated */
4940       ifx->generated = 1;
4941       goto release;
4942     }
4943
4944   /* if they are both bit variables */
4945   if (AOP_TYPE (left) == AOP_CRY &&
4946       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4947     {
4948       wassertl (0, "Tried to compare a bit to either a literal or another bit");
4949     }
4950   else
4951     {
4952       emitDebug(";4");
4953
4954       gencjne (left, right, newiTempLabel (NULL));
4955       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4956         {
4957           wassert (0);
4958         }
4959       if (ifx)
4960         {
4961           emitDebug(";5");
4962           genIfxJump (ifx, "a");
4963           goto release;
4964         }
4965       /* if the result is used in an arithmetic operation
4966          then put the result in place */
4967       if (AOP_TYPE (result) != AOP_CRY)
4968         {
4969           emitDebug(";6");
4970           outAcc (result);
4971         }
4972       /* leave the result in acc */
4973     }
4974
4975 release:
4976   freeAsmop (left, NULL, ic);
4977   freeAsmop (right, NULL, ic);
4978   freeAsmop (result, NULL, ic);
4979 }
4980
4981 /*-----------------------------------------------------------------*/
4982 /* ifxForOp - returns the icode containing the ifx for operand     */
4983 /*-----------------------------------------------------------------*/
4984 static iCode *
4985 ifxForOp (operand * op, iCode * ic)
4986 {
4987   /* if true symbol then needs to be assigned */
4988   if (IS_TRUE_SYMOP (op))
4989     return NULL;
4990
4991   /* if this has register type condition and
4992      the next instruction is ifx with the same operand
4993      and live to of the operand is upto the ifx only then */
4994   if (ic->next &&
4995       ic->next->op == IFX &&
4996       IC_COND (ic->next)->key == op->key &&
4997       OP_SYMBOL (op)->liveTo <= ic->next->seq)
4998     return ic->next;
4999
5000   return NULL;
5001 }
5002
5003 /*-----------------------------------------------------------------*/
5004 /* genAndOp - for && operation                                     */
5005 /*-----------------------------------------------------------------*/
5006 static void
5007 genAndOp (iCode * ic)
5008 {
5009   operand *left, *right, *result;
5010   symbol *tlbl;
5011
5012   /* note here that && operations that are in an if statement are
5013      taken away by backPatchLabels only those used in arthmetic
5014      operations remain */
5015   aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
5016   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
5017   aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
5018
5019   /* if both are bit variables */
5020   if (AOP_TYPE (left) == AOP_CRY &&
5021       AOP_TYPE (right) == AOP_CRY)
5022     {
5023       wassertl (0, "Tried to and two bits");
5024     }
5025   else
5026     {
5027       tlbl = newiTempLabel (NULL);
5028       _toBoolean (left);
5029       emit2 ("!shortjp Z,!tlabel", tlbl->key + 100);
5030       _toBoolean (right);
5031       emitLabel (tlbl->key + 100);
5032       outBitAcc (result);
5033     }
5034
5035   freeAsmop (left, NULL, ic);
5036   freeAsmop (right, NULL, ic);
5037   freeAsmop (result, NULL, ic);
5038 }
5039
5040 /*-----------------------------------------------------------------*/
5041 /* genOrOp - for || operation                                      */
5042 /*-----------------------------------------------------------------*/
5043 static void
5044 genOrOp (iCode * ic)
5045 {
5046   operand *left, *right, *result;
5047   symbol *tlbl;
5048
5049   /* note here that || operations that are in an
5050      if statement are taken away by backPatchLabels
5051      only those used in arthmetic operations remain */
5052   aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
5053   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
5054   aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
5055
5056   /* if both are bit variables */
5057   if (AOP_TYPE (left) == AOP_CRY &&
5058       AOP_TYPE (right) == AOP_CRY)
5059     {
5060       wassertl (0, "Tried to OR two bits");
5061     }
5062   else
5063     {
5064       tlbl = newiTempLabel (NULL);
5065       _toBoolean (left);
5066       emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
5067       _toBoolean (right);
5068       emitLabel (tlbl->key + 100);
5069       outBitAcc (result);
5070     }
5071
5072   freeAsmop (left, NULL, ic);
5073   freeAsmop (right, NULL, ic);
5074   freeAsmop (result, NULL, ic);
5075 }
5076
5077 /*-----------------------------------------------------------------*/
5078 /* isLiteralBit - test if lit == 2^n                               */
5079 /*-----------------------------------------------------------------*/
5080 int
5081 isLiteralBit (unsigned long lit)
5082 {
5083   unsigned long pw[32] =
5084   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5085    0x100L, 0x200L, 0x400L, 0x800L,
5086    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5087    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5088    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5089    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5090    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5091   int idx;
5092
5093   for (idx = 0; idx < 32; idx++)
5094     if (lit == pw[idx])
5095       return idx + 1;
5096   return 0;
5097 }
5098
5099 /*-----------------------------------------------------------------*/
5100 /* jmpTrueOrFalse -                                                */
5101 /*-----------------------------------------------------------------*/
5102 static void
5103 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5104 {
5105   // ugly but optimized by peephole
5106   if (IC_TRUE (ic))
5107     {
5108       symbol *nlbl = newiTempLabel (NULL);
5109       emit2 ("jp !tlabel", nlbl->key + 100);
5110       emitLabel (tlbl->key + 100);
5111       emit2 ("jp !tlabel", IC_TRUE (ic)->key + 100);
5112       emitLabel (nlbl->key + 100);
5113     }
5114   else
5115     {
5116       emit2 ("jp !tlabel", IC_FALSE (ic)->key + 100);
5117       emitLabel (tlbl->key + 100);
5118     }
5119   ic->generated = 1;
5120 }
5121
5122 /*-----------------------------------------------------------------*/
5123 /* genAnd  - code for and                                          */
5124 /*-----------------------------------------------------------------*/
5125 static void
5126 genAnd (iCode * ic, iCode * ifx)
5127 {
5128   operand *left, *right, *result;
5129   int size, offset = 0;
5130   unsigned long lit = 0L;
5131   int bytelit = 0;
5132
5133   aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
5134   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
5135   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
5136
5137   /* if left is a literal & right is not then exchange them */
5138   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5139       (AOP_NEEDSACC (right) && !AOP_NEEDSACC (left)))
5140     {
5141       operand *tmp = right;
5142       right = left;
5143       left = tmp;
5144     }
5145
5146   /* if result = right then exchange them */
5147   if (sameRegs (AOP (result), AOP (right)))
5148     {
5149       operand *tmp = right;
5150       right = left;
5151       left = tmp;
5152     }
5153
5154   /* if right is bit then exchange them */
5155   if (AOP_TYPE (right) == AOP_CRY &&
5156       AOP_TYPE (left) != AOP_CRY)
5157     {
5158       operand *tmp = right;
5159       right = left;
5160       left = tmp;
5161     }
5162   if (AOP_TYPE (right) == AOP_LIT)
5163     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5164
5165   size = AOP_SIZE (result);
5166
5167   if (AOP_TYPE (left) == AOP_CRY)
5168     {
5169       wassertl (0, "Tried to perform an AND with a bit as an operand");
5170       goto release;
5171     }
5172
5173   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5174   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5175   if ((AOP_TYPE (right) == AOP_LIT) &&
5176       (AOP_TYPE (result) == AOP_CRY) &&
5177       (AOP_TYPE (left) != AOP_CRY))
5178     {
5179       symbol *tlbl = newiTempLabel (NULL);
5180       int sizel = AOP_SIZE (left);
5181       if (size)
5182         {
5183           /* PENDING: Test case for this. */
5184           emit2 ("scf");
5185         }
5186       while (sizel--)
5187         {
5188           if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5189             {
5190               _moveA (aopGet (AOP (left), offset, FALSE));
5191               if (bytelit != 0x0FFL)
5192                 {
5193                   emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE));
5194                 }
5195               else
5196                 {
5197                   /* For the flags */
5198                   emit2 ("or a,a");
5199                 }
5200               emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
5201             }
5202               offset++;
5203         }
5204       // bit = left & literal
5205       if (size)
5206         {
5207           emit2 ("clr c");
5208           emit2 ("!tlabeldef", tlbl->key + 100);
5209           _G.lines.current->isLabel = 1;
5210         }
5211       // if(left & literal)
5212       else
5213         {
5214           if (ifx)
5215             {
5216               jmpTrueOrFalse (ifx, tlbl);
5217             }
5218           goto release;
5219         }
5220       outBitC (result);
5221       goto release;
5222     }
5223
5224   /* if left is same as result */
5225   if (sameRegs (AOP (result), AOP (left)))
5226     {
5227       for (; size--; offset++)
5228         {
5229           if (AOP_TYPE (right) == AOP_LIT)
5230             {
5231               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5232                 continue;
5233               else
5234                 {
5235                   if (bytelit == 0)
5236                     aopPut (AOP (result), "!zero", offset);
5237                   else
5238                     {
5239                       _moveA (aopGet (AOP (left), offset, FALSE));
5240                       emit2 ("and a,%s",
5241                                 aopGet (AOP (right), offset, FALSE));
5242                       aopPut (AOP (left), "a", offset);
5243                     }
5244                 }
5245
5246             }
5247           else
5248             {
5249               if (AOP_TYPE (left) == AOP_ACC)
5250                 {
5251                   wassertl (0, "Tried to perform an AND where the left operand is allocated into A");
5252                 }
5253               else
5254                 {
5255                   _moveA (aopGet (AOP (left), offset, FALSE));
5256                   emit2 ("and a,%s",
5257                             aopGet (AOP (right), offset, FALSE));
5258                   aopPut (AOP (left), "a", offset);
5259                 }
5260             }
5261         }
5262     }
5263   else
5264     {
5265       // left & result in different registers
5266       if (AOP_TYPE (result) == AOP_CRY)
5267         {
5268           wassertl (0, "Tried to AND where the result is in carry");
5269         }
5270       else
5271         {
5272           for (; (size--); offset++)
5273             {
5274               // normal case
5275               // result = left & right
5276               if (AOP_TYPE (right) == AOP_LIT)
5277                 {
5278                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5279                     {
5280                       aopPut (AOP (result),
5281                               aopGet (AOP (left), offset, FALSE),
5282                               offset);
5283                       continue;
5284                     }
5285                   else if (bytelit == 0)
5286                     {
5287                       aopPut (AOP (result), "!zero", offset);
5288                       continue;
5289                     }
5290                 }
5291               // faster than result <- left, anl result,right
5292               // and better if result is SFR
5293               if (AOP_TYPE (left) == AOP_ACC)
5294                 emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE));
5295               else
5296                 {
5297                   _moveA (aopGet (AOP (left), offset, FALSE));
5298                   emit2 ("and a,%s",
5299                             aopGet (AOP (right), offset, FALSE));
5300                 }
5301               aopPut (AOP (result), "a", offset);
5302             }
5303         }
5304
5305     }
5306
5307 release:
5308   freeAsmop (left, NULL, ic);
5309   freeAsmop (right, NULL, ic);
5310   freeAsmop (result, NULL, ic);
5311 }
5312
5313 /*-----------------------------------------------------------------*/
5314 /* genOr  - code for or                                            */
5315 /*-----------------------------------------------------------------*/
5316 static void
5317 genOr (iCode * ic, iCode * ifx)
5318 {
5319   operand *left, *right, *result;
5320   int size, offset = 0;
5321   unsigned long lit = 0L;
5322   int bytelit = 0;
5323
5324   aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
5325   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
5326   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
5327
5328   /* if left is a literal & right is not then exchange them */
5329   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5330       (AOP_NEEDSACC (right) && !AOP_NEEDSACC (left)))
5331     {
5332       operand *tmp = right;
5333       right = left;
5334       left = tmp;
5335     }
5336
5337   /* if result = right then exchange them */
5338   if (sameRegs (AOP (result), AOP (right)))
5339     {
5340       operand *tmp = right;
5341       right = left;
5342       left = tmp;
5343     }
5344
5345   /* if right is bit then exchange them */
5346   if (AOP_TYPE (right) == AOP_CRY &&
5347       AOP_TYPE (left) != AOP_CRY)
5348     {
5349       operand *tmp = right;
5350       right = left;
5351       left = tmp;
5352     }
5353   if (AOP_TYPE (right) == AOP_LIT)
5354     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5355
5356   size = AOP_SIZE (result);
5357
5358   if (AOP_TYPE (left) == AOP_CRY)
5359     {
5360       wassertl (0, "Tried to OR where left is a bit");
5361       goto release;
5362     }
5363
5364   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5365   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5366   if ((AOP_TYPE (right) == AOP_LIT) &&
5367       (AOP_TYPE (result) == AOP_CRY) &&
5368       (AOP_TYPE (left) != AOP_CRY))
5369     {
5370       symbol *tlbl = newiTempLabel (NULL);
5371       int sizel = AOP_SIZE (left);
5372
5373       if (size)
5374         {
5375           wassertl (0, "Result is assigned to a bit");
5376         }
5377       /* PENDING: Modeled after the AND code which is inefficient. */
5378       while (sizel--)
5379         {
5380           bytelit = (lit >> (offset * 8)) & 0x0FFL;
5381
5382           _moveA (aopGet (AOP (left), offset, FALSE));
5383           /* OR with any literal is the same as OR with itself. */
5384           emit2 ("or a,a");
5385           emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
5386
5387           offset++;
5388         }
5389       if (ifx)
5390         {
5391           jmpTrueOrFalse (ifx, tlbl);
5392         }
5393       goto release;
5394     }
5395
5396   /* if left is same as result */
5397   if (sameRegs (AOP (result), AOP (left)))
5398     {
5399       for (; size--; offset++)
5400         {
5401           if (AOP_TYPE (right) == AOP_LIT)
5402             {
5403               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5404                 continue;
5405               else
5406                 {
5407                   _moveA (aopGet (AOP (left), offset, FALSE));
5408                   emit2 ("or a,%s",
5409                             aopGet (AOP (right), offset, FALSE));
5410                   aopPut (AOP (result), "a", offset);
5411                 }
5412             }
5413           else
5414             {
5415               if (AOP_TYPE (left) == AOP_ACC)
5416                 emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
5417               else
5418                 {
5419                   _moveA (aopGet (AOP (left), offset, FALSE));
5420                   emit2 ("or a,%s",
5421                             aopGet (AOP (right), offset, FALSE));
5422                   aopPut (AOP (result), "a", offset);
5423                 }
5424             }
5425         }
5426     }
5427   else
5428     {
5429       // left & result in different registers
5430       if (AOP_TYPE (result) == AOP_CRY)
5431         {
5432           wassertl (0, "Result of OR is in a bit");
5433         }
5434       else
5435         for (; (size--); offset++)
5436           {
5437             // normal case
5438             // result = left & right
5439             if (AOP_TYPE (right) == AOP_LIT)
5440               {
5441                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5442                   {
5443                     aopPut (AOP (result),
5444                             aopGet (AOP (left), offset, FALSE),
5445                             offset);
5446                     continue;
5447                   }
5448               }
5449             // faster than result <- left, anl result,right
5450             // and better if result is SFR
5451             if (AOP_TYPE (left) == AOP_ACC)
5452               emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
5453             else
5454               {
5455                 _moveA (aopGet (AOP (left), offset, FALSE));
5456                 emit2 ("or a,%s",
5457                           aopGet (AOP (right), offset, FALSE));
5458               }
5459             aopPut (AOP (result), "a", offset);
5460             /* PENDING: something weird is going on here.  Add exception. */
5461             if (AOP_TYPE (result) == AOP_ACC)
5462               break;
5463           }
5464     }
5465
5466 release:
5467   freeAsmop (left, NULL, ic);
5468   freeAsmop (right, NULL, ic);
5469   freeAsmop (result, NULL, ic);
5470 }
5471
5472 /*-----------------------------------------------------------------*/
5473 /* genXor - code for xclusive or                                   */
5474 /*-----------------------------------------------------------------*/
5475 static void
5476 genXor (iCode * ic, iCode * ifx)
5477 {
5478   operand *left, *right, *result;
5479   int size, offset = 0;
5480   unsigned long lit = 0L;
5481
5482   aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
5483   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
5484   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
5485
5486   /* if left is a literal & right is not then exchange them */
5487   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5488       (AOP_NEEDSACC (right) && !AOP_NEEDSACC (left)))
5489     {
5490       operand *tmp = right;
5491       right = left;
5492       left = tmp;
5493     }
5494
5495   /* if result = right then exchange them */
5496   if (sameRegs (AOP (result), AOP (right)))
5497     {
5498       operand *tmp = right;
5499       right = left;
5500       left = tmp;
5501     }
5502
5503   /* if right is bit then exchange them */
5504   if (AOP_TYPE (right) == AOP_CRY &&
5505       AOP_TYPE (left) != AOP_CRY)
5506     {
5507       operand *tmp = right;
5508       right = left;
5509       left = tmp;
5510     }
5511   if (AOP_TYPE (right) == AOP_LIT)
5512     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5513
5514   size = AOP_SIZE (result);
5515
5516   if (AOP_TYPE (left) == AOP_CRY)
5517     {
5518       wassertl (0, "Tried to XOR a bit");
5519       goto release;
5520     }
5521
5522   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5523   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5524   if ((AOP_TYPE (right) == AOP_LIT) &&
5525       (AOP_TYPE (result) == AOP_CRY) &&
5526       (AOP_TYPE (left) != AOP_CRY))
5527     {
5528       symbol *tlbl = newiTempLabel (NULL);
5529       int sizel = AOP_SIZE (left);
5530
5531       if (size)
5532         {
5533           /* PENDING: Test case for this. */
5534           wassertl (0, "Tried to XOR left against a literal with the result going into a bit");
5535         }
5536       while (sizel--)
5537         {
5538           _moveA (aopGet (AOP (left), offset, FALSE));
5539           emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
5540           emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
5541           offset++;
5542         }
5543       if (ifx)
5544         {
5545           jmpTrueOrFalse (ifx, tlbl);
5546         }
5547       else
5548         {
5549           wassertl (0, "Result of XOR was destined for a bit");
5550         }
5551       goto release;
5552     }
5553
5554   /* if left is same as result */
5555   if (sameRegs (AOP (result), AOP (left)))
5556     {
5557       for (; size--; offset++)
5558         {
5559           if (AOP_TYPE (right) == AOP_LIT)
5560             {
5561               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5562                 continue;
5563               else
5564                 {
5565                   _moveA (aopGet (AOP (left), offset, FALSE));
5566                   emit2 ("xor a,%s",
5567                             aopGet (AOP (right), offset, FALSE));
5568                   aopPut (AOP (result), "a", offset);
5569                 }
5570             }
5571           else
5572             {
5573               if (AOP_TYPE (left) == AOP_ACC)
5574                 {
5575                   emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
5576                 }
5577               else
5578                 {
5579                   _moveA (aopGet (AOP (left), offset, FALSE));
5580                   emit2 ("xor a,%s",
5581                             aopGet (AOP (right), offset, FALSE));
5582                   aopPut (AOP (result), "a", offset);
5583                 }
5584             }
5585         }
5586     }
5587   else
5588     {
5589       // left & result in different registers
5590       if (AOP_TYPE (result) == AOP_CRY)
5591         {
5592           wassertl (0, "Result of XOR is in a bit");
5593         }
5594       else
5595         for (; (size--); offset++)
5596           {
5597             // normal case
5598             // result = left & right
5599             if (AOP_TYPE (right) == AOP_LIT)
5600               {
5601                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5602                   {
5603                     aopPut (AOP (result),
5604                             aopGet (AOP (left), offset, FALSE),
5605                             offset);
5606                     continue;
5607                   }
5608               }
5609             // faster than result <- left, anl result,right
5610             // and better if result is SFR
5611             if (AOP_TYPE (left) == AOP_ACC)
5612               {
5613                 emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
5614               }
5615             else
5616               {
5617                 _moveA (aopGet (AOP (left), offset, FALSE));
5618                 emit2 ("xor a,%s",
5619                           aopGet (AOP (right), offset, FALSE));
5620               }
5621             aopPut (AOP (result), "a", offset);
5622           }
5623     }
5624
5625 release:
5626   freeAsmop (left, NULL, ic);
5627   freeAsmop (right, NULL, ic);
5628   freeAsmop (result, NULL, ic);
5629 }
5630
5631 /*-----------------------------------------------------------------*/
5632 /* genInline - write the inline code out                           */
5633 /*-----------------------------------------------------------------*/
5634 static void
5635 genInline (iCode * ic)
5636 {
5637   char *buffer, *bp, *bp1;
5638
5639   _G.lines.isInline += (!options.asmpeep);
5640
5641   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5642   strcpy (buffer, IC_INLINE (ic));
5643
5644   /* emit each line as a code */
5645   while (*bp)
5646     {
5647       if (*bp == '\n')
5648         {
5649           *bp++ = '\0';
5650           emit2 (bp1);
5651           bp1 = bp;
5652         }
5653       else
5654         {
5655           if (*bp == ':')
5656             {
5657               bp++;
5658               *bp = '\0';
5659               bp++;
5660               emit2 (bp1);
5661               bp1 = bp;
5662             }
5663           else
5664             bp++;
5665         }
5666     }
5667   if (bp1 != bp)
5668     emit2 (bp1);
5669   _G.lines.isInline -= (!options.asmpeep);
5670
5671 }
5672
5673 /*-----------------------------------------------------------------*/
5674 /* genRRC - rotate right with carry                                */
5675 /*-----------------------------------------------------------------*/
5676 static void
5677 genRRC (iCode * ic)
5678 {
5679   wassert (0);
5680 }
5681
5682 /*-----------------------------------------------------------------*/
5683 /* genRLC - generate code for rotate left with carry               */
5684 /*-----------------------------------------------------------------*/
5685 static void
5686 genRLC (iCode * ic)
5687 {
5688   wassert (0);
5689 }
5690
5691 /*-----------------------------------------------------------------*/
5692 /* genGetHbit - generates code get highest order bit               */
5693 /*-----------------------------------------------------------------*/
5694 static void
5695 genGetHbit (iCode * ic)
5696 {
5697   operand *left, *result;
5698   left = IC_LEFT (ic);
5699   result = IC_RESULT (ic);
5700
5701   aopOp (left, ic, FALSE, FALSE);
5702   aopOp (result, ic, FALSE, FALSE);
5703
5704   /* get the highest order byte into a */
5705   emit2("ld a,%s", aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
5706
5707   if (AOP_TYPE (result) == AOP_CRY)
5708     {
5709       emit2 ("rl a");
5710       outBitC (result);
5711     }
5712   else
5713     {
5714       emit2 ("rlc a");
5715       emit2 ("and a,!one");
5716       outAcc (result);
5717     }
5718
5719
5720   freeAsmop (left, NULL, ic);
5721   freeAsmop (result, NULL, ic);
5722 }
5723
5724 static void
5725 emitRsh2 (asmop *aop, int size, int is_signed)
5726 {
5727   int offset = 0;
5728
5729   while (size--)
5730     {
5731       const char *l = aopGet (aop, size, FALSE);
5732       if (offset == 0)
5733         {
5734           emit2 ("%s %s", is_signed ? "sra" : "srl", l);
5735         }
5736       else
5737         {
5738           emit2 ("rr %s", l);
5739         }
5740       offset++;
5741     }
5742 }
5743
5744 /*-----------------------------------------------------------------*/
5745 /* shiftR2Left2Result - shift right two bytes from left to result  */
5746 /*-----------------------------------------------------------------*/
5747 static void
5748 shiftR2Left2Result (operand * left, int offl,
5749                     operand * result, int offr,
5750                     int shCount, int is_signed)
5751 {
5752   int size = 2;
5753   symbol *tlbl;
5754
5755   movLeft2Result (left, offl, result, offr, 0);
5756   movLeft2Result (left, offl + 1, result, offr + 1, 0);
5757
5758   if (shCount == 0)
5759     return;
5760
5761   /*  if (AOP(result)->type == AOP_REG) { */
5762
5763   tlbl = newiTempLabel (NULL);
5764
5765   /* Left is already in result - so now do the shift */
5766   /* Optimizing for speed by default. */
5767   if (!optimize.codeSize || shCount <= 2)
5768     {
5769       while (shCount--)
5770         {
5771           emitRsh2 (AOP (result), size, is_signed);
5772         }
5773     }
5774   else
5775     {
5776       emit2 ("ld a,!immedbyte", shCount);
5777
5778       emitLabel (tlbl->key + 100);
5779
5780       emitRsh2 (AOP (result), size, is_signed);
5781
5782       emit2 ("dec a");
5783       emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
5784     }
5785 }
5786
5787 /*-----------------------------------------------------------------*/
5788 /* shiftL2Left2Result - shift left two bytes from left to result   */
5789 /*-----------------------------------------------------------------*/
5790 static void
5791 shiftL2Left2Result (operand * left, int offl,
5792                     operand * result, int offr, int shCount)
5793 {
5794   if (sameRegs (AOP (result), AOP (left)) &&
5795       ((offl + MSB16) == offr))
5796     {
5797       wassert (0);
5798     }
5799   else
5800     {
5801       /* Copy left into result */
5802       movLeft2Result (left, offl, result, offr, 0);
5803       movLeft2Result (left, offl + 1, result, offr + 1, 0);
5804     }
5805
5806   if (shCount == 0)
5807     return;
5808
5809   if (getPairId (AOP (result)) == PAIR_HL)
5810     {
5811       while (shCount--)
5812         {
5813           emit2 ("add hl,hl");
5814         }
5815     }
5816   else
5817     {
5818     int size = 2;
5819     int offset = 0;
5820     symbol *tlbl, *tlbl1;
5821     const char *l;
5822
5823     tlbl = newiTempLabel (NULL);
5824     tlbl1 = newiTempLabel (NULL);
5825
5826     if (AOP (result)->type == AOP_REG)
5827       {
5828         while (shCount--)
5829           {
5830             for (offset = 0; offset < size; offset++)
5831               {
5832                 l = aopGet (AOP (result), offset, FALSE);
5833
5834                 if (offset == 0)
5835                   {
5836                     emit2 ("sla %s", l);
5837                   }
5838                 else
5839                   {
5840                     emit2 ("rl %s", l);
5841                   }
5842               }
5843           }
5844       }
5845     else
5846       {
5847         /* Left is already in result - so now do the shift */
5848         if (shCount > 1)
5849           {
5850             emit2 ("ld a,!immedbyte+1", shCount);
5851             emit2 ("!shortjp !tlabel", tlbl1->key + 100);
5852             emitLabel (tlbl->key + 100);
5853           }
5854
5855         while (size--)
5856           {
5857             l = aopGet (AOP (result), offset, FALSE);
5858
5859             if (offset == 0)
5860               {
5861                 emit2 ("sla %s", l);
5862               }
5863             else
5864               {
5865                 emit2 ("rl %s", l);
5866               }
5867
5868             offset++;
5869           }
5870         if (shCount > 1)
5871           {
5872             emitLabel (tlbl1->key + 100);
5873             emit2 ("dec a");
5874             emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
5875           }
5876       }
5877   }
5878 }
5879
5880 /*-----------------------------------------------------------------*/
5881 /* AccRol - rotate left accumulator by known count                 */
5882 /*-----------------------------------------------------------------*/
5883 static void
5884 AccRol (int shCount)
5885 {
5886   shCount &= 0x0007;            // shCount : 0..7
5887
5888 #if 0
5889   switch (shCount)
5890     {
5891     case 0:
5892       break;
5893     case 1:
5894       emit2 ("sla a");
5895       break;
5896     case 2:
5897       emit2 ("sla a");
5898       emit2 ("rl a");
5899       break;
5900     case 3:
5901       emit2 ("sla a");
5902       emit2 ("rl a");
5903       emit2 ("rl a");
5904       break;
5905     case 4:
5906       emit2 ("sla a");
5907       emit2 ("rl a");
5908       emit2 ("rl a");
5909       emit2 ("rl a");
5910       break;
5911     case 5:
5912       emit2 ("srl a");
5913       emit2 ("rr a");
5914       emit2 ("rr a");
5915       break;
5916     case 6:
5917       emit2 ("srl a");
5918       emit2 ("rr a");
5919       break;
5920     case 7:
5921       emit2 ("srl a");
5922       break;
5923     }
5924 #else
5925   switch (shCount)
5926     {
5927     case 0:
5928       break;
5929     case 1:
5930       emit2 ("rlca");
5931       break;
5932     case 2:
5933       emit2 ("rlca");
5934       emit2 ("rlca");
5935       break;
5936     case 3:
5937       emit2 ("rlca");
5938       emit2 ("rlca");
5939       emit2 ("rlca");
5940       break;
5941     case 4:
5942       emit2 ("rlca");
5943       emit2 ("rlca");
5944       emit2 ("rlca");
5945       emit2 ("rlca");
5946       break;
5947     case 5:
5948       emit2 ("rrca");
5949       emit2 ("rrca");
5950       emit2 ("rrca");
5951       break;
5952     case 6:
5953       emit2 ("rrca");
5954       emit2 ("rrca");
5955       break;
5956     case 7:
5957       emit2 ("rrca");
5958       break;
5959     }
5960 #endif
5961 }
5962
5963 /*-----------------------------------------------------------------*/
5964 /* AccLsh - left shift accumulator by known count                  */
5965 /*-----------------------------------------------------------------*/
5966 static void
5967 AccLsh (int shCount)
5968 {
5969   static const unsigned char SLMask[] =
5970     {
5971       0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00
5972     };
5973
5974   if (shCount != 0)
5975     {
5976       if (shCount == 1)
5977         {
5978           emit2 ("add a,a");
5979         }
5980       else if (shCount == 2)
5981         {
5982           emit2 ("add a,a");
5983           emit2 ("add a,a");
5984         }
5985       else
5986         {
5987           /* rotate left accumulator */
5988           AccRol (shCount);
5989           /* and kill the lower order bits */
5990           emit2 ("and a,!immedbyte", SLMask[shCount]);
5991         }
5992     }
5993 }
5994
5995 /*-----------------------------------------------------------------*/
5996 /* shiftL1Left2Result - shift left one byte from left to result    */
5997 /*-----------------------------------------------------------------*/
5998 static void
5999 shiftL1Left2Result (operand * left, int offl,
6000                     operand * result, int offr, int shCount)
6001 {
6002   const char *l;
6003   l = aopGet (AOP (left), offl, FALSE);
6004   _moveA (l);
6005   /* shift left accumulator */
6006   AccLsh (shCount);
6007   aopPut (AOP (result), "a", offr);
6008 }
6009
6010
6011 /*-----------------------------------------------------------------*/
6012 /* genlshTwo - left shift two bytes by known amount                */
6013 /*-----------------------------------------------------------------*/
6014 static void
6015 genlshTwo (operand * result, operand * left, int shCount)
6016 {
6017   int size = AOP_SIZE (result);
6018
6019   wassert (size == 2);
6020
6021   /* if shCount >= 8 */
6022   if (shCount >= 8)
6023     {
6024       shCount -= 8;
6025       if (size > 1)
6026         {
6027           if (shCount)
6028             {
6029               movLeft2Result (left, LSB, result, MSB16, 0);
6030               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6031               aopPut (AOP (result), "!zero", LSB);
6032             }
6033           else
6034             {
6035               movLeft2Result (left, LSB, result, MSB16, 0);
6036               aopPut (AOP (result), "!zero", 0);
6037             }
6038         }
6039       else
6040         {
6041           aopPut (AOP (result), "!zero", LSB);
6042         }
6043     }
6044   /*  0 <= shCount <= 7 */
6045   else
6046     {
6047       if (size == 1)
6048         {
6049           wassert (0);
6050         }
6051       else
6052         {
6053           shiftL2Left2Result (left, LSB, result, LSB, shCount);
6054         }
6055     }
6056 }
6057
6058 /*-----------------------------------------------------------------*/
6059 /* genlshOne - left shift a one byte quantity by known count       */
6060 /*-----------------------------------------------------------------*/
6061 static void
6062 genlshOne (operand * result, operand * left, int shCount)
6063 {
6064   shiftL1Left2Result (left, LSB, result, LSB, shCount);
6065 }
6066
6067 /*-----------------------------------------------------------------*/
6068 /* genLeftShiftLiteral - left shifting by known count              */
6069 /*-----------------------------------------------------------------*/
6070 static void
6071 genLeftShiftLiteral (operand * left,
6072                      operand * right,
6073                      operand * result,
6074                      iCode * ic)
6075 {
6076   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6077   int size;
6078
6079   freeAsmop (right, NULL, ic);
6080
6081   aopOp (left, ic, FALSE, FALSE);
6082   aopOp (result, ic, FALSE, FALSE);
6083
6084   size = getSize (operandType (result));
6085
6086   /* I suppose that the left size >= result size */
6087
6088   if (shCount >= (size * 8))
6089     {
6090       while (size--)
6091         {
6092           aopPut (AOP (result), "!zero", size);
6093         }
6094     }
6095   else
6096     {
6097       switch (size)
6098         {
6099         case 1:
6100           genlshOne (result, left, shCount);
6101           break;
6102         case 2:
6103           genlshTwo (result, left, shCount);
6104           break;
6105         case 4:
6106           wassertl (0, "Shifting of longs is currently unsupported");
6107           break;
6108         default:
6109           wassert (0);
6110         }
6111     }
6112   freeAsmop (left, NULL, ic);
6113   freeAsmop (result, NULL, ic);
6114 }
6115
6116 /*-----------------------------------------------------------------*/
6117 /* genLeftShift - generates code for left shifting                 */
6118 /*-----------------------------------------------------------------*/
6119 static void
6120 genLeftShift (iCode * ic)
6121 {
6122   int size, offset;
6123   const char *l;
6124   symbol *tlbl, *tlbl1;
6125   operand *left, *right, *result;
6126
6127   right = IC_RIGHT (ic);
6128   left = IC_LEFT (ic);
6129   result = IC_RESULT (ic);
6130
6131   aopOp (right, ic, FALSE, FALSE);
6132
6133   /* if the shift count is known then do it
6134      as efficiently as possible */
6135   if (AOP_TYPE (right) == AOP_LIT)
6136     {
6137       genLeftShiftLiteral (left, right, result, ic);
6138       return;
6139     }
6140
6141   /* shift count is unknown then we have to form a loop get the loop
6142      count in B : Note: we take only the lower order byte since
6143      shifting more that 32 bits make no sense anyway, ( the largest
6144      size of an object can be only 32 bits ) */
6145   emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
6146   emit2 ("inc a");
6147   freeAsmop (right, NULL, ic);
6148   aopOp (left, ic, FALSE, FALSE);
6149   aopOp (result, ic, FALSE, FALSE);
6150
6151   if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG)
6152      _push (PAIR_AF);
6153
6154   /* now move the left to the result if they are not the
6155      same */
6156
6157   if (!sameRegs (AOP (left), AOP (result)))
6158     {
6159
6160       size = AOP_SIZE (result);
6161       offset = 0;
6162       while (size--)
6163         {
6164           l = aopGet (AOP (left), offset, FALSE);
6165           aopPut (AOP (result), l, offset);
6166           offset++;
6167         }
6168     }
6169
6170   tlbl = newiTempLabel (NULL);
6171   size = AOP_SIZE (result);
6172   offset = 0;
6173   tlbl1 = newiTempLabel (NULL);
6174
6175   if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG)
6176      _pop (PAIR_AF);
6177
6178   emit2 ("!shortjp !tlabel", tlbl1->key + 100);
6179   emitLabel (tlbl->key + 100);
6180   l = aopGet (AOP (result), offset, FALSE);
6181
6182   while (size--)
6183     {
6184       l = aopGet (AOP (result), offset, FALSE);
6185
6186       if (offset == 0)
6187         {
6188           emit2 ("sla %s", l);
6189         }
6190       else
6191         {
6192           emit2 ("rl %s", l);
6193         }
6194       offset++;
6195     }
6196   emitLabel (tlbl1->key + 100);
6197   emit2 ("dec a");
6198   emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
6199
6200   freeAsmop (left, NULL, ic);
6201   freeAsmop (result, NULL, ic);
6202 }
6203
6204 /*-----------------------------------------------------------------*/
6205 /* genrshOne - left shift two bytes by known amount != 0           */
6206 /*-----------------------------------------------------------------*/
6207 static void
6208 genrshOne (operand * result, operand * left, int shCount, int is_signed)
6209 {
6210   /* Errk */
6211   int size = AOP_SIZE (result);
6212   const char *l;
6213
6214   wassert (size == 1);
6215   wassert (shCount < 8);
6216
6217   l = aopGet (AOP (left), 0, FALSE);
6218
6219   if (AOP (result)->type == AOP_REG)
6220     {
6221       aopPut (AOP (result), l, 0);
6222       l = aopGet (AOP (result), 0, FALSE);
6223       while (shCount--)
6224         {
6225           emit2 ("%s %s", is_signed ? "sra" : "srl", l);
6226         }
6227     }
6228   else
6229     {
6230       _moveA (l);
6231       while (shCount--)
6232         {
6233           emit2 ("%s a", is_signed ? "sra" : "srl");
6234         }
6235       aopPut (AOP (result), "a", 0);
6236     }
6237 }
6238
6239 /*-----------------------------------------------------------------*/
6240 /* AccRsh - right shift accumulator by known count                 */
6241 /*-----------------------------------------------------------------*/
6242 static void
6243 AccRsh (int shCount)
6244 {
6245   static const unsigned char SRMask[] =
6246     {
6247       0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00
6248     };
6249
6250   if (shCount != 0)
6251     {
6252       /* rotate right accumulator */
6253       AccRol (8 - shCount);
6254       /* and kill the higher order bits */
6255       emit2 ("and a,!immedbyte", SRMask[shCount]);
6256     }
6257 }
6258
6259 /*-----------------------------------------------------------------*/
6260 /* shiftR1Left2Result - shift right one byte from left to result   */
6261 /*-----------------------------------------------------------------*/
6262 static void
6263 shiftR1Left2Result (operand * left, int offl,
6264                     operand * result, int offr,
6265                     int shCount, int sign)
6266 {
6267   _moveA (aopGet (AOP (left), offl, FALSE));
6268   if (sign)
6269     {
6270       while (shCount--)
6271         {
6272           emit2 ("%s a", sign ? "sra" : "srl");
6273         }
6274     }
6275   else
6276     {
6277       AccRsh (shCount);
6278     }
6279   aopPut (AOP (result), "a", offr);
6280 }
6281
6282 /*-----------------------------------------------------------------*/
6283 /* genrshTwo - right shift two bytes by known amount               */
6284 /*-----------------------------------------------------------------*/
6285 static void
6286 genrshTwo (operand * result, operand * left,
6287            int shCount, int sign)
6288 {
6289   /* if shCount >= 8 */
6290   if (shCount >= 8)
6291     {
6292       shCount -= 8;
6293       if (shCount)
6294         {
6295           shiftR1Left2Result (left, MSB16, result, LSB,
6296                               shCount, sign);
6297         }
6298       else
6299         {
6300           movLeft2Result (left, MSB16, result, LSB, sign);
6301         }
6302       if (sign)
6303         {
6304           /* Sign extend the result */
6305           _moveA(aopGet (AOP (result), 0, FALSE));
6306           emit2 ("rlc a");
6307           emit2 ("sbc a,a");
6308
6309           aopPut (AOP (result), ACC_NAME, MSB16);
6310         }
6311       else
6312         {
6313           aopPut (AOP (result), "!zero", 1);
6314         }
6315     }
6316   /*  0 <= shCount <= 7 */
6317   else
6318     {
6319       shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6320     }
6321 }
6322
6323 /*-----------------------------------------------------------------*/
6324 /* genRightShiftLiteral - left shifting by known count              */
6325 /*-----------------------------------------------------------------*/
6326 static void
6327 genRightShiftLiteral (operand * left,
6328                       operand * right,
6329                       operand * result,
6330                       iCode * ic,
6331                       int sign)
6332 {
6333   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6334   int size;
6335
6336   freeAsmop (right, NULL, ic);
6337
6338   aopOp (left, ic, FALSE, FALSE);
6339   aopOp (result, ic, FALSE, FALSE);
6340
6341   size = getSize (operandType (result));
6342
6343   /* I suppose that the left size >= result size */
6344
6345   if (shCount >= (size * 8)) {
6346     const char *s;
6347     if (!SPEC_USIGN(getSpec(operandType(left)))) {
6348       _moveA(aopGet (AOP (left), 0, FALSE));
6349       emit2 ("rlc a");
6350       emit2 ("sbc a,a");
6351       s=ACC_NAME;
6352     } else {
6353       s="!zero";
6354     }
6355     while (size--)
6356       aopPut (AOP (result), s, size);
6357   }
6358   else
6359     {
6360       switch (size)
6361         {
6362         case 1:
6363           genrshOne (result, left, shCount, sign);
6364           break;
6365         case 2:
6366           genrshTwo (result, left, shCount, sign);
6367           break;
6368         case 4:
6369           wassertl (0, "Asked to shift right a long which should be a function call");
6370           break;
6371         default:
6372           wassertl (0, "Entered default case in right shift delegate");
6373         }
6374     }
6375   freeAsmop (left, NULL, ic);
6376   freeAsmop (result, NULL, ic);
6377 }
6378
6379 /*-----------------------------------------------------------------*/
6380 /* genRightShift - generate code for right shifting                */
6381 /*-----------------------------------------------------------------*/
6382 static void
6383 genRightShift (iCode * ic)
6384 {
6385   operand *right, *left, *result;
6386   sym_link *retype;
6387   int size, offset, first = 1;
6388   const char *l;
6389   bool is_signed;
6390
6391   symbol *tlbl, *tlbl1;
6392
6393   /* if signed then we do it the hard way preserve the
6394      sign bit moving it inwards */
6395   retype = getSpec (operandType (IC_RESULT (ic)));
6396
6397   is_signed = !SPEC_USIGN (retype);
6398
6399   /* signed & unsigned types are treated the same : i.e. the
6400      signed is NOT propagated inwards : quoting from the
6401      ANSI - standard : "for E1 >> E2, is equivalent to division
6402      by 2**E2 if unsigned or if it has a non-negative value,
6403      otherwise the result is implementation defined ", MY definition
6404      is that the sign does not get propagated */
6405
6406   right = IC_RIGHT (ic);
6407   left = IC_LEFT (ic);
6408   result = IC_RESULT (ic);
6409
6410   aopOp (right, ic, FALSE, FALSE);
6411
6412   /* if the shift count is known then do it
6413      as efficiently as possible */
6414   if (AOP_TYPE (right) == AOP_LIT)
6415     {
6416       genRightShiftLiteral (left, right, result, ic, is_signed);
6417       return;
6418     }
6419
6420   emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
6421   emit2 ("inc a");
6422   freeAsmop (right, NULL, ic);
6423
6424   aopOp (left, ic, FALSE, FALSE);
6425   aopOp (result, ic, FALSE, FALSE);
6426
6427   if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG)
6428      _push (PAIR_AF);
6429
6430   /* now move the left to the result if they are not the
6431      same */
6432   if (!sameRegs (AOP (left), AOP (result)))
6433     {
6434
6435       size = AOP_SIZE (result);
6436       offset = 0;
6437       while (size--)
6438         {
6439           l = aopGet (AOP (left), offset, FALSE);
6440           aopPut (AOP (result), l, offset);
6441           offset++;
6442         }
6443     }
6444
6445   tlbl = newiTempLabel (NULL);
6446   tlbl1 = newiTempLabel (NULL);
6447   size = AOP_SIZE (result);
6448   offset = size - 1;
6449
6450   if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG)
6451      _pop (PAIR_AF);
6452
6453   emit2 ("!shortjp !tlabel", tlbl1->key + 100);
6454   emitLabel (tlbl->key + 100);
6455   while (size--)
6456     {
6457       l = aopGet (AOP (result), offset--, FALSE);
6458       if (first)
6459         {
6460           emit2 ("%s %s", is_signed ? "sra" : "srl", l);
6461           first = 0;
6462         }
6463       else
6464         {
6465           emit2 ("rr %s", l);
6466         }
6467     }
6468   emitLabel (tlbl1->key + 100);
6469   emit2 ("dec a");
6470   emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
6471
6472   freeAsmop (left, NULL, ic);
6473   freeAsmop (result, NULL, ic);
6474 }
6475
6476
6477 /*-----------------------------------------------------------------*/
6478 /* genUnpackBits - generates code for unpacking bits               */
6479 /*-----------------------------------------------------------------*/
6480 static void
6481 genUnpackBits (operand * result, int pair)
6482 {
6483   int offset = 0;       /* result byte offset */
6484   int rsize;            /* result size */
6485   int rlen = 0;         /* remaining bitfield length */
6486   sym_link *etype;      /* bitfield type information */
6487   int blen;             /* bitfield length */
6488   int bstr;             /* bitfield starting bit within byte */
6489
6490   emitDebug ("; genUnpackBits");
6491
6492   etype = getSpec (operandType (result));
6493   rsize = getSize (operandType (result));
6494   blen = SPEC_BLEN (etype);
6495   bstr = SPEC_BSTR (etype);
6496
6497   /* If the bitfield length is less than a byte */
6498   if (blen < 8)
6499     {
6500       emit2 ("ld a,!*pair", _pairs[pair].name);
6501       AccRol (8 - bstr);
6502       emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (8 - blen));
6503       if (!SPEC_USIGN (etype))
6504         {
6505           /* signed bitfield */
6506           symbol *tlbl = newiTempLabel (NULL);
6507
6508           emit2 ("bit %d,a", blen - 1);
6509           emit2 ("jp Z,!tlabel", tlbl->key + 100);
6510           emit2 ("or a,!immedbyte", (unsigned char) (0xff << blen));
6511           emitLabel (tlbl->key + 100);
6512         }
6513       aopPut (AOP (result), "a", offset++);
6514       goto finish;
6515     }
6516
6517   /* TODO: what if pair == PAIR_DE ? */
6518   if (getPairId (AOP (result)) == PAIR_HL)
6519     {
6520       wassertl (rsize == 2, "HL must be of size 2");
6521       emit2 ("ld a,!*hl");
6522       emit2 ("inc hl");
6523       emit2 ("ld h,!*hl");
6524       emit2 ("ld l,a");
6525       emit2 ("ld a,h");
6526       emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (16 - blen));
6527       if (!SPEC_USIGN (etype))
6528         {
6529           /* signed bitfield */
6530           symbol *tlbl = newiTempLabel (NULL);
6531
6532           emit2 ("bit %d,a", blen - 1);
6533           emit2 ("jp Z,!tlabel", tlbl->key + 100);
6534           emit2 ("or a,!immedbyte", (unsigned char) (0xff << blen));
6535           emitLabel (tlbl->key + 100);
6536         }
6537       emit2 ("ld h,a");
6538       spillPair (PAIR_HL);
6539       return;
6540     }
6541
6542   /* Bit field did not fit in a byte. Copy all
6543      but the partial byte at the end.  */
6544   for (rlen=blen;rlen>=8;rlen-=8)
6545     {
6546       emit2 ("ld a,!*pair", _pairs[pair].name);
6547       aopPut (AOP (result), "a", offset++);
6548       if (rlen>8)
6549         {
6550           emit2 ("inc %s", _pairs[pair].name);
6551           _G.pairs[pair].offset++;
6552         }
6553     }
6554
6555   /* Handle the partial byte at the end */
6556   if (rlen)
6557     {
6558       emit2 ("ld a,!*pair", _pairs[pair].name);
6559       emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (8 - rlen));
6560       if (!SPEC_USIGN (etype))
6561         {
6562           /* signed bitfield */
6563           symbol *tlbl = newiTempLabel (NULL);
6564
6565           emit2 ("bit %d,a", rlen - 1);
6566           emit2 ("jp Z,!tlabel", tlbl->key + 100);
6567           emit2 ("or a,!immedbyte", (unsigned char) (0xff << rlen));
6568           emitLabel (tlbl->key + 100);
6569         }
6570       aopPut (AOP (result), "a", offset++);
6571     }
6572
6573 finish:
6574   if (offset < rsize)
6575     {
6576       char *source;
6577
6578       if (SPEC_USIGN (etype))
6579         source = "!zero";
6580       else
6581         {
6582           /* signed bitfield: sign extension with 0x00 or 0xff */
6583           emit2 ("rla");
6584           emit2 ("sbc a,a");
6585
6586           source = "a";
6587         }
6588       rsize -= offset;
6589       while (rsize--)
6590         aopPut (AOP (result), source, offset++);
6591     }
6592 }
6593
6594 /*-----------------------------------------------------------------*/
6595 /* genGenPointerGet -  get value from generic pointer space        */
6596 /*-----------------------------------------------------------------*/
6597 static void
6598 genGenPointerGet (operand * left,
6599                   operand * result, iCode * ic)
6600 {
6601   int size, offset;
6602   sym_link *retype = getSpec (operandType (result));
6603   int pair = PAIR_HL;
6604
6605   if (IS_GB)
6606     pair = PAIR_DE;
6607
6608   aopOp (left, ic, FALSE, FALSE);
6609   aopOp (result, ic, FALSE, FALSE);
6610
6611   size = AOP_SIZE (result);
6612
6613   if (isPair (AOP (left)) && size == 1 && !IS_BITVAR (retype))
6614     {
6615       /* Just do it */
6616       if (isPtrPair (AOP (left)))
6617         {
6618           tsprintf (buffer, sizeof(buffer),
6619                     "!*pair", getPairName (AOP (left)));
6620           aopPut (AOP (result), buffer, 0);
6621         }
6622       else
6623         {
6624           emit2 ("ld a,!*pair", getPairName (AOP (left)));
6625           aopPut (AOP (result), "a", 0);
6626         }
6627       freeAsmop (left, NULL, ic);
6628       goto release;
6629     }
6630
6631   if (getPairId (AOP (left)) == PAIR_IY && !IS_BITVAR (retype))
6632     {
6633       /* Just do it */
6634       offset = 0;
6635       while (size--)
6636         {
6637           char at[20];
6638           tsprintf (at, sizeof(at), "!*iyx", offset);
6639           aopPut (AOP (result), at, offset);
6640           offset++;
6641         }
6642
6643       freeAsmop (left, NULL, ic);
6644       goto release;
6645     }
6646
6647   /* For now we always load into IY */
6648   /* if this is remateriazable */
6649   fetchPair (pair, AOP (left));
6650
6651   /* if bit then unpack */
6652   if (IS_BITVAR (retype))
6653     {
6654       genUnpackBits (result, pair);
6655       freeAsmop (left, NULL, ic);
6656       goto release;
6657       //wassert (0);
6658     }
6659   else if (getPairId (AOP (result)) == PAIR_HL)
6660     {
6661       wassertl (size == 2, "HL must be of size 2");
6662       emit2 ("ld a,!*hl");
6663       emit2 ("inc hl");
6664       emit2 ("ld h,!*hl");
6665       emit2 ("ld l,a");
6666       spillPair (PAIR_HL);
6667     }
6668   else if (getPairId (AOP (left)) == PAIR_HL && !isLastUse (ic, left))
6669     {
6670       size = AOP_SIZE (result);
6671       offset = 0;
6672
6673       while (size--)
6674         {
6675           /* PENDING: make this better */
6676           if (!IS_GB && AOP_TYPE (result) == AOP_REG)
6677             {
6678               aopPut (AOP (result), "!*hl", offset++);
6679             }
6680           else
6681             {
6682               emit2 ("ld a,!*pair", _pairs[pair].name);
6683               aopPut (AOP (result), "a", offset++);
6684             }
6685           if (size)
6686             {
6687               emit2 ("inc %s", _pairs[pair].name);
6688               _G.pairs[pair].offset++;
6689             }
6690         }
6691       /* Fixup HL back down */
6692       for (size = AOP_SIZE (result)-1; size; size--)
6693         {
6694           emit2 ("dec %s", _pairs[pair].name);
6695         }
6696     }
6697   else
6698     {
6699       size = AOP_SIZE (result);
6700       offset = 0;
6701
6702       while (size--)
6703         {
6704           /* PENDING: make this better */
6705           if (!IS_GB &&
6706               (AOP_TYPE (result) == AOP_REG || AOP_TYPE (result) == AOP_HLREG))
6707             {
6708               aopPut (AOP (result), "!*hl", offset++);
6709             }
6710           else
6711             {
6712               emit2 ("ld a,!*pair", _pairs[pair].name);
6713               aopPut (AOP (result), "a", offset++);
6714             }
6715           if (size)
6716             {
6717               emit2 ("inc %s", _pairs[pair].name);
6718               _G.pairs[pair].offset++;
6719             }
6720         }
6721     }
6722
6723   freeAsmop (left, NULL, ic);
6724
6725 release:
6726   freeAsmop (result, NULL, ic);
6727 }
6728
6729 /*-----------------------------------------------------------------*/
6730 /* genPointerGet - generate code for pointer get                   */
6731 /*-----------------------------------------------------------------*/
6732 static void
6733 genPointerGet (iCode * ic)
6734 {
6735   operand *left, *result;
6736   sym_link *type, *etype;
6737
6738   left = IC_LEFT (ic);
6739   result = IC_RESULT (ic);
6740
6741   /* depending on the type of pointer we need to
6742      move it to the correct pointer register */
6743   type = operandType (left);
6744   etype = getSpec (type);
6745
6746   genGenPointerGet (left, result, ic);
6747 }
6748
6749 bool
6750 isRegOrLit (asmop * aop)
6751 {
6752   if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD || aop->type == AOP_HLREG)
6753     return TRUE;
6754   return FALSE;
6755 }
6756
6757
6758 /*-----------------------------------------------------------------*/
6759 /* genPackBits - generates code for packed bit storage             */
6760 /*-----------------------------------------------------------------*/
6761 static void
6762 genPackBits (sym_link * etype,
6763              operand * right,
6764              int pair,
6765              iCode *ic)
6766 {
6767   int offset = 0;       /* source byte offset */
6768   int rlen = 0;         /* remaining bitfield length */
6769   int blen;             /* bitfield length */
6770   int bstr;             /* bitfield starting bit within byte */
6771   int litval;           /* source literal value (if AOP_LIT) */
6772   unsigned char mask;   /* bitmask within current byte */
6773   int extraPair;        /* a tempory register */
6774   bool needPopExtra=0;  /* need to restore original value of temp reg */
6775
6776   emitDebug (";     genPackBits","");
6777
6778   blen = SPEC_BLEN (etype);
6779   bstr = SPEC_BSTR (etype);
6780
6781   /* If the bitfield length is less than a byte */
6782   if (blen < 8)
6783     {
6784       mask = ((unsigned char) (0xFF << (blen + bstr)) |
6785               (unsigned char) (0xFF >> (8 - bstr)));
6786
6787       if (AOP_TYPE (right) == AOP_LIT)
6788         {
6789           /* Case with a bitfield length <8 and literal source
6790           */
6791           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6792           litval <<= bstr;
6793           litval &= (~mask) & 0xff;
6794           emit2 ("ld a,!*pair", _pairs[pair].name);
6795           if ((mask|litval)!=0xff)
6796             emit2 ("and a,!immedbyte", mask);
6797           if (litval)
6798             emit2 ("or a,!immedbyte", litval);
6799           emit2 ("ld !*pair,a", _pairs[pair].name);
6800           return;
6801         }
6802       else
6803         {
6804           /* Case with a bitfield length <8 and arbitrary source
6805           */
6806           _moveA (aopGet (AOP (right), 0, FALSE));
6807           /* shift and mask source value */
6808           AccLsh (bstr);
6809           emit2 ("and a,!immedbyte", (~mask) & 0xff);
6810
6811           extraPair = getFreePairId(ic);
6812           if (extraPair == PAIR_INVALID)
6813             {
6814               extraPair = PAIR_BC;
6815               if (getPairId (AOP (right)) != PAIR_BC
6816                   || !isLastUse (ic, right))
6817                 {
6818                   _push (extraPair);
6819                   needPopExtra = 1;
6820                 }
6821             }
6822           emit2 ("ld %s,a", _pairs[extraPair].l);
6823           emit2 ("ld a,!*pair", _pairs[pair].name);
6824
6825           emit2 ("and a,!immedbyte", mask);
6826           emit2 ("or a,%s", _pairs[extraPair].l);
6827           emit2 ("ld !*pair,a", _pairs[pair].name);
6828           if (needPopExtra)
6829             _pop (extraPair);
6830           return;
6831         }
6832     }
6833
6834   /* Bit length is greater than 7 bits. In this case, copy  */
6835   /* all except the partial byte at the end                 */
6836   for (rlen=blen;rlen>=8;rlen-=8)
6837     {
6838       emit2 ("ld a,%s", aopGet (AOP (right), offset++, FALSE) );
6839       emit2 ("ld !*pair,a", _pairs[pair].name);
6840       if (rlen>8)
6841         {
6842           emit2 ("inc %s", _pairs[pair].name);
6843           _G.pairs[pair].offset++;
6844         }
6845     }
6846
6847   /* If there was a partial byte at the end */
6848   if (rlen)
6849     {
6850       mask = (((unsigned char) -1 << rlen) & 0xff);
6851
6852       if (AOP_TYPE (right) == AOP_LIT)
6853         {
6854           /* Case with partial byte and literal source
6855           */
6856           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6857           litval >>= (blen-rlen);
6858           litval &= (~mask) & 0xff;
6859           emit2 ("ld a,!*pair", _pairs[pair].name);
6860           if ((mask|litval)!=0xff)
6861             emit2 ("and a,!immedbyte", mask);
6862           if (litval)
6863             emit2 ("or a,!immedbyte", litval);
6864         }
6865       else
6866         {
6867           /* Case with partial byte and arbitrary source
6868           */
6869           _moveA (aopGet (AOP (right), offset++, FALSE));
6870           emit2 ("and a,!immedbyte", (~mask) & 0xff);
6871
6872           extraPair = getFreePairId(ic);
6873           if (extraPair == PAIR_INVALID)
6874             {
6875               extraPair = getPairId (AOP (right));
6876               if (!isLastUse (ic, right) || (extraPair == PAIR_INVALID))
6877                 extraPair = PAIR_BC;
6878
6879               if (getPairId (AOP (right)) != PAIR_BC
6880                   || !isLastUse (ic, right))
6881                 {
6882                   _push (extraPair);
6883                   needPopExtra = 1;
6884                 }
6885             }
6886           emit2 ("ld %s,a", _pairs[extraPair].l);
6887           emit2 ("ld a,!*pair", _pairs[pair].name);
6888
6889           emit2 ("and a,!immedbyte", mask);
6890           emit2 ("or a,%s", _pairs[extraPair].l);
6891           if (needPopExtra)
6892             _pop (extraPair);
6893
6894         }
6895       emit2 ("ld !*pair,a", _pairs[pair].name);
6896     }
6897 }
6898
6899
6900 /*-----------------------------------------------------------------*/
6901 /* genGenPointerSet - stores the value into a pointer location        */
6902 /*-----------------------------------------------------------------*/
6903 static void
6904 genGenPointerSet (operand * right,
6905                   operand * result, iCode * ic)
6906 {
6907   int size, offset;
6908   sym_link *retype = getSpec (operandType (right));
6909   sym_link *letype = getSpec (operandType (result));
6910   PAIR_ID pairId = PAIR_HL;
6911   bool isBitvar;
6912
6913   aopOp (result, ic, FALSE, FALSE);
6914   aopOp (right, ic, FALSE, FALSE);
6915
6916   if (IS_GB)
6917     pairId = PAIR_DE;
6918
6919   size = AOP_SIZE (right);
6920
6921   isBitvar = IS_BITVAR(retype) || IS_BITVAR(letype);
6922   emitDebug("; isBitvar = %d", isBitvar);
6923
6924   /* Handle the exceptions first */
6925   if (isPair (AOP (result)) && size == 1 && !isBitvar)
6926     {
6927       /* Just do it */
6928       const char *l = aopGet (AOP (right), 0, FALSE);
6929       const char *pair = getPairName (AOP (result));
6930       if (canAssignToPtr (l) && isPtr (pair))
6931         {
6932           emit2 ("ld !*pair,%s", pair, l);
6933         }
6934       else
6935         {
6936           _moveA (l);
6937           emit2 ("ld !*pair,a", pair);
6938         }
6939       goto release;
6940     }
6941
6942   if ( getPairId( AOP (result)) == PAIR_IY && !isBitvar)
6943     {
6944       /* Just do it */
6945       const char *l = aopGet (AOP (right), 0, FALSE);
6946
6947       offset = 0;
6948       while (size--)
6949         {
6950           if (canAssignToPtr (l))
6951             {
6952               emit2 ("ld !*iyx,%s", offset, aopGet( AOP(right), offset, FALSE));
6953             }
6954           else
6955             {
6956               _moveA (aopGet (AOP (right), offset, FALSE));
6957               emit2 ("ld !*iyx,a", offset);
6958             }
6959           offset++;
6960         }
6961       goto release;
6962     }
6963   else if (getPairId (AOP (result)) == PAIR_HL && !isLastUse (ic, result)
6964            && !isBitvar)
6965     {
6966       offset = 0;
6967
6968       while (size--)
6969         {
6970           const char *l = aopGet (AOP (right), offset, FALSE);
6971           if (isRegOrLit (AOP (right)) && !IS_GB)
6972             {
6973               emit2 ("ld !*pair,%s", _pairs[PAIR_HL].name, l);
6974             }
6975           else
6976             {
6977               _moveA (l);
6978               emit2 ("ld !*pair,a", _pairs[PAIR_HL].name);
6979             }
6980           if (size)
6981             {
6982               emit2 ("inc %s", _pairs[PAIR_HL].name);
6983               _G.pairs[PAIR_HL].offset++;
6984             }
6985           offset++;
6986         }
6987
6988       /* Fixup HL back down */
6989       for (size = AOP_SIZE (right)-1; size; size--)
6990         {
6991           emit2 ("dec %s", _pairs[PAIR_HL].name);
6992         }
6993       goto release;
6994     }
6995
6996   /* if the operand is already in dptr
6997      then we do nothing else we move the value to dptr */
6998   if (AOP_TYPE (result) != AOP_STR)
6999     {
7000       fetchPair (pairId, AOP (result));
7001     }
7002   /* so hl now contains the address */
7003   freeAsmop (result, NULL, ic);
7004
7005   /* if bit then unpack */
7006   if (isBitvar)
7007     {
7008       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, pairId, ic);
7009       goto release;
7010       //wassert (0);
7011     }
7012   else
7013     {
7014       offset = 0;
7015
7016       while (size--)
7017         {
7018           const char *l = aopGet (AOP (right), offset, FALSE);
7019           if (isRegOrLit (AOP (right)) && !IS_GB)
7020             {
7021               emit2 ("ld !*pair,%s", _pairs[pairId].name, l);
7022             }
7023           else
7024             {
7025               _moveA (l);
7026               emit2 ("ld !*pair,a", _pairs[pairId].name);
7027             }
7028           if (size)
7029             {
7030               emit2 ("inc %s", _pairs[pairId].name);
7031               _G.pairs[pairId].offset++;
7032             }
7033           offset++;
7034         }
7035     }
7036 release:
7037   freeAsmop (right, NULL, ic);
7038 }
7039
7040 /*-----------------------------------------------------------------*/
7041 /* genPointerSet - stores the value into a pointer location        */
7042 /*-----------------------------------------------------------------*/
7043 static void
7044 genPointerSet (iCode * ic)
7045 {
7046   operand *right, *result;
7047   sym_link *type, *etype;
7048
7049   right = IC_RIGHT (ic);
7050   result = IC_RESULT (ic);
7051
7052   /* depending on the type of pointer we need to
7053      move it to the correct pointer register */
7054   type = operandType (result);
7055   etype = getSpec (type);
7056
7057   genGenPointerSet (right, result, ic);
7058 }
7059
7060 /*-----------------------------------------------------------------*/
7061 /* genIfx - generate code for Ifx statement                        */
7062 /*-----------------------------------------------------------------*/
7063 static void
7064 genIfx (iCode * ic, iCode * popIc)
7065 {
7066   operand *cond = IC_COND (ic);
7067   int isbit = 0;
7068
7069   aopOp (cond, ic, FALSE, TRUE);
7070
7071   /* get the value into acc */
7072   if (AOP_TYPE (cond) != AOP_CRY)
7073     _toBoolean (cond);
7074   else
7075     isbit = 1;
7076   /* the result is now in the accumulator */
7077   freeAsmop (cond, NULL, ic);
7078
7079   /* if there was something to be popped then do it */
7080   if (popIc)
7081     genIpop (popIc);
7082
7083   /* if the condition is  a bit variable */
7084   if (isbit && IS_ITEMP (cond) &&
7085       SPIL_LOC (cond))
7086     genIfxJump (ic, SPIL_LOC (cond)->rname);
7087   else if (isbit && !IS_ITEMP (cond))
7088     genIfxJump (ic, OP_SYMBOL (cond)->rname);
7089   else
7090     genIfxJump (ic, "a");
7091
7092   ic->generated = 1;
7093 }
7094
7095 /*-----------------------------------------------------------------*/
7096 /* genAddrOf - generates code for address of                       */
7097 /*-----------------------------------------------------------------*/
7098 static void
7099 genAddrOf (iCode * ic)
7100 {
7101   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7102
7103   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
7104
7105   /* if the operand is on the stack then we
7106      need to get the stack offset of this
7107      variable */
7108   if (IS_GB)
7109     {
7110       if (sym->onStack)
7111         {
7112           spillCached ();
7113           if (sym->stack <= 0)
7114             {
7115               setupPairFromSP (PAIR_HL, sym->stack + _G.stack.pushed + _G.stack.offset);
7116             }
7117           else
7118             {
7119               setupPairFromSP (PAIR_HL, sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
7120             }
7121           commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
7122         }
7123       else
7124         {
7125           emit2 ("ld de,!hashedstr", sym->rname);
7126           commitPair (AOP (IC_RESULT (ic)), PAIR_DE);
7127         }
7128     }
7129   else
7130     {
7131       spillCached ();
7132       if (sym->onStack)
7133         {
7134           /* if it has an offset  then we need to compute it */
7135           if (sym->stack > 0)
7136             emit2 ("ld hl,!immedword", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
7137           else
7138             emit2 ("ld hl,!immedword", sym->stack + _G.stack.pushed + _G.stack.offset);
7139           emit2 ("add hl,sp");
7140         }
7141       else
7142         {
7143           emit2 ("ld hl,!hashedstr", sym->rname);
7144         }
7145       commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
7146     }
7147   freeAsmop (IC_RESULT (ic), NULL, ic);
7148 }
7149
7150 /*-----------------------------------------------------------------*/
7151 /* genAssign - generate code for assignment                        */
7152 /*-----------------------------------------------------------------*/
7153 static void
7154 genAssign (iCode * ic)
7155 {
7156   operand *result, *right;
7157   int size, offset;
7158   unsigned long lit = 0L;
7159
7160   result = IC_RESULT (ic);
7161   right = IC_RIGHT (ic);
7162
7163   /* Dont bother assigning if they are the same */
7164   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7165     {
7166       emitDebug ("; (operands are equal %u)", operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)));
7167       return;
7168     }
7169
7170   aopOp (right, ic, FALSE, FALSE);
7171   aopOp (result, ic, TRUE, FALSE);
7172
7173   /* if they are the same registers */
7174   if (sameRegs (AOP (right), AOP (result)))
7175     {
7176       emitDebug ("; (registers are the same)");
7177       goto release;
7178     }
7179
7180   /* if the result is a bit */
7181   if (AOP_TYPE (result) == AOP_CRY)
7182     {
7183       wassertl (0, "Tried to assign to a bit");
7184     }
7185
7186   /* general case */
7187   size = AOP_SIZE (result);
7188   offset = 0;
7189
7190   if (AOP_TYPE (right) == AOP_LIT)
7191     {
7192       lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7193     }
7194
7195   if (isPair (AOP (result)))
7196     {
7197       fetchPairLong (getPairId (AOP (result)), AOP (right), ic, LSB);
7198     }
7199   else if ((size > 1) &&
7200            (AOP_TYPE (result) != AOP_REG) &&
7201            (AOP_TYPE (right) == AOP_LIT) &&
7202            !IS_FLOAT (operandType (right)) &&
7203            (lit < 256L))
7204     {
7205       bool fXored = FALSE;
7206       offset = 0;
7207       /* Work from the top down.
7208          Done this way so that we can use the cached copy of 0
7209          in A for a fast clear */
7210       while (size--)
7211         {
7212           if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)
7213             {
7214               if (!fXored && size > 1)
7215                 {
7216                   emit2 ("xor a,a");
7217                   fXored = TRUE;
7218                 }
7219               if (fXored)
7220                 {
7221                   aopPut (AOP (result), "a", offset);
7222                 }
7223               else
7224                 {
7225                   aopPut (AOP (result), "!zero", offset);
7226                 }
7227             }
7228           else
7229             aopPut (AOP (result),
7230                     aopGet (AOP (right), offset, FALSE),
7231                     offset);
7232           offset++;
7233         }
7234     }
7235   else if (size == 2 && AOP_TYPE (right) == AOP_IY)
7236     {
7237       emit2 ("ld hl,(%s)", AOP (right)->aopu.aop_dir);
7238       aopPut (AOP (result), "l", LSB);
7239       aopPut (AOP (result), "h", MSB16);
7240     }
7241   else if (size == 2 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
7242     {
7243       /* Special case.  Load into a and d, then load out. */
7244       _moveA (aopGet (AOP (right), 0, FALSE));
7245       emit2 ("ld e,%s", aopGet (AOP (right), 1, FALSE));
7246       aopPut (AOP (result), "a", 0);
7247       aopPut (AOP (result), "e", 1);
7248     }
7249   else if (size == 4 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
7250     {
7251       /* Special case - simple memcpy */
7252       aopGet (AOP (right), LSB, FALSE);
7253       emit2 ("ld d,h");
7254       emit2 ("ld e,l");
7255       aopGet (AOP (result), LSB, FALSE);
7256
7257       while (size--)
7258         {
7259           emit2 ("ld a,(de)");
7260           /* Peephole will optimise this. */
7261           emit2 ("ld (hl),a");
7262
7263           if (size != 0)
7264             {
7265               emit2 ("inc hl");
7266               emit2 ("inc de");
7267             }
7268         }
7269       spillPair (PAIR_HL);
7270     }
7271   else
7272     {
7273       while (size--)
7274         {
7275           /* PENDING: do this check better */
7276           if (IS_GB && requiresHL (AOP (right)) && requiresHL (AOP (result)))
7277             {
7278               _moveA (aopGet (AOP (right), offset, FALSE));
7279               aopPut (AOP (result), "a", offset);
7280             }
7281           else
7282             aopPut (AOP (result),
7283                     aopGet (AOP (right), offset, FALSE),
7284                     offset);
7285           offset++;
7286         }
7287     }
7288
7289 release:
7290   freeAsmop (right, NULL, ic);
7291   freeAsmop (result, NULL, ic);
7292 }
7293
7294 /*-----------------------------------------------------------------*/
7295 /* genJumpTab - genrates code for jump table                       */
7296 /*-----------------------------------------------------------------*/
7297 static void
7298 genJumpTab (iCode * ic)
7299 {
7300   symbol *jtab;
7301   const char *l;
7302
7303   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
7304   /* get the condition into accumulator */
7305   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE);
7306   if (!IS_GB)
7307     emit2 ("push de");
7308   emit2 ("ld e,%s", l);
7309   emit2 ("ld d,!zero");
7310   jtab = newiTempLabel (NULL);
7311   spillCached ();
7312   emit2 ("ld hl,!immed!tlabel", jtab->key + 100);
7313   emit2 ("add hl,de");
7314   emit2 ("add hl,de");
7315   emit2 ("add hl,de");
7316   freeAsmop (IC_JTCOND (ic), NULL, ic);
7317   if (!IS_GB)
7318     emit2 ("pop de");
7319   emit2 ("jp !*hl");
7320   emitLabel (jtab->key + 100);
7321   /* now generate the jump labels */
7322   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7323        jtab = setNextItem (IC_JTLABELS (ic)))
7324     emit2 ("jp !tlabel", jtab->key + 100);
7325 }
7326
7327 /*-----------------------------------------------------------------*/
7328 /* genCast - gen code for casting                                  */
7329 /*-----------------------------------------------------------------*/
7330 static void
7331 genCast (iCode * ic)
7332 {
7333   operand *result = IC_RESULT (ic);
7334   sym_link *rtype = operandType (IC_RIGHT (ic));
7335   operand *right = IC_RIGHT (ic);
7336   int size, offset;
7337
7338   /* if they are equivalent then do nothing */
7339   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7340     return;
7341
7342   aopOp (right, ic, FALSE, FALSE);
7343   aopOp (result, ic, FALSE, FALSE);
7344
7345   /* if the result is a bit */
7346   if (AOP_TYPE (result) == AOP_CRY)
7347     {
7348       wassertl (0, "Tried to cast to a bit");
7349     }
7350
7351   /* if they are the same size : or less */
7352   if (AOP_SIZE (result) <= AOP_SIZE (right))
7353     {
7354
7355       /* if they are in the same place */
7356       if (sameRegs (AOP (right), AOP (result)))
7357         goto release;
7358
7359       /* if they in different places then copy */
7360       size = AOP_SIZE (result);
7361       offset = 0;
7362       while (size--)
7363         {
7364           aopPut (AOP (result),
7365                   aopGet (AOP (right), offset, FALSE),
7366                   offset);
7367           offset++;
7368         }
7369       goto release;
7370     }
7371
7372   /* So we now know that the size of destination is greater
7373      than the size of the source */
7374   /* we move to result for the size of source */
7375   size = AOP_SIZE (right);
7376   offset = 0;
7377   while (size--)
7378     {
7379       aopPut (AOP (result),
7380               aopGet (AOP (right), offset, FALSE),
7381               offset);
7382       offset++;
7383     }
7384
7385   /* now depending on the sign of the destination */
7386   size = AOP_SIZE (result) - AOP_SIZE (right);
7387   /* Unsigned or not an integral type - right fill with zeros */
7388   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7389     {
7390       while (size--)
7391         aopPut (AOP (result), "!zero", offset++);
7392     }
7393   else
7394     {
7395       /* we need to extend the sign :{ */
7396         const char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
7397                         FALSE);
7398       _moveA (l);
7399       emit2 ("rla ");
7400       emit2 ("sbc a,a");
7401       while (size--)
7402         aopPut (AOP (result), "a", offset++);
7403     }
7404
7405 release:
7406   freeAsmop (right, NULL, ic);
7407   freeAsmop (result, NULL, ic);
7408 }
7409
7410 /*-----------------------------------------------------------------*/
7411 /* genReceive - generate code for a receive iCode                  */
7412 /*-----------------------------------------------------------------*/
7413 static void
7414 genReceive (iCode * ic)
7415 {
7416   if (isOperandInFarSpace (IC_RESULT (ic)) &&
7417       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
7418        IS_TRUE_SYMOP (IC_RESULT (ic))))
7419     {
7420       wassert (0);
7421     }
7422   else
7423     {
7424         // PENDING: HACK
7425         int size;
7426         int i;
7427
7428         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
7429         size = AOP_SIZE(IC_RESULT(ic));
7430
7431         for (i = 0; i < size; i++) {
7432             aopPut(AOP(IC_RESULT(ic)), _fReceive[_G.receiveOffset++], i);
7433         }
7434     }
7435
7436   freeAsmop (IC_RESULT (ic), NULL, ic);
7437 }
7438
7439 /*-----------------------------------------------------------------*/
7440 /* genDummyRead - generate code for dummy read of volatiles        */
7441 /*-----------------------------------------------------------------*/
7442 static void
7443 genDummyRead (iCode * ic)
7444 {
7445   operand *op;
7446   int size, offset;
7447
7448   op = IC_RIGHT (ic);
7449   if (op && IS_SYMOP (op))
7450     {
7451       aopOp (op, ic, FALSE, FALSE);
7452
7453       /* general case */
7454       size = AOP_SIZE (op);
7455       offset = 0;
7456
7457       while (size--)
7458         {
7459           _moveA (aopGet (AOP (op), offset, FALSE));
7460           offset++;
7461         }
7462
7463       freeAsmop (op, NULL, ic);
7464     }
7465
7466   op = IC_LEFT (ic);
7467   if (op && IS_SYMOP (op))
7468     {
7469       aopOp (op, ic, FALSE, FALSE);
7470
7471       /* general case */
7472       size = AOP_SIZE (op);
7473       offset = 0;
7474
7475       while (size--)
7476         {
7477           _moveA (aopGet (AOP (op), offset, FALSE));
7478           offset++;
7479         }
7480
7481       freeAsmop (op, NULL, ic);
7482     }
7483 }
7484
7485 /*-----------------------------------------------------------------*/
7486 /* genCritical - generate code for start of a critical sequence    */
7487 /*-----------------------------------------------------------------*/
7488 static void
7489 genCritical (iCode *ic)
7490 {
7491   symbol *tlbl = newiTempLabel (NULL);
7492
7493   if (IS_GB)
7494     {
7495       emit2 ("!di");
7496     }
7497   else if (IC_RESULT (ic))
7498     {
7499       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
7500       aopPut (AOP (IC_RESULT (ic)), "!zero", 0);
7501       //get interrupt enable flag IFF2 into P/O
7502       emit2 ("ld a,i");
7503       //disable interrupt
7504       emit2 ("!di");
7505       //parity odd <==> P/O=0 <==> interrupt enable flag IFF2=0
7506       emit2 ("jp PO,!tlabel", tlbl->key + 100);
7507       aopPut (AOP (IC_RESULT (ic)), "!one", 0);
7508       emit2 ("!tlabeldef", (tlbl->key + 100));
7509       _G.lines.current->isLabel = 1;
7510       freeAsmop (IC_RESULT (ic), NULL, ic);
7511     }
7512   else
7513     {
7514       //get interrupt enable flag IFF2 into P/O
7515       emit2 ("ld a,i");
7516       //disable interrupt
7517       emit2 ("!di");
7518       //save P/O flag
7519       emit2 ("push af");
7520     }
7521 }
7522
7523 /*-----------------------------------------------------------------*/
7524 /* genEndCritical - generate code for end of a critical sequence   */
7525 /*-----------------------------------------------------------------*/
7526 static void
7527 genEndCritical (iCode *ic)
7528 {
7529   symbol *tlbl = newiTempLabel (NULL);
7530
7531   if (IS_GB)
7532     {
7533       emit2 ("!ei");
7534     }
7535   else if (IC_RIGHT (ic))
7536     {
7537       aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
7538       _toBoolean (IC_RIGHT (ic));
7539       //don't enable interrupts if they were off before
7540       emit2 ("!shortjp Z,!tlabel", tlbl->key + 100);
7541       emit2 ("!ei");
7542       emitLabel (tlbl->key + 100);
7543       freeAsmop (IC_RIGHT (ic), NULL, ic);
7544     }
7545   else
7546     {
7547       //restore P/O flag
7548       emit2 ("pop af");
7549       //parity odd <==> P/O=0 <==> interrupt enable flag IFF2 was 0 <==>
7550       //don't enable interrupts as they were off before
7551       emit2 ("jp PO,!tlabel", tlbl->key + 100);
7552       emit2 ("!ei");
7553       emit2 ("!tlabeldef", (tlbl->key + 100));
7554       _G.lines.current->isLabel = 1;
7555     }
7556 }
7557
7558 enum
7559   {
7560     /** Maximum number of bytes to emit per line. */
7561     DBEMIT_MAX_RUN = 8
7562   };
7563
7564 /** Context for the byte output chunker. */
7565 typedef struct
7566 {
7567   unsigned char buffer[DBEMIT_MAX_RUN];
7568   int pos;
7569 } DBEMITCTX;
7570
7571
7572 /** Flushes a byte chunker by writing out all in the buffer and
7573     reseting.
7574 */
7575 static void
7576 _dbFlush(DBEMITCTX *self)
7577 {
7578   char line[256];
7579
7580   if (self->pos > 0)
7581     {
7582       int i;
7583       sprintf(line, ".db 0x%02X", self->buffer[0]);
7584
7585       for (i = 1; i < self->pos; i++)
7586         {
7587           sprintf(line + strlen(line), ", 0x%02X", self->buffer[i]);
7588         }
7589       emit2(line);
7590     }
7591   self->pos = 0;
7592 }
7593
7594 /** Write out another byte, buffering until a decent line is
7595     generated.
7596 */
7597 static void
7598 _dbEmit(DBEMITCTX *self, int c)
7599 {
7600   if (self->pos == DBEMIT_MAX_RUN)
7601     {
7602       _dbFlush(self);
7603     }
7604   self->buffer[self->pos++] = c;
7605 }
7606
7607 /** Context for a simple run length encoder. */
7608 typedef struct
7609 {
7610   unsigned last;
7611   unsigned char buffer[128];
7612   int pos;
7613   /** runLen may be equivalent to pos. */
7614   int runLen;
7615 } RLECTX;
7616
7617 enum
7618   {
7619     RLE_CHANGE_COST = 4,
7620     RLE_MAX_BLOCK = 127
7621   };
7622
7623 /** Flush the buffer of a run length encoder by writing out the run or
7624     data that it currently contains.
7625 */
7626 static void
7627 _rleCommit(RLECTX *self)
7628 {
7629   int i;
7630   if (self->pos != 0)
7631     {
7632       DBEMITCTX db;
7633       memset(&db, 0, sizeof(db));
7634
7635       emit2(".db %u", self->pos);
7636
7637       for (i = 0; i < self->pos; i++)
7638         {
7639           _dbEmit(&db, self->buffer[i]);
7640         }
7641       _dbFlush(&db);
7642     }
7643   /* Reset */
7644   self->pos = 0;
7645 }
7646
7647 /* Encoder design:
7648    Can get either a run or a block of random stuff.
7649    Only want to change state if a good run comes in or a run ends.
7650    Detecting run end is easy.
7651    Initial state?
7652
7653    Say initial state is in run, len zero, last zero.  Then if you get a
7654    few zeros then something else then a short run will be output.
7655    Seems OK.  While in run mode, keep counting.  While in random mode,
7656    keep a count of the run.  If run hits margin, output all up to run,
7657    restart, enter run mode.
7658 */
7659
7660 /** Add another byte into the run length encoder, flushing as
7661     required.  The run length encoder uses the Amiga IFF style, where
7662     a block is prefixed by its run length.  A positive length means
7663     the next n bytes pass straight through.  A negative length means
7664     that the next byte is repeated -n times.  A zero terminates the
7665     chunks.
7666 */
7667 static void
7668 _rleAppend(RLECTX *self, unsigned c)
7669 {
7670   int i;
7671
7672   if (c != self->last)
7673     {
7674       /* The run has stopped.  See if it is worthwhile writing it out
7675          as a run.  Note that the random data comes in as runs of
7676          length one.
7677       */
7678       if (self->runLen > RLE_CHANGE_COST)
7679         {
7680           /* Yes, worthwhile. */
7681           /* Commit whatever was in the buffer. */
7682           _rleCommit(self);
7683           emit2("!db !immed-%u,!immedbyte", self->runLen, self->last);
7684         }
7685       else
7686         {
7687           /* Not worthwhile.  Append to the end of the random list. */
7688           for (i = 0; i < self->runLen; i++)
7689             {
7690               if (self->pos >= RLE_MAX_BLOCK)
7691                 {
7692                   /* Commit. */
7693                   _rleCommit(self);
7694                 }
7695               self->buffer[self->pos++] = self->last;
7696             }
7697         }
7698       self->runLen = 1;
7699       self->last = c;
7700     }
7701   else
7702     {
7703       if (self->runLen >= RLE_MAX_BLOCK)
7704         {
7705           /* Commit whatever was in the buffer. */
7706           _rleCommit(self);
7707
7708           emit2 ("!db !immed-%u,!immedbyte", self->runLen, self->last);
7709           self->runLen = 0;
7710         }
7711       self->runLen++;
7712     }
7713 }
7714
7715 static void
7716 _rleFlush(RLECTX *self)
7717 {
7718   _rleAppend(self, -1);
7719   _rleCommit(self);
7720   self->pos = 0;
7721   self->last = 0;
7722   self->runLen = 0;
7723 }
7724
7725 /** genArrayInit - Special code for initialising an array with constant
7726    data.
7727 */
7728 static void
7729 genArrayInit (iCode * ic)
7730 {
7731   literalList *iLoop;
7732   int         ix;
7733   int         elementSize = 0, eIndex, i;
7734   unsigned    val, lastVal;
7735   sym_link    *type;
7736   RLECTX      rle;
7737
7738   memset(&rle, 0, sizeof(rle));
7739
7740   aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
7741
7742   _saveRegsForCall(ic, 0);
7743
7744   fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
7745   emit2 ("call __initrleblock");
7746
7747   type = operandType(IC_LEFT(ic));
7748
7749   if (type && type->next)
7750     {
7751       if (IS_SPEC(type->next) || IS_PTR(type->next))
7752         {
7753           elementSize = getSize(type->next);
7754         }
7755       else if (IS_ARRAY(type->next) && type->next->next)
7756         {
7757           elementSize = getSize(type->next->next);
7758         }
7759       else
7760         {
7761           printTypeChainRaw (type, NULL);
7762           wassertl (0, "Can't determine element size in genArrayInit.");
7763         }
7764     }
7765   else
7766     {
7767       wassertl (0, "Can't determine element size in genArrayInit.");
7768     }
7769
7770   wassertl ((elementSize > 0) && (elementSize <= 4), "Illegal element size in genArrayInit.");
7771
7772   iLoop = IC_ARRAYILIST(ic);
7773   lastVal = (unsigned)-1;
7774
7775   /* Feed all the bytes into the run length encoder which will handle
7776      the actual output.
7777      This works well for mixed char data, and for random int and long
7778      data.
7779   */
7780   while (iLoop)
7781     {
7782       ix = iLoop->count;
7783
7784       for (i = 0; i < ix; i++)
7785         {
7786           for (eIndex = 0; eIndex < elementSize; eIndex++)
7787             {
7788               val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
7789               _rleAppend(&rle, val);
7790             }
7791         }
7792
7793       iLoop = iLoop->next;
7794     }
7795
7796   _rleFlush(&rle);
7797   /* Mark the end of the run. */
7798   emit2(".db 0");
7799
7800   _restoreRegsAfterCall();
7801
7802   spillCached ();
7803
7804   freeAsmop (IC_LEFT(ic), NULL, ic);
7805 }
7806
7807 static void
7808 _swap (PAIR_ID one, PAIR_ID two)
7809 {
7810   if ((one == PAIR_DE && two == PAIR_HL) || (one == PAIR_HL && two == PAIR_DE))
7811     {
7812       emit2 ("ex de,hl");
7813     }
7814   else
7815     {
7816       emit2 ("ld a,%s", _pairs[one].l);
7817       emit2 ("ld %s,%s", _pairs[one].l, _pairs[two].l);
7818       emit2 ("ld %s,a", _pairs[two].l);
7819       emit2 ("ld a,%s", _pairs[one].h);
7820       emit2 ("ld %s,%s", _pairs[one].h, _pairs[two].h);
7821       emit2 ("ld %s,a", _pairs[two].h);
7822     }
7823 }
7824
7825 /* The problem is that we may have all three pairs used and they may
7826    be needed in a different order.
7827
7828    Note: Have ex de,hl
7829
7830    Combinations:
7831      hl = hl            => unity, fine
7832      bc = bc
7833      de = de
7834
7835      hl = hl            hl = hl, swap de <=> bc
7836      bc = de
7837      de = bc
7838
7839      hl = bc            Worst case
7840      bc = de
7841      de = hl
7842
7843      hl = bc            de = de, swap bc <=> hl
7844      bc = hl
7845      de = de
7846
7847      hl = de            Worst case
7848      bc = hl
7849      de = bc
7850
7851      hl = de            bc = bc, swap hl <=> de
7852      bc = bc
7853      de = hl
7854
7855    Break it down into:
7856     * Any pair = pair are done last
7857     * Any pair = iTemp are done last
7858     * Any swaps can be done any time
7859
7860    A worst case:
7861     push p1
7862     p1 = p2
7863     p2 = p3
7864     pop  p3
7865
7866    So how do we detect the cases?
7867    How about a 3x3 matrix?
7868         source
7869    dest x x x x
7870         x x x x
7871         x x x x (Fourth for iTemp/other)
7872
7873    First determin which mode to use by counting the number of unity and
7874    iTemp assigns.
7875      Three - any order
7876      Two - Assign the pair first, then the rest
7877      One - Swap the two, then the rest
7878      Zero - Worst case.
7879 */
7880 static void
7881 setupForBuiltin3 (iCode *ic, int nparams, operand **pparams)
7882 {
7883   PAIR_ID ids[NUM_PAIRS][NUM_PAIRS];
7884   PAIR_ID dest[3] = {
7885     PAIR_BC, PAIR_HL, PAIR_DE
7886   };
7887   int i, j, nunity = 0;
7888   memset (ids, PAIR_INVALID, sizeof (ids));
7889
7890   /* Sanity checks */
7891   wassert (nparams == 3);
7892
7893   /* First save everything that needs to be saved. */
7894   _saveRegsForCall (ic, 0);
7895
7896   /* Loading HL first means that DE is always fine. */
7897   for (i = 0; i < nparams; i++)
7898     {
7899       aopOp (pparams[i], ic, FALSE, FALSE);
7900       ids[dest[i]][getPairId (AOP (pparams[i]))] = TRUE;
7901     }
7902
7903   /* Count the number of unity or iTemp assigns. */
7904   for (i = 0; i < 3; i++)
7905     {
7906       if (ids[dest[i]][dest[i]] == TRUE || ids[dest[i]][PAIR_INVALID] == TRUE)
7907         {
7908           nunity++;
7909         }
7910     }
7911
7912   if (nunity == 3)
7913     {
7914       /* Any order, fall through. */
7915     }
7916   else if (nunity == 2)
7917     {
7918       /* One is assigned.  Pull it out and assign. */
7919       for (i = 0; i < 3; i++)
7920         {
7921           for (j = 0; j < NUM_PAIRS; j++)
7922             {
7923               if (ids[dest[i]][j] == TRUE)
7924                 {
7925                   /* Found it.  See if it's the right one. */
7926                   if (j == PAIR_INVALID || j == dest[i])
7927                     {
7928                       /* Keep looking. */
7929                     }
7930                   else
7931                     {
7932                       fetchPair(dest[i], AOP (pparams[i]));
7933                       goto done;
7934                     }
7935                 }
7936             }
7937         }
7938     }
7939   else if (nunity == 1)
7940     {
7941       /* Find the pairs to swap. */
7942       for (i = 0; i < 3; i++)
7943         {
7944           for (j = 0; j < NUM_PAIRS; j++)
7945             {
7946               if (ids[dest[i]][j] == TRUE)
7947                 {
7948                   if (j == PAIR_INVALID || j == dest[i])
7949                     {
7950                       /* Keep looking. */
7951                     }
7952                   else
7953                     {
7954                       _swap (j, dest[i]);
7955                       goto done;
7956                     }
7957                 }
7958             }
7959         }
7960     }
7961   else
7962     {
7963       int next = getPairId (AOP (pparams[0]));
7964       emit2 ("push %s", _pairs[next].name);
7965
7966       if (next == dest[1])
7967         {
7968           fetchPair (dest[1], AOP (pparams[1]));
7969           fetchPair (dest[2], AOP (pparams[2]));
7970         }
7971       else
7972         {
7973           fetchPair (dest[2], AOP (pparams[2]));
7974           fetchPair (dest[1], AOP (pparams[1]));
7975         }
7976       emit2 ("pop %s", _pairs[dest[0]].name);
7977     }
7978  done:
7979   /* Finally pull out all of the iTemps */
7980   for (i = 0; i < 3; i++)
7981     {
7982       if (ids[dest[i]][PAIR_INVALID] == 1)
7983         {
7984           fetchPair (dest[i], AOP (pparams[i]));
7985         }
7986     }
7987 }
7988
7989 static void
7990 genBuiltInStrcpy (iCode *ic, int nParams, operand **pparams)
7991 {
7992   operand *from, *to;
7993   symbol *label;
7994   bool deInUse;
7995
7996   wassertl (nParams == 2, "Built-in strcpy must have two parameters");
7997   to = pparams[0];
7998   from = pparams[1];
7999
8000   deInUse = bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX);
8001
8002   setupForBuiltin3 (ic, nParams, pparams);
8003
8004   label = newiTempLabel(NULL);
8005
8006   emitLabel (label->key);
8007   emit2 ("ld a,(hl)");
8008   emit2 ("ldi");
8009   emit2 ("or a");
8010   emit2 ("!shortjp NZ,!tlabel ; 1", label->key);
8011
8012   freeAsmop (from, NULL, ic->next);
8013   freeAsmop (to, NULL, ic);
8014 }
8015
8016 static void
8017 genBuiltInMemcpy (iCode *ic, int nParams, operand **pparams)
8018 {
8019   operand *from, *to, *count;
8020   bool deInUse;
8021
8022   wassertl (nParams == 3, "Built-in memcpy must have two parameters");
8023   to = pparams[2];
8024   from = pparams[1];
8025   count = pparams[0];
8026
8027   deInUse = bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX);
8028
8029   setupForBuiltin3 (ic, nParams, pparams);
8030
8031   emit2 ("ldir");
8032
8033   freeAsmop (count, NULL, ic->next->next);
8034   freeAsmop (from, NULL, ic);
8035
8036   _restoreRegsAfterCall();
8037
8038   /* if we need assign a result value */
8039   if ((IS_ITEMP (IC_RESULT (ic)) &&
8040        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
8041         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
8042       IS_TRUE_SYMOP (IC_RESULT (ic)))
8043     {
8044       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8045       movLeft2ResultLong (to, 0, IC_RESULT (ic), 0, 0, 2);
8046       freeAsmop (IC_RESULT (ic), NULL, ic);
8047     }
8048
8049   freeAsmop (to, NULL, ic->next);
8050 }
8051
8052 /*-----------------------------------------------------------------*/
8053 /* genBuiltIn - calls the appropriate function to  generating code */
8054 /* for a built in function                                         */
8055 /*-----------------------------------------------------------------*/
8056 static void genBuiltIn (iCode *ic)
8057 {
8058     operand *bi_parms[MAX_BUILTIN_ARGS];
8059     int nbi_parms;
8060     iCode *bi_iCode;
8061     symbol *bif;
8062
8063     /* get all the arguments for a built in function */
8064     bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
8065
8066     /* which function is it */
8067     bif = OP_SYMBOL(IC_LEFT(bi_iCode));
8068
8069     if (strcmp(bif->name,"__builtin_strcpy")==0)
8070       {
8071         genBuiltInStrcpy(bi_iCode, nbi_parms, bi_parms);
8072       }
8073     else if (strcmp(bif->name,"__builtin_memcpy")==0)
8074       {
8075         genBuiltInMemcpy(bi_iCode, nbi_parms, bi_parms);
8076       }
8077     else
8078       {
8079         wassertl (0, "Unknown builtin function encountered");
8080       }
8081 }
8082
8083 /*-----------------------------------------------------------------*/
8084 /* genZ80Code - generate code for Z80 based controllers            */
8085 /*-----------------------------------------------------------------*/
8086 void
8087 genZ80Code (iCode * lic)
8088 {
8089   iCode *ic;
8090   int cln = 0;
8091
8092   /* Hack */
8093   if (IS_GB)
8094     {
8095       _fReturn = _gbz80_return;
8096       _fTmp = _gbz80_return;
8097     }
8098   else
8099     {
8100       _fReturn = _z80_return;
8101       _fTmp = _z80_return;
8102     }
8103
8104   _G.lines.head = _G.lines.current = NULL;
8105
8106   /* if debug information required */
8107   if (options.debug && currFunc)
8108     {
8109       debugFile->writeFunction (currFunc, lic);
8110     }
8111
8112   for (ic = lic; ic; ic = ic->next)
8113     {
8114       _G.current_iCode = ic;
8115
8116       if (ic->lineno && cln != ic->lineno)
8117         {
8118           if (options.debug)
8119             {
8120               debugFile->writeCLine (ic);
8121             }
8122           if (!options.noCcodeInAsm)
8123             {
8124               emit2 (";%s:%d: %s", ic->filename, ic->lineno,
8125                      printCLine(ic->filename, ic->lineno));
8126             }
8127           cln = ic->lineno;
8128         }
8129       if (options.iCodeInAsm)
8130         {
8131           char *iLine = printILine(ic);
8132           emit2 (";ic:%d: %s", ic->key, iLine);
8133           dbuf_free(iLine);
8134         }
8135       /* if the result is marked as
8136          spilt and rematerializable or code for
8137          this has already been generated then
8138          do nothing */
8139       if (resultRemat (ic) || ic->generated)
8140         continue;
8141
8142       /* depending on the operation */
8143       switch (ic->op)
8144         {
8145         case '!':
8146           emitDebug ("; genNot");
8147           genNot (ic);
8148           break;
8149
8150         case '~':
8151           emitDebug ("; genCpl");
8152           genCpl (ic);
8153           break;
8154
8155         case UNARYMINUS:
8156           emitDebug ("; genUminus");
8157           genUminus (ic);
8158           break;
8159
8160         case IPUSH:
8161           emitDebug ("; genIpush");
8162           genIpush (ic);
8163           break;
8164
8165         case IPOP:
8166           /* IPOP happens only when trying to restore a
8167              spilt live range, if there is an ifx statement
8168              following this pop then the if statement might
8169              be using some of the registers being popped which
8170              would destroy the contents of the register so
8171              we need to check for this condition and handle it */
8172           if (ic->next &&
8173               ic->next->op == IFX &&
8174               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8175             {
8176               emitDebug ("; genIfx");
8177               genIfx (ic->next, ic);
8178             }
8179           else
8180             {
8181               emitDebug ("; genIpop");
8182               genIpop (ic);
8183             }
8184           break;
8185
8186         case CALL:
8187           emitDebug ("; genCall");
8188           genCall (ic);
8189           break;
8190
8191         case PCALL:
8192           emitDebug ("; genPcall");
8193           genPcall (ic);
8194           break;
8195
8196         case FUNCTION:
8197           emitDebug ("; genFunction");
8198           genFunction (ic);
8199           break;
8200
8201         case ENDFUNCTION:
8202           emitDebug ("; genEndFunction");
8203           genEndFunction (ic);
8204           break;
8205
8206         case RETURN:
8207           emitDebug ("; genRet");
8208           genRet (ic);
8209           break;
8210
8211         case LABEL:
8212           emitDebug ("; genLabel");
8213           genLabel (ic);
8214           break;
8215
8216         case GOTO:
8217           emitDebug ("; genGoto");
8218           genGoto (ic);
8219           break;
8220
8221         case '+':
8222           emitDebug ("; genPlus");
8223           genPlus (ic);
8224           break;
8225
8226         case '-':
8227           emitDebug ("; genMinus");
8228           genMinus (ic);
8229           break;
8230
8231         case '*':
8232           emitDebug ("; genMult");
8233           genMult (ic);
8234           break;
8235
8236         case '/':
8237           emitDebug ("; genDiv");
8238           genDiv (ic);
8239           break;
8240
8241         case '%':
8242           emitDebug ("; genMod");
8243           genMod (ic);
8244           break;
8245
8246         case '>':
8247           emitDebug ("; genCmpGt");
8248           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8249           break;
8250
8251         case '<':
8252           emitDebug ("; genCmpLt");
8253           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8254           break;
8255
8256         case LE_OP:
8257         case GE_OP:
8258         case NE_OP:
8259
8260           /* note these two are xlated by algebraic equivalence
8261              during parsing SDCC.y */
8262           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8263                   "got '>=' or '<=' shouldn't have come here");
8264           break;
8265
8266         case EQ_OP:
8267           emitDebug ("; genCmpEq");
8268           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8269           break;
8270
8271         case AND_OP:
8272           emitDebug ("; genAndOp");
8273           genAndOp (ic);
8274           break;
8275
8276         case OR_OP:
8277           emitDebug ("; genOrOp");
8278           genOrOp (ic);
8279           break;
8280
8281         case '^':
8282           emitDebug ("; genXor");
8283           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8284           break;
8285
8286         case '|':
8287           emitDebug ("; genOr");
8288           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8289           break;
8290
8291         case BITWISEAND:
8292           emitDebug ("; genAnd");
8293           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8294           break;
8295
8296         case INLINEASM:
8297           emitDebug ("; genInline");
8298           genInline (ic);
8299           break;
8300
8301         case RRC:
8302           emitDebug ("; genRRC");
8303           genRRC (ic);
8304           break;
8305
8306         case RLC:
8307           emitDebug ("; genRLC");
8308           genRLC (ic);
8309           break;
8310
8311         case GETHBIT:
8312           emitDebug ("; genGetHBIT");
8313           genGetHbit (ic);
8314           break;
8315
8316         case LEFT_OP:
8317           emitDebug ("; genLeftShift");
8318           genLeftShift (ic);
8319           break;
8320
8321         case RIGHT_OP:
8322           emitDebug ("; genRightShift");
8323           genRightShift (ic);
8324           break;
8325
8326         case GET_VALUE_AT_ADDRESS:
8327           emitDebug ("; genPointerGet");
8328           genPointerGet (ic);
8329           break;
8330
8331         case '=':
8332
8333           if (POINTER_SET (ic))
8334             {
8335               emitDebug ("; genAssign (pointer)");
8336               genPointerSet (ic);
8337             }
8338           else
8339             {
8340               emitDebug ("; genAssign");
8341               genAssign (ic);
8342             }
8343           break;
8344
8345         case IFX:
8346           emitDebug ("; genIfx");
8347           genIfx (ic, NULL);
8348           break;
8349
8350         case ADDRESS_OF:
8351           emitDebug ("; genAddrOf");
8352           genAddrOf (ic);
8353           break;
8354
8355         case JUMPTABLE:
8356           emitDebug ("; genJumpTab");
8357           genJumpTab (ic);
8358           break;
8359
8360         case CAST:
8361           emitDebug ("; genCast");
8362           genCast (ic);
8363           break;
8364
8365         case RECEIVE:
8366           emitDebug ("; genReceive");
8367           genReceive (ic);
8368           break;
8369
8370         case SEND:
8371           if (ic->builtinSEND)
8372             {
8373               emitDebug ("; genBuiltIn");
8374               genBuiltIn(ic);
8375             }
8376           else
8377             {
8378               emitDebug ("; addSet");
8379               addSet (&_G.sendSet, ic);
8380             }
8381           break;
8382
8383         case ARRAYINIT:
8384           emitDebug ("; genArrayInit");
8385           genArrayInit(ic);
8386           break;
8387
8388         case DUMMY_READ_VOLATILE:
8389           emitDebug ("; genDummyRead");
8390           genDummyRead (ic);
8391           break;
8392
8393         case CRITICAL:
8394           emitDebug ("; genCritical");
8395           genCritical (ic);
8396           break;
8397
8398         case ENDCRITICAL:
8399           emitDebug ("; genEndCritical");
8400           genEndCritical (ic);
8401           break;
8402
8403         default:
8404           ic = ic;
8405         }
8406     }
8407
8408
8409   /* now we are ready to call the
8410      peep hole optimizer */
8411   if (!options.nopeep)
8412     peepHole (&_G.lines.head);
8413
8414   /* This is unfortunate */
8415   /* now do the actual printing */
8416   {
8417     struct dbuf_s *buf = codeOutBuf;
8418     if (isInHome () && codeOutBuf == &code->oBuf)
8419       codeOutBuf = &home->oBuf;
8420     printLine (_G.lines.head, codeOutBuf);
8421     if (_G.flushStatics)
8422       {
8423         flushStatics ();
8424         _G.flushStatics = 0;
8425       }
8426     codeOutBuf = buf;
8427   }
8428
8429   freeTrace(&_G.lines.trace);
8430   freeTrace(&_G.trace.aops);
8431 }
8432
8433 /*
8434   Attic
8435 static int
8436 _isPairUsed (iCode * ic, PAIR_ID pairId)
8437 {
8438   int ret = 0;
8439   switch (pairId)
8440     {
8441     case PAIR_DE:
8442       if (bitVectBitValue (ic->rMask, D_IDX))
8443         ret++;
8444       if (bitVectBitValue (ic->rMask, E_IDX))
8445         ret++;
8446       break;
8447     default:
8448       wassert (0);
8449     }
8450   return ret;
8451 }
8452
8453 static char *
8454 fetchLitSpecial (asmop * aop, bool negate, bool xor)
8455 {
8456   unsigned long v;
8457   value *val = aop->aopu.aop_lit;
8458
8459   wassert (aop->type == AOP_LIT);
8460   wassert (!IS_FLOAT (val->type));
8461
8462   v = (unsigned long) floatFromVal (val);
8463
8464   if (xor)
8465     v ^= 0x8000;
8466   if (negate)
8467     v = 0-v;
8468   v &= 0xFFFF;
8469
8470   tsprintf (buffer, sizeof(buffer), "!immedword", v);
8471   return traceAlloc(&_G.trace.aops, Safe_strdup (buffer));
8472 }
8473
8474
8475 */