fix several 'three operand in far space' problems
[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
1477   /* The generic part of a generic pointer should
1478    * not participate in it's truth value.
1479    *
1480    * i.e. 0x10000000 is zero.
1481    */
1482   if (opIsGptr (oper))
1483     {
1484       D (emitcode (";", "toBoolean: generic ptr special case.");
1485         );
1486       size--;
1487     }
1488
1489   _startLazyDPSEvaluation ();
1490   if (AOP_NEEDSACC (oper))
1491     {
1492       emitcode ("push", "b");
1493       emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1494     }
1495   else
1496     {
1497       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1498     }
1499   while (size--)
1500     {
1501       if (AOP_NEEDSACC (oper))
1502         {
1503           emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1504         }
1505       else
1506         {
1507           emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1508         }
1509     }
1510   _endLazyDPSEvaluation ();
1511
1512   if (AOP_NEEDSACC (oper))
1513     {
1514       emitcode ("mov", "a,b");
1515       emitcode ("pop", "b");
1516     }
1517 }
1518
1519
1520 /*-----------------------------------------------------------------*/
1521 /* genNot - generate code for ! operation                          */
1522 /*-----------------------------------------------------------------*/
1523 static void
1524 genNot (iCode * ic)
1525 {
1526   symbol *tlbl;
1527   sym_link *optype = operandType (IC_LEFT (ic));
1528
1529   D (emitcode (";", "genNot ");
1530     );
1531
1532   /* assign asmOps to operand & result */
1533   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1534   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1535
1536   /* if in bit space then a special case */
1537   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1538     {
1539       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1540       emitcode ("cpl", "c");
1541       outBitC (IC_RESULT (ic));
1542       goto release;
1543     }
1544
1545   /* if type float then do float */
1546   if (IS_FLOAT (optype))
1547     {
1548       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1549       goto release;
1550     }
1551
1552   toBoolean (IC_LEFT (ic));
1553
1554   tlbl = newiTempLabel (NULL);
1555   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1556   emitcode ("", "%05d$:", tlbl->key + 100);
1557   outBitC (IC_RESULT (ic));
1558
1559 release:
1560   /* release the aops */
1561   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1562   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1563 }
1564
1565
1566 /*-----------------------------------------------------------------*/
1567 /* genCpl - generate code for complement                           */
1568 /*-----------------------------------------------------------------*/
1569 static void
1570 genCpl (iCode * ic)
1571 {
1572   int offset = 0;
1573   int size;
1574
1575   D (emitcode (";", "genCpl ");
1576     );
1577
1578
1579   /* assign asmOps to operand & result */
1580   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1581   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1582
1583   /* if both are in bit space then
1584      a special case */
1585   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1586       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1587     {
1588
1589       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1590       emitcode ("cpl", "c");
1591       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1592       goto release;
1593     }
1594
1595   size = AOP_SIZE (IC_RESULT (ic));
1596   _startLazyDPSEvaluation ();
1597   while (size--)
1598     {
1599       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1600       MOVA (l);
1601       emitcode ("cpl", "a");
1602       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1603     }
1604   _endLazyDPSEvaluation ();
1605
1606
1607 release:
1608   /* release the aops */
1609   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1610   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1611 }
1612
1613 /*-----------------------------------------------------------------*/
1614 /* genUminusFloat - unary minus for floating points                */
1615 /*-----------------------------------------------------------------*/
1616 static void
1617 genUminusFloat (operand * op, operand * result)
1618 {
1619   int size, offset = 0;
1620   char *l;
1621   /* for this we just need to flip the
1622      first it then copy the rest in place */
1623   D (emitcode (";", "genUminusFloat");
1624     );
1625
1626   _startLazyDPSEvaluation ();
1627   size = AOP_SIZE (op) - 1;
1628   l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1629   MOVA (l);
1630
1631   emitcode ("cpl", "acc.7");
1632   aopPut (AOP (result), "a", 3);
1633
1634   while (size--)
1635     {
1636       aopPut (AOP (result),
1637               aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1638               offset);
1639       offset++;
1640     }
1641   _endLazyDPSEvaluation ();
1642 }
1643
1644 /*-----------------------------------------------------------------*/
1645 /* genUminus - unary minus code generation                         */
1646 /*-----------------------------------------------------------------*/
1647 static void
1648 genUminus (iCode * ic)
1649 {
1650   int offset, size;
1651   sym_link *optype, *rtype;
1652
1653   D (emitcode (";", "genUminus ");
1654     );
1655
1656
1657   /* assign asmops */
1658   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1659   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1660
1661   /* if both in bit space then special
1662      case */
1663   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1664       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1665     {
1666
1667       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1668       emitcode ("cpl", "c");
1669       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1670       goto release;
1671     }
1672
1673   optype = operandType (IC_LEFT (ic));
1674   rtype = operandType (IC_RESULT (ic));
1675
1676   /* if float then do float stuff */
1677   if (IS_FLOAT (optype))
1678     {
1679       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1680       goto release;
1681     }
1682
1683   /* otherwise subtract from zero */
1684   size = AOP_SIZE (IC_LEFT (ic));
1685   offset = 0;
1686   _startLazyDPSEvaluation ();
1687   while (size--)
1688     {
1689       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1690       if (!strcmp (l, "a"))
1691         {
1692           if (offset == 0)
1693             SETC;
1694           emitcode ("cpl", "a");
1695           emitcode ("addc", "a,#0");
1696         }
1697       else
1698         {
1699           if (offset == 0)
1700             CLRC;
1701           emitcode ("clr", "a");
1702           emitcode ("subb", "a,%s", l);
1703         }
1704       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1705     }
1706   _endLazyDPSEvaluation ();
1707
1708   /* if any remaining bytes in the result */
1709   /* we just need to propagate the sign   */
1710   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1711     {
1712       emitcode ("rlc", "a");
1713       emitcode ("subb", "a,acc");
1714       while (size--)
1715         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1716     }
1717
1718 release:
1719   /* release the aops */
1720   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1721   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1722 }
1723
1724 /*-----------------------------------------------------------------*/
1725 /* saveRegisters - will look for a call and save the registers     */
1726 /*-----------------------------------------------------------------*/
1727 static void
1728 saveRegisters (iCode * lic)
1729 {
1730   int i;
1731   iCode *ic;
1732   bitVect *rsave;
1733   sym_link *detype;
1734
1735   /* look for call */
1736   for (ic = lic; ic; ic = ic->next)
1737     if (ic->op == CALL || ic->op == PCALL)
1738       break;
1739
1740   if (!ic)
1741     {
1742       fprintf (stderr, "found parameter push with no function call\n");
1743       return;
1744     }
1745
1746   /* if the registers have been saved already then
1747      do nothing */
1748   if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1749     return;
1750
1751   /* find the registers in use at this time
1752      and push them away to safety */
1753   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1754                          ic->rUsed);
1755
1756   ic->regsSaved = 1;
1757   if (options.useXstack)
1758     {
1759       if (bitVectBitValue (rsave, R0_IDX))
1760         emitcode ("mov", "b,r0");
1761       emitcode ("mov", "r0,%s", spname);
1762       for (i = 0; i < ds390_nRegs; i++)
1763         {
1764           if (bitVectBitValue (rsave, i))
1765             {
1766               if (i == R0_IDX)
1767                 emitcode ("mov", "a,b");
1768               else
1769                 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1770               emitcode ("movx", "@r0,a");
1771               emitcode ("inc", "r0");
1772             }
1773         }
1774       emitcode ("mov", "%s,r0", spname);
1775       if (bitVectBitValue (rsave, R0_IDX))
1776         emitcode ("mov", "r0,b");
1777     }
1778   else
1779     for (i = 0; i < ds390_nRegs; i++)
1780       {
1781         if (bitVectBitValue (rsave, i))
1782           emitcode ("push", "%s ;jwk saveRegisters", ds390_regWithIdx (i)->dname);
1783       }
1784
1785   detype = getSpec (operandType (IC_LEFT (ic)));
1786   if (detype &&
1787       (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1788       IS_ISR (currFunc->etype) &&
1789       !ic->bankSaved)
1790
1791     saverbank (SPEC_BANK (detype), ic, TRUE);
1792
1793 }
1794 /*-----------------------------------------------------------------*/
1795 /* unsaveRegisters - pop the pushed registers                      */
1796 /*-----------------------------------------------------------------*/
1797 static void
1798 unsaveRegisters (iCode * ic)
1799 {
1800   int i;
1801   bitVect *rsave;
1802   /* find the registers in use at this time
1803      and push them away to safety */
1804   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1805                          ic->rUsed);
1806
1807   if (options.useXstack)
1808     {
1809       emitcode ("mov", "r0,%s", spname);
1810       for (i = ds390_nRegs; i >= 0; i--)
1811         {
1812           if (bitVectBitValue (rsave, i))
1813             {
1814               emitcode ("dec", "r0");
1815               emitcode ("movx", "a,@r0");
1816               if (i == R0_IDX)
1817                 emitcode ("mov", "b,a");
1818               else
1819                 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1820             }
1821
1822         }
1823       emitcode ("mov", "%s,r0", spname);
1824       if (bitVectBitValue (rsave, R0_IDX))
1825         emitcode ("mov", "r0,b");
1826     }
1827   else
1828     for (i = ds390_nRegs; i >= 0; i--)
1829       {
1830         if (bitVectBitValue (rsave, i))
1831           emitcode ("pop", "%s ;jwk unsaveRegisters", ds390_regWithIdx (i)->dname);
1832       }
1833
1834 }
1835
1836
1837 /*-----------------------------------------------------------------*/
1838 /* pushSide -                */
1839 /*-----------------------------------------------------------------*/
1840 static void
1841 pushSide (operand * oper, int size)
1842 {
1843   int offset = 0;
1844   _startLazyDPSEvaluation ();
1845   while (size--)
1846     {
1847       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1848       if (AOP_TYPE (oper) != AOP_REG &&
1849           AOP_TYPE (oper) != AOP_DIR &&
1850           strcmp (l, "a"))
1851         {
1852           emitcode ("mov", "a,%s", l);
1853           emitcode ("push", "acc");
1854         }
1855       else
1856         emitcode ("push", "%s", l);
1857     }
1858   _endLazyDPSEvaluation ();
1859 }
1860
1861 /*-----------------------------------------------------------------*/
1862 /* assignResultValue -               */
1863 /*-----------------------------------------------------------------*/
1864 static void
1865 assignResultValue (operand * oper)
1866 {
1867   int offset = 0;
1868   int size = AOP_SIZE (oper);
1869
1870   _startLazyDPSEvaluation ();
1871   while (size--)
1872     {
1873       aopPut (AOP (oper), fReturn[offset], offset);
1874       offset++;
1875     }
1876   _endLazyDPSEvaluation ();
1877 }
1878
1879
1880 /*-----------------------------------------------------------------*/
1881 /* genXpush - pushes onto the external stack                       */
1882 /*-----------------------------------------------------------------*/
1883 static void
1884 genXpush (iCode * ic)
1885 {
1886   asmop *aop = newAsmop (0);
1887   regs *r;
1888   int size, offset = 0;
1889
1890   D (emitcode (";", "genXpush ");
1891     );
1892
1893   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1894   r = getFreePtr (ic, &aop, FALSE);
1895
1896
1897   emitcode ("mov", "%s,_spx", r->name);
1898
1899   size = AOP_SIZE (IC_LEFT (ic));
1900   _startLazyDPSEvaluation ();
1901   while (size--)
1902     {
1903
1904       char *l = aopGet (AOP (IC_LEFT (ic)),
1905                         offset++, FALSE, FALSE, TRUE);
1906       MOVA (l);
1907       emitcode ("movx", "@%s,a", r->name);
1908       emitcode ("inc", "%s", r->name);
1909
1910     }
1911   _endLazyDPSEvaluation ();
1912
1913
1914   emitcode ("mov", "_spx,%s", r->name);
1915
1916   freeAsmop (NULL, aop, ic, TRUE);
1917   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1918 }
1919
1920 /*-----------------------------------------------------------------*/
1921 /* genIpush - genrate code for pushing this gets a little complex  */
1922 /*-----------------------------------------------------------------*/
1923 static void
1924 genIpush (iCode * ic)
1925 {
1926   int size, offset = 0;
1927   char *l;
1928
1929   D (emitcode (";", "genIpush ");
1930     );
1931
1932   /* if this is not a parm push : ie. it is spill push
1933      and spill push is always done on the local stack */
1934   if (!ic->parmPush)
1935     {
1936
1937       /* and the item is spilt then do nothing */
1938       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1939         return;
1940
1941       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1942       size = AOP_SIZE (IC_LEFT (ic));
1943       /* push it on the stack */
1944       _startLazyDPSEvaluation ();
1945       while (size--)
1946         {
1947           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1948           if (*l == '#')
1949             {
1950               MOVA (l);
1951               l = "acc";
1952             }
1953           emitcode ("push", "%s ;jwk genIpush: !parm", l);
1954         }
1955       _endLazyDPSEvaluation ();
1956       return;
1957     }
1958
1959   /* this is a paramter push: in this case we call
1960      the routine to find the call and save those
1961      registers that need to be saved */
1962   saveRegisters (ic);
1963
1964   /* if use external stack then call the external
1965      stack pushing routine */
1966   if (options.useXstack)
1967     {
1968       genXpush (ic);
1969       return;
1970     }
1971
1972   /* then do the push */
1973   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1974
1975   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1976   size = AOP_SIZE (IC_LEFT (ic));
1977
1978   _startLazyDPSEvaluation ();
1979   while (size--)
1980     {
1981       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
1982       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1983           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1984           strcmp (l, "a"))
1985         {
1986           emitcode ("mov", "a,%s", l);
1987           emitcode ("push", "acc");
1988         }
1989       else
1990         emitcode ("push", "%s ;jwk genIpush", l);
1991     }
1992   _endLazyDPSEvaluation ();
1993
1994   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1995 }
1996
1997 /*-----------------------------------------------------------------*/
1998 /* genIpop - recover the registers: can happen only for spilling   */
1999 /*-----------------------------------------------------------------*/
2000 static void
2001 genIpop (iCode * ic)
2002 {
2003   int size, offset;
2004
2005   D (emitcode (";", "genIpop ");
2006     );
2007
2008
2009   /* if the temp was not pushed then */
2010   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2011     return;
2012
2013   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2014   size = AOP_SIZE (IC_LEFT (ic));
2015   offset = (size - 1);
2016   _startLazyDPSEvaluation ();
2017   while (size--)
2018     {
2019       emitcode ("pop", "%s ;jwk genIpop", aopGet (AOP (IC_LEFT (ic)), offset--,
2020                                      FALSE, TRUE, TRUE));
2021     }
2022   _endLazyDPSEvaluation ();
2023
2024   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2025 }
2026
2027 /*-----------------------------------------------------------------*/
2028 /* unsaverbank - restores the resgister bank from stack            */
2029 /*-----------------------------------------------------------------*/
2030 static void
2031 unsaverbank (int bank, iCode * ic, bool popPsw)
2032 {
2033   int i;
2034   asmop *aop;
2035   regs *r = NULL;
2036
2037   if (popPsw)
2038     {
2039       if (options.useXstack)
2040         {
2041           aop = newAsmop (0);
2042           r = getFreePtr (ic, &aop, FALSE);
2043
2044
2045           emitcode ("mov", "%s,_spx", r->name);
2046           emitcode ("movx", "a,@%s", r->name);
2047           emitcode ("mov", "psw,a");
2048           emitcode ("dec", "%s", r->name);
2049
2050         }
2051       else
2052         emitcode ("pop", "psw");
2053     }
2054
2055   for (i = (ds390_nRegs - 1); i >= 0; i--)
2056     {
2057       if (options.useXstack)
2058         {
2059           emitcode ("movx", "a,@%s", r->name);
2060           emitcode ("mov", "(%s+%d),a",
2061                     regs390[i].base, 8 * bank + regs390[i].offset);
2062           emitcode ("dec", "%s", r->name);
2063
2064         }
2065       else
2066         emitcode ("pop", "(%s+%d)",
2067                   regs390[i].base, 8 * bank + regs390[i].offset);
2068     }
2069
2070   if (options.useXstack)
2071     {
2072
2073       emitcode ("mov", "_spx,%s", r->name);
2074       freeAsmop (NULL, aop, ic, TRUE);
2075
2076     }
2077 }
2078
2079 /*-----------------------------------------------------------------*/
2080 /* saverbank - saves an entire register bank on the stack          */
2081 /*-----------------------------------------------------------------*/
2082 static void
2083 saverbank (int bank, iCode * ic, bool pushPsw)
2084 {
2085   int i;
2086   asmop *aop;
2087   regs *r = NULL;
2088
2089   if (options.useXstack)
2090     {
2091
2092       aop = newAsmop (0);
2093       r = getFreePtr (ic, &aop, FALSE);
2094       emitcode ("mov", "%s,_spx", r->name);
2095
2096     }
2097
2098   for (i = 0; i < ds390_nRegs; i++)
2099     {
2100       if (options.useXstack)
2101         {
2102           emitcode ("inc", "%s", r->name);
2103           emitcode ("mov", "a,(%s+%d)",
2104                     regs390[i].base, 8 * bank + regs390[i].offset);
2105           emitcode ("movx", "@%s,a", r->name);
2106         }
2107       else
2108         emitcode ("push", "(%s+%d)",
2109                   regs390[i].base, 8 * bank + regs390[i].offset);
2110     }
2111
2112   if (pushPsw)
2113     {
2114       if (options.useXstack)
2115         {
2116           emitcode ("mov", "a,psw");
2117           emitcode ("movx", "@%s,a", r->name);
2118           emitcode ("inc", "%s", r->name);
2119           emitcode ("mov", "_spx,%s", r->name);
2120           freeAsmop (NULL, aop, ic, TRUE);
2121
2122         }
2123       else
2124         emitcode ("push", "psw");
2125
2126       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2127     }
2128   ic->bankSaved = 1;
2129
2130 }
2131
2132 /*-----------------------------------------------------------------*/
2133 /* genCall - generates a call statement                            */
2134 /*-----------------------------------------------------------------*/
2135 static void
2136 genCall (iCode * ic)
2137 {
2138   sym_link *detype;
2139
2140   D (emitcode (";", "genCall ");
2141     );
2142
2143   /* if caller saves & we have not saved then */
2144   if (!ic->regsSaved)
2145     saveRegisters (ic);
2146
2147   /* if we are calling a function that is not using
2148      the same register bank then we need to save the
2149      destination registers on the stack */
2150   detype = getSpec (operandType (IC_LEFT (ic)));
2151   if (detype &&
2152       (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2153       IS_ISR (currFunc->etype) &&
2154       !ic->bankSaved)
2155
2156     saverbank (SPEC_BANK (detype), ic, TRUE);
2157
2158   /* if send set is not empty the assign */
2159   if (_G.sendSet)
2160     {
2161       iCode *sic;
2162
2163       for (sic = setFirstItem (_G.sendSet); sic;
2164            sic = setNextItem (_G.sendSet))
2165         {
2166           int size, offset = 0;
2167
2168           aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2169           size = AOP_SIZE (IC_LEFT (sic));
2170
2171           _startLazyDPSEvaluation ();
2172           while (size--)
2173             {
2174               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2175                                 FALSE, FALSE, TRUE);
2176               if (strcmp (l, fReturn[offset])) {
2177                 genSetDPTR(0);
2178                 _flushLazyDPS();
2179                 emitcode ("mov", "%s,%s ;jwk lazy genCall",
2180                           fReturn[offset],
2181                           l);
2182               }
2183               offset++;
2184             }
2185           _endLazyDPSEvaluation ();
2186           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2187         }
2188       _G.sendSet = NULL;
2189     }
2190   /* make the call */
2191   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2192                             OP_SYMBOL (IC_LEFT (ic))->rname :
2193                             OP_SYMBOL (IC_LEFT (ic))->name));
2194
2195   /* if we need assign a result value */
2196   if ((IS_ITEMP (IC_RESULT (ic)) &&
2197        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2198         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2199       IS_TRUE_SYMOP (IC_RESULT (ic)))
2200     {
2201       if (isOperandInFarSpace (IC_RESULT (ic))
2202           && getSize (operandType (IC_RESULT (ic))) <= 2)
2203         {
2204           int size = getSize (operandType (IC_RESULT (ic)));
2205
2206           /* Special case for 1 or 2 byte return in far space. */
2207           emitcode (";", "Kevin function call abuse #1");
2208
2209           MOVA (fReturn[0]);
2210           if (size > 1)
2211             {
2212               emitcode ("mov", "b,%s", fReturn[1]);
2213             }
2214
2215           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2216           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2217
2218           if (size > 1)
2219             {
2220               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2221             }
2222           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2223         }
2224       else
2225         {
2226           _G.accInUse++;
2227           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2228           _G.accInUse--;
2229
2230           assignResultValue (IC_RESULT (ic));
2231
2232           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2233         }
2234     }
2235
2236   /* adjust the stack for parameters if
2237      required */
2238   if (ic->parmBytes)
2239     {
2240       int i;
2241       if (ic->parmBytes > 3)
2242         {
2243           emitcode ("mov", "a,%s", spname);
2244           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2245           emitcode ("mov", "%s,a", spname);
2246         }
2247       else
2248         for (i = 0; i < ic->parmBytes; i++)
2249           emitcode ("dec", "%s", spname);
2250
2251     }
2252
2253   /* if register bank was saved then pop them */
2254   if (ic->bankSaved)
2255     unsaverbank (SPEC_BANK (detype), ic, TRUE);
2256
2257   /* if we hade saved some registers then unsave them */
2258   if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2259     unsaveRegisters (ic);
2260
2261
2262 }
2263
2264 /*-----------------------------------------------------------------*/
2265 /* genPcall - generates a call by pointer statement                */
2266 /*-----------------------------------------------------------------*/
2267 static void
2268 genPcall (iCode * ic)
2269 {
2270   sym_link *detype;
2271   symbol *rlbl = newiTempLabel (NULL);
2272
2273   D (emitcode (";", "genPcall ");
2274     );
2275
2276
2277   /* if caller saves & we have not saved then */
2278   if (!ic->regsSaved)
2279     saveRegisters (ic);
2280
2281   /* if we are calling a function that is not using
2282      the same register bank then we need to save the
2283      destination registers on the stack */
2284   detype = getSpec (operandType (IC_LEFT (ic)));
2285   if (detype &&
2286       IS_ISR (currFunc->etype) &&
2287       (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2288     saverbank (SPEC_BANK (detype), ic, TRUE);
2289
2290
2291   /* push the return address on to the stack */
2292   emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2293   emitcode ("push", "acc");
2294   emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2295   emitcode ("push", "acc");
2296
2297   if (options.model == MODEL_FLAT24)
2298     {
2299       emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2300       emitcode ("push", "acc");
2301     }
2302
2303   /* now push the calling address */
2304   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2305
2306   pushSide (IC_LEFT (ic), FPTRSIZE);
2307
2308   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2309
2310   /* if send set is not empty the assign */
2311   if (_G.sendSet)
2312     {
2313       iCode *sic;
2314
2315       for (sic = setFirstItem (_G.sendSet); sic;
2316            sic = setNextItem (_G.sendSet))
2317         {
2318           int size, offset = 0;
2319
2320           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2321           size = AOP_SIZE (IC_LEFT (sic));
2322           _startLazyDPSEvaluation ();
2323           while (size--)
2324             {
2325               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2326                                 FALSE, FALSE, TRUE);
2327               if (strcmp (l, fReturn[offset]))
2328                 {
2329                   emitcode ("mov", "%s,%s",
2330                             fReturn[offset],
2331                             l);
2332                 }
2333               offset++;
2334             }
2335           _endLazyDPSEvaluation ();
2336           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2337         }
2338       _G.sendSet = NULL;
2339     }
2340
2341   emitcode ("ret", "");
2342   emitcode ("", "%05d$:", (rlbl->key + 100));
2343
2344
2345   /* if we need assign a result value */
2346   if ((IS_ITEMP (IC_RESULT (ic)) &&
2347        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2348         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2349       IS_TRUE_SYMOP (IC_RESULT (ic)))
2350     {
2351
2352       _G.accInUse++;
2353       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2354       _G.accInUse--;
2355
2356       assignResultValue (IC_RESULT (ic));
2357
2358       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2359     }
2360
2361   /* adjust the stack for parameters if
2362      required */
2363   if (ic->parmBytes)
2364     {
2365       int i;
2366       if (ic->parmBytes > 3)
2367         {
2368           emitcode ("mov", "a,%s", spname);
2369           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2370           emitcode ("mov", "%s,a", spname);
2371         }
2372       else
2373         for (i = 0; i < ic->parmBytes; i++)
2374           emitcode ("dec", "%s", spname);
2375
2376     }
2377
2378   /* if register bank was saved then unsave them */
2379   if (detype &&
2380       (SPEC_BANK (currFunc->etype) !=
2381        SPEC_BANK (detype)))
2382     unsaverbank (SPEC_BANK (detype), ic, TRUE);
2383
2384   /* if we hade saved some registers then
2385      unsave them */
2386   if (ic->regsSaved)
2387     unsaveRegisters (ic);
2388
2389 }
2390
2391 /*-----------------------------------------------------------------*/
2392 /* resultRemat - result  is rematerializable                       */
2393 /*-----------------------------------------------------------------*/
2394 static int
2395 resultRemat (iCode * ic)
2396 {
2397   if (SKIP_IC (ic) || ic->op == IFX)
2398     return 0;
2399
2400   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2401     {
2402       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2403       if (sym->remat && !POINTER_SET (ic))
2404         return 1;
2405     }
2406
2407   return 0;
2408 }
2409
2410 #if defined(__BORLANDC__) || defined(_MSC_VER)
2411 #define STRCASECMP stricmp
2412 #else
2413 #define STRCASECMP strcasecmp
2414 #endif
2415
2416 /*-----------------------------------------------------------------*/
2417 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2418 /*-----------------------------------------------------------------*/
2419 static bool
2420 inExcludeList (char *s)
2421 {
2422   int i = 0;
2423
2424   if (options.excludeRegs[i] &&
2425       STRCASECMP (options.excludeRegs[i], "none") == 0)
2426     return FALSE;
2427
2428   for (i = 0; options.excludeRegs[i]; i++)
2429     {
2430       if (options.excludeRegs[i] &&
2431           STRCASECMP (s, options.excludeRegs[i]) == 0)
2432         return TRUE;
2433     }
2434   return FALSE;
2435 }
2436
2437 /*-----------------------------------------------------------------*/
2438 /* genFunction - generated code for function entry                 */
2439 /*-----------------------------------------------------------------*/
2440 static void
2441 genFunction (iCode * ic)
2442 {
2443   symbol *sym;
2444   sym_link *fetype;
2445
2446   D (emitcode (";", "genFunction ");
2447     );
2448
2449   _G.nRegsSaved = 0;
2450   /* create the function header */
2451   emitcode (";", "-----------------------------------------");
2452   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2453   emitcode (";", "-----------------------------------------");
2454
2455   emitcode ("", "%s:", sym->rname);
2456   fetype = getSpec (operandType (IC_LEFT (ic)));
2457
2458   /* if critical function then turn interrupts off */
2459   if (SPEC_CRTCL (fetype))
2460     emitcode ("clr", "ea");
2461
2462   /* here we need to generate the equates for the
2463      register bank if required */
2464   if (SPEC_BANK (fetype) != rbank)
2465     {
2466       int i;
2467
2468       rbank = SPEC_BANK (fetype);
2469       for (i = 0; i < ds390_nRegs; i++)
2470         {
2471           if (strcmp (regs390[i].base, "0") == 0)
2472             emitcode ("", "%s = 0x%02x",
2473                       regs390[i].dname,
2474                       8 * rbank + regs390[i].offset);
2475           else
2476             emitcode ("", "%s = %s + 0x%02x",
2477                       regs390[i].dname,
2478                       regs390[i].base,
2479                       8 * rbank + regs390[i].offset);
2480         }
2481     }
2482
2483   /* if this is an interrupt service routine then
2484      save acc, b, dpl, dph  */
2485   if (IS_ISR (sym->etype))
2486     {
2487
2488       if (!inExcludeList ("acc"))
2489         emitcode ("push", "acc");
2490       if (!inExcludeList ("b"))
2491         emitcode ("push", "b");
2492       if (!inExcludeList ("dpl"))
2493         emitcode ("push", "dpl");
2494       if (!inExcludeList ("dph"))
2495         emitcode ("push", "dph");
2496       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2497         {
2498           emitcode ("push", "dpx");
2499           /* Make sure we're using standard DPTR */
2500           emitcode ("push", "dps");
2501           emitcode ("mov", "dps, #0x00");
2502           if (options.stack10bit)
2503             {
2504               /* This ISR could conceivably use DPTR2. Better save it. */
2505               emitcode ("push", "dpl1");
2506               emitcode ("push", "dph1");
2507               emitcode ("push", "dpx1");
2508               emitcode ("push",  DP2_RESULT_REG);
2509             }
2510         }
2511       /* if this isr has no bank i.e. is going to
2512          run with bank 0 , then we need to save more
2513          registers :-) */
2514       if (!SPEC_BANK (sym->etype))
2515         {
2516
2517           /* if this function does not call any other
2518              function then we can be economical and
2519              save only those registers that are used */
2520           if (!sym->hasFcall)
2521             {
2522               int i;
2523
2524               /* if any registers used */
2525               if (sym->regsUsed)
2526                 {
2527                   /* save the registers used */
2528                   for (i = 0; i < sym->regsUsed->size; i++)
2529                     {
2530                       if (bitVectBitValue (sym->regsUsed, i) ||
2531                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2532                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2533                     }
2534                 }
2535
2536             }
2537           else
2538             {
2539               /* this function has  a function call cannot
2540                  determines register usage so we will have the
2541                  entire bank */
2542               saverbank (0, ic, FALSE);
2543             }
2544         }
2545     }
2546   else
2547     {
2548       /* if callee-save to be used for this function
2549          then save the registers being used in this function */
2550       if (sym->calleeSave)
2551         {
2552           int i;
2553
2554           /* if any registers used */
2555           if (sym->regsUsed)
2556             {
2557               /* save the registers used */
2558               for (i = 0; i < sym->regsUsed->size; i++)
2559                 {
2560                   if (bitVectBitValue (sym->regsUsed, i) ||
2561                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2562                     {
2563                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2564                       _G.nRegsSaved++;
2565                     }
2566                 }
2567             }
2568         }
2569     }
2570
2571   /* set the register bank to the desired value */
2572   if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2573     {
2574       emitcode ("push", "psw");
2575       emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2576     }
2577
2578   if (IS_RENT (sym->etype) || options.stackAuto)
2579     {
2580
2581       if (options.useXstack)
2582         {
2583           emitcode ("mov", "r0,%s", spname);
2584           emitcode ("mov", "a,_bp");
2585           emitcode ("movx", "@r0,a");
2586           emitcode ("inc", "%s", spname);
2587         }
2588       else
2589         {
2590           /* set up the stack */
2591           emitcode ("push", "_bp");     /* save the callers stack  */
2592         }
2593       emitcode ("mov", "_bp,%s", spname);
2594     }
2595
2596   /* adjust the stack for the function */
2597   if (sym->stack)
2598     {
2599
2600       int i = sym->stack;
2601       if (i > 256)
2602         werror (W_STACK_OVERFLOW, sym->name);
2603
2604       if (i > 3 && sym->recvSize < 4)
2605         {
2606
2607           emitcode ("mov", "a,sp");
2608           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2609           emitcode ("mov", "sp,a");
2610
2611         }
2612       else
2613         while (i--)
2614           emitcode ("inc", "sp");
2615     }
2616
2617   if (sym->xstack)
2618     {
2619
2620       emitcode ("mov", "a,_spx");
2621       emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2622       emitcode ("mov", "_spx,a");
2623     }
2624
2625 }
2626
2627 /*-----------------------------------------------------------------*/
2628 /* genEndFunction - generates epilogue for functions               */
2629 /*-----------------------------------------------------------------*/
2630 static void
2631 genEndFunction (iCode * ic)
2632 {
2633   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2634
2635   D (emitcode (";", "genEndFunction ");
2636     );
2637
2638   if (IS_RENT (sym->etype) || options.stackAuto)
2639     {
2640       emitcode ("mov", "%s,_bp", spname);
2641     }
2642
2643   /* if use external stack but some variables were
2644      added to the local stack then decrement the
2645      local stack */
2646   if (options.useXstack && sym->stack)
2647     {
2648       emitcode ("mov", "a,sp");
2649       emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2650       emitcode ("mov", "sp,a");
2651     }
2652
2653
2654   if ((IS_RENT (sym->etype) || options.stackAuto))
2655     {
2656       if (options.useXstack)
2657         {
2658           emitcode ("mov", "r0,%s", spname);
2659           emitcode ("movx", "a,@r0");
2660           emitcode ("mov", "_bp,a");
2661           emitcode ("dec", "%s", spname);
2662         }
2663       else
2664         {
2665           emitcode ("pop", "_bp");
2666         }
2667     }
2668
2669   /* restore the register bank  */
2670   if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2671     emitcode ("pop", "psw");
2672
2673   if (IS_ISR (sym->etype))
2674     {
2675
2676       /* now we need to restore the registers */
2677       /* if this isr has no bank i.e. is going to
2678          run with bank 0 , then we need to save more
2679          registers :-) */
2680       if (!SPEC_BANK (sym->etype))
2681         {
2682
2683           /* if this function does not call any other
2684              function then we can be economical and
2685              save only those registers that are used */
2686           if (!sym->hasFcall)
2687             {
2688               int i;
2689
2690               /* if any registers used */
2691               if (sym->regsUsed)
2692                 {
2693                   /* save the registers used */
2694                   for (i = sym->regsUsed->size; i >= 0; i--)
2695                     {
2696                       if (bitVectBitValue (sym->regsUsed, i) ||
2697                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2698                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2699                     }
2700                 }
2701
2702             }
2703           else
2704             {
2705               /* this function has  a function call cannot
2706                  determines register usage so we will have the
2707                  entire bank */
2708               unsaverbank (0, ic, FALSE);
2709             }
2710         }
2711
2712       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2713         {
2714           if (options.stack10bit)
2715             {
2716               emitcode ("pop", DP2_RESULT_REG);
2717               emitcode ("pop", "dpx1");
2718               emitcode ("pop", "dph1");
2719               emitcode ("pop", "dpl1");
2720             }
2721           emitcode ("pop", "dps");
2722           emitcode ("pop", "dpx");
2723         }
2724       if (!inExcludeList ("dph"))
2725         emitcode ("pop", "dph");
2726       if (!inExcludeList ("dpl"))
2727         emitcode ("pop", "dpl");
2728       if (!inExcludeList ("b"))
2729         emitcode ("pop", "b");
2730       if (!inExcludeList ("acc"))
2731         emitcode ("pop", "acc");
2732
2733       if (SPEC_CRTCL (sym->etype))
2734         emitcode ("setb", "ea");
2735
2736       /* if debug then send end of function */
2737 /*  if (options.debug && currFunc) { */
2738       if (currFunc)
2739         {
2740           _G.debugLine = 1;
2741           emitcode ("", "C$%s$%d$%d$%d ==.",
2742                     FileBaseName (ic->filename), currFunc->lastLine,
2743                     ic->level, ic->block);
2744           if (IS_STATIC (currFunc->etype))
2745             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2746           else
2747             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2748           _G.debugLine = 0;
2749         }
2750
2751       emitcode ("reti", "");
2752     }
2753   else
2754     {
2755       if (SPEC_CRTCL (sym->etype))
2756         emitcode ("setb", "ea");
2757
2758       if (sym->calleeSave)
2759         {
2760           int i;
2761
2762           /* if any registers used */
2763           if (sym->regsUsed)
2764             {
2765               /* save the registers used */
2766               for (i = sym->regsUsed->size; i >= 0; i--)
2767                 {
2768                   if (bitVectBitValue (sym->regsUsed, i) ||
2769                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2770                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2771                 }
2772             }
2773
2774         }
2775
2776       /* if debug then send end of function */
2777       if (currFunc)
2778         {
2779           _G.debugLine = 1;
2780           emitcode ("", "C$%s$%d$%d$%d ==.",
2781                     FileBaseName (ic->filename), currFunc->lastLine,
2782                     ic->level, ic->block);
2783           if (IS_STATIC (currFunc->etype))
2784             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2785           else
2786             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2787           _G.debugLine = 0;
2788         }
2789
2790       emitcode ("ret", "");
2791     }
2792
2793 }
2794
2795 /*-----------------------------------------------------------------*/
2796 /* genRet - generate code for return statement                     */
2797 /*-----------------------------------------------------------------*/
2798 static void
2799 genRet (iCode * ic)
2800 {
2801   int size, offset = 0, pushed = 0;
2802
2803   D (emitcode (";", "genRet ");
2804     );
2805
2806   /* if we have no return value then
2807      just generate the "ret" */
2808   if (!IC_LEFT (ic))
2809     goto jumpret;
2810
2811   /* we have something to return then
2812      move the return value into place */
2813   aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2814   size = AOP_SIZE (IC_LEFT (ic));
2815
2816   _startLazyDPSEvaluation ();
2817   while (size--)
2818     {
2819       char *l;
2820       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2821         {
2822           l = aopGet (AOP (IC_LEFT (ic)), offset++,
2823                       FALSE, TRUE, FALSE);
2824           emitcode ("push", "%s", l);
2825           pushed++;
2826         }
2827       else
2828         {
2829           l = aopGet (AOP (IC_LEFT (ic)), offset,
2830                       FALSE, FALSE, FALSE);
2831           if (strcmp (fReturn[offset], l))
2832             emitcode ("mov", "%s,%s", fReturn[offset++], l);
2833         }
2834     }
2835   _endLazyDPSEvaluation ();
2836
2837   if (pushed)
2838     {
2839       while (pushed)
2840         {
2841           pushed--;
2842           if (strcmp (fReturn[pushed], "a"))
2843             emitcode ("pop", fReturn[pushed]);
2844           else
2845             emitcode ("pop", "acc");
2846         }
2847     }
2848   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2849
2850 jumpret:
2851   /* generate a jump to the return label
2852      if the next is not the return statement */
2853   if (!(ic->next && ic->next->op == LABEL &&
2854         IC_LABEL (ic->next) == returnLabel))
2855
2856     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2857
2858 }
2859
2860 /*-----------------------------------------------------------------*/
2861 /* genLabel - generates a label                                    */
2862 /*-----------------------------------------------------------------*/
2863 static void
2864 genLabel (iCode * ic)
2865 {
2866   /* special case never generate */
2867   if (IC_LABEL (ic) == entryLabel)
2868     return;
2869
2870   D (emitcode (";", "genLabel ");
2871     );
2872
2873   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2874 }
2875
2876 /*-----------------------------------------------------------------*/
2877 /* genGoto - generates a ljmp                                      */
2878 /*-----------------------------------------------------------------*/
2879 static void
2880 genGoto (iCode * ic)
2881 {
2882   D (emitcode (";", "genGoto ");
2883     );
2884   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2885 }
2886
2887 /*-----------------------------------------------------------------*/
2888 /* findLabelBackwards: walks back through the iCode chain looking  */
2889 /* for the given label. Returns number of iCode instructions     */
2890 /* between that label and given ic.          */
2891 /* Returns zero if label not found.          */
2892 /*-----------------------------------------------------------------*/
2893 static int
2894 findLabelBackwards (iCode * ic, int key)
2895 {
2896   int count = 0;
2897
2898   while (ic->prev)
2899     {
2900       ic = ic->prev;
2901       count++;
2902
2903       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2904         {
2905           /* printf("findLabelBackwards = %d\n", count); */
2906           return count;
2907         }
2908     }
2909
2910   return 0;
2911 }
2912
2913 /*-----------------------------------------------------------------*/
2914 /* genPlusIncr :- does addition with increment if possible         */
2915 /*-----------------------------------------------------------------*/
2916 static bool
2917 genPlusIncr (iCode * ic)
2918 {
2919   unsigned int icount;
2920   unsigned int size = getDataSize (IC_RESULT (ic));
2921
2922   /* will try to generate an increment */
2923   /* if the right side is not a literal
2924      we cannot */
2925   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2926     return FALSE;
2927
2928   /* if the literal value of the right hand side
2929      is greater than 4 then it is not worth it */
2930   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2931     return FALSE;
2932
2933   /* if increment 16 bits in register */
2934   if (
2935        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
2936        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
2937        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2938        (size > 1) &&
2939        (icount == 1))
2940     {
2941       symbol *tlbl;
2942       int emitTlbl;
2943       int labelRange;
2944
2945       /* If the next instruction is a goto and the goto target
2946        * is <= 5 instructions previous to this, we can generate
2947        * jumps straight to that target.
2948        */
2949       if (ic->next && ic->next->op == GOTO
2950           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2951           && labelRange <= 5)
2952         {
2953           emitcode (";", "tail increment optimized (range %d)", labelRange);
2954           tlbl = IC_LABEL (ic->next);
2955           emitTlbl = 0;
2956         }
2957       else
2958         {
2959           tlbl = newiTempLabel (NULL);
2960           emitTlbl = 1;
2961         }
2962       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
2963       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2964           IS_AOP_PREG (IC_RESULT (ic)))
2965         emitcode ("cjne", "%s,#0x00,%05d$"
2966                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2967                   ,tlbl->key + 100);
2968       else
2969         {
2970           emitcode ("clr", "a");
2971           emitcode ("cjne", "a,%s,%05d$"
2972                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2973                     ,tlbl->key + 100);
2974         }
2975
2976       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
2977       if (size > 2)
2978         {
2979           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2980               IS_AOP_PREG (IC_RESULT (ic)))
2981             emitcode ("cjne", "%s,#0x00,%05d$"
2982                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2983                       ,tlbl->key + 100);
2984           else
2985             emitcode ("cjne", "a,%s,%05d$"
2986                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2987                       ,tlbl->key + 100);
2988
2989           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
2990         }
2991       if (size > 3)
2992         {
2993           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2994               IS_AOP_PREG (IC_RESULT (ic)))
2995             emitcode ("cjne", "%s,#0x00,%05d$"
2996                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
2997                       ,tlbl->key + 100);
2998           else
2999             {
3000               emitcode ("cjne", "a,%s,%05d$"
3001                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3002                         ,tlbl->key + 100);
3003             }
3004           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3005         }
3006
3007       if (emitTlbl)
3008         {
3009           emitcode ("", "%05d$:", tlbl->key + 100);
3010         }
3011       return TRUE;
3012     }
3013
3014   /* if the sizes are greater than 1 then we cannot */
3015   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3016       AOP_SIZE (IC_LEFT (ic)) > 1)
3017     return FALSE;
3018
3019   /* we can if the aops of the left & result match or
3020      if they are in registers and the registers are the
3021      same */
3022   if (
3023        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3024        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3025        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3026     {
3027
3028       if (icount > 3)
3029         {
3030           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3031           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3032           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3033         }
3034       else
3035         {
3036
3037           _startLazyDPSEvaluation ();
3038           while (icount--)
3039             {
3040               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3041             }
3042           _endLazyDPSEvaluation ();
3043         }
3044
3045       return TRUE;
3046     }
3047
3048   return FALSE;
3049 }
3050
3051 /*-----------------------------------------------------------------*/
3052 /* outBitAcc - output a bit in acc                                 */
3053 /*-----------------------------------------------------------------*/
3054 static void
3055 outBitAcc (operand * result)
3056 {
3057   symbol *tlbl = newiTempLabel (NULL);
3058   /* if the result is a bit */
3059   if (AOP_TYPE (result) == AOP_CRY)
3060     {
3061       aopPut (AOP (result), "a", 0);
3062     }
3063   else
3064     {
3065       emitcode ("jz", "%05d$", tlbl->key + 100);
3066       emitcode ("mov", "a,%s", one);
3067       emitcode ("", "%05d$:", tlbl->key + 100);
3068       outAcc (result);
3069     }
3070 }
3071
3072 /*-----------------------------------------------------------------*/
3073 /* genPlusBits - generates code for addition of two bits           */
3074 /*-----------------------------------------------------------------*/
3075 static void
3076 genPlusBits (iCode * ic)
3077 {
3078   D (emitcode (";", "genPlusBits ");
3079     );
3080   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3081     {
3082       symbol *lbl = newiTempLabel (NULL);
3083       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3084       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3085       emitcode ("cpl", "c");
3086       emitcode ("", "%05d$:", (lbl->key + 100));
3087       outBitC (IC_RESULT (ic));
3088     }
3089   else
3090     {
3091       emitcode ("clr", "a");
3092       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3093       emitcode ("rlc", "a");
3094       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3095       emitcode ("addc", "a,#0x00");
3096       outAcc (IC_RESULT (ic));
3097     }
3098 }
3099
3100 static void
3101 adjustArithmeticResult (iCode * ic)
3102 {
3103   if (opIsGptr (IC_RESULT (ic)) &&
3104       opIsGptr (IC_LEFT (ic)) &&
3105       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3106     {
3107       aopPut (AOP (IC_RESULT (ic)),
3108               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3109               GPTRSIZE - 1);
3110     }
3111
3112   if (opIsGptr (IC_RESULT (ic)) &&
3113       opIsGptr (IC_RIGHT (ic)) &&
3114       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3115     {
3116       aopPut (AOP (IC_RESULT (ic)),
3117             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3118               GPTRSIZE - 1);
3119     }
3120
3121   if (opIsGptr (IC_RESULT (ic)) &&
3122       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3123       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3124       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3125       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3126     {
3127       char buffer[5];
3128       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3129       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3130     }
3131 }
3132
3133 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3134 // (because all three operands are in far space).
3135 #define AOP_OP_3(ic) \
3136     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3137     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3138     aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3139               (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3140     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3141         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3142     { \
3143         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3144         fprintf(stderr,                                  \
3145                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3146     }
3147
3148 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3149 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3150 // will be set TRUE. The caller must then handle the case specially, noting
3151 // that the IC_RESULT operand is not aopOp'd.
3152 #define AOP_OP_3_NOFATAL(ic, rc) \
3153     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3154     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3155     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3156         isOperandInFarSpace(IC_RESULT(ic))) \
3157     { \
3158        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3159        rc = TRUE; \
3160     }  \
3161     else \
3162     { \
3163        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3164                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3165        rc = FALSE; \
3166        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3167            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3168        { \
3169             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3170             fprintf(stderr,                                  \
3171                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3172        } \
3173     }
3174
3175 // aopOp the left & right operands of an ic.
3176 #define AOP_OP_2(ic) \
3177     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3178     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3179
3180 // convienience macro.
3181 #define AOP_SET_LOCALS(ic) \
3182     left = IC_LEFT(ic); \
3183     right = IC_RIGHT(ic); \
3184     result = IC_RESULT(ic);
3185
3186
3187 // Given an integer value of pushedSize bytes on the stack,
3188 // adjust it to be resultSize bytes, either by discarding
3189 // the most significant bytes or by zero-padding.
3190 //
3191 // On exit from this macro, pushedSize will have been adjusted to
3192 // equal resultSize, and ACC may be trashed.
3193 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3194       /* If the pushed data is bigger than the result,          \
3195        * simply discard unused bytes. Icky, but works.          \
3196        */                                                       \
3197       while (pushedSize > resultSize)                           \
3198       {                                                         \
3199           D (emitcode (";", "discarding unused result byte."););\
3200           emitcode ("pop", "acc");                              \
3201           pushedSize--;                                         \
3202       }                                                         \
3203       if (pushedSize < resultSize)                              \
3204       {                                                         \
3205           emitcode ("clr", "a");                                \
3206           /* Conversly, we haven't pushed enough here.          \
3207            * just zero-pad, and all is well.                    \
3208            */                                                   \
3209           while (pushedSize < resultSize)                       \
3210           {                                                     \
3211               emitcode("push", "acc");                          \
3212               pushedSize++;                                     \
3213           }                                                     \
3214       }                                                         \
3215       assert(pushedSize == resultSize);
3216
3217 /*-----------------------------------------------------------------*/
3218 /* genPlus - generates code for addition                           */
3219 /*-----------------------------------------------------------------*/
3220 static void
3221 genPlus (iCode * ic)
3222 {
3223   int size, offset = 0;
3224   bool pushResult = FALSE;
3225   int rSize;
3226
3227   D (emitcode (";", "genPlus "););
3228
3229   /* special cases :- */
3230
3231   AOP_OP_3_NOFATAL (ic, pushResult);
3232   if (pushResult)
3233     {
3234       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3235     }
3236
3237   if (!pushResult)
3238     {
3239       /* if literal, literal on the right or
3240          if left requires ACC or right is already
3241          in ACC */
3242       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3243        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3244           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3245         {
3246           operand *t = IC_RIGHT (ic);
3247           IC_RIGHT (ic) = IC_LEFT (ic);
3248           IC_LEFT (ic) = t;
3249           emitcode (";", "Swapped plus args.");
3250         }
3251
3252       /* if both left & right are in bit
3253          space */
3254       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3255           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3256         {
3257           genPlusBits (ic);
3258           goto release;
3259         }
3260
3261       /* if left in bit space & right literal */
3262       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3263           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3264         {
3265           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3266           /* if result in bit space */
3267           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3268             {
3269               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3270                 emitcode ("cpl", "c");
3271               outBitC (IC_RESULT (ic));
3272             }
3273           else
3274             {
3275               size = getDataSize (IC_RESULT (ic));
3276               _startLazyDPSEvaluation ();
3277               while (size--)
3278                 {
3279                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3280                   emitcode ("addc", "a,#00");
3281                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3282                 }
3283               _endLazyDPSEvaluation ();
3284             }
3285           goto release;
3286         }
3287
3288       /* if I can do an increment instead
3289          of add then GOOD for ME */
3290       if (genPlusIncr (ic) == TRUE)
3291         {
3292           emitcode (";", "did genPlusIncr");
3293           goto release;
3294         }
3295
3296     }
3297   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3298
3299   _startLazyDPSEvaluation ();
3300   while (size--)
3301     {
3302       if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3303         {
3304           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3305           if (offset == 0)
3306             emitcode ("add", "a,%s",
3307                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3308           else
3309             emitcode ("addc", "a,%s",
3310                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3311         }
3312       else
3313         {
3314           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3315           if (offset == 0)
3316             emitcode ("add", "a,%s",
3317                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3318           else
3319             emitcode ("addc", "a,%s",
3320                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3321         }
3322       if (!pushResult)
3323         {
3324           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3325         }
3326       else
3327         {
3328           emitcode ("push", "acc");
3329         }
3330       offset++;
3331     }
3332   _endLazyDPSEvaluation ();
3333
3334   if (pushResult)
3335     {
3336       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3337
3338       size = getDataSize (IC_LEFT (ic));
3339       rSize = getDataSize (IC_RESULT (ic));
3340
3341       ADJUST_PUSHED_RESULT(size, rSize);
3342
3343       _startLazyDPSEvaluation ();
3344       while (size--)
3345         {
3346           emitcode ("pop", "acc");
3347           aopPut (AOP (IC_RESULT (ic)), "a", size);
3348         }
3349       _endLazyDPSEvaluation ();
3350     }
3351
3352   adjustArithmeticResult (ic);
3353
3354 release:
3355   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3356   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3357   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3358 }
3359
3360 /*-----------------------------------------------------------------*/
3361 /* genMinusDec :- does subtraction with deccrement if possible     */
3362 /*-----------------------------------------------------------------*/
3363 static bool
3364 genMinusDec (iCode * ic)
3365 {
3366   unsigned int icount;
3367   unsigned int size = getDataSize (IC_RESULT (ic));
3368
3369   /* will try to generate an increment */
3370   /* if the right side is not a literal
3371      we cannot */
3372   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3373     return FALSE;
3374
3375   /* if the literal value of the right hand side
3376      is greater than 4 then it is not worth it */
3377   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3378     return FALSE;
3379
3380   /* if decrement 16 bits in register */
3381   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3382       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3383       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3384       (size > 1) &&
3385       (icount == 1))
3386     {
3387       symbol *tlbl;
3388       int emitTlbl;
3389       int labelRange;
3390
3391       /* If the next instruction is a goto and the goto target
3392          * is <= 5 instructions previous to this, we can generate
3393          * jumps straight to that target.
3394        */
3395       if (ic->next && ic->next->op == GOTO
3396           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3397           && labelRange <= 5)
3398         {
3399           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3400           tlbl = IC_LABEL (ic->next);
3401           emitTlbl = 0;
3402         }
3403       else
3404         {
3405           tlbl = newiTempLabel (NULL);
3406           emitTlbl = 1;
3407         }
3408
3409       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3410       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3411           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3412           IS_AOP_PREG (IC_RESULT (ic)))
3413         emitcode ("cjne", "%s,#0xff,%05d$"
3414                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3415                   ,tlbl->key + 100);
3416       else
3417         {
3418           emitcode ("mov", "a,#0xff");
3419           emitcode ("cjne", "a,%s,%05d$"
3420                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3421                     ,tlbl->key + 100);
3422         }
3423       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3424       if (size > 2)
3425         {
3426           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3427               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3428               IS_AOP_PREG (IC_RESULT (ic)))
3429             emitcode ("cjne", "%s,#0xff,%05d$"
3430                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3431                       ,tlbl->key + 100);
3432           else
3433             {
3434               emitcode ("cjne", "a,%s,%05d$"
3435                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3436                         ,tlbl->key + 100);
3437             }
3438           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3439         }
3440       if (size > 3)
3441         {
3442           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3443               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3444               IS_AOP_PREG (IC_RESULT (ic)))
3445             emitcode ("cjne", "%s,#0xff,%05d$"
3446                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3447                       ,tlbl->key + 100);
3448           else
3449             {
3450               emitcode ("cjne", "a,%s,%05d$"
3451                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3452                         ,tlbl->key + 100);
3453             }
3454           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3455         }
3456       if (emitTlbl)
3457         {
3458           emitcode ("", "%05d$:", tlbl->key + 100);
3459         }
3460       return TRUE;
3461     }
3462
3463   /* if the sizes are greater than 1 then we cannot */
3464   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3465       AOP_SIZE (IC_LEFT (ic)) > 1)
3466     return FALSE;
3467
3468   /* we can if the aops of the left & result match or
3469      if they are in registers and the registers are the
3470      same */
3471   if (
3472        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3473        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3474        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3475     {
3476
3477       _startLazyDPSEvaluation ();
3478       while (icount--)
3479         {
3480           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3481         }
3482       _endLazyDPSEvaluation ();
3483
3484       return TRUE;
3485     }
3486
3487   return FALSE;
3488 }
3489
3490 /*-----------------------------------------------------------------*/
3491 /* addSign - complete with sign                                    */
3492 /*-----------------------------------------------------------------*/
3493 static void
3494 addSign (operand * result, int offset, int sign)
3495 {
3496   int size = (getDataSize (result) - offset);
3497   if (size > 0)
3498     {
3499       if (sign)
3500         {
3501           emitcode ("rlc", "a");
3502           emitcode ("subb", "a,acc");
3503           while (size--)
3504             aopPut (AOP (result), "a", offset++);
3505         }
3506       else
3507         while (size--)
3508           aopPut (AOP (result), zero, offset++);
3509     }
3510 }
3511
3512 /*-----------------------------------------------------------------*/
3513 /* genMinusBits - generates code for subtraction  of two bits      */
3514 /*-----------------------------------------------------------------*/
3515 static void
3516 genMinusBits (iCode * ic)
3517 {
3518   symbol *lbl = newiTempLabel (NULL);
3519
3520   D (emitcode (";", "genMinusBits ");
3521     );
3522
3523   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3524     {
3525       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3526       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3527       emitcode ("cpl", "c");
3528       emitcode ("", "%05d$:", (lbl->key + 100));
3529       outBitC (IC_RESULT (ic));
3530     }
3531   else
3532     {
3533       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3534       emitcode ("subb", "a,acc");
3535       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3536       emitcode ("inc", "a");
3537       emitcode ("", "%05d$:", (lbl->key + 100));
3538       aopPut (AOP (IC_RESULT (ic)), "a", 0);
3539       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3540     }
3541 }
3542
3543 /*-----------------------------------------------------------------*/
3544 /* genMinus - generates code for subtraction                       */
3545 /*-----------------------------------------------------------------*/
3546 static void
3547 genMinus (iCode * ic)
3548 {
3549   int size, offset = 0;
3550   int rSize;
3551   unsigned long lit = 0L;
3552   bool pushResult = FALSE;
3553
3554   D (emitcode (";", "genMinus "););
3555
3556   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3557   aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3558   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3559       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3560     {
3561       pushResult = TRUE;
3562     }
3563   else
3564     {
3565       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3566
3567       /* special cases :- */
3568       /* if both left & right are in bit space */
3569       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3570           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3571         {
3572           genMinusBits (ic);
3573           goto release;
3574         }
3575
3576       /* if I can do an decrement instead
3577          of subtract then GOOD for ME */
3578       if (genMinusDec (ic) == TRUE)
3579         goto release;
3580
3581     }
3582
3583   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3584
3585   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3586     {
3587       CLRC;
3588     }
3589   else
3590     {
3591       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3592       lit = -(long) lit;
3593     }
3594
3595
3596   /* if literal, add a,#-lit, else normal subb */
3597   _startLazyDPSEvaluation ();
3598   while (size--)
3599     {
3600       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3601       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3602         emitcode ("subb", "a,%s",
3603                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3604       else
3605         {
3606           /* first add without previous c */
3607           if (!offset)
3608             emitcode ("add", "a,#0x%02x",
3609                       (unsigned int) (lit & 0x0FFL));
3610           else
3611             emitcode ("addc", "a,#0x%02x",
3612                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3613         }
3614
3615       if (pushResult)
3616         {
3617           emitcode ("push", "acc");
3618         }
3619       else
3620         {
3621           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3622         }
3623       offset++;
3624     }
3625   _endLazyDPSEvaluation ();
3626
3627   if (pushResult)
3628     {
3629       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3630
3631       size = getDataSize (IC_LEFT (ic));
3632       rSize = getDataSize (IC_RESULT (ic));
3633
3634       ADJUST_PUSHED_RESULT(size, rSize);
3635
3636       _startLazyDPSEvaluation ();
3637       while (size--)
3638         {
3639           emitcode ("pop", "acc");
3640           aopPut (AOP (IC_RESULT (ic)), "a", size);
3641         }
3642       _endLazyDPSEvaluation ();
3643     }
3644
3645   adjustArithmeticResult (ic);
3646
3647 release:
3648   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3649   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3650   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3651 }
3652
3653
3654 /*-----------------------------------------------------------------*/
3655 /* genMultbits :- multiplication of bits                           */
3656 /*-----------------------------------------------------------------*/
3657 static void
3658 genMultbits (operand * left,
3659              operand * right,
3660              operand * result)
3661 {
3662   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3663   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3664   outBitC (result);
3665 }
3666
3667
3668 /*-----------------------------------------------------------------*/
3669 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
3670 /*-----------------------------------------------------------------*/
3671 static void
3672 genMultOneByte (operand * left,
3673                 operand * right,
3674                 operand * result)
3675 {
3676   sym_link *opetype = operandType (result);
3677   symbol *lbl;
3678   int size=AOP_SIZE(result);
3679
3680   emitcode (";",__FUNCTION__);
3681   if (size<1 || size>2) {
3682     // this should never happen
3683       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
3684                AOP_SIZE(result), __FUNCTION__, lineno);
3685       exit (1);
3686   }
3687
3688   /* (if two literals: the value is computed before) */
3689   /* if one literal, literal on the right */
3690   if (AOP_TYPE (left) == AOP_LIT)
3691     {
3692       operand *t = right;
3693       right = left;
3694       left = t;
3695       emitcode (";", "swapped left and right");
3696     }
3697
3698   if (SPEC_USIGN(opetype)
3699       // ignore the sign of left and right, what else can we do?
3700       || (SPEC_USIGN(operandType(left)) && 
3701           SPEC_USIGN(operandType(right)))) {
3702     // just an unsigned 8*8=8/16 multiply
3703     //emitcode (";","unsigned");
3704     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3705     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3706     emitcode ("mul", "ab");
3707     aopPut (AOP (result), "a", 0);
3708     if (size==2) {
3709       aopPut (AOP (result), "b", 1);
3710     }
3711     return;
3712   }
3713
3714   // we have to do a signed multiply
3715
3716   emitcode (";", "signed");
3717   emitcode ("clr", "F0"); // reset sign flag
3718   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3719   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3720
3721   lbl=newiTempLabel(NULL);
3722   emitcode ("jnb", "acc.7,%05d$",  lbl->key+100);
3723   // left side is negative, 8-bit two's complement, this fails for -128
3724   emitcode ("setb", "F0"); // set sign flag
3725   emitcode ("cpl", "a");
3726   emitcode ("inc", "a");
3727
3728   emitcode ("", "%05d$:", lbl->key+100);
3729   emitcode ("xch", "a,b");
3730
3731   /* if literal */
3732   if (AOP_TYPE(right)==AOP_LIT) {
3733     /* AND literal negative */
3734     if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3735       // two's complement for literal<0
3736       emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3737       emitcode ("cpl", "a");
3738       emitcode ("inc", "a");
3739     }
3740   } else {
3741     lbl=newiTempLabel(NULL);
3742     emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3743     // right side is negative, 8-bit two's complement
3744     emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3745     emitcode ("cpl", "a");
3746     emitcode ("inc", "a");
3747     emitcode ("", "%05d$:", lbl->key+100);
3748   }
3749   emitcode ("mul", "ab");
3750     
3751   lbl=newiTempLabel(NULL);
3752   emitcode ("jnb", "F0,%05d$", lbl->key+100);
3753   // only ONE op was negative, we have to do a 8/16-bit two's complement
3754   emitcode ("cpl", "a"); // lsb
3755   if (size==1) {
3756     emitcode ("inc", "a");
3757   } else {
3758     emitcode ("add", "a,#1");
3759     emitcode ("xch", "a,b");
3760     emitcode ("cpl", "a"); // msb
3761     emitcode ("addc", "a,#0");
3762     emitcode ("xch", "a,b");
3763   }
3764
3765   emitcode ("", "%05d$:", lbl->key+100);
3766   aopPut (AOP (result), "a", 0);
3767   if (size==2) {
3768     aopPut (AOP (result), "b", 1);
3769   }
3770 }
3771
3772 /*-----------------------------------------------------------------*/
3773 /* genMult - generates code for multiplication                     */
3774 /*-----------------------------------------------------------------*/
3775 static void
3776 genMult (iCode * ic)
3777 {
3778   operand *left = IC_LEFT (ic);
3779   operand *right = IC_RIGHT (ic);
3780   operand *result = IC_RESULT (ic);
3781
3782   D (emitcode (";", "genMult "););
3783
3784   /* assign the amsops */
3785   AOP_OP_3 (ic);
3786
3787   /* special cases first */
3788   /* both are bits */
3789   if (AOP_TYPE (left) == AOP_CRY &&
3790       AOP_TYPE (right) == AOP_CRY)
3791     {
3792       genMultbits (left, right, result);
3793       goto release;
3794     }
3795
3796   /* if both are of size == 1 */
3797   if (AOP_SIZE (left) == 1 &&
3798       AOP_SIZE (right) == 1)
3799     {
3800       genMultOneByte (left, right, result);
3801       goto release;
3802     }
3803
3804   /* should have been converted to function call */
3805   assert (1);
3806
3807 release:
3808   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3809   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3810   freeAsmop (result, NULL, ic, TRUE);
3811 }
3812
3813 /*-----------------------------------------------------------------*/
3814 /* genDivbits :- division of bits                                  */
3815 /*-----------------------------------------------------------------*/
3816 static void
3817 genDivbits (operand * left,
3818             operand * right,
3819             operand * result)
3820 {
3821
3822   char *l;
3823
3824   /* the result must be bit */
3825   LOAD_AB_FOR_DIV (left, right, l);
3826   emitcode ("div", "ab");
3827   emitcode ("rrc", "a");
3828   aopPut (AOP (result), "c", 0);
3829 }
3830
3831 /*-----------------------------------------------------------------*/
3832 /* genDivOneByte : 8 bit division                                  */
3833 /*-----------------------------------------------------------------*/
3834 static void
3835 genDivOneByte (operand * left,
3836                operand * right,
3837                operand * result)
3838 {
3839   sym_link *opetype = operandType (result);
3840   char *l;
3841   symbol *lbl;
3842   int size, offset;
3843
3844   size = AOP_SIZE (result) - 1;
3845   offset = 1;
3846   /* signed or unsigned */
3847   if (SPEC_USIGN (opetype))
3848     {
3849       /* unsigned is easy */
3850       LOAD_AB_FOR_DIV (left, right, l);
3851       emitcode ("div", "ab");
3852       aopPut (AOP (result), "a", 0);
3853       while (size--)
3854         aopPut (AOP (result), zero, offset++);
3855       return;
3856     }
3857
3858   /* signed is a little bit more difficult */
3859
3860   /* save the signs of the operands */
3861   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3862   MOVA (l);
3863   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3864   emitcode ("push", "acc");     /* save it on the stack */
3865
3866   /* now sign adjust for both left & right */
3867   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3868   MOVA (l);
3869   lbl = newiTempLabel (NULL);
3870   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3871   emitcode ("cpl", "a");
3872   emitcode ("inc", "a");
3873   emitcode ("", "%05d$:", (lbl->key + 100));
3874   emitcode ("mov", "b,a");
3875
3876   /* sign adjust left side */
3877   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3878   MOVA (l);
3879
3880   lbl = newiTempLabel (NULL);
3881   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3882   emitcode ("cpl", "a");
3883   emitcode ("inc", "a");
3884   emitcode ("", "%05d$:", (lbl->key + 100));
3885
3886   /* now the division */
3887   emitcode ("nop", "; workaround for DS80C390 div bug.");
3888   emitcode ("div", "ab");
3889   /* we are interested in the lower order
3890      only */
3891   emitcode ("mov", "b,a");
3892   lbl = newiTempLabel (NULL);
3893   emitcode ("pop", "acc");
3894   /* if there was an over flow we don't
3895      adjust the sign of the result */
3896   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3897   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3898   CLRC;
3899   emitcode ("clr", "a");
3900   emitcode ("subb", "a,b");
3901   emitcode ("mov", "b,a");
3902   emitcode ("", "%05d$:", (lbl->key + 100));
3903
3904   /* now we are done */
3905   aopPut (AOP (result), "b", 0);
3906   if (size > 0)
3907     {
3908       emitcode ("mov", "c,b.7");
3909       emitcode ("subb", "a,acc");
3910     }
3911   while (size--)
3912     aopPut (AOP (result), "a", offset++);
3913
3914 }
3915
3916 /*-----------------------------------------------------------------*/
3917 /* genDiv - generates code for division                            */
3918 /*-----------------------------------------------------------------*/
3919 static void
3920 genDiv (iCode * ic)
3921 {
3922   operand *left = IC_LEFT (ic);
3923   operand *right = IC_RIGHT (ic);
3924   operand *result = IC_RESULT (ic);
3925
3926   D (emitcode (";", "genDiv ");
3927     );
3928
3929   /* assign the amsops */
3930   AOP_OP_3 (ic);
3931
3932   /* special cases first */
3933   /* both are bits */
3934   if (AOP_TYPE (left) == AOP_CRY &&
3935       AOP_TYPE (right) == AOP_CRY)
3936     {
3937       genDivbits (left, right, result);
3938       goto release;
3939     }
3940
3941   /* if both are of size == 1 */
3942   if (AOP_SIZE (left) == 1 &&
3943       AOP_SIZE (right) == 1)
3944     {
3945       genDivOneByte (left, right, result);
3946       goto release;
3947     }
3948
3949   /* should have been converted to function call */
3950   assert (1);
3951 release:
3952   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3953   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3954   freeAsmop (result, NULL, ic, TRUE);
3955 }
3956
3957 /*-----------------------------------------------------------------*/
3958 /* genModbits :- modulus of bits                                   */
3959 /*-----------------------------------------------------------------*/
3960 static void
3961 genModbits (operand * left,
3962             operand * right,
3963             operand * result)
3964 {
3965
3966   char *l;
3967
3968   /* the result must be bit */
3969   LOAD_AB_FOR_DIV (left, right, l);
3970   emitcode ("div", "ab");
3971   emitcode ("mov", "a,b");
3972   emitcode ("rrc", "a");
3973   aopPut (AOP (result), "c", 0);
3974 }
3975
3976 /*-----------------------------------------------------------------*/
3977 /* genModOneByte : 8 bit modulus                                   */
3978 /*-----------------------------------------------------------------*/
3979 static void
3980 genModOneByte (operand * left,
3981                operand * right,
3982                operand * result)
3983 {
3984   sym_link *opetype = operandType (result);
3985   char *l;
3986   symbol *lbl;
3987
3988   /* signed or unsigned */
3989   if (SPEC_USIGN (opetype))
3990     {
3991       /* unsigned is easy */
3992       LOAD_AB_FOR_DIV (left, right, l);
3993       emitcode ("div", "ab");
3994       aopPut (AOP (result), "b", 0);
3995       return;
3996     }
3997
3998   /* signed is a little bit more difficult */
3999
4000   /* save the signs of the operands */
4001   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4002   MOVA (l);
4003
4004   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4005   emitcode ("push", "acc");     /* save it on the stack */
4006
4007   /* now sign adjust for both left & right */
4008   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4009   MOVA (l);
4010
4011   lbl = newiTempLabel (NULL);
4012   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4013   emitcode ("cpl", "a");
4014   emitcode ("inc", "a");
4015   emitcode ("", "%05d$:", (lbl->key + 100));
4016   emitcode ("mov", "b,a");
4017
4018   /* sign adjust left side */
4019   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4020   MOVA (l);
4021
4022   lbl = newiTempLabel (NULL);
4023   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4024   emitcode ("cpl", "a");
4025   emitcode ("inc", "a");
4026   emitcode ("", "%05d$:", (lbl->key + 100));
4027
4028   /* now the multiplication */
4029   emitcode ("nop", "; workaround for DS80C390 div bug.");
4030   emitcode ("div", "ab");
4031   /* we are interested in the lower order
4032      only */
4033   lbl = newiTempLabel (NULL);
4034   emitcode ("pop", "acc");
4035   /* if there was an over flow we don't
4036      adjust the sign of the result */
4037   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4038   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4039   CLRC;
4040   emitcode ("clr", "a");
4041   emitcode ("subb", "a,b");
4042   emitcode ("mov", "b,a");
4043   emitcode ("", "%05d$:", (lbl->key + 100));
4044
4045   /* now we are done */
4046   aopPut (AOP (result), "b", 0);
4047
4048 }
4049
4050 /*-----------------------------------------------------------------*/
4051 /* genMod - generates code for division                            */
4052 /*-----------------------------------------------------------------*/
4053 static void
4054 genMod (iCode * ic)
4055 {
4056   operand *left = IC_LEFT (ic);
4057   operand *right = IC_RIGHT (ic);
4058   operand *result = IC_RESULT (ic);
4059
4060   D (emitcode (";", "genMod ");
4061     );
4062
4063   /* assign the amsops */
4064   AOP_OP_3 (ic);
4065
4066   /* special cases first */
4067   /* both are bits */
4068   if (AOP_TYPE (left) == AOP_CRY &&
4069       AOP_TYPE (right) == AOP_CRY)
4070     {
4071       genModbits (left, right, result);
4072       goto release;
4073     }
4074
4075   /* if both are of size == 1 */
4076   if (AOP_SIZE (left) == 1 &&
4077       AOP_SIZE (right) == 1)
4078     {
4079       genModOneByte (left, right, result);
4080       goto release;
4081     }
4082
4083   /* should have been converted to function call */
4084   assert (1);
4085
4086 release:
4087   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4088   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4089   freeAsmop (result, NULL, ic, TRUE);
4090 }
4091
4092 /*-----------------------------------------------------------------*/
4093 /* genIfxJump :- will create a jump depending on the ifx           */
4094 /*-----------------------------------------------------------------*/
4095 static void
4096 genIfxJump (iCode * ic, char *jval)
4097 {
4098   symbol *jlbl;
4099   symbol *tlbl = newiTempLabel (NULL);
4100   char *inst;
4101
4102   D (emitcode (";", "genIfxJump ");
4103     );
4104
4105   /* if true label then we jump if condition
4106      supplied is true */
4107   if (IC_TRUE (ic))
4108     {
4109       jlbl = IC_TRUE (ic);
4110       inst = ((strcmp (jval, "a") == 0 ? "jz" :
4111                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4112     }
4113   else
4114     {
4115       /* false label is present */
4116       jlbl = IC_FALSE (ic);
4117       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4118                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4119     }
4120   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4121     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4122   else
4123     emitcode (inst, "%05d$", tlbl->key + 100);
4124   emitcode ("ljmp", "%05d$", jlbl->key + 100);
4125   emitcode ("", "%05d$:", tlbl->key + 100);
4126
4127   /* mark the icode as generated */
4128   ic->generated = 1;
4129 }
4130
4131 /*-----------------------------------------------------------------*/
4132 /* genCmp :- greater or less than comparison                       */
4133 /*-----------------------------------------------------------------*/
4134 static void
4135 genCmp (operand * left, operand * right,
4136         iCode * ic, iCode * ifx, int sign)
4137 {
4138   int size, offset = 0;
4139   unsigned long lit = 0L;
4140   operand *result;
4141
4142   D (emitcode (";", "genCmp");
4143     );
4144
4145   result = IC_RESULT (ic);
4146
4147   /* if left & right are bit variables */
4148   if (AOP_TYPE (left) == AOP_CRY &&
4149       AOP_TYPE (right) == AOP_CRY)
4150     {
4151       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4152       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4153     }
4154   else
4155     {
4156       /* subtract right from left if at the
4157          end the carry flag is set then we know that
4158          left is greater than right */
4159       size = max (AOP_SIZE (left), AOP_SIZE (right));
4160
4161       /* if unsigned char cmp with lit, do cjne left,#right,zz */
4162       if ((size == 1) && !sign &&
4163           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4164         {
4165           symbol *lbl = newiTempLabel (NULL);
4166           emitcode ("cjne", "%s,%s,%05d$",
4167                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4168                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4169                     lbl->key + 100);
4170           emitcode ("", "%05d$:", lbl->key + 100);
4171         }
4172       else
4173         {
4174           if (AOP_TYPE (right) == AOP_LIT)
4175             {
4176               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4177               /* optimize if(x < 0) or if(x >= 0) */
4178               if (lit == 0L)
4179                 {
4180                   if (!sign)
4181                     {
4182                       CLRC;
4183                     }
4184                   else
4185                     {
4186                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4187
4188                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4189                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4190
4191                       aopOp (result, ic, FALSE, FALSE);
4192
4193                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4194                         {
4195                           freeAsmop (result, NULL, ic, TRUE);
4196                           genIfxJump (ifx, "acc.7");
4197                           return;
4198                         }
4199                       else
4200                         {
4201                           emitcode ("rlc", "a");
4202                         }
4203                       goto release_freedLR;
4204                     }
4205                   goto release;
4206                 }
4207             }
4208           CLRC;
4209           while (size--)
4210             {
4211               emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4212               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4213               emitcode (";", "genCmp #2");
4214               if (sign && (size == 0))
4215                 {
4216                   emitcode (";", "genCmp #3");
4217                   emitcode ("xrl", "a,#0x80");
4218                   if (AOP_TYPE (right) == AOP_LIT)
4219                     {
4220                       unsigned long lit = (unsigned long)
4221                       floatFromVal (AOP (right)->aopu.aop_lit);
4222                       emitcode (";", "genCmp #3.1");
4223                       emitcode ("subb", "a,#0x%02x",
4224                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4225                     }
4226                   else
4227                     {
4228                       emitcode (";", "genCmp #3.2");
4229                       if (AOP_NEEDSACC (right))
4230                         {
4231                           emitcode ("push", "acc");
4232                         }
4233                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4234                                                        FALSE, FALSE, FALSE));
4235                       emitcode ("xrl", "b,#0x80");
4236                       if (AOP_NEEDSACC (right))
4237                         {
4238                           emitcode ("pop", "acc");
4239                         }
4240                       emitcode ("subb", "a,b");
4241                     }
4242                 }
4243               else
4244                 {
4245                   const char *s;
4246
4247                   emitcode (";", "genCmp #4");
4248                   if (AOP_NEEDSACC (right))
4249                     {
4250                       /* Yuck!! */
4251                       emitcode (";", "genCmp #4.1");
4252                       emitcode ("xch", "a, b");
4253                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4254                       emitcode ("xch", "a, b");
4255                       s = "b";
4256                     }
4257                   else
4258                     {
4259                       emitcode (";", "genCmp #4.2");
4260                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4261                     }
4262
4263                   emitcode ("subb", "a,%s", s);
4264                 }
4265             }
4266         }
4267     }
4268
4269 release:
4270 /* Don't need the left & right operands any more; do need the result. */
4271   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4272   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4273
4274   aopOp (result, ic, FALSE, FALSE);
4275
4276 release_freedLR:
4277
4278   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4279     {
4280       outBitC (result);
4281     }
4282   else
4283     {
4284       /* if the result is used in the next
4285          ifx conditional branch then generate
4286          code a little differently */
4287       if (ifx)
4288         {
4289           genIfxJump (ifx, "c");
4290         }
4291       else
4292         {
4293           outBitC (result);
4294         }
4295       /* leave the result in acc */
4296     }
4297   freeAsmop (result, NULL, ic, TRUE);
4298 }
4299
4300 /*-----------------------------------------------------------------*/
4301 /* genCmpGt :- greater than comparison                             */
4302 /*-----------------------------------------------------------------*/
4303 static void
4304 genCmpGt (iCode * ic, iCode * ifx)
4305 {
4306   operand *left, *right;
4307   sym_link *letype, *retype;
4308   int sign;
4309
4310   D (emitcode (";", "genCmpGt ");
4311     );
4312
4313   left = IC_LEFT (ic);
4314   right = IC_RIGHT (ic);
4315
4316   letype = getSpec (operandType (left));
4317   retype = getSpec (operandType (right));
4318   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4319
4320   /* assign the left & right amsops */
4321   AOP_OP_2 (ic);
4322
4323   genCmp (right, left, ic, ifx, sign);
4324 }
4325
4326 /*-----------------------------------------------------------------*/
4327 /* genCmpLt - less than comparisons                                */
4328 /*-----------------------------------------------------------------*/
4329 static void
4330 genCmpLt (iCode * ic, iCode * ifx)
4331 {
4332   operand *left, *right;
4333   sym_link *letype, *retype;
4334   int sign;
4335
4336   D (emitcode (";", "genCmpLt ");
4337     );
4338
4339   left = IC_LEFT (ic);
4340   right = IC_RIGHT (ic);
4341
4342   letype = getSpec (operandType (left));
4343   retype = getSpec (operandType (right));
4344   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4345
4346   /* assign the left & right amsops */
4347   AOP_OP_2 (ic);
4348
4349   genCmp (left, right, ic, ifx, sign);
4350 }
4351
4352 /*-----------------------------------------------------------------*/
4353 /* gencjneshort - compare and jump if not equal                    */
4354 /*-----------------------------------------------------------------*/
4355 static void
4356 gencjneshort (operand * left, operand * right, symbol * lbl)
4357 {
4358   int size = max (AOP_SIZE (left), AOP_SIZE (right));
4359   int offset = 0;
4360   unsigned long lit = 0L;
4361
4362   D (emitcode (";", "gencjneshort");
4363     );
4364
4365   /* if the left side is a literal or
4366      if the right is in a pointer register and left
4367      is not */
4368   if ((AOP_TYPE (left) == AOP_LIT) ||
4369       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4370     {
4371       operand *t = right;
4372       right = left;
4373       left = t;
4374     }
4375
4376   if (AOP_TYPE (right) == AOP_LIT)
4377     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4378
4379   if (opIsGptr (left) || opIsGptr (right))
4380     {
4381       /* We are comparing a generic pointer to something.
4382        * Exclude the generic type byte from the comparison.
4383        */
4384       size--;
4385       D (emitcode (";", "cjneshort: generic ptr special case.");
4386         )
4387     }
4388
4389
4390   /* if the right side is a literal then anything goes */
4391   if (AOP_TYPE (right) == AOP_LIT &&
4392       AOP_TYPE (left) != AOP_DIR)
4393     {
4394       while (size--)
4395         {
4396           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4397           MOVA (l);
4398           emitcode ("cjne", "a,%s,%05d$",
4399                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4400                     lbl->key + 100);
4401           offset++;
4402         }
4403     }
4404
4405   /* if the right side is in a register or in direct space or
4406      if the left is a pointer register & right is not */
4407   else if (AOP_TYPE (right) == AOP_REG ||
4408            AOP_TYPE (right) == AOP_DIR ||
4409            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4410            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4411     {
4412       while (size--)
4413         {
4414           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4415           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4416               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4417             emitcode ("jnz", "%05d$", lbl->key + 100);
4418           else
4419             emitcode ("cjne", "a,%s,%05d$",
4420                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4421                       lbl->key + 100);
4422           offset++;
4423         }
4424     }
4425   else
4426     {
4427       /* right is a pointer reg need both a & b */
4428       while (size--)
4429         {
4430           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4431           if (strcmp (l, "b"))
4432             emitcode ("mov", "b,%s", l);
4433           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4434           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4435           offset++;
4436         }
4437     }
4438 }
4439
4440 /*-----------------------------------------------------------------*/
4441 /* gencjne - compare and jump if not equal                         */
4442 /*-----------------------------------------------------------------*/
4443 static void
4444 gencjne (operand * left, operand * right, symbol * lbl)
4445 {
4446   symbol *tlbl = newiTempLabel (NULL);
4447
4448   D (emitcode (";", "gencjne");
4449     );
4450
4451   gencjneshort (left, right, lbl);
4452
4453   emitcode ("mov", "a,%s", one);
4454   emitcode ("sjmp", "%05d$", tlbl->key + 100);
4455   emitcode ("", "%05d$:", lbl->key + 100);
4456   emitcode ("clr", "a");
4457   emitcode ("", "%05d$:", tlbl->key + 100);
4458 }
4459
4460 /*-----------------------------------------------------------------*/
4461 /* genCmpEq - generates code for equal to                          */
4462 /*-----------------------------------------------------------------*/
4463 static void
4464 genCmpEq (iCode * ic, iCode * ifx)
4465 {
4466   operand *left, *right, *result;
4467
4468   D (emitcode (";", "genCmpEq ");
4469     );
4470
4471   AOP_OP_2 (ic);
4472   AOP_SET_LOCALS (ic);
4473
4474   /* if literal, literal on the right or
4475      if the right is in a pointer register and left
4476      is not */
4477   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4478       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4479     {
4480       operand *t = IC_RIGHT (ic);
4481       IC_RIGHT (ic) = IC_LEFT (ic);
4482       IC_LEFT (ic) = t;
4483     }
4484
4485   if (ifx &&                    /* !AOP_SIZE(result) */
4486       OP_SYMBOL (result) &&
4487       OP_SYMBOL (result)->regType == REG_CND)
4488     {
4489       symbol *tlbl;
4490       /* if they are both bit variables */
4491       if (AOP_TYPE (left) == AOP_CRY &&
4492           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4493         {
4494           if (AOP_TYPE (right) == AOP_LIT)
4495             {
4496               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4497               if (lit == 0L)
4498                 {
4499                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4500                   emitcode ("cpl", "c");
4501                 }
4502               else if (lit == 1L)
4503                 {
4504                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4505                 }
4506               else
4507                 {
4508                   emitcode ("clr", "c");
4509                 }
4510               /* AOP_TYPE(right) == AOP_CRY */
4511             }
4512           else
4513             {
4514               symbol *lbl = newiTempLabel (NULL);
4515               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4516               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4517               emitcode ("cpl", "c");
4518               emitcode ("", "%05d$:", (lbl->key + 100));
4519             }
4520           /* if true label then we jump if condition
4521              supplied is true */
4522           tlbl = newiTempLabel (NULL);
4523           if (IC_TRUE (ifx))
4524             {
4525               emitcode ("jnc", "%05d$", tlbl->key + 100);
4526               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4527             }
4528           else
4529             {
4530               emitcode ("jc", "%05d$", tlbl->key + 100);
4531               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4532             }
4533           emitcode ("", "%05d$:", tlbl->key + 100);
4534         }
4535       else
4536         {
4537           tlbl = newiTempLabel (NULL);
4538           gencjneshort (left, right, tlbl);
4539           if (IC_TRUE (ifx))
4540             {
4541               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4542               emitcode ("", "%05d$:", tlbl->key + 100);
4543             }
4544           else
4545             {
4546               symbol *lbl = newiTempLabel (NULL);
4547               emitcode ("sjmp", "%05d$", lbl->key + 100);
4548               emitcode ("", "%05d$:", tlbl->key + 100);
4549               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4550               emitcode ("", "%05d$:", lbl->key + 100);
4551             }
4552         }
4553       /* mark the icode as generated */
4554       ifx->generated = 1;
4555
4556       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4557       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4558       return;
4559     }
4560
4561   /* if they are both bit variables */
4562   if (AOP_TYPE (left) == AOP_CRY &&
4563       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4564     {
4565       if (AOP_TYPE (right) == AOP_LIT)
4566         {
4567           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4568           if (lit == 0L)
4569             {
4570               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4571               emitcode ("cpl", "c");
4572             }
4573           else if (lit == 1L)
4574             {
4575               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4576             }
4577           else
4578             {
4579               emitcode ("clr", "c");
4580             }
4581           /* AOP_TYPE(right) == AOP_CRY */
4582         }
4583       else
4584         {
4585           symbol *lbl = newiTempLabel (NULL);
4586           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4587           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4588           emitcode ("cpl", "c");
4589           emitcode ("", "%05d$:", (lbl->key + 100));
4590         }
4591
4592       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4593       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4594
4595       aopOp (result, ic, TRUE, FALSE);
4596
4597       /* c = 1 if egal */
4598       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4599         {
4600           outBitC (result);
4601           goto release;
4602         }
4603       if (ifx)
4604         {
4605           genIfxJump (ifx, "c");
4606           goto release;
4607         }
4608       /* if the result is used in an arithmetic operation
4609          then put the result in place */
4610       outBitC (result);
4611     }
4612   else
4613     {
4614       gencjne (left, right, newiTempLabel (NULL));
4615
4616       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4617       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4618
4619       aopOp (result, ic, TRUE, FALSE);
4620
4621       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4622         {
4623           aopPut (AOP (result), "a", 0);
4624           goto release;
4625         }
4626       if (ifx)
4627         {
4628           genIfxJump (ifx, "a");
4629           goto release;
4630         }
4631       /* if the result is used in an arithmetic operation
4632          then put the result in place */
4633       if (AOP_TYPE (result) != AOP_CRY)
4634         outAcc (result);
4635       /* leave the result in acc */
4636     }
4637
4638 release:
4639   freeAsmop (result, NULL, ic, TRUE);
4640 }
4641
4642 /*-----------------------------------------------------------------*/
4643 /* ifxForOp - returns the icode containing the ifx for operand     */
4644 /*-----------------------------------------------------------------*/
4645 static iCode *
4646 ifxForOp (operand * op, iCode * ic)
4647 {
4648   /* if true symbol then needs to be assigned */
4649   if (IS_TRUE_SYMOP (op))
4650     return NULL;
4651
4652   /* if this has register type condition and
4653      the next instruction is ifx with the same operand
4654      and live to of the operand is upto the ifx only then */
4655   if (ic->next &&
4656       ic->next->op == IFX &&
4657       IC_COND (ic->next)->key == op->key &&
4658       OP_SYMBOL (op)->liveTo <= ic->next->seq)
4659     return ic->next;
4660
4661   return NULL;
4662 }
4663 /*-----------------------------------------------------------------*/
4664 /* genAndOp - for && operation                                     */
4665 /*-----------------------------------------------------------------*/
4666 static void
4667 genAndOp (iCode * ic)
4668 {
4669   operand *left, *right, *result;
4670   symbol *tlbl;
4671
4672   D (emitcode (";", "genAndOp "););
4673
4674   /* note here that && operations that are in an
4675      if statement are taken away by backPatchLabels
4676      only those used in arthmetic operations remain */
4677   AOP_OP_2 (ic);
4678   AOP_SET_LOCALS (ic);
4679
4680   /* if both are bit variables */
4681   if (AOP_TYPE (left) == AOP_CRY &&
4682       AOP_TYPE (right) == AOP_CRY)
4683     {
4684       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4685       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4686       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4687       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4688   
4689       aopOp (result,ic,FALSE, FALSE);
4690       outBitC (result);
4691     }
4692   else
4693     {
4694       tlbl = newiTempLabel (NULL);
4695       toBoolean (left);
4696       emitcode ("jz", "%05d$", tlbl->key + 100);
4697       toBoolean (right);
4698       emitcode ("", "%05d$:", tlbl->key + 100);
4699       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4700       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4701   
4702       aopOp (result,ic,FALSE, FALSE);
4703       outBitAcc (result);
4704     }
4705     freeAsmop (result, NULL, ic, TRUE);
4706 }
4707
4708
4709 /*-----------------------------------------------------------------*/
4710 /* genOrOp - for || operation                                      */
4711 /*-----------------------------------------------------------------*/
4712 static void
4713 genOrOp (iCode * ic)
4714 {
4715   operand *left, *right, *result;
4716   symbol *tlbl;
4717
4718   D (emitcode (";", "genOrOp "););
4719
4720   /* note here that || operations that are in an
4721      if statement are taken away by backPatchLabels
4722      only those used in arthmetic operations remain */
4723   AOP_OP_2 (ic);
4724   AOP_SET_LOCALS (ic);
4725
4726   /* if both are bit variables */
4727   if (AOP_TYPE (left) == AOP_CRY &&
4728       AOP_TYPE (right) == AOP_CRY)
4729     {
4730       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4731       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4732       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4733       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4734   
4735       aopOp (result,ic,FALSE, FALSE);
4736       
4737       outBitC (result);
4738     }
4739   else
4740     {
4741       tlbl = newiTempLabel (NULL);
4742       toBoolean (left);
4743       emitcode ("jnz", "%05d$", tlbl->key + 100);
4744       toBoolean (right);
4745       emitcode ("", "%05d$:", tlbl->key + 100);
4746       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4747       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4748   
4749       aopOp (result,ic,FALSE, FALSE);
4750       
4751       outBitAcc (result);
4752     }
4753
4754   freeAsmop (result, NULL, ic, TRUE);
4755 }
4756
4757 /*-----------------------------------------------------------------*/
4758 /* isLiteralBit - test if lit == 2^n                               */
4759 /*-----------------------------------------------------------------*/
4760 static int
4761 isLiteralBit (unsigned long lit)
4762 {
4763   unsigned long pw[32] =
4764   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4765    0x100L, 0x200L, 0x400L, 0x800L,
4766    0x1000L, 0x2000L, 0x4000L, 0x8000L,
4767    0x10000L, 0x20000L, 0x40000L, 0x80000L,
4768    0x100000L, 0x200000L, 0x400000L, 0x800000L,
4769    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4770    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4771   int idx;
4772
4773   for (idx = 0; idx < 32; idx++)
4774     if (lit == pw[idx])
4775       return idx + 1;
4776   return 0;
4777 }
4778
4779 /*-----------------------------------------------------------------*/
4780 /* continueIfTrue -                                                */
4781 /*-----------------------------------------------------------------*/
4782 static void
4783 continueIfTrue (iCode * ic)
4784 {
4785   if (IC_TRUE (ic))
4786     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4787   ic->generated = 1;
4788 }
4789
4790 /*-----------------------------------------------------------------*/
4791 /* jmpIfTrue -                                                     */
4792 /*-----------------------------------------------------------------*/
4793 static void
4794 jumpIfTrue (iCode * ic)
4795 {
4796   if (!IC_TRUE (ic))
4797     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4798   ic->generated = 1;
4799 }
4800
4801 /*-----------------------------------------------------------------*/
4802 /* jmpTrueOrFalse -                                                */
4803 /*-----------------------------------------------------------------*/
4804 static void
4805 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4806 {
4807   // ugly but optimized by peephole
4808   if (IC_TRUE (ic))
4809     {
4810       symbol *nlbl = newiTempLabel (NULL);
4811       emitcode ("sjmp", "%05d$", nlbl->key + 100);
4812       emitcode ("", "%05d$:", tlbl->key + 100);
4813       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4814       emitcode ("", "%05d$:", nlbl->key + 100);
4815     }
4816   else
4817     {
4818       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4819       emitcode ("", "%05d$:", tlbl->key + 100);
4820     }
4821   ic->generated = 1;
4822 }
4823
4824 // Generate code to perform a bit-wise logic operation
4825 // on two operands in far space (assumed to already have been 
4826 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
4827 // in far space. This requires pushing the result on the stack
4828 // then popping it into the result.
4829 static void
4830 genFarFarLogicOp(iCode *ic, char *logicOp)
4831 {
4832       int size, resultSize, compSize;
4833       int offset = 0;
4834       
4835       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
4836       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
4837                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
4838       
4839       _startLazyDPSEvaluation();
4840       for (size = compSize; (size--); offset++)
4841       {
4842           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
4843           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
4844           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
4845           
4846           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
4847           emitcode ("push", "acc");
4848       }
4849       _endLazyDPSEvaluation();
4850      
4851       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4852       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4853       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
4854      
4855       resultSize = AOP_SIZE(IC_RESULT(ic));
4856
4857       ADJUST_PUSHED_RESULT(compSize, resultSize);
4858
4859       _startLazyDPSEvaluation();
4860       while (compSize--)
4861       {
4862           emitcode ("pop", "acc");
4863           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
4864       }
4865       _endLazyDPSEvaluation();
4866       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
4867 }
4868
4869
4870 /*-----------------------------------------------------------------*/
4871 /* genAnd  - code for and                                          */
4872 /*-----------------------------------------------------------------*/
4873 static void
4874 genAnd (iCode * ic, iCode * ifx)
4875 {
4876   operand *left, *right, *result;
4877   int size, offset = 0;
4878   unsigned long lit = 0L;
4879   int bytelit = 0;
4880   char buffer[10];
4881   bool pushResult;
4882
4883   D (emitcode (";", "genAnd "););
4884
4885   AOP_OP_3_NOFATAL (ic, pushResult);
4886   AOP_SET_LOCALS (ic);
4887
4888   if (pushResult)
4889   {
4890       genFarFarLogicOp(ic, "anl");
4891       return;
4892   }  
4893
4894 #ifdef DEBUG_TYPE
4895   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4896             AOP_TYPE (result),
4897             AOP_TYPE (left), AOP_TYPE (right));
4898   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4899             AOP_SIZE (result),
4900             AOP_SIZE (left), AOP_SIZE (right));
4901 #endif
4902
4903   /* if left is a literal & right is not then exchange them */
4904   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4905       AOP_NEEDSACC (left))
4906     {
4907       operand *tmp = right;
4908       right = left;
4909       left = tmp;
4910     }
4911
4912   /* if result = right then exchange them */
4913   if (sameRegs (AOP (result), AOP (right)))
4914     {
4915       operand *tmp = right;
4916       right = left;
4917       left = tmp;
4918     }
4919
4920   /* if right is bit then exchange them */
4921   if (AOP_TYPE (right) == AOP_CRY &&
4922       AOP_TYPE (left) != AOP_CRY)
4923     {
4924       operand *tmp = right;
4925       right = left;
4926       left = tmp;
4927     }
4928   if (AOP_TYPE (right) == AOP_LIT)
4929     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4930
4931   size = AOP_SIZE (result);
4932
4933   // if(bit & yy)
4934   // result = bit & yy;
4935   if (AOP_TYPE (left) == AOP_CRY)
4936     {
4937       // c = bit & literal;
4938       if (AOP_TYPE (right) == AOP_LIT)
4939         {
4940           if (lit & 1)
4941             {
4942               if (size && sameRegs (AOP (result), AOP (left)))
4943                 // no change
4944                 goto release;
4945               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4946             }
4947           else
4948             {
4949               // bit(result) = 0;
4950               if (size && (AOP_TYPE (result) == AOP_CRY))
4951                 {
4952                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4953                   goto release;
4954                 }
4955               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4956                 {
4957                   jumpIfTrue (ifx);
4958                   goto release;
4959                 }
4960               emitcode ("clr", "c");
4961             }
4962         }
4963       else
4964         {
4965           if (AOP_TYPE (right) == AOP_CRY)
4966             {
4967               // c = bit & bit;
4968               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4969               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4970             }
4971           else
4972             {
4973               // c = bit & val;
4974               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4975               // c = lsb
4976               emitcode ("rrc", "a");
4977               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4978             }
4979         }
4980       // bit = c
4981       // val = c
4982       if (size)
4983         outBitC (result);
4984       // if(bit & ...)
4985       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4986         genIfxJump (ifx, "c");
4987       goto release;
4988     }
4989
4990   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
4991   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
4992   if ((AOP_TYPE (right) == AOP_LIT) &&
4993       (AOP_TYPE (result) == AOP_CRY) &&
4994       (AOP_TYPE (left) != AOP_CRY))
4995     {
4996       int posbit = isLiteralBit (lit);
4997       /* left &  2^n */
4998       if (posbit)
4999         {
5000           posbit--;
5001           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5002           // bit = left & 2^n
5003           if (size)
5004             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5005           // if(left &  2^n)
5006           else
5007             {
5008               if (ifx)
5009                 {
5010                   sprintf (buffer, "acc.%d", posbit & 0x07);
5011                   genIfxJump (ifx, buffer);
5012                 }
5013               goto release;
5014             }
5015         }
5016       else
5017         {
5018           symbol *tlbl = newiTempLabel (NULL);
5019           int sizel = AOP_SIZE (left);
5020           if (size)
5021             emitcode ("setb", "c");
5022           while (sizel--)
5023             {
5024               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5025                 {
5026                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5027                   // byte ==  2^n ?
5028                   if ((posbit = isLiteralBit (bytelit)) != 0)
5029                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5030                   else
5031                     {
5032                       if (bytelit != 0x0FFL)
5033                         emitcode ("anl", "a,%s",
5034                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5035                       emitcode ("jnz", "%05d$", tlbl->key + 100);
5036                     }
5037                 }
5038               offset++;
5039             }
5040           // bit = left & literal
5041           if (size)
5042             {
5043               emitcode ("clr", "c");
5044               emitcode ("", "%05d$:", tlbl->key + 100);
5045             }
5046           // if(left & literal)
5047           else
5048             {
5049               if (ifx)
5050                 jmpTrueOrFalse (ifx, tlbl);
5051               goto release;
5052             }
5053         }
5054       outBitC (result);
5055       goto release;
5056     }
5057
5058   /* if left is same as result */
5059   if (sameRegs (AOP (result), AOP (left)))
5060     {
5061       for (; size--; offset++)
5062         {
5063           if (AOP_TYPE (right) == AOP_LIT)
5064             {
5065               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5066                 continue;
5067               else if (bytelit == 0)
5068                 aopPut (AOP (result), zero, offset);
5069               else if (IS_AOP_PREG (result))
5070                 {
5071                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5072                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5073                   aopPut (AOP (result), "a", offset);
5074                 }
5075               else
5076                 emitcode ("anl", "%s,%s",
5077                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5078                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5079             }
5080           else
5081             {
5082               if (AOP_TYPE (left) == AOP_ACC)
5083                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5084               else
5085                 {
5086                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5087                   if (IS_AOP_PREG (result))
5088                     {
5089                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5090                       aopPut (AOP (result), "a", offset);
5091
5092                     }
5093                   else
5094                     emitcode ("anl", "%s,a",
5095                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5096                 }
5097             }
5098         }
5099     }
5100   else
5101     {
5102       // left & result in different registers
5103       if (AOP_TYPE (result) == AOP_CRY)
5104         {
5105           // result = bit
5106           // if(size), result in bit
5107           // if(!size && ifx), conditional oper: if(left & right)
5108           symbol *tlbl = newiTempLabel (NULL);
5109           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5110           if (size)
5111             emitcode ("setb", "c");
5112           while (sizer--)
5113             {
5114               MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5115               emitcode ("anl", "a,%s",
5116                         aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5117               emitcode ("jnz", "%05d$", tlbl->key + 100);
5118               offset++;
5119             }
5120           if (size)
5121             {
5122               CLRC;
5123               emitcode ("", "%05d$:", tlbl->key + 100);
5124               outBitC (result);
5125             }
5126           else if (ifx)
5127             jmpTrueOrFalse (ifx, tlbl);
5128         }
5129       else
5130         {
5131           for (; (size--); offset++)
5132             {
5133               // normal case
5134               // result = left & right
5135               if (AOP_TYPE (right) == AOP_LIT)
5136                 {
5137                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5138                     {
5139                       aopPut (AOP (result),
5140                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5141                               offset);
5142                       continue;
5143                     }
5144                   else if (bytelit == 0)
5145                     {
5146                       aopPut (AOP (result), zero, offset);
5147                       continue;
5148                     }
5149                   D (emitcode (";", "better literal AND.");
5150                     );
5151                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5152                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5153                                                     FALSE, FALSE, FALSE));
5154
5155                 }
5156               else
5157                 {
5158                   // faster than result <- left, anl result,right
5159                   // and better if result is SFR
5160                   if (AOP_TYPE (left) == AOP_ACC)
5161                     {
5162                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5163                                                        FALSE, FALSE, FALSE));
5164                     }
5165                   else
5166                     {
5167                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5168                       emitcode ("anl", "a,%s",
5169                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5170                     }
5171                 }
5172               aopPut (AOP (result), "a", offset);
5173             }
5174         }
5175     }
5176
5177 release:
5178   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5179   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5180   freeAsmop (result, NULL, ic, TRUE);
5181 }
5182
5183
5184 /*-----------------------------------------------------------------*/
5185 /* genOr  - code for or                                            */
5186 /*-----------------------------------------------------------------*/
5187 static void
5188 genOr (iCode * ic, iCode * ifx)
5189 {
5190   operand *left, *right, *result;
5191   int size, offset = 0;
5192   unsigned long lit = 0L;
5193   bool     pushResult;
5194
5195   D (emitcode (";", "genOr "););
5196
5197   AOP_OP_3_NOFATAL (ic, pushResult);
5198   AOP_SET_LOCALS (ic);
5199
5200   if (pushResult)
5201   {
5202       genFarFarLogicOp(ic, "orl");
5203       return;
5204   }
5205
5206
5207 #ifdef DEBUG_TYPE
5208   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5209             AOP_TYPE (result),
5210             AOP_TYPE (left), AOP_TYPE (right));
5211   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5212             AOP_SIZE (result),
5213             AOP_SIZE (left), AOP_SIZE (right));
5214 #endif
5215
5216   /* if left is a literal & right is not then exchange them */
5217   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5218       AOP_NEEDSACC (left))
5219     {
5220       operand *tmp = right;
5221       right = left;
5222       left = tmp;
5223     }
5224
5225   /* if result = right then exchange them */
5226   if (sameRegs (AOP (result), AOP (right)))
5227     {
5228       operand *tmp = right;
5229       right = left;
5230       left = tmp;
5231     }
5232
5233   /* if right is bit then exchange them */
5234   if (AOP_TYPE (right) == AOP_CRY &&
5235       AOP_TYPE (left) != AOP_CRY)
5236     {
5237       operand *tmp = right;
5238       right = left;
5239       left = tmp;
5240     }
5241   if (AOP_TYPE (right) == AOP_LIT)
5242     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5243
5244   size = AOP_SIZE (result);
5245
5246   // if(bit | yy)
5247   // xx = bit | yy;
5248   if (AOP_TYPE (left) == AOP_CRY)
5249     {
5250       if (AOP_TYPE (right) == AOP_LIT)
5251         {
5252           // c = bit & literal;
5253           if (lit)
5254             {
5255               // lit != 0 => result = 1
5256               if (AOP_TYPE (result) == AOP_CRY)
5257                 {
5258                   if (size)
5259                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5260                   else if (ifx)
5261                     continueIfTrue (ifx);
5262                   goto release;
5263                 }
5264               emitcode ("setb", "c");
5265             }
5266           else
5267             {
5268               // lit == 0 => result = left
5269               if (size && sameRegs (AOP (result), AOP (left)))
5270                 goto release;
5271               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5272             }
5273         }
5274       else
5275         {
5276           if (AOP_TYPE (right) == AOP_CRY)
5277             {
5278               // c = bit | bit;
5279               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5280               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5281             }
5282           else
5283             {
5284               // c = bit | val;
5285               symbol *tlbl = newiTempLabel (NULL);
5286               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5287                 emitcode ("setb", "c");
5288               emitcode ("jb", "%s,%05d$",
5289                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
5290               toBoolean (right);
5291               emitcode ("jnz", "%05d$", tlbl->key + 100);
5292               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5293                 {
5294                   jmpTrueOrFalse (ifx, tlbl);
5295                   goto release;
5296                 }
5297               else
5298                 {
5299                   CLRC;
5300                   emitcode ("", "%05d$:", tlbl->key + 100);
5301                 }
5302             }
5303         }
5304       // bit = c
5305       // val = c
5306       if (size)
5307         outBitC (result);
5308       // if(bit | ...)
5309       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5310         genIfxJump (ifx, "c");
5311       goto release;
5312     }
5313
5314   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5315   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5316   if ((AOP_TYPE (right) == AOP_LIT) &&
5317       (AOP_TYPE (result) == AOP_CRY) &&
5318       (AOP_TYPE (left) != AOP_CRY))
5319     {
5320       if (lit)
5321         {
5322           // result = 1
5323           if (size)
5324             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5325           else
5326             continueIfTrue (ifx);
5327           goto release;
5328         }
5329       else
5330         {
5331           // lit = 0, result = boolean(left)
5332           if (size)
5333             emitcode ("setb", "c");
5334           toBoolean (right);
5335           if (size)
5336             {
5337               symbol *tlbl = newiTempLabel (NULL);
5338               emitcode ("jnz", "%05d$", tlbl->key + 100);
5339               CLRC;
5340               emitcode ("", "%05d$:", tlbl->key + 100);
5341             }
5342           else
5343             {
5344               genIfxJump (ifx, "a");
5345               goto release;
5346             }
5347         }
5348       outBitC (result);
5349       goto release;
5350     }
5351
5352   /* if left is same as result */
5353   if (sameRegs (AOP (result), AOP (left)))
5354     {
5355       for (; size--; offset++)
5356         {
5357           if (AOP_TYPE (right) == AOP_LIT)
5358             {
5359               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5360                 {
5361                   continue;
5362                 }
5363               else
5364                 {
5365                   if (IS_AOP_PREG (left))
5366                     {
5367                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5368                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5369                       aopPut (AOP (result), "a", offset);
5370                     }
5371                   else
5372                     {
5373                       emitcode ("orl", "%s,%s",
5374                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5375                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5376                     }
5377                 }
5378             }
5379           else
5380             {
5381               if (AOP_TYPE (left) == AOP_ACC)
5382                 {
5383                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5384                 }
5385               else
5386                 {
5387                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5388                   if (IS_AOP_PREG (left))
5389                     {
5390                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5391                       aopPut (AOP (result), "a", offset);
5392                     }
5393                   else
5394                     {
5395                       emitcode ("orl", "%s,a",
5396                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5397                     }
5398                 }
5399             }
5400         }
5401     }
5402   else
5403     {
5404       // left & result in different registers
5405       if (AOP_TYPE (result) == AOP_CRY)
5406         {
5407           // result = bit
5408           // if(size), result in bit
5409           // if(!size && ifx), conditional oper: if(left | right)
5410           symbol *tlbl = newiTempLabel (NULL);
5411           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5412           if (size)
5413             emitcode ("setb", "c");
5414           while (sizer--)
5415             {
5416               MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5417               emitcode ("orl", "a,%s",
5418                         aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5419               emitcode ("jnz", "%05d$", tlbl->key + 100);
5420               offset++;
5421             }
5422           if (size)
5423             {
5424               CLRC;
5425               emitcode ("", "%05d$:", tlbl->key + 100);
5426               outBitC (result);
5427             }
5428           else if (ifx)
5429             jmpTrueOrFalse (ifx, tlbl);
5430         }
5431       else
5432         {
5433           for (; (size--); offset++)
5434             {
5435               // normal case
5436               // result = left & right
5437               if (AOP_TYPE (right) == AOP_LIT)
5438                 {
5439                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5440                     {
5441                       aopPut (AOP (result),
5442                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5443                               offset);
5444                       continue;
5445                     }
5446                   D (emitcode (";", "better literal OR.");
5447                     );
5448                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5449                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5450                                                     FALSE, FALSE, FALSE));
5451
5452                 }
5453               else
5454                 {
5455                   // faster than result <- left, anl result,right
5456                   // and better if result is SFR
5457                   if (AOP_TYPE (left) == AOP_ACC)
5458                     {
5459                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5460                                                        FALSE, FALSE, FALSE));
5461                     }
5462                   else
5463                     {
5464                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5465                       emitcode ("orl", "a,%s",
5466                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5467                     }
5468                 }
5469               aopPut (AOP (result), "a", offset);
5470             }
5471         }
5472     }
5473
5474 release:
5475   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5476   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5477   freeAsmop (result, NULL, ic, TRUE);
5478 }
5479
5480 /*-----------------------------------------------------------------*/
5481 /* genXor - code for xclusive or                                   */
5482 /*-----------------------------------------------------------------*/
5483 static void
5484 genXor (iCode * ic, iCode * ifx)
5485 {
5486   operand *left, *right, *result;
5487   int size, offset = 0;
5488   unsigned long lit = 0L;
5489   bool pushResult;
5490
5491   D (emitcode (";", "genXor "););
5492
5493   AOP_OP_3_NOFATAL (ic, pushResult);
5494   AOP_SET_LOCALS (ic);
5495
5496   if (pushResult)
5497   {
5498       genFarFarLogicOp(ic, "xrl");
5499       return;
5500   }  
5501
5502 #ifdef DEBUG_TYPE
5503   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5504             AOP_TYPE (result),
5505             AOP_TYPE (left), AOP_TYPE (right));
5506   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5507             AOP_SIZE (result),
5508             AOP_SIZE (left), AOP_SIZE (right));
5509 #endif
5510
5511   /* if left is a literal & right is not ||
5512      if left needs acc & right does not */
5513   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5514       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5515     {
5516       operand *tmp = right;
5517       right = left;
5518       left = tmp;
5519     }
5520
5521   /* if result = right then exchange them */
5522   if (sameRegs (AOP (result), AOP (right)))
5523     {
5524       operand *tmp = right;
5525       right = left;
5526       left = tmp;
5527     }
5528
5529   /* if right is bit then exchange them */
5530   if (AOP_TYPE (right) == AOP_CRY &&
5531       AOP_TYPE (left) != AOP_CRY)
5532     {
5533       operand *tmp = right;
5534       right = left;
5535       left = tmp;
5536     }
5537   if (AOP_TYPE (right) == AOP_LIT)
5538     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5539
5540   size = AOP_SIZE (result);
5541
5542   // if(bit ^ yy)
5543   // xx = bit ^ yy;
5544   if (AOP_TYPE (left) == AOP_CRY)
5545     {
5546       if (AOP_TYPE (right) == AOP_LIT)
5547         {
5548           // c = bit & literal;
5549           if (lit >> 1)
5550             {
5551               // lit>>1  != 0 => result = 1
5552               if (AOP_TYPE (result) == AOP_CRY)
5553                 {
5554                   if (size)
5555                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5556                   else if (ifx)
5557                     continueIfTrue (ifx);
5558                   goto release;
5559                 }
5560               emitcode ("setb", "c");
5561             }
5562           else
5563             {
5564               // lit == (0 or 1)
5565               if (lit == 0)
5566                 {
5567                   // lit == 0, result = left
5568                   if (size && sameRegs (AOP (result), AOP (left)))
5569                     goto release;
5570                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5571                 }
5572               else
5573                 {
5574                   // lit == 1, result = not(left)
5575                   if (size && sameRegs (AOP (result), AOP (left)))
5576                     {
5577                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5578                       goto release;
5579                     }
5580                   else
5581                     {
5582                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5583                       emitcode ("cpl", "c");
5584                     }
5585                 }
5586             }
5587
5588         }
5589       else
5590         {
5591           // right != literal
5592           symbol *tlbl = newiTempLabel (NULL);
5593           if (AOP_TYPE (right) == AOP_CRY)
5594             {
5595               // c = bit ^ bit;
5596               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5597             }
5598           else
5599             {
5600               int sizer = AOP_SIZE (right);
5601               // c = bit ^ val
5602               // if val>>1 != 0, result = 1
5603               emitcode ("setb", "c");
5604               while (sizer)
5605                 {
5606                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5607                   if (sizer == 1)
5608                     // test the msb of the lsb
5609                     emitcode ("anl", "a,#0xfe");
5610                   emitcode ("jnz", "%05d$", tlbl->key + 100);
5611                   sizer--;
5612                 }
5613               // val = (0,1)
5614               emitcode ("rrc", "a");
5615             }
5616           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5617           emitcode ("cpl", "c");
5618           emitcode ("", "%05d$:", (tlbl->key + 100));
5619         }
5620       // bit = c
5621       // val = c
5622       if (size)
5623         outBitC (result);
5624       // if(bit | ...)
5625       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5626         genIfxJump (ifx, "c");
5627       goto release;
5628     }
5629
5630   if (sameRegs (AOP (result), AOP (left)))
5631     {
5632       /* if left is same as result */
5633       for (; size--; offset++)
5634         {
5635           if (AOP_TYPE (right) == AOP_LIT)
5636             {
5637               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5638                 continue;
5639               else if (IS_AOP_PREG (left))
5640                 {
5641                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5642                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5643                   aopPut (AOP (result), "a", offset);
5644                 }
5645               else
5646                 emitcode ("xrl", "%s,%s",
5647                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5648                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5649             }
5650           else
5651             {
5652               if (AOP_TYPE (left) == AOP_ACC)
5653                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5654               else
5655                 {
5656                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5657                   if (IS_AOP_PREG (left))
5658                     {
5659                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5660                       aopPut (AOP (result), "a", offset);
5661                     }
5662                   else
5663                     emitcode ("xrl", "%s,a",
5664                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5665                 }
5666             }
5667         }
5668     }
5669   else
5670     {
5671       // left & result in different registers
5672       if (AOP_TYPE (result) == AOP_CRY)
5673         {
5674           // result = bit
5675           // if(size), result in bit
5676           // if(!size && ifx), conditional oper: if(left ^ right)
5677           symbol *tlbl = newiTempLabel (NULL);
5678           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5679           if (size)
5680             emitcode ("setb", "c");
5681           while (sizer--)
5682             {
5683               if ((AOP_TYPE (right) == AOP_LIT) &&
5684                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5685                 {
5686                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5687                 }
5688               else
5689                 {
5690                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5691                   emitcode ("xrl", "a,%s",
5692                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5693                 }
5694               emitcode ("jnz", "%05d$", tlbl->key + 100);
5695               offset++;
5696             }
5697           if (size)
5698             {
5699               CLRC;
5700               emitcode ("", "%05d$:", tlbl->key + 100);
5701               outBitC (result);
5702             }
5703           else if (ifx)
5704             jmpTrueOrFalse (ifx, tlbl);
5705         }
5706       else
5707         for (; (size--); offset++)
5708           {
5709             // normal case
5710             // result = left & right
5711             if (AOP_TYPE (right) == AOP_LIT)
5712               {
5713                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5714                   {
5715                     aopPut (AOP (result),
5716                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5717                             offset);
5718                     continue;
5719                   }
5720                 D (emitcode (";", "better literal XOR.");
5721                   );
5722                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5723                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5724                                                   FALSE, FALSE, FALSE));
5725               }
5726             else
5727               {
5728                 // faster than result <- left, anl result,right
5729                 // and better if result is SFR
5730                 if (AOP_TYPE (left) == AOP_ACC)
5731                   {
5732                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5733                                                      FALSE, FALSE, FALSE));
5734                   }
5735                 else
5736                   {
5737                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5738                     emitcode ("xrl", "a,%s",
5739                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5740                   }
5741               }
5742             aopPut (AOP (result), "a", offset);
5743           }
5744     }
5745
5746 release:
5747   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5748   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5749   freeAsmop (result, NULL, ic, TRUE);
5750 }
5751
5752 /*-----------------------------------------------------------------*/
5753 /* genInline - write the inline code out                           */
5754 /*-----------------------------------------------------------------*/
5755 static void
5756 genInline (iCode * ic)
5757 {
5758   char buffer[MAX_INLINEASM];
5759   char *bp = buffer;
5760   char *bp1 = buffer;
5761
5762   D (emitcode (";", "genInline ");
5763     );
5764
5765   _G.inLine += (!options.asmpeep);
5766   strcpy (buffer, IC_INLINE (ic));
5767
5768   /* emit each line as a code */
5769   while (*bp)
5770     {
5771       if (*bp == '\n')
5772         {
5773           *bp++ = '\0';
5774           emitcode (bp1, "");
5775           bp1 = bp;
5776         }
5777       else
5778         {
5779           if (*bp == ':')
5780             {
5781               bp++;
5782               *bp = '\0';
5783               bp++;
5784               emitcode (bp1, "");
5785               bp1 = bp;
5786             }
5787           else
5788             bp++;
5789         }
5790     }
5791   if (bp1 != bp)
5792     emitcode (bp1, "");
5793   /*     emitcode("",buffer); */
5794   _G.inLine -= (!options.asmpeep);
5795 }
5796
5797 /*-----------------------------------------------------------------*/
5798 /* genRRC - rotate right with carry                                */
5799 /*-----------------------------------------------------------------*/
5800 static void
5801 genRRC (iCode * ic)
5802 {
5803   operand *left, *result;
5804   int size, offset = 0;
5805   char *l;
5806
5807   D (emitcode (";", "genRRC ");
5808     );
5809
5810   /* rotate right with carry */
5811   left = IC_LEFT (ic);
5812   result = IC_RESULT (ic);
5813   aopOp (left, ic, FALSE, FALSE);
5814   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5815
5816   /* move it to the result */
5817   size = AOP_SIZE (result);
5818   offset = size - 1;
5819   CLRC;
5820
5821   _startLazyDPSEvaluation ();
5822   while (size--)
5823     {
5824       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5825       MOVA (l);
5826       emitcode ("rrc", "a");
5827       if (AOP_SIZE (result) > 1)
5828         aopPut (AOP (result), "a", offset--);
5829     }
5830   _endLazyDPSEvaluation ();
5831
5832   /* now we need to put the carry into the
5833      highest order byte of the result */
5834   if (AOP_SIZE (result) > 1)
5835     {
5836       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5837       MOVA (l);
5838     }
5839   emitcode ("mov", "acc.7,c");
5840   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5841   freeAsmop (left, NULL, ic, TRUE);
5842   freeAsmop (result, NULL, ic, TRUE);
5843 }
5844
5845 /*-----------------------------------------------------------------*/
5846 /* genRLC - generate code for rotate left with carry               */
5847 /*-----------------------------------------------------------------*/
5848 static void
5849 genRLC (iCode * ic)
5850 {
5851   operand *left, *result;
5852   int size, offset = 0;
5853   char *l;
5854
5855   D (emitcode (";", "genRLC ");
5856     );
5857
5858   /* rotate right with carry */
5859   left = IC_LEFT (ic);
5860   result = IC_RESULT (ic);
5861   aopOp (left, ic, FALSE, FALSE);
5862   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5863
5864   /* move it to the result */
5865   size = AOP_SIZE (result);
5866   offset = 0;
5867   if (size--)
5868     {
5869       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5870       MOVA (l);
5871       emitcode ("add", "a,acc");
5872       if (AOP_SIZE (result) > 1)
5873         {
5874           aopPut (AOP (result), "a", offset++);
5875         }
5876
5877       _startLazyDPSEvaluation ();
5878       while (size--)
5879         {
5880           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5881           MOVA (l);
5882           emitcode ("rlc", "a");
5883           if (AOP_SIZE (result) > 1)
5884             aopPut (AOP (result), "a", offset++);
5885         }
5886       _endLazyDPSEvaluation ();
5887     }
5888   /* now we need to put the carry into the
5889      highest order byte of the result */
5890   if (AOP_SIZE (result) > 1)
5891     {
5892       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5893       MOVA (l);
5894     }
5895   emitcode ("mov", "acc.0,c");
5896   aopPut (AOP (result), "a", 0);
5897   freeAsmop (left, NULL, ic, TRUE);
5898   freeAsmop (result, NULL, ic, TRUE);
5899 }
5900
5901 /*-----------------------------------------------------------------*/
5902 /* genGetHbit - generates code get highest order bit               */
5903 /*-----------------------------------------------------------------*/
5904 static void
5905 genGetHbit (iCode * ic)
5906 {
5907   operand *left, *result;
5908   left = IC_LEFT (ic);
5909   result = IC_RESULT (ic);
5910   aopOp (left, ic, FALSE, FALSE);
5911   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5912
5913   D (emitcode (";", "genGetHbit ");
5914     );
5915
5916   /* get the highest order byte into a */
5917   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5918   if (AOP_TYPE (result) == AOP_CRY)
5919     {
5920       emitcode ("rlc", "a");
5921       outBitC (result);
5922     }
5923   else
5924     {
5925       emitcode ("rl", "a");
5926       emitcode ("anl", "a,#0x01");
5927       outAcc (result);
5928     }
5929
5930
5931   freeAsmop (left, NULL, ic, TRUE);
5932   freeAsmop (result, NULL, ic, TRUE);
5933 }
5934
5935 /*-----------------------------------------------------------------*/
5936 /* AccRol - rotate left accumulator by known count                 */
5937 /*-----------------------------------------------------------------*/
5938 static void
5939 AccRol (int shCount)
5940 {
5941   shCount &= 0x0007;            // shCount : 0..7
5942
5943   switch (shCount)
5944     {
5945     case 0:
5946       break;
5947     case 1:
5948       emitcode ("rl", "a");
5949       break;
5950     case 2:
5951       emitcode ("rl", "a");
5952       emitcode ("rl", "a");
5953       break;
5954     case 3:
5955       emitcode ("swap", "a");
5956       emitcode ("rr", "a");
5957       break;
5958     case 4:
5959       emitcode ("swap", "a");
5960       break;
5961     case 5:
5962       emitcode ("swap", "a");
5963       emitcode ("rl", "a");
5964       break;
5965     case 6:
5966       emitcode ("rr", "a");
5967       emitcode ("rr", "a");
5968       break;
5969     case 7:
5970       emitcode ("rr", "a");
5971       break;
5972     }
5973 }
5974
5975 /*-----------------------------------------------------------------*/
5976 /* AccLsh - left shift accumulator by known count                  */
5977 /*-----------------------------------------------------------------*/
5978 static void
5979 AccLsh (int shCount)
5980 {
5981   if (shCount != 0)
5982     {
5983       if (shCount == 1)
5984         emitcode ("add", "a,acc");
5985       else if (shCount == 2)
5986         {
5987           emitcode ("add", "a,acc");
5988           emitcode ("add", "a,acc");
5989         }
5990       else
5991         {
5992           /* rotate left accumulator */
5993           AccRol (shCount);
5994           /* and kill the lower order bits */
5995           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5996         }
5997     }
5998 }
5999
6000 /*-----------------------------------------------------------------*/
6001 /* AccRsh - right shift accumulator by known count                 */
6002 /*-----------------------------------------------------------------*/
6003 static void
6004 AccRsh (int shCount)
6005 {
6006   if (shCount != 0)
6007     {
6008       if (shCount == 1)
6009         {
6010           CLRC;
6011           emitcode ("rrc", "a");
6012         }
6013       else
6014         {
6015           /* rotate right accumulator */
6016           AccRol (8 - shCount);
6017           /* and kill the higher order bits */
6018           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6019         }
6020     }
6021 }
6022
6023 #if 0
6024 //REMOVE ME!!!
6025 /*-----------------------------------------------------------------*/
6026 /* AccSRsh - signed right shift accumulator by known count                 */
6027 /*-----------------------------------------------------------------*/
6028 static void
6029 AccSRsh (int shCount)
6030 {
6031   symbol *tlbl;
6032   if (shCount != 0)
6033     {
6034       if (shCount == 1)
6035         {
6036           emitcode ("mov", "c,acc.7");
6037           emitcode ("rrc", "a");
6038         }
6039       else if (shCount == 2)
6040         {
6041           emitcode ("mov", "c,acc.7");
6042           emitcode ("rrc", "a");
6043           emitcode ("mov", "c,acc.7");
6044           emitcode ("rrc", "a");
6045         }
6046       else
6047         {
6048           tlbl = newiTempLabel (NULL);
6049           /* rotate right accumulator */
6050           AccRol (8 - shCount);
6051           /* and kill the higher order bits */
6052           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6053           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6054           emitcode ("orl", "a,#0x%02x",
6055                     (unsigned char) ~SRMask[shCount]);
6056           emitcode ("", "%05d$:", tlbl->key + 100);
6057         }
6058     }
6059 }
6060 #endif
6061
6062 #if 0
6063 //REMOVE ME!!!
6064 /*-----------------------------------------------------------------*/
6065 /* shiftR1Left2Result - shift right one byte from left to result   */
6066 /*-----------------------------------------------------------------*/
6067 static void
6068 shiftR1Left2Result (operand * left, int offl,
6069                     operand * result, int offr,
6070                     int shCount, int sign)
6071 {
6072   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6073   /* shift right accumulator */
6074   if (sign)
6075     AccSRsh (shCount);
6076   else
6077     AccRsh (shCount);
6078   aopPut (AOP (result), "a", offr);
6079 }
6080 #endif
6081
6082 #if 0
6083 //REMOVE ME!!!
6084 /*-----------------------------------------------------------------*/
6085 /* shiftL1Left2Result - shift left one byte from left to result    */
6086 /*-----------------------------------------------------------------*/
6087 static void
6088 shiftL1Left2Result (operand * left, int offl,
6089                     operand * result, int offr, int shCount)
6090 {
6091   char *l;
6092   l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6093   MOVA (l);
6094   /* shift left accumulator */
6095   AccLsh (shCount);
6096   aopPut (AOP (result), "a", offr);
6097 }
6098 #endif
6099
6100 #if 0
6101 //REMOVE ME!!!
6102 /*-----------------------------------------------------------------*/
6103 /* movLeft2Result - move byte from left to result                  */
6104 /*-----------------------------------------------------------------*/
6105 static void
6106 movLeft2Result (operand * left, int offl,
6107                 operand * result, int offr, int sign)
6108 {
6109   char *l;
6110   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6111     {
6112       l = aopGet (AOP (left), offl, FALSE, FALSE, FALSE);
6113
6114       if (*l == '@' && (IS_AOP_PREG (result)))
6115         {
6116           emitcode ("mov", "a,%s", l);
6117           aopPut (AOP (result), "a", offr);
6118         }
6119       else
6120         {
6121           if (!sign)
6122             aopPut (AOP (result), l, offr);
6123           else
6124             {
6125               /* MSB sign in acc.7 ! */
6126               if (getDataSize (left) == offl + 1)
6127                 {
6128                   emitcode ("mov", "a,%s", l);
6129                   aopPut (AOP (result), "a", offr);
6130                 }
6131             }
6132         }
6133     }
6134 }
6135 #endif
6136
6137 #if 0
6138 //REMOVE ME!!!
6139 /*-----------------------------------------------------------------*/
6140 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6141 /*-----------------------------------------------------------------*/
6142 static void
6143 AccAXRrl1 (char *x)
6144 {
6145   emitcode ("rrc", "a");
6146   emitcode ("xch", "a,%s", x);
6147   emitcode ("rrc", "a");
6148   emitcode ("xch", "a,%s", x);
6149 }
6150 #endif
6151
6152 #if 0
6153 //REMOVE ME!!!
6154 /*-----------------------------------------------------------------*/
6155 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
6156 /*-----------------------------------------------------------------*/
6157 static void
6158 AccAXLrl1 (char *x)
6159 {
6160   emitcode ("xch", "a,%s", x);
6161   emitcode ("rlc", "a");
6162   emitcode ("xch", "a,%s", x);
6163   emitcode ("rlc", "a");
6164 }
6165 #endif
6166
6167 #if 0
6168 //REMOVE ME!!!
6169 /*-----------------------------------------------------------------*/
6170 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
6171 /*-----------------------------------------------------------------*/
6172 static void
6173 AccAXLsh1 (char *x)
6174 {
6175   emitcode ("xch", "a,%s", x);
6176   emitcode ("add", "a,acc");
6177   emitcode ("xch", "a,%s", x);
6178   emitcode ("rlc", "a");
6179 }
6180 #endif
6181
6182 #if 0
6183 //REMOVE ME!!!
6184 /*-----------------------------------------------------------------*/
6185 /* AccAXLsh - left shift a:x by known count (0..7)                 */
6186 /*-----------------------------------------------------------------*/
6187 static void
6188 AccAXLsh (char *x, int shCount)
6189 {
6190   switch (shCount)
6191     {
6192     case 0:
6193       break;
6194     case 1:
6195       AccAXLsh1 (x);
6196       break;
6197     case 2:
6198       AccAXLsh1 (x);
6199       AccAXLsh1 (x);
6200       break;
6201     case 3:
6202     case 4:
6203     case 5:                     // AAAAABBB:CCCCCDDD
6204
6205       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
6206
6207       emitcode ("anl", "a,#0x%02x",
6208                 SLMask[shCount]);       // BBB00000:CCCCCDDD
6209
6210       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
6211
6212       AccRol (shCount);         // DDDCCCCC:BBB00000
6213
6214       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
6215
6216       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
6217
6218       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
6219
6220       emitcode ("anl", "a,#0x%02x",
6221                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
6222
6223       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
6224
6225       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
6226
6227       break;
6228     case 6:                     // AAAAAABB:CCCCCCDD
6229       emitcode ("anl", "a,#0x%02x",
6230                 SRMask[shCount]);       // 000000BB:CCCCCCDD
6231       emitcode ("mov", "c,acc.0");      // c = B
6232       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
6233 #if 0
6234       AccAXRrl1 (x);            // BCCCCCCD:D000000B
6235       AccAXRrl1 (x);            // BBCCCCCC:DD000000
6236 #else
6237       emitcode("rrc","a"); 
6238       emitcode("xch","a,%s", x); 
6239       emitcode("rrc","a"); 
6240       emitcode("mov","c,acc.0"); //<< get correct bit 
6241       emitcode("xch","a,%s", x); 
6242
6243       emitcode("rrc","a"); 
6244       emitcode("xch","a,%s", x); 
6245       emitcode("rrc","a"); 
6246       emitcode("xch","a,%s", x); 
6247 #endif
6248       break;
6249     case 7:                     // a:x <<= 7
6250
6251       emitcode ("anl", "a,#0x%02x",
6252                 SRMask[shCount]);       // 0000000B:CCCCCCCD
6253
6254       emitcode ("mov", "c,acc.0");      // c = B
6255
6256       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
6257
6258       AccAXRrl1 (x);            // BCCCCCCC:D0000000
6259
6260       break;
6261     default:
6262       break;
6263     }
6264 }
6265 #endif
6266
6267 #if 0
6268 //REMOVE ME!!!
6269 /*-----------------------------------------------------------------*/
6270 /* AccAXRsh - right shift a:x known count (0..7)                   */
6271 /*-----------------------------------------------------------------*/
6272 static void
6273 AccAXRsh (char *x, int shCount)
6274 {
6275   switch (shCount)
6276     {
6277     case 0:
6278       break;
6279     case 1:
6280       CLRC;
6281       AccAXRrl1 (x);            // 0->a:x
6282
6283       break;
6284     case 2:
6285       CLRC;
6286       AccAXRrl1 (x);            // 0->a:x
6287
6288       CLRC;
6289       AccAXRrl1 (x);            // 0->a:x
6290
6291       break;
6292     case 3:
6293     case 4:
6294     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6295
6296       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
6297
6298       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6299
6300       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6301
6302       emitcode ("anl", "a,#0x%02x",
6303                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6304
6305       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6306
6307       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6308
6309       emitcode ("anl", "a,#0x%02x",
6310                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6311
6312       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6313
6314       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6315
6316       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
6317
6318       break;
6319     case 6:                     // AABBBBBB:CCDDDDDD
6320
6321       emitcode ("mov", "c,acc.7");
6322       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6323
6324       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6325
6326       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6327
6328       emitcode ("anl", "a,#0x%02x",
6329                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6330
6331       break;
6332     case 7:                     // ABBBBBBB:CDDDDDDD
6333
6334       emitcode ("mov", "c,acc.7");      // c = A
6335
6336       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6337
6338       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6339
6340       emitcode ("anl", "a,#0x%02x",
6341                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6342
6343       break;
6344     default:
6345       break;
6346     }
6347 }
6348 #endif
6349
6350 #if 0
6351 //REMOVE ME!!!
6352 /*-----------------------------------------------------------------*/
6353 /* AccAXRshS - right shift signed a:x known count (0..7)           */
6354 /*-----------------------------------------------------------------*/
6355 static void
6356 AccAXRshS (char *x, int shCount)
6357 {
6358   symbol *tlbl;
6359   switch (shCount)
6360     {
6361     case 0:
6362       break;
6363     case 1:
6364       emitcode ("mov", "c,acc.7");
6365       AccAXRrl1 (x);            // s->a:x
6366
6367       break;
6368     case 2:
6369       emitcode ("mov", "c,acc.7");
6370       AccAXRrl1 (x);            // s->a:x
6371
6372       emitcode ("mov", "c,acc.7");
6373       AccAXRrl1 (x);            // s->a:x
6374
6375       break;
6376     case 3:
6377     case 4:
6378     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6379
6380       tlbl = newiTempLabel (NULL);
6381       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
6382
6383       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6384
6385       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6386
6387       emitcode ("anl", "a,#0x%02x",
6388                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6389
6390       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6391
6392       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6393
6394       emitcode ("anl", "a,#0x%02x",
6395                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6396
6397       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6398
6399       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6400
6401       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
6402
6403       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6404       emitcode ("orl", "a,#0x%02x",
6405                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
6406
6407       emitcode ("", "%05d$:", tlbl->key + 100);
6408       break;                    // SSSSAAAA:BBBCCCCC
6409
6410     case 6:                     // AABBBBBB:CCDDDDDD
6411
6412       tlbl = newiTempLabel (NULL);
6413       emitcode ("mov", "c,acc.7");
6414       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6415
6416       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6417
6418       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6419
6420       emitcode ("anl", "a,#0x%02x",
6421                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6422
6423       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6424       emitcode ("orl", "a,#0x%02x",
6425                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
6426
6427       emitcode ("", "%05d$:", tlbl->key + 100);
6428       break;
6429     case 7:                     // ABBBBBBB:CDDDDDDD
6430
6431       tlbl = newiTempLabel (NULL);
6432       emitcode ("mov", "c,acc.7");      // c = A
6433
6434       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6435
6436       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6437
6438       emitcode ("anl", "a,#0x%02x",
6439                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6440
6441       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6442       emitcode ("orl", "a,#0x%02x",
6443                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
6444
6445       emitcode ("", "%05d$:", tlbl->key + 100);
6446       break;
6447     default:
6448       break;
6449     }
6450 }
6451 #endif
6452
6453 #if 0
6454 //REMOVE ME!!!
6455 /*-----------------------------------------------------------------*/
6456 /* shiftL2Left2Result - shift left two bytes from left to result   */
6457 /*-----------------------------------------------------------------*/
6458 static void
6459 shiftL2Left2Result (operand * left, int offl,
6460                     operand * result, int offr, int shCount)
6461 {
6462   if (sameRegs (AOP (result), AOP (left)) &&
6463       ((offl + MSB16) == offr))
6464     {
6465       /* don't crash result[offr] */
6466       MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6467       emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6468     }
6469   else
6470     {
6471       movLeft2Result (left, offl, result, offr, 0);
6472       MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6473     }
6474   /* ax << shCount (x = lsb(result)) */
6475   AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6476   aopPut (AOP (result), "a", offr + MSB16);
6477 }
6478 #endif
6479
6480 #if 0
6481 //REMOVE ME!!!
6482 /*-----------------------------------------------------------------*/
6483 /* shiftR2Left2Result - shift right two bytes from left to result  */
6484 /*-----------------------------------------------------------------*/
6485 static void
6486 shiftR2Left2Result (operand * left, int offl,
6487                     operand * result, int offr,
6488                     int shCount, int sign)
6489 {
6490   if (sameRegs (AOP (result), AOP (left)) &&
6491       ((offl + MSB16) == offr))
6492     {
6493       /* don't crash result[offr] */
6494       MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6495       emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6496     }
6497   else
6498     {
6499       movLeft2Result (left, offl, result, offr, 0);
6500       MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6501     }
6502   /* a:x >> shCount (x = lsb(result)) */
6503   if (sign)
6504     AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6505   else
6506     AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6507   if (getDataSize (result) > 1)
6508     aopPut (AOP (result), "a", offr + MSB16);
6509 }
6510 #endif
6511
6512 #if 0
6513 //REMOVE ME!!!
6514 /*-----------------------------------------------------------------*/
6515 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6516 /*-----------------------------------------------------------------*/
6517 static void
6518 shiftLLeftOrResult (operand * left, int offl,
6519                     operand * result, int offr, int shCount)
6520 {
6521   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6522   /* shift left accumulator */
6523   AccLsh (shCount);
6524   /* or with result */
6525   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6526   /* back to result */
6527   aopPut (AOP (result), "a", offr);
6528 }
6529 #endif
6530
6531 #if 0
6532 //REMOVE ME!!!
6533 /*-----------------------------------------------------------------*/
6534 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6535 /*-----------------------------------------------------------------*/
6536 static void
6537 shiftRLeftOrResult (operand * left, int offl,
6538                     operand * result, int offr, int shCount)
6539 {
6540   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6541   /* shift right accumulator */
6542   AccRsh (shCount);
6543   /* or with result */
6544   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6545   /* back to result */
6546   aopPut (AOP (result), "a", offr);
6547 }
6548 #endif
6549
6550 #if 0
6551 //REMOVE ME!!!
6552 /*-----------------------------------------------------------------*/
6553 /* genlshOne - left shift a one byte quantity by known count       */
6554 /*-----------------------------------------------------------------*/
6555 static void
6556 genlshOne (operand * result, operand * left, int shCount)
6557 {
6558   D (emitcode (";", "genlshOne ");
6559     );
6560   shiftL1Left2Result (left, LSB, result, LSB, shCount);
6561 }
6562 #endif
6563
6564 #if 0
6565 //REMOVE ME!!!
6566 /*-----------------------------------------------------------------*/
6567 /* genlshTwo - left shift two bytes by known amount != 0           */
6568 /*-----------------------------------------------------------------*/
6569 static void
6570 genlshTwo (operand * result, operand * left, int shCount)
6571 {
6572   int size;
6573
6574   D (emitcode (";", "genlshTwo ");
6575     );
6576
6577   size = getDataSize (result);
6578
6579   /* if shCount >= 8 */
6580   if (shCount >= 8)
6581     {
6582       shCount -= 8;
6583
6584       if (size > 1)
6585         {
6586           if (shCount)
6587             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6588           else
6589             movLeft2Result (left, LSB, result, MSB16, 0);
6590         }
6591       aopPut (AOP (result), zero, LSB);
6592     }
6593
6594   /*  1 <= shCount <= 7 */
6595   else
6596     {
6597       if (size == 1)
6598         shiftL1Left2Result (left, LSB, result, LSB, shCount);
6599       else
6600         shiftL2Left2Result (left, LSB, result, LSB, shCount);
6601     }
6602 }
6603 #endif
6604
6605 #if 0
6606 //REMOVE ME!!!
6607 /*-----------------------------------------------------------------*/
6608 /* shiftLLong - shift left one long from left to result            */
6609 /* offl = LSB or MSB16                                             */
6610 /*-----------------------------------------------------------------*/
6611 static void
6612 shiftLLong (operand * left, operand * result, int offr)
6613 {
6614   char *l;
6615   int size = AOP_SIZE (result);
6616
6617   if (size >= LSB + offr)
6618     {
6619       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6620       MOVA (l);
6621       emitcode ("add", "a,acc");
6622       if (sameRegs (AOP (left), AOP (result)) &&
6623           size >= MSB16 + offr && offr != LSB)
6624         emitcode ("xch", "a,%s",
6625                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6626       else
6627         aopPut (AOP (result), "a", LSB + offr);
6628     }
6629
6630   if (size >= MSB16 + offr)
6631     {
6632       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6633         {
6634           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6635           MOVA (l);
6636         }
6637       emitcode ("rlc", "a");
6638       if (sameRegs (AOP (left), AOP (result)) &&
6639           size >= MSB24 + offr && offr != LSB)
6640         emitcode ("xch", "a,%s",
6641                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6642       else
6643         aopPut (AOP (result), "a", MSB16 + offr);
6644     }
6645
6646   if (size >= MSB24 + offr)
6647     {
6648       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6649         {
6650           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6651           MOVA (l);
6652         }
6653       emitcode ("rlc", "a");
6654       if (sameRegs (AOP (left), AOP (result)) &&
6655           size >= MSB32 + offr && offr != LSB)
6656         emitcode ("xch", "a,%s",
6657                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6658       else
6659         aopPut (AOP (result), "a", MSB24 + offr);
6660     }
6661
6662   if (size > MSB32 + offr)
6663     {
6664       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6665         {
6666           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6667           MOVA (l);
6668         }
6669       emitcode ("rlc", "a");
6670       aopPut (AOP (result), "a", MSB32 + offr);
6671     }
6672   if (offr != LSB)
6673     aopPut (AOP (result), zero, LSB);
6674 }
6675 #endif
6676
6677 #if 0
6678 //REMOVE ME!!!
6679 /*-----------------------------------------------------------------*/
6680 /* genlshFour - shift four byte by a known amount != 0             */
6681 /*-----------------------------------------------------------------*/
6682 static void
6683 genlshFour (operand * result, operand * left, int shCount)
6684 {
6685   int size;
6686
6687   D (emitcode (";", "genlshFour ");
6688     );
6689
6690   size = AOP_SIZE (result);
6691
6692   /* if shifting more that 3 bytes */
6693   if (shCount >= 24)
6694     {
6695       shCount -= 24;
6696       if (shCount)
6697         /* lowest order of left goes to the highest
6698            order of the destination */
6699         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6700       else
6701         movLeft2Result (left, LSB, result, MSB32, 0);
6702       aopPut (AOP (result), zero, LSB);
6703       aopPut (AOP (result), zero, MSB16);
6704       aopPut (AOP (result), zero, MSB24);
6705       return;
6706     }
6707
6708   /* more than two bytes */
6709   else if (shCount >= 16)
6710     {
6711       /* lower order two bytes goes to higher order two bytes */
6712       shCount -= 16;
6713       /* if some more remaining */
6714       if (shCount)
6715         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6716       else
6717         {
6718           movLeft2Result (left, MSB16, result, MSB32, 0);
6719           movLeft2Result (left, LSB, result, MSB24, 0);
6720         }
6721       aopPut (AOP (result), zero, MSB16);
6722       aopPut (AOP (result), zero, LSB);
6723       return;
6724     }
6725
6726   /* if more than 1 byte */
6727   else if (shCount >= 8)
6728     {
6729       /* lower order three bytes goes to higher order  three bytes */
6730       shCount -= 8;
6731       if (size == 2)
6732         {
6733           if (shCount)
6734             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6735           else
6736             movLeft2Result (left, LSB, result, MSB16, 0);
6737         }
6738       else
6739         {                       /* size = 4 */
6740           if (shCount == 0)
6741             {
6742               movLeft2Result (left, MSB24, result, MSB32, 0);
6743               movLeft2Result (left, MSB16, result, MSB24, 0);
6744               movLeft2Result (left, LSB, result, MSB16, 0);
6745               aopPut (AOP (result), zero, LSB);
6746             }
6747           else if (shCount == 1)
6748             shiftLLong (left, result, MSB16);
6749           else
6750             {
6751               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6752               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6753               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6754               aopPut (AOP (result), zero, LSB);
6755             }
6756         }
6757     }
6758
6759   /* 1 <= shCount <= 7 */
6760   else if (shCount <= 2)
6761     {
6762       shiftLLong (left, result, LSB);
6763       if (shCount == 2)
6764         shiftLLong (result, result, LSB);
6765     }
6766   /* 3 <= shCount <= 7, optimize */
6767   else
6768     {
6769       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6770       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6771       shiftL2Left2Result (left, LSB, result, LSB, shCount);
6772     }
6773 }
6774 #endif
6775
6776 #if 0
6777 //REMOVE ME!!!
6778 /*-----------------------------------------------------------------*/
6779 /* genLeftShiftLiteral - left shifting by known count              */
6780 /*-----------------------------------------------------------------*/
6781 static void
6782 genLeftShiftLiteral (operand * left,
6783                      operand * right,
6784                      operand * result,
6785                      iCode * ic)
6786 {
6787   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6788   int size;
6789
6790   D (emitcode (";", "genLeftShiftLiteral (%d)", shCount);
6791     );
6792
6793   freeAsmop (right, NULL, ic, TRUE);
6794
6795   aopOp (left, ic, FALSE, FALSE);
6796   aopOp (result, ic, FALSE, TRUE);
6797
6798   size = getSize (operandType (result));
6799
6800 #if VIEW_SIZE
6801   emitcode ("; shift left ", "result %d, left %d", size,
6802             AOP_SIZE (left));
6803 #endif
6804
6805   /* I suppose that the left size >= result size */
6806   if (shCount == 0)
6807     {
6808       while (size--)
6809         {
6810           movLeft2Result (left, size, result, size, 0);
6811         }
6812     }
6813
6814   else if (shCount >= (size * 8))
6815     while (size--)
6816       aopPut (AOP (result), zero, size);
6817   else
6818     {
6819       switch (size)
6820         {
6821         case 1:
6822           genlshOne (result, left, shCount);
6823           break;
6824
6825         case 2:
6826         case 3:         /* bug: this is for generic pointers, I bet. */
6827           genlshTwo (result, left, shCount);
6828           break;
6829
6830         case 4:
6831           genlshFour (result, left, shCount);
6832           break;
6833         }
6834     }
6835   freeAsmop (left, NULL, ic, TRUE);
6836   freeAsmop (result, NULL, ic, TRUE);
6837 }
6838 #endif
6839
6840 /*-----------------------------------------------------------------*/
6841 /* genLeftShift - generates code for left shifting                 */
6842 /*-----------------------------------------------------------------*/
6843 static void
6844 genLeftShift (iCode * ic)
6845 {
6846   operand *left, *right, *result;
6847   int size, offset;
6848   char *l;
6849   symbol *tlbl, *tlbl1;
6850
6851   D (emitcode (";", "genLeftShift ");
6852     );
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
8648   aopOp (cond, ic, FALSE, FALSE);
8649
8650   /* get the value into acc */
8651   if (AOP_TYPE (cond) != AOP_CRY)
8652     toBoolean (cond);
8653   else
8654     isbit = 1;
8655   /* the result is now in the accumulator */
8656   freeAsmop (cond, NULL, ic, TRUE);
8657
8658   /* if there was something to be popped then do it */
8659   if (popIc)
8660     genIpop (popIc);
8661
8662   /* if the condition is  a bit variable */
8663   if (isbit && IS_ITEMP (cond) &&
8664       SPIL_LOC (cond))
8665     genIfxJump (ic, SPIL_LOC (cond)->rname);
8666   else if (isbit && !IS_ITEMP (cond))
8667     genIfxJump (ic, OP_SYMBOL (cond)->rname);
8668   else
8669     genIfxJump (ic, "a");
8670
8671   ic->generated = 1;
8672 }
8673
8674 /*-----------------------------------------------------------------*/
8675 /* genAddrOf - generates code for address of                       */
8676 /*-----------------------------------------------------------------*/
8677 static void
8678 genAddrOf (iCode * ic)
8679 {
8680   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8681   int size, offset;
8682
8683   D (emitcode (";", "genAddrOf ");
8684     );
8685
8686   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8687
8688   /* if the operand is on the stack then we
8689      need to get the stack offset of this
8690      variable */
8691   if (sym->onStack)
8692     {
8693       /* if it has an offset then we need to compute
8694          it */
8695       if (sym->stack)
8696         {
8697           emitcode ("mov", "a,_bp");
8698           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8699           aopPut (AOP (IC_RESULT (ic)), "a", 0);
8700         }
8701       else
8702         {
8703           /* we can just move _bp */
8704           aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8705         }
8706       /* fill the result with zero */
8707       size = AOP_SIZE (IC_RESULT (ic)) - 1;
8708
8709
8710       if (options.stack10bit && size < (FPTRSIZE - 1))
8711         {
8712           fprintf (stderr,
8713                    "*** warning: pointer to stack var truncated.\n");
8714         }
8715
8716       offset = 1;
8717       while (size--)
8718         {
8719           /* Yuck! */
8720           if (options.stack10bit && offset == 2)
8721             {
8722               aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8723             }
8724           else
8725             {
8726               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8727             }
8728         }
8729
8730       goto release;
8731     }
8732
8733   /* object not on stack then we need the name */
8734   size = AOP_SIZE (IC_RESULT (ic));
8735   offset = 0;
8736
8737   while (size--)
8738     {
8739       char s[SDCC_NAME_MAX];
8740       if (offset)
8741         sprintf (s, "#(%s >> %d)",
8742                  sym->rname,
8743                  offset * 8);
8744       else
8745         sprintf (s, "#%s", sym->rname);
8746       aopPut (AOP (IC_RESULT (ic)), s, offset++);
8747     }
8748
8749 release:
8750   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8751
8752 }
8753
8754 /*-----------------------------------------------------------------*/
8755 /* genFarFarAssign - assignment when both are in far space         */
8756 /*-----------------------------------------------------------------*/
8757 static void
8758 genFarFarAssign (operand * result, operand * right, iCode * ic)
8759 {
8760   int size = AOP_SIZE (right);
8761   int offset = 0;
8762   char *l;
8763
8764   if (size > 1)
8765     {
8766       /* This is a net loss for size == 1, but a big gain
8767        * otherwise.
8768        */
8769       D (emitcode (";", "genFarFarAssign (improved)");
8770         );
8771
8772       aopOp (result, ic, TRUE, TRUE);
8773
8774       _startLazyDPSEvaluation ();
8775       while (size--)
8776         {
8777           aopPut (AOP (result),
8778                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
8779           offset++;
8780         }
8781       _endLazyDPSEvaluation ();
8782       freeAsmop (result, NULL, ic, FALSE);
8783       freeAsmop (right, NULL, ic, FALSE);
8784     }
8785   else
8786     {
8787       D (emitcode (";", "genFarFarAssign ");
8788         );
8789
8790       /* first push the right side on to the stack */
8791       _startLazyDPSEvaluation ();
8792       while (size--)
8793         {
8794           l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8795           MOVA (l);
8796           emitcode ("push", "acc");
8797         }
8798
8799       freeAsmop (right, NULL, ic, FALSE);
8800       /* now assign DPTR to result */
8801       aopOp (result, ic, FALSE, FALSE);
8802       size = AOP_SIZE (result);
8803       while (size--)
8804         {
8805           emitcode ("pop", "acc");
8806           aopPut (AOP (result), "a", --offset);
8807         }
8808       freeAsmop (result, NULL, ic, FALSE);
8809       _endLazyDPSEvaluation ();
8810     }
8811 }
8812
8813 /*-----------------------------------------------------------------*/
8814 /* genAssign - generate code for assignment                        */
8815 /*-----------------------------------------------------------------*/
8816 static void
8817 genAssign (iCode * ic)
8818 {
8819   operand *result, *right;
8820   int size, offset;
8821   unsigned long lit = 0L;
8822
8823   D (emitcode (";", "genAssign ");
8824     );
8825
8826   result = IC_RESULT (ic);
8827   right = IC_RIGHT (ic);
8828
8829   /* if they are the same */
8830   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8831     return;
8832
8833   aopOp (right, ic, FALSE, FALSE);
8834
8835   emitcode (";", "genAssign: resultIsFar = %s",
8836             isOperandInFarSpace (result) ?
8837             "TRUE" : "FALSE");
8838
8839   /* special case both in far space */
8840   if ((AOP_TYPE (right) == AOP_DPTR ||
8841        AOP_TYPE (right) == AOP_DPTR2) &&
8842   /* IS_TRUE_SYMOP(result)       && */
8843       isOperandInFarSpace (result))
8844     {
8845       genFarFarAssign (result, right, ic);
8846       return;
8847     }
8848
8849   aopOp (result, ic, TRUE, FALSE);
8850
8851   /* if they are the same registers */
8852   if (sameRegs (AOP (right), AOP (result)))
8853     goto release;
8854
8855   /* if the result is a bit */
8856   if (AOP_TYPE (result) == AOP_CRY)
8857     {
8858
8859       /* if the right size is a literal then
8860          we know what the value is */
8861       if (AOP_TYPE (right) == AOP_LIT)
8862         {
8863           if (((int) operandLitValue (right)))
8864             aopPut (AOP (result), one, 0);
8865           else
8866             aopPut (AOP (result), zero, 0);
8867           goto release;
8868         }
8869
8870       /* the right is also a bit variable */
8871       if (AOP_TYPE (right) == AOP_CRY)
8872         {
8873           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8874           aopPut (AOP (result), "c", 0);
8875           goto release;
8876         }
8877
8878       /* we need to or */
8879       toBoolean (right);
8880       aopPut (AOP (result), "a", 0);
8881       goto release;
8882     }
8883
8884   /* bit variables done */
8885   /* general case */
8886   size = AOP_SIZE (result);
8887   offset = 0;
8888   if (AOP_TYPE (right) == AOP_LIT)
8889     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8890
8891   if ((size > 1) &&
8892       (AOP_TYPE (result) != AOP_REG) &&
8893       (AOP_TYPE (right) == AOP_LIT) &&
8894       !IS_FLOAT (operandType (right)))
8895     {
8896       D (emitcode (";", "Kevin's better literal load code");
8897         );
8898       _startLazyDPSEvaluation ();
8899       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
8900         {
8901           aopPut (AOP (result),
8902                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
8903                   offset);
8904           offset++;
8905           size--;
8906         }
8907       /* And now fill the rest with zeros. */
8908       if (size)
8909         {
8910           emitcode ("clr", "a");
8911         }
8912       while (size--)
8913         {
8914           aopPut (AOP (result), "a", offset++);
8915         }
8916       _endLazyDPSEvaluation ();
8917     }
8918   else
8919     {
8920       _startLazyDPSEvaluation ();
8921       while (size--)
8922         {
8923           aopPut (AOP (result),
8924                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8925                   offset);
8926           offset++;
8927         }
8928       _endLazyDPSEvaluation ();
8929     }
8930
8931 release:
8932   freeAsmop (right, NULL, ic, FALSE);
8933   freeAsmop (result, NULL, ic, TRUE);
8934 }
8935
8936 /*-----------------------------------------------------------------*/
8937 /* genJumpTab - generates code for jump table                      */
8938 /*-----------------------------------------------------------------*/
8939 static void
8940 genJumpTab (iCode * ic)
8941 {
8942   symbol *jtab;
8943   char *l;
8944
8945   D (emitcode (";", "genJumpTab ");
8946     );
8947
8948   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
8949   /* get the condition into accumulator */
8950   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
8951   MOVA (l);
8952   /* multiply by four! */
8953   emitcode ("add", "a,acc");
8954   emitcode ("add", "a,acc");
8955   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8956
8957   jtab = newiTempLabel (NULL);
8958   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8959   emitcode ("jmp", "@a+dptr");
8960   emitcode ("", "%05d$:", jtab->key + 100);
8961   /* now generate the jump labels */
8962   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8963        jtab = setNextItem (IC_JTLABELS (ic)))
8964     emitcode ("ljmp", "%05d$", jtab->key + 100);
8965
8966 }
8967
8968 /*-----------------------------------------------------------------*/
8969 /* genCast - gen code for casting                                  */
8970 /*-----------------------------------------------------------------*/
8971 static void
8972 genCast (iCode * ic)
8973 {
8974   operand *result = IC_RESULT (ic);
8975   sym_link *ctype = operandType (IC_LEFT (ic));
8976   sym_link *rtype = operandType (IC_RIGHT (ic));
8977   operand *right = IC_RIGHT (ic);
8978   int size, offset;
8979
8980   D (emitcode (";", "genCast ");
8981     );
8982
8983   /* if they are equivalent then do nothing */
8984   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8985     return;
8986
8987   aopOp (right, ic, FALSE, FALSE);
8988   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
8989
8990   /* if the result is a bit */
8991   if (AOP_TYPE (result) == AOP_CRY)
8992     {
8993       /* if the right size is a literal then
8994          we know what the value is */
8995       if (AOP_TYPE (right) == AOP_LIT)
8996         {
8997           if (((int) operandLitValue (right)))
8998             aopPut (AOP (result), one, 0);
8999           else
9000             aopPut (AOP (result), zero, 0);
9001
9002           goto release;
9003         }
9004
9005       /* the right is also a bit variable */
9006       if (AOP_TYPE (right) == AOP_CRY)
9007         {
9008           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9009           aopPut (AOP (result), "c", 0);
9010           goto release;
9011         }
9012
9013       /* we need to or */
9014       toBoolean (right);
9015       aopPut (AOP (result), "a", 0);
9016       goto release;
9017     }
9018
9019   /* if they are the same size : or less */
9020   if (AOP_SIZE (result) <= AOP_SIZE (right))
9021     {
9022
9023       /* if they are in the same place */
9024       if (sameRegs (AOP (right), AOP (result)))
9025         goto release;
9026
9027       /* if they in different places then copy */
9028       size = AOP_SIZE (result);
9029       offset = 0;
9030       _startLazyDPSEvaluation ();
9031       while (size--)
9032         {
9033           aopPut (AOP (result),
9034                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9035                   offset);
9036           offset++;
9037         }
9038       _endLazyDPSEvaluation ();
9039       goto release;
9040     }
9041
9042
9043   /* if the result is of type pointer */
9044   if (IS_PTR (ctype))
9045     {
9046
9047       int p_type;
9048       sym_link *type = operandType (right);
9049
9050       /* pointer to generic pointer */
9051       if (IS_GENPTR (ctype))
9052         {
9053           char *l = zero;
9054
9055           if (IS_PTR (type))
9056             {
9057               p_type = DCL_TYPE (type);
9058             }
9059           else
9060             {
9061 #if OLD_CAST_BEHAVIOR
9062               /* KV: we are converting a non-pointer type to
9063                * a generic pointer. This (ifdef'd out) code
9064                * says that the resulting generic pointer
9065                * should have the same class as the storage
9066                * location of the non-pointer variable.
9067                *
9068                * For example, converting an int (which happens
9069                * to be stored in DATA space) to a pointer results
9070                * in a DATA generic pointer; if the original int
9071                * in XDATA space, so will be the resulting pointer.
9072                *
9073                * I don't like that behavior, and thus this change:
9074                * all such conversions will be forced to XDATA and
9075                * throw a warning. If you want some non-XDATA
9076                * type, or you want to suppress the warning, you
9077                * must go through an intermediate cast, like so:
9078                *
9079                * char _generic *gp = (char _xdata *)(intVar);
9080                */
9081               sym_link *etype = getSpec (type);
9082
9083               /* we have to go by the storage class */
9084               if (SPEC_OCLS (etype) != generic)
9085                 {
9086                   p_type = PTR_TYPE (SPEC_OCLS (etype));
9087                 }
9088               else
9089 #endif
9090                 {
9091                   /* Converting unknown class (i.e. register variable)
9092                    * to generic pointer. This is not good, but
9093                    * we'll make a guess (and throw a warning).
9094                    */
9095                   p_type = FPOINTER;
9096                   werror (W_INT_TO_GEN_PTR_CAST);
9097                 }
9098             }
9099
9100           /* the first two bytes are known */
9101           size = GPTRSIZE - 1;
9102           offset = 0;
9103           _startLazyDPSEvaluation ();
9104           while (size--)
9105             {
9106               aopPut (AOP (result),
9107                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9108                       offset);
9109               offset++;
9110             }
9111           _endLazyDPSEvaluation ();
9112
9113           /* the last byte depending on type */
9114           switch (p_type)
9115             {
9116             case IPOINTER:
9117             case POINTER:
9118               l = zero;
9119               break;
9120             case FPOINTER:
9121               l = one;
9122               break;
9123             case CPOINTER:
9124               l = "#0x02";
9125               break;
9126             case PPOINTER:
9127               l = "#0x03";
9128               break;
9129
9130             default:
9131               /* this should never happen */
9132               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9133                       "got unknown pointer type");
9134               exit (1);
9135             }
9136           aopPut (AOP (result), l, GPTRSIZE - 1);
9137           goto release;
9138         }
9139
9140       /* just copy the pointers */
9141       size = AOP_SIZE (result);
9142       offset = 0;
9143       _startLazyDPSEvaluation ();
9144       while (size--)
9145         {
9146           aopPut (AOP (result),
9147                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9148                   offset);
9149           offset++;
9150         }
9151       _endLazyDPSEvaluation ();
9152       goto release;
9153     }
9154
9155   /* so we now know that the size of destination is greater
9156      than the size of the source */
9157   /* we move to result for the size of source */
9158   size = AOP_SIZE (right);
9159   offset = 0;
9160   _startLazyDPSEvaluation ();
9161   while (size--)
9162     {
9163       aopPut (AOP (result),
9164               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9165               offset);
9166       offset++;
9167     }
9168   _endLazyDPSEvaluation ();
9169
9170   /* now depending on the sign of the source && destination */
9171   size = AOP_SIZE (result) - AOP_SIZE (right);
9172   /* if unsigned or not an integral type */
9173   /* also, if the source is a bit, we don't need to sign extend, because
9174    * it can't possibly have set the sign bit.
9175    */
9176   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9177     {
9178       while (size--)
9179         {
9180           aopPut (AOP (result), zero, offset++);
9181         }
9182     }
9183   else
9184     {
9185       /* we need to extend the sign :{ */
9186       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9187                         FALSE, FALSE, TRUE);
9188       MOVA (l);
9189       emitcode ("rlc", "a");
9190       emitcode ("subb", "a,acc");
9191       while (size--)
9192         aopPut (AOP (result), "a", offset++);
9193     }
9194
9195   /* we are done hurray !!!! */
9196
9197 release:
9198   freeAsmop (right, NULL, ic, TRUE);
9199   freeAsmop (result, NULL, ic, TRUE);
9200
9201 }
9202
9203 /*-----------------------------------------------------------------*/
9204 /* genDjnz - generate decrement & jump if not zero instrucion      */
9205 /*-----------------------------------------------------------------*/
9206 static int
9207 genDjnz (iCode * ic, iCode * ifx)
9208 {
9209   symbol *lbl, *lbl1;
9210   if (!ifx)
9211     return 0;
9212
9213   /* if the if condition has a false label
9214      then we cannot save */
9215   if (IC_FALSE (ifx))
9216     return 0;
9217
9218   /* if the minus is not of the form
9219      a = a - 1 */
9220   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9221       !IS_OP_LITERAL (IC_RIGHT (ic)))
9222     return 0;
9223
9224   if (operandLitValue (IC_RIGHT (ic)) != 1)
9225     return 0;
9226
9227   /* if the size of this greater than one then no
9228      saving */
9229   if (getSize (operandType (IC_RESULT (ic))) > 1)
9230     return 0;
9231
9232   /* otherwise we can save BIG */
9233   lbl = newiTempLabel (NULL);
9234   lbl1 = newiTempLabel (NULL);
9235
9236   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9237
9238   if (IS_AOP_PREG (IC_RESULT (ic)))
9239     {
9240       emitcode ("dec", "%s",
9241                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9242       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9243       emitcode ("jnz", "%05d$", lbl->key + 100);
9244     }
9245   else
9246     {
9247       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9248                 lbl->key + 100);
9249     }
9250   emitcode ("sjmp", "%05d$", lbl1->key + 100);
9251   emitcode ("", "%05d$:", lbl->key + 100);
9252   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9253   emitcode ("", "%05d$:", lbl1->key + 100);
9254
9255   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9256   ifx->generated = 1;
9257   return 1;
9258 }
9259
9260 /*-----------------------------------------------------------------*/
9261 /* genReceive - generate code for a receive iCode                  */
9262 /*-----------------------------------------------------------------*/
9263 static void
9264 genReceive (iCode * ic)
9265 {
9266
9267   D (emitcode (";", "genReceive ");
9268     );
9269
9270   if (isOperandInFarSpace (IC_RESULT (ic)) &&
9271       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9272        IS_TRUE_SYMOP (IC_RESULT (ic))))
9273     {
9274       int size = getSize (operandType (IC_RESULT (ic)));
9275       int offset = fReturnSizeDS390 - size;
9276       while (size--)
9277         {
9278           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9279                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9280           offset++;
9281         }
9282       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9283       size = AOP_SIZE (IC_RESULT (ic));
9284       offset = 0;
9285       while (size--)
9286         {
9287           emitcode ("pop", "acc");
9288           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9289         }
9290
9291     }
9292   else
9293     {
9294       _G.accInUse++;
9295       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9296       _G.accInUse--;
9297       assignResultValue (IC_RESULT (ic));
9298     }
9299
9300   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9301 }
9302
9303 /*-----------------------------------------------------------------*/
9304 /* gen390Code - generate code for Dallas 390 based controllers     */
9305 /*-----------------------------------------------------------------*/
9306 void
9307 gen390Code (iCode * lic)
9308 {
9309   iCode *ic;
9310   int cln = 0;
9311
9312   lineHead = lineCurr = NULL;
9313
9314 #if 0
9315   //REMOVE ME!!!
9316   /* print the allocation information */
9317   if (allocInfo)
9318     printAllocInfo (currFunc, codeOutFile);
9319 #endif
9320   /* if debug information required */
9321   if (options.debug && currFunc)
9322     {
9323       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9324       _G.debugLine = 1;
9325       if (IS_STATIC (currFunc->etype))
9326         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9327       else
9328         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9329       _G.debugLine = 0;
9330     }
9331   /* stack pointer name */
9332   if (options.useXstack)
9333     spname = "_spx";
9334   else
9335     spname = "sp";
9336
9337
9338   for (ic = lic; ic; ic = ic->next)
9339     {
9340
9341       if (cln != ic->lineno)
9342         {
9343           if (options.debug)
9344             {
9345               _G.debugLine = 1;
9346               emitcode ("", "C$%s$%d$%d$%d ==.",
9347                         FileBaseName (ic->filename), ic->lineno,
9348                         ic->level, ic->block);
9349               _G.debugLine = 0;
9350             }
9351           emitcode (";", "%s %d", ic->filename, ic->lineno);
9352           cln = ic->lineno;
9353         }
9354       /* if the result is marked as
9355          spilt and rematerializable or code for
9356          this has already been generated then
9357          do nothing */
9358       if (resultRemat (ic) || ic->generated)
9359         continue;
9360
9361       /* depending on the operation */
9362       switch (ic->op)
9363         {
9364         case '!':
9365           genNot (ic);
9366           break;
9367
9368         case '~':
9369           genCpl (ic);
9370           break;
9371
9372         case UNARYMINUS:
9373           genUminus (ic);
9374           break;
9375
9376         case IPUSH:
9377           genIpush (ic);
9378           break;
9379
9380         case IPOP:
9381           /* IPOP happens only when trying to restore a
9382              spilt live range, if there is an ifx statement
9383              following this pop then the if statement might
9384              be using some of the registers being popped which
9385              would destory the contents of the register so
9386              we need to check for this condition and handle it */
9387           if (ic->next &&
9388               ic->next->op == IFX &&
9389               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9390             genIfx (ic->next, ic);
9391           else
9392             genIpop (ic);
9393           break;
9394
9395         case CALL:
9396           genCall (ic);
9397           break;
9398
9399         case PCALL:
9400           genPcall (ic);
9401           break;
9402
9403         case FUNCTION:
9404           genFunction (ic);
9405           break;
9406
9407         case ENDFUNCTION:
9408           genEndFunction (ic);
9409           break;
9410
9411         case RETURN:
9412           genRet (ic);
9413           break;
9414
9415         case LABEL:
9416           genLabel (ic);
9417           break;
9418
9419         case GOTO:
9420           genGoto (ic);
9421           break;
9422
9423         case '+':
9424           genPlus (ic);
9425           break;
9426
9427         case '-':
9428           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9429             genMinus (ic);
9430           break;
9431
9432         case '*':
9433           genMult (ic);
9434           break;
9435
9436         case '/':
9437           genDiv (ic);
9438           break;
9439
9440         case '%':
9441           genMod (ic);
9442           break;
9443
9444         case '>':
9445           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9446           break;
9447
9448         case '<':
9449           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9450           break;
9451
9452         case LE_OP:
9453         case GE_OP:
9454         case NE_OP:
9455
9456           /* note these two are xlated by algebraic equivalence
9457              during parsing SDCC.y */
9458           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9459                   "got '>=' or '<=' shouldn't have come here");
9460           break;
9461
9462         case EQ_OP:
9463           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9464           break;
9465
9466         case AND_OP:
9467           genAndOp (ic);
9468           break;
9469
9470         case OR_OP:
9471           genOrOp (ic);
9472           break;
9473
9474         case '^':
9475           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9476           break;
9477
9478         case '|':
9479           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9480           break;
9481
9482         case BITWISEAND:
9483           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9484           break;
9485
9486         case INLINEASM:
9487           genInline (ic);
9488           break;
9489
9490         case RRC:
9491           genRRC (ic);
9492           break;
9493
9494         case RLC:
9495           genRLC (ic);
9496           break;
9497
9498         case GETHBIT:
9499           genGetHbit (ic);
9500           break;
9501
9502         case LEFT_OP:
9503           genLeftShift (ic);
9504           break;
9505
9506         case RIGHT_OP:
9507           genRightShift (ic);
9508           break;
9509
9510         case GET_VALUE_AT_ADDRESS:
9511           genPointerGet (ic);
9512           break;
9513
9514         case '=':
9515           if (POINTER_SET (ic))
9516             genPointerSet (ic);
9517           else
9518             genAssign (ic);
9519           break;
9520
9521         case IFX:
9522           genIfx (ic, NULL);
9523           break;
9524
9525         case ADDRESS_OF:
9526           genAddrOf (ic);
9527           break;
9528
9529         case JUMPTABLE:
9530           genJumpTab (ic);
9531           break;
9532
9533         case CAST:
9534           genCast (ic);
9535           break;
9536
9537         case RECEIVE:
9538           genReceive (ic);
9539           break;
9540
9541         case SEND:
9542           addSet (&_G.sendSet, ic);
9543           break;
9544
9545         default:
9546           ic = ic;
9547         }
9548     }
9549
9550
9551   /* now we are ready to call the
9552      peep hole optimizer */
9553   if (!options.nopeep)
9554     peepHole (&lineHead);
9555
9556   /* now do the actual printing */
9557   printLine (lineHead, codeOutFile);
9558   return;
9559 }