* src/mcs51/gen.c, src/avr/gen.c, src/pic/gen.c, src/z80/gen.c,
[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   bool inComment = FALSE;
5639
5640   _G.lines.isInline += (!options.asmpeep);
5641
5642   buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
5643
5644   /* emit each line as a code */
5645   while (*bp)
5646     {
5647       switch (*bp)
5648         {
5649         case ';':
5650           inComment = TRUE;
5651           ++bp;
5652           break;
5653
5654         case '\n':
5655           inComment = FALSE;
5656           *bp++ = '\0';
5657           emit2 (bp1);
5658           bp1 = bp;
5659           break;
5660
5661         default:
5662           /* Add \n for labels, not dirs such as c:\mydir */
5663           if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
5664             {
5665               ++bp;
5666               *bp = '\0';
5667               ++bp;
5668               emit2 (bp1);
5669               bp1 = bp;
5670             }
5671           else
5672             ++bp;
5673           break;
5674         }
5675     }
5676   if (bp1 != bp)
5677     emit2 (bp1);
5678
5679   Safe_free (buffer);
5680
5681   _G.lines.isInline -= (!options.asmpeep);
5682
5683 }
5684
5685 /*-----------------------------------------------------------------*/
5686 /* genRRC - rotate right with carry                                */
5687 /*-----------------------------------------------------------------*/
5688 static void
5689 genRRC (iCode * ic)
5690 {
5691   wassert (0);
5692 }
5693
5694 /*-----------------------------------------------------------------*/
5695 /* genRLC - generate code for rotate left with carry               */
5696 /*-----------------------------------------------------------------*/
5697 static void
5698 genRLC (iCode * ic)
5699 {
5700   wassert (0);
5701 }
5702
5703 /*-----------------------------------------------------------------*/
5704 /* genGetHbit - generates code get highest order bit               */
5705 /*-----------------------------------------------------------------*/
5706 static void
5707 genGetHbit (iCode * ic)
5708 {
5709   operand *left, *result;
5710   left = IC_LEFT (ic);
5711   result = IC_RESULT (ic);
5712
5713   aopOp (left, ic, FALSE, FALSE);
5714   aopOp (result, ic, FALSE, FALSE);
5715
5716   /* get the highest order byte into a */
5717   emit2("ld a,%s", aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
5718
5719   if (AOP_TYPE (result) == AOP_CRY)
5720     {
5721       emit2 ("rl a");
5722       outBitC (result);
5723     }
5724   else
5725     {
5726       emit2 ("rlc a");
5727       emit2 ("and a,!one");
5728       outAcc (result);
5729     }
5730
5731
5732   freeAsmop (left, NULL, ic);
5733   freeAsmop (result, NULL, ic);
5734 }
5735
5736 static void
5737 emitRsh2 (asmop *aop, int size, int is_signed)
5738 {
5739   int offset = 0;
5740
5741   while (size--)
5742     {
5743       const char *l = aopGet (aop, size, FALSE);
5744       if (offset == 0)
5745         {
5746           emit2 ("%s %s", is_signed ? "sra" : "srl", l);
5747         }
5748       else
5749         {
5750           emit2 ("rr %s", l);
5751         }
5752       offset++;
5753     }
5754 }
5755
5756 /*-----------------------------------------------------------------*/
5757 /* shiftR2Left2Result - shift right two bytes from left to result  */
5758 /*-----------------------------------------------------------------*/
5759 static void
5760 shiftR2Left2Result (operand * left, int offl,
5761                     operand * result, int offr,
5762                     int shCount, int is_signed)
5763 {
5764   int size = 2;
5765   symbol *tlbl;
5766
5767   movLeft2Result (left, offl, result, offr, 0);
5768   movLeft2Result (left, offl + 1, result, offr + 1, 0);
5769
5770   if (shCount == 0)
5771     return;
5772
5773   /*  if (AOP(result)->type == AOP_REG) { */
5774
5775   tlbl = newiTempLabel (NULL);
5776
5777   /* Left is already in result - so now do the shift */
5778   /* Optimizing for speed by default. */
5779   if (!optimize.codeSize || shCount <= 2)
5780     {
5781       while (shCount--)
5782         {
5783           emitRsh2 (AOP (result), size, is_signed);
5784         }
5785     }
5786   else
5787     {
5788       emit2 ("ld a,!immedbyte", shCount);
5789
5790       emitLabel (tlbl->key + 100);
5791
5792       emitRsh2 (AOP (result), size, is_signed);
5793
5794       emit2 ("dec a");
5795       emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
5796     }
5797 }
5798
5799 /*-----------------------------------------------------------------*/
5800 /* shiftL2Left2Result - shift left two bytes from left to result   */
5801 /*-----------------------------------------------------------------*/
5802 static void
5803 shiftL2Left2Result (operand * left, int offl,
5804                     operand * result, int offr, int shCount)
5805 {
5806   if (sameRegs (AOP (result), AOP (left)) &&
5807       ((offl + MSB16) == offr))
5808     {
5809       wassert (0);
5810     }
5811   else
5812     {
5813       /* Copy left into result */
5814       movLeft2Result (left, offl, result, offr, 0);
5815       movLeft2Result (left, offl + 1, result, offr + 1, 0);
5816     }
5817
5818   if (shCount == 0)
5819     return;
5820
5821   if (getPairId (AOP (result)) == PAIR_HL)
5822     {
5823       while (shCount--)
5824         {
5825           emit2 ("add hl,hl");
5826         }
5827     }
5828   else
5829     {
5830     int size = 2;
5831     int offset = 0;
5832     symbol *tlbl, *tlbl1;
5833     const char *l;
5834
5835     tlbl = newiTempLabel (NULL);
5836     tlbl1 = newiTempLabel (NULL);
5837
5838     if (AOP (result)->type == AOP_REG)
5839       {
5840         while (shCount--)
5841           {
5842             for (offset = 0; offset < size; offset++)
5843               {
5844                 l = aopGet (AOP (result), offset, FALSE);
5845
5846                 if (offset == 0)
5847                   {
5848                     emit2 ("sla %s", l);
5849                   }
5850                 else
5851                   {
5852                     emit2 ("rl %s", l);
5853                   }
5854               }
5855           }
5856       }
5857     else
5858       {
5859         /* Left is already in result - so now do the shift */
5860         if (shCount > 1)
5861           {
5862             emit2 ("ld a,!immedbyte+1", shCount);
5863             emit2 ("!shortjp !tlabel", tlbl1->key + 100);
5864             emitLabel (tlbl->key + 100);
5865           }
5866
5867         while (size--)
5868           {
5869             l = aopGet (AOP (result), offset, FALSE);
5870
5871             if (offset == 0)
5872               {
5873                 emit2 ("sla %s", l);
5874               }
5875             else
5876               {
5877                 emit2 ("rl %s", l);
5878               }
5879
5880             offset++;
5881           }
5882         if (shCount > 1)
5883           {
5884             emitLabel (tlbl1->key + 100);
5885             emit2 ("dec a");
5886             emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
5887           }
5888       }
5889   }
5890 }
5891
5892 /*-----------------------------------------------------------------*/
5893 /* AccRol - rotate left accumulator by known count                 */
5894 /*-----------------------------------------------------------------*/
5895 static void
5896 AccRol (int shCount)
5897 {
5898   shCount &= 0x0007;            // shCount : 0..7
5899
5900 #if 0
5901   switch (shCount)
5902     {
5903     case 0:
5904       break;
5905     case 1:
5906       emit2 ("sla a");
5907       break;
5908     case 2:
5909       emit2 ("sla a");
5910       emit2 ("rl a");
5911       break;
5912     case 3:
5913       emit2 ("sla a");
5914       emit2 ("rl a");
5915       emit2 ("rl a");
5916       break;
5917     case 4:
5918       emit2 ("sla a");
5919       emit2 ("rl a");
5920       emit2 ("rl a");
5921       emit2 ("rl a");
5922       break;
5923     case 5:
5924       emit2 ("srl a");
5925       emit2 ("rr a");
5926       emit2 ("rr a");
5927       break;
5928     case 6:
5929       emit2 ("srl a");
5930       emit2 ("rr a");
5931       break;
5932     case 7:
5933       emit2 ("srl a");
5934       break;
5935     }
5936 #else
5937   switch (shCount)
5938     {
5939     case 0:
5940       break;
5941     case 1:
5942       emit2 ("rlca");
5943       break;
5944     case 2:
5945       emit2 ("rlca");
5946       emit2 ("rlca");
5947       break;
5948     case 3:
5949       emit2 ("rlca");
5950       emit2 ("rlca");
5951       emit2 ("rlca");
5952       break;
5953     case 4:
5954       emit2 ("rlca");
5955       emit2 ("rlca");
5956       emit2 ("rlca");
5957       emit2 ("rlca");
5958       break;
5959     case 5:
5960       emit2 ("rrca");
5961       emit2 ("rrca");
5962       emit2 ("rrca");
5963       break;
5964     case 6:
5965       emit2 ("rrca");
5966       emit2 ("rrca");
5967       break;
5968     case 7:
5969       emit2 ("rrca");
5970       break;
5971     }
5972 #endif
5973 }
5974
5975 /*-----------------------------------------------------------------*/
5976 /* AccLsh - left shift accumulator by known count                  */
5977 /*-----------------------------------------------------------------*/
5978 static void
5979 AccLsh (int shCount)
5980 {
5981   static const unsigned char SLMask[] =
5982     {
5983       0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00
5984     };
5985
5986   if (shCount != 0)
5987     {
5988       if (shCount == 1)
5989         {
5990           emit2 ("add a,a");
5991         }
5992       else if (shCount == 2)
5993         {
5994           emit2 ("add a,a");
5995           emit2 ("add a,a");
5996         }
5997       else
5998         {
5999           /* rotate left accumulator */
6000           AccRol (shCount);
6001           /* and kill the lower order bits */
6002           emit2 ("and a,!immedbyte", SLMask[shCount]);
6003         }
6004     }
6005 }
6006
6007 /*-----------------------------------------------------------------*/
6008 /* shiftL1Left2Result - shift left one byte from left to result    */
6009 /*-----------------------------------------------------------------*/
6010 static void
6011 shiftL1Left2Result (operand * left, int offl,
6012                     operand * result, int offr, int shCount)
6013 {
6014   const char *l;
6015   l = aopGet (AOP (left), offl, FALSE);
6016   _moveA (l);
6017   /* shift left accumulator */
6018   AccLsh (shCount);
6019   aopPut (AOP (result), "a", offr);
6020 }
6021
6022
6023 /*-----------------------------------------------------------------*/
6024 /* genlshTwo - left shift two bytes by known amount                */
6025 /*-----------------------------------------------------------------*/
6026 static void
6027 genlshTwo (operand * result, operand * left, int shCount)
6028 {
6029   int size = AOP_SIZE (result);
6030
6031   wassert (size == 2);
6032
6033   /* if shCount >= 8 */
6034   if (shCount >= 8)
6035     {
6036       shCount -= 8;
6037       if (size > 1)
6038         {
6039           if (shCount)
6040             {
6041               movLeft2Result (left, LSB, result, MSB16, 0);
6042               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6043               aopPut (AOP (result), "!zero", LSB);
6044             }
6045           else
6046             {
6047               movLeft2Result (left, LSB, result, MSB16, 0);
6048               aopPut (AOP (result), "!zero", 0);
6049             }
6050         }
6051       else
6052         {
6053           aopPut (AOP (result), "!zero", LSB);
6054         }
6055     }
6056   /*  0 <= shCount <= 7 */
6057   else
6058     {
6059       if (size == 1)
6060         {
6061           wassert (0);
6062         }
6063       else
6064         {
6065           shiftL2Left2Result (left, LSB, result, LSB, shCount);
6066         }
6067     }
6068 }
6069
6070 /*-----------------------------------------------------------------*/
6071 /* genlshOne - left shift a one byte quantity by known count       */
6072 /*-----------------------------------------------------------------*/
6073 static void
6074 genlshOne (operand * result, operand * left, int shCount)
6075 {
6076   shiftL1Left2Result (left, LSB, result, LSB, shCount);
6077 }
6078
6079 /*-----------------------------------------------------------------*/
6080 /* genLeftShiftLiteral - left shifting by known count              */
6081 /*-----------------------------------------------------------------*/
6082 static void
6083 genLeftShiftLiteral (operand * left,
6084                      operand * right,
6085                      operand * result,
6086                      iCode * ic)
6087 {
6088   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6089   int size;
6090
6091   freeAsmop (right, NULL, ic);
6092
6093   aopOp (left, ic, FALSE, FALSE);
6094   aopOp (result, ic, FALSE, FALSE);
6095
6096   size = getSize (operandType (result));
6097
6098   /* I suppose that the left size >= result size */
6099
6100   if (shCount >= (size * 8))
6101     {
6102       while (size--)
6103         {
6104           aopPut (AOP (result), "!zero", size);
6105         }
6106     }
6107   else
6108     {
6109       switch (size)
6110         {
6111         case 1:
6112           genlshOne (result, left, shCount);
6113           break;
6114         case 2:
6115           genlshTwo (result, left, shCount);
6116           break;
6117         case 4:
6118           wassertl (0, "Shifting of longs is currently unsupported");
6119           break;
6120         default:
6121           wassert (0);
6122         }
6123     }
6124   freeAsmop (left, NULL, ic);
6125   freeAsmop (result, NULL, ic);
6126 }
6127
6128 /*-----------------------------------------------------------------*/
6129 /* genLeftShift - generates code for left shifting                 */
6130 /*-----------------------------------------------------------------*/
6131 static void
6132 genLeftShift (iCode * ic)
6133 {
6134   int size, offset;
6135   const char *l;
6136   symbol *tlbl, *tlbl1;
6137   operand *left, *right, *result;
6138
6139   right = IC_RIGHT (ic);
6140   left = IC_LEFT (ic);
6141   result = IC_RESULT (ic);
6142
6143   aopOp (right, ic, FALSE, FALSE);
6144
6145   /* if the shift count is known then do it
6146      as efficiently as possible */
6147   if (AOP_TYPE (right) == AOP_LIT)
6148     {
6149       genLeftShiftLiteral (left, right, result, ic);
6150       return;
6151     }
6152
6153   /* shift count is unknown then we have to form a loop get the loop
6154      count in B : Note: we take only the lower order byte since
6155      shifting more that 32 bits make no sense anyway, ( the largest
6156      size of an object can be only 32 bits ) */
6157   emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
6158   emit2 ("inc a");
6159   freeAsmop (right, NULL, ic);
6160   aopOp (left, ic, FALSE, FALSE);
6161   aopOp (result, ic, FALSE, FALSE);
6162
6163   if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG)
6164      _push (PAIR_AF);
6165
6166   /* now move the left to the result if they are not the
6167      same */
6168
6169   if (!sameRegs (AOP (left), AOP (result)))
6170     {
6171
6172       size = AOP_SIZE (result);
6173       offset = 0;
6174       while (size--)
6175         {
6176           l = aopGet (AOP (left), offset, FALSE);
6177           aopPut (AOP (result), l, offset);
6178           offset++;
6179         }
6180     }
6181
6182   tlbl = newiTempLabel (NULL);
6183   size = AOP_SIZE (result);
6184   offset = 0;
6185   tlbl1 = newiTempLabel (NULL);
6186
6187   if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG)
6188      _pop (PAIR_AF);
6189
6190   emit2 ("!shortjp !tlabel", tlbl1->key + 100);
6191   emitLabel (tlbl->key + 100);
6192   l = aopGet (AOP (result), offset, FALSE);
6193
6194   while (size--)
6195     {
6196       l = aopGet (AOP (result), offset, FALSE);
6197
6198       if (offset == 0)
6199         {
6200           emit2 ("sla %s", l);
6201         }
6202       else
6203         {
6204           emit2 ("rl %s", l);
6205         }
6206       offset++;
6207     }
6208   emitLabel (tlbl1->key + 100);
6209   emit2 ("dec a");
6210   emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
6211
6212   freeAsmop (left, NULL, ic);
6213   freeAsmop (result, NULL, ic);
6214 }
6215
6216 /*-----------------------------------------------------------------*/
6217 /* genrshOne - left shift two bytes by known amount != 0           */
6218 /*-----------------------------------------------------------------*/
6219 static void
6220 genrshOne (operand * result, operand * left, int shCount, int is_signed)
6221 {
6222   /* Errk */
6223   int size = AOP_SIZE (result);
6224   const char *l;
6225
6226   wassert (size == 1);
6227   wassert (shCount < 8);
6228
6229   l = aopGet (AOP (left), 0, FALSE);
6230
6231   if (AOP (result)->type == AOP_REG)
6232     {
6233       aopPut (AOP (result), l, 0);
6234       l = aopGet (AOP (result), 0, FALSE);
6235       while (shCount--)
6236         {
6237           emit2 ("%s %s", is_signed ? "sra" : "srl", l);
6238         }
6239     }
6240   else
6241     {
6242       _moveA (l);
6243       while (shCount--)
6244         {
6245           emit2 ("%s a", is_signed ? "sra" : "srl");
6246         }
6247       aopPut (AOP (result), "a", 0);
6248     }
6249 }
6250
6251 /*-----------------------------------------------------------------*/
6252 /* AccRsh - right shift accumulator by known count                 */
6253 /*-----------------------------------------------------------------*/
6254 static void
6255 AccRsh (int shCount)
6256 {
6257   static const unsigned char SRMask[] =
6258     {
6259       0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00
6260     };
6261
6262   if (shCount != 0)
6263     {
6264       /* rotate right accumulator */
6265       AccRol (8 - shCount);
6266       /* and kill the higher order bits */
6267       emit2 ("and a,!immedbyte", SRMask[shCount]);
6268     }
6269 }
6270
6271 /*-----------------------------------------------------------------*/
6272 /* shiftR1Left2Result - shift right one byte from left to result   */
6273 /*-----------------------------------------------------------------*/
6274 static void
6275 shiftR1Left2Result (operand * left, int offl,
6276                     operand * result, int offr,
6277                     int shCount, int sign)
6278 {
6279   _moveA (aopGet (AOP (left), offl, FALSE));
6280   if (sign)
6281     {
6282       while (shCount--)
6283         {
6284           emit2 ("%s a", sign ? "sra" : "srl");
6285         }
6286     }
6287   else
6288     {
6289       AccRsh (shCount);
6290     }
6291   aopPut (AOP (result), "a", offr);
6292 }
6293
6294 /*-----------------------------------------------------------------*/
6295 /* genrshTwo - right shift two bytes by known amount               */
6296 /*-----------------------------------------------------------------*/
6297 static void
6298 genrshTwo (operand * result, operand * left,
6299            int shCount, int sign)
6300 {
6301   /* if shCount >= 8 */
6302   if (shCount >= 8)
6303     {
6304       shCount -= 8;
6305       if (shCount)
6306         {
6307           shiftR1Left2Result (left, MSB16, result, LSB,
6308                               shCount, sign);
6309         }
6310       else
6311         {
6312           movLeft2Result (left, MSB16, result, LSB, sign);
6313         }
6314       if (sign)
6315         {
6316           /* Sign extend the result */
6317           _moveA(aopGet (AOP (result), 0, FALSE));
6318           emit2 ("rlc a");
6319           emit2 ("sbc a,a");
6320
6321           aopPut (AOP (result), ACC_NAME, MSB16);
6322         }
6323       else
6324         {
6325           aopPut (AOP (result), "!zero", 1);
6326         }
6327     }
6328   /*  0 <= shCount <= 7 */
6329   else
6330     {
6331       shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6332     }
6333 }
6334
6335 /*-----------------------------------------------------------------*/
6336 /* genRightShiftLiteral - left shifting by known count              */
6337 /*-----------------------------------------------------------------*/
6338 static void
6339 genRightShiftLiteral (operand * left,
6340                       operand * right,
6341                       operand * result,
6342                       iCode * ic,
6343                       int sign)
6344 {
6345   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6346   int size;
6347
6348   freeAsmop (right, NULL, ic);
6349
6350   aopOp (left, ic, FALSE, FALSE);
6351   aopOp (result, ic, FALSE, FALSE);
6352
6353   size = getSize (operandType (result));
6354
6355   /* I suppose that the left size >= result size */
6356
6357   if (shCount >= (size * 8)) {
6358     const char *s;
6359     if (!SPEC_USIGN(getSpec(operandType(left)))) {
6360       _moveA(aopGet (AOP (left), 0, FALSE));
6361       emit2 ("rlc a");
6362       emit2 ("sbc a,a");
6363       s=ACC_NAME;
6364     } else {
6365       s="!zero";
6366     }
6367     while (size--)
6368       aopPut (AOP (result), s, size);
6369   }
6370   else
6371     {
6372       switch (size)
6373         {
6374         case 1:
6375           genrshOne (result, left, shCount, sign);
6376           break;
6377         case 2:
6378           genrshTwo (result, left, shCount, sign);
6379           break;
6380         case 4:
6381           wassertl (0, "Asked to shift right a long which should be a function call");
6382           break;
6383         default:
6384           wassertl (0, "Entered default case in right shift delegate");
6385         }
6386     }
6387   freeAsmop (left, NULL, ic);
6388   freeAsmop (result, NULL, ic);
6389 }
6390
6391 /*-----------------------------------------------------------------*/
6392 /* genRightShift - generate code for right shifting                */
6393 /*-----------------------------------------------------------------*/
6394 static void
6395 genRightShift (iCode * ic)
6396 {
6397   operand *right, *left, *result;
6398   sym_link *retype;
6399   int size, offset, first = 1;
6400   const char *l;
6401   bool is_signed;
6402
6403   symbol *tlbl, *tlbl1;
6404
6405   /* if signed then we do it the hard way preserve the
6406      sign bit moving it inwards */
6407   retype = getSpec (operandType (IC_RESULT (ic)));
6408
6409   is_signed = !SPEC_USIGN (retype);
6410
6411   /* signed & unsigned types are treated the same : i.e. the
6412      signed is NOT propagated inwards : quoting from the
6413      ANSI - standard : "for E1 >> E2, is equivalent to division
6414      by 2**E2 if unsigned or if it has a non-negative value,
6415      otherwise the result is implementation defined ", MY definition
6416      is that the sign does not get propagated */
6417
6418   right = IC_RIGHT (ic);
6419   left = IC_LEFT (ic);
6420   result = IC_RESULT (ic);
6421
6422   aopOp (right, ic, FALSE, FALSE);
6423
6424   /* if the shift count is known then do it
6425      as efficiently as possible */
6426   if (AOP_TYPE (right) == AOP_LIT)
6427     {
6428       genRightShiftLiteral (left, right, result, ic, is_signed);
6429       return;
6430     }
6431
6432   emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
6433   emit2 ("inc a");
6434   freeAsmop (right, NULL, ic);
6435
6436   aopOp (left, ic, FALSE, FALSE);
6437   aopOp (result, ic, FALSE, FALSE);
6438
6439   if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG)
6440      _push (PAIR_AF);
6441
6442   /* now move the left to the result if they are not the
6443      same */
6444   if (!sameRegs (AOP (left), AOP (result)))
6445     {
6446
6447       size = AOP_SIZE (result);
6448       offset = 0;
6449       while (size--)
6450         {
6451           l = aopGet (AOP (left), offset, FALSE);
6452           aopPut (AOP (result), l, offset);
6453           offset++;
6454         }
6455     }
6456
6457   tlbl = newiTempLabel (NULL);
6458   tlbl1 = newiTempLabel (NULL);
6459   size = AOP_SIZE (result);
6460   offset = size - 1;
6461
6462   if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG)
6463      _pop (PAIR_AF);
6464
6465   emit2 ("!shortjp !tlabel", tlbl1->key + 100);
6466   emitLabel (tlbl->key + 100);
6467   while (size--)
6468     {
6469       l = aopGet (AOP (result), offset--, FALSE);
6470       if (first)
6471         {
6472           emit2 ("%s %s", is_signed ? "sra" : "srl", l);
6473           first = 0;
6474         }
6475       else
6476         {
6477           emit2 ("rr %s", l);
6478         }
6479     }
6480   emitLabel (tlbl1->key + 100);
6481   emit2 ("dec a");
6482   emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
6483
6484   freeAsmop (left, NULL, ic);
6485   freeAsmop (result, NULL, ic);
6486 }
6487
6488
6489 /*-----------------------------------------------------------------*/
6490 /* genUnpackBits - generates code for unpacking bits               */
6491 /*-----------------------------------------------------------------*/
6492 static void
6493 genUnpackBits (operand * result, int pair)
6494 {
6495   int offset = 0;       /* result byte offset */
6496   int rsize;            /* result size */
6497   int rlen = 0;         /* remaining bitfield length */
6498   sym_link *etype;      /* bitfield type information */
6499   int blen;             /* bitfield length */
6500   int bstr;             /* bitfield starting bit within byte */
6501
6502   emitDebug ("; genUnpackBits");
6503
6504   etype = getSpec (operandType (result));
6505   rsize = getSize (operandType (result));
6506   blen = SPEC_BLEN (etype);
6507   bstr = SPEC_BSTR (etype);
6508
6509   /* If the bitfield length is less than a byte */
6510   if (blen < 8)
6511     {
6512       emit2 ("ld a,!*pair", _pairs[pair].name);
6513       AccRol (8 - bstr);
6514       emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (8 - blen));
6515       if (!SPEC_USIGN (etype))
6516         {
6517           /* signed bitfield */
6518           symbol *tlbl = newiTempLabel (NULL);
6519
6520           emit2 ("bit %d,a", blen - 1);
6521           emit2 ("jp Z,!tlabel", tlbl->key + 100);
6522           emit2 ("or a,!immedbyte", (unsigned char) (0xff << blen));
6523           emitLabel (tlbl->key + 100);
6524         }
6525       aopPut (AOP (result), "a", offset++);
6526       goto finish;
6527     }
6528
6529   /* TODO: what if pair == PAIR_DE ? */
6530   if (getPairId (AOP (result)) == PAIR_HL)
6531     {
6532       wassertl (rsize == 2, "HL must be of size 2");
6533       emit2 ("ld a,!*hl");
6534       emit2 ("inc hl");
6535       emit2 ("ld h,!*hl");
6536       emit2 ("ld l,a");
6537       emit2 ("ld a,h");
6538       emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (16 - blen));
6539       if (!SPEC_USIGN (etype))
6540         {
6541           /* signed bitfield */
6542           symbol *tlbl = newiTempLabel (NULL);
6543
6544           emit2 ("bit %d,a", blen - 1);
6545           emit2 ("jp Z,!tlabel", tlbl->key + 100);
6546           emit2 ("or a,!immedbyte", (unsigned char) (0xff << blen));
6547           emitLabel (tlbl->key + 100);
6548         }
6549       emit2 ("ld h,a");
6550       spillPair (PAIR_HL);
6551       return;
6552     }
6553
6554   /* Bit field did not fit in a byte. Copy all
6555      but the partial byte at the end.  */
6556   for (rlen=blen;rlen>=8;rlen-=8)
6557     {
6558       emit2 ("ld a,!*pair", _pairs[pair].name);
6559       aopPut (AOP (result), "a", offset++);
6560       if (rlen>8)
6561         {
6562           emit2 ("inc %s", _pairs[pair].name);
6563           _G.pairs[pair].offset++;
6564         }
6565     }
6566
6567   /* Handle the partial byte at the end */
6568   if (rlen)
6569     {
6570       emit2 ("ld a,!*pair", _pairs[pair].name);
6571       emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (8 - rlen));
6572       if (!SPEC_USIGN (etype))
6573         {
6574           /* signed bitfield */
6575           symbol *tlbl = newiTempLabel (NULL);
6576
6577           emit2 ("bit %d,a", rlen - 1);
6578           emit2 ("jp Z,!tlabel", tlbl->key + 100);
6579           emit2 ("or a,!immedbyte", (unsigned char) (0xff << rlen));
6580           emitLabel (tlbl->key + 100);
6581         }
6582       aopPut (AOP (result), "a", offset++);
6583     }
6584
6585 finish:
6586   if (offset < rsize)
6587     {
6588       char *source;
6589
6590       if (SPEC_USIGN (etype))
6591         source = "!zero";
6592       else
6593         {
6594           /* signed bitfield: sign extension with 0x00 or 0xff */
6595           emit2 ("rla");
6596           emit2 ("sbc a,a");
6597
6598           source = "a";
6599         }
6600       rsize -= offset;
6601       while (rsize--)
6602         aopPut (AOP (result), source, offset++);
6603     }
6604 }
6605
6606 /*-----------------------------------------------------------------*/
6607 /* genGenPointerGet -  get value from generic pointer space        */
6608 /*-----------------------------------------------------------------*/
6609 static void
6610 genGenPointerGet (operand * left,
6611                   operand * result, iCode * ic)
6612 {
6613   int size, offset;
6614   sym_link *retype = getSpec (operandType (result));
6615   int pair = PAIR_HL;
6616
6617   if (IS_GB)
6618     pair = PAIR_DE;
6619
6620   aopOp (left, ic, FALSE, FALSE);
6621   aopOp (result, ic, FALSE, FALSE);
6622
6623   size = AOP_SIZE (result);
6624
6625   if (isPair (AOP (left)) && size == 1 && !IS_BITVAR (retype))
6626     {
6627       /* Just do it */
6628       if (isPtrPair (AOP (left)))
6629         {
6630           tsprintf (buffer, sizeof(buffer),
6631                     "!*pair", getPairName (AOP (left)));
6632           aopPut (AOP (result), buffer, 0);
6633         }
6634       else
6635         {
6636           emit2 ("ld a,!*pair", getPairName (AOP (left)));
6637           aopPut (AOP (result), "a", 0);
6638         }
6639       freeAsmop (left, NULL, ic);
6640       goto release;
6641     }
6642
6643   if (getPairId (AOP (left)) == PAIR_IY && !IS_BITVAR (retype))
6644     {
6645       /* Just do it */
6646       offset = 0;
6647       while (size--)
6648         {
6649           char at[20];
6650           tsprintf (at, sizeof(at), "!*iyx", offset);
6651           aopPut (AOP (result), at, offset);
6652           offset++;
6653         }
6654
6655       freeAsmop (left, NULL, ic);
6656       goto release;
6657     }
6658
6659   /* For now we always load into IY */
6660   /* if this is remateriazable */
6661   fetchPair (pair, AOP (left));
6662
6663   /* if bit then unpack */
6664   if (IS_BITVAR (retype))
6665     {
6666       genUnpackBits (result, pair);
6667       freeAsmop (left, NULL, ic);
6668       goto release;
6669       //wassert (0);
6670     }
6671   else if (getPairId (AOP (result)) == PAIR_HL)
6672     {
6673       wassertl (size == 2, "HL must be of size 2");
6674       emit2 ("ld a,!*hl");
6675       emit2 ("inc hl");
6676       emit2 ("ld h,!*hl");
6677       emit2 ("ld l,a");
6678       spillPair (PAIR_HL);
6679     }
6680   else if (getPairId (AOP (left)) == PAIR_HL && !isLastUse (ic, left))
6681     {
6682       size = AOP_SIZE (result);
6683       offset = 0;
6684
6685       while (size--)
6686         {
6687           /* PENDING: make this better */
6688           if (!IS_GB && AOP_TYPE (result) == AOP_REG)
6689             {
6690               aopPut (AOP (result), "!*hl", offset++);
6691             }
6692           else
6693             {
6694               emit2 ("ld a,!*pair", _pairs[pair].name);
6695               aopPut (AOP (result), "a", offset++);
6696             }
6697           if (size)
6698             {
6699               emit2 ("inc %s", _pairs[pair].name);
6700               _G.pairs[pair].offset++;
6701             }
6702         }
6703       /* Fixup HL back down */
6704       for (size = AOP_SIZE (result)-1; size; size--)
6705         {
6706           emit2 ("dec %s", _pairs[pair].name);
6707         }
6708     }
6709   else
6710     {
6711       size = AOP_SIZE (result);
6712       offset = 0;
6713
6714       while (size--)
6715         {
6716           /* PENDING: make this better */
6717           if (!IS_GB &&
6718               (AOP_TYPE (result) == AOP_REG || AOP_TYPE (result) == AOP_HLREG))
6719             {
6720               aopPut (AOP (result), "!*hl", offset++);
6721             }
6722           else
6723             {
6724               emit2 ("ld a,!*pair", _pairs[pair].name);
6725               aopPut (AOP (result), "a", offset++);
6726             }
6727           if (size)
6728             {
6729               emit2 ("inc %s", _pairs[pair].name);
6730               _G.pairs[pair].offset++;
6731             }
6732         }
6733     }
6734
6735   freeAsmop (left, NULL, ic);
6736
6737 release:
6738   freeAsmop (result, NULL, ic);
6739 }
6740
6741 /*-----------------------------------------------------------------*/
6742 /* genPointerGet - generate code for pointer get                   */
6743 /*-----------------------------------------------------------------*/
6744 static void
6745 genPointerGet (iCode * ic)
6746 {
6747   operand *left, *result;
6748   sym_link *type, *etype;
6749
6750   left = IC_LEFT (ic);
6751   result = IC_RESULT (ic);
6752
6753   /* depending on the type of pointer we need to
6754      move it to the correct pointer register */
6755   type = operandType (left);
6756   etype = getSpec (type);
6757
6758   genGenPointerGet (left, result, ic);
6759 }
6760
6761 bool
6762 isRegOrLit (asmop * aop)
6763 {
6764   if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD || aop->type == AOP_HLREG)
6765     return TRUE;
6766   return FALSE;
6767 }
6768
6769
6770 /*-----------------------------------------------------------------*/
6771 /* genPackBits - generates code for packed bit storage             */
6772 /*-----------------------------------------------------------------*/
6773 static void
6774 genPackBits (sym_link * etype,
6775              operand * right,
6776              int pair,
6777              iCode *ic)
6778 {
6779   int offset = 0;       /* source byte offset */
6780   int rlen = 0;         /* remaining bitfield length */
6781   int blen;             /* bitfield length */
6782   int bstr;             /* bitfield starting bit within byte */
6783   int litval;           /* source literal value (if AOP_LIT) */
6784   unsigned char mask;   /* bitmask within current byte */
6785   int extraPair;        /* a tempory register */
6786   bool needPopExtra=0;  /* need to restore original value of temp reg */
6787
6788   emitDebug (";     genPackBits","");
6789
6790   blen = SPEC_BLEN (etype);
6791   bstr = SPEC_BSTR (etype);
6792
6793   /* If the bitfield length is less than a byte */
6794   if (blen < 8)
6795     {
6796       mask = ((unsigned char) (0xFF << (blen + bstr)) |
6797               (unsigned char) (0xFF >> (8 - bstr)));
6798
6799       if (AOP_TYPE (right) == AOP_LIT)
6800         {
6801           /* Case with a bitfield length <8 and literal source
6802           */
6803           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6804           litval <<= bstr;
6805           litval &= (~mask) & 0xff;
6806           emit2 ("ld a,!*pair", _pairs[pair].name);
6807           if ((mask|litval)!=0xff)
6808             emit2 ("and a,!immedbyte", mask);
6809           if (litval)
6810             emit2 ("or a,!immedbyte", litval);
6811           emit2 ("ld !*pair,a", _pairs[pair].name);
6812           return;
6813         }
6814       else
6815         {
6816           /* Case with a bitfield length <8 and arbitrary source
6817           */
6818           _moveA (aopGet (AOP (right), 0, FALSE));
6819           /* shift and mask source value */
6820           AccLsh (bstr);
6821           emit2 ("and a,!immedbyte", (~mask) & 0xff);
6822
6823           extraPair = getFreePairId(ic);
6824           if (extraPair == PAIR_INVALID)
6825             {
6826               extraPair = PAIR_BC;
6827               if (getPairId (AOP (right)) != PAIR_BC
6828                   || !isLastUse (ic, right))
6829                 {
6830                   _push (extraPair);
6831                   needPopExtra = 1;
6832                 }
6833             }
6834           emit2 ("ld %s,a", _pairs[extraPair].l);
6835           emit2 ("ld a,!*pair", _pairs[pair].name);
6836
6837           emit2 ("and a,!immedbyte", mask);
6838           emit2 ("or a,%s", _pairs[extraPair].l);
6839           emit2 ("ld !*pair,a", _pairs[pair].name);
6840           if (needPopExtra)
6841             _pop (extraPair);
6842           return;
6843         }
6844     }
6845
6846   /* Bit length is greater than 7 bits. In this case, copy  */
6847   /* all except the partial byte at the end                 */
6848   for (rlen=blen;rlen>=8;rlen-=8)
6849     {
6850       emit2 ("ld a,%s", aopGet (AOP (right), offset++, FALSE) );
6851       emit2 ("ld !*pair,a", _pairs[pair].name);
6852       if (rlen>8)
6853         {
6854           emit2 ("inc %s", _pairs[pair].name);
6855           _G.pairs[pair].offset++;
6856         }
6857     }
6858
6859   /* If there was a partial byte at the end */
6860   if (rlen)
6861     {
6862       mask = (((unsigned char) -1 << rlen) & 0xff);
6863
6864       if (AOP_TYPE (right) == AOP_LIT)
6865         {
6866           /* Case with partial byte and literal source
6867           */
6868           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6869           litval >>= (blen-rlen);
6870           litval &= (~mask) & 0xff;
6871           emit2 ("ld a,!*pair", _pairs[pair].name);
6872           if ((mask|litval)!=0xff)
6873             emit2 ("and a,!immedbyte", mask);
6874           if (litval)
6875             emit2 ("or a,!immedbyte", litval);
6876         }
6877       else
6878         {
6879           /* Case with partial byte and arbitrary source
6880           */
6881           _moveA (aopGet (AOP (right), offset++, FALSE));
6882           emit2 ("and a,!immedbyte", (~mask) & 0xff);
6883
6884           extraPair = getFreePairId(ic);
6885           if (extraPair == PAIR_INVALID)
6886             {
6887               extraPair = getPairId (AOP (right));
6888               if (!isLastUse (ic, right) || (extraPair == PAIR_INVALID))
6889                 extraPair = PAIR_BC;
6890
6891               if (getPairId (AOP (right)) != PAIR_BC
6892                   || !isLastUse (ic, right))
6893                 {
6894                   _push (extraPair);
6895                   needPopExtra = 1;
6896                 }
6897             }
6898           emit2 ("ld %s,a", _pairs[extraPair].l);
6899           emit2 ("ld a,!*pair", _pairs[pair].name);
6900
6901           emit2 ("and a,!immedbyte", mask);
6902           emit2 ("or a,%s", _pairs[extraPair].l);
6903           if (needPopExtra)
6904             _pop (extraPair);
6905
6906         }
6907       emit2 ("ld !*pair,a", _pairs[pair].name);
6908     }
6909 }
6910
6911
6912 /*-----------------------------------------------------------------*/
6913 /* genGenPointerSet - stores the value into a pointer location        */
6914 /*-----------------------------------------------------------------*/
6915 static void
6916 genGenPointerSet (operand * right,
6917                   operand * result, iCode * ic)
6918 {
6919   int size, offset;
6920   sym_link *retype = getSpec (operandType (right));
6921   sym_link *letype = getSpec (operandType (result));
6922   PAIR_ID pairId = PAIR_HL;
6923   bool isBitvar;
6924
6925   aopOp (result, ic, FALSE, FALSE);
6926   aopOp (right, ic, FALSE, FALSE);
6927
6928   if (IS_GB)
6929     pairId = PAIR_DE;
6930
6931   size = AOP_SIZE (right);
6932
6933   isBitvar = IS_BITVAR(retype) || IS_BITVAR(letype);
6934   emitDebug("; isBitvar = %d", isBitvar);
6935
6936   /* Handle the exceptions first */
6937   if (isPair (AOP (result)) && size == 1 && !isBitvar)
6938     {
6939       /* Just do it */
6940       const char *l = aopGet (AOP (right), 0, FALSE);
6941       const char *pair = getPairName (AOP (result));
6942       if (canAssignToPtr (l) && isPtr (pair))
6943         {
6944           emit2 ("ld !*pair,%s", pair, l);
6945         }
6946       else
6947         {
6948           _moveA (l);
6949           emit2 ("ld !*pair,a", pair);
6950         }
6951       goto release;
6952     }
6953
6954   if ( getPairId( AOP (result)) == PAIR_IY && !isBitvar)
6955     {
6956       /* Just do it */
6957       const char *l = aopGet (AOP (right), 0, FALSE);
6958
6959       offset = 0;
6960       while (size--)
6961         {
6962           if (canAssignToPtr (l))
6963             {
6964               emit2 ("ld !*iyx,%s", offset, aopGet( AOP(right), offset, FALSE));
6965             }
6966           else
6967             {
6968               _moveA (aopGet (AOP (right), offset, FALSE));
6969               emit2 ("ld !*iyx,a", offset);
6970             }
6971           offset++;
6972         }
6973       goto release;
6974     }
6975   else if (getPairId (AOP (result)) == PAIR_HL && !isLastUse (ic, result)
6976            && !isBitvar)
6977     {
6978       offset = 0;
6979
6980       while (size--)
6981         {
6982           const char *l = aopGet (AOP (right), offset, FALSE);
6983           if (isRegOrLit (AOP (right)) && !IS_GB)
6984             {
6985               emit2 ("ld !*pair,%s", _pairs[PAIR_HL].name, l);
6986             }
6987           else
6988             {
6989               _moveA (l);
6990               emit2 ("ld !*pair,a", _pairs[PAIR_HL].name);
6991             }
6992           if (size)
6993             {
6994               emit2 ("inc %s", _pairs[PAIR_HL].name);
6995               _G.pairs[PAIR_HL].offset++;
6996             }
6997           offset++;
6998         }
6999
7000       /* Fixup HL back down */
7001       for (size = AOP_SIZE (right)-1; size; size--)
7002         {
7003           emit2 ("dec %s", _pairs[PAIR_HL].name);
7004         }
7005       goto release;
7006     }
7007
7008   /* if the operand is already in dptr
7009      then we do nothing else we move the value to dptr */
7010   if (AOP_TYPE (result) != AOP_STR)
7011     {
7012       fetchPair (pairId, AOP (result));
7013     }
7014   /* so hl now contains the address */
7015   freeAsmop (result, NULL, ic);
7016
7017   /* if bit then unpack */
7018   if (isBitvar)
7019     {
7020       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, pairId, ic);
7021       goto release;
7022       //wassert (0);
7023     }
7024   else
7025     {
7026       offset = 0;
7027
7028       while (size--)
7029         {
7030           const char *l = aopGet (AOP (right), offset, FALSE);
7031           if (isRegOrLit (AOP (right)) && !IS_GB)
7032             {
7033               emit2 ("ld !*pair,%s", _pairs[pairId].name, l);
7034             }
7035           else
7036             {
7037               _moveA (l);
7038               emit2 ("ld !*pair,a", _pairs[pairId].name);
7039             }
7040           if (size)
7041             {
7042               emit2 ("inc %s", _pairs[pairId].name);
7043               _G.pairs[pairId].offset++;
7044             }
7045           offset++;
7046         }
7047     }
7048 release:
7049   freeAsmop (right, NULL, ic);
7050 }
7051
7052 /*-----------------------------------------------------------------*/
7053 /* genPointerSet - stores the value into a pointer location        */
7054 /*-----------------------------------------------------------------*/
7055 static void
7056 genPointerSet (iCode * ic)
7057 {
7058   operand *right, *result;
7059   sym_link *type, *etype;
7060
7061   right = IC_RIGHT (ic);
7062   result = IC_RESULT (ic);
7063
7064   /* depending on the type of pointer we need to
7065      move it to the correct pointer register */
7066   type = operandType (result);
7067   etype = getSpec (type);
7068
7069   genGenPointerSet (right, result, ic);
7070 }
7071
7072 /*-----------------------------------------------------------------*/
7073 /* genIfx - generate code for Ifx statement                        */
7074 /*-----------------------------------------------------------------*/
7075 static void
7076 genIfx (iCode * ic, iCode * popIc)
7077 {
7078   operand *cond = IC_COND (ic);
7079   int isbit = 0;
7080
7081   aopOp (cond, ic, FALSE, TRUE);
7082
7083   /* get the value into acc */
7084   if (AOP_TYPE (cond) != AOP_CRY)
7085     _toBoolean (cond);
7086   else
7087     isbit = 1;
7088   /* the result is now in the accumulator */
7089   freeAsmop (cond, NULL, ic);
7090
7091   /* if there was something to be popped then do it */
7092   if (popIc)
7093     genIpop (popIc);
7094
7095   /* if the condition is  a bit variable */
7096   if (isbit && IS_ITEMP (cond) &&
7097       SPIL_LOC (cond))
7098     genIfxJump (ic, SPIL_LOC (cond)->rname);
7099   else if (isbit && !IS_ITEMP (cond))
7100     genIfxJump (ic, OP_SYMBOL (cond)->rname);
7101   else
7102     genIfxJump (ic, "a");
7103
7104   ic->generated = 1;
7105 }
7106
7107 /*-----------------------------------------------------------------*/
7108 /* genAddrOf - generates code for address of                       */
7109 /*-----------------------------------------------------------------*/
7110 static void
7111 genAddrOf (iCode * ic)
7112 {
7113   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7114
7115   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
7116
7117   /* if the operand is on the stack then we
7118      need to get the stack offset of this
7119      variable */
7120   if (IS_GB)
7121     {
7122       if (sym->onStack)
7123         {
7124           spillCached ();
7125           if (sym->stack <= 0)
7126             {
7127               setupPairFromSP (PAIR_HL, sym->stack + _G.stack.pushed + _G.stack.offset);
7128             }
7129           else
7130             {
7131               setupPairFromSP (PAIR_HL, sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
7132             }
7133           commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
7134         }
7135       else
7136         {
7137           emit2 ("ld de,!hashedstr", sym->rname);
7138           commitPair (AOP (IC_RESULT (ic)), PAIR_DE);
7139         }
7140     }
7141   else
7142     {
7143       spillCached ();
7144       if (sym->onStack)
7145         {
7146           /* if it has an offset  then we need to compute it */
7147           if (sym->stack > 0)
7148             emit2 ("ld hl,!immedword", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
7149           else
7150             emit2 ("ld hl,!immedword", sym->stack + _G.stack.pushed + _G.stack.offset);
7151           emit2 ("add hl,sp");
7152         }
7153       else
7154         {
7155           emit2 ("ld hl,!hashedstr", sym->rname);
7156         }
7157       commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
7158     }
7159   freeAsmop (IC_RESULT (ic), NULL, ic);
7160 }
7161
7162 /*-----------------------------------------------------------------*/
7163 /* genAssign - generate code for assignment                        */
7164 /*-----------------------------------------------------------------*/
7165 static void
7166 genAssign (iCode * ic)
7167 {
7168   operand *result, *right;
7169   int size, offset;
7170   unsigned long lit = 0L;
7171
7172   result = IC_RESULT (ic);
7173   right = IC_RIGHT (ic);
7174
7175   /* Dont bother assigning if they are the same */
7176   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7177     {
7178       emitDebug ("; (operands are equal %u)", operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)));
7179       return;
7180     }
7181
7182   aopOp (right, ic, FALSE, FALSE);
7183   aopOp (result, ic, TRUE, FALSE);
7184
7185   /* if they are the same registers */
7186   if (sameRegs (AOP (right), AOP (result)))
7187     {
7188       emitDebug ("; (registers are the same)");
7189       goto release;
7190     }
7191
7192   /* if the result is a bit */
7193   if (AOP_TYPE (result) == AOP_CRY)
7194     {
7195       wassertl (0, "Tried to assign to a bit");
7196     }
7197
7198   /* general case */
7199   size = AOP_SIZE (result);
7200   offset = 0;
7201
7202   if (AOP_TYPE (right) == AOP_LIT)
7203     {
7204       lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7205     }
7206
7207   if (isPair (AOP (result)))
7208     {
7209       fetchPairLong (getPairId (AOP (result)), AOP (right), ic, LSB);
7210     }
7211   else if ((size > 1) &&
7212            (AOP_TYPE (result) != AOP_REG) &&
7213            (AOP_TYPE (right) == AOP_LIT) &&
7214            !IS_FLOAT (operandType (right)) &&
7215            (lit < 256L))
7216     {
7217       bool fXored = FALSE;
7218       offset = 0;
7219       /* Work from the top down.
7220          Done this way so that we can use the cached copy of 0
7221          in A for a fast clear */
7222       while (size--)
7223         {
7224           if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)
7225             {
7226               if (!fXored && size > 1)
7227                 {
7228                   emit2 ("xor a,a");
7229                   fXored = TRUE;
7230                 }
7231               if (fXored)
7232                 {
7233                   aopPut (AOP (result), "a", offset);
7234                 }
7235               else
7236                 {
7237                   aopPut (AOP (result), "!zero", offset);
7238                 }
7239             }
7240           else
7241             aopPut (AOP (result),
7242                     aopGet (AOP (right), offset, FALSE),
7243                     offset);
7244           offset++;
7245         }
7246     }
7247   else if (size == 2 && AOP_TYPE (right) == AOP_IY)
7248     {
7249       emit2 ("ld hl,(%s)", AOP (right)->aopu.aop_dir);
7250       aopPut (AOP (result), "l", LSB);
7251       aopPut (AOP (result), "h", MSB16);
7252     }
7253   else if (size == 2 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
7254     {
7255       /* Special case.  Load into a and d, then load out. */
7256       _moveA (aopGet (AOP (right), 0, FALSE));
7257       emit2 ("ld e,%s", aopGet (AOP (right), 1, FALSE));
7258       aopPut (AOP (result), "a", 0);
7259       aopPut (AOP (result), "e", 1);
7260     }
7261   else if (size == 4 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
7262     {
7263       /* Special case - simple memcpy */
7264       aopGet (AOP (right), LSB, FALSE);
7265       emit2 ("ld d,h");
7266       emit2 ("ld e,l");
7267       aopGet (AOP (result), LSB, FALSE);
7268
7269       while (size--)
7270         {
7271           emit2 ("ld a,(de)");
7272           /* Peephole will optimise this. */
7273           emit2 ("ld (hl),a");
7274
7275           if (size != 0)
7276             {
7277               emit2 ("inc hl");
7278               emit2 ("inc de");
7279             }
7280         }
7281       spillPair (PAIR_HL);
7282     }
7283   else
7284     {
7285       while (size--)
7286         {
7287           /* PENDING: do this check better */
7288           if (IS_GB && requiresHL (AOP (right)) && requiresHL (AOP (result)))
7289             {
7290               _moveA (aopGet (AOP (right), offset, FALSE));
7291               aopPut (AOP (result), "a", offset);
7292             }
7293           else
7294             aopPut (AOP (result),
7295                     aopGet (AOP (right), offset, FALSE),
7296                     offset);
7297           offset++;
7298         }
7299     }
7300
7301 release:
7302   freeAsmop (right, NULL, ic);
7303   freeAsmop (result, NULL, ic);
7304 }
7305
7306 /*-----------------------------------------------------------------*/
7307 /* genJumpTab - genrates code for jump table                       */
7308 /*-----------------------------------------------------------------*/
7309 static void
7310 genJumpTab (iCode * ic)
7311 {
7312   symbol *jtab;
7313   const char *l;
7314
7315   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
7316   /* get the condition into accumulator */
7317   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE);
7318   if (!IS_GB)
7319     emit2 ("push de");
7320   emit2 ("ld e,%s", l);
7321   emit2 ("ld d,!zero");
7322   jtab = newiTempLabel (NULL);
7323   spillCached ();
7324   emit2 ("ld hl,!immed!tlabel", jtab->key + 100);
7325   emit2 ("add hl,de");
7326   emit2 ("add hl,de");
7327   emit2 ("add hl,de");
7328   freeAsmop (IC_JTCOND (ic), NULL, ic);
7329   if (!IS_GB)
7330     emit2 ("pop de");
7331   emit2 ("jp !*hl");
7332   emitLabel (jtab->key + 100);
7333   /* now generate the jump labels */
7334   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7335        jtab = setNextItem (IC_JTLABELS (ic)))
7336     emit2 ("jp !tlabel", jtab->key + 100);
7337 }
7338
7339 /*-----------------------------------------------------------------*/
7340 /* genCast - gen code for casting                                  */
7341 /*-----------------------------------------------------------------*/
7342 static void
7343 genCast (iCode * ic)
7344 {
7345   operand *result = IC_RESULT (ic);
7346   sym_link *rtype = operandType (IC_RIGHT (ic));
7347   operand *right = IC_RIGHT (ic);
7348   int size, offset;
7349
7350   /* if they are equivalent then do nothing */
7351   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7352     return;
7353
7354   aopOp (right, ic, FALSE, FALSE);
7355   aopOp (result, ic, FALSE, FALSE);
7356
7357   /* if the result is a bit */
7358   if (AOP_TYPE (result) == AOP_CRY)
7359     {
7360       wassertl (0, "Tried to cast to a bit");
7361     }
7362
7363   /* if they are the same size : or less */
7364   if (AOP_SIZE (result) <= AOP_SIZE (right))
7365     {
7366
7367       /* if they are in the same place */
7368       if (sameRegs (AOP (right), AOP (result)))
7369         goto release;
7370
7371       /* if they in different places then copy */
7372       size = AOP_SIZE (result);
7373       offset = 0;
7374       while (size--)
7375         {
7376           aopPut (AOP (result),
7377                   aopGet (AOP (right), offset, FALSE),
7378                   offset);
7379           offset++;
7380         }
7381       goto release;
7382     }
7383
7384   /* So we now know that the size of destination is greater
7385      than the size of the source */
7386   /* we move to result for the size of source */
7387   size = AOP_SIZE (right);
7388   offset = 0;
7389   while (size--)
7390     {
7391       aopPut (AOP (result),
7392               aopGet (AOP (right), offset, FALSE),
7393               offset);
7394       offset++;
7395     }
7396
7397   /* now depending on the sign of the destination */
7398   size = AOP_SIZE (result) - AOP_SIZE (right);
7399   /* Unsigned or not an integral type - right fill with zeros */
7400   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7401     {
7402       while (size--)
7403         aopPut (AOP (result), "!zero", offset++);
7404     }
7405   else
7406     {
7407       /* we need to extend the sign :{ */
7408         const char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
7409                         FALSE);
7410       _moveA (l);
7411       emit2 ("rla ");
7412       emit2 ("sbc a,a");
7413       while (size--)
7414         aopPut (AOP (result), "a", offset++);
7415     }
7416
7417 release:
7418   freeAsmop (right, NULL, ic);
7419   freeAsmop (result, NULL, ic);
7420 }
7421
7422 /*-----------------------------------------------------------------*/
7423 /* genReceive - generate code for a receive iCode                  */
7424 /*-----------------------------------------------------------------*/
7425 static void
7426 genReceive (iCode * ic)
7427 {
7428   if (isOperandInFarSpace (IC_RESULT (ic)) &&
7429       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
7430        IS_TRUE_SYMOP (IC_RESULT (ic))))
7431     {
7432       wassert (0);
7433     }
7434   else
7435     {
7436         // PENDING: HACK
7437         int size;
7438         int i;
7439
7440         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
7441         size = AOP_SIZE(IC_RESULT(ic));
7442
7443         for (i = 0; i < size; i++) {
7444             aopPut(AOP(IC_RESULT(ic)), _fReceive[_G.receiveOffset++], i);
7445         }
7446     }
7447
7448   freeAsmop (IC_RESULT (ic), NULL, ic);
7449 }
7450
7451 /*-----------------------------------------------------------------*/
7452 /* genDummyRead - generate code for dummy read of volatiles        */
7453 /*-----------------------------------------------------------------*/
7454 static void
7455 genDummyRead (iCode * ic)
7456 {
7457   operand *op;
7458   int size, offset;
7459
7460   op = IC_RIGHT (ic);
7461   if (op && IS_SYMOP (op))
7462     {
7463       aopOp (op, ic, FALSE, FALSE);
7464
7465       /* general case */
7466       size = AOP_SIZE (op);
7467       offset = 0;
7468
7469       while (size--)
7470         {
7471           _moveA (aopGet (AOP (op), offset, FALSE));
7472           offset++;
7473         }
7474
7475       freeAsmop (op, NULL, ic);
7476     }
7477
7478   op = IC_LEFT (ic);
7479   if (op && IS_SYMOP (op))
7480     {
7481       aopOp (op, ic, FALSE, FALSE);
7482
7483       /* general case */
7484       size = AOP_SIZE (op);
7485       offset = 0;
7486
7487       while (size--)
7488         {
7489           _moveA (aopGet (AOP (op), offset, FALSE));
7490           offset++;
7491         }
7492
7493       freeAsmop (op, NULL, ic);
7494     }
7495 }
7496
7497 /*-----------------------------------------------------------------*/
7498 /* genCritical - generate code for start of a critical sequence    */
7499 /*-----------------------------------------------------------------*/
7500 static void
7501 genCritical (iCode *ic)
7502 {
7503   symbol *tlbl = newiTempLabel (NULL);
7504
7505   if (IS_GB)
7506     {
7507       emit2 ("!di");
7508     }
7509   else if (IC_RESULT (ic))
7510     {
7511       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
7512       aopPut (AOP (IC_RESULT (ic)), "!zero", 0);
7513       //get interrupt enable flag IFF2 into P/O
7514       emit2 ("ld a,i");
7515       //disable interrupt
7516       emit2 ("!di");
7517       //parity odd <==> P/O=0 <==> interrupt enable flag IFF2=0
7518       emit2 ("jp PO,!tlabel", tlbl->key + 100);
7519       aopPut (AOP (IC_RESULT (ic)), "!one", 0);
7520       emit2 ("!tlabeldef", (tlbl->key + 100));
7521       _G.lines.current->isLabel = 1;
7522       freeAsmop (IC_RESULT (ic), NULL, ic);
7523     }
7524   else
7525     {
7526       //get interrupt enable flag IFF2 into P/O
7527       emit2 ("ld a,i");
7528       //disable interrupt
7529       emit2 ("!di");
7530       //save P/O flag
7531       emit2 ("push af");
7532     }
7533 }
7534
7535 /*-----------------------------------------------------------------*/
7536 /* genEndCritical - generate code for end of a critical sequence   */
7537 /*-----------------------------------------------------------------*/
7538 static void
7539 genEndCritical (iCode *ic)
7540 {
7541   symbol *tlbl = newiTempLabel (NULL);
7542
7543   if (IS_GB)
7544     {
7545       emit2 ("!ei");
7546     }
7547   else if (IC_RIGHT (ic))
7548     {
7549       aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
7550       _toBoolean (IC_RIGHT (ic));
7551       //don't enable interrupts if they were off before
7552       emit2 ("!shortjp Z,!tlabel", tlbl->key + 100);
7553       emit2 ("!ei");
7554       emitLabel (tlbl->key + 100);
7555       freeAsmop (IC_RIGHT (ic), NULL, ic);
7556     }
7557   else
7558     {
7559       //restore P/O flag
7560       emit2 ("pop af");
7561       //parity odd <==> P/O=0 <==> interrupt enable flag IFF2 was 0 <==>
7562       //don't enable interrupts as they were off before
7563       emit2 ("jp PO,!tlabel", tlbl->key + 100);
7564       emit2 ("!ei");
7565       emit2 ("!tlabeldef", (tlbl->key + 100));
7566       _G.lines.current->isLabel = 1;
7567     }
7568 }
7569
7570 enum
7571   {
7572     /** Maximum number of bytes to emit per line. */
7573     DBEMIT_MAX_RUN = 8
7574   };
7575
7576 /** Context for the byte output chunker. */
7577 typedef struct
7578 {
7579   unsigned char buffer[DBEMIT_MAX_RUN];
7580   int pos;
7581 } DBEMITCTX;
7582
7583
7584 /** Flushes a byte chunker by writing out all in the buffer and
7585     reseting.
7586 */
7587 static void
7588 _dbFlush(DBEMITCTX *self)
7589 {
7590   char line[256];
7591
7592   if (self->pos > 0)
7593     {
7594       int i;
7595       sprintf(line, ".db 0x%02X", self->buffer[0]);
7596
7597       for (i = 1; i < self->pos; i++)
7598         {
7599           sprintf(line + strlen(line), ", 0x%02X", self->buffer[i]);
7600         }
7601       emit2(line);
7602     }
7603   self->pos = 0;
7604 }
7605
7606 /** Write out another byte, buffering until a decent line is
7607     generated.
7608 */
7609 static void
7610 _dbEmit(DBEMITCTX *self, int c)
7611 {
7612   if (self->pos == DBEMIT_MAX_RUN)
7613     {
7614       _dbFlush(self);
7615     }
7616   self->buffer[self->pos++] = c;
7617 }
7618
7619 /** Context for a simple run length encoder. */
7620 typedef struct
7621 {
7622   unsigned last;
7623   unsigned char buffer[128];
7624   int pos;
7625   /** runLen may be equivalent to pos. */
7626   int runLen;
7627 } RLECTX;
7628
7629 enum
7630   {
7631     RLE_CHANGE_COST = 4,
7632     RLE_MAX_BLOCK = 127
7633   };
7634
7635 /** Flush the buffer of a run length encoder by writing out the run or
7636     data that it currently contains.
7637 */
7638 static void
7639 _rleCommit(RLECTX *self)
7640 {
7641   int i;
7642   if (self->pos != 0)
7643     {
7644       DBEMITCTX db;
7645       memset(&db, 0, sizeof(db));
7646
7647       emit2(".db %u", self->pos);
7648
7649       for (i = 0; i < self->pos; i++)
7650         {
7651           _dbEmit(&db, self->buffer[i]);
7652         }
7653       _dbFlush(&db);
7654     }
7655   /* Reset */
7656   self->pos = 0;
7657 }
7658
7659 /* Encoder design:
7660    Can get either a run or a block of random stuff.
7661    Only want to change state if a good run comes in or a run ends.
7662    Detecting run end is easy.
7663    Initial state?
7664
7665    Say initial state is in run, len zero, last zero.  Then if you get a
7666    few zeros then something else then a short run will be output.
7667    Seems OK.  While in run mode, keep counting.  While in random mode,
7668    keep a count of the run.  If run hits margin, output all up to run,
7669    restart, enter run mode.
7670 */
7671
7672 /** Add another byte into the run length encoder, flushing as
7673     required.  The run length encoder uses the Amiga IFF style, where
7674     a block is prefixed by its run length.  A positive length means
7675     the next n bytes pass straight through.  A negative length means
7676     that the next byte is repeated -n times.  A zero terminates the
7677     chunks.
7678 */
7679 static void
7680 _rleAppend(RLECTX *self, unsigned c)
7681 {
7682   int i;
7683
7684   if (c != self->last)
7685     {
7686       /* The run has stopped.  See if it is worthwhile writing it out
7687          as a run.  Note that the random data comes in as runs of
7688          length one.
7689       */
7690       if (self->runLen > RLE_CHANGE_COST)
7691         {
7692           /* Yes, worthwhile. */
7693           /* Commit whatever was in the buffer. */
7694           _rleCommit(self);
7695           emit2("!db !immed-%u,!immedbyte", self->runLen, self->last);
7696         }
7697       else
7698         {
7699           /* Not worthwhile.  Append to the end of the random list. */
7700           for (i = 0; i < self->runLen; i++)
7701             {
7702               if (self->pos >= RLE_MAX_BLOCK)
7703                 {
7704                   /* Commit. */
7705                   _rleCommit(self);
7706                 }
7707               self->buffer[self->pos++] = self->last;
7708             }
7709         }
7710       self->runLen = 1;
7711       self->last = c;
7712     }
7713   else
7714     {
7715       if (self->runLen >= RLE_MAX_BLOCK)
7716         {
7717           /* Commit whatever was in the buffer. */
7718           _rleCommit(self);
7719
7720           emit2 ("!db !immed-%u,!immedbyte", self->runLen, self->last);
7721           self->runLen = 0;
7722         }
7723       self->runLen++;
7724     }
7725 }
7726
7727 static void
7728 _rleFlush(RLECTX *self)
7729 {
7730   _rleAppend(self, -1);
7731   _rleCommit(self);
7732   self->pos = 0;
7733   self->last = 0;
7734   self->runLen = 0;
7735 }
7736
7737 /** genArrayInit - Special code for initialising an array with constant
7738    data.
7739 */
7740 static void
7741 genArrayInit (iCode * ic)
7742 {
7743   literalList *iLoop;
7744   int         ix;
7745   int         elementSize = 0, eIndex, i;
7746   unsigned    val, lastVal;
7747   sym_link    *type;
7748   RLECTX      rle;
7749
7750   memset(&rle, 0, sizeof(rle));
7751
7752   aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
7753
7754   _saveRegsForCall(ic, 0);
7755
7756   fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
7757   emit2 ("call __initrleblock");
7758
7759   type = operandType(IC_LEFT(ic));
7760
7761   if (type && type->next)
7762     {
7763       if (IS_SPEC(type->next) || IS_PTR(type->next))
7764         {
7765           elementSize = getSize(type->next);
7766         }
7767       else if (IS_ARRAY(type->next) && type->next->next)
7768         {
7769           elementSize = getSize(type->next->next);
7770         }
7771       else
7772         {
7773           printTypeChainRaw (type, NULL);
7774           wassertl (0, "Can't determine element size in genArrayInit.");
7775         }
7776     }
7777   else
7778     {
7779       wassertl (0, "Can't determine element size in genArrayInit.");
7780     }
7781
7782   wassertl ((elementSize > 0) && (elementSize <= 4), "Illegal element size in genArrayInit.");
7783
7784   iLoop = IC_ARRAYILIST(ic);
7785   lastVal = (unsigned)-1;
7786
7787   /* Feed all the bytes into the run length encoder which will handle
7788      the actual output.
7789      This works well for mixed char data, and for random int and long
7790      data.
7791   */
7792   while (iLoop)
7793     {
7794       ix = iLoop->count;
7795
7796       for (i = 0; i < ix; i++)
7797         {
7798           for (eIndex = 0; eIndex < elementSize; eIndex++)
7799             {
7800               val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
7801               _rleAppend(&rle, val);
7802             }
7803         }
7804
7805       iLoop = iLoop->next;
7806     }
7807
7808   _rleFlush(&rle);
7809   /* Mark the end of the run. */
7810   emit2(".db 0");
7811
7812   _restoreRegsAfterCall();
7813
7814   spillCached ();
7815
7816   freeAsmop (IC_LEFT(ic), NULL, ic);
7817 }
7818
7819 static void
7820 _swap (PAIR_ID one, PAIR_ID two)
7821 {
7822   if ((one == PAIR_DE && two == PAIR_HL) || (one == PAIR_HL && two == PAIR_DE))
7823     {
7824       emit2 ("ex de,hl");
7825     }
7826   else
7827     {
7828       emit2 ("ld a,%s", _pairs[one].l);
7829       emit2 ("ld %s,%s", _pairs[one].l, _pairs[two].l);
7830       emit2 ("ld %s,a", _pairs[two].l);
7831       emit2 ("ld a,%s", _pairs[one].h);
7832       emit2 ("ld %s,%s", _pairs[one].h, _pairs[two].h);
7833       emit2 ("ld %s,a", _pairs[two].h);
7834     }
7835 }
7836
7837 /* The problem is that we may have all three pairs used and they may
7838    be needed in a different order.
7839
7840    Note: Have ex de,hl
7841
7842    Combinations:
7843      hl = hl            => unity, fine
7844      bc = bc
7845      de = de
7846
7847      hl = hl            hl = hl, swap de <=> bc
7848      bc = de
7849      de = bc
7850
7851      hl = bc            Worst case
7852      bc = de
7853      de = hl
7854
7855      hl = bc            de = de, swap bc <=> hl
7856      bc = hl
7857      de = de
7858
7859      hl = de            Worst case
7860      bc = hl
7861      de = bc
7862
7863      hl = de            bc = bc, swap hl <=> de
7864      bc = bc
7865      de = hl
7866
7867    Break it down into:
7868     * Any pair = pair are done last
7869     * Any pair = iTemp are done last
7870     * Any swaps can be done any time
7871
7872    A worst case:
7873     push p1
7874     p1 = p2
7875     p2 = p3
7876     pop  p3
7877
7878    So how do we detect the cases?
7879    How about a 3x3 matrix?
7880         source
7881    dest x x x x
7882         x x x x
7883         x x x x (Fourth for iTemp/other)
7884
7885    First determin which mode to use by counting the number of unity and
7886    iTemp assigns.
7887      Three - any order
7888      Two - Assign the pair first, then the rest
7889      One - Swap the two, then the rest
7890      Zero - Worst case.
7891 */
7892 static void
7893 setupForBuiltin3 (iCode *ic, int nparams, operand **pparams)
7894 {
7895   PAIR_ID ids[NUM_PAIRS][NUM_PAIRS];
7896   PAIR_ID dest[3] = {
7897     PAIR_BC, PAIR_HL, PAIR_DE
7898   };
7899   int i, j, nunity = 0;
7900   memset (ids, PAIR_INVALID, sizeof (ids));
7901
7902   /* Sanity checks */
7903   wassert (nparams == 3);
7904
7905   /* First save everything that needs to be saved. */
7906   _saveRegsForCall (ic, 0);
7907
7908   /* Loading HL first means that DE is always fine. */
7909   for (i = 0; i < nparams; i++)
7910     {
7911       aopOp (pparams[i], ic, FALSE, FALSE);
7912       ids[dest[i]][getPairId (AOP (pparams[i]))] = TRUE;
7913     }
7914
7915   /* Count the number of unity or iTemp assigns. */
7916   for (i = 0; i < 3; i++)
7917     {
7918       if (ids[dest[i]][dest[i]] == TRUE || ids[dest[i]][PAIR_INVALID] == TRUE)
7919         {
7920           nunity++;
7921         }
7922     }
7923
7924   if (nunity == 3)
7925     {
7926       /* Any order, fall through. */
7927     }
7928   else if (nunity == 2)
7929     {
7930       /* One is assigned.  Pull it out and assign. */
7931       for (i = 0; i < 3; i++)
7932         {
7933           for (j = 0; j < NUM_PAIRS; j++)
7934             {
7935               if (ids[dest[i]][j] == TRUE)
7936                 {
7937                   /* Found it.  See if it's the right one. */
7938                   if (j == PAIR_INVALID || j == dest[i])
7939                     {
7940                       /* Keep looking. */
7941                     }
7942                   else
7943                     {
7944                       fetchPair(dest[i], AOP (pparams[i]));
7945                       goto done;
7946                     }
7947                 }
7948             }
7949         }
7950     }
7951   else if (nunity == 1)
7952     {
7953       /* Find the pairs to swap. */
7954       for (i = 0; i < 3; i++)
7955         {
7956           for (j = 0; j < NUM_PAIRS; j++)
7957             {
7958               if (ids[dest[i]][j] == TRUE)
7959                 {
7960                   if (j == PAIR_INVALID || j == dest[i])
7961                     {
7962                       /* Keep looking. */
7963                     }
7964                   else
7965                     {
7966                       _swap (j, dest[i]);
7967                       goto done;
7968                     }
7969                 }
7970             }
7971         }
7972     }
7973   else
7974     {
7975       int next = getPairId (AOP (pparams[0]));
7976       emit2 ("push %s", _pairs[next].name);
7977
7978       if (next == dest[1])
7979         {
7980           fetchPair (dest[1], AOP (pparams[1]));
7981           fetchPair (dest[2], AOP (pparams[2]));
7982         }
7983       else
7984         {
7985           fetchPair (dest[2], AOP (pparams[2]));
7986           fetchPair (dest[1], AOP (pparams[1]));
7987         }
7988       emit2 ("pop %s", _pairs[dest[0]].name);
7989     }
7990  done:
7991   /* Finally pull out all of the iTemps */
7992   for (i = 0; i < 3; i++)
7993     {
7994       if (ids[dest[i]][PAIR_INVALID] == 1)
7995         {
7996           fetchPair (dest[i], AOP (pparams[i]));
7997         }
7998     }
7999 }
8000
8001 static void
8002 genBuiltInStrcpy (iCode *ic, int nParams, operand **pparams)
8003 {
8004   operand *from, *to;
8005   symbol *label;
8006   bool deInUse;
8007
8008   wassertl (nParams == 2, "Built-in strcpy must have two parameters");
8009   to = pparams[0];
8010   from = pparams[1];
8011
8012   deInUse = bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX);
8013
8014   setupForBuiltin3 (ic, nParams, pparams);
8015
8016   label = newiTempLabel(NULL);
8017
8018   emitLabel (label->key);
8019   emit2 ("ld a,(hl)");
8020   emit2 ("ldi");
8021   emit2 ("or a");
8022   emit2 ("!shortjp NZ,!tlabel ; 1", label->key);
8023
8024   freeAsmop (from, NULL, ic->next);
8025   freeAsmop (to, NULL, ic);
8026 }
8027
8028 static void
8029 genBuiltInMemcpy (iCode *ic, int nParams, operand **pparams)
8030 {
8031   operand *from, *to, *count;
8032   bool deInUse;
8033
8034   wassertl (nParams == 3, "Built-in memcpy must have two parameters");
8035   to = pparams[2];
8036   from = pparams[1];
8037   count = pparams[0];
8038
8039   deInUse = bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX);
8040
8041   setupForBuiltin3 (ic, nParams, pparams);
8042
8043   emit2 ("ldir");
8044
8045   freeAsmop (count, NULL, ic->next->next);
8046   freeAsmop (from, NULL, ic);
8047
8048   _restoreRegsAfterCall();
8049
8050   /* if we need assign a result value */
8051   if ((IS_ITEMP (IC_RESULT (ic)) &&
8052        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
8053         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
8054       IS_TRUE_SYMOP (IC_RESULT (ic)))
8055     {
8056       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8057       movLeft2ResultLong (to, 0, IC_RESULT (ic), 0, 0, 2);
8058       freeAsmop (IC_RESULT (ic), NULL, ic);
8059     }
8060
8061   freeAsmop (to, NULL, ic->next);
8062 }
8063
8064 /*-----------------------------------------------------------------*/
8065 /* genBuiltIn - calls the appropriate function to  generating code */
8066 /* for a built in function                                         */
8067 /*-----------------------------------------------------------------*/
8068 static void genBuiltIn (iCode *ic)
8069 {
8070     operand *bi_parms[MAX_BUILTIN_ARGS];
8071     int nbi_parms;
8072     iCode *bi_iCode;
8073     symbol *bif;
8074
8075     /* get all the arguments for a built in function */
8076     bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
8077
8078     /* which function is it */
8079     bif = OP_SYMBOL(IC_LEFT(bi_iCode));
8080
8081     if (strcmp(bif->name,"__builtin_strcpy")==0)
8082       {
8083         genBuiltInStrcpy(bi_iCode, nbi_parms, bi_parms);
8084       }
8085     else if (strcmp(bif->name,"__builtin_memcpy")==0)
8086       {
8087         genBuiltInMemcpy(bi_iCode, nbi_parms, bi_parms);
8088       }
8089     else
8090       {
8091         wassertl (0, "Unknown builtin function encountered");
8092       }
8093 }
8094
8095 /*-----------------------------------------------------------------*/
8096 /* genZ80Code - generate code for Z80 based controllers            */
8097 /*-----------------------------------------------------------------*/
8098 void
8099 genZ80Code (iCode * lic)
8100 {
8101   iCode *ic;
8102   int cln = 0;
8103
8104   /* Hack */
8105   if (IS_GB)
8106     {
8107       _fReturn = _gbz80_return;
8108       _fTmp = _gbz80_return;
8109     }
8110   else
8111     {
8112       _fReturn = _z80_return;
8113       _fTmp = _z80_return;
8114     }
8115
8116   _G.lines.head = _G.lines.current = NULL;
8117
8118   /* if debug information required */
8119   if (options.debug && currFunc)
8120     {
8121       debugFile->writeFunction (currFunc, lic);
8122     }
8123
8124   for (ic = lic; ic; ic = ic->next)
8125     {
8126       _G.current_iCode = ic;
8127
8128       if (ic->lineno && cln != ic->lineno)
8129         {
8130           if (options.debug)
8131             {
8132               debugFile->writeCLine (ic);
8133             }
8134           if (!options.noCcodeInAsm)
8135             {
8136               emit2 (";%s:%d: %s", ic->filename, ic->lineno,
8137                      printCLine(ic->filename, ic->lineno));
8138             }
8139           cln = ic->lineno;
8140         }
8141       if (options.iCodeInAsm)
8142         {
8143           char *iLine = printILine(ic);
8144           emit2 (";ic:%d: %s", ic->key, iLine);
8145           dbuf_free(iLine);
8146         }
8147       /* if the result is marked as
8148          spilt and rematerializable or code for
8149          this has already been generated then
8150          do nothing */
8151       if (resultRemat (ic) || ic->generated)
8152         continue;
8153
8154       /* depending on the operation */
8155       switch (ic->op)
8156         {
8157         case '!':
8158           emitDebug ("; genNot");
8159           genNot (ic);
8160           break;
8161
8162         case '~':
8163           emitDebug ("; genCpl");
8164           genCpl (ic);
8165           break;
8166
8167         case UNARYMINUS:
8168           emitDebug ("; genUminus");
8169           genUminus (ic);
8170           break;
8171
8172         case IPUSH:
8173           emitDebug ("; genIpush");
8174           genIpush (ic);
8175           break;
8176
8177         case IPOP:
8178           /* IPOP happens only when trying to restore a
8179              spilt live range, if there is an ifx statement
8180              following this pop then the if statement might
8181              be using some of the registers being popped which
8182              would destroy the contents of the register so
8183              we need to check for this condition and handle it */
8184           if (ic->next &&
8185               ic->next->op == IFX &&
8186               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8187             {
8188               emitDebug ("; genIfx");
8189               genIfx (ic->next, ic);
8190             }
8191           else
8192             {
8193               emitDebug ("; genIpop");
8194               genIpop (ic);
8195             }
8196           break;
8197
8198         case CALL:
8199           emitDebug ("; genCall");
8200           genCall (ic);
8201           break;
8202
8203         case PCALL:
8204           emitDebug ("; genPcall");
8205           genPcall (ic);
8206           break;
8207
8208         case FUNCTION:
8209           emitDebug ("; genFunction");
8210           genFunction (ic);
8211           break;
8212
8213         case ENDFUNCTION:
8214           emitDebug ("; genEndFunction");
8215           genEndFunction (ic);
8216           break;
8217
8218         case RETURN:
8219           emitDebug ("; genRet");
8220           genRet (ic);
8221           break;
8222
8223         case LABEL:
8224           emitDebug ("; genLabel");
8225           genLabel (ic);
8226           break;
8227
8228         case GOTO:
8229           emitDebug ("; genGoto");
8230           genGoto (ic);
8231           break;
8232
8233         case '+':
8234           emitDebug ("; genPlus");
8235           genPlus (ic);
8236           break;
8237
8238         case '-':
8239           emitDebug ("; genMinus");
8240           genMinus (ic);
8241           break;
8242
8243         case '*':
8244           emitDebug ("; genMult");
8245           genMult (ic);
8246           break;
8247
8248         case '/':
8249           emitDebug ("; genDiv");
8250           genDiv (ic);
8251           break;
8252
8253         case '%':
8254           emitDebug ("; genMod");
8255           genMod (ic);
8256           break;
8257
8258         case '>':
8259           emitDebug ("; genCmpGt");
8260           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8261           break;
8262
8263         case '<':
8264           emitDebug ("; genCmpLt");
8265           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8266           break;
8267
8268         case LE_OP:
8269         case GE_OP:
8270         case NE_OP:
8271
8272           /* note these two are xlated by algebraic equivalence
8273              during parsing SDCC.y */
8274           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8275                   "got '>=' or '<=' shouldn't have come here");
8276           break;
8277
8278         case EQ_OP:
8279           emitDebug ("; genCmpEq");
8280           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8281           break;
8282
8283         case AND_OP:
8284           emitDebug ("; genAndOp");
8285           genAndOp (ic);
8286           break;
8287
8288         case OR_OP:
8289           emitDebug ("; genOrOp");
8290           genOrOp (ic);
8291           break;
8292
8293         case '^':
8294           emitDebug ("; genXor");
8295           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8296           break;
8297
8298         case '|':
8299           emitDebug ("; genOr");
8300           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8301           break;
8302
8303         case BITWISEAND:
8304           emitDebug ("; genAnd");
8305           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8306           break;
8307
8308         case INLINEASM:
8309           emitDebug ("; genInline");
8310           genInline (ic);
8311           break;
8312
8313         case RRC:
8314           emitDebug ("; genRRC");
8315           genRRC (ic);
8316           break;
8317
8318         case RLC:
8319           emitDebug ("; genRLC");
8320           genRLC (ic);
8321           break;
8322
8323         case GETHBIT:
8324           emitDebug ("; genGetHBIT");
8325           genGetHbit (ic);
8326           break;
8327
8328         case LEFT_OP:
8329           emitDebug ("; genLeftShift");
8330           genLeftShift (ic);
8331           break;
8332
8333         case RIGHT_OP:
8334           emitDebug ("; genRightShift");
8335           genRightShift (ic);
8336           break;
8337
8338         case GET_VALUE_AT_ADDRESS:
8339           emitDebug ("; genPointerGet");
8340           genPointerGet (ic);
8341           break;
8342
8343         case '=':
8344
8345           if (POINTER_SET (ic))
8346             {
8347               emitDebug ("; genAssign (pointer)");
8348               genPointerSet (ic);
8349             }
8350           else
8351             {
8352               emitDebug ("; genAssign");
8353               genAssign (ic);
8354             }
8355           break;
8356
8357         case IFX:
8358           emitDebug ("; genIfx");
8359           genIfx (ic, NULL);
8360           break;
8361
8362         case ADDRESS_OF:
8363           emitDebug ("; genAddrOf");
8364           genAddrOf (ic);
8365           break;
8366
8367         case JUMPTABLE:
8368           emitDebug ("; genJumpTab");
8369           genJumpTab (ic);
8370           break;
8371
8372         case CAST:
8373           emitDebug ("; genCast");
8374           genCast (ic);
8375           break;
8376
8377         case RECEIVE:
8378           emitDebug ("; genReceive");
8379           genReceive (ic);
8380           break;
8381
8382         case SEND:
8383           if (ic->builtinSEND)
8384             {
8385               emitDebug ("; genBuiltIn");
8386               genBuiltIn(ic);
8387             }
8388           else
8389             {
8390               emitDebug ("; addSet");
8391               addSet (&_G.sendSet, ic);
8392             }
8393           break;
8394
8395         case ARRAYINIT:
8396           emitDebug ("; genArrayInit");
8397           genArrayInit(ic);
8398           break;
8399
8400         case DUMMY_READ_VOLATILE:
8401           emitDebug ("; genDummyRead");
8402           genDummyRead (ic);
8403           break;
8404
8405         case CRITICAL:
8406           emitDebug ("; genCritical");
8407           genCritical (ic);
8408           break;
8409
8410         case ENDCRITICAL:
8411           emitDebug ("; genEndCritical");
8412           genEndCritical (ic);
8413           break;
8414
8415         default:
8416           ic = ic;
8417         }
8418     }
8419
8420
8421   /* now we are ready to call the
8422      peep hole optimizer */
8423   if (!options.nopeep)
8424     peepHole (&_G.lines.head);
8425
8426   /* This is unfortunate */
8427   /* now do the actual printing */
8428   {
8429     struct dbuf_s *buf = codeOutBuf;
8430     if (isInHome () && codeOutBuf == &code->oBuf)
8431       codeOutBuf = &home->oBuf;
8432     printLine (_G.lines.head, codeOutBuf);
8433     if (_G.flushStatics)
8434       {
8435         flushStatics ();
8436         _G.flushStatics = 0;
8437       }
8438     codeOutBuf = buf;
8439   }
8440
8441   freeTrace(&_G.lines.trace);
8442   freeTrace(&_G.trace.aops);
8443 }
8444
8445 /*
8446   Attic
8447 static int
8448 _isPairUsed (iCode * ic, PAIR_ID pairId)
8449 {
8450   int ret = 0;
8451   switch (pairId)
8452     {
8453     case PAIR_DE:
8454       if (bitVectBitValue (ic->rMask, D_IDX))
8455         ret++;
8456       if (bitVectBitValue (ic->rMask, E_IDX))
8457         ret++;
8458       break;
8459     default:
8460       wassert (0);
8461     }
8462   return ret;
8463 }
8464
8465 static char *
8466 fetchLitSpecial (asmop * aop, bool negate, bool xor)
8467 {
8468   unsigned long v;
8469   value *val = aop->aopu.aop_lit;
8470
8471   wassert (aop->type == AOP_LIT);
8472   wassert (!IS_FLOAT (val->type));
8473
8474   v = (unsigned long) floatFromVal (val);
8475
8476   if (xor)
8477     v ^= 0x8000;
8478   if (negate)
8479     v = 0-v;
8480   v &= 0xFFFF;
8481
8482   tsprintf (buffer, sizeof(buffer), "!immedword", v);
8483   return traceAlloc(&_G.trace.aops, Safe_strdup (buffer));
8484 }
8485
8486
8487 */