clean up genDjnz for far data case; include same fix for mcs51 port.
[fw/sdcc] / src / ds390 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for DS80C390
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7
8   This program is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by the
10   Free Software Foundation; either version 2, or (at your option) any
11   later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22   In other words, you are welcome to use, share and improve this program.
23   You are forbidden to forbid anyone else to use, share and improve
24   what you give them.   Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <ctype.h>
31
32 #include <common.h>
33 #include "ralloc.h"
34 #include "gen.h"
35 #include "SDCCglobl.h"
36 #include "newalloc.h"
37
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
40 #else
41 #ifdef HAVE_ENDIAN_H
42 #include <endian.h>
43 #else
44 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
45 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
46 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
47 #endif
48 #endif
49 #endif
50
51 char *aopLiteral (value * val, int offset);
52
53 /* this is the down and dirty file with all kinds of
54    kludgy & hacky stuff. This is what it is all about
55    CODE GENERATION for a specific MCU . some of the
56    routines may be reusable, will have to see */
57
58 static char *zero = "#0x00";
59 static char *one = "#0x01";
60 static char *spname;
61
62 #define D(x) x
63
64 unsigned fReturnSizeDS390 = 5;  /* shared with ralloc.c */
65 static char *fReturn[] =
66 {"dpl", "dph", "dpx", "b", "a"};
67 static char *accUse[] =
68 {"a", "b"};
69
70 static short rbank = -1;
71
72 static struct
73   {
74     short r0Pushed;
75     short r1Pushed;
76     short accInUse;
77     short inLine;
78     short debugLine;
79     short nRegsSaved;
80     set *sendSet;
81   }
82 _G;
83
84 static void saverbank (int, iCode *, bool);
85
86 #define RESULTONSTACK(x) \
87                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
88                          IC_RESULT(x)->aop->type == AOP_STK )
89
90 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
91 #define MOVA(x) { char *_mova_tmp = strdup(x); \
92                  if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
93                  { \
94                     emitcode("mov","a,%s",_mova_tmp); \
95                  } \
96                  free(_mova_tmp); \
97                 }
98 #define CLRC    emitcode("clr","c")
99 #define SETC    emitcode("setb","c")
100
101 // A scratch register which will be used to hold
102 // result bytes from operands in far space via DPTR2.
103 #define DP2_RESULT_REG  "ap"
104
105 static lineNode *lineHead = NULL;
106 static lineNode *lineCurr = NULL;
107
108 static unsigned char SLMask[] =
109 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
110  0xE0, 0xC0, 0x80, 0x00};
111 static unsigned char SRMask[] =
112 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
113  0x07, 0x03, 0x01, 0x00};
114
115 #define LSB     0
116 #define MSB16   1
117 #define MSB24   2
118 #define MSB32   3
119
120 /*-----------------------------------------------------------------*/
121 /* emitcode - writes the code into a file : for now it is simple    */
122 /*-----------------------------------------------------------------*/
123 static void
124 emitcode (char *inst, char *fmt,...)
125 {
126   va_list ap;
127   char lb[MAX_INLINEASM];
128   char *lbp = lb;
129
130   va_start (ap, fmt);
131
132   if (inst && *inst)
133     {
134       if (fmt && *fmt)
135         sprintf (lb, "%s\t", inst);
136       else
137         sprintf (lb, "%s", inst);
138       vsprintf (lb + (strlen (lb)), fmt, ap);
139     }
140   else
141     vsprintf (lb, fmt, ap);
142
143   while (isspace (*lbp))
144     lbp++;
145
146   if (lbp && *lbp)
147     lineCurr = (lineCurr ?
148                 connectLine (lineCurr, newLineNode (lb)) :
149                 (lineHead = newLineNode (lb)));
150   lineCurr->isInline = _G.inLine;
151   lineCurr->isDebug = _G.debugLine;
152   va_end (ap);
153 }
154
155 /*-----------------------------------------------------------------*/
156 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
157 /*-----------------------------------------------------------------*/
158 static regs *
159 getFreePtr (iCode * ic, asmop ** aopp, bool result)
160 {
161   bool r0iu = FALSE, r1iu = FALSE;
162   bool r0ou = FALSE, r1ou = FALSE;
163
164   /* the logic: if r0 & r1 used in the instruction
165      then we are in trouble otherwise */
166
167   /* first check if r0 & r1 are used by this
168      instruction, in which case we are in trouble */
169   if ((r0iu = bitVectBitValue (ic->rUsed, R0_IDX)) &&
170       (r1iu = bitVectBitValue (ic->rUsed, R1_IDX)))
171     {
172       goto endOfWorld;
173     }
174
175   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
176   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
177
178   /* if no usage of r0 then return it */
179   if (!r0iu && !r0ou)
180     {
181       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
182       (*aopp)->type = AOP_R0;
183
184       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
185     }
186
187   /* if no usage of r1 then return it */
188   if (!r1iu && !r1ou)
189     {
190       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
191       (*aopp)->type = AOP_R1;
192
193       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
194     }
195
196   /* now we know they both have usage */
197   /* if r0 not used in this instruction */
198   if (!r0iu)
199     {
200       /* push it if not already pushed */
201       if (!_G.r0Pushed)
202         {
203           emitcode ("push", "%s",
204                     ds390_regWithIdx (R0_IDX)->dname);
205           _G.r0Pushed++;
206         }
207
208       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
209       (*aopp)->type = AOP_R0;
210
211       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
212     }
213
214   /* if r1 not used then */
215
216   if (!r1iu)
217     {
218       /* push it if not already pushed */
219       if (!_G.r1Pushed)
220         {
221           emitcode ("push", "%s",
222                     ds390_regWithIdx (R1_IDX)->dname);
223           _G.r1Pushed++;
224         }
225
226       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
227       (*aopp)->type = AOP_R1;
228       return ds390_regWithIdx (R1_IDX);
229     }
230
231 endOfWorld:
232   /* I said end of world but not quite end of world yet */
233   /* if this is a result then we can push it on the stack */
234   if (result)
235     {
236       (*aopp)->type = AOP_STK;
237       return NULL;
238     }
239
240   /* other wise this is true end of the world */
241   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
242           "getFreePtr should never reach here");
243   exit (1);
244 }
245
246 /*-----------------------------------------------------------------*/
247 /* newAsmop - creates a new asmOp                                  */
248 /*-----------------------------------------------------------------*/
249 static asmop *
250 newAsmop (short type)
251 {
252   asmop *aop;
253
254   aop = Safe_calloc (1, sizeof (asmop));
255   aop->type = type;
256   return aop;
257 }
258
259 static int _currentDPS;         /* Current processor DPS. */
260 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
261 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
262
263 /*-----------------------------------------------------------------*/
264 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
265 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
266 /* alternate DPTR (DPL1/DPH1/DPX1).          */
267 /*-----------------------------------------------------------------*/
268 static void
269 genSetDPTR (int n)
270 {
271
272   /* If we are doing lazy evaluation, simply note the desired
273    * change, but don't emit any code yet.
274    */
275   if (_lazyDPS)
276     {
277       _desiredDPS = n;
278       return;
279     }
280
281   if (!n)
282     {
283       emitcode ("mov", "dps, #0x00");
284     }
285   else
286     {
287       emitcode ("mov", "dps, #0x01");
288     }
289 }
290
291 /*-----------------------------------------------------------------*/
292 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
293 /*                   */
294 /* Any code that operates on DPTR (NB: not on the individual     */
295 /* components, like DPH) *must* call _flushLazyDPS() before using  */
296 /* DPTR within a lazy DPS evaluation block.        */
297 /*                   */
298 /* Note that aopPut and aopGet already contain the proper calls to */
299 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
300 /* DPS evaluation block.             */
301 /*                   */
302 /* Also, _flushLazyDPS must be called before any flow control      */
303 /* operations that could potentially branch out of the block.    */
304 /*                         */
305 /* Lazy DPS evaluation is simply an optimization (though an      */
306 /* important one), so if in doubt, leave it out.       */
307 /*-----------------------------------------------------------------*/
308 static void
309 _startLazyDPSEvaluation (void)
310 {
311   _currentDPS = 0;
312   _desiredDPS = 0;
313   _lazyDPS = 1;
314 }
315
316 /*-----------------------------------------------------------------*/
317 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
318 /* desired one. Call before using DPTR within a lazy DPS evaluation */
319 /* block.                */
320 /*-----------------------------------------------------------------*/
321 static void
322 _flushLazyDPS (void)
323 {
324   if (!_lazyDPS)
325     {
326       /* nothing to do. */
327       return;
328     }
329
330   if (_desiredDPS != _currentDPS)
331     {
332       if (_desiredDPS)
333         {
334           emitcode ("inc", "dps");
335         }
336       else
337         {
338           emitcode ("dec", "dps");
339         }
340       _currentDPS = _desiredDPS;
341     }
342 }
343
344 /*-----------------------------------------------------------------*/
345 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
346 /*                   */
347 /* Forces us back to the safe state (standard DPTR selected).    */
348 /*-----------------------------------------------------------------*/
349 static void
350 _endLazyDPSEvaluation (void)
351 {
352   if (_currentDPS)
353     {
354       genSetDPTR (0);
355       _flushLazyDPS ();
356     }
357   _lazyDPS = 0;
358   _currentDPS = 0;
359   _desiredDPS = 0;
360 }
361
362
363
364 /*-----------------------------------------------------------------*/
365 /* pointerCode - returns the code for a pointer type               */
366 /*-----------------------------------------------------------------*/
367 static int
368 pointerCode (sym_link * etype)
369 {
370
371   return PTR_TYPE (SPEC_OCLS (etype));
372
373 }
374
375 /*-----------------------------------------------------------------*/
376 /* aopForSym - for a true symbol                                   */
377 /*-----------------------------------------------------------------*/
378 static asmop *
379 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
380 {
381   asmop *aop;
382   memmap *space = SPEC_OCLS (sym->etype);
383
384   /* if already has one */
385   if (sym->aop)
386     return sym->aop;
387
388   /* assign depending on the storage class */
389   /* if it is on the stack or indirectly addressable */
390   /* space we need to assign either r0 or r1 to it   */
391   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
392     {
393       sym->aop = aop = newAsmop (0);
394       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
395       aop->size = getSize (sym->type);
396
397       /* now assign the address of the variable to
398          the pointer register */
399       if (aop->type != AOP_STK)
400         {
401
402           if (sym->onStack)
403             {
404               if (_G.accInUse)
405                 emitcode ("push", "acc");
406
407               emitcode ("mov", "a,_bp");
408               emitcode ("add", "a,#0x%02x",
409                         ((sym->stack < 0) ?
410                          ((char) (sym->stack - _G.nRegsSaved)) :
411                          ((char) sym->stack)) & 0xff);
412               emitcode ("mov", "%s,a",
413                         aop->aopu.aop_ptr->name);
414
415               if (_G.accInUse)
416                 emitcode ("pop", "acc");
417             }
418           else
419             emitcode ("mov", "%s,#%s",
420                       aop->aopu.aop_ptr->name,
421                       sym->rname);
422           aop->paged = space->paged;
423         }
424       else
425         aop->aopu.aop_stk = sym->stack;
426       return aop;
427     }
428
429   if (sym->onStack && options.stack10bit)
430     {
431       /* It's on the 10 bit stack, which is located in
432        * far data space.
433        */
434
435       if (_G.accInUse)
436         emitcode ("push", "acc");
437
438       emitcode ("mov", "a,_bp");
439       emitcode ("add", "a,#0x%02x",
440                 ((sym->stack < 0) ?
441                  ((char) (sym->stack - _G.nRegsSaved)) :
442                  ((char) sym->stack)) & 0xff);
443
444       if (useDP2)
445         {
446           /* genSetDPTR(1); */
447           emitcode ("mov", "dpx1,#0x40");
448           emitcode ("mov", "dph1,#0x00");
449           emitcode ("mov", "dpl1, a");
450           /* genSetDPTR(0); */
451         }
452       else
453         {
454           emitcode ("mov", "dpx,#0x40");
455           emitcode ("mov", "dph,#0x00");
456           emitcode ("mov", "dpl, a");
457         }
458
459       if (_G.accInUse)
460         emitcode ("pop", "acc");
461
462       sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
463       aop->size = getSize (sym->type);
464       return aop;
465     }
466
467   /* if in bit space */
468   if (IN_BITSPACE (space))
469     {
470       sym->aop = aop = newAsmop (AOP_CRY);
471       aop->aopu.aop_dir = sym->rname;
472       aop->size = getSize (sym->type);
473       return aop;
474     }
475   /* if it is in direct space */
476   if (IN_DIRSPACE (space))
477     {
478       sym->aop = aop = newAsmop (AOP_DIR);
479       aop->aopu.aop_dir = sym->rname;
480       aop->size = getSize (sym->type);
481       return aop;
482     }
483
484   /* special case for a function */
485   if (IS_FUNC (sym->type))
486     {
487       sym->aop = aop = newAsmop (AOP_IMMD);
488       aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
489       strcpy (aop->aopu.aop_immd, sym->rname);
490       aop->size = FPTRSIZE;
491       return aop;
492     }
493
494   /* only remaining is far space */
495   /* in which case DPTR gets the address */
496   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
497   if (useDP2)
498     {
499       genSetDPTR (1);
500       _flushLazyDPS ();
501       emitcode ("mov", "dptr,#%s", sym->rname);
502       genSetDPTR (0);
503     }
504   else
505     {
506       emitcode ("mov", "dptr,#%s", sym->rname);
507     }
508   aop->size = getSize (sym->type);
509
510   /* if it is in code space */
511   if (IN_CODESPACE (space))
512     aop->code = 1;
513
514   return aop;
515 }
516
517 /*-----------------------------------------------------------------*/
518 /* aopForRemat - rematerialzes an object                           */
519 /*-----------------------------------------------------------------*/
520 static asmop *
521 aopForRemat (symbol * sym)
522 {
523   iCode *ic = sym->rematiCode;
524   asmop *aop = newAsmop (AOP_IMMD);
525
526   int val = 0;
527
528   for (;;)
529     {
530       if (ic->op == '+')
531         val += (int) operandLitValue (IC_RIGHT (ic));
532       else if (ic->op == '-')
533         val -= (int) operandLitValue (IC_RIGHT (ic));
534       else
535         break;
536
537       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
538     }
539
540   if (val)
541     sprintf (buffer, "(%s %c 0x%04x)",
542              OP_SYMBOL (IC_LEFT (ic))->rname,
543              val >= 0 ? '+' : '-',
544              abs (val) & 0xffff);
545   else
546     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
547
548   aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
549   strcpy (aop->aopu.aop_immd, buffer);
550   return aop;
551 }
552
553 /*-----------------------------------------------------------------*/
554 /* regsInCommon - two operands have some registers in common       */
555 /*-----------------------------------------------------------------*/
556 static bool
557 regsInCommon (operand * op1, operand * op2)
558 {
559   symbol *sym1, *sym2;
560   int i;
561
562   /* if they have registers in common */
563   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
564     return FALSE;
565
566   sym1 = OP_SYMBOL (op1);
567   sym2 = OP_SYMBOL (op2);
568
569   if (sym1->nRegs == 0 || sym2->nRegs == 0)
570     return FALSE;
571
572   for (i = 0; i < sym1->nRegs; i++)
573     {
574       int j;
575       if (!sym1->regs[i])
576         continue;
577
578       for (j = 0; j < sym2->nRegs; j++)
579         {
580           if (!sym2->regs[j])
581             continue;
582
583           if (sym2->regs[j] == sym1->regs[i])
584             return TRUE;
585         }
586     }
587
588   return FALSE;
589 }
590
591 /*-----------------------------------------------------------------*/
592 /* operandsEqu - equivalent                                        */
593 /*-----------------------------------------------------------------*/
594 static bool
595 operandsEqu (operand * op1, operand * op2)
596 {
597   symbol *sym1, *sym2;
598
599   /* if they not symbols */
600   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
601     return FALSE;
602
603   sym1 = OP_SYMBOL (op1);
604   sym2 = OP_SYMBOL (op2);
605
606   /* if both are itemps & one is spilt
607      and the other is not then false */
608   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
609       sym1->isspilt != sym2->isspilt)
610     return FALSE;
611
612   /* if they are the same */
613   if (sym1 == sym2)
614     return TRUE;
615
616   if (strcmp (sym1->rname, sym2->rname) == 0)
617     return TRUE;
618
619
620   /* if left is a tmp & right is not */
621   if (IS_ITEMP (op1) &&
622       !IS_ITEMP (op2) &&
623       sym1->isspilt &&
624       (sym1->usl.spillLoc == sym2))
625     return TRUE;
626
627   if (IS_ITEMP (op2) &&
628       !IS_ITEMP (op1) &&
629       sym2->isspilt &&
630       sym1->level > 0 &&
631       (sym2->usl.spillLoc == sym1))
632     return TRUE;
633
634   return FALSE;
635 }
636
637 /*-----------------------------------------------------------------*/
638 /* sameRegs - two asmops have the same registers                   */
639 /*-----------------------------------------------------------------*/
640 static bool
641 sameRegs (asmop * aop1, asmop * aop2)
642 {
643   int i;
644
645   if (aop1 == aop2)
646     {
647       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
648         {
649           return FALSE;
650         }
651       return TRUE;
652     }
653
654   if (aop1->type != AOP_REG ||
655       aop2->type != AOP_REG)
656     return FALSE;
657
658   if (aop1->size != aop2->size)
659     return FALSE;
660
661   for (i = 0; i < aop1->size; i++)
662     if (aop1->aopu.aop_reg[i] !=
663         aop2->aopu.aop_reg[i])
664       return FALSE;
665
666   return TRUE;
667 }
668
669 /*-----------------------------------------------------------------*/
670 /* aopOp - allocates an asmop for an operand  :                    */
671 /*-----------------------------------------------------------------*/
672 static void
673 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
674 {
675   asmop *aop;
676   symbol *sym;
677   int i;
678
679   if (!op)
680     return;
681
682   /* if this a literal */
683   if (IS_OP_LITERAL (op))
684     {
685       op->aop = aop = newAsmop (AOP_LIT);
686       aop->aopu.aop_lit = op->operand.valOperand;
687       aop->size = getSize (operandType (op));
688       return;
689     }
690
691   /* if already has a asmop then continue */
692   if (op->aop)
693     return;
694
695   /* if the underlying symbol has a aop */
696   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
697     {
698       op->aop = OP_SYMBOL (op)->aop;
699       return;
700     }
701
702   /* if this is a true symbol */
703   if (IS_TRUE_SYMOP (op))
704     {
705       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
706       return;
707     }
708
709   /* this is a temporary : this has
710      only four choices :
711      a) register
712      b) spillocation
713      c) rematerialize
714      d) conditional
715      e) can be a return use only */
716
717   sym = OP_SYMBOL (op);
718
719
720   /* if the type is a conditional */
721   if (sym->regType == REG_CND)
722     {
723       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
724       aop->size = 0;
725       return;
726     }
727
728   /* if it is spilt then two situations
729      a) is rematerialize
730      b) has a spill location */
731   if (sym->isspilt || sym->nRegs == 0)
732     {
733
734       /* rematerialize it NOW */
735       if (sym->remat)
736         {
737           sym->aop = op->aop = aop =
738             aopForRemat (sym);
739           aop->size = getSize (sym->type);
740           return;
741         }
742
743       if (sym->accuse)
744         {
745           int i;
746           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
747           aop->size = getSize (sym->type);
748           for (i = 0; i < 2; i++)
749             aop->aopu.aop_str[i] = accUse[i];
750           return;
751         }
752
753       if (sym->ruonly)
754         {
755           int i;
756
757           if (useDP2)
758             {
759               /* a AOP_STR uses DPTR, but DPTR is already in use;
760                * we're just hosed.
761                */
762               fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
763             }
764
765           aop = op->aop = sym->aop = newAsmop (AOP_STR);
766           aop->size = getSize (sym->type);
767           for (i = 0; i < (int) fReturnSizeDS390; i++)
768             aop->aopu.aop_str[i] = fReturn[i];
769           return;
770         }
771
772       /* else spill location  */
773       sym->aop = op->aop = aop =
774         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
775       aop->size = getSize (sym->type);
776       return;
777     }
778
779   /* must be in a register */
780   sym->aop = op->aop = aop = newAsmop (AOP_REG);
781   aop->size = sym->nRegs;
782   for (i = 0; i < sym->nRegs; i++)
783     aop->aopu.aop_reg[i] = sym->regs[i];
784 }
785
786 /*-----------------------------------------------------------------*/
787 /* freeAsmop - free up the asmop given to an operand               */
788 /*----------------------------------------------------------------*/
789 static void
790 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
791 {
792   asmop *aop;
793
794   if (!op)
795     aop = aaop;
796   else
797     aop = op->aop;
798
799   if (!aop)
800     return;
801
802   if (aop->freed)
803     goto dealloc;
804
805   aop->freed = 1;
806
807   /* depending on the asmop type only three cases need work AOP_RO
808      , AOP_R1 && AOP_STK */
809   switch (aop->type)
810     {
811     case AOP_R0:
812       if (_G.r0Pushed)
813         {
814           if (pop)
815             {
816               emitcode ("pop", "ar0");
817               _G.r0Pushed--;
818             }
819         }
820       bitVectUnSetBit (ic->rUsed, R0_IDX);
821       break;
822
823     case AOP_R1:
824       if (_G.r1Pushed)
825         {
826           if (pop)
827             {
828               emitcode ("pop", "ar1");
829               _G.r1Pushed--;
830             }
831         }
832       bitVectUnSetBit (ic->rUsed, R1_IDX);
833       break;
834
835     case AOP_STK:
836       {
837         int sz = aop->size;
838         int stk = aop->aopu.aop_stk + aop->size;
839         bitVectUnSetBit (ic->rUsed, R0_IDX);
840         bitVectUnSetBit (ic->rUsed, R1_IDX);
841
842         getFreePtr (ic, &aop, FALSE);
843
844         if (options.stack10bit)
845           {
846             /* I'm not sure what to do here yet... */
847             /* #STUB */
848             fprintf (stderr,
849                      "*** Warning: probably generating bad code for "
850                      "10 bit stack mode.\n");
851           }
852
853         if (stk)
854           {
855             emitcode ("mov", "a,_bp");
856             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
857             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
858           }
859         else
860           {
861             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
862           }
863
864         while (sz--)
865           {
866             emitcode ("pop", "acc");
867             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
868             if (!sz)
869               break;
870             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
871           }
872         op->aop = aop;
873         freeAsmop (op, NULL, ic, TRUE);
874         if (_G.r0Pushed)
875           {
876             emitcode ("pop", "ar0");
877             _G.r0Pushed--;
878           }
879
880         if (_G.r1Pushed)
881           {
882             emitcode ("pop", "ar1");
883             _G.r1Pushed--;
884           }
885       }
886     }
887
888 dealloc:
889   /* all other cases just dealloc */
890   if (op)
891     {
892       op->aop = NULL;
893       if (IS_SYMOP (op))
894         {
895           OP_SYMBOL (op)->aop = NULL;
896           /* if the symbol has a spill */
897           if (SPIL_LOC (op))
898             SPIL_LOC (op)->aop = NULL;
899         }
900     }
901 }
902
903 /*------------------------------------------------------------------*/
904 /* aopGet - for fetching value of the aop                           */
905 /*                    */
906 /* Set canClobberACC if you are sure it is OK to clobber the value  */
907 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
908 /* just less efficient.               */
909 /*------------------------------------------------------------------*/
910
911 static char *
912 aopGet (asmop * aop,
913         int offset,
914         bool bit16,
915         bool dname,
916         bool canClobberACC)
917 {
918   char *s = buffer;
919   char *rs;
920
921   /* offset is greater than
922      size then zero */
923   if (offset > (aop->size - 1) &&
924       aop->type != AOP_LIT)
925     return zero;
926
927   /* depending on type */
928   switch (aop->type)
929     {
930
931     case AOP_R0:
932     case AOP_R1:
933       /* if we need to increment it */
934       while (offset > aop->coff)
935         {
936           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
937           aop->coff++;
938         }
939
940       while (offset < aop->coff)
941         {
942           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
943           aop->coff--;
944         }
945
946       aop->coff = offset;
947       if (aop->paged)
948         {
949           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
950           return (dname ? "acc" : "a");
951         }
952       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
953       rs = Safe_calloc (1, strlen (s) + 1);
954       strcpy (rs, s);
955       return rs;
956
957     case AOP_DPTR:
958     case AOP_DPTR2:
959
960       if (aop->type == AOP_DPTR2)
961         {
962           genSetDPTR (1);
963           if (!canClobberACC)
964             {
965               emitcode ("xch", "a, %s", DP2_RESULT_REG);
966             }
967         }
968
969       _flushLazyDPS ();
970
971       while (offset > aop->coff)
972         {
973           emitcode ("inc", "dptr");
974           aop->coff++;
975         }
976
977       while (offset < aop->coff)
978         {
979           emitcode ("lcall", "__decdptr");
980           aop->coff--;
981         }
982
983       aop->coff = offset;
984       if (aop->code)
985         {
986           emitcode ("clr", "a");
987           emitcode ("movc", "a,@a+dptr");
988         }
989       else
990         {
991           emitcode ("movx", "a,@dptr");
992         }
993
994       if (aop->type == AOP_DPTR2)
995         {
996           genSetDPTR (0);
997           if (!canClobberACC)
998             {
999               emitcode ("xch", "a, %s", DP2_RESULT_REG);
1000               return DP2_RESULT_REG;
1001             }
1002         }
1003       return (dname ? "acc" : "a");
1004
1005     case AOP_IMMD:
1006       if (bit16)
1007         sprintf (s, "#%s", aop->aopu.aop_immd);
1008       else if (offset)
1009         sprintf (s, "#(%s >> %d)",
1010                  aop->aopu.aop_immd,
1011                  offset * 8);
1012       else
1013         sprintf (s, "#%s",
1014                  aop->aopu.aop_immd);
1015       rs = Safe_calloc (1, strlen (s) + 1);
1016       strcpy (rs, s);
1017       return rs;
1018
1019     case AOP_DIR:
1020       if (offset)
1021         sprintf (s, "(%s + %d)",
1022                  aop->aopu.aop_dir,
1023                  offset);
1024       else
1025         sprintf (s, "%s", aop->aopu.aop_dir);
1026       rs = Safe_calloc (1, strlen (s) + 1);
1027       strcpy (rs, s);
1028       return rs;
1029
1030     case AOP_REG:
1031       if (dname)
1032         return aop->aopu.aop_reg[offset]->dname;
1033       else
1034         return aop->aopu.aop_reg[offset]->name;
1035
1036     case AOP_CRY:
1037       emitcode ("clr", "a");
1038       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1039       emitcode ("rlc", "a");
1040       return (dname ? "acc" : "a");
1041
1042     case AOP_ACC:
1043       if (!offset && dname)
1044         return "acc";
1045       return aop->aopu.aop_str[offset];
1046
1047     case AOP_LIT:
1048       return aopLiteral (aop->aopu.aop_lit, offset);
1049
1050     case AOP_STR:
1051       aop->coff = offset;
1052       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1053           dname)
1054         return "acc";
1055
1056       return aop->aopu.aop_str[offset];
1057
1058     }
1059
1060   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1061           "aopget got unsupported aop->type");
1062   exit (1);
1063 }
1064 /*-----------------------------------------------------------------*/
1065 /* aopPut - puts a string for a aop                                */
1066 /*-----------------------------------------------------------------*/
1067 static void
1068 aopPut (asmop * aop, char *s, int offset)
1069 {
1070   char *d = buffer;
1071
1072   if (aop->size && offset > (aop->size - 1))
1073     {
1074       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1075               "aopPut got offset > aop->size");
1076       exit (1);
1077     }
1078
1079   /* will assign value to value */
1080   /* depending on where it is ofcourse */
1081   switch (aop->type)
1082     {
1083     case AOP_DIR:
1084       if (offset)
1085         sprintf (d, "(%s + %d)",
1086                  aop->aopu.aop_dir, offset);
1087       else
1088         sprintf (d, "%s", aop->aopu.aop_dir);
1089
1090       if (strcmp (d, s))
1091         emitcode ("mov", "%s,%s", d, s);
1092
1093       break;
1094
1095     case AOP_REG:
1096       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1097           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1098         {
1099           if (*s == '@' ||
1100               strcmp (s, "r0") == 0 ||
1101               strcmp (s, "r1") == 0 ||
1102               strcmp (s, "r2") == 0 ||
1103               strcmp (s, "r3") == 0 ||
1104               strcmp (s, "r4") == 0 ||
1105               strcmp (s, "r5") == 0 ||
1106               strcmp (s, "r6") == 0 ||
1107               strcmp (s, "r7") == 0)
1108             emitcode ("mov", "%s,%s",
1109                       aop->aopu.aop_reg[offset]->dname, s);
1110           else
1111             emitcode ("mov", "%s,%s",
1112                       aop->aopu.aop_reg[offset]->name, s);
1113         }
1114       break;
1115
1116     case AOP_DPTR:
1117     case AOP_DPTR2:
1118
1119       if (aop->type == AOP_DPTR2)
1120         {
1121           genSetDPTR (1);
1122         }
1123       _flushLazyDPS ();
1124
1125       if (aop->code)
1126         {
1127           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1128                   "aopPut writting to code space");
1129           exit (1);
1130         }
1131
1132       while (offset > aop->coff)
1133         {
1134           aop->coff++;
1135           emitcode ("inc", "dptr");
1136         }
1137
1138       while (offset < aop->coff)
1139         {
1140           aop->coff--;
1141           emitcode ("lcall", "__decdptr");
1142         }
1143
1144       aop->coff = offset;
1145
1146       /* if not in accumulater */
1147       MOVA (s);
1148
1149       emitcode ("movx", "@dptr,a");
1150
1151       if (aop->type == AOP_DPTR2)
1152         {
1153           genSetDPTR (0);
1154         }
1155       break;
1156
1157     case AOP_R0:
1158     case AOP_R1:
1159       while (offset > aop->coff)
1160         {
1161           aop->coff++;
1162           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1163         }
1164       while (offset < aop->coff)
1165         {
1166           aop->coff--;
1167           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1168         }
1169       aop->coff = offset;
1170
1171       if (aop->paged)
1172         {
1173           MOVA (s);
1174           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1175
1176         }
1177       else if (*s == '@')
1178         {
1179           MOVA (s);
1180           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1181         }
1182       else if (strcmp (s, "r0") == 0 ||
1183                strcmp (s, "r1") == 0 ||
1184                strcmp (s, "r2") == 0 ||
1185                strcmp (s, "r3") == 0 ||
1186                strcmp (s, "r4") == 0 ||
1187                strcmp (s, "r5") == 0 ||
1188                strcmp (s, "r6") == 0 ||
1189                strcmp (s, "r7") == 0)
1190         {
1191           char buffer[10];
1192           sprintf (buffer, "a%s", s);
1193           emitcode ("mov", "@%s,%s",
1194                     aop->aopu.aop_ptr->name, buffer);
1195         }
1196       else
1197         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1198
1199       break;
1200
1201     case AOP_STK:
1202       if (strcmp (s, "a") == 0)
1203         emitcode ("push", "acc");
1204       else
1205         emitcode ("push", "%s", s);
1206
1207       break;
1208
1209     case AOP_CRY:
1210       /* if bit variable */
1211       if (!aop->aopu.aop_dir)
1212         {
1213           emitcode ("clr", "a");
1214           emitcode ("rlc", "a");
1215         }
1216       else
1217         {
1218           if (s == zero)
1219             emitcode ("clr", "%s", aop->aopu.aop_dir);
1220           else if (s == one)
1221             emitcode ("setb", "%s", aop->aopu.aop_dir);
1222           else if (!strcmp (s, "c"))
1223             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1224           else
1225             {
1226               if (strcmp (s, "a"))
1227                 {
1228                   MOVA (s);
1229                 }
1230               {
1231                 symbol *lbl = newiTempLabel (NULL);
1232                 emitcode ("clr", "c");
1233                 emitcode ("jz", "%05d$", lbl->key + 100);
1234                 emitcode ("cpl", "c");
1235                 emitcode ("", "%05d$:", lbl->key + 100);
1236                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1237               }
1238             }
1239         }
1240       break;
1241
1242     case AOP_STR:
1243       aop->coff = offset;
1244       if (strcmp (aop->aopu.aop_str[offset], s))
1245         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1246       break;
1247
1248     case AOP_ACC:
1249       aop->coff = offset;
1250       if (!offset && (strcmp (s, "acc") == 0))
1251         break;
1252
1253       if (strcmp (aop->aopu.aop_str[offset], s))
1254         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1255       break;
1256
1257     default:
1258       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1259               "aopPut got unsupported aop->type");
1260       exit (1);
1261     }
1262
1263 }
1264
1265
1266 /*--------------------------------------------------------------------*/
1267 /* reAdjustPreg - points a register back to where it should (coff==0) */
1268 /*--------------------------------------------------------------------*/
1269 static void
1270 reAdjustPreg (asmop * aop)
1271 {
1272   if ((aop->coff==0) || (aop->size <= 1)) {
1273     return;
1274   }
1275
1276   switch (aop->type)
1277     {
1278     case AOP_R0:
1279     case AOP_R1:
1280       while (aop->coff--)
1281         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1282       break;
1283     case AOP_DPTR:
1284     case AOP_DPTR2:
1285       if (aop->type == AOP_DPTR2)
1286         {
1287           genSetDPTR (1);
1288           _flushLazyDPS ();
1289         }
1290       while (aop->coff--)
1291         {
1292           emitcode ("lcall", "__decdptr");
1293         }
1294
1295       if (aop->type == AOP_DPTR2)
1296         {
1297           genSetDPTR (0);
1298         }
1299       break;
1300
1301     }
1302   aop->coff=0;
1303 }
1304
1305 #define AOP(op) op->aop
1306 #define AOP_TYPE(op) AOP(op)->type
1307 #define AOP_SIZE(op) AOP(op)->size
1308 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1309                        AOP_TYPE(x) == AOP_R0))
1310
1311 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1312                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1313                          AOP(x)->paged))
1314
1315 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1316                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1317                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1318
1319 /* Workaround for DS80C390 bug: div ab may return bogus results
1320  * if A is accessed in instruction immediately before the div.
1321  *
1322  * Will be fixed in B4 rev of processor, Dallas claims.
1323  */
1324
1325 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1326     if (!AOP_NEEDSACC(RIGHT))         \
1327     {               \
1328       /* We can load A first, then B, since     \
1329        * B (the RIGHT operand) won't clobber A,   \
1330        * thus avoiding touching A right before the div. \
1331        */             \
1332       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1333       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);     \
1334       MOVA(L);            \
1335       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1336     }               \
1337     else              \
1338     {               \
1339       /* Just stuff in a nop after loading A. */    \
1340       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1341       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);   \
1342       MOVA(L);            \
1343       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1344     }
1345
1346 /*-----------------------------------------------------------------*/
1347 /* genNotFloat - generates not for float operations              */
1348 /*-----------------------------------------------------------------*/
1349 static void
1350 genNotFloat (operand * op, operand * res)
1351 {
1352   int size, offset;
1353   char *l;
1354   symbol *tlbl;
1355
1356   D (emitcode (";", "genNotFloat ");
1357     );
1358
1359   /* we will put 127 in the first byte of
1360      the result */
1361   aopPut (AOP (res), "#127", 0);
1362   size = AOP_SIZE (op) - 1;
1363   offset = 1;
1364
1365   _startLazyDPSEvaluation ();
1366   l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1367   MOVA (l);
1368
1369   while (size--)
1370     {
1371       emitcode ("orl", "a,%s",
1372                 aopGet (op->aop,
1373                         offset++, FALSE, FALSE, FALSE));
1374     }
1375   _endLazyDPSEvaluation ();
1376
1377   tlbl = newiTempLabel (NULL);
1378   aopPut (res->aop, one, 1);
1379   emitcode ("jz", "%05d$", (tlbl->key + 100));
1380   aopPut (res->aop, zero, 1);
1381   emitcode ("", "%05d$:", (tlbl->key + 100));
1382
1383   size = res->aop->size - 2;
1384   offset = 2;
1385   /* put zeros in the rest */
1386   while (size--)
1387     aopPut (res->aop, zero, offset++);
1388 }
1389
1390 /*-----------------------------------------------------------------*/
1391 /* opIsGptr: returns non-zero if the passed operand is       */
1392 /* a generic pointer type.             */
1393 /*-----------------------------------------------------------------*/
1394 static int
1395 opIsGptr (operand * op)
1396 {
1397   sym_link *type = operandType (op);
1398
1399   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1400     {
1401       return 1;
1402     }
1403   return 0;
1404 }
1405
1406 /*-----------------------------------------------------------------*/
1407 /* getDataSize - get the operand data size                         */
1408 /*-----------------------------------------------------------------*/
1409 static int
1410 getDataSize (operand * op)
1411 {
1412   int size;
1413   size = AOP_SIZE (op);
1414   if (size == GPTRSIZE)
1415     {
1416       sym_link *type = operandType (op);
1417       if (IS_GENPTR (type))
1418         {
1419           /* generic pointer; arithmetic operations
1420            * should ignore the high byte (pointer type).
1421            */
1422           size--;
1423         }
1424     }
1425   return size;
1426 }
1427
1428 /*-----------------------------------------------------------------*/
1429 /* outAcc - output Acc                                             */
1430 /*-----------------------------------------------------------------*/
1431 static void
1432 outAcc (operand * result)
1433 {
1434   int size, offset;
1435   size = getDataSize (result);
1436   if (size)
1437     {
1438       aopPut (AOP (result), "a", 0);
1439       size--;
1440       offset = 1;
1441       /* unsigned or positive */
1442       while (size--)
1443         {
1444           aopPut (AOP (result), zero, offset++);
1445         }
1446     }
1447 }
1448
1449 /*-----------------------------------------------------------------*/
1450 /* outBitC - output a bit C                                        */
1451 /*-----------------------------------------------------------------*/
1452 static void
1453 outBitC (operand * result)
1454 {
1455   /* if the result is bit */
1456   if (AOP_TYPE (result) == AOP_CRY)
1457     {
1458       aopPut (AOP (result), "c", 0);
1459     }
1460   else
1461     {
1462       emitcode ("clr", "a");
1463       emitcode ("rlc", "a");
1464       outAcc (result);
1465     }
1466 }
1467
1468 /*-----------------------------------------------------------------*/
1469 /* toBoolean - emit code for orl a,operator(sizeop)                */
1470 /*-----------------------------------------------------------------*/
1471 static void
1472 toBoolean (operand * oper)
1473 {
1474   int   size = AOP_SIZE (oper) - 1;
1475   int   offset = 1;
1476   bool usedB = FALSE;
1477
1478   /* The generic part of a generic pointer should
1479    * not participate in it's truth value.
1480    *
1481    * i.e. 0x10000000 is zero.
1482    */
1483   if (opIsGptr (oper))
1484     {
1485       D (emitcode (";", "toBoolean: generic ptr special case.");
1486         );
1487       size--;
1488     }
1489
1490   _startLazyDPSEvaluation ();
1491   if (AOP_NEEDSACC (oper) && size)
1492     {
1493       usedB = TRUE;
1494       emitcode ("push", "b");
1495       emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1496     }
1497   else
1498     {
1499       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1500     }
1501   while (size--)
1502     {
1503       if (usedB)
1504         {
1505           emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1506         }
1507       else
1508         {
1509           emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1510         }
1511     }
1512   _endLazyDPSEvaluation ();
1513
1514   if (usedB)
1515     {
1516       emitcode ("mov", "a,b");
1517       emitcode ("pop", "b");
1518     }
1519 }
1520
1521
1522 /*-----------------------------------------------------------------*/
1523 /* genNot - generate code for ! operation                          */
1524 /*-----------------------------------------------------------------*/
1525 static void
1526 genNot (iCode * ic)
1527 {
1528   symbol *tlbl;
1529   sym_link *optype = operandType (IC_LEFT (ic));
1530
1531   D (emitcode (";", "genNot ");
1532     );
1533
1534   /* assign asmOps to operand & result */
1535   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1536   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1537
1538   /* if in bit space then a special case */
1539   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1540     {
1541       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1542       emitcode ("cpl", "c");
1543       outBitC (IC_RESULT (ic));
1544       goto release;
1545     }
1546
1547   /* if type float then do float */
1548   if (IS_FLOAT (optype))
1549     {
1550       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1551       goto release;
1552     }
1553
1554   toBoolean (IC_LEFT (ic));
1555
1556   tlbl = newiTempLabel (NULL);
1557   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1558   emitcode ("", "%05d$:", tlbl->key + 100);
1559   outBitC (IC_RESULT (ic));
1560
1561 release:
1562   /* release the aops */
1563   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1564   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1565 }
1566
1567
1568 /*-----------------------------------------------------------------*/
1569 /* genCpl - generate code for complement                           */
1570 /*-----------------------------------------------------------------*/
1571 static void
1572 genCpl (iCode * ic)
1573 {
1574   int offset = 0;
1575   int size;
1576
1577   D (emitcode (";", "genCpl ");
1578     );
1579
1580
1581   /* assign asmOps to operand & result */
1582   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1583   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1584
1585   /* if both are in bit space then
1586      a special case */
1587   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1588       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1589     {
1590
1591       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1592       emitcode ("cpl", "c");
1593       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1594       goto release;
1595     }
1596
1597   size = AOP_SIZE (IC_RESULT (ic));
1598   _startLazyDPSEvaluation ();
1599   while (size--)
1600     {
1601       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1602       MOVA (l);
1603       emitcode ("cpl", "a");
1604       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1605     }
1606   _endLazyDPSEvaluation ();
1607
1608
1609 release:
1610   /* release the aops */
1611   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1612   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1613 }
1614
1615 /*-----------------------------------------------------------------*/
1616 /* genUminusFloat - unary minus for floating points                */
1617 /*-----------------------------------------------------------------*/
1618 static void
1619 genUminusFloat (operand * op, operand * result)
1620 {
1621   int size, offset = 0;
1622   char *l;
1623   /* for this we just need to flip the
1624      first it then copy the rest in place */
1625   D (emitcode (";", "genUminusFloat");
1626     );
1627
1628   _startLazyDPSEvaluation ();
1629   size = AOP_SIZE (op) - 1;
1630   l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1631   MOVA (l);
1632
1633   emitcode ("cpl", "acc.7");
1634   aopPut (AOP (result), "a", 3);
1635
1636   while (size--)
1637     {
1638       aopPut (AOP (result),
1639               aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1640               offset);
1641       offset++;
1642     }
1643   _endLazyDPSEvaluation ();
1644 }
1645
1646 /*-----------------------------------------------------------------*/
1647 /* genUminus - unary minus code generation                         */
1648 /*-----------------------------------------------------------------*/
1649 static void
1650 genUminus (iCode * ic)
1651 {
1652   int offset, size;
1653   sym_link *optype, *rtype;
1654
1655   D (emitcode (";", "genUminus ");
1656     );
1657
1658
1659   /* assign asmops */
1660   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1661   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1662
1663   /* if both in bit space then special
1664      case */
1665   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1666       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1667     {
1668
1669       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1670       emitcode ("cpl", "c");
1671       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1672       goto release;
1673     }
1674
1675   optype = operandType (IC_LEFT (ic));
1676   rtype = operandType (IC_RESULT (ic));
1677
1678   /* if float then do float stuff */
1679   if (IS_FLOAT (optype))
1680     {
1681       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1682       goto release;
1683     }
1684
1685   /* otherwise subtract from zero */
1686   size = AOP_SIZE (IC_LEFT (ic));
1687   offset = 0;
1688   _startLazyDPSEvaluation ();
1689   while (size--)
1690     {
1691       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1692       if (!strcmp (l, "a"))
1693         {
1694           if (offset == 0)
1695             SETC;
1696           emitcode ("cpl", "a");
1697           emitcode ("addc", "a,#0");
1698         }
1699       else
1700         {
1701           if (offset == 0)
1702             CLRC;
1703           emitcode ("clr", "a");
1704           emitcode ("subb", "a,%s", l);
1705         }
1706       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1707     }
1708   _endLazyDPSEvaluation ();
1709
1710   /* if any remaining bytes in the result */
1711   /* we just need to propagate the sign   */
1712   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1713     {
1714       emitcode ("rlc", "a");
1715       emitcode ("subb", "a,acc");
1716       while (size--)
1717         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1718     }
1719
1720 release:
1721   /* release the aops */
1722   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1723   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1724 }
1725
1726 /*-----------------------------------------------------------------*/
1727 /* saveRegisters - will look for a call and save the registers     */
1728 /*-----------------------------------------------------------------*/
1729 static void
1730 saveRegisters (iCode * lic)
1731 {
1732   int i;
1733   iCode *ic;
1734   bitVect *rsave;
1735   sym_link *detype;
1736
1737   /* look for call */
1738   for (ic = lic; ic; ic = ic->next)
1739     if (ic->op == CALL || ic->op == PCALL)
1740       break;
1741
1742   if (!ic)
1743     {
1744       fprintf (stderr, "found parameter push with no function call\n");
1745       return;
1746     }
1747
1748   /* if the registers have been saved already then
1749      do nothing */
1750   if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1751     return;
1752
1753   /* find the registers in use at this time
1754      and push them away to safety */
1755   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1756                          ic->rUsed);
1757
1758   ic->regsSaved = 1;
1759   if (options.useXstack)
1760     {
1761       if (bitVectBitValue (rsave, R0_IDX))
1762         emitcode ("mov", "b,r0");
1763       emitcode ("mov", "r0,%s", spname);
1764       for (i = 0; i < ds390_nRegs; i++)
1765         {
1766           if (bitVectBitValue (rsave, i))
1767             {
1768               if (i == R0_IDX)
1769                 emitcode ("mov", "a,b");
1770               else
1771                 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1772               emitcode ("movx", "@r0,a");
1773               emitcode ("inc", "r0");
1774             }
1775         }
1776       emitcode ("mov", "%s,r0", spname);
1777       if (bitVectBitValue (rsave, R0_IDX))
1778         emitcode ("mov", "r0,b");
1779     }
1780   else
1781     for (i = 0; i < ds390_nRegs; i++)
1782       {
1783         if (bitVectBitValue (rsave, i))
1784           emitcode ("push", "%s ;jwk saveRegisters", ds390_regWithIdx (i)->dname);
1785       }
1786
1787   detype = getSpec (operandType (IC_LEFT (ic)));
1788   if (detype &&
1789       (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1790       IS_ISR (currFunc->etype) &&
1791       !ic->bankSaved)
1792
1793     saverbank (SPEC_BANK (detype), ic, TRUE);
1794
1795 }
1796 /*-----------------------------------------------------------------*/
1797 /* unsaveRegisters - pop the pushed registers                      */
1798 /*-----------------------------------------------------------------*/
1799 static void
1800 unsaveRegisters (iCode * ic)
1801 {
1802   int i;
1803   bitVect *rsave;
1804   /* find the registers in use at this time
1805      and push them away to safety */
1806   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1807                          ic->rUsed);
1808
1809   if (options.useXstack)
1810     {
1811       emitcode ("mov", "r0,%s", spname);
1812       for (i = ds390_nRegs; i >= 0; i--)
1813         {
1814           if (bitVectBitValue (rsave, i))
1815             {
1816               emitcode ("dec", "r0");
1817               emitcode ("movx", "a,@r0");
1818               if (i == R0_IDX)
1819                 emitcode ("mov", "b,a");
1820               else
1821                 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1822             }
1823
1824         }
1825       emitcode ("mov", "%s,r0", spname);
1826       if (bitVectBitValue (rsave, R0_IDX))
1827         emitcode ("mov", "r0,b");
1828     }
1829   else
1830     for (i = ds390_nRegs; i >= 0; i--)
1831       {
1832         if (bitVectBitValue (rsave, i))
1833           emitcode ("pop", "%s ;jwk unsaveRegisters", ds390_regWithIdx (i)->dname);
1834       }
1835
1836 }
1837
1838
1839 /*-----------------------------------------------------------------*/
1840 /* pushSide -                */
1841 /*-----------------------------------------------------------------*/
1842 static void
1843 pushSide (operand * oper, int size)
1844 {
1845   int offset = 0;
1846   _startLazyDPSEvaluation ();
1847   while (size--)
1848     {
1849       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1850       if (AOP_TYPE (oper) != AOP_REG &&
1851           AOP_TYPE (oper) != AOP_DIR &&
1852           strcmp (l, "a"))
1853         {
1854           emitcode ("mov", "a,%s", l);
1855           emitcode ("push", "acc");
1856         }
1857       else
1858         emitcode ("push", "%s", l);
1859     }
1860   _endLazyDPSEvaluation ();
1861 }
1862
1863 /*-----------------------------------------------------------------*/
1864 /* assignResultValue -               */
1865 /*-----------------------------------------------------------------*/
1866 static void
1867 assignResultValue (operand * oper)
1868 {
1869   int offset = 0;
1870   int size = AOP_SIZE (oper);
1871
1872   _startLazyDPSEvaluation ();
1873   while (size--)
1874     {
1875       aopPut (AOP (oper), fReturn[offset], offset);
1876       offset++;
1877     }
1878   _endLazyDPSEvaluation ();
1879 }
1880
1881
1882 /*-----------------------------------------------------------------*/
1883 /* genXpush - pushes onto the external stack                       */
1884 /*-----------------------------------------------------------------*/
1885 static void
1886 genXpush (iCode * ic)
1887 {
1888   asmop *aop = newAsmop (0);
1889   regs *r;
1890   int size, offset = 0;
1891
1892   D (emitcode (";", "genXpush ");
1893     );
1894
1895   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1896   r = getFreePtr (ic, &aop, FALSE);
1897
1898
1899   emitcode ("mov", "%s,_spx", r->name);
1900
1901   size = AOP_SIZE (IC_LEFT (ic));
1902   _startLazyDPSEvaluation ();
1903   while (size--)
1904     {
1905
1906       char *l = aopGet (AOP (IC_LEFT (ic)),
1907                         offset++, FALSE, FALSE, TRUE);
1908       MOVA (l);
1909       emitcode ("movx", "@%s,a", r->name);
1910       emitcode ("inc", "%s", r->name);
1911
1912     }
1913   _endLazyDPSEvaluation ();
1914
1915
1916   emitcode ("mov", "_spx,%s", r->name);
1917
1918   freeAsmop (NULL, aop, ic, TRUE);
1919   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1920 }
1921
1922 /*-----------------------------------------------------------------*/
1923 /* genIpush - genrate code for pushing this gets a little complex  */
1924 /*-----------------------------------------------------------------*/
1925 static void
1926 genIpush (iCode * ic)
1927 {
1928   int size, offset = 0;
1929   char *l;
1930
1931   D (emitcode (";", "genIpush ");
1932     );
1933
1934   /* if this is not a parm push : ie. it is spill push
1935      and spill push is always done on the local stack */
1936   if (!ic->parmPush)
1937     {
1938
1939       /* and the item is spilt then do nothing */
1940       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1941         return;
1942
1943       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1944       size = AOP_SIZE (IC_LEFT (ic));
1945       /* push it on the stack */
1946       _startLazyDPSEvaluation ();
1947       while (size--)
1948         {
1949           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1950           if (*l == '#')
1951             {
1952               MOVA (l);
1953               l = "acc";
1954             }
1955           emitcode ("push", "%s ;jwk genIpush: !parm", l);
1956         }
1957       _endLazyDPSEvaluation ();
1958       return;
1959     }
1960
1961   /* this is a paramter push: in this case we call
1962      the routine to find the call and save those
1963      registers that need to be saved */
1964   saveRegisters (ic);
1965
1966   /* if use external stack then call the external
1967      stack pushing routine */
1968   if (options.useXstack)
1969     {
1970       genXpush (ic);
1971       return;
1972     }
1973
1974   /* then do the push */
1975   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1976
1977   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1978   size = AOP_SIZE (IC_LEFT (ic));
1979
1980   _startLazyDPSEvaluation ();
1981   while (size--)
1982     {
1983       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
1984       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1985           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1986           strcmp (l, "a"))
1987         {
1988           emitcode ("mov", "a,%s", l);
1989           emitcode ("push", "acc");
1990         }
1991       else
1992         emitcode ("push", "%s ;jwk genIpush", l);
1993     }
1994   _endLazyDPSEvaluation ();
1995
1996   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1997 }
1998
1999 /*-----------------------------------------------------------------*/
2000 /* genIpop - recover the registers: can happen only for spilling   */
2001 /*-----------------------------------------------------------------*/
2002 static void
2003 genIpop (iCode * ic)
2004 {
2005   int size, offset;
2006
2007   D (emitcode (";", "genIpop ");
2008     );
2009
2010
2011   /* if the temp was not pushed then */
2012   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2013     return;
2014
2015   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2016   size = AOP_SIZE (IC_LEFT (ic));
2017   offset = (size - 1);
2018   _startLazyDPSEvaluation ();
2019   while (size--)
2020     {
2021       emitcode ("pop", "%s ;jwk genIpop", aopGet (AOP (IC_LEFT (ic)), offset--,
2022                                      FALSE, TRUE, TRUE));
2023     }
2024   _endLazyDPSEvaluation ();
2025
2026   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2027 }
2028
2029 /*-----------------------------------------------------------------*/
2030 /* unsaverbank - restores the resgister bank from stack            */
2031 /*-----------------------------------------------------------------*/
2032 static void
2033 unsaverbank (int bank, iCode * ic, bool popPsw)
2034 {
2035   int i;
2036   asmop *aop;
2037   regs *r = NULL;
2038
2039   if (popPsw)
2040     {
2041       if (options.useXstack)
2042         {
2043           aop = newAsmop (0);
2044           r = getFreePtr (ic, &aop, FALSE);
2045
2046
2047           emitcode ("mov", "%s,_spx", r->name);
2048           emitcode ("movx", "a,@%s", r->name);
2049           emitcode ("mov", "psw,a");
2050           emitcode ("dec", "%s", r->name);
2051
2052         }
2053       else
2054         emitcode ("pop", "psw");
2055     }
2056
2057   for (i = (ds390_nRegs - 1); i >= 0; i--)
2058     {
2059       if (options.useXstack)
2060         {
2061           emitcode ("movx", "a,@%s", r->name);
2062           emitcode ("mov", "(%s+%d),a",
2063                     regs390[i].base, 8 * bank + regs390[i].offset);
2064           emitcode ("dec", "%s", r->name);
2065
2066         }
2067       else
2068         emitcode ("pop", "(%s+%d)",
2069                   regs390[i].base, 8 * bank + regs390[i].offset);
2070     }
2071
2072   if (options.useXstack)
2073     {
2074
2075       emitcode ("mov", "_spx,%s", r->name);
2076       freeAsmop (NULL, aop, ic, TRUE);
2077
2078     }
2079 }
2080
2081 /*-----------------------------------------------------------------*/
2082 /* saverbank - saves an entire register bank on the stack          */
2083 /*-----------------------------------------------------------------*/
2084 static void
2085 saverbank (int bank, iCode * ic, bool pushPsw)
2086 {
2087   int i;
2088   asmop *aop;
2089   regs *r = NULL;
2090
2091   if (options.useXstack)
2092     {
2093
2094       aop = newAsmop (0);
2095       r = getFreePtr (ic, &aop, FALSE);
2096       emitcode ("mov", "%s,_spx", r->name);
2097
2098     }
2099
2100   for (i = 0; i < ds390_nRegs; i++)
2101     {
2102       if (options.useXstack)
2103         {
2104           emitcode ("inc", "%s", r->name);
2105           emitcode ("mov", "a,(%s+%d)",
2106                     regs390[i].base, 8 * bank + regs390[i].offset);
2107           emitcode ("movx", "@%s,a", r->name);
2108         }
2109       else
2110         emitcode ("push", "(%s+%d)",
2111                   regs390[i].base, 8 * bank + regs390[i].offset);
2112     }
2113
2114   if (pushPsw)
2115     {
2116       if (options.useXstack)
2117         {
2118           emitcode ("mov", "a,psw");
2119           emitcode ("movx", "@%s,a", r->name);
2120           emitcode ("inc", "%s", r->name);
2121           emitcode ("mov", "_spx,%s", r->name);
2122           freeAsmop (NULL, aop, ic, TRUE);
2123
2124         }
2125       else
2126         emitcode ("push", "psw");
2127
2128       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2129     }
2130   ic->bankSaved = 1;
2131
2132 }
2133
2134 /*-----------------------------------------------------------------*/
2135 /* genCall - generates a call statement                            */
2136 /*-----------------------------------------------------------------*/
2137 static void
2138 genCall (iCode * ic)
2139 {
2140   sym_link *detype;
2141
2142   D (emitcode (";", "genCall ");
2143     );
2144
2145   /* if caller saves & we have not saved then */
2146   if (!ic->regsSaved)
2147     saveRegisters (ic);
2148
2149   /* if we are calling a function that is not using
2150      the same register bank then we need to save the
2151      destination registers on the stack */
2152   detype = getSpec (operandType (IC_LEFT (ic)));
2153   if (detype &&
2154       (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2155       IS_ISR (currFunc->etype) &&
2156       !ic->bankSaved)
2157
2158     saverbank (SPEC_BANK (detype), ic, TRUE);
2159
2160   /* if send set is not empty the assign */
2161   if (_G.sendSet)
2162     {
2163       iCode *sic;
2164
2165       for (sic = setFirstItem (_G.sendSet); sic;
2166            sic = setNextItem (_G.sendSet))
2167         {
2168           int size, offset = 0;
2169
2170           aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2171           size = AOP_SIZE (IC_LEFT (sic));
2172
2173           _startLazyDPSEvaluation ();
2174           while (size--)
2175             {
2176               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2177                                 FALSE, FALSE, TRUE);
2178               if (strcmp (l, fReturn[offset])) {
2179                 genSetDPTR(0);
2180                 _flushLazyDPS();
2181                 emitcode ("mov", "%s,%s ;jwk lazy genCall",
2182                           fReturn[offset],
2183                           l);
2184               }
2185               offset++;
2186             }
2187           _endLazyDPSEvaluation ();
2188           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2189         }
2190       _G.sendSet = NULL;
2191     }
2192   /* make the call */
2193   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2194                             OP_SYMBOL (IC_LEFT (ic))->rname :
2195                             OP_SYMBOL (IC_LEFT (ic))->name));
2196
2197   /* if we need assign a result value */
2198   if ((IS_ITEMP (IC_RESULT (ic)) &&
2199        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2200         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2201       IS_TRUE_SYMOP (IC_RESULT (ic)))
2202     {
2203       if (isOperandInFarSpace (IC_RESULT (ic))
2204           && getSize (operandType (IC_RESULT (ic))) <= 2)
2205         {
2206           int size = getSize (operandType (IC_RESULT (ic)));
2207
2208           /* Special case for 1 or 2 byte return in far space. */
2209           emitcode (";", "Kevin function call abuse #1");
2210
2211           MOVA (fReturn[0]);
2212           if (size > 1)
2213             {
2214               emitcode ("mov", "b,%s", fReturn[1]);
2215             }
2216
2217           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2218           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2219
2220           if (size > 1)
2221             {
2222               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2223             }
2224           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2225         }
2226       else
2227         {
2228           _G.accInUse++;
2229           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2230           _G.accInUse--;
2231
2232           assignResultValue (IC_RESULT (ic));
2233
2234           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2235         }
2236     }
2237
2238   /* adjust the stack for parameters if
2239      required */
2240   if (ic->parmBytes)
2241     {
2242       int i;
2243       if (ic->parmBytes > 3)
2244         {
2245           emitcode ("mov", "a,%s", spname);
2246           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2247           emitcode ("mov", "%s,a", spname);
2248         }
2249       else
2250         for (i = 0; i < ic->parmBytes; i++)
2251           emitcode ("dec", "%s", spname);
2252
2253     }
2254
2255   /* if register bank was saved then pop them */
2256   if (ic->bankSaved)
2257     unsaverbank (SPEC_BANK (detype), ic, TRUE);
2258
2259   /* if we hade saved some registers then unsave them */
2260   if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2261     unsaveRegisters (ic);
2262
2263
2264 }
2265
2266 /*-----------------------------------------------------------------*/
2267 /* genPcall - generates a call by pointer statement                */
2268 /*-----------------------------------------------------------------*/
2269 static void
2270 genPcall (iCode * ic)
2271 {
2272   sym_link *detype;
2273   symbol *rlbl = newiTempLabel (NULL);
2274
2275   D (emitcode (";", "genPcall ");
2276     );
2277
2278
2279   /* if caller saves & we have not saved then */
2280   if (!ic->regsSaved)
2281     saveRegisters (ic);
2282
2283   /* if we are calling a function that is not using
2284      the same register bank then we need to save the
2285      destination registers on the stack */
2286   detype = getSpec (operandType (IC_LEFT (ic)));
2287   if (detype &&
2288       IS_ISR (currFunc->etype) &&
2289       (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2290     saverbank (SPEC_BANK (detype), ic, TRUE);
2291
2292
2293   /* push the return address on to the stack */
2294   emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2295   emitcode ("push", "acc");
2296   emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2297   emitcode ("push", "acc");
2298
2299   if (options.model == MODEL_FLAT24)
2300     {
2301       emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2302       emitcode ("push", "acc");
2303     }
2304
2305   /* now push the calling address */
2306   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2307
2308   pushSide (IC_LEFT (ic), FPTRSIZE);
2309
2310   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2311
2312   /* if send set is not empty the assign */
2313   if (_G.sendSet)
2314     {
2315       iCode *sic;
2316
2317       for (sic = setFirstItem (_G.sendSet); sic;
2318            sic = setNextItem (_G.sendSet))
2319         {
2320           int size, offset = 0;
2321
2322           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2323           size = AOP_SIZE (IC_LEFT (sic));
2324           _startLazyDPSEvaluation ();
2325           while (size--)
2326             {
2327               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2328                                 FALSE, FALSE, TRUE);
2329               if (strcmp (l, fReturn[offset]))
2330                 {
2331                   emitcode ("mov", "%s,%s",
2332                             fReturn[offset],
2333                             l);
2334                 }
2335               offset++;
2336             }
2337           _endLazyDPSEvaluation ();
2338           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2339         }
2340       _G.sendSet = NULL;
2341     }
2342
2343   emitcode ("ret", "");
2344   emitcode ("", "%05d$:", (rlbl->key + 100));
2345
2346
2347   /* if we need assign a result value */
2348   if ((IS_ITEMP (IC_RESULT (ic)) &&
2349        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2350         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2351       IS_TRUE_SYMOP (IC_RESULT (ic)))
2352     {
2353
2354       _G.accInUse++;
2355       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2356       _G.accInUse--;
2357
2358       assignResultValue (IC_RESULT (ic));
2359
2360       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2361     }
2362
2363   /* adjust the stack for parameters if
2364      required */
2365   if (ic->parmBytes)
2366     {
2367       int i;
2368       if (ic->parmBytes > 3)
2369         {
2370           emitcode ("mov", "a,%s", spname);
2371           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2372           emitcode ("mov", "%s,a", spname);
2373         }
2374       else
2375         for (i = 0; i < ic->parmBytes; i++)
2376           emitcode ("dec", "%s", spname);
2377
2378     }
2379
2380   /* if register bank was saved then unsave them */
2381   if (detype &&
2382       (SPEC_BANK (currFunc->etype) !=
2383        SPEC_BANK (detype)))
2384     unsaverbank (SPEC_BANK (detype), ic, TRUE);
2385
2386   /* if we hade saved some registers then
2387      unsave them */
2388   if (ic->regsSaved)
2389     unsaveRegisters (ic);
2390
2391 }
2392
2393 /*-----------------------------------------------------------------*/
2394 /* resultRemat - result  is rematerializable                       */
2395 /*-----------------------------------------------------------------*/
2396 static int
2397 resultRemat (iCode * ic)
2398 {
2399   if (SKIP_IC (ic) || ic->op == IFX)
2400     return 0;
2401
2402   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2403     {
2404       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2405       if (sym->remat && !POINTER_SET (ic))
2406         return 1;
2407     }
2408
2409   return 0;
2410 }
2411
2412 #if defined(__BORLANDC__) || defined(_MSC_VER)
2413 #define STRCASECMP stricmp
2414 #else
2415 #define STRCASECMP strcasecmp
2416 #endif
2417
2418 /*-----------------------------------------------------------------*/
2419 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2420 /*-----------------------------------------------------------------*/
2421 static bool
2422 inExcludeList (char *s)
2423 {
2424   int i = 0;
2425
2426   if (options.excludeRegs[i] &&
2427       STRCASECMP (options.excludeRegs[i], "none") == 0)
2428     return FALSE;
2429
2430   for (i = 0; options.excludeRegs[i]; i++)
2431     {
2432       if (options.excludeRegs[i] &&
2433           STRCASECMP (s, options.excludeRegs[i]) == 0)
2434         return TRUE;
2435     }
2436   return FALSE;
2437 }
2438
2439 /*-----------------------------------------------------------------*/
2440 /* genFunction - generated code for function entry                 */
2441 /*-----------------------------------------------------------------*/
2442 static void
2443 genFunction (iCode * ic)
2444 {
2445   symbol *sym;
2446   sym_link *fetype;
2447
2448   D (emitcode (";", "genFunction ");
2449     );
2450
2451   _G.nRegsSaved = 0;
2452   /* create the function header */
2453   emitcode (";", "-----------------------------------------");
2454   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2455   emitcode (";", "-----------------------------------------");
2456
2457   emitcode ("", "%s:", sym->rname);
2458   fetype = getSpec (operandType (IC_LEFT (ic)));
2459
2460   /* if critical function then turn interrupts off */
2461   if (SPEC_CRTCL (fetype))
2462     emitcode ("clr", "ea");
2463
2464   /* here we need to generate the equates for the
2465      register bank if required */
2466   if (SPEC_BANK (fetype) != rbank)
2467     {
2468       int i;
2469
2470       rbank = SPEC_BANK (fetype);
2471       for (i = 0; i < ds390_nRegs; i++)
2472         {
2473           if (strcmp (regs390[i].base, "0") == 0)
2474             emitcode ("", "%s = 0x%02x",
2475                       regs390[i].dname,
2476                       8 * rbank + regs390[i].offset);
2477           else
2478             emitcode ("", "%s = %s + 0x%02x",
2479                       regs390[i].dname,
2480                       regs390[i].base,
2481                       8 * rbank + regs390[i].offset);
2482         }
2483     }
2484
2485   /* if this is an interrupt service routine then
2486      save acc, b, dpl, dph  */
2487   if (IS_ISR (sym->etype))
2488     {
2489
2490       if (!inExcludeList ("acc"))
2491         emitcode ("push", "acc");
2492       if (!inExcludeList ("b"))
2493         emitcode ("push", "b");
2494       if (!inExcludeList ("dpl"))
2495         emitcode ("push", "dpl");
2496       if (!inExcludeList ("dph"))
2497         emitcode ("push", "dph");
2498       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2499         {
2500           emitcode ("push", "dpx");
2501           /* Make sure we're using standard DPTR */
2502           emitcode ("push", "dps");
2503           emitcode ("mov", "dps, #0x00");
2504           if (options.stack10bit)
2505             {
2506               /* This ISR could conceivably use DPTR2. Better save it. */
2507               emitcode ("push", "dpl1");
2508               emitcode ("push", "dph1");
2509               emitcode ("push", "dpx1");
2510               emitcode ("push",  DP2_RESULT_REG);
2511             }
2512         }
2513       /* if this isr has no bank i.e. is going to
2514          run with bank 0 , then we need to save more
2515          registers :-) */
2516       if (!SPEC_BANK (sym->etype))
2517         {
2518
2519           /* if this function does not call any other
2520              function then we can be economical and
2521              save only those registers that are used */
2522           if (!sym->hasFcall)
2523             {
2524               int i;
2525
2526               /* if any registers used */
2527               if (sym->regsUsed)
2528                 {
2529                   /* save the registers used */
2530                   for (i = 0; i < sym->regsUsed->size; i++)
2531                     {
2532                       if (bitVectBitValue (sym->regsUsed, i) ||
2533                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2534                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2535                     }
2536                 }
2537
2538             }
2539           else
2540             {
2541               /* this function has  a function call cannot
2542                  determines register usage so we will have the
2543                  entire bank */
2544               saverbank (0, ic, FALSE);
2545             }
2546         }
2547     }
2548   else
2549     {
2550       /* if callee-save to be used for this function
2551          then save the registers being used in this function */
2552       if (sym->calleeSave)
2553         {
2554           int i;
2555
2556           /* if any registers used */
2557           if (sym->regsUsed)
2558             {
2559               /* save the registers used */
2560               for (i = 0; i < sym->regsUsed->size; i++)
2561                 {
2562                   if (bitVectBitValue (sym->regsUsed, i) ||
2563                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2564                     {
2565                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2566                       _G.nRegsSaved++;
2567                     }
2568                 }
2569             }
2570         }
2571     }
2572
2573   /* set the register bank to the desired value */
2574   if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2575     {
2576       emitcode ("push", "psw");
2577       emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2578     }
2579
2580   if (IS_RENT (sym->etype) || options.stackAuto)
2581     {
2582
2583       if (options.useXstack)
2584         {
2585           emitcode ("mov", "r0,%s", spname);
2586           emitcode ("mov", "a,_bp");
2587           emitcode ("movx", "@r0,a");
2588           emitcode ("inc", "%s", spname);
2589         }
2590       else
2591         {
2592           /* set up the stack */
2593           emitcode ("push", "_bp");     /* save the callers stack  */
2594         }
2595       emitcode ("mov", "_bp,%s", spname);
2596     }
2597
2598   /* adjust the stack for the function */
2599   if (sym->stack)
2600     {
2601
2602       int i = sym->stack;
2603       if (i > 256)
2604         werror (W_STACK_OVERFLOW, sym->name);
2605
2606       if (i > 3 && sym->recvSize < 4)
2607         {
2608
2609           emitcode ("mov", "a,sp");
2610           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2611           emitcode ("mov", "sp,a");
2612
2613         }
2614       else
2615         while (i--)
2616           emitcode ("inc", "sp");
2617     }
2618
2619   if (sym->xstack)
2620     {
2621
2622       emitcode ("mov", "a,_spx");
2623       emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2624       emitcode ("mov", "_spx,a");
2625     }
2626
2627 }
2628
2629 /*-----------------------------------------------------------------*/
2630 /* genEndFunction - generates epilogue for functions               */
2631 /*-----------------------------------------------------------------*/
2632 static void
2633 genEndFunction (iCode * ic)
2634 {
2635   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2636
2637   D (emitcode (";", "genEndFunction ");
2638     );
2639
2640   if (IS_RENT (sym->etype) || options.stackAuto)
2641     {
2642       emitcode ("mov", "%s,_bp", spname);
2643     }
2644
2645   /* if use external stack but some variables were
2646      added to the local stack then decrement the
2647      local stack */
2648   if (options.useXstack && sym->stack)
2649     {
2650       emitcode ("mov", "a,sp");
2651       emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2652       emitcode ("mov", "sp,a");
2653     }
2654
2655
2656   if ((IS_RENT (sym->etype) || options.stackAuto))
2657     {
2658       if (options.useXstack)
2659         {
2660           emitcode ("mov", "r0,%s", spname);
2661           emitcode ("movx", "a,@r0");
2662           emitcode ("mov", "_bp,a");
2663           emitcode ("dec", "%s", spname);
2664         }
2665       else
2666         {
2667           emitcode ("pop", "_bp");
2668         }
2669     }
2670
2671   /* restore the register bank  */
2672   if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2673     emitcode ("pop", "psw");
2674
2675   if (IS_ISR (sym->etype))
2676     {
2677
2678       /* now we need to restore the registers */
2679       /* if this isr has no bank i.e. is going to
2680          run with bank 0 , then we need to save more
2681          registers :-) */
2682       if (!SPEC_BANK (sym->etype))
2683         {
2684
2685           /* if this function does not call any other
2686              function then we can be economical and
2687              save only those registers that are used */
2688           if (!sym->hasFcall)
2689             {
2690               int i;
2691
2692               /* if any registers used */
2693               if (sym->regsUsed)
2694                 {
2695                   /* save the registers used */
2696                   for (i = sym->regsUsed->size; i >= 0; i--)
2697                     {
2698                       if (bitVectBitValue (sym->regsUsed, i) ||
2699                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2700                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2701                     }
2702                 }
2703
2704             }
2705           else
2706             {
2707               /* this function has  a function call cannot
2708                  determines register usage so we will have the
2709                  entire bank */
2710               unsaverbank (0, ic, FALSE);
2711             }
2712         }
2713
2714       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2715         {
2716           if (options.stack10bit)
2717             {
2718               emitcode ("pop", DP2_RESULT_REG);
2719               emitcode ("pop", "dpx1");
2720               emitcode ("pop", "dph1");
2721               emitcode ("pop", "dpl1");
2722             }
2723           emitcode ("pop", "dps");
2724           emitcode ("pop", "dpx");
2725         }
2726       if (!inExcludeList ("dph"))
2727         emitcode ("pop", "dph");
2728       if (!inExcludeList ("dpl"))
2729         emitcode ("pop", "dpl");
2730       if (!inExcludeList ("b"))
2731         emitcode ("pop", "b");
2732       if (!inExcludeList ("acc"))
2733         emitcode ("pop", "acc");
2734
2735       if (SPEC_CRTCL (sym->etype))
2736         emitcode ("setb", "ea");
2737
2738       /* if debug then send end of function */
2739 /*  if (options.debug && currFunc) { */
2740       if (currFunc)
2741         {
2742           _G.debugLine = 1;
2743           emitcode ("", "C$%s$%d$%d$%d ==.",
2744                     FileBaseName (ic->filename), currFunc->lastLine,
2745                     ic->level, ic->block);
2746           if (IS_STATIC (currFunc->etype))
2747             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2748           else
2749             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2750           _G.debugLine = 0;
2751         }
2752
2753       emitcode ("reti", "");
2754     }
2755   else
2756     {
2757       if (SPEC_CRTCL (sym->etype))
2758         emitcode ("setb", "ea");
2759
2760       if (sym->calleeSave)
2761         {
2762           int i;
2763
2764           /* if any registers used */
2765           if (sym->regsUsed)
2766             {
2767               /* save the registers used */
2768               for (i = sym->regsUsed->size; i >= 0; i--)
2769                 {
2770                   if (bitVectBitValue (sym->regsUsed, i) ||
2771                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2772                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2773                 }
2774             }
2775
2776         }
2777
2778       /* if debug then send end of function */
2779       if (currFunc)
2780         {
2781           _G.debugLine = 1;
2782           emitcode ("", "C$%s$%d$%d$%d ==.",
2783                     FileBaseName (ic->filename), currFunc->lastLine,
2784                     ic->level, ic->block);
2785           if (IS_STATIC (currFunc->etype))
2786             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2787           else
2788             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2789           _G.debugLine = 0;
2790         }
2791
2792       emitcode ("ret", "");
2793     }
2794
2795 }
2796
2797 /*-----------------------------------------------------------------*/
2798 /* genRet - generate code for return statement                     */
2799 /*-----------------------------------------------------------------*/
2800 static void
2801 genRet (iCode * ic)
2802 {
2803   int size, offset = 0, pushed = 0;
2804
2805   D (emitcode (";", "genRet ");
2806     );
2807
2808   /* if we have no return value then
2809      just generate the "ret" */
2810   if (!IC_LEFT (ic))
2811     goto jumpret;
2812
2813   /* we have something to return then
2814      move the return value into place */
2815   aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2816   size = AOP_SIZE (IC_LEFT (ic));
2817
2818   _startLazyDPSEvaluation ();
2819   while (size--)
2820     {
2821       char *l;
2822       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2823         {
2824           l = aopGet (AOP (IC_LEFT (ic)), offset++,
2825                       FALSE, TRUE, FALSE);
2826           emitcode ("push", "%s", l);
2827           pushed++;
2828         }
2829       else
2830         {
2831           l = aopGet (AOP (IC_LEFT (ic)), offset,
2832                       FALSE, FALSE, FALSE);
2833           if (strcmp (fReturn[offset], l))
2834             emitcode ("mov", "%s,%s", fReturn[offset++], l);
2835         }
2836     }
2837   _endLazyDPSEvaluation ();
2838
2839   if (pushed)
2840     {
2841       while (pushed)
2842         {
2843           pushed--;
2844           if (strcmp (fReturn[pushed], "a"))
2845             emitcode ("pop", fReturn[pushed]);
2846           else
2847             emitcode ("pop", "acc");
2848         }
2849     }
2850   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2851
2852 jumpret:
2853   /* generate a jump to the return label
2854      if the next is not the return statement */
2855   if (!(ic->next && ic->next->op == LABEL &&
2856         IC_LABEL (ic->next) == returnLabel))
2857
2858     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2859
2860 }
2861
2862 /*-----------------------------------------------------------------*/
2863 /* genLabel - generates a label                                    */
2864 /*-----------------------------------------------------------------*/
2865 static void
2866 genLabel (iCode * ic)
2867 {
2868   /* special case never generate */
2869   if (IC_LABEL (ic) == entryLabel)
2870     return;
2871
2872   D (emitcode (";", "genLabel ");
2873     );
2874
2875   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2876 }
2877
2878 /*-----------------------------------------------------------------*/
2879 /* genGoto - generates a ljmp                                      */
2880 /*-----------------------------------------------------------------*/
2881 static void
2882 genGoto (iCode * ic)
2883 {
2884   D (emitcode (";", "genGoto ");
2885     );
2886   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2887 }
2888
2889 /*-----------------------------------------------------------------*/
2890 /* findLabelBackwards: walks back through the iCode chain looking  */
2891 /* for the given label. Returns number of iCode instructions     */
2892 /* between that label and given ic.          */
2893 /* Returns zero if label not found.          */
2894 /*-----------------------------------------------------------------*/
2895 static int
2896 findLabelBackwards (iCode * ic, int key)
2897 {
2898   int count = 0;
2899
2900   while (ic->prev)
2901     {
2902       ic = ic->prev;
2903       count++;
2904
2905       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2906         {
2907           /* printf("findLabelBackwards = %d\n", count); */
2908           return count;
2909         }
2910     }
2911
2912   return 0;
2913 }
2914
2915 /*-----------------------------------------------------------------*/
2916 /* genPlusIncr :- does addition with increment if possible         */
2917 /*-----------------------------------------------------------------*/
2918 static bool
2919 genPlusIncr (iCode * ic)
2920 {
2921   unsigned int icount;
2922   unsigned int size = getDataSize (IC_RESULT (ic));
2923
2924   /* will try to generate an increment */
2925   /* if the right side is not a literal
2926      we cannot */
2927   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2928     return FALSE;
2929
2930   /* if the literal value of the right hand side
2931      is greater than 4 then it is not worth it */
2932   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2933     return FALSE;
2934
2935   /* if increment 16 bits in register */
2936   if (
2937        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
2938        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
2939        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2940        (size > 1) &&
2941        (icount == 1))
2942     {
2943       symbol *tlbl;
2944       int emitTlbl;
2945       int labelRange;
2946
2947       /* If the next instruction is a goto and the goto target
2948        * is <= 5 instructions previous to this, we can generate
2949        * jumps straight to that target.
2950        */
2951       if (ic->next && ic->next->op == GOTO
2952           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2953           && labelRange <= 5)
2954         {
2955           emitcode (";", "tail increment optimized (range %d)", labelRange);
2956           tlbl = IC_LABEL (ic->next);
2957           emitTlbl = 0;
2958         }
2959       else
2960         {
2961           tlbl = newiTempLabel (NULL);
2962           emitTlbl = 1;
2963         }
2964       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
2965       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2966           IS_AOP_PREG (IC_RESULT (ic)))
2967         emitcode ("cjne", "%s,#0x00,%05d$"
2968                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2969                   ,tlbl->key + 100);
2970       else
2971         {
2972           emitcode ("clr", "a");
2973           emitcode ("cjne", "a,%s,%05d$"
2974                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2975                     ,tlbl->key + 100);
2976         }
2977
2978       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
2979       if (size > 2)
2980         {
2981           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2982               IS_AOP_PREG (IC_RESULT (ic)))
2983             emitcode ("cjne", "%s,#0x00,%05d$"
2984                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2985                       ,tlbl->key + 100);
2986           else
2987             emitcode ("cjne", "a,%s,%05d$"
2988                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2989                       ,tlbl->key + 100);
2990
2991           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
2992         }
2993       if (size > 3)
2994         {
2995           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2996               IS_AOP_PREG (IC_RESULT (ic)))
2997             emitcode ("cjne", "%s,#0x00,%05d$"
2998                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
2999                       ,tlbl->key + 100);
3000           else
3001             {
3002               emitcode ("cjne", "a,%s,%05d$"
3003                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3004                         ,tlbl->key + 100);
3005             }
3006           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3007         }
3008
3009       if (emitTlbl)
3010         {
3011           emitcode ("", "%05d$:", tlbl->key + 100);
3012         }
3013       return TRUE;
3014     }
3015
3016   /* if the sizes are greater than 1 then we cannot */
3017   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3018       AOP_SIZE (IC_LEFT (ic)) > 1)
3019     return FALSE;
3020
3021   /* we can if the aops of the left & result match or
3022      if they are in registers and the registers are the
3023      same */
3024   if (
3025        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3026        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3027        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3028     {
3029
3030       if (icount > 3)
3031         {
3032           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3033           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3034           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3035         }
3036       else
3037         {
3038
3039           _startLazyDPSEvaluation ();
3040           while (icount--)
3041             {
3042               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3043             }
3044           _endLazyDPSEvaluation ();
3045         }
3046
3047       return TRUE;
3048     }
3049
3050   return FALSE;
3051 }
3052
3053 /*-----------------------------------------------------------------*/
3054 /* outBitAcc - output a bit in acc                                 */
3055 /*-----------------------------------------------------------------*/
3056 static void
3057 outBitAcc (operand * result)
3058 {
3059   symbol *tlbl = newiTempLabel (NULL);
3060   /* if the result is a bit */
3061   if (AOP_TYPE (result) == AOP_CRY)
3062     {
3063       aopPut (AOP (result), "a", 0);
3064     }
3065   else
3066     {
3067       emitcode ("jz", "%05d$", tlbl->key + 100);
3068       emitcode ("mov", "a,%s", one);
3069       emitcode ("", "%05d$:", tlbl->key + 100);
3070       outAcc (result);
3071     }
3072 }
3073
3074 /*-----------------------------------------------------------------*/
3075 /* genPlusBits - generates code for addition of two bits           */
3076 /*-----------------------------------------------------------------*/
3077 static void
3078 genPlusBits (iCode * ic)
3079 {
3080   D (emitcode (";", "genPlusBits ");
3081     );
3082   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3083     {
3084       symbol *lbl = newiTempLabel (NULL);
3085       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3086       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3087       emitcode ("cpl", "c");
3088       emitcode ("", "%05d$:", (lbl->key + 100));
3089       outBitC (IC_RESULT (ic));
3090     }
3091   else
3092     {
3093       emitcode ("clr", "a");
3094       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3095       emitcode ("rlc", "a");
3096       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3097       emitcode ("addc", "a,#0x00");
3098       outAcc (IC_RESULT (ic));
3099     }
3100 }
3101
3102 static void
3103 adjustArithmeticResult (iCode * ic)
3104 {
3105   if (opIsGptr (IC_RESULT (ic)) &&
3106       opIsGptr (IC_LEFT (ic)) &&
3107       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3108     {
3109       aopPut (AOP (IC_RESULT (ic)),
3110               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3111               GPTRSIZE - 1);
3112     }
3113
3114   if (opIsGptr (IC_RESULT (ic)) &&
3115       opIsGptr (IC_RIGHT (ic)) &&
3116       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3117     {
3118       aopPut (AOP (IC_RESULT (ic)),
3119             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3120               GPTRSIZE - 1);
3121     }
3122
3123   if (opIsGptr (IC_RESULT (ic)) &&
3124       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3125       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3126       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3127       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3128     {
3129       char buffer[5];
3130       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3131       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3132     }
3133 }
3134
3135 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3136 // (because all three operands are in far space).
3137 #define AOP_OP_3(ic) \
3138     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3139     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3140     aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3141               (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3142     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3143         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3144     { \
3145         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3146         fprintf(stderr,                                  \
3147                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3148     }
3149
3150 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3151 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3152 // will be set TRUE. The caller must then handle the case specially, noting
3153 // that the IC_RESULT operand is not aopOp'd.
3154 #define AOP_OP_3_NOFATAL(ic, rc) \
3155     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3156     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3157     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3158         isOperandInFarSpace(IC_RESULT(ic))) \
3159     { \
3160        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3161        rc = TRUE; \
3162     }  \
3163     else \
3164     { \
3165        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3166                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3167        rc = FALSE; \
3168        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3169            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3170        { \
3171             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3172             fprintf(stderr,                                  \
3173                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3174        } \
3175     }
3176
3177 // aopOp the left & right operands of an ic.
3178 #define AOP_OP_2(ic) \
3179     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3180     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3181
3182 // convienience macro.
3183 #define AOP_SET_LOCALS(ic) \
3184     left = IC_LEFT(ic); \
3185     right = IC_RIGHT(ic); \
3186     result = IC_RESULT(ic);
3187
3188
3189 // Given an integer value of pushedSize bytes on the stack,
3190 // adjust it to be resultSize bytes, either by discarding
3191 // the most significant bytes or by zero-padding.
3192 //
3193 // On exit from this macro, pushedSize will have been adjusted to
3194 // equal resultSize, and ACC may be trashed.
3195 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3196       /* If the pushed data is bigger than the result,          \
3197        * simply discard unused bytes. Icky, but works.          \
3198        */                                                       \
3199       while (pushedSize > resultSize)                           \
3200       {                                                         \
3201           D (emitcode (";", "discarding unused result byte."););\
3202           emitcode ("pop", "acc");                              \
3203           pushedSize--;                                         \
3204       }                                                         \
3205       if (pushedSize < resultSize)                              \
3206       {                                                         \
3207           emitcode ("clr", "a");                                \
3208           /* Conversly, we haven't pushed enough here.          \
3209            * just zero-pad, and all is well.                    \
3210            */                                                   \
3211           while (pushedSize < resultSize)                       \
3212           {                                                     \
3213               emitcode("push", "acc");                          \
3214               pushedSize++;                                     \
3215           }                                                     \
3216       }                                                         \
3217       assert(pushedSize == resultSize);
3218
3219 /*-----------------------------------------------------------------*/
3220 /* genPlus - generates code for addition                           */
3221 /*-----------------------------------------------------------------*/
3222 static void
3223 genPlus (iCode * ic)
3224 {
3225   int size, offset = 0;
3226   bool pushResult = FALSE;
3227   int rSize;
3228
3229   D (emitcode (";", "genPlus "););
3230
3231   /* special cases :- */
3232
3233   AOP_OP_3_NOFATAL (ic, pushResult);
3234   if (pushResult)
3235     {
3236       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3237     }
3238
3239   if (!pushResult)
3240     {
3241       /* if literal, literal on the right or
3242          if left requires ACC or right is already
3243          in ACC */
3244       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3245        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3246           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3247         {
3248           operand *t = IC_RIGHT (ic);
3249           IC_RIGHT (ic) = IC_LEFT (ic);
3250           IC_LEFT (ic) = t;
3251           emitcode (";", "Swapped plus args.");
3252         }
3253
3254       /* if both left & right are in bit
3255          space */
3256       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3257           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3258         {
3259           genPlusBits (ic);
3260           goto release;
3261         }
3262
3263       /* if left in bit space & right literal */
3264       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3265           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3266         {
3267           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3268           /* if result in bit space */
3269           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3270             {
3271               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3272                 emitcode ("cpl", "c");
3273               outBitC (IC_RESULT (ic));
3274             }
3275           else
3276             {
3277               size = getDataSize (IC_RESULT (ic));
3278               _startLazyDPSEvaluation ();
3279               while (size--)
3280                 {
3281                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3282                   emitcode ("addc", "a,#00");
3283                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3284                 }
3285               _endLazyDPSEvaluation ();
3286             }
3287           goto release;
3288         }
3289
3290       /* if I can do an increment instead
3291          of add then GOOD for ME */
3292       if (genPlusIncr (ic) == TRUE)
3293         {
3294           emitcode (";", "did genPlusIncr");
3295           goto release;
3296         }
3297
3298     }
3299   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3300
3301   _startLazyDPSEvaluation ();
3302   while (size--)
3303     {
3304       if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3305         {
3306           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3307           if (offset == 0)
3308             emitcode ("add", "a,%s",
3309                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3310           else
3311             emitcode ("addc", "a,%s",
3312                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3313         }
3314       else
3315         {
3316           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3317           if (offset == 0)
3318             emitcode ("add", "a,%s",
3319                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3320           else
3321             emitcode ("addc", "a,%s",
3322                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3323         }
3324       if (!pushResult)
3325         {
3326           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3327         }
3328       else
3329         {
3330           emitcode ("push", "acc");
3331         }
3332       offset++;
3333     }
3334   _endLazyDPSEvaluation ();
3335
3336   if (pushResult)
3337     {
3338       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3339
3340       size = getDataSize (IC_LEFT (ic));
3341       rSize = getDataSize (IC_RESULT (ic));
3342
3343       ADJUST_PUSHED_RESULT(size, rSize);
3344
3345       _startLazyDPSEvaluation ();
3346       while (size--)
3347         {
3348           emitcode ("pop", "acc");
3349           aopPut (AOP (IC_RESULT (ic)), "a", size);
3350         }
3351       _endLazyDPSEvaluation ();
3352     }
3353
3354   adjustArithmeticResult (ic);
3355
3356 release:
3357   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3358   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3359   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3360 }
3361
3362 /*-----------------------------------------------------------------*/
3363 /* genMinusDec :- does subtraction with deccrement if possible     */
3364 /*-----------------------------------------------------------------*/
3365 static bool
3366 genMinusDec (iCode * ic)
3367 {
3368   unsigned int icount;
3369   unsigned int size = getDataSize (IC_RESULT (ic));
3370
3371   /* will try to generate an increment */
3372   /* if the right side is not a literal
3373      we cannot */
3374   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3375     return FALSE;
3376
3377   /* if the literal value of the right hand side
3378      is greater than 4 then it is not worth it */
3379   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3380     return FALSE;
3381
3382   /* if decrement 16 bits in register */
3383   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3384       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3385       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3386       (size > 1) &&
3387       (icount == 1))
3388     {
3389       symbol *tlbl;
3390       int emitTlbl;
3391       int labelRange;
3392
3393       /* If the next instruction is a goto and the goto target
3394          * is <= 5 instructions previous to this, we can generate
3395          * jumps straight to that target.
3396        */
3397       if (ic->next && ic->next->op == GOTO
3398           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3399           && labelRange <= 5)
3400         {
3401           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3402           tlbl = IC_LABEL (ic->next);
3403           emitTlbl = 0;
3404         }
3405       else
3406         {
3407           tlbl = newiTempLabel (NULL);
3408           emitTlbl = 1;
3409         }
3410
3411       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3412       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3413           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3414           IS_AOP_PREG (IC_RESULT (ic)))
3415         emitcode ("cjne", "%s,#0xff,%05d$"
3416                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3417                   ,tlbl->key + 100);
3418       else
3419         {
3420           emitcode ("mov", "a,#0xff");
3421           emitcode ("cjne", "a,%s,%05d$"
3422                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3423                     ,tlbl->key + 100);
3424         }
3425       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3426       if (size > 2)
3427         {
3428           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3429               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3430               IS_AOP_PREG (IC_RESULT (ic)))
3431             emitcode ("cjne", "%s,#0xff,%05d$"
3432                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3433                       ,tlbl->key + 100);
3434           else
3435             {
3436               emitcode ("cjne", "a,%s,%05d$"
3437                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3438                         ,tlbl->key + 100);
3439             }
3440           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3441         }
3442       if (size > 3)
3443         {
3444           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3445               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3446               IS_AOP_PREG (IC_RESULT (ic)))
3447             emitcode ("cjne", "%s,#0xff,%05d$"
3448                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3449                       ,tlbl->key + 100);
3450           else
3451             {
3452               emitcode ("cjne", "a,%s,%05d$"
3453                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3454                         ,tlbl->key + 100);
3455             }
3456           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3457         }
3458       if (emitTlbl)
3459         {
3460           emitcode ("", "%05d$:", tlbl->key + 100);
3461         }
3462       return TRUE;
3463     }
3464
3465   /* if the sizes are greater than 1 then we cannot */
3466   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3467       AOP_SIZE (IC_LEFT (ic)) > 1)
3468     return FALSE;
3469
3470   /* we can if the aops of the left & result match or
3471      if they are in registers and the registers are the
3472      same */
3473   if (
3474        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3475        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3476        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3477     {
3478
3479       _startLazyDPSEvaluation ();
3480       while (icount--)
3481         {
3482           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3483         }
3484       _endLazyDPSEvaluation ();
3485
3486       return TRUE;
3487     }
3488
3489   return FALSE;
3490 }
3491
3492 /*-----------------------------------------------------------------*/
3493 /* addSign - complete with sign                                    */
3494 /*-----------------------------------------------------------------*/
3495 static void
3496 addSign (operand * result, int offset, int sign)
3497 {
3498   int size = (getDataSize (result) - offset);
3499   if (size > 0)
3500     {
3501       if (sign)
3502         {
3503           emitcode ("rlc", "a");
3504           emitcode ("subb", "a,acc");
3505           while (size--)
3506             aopPut (AOP (result), "a", offset++);
3507         }
3508       else
3509         while (size--)
3510           aopPut (AOP (result), zero, offset++);
3511     }
3512 }
3513
3514 /*-----------------------------------------------------------------*/
3515 /* genMinusBits - generates code for subtraction  of two bits      */
3516 /*-----------------------------------------------------------------*/
3517 static void
3518 genMinusBits (iCode * ic)
3519 {
3520   symbol *lbl = newiTempLabel (NULL);
3521
3522   D (emitcode (";", "genMinusBits ");
3523     );
3524
3525   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3526     {
3527       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3528       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3529       emitcode ("cpl", "c");
3530       emitcode ("", "%05d$:", (lbl->key + 100));
3531       outBitC (IC_RESULT (ic));
3532     }
3533   else
3534     {
3535       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3536       emitcode ("subb", "a,acc");
3537       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3538       emitcode ("inc", "a");
3539       emitcode ("", "%05d$:", (lbl->key + 100));
3540       aopPut (AOP (IC_RESULT (ic)), "a", 0);
3541       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3542     }
3543 }
3544
3545 /*-----------------------------------------------------------------*/
3546 /* genMinus - generates code for subtraction                       */
3547 /*-----------------------------------------------------------------*/
3548 static void
3549 genMinus (iCode * ic)
3550 {
3551   int size, offset = 0;
3552   int rSize;
3553   unsigned long lit = 0L;
3554   bool pushResult = FALSE;
3555
3556   D (emitcode (";", "genMinus "););
3557
3558   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3559   aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3560   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3561       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3562     {
3563       pushResult = TRUE;
3564     }
3565   else
3566     {
3567       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3568
3569       /* special cases :- */
3570       /* if both left & right are in bit space */
3571       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3572           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3573         {
3574           genMinusBits (ic);
3575           goto release;
3576         }
3577
3578       /* if I can do an decrement instead
3579          of subtract then GOOD for ME */
3580       if (genMinusDec (ic) == TRUE)
3581         goto release;
3582
3583     }
3584
3585   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3586
3587   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3588     {
3589       CLRC;
3590     }
3591   else
3592     {
3593       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3594       lit = -(long) lit;
3595     }
3596
3597
3598   /* if literal, add a,#-lit, else normal subb */
3599   _startLazyDPSEvaluation ();
3600   while (size--)
3601     {
3602       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3603       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3604         emitcode ("subb", "a,%s",
3605                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3606       else
3607         {
3608           /* first add without previous c */
3609           if (!offset)
3610             emitcode ("add", "a,#0x%02x",
3611                       (unsigned int) (lit & 0x0FFL));
3612           else
3613             emitcode ("addc", "a,#0x%02x",
3614                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3615         }
3616
3617       if (pushResult)
3618         {
3619           emitcode ("push", "acc");
3620         }
3621       else
3622         {
3623           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3624         }
3625       offset++;
3626     }
3627   _endLazyDPSEvaluation ();
3628
3629   if (pushResult)
3630     {
3631       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3632
3633       size = getDataSize (IC_LEFT (ic));
3634       rSize = getDataSize (IC_RESULT (ic));
3635
3636       ADJUST_PUSHED_RESULT(size, rSize);
3637
3638       _startLazyDPSEvaluation ();
3639       while (size--)
3640         {
3641           emitcode ("pop", "acc");
3642           aopPut (AOP (IC_RESULT (ic)), "a", size);
3643         }
3644       _endLazyDPSEvaluation ();
3645     }
3646
3647   adjustArithmeticResult (ic);
3648
3649 release:
3650   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3651   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3652   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3653 }
3654
3655
3656 /*-----------------------------------------------------------------*/
3657 /* genMultbits :- multiplication of bits                           */
3658 /*-----------------------------------------------------------------*/
3659 static void
3660 genMultbits (operand * left,
3661              operand * right,
3662              operand * result)
3663 {
3664   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3665   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3666   outBitC (result);
3667 }
3668
3669
3670 /*-----------------------------------------------------------------*/
3671 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
3672 /*-----------------------------------------------------------------*/
3673 static void
3674 genMultOneByte (operand * left,
3675                 operand * right,
3676                 operand * result)
3677 {
3678   sym_link *opetype = operandType (result);
3679   symbol *lbl;
3680   int size=AOP_SIZE(result);
3681
3682   emitcode (";",__FUNCTION__);
3683   if (size<1 || size>2) {
3684     // this should never happen
3685       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
3686                AOP_SIZE(result), __FUNCTION__, lineno);
3687       exit (1);
3688   }
3689
3690   /* (if two literals: the value is computed before) */
3691   /* if one literal, literal on the right */
3692   if (AOP_TYPE (left) == AOP_LIT)
3693     {
3694       operand *t = right;
3695       right = left;
3696       left = t;
3697       emitcode (";", "swapped left and right");
3698     }
3699
3700   if (SPEC_USIGN(opetype)
3701       // ignore the sign of left and right, what else can we do?
3702       || (SPEC_USIGN(operandType(left)) && 
3703           SPEC_USIGN(operandType(right)))) {
3704     // just an unsigned 8*8=8/16 multiply
3705     //emitcode (";","unsigned");
3706     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3707     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3708     emitcode ("mul", "ab");
3709     aopPut (AOP (result), "a", 0);
3710     if (size==2) {
3711       aopPut (AOP (result), "b", 1);
3712     }
3713     return;
3714   }
3715
3716   // we have to do a signed multiply
3717
3718   emitcode (";", "signed");
3719   emitcode ("clr", "F0"); // reset sign flag
3720   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3721   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3722
3723   lbl=newiTempLabel(NULL);
3724   emitcode ("jnb", "acc.7,%05d$",  lbl->key+100);
3725   // left side is negative, 8-bit two's complement, this fails for -128
3726   emitcode ("setb", "F0"); // set sign flag
3727   emitcode ("cpl", "a");
3728   emitcode ("inc", "a");
3729
3730   emitcode ("", "%05d$:", lbl->key+100);
3731   emitcode ("xch", "a,b");
3732
3733   /* if literal */
3734   if (AOP_TYPE(right)==AOP_LIT) {
3735     /* AND literal negative */
3736     if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3737       // two's complement for literal<0
3738       emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3739       emitcode ("cpl", "a");
3740       emitcode ("inc", "a");
3741     }
3742   } else {
3743     lbl=newiTempLabel(NULL);
3744     emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3745     // right side is negative, 8-bit two's complement
3746     emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3747     emitcode ("cpl", "a");
3748     emitcode ("inc", "a");
3749     emitcode ("", "%05d$:", lbl->key+100);
3750   }
3751   emitcode ("mul", "ab");
3752     
3753   lbl=newiTempLabel(NULL);
3754   emitcode ("jnb", "F0,%05d$", lbl->key+100);
3755   // only ONE op was negative, we have to do a 8/16-bit two's complement
3756   emitcode ("cpl", "a"); // lsb
3757   if (size==1) {
3758     emitcode ("inc", "a");
3759   } else {
3760     emitcode ("add", "a,#1");
3761     emitcode ("xch", "a,b");
3762     emitcode ("cpl", "a"); // msb
3763     emitcode ("addc", "a,#0");
3764     emitcode ("xch", "a,b");
3765   }
3766
3767   emitcode ("", "%05d$:", lbl->key+100);
3768   aopPut (AOP (result), "a", 0);
3769   if (size==2) {
3770     aopPut (AOP (result), "b", 1);
3771   }
3772 }
3773
3774 /*-----------------------------------------------------------------*/
3775 /* genMult - generates code for multiplication                     */
3776 /*-----------------------------------------------------------------*/
3777 static void
3778 genMult (iCode * ic)
3779 {
3780   operand *left = IC_LEFT (ic);
3781   operand *right = IC_RIGHT (ic);
3782   operand *result = IC_RESULT (ic);
3783
3784   D (emitcode (";", "genMult "););
3785
3786   /* assign the amsops */
3787   AOP_OP_3 (ic);
3788
3789   /* special cases first */
3790   /* both are bits */
3791   if (AOP_TYPE (left) == AOP_CRY &&
3792       AOP_TYPE (right) == AOP_CRY)
3793     {
3794       genMultbits (left, right, result);
3795       goto release;
3796     }
3797
3798   /* if both are of size == 1 */
3799   if (AOP_SIZE (left) == 1 &&
3800       AOP_SIZE (right) == 1)
3801     {
3802       genMultOneByte (left, right, result);
3803       goto release;
3804     }
3805
3806   /* should have been converted to function call */
3807   assert (1);
3808
3809 release:
3810   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3811   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3812   freeAsmop (result, NULL, ic, TRUE);
3813 }
3814
3815 /*-----------------------------------------------------------------*/
3816 /* genDivbits :- division of bits                                  */
3817 /*-----------------------------------------------------------------*/
3818 static void
3819 genDivbits (operand * left,
3820             operand * right,
3821             operand * result)
3822 {
3823
3824   char *l;
3825
3826   /* the result must be bit */
3827   LOAD_AB_FOR_DIV (left, right, l);
3828   emitcode ("div", "ab");
3829   emitcode ("rrc", "a");
3830   aopPut (AOP (result), "c", 0);
3831 }
3832
3833 /*-----------------------------------------------------------------*/
3834 /* genDivOneByte : 8 bit division                                  */
3835 /*-----------------------------------------------------------------*/
3836 static void
3837 genDivOneByte (operand * left,
3838                operand * right,
3839                operand * result)
3840 {
3841   sym_link *opetype = operandType (result);
3842   char *l;
3843   symbol *lbl;
3844   int size, offset;
3845
3846   size = AOP_SIZE (result) - 1;
3847   offset = 1;
3848   /* signed or unsigned */
3849   if (SPEC_USIGN (opetype))
3850     {
3851       /* unsigned is easy */
3852       LOAD_AB_FOR_DIV (left, right, l);
3853       emitcode ("div", "ab");
3854       aopPut (AOP (result), "a", 0);
3855       while (size--)
3856         aopPut (AOP (result), zero, offset++);
3857       return;
3858     }
3859
3860   /* signed is a little bit more difficult */
3861
3862   /* save the signs of the operands */
3863   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3864   MOVA (l);
3865   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3866   emitcode ("push", "acc");     /* save it on the stack */
3867
3868   /* now sign adjust for both left & right */
3869   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3870   MOVA (l);
3871   lbl = newiTempLabel (NULL);
3872   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3873   emitcode ("cpl", "a");
3874   emitcode ("inc", "a");
3875   emitcode ("", "%05d$:", (lbl->key + 100));
3876   emitcode ("mov", "b,a");
3877
3878   /* sign adjust left side */
3879   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3880   MOVA (l);
3881
3882   lbl = newiTempLabel (NULL);
3883   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3884   emitcode ("cpl", "a");
3885   emitcode ("inc", "a");
3886   emitcode ("", "%05d$:", (lbl->key + 100));
3887
3888   /* now the division */
3889   emitcode ("nop", "; workaround for DS80C390 div bug.");
3890   emitcode ("div", "ab");
3891   /* we are interested in the lower order
3892      only */
3893   emitcode ("mov", "b,a");
3894   lbl = newiTempLabel (NULL);
3895   emitcode ("pop", "acc");
3896   /* if there was an over flow we don't
3897      adjust the sign of the result */
3898   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3899   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3900   CLRC;
3901   emitcode ("clr", "a");
3902   emitcode ("subb", "a,b");
3903   emitcode ("mov", "b,a");
3904   emitcode ("", "%05d$:", (lbl->key + 100));
3905
3906   /* now we are done */
3907   aopPut (AOP (result), "b", 0);
3908   if (size > 0)
3909     {
3910       emitcode ("mov", "c,b.7");
3911       emitcode ("subb", "a,acc");
3912     }
3913   while (size--)
3914     aopPut (AOP (result), "a", offset++);
3915
3916 }
3917
3918 /*-----------------------------------------------------------------*/
3919 /* genDiv - generates code for division                            */
3920 /*-----------------------------------------------------------------*/
3921 static void
3922 genDiv (iCode * ic)
3923 {
3924   operand *left = IC_LEFT (ic);
3925   operand *right = IC_RIGHT (ic);
3926   operand *result = IC_RESULT (ic);
3927
3928   D (emitcode (";", "genDiv ");
3929     );
3930
3931   /* assign the amsops */
3932   AOP_OP_3 (ic);
3933
3934   /* special cases first */
3935   /* both are bits */
3936   if (AOP_TYPE (left) == AOP_CRY &&
3937       AOP_TYPE (right) == AOP_CRY)
3938     {
3939       genDivbits (left, right, result);
3940       goto release;
3941     }
3942
3943   /* if both are of size == 1 */
3944   if (AOP_SIZE (left) == 1 &&
3945       AOP_SIZE (right) == 1)
3946     {
3947       genDivOneByte (left, right, result);
3948       goto release;
3949     }
3950
3951   /* should have been converted to function call */
3952   assert (1);
3953 release:
3954   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3955   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3956   freeAsmop (result, NULL, ic, TRUE);
3957 }
3958
3959 /*-----------------------------------------------------------------*/
3960 /* genModbits :- modulus of bits                                   */
3961 /*-----------------------------------------------------------------*/
3962 static void
3963 genModbits (operand * left,
3964             operand * right,
3965             operand * result)
3966 {
3967
3968   char *l;
3969
3970   /* the result must be bit */
3971   LOAD_AB_FOR_DIV (left, right, l);
3972   emitcode ("div", "ab");
3973   emitcode ("mov", "a,b");
3974   emitcode ("rrc", "a");
3975   aopPut (AOP (result), "c", 0);
3976 }
3977
3978 /*-----------------------------------------------------------------*/
3979 /* genModOneByte : 8 bit modulus                                   */
3980 /*-----------------------------------------------------------------*/
3981 static void
3982 genModOneByte (operand * left,
3983                operand * right,
3984                operand * result)
3985 {
3986   sym_link *opetype = operandType (result);
3987   char *l;
3988   symbol *lbl;
3989
3990   /* signed or unsigned */
3991   if (SPEC_USIGN (opetype))
3992     {
3993       /* unsigned is easy */
3994       LOAD_AB_FOR_DIV (left, right, l);
3995       emitcode ("div", "ab");
3996       aopPut (AOP (result), "b", 0);
3997       return;
3998     }
3999
4000   /* signed is a little bit more difficult */
4001
4002   /* save the signs of the operands */
4003   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4004   MOVA (l);
4005
4006   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4007   emitcode ("push", "acc");     /* save it on the stack */
4008
4009   /* now sign adjust for both left & right */
4010   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4011   MOVA (l);
4012
4013   lbl = newiTempLabel (NULL);
4014   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4015   emitcode ("cpl", "a");
4016   emitcode ("inc", "a");
4017   emitcode ("", "%05d$:", (lbl->key + 100));
4018   emitcode ("mov", "b,a");
4019
4020   /* sign adjust left side */
4021   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4022   MOVA (l);
4023
4024   lbl = newiTempLabel (NULL);
4025   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4026   emitcode ("cpl", "a");
4027   emitcode ("inc", "a");
4028   emitcode ("", "%05d$:", (lbl->key + 100));
4029
4030   /* now the multiplication */
4031   emitcode ("nop", "; workaround for DS80C390 div bug.");
4032   emitcode ("div", "ab");
4033   /* we are interested in the lower order
4034      only */
4035   lbl = newiTempLabel (NULL);
4036   emitcode ("pop", "acc");
4037   /* if there was an over flow we don't
4038      adjust the sign of the result */
4039   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4040   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4041   CLRC;
4042   emitcode ("clr", "a");
4043   emitcode ("subb", "a,b");
4044   emitcode ("mov", "b,a");
4045   emitcode ("", "%05d$:", (lbl->key + 100));
4046
4047   /* now we are done */
4048   aopPut (AOP (result), "b", 0);
4049
4050 }
4051
4052 /*-----------------------------------------------------------------*/
4053 /* genMod - generates code for division                            */
4054 /*-----------------------------------------------------------------*/
4055 static void
4056 genMod (iCode * ic)
4057 {
4058   operand *left = IC_LEFT (ic);
4059   operand *right = IC_RIGHT (ic);
4060   operand *result = IC_RESULT (ic);
4061
4062   D (emitcode (";", "genMod ");
4063     );
4064
4065   /* assign the amsops */
4066   AOP_OP_3 (ic);
4067
4068   /* special cases first */
4069   /* both are bits */
4070   if (AOP_TYPE (left) == AOP_CRY &&
4071       AOP_TYPE (right) == AOP_CRY)
4072     {
4073       genModbits (left, right, result);
4074       goto release;
4075     }
4076
4077   /* if both are of size == 1 */
4078   if (AOP_SIZE (left) == 1 &&
4079       AOP_SIZE (right) == 1)
4080     {
4081       genModOneByte (left, right, result);
4082       goto release;
4083     }
4084
4085   /* should have been converted to function call */
4086   assert (1);
4087
4088 release:
4089   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4090   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4091   freeAsmop (result, NULL, ic, TRUE);
4092 }
4093
4094 /*-----------------------------------------------------------------*/
4095 /* genIfxJump :- will create a jump depending on the ifx           */
4096 /*-----------------------------------------------------------------*/
4097 static void
4098 genIfxJump (iCode * ic, char *jval)
4099 {
4100   symbol *jlbl;
4101   symbol *tlbl = newiTempLabel (NULL);
4102   char *inst;
4103
4104   D (emitcode (";", "genIfxJump ");
4105     );
4106
4107   /* if true label then we jump if condition
4108      supplied is true */
4109   if (IC_TRUE (ic))
4110     {
4111       jlbl = IC_TRUE (ic);
4112       inst = ((strcmp (jval, "a") == 0 ? "jz" :
4113                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4114     }
4115   else
4116     {
4117       /* false label is present */
4118       jlbl = IC_FALSE (ic);
4119       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4120                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4121     }
4122   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4123     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4124   else
4125     emitcode (inst, "%05d$", tlbl->key + 100);
4126   emitcode ("ljmp", "%05d$", jlbl->key + 100);
4127   emitcode ("", "%05d$:", tlbl->key + 100);
4128
4129   /* mark the icode as generated */
4130   ic->generated = 1;
4131 }
4132
4133 /*-----------------------------------------------------------------*/
4134 /* genCmp :- greater or less than comparison                       */
4135 /*-----------------------------------------------------------------*/
4136 static void
4137 genCmp (operand * left, operand * right,
4138         iCode * ic, iCode * ifx, int sign)
4139 {
4140   int size, offset = 0;
4141   unsigned long lit = 0L;
4142   operand *result;
4143
4144   D (emitcode (";", "genCmp");
4145     );
4146
4147   result = IC_RESULT (ic);
4148
4149   /* if left & right are bit variables */
4150   if (AOP_TYPE (left) == AOP_CRY &&
4151       AOP_TYPE (right) == AOP_CRY)
4152     {
4153       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4154       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4155     }
4156   else
4157     {
4158       /* subtract right from left if at the
4159          end the carry flag is set then we know that
4160          left is greater than right */
4161       size = max (AOP_SIZE (left), AOP_SIZE (right));
4162
4163       /* if unsigned char cmp with lit, do cjne left,#right,zz */
4164       if ((size == 1) && !sign &&
4165           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4166         {
4167           symbol *lbl = newiTempLabel (NULL);
4168           emitcode ("cjne", "%s,%s,%05d$",
4169                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4170                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4171                     lbl->key + 100);
4172           emitcode ("", "%05d$:", lbl->key + 100);
4173         }
4174       else
4175         {
4176           if (AOP_TYPE (right) == AOP_LIT)
4177             {
4178               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4179               /* optimize if(x < 0) or if(x >= 0) */
4180               if (lit == 0L)
4181                 {
4182                   if (!sign)
4183                     {
4184                       CLRC;
4185                     }
4186                   else
4187                     {
4188                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4189
4190                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4191                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4192
4193                       aopOp (result, ic, FALSE, FALSE);
4194
4195                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4196                         {
4197                           freeAsmop (result, NULL, ic, TRUE);
4198                           genIfxJump (ifx, "acc.7");
4199                           return;
4200                         }
4201                       else
4202                         {
4203                           emitcode ("rlc", "a");
4204                         }
4205                       goto release_freedLR;
4206                     }
4207                   goto release;
4208                 }
4209             }
4210           CLRC;
4211           while (size--)
4212             {
4213               emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4214               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4215               emitcode (";", "genCmp #2");
4216               if (sign && (size == 0))
4217                 {
4218                   emitcode (";", "genCmp #3");
4219                   emitcode ("xrl", "a,#0x80");
4220                   if (AOP_TYPE (right) == AOP_LIT)
4221                     {
4222                       unsigned long lit = (unsigned long)
4223                       floatFromVal (AOP (right)->aopu.aop_lit);
4224                       emitcode (";", "genCmp #3.1");
4225                       emitcode ("subb", "a,#0x%02x",
4226                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4227                     }
4228                   else
4229                     {
4230                       emitcode (";", "genCmp #3.2");
4231                       if (AOP_NEEDSACC (right))
4232                         {
4233                           emitcode ("push", "acc");
4234                         }
4235                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4236                                                        FALSE, FALSE, FALSE));
4237                       emitcode ("xrl", "b,#0x80");
4238                       if (AOP_NEEDSACC (right))
4239                         {
4240                           emitcode ("pop", "acc");
4241                         }
4242                       emitcode ("subb", "a,b");
4243                     }
4244                 }
4245               else
4246                 {
4247                   const char *s;
4248
4249                   emitcode (";", "genCmp #4");
4250                   if (AOP_NEEDSACC (right))
4251                     {
4252                       /* Yuck!! */
4253                       emitcode (";", "genCmp #4.1");
4254                       emitcode ("xch", "a, b");
4255                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4256                       emitcode ("xch", "a, b");
4257                       s = "b";
4258                     }
4259                   else
4260                     {
4261                       emitcode (";", "genCmp #4.2");
4262                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4263                     }
4264
4265                   emitcode ("subb", "a,%s", s);
4266                 }
4267             }
4268         }
4269     }
4270
4271 release:
4272 /* Don't need the left & right operands any more; do need the result. */
4273   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4274   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4275
4276   aopOp (result, ic, FALSE, FALSE);
4277
4278 release_freedLR:
4279
4280   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4281     {
4282       outBitC (result);
4283     }
4284   else
4285     {
4286       /* if the result is used in the next
4287          ifx conditional branch then generate
4288          code a little differently */
4289       if (ifx)
4290         {
4291           genIfxJump (ifx, "c");
4292         }
4293       else
4294         {
4295           outBitC (result);
4296         }
4297       /* leave the result in acc */
4298     }
4299   freeAsmop (result, NULL, ic, TRUE);
4300 }
4301
4302 /*-----------------------------------------------------------------*/
4303 /* genCmpGt :- greater than comparison                             */
4304 /*-----------------------------------------------------------------*/
4305 static void
4306 genCmpGt (iCode * ic, iCode * ifx)
4307 {
4308   operand *left, *right;
4309   sym_link *letype, *retype;
4310   int sign;
4311
4312   D (emitcode (";", "genCmpGt ");
4313     );
4314
4315   left = IC_LEFT (ic);
4316   right = IC_RIGHT (ic);
4317
4318   letype = getSpec (operandType (left));
4319   retype = getSpec (operandType (right));
4320   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4321
4322   /* assign the left & right amsops */
4323   AOP_OP_2 (ic);
4324
4325   genCmp (right, left, ic, ifx, sign);
4326 }
4327
4328 /*-----------------------------------------------------------------*/
4329 /* genCmpLt - less than comparisons                                */
4330 /*-----------------------------------------------------------------*/
4331 static void
4332 genCmpLt (iCode * ic, iCode * ifx)
4333 {
4334   operand *left, *right;
4335   sym_link *letype, *retype;
4336   int sign;
4337
4338   D (emitcode (";", "genCmpLt "););
4339
4340   left = IC_LEFT (ic);
4341   right = IC_RIGHT (ic);
4342
4343   letype = getSpec (operandType (left));
4344   retype = getSpec (operandType (right));
4345   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4346
4347   /* assign the left & right amsops */
4348   AOP_OP_2 (ic);
4349
4350   genCmp (left, right, ic, ifx, sign);
4351 }
4352
4353 /*-----------------------------------------------------------------*/
4354 /* gencjneshort - compare and jump if not equal                    */
4355 /*-----------------------------------------------------------------*/
4356 static void
4357 gencjneshort (operand * left, operand * right, symbol * lbl)
4358 {
4359   int size = max (AOP_SIZE (left), AOP_SIZE (right));
4360   int offset = 0;
4361   unsigned long lit = 0L;
4362
4363   D (emitcode (";", "gencjneshort");
4364     );
4365
4366   /* if the left side is a literal or
4367      if the right is in a pointer register and left
4368      is not */
4369   if ((AOP_TYPE (left) == AOP_LIT) ||
4370       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4371     {
4372       operand *t = right;
4373       right = left;
4374       left = t;
4375     }
4376
4377   if (AOP_TYPE (right) == AOP_LIT)
4378     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4379
4380   if (opIsGptr (left) || opIsGptr (right))
4381     {
4382       /* We are comparing a generic pointer to something.
4383        * Exclude the generic type byte from the comparison.
4384        */
4385       size--;
4386       D (emitcode (";", "cjneshort: generic ptr special case.");
4387         )
4388     }
4389
4390
4391   /* if the right side is a literal then anything goes */
4392   if (AOP_TYPE (right) == AOP_LIT &&
4393       AOP_TYPE (left) != AOP_DIR)
4394     {
4395       while (size--)
4396         {
4397           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4398           MOVA (l);
4399           emitcode ("cjne", "a,%s,%05d$",
4400                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4401                     lbl->key + 100);
4402           offset++;
4403         }
4404     }
4405
4406   /* if the right side is in a register or in direct space or
4407      if the left is a pointer register & right is not */
4408   else if (AOP_TYPE (right) == AOP_REG ||
4409            AOP_TYPE (right) == AOP_DIR ||
4410            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4411            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4412     {
4413       while (size--)
4414         {
4415           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4416           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4417               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4418             emitcode ("jnz", "%05d$", lbl->key + 100);
4419           else
4420             emitcode ("cjne", "a,%s,%05d$",
4421                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4422                       lbl->key + 100);
4423           offset++;
4424         }
4425     }
4426   else
4427     {
4428       /* right is a pointer reg need both a & b */
4429       while (size--)
4430         {
4431           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4432           if (strcmp (l, "b"))
4433             emitcode ("mov", "b,%s", l);
4434           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4435           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4436           offset++;
4437         }
4438     }
4439 }
4440
4441 /*-----------------------------------------------------------------*/
4442 /* gencjne - compare and jump if not equal                         */
4443 /*-----------------------------------------------------------------*/
4444 static void
4445 gencjne (operand * left, operand * right, symbol * lbl)
4446 {
4447   symbol *tlbl = newiTempLabel (NULL);
4448
4449   D (emitcode (";", "gencjne");
4450     );
4451
4452   gencjneshort (left, right, lbl);
4453
4454   emitcode ("mov", "a,%s", one);
4455   emitcode ("sjmp", "%05d$", tlbl->key + 100);
4456   emitcode ("", "%05d$:", lbl->key + 100);
4457   emitcode ("clr", "a");
4458   emitcode ("", "%05d$:", tlbl->key + 100);
4459 }
4460
4461 /*-----------------------------------------------------------------*/
4462 /* genCmpEq - generates code for equal to                          */
4463 /*-----------------------------------------------------------------*/
4464 static void
4465 genCmpEq (iCode * ic, iCode * ifx)
4466 {
4467   operand *left, *right, *result;
4468
4469   D (emitcode (";", "genCmpEq ");
4470     );
4471
4472   AOP_OP_2 (ic);
4473   AOP_SET_LOCALS (ic);
4474
4475   /* if literal, literal on the right or
4476      if the right is in a pointer register and left
4477      is not */
4478   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4479       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4480     {
4481       operand *t = IC_RIGHT (ic);
4482       IC_RIGHT (ic) = IC_LEFT (ic);
4483       IC_LEFT (ic) = t;
4484     }
4485
4486   if (ifx &&                    /* !AOP_SIZE(result) */
4487       OP_SYMBOL (result) &&
4488       OP_SYMBOL (result)->regType == REG_CND)
4489     {
4490       symbol *tlbl;
4491       /* if they are both bit variables */
4492       if (AOP_TYPE (left) == AOP_CRY &&
4493           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4494         {
4495           if (AOP_TYPE (right) == AOP_LIT)
4496             {
4497               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4498               if (lit == 0L)
4499                 {
4500                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4501                   emitcode ("cpl", "c");
4502                 }
4503               else if (lit == 1L)
4504                 {
4505                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4506                 }
4507               else
4508                 {
4509                   emitcode ("clr", "c");
4510                 }
4511               /* AOP_TYPE(right) == AOP_CRY */
4512             }
4513           else
4514             {
4515               symbol *lbl = newiTempLabel (NULL);
4516               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4517               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4518               emitcode ("cpl", "c");
4519               emitcode ("", "%05d$:", (lbl->key + 100));
4520             }
4521           /* if true label then we jump if condition
4522              supplied is true */
4523           tlbl = newiTempLabel (NULL);
4524           if (IC_TRUE (ifx))
4525             {
4526               emitcode ("jnc", "%05d$", tlbl->key + 100);
4527               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4528             }
4529           else
4530             {
4531               emitcode ("jc", "%05d$", tlbl->key + 100);
4532               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4533             }
4534           emitcode ("", "%05d$:", tlbl->key + 100);
4535         }
4536       else
4537         {
4538           tlbl = newiTempLabel (NULL);
4539           gencjneshort (left, right, tlbl);
4540           if (IC_TRUE (ifx))
4541             {
4542               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4543               emitcode ("", "%05d$:", tlbl->key + 100);
4544             }
4545           else
4546             {
4547               symbol *lbl = newiTempLabel (NULL);
4548               emitcode ("sjmp", "%05d$", lbl->key + 100);
4549               emitcode ("", "%05d$:", tlbl->key + 100);
4550               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4551               emitcode ("", "%05d$:", lbl->key + 100);
4552             }
4553         }
4554       /* mark the icode as generated */
4555       ifx->generated = 1;
4556
4557       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4558       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4559       return;
4560     }
4561
4562   /* if they are both bit variables */
4563   if (AOP_TYPE (left) == AOP_CRY &&
4564       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4565     {
4566       if (AOP_TYPE (right) == AOP_LIT)
4567         {
4568           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4569           if (lit == 0L)
4570             {
4571               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4572               emitcode ("cpl", "c");
4573             }
4574           else if (lit == 1L)
4575             {
4576               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4577             }
4578           else
4579             {
4580               emitcode ("clr", "c");
4581             }
4582           /* AOP_TYPE(right) == AOP_CRY */
4583         }
4584       else
4585         {
4586           symbol *lbl = newiTempLabel (NULL);
4587           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4588           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4589           emitcode ("cpl", "c");
4590           emitcode ("", "%05d$:", (lbl->key + 100));
4591         }
4592
4593       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4594       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4595
4596       aopOp (result, ic, TRUE, FALSE);
4597
4598       /* c = 1 if egal */
4599       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4600         {
4601           outBitC (result);
4602           goto release;
4603         }
4604       if (ifx)
4605         {
4606           genIfxJump (ifx, "c");
4607           goto release;
4608         }
4609       /* if the result is used in an arithmetic operation
4610          then put the result in place */
4611       outBitC (result);
4612     }
4613   else
4614     {
4615       gencjne (left, right, newiTempLabel (NULL));
4616
4617       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4618       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4619
4620       aopOp (result, ic, TRUE, FALSE);
4621
4622       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4623         {
4624           aopPut (AOP (result), "a", 0);
4625           goto release;
4626         }
4627       if (ifx)
4628         {
4629           genIfxJump (ifx, "a");
4630           goto release;
4631         }
4632       /* if the result is used in an arithmetic operation
4633          then put the result in place */
4634       if (AOP_TYPE (result) != AOP_CRY)
4635         outAcc (result);
4636       /* leave the result in acc */
4637     }
4638
4639 release:
4640   freeAsmop (result, NULL, ic, TRUE);
4641 }
4642
4643 /*-----------------------------------------------------------------*/
4644 /* ifxForOp - returns the icode containing the ifx for operand     */
4645 /*-----------------------------------------------------------------*/
4646 static iCode *
4647 ifxForOp (operand * op, iCode * ic)
4648 {
4649   /* if true symbol then needs to be assigned */
4650   if (IS_TRUE_SYMOP (op))
4651     return NULL;
4652
4653   /* if this has register type condition and
4654      the next instruction is ifx with the same operand
4655      and live to of the operand is upto the ifx only then */
4656   if (ic->next &&
4657       ic->next->op == IFX &&
4658       IC_COND (ic->next)->key == op->key &&
4659       OP_SYMBOL (op)->liveTo <= ic->next->seq)
4660     return ic->next;
4661
4662   return NULL;
4663 }
4664 /*-----------------------------------------------------------------*/
4665 /* genAndOp - for && operation                                     */
4666 /*-----------------------------------------------------------------*/
4667 static void
4668 genAndOp (iCode * ic)
4669 {
4670   operand *left, *right, *result;
4671   symbol *tlbl;
4672
4673   D (emitcode (";", "genAndOp "););
4674
4675   /* note here that && operations that are in an
4676      if statement are taken away by backPatchLabels
4677      only those used in arthmetic operations remain */
4678   AOP_OP_2 (ic);
4679   AOP_SET_LOCALS (ic);
4680
4681   /* if both are bit variables */
4682   if (AOP_TYPE (left) == AOP_CRY &&
4683       AOP_TYPE (right) == AOP_CRY)
4684     {
4685       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4686       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4687       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4688       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4689   
4690       aopOp (result,ic,FALSE, FALSE);
4691       outBitC (result);
4692     }
4693   else
4694     {
4695       tlbl = newiTempLabel (NULL);
4696       toBoolean (left);
4697       emitcode ("jz", "%05d$", tlbl->key + 100);
4698       toBoolean (right);
4699       emitcode ("", "%05d$:", tlbl->key + 100);
4700       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4701       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4702   
4703       aopOp (result,ic,FALSE, FALSE);
4704       outBitAcc (result);
4705     }
4706     freeAsmop (result, NULL, ic, TRUE);
4707 }
4708
4709
4710 /*-----------------------------------------------------------------*/
4711 /* genOrOp - for || operation                                      */
4712 /*-----------------------------------------------------------------*/
4713 static void
4714 genOrOp (iCode * ic)
4715 {
4716   operand *left, *right, *result;
4717   symbol *tlbl;
4718
4719   D (emitcode (";", "genOrOp "););
4720
4721   /* note here that || operations that are in an
4722      if statement are taken away by backPatchLabels
4723      only those used in arthmetic operations remain */
4724   AOP_OP_2 (ic);
4725   AOP_SET_LOCALS (ic);
4726
4727   /* if both are bit variables */
4728   if (AOP_TYPE (left) == AOP_CRY &&
4729       AOP_TYPE (right) == AOP_CRY)
4730     {
4731       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4732       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4733       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4734       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4735   
4736       aopOp (result,ic,FALSE, FALSE);
4737       
4738       outBitC (result);
4739     }
4740   else
4741     {
4742       tlbl = newiTempLabel (NULL);
4743       toBoolean (left);
4744       emitcode ("jnz", "%05d$", tlbl->key + 100);
4745       toBoolean (right);
4746       emitcode ("", "%05d$:", tlbl->key + 100);
4747       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4748       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4749   
4750       aopOp (result,ic,FALSE, FALSE);
4751       
4752       outBitAcc (result);
4753     }
4754
4755   freeAsmop (result, NULL, ic, TRUE);
4756 }
4757
4758 /*-----------------------------------------------------------------*/
4759 /* isLiteralBit - test if lit == 2^n                               */
4760 /*-----------------------------------------------------------------*/
4761 static int
4762 isLiteralBit (unsigned long lit)
4763 {
4764   unsigned long pw[32] =
4765   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4766    0x100L, 0x200L, 0x400L, 0x800L,
4767    0x1000L, 0x2000L, 0x4000L, 0x8000L,
4768    0x10000L, 0x20000L, 0x40000L, 0x80000L,
4769    0x100000L, 0x200000L, 0x400000L, 0x800000L,
4770    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4771    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4772   int idx;
4773
4774   for (idx = 0; idx < 32; idx++)
4775     if (lit == pw[idx])
4776       return idx + 1;
4777   return 0;
4778 }
4779
4780 /*-----------------------------------------------------------------*/
4781 /* continueIfTrue -                                                */
4782 /*-----------------------------------------------------------------*/
4783 static void
4784 continueIfTrue (iCode * ic)
4785 {
4786   if (IC_TRUE (ic))
4787     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4788   ic->generated = 1;
4789 }
4790
4791 /*-----------------------------------------------------------------*/
4792 /* jmpIfTrue -                                                     */
4793 /*-----------------------------------------------------------------*/
4794 static void
4795 jumpIfTrue (iCode * ic)
4796 {
4797   if (!IC_TRUE (ic))
4798     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4799   ic->generated = 1;
4800 }
4801
4802 /*-----------------------------------------------------------------*/
4803 /* jmpTrueOrFalse -                                                */
4804 /*-----------------------------------------------------------------*/
4805 static void
4806 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4807 {
4808   // ugly but optimized by peephole
4809   if (IC_TRUE (ic))
4810     {
4811       symbol *nlbl = newiTempLabel (NULL);
4812       emitcode ("sjmp", "%05d$", nlbl->key + 100);
4813       emitcode ("", "%05d$:", tlbl->key + 100);
4814       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4815       emitcode ("", "%05d$:", nlbl->key + 100);
4816     }
4817   else
4818     {
4819       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4820       emitcode ("", "%05d$:", tlbl->key + 100);
4821     }
4822   ic->generated = 1;
4823 }
4824
4825 // Generate code to perform a bit-wise logic operation
4826 // on two operands in far space (assumed to already have been 
4827 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
4828 // in far space. This requires pushing the result on the stack
4829 // then popping it into the result.
4830 static void
4831 genFarFarLogicOp(iCode *ic, char *logicOp)
4832 {
4833       int size, resultSize, compSize;
4834       int offset = 0;
4835       
4836       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
4837       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
4838                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
4839       
4840       _startLazyDPSEvaluation();
4841       for (size = compSize; (size--); offset++)
4842       {
4843           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
4844           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
4845           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
4846           
4847           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
4848           emitcode ("push", "acc");
4849       }
4850       _endLazyDPSEvaluation();
4851      
4852       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4853       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4854       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
4855      
4856       resultSize = AOP_SIZE(IC_RESULT(ic));
4857
4858       ADJUST_PUSHED_RESULT(compSize, resultSize);
4859
4860       _startLazyDPSEvaluation();
4861       while (compSize--)
4862       {
4863           emitcode ("pop", "acc");
4864           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
4865       }
4866       _endLazyDPSEvaluation();
4867       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
4868 }
4869
4870
4871 /*-----------------------------------------------------------------*/
4872 /* genAnd  - code for and                                          */
4873 /*-----------------------------------------------------------------*/
4874 static void
4875 genAnd (iCode * ic, iCode * ifx)
4876 {
4877   operand *left, *right, *result;
4878   int size, offset = 0;
4879   unsigned long lit = 0L;
4880   int bytelit = 0;
4881   char buffer[10];
4882   bool pushResult;
4883
4884   D (emitcode (";", "genAnd "););
4885
4886   AOP_OP_3_NOFATAL (ic, pushResult);
4887   AOP_SET_LOCALS (ic);
4888
4889   if (pushResult)
4890   {
4891       genFarFarLogicOp(ic, "anl");
4892       return;
4893   }  
4894
4895 #ifdef DEBUG_TYPE
4896   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4897             AOP_TYPE (result),
4898             AOP_TYPE (left), AOP_TYPE (right));
4899   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4900             AOP_SIZE (result),
4901             AOP_SIZE (left), AOP_SIZE (right));
4902 #endif
4903
4904   /* if left is a literal & right is not then exchange them */
4905   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4906       AOP_NEEDSACC (left))
4907     {
4908       operand *tmp = right;
4909       right = left;
4910       left = tmp;
4911     }
4912
4913   /* if result = right then exchange them */
4914   if (sameRegs (AOP (result), AOP (right)))
4915     {
4916       operand *tmp = right;
4917       right = left;
4918       left = tmp;
4919     }
4920
4921   /* if right is bit then exchange them */
4922   if (AOP_TYPE (right) == AOP_CRY &&
4923       AOP_TYPE (left) != AOP_CRY)
4924     {
4925       operand *tmp = right;
4926       right = left;
4927       left = tmp;
4928     }
4929   if (AOP_TYPE (right) == AOP_LIT)
4930     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4931
4932   size = AOP_SIZE (result);
4933
4934   // if(bit & yy)
4935   // result = bit & yy;
4936   if (AOP_TYPE (left) == AOP_CRY)
4937     {
4938       // c = bit & literal;
4939       if (AOP_TYPE (right) == AOP_LIT)
4940         {
4941           if (lit & 1)
4942             {
4943               if (size && sameRegs (AOP (result), AOP (left)))
4944                 // no change
4945                 goto release;
4946               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4947             }
4948           else
4949             {
4950               // bit(result) = 0;
4951               if (size && (AOP_TYPE (result) == AOP_CRY))
4952                 {
4953                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4954                   goto release;
4955                 }
4956               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4957                 {
4958                   jumpIfTrue (ifx);
4959                   goto release;
4960                 }
4961               emitcode ("clr", "c");
4962             }
4963         }
4964       else
4965         {
4966           if (AOP_TYPE (right) == AOP_CRY)
4967             {
4968               // c = bit & bit;
4969               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4970               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4971             }
4972           else
4973             {
4974               // c = bit & val;
4975               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4976               // c = lsb
4977               emitcode ("rrc", "a");
4978               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4979             }
4980         }
4981       // bit = c
4982       // val = c
4983       if (size)
4984         outBitC (result);
4985       // if(bit & ...)
4986       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4987         genIfxJump (ifx, "c");
4988       goto release;
4989     }
4990
4991   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
4992   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
4993   if ((AOP_TYPE (right) == AOP_LIT) &&
4994       (AOP_TYPE (result) == AOP_CRY) &&
4995       (AOP_TYPE (left) != AOP_CRY))
4996     {
4997       int posbit = isLiteralBit (lit);
4998       /* left &  2^n */
4999       if (posbit)
5000         {
5001           posbit--;
5002           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5003           // bit = left & 2^n
5004           if (size)
5005             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5006           // if(left &  2^n)
5007           else
5008             {
5009               if (ifx)
5010                 {
5011                   sprintf (buffer, "acc.%d", posbit & 0x07);
5012                   genIfxJump (ifx, buffer);
5013                 }
5014               goto release;
5015             }
5016         }
5017       else
5018         {
5019           symbol *tlbl = newiTempLabel (NULL);
5020           int sizel = AOP_SIZE (left);
5021           if (size)
5022             emitcode ("setb", "c");
5023           while (sizel--)
5024             {
5025               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5026                 {
5027                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5028                   // byte ==  2^n ?
5029                   if ((posbit = isLiteralBit (bytelit)) != 0)
5030                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5031                   else
5032                     {
5033                       if (bytelit != 0x0FFL)
5034                         emitcode ("anl", "a,%s",
5035                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5036                       emitcode ("jnz", "%05d$", tlbl->key + 100);
5037                     }
5038                 }
5039               offset++;
5040             }
5041           // bit = left & literal
5042           if (size)
5043             {
5044               emitcode ("clr", "c");
5045               emitcode ("", "%05d$:", tlbl->key + 100);
5046             }
5047           // if(left & literal)
5048           else
5049             {
5050               if (ifx)
5051                 jmpTrueOrFalse (ifx, tlbl);
5052               goto release;
5053             }
5054         }
5055       outBitC (result);
5056       goto release;
5057     }
5058
5059   /* if left is same as result */
5060   if (sameRegs (AOP (result), AOP (left)))
5061     {
5062       for (; size--; offset++)
5063         {
5064           if (AOP_TYPE (right) == AOP_LIT)
5065             {
5066               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5067                 continue;
5068               else if (bytelit == 0)
5069                 aopPut (AOP (result), zero, offset);
5070               else if (IS_AOP_PREG (result))
5071                 {
5072                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5073                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5074                   aopPut (AOP (result), "a", offset);
5075                 }
5076               else
5077                 emitcode ("anl", "%s,%s",
5078                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5079                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5080             }
5081           else
5082             {
5083               if (AOP_TYPE (left) == AOP_ACC)
5084                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5085               else
5086                 {
5087                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5088                   if (IS_AOP_PREG (result))
5089                     {
5090                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5091                       aopPut (AOP (result), "a", offset);
5092
5093                     }
5094                   else
5095                     emitcode ("anl", "%s,a",
5096                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5097                 }
5098             }
5099         }
5100     }
5101   else
5102     {
5103       // left & result in different registers
5104       if (AOP_TYPE (result) == AOP_CRY)
5105         {
5106           // result = bit
5107           // if(size), result in bit
5108           // if(!size && ifx), conditional oper: if(left & right)
5109           symbol *tlbl = newiTempLabel (NULL);
5110           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5111           if (size)
5112             emitcode ("setb", "c");
5113           while (sizer--)
5114             {
5115               MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5116               emitcode ("anl", "a,%s",
5117                         aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5118               emitcode ("jnz", "%05d$", tlbl->key + 100);
5119               offset++;
5120             }
5121           if (size)
5122             {
5123               CLRC;
5124               emitcode ("", "%05d$:", tlbl->key + 100);
5125               outBitC (result);
5126             }
5127           else if (ifx)
5128             jmpTrueOrFalse (ifx, tlbl);
5129         }
5130       else
5131         {
5132           for (; (size--); offset++)
5133             {
5134               // normal case
5135               // result = left & right
5136               if (AOP_TYPE (right) == AOP_LIT)
5137                 {
5138                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5139                     {
5140                       aopPut (AOP (result),
5141                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5142                               offset);
5143                       continue;
5144                     }
5145                   else if (bytelit == 0)
5146                     {
5147                       aopPut (AOP (result), zero, offset);
5148                       continue;
5149                     }
5150                   D (emitcode (";", "better literal AND.");
5151                     );
5152                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5153                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5154                                                     FALSE, FALSE, FALSE));
5155
5156                 }
5157               else
5158                 {
5159                   // faster than result <- left, anl result,right
5160                   // and better if result is SFR
5161                   if (AOP_TYPE (left) == AOP_ACC)
5162                     {
5163                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5164                                                        FALSE, FALSE, FALSE));
5165                     }
5166                   else
5167                     {
5168                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5169                       emitcode ("anl", "a,%s",
5170                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5171                     }
5172                 }
5173               aopPut (AOP (result), "a", offset);
5174             }
5175         }
5176     }
5177
5178 release:
5179   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5180   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5181   freeAsmop (result, NULL, ic, TRUE);
5182 }
5183
5184
5185 /*-----------------------------------------------------------------*/
5186 /* genOr  - code for or                                            */
5187 /*-----------------------------------------------------------------*/
5188 static void
5189 genOr (iCode * ic, iCode * ifx)
5190 {
5191   operand *left, *right, *result;
5192   int size, offset = 0;
5193   unsigned long lit = 0L;
5194   bool     pushResult;
5195
5196   D (emitcode (";", "genOr "););
5197
5198   AOP_OP_3_NOFATAL (ic, pushResult);
5199   AOP_SET_LOCALS (ic);
5200
5201   if (pushResult)
5202   {
5203       genFarFarLogicOp(ic, "orl");
5204       return;
5205   }
5206
5207
5208 #ifdef DEBUG_TYPE
5209   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5210             AOP_TYPE (result),
5211             AOP_TYPE (left), AOP_TYPE (right));
5212   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5213             AOP_SIZE (result),
5214             AOP_SIZE (left), AOP_SIZE (right));
5215 #endif
5216
5217   /* if left is a literal & right is not then exchange them */
5218   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5219       AOP_NEEDSACC (left))
5220     {
5221       operand *tmp = right;
5222       right = left;
5223       left = tmp;
5224     }
5225
5226   /* if result = right then exchange them */
5227   if (sameRegs (AOP (result), AOP (right)))
5228     {
5229       operand *tmp = right;
5230       right = left;
5231       left = tmp;
5232     }
5233
5234   /* if right is bit then exchange them */
5235   if (AOP_TYPE (right) == AOP_CRY &&
5236       AOP_TYPE (left) != AOP_CRY)
5237     {
5238       operand *tmp = right;
5239       right = left;
5240       left = tmp;
5241     }
5242   if (AOP_TYPE (right) == AOP_LIT)
5243     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5244
5245   size = AOP_SIZE (result);
5246
5247   // if(bit | yy)
5248   // xx = bit | yy;
5249   if (AOP_TYPE (left) == AOP_CRY)
5250     {
5251       if (AOP_TYPE (right) == AOP_LIT)
5252         {
5253           // c = bit & literal;
5254           if (lit)
5255             {
5256               // lit != 0 => result = 1
5257               if (AOP_TYPE (result) == AOP_CRY)
5258                 {
5259                   if (size)
5260                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5261                   else if (ifx)
5262                     continueIfTrue (ifx);
5263                   goto release;
5264                 }
5265               emitcode ("setb", "c");
5266             }
5267           else
5268             {
5269               // lit == 0 => result = left
5270               if (size && sameRegs (AOP (result), AOP (left)))
5271                 goto release;
5272               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5273             }
5274         }
5275       else
5276         {
5277           if (AOP_TYPE (right) == AOP_CRY)
5278             {
5279               // c = bit | bit;
5280               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5281               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5282             }
5283           else
5284             {
5285               // c = bit | val;
5286               symbol *tlbl = newiTempLabel (NULL);
5287               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5288                 emitcode ("setb", "c");
5289               emitcode ("jb", "%s,%05d$",
5290                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
5291               toBoolean (right);
5292               emitcode ("jnz", "%05d$", tlbl->key + 100);
5293               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5294                 {
5295                   jmpTrueOrFalse (ifx, tlbl);
5296                   goto release;
5297                 }
5298               else
5299                 {
5300                   CLRC;
5301                   emitcode ("", "%05d$:", tlbl->key + 100);
5302                 }
5303             }
5304         }
5305       // bit = c
5306       // val = c
5307       if (size)
5308         outBitC (result);
5309       // if(bit | ...)
5310       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5311         genIfxJump (ifx, "c");
5312       goto release;
5313     }
5314
5315   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5316   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5317   if ((AOP_TYPE (right) == AOP_LIT) &&
5318       (AOP_TYPE (result) == AOP_CRY) &&
5319       (AOP_TYPE (left) != AOP_CRY))
5320     {
5321       if (lit)
5322         {
5323           // result = 1
5324           if (size)
5325             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5326           else
5327             continueIfTrue (ifx);
5328           goto release;
5329         }
5330       else
5331         {
5332           // lit = 0, result = boolean(left)
5333           if (size)
5334             emitcode ("setb", "c");
5335           toBoolean (right);
5336           if (size)
5337             {
5338               symbol *tlbl = newiTempLabel (NULL);
5339               emitcode ("jnz", "%05d$", tlbl->key + 100);
5340               CLRC;
5341               emitcode ("", "%05d$:", tlbl->key + 100);
5342             }
5343           else
5344             {
5345               genIfxJump (ifx, "a");
5346               goto release;
5347             }
5348         }
5349       outBitC (result);
5350       goto release;
5351     }
5352
5353   /* if left is same as result */
5354   if (sameRegs (AOP (result), AOP (left)))
5355     {
5356       for (; size--; offset++)
5357         {
5358           if (AOP_TYPE (right) == AOP_LIT)
5359             {
5360               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5361                 {
5362                   continue;
5363                 }
5364               else
5365                 {
5366                   if (IS_AOP_PREG (left))
5367                     {
5368                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5369                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5370                       aopPut (AOP (result), "a", offset);
5371                     }
5372                   else
5373                     {
5374                       emitcode ("orl", "%s,%s",
5375                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5376                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5377                     }
5378                 }
5379             }
5380           else
5381             {
5382               if (AOP_TYPE (left) == AOP_ACC)
5383                 {
5384                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5385                 }
5386               else
5387                 {
5388                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5389                   if (IS_AOP_PREG (left))
5390                     {
5391                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5392                       aopPut (AOP (result), "a", offset);
5393                     }
5394                   else
5395                     {
5396                       emitcode ("orl", "%s,a",
5397                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5398                     }
5399                 }
5400             }
5401         }
5402     }
5403   else
5404     {
5405       // left & result in different registers
5406       if (AOP_TYPE (result) == AOP_CRY)
5407         {
5408           // result = bit
5409           // if(size), result in bit
5410           // if(!size && ifx), conditional oper: if(left | right)
5411           symbol *tlbl = newiTempLabel (NULL);
5412           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5413           if (size)
5414             emitcode ("setb", "c");
5415           while (sizer--)
5416             {
5417               MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5418               emitcode ("orl", "a,%s",
5419                         aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5420               emitcode ("jnz", "%05d$", tlbl->key + 100);
5421               offset++;
5422             }
5423           if (size)
5424             {
5425               CLRC;
5426               emitcode ("", "%05d$:", tlbl->key + 100);
5427               outBitC (result);
5428             }
5429           else if (ifx)
5430             jmpTrueOrFalse (ifx, tlbl);
5431         }
5432       else
5433         {
5434           for (; (size--); offset++)
5435             {
5436               // normal case
5437               // result = left & right
5438               if (AOP_TYPE (right) == AOP_LIT)
5439                 {
5440                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5441                     {
5442                       aopPut (AOP (result),
5443                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5444                               offset);
5445                       continue;
5446                     }
5447                   D (emitcode (";", "better literal OR.");
5448                     );
5449                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5450                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5451                                                     FALSE, FALSE, FALSE));
5452
5453                 }
5454               else
5455                 {
5456                   // faster than result <- left, anl result,right
5457                   // and better if result is SFR
5458                   if (AOP_TYPE (left) == AOP_ACC)
5459                     {
5460                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5461                                                        FALSE, FALSE, FALSE));
5462                     }
5463                   else
5464                     {
5465                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5466                       emitcode ("orl", "a,%s",
5467                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5468                     }
5469                 }
5470               aopPut (AOP (result), "a", offset);
5471             }
5472         }
5473     }
5474
5475 release:
5476   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5477   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5478   freeAsmop (result, NULL, ic, TRUE);
5479 }
5480
5481 /*-----------------------------------------------------------------*/
5482 /* genXor - code for xclusive or                                   */
5483 /*-----------------------------------------------------------------*/
5484 static void
5485 genXor (iCode * ic, iCode * ifx)
5486 {
5487   operand *left, *right, *result;
5488   int size, offset = 0;
5489   unsigned long lit = 0L;
5490   bool pushResult;
5491
5492   D (emitcode (";", "genXor "););
5493
5494   AOP_OP_3_NOFATAL (ic, pushResult);
5495   AOP_SET_LOCALS (ic);
5496
5497   if (pushResult)
5498   {
5499       genFarFarLogicOp(ic, "xrl");
5500       return;
5501   }  
5502
5503 #ifdef DEBUG_TYPE
5504   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5505             AOP_TYPE (result),
5506             AOP_TYPE (left), AOP_TYPE (right));
5507   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5508             AOP_SIZE (result),
5509             AOP_SIZE (left), AOP_SIZE (right));
5510 #endif
5511
5512   /* if left is a literal & right is not ||
5513      if left needs acc & right does not */
5514   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5515       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5516     {
5517       operand *tmp = right;
5518       right = left;
5519       left = tmp;
5520     }
5521
5522   /* if result = right then exchange them */
5523   if (sameRegs (AOP (result), AOP (right)))
5524     {
5525       operand *tmp = right;
5526       right = left;
5527       left = tmp;
5528     }
5529
5530   /* if right is bit then exchange them */
5531   if (AOP_TYPE (right) == AOP_CRY &&
5532       AOP_TYPE (left) != AOP_CRY)
5533     {
5534       operand *tmp = right;
5535       right = left;
5536       left = tmp;
5537     }
5538   if (AOP_TYPE (right) == AOP_LIT)
5539     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5540
5541   size = AOP_SIZE (result);
5542
5543   // if(bit ^ yy)
5544   // xx = bit ^ yy;
5545   if (AOP_TYPE (left) == AOP_CRY)
5546     {
5547       if (AOP_TYPE (right) == AOP_LIT)
5548         {
5549           // c = bit & literal;
5550           if (lit >> 1)
5551             {
5552               // lit>>1  != 0 => result = 1
5553               if (AOP_TYPE (result) == AOP_CRY)
5554                 {
5555                   if (size)
5556                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5557                   else if (ifx)
5558                     continueIfTrue (ifx);
5559                   goto release;
5560                 }
5561               emitcode ("setb", "c");
5562             }
5563           else
5564             {
5565               // lit == (0 or 1)
5566               if (lit == 0)
5567                 {
5568                   // lit == 0, result = left
5569                   if (size && sameRegs (AOP (result), AOP (left)))
5570                     goto release;
5571                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5572                 }
5573               else
5574                 {
5575                   // lit == 1, result = not(left)
5576                   if (size && sameRegs (AOP (result), AOP (left)))
5577                     {
5578                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5579                       goto release;
5580                     }
5581                   else
5582                     {
5583                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5584                       emitcode ("cpl", "c");
5585                     }
5586                 }
5587             }
5588
5589         }
5590       else
5591         {
5592           // right != literal
5593           symbol *tlbl = newiTempLabel (NULL);
5594           if (AOP_TYPE (right) == AOP_CRY)
5595             {
5596               // c = bit ^ bit;
5597               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5598             }
5599           else
5600             {
5601               int sizer = AOP_SIZE (right);
5602               // c = bit ^ val
5603               // if val>>1 != 0, result = 1
5604               emitcode ("setb", "c");
5605               while (sizer)
5606                 {
5607                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5608                   if (sizer == 1)
5609                     // test the msb of the lsb
5610                     emitcode ("anl", "a,#0xfe");
5611                   emitcode ("jnz", "%05d$", tlbl->key + 100);
5612                   sizer--;
5613                 }
5614               // val = (0,1)
5615               emitcode ("rrc", "a");
5616             }
5617           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5618           emitcode ("cpl", "c");
5619           emitcode ("", "%05d$:", (tlbl->key + 100));
5620         }
5621       // bit = c
5622       // val = c
5623       if (size)
5624         outBitC (result);
5625       // if(bit | ...)
5626       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5627         genIfxJump (ifx, "c");
5628       goto release;
5629     }
5630
5631   if (sameRegs (AOP (result), AOP (left)))
5632     {
5633       /* if left is same as result */
5634       for (; size--; offset++)
5635         {
5636           if (AOP_TYPE (right) == AOP_LIT)
5637             {
5638               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5639                 continue;
5640               else if (IS_AOP_PREG (left))
5641                 {
5642                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5643                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5644                   aopPut (AOP (result), "a", offset);
5645                 }
5646               else
5647                 emitcode ("xrl", "%s,%s",
5648                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5649                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5650             }
5651           else
5652             {
5653               if (AOP_TYPE (left) == AOP_ACC)
5654                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5655               else
5656                 {
5657                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5658                   if (IS_AOP_PREG (left))
5659                     {
5660                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5661                       aopPut (AOP (result), "a", offset);
5662                     }
5663                   else
5664                     emitcode ("xrl", "%s,a",
5665                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5666                 }
5667             }
5668         }
5669     }
5670   else
5671     {
5672       // left & result in different registers
5673       if (AOP_TYPE (result) == AOP_CRY)
5674         {
5675           // result = bit
5676           // if(size), result in bit
5677           // if(!size && ifx), conditional oper: if(left ^ right)
5678           symbol *tlbl = newiTempLabel (NULL);
5679           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5680           if (size)
5681             emitcode ("setb", "c");
5682           while (sizer--)
5683             {
5684               if ((AOP_TYPE (right) == AOP_LIT) &&
5685                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5686                 {
5687                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5688                 }
5689               else
5690                 {
5691                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5692                   emitcode ("xrl", "a,%s",
5693                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5694                 }
5695               emitcode ("jnz", "%05d$", tlbl->key + 100);
5696               offset++;
5697             }
5698           if (size)
5699             {
5700               CLRC;
5701               emitcode ("", "%05d$:", tlbl->key + 100);
5702               outBitC (result);
5703             }
5704           else if (ifx)
5705             jmpTrueOrFalse (ifx, tlbl);
5706         }
5707       else
5708         for (; (size--); offset++)
5709           {
5710             // normal case
5711             // result = left & right
5712             if (AOP_TYPE (right) == AOP_LIT)
5713               {
5714                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5715                   {
5716                     aopPut (AOP (result),
5717                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5718                             offset);
5719                     continue;
5720                   }
5721                 D (emitcode (";", "better literal XOR.");
5722                   );
5723                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5724                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5725                                                   FALSE, FALSE, FALSE));
5726               }
5727             else
5728               {
5729                 // faster than result <- left, anl result,right
5730                 // and better if result is SFR
5731                 if (AOP_TYPE (left) == AOP_ACC)
5732                   {
5733                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5734                                                      FALSE, FALSE, FALSE));
5735                   }
5736                 else
5737                   {
5738                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5739                     emitcode ("xrl", "a,%s",
5740                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5741                   }
5742               }
5743             aopPut (AOP (result), "a", offset);
5744           }
5745     }
5746
5747 release:
5748   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5749   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5750   freeAsmop (result, NULL, ic, TRUE);
5751 }
5752
5753 /*-----------------------------------------------------------------*/
5754 /* genInline - write the inline code out                           */
5755 /*-----------------------------------------------------------------*/
5756 static void
5757 genInline (iCode * ic)
5758 {
5759   char buffer[MAX_INLINEASM];
5760   char *bp = buffer;
5761   char *bp1 = buffer;
5762
5763   D (emitcode (";", "genInline ");
5764     );
5765
5766   _G.inLine += (!options.asmpeep);
5767   strcpy (buffer, IC_INLINE (ic));
5768
5769   /* emit each line as a code */
5770   while (*bp)
5771     {
5772       if (*bp == '\n')
5773         {
5774           *bp++ = '\0';
5775           emitcode (bp1, "");
5776           bp1 = bp;
5777         }
5778       else
5779         {
5780           if (*bp == ':')
5781             {
5782               bp++;
5783               *bp = '\0';
5784               bp++;
5785               emitcode (bp1, "");
5786               bp1 = bp;
5787             }
5788           else
5789             bp++;
5790         }
5791     }
5792   if (bp1 != bp)
5793     emitcode (bp1, "");
5794   /*     emitcode("",buffer); */
5795   _G.inLine -= (!options.asmpeep);
5796 }
5797
5798 /*-----------------------------------------------------------------*/
5799 /* genRRC - rotate right with carry                                */
5800 /*-----------------------------------------------------------------*/
5801 static void
5802 genRRC (iCode * ic)
5803 {
5804   operand *left, *result;
5805   int size, offset = 0;
5806   char *l;
5807
5808   D (emitcode (";", "genRRC ");
5809     );
5810
5811   /* rotate right with carry */
5812   left = IC_LEFT (ic);
5813   result = IC_RESULT (ic);
5814   aopOp (left, ic, FALSE, FALSE);
5815   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5816
5817   /* move it to the result */
5818   size = AOP_SIZE (result);
5819   offset = size - 1;
5820   CLRC;
5821
5822   _startLazyDPSEvaluation ();
5823   while (size--)
5824     {
5825       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5826       MOVA (l);
5827       emitcode ("rrc", "a");
5828       if (AOP_SIZE (result) > 1)
5829         aopPut (AOP (result), "a", offset--);
5830     }
5831   _endLazyDPSEvaluation ();
5832
5833   /* now we need to put the carry into the
5834      highest order byte of the result */
5835   if (AOP_SIZE (result) > 1)
5836     {
5837       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5838       MOVA (l);
5839     }
5840   emitcode ("mov", "acc.7,c");
5841   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5842   freeAsmop (left, NULL, ic, TRUE);
5843   freeAsmop (result, NULL, ic, TRUE);
5844 }
5845
5846 /*-----------------------------------------------------------------*/
5847 /* genRLC - generate code for rotate left with carry               */
5848 /*-----------------------------------------------------------------*/
5849 static void
5850 genRLC (iCode * ic)
5851 {
5852   operand *left, *result;
5853   int size, offset = 0;
5854   char *l;
5855
5856   D (emitcode (";", "genRLC ");
5857     );
5858
5859   /* rotate right with carry */
5860   left = IC_LEFT (ic);
5861   result = IC_RESULT (ic);
5862   aopOp (left, ic, FALSE, FALSE);
5863   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5864
5865   /* move it to the result */
5866   size = AOP_SIZE (result);
5867   offset = 0;
5868   if (size--)
5869     {
5870       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5871       MOVA (l);
5872       emitcode ("add", "a,acc");
5873       if (AOP_SIZE (result) > 1)
5874         {
5875           aopPut (AOP (result), "a", offset++);
5876         }
5877
5878       _startLazyDPSEvaluation ();
5879       while (size--)
5880         {
5881           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5882           MOVA (l);
5883           emitcode ("rlc", "a");
5884           if (AOP_SIZE (result) > 1)
5885             aopPut (AOP (result), "a", offset++);
5886         }
5887       _endLazyDPSEvaluation ();
5888     }
5889   /* now we need to put the carry into the
5890      highest order byte of the result */
5891   if (AOP_SIZE (result) > 1)
5892     {
5893       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5894       MOVA (l);
5895     }
5896   emitcode ("mov", "acc.0,c");
5897   aopPut (AOP (result), "a", 0);
5898   freeAsmop (left, NULL, ic, TRUE);
5899   freeAsmop (result, NULL, ic, TRUE);
5900 }
5901
5902 /*-----------------------------------------------------------------*/
5903 /* genGetHbit - generates code get highest order bit               */
5904 /*-----------------------------------------------------------------*/
5905 static void
5906 genGetHbit (iCode * ic)
5907 {
5908   operand *left, *result;
5909   left = IC_LEFT (ic);
5910   result = IC_RESULT (ic);
5911   aopOp (left, ic, FALSE, FALSE);
5912   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5913
5914   D (emitcode (";", "genGetHbit ");
5915     );
5916
5917   /* get the highest order byte into a */
5918   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5919   if (AOP_TYPE (result) == AOP_CRY)
5920     {
5921       emitcode ("rlc", "a");
5922       outBitC (result);
5923     }
5924   else
5925     {
5926       emitcode ("rl", "a");
5927       emitcode ("anl", "a,#0x01");
5928       outAcc (result);
5929     }
5930
5931
5932   freeAsmop (left, NULL, ic, TRUE);
5933   freeAsmop (result, NULL, ic, TRUE);
5934 }
5935
5936 /*-----------------------------------------------------------------*/
5937 /* AccRol - rotate left accumulator by known count                 */
5938 /*-----------------------------------------------------------------*/
5939 static void
5940 AccRol (int shCount)
5941 {
5942   shCount &= 0x0007;            // shCount : 0..7
5943
5944   switch (shCount)
5945     {
5946     case 0:
5947       break;
5948     case 1:
5949       emitcode ("rl", "a");
5950       break;
5951     case 2:
5952       emitcode ("rl", "a");
5953       emitcode ("rl", "a");
5954       break;
5955     case 3:
5956       emitcode ("swap", "a");
5957       emitcode ("rr", "a");
5958       break;
5959     case 4:
5960       emitcode ("swap", "a");
5961       break;
5962     case 5:
5963       emitcode ("swap", "a");
5964       emitcode ("rl", "a");
5965       break;
5966     case 6:
5967       emitcode ("rr", "a");
5968       emitcode ("rr", "a");
5969       break;
5970     case 7:
5971       emitcode ("rr", "a");
5972       break;
5973     }
5974 }
5975
5976 /*-----------------------------------------------------------------*/
5977 /* AccLsh - left shift accumulator by known count                  */
5978 /*-----------------------------------------------------------------*/
5979 static void
5980 AccLsh (int shCount)
5981 {
5982   if (shCount != 0)
5983     {
5984       if (shCount == 1)
5985         emitcode ("add", "a,acc");
5986       else if (shCount == 2)
5987         {
5988           emitcode ("add", "a,acc");
5989           emitcode ("add", "a,acc");
5990         }
5991       else
5992         {
5993           /* rotate left accumulator */
5994           AccRol (shCount);
5995           /* and kill the lower order bits */
5996           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5997         }
5998     }
5999 }
6000
6001 /*-----------------------------------------------------------------*/
6002 /* AccRsh - right shift accumulator by known count                 */
6003 /*-----------------------------------------------------------------*/
6004 static void
6005 AccRsh (int shCount)
6006 {
6007   if (shCount != 0)
6008     {
6009       if (shCount == 1)
6010         {
6011           CLRC;
6012           emitcode ("rrc", "a");
6013         }
6014       else
6015         {
6016           /* rotate right accumulator */
6017           AccRol (8 - shCount);
6018           /* and kill the higher order bits */
6019           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6020         }
6021     }
6022 }
6023
6024 #if 0
6025 //REMOVE ME!!!
6026 /*-----------------------------------------------------------------*/
6027 /* AccSRsh - signed right shift accumulator by known count                 */
6028 /*-----------------------------------------------------------------*/
6029 static void
6030 AccSRsh (int shCount)
6031 {
6032   symbol *tlbl;
6033   if (shCount != 0)
6034     {
6035       if (shCount == 1)
6036         {
6037           emitcode ("mov", "c,acc.7");
6038           emitcode ("rrc", "a");
6039         }
6040       else if (shCount == 2)
6041         {
6042           emitcode ("mov", "c,acc.7");
6043           emitcode ("rrc", "a");
6044           emitcode ("mov", "c,acc.7");
6045           emitcode ("rrc", "a");
6046         }
6047       else
6048         {
6049           tlbl = newiTempLabel (NULL);
6050           /* rotate right accumulator */
6051           AccRol (8 - shCount);
6052           /* and kill the higher order bits */
6053           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6054           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6055           emitcode ("orl", "a,#0x%02x",
6056                     (unsigned char) ~SRMask[shCount]);
6057           emitcode ("", "%05d$:", tlbl->key + 100);
6058         }
6059     }
6060 }
6061 #endif
6062
6063 #if 0
6064 //REMOVE ME!!!
6065 /*-----------------------------------------------------------------*/
6066 /* shiftR1Left2Result - shift right one byte from left to result   */
6067 /*-----------------------------------------------------------------*/
6068 static void
6069 shiftR1Left2Result (operand * left, int offl,
6070                     operand * result, int offr,
6071                     int shCount, int sign)
6072 {
6073   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6074   /* shift right accumulator */
6075   if (sign)
6076     AccSRsh (shCount);
6077   else
6078     AccRsh (shCount);
6079   aopPut (AOP (result), "a", offr);
6080 }
6081 #endif
6082
6083 #if 0
6084 //REMOVE ME!!!
6085 /*-----------------------------------------------------------------*/
6086 /* shiftL1Left2Result - shift left one byte from left to result    */
6087 /*-----------------------------------------------------------------*/
6088 static void
6089 shiftL1Left2Result (operand * left, int offl,
6090                     operand * result, int offr, int shCount)
6091 {
6092   char *l;
6093   l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6094   MOVA (l);
6095   /* shift left accumulator */
6096   AccLsh (shCount);
6097   aopPut (AOP (result), "a", offr);
6098 }
6099 #endif
6100
6101 #if 0
6102 //REMOVE ME!!!
6103 /*-----------------------------------------------------------------*/
6104 /* movLeft2Result - move byte from left to result                  */
6105 /*-----------------------------------------------------------------*/
6106 static void
6107 movLeft2Result (operand * left, int offl,
6108                 operand * result, int offr, int sign)
6109 {
6110   char *l;
6111   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6112     {
6113       l = aopGet (AOP (left), offl, FALSE, FALSE, FALSE);
6114
6115       if (*l == '@' && (IS_AOP_PREG (result)))
6116         {
6117           emitcode ("mov", "a,%s", l);
6118           aopPut (AOP (result), "a", offr);
6119         }
6120       else
6121         {
6122           if (!sign)
6123             aopPut (AOP (result), l, offr);
6124           else
6125             {
6126               /* MSB sign in acc.7 ! */
6127               if (getDataSize (left) == offl + 1)
6128                 {
6129                   emitcode ("mov", "a,%s", l);
6130                   aopPut (AOP (result), "a", offr);
6131                 }
6132             }
6133         }
6134     }
6135 }
6136 #endif
6137
6138 #if 0
6139 //REMOVE ME!!!
6140 /*-----------------------------------------------------------------*/
6141 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6142 /*-----------------------------------------------------------------*/
6143 static void
6144 AccAXRrl1 (char *x)
6145 {
6146   emitcode ("rrc", "a");
6147   emitcode ("xch", "a,%s", x);
6148   emitcode ("rrc", "a");
6149   emitcode ("xch", "a,%s", x);
6150 }
6151 #endif
6152
6153 #if 0
6154 //REMOVE ME!!!
6155 /*-----------------------------------------------------------------*/
6156 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
6157 /*-----------------------------------------------------------------*/
6158 static void
6159 AccAXLrl1 (char *x)
6160 {
6161   emitcode ("xch", "a,%s", x);
6162   emitcode ("rlc", "a");
6163   emitcode ("xch", "a,%s", x);
6164   emitcode ("rlc", "a");
6165 }
6166 #endif
6167
6168 #if 0
6169 //REMOVE ME!!!
6170 /*-----------------------------------------------------------------*/
6171 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
6172 /*-----------------------------------------------------------------*/
6173 static void
6174 AccAXLsh1 (char *x)
6175 {
6176   emitcode ("xch", "a,%s", x);
6177   emitcode ("add", "a,acc");
6178   emitcode ("xch", "a,%s", x);
6179   emitcode ("rlc", "a");
6180 }
6181 #endif
6182
6183 #if 0
6184 //REMOVE ME!!!
6185 /*-----------------------------------------------------------------*/
6186 /* AccAXLsh - left shift a:x by known count (0..7)                 */
6187 /*-----------------------------------------------------------------*/
6188 static void
6189 AccAXLsh (char *x, int shCount)
6190 {
6191   switch (shCount)
6192     {
6193     case 0:
6194       break;
6195     case 1:
6196       AccAXLsh1 (x);
6197       break;
6198     case 2:
6199       AccAXLsh1 (x);
6200       AccAXLsh1 (x);
6201       break;
6202     case 3:
6203     case 4:
6204     case 5:                     // AAAAABBB:CCCCCDDD
6205
6206       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
6207
6208       emitcode ("anl", "a,#0x%02x",
6209                 SLMask[shCount]);       // BBB00000:CCCCCDDD
6210
6211       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
6212
6213       AccRol (shCount);         // DDDCCCCC:BBB00000
6214
6215       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
6216
6217       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
6218
6219       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
6220
6221       emitcode ("anl", "a,#0x%02x",
6222                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
6223
6224       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
6225
6226       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
6227
6228       break;
6229     case 6:                     // AAAAAABB:CCCCCCDD
6230       emitcode ("anl", "a,#0x%02x",
6231                 SRMask[shCount]);       // 000000BB:CCCCCCDD
6232       emitcode ("mov", "c,acc.0");      // c = B
6233       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
6234 #if 0
6235       AccAXRrl1 (x);            // BCCCCCCD:D000000B
6236       AccAXRrl1 (x);            // BBCCCCCC:DD000000
6237 #else
6238       emitcode("rrc","a"); 
6239       emitcode("xch","a,%s", x); 
6240       emitcode("rrc","a"); 
6241       emitcode("mov","c,acc.0"); //<< get correct bit 
6242       emitcode("xch","a,%s", x); 
6243
6244       emitcode("rrc","a"); 
6245       emitcode("xch","a,%s", x); 
6246       emitcode("rrc","a"); 
6247       emitcode("xch","a,%s", x); 
6248 #endif
6249       break;
6250     case 7:                     // a:x <<= 7
6251
6252       emitcode ("anl", "a,#0x%02x",
6253                 SRMask[shCount]);       // 0000000B:CCCCCCCD
6254
6255       emitcode ("mov", "c,acc.0");      // c = B
6256
6257       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
6258
6259       AccAXRrl1 (x);            // BCCCCCCC:D0000000
6260
6261       break;
6262     default:
6263       break;
6264     }
6265 }
6266 #endif
6267
6268 #if 0
6269 //REMOVE ME!!!
6270 /*-----------------------------------------------------------------*/
6271 /* AccAXRsh - right shift a:x known count (0..7)                   */
6272 /*-----------------------------------------------------------------*/
6273 static void
6274 AccAXRsh (char *x, int shCount)
6275 {
6276   switch (shCount)
6277     {
6278     case 0:
6279       break;
6280     case 1:
6281       CLRC;
6282       AccAXRrl1 (x);            // 0->a:x
6283
6284       break;
6285     case 2:
6286       CLRC;
6287       AccAXRrl1 (x);            // 0->a:x
6288
6289       CLRC;
6290       AccAXRrl1 (x);            // 0->a:x
6291
6292       break;
6293     case 3:
6294     case 4:
6295     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6296
6297       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
6298
6299       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6300
6301       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6302
6303       emitcode ("anl", "a,#0x%02x",
6304                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6305
6306       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6307
6308       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6309
6310       emitcode ("anl", "a,#0x%02x",
6311                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6312
6313       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6314
6315       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6316
6317       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
6318
6319       break;
6320     case 6:                     // AABBBBBB:CCDDDDDD
6321
6322       emitcode ("mov", "c,acc.7");
6323       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6324
6325       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6326
6327       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6328
6329       emitcode ("anl", "a,#0x%02x",
6330                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6331
6332       break;
6333     case 7:                     // ABBBBBBB:CDDDDDDD
6334
6335       emitcode ("mov", "c,acc.7");      // c = A
6336
6337       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6338
6339       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6340
6341       emitcode ("anl", "a,#0x%02x",
6342                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6343
6344       break;
6345     default:
6346       break;
6347     }
6348 }
6349 #endif
6350
6351 #if 0
6352 //REMOVE ME!!!
6353 /*-----------------------------------------------------------------*/
6354 /* AccAXRshS - right shift signed a:x known count (0..7)           */
6355 /*-----------------------------------------------------------------*/
6356 static void
6357 AccAXRshS (char *x, int shCount)
6358 {
6359   symbol *tlbl;
6360   switch (shCount)
6361     {
6362     case 0:
6363       break;
6364     case 1:
6365       emitcode ("mov", "c,acc.7");
6366       AccAXRrl1 (x);            // s->a:x
6367
6368       break;
6369     case 2:
6370       emitcode ("mov", "c,acc.7");
6371       AccAXRrl1 (x);            // s->a:x
6372
6373       emitcode ("mov", "c,acc.7");
6374       AccAXRrl1 (x);            // s->a:x
6375
6376       break;
6377     case 3:
6378     case 4:
6379     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6380
6381       tlbl = newiTempLabel (NULL);
6382       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
6383
6384       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6385
6386       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6387
6388       emitcode ("anl", "a,#0x%02x",
6389                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6390
6391       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6392
6393       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6394
6395       emitcode ("anl", "a,#0x%02x",
6396                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6397
6398       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6399
6400       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6401
6402       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
6403
6404       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6405       emitcode ("orl", "a,#0x%02x",
6406                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
6407
6408       emitcode ("", "%05d$:", tlbl->key + 100);
6409       break;                    // SSSSAAAA:BBBCCCCC
6410
6411     case 6:                     // AABBBBBB:CCDDDDDD
6412
6413       tlbl = newiTempLabel (NULL);
6414       emitcode ("mov", "c,acc.7");
6415       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6416
6417       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6418
6419       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6420
6421       emitcode ("anl", "a,#0x%02x",
6422                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6423
6424       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6425       emitcode ("orl", "a,#0x%02x",
6426                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
6427
6428       emitcode ("", "%05d$:", tlbl->key + 100);
6429       break;
6430     case 7:                     // ABBBBBBB:CDDDDDDD
6431
6432       tlbl = newiTempLabel (NULL);
6433       emitcode ("mov", "c,acc.7");      // c = A
6434
6435       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6436
6437       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6438
6439       emitcode ("anl", "a,#0x%02x",
6440                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6441
6442       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6443       emitcode ("orl", "a,#0x%02x",
6444                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
6445
6446       emitcode ("", "%05d$:", tlbl->key + 100);
6447       break;
6448     default:
6449       break;
6450     }
6451 }
6452 #endif
6453
6454 #if 0
6455 //REMOVE ME!!!
6456 /*-----------------------------------------------------------------*/
6457 /* shiftL2Left2Result - shift left two bytes from left to result   */
6458 /*-----------------------------------------------------------------*/
6459 static void
6460 shiftL2Left2Result (operand * left, int offl,
6461                     operand * result, int offr, int shCount)
6462 {
6463   if (sameRegs (AOP (result), AOP (left)) &&
6464       ((offl + MSB16) == offr))
6465     {
6466       /* don't crash result[offr] */
6467       MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6468       emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6469     }
6470   else
6471     {
6472       movLeft2Result (left, offl, result, offr, 0);
6473       MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6474     }
6475   /* ax << shCount (x = lsb(result)) */
6476   AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6477   aopPut (AOP (result), "a", offr + MSB16);
6478 }
6479 #endif
6480
6481 #if 0
6482 //REMOVE ME!!!
6483 /*-----------------------------------------------------------------*/
6484 /* shiftR2Left2Result - shift right two bytes from left to result  */
6485 /*-----------------------------------------------------------------*/
6486 static void
6487 shiftR2Left2Result (operand * left, int offl,
6488                     operand * result, int offr,
6489                     int shCount, int sign)
6490 {
6491   if (sameRegs (AOP (result), AOP (left)) &&
6492       ((offl + MSB16) == offr))
6493     {
6494       /* don't crash result[offr] */
6495       MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6496       emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6497     }
6498   else
6499     {
6500       movLeft2Result (left, offl, result, offr, 0);
6501       MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6502     }
6503   /* a:x >> shCount (x = lsb(result)) */
6504   if (sign)
6505     AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6506   else
6507     AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6508   if (getDataSize (result) > 1)
6509     aopPut (AOP (result), "a", offr + MSB16);
6510 }
6511 #endif
6512
6513 #if 0
6514 //REMOVE ME!!!
6515 /*-----------------------------------------------------------------*/
6516 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6517 /*-----------------------------------------------------------------*/
6518 static void
6519 shiftLLeftOrResult (operand * left, int offl,
6520                     operand * result, int offr, int shCount)
6521 {
6522   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6523   /* shift left accumulator */
6524   AccLsh (shCount);
6525   /* or with result */
6526   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6527   /* back to result */
6528   aopPut (AOP (result), "a", offr);
6529 }
6530 #endif
6531
6532 #if 0
6533 //REMOVE ME!!!
6534 /*-----------------------------------------------------------------*/
6535 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6536 /*-----------------------------------------------------------------*/
6537 static void
6538 shiftRLeftOrResult (operand * left, int offl,
6539                     operand * result, int offr, int shCount)
6540 {
6541   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6542   /* shift right accumulator */
6543   AccRsh (shCount);
6544   /* or with result */
6545   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6546   /* back to result */
6547   aopPut (AOP (result), "a", offr);
6548 }
6549 #endif
6550
6551 #if 0
6552 //REMOVE ME!!!
6553 /*-----------------------------------------------------------------*/
6554 /* genlshOne - left shift a one byte quantity by known count       */
6555 /*-----------------------------------------------------------------*/
6556 static void
6557 genlshOne (operand * result, operand * left, int shCount)
6558 {
6559   D (emitcode (";", "genlshOne ");
6560     );
6561   shiftL1Left2Result (left, LSB, result, LSB, shCount);
6562 }
6563 #endif
6564
6565 #if 0
6566 //REMOVE ME!!!
6567 /*-----------------------------------------------------------------*/
6568 /* genlshTwo - left shift two bytes by known amount != 0           */
6569 /*-----------------------------------------------------------------*/
6570 static void
6571 genlshTwo (operand * result, operand * left, int shCount)
6572 {
6573   int size;
6574
6575   D (emitcode (";", "genlshTwo ");
6576     );
6577
6578   size = getDataSize (result);
6579
6580   /* if shCount >= 8 */
6581   if (shCount >= 8)
6582     {
6583       shCount -= 8;
6584
6585       if (size > 1)
6586         {
6587           if (shCount)
6588             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6589           else
6590             movLeft2Result (left, LSB, result, MSB16, 0);
6591         }
6592       aopPut (AOP (result), zero, LSB);
6593     }
6594
6595   /*  1 <= shCount <= 7 */
6596   else
6597     {
6598       if (size == 1)
6599         shiftL1Left2Result (left, LSB, result, LSB, shCount);
6600       else
6601         shiftL2Left2Result (left, LSB, result, LSB, shCount);
6602     }
6603 }
6604 #endif
6605
6606 #if 0
6607 //REMOVE ME!!!
6608 /*-----------------------------------------------------------------*/
6609 /* shiftLLong - shift left one long from left to result            */
6610 /* offl = LSB or MSB16                                             */
6611 /*-----------------------------------------------------------------*/
6612 static void
6613 shiftLLong (operand * left, operand * result, int offr)
6614 {
6615   char *l;
6616   int size = AOP_SIZE (result);
6617
6618   if (size >= LSB + offr)
6619     {
6620       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6621       MOVA (l);
6622       emitcode ("add", "a,acc");
6623       if (sameRegs (AOP (left), AOP (result)) &&
6624           size >= MSB16 + offr && offr != LSB)
6625         emitcode ("xch", "a,%s",
6626                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6627       else
6628         aopPut (AOP (result), "a", LSB + offr);
6629     }
6630
6631   if (size >= MSB16 + offr)
6632     {
6633       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6634         {
6635           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6636           MOVA (l);
6637         }
6638       emitcode ("rlc", "a");
6639       if (sameRegs (AOP (left), AOP (result)) &&
6640           size >= MSB24 + offr && offr != LSB)
6641         emitcode ("xch", "a,%s",
6642                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6643       else
6644         aopPut (AOP (result), "a", MSB16 + offr);
6645     }
6646
6647   if (size >= MSB24 + offr)
6648     {
6649       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6650         {
6651           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6652           MOVA (l);
6653         }
6654       emitcode ("rlc", "a");
6655       if (sameRegs (AOP (left), AOP (result)) &&
6656           size >= MSB32 + offr && offr != LSB)
6657         emitcode ("xch", "a,%s",
6658                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6659       else
6660         aopPut (AOP (result), "a", MSB24 + offr);
6661     }
6662
6663   if (size > MSB32 + offr)
6664     {
6665       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6666         {
6667           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6668           MOVA (l);
6669         }
6670       emitcode ("rlc", "a");
6671       aopPut (AOP (result), "a", MSB32 + offr);
6672     }
6673   if (offr != LSB)
6674     aopPut (AOP (result), zero, LSB);
6675 }
6676 #endif
6677
6678 #if 0
6679 //REMOVE ME!!!
6680 /*-----------------------------------------------------------------*/
6681 /* genlshFour - shift four byte by a known amount != 0             */
6682 /*-----------------------------------------------------------------*/
6683 static void
6684 genlshFour (operand * result, operand * left, int shCount)
6685 {
6686   int size;
6687
6688   D (emitcode (";", "genlshFour ");
6689     );
6690
6691   size = AOP_SIZE (result);
6692
6693   /* if shifting more that 3 bytes */
6694   if (shCount >= 24)
6695     {
6696       shCount -= 24;
6697       if (shCount)
6698         /* lowest order of left goes to the highest
6699            order of the destination */
6700         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6701       else
6702         movLeft2Result (left, LSB, result, MSB32, 0);
6703       aopPut (AOP (result), zero, LSB);
6704       aopPut (AOP (result), zero, MSB16);
6705       aopPut (AOP (result), zero, MSB24);
6706       return;
6707     }
6708
6709   /* more than two bytes */
6710   else if (shCount >= 16)
6711     {
6712       /* lower order two bytes goes to higher order two bytes */
6713       shCount -= 16;
6714       /* if some more remaining */
6715       if (shCount)
6716         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6717       else
6718         {
6719           movLeft2Result (left, MSB16, result, MSB32, 0);
6720           movLeft2Result (left, LSB, result, MSB24, 0);
6721         }
6722       aopPut (AOP (result), zero, MSB16);
6723       aopPut (AOP (result), zero, LSB);
6724       return;
6725     }
6726
6727   /* if more than 1 byte */
6728   else if (shCount >= 8)
6729     {
6730       /* lower order three bytes goes to higher order  three bytes */
6731       shCount -= 8;
6732       if (size == 2)
6733         {
6734           if (shCount)
6735             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6736           else
6737             movLeft2Result (left, LSB, result, MSB16, 0);
6738         }
6739       else
6740         {                       /* size = 4 */
6741           if (shCount == 0)
6742             {
6743               movLeft2Result (left, MSB24, result, MSB32, 0);
6744               movLeft2Result (left, MSB16, result, MSB24, 0);
6745               movLeft2Result (left, LSB, result, MSB16, 0);
6746               aopPut (AOP (result), zero, LSB);
6747             }
6748           else if (shCount == 1)
6749             shiftLLong (left, result, MSB16);
6750           else
6751             {
6752               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6753               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6754               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6755               aopPut (AOP (result), zero, LSB);
6756             }
6757         }
6758     }
6759
6760   /* 1 <= shCount <= 7 */
6761   else if (shCount <= 2)
6762     {
6763       shiftLLong (left, result, LSB);
6764       if (shCount == 2)
6765         shiftLLong (result, result, LSB);
6766     }
6767   /* 3 <= shCount <= 7, optimize */
6768   else
6769     {
6770       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6771       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6772       shiftL2Left2Result (left, LSB, result, LSB, shCount);
6773     }
6774 }
6775 #endif
6776
6777 #if 0
6778 //REMOVE ME!!!
6779 /*-----------------------------------------------------------------*/
6780 /* genLeftShiftLiteral - left shifting by known count              */
6781 /*-----------------------------------------------------------------*/
6782 static void
6783 genLeftShiftLiteral (operand * left,
6784                      operand * right,
6785                      operand * result,
6786                      iCode * ic)
6787 {
6788   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6789   int size;
6790
6791   D (emitcode (";", "genLeftShiftLiteral (%d)", shCount);
6792     );
6793
6794   freeAsmop (right, NULL, ic, TRUE);
6795
6796   aopOp (left, ic, FALSE, FALSE);
6797   aopOp (result, ic, FALSE, TRUE);
6798
6799   size = getSize (operandType (result));
6800
6801 #if VIEW_SIZE
6802   emitcode ("; shift left ", "result %d, left %d", size,
6803             AOP_SIZE (left));
6804 #endif
6805
6806   /* I suppose that the left size >= result size */
6807   if (shCount == 0)
6808     {
6809       while (size--)
6810         {
6811           movLeft2Result (left, size, result, size, 0);
6812         }
6813     }
6814
6815   else if (shCount >= (size * 8))
6816     while (size--)
6817       aopPut (AOP (result), zero, size);
6818   else
6819     {
6820       switch (size)
6821         {
6822         case 1:
6823           genlshOne (result, left, shCount);
6824           break;
6825
6826         case 2:
6827         case 3:         /* bug: this is for generic pointers, I bet. */
6828           genlshTwo (result, left, shCount);
6829           break;
6830
6831         case 4:
6832           genlshFour (result, left, shCount);
6833           break;
6834         }
6835     }
6836   freeAsmop (left, NULL, ic, TRUE);
6837   freeAsmop (result, NULL, ic, TRUE);
6838 }
6839 #endif
6840
6841 /*-----------------------------------------------------------------*/
6842 /* genLeftShift - generates code for left shifting                 */
6843 /*-----------------------------------------------------------------*/
6844 static void
6845 genLeftShift (iCode * ic)
6846 {
6847   operand *left, *right, *result;
6848   int size, offset;
6849   char *l;
6850   symbol *tlbl, *tlbl1;
6851
6852   D (emitcode (";", "genLeftShift "););
6853
6854   right = IC_RIGHT (ic);
6855   left = IC_LEFT (ic);
6856   result = IC_RESULT (ic);
6857
6858   aopOp (right, ic, FALSE, FALSE);
6859
6860 #if 0
6861   /* if the shift count is known then do it
6862      as efficiently as possible */
6863   if (AOP_TYPE (right) == AOP_LIT)
6864     {
6865       genLeftShiftLiteral (left, right, result, ic);
6866       return;
6867     }
6868 #endif
6869
6870   /* shift count is unknown then we have to form
6871      a loop get the loop count in B : Note: we take
6872      only the lower order byte since shifting
6873      more that 32 bits make no sense anyway, ( the
6874      largest size of an object can be only 32 bits ) */
6875
6876   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
6877   emitcode ("inc", "b");
6878   freeAsmop (right, NULL, ic, TRUE);
6879   aopOp (left, ic, FALSE, FALSE);
6880   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6881
6882   /* now move the left to the result if they are not the
6883      same */
6884   if (!sameRegs (AOP (left), AOP (result)) &&
6885       AOP_SIZE (result) > 1)
6886     {
6887
6888       size = AOP_SIZE (result);
6889       offset = 0;
6890       _startLazyDPSEvaluation ();
6891       while (size--)
6892         {
6893           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
6894           if (*l == '@' && (IS_AOP_PREG (result)))
6895             {
6896
6897               emitcode ("mov", "a,%s", l);
6898               aopPut (AOP (result), "a", offset);
6899             }
6900           else
6901             aopPut (AOP (result), l, offset);
6902           offset++;
6903         }
6904       _endLazyDPSEvaluation ();
6905     }
6906
6907   tlbl = newiTempLabel (NULL);
6908   size = AOP_SIZE (result);
6909   offset = 0;
6910   tlbl1 = newiTempLabel (NULL);
6911
6912   /* if it is only one byte then */
6913   if (size == 1)
6914     {
6915       symbol *tlbl1 = newiTempLabel (NULL);
6916
6917       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
6918       MOVA (l);
6919       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6920       emitcode ("", "%05d$:", tlbl->key + 100);
6921       emitcode ("add", "a,acc");
6922       emitcode ("", "%05d$:", tlbl1->key + 100);
6923       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6924       aopPut (AOP (result), "a", 0);
6925       goto release;
6926     }
6927
6928   reAdjustPreg (AOP (result));
6929
6930   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6931   emitcode ("", "%05d$:", tlbl->key + 100);
6932   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6933   MOVA (l);
6934   emitcode ("add", "a,acc");
6935   aopPut (AOP (result), "a", offset++);
6936   _startLazyDPSEvaluation ();
6937   while (--size)
6938     {
6939       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6940       MOVA (l);
6941       emitcode ("rlc", "a");
6942       aopPut (AOP (result), "a", offset++);
6943     }
6944   _endLazyDPSEvaluation ();
6945   reAdjustPreg (AOP (result));
6946
6947   emitcode ("", "%05d$:", tlbl1->key + 100);
6948   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6949 release:
6950   freeAsmop (left, NULL, ic, TRUE);
6951   freeAsmop (result, NULL, ic, TRUE);
6952 }
6953
6954 #if 0
6955 //REMOVE ME!!!
6956 /*-----------------------------------------------------------------*/
6957 /* genrshOne - right shift a one byte quantity by known count      */
6958 /*-----------------------------------------------------------------*/
6959 static void
6960 genrshOne (operand * result, operand * left,
6961            int shCount, int sign)
6962 {
6963   D (emitcode (";", "genrshOne");
6964     );
6965   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6966 }
6967 #endif
6968
6969 #if 0
6970 //REMOVE ME!!!
6971 /*-----------------------------------------------------------------*/
6972 /* genrshTwo - right shift two bytes by known amount != 0          */
6973 /*-----------------------------------------------------------------*/
6974 static void
6975 genrshTwo (operand * result, operand * left,
6976            int shCount, int sign)
6977 {
6978   D (emitcode (";", "genrshTwo");
6979     );
6980
6981   /* if shCount >= 8 */
6982   if (shCount >= 8)
6983     {
6984       shCount -= 8;
6985       if (shCount)
6986         shiftR1Left2Result (left, MSB16, result, LSB,
6987                             shCount, sign);
6988       else
6989         movLeft2Result (left, MSB16, result, LSB, sign);
6990       addSign (result, MSB16, sign);
6991     }
6992
6993   /*  1 <= shCount <= 7 */
6994   else
6995     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6996 }
6997 #endif
6998
6999 #if 0
7000 //REMOVE ME!!!
7001 /*-----------------------------------------------------------------*/
7002 /* shiftRLong - shift right one long from left to result           */
7003 /* offl = LSB or MSB16                                             */
7004 /*-----------------------------------------------------------------*/
7005 static void
7006 shiftRLong (operand * left, int offl,
7007             operand * result, int sign)
7008 {
7009   if (!sign)
7010     emitcode ("clr", "c");
7011   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
7012   if (sign)
7013     emitcode ("mov", "c,acc.7");
7014   emitcode ("rrc", "a");
7015   aopPut (AOP (result), "a", MSB32 - offl);
7016   if (offl == MSB16)
7017     /* add sign of "a" */
7018     addSign (result, MSB32, sign);
7019
7020   MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
7021   emitcode ("rrc", "a");
7022   aopPut (AOP (result), "a", MSB24 - offl);
7023
7024   MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
7025   emitcode ("rrc", "a");
7026   aopPut (AOP (result), "a", MSB16 - offl);
7027
7028   if (offl == LSB)
7029     {
7030       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
7031       emitcode ("rrc", "a");
7032       aopPut (AOP (result), "a", LSB);
7033     }
7034 }
7035 #endif
7036
7037 #if 0
7038 //REMOVE ME!!!
7039 /*-----------------------------------------------------------------*/
7040 /* genrshFour - shift four byte by a known amount != 0             */
7041 /*-----------------------------------------------------------------*/
7042 static void
7043 genrshFour (operand * result, operand * left,
7044             int shCount, int sign)
7045 {
7046   D (emitcode (";", "genrshFour");
7047     );
7048
7049   /* if shifting more that 3 bytes */
7050   if (shCount >= 24)
7051     {
7052       shCount -= 24;
7053       if (shCount)
7054         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7055       else
7056         movLeft2Result (left, MSB32, result, LSB, sign);
7057       addSign (result, MSB16, sign);
7058     }
7059   else if (shCount >= 16)
7060     {
7061       shCount -= 16;
7062       if (shCount)
7063         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7064       else
7065         {
7066           movLeft2Result (left, MSB24, result, LSB, 0);
7067           movLeft2Result (left, MSB32, result, MSB16, sign);
7068         }
7069       addSign (result, MSB24, sign);
7070     }
7071   else if (shCount >= 8)
7072     {
7073       shCount -= 8;
7074       if (shCount == 1)
7075         shiftRLong (left, MSB16, result, sign);
7076       else if (shCount == 0)
7077         {
7078           movLeft2Result (left, MSB16, result, LSB, 0);
7079           movLeft2Result (left, MSB24, result, MSB16, 0);
7080           movLeft2Result (left, MSB32, result, MSB24, sign);
7081           addSign (result, MSB32, sign);
7082         }
7083       else
7084         {
7085           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7086           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7087           /* the last shift is signed */
7088           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7089           addSign (result, MSB32, sign);
7090         }
7091     }
7092   else
7093     {                           /* 1 <= shCount <= 7 */
7094       if (shCount <= 2)
7095         {
7096           shiftRLong (left, LSB, result, sign);
7097           if (shCount == 2)
7098             shiftRLong (result, LSB, result, sign);
7099         }
7100       else
7101         {
7102           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7103           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7104           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7105         }
7106     }
7107 }
7108 #endif
7109
7110 #if 0
7111 //REMOVE ME!!!
7112 /*-----------------------------------------------------------------*/
7113 /* genRightShiftLiteral - right shifting by known count            */
7114 /*-----------------------------------------------------------------*/
7115 static void
7116 genRightShiftLiteral (operand * left,
7117                       operand * right,
7118                       operand * result,
7119                       iCode * ic,
7120                       int sign)
7121 {
7122   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7123   int size;
7124
7125   D (emitcode (";", "genRightShiftLiteral");
7126     );
7127
7128   freeAsmop (right, NULL, ic, TRUE);
7129
7130   aopOp (left, ic, FALSE, FALSE);
7131   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7132
7133 #if VIEW_SIZE
7134   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7135             AOP_SIZE (left));
7136 #endif
7137
7138   size = getDataSize (left);
7139   /* test the LEFT size !!! */
7140
7141   /* I suppose that the left size >= result size */
7142   if (shCount == 0)
7143     {
7144       size = getDataSize (result);
7145       while (size--)
7146         movLeft2Result (left, size, result, size, 0);
7147     }
7148
7149   else if (shCount >= (size * 8))
7150     {
7151       if (sign)
7152         /* get sign in acc.7 */
7153         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7154       addSign (result, LSB, sign);
7155     }
7156   else
7157     {
7158       switch (size)
7159         {
7160         case 1:
7161           genrshOne (result, left, shCount, sign);
7162           break;
7163
7164         case 2:
7165           genrshTwo (result, left, shCount, sign);
7166           break;
7167
7168         case 4:
7169           genrshFour (result, left, shCount, sign);
7170           break;
7171         default:
7172           break;
7173         }
7174
7175       freeAsmop (left, NULL, ic, TRUE);
7176       freeAsmop (result, NULL, ic, TRUE);
7177     }
7178 }
7179 #endif
7180
7181 /*-----------------------------------------------------------------*/
7182 /* genSignedRightShift - right shift of signed number              */
7183 /*-----------------------------------------------------------------*/
7184 static void
7185 genSignedRightShift (iCode * ic)
7186 {
7187   operand *right, *left, *result;
7188   int size, offset;
7189   char *l;
7190   symbol *tlbl, *tlbl1;
7191
7192   D (emitcode (";", "genSignedRightShift ");
7193     );
7194
7195   /* we do it the hard way put the shift count in b
7196      and loop thru preserving the sign */
7197
7198   right = IC_RIGHT (ic);
7199   left = IC_LEFT (ic);
7200   result = IC_RESULT (ic);
7201
7202   aopOp (right, ic, FALSE, FALSE);
7203
7204 #if 0
7205   if (AOP_TYPE (right) == AOP_LIT)
7206     {
7207       genRightShiftLiteral (left, right, result, ic, 1);
7208       return;
7209     }
7210 #endif
7211   /* shift count is unknown then we have to form
7212      a loop get the loop count in B : Note: we take
7213      only the lower order byte since shifting
7214      more that 32 bits make no sense anyway, ( the
7215      largest size of an object can be only 32 bits ) */
7216
7217   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7218   emitcode ("inc", "b");
7219   freeAsmop (right, NULL, ic, TRUE);
7220   aopOp (left, ic, FALSE, FALSE);
7221   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7222
7223   /* now move the left to the result if they are not the
7224      same */
7225   if (!sameRegs (AOP (left), AOP (result)) &&
7226       AOP_SIZE (result) > 1)
7227     {
7228
7229       size = AOP_SIZE (result);
7230       offset = 0;
7231       _startLazyDPSEvaluation ();
7232       while (size--)
7233         {
7234           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7235           if (*l == '@' && IS_AOP_PREG (result))
7236             {
7237
7238               emitcode ("mov", "a,%s", l);
7239               aopPut (AOP (result), "a", offset);
7240             }
7241           else
7242             aopPut (AOP (result), l, offset);
7243           offset++;
7244         }
7245       _endLazyDPSEvaluation ();
7246     }
7247
7248   /* mov the highest order bit to OVR */
7249   tlbl = newiTempLabel (NULL);
7250   tlbl1 = newiTempLabel (NULL);
7251
7252   size = AOP_SIZE (result);
7253   offset = size - 1;
7254   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7255   emitcode ("rlc", "a");
7256   emitcode ("mov", "ov,c");
7257   /* if it is only one byte then */
7258   if (size == 1)
7259     {
7260       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7261       MOVA (l);
7262       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7263       emitcode ("", "%05d$:", tlbl->key + 100);
7264       emitcode ("mov", "c,ov");
7265       emitcode ("rrc", "a");
7266       emitcode ("", "%05d$:", tlbl1->key + 100);
7267       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7268       aopPut (AOP (result), "a", 0);
7269       goto release;
7270     }
7271
7272   reAdjustPreg (AOP (result));
7273   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7274   emitcode ("", "%05d$:", tlbl->key + 100);
7275   emitcode ("mov", "c,ov");
7276   _startLazyDPSEvaluation ();
7277   while (size--)
7278     {
7279       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7280       MOVA (l);
7281       emitcode ("rrc", "a");
7282       aopPut (AOP (result), "a", offset--);
7283     }
7284   _endLazyDPSEvaluation ();
7285   reAdjustPreg (AOP (result));
7286   emitcode ("", "%05d$:", tlbl1->key + 100);
7287   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7288
7289 release:
7290   freeAsmop (left, NULL, ic, TRUE);
7291   freeAsmop (result, NULL, ic, TRUE);
7292 }
7293
7294 /*-----------------------------------------------------------------*/
7295 /* genRightShift - generate code for right shifting                */
7296 /*-----------------------------------------------------------------*/
7297 static void
7298 genRightShift (iCode * ic)
7299 {
7300   operand *right, *left, *result;
7301   sym_link *retype;
7302   int size, offset;
7303   char *l;
7304   symbol *tlbl, *tlbl1;
7305
7306   D (emitcode (";", "genRightShift ");
7307     );
7308
7309   /* if signed then we do it the hard way preserve the
7310      sign bit moving it inwards */
7311   retype = getSpec (operandType (IC_RESULT (ic)));
7312
7313   if (!SPEC_USIGN (retype))
7314     {
7315       genSignedRightShift (ic);
7316       return;
7317     }
7318
7319   /* signed & unsigned types are treated the same : i.e. the
7320      signed is NOT propagated inwards : quoting from the
7321      ANSI - standard : "for E1 >> E2, is equivalent to division
7322      by 2**E2 if unsigned or if it has a non-negative value,
7323      otherwise the result is implementation defined ", MY definition
7324      is that the sign does not get propagated */
7325
7326   right = IC_RIGHT (ic);
7327   left = IC_LEFT (ic);
7328   result = IC_RESULT (ic);
7329
7330   aopOp (right, ic, FALSE, FALSE);
7331
7332 #if 0
7333   /* if the shift count is known then do it
7334      as efficiently as possible */
7335   if (AOP_TYPE (right) == AOP_LIT)
7336     {
7337       genRightShiftLiteral (left, right, result, ic, 0);
7338       return;
7339     }
7340 #endif
7341
7342   /* shift count is unknown then we have to form
7343      a loop get the loop count in B : Note: we take
7344      only the lower order byte since shifting
7345      more that 32 bits make no sense anyway, ( the
7346      largest size of an object can be only 32 bits ) */
7347
7348   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7349   emitcode ("inc", "b");
7350   freeAsmop (right, NULL, ic, TRUE);
7351   aopOp (left, ic, FALSE, FALSE);
7352   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7353
7354   /* now move the left to the result if they are not the
7355      same */
7356   if (!sameRegs (AOP (left), AOP (result)) &&
7357       AOP_SIZE (result) > 1)
7358     {
7359
7360       size = AOP_SIZE (result);
7361       offset = 0;
7362       _startLazyDPSEvaluation ();
7363       while (size--)
7364         {
7365           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7366           if (*l == '@' && IS_AOP_PREG (result))
7367             {
7368
7369               emitcode ("mov", "a,%s", l);
7370               aopPut (AOP (result), "a", offset);
7371             }
7372           else
7373             aopPut (AOP (result), l, offset);
7374           offset++;
7375         }
7376       _endLazyDPSEvaluation ();
7377     }
7378
7379   tlbl = newiTempLabel (NULL);
7380   tlbl1 = newiTempLabel (NULL);
7381   size = AOP_SIZE (result);
7382   offset = size - 1;
7383
7384   /* if it is only one byte then */
7385   if (size == 1)
7386     {
7387       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7388       MOVA (l);
7389       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7390       emitcode ("", "%05d$:", tlbl->key + 100);
7391       CLRC;
7392       emitcode ("rrc", "a");
7393       emitcode ("", "%05d$:", tlbl1->key + 100);
7394       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7395       aopPut (AOP (result), "a", 0);
7396       goto release;
7397     }
7398
7399   reAdjustPreg (AOP (result));
7400   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7401   emitcode ("", "%05d$:", tlbl->key + 100);
7402   CLRC;
7403   _startLazyDPSEvaluation ();
7404   while (size--)
7405     {
7406       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7407       MOVA (l);
7408       emitcode ("rrc", "a");
7409       aopPut (AOP (result), "a", offset--);
7410     }
7411   _endLazyDPSEvaluation ();
7412   reAdjustPreg (AOP (result));
7413
7414   emitcode ("", "%05d$:", tlbl1->key + 100);
7415   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7416
7417 release:
7418   freeAsmop (left, NULL, ic, TRUE);
7419   freeAsmop (result, NULL, ic, TRUE);
7420 }
7421
7422 /*-----------------------------------------------------------------*/
7423 /* genUnpackBits - generates code for unpacking bits               */
7424 /*-----------------------------------------------------------------*/
7425 static void
7426 genUnpackBits (operand * result, char *rname, int ptype)
7427 {
7428   int shCnt;
7429   int rlen = 0;
7430   sym_link *etype;
7431   int offset = 0;
7432
7433   D (emitcode (";", "genUnpackBits ");
7434     );
7435
7436   etype = getSpec (operandType (result));
7437
7438   /* read the first byte  */
7439   switch (ptype)
7440     {
7441
7442     case POINTER:
7443     case IPOINTER:
7444       emitcode ("mov", "a,@%s", rname);
7445       break;
7446
7447     case PPOINTER:
7448       emitcode ("movx", "a,@%s", rname);
7449       break;
7450
7451     case FPOINTER:
7452       emitcode ("movx", "a,@dptr");
7453       break;
7454
7455     case CPOINTER:
7456       emitcode ("clr", "a");
7457       emitcode ("movc", "a", "@a+dptr");
7458       break;
7459
7460     case GPOINTER:
7461       emitcode ("lcall", "__gptrget");
7462       break;
7463     }
7464
7465   /* if we have bitdisplacement then it fits   */
7466   /* into this byte completely or if length is */
7467   /* less than a byte                          */
7468   if ((shCnt = SPEC_BSTR (etype)) ||
7469       (SPEC_BLEN (etype) <= 8))
7470     {
7471
7472       /* shift right acc */
7473       AccRsh (shCnt);
7474
7475       emitcode ("anl", "a,#0x%02x",
7476                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7477       aopPut (AOP (result), "a", offset);
7478       return;
7479     }
7480
7481   /* bit field did not fit in a byte  */
7482   rlen = SPEC_BLEN (etype) - 8;
7483   aopPut (AOP (result), "a", offset++);
7484
7485   while (1)
7486     {
7487
7488       switch (ptype)
7489         {
7490         case POINTER:
7491         case IPOINTER:
7492           emitcode ("inc", "%s", rname);
7493           emitcode ("mov", "a,@%s", rname);
7494           break;
7495
7496         case PPOINTER:
7497           emitcode ("inc", "%s", rname);
7498           emitcode ("movx", "a,@%s", rname);
7499           break;
7500
7501         case FPOINTER:
7502           emitcode ("inc", "dptr");
7503           emitcode ("movx", "a,@dptr");
7504           break;
7505
7506         case CPOINTER:
7507           emitcode ("clr", "a");
7508           emitcode ("inc", "dptr");
7509           emitcode ("movc", "a", "@a+dptr");
7510           break;
7511
7512         case GPOINTER:
7513           emitcode ("inc", "dptr");
7514           emitcode ("lcall", "__gptrget");
7515           break;
7516         }
7517
7518       rlen -= 8;
7519       /* if we are done */
7520       if (rlen < 8)
7521         break;
7522
7523       aopPut (AOP (result), "a", offset++);
7524
7525     }
7526
7527   if (rlen)
7528     {
7529       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7530       aopPut (AOP (result), "a", offset);
7531     }
7532
7533   return;
7534 }
7535
7536
7537 /*-----------------------------------------------------------------*/
7538 /* genDataPointerGet - generates code when ptr offset is known     */
7539 /*-----------------------------------------------------------------*/
7540 static void
7541 genDataPointerGet (operand * left,
7542                    operand * result,
7543                    iCode * ic)
7544 {
7545   char *l;
7546   char buffer[256];
7547   int size, offset = 0;
7548   aopOp (result, ic, TRUE, FALSE);
7549
7550   /* get the string representation of the name */
7551   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7552   size = AOP_SIZE (result);
7553   _startLazyDPSEvaluation ();
7554   while (size--)
7555     {
7556       if (offset)
7557         sprintf (buffer, "(%s + %d)", l + 1, offset);
7558       else
7559         sprintf (buffer, "%s", l + 1);
7560       aopPut (AOP (result), buffer, offset++);
7561     }
7562   _endLazyDPSEvaluation ();
7563
7564   freeAsmop (left, NULL, ic, TRUE);
7565   freeAsmop (result, NULL, ic, TRUE);
7566 }
7567
7568 /*-----------------------------------------------------------------*/
7569 /* genNearPointerGet - emitcode for near pointer fetch             */
7570 /*-----------------------------------------------------------------*/
7571 static void
7572 genNearPointerGet (operand * left,
7573                    operand * result,
7574                    iCode * ic)
7575 {
7576   asmop *aop = NULL;
7577   regs *preg = NULL;
7578   char *rname;
7579   sym_link *rtype, *retype, *letype;
7580   sym_link *ltype = operandType (left);
7581   char buffer[80];
7582
7583   rtype = operandType (result);
7584   retype = getSpec (rtype);
7585   letype = getSpec (ltype);
7586
7587   aopOp (left, ic, FALSE, FALSE);
7588
7589   /* if left is rematerialisable and
7590      result is not bit variable type and
7591      the left is pointer to data space i.e
7592      lower 128 bytes of space */
7593   if (AOP_TYPE (left) == AOP_IMMD &&
7594       !IS_BITVAR (retype) &&
7595       !IS_BITVAR (letype) &&
7596       DCL_TYPE (ltype) == POINTER)
7597     {
7598       genDataPointerGet (left, result, ic);
7599       return;
7600     }
7601
7602   /* if the value is already in a pointer register
7603      then don't need anything more */
7604   if (!AOP_INPREG (AOP (left)))
7605     {
7606       /* otherwise get a free pointer register */
7607       aop = newAsmop (0);
7608       preg = getFreePtr (ic, &aop, FALSE);
7609       emitcode ("mov", "%s,%s",
7610                 preg->name,
7611                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7612       rname = preg->name;
7613     }
7614   else
7615     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7616
7617   freeAsmop (left, NULL, ic, TRUE);
7618   aopOp (result, ic, FALSE, FALSE);
7619
7620   /* if bitfield then unpack the bits */
7621   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7622     genUnpackBits (result, rname, POINTER);
7623   else
7624     {
7625       /* we have can just get the values */
7626       int size = AOP_SIZE (result);
7627       int offset = 0;
7628
7629       while (size--)
7630         {
7631           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7632             {
7633
7634               emitcode ("mov", "a,@%s", rname);
7635               aopPut (AOP (result), "a", offset);
7636             }
7637           else
7638             {
7639               sprintf (buffer, "@%s", rname);
7640               aopPut (AOP (result), buffer, offset);
7641             }
7642           offset++;
7643           if (size)
7644             emitcode ("inc", "%s", rname);
7645         }
7646     }
7647
7648   /* now some housekeeping stuff */
7649   if (aop)
7650     {
7651       /* we had to allocate for this iCode */
7652       freeAsmop (NULL, aop, ic, TRUE);
7653     }
7654   else
7655     {
7656       /* we did not allocate which means left
7657          already in a pointer register, then
7658          if size > 0 && this could be used again
7659          we have to point it back to where it
7660          belongs */
7661       if (AOP_SIZE (result) > 1 &&
7662           !OP_SYMBOL (left)->remat &&
7663           (OP_SYMBOL (left)->liveTo > ic->seq ||
7664            ic->depth))
7665         {
7666           int size = AOP_SIZE (result) - 1;
7667           while (size--)
7668             emitcode ("dec", "%s", rname);
7669         }
7670     }
7671
7672   /* done */
7673   freeAsmop (result, NULL, ic, TRUE);
7674
7675 }
7676
7677 /*-----------------------------------------------------------------*/
7678 /* genPagedPointerGet - emitcode for paged pointer fetch           */
7679 /*-----------------------------------------------------------------*/
7680 static void
7681 genPagedPointerGet (operand * left,
7682                     operand * result,
7683                     iCode * ic)
7684 {
7685   asmop *aop = NULL;
7686   regs *preg = NULL;
7687   char *rname;
7688   sym_link *rtype, *retype, *letype;
7689
7690   rtype = operandType (result);
7691   retype = getSpec (rtype);
7692   letype = getSpec (operandType (left));
7693   aopOp (left, ic, FALSE, FALSE);
7694
7695   /* if the value is already in a pointer register
7696      then don't need anything more */
7697   if (!AOP_INPREG (AOP (left)))
7698     {
7699       /* otherwise get a free pointer register */
7700       aop = newAsmop (0);
7701       preg = getFreePtr (ic, &aop, FALSE);
7702       emitcode ("mov", "%s,%s",
7703                 preg->name,
7704                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7705       rname = preg->name;
7706     }
7707   else
7708     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7709
7710   freeAsmop (left, NULL, ic, TRUE);
7711   aopOp (result, ic, FALSE, FALSE);
7712
7713   /* if bitfield then unpack the bits */
7714   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7715     genUnpackBits (result, rname, PPOINTER);
7716   else
7717     {
7718       /* we have can just get the values */
7719       int size = AOP_SIZE (result);
7720       int offset = 0;
7721
7722       while (size--)
7723         {
7724
7725           emitcode ("movx", "a,@%s", rname);
7726           aopPut (AOP (result), "a", offset);
7727
7728           offset++;
7729
7730           if (size)
7731             emitcode ("inc", "%s", rname);
7732         }
7733     }
7734
7735   /* now some housekeeping stuff */
7736   if (aop)
7737     {
7738       /* we had to allocate for this iCode */
7739       freeAsmop (NULL, aop, ic, TRUE);
7740     }
7741   else
7742     {
7743       /* we did not allocate which means left
7744          already in a pointer register, then
7745          if size > 0 && this could be used again
7746          we have to point it back to where it
7747          belongs */
7748       if (AOP_SIZE (result) > 1 &&
7749           !OP_SYMBOL (left)->remat &&
7750           (OP_SYMBOL (left)->liveTo > ic->seq ||
7751            ic->depth))
7752         {
7753           int size = AOP_SIZE (result) - 1;
7754           while (size--)
7755             emitcode ("dec", "%s", rname);
7756         }
7757     }
7758
7759   /* done */
7760   freeAsmop (result, NULL, ic, TRUE);
7761
7762
7763 }
7764
7765 /*-----------------------------------------------------------------*/
7766 /* genFarPointerGet - gget value from far space                    */
7767 /*-----------------------------------------------------------------*/
7768 static void
7769 genFarPointerGet (operand * left,
7770                   operand * result, iCode * ic)
7771 {
7772   int size, offset;
7773   sym_link *retype = getSpec (operandType (result));
7774   sym_link *letype = getSpec (operandType (left));
7775   D (emitcode (";", "genFarPointerGet");
7776     );
7777
7778   aopOp (left, ic, FALSE, FALSE);
7779
7780   /* if the operand is already in dptr
7781      then we do nothing else we move the value to dptr */
7782   if (AOP_TYPE (left) != AOP_STR)
7783     {
7784       /* if this is remateriazable */
7785       if (AOP_TYPE (left) == AOP_IMMD)
7786         {
7787           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7788         }
7789       else
7790         {
7791           /* we need to get it byte by byte */
7792           _startLazyDPSEvaluation ();
7793           if (AOP_TYPE (left) != AOP_DPTR)
7794             {
7795               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7796               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7797               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7798             }
7799           else
7800             {
7801               /* We need to generate a load to DPTR indirect through DPTR. */
7802               D (emitcode (";", "genFarPointerGet -- indirection special case.");
7803                 );
7804               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7805               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7806               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7807               emitcode ("pop", "dph");
7808               emitcode ("pop", "dpl");
7809             }
7810           _endLazyDPSEvaluation ();
7811         }
7812     }
7813   /* so dptr know contains the address */
7814   freeAsmop (left, NULL, ic, TRUE);
7815   aopOp (result, ic, FALSE, TRUE);
7816
7817   /* if bit then unpack */
7818   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7819     genUnpackBits (result, "dptr", FPOINTER);
7820   else
7821     {
7822       size = AOP_SIZE (result);
7823       offset = 0;
7824
7825       _startLazyDPSEvaluation ();
7826       while (size--)
7827         {
7828
7829           genSetDPTR (0);
7830           _flushLazyDPS ();
7831
7832           emitcode ("movx", "a,@dptr");
7833           if (size)
7834             emitcode ("inc", "dptr");
7835
7836           aopPut (AOP (result), "a", offset++);
7837         }
7838       _endLazyDPSEvaluation ();
7839     }
7840
7841   freeAsmop (result, NULL, ic, TRUE);
7842 }
7843
7844 /*-----------------------------------------------------------------*/
7845 /* emitcodePointerGet - gget value from code space                  */
7846 /*-----------------------------------------------------------------*/
7847 static void
7848 emitcodePointerGet (operand * left,
7849                     operand * result, iCode * ic)
7850 {
7851   int size, offset;
7852   sym_link *retype = getSpec (operandType (result));
7853
7854   aopOp (left, ic, FALSE, FALSE);
7855
7856   /* if the operand is already in dptr
7857      then we do nothing else we move the value to dptr */
7858   if (AOP_TYPE (left) != AOP_STR)
7859     {
7860       /* if this is remateriazable */
7861       if (AOP_TYPE (left) == AOP_IMMD)
7862         {
7863           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7864         }
7865       else
7866         {                       /* we need to get it byte by byte */
7867           _startLazyDPSEvaluation ();
7868           if (AOP_TYPE (left) != AOP_DPTR)
7869             {
7870               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7871               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7872               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7873             }
7874           else
7875             {
7876               /* We need to generate a load to DPTR indirect through DPTR. */
7877               D (emitcode (";", "gencodePointerGet -- indirection special case.");
7878                 );
7879               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7880               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7881               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7882               emitcode ("pop", "dph");
7883               emitcode ("pop", "dpl");
7884             }
7885           _endLazyDPSEvaluation ();
7886         }
7887     }
7888   /* so dptr know contains the address */
7889   freeAsmop (left, NULL, ic, TRUE);
7890   aopOp (result, ic, FALSE, TRUE);
7891
7892   /* if bit then unpack */
7893   if (IS_BITVAR (retype))
7894     genUnpackBits (result, "dptr", CPOINTER);
7895   else
7896     {
7897       size = AOP_SIZE (result);
7898       offset = 0;
7899
7900       _startLazyDPSEvaluation ();
7901       while (size--)
7902         {
7903           genSetDPTR (0);
7904           _flushLazyDPS ();
7905
7906           emitcode ("clr", "a");
7907           emitcode ("movc", "a,@a+dptr");
7908           if (size)
7909             emitcode ("inc", "dptr");
7910           aopPut (AOP (result), "a", offset++);
7911         }
7912       _endLazyDPSEvaluation ();
7913     }
7914
7915   freeAsmop (result, NULL, ic, TRUE);
7916 }
7917
7918 /*-----------------------------------------------------------------*/
7919 /* genGenPointerGet - gget value from generic pointer space        */
7920 /*-----------------------------------------------------------------*/
7921 static void
7922 genGenPointerGet (operand * left,
7923                   operand * result, iCode * ic)
7924 {
7925   int size, offset;
7926   sym_link *retype = getSpec (operandType (result));
7927   sym_link *letype = getSpec (operandType (left));
7928
7929   D (emitcode (";", "genGenPointerGet "); );
7930
7931   aopOp (left, ic, FALSE, TRUE);
7932
7933   /* if the operand is already in dptr
7934      then we do nothing else we move the value to dptr */
7935   if (AOP_TYPE (left) != AOP_STR)
7936     {
7937       /* if this is remateriazable */
7938       if (AOP_TYPE (left) == AOP_IMMD)
7939         {
7940           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7941           emitcode ("mov", "b,#%d", pointerCode (retype));
7942         }
7943       else
7944         {                       /* we need to get it byte by byte */
7945           _startLazyDPSEvaluation ();
7946           if (AOP(left)->type==AOP_DPTR2) {
7947             char *l;
7948             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
7949             genSetDPTR(0);
7950             _flushLazyDPS();
7951             emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l);
7952             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
7953             genSetDPTR(0);
7954             _flushLazyDPS();
7955             emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l);
7956             l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
7957             genSetDPTR(0);
7958             _flushLazyDPS();
7959             emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l);
7960             emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7961           } else {
7962             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
7963             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
7964             emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
7965             emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7966           }
7967           _endLazyDPSEvaluation ();
7968         }
7969     }
7970   /* so dptr know contains the address */
7971   freeAsmop (left, NULL, ic, TRUE);
7972   aopOp (result, ic, FALSE, TRUE);
7973
7974   /* if bit then unpack */
7975   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7976     genUnpackBits (result, "dptr", GPOINTER);
7977   else
7978     {
7979       size = AOP_SIZE (result);
7980       offset = 0;
7981
7982       while (size--)
7983         {
7984           emitcode ("lcall", "__gptrget");
7985           aopPut (AOP (result), "a", offset++);
7986           if (size)
7987             emitcode ("inc", "dptr");
7988         }
7989     }
7990
7991   freeAsmop (result, NULL, ic, TRUE);
7992 }
7993
7994 /*-----------------------------------------------------------------*/
7995 /* genPointerGet - generate code for pointer get                   */
7996 /*-----------------------------------------------------------------*/
7997 static void
7998 genPointerGet (iCode * ic)
7999 {
8000   operand *left, *result;
8001   sym_link *type, *etype;
8002   int p_type;
8003
8004   D (emitcode (";", "genPointerGet ");
8005     );
8006
8007   left = IC_LEFT (ic);
8008   result = IC_RESULT (ic);
8009
8010   /* depending on the type of pointer we need to
8011      move it to the correct pointer register */
8012   type = operandType (left);
8013   etype = getSpec (type);
8014   /* if left is of type of pointer then it is simple */
8015   if (IS_PTR (type) && !IS_FUNC (type->next))
8016     p_type = DCL_TYPE (type);
8017   else
8018     {
8019       /* we have to go by the storage class */
8020       p_type = PTR_TYPE (SPEC_OCLS (etype));
8021     }
8022
8023   /* now that we have the pointer type we assign
8024      the pointer values */
8025   switch (p_type)
8026     {
8027
8028     case POINTER:
8029     case IPOINTER:
8030       genNearPointerGet (left, result, ic);
8031       break;
8032
8033     case PPOINTER:
8034       genPagedPointerGet (left, result, ic);
8035       break;
8036
8037     case FPOINTER:
8038       genFarPointerGet (left, result, ic);
8039       break;
8040
8041     case CPOINTER:
8042       emitcodePointerGet (left, result, ic);
8043       break;
8044
8045     case GPOINTER:
8046       genGenPointerGet (left, result, ic);
8047       break;
8048     }
8049
8050 }
8051
8052 /*-----------------------------------------------------------------*/
8053 /* genPackBits - generates code for packed bit storage             */
8054 /*-----------------------------------------------------------------*/
8055 static void
8056 genPackBits (sym_link * etype,
8057              operand * right,
8058              char *rname, int p_type)
8059 {
8060   int shCount = 0;
8061   int offset = 0;
8062   int rLen = 0;
8063   int blen, bstr;
8064   char *l;
8065
8066   blen = SPEC_BLEN (etype);
8067   bstr = SPEC_BSTR (etype);
8068
8069   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8070   MOVA (l);
8071
8072   /* if the bit lenth is less than or    */
8073   /* it exactly fits a byte then         */
8074   if (SPEC_BLEN (etype) <= 8)
8075     {
8076       shCount = SPEC_BSTR (etype);
8077
8078       /* shift left acc */
8079       AccLsh (shCount);
8080
8081       if (SPEC_BLEN (etype) < 8)
8082         {                       /* if smaller than a byte */
8083
8084
8085           switch (p_type)
8086             {
8087             case POINTER:
8088               emitcode ("mov", "b,a");
8089               emitcode ("mov", "a,@%s", rname);
8090               break;
8091
8092             case FPOINTER:
8093               emitcode ("mov", "b,a");
8094               emitcode ("movx", "a,@dptr");
8095               break;
8096
8097             case GPOINTER:
8098               emitcode ("push", "b");
8099               emitcode ("push", "acc");
8100               emitcode ("lcall", "__gptrget");
8101               emitcode ("pop", "b");
8102               break;
8103             }
8104
8105           emitcode ("anl", "a,#0x%02x", (unsigned char)
8106                     ((unsigned char) (0xFF << (blen + bstr)) |
8107                      (unsigned char) (0xFF >> (8 - bstr))));
8108           emitcode ("orl", "a,b");
8109           if (p_type == GPOINTER)
8110             emitcode ("pop", "b");
8111         }
8112     }
8113
8114   switch (p_type)
8115     {
8116     case POINTER:
8117       emitcode ("mov", "@%s,a", rname);
8118       break;
8119
8120     case FPOINTER:
8121       emitcode ("movx", "@dptr,a");
8122       break;
8123
8124     case GPOINTER:
8125       emitcode ("lcall", "__gptrput");
8126       break;
8127     }
8128
8129   /* if we r done */
8130   if (SPEC_BLEN (etype) <= 8)
8131     return;
8132
8133   emitcode ("inc", "%s", rname);
8134   rLen = SPEC_BLEN (etype);
8135
8136   /* now generate for lengths greater than one byte */
8137   while (1)
8138     {
8139
8140       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8141
8142       rLen -= 8;
8143       if (rLen < 8)
8144         break;
8145
8146       switch (p_type)
8147         {
8148         case POINTER:
8149           if (*l == '@')
8150             {
8151               MOVA (l);
8152               emitcode ("mov", "@%s,a", rname);
8153             }
8154           else
8155             emitcode ("mov", "@%s,%s", rname, l);
8156           break;
8157
8158         case FPOINTER:
8159           MOVA (l);
8160           emitcode ("movx", "@dptr,a");
8161           break;
8162
8163         case GPOINTER:
8164           MOVA (l);
8165           emitcode ("lcall", "__gptrput");
8166           break;
8167         }
8168       emitcode ("inc", "%s", rname);
8169     }
8170
8171   MOVA (l);
8172
8173   /* last last was not complete */
8174   if (rLen)
8175     {
8176       /* save the byte & read byte */
8177       switch (p_type)
8178         {
8179         case POINTER:
8180           emitcode ("mov", "b,a");
8181           emitcode ("mov", "a,@%s", rname);
8182           break;
8183
8184         case FPOINTER:
8185           emitcode ("mov", "b,a");
8186           emitcode ("movx", "a,@dptr");
8187           break;
8188
8189         case GPOINTER:
8190           emitcode ("push", "b");
8191           emitcode ("push", "acc");
8192           emitcode ("lcall", "__gptrget");
8193           emitcode ("pop", "b");
8194           break;
8195         }
8196
8197       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8198       emitcode ("orl", "a,b");
8199     }
8200
8201   if (p_type == GPOINTER)
8202     emitcode ("pop", "b");
8203
8204   switch (p_type)
8205     {
8206
8207     case POINTER:
8208       emitcode ("mov", "@%s,a", rname);
8209       break;
8210
8211     case FPOINTER:
8212       emitcode ("movx", "@dptr,a");
8213       break;
8214
8215     case GPOINTER:
8216       emitcode ("lcall", "__gptrput");
8217       break;
8218     }
8219 }
8220 /*-----------------------------------------------------------------*/
8221 /* genDataPointerSet - remat pointer to data space                 */
8222 /*-----------------------------------------------------------------*/
8223 static void
8224 genDataPointerSet (operand * right,
8225                    operand * result,
8226                    iCode * ic)
8227 {
8228   int size, offset = 0;
8229   char *l, buffer[256];
8230
8231   aopOp (right, ic, FALSE, FALSE);
8232
8233   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8234   size = AOP_SIZE (right);
8235   while (size--)
8236     {
8237       if (offset)
8238         sprintf (buffer, "(%s + %d)", l + 1, offset);
8239       else
8240         sprintf (buffer, "%s", l + 1);
8241       emitcode ("mov", "%s,%s", buffer,
8242                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8243     }
8244
8245   freeAsmop (right, NULL, ic, TRUE);
8246   freeAsmop (result, NULL, ic, TRUE);
8247 }
8248
8249 /*-----------------------------------------------------------------*/
8250 /* genNearPointerSet - emitcode for near pointer put                */
8251 /*-----------------------------------------------------------------*/
8252 static void
8253 genNearPointerSet (operand * right,
8254                    operand * result,
8255                    iCode * ic)
8256 {
8257   asmop *aop = NULL;
8258   regs *preg = NULL;
8259   char *rname, *l;
8260   sym_link *retype, *letype;
8261   sym_link *ptype = operandType (result);
8262
8263   retype = getSpec (operandType (right));
8264   letype = getSpec (ptype);
8265
8266   aopOp (result, ic, FALSE, FALSE);
8267
8268   /* if the result is rematerializable &
8269      in data space & not a bit variable */
8270   if (AOP_TYPE (result) == AOP_IMMD &&
8271       DCL_TYPE (ptype) == POINTER &&
8272       !IS_BITVAR (retype) &&
8273       !IS_BITVAR (letype))
8274     {
8275       genDataPointerSet (right, result, ic);
8276       return;
8277     }
8278
8279   /* if the value is already in a pointer register
8280      then don't need anything more */
8281   if (!AOP_INPREG (AOP (result)))
8282     {
8283       /* otherwise get a free pointer register */
8284       aop = newAsmop (0);
8285       preg = getFreePtr (ic, &aop, FALSE);
8286       emitcode ("mov", "%s,%s",
8287                 preg->name,
8288                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8289       rname = preg->name;
8290     }
8291   else
8292     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8293
8294   freeAsmop (result, NULL, ic, TRUE);
8295   aopOp (right, ic, FALSE, FALSE);
8296
8297   /* if bitfield then unpack the bits */
8298   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8299     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8300   else
8301     {
8302       /* we have can just get the values */
8303       int size = AOP_SIZE (right);
8304       int offset = 0;
8305
8306       while (size--)
8307         {
8308           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8309           if (*l == '@')
8310             {
8311               MOVA (l);
8312               emitcode ("mov", "@%s,a", rname);
8313             }
8314           else
8315             emitcode ("mov", "@%s,%s", rname, l);
8316           if (size)
8317             emitcode ("inc", "%s", rname);
8318           offset++;
8319         }
8320     }
8321
8322   /* now some housekeeping stuff */
8323   if (aop)
8324     {
8325       /* we had to allocate for this iCode */
8326       freeAsmop (NULL, aop, ic, TRUE);
8327     }
8328   else
8329     {
8330       /* we did not allocate which means left
8331          already in a pointer register, then
8332          if size > 0 && this could be used again
8333          we have to point it back to where it
8334          belongs */
8335       if (AOP_SIZE (right) > 1 &&
8336           !OP_SYMBOL (result)->remat &&
8337           (OP_SYMBOL (result)->liveTo > ic->seq ||
8338            ic->depth))
8339         {
8340           int size = AOP_SIZE (right) - 1;
8341           while (size--)
8342             emitcode ("dec", "%s", rname);
8343         }
8344     }
8345
8346   /* done */
8347   freeAsmop (right, NULL, ic, TRUE);
8348
8349
8350 }
8351
8352 /*-----------------------------------------------------------------*/
8353 /* genPagedPointerSet - emitcode for Paged pointer put             */
8354 /*-----------------------------------------------------------------*/
8355 static void
8356 genPagedPointerSet (operand * right,
8357                     operand * result,
8358                     iCode * ic)
8359 {
8360   asmop *aop = NULL;
8361   regs *preg = NULL;
8362   char *rname, *l;
8363   sym_link *retype, *letype;
8364
8365   retype = getSpec (operandType (right));
8366   letype = getSpec (operandType (result));
8367
8368   aopOp (result, ic, FALSE, FALSE);
8369
8370   /* if the value is already in a pointer register
8371      then don't need anything more */
8372   if (!AOP_INPREG (AOP (result)))
8373     {
8374       /* otherwise get a free pointer register */
8375       aop = newAsmop (0);
8376       preg = getFreePtr (ic, &aop, FALSE);
8377       emitcode ("mov", "%s,%s",
8378                 preg->name,
8379                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8380       rname = preg->name;
8381     }
8382   else
8383     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8384
8385   freeAsmop (result, NULL, ic, TRUE);
8386   aopOp (right, ic, FALSE, FALSE);
8387
8388   /* if bitfield then unpack the bits */
8389   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8390     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8391   else
8392     {
8393       /* we have can just get the values */
8394       int size = AOP_SIZE (right);
8395       int offset = 0;
8396
8397       while (size--)
8398         {
8399           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8400
8401           MOVA (l);
8402           emitcode ("movx", "@%s,a", rname);
8403
8404           if (size)
8405             emitcode ("inc", "%s", rname);
8406
8407           offset++;
8408         }
8409     }
8410
8411   /* now some housekeeping stuff */
8412   if (aop)
8413     {
8414       /* we had to allocate for this iCode */
8415       freeAsmop (NULL, aop, ic, TRUE);
8416     }
8417   else
8418     {
8419       /* we did not allocate which means left
8420          already in a pointer register, then
8421          if size > 0 && this could be used again
8422          we have to point it back to where it
8423          belongs */
8424       if (AOP_SIZE (right) > 1 &&
8425           !OP_SYMBOL (result)->remat &&
8426           (OP_SYMBOL (result)->liveTo > ic->seq ||
8427            ic->depth))
8428         {
8429           int size = AOP_SIZE (right) - 1;
8430           while (size--)
8431             emitcode ("dec", "%s", rname);
8432         }
8433     }
8434
8435   /* done */
8436   freeAsmop (right, NULL, ic, TRUE);
8437
8438
8439 }
8440
8441 /*-----------------------------------------------------------------*/
8442 /* genFarPointerSet - set value from far space                     */
8443 /*-----------------------------------------------------------------*/
8444 static void
8445 genFarPointerSet (operand * right,
8446                   operand * result, iCode * ic)
8447 {
8448   int size, offset;
8449   sym_link *retype = getSpec (operandType (right));
8450   sym_link *letype = getSpec (operandType (result));
8451
8452   aopOp (result, ic, FALSE, FALSE);
8453
8454   /* if the operand is already in dptr
8455      then we do nothing else we move the value to dptr */
8456   if (AOP_TYPE (result) != AOP_STR)
8457     {
8458       /* if this is remateriazable */
8459       if (AOP_TYPE (result) == AOP_IMMD)
8460         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8461       else
8462         {
8463           /* we need to get it byte by byte */
8464           _startLazyDPSEvaluation ();
8465           if (AOP_TYPE (result) != AOP_DPTR)
8466             {
8467               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8468               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8469               emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8470             }
8471           else
8472             {
8473               /* We need to generate a load to DPTR indirect through DPTR. */
8474               D (emitcode (";", "genFarPointerSet -- indirection special case.");
8475                 );
8476               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8477               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8478               emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8479               emitcode ("pop", "dph");
8480               emitcode ("pop", "dpl");
8481             }
8482           _endLazyDPSEvaluation ();
8483         }
8484     }
8485   /* so dptr know contains the address */
8486   freeAsmop (result, NULL, ic, TRUE);
8487   aopOp (right, ic, FALSE, TRUE);
8488
8489   /* if bit then unpack */
8490   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8491     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8492   else
8493     {
8494       size = AOP_SIZE (right);
8495       offset = 0;
8496
8497       _startLazyDPSEvaluation ();
8498       while (size--)
8499         {
8500           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8501           MOVA (l);
8502
8503           genSetDPTR (0);
8504           _flushLazyDPS ();
8505
8506           emitcode ("movx", "@dptr,a");
8507           if (size)
8508             emitcode ("inc", "dptr");
8509         }
8510       _endLazyDPSEvaluation ();
8511     }
8512
8513   freeAsmop (right, NULL, ic, TRUE);
8514 }
8515
8516 /*-----------------------------------------------------------------*/
8517 /* genGenPointerSet - set value from generic pointer space         */
8518 /*-----------------------------------------------------------------*/
8519 static void
8520 genGenPointerSet (operand * right,
8521                   operand * result, iCode * ic)
8522 {
8523   int size, offset;
8524   sym_link *retype = getSpec (operandType (right));
8525   sym_link *letype = getSpec (operandType (result));
8526
8527   aopOp (result, ic, FALSE, TRUE);
8528
8529   /* if the operand is already in dptr
8530      then we do nothing else we move the value to dptr */
8531   if (AOP_TYPE (result) != AOP_STR)
8532     {
8533       _startLazyDPSEvaluation ();
8534       /* if this is remateriazable */
8535       if (AOP_TYPE (result) == AOP_IMMD)
8536         {
8537           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8538           emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8539         }
8540       else
8541         {                       /* we need to get it byte by byte */
8542           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8543           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8544           emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8545           emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8546         }
8547       _endLazyDPSEvaluation ();
8548     }
8549   /* so dptr know contains the address */
8550   freeAsmop (result, NULL, ic, TRUE);
8551   aopOp (right, ic, FALSE, TRUE);
8552
8553   /* if bit then unpack */
8554   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8555     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8556   else
8557     {
8558       size = AOP_SIZE (right);
8559       offset = 0;
8560
8561       _startLazyDPSEvaluation ();
8562       while (size--)
8563         {
8564           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8565           MOVA (l);
8566
8567           genSetDPTR (0);
8568           _flushLazyDPS ();
8569
8570           emitcode ("lcall", "__gptrput");
8571           if (size)
8572             emitcode ("inc", "dptr");
8573         }
8574       _endLazyDPSEvaluation ();
8575     }
8576
8577   freeAsmop (right, NULL, ic, TRUE);
8578 }
8579
8580 /*-----------------------------------------------------------------*/
8581 /* genPointerSet - stores the value into a pointer location        */
8582 /*-----------------------------------------------------------------*/
8583 static void
8584 genPointerSet (iCode * ic)
8585 {
8586   operand *right, *result;
8587   sym_link *type, *etype;
8588   int p_type;
8589
8590   D (emitcode (";", "genPointerSet ");
8591     );
8592
8593   right = IC_RIGHT (ic);
8594   result = IC_RESULT (ic);
8595
8596   /* depending on the type of pointer we need to
8597      move it to the correct pointer register */
8598   type = operandType (result);
8599   etype = getSpec (type);
8600   /* if left is of type of pointer then it is simple */
8601   if (IS_PTR (type) && !IS_FUNC (type->next))
8602     {
8603       p_type = DCL_TYPE (type);
8604     }
8605   else
8606     {
8607       /* we have to go by the storage class */
8608       p_type = PTR_TYPE (SPEC_OCLS (etype));
8609     }
8610
8611   /* now that we have the pointer type we assign
8612      the pointer values */
8613   switch (p_type)
8614     {
8615
8616     case POINTER:
8617     case IPOINTER:
8618       genNearPointerSet (right, result, ic);
8619       break;
8620
8621     case PPOINTER:
8622       genPagedPointerSet (right, result, ic);
8623       break;
8624
8625     case FPOINTER:
8626       genFarPointerSet (right, result, ic);
8627       break;
8628
8629     case GPOINTER:
8630       genGenPointerSet (right, result, ic);
8631       break;
8632     }
8633
8634 }
8635
8636 /*-----------------------------------------------------------------*/
8637 /* genIfx - generate code for Ifx statement                        */
8638 /*-----------------------------------------------------------------*/
8639 static void
8640 genIfx (iCode * ic, iCode * popIc)
8641 {
8642   operand *cond = IC_COND (ic);
8643   int isbit = 0;
8644
8645   D (emitcode (";", "genIfx "););
8646
8647   aopOp (cond, ic, FALSE, FALSE);
8648
8649   /* get the value into acc */
8650   if (AOP_TYPE (cond) != AOP_CRY)
8651     toBoolean (cond);
8652   else
8653     isbit = 1;
8654   /* the result is now in the accumulator */
8655   freeAsmop (cond, NULL, ic, TRUE);
8656
8657   /* if there was something to be popped then do it */
8658   if (popIc)
8659     genIpop (popIc);
8660
8661   /* if the condition is  a bit variable */
8662   if (isbit && IS_ITEMP (cond) &&
8663       SPIL_LOC (cond))
8664     genIfxJump (ic, SPIL_LOC (cond)->rname);
8665   else if (isbit && !IS_ITEMP (cond))
8666     genIfxJump (ic, OP_SYMBOL (cond)->rname);
8667   else
8668     genIfxJump (ic, "a");
8669
8670   ic->generated = 1;
8671 }
8672
8673 /*-----------------------------------------------------------------*/
8674 /* genAddrOf - generates code for address of                       */
8675 /*-----------------------------------------------------------------*/
8676 static void
8677 genAddrOf (iCode * ic)
8678 {
8679   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8680   int size, offset;
8681
8682   D (emitcode (";", "genAddrOf ");
8683     );
8684
8685   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8686
8687   /* if the operand is on the stack then we
8688      need to get the stack offset of this
8689      variable */
8690   if (sym->onStack)
8691     {
8692       /* if it has an offset then we need to compute
8693          it */
8694       if (sym->stack)
8695         {
8696           emitcode ("mov", "a,_bp");
8697           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8698           aopPut (AOP (IC_RESULT (ic)), "a", 0);
8699         }
8700       else
8701         {
8702           /* we can just move _bp */
8703           aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8704         }
8705       /* fill the result with zero */
8706       size = AOP_SIZE (IC_RESULT (ic)) - 1;
8707
8708
8709       if (options.stack10bit && size < (FPTRSIZE - 1))
8710         {
8711           fprintf (stderr,
8712                    "*** warning: pointer to stack var truncated.\n");
8713         }
8714
8715       offset = 1;
8716       while (size--)
8717         {
8718           /* Yuck! */
8719           if (options.stack10bit && offset == 2)
8720             {
8721               aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8722             }
8723           else
8724             {
8725               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8726             }
8727         }
8728
8729       goto release;
8730     }
8731
8732   /* object not on stack then we need the name */
8733   size = AOP_SIZE (IC_RESULT (ic));
8734   offset = 0;
8735
8736   while (size--)
8737     {
8738       char s[SDCC_NAME_MAX];
8739       if (offset)
8740         sprintf (s, "#(%s >> %d)",
8741                  sym->rname,
8742                  offset * 8);
8743       else
8744         sprintf (s, "#%s", sym->rname);
8745       aopPut (AOP (IC_RESULT (ic)), s, offset++);
8746     }
8747
8748 release:
8749   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8750
8751 }
8752
8753 /*-----------------------------------------------------------------*/
8754 /* genFarFarAssign - assignment when both are in far space         */
8755 /*-----------------------------------------------------------------*/
8756 static void
8757 genFarFarAssign (operand * result, operand * right, iCode * ic)
8758 {
8759   int size = AOP_SIZE (right);
8760   int offset = 0;
8761   char *l;
8762
8763   if (size > 1)
8764     {
8765       /* This is a net loss for size == 1, but a big gain
8766        * otherwise.
8767        */
8768       D (emitcode (";", "genFarFarAssign (improved)");
8769         );
8770
8771       aopOp (result, ic, TRUE, TRUE);
8772
8773       _startLazyDPSEvaluation ();
8774       while (size--)
8775         {
8776           aopPut (AOP (result),
8777                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
8778           offset++;
8779         }
8780       _endLazyDPSEvaluation ();
8781       freeAsmop (result, NULL, ic, FALSE);
8782       freeAsmop (right, NULL, ic, FALSE);
8783     }
8784   else
8785     {
8786       D (emitcode (";", "genFarFarAssign ");
8787         );
8788
8789       /* first push the right side on to the stack */
8790       _startLazyDPSEvaluation ();
8791       while (size--)
8792         {
8793           l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8794           MOVA (l);
8795           emitcode ("push", "acc");
8796         }
8797
8798       freeAsmop (right, NULL, ic, FALSE);
8799       /* now assign DPTR to result */
8800       aopOp (result, ic, FALSE, FALSE);
8801       size = AOP_SIZE (result);
8802       while (size--)
8803         {
8804           emitcode ("pop", "acc");
8805           aopPut (AOP (result), "a", --offset);
8806         }
8807       freeAsmop (result, NULL, ic, FALSE);
8808       _endLazyDPSEvaluation ();
8809     }
8810 }
8811
8812 /*-----------------------------------------------------------------*/
8813 /* genAssign - generate code for assignment                        */
8814 /*-----------------------------------------------------------------*/
8815 static void
8816 genAssign (iCode * ic)
8817 {
8818   operand *result, *right;
8819   int size, offset;
8820   unsigned long lit = 0L;
8821
8822   D (emitcode (";", "genAssign ");
8823     );
8824
8825   result = IC_RESULT (ic);
8826   right = IC_RIGHT (ic);
8827
8828   /* if they are the same */
8829   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8830     return;
8831
8832   aopOp (right, ic, FALSE, FALSE);
8833
8834   emitcode (";", "genAssign: resultIsFar = %s",
8835             isOperandInFarSpace (result) ?
8836             "TRUE" : "FALSE");
8837
8838   /* special case both in far space */
8839   if ((AOP_TYPE (right) == AOP_DPTR ||
8840        AOP_TYPE (right) == AOP_DPTR2) &&
8841   /* IS_TRUE_SYMOP(result)       && */
8842       isOperandInFarSpace (result))
8843     {
8844       genFarFarAssign (result, right, ic);
8845       return;
8846     }
8847
8848   aopOp (result, ic, TRUE, FALSE);
8849
8850   /* if they are the same registers */
8851   if (sameRegs (AOP (right), AOP (result)))
8852     goto release;
8853
8854   /* if the result is a bit */
8855   if (AOP_TYPE (result) == AOP_CRY)
8856     {
8857
8858       /* if the right size is a literal then
8859          we know what the value is */
8860       if (AOP_TYPE (right) == AOP_LIT)
8861         {
8862           if (((int) operandLitValue (right)))
8863             aopPut (AOP (result), one, 0);
8864           else
8865             aopPut (AOP (result), zero, 0);
8866           goto release;
8867         }
8868
8869       /* the right is also a bit variable */
8870       if (AOP_TYPE (right) == AOP_CRY)
8871         {
8872           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8873           aopPut (AOP (result), "c", 0);
8874           goto release;
8875         }
8876
8877       /* we need to or */
8878       toBoolean (right);
8879       aopPut (AOP (result), "a", 0);
8880       goto release;
8881     }
8882
8883   /* bit variables done */
8884   /* general case */
8885   size = AOP_SIZE (result);
8886   offset = 0;
8887   if (AOP_TYPE (right) == AOP_LIT)
8888     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8889
8890   if ((size > 1) &&
8891       (AOP_TYPE (result) != AOP_REG) &&
8892       (AOP_TYPE (right) == AOP_LIT) &&
8893       !IS_FLOAT (operandType (right)))
8894     {
8895       D (emitcode (";", "Kevin's better literal load code");
8896         );
8897       _startLazyDPSEvaluation ();
8898       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
8899         {
8900           aopPut (AOP (result),
8901                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
8902                   offset);
8903           offset++;
8904           size--;
8905         }
8906       /* And now fill the rest with zeros. */
8907       if (size)
8908         {
8909           emitcode ("clr", "a");
8910         }
8911       while (size--)
8912         {
8913           aopPut (AOP (result), "a", offset++);
8914         }
8915       _endLazyDPSEvaluation ();
8916     }
8917   else
8918     {
8919       _startLazyDPSEvaluation ();
8920       while (size--)
8921         {
8922           aopPut (AOP (result),
8923                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8924                   offset);
8925           offset++;
8926         }
8927       _endLazyDPSEvaluation ();
8928     }
8929
8930 release:
8931   freeAsmop (right, NULL, ic, FALSE);
8932   freeAsmop (result, NULL, ic, TRUE);
8933 }
8934
8935 /*-----------------------------------------------------------------*/
8936 /* genJumpTab - generates code for jump table                      */
8937 /*-----------------------------------------------------------------*/
8938 static void
8939 genJumpTab (iCode * ic)
8940 {
8941   symbol *jtab;
8942   char *l;
8943
8944   D (emitcode (";", "genJumpTab ");
8945     );
8946
8947   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
8948   /* get the condition into accumulator */
8949   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
8950   MOVA (l);
8951   /* multiply by four! */
8952   emitcode ("add", "a,acc");
8953   emitcode ("add", "a,acc");
8954   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8955
8956   jtab = newiTempLabel (NULL);
8957   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8958   emitcode ("jmp", "@a+dptr");
8959   emitcode ("", "%05d$:", jtab->key + 100);
8960   /* now generate the jump labels */
8961   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8962        jtab = setNextItem (IC_JTLABELS (ic)))
8963     emitcode ("ljmp", "%05d$", jtab->key + 100);
8964
8965 }
8966
8967 /*-----------------------------------------------------------------*/
8968 /* genCast - gen code for casting                                  */
8969 /*-----------------------------------------------------------------*/
8970 static void
8971 genCast (iCode * ic)
8972 {
8973   operand *result = IC_RESULT (ic);
8974   sym_link *ctype = operandType (IC_LEFT (ic));
8975   sym_link *rtype = operandType (IC_RIGHT (ic));
8976   operand *right = IC_RIGHT (ic);
8977   int size, offset;
8978
8979   D (emitcode (";", "genCast ");
8980     );
8981
8982   /* if they are equivalent then do nothing */
8983   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8984     return;
8985
8986   aopOp (right, ic, FALSE, FALSE);
8987   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
8988
8989   /* if the result is a bit */
8990   if (AOP_TYPE (result) == AOP_CRY)
8991     {
8992       /* if the right size is a literal then
8993          we know what the value is */
8994       if (AOP_TYPE (right) == AOP_LIT)
8995         {
8996           if (((int) operandLitValue (right)))
8997             aopPut (AOP (result), one, 0);
8998           else
8999             aopPut (AOP (result), zero, 0);
9000
9001           goto release;
9002         }
9003
9004       /* the right is also a bit variable */
9005       if (AOP_TYPE (right) == AOP_CRY)
9006         {
9007           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9008           aopPut (AOP (result), "c", 0);
9009           goto release;
9010         }
9011
9012       /* we need to or */
9013       toBoolean (right);
9014       aopPut (AOP (result), "a", 0);
9015       goto release;
9016     }
9017
9018   /* if they are the same size : or less */
9019   if (AOP_SIZE (result) <= AOP_SIZE (right))
9020     {
9021
9022       /* if they are in the same place */
9023       if (sameRegs (AOP (right), AOP (result)))
9024         goto release;
9025
9026       /* if they in different places then copy */
9027       size = AOP_SIZE (result);
9028       offset = 0;
9029       _startLazyDPSEvaluation ();
9030       while (size--)
9031         {
9032           aopPut (AOP (result),
9033                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9034                   offset);
9035           offset++;
9036         }
9037       _endLazyDPSEvaluation ();
9038       goto release;
9039     }
9040
9041
9042   /* if the result is of type pointer */
9043   if (IS_PTR (ctype))
9044     {
9045
9046       int p_type;
9047       sym_link *type = operandType (right);
9048
9049       /* pointer to generic pointer */
9050       if (IS_GENPTR (ctype))
9051         {
9052           char *l = zero;
9053
9054           if (IS_PTR (type))
9055             {
9056               p_type = DCL_TYPE (type);
9057             }
9058           else
9059             {
9060 #if OLD_CAST_BEHAVIOR
9061               /* KV: we are converting a non-pointer type to
9062                * a generic pointer. This (ifdef'd out) code
9063                * says that the resulting generic pointer
9064                * should have the same class as the storage
9065                * location of the non-pointer variable.
9066                *
9067                * For example, converting an int (which happens
9068                * to be stored in DATA space) to a pointer results
9069                * in a DATA generic pointer; if the original int
9070                * in XDATA space, so will be the resulting pointer.
9071                *
9072                * I don't like that behavior, and thus this change:
9073                * all such conversions will be forced to XDATA and
9074                * throw a warning. If you want some non-XDATA
9075                * type, or you want to suppress the warning, you
9076                * must go through an intermediate cast, like so:
9077                *
9078                * char _generic *gp = (char _xdata *)(intVar);
9079                */
9080               sym_link *etype = getSpec (type);
9081
9082               /* we have to go by the storage class */
9083               if (SPEC_OCLS (etype) != generic)
9084                 {
9085                   p_type = PTR_TYPE (SPEC_OCLS (etype));
9086                 }
9087               else
9088 #endif
9089                 {
9090                   /* Converting unknown class (i.e. register variable)
9091                    * to generic pointer. This is not good, but
9092                    * we'll make a guess (and throw a warning).
9093                    */
9094                   p_type = FPOINTER;
9095                   werror (W_INT_TO_GEN_PTR_CAST);
9096                 }
9097             }
9098
9099           /* the first two bytes are known */
9100           size = GPTRSIZE - 1;
9101           offset = 0;
9102           _startLazyDPSEvaluation ();
9103           while (size--)
9104             {
9105               aopPut (AOP (result),
9106                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9107                       offset);
9108               offset++;
9109             }
9110           _endLazyDPSEvaluation ();
9111
9112           /* the last byte depending on type */
9113           switch (p_type)
9114             {
9115             case IPOINTER:
9116             case POINTER:
9117               l = zero;
9118               break;
9119             case FPOINTER:
9120               l = one;
9121               break;
9122             case CPOINTER:
9123               l = "#0x02";
9124               break;
9125             case PPOINTER:
9126               l = "#0x03";
9127               break;
9128
9129             default:
9130               /* this should never happen */
9131               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9132                       "got unknown pointer type");
9133               exit (1);
9134             }
9135           aopPut (AOP (result), l, GPTRSIZE - 1);
9136           goto release;
9137         }
9138
9139       /* just copy the pointers */
9140       size = AOP_SIZE (result);
9141       offset = 0;
9142       _startLazyDPSEvaluation ();
9143       while (size--)
9144         {
9145           aopPut (AOP (result),
9146                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9147                   offset);
9148           offset++;
9149         }
9150       _endLazyDPSEvaluation ();
9151       goto release;
9152     }
9153
9154   /* so we now know that the size of destination is greater
9155      than the size of the source */
9156   /* we move to result for the size of source */
9157   size = AOP_SIZE (right);
9158   offset = 0;
9159   _startLazyDPSEvaluation ();
9160   while (size--)
9161     {
9162       aopPut (AOP (result),
9163               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9164               offset);
9165       offset++;
9166     }
9167   _endLazyDPSEvaluation ();
9168
9169   /* now depending on the sign of the source && destination */
9170   size = AOP_SIZE (result) - AOP_SIZE (right);
9171   /* if unsigned or not an integral type */
9172   /* also, if the source is a bit, we don't need to sign extend, because
9173    * it can't possibly have set the sign bit.
9174    */
9175   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9176     {
9177       while (size--)
9178         {
9179           aopPut (AOP (result), zero, offset++);
9180         }
9181     }
9182   else
9183     {
9184       /* we need to extend the sign :{ */
9185       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9186                         FALSE, FALSE, TRUE);
9187       MOVA (l);
9188       emitcode ("rlc", "a");
9189       emitcode ("subb", "a,acc");
9190       while (size--)
9191         aopPut (AOP (result), "a", offset++);
9192     }
9193
9194   /* we are done hurray !!!! */
9195
9196 release:
9197   freeAsmop (right, NULL, ic, TRUE);
9198   freeAsmop (result, NULL, ic, TRUE);
9199
9200 }
9201
9202 /*-----------------------------------------------------------------*/
9203 /* genDjnz - generate decrement & jump if not zero instrucion      */
9204 /*-----------------------------------------------------------------*/
9205 static int
9206 genDjnz (iCode * ic, iCode * ifx)
9207 {
9208   symbol *lbl, *lbl1;
9209   if (!ifx)
9210     return 0;
9211
9212   /* if the if condition has a false label
9213      then we cannot save */
9214   if (IC_FALSE (ifx))
9215     return 0;
9216
9217   /* if the minus is not of the form
9218      a = a - 1 */
9219   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9220       !IS_OP_LITERAL (IC_RIGHT (ic)))
9221     return 0;
9222
9223   if (operandLitValue (IC_RIGHT (ic)) != 1)
9224     return 0;
9225
9226   /* if the size of this greater than one then no
9227      saving */
9228   if (getSize (operandType (IC_RESULT (ic))) > 1)
9229     return 0;
9230
9231   /* otherwise we can save BIG */
9232   D(emitcode(";", "genDjnz"););
9233
9234   lbl = newiTempLabel (NULL);
9235   lbl1 = newiTempLabel (NULL);
9236
9237   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9238
9239   if (AOP_NEEDSACC(IC_RESULT(ic)))
9240   {
9241       /* If the result is accessed indirectly via
9242        * the accumulator, we must explicitly write
9243        * it back after the decrement.
9244        */
9245       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9246       
9247       if (strcmp(rByte, "a"))
9248       {
9249            /* Something is hopelessly wrong */
9250            fprintf(stderr, "*** warning: internal error at %s:%d\n",
9251                    __FILE__, __LINE__);
9252            /* We can just give up; the generated code will be inefficient,
9253             * but what the hey.
9254             */
9255            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9256            return 0;
9257       }
9258       emitcode ("dec", "%s", rByte);
9259       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9260       emitcode ("jnz", "%05d$", lbl->key + 100);
9261   }
9262   else if (IS_AOP_PREG (IC_RESULT (ic)))
9263     {
9264       emitcode ("dec", "%s",
9265                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9266       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9267       emitcode ("jnz", "%05d$", lbl->key + 100);
9268     }
9269   else
9270     {
9271       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9272                 lbl->key + 100);
9273     }
9274   emitcode ("sjmp", "%05d$", lbl1->key + 100);
9275   emitcode ("", "%05d$:", lbl->key + 100);
9276   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9277   emitcode ("", "%05d$:", lbl1->key + 100);
9278
9279   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9280   ifx->generated = 1;
9281   return 1;
9282 }
9283
9284 /*-----------------------------------------------------------------*/
9285 /* genReceive - generate code for a receive iCode                  */
9286 /*-----------------------------------------------------------------*/
9287 static void
9288 genReceive (iCode * ic)
9289 {
9290
9291   D (emitcode (";", "genReceive ");
9292     );
9293
9294   if (isOperandInFarSpace (IC_RESULT (ic)) &&
9295       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9296        IS_TRUE_SYMOP (IC_RESULT (ic))))
9297     {
9298       int size = getSize (operandType (IC_RESULT (ic)));
9299       int offset = fReturnSizeDS390 - size;
9300       while (size--)
9301         {
9302           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9303                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9304           offset++;
9305         }
9306       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9307       size = AOP_SIZE (IC_RESULT (ic));
9308       offset = 0;
9309       while (size--)
9310         {
9311           emitcode ("pop", "acc");
9312           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9313         }
9314
9315     }
9316   else
9317     {
9318       _G.accInUse++;
9319       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9320       _G.accInUse--;
9321       assignResultValue (IC_RESULT (ic));
9322     }
9323
9324   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9325 }
9326
9327 /*-----------------------------------------------------------------*/
9328 /* gen390Code - generate code for Dallas 390 based controllers     */
9329 /*-----------------------------------------------------------------*/
9330 void
9331 gen390Code (iCode * lic)
9332 {
9333   iCode *ic;
9334   int cln = 0;
9335
9336   lineHead = lineCurr = NULL;
9337
9338 #if 0
9339   //REMOVE ME!!!
9340   /* print the allocation information */
9341   if (allocInfo)
9342     printAllocInfo (currFunc, codeOutFile);
9343 #endif
9344   /* if debug information required */
9345   if (options.debug && currFunc)
9346     {
9347       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9348       _G.debugLine = 1;
9349       if (IS_STATIC (currFunc->etype))
9350         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9351       else
9352         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9353       _G.debugLine = 0;
9354     }
9355   /* stack pointer name */
9356   if (options.useXstack)
9357     spname = "_spx";
9358   else
9359     spname = "sp";
9360
9361
9362   for (ic = lic; ic; ic = ic->next)
9363     {
9364
9365       if (cln != ic->lineno)
9366         {
9367           if (options.debug)
9368             {
9369               _G.debugLine = 1;
9370               emitcode ("", "C$%s$%d$%d$%d ==.",
9371                         FileBaseName (ic->filename), ic->lineno,
9372                         ic->level, ic->block);
9373               _G.debugLine = 0;
9374             }
9375           emitcode (";", "%s %d", ic->filename, ic->lineno);
9376           cln = ic->lineno;
9377         }
9378       /* if the result is marked as
9379          spilt and rematerializable or code for
9380          this has already been generated then
9381          do nothing */
9382       if (resultRemat (ic) || ic->generated)
9383         continue;
9384
9385       /* depending on the operation */
9386       switch (ic->op)
9387         {
9388         case '!':
9389           genNot (ic);
9390           break;
9391
9392         case '~':
9393           genCpl (ic);
9394           break;
9395
9396         case UNARYMINUS:
9397           genUminus (ic);
9398           break;
9399
9400         case IPUSH:
9401           genIpush (ic);
9402           break;
9403
9404         case IPOP:
9405           /* IPOP happens only when trying to restore a
9406              spilt live range, if there is an ifx statement
9407              following this pop then the if statement might
9408              be using some of the registers being popped which
9409              would destory the contents of the register so
9410              we need to check for this condition and handle it */
9411           if (ic->next &&
9412               ic->next->op == IFX &&
9413               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9414             genIfx (ic->next, ic);
9415           else
9416             genIpop (ic);
9417           break;
9418
9419         case CALL:
9420           genCall (ic);
9421           break;
9422
9423         case PCALL:
9424           genPcall (ic);
9425           break;
9426
9427         case FUNCTION:
9428           genFunction (ic);
9429           break;
9430
9431         case ENDFUNCTION:
9432           genEndFunction (ic);
9433           break;
9434
9435         case RETURN:
9436           genRet (ic);
9437           break;
9438
9439         case LABEL:
9440           genLabel (ic);
9441           break;
9442
9443         case GOTO:
9444           genGoto (ic);
9445           break;
9446
9447         case '+':
9448           genPlus (ic);
9449           break;
9450
9451         case '-':
9452           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9453             genMinus (ic);
9454           break;
9455
9456         case '*':
9457           genMult (ic);
9458           break;
9459
9460         case '/':
9461           genDiv (ic);
9462           break;
9463
9464         case '%':
9465           genMod (ic);
9466           break;
9467
9468         case '>':
9469           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9470           break;
9471
9472         case '<':
9473           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9474           break;
9475
9476         case LE_OP:
9477         case GE_OP:
9478         case NE_OP:
9479
9480           /* note these two are xlated by algebraic equivalence
9481              during parsing SDCC.y */
9482           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9483                   "got '>=' or '<=' shouldn't have come here");
9484           break;
9485
9486         case EQ_OP:
9487           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9488           break;
9489
9490         case AND_OP:
9491           genAndOp (ic);
9492           break;
9493
9494         case OR_OP:
9495           genOrOp (ic);
9496           break;
9497
9498         case '^':
9499           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9500           break;
9501
9502         case '|':
9503           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9504           break;
9505
9506         case BITWISEAND:
9507           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9508           break;
9509
9510         case INLINEASM:
9511           genInline (ic);
9512           break;
9513
9514         case RRC:
9515           genRRC (ic);
9516           break;
9517
9518         case RLC:
9519           genRLC (ic);
9520           break;
9521
9522         case GETHBIT:
9523           genGetHbit (ic);
9524           break;
9525
9526         case LEFT_OP:
9527           genLeftShift (ic);
9528           break;
9529
9530         case RIGHT_OP:
9531           genRightShift (ic);
9532           break;
9533
9534         case GET_VALUE_AT_ADDRESS:
9535           genPointerGet (ic);
9536           break;
9537
9538         case '=':
9539           if (POINTER_SET (ic))
9540             genPointerSet (ic);
9541           else
9542             genAssign (ic);
9543           break;
9544
9545         case IFX:
9546           genIfx (ic, NULL);
9547           break;
9548
9549         case ADDRESS_OF:
9550           genAddrOf (ic);
9551           break;
9552
9553         case JUMPTABLE:
9554           genJumpTab (ic);
9555           break;
9556
9557         case CAST:
9558           genCast (ic);
9559           break;
9560
9561         case RECEIVE:
9562           genReceive (ic);
9563           break;
9564
9565         case SEND:
9566           addSet (&_G.sendSet, ic);
9567           break;
9568
9569         default:
9570           ic = ic;
9571         }
9572     }
9573
9574
9575   /* now we are ready to call the
9576      peep hole optimizer */
9577   if (!options.nopeep)
9578     peepHole (&lineHead);
9579
9580   /* now do the actual printing */
9581   printLine (lineHead, codeOutFile);
9582   return;
9583 }