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