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