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