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