fixed the bankswitch critical races
[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[MAX_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   if (/* why would we do this?: jwk20010511 */ 0 &&
1800       detype &&
1801       (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1802       IS_ISR (currFunc->etype) &&
1803       !ic->bankSaved)
1804     saverbank (SPEC_BANK (detype), ic, TRUE);
1805
1806 }
1807 /*-----------------------------------------------------------------*/
1808 /* unsaveRegisters - pop the pushed registers                      */
1809 /*-----------------------------------------------------------------*/
1810 static void
1811 unsaveRegisters (iCode * ic)
1812 {
1813   int i;
1814   bitVect *rsave;
1815   /* find the registers in use at this time
1816      and push them away to safety */
1817   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1818                          ic->rUsed);
1819
1820   if (options.useXstack)
1821     {
1822       emitcode ("mov", "r0,%s", spname);
1823       for (i = ds390_nRegs; i >= 0; i--)
1824         {
1825           if (bitVectBitValue (rsave, i))
1826             {
1827               emitcode ("dec", "r0");
1828               emitcode ("movx", "a,@r0");
1829               if (i == R0_IDX)
1830                 emitcode ("mov", "b,a");
1831               else
1832                 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1833             }
1834
1835         }
1836       emitcode ("mov", "%s,r0", spname);
1837       if (bitVectBitValue (rsave, R0_IDX))
1838         emitcode ("mov", "r0,b");
1839     }
1840   else
1841     for (i = ds390_nRegs; i >= 0; i--)
1842       {
1843         if (bitVectBitValue (rsave, i))
1844           emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1845       }
1846
1847 }
1848
1849
1850 /*-----------------------------------------------------------------*/
1851 /* pushSide -                */
1852 /*-----------------------------------------------------------------*/
1853 static void
1854 pushSide (operand * oper, int size)
1855 {
1856   int offset = 0;
1857   _startLazyDPSEvaluation ();
1858   while (size--)
1859     {
1860       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1861       if (AOP_TYPE (oper) != AOP_REG &&
1862           AOP_TYPE (oper) != AOP_DIR &&
1863           strcmp (l, "a"))
1864         {
1865           emitcode ("mov", "a,%s", l);
1866           emitcode ("push", "acc");
1867         }
1868       else
1869         emitcode ("push", "%s", l);
1870     }
1871   _endLazyDPSEvaluation ();
1872 }
1873
1874 /*-----------------------------------------------------------------*/
1875 /* assignResultValue -               */
1876 /*-----------------------------------------------------------------*/
1877 static void
1878 assignResultValue (operand * oper)
1879 {
1880   int offset = 0;
1881   int size = AOP_SIZE (oper);
1882
1883   _startLazyDPSEvaluation ();
1884   while (size--)
1885     {
1886       aopPut (AOP (oper), fReturn[offset], offset);
1887       offset++;
1888     }
1889   _endLazyDPSEvaluation ();
1890 }
1891
1892
1893 /*-----------------------------------------------------------------*/
1894 /* genXpush - pushes onto the external stack                       */
1895 /*-----------------------------------------------------------------*/
1896 static void
1897 genXpush (iCode * ic)
1898 {
1899   asmop *aop = newAsmop (0);
1900   regs *r;
1901   int size, offset = 0;
1902
1903   D (emitcode (";", "genXpush ");
1904     );
1905
1906   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1907   r = getFreePtr (ic, &aop, FALSE);
1908
1909
1910   emitcode ("mov", "%s,_spx", r->name);
1911
1912   size = AOP_SIZE (IC_LEFT (ic));
1913   _startLazyDPSEvaluation ();
1914   while (size--)
1915     {
1916
1917       char *l = aopGet (AOP (IC_LEFT (ic)),
1918                         offset++, FALSE, FALSE, TRUE);
1919       MOVA (l);
1920       emitcode ("movx", "@%s,a", r->name);
1921       emitcode ("inc", "%s", r->name);
1922
1923     }
1924   _endLazyDPSEvaluation ();
1925
1926
1927   emitcode ("mov", "_spx,%s", r->name);
1928
1929   freeAsmop (NULL, aop, ic, TRUE);
1930   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1931 }
1932
1933 /*-----------------------------------------------------------------*/
1934 /* genIpush - genrate code for pushing this gets a little complex  */
1935 /*-----------------------------------------------------------------*/
1936 static void
1937 genIpush (iCode * ic)
1938 {
1939   int size, offset = 0;
1940   char *l;
1941
1942   D (emitcode (";", "genIpush ");
1943     );
1944
1945   /* if this is not a parm push : ie. it is spill push
1946      and spill push is always done on the local stack */
1947   if (!ic->parmPush)
1948     {
1949
1950       /* and the item is spilt then do nothing */
1951       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1952         return;
1953
1954       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1955       size = AOP_SIZE (IC_LEFT (ic));
1956       /* push it on the stack */
1957       _startLazyDPSEvaluation ();
1958       while (size--)
1959         {
1960           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1961           if (*l == '#')
1962             {
1963               MOVA (l);
1964               l = "acc";
1965             }
1966           emitcode ("push", "%s", l);
1967         }
1968       _endLazyDPSEvaluation ();
1969       return;
1970     }
1971
1972   /* this is a paramter push: in this case we call
1973      the routine to find the call and save those
1974      registers that need to be saved */
1975   saveRegisters (ic);
1976
1977   /* if use external stack then call the external
1978      stack pushing routine */
1979   if (options.useXstack)
1980     {
1981       genXpush (ic);
1982       return;
1983     }
1984
1985   /* then do the push */
1986   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1987
1988   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1989   size = AOP_SIZE (IC_LEFT (ic));
1990
1991   _startLazyDPSEvaluation ();
1992   while (size--)
1993     {
1994       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
1995       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1996           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1997           strcmp (l, "a"))
1998         {
1999           emitcode ("mov", "a,%s", l);
2000           emitcode ("push", "acc");
2001         }
2002       else
2003         emitcode ("push", "%s", l);
2004     }
2005   _endLazyDPSEvaluation ();
2006
2007   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2008 }
2009
2010 /*-----------------------------------------------------------------*/
2011 /* genIpop - recover the registers: can happen only for spilling   */
2012 /*-----------------------------------------------------------------*/
2013 static void
2014 genIpop (iCode * ic)
2015 {
2016   int size, offset;
2017
2018   D (emitcode (";", "genIpop ");
2019     );
2020
2021
2022   /* if the temp was not pushed then */
2023   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2024     return;
2025
2026   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2027   size = AOP_SIZE (IC_LEFT (ic));
2028   offset = (size - 1);
2029   _startLazyDPSEvaluation ();
2030   while (size--)
2031     {
2032       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2033                                      FALSE, TRUE, TRUE));
2034     }
2035   _endLazyDPSEvaluation ();
2036
2037   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2038 }
2039
2040 /*-----------------------------------------------------------------*/
2041 /* unsaverbank - restores the resgister bank from stack            */
2042 /*-----------------------------------------------------------------*/
2043 static void
2044 unsaverbank (int bank, iCode * ic, bool popPsw)
2045 {
2046   int i;
2047   asmop *aop;
2048   regs *r = NULL;
2049
2050   if (popPsw)
2051     {
2052       if (options.useXstack)
2053         {
2054           aop = newAsmop (0);
2055           r = getFreePtr (ic, &aop, FALSE);
2056
2057
2058           emitcode ("mov", "%s,_spx", r->name);
2059           emitcode ("movx", "a,@%s", r->name);
2060           emitcode ("mov", "psw,a");
2061           emitcode ("dec", "%s", r->name);
2062
2063         }
2064       else
2065         emitcode ("pop", "psw");
2066     }
2067
2068   for (i = (ds390_nRegs - 1); i >= 0; i--)
2069     {
2070       if (options.useXstack)
2071         {
2072           emitcode ("movx", "a,@%s", r->name);
2073           emitcode ("mov", "(%s+%d),a",
2074                     regs390[i].base, 8 * bank + regs390[i].offset);
2075           emitcode ("dec", "%s", r->name);
2076
2077         }
2078       else
2079         emitcode ("pop", "(%s+%d)",
2080                   regs390[i].base, 8 * bank + regs390[i].offset);
2081     }
2082
2083   if (options.useXstack)
2084     {
2085
2086       emitcode ("mov", "_spx,%s", r->name);
2087       freeAsmop (NULL, aop, ic, TRUE);
2088
2089     }
2090 }
2091
2092 /*-----------------------------------------------------------------*/
2093 /* saverbank - saves an entire register bank on the stack          */
2094 /*-----------------------------------------------------------------*/
2095 static void
2096 saverbank (int bank, iCode * ic, bool pushPsw)
2097 {
2098   int i;
2099   asmop *aop;
2100   regs *r = NULL;
2101
2102   if (options.useXstack)
2103     {
2104
2105       aop = newAsmop (0);
2106       r = getFreePtr (ic, &aop, FALSE);
2107       emitcode ("mov", "%s,_spx", r->name);
2108
2109     }
2110
2111   for (i = 0; i < ds390_nRegs; i++)
2112     {
2113       if (options.useXstack)
2114         {
2115           emitcode ("inc", "%s", r->name);
2116           emitcode ("mov", "a,(%s+%d)",
2117                     regs390[i].base, 8 * bank + regs390[i].offset);
2118           emitcode ("movx", "@%s,a", r->name);
2119         }
2120       else
2121         emitcode ("push", "(%s+%d)",
2122                   regs390[i].base, 8 * bank + regs390[i].offset);
2123     }
2124
2125   if (pushPsw)
2126     {
2127       if (options.useXstack)
2128         {
2129           emitcode ("mov", "a,psw");
2130           emitcode ("movx", "@%s,a", r->name);
2131           emitcode ("inc", "%s", r->name);
2132           emitcode ("mov", "_spx,%s", r->name);
2133           freeAsmop (NULL, aop, ic, TRUE);
2134
2135         }
2136       else
2137         emitcode ("push", "psw");
2138
2139       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2140     }
2141   ic->bankSaved = 1;
2142
2143 }
2144
2145 /*-----------------------------------------------------------------*/
2146 /* genCall - generates a call statement                            */
2147 /*-----------------------------------------------------------------*/
2148 static void
2149 genCall (iCode * ic)
2150 {
2151   sym_link *detype;
2152   int bankSwitched=0;
2153
2154   D (emitcode (";", "genCall "););
2155
2156   /* if we are calling a function that is not using
2157      the same register bank then we need to save the
2158      destination registers on the stack */
2159   detype = getSpec (operandType (IC_LEFT (ic)));
2160   if (detype &&
2161       (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2162       IS_ISR (currFunc->etype) &&
2163       !ic->bankSaved) {
2164     bankSwitched=1;
2165   }
2166   
2167   /* if caller saves & we have not saved then */
2168   if (!ic->regsSaved) {
2169     if (bankSwitched) {
2170       // no need to save if we switch banks
2171     } else {
2172       saveRegisters (ic);
2173     }
2174   }
2175   
2176   /* if send set is not empty the assign */
2177   if (_G.sendSet)
2178     {
2179       iCode *sic;
2180
2181       for (sic = setFirstItem (_G.sendSet); sic;
2182            sic = setNextItem (_G.sendSet))
2183         {
2184           int size, offset = 0;
2185
2186           aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2187           size = AOP_SIZE (IC_LEFT (sic));
2188
2189           _startLazyDPSEvaluation ();
2190           while (size--)
2191             {
2192               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2193                                 FALSE, FALSE, TRUE);
2194               if (strcmp (l, fReturn[offset])) {
2195                 genSetDPTR(0);
2196                 _flushLazyDPS();
2197                 emitcode ("mov", "%s,%s",
2198                           fReturn[offset],
2199                           l);
2200               }
2201               offset++;
2202             }
2203           _endLazyDPSEvaluation ();
2204           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2205         }
2206       _G.sendSet = NULL;
2207     }
2208
2209   if (bankSwitched) {
2210     saverbank(SPEC_BANK(detype), ic, TRUE);
2211   }
2212
2213   /* make the call */
2214   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2215                             OP_SYMBOL (IC_LEFT (ic))->rname :
2216                             OP_SYMBOL (IC_LEFT (ic))->name));
2217
2218   /* if we need assign a result value */
2219   if ((IS_ITEMP (IC_RESULT (ic)) &&
2220        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2221         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2222       IS_TRUE_SYMOP (IC_RESULT (ic)))
2223     {
2224       if (isOperandInFarSpace (IC_RESULT (ic))
2225           && getSize (operandType (IC_RESULT (ic))) <= 2)
2226         {
2227           int size = getSize (operandType (IC_RESULT (ic)));
2228
2229           /* Special case for 1 or 2 byte return in far space. */
2230           MOVA (fReturn[0]);
2231           if (size > 1)
2232             {
2233               emitcode ("mov", "b,%s", fReturn[1]);
2234             }
2235
2236           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2237           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2238
2239           if (size > 1)
2240             {
2241               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2242             }
2243           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2244         }
2245       else
2246         {
2247           _G.accInUse++;
2248           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2249           _G.accInUse--;
2250
2251           assignResultValue (IC_RESULT (ic));
2252
2253           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2254         }
2255     }
2256
2257   /* adjust the stack for parameters if
2258      required */
2259   if (ic->parmBytes)
2260     {
2261       int i;
2262       if (ic->parmBytes > 3)
2263         {
2264           emitcode ("mov", "a,%s", spname);
2265           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2266           emitcode ("mov", "%s,a", spname);
2267         }
2268       else
2269         for (i = 0; i < ic->parmBytes; i++)
2270           emitcode ("dec", "%s", spname);
2271     }
2272
2273   /* if register bank was saved then pop them */
2274   if (bankSwitched) {
2275     unsaverbank (SPEC_BANK (detype), ic, TRUE);
2276   } else {
2277     /* if we have saved some registers then unsave them */
2278     if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2279       unsaveRegisters (ic);
2280   }
2281 }
2282
2283 /*-----------------------------------------------------------------*/
2284 /* genPcall - generates a call by pointer statement                */
2285 /*-----------------------------------------------------------------*/
2286 static void
2287 genPcall (iCode * ic)
2288 {
2289   sym_link *detype;
2290   symbol *rlbl = newiTempLabel (NULL);
2291
2292   D (emitcode (";", "genPcall ");
2293     );
2294
2295   /* if caller saves & we have not saved then */
2296   if (!ic->regsSaved)
2297     saveRegisters (ic);
2298
2299   /* if we are calling a function that is not using
2300      the same register bank then we need to save the
2301      destination registers on the stack */
2302   detype = getSpec (operandType (IC_LEFT (ic)));
2303   if (detype &&
2304       IS_ISR (currFunc->etype) &&
2305       (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2306     saverbank (SPEC_BANK (detype), ic, TRUE);
2307
2308   /* push the return address on to the stack */
2309   emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2310   emitcode ("push", "acc");
2311   emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2312   emitcode ("push", "acc");
2313
2314   if (options.model == MODEL_FLAT24)
2315     {
2316       emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2317       emitcode ("push", "acc");
2318     }
2319
2320   /* now push the calling address */
2321   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2322
2323   pushSide (IC_LEFT (ic), FPTRSIZE);
2324
2325   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2326
2327   /* if send set is not empty the assign */
2328   if (_G.sendSet)
2329     {
2330       iCode *sic;
2331
2332       for (sic = setFirstItem (_G.sendSet); sic;
2333            sic = setNextItem (_G.sendSet))
2334         {
2335           int size, offset = 0;
2336
2337           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2338           size = AOP_SIZE (IC_LEFT (sic));
2339           _startLazyDPSEvaluation ();
2340           while (size--)
2341             {
2342               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2343                                 FALSE, FALSE, TRUE);
2344               if (strcmp (l, fReturn[offset]))
2345                 {
2346                   emitcode ("mov", "%s,%s",
2347                             fReturn[offset],
2348                             l);
2349                 }
2350               offset++;
2351             }
2352           _endLazyDPSEvaluation ();
2353           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2354         }
2355       _G.sendSet = NULL;
2356     }
2357
2358   emitcode ("ret", "");
2359   emitcode ("", "%05d$:", (rlbl->key + 100));
2360
2361
2362   /* if we need assign a result value */
2363   if ((IS_ITEMP (IC_RESULT (ic)) &&
2364        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2365         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2366       IS_TRUE_SYMOP (IC_RESULT (ic)))
2367     {
2368
2369       _G.accInUse++;
2370       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2371       _G.accInUse--;
2372
2373       assignResultValue (IC_RESULT (ic));
2374
2375       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2376     }
2377
2378   /* adjust the stack for parameters if
2379      required */
2380   if (ic->parmBytes)
2381     {
2382       int i;
2383       if (ic->parmBytes > 3)
2384         {
2385           emitcode ("mov", "a,%s", spname);
2386           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2387           emitcode ("mov", "%s,a", spname);
2388         }
2389       else
2390         for (i = 0; i < ic->parmBytes; i++)
2391           emitcode ("dec", "%s", spname);
2392
2393     }
2394
2395   /* if register bank was saved then unsave them */
2396   if (detype &&
2397       (SPEC_BANK (currFunc->etype) !=
2398        SPEC_BANK (detype)))
2399     unsaverbank (SPEC_BANK (detype), ic, TRUE);
2400
2401   /* if we hade saved some registers then
2402      unsave them */
2403   if (ic->regsSaved)
2404     unsaveRegisters (ic);
2405
2406 }
2407
2408 /*-----------------------------------------------------------------*/
2409 /* resultRemat - result  is rematerializable                       */
2410 /*-----------------------------------------------------------------*/
2411 static int
2412 resultRemat (iCode * ic)
2413 {
2414   if (SKIP_IC (ic) || ic->op == IFX)
2415     return 0;
2416
2417   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2418     {
2419       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2420       if (sym->remat && !POINTER_SET (ic))
2421         return 1;
2422     }
2423
2424   return 0;
2425 }
2426
2427 #if defined(__BORLANDC__) || defined(_MSC_VER)
2428 #define STRCASECMP stricmp
2429 #else
2430 #define STRCASECMP strcasecmp
2431 #endif
2432
2433 /*-----------------------------------------------------------------*/
2434 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2435 /*-----------------------------------------------------------------*/
2436 static bool
2437 inExcludeList (char *s)
2438 {
2439   int i = 0;
2440
2441   if (options.excludeRegs[i] &&
2442       STRCASECMP (options.excludeRegs[i], "none") == 0)
2443     return FALSE;
2444
2445   for (i = 0; options.excludeRegs[i]; i++)
2446     {
2447       if (options.excludeRegs[i] &&
2448           STRCASECMP (s, options.excludeRegs[i]) == 0)
2449         return TRUE;
2450     }
2451   return FALSE;
2452 }
2453
2454 /*-----------------------------------------------------------------*/
2455 /* genFunction - generated code for function entry                 */
2456 /*-----------------------------------------------------------------*/
2457 static void
2458 genFunction (iCode * ic)
2459 {
2460   symbol *sym;
2461   sym_link *fetype;
2462
2463   D (emitcode (";", "genFunction ");
2464     );
2465
2466   _G.nRegsSaved = 0;
2467   /* create the function header */
2468   emitcode (";", "-----------------------------------------");
2469   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2470   emitcode (";", "-----------------------------------------");
2471
2472   emitcode ("", "%s:", sym->rname);
2473   fetype = getSpec (operandType (IC_LEFT (ic)));
2474
2475   /* if critical function then turn interrupts off */
2476   if (SPEC_CRTCL (fetype))
2477     emitcode ("clr", "ea");
2478
2479   /* here we need to generate the equates for the
2480      register bank if required */
2481   if (SPEC_BANK (fetype) != rbank)
2482     {
2483       int i;
2484
2485       rbank = SPEC_BANK (fetype);
2486       for (i = 0; i < ds390_nRegs; i++)
2487         {
2488           if (strcmp (regs390[i].base, "0") == 0)
2489             emitcode ("", "%s = 0x%02x",
2490                       regs390[i].dname,
2491                       8 * rbank + regs390[i].offset);
2492           else
2493             emitcode ("", "%s = %s + 0x%02x",
2494                       regs390[i].dname,
2495                       regs390[i].base,
2496                       8 * rbank + regs390[i].offset);
2497         }
2498     }
2499
2500   /* if this is an interrupt service routine then
2501      save acc, b, dpl, dph  */
2502   if (IS_ISR (sym->etype))
2503     {
2504
2505       if (!inExcludeList ("acc"))
2506         emitcode ("push", "acc");
2507       if (!inExcludeList ("b"))
2508         emitcode ("push", "b");
2509       if (!inExcludeList ("dpl"))
2510         emitcode ("push", "dpl");
2511       if (!inExcludeList ("dph"))
2512         emitcode ("push", "dph");
2513       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2514         {
2515           emitcode ("push", "dpx");
2516           /* Make sure we're using standard DPTR */
2517           emitcode ("push", "dps");
2518           emitcode ("mov", "dps, #0x00");
2519           if (options.stack10bit)
2520             {
2521               /* This ISR could conceivably use DPTR2. Better save it. */
2522               emitcode ("push", "dpl1");
2523               emitcode ("push", "dph1");
2524               emitcode ("push", "dpx1");
2525               emitcode ("push",  DP2_RESULT_REG);
2526             }
2527         }
2528       /* if this isr has no bank i.e. is going to
2529          run with bank 0 , then we need to save more
2530          registers :-) */
2531       if (!SPEC_BANK (sym->etype))
2532         {
2533
2534           /* if this function does not call any other
2535              function then we can be economical and
2536              save only those registers that are used */
2537           if (!sym->hasFcall)
2538             {
2539               int i;
2540
2541               /* if any registers used */
2542               if (sym->regsUsed)
2543                 {
2544                   /* save the registers used */
2545                   for (i = 0; i < sym->regsUsed->size; i++)
2546                     {
2547                       if (bitVectBitValue (sym->regsUsed, i) ||
2548                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2549                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2550                     }
2551                 }
2552
2553             }
2554           else
2555             {
2556               /* this function has  a function call cannot
2557                  determines register usage so we will have the
2558                  entire bank */
2559               saverbank (0, ic, FALSE);
2560             }
2561         }
2562     }
2563   else
2564     {
2565       /* if callee-save to be used for this function
2566          then save the registers being used in this function */
2567       if (sym->calleeSave)
2568         {
2569           int i;
2570
2571           /* if any registers used */
2572           if (sym->regsUsed)
2573             {
2574               /* save the registers used */
2575               for (i = 0; i < sym->regsUsed->size; i++)
2576                 {
2577                   if (bitVectBitValue (sym->regsUsed, i) ||
2578                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2579                     {
2580                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2581                       _G.nRegsSaved++;
2582                     }
2583                 }
2584             }
2585         }
2586     }
2587
2588   /* set the register bank to the desired value */
2589   if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2590     {
2591       emitcode ("push", "psw");
2592       emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2593     }
2594
2595   if (IS_RENT (sym->etype) || options.stackAuto)
2596     {
2597
2598       if (options.useXstack)
2599         {
2600           emitcode ("mov", "r0,%s", spname);
2601           emitcode ("mov", "a,_bp");
2602           emitcode ("movx", "@r0,a");
2603           emitcode ("inc", "%s", spname);
2604         }
2605       else
2606         {
2607           /* set up the stack */
2608           emitcode ("push", "_bp");     /* save the callers stack  */
2609         }
2610       emitcode ("mov", "_bp,%s", spname);
2611     }
2612
2613   /* adjust the stack for the function */
2614   if (sym->stack)
2615     {
2616
2617       int i = sym->stack;
2618       if (i > 256)
2619         werror (W_STACK_OVERFLOW, sym->name);
2620
2621       if (i > 3 && sym->recvSize < 4)
2622         {
2623
2624           emitcode ("mov", "a,sp");
2625           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2626           emitcode ("mov", "sp,a");
2627
2628         }
2629       else
2630         while (i--)
2631           emitcode ("inc", "sp");
2632     }
2633
2634   if (sym->xstack)
2635     {
2636
2637       emitcode ("mov", "a,_spx");
2638       emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2639       emitcode ("mov", "_spx,a");
2640     }
2641
2642 }
2643
2644 /*-----------------------------------------------------------------*/
2645 /* genEndFunction - generates epilogue for functions               */
2646 /*-----------------------------------------------------------------*/
2647 static void
2648 genEndFunction (iCode * ic)
2649 {
2650   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2651
2652   D (emitcode (";", "genEndFunction ");
2653     );
2654
2655   if (IS_RENT (sym->etype) || options.stackAuto)
2656     {
2657       emitcode ("mov", "%s,_bp", spname);
2658     }
2659
2660   /* if use external stack but some variables were
2661      added to the local stack then decrement the
2662      local stack */
2663   if (options.useXstack && sym->stack)
2664     {
2665       emitcode ("mov", "a,sp");
2666       emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2667       emitcode ("mov", "sp,a");
2668     }
2669
2670
2671   if ((IS_RENT (sym->etype) || options.stackAuto))
2672     {
2673       if (options.useXstack)
2674         {
2675           emitcode ("mov", "r0,%s", spname);
2676           emitcode ("movx", "a,@r0");
2677           emitcode ("mov", "_bp,a");
2678           emitcode ("dec", "%s", spname);
2679         }
2680       else
2681         {
2682           emitcode ("pop", "_bp");
2683         }
2684     }
2685
2686   /* restore the register bank  */
2687   if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2688     emitcode ("pop", "psw");
2689
2690   if (IS_ISR (sym->etype))
2691     {
2692
2693       /* now we need to restore the registers */
2694       /* if this isr has no bank i.e. is going to
2695          run with bank 0 , then we need to save more
2696          registers :-) */
2697       if (!SPEC_BANK (sym->etype))
2698         {
2699
2700           /* if this function does not call any other
2701              function then we can be economical and
2702              save only those registers that are used */
2703           if (!sym->hasFcall)
2704             {
2705               int i;
2706
2707               /* if any registers used */
2708               if (sym->regsUsed)
2709                 {
2710                   /* save the registers used */
2711                   for (i = sym->regsUsed->size; i >= 0; i--)
2712                     {
2713                       if (bitVectBitValue (sym->regsUsed, i) ||
2714                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2715                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2716                     }
2717                 }
2718
2719             }
2720           else
2721             {
2722               /* this function has  a function call cannot
2723                  determines register usage so we will have the
2724                  entire bank */
2725               unsaverbank (0, ic, FALSE);
2726             }
2727         }
2728
2729       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2730         {
2731           if (options.stack10bit)
2732             {
2733               emitcode ("pop", DP2_RESULT_REG);
2734               emitcode ("pop", "dpx1");
2735               emitcode ("pop", "dph1");
2736               emitcode ("pop", "dpl1");
2737             }
2738           emitcode ("pop", "dps");
2739           emitcode ("pop", "dpx");
2740         }
2741       if (!inExcludeList ("dph"))
2742         emitcode ("pop", "dph");
2743       if (!inExcludeList ("dpl"))
2744         emitcode ("pop", "dpl");
2745       if (!inExcludeList ("b"))
2746         emitcode ("pop", "b");
2747       if (!inExcludeList ("acc"))
2748         emitcode ("pop", "acc");
2749
2750       if (SPEC_CRTCL (sym->etype))
2751         emitcode ("setb", "ea");
2752
2753       /* if debug then send end of function */
2754 /*  if (options.debug && currFunc) { */
2755       if (currFunc)
2756         {
2757           _G.debugLine = 1;
2758           emitcode ("", "C$%s$%d$%d$%d ==.",
2759                     FileBaseName (ic->filename), currFunc->lastLine,
2760                     ic->level, ic->block);
2761           if (IS_STATIC (currFunc->etype))
2762             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2763           else
2764             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2765           _G.debugLine = 0;
2766         }
2767
2768       emitcode ("reti", "");
2769     }
2770   else
2771     {
2772       if (SPEC_CRTCL (sym->etype))
2773         emitcode ("setb", "ea");
2774
2775       if (sym->calleeSave)
2776         {
2777           int i;
2778
2779           /* if any registers used */
2780           if (sym->regsUsed)
2781             {
2782               /* save the registers used */
2783               for (i = sym->regsUsed->size; i >= 0; i--)
2784                 {
2785                   if (bitVectBitValue (sym->regsUsed, i) ||
2786                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2787                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2788                 }
2789             }
2790
2791         }
2792
2793       /* if debug then send end of function */
2794       if (currFunc)
2795         {
2796           _G.debugLine = 1;
2797           emitcode ("", "C$%s$%d$%d$%d ==.",
2798                     FileBaseName (ic->filename), currFunc->lastLine,
2799                     ic->level, ic->block);
2800           if (IS_STATIC (currFunc->etype))
2801             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2802           else
2803             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2804           _G.debugLine = 0;
2805         }
2806
2807       emitcode ("ret", "");
2808     }
2809
2810 }
2811
2812 /*-----------------------------------------------------------------*/
2813 /* genRet - generate code for return statement                     */
2814 /*-----------------------------------------------------------------*/
2815 static void
2816 genRet (iCode * ic)
2817 {
2818   int size, offset = 0, pushed = 0;
2819
2820   D (emitcode (";", "genRet ");
2821     );
2822
2823   /* if we have no return value then
2824      just generate the "ret" */
2825   if (!IC_LEFT (ic))
2826     goto jumpret;
2827
2828   /* we have something to return then
2829      move the return value into place */
2830   aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2831   size = AOP_SIZE (IC_LEFT (ic));
2832
2833   _startLazyDPSEvaluation ();
2834   while (size--)
2835     {
2836       char *l;
2837       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2838         {
2839           l = aopGet (AOP (IC_LEFT (ic)), offset++,
2840                       FALSE, TRUE, FALSE);
2841           emitcode ("push", "%s", l);
2842           pushed++;
2843         }
2844       else
2845         {
2846           l = aopGet (AOP (IC_LEFT (ic)), offset,
2847                       FALSE, FALSE, FALSE);
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   emitcode (";",__FUNCTION__);
3705   if (size<1 || size>2) {
3706     // this should never happen
3707       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
3708                AOP_SIZE(result), __FUNCTION__, lineno);
3709       exit (1);
3710   }
3711
3712   /* (if two literals: the value is computed before) */
3713   /* if one literal, literal on the right */
3714   if (AOP_TYPE (left) == AOP_LIT)
3715     {
3716       operand *t = right;
3717       right = left;
3718       left = t;
3719       emitcode (";", "swapped left and right");
3720     }
3721
3722   if (SPEC_USIGN(opetype)
3723       // ignore the sign of left and right, what else can we do?
3724       || (SPEC_USIGN(operandType(left)) && 
3725           SPEC_USIGN(operandType(right)))) {
3726     // just an unsigned 8*8=8/16 multiply
3727     //emitcode (";","unsigned");
3728     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3729     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3730     emitcode ("mul", "ab");
3731     aopPut (AOP (result), "a", 0);
3732     if (size==2) {
3733       aopPut (AOP (result), "b", 1);
3734     }
3735     return;
3736   }
3737
3738   // we have to do a signed multiply
3739
3740   emitcode (";", "signed");
3741   emitcode ("clr", "F0"); // reset sign flag
3742   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3743   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3744
3745   lbl=newiTempLabel(NULL);
3746   emitcode ("jnb", "acc.7,%05d$",  lbl->key+100);
3747   // left side is negative, 8-bit two's complement, this fails for -128
3748   emitcode ("setb", "F0"); // set sign flag
3749   emitcode ("cpl", "a");
3750   emitcode ("inc", "a");
3751
3752   emitcode ("", "%05d$:", lbl->key+100);
3753   emitcode ("xch", "a,b");
3754
3755   /* if literal */
3756   if (AOP_TYPE(right)==AOP_LIT) {
3757     /* AND literal negative */
3758     if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3759       // two's complement for literal<0
3760       emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3761       emitcode ("cpl", "a");
3762       emitcode ("inc", "a");
3763     }
3764   } else {
3765     lbl=newiTempLabel(NULL);
3766     emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3767     // right side is negative, 8-bit two's complement
3768     emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3769     emitcode ("cpl", "a");
3770     emitcode ("inc", "a");
3771     emitcode ("", "%05d$:", lbl->key+100);
3772   }
3773   emitcode ("mul", "ab");
3774     
3775   lbl=newiTempLabel(NULL);
3776   emitcode ("jnb", "F0,%05d$", lbl->key+100);
3777   // only ONE op was negative, we have to do a 8/16-bit two's complement
3778   emitcode ("cpl", "a"); // lsb
3779   if (size==1) {
3780     emitcode ("inc", "a");
3781   } else {
3782     emitcode ("add", "a,#1");
3783     emitcode ("xch", "a,b");
3784     emitcode ("cpl", "a"); // msb
3785     emitcode ("addc", "a,#0");
3786     emitcode ("xch", "a,b");
3787   }
3788
3789   emitcode ("", "%05d$:", lbl->key+100);
3790   aopPut (AOP (result), "a", 0);
3791   if (size==2) {
3792     aopPut (AOP (result), "b", 1);
3793   }
3794 }
3795
3796 /*-----------------------------------------------------------------*/
3797 /* genMult - generates code for multiplication                     */
3798 /*-----------------------------------------------------------------*/
3799 static void
3800 genMult (iCode * ic)
3801 {
3802   operand *left = IC_LEFT (ic);
3803   operand *right = IC_RIGHT (ic);
3804   operand *result = IC_RESULT (ic);
3805
3806   D (emitcode (";", "genMult "););
3807
3808   /* assign the amsops */
3809   AOP_OP_3 (ic);
3810
3811   /* special cases first */
3812   /* both are bits */
3813   if (AOP_TYPE (left) == AOP_CRY &&
3814       AOP_TYPE (right) == AOP_CRY)
3815     {
3816       genMultbits (left, right, result);
3817       goto release;
3818     }
3819
3820   /* if both are of size == 1 */
3821   if (AOP_SIZE (left) == 1 &&
3822       AOP_SIZE (right) == 1)
3823     {
3824       genMultOneByte (left, right, result);
3825       goto release;
3826     }
3827
3828   /* should have been converted to function call */
3829   assert (1);
3830
3831 release:
3832   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3833   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3834   freeAsmop (result, NULL, ic, TRUE);
3835 }
3836
3837 /*-----------------------------------------------------------------*/
3838 /* genDivbits :- division of bits                                  */
3839 /*-----------------------------------------------------------------*/
3840 static void
3841 genDivbits (operand * left,
3842             operand * right,
3843             operand * result)
3844 {
3845
3846   char *l;
3847
3848   /* the result must be bit */
3849   LOAD_AB_FOR_DIV (left, right, l);
3850   emitcode ("div", "ab");
3851   emitcode ("rrc", "a");
3852   aopPut (AOP (result), "c", 0);
3853 }
3854
3855 /*-----------------------------------------------------------------*/
3856 /* genDivOneByte : 8 bit division                                  */
3857 /*-----------------------------------------------------------------*/
3858 static void
3859 genDivOneByte (operand * left,
3860                operand * right,
3861                operand * result)
3862 {
3863   sym_link *opetype = operandType (result);
3864   char *l;
3865   symbol *lbl;
3866   int size, offset;
3867
3868   size = AOP_SIZE (result) - 1;
3869   offset = 1;
3870   /* signed or unsigned */
3871   if (SPEC_USIGN (opetype))
3872     {
3873       /* unsigned is easy */
3874       LOAD_AB_FOR_DIV (left, right, l);
3875       emitcode ("div", "ab");
3876       aopPut (AOP (result), "a", 0);
3877       while (size--)
3878         aopPut (AOP (result), zero, offset++);
3879       return;
3880     }
3881
3882   /* signed is a little bit more difficult */
3883
3884   /* save the signs of the operands */
3885   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3886   MOVA (l);
3887   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3888   emitcode ("push", "acc");     /* save it on the stack */
3889
3890   /* now sign adjust for both left & right */
3891   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3892   MOVA (l);
3893   lbl = newiTempLabel (NULL);
3894   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3895   emitcode ("cpl", "a");
3896   emitcode ("inc", "a");
3897   emitcode ("", "%05d$:", (lbl->key + 100));
3898   emitcode ("mov", "b,a");
3899
3900   /* sign adjust left side */
3901   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3902   MOVA (l);
3903
3904   lbl = newiTempLabel (NULL);
3905   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3906   emitcode ("cpl", "a");
3907   emitcode ("inc", "a");
3908   emitcode ("", "%05d$:", (lbl->key + 100));
3909
3910   /* now the division */
3911   emitcode ("nop", "; workaround for DS80C390 div bug.");
3912   emitcode ("div", "ab");
3913   /* we are interested in the lower order
3914      only */
3915   emitcode ("mov", "b,a");
3916   lbl = newiTempLabel (NULL);
3917   emitcode ("pop", "acc");
3918   /* if there was an over flow we don't
3919      adjust the sign of the result */
3920   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3921   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3922   CLRC;
3923   emitcode ("clr", "a");
3924   emitcode ("subb", "a,b");
3925   emitcode ("mov", "b,a");
3926   emitcode ("", "%05d$:", (lbl->key + 100));
3927
3928   /* now we are done */
3929   aopPut (AOP (result), "b", 0);
3930   if (size > 0)
3931     {
3932       emitcode ("mov", "c,b.7");
3933       emitcode ("subb", "a,acc");
3934     }
3935   while (size--)
3936     aopPut (AOP (result), "a", offset++);
3937
3938 }
3939
3940 /*-----------------------------------------------------------------*/
3941 /* genDiv - generates code for division                            */
3942 /*-----------------------------------------------------------------*/
3943 static void
3944 genDiv (iCode * ic)
3945 {
3946   operand *left = IC_LEFT (ic);
3947   operand *right = IC_RIGHT (ic);
3948   operand *result = IC_RESULT (ic);
3949
3950   D (emitcode (";", "genDiv ");
3951     );
3952
3953   /* assign the amsops */
3954   AOP_OP_3 (ic);
3955
3956   /* special cases first */
3957   /* both are bits */
3958   if (AOP_TYPE (left) == AOP_CRY &&
3959       AOP_TYPE (right) == AOP_CRY)
3960     {
3961       genDivbits (left, right, result);
3962       goto release;
3963     }
3964
3965   /* if both are of size == 1 */
3966   if (AOP_SIZE (left) == 1 &&
3967       AOP_SIZE (right) == 1)
3968     {
3969       genDivOneByte (left, right, result);
3970       goto release;
3971     }
3972
3973   /* should have been converted to function call */
3974   assert (1);
3975 release:
3976   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3977   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3978   freeAsmop (result, NULL, ic, TRUE);
3979 }
3980
3981 /*-----------------------------------------------------------------*/
3982 /* genModbits :- modulus of bits                                   */
3983 /*-----------------------------------------------------------------*/
3984 static void
3985 genModbits (operand * left,
3986             operand * right,
3987             operand * result)
3988 {
3989
3990   char *l;
3991
3992   /* the result must be bit */
3993   LOAD_AB_FOR_DIV (left, right, l);
3994   emitcode ("div", "ab");
3995   emitcode ("mov", "a,b");
3996   emitcode ("rrc", "a");
3997   aopPut (AOP (result), "c", 0);
3998 }
3999
4000 /*-----------------------------------------------------------------*/
4001 /* genModOneByte : 8 bit modulus                                   */
4002 /*-----------------------------------------------------------------*/
4003 static void
4004 genModOneByte (operand * left,
4005                operand * right,
4006                operand * result)
4007 {
4008   sym_link *opetype = operandType (result);
4009   char *l;
4010   symbol *lbl;
4011
4012   /* signed or unsigned */
4013   if (SPEC_USIGN (opetype))
4014     {
4015       /* unsigned is easy */
4016       LOAD_AB_FOR_DIV (left, right, l);
4017       emitcode ("div", "ab");
4018       aopPut (AOP (result), "b", 0);
4019       return;
4020     }
4021
4022   /* signed is a little bit more difficult */
4023
4024   /* save the signs of the operands */
4025   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4026   MOVA (l);
4027
4028   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4029   emitcode ("push", "acc");     /* save it on the stack */
4030
4031   /* now sign adjust for both left & right */
4032   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4033   MOVA (l);
4034
4035   lbl = newiTempLabel (NULL);
4036   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4037   emitcode ("cpl", "a");
4038   emitcode ("inc", "a");
4039   emitcode ("", "%05d$:", (lbl->key + 100));
4040   emitcode ("mov", "b,a");
4041
4042   /* sign adjust left side */
4043   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4044   MOVA (l);
4045
4046   lbl = newiTempLabel (NULL);
4047   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4048   emitcode ("cpl", "a");
4049   emitcode ("inc", "a");
4050   emitcode ("", "%05d$:", (lbl->key + 100));
4051
4052   /* now the multiplication */
4053   emitcode ("nop", "; workaround for DS80C390 div bug.");
4054   emitcode ("div", "ab");
4055   /* we are interested in the lower order
4056      only */
4057   lbl = newiTempLabel (NULL);
4058   emitcode ("pop", "acc");
4059   /* if there was an over flow we don't
4060      adjust the sign of the result */
4061   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4062   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4063   CLRC;
4064   emitcode ("clr", "a");
4065   emitcode ("subb", "a,b");
4066   emitcode ("mov", "b,a");
4067   emitcode ("", "%05d$:", (lbl->key + 100));
4068
4069   /* now we are done */
4070   aopPut (AOP (result), "b", 0);
4071
4072 }
4073
4074 /*-----------------------------------------------------------------*/
4075 /* genMod - generates code for division                            */
4076 /*-----------------------------------------------------------------*/
4077 static void
4078 genMod (iCode * ic)
4079 {
4080   operand *left = IC_LEFT (ic);
4081   operand *right = IC_RIGHT (ic);
4082   operand *result = IC_RESULT (ic);
4083
4084   D (emitcode (";", "genMod ");
4085     );
4086
4087   /* assign the amsops */
4088   AOP_OP_3 (ic);
4089
4090   /* special cases first */
4091   /* both are bits */
4092   if (AOP_TYPE (left) == AOP_CRY &&
4093       AOP_TYPE (right) == AOP_CRY)
4094     {
4095       genModbits (left, right, result);
4096       goto release;
4097     }
4098
4099   /* if both are of size == 1 */
4100   if (AOP_SIZE (left) == 1 &&
4101       AOP_SIZE (right) == 1)
4102     {
4103       genModOneByte (left, right, result);
4104       goto release;
4105     }
4106
4107   /* should have been converted to function call */
4108   assert (1);
4109
4110 release:
4111   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4112   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4113   freeAsmop (result, NULL, ic, TRUE);
4114 }
4115
4116 /*-----------------------------------------------------------------*/
4117 /* genIfxJump :- will create a jump depending on the ifx           */
4118 /*-----------------------------------------------------------------*/
4119 static void
4120 genIfxJump (iCode * ic, char *jval)
4121 {
4122   symbol *jlbl;
4123   symbol *tlbl = newiTempLabel (NULL);
4124   char *inst;
4125
4126   D (emitcode (";", "genIfxJump ");
4127     );
4128
4129   /* if true label then we jump if condition
4130      supplied is true */
4131   if (IC_TRUE (ic))
4132     {
4133       jlbl = IC_TRUE (ic);
4134       inst = ((strcmp (jval, "a") == 0 ? "jz" :
4135                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4136     }
4137   else
4138     {
4139       /* false label is present */
4140       jlbl = IC_FALSE (ic);
4141       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4142                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4143     }
4144   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4145     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4146   else
4147     emitcode (inst, "%05d$", tlbl->key + 100);
4148   emitcode ("ljmp", "%05d$", jlbl->key + 100);
4149   emitcode ("", "%05d$:", tlbl->key + 100);
4150
4151   /* mark the icode as generated */
4152   ic->generated = 1;
4153 }
4154
4155 /*-----------------------------------------------------------------*/
4156 /* genCmp :- greater or less than comparison                       */
4157 /*-----------------------------------------------------------------*/
4158 static void
4159 genCmp (operand * left, operand * right,
4160         iCode * ic, iCode * ifx, int sign)
4161 {
4162   int size, offset = 0;
4163   unsigned long lit = 0L;
4164   operand *result;
4165
4166   D (emitcode (";", "genCmp");
4167     );
4168
4169   result = IC_RESULT (ic);
4170
4171   /* if left & right are bit variables */
4172   if (AOP_TYPE (left) == AOP_CRY &&
4173       AOP_TYPE (right) == AOP_CRY)
4174     {
4175       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4176       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4177     }
4178   else
4179     {
4180       /* subtract right from left if at the
4181          end the carry flag is set then we know that
4182          left is greater than right */
4183       size = max (AOP_SIZE (left), AOP_SIZE (right));
4184
4185       /* if unsigned char cmp with lit, do cjne left,#right,zz */
4186       if ((size == 1) && !sign &&
4187           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4188         {
4189           symbol *lbl = newiTempLabel (NULL);
4190           emitcode ("cjne", "%s,%s,%05d$",
4191                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4192                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4193                     lbl->key + 100);
4194           emitcode ("", "%05d$:", lbl->key + 100);
4195         }
4196       else
4197         {
4198           if (AOP_TYPE (right) == AOP_LIT)
4199             {
4200               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4201               /* optimize if(x < 0) or if(x >= 0) */
4202               if (lit == 0L)
4203                 {
4204                   if (!sign)
4205                     {
4206                       CLRC;
4207                     }
4208                   else
4209                     {
4210                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4211
4212                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4213                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4214
4215                       aopOp (result, ic, FALSE, FALSE);
4216
4217                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4218                         {
4219                           freeAsmop (result, NULL, ic, TRUE);
4220                           genIfxJump (ifx, "acc.7");
4221                           return;
4222                         }
4223                       else
4224                         {
4225                           emitcode ("rlc", "a");
4226                         }
4227                       goto release_freedLR;
4228                     }
4229                   goto release;
4230                 }
4231             }
4232           CLRC;
4233           while (size--)
4234             {
4235               emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4236               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4237               emitcode (";", "genCmp #2");
4238               if (sign && (size == 0))
4239                 {
4240                   emitcode (";", "genCmp #3");
4241                   emitcode ("xrl", "a,#0x80");
4242                   if (AOP_TYPE (right) == AOP_LIT)
4243                     {
4244                       unsigned long lit = (unsigned long)
4245                       floatFromVal (AOP (right)->aopu.aop_lit);
4246                       emitcode (";", "genCmp #3.1");
4247                       emitcode ("subb", "a,#0x%02x",
4248                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4249                     }
4250                   else
4251                     {
4252                       emitcode (";", "genCmp #3.2");
4253                       if (AOP_NEEDSACC (right))
4254                         {
4255                           emitcode ("push", "acc");
4256                         }
4257                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4258                                                        FALSE, FALSE, FALSE));
4259                       emitcode ("xrl", "b,#0x80");
4260                       if (AOP_NEEDSACC (right))
4261                         {
4262                           emitcode ("pop", "acc");
4263                         }
4264                       emitcode ("subb", "a,b");
4265                     }
4266                 }
4267               else
4268                 {
4269                   const char *s;
4270
4271                   emitcode (";", "genCmp #4");
4272                   if (AOP_NEEDSACC (right))
4273                     {
4274                       /* Yuck!! */
4275                       emitcode (";", "genCmp #4.1");
4276                       emitcode ("xch", "a, b");
4277                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4278                       emitcode ("xch", "a, b");
4279                       s = "b";
4280                     }
4281                   else
4282                     {
4283                       emitcode (";", "genCmp #4.2");
4284                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4285                     }
4286
4287                   emitcode ("subb", "a,%s", s);
4288                 }
4289             }
4290         }
4291     }
4292
4293 release:
4294 /* Don't need the left & right operands any more; do need the result. */
4295   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4296   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4297
4298   aopOp (result, ic, FALSE, FALSE);
4299
4300 release_freedLR:
4301
4302   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4303     {
4304       outBitC (result);
4305     }
4306   else
4307     {
4308       /* if the result is used in the next
4309          ifx conditional branch then generate
4310          code a little differently */
4311       if (ifx)
4312         {
4313           genIfxJump (ifx, "c");
4314         }
4315       else
4316         {
4317           outBitC (result);
4318         }
4319       /* leave the result in acc */
4320     }
4321   freeAsmop (result, NULL, ic, TRUE);
4322 }
4323
4324 /*-----------------------------------------------------------------*/
4325 /* genCmpGt :- greater than comparison                             */
4326 /*-----------------------------------------------------------------*/
4327 static void
4328 genCmpGt (iCode * ic, iCode * ifx)
4329 {
4330   operand *left, *right;
4331   sym_link *letype, *retype;
4332   int sign;
4333
4334   D (emitcode (";", "genCmpGt ");
4335     );
4336
4337   left = IC_LEFT (ic);
4338   right = IC_RIGHT (ic);
4339
4340   letype = getSpec (operandType (left));
4341   retype = getSpec (operandType (right));
4342   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4343
4344   /* assign the left & right amsops */
4345   AOP_OP_2 (ic);
4346
4347   genCmp (right, left, ic, ifx, sign);
4348 }
4349
4350 /*-----------------------------------------------------------------*/
4351 /* genCmpLt - less than comparisons                                */
4352 /*-----------------------------------------------------------------*/
4353 static void
4354 genCmpLt (iCode * ic, iCode * ifx)
4355 {
4356   operand *left, *right;
4357   sym_link *letype, *retype;
4358   int sign;
4359
4360   D (emitcode (";", "genCmpLt "););
4361
4362   left = IC_LEFT (ic);
4363   right = IC_RIGHT (ic);
4364
4365   letype = getSpec (operandType (left));
4366   retype = getSpec (operandType (right));
4367   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4368
4369   /* assign the left & right amsops */
4370   AOP_OP_2 (ic);
4371
4372   genCmp (left, right, ic, ifx, sign);
4373 }
4374
4375 /*-----------------------------------------------------------------*/
4376 /* gencjneshort - compare and jump if not equal                    */
4377 /*-----------------------------------------------------------------*/
4378 static void
4379 gencjneshort (operand * left, operand * right, symbol * lbl)
4380 {
4381   int size = max (AOP_SIZE (left), AOP_SIZE (right));
4382   int offset = 0;
4383   unsigned long lit = 0L;
4384
4385   D (emitcode (";", "gencjneshort");
4386     );
4387
4388   /* if the left side is a literal or
4389      if the right is in a pointer register and left
4390      is not */
4391   if ((AOP_TYPE (left) == AOP_LIT) ||
4392       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4393     {
4394       operand *t = right;
4395       right = left;
4396       left = t;
4397     }
4398
4399   if (AOP_TYPE (right) == AOP_LIT)
4400     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4401
4402   if (opIsGptr (left) || opIsGptr (right))
4403     {
4404       /* We are comparing a generic pointer to something.
4405        * Exclude the generic type byte from the comparison.
4406        */
4407       size--;
4408       D (emitcode (";", "cjneshort: generic ptr special case.");
4409         )
4410     }
4411
4412
4413   /* if the right side is a literal then anything goes */
4414   if (AOP_TYPE (right) == AOP_LIT &&
4415       AOP_TYPE (left) != AOP_DIR)
4416     {
4417       while (size--)
4418         {
4419           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4420           MOVA (l);
4421           emitcode ("cjne", "a,%s,%05d$",
4422                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4423                     lbl->key + 100);
4424           offset++;
4425         }
4426     }
4427
4428   /* if the right side is in a register or in direct space or
4429      if the left is a pointer register & right is not */
4430   else if (AOP_TYPE (right) == AOP_REG ||
4431            AOP_TYPE (right) == AOP_DIR ||
4432            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4433            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4434     {
4435       while (size--)
4436         {
4437           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4438           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4439               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4440             emitcode ("jnz", "%05d$", lbl->key + 100);
4441           else
4442             emitcode ("cjne", "a,%s,%05d$",
4443                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4444                       lbl->key + 100);
4445           offset++;
4446         }
4447     }
4448   else
4449     {
4450       /* right is a pointer reg need both a & b */
4451       while (size--)
4452         {
4453           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4454           if (strcmp (l, "b"))
4455             emitcode ("mov", "b,%s", l);
4456           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4457           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4458           offset++;
4459         }
4460     }
4461 }
4462
4463 /*-----------------------------------------------------------------*/
4464 /* gencjne - compare and jump if not equal                         */
4465 /*-----------------------------------------------------------------*/
4466 static void
4467 gencjne (operand * left, operand * right, symbol * lbl)
4468 {
4469   symbol *tlbl = newiTempLabel (NULL);
4470
4471   D (emitcode (";", "gencjne");
4472     );
4473
4474   gencjneshort (left, right, lbl);
4475
4476   emitcode ("mov", "a,%s", one);
4477   emitcode ("sjmp", "%05d$", tlbl->key + 100);
4478   emitcode ("", "%05d$:", lbl->key + 100);
4479   emitcode ("clr", "a");
4480   emitcode ("", "%05d$:", tlbl->key + 100);
4481 }
4482
4483 /*-----------------------------------------------------------------*/
4484 /* genCmpEq - generates code for equal to                          */
4485 /*-----------------------------------------------------------------*/
4486 static void
4487 genCmpEq (iCode * ic, iCode * ifx)
4488 {
4489   operand *left, *right, *result;
4490
4491   D (emitcode (";", "genCmpEq ");
4492     );
4493
4494   AOP_OP_2 (ic);
4495   AOP_SET_LOCALS (ic);
4496
4497   /* if literal, literal on the right or
4498      if the right is in a pointer register and left
4499      is not */
4500   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4501       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4502     {
4503       operand *t = IC_RIGHT (ic);
4504       IC_RIGHT (ic) = IC_LEFT (ic);
4505       IC_LEFT (ic) = t;
4506     }
4507
4508   if (ifx &&                    /* !AOP_SIZE(result) */
4509       OP_SYMBOL (result) &&
4510       OP_SYMBOL (result)->regType == REG_CND)
4511     {
4512       symbol *tlbl;
4513       /* if they are both bit variables */
4514       if (AOP_TYPE (left) == AOP_CRY &&
4515           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4516         {
4517           if (AOP_TYPE (right) == AOP_LIT)
4518             {
4519               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4520               if (lit == 0L)
4521                 {
4522                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4523                   emitcode ("cpl", "c");
4524                 }
4525               else if (lit == 1L)
4526                 {
4527                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4528                 }
4529               else
4530                 {
4531                   emitcode ("clr", "c");
4532                 }
4533               /* AOP_TYPE(right) == AOP_CRY */
4534             }
4535           else
4536             {
4537               symbol *lbl = newiTempLabel (NULL);
4538               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4539               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4540               emitcode ("cpl", "c");
4541               emitcode ("", "%05d$:", (lbl->key + 100));
4542             }
4543           /* if true label then we jump if condition
4544              supplied is true */
4545           tlbl = newiTempLabel (NULL);
4546           if (IC_TRUE (ifx))
4547             {
4548               emitcode ("jnc", "%05d$", tlbl->key + 100);
4549               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4550             }
4551           else
4552             {
4553               emitcode ("jc", "%05d$", tlbl->key + 100);
4554               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4555             }
4556           emitcode ("", "%05d$:", tlbl->key + 100);
4557         }
4558       else
4559         {
4560           tlbl = newiTempLabel (NULL);
4561           gencjneshort (left, right, tlbl);
4562           if (IC_TRUE (ifx))
4563             {
4564               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4565               emitcode ("", "%05d$:", tlbl->key + 100);
4566             }
4567           else
4568             {
4569               symbol *lbl = newiTempLabel (NULL);
4570               emitcode ("sjmp", "%05d$", lbl->key + 100);
4571               emitcode ("", "%05d$:", tlbl->key + 100);
4572               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4573               emitcode ("", "%05d$:", lbl->key + 100);
4574             }
4575         }
4576       /* mark the icode as generated */
4577       ifx->generated = 1;
4578
4579       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4580       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4581       return;
4582     }
4583
4584   /* if they are both bit variables */
4585   if (AOP_TYPE (left) == AOP_CRY &&
4586       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4587     {
4588       if (AOP_TYPE (right) == AOP_LIT)
4589         {
4590           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4591           if (lit == 0L)
4592             {
4593               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4594               emitcode ("cpl", "c");
4595             }
4596           else if (lit == 1L)
4597             {
4598               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4599             }
4600           else
4601             {
4602               emitcode ("clr", "c");
4603             }
4604           /* AOP_TYPE(right) == AOP_CRY */
4605         }
4606       else
4607         {
4608           symbol *lbl = newiTempLabel (NULL);
4609           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4610           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4611           emitcode ("cpl", "c");
4612           emitcode ("", "%05d$:", (lbl->key + 100));
4613         }
4614
4615       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4616       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4617
4618       aopOp (result, ic, TRUE, FALSE);
4619
4620       /* c = 1 if egal */
4621       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4622         {
4623           outBitC (result);
4624           goto release;
4625         }
4626       if (ifx)
4627         {
4628           genIfxJump (ifx, "c");
4629           goto release;
4630         }
4631       /* if the result is used in an arithmetic operation
4632          then put the result in place */
4633       outBitC (result);
4634     }
4635   else
4636     {
4637       gencjne (left, right, newiTempLabel (NULL));
4638
4639       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4640       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4641
4642       aopOp (result, ic, TRUE, FALSE);
4643
4644       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4645         {
4646           aopPut (AOP (result), "a", 0);
4647           goto release;
4648         }
4649       if (ifx)
4650         {
4651           genIfxJump (ifx, "a");
4652           goto release;
4653         }
4654       /* if the result is used in an arithmetic operation
4655          then put the result in place */
4656       if (AOP_TYPE (result) != AOP_CRY)
4657         outAcc (result);
4658       /* leave the result in acc */
4659     }
4660
4661 release:
4662   freeAsmop (result, NULL, ic, TRUE);
4663 }
4664
4665 /*-----------------------------------------------------------------*/
4666 /* ifxForOp - returns the icode containing the ifx for operand     */
4667 /*-----------------------------------------------------------------*/
4668 static iCode *
4669 ifxForOp (operand * op, iCode * ic)
4670 {
4671   /* if true symbol then needs to be assigned */
4672   if (IS_TRUE_SYMOP (op))
4673     return NULL;
4674
4675   /* if this has register type condition and
4676      the next instruction is ifx with the same operand
4677      and live to of the operand is upto the ifx only then */
4678   if (ic->next &&
4679       ic->next->op == IFX &&
4680       IC_COND (ic->next)->key == op->key &&
4681       OP_SYMBOL (op)->liveTo <= ic->next->seq)
4682     return ic->next;
4683
4684   return NULL;
4685 }
4686 /*-----------------------------------------------------------------*/
4687 /* genAndOp - for && operation                                     */
4688 /*-----------------------------------------------------------------*/
4689 static void
4690 genAndOp (iCode * ic)
4691 {
4692   operand *left, *right, *result;
4693   symbol *tlbl;
4694
4695   D (emitcode (";", "genAndOp "););
4696
4697   /* note here that && operations that are in an
4698      if statement are taken away by backPatchLabels
4699      only those used in arthmetic operations remain */
4700   AOP_OP_2 (ic);
4701   AOP_SET_LOCALS (ic);
4702
4703   /* if both are bit variables */
4704   if (AOP_TYPE (left) == AOP_CRY &&
4705       AOP_TYPE (right) == AOP_CRY)
4706     {
4707       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4708       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4709       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4710       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4711   
4712       aopOp (result,ic,FALSE, FALSE);
4713       outBitC (result);
4714     }
4715   else
4716     {
4717       tlbl = newiTempLabel (NULL);
4718       toBoolean (left);
4719       emitcode ("jz", "%05d$", tlbl->key + 100);
4720       toBoolean (right);
4721       emitcode ("", "%05d$:", tlbl->key + 100);
4722       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4723       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4724   
4725       aopOp (result,ic,FALSE, FALSE);
4726       outBitAcc (result);
4727     }
4728     freeAsmop (result, NULL, ic, TRUE);
4729 }
4730
4731
4732 /*-----------------------------------------------------------------*/
4733 /* genOrOp - for || operation                                      */
4734 /*-----------------------------------------------------------------*/
4735 static void
4736 genOrOp (iCode * ic)
4737 {
4738   operand *left, *right, *result;
4739   symbol *tlbl;
4740
4741   D (emitcode (";", "genOrOp "););
4742
4743   /* note here that || operations that are in an
4744      if statement are taken away by backPatchLabels
4745      only those used in arthmetic operations remain */
4746   AOP_OP_2 (ic);
4747   AOP_SET_LOCALS (ic);
4748
4749   /* if both are bit variables */
4750   if (AOP_TYPE (left) == AOP_CRY &&
4751       AOP_TYPE (right) == AOP_CRY)
4752     {
4753       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4754       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4755       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4756       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4757   
4758       aopOp (result,ic,FALSE, FALSE);
4759       
4760       outBitC (result);
4761     }
4762   else
4763     {
4764       tlbl = newiTempLabel (NULL);
4765       toBoolean (left);
4766       emitcode ("jnz", "%05d$", tlbl->key + 100);
4767       toBoolean (right);
4768       emitcode ("", "%05d$:", tlbl->key + 100);
4769       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4770       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4771   
4772       aopOp (result,ic,FALSE, FALSE);
4773       
4774       outBitAcc (result);
4775     }
4776
4777   freeAsmop (result, NULL, ic, TRUE);
4778 }
4779
4780 /*-----------------------------------------------------------------*/
4781 /* isLiteralBit - test if lit == 2^n                               */
4782 /*-----------------------------------------------------------------*/
4783 static int
4784 isLiteralBit (unsigned long lit)
4785 {
4786   unsigned long pw[32] =
4787   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4788    0x100L, 0x200L, 0x400L, 0x800L,
4789    0x1000L, 0x2000L, 0x4000L, 0x8000L,
4790    0x10000L, 0x20000L, 0x40000L, 0x80000L,
4791    0x100000L, 0x200000L, 0x400000L, 0x800000L,
4792    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4793    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4794   int idx;
4795
4796   for (idx = 0; idx < 32; idx++)
4797     if (lit == pw[idx])
4798       return idx + 1;
4799   return 0;
4800 }
4801
4802 /*-----------------------------------------------------------------*/
4803 /* continueIfTrue -                                                */
4804 /*-----------------------------------------------------------------*/
4805 static void
4806 continueIfTrue (iCode * ic)
4807 {
4808   if (IC_TRUE (ic))
4809     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4810   ic->generated = 1;
4811 }
4812
4813 /*-----------------------------------------------------------------*/
4814 /* jmpIfTrue -                                                     */
4815 /*-----------------------------------------------------------------*/
4816 static void
4817 jumpIfTrue (iCode * ic)
4818 {
4819   if (!IC_TRUE (ic))
4820     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4821   ic->generated = 1;
4822 }
4823
4824 /*-----------------------------------------------------------------*/
4825 /* jmpTrueOrFalse -                                                */
4826 /*-----------------------------------------------------------------*/
4827 static void
4828 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4829 {
4830   // ugly but optimized by peephole
4831   if (IC_TRUE (ic))
4832     {
4833       symbol *nlbl = newiTempLabel (NULL);
4834       emitcode ("sjmp", "%05d$", nlbl->key + 100);
4835       emitcode ("", "%05d$:", tlbl->key + 100);
4836       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4837       emitcode ("", "%05d$:", nlbl->key + 100);
4838     }
4839   else
4840     {
4841       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4842       emitcode ("", "%05d$:", tlbl->key + 100);
4843     }
4844   ic->generated = 1;
4845 }
4846
4847 // Generate code to perform a bit-wise logic operation
4848 // on two operands in far space (assumed to already have been 
4849 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
4850 // in far space. This requires pushing the result on the stack
4851 // then popping it into the result.
4852 static void
4853 genFarFarLogicOp(iCode *ic, char *logicOp)
4854 {
4855       int size, resultSize, compSize;
4856       int offset = 0;
4857       
4858       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
4859       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
4860                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
4861       
4862       _startLazyDPSEvaluation();
4863       for (size = compSize; (size--); offset++)
4864       {
4865           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
4866           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
4867           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
4868           
4869           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
4870           emitcode ("push", "acc");
4871       }
4872       _endLazyDPSEvaluation();
4873      
4874       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4875       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4876       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
4877      
4878       resultSize = AOP_SIZE(IC_RESULT(ic));
4879
4880       ADJUST_PUSHED_RESULT(compSize, resultSize);
4881
4882       _startLazyDPSEvaluation();
4883       while (compSize--)
4884       {
4885           emitcode ("pop", "acc");
4886           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
4887       }
4888       _endLazyDPSEvaluation();
4889       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
4890 }
4891
4892
4893 /*-----------------------------------------------------------------*/
4894 /* genAnd  - code for and                                          */
4895 /*-----------------------------------------------------------------*/
4896 static void
4897 genAnd (iCode * ic, iCode * ifx)
4898 {
4899   operand *left, *right, *result;
4900   int size, offset = 0;
4901   unsigned long lit = 0L;
4902   int bytelit = 0;
4903   char buffer[10];
4904   bool pushResult;
4905
4906   D (emitcode (";", "genAnd "););
4907
4908   AOP_OP_3_NOFATAL (ic, pushResult);
4909   AOP_SET_LOCALS (ic);
4910
4911   if (pushResult)
4912   {
4913       genFarFarLogicOp(ic, "anl");
4914       return;
4915   }  
4916
4917 #ifdef DEBUG_TYPE
4918   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4919             AOP_TYPE (result),
4920             AOP_TYPE (left), AOP_TYPE (right));
4921   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4922             AOP_SIZE (result),
4923             AOP_SIZE (left), AOP_SIZE (right));
4924 #endif
4925
4926   /* if left is a literal & right is not then exchange them */
4927   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4928       AOP_NEEDSACC (left))
4929     {
4930       operand *tmp = right;
4931       right = left;
4932       left = tmp;
4933     }
4934
4935   /* if result = right then exchange them */
4936   if (sameRegs (AOP (result), AOP (right)))
4937     {
4938       operand *tmp = right;
4939       right = left;
4940       left = tmp;
4941     }
4942
4943   /* if right is bit then exchange them */
4944   if (AOP_TYPE (right) == AOP_CRY &&
4945       AOP_TYPE (left) != AOP_CRY)
4946     {
4947       operand *tmp = right;
4948       right = left;
4949       left = tmp;
4950     }
4951   if (AOP_TYPE (right) == AOP_LIT)
4952     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4953
4954   size = AOP_SIZE (result);
4955
4956   // if(bit & yy)
4957   // result = bit & yy;
4958   if (AOP_TYPE (left) == AOP_CRY)
4959     {
4960       // c = bit & literal;
4961       if (AOP_TYPE (right) == AOP_LIT)
4962         {
4963           if (lit & 1)
4964             {
4965               if (size && sameRegs (AOP (result), AOP (left)))
4966                 // no change
4967                 goto release;
4968               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4969             }
4970           else
4971             {
4972               // bit(result) = 0;
4973               if (size && (AOP_TYPE (result) == AOP_CRY))
4974                 {
4975                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4976                   goto release;
4977                 }
4978               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4979                 {
4980                   jumpIfTrue (ifx);
4981                   goto release;
4982                 }
4983               emitcode ("clr", "c");
4984             }
4985         }
4986       else
4987         {
4988           if (AOP_TYPE (right) == AOP_CRY)
4989             {
4990               // c = bit & bit;
4991               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4992               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4993             }
4994           else
4995             {
4996               // c = bit & val;
4997               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4998               // c = lsb
4999               emitcode ("rrc", "a");
5000               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5001             }
5002         }
5003       // bit = c
5004       // val = c
5005       if (size)
5006         outBitC (result);
5007       // if(bit & ...)
5008       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5009         genIfxJump (ifx, "c");
5010       goto release;
5011     }
5012
5013   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5014   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5015   if ((AOP_TYPE (right) == AOP_LIT) &&
5016       (AOP_TYPE (result) == AOP_CRY) &&
5017       (AOP_TYPE (left) != AOP_CRY))
5018     {
5019       int posbit = isLiteralBit (lit);
5020       /* left &  2^n */
5021       if (posbit)
5022         {
5023           posbit--;
5024           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5025           // bit = left & 2^n
5026           if (size)
5027             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5028           // if(left &  2^n)
5029           else
5030             {
5031               if (ifx)
5032                 {
5033                   sprintf (buffer, "acc.%d", posbit & 0x07);
5034                   genIfxJump (ifx, buffer);
5035                 }
5036               goto release;
5037             }
5038         }
5039       else
5040         {
5041           symbol *tlbl = newiTempLabel (NULL);
5042           int sizel = AOP_SIZE (left);
5043           if (size)
5044             emitcode ("setb", "c");
5045           while (sizel--)
5046             {
5047               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5048                 {
5049                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5050                   // byte ==  2^n ?
5051                   if ((posbit = isLiteralBit (bytelit)) != 0)
5052                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5053                   else
5054                     {
5055                       if (bytelit != 0x0FFL)
5056                         emitcode ("anl", "a,%s",
5057                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5058                       emitcode ("jnz", "%05d$", tlbl->key + 100);
5059                     }
5060                 }
5061               offset++;
5062             }
5063           // bit = left & literal
5064           if (size)
5065             {
5066               emitcode ("clr", "c");
5067               emitcode ("", "%05d$:", tlbl->key + 100);
5068             }
5069           // if(left & literal)
5070           else
5071             {
5072               if (ifx)
5073                 jmpTrueOrFalse (ifx, tlbl);
5074               goto release;
5075             }
5076         }
5077       outBitC (result);
5078       goto release;
5079     }
5080
5081   /* if left is same as result */
5082   if (sameRegs (AOP (result), AOP (left)))
5083     {
5084       for (; size--; offset++)
5085         {
5086           if (AOP_TYPE (right) == AOP_LIT)
5087             {
5088               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5089                 continue;
5090               else if (bytelit == 0)
5091                 aopPut (AOP (result), zero, offset);
5092               else if (IS_AOP_PREG (result))
5093                 {
5094                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5095                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5096                   aopPut (AOP (result), "a", offset);
5097                 }
5098               else
5099                 emitcode ("anl", "%s,%s",
5100                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5101                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5102             }
5103           else
5104             {
5105               if (AOP_TYPE (left) == AOP_ACC)
5106                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5107               else
5108                 {
5109                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5110                   if (IS_AOP_PREG (result))
5111                     {
5112                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5113                       aopPut (AOP (result), "a", offset);
5114
5115                     }
5116                   else
5117                     emitcode ("anl", "%s,a",
5118                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5119                 }
5120             }
5121         }
5122     }
5123   else
5124     {
5125       // left & result in different registers
5126       if (AOP_TYPE (result) == AOP_CRY)
5127         {
5128           // result = bit
5129           // if(size), result in bit
5130           // if(!size && ifx), conditional oper: if(left & right)
5131           symbol *tlbl = newiTempLabel (NULL);
5132           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5133           if (size)
5134             emitcode ("setb", "c");
5135           while (sizer--)
5136             {
5137               MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5138               emitcode ("anl", "a,%s",
5139                         aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5140               emitcode ("jnz", "%05d$", tlbl->key + 100);
5141               offset++;
5142             }
5143           if (size)
5144             {
5145               CLRC;
5146               emitcode ("", "%05d$:", tlbl->key + 100);
5147               outBitC (result);
5148             }
5149           else if (ifx)
5150             jmpTrueOrFalse (ifx, tlbl);
5151         }
5152       else
5153         {
5154           for (; (size--); offset++)
5155             {
5156               // normal case
5157               // result = left & right
5158               if (AOP_TYPE (right) == AOP_LIT)
5159                 {
5160                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5161                     {
5162                       aopPut (AOP (result),
5163                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5164                               offset);
5165                       continue;
5166                     }
5167                   else if (bytelit == 0)
5168                     {
5169                       aopPut (AOP (result), zero, offset);
5170                       continue;
5171                     }
5172                   D (emitcode (";", "better literal AND.");
5173                     );
5174                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5175                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5176                                                     FALSE, FALSE, FALSE));
5177
5178                 }
5179               else
5180                 {
5181                   // faster than result <- left, anl result,right
5182                   // and better if result is SFR
5183                   if (AOP_TYPE (left) == AOP_ACC)
5184                     {
5185                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5186                                                        FALSE, FALSE, FALSE));
5187                     }
5188                   else
5189                     {
5190                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5191                       emitcode ("anl", "a,%s",
5192                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5193                     }
5194                 }
5195               aopPut (AOP (result), "a", offset);
5196             }
5197         }
5198     }
5199
5200 release:
5201   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5202   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5203   freeAsmop (result, NULL, ic, TRUE);
5204 }
5205
5206
5207 /*-----------------------------------------------------------------*/
5208 /* genOr  - code for or                                            */
5209 /*-----------------------------------------------------------------*/
5210 static void
5211 genOr (iCode * ic, iCode * ifx)
5212 {
5213   operand *left, *right, *result;
5214   int size, offset = 0;
5215   unsigned long lit = 0L;
5216   bool     pushResult;
5217
5218   D (emitcode (";", "genOr "););
5219
5220   AOP_OP_3_NOFATAL (ic, pushResult);
5221   AOP_SET_LOCALS (ic);
5222
5223   if (pushResult)
5224   {
5225       genFarFarLogicOp(ic, "orl");
5226       return;
5227   }
5228
5229
5230 #ifdef DEBUG_TYPE
5231   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5232             AOP_TYPE (result),
5233             AOP_TYPE (left), AOP_TYPE (right));
5234   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5235             AOP_SIZE (result),
5236             AOP_SIZE (left), AOP_SIZE (right));
5237 #endif
5238
5239   /* if left is a literal & right is not then exchange them */
5240   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5241       AOP_NEEDSACC (left))
5242     {
5243       operand *tmp = right;
5244       right = left;
5245       left = tmp;
5246     }
5247
5248   /* if result = right then exchange them */
5249   if (sameRegs (AOP (result), AOP (right)))
5250     {
5251       operand *tmp = right;
5252       right = left;
5253       left = tmp;
5254     }
5255
5256   /* if right is bit then exchange them */
5257   if (AOP_TYPE (right) == AOP_CRY &&
5258       AOP_TYPE (left) != AOP_CRY)
5259     {
5260       operand *tmp = right;
5261       right = left;
5262       left = tmp;
5263     }
5264   if (AOP_TYPE (right) == AOP_LIT)
5265     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5266
5267   size = AOP_SIZE (result);
5268
5269   // if(bit | yy)
5270   // xx = bit | yy;
5271   if (AOP_TYPE (left) == AOP_CRY)
5272     {
5273       if (AOP_TYPE (right) == AOP_LIT)
5274         {
5275           // c = bit & literal;
5276           if (lit)
5277             {
5278               // lit != 0 => result = 1
5279               if (AOP_TYPE (result) == AOP_CRY)
5280                 {
5281                   if (size)
5282                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5283                   else if (ifx)
5284                     continueIfTrue (ifx);
5285                   goto release;
5286                 }
5287               emitcode ("setb", "c");
5288             }
5289           else
5290             {
5291               // lit == 0 => result = left
5292               if (size && sameRegs (AOP (result), AOP (left)))
5293                 goto release;
5294               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5295             }
5296         }
5297       else
5298         {
5299           if (AOP_TYPE (right) == AOP_CRY)
5300             {
5301               // c = bit | bit;
5302               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5303               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5304             }
5305           else
5306             {
5307               // c = bit | val;
5308               symbol *tlbl = newiTempLabel (NULL);
5309               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5310                 emitcode ("setb", "c");
5311               emitcode ("jb", "%s,%05d$",
5312                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
5313               toBoolean (right);
5314               emitcode ("jnz", "%05d$", tlbl->key + 100);
5315               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5316                 {
5317                   jmpTrueOrFalse (ifx, tlbl);
5318                   goto release;
5319                 }
5320               else
5321                 {
5322                   CLRC;
5323                   emitcode ("", "%05d$:", tlbl->key + 100);
5324                 }
5325             }
5326         }
5327       // bit = c
5328       // val = c
5329       if (size)
5330         outBitC (result);
5331       // if(bit | ...)
5332       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5333         genIfxJump (ifx, "c");
5334       goto release;
5335     }
5336
5337   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5338   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5339   if ((AOP_TYPE (right) == AOP_LIT) &&
5340       (AOP_TYPE (result) == AOP_CRY) &&
5341       (AOP_TYPE (left) != AOP_CRY))
5342     {
5343       if (lit)
5344         {
5345           // result = 1
5346           if (size)
5347             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5348           else
5349             continueIfTrue (ifx);
5350           goto release;
5351         }
5352       else
5353         {
5354           // lit = 0, result = boolean(left)
5355           if (size)
5356             emitcode ("setb", "c");
5357           toBoolean (right);
5358           if (size)
5359             {
5360               symbol *tlbl = newiTempLabel (NULL);
5361               emitcode ("jnz", "%05d$", tlbl->key + 100);
5362               CLRC;
5363               emitcode ("", "%05d$:", tlbl->key + 100);
5364             }
5365           else
5366             {
5367               genIfxJump (ifx, "a");
5368               goto release;
5369             }
5370         }
5371       outBitC (result);
5372       goto release;
5373     }
5374
5375   /* if left is same as result */
5376   if (sameRegs (AOP (result), AOP (left)))
5377     {
5378       for (; size--; offset++)
5379         {
5380           if (AOP_TYPE (right) == AOP_LIT)
5381             {
5382               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5383                 {
5384                   continue;
5385                 }
5386               else
5387                 {
5388                   if (IS_AOP_PREG (left))
5389                     {
5390                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5391                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5392                       aopPut (AOP (result), "a", offset);
5393                     }
5394                   else
5395                     {
5396                       emitcode ("orl", "%s,%s",
5397                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5398                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5399                     }
5400                 }
5401             }
5402           else
5403             {
5404               if (AOP_TYPE (left) == AOP_ACC)
5405                 {
5406                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5407                 }
5408               else
5409                 {
5410                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5411                   if (IS_AOP_PREG (left))
5412                     {
5413                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5414                       aopPut (AOP (result), "a", offset);
5415                     }
5416                   else
5417                     {
5418                       emitcode ("orl", "%s,a",
5419                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5420                     }
5421                 }
5422             }
5423         }
5424     }
5425   else
5426     {
5427       // left & result in different registers
5428       if (AOP_TYPE (result) == AOP_CRY)
5429         {
5430           // result = bit
5431           // if(size), result in bit
5432           // if(!size && ifx), conditional oper: if(left | right)
5433           symbol *tlbl = newiTempLabel (NULL);
5434           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5435           if (size)
5436             emitcode ("setb", "c");
5437           while (sizer--)
5438             {
5439               MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5440               emitcode ("orl", "a,%s",
5441                         aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5442               emitcode ("jnz", "%05d$", tlbl->key + 100);
5443               offset++;
5444             }
5445           if (size)
5446             {
5447               CLRC;
5448               emitcode ("", "%05d$:", tlbl->key + 100);
5449               outBitC (result);
5450             }
5451           else if (ifx)
5452             jmpTrueOrFalse (ifx, tlbl);
5453         }
5454       else
5455         {
5456           for (; (size--); offset++)
5457             {
5458               // normal case
5459               // result = left & right
5460               if (AOP_TYPE (right) == AOP_LIT)
5461                 {
5462                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5463                     {
5464                       aopPut (AOP (result),
5465                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5466                               offset);
5467                       continue;
5468                     }
5469                   D (emitcode (";", "better literal OR.");
5470                     );
5471                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5472                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5473                                                     FALSE, FALSE, FALSE));
5474
5475                 }
5476               else
5477                 {
5478                   // faster than result <- left, anl result,right
5479                   // and better if result is SFR
5480                   if (AOP_TYPE (left) == AOP_ACC)
5481                     {
5482                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5483                                                        FALSE, FALSE, FALSE));
5484                     }
5485                   else
5486                     {
5487                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5488                       emitcode ("orl", "a,%s",
5489                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5490                     }
5491                 }
5492               aopPut (AOP (result), "a", offset);
5493             }
5494         }
5495     }
5496
5497 release:
5498   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5499   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5500   freeAsmop (result, NULL, ic, TRUE);
5501 }
5502
5503 /*-----------------------------------------------------------------*/
5504 /* genXor - code for xclusive or                                   */
5505 /*-----------------------------------------------------------------*/
5506 static void
5507 genXor (iCode * ic, iCode * ifx)
5508 {
5509   operand *left, *right, *result;
5510   int size, offset = 0;
5511   unsigned long lit = 0L;
5512   bool pushResult;
5513
5514   D (emitcode (";", "genXor "););
5515
5516   AOP_OP_3_NOFATAL (ic, pushResult);
5517   AOP_SET_LOCALS (ic);
5518
5519   if (pushResult)
5520   {
5521       genFarFarLogicOp(ic, "xrl");
5522       return;
5523   }  
5524
5525 #ifdef DEBUG_TYPE
5526   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5527             AOP_TYPE (result),
5528             AOP_TYPE (left), AOP_TYPE (right));
5529   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5530             AOP_SIZE (result),
5531             AOP_SIZE (left), AOP_SIZE (right));
5532 #endif
5533
5534   /* if left is a literal & right is not ||
5535      if left needs acc & right does not */
5536   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5537       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5538     {
5539       operand *tmp = right;
5540       right = left;
5541       left = tmp;
5542     }
5543
5544   /* if result = right then exchange them */
5545   if (sameRegs (AOP (result), AOP (right)))
5546     {
5547       operand *tmp = right;
5548       right = left;
5549       left = tmp;
5550     }
5551
5552   /* if right is bit then exchange them */
5553   if (AOP_TYPE (right) == AOP_CRY &&
5554       AOP_TYPE (left) != AOP_CRY)
5555     {
5556       operand *tmp = right;
5557       right = left;
5558       left = tmp;
5559     }
5560   if (AOP_TYPE (right) == AOP_LIT)
5561     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5562
5563   size = AOP_SIZE (result);
5564
5565   // if(bit ^ yy)
5566   // xx = bit ^ yy;
5567   if (AOP_TYPE (left) == AOP_CRY)
5568     {
5569       if (AOP_TYPE (right) == AOP_LIT)
5570         {
5571           // c = bit & literal;
5572           if (lit >> 1)
5573             {
5574               // lit>>1  != 0 => result = 1
5575               if (AOP_TYPE (result) == AOP_CRY)
5576                 {
5577                   if (size)
5578                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5579                   else if (ifx)
5580                     continueIfTrue (ifx);
5581                   goto release;
5582                 }
5583               emitcode ("setb", "c");
5584             }
5585           else
5586             {
5587               // lit == (0 or 1)
5588               if (lit == 0)
5589                 {
5590                   // lit == 0, result = left
5591                   if (size && sameRegs (AOP (result), AOP (left)))
5592                     goto release;
5593                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5594                 }
5595               else
5596                 {
5597                   // lit == 1, result = not(left)
5598                   if (size && sameRegs (AOP (result), AOP (left)))
5599                     {
5600                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5601                       goto release;
5602                     }
5603                   else
5604                     {
5605                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5606                       emitcode ("cpl", "c");
5607                     }
5608                 }
5609             }
5610
5611         }
5612       else
5613         {
5614           // right != literal
5615           symbol *tlbl = newiTempLabel (NULL);
5616           if (AOP_TYPE (right) == AOP_CRY)
5617             {
5618               // c = bit ^ bit;
5619               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5620             }
5621           else
5622             {
5623               int sizer = AOP_SIZE (right);
5624               // c = bit ^ val
5625               // if val>>1 != 0, result = 1
5626               emitcode ("setb", "c");
5627               while (sizer)
5628                 {
5629                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5630                   if (sizer == 1)
5631                     // test the msb of the lsb
5632                     emitcode ("anl", "a,#0xfe");
5633                   emitcode ("jnz", "%05d$", tlbl->key + 100);
5634                   sizer--;
5635                 }
5636               // val = (0,1)
5637               emitcode ("rrc", "a");
5638             }
5639           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5640           emitcode ("cpl", "c");
5641           emitcode ("", "%05d$:", (tlbl->key + 100));
5642         }
5643       // bit = c
5644       // val = c
5645       if (size)
5646         outBitC (result);
5647       // if(bit | ...)
5648       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5649         genIfxJump (ifx, "c");
5650       goto release;
5651     }
5652
5653   if (sameRegs (AOP (result), AOP (left)))
5654     {
5655       /* if left is same as result */
5656       for (; size--; offset++)
5657         {
5658           if (AOP_TYPE (right) == AOP_LIT)
5659             {
5660               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5661                 continue;
5662               else if (IS_AOP_PREG (left))
5663                 {
5664                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5665                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5666                   aopPut (AOP (result), "a", offset);
5667                 }
5668               else
5669                 emitcode ("xrl", "%s,%s",
5670                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5671                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5672             }
5673           else
5674             {
5675               if (AOP_TYPE (left) == AOP_ACC)
5676                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5677               else
5678                 {
5679                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5680                   if (IS_AOP_PREG (left))
5681                     {
5682                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5683                       aopPut (AOP (result), "a", offset);
5684                     }
5685                   else
5686                     emitcode ("xrl", "%s,a",
5687                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5688                 }
5689             }
5690         }
5691     }
5692   else
5693     {
5694       // left & result in different registers
5695       if (AOP_TYPE (result) == AOP_CRY)
5696         {
5697           // result = bit
5698           // if(size), result in bit
5699           // if(!size && ifx), conditional oper: if(left ^ right)
5700           symbol *tlbl = newiTempLabel (NULL);
5701           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5702           if (size)
5703             emitcode ("setb", "c");
5704           while (sizer--)
5705             {
5706               if ((AOP_TYPE (right) == AOP_LIT) &&
5707                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5708                 {
5709                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5710                 }
5711               else
5712                 {
5713                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5714                   emitcode ("xrl", "a,%s",
5715                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5716                 }
5717               emitcode ("jnz", "%05d$", tlbl->key + 100);
5718               offset++;
5719             }
5720           if (size)
5721             {
5722               CLRC;
5723               emitcode ("", "%05d$:", tlbl->key + 100);
5724               outBitC (result);
5725             }
5726           else if (ifx)
5727             jmpTrueOrFalse (ifx, tlbl);
5728         }
5729       else
5730         for (; (size--); offset++)
5731           {
5732             // normal case
5733             // result = left & right
5734             if (AOP_TYPE (right) == AOP_LIT)
5735               {
5736                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5737                   {
5738                     aopPut (AOP (result),
5739                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5740                             offset);
5741                     continue;
5742                   }
5743                 D (emitcode (";", "better literal XOR.");
5744                   );
5745                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5746                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5747                                                   FALSE, FALSE, FALSE));
5748               }
5749             else
5750               {
5751                 // faster than result <- left, anl result,right
5752                 // and better if result is SFR
5753                 if (AOP_TYPE (left) == AOP_ACC)
5754                   {
5755                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5756                                                      FALSE, FALSE, FALSE));
5757                   }
5758                 else
5759                   {
5760                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5761                     emitcode ("xrl", "a,%s",
5762                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5763                   }
5764               }
5765             aopPut (AOP (result), "a", offset);
5766           }
5767     }
5768
5769 release:
5770   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5771   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5772   freeAsmop (result, NULL, ic, TRUE);
5773 }
5774
5775 /*-----------------------------------------------------------------*/
5776 /* genInline - write the inline code out                           */
5777 /*-----------------------------------------------------------------*/
5778 static void
5779 genInline (iCode * ic)
5780 {
5781   char buffer[MAX_INLINEASM];
5782   char *bp = buffer;
5783   char *bp1 = buffer;
5784
5785   D (emitcode (";", "genInline ");
5786     );
5787
5788   _G.inLine += (!options.asmpeep);
5789   strcpy (buffer, IC_INLINE (ic));
5790
5791   /* emit each line as a code */
5792   while (*bp)
5793     {
5794       if (*bp == '\n')
5795         {
5796           *bp++ = '\0';
5797           emitcode (bp1, "");
5798           bp1 = bp;
5799         }
5800       else
5801         {
5802           if (*bp == ':')
5803             {
5804               bp++;
5805               *bp = '\0';
5806               bp++;
5807               emitcode (bp1, "");
5808               bp1 = bp;
5809             }
5810           else
5811             bp++;
5812         }
5813     }
5814   if (bp1 != bp)
5815     emitcode (bp1, "");
5816   /*     emitcode("",buffer); */
5817   _G.inLine -= (!options.asmpeep);
5818 }
5819
5820 /*-----------------------------------------------------------------*/
5821 /* genRRC - rotate right with carry                                */
5822 /*-----------------------------------------------------------------*/
5823 static void
5824 genRRC (iCode * ic)
5825 {
5826   operand *left, *result;
5827   int size, offset = 0;
5828   char *l;
5829
5830   D (emitcode (";", "genRRC ");
5831     );
5832
5833   /* rotate right with carry */
5834   left = IC_LEFT (ic);
5835   result = IC_RESULT (ic);
5836   aopOp (left, ic, FALSE, FALSE);
5837   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5838
5839   /* move it to the result */
5840   size = AOP_SIZE (result);
5841   offset = size - 1;
5842   CLRC;
5843
5844   _startLazyDPSEvaluation ();
5845   while (size--)
5846     {
5847       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5848       MOVA (l);
5849       emitcode ("rrc", "a");
5850       if (AOP_SIZE (result) > 1)
5851         aopPut (AOP (result), "a", offset--);
5852     }
5853   _endLazyDPSEvaluation ();
5854
5855   /* now we need to put the carry into the
5856      highest order byte of the result */
5857   if (AOP_SIZE (result) > 1)
5858     {
5859       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5860       MOVA (l);
5861     }
5862   emitcode ("mov", "acc.7,c");
5863   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5864   freeAsmop (left, NULL, ic, TRUE);
5865   freeAsmop (result, NULL, ic, TRUE);
5866 }
5867
5868 /*-----------------------------------------------------------------*/
5869 /* genRLC - generate code for rotate left with carry               */
5870 /*-----------------------------------------------------------------*/
5871 static void
5872 genRLC (iCode * ic)
5873 {
5874   operand *left, *result;
5875   int size, offset = 0;
5876   char *l;
5877
5878   D (emitcode (";", "genRLC ");
5879     );
5880
5881   /* rotate right with carry */
5882   left = IC_LEFT (ic);
5883   result = IC_RESULT (ic);
5884   aopOp (left, ic, FALSE, FALSE);
5885   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5886
5887   /* move it to the result */
5888   size = AOP_SIZE (result);
5889   offset = 0;
5890   if (size--)
5891     {
5892       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5893       MOVA (l);
5894       emitcode ("add", "a,acc");
5895       if (AOP_SIZE (result) > 1)
5896         {
5897           aopPut (AOP (result), "a", offset++);
5898         }
5899
5900       _startLazyDPSEvaluation ();
5901       while (size--)
5902         {
5903           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5904           MOVA (l);
5905           emitcode ("rlc", "a");
5906           if (AOP_SIZE (result) > 1)
5907             aopPut (AOP (result), "a", offset++);
5908         }
5909       _endLazyDPSEvaluation ();
5910     }
5911   /* now we need to put the carry into the
5912      highest order byte of the result */
5913   if (AOP_SIZE (result) > 1)
5914     {
5915       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5916       MOVA (l);
5917     }
5918   emitcode ("mov", "acc.0,c");
5919   aopPut (AOP (result), "a", 0);
5920   freeAsmop (left, NULL, ic, TRUE);
5921   freeAsmop (result, NULL, ic, TRUE);
5922 }
5923
5924 /*-----------------------------------------------------------------*/
5925 /* genGetHbit - generates code get highest order bit               */
5926 /*-----------------------------------------------------------------*/
5927 static void
5928 genGetHbit (iCode * ic)
5929 {
5930   operand *left, *result;
5931   left = IC_LEFT (ic);
5932   result = IC_RESULT (ic);
5933   aopOp (left, ic, FALSE, FALSE);
5934   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5935
5936   D (emitcode (";", "genGetHbit ");
5937     );
5938
5939   /* get the highest order byte into a */
5940   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5941   if (AOP_TYPE (result) == AOP_CRY)
5942     {
5943       emitcode ("rlc", "a");
5944       outBitC (result);
5945     }
5946   else
5947     {
5948       emitcode ("rl", "a");
5949       emitcode ("anl", "a,#0x01");
5950       outAcc (result);
5951     }
5952
5953
5954   freeAsmop (left, NULL, ic, TRUE);
5955   freeAsmop (result, NULL, ic, TRUE);
5956 }
5957
5958 /*-----------------------------------------------------------------*/
5959 /* AccRol - rotate left accumulator by known count                 */
5960 /*-----------------------------------------------------------------*/
5961 static void
5962 AccRol (int shCount)
5963 {
5964   shCount &= 0x0007;            // shCount : 0..7
5965
5966   switch (shCount)
5967     {
5968     case 0:
5969       break;
5970     case 1:
5971       emitcode ("rl", "a");
5972       break;
5973     case 2:
5974       emitcode ("rl", "a");
5975       emitcode ("rl", "a");
5976       break;
5977     case 3:
5978       emitcode ("swap", "a");
5979       emitcode ("rr", "a");
5980       break;
5981     case 4:
5982       emitcode ("swap", "a");
5983       break;
5984     case 5:
5985       emitcode ("swap", "a");
5986       emitcode ("rl", "a");
5987       break;
5988     case 6:
5989       emitcode ("rr", "a");
5990       emitcode ("rr", "a");
5991       break;
5992     case 7:
5993       emitcode ("rr", "a");
5994       break;
5995     }
5996 }
5997
5998 /*-----------------------------------------------------------------*/
5999 /* AccLsh - left shift accumulator by known count                  */
6000 /*-----------------------------------------------------------------*/
6001 static void
6002 AccLsh (int shCount)
6003 {
6004   if (shCount != 0)
6005     {
6006       if (shCount == 1)
6007         emitcode ("add", "a,acc");
6008       else if (shCount == 2)
6009         {
6010           emitcode ("add", "a,acc");
6011           emitcode ("add", "a,acc");
6012         }
6013       else
6014         {
6015           /* rotate left accumulator */
6016           AccRol (shCount);
6017           /* and kill the lower order bits */
6018           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6019         }
6020     }
6021 }
6022
6023 /*-----------------------------------------------------------------*/
6024 /* AccRsh - right shift accumulator by known count                 */
6025 /*-----------------------------------------------------------------*/
6026 static void
6027 AccRsh (int shCount)
6028 {
6029   if (shCount != 0)
6030     {
6031       if (shCount == 1)
6032         {
6033           CLRC;
6034           emitcode ("rrc", "a");
6035         }
6036       else
6037         {
6038           /* rotate right accumulator */
6039           AccRol (8 - shCount);
6040           /* and kill the higher order bits */
6041           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6042         }
6043     }
6044 }
6045
6046 #ifdef BETTER_LITERAL_SHIFT
6047 /*-----------------------------------------------------------------*/
6048 /* AccSRsh - signed right shift accumulator by known count                 */
6049 /*-----------------------------------------------------------------*/
6050 static void
6051 AccSRsh (int shCount)
6052 {
6053   symbol *tlbl;
6054   if (shCount != 0)
6055     {
6056       if (shCount == 1)
6057         {
6058           emitcode ("mov", "c,acc.7");
6059           emitcode ("rrc", "a");
6060         }
6061       else if (shCount == 2)
6062         {
6063           emitcode ("mov", "c,acc.7");
6064           emitcode ("rrc", "a");
6065           emitcode ("mov", "c,acc.7");
6066           emitcode ("rrc", "a");
6067         }
6068       else
6069         {
6070           tlbl = newiTempLabel (NULL);
6071           /* rotate right accumulator */
6072           AccRol (8 - shCount);
6073           /* and kill the higher order bits */
6074           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6075           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6076           emitcode ("orl", "a,#0x%02x",
6077                     (unsigned char) ~SRMask[shCount]);
6078           emitcode ("", "%05d$:", tlbl->key + 100);
6079         }
6080     }
6081 }
6082 #endif
6083
6084 #ifdef BETTER_LITERAL_SHIFT
6085 /*-----------------------------------------------------------------*/
6086 /* shiftR1Left2Result - shift right one byte from left to result   */
6087 /*-----------------------------------------------------------------*/
6088 static void
6089 shiftR1Left2Result (operand * left, int offl,
6090                     operand * result, int offr,
6091                     int shCount, int sign)
6092 {
6093   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6094   /* shift right accumulator */
6095   if (sign)
6096     AccSRsh (shCount);
6097   else
6098     AccRsh (shCount);
6099   aopPut (AOP (result), "a", offr);
6100 }
6101 #endif
6102
6103 #ifdef BETTER_LITERAL_SHIFT
6104 /*-----------------------------------------------------------------*/
6105 /* shiftL1Left2Result - shift left one byte from left to result    */
6106 /*-----------------------------------------------------------------*/
6107 static void
6108 shiftL1Left2Result (operand * left, int offl,
6109                     operand * result, int offr, int shCount)
6110 {
6111   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6112   /* shift left accumulator */
6113   AccLsh (shCount);
6114   aopPut (AOP (result), "a", offr);
6115 }
6116 #endif
6117
6118 #ifdef BETTER_LITERAL_SHIFT
6119 /*-----------------------------------------------------------------*/
6120 /* movLeft2Result - move byte from left to result                  */
6121 /*-----------------------------------------------------------------*/
6122 static void
6123 movLeft2Result (operand * left, int offl,
6124                 operand * result, int offr, int sign)
6125 {
6126   char *l;
6127   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6128   {
6129       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6130
6131       if (*l == '@' && (IS_AOP_PREG (result)))
6132       {
6133           emitcode ("mov", "a,%s", l);
6134           aopPut (AOP (result), "a", offr);
6135       }
6136       else
6137       {
6138           if (!sign)
6139           {
6140             aopPut (AOP (result), l, offr);
6141           }
6142           else
6143             {
6144               /* MSB sign in acc.7 ! */
6145               if (getDataSize (left) == offl + 1)
6146                 {
6147                   emitcode ("mov", "a,%s", l);
6148                   aopPut (AOP (result), "a", offr);
6149                 }
6150             }
6151       }
6152   }
6153 }
6154 #endif
6155
6156 #ifdef BETTER_LITERAL_SHIFT
6157 /*-----------------------------------------------------------------*/
6158 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6159 /*-----------------------------------------------------------------*/
6160 static void
6161 AccAXRrl1 (char *x)
6162 {
6163   emitcode ("rrc", "a");
6164   emitcode ("xch", "a,%s", x);
6165   emitcode ("rrc", "a");
6166   emitcode ("xch", "a,%s", x);
6167 }
6168 #endif
6169
6170 #ifdef BETTER_LITERAL_SHIFT
6171 //REMOVE ME!!!
6172 /*-----------------------------------------------------------------*/
6173 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
6174 /*-----------------------------------------------------------------*/
6175 static void
6176 AccAXLrl1 (char *x)
6177 {
6178   emitcode ("xch", "a,%s", x);
6179   emitcode ("rlc", "a");
6180   emitcode ("xch", "a,%s", x);
6181   emitcode ("rlc", "a");
6182 }
6183 #endif
6184
6185 #ifdef BETTER_LITERAL_SHIFT
6186 /*-----------------------------------------------------------------*/
6187 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
6188 /*-----------------------------------------------------------------*/
6189 static void
6190 AccAXLsh1 (char *x)
6191 {
6192   emitcode ("xch", "a,%s", x);
6193   emitcode ("add", "a,acc");
6194   emitcode ("xch", "a,%s", x);
6195   emitcode ("rlc", "a");
6196 }
6197 #endif
6198
6199 #ifdef BETTER_LITERAL_SHIFT
6200 /*-----------------------------------------------------------------*/
6201 /* AccAXLsh - left shift a:x by known count (0..7)                 */
6202 /*-----------------------------------------------------------------*/
6203 static void
6204 AccAXLsh (char *x, int shCount)
6205 {
6206   switch (shCount)
6207     {
6208     case 0:
6209       break;
6210     case 1:
6211       AccAXLsh1 (x);
6212       break;
6213     case 2:
6214       AccAXLsh1 (x);
6215       AccAXLsh1 (x);
6216       break;
6217     case 3:
6218     case 4:
6219     case 5:                     // AAAAABBB:CCCCCDDD
6220
6221       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
6222
6223       emitcode ("anl", "a,#0x%02x",
6224                 SLMask[shCount]);       // BBB00000:CCCCCDDD
6225
6226       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
6227
6228       AccRol (shCount);         // DDDCCCCC:BBB00000
6229
6230       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
6231
6232       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
6233
6234       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
6235
6236       emitcode ("anl", "a,#0x%02x",
6237                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
6238
6239       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
6240
6241       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
6242
6243       break;
6244     case 6:                     // AAAAAABB:CCCCCCDD
6245       emitcode ("anl", "a,#0x%02x",
6246                 SRMask[shCount]);       // 000000BB:CCCCCCDD
6247       emitcode ("mov", "c,acc.0");      // c = B
6248       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
6249 #if 0
6250       AccAXRrl1 (x);            // BCCCCCCD:D000000B
6251       AccAXRrl1 (x);            // BBCCCCCC:DD000000
6252 #else
6253       emitcode("rrc","a"); 
6254       emitcode("xch","a,%s", x); 
6255       emitcode("rrc","a"); 
6256       emitcode("mov","c,acc.0"); //<< get correct bit 
6257       emitcode("xch","a,%s", x); 
6258
6259       emitcode("rrc","a"); 
6260       emitcode("xch","a,%s", x); 
6261       emitcode("rrc","a"); 
6262       emitcode("xch","a,%s", x); 
6263 #endif
6264       break;
6265     case 7:                     // a:x <<= 7
6266
6267       emitcode ("anl", "a,#0x%02x",
6268                 SRMask[shCount]);       // 0000000B:CCCCCCCD
6269
6270       emitcode ("mov", "c,acc.0");      // c = B
6271
6272       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
6273
6274       AccAXRrl1 (x);            // BCCCCCCC:D0000000
6275
6276       break;
6277     default:
6278       break;
6279     }
6280 }
6281 #endif
6282
6283 #ifdef BETTER_LITERAL_SHIFT
6284 //REMOVE ME!!!
6285 /*-----------------------------------------------------------------*/
6286 /* AccAXRsh - right shift a:x known count (0..7)                   */
6287 /*-----------------------------------------------------------------*/
6288 static void
6289 AccAXRsh (char *x, int shCount)
6290 {
6291   switch (shCount)
6292     {
6293     case 0:
6294       break;
6295     case 1:
6296       CLRC;
6297       AccAXRrl1 (x);            // 0->a:x
6298
6299       break;
6300     case 2:
6301       CLRC;
6302       AccAXRrl1 (x);            // 0->a:x
6303
6304       CLRC;
6305       AccAXRrl1 (x);            // 0->a:x
6306
6307       break;
6308     case 3:
6309     case 4:
6310     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6311
6312       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
6313
6314       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6315
6316       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6317
6318       emitcode ("anl", "a,#0x%02x",
6319                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6320
6321       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6322
6323       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6324
6325       emitcode ("anl", "a,#0x%02x",
6326                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6327
6328       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6329
6330       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6331
6332       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
6333
6334       break;
6335     case 6:                     // AABBBBBB:CCDDDDDD
6336
6337       emitcode ("mov", "c,acc.7");
6338       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6339
6340       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6341
6342       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6343
6344       emitcode ("anl", "a,#0x%02x",
6345                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6346
6347       break;
6348     case 7:                     // ABBBBBBB:CDDDDDDD
6349
6350       emitcode ("mov", "c,acc.7");      // c = A
6351
6352       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6353
6354       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6355
6356       emitcode ("anl", "a,#0x%02x",
6357                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6358
6359       break;
6360     default:
6361       break;
6362     }
6363 }
6364 #endif
6365
6366 #ifdef BETTER_LITERAL_SHIFT
6367 //REMOVE ME!!!
6368 /*-----------------------------------------------------------------*/
6369 /* AccAXRshS - right shift signed a:x known count (0..7)           */
6370 /*-----------------------------------------------------------------*/
6371 static void
6372 AccAXRshS (char *x, int shCount)
6373 {
6374   symbol *tlbl;
6375   switch (shCount)
6376     {
6377     case 0:
6378       break;
6379     case 1:
6380       emitcode ("mov", "c,acc.7");
6381       AccAXRrl1 (x);            // s->a:x
6382
6383       break;
6384     case 2:
6385       emitcode ("mov", "c,acc.7");
6386       AccAXRrl1 (x);            // s->a:x
6387
6388       emitcode ("mov", "c,acc.7");
6389       AccAXRrl1 (x);            // s->a:x
6390
6391       break;
6392     case 3:
6393     case 4:
6394     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6395
6396       tlbl = newiTempLabel (NULL);
6397       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
6398
6399       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6400
6401       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6402
6403       emitcode ("anl", "a,#0x%02x",
6404                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6405
6406       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6407
6408       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6409
6410       emitcode ("anl", "a,#0x%02x",
6411                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6412
6413       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6414
6415       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6416
6417       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
6418
6419       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6420       emitcode ("orl", "a,#0x%02x",
6421                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
6422
6423       emitcode ("", "%05d$:", tlbl->key + 100);
6424       break;                    // SSSSAAAA:BBBCCCCC
6425
6426     case 6:                     // AABBBBBB:CCDDDDDD
6427
6428       tlbl = newiTempLabel (NULL);
6429       emitcode ("mov", "c,acc.7");
6430       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6431
6432       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6433
6434       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6435
6436       emitcode ("anl", "a,#0x%02x",
6437                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6438
6439       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6440       emitcode ("orl", "a,#0x%02x",
6441                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
6442
6443       emitcode ("", "%05d$:", tlbl->key + 100);
6444       break;
6445     case 7:                     // ABBBBBBB:CDDDDDDD
6446
6447       tlbl = newiTempLabel (NULL);
6448       emitcode ("mov", "c,acc.7");      // c = A
6449
6450       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6451
6452       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6453
6454       emitcode ("anl", "a,#0x%02x",
6455                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6456
6457       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6458       emitcode ("orl", "a,#0x%02x",
6459                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
6460
6461       emitcode ("", "%05d$:", tlbl->key + 100);
6462       break;
6463     default:
6464       break;
6465     }
6466 }
6467 #endif
6468
6469 #ifdef BETTER_LITERAL_SHIFT
6470 static void
6471 _loadLeftIntoAx(char    **lsb, 
6472                 operand *left, 
6473                 operand *result,
6474                 int     offl,
6475                 int     offr)
6476 {
6477   // Get the initial value from left into a pair of registers.
6478   // MSB must be in A, LSB can be any register.
6479   //
6480   // If the result is held in registers, it is an optimization
6481   // if the LSB can be held in the register which will hold the,
6482   // result LSB since this saves us from having to copy it into
6483   // the result following AccAXLsh.
6484   //
6485   // If the result is addressed indirectly, this is not a gain.
6486   if (AOP_NEEDSACC(result))
6487   {
6488        char *leftByte;
6489        
6490        _startLazyDPSEvaluation();
6491        if (AOP_TYPE(left) == AOP_DPTR2)
6492        {
6493            // Get MSB in A.
6494            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6495            // get LSB in DP2_RESULT_REG.
6496            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6497            assert(!strcmp(leftByte, DP2_RESULT_REG));
6498        }
6499        else
6500        {
6501            // get LSB into DP2_RESULT_REG
6502            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6503            if (strcmp(leftByte, DP2_RESULT_REG))
6504            {
6505                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6506            }
6507            // And MSB in A.
6508            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6509            assert(strcmp(leftByte, DP2_RESULT_REG));
6510            MOVA(leftByte);
6511        }
6512        _endLazyDPSEvaluation();
6513        *lsb = DP2_RESULT_REG;
6514   }
6515   else
6516   {
6517       if (sameRegs (AOP (result), AOP (left)) &&
6518         ((offl + MSB16) == offr))
6519       {
6520           /* don't crash result[offr] */
6521           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6522           emitcode ("xch", "a,%s", 
6523                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6524       }
6525       else
6526       {
6527           movLeft2Result (left, offl, result, offr, 0);
6528           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6529       }
6530       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6531       assert(strcmp(*lsb,"a"));      
6532   }
6533 }
6534
6535 static void
6536 _storeAxResults(char    *lsb,
6537                 operand *result,
6538                 int     offr)
6539 {
6540   _startLazyDPSEvaluation();
6541   if (AOP_NEEDSACC(result))
6542   {
6543       /* We have to explicitly update the result LSB.
6544        */
6545       emitcode("xch","a,%s", lsb);
6546       aopPut(AOP(result), "a", offr);
6547       emitcode("mov","a,%s", lsb);
6548   }
6549   if (getDataSize (result) > 1)
6550   {
6551       aopPut (AOP (result), "a", offr + MSB16);
6552   }
6553   _endLazyDPSEvaluation();
6554 }
6555
6556 /*-----------------------------------------------------------------*/
6557 /* shiftL2Left2Result - shift left two bytes from left to result   */
6558 /*-----------------------------------------------------------------*/
6559 static void
6560 shiftL2Left2Result (operand * left, int offl,
6561                     operand * result, int offr, int shCount)
6562 {
6563   char *lsb;
6564
6565   _loadLeftIntoAx(&lsb, left, result, offl, offr);
6566   
6567   AccAXLsh (lsb, shCount);
6568   
6569   _storeAxResults(lsb, result, offr);
6570 }
6571 #endif
6572
6573 #ifdef BETTER_LITERAL_SHIFT
6574 /*-----------------------------------------------------------------*/
6575 /* shiftR2Left2Result - shift right two bytes from left to result  */
6576 /*-----------------------------------------------------------------*/
6577 static void
6578 shiftR2Left2Result (operand * left, int offl,
6579                     operand * result, int offr,
6580                     int shCount, int sign)
6581 {
6582   char *lsb;
6583   
6584   _loadLeftIntoAx(&lsb, left, result, offl, offr);
6585   
6586   /* a:x >> shCount (x = lsb(result)) */
6587   if (sign)
6588   {
6589     AccAXRshS(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6590   }
6591   else
6592   {
6593     AccAXRsh(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6594   }
6595   
6596   _storeAxResults(lsb, result, offr);
6597 }
6598 #endif
6599
6600 #if 0
6601 //REMOVE ME!!!
6602 /*-----------------------------------------------------------------*/
6603 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6604 /*-----------------------------------------------------------------*/
6605 static void
6606 shiftLLeftOrResult (operand * left, int offl,
6607                     operand * result, int offr, int shCount)
6608 {
6609   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6610   /* shift left accumulator */
6611   AccLsh (shCount);
6612   /* or with result */
6613   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6614   /* back to result */
6615   aopPut (AOP (result), "a", offr);
6616 }
6617 #endif
6618
6619 #if 0
6620 //REMOVE ME!!!
6621 /*-----------------------------------------------------------------*/
6622 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6623 /*-----------------------------------------------------------------*/
6624 static void
6625 shiftRLeftOrResult (operand * left, int offl,
6626                     operand * result, int offr, int shCount)
6627 {
6628   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6629   /* shift right accumulator */
6630   AccRsh (shCount);
6631   /* or with result */
6632   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6633   /* back to result */
6634   aopPut (AOP (result), "a", offr);
6635 }
6636 #endif
6637
6638 #ifdef BETTER_LITERAL_SHIFT
6639 /*-----------------------------------------------------------------*/
6640 /* genlshOne - left shift a one byte quantity by known count       */
6641 /*-----------------------------------------------------------------*/
6642 static void
6643 genlshOne (operand * result, operand * left, int shCount)
6644 {
6645   D (emitcode (";", "genlshOne "););
6646   shiftL1Left2Result (left, LSB, result, LSB, shCount);
6647 }
6648 #endif
6649
6650 #ifdef BETTER_LITERAL_SHIFT
6651 /*-----------------------------------------------------------------*/
6652 /* genlshTwo - left shift two bytes by known amount != 0           */
6653 /*-----------------------------------------------------------------*/
6654 static void
6655 genlshTwo (operand * result, operand * left, int shCount)
6656 {
6657   int size;
6658
6659   D (emitcode (";", "genlshTwo "););
6660
6661   size = getDataSize (result);
6662
6663   /* if shCount >= 8 */
6664   if (shCount >= 8)
6665   {
6666       shCount -= 8;
6667
6668       _startLazyDPSEvaluation();
6669
6670       if (size > 1)
6671         {
6672           if (shCount)
6673           {
6674             _endLazyDPSEvaluation();
6675             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6676             aopPut (AOP (result), zero, LSB);       
6677           }
6678           else
6679           {
6680             movLeft2Result (left, LSB, result, MSB16, 0);
6681             aopPut (AOP (result), zero, LSB);
6682             _endLazyDPSEvaluation();
6683           }
6684         }
6685         else
6686         {
6687           aopPut (AOP (result), zero, LSB);
6688           _endLazyDPSEvaluation();
6689         }
6690   }
6691
6692   /*  1 <= shCount <= 7 */
6693   else
6694     {
6695       if (size == 1)
6696       {
6697         shiftL1Left2Result (left, LSB, result, LSB, shCount);
6698       }
6699       else
6700       {
6701         shiftL2Left2Result (left, LSB, result, LSB, shCount);
6702       }
6703     }
6704 }
6705 #endif
6706
6707 #if 0
6708 //REMOVE ME!!!
6709 /*-----------------------------------------------------------------*/
6710 /* shiftLLong - shift left one long from left to result            */
6711 /* offl = LSB or MSB16                                             */
6712 /*-----------------------------------------------------------------*/
6713 static void
6714 shiftLLong (operand * left, operand * result, int offr)
6715 {
6716   char *l;
6717   int size = AOP_SIZE (result);
6718
6719   if (size >= LSB + offr)
6720     {
6721       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6722       MOVA (l);
6723       emitcode ("add", "a,acc");
6724       if (sameRegs (AOP (left), AOP (result)) &&
6725           size >= MSB16 + offr && offr != LSB)
6726         emitcode ("xch", "a,%s",
6727                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6728       else
6729         aopPut (AOP (result), "a", LSB + offr);
6730     }
6731
6732   if (size >= MSB16 + offr)
6733     {
6734       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6735         {
6736           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6737           MOVA (l);
6738         }
6739       emitcode ("rlc", "a");
6740       if (sameRegs (AOP (left), AOP (result)) &&
6741           size >= MSB24 + offr && offr != LSB)
6742         emitcode ("xch", "a,%s",
6743                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6744       else
6745         aopPut (AOP (result), "a", MSB16 + offr);
6746     }
6747
6748   if (size >= MSB24 + offr)
6749     {
6750       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6751         {
6752           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6753           MOVA (l);
6754         }
6755       emitcode ("rlc", "a");
6756       if (sameRegs (AOP (left), AOP (result)) &&
6757           size >= MSB32 + offr && offr != LSB)
6758         emitcode ("xch", "a,%s",
6759                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6760       else
6761         aopPut (AOP (result), "a", MSB24 + offr);
6762     }
6763
6764   if (size > MSB32 + offr)
6765     {
6766       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6767         {
6768           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6769           MOVA (l);
6770         }
6771       emitcode ("rlc", "a");
6772       aopPut (AOP (result), "a", MSB32 + offr);
6773     }
6774   if (offr != LSB)
6775     aopPut (AOP (result), zero, LSB);
6776 }
6777 #endif
6778
6779 #if 0
6780 //REMOVE ME!!!
6781 /*-----------------------------------------------------------------*/
6782 /* genlshFour - shift four byte by a known amount != 0             */
6783 /*-----------------------------------------------------------------*/
6784 static void
6785 genlshFour (operand * result, operand * left, int shCount)
6786 {
6787   int size;
6788
6789   D (emitcode (";", "genlshFour ");
6790     );
6791
6792   size = AOP_SIZE (result);
6793
6794   /* if shifting more that 3 bytes */
6795   if (shCount >= 24)
6796     {
6797       shCount -= 24;
6798       if (shCount)
6799         /* lowest order of left goes to the highest
6800            order of the destination */
6801         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6802       else
6803         movLeft2Result (left, LSB, result, MSB32, 0);
6804       aopPut (AOP (result), zero, LSB);
6805       aopPut (AOP (result), zero, MSB16);
6806       aopPut (AOP (result), zero, MSB24);
6807       return;
6808     }
6809
6810   /* more than two bytes */
6811   else if (shCount >= 16)
6812     {
6813       /* lower order two bytes goes to higher order two bytes */
6814       shCount -= 16;
6815       /* if some more remaining */
6816       if (shCount)
6817         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6818       else
6819         {
6820           movLeft2Result (left, MSB16, result, MSB32, 0);
6821           movLeft2Result (left, LSB, result, MSB24, 0);
6822         }
6823       aopPut (AOP (result), zero, MSB16);
6824       aopPut (AOP (result), zero, LSB);
6825       return;
6826     }
6827
6828   /* if more than 1 byte */
6829   else if (shCount >= 8)
6830     {
6831       /* lower order three bytes goes to higher order  three bytes */
6832       shCount -= 8;
6833       if (size == 2)
6834         {
6835           if (shCount)
6836             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6837           else
6838             movLeft2Result (left, LSB, result, MSB16, 0);
6839         }
6840       else
6841         {                       /* size = 4 */
6842           if (shCount == 0)
6843             {
6844               movLeft2Result (left, MSB24, result, MSB32, 0);
6845               movLeft2Result (left, MSB16, result, MSB24, 0);
6846               movLeft2Result (left, LSB, result, MSB16, 0);
6847               aopPut (AOP (result), zero, LSB);
6848             }
6849           else if (shCount == 1)
6850             shiftLLong (left, result, MSB16);
6851           else
6852             {
6853               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6854               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6855               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6856               aopPut (AOP (result), zero, LSB);
6857             }
6858         }
6859     }
6860
6861   /* 1 <= shCount <= 7 */
6862   else if (shCount <= 2)
6863     {
6864       shiftLLong (left, result, LSB);
6865       if (shCount == 2)
6866         shiftLLong (result, result, LSB);
6867     }
6868   /* 3 <= shCount <= 7, optimize */
6869   else
6870     {
6871       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6872       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6873       shiftL2Left2Result (left, LSB, result, LSB, shCount);
6874     }
6875 }
6876 #endif
6877
6878 #ifdef BETTER_LITERAL_SHIFT
6879 /*-----------------------------------------------------------------*/
6880 /* genLeftShiftLiteral - left shifting by known count              */
6881 /*-----------------------------------------------------------------*/
6882 static bool
6883 genLeftShiftLiteral (operand * left,
6884                      operand * right,
6885                      operand * result,
6886                      iCode * ic)
6887 {
6888   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6889   int size;
6890
6891   size = getSize (operandType (result));
6892
6893   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
6894
6895   /* We only handle certain easy cases so far. */
6896   if ((shCount != 0)
6897    && (shCount < (size * 8))
6898    && (size != 1)
6899    && (size != 2))
6900   {
6901       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
6902       return FALSE;
6903   }
6904
6905   freeAsmop (right, NULL, ic, TRUE);
6906
6907   aopOp(left, ic, FALSE, FALSE);
6908   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
6909
6910 #if 1 // debug spew
6911   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
6912   {
6913         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
6914         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
6915         {
6916            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
6917         }
6918   }
6919   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
6920   {
6921         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
6922         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
6923         {
6924            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
6925         }       
6926   }  
6927 #endif
6928   
6929 #if VIEW_SIZE
6930   emitcode ("; shift left ", "result %d, left %d", size,
6931             AOP_SIZE (left));
6932 #endif
6933
6934   /* I suppose that the left size >= result size */
6935   if (shCount == 0)
6936   {
6937         _startLazyDPSEvaluation();
6938         while (size--)
6939         {
6940           movLeft2Result (left, size, result, size, 0);
6941         }
6942         _endLazyDPSEvaluation();
6943   }
6944   else if (shCount >= (size * 8))
6945   {
6946     _startLazyDPSEvaluation();
6947     while (size--)
6948     {
6949       aopPut (AOP (result), zero, size);
6950     }
6951     _endLazyDPSEvaluation();
6952   }
6953   else
6954   {
6955       switch (size)
6956         {
6957         case 1:
6958           genlshOne (result, left, shCount);
6959           break;
6960
6961         case 2:
6962           genlshTwo (result, left, shCount);
6963           break;
6964 #if 0
6965         case 4:
6966           genlshFour (result, left, shCount);
6967           break;
6968 #endif
6969         default:
6970           fprintf(stderr, "*** ack! mystery literal shift!\n");   
6971           break;
6972         }
6973     }
6974   freeAsmop (left, NULL, ic, TRUE);
6975   freeAsmop (result, NULL, ic, TRUE);
6976   return TRUE;
6977 }
6978 #endif
6979
6980 /*-----------------------------------------------------------------*/
6981 /* genLeftShift - generates code for left shifting                 */
6982 /*-----------------------------------------------------------------*/
6983 static void
6984 genLeftShift (iCode * ic)
6985 {
6986   operand *left, *right, *result;
6987   int size, offset;
6988   char *l;
6989   symbol *tlbl, *tlbl1;
6990
6991   D (emitcode (";", "genLeftShift "););
6992
6993   right = IC_RIGHT (ic);
6994   left = IC_LEFT (ic);
6995   result = IC_RESULT (ic);
6996
6997   aopOp (right, ic, FALSE, FALSE);
6998
6999
7000 #ifdef BETTER_LITERAL_SHIFT
7001   /* if the shift count is known then do it
7002      as efficiently as possible */
7003   if (AOP_TYPE (right) == AOP_LIT)
7004     {
7005       if (genLeftShiftLiteral (left, right, result, ic))
7006       {
7007         return;
7008       }
7009     }
7010 #endif
7011
7012   /* shift count is unknown then we have to form
7013      a loop get the loop count in B : Note: we take
7014      only the lower order byte since shifting
7015      more that 32 bits make no sense anyway, ( the
7016      largest size of an object can be only 32 bits ) */
7017
7018   if (AOP_TYPE (right) == AOP_LIT)
7019   {
7020       /* Really should be handled by genLeftShiftLiteral,
7021        * but since I'm too lazy to fix that today, at least we can make
7022        * some small improvement.
7023        */
7024        emitcode("mov", "b,#0x%02x",
7025                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7026   }
7027   else
7028   {
7029         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7030         emitcode ("inc", "b");
7031   }
7032   freeAsmop (right, NULL, ic, TRUE);
7033   aopOp (left, ic, FALSE, FALSE);
7034   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7035
7036   /* now move the left to the result if they are not the
7037      same */
7038   if (!sameRegs (AOP (left), AOP (result)) &&
7039       AOP_SIZE (result) > 1)
7040     {
7041
7042       size = AOP_SIZE (result);
7043       offset = 0;
7044       _startLazyDPSEvaluation ();
7045       while (size--)
7046         {
7047           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7048           if (*l == '@' && (IS_AOP_PREG (result)))
7049             {
7050
7051               emitcode ("mov", "a,%s", l);
7052               aopPut (AOP (result), "a", offset);
7053             }
7054           else
7055             aopPut (AOP (result), l, offset);
7056           offset++;
7057         }
7058       _endLazyDPSEvaluation ();
7059     }
7060
7061   tlbl = newiTempLabel (NULL);
7062   size = AOP_SIZE (result);
7063   offset = 0;
7064   tlbl1 = newiTempLabel (NULL);
7065
7066   /* if it is only one byte then */
7067   if (size == 1)
7068     {
7069       symbol *tlbl1 = newiTempLabel (NULL);
7070
7071       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7072       MOVA (l);
7073       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7074       emitcode ("", "%05d$:", tlbl->key + 100);
7075       emitcode ("add", "a,acc");
7076       emitcode ("", "%05d$:", tlbl1->key + 100);
7077       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7078       aopPut (AOP (result), "a", 0);
7079       goto release;
7080     }
7081
7082   reAdjustPreg (AOP (result));
7083
7084   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7085   emitcode ("", "%05d$:", tlbl->key + 100);
7086   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7087   MOVA (l);
7088   emitcode ("add", "a,acc");
7089   aopPut (AOP (result), "a", offset++);
7090   _startLazyDPSEvaluation ();
7091   while (--size)
7092     {
7093       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7094       MOVA (l);
7095       emitcode ("rlc", "a");
7096       aopPut (AOP (result), "a", offset++);
7097     }
7098   _endLazyDPSEvaluation ();
7099   reAdjustPreg (AOP (result));
7100
7101   emitcode ("", "%05d$:", tlbl1->key + 100);
7102   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7103 release:
7104   freeAsmop (left, NULL, ic, TRUE);
7105   freeAsmop (result, NULL, ic, TRUE);
7106 }
7107
7108 #ifdef BETTER_LITERAL_SHIFT
7109 /*-----------------------------------------------------------------*/
7110 /* genrshOne - right shift a one byte quantity by known count      */
7111 /*-----------------------------------------------------------------*/
7112 static void
7113 genrshOne (operand * result, operand * left,
7114            int shCount, int sign)
7115 {
7116   D (emitcode (";", "genrshOne"););
7117   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7118 }
7119 #endif
7120
7121 #ifdef BETTER_LITERAL_SHIFT
7122 /*-----------------------------------------------------------------*/
7123 /* genrshTwo - right shift two bytes by known amount != 0          */
7124 /*-----------------------------------------------------------------*/
7125 static void
7126 genrshTwo (operand * result, operand * left,
7127            int shCount, int sign)
7128 {
7129   D (emitcode (";", "genrshTwo"););
7130
7131   /* if shCount >= 8 */
7132   if (shCount >= 8)
7133     {
7134       shCount -= 8;
7135       _startLazyDPSEvaluation();
7136       if (shCount)
7137       {
7138         shiftR1Left2Result (left, MSB16, result, LSB,
7139                             shCount, sign);
7140       }                     
7141       else
7142       {
7143         movLeft2Result (left, MSB16, result, LSB, sign);
7144       }
7145       addSign (result, MSB16, sign);
7146       _endLazyDPSEvaluation();
7147     }
7148
7149   /*  1 <= shCount <= 7 */
7150   else
7151   {
7152     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7153   }
7154 }
7155 #endif
7156
7157 #if 0
7158 //REMOVE ME!!!
7159 /*-----------------------------------------------------------------*/
7160 /* shiftRLong - shift right one long from left to result           */
7161 /* offl = LSB or MSB16                                             */
7162 /*-----------------------------------------------------------------*/
7163 static void
7164 shiftRLong (operand * left, int offl,
7165             operand * result, int sign)
7166 {
7167   if (!sign)
7168     emitcode ("clr", "c");
7169   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
7170   if (sign)
7171     emitcode ("mov", "c,acc.7");
7172   emitcode ("rrc", "a");
7173   aopPut (AOP (result), "a", MSB32 - offl);
7174   if (offl == MSB16)
7175     /* add sign of "a" */
7176     addSign (result, MSB32, sign);
7177
7178   MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
7179   emitcode ("rrc", "a");
7180   aopPut (AOP (result), "a", MSB24 - offl);
7181
7182   MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
7183   emitcode ("rrc", "a");
7184   aopPut (AOP (result), "a", MSB16 - offl);
7185
7186   if (offl == LSB)
7187     {
7188       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
7189       emitcode ("rrc", "a");
7190       aopPut (AOP (result), "a", LSB);
7191     }
7192 }
7193 #endif
7194
7195 #if 0
7196 //REMOVE ME!!!
7197 /*-----------------------------------------------------------------*/
7198 /* genrshFour - shift four byte by a known amount != 0             */
7199 /*-----------------------------------------------------------------*/
7200 static void
7201 genrshFour (operand * result, operand * left,
7202             int shCount, int sign)
7203 {
7204   D (emitcode (";", "genrshFour");
7205     );
7206
7207   /* if shifting more that 3 bytes */
7208   if (shCount >= 24)
7209     {
7210       shCount -= 24;
7211       if (shCount)
7212         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7213       else
7214         movLeft2Result (left, MSB32, result, LSB, sign);
7215       addSign (result, MSB16, sign);
7216     }
7217   else if (shCount >= 16)
7218     {
7219       shCount -= 16;
7220       if (shCount)
7221         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7222       else
7223         {
7224           movLeft2Result (left, MSB24, result, LSB, 0);
7225           movLeft2Result (left, MSB32, result, MSB16, sign);
7226         }
7227       addSign (result, MSB24, sign);
7228     }
7229   else if (shCount >= 8)
7230     {
7231       shCount -= 8;
7232       if (shCount == 1)
7233         shiftRLong (left, MSB16, result, sign);
7234       else if (shCount == 0)
7235         {
7236           movLeft2Result (left, MSB16, result, LSB, 0);
7237           movLeft2Result (left, MSB24, result, MSB16, 0);
7238           movLeft2Result (left, MSB32, result, MSB24, sign);
7239           addSign (result, MSB32, sign);
7240         }
7241       else
7242         {
7243           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7244           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7245           /* the last shift is signed */
7246           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7247           addSign (result, MSB32, sign);
7248         }
7249     }
7250   else
7251     {                           /* 1 <= shCount <= 7 */
7252       if (shCount <= 2)
7253         {
7254           shiftRLong (left, LSB, result, sign);
7255           if (shCount == 2)
7256             shiftRLong (result, LSB, result, sign);
7257         }
7258       else
7259         {
7260           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7261           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7262           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7263         }
7264     }
7265 }
7266 #endif
7267
7268 #ifdef BETTER_LITERAL_SHIFT
7269 /*-----------------------------------------------------------------*/
7270 /* genRightShiftLiteral - right shifting by known count            */
7271 /*-----------------------------------------------------------------*/
7272 static bool
7273 genRightShiftLiteral (operand * left,
7274                       operand * right,
7275                       operand * result,
7276                       iCode * ic,
7277                       int sign)
7278 {
7279   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7280   int size;
7281
7282   size = getSize (operandType (result));
7283
7284   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7285
7286   /* We only handle certain easy cases so far. */
7287   if ((shCount != 0)
7288    && (shCount < (size * 8))
7289    && (size != 1)
7290    && (size != 2))
7291   {
7292       D(emitcode (";", "genRightShiftLiteral wimping out"););   
7293       return FALSE;
7294   }
7295
7296   freeAsmop (right, NULL, ic, TRUE);
7297
7298   aopOp (left, ic, FALSE, FALSE);
7299   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7300
7301 #if VIEW_SIZE
7302   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7303             AOP_SIZE (left));
7304 #endif
7305
7306   /* test the LEFT size !!! */
7307
7308   /* I suppose that the left size >= result size */
7309   if (shCount == 0)
7310   {
7311       size = getDataSize (result);
7312       _startLazyDPSEvaluation();
7313       while (size--)
7314       {
7315         movLeft2Result (left, size, result, size, 0);
7316       }
7317       _endLazyDPSEvaluation();
7318   }
7319   else if (shCount >= (size * 8))
7320     {
7321       if (sign)
7322       {
7323         /* get sign in acc.7 */
7324         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7325       }
7326       addSign (result, LSB, sign);
7327     }
7328   else
7329     {
7330       switch (size)
7331         {
7332         case 1:
7333           genrshOne (result, left, shCount, sign);
7334           break;
7335
7336         case 2:
7337           genrshTwo (result, left, shCount, sign);
7338           break;
7339 #if 0
7340         case 4:
7341           genrshFour (result, left, shCount, sign);
7342           break;
7343 #endif    
7344         default:
7345           break;
7346         }
7347
7348       freeAsmop (left, NULL, ic, TRUE);
7349       freeAsmop (result, NULL, ic, TRUE);
7350     }
7351     return TRUE;
7352 }
7353 #endif
7354
7355 /*-----------------------------------------------------------------*/
7356 /* genSignedRightShift - right shift of signed number              */
7357 /*-----------------------------------------------------------------*/
7358 static void
7359 genSignedRightShift (iCode * ic)
7360 {
7361   operand *right, *left, *result;
7362   int size, offset;
7363   char *l;
7364   symbol *tlbl, *tlbl1;
7365
7366   D (emitcode (";", "genSignedRightShift "););
7367
7368   /* we do it the hard way put the shift count in b
7369      and loop thru preserving the sign */
7370
7371   right = IC_RIGHT (ic);
7372   left = IC_LEFT (ic);
7373   result = IC_RESULT (ic);
7374
7375   aopOp (right, ic, FALSE, FALSE);
7376
7377 #ifdef BETTER_LITERAL_SHIFT
7378   if (AOP_TYPE (right) == AOP_LIT)
7379     {
7380       if (genRightShiftLiteral (left, right, result, ic, 1))
7381       {
7382         return;
7383       }
7384     }
7385 #endif
7386   /* shift count is unknown then we have to form
7387      a loop get the loop count in B : Note: we take
7388      only the lower order byte since shifting
7389      more that 32 bits make no sense anyway, ( the
7390      largest size of an object can be only 32 bits ) */
7391
7392   if (AOP_TYPE (right) == AOP_LIT)
7393   {
7394       /* Really should be handled by genRightShiftLiteral,
7395        * but since I'm too lazy to fix that today, at least we can make
7396        * some small improvement.
7397        */
7398        emitcode("mov", "b,#0x%02x",
7399                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7400   }
7401   else
7402   {
7403         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7404         emitcode ("inc", "b");
7405   }
7406   freeAsmop (right, NULL, ic, TRUE);
7407   aopOp (left, ic, FALSE, FALSE);
7408   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7409
7410   /* now move the left to the result if they are not the
7411      same */
7412   if (!sameRegs (AOP (left), AOP (result)) &&
7413       AOP_SIZE (result) > 1)
7414     {
7415
7416       size = AOP_SIZE (result);
7417       offset = 0;
7418       _startLazyDPSEvaluation ();
7419       while (size--)
7420         {
7421           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7422           if (*l == '@' && IS_AOP_PREG (result))
7423             {
7424
7425               emitcode ("mov", "a,%s", l);
7426               aopPut (AOP (result), "a", offset);
7427             }
7428           else
7429             aopPut (AOP (result), l, offset);
7430           offset++;
7431         }
7432       _endLazyDPSEvaluation ();
7433     }
7434
7435   /* mov the highest order bit to OVR */
7436   tlbl = newiTempLabel (NULL);
7437   tlbl1 = newiTempLabel (NULL);
7438
7439   size = AOP_SIZE (result);
7440   offset = size - 1;
7441   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7442   emitcode ("rlc", "a");
7443   emitcode ("mov", "ov,c");
7444   /* if it is only one byte then */
7445   if (size == 1)
7446     {
7447       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7448       MOVA (l);
7449       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7450       emitcode ("", "%05d$:", tlbl->key + 100);
7451       emitcode ("mov", "c,ov");
7452       emitcode ("rrc", "a");
7453       emitcode ("", "%05d$:", tlbl1->key + 100);
7454       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7455       aopPut (AOP (result), "a", 0);
7456       goto release;
7457     }
7458
7459   reAdjustPreg (AOP (result));
7460   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7461   emitcode ("", "%05d$:", tlbl->key + 100);
7462   emitcode ("mov", "c,ov");
7463   _startLazyDPSEvaluation ();
7464   while (size--)
7465     {
7466       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7467       MOVA (l);
7468       emitcode ("rrc", "a");
7469       aopPut (AOP (result), "a", offset--);
7470     }
7471   _endLazyDPSEvaluation ();
7472   reAdjustPreg (AOP (result));
7473   emitcode ("", "%05d$:", tlbl1->key + 100);
7474   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7475
7476 release:
7477   freeAsmop (left, NULL, ic, TRUE);
7478   freeAsmop (result, NULL, ic, TRUE);
7479 }
7480
7481 /*-----------------------------------------------------------------*/
7482 /* genRightShift - generate code for right shifting                */
7483 /*-----------------------------------------------------------------*/
7484 static void
7485 genRightShift (iCode * ic)
7486 {
7487   operand *right, *left, *result;
7488   sym_link *retype;
7489   int size, offset;
7490   char *l;
7491   symbol *tlbl, *tlbl1;
7492
7493   D (emitcode (";", "genRightShift "););
7494
7495   /* if signed then we do it the hard way preserve the
7496      sign bit moving it inwards */
7497   retype = getSpec (operandType (IC_RESULT (ic)));
7498
7499   if (!SPEC_USIGN (retype))
7500     {
7501       genSignedRightShift (ic);
7502       return;
7503     }
7504
7505   /* signed & unsigned types are treated the same : i.e. the
7506      signed is NOT propagated inwards : quoting from the
7507      ANSI - standard : "for E1 >> E2, is equivalent to division
7508      by 2**E2 if unsigned or if it has a non-negative value,
7509      otherwise the result is implementation defined ", MY definition
7510      is that the sign does not get propagated */
7511
7512   right = IC_RIGHT (ic);
7513   left = IC_LEFT (ic);
7514   result = IC_RESULT (ic);
7515
7516   aopOp (right, ic, FALSE, FALSE);
7517
7518 #ifdef BETTER_LITERAL_SHIFT
7519   /* if the shift count is known then do it
7520      as efficiently as possible */
7521   if (AOP_TYPE (right) == AOP_LIT)
7522     {
7523       if (genRightShiftLiteral (left, right, result, ic, 0))
7524       {
7525         return;
7526       }
7527     }
7528 #endif
7529
7530   /* shift count is unknown then we have to form
7531      a loop get the loop count in B : Note: we take
7532      only the lower order byte since shifting
7533      more that 32 bits make no sense anyway, ( the
7534      largest size of an object can be only 32 bits ) */
7535   
7536   if (AOP_TYPE (right) == AOP_LIT)
7537   {
7538       /* Really should be handled by genRightShiftLiteral,
7539        * but since I'm too lazy to fix that today, at least we can make
7540        * some small improvement.
7541        */
7542        emitcode("mov", "b,#0x%02x",
7543                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7544   }
7545   else
7546   {
7547         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7548         emitcode ("inc", "b");
7549   }
7550   freeAsmop (right, NULL, ic, TRUE);
7551   aopOp (left, ic, FALSE, FALSE);
7552   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7553
7554   /* now move the left to the result if they are not the
7555      same */
7556   if (!sameRegs (AOP (left), AOP (result)) &&
7557       AOP_SIZE (result) > 1)
7558     {
7559
7560       size = AOP_SIZE (result);
7561       offset = 0;
7562       _startLazyDPSEvaluation ();
7563       while (size--)
7564         {
7565           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7566           if (*l == '@' && IS_AOP_PREG (result))
7567             {
7568
7569               emitcode ("mov", "a,%s", l);
7570               aopPut (AOP (result), "a", offset);
7571             }
7572           else
7573             aopPut (AOP (result), l, offset);
7574           offset++;
7575         }
7576       _endLazyDPSEvaluation ();
7577     }
7578
7579   tlbl = newiTempLabel (NULL);
7580   tlbl1 = newiTempLabel (NULL);
7581   size = AOP_SIZE (result);
7582   offset = size - 1;
7583
7584   /* if it is only one byte then */
7585   if (size == 1)
7586     {
7587       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7588       MOVA (l);
7589       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7590       emitcode ("", "%05d$:", tlbl->key + 100);
7591       CLRC;
7592       emitcode ("rrc", "a");
7593       emitcode ("", "%05d$:", tlbl1->key + 100);
7594       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7595       aopPut (AOP (result), "a", 0);
7596       goto release;
7597     }
7598
7599   reAdjustPreg (AOP (result));
7600   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7601   emitcode ("", "%05d$:", tlbl->key + 100);
7602   CLRC;
7603   _startLazyDPSEvaluation ();
7604   while (size--)
7605     {
7606       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7607       MOVA (l);
7608       emitcode ("rrc", "a");
7609       aopPut (AOP (result), "a", offset--);
7610     }
7611   _endLazyDPSEvaluation ();
7612   reAdjustPreg (AOP (result));
7613
7614   emitcode ("", "%05d$:", tlbl1->key + 100);
7615   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7616
7617 release:
7618   freeAsmop (left, NULL, ic, TRUE);
7619   freeAsmop (result, NULL, ic, TRUE);
7620 }
7621
7622 /*-----------------------------------------------------------------*/
7623 /* genUnpackBits - generates code for unpacking bits               */
7624 /*-----------------------------------------------------------------*/
7625 static void
7626 genUnpackBits (operand * result, char *rname, int ptype)
7627 {
7628   int shCnt;
7629   int rlen = 0;
7630   sym_link *etype;
7631   int offset = 0;
7632
7633   D (emitcode (";", "genUnpackBits ");
7634     );
7635
7636   etype = getSpec (operandType (result));
7637
7638   /* read the first byte  */
7639   switch (ptype)
7640     {
7641
7642     case POINTER:
7643     case IPOINTER:
7644       emitcode ("mov", "a,@%s", rname);
7645       break;
7646
7647     case PPOINTER:
7648       emitcode ("movx", "a,@%s", rname);
7649       break;
7650
7651     case FPOINTER:
7652       emitcode ("movx", "a,@dptr");
7653       break;
7654
7655     case CPOINTER:
7656       emitcode ("clr", "a");
7657       emitcode ("movc", "a", "@a+dptr");
7658       break;
7659
7660     case GPOINTER:
7661       emitcode ("lcall", "__gptrget");
7662       break;
7663     }
7664
7665   /* if we have bitdisplacement then it fits   */
7666   /* into this byte completely or if length is */
7667   /* less than a byte                          */
7668   if ((shCnt = SPEC_BSTR (etype)) ||
7669       (SPEC_BLEN (etype) <= 8))
7670     {
7671
7672       /* shift right acc */
7673       AccRsh (shCnt);
7674
7675       emitcode ("anl", "a,#0x%02x",
7676                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7677       aopPut (AOP (result), "a", offset);
7678       return;
7679     }
7680
7681   /* bit field did not fit in a byte  */
7682   rlen = SPEC_BLEN (etype) - 8;
7683   aopPut (AOP (result), "a", offset++);
7684
7685   while (1)
7686     {
7687
7688       switch (ptype)
7689         {
7690         case POINTER:
7691         case IPOINTER:
7692           emitcode ("inc", "%s", rname);
7693           emitcode ("mov", "a,@%s", rname);
7694           break;
7695
7696         case PPOINTER:
7697           emitcode ("inc", "%s", rname);
7698           emitcode ("movx", "a,@%s", rname);
7699           break;
7700
7701         case FPOINTER:
7702           emitcode ("inc", "dptr");
7703           emitcode ("movx", "a,@dptr");
7704           break;
7705
7706         case CPOINTER:
7707           emitcode ("clr", "a");
7708           emitcode ("inc", "dptr");
7709           emitcode ("movc", "a", "@a+dptr");
7710           break;
7711
7712         case GPOINTER:
7713           emitcode ("inc", "dptr");
7714           emitcode ("lcall", "__gptrget");
7715           break;
7716         }
7717
7718       rlen -= 8;
7719       /* if we are done */
7720       if (rlen < 8)
7721         break;
7722
7723       aopPut (AOP (result), "a", offset++);
7724
7725     }
7726
7727   if (rlen)
7728     {
7729       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7730       aopPut (AOP (result), "a", offset);
7731     }
7732
7733   return;
7734 }
7735
7736
7737 /*-----------------------------------------------------------------*/
7738 /* genDataPointerGet - generates code when ptr offset is known     */
7739 /*-----------------------------------------------------------------*/
7740 static void
7741 genDataPointerGet (operand * left,
7742                    operand * result,
7743                    iCode * ic)
7744 {
7745   char *l;
7746   char buffer[256];
7747   int size, offset = 0;
7748   aopOp (result, ic, TRUE, FALSE);
7749
7750   /* get the string representation of the name */
7751   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7752   size = AOP_SIZE (result);
7753   _startLazyDPSEvaluation ();
7754   while (size--)
7755     {
7756       if (offset)
7757         sprintf (buffer, "(%s + %d)", l + 1, offset);
7758       else
7759         sprintf (buffer, "%s", l + 1);
7760       aopPut (AOP (result), buffer, offset++);
7761     }
7762   _endLazyDPSEvaluation ();
7763
7764   freeAsmop (left, NULL, ic, TRUE);
7765   freeAsmop (result, NULL, ic, TRUE);
7766 }
7767
7768 /*-----------------------------------------------------------------*/
7769 /* genNearPointerGet - emitcode for near pointer fetch             */
7770 /*-----------------------------------------------------------------*/
7771 static void
7772 genNearPointerGet (operand * left,
7773                    operand * result,
7774                    iCode * ic)
7775 {
7776   asmop *aop = NULL;
7777   regs *preg = NULL;
7778   char *rname;
7779   sym_link *rtype, *retype, *letype;
7780   sym_link *ltype = operandType (left);
7781   char buffer[80];
7782
7783   rtype = operandType (result);
7784   retype = getSpec (rtype);
7785   letype = getSpec (ltype);
7786
7787   aopOp (left, ic, FALSE, FALSE);
7788
7789   /* if left is rematerialisable and
7790      result is not bit variable type and
7791      the left is pointer to data space i.e
7792      lower 128 bytes of space */
7793   if (AOP_TYPE (left) == AOP_IMMD &&
7794       !IS_BITVAR (retype) &&
7795       !IS_BITVAR (letype) &&
7796       DCL_TYPE (ltype) == POINTER)
7797     {
7798       genDataPointerGet (left, result, ic);
7799       return;
7800     }
7801
7802   /* if the value is already in a pointer register
7803      then don't need anything more */
7804   if (!AOP_INPREG (AOP (left)))
7805     {
7806       /* otherwise get a free pointer register */
7807       aop = newAsmop (0);
7808       preg = getFreePtr (ic, &aop, FALSE);
7809       emitcode ("mov", "%s,%s",
7810                 preg->name,
7811                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7812       rname = preg->name;
7813     }
7814   else
7815     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7816
7817   freeAsmop (left, NULL, ic, TRUE);
7818   aopOp (result, ic, FALSE, FALSE);
7819
7820   /* if bitfield then unpack the bits */
7821   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7822     genUnpackBits (result, rname, POINTER);
7823   else
7824     {
7825       /* we have can just get the values */
7826       int size = AOP_SIZE (result);
7827       int offset = 0;
7828
7829       while (size--)
7830         {
7831           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7832             {
7833
7834               emitcode ("mov", "a,@%s", rname);
7835               aopPut (AOP (result), "a", offset);
7836             }
7837           else
7838             {
7839               sprintf (buffer, "@%s", rname);
7840               aopPut (AOP (result), buffer, offset);
7841             }
7842           offset++;
7843           if (size)
7844             emitcode ("inc", "%s", rname);
7845         }
7846     }
7847
7848   /* now some housekeeping stuff */
7849   if (aop)
7850     {
7851       /* we had to allocate for this iCode */
7852       freeAsmop (NULL, aop, ic, TRUE);
7853     }
7854   else
7855     {
7856       /* we did not allocate which means left
7857          already in a pointer register, then
7858          if size > 0 && this could be used again
7859          we have to point it back to where it
7860          belongs */
7861       if (AOP_SIZE (result) > 1 &&
7862           !OP_SYMBOL (left)->remat &&
7863           (OP_SYMBOL (left)->liveTo > ic->seq ||
7864            ic->depth))
7865         {
7866           int size = AOP_SIZE (result) - 1;
7867           while (size--)
7868             emitcode ("dec", "%s", rname);
7869         }
7870     }
7871
7872   /* done */
7873   freeAsmop (result, NULL, ic, TRUE);
7874
7875 }
7876
7877 /*-----------------------------------------------------------------*/
7878 /* genPagedPointerGet - emitcode for paged pointer fetch           */
7879 /*-----------------------------------------------------------------*/
7880 static void
7881 genPagedPointerGet (operand * left,
7882                     operand * result,
7883                     iCode * ic)
7884 {
7885   asmop *aop = NULL;
7886   regs *preg = NULL;
7887   char *rname;
7888   sym_link *rtype, *retype, *letype;
7889
7890   rtype = operandType (result);
7891   retype = getSpec (rtype);
7892   letype = getSpec (operandType (left));
7893   aopOp (left, ic, FALSE, FALSE);
7894
7895   /* if the value is already in a pointer register
7896      then don't need anything more */
7897   if (!AOP_INPREG (AOP (left)))
7898     {
7899       /* otherwise get a free pointer register */
7900       aop = newAsmop (0);
7901       preg = getFreePtr (ic, &aop, FALSE);
7902       emitcode ("mov", "%s,%s",
7903                 preg->name,
7904                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7905       rname = preg->name;
7906     }
7907   else
7908     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7909
7910   freeAsmop (left, NULL, ic, TRUE);
7911   aopOp (result, ic, FALSE, FALSE);
7912
7913   /* if bitfield then unpack the bits */
7914   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7915     genUnpackBits (result, rname, PPOINTER);
7916   else
7917     {
7918       /* we have can just get the values */
7919       int size = AOP_SIZE (result);
7920       int offset = 0;
7921
7922       while (size--)
7923         {
7924
7925           emitcode ("movx", "a,@%s", rname);
7926           aopPut (AOP (result), "a", offset);
7927
7928           offset++;
7929
7930           if (size)
7931             emitcode ("inc", "%s", rname);
7932         }
7933     }
7934
7935   /* now some housekeeping stuff */
7936   if (aop)
7937     {
7938       /* we had to allocate for this iCode */
7939       freeAsmop (NULL, aop, ic, TRUE);
7940     }
7941   else
7942     {
7943       /* we did not allocate which means left
7944          already in a pointer register, then
7945          if size > 0 && this could be used again
7946          we have to point it back to where it
7947          belongs */
7948       if (AOP_SIZE (result) > 1 &&
7949           !OP_SYMBOL (left)->remat &&
7950           (OP_SYMBOL (left)->liveTo > ic->seq ||
7951            ic->depth))
7952         {
7953           int size = AOP_SIZE (result) - 1;
7954           while (size--)
7955             emitcode ("dec", "%s", rname);
7956         }
7957     }
7958
7959   /* done */
7960   freeAsmop (result, NULL, ic, TRUE);
7961
7962
7963 }
7964
7965 /*-----------------------------------------------------------------*/
7966 /* genFarPointerGet - gget value from far space                    */
7967 /*-----------------------------------------------------------------*/
7968 static void
7969 genFarPointerGet (operand * left,
7970                   operand * result, iCode * ic)
7971 {
7972   int size, offset;
7973   sym_link *retype = getSpec (operandType (result));
7974   sym_link *letype = getSpec (operandType (left));
7975   D (emitcode (";", "genFarPointerGet");
7976     );
7977
7978   aopOp (left, ic, FALSE, FALSE);
7979
7980   /* if the operand is already in dptr
7981      then we do nothing else we move the value to dptr */
7982   if (AOP_TYPE (left) != AOP_STR)
7983     {
7984       /* if this is remateriazable */
7985       if (AOP_TYPE (left) == AOP_IMMD)
7986         {
7987           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7988         }
7989       else
7990         {
7991           /* we need to get it byte by byte */
7992           _startLazyDPSEvaluation ();
7993           if (AOP_TYPE (left) != AOP_DPTR)
7994             {
7995               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7996               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7997               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7998             }
7999           else
8000             {
8001               /* We need to generate a load to DPTR indirect through DPTR. */
8002               D (emitcode (";", "genFarPointerGet -- indirection special case.");
8003                 );
8004               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8005               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8006               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8007               emitcode ("pop", "dph");
8008               emitcode ("pop", "dpl");
8009             }
8010           _endLazyDPSEvaluation ();
8011         }
8012     }
8013   /* so dptr know contains the address */
8014   freeAsmop (left, NULL, ic, TRUE);
8015   aopOp (result, ic, FALSE, TRUE);
8016
8017   /* if bit then unpack */
8018   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8019     genUnpackBits (result, "dptr", FPOINTER);
8020   else
8021     {
8022       size = AOP_SIZE (result);
8023       offset = 0;
8024
8025       _startLazyDPSEvaluation ();
8026       while (size--)
8027         {
8028
8029           genSetDPTR (0);
8030           _flushLazyDPS ();
8031
8032           emitcode ("movx", "a,@dptr");
8033           if (size)
8034             emitcode ("inc", "dptr");
8035
8036           aopPut (AOP (result), "a", offset++);
8037         }
8038       _endLazyDPSEvaluation ();
8039     }
8040
8041   freeAsmop (result, NULL, ic, TRUE);
8042 }
8043
8044 /*-----------------------------------------------------------------*/
8045 /* emitcodePointerGet - gget value from code space                  */
8046 /*-----------------------------------------------------------------*/
8047 static void
8048 emitcodePointerGet (operand * left,
8049                     operand * result, iCode * ic)
8050 {
8051   int size, offset;
8052   sym_link *retype = getSpec (operandType (result));
8053
8054   aopOp (left, ic, FALSE, FALSE);
8055
8056   /* if the operand is already in dptr
8057      then we do nothing else we move the value to dptr */
8058   if (AOP_TYPE (left) != AOP_STR)
8059     {
8060       /* if this is remateriazable */
8061       if (AOP_TYPE (left) == AOP_IMMD)
8062         {
8063           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8064         }
8065       else
8066         {                       /* we need to get it byte by byte */
8067           _startLazyDPSEvaluation ();
8068           if (AOP_TYPE (left) != AOP_DPTR)
8069             {
8070               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8071               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8072               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8073             }
8074           else
8075             {
8076               /* We need to generate a load to DPTR indirect through DPTR. */
8077               D (emitcode (";", "gencodePointerGet -- indirection special case.");
8078                 );
8079               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8080               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8081               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8082               emitcode ("pop", "dph");
8083               emitcode ("pop", "dpl");
8084             }
8085           _endLazyDPSEvaluation ();
8086         }
8087     }
8088   /* so dptr know contains the address */
8089   freeAsmop (left, NULL, ic, TRUE);
8090   aopOp (result, ic, FALSE, TRUE);
8091
8092   /* if bit then unpack */
8093   if (IS_BITVAR (retype))
8094     genUnpackBits (result, "dptr", CPOINTER);
8095   else
8096     {
8097       size = AOP_SIZE (result);
8098       offset = 0;
8099
8100       _startLazyDPSEvaluation ();
8101       while (size--)
8102         {
8103           genSetDPTR (0);
8104           _flushLazyDPS ();
8105
8106           emitcode ("clr", "a");
8107           emitcode ("movc", "a,@a+dptr");
8108           if (size)
8109             emitcode ("inc", "dptr");
8110           aopPut (AOP (result), "a", offset++);
8111         }
8112       _endLazyDPSEvaluation ();
8113     }
8114
8115   freeAsmop (result, NULL, ic, TRUE);
8116 }
8117
8118 /*-----------------------------------------------------------------*/
8119 /* genGenPointerGet - gget value from generic pointer space        */
8120 /*-----------------------------------------------------------------*/
8121 static void
8122 genGenPointerGet (operand * left,
8123                   operand * result, iCode * ic)
8124 {
8125   int size, offset;
8126   sym_link *retype = getSpec (operandType (result));
8127   sym_link *letype = getSpec (operandType (left));
8128
8129   D (emitcode (";", "genGenPointerGet "); );
8130
8131   aopOp (left, ic, FALSE, TRUE);
8132
8133   /* if the operand is already in dptr
8134      then we do nothing else we move the value to dptr */
8135   if (AOP_TYPE (left) != AOP_STR)
8136     {
8137       /* if this is remateriazable */
8138       if (AOP_TYPE (left) == AOP_IMMD)
8139         {
8140           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8141           emitcode ("mov", "b,#%d", pointerCode (retype));
8142         }
8143       else
8144         {                       /* we need to get it byte by byte */
8145           _startLazyDPSEvaluation ();
8146           if (AOP(left)->type==AOP_DPTR2) {
8147             char *l;
8148             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8149             genSetDPTR(0);
8150             _flushLazyDPS();
8151             emitcode ("mov", "dpl,%s", l);
8152             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8153             genSetDPTR(0);
8154             _flushLazyDPS();
8155             emitcode ("mov", "dph,%s", l);
8156             l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8157             genSetDPTR(0);
8158             _flushLazyDPS();
8159             emitcode ("mov", "dpx,%s", l);
8160             emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8161           } else {
8162             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8163             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8164             emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8165             emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8166           }
8167           _endLazyDPSEvaluation ();
8168         }
8169     }
8170   /* so dptr know contains the address */
8171   freeAsmop (left, NULL, ic, TRUE);
8172   aopOp (result, ic, FALSE, TRUE);
8173
8174   /* if bit then unpack */
8175   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8176     genUnpackBits (result, "dptr", GPOINTER);
8177   else
8178     {
8179       size = AOP_SIZE (result);
8180       offset = 0;
8181
8182       while (size--)
8183         {
8184           emitcode ("lcall", "__gptrget");
8185           aopPut (AOP (result), "a", offset++);
8186           if (size)
8187             emitcode ("inc", "dptr");
8188         }
8189     }
8190
8191   freeAsmop (result, NULL, ic, TRUE);
8192 }
8193
8194 /*-----------------------------------------------------------------*/
8195 /* genPointerGet - generate code for pointer get                   */
8196 /*-----------------------------------------------------------------*/
8197 static void
8198 genPointerGet (iCode * ic)
8199 {
8200   operand *left, *result;
8201   sym_link *type, *etype;
8202   int p_type;
8203
8204   D (emitcode (";", "genPointerGet ");
8205     );
8206
8207   left = IC_LEFT (ic);
8208   result = IC_RESULT (ic);
8209
8210   /* depending on the type of pointer we need to
8211      move it to the correct pointer register */
8212   type = operandType (left);
8213   etype = getSpec (type);
8214   /* if left is of type of pointer then it is simple */
8215   if (IS_PTR (type) && !IS_FUNC (type->next))
8216     p_type = DCL_TYPE (type);
8217   else
8218     {
8219       /* we have to go by the storage class */
8220       p_type = PTR_TYPE (SPEC_OCLS (etype));
8221     }
8222
8223   /* now that we have the pointer type we assign
8224      the pointer values */
8225   switch (p_type)
8226     {
8227
8228     case POINTER:
8229     case IPOINTER:
8230       genNearPointerGet (left, result, ic);
8231       break;
8232
8233     case PPOINTER:
8234       genPagedPointerGet (left, result, ic);
8235       break;
8236
8237     case FPOINTER:
8238       genFarPointerGet (left, result, ic);
8239       break;
8240
8241     case CPOINTER:
8242       emitcodePointerGet (left, result, ic);
8243       break;
8244
8245     case GPOINTER:
8246       genGenPointerGet (left, result, ic);
8247       break;
8248     }
8249
8250 }
8251
8252 /*-----------------------------------------------------------------*/
8253 /* genPackBits - generates code for packed bit storage             */
8254 /*-----------------------------------------------------------------*/
8255 static void
8256 genPackBits (sym_link * etype,
8257              operand * right,
8258              char *rname, int p_type)
8259 {
8260   int shCount = 0;
8261   int offset = 0;
8262   int rLen = 0;
8263   int blen, bstr;
8264   char *l;
8265
8266   blen = SPEC_BLEN (etype);
8267   bstr = SPEC_BSTR (etype);
8268
8269   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8270   MOVA (l);
8271
8272   /* if the bit lenth is less than or    */
8273   /* it exactly fits a byte then         */
8274   if (SPEC_BLEN (etype) <= 8)
8275     {
8276       shCount = SPEC_BSTR (etype);
8277
8278       /* shift left acc */
8279       AccLsh (shCount);
8280
8281       if (SPEC_BLEN (etype) < 8)
8282         {                       /* if smaller than a byte */
8283
8284
8285           switch (p_type)
8286             {
8287             case POINTER:
8288               emitcode ("mov", "b,a");
8289               emitcode ("mov", "a,@%s", rname);
8290               break;
8291
8292             case FPOINTER:
8293               emitcode ("mov", "b,a");
8294               emitcode ("movx", "a,@dptr");
8295               break;
8296
8297             case GPOINTER:
8298               emitcode ("push", "b");
8299               emitcode ("push", "acc");
8300               emitcode ("lcall", "__gptrget");
8301               emitcode ("pop", "b");
8302               break;
8303             }
8304
8305           emitcode ("anl", "a,#0x%02x", (unsigned char)
8306                     ((unsigned char) (0xFF << (blen + bstr)) |
8307                      (unsigned char) (0xFF >> (8 - bstr))));
8308           emitcode ("orl", "a,b");
8309           if (p_type == GPOINTER)
8310             emitcode ("pop", "b");
8311         }
8312     }
8313
8314   switch (p_type)
8315     {
8316     case POINTER:
8317       emitcode ("mov", "@%s,a", rname);
8318       break;
8319
8320     case FPOINTER:
8321       emitcode ("movx", "@dptr,a");
8322       break;
8323
8324     case GPOINTER:
8325       emitcode ("lcall", "__gptrput");
8326       break;
8327     }
8328
8329   /* if we r done */
8330   if (SPEC_BLEN (etype) <= 8)
8331     return;
8332
8333   emitcode ("inc", "%s", rname);
8334   rLen = SPEC_BLEN (etype);
8335
8336   /* now generate for lengths greater than one byte */
8337   while (1)
8338     {
8339
8340       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8341
8342       rLen -= 8;
8343       if (rLen < 8)
8344         break;
8345
8346       switch (p_type)
8347         {
8348         case POINTER:
8349           if (*l == '@')
8350             {
8351               MOVA (l);
8352               emitcode ("mov", "@%s,a", rname);
8353             }
8354           else
8355             emitcode ("mov", "@%s,%s", rname, l);
8356           break;
8357
8358         case FPOINTER:
8359           MOVA (l);
8360           emitcode ("movx", "@dptr,a");
8361           break;
8362
8363         case GPOINTER:
8364           MOVA (l);
8365           emitcode ("lcall", "__gptrput");
8366           break;
8367         }
8368       emitcode ("inc", "%s", rname);
8369     }
8370
8371   MOVA (l);
8372
8373   /* last last was not complete */
8374   if (rLen)
8375     {
8376       /* save the byte & read byte */
8377       switch (p_type)
8378         {
8379         case POINTER:
8380           emitcode ("mov", "b,a");
8381           emitcode ("mov", "a,@%s", rname);
8382           break;
8383
8384         case FPOINTER:
8385           emitcode ("mov", "b,a");
8386           emitcode ("movx", "a,@dptr");
8387           break;
8388
8389         case GPOINTER:
8390           emitcode ("push", "b");
8391           emitcode ("push", "acc");
8392           emitcode ("lcall", "__gptrget");
8393           emitcode ("pop", "b");
8394           break;
8395         }
8396
8397       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8398       emitcode ("orl", "a,b");
8399     }
8400
8401   if (p_type == GPOINTER)
8402     emitcode ("pop", "b");
8403
8404   switch (p_type)
8405     {
8406
8407     case POINTER:
8408       emitcode ("mov", "@%s,a", rname);
8409       break;
8410
8411     case FPOINTER:
8412       emitcode ("movx", "@dptr,a");
8413       break;
8414
8415     case GPOINTER:
8416       emitcode ("lcall", "__gptrput");
8417       break;
8418     }
8419 }
8420 /*-----------------------------------------------------------------*/
8421 /* genDataPointerSet - remat pointer to data space                 */
8422 /*-----------------------------------------------------------------*/
8423 static void
8424 genDataPointerSet (operand * right,
8425                    operand * result,
8426                    iCode * ic)
8427 {
8428   int size, offset = 0;
8429   char *l, buffer[256];
8430
8431   aopOp (right, ic, FALSE, FALSE);
8432
8433   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8434   size = AOP_SIZE (right);
8435   while (size--)
8436     {
8437       if (offset)
8438         sprintf (buffer, "(%s + %d)", l + 1, offset);
8439       else
8440         sprintf (buffer, "%s", l + 1);
8441       emitcode ("mov", "%s,%s", buffer,
8442                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8443     }
8444
8445   freeAsmop (right, NULL, ic, TRUE);
8446   freeAsmop (result, NULL, ic, TRUE);
8447 }
8448
8449 /*-----------------------------------------------------------------*/
8450 /* genNearPointerSet - emitcode for near pointer put                */
8451 /*-----------------------------------------------------------------*/
8452 static void
8453 genNearPointerSet (operand * right,
8454                    operand * result,
8455                    iCode * ic)
8456 {
8457   asmop *aop = NULL;
8458   regs *preg = NULL;
8459   char *rname, *l;
8460   sym_link *retype, *letype;
8461   sym_link *ptype = operandType (result);
8462
8463   retype = getSpec (operandType (right));
8464   letype = getSpec (ptype);
8465
8466   aopOp (result, ic, FALSE, FALSE);
8467
8468   /* if the result is rematerializable &
8469      in data space & not a bit variable */
8470   if (AOP_TYPE (result) == AOP_IMMD &&
8471       DCL_TYPE (ptype) == POINTER &&
8472       !IS_BITVAR (retype) &&
8473       !IS_BITVAR (letype))
8474     {
8475       genDataPointerSet (right, result, ic);
8476       return;
8477     }
8478
8479   /* if the value is already in a pointer register
8480      then don't need anything more */
8481   if (!AOP_INPREG (AOP (result)))
8482     {
8483       /* otherwise get a free pointer register */
8484       aop = newAsmop (0);
8485       preg = getFreePtr (ic, &aop, FALSE);
8486       emitcode ("mov", "%s,%s",
8487                 preg->name,
8488                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8489       rname = preg->name;
8490     }
8491   else
8492     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8493
8494   freeAsmop (result, NULL, ic, TRUE);
8495   aopOp (right, ic, FALSE, FALSE);
8496
8497   /* if bitfield then unpack the bits */
8498   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8499     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8500   else
8501     {
8502       /* we have can just get the values */
8503       int size = AOP_SIZE (right);
8504       int offset = 0;
8505
8506       while (size--)
8507         {
8508           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8509           if (*l == '@')
8510             {
8511               MOVA (l);
8512               emitcode ("mov", "@%s,a", rname);
8513             }
8514           else
8515             emitcode ("mov", "@%s,%s", rname, l);
8516           if (size)
8517             emitcode ("inc", "%s", rname);
8518           offset++;
8519         }
8520     }
8521
8522   /* now some housekeeping stuff */
8523   if (aop)
8524     {
8525       /* we had to allocate for this iCode */
8526       freeAsmop (NULL, aop, ic, TRUE);
8527     }
8528   else
8529     {
8530       /* we did not allocate which means left
8531          already in a pointer register, then
8532          if size > 0 && this could be used again
8533          we have to point it back to where it
8534          belongs */
8535       if (AOP_SIZE (right) > 1 &&
8536           !OP_SYMBOL (result)->remat &&
8537           (OP_SYMBOL (result)->liveTo > ic->seq ||
8538            ic->depth))
8539         {
8540           int size = AOP_SIZE (right) - 1;
8541           while (size--)
8542             emitcode ("dec", "%s", rname);
8543         }
8544     }
8545
8546   /* done */
8547   freeAsmop (right, NULL, ic, TRUE);
8548
8549
8550 }
8551
8552 /*-----------------------------------------------------------------*/
8553 /* genPagedPointerSet - emitcode for Paged pointer put             */
8554 /*-----------------------------------------------------------------*/
8555 static void
8556 genPagedPointerSet (operand * right,
8557                     operand * result,
8558                     iCode * ic)
8559 {
8560   asmop *aop = NULL;
8561   regs *preg = NULL;
8562   char *rname, *l;
8563   sym_link *retype, *letype;
8564
8565   retype = getSpec (operandType (right));
8566   letype = getSpec (operandType (result));
8567
8568   aopOp (result, ic, FALSE, FALSE);
8569
8570   /* if the value is already in a pointer register
8571      then don't need anything more */
8572   if (!AOP_INPREG (AOP (result)))
8573     {
8574       /* otherwise get a free pointer register */
8575       aop = newAsmop (0);
8576       preg = getFreePtr (ic, &aop, FALSE);
8577       emitcode ("mov", "%s,%s",
8578                 preg->name,
8579                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8580       rname = preg->name;
8581     }
8582   else
8583     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8584
8585   freeAsmop (result, NULL, ic, TRUE);
8586   aopOp (right, ic, FALSE, FALSE);
8587
8588   /* if bitfield then unpack the bits */
8589   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8590     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8591   else
8592     {
8593       /* we have can just get the values */
8594       int size = AOP_SIZE (right);
8595       int offset = 0;
8596
8597       while (size--)
8598         {
8599           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8600
8601           MOVA (l);
8602           emitcode ("movx", "@%s,a", rname);
8603
8604           if (size)
8605             emitcode ("inc", "%s", rname);
8606
8607           offset++;
8608         }
8609     }
8610
8611   /* now some housekeeping stuff */
8612   if (aop)
8613     {
8614       /* we had to allocate for this iCode */
8615       freeAsmop (NULL, aop, ic, TRUE);
8616     }
8617   else
8618     {
8619       /* we did not allocate which means left
8620          already in a pointer register, then
8621          if size > 0 && this could be used again
8622          we have to point it back to where it
8623          belongs */
8624       if (AOP_SIZE (right) > 1 &&
8625           !OP_SYMBOL (result)->remat &&
8626           (OP_SYMBOL (result)->liveTo > ic->seq ||
8627            ic->depth))
8628         {
8629           int size = AOP_SIZE (right) - 1;
8630           while (size--)
8631             emitcode ("dec", "%s", rname);
8632         }
8633     }
8634
8635   /* done */
8636   freeAsmop (right, NULL, ic, TRUE);
8637
8638
8639 }
8640
8641 /*-----------------------------------------------------------------*/
8642 /* genFarPointerSet - set value from far space                     */
8643 /*-----------------------------------------------------------------*/
8644 static void
8645 genFarPointerSet (operand * right,
8646                   operand * result, iCode * ic)
8647 {
8648   int size, offset;
8649   sym_link *retype = getSpec (operandType (right));
8650   sym_link *letype = getSpec (operandType (result));
8651
8652   aopOp (result, ic, FALSE, FALSE);
8653
8654   /* if the operand is already in dptr
8655      then we do nothing else we move the value to dptr */
8656   if (AOP_TYPE (result) != AOP_STR)
8657     {
8658       /* if this is remateriazable */
8659       if (AOP_TYPE (result) == AOP_IMMD)
8660         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8661       else
8662         {
8663           /* we need to get it byte by byte */
8664           _startLazyDPSEvaluation ();
8665           if (AOP_TYPE (result) != AOP_DPTR)
8666             {
8667               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8668               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8669               emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8670             }
8671           else
8672             {
8673               /* We need to generate a load to DPTR indirect through DPTR. */
8674               D (emitcode (";", "genFarPointerSet -- indirection special case.");
8675                 );
8676               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8677               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8678               emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8679               emitcode ("pop", "dph");
8680               emitcode ("pop", "dpl");
8681             }
8682           _endLazyDPSEvaluation ();
8683         }
8684     }
8685   /* so dptr know contains the address */
8686   freeAsmop (result, NULL, ic, TRUE);
8687   aopOp (right, ic, FALSE, TRUE);
8688
8689   /* if bit then unpack */
8690   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8691     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8692   else
8693     {
8694       size = AOP_SIZE (right);
8695       offset = 0;
8696
8697       _startLazyDPSEvaluation ();
8698       while (size--)
8699         {
8700           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8701           MOVA (l);
8702
8703           genSetDPTR (0);
8704           _flushLazyDPS ();
8705
8706           emitcode ("movx", "@dptr,a");
8707           if (size)
8708             emitcode ("inc", "dptr");
8709         }
8710       _endLazyDPSEvaluation ();
8711     }
8712
8713   freeAsmop (right, NULL, ic, TRUE);
8714 }
8715
8716 /*-----------------------------------------------------------------*/
8717 /* genGenPointerSet - set value from generic pointer space         */
8718 /*-----------------------------------------------------------------*/
8719 static void
8720 genGenPointerSet (operand * right,
8721                   operand * result, iCode * ic)
8722 {
8723   int size, offset;
8724   sym_link *retype = getSpec (operandType (right));
8725   sym_link *letype = getSpec (operandType (result));
8726
8727   aopOp (result, ic, FALSE, TRUE);
8728
8729   /* if the operand is already in dptr
8730      then we do nothing else we move the value to dptr */
8731   if (AOP_TYPE (result) != AOP_STR)
8732     {
8733       _startLazyDPSEvaluation ();
8734       /* if this is remateriazable */
8735       if (AOP_TYPE (result) == AOP_IMMD)
8736         {
8737           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8738           emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8739         }
8740       else
8741         {                       /* we need to get it byte by byte */
8742           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8743           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8744           emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8745           emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8746         }
8747       _endLazyDPSEvaluation ();
8748     }
8749   /* so dptr know contains the address */
8750   freeAsmop (result, NULL, ic, TRUE);
8751   aopOp (right, ic, FALSE, TRUE);
8752
8753   /* if bit then unpack */
8754   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8755     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8756   else
8757     {
8758       size = AOP_SIZE (right);
8759       offset = 0;
8760
8761       _startLazyDPSEvaluation ();
8762       while (size--)
8763         {
8764           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8765           MOVA (l);
8766
8767           genSetDPTR (0);
8768           _flushLazyDPS ();
8769
8770           emitcode ("lcall", "__gptrput");
8771           if (size)
8772             emitcode ("inc", "dptr");
8773         }
8774       _endLazyDPSEvaluation ();
8775     }
8776
8777   freeAsmop (right, NULL, ic, TRUE);
8778 }
8779
8780 /*-----------------------------------------------------------------*/
8781 /* genPointerSet - stores the value into a pointer location        */
8782 /*-----------------------------------------------------------------*/
8783 static void
8784 genPointerSet (iCode * ic)
8785 {
8786   operand *right, *result;
8787   sym_link *type, *etype;
8788   int p_type;
8789
8790   D (emitcode (";", "genPointerSet ");
8791     );
8792
8793   right = IC_RIGHT (ic);
8794   result = IC_RESULT (ic);
8795
8796   /* depending on the type of pointer we need to
8797      move it to the correct pointer register */
8798   type = operandType (result);
8799   etype = getSpec (type);
8800   /* if left is of type of pointer then it is simple */
8801   if (IS_PTR (type) && !IS_FUNC (type->next))
8802     {
8803       p_type = DCL_TYPE (type);
8804     }
8805   else
8806     {
8807       /* we have to go by the storage class */
8808       p_type = PTR_TYPE (SPEC_OCLS (etype));
8809     }
8810
8811   /* now that we have the pointer type we assign
8812      the pointer values */
8813   switch (p_type)
8814     {
8815
8816     case POINTER:
8817     case IPOINTER:
8818       genNearPointerSet (right, result, ic);
8819       break;
8820
8821     case PPOINTER:
8822       genPagedPointerSet (right, result, ic);
8823       break;
8824
8825     case FPOINTER:
8826       genFarPointerSet (right, result, ic);
8827       break;
8828
8829     case GPOINTER:
8830       genGenPointerSet (right, result, ic);
8831       break;
8832     }
8833
8834 }
8835
8836 /*-----------------------------------------------------------------*/
8837 /* genIfx - generate code for Ifx statement                        */
8838 /*-----------------------------------------------------------------*/
8839 static void
8840 genIfx (iCode * ic, iCode * popIc)
8841 {
8842   operand *cond = IC_COND (ic);
8843   int isbit = 0;
8844
8845   D (emitcode (";", "genIfx "););
8846
8847   aopOp (cond, ic, FALSE, FALSE);
8848
8849   /* get the value into acc */
8850   if (AOP_TYPE (cond) != AOP_CRY)
8851     toBoolean (cond);
8852   else
8853     isbit = 1;
8854   /* the result is now in the accumulator */
8855   freeAsmop (cond, NULL, ic, TRUE);
8856
8857   /* if there was something to be popped then do it */
8858   if (popIc)
8859     genIpop (popIc);
8860
8861   /* if the condition is  a bit variable */
8862   if (isbit && IS_ITEMP (cond) &&
8863       SPIL_LOC (cond))
8864     genIfxJump (ic, SPIL_LOC (cond)->rname);
8865   else if (isbit && !IS_ITEMP (cond))
8866     genIfxJump (ic, OP_SYMBOL (cond)->rname);
8867   else
8868     genIfxJump (ic, "a");
8869
8870   ic->generated = 1;
8871 }
8872
8873 /*-----------------------------------------------------------------*/
8874 /* genAddrOf - generates code for address of                       */
8875 /*-----------------------------------------------------------------*/
8876 static void
8877 genAddrOf (iCode * ic)
8878 {
8879   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8880   int size, offset;
8881
8882   D (emitcode (";", "genAddrOf ");
8883     );
8884
8885   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8886
8887   /* if the operand is on the stack then we
8888      need to get the stack offset of this
8889      variable */
8890   if (sym->onStack)
8891     {
8892       /* if it has an offset then we need to compute
8893          it */
8894       if (sym->stack)
8895         {
8896           emitcode ("mov", "a,_bp");
8897           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8898           aopPut (AOP (IC_RESULT (ic)), "a", 0);
8899         }
8900       else
8901         {
8902           /* we can just move _bp */
8903           aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8904         }
8905       /* fill the result with zero */
8906       size = AOP_SIZE (IC_RESULT (ic)) - 1;
8907
8908
8909       if (options.stack10bit && size < (FPTRSIZE - 1))
8910         {
8911           fprintf (stderr,
8912                    "*** warning: pointer to stack var truncated.\n");
8913         }
8914
8915       offset = 1;
8916       while (size--)
8917         {
8918           /* Yuck! */
8919           if (options.stack10bit && offset == 2)
8920             {
8921               aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8922             }
8923           else
8924             {
8925               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8926             }
8927         }
8928
8929       goto release;
8930     }
8931
8932   /* object not on stack then we need the name */
8933   size = AOP_SIZE (IC_RESULT (ic));
8934   offset = 0;
8935
8936   while (size--)
8937     {
8938       char s[SDCC_NAME_MAX];
8939       if (offset)
8940         sprintf (s, "#(%s >> %d)",
8941                  sym->rname,
8942                  offset * 8);
8943       else
8944         sprintf (s, "#%s", sym->rname);
8945       aopPut (AOP (IC_RESULT (ic)), s, offset++);
8946     }
8947
8948 release:
8949   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8950
8951 }
8952
8953 /*-----------------------------------------------------------------*/
8954 /* genFarFarAssign - assignment when both are in far space         */
8955 /*-----------------------------------------------------------------*/
8956 static void
8957 genFarFarAssign (operand * result, operand * right, iCode * ic)
8958 {
8959   int size = AOP_SIZE (right);
8960   int offset = 0;
8961   symbol *rSym = NULL;
8962
8963   if (size == 1)
8964   {
8965       /* quick & easy case. */
8966       D(emitcode(";","genFarFarAssign (1 byte case)"););      
8967       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
8968       freeAsmop (right, NULL, ic, FALSE);
8969       /* now assign DPTR to result */
8970       _G.accInUse++;
8971       aopOp(result, ic, FALSE, FALSE);
8972       _G.accInUse--;
8973       aopPut(AOP(result), "a", 0);
8974       freeAsmop(result, NULL, ic, FALSE);
8975       return;
8976   }
8977   
8978   /* See if we've got an underlying symbol to abuse. */
8979   if (IS_SYMOP(result) && OP_SYMBOL(result))
8980   {
8981       if (IS_TRUE_SYMOP(result))
8982       {
8983           rSym = OP_SYMBOL(result);
8984       }
8985       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
8986       {
8987           rSym = OP_SYMBOL(result)->usl.spillLoc;
8988       }
8989   }
8990              
8991   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
8992   {
8993       /* We can use the '390 auto-toggle feature to good effect here. */
8994       
8995       D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
8996       emitcode("mov", "dps, #0x21");    /* Select DPTR2 & auto-toggle. */
8997       emitcode ("mov", "dptr,#%s", rSym->rname); 
8998       /* DP2 = result, DP1 = right, DP1 is current. */
8999       while (size)
9000       {
9001           emitcode("movx", "a,@dptr");
9002           emitcode("movx", "@dptr,a");
9003           if (--size)
9004           {
9005                emitcode("inc", "dptr");
9006                emitcode("inc", "dptr");
9007           }
9008       }
9009       emitcode("mov", "dps, #0");
9010       freeAsmop (right, NULL, ic, FALSE);
9011   }
9012   else
9013   {
9014       D (emitcode (";", "genFarFarAssign"););
9015       aopOp (result, ic, TRUE, TRUE);
9016
9017       _startLazyDPSEvaluation ();
9018       
9019       while (size--)
9020         {
9021           aopPut (AOP (result),
9022                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9023           offset++;
9024         }
9025       _endLazyDPSEvaluation ();
9026       freeAsmop (result, NULL, ic, FALSE);
9027       freeAsmop (right, NULL, ic, FALSE);
9028   }
9029 }
9030
9031 /*-----------------------------------------------------------------*/
9032 /* genAssign - generate code for assignment                        */
9033 /*-----------------------------------------------------------------*/
9034 static void
9035 genAssign (iCode * ic)
9036 {
9037   operand *result, *right;
9038   int size, offset;
9039   unsigned long lit = 0L;
9040
9041   D (emitcode (";", "genAssign ");
9042     );
9043
9044   result = IC_RESULT (ic);
9045   right = IC_RIGHT (ic);
9046
9047   /* if they are the same */
9048   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9049     return;
9050
9051   aopOp (right, ic, FALSE, FALSE);
9052
9053   emitcode (";", "genAssign: resultIsFar = %s",
9054             isOperandInFarSpace (result) ?
9055             "TRUE" : "FALSE");
9056
9057   /* special case both in far space */
9058   if ((AOP_TYPE (right) == AOP_DPTR ||
9059        AOP_TYPE (right) == AOP_DPTR2) &&
9060   /* IS_TRUE_SYMOP(result)       && */
9061       isOperandInFarSpace (result))
9062     {
9063       genFarFarAssign (result, right, ic);
9064       return;
9065     }
9066
9067   aopOp (result, ic, TRUE, FALSE);
9068
9069   /* if they are the same registers */
9070   if (sameRegs (AOP (right), AOP (result)))
9071     goto release;
9072
9073   /* if the result is a bit */
9074   if (AOP_TYPE (result) == AOP_CRY)
9075     {
9076
9077       /* if the right size is a literal then
9078          we know what the value is */
9079       if (AOP_TYPE (right) == AOP_LIT)
9080         {
9081           if (((int) operandLitValue (right)))
9082             aopPut (AOP (result), one, 0);
9083           else
9084             aopPut (AOP (result), zero, 0);
9085           goto release;
9086         }
9087
9088       /* the right is also a bit variable */
9089       if (AOP_TYPE (right) == AOP_CRY)
9090         {
9091           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9092           aopPut (AOP (result), "c", 0);
9093           goto release;
9094         }
9095
9096       /* we need to or */
9097       toBoolean (right);
9098       aopPut (AOP (result), "a", 0);
9099       goto release;
9100     }
9101
9102   /* bit variables done */
9103   /* general case */
9104   size = AOP_SIZE (result);
9105   offset = 0;
9106   if (AOP_TYPE (right) == AOP_LIT)
9107     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9108
9109   if ((size > 1) &&
9110       (AOP_TYPE (result) != AOP_REG) &&
9111       (AOP_TYPE (right) == AOP_LIT) &&
9112       !IS_FLOAT (operandType (right)))
9113     {
9114       _startLazyDPSEvaluation ();
9115       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9116         {
9117           aopPut (AOP (result),
9118                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9119                   offset);
9120           offset++;
9121           size--;
9122         }
9123       /* And now fill the rest with zeros. */
9124       if (size)
9125         {
9126           emitcode ("clr", "a");
9127         }
9128       while (size--)
9129         {
9130           aopPut (AOP (result), "a", offset++);
9131         }
9132       _endLazyDPSEvaluation ();
9133     }
9134   else
9135     {
9136       _startLazyDPSEvaluation ();
9137       while (size--)
9138         {
9139           aopPut (AOP (result),
9140                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9141                   offset);
9142           offset++;
9143         }
9144       _endLazyDPSEvaluation ();
9145     }
9146
9147 release:
9148   freeAsmop (right, NULL, ic, FALSE);
9149   freeAsmop (result, NULL, ic, TRUE);
9150 }
9151
9152 /*-----------------------------------------------------------------*/
9153 /* genJumpTab - generates code for jump table                      */
9154 /*-----------------------------------------------------------------*/
9155 static void
9156 genJumpTab (iCode * ic)
9157 {
9158   symbol *jtab;
9159   char *l;
9160
9161   D (emitcode (";", "genJumpTab ");
9162     );
9163
9164   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9165   /* get the condition into accumulator */
9166   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9167   MOVA (l);
9168   /* multiply by four! */
9169   emitcode ("add", "a,acc");
9170   emitcode ("add", "a,acc");
9171   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9172
9173   jtab = newiTempLabel (NULL);
9174   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9175   emitcode ("jmp", "@a+dptr");
9176   emitcode ("", "%05d$:", jtab->key + 100);
9177   /* now generate the jump labels */
9178   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9179        jtab = setNextItem (IC_JTLABELS (ic)))
9180     emitcode ("ljmp", "%05d$", jtab->key + 100);
9181
9182 }
9183
9184 /*-----------------------------------------------------------------*/
9185 /* genCast - gen code for casting                                  */
9186 /*-----------------------------------------------------------------*/
9187 static void
9188 genCast (iCode * ic)
9189 {
9190   operand *result = IC_RESULT (ic);
9191   sym_link *ctype = operandType (IC_LEFT (ic));
9192   sym_link *rtype = operandType (IC_RIGHT (ic));
9193   operand *right = IC_RIGHT (ic);
9194   int size, offset;
9195
9196   D (emitcode (";", "genCast ");
9197     );
9198
9199   /* if they are equivalent then do nothing */
9200   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9201     return;
9202
9203   aopOp (right, ic, FALSE, FALSE);
9204   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9205
9206   /* if the result is a bit */
9207   if (AOP_TYPE (result) == AOP_CRY)
9208     {
9209       /* if the right size is a literal then
9210          we know what the value is */
9211       if (AOP_TYPE (right) == AOP_LIT)
9212         {
9213           if (((int) operandLitValue (right)))
9214             aopPut (AOP (result), one, 0);
9215           else
9216             aopPut (AOP (result), zero, 0);
9217
9218           goto release;
9219         }
9220
9221       /* the right is also a bit variable */
9222       if (AOP_TYPE (right) == AOP_CRY)
9223         {
9224           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9225           aopPut (AOP (result), "c", 0);
9226           goto release;
9227         }
9228
9229       /* we need to or */
9230       toBoolean (right);
9231       aopPut (AOP (result), "a", 0);
9232       goto release;
9233     }
9234
9235   /* if they are the same size : or less */
9236   if (AOP_SIZE (result) <= AOP_SIZE (right))
9237     {
9238
9239       /* if they are in the same place */
9240       if (sameRegs (AOP (right), AOP (result)))
9241         goto release;
9242
9243       /* if they in different places then copy */
9244       size = AOP_SIZE (result);
9245       offset = 0;
9246       _startLazyDPSEvaluation ();
9247       while (size--)
9248         {
9249           aopPut (AOP (result),
9250                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9251                   offset);
9252           offset++;
9253         }
9254       _endLazyDPSEvaluation ();
9255       goto release;
9256     }
9257
9258
9259   /* if the result is of type pointer */
9260   if (IS_PTR (ctype))
9261     {
9262
9263       int p_type;
9264       sym_link *type = operandType (right);
9265
9266       /* pointer to generic pointer */
9267       if (IS_GENPTR (ctype))
9268         {
9269           char *l = zero;
9270
9271           if (IS_PTR (type))
9272             {
9273               p_type = DCL_TYPE (type);
9274             }
9275           else
9276             {
9277 #if OLD_CAST_BEHAVIOR
9278               /* KV: we are converting a non-pointer type to
9279                * a generic pointer. This (ifdef'd out) code
9280                * says that the resulting generic pointer
9281                * should have the same class as the storage
9282                * location of the non-pointer variable.
9283                *
9284                * For example, converting an int (which happens
9285                * to be stored in DATA space) to a pointer results
9286                * in a DATA generic pointer; if the original int
9287                * in XDATA space, so will be the resulting pointer.
9288                *
9289                * I don't like that behavior, and thus this change:
9290                * all such conversions will be forced to XDATA and
9291                * throw a warning. If you want some non-XDATA
9292                * type, or you want to suppress the warning, you
9293                * must go through an intermediate cast, like so:
9294                *
9295                * char _generic *gp = (char _xdata *)(intVar);
9296                */
9297               sym_link *etype = getSpec (type);
9298
9299               /* we have to go by the storage class */
9300               if (SPEC_OCLS (etype) != generic)
9301                 {
9302                   p_type = PTR_TYPE (SPEC_OCLS (etype));
9303                 }
9304               else
9305 #endif
9306                 {
9307                   /* Converting unknown class (i.e. register variable)
9308                    * to generic pointer. This is not good, but
9309                    * we'll make a guess (and throw a warning).
9310                    */
9311                   p_type = FPOINTER;
9312                   werror (W_INT_TO_GEN_PTR_CAST);
9313                 }
9314             }
9315
9316           /* the first two bytes are known */
9317           size = GPTRSIZE - 1;
9318           offset = 0;
9319           _startLazyDPSEvaluation ();
9320           while (size--)
9321             {
9322               aopPut (AOP (result),
9323                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9324                       offset);
9325               offset++;
9326             }
9327           _endLazyDPSEvaluation ();
9328
9329           /* the last byte depending on type */
9330           switch (p_type)
9331             {
9332             case IPOINTER:
9333             case POINTER:
9334               l = zero;
9335               break;
9336             case FPOINTER:
9337               l = one;
9338               break;
9339             case CPOINTER:
9340               l = "#0x02";
9341               break;
9342             case PPOINTER:
9343               l = "#0x03";
9344               break;
9345
9346             default:
9347               /* this should never happen */
9348               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9349                       "got unknown pointer type");
9350               exit (1);
9351             }
9352           aopPut (AOP (result), l, GPTRSIZE - 1);
9353           goto release;
9354         }
9355
9356       /* just copy the pointers */
9357       size = AOP_SIZE (result);
9358       offset = 0;
9359       _startLazyDPSEvaluation ();
9360       while (size--)
9361         {
9362           aopPut (AOP (result),
9363                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9364                   offset);
9365           offset++;
9366         }
9367       _endLazyDPSEvaluation ();
9368       goto release;
9369     }
9370
9371   /* so we now know that the size of destination is greater
9372      than the size of the source */
9373   /* we move to result for the size of source */
9374   size = AOP_SIZE (right);
9375   offset = 0;
9376   _startLazyDPSEvaluation ();
9377   while (size--)
9378     {
9379       aopPut (AOP (result),
9380               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9381               offset);
9382       offset++;
9383     }
9384   _endLazyDPSEvaluation ();
9385
9386   /* now depending on the sign of the source && destination */
9387   size = AOP_SIZE (result) - AOP_SIZE (right);
9388   /* if unsigned or not an integral type */
9389   /* also, if the source is a bit, we don't need to sign extend, because
9390    * it can't possibly have set the sign bit.
9391    */
9392   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9393     {
9394       while (size--)
9395         {
9396           aopPut (AOP (result), zero, offset++);
9397         }
9398     }
9399   else
9400     {
9401       /* we need to extend the sign :{ */
9402       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9403                         FALSE, FALSE, TRUE);
9404       MOVA (l);
9405       emitcode ("rlc", "a");
9406       emitcode ("subb", "a,acc");
9407       while (size--)
9408         aopPut (AOP (result), "a", offset++);
9409     }
9410
9411   /* we are done hurray !!!! */
9412
9413 release:
9414   freeAsmop (right, NULL, ic, TRUE);
9415   freeAsmop (result, NULL, ic, TRUE);
9416
9417 }
9418
9419 /*-----------------------------------------------------------------*/
9420 /* genDjnz - generate decrement & jump if not zero instrucion      */
9421 /*-----------------------------------------------------------------*/
9422 static int
9423 genDjnz (iCode * ic, iCode * ifx)
9424 {
9425   symbol *lbl, *lbl1;
9426   if (!ifx)
9427     return 0;
9428
9429   /* if the if condition has a false label
9430      then we cannot save */
9431   if (IC_FALSE (ifx))
9432     return 0;
9433
9434   /* if the minus is not of the form
9435      a = a - 1 */
9436   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9437       !IS_OP_LITERAL (IC_RIGHT (ic)))
9438     return 0;
9439
9440   if (operandLitValue (IC_RIGHT (ic)) != 1)
9441     return 0;
9442
9443   /* if the size of this greater than one then no
9444      saving */
9445   if (getSize (operandType (IC_RESULT (ic))) > 1)
9446     return 0;
9447
9448   /* otherwise we can save BIG */
9449   D(emitcode(";", "genDjnz"););
9450
9451   lbl = newiTempLabel (NULL);
9452   lbl1 = newiTempLabel (NULL);
9453
9454   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9455
9456   if (AOP_NEEDSACC(IC_RESULT(ic)))
9457   {
9458       /* If the result is accessed indirectly via
9459        * the accumulator, we must explicitly write
9460        * it back after the decrement.
9461        */
9462       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9463       
9464       if (strcmp(rByte, "a"))
9465       {
9466            /* Something is hopelessly wrong */
9467            fprintf(stderr, "*** warning: internal error at %s:%d\n",
9468                    __FILE__, __LINE__);
9469            /* We can just give up; the generated code will be inefficient,
9470             * but what the hey.
9471             */
9472            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9473            return 0;
9474       }
9475       emitcode ("dec", "%s", rByte);
9476       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9477       emitcode ("jnz", "%05d$", lbl->key + 100);
9478   }
9479   else if (IS_AOP_PREG (IC_RESULT (ic)))
9480     {
9481       emitcode ("dec", "%s",
9482                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9483       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9484       emitcode ("jnz", "%05d$", lbl->key + 100);
9485     }
9486   else
9487     {
9488       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9489                 lbl->key + 100);
9490     }
9491   emitcode ("sjmp", "%05d$", lbl1->key + 100);
9492   emitcode ("", "%05d$:", lbl->key + 100);
9493   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9494   emitcode ("", "%05d$:", lbl1->key + 100);
9495
9496   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9497   ifx->generated = 1;
9498   return 1;
9499 }
9500
9501 /*-----------------------------------------------------------------*/
9502 /* genReceive - generate code for a receive iCode                  */
9503 /*-----------------------------------------------------------------*/
9504 static void
9505 genReceive (iCode * ic)
9506 {
9507
9508   D (emitcode (";", "genReceive ");
9509     );
9510
9511   if (isOperandInFarSpace (IC_RESULT (ic)) &&
9512       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9513        IS_TRUE_SYMOP (IC_RESULT (ic))))
9514     {
9515       int size = getSize (operandType (IC_RESULT (ic)));
9516       int offset = fReturnSizeDS390 - size;
9517       while (size--)
9518         {
9519           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9520                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9521           offset++;
9522         }
9523       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9524       size = AOP_SIZE (IC_RESULT (ic));
9525       offset = 0;
9526       while (size--)
9527         {
9528           emitcode ("pop", "acc");
9529           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9530         }
9531
9532     }
9533   else
9534     {
9535       _G.accInUse++;
9536       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9537       _G.accInUse--;
9538       assignResultValue (IC_RESULT (ic));
9539     }
9540
9541   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9542 }
9543
9544 /*-----------------------------------------------------------------*/
9545 /* gen390Code - generate code for Dallas 390 based controllers     */
9546 /*-----------------------------------------------------------------*/
9547 void
9548 gen390Code (iCode * lic)
9549 {
9550   iCode *ic;
9551   int cln = 0;
9552
9553   lineHead = lineCurr = NULL;
9554
9555 #if 0
9556   //REMOVE ME!!!
9557   /* print the allocation information */
9558   if (allocInfo)
9559     printAllocInfo (currFunc, codeOutFile);
9560 #endif
9561   /* if debug information required */
9562   if (options.debug && currFunc)
9563     {
9564       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9565       _G.debugLine = 1;
9566       if (IS_STATIC (currFunc->etype))
9567         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9568       else
9569         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9570       _G.debugLine = 0;
9571     }
9572   /* stack pointer name */
9573   if (options.useXstack)
9574     spname = "_spx";
9575   else
9576     spname = "sp";
9577
9578
9579   for (ic = lic; ic; ic = ic->next)
9580     {
9581
9582       if (cln != ic->lineno)
9583         {
9584           if (options.debug)
9585             {
9586               _G.debugLine = 1;
9587               emitcode ("", "C$%s$%d$%d$%d ==.",
9588                         FileBaseName (ic->filename), ic->lineno,
9589                         ic->level, ic->block);
9590               _G.debugLine = 0;
9591             }
9592           emitcode (";", "%s %d", ic->filename, ic->lineno);
9593           cln = ic->lineno;
9594         }
9595       /* if the result is marked as
9596          spilt and rematerializable or code for
9597          this has already been generated then
9598          do nothing */
9599       if (resultRemat (ic) || ic->generated)
9600         continue;
9601
9602       /* depending on the operation */
9603       switch (ic->op)
9604         {
9605         case '!':
9606           genNot (ic);
9607           break;
9608
9609         case '~':
9610           genCpl (ic);
9611           break;
9612
9613         case UNARYMINUS:
9614           genUminus (ic);
9615           break;
9616
9617         case IPUSH:
9618           genIpush (ic);
9619           break;
9620
9621         case IPOP:
9622           /* IPOP happens only when trying to restore a
9623              spilt live range, if there is an ifx statement
9624              following this pop then the if statement might
9625              be using some of the registers being popped which
9626              would destory the contents of the register so
9627              we need to check for this condition and handle it */
9628           if (ic->next &&
9629               ic->next->op == IFX &&
9630               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9631             genIfx (ic->next, ic);
9632           else
9633             genIpop (ic);
9634           break;
9635
9636         case CALL:
9637           genCall (ic);
9638           break;
9639
9640         case PCALL:
9641           genPcall (ic);
9642           break;
9643
9644         case FUNCTION:
9645           genFunction (ic);
9646           break;
9647
9648         case ENDFUNCTION:
9649           genEndFunction (ic);
9650           break;
9651
9652         case RETURN:
9653           genRet (ic);
9654           break;
9655
9656         case LABEL:
9657           genLabel (ic);
9658           break;
9659
9660         case GOTO:
9661           genGoto (ic);
9662           break;
9663
9664         case '+':
9665           genPlus (ic);
9666           break;
9667
9668         case '-':
9669           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9670             genMinus (ic);
9671           break;
9672
9673         case '*':
9674           genMult (ic);
9675           break;
9676
9677         case '/':
9678           genDiv (ic);
9679           break;
9680
9681         case '%':
9682           genMod (ic);
9683           break;
9684
9685         case '>':
9686           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9687           break;
9688
9689         case '<':
9690           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9691           break;
9692
9693         case LE_OP:
9694         case GE_OP:
9695         case NE_OP:
9696
9697           /* note these two are xlated by algebraic equivalence
9698              during parsing SDCC.y */
9699           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9700                   "got '>=' or '<=' shouldn't have come here");
9701           break;
9702
9703         case EQ_OP:
9704           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9705           break;
9706
9707         case AND_OP:
9708           genAndOp (ic);
9709           break;
9710
9711         case OR_OP:
9712           genOrOp (ic);
9713           break;
9714
9715         case '^':
9716           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9717           break;
9718
9719         case '|':
9720           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9721           break;
9722
9723         case BITWISEAND:
9724           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9725           break;
9726
9727         case INLINEASM:
9728           genInline (ic);
9729           break;
9730
9731         case RRC:
9732           genRRC (ic);
9733           break;
9734
9735         case RLC:
9736           genRLC (ic);
9737           break;
9738
9739         case GETHBIT:
9740           genGetHbit (ic);
9741           break;
9742
9743         case LEFT_OP:
9744           genLeftShift (ic);
9745           break;
9746
9747         case RIGHT_OP:
9748           genRightShift (ic);
9749           break;
9750
9751         case GET_VALUE_AT_ADDRESS:
9752           genPointerGet (ic);
9753           break;
9754
9755         case '=':
9756           if (POINTER_SET (ic))
9757             genPointerSet (ic);
9758           else
9759             genAssign (ic);
9760           break;
9761
9762         case IFX:
9763           genIfx (ic, NULL);
9764           break;
9765
9766         case ADDRESS_OF:
9767           genAddrOf (ic);
9768           break;
9769
9770         case JUMPTABLE:
9771           genJumpTab (ic);
9772           break;
9773
9774         case CAST:
9775           genCast (ic);
9776           break;
9777
9778         case RECEIVE:
9779           genReceive (ic);
9780           break;
9781
9782         case SEND:
9783           addSet (&_G.sendSet, ic);
9784           break;
9785
9786         default:
9787           ic = ic;
9788         }
9789     }
9790
9791
9792   /* now we are ready to call the
9793      peep hole optimizer */
9794   if (!options.nopeep)
9795     peepHole (&lineHead);
9796
9797   /* now do the actual printing */
9798   printLine (lineHead, codeOutFile);
9799   return;
9800 }