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