enable BETTER_LITERAL_SHIFT by default
[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
6669       if (size > 1)
6670         {
6671           if (shCount)
6672           {
6673             _endLazyDPSEvaluation();
6674             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6675             aopPut (AOP (result), zero, LSB);       
6676           }
6677           else
6678           {
6679             movLeft2Result (left, LSB, result, MSB16, 0);
6680             aopPut (AOP (result), zero, LSB);
6681             _endLazyDPSEvaluation();
6682           }
6683         }
6684         else
6685         {
6686           aopPut (AOP (result), zero, LSB);
6687           _endLazyDPSEvaluation();
6688         }
6689   }
6690
6691   /*  1 <= shCount <= 7 */
6692   else
6693     {
6694       if (size == 1)
6695       {
6696         shiftL1Left2Result (left, LSB, result, LSB, shCount);
6697       }
6698       else
6699       {
6700         shiftL2Left2Result (left, LSB, result, LSB, shCount);
6701       }
6702     }
6703 }
6704 #endif
6705
6706 #if 0
6707 //REMOVE ME!!!
6708 /*-----------------------------------------------------------------*/
6709 /* shiftLLong - shift left one long from left to result            */
6710 /* offl = LSB or MSB16                                             */
6711 /*-----------------------------------------------------------------*/
6712 static void
6713 shiftLLong (operand * left, operand * result, int offr)
6714 {
6715   char *l;
6716   int size = AOP_SIZE (result);
6717
6718   if (size >= LSB + offr)
6719     {
6720       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6721       MOVA (l);
6722       emitcode ("add", "a,acc");
6723       if (sameRegs (AOP (left), AOP (result)) &&
6724           size >= MSB16 + offr && offr != LSB)
6725         emitcode ("xch", "a,%s",
6726                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6727       else
6728         aopPut (AOP (result), "a", LSB + offr);
6729     }
6730
6731   if (size >= MSB16 + offr)
6732     {
6733       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6734         {
6735           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6736           MOVA (l);
6737         }
6738       emitcode ("rlc", "a");
6739       if (sameRegs (AOP (left), AOP (result)) &&
6740           size >= MSB24 + offr && offr != LSB)
6741         emitcode ("xch", "a,%s",
6742                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6743       else
6744         aopPut (AOP (result), "a", MSB16 + offr);
6745     }
6746
6747   if (size >= MSB24 + offr)
6748     {
6749       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6750         {
6751           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6752           MOVA (l);
6753         }
6754       emitcode ("rlc", "a");
6755       if (sameRegs (AOP (left), AOP (result)) &&
6756           size >= MSB32 + offr && offr != LSB)
6757         emitcode ("xch", "a,%s",
6758                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6759       else
6760         aopPut (AOP (result), "a", MSB24 + offr);
6761     }
6762
6763   if (size > MSB32 + offr)
6764     {
6765       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6766         {
6767           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6768           MOVA (l);
6769         }
6770       emitcode ("rlc", "a");
6771       aopPut (AOP (result), "a", MSB32 + offr);
6772     }
6773   if (offr != LSB)
6774     aopPut (AOP (result), zero, LSB);
6775 }
6776 #endif
6777
6778 #if 0
6779 //REMOVE ME!!!
6780 /*-----------------------------------------------------------------*/
6781 /* genlshFour - shift four byte by a known amount != 0             */
6782 /*-----------------------------------------------------------------*/
6783 static void
6784 genlshFour (operand * result, operand * left, int shCount)
6785 {
6786   int size;
6787
6788   D (emitcode (";", "genlshFour ");
6789     );
6790
6791   size = AOP_SIZE (result);
6792
6793   /* if shifting more that 3 bytes */
6794   if (shCount >= 24)
6795     {
6796       shCount -= 24;
6797       if (shCount)
6798         /* lowest order of left goes to the highest
6799            order of the destination */
6800         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6801       else
6802         movLeft2Result (left, LSB, result, MSB32, 0);
6803       aopPut (AOP (result), zero, LSB);
6804       aopPut (AOP (result), zero, MSB16);
6805       aopPut (AOP (result), zero, MSB24);
6806       return;
6807     }
6808
6809   /* more than two bytes */
6810   else if (shCount >= 16)
6811     {
6812       /* lower order two bytes goes to higher order two bytes */
6813       shCount -= 16;
6814       /* if some more remaining */
6815       if (shCount)
6816         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6817       else
6818         {
6819           movLeft2Result (left, MSB16, result, MSB32, 0);
6820           movLeft2Result (left, LSB, result, MSB24, 0);
6821         }
6822       aopPut (AOP (result), zero, MSB16);
6823       aopPut (AOP (result), zero, LSB);
6824       return;
6825     }
6826
6827   /* if more than 1 byte */
6828   else if (shCount >= 8)
6829     {
6830       /* lower order three bytes goes to higher order  three bytes */
6831       shCount -= 8;
6832       if (size == 2)
6833         {
6834           if (shCount)
6835             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6836           else
6837             movLeft2Result (left, LSB, result, MSB16, 0);
6838         }
6839       else
6840         {                       /* size = 4 */
6841           if (shCount == 0)
6842             {
6843               movLeft2Result (left, MSB24, result, MSB32, 0);
6844               movLeft2Result (left, MSB16, result, MSB24, 0);
6845               movLeft2Result (left, LSB, result, MSB16, 0);
6846               aopPut (AOP (result), zero, LSB);
6847             }
6848           else if (shCount == 1)
6849             shiftLLong (left, result, MSB16);
6850           else
6851             {
6852               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6853               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6854               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6855               aopPut (AOP (result), zero, LSB);
6856             }
6857         }
6858     }
6859
6860   /* 1 <= shCount <= 7 */
6861   else if (shCount <= 2)
6862     {
6863       shiftLLong (left, result, LSB);
6864       if (shCount == 2)
6865         shiftLLong (result, result, LSB);
6866     }
6867   /* 3 <= shCount <= 7, optimize */
6868   else
6869     {
6870       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6871       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6872       shiftL2Left2Result (left, LSB, result, LSB, shCount);
6873     }
6874 }
6875 #endif
6876
6877 #ifdef BETTER_LITERAL_SHIFT
6878 /*-----------------------------------------------------------------*/
6879 /* genLeftShiftLiteral - left shifting by known count              */
6880 /*-----------------------------------------------------------------*/
6881 static bool
6882 genLeftShiftLiteral (operand * left,
6883                      operand * right,
6884                      operand * result,
6885                      iCode * ic)
6886 {
6887   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6888   int size;
6889
6890   size = getSize (operandType (result));
6891
6892   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
6893
6894   /* We only handle certain easy cases so far. */
6895   if ((shCount != 0)
6896    && (shCount < (size * 8))
6897    && (size != 1)
6898    && (size != 2))
6899   {
6900       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
6901       return FALSE;
6902   }
6903
6904   freeAsmop (right, NULL, ic, TRUE);
6905
6906   aopOp(left, ic, FALSE, FALSE);
6907   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
6908
6909 #if 1 // debug spew
6910   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
6911   {
6912         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
6913         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
6914         {
6915            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
6916         }
6917   }
6918   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
6919   {
6920         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
6921         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
6922         {
6923            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
6924         }       
6925   }  
6926 #endif
6927   
6928 #if VIEW_SIZE
6929   emitcode ("; shift left ", "result %d, left %d", size,
6930             AOP_SIZE (left));
6931 #endif
6932
6933   /* I suppose that the left size >= result size */
6934   if (shCount == 0)
6935   {
6936         _startLazyDPSEvaluation();
6937         while (size--)
6938         {
6939           movLeft2Result (left, size, result, size, 0);
6940         }
6941         _endLazyDPSEvaluation();
6942   }
6943   else if (shCount >= (size * 8))
6944   {
6945     _startLazyDPSEvaluation();
6946     while (size--)
6947     {
6948       aopPut (AOP (result), zero, size);
6949     }
6950     _endLazyDPSEvaluation();
6951   }
6952   else
6953   {
6954       switch (size)
6955         {
6956         case 1:
6957           genlshOne (result, left, shCount);
6958           break;
6959
6960         case 2:
6961           genlshTwo (result, left, shCount);
6962           break;
6963 #if 0
6964         case 4:
6965           genlshFour (result, left, shCount);
6966           break;
6967 #endif
6968         default:
6969           fprintf(stderr, "*** ack! mystery literal shift!\n");   
6970           break;
6971         }
6972     }
6973   freeAsmop (left, NULL, ic, TRUE);
6974   freeAsmop (result, NULL, ic, TRUE);
6975   return TRUE;
6976 }
6977 #endif
6978
6979 /*-----------------------------------------------------------------*/
6980 /* genLeftShift - generates code for left shifting                 */
6981 /*-----------------------------------------------------------------*/
6982 static void
6983 genLeftShift (iCode * ic)
6984 {
6985   operand *left, *right, *result;
6986   int size, offset;
6987   char *l;
6988   symbol *tlbl, *tlbl1;
6989
6990   D (emitcode (";", "genLeftShift "););
6991
6992   right = IC_RIGHT (ic);
6993   left = IC_LEFT (ic);
6994   result = IC_RESULT (ic);
6995
6996   aopOp (right, ic, FALSE, FALSE);
6997
6998
6999 #ifdef BETTER_LITERAL_SHIFT
7000   /* if the shift count is known then do it
7001      as efficiently as possible */
7002   if (AOP_TYPE (right) == AOP_LIT)
7003     {
7004       if (genLeftShiftLiteral (left, right, result, ic))
7005       {
7006         return;
7007       }
7008     }
7009 #endif
7010
7011   /* shift count is unknown then we have to form
7012      a loop get the loop count in B : Note: we take
7013      only the lower order byte since shifting
7014      more that 32 bits make no sense anyway, ( the
7015      largest size of an object can be only 32 bits ) */
7016
7017   if (AOP_TYPE (right) == AOP_LIT)
7018   {
7019       /* Really should be handled by genLeftShiftLiteral,
7020        * but since I'm too lazy to fix that today, at least we can make
7021        * some small improvement.
7022        */
7023        emitcode("mov", "b,#0x%02x",
7024                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7025   }
7026   else
7027   {
7028         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7029         emitcode ("inc", "b");
7030   }
7031   freeAsmop (right, NULL, ic, TRUE);
7032   aopOp (left, ic, FALSE, FALSE);
7033   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7034
7035   /* now move the left to the result if they are not the
7036      same */
7037   if (!sameRegs (AOP (left), AOP (result)) &&
7038       AOP_SIZE (result) > 1)
7039     {
7040
7041       size = AOP_SIZE (result);
7042       offset = 0;
7043       _startLazyDPSEvaluation ();
7044       while (size--)
7045         {
7046           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7047           if (*l == '@' && (IS_AOP_PREG (result)))
7048             {
7049
7050               emitcode ("mov", "a,%s", l);
7051               aopPut (AOP (result), "a", offset);
7052             }
7053           else
7054             aopPut (AOP (result), l, offset);
7055           offset++;
7056         }
7057       _endLazyDPSEvaluation ();
7058     }
7059
7060   tlbl = newiTempLabel (NULL);
7061   size = AOP_SIZE (result);
7062   offset = 0;
7063   tlbl1 = newiTempLabel (NULL);
7064
7065   /* if it is only one byte then */
7066   if (size == 1)
7067     {
7068       symbol *tlbl1 = newiTempLabel (NULL);
7069
7070       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7071       MOVA (l);
7072       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7073       emitcode ("", "%05d$:", tlbl->key + 100);
7074       emitcode ("add", "a,acc");
7075       emitcode ("", "%05d$:", tlbl1->key + 100);
7076       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7077       aopPut (AOP (result), "a", 0);
7078       goto release;
7079     }
7080
7081   reAdjustPreg (AOP (result));
7082
7083   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7084   emitcode ("", "%05d$:", tlbl->key + 100);
7085   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7086   MOVA (l);
7087   emitcode ("add", "a,acc");
7088   aopPut (AOP (result), "a", offset++);
7089   _startLazyDPSEvaluation ();
7090   while (--size)
7091     {
7092       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7093       MOVA (l);
7094       emitcode ("rlc", "a");
7095       aopPut (AOP (result), "a", offset++);
7096     }
7097   _endLazyDPSEvaluation ();
7098   reAdjustPreg (AOP (result));
7099
7100   emitcode ("", "%05d$:", tlbl1->key + 100);
7101   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7102 release:
7103   freeAsmop (left, NULL, ic, TRUE);
7104   freeAsmop (result, NULL, ic, TRUE);
7105 }
7106
7107 #ifdef BETTER_LITERAL_SHIFT
7108 /*-----------------------------------------------------------------*/
7109 /* genrshOne - right shift a one byte quantity by known count      */
7110 /*-----------------------------------------------------------------*/
7111 static void
7112 genrshOne (operand * result, operand * left,
7113            int shCount, int sign)
7114 {
7115   D (emitcode (";", "genrshOne"););
7116   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7117 }
7118 #endif
7119
7120 #ifdef BETTER_LITERAL_SHIFT
7121 /*-----------------------------------------------------------------*/
7122 /* genrshTwo - right shift two bytes by known amount != 0          */
7123 /*-----------------------------------------------------------------*/
7124 static void
7125 genrshTwo (operand * result, operand * left,
7126            int shCount, int sign)
7127 {
7128   D (emitcode (";", "genrshTwo"););
7129
7130   /* if shCount >= 8 */
7131   if (shCount >= 8)
7132     {
7133       shCount -= 8;
7134       _startLazyDPSEvaluation();
7135       if (shCount)
7136       {
7137         shiftR1Left2Result (left, MSB16, result, LSB,
7138                             shCount, sign);
7139       }                     
7140       else
7141       {
7142         movLeft2Result (left, MSB16, result, LSB, sign);
7143       }
7144       addSign (result, MSB16, sign);
7145       _endLazyDPSEvaluation();
7146     }
7147
7148   /*  1 <= shCount <= 7 */
7149   else
7150   {
7151     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7152   }
7153 }
7154 #endif
7155
7156 #if 0
7157 //REMOVE ME!!!
7158 /*-----------------------------------------------------------------*/
7159 /* shiftRLong - shift right one long from left to result           */
7160 /* offl = LSB or MSB16                                             */
7161 /*-----------------------------------------------------------------*/
7162 static void
7163 shiftRLong (operand * left, int offl,
7164             operand * result, int sign)
7165 {
7166   if (!sign)
7167     emitcode ("clr", "c");
7168   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
7169   if (sign)
7170     emitcode ("mov", "c,acc.7");
7171   emitcode ("rrc", "a");
7172   aopPut (AOP (result), "a", MSB32 - offl);
7173   if (offl == MSB16)
7174     /* add sign of "a" */
7175     addSign (result, MSB32, sign);
7176
7177   MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
7178   emitcode ("rrc", "a");
7179   aopPut (AOP (result), "a", MSB24 - offl);
7180
7181   MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
7182   emitcode ("rrc", "a");
7183   aopPut (AOP (result), "a", MSB16 - offl);
7184
7185   if (offl == LSB)
7186     {
7187       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
7188       emitcode ("rrc", "a");
7189       aopPut (AOP (result), "a", LSB);
7190     }
7191 }
7192 #endif
7193
7194 #if 0
7195 //REMOVE ME!!!
7196 /*-----------------------------------------------------------------*/
7197 /* genrshFour - shift four byte by a known amount != 0             */
7198 /*-----------------------------------------------------------------*/
7199 static void
7200 genrshFour (operand * result, operand * left,
7201             int shCount, int sign)
7202 {
7203   D (emitcode (";", "genrshFour");
7204     );
7205
7206   /* if shifting more that 3 bytes */
7207   if (shCount >= 24)
7208     {
7209       shCount -= 24;
7210       if (shCount)
7211         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7212       else
7213         movLeft2Result (left, MSB32, result, LSB, sign);
7214       addSign (result, MSB16, sign);
7215     }
7216   else if (shCount >= 16)
7217     {
7218       shCount -= 16;
7219       if (shCount)
7220         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7221       else
7222         {
7223           movLeft2Result (left, MSB24, result, LSB, 0);
7224           movLeft2Result (left, MSB32, result, MSB16, sign);
7225         }
7226       addSign (result, MSB24, sign);
7227     }
7228   else if (shCount >= 8)
7229     {
7230       shCount -= 8;
7231       if (shCount == 1)
7232         shiftRLong (left, MSB16, result, sign);
7233       else if (shCount == 0)
7234         {
7235           movLeft2Result (left, MSB16, result, LSB, 0);
7236           movLeft2Result (left, MSB24, result, MSB16, 0);
7237           movLeft2Result (left, MSB32, result, MSB24, sign);
7238           addSign (result, MSB32, sign);
7239         }
7240       else
7241         {
7242           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7243           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7244           /* the last shift is signed */
7245           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7246           addSign (result, MSB32, sign);
7247         }
7248     }
7249   else
7250     {                           /* 1 <= shCount <= 7 */
7251       if (shCount <= 2)
7252         {
7253           shiftRLong (left, LSB, result, sign);
7254           if (shCount == 2)
7255             shiftRLong (result, LSB, result, sign);
7256         }
7257       else
7258         {
7259           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7260           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7261           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7262         }
7263     }
7264 }
7265 #endif
7266
7267 #ifdef BETTER_LITERAL_SHIFT
7268 /*-----------------------------------------------------------------*/
7269 /* genRightShiftLiteral - right shifting by known count            */
7270 /*-----------------------------------------------------------------*/
7271 static bool
7272 genRightShiftLiteral (operand * left,
7273                       operand * right,
7274                       operand * result,
7275                       iCode * ic,
7276                       int sign)
7277 {
7278   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7279   int size;
7280
7281   size = getSize (operandType (result));
7282
7283   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7284
7285   /* We only handle certain easy cases so far. */
7286   if ((shCount != 0)
7287    && (shCount < (size * 8))
7288    && (size != 1)
7289    && (size != 2))
7290   {
7291       D(emitcode (";", "genRightShiftLiteral wimping out"););   
7292       return FALSE;
7293   }
7294
7295   freeAsmop (right, NULL, ic, TRUE);
7296
7297   aopOp (left, ic, FALSE, FALSE);
7298   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7299
7300 #if VIEW_SIZE
7301   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7302             AOP_SIZE (left));
7303 #endif
7304
7305   /* test the LEFT size !!! */
7306
7307   /* I suppose that the left size >= result size */
7308   if (shCount == 0)
7309   {
7310       size = getDataSize (result);
7311       _startLazyDPSEvaluation();
7312       while (size--)
7313       {
7314         movLeft2Result (left, size, result, size, 0);
7315       }
7316       _endLazyDPSEvaluation();
7317   }
7318   else if (shCount >= (size * 8))
7319     {
7320       if (sign)
7321       {
7322         /* get sign in acc.7 */
7323         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7324       }
7325       addSign (result, LSB, sign);
7326     }
7327   else
7328     {
7329       switch (size)
7330         {
7331         case 1:
7332           genrshOne (result, left, shCount, sign);
7333           break;
7334
7335         case 2:
7336           genrshTwo (result, left, shCount, sign);
7337           break;
7338 #if 0
7339         case 4:
7340           genrshFour (result, left, shCount, sign);
7341           break;
7342 #endif    
7343         default:
7344           break;
7345         }
7346
7347       freeAsmop (left, NULL, ic, TRUE);
7348       freeAsmop (result, NULL, ic, TRUE);
7349     }
7350     return TRUE;
7351 }
7352 #endif
7353
7354 /*-----------------------------------------------------------------*/
7355 /* genSignedRightShift - right shift of signed number              */
7356 /*-----------------------------------------------------------------*/
7357 static void
7358 genSignedRightShift (iCode * ic)
7359 {
7360   operand *right, *left, *result;
7361   int size, offset;
7362   char *l;
7363   symbol *tlbl, *tlbl1;
7364
7365   D (emitcode (";", "genSignedRightShift "););
7366
7367   /* we do it the hard way put the shift count in b
7368      and loop thru preserving the sign */
7369
7370   right = IC_RIGHT (ic);
7371   left = IC_LEFT (ic);
7372   result = IC_RESULT (ic);
7373
7374   aopOp (right, ic, FALSE, FALSE);
7375
7376 #ifdef BETTER_LITERAL_SHIFT
7377   if (AOP_TYPE (right) == AOP_LIT)
7378     {
7379       if (genRightShiftLiteral (left, right, result, ic, 1))
7380       {
7381         return;
7382       }
7383     }
7384 #endif
7385   /* shift count is unknown then we have to form
7386      a loop get the loop count in B : Note: we take
7387      only the lower order byte since shifting
7388      more that 32 bits make no sense anyway, ( the
7389      largest size of an object can be only 32 bits ) */
7390
7391   if (AOP_TYPE (right) == AOP_LIT)
7392   {
7393       /* Really should be handled by genRightShiftLiteral,
7394        * but since I'm too lazy to fix that today, at least we can make
7395        * some small improvement.
7396        */
7397        emitcode("mov", "b,#0x%02x",
7398                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7399   }
7400   else
7401   {
7402         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7403         emitcode ("inc", "b");
7404   }
7405   freeAsmop (right, NULL, ic, TRUE);
7406   aopOp (left, ic, FALSE, FALSE);
7407   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7408
7409   /* now move the left to the result if they are not the
7410      same */
7411   if (!sameRegs (AOP (left), AOP (result)) &&
7412       AOP_SIZE (result) > 1)
7413     {
7414
7415       size = AOP_SIZE (result);
7416       offset = 0;
7417       _startLazyDPSEvaluation ();
7418       while (size--)
7419         {
7420           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7421           if (*l == '@' && IS_AOP_PREG (result))
7422             {
7423
7424               emitcode ("mov", "a,%s", l);
7425               aopPut (AOP (result), "a", offset);
7426             }
7427           else
7428             aopPut (AOP (result), l, offset);
7429           offset++;
7430         }
7431       _endLazyDPSEvaluation ();
7432     }
7433
7434   /* mov the highest order bit to OVR */
7435   tlbl = newiTempLabel (NULL);
7436   tlbl1 = newiTempLabel (NULL);
7437
7438   size = AOP_SIZE (result);
7439   offset = size - 1;
7440   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7441   emitcode ("rlc", "a");
7442   emitcode ("mov", "ov,c");
7443   /* if it is only one byte then */
7444   if (size == 1)
7445     {
7446       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7447       MOVA (l);
7448       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7449       emitcode ("", "%05d$:", tlbl->key + 100);
7450       emitcode ("mov", "c,ov");
7451       emitcode ("rrc", "a");
7452       emitcode ("", "%05d$:", tlbl1->key + 100);
7453       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7454       aopPut (AOP (result), "a", 0);
7455       goto release;
7456     }
7457
7458   reAdjustPreg (AOP (result));
7459   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7460   emitcode ("", "%05d$:", tlbl->key + 100);
7461   emitcode ("mov", "c,ov");
7462   _startLazyDPSEvaluation ();
7463   while (size--)
7464     {
7465       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7466       MOVA (l);
7467       emitcode ("rrc", "a");
7468       aopPut (AOP (result), "a", offset--);
7469     }
7470   _endLazyDPSEvaluation ();
7471   reAdjustPreg (AOP (result));
7472   emitcode ("", "%05d$:", tlbl1->key + 100);
7473   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7474
7475 release:
7476   freeAsmop (left, NULL, ic, TRUE);
7477   freeAsmop (result, NULL, ic, TRUE);
7478 }
7479
7480 /*-----------------------------------------------------------------*/
7481 /* genRightShift - generate code for right shifting                */
7482 /*-----------------------------------------------------------------*/
7483 static void
7484 genRightShift (iCode * ic)
7485 {
7486   operand *right, *left, *result;
7487   sym_link *retype;
7488   int size, offset;
7489   char *l;
7490   symbol *tlbl, *tlbl1;
7491
7492   D (emitcode (";", "genRightShift "););
7493
7494   /* if signed then we do it the hard way preserve the
7495      sign bit moving it inwards */
7496   retype = getSpec (operandType (IC_RESULT (ic)));
7497
7498   if (!SPEC_USIGN (retype))
7499     {
7500       genSignedRightShift (ic);
7501       return;
7502     }
7503
7504   /* signed & unsigned types are treated the same : i.e. the
7505      signed is NOT propagated inwards : quoting from the
7506      ANSI - standard : "for E1 >> E2, is equivalent to division
7507      by 2**E2 if unsigned or if it has a non-negative value,
7508      otherwise the result is implementation defined ", MY definition
7509      is that the sign does not get propagated */
7510
7511   right = IC_RIGHT (ic);
7512   left = IC_LEFT (ic);
7513   result = IC_RESULT (ic);
7514
7515   aopOp (right, ic, FALSE, FALSE);
7516
7517 #ifdef BETTER_LITERAL_SHIFT
7518   /* if the shift count is known then do it
7519      as efficiently as possible */
7520   if (AOP_TYPE (right) == AOP_LIT)
7521     {
7522       if (genRightShiftLiteral (left, right, result, ic, 0))
7523       {
7524         return;
7525       }
7526     }
7527 #endif
7528
7529   /* shift count is unknown then we have to form
7530      a loop get the loop count in B : Note: we take
7531      only the lower order byte since shifting
7532      more that 32 bits make no sense anyway, ( the
7533      largest size of an object can be only 32 bits ) */
7534   
7535   if (AOP_TYPE (right) == AOP_LIT)
7536   {
7537       /* Really should be handled by genRightShiftLiteral,
7538        * but since I'm too lazy to fix that today, at least we can make
7539        * some small improvement.
7540        */
7541        emitcode("mov", "b,#0x%02x",
7542                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7543   }
7544   else
7545   {
7546         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7547         emitcode ("inc", "b");
7548   }
7549   freeAsmop (right, NULL, ic, TRUE);
7550   aopOp (left, ic, FALSE, FALSE);
7551   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7552
7553   /* now move the left to the result if they are not the
7554      same */
7555   if (!sameRegs (AOP (left), AOP (result)) &&
7556       AOP_SIZE (result) > 1)
7557     {
7558
7559       size = AOP_SIZE (result);
7560       offset = 0;
7561       _startLazyDPSEvaluation ();
7562       while (size--)
7563         {
7564           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7565           if (*l == '@' && IS_AOP_PREG (result))
7566             {
7567
7568               emitcode ("mov", "a,%s", l);
7569               aopPut (AOP (result), "a", offset);
7570             }
7571           else
7572             aopPut (AOP (result), l, offset);
7573           offset++;
7574         }
7575       _endLazyDPSEvaluation ();
7576     }
7577
7578   tlbl = newiTempLabel (NULL);
7579   tlbl1 = newiTempLabel (NULL);
7580   size = AOP_SIZE (result);
7581   offset = size - 1;
7582
7583   /* if it is only one byte then */
7584   if (size == 1)
7585     {
7586       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7587       MOVA (l);
7588       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7589       emitcode ("", "%05d$:", tlbl->key + 100);
7590       CLRC;
7591       emitcode ("rrc", "a");
7592       emitcode ("", "%05d$:", tlbl1->key + 100);
7593       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7594       aopPut (AOP (result), "a", 0);
7595       goto release;
7596     }
7597
7598   reAdjustPreg (AOP (result));
7599   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7600   emitcode ("", "%05d$:", tlbl->key + 100);
7601   CLRC;
7602   _startLazyDPSEvaluation ();
7603   while (size--)
7604     {
7605       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7606       MOVA (l);
7607       emitcode ("rrc", "a");
7608       aopPut (AOP (result), "a", offset--);
7609     }
7610   _endLazyDPSEvaluation ();
7611   reAdjustPreg (AOP (result));
7612
7613   emitcode ("", "%05d$:", tlbl1->key + 100);
7614   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7615
7616 release:
7617   freeAsmop (left, NULL, ic, TRUE);
7618   freeAsmop (result, NULL, ic, TRUE);
7619 }
7620
7621 /*-----------------------------------------------------------------*/
7622 /* genUnpackBits - generates code for unpacking bits               */
7623 /*-----------------------------------------------------------------*/
7624 static void
7625 genUnpackBits (operand * result, char *rname, int ptype)
7626 {
7627   int shCnt;
7628   int rlen = 0;
7629   sym_link *etype;
7630   int offset = 0;
7631
7632   D (emitcode (";", "genUnpackBits ");
7633     );
7634
7635   etype = getSpec (operandType (result));
7636
7637   /* read the first byte  */
7638   switch (ptype)
7639     {
7640
7641     case POINTER:
7642     case IPOINTER:
7643       emitcode ("mov", "a,@%s", rname);
7644       break;
7645
7646     case PPOINTER:
7647       emitcode ("movx", "a,@%s", rname);
7648       break;
7649
7650     case FPOINTER:
7651       emitcode ("movx", "a,@dptr");
7652       break;
7653
7654     case CPOINTER:
7655       emitcode ("clr", "a");
7656       emitcode ("movc", "a", "@a+dptr");
7657       break;
7658
7659     case GPOINTER:
7660       emitcode ("lcall", "__gptrget");
7661       break;
7662     }
7663
7664   /* if we have bitdisplacement then it fits   */
7665   /* into this byte completely or if length is */
7666   /* less than a byte                          */
7667   if ((shCnt = SPEC_BSTR (etype)) ||
7668       (SPEC_BLEN (etype) <= 8))
7669     {
7670
7671       /* shift right acc */
7672       AccRsh (shCnt);
7673
7674       emitcode ("anl", "a,#0x%02x",
7675                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7676       aopPut (AOP (result), "a", offset);
7677       return;
7678     }
7679
7680   /* bit field did not fit in a byte  */
7681   rlen = SPEC_BLEN (etype) - 8;
7682   aopPut (AOP (result), "a", offset++);
7683
7684   while (1)
7685     {
7686
7687       switch (ptype)
7688         {
7689         case POINTER:
7690         case IPOINTER:
7691           emitcode ("inc", "%s", rname);
7692           emitcode ("mov", "a,@%s", rname);
7693           break;
7694
7695         case PPOINTER:
7696           emitcode ("inc", "%s", rname);
7697           emitcode ("movx", "a,@%s", rname);
7698           break;
7699
7700         case FPOINTER:
7701           emitcode ("inc", "dptr");
7702           emitcode ("movx", "a,@dptr");
7703           break;
7704
7705         case CPOINTER:
7706           emitcode ("clr", "a");
7707           emitcode ("inc", "dptr");
7708           emitcode ("movc", "a", "@a+dptr");
7709           break;
7710
7711         case GPOINTER:
7712           emitcode ("inc", "dptr");
7713           emitcode ("lcall", "__gptrget");
7714           break;
7715         }
7716
7717       rlen -= 8;
7718       /* if we are done */
7719       if (rlen < 8)
7720         break;
7721
7722       aopPut (AOP (result), "a", offset++);
7723
7724     }
7725
7726   if (rlen)
7727     {
7728       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7729       aopPut (AOP (result), "a", offset);
7730     }
7731
7732   return;
7733 }
7734
7735
7736 /*-----------------------------------------------------------------*/
7737 /* genDataPointerGet - generates code when ptr offset is known     */
7738 /*-----------------------------------------------------------------*/
7739 static void
7740 genDataPointerGet (operand * left,
7741                    operand * result,
7742                    iCode * ic)
7743 {
7744   char *l;
7745   char buffer[256];
7746   int size, offset = 0;
7747   aopOp (result, ic, TRUE, FALSE);
7748
7749   /* get the string representation of the name */
7750   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7751   size = AOP_SIZE (result);
7752   _startLazyDPSEvaluation ();
7753   while (size--)
7754     {
7755       if (offset)
7756         sprintf (buffer, "(%s + %d)", l + 1, offset);
7757       else
7758         sprintf (buffer, "%s", l + 1);
7759       aopPut (AOP (result), buffer, offset++);
7760     }
7761   _endLazyDPSEvaluation ();
7762
7763   freeAsmop (left, NULL, ic, TRUE);
7764   freeAsmop (result, NULL, ic, TRUE);
7765 }
7766
7767 /*-----------------------------------------------------------------*/
7768 /* genNearPointerGet - emitcode for near pointer fetch             */
7769 /*-----------------------------------------------------------------*/
7770 static void
7771 genNearPointerGet (operand * left,
7772                    operand * result,
7773                    iCode * ic)
7774 {
7775   asmop *aop = NULL;
7776   regs *preg = NULL;
7777   char *rname;
7778   sym_link *rtype, *retype, *letype;
7779   sym_link *ltype = operandType (left);
7780   char buffer[80];
7781
7782   rtype = operandType (result);
7783   retype = getSpec (rtype);
7784   letype = getSpec (ltype);
7785
7786   aopOp (left, ic, FALSE, FALSE);
7787
7788   /* if left is rematerialisable and
7789      result is not bit variable type and
7790      the left is pointer to data space i.e
7791      lower 128 bytes of space */
7792   if (AOP_TYPE (left) == AOP_IMMD &&
7793       !IS_BITVAR (retype) &&
7794       !IS_BITVAR (letype) &&
7795       DCL_TYPE (ltype) == POINTER)
7796     {
7797       genDataPointerGet (left, result, ic);
7798       return;
7799     }
7800
7801   /* if the value is already in a pointer register
7802      then don't need anything more */
7803   if (!AOP_INPREG (AOP (left)))
7804     {
7805       /* otherwise get a free pointer register */
7806       aop = newAsmop (0);
7807       preg = getFreePtr (ic, &aop, FALSE);
7808       emitcode ("mov", "%s,%s",
7809                 preg->name,
7810                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7811       rname = preg->name;
7812     }
7813   else
7814     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7815
7816   freeAsmop (left, NULL, ic, TRUE);
7817   aopOp (result, ic, FALSE, FALSE);
7818
7819   /* if bitfield then unpack the bits */
7820   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7821     genUnpackBits (result, rname, POINTER);
7822   else
7823     {
7824       /* we have can just get the values */
7825       int size = AOP_SIZE (result);
7826       int offset = 0;
7827
7828       while (size--)
7829         {
7830           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7831             {
7832
7833               emitcode ("mov", "a,@%s", rname);
7834               aopPut (AOP (result), "a", offset);
7835             }
7836           else
7837             {
7838               sprintf (buffer, "@%s", rname);
7839               aopPut (AOP (result), buffer, offset);
7840             }
7841           offset++;
7842           if (size)
7843             emitcode ("inc", "%s", rname);
7844         }
7845     }
7846
7847   /* now some housekeeping stuff */
7848   if (aop)
7849     {
7850       /* we had to allocate for this iCode */
7851       freeAsmop (NULL, aop, ic, TRUE);
7852     }
7853   else
7854     {
7855       /* we did not allocate which means left
7856          already in a pointer register, then
7857          if size > 0 && this could be used again
7858          we have to point it back to where it
7859          belongs */
7860       if (AOP_SIZE (result) > 1 &&
7861           !OP_SYMBOL (left)->remat &&
7862           (OP_SYMBOL (left)->liveTo > ic->seq ||
7863            ic->depth))
7864         {
7865           int size = AOP_SIZE (result) - 1;
7866           while (size--)
7867             emitcode ("dec", "%s", rname);
7868         }
7869     }
7870
7871   /* done */
7872   freeAsmop (result, NULL, ic, TRUE);
7873
7874 }
7875
7876 /*-----------------------------------------------------------------*/
7877 /* genPagedPointerGet - emitcode for paged pointer fetch           */
7878 /*-----------------------------------------------------------------*/
7879 static void
7880 genPagedPointerGet (operand * left,
7881                     operand * result,
7882                     iCode * ic)
7883 {
7884   asmop *aop = NULL;
7885   regs *preg = NULL;
7886   char *rname;
7887   sym_link *rtype, *retype, *letype;
7888
7889   rtype = operandType (result);
7890   retype = getSpec (rtype);
7891   letype = getSpec (operandType (left));
7892   aopOp (left, ic, FALSE, FALSE);
7893
7894   /* if the value is already in a pointer register
7895      then don't need anything more */
7896   if (!AOP_INPREG (AOP (left)))
7897     {
7898       /* otherwise get a free pointer register */
7899       aop = newAsmop (0);
7900       preg = getFreePtr (ic, &aop, FALSE);
7901       emitcode ("mov", "%s,%s",
7902                 preg->name,
7903                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7904       rname = preg->name;
7905     }
7906   else
7907     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7908
7909   freeAsmop (left, NULL, ic, TRUE);
7910   aopOp (result, ic, FALSE, FALSE);
7911
7912   /* if bitfield then unpack the bits */
7913   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7914     genUnpackBits (result, rname, PPOINTER);
7915   else
7916     {
7917       /* we have can just get the values */
7918       int size = AOP_SIZE (result);
7919       int offset = 0;
7920
7921       while (size--)
7922         {
7923
7924           emitcode ("movx", "a,@%s", rname);
7925           aopPut (AOP (result), "a", offset);
7926
7927           offset++;
7928
7929           if (size)
7930             emitcode ("inc", "%s", rname);
7931         }
7932     }
7933
7934   /* now some housekeeping stuff */
7935   if (aop)
7936     {
7937       /* we had to allocate for this iCode */
7938       freeAsmop (NULL, aop, ic, TRUE);
7939     }
7940   else
7941     {
7942       /* we did not allocate which means left
7943          already in a pointer register, then
7944          if size > 0 && this could be used again
7945          we have to point it back to where it
7946          belongs */
7947       if (AOP_SIZE (result) > 1 &&
7948           !OP_SYMBOL (left)->remat &&
7949           (OP_SYMBOL (left)->liveTo > ic->seq ||
7950            ic->depth))
7951         {
7952           int size = AOP_SIZE (result) - 1;
7953           while (size--)
7954             emitcode ("dec", "%s", rname);
7955         }
7956     }
7957
7958   /* done */
7959   freeAsmop (result, NULL, ic, TRUE);
7960
7961
7962 }
7963
7964 /*-----------------------------------------------------------------*/
7965 /* genFarPointerGet - gget value from far space                    */
7966 /*-----------------------------------------------------------------*/
7967 static void
7968 genFarPointerGet (operand * left,
7969                   operand * result, iCode * ic)
7970 {
7971   int size, offset;
7972   sym_link *retype = getSpec (operandType (result));
7973   sym_link *letype = getSpec (operandType (left));
7974   D (emitcode (";", "genFarPointerGet");
7975     );
7976
7977   aopOp (left, ic, FALSE, FALSE);
7978
7979   /* if the operand is already in dptr
7980      then we do nothing else we move the value to dptr */
7981   if (AOP_TYPE (left) != AOP_STR)
7982     {
7983       /* if this is remateriazable */
7984       if (AOP_TYPE (left) == AOP_IMMD)
7985         {
7986           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7987         }
7988       else
7989         {
7990           /* we need to get it byte by byte */
7991           _startLazyDPSEvaluation ();
7992           if (AOP_TYPE (left) != AOP_DPTR)
7993             {
7994               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7995               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7996               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7997             }
7998           else
7999             {
8000               /* We need to generate a load to DPTR indirect through DPTR. */
8001               D (emitcode (";", "genFarPointerGet -- indirection special case.");
8002                 );
8003               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8004               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8005               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8006               emitcode ("pop", "dph");
8007               emitcode ("pop", "dpl");
8008             }
8009           _endLazyDPSEvaluation ();
8010         }
8011     }
8012   /* so dptr know contains the address */
8013   freeAsmop (left, NULL, ic, TRUE);
8014   aopOp (result, ic, FALSE, TRUE);
8015
8016   /* if bit then unpack */
8017   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8018     genUnpackBits (result, "dptr", FPOINTER);
8019   else
8020     {
8021       size = AOP_SIZE (result);
8022       offset = 0;
8023
8024       _startLazyDPSEvaluation ();
8025       while (size--)
8026         {
8027
8028           genSetDPTR (0);
8029           _flushLazyDPS ();
8030
8031           emitcode ("movx", "a,@dptr");
8032           if (size)
8033             emitcode ("inc", "dptr");
8034
8035           aopPut (AOP (result), "a", offset++);
8036         }
8037       _endLazyDPSEvaluation ();
8038     }
8039
8040   freeAsmop (result, NULL, ic, TRUE);
8041 }
8042
8043 /*-----------------------------------------------------------------*/
8044 /* emitcodePointerGet - gget value from code space                  */
8045 /*-----------------------------------------------------------------*/
8046 static void
8047 emitcodePointerGet (operand * left,
8048                     operand * result, iCode * ic)
8049 {
8050   int size, offset;
8051   sym_link *retype = getSpec (operandType (result));
8052
8053   aopOp (left, ic, FALSE, FALSE);
8054
8055   /* if the operand is already in dptr
8056      then we do nothing else we move the value to dptr */
8057   if (AOP_TYPE (left) != AOP_STR)
8058     {
8059       /* if this is remateriazable */
8060       if (AOP_TYPE (left) == AOP_IMMD)
8061         {
8062           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8063         }
8064       else
8065         {                       /* we need to get it byte by byte */
8066           _startLazyDPSEvaluation ();
8067           if (AOP_TYPE (left) != AOP_DPTR)
8068             {
8069               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8070               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8071               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8072             }
8073           else
8074             {
8075               /* We need to generate a load to DPTR indirect through DPTR. */
8076               D (emitcode (";", "gencodePointerGet -- indirection special case.");
8077                 );
8078               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8079               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8080               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8081               emitcode ("pop", "dph");
8082               emitcode ("pop", "dpl");
8083             }
8084           _endLazyDPSEvaluation ();
8085         }
8086     }
8087   /* so dptr know contains the address */
8088   freeAsmop (left, NULL, ic, TRUE);
8089   aopOp (result, ic, FALSE, TRUE);
8090
8091   /* if bit then unpack */
8092   if (IS_BITVAR (retype))
8093     genUnpackBits (result, "dptr", CPOINTER);
8094   else
8095     {
8096       size = AOP_SIZE (result);
8097       offset = 0;
8098
8099       _startLazyDPSEvaluation ();
8100       while (size--)
8101         {
8102           genSetDPTR (0);
8103           _flushLazyDPS ();
8104
8105           emitcode ("clr", "a");
8106           emitcode ("movc", "a,@a+dptr");
8107           if (size)
8108             emitcode ("inc", "dptr");
8109           aopPut (AOP (result), "a", offset++);
8110         }
8111       _endLazyDPSEvaluation ();
8112     }
8113
8114   freeAsmop (result, NULL, ic, TRUE);
8115 }
8116
8117 /*-----------------------------------------------------------------*/
8118 /* genGenPointerGet - gget value from generic pointer space        */
8119 /*-----------------------------------------------------------------*/
8120 static void
8121 genGenPointerGet (operand * left,
8122                   operand * result, iCode * ic)
8123 {
8124   int size, offset;
8125   sym_link *retype = getSpec (operandType (result));
8126   sym_link *letype = getSpec (operandType (left));
8127
8128   D (emitcode (";", "genGenPointerGet "); );
8129
8130   aopOp (left, ic, FALSE, TRUE);
8131
8132   /* if the operand is already in dptr
8133      then we do nothing else we move the value to dptr */
8134   if (AOP_TYPE (left) != AOP_STR)
8135     {
8136       /* if this is remateriazable */
8137       if (AOP_TYPE (left) == AOP_IMMD)
8138         {
8139           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8140           emitcode ("mov", "b,#%d", pointerCode (retype));
8141         }
8142       else
8143         {                       /* we need to get it byte by byte */
8144           _startLazyDPSEvaluation ();
8145           if (AOP(left)->type==AOP_DPTR2) {
8146             char *l;
8147             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8148             genSetDPTR(0);
8149             _flushLazyDPS();
8150             emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l);
8151             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8152             genSetDPTR(0);
8153             _flushLazyDPS();
8154             emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l);
8155             l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8156             genSetDPTR(0);
8157             _flushLazyDPS();
8158             emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l);
8159             emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8160           } else {
8161             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8162             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8163             emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8164             emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8165           }
8166           _endLazyDPSEvaluation ();
8167         }
8168     }
8169   /* so dptr know contains the address */
8170   freeAsmop (left, NULL, ic, TRUE);
8171   aopOp (result, ic, FALSE, TRUE);
8172
8173   /* if bit then unpack */
8174   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8175     genUnpackBits (result, "dptr", GPOINTER);
8176   else
8177     {
8178       size = AOP_SIZE (result);
8179       offset = 0;
8180
8181       while (size--)
8182         {
8183           emitcode ("lcall", "__gptrget");
8184           aopPut (AOP (result), "a", offset++);
8185           if (size)
8186             emitcode ("inc", "dptr");
8187         }
8188     }
8189
8190   freeAsmop (result, NULL, ic, TRUE);
8191 }
8192
8193 /*-----------------------------------------------------------------*/
8194 /* genPointerGet - generate code for pointer get                   */
8195 /*-----------------------------------------------------------------*/
8196 static void
8197 genPointerGet (iCode * ic)
8198 {
8199   operand *left, *result;
8200   sym_link *type, *etype;
8201   int p_type;
8202
8203   D (emitcode (";", "genPointerGet ");
8204     );
8205
8206   left = IC_LEFT (ic);
8207   result = IC_RESULT (ic);
8208
8209   /* depending on the type of pointer we need to
8210      move it to the correct pointer register */
8211   type = operandType (left);
8212   etype = getSpec (type);
8213   /* if left is of type of pointer then it is simple */
8214   if (IS_PTR (type) && !IS_FUNC (type->next))
8215     p_type = DCL_TYPE (type);
8216   else
8217     {
8218       /* we have to go by the storage class */
8219       p_type = PTR_TYPE (SPEC_OCLS (etype));
8220     }
8221
8222   /* now that we have the pointer type we assign
8223      the pointer values */
8224   switch (p_type)
8225     {
8226
8227     case POINTER:
8228     case IPOINTER:
8229       genNearPointerGet (left, result, ic);
8230       break;
8231
8232     case PPOINTER:
8233       genPagedPointerGet (left, result, ic);
8234       break;
8235
8236     case FPOINTER:
8237       genFarPointerGet (left, result, ic);
8238       break;
8239
8240     case CPOINTER:
8241       emitcodePointerGet (left, result, ic);
8242       break;
8243
8244     case GPOINTER:
8245       genGenPointerGet (left, result, ic);
8246       break;
8247     }
8248
8249 }
8250
8251 /*-----------------------------------------------------------------*/
8252 /* genPackBits - generates code for packed bit storage             */
8253 /*-----------------------------------------------------------------*/
8254 static void
8255 genPackBits (sym_link * etype,
8256              operand * right,
8257              char *rname, int p_type)
8258 {
8259   int shCount = 0;
8260   int offset = 0;
8261   int rLen = 0;
8262   int blen, bstr;
8263   char *l;
8264
8265   blen = SPEC_BLEN (etype);
8266   bstr = SPEC_BSTR (etype);
8267
8268   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8269   MOVA (l);
8270
8271   /* if the bit lenth is less than or    */
8272   /* it exactly fits a byte then         */
8273   if (SPEC_BLEN (etype) <= 8)
8274     {
8275       shCount = SPEC_BSTR (etype);
8276
8277       /* shift left acc */
8278       AccLsh (shCount);
8279
8280       if (SPEC_BLEN (etype) < 8)
8281         {                       /* if smaller than a byte */
8282
8283
8284           switch (p_type)
8285             {
8286             case POINTER:
8287               emitcode ("mov", "b,a");
8288               emitcode ("mov", "a,@%s", rname);
8289               break;
8290
8291             case FPOINTER:
8292               emitcode ("mov", "b,a");
8293               emitcode ("movx", "a,@dptr");
8294               break;
8295
8296             case GPOINTER:
8297               emitcode ("push", "b");
8298               emitcode ("push", "acc");
8299               emitcode ("lcall", "__gptrget");
8300               emitcode ("pop", "b");
8301               break;
8302             }
8303
8304           emitcode ("anl", "a,#0x%02x", (unsigned char)
8305                     ((unsigned char) (0xFF << (blen + bstr)) |
8306                      (unsigned char) (0xFF >> (8 - bstr))));
8307           emitcode ("orl", "a,b");
8308           if (p_type == GPOINTER)
8309             emitcode ("pop", "b");
8310         }
8311     }
8312
8313   switch (p_type)
8314     {
8315     case POINTER:
8316       emitcode ("mov", "@%s,a", rname);
8317       break;
8318
8319     case FPOINTER:
8320       emitcode ("movx", "@dptr,a");
8321       break;
8322
8323     case GPOINTER:
8324       emitcode ("lcall", "__gptrput");
8325       break;
8326     }
8327
8328   /* if we r done */
8329   if (SPEC_BLEN (etype) <= 8)
8330     return;
8331
8332   emitcode ("inc", "%s", rname);
8333   rLen = SPEC_BLEN (etype);
8334
8335   /* now generate for lengths greater than one byte */
8336   while (1)
8337     {
8338
8339       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8340
8341       rLen -= 8;
8342       if (rLen < 8)
8343         break;
8344
8345       switch (p_type)
8346         {
8347         case POINTER:
8348           if (*l == '@')
8349             {
8350               MOVA (l);
8351               emitcode ("mov", "@%s,a", rname);
8352             }
8353           else
8354             emitcode ("mov", "@%s,%s", rname, l);
8355           break;
8356
8357         case FPOINTER:
8358           MOVA (l);
8359           emitcode ("movx", "@dptr,a");
8360           break;
8361
8362         case GPOINTER:
8363           MOVA (l);
8364           emitcode ("lcall", "__gptrput");
8365           break;
8366         }
8367       emitcode ("inc", "%s", rname);
8368     }
8369
8370   MOVA (l);
8371
8372   /* last last was not complete */
8373   if (rLen)
8374     {
8375       /* save the byte & read byte */
8376       switch (p_type)
8377         {
8378         case POINTER:
8379           emitcode ("mov", "b,a");
8380           emitcode ("mov", "a,@%s", rname);
8381           break;
8382
8383         case FPOINTER:
8384           emitcode ("mov", "b,a");
8385           emitcode ("movx", "a,@dptr");
8386           break;
8387
8388         case GPOINTER:
8389           emitcode ("push", "b");
8390           emitcode ("push", "acc");
8391           emitcode ("lcall", "__gptrget");
8392           emitcode ("pop", "b");
8393           break;
8394         }
8395
8396       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8397       emitcode ("orl", "a,b");
8398     }
8399
8400   if (p_type == GPOINTER)
8401     emitcode ("pop", "b");
8402
8403   switch (p_type)
8404     {
8405
8406     case POINTER:
8407       emitcode ("mov", "@%s,a", rname);
8408       break;
8409
8410     case FPOINTER:
8411       emitcode ("movx", "@dptr,a");
8412       break;
8413
8414     case GPOINTER:
8415       emitcode ("lcall", "__gptrput");
8416       break;
8417     }
8418 }
8419 /*-----------------------------------------------------------------*/
8420 /* genDataPointerSet - remat pointer to data space                 */
8421 /*-----------------------------------------------------------------*/
8422 static void
8423 genDataPointerSet (operand * right,
8424                    operand * result,
8425                    iCode * ic)
8426 {
8427   int size, offset = 0;
8428   char *l, buffer[256];
8429
8430   aopOp (right, ic, FALSE, FALSE);
8431
8432   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8433   size = AOP_SIZE (right);
8434   while (size--)
8435     {
8436       if (offset)
8437         sprintf (buffer, "(%s + %d)", l + 1, offset);
8438       else
8439         sprintf (buffer, "%s", l + 1);
8440       emitcode ("mov", "%s,%s", buffer,
8441                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8442     }
8443
8444   freeAsmop (right, NULL, ic, TRUE);
8445   freeAsmop (result, NULL, ic, TRUE);
8446 }
8447
8448 /*-----------------------------------------------------------------*/
8449 /* genNearPointerSet - emitcode for near pointer put                */
8450 /*-----------------------------------------------------------------*/
8451 static void
8452 genNearPointerSet (operand * right,
8453                    operand * result,
8454                    iCode * ic)
8455 {
8456   asmop *aop = NULL;
8457   regs *preg = NULL;
8458   char *rname, *l;
8459   sym_link *retype, *letype;
8460   sym_link *ptype = operandType (result);
8461
8462   retype = getSpec (operandType (right));
8463   letype = getSpec (ptype);
8464
8465   aopOp (result, ic, FALSE, FALSE);
8466
8467   /* if the result is rematerializable &
8468      in data space & not a bit variable */
8469   if (AOP_TYPE (result) == AOP_IMMD &&
8470       DCL_TYPE (ptype) == POINTER &&
8471       !IS_BITVAR (retype) &&
8472       !IS_BITVAR (letype))
8473     {
8474       genDataPointerSet (right, result, ic);
8475       return;
8476     }
8477
8478   /* if the value is already in a pointer register
8479      then don't need anything more */
8480   if (!AOP_INPREG (AOP (result)))
8481     {
8482       /* otherwise get a free pointer register */
8483       aop = newAsmop (0);
8484       preg = getFreePtr (ic, &aop, FALSE);
8485       emitcode ("mov", "%s,%s",
8486                 preg->name,
8487                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8488       rname = preg->name;
8489     }
8490   else
8491     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8492
8493   freeAsmop (result, NULL, ic, TRUE);
8494   aopOp (right, ic, FALSE, FALSE);
8495
8496   /* if bitfield then unpack the bits */
8497   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8498     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8499   else
8500     {
8501       /* we have can just get the values */
8502       int size = AOP_SIZE (right);
8503       int offset = 0;
8504
8505       while (size--)
8506         {
8507           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8508           if (*l == '@')
8509             {
8510               MOVA (l);
8511               emitcode ("mov", "@%s,a", rname);
8512             }
8513           else
8514             emitcode ("mov", "@%s,%s", rname, l);
8515           if (size)
8516             emitcode ("inc", "%s", rname);
8517           offset++;
8518         }
8519     }
8520
8521   /* now some housekeeping stuff */
8522   if (aop)
8523     {
8524       /* we had to allocate for this iCode */
8525       freeAsmop (NULL, aop, ic, TRUE);
8526     }
8527   else
8528     {
8529       /* we did not allocate which means left
8530          already in a pointer register, then
8531          if size > 0 && this could be used again
8532          we have to point it back to where it
8533          belongs */
8534       if (AOP_SIZE (right) > 1 &&
8535           !OP_SYMBOL (result)->remat &&
8536           (OP_SYMBOL (result)->liveTo > ic->seq ||
8537            ic->depth))
8538         {
8539           int size = AOP_SIZE (right) - 1;
8540           while (size--)
8541             emitcode ("dec", "%s", rname);
8542         }
8543     }
8544
8545   /* done */
8546   freeAsmop (right, NULL, ic, TRUE);
8547
8548
8549 }
8550
8551 /*-----------------------------------------------------------------*/
8552 /* genPagedPointerSet - emitcode for Paged pointer put             */
8553 /*-----------------------------------------------------------------*/
8554 static void
8555 genPagedPointerSet (operand * right,
8556                     operand * result,
8557                     iCode * ic)
8558 {
8559   asmop *aop = NULL;
8560   regs *preg = NULL;
8561   char *rname, *l;
8562   sym_link *retype, *letype;
8563
8564   retype = getSpec (operandType (right));
8565   letype = getSpec (operandType (result));
8566
8567   aopOp (result, ic, FALSE, FALSE);
8568
8569   /* if the value is already in a pointer register
8570      then don't need anything more */
8571   if (!AOP_INPREG (AOP (result)))
8572     {
8573       /* otherwise get a free pointer register */
8574       aop = newAsmop (0);
8575       preg = getFreePtr (ic, &aop, FALSE);
8576       emitcode ("mov", "%s,%s",
8577                 preg->name,
8578                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8579       rname = preg->name;
8580     }
8581   else
8582     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8583
8584   freeAsmop (result, NULL, ic, TRUE);
8585   aopOp (right, ic, FALSE, FALSE);
8586
8587   /* if bitfield then unpack the bits */
8588   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8589     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8590   else
8591     {
8592       /* we have can just get the values */
8593       int size = AOP_SIZE (right);
8594       int offset = 0;
8595
8596       while (size--)
8597         {
8598           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8599
8600           MOVA (l);
8601           emitcode ("movx", "@%s,a", rname);
8602
8603           if (size)
8604             emitcode ("inc", "%s", rname);
8605
8606           offset++;
8607         }
8608     }
8609
8610   /* now some housekeeping stuff */
8611   if (aop)
8612     {
8613       /* we had to allocate for this iCode */
8614       freeAsmop (NULL, aop, ic, TRUE);
8615     }
8616   else
8617     {
8618       /* we did not allocate which means left
8619          already in a pointer register, then
8620          if size > 0 && this could be used again
8621          we have to point it back to where it
8622          belongs */
8623       if (AOP_SIZE (right) > 1 &&
8624           !OP_SYMBOL (result)->remat &&
8625           (OP_SYMBOL (result)->liveTo > ic->seq ||
8626            ic->depth))
8627         {
8628           int size = AOP_SIZE (right) - 1;
8629           while (size--)
8630             emitcode ("dec", "%s", rname);
8631         }
8632     }
8633
8634   /* done */
8635   freeAsmop (right, NULL, ic, TRUE);
8636
8637
8638 }
8639
8640 /*-----------------------------------------------------------------*/
8641 /* genFarPointerSet - set value from far space                     */
8642 /*-----------------------------------------------------------------*/
8643 static void
8644 genFarPointerSet (operand * right,
8645                   operand * result, iCode * ic)
8646 {
8647   int size, offset;
8648   sym_link *retype = getSpec (operandType (right));
8649   sym_link *letype = getSpec (operandType (result));
8650
8651   aopOp (result, ic, FALSE, FALSE);
8652
8653   /* if the operand is already in dptr
8654      then we do nothing else we move the value to dptr */
8655   if (AOP_TYPE (result) != AOP_STR)
8656     {
8657       /* if this is remateriazable */
8658       if (AOP_TYPE (result) == AOP_IMMD)
8659         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8660       else
8661         {
8662           /* we need to get it byte by byte */
8663           _startLazyDPSEvaluation ();
8664           if (AOP_TYPE (result) != AOP_DPTR)
8665             {
8666               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8667               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8668               emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8669             }
8670           else
8671             {
8672               /* We need to generate a load to DPTR indirect through DPTR. */
8673               D (emitcode (";", "genFarPointerSet -- indirection special case.");
8674                 );
8675               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8676               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8677               emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8678               emitcode ("pop", "dph");
8679               emitcode ("pop", "dpl");
8680             }
8681           _endLazyDPSEvaluation ();
8682         }
8683     }
8684   /* so dptr know contains the address */
8685   freeAsmop (result, NULL, ic, TRUE);
8686   aopOp (right, ic, FALSE, TRUE);
8687
8688   /* if bit then unpack */
8689   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8690     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8691   else
8692     {
8693       size = AOP_SIZE (right);
8694       offset = 0;
8695
8696       _startLazyDPSEvaluation ();
8697       while (size--)
8698         {
8699           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8700           MOVA (l);
8701
8702           genSetDPTR (0);
8703           _flushLazyDPS ();
8704
8705           emitcode ("movx", "@dptr,a");
8706           if (size)
8707             emitcode ("inc", "dptr");
8708         }
8709       _endLazyDPSEvaluation ();
8710     }
8711
8712   freeAsmop (right, NULL, ic, TRUE);
8713 }
8714
8715 /*-----------------------------------------------------------------*/
8716 /* genGenPointerSet - set value from generic pointer space         */
8717 /*-----------------------------------------------------------------*/
8718 static void
8719 genGenPointerSet (operand * right,
8720                   operand * result, iCode * ic)
8721 {
8722   int size, offset;
8723   sym_link *retype = getSpec (operandType (right));
8724   sym_link *letype = getSpec (operandType (result));
8725
8726   aopOp (result, ic, FALSE, TRUE);
8727
8728   /* if the operand is already in dptr
8729      then we do nothing else we move the value to dptr */
8730   if (AOP_TYPE (result) != AOP_STR)
8731     {
8732       _startLazyDPSEvaluation ();
8733       /* if this is remateriazable */
8734       if (AOP_TYPE (result) == AOP_IMMD)
8735         {
8736           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8737           emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8738         }
8739       else
8740         {                       /* we need to get it byte by byte */
8741           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8742           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8743           emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8744           emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8745         }
8746       _endLazyDPSEvaluation ();
8747     }
8748   /* so dptr know contains the address */
8749   freeAsmop (result, NULL, ic, TRUE);
8750   aopOp (right, ic, FALSE, TRUE);
8751
8752   /* if bit then unpack */
8753   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8754     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8755   else
8756     {
8757       size = AOP_SIZE (right);
8758       offset = 0;
8759
8760       _startLazyDPSEvaluation ();
8761       while (size--)
8762         {
8763           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8764           MOVA (l);
8765
8766           genSetDPTR (0);
8767           _flushLazyDPS ();
8768
8769           emitcode ("lcall", "__gptrput");
8770           if (size)
8771             emitcode ("inc", "dptr");
8772         }
8773       _endLazyDPSEvaluation ();
8774     }
8775
8776   freeAsmop (right, NULL, ic, TRUE);
8777 }
8778
8779 /*-----------------------------------------------------------------*/
8780 /* genPointerSet - stores the value into a pointer location        */
8781 /*-----------------------------------------------------------------*/
8782 static void
8783 genPointerSet (iCode * ic)
8784 {
8785   operand *right, *result;
8786   sym_link *type, *etype;
8787   int p_type;
8788
8789   D (emitcode (";", "genPointerSet ");
8790     );
8791
8792   right = IC_RIGHT (ic);
8793   result = IC_RESULT (ic);
8794
8795   /* depending on the type of pointer we need to
8796      move it to the correct pointer register */
8797   type = operandType (result);
8798   etype = getSpec (type);
8799   /* if left is of type of pointer then it is simple */
8800   if (IS_PTR (type) && !IS_FUNC (type->next))
8801     {
8802       p_type = DCL_TYPE (type);
8803     }
8804   else
8805     {
8806       /* we have to go by the storage class */
8807       p_type = PTR_TYPE (SPEC_OCLS (etype));
8808     }
8809
8810   /* now that we have the pointer type we assign
8811      the pointer values */
8812   switch (p_type)
8813     {
8814
8815     case POINTER:
8816     case IPOINTER:
8817       genNearPointerSet (right, result, ic);
8818       break;
8819
8820     case PPOINTER:
8821       genPagedPointerSet (right, result, ic);
8822       break;
8823
8824     case FPOINTER:
8825       genFarPointerSet (right, result, ic);
8826       break;
8827
8828     case GPOINTER:
8829       genGenPointerSet (right, result, ic);
8830       break;
8831     }
8832
8833 }
8834
8835 /*-----------------------------------------------------------------*/
8836 /* genIfx - generate code for Ifx statement                        */
8837 /*-----------------------------------------------------------------*/
8838 static void
8839 genIfx (iCode * ic, iCode * popIc)
8840 {
8841   operand *cond = IC_COND (ic);
8842   int isbit = 0;
8843
8844   D (emitcode (";", "genIfx "););
8845
8846   aopOp (cond, ic, FALSE, FALSE);
8847
8848   /* get the value into acc */
8849   if (AOP_TYPE (cond) != AOP_CRY)
8850     toBoolean (cond);
8851   else
8852     isbit = 1;
8853   /* the result is now in the accumulator */
8854   freeAsmop (cond, NULL, ic, TRUE);
8855
8856   /* if there was something to be popped then do it */
8857   if (popIc)
8858     genIpop (popIc);
8859
8860   /* if the condition is  a bit variable */
8861   if (isbit && IS_ITEMP (cond) &&
8862       SPIL_LOC (cond))
8863     genIfxJump (ic, SPIL_LOC (cond)->rname);
8864   else if (isbit && !IS_ITEMP (cond))
8865     genIfxJump (ic, OP_SYMBOL (cond)->rname);
8866   else
8867     genIfxJump (ic, "a");
8868
8869   ic->generated = 1;
8870 }
8871
8872 /*-----------------------------------------------------------------*/
8873 /* genAddrOf - generates code for address of                       */
8874 /*-----------------------------------------------------------------*/
8875 static void
8876 genAddrOf (iCode * ic)
8877 {
8878   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8879   int size, offset;
8880
8881   D (emitcode (";", "genAddrOf ");
8882     );
8883
8884   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8885
8886   /* if the operand is on the stack then we
8887      need to get the stack offset of this
8888      variable */
8889   if (sym->onStack)
8890     {
8891       /* if it has an offset then we need to compute
8892          it */
8893       if (sym->stack)
8894         {
8895           emitcode ("mov", "a,_bp");
8896           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8897           aopPut (AOP (IC_RESULT (ic)), "a", 0);
8898         }
8899       else
8900         {
8901           /* we can just move _bp */
8902           aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8903         }
8904       /* fill the result with zero */
8905       size = AOP_SIZE (IC_RESULT (ic)) - 1;
8906
8907
8908       if (options.stack10bit && size < (FPTRSIZE - 1))
8909         {
8910           fprintf (stderr,
8911                    "*** warning: pointer to stack var truncated.\n");
8912         }
8913
8914       offset = 1;
8915       while (size--)
8916         {
8917           /* Yuck! */
8918           if (options.stack10bit && offset == 2)
8919             {
8920               aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8921             }
8922           else
8923             {
8924               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8925             }
8926         }
8927
8928       goto release;
8929     }
8930
8931   /* object not on stack then we need the name */
8932   size = AOP_SIZE (IC_RESULT (ic));
8933   offset = 0;
8934
8935   while (size--)
8936     {
8937       char s[SDCC_NAME_MAX];
8938       if (offset)
8939         sprintf (s, "#(%s >> %d)",
8940                  sym->rname,
8941                  offset * 8);
8942       else
8943         sprintf (s, "#%s", sym->rname);
8944       aopPut (AOP (IC_RESULT (ic)), s, offset++);
8945     }
8946
8947 release:
8948   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8949
8950 }
8951
8952 /*-----------------------------------------------------------------*/
8953 /* genFarFarAssign - assignment when both are in far space         */
8954 /*-----------------------------------------------------------------*/
8955 static void
8956 genFarFarAssign (operand * result, operand * right, iCode * ic)
8957 {
8958   int size = AOP_SIZE (right);
8959   int offset = 0;
8960   char *l;
8961
8962   if (size > 1)
8963     {
8964       /* This is a net loss for size == 1, but a big gain
8965        * otherwise.
8966        */
8967       D (emitcode (";", "genFarFarAssign (improved)");
8968         );
8969
8970       aopOp (result, ic, TRUE, TRUE);
8971
8972       _startLazyDPSEvaluation ();
8973       while (size--)
8974         {
8975           aopPut (AOP (result),
8976                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
8977           offset++;
8978         }
8979       _endLazyDPSEvaluation ();
8980       freeAsmop (result, NULL, ic, FALSE);
8981       freeAsmop (right, NULL, ic, FALSE);
8982     }
8983   else
8984     {
8985       D (emitcode (";", "genFarFarAssign ");
8986         );
8987
8988       /* first push the right side on to the stack */
8989       _startLazyDPSEvaluation ();
8990       while (size--)
8991         {
8992           l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8993           MOVA (l);
8994           emitcode ("push", "acc");
8995         }
8996
8997       freeAsmop (right, NULL, ic, FALSE);
8998       /* now assign DPTR to result */
8999       aopOp (result, ic, FALSE, FALSE);
9000       size = AOP_SIZE (result);
9001       while (size--)
9002         {
9003           emitcode ("pop", "acc");
9004           aopPut (AOP (result), "a", --offset);
9005         }
9006       freeAsmop (result, NULL, ic, FALSE);
9007       _endLazyDPSEvaluation ();
9008     }
9009 }
9010
9011 /*-----------------------------------------------------------------*/
9012 /* genAssign - generate code for assignment                        */
9013 /*-----------------------------------------------------------------*/
9014 static void
9015 genAssign (iCode * ic)
9016 {
9017   operand *result, *right;
9018   int size, offset;
9019   unsigned long lit = 0L;
9020
9021   D (emitcode (";", "genAssign ");
9022     );
9023
9024   result = IC_RESULT (ic);
9025   right = IC_RIGHT (ic);
9026
9027   /* if they are the same */
9028   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9029     return;
9030
9031   aopOp (right, ic, FALSE, FALSE);
9032
9033   emitcode (";", "genAssign: resultIsFar = %s",
9034             isOperandInFarSpace (result) ?
9035             "TRUE" : "FALSE");
9036
9037   /* special case both in far space */
9038   if ((AOP_TYPE (right) == AOP_DPTR ||
9039        AOP_TYPE (right) == AOP_DPTR2) &&
9040   /* IS_TRUE_SYMOP(result)       && */
9041       isOperandInFarSpace (result))
9042     {
9043       genFarFarAssign (result, right, ic);
9044       return;
9045     }
9046
9047   aopOp (result, ic, TRUE, FALSE);
9048
9049   /* if they are the same registers */
9050   if (sameRegs (AOP (right), AOP (result)))
9051     goto release;
9052
9053   /* if the result is a bit */
9054   if (AOP_TYPE (result) == AOP_CRY)
9055     {
9056
9057       /* if the right size is a literal then
9058          we know what the value is */
9059       if (AOP_TYPE (right) == AOP_LIT)
9060         {
9061           if (((int) operandLitValue (right)))
9062             aopPut (AOP (result), one, 0);
9063           else
9064             aopPut (AOP (result), zero, 0);
9065           goto release;
9066         }
9067
9068       /* the right is also a bit variable */
9069       if (AOP_TYPE (right) == AOP_CRY)
9070         {
9071           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9072           aopPut (AOP (result), "c", 0);
9073           goto release;
9074         }
9075
9076       /* we need to or */
9077       toBoolean (right);
9078       aopPut (AOP (result), "a", 0);
9079       goto release;
9080     }
9081
9082   /* bit variables done */
9083   /* general case */
9084   size = AOP_SIZE (result);
9085   offset = 0;
9086   if (AOP_TYPE (right) == AOP_LIT)
9087     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9088
9089   if ((size > 1) &&
9090       (AOP_TYPE (result) != AOP_REG) &&
9091       (AOP_TYPE (right) == AOP_LIT) &&
9092       !IS_FLOAT (operandType (right)))
9093     {
9094       D (emitcode (";", "Kevin's better literal load code");
9095         );
9096       _startLazyDPSEvaluation ();
9097       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9098         {
9099           aopPut (AOP (result),
9100                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9101                   offset);
9102           offset++;
9103           size--;
9104         }
9105       /* And now fill the rest with zeros. */
9106       if (size)
9107         {
9108           emitcode ("clr", "a");
9109         }
9110       while (size--)
9111         {
9112           aopPut (AOP (result), "a", offset++);
9113         }
9114       _endLazyDPSEvaluation ();
9115     }
9116   else
9117     {
9118       _startLazyDPSEvaluation ();
9119       while (size--)
9120         {
9121           aopPut (AOP (result),
9122                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9123                   offset);
9124           offset++;
9125         }
9126       _endLazyDPSEvaluation ();
9127     }
9128
9129 release:
9130   freeAsmop (right, NULL, ic, FALSE);
9131   freeAsmop (result, NULL, ic, TRUE);
9132 }
9133
9134 /*-----------------------------------------------------------------*/
9135 /* genJumpTab - generates code for jump table                      */
9136 /*-----------------------------------------------------------------*/
9137 static void
9138 genJumpTab (iCode * ic)
9139 {
9140   symbol *jtab;
9141   char *l;
9142
9143   D (emitcode (";", "genJumpTab ");
9144     );
9145
9146   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9147   /* get the condition into accumulator */
9148   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9149   MOVA (l);
9150   /* multiply by four! */
9151   emitcode ("add", "a,acc");
9152   emitcode ("add", "a,acc");
9153   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9154
9155   jtab = newiTempLabel (NULL);
9156   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9157   emitcode ("jmp", "@a+dptr");
9158   emitcode ("", "%05d$:", jtab->key + 100);
9159   /* now generate the jump labels */
9160   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9161        jtab = setNextItem (IC_JTLABELS (ic)))
9162     emitcode ("ljmp", "%05d$", jtab->key + 100);
9163
9164 }
9165
9166 /*-----------------------------------------------------------------*/
9167 /* genCast - gen code for casting                                  */
9168 /*-----------------------------------------------------------------*/
9169 static void
9170 genCast (iCode * ic)
9171 {
9172   operand *result = IC_RESULT (ic);
9173   sym_link *ctype = operandType (IC_LEFT (ic));
9174   sym_link *rtype = operandType (IC_RIGHT (ic));
9175   operand *right = IC_RIGHT (ic);
9176   int size, offset;
9177
9178   D (emitcode (";", "genCast ");
9179     );
9180
9181   /* if they are equivalent then do nothing */
9182   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9183     return;
9184
9185   aopOp (right, ic, FALSE, FALSE);
9186   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9187
9188   /* if the result is a bit */
9189   if (AOP_TYPE (result) == AOP_CRY)
9190     {
9191       /* if the right size is a literal then
9192          we know what the value is */
9193       if (AOP_TYPE (right) == AOP_LIT)
9194         {
9195           if (((int) operandLitValue (right)))
9196             aopPut (AOP (result), one, 0);
9197           else
9198             aopPut (AOP (result), zero, 0);
9199
9200           goto release;
9201         }
9202
9203       /* the right is also a bit variable */
9204       if (AOP_TYPE (right) == AOP_CRY)
9205         {
9206           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9207           aopPut (AOP (result), "c", 0);
9208           goto release;
9209         }
9210
9211       /* we need to or */
9212       toBoolean (right);
9213       aopPut (AOP (result), "a", 0);
9214       goto release;
9215     }
9216
9217   /* if they are the same size : or less */
9218   if (AOP_SIZE (result) <= AOP_SIZE (right))
9219     {
9220
9221       /* if they are in the same place */
9222       if (sameRegs (AOP (right), AOP (result)))
9223         goto release;
9224
9225       /* if they in different places then copy */
9226       size = AOP_SIZE (result);
9227       offset = 0;
9228       _startLazyDPSEvaluation ();
9229       while (size--)
9230         {
9231           aopPut (AOP (result),
9232                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9233                   offset);
9234           offset++;
9235         }
9236       _endLazyDPSEvaluation ();
9237       goto release;
9238     }
9239
9240
9241   /* if the result is of type pointer */
9242   if (IS_PTR (ctype))
9243     {
9244
9245       int p_type;
9246       sym_link *type = operandType (right);
9247
9248       /* pointer to generic pointer */
9249       if (IS_GENPTR (ctype))
9250         {
9251           char *l = zero;
9252
9253           if (IS_PTR (type))
9254             {
9255               p_type = DCL_TYPE (type);
9256             }
9257           else
9258             {
9259 #if OLD_CAST_BEHAVIOR
9260               /* KV: we are converting a non-pointer type to
9261                * a generic pointer. This (ifdef'd out) code
9262                * says that the resulting generic pointer
9263                * should have the same class as the storage
9264                * location of the non-pointer variable.
9265                *
9266                * For example, converting an int (which happens
9267                * to be stored in DATA space) to a pointer results
9268                * in a DATA generic pointer; if the original int
9269                * in XDATA space, so will be the resulting pointer.
9270                *
9271                * I don't like that behavior, and thus this change:
9272                * all such conversions will be forced to XDATA and
9273                * throw a warning. If you want some non-XDATA
9274                * type, or you want to suppress the warning, you
9275                * must go through an intermediate cast, like so:
9276                *
9277                * char _generic *gp = (char _xdata *)(intVar);
9278                */
9279               sym_link *etype = getSpec (type);
9280
9281               /* we have to go by the storage class */
9282               if (SPEC_OCLS (etype) != generic)
9283                 {
9284                   p_type = PTR_TYPE (SPEC_OCLS (etype));
9285                 }
9286               else
9287 #endif
9288                 {
9289                   /* Converting unknown class (i.e. register variable)
9290                    * to generic pointer. This is not good, but
9291                    * we'll make a guess (and throw a warning).
9292                    */
9293                   p_type = FPOINTER;
9294                   werror (W_INT_TO_GEN_PTR_CAST);
9295                 }
9296             }
9297
9298           /* the first two bytes are known */
9299           size = GPTRSIZE - 1;
9300           offset = 0;
9301           _startLazyDPSEvaluation ();
9302           while (size--)
9303             {
9304               aopPut (AOP (result),
9305                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9306                       offset);
9307               offset++;
9308             }
9309           _endLazyDPSEvaluation ();
9310
9311           /* the last byte depending on type */
9312           switch (p_type)
9313             {
9314             case IPOINTER:
9315             case POINTER:
9316               l = zero;
9317               break;
9318             case FPOINTER:
9319               l = one;
9320               break;
9321             case CPOINTER:
9322               l = "#0x02";
9323               break;
9324             case PPOINTER:
9325               l = "#0x03";
9326               break;
9327
9328             default:
9329               /* this should never happen */
9330               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9331                       "got unknown pointer type");
9332               exit (1);
9333             }
9334           aopPut (AOP (result), l, GPTRSIZE - 1);
9335           goto release;
9336         }
9337
9338       /* just copy the pointers */
9339       size = AOP_SIZE (result);
9340       offset = 0;
9341       _startLazyDPSEvaluation ();
9342       while (size--)
9343         {
9344           aopPut (AOP (result),
9345                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9346                   offset);
9347           offset++;
9348         }
9349       _endLazyDPSEvaluation ();
9350       goto release;
9351     }
9352
9353   /* so we now know that the size of destination is greater
9354      than the size of the source */
9355   /* we move to result for the size of source */
9356   size = AOP_SIZE (right);
9357   offset = 0;
9358   _startLazyDPSEvaluation ();
9359   while (size--)
9360     {
9361       aopPut (AOP (result),
9362               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9363               offset);
9364       offset++;
9365     }
9366   _endLazyDPSEvaluation ();
9367
9368   /* now depending on the sign of the source && destination */
9369   size = AOP_SIZE (result) - AOP_SIZE (right);
9370   /* if unsigned or not an integral type */
9371   /* also, if the source is a bit, we don't need to sign extend, because
9372    * it can't possibly have set the sign bit.
9373    */
9374   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9375     {
9376       while (size--)
9377         {
9378           aopPut (AOP (result), zero, offset++);
9379         }
9380     }
9381   else
9382     {
9383       /* we need to extend the sign :{ */
9384       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9385                         FALSE, FALSE, TRUE);
9386       MOVA (l);
9387       emitcode ("rlc", "a");
9388       emitcode ("subb", "a,acc");
9389       while (size--)
9390         aopPut (AOP (result), "a", offset++);
9391     }
9392
9393   /* we are done hurray !!!! */
9394
9395 release:
9396   freeAsmop (right, NULL, ic, TRUE);
9397   freeAsmop (result, NULL, ic, TRUE);
9398
9399 }
9400
9401 /*-----------------------------------------------------------------*/
9402 /* genDjnz - generate decrement & jump if not zero instrucion      */
9403 /*-----------------------------------------------------------------*/
9404 static int
9405 genDjnz (iCode * ic, iCode * ifx)
9406 {
9407   symbol *lbl, *lbl1;
9408   if (!ifx)
9409     return 0;
9410
9411   /* if the if condition has a false label
9412      then we cannot save */
9413   if (IC_FALSE (ifx))
9414     return 0;
9415
9416   /* if the minus is not of the form
9417      a = a - 1 */
9418   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9419       !IS_OP_LITERAL (IC_RIGHT (ic)))
9420     return 0;
9421
9422   if (operandLitValue (IC_RIGHT (ic)) != 1)
9423     return 0;
9424
9425   /* if the size of this greater than one then no
9426      saving */
9427   if (getSize (operandType (IC_RESULT (ic))) > 1)
9428     return 0;
9429
9430   /* otherwise we can save BIG */
9431   D(emitcode(";", "genDjnz"););
9432
9433   lbl = newiTempLabel (NULL);
9434   lbl1 = newiTempLabel (NULL);
9435
9436   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9437
9438   if (AOP_NEEDSACC(IC_RESULT(ic)))
9439   {
9440       /* If the result is accessed indirectly via
9441        * the accumulator, we must explicitly write
9442        * it back after the decrement.
9443        */
9444       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9445       
9446       if (strcmp(rByte, "a"))
9447       {
9448            /* Something is hopelessly wrong */
9449            fprintf(stderr, "*** warning: internal error at %s:%d\n",
9450                    __FILE__, __LINE__);
9451            /* We can just give up; the generated code will be inefficient,
9452             * but what the hey.
9453             */
9454            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9455            return 0;
9456       }
9457       emitcode ("dec", "%s", rByte);
9458       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9459       emitcode ("jnz", "%05d$", lbl->key + 100);
9460   }
9461   else if (IS_AOP_PREG (IC_RESULT (ic)))
9462     {
9463       emitcode ("dec", "%s",
9464                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9465       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9466       emitcode ("jnz", "%05d$", lbl->key + 100);
9467     }
9468   else
9469     {
9470       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9471                 lbl->key + 100);
9472     }
9473   emitcode ("sjmp", "%05d$", lbl1->key + 100);
9474   emitcode ("", "%05d$:", lbl->key + 100);
9475   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9476   emitcode ("", "%05d$:", lbl1->key + 100);
9477
9478   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9479   ifx->generated = 1;
9480   return 1;
9481 }
9482
9483 /*-----------------------------------------------------------------*/
9484 /* genReceive - generate code for a receive iCode                  */
9485 /*-----------------------------------------------------------------*/
9486 static void
9487 genReceive (iCode * ic)
9488 {
9489
9490   D (emitcode (";", "genReceive ");
9491     );
9492
9493   if (isOperandInFarSpace (IC_RESULT (ic)) &&
9494       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9495        IS_TRUE_SYMOP (IC_RESULT (ic))))
9496     {
9497       int size = getSize (operandType (IC_RESULT (ic)));
9498       int offset = fReturnSizeDS390 - size;
9499       while (size--)
9500         {
9501           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9502                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9503           offset++;
9504         }
9505       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9506       size = AOP_SIZE (IC_RESULT (ic));
9507       offset = 0;
9508       while (size--)
9509         {
9510           emitcode ("pop", "acc");
9511           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9512         }
9513
9514     }
9515   else
9516     {
9517       _G.accInUse++;
9518       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9519       _G.accInUse--;
9520       assignResultValue (IC_RESULT (ic));
9521     }
9522
9523   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9524 }
9525
9526 /*-----------------------------------------------------------------*/
9527 /* gen390Code - generate code for Dallas 390 based controllers     */
9528 /*-----------------------------------------------------------------*/
9529 void
9530 gen390Code (iCode * lic)
9531 {
9532   iCode *ic;
9533   int cln = 0;
9534
9535   lineHead = lineCurr = NULL;
9536
9537 #if 0
9538   //REMOVE ME!!!
9539   /* print the allocation information */
9540   if (allocInfo)
9541     printAllocInfo (currFunc, codeOutFile);
9542 #endif
9543   /* if debug information required */
9544   if (options.debug && currFunc)
9545     {
9546       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9547       _G.debugLine = 1;
9548       if (IS_STATIC (currFunc->etype))
9549         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9550       else
9551         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9552       _G.debugLine = 0;
9553     }
9554   /* stack pointer name */
9555   if (options.useXstack)
9556     spname = "_spx";
9557   else
9558     spname = "sp";
9559
9560
9561   for (ic = lic; ic; ic = ic->next)
9562     {
9563
9564       if (cln != ic->lineno)
9565         {
9566           if (options.debug)
9567             {
9568               _G.debugLine = 1;
9569               emitcode ("", "C$%s$%d$%d$%d ==.",
9570                         FileBaseName (ic->filename), ic->lineno,
9571                         ic->level, ic->block);
9572               _G.debugLine = 0;
9573             }
9574           emitcode (";", "%s %d", ic->filename, ic->lineno);
9575           cln = ic->lineno;
9576         }
9577       /* if the result is marked as
9578          spilt and rematerializable or code for
9579          this has already been generated then
9580          do nothing */
9581       if (resultRemat (ic) || ic->generated)
9582         continue;
9583
9584       /* depending on the operation */
9585       switch (ic->op)
9586         {
9587         case '!':
9588           genNot (ic);
9589           break;
9590
9591         case '~':
9592           genCpl (ic);
9593           break;
9594
9595         case UNARYMINUS:
9596           genUminus (ic);
9597           break;
9598
9599         case IPUSH:
9600           genIpush (ic);
9601           break;
9602
9603         case IPOP:
9604           /* IPOP happens only when trying to restore a
9605              spilt live range, if there is an ifx statement
9606              following this pop then the if statement might
9607              be using some of the registers being popped which
9608              would destory the contents of the register so
9609              we need to check for this condition and handle it */
9610           if (ic->next &&
9611               ic->next->op == IFX &&
9612               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9613             genIfx (ic->next, ic);
9614           else
9615             genIpop (ic);
9616           break;
9617
9618         case CALL:
9619           genCall (ic);
9620           break;
9621
9622         case PCALL:
9623           genPcall (ic);
9624           break;
9625
9626         case FUNCTION:
9627           genFunction (ic);
9628           break;
9629
9630         case ENDFUNCTION:
9631           genEndFunction (ic);
9632           break;
9633
9634         case RETURN:
9635           genRet (ic);
9636           break;
9637
9638         case LABEL:
9639           genLabel (ic);
9640           break;
9641
9642         case GOTO:
9643           genGoto (ic);
9644           break;
9645
9646         case '+':
9647           genPlus (ic);
9648           break;
9649
9650         case '-':
9651           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9652             genMinus (ic);
9653           break;
9654
9655         case '*':
9656           genMult (ic);
9657           break;
9658
9659         case '/':
9660           genDiv (ic);
9661           break;
9662
9663         case '%':
9664           genMod (ic);
9665           break;
9666
9667         case '>':
9668           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9669           break;
9670
9671         case '<':
9672           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9673           break;
9674
9675         case LE_OP:
9676         case GE_OP:
9677         case NE_OP:
9678
9679           /* note these two are xlated by algebraic equivalence
9680              during parsing SDCC.y */
9681           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9682                   "got '>=' or '<=' shouldn't have come here");
9683           break;
9684
9685         case EQ_OP:
9686           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9687           break;
9688
9689         case AND_OP:
9690           genAndOp (ic);
9691           break;
9692
9693         case OR_OP:
9694           genOrOp (ic);
9695           break;
9696
9697         case '^':
9698           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9699           break;
9700
9701         case '|':
9702           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9703           break;
9704
9705         case BITWISEAND:
9706           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9707           break;
9708
9709         case INLINEASM:
9710           genInline (ic);
9711           break;
9712
9713         case RRC:
9714           genRRC (ic);
9715           break;
9716
9717         case RLC:
9718           genRLC (ic);
9719           break;
9720
9721         case GETHBIT:
9722           genGetHbit (ic);
9723           break;
9724
9725         case LEFT_OP:
9726           genLeftShift (ic);
9727           break;
9728
9729         case RIGHT_OP:
9730           genRightShift (ic);
9731           break;
9732
9733         case GET_VALUE_AT_ADDRESS:
9734           genPointerGet (ic);
9735           break;
9736
9737         case '=':
9738           if (POINTER_SET (ic))
9739             genPointerSet (ic);
9740           else
9741             genAssign (ic);
9742           break;
9743
9744         case IFX:
9745           genIfx (ic, NULL);
9746           break;
9747
9748         case ADDRESS_OF:
9749           genAddrOf (ic);
9750           break;
9751
9752         case JUMPTABLE:
9753           genJumpTab (ic);
9754           break;
9755
9756         case CAST:
9757           genCast (ic);
9758           break;
9759
9760         case RECEIVE:
9761           genReceive (ic);
9762           break;
9763
9764         case SEND:
9765           addSet (&_G.sendSet, ic);
9766           break;
9767
9768         default:
9769           ic = ic;
9770         }
9771     }
9772
9773
9774   /* now we are ready to call the
9775      peep hole optimizer */
9776   if (!options.nopeep)
9777     peepHole (&lineHead);
9778
9779   /* now do the actual printing */
9780   printLine (lineHead, codeOutFile);
9781   return;
9782 }