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