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