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