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