6f1f6e13448d0ed7df9fbc5249ec27934c251754
[fw/sdcc] / src / ds390 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for DS80C390
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
8
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23   In other words, you are welcome to use, share and improve this program.
24   You are forbidden to forbid anyone else to use, share and improve
25   what you give them.   Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32
33 #include <common.h>
34 #include "ralloc.h"
35 #include "gen.h"
36 #include "SDCCglobl.h"
37 #include "newalloc.h"
38
39 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
41 #else
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
44 #else
45 #ifdef HAVE_ENDIAN_H
46 #include <endian.h>
47 #else
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
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 #endif
55
56 #define BETTER_LITERAL_SHIFT
57
58 char *aopLiteral (value * val, int offset);
59
60 /* this is the down and dirty file with all kinds of
61    kludgy & hacky stuff. This is what it is all about
62    CODE GENERATION for a specific MCU . some of the
63    routines may be reusable, will have to see */
64
65 static char *zero = "#0x00";
66 static char *one = "#0x01";
67 static char *spname;
68
69 #define D(x) x
70
71 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
72 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
73
74 unsigned fReturnSizeDS390 = 5;  /* shared with ralloc.c */
75 static char *fReturn24[] =
76 {"dpl", "dph", "dpx", "b", "a"};
77 static char *fReturn16[] =
78 {"dpl", "dph", "b", "a"};
79 static char **fReturn = fReturn24;
80 static char *accUse[] =
81 {"a", "b"};
82
83 static short rbank = -1;
84
85 static struct
86   {
87     short r0Pushed;
88     short r1Pushed;
89     short accInUse;
90     short inLine;
91     short debugLine;
92     short nRegsSaved;
93     set *sendSet;
94   }
95 _G;
96
97 static void saveRBank (int, iCode *, bool);
98
99 #define RESULTONSTACK(x) \
100                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
101                          IC_RESULT(x)->aop->type == AOP_STK )
102
103 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
104 #define MOVA(x) { char *_mova_tmp = strdup(x); \
105                  if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
106                  { \
107                     emitcode("mov","a,%s",_mova_tmp); \
108                  } \
109                  free(_mova_tmp); \
110                 }
111 #define CLRC    emitcode("clr","c")
112 #define SETC    emitcode("setb","c")
113
114 // A scratch register which will be used to hold
115 // result bytes from operands in far space via DPTR2.
116 #define DP2_RESULT_REG  "ap"
117
118 static lineNode *lineHead = NULL;
119 static lineNode *lineCurr = NULL;
120
121 static unsigned char SLMask[] =
122 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
123  0xE0, 0xC0, 0x80, 0x00};
124 static unsigned char SRMask[] =
125 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
126  0x07, 0x03, 0x01, 0x00};
127
128 #define LSB     0
129 #define MSB16   1
130 #define MSB24   2
131 #define MSB32   3
132
133 /*-----------------------------------------------------------------*/
134 /* emitcode - writes the code into a file : for now it is simple    */
135 /*-----------------------------------------------------------------*/
136 static void
137 emitcode (char *inst, char *fmt,...)
138 {
139   va_list ap;
140   char lb[INITIAL_INLINEASM];
141   char *lbp = lb;
142
143   va_start (ap, fmt);
144
145   if (inst && *inst)
146     {
147       if (fmt && *fmt)
148         sprintf (lb, "%s\t", inst);
149       else
150         sprintf (lb, "%s", inst);
151       vsprintf (lb + (strlen (lb)), fmt, ap);
152     }
153   else
154     vsprintf (lb, fmt, ap);
155
156   while (isspace (*lbp))
157     lbp++;
158
159   if (lbp && *lbp)
160     lineCurr = (lineCurr ?
161                 connectLine (lineCurr, newLineNode (lb)) :
162                 (lineHead = newLineNode (lb)));
163   lineCurr->isInline = _G.inLine;
164   lineCurr->isDebug = _G.debugLine;
165   va_end (ap);
166 }
167
168 /*-----------------------------------------------------------------*/
169 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
170 /*-----------------------------------------------------------------*/
171 static regs *
172 getFreePtr (iCode * ic, asmop ** aopp, bool result)
173 {
174   bool r0iu = FALSE, r1iu = FALSE;
175   bool r0ou = FALSE, r1ou = FALSE;
176
177   /* the logic: if r0 & r1 used in the instruction
178      then we are in trouble otherwise */
179
180   /* first check if r0 & r1 are used by this
181      instruction, in which case we are in trouble */
182   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
183   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
184   if (r0iu && r1iu) {
185       goto endOfWorld;
186     }
187
188   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
189   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
190
191   /* if no usage of r0 then return it */
192   if (!r0iu && !r0ou)
193     {
194       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
195       (*aopp)->type = AOP_R0;
196
197       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
198     }
199
200   /* if no usage of r1 then return it */
201   if (!r1iu && !r1ou)
202     {
203       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
204       (*aopp)->type = AOP_R1;
205
206       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
207     }
208
209   /* now we know they both have usage */
210   /* if r0 not used in this instruction */
211   if (!r0iu)
212     {
213       /* push it if not already pushed */
214       if (!_G.r0Pushed)
215         {
216           emitcode ("push", "%s",
217                     ds390_regWithIdx (R0_IDX)->dname);
218           _G.r0Pushed++;
219         }
220
221       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
222       (*aopp)->type = AOP_R0;
223
224       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
225     }
226
227   /* if r1 not used then */
228
229   if (!r1iu)
230     {
231       /* push it if not already pushed */
232       if (!_G.r1Pushed)
233         {
234           emitcode ("push", "%s",
235                     ds390_regWithIdx (R1_IDX)->dname);
236           _G.r1Pushed++;
237         }
238
239       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
240       (*aopp)->type = AOP_R1;
241       return ds390_regWithIdx (R1_IDX);
242     }
243
244 endOfWorld:
245   /* I said end of world but not quite end of world yet */
246   /* if this is a result then we can push it on the stack */
247   if (result)
248     {
249       (*aopp)->type = AOP_STK;
250       return NULL;
251     }
252
253   /* other wise this is true end of the world */
254   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
255           "getFreePtr should never reach here");
256   exit (1);
257 }
258
259 /*-----------------------------------------------------------------*/
260 /* newAsmop - creates a new asmOp                                  */
261 /*-----------------------------------------------------------------*/
262 static asmop *
263 newAsmop (short type)
264 {
265   asmop *aop;
266
267   aop = Safe_calloc (1, sizeof (asmop));
268   aop->type = type;
269   return aop;
270 }
271
272 static int _currentDPS;         /* Current processor DPS. */
273 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
274 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
275
276 /*-----------------------------------------------------------------*/
277 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
278 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
279 /* alternate DPTR (DPL1/DPH1/DPX1).          */
280 /*-----------------------------------------------------------------*/
281 static void
282 genSetDPTR (int n)
283 {
284
285   /* If we are doing lazy evaluation, simply note the desired
286    * change, but don't emit any code yet.
287    */
288   if (_lazyDPS)
289     {
290       _desiredDPS = n;
291       return;
292     }
293
294   if (!n)
295     {
296       emitcode ("mov", "dps, #0x00");
297     }
298   else
299     {
300       TR_DPTR("#1");
301       emitcode ("mov", "dps, #0x01");
302     }
303 }
304
305 /*-----------------------------------------------------------------*/
306 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
307 /*                   */
308 /* Any code that operates on DPTR (NB: not on the individual     */
309 /* components, like DPH) *must* call _flushLazyDPS() before using  */
310 /* DPTR within a lazy DPS evaluation block.        */
311 /*                   */
312 /* Note that aopPut and aopGet already contain the proper calls to */
313 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
314 /* DPS evaluation block.             */
315 /*                   */
316 /* Also, _flushLazyDPS must be called before any flow control      */
317 /* operations that could potentially branch out of the block.    */
318 /*                         */
319 /* Lazy DPS evaluation is simply an optimization (though an      */
320 /* important one), so if in doubt, leave it out.       */
321 /*-----------------------------------------------------------------*/
322 static void
323 _startLazyDPSEvaluation (void)
324 {
325   _currentDPS = 0;
326   _desiredDPS = 0;
327 #ifdef BETTER_LITERAL_SHIFT  
328   _lazyDPS++;
329 #else
330   _lazyDPS = 1;
331 #endif  
332 }
333
334 /*-----------------------------------------------------------------*/
335 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
336 /* desired one. Call before using DPTR within a lazy DPS evaluation */
337 /* block.                */
338 /*-----------------------------------------------------------------*/
339 static void
340 _flushLazyDPS (void)
341 {
342   if (!_lazyDPS)
343     {
344       /* nothing to do. */
345       return;
346     }
347
348   if (_desiredDPS != _currentDPS)
349     {
350       if (_desiredDPS)
351         {
352           emitcode ("inc", "dps");
353         }
354       else
355         {
356           emitcode ("dec", "dps");
357         }
358       _currentDPS = _desiredDPS;
359     }
360 }
361
362 /*-----------------------------------------------------------------*/
363 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
364 /*                   */
365 /* Forces us back to the safe state (standard DPTR selected).    */
366 /*-----------------------------------------------------------------*/
367 static void
368 _endLazyDPSEvaluation (void)
369 {
370 #ifdef BETTER_LITERAL_SHIFT  
371   _lazyDPS--;
372 #else
373   _lazyDPS = 0;
374 #endif    
375   if (!_lazyDPS)
376   {
377     if (_currentDPS)
378     {
379       genSetDPTR (0);
380       _flushLazyDPS ();
381     }
382     _currentDPS = 0;
383     _desiredDPS = 0;
384   }
385 }
386
387
388
389 /*-----------------------------------------------------------------*/
390 /* pointerCode - returns the code for a pointer type               */
391 /*-----------------------------------------------------------------*/
392 static int
393 pointerCode (sym_link * etype)
394 {
395
396   return PTR_TYPE (SPEC_OCLS (etype));
397
398 }
399
400 /*-----------------------------------------------------------------*/
401 /* aopForSym - for a true symbol                                   */
402 /*-----------------------------------------------------------------*/
403 static asmop *
404 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
405 {
406   asmop *aop;
407   memmap *space = SPEC_OCLS (sym->etype);
408
409   /* if already has one */
410   if (sym->aop)
411     return sym->aop;
412
413   /* assign depending on the storage class */
414   /* if it is on the stack or indirectly addressable */
415   /* space we need to assign either r0 or r1 to it   */
416   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
417     {
418       sym->aop = aop = newAsmop (0);
419       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
420       aop->size = getSize (sym->type);
421
422       /* now assign the address of the variable to
423          the pointer register */
424       if (aop->type != AOP_STK)
425         {
426
427           if (sym->onStack)
428             {
429               if (_G.accInUse)
430                 emitcode ("push", "acc");
431
432               emitcode ("mov", "a,_bp");
433               emitcode ("add", "a,#0x%02x",
434                         ((sym->stack < 0) ?
435                          ((char) (sym->stack - _G.nRegsSaved)) :
436                          ((char) sym->stack)) & 0xff);
437               emitcode ("mov", "%s,a",
438                         aop->aopu.aop_ptr->name);
439
440               if (_G.accInUse)
441                 emitcode ("pop", "acc");
442             }
443           else
444             emitcode ("mov", "%s,#%s",
445                       aop->aopu.aop_ptr->name,
446                       sym->rname);
447           aop->paged = space->paged;
448         }
449       else
450         aop->aopu.aop_stk = sym->stack;
451       return aop;
452     }
453
454   if (sym->onStack && options.stack10bit)
455     {
456       /* It's on the 10 bit stack, which is located in
457        * far data space.
458        */
459
460       if (_G.accInUse)
461         emitcode ("push", "acc");
462
463       emitcode ("mov", "a,_bp");
464       emitcode ("add", "a,#0x%02x",
465                 ((sym->stack < 0) ?
466                  ((char) (sym->stack - _G.nRegsSaved)) :
467                  ((char) sym->stack)) & 0xff);
468
469       if (useDP2)
470         {
471           if (options.model == MODEL_FLAT24)
472             emitcode ("mov", "dpx1,#0x40");
473           TR_DPTR("#2");
474           emitcode ("mov", "dph1,#0x00");
475           emitcode ("mov", "dpl1, a");
476         }
477       else
478         {
479           if (options.model == MODEL_FLAT24)
480             emitcode ("mov", "dpx,#0x40");
481           emitcode ("mov", "dph,#0x00");
482           emitcode ("mov", "dpl, a");
483         }
484
485       if (_G.accInUse)
486         emitcode ("pop", "acc");
487
488       sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
489       aop->size = getSize (sym->type);
490       return aop;
491     }
492
493   /* if in bit space */
494   if (IN_BITSPACE (space))
495     {
496       sym->aop = aop = newAsmop (AOP_CRY);
497       aop->aopu.aop_dir = sym->rname;
498       aop->size = getSize (sym->type);
499       return aop;
500     }
501   /* if it is in direct space */
502   if (IN_DIRSPACE (space))
503     {
504       sym->aop = aop = newAsmop (AOP_DIR);
505       aop->aopu.aop_dir = sym->rname;
506       aop->size = getSize (sym->type);
507       return aop;
508     }
509
510   /* special case for a function */
511   if (IS_FUNC (sym->type))
512     {
513       sym->aop = aop = newAsmop (AOP_IMMD);
514       aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
515       strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
516       aop->size = FPTRSIZE;
517       return aop;
518     }
519
520   /* only remaining is far space */
521   /* in which case DPTR gets the address */
522   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
523   if (useDP2)
524     {
525       genSetDPTR (1);
526       _flushLazyDPS ();
527       emitcode ("mov", "dptr,#%s", sym->rname);
528       genSetDPTR (0);
529     }
530   else
531     {
532       emitcode ("mov", "dptr,#%s", sym->rname);
533     }
534   aop->size = getSize (sym->type);
535
536   /* if it is in code space */
537   if (IN_CODESPACE (space))
538     aop->code = 1;
539
540   return aop;
541 }
542
543 /*-----------------------------------------------------------------*/
544 /* aopForRemat - rematerialzes an object                           */
545 /*-----------------------------------------------------------------*/
546 static asmop *
547 aopForRemat (symbol * sym)
548 {
549   iCode *ic = sym->rematiCode;
550   asmop *aop = newAsmop (AOP_IMMD);
551   int ptr_type =0;
552   int val = 0;
553
554   for (;;)
555     {
556       if (ic->op == '+')
557         val += (int) operandLitValue (IC_RIGHT (ic));
558       else if (ic->op == '-')
559         val -= (int) operandLitValue (IC_RIGHT (ic));
560       else if (IS_CAST_ICODE(ic)) {
561               sym_link *from_type = operandType(IC_RIGHT(ic));
562               aop->aopu.aop_immd.from_cast_remat = 1;
563               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
564               ptr_type = DCL_TYPE(from_type);
565               continue ;
566       } else break;
567       
568       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
569     }
570
571   if (val)
572     sprintf (buffer, "(%s %c 0x%04x)",
573              OP_SYMBOL (IC_LEFT (ic))->rname,
574              val >= 0 ? '+' : '-',
575              abs (val) & 0xffff);
576   else
577     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
578
579   aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
580   strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
581   /* set immd2 field if required */
582   if (aop->aopu.aop_immd.from_cast_remat) {
583           sprintf(buffer,"#0x%02x",ptr_type);
584           aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
585           strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
586   }
587
588   return aop;
589 }
590
591 /*-----------------------------------------------------------------*/
592 /* regsInCommon - two operands have some registers in common       */
593 /*-----------------------------------------------------------------*/
594 static bool
595 regsInCommon (operand * op1, operand * op2)
596 {
597   symbol *sym1, *sym2;
598   int i;
599
600   /* if they have registers in common */
601   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
602     return FALSE;
603
604   sym1 = OP_SYMBOL (op1);
605   sym2 = OP_SYMBOL (op2);
606
607   if (sym1->nRegs == 0 || sym2->nRegs == 0)
608     return FALSE;
609
610   for (i = 0; i < sym1->nRegs; i++)
611     {
612       int j;
613       if (!sym1->regs[i])
614         continue;
615
616       for (j = 0; j < sym2->nRegs; j++)
617         {
618           if (!sym2->regs[j])
619             continue;
620
621           if (sym2->regs[j] == sym1->regs[i])
622             return TRUE;
623         }
624     }
625
626   return FALSE;
627 }
628
629 /*-----------------------------------------------------------------*/
630 /* operandsEqu - equivalent                                        */
631 /*-----------------------------------------------------------------*/
632 static bool
633 operandsEqu (operand * op1, operand * op2)
634 {
635   symbol *sym1, *sym2;
636
637   /* if they not symbols */
638   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
639     return FALSE;
640
641   sym1 = OP_SYMBOL (op1);
642   sym2 = OP_SYMBOL (op2);
643
644   /* if both are itemps & one is spilt
645      and the other is not then false */
646   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
647       sym1->isspilt != sym2->isspilt)
648     return FALSE;
649
650   /* if they are the same */
651   if (sym1 == sym2)
652     return TRUE;
653
654   if (strcmp (sym1->rname, sym2->rname) == 0)
655     return TRUE;
656
657
658   /* if left is a tmp & right is not */
659   if (IS_ITEMP (op1) &&
660       !IS_ITEMP (op2) &&
661       sym1->isspilt &&
662       (sym1->usl.spillLoc == sym2))
663     return TRUE;
664
665   if (IS_ITEMP (op2) &&
666       !IS_ITEMP (op1) &&
667       sym2->isspilt &&
668       sym1->level > 0 &&
669       (sym2->usl.spillLoc == sym1))
670     return TRUE;
671
672   return FALSE;
673 }
674
675 /*-----------------------------------------------------------------*/
676 /* sameRegs - two asmops have the same registers                   */
677 /*-----------------------------------------------------------------*/
678 static bool
679 sameRegs (asmop * aop1, asmop * aop2)
680 {
681   int i;
682
683   if (aop1 == aop2)
684     {
685       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
686         {
687           return FALSE;
688         }
689       return TRUE;
690     }
691
692   if (aop1->type != AOP_REG ||
693       aop2->type != AOP_REG)
694     return FALSE;
695
696   if (aop1->size != aop2->size)
697     return FALSE;
698
699   for (i = 0; i < aop1->size; i++)
700     if (aop1->aopu.aop_reg[i] !=
701         aop2->aopu.aop_reg[i])
702       return FALSE;
703
704   return TRUE;
705 }
706
707 /*-----------------------------------------------------------------*/
708 /* aopOp - allocates an asmop for an operand  :                    */
709 /*-----------------------------------------------------------------*/
710 static void
711 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
712 {
713   asmop *aop;
714   symbol *sym;
715   int i;
716
717   if (!op)
718     return;
719
720   /* if this a literal */
721   if (IS_OP_LITERAL (op))
722     {
723       op->aop = aop = newAsmop (AOP_LIT);
724       aop->aopu.aop_lit = op->operand.valOperand;
725       aop->size = getSize (operandType (op));
726       return;
727     }
728
729   /* if already has a asmop then continue */
730   if (op->aop)
731     return;
732
733   /* if the underlying symbol has a aop */
734   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
735     {
736       op->aop = OP_SYMBOL (op)->aop;
737       return;
738     }
739
740   /* if this is a true symbol */
741   if (IS_TRUE_SYMOP (op))
742     {
743       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
744       return;
745     }
746
747   /* this is a temporary : this has
748      only four choices :
749      a) register
750      b) spillocation
751      c) rematerialize
752      d) conditional
753      e) can be a return use only */
754
755   sym = OP_SYMBOL (op);
756
757
758   /* if the type is a conditional */
759   if (sym->regType == REG_CND)
760     {
761       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
762       aop->size = 0;
763       return;
764     }
765
766   /* if it is spilt then two situations
767      a) is rematerialize
768      b) has a spill location */
769   if (sym->isspilt || sym->nRegs == 0)
770     {
771
772       /* rematerialize it NOW */
773       if (sym->remat)
774         {
775           sym->aop = op->aop = aop =
776             aopForRemat (sym);
777           aop->size = getSize (sym->type);
778           return;
779         }
780
781       if (sym->accuse)
782         {
783           int i;
784           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
785           aop->size = getSize (sym->type);
786           for (i = 0; i < 2; i++)
787             aop->aopu.aop_str[i] = accUse[i];
788           return;
789         }
790
791       if (sym->ruonly)
792         {
793           int i;
794
795           if (useDP2)
796             {
797               /* a AOP_STR uses DPTR, but DPTR is already in use;
798                * we're just hosed.
799                */
800               fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
801             }
802
803           aop = op->aop = sym->aop = newAsmop (AOP_STR);
804           aop->size = getSize (sym->type);
805           for (i = 0; i < (int) fReturnSizeDS390; i++)
806             aop->aopu.aop_str[i] = fReturn[i];
807           return;
808         }
809
810       /* else spill location  */
811       sym->aop = op->aop = aop =
812         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
813       aop->size = getSize (sym->type);
814       return;
815     }
816
817   /* must be in a register */
818   sym->aop = op->aop = aop = newAsmop (AOP_REG);
819   aop->size = sym->nRegs;
820   for (i = 0; i < sym->nRegs; i++)
821     aop->aopu.aop_reg[i] = sym->regs[i];
822 }
823
824 /*-----------------------------------------------------------------*/
825 /* freeAsmop - free up the asmop given to an operand               */
826 /*----------------------------------------------------------------*/
827 static void
828 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
829 {
830   asmop *aop;
831
832   if (!op)
833     aop = aaop;
834   else
835     aop = op->aop;
836
837   if (!aop)
838     return;
839
840   if (aop->freed)
841     goto dealloc;
842
843   aop->freed = 1;
844
845   /* depending on the asmop type only three cases need work AOP_RO
846      , AOP_R1 && AOP_STK */
847   switch (aop->type)
848     {
849     case AOP_R0:
850       if (_G.r0Pushed)
851         {
852           if (pop)
853             {
854               emitcode ("pop", "ar0");
855               _G.r0Pushed--;
856             }
857         }
858       bitVectUnSetBit (ic->rUsed, R0_IDX);
859       break;
860
861     case AOP_R1:
862       if (_G.r1Pushed)
863         {
864           if (pop)
865             {
866               emitcode ("pop", "ar1");
867               _G.r1Pushed--;
868             }
869         }
870       bitVectUnSetBit (ic->rUsed, R1_IDX);
871       break;
872
873     case AOP_STK:
874       {
875         int sz = aop->size;
876         int stk = aop->aopu.aop_stk + aop->size;
877         bitVectUnSetBit (ic->rUsed, R0_IDX);
878         bitVectUnSetBit (ic->rUsed, R1_IDX);
879
880         getFreePtr (ic, &aop, FALSE);
881
882         if (options.stack10bit)
883           {
884             /* I'm not sure what to do here yet... */
885             /* #STUB */
886             fprintf (stderr,
887                      "*** Warning: probably generating bad code for "
888                      "10 bit stack mode.\n");
889           }
890
891         if (stk)
892           {
893             emitcode ("mov", "a,_bp");
894             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
895             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
896           }
897         else
898           {
899             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
900           }
901
902         while (sz--)
903           {
904             emitcode ("pop", "acc");
905             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
906             if (!sz)
907               break;
908             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
909           }
910         op->aop = aop;
911         freeAsmop (op, NULL, ic, TRUE);
912         if (_G.r0Pushed)
913           {
914             emitcode ("pop", "ar0");
915             _G.r0Pushed--;
916           }
917
918         if (_G.r1Pushed)
919           {
920             emitcode ("pop", "ar1");
921             _G.r1Pushed--;
922           }
923       }
924     }
925
926 dealloc:
927   /* all other cases just dealloc */
928   if (op)
929     {
930       op->aop = NULL;
931       if (IS_SYMOP (op))
932         {
933           OP_SYMBOL (op)->aop = NULL;
934           /* if the symbol has a spill */
935           if (SPIL_LOC (op))
936             SPIL_LOC (op)->aop = NULL;
937         }
938     }
939 }
940
941 /*------------------------------------------------------------------*/
942 /* aopGet - for fetching value of the aop                           */
943 /*                    */
944 /* Set canClobberACC if you are sure it is OK to clobber the value  */
945 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
946 /* just less efficient.               */
947 /*------------------------------------------------------------------*/
948
949 static char *
950 aopGet (asmop * aop,
951         int offset,
952         bool bit16,
953         bool dname,
954         bool canClobberACC)
955 {
956   char *s = buffer;
957   char *rs;
958
959   /* offset is greater than
960      size then zero */
961   if (offset > (aop->size - 1) &&
962       aop->type != AOP_LIT)
963     return zero;
964
965   /* depending on type */
966   switch (aop->type)
967     {
968
969     case AOP_R0:
970     case AOP_R1:
971       /* if we need to increment it */
972       while (offset > aop->coff)
973         {
974           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
975           aop->coff++;
976         }
977
978       while (offset < aop->coff)
979         {
980           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
981           aop->coff--;
982         }
983
984       aop->coff = offset;
985       if (aop->paged)
986         {
987           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
988           return (dname ? "acc" : "a");
989         }
990       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
991       rs = Safe_calloc (1, strlen (s) + 1);
992       strcpy (rs, s);
993       return rs;
994
995     case AOP_DPTR:
996     case AOP_DPTR2:
997
998       if (aop->type == AOP_DPTR2)
999         {
1000           genSetDPTR (1);
1001           if (!canClobberACC)
1002             {
1003                     TR_AP("#1");
1004                     emitcode ("xch", "a, %s", DP2_RESULT_REG);
1005             }
1006         }
1007
1008       _flushLazyDPS ();
1009
1010       while (offset > aop->coff)
1011         {
1012           emitcode ("inc", "dptr");
1013           aop->coff++;
1014         }
1015
1016       while (offset < aop->coff)
1017         {
1018           emitcode ("lcall", "__decdptr");
1019           aop->coff--;
1020         }
1021
1022       aop->coff = offset;
1023       if (aop->code)
1024         {
1025           emitcode ("clr", "a");
1026           emitcode ("movc", "a,@a+dptr");
1027         }
1028       else
1029         {
1030           emitcode ("movx", "a,@dptr");
1031         }
1032
1033       if (aop->type == AOP_DPTR2)
1034         {
1035           genSetDPTR (0);
1036           if (!canClobberACC)
1037             {
1038        TR_AP("#2");
1039               emitcode ("xch", "a, %s", DP2_RESULT_REG);
1040               return DP2_RESULT_REG;
1041             }
1042         }
1043       return (dname ? "acc" : "a");
1044
1045     case AOP_IMMD:
1046       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1047               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1048       } else if (bit16)
1049         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1050       else if (offset)
1051         sprintf (s, "#(%s >> %d)",
1052                  aop->aopu.aop_immd.aop_immd1,
1053                  offset * 8);
1054       else
1055         sprintf (s, "#%s",
1056                  aop->aopu.aop_immd.aop_immd1);
1057       rs = Safe_calloc (1, strlen (s) + 1);
1058       strcpy (rs, s);
1059       return rs;
1060
1061     case AOP_DIR:
1062       if (offset)
1063         sprintf (s, "(%s + %d)",
1064                  aop->aopu.aop_dir,
1065                  offset);
1066       else
1067         sprintf (s, "%s", aop->aopu.aop_dir);
1068       rs = Safe_calloc (1, strlen (s) + 1);
1069       strcpy (rs, s);
1070       return rs;
1071
1072     case AOP_REG:
1073       if (dname)
1074         return aop->aopu.aop_reg[offset]->dname;
1075       else
1076         return aop->aopu.aop_reg[offset]->name;
1077
1078     case AOP_CRY:
1079       emitcode ("clr", "a");
1080       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1081       emitcode ("rlc", "a");
1082       return (dname ? "acc" : "a");
1083
1084     case AOP_ACC:
1085       if (!offset && dname)
1086         return "acc";
1087       return aop->aopu.aop_str[offset];
1088
1089     case AOP_LIT:
1090       return aopLiteral (aop->aopu.aop_lit, offset);
1091
1092     case AOP_STR:
1093       aop->coff = offset;
1094       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1095           dname)
1096         return "acc";
1097
1098       return aop->aopu.aop_str[offset];
1099
1100     }
1101
1102   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1103           "aopget got unsupported aop->type");
1104   exit (1);
1105 }
1106 /*-----------------------------------------------------------------*/
1107 /* aopPut - puts a string for a aop                                */
1108 /*-----------------------------------------------------------------*/
1109 static void
1110 aopPut (asmop * aop, char *s, int offset)
1111 {
1112   char *d = buffer;
1113
1114   if (aop->size && offset > (aop->size - 1))
1115     {
1116       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1117               "aopPut got offset > aop->size");
1118       exit (1);
1119     }
1120
1121   /* will assign value to value */
1122   /* depending on where it is ofcourse */
1123   switch (aop->type)
1124     {
1125     case AOP_DIR:
1126       if (offset)
1127         sprintf (d, "(%s + %d)",
1128                  aop->aopu.aop_dir, offset);
1129       else
1130         sprintf (d, "%s", aop->aopu.aop_dir);
1131
1132       if (strcmp (d, s))
1133         emitcode ("mov", "%s,%s", d, s);
1134
1135       break;
1136
1137     case AOP_REG:
1138       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1139           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1140         {
1141           if (*s == '@' ||
1142               strcmp (s, "r0") == 0 ||
1143               strcmp (s, "r1") == 0 ||
1144               strcmp (s, "r2") == 0 ||
1145               strcmp (s, "r3") == 0 ||
1146               strcmp (s, "r4") == 0 ||
1147               strcmp (s, "r5") == 0 ||
1148               strcmp (s, "r6") == 0 ||
1149               strcmp (s, "r7") == 0)
1150             emitcode ("mov", "%s,%s",
1151                       aop->aopu.aop_reg[offset]->dname, s);
1152           else
1153             emitcode ("mov", "%s,%s",
1154                       aop->aopu.aop_reg[offset]->name, s);
1155         }
1156       break;
1157
1158     case AOP_DPTR:
1159     case AOP_DPTR2:
1160
1161       if (aop->type == AOP_DPTR2)
1162         {
1163           genSetDPTR (1);
1164         }
1165       _flushLazyDPS ();
1166
1167       if (aop->code)
1168         {
1169           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1170                   "aopPut writting to code space");
1171           exit (1);
1172         }
1173
1174       while (offset > aop->coff)
1175         {
1176           aop->coff++;
1177           emitcode ("inc", "dptr");
1178         }
1179
1180       while (offset < aop->coff)
1181         {
1182           aop->coff--;
1183           emitcode ("lcall", "__decdptr");
1184         }
1185
1186       aop->coff = offset;
1187
1188       /* if not in accumulater */
1189       MOVA (s);
1190
1191       emitcode ("movx", "@dptr,a");
1192
1193       if (aop->type == AOP_DPTR2)
1194         {
1195           genSetDPTR (0);
1196         }
1197       break;
1198
1199     case AOP_R0:
1200     case AOP_R1:
1201       while (offset > aop->coff)
1202         {
1203           aop->coff++;
1204           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1205         }
1206       while (offset < aop->coff)
1207         {
1208           aop->coff--;
1209           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1210         }
1211       aop->coff = offset;
1212
1213       if (aop->paged)
1214         {
1215           MOVA (s);
1216           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1217
1218         }
1219       else if (*s == '@')
1220         {
1221           MOVA (s);
1222           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1223         }
1224       else if (strcmp (s, "r0") == 0 ||
1225                strcmp (s, "r1") == 0 ||
1226                strcmp (s, "r2") == 0 ||
1227                strcmp (s, "r3") == 0 ||
1228                strcmp (s, "r4") == 0 ||
1229                strcmp (s, "r5") == 0 ||
1230                strcmp (s, "r6") == 0 ||
1231                strcmp (s, "r7") == 0)
1232         {
1233           char buffer[10];
1234           sprintf (buffer, "a%s", s);
1235           emitcode ("mov", "@%s,%s",
1236                     aop->aopu.aop_ptr->name, buffer);
1237         }
1238       else
1239         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1240
1241       break;
1242
1243     case AOP_STK:
1244       if (strcmp (s, "a") == 0)
1245         emitcode ("push", "acc");
1246       else
1247         if (*s=='@') {
1248           MOVA(s);
1249           emitcode ("push", "acc");
1250         } else {
1251           emitcode ("push", s);
1252         }
1253
1254       break;
1255
1256     case AOP_CRY:
1257       /* if bit variable */
1258       if (!aop->aopu.aop_dir)
1259         {
1260           emitcode ("clr", "a");
1261           emitcode ("rlc", "a");
1262         }
1263       else
1264         {
1265           if (s == zero)
1266             emitcode ("clr", "%s", aop->aopu.aop_dir);
1267           else if (s == one)
1268             emitcode ("setb", "%s", aop->aopu.aop_dir);
1269           else if (!strcmp (s, "c"))
1270             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1271           else
1272             {
1273               if (strcmp (s, "a"))
1274                 {
1275                   MOVA (s);
1276                 }
1277               {
1278                 symbol *lbl = newiTempLabel (NULL);
1279                 emitcode ("clr", "c");
1280                 emitcode ("jz", "%05d$", lbl->key + 100);
1281                 emitcode ("cpl", "c");
1282                 emitcode ("", "%05d$:", lbl->key + 100);
1283                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1284               }
1285             }
1286         }
1287       break;
1288
1289     case AOP_STR:
1290       aop->coff = offset;
1291       if (strcmp (aop->aopu.aop_str[offset], s))
1292         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1293       break;
1294
1295     case AOP_ACC:
1296       aop->coff = offset;
1297       if (!offset && (strcmp (s, "acc") == 0))
1298         break;
1299
1300       if (strcmp (aop->aopu.aop_str[offset], s))
1301         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1302       break;
1303
1304     default:
1305       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1306               "aopPut got unsupported aop->type");
1307       exit (1);
1308     }
1309
1310 }
1311
1312
1313 /*--------------------------------------------------------------------*/
1314 /* reAdjustPreg - points a register back to where it should (coff==0) */
1315 /*--------------------------------------------------------------------*/
1316 static void
1317 reAdjustPreg (asmop * aop)
1318 {
1319   if ((aop->coff==0) || (aop->size <= 1)) {
1320     return;
1321   }
1322
1323   switch (aop->type)
1324     {
1325     case AOP_R0:
1326     case AOP_R1:
1327       while (aop->coff--)
1328         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1329       break;
1330     case AOP_DPTR:
1331     case AOP_DPTR2:
1332       if (aop->type == AOP_DPTR2)
1333         {
1334           genSetDPTR (1);
1335           _flushLazyDPS ();
1336         }
1337       while (aop->coff--)
1338         {
1339           emitcode ("lcall", "__decdptr");
1340         }
1341
1342       if (aop->type == AOP_DPTR2)
1343         {
1344           genSetDPTR (0);
1345         }
1346       break;
1347
1348     }
1349   aop->coff=0;
1350 }
1351
1352 #define AOP(op) op->aop
1353 #define AOP_TYPE(op) AOP(op)->type
1354 #define AOP_SIZE(op) AOP(op)->size
1355 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1356                        AOP_TYPE(x) == AOP_R0))
1357
1358 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1359                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1360                          AOP(x)->paged))
1361
1362 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1363                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1364                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1365
1366 /* Workaround for DS80C390 bug: div ab may return bogus results
1367  * if A is accessed in instruction immediately before the div.
1368  *
1369  * Will be fixed in B4 rev of processor, Dallas claims.
1370  */
1371
1372 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1373     if (!AOP_NEEDSACC(RIGHT))         \
1374     {               \
1375       /* We can load A first, then B, since     \
1376        * B (the RIGHT operand) won't clobber A,   \
1377        * thus avoiding touching A right before the div. \
1378        */             \
1379       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1380       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);     \
1381       MOVA(L);            \
1382       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1383     }               \
1384     else              \
1385     {               \
1386       /* Just stuff in a nop after loading A. */    \
1387       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1388       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);   \
1389       MOVA(L);            \
1390       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1391     }
1392
1393 /*-----------------------------------------------------------------*/
1394 /* genNotFloat - generates not for float operations              */
1395 /*-----------------------------------------------------------------*/
1396 static void
1397 genNotFloat (operand * op, operand * res)
1398 {
1399   int size, offset;
1400   char *l;
1401   symbol *tlbl;
1402
1403   D (emitcode (";", "genNotFloat ");
1404     );
1405
1406   /* we will put 127 in the first byte of
1407      the result */
1408   aopPut (AOP (res), "#127", 0);
1409   size = AOP_SIZE (op) - 1;
1410   offset = 1;
1411
1412   _startLazyDPSEvaluation ();
1413   l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1414   MOVA (l);
1415
1416   while (size--)
1417     {
1418       emitcode ("orl", "a,%s",
1419                 aopGet (op->aop,
1420                         offset++, FALSE, FALSE, FALSE));
1421     }
1422   _endLazyDPSEvaluation ();
1423
1424   tlbl = newiTempLabel (NULL);
1425   aopPut (res->aop, one, 1);
1426   emitcode ("jz", "%05d$", (tlbl->key + 100));
1427   aopPut (res->aop, zero, 1);
1428   emitcode ("", "%05d$:", (tlbl->key + 100));
1429
1430   size = res->aop->size - 2;
1431   offset = 2;
1432   /* put zeros in the rest */
1433   while (size--)
1434     aopPut (res->aop, zero, offset++);
1435 }
1436
1437 /*-----------------------------------------------------------------*/
1438 /* opIsGptr: returns non-zero if the passed operand is       */
1439 /* a generic pointer type.             */
1440 /*-----------------------------------------------------------------*/
1441 static int
1442 opIsGptr (operand * op)
1443 {
1444   sym_link *type = operandType (op);
1445
1446   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1447     {
1448       return 1;
1449     }
1450   return 0;
1451 }
1452
1453 /*-----------------------------------------------------------------*/
1454 /* getDataSize - get the operand data size                         */
1455 /*-----------------------------------------------------------------*/
1456 static int
1457 getDataSize (operand * op)
1458 {
1459   int size;
1460   size = AOP_SIZE (op);
1461   if (size == GPTRSIZE)
1462     {
1463       sym_link *type = operandType (op);
1464       if (IS_GENPTR (type))
1465         {
1466           /* generic pointer; arithmetic operations
1467            * should ignore the high byte (pointer type).
1468            */
1469           size--;
1470         }
1471     }
1472   return size;
1473 }
1474
1475 /*-----------------------------------------------------------------*/
1476 /* outAcc - output Acc                                             */
1477 /*-----------------------------------------------------------------*/
1478 static void
1479 outAcc (operand * result)
1480 {
1481   int size, offset;
1482   size = getDataSize (result);
1483   if (size)
1484     {
1485       aopPut (AOP (result), "a", 0);
1486       size--;
1487       offset = 1;
1488       /* unsigned or positive */
1489       while (size--)
1490         {
1491           aopPut (AOP (result), zero, offset++);
1492         }
1493     }
1494 }
1495
1496 /*-----------------------------------------------------------------*/
1497 /* outBitC - output a bit C                                        */
1498 /*-----------------------------------------------------------------*/
1499 static void
1500 outBitC (operand * result)
1501 {
1502   /* if the result is bit */
1503   if (AOP_TYPE (result) == AOP_CRY)
1504     {
1505       aopPut (AOP (result), "c", 0);
1506     }
1507   else
1508     {
1509       emitcode ("clr", "a");
1510       emitcode ("rlc", "a");
1511       outAcc (result);
1512     }
1513 }
1514
1515 /*-----------------------------------------------------------------*/
1516 /* toBoolean - emit code for orl a,operator(sizeop)                */
1517 /*-----------------------------------------------------------------*/
1518 static void
1519 toBoolean (operand * oper)
1520 {
1521   int   size = AOP_SIZE (oper) - 1;
1522   int   offset = 1;
1523   bool usedB = FALSE;
1524
1525   /* The generic part of a generic pointer should
1526    * not participate in it's truth value.
1527    *
1528    * i.e. 0x10000000 is zero.
1529    */
1530   if (opIsGptr (oper))
1531     {
1532       D (emitcode (";", "toBoolean: generic ptr special case.");
1533         );
1534       size--;
1535     }
1536
1537   _startLazyDPSEvaluation ();
1538   if (AOP_NEEDSACC (oper) && size)
1539     {
1540       usedB = TRUE;
1541       emitcode ("push", "b");
1542       emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1543     }
1544   else
1545     {
1546       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1547     }
1548   while (size--)
1549     {
1550       if (usedB)
1551         {
1552           emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1553         }
1554       else
1555         {
1556           emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1557         }
1558     }
1559   _endLazyDPSEvaluation ();
1560
1561   if (usedB)
1562     {
1563       emitcode ("mov", "a,b");
1564       emitcode ("pop", "b");
1565     }
1566 }
1567
1568
1569 /*-----------------------------------------------------------------*/
1570 /* genNot - generate code for ! operation                          */
1571 /*-----------------------------------------------------------------*/
1572 static void
1573 genNot (iCode * ic)
1574 {
1575   symbol *tlbl;
1576   sym_link *optype = operandType (IC_LEFT (ic));
1577
1578   D (emitcode (";", "genNot ");
1579     );
1580
1581   /* assign asmOps to operand & result */
1582   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1583   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1584
1585   /* if in bit space then a special case */
1586   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1587     {
1588       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1589       emitcode ("cpl", "c");
1590       outBitC (IC_RESULT (ic));
1591       goto release;
1592     }
1593
1594   /* if type float then do float */
1595   if (IS_FLOAT (optype))
1596     {
1597       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1598       goto release;
1599     }
1600
1601   toBoolean (IC_LEFT (ic));
1602
1603   tlbl = newiTempLabel (NULL);
1604   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1605   emitcode ("", "%05d$:", tlbl->key + 100);
1606   outBitC (IC_RESULT (ic));
1607
1608 release:
1609   /* release the aops */
1610   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1611   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1612 }
1613
1614
1615 /*-----------------------------------------------------------------*/
1616 /* genCpl - generate code for complement                           */
1617 /*-----------------------------------------------------------------*/
1618 static void
1619 genCpl (iCode * ic)
1620 {
1621   int offset = 0;
1622   int size;
1623
1624   D (emitcode (";", "genCpl ");
1625     );
1626
1627
1628   /* assign asmOps to operand & result */
1629   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1630   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1631
1632   /* if both are in bit space then
1633      a special case */
1634   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1635       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1636     {
1637
1638       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1639       emitcode ("cpl", "c");
1640       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1641       goto release;
1642     }
1643
1644   size = AOP_SIZE (IC_RESULT (ic));
1645   _startLazyDPSEvaluation ();
1646   while (size--)
1647     {
1648       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1649       MOVA (l);
1650       emitcode ("cpl", "a");
1651       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1652     }
1653   _endLazyDPSEvaluation ();
1654
1655
1656 release:
1657   /* release the aops */
1658   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1659   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1660 }
1661
1662 /*-----------------------------------------------------------------*/
1663 /* genUminusFloat - unary minus for floating points                */
1664 /*-----------------------------------------------------------------*/
1665 static void
1666 genUminusFloat (operand * op, operand * result)
1667 {
1668   int size, offset = 0;
1669   char *l;
1670   /* for this we just need to flip the
1671      first it then copy the rest in place */
1672   D (emitcode (";", "genUminusFloat");
1673     );
1674
1675   _startLazyDPSEvaluation ();
1676   size = AOP_SIZE (op) - 1;
1677   l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1678   MOVA (l);
1679
1680   emitcode ("cpl", "acc.7");
1681   aopPut (AOP (result), "a", 3);
1682
1683   while (size--)
1684     {
1685       aopPut (AOP (result),
1686               aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1687               offset);
1688       offset++;
1689     }
1690   _endLazyDPSEvaluation ();
1691 }
1692
1693 /*-----------------------------------------------------------------*/
1694 /* genUminus - unary minus code generation                         */
1695 /*-----------------------------------------------------------------*/
1696 static void
1697 genUminus (iCode * ic)
1698 {
1699   int offset, size;
1700   sym_link *optype, *rtype;
1701
1702   D (emitcode (";", "genUminus ");
1703     );
1704
1705
1706   /* assign asmops */
1707   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1708   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1709
1710   /* if both in bit space then special
1711      case */
1712   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1713       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1714     {
1715
1716       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1717       emitcode ("cpl", "c");
1718       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1719       goto release;
1720     }
1721
1722   optype = operandType (IC_LEFT (ic));
1723   rtype = operandType (IC_RESULT (ic));
1724
1725   /* if float then do float stuff */
1726   if (IS_FLOAT (optype))
1727     {
1728       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1729       goto release;
1730     }
1731
1732   /* otherwise subtract from zero */
1733   size = AOP_SIZE (IC_LEFT (ic));
1734   offset = 0;
1735   _startLazyDPSEvaluation ();
1736   while (size--)
1737     {
1738       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1739       if (!strcmp (l, "a"))
1740         {
1741           if (offset == 0)
1742             SETC;
1743           emitcode ("cpl", "a");
1744           emitcode ("addc", "a,#0");
1745         }
1746       else
1747         {
1748           if (offset == 0)
1749             CLRC;
1750           emitcode ("clr", "a");
1751           emitcode ("subb", "a,%s", l);
1752         }
1753       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1754     }
1755   _endLazyDPSEvaluation ();
1756
1757   /* if any remaining bytes in the result */
1758   /* we just need to propagate the sign   */
1759   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1760     {
1761       emitcode ("rlc", "a");
1762       emitcode ("subb", "a,acc");
1763       while (size--)
1764         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1765     }
1766
1767 release:
1768   /* release the aops */
1769   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1770   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1771 }
1772
1773 /*-----------------------------------------------------------------*/
1774 /* saveRegisters - will look for a call and save the registers     */
1775 /*-----------------------------------------------------------------*/
1776 static void
1777 saveRegisters (iCode * lic)
1778 {
1779   int i;
1780   iCode *ic;
1781   bitVect *rsave;
1782   sym_link *detype;
1783
1784   /* look for call */
1785   for (ic = lic; ic; ic = ic->next)
1786     if (ic->op == CALL || ic->op == PCALL)
1787       break;
1788
1789   if (!ic)
1790     {
1791       fprintf (stderr, "found parameter push with no function call\n");
1792       return;
1793     }
1794
1795   /* if the registers have been saved already then
1796      do nothing */
1797   if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type) ||
1798       IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))))
1799     return;
1800
1801   /* find the registers in use at this time
1802      and push them away to safety */
1803   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1804                          ic->rUsed);
1805
1806   ic->regsSaved = 1;
1807   if (options.useXstack)
1808     {
1809       if (bitVectBitValue (rsave, R0_IDX))
1810         emitcode ("mov", "b,r0");
1811       emitcode ("mov", "r0,%s", spname);
1812       for (i = 0; i < ds390_nRegs; i++)
1813         {
1814           if (bitVectBitValue (rsave, i))
1815             {
1816               if (i == R0_IDX)
1817                 emitcode ("mov", "a,b");
1818               else
1819                 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1820               emitcode ("movx", "@r0,a");
1821               emitcode ("inc", "r0");
1822             }
1823         }
1824       emitcode ("mov", "%s,r0", spname);
1825       if (bitVectBitValue (rsave, R0_IDX))
1826         emitcode ("mov", "r0,b");
1827     }
1828   else
1829     for (i = 0; i < ds390_nRegs; i++)
1830       {
1831         if (bitVectBitValue (rsave, i))
1832           emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1833       }
1834
1835   detype = getSpec (operandType (IC_LEFT (ic)));
1836 }
1837
1838 /*-----------------------------------------------------------------*/
1839 /* unsaveRegisters - pop the pushed registers                      */
1840 /*-----------------------------------------------------------------*/
1841 static void
1842 unsaveRegisters (iCode * ic)
1843 {
1844   int i;
1845   bitVect *rsave;
1846   /* find the registers in use at this time
1847      and push them away to safety */
1848   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1849                          ic->rUsed);
1850
1851   if (options.useXstack)
1852     {
1853       emitcode ("mov", "r0,%s", spname);
1854       for (i = ds390_nRegs; i >= 0; i--)
1855         {
1856           if (bitVectBitValue (rsave, i))
1857             {
1858               emitcode ("dec", "r0");
1859               emitcode ("movx", "a,@r0");
1860               if (i == R0_IDX)
1861                 emitcode ("mov", "b,a");
1862               else
1863                 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1864             }
1865
1866         }
1867       emitcode ("mov", "%s,r0", spname);
1868       if (bitVectBitValue (rsave, R0_IDX))
1869         emitcode ("mov", "r0,b");
1870     }
1871   else
1872     for (i = ds390_nRegs; i >= 0; i--)
1873       {
1874         if (bitVectBitValue (rsave, i))
1875           emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1876       }
1877
1878 }
1879
1880
1881 /*-----------------------------------------------------------------*/
1882 /* pushSide -                */
1883 /*-----------------------------------------------------------------*/
1884 static void
1885 pushSide (operand * oper, int size)
1886 {
1887   int offset = 0;
1888   _startLazyDPSEvaluation ();
1889   while (size--)
1890     {
1891       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1892       if (AOP_TYPE (oper) != AOP_REG &&
1893           AOP_TYPE (oper) != AOP_DIR &&
1894           strcmp (l, "a"))
1895         {
1896           emitcode ("mov", "a,%s", l);
1897           emitcode ("push", "acc");
1898         }
1899       else
1900         emitcode ("push", "%s", l);
1901     }
1902   _endLazyDPSEvaluation ();
1903 }
1904
1905 /*-----------------------------------------------------------------*/
1906 /* assignResultValue -               */
1907 /*-----------------------------------------------------------------*/
1908 static void
1909 assignResultValue (operand * oper)
1910 {
1911   int offset = 0;
1912   int size = AOP_SIZE (oper);
1913
1914   _startLazyDPSEvaluation ();
1915   while (size--)
1916     {
1917       aopPut (AOP (oper), fReturn[offset], offset);
1918       offset++;
1919     }
1920   _endLazyDPSEvaluation ();
1921 }
1922
1923
1924 /*-----------------------------------------------------------------*/
1925 /* genXpush - pushes onto the external stack                       */
1926 /*-----------------------------------------------------------------*/
1927 static void
1928 genXpush (iCode * ic)
1929 {
1930   asmop *aop = newAsmop (0);
1931   regs *r;
1932   int size, offset = 0;
1933
1934   D (emitcode (";", "genXpush ");
1935     );
1936
1937   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1938   r = getFreePtr (ic, &aop, FALSE);
1939
1940
1941   emitcode ("mov", "%s,_spx", r->name);
1942
1943   size = AOP_SIZE (IC_LEFT (ic));
1944   _startLazyDPSEvaluation ();
1945   while (size--)
1946     {
1947
1948       char *l = aopGet (AOP (IC_LEFT (ic)),
1949                         offset++, FALSE, FALSE, TRUE);
1950       MOVA (l);
1951       emitcode ("movx", "@%s,a", r->name);
1952       emitcode ("inc", "%s", r->name);
1953
1954     }
1955   _endLazyDPSEvaluation ();
1956
1957
1958   emitcode ("mov", "_spx,%s", r->name);
1959
1960   freeAsmop (NULL, aop, ic, TRUE);
1961   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1962 }
1963
1964 /*-----------------------------------------------------------------*/
1965 /* genIpush - genrate code for pushing this gets a little complex  */
1966 /*-----------------------------------------------------------------*/
1967 static void
1968 genIpush (iCode * ic)
1969 {
1970   int size, offset = 0;
1971   char *l;
1972
1973   D (emitcode (";", "genIpush ");
1974     );
1975
1976   /* if this is not a parm push : ie. it is spill push
1977      and spill push is always done on the local stack */
1978   if (!ic->parmPush)
1979     {
1980
1981       /* and the item is spilt then do nothing */
1982       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1983         return;
1984
1985       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1986       size = AOP_SIZE (IC_LEFT (ic));
1987       /* push it on the stack */
1988       _startLazyDPSEvaluation ();
1989       while (size--)
1990         {
1991           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1992           if (*l == '#')
1993             {
1994               MOVA (l);
1995               l = "acc";
1996             }
1997           emitcode ("push", "%s", l);
1998         }
1999       _endLazyDPSEvaluation ();
2000       return;
2001     }
2002
2003   /* this is a paramter push: in this case we call
2004      the routine to find the call and save those
2005      registers that need to be saved */
2006   saveRegisters (ic);
2007
2008   /* if use external stack then call the external
2009      stack pushing routine */
2010   if (options.useXstack)
2011     {
2012       genXpush (ic);
2013       return;
2014     }
2015
2016   /* then do the push */
2017   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2018
2019   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2020   size = AOP_SIZE (IC_LEFT (ic));
2021
2022   _startLazyDPSEvaluation ();
2023   while (size--)
2024     {
2025       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2026       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2027           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2028           strcmp (l, "a"))
2029         {
2030           emitcode ("mov", "a,%s", l);
2031           emitcode ("push", "acc");
2032         }
2033       else
2034         emitcode ("push", "%s", l);
2035     }
2036   _endLazyDPSEvaluation ();
2037
2038   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2039 }
2040
2041 /*-----------------------------------------------------------------*/
2042 /* genIpop - recover the registers: can happen only for spilling   */
2043 /*-----------------------------------------------------------------*/
2044 static void
2045 genIpop (iCode * ic)
2046 {
2047   int size, offset;
2048
2049   D (emitcode (";", "genIpop ");
2050     );
2051
2052
2053   /* if the temp was not pushed then */
2054   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2055     return;
2056
2057   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2058   size = AOP_SIZE (IC_LEFT (ic));
2059   offset = (size - 1);
2060   _startLazyDPSEvaluation ();
2061   while (size--)
2062     {
2063       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2064                                      FALSE, TRUE, TRUE));
2065     }
2066   _endLazyDPSEvaluation ();
2067
2068   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2069 }
2070
2071 /*-----------------------------------------------------------------*/
2072 /* unsaveRBank - restores the resgister bank from stack            */
2073 /*-----------------------------------------------------------------*/
2074 static void
2075 unsaveRBank (int bank, iCode * ic, bool popPsw)
2076 {
2077   int i;
2078   asmop *aop = NULL;
2079   regs *r = NULL;
2080
2081   if (options.useXstack)
2082   {
2083       if (!ic)
2084       {
2085           /* Assume r0 is available for use. */
2086           r = ds390_regWithIdx (R0_IDX);;          
2087       } 
2088       else
2089       {
2090           aop = newAsmop (0);
2091           r = getFreePtr (ic, &aop, FALSE);
2092       }
2093       emitcode ("mov", "%s,_spx", r->name);      
2094   }
2095   
2096   if (popPsw)
2097     {
2098       if (options.useXstack)
2099       {
2100           emitcode ("movx", "a,@%s", r->name);
2101           emitcode ("mov", "psw,a");
2102           emitcode ("dec", "%s", r->name);
2103         }
2104       else
2105       {
2106         emitcode ("pop", "psw");
2107       }
2108     }
2109
2110   for (i = (ds390_nRegs - 1); i >= 0; i--)
2111     {
2112       if (options.useXstack)
2113         {
2114           emitcode ("movx", "a,@%s", r->name);
2115           emitcode ("mov", "(%s+%d),a",
2116                     regs390[i].base, 8 * bank + regs390[i].offset);
2117           emitcode ("dec", "%s", r->name);
2118
2119         }
2120       else
2121         emitcode ("pop", "(%s+%d)",
2122                   regs390[i].base, 8 * bank + regs390[i].offset);
2123     }
2124
2125   if (options.useXstack)
2126     {
2127       emitcode ("mov", "_spx,%s", r->name);
2128     }
2129     
2130   if (aop)
2131   {
2132       freeAsmop (NULL, aop, ic, TRUE);  
2133   }    
2134 }
2135
2136 /*-----------------------------------------------------------------*/
2137 /* saveRBank - saves an entire register bank on the stack          */
2138 /*-----------------------------------------------------------------*/
2139 static void
2140 saveRBank (int bank, iCode * ic, bool pushPsw)
2141 {
2142   int i;
2143   asmop *aop = NULL;
2144   regs *r = NULL;
2145
2146   if (options.useXstack)
2147     {
2148         if (!ic)
2149         {
2150           /* Assume r0 is available for use. */
2151                   r = ds390_regWithIdx (R0_IDX);;
2152         }
2153         else
2154         {
2155           aop = newAsmop (0);
2156           r = getFreePtr (ic, &aop, FALSE);
2157         }
2158         emitcode ("mov", "%s,_spx", r->name);    
2159     }
2160
2161   for (i = 0; i < ds390_nRegs; i++)
2162     {
2163       if (options.useXstack)
2164         {
2165           emitcode ("inc", "%s", r->name);
2166           emitcode ("mov", "a,(%s+%d)",
2167                     regs390[i].base, 8 * bank + regs390[i].offset);
2168           emitcode ("movx", "@%s,a", r->name);
2169         }
2170       else
2171         emitcode ("push", "(%s+%d)",
2172                   regs390[i].base, 8 * bank + regs390[i].offset);
2173     }
2174
2175   if (pushPsw)
2176     {
2177       if (options.useXstack)
2178         {
2179           emitcode ("mov", "a,psw");
2180           emitcode ("movx", "@%s,a", r->name);
2181           emitcode ("inc", "%s", r->name);
2182           emitcode ("mov", "_spx,%s", r->name);
2183         }
2184       else
2185       {
2186         emitcode ("push", "psw");
2187       }
2188
2189       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2190     }
2191   
2192   if (aop)
2193   {
2194        freeAsmop (NULL, aop, ic, TRUE);
2195   }    
2196     
2197   if (ic)
2198   {  
2199       ic->bankSaved = 1;
2200   }
2201 }
2202
2203 /*-----------------------------------------------------------------*/
2204 /* genCall - generates a call statement                            */
2205 /*-----------------------------------------------------------------*/
2206 static void
2207 genCall (iCode * ic)
2208 {
2209   sym_link *dtype;
2210   bool restoreBank = FALSE;
2211   bool swapBanks = FALSE;
2212
2213   D (emitcode (";", "genCall "););
2214
2215   /* if we are calling a not _naked function that is not using
2216      the same register bank then we need to save the
2217      destination registers on the stack */
2218   dtype = operandType (IC_LEFT (ic));
2219   if (dtype && !IFFUNC_ISNAKED(dtype) &&
2220       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2221       IFFUNC_ISISR (currFunc->type))
2222   {
2223       if (!ic->bankSaved) 
2224       {
2225            /* This is unexpected; the bank should have been saved in
2226             * genFunction.
2227             */
2228            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2229            restoreBank = TRUE;
2230       }
2231       swapBanks = TRUE;
2232   }
2233   
2234     /* if caller saves & we have not saved then */
2235     if (!ic->regsSaved)
2236       saveRegisters (ic);
2237   
2238   /* if send set is not empty the assign */
2239   /* We've saved all the registers we care about;
2240   * therefore, we may clobber any register not used
2241   * in the calling convention (i.e. anything not in
2242   * fReturn.
2243   */
2244   if (_G.sendSet)
2245     {
2246       iCode *sic;
2247
2248       for (sic = setFirstItem (_G.sendSet); sic;
2249            sic = setNextItem (_G.sendSet))
2250         {
2251           int size, offset = 0;
2252
2253           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2254           size = AOP_SIZE (IC_LEFT (sic));
2255
2256           _startLazyDPSEvaluation ();
2257           while (size--)
2258             {
2259               char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2260                                 FALSE, FALSE, TRUE);
2261                 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2262                 {
2263                     emitcode("mov", "%s,%s", regs390[offset].name, l);
2264                 }
2265                 else if (strcmp (l, fReturn[offset]))
2266                 {
2267                     emitcode ("mov", "%s,%s",
2268                               fReturn[offset],
2269                               l);
2270                 }
2271               offset++;
2272             }
2273           _endLazyDPSEvaluation ();
2274           if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2275           {
2276               size = AOP_SIZE (IC_LEFT (sic));
2277               if (size)
2278               {
2279                  size--;
2280               }
2281               while (size)
2282               {
2283                    size--;
2284                    emitcode("mov", "%s,%s",
2285                                     fReturn[size], regs390[size].name);
2286               }
2287           }
2288           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2289         }
2290       _G.sendSet = NULL;
2291     }  
2292     
2293   if (swapBanks)
2294   {
2295         emitcode ("mov", "psw,#0x%02x", 
2296            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2297   }
2298
2299   /* make the call */
2300   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2301                             OP_SYMBOL (IC_LEFT (ic))->rname :
2302                             OP_SYMBOL (IC_LEFT (ic))->name));
2303
2304   if (swapBanks)
2305   {
2306        emitcode ("mov", "psw,#0x%02x", 
2307           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2308   }
2309
2310   /* if we need assign a result value */
2311   if ((IS_ITEMP (IC_RESULT (ic)) &&
2312        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2313         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2314       IS_TRUE_SYMOP (IC_RESULT (ic)))
2315     {
2316       if (isOperandInFarSpace (IC_RESULT (ic))
2317           && getSize (operandType (IC_RESULT (ic))) <= 2)
2318         {
2319           int size = getSize (operandType (IC_RESULT (ic)));
2320
2321           /* Special case for 1 or 2 byte return in far space. */
2322           MOVA (fReturn[0]);
2323           if (size > 1)
2324             {
2325               emitcode ("mov", "b,%s", fReturn[1]);
2326             }
2327
2328           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2329           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2330
2331           if (size > 1)
2332             {
2333               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2334             }
2335           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2336         }
2337       else
2338         {
2339           _G.accInUse++;
2340           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2341           _G.accInUse--;
2342
2343           assignResultValue (IC_RESULT (ic));
2344
2345           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2346         }
2347     }
2348
2349   /* adjust the stack for parameters if
2350      required */
2351   if (ic->parmBytes)
2352     {
2353       int i;
2354       if (ic->parmBytes > 3)
2355         {
2356           emitcode ("mov", "a,%s", spname);
2357           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2358           emitcode ("mov", "%s,a", spname);
2359         }
2360       else
2361         for (i = 0; i < ic->parmBytes; i++)
2362           emitcode ("dec", "%s", spname);
2363     }
2364
2365   /* if we hade saved some registers then unsave them */
2366   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2367     unsaveRegisters (ic);
2368
2369   /* if register bank was saved then pop them */
2370   if (restoreBank)
2371     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2372 }
2373
2374 /*-----------------------------------------------------------------*/
2375 /* genPcall - generates a call by pointer statement                */
2376 /*-----------------------------------------------------------------*/
2377 static void
2378 genPcall (iCode * ic)
2379 {
2380   sym_link *dtype;
2381   symbol *rlbl = newiTempLabel (NULL);
2382   bool restoreBank=FALSE;
2383
2384   D (emitcode (";", "genPcall ");
2385     );
2386
2387
2388   /* if caller saves & we have not saved then */
2389   if (!ic->regsSaved)
2390     saveRegisters (ic);
2391
2392   /* if we are calling a function that is not using
2393      the same register bank then we need to save the
2394      destination registers on the stack */
2395   dtype = operandType (IC_LEFT (ic));
2396   if (dtype && !IFFUNC_ISNAKED(dtype) &&
2397       IFFUNC_ISISR (currFunc->type) &&
2398       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2399     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2400     restoreBank=TRUE;
2401   }
2402
2403   /* push the return address on to the stack */
2404   emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2405   emitcode ("push", "acc");
2406   emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2407   emitcode ("push", "acc");
2408
2409   if (options.model == MODEL_FLAT24)
2410     {
2411       emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2412       emitcode ("push", "acc");
2413     }
2414
2415   /* now push the calling address */
2416   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2417
2418   pushSide (IC_LEFT (ic), FPTRSIZE);
2419
2420   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2421
2422   /* if send set is not empty the assign */
2423   if (_G.sendSet)
2424     {
2425       iCode *sic;
2426
2427       for (sic = setFirstItem (_G.sendSet); sic;
2428            sic = setNextItem (_G.sendSet))
2429         {
2430           int size, offset = 0;
2431
2432           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2433           size = AOP_SIZE (IC_LEFT (sic));
2434           _startLazyDPSEvaluation ();
2435           while (size--)
2436             {
2437               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2438                                 FALSE, FALSE, TRUE);
2439               if (strcmp (l, fReturn[offset]))
2440                 {
2441                   emitcode ("mov", "%s,%s",
2442                             fReturn[offset],
2443                             l);
2444                 }
2445               offset++;
2446             }
2447           _endLazyDPSEvaluation ();
2448           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2449         }
2450       _G.sendSet = NULL;
2451     }
2452
2453   emitcode ("ret", "");
2454   emitcode ("", "%05d$:", (rlbl->key + 100));
2455
2456
2457   /* if we need assign a result value */
2458   if ((IS_ITEMP (IC_RESULT (ic)) &&
2459        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2460         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2461       IS_TRUE_SYMOP (IC_RESULT (ic)))
2462     {
2463
2464       _G.accInUse++;
2465       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2466       _G.accInUse--;
2467
2468       assignResultValue (IC_RESULT (ic));
2469
2470       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2471     }
2472
2473   /* adjust the stack for parameters if
2474      required */
2475   if (ic->parmBytes)
2476     {
2477       int i;
2478       if (ic->parmBytes > 3)
2479         {
2480           emitcode ("mov", "a,%s", spname);
2481           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2482           emitcode ("mov", "%s,a", spname);
2483         }
2484       else
2485         for (i = 0; i < ic->parmBytes; i++)
2486           emitcode ("dec", "%s", spname);
2487
2488     }
2489
2490   /* if register bank was saved then unsave them */
2491   if (restoreBank)
2492     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2493   
2494   /* if we hade saved some registers then
2495      unsave them */
2496   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2497     unsaveRegisters (ic);
2498
2499 }
2500
2501 /*-----------------------------------------------------------------*/
2502 /* resultRemat - result  is rematerializable                       */
2503 /*-----------------------------------------------------------------*/
2504 static int
2505 resultRemat (iCode * ic)
2506 {
2507   if (SKIP_IC (ic) || ic->op == IFX)
2508     return 0;
2509
2510   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2511     {
2512       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2513       if (sym->remat && !POINTER_SET (ic))
2514         return 1;
2515     }
2516
2517   return 0;
2518 }
2519
2520 #if defined(__BORLANDC__) || defined(_MSC_VER)
2521 #define STRCASECMP stricmp
2522 #else
2523 #define STRCASECMP strcasecmp
2524 #endif
2525
2526 /*-----------------------------------------------------------------*/
2527 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2528 /*-----------------------------------------------------------------*/
2529 static bool
2530 inExcludeList (char *s)
2531 {
2532   int i = 0;
2533
2534   if (options.excludeRegs[i] &&
2535       STRCASECMP (options.excludeRegs[i], "none") == 0)
2536     return FALSE;
2537
2538   for (i = 0; options.excludeRegs[i]; i++)
2539     {
2540       if (options.excludeRegs[i] &&
2541           STRCASECMP (s, options.excludeRegs[i]) == 0)
2542         return TRUE;
2543     }
2544   return FALSE;
2545 }
2546
2547 /*-----------------------------------------------------------------*/
2548 /* genFunction - generated code for function entry                 */
2549 /*-----------------------------------------------------------------*/
2550 static void
2551 genFunction (iCode * ic)
2552 {
2553   symbol *sym;
2554   sym_link *ftype;
2555   bool   switchedPSW = FALSE;
2556
2557   D (emitcode (";", "genFunction "););
2558
2559   _G.nRegsSaved = 0;
2560   /* create the function header */
2561   emitcode (";", "-----------------------------------------");
2562   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2563   emitcode (";", "-----------------------------------------");
2564
2565   emitcode ("", "%s:", sym->rname);
2566   ftype = operandType (IC_LEFT (ic));
2567
2568   if (IFFUNC_ISNAKED(ftype))
2569   {
2570       emitcode(";", "naked function: no prologue.");
2571       return;
2572   }
2573
2574   /* if critical function then turn interrupts off */
2575   if (IFFUNC_ISCRITICAL (ftype))
2576     emitcode ("clr", "ea");
2577
2578   /* here we need to generate the equates for the
2579      register bank if required */
2580   if (FUNC_REGBANK (ftype) != rbank)
2581     {
2582       int i;
2583
2584       rbank = FUNC_REGBANK (ftype);
2585       for (i = 0; i < ds390_nRegs; i++)
2586         {
2587           if (strcmp (regs390[i].base, "0") == 0)
2588             emitcode ("", "%s = 0x%02x",
2589                       regs390[i].dname,
2590                       8 * rbank + regs390[i].offset);
2591           else
2592             emitcode ("", "%s = %s + 0x%02x",
2593                       regs390[i].dname,
2594                       regs390[i].base,
2595                       8 * rbank + regs390[i].offset);
2596         }
2597     }
2598
2599   /* if this is an interrupt service routine then
2600      save acc, b, dpl, dph  */
2601   if (IFFUNC_ISISR (sym->type))
2602     {
2603
2604       if (!inExcludeList ("acc"))
2605         emitcode ("push", "acc");
2606       if (!inExcludeList ("b"))
2607         emitcode ("push", "b");
2608       if (!inExcludeList ("dpl"))
2609         emitcode ("push", "dpl");
2610       if (!inExcludeList ("dph"))
2611         emitcode ("push", "dph");
2612       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2613         {
2614           emitcode ("push", "dpx");
2615           /* Make sure we're using standard DPTR */
2616           emitcode ("push", "dps");
2617           emitcode ("mov", "dps, #0x00");
2618           if (options.stack10bit)
2619             {
2620               /* This ISR could conceivably use DPTR2. Better save it. */
2621               emitcode ("push", "dpl1");
2622               emitcode ("push", "dph1");
2623               emitcode ("push", "dpx1");
2624               emitcode ("push",  DP2_RESULT_REG);
2625             }
2626         }
2627       /* if this isr has no bank i.e. is going to
2628          run with bank 0 , then we need to save more
2629          registers :-) */
2630       if (!FUNC_REGBANK (sym->type))
2631         {
2632
2633           /* if this function does not call any other
2634              function then we can be economical and
2635              save only those registers that are used */
2636           if (!IFFUNC_HASFCALL(sym->type))
2637             {
2638               int i;
2639
2640               /* if any registers used */
2641               if (sym->regsUsed)
2642                 {
2643                   /* save the registers used */
2644                   for (i = 0; i < sym->regsUsed->size; i++)
2645                     {
2646                       if (bitVectBitValue (sym->regsUsed, i) ||
2647                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2648                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2649                     }
2650                 }
2651
2652             }
2653           else
2654             {
2655               /* this function has  a function call cannot
2656                  determines register usage so we will have to push the
2657                  entire bank */
2658               saveRBank (0, ic, FALSE);
2659             }
2660         }
2661         else
2662         {
2663             /* This ISR uses a non-zero bank.
2664              *
2665              * We assume that the bank is available for our
2666              * exclusive use.
2667              *
2668              * However, if this ISR calls a function which uses some
2669              * other bank, we must save that bank entirely.
2670              */
2671             unsigned long banksToSave = 0;
2672             
2673             if (IFFUNC_HASFCALL(sym->type))
2674             {
2675
2676 #define MAX_REGISTER_BANKS 4
2677
2678                 iCode *i;
2679                 int ix;
2680
2681                 for (i = ic; i; i = i->next)
2682                 {
2683                     if (i->op == ENDFUNCTION)
2684                     {
2685                         /* we got to the end OK. */
2686                         break;
2687                     }
2688                     
2689                     if (i->op == CALL)
2690                     {
2691                         sym_link *dtype;
2692                         
2693                         dtype = operandType (IC_LEFT(i));
2694                         if (dtype 
2695                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2696                         {
2697                              /* Mark this bank for saving. */
2698                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2699                              {
2700                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2701                              }
2702                              else
2703                              {
2704                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2705                              }
2706                              
2707                              /* And note that we don't need to do it in 
2708                               * genCall.
2709                               */
2710                              i->bankSaved = 1;
2711                         }
2712                     }
2713                     if (i->op == PCALL)
2714                     {
2715                         /* This is a mess; we have no idea what
2716                          * register bank the called function might
2717                          * use.
2718                          *
2719                          * The only thing I can think of to do is
2720                          * throw a warning and hope.
2721                          */
2722                         werror(W_FUNCPTR_IN_USING_ISR);   
2723                     }
2724                 }
2725
2726                 if (banksToSave && options.useXstack)
2727                 {
2728                     /* Since we aren't passing it an ic, 
2729                      * saveRBank will assume r0 is available to abuse.
2730                      *
2731                      * So switch to our (trashable) bank now, so
2732                      * the caller's R0 isn't trashed.
2733                      */
2734                     emitcode ("push", "psw");
2735                     emitcode ("mov", "psw,#0x%02x", 
2736                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2737                     switchedPSW = TRUE;
2738                 }
2739                 
2740                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2741                 {
2742                      if (banksToSave & (1 << ix))
2743                      {
2744                          saveRBank(ix, NULL, FALSE);
2745                      }
2746                 }
2747             }
2748             // jwk: this needs a closer look
2749             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2750         }
2751     }
2752   else
2753     {
2754       /* if callee-save to be used for this function
2755          then save the registers being used in this function */
2756       if (IFFUNC_CALLEESAVES(sym->type))
2757         {
2758           int i;
2759
2760           /* if any registers used */
2761           if (sym->regsUsed)
2762             {
2763               /* save the registers used */
2764               for (i = 0; i < sym->regsUsed->size; i++)
2765                 {
2766                   if (bitVectBitValue (sym->regsUsed, i) ||
2767                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2768                     {
2769                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2770                       _G.nRegsSaved++;
2771                     }
2772                 }
2773             }
2774         }
2775     }
2776
2777   /* set the register bank to the desired value */
2778   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2779    && !switchedPSW)
2780     {
2781       emitcode ("push", "psw");
2782       emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2783     }
2784
2785   if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2786     {
2787
2788       if (options.useXstack)
2789         {
2790           emitcode ("mov", "r0,%s", spname);
2791           emitcode ("mov", "a,_bp");
2792           emitcode ("movx", "@r0,a");
2793           emitcode ("inc", "%s", spname);
2794         }
2795       else
2796         {
2797           /* set up the stack */
2798           emitcode ("push", "_bp");     /* save the callers stack  */
2799         }
2800       emitcode ("mov", "_bp,%s", spname);
2801     }
2802
2803   /* adjust the stack for the function */
2804   if (sym->stack)
2805     {
2806
2807       int i = sym->stack;
2808       if (i > 256)
2809         werror (W_STACK_OVERFLOW, sym->name);
2810
2811       if (i > 3 && sym->recvSize < 4)
2812         {
2813
2814           emitcode ("mov", "a,sp");
2815           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2816           emitcode ("mov", "sp,a");
2817
2818         }
2819       else
2820         while (i--)
2821           emitcode ("inc", "sp");
2822     }
2823
2824   if (sym->xstack)
2825     {
2826
2827       emitcode ("mov", "a,_spx");
2828       emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2829       emitcode ("mov", "_spx,a");
2830     }
2831
2832 }
2833
2834 /*-----------------------------------------------------------------*/
2835 /* genEndFunction - generates epilogue for functions               */
2836 /*-----------------------------------------------------------------*/
2837 static void
2838 genEndFunction (iCode * ic)
2839 {
2840   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2841
2842   D (emitcode (";", "genEndFunction "););
2843
2844   if (IFFUNC_ISNAKED(sym->type))
2845   {
2846       emitcode(";", "naked function: no epilogue.");
2847       return;
2848   }
2849
2850   if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2851     {
2852       emitcode ("mov", "%s,_bp", spname);
2853     }
2854
2855   /* if use external stack but some variables were
2856      added to the local stack then decrement the
2857      local stack */
2858   if (options.useXstack && sym->stack)
2859     {
2860       emitcode ("mov", "a,sp");
2861       emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2862       emitcode ("mov", "sp,a");
2863     }
2864
2865
2866   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2867     {
2868       if (options.useXstack)
2869         {
2870           emitcode ("mov", "r0,%s", spname);
2871           emitcode ("movx", "a,@r0");
2872           emitcode ("mov", "_bp,a");
2873           emitcode ("dec", "%s", spname);
2874         }
2875       else
2876         {
2877           emitcode ("pop", "_bp");
2878         }
2879     }
2880
2881   /* restore the register bank  */
2882   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2883   {
2884     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2885      || !options.useXstack)
2886     {
2887         /* Special case of ISR using non-zero bank with useXstack
2888          * is handled below.
2889          */
2890         emitcode ("pop", "psw");
2891     }
2892   }
2893
2894   if (IFFUNC_ISISR (sym->type))
2895     {
2896
2897       /* now we need to restore the registers */
2898       /* if this isr has no bank i.e. is going to
2899          run with bank 0 , then we need to save more
2900          registers :-) */
2901       if (!FUNC_REGBANK (sym->type))
2902         {
2903           /* if this function does not call any other
2904              function then we can be economical and
2905              save only those registers that are used */
2906           if (!IFFUNC_HASFCALL(sym->type))
2907             {
2908               int i;
2909
2910               /* if any registers used */
2911               if (sym->regsUsed)
2912                 {
2913                   /* save the registers used */
2914                   for (i = sym->regsUsed->size; i >= 0; i--)
2915                     {
2916                       if (bitVectBitValue (sym->regsUsed, i) ||
2917                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2918                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2919                     }
2920                 }
2921
2922             }
2923           else
2924             {
2925               /* this function has  a function call cannot
2926                  determines register usage so we will have to pop the
2927                  entire bank */
2928               unsaveRBank (0, ic, FALSE);
2929             }
2930         }
2931         else
2932         {
2933             /* This ISR uses a non-zero bank.
2934              *
2935              * Restore any register banks saved by genFunction
2936              * in reverse order.
2937              */
2938           // jwk: this needs a closer look
2939             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2940             int ix;
2941           
2942             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2943             {
2944                 if (savedBanks & (1 << ix))
2945                 {
2946                     unsaveRBank(ix, NULL, FALSE);
2947                 }
2948             }
2949             
2950             if (options.useXstack)
2951             {
2952                 /* Restore bank AFTER calling unsaveRBank,
2953                  * since it can trash r0.
2954                  */
2955                 emitcode ("pop", "psw");
2956             }
2957         }
2958
2959       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2960         {
2961           if (options.stack10bit)
2962             {
2963               emitcode ("pop", DP2_RESULT_REG);
2964               emitcode ("pop", "dpx1");
2965               emitcode ("pop", "dph1");
2966               emitcode ("pop", "dpl1");
2967             }
2968           emitcode ("pop", "dps");
2969           emitcode ("pop", "dpx");
2970         }
2971       if (!inExcludeList ("dph"))
2972         emitcode ("pop", "dph");
2973       if (!inExcludeList ("dpl"))
2974         emitcode ("pop", "dpl");
2975       if (!inExcludeList ("b"))
2976         emitcode ("pop", "b");
2977       if (!inExcludeList ("acc"))
2978         emitcode ("pop", "acc");
2979
2980       if (IFFUNC_ISCRITICAL (sym->type))
2981         emitcode ("setb", "ea");
2982
2983       /* if debug then send end of function */
2984       if (options.debug && currFunc) {
2985           _G.debugLine = 1;
2986           emitcode ("", "C$%s$%d$%d$%d ==.",
2987                     FileBaseName (ic->filename), currFunc->lastLine,
2988                     ic->level, ic->block);
2989           if (IS_STATIC (currFunc->etype))
2990             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2991           else
2992             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2993           _G.debugLine = 0;
2994         }
2995
2996       emitcode ("reti", "");
2997     }
2998   else
2999     {
3000       if (IFFUNC_ISCRITICAL (sym->type))
3001         emitcode ("setb", "ea");
3002
3003       if (IFFUNC_CALLEESAVES(sym->type))
3004         {
3005           int i;
3006
3007           /* if any registers used */
3008           if (sym->regsUsed)
3009             {
3010               /* save the registers used */
3011               for (i = sym->regsUsed->size; i >= 0; i--)
3012                 {
3013                   if (bitVectBitValue (sym->regsUsed, i) ||
3014                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3015                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3016                 }
3017             }
3018
3019         }
3020
3021       /* if debug then send end of function */
3022       if (options.debug && currFunc)
3023         {
3024           _G.debugLine = 1;
3025           emitcode ("", "C$%s$%d$%d$%d ==.",
3026                     FileBaseName (ic->filename), currFunc->lastLine,
3027                     ic->level, ic->block);
3028           if (IS_STATIC (currFunc->etype))
3029             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3030           else
3031             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3032           _G.debugLine = 0;
3033         }
3034
3035       emitcode ("ret", "");
3036     }
3037
3038 }
3039
3040 /*-----------------------------------------------------------------*/
3041 /* genRet - generate code for return statement                     */
3042 /*-----------------------------------------------------------------*/
3043 static void
3044 genRet (iCode * ic)
3045 {
3046   int size, offset = 0, pushed = 0;
3047
3048   D (emitcode (";", "genRet ");
3049     );
3050
3051   /* if we have no return value then
3052      just generate the "ret" */
3053   if (!IC_LEFT (ic))
3054     goto jumpret;
3055
3056   /* we have something to return then
3057      move the return value into place */
3058   aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3059   size = AOP_SIZE (IC_LEFT (ic));
3060
3061   _startLazyDPSEvaluation ();
3062   while (size--)
3063     {
3064       char *l;
3065       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3066         {
3067           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3068                       FALSE, TRUE, FALSE);
3069           emitcode ("push", "%s", l);
3070           pushed++;
3071         }
3072       else
3073         {
3074           /* Since A is the last element of fReturn,
3075            * is is OK to clobber it in the aopGet.
3076            */
3077           l = aopGet (AOP (IC_LEFT (ic)), offset,
3078                       FALSE, FALSE, TRUE);
3079           if (strcmp (fReturn[offset], l))
3080             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3081         }
3082     }
3083   _endLazyDPSEvaluation ();
3084
3085   if (pushed)
3086     {
3087       while (pushed)
3088         {
3089           pushed--;
3090           if (strcmp (fReturn[pushed], "a"))
3091             emitcode ("pop", fReturn[pushed]);
3092           else
3093             emitcode ("pop", "acc");
3094         }
3095     }
3096   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3097
3098 jumpret:
3099   /* generate a jump to the return label
3100      if the next is not the return statement */
3101   if (!(ic->next && ic->next->op == LABEL &&
3102         IC_LABEL (ic->next) == returnLabel))
3103
3104     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3105
3106 }
3107
3108 /*-----------------------------------------------------------------*/
3109 /* genLabel - generates a label                                    */
3110 /*-----------------------------------------------------------------*/
3111 static void
3112 genLabel (iCode * ic)
3113 {
3114   /* special case never generate */
3115   if (IC_LABEL (ic) == entryLabel)
3116     return;
3117
3118   D (emitcode (";", "genLabel ");
3119     );
3120
3121   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3122 }
3123
3124 /*-----------------------------------------------------------------*/
3125 /* genGoto - generates a ljmp                                      */
3126 /*-----------------------------------------------------------------*/
3127 static void
3128 genGoto (iCode * ic)
3129 {
3130   D (emitcode (";", "genGoto ");
3131     );
3132   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3133 }
3134
3135 /*-----------------------------------------------------------------*/
3136 /* findLabelBackwards: walks back through the iCode chain looking  */
3137 /* for the given label. Returns number of iCode instructions     */
3138 /* between that label and given ic.          */
3139 /* Returns zero if label not found.          */
3140 /*-----------------------------------------------------------------*/
3141 static int
3142 findLabelBackwards (iCode * ic, int key)
3143 {
3144   int count = 0;
3145
3146   while (ic->prev)
3147     {
3148       ic = ic->prev;
3149       count++;
3150
3151       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3152         {
3153           /* printf("findLabelBackwards = %d\n", count); */
3154           return count;
3155         }
3156     }
3157
3158   return 0;
3159 }
3160
3161 /*-----------------------------------------------------------------*/
3162 /* genPlusIncr :- does addition with increment if possible         */
3163 /*-----------------------------------------------------------------*/
3164 static bool
3165 genPlusIncr (iCode * ic)
3166 {
3167   unsigned int icount;
3168   unsigned int size = getDataSize (IC_RESULT (ic));
3169
3170   /* will try to generate an increment */
3171   /* if the right side is not a literal
3172      we cannot */
3173   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3174     return FALSE;
3175
3176   /* if the literal value of the right hand side
3177      is greater than 4 then it is not worth it */
3178   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3179     return FALSE;
3180
3181   /* if increment 16 bits in register */
3182   if (
3183        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3184        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3185        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3186        (size > 1) &&
3187        (icount == 1))
3188     {
3189       symbol *tlbl;
3190       int emitTlbl;
3191       int labelRange;
3192
3193       /* If the next instruction is a goto and the goto target
3194        * is <= 5 instructions previous to this, we can generate
3195        * jumps straight to that target.
3196        */
3197       if (ic->next && ic->next->op == GOTO
3198           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3199           && labelRange <= 5)
3200         {
3201           emitcode (";", "tail increment optimized (range %d)", labelRange);
3202           tlbl = IC_LABEL (ic->next);
3203           emitTlbl = 0;
3204         }
3205       else
3206         {
3207           tlbl = newiTempLabel (NULL);
3208           emitTlbl = 1;
3209         }
3210       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3211       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3212           IS_AOP_PREG (IC_RESULT (ic)))
3213         emitcode ("cjne", "%s,#0x00,%05d$"
3214                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3215                   ,tlbl->key + 100);
3216       else
3217         {
3218           emitcode ("clr", "a");
3219           emitcode ("cjne", "a,%s,%05d$"
3220                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3221                     ,tlbl->key + 100);
3222         }
3223
3224       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3225       if (size > 2)
3226         {
3227           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3228               IS_AOP_PREG (IC_RESULT (ic)))
3229             emitcode ("cjne", "%s,#0x00,%05d$"
3230                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3231                       ,tlbl->key + 100);
3232           else
3233             emitcode ("cjne", "a,%s,%05d$"
3234                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3235                       ,tlbl->key + 100);
3236
3237           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3238         }
3239       if (size > 3)
3240         {
3241           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3242               IS_AOP_PREG (IC_RESULT (ic)))
3243             emitcode ("cjne", "%s,#0x00,%05d$"
3244                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3245                       ,tlbl->key + 100);
3246           else
3247             {
3248               emitcode ("cjne", "a,%s,%05d$"
3249                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3250                         ,tlbl->key + 100);
3251             }
3252           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3253         }
3254
3255       if (emitTlbl)
3256         {
3257           emitcode ("", "%05d$:", tlbl->key + 100);
3258         }
3259       return TRUE;
3260     }
3261
3262   /* if the sizes are greater than 1 then we cannot */
3263   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3264       AOP_SIZE (IC_LEFT (ic)) > 1)
3265     return FALSE;
3266
3267   /* we can if the aops of the left & result match or
3268      if they are in registers and the registers are the
3269      same */
3270   if (
3271        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3272        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3273        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3274     {
3275
3276       if (icount > 3)
3277         {
3278           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3279           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3280           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3281         }
3282       else
3283         {
3284
3285           _startLazyDPSEvaluation ();
3286           while (icount--)
3287             {
3288               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3289             }
3290           _endLazyDPSEvaluation ();
3291         }
3292
3293       return TRUE;
3294     }
3295
3296   return FALSE;
3297 }
3298
3299 /*-----------------------------------------------------------------*/
3300 /* outBitAcc - output a bit in acc                                 */
3301 /*-----------------------------------------------------------------*/
3302 static void
3303 outBitAcc (operand * result)
3304 {
3305   symbol *tlbl = newiTempLabel (NULL);
3306   /* if the result is a bit */
3307   if (AOP_TYPE (result) == AOP_CRY)
3308     {
3309       aopPut (AOP (result), "a", 0);
3310     }
3311   else
3312     {
3313       emitcode ("jz", "%05d$", tlbl->key + 100);
3314       emitcode ("mov", "a,%s", one);
3315       emitcode ("", "%05d$:", tlbl->key + 100);
3316       outAcc (result);
3317     }
3318 }
3319
3320 /*-----------------------------------------------------------------*/
3321 /* genPlusBits - generates code for addition of two bits           */
3322 /*-----------------------------------------------------------------*/
3323 static void
3324 genPlusBits (iCode * ic)
3325 {
3326   D (emitcode (";", "genPlusBits ");
3327     );
3328   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3329     {
3330       symbol *lbl = newiTempLabel (NULL);
3331       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3332       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3333       emitcode ("cpl", "c");
3334       emitcode ("", "%05d$:", (lbl->key + 100));
3335       outBitC (IC_RESULT (ic));
3336     }
3337   else
3338     {
3339       emitcode ("clr", "a");
3340       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3341       emitcode ("rlc", "a");
3342       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3343       emitcode ("addc", "a,#0x00");
3344       outAcc (IC_RESULT (ic));
3345     }
3346 }
3347
3348 static void
3349 adjustArithmeticResult (iCode * ic)
3350 {
3351   if (opIsGptr (IC_RESULT (ic)) &&
3352       opIsGptr (IC_LEFT (ic)) &&
3353       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3354     {
3355       aopPut (AOP (IC_RESULT (ic)),
3356               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3357               GPTRSIZE - 1);
3358     }
3359
3360   if (opIsGptr (IC_RESULT (ic)) &&
3361       opIsGptr (IC_RIGHT (ic)) &&
3362       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3363     {
3364       aopPut (AOP (IC_RESULT (ic)),
3365             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3366               GPTRSIZE - 1);
3367     }
3368
3369   if (opIsGptr (IC_RESULT (ic)) &&
3370       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3371       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3372       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3373       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3374     {
3375       char buffer[5];
3376       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3377       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3378     }
3379 }
3380
3381 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3382       // Please don't bring it back without a really good reason.
3383 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3384 // (because all three operands are in far space).
3385 #define AOP_OP_3(ic) \
3386     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3387     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3388     aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3389               (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3390     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3391         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3392     { \
3393         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3394         fprintf(stderr,                                  \
3395                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3396     }
3397 #endif
3398
3399 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3400 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3401 // will be set TRUE. The caller must then handle the case specially, noting
3402 // that the IC_RESULT operand is not aopOp'd.
3403 #define AOP_OP_3_NOFATAL(ic, rc) \
3404     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3405     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3406     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3407         isOperandInFarSpace(IC_RESULT(ic))) \
3408     { \
3409        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3410        rc = TRUE; \
3411     }  \
3412     else \
3413     { \
3414        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3415                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3416        rc = FALSE; \
3417        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3418            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3419        { \
3420             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3421             fprintf(stderr,                                  \
3422                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3423        } \
3424     }
3425
3426 // aopOp the left & right operands of an ic.
3427 #define AOP_OP_2(ic) \
3428     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3429     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3430
3431 // convienience macro.
3432 #define AOP_SET_LOCALS(ic) \
3433     left = IC_LEFT(ic); \
3434     right = IC_RIGHT(ic); \
3435     result = IC_RESULT(ic);
3436
3437
3438 // Given an integer value of pushedSize bytes on the stack,
3439 // adjust it to be resultSize bytes, either by discarding
3440 // the most significant bytes or by zero-padding.
3441 //
3442 // On exit from this macro, pushedSize will have been adjusted to
3443 // equal resultSize, and ACC may be trashed.
3444 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3445       /* If the pushed data is bigger than the result,          \
3446        * simply discard unused bytes. Icky, but works.          \
3447        */                                                       \
3448       while (pushedSize > resultSize)                           \
3449       {                                                         \
3450           D (emitcode (";", "discarding unused result byte."););\
3451           emitcode ("pop", "acc");                              \
3452           pushedSize--;                                         \
3453       }                                                         \
3454       if (pushedSize < resultSize)                              \
3455       {                                                         \
3456           emitcode ("clr", "a");                                \
3457           /* Conversly, we haven't pushed enough here.          \
3458            * just zero-pad, and all is well.                    \
3459            */                                                   \
3460           while (pushedSize < resultSize)                       \
3461           {                                                     \
3462               emitcode("push", "acc");                          \
3463               pushedSize++;                                     \
3464           }                                                     \
3465       }                                                         \
3466       assert(pushedSize == resultSize);
3467
3468 /*-----------------------------------------------------------------*/
3469 /* genPlus - generates code for addition                           */
3470 /*-----------------------------------------------------------------*/
3471 static void
3472 genPlus (iCode * ic)
3473 {
3474   int size, offset = 0;
3475   bool pushResult = FALSE;
3476   int rSize;
3477
3478   D (emitcode (";", "genPlus "););
3479
3480   /* special cases :- */
3481
3482   AOP_OP_3_NOFATAL (ic, pushResult);
3483   if (pushResult)
3484     {
3485       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3486     }
3487
3488   if (!pushResult)
3489     {
3490       /* if literal, literal on the right or
3491          if left requires ACC or right is already
3492          in ACC */
3493       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3494        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3495           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3496         {
3497           operand *t = IC_RIGHT (ic);
3498           IC_RIGHT (ic) = IC_LEFT (ic);
3499           IC_LEFT (ic) = t;
3500           emitcode (";", "Swapped plus args.");
3501         }
3502
3503       /* if both left & right are in bit
3504          space */
3505       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3506           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3507         {
3508           genPlusBits (ic);
3509           goto release;
3510         }
3511
3512       /* if left in bit space & right literal */
3513       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3514           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3515         {
3516           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3517           /* if result in bit space */
3518           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3519             {
3520               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3521                 emitcode ("cpl", "c");
3522               outBitC (IC_RESULT (ic));
3523             }
3524           else
3525             {
3526               size = getDataSize (IC_RESULT (ic));
3527               _startLazyDPSEvaluation ();
3528               while (size--)
3529                 {
3530                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3531                   emitcode ("addc", "a,#00");
3532                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3533                 }
3534               _endLazyDPSEvaluation ();
3535             }
3536           goto release;
3537         }
3538
3539       /* if I can do an increment instead
3540          of add then GOOD for ME */
3541       if (genPlusIncr (ic) == TRUE)
3542         {
3543           emitcode (";", "did genPlusIncr");
3544           goto release;
3545         }
3546
3547     }
3548   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3549
3550   _startLazyDPSEvaluation ();
3551   while (size--)
3552     {
3553       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3554         {
3555           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3556           if (offset == 0)
3557             emitcode ("add", "a,%s",
3558                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3559           else
3560             emitcode ("addc", "a,%s",
3561                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3562         }
3563       else
3564         {
3565           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3566           {
3567               /* right is going to use ACC or we would have taken the
3568                * above branch.
3569                */
3570               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3571        TR_AP("#3");
3572               D(emitcode(";", "+ AOP_ACC special case."););
3573               emitcode("xch", "a, %s", DP2_RESULT_REG);
3574           }
3575           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3576           if (offset == 0)
3577           {
3578             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3579             {
3580          TR_AP("#4");
3581                 emitcode("add", "a, %s", DP2_RESULT_REG); 
3582             }
3583             else
3584             {
3585                 emitcode ("add", "a,%s",
3586                         aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3587             }
3588           }
3589           else
3590           {
3591             emitcode ("addc", "a,%s",
3592                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3593           }
3594         }
3595       if (!pushResult)
3596         {
3597           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3598         }
3599       else
3600         {
3601           emitcode ("push", "acc");
3602         }
3603       offset++;
3604     }
3605   _endLazyDPSEvaluation ();
3606
3607   if (pushResult)
3608     {
3609       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3610
3611       size = getDataSize (IC_LEFT (ic));
3612       rSize = getDataSize (IC_RESULT (ic));
3613
3614       ADJUST_PUSHED_RESULT(size, rSize);
3615
3616       _startLazyDPSEvaluation ();
3617       while (size--)
3618         {
3619           emitcode ("pop", "acc");
3620           aopPut (AOP (IC_RESULT (ic)), "a", size);
3621         }
3622       _endLazyDPSEvaluation ();
3623     }
3624
3625   adjustArithmeticResult (ic);
3626
3627 release:
3628   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3629   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3630   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3631 }
3632
3633 /*-----------------------------------------------------------------*/
3634 /* genMinusDec :- does subtraction with deccrement if possible     */
3635 /*-----------------------------------------------------------------*/
3636 static bool
3637 genMinusDec (iCode * ic)
3638 {
3639   unsigned int icount;
3640   unsigned int size = getDataSize (IC_RESULT (ic));
3641
3642   /* will try to generate an increment */
3643   /* if the right side is not a literal
3644      we cannot */
3645   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3646     return FALSE;
3647
3648   /* if the literal value of the right hand side
3649      is greater than 4 then it is not worth it */
3650   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3651     return FALSE;
3652
3653   /* if decrement 16 bits in register */
3654   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3655       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3656       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3657       (size > 1) &&
3658       (icount == 1))
3659     {
3660       symbol *tlbl;
3661       int emitTlbl;
3662       int labelRange;
3663
3664       /* If the next instruction is a goto and the goto target
3665          * is <= 5 instructions previous to this, we can generate
3666          * jumps straight to that target.
3667        */
3668       if (ic->next && ic->next->op == GOTO
3669           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3670           && labelRange <= 5)
3671         {
3672           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3673           tlbl = IC_LABEL (ic->next);
3674           emitTlbl = 0;
3675         }
3676       else
3677         {
3678           tlbl = newiTempLabel (NULL);
3679           emitTlbl = 1;
3680         }
3681
3682       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3683       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3684           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3685           IS_AOP_PREG (IC_RESULT (ic)))
3686         emitcode ("cjne", "%s,#0xff,%05d$"
3687                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3688                   ,tlbl->key + 100);
3689       else
3690         {
3691           emitcode ("mov", "a,#0xff");
3692           emitcode ("cjne", "a,%s,%05d$"
3693                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3694                     ,tlbl->key + 100);
3695         }
3696       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3697       if (size > 2)
3698         {
3699           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3700               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3701               IS_AOP_PREG (IC_RESULT (ic)))
3702             emitcode ("cjne", "%s,#0xff,%05d$"
3703                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3704                       ,tlbl->key + 100);
3705           else
3706             {
3707               emitcode ("cjne", "a,%s,%05d$"
3708                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3709                         ,tlbl->key + 100);
3710             }
3711           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3712         }
3713       if (size > 3)
3714         {
3715           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3716               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3717               IS_AOP_PREG (IC_RESULT (ic)))
3718             emitcode ("cjne", "%s,#0xff,%05d$"
3719                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3720                       ,tlbl->key + 100);
3721           else
3722             {
3723               emitcode ("cjne", "a,%s,%05d$"
3724                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3725                         ,tlbl->key + 100);
3726             }
3727           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3728         }
3729       if (emitTlbl)
3730         {
3731           emitcode ("", "%05d$:", tlbl->key + 100);
3732         }
3733       return TRUE;
3734     }
3735
3736   /* if the sizes are greater than 1 then we cannot */
3737   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3738       AOP_SIZE (IC_LEFT (ic)) > 1)
3739     return FALSE;
3740
3741   /* we can if the aops of the left & result match or
3742      if they are in registers and the registers are the
3743      same */
3744   if (
3745        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3746        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3747        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3748     {
3749
3750       _startLazyDPSEvaluation ();
3751       while (icount--)
3752         {
3753           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3754         }
3755       _endLazyDPSEvaluation ();
3756
3757       return TRUE;
3758     }
3759
3760   return FALSE;
3761 }
3762
3763 /*-----------------------------------------------------------------*/
3764 /* addSign - complete with sign                                    */
3765 /*-----------------------------------------------------------------*/
3766 static void
3767 addSign (operand * result, int offset, int sign)
3768 {
3769   int size = (getDataSize (result) - offset);
3770   if (size > 0)
3771     {
3772       _startLazyDPSEvaluation();
3773       if (sign)
3774         {
3775           emitcode ("rlc", "a");
3776           emitcode ("subb", "a,acc");
3777           while (size--)
3778           {
3779             aopPut (AOP (result), "a", offset++);
3780           }
3781         }
3782       else
3783       {
3784         while (size--)
3785         {
3786           aopPut (AOP (result), zero, offset++);
3787         }
3788       }
3789       _endLazyDPSEvaluation();
3790     }
3791 }
3792
3793 /*-----------------------------------------------------------------*/
3794 /* genMinusBits - generates code for subtraction  of two bits      */
3795 /*-----------------------------------------------------------------*/
3796 static void
3797 genMinusBits (iCode * ic)
3798 {
3799   symbol *lbl = newiTempLabel (NULL);
3800
3801   D (emitcode (";", "genMinusBits "););
3802
3803   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3804     {
3805       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3806       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3807       emitcode ("cpl", "c");
3808       emitcode ("", "%05d$:", (lbl->key + 100));
3809       outBitC (IC_RESULT (ic));
3810     }
3811   else
3812     {
3813       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3814       emitcode ("subb", "a,acc");
3815       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3816       emitcode ("inc", "a");
3817       emitcode ("", "%05d$:", (lbl->key + 100));
3818       aopPut (AOP (IC_RESULT (ic)), "a", 0);
3819       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3820     }
3821 }
3822
3823 /*-----------------------------------------------------------------*/
3824 /* genMinus - generates code for subtraction                       */
3825 /*-----------------------------------------------------------------*/
3826 static void
3827 genMinus (iCode * ic)
3828 {
3829   int size, offset = 0;
3830   int rSize;
3831   unsigned long lit = 0L;
3832   bool pushResult = FALSE;
3833
3834   D (emitcode (";", "genMinus "););
3835
3836   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3837   aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3838   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3839       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3840     {
3841       pushResult = TRUE;
3842     }
3843   else
3844     {
3845       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3846
3847       /* special cases :- */
3848       /* if both left & right are in bit space */
3849       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3850           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3851         {
3852           genMinusBits (ic);
3853           goto release;
3854         }
3855
3856       /* if I can do an decrement instead
3857          of subtract then GOOD for ME */
3858       if (genMinusDec (ic) == TRUE)
3859         goto release;
3860
3861     }
3862
3863   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3864
3865   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3866     {
3867       CLRC;
3868     }
3869   else
3870     {
3871       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3872       lit = -(long) lit;
3873     }
3874
3875
3876   /* if literal, add a,#-lit, else normal subb */
3877   _startLazyDPSEvaluation ();
3878   while (size--)
3879     {
3880       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3881       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3882         emitcode ("subb", "a,%s",
3883                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3884       else
3885         {
3886           /* first add without previous c */
3887           if (!offset) {
3888             if (!size && lit==-1) {
3889               emitcode ("dec", "a");
3890             } else {
3891               emitcode ("add", "a,#0x%02x",
3892                         (unsigned int) (lit & 0x0FFL));
3893             }
3894           } else {
3895             emitcode ("addc", "a,#0x%02x",
3896                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3897           }
3898         }
3899
3900       if (pushResult)
3901         {
3902           emitcode ("push", "acc");
3903         }
3904       else
3905         {
3906           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3907         }
3908       offset++;
3909     }
3910   _endLazyDPSEvaluation ();
3911
3912   if (pushResult)
3913     {
3914       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3915
3916       size = getDataSize (IC_LEFT (ic));
3917       rSize = getDataSize (IC_RESULT (ic));
3918
3919       ADJUST_PUSHED_RESULT(size, rSize);
3920
3921       _startLazyDPSEvaluation ();
3922       while (size--)
3923         {
3924           emitcode ("pop", "acc");
3925           aopPut (AOP (IC_RESULT (ic)), "a", size);
3926         }
3927       _endLazyDPSEvaluation ();
3928     }
3929
3930   adjustArithmeticResult (ic);
3931
3932 release:
3933   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3934   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3935   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3936 }
3937
3938
3939 /*-----------------------------------------------------------------*/
3940 /* genMultbits :- multiplication of bits                           */
3941 /*-----------------------------------------------------------------*/
3942 static void
3943 genMultbits (operand * left,
3944              operand * right,
3945              operand * result,
3946              iCode   * ic)
3947 {
3948   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3949   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3950   aopOp(result, ic, TRUE, FALSE);
3951   outBitC (result);
3952 }
3953
3954
3955 /*-----------------------------------------------------------------*/
3956 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
3957 /*-----------------------------------------------------------------*/
3958 static void
3959 genMultOneByte (operand * left,
3960                 operand * right,
3961                 operand * result,
3962                 iCode   * ic)
3963 {
3964   sym_link *opetype = operandType (result);
3965   symbol *lbl;
3966
3967
3968   /* (if two literals: the value is computed before) */
3969   /* if one literal, literal on the right */
3970   if (AOP_TYPE (left) == AOP_LIT)
3971     {
3972       operand *t = right;
3973       right = left;
3974       left = t;
3975       emitcode (";", "swapped left and right");
3976     }
3977
3978   if (SPEC_USIGN(opetype)
3979       // ignore the sign of left and right, what else can we do?
3980       || (SPEC_USIGN(operandType(left)) && 
3981           SPEC_USIGN(operandType(right)))) {
3982     // just an unsigned 8*8=8/16 multiply
3983     //emitcode (";","unsigned");
3984     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3985     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3986     emitcode ("mul", "ab");
3987    
3988     _G.accInUse++;
3989     aopOp(result, ic, TRUE, FALSE);
3990       
3991       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
3992       {
3993           // this should never happen
3994           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
3995                    AOP_SIZE(result), __FILE__, lineno);
3996           exit (1);
3997       }      
3998       
3999     aopPut (AOP (result), "a", 0);
4000     _G.accInUse--;
4001     if (AOP_SIZE(result)==2) 
4002     {
4003       aopPut (AOP (result), "b", 1);
4004     }
4005     return;
4006   }
4007
4008   // we have to do a signed multiply
4009
4010   emitcode (";", "signed");
4011   emitcode ("clr", "F0"); // reset sign flag
4012   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4013
4014   lbl=newiTempLabel(NULL);
4015   emitcode ("jnb", "acc.7,%05d$",  lbl->key+100);
4016   // left side is negative, 8-bit two's complement, this fails for -128
4017   emitcode ("setb", "F0"); // set sign flag
4018   emitcode ("cpl", "a");
4019   emitcode ("inc", "a");
4020
4021   emitcode ("", "%05d$:", lbl->key+100);
4022
4023   /* if literal */
4024   if (AOP_TYPE(right)==AOP_LIT) {
4025     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4026     /* AND literal negative */
4027     if ((int) val < 0) {
4028       emitcode ("cpl", "F0"); // complement sign flag
4029       emitcode ("mov", "b,#0x%02x", -val);
4030     } else {
4031       emitcode ("mov", "b,#0x%02x", val);
4032     }
4033   } else {
4034     lbl=newiTempLabel(NULL);
4035     emitcode ("mov", "b,a");
4036     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4037     emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4038     // right side is negative, 8-bit two's complement
4039     emitcode ("cpl", "F0"); // complement sign flag
4040     emitcode ("cpl", "a");
4041     emitcode ("inc", "a");
4042     emitcode ("", "%05d$:", lbl->key+100);
4043   }
4044   emitcode ("mul", "ab");
4045     
4046   _G.accInUse++;
4047   aopOp(result, ic, TRUE, FALSE);
4048     
4049   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4050   {
4051     // this should never happen
4052       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4053                AOP_SIZE(result), __FILE__, lineno);
4054       exit (1);
4055   }    
4056     
4057   lbl=newiTempLabel(NULL);
4058   emitcode ("jnb", "F0,%05d$", lbl->key+100);
4059   // only ONE op was negative, we have to do a 8/16-bit two's complement
4060   emitcode ("cpl", "a"); // lsb
4061   if (AOP_SIZE(result)==1) {
4062     emitcode ("inc", "a");
4063   } else {
4064     emitcode ("add", "a,#1");
4065     emitcode ("xch", "a,b");
4066     emitcode ("cpl", "a"); // msb
4067     emitcode ("addc", "a,#0");
4068     emitcode ("xch", "a,b");
4069   }
4070
4071   emitcode ("", "%05d$:", lbl->key+100);
4072   aopPut (AOP (result), "a", 0);
4073   _G.accInUse--;
4074   if (AOP_SIZE(result)==2) {
4075     aopPut (AOP (result), "b", 1);
4076   }
4077 }
4078
4079 /*-----------------------------------------------------------------*/
4080 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4081 /*-----------------------------------------------------------------*/
4082 static void genMultTwoByte (operand *left, operand *right, 
4083                             operand *result, iCode *ic)
4084 {
4085         sym_link *retype = getSpec(operandType(right));
4086         sym_link *letype = getSpec(operandType(left));
4087         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4088         symbol *lbl;
4089
4090         if (AOP_TYPE (left) == AOP_LIT) {
4091                 operand *t = right;
4092                 right = left;
4093                 left = t;
4094         }
4095         /* save EA bit in F1 */
4096         lbl = newiTempLabel(NULL);
4097         emitcode ("setb","F1");
4098         emitcode ("jbc","EA,%05d$",lbl->key+100);
4099         emitcode ("clr","F1");
4100         emitcode("","%05d$:",lbl->key+100);
4101
4102         /* load up MB with right */
4103         if (!umult) {
4104                 emitcode("clr","F0");
4105                 if (AOP_TYPE(right) == AOP_LIT) {
4106                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4107                         if (val < 0) {
4108                                 emitcode("setb","F0");
4109                                 val = -val;
4110                         }
4111                         emitcode ("mov","mb,#0x%02x",val & 0xff);
4112                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);                    
4113                 } else {
4114                         lbl = newiTempLabel(NULL);
4115                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4116                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4117                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4118                         emitcode ("xch", "a,b");
4119                         emitcode ("cpl","a");
4120                         emitcode ("add", "a,#1");
4121                         emitcode ("xch", "a,b");
4122                         emitcode ("cpl", "a"); // msb
4123                         emitcode ("addc", "a,#0");
4124                         emitcode ("setb","F0");
4125                         emitcode ("","%05d$:",lbl->key+100);
4126                         emitcode ("mov","mb,b");
4127                         emitcode ("mov","mb,a");
4128                 }
4129         } else {
4130                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4131                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4132         }
4133         /* load up MA with left */
4134         if (!umult) {
4135                 lbl = newiTempLabel(NULL);
4136                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4137                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4138                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4139                 emitcode ("xch", "a,b");
4140                 emitcode ("cpl","a");
4141                 emitcode ("add", "a,#1");
4142                 emitcode ("xch", "a,b");
4143                 emitcode ("cpl", "a"); // msb
4144                 emitcode ("addc","a,#0");
4145                 emitcode ("jbc","F0,%05d$",lbl->key+100);
4146                 emitcode ("setb","F0");
4147                 emitcode ("","%05d$:",lbl->key+100);
4148                 emitcode ("mov","ma,b");
4149                 emitcode ("mov","ma,a");
4150         } else {
4151                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4152                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4153         }
4154         /* wait for multiplication to finish */
4155         lbl = newiTempLabel(NULL);
4156         emitcode("","%05d$:", lbl->key+100);
4157         emitcode("mov","a,mcnt1");
4158         emitcode("anl","a,#0x80");
4159         emitcode("jnz","%05d$",lbl->key+100);
4160         
4161         freeAsmop (left, NULL, ic, TRUE);
4162         freeAsmop (right, NULL, ic,TRUE);
4163         aopOp(result, ic, TRUE, FALSE);
4164
4165         /* if unsigned then simple */   
4166         if (umult) {
4167                 emitcode ("mov","a,ma");
4168                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4169                 emitcode ("mov","a,ma");
4170                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4171                 aopPut(AOP(result),"ma",1);
4172                 aopPut(AOP(result),"ma",0);
4173         } else {
4174                 emitcode("push","ma");
4175                 emitcode("push","ma");
4176                 emitcode("push","ma");
4177                 MOVA("ma");
4178                 /* negate result if needed */
4179                 lbl = newiTempLabel(NULL);      
4180                 emitcode("jnb","F0,%05d$",lbl->key+100);
4181                 emitcode("cpl","a");
4182                 emitcode("add","a,#1");
4183                 emitcode("","%05d$:", lbl->key+100);
4184                 if (AOP_TYPE(result) == AOP_ACC)
4185                 {
4186                     D(emitcode(";", "ACC special case."););
4187                     /* We know result is the only live aop, and 
4188                      * it's obviously not a DPTR2, so AP is available.
4189                      */
4190                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4191                 }
4192                 else
4193                 {
4194                     aopPut(AOP(result),"a",0);
4195                 }
4196             
4197                 emitcode("pop","acc");
4198                 lbl = newiTempLabel(NULL);      
4199                 emitcode("jnb","F0,%05d$",lbl->key+100);
4200                 emitcode("cpl","a");
4201                 emitcode("addc","a,#0");
4202                 emitcode("","%05d$:", lbl->key+100);
4203                 aopPut(AOP(result),"a",1);
4204                 emitcode("pop","acc");
4205                 if (AOP_SIZE(result) >= 3) {
4206                         lbl = newiTempLabel(NULL);      
4207                         emitcode("jnb","F0,%05d$",lbl->key+100);
4208                         emitcode("cpl","a");
4209                         emitcode("addc","a,#0");                        
4210                         emitcode("","%05d$:", lbl->key+100);
4211                         aopPut(AOP(result),"a",2);
4212                 }
4213                 emitcode("pop","acc");
4214                 if (AOP_SIZE(result) >= 4) {
4215                         lbl = newiTempLabel(NULL);      
4216                         emitcode("jnb","F0,%05d$",lbl->key+100);
4217                         emitcode("cpl","a");
4218                         emitcode("addc","a,#0");                        
4219                         emitcode("","%05d$:", lbl->key+100);
4220                         aopPut(AOP(result),"a",3);
4221                 }
4222                 if (AOP_TYPE(result) == AOP_ACC)
4223                 {
4224                     /* We stashed the result away above. */
4225                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4226                 }           
4227                 
4228         }
4229         freeAsmop (result, NULL, ic, TRUE);
4230
4231         /* restore EA bit in F1 */
4232         lbl = newiTempLabel(NULL);
4233         emitcode ("jnb","F1,%05d$",lbl->key+100);
4234         emitcode ("setb","EA");
4235         emitcode("","%05d$:",lbl->key+100);
4236         return ;
4237 }
4238
4239 /*-----------------------------------------------------------------*/
4240 /* genMult - generates code for multiplication                     */
4241 /*-----------------------------------------------------------------*/
4242 static void
4243 genMult (iCode * ic)
4244 {
4245   operand *left = IC_LEFT (ic);
4246   operand *right = IC_RIGHT (ic);
4247   operand *result = IC_RESULT (ic);
4248
4249   D (emitcode (";", "genMult "););
4250
4251   /* assign the amsops */
4252   AOP_OP_2 (ic);
4253
4254   /* special cases first */
4255   /* both are bits */
4256   if (AOP_TYPE (left) == AOP_CRY &&
4257       AOP_TYPE (right) == AOP_CRY)
4258     {
4259       genMultbits (left, right, result, ic);
4260       goto release;
4261     }
4262
4263   /* if both are of size == 1 */
4264   if (AOP_SIZE (left) == 1 &&
4265       AOP_SIZE (right) == 1)
4266     {
4267       genMultOneByte (left, right, result, ic);
4268       goto release;
4269     }
4270
4271   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4272           /* use the ds390 ARITHMETIC accel UNIT */
4273           genMultTwoByte (left, right, result, ic);
4274           return ;
4275   }
4276   /* should have been converted to function call */
4277   assert (0);
4278
4279 release:
4280   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4281   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4282   freeAsmop (result, NULL, ic, TRUE);
4283 }
4284
4285 /*-----------------------------------------------------------------*/
4286 /* genDivbits :- division of bits                                  */
4287 /*-----------------------------------------------------------------*/
4288 static void
4289 genDivbits (operand * left,
4290             operand * right,
4291             operand * result,
4292             iCode   * ic)
4293 {
4294
4295   char *l;
4296
4297   /* the result must be bit */
4298   LOAD_AB_FOR_DIV (left, right, l);
4299   emitcode ("div", "ab");
4300   emitcode ("rrc", "a");
4301   aopOp(result, ic, TRUE, FALSE);
4302     
4303   aopPut (AOP (result), "c", 0);
4304 }
4305
4306 /*-----------------------------------------------------------------*/
4307 /* genDivOneByte : 8 bit division                                  */
4308 /*-----------------------------------------------------------------*/
4309 static void
4310 genDivOneByte (operand * left,
4311                operand * right,
4312                operand * result,
4313                iCode   * ic)
4314 {
4315   sym_link *opetype = operandType (result);
4316   char *l;
4317   symbol *lbl;
4318   int size, offset;
4319
4320   offset = 1;
4321   /* signed or unsigned */
4322   if (SPEC_USIGN (opetype))
4323     {
4324         /* unsigned is easy */
4325         LOAD_AB_FOR_DIV (left, right, l);
4326         emitcode ("div", "ab");
4327
4328         _G.accInUse++;
4329         aopOp(result, ic, TRUE, FALSE);
4330         aopPut (AOP (result), "a", 0);
4331         _G.accInUse--;
4332
4333         size = AOP_SIZE (result) - 1;
4334         
4335         while (size--)
4336         {
4337             aopPut (AOP (result), zero, offset++);
4338         }
4339       return;
4340     }
4341
4342   /* signed is a little bit more difficult */
4343
4344   /* save the signs of the operands */
4345   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4346   MOVA (l);
4347   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4348   emitcode ("push", "acc");     /* save it on the stack */
4349
4350   /* now sign adjust for both left & right */
4351   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4352   MOVA (l);
4353   lbl = newiTempLabel (NULL);
4354   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4355   emitcode ("cpl", "a");
4356   emitcode ("inc", "a");
4357   emitcode ("", "%05d$:", (lbl->key + 100));
4358   emitcode ("mov", "b,a");
4359
4360   /* sign adjust left side */
4361   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4362   MOVA (l);
4363
4364   lbl = newiTempLabel (NULL);
4365   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4366   emitcode ("cpl", "a");
4367   emitcode ("inc", "a");
4368   emitcode ("", "%05d$:", (lbl->key + 100));
4369
4370   /* now the division */
4371   emitcode ("nop", "; workaround for DS80C390 div bug.");
4372   emitcode ("div", "ab");
4373   /* we are interested in the lower order
4374      only */
4375   emitcode ("mov", "b,a");
4376   lbl = newiTempLabel (NULL);
4377   emitcode ("pop", "acc");
4378   /* if there was an over flow we don't
4379      adjust the sign of the result */
4380   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4381   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4382   CLRC;
4383   emitcode ("clr", "a");
4384   emitcode ("subb", "a,b");
4385   emitcode ("mov", "b,a");
4386   emitcode ("", "%05d$:", (lbl->key + 100));
4387
4388   /* now we are done */
4389     _G.accInUse++;
4390     aopOp(result, ic, TRUE, FALSE);
4391     
4392     aopPut (AOP (result), "b", 0);
4393     
4394     size = AOP_SIZE (result) - 1;
4395     
4396     if (size > 0)
4397     {
4398       emitcode ("mov", "c,b.7");
4399       emitcode ("subb", "a,acc");
4400     }
4401     while (size--)
4402     {
4403         aopPut (AOP (result), "a", offset++);
4404     }
4405     _G.accInUse--;
4406
4407 }
4408
4409 /*-----------------------------------------------------------------*/
4410 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4411 /*-----------------------------------------------------------------*/
4412 static void genDivTwoByte (operand *left, operand *right, 
4413                             operand *result, iCode *ic)
4414 {
4415         sym_link *retype = getSpec(operandType(right));
4416         sym_link *letype = getSpec(operandType(left));
4417         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4418         symbol *lbl;
4419
4420         /* save EA bit in F1 */
4421         lbl = newiTempLabel(NULL);
4422         emitcode ("setb","F1");
4423         emitcode ("jbc","EA,%05d$",lbl->key+100);
4424         emitcode ("clr","F1");
4425         emitcode("","%05d$:",lbl->key+100);
4426
4427         /* load up MA with left */
4428         if (!umult) {
4429                 emitcode("clr","F0");
4430                 lbl = newiTempLabel(NULL);
4431                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4432                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4433                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4434                 emitcode ("xch", "a,b");
4435                 emitcode ("cpl","a");
4436                 emitcode ("add", "a,#1");
4437                 emitcode ("xch", "a,b");
4438                 emitcode ("cpl", "a"); // msb
4439                 emitcode ("addc","a,#0");
4440                 emitcode ("setb","F0");
4441                 emitcode ("","%05d$:",lbl->key+100);
4442                 emitcode ("mov","ma,b");
4443                 emitcode ("mov","ma,a");
4444         } else {
4445                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4446                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4447         }
4448
4449         /* load up MB with right */
4450         if (!umult) {
4451                 if (AOP_TYPE(right) == AOP_LIT) {
4452                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4453                         if (val < 0) {
4454                                 lbl = newiTempLabel(NULL);
4455                                 emitcode ("jbc","F0,%05d$",lbl->key+100);
4456                                 emitcode("setb","F0");
4457                                 emitcode ("","%05d$:",lbl->key+100);
4458                                 val = -val;
4459                         } 
4460                         emitcode ("mov","mb,#0x%02x",val & 0xff);                   
4461                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4462                 } else {
4463                         lbl = newiTempLabel(NULL);
4464                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4465                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4466                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4467                         emitcode ("xch", "a,b");
4468                         emitcode ("cpl","a");
4469                         emitcode ("add", "a,#1");
4470                         emitcode ("xch", "a,b");
4471                         emitcode ("cpl", "a"); // msb
4472                         emitcode ("addc", "a,#0");
4473                         emitcode ("jbc","F0,%05d$",lbl->key+100);
4474                         emitcode ("setb","F0");
4475                         emitcode ("","%05d$:",lbl->key+100);
4476                         emitcode ("mov","mb,b");
4477                         emitcode ("mov","mb,a");
4478                 }
4479         } else {
4480                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4481                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4482         }
4483
4484         /* wait for multiplication to finish */
4485         lbl = newiTempLabel(NULL);
4486         emitcode("","%05d$:", lbl->key+100);
4487         emitcode("mov","a,mcnt1");
4488         emitcode("anl","a,#0x80");
4489         emitcode("jnz","%05d$",lbl->key+100);
4490         
4491         freeAsmop (left, NULL, ic, TRUE);
4492         freeAsmop (right, NULL, ic,TRUE);
4493         aopOp(result, ic, TRUE, FALSE);
4494
4495         /* if unsigned then simple */   
4496         if (umult) {
4497                 aopPut(AOP(result),"ma",1);
4498                 aopPut(AOP(result),"ma",0);
4499         } else {
4500                 emitcode("push","ma");
4501                 MOVA("ma");
4502                 /* negate result if needed */
4503                 lbl = newiTempLabel(NULL);      
4504                 emitcode("jnb","F0,%05d$",lbl->key+100);
4505                 emitcode("cpl","a");
4506                 emitcode("add","a,#1");
4507                 emitcode("","%05d$:", lbl->key+100);
4508                 aopPut(AOP(result),"a",0);
4509                 emitcode("pop","acc");
4510                 lbl = newiTempLabel(NULL);      
4511                 emitcode("jnb","F0,%05d$",lbl->key+100);
4512                 emitcode("cpl","a");
4513                 emitcode("addc","a,#0");
4514                 emitcode("","%05d$:", lbl->key+100);
4515                 aopPut(AOP(result),"a",1);
4516         }
4517         freeAsmop (result, NULL, ic, TRUE);
4518         /* restore EA bit in F1 */
4519         lbl = newiTempLabel(NULL);
4520         emitcode ("jnb","F1,%05d$",lbl->key+100);
4521         emitcode ("setb","EA");
4522         emitcode("","%05d$:",lbl->key+100);
4523         return ;
4524 }
4525
4526 /*-----------------------------------------------------------------*/
4527 /* genDiv - generates code for division                            */
4528 /*-----------------------------------------------------------------*/
4529 static void
4530 genDiv (iCode * ic)
4531 {
4532   operand *left = IC_LEFT (ic);
4533   operand *right = IC_RIGHT (ic);
4534   operand *result = IC_RESULT (ic);
4535
4536   D (emitcode (";", "genDiv "););
4537
4538   /* assign the amsops */
4539   AOP_OP_2 (ic);
4540
4541   /* special cases first */
4542   /* both are bits */
4543   if (AOP_TYPE (left) == AOP_CRY &&
4544       AOP_TYPE (right) == AOP_CRY)
4545     {
4546       genDivbits (left, right, result, ic);
4547       goto release;
4548     }
4549
4550   /* if both are of size == 1 */
4551   if (AOP_SIZE (left) == 1 &&
4552       AOP_SIZE (right) == 1)
4553     {
4554       genDivOneByte (left, right, result, ic);
4555       goto release;
4556     }
4557
4558   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4559           /* use the ds390 ARITHMETIC accel UNIT */
4560           genDivTwoByte (left, right, result, ic);
4561           return ;
4562   }
4563   /* should have been converted to function call */
4564   assert (0);
4565 release:
4566   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4567   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4568   freeAsmop (result, NULL, ic, TRUE);
4569 }
4570
4571 /*-----------------------------------------------------------------*/
4572 /* genModbits :- modulus of bits                                   */
4573 /*-----------------------------------------------------------------*/
4574 static void
4575 genModbits (operand * left,
4576             operand * right,
4577             operand * result,
4578             iCode   * ic)
4579 {
4580
4581   char *l;
4582
4583   /* the result must be bit */
4584   LOAD_AB_FOR_DIV (left, right, l);
4585   emitcode ("div", "ab");
4586   emitcode ("mov", "a,b");
4587   emitcode ("rrc", "a");
4588   aopOp(result, ic, TRUE, FALSE);
4589   aopPut (AOP (result), "c", 0);
4590 }
4591
4592 /*-----------------------------------------------------------------*/
4593 /* genModOneByte : 8 bit modulus                                   */
4594 /*-----------------------------------------------------------------*/
4595 static void
4596 genModOneByte (operand * left,
4597                operand * right,
4598                operand * result,
4599                iCode   * ic)
4600 {
4601   sym_link *opetype = operandType (result);
4602   char *l;
4603   symbol *lbl;
4604
4605   /* signed or unsigned */
4606   if (SPEC_USIGN (opetype))
4607     {
4608       /* unsigned is easy */
4609       LOAD_AB_FOR_DIV (left, right, l);
4610       emitcode ("div", "ab");
4611       aopOp(result, ic, TRUE, FALSE);   
4612       aopPut (AOP (result), "b", 0);
4613       return;
4614     }
4615
4616   /* signed is a little bit more difficult */
4617
4618   /* save the signs of the operands */
4619   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4620   MOVA (l);
4621
4622   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4623   emitcode ("push", "acc");     /* save it on the stack */
4624
4625   /* now sign adjust for both left & right */
4626   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4627   MOVA (l);
4628
4629   lbl = newiTempLabel (NULL);
4630   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4631   emitcode ("cpl", "a");
4632   emitcode ("inc", "a");
4633   emitcode ("", "%05d$:", (lbl->key + 100));
4634   emitcode ("mov", "b,a");
4635
4636   /* sign adjust left side */
4637   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4638   MOVA (l);
4639
4640   lbl = newiTempLabel (NULL);
4641   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4642   emitcode ("cpl", "a");
4643   emitcode ("inc", "a");
4644   emitcode ("", "%05d$:", (lbl->key + 100));
4645
4646   /* now the multiplication */
4647   emitcode ("nop", "; workaround for DS80C390 div bug.");
4648   emitcode ("div", "ab");
4649   /* we are interested in the lower order
4650      only */
4651   lbl = newiTempLabel (NULL);
4652   emitcode ("pop", "acc");
4653   /* if there was an over flow we don't
4654      adjust the sign of the result */
4655   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4656   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4657   CLRC;
4658   emitcode ("clr", "a");
4659   emitcode ("subb", "a,b");
4660   emitcode ("mov", "b,a");
4661   emitcode ("", "%05d$:", (lbl->key + 100));
4662
4663   /* now we are done */
4664   aopOp(result, ic, TRUE, FALSE);    
4665   aopPut (AOP (result), "b", 0);
4666
4667 }
4668
4669 /*-----------------------------------------------------------------*/
4670 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
4671 /*-----------------------------------------------------------------*/
4672 static void genModTwoByte (operand *left, operand *right, 
4673                             operand *result, iCode *ic)
4674 {
4675         sym_link *retype = getSpec(operandType(right));
4676         sym_link *letype = getSpec(operandType(left));
4677         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4678         symbol *lbl;
4679
4680         /* load up MA with left */
4681         /* save EA bit in F1 */
4682         lbl = newiTempLabel(NULL);
4683         emitcode ("setb","F1");
4684         emitcode ("jbc","EA,%05d$",lbl->key+100);
4685         emitcode ("clr","F1");
4686         emitcode("","%05d$:",lbl->key+100);
4687
4688         if (!umult) {
4689                 lbl = newiTempLabel(NULL);
4690                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4691                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4692                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4693                 emitcode ("xch", "a,b");
4694                 emitcode ("cpl","a");
4695                 emitcode ("add", "a,#1");
4696                 emitcode ("xch", "a,b");
4697                 emitcode ("cpl", "a"); // msb
4698                 emitcode ("addc","a,#0");
4699                 emitcode ("","%05d$:",lbl->key+100);
4700                 emitcode ("mov","ma,b");
4701                 emitcode ("mov","ma,a");
4702         } else {
4703                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4704                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4705         }
4706
4707         /* load up MB with right */
4708         if (!umult) {
4709                 if (AOP_TYPE(right) == AOP_LIT) {
4710                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4711                         if (val < 0) {
4712                                 val = -val;
4713                         } 
4714                         emitcode ("mov","mb,#0x%02x",val & 0xff);
4715                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);                    
4716                 } else {
4717                         lbl = newiTempLabel(NULL);
4718                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4719                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4720                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4721                         emitcode ("xch", "a,b");
4722                         emitcode ("cpl","a");
4723                         emitcode ("add", "a,#1");
4724                         emitcode ("xch", "a,b");
4725                         emitcode ("cpl", "a"); // msb
4726                         emitcode ("addc", "a,#0");
4727                         emitcode ("","%05d$:",lbl->key+100);
4728                         emitcode ("mov","mb,b");
4729                         emitcode ("mov","mb,a");
4730                 }
4731         } else {
4732                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4733                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4734         }
4735
4736         /* wait for multiplication to finish */
4737         lbl = newiTempLabel(NULL);
4738         emitcode("","%05d$:", lbl->key+100);
4739         emitcode("mov","a,mcnt1");
4740         emitcode("anl","a,#0x80");
4741         emitcode("jnz","%05d$",lbl->key+100);
4742         
4743         freeAsmop (left, NULL, ic, TRUE);
4744         freeAsmop (right, NULL, ic,TRUE);
4745         aopOp(result, ic, TRUE, FALSE);
4746
4747         aopPut(AOP(result),"mb",1);
4748         aopPut(AOP(result),"mb",0);
4749         freeAsmop (result, NULL, ic, TRUE);
4750
4751         /* restore EA bit in F1 */
4752         lbl = newiTempLabel(NULL);
4753         emitcode ("jnb","F1,%05d$",lbl->key+100);
4754         emitcode ("setb","EA");
4755         emitcode("","%05d$:",lbl->key+100);
4756         return ;
4757 }
4758
4759 /*-----------------------------------------------------------------*/
4760 /* genMod - generates code for division                            */
4761 /*-----------------------------------------------------------------*/
4762 static void
4763 genMod (iCode * ic)
4764 {
4765   operand *left = IC_LEFT (ic);
4766   operand *right = IC_RIGHT (ic);
4767   operand *result = IC_RESULT (ic);
4768
4769   D (emitcode (";", "genMod "); );
4770
4771   /* assign the amsops */
4772   AOP_OP_2 (ic);
4773
4774   /* special cases first */
4775   /* both are bits */
4776   if (AOP_TYPE (left) == AOP_CRY &&
4777       AOP_TYPE (right) == AOP_CRY)
4778     {
4779       genModbits (left, right, result, ic);
4780       goto release;
4781     }
4782
4783   /* if both are of size == 1 */
4784   if (AOP_SIZE (left) == 1 &&
4785       AOP_SIZE (right) == 1)
4786     {
4787       genModOneByte (left, right, result, ic);
4788       goto release;
4789     }
4790
4791   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4792           /* use the ds390 ARITHMETIC accel UNIT */
4793           genModTwoByte (left, right, result, ic);
4794           return ;
4795   }
4796
4797   /* should have been converted to function call */
4798   assert (0);
4799
4800 release:
4801   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4802   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4803   freeAsmop (result, NULL, ic, TRUE);
4804 }
4805
4806 /*-----------------------------------------------------------------*/
4807 /* genIfxJump :- will create a jump depending on the ifx           */
4808 /*-----------------------------------------------------------------*/
4809 static void
4810 genIfxJump (iCode * ic, char *jval)
4811 {
4812   symbol *jlbl;
4813   symbol *tlbl = newiTempLabel (NULL);
4814   char *inst;
4815
4816   D (emitcode (";", "genIfxJump ");
4817     );
4818
4819   /* if true label then we jump if condition
4820      supplied is true */
4821   if (IC_TRUE (ic))
4822     {
4823       jlbl = IC_TRUE (ic);
4824       inst = ((strcmp (jval, "a") == 0 ? "jz" :
4825                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4826     }
4827   else
4828     {
4829       /* false label is present */
4830       jlbl = IC_FALSE (ic);
4831       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4832                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4833     }
4834   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4835     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4836   else
4837     emitcode (inst, "%05d$", tlbl->key + 100);
4838   emitcode ("ljmp", "%05d$", jlbl->key + 100);
4839   emitcode ("", "%05d$:", tlbl->key + 100);
4840
4841   /* mark the icode as generated */
4842   ic->generated = 1;
4843 }
4844
4845 /*-----------------------------------------------------------------*/
4846 /* genCmp :- greater or less than comparison                       */
4847 /*-----------------------------------------------------------------*/
4848 static void
4849 genCmp (operand * left, operand * right,
4850         iCode * ic, iCode * ifx, int sign)
4851 {
4852   int size, offset = 0;
4853   unsigned long lit = 0L;
4854   operand *result;
4855
4856   D (emitcode (";", "genCmp");
4857     );
4858
4859   result = IC_RESULT (ic);
4860
4861   /* if left & right are bit variables */
4862   if (AOP_TYPE (left) == AOP_CRY &&
4863       AOP_TYPE (right) == AOP_CRY)
4864     {
4865       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4866       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4867     }
4868   else
4869     {
4870       /* subtract right from left if at the
4871          end the carry flag is set then we know that
4872          left is greater than right */
4873       size = max (AOP_SIZE (left), AOP_SIZE (right));
4874
4875       /* if unsigned char cmp with lit, do cjne left,#right,zz */
4876       if ((size == 1) && !sign &&
4877           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4878         {
4879           symbol *lbl = newiTempLabel (NULL);
4880           emitcode ("cjne", "%s,%s,%05d$",
4881                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4882                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4883                     lbl->key + 100);
4884           emitcode ("", "%05d$:", lbl->key + 100);
4885         }
4886       else
4887         {
4888           if (AOP_TYPE (right) == AOP_LIT)
4889             {
4890               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4891               /* optimize if(x < 0) or if(x >= 0) */
4892               if (lit == 0L)
4893                 {
4894                   if (!sign)
4895                     {
4896                       CLRC;
4897                     }
4898                   else
4899                     {
4900                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4901
4902                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4903                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4904
4905                       aopOp (result, ic, FALSE, FALSE);
4906
4907                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4908                         {
4909                           freeAsmop (result, NULL, ic, TRUE);
4910                           genIfxJump (ifx, "acc.7");
4911                           return;
4912                         }
4913                       else
4914                         {
4915                           emitcode ("rlc", "a");
4916                         }
4917                       goto release_freedLR;
4918                     }
4919                   goto release;
4920                 }
4921             }
4922           CLRC;
4923           while (size--)
4924             {
4925               emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4926               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4927               emitcode (";", "genCmp #2");
4928               if (sign && (size == 0))
4929                 {
4930                   emitcode (";", "genCmp #3");
4931                   emitcode ("xrl", "a,#0x80");
4932                   if (AOP_TYPE (right) == AOP_LIT)
4933                     {
4934                       unsigned long lit = (unsigned long)
4935                       floatFromVal (AOP (right)->aopu.aop_lit);
4936                       emitcode (";", "genCmp #3.1");
4937                       emitcode ("subb", "a,#0x%02x",
4938                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4939                     }
4940                   else
4941                     {
4942                       emitcode (";", "genCmp #3.2");
4943                       if (AOP_NEEDSACC (right))
4944                         {
4945                           emitcode ("push", "acc");
4946                         }
4947                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4948                                                        FALSE, FALSE, FALSE));
4949                       emitcode ("xrl", "b,#0x80");
4950                       if (AOP_NEEDSACC (right))
4951                         {
4952                           emitcode ("pop", "acc");
4953                         }
4954                       emitcode ("subb", "a,b");
4955                     }
4956                 }
4957               else
4958                 {
4959                   const char *s;
4960
4961                   emitcode (";", "genCmp #4");
4962                   if (AOP_NEEDSACC (right))
4963                     {
4964                       /* Yuck!! */
4965                       emitcode (";", "genCmp #4.1");
4966                       emitcode ("xch", "a, b");
4967                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4968                       emitcode ("xch", "a, b");
4969                       s = "b";
4970                     }
4971                   else
4972                     {
4973                       emitcode (";", "genCmp #4.2");
4974                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4975                     }
4976
4977                   emitcode ("subb", "a,%s", s);
4978                 }
4979             }
4980         }
4981     }
4982
4983 release:
4984 /* Don't need the left & right operands any more; do need the result. */
4985   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4986   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4987
4988   aopOp (result, ic, FALSE, FALSE);
4989
4990 release_freedLR:
4991
4992   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4993     {
4994       outBitC (result);
4995     }
4996   else
4997     {
4998       /* if the result is used in the next
4999          ifx conditional branch then generate
5000          code a little differently */
5001       if (ifx)
5002         {
5003           genIfxJump (ifx, "c");
5004         }
5005       else
5006         {
5007           outBitC (result);
5008         }
5009       /* leave the result in acc */
5010     }
5011   freeAsmop (result, NULL, ic, TRUE);
5012 }
5013
5014 /*-----------------------------------------------------------------*/
5015 /* genCmpGt :- greater than comparison                             */
5016 /*-----------------------------------------------------------------*/
5017 static void
5018 genCmpGt (iCode * ic, iCode * ifx)
5019 {
5020   operand *left, *right;
5021   sym_link *letype, *retype;
5022   int sign;
5023
5024   D (emitcode (";", "genCmpGt ");
5025     );
5026
5027   left = IC_LEFT (ic);
5028   right = IC_RIGHT (ic);
5029
5030   letype = getSpec (operandType (left));
5031   retype = getSpec (operandType (right));
5032   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5033
5034   /* assign the left & right amsops */
5035   AOP_OP_2 (ic);
5036
5037   genCmp (right, left, ic, ifx, sign);
5038 }
5039
5040 /*-----------------------------------------------------------------*/
5041 /* genCmpLt - less than comparisons                                */
5042 /*-----------------------------------------------------------------*/
5043 static void
5044 genCmpLt (iCode * ic, iCode * ifx)
5045 {
5046   operand *left, *right;
5047   sym_link *letype, *retype;
5048   int sign;
5049
5050   D (emitcode (";", "genCmpLt "););
5051
5052   left = IC_LEFT (ic);
5053   right = IC_RIGHT (ic);
5054
5055   letype = getSpec (operandType (left));
5056   retype = getSpec (operandType (right));
5057   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5058
5059   /* assign the left & right amsops */
5060   AOP_OP_2 (ic);
5061
5062   genCmp (left, right, ic, ifx, sign);
5063 }
5064
5065 /*-----------------------------------------------------------------*/
5066 /* gencjneshort - compare and jump if not equal                    */
5067 /*-----------------------------------------------------------------*/
5068 static void
5069 gencjneshort (operand * left, operand * right, symbol * lbl)
5070 {
5071   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5072   int offset = 0;
5073   unsigned long lit = 0L;
5074
5075   D (emitcode (";", "gencjneshort");
5076     );
5077
5078   /* if the left side is a literal or
5079      if the right is in a pointer register and left
5080      is not */
5081   if ((AOP_TYPE (left) == AOP_LIT) ||
5082       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5083     {
5084       operand *t = right;
5085       right = left;
5086       left = t;
5087     }
5088
5089   if (AOP_TYPE (right) == AOP_LIT)
5090     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5091
5092   if (opIsGptr (left) || opIsGptr (right))
5093     {
5094       /* We are comparing a generic pointer to something.
5095        * Exclude the generic type byte from the comparison.
5096        */
5097       size--;
5098       D (emitcode (";", "cjneshort: generic ptr special case.");
5099         )
5100     }
5101
5102
5103   /* if the right side is a literal then anything goes */
5104   if (AOP_TYPE (right) == AOP_LIT &&
5105       AOP_TYPE (left) != AOP_DIR)
5106     {
5107       while (size--)
5108         {
5109           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5110           MOVA (l);
5111           emitcode ("cjne", "a,%s,%05d$",
5112                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5113                     lbl->key + 100);
5114           offset++;
5115         }
5116     }
5117
5118   /* if the right side is in a register or in direct space or
5119      if the left is a pointer register & right is not */
5120   else if (AOP_TYPE (right) == AOP_REG ||
5121            AOP_TYPE (right) == AOP_DIR ||
5122            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5123            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5124     {
5125       while (size--)
5126         {
5127           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5128           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5129               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5130             emitcode ("jnz", "%05d$", lbl->key + 100);
5131           else
5132             emitcode ("cjne", "a,%s,%05d$",
5133                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5134                       lbl->key + 100);
5135           offset++;
5136         }
5137     }
5138   else
5139     {
5140       /* right is a pointer reg need both a & b */
5141       while (size--)
5142         {
5143           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5144           if (strcmp (l, "b"))
5145             emitcode ("mov", "b,%s", l);
5146           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5147           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5148           offset++;
5149         }
5150     }
5151 }
5152
5153 /*-----------------------------------------------------------------*/
5154 /* gencjne - compare and jump if not equal                         */
5155 /*-----------------------------------------------------------------*/
5156 static void
5157 gencjne (operand * left, operand * right, symbol * lbl)
5158 {
5159   symbol *tlbl = newiTempLabel (NULL);
5160
5161   D (emitcode (";", "gencjne");
5162     );
5163
5164   gencjneshort (left, right, lbl);
5165
5166   emitcode ("mov", "a,%s", one);
5167   emitcode ("sjmp", "%05d$", tlbl->key + 100);
5168   emitcode ("", "%05d$:", lbl->key + 100);
5169   emitcode ("clr", "a");
5170   emitcode ("", "%05d$:", tlbl->key + 100);
5171 }
5172
5173 /*-----------------------------------------------------------------*/
5174 /* genCmpEq - generates code for equal to                          */
5175 /*-----------------------------------------------------------------*/
5176 static void
5177 genCmpEq (iCode * ic, iCode * ifx)
5178 {
5179   operand *left, *right, *result;
5180
5181   D (emitcode (";", "genCmpEq ");
5182     );
5183
5184   AOP_OP_2 (ic);
5185   AOP_SET_LOCALS (ic);
5186
5187   /* if literal, literal on the right or
5188      if the right is in a pointer register and left
5189      is not */
5190   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5191       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5192     {
5193       operand *t = IC_RIGHT (ic);
5194       IC_RIGHT (ic) = IC_LEFT (ic);
5195       IC_LEFT (ic) = t;
5196     }
5197
5198   if (ifx &&                    /* !AOP_SIZE(result) */
5199       OP_SYMBOL (result) &&
5200       OP_SYMBOL (result)->regType == REG_CND)
5201     {
5202       symbol *tlbl;
5203       /* if they are both bit variables */
5204       if (AOP_TYPE (left) == AOP_CRY &&
5205           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5206         {
5207           if (AOP_TYPE (right) == AOP_LIT)
5208             {
5209               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5210               if (lit == 0L)
5211                 {
5212                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5213                   emitcode ("cpl", "c");
5214                 }
5215               else if (lit == 1L)
5216                 {
5217                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5218                 }
5219               else
5220                 {
5221                   emitcode ("clr", "c");
5222                 }
5223               /* AOP_TYPE(right) == AOP_CRY */
5224             }
5225           else
5226             {
5227               symbol *lbl = newiTempLabel (NULL);
5228               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5229               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5230               emitcode ("cpl", "c");
5231               emitcode ("", "%05d$:", (lbl->key + 100));
5232             }
5233           /* if true label then we jump if condition
5234              supplied is true */
5235           tlbl = newiTempLabel (NULL);
5236           if (IC_TRUE (ifx))
5237             {
5238               emitcode ("jnc", "%05d$", tlbl->key + 100);
5239               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5240             }
5241           else
5242             {
5243               emitcode ("jc", "%05d$", tlbl->key + 100);
5244               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5245             }
5246           emitcode ("", "%05d$:", tlbl->key + 100);
5247         }
5248       else
5249         {
5250           tlbl = newiTempLabel (NULL);
5251           gencjneshort (left, right, tlbl);
5252           if (IC_TRUE (ifx))
5253             {
5254               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5255               emitcode ("", "%05d$:", tlbl->key + 100);
5256             }
5257           else
5258             {
5259               symbol *lbl = newiTempLabel (NULL);
5260               emitcode ("sjmp", "%05d$", lbl->key + 100);
5261               emitcode ("", "%05d$:", tlbl->key + 100);
5262               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5263               emitcode ("", "%05d$:", lbl->key + 100);
5264             }
5265         }
5266       /* mark the icode as generated */
5267       ifx->generated = 1;
5268
5269       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5270       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5271       return;
5272     }
5273
5274   /* if they are both bit variables */
5275   if (AOP_TYPE (left) == AOP_CRY &&
5276       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5277     {
5278       if (AOP_TYPE (right) == AOP_LIT)
5279         {
5280           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5281           if (lit == 0L)
5282             {
5283               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5284               emitcode ("cpl", "c");
5285             }
5286           else if (lit == 1L)
5287             {
5288               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5289             }
5290           else
5291             {
5292               emitcode ("clr", "c");
5293             }
5294           /* AOP_TYPE(right) == AOP_CRY */
5295         }
5296       else
5297         {
5298           symbol *lbl = newiTempLabel (NULL);
5299           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5300           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5301           emitcode ("cpl", "c");
5302           emitcode ("", "%05d$:", (lbl->key + 100));
5303         }
5304
5305       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5306       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5307
5308       aopOp (result, ic, TRUE, FALSE);
5309
5310       /* c = 1 if egal */
5311       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5312         {
5313           outBitC (result);
5314           goto release;
5315         }
5316       if (ifx)
5317         {
5318           genIfxJump (ifx, "c");
5319           goto release;
5320         }
5321       /* if the result is used in an arithmetic operation
5322          then put the result in place */
5323       outBitC (result);
5324     }
5325   else
5326     {
5327       gencjne (left, right, newiTempLabel (NULL));
5328
5329       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5330       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5331
5332       aopOp (result, ic, TRUE, FALSE);
5333
5334       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5335         {
5336           aopPut (AOP (result), "a", 0);
5337           goto release;
5338         }
5339       if (ifx)
5340         {
5341           genIfxJump (ifx, "a");
5342           goto release;
5343         }
5344       /* if the result is used in an arithmetic operation
5345          then put the result in place */
5346       if (AOP_TYPE (result) != AOP_CRY)
5347         outAcc (result);
5348       /* leave the result in acc */
5349     }
5350
5351 release:
5352   freeAsmop (result, NULL, ic, TRUE);
5353 }
5354
5355 /*-----------------------------------------------------------------*/
5356 /* ifxForOp - returns the icode containing the ifx for operand     */
5357 /*-----------------------------------------------------------------*/
5358 static iCode *
5359 ifxForOp (operand * op, iCode * ic)
5360 {
5361   /* if true symbol then needs to be assigned */
5362   if (IS_TRUE_SYMOP (op))
5363     return NULL;
5364
5365   /* if this has register type condition and
5366      the next instruction is ifx with the same operand
5367      and live to of the operand is upto the ifx only then */
5368   if (ic->next &&
5369       ic->next->op == IFX &&
5370       IC_COND (ic->next)->key == op->key &&
5371       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5372     return ic->next;
5373
5374   return NULL;
5375 }
5376 /*-----------------------------------------------------------------*/
5377 /* genAndOp - for && operation                                     */
5378 /*-----------------------------------------------------------------*/
5379 static void
5380 genAndOp (iCode * ic)
5381 {
5382   operand *left, *right, *result;
5383   symbol *tlbl;
5384
5385   D (emitcode (";", "genAndOp "););
5386
5387   /* note here that && operations that are in an
5388      if statement are taken away by backPatchLabels
5389      only those used in arthmetic operations remain */
5390   AOP_OP_2 (ic);
5391   AOP_SET_LOCALS (ic);
5392
5393   /* if both are bit variables */
5394   if (AOP_TYPE (left) == AOP_CRY &&
5395       AOP_TYPE (right) == AOP_CRY)
5396     {
5397       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5398       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5399       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5400       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5401   
5402       aopOp (result,ic,FALSE, FALSE);
5403       outBitC (result);
5404     }
5405   else
5406     {
5407       tlbl = newiTempLabel (NULL);
5408       toBoolean (left);
5409       emitcode ("jz", "%05d$", tlbl->key + 100);
5410       toBoolean (right);
5411       emitcode ("", "%05d$:", tlbl->key + 100);
5412       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5413       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5414   
5415       aopOp (result,ic,FALSE, FALSE);
5416       outBitAcc (result);
5417     }
5418     freeAsmop (result, NULL, ic, TRUE);
5419 }
5420
5421
5422 /*-----------------------------------------------------------------*/
5423 /* genOrOp - for || operation                                      */
5424 /*-----------------------------------------------------------------*/
5425 static void
5426 genOrOp (iCode * ic)
5427 {
5428   operand *left, *right, *result;
5429   symbol *tlbl;
5430
5431   D (emitcode (";", "genOrOp "););
5432
5433   /* note here that || operations that are in an
5434      if statement are taken away by backPatchLabels
5435      only those used in arthmetic operations remain */
5436   AOP_OP_2 (ic);
5437   AOP_SET_LOCALS (ic);
5438
5439   /* if both are bit variables */
5440   if (AOP_TYPE (left) == AOP_CRY &&
5441       AOP_TYPE (right) == AOP_CRY)
5442     {
5443       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5444       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5445       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5446       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5447   
5448       aopOp (result,ic,FALSE, FALSE);
5449       
5450       outBitC (result);
5451     }
5452   else
5453     {
5454       tlbl = newiTempLabel (NULL);
5455       toBoolean (left);
5456       emitcode ("jnz", "%05d$", tlbl->key + 100);
5457       toBoolean (right);
5458       emitcode ("", "%05d$:", tlbl->key + 100);
5459       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5460       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5461   
5462       aopOp (result,ic,FALSE, FALSE);
5463       
5464       outBitAcc (result);
5465     }
5466
5467   freeAsmop (result, NULL, ic, TRUE);
5468 }
5469
5470 /*-----------------------------------------------------------------*/
5471 /* isLiteralBit - test if lit == 2^n                               */
5472 /*-----------------------------------------------------------------*/
5473 static int
5474 isLiteralBit (unsigned long lit)
5475 {
5476   unsigned long pw[32] =
5477   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5478    0x100L, 0x200L, 0x400L, 0x800L,
5479    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5480    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5481    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5482    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5483    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5484   int idx;
5485
5486   for (idx = 0; idx < 32; idx++)
5487     if (lit == pw[idx])
5488       return idx + 1;
5489   return 0;
5490 }
5491
5492 /*-----------------------------------------------------------------*/
5493 /* continueIfTrue -                                                */
5494 /*-----------------------------------------------------------------*/
5495 static void
5496 continueIfTrue (iCode * ic)
5497 {
5498   if (IC_TRUE (ic))
5499     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5500   ic->generated = 1;
5501 }
5502
5503 /*-----------------------------------------------------------------*/
5504 /* jmpIfTrue -                                                     */
5505 /*-----------------------------------------------------------------*/
5506 static void
5507 jumpIfTrue (iCode * ic)
5508 {
5509   if (!IC_TRUE (ic))
5510     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5511   ic->generated = 1;
5512 }
5513
5514 /*-----------------------------------------------------------------*/
5515 /* jmpTrueOrFalse -                                                */
5516 /*-----------------------------------------------------------------*/
5517 static void
5518 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5519 {
5520   // ugly but optimized by peephole
5521   if (IC_TRUE (ic))
5522     {
5523       symbol *nlbl = newiTempLabel (NULL);
5524       emitcode ("sjmp", "%05d$", nlbl->key + 100);
5525       emitcode ("", "%05d$:", tlbl->key + 100);
5526       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5527       emitcode ("", "%05d$:", nlbl->key + 100);
5528     }
5529   else
5530     {
5531       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5532       emitcode ("", "%05d$:", tlbl->key + 100);
5533     }
5534   ic->generated = 1;
5535 }
5536
5537 // Generate code to perform a bit-wise logic operation
5538 // on two operands in far space (assumed to already have been 
5539 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5540 // in far space. This requires pushing the result on the stack
5541 // then popping it into the result.
5542 static void
5543 genFarFarLogicOp(iCode *ic, char *logicOp)
5544 {
5545       int size, resultSize, compSize;
5546       int offset = 0;
5547       
5548       TR_AP("#5");
5549       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5550       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
5551                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5552       
5553       _startLazyDPSEvaluation();
5554       for (size = compSize; (size--); offset++)
5555       {
5556           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5557           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5558           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5559           
5560           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5561           emitcode ("push", "acc");
5562       }
5563       _endLazyDPSEvaluation();
5564      
5565       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5566       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5567       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5568      
5569       resultSize = AOP_SIZE(IC_RESULT(ic));
5570
5571       ADJUST_PUSHED_RESULT(compSize, resultSize);
5572
5573       _startLazyDPSEvaluation();
5574       while (compSize--)
5575       {
5576           emitcode ("pop", "acc");
5577           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5578       }
5579       _endLazyDPSEvaluation();
5580       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5581 }
5582
5583
5584 /*-----------------------------------------------------------------*/
5585 /* genAnd  - code for and                                          */
5586 /*-----------------------------------------------------------------*/
5587 static void
5588 genAnd (iCode * ic, iCode * ifx)
5589 {
5590   operand *left, *right, *result;
5591   int size, offset = 0;
5592   unsigned long lit = 0L;
5593   int bytelit = 0;
5594   char buffer[10];
5595   bool pushResult;
5596
5597   D (emitcode (";", "genAnd "););
5598
5599   AOP_OP_3_NOFATAL (ic, pushResult);
5600   AOP_SET_LOCALS (ic);
5601
5602   if (pushResult)
5603   {
5604       genFarFarLogicOp(ic, "anl");
5605       return;
5606   }  
5607
5608 #ifdef DEBUG_TYPE
5609   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5610             AOP_TYPE (result),
5611             AOP_TYPE (left), AOP_TYPE (right));
5612   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5613             AOP_SIZE (result),
5614             AOP_SIZE (left), AOP_SIZE (right));
5615 #endif
5616
5617   /* if left is a literal & right is not then exchange them */
5618   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5619 #ifdef LOGIC_OPS_BROKEN      
5620     ||  AOP_NEEDSACC (left)
5621 #endif
5622     )
5623     {
5624       operand *tmp = right;
5625       right = left;
5626       left = tmp;
5627     }
5628
5629   /* if result = right then exchange them */
5630   if (sameRegs (AOP (result), AOP (right)))
5631     {
5632       operand *tmp = right;
5633       right = left;
5634       left = tmp;
5635     }
5636
5637   /* if right is bit then exchange them */
5638   if (AOP_TYPE (right) == AOP_CRY &&
5639       AOP_TYPE (left) != AOP_CRY)
5640     {
5641       operand *tmp = right;
5642       right = left;
5643       left = tmp;
5644     }
5645   if (AOP_TYPE (right) == AOP_LIT)
5646     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5647
5648   size = AOP_SIZE (result);
5649
5650   // if(bit & yy)
5651   // result = bit & yy;
5652   if (AOP_TYPE (left) == AOP_CRY)
5653     {
5654       // c = bit & literal;
5655       if (AOP_TYPE (right) == AOP_LIT)
5656         {
5657           if (lit & 1)
5658             {
5659               if (size && sameRegs (AOP (result), AOP (left)))
5660                 // no change
5661                 goto release;
5662               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5663             }
5664           else
5665             {
5666               // bit(result) = 0;
5667               if (size && (AOP_TYPE (result) == AOP_CRY))
5668                 {
5669                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5670                   goto release;
5671                 }
5672               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5673                 {
5674                   jumpIfTrue (ifx);
5675                   goto release;
5676                 }
5677               emitcode ("clr", "c");
5678             }
5679         }
5680       else
5681         {
5682           if (AOP_TYPE (right) == AOP_CRY)
5683             {
5684               // c = bit & bit;
5685               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5686               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5687             }
5688           else
5689             {
5690               // c = bit & val;
5691               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5692               // c = lsb
5693               emitcode ("rrc", "a");
5694               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5695             }
5696         }
5697       // bit = c
5698       // val = c
5699       if (size)
5700         outBitC (result);
5701       // if(bit & ...)
5702       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5703         genIfxJump (ifx, "c");
5704       goto release;
5705     }
5706
5707   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5708   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5709   if ((AOP_TYPE (right) == AOP_LIT) &&
5710       (AOP_TYPE (result) == AOP_CRY) &&
5711       (AOP_TYPE (left) != AOP_CRY))
5712     {
5713       int posbit = isLiteralBit (lit);
5714       /* left &  2^n */
5715       if (posbit)
5716         {
5717           posbit--;
5718           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5719           // bit = left & 2^n
5720           if (size)
5721             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5722           // if(left &  2^n)
5723           else
5724             {
5725               if (ifx)
5726                 {
5727                   sprintf (buffer, "acc.%d", posbit & 0x07);
5728                   genIfxJump (ifx, buffer);
5729                 }
5730               goto release;
5731             }
5732         }
5733       else
5734         {
5735           symbol *tlbl = newiTempLabel (NULL);
5736           int sizel = AOP_SIZE (left);
5737           if (size)
5738             emitcode ("setb", "c");
5739           while (sizel--)
5740             {
5741               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5742                 {
5743                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5744                   // byte ==  2^n ?
5745                   if ((posbit = isLiteralBit (bytelit)) != 0)
5746                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5747                   else
5748                     {
5749                       if (bytelit != 0x0FFL)
5750                         emitcode ("anl", "a,%s",
5751                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5752                       emitcode ("jnz", "%05d$", tlbl->key + 100);
5753                     }
5754                 }
5755               offset++;
5756             }
5757           // bit = left & literal
5758           if (size)
5759             {
5760               emitcode ("clr", "c");
5761               emitcode ("", "%05d$:", tlbl->key + 100);
5762             }
5763           // if(left & literal)
5764           else
5765             {
5766               if (ifx)
5767                 jmpTrueOrFalse (ifx, tlbl);
5768               goto release;
5769             }
5770         }
5771       outBitC (result);
5772       goto release;
5773     }
5774
5775   /* if left is same as result */
5776   if (sameRegs (AOP (result), AOP (left)))
5777     {
5778       for (; size--; offset++)
5779         {
5780           if (AOP_TYPE (right) == AOP_LIT)
5781             {
5782               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5783                 continue;
5784               else if (bytelit == 0)
5785                 aopPut (AOP (result), zero, offset);
5786               else if (IS_AOP_PREG (result))
5787                 {
5788                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5789                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5790                   aopPut (AOP (result), "a", offset);
5791                 }
5792               else
5793                 emitcode ("anl", "%s,%s",
5794                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5795                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5796             }
5797           else
5798             {
5799               if (AOP_TYPE (left) == AOP_ACC)
5800                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5801               else
5802                 {
5803                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5804                   if (IS_AOP_PREG (result))
5805                     {
5806                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5807                       aopPut (AOP (result), "a", offset);
5808
5809                     }
5810                   else
5811                     emitcode ("anl", "%s,a",
5812                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5813                 }
5814             }
5815         }
5816     }
5817   else
5818     {
5819       // left & result in different registers
5820       if (AOP_TYPE (result) == AOP_CRY)
5821         {
5822           // result = bit
5823           // if(size), result in bit
5824           // if(!size && ifx), conditional oper: if(left & right)
5825           symbol *tlbl = newiTempLabel (NULL);
5826           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5827           if (size)
5828             emitcode ("setb", "c");
5829           while (sizer--)
5830             {
5831               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5832                 emitcode ("anl", "a,%s",
5833                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5834               } else {
5835                 if (AOP_TYPE(left)==AOP_ACC) {
5836                   emitcode("mov", "b,a");
5837                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5838                   emitcode("anl", "a,b");
5839                 }else {
5840                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5841                   emitcode ("anl", "a,%s",
5842                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5843                 }
5844               }
5845               emitcode ("jnz", "%05d$", tlbl->key + 100);
5846               offset++;
5847             }
5848           if (size)
5849             {
5850               CLRC;
5851               emitcode ("", "%05d$:", tlbl->key + 100);
5852               outBitC (result);
5853             }
5854           else if (ifx)
5855             jmpTrueOrFalse (ifx, tlbl);
5856         }
5857       else
5858         {
5859           for (; (size--); offset++)
5860             {
5861               // normal case
5862               // result = left & right
5863               if (AOP_TYPE (right) == AOP_LIT)
5864                 {
5865                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5866                     {
5867                       aopPut (AOP (result),
5868                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5869                               offset);
5870                       continue;
5871                     }
5872                   else if (bytelit == 0)
5873                     {
5874                       aopPut (AOP (result), zero, offset);
5875                       continue;
5876                     }
5877                   D (emitcode (";", "better literal AND."););
5878                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5879                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5880                                                     FALSE, FALSE, FALSE));
5881
5882                 }
5883               else
5884                 {
5885                   // faster than result <- left, anl result,right
5886                   // and better if result is SFR
5887                   if (AOP_TYPE (left) == AOP_ACC)
5888                     {
5889                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5890                                                        FALSE, FALSE, FALSE));
5891                     }
5892                   else
5893                     {
5894                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
5895                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
5896                       {
5897                           emitcode("mov", "b,a");
5898                           rOp = "b";
5899                       }
5900                         
5901                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5902                       emitcode ("anl", "a,%s", rOp);
5903                     }                   
5904                 }
5905               aopPut (AOP (result), "a", offset);
5906             }
5907         }
5908     }
5909
5910 release:
5911   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5912   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5913   freeAsmop (result, NULL, ic, TRUE);
5914 }
5915
5916
5917 /*-----------------------------------------------------------------*/
5918 /* genOr  - code for or                                            */
5919 /*-----------------------------------------------------------------*/
5920 static void
5921 genOr (iCode * ic, iCode * ifx)
5922 {
5923   operand *left, *right, *result;
5924   int size, offset = 0;
5925   unsigned long lit = 0L;
5926   bool     pushResult;
5927
5928   D (emitcode (";", "genOr "););
5929
5930   AOP_OP_3_NOFATAL (ic, pushResult);
5931   AOP_SET_LOCALS (ic);
5932
5933   if (pushResult)
5934   {
5935       genFarFarLogicOp(ic, "orl");
5936       return;
5937   }
5938
5939
5940 #ifdef DEBUG_TYPE
5941   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5942             AOP_TYPE (result),
5943             AOP_TYPE (left), AOP_TYPE (right));
5944   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5945             AOP_SIZE (result),
5946             AOP_SIZE (left), AOP_SIZE (right));
5947 #endif
5948
5949   /* if left is a literal & right is not then exchange them */
5950   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5951 #ifdef LOGIC_OPS_BROKEN
5952    || AOP_NEEDSACC (left) // I think this is a net loss now.
5953 #endif      
5954       )
5955     {
5956       operand *tmp = right;
5957       right = left;
5958       left = tmp;
5959     }
5960
5961   /* if result = right then exchange them */
5962   if (sameRegs (AOP (result), AOP (right)))
5963     {
5964       operand *tmp = right;
5965       right = left;
5966       left = tmp;
5967     }
5968
5969   /* if right is bit then exchange them */
5970   if (AOP_TYPE (right) == AOP_CRY &&
5971       AOP_TYPE (left) != AOP_CRY)
5972     {
5973       operand *tmp = right;
5974       right = left;
5975       left = tmp;
5976     }
5977   if (AOP_TYPE (right) == AOP_LIT)
5978     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5979
5980   size = AOP_SIZE (result);
5981
5982   // if(bit | yy)
5983   // xx = bit | yy;
5984   if (AOP_TYPE (left) == AOP_CRY)
5985     {
5986       if (AOP_TYPE (right) == AOP_LIT)
5987         {
5988           // c = bit & literal;
5989           if (lit)
5990             {
5991               // lit != 0 => result = 1
5992               if (AOP_TYPE (result) == AOP_CRY)
5993                 {
5994                   if (size)
5995                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5996                   else if (ifx)
5997                     continueIfTrue (ifx);
5998                   goto release;
5999                 }
6000               emitcode ("setb", "c");
6001             }
6002           else
6003             {
6004               // lit == 0 => result = left
6005               if (size && sameRegs (AOP (result), AOP (left)))
6006                 goto release;
6007               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6008             }
6009         }
6010       else
6011         {
6012           if (AOP_TYPE (right) == AOP_CRY)
6013             {
6014               // c = bit | bit;
6015               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6016               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6017             }
6018           else
6019             {
6020               // c = bit | val;
6021               symbol *tlbl = newiTempLabel (NULL);
6022               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6023                 emitcode ("setb", "c");
6024               emitcode ("jb", "%s,%05d$",
6025                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6026               toBoolean (right);
6027               emitcode ("jnz", "%05d$", tlbl->key + 100);
6028               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6029                 {
6030                   jmpTrueOrFalse (ifx, tlbl);
6031                   goto release;
6032                 }
6033               else
6034                 {
6035                   CLRC;
6036                   emitcode ("", "%05d$:", tlbl->key + 100);
6037                 }
6038             }
6039         }
6040       // bit = c
6041       // val = c
6042       if (size)
6043         outBitC (result);
6044       // if(bit | ...)
6045       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6046         genIfxJump (ifx, "c");
6047       goto release;
6048     }
6049
6050   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6051   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6052   if ((AOP_TYPE (right) == AOP_LIT) &&
6053       (AOP_TYPE (result) == AOP_CRY) &&
6054       (AOP_TYPE (left) != AOP_CRY))
6055     {
6056       if (lit)
6057         {
6058           // result = 1
6059           if (size)
6060             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6061           else
6062             continueIfTrue (ifx);
6063           goto release;
6064         }
6065       else
6066         {
6067           // lit = 0, result = boolean(left)
6068           if (size)
6069             emitcode ("setb", "c");
6070           toBoolean (right);
6071           if (size)
6072             {
6073               symbol *tlbl = newiTempLabel (NULL);
6074               emitcode ("jnz", "%05d$", tlbl->key + 100);
6075               CLRC;
6076               emitcode ("", "%05d$:", tlbl->key + 100);
6077             }
6078           else
6079             {
6080               genIfxJump (ifx, "a");
6081               goto release;
6082             }
6083         }
6084       outBitC (result);
6085       goto release;
6086     }
6087
6088   /* if left is same as result */
6089   if (sameRegs (AOP (result), AOP (left)))
6090     {
6091       for (; size--; offset++)
6092         {
6093           if (AOP_TYPE (right) == AOP_LIT)
6094             {
6095               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6096                 {
6097                   continue;
6098                 }
6099               else
6100                 {
6101                   if (IS_AOP_PREG (left))
6102                     {
6103                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6104                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6105                       aopPut (AOP (result), "a", offset);
6106                     }
6107                   else
6108                     {
6109                       emitcode ("orl", "%s,%s",
6110                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6111                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6112                     }
6113                 }
6114             }
6115           else
6116             {
6117               if (AOP_TYPE (left) == AOP_ACC)
6118                 {
6119                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6120                 }
6121               else
6122                 {
6123                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6124                   if (IS_AOP_PREG (left))
6125                     {
6126                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6127                       aopPut (AOP (result), "a", offset);
6128                     }
6129                   else
6130                     {
6131                       emitcode ("orl", "%s,a",
6132                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6133                     }
6134                 }
6135             }
6136         }
6137     }
6138   else
6139     {
6140       // left & result in different registers
6141       if (AOP_TYPE (result) == AOP_CRY)
6142         {
6143           // result = bit
6144           // if(size), result in bit
6145           // if(!size && ifx), conditional oper: if(left | right)
6146           symbol *tlbl = newiTempLabel (NULL);
6147           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6148           if (size)
6149             emitcode ("setb", "c");
6150           while (sizer--)
6151             {
6152               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6153                 emitcode ("orl", "a,%s",
6154                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6155               } else {
6156                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6157                 emitcode ("orl", "a,%s",
6158                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6159               }
6160               emitcode ("jnz", "%05d$", tlbl->key + 100);
6161               offset++;
6162             }
6163           if (size)
6164             {
6165               CLRC;
6166               emitcode ("", "%05d$:", tlbl->key + 100);
6167               outBitC (result);
6168             }
6169           else if (ifx)
6170             jmpTrueOrFalse (ifx, tlbl);
6171         }
6172       else
6173         {
6174             _startLazyDPSEvaluation();
6175           for (; (size--); offset++)
6176             {
6177               // normal case
6178               // result = left & right
6179               if (AOP_TYPE (right) == AOP_LIT)
6180                 {
6181                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6182                     {
6183                       aopPut (AOP (result),
6184                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6185                               offset);
6186                       continue;
6187                     }
6188                   D (emitcode (";", "better literal OR."););
6189                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6190                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6191                                                     FALSE, FALSE, FALSE));
6192
6193                 }
6194               else
6195                 {
6196                   // faster than result <- left, anl result,right
6197                   // and better if result is SFR
6198                   if (AOP_TYPE (left) == AOP_ACC)
6199                     {
6200                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6201                                                        FALSE, FALSE, FALSE));
6202                     }
6203                   else
6204                     {
6205                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6206                         
6207                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6208                       {
6209                           emitcode("mov", "b,a");
6210                           rOp = "b";
6211                       }
6212                         
6213                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6214                       emitcode ("orl", "a,%s", rOp);
6215                     }
6216                 }
6217               aopPut (AOP (result), "a", offset);
6218             }
6219             _endLazyDPSEvaluation();
6220         }
6221     }
6222
6223 release:
6224   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6225   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6226   freeAsmop (result, NULL, ic, TRUE);
6227 }
6228
6229 /*-----------------------------------------------------------------*/
6230 /* genXor - code for xclusive or                                   */
6231 /*-----------------------------------------------------------------*/
6232 static void
6233 genXor (iCode * ic, iCode * ifx)
6234 {
6235   operand *left, *right, *result;
6236   int size, offset = 0;
6237   unsigned long lit = 0L;
6238   bool pushResult;
6239
6240   D (emitcode (";", "genXor "););
6241
6242   AOP_OP_3_NOFATAL (ic, pushResult);
6243   AOP_SET_LOCALS (ic);
6244
6245   if (pushResult)
6246   {
6247       genFarFarLogicOp(ic, "xrl");
6248       return;
6249   }  
6250
6251 #ifdef DEBUG_TYPE
6252   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6253             AOP_TYPE (result),
6254             AOP_TYPE (left), AOP_TYPE (right));
6255   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6256             AOP_SIZE (result),
6257             AOP_SIZE (left), AOP_SIZE (right));
6258 #endif
6259
6260   /* if left is a literal & right is not ||
6261      if left needs acc & right does not */
6262   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6263 #ifdef LOGIC_OPS_BROKEN      
6264       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6265 #endif
6266      )
6267     {
6268       operand *tmp = right;
6269       right = left;
6270       left = tmp;
6271     }
6272
6273   /* if result = right then exchange them */
6274   if (sameRegs (AOP (result), AOP (right)))
6275     {
6276       operand *tmp = right;
6277       right = left;
6278       left = tmp;
6279     }
6280
6281   /* if right is bit then exchange them */
6282   if (AOP_TYPE (right) == AOP_CRY &&
6283       AOP_TYPE (left) != AOP_CRY)
6284     {
6285       operand *tmp = right;
6286       right = left;
6287       left = tmp;
6288     }
6289   if (AOP_TYPE (right) == AOP_LIT)
6290     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6291
6292   size = AOP_SIZE (result);
6293
6294   // if(bit ^ yy)
6295   // xx = bit ^ yy;
6296   if (AOP_TYPE (left) == AOP_CRY)
6297     {
6298       if (AOP_TYPE (right) == AOP_LIT)
6299         {
6300           // c = bit & literal;
6301           if (lit >> 1)
6302             {
6303               // lit>>1  != 0 => result = 1
6304               if (AOP_TYPE (result) == AOP_CRY)
6305                 {
6306                   if (size)
6307                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6308                   else if (ifx)
6309                     continueIfTrue (ifx);
6310                   goto release;
6311                 }
6312               emitcode ("setb", "c");
6313             }
6314           else
6315             {
6316               // lit == (0 or 1)
6317               if (lit == 0)
6318                 {
6319                   // lit == 0, result = left
6320                   if (size && sameRegs (AOP (result), AOP (left)))
6321                     goto release;
6322                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6323                 }
6324               else
6325                 {
6326                   // lit == 1, result = not(left)
6327                   if (size && sameRegs (AOP (result), AOP (left)))
6328                     {
6329                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6330                       goto release;
6331                     }
6332                   else
6333                     {
6334                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6335                       emitcode ("cpl", "c");
6336                     }
6337                 }
6338             }
6339
6340         }
6341       else
6342         {
6343           // right != literal
6344           symbol *tlbl = newiTempLabel (NULL);
6345           if (AOP_TYPE (right) == AOP_CRY)
6346             {
6347               // c = bit ^ bit;
6348               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6349             }
6350           else
6351             {
6352               int sizer = AOP_SIZE (right);
6353               // c = bit ^ val
6354               // if val>>1 != 0, result = 1
6355               emitcode ("setb", "c");
6356               while (sizer)
6357                 {
6358                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6359                   if (sizer == 1)
6360                     // test the msb of the lsb
6361                     emitcode ("anl", "a,#0xfe");
6362                   emitcode ("jnz", "%05d$", tlbl->key + 100);
6363                   sizer--;
6364                 }
6365               // val = (0,1)
6366               emitcode ("rrc", "a");
6367             }
6368           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6369           emitcode ("cpl", "c");
6370           emitcode ("", "%05d$:", (tlbl->key + 100));
6371         }
6372       // bit = c
6373       // val = c
6374       if (size)
6375         outBitC (result);
6376       // if(bit | ...)
6377       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6378         genIfxJump (ifx, "c");
6379       goto release;
6380     }
6381
6382   if (sameRegs (AOP (result), AOP (left)))
6383     {
6384       /* if left is same as result */
6385       for (; size--; offset++)
6386         {
6387           if (AOP_TYPE (right) == AOP_LIT)
6388             {
6389               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6390                 continue;
6391               else if (IS_AOP_PREG (left))
6392                 {
6393                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6394                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6395                   aopPut (AOP (result), "a", offset);
6396                 }
6397               else
6398                 emitcode ("xrl", "%s,%s",
6399                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6400                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6401             }
6402           else
6403             {
6404               if (AOP_TYPE (left) == AOP_ACC)
6405                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6406               else
6407                 {
6408                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6409                   if (IS_AOP_PREG (left))
6410                     {
6411                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6412                       aopPut (AOP (result), "a", offset);
6413                     }
6414                   else
6415                     emitcode ("xrl", "%s,a",
6416                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6417                 }
6418             }
6419         }
6420     }
6421   else
6422     {
6423       // left & result in different registers
6424       if (AOP_TYPE (result) == AOP_CRY)
6425         {
6426           // result = bit
6427           // if(size), result in bit
6428           // if(!size && ifx), conditional oper: if(left ^ right)
6429           symbol *tlbl = newiTempLabel (NULL);
6430           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6431           if (size)
6432             emitcode ("setb", "c");
6433           while (sizer--)
6434             {
6435               if ((AOP_TYPE (right) == AOP_LIT) &&
6436                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6437                 {
6438                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6439                 }
6440               else
6441                 {
6442                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6443                     emitcode ("xrl", "a,%s",
6444                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6445                   } else {
6446                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6447                     emitcode ("xrl", "a,%s",
6448                               aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6449                   }
6450                 }
6451               emitcode ("jnz", "%05d$", tlbl->key + 100);
6452               offset++;
6453             }
6454           if (size)
6455             {
6456               CLRC;
6457               emitcode ("", "%05d$:", tlbl->key + 100);
6458               outBitC (result);
6459             }
6460           else if (ifx)
6461             jmpTrueOrFalse (ifx, tlbl);
6462         }
6463       else
6464         for (; (size--); offset++)
6465           {
6466             // normal case
6467             // result = left & right
6468             if (AOP_TYPE (right) == AOP_LIT)
6469               {
6470                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6471                   {
6472                     aopPut (AOP (result),
6473                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6474                             offset);
6475                     continue;
6476                   }
6477                 D (emitcode (";", "better literal XOR.");
6478                   );
6479                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6480                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6481                                                   FALSE, FALSE, FALSE));
6482               }
6483             else
6484               {
6485                 // faster than result <- left, anl result,right
6486                 // and better if result is SFR
6487                 if (AOP_TYPE (left) == AOP_ACC)
6488                   {
6489                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6490                                                      FALSE, FALSE, FALSE));
6491                   }
6492                 else
6493                   {
6494                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6495                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6496                       {
6497                           emitcode("mov", "b,a");
6498                           rOp = "b";
6499                       }
6500                         
6501                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6502                       emitcode ("xrl", "a,%s", rOp);
6503                   }
6504               }
6505             aopPut (AOP (result), "a", offset);
6506           }
6507     }
6508
6509 release:
6510   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6511   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6512   freeAsmop (result, NULL, ic, TRUE);
6513 }
6514
6515 /*-----------------------------------------------------------------*/
6516 /* genInline - write the inline code out                           */
6517 /*-----------------------------------------------------------------*/
6518 static void
6519 genInline (iCode * ic)
6520 {
6521   char *buffer, *bp, *bp1;
6522
6523   D (emitcode (";", "genInline ");
6524     );
6525
6526   _G.inLine += (!options.asmpeep);
6527
6528   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6529   strcpy (buffer, IC_INLINE (ic));
6530
6531   /* emit each line as a code */
6532   while (*bp)
6533     {
6534       if (*bp == '\n')
6535         {
6536           *bp++ = '\0';
6537           emitcode (bp1, "");
6538           bp1 = bp;
6539         }
6540       else
6541         {
6542           if (*bp == ':')
6543             {
6544               bp++;
6545               *bp = '\0';
6546               bp++;
6547               emitcode (bp1, "");
6548               bp1 = bp;
6549             }
6550           else
6551             bp++;
6552         }
6553     }
6554   if (bp1 != bp)
6555     emitcode (bp1, "");
6556   /*     emitcode("",buffer); */
6557   _G.inLine -= (!options.asmpeep);
6558 }
6559
6560 /*-----------------------------------------------------------------*/
6561 /* genRRC - rotate right with carry                                */
6562 /*-----------------------------------------------------------------*/
6563 static void
6564 genRRC (iCode * ic)
6565 {
6566   operand *left, *result;
6567   int size, offset = 0;
6568   char *l;
6569
6570   D (emitcode (";", "genRRC ");
6571     );
6572
6573   /* rotate right with carry */
6574   left = IC_LEFT (ic);
6575   result = IC_RESULT (ic);
6576   aopOp (left, ic, FALSE, FALSE);
6577   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6578
6579   /* move it to the result */
6580   size = AOP_SIZE (result);
6581   offset = size - 1;
6582   CLRC;
6583
6584   _startLazyDPSEvaluation ();
6585   while (size--)
6586     {
6587       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6588       MOVA (l);
6589       emitcode ("rrc", "a");
6590       if (AOP_SIZE (result) > 1)
6591         aopPut (AOP (result), "a", offset--);
6592     }
6593   _endLazyDPSEvaluation ();
6594
6595   /* now we need to put the carry into the
6596      highest order byte of the result */
6597   if (AOP_SIZE (result) > 1)
6598     {
6599       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6600       MOVA (l);
6601     }
6602   emitcode ("mov", "acc.7,c");
6603   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6604   freeAsmop (left, NULL, ic, TRUE);
6605   freeAsmop (result, NULL, ic, TRUE);
6606 }
6607
6608 /*-----------------------------------------------------------------*/
6609 /* genRLC - generate code for rotate left with carry               */
6610 /*-----------------------------------------------------------------*/
6611 static void
6612 genRLC (iCode * ic)
6613 {
6614   operand *left, *result;
6615   int size, offset = 0;
6616   char *l;
6617
6618   D (emitcode (";", "genRLC ");
6619     );
6620
6621   /* rotate right with carry */
6622   left = IC_LEFT (ic);
6623   result = IC_RESULT (ic);
6624   aopOp (left, ic, FALSE, FALSE);
6625   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6626
6627   /* move it to the result */
6628   size = AOP_SIZE (result);
6629   offset = 0;
6630   if (size--)
6631     {
6632       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6633       MOVA (l);
6634       emitcode ("add", "a,acc");
6635       if (AOP_SIZE (result) > 1)
6636         {
6637           aopPut (AOP (result), "a", offset++);
6638         }
6639
6640       _startLazyDPSEvaluation ();
6641       while (size--)
6642         {
6643           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6644           MOVA (l);
6645           emitcode ("rlc", "a");
6646           if (AOP_SIZE (result) > 1)
6647             aopPut (AOP (result), "a", offset++);
6648         }
6649       _endLazyDPSEvaluation ();
6650     }
6651   /* now we need to put the carry into the
6652      highest order byte of the result */
6653   if (AOP_SIZE (result) > 1)
6654     {
6655       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6656       MOVA (l);
6657     }
6658   emitcode ("mov", "acc.0,c");
6659   aopPut (AOP (result), "a", 0);
6660   freeAsmop (left, NULL, ic, TRUE);
6661   freeAsmop (result, NULL, ic, TRUE);
6662 }
6663
6664 /*-----------------------------------------------------------------*/
6665 /* genGetHbit - generates code get highest order bit               */
6666 /*-----------------------------------------------------------------*/
6667 static void
6668 genGetHbit (iCode * ic)
6669 {
6670   operand *left, *result;
6671   left = IC_LEFT (ic);
6672   result = IC_RESULT (ic);
6673   aopOp (left, ic, FALSE, FALSE);
6674   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6675
6676   D (emitcode (";", "genGetHbit ");
6677     );
6678
6679   /* get the highest order byte into a */
6680   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6681   if (AOP_TYPE (result) == AOP_CRY)
6682     {
6683       emitcode ("rlc", "a");
6684       outBitC (result);
6685     }
6686   else
6687     {
6688       emitcode ("rl", "a");
6689       emitcode ("anl", "a,#0x01");
6690       outAcc (result);
6691     }
6692
6693
6694   freeAsmop (left, NULL, ic, TRUE);
6695   freeAsmop (result, NULL, ic, TRUE);
6696 }
6697
6698 /*-----------------------------------------------------------------*/
6699 /* AccRol - rotate left accumulator by known count                 */
6700 /*-----------------------------------------------------------------*/
6701 static void
6702 AccRol (int shCount)
6703 {
6704   shCount &= 0x0007;            // shCount : 0..7
6705
6706   switch (shCount)
6707     {
6708     case 0:
6709       break;
6710     case 1:
6711       emitcode ("rl", "a");
6712       break;
6713     case 2:
6714       emitcode ("rl", "a");
6715       emitcode ("rl", "a");
6716       break;
6717     case 3:
6718       emitcode ("swap", "a");
6719       emitcode ("rr", "a");
6720       break;
6721     case 4:
6722       emitcode ("swap", "a");
6723       break;
6724     case 5:
6725       emitcode ("swap", "a");
6726       emitcode ("rl", "a");
6727       break;
6728     case 6:
6729       emitcode ("rr", "a");
6730       emitcode ("rr", "a");
6731       break;
6732     case 7:
6733       emitcode ("rr", "a");
6734       break;
6735     }
6736 }
6737
6738 /*-----------------------------------------------------------------*/
6739 /* AccLsh - left shift accumulator by known count                  */
6740 /*-----------------------------------------------------------------*/
6741 static void
6742 AccLsh (int shCount)
6743 {
6744   if (shCount != 0)
6745     {
6746       if (shCount == 1)
6747         emitcode ("add", "a,acc");
6748       else if (shCount == 2)
6749         {
6750           emitcode ("add", "a,acc");
6751           emitcode ("add", "a,acc");
6752         }
6753       else
6754         {
6755           /* rotate left accumulator */
6756           AccRol (shCount);
6757           /* and kill the lower order bits */
6758           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6759         }
6760     }
6761 }
6762
6763 /*-----------------------------------------------------------------*/
6764 /* AccRsh - right shift accumulator by known count                 */
6765 /*-----------------------------------------------------------------*/
6766 static void
6767 AccRsh (int shCount)
6768 {
6769   if (shCount != 0)
6770     {
6771       if (shCount == 1)
6772         {
6773           CLRC;
6774           emitcode ("rrc", "a");
6775         }
6776       else
6777         {
6778           /* rotate right accumulator */
6779           AccRol (8 - shCount);
6780           /* and kill the higher order bits */
6781           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6782         }
6783     }
6784 }
6785
6786 #ifdef BETTER_LITERAL_SHIFT
6787 /*-----------------------------------------------------------------*/
6788 /* AccSRsh - signed right shift accumulator by known count                 */
6789 /*-----------------------------------------------------------------*/
6790 static void
6791 AccSRsh (int shCount)
6792 {
6793   symbol *tlbl;
6794   if (shCount != 0)
6795     {
6796       if (shCount == 1)
6797         {
6798           emitcode ("mov", "c,acc.7");
6799           emitcode ("rrc", "a");
6800         }
6801       else if (shCount == 2)
6802         {
6803           emitcode ("mov", "c,acc.7");
6804           emitcode ("rrc", "a");
6805           emitcode ("mov", "c,acc.7");
6806           emitcode ("rrc", "a");
6807         }
6808       else
6809         {
6810           tlbl = newiTempLabel (NULL);
6811           /* rotate right accumulator */
6812           AccRol (8 - shCount);
6813           /* and kill the higher order bits */
6814           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6815           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6816           emitcode ("orl", "a,#0x%02x",
6817                     (unsigned char) ~SRMask[shCount]);
6818           emitcode ("", "%05d$:", tlbl->key + 100);
6819         }
6820     }
6821 }
6822 #endif
6823
6824 #ifdef BETTER_LITERAL_SHIFT
6825 /*-----------------------------------------------------------------*/
6826 /* shiftR1Left2Result - shift right one byte from left to result   */
6827 /*-----------------------------------------------------------------*/
6828 static void
6829 shiftR1Left2Result (operand * left, int offl,
6830                     operand * result, int offr,
6831                     int shCount, int sign)
6832 {
6833   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6834   /* shift right accumulator */
6835   if (sign)
6836     AccSRsh (shCount);
6837   else
6838     AccRsh (shCount);
6839   aopPut (AOP (result), "a", offr);
6840 }
6841 #endif
6842
6843 #ifdef BETTER_LITERAL_SHIFT
6844 /*-----------------------------------------------------------------*/
6845 /* shiftL1Left2Result - shift left one byte from left to result    */
6846 /*-----------------------------------------------------------------*/
6847 static void
6848 shiftL1Left2Result (operand * left, int offl,
6849                     operand * result, int offr, int shCount)
6850 {
6851   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6852   /* shift left accumulator */
6853   AccLsh (shCount);
6854   aopPut (AOP (result), "a", offr);
6855 }
6856 #endif
6857
6858 #ifdef BETTER_LITERAL_SHIFT
6859 /*-----------------------------------------------------------------*/
6860 /* movLeft2Result - move byte from left to result                  */
6861 /*-----------------------------------------------------------------*/
6862 static void
6863 movLeft2Result (operand * left, int offl,
6864                 operand * result, int offr, int sign)
6865 {
6866   char *l;
6867   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6868   {
6869       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6870
6871       if (*l == '@' && (IS_AOP_PREG (result)))
6872       {
6873           emitcode ("mov", "a,%s", l);
6874           aopPut (AOP (result), "a", offr);
6875       }
6876       else
6877       {
6878           if (!sign)
6879           {
6880             aopPut (AOP (result), l, offr);
6881           }
6882           else
6883             {
6884               /* MSB sign in acc.7 ! */
6885               if (getDataSize (left) == offl + 1)
6886                 {
6887                   emitcode ("mov", "a,%s", l);
6888                   aopPut (AOP (result), "a", offr);
6889                 }
6890             }
6891       }
6892   }
6893 }
6894 #endif
6895
6896 #ifdef BETTER_LITERAL_SHIFT
6897 /*-----------------------------------------------------------------*/
6898 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6899 /*-----------------------------------------------------------------*/
6900 static void
6901 AccAXRrl1 (char *x)
6902 {
6903   emitcode ("rrc", "a");
6904   emitcode ("xch", "a,%s", x);
6905   emitcode ("rrc", "a");
6906   emitcode ("xch", "a,%s", x);
6907 }
6908 #endif
6909
6910 #ifdef BETTER_LITERAL_SHIFT
6911 //REMOVE ME!!!
6912 /*-----------------------------------------------------------------*/
6913 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
6914 /*-----------------------------------------------------------------*/
6915 static void
6916 AccAXLrl1 (char *x)
6917 {
6918   emitcode ("xch", "a,%s", x);
6919   emitcode ("rlc", "a");
6920   emitcode ("xch", "a,%s", x);
6921   emitcode ("rlc", "a");
6922 }
6923 #endif
6924
6925 #ifdef BETTER_LITERAL_SHIFT
6926 /*-----------------------------------------------------------------*/
6927 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
6928 /*-----------------------------------------------------------------*/
6929 static void
6930 AccAXLsh1 (char *x)
6931 {
6932   emitcode ("xch", "a,%s", x);
6933   emitcode ("add", "a,acc");
6934   emitcode ("xch", "a,%s", x);
6935   emitcode ("rlc", "a");
6936 }
6937 #endif
6938
6939 #ifdef BETTER_LITERAL_SHIFT
6940 /*-----------------------------------------------------------------*/
6941 /* AccAXLsh - left shift a:x by known count (0..7)                 */
6942 /*-----------------------------------------------------------------*/
6943 static void
6944 AccAXLsh (char *x, int shCount)
6945 {
6946   switch (shCount)
6947     {
6948     case 0:
6949       break;
6950     case 1:
6951       AccAXLsh1 (x);
6952       break;
6953     case 2:
6954       AccAXLsh1 (x);
6955       AccAXLsh1 (x);
6956       break;
6957     case 3:
6958     case 4:
6959     case 5:                     // AAAAABBB:CCCCCDDD
6960
6961       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
6962
6963       emitcode ("anl", "a,#0x%02x",
6964                 SLMask[shCount]);       // BBB00000:CCCCCDDD
6965
6966       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
6967
6968       AccRol (shCount);         // DDDCCCCC:BBB00000
6969
6970       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
6971
6972       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
6973
6974       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
6975
6976       emitcode ("anl", "a,#0x%02x",
6977                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
6978
6979       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
6980
6981       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
6982
6983       break;
6984     case 6:                     // AAAAAABB:CCCCCCDD
6985       emitcode ("anl", "a,#0x%02x",
6986                 SRMask[shCount]);       // 000000BB:CCCCCCDD
6987       emitcode ("mov", "c,acc.0");      // c = B
6988       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
6989 #if 0
6990       AccAXRrl1 (x);            // BCCCCCCD:D000000B
6991       AccAXRrl1 (x);            // BBCCCCCC:DD000000
6992 #else
6993       emitcode("rrc","a"); 
6994       emitcode("xch","a,%s", x); 
6995       emitcode("rrc","a"); 
6996       emitcode("mov","c,acc.0"); //<< get correct bit 
6997       emitcode("xch","a,%s", x); 
6998
6999       emitcode("rrc","a"); 
7000       emitcode("xch","a,%s", x); 
7001       emitcode("rrc","a"); 
7002       emitcode("xch","a,%s", x); 
7003 #endif
7004       break;
7005     case 7:                     // a:x <<= 7
7006
7007       emitcode ("anl", "a,#0x%02x",
7008                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7009
7010       emitcode ("mov", "c,acc.0");      // c = B
7011
7012       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7013
7014       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7015
7016       break;
7017     default:
7018       break;
7019     }
7020 }
7021 #endif
7022
7023 #ifdef BETTER_LITERAL_SHIFT
7024 //REMOVE ME!!!
7025 /*-----------------------------------------------------------------*/
7026 /* AccAXRsh - right shift a:x known count (0..7)                   */
7027 /*-----------------------------------------------------------------*/
7028 static void
7029 AccAXRsh (char *x, int shCount)
7030 {
7031   switch (shCount)
7032     {
7033     case 0:
7034       break;
7035     case 1:
7036       CLRC;
7037       AccAXRrl1 (x);            // 0->a:x
7038
7039       break;
7040     case 2:
7041       CLRC;
7042       AccAXRrl1 (x);            // 0->a:x
7043
7044       CLRC;
7045       AccAXRrl1 (x);            // 0->a:x
7046
7047       break;
7048     case 3:
7049     case 4:
7050     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7051
7052       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7053
7054       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7055
7056       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7057
7058       emitcode ("anl", "a,#0x%02x",
7059                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7060
7061       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7062
7063       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7064
7065       emitcode ("anl", "a,#0x%02x",
7066                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7067
7068       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7069
7070       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7071
7072       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7073
7074       break;
7075     case 6:                     // AABBBBBB:CCDDDDDD
7076
7077       emitcode ("mov", "c,acc.7");
7078       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7079
7080       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7081
7082       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7083
7084       emitcode ("anl", "a,#0x%02x",
7085                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7086
7087       break;
7088     case 7:                     // ABBBBBBB:CDDDDDDD
7089
7090       emitcode ("mov", "c,acc.7");      // c = A
7091
7092       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7093
7094       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7095
7096       emitcode ("anl", "a,#0x%02x",
7097                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7098
7099       break;
7100     default:
7101       break;
7102     }
7103 }
7104 #endif
7105
7106 #ifdef BETTER_LITERAL_SHIFT
7107 /*-----------------------------------------------------------------*/
7108 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7109 /*-----------------------------------------------------------------*/
7110 static void
7111 AccAXRshS (char *x, int shCount)
7112 {
7113   symbol *tlbl;
7114   switch (shCount)
7115     {
7116     case 0:
7117       break;
7118     case 1:
7119       emitcode ("mov", "c,acc.7");
7120       AccAXRrl1 (x);            // s->a:x
7121
7122       break;
7123     case 2:
7124       emitcode ("mov", "c,acc.7");
7125       AccAXRrl1 (x);            // s->a:x
7126
7127       emitcode ("mov", "c,acc.7");
7128       AccAXRrl1 (x);            // s->a:x
7129
7130       break;
7131     case 3:
7132     case 4:
7133     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7134
7135       tlbl = newiTempLabel (NULL);
7136       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7137
7138       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7139
7140       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7141
7142       emitcode ("anl", "a,#0x%02x",
7143                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7144
7145       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7146
7147       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7148
7149       emitcode ("anl", "a,#0x%02x",
7150                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7151
7152       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7153
7154       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7155
7156       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7157
7158       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7159       emitcode ("orl", "a,#0x%02x",
7160                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7161
7162       emitcode ("", "%05d$:", tlbl->key + 100);
7163       break;                    // SSSSAAAA:BBBCCCCC
7164
7165     case 6:                     // AABBBBBB:CCDDDDDD
7166
7167       tlbl = newiTempLabel (NULL);
7168       emitcode ("mov", "c,acc.7");
7169       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7170
7171       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7172
7173       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7174
7175       emitcode ("anl", "a,#0x%02x",
7176                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7177
7178       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7179       emitcode ("orl", "a,#0x%02x",
7180                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7181
7182       emitcode ("", "%05d$:", tlbl->key + 100);
7183       break;
7184     case 7:                     // ABBBBBBB:CDDDDDDD
7185
7186       tlbl = newiTempLabel (NULL);
7187       emitcode ("mov", "c,acc.7");      // c = A
7188
7189       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7190
7191       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7192
7193       emitcode ("anl", "a,#0x%02x",
7194                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7195
7196       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7197       emitcode ("orl", "a,#0x%02x",
7198                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7199
7200       emitcode ("", "%05d$:", tlbl->key + 100);
7201       break;
7202     default:
7203       break;
7204     }
7205 }
7206 #endif
7207
7208 #ifdef BETTER_LITERAL_SHIFT
7209 static void
7210 _loadLeftIntoAx(char    **lsb, 
7211                 operand *left, 
7212                 operand *result,
7213                 int     offl,
7214                 int     offr)
7215 {
7216   // Get the initial value from left into a pair of registers.
7217   // MSB must be in A, LSB can be any register.
7218   //
7219   // If the result is held in registers, it is an optimization
7220   // if the LSB can be held in the register which will hold the,
7221   // result LSB since this saves us from having to copy it into
7222   // the result following AccAXLsh.
7223   //
7224   // If the result is addressed indirectly, this is not a gain.
7225   if (AOP_NEEDSACC(result))
7226   {
7227        char *leftByte;
7228        
7229        _startLazyDPSEvaluation();
7230       if (AOP_TYPE(left) == AOP_DPTR2)
7231        {
7232            // Get MSB in A.
7233            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7234            // get LSB in DP2_RESULT_REG.
7235            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7236            assert(!strcmp(leftByte, DP2_RESULT_REG));
7237        }
7238        else
7239        {
7240            // get LSB into DP2_RESULT_REG
7241            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7242            if (strcmp(leftByte, DP2_RESULT_REG))
7243            {
7244                TR_AP("#7");
7245                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7246            }
7247            // And MSB in A.
7248            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7249            assert(strcmp(leftByte, DP2_RESULT_REG));
7250            MOVA(leftByte);
7251        }
7252        _endLazyDPSEvaluation();
7253        *lsb = DP2_RESULT_REG;
7254   }
7255   else
7256   {
7257       if (sameRegs (AOP (result), AOP (left)) &&
7258         ((offl + MSB16) == offr))
7259       {
7260           /* don't crash result[offr] */
7261           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7262           emitcode ("xch", "a,%s", 
7263                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7264       }
7265       else
7266       {
7267           movLeft2Result (left, offl, result, offr, 0);
7268           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7269       }
7270       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7271       assert(strcmp(*lsb,"a"));      
7272   }
7273 }
7274
7275 static void
7276 _storeAxResults(char    *lsb,
7277                 operand *result,
7278                 int     offr)
7279 {
7280   _startLazyDPSEvaluation();
7281   if (AOP_NEEDSACC(result))
7282   {
7283       /* We have to explicitly update the result LSB.
7284        */
7285       emitcode("xch","a,%s", lsb);
7286       aopPut(AOP(result), "a", offr);
7287       emitcode("mov","a,%s", lsb);
7288   }
7289   if (getDataSize (result) > 1)
7290   {
7291       aopPut (AOP (result), "a", offr + MSB16);
7292   }
7293   _endLazyDPSEvaluation();
7294 }
7295
7296 /*-----------------------------------------------------------------*/
7297 /* shiftL2Left2Result - shift left two bytes from left to result   */
7298 /*-----------------------------------------------------------------*/
7299 static void
7300 shiftL2Left2Result (operand * left, int offl,
7301                     operand * result, int offr, int shCount)
7302 {
7303   char *lsb;
7304
7305   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7306   
7307   AccAXLsh (lsb, shCount);
7308   
7309   _storeAxResults(lsb, result, offr);
7310 }
7311 #endif
7312
7313 #ifdef BETTER_LITERAL_SHIFT
7314 /*-----------------------------------------------------------------*/
7315 /* shiftR2Left2Result - shift right two bytes from left to result  */
7316 /*-----------------------------------------------------------------*/
7317 static void
7318 shiftR2Left2Result (operand * left, int offl,
7319                     operand * result, int offr,
7320                     int shCount, int sign)
7321 {
7322   char *lsb;
7323   
7324   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7325   
7326   /* a:x >> shCount (x = lsb(result)) */
7327   if (sign)
7328   {
7329      AccAXRshS(lsb, shCount);
7330   }
7331   else
7332   {
7333     AccAXRsh(lsb, shCount);
7334   }
7335   
7336   _storeAxResults(lsb, result, offr);
7337 }
7338 #endif
7339
7340 #if 0
7341 //REMOVE ME!!!
7342 /*-----------------------------------------------------------------*/
7343 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7344 /*-----------------------------------------------------------------*/
7345 static void
7346 shiftLLeftOrResult (operand * left, int offl,
7347                     operand * result, int offr, int shCount)
7348 {
7349   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7350   /* shift left accumulator */
7351   AccLsh (shCount);
7352   /* or with result */
7353   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7354   /* back to result */
7355   aopPut (AOP (result), "a", offr);
7356 }
7357 #endif
7358
7359 #if 0
7360 //REMOVE ME!!!
7361 /*-----------------------------------------------------------------*/
7362 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7363 /*-----------------------------------------------------------------*/
7364 static void
7365 shiftRLeftOrResult (operand * left, int offl,
7366                     operand * result, int offr, int shCount)
7367 {
7368   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7369   /* shift right accumulator */
7370   AccRsh (shCount);
7371   /* or with result */
7372   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7373   /* back to result */
7374   aopPut (AOP (result), "a", offr);
7375 }
7376 #endif
7377
7378 #ifdef BETTER_LITERAL_SHIFT
7379 /*-----------------------------------------------------------------*/
7380 /* genlshOne - left shift a one byte quantity by known count       */
7381 /*-----------------------------------------------------------------*/
7382 static void
7383 genlshOne (operand * result, operand * left, int shCount)
7384 {
7385   D (emitcode (";", "genlshOne "););
7386   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7387 }
7388 #endif
7389
7390 #ifdef BETTER_LITERAL_SHIFT
7391 /*-----------------------------------------------------------------*/
7392 /* genlshTwo - left shift two bytes by known amount != 0           */
7393 /*-----------------------------------------------------------------*/
7394 static void
7395 genlshTwo (operand * result, operand * left, int shCount)
7396 {
7397   int size;
7398
7399   D (emitcode (";", "genlshTwo "););
7400
7401   size = getDataSize (result);
7402
7403   /* if shCount >= 8 */
7404   if (shCount >= 8)
7405   {
7406       shCount -= 8;
7407
7408       _startLazyDPSEvaluation();
7409
7410       if (size > 1)
7411         {
7412           if (shCount)
7413           {
7414             _endLazyDPSEvaluation();
7415             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7416             aopPut (AOP (result), zero, LSB);       
7417           }
7418           else
7419           {
7420             movLeft2Result (left, LSB, result, MSB16, 0);
7421             aopPut (AOP (result), zero, LSB);
7422             _endLazyDPSEvaluation();
7423           }
7424         }
7425         else
7426         {
7427           aopPut (AOP (result), zero, LSB);
7428           _endLazyDPSEvaluation();
7429         }
7430   }
7431
7432   /*  1 <= shCount <= 7 */
7433   else
7434     {
7435       if (size == 1)
7436       {
7437         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7438       }
7439       else
7440       {
7441         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7442       }
7443     }
7444 }
7445 #endif
7446
7447 #if 0
7448 //REMOVE ME!!!
7449 /*-----------------------------------------------------------------*/
7450 /* shiftLLong - shift left one long from left to result            */
7451 /* offl = LSB or MSB16                                             */
7452 /*-----------------------------------------------------------------*/
7453 static void
7454 shiftLLong (operand * left, operand * result, int offr)
7455 {
7456   char *l;
7457   int size = AOP_SIZE (result);
7458
7459   if (size >= LSB + offr)
7460     {
7461       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7462       MOVA (l);
7463       emitcode ("add", "a,acc");
7464       if (sameRegs (AOP (left), AOP (result)) &&
7465           size >= MSB16 + offr && offr != LSB)
7466         emitcode ("xch", "a,%s",
7467                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7468       else
7469         aopPut (AOP (result), "a", LSB + offr);
7470     }
7471
7472   if (size >= MSB16 + offr)
7473     {
7474       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7475         {
7476           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7477           MOVA (l);
7478         }
7479       emitcode ("rlc", "a");
7480       if (sameRegs (AOP (left), AOP (result)) &&
7481           size >= MSB24 + offr && offr != LSB)
7482         emitcode ("xch", "a,%s",
7483                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7484       else
7485         aopPut (AOP (result), "a", MSB16 + offr);
7486     }
7487
7488   if (size >= MSB24 + offr)
7489     {
7490       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7491         {
7492           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7493           MOVA (l);
7494         }
7495       emitcode ("rlc", "a");
7496       if (sameRegs (AOP (left), AOP (result)) &&
7497           size >= MSB32 + offr && offr != LSB)
7498         emitcode ("xch", "a,%s",
7499                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7500       else
7501         aopPut (AOP (result), "a", MSB24 + offr);
7502     }
7503
7504   if (size > MSB32 + offr)
7505     {
7506       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7507         {
7508           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7509           MOVA (l);
7510         }
7511       emitcode ("rlc", "a");
7512       aopPut (AOP (result), "a", MSB32 + offr);
7513     }
7514   if (offr != LSB)
7515     aopPut (AOP (result), zero, LSB);
7516 }
7517 #endif
7518
7519 #if 0
7520 //REMOVE ME!!!
7521 /*-----------------------------------------------------------------*/
7522 /* genlshFour - shift four byte by a known amount != 0             */
7523 /*-----------------------------------------------------------------*/
7524 static void
7525 genlshFour (operand * result, operand * left, int shCount)
7526 {
7527   int size;
7528
7529   D (emitcode (";", "genlshFour ");
7530     );
7531
7532   size = AOP_SIZE (result);
7533
7534   /* if shifting more that 3 bytes */
7535   if (shCount >= 24)
7536     {
7537       shCount -= 24;
7538       if (shCount)
7539         /* lowest order of left goes to the highest
7540            order of the destination */
7541         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7542       else
7543         movLeft2Result (left, LSB, result, MSB32, 0);
7544       aopPut (AOP (result), zero, LSB);
7545       aopPut (AOP (result), zero, MSB16);
7546       aopPut (AOP (result), zero, MSB24);
7547       return;
7548     }
7549
7550   /* more than two bytes */
7551   else if (shCount >= 16)
7552     {
7553       /* lower order two bytes goes to higher order two bytes */
7554       shCount -= 16;
7555       /* if some more remaining */
7556       if (shCount)
7557         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7558       else
7559         {
7560           movLeft2Result (left, MSB16, result, MSB32, 0);
7561           movLeft2Result (left, LSB, result, MSB24, 0);
7562         }
7563       aopPut (AOP (result), zero, MSB16);
7564       aopPut (AOP (result), zero, LSB);
7565       return;
7566     }
7567
7568   /* if more than 1 byte */
7569   else if (shCount >= 8)
7570     {
7571       /* lower order three bytes goes to higher order  three bytes */
7572       shCount -= 8;
7573       if (size == 2)
7574         {
7575           if (shCount)
7576             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7577           else
7578             movLeft2Result (left, LSB, result, MSB16, 0);
7579         }
7580       else
7581         {                       /* size = 4 */
7582           if (shCount == 0)
7583             {
7584               movLeft2Result (left, MSB24, result, MSB32, 0);
7585               movLeft2Result (left, MSB16, result, MSB24, 0);
7586               movLeft2Result (left, LSB, result, MSB16, 0);
7587               aopPut (AOP (result), zero, LSB);
7588             }
7589           else if (shCount == 1)
7590             shiftLLong (left, result, MSB16);
7591           else
7592             {
7593               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7594               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7595               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7596               aopPut (AOP (result), zero, LSB);
7597             }
7598         }
7599     }
7600
7601   /* 1 <= shCount <= 7 */
7602   else if (shCount <= 2)
7603     {
7604       shiftLLong (left, result, LSB);
7605       if (shCount == 2)
7606         shiftLLong (result, result, LSB);
7607     }
7608   /* 3 <= shCount <= 7, optimize */
7609   else
7610     {
7611       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7612       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7613       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7614     }
7615 }
7616 #endif
7617
7618 #ifdef BETTER_LITERAL_SHIFT
7619 /*-----------------------------------------------------------------*/
7620 /* genLeftShiftLiteral - left shifting by known count              */
7621 /*-----------------------------------------------------------------*/
7622 static bool
7623 genLeftShiftLiteral (operand * left,
7624                      operand * right,
7625                      operand * result,
7626                      iCode * ic)
7627 {
7628   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7629   int size;
7630
7631   size = getSize (operandType (result));
7632
7633   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7634
7635   /* We only handle certain easy cases so far. */
7636   if ((shCount != 0)
7637    && (shCount < (size * 8))
7638    && (size != 1)
7639    && (size != 2))
7640   {
7641       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
7642       return FALSE;
7643   }
7644
7645   freeAsmop (right, NULL, ic, TRUE);
7646
7647   aopOp(left, ic, FALSE, FALSE);
7648   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7649
7650 #if 1 // debug spew
7651   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7652   {
7653         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7654         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7655         {
7656            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7657         }
7658   }
7659   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7660   {
7661         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7662         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7663         {
7664            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7665         }       
7666   }  
7667 #endif
7668   
7669 #if VIEW_SIZE
7670   emitcode ("; shift left ", "result %d, left %d", size,
7671             AOP_SIZE (left));
7672 #endif
7673
7674   /* I suppose that the left size >= result size */
7675   if (shCount == 0)
7676   {
7677         _startLazyDPSEvaluation();
7678         while (size--)
7679         {
7680           movLeft2Result (left, size, result, size, 0);
7681         }
7682         _endLazyDPSEvaluation();
7683   }
7684   else if (shCount >= (size * 8))
7685   {
7686     _startLazyDPSEvaluation();
7687     while (size--)
7688     {
7689       aopPut (AOP (result), zero, size);
7690     }
7691     _endLazyDPSEvaluation();
7692   }
7693   else
7694   {
7695       switch (size)
7696         {
7697         case 1:
7698           genlshOne (result, left, shCount);
7699           break;
7700
7701         case 2:
7702           genlshTwo (result, left, shCount);
7703           break;
7704 #if 0
7705         case 4:
7706           genlshFour (result, left, shCount);
7707           break;
7708 #endif
7709         default:
7710           fprintf(stderr, "*** ack! mystery literal shift!\n");   
7711           break;
7712         }
7713     }
7714   freeAsmop (left, NULL, ic, TRUE);
7715   freeAsmop (result, NULL, ic, TRUE);
7716   return TRUE;
7717 }
7718 #endif
7719
7720 /*-----------------------------------------------------------------*/
7721 /* genLeftShift - generates code for left shifting                 */
7722 /*-----------------------------------------------------------------*/
7723 static void
7724 genLeftShift (iCode * ic)
7725 {
7726   operand *left, *right, *result;
7727   int size, offset;
7728   char *l;
7729   symbol *tlbl, *tlbl1;
7730
7731   D (emitcode (";", "genLeftShift "););
7732
7733   right = IC_RIGHT (ic);
7734   left = IC_LEFT (ic);
7735   result = IC_RESULT (ic);
7736
7737   aopOp (right, ic, FALSE, FALSE);
7738
7739
7740 #ifdef BETTER_LITERAL_SHIFT
7741   /* if the shift count is known then do it
7742      as efficiently as possible */
7743   if (AOP_TYPE (right) == AOP_LIT)
7744     {
7745       if (genLeftShiftLiteral (left, right, result, ic))
7746       {
7747         return;
7748       }
7749     }
7750 #endif
7751
7752   /* shift count is unknown then we have to form
7753      a loop get the loop count in B : Note: we take
7754      only the lower order byte since shifting
7755      more that 32 bits make no sense anyway, ( the
7756      largest size of an object can be only 32 bits ) */
7757
7758   if (AOP_TYPE (right) == AOP_LIT)
7759   {
7760       /* Really should be handled by genLeftShiftLiteral,
7761        * but since I'm too lazy to fix that today, at least we can make
7762        * some small improvement.
7763        */
7764        emitcode("mov", "b,#0x%02x",
7765                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7766   }
7767   else
7768   {
7769         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7770         emitcode ("inc", "b");
7771   }
7772   freeAsmop (right, NULL, ic, TRUE);
7773   aopOp (left, ic, FALSE, FALSE);
7774   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7775
7776   /* now move the left to the result if they are not the
7777      same */
7778   if (!sameRegs (AOP (left), AOP (result)) &&
7779       AOP_SIZE (result) > 1)
7780     {
7781
7782       size = AOP_SIZE (result);
7783       offset = 0;
7784       _startLazyDPSEvaluation ();
7785       while (size--)
7786         {
7787           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7788           if (*l == '@' && (IS_AOP_PREG (result)))
7789             {
7790
7791               emitcode ("mov", "a,%s", l);
7792               aopPut (AOP (result), "a", offset);
7793             }
7794           else
7795             aopPut (AOP (result), l, offset);
7796           offset++;
7797         }
7798       _endLazyDPSEvaluation ();
7799     }
7800
7801   tlbl = newiTempLabel (NULL);
7802   size = AOP_SIZE (result);
7803   offset = 0;
7804   tlbl1 = newiTempLabel (NULL);
7805
7806   /* if it is only one byte then */
7807   if (size == 1)
7808     {
7809       symbol *tlbl1 = newiTempLabel (NULL);
7810
7811       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7812       MOVA (l);
7813       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7814       emitcode ("", "%05d$:", tlbl->key + 100);
7815       emitcode ("add", "a,acc");
7816       emitcode ("", "%05d$:", tlbl1->key + 100);
7817       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7818       aopPut (AOP (result), "a", 0);
7819       goto release;
7820     }
7821
7822   reAdjustPreg (AOP (result));
7823
7824   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7825   emitcode ("", "%05d$:", tlbl->key + 100);
7826   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7827   MOVA (l);
7828   emitcode ("add", "a,acc");
7829   aopPut (AOP (result), "a", offset++);
7830   _startLazyDPSEvaluation ();
7831   while (--size)
7832     {
7833       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7834       MOVA (l);
7835       emitcode ("rlc", "a");
7836       aopPut (AOP (result), "a", offset++);
7837     }
7838   _endLazyDPSEvaluation ();
7839   reAdjustPreg (AOP (result));
7840
7841   emitcode ("", "%05d$:", tlbl1->key + 100);
7842   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7843 release:
7844   freeAsmop (left, NULL, ic, TRUE);
7845   freeAsmop (result, NULL, ic, TRUE);
7846 }
7847
7848 #ifdef BETTER_LITERAL_SHIFT
7849 /*-----------------------------------------------------------------*/
7850 /* genrshOne - right shift a one byte quantity by known count      */
7851 /*-----------------------------------------------------------------*/
7852 static void
7853 genrshOne (operand * result, operand * left,
7854            int shCount, int sign)
7855 {
7856   D (emitcode (";", "genrshOne"););
7857   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7858 }
7859 #endif
7860
7861 #ifdef BETTER_LITERAL_SHIFT
7862 /*-----------------------------------------------------------------*/
7863 /* genrshTwo - right shift two bytes by known amount != 0          */
7864 /*-----------------------------------------------------------------*/
7865 static void
7866 genrshTwo (operand * result, operand * left,
7867            int shCount, int sign)
7868 {
7869   D (emitcode (";", "genrshTwo"););
7870
7871   /* if shCount >= 8 */
7872   if (shCount >= 8)
7873     {
7874       shCount -= 8;
7875       _startLazyDPSEvaluation();
7876       if (shCount)
7877       {
7878         shiftR1Left2Result (left, MSB16, result, LSB,
7879                             shCount, sign);
7880       }                     
7881       else
7882       {
7883         movLeft2Result (left, MSB16, result, LSB, sign);
7884       }
7885       addSign (result, MSB16, sign);
7886       _endLazyDPSEvaluation();
7887     }
7888
7889   /*  1 <= shCount <= 7 */
7890   else
7891   {
7892     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7893   }
7894 }
7895 #endif
7896
7897 #if 0
7898 //REMOVE ME!!!
7899 /*-----------------------------------------------------------------*/
7900 /* shiftRLong - shift right one long from left to result           */
7901 /* offl = LSB or MSB16                                             */
7902 /*-----------------------------------------------------------------*/
7903 static void
7904 shiftRLong (operand * left, int offl,
7905             operand * result, int sign)
7906 {
7907   int isSameRegs=sameRegs(AOP(left),AOP(result));
7908
7909   if (isSameRegs && offl>1) {
7910     // we are in big trouble, but this shouldn't happen
7911     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7912   }
7913
7914   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7915   
7916   if (offl==MSB16) {
7917     // shift is > 8
7918     if (sign) {
7919       emitcode ("rlc", "a");
7920       emitcode ("subb", "a,acc");
7921       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7922     } else {
7923       aopPut (AOP(result), zero, MSB32);
7924     }
7925   }
7926
7927   if (!sign) {
7928     emitcode ("clr", "c");
7929   } else {
7930     emitcode ("mov", "c,acc.7");
7931   }
7932
7933   emitcode ("rrc", "a");
7934
7935   if (isSameRegs && offl==MSB16) {
7936     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7937   } else {
7938     aopPut (AOP (result), "a", MSB32);
7939     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7940   }
7941
7942   emitcode ("rrc", "a");
7943   if (isSameRegs && offl==1) {
7944     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7945   } else {
7946     aopPut (AOP (result), "a", MSB24);
7947     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7948   }
7949   emitcode ("rrc", "a");
7950   aopPut (AOP (result), "a", MSB16 - offl);
7951
7952   if (offl == LSB)
7953     {
7954       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7955       emitcode ("rrc", "a");
7956       aopPut (AOP (result), "a", LSB);
7957     }
7958 }
7959 #endif
7960
7961 #if 0
7962 //REMOVE ME!!!
7963 /*-----------------------------------------------------------------*/
7964 /* genrshFour - shift four byte by a known amount != 0             */
7965 /*-----------------------------------------------------------------*/
7966 static void
7967 genrshFour (operand * result, operand * left,
7968             int shCount, int sign)
7969 {
7970   D (emitcode (";", "genrshFour");
7971     );
7972
7973   /* if shifting more that 3 bytes */
7974   if (shCount >= 24)
7975     {
7976       shCount -= 24;
7977       if (shCount)
7978         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7979       else
7980         movLeft2Result (left, MSB32, result, LSB, sign);
7981       addSign (result, MSB16, sign);
7982     }
7983   else if (shCount >= 16)
7984     {
7985       shCount -= 16;
7986       if (shCount)
7987         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7988       else
7989         {
7990           movLeft2Result (left, MSB24, result, LSB, 0);
7991           movLeft2Result (left, MSB32, result, MSB16, sign);
7992         }
7993       addSign (result, MSB24, sign);
7994     }
7995   else if (shCount >= 8)
7996     {
7997       shCount -= 8;
7998       if (shCount == 1)
7999         shiftRLong (left, MSB16, result, sign);
8000       else if (shCount == 0)
8001         {
8002           movLeft2Result (left, MSB16, result, LSB, 0);
8003           movLeft2Result (left, MSB24, result, MSB16, 0);
8004           movLeft2Result (left, MSB32, result, MSB24, sign);
8005           addSign (result, MSB32, sign);
8006         }
8007       else
8008         {
8009           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8010           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8011           /* the last shift is signed */
8012           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8013           addSign (result, MSB32, sign);
8014         }
8015     }
8016   else
8017     {                           /* 1 <= shCount <= 7 */
8018       if (shCount <= 2)
8019         {
8020           shiftRLong (left, LSB, result, sign);
8021           if (shCount == 2)
8022             shiftRLong (result, LSB, result, sign);
8023         }
8024       else
8025         {
8026           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8027           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8028           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8029         }
8030     }
8031 }
8032 #endif
8033
8034 #ifdef BETTER_LITERAL_SHIFT
8035 /*-----------------------------------------------------------------*/
8036 /* genRightShiftLiteral - right shifting by known count            */
8037 /*-----------------------------------------------------------------*/
8038 static bool
8039 genRightShiftLiteral (operand * left,
8040                       operand * right,
8041                       operand * result,
8042                       iCode * ic,
8043                       int sign)
8044 {
8045   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8046   int size;
8047
8048   size = getSize (operandType (result));
8049
8050   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8051
8052   /* We only handle certain easy cases so far. */
8053   if ((shCount != 0)
8054    && (shCount < (size * 8))
8055    && (size != 1)
8056    && (size != 2))
8057   {
8058       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8059       return FALSE;
8060   }
8061
8062   freeAsmop (right, NULL, ic, TRUE);
8063
8064   aopOp (left, ic, FALSE, FALSE);
8065   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8066
8067 #if VIEW_SIZE
8068   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8069             AOP_SIZE (left));
8070 #endif
8071
8072   /* test the LEFT size !!! */
8073
8074   /* I suppose that the left size >= result size */
8075   if (shCount == 0)
8076   {
8077       size = getDataSize (result);
8078       _startLazyDPSEvaluation();
8079       while (size--)
8080       {
8081         movLeft2Result (left, size, result, size, 0);
8082       }
8083       _endLazyDPSEvaluation();
8084   }
8085   else if (shCount >= (size * 8))
8086     {
8087       if (sign)
8088       {
8089         /* get sign in acc.7 */
8090         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8091       }
8092       addSign (result, LSB, sign);
8093     }
8094   else
8095     {
8096       switch (size)
8097         {
8098         case 1:
8099           genrshOne (result, left, shCount, sign);
8100           break;
8101
8102         case 2:
8103           genrshTwo (result, left, shCount, sign);
8104           break;
8105 #if 0
8106         case 4:
8107           genrshFour (result, left, shCount, sign);
8108           break;
8109 #endif    
8110         default:
8111           break;
8112         }
8113
8114       freeAsmop (left, NULL, ic, TRUE);
8115       freeAsmop (result, NULL, ic, TRUE);
8116     }
8117     return TRUE;
8118 }
8119 #endif
8120
8121 /*-----------------------------------------------------------------*/
8122 /* genSignedRightShift - right shift of signed number              */
8123 /*-----------------------------------------------------------------*/
8124 static void
8125 genSignedRightShift (iCode * ic)
8126 {
8127   operand *right, *left, *result;
8128   int size, offset;
8129   char *l;
8130   symbol *tlbl, *tlbl1;
8131
8132   D (emitcode (";", "genSignedRightShift "););
8133
8134   /* we do it the hard way put the shift count in b
8135      and loop thru preserving the sign */
8136
8137   right = IC_RIGHT (ic);
8138   left = IC_LEFT (ic);
8139   result = IC_RESULT (ic);
8140
8141   aopOp (right, ic, FALSE, FALSE);
8142
8143 #ifdef BETTER_LITERAL_SHIFT
8144   if (AOP_TYPE (right) == AOP_LIT)
8145     {
8146       if (genRightShiftLiteral (left, right, result, ic, 1))
8147       {
8148         return;
8149       }
8150     }
8151 #endif
8152   /* shift count is unknown then we have to form
8153      a loop get the loop count in B : Note: we take
8154      only the lower order byte since shifting
8155      more that 32 bits make no sense anyway, ( the
8156      largest size of an object can be only 32 bits ) */
8157
8158   if (AOP_TYPE (right) == AOP_LIT)
8159   {
8160       /* Really should be handled by genRightShiftLiteral,
8161        * but since I'm too lazy to fix that today, at least we can make
8162        * some small improvement.
8163        */
8164        emitcode("mov", "b,#0x%02x",
8165                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8166   }
8167   else
8168   {
8169         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8170         emitcode ("inc", "b");
8171   }
8172   freeAsmop (right, NULL, ic, TRUE);
8173   aopOp (left, ic, FALSE, FALSE);
8174   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8175
8176   /* now move the left to the result if they are not the
8177      same */
8178   if (!sameRegs (AOP (left), AOP (result)) &&
8179       AOP_SIZE (result) > 1)
8180     {
8181
8182       size = AOP_SIZE (result);
8183       offset = 0;
8184       _startLazyDPSEvaluation ();
8185       while (size--)
8186         {
8187           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8188           if (*l == '@' && IS_AOP_PREG (result))
8189             {
8190
8191               emitcode ("mov", "a,%s", l);
8192               aopPut (AOP (result), "a", offset);
8193             }
8194           else
8195             aopPut (AOP (result), l, offset);
8196           offset++;
8197         }
8198       _endLazyDPSEvaluation ();
8199     }
8200
8201   /* mov the highest order bit to OVR */
8202   tlbl = newiTempLabel (NULL);
8203   tlbl1 = newiTempLabel (NULL);
8204
8205   size = AOP_SIZE (result);
8206   offset = size - 1;
8207   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8208   emitcode ("rlc", "a");
8209   emitcode ("mov", "ov,c");
8210   /* if it is only one byte then */
8211   if (size == 1)
8212     {
8213       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8214       MOVA (l);
8215       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8216       emitcode ("", "%05d$:", tlbl->key + 100);
8217       emitcode ("mov", "c,ov");
8218       emitcode ("rrc", "a");
8219       emitcode ("", "%05d$:", tlbl1->key + 100);
8220       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8221       aopPut (AOP (result), "a", 0);
8222       goto release;
8223     }
8224
8225   reAdjustPreg (AOP (result));
8226   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8227   emitcode ("", "%05d$:", tlbl->key + 100);
8228   emitcode ("mov", "c,ov");
8229   _startLazyDPSEvaluation ();
8230   while (size--)
8231     {
8232       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8233       MOVA (l);
8234       emitcode ("rrc", "a");
8235       aopPut (AOP (result), "a", offset--);
8236     }
8237   _endLazyDPSEvaluation ();
8238   reAdjustPreg (AOP (result));
8239   emitcode ("", "%05d$:", tlbl1->key + 100);
8240   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8241
8242 release:
8243   freeAsmop (left, NULL, ic, TRUE);
8244   freeAsmop (result, NULL, ic, TRUE);
8245 }
8246
8247 /*-----------------------------------------------------------------*/
8248 /* genRightShift - generate code for right shifting                */
8249 /*-----------------------------------------------------------------*/
8250 static void
8251 genRightShift (iCode * ic)
8252 {
8253   operand *right, *left, *result;
8254   sym_link *retype;
8255   int size, offset;
8256   char *l;
8257   symbol *tlbl, *tlbl1;
8258
8259   D (emitcode (";", "genRightShift "););
8260
8261   /* if signed then we do it the hard way preserve the
8262      sign bit moving it inwards */
8263   retype = getSpec (operandType (IC_RESULT (ic)));
8264
8265   if (!SPEC_USIGN (retype))
8266     {
8267       genSignedRightShift (ic);
8268       return;
8269     }
8270
8271   /* signed & unsigned types are treated the same : i.e. the
8272      signed is NOT propagated inwards : quoting from the
8273      ANSI - standard : "for E1 >> E2, is equivalent to division
8274      by 2**E2 if unsigned or if it has a non-negative value,
8275      otherwise the result is implementation defined ", MY definition
8276      is that the sign does not get propagated */
8277
8278   right = IC_RIGHT (ic);
8279   left = IC_LEFT (ic);
8280   result = IC_RESULT (ic);
8281
8282   aopOp (right, ic, FALSE, FALSE);
8283
8284 #ifdef BETTER_LITERAL_SHIFT
8285   /* if the shift count is known then do it
8286      as efficiently as possible */
8287   if (AOP_TYPE (right) == AOP_LIT)
8288     {
8289       if (genRightShiftLiteral (left, right, result, ic, 0))
8290       {
8291         return;
8292       }
8293     }
8294 #endif
8295
8296   /* shift count is unknown then we have to form
8297      a loop get the loop count in B : Note: we take
8298      only the lower order byte since shifting
8299      more that 32 bits make no sense anyway, ( the
8300      largest size of an object can be only 32 bits ) */
8301   
8302   if (AOP_TYPE (right) == AOP_LIT)
8303   {
8304       /* Really should be handled by genRightShiftLiteral,
8305        * but since I'm too lazy to fix that today, at least we can make
8306        * some small improvement.
8307        */
8308        emitcode("mov", "b,#0x%02x",
8309                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8310   }
8311   else
8312   {
8313         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8314         emitcode ("inc", "b");
8315   }
8316   freeAsmop (right, NULL, ic, TRUE);
8317   aopOp (left, ic, FALSE, FALSE);
8318   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8319
8320   /* now move the left to the result if they are not the
8321      same */
8322   if (!sameRegs (AOP (left), AOP (result)) &&
8323       AOP_SIZE (result) > 1)
8324     {
8325
8326       size = AOP_SIZE (result);
8327       offset = 0;
8328       _startLazyDPSEvaluation ();
8329       while (size--)
8330         {
8331           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8332           if (*l == '@' && IS_AOP_PREG (result))
8333             {
8334
8335               emitcode ("mov", "a,%s", l);
8336               aopPut (AOP (result), "a", offset);
8337             }
8338           else
8339             aopPut (AOP (result), l, offset);
8340           offset++;
8341         }
8342       _endLazyDPSEvaluation ();
8343     }
8344
8345   tlbl = newiTempLabel (NULL);
8346   tlbl1 = newiTempLabel (NULL);
8347   size = AOP_SIZE (result);
8348   offset = size - 1;
8349
8350   /* if it is only one byte then */
8351   if (size == 1)
8352     {
8353       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8354       MOVA (l);
8355       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8356       emitcode ("", "%05d$:", tlbl->key + 100);
8357       CLRC;
8358       emitcode ("rrc", "a");
8359       emitcode ("", "%05d$:", tlbl1->key + 100);
8360       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8361       aopPut (AOP (result), "a", 0);
8362       goto release;
8363     }
8364
8365   reAdjustPreg (AOP (result));
8366   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8367   emitcode ("", "%05d$:", tlbl->key + 100);
8368   CLRC;
8369   _startLazyDPSEvaluation ();
8370   while (size--)
8371     {
8372       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8373       MOVA (l);
8374       emitcode ("rrc", "a");
8375       aopPut (AOP (result), "a", offset--);
8376     }
8377   _endLazyDPSEvaluation ();
8378   reAdjustPreg (AOP (result));
8379
8380   emitcode ("", "%05d$:", tlbl1->key + 100);
8381   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8382
8383 release:
8384   freeAsmop (left, NULL, ic, TRUE);
8385   freeAsmop (result, NULL, ic, TRUE);
8386 }
8387
8388 /*-----------------------------------------------------------------*/
8389 /* genUnpackBits - generates code for unpacking bits               */
8390 /*-----------------------------------------------------------------*/
8391 static void
8392 genUnpackBits (operand * result, char *rname, int ptype)
8393 {
8394   int shCnt;
8395   int rlen = 0;
8396   sym_link *etype;
8397   int offset = 0;
8398
8399   D (emitcode (";", "genUnpackBits ");
8400     );
8401
8402   etype = getSpec (operandType (result));
8403
8404   /* read the first byte  */
8405   switch (ptype)
8406     {
8407
8408     case POINTER:
8409     case IPOINTER:
8410       emitcode ("mov", "a,@%s", rname);
8411       break;
8412
8413     case PPOINTER:
8414       emitcode ("movx", "a,@%s", rname);
8415       break;
8416
8417     case FPOINTER:
8418       emitcode ("movx", "a,@dptr");
8419       break;
8420
8421     case CPOINTER:
8422       emitcode ("clr", "a");
8423       emitcode ("movc", "a,@a+dptr");
8424       break;
8425
8426     case GPOINTER:
8427       emitcode ("lcall", "__gptrget");
8428       break;
8429     }
8430
8431   /* if we have bitdisplacement then it fits   */
8432   /* into this byte completely or if length is */
8433   /* less than a byte                          */
8434   if ((shCnt = SPEC_BSTR (etype)) ||
8435       (SPEC_BLEN (etype) <= 8))
8436     {
8437
8438       /* shift right acc */
8439       AccRsh (shCnt);
8440
8441       emitcode ("anl", "a,#0x%02x",
8442                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8443       aopPut (AOP (result), "a", offset);
8444       return;
8445     }
8446
8447   /* bit field did not fit in a byte  */
8448   rlen = SPEC_BLEN (etype) - 8;
8449   aopPut (AOP (result), "a", offset++);
8450
8451   while (1)
8452     {
8453
8454       switch (ptype)
8455         {
8456         case POINTER:
8457         case IPOINTER:
8458           emitcode ("inc", "%s", rname);
8459           emitcode ("mov", "a,@%s", rname);
8460           break;
8461
8462         case PPOINTER:
8463           emitcode ("inc", "%s", rname);
8464           emitcode ("movx", "a,@%s", rname);
8465           break;
8466
8467         case FPOINTER:
8468           emitcode ("inc", "dptr");
8469           emitcode ("movx", "a,@dptr");
8470           break;
8471
8472         case CPOINTER:
8473           emitcode ("clr", "a");
8474           emitcode ("inc", "dptr");
8475           emitcode ("movc", "a,@a+dptr");
8476           break;
8477
8478         case GPOINTER:
8479           emitcode ("inc", "dptr");
8480           emitcode ("lcall", "__gptrget");
8481           break;
8482         }
8483
8484       rlen -= 8;
8485       /* if we are done */
8486       if (rlen < 8)
8487         break;
8488
8489       aopPut (AOP (result), "a", offset++);
8490
8491     }
8492
8493   if (rlen)
8494     {
8495       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8496       aopPut (AOP (result), "a", offset);
8497     }
8498
8499   return;
8500 }
8501
8502
8503 /*-----------------------------------------------------------------*/
8504 /* genDataPointerGet - generates code when ptr offset is known     */
8505 /*-----------------------------------------------------------------*/
8506 static void
8507 genDataPointerGet (operand * left,
8508                    operand * result,
8509                    iCode * ic)
8510 {
8511   char *l;
8512   char buffer[256];
8513   int size, offset = 0;
8514   aopOp (result, ic, TRUE, FALSE);
8515
8516   /* get the string representation of the name */
8517   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8518   size = AOP_SIZE (result);
8519   _startLazyDPSEvaluation ();
8520   while (size--)
8521     {
8522       if (offset)
8523         sprintf (buffer, "(%s + %d)", l + 1, offset);
8524       else
8525         sprintf (buffer, "%s", l + 1);
8526       aopPut (AOP (result), buffer, offset++);
8527     }
8528   _endLazyDPSEvaluation ();
8529
8530   freeAsmop (left, NULL, ic, TRUE);
8531   freeAsmop (result, NULL, ic, TRUE);
8532 }
8533
8534 /*-----------------------------------------------------------------*/
8535 /* genNearPointerGet - emitcode for near pointer fetch             */
8536 /*-----------------------------------------------------------------*/
8537 static void
8538 genNearPointerGet (operand * left,
8539                    operand * result,
8540                    iCode * ic)
8541 {
8542   asmop *aop = NULL;
8543   regs *preg = NULL;
8544   char *rname;
8545   sym_link *rtype, *retype, *letype;
8546   sym_link *ltype = operandType (left);
8547   char buffer[80];
8548
8549   rtype = operandType (result);
8550   retype = getSpec (rtype);
8551   letype = getSpec (ltype);
8552
8553   aopOp (left, ic, FALSE, FALSE);
8554
8555   /* if left is rematerialisable and
8556      result is not bit variable type and
8557      the left is pointer to data space i.e
8558      lower 128 bytes of space */
8559   if (AOP_TYPE (left) == AOP_IMMD &&
8560       !IS_BITVAR (retype) &&
8561       !IS_BITVAR (letype) &&
8562       DCL_TYPE (ltype) == POINTER)
8563     {
8564       genDataPointerGet (left, result, ic);
8565       return;
8566     }
8567
8568   /* if the value is already in a pointer register
8569      then don't need anything more */
8570   if (!AOP_INPREG (AOP (left)))
8571     {
8572       /* otherwise get a free pointer register */
8573       aop = newAsmop (0);
8574       preg = getFreePtr (ic, &aop, FALSE);
8575       emitcode ("mov", "%s,%s",
8576                 preg->name,
8577                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8578       rname = preg->name;
8579     }
8580   else
8581     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8582
8583   freeAsmop (left, NULL, ic, TRUE);
8584   aopOp (result, ic, FALSE, FALSE);
8585
8586   /* if bitfield then unpack the bits */
8587   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8588     genUnpackBits (result, rname, POINTER);
8589   else
8590     {
8591       /* we have can just get the values */
8592       int size = AOP_SIZE (result);
8593       int offset = 0;
8594
8595       while (size--)
8596         {
8597           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8598             {
8599
8600               emitcode ("mov", "a,@%s", rname);
8601               aopPut (AOP (result), "a", offset);
8602             }
8603           else
8604             {
8605               sprintf (buffer, "@%s", rname);
8606               aopPut (AOP (result), buffer, offset);
8607             }
8608           offset++;
8609           if (size)
8610             emitcode ("inc", "%s", rname);
8611         }
8612     }
8613
8614   /* now some housekeeping stuff */
8615   if (aop)
8616     {
8617       /* we had to allocate for this iCode */
8618       freeAsmop (NULL, aop, ic, TRUE);
8619     }
8620   else
8621     {
8622       /* we did not allocate which means left
8623          already in a pointer register, then
8624          if size > 0 && this could be used again
8625          we have to point it back to where it
8626          belongs */
8627       if (AOP_SIZE (result) > 1 &&
8628           !OP_SYMBOL (left)->remat &&
8629           (OP_SYMBOL (left)->liveTo > ic->seq ||
8630            ic->depth))
8631         {
8632           int size = AOP_SIZE (result) - 1;
8633           while (size--)
8634             emitcode ("dec", "%s", rname);
8635         }
8636     }
8637
8638   /* done */
8639   freeAsmop (result, NULL, ic, TRUE);
8640
8641 }
8642
8643 /*-----------------------------------------------------------------*/
8644 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8645 /*-----------------------------------------------------------------*/
8646 static void
8647 genPagedPointerGet (operand * left,
8648                     operand * result,
8649                     iCode * ic)
8650 {
8651   asmop *aop = NULL;
8652   regs *preg = NULL;
8653   char *rname;
8654   sym_link *rtype, *retype, *letype;
8655
8656   rtype = operandType (result);
8657   retype = getSpec (rtype);
8658   letype = getSpec (operandType (left));
8659   aopOp (left, ic, FALSE, FALSE);
8660
8661   /* if the value is already in a pointer register
8662      then don't need anything more */
8663   if (!AOP_INPREG (AOP (left)))
8664     {
8665       /* otherwise get a free pointer register */
8666       aop = newAsmop (0);
8667       preg = getFreePtr (ic, &aop, FALSE);
8668       emitcode ("mov", "%s,%s",
8669                 preg->name,
8670                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8671       rname = preg->name;
8672     }
8673   else
8674     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8675
8676   freeAsmop (left, NULL, ic, TRUE);
8677   aopOp (result, ic, FALSE, FALSE);
8678
8679   /* if bitfield then unpack the bits */
8680   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8681     genUnpackBits (result, rname, PPOINTER);
8682   else
8683     {
8684       /* we have can just get the values */
8685       int size = AOP_SIZE (result);
8686       int offset = 0;
8687
8688       while (size--)
8689         {
8690
8691           emitcode ("movx", "a,@%s", rname);
8692           aopPut (AOP (result), "a", offset);
8693
8694           offset++;
8695
8696           if (size)
8697             emitcode ("inc", "%s", rname);
8698         }
8699     }
8700
8701   /* now some housekeeping stuff */
8702   if (aop)
8703     {
8704       /* we had to allocate for this iCode */
8705       freeAsmop (NULL, aop, ic, TRUE);
8706     }
8707   else
8708     {
8709       /* we did not allocate which means left
8710          already in a pointer register, then
8711          if size > 0 && this could be used again
8712          we have to point it back to where it
8713          belongs */
8714       if (AOP_SIZE (result) > 1 &&
8715           !OP_SYMBOL (left)->remat &&
8716           (OP_SYMBOL (left)->liveTo > ic->seq ||
8717            ic->depth))
8718         {
8719           int size = AOP_SIZE (result) - 1;
8720           while (size--)
8721             emitcode ("dec", "%s", rname);
8722         }
8723     }
8724
8725   /* done */
8726   freeAsmop (result, NULL, ic, TRUE);
8727
8728
8729 }
8730
8731 /*-----------------------------------------------------------------*/
8732 /* genFarPointerGet - gget value from far space                    */
8733 /*-----------------------------------------------------------------*/
8734 static void
8735 genFarPointerGet (operand * left,
8736                   operand * result, iCode * ic)
8737 {
8738   int size, offset;
8739   sym_link *retype = getSpec (operandType (result));
8740   sym_link *letype = getSpec (operandType (left));
8741   D (emitcode (";", "genFarPointerGet");
8742     );
8743
8744   aopOp (left, ic, FALSE, FALSE);
8745
8746   /* if the operand is already in dptr
8747      then we do nothing else we move the value to dptr */
8748   if (AOP_TYPE (left) != AOP_STR)
8749     {
8750       /* if this is remateriazable */
8751       if (AOP_TYPE (left) == AOP_IMMD)
8752         {
8753           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8754         }
8755       else
8756         {
8757           /* we need to get it byte by byte */
8758           _startLazyDPSEvaluation ();
8759           if (AOP_TYPE (left) != AOP_DPTR)
8760             {
8761               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8762               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8763               if (options.model == MODEL_FLAT24)
8764                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8765             }
8766           else
8767             {
8768               /* We need to generate a load to DPTR indirect through DPTR. */
8769               D (emitcode (";", "genFarPointerGet -- indirection special case.");
8770                 );
8771               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8772               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8773               if (options.model == MODEL_FLAT24)
8774                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8775               emitcode ("pop", "dph");
8776               emitcode ("pop", "dpl");
8777             }
8778           _endLazyDPSEvaluation ();
8779         }
8780     }
8781   /* so dptr know contains the address */
8782   freeAsmop (left, NULL, ic, TRUE);
8783   aopOp (result, ic, FALSE, TRUE);
8784
8785   /* if bit then unpack */
8786   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8787     genUnpackBits (result, "dptr", FPOINTER);
8788   else
8789     {
8790       size = AOP_SIZE (result);
8791       offset = 0;
8792
8793       _startLazyDPSEvaluation ();
8794       while (size--)
8795         {
8796
8797           genSetDPTR (0);
8798           _flushLazyDPS ();
8799
8800           emitcode ("movx", "a,@dptr");
8801           if (size)
8802             emitcode ("inc", "dptr");
8803
8804           aopPut (AOP (result), "a", offset++);
8805         }
8806       _endLazyDPSEvaluation ();
8807     }
8808
8809   freeAsmop (result, NULL, ic, TRUE);
8810 }
8811
8812 /*-----------------------------------------------------------------*/
8813 /* emitcodePointerGet - gget value from code space                  */
8814 /*-----------------------------------------------------------------*/
8815 static void
8816 emitcodePointerGet (operand * left,
8817                     operand * result, iCode * ic)
8818 {
8819   int size, offset;
8820   sym_link *retype = getSpec (operandType (result));
8821
8822   aopOp (left, ic, FALSE, FALSE);
8823
8824   /* if the operand is already in dptr
8825      then we do nothing else we move the value to dptr */
8826   if (AOP_TYPE (left) != AOP_STR)
8827     {
8828       /* if this is remateriazable */
8829       if (AOP_TYPE (left) == AOP_IMMD)
8830         {
8831           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8832         }
8833       else
8834         {                       /* we need to get it byte by byte */
8835           _startLazyDPSEvaluation ();
8836           if (AOP_TYPE (left) != AOP_DPTR)
8837             {
8838               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8839               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8840               if (options.model == MODEL_FLAT24)
8841                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8842             }
8843           else
8844             {
8845               /* We need to generate a load to DPTR indirect through DPTR. */
8846               D (emitcode (";", "gencodePointerGet -- indirection special case.");
8847                 );
8848               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8849               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8850               if (options.model == MODEL_FLAT24)
8851                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8852               emitcode ("pop", "dph");
8853               emitcode ("pop", "dpl");
8854             }
8855           _endLazyDPSEvaluation ();
8856         }
8857     }
8858   /* so dptr know contains the address */
8859   freeAsmop (left, NULL, ic, TRUE);
8860   aopOp (result, ic, FALSE, TRUE);
8861
8862   /* if bit then unpack */
8863   if (IS_BITVAR (retype))
8864     genUnpackBits (result, "dptr", CPOINTER);
8865   else
8866     {
8867       size = AOP_SIZE (result);
8868       offset = 0;
8869
8870       _startLazyDPSEvaluation ();
8871       while (size--)
8872         {
8873           genSetDPTR (0);
8874           _flushLazyDPS ();
8875
8876           emitcode ("clr", "a");
8877           emitcode ("movc", "a,@a+dptr");
8878           if (size)
8879             emitcode ("inc", "dptr");
8880           aopPut (AOP (result), "a", offset++);
8881         }
8882       _endLazyDPSEvaluation ();
8883     }
8884
8885   freeAsmop (result, NULL, ic, TRUE);
8886 }
8887
8888 /*-----------------------------------------------------------------*/
8889 /* genGenPointerGet - gget value from generic pointer space        */
8890 /*-----------------------------------------------------------------*/
8891 static void
8892 genGenPointerGet (operand * left,
8893                   operand * result, iCode * ic)
8894 {
8895   int size, offset;
8896   sym_link *retype = getSpec (operandType (result));
8897   sym_link *letype = getSpec (operandType (left));
8898
8899   D (emitcode (";", "genGenPointerGet "); );
8900
8901   aopOp (left, ic, FALSE, TRUE);
8902
8903   /* if the operand is already in dptr
8904      then we do nothing else we move the value to dptr */
8905   if (AOP_TYPE (left) != AOP_STR)
8906     {
8907       /* if this is remateriazable */
8908       if (AOP_TYPE (left) == AOP_IMMD)
8909         {
8910           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8911           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
8912                   emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
8913           else
8914                   emitcode ("mov", "b,#%d", pointerCode (retype));
8915         }
8916       else
8917         {                       /* we need to get it byte by byte */
8918           _startLazyDPSEvaluation ();
8919           if (AOP(left)->type==AOP_DPTR2) {
8920             char *l;
8921             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8922             genSetDPTR(0);
8923             _flushLazyDPS();
8924             emitcode ("mov", "dpl,%s", l);
8925             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8926             genSetDPTR(0);
8927             _flushLazyDPS();
8928             emitcode ("mov", "dph,%s", l);
8929             if (options.model == MODEL_FLAT24) {
8930               l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8931               genSetDPTR(0);
8932               _flushLazyDPS();
8933               emitcode ("mov", "dpx,%s", l);
8934               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8935             } else {
8936               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8937             }
8938           } else {
8939             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8940             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8941             if (options.model == MODEL_FLAT24) {
8942               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8943               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8944             } else {
8945               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8946             }
8947           }
8948           _endLazyDPSEvaluation ();
8949         }
8950     }
8951   /* so dptr know contains the address */
8952   freeAsmop (left, NULL, ic, TRUE);
8953   aopOp (result, ic, FALSE, TRUE);
8954
8955   /* if bit then unpack */
8956   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8957     genUnpackBits (result, "dptr", GPOINTER);
8958   else
8959     {
8960       size = AOP_SIZE (result);
8961       offset = 0;
8962
8963       while (size--)
8964         {
8965           emitcode ("lcall", "__gptrget");
8966           aopPut (AOP (result), "a", offset++);
8967           if (size)
8968             emitcode ("inc", "dptr");
8969         }
8970     }
8971
8972   freeAsmop (result, NULL, ic, TRUE);
8973 }
8974
8975 /*-----------------------------------------------------------------*/
8976 /* genPointerGet - generate code for pointer get                   */
8977 /*-----------------------------------------------------------------*/
8978 static void
8979 genPointerGet (iCode * ic)
8980 {
8981   operand *left, *result;
8982   sym_link *type, *etype;
8983   int p_type;
8984
8985   D (emitcode (";", "genPointerGet ");
8986     );
8987
8988   left = IC_LEFT (ic);
8989   result = IC_RESULT (ic);
8990
8991   /* depending on the type of pointer we need to
8992      move it to the correct pointer register */
8993   type = operandType (left);
8994   etype = getSpec (type);
8995   /* if left is of type of pointer then it is simple */
8996   if (IS_PTR (type) && !IS_FUNC (type->next))
8997     p_type = DCL_TYPE (type);
8998   else
8999     {
9000       /* we have to go by the storage class */
9001       p_type = PTR_TYPE (SPEC_OCLS (etype));
9002     }
9003   /* special case when cast remat */
9004   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9005       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9006           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9007           type =   type = operandType (left);
9008           p_type = DCL_TYPE (type);
9009   }
9010   /* now that we have the pointer type we assign
9011      the pointer values */
9012   switch (p_type)
9013     {
9014
9015     case POINTER:
9016     case IPOINTER:
9017       genNearPointerGet (left, result, ic);
9018       break;
9019
9020     case PPOINTER:
9021       genPagedPointerGet (left, result, ic);
9022       break;
9023
9024     case FPOINTER:
9025       genFarPointerGet (left, result, ic);
9026       break;
9027
9028     case CPOINTER:
9029       emitcodePointerGet (left, result, ic);
9030       break;
9031
9032     case GPOINTER:
9033       genGenPointerGet (left, result, ic);
9034       break;
9035     }
9036
9037 }
9038
9039 /*-----------------------------------------------------------------*/
9040 /* genPackBits - generates code for packed bit storage             */
9041 /*-----------------------------------------------------------------*/
9042 static void
9043 genPackBits (sym_link * etype,
9044              operand * right,
9045              char *rname, int p_type)
9046 {
9047   int shCount = 0;
9048   int offset = 0;
9049   int rLen = 0;
9050   int blen, bstr;
9051   char *l;
9052
9053   blen = SPEC_BLEN (etype);
9054   bstr = SPEC_BSTR (etype);
9055
9056   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9057   MOVA (l);
9058
9059   /* if the bit lenth is less than or    */
9060   /* it exactly fits a byte then         */
9061   if (SPEC_BLEN (etype) <= 8)
9062     {
9063       shCount = SPEC_BSTR (etype);
9064
9065       /* shift left acc */
9066       AccLsh (shCount);
9067
9068       if (SPEC_BLEN (etype) < 8)
9069         {                       /* if smaller than a byte */
9070
9071
9072           switch (p_type)
9073             {
9074             case POINTER:
9075               emitcode ("mov", "b,a");
9076               emitcode ("mov", "a,@%s", rname);
9077               break;
9078
9079             case FPOINTER:
9080               emitcode ("mov", "b,a");
9081               emitcode ("movx", "a,@dptr");
9082               break;
9083
9084             case GPOINTER:
9085               emitcode ("push", "b");
9086               emitcode ("push", "acc");
9087               emitcode ("lcall", "__gptrget");
9088               emitcode ("pop", "b");
9089               break;
9090             }
9091
9092           emitcode ("anl", "a,#0x%02x", (unsigned char)
9093                     ((unsigned char) (0xFF << (blen + bstr)) |
9094                      (unsigned char) (0xFF >> (8 - bstr))));
9095           emitcode ("orl", "a,b");
9096           if (p_type == GPOINTER)
9097             emitcode ("pop", "b");
9098         }
9099     }
9100
9101   switch (p_type)
9102     {
9103     case POINTER:
9104       emitcode ("mov", "@%s,a", rname);
9105       break;
9106
9107     case FPOINTER:
9108       emitcode ("movx", "@dptr,a");
9109       break;
9110
9111     case GPOINTER:
9112       emitcode ("lcall", "__gptrput");
9113       break;
9114     }
9115
9116   /* if we r done */
9117   if (SPEC_BLEN (etype) <= 8)
9118     return;
9119
9120   emitcode ("inc", "%s", rname);
9121   rLen = SPEC_BLEN (etype);
9122
9123   /* now generate for lengths greater than one byte */
9124   while (1)
9125     {
9126
9127       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9128
9129       rLen -= 8;
9130       if (rLen < 8)
9131         break;
9132
9133       switch (p_type)
9134         {
9135         case POINTER:
9136           if (*l == '@')
9137             {
9138               MOVA (l);
9139               emitcode ("mov", "@%s,a", rname);
9140             }
9141           else
9142             emitcode ("mov", "@%s,%s", rname, l);
9143           break;
9144
9145         case FPOINTER:
9146           MOVA (l);
9147           emitcode ("movx", "@dptr,a");
9148           break;
9149
9150         case GPOINTER:
9151           MOVA (l);
9152           emitcode ("lcall", "__gptrput");
9153           break;
9154         }
9155       emitcode ("inc", "%s", rname);
9156     }
9157
9158   MOVA (l);
9159
9160   /* last last was not complete */
9161   if (rLen)
9162     {
9163       /* save the byte & read byte */
9164       switch (p_type)
9165         {
9166         case POINTER:
9167           emitcode ("mov", "b,a");
9168           emitcode ("mov", "a,@%s", rname);
9169           break;
9170
9171         case FPOINTER:
9172           emitcode ("mov", "b,a");
9173           emitcode ("movx", "a,@dptr");
9174           break;
9175
9176         case GPOINTER:
9177           emitcode ("push", "b");
9178           emitcode ("push", "acc");
9179           emitcode ("lcall", "__gptrget");
9180           emitcode ("pop", "b");
9181           break;
9182         }
9183
9184       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
9185       emitcode ("orl", "a,b");
9186     }
9187
9188   if (p_type == GPOINTER)
9189     emitcode ("pop", "b");
9190
9191   switch (p_type)
9192     {
9193
9194     case POINTER:
9195       emitcode ("mov", "@%s,a", rname);
9196       break;
9197
9198     case FPOINTER:
9199       emitcode ("movx", "@dptr,a");
9200       break;
9201
9202     case GPOINTER:
9203       emitcode ("lcall", "__gptrput");
9204       break;
9205     }
9206 }
9207 /*-----------------------------------------------------------------*/
9208 /* genDataPointerSet - remat pointer to data space                 */
9209 /*-----------------------------------------------------------------*/
9210 static void
9211 genDataPointerSet (operand * right,
9212                    operand * result,
9213                    iCode * ic)
9214 {
9215   int size, offset = 0;
9216   char *l, buffer[256];
9217
9218   aopOp (right, ic, FALSE, FALSE);
9219
9220   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9221   size = AOP_SIZE (right);
9222   while (size--)
9223     {
9224       if (offset)
9225         sprintf (buffer, "(%s + %d)", l + 1, offset);
9226       else
9227         sprintf (buffer, "%s", l + 1);
9228       emitcode ("mov", "%s,%s", buffer,
9229                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9230     }
9231
9232   freeAsmop (right, NULL, ic, TRUE);
9233   freeAsmop (result, NULL, ic, TRUE);
9234 }
9235
9236 /*-----------------------------------------------------------------*/
9237 /* genNearPointerSet - emitcode for near pointer put                */
9238 /*-----------------------------------------------------------------*/
9239 static void
9240 genNearPointerSet (operand * right,
9241                    operand * result,
9242                    iCode * ic)
9243 {
9244   asmop *aop = NULL;
9245   regs *preg = NULL;
9246   char *rname, *l;
9247   sym_link *retype, *letype;
9248   sym_link *ptype = operandType (result);
9249
9250   retype = getSpec (operandType (right));
9251   letype = getSpec (ptype);
9252
9253   aopOp (result, ic, FALSE, FALSE);
9254
9255   /* if the result is rematerializable &
9256      in data space & not a bit variable */
9257   if (AOP_TYPE (result) == AOP_IMMD &&
9258       DCL_TYPE (ptype) == POINTER &&
9259       !IS_BITVAR (retype) &&
9260       !IS_BITVAR (letype))
9261     {
9262       genDataPointerSet (right, result, ic);
9263       return;
9264     }
9265
9266   /* if the value is already in a pointer register
9267      then don't need anything more */
9268   if (!AOP_INPREG (AOP (result)))
9269     {
9270       /* otherwise get a free pointer register */
9271       aop = newAsmop (0);
9272       preg = getFreePtr (ic, &aop, FALSE);
9273       emitcode ("mov", "%s,%s",
9274                 preg->name,
9275                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9276       rname = preg->name;
9277     }
9278   else
9279     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9280
9281   freeAsmop (result, NULL, ic, TRUE);
9282   aopOp (right, ic, FALSE, FALSE);
9283
9284   /* if bitfield then unpack the bits */
9285   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9286     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9287   else
9288     {
9289       /* we have can just get the values */
9290       int size = AOP_SIZE (right);
9291       int offset = 0;
9292
9293       while (size--)
9294         {
9295           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9296           if (*l == '@')
9297             {
9298               MOVA (l);
9299               emitcode ("mov", "@%s,a", rname);
9300             }
9301           else
9302             emitcode ("mov", "@%s,%s", rname, l);
9303           if (size)
9304             emitcode ("inc", "%s", rname);
9305           offset++;
9306         }
9307     }
9308
9309   /* now some housekeeping stuff */
9310   if (aop)
9311     {
9312       /* we had to allocate for this iCode */
9313       freeAsmop (NULL, aop, ic, TRUE);
9314     }
9315   else
9316     {
9317       /* we did not allocate which means left
9318          already in a pointer register, then
9319          if size > 0 && this could be used again
9320          we have to point it back to where it
9321          belongs */
9322       if (AOP_SIZE (right) > 1 &&
9323           !OP_SYMBOL (result)->remat &&
9324           (OP_SYMBOL (result)->liveTo > ic->seq ||
9325            ic->depth))
9326         {
9327           int size = AOP_SIZE (right) - 1;
9328           while (size--)
9329             emitcode ("dec", "%s", rname);
9330         }
9331     }
9332
9333   /* done */
9334   freeAsmop (right, NULL, ic, TRUE);
9335
9336
9337 }
9338
9339 /*-----------------------------------------------------------------*/
9340 /* genPagedPointerSet - emitcode for Paged pointer put             */
9341 /*-----------------------------------------------------------------*/
9342 static void
9343 genPagedPointerSet (operand * right,
9344                     operand * result,
9345                     iCode * ic)
9346 {
9347   asmop *aop = NULL;
9348   regs *preg = NULL;
9349   char *rname, *l;
9350   sym_link *retype, *letype;
9351
9352   retype = getSpec (operandType (right));
9353   letype = getSpec (operandType (result));
9354
9355   aopOp (result, ic, FALSE, FALSE);
9356
9357   /* if the value is already in a pointer register
9358      then don't need anything more */
9359   if (!AOP_INPREG (AOP (result)))
9360     {
9361       /* otherwise get a free pointer register */
9362       aop = newAsmop (0);
9363       preg = getFreePtr (ic, &aop, FALSE);
9364       emitcode ("mov", "%s,%s",
9365                 preg->name,
9366                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9367       rname = preg->name;
9368     }
9369   else
9370     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9371
9372   freeAsmop (result, NULL, ic, TRUE);
9373   aopOp (right, ic, FALSE, FALSE);
9374
9375   /* if bitfield then unpack the bits */
9376   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9377     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9378   else
9379     {
9380       /* we have can just get the values */
9381       int size = AOP_SIZE (right);
9382       int offset = 0;
9383
9384       while (size--)
9385         {
9386           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9387
9388           MOVA (l);
9389           emitcode ("movx", "@%s,a", rname);
9390
9391           if (size)
9392             emitcode ("inc", "%s", rname);
9393
9394           offset++;
9395         }
9396     }
9397
9398   /* now some housekeeping stuff */
9399   if (aop)
9400     {
9401       /* we had to allocate for this iCode */
9402       freeAsmop (NULL, aop, ic, TRUE);
9403     }
9404   else
9405     {
9406       /* we did not allocate which means left
9407          already in a pointer register, then
9408          if size > 0 && this could be used again
9409          we have to point it back to where it
9410          belongs */
9411       if (AOP_SIZE (right) > 1 &&
9412           !OP_SYMBOL (result)->remat &&
9413           (OP_SYMBOL (result)->liveTo > ic->seq ||
9414            ic->depth))
9415         {
9416           int size = AOP_SIZE (right) - 1;
9417           while (size--)
9418             emitcode ("dec", "%s", rname);
9419         }
9420     }
9421
9422   /* done */
9423   freeAsmop (right, NULL, ic, TRUE);
9424
9425
9426 }
9427
9428 /*-----------------------------------------------------------------*/
9429 /* genFarPointerSet - set value from far space                     */
9430 /*-----------------------------------------------------------------*/
9431 static void
9432 genFarPointerSet (operand * right,
9433                   operand * result, iCode * ic)
9434 {
9435   int size, offset;
9436   sym_link *retype = getSpec (operandType (right));
9437   sym_link *letype = getSpec (operandType (result));
9438
9439   aopOp (result, ic, FALSE, FALSE);
9440
9441   /* if the operand is already in dptr
9442      then we do nothing else we move the value to dptr */
9443   if (AOP_TYPE (result) != AOP_STR)
9444     {
9445       /* if this is remateriazable */
9446       if (AOP_TYPE (result) == AOP_IMMD)
9447         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9448       else
9449         {
9450           /* we need to get it byte by byte */
9451           _startLazyDPSEvaluation ();
9452           if (AOP_TYPE (result) != AOP_DPTR)
9453             {
9454               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9455               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9456               if (options.model == MODEL_FLAT24)
9457                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9458             }
9459           else
9460             {
9461               /* We need to generate a load to DPTR indirect through DPTR. */
9462               D (emitcode (";", "genFarPointerSet -- indirection special case.");
9463                 );
9464               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9465               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9466               if (options.model == MODEL_FLAT24)
9467                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9468               emitcode ("pop", "dph");
9469               emitcode ("pop", "dpl");
9470             }
9471           _endLazyDPSEvaluation ();
9472         }
9473     }
9474   /* so dptr know contains the address */
9475   freeAsmop (result, NULL, ic, TRUE);
9476   aopOp (right, ic, FALSE, TRUE);
9477
9478   /* if bit then unpack */
9479   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9480     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9481   else
9482     {
9483       size = AOP_SIZE (right);
9484       offset = 0;
9485
9486       _startLazyDPSEvaluation ();
9487       while (size--)
9488         {
9489           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9490           MOVA (l);
9491
9492           genSetDPTR (0);
9493           _flushLazyDPS ();
9494
9495           emitcode ("movx", "@dptr,a");
9496           if (size)
9497             emitcode ("inc", "dptr");
9498         }
9499       _endLazyDPSEvaluation ();
9500     }
9501
9502   freeAsmop (right, NULL, ic, TRUE);
9503 }
9504
9505 /*-----------------------------------------------------------------*/
9506 /* genGenPointerSet - set value from generic pointer space         */
9507 /*-----------------------------------------------------------------*/
9508 static void
9509 genGenPointerSet (operand * right,
9510                   operand * result, iCode * ic)
9511 {
9512   int size, offset;
9513   sym_link *retype = getSpec (operandType (right));
9514   sym_link *letype = getSpec (operandType (result));
9515
9516   aopOp (result, ic, FALSE, TRUE);
9517
9518   /* if the operand is already in dptr
9519      then we do nothing else we move the value to dptr */
9520   if (AOP_TYPE (result) != AOP_STR)
9521     {
9522       _startLazyDPSEvaluation ();
9523       /* if this is remateriazable */
9524       if (AOP_TYPE (result) == AOP_IMMD)
9525         {
9526           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9527           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
9528                   emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9529           else
9530                   emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9531         }
9532       else
9533         {                       /* we need to get it byte by byte */
9534           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9535           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9536           if (options.model == MODEL_FLAT24) {
9537             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9538             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9539           } else {
9540             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9541           }
9542         }
9543       _endLazyDPSEvaluation ();
9544     }
9545   /* so dptr know contains the address */
9546   freeAsmop (result, NULL, ic, TRUE);
9547   aopOp (right, ic, FALSE, TRUE);
9548
9549   /* if bit then unpack */
9550   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9551     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9552   else
9553     {
9554       size = AOP_SIZE (right);
9555       offset = 0;
9556
9557       _startLazyDPSEvaluation ();
9558       while (size--)
9559         {
9560           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9561           MOVA (l);
9562
9563           genSetDPTR (0);
9564           _flushLazyDPS ();
9565
9566           emitcode ("lcall", "__gptrput");
9567           if (size)
9568             emitcode ("inc", "dptr");
9569         }
9570       _endLazyDPSEvaluation ();
9571     }
9572
9573   freeAsmop (right, NULL, ic, TRUE);
9574 }
9575
9576 /*-----------------------------------------------------------------*/
9577 /* genPointerSet - stores the value into a pointer location        */
9578 /*-----------------------------------------------------------------*/
9579 static void
9580 genPointerSet (iCode * ic)
9581 {
9582   operand *right, *result;
9583   sym_link *type, *etype;
9584   int p_type;
9585
9586   D (emitcode (";", "genPointerSet ");
9587     );
9588
9589   right = IC_RIGHT (ic);
9590   result = IC_RESULT (ic);
9591
9592   /* depending on the type of pointer we need to
9593      move it to the correct pointer register */
9594   type = operandType (result);
9595   etype = getSpec (type);
9596   /* if left is of type of pointer then it is simple */
9597   if (IS_PTR (type) && !IS_FUNC (type->next))
9598     {
9599       p_type = DCL_TYPE (type);
9600     }
9601   else
9602     {
9603       /* we have to go by the storage class */
9604       p_type = PTR_TYPE (SPEC_OCLS (etype));
9605     }
9606   /* special case when cast remat */
9607   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9608       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9609           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9610           type =   type = operandType (result);
9611           p_type = DCL_TYPE (type);
9612   }
9613
9614   /* now that we have the pointer type we assign
9615      the pointer values */
9616   switch (p_type)
9617     {
9618
9619     case POINTER:
9620     case IPOINTER:
9621       genNearPointerSet (right, result, ic);
9622       break;
9623
9624     case PPOINTER:
9625       genPagedPointerSet (right, result, ic);
9626       break;
9627
9628     case FPOINTER:
9629       genFarPointerSet (right, result, ic);
9630       break;
9631
9632     case GPOINTER:
9633       genGenPointerSet (right, result, ic);
9634       break;
9635     }
9636
9637 }
9638
9639 /*-----------------------------------------------------------------*/
9640 /* genIfx - generate code for Ifx statement                        */
9641 /*-----------------------------------------------------------------*/
9642 static void
9643 genIfx (iCode * ic, iCode * popIc)
9644 {
9645   operand *cond = IC_COND (ic);
9646   int isbit = 0;
9647
9648   D (emitcode (";", "genIfx "););
9649
9650   aopOp (cond, ic, FALSE, FALSE);
9651
9652   /* get the value into acc */
9653   if (AOP_TYPE (cond) != AOP_CRY)
9654     toBoolean (cond);
9655   else
9656     isbit = 1;
9657   /* the result is now in the accumulator */
9658   freeAsmop (cond, NULL, ic, TRUE);
9659
9660   /* if there was something to be popped then do it */
9661   if (popIc)
9662     genIpop (popIc);
9663
9664   /* if the condition is  a bit variable */
9665   if (isbit && IS_ITEMP (cond) &&
9666       SPIL_LOC (cond))
9667     genIfxJump (ic, SPIL_LOC (cond)->rname);
9668   else if (isbit && !IS_ITEMP (cond))
9669     genIfxJump (ic, OP_SYMBOL (cond)->rname);
9670   else
9671     genIfxJump (ic, "a");
9672
9673   ic->generated = 1;
9674 }
9675
9676 /*-----------------------------------------------------------------*/
9677 /* genAddrOf - generates code for address of                       */
9678 /*-----------------------------------------------------------------*/
9679 static void
9680 genAddrOf (iCode * ic)
9681 {
9682   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9683   int size, offset;
9684
9685   D (emitcode (";", "genAddrOf ");
9686     );
9687
9688   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9689
9690   /* if the operand is on the stack then we
9691      need to get the stack offset of this
9692      variable */
9693   if (sym->onStack)
9694     {
9695       /* if it has an offset then we need to compute
9696          it */
9697       if (sym->stack)
9698         {
9699           emitcode ("mov", "a,_bp");
9700           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9701           aopPut (AOP (IC_RESULT (ic)), "a", 0);
9702         }
9703       else
9704         {
9705           /* we can just move _bp */
9706           aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9707         }
9708       /* fill the result with zero */
9709       size = AOP_SIZE (IC_RESULT (ic)) - 1;
9710
9711
9712       if (options.stack10bit && size < (FPTRSIZE - 1))
9713         {
9714           fprintf (stderr,
9715                    "*** warning: pointer to stack var truncated.\n");
9716         }
9717
9718       offset = 1;
9719       while (size--)
9720         {
9721           /* Yuck! */
9722           if (options.stack10bit && offset == 2)
9723             {
9724               aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9725             }
9726           else
9727             {
9728               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9729             }
9730         }
9731
9732       goto release;
9733     }
9734
9735   /* object not on stack then we need the name */
9736   size = AOP_SIZE (IC_RESULT (ic));
9737   offset = 0;
9738
9739   while (size--)
9740     {
9741       char s[SDCC_NAME_MAX];
9742       if (offset)
9743         sprintf (s, "#(%s >> %d)",
9744                  sym->rname,
9745                  offset * 8);
9746       else
9747         sprintf (s, "#%s", sym->rname);
9748       aopPut (AOP (IC_RESULT (ic)), s, offset++);
9749     }
9750
9751 release:
9752   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9753
9754 }
9755
9756 /*-----------------------------------------------------------------*/
9757 /* genArrayInit - generates code for address of                       */
9758 /*-----------------------------------------------------------------*/
9759 static void
9760 genArrayInit (iCode * ic)
9761 {
9762     literalList *iLoop;
9763     int         ix, count;
9764     int         elementSize = 0, eIndex;
9765     unsigned    val, lastVal;
9766     sym_link    *type;
9767     operand     *left=IC_LEFT(ic);
9768     
9769     D (emitcode (";", "genArrayInit "););
9770
9771     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9772     
9773     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9774     {
9775         // Load immediate value into DPTR.
9776         emitcode("mov", "dptr, %s",
9777              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9778     }
9779     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9780     {
9781 #if 0
9782       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9783               "Unexpected operand to genArrayInit.\n");
9784       exit(1);
9785 #else
9786       // a regression because of SDCCcse.c:1.52
9787       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9788       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9789       if (options.model == MODEL_FLAT24)
9790         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9791 #endif
9792     }
9793     
9794     type = operandType(IC_LEFT(ic));
9795     
9796     if (type && type->next)
9797     {
9798         elementSize = getSize(type->next);
9799     }
9800     else
9801     {
9802         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9803                                 "can't determine element size in genArrayInit.\n");
9804         exit(1);
9805     }
9806     
9807     iLoop = IC_ARRAYILIST(ic);
9808     lastVal = 0xffff;
9809     
9810     while (iLoop)
9811     {
9812         bool firstpass = TRUE;
9813         
9814         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
9815                  iLoop->count, (int)iLoop->literalValue, elementSize);
9816         
9817         ix = iLoop->count;
9818         
9819         while (ix)
9820         {
9821             symbol *tlbl = NULL;
9822             
9823             count = ix > 256 ? 256 : ix;
9824             
9825             if (count > 1)
9826             {
9827                 tlbl = newiTempLabel (NULL);
9828                 if (firstpass || (count & 0xff))
9829                 {
9830                     emitcode("mov", "b, #0x%x", count & 0xff);
9831                 }
9832                 
9833                 emitcode ("", "%05d$:", tlbl->key + 100);
9834             }
9835             
9836             firstpass = FALSE;
9837                 
9838             for (eIndex = 0; eIndex < elementSize; eIndex++)
9839             {
9840                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9841                 if (val != lastVal)
9842                 {
9843                     emitcode("mov", "a, #0x%x", val);
9844                     lastVal = val;
9845                 }
9846                 
9847                 emitcode("movx", "@dptr, a");
9848                 emitcode("inc", "dptr");
9849             }
9850             
9851             if (count > 1)
9852             {
9853                 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9854             }
9855             
9856             ix -= count;
9857         }
9858         
9859         iLoop = iLoop->next;
9860     }
9861     
9862     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9863 }
9864
9865 /*-----------------------------------------------------------------*/
9866 /* genFarFarAssign - assignment when both are in far space         */
9867 /*-----------------------------------------------------------------*/
9868 static void
9869 genFarFarAssign (operand * result, operand * right, iCode * ic)
9870 {
9871   int size = AOP_SIZE (right);
9872   int offset = 0;
9873   symbol *rSym = NULL;
9874
9875   if (size == 1)
9876   {
9877       /* quick & easy case. */
9878       D(emitcode(";","genFarFarAssign (1 byte case)"););      
9879       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9880       freeAsmop (right, NULL, ic, FALSE);
9881       /* now assign DPTR to result */
9882       _G.accInUse++;
9883       aopOp(result, ic, FALSE, FALSE);
9884       _G.accInUse--;
9885       aopPut(AOP(result), "a", 0);
9886       freeAsmop(result, NULL, ic, FALSE);
9887       return;
9888   }
9889   
9890   /* See if we've got an underlying symbol to abuse. */
9891   if (IS_SYMOP(result) && OP_SYMBOL(result))
9892   {
9893       if (IS_TRUE_SYMOP(result))
9894       {
9895           rSym = OP_SYMBOL(result);
9896       }
9897       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9898       {
9899           rSym = OP_SYMBOL(result)->usl.spillLoc;
9900       }
9901   }
9902              
9903   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9904   {
9905       /* We can use the '390 auto-toggle feature to good effect here. */
9906       
9907       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
9908       emitcode("mov", "dps, #0x21");    /* Select DPTR2 & auto-toggle. */
9909       emitcode ("mov", "dptr,#%s", rSym->rname); 
9910       /* DP2 = result, DP1 = right, DP1 is current. */
9911       while (size)
9912       {
9913           emitcode("movx", "a,@dptr");
9914           emitcode("movx", "@dptr,a");
9915           if (--size)
9916           {
9917                emitcode("inc", "dptr");
9918                emitcode("inc", "dptr");
9919           }
9920       }
9921       emitcode("mov", "dps, #0");
9922       freeAsmop (right, NULL, ic, FALSE);
9923 #if 0
9924 some alternative code for processors without auto-toggle
9925 no time to test now, so later well put in...kpb
9926         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
9927         emitcode("mov", "dps, #0x01");  /* Select DPTR2. */
9928         emitcode ("mov", "dptr,#%s", rSym->rname); 
9929         /* DP2 = result, DP1 = right, DP1 is current. */
9930         while (size)
9931         {
9932           --size;
9933           emitcode("movx", "a,@dptr");
9934           if (size)
9935             emitcode("inc", "dptr");
9936           emitcode("inc", "dps");
9937           emitcode("movx", "@dptr,a");
9938           if (size)
9939             emitcode("inc", "dptr");
9940           emitcode("inc", "dps");
9941         }
9942         emitcode("mov", "dps, #0");
9943         freeAsmop (right, NULL, ic, FALSE);
9944 #endif
9945   }
9946   else
9947   {
9948       D (emitcode (";", "genFarFarAssign"););
9949       aopOp (result, ic, TRUE, TRUE);
9950
9951       _startLazyDPSEvaluation ();
9952       
9953       while (size--)
9954         {
9955           aopPut (AOP (result),
9956                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9957           offset++;
9958         }
9959       _endLazyDPSEvaluation ();
9960       freeAsmop (result, NULL, ic, FALSE);
9961       freeAsmop (right, NULL, ic, FALSE);
9962   }
9963 }
9964
9965 /*-----------------------------------------------------------------*/
9966 /* genAssign - generate code for assignment                        */
9967 /*-----------------------------------------------------------------*/
9968 static void
9969 genAssign (iCode * ic)
9970 {
9971   operand *result, *right;
9972   int size, offset;
9973   unsigned long lit = 0L;
9974
9975   D (emitcode (";", "genAssign ");
9976     );
9977
9978   result = IC_RESULT (ic);
9979   right = IC_RIGHT (ic);
9980
9981   /* if they are the same */
9982   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9983     return;
9984
9985   aopOp (right, ic, FALSE, FALSE);
9986
9987   emitcode (";", "genAssign: resultIsFar = %s",
9988             isOperandInFarSpace (result) ?
9989             "TRUE" : "FALSE");
9990
9991   /* special case both in far space */
9992   if ((AOP_TYPE (right) == AOP_DPTR ||
9993        AOP_TYPE (right) == AOP_DPTR2) &&
9994   /* IS_TRUE_SYMOP(result)       && */
9995       isOperandInFarSpace (result))
9996     {
9997       genFarFarAssign (result, right, ic);
9998       return;
9999     }
10000
10001   aopOp (result, ic, TRUE, FALSE);
10002
10003   /* if they are the same registers */
10004   if (sameRegs (AOP (right), AOP (result)))
10005     goto release;
10006
10007   /* if the result is a bit */
10008   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10009     {
10010       /* if the right size is a literal then
10011          we know what the value is */
10012       if (AOP_TYPE (right) == AOP_LIT)
10013         {
10014           if (((int) operandLitValue (right)))
10015             aopPut (AOP (result), one, 0);
10016           else
10017             aopPut (AOP (result), zero, 0);
10018           goto release;
10019         }
10020
10021       /* the right is also a bit variable */
10022       if (AOP_TYPE (right) == AOP_CRY)
10023         {
10024           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10025           aopPut (AOP (result), "c", 0);
10026           goto release;
10027         }
10028
10029       /* we need to or */
10030       toBoolean (right);
10031       aopPut (AOP (result), "a", 0);
10032       goto release;
10033     }
10034
10035   /* bit variables done */
10036   /* general case */
10037   size = AOP_SIZE (result);
10038   offset = 0;
10039   if (AOP_TYPE (right) == AOP_LIT)
10040     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10041
10042   if ((size > 1) &&
10043       (AOP_TYPE (result) != AOP_REG) &&
10044       (AOP_TYPE (right) == AOP_LIT) &&
10045       !IS_FLOAT (operandType (right)))
10046     {
10047       _startLazyDPSEvaluation ();
10048       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10049         {
10050           aopPut (AOP (result),
10051                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10052                   offset);
10053           offset++;
10054           size--;
10055         }
10056       /* And now fill the rest with zeros. */
10057       if (size)
10058         {
10059           emitcode ("clr", "a");
10060         }
10061       while (size--)
10062         {
10063           aopPut (AOP (result), "a", offset++);
10064         }
10065       _endLazyDPSEvaluation ();
10066     }
10067   else
10068     {
10069       _startLazyDPSEvaluation ();
10070       while (size--)
10071         {
10072           aopPut (AOP (result),
10073                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10074                   offset);
10075           offset++;
10076         }
10077       _endLazyDPSEvaluation ();
10078     }
10079
10080 release:
10081   freeAsmop (right, NULL, ic, FALSE);
10082   freeAsmop (result, NULL, ic, TRUE);
10083 }
10084
10085 /*-----------------------------------------------------------------*/
10086 /* genJumpTab - generates code for jump table                      */
10087 /*-----------------------------------------------------------------*/
10088 static void
10089 genJumpTab (iCode * ic)
10090 {
10091   symbol *jtab;
10092   char *l;
10093
10094   D (emitcode (";", "genJumpTab ");
10095     );
10096
10097   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10098   /* get the condition into accumulator */
10099   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10100   MOVA (l);
10101   /* multiply by four! */
10102   emitcode ("add", "a,acc");
10103   emitcode ("add", "a,acc");
10104   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10105
10106   jtab = newiTempLabel (NULL);
10107   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10108   emitcode ("jmp", "@a+dptr");
10109   emitcode ("", "%05d$:", jtab->key + 100);
10110   /* now generate the jump labels */
10111   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10112        jtab = setNextItem (IC_JTLABELS (ic)))
10113     emitcode ("ljmp", "%05d$", jtab->key + 100);
10114
10115 }
10116
10117 /*-----------------------------------------------------------------*/
10118 /* genCast - gen code for casting                                  */
10119 /*-----------------------------------------------------------------*/
10120 static void
10121 genCast (iCode * ic)
10122 {
10123   operand *result = IC_RESULT (ic);
10124   sym_link *ctype = operandType (IC_LEFT (ic));
10125   sym_link *rtype = operandType (IC_RIGHT (ic));
10126   operand *right = IC_RIGHT (ic);
10127   int size, offset;
10128
10129   D (emitcode (";", "genCast ");
10130     );
10131
10132   /* if they are equivalent then do nothing */
10133   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10134     return;
10135
10136   aopOp (right, ic, FALSE, FALSE);
10137   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10138
10139   /* if the result is a bit */
10140   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10141   if (IS_BITVAR(OP_SYMBOL(result)->type))
10142     {
10143       /* if the right size is a literal then
10144          we know what the value is */
10145       if (AOP_TYPE (right) == AOP_LIT)
10146         {
10147           if (((int) operandLitValue (right)))
10148             aopPut (AOP (result), one, 0);
10149           else
10150             aopPut (AOP (result), zero, 0);
10151
10152           goto release;
10153         }
10154
10155       /* the right is also a bit variable */
10156       if (AOP_TYPE (right) == AOP_CRY)
10157         {
10158           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10159           aopPut (AOP (result), "c", 0);
10160           goto release;
10161         }
10162
10163       /* we need to or */
10164       toBoolean (right);
10165       aopPut (AOP (result), "a", 0);
10166       goto release;
10167     }
10168
10169   /* if they are the same size : or less */
10170   if (AOP_SIZE (result) <= AOP_SIZE (right))
10171     {
10172
10173       /* if they are in the same place */
10174       if (sameRegs (AOP (right), AOP (result)))
10175         goto release;
10176
10177       /* if they in different places then copy */
10178       size = AOP_SIZE (result);
10179       offset = 0;
10180       _startLazyDPSEvaluation ();
10181       while (size--)
10182         {
10183           aopPut (AOP (result),
10184                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10185                   offset);
10186           offset++;
10187         }
10188       _endLazyDPSEvaluation ();
10189       goto release;
10190     }
10191
10192
10193   /* if the result is of type pointer */
10194   if (IS_PTR (ctype))
10195     {
10196
10197       int p_type;
10198       sym_link *type = operandType (right);
10199
10200       /* pointer to generic pointer */
10201       if (IS_GENPTR (ctype))
10202         {
10203           char *l = zero;
10204
10205           if (IS_PTR (type))
10206             {
10207               p_type = DCL_TYPE (type);
10208             }
10209           else
10210             {
10211 #if OLD_CAST_BEHAVIOR
10212               /* KV: we are converting a non-pointer type to
10213                * a generic pointer. This (ifdef'd out) code
10214                * says that the resulting generic pointer
10215                * should have the same class as the storage
10216                * location of the non-pointer variable.
10217                *
10218                * For example, converting an int (which happens
10219                * to be stored in DATA space) to a pointer results
10220                * in a DATA generic pointer; if the original int
10221                * in XDATA space, so will be the resulting pointer.
10222                *
10223                * I don't like that behavior, and thus this change:
10224                * all such conversions will be forced to XDATA and
10225                * throw a warning. If you want some non-XDATA
10226                * type, or you want to suppress the warning, you
10227                * must go through an intermediate cast, like so:
10228                *
10229                * char _generic *gp = (char _xdata *)(intVar);
10230                */
10231               sym_link *etype = getSpec (type);
10232
10233               /* we have to go by the storage class */
10234               if (SPEC_OCLS (etype) != generic)
10235                 {
10236                   p_type = PTR_TYPE (SPEC_OCLS (etype));
10237                 }
10238               else
10239 #endif
10240                 {
10241                   /* Converting unknown class (i.e. register variable)
10242                    * to generic pointer. This is not good, but
10243                    * we'll make a guess (and throw a warning).
10244                    */
10245                   p_type = FPOINTER;
10246                   werror (W_INT_TO_GEN_PTR_CAST);
10247                 }
10248             }
10249
10250           /* the first two bytes are known */
10251           size = GPTRSIZE - 1;
10252           offset = 0;
10253           _startLazyDPSEvaluation ();
10254           while (size--)
10255             {
10256               aopPut (AOP (result),
10257                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10258                       offset);
10259               offset++;
10260             }
10261           _endLazyDPSEvaluation ();
10262
10263           /* the last byte depending on type */
10264           switch (p_type)
10265             {
10266             case IPOINTER:
10267             case POINTER:
10268               l = zero;
10269               break;
10270             case FPOINTER:
10271               l = one;
10272               break;
10273             case CPOINTER:
10274               l = "#0x02";
10275               break;
10276             case PPOINTER:
10277               l = "#0x03";
10278               break;
10279
10280             default:
10281               /* this should never happen */
10282               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10283                       "got unknown pointer type");
10284               exit (1);
10285             }
10286           aopPut (AOP (result), l, GPTRSIZE - 1);
10287           goto release;
10288         }
10289
10290       /* just copy the pointers */
10291       size = AOP_SIZE (result);
10292       offset = 0;
10293       _startLazyDPSEvaluation ();
10294       while (size--)
10295         {
10296           aopPut (AOP (result),
10297                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10298                   offset);
10299           offset++;
10300         }
10301       _endLazyDPSEvaluation ();
10302       goto release;
10303     }
10304
10305   /* so we now know that the size of destination is greater
10306      than the size of the source */
10307   /* we move to result for the size of source */
10308   size = AOP_SIZE (right);
10309   offset = 0;
10310   _startLazyDPSEvaluation ();
10311   while (size--)
10312     {
10313       aopPut (AOP (result),
10314               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10315               offset);
10316       offset++;
10317     }
10318   _endLazyDPSEvaluation ();
10319
10320   /* now depending on the sign of the source && destination */
10321   size = AOP_SIZE (result) - AOP_SIZE (right);
10322   /* if unsigned or not an integral type */
10323   /* also, if the source is a bit, we don't need to sign extend, because
10324    * it can't possibly have set the sign bit.
10325    */
10326   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10327     {
10328       while (size--)
10329         {
10330           aopPut (AOP (result), zero, offset++);
10331         }
10332     }
10333   else
10334     {
10335       /* we need to extend the sign :{ */
10336       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10337                         FALSE, FALSE, TRUE);
10338       MOVA (l);
10339       emitcode ("rlc", "a");
10340       emitcode ("subb", "a,acc");
10341       while (size--)
10342         aopPut (AOP (result), "a", offset++);
10343     }
10344
10345   /* we are done hurray !!!! */
10346
10347 release:
10348   freeAsmop (right, NULL, ic, TRUE);
10349   freeAsmop (result, NULL, ic, TRUE);
10350
10351 }
10352
10353 /*-----------------------------------------------------------------*/
10354 /* genDjnz - generate decrement & jump if not zero instrucion      */
10355 /*-----------------------------------------------------------------*/
10356 static int
10357 genDjnz (iCode * ic, iCode * ifx)
10358 {
10359   symbol *lbl, *lbl1;
10360   if (!ifx)
10361     return 0;
10362
10363   /* if the if condition has a false label
10364      then we cannot save */
10365   if (IC_FALSE (ifx))
10366     return 0;
10367
10368   /* if the minus is not of the form
10369      a = a - 1 */
10370   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10371       !IS_OP_LITERAL (IC_RIGHT (ic)))
10372     return 0;
10373
10374   if (operandLitValue (IC_RIGHT (ic)) != 1)
10375     return 0;
10376
10377   /* if the size of this greater than one then no
10378      saving */
10379   if (getSize (operandType (IC_RESULT (ic))) > 1)
10380     return 0;
10381
10382   /* otherwise we can save BIG */
10383   D(emitcode(";", "genDjnz"););
10384
10385   lbl = newiTempLabel (NULL);
10386   lbl1 = newiTempLabel (NULL);
10387
10388   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10389
10390   if (AOP_NEEDSACC(IC_RESULT(ic)))
10391   {
10392       /* If the result is accessed indirectly via
10393        * the accumulator, we must explicitly write
10394        * it back after the decrement.
10395        */
10396       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10397       
10398       if (strcmp(rByte, "a"))
10399       {
10400            /* Something is hopelessly wrong */
10401            fprintf(stderr, "*** warning: internal error at %s:%d\n",
10402                    __FILE__, __LINE__);
10403            /* We can just give up; the generated code will be inefficient,
10404             * but what the hey.
10405             */
10406            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10407            return 0;
10408       }
10409       emitcode ("dec", "%s", rByte);
10410       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10411       emitcode ("jnz", "%05d$", lbl->key + 100);
10412   }
10413   else if (IS_AOP_PREG (IC_RESULT (ic)))
10414     {
10415       emitcode ("dec", "%s",
10416                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10417       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10418       emitcode ("jnz", "%05d$", lbl->key + 100);
10419     }
10420   else
10421     {
10422       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10423                 lbl->key + 100);
10424     }
10425   emitcode ("sjmp", "%05d$", lbl1->key + 100);
10426   emitcode ("", "%05d$:", lbl->key + 100);
10427   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10428   emitcode ("", "%05d$:", lbl1->key + 100);
10429
10430   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10431   ifx->generated = 1;
10432   return 1;
10433 }
10434
10435 /*-----------------------------------------------------------------*/
10436 /* genReceive - generate code for a receive iCode                  */
10437 /*-----------------------------------------------------------------*/
10438 static void
10439 genReceive (iCode * ic)
10440 {
10441
10442   D (emitcode (";", "genReceive ");
10443     );
10444
10445   if (isOperandInFarSpace (IC_RESULT (ic)) &&
10446       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10447        IS_TRUE_SYMOP (IC_RESULT (ic))))
10448     {
10449       int size = getSize (operandType (IC_RESULT (ic)));
10450       int offset = fReturnSizeDS390 - size;
10451       while (size--)
10452         {
10453           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10454                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10455           offset++;
10456         }
10457       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10458       size = AOP_SIZE (IC_RESULT (ic));
10459       offset = 0;
10460       while (size--)
10461         {
10462           emitcode ("pop", "acc");
10463           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10464         }
10465
10466     }
10467   else
10468     {
10469       _G.accInUse++;
10470       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10471       _G.accInUse--;
10472       assignResultValue (IC_RESULT (ic));
10473     }
10474
10475   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10476 }
10477
10478 /*-----------------------------------------------------------------*/
10479 /* gen390Code - generate code for Dallas 390 based controllers     */
10480 /*-----------------------------------------------------------------*/
10481 void
10482 gen390Code (iCode * lic)
10483 {
10484   iCode *ic;
10485   int cln = 0;
10486
10487   lineHead = lineCurr = NULL;
10488
10489   if (options.model == MODEL_FLAT24) {
10490     fReturnSizeDS390 = 5;
10491     fReturn = fReturn24;
10492   } else {
10493     fReturnSizeDS390 = 4;
10494     fReturn = fReturn16;
10495     options.stack10bit=0;
10496   }
10497 #if 0
10498   //REMOVE ME!!!
10499   /* print the allocation information */
10500   if (allocInfo)
10501     printAllocInfo (currFunc, codeOutFile);
10502 #endif
10503   /* if debug information required */
10504   if (options.debug && currFunc)
10505     {
10506       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10507       _G.debugLine = 1;
10508       if (IS_STATIC (currFunc->etype))
10509         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10510       else
10511         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10512       _G.debugLine = 0;
10513     }
10514   /* stack pointer name */
10515   if (options.useXstack)
10516     spname = "_spx";
10517   else
10518     spname = "sp";
10519
10520
10521   for (ic = lic; ic; ic = ic->next)
10522     {
10523
10524       if (cln != ic->lineno)
10525         {
10526           if (options.debug)
10527             {
10528               _G.debugLine = 1;
10529               emitcode ("", "C$%s$%d$%d$%d ==.",
10530                         FileBaseName (ic->filename), ic->lineno,
10531                         ic->level, ic->block);
10532               _G.debugLine = 0;
10533             }
10534           emitcode (";", "%s %d", ic->filename, ic->lineno);
10535           cln = ic->lineno;
10536         }
10537       /* if the result is marked as
10538          spilt and rematerializable or code for
10539          this has already been generated then
10540          do nothing */
10541       if (resultRemat (ic) || ic->generated)
10542         continue;
10543
10544       /* depending on the operation */
10545       switch (ic->op)
10546         {
10547         case '!':
10548           genNot (ic);
10549           break;
10550
10551         case '~':
10552           genCpl (ic);
10553           break;
10554
10555         case UNARYMINUS:
10556           genUminus (ic);
10557           break;
10558
10559         case IPUSH:
10560           genIpush (ic);
10561           break;
10562
10563         case IPOP:
10564           /* IPOP happens only when trying to restore a
10565              spilt live range, if there is an ifx statement
10566              following this pop then the if statement might
10567              be using some of the registers being popped which
10568              would destory the contents of the register so
10569              we need to check for this condition and handle it */
10570           if (ic->next &&
10571               ic->next->op == IFX &&
10572               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10573             genIfx (ic->next, ic);
10574           else
10575             genIpop (ic);
10576           break;
10577
10578         case CALL:
10579           genCall (ic);
10580           break;
10581
10582         case PCALL:
10583           genPcall (ic);
10584           break;
10585
10586         case FUNCTION:
10587           genFunction (ic);
10588           break;
10589
10590         case ENDFUNCTION:
10591           genEndFunction (ic);
10592           break;
10593
10594         case RETURN:
10595           genRet (ic);
10596           break;
10597
10598         case LABEL:
10599           genLabel (ic);
10600           break;
10601
10602         case GOTO:
10603           genGoto (ic);
10604           break;
10605
10606         case '+':
10607           genPlus (ic);
10608           break;
10609
10610         case '-':
10611           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10612             genMinus (ic);
10613           break;
10614
10615         case '*':
10616           genMult (ic);
10617           break;
10618
10619         case '/':
10620           genDiv (ic);
10621           break;
10622
10623         case '%':
10624           genMod (ic);
10625           break;
10626
10627         case '>':
10628           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10629           break;
10630
10631         case '<':
10632           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10633           break;
10634
10635         case LE_OP:
10636         case GE_OP:
10637         case NE_OP:
10638
10639           /* note these two are xlated by algebraic equivalence
10640              during parsing SDCC.y */
10641           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10642                   "got '>=' or '<=' shouldn't have come here");
10643           break;
10644
10645         case EQ_OP:
10646           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10647           break;
10648
10649         case AND_OP:
10650           genAndOp (ic);
10651           break;
10652
10653         case OR_OP:
10654           genOrOp (ic);
10655           break;
10656
10657         case '^':
10658           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10659           break;
10660
10661         case '|':
10662           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10663           break;
10664
10665         case BITWISEAND:
10666           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10667           break;
10668
10669         case INLINEASM:
10670           genInline (ic);
10671           break;
10672
10673         case RRC:
10674           genRRC (ic);
10675           break;
10676
10677         case RLC:
10678           genRLC (ic);
10679           break;
10680
10681         case GETHBIT:
10682           genGetHbit (ic);
10683           break;
10684
10685         case LEFT_OP:
10686           genLeftShift (ic);
10687           break;
10688
10689         case RIGHT_OP:
10690           genRightShift (ic);
10691           break;
10692
10693         case GET_VALUE_AT_ADDRESS:
10694           genPointerGet (ic);
10695           break;
10696
10697         case '=':
10698           if (POINTER_SET (ic))
10699             genPointerSet (ic);
10700           else
10701             genAssign (ic);
10702           break;
10703
10704         case IFX:
10705           genIfx (ic, NULL);
10706           break;
10707
10708         case ADDRESS_OF:
10709           genAddrOf (ic);
10710           break;
10711
10712         case JUMPTABLE:
10713           genJumpTab (ic);
10714           break;
10715
10716         case CAST:
10717           genCast (ic);
10718           break;
10719
10720         case RECEIVE:
10721           genReceive (ic);
10722           break;
10723
10724         case SEND:
10725           addSet (&_G.sendSet, ic);
10726           break;
10727
10728         case ARRAYINIT:
10729             genArrayInit(ic);
10730             break;
10731             
10732         default:
10733           ic = ic;
10734         }
10735     }
10736
10737
10738   /* now we are ready to call the
10739      peep hole optimizer */
10740   if (!options.nopeep)
10741     peepHole (&lineHead);
10742
10743   /* now do the actual printing */
10744   printLine (lineHead, codeOutFile);
10745   return;
10746 }