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