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