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