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