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