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