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