d4a79b53236193c7f5fb1e170c4408a755f27514
[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 #define BETTER_LITERAL_SHIFT
40
41 char *aopLiteral (value * val, int offset);
42 extern int allocInfo;
43
44 /* this is the down and dirty file with all kinds of
45    kludgy & hacky stuff. This is what it is all about
46    CODE GENERATION for a specific MCU . some of the
47    routines may be reusable, will have to see */
48
49 static char *zero = "#0";
50 static char *one = "#1";
51 static char *spname;
52
53 #define D(x) x
54
55 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
56 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
57
58 unsigned fReturnSizeDS390 = 5;  /* shared with ralloc.c */
59 static char *fReturn24[] =
60 {"dpl", "dph", "dpx", "b", "a"};
61 static char *fReturn16[] =
62 {"dpl", "dph", "b", "a"};
63 static char **fReturn = fReturn24;
64 static char *accUse[] =
65 {"a", "b"};
66 static char *dptrn[2][3];
67 static char *javaRet[] = { "r0","r1","r2","r3"};
68 static short rbank = -1;
69
70 static struct
71   {
72     short r0Pushed;
73     short r1Pushed;
74     short accInUse;
75     short bInUse;
76     short inLine;
77     short debugLine;
78     short nRegsSaved;
79     short dptrInUse;
80     short dptr1InUse;
81     set *sendSet;
82   }
83 _G;
84
85 static char *rb1regs[] = {
86     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
87 };
88
89 static void saveRBank (int, iCode *, bool);
90
91 #define RESULTONSTACK(x) \
92                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
93                          IC_RESULT(x)->aop->type == AOP_STK )
94
95 #define MOVA(x) _movA(x)
96 #define MOVB(x) _movB(x)
97                 
98 #define CLRC    emitcode("clr","c")
99 #define SETC    emitcode("setb","c")
100
101 // A scratch register which will be used to hold
102 // result bytes from operands in far space via DPTR2.
103 #define DP2_RESULT_REG  "_ap"
104
105 static lineNode *lineHead = NULL;
106 static lineNode *lineCurr = NULL;
107
108 static unsigned char SLMask[] =
109 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
110  0xE0, 0xC0, 0x80, 0x00};
111 static unsigned char SRMask[] =
112 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
113  0x07, 0x03, 0x01, 0x00};
114
115 #define LSB     0
116 #define MSB16   1
117 #define MSB24   2
118 #define MSB32   3
119 #define PROTECT_SP      {if (options.protect_sp_update) {                       \
120                                 symbol *lbl = newiTempLabel(NULL);              \
121                                 emitcode ("setb","F1");                         \
122                                 emitcode ("jbc","EA,!tlabel",lbl->key+100);     \
123                                 emitcode ("clr","F1");                          \
124                                 emitcode ("","!tlabeldef",lbl->key+100);        \
125                         }}
126 #define UNPROTECT_SP    { if (options.protect_sp_update) {                      \
127                                 symbol *lbl = newiTempLabel(NULL);              \
128                                 emitcode ("jnb","F1,!tlabel",lbl->key+100);     \
129                                 emitcode ("setb","EA");                         \
130                                 emitcode ("","!tlabeldef",lbl->key+100);        \
131                         }}
132
133
134 /*-----------------------------------------------------------------*/
135 /* emitcode - writes the code into a file : for now it is simple    */
136 /*-----------------------------------------------------------------*/
137 static void
138 emitcode (char *inst, char *fmt,...)
139 {
140     va_list ap;
141     char lb[INITIAL_INLINEASM];
142     char *lbp = lb;
143     
144     va_start (ap, fmt);
145     
146     if (inst && *inst)
147     {
148         if (fmt && *fmt)
149         {
150             SNPRINTF (lb, sizeof(lb), "%s\t", inst);
151         }
152         else
153         {
154             SNPRINTF (lb, sizeof(lb), "%s", inst);
155         }
156         
157         tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), 
158                    fmt, ap);
159     }
160     else
161     {
162         tvsprintf (lb, sizeof(lb), fmt, ap);
163     }
164     
165
166     while (isspace (*lbp))
167     {
168         lbp++;
169     }
170
171     if (lbp && *lbp)
172     {
173         lineCurr = (lineCurr ?
174                     connectLine (lineCurr, newLineNode (lb)) :
175                     (lineHead = newLineNode (lb)));
176     }
177     
178     lineCurr->isInline = _G.inLine;
179     lineCurr->isDebug = _G.debugLine;
180     va_end (ap);
181 }
182
183 //
184 // Move the passed value into A unless it is already there.
185 // 
186 static void
187 _movA(const char *s)
188 {
189     if (strcmp(s,"a") && strcmp(s,"acc"))
190     { 
191         emitcode("mov","a,%s",s);
192     } 
193 }
194
195 //
196 // Move the passed value into B unless it is already there.
197 // 
198 static void
199 _movB(const char *s)
200 {
201     if (strcmp(s,"b"))
202     { 
203         emitcode("mov","b,%s",s);
204     } 
205 }
206
207 /*-----------------------------------------------------------------*/
208 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
209 /*-----------------------------------------------------------------*/
210 static regs *
211 getFreePtr (iCode * ic, asmop ** aopp, bool result)
212 {
213   bool r0iu, r1iu;
214   bool r0ou, r1ou;
215
216   /* the logic: if r0 & r1 used in the instruction
217      then we are in trouble otherwise */
218
219   /* first check if r0 & r1 are used by this
220      instruction, in which case we are in trouble */
221   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
222   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
223   if (r0iu && r1iu) {
224       goto endOfWorld;
225     }
226
227   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
228   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
229
230   /* if no usage of r0 then return it */
231   if (!r0iu && !r0ou)
232     {
233       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
234       (*aopp)->type = AOP_R0;
235
236       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
237     }
238
239   /* if no usage of r1 then return it */
240   if (!r1iu && !r1ou)
241     {
242       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
243       (*aopp)->type = AOP_R1;
244
245       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
246     }
247
248   /* now we know they both have usage */
249   /* if r0 not used in this instruction */
250   if (!r0iu)
251     {
252       /* push it if not already pushed */
253       if (!_G.r0Pushed)
254         {
255           emitcode ("push", "%s",
256                     ds390_regWithIdx (R0_IDX)->dname);
257           _G.r0Pushed++;
258         }
259
260       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
261       (*aopp)->type = AOP_R0;
262
263       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
264     }
265
266   /* if r1 not used then */
267
268   if (!r1iu)
269     {
270       /* push it if not already pushed */
271       if (!_G.r1Pushed)
272         {
273           emitcode ("push", "%s",
274                     ds390_regWithIdx (R1_IDX)->dname);
275           _G.r1Pushed++;
276         }
277
278       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
279       (*aopp)->type = AOP_R1;
280       return ds390_regWithIdx (R1_IDX);
281     }
282
283 endOfWorld:
284   /* I said end of world but not quite end of world yet */
285   /* if this is a result then we can push it on the stack */
286   if (result)
287     {
288       (*aopp)->type = AOP_STK;
289       return NULL;
290     }
291
292   /* other wise this is true end of the world */
293   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
294           "getFreePtr should never reach here");
295   exit (1);
296     
297   return NULL; // notreached, but makes compiler happy.
298 }
299
300 /*-----------------------------------------------------------------*/
301 /* newAsmop - creates a new asmOp                                  */
302 /*-----------------------------------------------------------------*/
303 static asmop *
304 newAsmop (short type)
305 {
306   asmop *aop;
307
308   aop = Safe_calloc (1, sizeof (asmop));
309   aop->type = type;
310   return aop;
311 }
312
313 static int _currentDPS;         /* Current processor DPS. */
314 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
315 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
316
317 /*-----------------------------------------------------------------*/
318 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
319 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
320 /* alternate DPTR (DPL1/DPH1/DPX1).          */
321 /*-----------------------------------------------------------------*/
322 static void
323 genSetDPTR (int n)
324 {
325
326   /* If we are doing lazy evaluation, simply note the desired
327    * change, but don't emit any code yet.
328    */
329   if (_lazyDPS)
330     {
331       _desiredDPS = n;
332       return;
333     }
334
335   if (!n)
336     {
337       emitcode ("mov", "dps,#0");
338     }
339   else
340     {
341       TR_DPTR("#1");
342       emitcode ("mov", "dps,#1");
343     }
344 }
345
346 /*-----------------------------------------------------------------*/
347 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
348 /*                   */
349 /* Any code that operates on DPTR (NB: not on the individual     */
350 /* components, like DPH) *must* call _flushLazyDPS() before using  */
351 /* DPTR within a lazy DPS evaluation block.        */
352 /*                   */
353 /* Note that aopPut and aopGet already contain the proper calls to */
354 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
355 /* DPS evaluation block.             */
356 /*                   */
357 /* Also, _flushLazyDPS must be called before any flow control      */
358 /* operations that could potentially branch out of the block.    */
359 /*                         */
360 /* Lazy DPS evaluation is simply an optimization (though an      */
361 /* important one), so if in doubt, leave it out.       */
362 /*-----------------------------------------------------------------*/
363 static void
364 _startLazyDPSEvaluation (void)
365 {
366   _currentDPS = 0;
367   _desiredDPS = 0;
368 #ifdef BETTER_LITERAL_SHIFT  
369   _lazyDPS++;
370 #else
371   _lazyDPS = 1;
372 #endif  
373 }
374
375 /*-----------------------------------------------------------------*/
376 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
377 /* desired one. Call before using DPTR within a lazy DPS evaluation */
378 /* block.                */
379 /*-----------------------------------------------------------------*/
380 static void
381 _flushLazyDPS (void)
382 {
383   if (!_lazyDPS)
384     {
385       /* nothing to do. */
386       return;
387     }
388
389   if (_desiredDPS != _currentDPS)
390     {
391       if (_desiredDPS)
392         {
393           emitcode ("inc", "dps");
394         }
395       else
396         {
397           emitcode ("dec", "dps");
398         }
399       _currentDPS = _desiredDPS;
400     }
401 }
402
403 /*-----------------------------------------------------------------*/
404 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
405 /*                   */
406 /* Forces us back to the safe state (standard DPTR selected).    */
407 /*-----------------------------------------------------------------*/
408 static void
409 _endLazyDPSEvaluation (void)
410 {
411 #ifdef BETTER_LITERAL_SHIFT  
412   _lazyDPS--;
413 #else
414   _lazyDPS = 0;
415 #endif    
416   if (!_lazyDPS)
417   {
418     if (_currentDPS)
419     {
420       genSetDPTR (0);
421       _flushLazyDPS ();
422     }
423     _currentDPS = 0;
424     _desiredDPS = 0;
425   }
426 }
427
428
429
430 /*-----------------------------------------------------------------*/
431 /* pointerCode - returns the code for a pointer type               */
432 /*-----------------------------------------------------------------*/
433 static int
434 pointerCode (sym_link * etype)
435 {
436
437   return PTR_TYPE (SPEC_OCLS (etype));
438
439 }
440
441 /*-----------------------------------------------------------------*/
442 /* aopForSym - for a true symbol                                   */
443 /*-----------------------------------------------------------------*/
444 static asmop *
445 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
446 {
447   asmop *aop;
448   memmap *space = SPEC_OCLS (sym->etype);
449
450   /* if already has one */
451   if (sym->aop)
452     return sym->aop;
453
454   /* assign depending on the storage class */
455   /* if it is on the stack or indirectly addressable */
456   /* space we need to assign either r0 or r1 to it   */
457   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
458     {
459       sym->aop = aop = newAsmop (0);
460       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
461       aop->size = getSize (sym->type);
462
463       /* now assign the address of the variable to
464          the pointer register */
465       if (aop->type != AOP_STK)
466         {
467
468           if (sym->onStack)
469             {
470               if (_G.accInUse)
471                 emitcode ("push", "acc");
472
473               if (_G.bInUse)
474                 emitcode ("push", "b");
475
476               emitcode ("mov", "a,_bp");
477               emitcode ("add", "a,#!constbyte",
478                         ((sym->stack < 0) ?
479                          ((char) (sym->stack - _G.nRegsSaved)) :
480                          ((char) sym->stack)) & 0xff);
481               emitcode ("mov", "%s,a",
482                         aop->aopu.aop_ptr->name);
483
484               if (_G.bInUse)
485                 emitcode ("pop", "b");
486
487               if (_G.accInUse)
488                 emitcode ("pop", "acc");
489             }
490           else
491             emitcode ("mov", "%s,#%s",
492                       aop->aopu.aop_ptr->name,
493                       sym->rname);
494           aop->paged = space->paged;
495         }
496       else
497         aop->aopu.aop_stk = sym->stack;
498       return aop;
499     }
500
501   if (sym->onStack && options.stack10bit)
502     {
503         short stack_val = -((sym->stack < 0) ?
504                             ((short) (sym->stack - _G.nRegsSaved)) :
505                             ((short) sym->stack)) ;
506         if (useDP2 && _G.dptr1InUse) {
507             emitcode ("push","dpl1");
508             emitcode ("push","dph1");
509             emitcode ("push","dpx1");
510         } else if (_G.dptrInUse ) {
511             emitcode ("push","dpl");
512             emitcode ("push","dph");
513             emitcode ("push","dpx");
514         }
515       /* It's on the 10 bit stack, which is located in
516        * far data space.
517        */           
518         if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
519             if (useDP2) {
520                 if (options.model == MODEL_FLAT24)
521                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
522                 TR_DPTR("#2");
523                 emitcode ("mov", "dph1,_bpx+1");
524                 emitcode ("mov", "dpl1,_bpx");
525                 emitcode ("mov","dps,#1");
526             } else {
527                 if (options.model == MODEL_FLAT24)
528                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
529                 emitcode ("mov", "dph,_bpx+1");
530                 emitcode ("mov", "dpl,_bpx");
531             }
532             stack_val = -stack_val;
533             while (stack_val--) {
534                 emitcode ("inc","dptr");
535             }
536             if (useDP2) {
537                 emitcode("mov","dps,#0");
538             }
539         }  else {
540             if (_G.accInUse)
541                 emitcode ("push", "acc");
542             
543             if (_G.bInUse)
544                 emitcode ("push", "b");
545         
546             emitcode ("mov", "a,_bpx");
547             emitcode ("clr","c");
548             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
549             emitcode ("mov","b,a");
550             emitcode ("mov","a,_bpx+1");
551             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
552             if (useDP2) {
553                 if (options.model == MODEL_FLAT24)
554                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
555                 TR_DPTR("#2");
556                 emitcode ("mov", "dph1,a");
557                 emitcode ("mov", "dpl1,b");
558             } else {
559                 if (options.model == MODEL_FLAT24)
560                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
561                 emitcode ("mov", "dph,a");
562                 emitcode ("mov", "dpl,b");
563             }
564             
565             if (_G.bInUse)
566                 emitcode ("pop", "b");
567             
568             if (_G.accInUse)
569                 emitcode ("pop", "acc");
570         }
571         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
572         aop->size = getSize (sym->type);
573         return aop;
574     }
575
576   /* if in bit space */
577   if (IN_BITSPACE (space))
578     {
579       sym->aop = aop = newAsmop (AOP_CRY);
580       aop->aopu.aop_dir = sym->rname;
581       aop->size = getSize (sym->type);
582       return aop;
583     }
584   /* if it is in direct space */
585   if (IN_DIRSPACE (space))
586     {
587       sym->aop = aop = newAsmop (AOP_DIR);
588       aop->aopu.aop_dir = sym->rname;
589       aop->size = getSize (sym->type);
590       return aop;
591     }
592
593   /* special case for a function */
594   if (IS_FUNC (sym->type))
595     {
596       sym->aop = aop = newAsmop (AOP_IMMD);
597       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);   
598       aop->size = FPTRSIZE;
599       return aop;
600     }
601   
602   /* only remaining is far space */
603   /* in which case DPTR gets the address */
604   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
605   if (useDP2)
606     {
607       genSetDPTR (1);
608       _flushLazyDPS ();
609       emitcode ("mov", "dptr,#%s", sym->rname);
610       genSetDPTR (0);
611     }
612   else
613     {
614       emitcode ("mov", "dptr,#%s", sym->rname);
615     }
616   aop->size = getSize (sym->type);
617
618   /* if it is in code space */
619   if (IN_CODESPACE (space))
620     aop->code = 1;
621
622   return aop;
623 }
624
625 /*-----------------------------------------------------------------*/
626 /* aopForRemat - rematerialzes an object                           */
627 /*-----------------------------------------------------------------*/
628 static asmop *
629 aopForRemat (symbol * sym)
630 {
631   iCode *ic = sym->rematiCode;
632   asmop *aop = newAsmop (AOP_IMMD);
633   int ptr_type =0;
634   int val = 0;
635
636   for (;;)
637     {
638       if (ic->op == '+')
639         val += (int) operandLitValue (IC_RIGHT (ic));
640       else if (ic->op == '-')
641         val -= (int) operandLitValue (IC_RIGHT (ic));
642       else if (IS_CAST_ICODE(ic)) {
643               sym_link *from_type = operandType(IC_RIGHT(ic));
644               aop->aopu.aop_immd.from_cast_remat = 1;
645               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
646               ptr_type = DCL_TYPE(from_type);
647               if (ptr_type == IPOINTER) {
648                 // bug #481053
649                 ptr_type = POINTER;
650               }
651               continue ;
652       } else break;
653       
654       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
655     }
656
657   if (val)
658   {
659       SNPRINTF (buffer, sizeof(buffer),
660                 "(%s %c 0x%04x)",
661                 OP_SYMBOL (IC_LEFT (ic))->rname,
662                 val >= 0 ? '+' : '-',
663                 abs (val) & 0xffffff);
664   }
665   else 
666   {
667       if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
668       {
669           SNPRINTF(buffer, sizeof(buffer), 
670                    "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
671       }
672       else
673       {
674           strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
675       }
676   }
677
678   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);  
679   /* set immd2 field if required */
680   if (aop->aopu.aop_immd.from_cast_remat) 
681   {
682       tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
683       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
684   }
685
686   return aop;
687 }
688
689 /*-----------------------------------------------------------------*/
690 /* aopHasRegs - returns true if aop has regs between from-to       */
691 /*-----------------------------------------------------------------*/
692 static int aopHasRegs(asmop *aop, int from, int to)
693 {
694     int size =0;
695
696     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
697
698     for (; size < aop->size ; size++) {
699         int reg;
700         for (reg = from ; reg <= to ; reg++)
701             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
702     }
703     return 0;
704 }
705
706 /*-----------------------------------------------------------------*/
707 /* regsInCommon - two operands have some registers in common       */
708 /*-----------------------------------------------------------------*/
709 static bool
710 regsInCommon (operand * op1, operand * op2)
711 {
712   symbol *sym1, *sym2;
713   int i;
714
715   /* if they have registers in common */
716   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
717     return FALSE;
718
719   sym1 = OP_SYMBOL (op1);
720   sym2 = OP_SYMBOL (op2);
721
722   if (sym1->nRegs == 0 || sym2->nRegs == 0)
723     return FALSE;
724
725   for (i = 0; i < sym1->nRegs; i++)
726     {
727       int j;
728       if (!sym1->regs[i])
729         continue;
730
731       for (j = 0; j < sym2->nRegs; j++)
732         {
733           if (!sym2->regs[j])
734             continue;
735
736           if (sym2->regs[j] == sym1->regs[i])
737             return TRUE;
738         }
739     }
740
741   return FALSE;
742 }
743
744 /*-----------------------------------------------------------------*/
745 /* operandsEqu - equivalent                                        */
746 /*-----------------------------------------------------------------*/
747 static bool
748 operandsEqu (operand * op1, operand * op2)
749 {
750   symbol *sym1, *sym2;
751
752   /* if they not symbols */
753   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
754     return FALSE;
755
756   sym1 = OP_SYMBOL (op1);
757   sym2 = OP_SYMBOL (op2);
758
759   /* if both are itemps & one is spilt
760      and the other is not then false */
761   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
762       sym1->isspilt != sym2->isspilt)
763     return FALSE;
764
765   /* if they are the same */
766   if (sym1 == sym2)
767     return TRUE;
768
769   if (strcmp (sym1->rname, sym2->rname) == 0)
770     return TRUE;
771
772
773   /* if left is a tmp & right is not */
774   if (IS_ITEMP (op1) &&
775       !IS_ITEMP (op2) &&
776       sym1->isspilt &&
777       (sym1->usl.spillLoc == sym2))
778     return TRUE;
779
780   if (IS_ITEMP (op2) &&
781       !IS_ITEMP (op1) &&
782       sym2->isspilt &&
783       sym1->level > 0 &&
784       (sym2->usl.spillLoc == sym1))
785     return TRUE;
786
787   return FALSE;
788 }
789
790 /*-----------------------------------------------------------------*/
791 /* sameRegs - two asmops have the same registers                   */
792 /*-----------------------------------------------------------------*/
793 static bool
794 sameRegs (asmop * aop1, asmop * aop2)
795 {
796   int i;
797
798   if (aop1 == aop2)
799     {
800       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
801         {
802           return FALSE;
803         }
804       return TRUE;
805     }
806
807   if (aop1->type != AOP_REG ||
808       aop2->type != AOP_REG)
809     return FALSE;
810
811   if (aop1->size != aop2->size)
812     return FALSE;
813
814   for (i = 0; i < aop1->size; i++)
815     if (aop1->aopu.aop_reg[i] !=
816         aop2->aopu.aop_reg[i])
817       return FALSE;
818
819   return TRUE;
820 }
821
822 /*-----------------------------------------------------------------*/
823 /* aopOp - allocates an asmop for an operand  :                    */
824 /*-----------------------------------------------------------------*/
825 static void
826 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
827 {
828   asmop *aop;
829   symbol *sym;
830   int i;
831
832   if (!op)
833     return;
834
835   /* if this a literal */
836   if (IS_OP_LITERAL (op))
837     {
838       op->aop = aop = newAsmop (AOP_LIT);
839       aop->aopu.aop_lit = op->operand.valOperand;
840       aop->size = getSize (operandType (op));
841       return;
842     }
843
844   /* if already has a asmop then continue */
845   if (op->aop)
846     return;
847
848   /* if the underlying symbol has a aop */
849   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
850     {
851       op->aop = OP_SYMBOL (op)->aop;
852       return;
853     }
854
855   /* if this is a true symbol */
856   if (IS_TRUE_SYMOP (op))
857     {
858       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
859       return;
860     }
861
862   /* this is a temporary : this has
863      only four choices :
864      a) register
865      b) spillocation
866      c) rematerialize
867      d) conditional
868      e) can be a return use only */
869
870   sym = OP_SYMBOL (op);
871
872
873   /* if the type is a conditional */
874   if (sym->regType == REG_CND)
875     {
876       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
877       aop->size = 0;
878       return;
879     }
880
881   /* if it is spilt then two situations
882      a) is rematerialize
883      b) has a spill location */
884   if (sym->isspilt || sym->nRegs == 0)
885     {
886
887       /* rematerialize it NOW */
888       if (sym->remat)
889         {
890           sym->aop = op->aop = aop =
891             aopForRemat (sym);
892           aop->size = getSize (sym->type);
893           return;
894         }
895
896       if (sym->accuse)
897         {
898           int i;
899           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
900           aop->size = getSize (sym->type);
901           for (i = 0; i < 2; i++)
902             aop->aopu.aop_str[i] = accUse[i];
903           return;
904         }
905
906       if (sym->ruonly)
907         {
908           int i;
909
910           if (useDP2)
911             {
912               /* a AOP_STR uses DPTR, but DPTR is already in use;
913                * we're just hosed.
914                */
915                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
916             }
917
918           aop = op->aop = sym->aop = newAsmop (AOP_STR);
919           aop->size = getSize (sym->type);
920           for (i = 0; i < (int) fReturnSizeDS390; i++)
921             aop->aopu.aop_str[i] = fReturn[i];
922           return;
923         }
924       
925       if (sym->dptr) { /* has been allocated to a DPTRn */
926           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
927           aop->size = getSize (sym->type);
928           aop->aopu.dptr = sym->dptr;
929           return ;
930       }
931       /* else spill location  */
932       if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
933           /* force a new aop if sizes differ */
934           sym->usl.spillLoc->aop = NULL;
935       }
936       sym->aop = op->aop = aop =
937         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
938       aop->size = getSize (sym->type);
939       return;
940     }
941
942   /* must be in a register */
943   sym->aop = op->aop = aop = newAsmop (AOP_REG);
944   aop->size = sym->nRegs;
945   for (i = 0; i < sym->nRegs; i++)
946     aop->aopu.aop_reg[i] = sym->regs[i];
947 }
948
949 /*-----------------------------------------------------------------*/
950 /* freeAsmop - free up the asmop given to an operand               */
951 /*----------------------------------------------------------------*/
952 static void
953 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
954 {
955   asmop *aop;
956
957   if (!op)
958     aop = aaop;
959   else
960     aop = op->aop;
961
962   if (!aop)
963     return;
964
965   if (aop->freed)
966     goto dealloc;
967
968   aop->freed = 1;
969
970   /* depending on the asmop type only three cases need work AOP_RO
971      , AOP_R1 && AOP_STK */
972   switch (aop->type)
973     {
974     case AOP_R0:
975       if (_G.r0Pushed)
976         {
977           if (pop)
978             {
979               emitcode ("pop", "ar0");
980               _G.r0Pushed--;
981             }
982         }
983       bitVectUnSetBit (ic->rUsed, R0_IDX);
984       break;
985
986     case AOP_R1:
987       if (_G.r1Pushed)
988         {
989           if (pop)
990             {
991               emitcode ("pop", "ar1");
992               _G.r1Pushed--;
993             }
994         }
995       bitVectUnSetBit (ic->rUsed, R1_IDX);
996       break;
997
998     case AOP_STK:
999       {
1000         int sz = aop->size;
1001         int stk = aop->aopu.aop_stk + aop->size;
1002         bitVectUnSetBit (ic->rUsed, R0_IDX);
1003         bitVectUnSetBit (ic->rUsed, R1_IDX);
1004
1005         getFreePtr (ic, &aop, FALSE);
1006
1007         if (options.stack10bit)
1008           {
1009             /* I'm not sure what to do here yet... */
1010             /* #STUB */
1011             fprintf (stderr,
1012                      "*** Warning: probably generating bad code for "
1013                      "10 bit stack mode.\n");
1014           }
1015
1016         if (stk)
1017           {
1018             emitcode ("mov", "a,_bp");
1019             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1020             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1021           }
1022         else
1023           {
1024             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1025           }
1026
1027         while (sz--)
1028           {
1029             emitcode ("pop", "acc");
1030             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1031             if (!sz)
1032               break;
1033             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1034           }
1035         op->aop = aop;
1036         freeAsmop (op, NULL, ic, TRUE);
1037         if (_G.r0Pushed)
1038           {
1039             emitcode ("pop", "ar0");
1040             _G.r0Pushed--;
1041           }
1042
1043         if (_G.r1Pushed)
1044           {
1045             emitcode ("pop", "ar1");
1046             _G.r1Pushed--;
1047           }
1048       }
1049     case AOP_DPTR2:
1050         if (_G.dptr1InUse) {
1051             emitcode ("pop","dpx1");
1052             emitcode ("pop","dph1");
1053             emitcode ("pop","dpl1");
1054         }
1055         break;
1056     case AOP_DPTR:
1057         if (_G.dptrInUse) {
1058             emitcode ("pop","dpx");
1059             emitcode ("pop","dph");
1060             emitcode ("pop","dpl");
1061         }
1062         break;
1063     }
1064 dealloc:
1065   /* all other cases just dealloc */
1066   if (op)
1067     {
1068       op->aop = NULL;
1069       if (IS_SYMOP (op))
1070         {
1071           OP_SYMBOL (op)->aop = NULL;
1072           /* if the symbol has a spill */
1073           if (SPIL_LOC (op))
1074             SPIL_LOC (op)->aop = NULL;
1075         }
1076     }
1077 }
1078
1079 #define DEFAULT_ACC_WARNING 0
1080 static int saveAccWarn = DEFAULT_ACC_WARNING;
1081
1082 /*-------------------------------------------------------------------*/
1083 /* aopGet - for fetching value of the aop                            */
1084 /*                                                                   */
1085 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1086 /* in the accumulator. Set it to the name of a free register         */
1087 /* if acc must be preserved; the register will be used to preserve   */
1088 /* acc temporarily and to return the result byte.                    */
1089 /*-------------------------------------------------------------------*/
1090
1091 static char *
1092 aopGet (asmop *aop,
1093         int   offset,
1094         bool  bit16,
1095         bool  dname,
1096         char  *saveAcc)
1097 {
1098   /* offset is greater than
1099      size then zero */
1100   if (offset > (aop->size - 1) &&
1101       aop->type != AOP_LIT)
1102     return zero;
1103
1104   /* depending on type */
1105   switch (aop->type)
1106     {
1107
1108     case AOP_R0:
1109     case AOP_R1:
1110       /* if we need to increment it */
1111       while (offset > aop->coff)
1112         {
1113           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1114           aop->coff++;
1115         }
1116
1117       while (offset < aop->coff)
1118         {
1119           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1120           aop->coff--;
1121         }
1122
1123       aop->coff = offset;
1124       if (aop->paged)
1125         {
1126           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1127           return (dname ? "acc" : "a");
1128         }
1129       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1130       return Safe_strdup(buffer);       
1131
1132     case AOP_DPTRn:
1133         assert(offset <= 3);
1134         return dptrn[aop->aopu.dptr][offset];
1135
1136     case AOP_DPTR:
1137     case AOP_DPTR2:
1138
1139       if (aop->type == AOP_DPTR2)
1140         {
1141           genSetDPTR (1);
1142         }
1143         
1144       if (saveAcc)
1145         {
1146             TR_AP("#1");
1147 //          if (aop->type != AOP_DPTR2)
1148 //          {
1149 //              if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1150 //              emitcode(";", "spanky: saveAcc for DPTR");
1151 //          }
1152             
1153             emitcode ("xch", "a, %s", saveAcc);
1154         }
1155
1156       _flushLazyDPS ();
1157
1158       while (offset > aop->coff)
1159         {
1160           emitcode ("inc", "dptr");
1161           aop->coff++;
1162         }
1163
1164       while (offset < aop->coff)
1165         {
1166           emitcode ("lcall", "__decdptr");
1167           aop->coff--;
1168         }
1169
1170       aop->coff = offset;
1171       if (aop->code)
1172         {
1173           emitcode ("clr", "a");
1174           emitcode ("movc", "a,@a+dptr");
1175         }
1176       else
1177         {
1178           emitcode ("movx", "a,@dptr");
1179         }
1180
1181       if (aop->type == AOP_DPTR2)
1182         {
1183           genSetDPTR (0);
1184         }
1185         
1186         if (saveAcc)
1187         {
1188        TR_AP("#2");
1189               emitcode ("xch", "a, %s", saveAcc);
1190 //            if (strcmp(saveAcc, "_ap"))
1191 //            {
1192 //                emitcode(";", "spiffy: non _ap return from aopGet.");
1193 //            }
1194                   
1195               return saveAcc;
1196         }
1197       return (dname ? "acc" : "a");
1198
1199     case AOP_IMMD:
1200       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) 
1201       {
1202           SNPRINTF(buffer, sizeof(buffer), 
1203                    "%s",aop->aopu.aop_immd.aop_immd2);
1204       } 
1205       else if (bit16)
1206       {
1207          SNPRINTF(buffer, sizeof(buffer), 
1208                   "#%s", aop->aopu.aop_immd.aop_immd1);
1209       }
1210       else if (offset) 
1211       {
1212           switch (offset) {
1213           case 1:
1214               tsprintf(buffer, sizeof(buffer),
1215                        "#!his",aop->aopu.aop_immd.aop_immd1);
1216               break;
1217           case 2:
1218               tsprintf(buffer, sizeof(buffer), 
1219                        "#!hihis",aop->aopu.aop_immd.aop_immd1);
1220               break;
1221           case 3:
1222               tsprintf(buffer, sizeof(buffer),
1223                        "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1224               break;
1225           default: /* should not need this (just in case) */
1226               SNPRINTF (buffer, sizeof(buffer), 
1227                         "#(%s >> %d)",
1228                        aop->aopu.aop_immd.aop_immd1,
1229                        offset * 8);
1230           }
1231       }
1232       else
1233       {
1234         SNPRINTF (buffer, sizeof(buffer), 
1235                   "#%s", aop->aopu.aop_immd.aop_immd1);
1236       }
1237       return Safe_strdup(buffer);       
1238
1239     case AOP_DIR:
1240       if (offset)
1241       {
1242         SNPRINTF (buffer, sizeof(buffer),
1243                   "(%s + %d)",
1244                  aop->aopu.aop_dir,
1245                  offset);
1246       }
1247       else
1248       {
1249         SNPRINTF(buffer, sizeof(buffer), 
1250                  "%s", aop->aopu.aop_dir);
1251       }
1252
1253       return Safe_strdup(buffer);
1254
1255     case AOP_REG:
1256       if (dname)
1257         return aop->aopu.aop_reg[offset]->dname;
1258       else
1259         return aop->aopu.aop_reg[offset]->name;
1260
1261     case AOP_CRY:
1262       emitcode ("clr", "a");
1263       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1264       emitcode ("rlc", "a");
1265       return (dname ? "acc" : "a");
1266
1267     case AOP_ACC:
1268       if (!offset && dname)
1269         return "acc";
1270       return aop->aopu.aop_str[offset];
1271
1272     case AOP_LIT:
1273       return aopLiteral (aop->aopu.aop_lit, offset);
1274
1275     case AOP_STR:
1276       aop->coff = offset;
1277       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1278           dname)
1279         return "acc";
1280
1281       return aop->aopu.aop_str[offset];
1282
1283     }
1284
1285   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1286           "aopget got unsupported aop->type");
1287   exit (1);
1288     
1289   return NULL;  // not reached, but makes compiler happy.
1290 }
1291 /*-----------------------------------------------------------------*/
1292 /* aopPut - puts a string for a aop                                */
1293 /*-----------------------------------------------------------------*/
1294 static void
1295 aopPut (asmop * aop, char *s, int offset)
1296 {
1297   if (aop->size && offset > (aop->size - 1))
1298     {
1299       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1300               "aopPut got offset > aop->size");
1301       exit (1);
1302     }
1303
1304   /* will assign value to value */
1305   /* depending on where it is ofcourse */
1306   switch (aop->type)
1307     {
1308     case AOP_DIR:
1309         if (offset)
1310         {
1311             SNPRINTF (buffer, sizeof(buffer),
1312                       "(%s + %d)",
1313                       aop->aopu.aop_dir, offset);
1314         }
1315         else
1316         {
1317             SNPRINTF (buffer, sizeof(buffer), 
1318                      "%s", aop->aopu.aop_dir);
1319         }
1320         
1321
1322         if (strcmp (buffer, s))
1323         {
1324             emitcode ("mov", "%s,%s", buffer, s);
1325         }
1326       break;
1327
1328     case AOP_REG:
1329       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1330           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1331         {
1332           if (*s == '@' ||
1333               strcmp (s, "r0") == 0 ||
1334               strcmp (s, "r1") == 0 ||
1335               strcmp (s, "r2") == 0 ||
1336               strcmp (s, "r3") == 0 ||
1337               strcmp (s, "r4") == 0 ||
1338               strcmp (s, "r5") == 0 ||
1339               strcmp (s, "r6") == 0 ||
1340               strcmp (s, "r7") == 0)
1341             {
1342                 emitcode ("mov", "%s,%s",
1343                           aop->aopu.aop_reg[offset]->dname, s);
1344             }
1345             else
1346             {
1347                 emitcode ("mov", "%s,%s",
1348                           aop->aopu.aop_reg[offset]->name, s);
1349             }
1350         }
1351       break;
1352
1353     case AOP_DPTRn:
1354         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1355         break;
1356
1357     case AOP_DPTR:
1358     case AOP_DPTR2:
1359
1360       if (aop->type == AOP_DPTR2)
1361         {
1362           genSetDPTR (1);
1363         }
1364       _flushLazyDPS ();
1365
1366       if (aop->code)
1367         {
1368           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1369                   "aopPut writting to code space");
1370           exit (1);
1371         }
1372
1373       while (offset > aop->coff)
1374         {
1375           aop->coff++;
1376           emitcode ("inc", "dptr");
1377         }
1378
1379       while (offset < aop->coff)
1380         {
1381           aop->coff--;
1382           emitcode ("lcall", "__decdptr");
1383         }
1384
1385       aop->coff = offset;
1386
1387       /* if not in accumulater */
1388       MOVA (s);
1389
1390       emitcode ("movx", "@dptr,a");
1391
1392       if (aop->type == AOP_DPTR2)
1393         {
1394           genSetDPTR (0);
1395         }
1396       break;
1397
1398     case AOP_R0:
1399     case AOP_R1:
1400       while (offset > aop->coff)
1401         {
1402           aop->coff++;
1403           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1404         }
1405       while (offset < aop->coff)
1406         {
1407           aop->coff--;
1408           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1409         }
1410       aop->coff = offset;
1411
1412       if (aop->paged)
1413         {
1414           MOVA (s);
1415           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1416
1417         }
1418       else if (*s == '@')
1419         {
1420           MOVA (s);
1421           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1422         }
1423       else if (strcmp (s, "r0") == 0 ||
1424                strcmp (s, "r1") == 0 ||
1425                strcmp (s, "r2") == 0 ||
1426                strcmp (s, "r3") == 0 ||
1427                strcmp (s, "r4") == 0 ||
1428                strcmp (s, "r5") == 0 ||
1429                strcmp (s, "r6") == 0 ||
1430                strcmp (s, "r7") == 0)
1431         {
1432           char buff[10];
1433           SNPRINTF(buff, sizeof(buff), 
1434                    "a%s", s);
1435           emitcode ("mov", "@%s,%s",
1436                     aop->aopu.aop_ptr->name, buff);
1437         }
1438         else
1439         {
1440             emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1441         }
1442       break;
1443
1444     case AOP_STK:
1445       if (strcmp (s, "a") == 0)
1446         emitcode ("push", "acc");
1447       else
1448         if (*s=='@') {
1449           MOVA(s);
1450           emitcode ("push", "acc");
1451         } else {
1452           emitcode ("push", s);
1453         }
1454
1455       break;
1456
1457     case AOP_CRY:
1458       /* if bit variable */
1459       if (!aop->aopu.aop_dir)
1460         {
1461           emitcode ("clr", "a");
1462           emitcode ("rlc", "a");
1463         }
1464       else
1465         {
1466           if (s == zero)
1467             emitcode ("clr", "%s", aop->aopu.aop_dir);
1468           else if (s == one)
1469             emitcode ("setb", "%s", aop->aopu.aop_dir);
1470           else if (!strcmp (s, "c"))
1471             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1472           else
1473             {
1474               if (strcmp (s, "a"))
1475                 {
1476                   MOVA (s);
1477                 }
1478               {
1479                 /* set C, if a >= 1 */
1480                 emitcode ("add", "a,#!constbyte",0xff);
1481                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1482               }
1483             }
1484         }
1485       break;
1486
1487     case AOP_STR:
1488       aop->coff = offset;
1489       if (strcmp (aop->aopu.aop_str[offset], s))
1490         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1491       break;
1492
1493     case AOP_ACC:
1494       aop->coff = offset;
1495       if (!offset && (strcmp (s, "acc") == 0))
1496         break;
1497
1498       if (strcmp (aop->aopu.aop_str[offset], s))
1499         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1500       break;
1501
1502     default:
1503       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1504               "aopPut got unsupported aop->type");
1505       exit (1);
1506     }
1507
1508 }
1509
1510
1511 /*--------------------------------------------------------------------*/
1512 /* reAdjustPreg - points a register back to where it should (coff==0) */
1513 /*--------------------------------------------------------------------*/
1514 static void
1515 reAdjustPreg (asmop * aop)
1516 {
1517   if ((aop->coff==0) || (aop->size <= 1)) {
1518     return;
1519   }
1520
1521   switch (aop->type)
1522     {
1523     case AOP_R0:
1524     case AOP_R1:
1525       while (aop->coff--)
1526         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1527       break;
1528     case AOP_DPTR:
1529     case AOP_DPTR2:
1530       if (aop->type == AOP_DPTR2)
1531         {
1532           genSetDPTR (1);
1533           _flushLazyDPS ();
1534         }
1535       while (aop->coff--)
1536         {
1537           emitcode ("lcall", "__decdptr");
1538         }
1539
1540       if (aop->type == AOP_DPTR2)
1541         {
1542           genSetDPTR (0);
1543         }
1544       break;
1545
1546     }
1547   aop->coff=0;
1548 }
1549
1550 #define AOP(op) op->aop
1551 #define AOP_TYPE(op) AOP(op)->type
1552 #define AOP_SIZE(op) AOP(op)->size
1553 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1554                        AOP_TYPE(x) == AOP_R0))
1555
1556 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1557                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1558                          AOP(x)->paged))
1559
1560 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1561                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1562                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1563 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1564 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1565 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1566
1567 // The following two macros can be used even if the aop has not yet been aopOp'd.
1568 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1569 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1570
1571 /* Workaround for DS80C390 bug: div ab may return bogus results
1572  * if A is accessed in instruction immediately before the div.
1573  *
1574  * Will be fixed in B4 rev of processor, Dallas claims.
1575  */
1576
1577 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1578     if (!AOP_NEEDSACC(RIGHT))         \
1579     {               \
1580       /* We can load A first, then B, since     \
1581        * B (the RIGHT operand) won't clobber A,   \
1582        * thus avoiding touching A right before the div. \
1583        */             \
1584       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1585       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);     \
1586       MOVA(L);            \
1587       L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1588       MOVB(L); \
1589     }               \
1590     else              \
1591     {               \
1592       /* Just stuff in a nop after loading A. */    \
1593       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1594       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);   \
1595       MOVA(L);            \
1596       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1597     }
1598
1599 /*-----------------------------------------------------------------*/
1600 /* genNotFloat - generates not for float operations              */
1601 /*-----------------------------------------------------------------*/
1602 static void
1603 genNotFloat (operand * op, operand * res)
1604 {
1605   int size, offset;
1606   symbol *tlbl;
1607
1608   D (emitcode (";", "genNotFloat "););
1609
1610   /* we will put 127 in the first byte of
1611      the result */
1612   aopPut (AOP (res), "#127", 0);
1613   size = AOP_SIZE (op) - 1;
1614   offset = 1;
1615
1616   _startLazyDPSEvaluation ();
1617   MOVA(aopGet(op->aop, offset++, FALSE, FALSE, NULL));
1618
1619   while (size--)
1620     {
1621       emitcode ("orl", "a,%s",
1622                 aopGet (op->aop,
1623                         offset++, FALSE, FALSE,
1624                         DP2_RESULT_REG));
1625     }
1626   _endLazyDPSEvaluation ();
1627
1628   tlbl = newiTempLabel (NULL);
1629   aopPut (res->aop, one, 1);
1630   emitcode ("jz", "!tlabel", (tlbl->key + 100));
1631   aopPut (res->aop, zero, 1);
1632   emitcode ("", "!tlabeldef", (tlbl->key + 100));
1633
1634   size = res->aop->size - 2;
1635   offset = 2;
1636   /* put zeros in the rest */
1637   while (size--)
1638     aopPut (res->aop, zero, offset++);
1639 }
1640
1641 /*-----------------------------------------------------------------*/
1642 /* opIsGptr: returns non-zero if the passed operand is       */
1643 /* a generic pointer type.             */
1644 /*-----------------------------------------------------------------*/
1645 static int
1646 opIsGptr (operand * op)
1647 {
1648   sym_link *type = operandType (op);
1649
1650   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1651     {
1652       return 1;
1653     }
1654   return 0;
1655 }
1656
1657 /*-----------------------------------------------------------------*/
1658 /* getDataSize - get the operand data size                         */
1659 /*-----------------------------------------------------------------*/
1660 static int
1661 getDataSize (operand * op)
1662 {
1663   int size;
1664   size = AOP_SIZE (op);
1665   if (size == GPTRSIZE)
1666     {
1667       sym_link *type = operandType (op);
1668       if (IS_GENPTR (type))
1669         {
1670           /* generic pointer; arithmetic operations
1671            * should ignore the high byte (pointer type).
1672            */
1673           size--;
1674         }
1675     }
1676   return size;
1677 }
1678
1679 /*-----------------------------------------------------------------*/
1680 /* outAcc - output Acc                                             */
1681 /*-----------------------------------------------------------------*/
1682 static void
1683 outAcc (operand * result)
1684 {
1685   int size, offset;
1686   size = getDataSize (result);
1687   if (size)
1688     {
1689       aopPut (AOP (result), "a", 0);
1690       size--;
1691       offset = 1;
1692       /* unsigned or positive */
1693       while (size--)
1694         {
1695           aopPut (AOP (result), zero, offset++);
1696         }
1697     }
1698 }
1699
1700 /*-----------------------------------------------------------------*/
1701 /* outBitC - output a bit C                                        */
1702 /*-----------------------------------------------------------------*/
1703 static void
1704 outBitC (operand * result)
1705 {
1706   /* if the result is bit */
1707   if (AOP_TYPE (result) == AOP_CRY)
1708     {
1709       aopPut (AOP (result), "c", 0);
1710     }
1711   else
1712     {
1713       emitcode ("clr", "a");
1714       emitcode ("rlc", "a");
1715       outAcc (result);
1716     }
1717 }
1718
1719 /*-----------------------------------------------------------------*/
1720 /* toBoolean - emit code for orl a,operator(sizeop)                */
1721 /*-----------------------------------------------------------------*/
1722 static void
1723 toBoolean (operand * oper)
1724 {
1725   int   size = AOP_SIZE (oper) - 1;
1726   int   offset = 1;
1727   bool usedB = FALSE;
1728
1729   /* The generic part of a generic pointer should
1730    * not participate in it's truth value.
1731    *
1732    * i.e. 0x10000000 is zero.
1733    */
1734   if (opIsGptr (oper))
1735     {
1736       D (emitcode (";", "toBoolean: generic ptr special case."););
1737       size--;
1738     }
1739
1740   _startLazyDPSEvaluation ();
1741   if (AOP_NEEDSACC (oper) && size)
1742     {
1743       usedB = TRUE;
1744       if (_G.bInUse)
1745       {
1746           emitcode ("push", "b");
1747       }
1748       MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1749     }
1750   else
1751     {
1752       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1753     }
1754     
1755   while (size--)
1756     {
1757       if (usedB)
1758         {
1759           emitcode ("orl", "b,%s",
1760                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1761         }
1762       else
1763         {
1764           emitcode ("orl", "a,%s",
1765                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1766         }
1767     }
1768   _endLazyDPSEvaluation ();
1769
1770   if (usedB)
1771     {
1772       emitcode ("mov", "a,b");
1773       if (_G.bInUse)
1774       {
1775           emitcode ("pop", "b");
1776       }
1777         
1778     }
1779 }
1780
1781
1782 /*-----------------------------------------------------------------*/
1783 /* genNot - generate code for ! operation                          */
1784 /*-----------------------------------------------------------------*/
1785 static void
1786 genNot (iCode * ic)
1787 {
1788   symbol *tlbl;
1789   sym_link *optype = operandType (IC_LEFT (ic));
1790
1791   D (emitcode (";", "genNot "););
1792
1793   /* assign asmOps to operand & result */
1794   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1795   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1796
1797   /* if in bit space then a special case */
1798   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1799     {
1800       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1801       emitcode ("cpl", "c");
1802       outBitC (IC_RESULT (ic));
1803       goto release;
1804     }
1805
1806   /* if type float then do float */
1807   if (IS_FLOAT (optype))
1808     {
1809       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1810       goto release;
1811     }
1812
1813   toBoolean (IC_LEFT (ic));
1814
1815   tlbl = newiTempLabel (NULL);
1816   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1817   emitcode ("", "!tlabeldef", tlbl->key + 100);
1818   outBitC (IC_RESULT (ic));
1819
1820 release:
1821   /* release the aops */
1822   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1823   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1824 }
1825
1826
1827 /*-----------------------------------------------------------------*/
1828 /* genCpl - generate code for complement                           */
1829 /*-----------------------------------------------------------------*/
1830 static void
1831 genCpl (iCode * ic)
1832 {
1833   int offset = 0;
1834   int size;
1835   symbol *tlbl;
1836
1837   D (emitcode (";", "genCpl "););
1838
1839
1840   /* assign asmOps to operand & result */
1841   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1842   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1843
1844   /* special case if in bit space */
1845   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1846     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1847       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1848       emitcode ("cpl", "c");
1849       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1850       goto release;
1851     }
1852     tlbl=newiTempLabel(NULL);
1853     emitcode ("cjne", "%s,#0x01,%05d$", 
1854               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1855     emitcode ("", "%05d$:", tlbl->key+100);
1856     outBitC (IC_RESULT(ic));
1857     goto release;
1858   }
1859
1860   size = AOP_SIZE (IC_RESULT (ic));
1861   _startLazyDPSEvaluation ();
1862   while (size--)
1863     {
1864       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1865       emitcode ("cpl", "a");
1866       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1867     }
1868   _endLazyDPSEvaluation ();
1869
1870
1871 release:
1872   /* release the aops */
1873   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1874   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1875 }
1876
1877 /*-----------------------------------------------------------------*/
1878 /* genUminusFloat - unary minus for floating points                */
1879 /*-----------------------------------------------------------------*/
1880 static void
1881 genUminusFloat (operand * op, operand * result)
1882 {
1883   int size, offset = 0;
1884     
1885   D(emitcode (";", "genUminusFloat"););
1886   
1887   /* for this we just copy and then flip the bit */
1888     
1889   _startLazyDPSEvaluation ();
1890   size = AOP_SIZE (op) - 1;
1891
1892   while (size--)
1893   {
1894       aopPut (AOP (result),
1895               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1896               offset);
1897       offset++;
1898     }
1899   
1900   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1901
1902   emitcode ("cpl", "acc.7");
1903   aopPut (AOP (result), "a", offset);    
1904   _endLazyDPSEvaluation ();
1905 }
1906
1907 /*-----------------------------------------------------------------*/
1908 /* genUminus - unary minus code generation                         */
1909 /*-----------------------------------------------------------------*/
1910 static void
1911 genUminus (iCode * ic)
1912 {
1913   int offset, size;
1914   sym_link *optype;
1915
1916   D (emitcode (";", "genUminus "););
1917
1918   /* assign asmops */
1919   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1920   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1921
1922   /* if both in bit space then special
1923      case */
1924   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1925       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1926     {
1927
1928       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1929       emitcode ("cpl", "c");
1930       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1931       goto release;
1932     }
1933
1934   optype = operandType (IC_LEFT (ic));
1935
1936   /* if float then do float stuff */
1937   if (IS_FLOAT (optype))
1938     {
1939       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1940       goto release;
1941     }
1942
1943   /* otherwise subtract from zero */
1944   size = AOP_SIZE (IC_LEFT (ic));
1945   offset = 0;
1946   _startLazyDPSEvaluation ();
1947   while (size--)
1948     {
1949       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1950       if (!strcmp (l, "a"))
1951         {
1952           if (offset == 0)
1953             SETC;
1954           emitcode ("cpl", "a");
1955           emitcode ("addc", "a,#0");
1956         }
1957       else
1958         {
1959           if (offset == 0)
1960             CLRC;
1961           emitcode ("clr", "a");
1962           emitcode ("subb", "a,%s", l);
1963         }
1964       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1965     }
1966   _endLazyDPSEvaluation ();
1967
1968   /* if any remaining bytes in the result */
1969   /* we just need to propagate the sign   */
1970   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
1971     {
1972       emitcode ("rlc", "a");
1973       emitcode ("subb", "a,acc");
1974       while (size--)
1975         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1976     }
1977
1978 release:
1979   /* release the aops */
1980   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1981   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1982 }
1983
1984 /*-----------------------------------------------------------------*/
1985 /* savermask - saves registers in the mask                         */
1986 /*-----------------------------------------------------------------*/
1987 static void savermask(bitVect *rs_mask)
1988 {
1989     int i;
1990     if (options.useXstack) {
1991         if (bitVectBitValue (rs_mask, R0_IDX))
1992             emitcode ("mov", "b,r0");
1993         emitcode ("mov", "r0,%s", spname);
1994         for (i = 0; i < ds390_nRegs; i++) {
1995             if (bitVectBitValue (rs_mask, i)) {
1996                 if (i == R0_IDX)
1997                     emitcode ("mov", "a,b");
1998                 else
1999                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2000                 emitcode ("movx", "@r0,a");
2001                 emitcode ("inc", "r0");
2002             }
2003         }
2004         emitcode ("mov", "%s,r0", spname);
2005         if (bitVectBitValue (rs_mask, R0_IDX))
2006             emitcode ("mov", "r0,b");
2007     } else {
2008         for (i = 0; i < ds390_nRegs; i++) {
2009             if (bitVectBitValue (rs_mask, i))
2010                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2011         }
2012     }
2013 }
2014
2015 /*-----------------------------------------------------------------*/
2016 /* saveRegisters - will look for a call and save the registers     */
2017 /*-----------------------------------------------------------------*/
2018 static void
2019 saveRegisters (iCode * lic)
2020 {
2021   iCode *ic;
2022   bitVect *rsave;
2023
2024   /* look for call */
2025   for (ic = lic; ic; ic = ic->next)
2026     if (ic->op == CALL || ic->op == PCALL)
2027       break;
2028
2029   if (!ic)
2030     {
2031       fprintf (stderr, "found parameter push with no function call\n");
2032       return;
2033     }
2034
2035   /* if the registers have been saved already then
2036      do nothing */
2037   if (ic->regsSaved || 
2038       (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))))
2039     return ;
2040
2041   /* special case if DPTR alive across a function call then must save it 
2042      even though callee saves */
2043   if (IS_SYMOP(IC_LEFT(ic)) &&
2044       IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2045       int i;
2046       rsave = newBitVect(ic->rMask->size);
2047       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2048           if (bitVectBitValue(ic->rMask,i))
2049               rsave = bitVectSetBit(rsave,i);
2050       }
2051       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2052   } else {
2053     /* safe the registers in use at this time but skip the
2054        ones for the result */
2055     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2056                            ds390_rUmaskForOp (IC_RESULT(ic)));
2057   }
2058   ic->regsSaved = 1;
2059   savermask(rsave);
2060 }
2061
2062 /*-----------------------------------------------------------------*/
2063 /* usavermask - restore registers with mask                        */
2064 /*-----------------------------------------------------------------*/
2065 static void unsavermask(bitVect *rs_mask)
2066 {
2067     int i;
2068     if (options.useXstack) {
2069         emitcode ("mov", "r0,%s", spname);
2070         for (i = ds390_nRegs; i >= 0; i--) {
2071             if (bitVectBitValue (rs_mask, i)) {
2072                 emitcode ("dec", "r0");
2073                 emitcode ("movx", "a,@r0");
2074                 if (i == R0_IDX)
2075                     emitcode ("mov", "b,a");
2076                 else
2077                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2078             }       
2079         }
2080         emitcode ("mov", "%s,r0", spname);
2081         if (bitVectBitValue (rs_mask, R0_IDX))
2082             emitcode ("mov", "r0,b");
2083     } else {
2084         for (i = ds390_nRegs; i >= 0; i--) {
2085             if (bitVectBitValue (rs_mask, i))
2086                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2087         }
2088     }
2089 }
2090
2091 /*-----------------------------------------------------------------*/
2092 /* unsaveRegisters - pop the pushed registers                      */
2093 /*-----------------------------------------------------------------*/
2094 static void
2095 unsaveRegisters (iCode * ic)
2096 {
2097   bitVect *rsave;
2098
2099   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2100       int i;
2101       rsave = newBitVect(ic->rMask->size);
2102       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2103           if (bitVectBitValue(ic->rMask,i))
2104               rsave = bitVectSetBit(rsave,i);
2105       }
2106       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2107   } else {
2108     /* restore the registers in use at this time but skip the
2109        ones for the result */
2110     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2111                            ds390_rUmaskForOp (IC_RESULT(ic)));
2112   }
2113   unsavermask(rsave);
2114 }
2115
2116
2117 /*-----------------------------------------------------------------*/
2118 /* pushSide -                */
2119 /*-----------------------------------------------------------------*/
2120 static void
2121 pushSide (operand * oper, int size)
2122 {
2123   int offset = 0;
2124   _startLazyDPSEvaluation ();
2125   while (size--)
2126     {
2127       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2128       if (AOP_TYPE (oper) != AOP_REG &&
2129           AOP_TYPE (oper) != AOP_DIR &&
2130           strcmp (l, "a"))
2131         {
2132           emitcode ("mov", "a,%s", l);
2133           emitcode ("push", "acc");
2134         }
2135       else
2136         emitcode ("push", "%s", l);
2137     }
2138   _endLazyDPSEvaluation ();
2139 }
2140
2141 /*-----------------------------------------------------------------*/
2142 /* assignResultValue -               */
2143 /*-----------------------------------------------------------------*/
2144 static void
2145 assignResultValue (operand * oper)
2146 {
2147   int offset = 0;
2148   int size = AOP_SIZE (oper);
2149   bool pushedAcc = FALSE;
2150
2151   if (size == fReturnSizeDS390)
2152   {
2153       /* I don't think this case can ever happen... */
2154       /* ACC is the last part of this. If writing the result
2155        * uses AC, we must preserve it.
2156        */
2157       if (AOP_NEEDSACC(oper))
2158       {
2159           emitcode(";", "assignResultValue special case for ACC.");
2160           emitcode("push", "acc");
2161           pushedAcc = TRUE;
2162           size--;
2163       }
2164   }
2165     
2166     
2167   _startLazyDPSEvaluation ();
2168   while (size--)
2169     {
2170       aopPut (AOP (oper), fReturn[offset], offset);
2171       offset++;
2172     }
2173   _endLazyDPSEvaluation ();
2174     
2175   if (pushedAcc)
2176     {
2177         emitcode("pop", "acc");
2178         aopPut(AOP(oper), "a", offset);
2179     }
2180 }
2181
2182
2183 /*-----------------------------------------------------------------*/
2184 /* genXpush - pushes onto the external stack                       */
2185 /*-----------------------------------------------------------------*/
2186 static void
2187 genXpush (iCode * ic)
2188 {
2189   asmop *aop = newAsmop (0);
2190   regs *r;
2191   int size, offset = 0;
2192
2193   D (emitcode (";", "genXpush ");
2194     );
2195
2196   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2197   r = getFreePtr (ic, &aop, FALSE);
2198
2199
2200   emitcode ("mov", "%s,_spx", r->name);
2201
2202   size = AOP_SIZE (IC_LEFT (ic));
2203   _startLazyDPSEvaluation ();
2204   while (size--)
2205     {
2206
2207       MOVA (aopGet (AOP (IC_LEFT (ic)),
2208                         offset++, FALSE, FALSE, NULL));
2209       emitcode ("movx", "@%s,a", r->name);
2210       emitcode ("inc", "%s", r->name);
2211
2212     }
2213   _endLazyDPSEvaluation ();
2214
2215
2216   emitcode ("mov", "_spx,%s", r->name);
2217
2218   freeAsmop (NULL, aop, ic, TRUE);
2219   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2220 }
2221
2222 /*-----------------------------------------------------------------*/
2223 /* genIpush - generate code for pushing this gets a little complex  */
2224 /*-----------------------------------------------------------------*/
2225 static void
2226 genIpush (iCode * ic)
2227 {
2228   int size, offset = 0;
2229   char *l;
2230
2231   D (emitcode (";", "genIpush ");
2232     );
2233
2234   /* if this is not a parm push : ie. it is spill push
2235      and spill push is always done on the local stack */
2236   if (!ic->parmPush)
2237     {
2238
2239       /* and the item is spilt then do nothing */
2240       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2241         return;
2242
2243       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2244       size = AOP_SIZE (IC_LEFT (ic));
2245       /* push it on the stack */
2246       _startLazyDPSEvaluation ();
2247       while (size--)
2248         {
2249           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2250           if (*l == '#')
2251             {
2252               MOVA (l);
2253               l = "acc";
2254             }
2255           emitcode ("push", "%s", l);
2256         }
2257       _endLazyDPSEvaluation ();
2258       return;
2259     }
2260
2261   /* this is a paramter push: in this case we call
2262      the routine to find the call and save those
2263      registers that need to be saved */
2264   saveRegisters (ic);
2265
2266   /* if use external stack then call the external
2267      stack pushing routine */
2268   if (options.useXstack)
2269     {
2270       genXpush (ic);
2271       return;
2272     }
2273
2274   /* then do the push */
2275   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2276
2277   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2278   size = AOP_SIZE (IC_LEFT (ic));
2279
2280   _startLazyDPSEvaluation ();
2281   while (size--)
2282     {
2283       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2284       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2285           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2286           strcmp (l, "acc"))
2287         {
2288           emitcode ("mov", "a,%s", l);
2289           emitcode ("push", "acc");
2290         }
2291       else
2292         {
2293             emitcode ("push", "%s", l);
2294         }
2295     }
2296   _endLazyDPSEvaluation ();
2297
2298   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2299 }
2300
2301 /*-----------------------------------------------------------------*/
2302 /* genIpop - recover the registers: can happen only for spilling   */
2303 /*-----------------------------------------------------------------*/
2304 static void
2305 genIpop (iCode * ic)
2306 {
2307   int size, offset;
2308
2309   D (emitcode (";", "genIpop ");
2310     );
2311
2312
2313   /* if the temp was not pushed then */
2314   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2315     return;
2316
2317   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2318   size = AOP_SIZE (IC_LEFT (ic));
2319   offset = (size - 1);
2320   _startLazyDPSEvaluation ();
2321   while (size--)
2322     {
2323       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2324                                      FALSE, TRUE, NULL));
2325     }
2326   _endLazyDPSEvaluation ();
2327
2328   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2329 }
2330
2331 /*-----------------------------------------------------------------*/
2332 /* unsaveRBank - restores the resgister bank from stack            */
2333 /*-----------------------------------------------------------------*/
2334 static void
2335 unsaveRBank (int bank, iCode * ic, bool popPsw)
2336 {
2337   int i;
2338   asmop *aop = NULL;
2339   regs *r = NULL;
2340
2341   if (options.useXstack)
2342   {
2343       if (!ic)
2344       {
2345           /* Assume r0 is available for use. */
2346           r = ds390_regWithIdx (R0_IDX);;          
2347       } 
2348       else
2349       {
2350           aop = newAsmop (0);
2351           r = getFreePtr (ic, &aop, FALSE);
2352       }
2353       emitcode ("mov", "%s,_spx", r->name);      
2354   }
2355   
2356   if (popPsw)
2357     {
2358       if (options.useXstack)
2359       {
2360           emitcode ("movx", "a,@%s", r->name);
2361           emitcode ("mov", "psw,a");
2362           emitcode ("dec", "%s", r->name);
2363         }
2364       else
2365       {
2366         emitcode ("pop", "psw");
2367       }
2368     }
2369
2370   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2371     {
2372       if (options.useXstack)
2373         {
2374           emitcode ("movx", "a,@%s", r->name);
2375           emitcode ("mov", "(%s+%d),a",
2376                     regs390[i].base, 8 * bank + regs390[i].offset);
2377           emitcode ("dec", "%s", r->name);
2378
2379         }
2380       else
2381         emitcode ("pop", "(%s+%d)",
2382                   regs390[i].base, 8 * bank + regs390[i].offset);
2383     }
2384
2385   if (options.useXstack)
2386     {
2387       emitcode ("mov", "_spx,%s", r->name);
2388     }
2389     
2390   if (aop)
2391   {
2392       freeAsmop (NULL, aop, ic, TRUE);  
2393   }    
2394 }
2395
2396 /*-----------------------------------------------------------------*/
2397 /* saveRBank - saves an entire register bank on the stack          */
2398 /*-----------------------------------------------------------------*/
2399 static void
2400 saveRBank (int bank, iCode * ic, bool pushPsw)
2401 {
2402   int i;
2403   asmop *aop = NULL;
2404   regs *r = NULL;
2405
2406   if (options.useXstack)
2407     {
2408         if (!ic)
2409         {
2410           /* Assume r0 is available for use. */
2411                   r = ds390_regWithIdx (R0_IDX);;
2412         }
2413         else
2414         {
2415           aop = newAsmop (0);
2416           r = getFreePtr (ic, &aop, FALSE);
2417         }
2418         emitcode ("mov", "%s,_spx", r->name);    
2419     }
2420
2421   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2422     {
2423       if (options.useXstack)
2424         {
2425           emitcode ("inc", "%s", r->name);
2426           emitcode ("mov", "a,(%s+%d)",
2427                     regs390[i].base, 8 * bank + regs390[i].offset);
2428           emitcode ("movx", "@%s,a", r->name);
2429         }
2430       else
2431         emitcode ("push", "(%s+%d)",
2432                   regs390[i].base, 8 * bank + regs390[i].offset);
2433     }
2434
2435   if (pushPsw)
2436     {
2437       if (options.useXstack)
2438         {
2439           emitcode ("mov", "a,psw");
2440           emitcode ("movx", "@%s,a", r->name);
2441           emitcode ("inc", "%s", r->name);
2442           emitcode ("mov", "_spx,%s", r->name);
2443         }
2444       else
2445       {
2446         emitcode ("push", "psw");
2447       }
2448
2449       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2450     }
2451   
2452   if (aop)
2453   {
2454        freeAsmop (NULL, aop, ic, TRUE);
2455   }    
2456     
2457   if (ic)
2458   {  
2459       ic->bankSaved = 1;
2460   }
2461 }
2462
2463 /*-----------------------------------------------------------------*/
2464 /* genSend - gen code for SEND                                     */
2465 /*-----------------------------------------------------------------*/
2466 static void genSend(set *sendSet)
2467 {
2468     iCode *sic;
2469     int sendCount = 0 ;
2470     static int rb1_count = 0;
2471
2472     for (sic = setFirstItem (sendSet); sic;
2473          sic = setNextItem (sendSet)) {     
2474         int size, offset = 0;
2475         
2476         size=getSize(operandType(IC_LEFT(sic)));
2477         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2478         if (sendCount == 0) { /* first parameter */
2479             // we know that dpl(hxb) is the result, so
2480             rb1_count = 0 ;
2481             _startLazyDPSEvaluation ();
2482             if (size>1) {
2483                 aopOp (IC_LEFT (sic), sic, FALSE, 
2484                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2485             } else {
2486                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2487             }
2488             while (size--) {
2489                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2490                                   FALSE, FALSE, NULL);
2491                 if (strcmp (l, fReturn[offset])) {
2492                     emitcode ("mov", "%s,%s",
2493                               fReturn[offset],
2494                               l);
2495                 }
2496                 offset++;
2497             }
2498             _endLazyDPSEvaluation ();
2499             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2500             rb1_count =0;
2501         } else { /* if more parameter in registers */
2502             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2503             while (size--) {
2504                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2505                                                                 FALSE, FALSE, NULL));
2506             }
2507             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2508         }
2509         sendCount++;
2510     }
2511 }
2512
2513 /*-----------------------------------------------------------------*/
2514 /* genCall - generates a call statement                            */
2515 /*-----------------------------------------------------------------*/
2516 static void
2517 genCall (iCode * ic)
2518 {
2519   sym_link *dtype;
2520   bool restoreBank = FALSE;
2521   bool swapBanks = FALSE;
2522
2523   D (emitcode (";", "genCall "););
2524
2525   /* if we are calling a not _naked function that is not using
2526      the same register bank then we need to save the
2527      destination registers on the stack */
2528   dtype = operandType (IC_LEFT (ic));
2529   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2530       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2531       IFFUNC_ISISR (currFunc->type))
2532   {
2533       if (!ic->bankSaved) 
2534       {
2535            /* This is unexpected; the bank should have been saved in
2536             * genFunction.
2537             */
2538            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2539            restoreBank = TRUE;
2540       }
2541       swapBanks = TRUE;
2542   }
2543   
2544     /* if caller saves & we have not saved then */
2545     if (!ic->regsSaved)
2546       saveRegisters (ic);
2547   
2548   /* if send set is not empty the assign */
2549   /* We've saved all the registers we care about;
2550   * therefore, we may clobber any register not used
2551   * in the calling convention (i.e. anything not in
2552   * fReturn.
2553   */
2554   if (_G.sendSet)
2555     {
2556         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2557             genSend(reverseSet(_G.sendSet));
2558         } else {
2559             genSend(_G.sendSet);
2560         }
2561       _G.sendSet = NULL;
2562     }  
2563     
2564   if (swapBanks)
2565   {
2566         emitcode ("mov", "psw,#!constbyte", 
2567            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2568   }
2569
2570   /* make the call */
2571   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2572                             OP_SYMBOL (IC_LEFT (ic))->rname :
2573                             OP_SYMBOL (IC_LEFT (ic))->name));
2574
2575   if (swapBanks)
2576   {
2577        emitcode ("mov", "psw,#!constbyte", 
2578           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2579   }
2580
2581   /* if we need assign a result value */
2582   if ((IS_ITEMP (IC_RESULT (ic)) &&
2583        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2584         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2585         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2586       IS_TRUE_SYMOP (IC_RESULT (ic)))
2587     {
2588       if (isOperandInFarSpace (IC_RESULT (ic))
2589           && getSize (operandType (IC_RESULT (ic))) <= 2)
2590         {
2591           int size = getSize (operandType (IC_RESULT (ic)));
2592
2593           /* Special case for 1 or 2 byte return in far space. */
2594           MOVA (fReturn[0]);
2595           if (size > 1)
2596             {
2597               emitcode ("mov", "b,%s", fReturn[1]);
2598             }
2599
2600           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2601           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2602
2603           if (size > 1)
2604             {
2605               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2606             }
2607           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2608         }
2609       else
2610         {
2611           _G.accInUse++;
2612           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2613           _G.accInUse--;
2614
2615           assignResultValue (IC_RESULT (ic));
2616
2617           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2618         }
2619     }
2620
2621   /* adjust the stack for parameters if
2622      required */
2623   if (ic->parmBytes) {
2624       int i;
2625       if (options.stack10bit) {
2626           if (ic->parmBytes <= 10) {
2627               emitcode(";","stack adjustment for parms");
2628               for (i=0; i < ic->parmBytes ; i++) {
2629                   emitcode("pop","acc");
2630               }
2631           } else {            
2632               PROTECT_SP;
2633               emitcode ("clr","c");
2634               emitcode ("mov","a,sp");
2635               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2636               emitcode ("mov","sp,a");
2637               emitcode ("mov","a,esp");
2638               emitcode ("anl","a,#3");
2639               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2640               emitcode ("mov","esp,a");   
2641               UNPROTECT_SP;
2642           }
2643       } else {
2644           if (ic->parmBytes > 3) {
2645               emitcode ("mov", "a,%s", spname);
2646               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2647               emitcode ("mov", "%s,a", spname);
2648           } else
2649               for (i = 0; i < ic->parmBytes; i++)
2650                   emitcode ("dec", "%s", spname);
2651       }
2652   }
2653
2654   /* if we hade saved some registers then unsave them */
2655   if (ic->regsSaved)
2656     unsaveRegisters (ic);
2657
2658   /* if register bank was saved then pop them */
2659   if (restoreBank)
2660     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2661 }
2662
2663 /*-----------------------------------------------------------------*/
2664 /* genPcall - generates a call by pointer statement                */
2665 /*-----------------------------------------------------------------*/
2666 static void
2667 genPcall (iCode * ic)
2668 {
2669   sym_link *dtype;
2670   symbol *rlbl = newiTempLabel (NULL);
2671   bool restoreBank=FALSE;
2672
2673   D (emitcode (";", "genPcall ");
2674     );
2675
2676
2677   /* if caller saves & we have not saved then */
2678   if (!ic->regsSaved)
2679     saveRegisters (ic);
2680
2681   /* if we are calling a function that is not using
2682      the same register bank then we need to save the
2683      destination registers on the stack */
2684   dtype = operandType (IC_LEFT (ic));
2685   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2686       IFFUNC_ISISR (currFunc->type) &&
2687       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2688     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2689     restoreBank=TRUE;
2690   }
2691
2692   /* push the return address on to the stack */
2693   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2694   emitcode ("push", "acc");
2695   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2696   emitcode ("push", "acc");
2697
2698   if (options.model == MODEL_FLAT24)
2699     {
2700       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2701       emitcode ("push", "acc");
2702     }
2703
2704   /* now push the calling address */
2705   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2706
2707   pushSide (IC_LEFT (ic), FPTRSIZE);
2708
2709   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2710
2711   /* if send set is not empty the assign */
2712   if (_G.sendSet)
2713     {
2714         genSend(reverseSet(_G.sendSet));
2715         _G.sendSet = NULL;
2716     }
2717
2718   emitcode ("ret", "");
2719   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2720
2721
2722   /* if we need assign a result value */
2723   if ((IS_ITEMP (IC_RESULT (ic)) &&
2724        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2725         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2726       IS_TRUE_SYMOP (IC_RESULT (ic)))
2727     {
2728
2729       _G.accInUse++;
2730       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2731       _G.accInUse--;
2732
2733       assignResultValue (IC_RESULT (ic));
2734
2735       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2736     }
2737
2738   /* adjust the stack for parameters if
2739      required */
2740   if (ic->parmBytes)
2741     {
2742       int i;
2743       if (options.stack10bit) {
2744           if (ic->parmBytes <= 10) {
2745               emitcode(";","stack adjustment for parms");
2746               for (i=0; i < ic->parmBytes ; i++) {
2747                   emitcode("pop","acc");
2748               }
2749           } else {            
2750               PROTECT_SP;
2751               emitcode ("clr","c");
2752               emitcode ("mov","a,sp");
2753               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2754               emitcode ("mov","sp,a");
2755               emitcode ("mov","a,esp");
2756               emitcode ("anl","a,#3");
2757               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2758               emitcode ("mov","esp,a");   
2759               UNPROTECT_SP;
2760           }
2761       } else {
2762           if (ic->parmBytes > 3) {
2763               emitcode ("mov", "a,%s", spname);
2764               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2765               emitcode ("mov", "%s,a", spname);
2766           }
2767           else
2768               for (i = 0; i < ic->parmBytes; i++)
2769                   emitcode ("dec", "%s", spname);
2770           
2771       }
2772     }
2773   /* if register bank was saved then unsave them */
2774   if (restoreBank)
2775     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2776   
2777   /* if we hade saved some registers then
2778      unsave them */
2779   if (ic->regsSaved)
2780     unsaveRegisters (ic);
2781
2782 }
2783
2784 /*-----------------------------------------------------------------*/
2785 /* resultRemat - result  is rematerializable                       */
2786 /*-----------------------------------------------------------------*/
2787 static int
2788 resultRemat (iCode * ic)
2789 {
2790   if (SKIP_IC (ic) || ic->op == IFX)
2791     return 0;
2792
2793   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2794     {
2795       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2796       if (sym->remat && !POINTER_SET (ic))
2797         return 1;
2798     }
2799
2800   return 0;
2801 }
2802
2803 #if defined(__BORLANDC__) || defined(_MSC_VER)
2804 #define STRCASECMP stricmp
2805 #else
2806 #define STRCASECMP strcasecmp
2807 #endif
2808
2809 /*-----------------------------------------------------------------*/
2810 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2811 /*-----------------------------------------------------------------*/
2812 static bool
2813 inExcludeList (char *s)
2814 {
2815   int i = 0;
2816
2817   if (options.excludeRegs[i] &&
2818       STRCASECMP (options.excludeRegs[i], "none") == 0)
2819     return FALSE;
2820
2821   for (i = 0; options.excludeRegs[i]; i++)
2822     {
2823       if (options.excludeRegs[i] &&
2824           STRCASECMP (s, options.excludeRegs[i]) == 0)
2825         return TRUE;
2826     }
2827   return FALSE;
2828 }
2829
2830 /*-----------------------------------------------------------------*/
2831 /* genFunction - generated code for function entry                 */
2832 /*-----------------------------------------------------------------*/
2833 static void
2834 genFunction (iCode * ic)
2835 {
2836   symbol *sym;
2837   sym_link *ftype;
2838   bool   switchedPSW = FALSE;
2839
2840   D (emitcode (";", "genFunction "););
2841
2842   _G.nRegsSaved = 0;
2843   /* create the function header */
2844   emitcode (";", "-----------------------------------------");
2845   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2846   emitcode (";", "-----------------------------------------");
2847
2848   emitcode ("", "%s:", sym->rname);
2849   ftype = operandType (IC_LEFT (ic));
2850
2851   if (IFFUNC_ISNAKED(ftype))
2852   {
2853       emitcode(";", "naked function: no prologue.");
2854       return;
2855   }
2856   
2857   if (options.stack_probe) 
2858       emitcode ("lcall","__stack_probe");
2859   /* if critical function then turn interrupts off */
2860   if (IFFUNC_ISCRITICAL (ftype))
2861     emitcode ("clr", "ea");
2862
2863   /* here we need to generate the equates for the
2864      register bank if required */
2865   if (FUNC_REGBANK (ftype) != rbank)
2866     {
2867       int i;
2868
2869       rbank = FUNC_REGBANK (ftype);
2870       for (i = 0; i < ds390_nRegs; i++)
2871         {
2872           if (regs390[i].print) {
2873               if (strcmp (regs390[i].base, "0") == 0)
2874                   emitcode ("", "%s !equ !constbyte",
2875                             regs390[i].dname,
2876                             8 * rbank + regs390[i].offset);
2877               else
2878                   emitcode ("", "%s !equ %s + !constbyte",
2879                             regs390[i].dname,
2880                             regs390[i].base,
2881                             8 * rbank + regs390[i].offset);
2882           }
2883         }
2884     }
2885
2886   /* if this is an interrupt service routine then
2887      save acc, b, dpl, dph  */
2888   if (IFFUNC_ISISR (sym->type))
2889       { /* is ISR */
2890       if (!inExcludeList ("acc"))
2891         emitcode ("push", "acc");
2892       if (!inExcludeList ("b"))
2893         emitcode ("push", "b");
2894       if (!inExcludeList ("dpl"))
2895         emitcode ("push", "dpl");
2896       if (!inExcludeList ("dph"))
2897         emitcode ("push", "dph");
2898       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2899         {
2900           emitcode ("push", "dpx");
2901           /* Make sure we're using standard DPTR */
2902           emitcode ("push", "dps");
2903           emitcode ("mov", "dps,#0");
2904           if (options.stack10bit)
2905             {
2906               /* This ISR could conceivably use DPTR2. Better save it. */
2907               emitcode ("push", "dpl1");
2908               emitcode ("push", "dph1");
2909               emitcode ("push", "dpx1");
2910               emitcode ("push",  DP2_RESULT_REG);
2911             }
2912         }
2913       /* if this isr has no bank i.e. is going to
2914          run with bank 0 , then we need to save more
2915          registers :-) */
2916       if (!FUNC_REGBANK (sym->type))
2917         {
2918             int i;
2919
2920           /* if this function does not call any other
2921              function then we can be economical and
2922              save only those registers that are used */
2923           if (!IFFUNC_HASFCALL(sym->type))
2924             {
2925
2926               /* if any registers used */
2927               if (sym->regsUsed)
2928                 {
2929                   /* save the registers used */
2930                   for (i = 0; i < sym->regsUsed->size; i++)
2931                     {
2932                       if (bitVectBitValue (sym->regsUsed, i) ||
2933                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2934                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2935                     }
2936                 }
2937
2938             }
2939           else
2940             {
2941               /* this function has  a function call cannot
2942                  determines register usage so we will have to push the
2943                  entire bank */
2944               saveRBank (0, ic, FALSE);
2945               if (options.parms_in_bank1) {
2946                   for (i=0; i < 8 ; i++ ) {
2947                       emitcode ("push","%s",rb1regs[i]);
2948                   }
2949               }
2950             }
2951         }
2952         else
2953         {
2954             /* This ISR uses a non-zero bank.
2955              *
2956              * We assume that the bank is available for our
2957              * exclusive use.
2958              *
2959              * However, if this ISR calls a function which uses some
2960              * other bank, we must save that bank entirely.
2961              */
2962             unsigned long banksToSave = 0;
2963             
2964             if (IFFUNC_HASFCALL(sym->type))
2965             {
2966
2967 #define MAX_REGISTER_BANKS 4
2968
2969                 iCode *i;
2970                 int ix;
2971
2972                 for (i = ic; i; i = i->next)
2973                 {
2974                     if (i->op == ENDFUNCTION)
2975                     {
2976                         /* we got to the end OK. */
2977                         break;
2978                     }
2979                     
2980                     if (i->op == CALL)
2981                     {
2982                         sym_link *dtype;
2983                         
2984                         dtype = operandType (IC_LEFT(i));
2985                         if (dtype 
2986                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2987                         {
2988                              /* Mark this bank for saving. */
2989                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2990                              {
2991                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2992                              }
2993                              else
2994                              {
2995                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2996                              }
2997                              
2998                              /* And note that we don't need to do it in 
2999                               * genCall.
3000                               */
3001                              i->bankSaved = 1;
3002                         }
3003                     }
3004                     if (i->op == PCALL)
3005                     {
3006                         /* This is a mess; we have no idea what
3007                          * register bank the called function might
3008                          * use.
3009                          *
3010                          * The only thing I can think of to do is
3011                          * throw a warning and hope.
3012                          */
3013                         werror(W_FUNCPTR_IN_USING_ISR);   
3014                     }
3015                 }
3016
3017                 if (banksToSave && options.useXstack)
3018                 {
3019                     /* Since we aren't passing it an ic, 
3020                      * saveRBank will assume r0 is available to abuse.
3021                      *
3022                      * So switch to our (trashable) bank now, so
3023                      * the caller's R0 isn't trashed.
3024                      */
3025                     emitcode ("push", "psw");
3026                     emitcode ("mov", "psw,#!constbyte", 
3027                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3028                     switchedPSW = TRUE;
3029                 }
3030                 
3031                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3032                 {
3033                      if (banksToSave & (1 << ix))
3034                      {
3035                          saveRBank(ix, NULL, FALSE);
3036                      }
3037                 }
3038             }
3039             // TODO: this needs a closer look
3040             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3041         }
3042     }
3043   else
3044     {
3045       /* if callee-save to be used for this function
3046          then save the registers being used in this function */
3047       if (IFFUNC_CALLEESAVES(sym->type))
3048         {
3049           int i;
3050
3051           /* if any registers used */
3052           if (sym->regsUsed)
3053             {
3054               /* save the registers used */
3055               for (i = 0; i < sym->regsUsed->size; i++)
3056                 {
3057                   if (bitVectBitValue (sym->regsUsed, i) ||
3058                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3059                     {
3060                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3061                       _G.nRegsSaved++;
3062                     }
3063                 }
3064             }
3065         }
3066     }
3067
3068   /* set the register bank to the desired value */
3069   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3070    && !switchedPSW)
3071     {
3072       emitcode ("push", "psw");
3073       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3074     }
3075
3076   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3077        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3078       if (options.stack10bit) {
3079           emitcode ("push","_bpx");
3080           emitcode ("push","_bpx+1");
3081           emitcode ("mov","_bpx,%s",spname);
3082           emitcode ("mov","_bpx+1,esp");
3083           emitcode ("anl","_bpx+1,#3");
3084       } else {
3085           if (options.useXstack) {
3086               emitcode ("mov", "r0,%s", spname);
3087               emitcode ("mov", "a,_bp");
3088               emitcode ("movx", "@r0,a");
3089               emitcode ("inc", "%s", spname);
3090           } else {
3091               /* set up the stack */
3092               emitcode ("push", "_bp"); /* save the callers stack  */
3093           }
3094           emitcode ("mov", "_bp,%s", spname);
3095       }
3096   }
3097
3098   /* adjust the stack for the function */
3099   if (sym->stack) {
3100       int i = sym->stack;
3101       if (options.stack10bit) {
3102           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3103           assert (sym->recvSize <= 4);
3104           if (sym->stack <= 8) {
3105               while (i--) emitcode ("push","acc");
3106           } else {
3107               PROTECT_SP;
3108               emitcode ("mov","a,sp");
3109               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3110               emitcode ("mov","sp,a");
3111               emitcode ("mov","a,esp");
3112               emitcode ("anl","a,#3");
3113               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3114               emitcode ("mov","esp,a");
3115               UNPROTECT_SP;
3116           }
3117       } else {
3118           if (i > 256)
3119               werror (W_STACK_OVERFLOW, sym->name);
3120           
3121           if (i > 3 && sym->recvSize < 4) {
3122               
3123               emitcode ("mov", "a,sp");
3124               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3125               emitcode ("mov", "sp,a");
3126               
3127           } else
3128               while (i--)
3129                   emitcode ("inc", "sp");
3130       }
3131   }
3132
3133   if (sym->xstack)
3134     {
3135
3136       emitcode ("mov", "a,_spx");
3137       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3138       emitcode ("mov", "_spx,a");
3139     }
3140
3141 }
3142
3143 /*-----------------------------------------------------------------*/
3144 /* genEndFunction - generates epilogue for functions               */
3145 /*-----------------------------------------------------------------*/
3146 static void
3147 genEndFunction (iCode * ic)
3148 {
3149   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3150
3151   D (emitcode (";", "genEndFunction "););
3152
3153   if (IFFUNC_ISNAKED(sym->type))
3154   {
3155       emitcode(";", "naked function: no epilogue.");
3156       return;
3157   }
3158
3159   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3160        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3161
3162       if (options.stack10bit) {
3163           PROTECT_SP;     
3164           emitcode ("mov", "sp,_bpx", spname);
3165           emitcode ("mov", "esp,_bpx+1", spname);
3166           UNPROTECT_SP;
3167       } else {
3168           emitcode ("mov", "%s,_bp", spname);
3169       }
3170   }
3171
3172   /* if use external stack but some variables were
3173      added to the local stack then decrement the
3174      local stack */
3175   if (options.useXstack && sym->stack) {
3176       emitcode ("mov", "a,sp");
3177       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3178       emitcode ("mov", "sp,a");
3179   }
3180
3181
3182   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3183        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3184
3185       if (options.useXstack) {
3186           emitcode ("mov", "r0,%s", spname);
3187           emitcode ("movx", "a,@r0");
3188           emitcode ("mov", "_bp,a");
3189           emitcode ("dec", "%s", spname);
3190       } else {
3191           if (options.stack10bit) {
3192               emitcode ("pop", "_bpx+1");
3193               emitcode ("pop", "_bpx");
3194           } else {
3195               emitcode ("pop", "_bp");
3196           }
3197       }
3198   }
3199
3200   /* restore the register bank  */
3201   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3202   {
3203     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3204      || !options.useXstack)
3205     {
3206         /* Special case of ISR using non-zero bank with useXstack
3207          * is handled below.
3208          */
3209         emitcode ("pop", "psw");
3210     }
3211   } 
3212
3213   if (IFFUNC_ISISR (sym->type))
3214       { /* is ISR */  
3215
3216       /* now we need to restore the registers */
3217       /* if this isr has no bank i.e. is going to
3218          run with bank 0 , then we need to save more
3219          registers :-) */
3220       if (!FUNC_REGBANK (sym->type))
3221         {
3222             int i;
3223           /* if this function does not call any other
3224              function then we can be economical and
3225              save only those registers that are used */
3226           if (!IFFUNC_HASFCALL(sym->type))
3227             {
3228
3229               /* if any registers used */
3230               if (sym->regsUsed)
3231                 {
3232                   /* save the registers used */
3233                   for (i = sym->regsUsed->size; i >= 0; i--)
3234                     {
3235                       if (bitVectBitValue (sym->regsUsed, i) ||
3236                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3237                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3238                     }
3239                 }
3240
3241             }
3242           else
3243             {
3244               /* this function has  a function call cannot
3245                  determines register usage so we will have to pop the
3246                  entire bank */
3247               if (options.parms_in_bank1) {
3248                   for (i = 7 ; i >= 0 ; i-- ) {
3249                       emitcode ("pop","%s",rb1regs[i]);
3250                   }
3251               }
3252               unsaveRBank (0, ic, FALSE);
3253             }
3254         }
3255         else
3256         {
3257             /* This ISR uses a non-zero bank.
3258              *
3259              * Restore any register banks saved by genFunction
3260              * in reverse order.
3261              */
3262             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3263             int ix;
3264           
3265             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3266             {
3267                 if (savedBanks & (1 << ix))
3268                 {
3269                     unsaveRBank(ix, NULL, FALSE);
3270                 }
3271             }
3272             
3273             if (options.useXstack)
3274             {
3275                 /* Restore bank AFTER calling unsaveRBank,
3276                  * since it can trash r0.
3277                  */
3278                 emitcode ("pop", "psw");
3279             }
3280         }
3281
3282       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3283         {
3284           if (options.stack10bit)
3285             {
3286               emitcode ("pop", DP2_RESULT_REG);
3287               emitcode ("pop", "dpx1");
3288               emitcode ("pop", "dph1");
3289               emitcode ("pop", "dpl1");
3290             }
3291           emitcode ("pop", "dps");
3292           emitcode ("pop", "dpx");
3293         }
3294       if (!inExcludeList ("dph"))
3295         emitcode ("pop", "dph");
3296       if (!inExcludeList ("dpl"))
3297         emitcode ("pop", "dpl");
3298       if (!inExcludeList ("b"))
3299         emitcode ("pop", "b");
3300       if (!inExcludeList ("acc"))
3301         emitcode ("pop", "acc");
3302
3303       if (IFFUNC_ISCRITICAL (sym->type))
3304         emitcode ("setb", "ea");
3305
3306       /* if debug then send end of function */
3307       if (options.debug && currFunc) {
3308           _G.debugLine = 1;
3309           emitcode ("", "C$%s$%d$%d$%d ==.",
3310                     FileBaseName (ic->filename), currFunc->lastLine,
3311                     ic->level, ic->block);
3312           if (IS_STATIC (currFunc->etype))
3313             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3314           else
3315             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3316           _G.debugLine = 0;
3317         }
3318
3319       emitcode ("reti", "");
3320     }
3321   else
3322     {
3323       if (IFFUNC_ISCRITICAL (sym->type))
3324         emitcode ("setb", "ea");
3325
3326       if (IFFUNC_CALLEESAVES(sym->type))
3327         {
3328           int i;
3329
3330           /* if any registers used */
3331           if (sym->regsUsed)
3332             {
3333               /* save the registers used */
3334               for (i = sym->regsUsed->size; i >= 0; i--)
3335                 {
3336                   if (bitVectBitValue (sym->regsUsed, i) ||
3337                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3338                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3339                 }
3340             }
3341
3342         }
3343
3344       /* if debug then send end of function */
3345       if (options.debug && currFunc)
3346         {
3347           _G.debugLine = 1;
3348           emitcode ("", "C$%s$%d$%d$%d ==.",
3349                     FileBaseName (ic->filename), currFunc->lastLine,
3350                     ic->level, ic->block);
3351           if (IS_STATIC (currFunc->etype))
3352             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3353           else
3354             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3355           _G.debugLine = 0;
3356         }
3357
3358       emitcode ("ret", "");
3359     }
3360
3361 }
3362
3363 /*-----------------------------------------------------------------*/
3364 /* genJavaNativeRet - generate code for return JavaNative          */
3365 /*-----------------------------------------------------------------*/
3366 static void genJavaNativeRet(iCode *ic)
3367 {
3368     int i, size;
3369
3370     aopOp (IC_LEFT (ic), ic, FALSE, 
3371            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3372     size = AOP_SIZE (IC_LEFT (ic));
3373
3374     assert (size <= 4);
3375
3376     /* it is assigned to GPR0-R3 then push them */
3377     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3378         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3379         for (i = 0 ; i < size ; i++ ) {
3380             emitcode ("push","%s",
3381                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3382         }
3383         for (i = (size-1) ; i >= 0 ; i--) {
3384             emitcode ("pop","a%s",javaRet[i]);
3385         }
3386     } else {
3387         for (i = 0 ; i < size ; i++) 
3388             emitcode ("mov","%s,%s",javaRet[i],
3389                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3390     }
3391     for (i = size ; i < 4 ; i++ )
3392             emitcode ("mov","%s,#0",javaRet[i]);
3393     return;
3394 }
3395
3396 /*-----------------------------------------------------------------*/
3397 /* genRet - generate code for return statement                     */
3398 /*-----------------------------------------------------------------*/
3399 static void
3400 genRet (iCode * ic)
3401 {
3402   int size, offset = 0, pushed = 0;
3403
3404   D (emitcode (";", "genRet "););
3405
3406   /* if we have no return value then
3407      just generate the "ret" */
3408   if (!IC_LEFT (ic))
3409     goto jumpret;
3410
3411   /* if this is a JavaNative function then return 
3412      value in different register */
3413   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3414       genJavaNativeRet(ic);
3415       goto jumpret;
3416   }
3417   /* we have something to return then
3418      move the return value into place */
3419   aopOp (IC_LEFT (ic), ic, FALSE, 
3420          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3421   size = AOP_SIZE (IC_LEFT (ic));
3422
3423   _startLazyDPSEvaluation ();
3424   while (size--)
3425     {
3426       char *l;
3427       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3428         {
3429           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3430                       FALSE, TRUE, NULL);
3431           emitcode ("push", "%s", l);
3432           pushed++;
3433         }
3434       else
3435         {
3436           /* Since A is the last element of fReturn,
3437            * is is OK to clobber it in the aopGet.
3438            */
3439           l = aopGet (AOP (IC_LEFT (ic)), offset,
3440                       FALSE, FALSE, NULL);
3441           if (strcmp (fReturn[offset], l))
3442             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3443         }
3444     }
3445   _endLazyDPSEvaluation ();
3446
3447   if (pushed)
3448     {
3449       while (pushed)
3450         {
3451           pushed--;
3452           if (strcmp (fReturn[pushed], "a"))
3453             emitcode ("pop", fReturn[pushed]);
3454           else
3455             emitcode ("pop", "acc");
3456         }
3457     }
3458   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3459
3460 jumpret:
3461   /* generate a jump to the return label
3462      if the next is not the return statement */
3463   if (!(ic->next && ic->next->op == LABEL &&
3464         IC_LABEL (ic->next) == returnLabel))
3465
3466     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3467
3468 }
3469
3470 /*-----------------------------------------------------------------*/
3471 /* genLabel - generates a label                                    */
3472 /*-----------------------------------------------------------------*/
3473 static void
3474 genLabel (iCode * ic)
3475 {
3476   /* special case never generate */
3477   if (IC_LABEL (ic) == entryLabel)
3478     return;
3479
3480   D (emitcode (";", "genLabel ");
3481     );
3482
3483   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3484 }
3485
3486 /*-----------------------------------------------------------------*/
3487 /* genGoto - generates a ljmp                                      */
3488 /*-----------------------------------------------------------------*/
3489 static void
3490 genGoto (iCode * ic)
3491 {
3492   D (emitcode (";", "genGoto ");
3493     );
3494   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3495 }
3496
3497 /*-----------------------------------------------------------------*/
3498 /* findLabelBackwards: walks back through the iCode chain looking  */
3499 /* for the given label. Returns number of iCode instructions     */
3500 /* between that label and given ic.          */
3501 /* Returns zero if label not found.          */
3502 /*-----------------------------------------------------------------*/
3503 static int
3504 findLabelBackwards (iCode * ic, int key)
3505 {
3506   int count = 0;
3507
3508   while (ic->prev)
3509     {
3510       ic = ic->prev;
3511       count++;
3512
3513       /* If we have any pushes or pops, we cannot predict the distance.
3514          I don't like this at all, this should be dealt with in the 
3515          back-end */
3516       if (ic->op == IPUSH || ic->op == IPOP) {
3517         return 0;
3518       }
3519
3520       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3521         {
3522           /* printf("findLabelBackwards = %d\n", count); */
3523           return count;
3524         }
3525     }
3526
3527   return 0;
3528 }
3529
3530 /*-----------------------------------------------------------------*/
3531 /* genPlusIncr :- does addition with increment if possible         */
3532 /*-----------------------------------------------------------------*/
3533 static bool
3534 genPlusIncr (iCode * ic)
3535 {
3536   unsigned int icount;
3537   unsigned int size = getDataSize (IC_RESULT (ic));
3538
3539   /* will try to generate an increment */
3540   /* if the right side is not a literal
3541      we cannot */
3542   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3543     return FALSE;
3544
3545   /* if the literal value of the right hand side
3546      is greater than 4 then it is not worth it */
3547   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3548     return FALSE;
3549
3550   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3551       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3552       while (icount--) {
3553           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3554       }
3555       return TRUE;
3556   }
3557   /* if increment 16 bits in register */
3558   if (
3559        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3560        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3561        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3562        (size > 1) &&
3563        (icount == 1))
3564     {
3565       symbol  *tlbl;
3566       int     emitTlbl;
3567       int     labelRange;
3568       char    *l;
3569
3570       /* If the next instruction is a goto and the goto target
3571        * is <= 5 instructions previous to this, we can generate
3572        * jumps straight to that target.
3573        */
3574       if (ic->next && ic->next->op == GOTO
3575           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3576           && labelRange <= 5)
3577         {
3578           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3579           tlbl = IC_LABEL (ic->next);
3580           emitTlbl = 0;
3581         }
3582       else
3583         {
3584           tlbl = newiTempLabel (NULL);
3585           emitTlbl = 1;
3586         }
3587         
3588       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3589       emitcode ("inc", "%s", l);
3590       
3591       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3592           IS_AOP_PREG (IC_RESULT (ic)))
3593       {   
3594         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3595       }
3596       else
3597       {
3598           emitcode ("clr", "a");
3599           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3600       }
3601
3602       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3603       emitcode ("inc", "%s", l);
3604       if (size > 2)
3605         {
3606             if (!strcmp(l, "acc"))
3607             {
3608                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3609             }
3610             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3611                      IS_AOP_PREG (IC_RESULT (ic)))
3612             {
3613                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3614             }
3615             else
3616             {
3617                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3618             }
3619
3620             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3621             emitcode ("inc", "%s", l);
3622         }
3623       if (size > 3)
3624         {
3625             if (!strcmp(l, "acc"))
3626             {
3627                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3628             }
3629             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3630                      IS_AOP_PREG (IC_RESULT (ic)))
3631             {
3632                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3633             }
3634             else
3635             {
3636                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3637             }
3638
3639             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3640             emitcode ("inc", "%s", l);  }
3641
3642       if (emitTlbl)
3643         {
3644           emitcode ("", "!tlabeldef", tlbl->key + 100);
3645         }
3646       return TRUE;
3647     }
3648
3649   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3650       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3651       options.model == MODEL_FLAT24 ) {
3652
3653       switch (size) {
3654       case 3:
3655           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3656       case 2:
3657           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3658       case 1:
3659           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3660           break;
3661       }
3662       while (icount--) emitcode ("inc","dptr");      
3663       return TRUE;
3664   }
3665
3666   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3667       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3668       icount <= 5 ) {
3669       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3670       while (icount--) emitcode ("inc","dptr");
3671       emitcode ("mov","dps,#0");
3672       return TRUE;
3673   }
3674
3675   /* if the sizes are greater than 1 then we cannot */
3676   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3677       AOP_SIZE (IC_LEFT (ic)) > 1)
3678     return FALSE;
3679
3680   /* we can if the aops of the left & result match or
3681      if they are in registers and the registers are the
3682      same */
3683   if (
3684        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3685        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3686        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3687     {
3688
3689       if (icount > 3)
3690         {
3691           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3692           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3693           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3694         }
3695       else
3696         {
3697
3698           _startLazyDPSEvaluation ();
3699           while (icount--)
3700             {
3701               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3702             }
3703           _endLazyDPSEvaluation ();
3704         }
3705
3706       return TRUE;
3707     }
3708
3709   return FALSE;
3710 }
3711
3712 /*-----------------------------------------------------------------*/
3713 /* outBitAcc - output a bit in acc                                 */
3714 /*-----------------------------------------------------------------*/
3715 static void
3716 outBitAcc (operand * result)
3717 {
3718   symbol *tlbl = newiTempLabel (NULL);
3719   /* if the result is a bit */
3720   if (AOP_TYPE (result) == AOP_CRY)
3721     {
3722       aopPut (AOP (result), "a", 0);
3723     }
3724   else
3725     {
3726       emitcode ("jz", "!tlabel", tlbl->key + 100);
3727       emitcode ("mov", "a,%s", one);
3728       emitcode ("", "!tlabeldef", tlbl->key + 100);
3729       outAcc (result);
3730     }
3731 }
3732
3733 /*-----------------------------------------------------------------*/
3734 /* genPlusBits - generates code for addition of two bits           */
3735 /*-----------------------------------------------------------------*/
3736 static void
3737 genPlusBits (iCode * ic)
3738 {
3739   D (emitcode (";", "genPlusBits "););
3740     
3741   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3742     {
3743       symbol *lbl = newiTempLabel (NULL);
3744       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3745       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3746       emitcode ("cpl", "c");
3747       emitcode ("", "!tlabeldef", (lbl->key + 100));
3748       outBitC (IC_RESULT (ic));
3749     }
3750   else
3751     {
3752       emitcode ("clr", "a");
3753       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3754       emitcode ("rlc", "a");
3755       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3756       emitcode ("addc", "a,#0");
3757       outAcc (IC_RESULT (ic));
3758     }
3759 }
3760
3761 static void
3762 adjustArithmeticResult (iCode * ic)
3763 {
3764   if (opIsGptr (IC_RESULT (ic)) &&
3765       opIsGptr (IC_LEFT (ic)) &&
3766       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3767     {
3768       aopPut (AOP (IC_RESULT (ic)),
3769               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3770               GPTRSIZE - 1);
3771     }
3772
3773   if (opIsGptr (IC_RESULT (ic)) &&
3774       opIsGptr (IC_RIGHT (ic)) &&
3775       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3776     {
3777       aopPut (AOP (IC_RESULT (ic)),
3778             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3779               GPTRSIZE - 1);
3780     }
3781
3782   if (opIsGptr (IC_RESULT (ic)) &&
3783       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3784       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3785       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3786       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3787     {
3788       char buff[5];
3789       SNPRINTF (buff, sizeof(buff), 
3790                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3791       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3792     }
3793 }
3794
3795 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3796 // generates the result if possible. If result is generated, returns TRUE; otherwise
3797 // returns false and caller must deal with fact that result isn't aopOp'd.
3798 bool aopOp3(iCode * ic)
3799 {
3800     bool dp1InUse, dp2InUse;
3801     bool useDp2;
3802     
3803     // First, generate the right opcode. DPTR may be used if neither left nor result are
3804     // of type AOP_STR.
3805     
3806 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3807 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3808 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3809 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3810 //      );
3811 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3812 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3813 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3814 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3815 //      );
3816     
3817     // Right uses DPTR unless left or result is an AOP_STR; however,
3818     // if right is an AOP_STR, it must use DPTR regardless.
3819     if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3820      && !AOP_IS_STR(IC_RIGHT(ic)))
3821     {
3822         useDp2 = TRUE;
3823     }
3824     else
3825     {
3826         useDp2 = FALSE;
3827     }
3828         
3829     aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3830     
3831     // if the right used DPTR, left MUST use DPTR2.
3832     // if the right used DPTR2, left MUST use DPTR.
3833     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3834     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3835     // enabling us to assign DPTR to result.
3836      
3837     if (AOP_USESDPTR(IC_RIGHT(ic)))
3838     {
3839         useDp2 = TRUE;
3840     }
3841     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3842     {
3843         useDp2 = FALSE;
3844     }
3845     else
3846     {
3847         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3848         {
3849             useDp2 = TRUE;
3850         }
3851         else
3852         {
3853             useDp2 = FALSE;
3854         }
3855     }
3856
3857     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3858     
3859     // We've op'd the left & right. So, if left or right are the same operand as result, 
3860     // we know aopOp will succeed, and we can just do it & bail.
3861     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3862         isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3863     {
3864 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
3865         aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3866         return TRUE;
3867     }
3868     
3869     // Note which dptrs are currently in use.
3870     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3871     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3872     
3873     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
3874     // generate it.
3875     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3876     {
3877         return FALSE;
3878     }
3879     
3880     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3881     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3882     {
3883         return FALSE;
3884     }
3885     
3886     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
3887     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3888     {
3889         return FALSE;
3890     }
3891
3892     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3893
3894     // Some sanity checking...
3895     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3896     {
3897         fprintf(stderr,
3898                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3899                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3900         emitcode(";", ">>> unexpected DPTR here.");
3901     }
3902     
3903     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3904     {
3905         fprintf(stderr,
3906                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3907                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3908         emitcode(";", ">>> unexpected DPTR2 here.");
3909     }    
3910     
3911     return TRUE;
3912 }
3913
3914 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3915 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3916 // will be set TRUE. The caller must then handle the case specially, noting
3917 // that the IC_RESULT operand is not aopOp'd.
3918 // 
3919 #define AOP_OP_3_NOFATAL(ic, rc) \
3920             do { rc = !aopOp3(ic); } while (0)
3921
3922 // aopOp the left & right operands of an ic.
3923 #define AOP_OP_2(ic) \
3924     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3925     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3926
3927 // convienience macro.
3928 #define AOP_SET_LOCALS(ic) \
3929     left = IC_LEFT(ic); \
3930     right = IC_RIGHT(ic); \
3931     result = IC_RESULT(ic);
3932
3933
3934 // Given an integer value of pushedSize bytes on the stack,
3935 // adjust it to be resultSize bytes, either by discarding
3936 // the most significant bytes or by zero-padding.
3937 //
3938 // On exit from this macro, pushedSize will have been adjusted to
3939 // equal resultSize, and ACC may be trashed.
3940 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3941       /* If the pushed data is bigger than the result,          \
3942        * simply discard unused bytes. Icky, but works.          \
3943        */                                                       \
3944       while (pushedSize > resultSize)                           \
3945       {                                                         \
3946           D (emitcode (";", "discarding unused result byte."););\
3947           emitcode ("pop", "acc");                              \
3948           pushedSize--;                                         \
3949       }                                                         \
3950       if (pushedSize < resultSize)                              \
3951       {                                                         \
3952           emitcode ("clr", "a");                                \
3953           /* Conversly, we haven't pushed enough here.          \
3954            * just zero-pad, and all is well.                    \
3955            */                                                   \
3956           while (pushedSize < resultSize)                       \
3957           {                                                     \
3958               emitcode("push", "acc");                          \
3959               pushedSize++;                                     \
3960           }                                                     \
3961       }                                                         \
3962       assert(pushedSize == resultSize);
3963
3964 /*-----------------------------------------------------------------*/
3965 /* genPlus - generates code for addition                           */
3966 /*-----------------------------------------------------------------*/
3967 static void
3968 genPlus (iCode * ic)
3969 {
3970   int size, offset = 0;
3971   bool pushResult;
3972   int rSize;
3973
3974   D (emitcode (";", "genPlus "););
3975
3976   /* special cases :- */
3977   if ( AOP_IS_STR(IC_LEFT(ic)) &&
3978       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3979       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3980       size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3981       if (size <= 9) {
3982           while (size--) emitcode ("inc","dptr");
3983       } else {
3984           emitcode ("mov","a,dpl");
3985           emitcode ("add","a,#!constbyte",size & 0xff);
3986           emitcode ("mov","dpl,a");
3987           emitcode ("mov","a,dph");
3988           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3989           emitcode ("mov","dph,a");
3990           emitcode ("mov","a,dpx");
3991           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3992           emitcode ("mov","dpx,a");
3993       }
3994       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3995       return ;
3996   }
3997   if ( IS_SYMOP(IC_LEFT(ic)) && 
3998        OP_SYMBOL(IC_LEFT(ic))->remat &&
3999        isOperandInFarSpace(IC_RIGHT(ic))) {
4000       operand *op = IC_RIGHT(ic);
4001       IC_RIGHT(ic) = IC_LEFT(ic);
4002       IC_LEFT(ic) = op;
4003   }
4004                 
4005   AOP_OP_3_NOFATAL (ic, pushResult);
4006     
4007   if (pushResult)
4008     {
4009       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4010     }
4011
4012   if (!pushResult)
4013     {
4014       /* if literal, literal on the right or
4015          if left requires ACC or right is already
4016          in ACC */
4017       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4018        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4019           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4020         {
4021           operand *t = IC_RIGHT (ic);
4022           IC_RIGHT (ic) = IC_LEFT (ic);
4023           IC_LEFT (ic) = t;
4024           emitcode (";", "Swapped plus args.");
4025         }
4026
4027       /* if both left & right are in bit
4028          space */
4029       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4030           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4031         {
4032           genPlusBits (ic);
4033           goto release;
4034         }
4035
4036       /* if left in bit space & right literal */
4037       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4038           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4039         {
4040           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4041           /* if result in bit space */
4042           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4043             {
4044               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4045                 emitcode ("cpl", "c");
4046               outBitC (IC_RESULT (ic));
4047             }
4048           else
4049             {
4050               size = getDataSize (IC_RESULT (ic));
4051               _startLazyDPSEvaluation ();
4052               while (size--)
4053                 {
4054                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4055                   emitcode ("addc", "a,#0");
4056                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4057                 }
4058               _endLazyDPSEvaluation ();
4059             }
4060           goto release;
4061         }
4062
4063       /* if I can do an increment instead
4064          of add then GOOD for ME */
4065       if (genPlusIncr (ic) == TRUE)
4066         {
4067           emitcode (";", "did genPlusIncr");
4068           goto release;
4069         }
4070
4071     }
4072   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4073
4074   _startLazyDPSEvaluation ();
4075   while (size--)
4076     {
4077       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4078         {
4079           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4080           if (offset == 0)
4081             emitcode ("add", "a,%s",
4082                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4083           else
4084             emitcode ("addc", "a,%s",
4085                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4086         }
4087       else
4088         {
4089           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4090           {
4091               /* right is going to use ACC or we would have taken the
4092                * above branch.
4093                */
4094               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4095        TR_AP("#3");
4096               D(emitcode(";", "+ AOP_ACC special case."););
4097               emitcode("xch", "a, %s", DP2_RESULT_REG);
4098           }
4099           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4100           if (offset == 0)
4101           {
4102             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4103             {
4104          TR_AP("#4");
4105                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4106             }
4107             else
4108             {
4109                 emitcode ("add", "a,%s",
4110                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4111                                   DP2_RESULT_REG));
4112             }
4113           }
4114           else
4115           {
4116             emitcode ("addc", "a,%s",
4117                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4118                           DP2_RESULT_REG));
4119           }
4120         }
4121       if (!pushResult)
4122         {
4123           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4124         }
4125       else
4126         {
4127           emitcode ("push", "acc");
4128         }
4129       offset++;
4130     }
4131   _endLazyDPSEvaluation ();
4132
4133   if (pushResult)
4134     {
4135       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4136
4137       size = getDataSize (IC_LEFT (ic));
4138       rSize = getDataSize (IC_RESULT (ic));
4139
4140       ADJUST_PUSHED_RESULT(size, rSize);
4141
4142       _startLazyDPSEvaluation ();
4143       while (size--)
4144         {
4145           emitcode ("pop", "acc");
4146           aopPut (AOP (IC_RESULT (ic)), "a", size);
4147         }
4148       _endLazyDPSEvaluation ();
4149     }
4150
4151   adjustArithmeticResult (ic);
4152
4153 release:
4154   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4155   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4156   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4157 }
4158
4159 /*-----------------------------------------------------------------*/
4160 /* genMinusDec :- does subtraction with deccrement if possible     */
4161 /*-----------------------------------------------------------------*/
4162 static bool
4163 genMinusDec (iCode * ic)
4164 {
4165   unsigned int icount;
4166   unsigned int size = getDataSize (IC_RESULT (ic));
4167
4168   /* will try to generate an increment */
4169   /* if the right side is not a literal
4170      we cannot */
4171   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4172     return FALSE;
4173
4174   /* if the literal value of the right hand side
4175      is greater than 4 then it is not worth it */
4176   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4177     return FALSE;
4178
4179   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4180       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4181       while (icount--) {
4182           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4183       }
4184       return TRUE;
4185   }
4186   /* if decrement 16 bits in register */
4187   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4188       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4189       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4190       (size > 1) &&
4191       (icount == 1))
4192     {
4193       symbol *tlbl;
4194       int    emitTlbl;
4195       int    labelRange;
4196       char   *l;
4197
4198       /* If the next instruction is a goto and the goto target
4199          * is <= 5 instructions previous to this, we can generate
4200          * jumps straight to that target.
4201        */
4202       if (ic->next && ic->next->op == GOTO
4203           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4204           && labelRange <= 5)
4205         {
4206           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4207           tlbl = IC_LABEL (ic->next);
4208           emitTlbl = 0;
4209         }
4210       else
4211         {
4212           tlbl = newiTempLabel (NULL);
4213           emitTlbl = 1;
4214         }
4215
4216       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4217       emitcode ("dec", "%s", l);
4218  
4219       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4220           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4221           IS_AOP_PREG (IC_RESULT (ic)))
4222       {     
4223           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4224       }
4225       else
4226       {
4227           emitcode ("mov", "a,#!constbyte",0xff);
4228           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4229       }
4230       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4231       emitcode ("dec", "%s", l);
4232       if (size > 2)
4233         {
4234             if (!strcmp(l, "acc"))
4235             {
4236                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4237             }
4238             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4239                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4240                      IS_AOP_PREG (IC_RESULT (ic)))
4241             {       
4242                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4243             }
4244             else
4245             {
4246                 emitcode ("mov", "a,#!constbyte",0xff);
4247                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4248             }
4249             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4250             emitcode ("dec", "%s", l);
4251         }
4252       if (size > 3)
4253         {
4254             if (!strcmp(l, "acc"))
4255             {
4256                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4257             }
4258             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4259                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4260                      IS_AOP_PREG (IC_RESULT (ic)))
4261             {       
4262                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4263             }
4264             else
4265             {
4266                 emitcode ("mov", "a,#!constbyte",0xff);
4267                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4268             }       
4269             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4270             emitcode ("dec", "%s", l);
4271         }
4272       if (emitTlbl)
4273         {
4274           emitcode ("", "!tlabeldef", tlbl->key + 100);
4275         }
4276       return TRUE;
4277     }
4278
4279   /* if the sizes are greater than 1 then we cannot */
4280   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4281       AOP_SIZE (IC_LEFT (ic)) > 1)
4282     return FALSE;
4283
4284   /* we can if the aops of the left & result match or
4285      if they are in registers and the registers are the
4286      same */
4287   if (
4288        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4289        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4290        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4291     {
4292
4293       _startLazyDPSEvaluation ();
4294       while (icount--)
4295         {
4296           emitcode ("dec", "%s",
4297                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4298         }
4299       _endLazyDPSEvaluation ();
4300
4301       return TRUE;
4302     }
4303
4304   return FALSE;
4305 }
4306
4307 /*-----------------------------------------------------------------*/
4308 /* addSign - complete with sign                                    */
4309 /*-----------------------------------------------------------------*/
4310 static void
4311 addSign (operand * result, int offset, int sign)
4312 {
4313   int size = (getDataSize (result) - offset);
4314   if (size > 0)
4315     {
4316       _startLazyDPSEvaluation();
4317       if (sign)
4318         {
4319           emitcode ("rlc", "a");
4320           emitcode ("subb", "a,acc");
4321           while (size--)
4322           {
4323             aopPut (AOP (result), "a", offset++);
4324           }
4325         }
4326       else
4327       {
4328         while (size--)
4329         {
4330           aopPut (AOP (result), zero, offset++);
4331         }
4332       }
4333       _endLazyDPSEvaluation();
4334     }
4335 }
4336
4337 /*-----------------------------------------------------------------*/
4338 /* genMinusBits - generates code for subtraction  of two bits      */
4339 /*-----------------------------------------------------------------*/
4340 static void
4341 genMinusBits (iCode * ic)
4342 {
4343   symbol *lbl = newiTempLabel (NULL);
4344
4345   D (emitcode (";", "genMinusBits "););
4346
4347   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4348     {
4349       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4350       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4351       emitcode ("cpl", "c");
4352       emitcode ("", "!tlabeldef", (lbl->key + 100));
4353       outBitC (IC_RESULT (ic));
4354     }
4355   else
4356     {
4357       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4358       emitcode ("subb", "a,acc");
4359       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4360       emitcode ("inc", "a");
4361       emitcode ("", "!tlabeldef", (lbl->key + 100));
4362       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4363       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4364     }
4365 }
4366
4367 /*-----------------------------------------------------------------*/
4368 /* genMinus - generates code for subtraction                       */
4369 /*-----------------------------------------------------------------*/
4370 static void
4371 genMinus (iCode * ic)
4372 {
4373     int size, offset = 0;
4374     int rSize;
4375     long lit = 0L;
4376     bool pushResult;
4377
4378     D (emitcode (";", "genMinus "););
4379
4380     AOP_OP_3_NOFATAL(ic, pushResult);   
4381
4382     if (!pushResult)
4383     {
4384       /* special cases :- */
4385       /* if both left & right are in bit space */
4386       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4387           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4388         {
4389           genMinusBits (ic);
4390           goto release;
4391         }
4392
4393       /* if I can do an decrement instead
4394          of subtract then GOOD for ME */
4395       if (genMinusDec (ic) == TRUE)
4396         goto release;
4397
4398     }
4399
4400   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4401
4402   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4403     {
4404       CLRC;
4405     }
4406   else
4407     {
4408       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4409       lit = -lit;
4410     }
4411
4412
4413   /* if literal, add a,#-lit, else normal subb */
4414   _startLazyDPSEvaluation ();
4415   while (size--) {
4416       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4417           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4418               emitcode ("mov","b,%s",
4419                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4420               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4421               emitcode ("subb","a,b");
4422           } else {
4423               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4424               emitcode ("subb", "a,%s",
4425                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4426                                 DP2_RESULT_REG));
4427           }
4428       } else {
4429           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4430           /* first add without previous c */
4431           if (!offset) {
4432               if (!size && lit==-1) {
4433                   emitcode ("dec", "a");
4434               } else {
4435                   emitcode ("add", "a,#!constbyte",
4436                             (unsigned int) (lit & 0x0FFL));
4437               }
4438           } else {
4439               emitcode ("addc", "a,#!constbyte",
4440                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4441           }
4442       }
4443       
4444       if (pushResult) {
4445           emitcode ("push", "acc");
4446       } else {
4447           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4448       }
4449       offset++;
4450   }
4451   _endLazyDPSEvaluation ();
4452   
4453   if (pushResult)
4454     {
4455       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4456
4457       size = getDataSize (IC_LEFT (ic));
4458       rSize = getDataSize (IC_RESULT (ic));
4459
4460       ADJUST_PUSHED_RESULT(size, rSize);
4461
4462       _startLazyDPSEvaluation ();
4463       while (size--)
4464         {
4465           emitcode ("pop", "acc");
4466           aopPut (AOP (IC_RESULT (ic)), "a", size);
4467         }
4468       _endLazyDPSEvaluation ();
4469     }
4470
4471   adjustArithmeticResult (ic);
4472
4473 release:
4474   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4475   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4476   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4477 }
4478
4479
4480 /*-----------------------------------------------------------------*/
4481 /* genMultbits :- multiplication of bits                           */
4482 /*-----------------------------------------------------------------*/
4483 static void
4484 genMultbits (operand * left,
4485              operand * right,
4486              operand * result,
4487              iCode   * ic)
4488 {
4489   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4490   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4491   aopOp(result, ic, TRUE, FALSE);
4492   outBitC (result);
4493 }
4494
4495
4496 /*-----------------------------------------------------------------*/
4497 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4498 /*-----------------------------------------------------------------*/
4499 static void
4500 genMultOneByte (operand * left,
4501                 operand * right,
4502                 operand * result,
4503                 iCode   * ic)
4504 {
4505   sym_link *opetype = operandType (result);
4506   symbol *lbl;
4507
4508
4509   /* (if two literals: the value is computed before) */
4510   /* if one literal, literal on the right */
4511   if (AOP_TYPE (left) == AOP_LIT)
4512     {
4513       operand *t = right;
4514       right = left;
4515       left = t;
4516       emitcode (";", "swapped left and right");
4517     }
4518
4519   if (SPEC_USIGN(opetype)
4520       // ignore the sign of left and right, what else can we do?
4521       || (SPEC_USIGN(operandType(left)) && 
4522           SPEC_USIGN(operandType(right)))) {
4523     // just an unsigned 8*8=8/16 multiply
4524     //emitcode (";","unsigned");
4525     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4526     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4527     emitcode ("mul", "ab");
4528    
4529     _G.accInUse++; _G.bInUse++;
4530     aopOp(result, ic, TRUE, FALSE);
4531       
4532       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4533       {
4534           // this should never happen
4535           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4536                    AOP_SIZE(result), __FILE__, lineno);
4537           exit (1);
4538       }      
4539       
4540     aopPut (AOP (result), "a", 0);
4541     _G.accInUse--; _G.bInUse--;
4542     if (AOP_SIZE(result)==2) 
4543     {
4544       aopPut (AOP (result), "b", 1);
4545     }
4546     return;
4547   }
4548
4549   // we have to do a signed multiply
4550
4551   emitcode (";", "signed");
4552   emitcode ("clr", "F0"); // reset sign flag
4553   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4554
4555   lbl=newiTempLabel(NULL);
4556   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4557   // left side is negative, 8-bit two's complement, this fails for -128
4558   emitcode ("setb", "F0"); // set sign flag
4559   emitcode ("cpl", "a");
4560   emitcode ("inc", "a");
4561
4562   emitcode ("", "!tlabeldef", lbl->key+100);
4563
4564   /* if literal */
4565   if (AOP_TYPE(right)==AOP_LIT) {
4566     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4567     /* AND literal negative */
4568     if ((int) val < 0) {
4569       emitcode ("cpl", "F0"); // complement sign flag
4570       emitcode ("mov", "b,#!constbyte", -val);
4571     } else {
4572       emitcode ("mov", "b,#!constbyte", val);
4573     }
4574   } else {
4575     lbl=newiTempLabel(NULL);
4576     emitcode ("mov", "b,a");
4577     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4578     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4579     // right side is negative, 8-bit two's complement
4580     emitcode ("cpl", "F0"); // complement sign flag
4581     emitcode ("cpl", "a");
4582     emitcode ("inc", "a");
4583     emitcode ("", "!tlabeldef", lbl->key+100);
4584   }
4585   emitcode ("mul", "ab");
4586     
4587   _G.accInUse++;_G.bInUse++;
4588   aopOp(result, ic, TRUE, FALSE);
4589     
4590   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4591   {
4592     // this should never happen
4593       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4594                AOP_SIZE(result), __FILE__, lineno);
4595       exit (1);
4596   }    
4597     
4598   lbl=newiTempLabel(NULL);
4599   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4600   // only ONE op was negative, we have to do a 8/16-bit two's complement
4601   emitcode ("cpl", "a"); // lsb
4602   if (AOP_SIZE(result)==1) {
4603     emitcode ("inc", "a");
4604   } else {
4605     emitcode ("add", "a,#1");
4606     emitcode ("xch", "a,b");
4607     emitcode ("cpl", "a"); // msb
4608     emitcode ("addc", "a,#0");
4609     emitcode ("xch", "a,b");
4610   }
4611
4612   emitcode ("", "!tlabeldef", lbl->key+100);
4613   aopPut (AOP (result), "a", 0);
4614   _G.accInUse--;_G.bInUse--;
4615   if (AOP_SIZE(result)==2) {
4616     aopPut (AOP (result), "b", 1);
4617   }
4618 }
4619
4620 /*-----------------------------------------------------------------*/
4621 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4622 /*-----------------------------------------------------------------*/
4623 static void genMultTwoByte (operand *left, operand *right, 
4624                             operand *result, iCode *ic)
4625 {
4626         sym_link *retype = getSpec(operandType(right));
4627         sym_link *letype = getSpec(operandType(left));
4628         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4629         symbol *lbl;
4630
4631         if (AOP_TYPE (left) == AOP_LIT) {
4632                 operand *t = right;
4633                 right = left;
4634                 left = t;
4635         }
4636         /* save EA bit in F1 */
4637         lbl = newiTempLabel(NULL);
4638         emitcode ("setb","F1");
4639         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4640         emitcode ("clr","F1");
4641         emitcode("","!tlabeldef",lbl->key+100);
4642
4643         /* load up MB with right */
4644         if (!umult) {
4645                 emitcode("clr","F0");
4646                 if (AOP_TYPE(right) == AOP_LIT) {
4647                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4648                         if (val < 0) {
4649                                 emitcode("setb","F0");
4650                                 val = -val;
4651                         }
4652                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4653                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4654                 } else {
4655                         lbl = newiTempLabel(NULL);
4656                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4657                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4658                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4659                         emitcode ("xch", "a,b");
4660                         emitcode ("cpl","a");
4661                         emitcode ("add", "a,#1");
4662                         emitcode ("xch", "a,b");
4663                         emitcode ("cpl", "a"); // msb
4664                         emitcode ("addc", "a,#0");
4665                         emitcode ("setb","F0");
4666                         emitcode ("","!tlabeldef",lbl->key+100);
4667                         emitcode ("mov","mb,b");
4668                         emitcode ("mov","mb,a");
4669                 }
4670         } else {
4671                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4672                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4673         }
4674         /* load up MA with left */
4675         if (!umult) {
4676                 lbl = newiTempLabel(NULL);
4677                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4678                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4679                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4680                 emitcode ("xch", "a,b");
4681                 emitcode ("cpl","a");
4682                 emitcode ("add", "a,#1");
4683                 emitcode ("xch", "a,b");
4684                 emitcode ("cpl", "a"); // msb
4685                 emitcode ("addc","a,#0");
4686                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4687                 emitcode ("setb","F0");
4688                 emitcode ("","!tlabeldef",lbl->key+100);
4689                 emitcode ("mov","ma,b");
4690                 emitcode ("mov","ma,a");
4691         } else {
4692                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4693                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4694         }
4695         /* wait for multiplication to finish */
4696         lbl = newiTempLabel(NULL);
4697         emitcode("","!tlabeldef", lbl->key+100);
4698         emitcode("mov","a,mcnt1");
4699         emitcode("anl","a,#!constbyte",0x80);
4700         emitcode("jnz","!tlabel",lbl->key+100);
4701         
4702         freeAsmop (left, NULL, ic, TRUE);
4703         freeAsmop (right, NULL, ic,TRUE);
4704         aopOp(result, ic, TRUE, FALSE);
4705
4706         /* if unsigned then simple */   
4707         if (umult) {
4708                 emitcode ("mov","a,ma");
4709                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4710                 emitcode ("mov","a,ma");
4711                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4712                 aopPut(AOP(result),"ma",1);
4713                 aopPut(AOP(result),"ma",0);
4714         } else {
4715                 emitcode("push","ma");
4716                 emitcode("push","ma");
4717                 emitcode("push","ma");
4718                 MOVA("ma");
4719                 /* negate result if needed */
4720                 lbl = newiTempLabel(NULL);      
4721                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4722                 emitcode("cpl","a");
4723                 emitcode("add","a,#1");
4724                 emitcode("","!tlabeldef", lbl->key+100);
4725                 if (AOP_TYPE(result) == AOP_ACC)
4726                 {
4727                     D(emitcode(";", "ACC special case."););
4728                     /* We know result is the only live aop, and 
4729                      * it's obviously not a DPTR2, so AP is available.
4730                      */
4731                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4732                 }
4733                 else
4734                 {
4735                     aopPut(AOP(result),"a",0);
4736                 }
4737             
4738                 emitcode("pop","acc");
4739                 lbl = newiTempLabel(NULL);      
4740                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4741                 emitcode("cpl","a");
4742                 emitcode("addc","a,#0");
4743                 emitcode("","!tlabeldef", lbl->key+100);
4744                 aopPut(AOP(result),"a",1);
4745                 emitcode("pop","acc");
4746                 if (AOP_SIZE(result) >= 3) {
4747                         lbl = newiTempLabel(NULL);      
4748                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4749                         emitcode("cpl","a");
4750                         emitcode("addc","a,#0");                        
4751                         emitcode("","!tlabeldef", lbl->key+100);
4752                         aopPut(AOP(result),"a",2);
4753                 }
4754                 emitcode("pop","acc");
4755                 if (AOP_SIZE(result) >= 4) {
4756                         lbl = newiTempLabel(NULL);      
4757                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4758                         emitcode("cpl","a");
4759                         emitcode("addc","a,#0");                        
4760                         emitcode("","!tlabeldef", lbl->key+100);
4761                         aopPut(AOP(result),"a",3);
4762                 }
4763                 if (AOP_TYPE(result) == AOP_ACC)
4764                 {
4765                     /* We stashed the result away above. */
4766                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4767                 }           
4768                 
4769         }
4770         freeAsmop (result, NULL, ic, TRUE);
4771
4772         /* restore EA bit in F1 */
4773         lbl = newiTempLabel(NULL);
4774         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4775         emitcode ("setb","EA");
4776         emitcode("","!tlabeldef",lbl->key+100);
4777         return ;
4778 }
4779
4780 /*-----------------------------------------------------------------*/
4781 /* genMult - generates code for multiplication                     */
4782 /*-----------------------------------------------------------------*/
4783 static void
4784 genMult (iCode * ic)
4785 {
4786   operand *left = IC_LEFT (ic);
4787   operand *right = IC_RIGHT (ic);
4788   operand *result = IC_RESULT (ic);
4789
4790   D (emitcode (";", "genMult "););
4791
4792   /* assign the amsops */
4793   AOP_OP_2 (ic);
4794
4795   /* special cases first */
4796   /* both are bits */
4797   if (AOP_TYPE (left) == AOP_CRY &&
4798       AOP_TYPE (right) == AOP_CRY)
4799     {
4800       genMultbits (left, right, result, ic);
4801       goto release;
4802     }
4803
4804   /* if both are of size == 1 */
4805   if (AOP_SIZE (left) == 1 &&
4806       AOP_SIZE (right) == 1)
4807     {
4808       genMultOneByte (left, right, result, ic);
4809       goto release;
4810     }
4811
4812   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4813           /* use the ds390 ARITHMETIC accel UNIT */
4814           genMultTwoByte (left, right, result, ic);
4815           return ;
4816   }
4817   /* should have been converted to function call */
4818   assert (0);
4819
4820 release:
4821   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4822   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4823   freeAsmop (result, NULL, ic, TRUE);
4824 }
4825
4826 /*-----------------------------------------------------------------*/
4827 /* genDivbits :- division of bits                                  */
4828 /*-----------------------------------------------------------------*/
4829 static void
4830 genDivbits (operand * left,
4831             operand * right,
4832             operand * result,
4833             iCode   * ic)
4834 {
4835
4836   char *l;
4837
4838   /* the result must be bit */
4839   LOAD_AB_FOR_DIV (left, right, l);
4840   emitcode ("div", "ab");
4841   emitcode ("rrc", "a");
4842   aopOp(result, ic, TRUE, FALSE);
4843     
4844   aopPut (AOP (result), "c", 0);
4845 }
4846
4847 /*-----------------------------------------------------------------*/
4848 /* genDivOneByte : 8 bit division                                  */
4849 /*-----------------------------------------------------------------*/
4850 static void
4851 genDivOneByte (operand * left,
4852                operand * right,
4853                operand * result,
4854                iCode   * ic)
4855 {
4856   sym_link *opetype = operandType (result);
4857   char *l;
4858   symbol *lbl;
4859   int size, offset;
4860
4861   offset = 1;
4862   /* signed or unsigned */
4863   if (SPEC_USIGN (opetype))
4864     {
4865         /* unsigned is easy */
4866         LOAD_AB_FOR_DIV (left, right, l);
4867         emitcode ("div", "ab");
4868
4869         _G.accInUse++;
4870         aopOp(result, ic, TRUE, FALSE);
4871         aopPut (AOP (result), "a", 0);
4872         _G.accInUse--;
4873
4874         size = AOP_SIZE (result) - 1;
4875         
4876         while (size--)
4877         {
4878             aopPut (AOP (result), zero, offset++);
4879         }
4880       return;
4881     }
4882
4883   /* signed is a little bit more difficult */
4884
4885   /* save the signs of the operands */
4886   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4887   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4888   emitcode ("push", "acc");     /* save it on the stack */
4889
4890   /* now sign adjust for both left & right */
4891   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4892   lbl = newiTempLabel (NULL);
4893   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4894   emitcode ("cpl", "a");
4895   emitcode ("inc", "a");
4896   emitcode ("", "!tlabeldef", (lbl->key + 100));
4897   emitcode ("mov", "b,a");
4898
4899   /* sign adjust left side */
4900   MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4901
4902   lbl = newiTempLabel (NULL);
4903   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4904   emitcode ("cpl", "a");
4905   emitcode ("inc", "a");
4906   emitcode ("", "!tlabeldef", (lbl->key + 100));
4907
4908   /* now the division */
4909   emitcode ("nop", "; workaround for DS80C390 div bug.");
4910   emitcode ("div", "ab");
4911   /* we are interested in the lower order
4912      only */
4913   emitcode ("mov", "b,a");
4914   lbl = newiTempLabel (NULL);
4915   emitcode ("pop", "acc");
4916   /* if there was an over flow we don't
4917      adjust the sign of the result */
4918   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4919   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4920   CLRC;
4921   emitcode ("clr", "a");
4922   emitcode ("subb", "a,b");
4923   emitcode ("mov", "b,a");
4924   emitcode ("", "!tlabeldef", (lbl->key + 100));
4925
4926   /* now we are done */
4927   _G.accInUse++;     _G.bInUse++;
4928     aopOp(result, ic, TRUE, FALSE);
4929     
4930     aopPut (AOP (result), "b", 0);
4931     
4932     size = AOP_SIZE (result) - 1;
4933     
4934     if (size > 0)
4935     {
4936       emitcode ("mov", "c,b.7");
4937       emitcode ("subb", "a,acc");
4938     }
4939     while (size--)
4940     {
4941         aopPut (AOP (result), "a", offset++);
4942     }
4943     _G.accInUse--;     _G.bInUse--;
4944
4945 }
4946
4947 /*-----------------------------------------------------------------*/
4948 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4949 /*-----------------------------------------------------------------*/
4950 static void genDivTwoByte (operand *left, operand *right, 
4951                             operand *result, iCode *ic)
4952 {
4953         sym_link *retype = getSpec(operandType(right));
4954         sym_link *letype = getSpec(operandType(left));
4955         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4956         symbol *lbl;
4957
4958         /* save EA bit in F1 */
4959         lbl = newiTempLabel(NULL);
4960         emitcode ("setb","F1");
4961         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4962         emitcode ("clr","F1");
4963         emitcode("","!tlabeldef",lbl->key+100);
4964
4965         /* load up MA with left */
4966         if (!umult) {
4967                 emitcode("clr","F0");
4968                 lbl = newiTempLabel(NULL);
4969                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4970                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4971                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4972                 emitcode ("xch", "a,b");
4973                 emitcode ("cpl","a");
4974                 emitcode ("add", "a,#1");
4975                 emitcode ("xch", "a,b");
4976                 emitcode ("cpl", "a"); // msb
4977                 emitcode ("addc","a,#0");
4978                 emitcode ("setb","F0");
4979                 emitcode ("","!tlabeldef",lbl->key+100);
4980                 emitcode ("mov","ma,b");
4981                 emitcode ("mov","ma,a");
4982         } else {
4983                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4984                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4985         }
4986
4987         /* load up MB with right */
4988         if (!umult) {
4989                 if (AOP_TYPE(right) == AOP_LIT) {
4990                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4991                         if (val < 0) {
4992                                 lbl = newiTempLabel(NULL);
4993                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4994                                 emitcode("setb","F0");
4995                                 emitcode ("","!tlabeldef",lbl->key+100);
4996                                 val = -val;
4997                         } 
4998                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
4999                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5000                 } else {
5001                         lbl = newiTempLabel(NULL);
5002                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5003                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5004                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5005                         emitcode ("xch", "a,b");
5006                         emitcode ("cpl","a");
5007                         emitcode ("add", "a,#1");
5008                         emitcode ("xch", "a,b");
5009                         emitcode ("cpl", "a"); // msb
5010                         emitcode ("addc", "a,#0");
5011                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5012                         emitcode ("setb","F0");
5013                         emitcode ("","!tlabeldef",lbl->key+100);
5014                         emitcode ("mov","mb,b");
5015                         emitcode ("mov","mb,a");
5016                 }
5017         } else {
5018                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5019                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5020         }
5021
5022         /* wait for multiplication to finish */
5023         lbl = newiTempLabel(NULL);
5024         emitcode("","!tlabeldef", lbl->key+100);
5025         emitcode("mov","a,mcnt1");
5026         emitcode("anl","a,#!constbyte",0x80);
5027         emitcode("jnz","!tlabel",lbl->key+100);
5028         
5029         freeAsmop (left, NULL, ic, TRUE);
5030         freeAsmop (right, NULL, ic,TRUE);
5031         aopOp(result, ic, TRUE, FALSE);
5032
5033         /* if unsigned then simple */   
5034         if (umult) {
5035                 aopPut(AOP(result),"ma",1);
5036                 aopPut(AOP(result),"ma",0);
5037         } else {
5038                 emitcode("push","ma");
5039                 MOVA("ma");
5040                 /* negate result if needed */
5041                 lbl = newiTempLabel(NULL);      
5042                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5043                 emitcode("cpl","a");
5044                 emitcode("add","a,#1");
5045                 emitcode("","!tlabeldef", lbl->key+100);
5046                 aopPut(AOP(result),"a",0);
5047                 emitcode("pop","acc");
5048                 lbl = newiTempLabel(NULL);      
5049                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5050                 emitcode("cpl","a");
5051                 emitcode("addc","a,#0");
5052                 emitcode("","!tlabeldef", lbl->key+100);
5053                 aopPut(AOP(result),"a",1);
5054         }
5055         freeAsmop (result, NULL, ic, TRUE);
5056         /* restore EA bit in F1 */
5057         lbl = newiTempLabel(NULL);
5058         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5059         emitcode ("setb","EA");
5060         emitcode("","!tlabeldef",lbl->key+100);
5061         return ;
5062 }
5063
5064 /*-----------------------------------------------------------------*/
5065 /* genDiv - generates code for division                            */
5066 /*-----------------------------------------------------------------*/
5067 static void
5068 genDiv (iCode * ic)
5069 {
5070   operand *left = IC_LEFT (ic);
5071   operand *right = IC_RIGHT (ic);
5072   operand *result = IC_RESULT (ic);
5073
5074   D (emitcode (";", "genDiv "););
5075
5076   /* assign the amsops */
5077   AOP_OP_2 (ic);
5078
5079   /* special cases first */
5080   /* both are bits */
5081   if (AOP_TYPE (left) == AOP_CRY &&
5082       AOP_TYPE (right) == AOP_CRY)
5083     {
5084       genDivbits (left, right, result, ic);
5085       goto release;
5086     }
5087
5088   /* if both are of size == 1 */
5089   if (AOP_SIZE (left) == 1 &&
5090       AOP_SIZE (right) == 1)
5091     {
5092       genDivOneByte (left, right, result, ic);
5093       goto release;
5094     }
5095
5096   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5097           /* use the ds390 ARITHMETIC accel UNIT */
5098           genDivTwoByte (left, right, result, ic);
5099           return ;
5100   }
5101   /* should have been converted to function call */
5102   assert (0);
5103 release:
5104   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5105   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5106   freeAsmop (result, NULL, ic, TRUE);
5107 }
5108
5109 /*-----------------------------------------------------------------*/
5110 /* genModbits :- modulus of bits                                   */
5111 /*-----------------------------------------------------------------*/
5112 static void
5113 genModbits (operand * left,
5114             operand * right,
5115             operand * result,
5116             iCode   * ic)
5117 {
5118
5119   char *l;
5120
5121   /* the result must be bit */
5122   LOAD_AB_FOR_DIV (left, right, l);
5123   emitcode ("div", "ab");
5124   emitcode ("mov", "a,b");
5125   emitcode ("rrc", "a");
5126   aopOp(result, ic, TRUE, FALSE);
5127   aopPut (AOP (result), "c", 0);
5128 }
5129
5130 /*-----------------------------------------------------------------*/
5131 /* genModOneByte : 8 bit modulus                                   */
5132 /*-----------------------------------------------------------------*/
5133 static void
5134 genModOneByte (operand * left,
5135                operand * right,
5136                operand * result,
5137                iCode   * ic)
5138 {
5139   sym_link *opetype = operandType (result);
5140   char *l;
5141   symbol *lbl;
5142
5143   /* signed or unsigned */
5144   if (SPEC_USIGN (opetype))
5145     {
5146       /* unsigned is easy */
5147       LOAD_AB_FOR_DIV (left, right, l);
5148       emitcode ("div", "ab");
5149       aopOp(result, ic, TRUE, FALSE);   
5150       aopPut (AOP (result), "b", 0);
5151       return;
5152     }
5153
5154   /* signed is a little bit more difficult */
5155
5156   /* save the signs of the operands */
5157   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5158
5159   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5160   emitcode ("push", "acc");     /* save it on the stack */
5161
5162   /* now sign adjust for both left & right */
5163   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5164
5165   lbl = newiTempLabel (NULL);
5166   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5167   emitcode ("cpl", "a");
5168   emitcode ("inc", "a");
5169   emitcode ("", "!tlabeldef", (lbl->key + 100));
5170   emitcode ("mov", "b,a");
5171
5172   /* sign adjust left side */
5173   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5174
5175   lbl = newiTempLabel (NULL);
5176   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5177   emitcode ("cpl", "a");
5178   emitcode ("inc", "a");
5179   emitcode ("", "!tlabeldef", (lbl->key + 100));
5180
5181   /* now the multiplication */
5182   emitcode ("nop", "; workaround for DS80C390 div bug.");
5183   emitcode ("div", "ab");
5184   /* we are interested in the lower order
5185      only */
5186   lbl = newiTempLabel (NULL);
5187   emitcode ("pop", "acc");
5188   /* if there was an over flow we don't
5189      adjust the sign of the result */
5190   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5191   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5192   CLRC;
5193   emitcode ("clr", "a");
5194   emitcode ("subb", "a,b");
5195   emitcode ("mov", "b,a");
5196   emitcode ("", "!tlabeldef", (lbl->key + 100));
5197   
5198   _G.bInUse++;
5199   /* now we are done */
5200   aopOp(result, ic, TRUE, FALSE);    
5201   aopPut (AOP (result), "b", 0);
5202   _G.bInUse--;
5203
5204 }
5205
5206 /*-----------------------------------------------------------------*/
5207 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5208 /*-----------------------------------------------------------------*/
5209 static void genModTwoByte (operand *left, operand *right, 
5210                             operand *result, iCode *ic)
5211 {
5212         sym_link *retype = getSpec(operandType(right));
5213         sym_link *letype = getSpec(operandType(left));
5214         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5215         symbol *lbl;
5216
5217         /* load up MA with left */
5218         /* save EA bit in F1 */
5219         lbl = newiTempLabel(NULL);
5220         emitcode ("setb","F1");
5221         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5222         emitcode ("clr","F1");
5223         emitcode("","!tlabeldef",lbl->key+100);
5224
5225         if (!umult) {
5226                 lbl = newiTempLabel(NULL);
5227                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5228                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5229                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5230                 emitcode ("xch", "a,b");
5231                 emitcode ("cpl","a");
5232                 emitcode ("add", "a,#1");
5233                 emitcode ("xch", "a,b");
5234                 emitcode ("cpl", "a"); // msb
5235                 emitcode ("addc","a,#0");
5236                 emitcode ("","!tlabeldef",lbl->key+100);
5237                 emitcode ("mov","ma,b");
5238                 emitcode ("mov","ma,a");
5239         } else {
5240                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5241                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5242         }
5243
5244         /* load up MB with right */
5245         if (!umult) {
5246                 if (AOP_TYPE(right) == AOP_LIT) {
5247                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
5248                         if (val < 0) {
5249                                 val = -val;
5250                         } 
5251                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5252                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5253                 } else {
5254                         lbl = newiTempLabel(NULL);
5255                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5256                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5257                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5258                         emitcode ("xch", "a,b");
5259                         emitcode ("cpl","a");
5260                         emitcode ("add", "a,#1");
5261                         emitcode ("xch", "a,b");
5262                         emitcode ("cpl", "a"); // msb
5263                         emitcode ("addc", "a,#0");
5264                         emitcode ("","!tlabeldef",lbl->key+100);
5265                         emitcode ("mov","mb,b");
5266                         emitcode ("mov","mb,a");
5267                 }
5268         } else {
5269                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5270                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5271         }
5272
5273         /* wait for multiplication to finish */
5274         lbl = newiTempLabel(NULL);
5275         emitcode("","!tlabeldef", lbl->key+100);
5276         emitcode("mov","a,mcnt1");
5277         emitcode("anl","a,#!constbyte",0x80);
5278         emitcode("jnz","!tlabel",lbl->key+100);
5279         
5280         freeAsmop (left, NULL, ic, TRUE);
5281         freeAsmop (right, NULL, ic,TRUE);
5282         aopOp(result, ic, TRUE, FALSE);
5283
5284         aopPut(AOP(result),"mb",1);
5285         aopPut(AOP(result),"mb",0);
5286         freeAsmop (result, NULL, ic, TRUE);
5287
5288         /* restore EA bit in F1 */
5289         lbl = newiTempLabel(NULL);
5290         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5291         emitcode ("setb","EA");
5292         emitcode("","!tlabeldef",lbl->key+100);
5293         return ;
5294 }
5295
5296 /*-----------------------------------------------------------------*/
5297 /* genMod - generates code for division                            */
5298 /*-----------------------------------------------------------------*/
5299 static void
5300 genMod (iCode * ic)
5301 {
5302   operand *left = IC_LEFT (ic);
5303   operand *right = IC_RIGHT (ic);
5304   operand *result = IC_RESULT (ic);
5305
5306   D (emitcode (";", "genMod "); );
5307
5308   /* assign the amsops */
5309   AOP_OP_2 (ic);
5310
5311   /* special cases first */
5312   /* both are bits */
5313   if (AOP_TYPE (left) == AOP_CRY &&
5314       AOP_TYPE (right) == AOP_CRY)
5315     {
5316       genModbits (left, right, result, ic);
5317       goto release;
5318     }
5319
5320   /* if both are of size == 1 */
5321   if (AOP_SIZE (left) == 1 &&
5322       AOP_SIZE (right) == 1)
5323     {
5324       genModOneByte (left, right, result, ic);
5325       goto release;
5326     }
5327
5328   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5329           /* use the ds390 ARITHMETIC accel UNIT */
5330           genModTwoByte (left, right, result, ic);
5331           return ;
5332   }
5333
5334   /* should have been converted to function call */
5335   assert (0);
5336
5337 release:
5338   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5339   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5340   freeAsmop (result, NULL, ic, TRUE);
5341 }
5342
5343 /*-----------------------------------------------------------------*/
5344 /* genIfxJump :- will create a jump depending on the ifx           */
5345 /*-----------------------------------------------------------------*/
5346 static void
5347 genIfxJump (iCode * ic, char *jval)
5348 {
5349   symbol *jlbl;
5350   symbol *tlbl = newiTempLabel (NULL);
5351   char *inst;
5352
5353   D (emitcode (";", "genIfxJump"););
5354
5355   /* if true label then we jump if condition
5356      supplied is true */
5357   if (IC_TRUE (ic))
5358     {
5359       jlbl = IC_TRUE (ic);
5360       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5361                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5362     }
5363   else
5364     {
5365       /* false label is present */
5366       jlbl = IC_FALSE (ic);
5367       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5368                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5369     }
5370   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5371     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5372   else
5373     emitcode (inst, "!tlabel", tlbl->key + 100);
5374   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5375   emitcode ("", "!tlabeldef", tlbl->key + 100);
5376
5377   /* mark the icode as generated */
5378   ic->generated = 1;
5379 }
5380
5381 /*-----------------------------------------------------------------*/
5382 /* genCmp :- greater or less than comparison                       */
5383 /*-----------------------------------------------------------------*/
5384 static void
5385 genCmp (operand * left, operand * right,
5386         iCode * ic, iCode * ifx, int sign)
5387 {
5388   int size, offset = 0;
5389   unsigned long lit = 0L;
5390   operand *result;
5391
5392   D (emitcode (";", "genCmp"););
5393
5394   result = IC_RESULT (ic);
5395
5396   /* if left & right are bit variables */
5397   if (AOP_TYPE (left) == AOP_CRY &&
5398       AOP_TYPE (right) == AOP_CRY)
5399     {
5400       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5401       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5402     }
5403   else
5404     {
5405       /* subtract right from left if at the
5406          end the carry flag is set then we know that
5407          left is greater than right */
5408       size = max (AOP_SIZE (left), AOP_SIZE (right));
5409
5410       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5411       if ((size == 1) && !sign 
5412           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5413         {
5414           symbol *lbl = newiTempLabel (NULL);
5415           emitcode ("cjne", "%s,%s,!tlabel",
5416                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5417                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5418                     lbl->key + 100);
5419           emitcode ("", "!tlabeldef", lbl->key + 100);
5420         }
5421       else
5422         {
5423           if (AOP_TYPE (right) == AOP_LIT)
5424             {
5425               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5426               /* optimize if(x < 0) or if(x >= 0) */
5427               if (lit == 0L)
5428                 {
5429                   if (!sign)
5430                     {
5431                       CLRC;
5432                     }
5433                   else
5434                     {
5435                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5436
5437                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5438                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5439
5440                       aopOp (result, ic, FALSE, FALSE);
5441
5442                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5443                         {
5444                           freeAsmop (result, NULL, ic, TRUE);
5445                           genIfxJump (ifx, "acc.7");
5446                           return;
5447                         }
5448                       else
5449                         {
5450                           emitcode ("rlc", "a");
5451                         }
5452                       goto release_freedLR;
5453                     }
5454                   goto release;
5455                 }
5456             }
5457           CLRC;
5458           while (size--)
5459             {
5460               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5461               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5462               // emitcode (";", "genCmp #2");
5463               if (sign && (size == 0))
5464                 {
5465                   // emitcode (";", "genCmp #3");
5466                   emitcode ("xrl", "a,#!constbyte",0x80);
5467                   if (AOP_TYPE (right) == AOP_LIT)
5468                     {
5469                       unsigned long lit = (unsigned long)
5470                       floatFromVal (AOP (right)->aopu.aop_lit);
5471                       // emitcode (";", "genCmp #3.1");
5472                       emitcode ("subb", "a,#!constbyte",
5473                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5474                     }
5475                   else
5476                     {
5477                       // emitcode (";", "genCmp #3.2");
5478                       saveAccWarn = 0;  
5479                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5480                       saveAccWarn = DEFAULT_ACC_WARNING;
5481                       emitcode ("xrl", "b,#!constbyte",0x80);
5482                       emitcode ("subb", "a,b");
5483                     }
5484                 }
5485               else
5486                 {
5487                   const char *s;
5488
5489                   // emitcode (";", "genCmp #4");
5490                   saveAccWarn = 0;
5491                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5492                   saveAccWarn = DEFAULT_ACC_WARNING;
5493
5494                   emitcode ("subb", "a,%s", s);
5495                 }
5496             }
5497         }
5498     }
5499
5500 release:
5501 /* Don't need the left & right operands any more; do need the result. */
5502   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5503   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5504
5505   aopOp (result, ic, FALSE, FALSE);
5506
5507 release_freedLR:
5508
5509   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5510     {
5511       outBitC (result);
5512     }
5513   else
5514     {
5515       /* if the result is used in the next
5516          ifx conditional branch then generate
5517          code a little differently */
5518       if (ifx)
5519         {
5520           genIfxJump (ifx, "c");
5521         }
5522       else
5523         {
5524           outBitC (result);
5525         }
5526       /* leave the result in acc */
5527     }
5528   freeAsmop (result, NULL, ic, TRUE);
5529 }
5530
5531 /*-----------------------------------------------------------------*/
5532 /* genCmpGt :- greater than comparison                             */
5533 /*-----------------------------------------------------------------*/
5534 static void
5535 genCmpGt (iCode * ic, iCode * ifx)
5536 {
5537   operand *left, *right;
5538   sym_link *letype, *retype;
5539   int sign;
5540
5541   D (emitcode (";", "genCmpGt ");
5542     );
5543
5544   left = IC_LEFT (ic);
5545   right = IC_RIGHT (ic);
5546
5547   letype = getSpec (operandType (left));
5548   retype = getSpec (operandType (right));
5549   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5550
5551   /* assign the left & right amsops */
5552   AOP_OP_2 (ic);
5553
5554   genCmp (right, left, ic, ifx, sign);
5555 }
5556
5557 /*-----------------------------------------------------------------*/
5558 /* genCmpLt - less than comparisons                                */
5559 /*-----------------------------------------------------------------*/
5560 static void
5561 genCmpLt (iCode * ic, iCode * ifx)
5562 {
5563   operand *left, *right;
5564   sym_link *letype, *retype;
5565   int sign;
5566
5567   D (emitcode (";", "genCmpLt "););
5568
5569   left = IC_LEFT (ic);
5570   right = IC_RIGHT (ic);
5571
5572   letype = getSpec (operandType (left));
5573   retype = getSpec (operandType (right));
5574   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5575
5576   /* assign the left & right amsops */
5577   AOP_OP_2 (ic);
5578
5579   genCmp (left, right, ic, ifx, sign);
5580 }
5581
5582 /*-----------------------------------------------------------------*/
5583 /* gencjneshort - compare and jump if not equal                    */
5584 /*-----------------------------------------------------------------*/
5585 static void
5586 gencjneshort (operand * left, operand * right, symbol * lbl)
5587 {
5588   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5589   int offset = 0;
5590   unsigned long lit = 0L;
5591
5592   D (emitcode (";", "gencjneshort");
5593     );
5594
5595   /* if the left side is a literal or
5596      if the right is in a pointer register and left
5597      is not */
5598   if ((AOP_TYPE (left) == AOP_LIT) ||
5599       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5600     {
5601       operand *t = right;
5602       right = left;
5603       left = t;
5604     }
5605
5606   if (AOP_TYPE (right) == AOP_LIT)
5607     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5608
5609   if (opIsGptr (left) || opIsGptr (right))
5610     {
5611       /* We are comparing a generic pointer to something.
5612        * Exclude the generic type byte from the comparison.
5613        */
5614       size--;
5615       D (emitcode (";", "cjneshort: generic ptr special case."););
5616     }
5617
5618
5619   /* if the right side is a literal then anything goes */
5620   if (AOP_TYPE (right) == AOP_LIT &&
5621       AOP_TYPE (left) != AOP_DIR)
5622     {
5623       while (size--)
5624         {
5625           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5626           emitcode ("cjne", "a,%s,!tlabel",
5627                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5628                     lbl->key + 100);
5629           offset++;
5630         }
5631     }
5632
5633   /* if the right side is in a register or in direct space or
5634      if the left is a pointer register & right is not */
5635   else if (AOP_TYPE (right) == AOP_REG ||
5636            AOP_TYPE (right) == AOP_DIR ||
5637            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5638            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5639     {
5640       while (size--)
5641         {
5642           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5643           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5644               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5645             emitcode ("jnz", "!tlabel", lbl->key + 100);
5646           else
5647             emitcode ("cjne", "a,%s,!tlabel",
5648                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5649                       lbl->key + 100);
5650           offset++;
5651         }
5652     }
5653   else
5654     {
5655       /* right is a pointer reg need both a & b */
5656       while (size--)
5657         {
5658           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5659           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5660           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5661           offset++;
5662         }
5663     }
5664 }
5665
5666 /*-----------------------------------------------------------------*/
5667 /* gencjne - compare and jump if not equal                         */
5668 /*-----------------------------------------------------------------*/
5669 static void
5670 gencjne (operand * left, operand * right, symbol * lbl)
5671 {
5672   symbol *tlbl = newiTempLabel (NULL);
5673
5674   D (emitcode (";", "gencjne");
5675     );
5676
5677   gencjneshort (left, right, lbl);
5678
5679   emitcode ("mov", "a,%s", one);
5680   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5681   emitcode ("", "!tlabeldef", lbl->key + 100);
5682   emitcode ("clr", "a");
5683   emitcode ("", "!tlabeldef", tlbl->key + 100);
5684 }
5685
5686 /*-----------------------------------------------------------------*/
5687 /* genCmpEq - generates code for equal to                          */
5688 /*-----------------------------------------------------------------*/
5689 static void
5690 genCmpEq (iCode * ic, iCode * ifx)
5691 {
5692   operand *left, *right, *result;
5693
5694   D (emitcode (";", "genCmpEq ");
5695     );
5696
5697   AOP_OP_2 (ic);
5698   AOP_SET_LOCALS (ic);
5699
5700   /* if literal, literal on the right or
5701      if the right is in a pointer register and left
5702      is not */
5703   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5704       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5705     {
5706       operand *t = IC_RIGHT (ic);
5707       IC_RIGHT (ic) = IC_LEFT (ic);
5708       IC_LEFT (ic) = t;
5709     }
5710
5711   if (ifx &&                    /* !AOP_SIZE(result) */
5712       OP_SYMBOL (result) &&
5713       OP_SYMBOL (result)->regType == REG_CND)
5714     {
5715       symbol *tlbl;
5716       /* if they are both bit variables */
5717       if (AOP_TYPE (left) == AOP_CRY &&
5718           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5719         {
5720           if (AOP_TYPE (right) == AOP_LIT)
5721             {
5722               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5723               if (lit == 0L)
5724                 {
5725                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5726                   emitcode ("cpl", "c");
5727                 }
5728               else if (lit == 1L)
5729                 {
5730                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5731                 }
5732               else
5733                 {
5734                   emitcode ("clr", "c");
5735                 }
5736               /* AOP_TYPE(right) == AOP_CRY */
5737             }
5738           else
5739             {
5740               symbol *lbl = newiTempLabel (NULL);
5741               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5742               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5743               emitcode ("cpl", "c");
5744               emitcode ("", "!tlabeldef", (lbl->key + 100));
5745             }
5746           /* if true label then we jump if condition
5747              supplied is true */
5748           tlbl = newiTempLabel (NULL);
5749           if (IC_TRUE (ifx))
5750             {
5751               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5752               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5753             }
5754           else
5755             {
5756               emitcode ("jc", "!tlabel", tlbl->key + 100);
5757               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5758             }
5759           emitcode ("", "!tlabeldef", tlbl->key + 100);
5760         }
5761       else
5762         {
5763           tlbl = newiTempLabel (NULL);
5764           gencjneshort (left, right, tlbl);
5765           if (IC_TRUE (ifx))
5766             {
5767               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5768               emitcode ("", "!tlabeldef", tlbl->key + 100);
5769             }
5770           else
5771             {
5772               symbol *lbl = newiTempLabel (NULL);
5773               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5774               emitcode ("", "!tlabeldef", tlbl->key + 100);
5775               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5776               emitcode ("", "!tlabeldef", lbl->key + 100);
5777             }
5778         }
5779       /* mark the icode as generated */
5780       ifx->generated = 1;
5781
5782       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5783       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5784       return;
5785     }
5786
5787   /* if they are both bit variables */
5788   if (AOP_TYPE (left) == AOP_CRY &&
5789       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5790     {
5791       if (AOP_TYPE (right) == AOP_LIT)
5792         {
5793           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5794           if (lit == 0L)
5795             {
5796               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5797               emitcode ("cpl", "c");
5798             }
5799           else if (lit == 1L)
5800             {
5801               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5802             }
5803           else
5804             {
5805               emitcode ("clr", "c");
5806             }
5807           /* AOP_TYPE(right) == AOP_CRY */
5808         }
5809       else
5810         {
5811           symbol *lbl = newiTempLabel (NULL);
5812           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5813           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5814           emitcode ("cpl", "c");
5815           emitcode ("", "!tlabeldef", (lbl->key + 100));
5816         }
5817
5818       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5819       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5820
5821       aopOp (result, ic, TRUE, FALSE);
5822
5823       /* c = 1 if egal */
5824       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5825         {
5826           outBitC (result);
5827           goto release;
5828         }
5829       if (ifx)
5830         {
5831           genIfxJump (ifx, "c");
5832           goto release;
5833         }
5834       /* if the result is used in an arithmetic operation
5835          then put the result in place */
5836       outBitC (result);
5837     }
5838   else
5839     {
5840       gencjne (left, right, newiTempLabel (NULL));
5841
5842       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5843       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5844
5845       aopOp (result, ic, TRUE, FALSE);
5846
5847       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5848         {
5849           aopPut (AOP (result), "a", 0);
5850           goto release;
5851         }
5852       if (ifx)
5853         {
5854           genIfxJump (ifx, "a");
5855           goto release;
5856         }
5857       /* if the result is used in an arithmetic operation
5858          then put the result in place */
5859       if (AOP_TYPE (result) != AOP_CRY)
5860         outAcc (result);
5861       /* leave the result in acc */
5862     }
5863
5864 release:
5865   freeAsmop (result, NULL, ic, TRUE);
5866 }
5867
5868 /*-----------------------------------------------------------------*/
5869 /* ifxForOp - returns the icode containing the ifx for operand     */
5870 /*-----------------------------------------------------------------*/
5871 static iCode *
5872 ifxForOp (operand * op, iCode * ic)
5873 {
5874   /* if true symbol then needs to be assigned */
5875   if (IS_TRUE_SYMOP (op))
5876     return NULL;
5877
5878   /* if this has register type condition and
5879      the next instruction is ifx with the same operand
5880      and live to of the operand is upto the ifx only then */
5881   if (ic->next &&
5882       ic->next->op == IFX &&
5883       IC_COND (ic->next)->key == op->key &&
5884       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5885     return ic->next;
5886
5887   return NULL;
5888 }
5889 /*-----------------------------------------------------------------*/
5890 /* hasInc - operand is incremented before any other use            */
5891 /*-----------------------------------------------------------------*/
5892 static iCode *
5893 hasInc (operand *op, iCode *ic, int osize)
5894 {
5895   sym_link *type = operandType(op);
5896   sym_link *retype = getSpec (type);
5897   iCode *lic = ic->next;
5898   int isize ;
5899   
5900   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5901   if (!IS_SYMOP(op)) return NULL;
5902
5903   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5904   if (IS_AGGREGATE(type->next)) return NULL;
5905   if (osize != (isize = getSize(type->next))) return NULL;
5906
5907   while (lic) {
5908       /* if operand of the form op = op + <sizeof *op> */
5909       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5910           isOperandEqual(IC_RESULT(lic),op) && 
5911           isOperandLiteral(IC_RIGHT(lic)) &&
5912           operandLitValue(IC_RIGHT(lic)) == isize) {
5913           return lic;
5914       }
5915       /* if the operand used or deffed */
5916       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5917           return NULL;
5918       }
5919       /* if GOTO or IFX */
5920       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5921       lic = lic->next;
5922   }
5923   return NULL;
5924 }
5925
5926 /*-----------------------------------------------------------------*/
5927 /* genAndOp - for && operation                                     */
5928 /*-----------------------------------------------------------------*/
5929 static void
5930 genAndOp (iCode * ic)
5931 {
5932   operand *left, *right, *result;
5933   symbol *tlbl;
5934
5935   D (emitcode (";", "genAndOp "););
5936
5937   /* note here that && operations that are in an
5938      if statement are taken away by backPatchLabels
5939      only those used in arthmetic operations remain */
5940   AOP_OP_2 (ic);
5941   AOP_SET_LOCALS (ic);
5942
5943   /* if both are bit variables */
5944   if (AOP_TYPE (left) == AOP_CRY &&
5945       AOP_TYPE (right) == AOP_CRY)
5946     {
5947       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5948       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5949       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5950       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5951   
5952       aopOp (result,ic,FALSE, FALSE);
5953       outBitC (result);
5954     }
5955   else
5956     {
5957       tlbl = newiTempLabel (NULL);
5958       toBoolean (left);
5959       emitcode ("jz", "!tlabel", tlbl->key + 100);
5960       toBoolean (right);
5961       emitcode ("", "!tlabeldef", tlbl->key + 100);
5962       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5963       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5964   
5965       aopOp (result,ic,FALSE, FALSE);
5966       outBitAcc (result);
5967     }
5968     freeAsmop (result, NULL, ic, TRUE);
5969 }
5970
5971
5972 /*-----------------------------------------------------------------*/
5973 /* genOrOp - for || operation                                      */
5974 /*-----------------------------------------------------------------*/
5975 static void
5976 genOrOp (iCode * ic)
5977 {
5978   operand *left, *right, *result;
5979   symbol *tlbl;
5980
5981   D (emitcode (";", "genOrOp "););
5982
5983   /* note here that || operations that are in an
5984      if statement are taken away by backPatchLabels
5985      only those used in arthmetic operations remain */
5986   AOP_OP_2 (ic);
5987   AOP_SET_LOCALS (ic);
5988
5989   /* if both are bit variables */
5990   if (AOP_TYPE (left) == AOP_CRY &&
5991       AOP_TYPE (right) == AOP_CRY)
5992     {
5993       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5994       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5995       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5996       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5997   
5998       aopOp (result,ic,FALSE, FALSE);
5999       
6000       outBitC (result);
6001     }
6002   else
6003     {
6004       tlbl = newiTempLabel (NULL);
6005       toBoolean (left);
6006       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6007       toBoolean (right);
6008       emitcode ("", "!tlabeldef", tlbl->key + 100);
6009       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6010       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6011   
6012       aopOp (result,ic,FALSE, FALSE);
6013       
6014       outBitAcc (result);
6015     }
6016
6017   freeAsmop (result, NULL, ic, TRUE);
6018 }
6019
6020 /*-----------------------------------------------------------------*/
6021 /* isLiteralBit - test if lit == 2^n                               */
6022 /*-----------------------------------------------------------------*/
6023 static int
6024 isLiteralBit (unsigned long lit)
6025 {
6026   unsigned long pw[32] =
6027   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6028    0x100L, 0x200L, 0x400L, 0x800L,
6029    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6030    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6031    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6032    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6033    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6034   int idx;
6035
6036   for (idx = 0; idx < 32; idx++)
6037     if (lit == pw[idx])
6038       return idx + 1;
6039   return 0;
6040 }
6041
6042 /*-----------------------------------------------------------------*/
6043 /* continueIfTrue -                                                */
6044 /*-----------------------------------------------------------------*/
6045 static void
6046 continueIfTrue (iCode * ic)
6047 {
6048   if (IC_TRUE (ic))
6049     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6050   ic->generated = 1;
6051 }
6052
6053 /*-----------------------------------------------------------------*/
6054 /* jmpIfTrue -                                                     */
6055 /*-----------------------------------------------------------------*/
6056 static void
6057 jumpIfTrue (iCode * ic)
6058 {
6059   if (!IC_TRUE (ic))
6060     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6061   ic->generated = 1;
6062 }
6063
6064 /*-----------------------------------------------------------------*/
6065 /* jmpTrueOrFalse -                                                */
6066 /*-----------------------------------------------------------------*/
6067 static void
6068 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6069 {
6070   // ugly but optimized by peephole
6071   if (IC_TRUE (ic))
6072     {
6073       symbol *nlbl = newiTempLabel (NULL);
6074       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6075       emitcode ("", "!tlabeldef", tlbl->key + 100);
6076       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6077       emitcode ("", "!tlabeldef", nlbl->key + 100);
6078     }
6079   else
6080     {
6081       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6082       emitcode ("", "!tlabeldef", tlbl->key + 100);
6083     }
6084   ic->generated = 1;
6085 }
6086
6087 // Generate code to perform a bit-wise logic operation
6088 // on two operands in far space (assumed to already have been 
6089 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6090 // in far space. This requires pushing the result on the stack
6091 // then popping it into the result.
6092 static void
6093 genFarFarLogicOp(iCode *ic, char *logicOp)
6094 {
6095       int size, resultSize, compSize;
6096       int offset = 0;
6097       
6098       TR_AP("#5");
6099       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6100       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6101                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6102       
6103       _startLazyDPSEvaluation();
6104       for (size = compSize; (size--); offset++)
6105       {
6106           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6107           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6108           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6109           
6110           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6111           emitcode ("push", "acc");
6112       }
6113       _endLazyDPSEvaluation();
6114      
6115       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6116       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6117       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6118      
6119       resultSize = AOP_SIZE(IC_RESULT(ic));
6120
6121       ADJUST_PUSHED_RESULT(compSize, resultSize);
6122
6123       _startLazyDPSEvaluation();
6124       while (compSize--)
6125       {
6126           emitcode ("pop", "acc");
6127           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6128       }
6129       _endLazyDPSEvaluation();
6130       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6131 }
6132
6133
6134 /*-----------------------------------------------------------------*/
6135 /* genAnd  - code for and                                          */
6136 /*-----------------------------------------------------------------*/
6137 static void
6138 genAnd (iCode * ic, iCode * ifx)
6139 {
6140   operand *left, *right, *result;
6141   int size, offset = 0;
6142   unsigned long lit = 0L;
6143   int bytelit;
6144   char buff[10];
6145   bool pushResult;
6146
6147   D (emitcode (";", "genAnd "););
6148
6149   AOP_OP_3_NOFATAL (ic, pushResult);
6150   AOP_SET_LOCALS (ic);
6151
6152   if (pushResult)
6153   {
6154       genFarFarLogicOp(ic, "anl");
6155       return;
6156   }  
6157
6158 #ifdef DEBUG_TYPE
6159   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6160             AOP_TYPE (result),
6161             AOP_TYPE (left), AOP_TYPE (right));
6162   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6163             AOP_SIZE (result),
6164             AOP_SIZE (left), AOP_SIZE (right));
6165 #endif
6166
6167   /* if left is a literal & right is not then exchange them */
6168   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6169 #ifdef LOGIC_OPS_BROKEN      
6170     ||  AOP_NEEDSACC (left)
6171 #endif
6172     )
6173     {
6174       operand *tmp = right;
6175       right = left;
6176       left = tmp;
6177     }
6178
6179   /* if result = right then exchange them */
6180   if (sameRegs (AOP (result), AOP (right)))
6181     {
6182       operand *tmp = right;
6183       right = left;
6184       left = tmp;
6185     }
6186
6187   /* if right is bit then exchange them */
6188   if (AOP_TYPE (right) == AOP_CRY &&
6189       AOP_TYPE (left) != AOP_CRY)
6190     {
6191       operand *tmp = right;
6192       right = left;
6193       left = tmp;
6194     }
6195   if (AOP_TYPE (right) == AOP_LIT)
6196     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6197
6198   size = AOP_SIZE (result);
6199
6200   // if(bit & yy)
6201   // result = bit & yy;
6202   if (AOP_TYPE (left) == AOP_CRY)
6203     {
6204       // c = bit & literal;
6205       if (AOP_TYPE (right) == AOP_LIT)
6206         {
6207           if (lit & 1)
6208             {
6209               if (size && sameRegs (AOP (result), AOP (left)))
6210                 // no change
6211                 goto release;
6212               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6213             }
6214           else
6215             {
6216               // bit(result) = 0;
6217               if (size && (AOP_TYPE (result) == AOP_CRY))
6218                 {
6219                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6220                   goto release;
6221                 }
6222               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6223                 {
6224                   jumpIfTrue (ifx);
6225                   goto release;
6226                 }
6227               emitcode ("clr", "c");
6228             }
6229         }
6230       else
6231         {
6232           if (AOP_TYPE (right) == AOP_CRY)
6233             {
6234               // c = bit & bit;
6235               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6236               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6237             }
6238           else
6239             {
6240               // c = bit & val;
6241               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6242               // c = lsb
6243               emitcode ("rrc", "a");
6244               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6245             }
6246         }
6247       // bit = c
6248       // val = c
6249       if (size)
6250         outBitC (result);
6251       // if(bit & ...)
6252       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6253         genIfxJump (ifx, "c");
6254       goto release;
6255     }
6256
6257   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6258   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6259   if ((AOP_TYPE (right) == AOP_LIT) &&
6260       (AOP_TYPE (result) == AOP_CRY) &&
6261       (AOP_TYPE (left) != AOP_CRY))
6262     {
6263       int posbit = isLiteralBit (lit);
6264       /* left &  2^n */
6265       if (posbit)
6266         {
6267           posbit--;
6268           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6269           // bit = left & 2^n
6270           if (size)
6271             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6272           // if(left &  2^n)
6273           else
6274             {
6275               if (ifx)
6276                 {
6277                   SNPRINTF (buff, sizeof(buff), 
6278                             "acc.%d", posbit & 0x07);
6279                   genIfxJump (ifx, buff);
6280                 }
6281               else 
6282                   {
6283                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6284                   }
6285               goto release;
6286             }
6287         }
6288       else
6289         {
6290           symbol *tlbl = newiTempLabel (NULL);
6291           int sizel = AOP_SIZE (left);
6292           if (size)
6293             emitcode ("setb", "c");
6294           while (sizel--)
6295             {
6296               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6297                 {
6298                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6299                   // byte ==  2^n ?
6300                   if ((posbit = isLiteralBit (bytelit)) != 0)
6301                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6302                   else
6303                     {
6304                       if (bytelit != 0x0FFL)
6305                         emitcode ("anl", "a,%s",
6306                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6307                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6308                     }
6309                 }
6310               offset++;
6311             }
6312           // bit = left & literal
6313           if (size)
6314             {
6315               emitcode ("clr", "c");
6316               emitcode ("", "!tlabeldef", tlbl->key + 100);
6317             }
6318           // if(left & literal)
6319           else
6320             {
6321               if (ifx)
6322                 jmpTrueOrFalse (ifx, tlbl);
6323               goto release;
6324             }
6325         }
6326       outBitC (result);
6327       goto release;
6328     }
6329
6330   /* if left is same as result */
6331   if (sameRegs (AOP (result), AOP (left)))
6332     {
6333       for (; size--; offset++)
6334         {
6335           if (AOP_TYPE (right) == AOP_LIT)
6336             {
6337               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6338                 continue;
6339               else if (bytelit == 0)
6340                 aopPut (AOP (result), zero, offset);
6341               else if (IS_AOP_PREG (result))
6342                 {
6343                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6344                   emitcode ("anl", "a,%s",
6345                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6346                   aopPut (AOP (result), "a", offset);
6347                 }
6348               else
6349                 emitcode ("anl", "%s,%s",
6350                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6351                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6352             }
6353           else
6354             {
6355               if (AOP_TYPE (left) == AOP_ACC)
6356                 emitcode ("anl", "a,%s",
6357                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6358               else
6359                 {
6360                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6361                   if (IS_AOP_PREG (result))
6362                     {
6363                       emitcode ("anl", "a,%s",
6364                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6365                       aopPut (AOP (result), "a", offset);
6366                     }
6367                   else
6368                     emitcode ("anl", "%s,a",
6369                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6370                 }
6371             }
6372         }
6373     }
6374   else
6375     {
6376       // left & result in different registers
6377       if (AOP_TYPE (result) == AOP_CRY)
6378         {
6379           // result = bit
6380           // if(size), result in bit
6381           // if(!size && ifx), conditional oper: if(left & right)
6382           symbol *tlbl = newiTempLabel (NULL);
6383           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6384           if (size)
6385             emitcode ("setb", "c");
6386           while (sizer--)
6387             {
6388               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6389                 emitcode ("anl", "a,%s",
6390                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6391               } else {
6392                 if (AOP_TYPE(left)==AOP_ACC) {
6393                   emitcode("mov", "b,a");
6394                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6395                   emitcode("anl", "a,b");
6396                 }else {
6397                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6398                   emitcode ("anl", "a,%s",
6399                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6400                 }
6401               }
6402               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6403               offset++;
6404             }
6405           if (size)
6406             {
6407               CLRC;
6408               emitcode ("", "!tlabeldef", tlbl->key + 100);
6409               outBitC (result);
6410             }
6411           else if (ifx)
6412             jmpTrueOrFalse (ifx, tlbl);
6413         }
6414       else
6415         {
6416           for (; (size--); offset++)
6417             {
6418               // normal case
6419               // result = left & right
6420               if (AOP_TYPE (right) == AOP_LIT)
6421                 {
6422                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6423                     {
6424                       aopPut (AOP (result),
6425                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6426                               offset);
6427                       continue;
6428                     }
6429                   else if (bytelit == 0)
6430                     {
6431                       aopPut (AOP (result), zero, offset);
6432                       continue;
6433                     }
6434                   D (emitcode (";", "better literal AND."););
6435                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6436                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6437                                                     FALSE, FALSE, DP2_RESULT_REG));
6438
6439                 }
6440               else
6441                 {
6442                   // faster than result <- left, anl result,right
6443                   // and better if result is SFR
6444                   if (AOP_TYPE (left) == AOP_ACC)
6445                     {
6446                       emitcode ("anl", "a,%s", 
6447                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6448                     }
6449                   else
6450                     {
6451                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6452                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6453                       {
6454                           emitcode("mov", "b,a");
6455                           rOp = "b";
6456                       }
6457                         
6458                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6459                       emitcode ("anl", "a,%s", rOp);
6460                     }                   
6461                 }
6462               aopPut (AOP (result), "a", offset);
6463             }
6464         }
6465     }
6466
6467 release:
6468   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6469   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6470   freeAsmop (result, NULL, ic, TRUE);
6471 }
6472
6473
6474 /*-----------------------------------------------------------------*/
6475 /* genOr  - code for or                                            */
6476 /*-----------------------------------------------------------------*/
6477 static void
6478 genOr (iCode * ic, iCode * ifx)
6479 {
6480   operand *left, *right, *result;
6481   int size, offset = 0;
6482   unsigned long lit = 0L;
6483   bool     pushResult;
6484
6485   D (emitcode (";", "genOr "););
6486
6487   AOP_OP_3_NOFATAL (ic, pushResult);
6488   AOP_SET_LOCALS (ic);
6489
6490   if (pushResult)
6491   {
6492       genFarFarLogicOp(ic, "orl");
6493       return;
6494   }
6495
6496
6497 #ifdef DEBUG_TYPE
6498   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6499             AOP_TYPE (result),
6500             AOP_TYPE (left), AOP_TYPE (right));
6501   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6502             AOP_SIZE (result),
6503             AOP_SIZE (left), AOP_SIZE (right));
6504 #endif
6505
6506   /* if left is a literal & right is not then exchange them */
6507   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6508 #ifdef LOGIC_OPS_BROKEN
6509    || AOP_NEEDSACC (left) // I think this is a net loss now.
6510 #endif      
6511       )
6512     {
6513       operand *tmp = right;
6514       right = left;
6515       left = tmp;
6516     }
6517
6518   /* if result = right then exchange them */
6519   if (sameRegs (AOP (result), AOP (right)))
6520     {
6521       operand *tmp = right;
6522       right = left;
6523       left = tmp;
6524     }
6525
6526   /* if right is bit then exchange them */
6527   if (AOP_TYPE (right) == AOP_CRY &&
6528       AOP_TYPE (left) != AOP_CRY)
6529     {
6530       operand *tmp = right;
6531       right = left;
6532       left = tmp;
6533     }
6534   if (AOP_TYPE (right) == AOP_LIT)
6535     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6536
6537   size = AOP_SIZE (result);
6538
6539   // if(bit | yy)
6540   // xx = bit | yy;
6541   if (AOP_TYPE (left) == AOP_CRY)
6542     {
6543       if (AOP_TYPE (right) == AOP_LIT)
6544         {
6545           // c = bit & literal;
6546           if (lit)
6547             {
6548               // lit != 0 => result = 1
6549               if (AOP_TYPE (result) == AOP_CRY)
6550                 {
6551                   if (size)
6552                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6553                   else if (ifx)
6554                     continueIfTrue (ifx);
6555                   goto release;
6556                 }
6557               emitcode ("setb", "c");
6558             }
6559           else
6560             {
6561               // lit == 0 => result = left
6562               if (size && sameRegs (AOP (result), AOP (left)))
6563                 goto release;
6564               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6565             }
6566         }
6567       else
6568         {
6569           if (AOP_TYPE (right) == AOP_CRY)
6570             {
6571               // c = bit | bit;
6572               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6573               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6574             }
6575           else
6576             {
6577               // c = bit | val;
6578               symbol *tlbl = newiTempLabel (NULL);
6579               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6580                 emitcode ("setb", "c");
6581               emitcode ("jb", "%s,!tlabel",
6582                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6583               toBoolean (right);
6584               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6585               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6586                 {
6587                   jmpTrueOrFalse (ifx, tlbl);
6588                   goto release;
6589                 }
6590               else
6591                 {
6592                   CLRC;
6593                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6594                 }
6595             }
6596         }
6597       // bit = c
6598       // val = c
6599       if (size)
6600         outBitC (result);
6601       // if(bit | ...)
6602       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6603            genIfxJump (ifx, "c");
6604       goto release;
6605     }
6606
6607   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6608   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6609   if ((AOP_TYPE (right) == AOP_LIT) &&
6610       (AOP_TYPE (result) == AOP_CRY) &&
6611       (AOP_TYPE (left) != AOP_CRY))
6612     {
6613       if (lit)
6614         {
6615           // result = 1
6616           if (size)
6617             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6618           else
6619             continueIfTrue (ifx);
6620           goto release;
6621         }
6622       else
6623         {
6624           // lit = 0, result = boolean(left)
6625           if (size)
6626             emitcode ("setb", "c");
6627           toBoolean (right);
6628           if (size)
6629             {
6630               symbol *tlbl = newiTempLabel (NULL);
6631               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6632               CLRC;
6633               emitcode ("", "!tlabeldef", tlbl->key + 100);
6634             }
6635           else
6636             {
6637               genIfxJump (ifx, "a");
6638               goto release;
6639             }
6640         }
6641       outBitC (result);
6642       goto release;
6643     }
6644
6645   /* if left is same as result */
6646   if (sameRegs (AOP (result), AOP (left)))
6647     {
6648       for (; size--; offset++)
6649         {
6650           if (AOP_TYPE (right) == AOP_LIT)
6651             {
6652               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6653                 {
6654                   continue;
6655                 }
6656               else
6657                 {
6658                   if (IS_AOP_PREG (left))
6659                     {
6660                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6661                       emitcode ("orl", "a,%s",
6662                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6663                       aopPut (AOP (result), "a", offset);
6664                     }
6665                   else
6666                     {
6667                       emitcode ("orl", "%s,%s",
6668                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6669                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6670                     }
6671                 }
6672             }
6673           else
6674             {
6675               if (AOP_TYPE (left) == AOP_ACC)
6676                 {
6677                   emitcode ("orl", "a,%s",
6678                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6679                 }
6680               else
6681                 {
6682                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6683                   if (IS_AOP_PREG (left))
6684                     {
6685                       emitcode ("orl", "a,%s", 
6686                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6687                       aopPut (AOP (result), "a", offset);
6688                     }
6689                   else
6690                     {
6691                       emitcode ("orl", "%s,a",
6692                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6693                     }
6694                 }
6695             }
6696         }
6697     }
6698   else
6699     {
6700       // left & result in different registers
6701       if (AOP_TYPE (result) == AOP_CRY)
6702         {
6703           // result = bit
6704           // if(size), result in bit
6705           // if(!size && ifx), conditional oper: if(left | right)
6706           symbol *tlbl = newiTempLabel (NULL);
6707           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6708           if (size)
6709             emitcode ("setb", "c");
6710           while (sizer--)
6711             {
6712               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6713                 emitcode ("orl", "a,%s",
6714                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6715               } else {
6716                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6717                 emitcode ("orl", "a,%s",
6718                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6719               }
6720               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6721               offset++;
6722             }
6723           if (size)
6724             {
6725               CLRC;
6726               emitcode ("", "!tlabeldef", tlbl->key + 100);
6727               outBitC (result);
6728             }
6729           else if (ifx)
6730             jmpTrueOrFalse (ifx, tlbl);
6731         }
6732       else
6733         {
6734             _startLazyDPSEvaluation();
6735           for (; (size--); offset++)
6736             {
6737               // normal case
6738               // result = left & right
6739               if (AOP_TYPE (right) == AOP_LIT)
6740                 {
6741                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6742                     {
6743                       aopPut (AOP (result),
6744                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6745                               offset);
6746                       continue;
6747                     }
6748                   D (emitcode (";", "better literal OR."););
6749                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6750                   emitcode ("orl", "a, %s",
6751                             aopGet (AOP (right), offset,
6752                                     FALSE, FALSE, DP2_RESULT_REG));
6753
6754                 }
6755               else
6756                 {
6757                   // faster than result <- left, anl result,right
6758                   // and better if result is SFR
6759                   if (AOP_TYPE (left) == AOP_ACC)
6760                     {
6761                       emitcode ("orl", "a,%s",
6762                                 aopGet (AOP (right), offset,
6763                                         FALSE, FALSE, DP2_RESULT_REG));
6764                     }
6765                   else
6766                     {
6767                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6768                         
6769                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6770                       {
6771                           emitcode("mov", "b,a");
6772                           rOp = "b";
6773                       }
6774                         
6775                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6776                       emitcode ("orl", "a,%s", rOp);
6777                     }
6778                 }
6779               aopPut (AOP (result), "a", offset);
6780             }
6781             _endLazyDPSEvaluation();
6782         }
6783     }
6784
6785 release:
6786   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6787   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6788   freeAsmop (result, NULL, ic, TRUE);
6789 }
6790
6791 /*-----------------------------------------------------------------*/
6792 /* genXor - code for xclusive or                                   */
6793 /*-----------------------------------------------------------------*/
6794 static void
6795 genXor (iCode * ic, iCode * ifx)
6796 {
6797   operand *left, *right, *result;
6798   int size, offset = 0;
6799   unsigned long lit = 0L;
6800   bool pushResult;
6801
6802   D (emitcode (";", "genXor "););
6803
6804   AOP_OP_3_NOFATAL (ic, pushResult);
6805   AOP_SET_LOCALS (ic);
6806
6807   if (pushResult)
6808   {
6809       genFarFarLogicOp(ic, "xrl");
6810       return;
6811   }  
6812
6813 #ifdef DEBUG_TYPE
6814   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6815             AOP_TYPE (result),
6816             AOP_TYPE (left), AOP_TYPE (right));
6817   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6818             AOP_SIZE (result),
6819             AOP_SIZE (left), AOP_SIZE (right));
6820 #endif
6821
6822   /* if left is a literal & right is not ||
6823      if left needs acc & right does not */
6824   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6825 #ifdef LOGIC_OPS_BROKEN      
6826       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6827 #endif
6828      )
6829     {
6830       operand *tmp = right;
6831       right = left;
6832       left = tmp;
6833     }
6834
6835   /* if result = right then exchange them */
6836   if (sameRegs (AOP (result), AOP (right)))
6837     {
6838       operand *tmp = right;
6839       right = left;
6840       left = tmp;
6841     }
6842
6843   /* if right is bit then exchange them */
6844   if (AOP_TYPE (right) == AOP_CRY &&
6845       AOP_TYPE (left) != AOP_CRY)
6846     {
6847       operand *tmp = right;
6848       right = left;
6849       left = tmp;
6850     }
6851   if (AOP_TYPE (right) == AOP_LIT)
6852     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6853
6854   size = AOP_SIZE (result);
6855
6856   // if(bit ^ yy)
6857   // xx = bit ^ yy;
6858   if (AOP_TYPE (left) == AOP_CRY)
6859     {
6860       if (AOP_TYPE (right) == AOP_LIT)
6861         {
6862           // c = bit & literal;
6863           if (lit >> 1)
6864             {
6865               // lit>>1  != 0 => result = 1
6866               if (AOP_TYPE (result) == AOP_CRY)
6867                 {
6868                   if (size)
6869                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6870                   else if (ifx)
6871                     continueIfTrue (ifx);
6872                   goto release;
6873                 }
6874               emitcode ("setb", "c");
6875             }
6876           else
6877             {
6878               // lit == (0 or 1)
6879               if (lit == 0)
6880                 {
6881                   // lit == 0, result = left
6882                   if (size && sameRegs (AOP (result), AOP (left)))
6883                     goto release;
6884                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6885                 }
6886               else
6887                 {
6888                   // lit == 1, result = not(left)
6889                   if (size && sameRegs (AOP (result), AOP (left)))
6890                     {
6891                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6892                       goto release;
6893                     }
6894                   else
6895                     {
6896                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6897                       emitcode ("cpl", "c");
6898                     }
6899                 }
6900             }
6901
6902         }
6903       else
6904         {
6905           // right != literal
6906           symbol *tlbl = newiTempLabel (NULL);
6907           if (AOP_TYPE (right) == AOP_CRY)
6908             {
6909               // c = bit ^ bit;
6910               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6911             }
6912           else
6913             {
6914               int sizer = AOP_SIZE (right);
6915               // c = bit ^ val
6916               // if val>>1 != 0, result = 1
6917               emitcode ("setb", "c");
6918               while (sizer)
6919                 {
6920                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6921                   if (sizer == 1)
6922                     // test the msb of the lsb
6923                     emitcode ("anl", "a,#!constbyte",0xfe);
6924                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6925                   sizer--;
6926                 }
6927               // val = (0,1)
6928               emitcode ("rrc", "a");
6929             }
6930           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6931           emitcode ("cpl", "c");
6932           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6933         }
6934       // bit = c
6935       // val = c
6936       if (size)
6937         outBitC (result);
6938       // if(bit | ...)
6939       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6940         genIfxJump (ifx, "c");
6941       goto release;
6942     }
6943
6944   if (sameRegs (AOP (result), AOP (left)))
6945     {
6946       /* if left is same as result */
6947       for (; size--; offset++)
6948         {
6949           if (AOP_TYPE (right) == AOP_LIT)
6950             {
6951               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6952                 continue;
6953               else if (IS_AOP_PREG (left))
6954                 {
6955                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6956                   emitcode ("xrl", "a,%s",
6957                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6958                   aopPut (AOP (result), "a", offset);
6959                 }
6960               else
6961                 emitcode ("xrl", "%s,%s",
6962                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6963                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6964             }
6965           else
6966             {
6967               if (AOP_TYPE (left) == AOP_ACC)
6968                 emitcode ("xrl", "a,%s",
6969                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6970               else
6971                 {
6972                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6973                   if (IS_AOP_PREG (left))
6974                     {
6975                       emitcode ("xrl", "a,%s",
6976                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6977                       aopPut (AOP (result), "a", offset);
6978                     }
6979                   else
6980                     emitcode ("xrl", "%s,a",
6981                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6982                 }
6983             }
6984         }
6985     }
6986   else
6987     {
6988       // left & result in different registers
6989       if (AOP_TYPE (result) == AOP_CRY)
6990         {
6991           // result = bit
6992           // if(size), result in bit
6993           // if(!size && ifx), conditional oper: if(left ^ right)
6994           symbol *tlbl = newiTempLabel (NULL);
6995           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6996                   
6997           if (size)
6998             emitcode ("setb", "c");
6999           while (sizer--)
7000             {
7001               if ((AOP_TYPE (right) == AOP_LIT) &&
7002                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7003                 {
7004                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7005                 }
7006               else
7007                 {
7008                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7009                     emitcode ("xrl", "a,%s",
7010                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7011                   } else {
7012                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7013                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7014                       {
7015                           emitcode("mov", "b,a");
7016                           rOp = "b";
7017                       }
7018                         
7019                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7020                       emitcode ("xrl", "a,%s", rOp);                  
7021                   }
7022                 }
7023               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7024               offset++;
7025             }
7026           if (size)
7027             {
7028               CLRC;
7029               emitcode ("", "!tlabeldef", tlbl->key + 100);
7030               outBitC (result);
7031             }
7032           else if (ifx)
7033             jmpTrueOrFalse (ifx, tlbl);
7034         }
7035       else
7036         {
7037         for (; (size--); offset++)
7038           {
7039             // normal case
7040             // result = left & right
7041             if (AOP_TYPE (right) == AOP_LIT)
7042               {
7043                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7044                   {
7045                     aopPut (AOP (result),
7046                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7047                             offset);
7048                     continue;
7049                   }
7050                 D (emitcode (";", "better literal XOR."););
7051                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7052                 emitcode ("xrl", "a, %s",
7053                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7054               }
7055             else
7056               {
7057                 // faster than result <- left, anl result,right
7058                 // and better if result is SFR
7059                 if (AOP_TYPE (left) == AOP_ACC)
7060                   {
7061                     emitcode ("xrl", "a,%s",
7062                               aopGet (AOP (right), offset,
7063                                       FALSE, FALSE, DP2_RESULT_REG));
7064                   }
7065                 else
7066                   {
7067                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7068                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7069                       {
7070                           emitcode("mov", "b,a");
7071                           rOp = "b";
7072                       }
7073                         
7074                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7075                       emitcode ("xrl", "a,%s", rOp);
7076                   }
7077               }
7078             aopPut (AOP (result), "a", offset);
7079           }
7080         }
7081         
7082     }
7083
7084 release:
7085   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7086   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7087   freeAsmop (result, NULL, ic, TRUE);
7088 }
7089
7090 /*-----------------------------------------------------------------*/
7091 /* genInline - write the inline code out                           */
7092 /*-----------------------------------------------------------------*/
7093 static void
7094 genInline (iCode * ic)
7095 {
7096   char *buffer, *bp, *bp1;
7097
7098   D (emitcode (";", "genInline "); );
7099
7100   _G.inLine += (!options.asmpeep);
7101
7102   buffer = Safe_strdup(IC_INLINE(ic));
7103   bp = buffer;
7104   bp1 = buffer;
7105
7106   /* emit each line as a code */
7107   while (*bp)
7108     {
7109       if (*bp == '\n')
7110         {
7111           *bp++ = '\0';
7112           emitcode (bp1, "");
7113           bp1 = bp;
7114         }
7115       else
7116         {
7117           if (*bp == ':')
7118             {
7119               bp++;
7120               *bp = '\0';
7121               bp++;
7122               emitcode (bp1, "");
7123               bp1 = bp;
7124             }
7125           else
7126             bp++;
7127         }
7128     }
7129   if (bp1 != bp)
7130     emitcode (bp1, "");
7131   /*     emitcode("",buffer); */
7132   _G.inLine -= (!options.asmpeep);
7133 }
7134
7135 /*-----------------------------------------------------------------*/
7136 /* genRRC - rotate right with carry                                */
7137 /*-----------------------------------------------------------------*/
7138 static void
7139 genRRC (iCode * ic)
7140 {
7141   operand *left, *result;
7142   int     size, offset;
7143
7144   D (emitcode (";", "genRRC "););
7145
7146   /* rotate right with carry */
7147   left = IC_LEFT (ic);
7148   result = IC_RESULT (ic);
7149   aopOp (left, ic, FALSE, FALSE);
7150   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7151
7152   /* move it to the result */
7153   size = AOP_SIZE (result);
7154   offset = size - 1;
7155   CLRC;
7156
7157   _startLazyDPSEvaluation ();
7158   while (size--)
7159     {
7160       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7161       emitcode ("rrc", "a");
7162       if (AOP_SIZE (result) > 1)
7163         aopPut (AOP (result), "a", offset--);
7164     }
7165   _endLazyDPSEvaluation ();
7166
7167   /* now we need to put the carry into the
7168      highest order byte of the result */
7169   if (AOP_SIZE (result) > 1)
7170     {
7171       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7172     }
7173   emitcode ("mov", "acc.7,c");
7174   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7175   freeAsmop (left, NULL, ic, TRUE);
7176   freeAsmop (result, NULL, ic, TRUE);
7177 }
7178
7179 /*-----------------------------------------------------------------*/
7180 /* genRLC - generate code for rotate left with carry               */
7181 /*-----------------------------------------------------------------*/
7182 static void
7183 genRLC (iCode * ic)
7184 {
7185   operand *left, *result;
7186   int size, offset;
7187   char *l;
7188
7189   D (emitcode (";", "genRLC "););
7190
7191   /* rotate right with carry */
7192   left = IC_LEFT (ic);
7193   result = IC_RESULT (ic);
7194   aopOp (left, ic, FALSE, FALSE);
7195   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7196
7197   /* move it to the result */
7198   size = AOP_SIZE (result);
7199   offset = 0;
7200   if (size--)
7201     {
7202       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7203       MOVA (l);
7204       emitcode ("add", "a,acc");
7205       if (AOP_SIZE (result) > 1)
7206         {
7207           aopPut (AOP (result), "a", offset++);
7208         }
7209
7210       _startLazyDPSEvaluation ();
7211       while (size--)
7212         {
7213           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7214           MOVA (l);
7215           emitcode ("rlc", "a");
7216           if (AOP_SIZE (result) > 1)
7217             aopPut (AOP (result), "a", offset++);
7218         }
7219       _endLazyDPSEvaluation ();
7220     }
7221   /* now we need to put the carry into the
7222      highest order byte of the result */
7223   if (AOP_SIZE (result) > 1)
7224     {
7225       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7226       MOVA (l);
7227     }
7228   emitcode ("mov", "acc.0,c");
7229   aopPut (AOP (result), "a", 0);
7230   freeAsmop (left, NULL, ic, TRUE);
7231   freeAsmop (result, NULL, ic, TRUE);
7232 }
7233
7234 /*-----------------------------------------------------------------*/
7235 /* genGetHbit - generates code get highest order bit               */
7236 /*-----------------------------------------------------------------*/
7237 static void
7238 genGetHbit (iCode * ic)
7239 {
7240   operand *left, *result;
7241   left = IC_LEFT (ic);
7242   result = IC_RESULT (ic);
7243   aopOp (left, ic, FALSE, FALSE);
7244   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7245
7246   D (emitcode (";", "genGetHbit "););
7247
7248   /* get the highest order byte into a */
7249   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7250   if (AOP_TYPE (result) == AOP_CRY)
7251     {
7252       emitcode ("rlc", "a");
7253       outBitC (result);
7254     }
7255   else
7256     {
7257       emitcode ("rl", "a");
7258       emitcode ("anl", "a,#1");
7259       outAcc (result);
7260     }
7261
7262
7263   freeAsmop (left, NULL, ic, TRUE);
7264   freeAsmop (result, NULL, ic, TRUE);
7265 }
7266
7267 /*-----------------------------------------------------------------*/
7268 /* AccRol - rotate left accumulator by known count                 */
7269 /*-----------------------------------------------------------------*/
7270 static void
7271 AccRol (int shCount)
7272 {
7273   shCount &= 0x0007;            // shCount : 0..7
7274
7275   switch (shCount)
7276     {
7277     case 0:
7278       break;
7279     case 1:
7280       emitcode ("rl", "a");
7281       break;
7282     case 2:
7283       emitcode ("rl", "a");
7284       emitcode ("rl", "a");
7285       break;
7286     case 3:
7287       emitcode ("swap", "a");
7288       emitcode ("rr", "a");
7289       break;
7290     case 4:
7291       emitcode ("swap", "a");
7292       break;
7293     case 5:
7294       emitcode ("swap", "a");
7295       emitcode ("rl", "a");
7296       break;
7297     case 6:
7298       emitcode ("rr", "a");
7299       emitcode ("rr", "a");
7300       break;
7301     case 7:
7302       emitcode ("rr", "a");
7303       break;
7304     }
7305 }
7306
7307 /*-----------------------------------------------------------------*/
7308 /* AccLsh - left shift accumulator by known count                  */
7309 /*-----------------------------------------------------------------*/
7310 static void
7311 AccLsh (int shCount)
7312 {
7313   if (shCount != 0)
7314     {
7315       if (shCount == 1)
7316         emitcode ("add", "a,acc");
7317       else if (shCount == 2)
7318         {
7319           emitcode ("add", "a,acc");
7320           emitcode ("add", "a,acc");
7321         }
7322       else
7323         {
7324           /* rotate left accumulator */
7325           AccRol (shCount);
7326           /* and kill the lower order bits */
7327           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7328         }
7329     }
7330 }
7331
7332 /*-----------------------------------------------------------------*/
7333 /* AccRsh - right shift accumulator by known count                 */
7334 /*-----------------------------------------------------------------*/
7335 static void
7336 AccRsh (int shCount)
7337 {
7338   if (shCount != 0)
7339     {
7340       if (shCount == 1)
7341         {
7342           CLRC;
7343           emitcode ("rrc", "a");
7344         }
7345       else
7346         {
7347           /* rotate right accumulator */
7348           AccRol (8 - shCount);
7349           /* and kill the higher order bits */
7350           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7351         }
7352     }
7353 }
7354
7355 #ifdef BETTER_LITERAL_SHIFT
7356 /*-----------------------------------------------------------------*/
7357 /* AccSRsh - signed right shift accumulator by known count                 */
7358 /*-----------------------------------------------------------------*/
7359 static void
7360 AccSRsh (int shCount)
7361 {
7362   symbol *tlbl;
7363   if (shCount != 0)
7364     {
7365       if (shCount == 1)
7366         {
7367           emitcode ("mov", "c,acc.7");
7368           emitcode ("rrc", "a");
7369         }
7370       else if (shCount == 2)
7371         {
7372           emitcode ("mov", "c,acc.7");
7373           emitcode ("rrc", "a");
7374           emitcode ("mov", "c,acc.7");
7375           emitcode ("rrc", "a");
7376         }
7377       else
7378         {
7379           tlbl = newiTempLabel (NULL);
7380           /* rotate right accumulator */
7381           AccRol (8 - shCount);
7382           /* and kill the higher order bits */
7383           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7384           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7385           emitcode ("orl", "a,#!constbyte",
7386                     (unsigned char) ~SRMask[shCount]);
7387           emitcode ("", "!tlabeldef", tlbl->key + 100);
7388         }
7389     }
7390 }
7391 #endif
7392
7393 #ifdef BETTER_LITERAL_SHIFT
7394 /*-----------------------------------------------------------------*/
7395 /* shiftR1Left2Result - shift right one byte from left to result   */
7396 /*-----------------------------------------------------------------*/
7397 static void
7398 shiftR1Left2Result (operand * left, int offl,
7399                     operand * result, int offr,
7400                     int shCount, int sign)
7401 {
7402   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7403   /* shift right accumulator */
7404   if (sign)
7405     AccSRsh (shCount);
7406   else
7407     AccRsh (shCount);
7408   aopPut (AOP (result), "a", offr);
7409 }
7410 #endif
7411
7412 #ifdef BETTER_LITERAL_SHIFT
7413 /*-----------------------------------------------------------------*/
7414 /* shiftL1Left2Result - shift left one byte from left to result    */
7415 /*-----------------------------------------------------------------*/
7416 static void
7417 shiftL1Left2Result (operand * left, int offl,
7418                     operand * result, int offr, int shCount)
7419 {
7420   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7421   /* shift left accumulator */
7422   AccLsh (shCount);
7423   aopPut (AOP (result), "a", offr);
7424 }
7425 #endif
7426
7427 #ifdef BETTER_LITERAL_SHIFT
7428 /*-----------------------------------------------------------------*/
7429 /* movLeft2Result - move byte from left to result                  */
7430 /*-----------------------------------------------------------------*/
7431 static void
7432 movLeft2Result (operand * left, int offl,
7433                 operand * result, int offr, int sign)
7434 {
7435   char *l;
7436   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7437   {
7438       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7439
7440       if (*l == '@' && (IS_AOP_PREG (result)))
7441       {
7442           emitcode ("mov", "a,%s", l);
7443           aopPut (AOP (result), "a", offr);
7444       }
7445       else
7446       {
7447           if (!sign)
7448           {
7449             aopPut (AOP (result), l, offr);
7450           }
7451           else
7452             {
7453               /* MSB sign in acc.7 ! */
7454               if (getDataSize (left) == offl + 1)
7455                 {
7456                   emitcode ("mov", "a,%s", l);
7457                   aopPut (AOP (result), "a", offr);
7458                 }
7459             }
7460       }
7461   }
7462 }
7463 #endif
7464
7465 #ifdef BETTER_LITERAL_SHIFT
7466 /*-----------------------------------------------------------------*/
7467 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7468 /*-----------------------------------------------------------------*/
7469 static void
7470 AccAXRrl1 (char *x)
7471 {
7472   emitcode ("rrc", "a");
7473   emitcode ("xch", "a,%s", x);
7474   emitcode ("rrc", "a");
7475   emitcode ("xch", "a,%s", x);
7476 }
7477 #endif
7478
7479 #ifdef BETTER_LITERAL_SHIFT
7480 //REMOVE ME!!!
7481 /*-----------------------------------------------------------------*/
7482 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7483 /*-----------------------------------------------------------------*/
7484 static void
7485 AccAXLrl1 (char *x)
7486 {
7487   emitcode ("xch", "a,%s", x);
7488   emitcode ("rlc", "a");
7489   emitcode ("xch", "a,%s", x);
7490   emitcode ("rlc", "a");
7491 }
7492 #endif
7493
7494 #ifdef BETTER_LITERAL_SHIFT
7495 /*-----------------------------------------------------------------*/
7496 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7497 /*-----------------------------------------------------------------*/
7498 static void
7499 AccAXLsh1 (char *x)
7500 {
7501   emitcode ("xch", "a,%s", x);
7502   emitcode ("add", "a,acc");
7503   emitcode ("xch", "a,%s", x);
7504   emitcode ("rlc", "a");
7505 }
7506 #endif
7507
7508 #ifdef BETTER_LITERAL_SHIFT
7509 /*-----------------------------------------------------------------*/
7510 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7511 /*-----------------------------------------------------------------*/
7512 static void
7513 AccAXLsh (char *x, int shCount)
7514 {
7515   switch (shCount)
7516     {
7517     case 0:
7518       break;
7519     case 1:
7520       AccAXLsh1 (x);
7521       break;
7522     case 2:
7523       AccAXLsh1 (x);
7524       AccAXLsh1 (x);
7525       break;
7526     case 3:
7527     case 4:
7528     case 5:                     // AAAAABBB:CCCCCDDD
7529
7530       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7531
7532       emitcode ("anl", "a,#!constbyte",
7533                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7534
7535       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7536
7537       AccRol (shCount);         // DDDCCCCC:BBB00000
7538
7539       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7540
7541       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7542
7543       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7544
7545       emitcode ("anl", "a,#!constbyte",
7546                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7547
7548       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7549
7550       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7551
7552       break;
7553     case 6:                     // AAAAAABB:CCCCCCDD
7554       emitcode ("anl", "a,#!constbyte",
7555                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7556       emitcode ("mov", "c,acc.0");      // c = B
7557       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7558 #if 0
7559       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7560       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7561 #else
7562       emitcode("rrc","a"); 
7563       emitcode("xch","a,%s", x); 
7564       emitcode("rrc","a"); 
7565       emitcode("mov","c,acc.0"); //<< get correct bit 
7566       emitcode("xch","a,%s", x); 
7567
7568       emitcode("rrc","a"); 
7569       emitcode("xch","a,%s", x); 
7570       emitcode("rrc","a"); 
7571       emitcode("xch","a,%s", x); 
7572 #endif
7573       break;
7574     case 7:                     // a:x <<= 7
7575
7576       emitcode ("anl", "a,#!constbyte",
7577                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7578
7579       emitcode ("mov", "c,acc.0");      // c = B
7580
7581       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7582
7583       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7584
7585       break;
7586     default:
7587       break;
7588     }
7589 }
7590 #endif
7591
7592 #ifdef BETTER_LITERAL_SHIFT
7593 //REMOVE ME!!!
7594 /*-----------------------------------------------------------------*/
7595 /* AccAXRsh - right shift a:x known count (0..7)                   */
7596 /*-----------------------------------------------------------------*/
7597 static void
7598 AccAXRsh (char *x, int shCount)
7599 {
7600   switch (shCount)
7601     {
7602     case 0:
7603       break;
7604     case 1:
7605       CLRC;
7606       AccAXRrl1 (x);            // 0->a:x
7607
7608       break;
7609     case 2:
7610       CLRC;
7611       AccAXRrl1 (x);            // 0->a:x
7612
7613       CLRC;
7614       AccAXRrl1 (x);            // 0->a:x
7615
7616       break;
7617     case 3:
7618     case 4:
7619     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7620
7621       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7622
7623       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7624
7625       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7626
7627       emitcode ("anl", "a,#!constbyte",
7628                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7629
7630       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7631
7632       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7633
7634       emitcode ("anl", "a,#!constbyte",
7635                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7636
7637       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7638
7639       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7640
7641       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7642
7643       break;
7644     case 6:                     // AABBBBBB:CCDDDDDD
7645
7646       emitcode ("mov", "c,acc.7");
7647       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7648
7649       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7650
7651       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7652
7653       emitcode ("anl", "a,#!constbyte",
7654                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7655
7656       break;
7657     case 7:                     // ABBBBBBB:CDDDDDDD
7658
7659       emitcode ("mov", "c,acc.7");      // c = A
7660
7661       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7662
7663       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7664
7665       emitcode ("anl", "a,#!constbyte",
7666                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7667
7668       break;
7669     default:
7670       break;
7671     }
7672 }
7673 #endif
7674
7675 #ifdef BETTER_LITERAL_SHIFT
7676 /*-----------------------------------------------------------------*/
7677 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7678 /*-----------------------------------------------------------------*/
7679 static void
7680 AccAXRshS (char *x, int shCount)
7681 {
7682   symbol *tlbl;
7683   switch (shCount)
7684     {
7685     case 0:
7686       break;
7687     case 1:
7688       emitcode ("mov", "c,acc.7");
7689       AccAXRrl1 (x);            // s->a:x
7690
7691       break;
7692     case 2:
7693       emitcode ("mov", "c,acc.7");
7694       AccAXRrl1 (x);            // s->a:x
7695
7696       emitcode ("mov", "c,acc.7");
7697       AccAXRrl1 (x);            // s->a:x
7698
7699       break;
7700     case 3:
7701     case 4:
7702     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7703
7704       tlbl = newiTempLabel (NULL);
7705       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7706
7707       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7708
7709       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7710
7711       emitcode ("anl", "a,#!constbyte",
7712                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7713
7714       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7715
7716       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7717
7718       emitcode ("anl", "a,#!constbyte",
7719                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7720
7721       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7722
7723       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7724
7725       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7726
7727       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7728       emitcode ("orl", "a,#!constbyte",
7729                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7730
7731       emitcode ("", "!tlabeldef", tlbl->key + 100);
7732       break;                    // SSSSAAAA:BBBCCCCC
7733
7734     case 6:                     // AABBBBBB:CCDDDDDD
7735
7736       tlbl = newiTempLabel (NULL);
7737       emitcode ("mov", "c,acc.7");
7738       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7739
7740       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7741
7742       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7743
7744       emitcode ("anl", "a,#!constbyte",
7745                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7746
7747       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7748       emitcode ("orl", "a,#!constbyte",
7749                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7750
7751       emitcode ("", "!tlabeldef", tlbl->key + 100);
7752       break;
7753     case 7:                     // ABBBBBBB:CDDDDDDD
7754
7755       tlbl = newiTempLabel (NULL);
7756       emitcode ("mov", "c,acc.7");      // c = A
7757
7758       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7759
7760       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7761
7762       emitcode ("anl", "a,#!constbyte",
7763                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7764
7765       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7766       emitcode ("orl", "a,#!constbyte",
7767                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7768
7769       emitcode ("", "!tlabeldef", tlbl->key + 100);
7770       break;
7771     default:
7772       break;
7773     }
7774 }
7775 #endif
7776
7777 #ifdef BETTER_LITERAL_SHIFT
7778 static void
7779 _loadLeftIntoAx(char    **lsb, 
7780                 operand *left, 
7781                 operand *result,
7782                 int     offl,
7783                 int     offr)
7784 {
7785   // Get the initial value from left into a pair of registers.
7786   // MSB must be in A, LSB can be any register.
7787   //
7788   // If the result is held in registers, it is an optimization
7789   // if the LSB can be held in the register which will hold the,
7790   // result LSB since this saves us from having to copy it into
7791   // the result following AccAXLsh.
7792   //
7793   // If the result is addressed indirectly, this is not a gain.
7794   if (AOP_NEEDSACC(result))
7795   {
7796        char *leftByte;
7797        
7798        _startLazyDPSEvaluation();
7799       if (AOP_TYPE(left) == AOP_DPTR2)
7800        {
7801            // Get MSB in A.
7802            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7803            // get LSB in DP2_RESULT_REG.
7804            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7805            assert(!strcmp(leftByte, DP2_RESULT_REG));
7806        }
7807        else
7808        {
7809            // get LSB into DP2_RESULT_REG
7810            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7811            if (strcmp(leftByte, DP2_RESULT_REG))
7812            {
7813                TR_AP("#7");
7814                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7815            }
7816            // And MSB in A.
7817            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7818            assert(strcmp(leftByte, DP2_RESULT_REG));
7819            MOVA(leftByte);
7820        }
7821        _endLazyDPSEvaluation();
7822        *lsb = DP2_RESULT_REG;
7823   }
7824   else
7825   {
7826       if (sameRegs (AOP (result), AOP (left)) &&
7827         ((offl + MSB16) == offr))
7828       {
7829           /* don't crash result[offr] */
7830           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7831           emitcode ("xch", "a,%s", 
7832                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7833       }
7834       else
7835       {
7836           movLeft2Result (left, offl, result, offr, 0);
7837           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7838       }
7839       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7840       assert(strcmp(*lsb,"a"));      
7841   }
7842 }
7843
7844 static void
7845 _storeAxResults(char    *lsb,
7846                 operand *result,
7847                 int     offr)
7848 {
7849   _startLazyDPSEvaluation();
7850   if (AOP_NEEDSACC(result))
7851   {
7852       /* We have to explicitly update the result LSB.
7853        */
7854       emitcode("xch","a,%s", lsb);
7855       aopPut(AOP(result), "a", offr);
7856       emitcode("mov","a,%s", lsb);
7857   }
7858   if (getDataSize (result) > 1)
7859   {
7860       aopPut (AOP (result), "a", offr + MSB16);
7861   }
7862   _endLazyDPSEvaluation();
7863 }
7864
7865 /*-----------------------------------------------------------------*/
7866 /* shiftL2Left2Result - shift left two bytes from left to result   */
7867 /*-----------------------------------------------------------------*/
7868 static void
7869 shiftL2Left2Result (operand * left, int offl,
7870                     operand * result, int offr, int shCount)
7871 {
7872   char *lsb;
7873
7874   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7875   
7876   AccAXLsh (lsb, shCount);
7877   
7878   _storeAxResults(lsb, result, offr);
7879 }
7880 #endif
7881
7882 #ifdef BETTER_LITERAL_SHIFT
7883 /*-----------------------------------------------------------------*/
7884 /* shiftR2Left2Result - shift right two bytes from left to result  */
7885 /*-----------------------------------------------------------------*/
7886 static void
7887 shiftR2Left2Result (operand * left, int offl,
7888                     operand * result, int offr,
7889                     int shCount, int sign)
7890 {
7891   char *lsb;
7892   
7893   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7894   
7895   /* a:x >> shCount (x = lsb(result)) */
7896   if (sign)
7897   {
7898      AccAXRshS(lsb, shCount);
7899   }
7900   else
7901   {
7902     AccAXRsh(lsb, shCount);
7903   }
7904   
7905   _storeAxResults(lsb, result, offr);
7906 }
7907 #endif
7908
7909 #if 0
7910 //REMOVE ME!!!
7911 /*-----------------------------------------------------------------*/
7912 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7913 /*-----------------------------------------------------------------*/
7914 static void
7915 shiftLLeftOrResult (operand * left, int offl,
7916                     operand * result, int offr, int shCount)
7917 {
7918   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7919   /* shift left accumulator */
7920   AccLsh (shCount);
7921   /* or with result */
7922   emitcode ("orl", "a,%s",
7923             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7924   /* back to result */
7925   aopPut (AOP (result), "a", offr);
7926 }
7927 #endif
7928
7929 #if 0
7930 //REMOVE ME!!!
7931 /*-----------------------------------------------------------------*/
7932 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7933 /*-----------------------------------------------------------------*/
7934 static void
7935 shiftRLeftOrResult (operand * left, int offl,
7936                     operand * result, int offr, int shCount)
7937 {
7938   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7939   /* shift right accumulator */
7940   AccRsh (shCount);
7941   /* or with result */
7942   emitcode ("orl", "a,%s",
7943             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7944   /* back to result */
7945   aopPut (AOP (result), "a", offr);
7946 }
7947 #endif
7948
7949 #ifdef BETTER_LITERAL_SHIFT
7950 /*-----------------------------------------------------------------*/
7951 /* genlshOne - left shift a one byte quantity by known count       */
7952 /*-----------------------------------------------------------------*/
7953 static void
7954 genlshOne (operand * result, operand * left, int shCount)
7955 {
7956   D (emitcode (";", "genlshOne "););
7957   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7958 }
7959 #endif
7960
7961 #ifdef BETTER_LITERAL_SHIFT
7962 /*-----------------------------------------------------------------*/
7963 /* genlshTwo - left shift two bytes by known amount != 0           */
7964 /*-----------------------------------------------------------------*/
7965 static void
7966 genlshTwo (operand * result, operand * left, int shCount)
7967 {
7968   int size;
7969
7970   D (emitcode (";", "genlshTwo "););
7971
7972   size = getDataSize (result);
7973
7974   /* if shCount >= 8 */
7975   if (shCount >= 8)
7976   {
7977       shCount -= 8;
7978
7979       _startLazyDPSEvaluation();
7980
7981       if (size > 1)
7982         {
7983           if (shCount)
7984           {
7985             _endLazyDPSEvaluation();
7986             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7987             aopPut (AOP (result), zero, LSB);       
7988           }
7989           else
7990           {
7991             movLeft2Result (left, LSB, result, MSB16, 0);
7992             aopPut (AOP (result), zero, LSB);
7993             _endLazyDPSEvaluation();
7994           }
7995         }
7996         else
7997         {
7998           aopPut (AOP (result), zero, LSB);
7999           _endLazyDPSEvaluation();
8000         }
8001   }
8002
8003   /*  1 <= shCount <= 7 */
8004   else
8005     {
8006       if (size == 1)
8007       {
8008         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8009       }
8010       else
8011       {
8012         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8013       }
8014     }
8015 }
8016 #endif
8017
8018 #if 0
8019 //REMOVE ME!!!
8020 /*-----------------------------------------------------------------*/
8021 /* shiftLLong - shift left one long from left to result            */
8022 /* offl = LSB or MSB16                                             */
8023 /*-----------------------------------------------------------------*/
8024 static void
8025 shiftLLong (operand * left, operand * result, int offr)
8026 {
8027   char *l;
8028   int size = AOP_SIZE (result);
8029
8030   if (size >= LSB + offr)
8031     {
8032       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8033       MOVA (l);
8034       emitcode ("add", "a,acc");
8035       if (sameRegs (AOP (left), AOP (result)) &&
8036           size >= MSB16 + offr && offr != LSB)
8037         emitcode ("xch", "a,%s",
8038                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8039       else
8040         aopPut (AOP (result), "a", LSB + offr);
8041     }
8042
8043   if (size >= MSB16 + offr)
8044     {
8045       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8046         {
8047           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8048         }
8049       emitcode ("rlc", "a");
8050       if (sameRegs (AOP (left), AOP (result)) &&
8051           size >= MSB24 + offr && offr != LSB)
8052         emitcode ("xch", "a,%s",
8053                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8054       else
8055         aopPut (AOP (result), "a", MSB16 + offr);
8056     }
8057
8058   if (size >= MSB24 + offr)
8059     {
8060       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8061         {
8062           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8063         }
8064       emitcode ("rlc", "a");
8065       if (sameRegs (AOP (left), AOP (result)) &&
8066           size >= MSB32 + offr && offr != LSB)
8067         emitcode ("xch", "a,%s",
8068                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8069       else
8070         aopPut (AOP (result), "a", MSB24 + offr);
8071     }
8072
8073   if (size > MSB32 + offr)
8074     {
8075       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8076         {
8077           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8078         }
8079       emitcode ("rlc", "a");
8080       aopPut (AOP (result), "a", MSB32 + offr);
8081     }
8082   if (offr != LSB)
8083     aopPut (AOP (result), zero, LSB);
8084 }
8085 #endif
8086
8087 #if 0
8088 //REMOVE ME!!!
8089 /*-----------------------------------------------------------------*/
8090 /* genlshFour - shift four byte by a known amount != 0             */
8091 /*-----------------------------------------------------------------*/
8092 static void
8093 genlshFour (operand * result, operand * left, int shCount)
8094 {
8095   int size;
8096
8097   D (emitcode (";", "genlshFour ");
8098     );
8099
8100   size = AOP_SIZE (result);
8101
8102   /* if shifting more that 3 bytes */
8103   if (shCount >= 24)
8104     {
8105       shCount -= 24;
8106       if (shCount)
8107         /* lowest order of left goes to the highest
8108            order of the destination */
8109         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8110       else
8111         movLeft2Result (left, LSB, result, MSB32, 0);
8112       aopPut (AOP (result), zero, LSB);
8113       aopPut (AOP (result), zero, MSB16);
8114       aopPut (AOP (result), zero, MSB24);
8115       return;
8116     }
8117
8118   /* more than two bytes */
8119   else if (shCount >= 16)
8120     {
8121       /* lower order two bytes goes to higher order two bytes */
8122       shCount -= 16;
8123       /* if some more remaining */
8124       if (shCount)
8125         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8126       else
8127         {
8128           movLeft2Result (left, MSB16, result, MSB32, 0);
8129           movLeft2Result (left, LSB, result, MSB24, 0);
8130         }
8131       aopPut (AOP (result), zero, MSB16);
8132       aopPut (AOP (result), zero, LSB);
8133       return;
8134     }
8135
8136   /* if more than 1 byte */
8137   else if (shCount >= 8)
8138     {
8139       /* lower order three bytes goes to higher order  three bytes */
8140       shCount -= 8;
8141       if (size == 2)
8142         {
8143           if (shCount)
8144             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8145           else
8146             movLeft2Result (left, LSB, result, MSB16, 0);
8147         }
8148       else
8149         {                       /* size = 4 */
8150           if (shCount == 0)
8151             {
8152               movLeft2Result (left, MSB24, result, MSB32, 0);
8153               movLeft2Result (left, MSB16, result, MSB24, 0);
8154               movLeft2Result (left, LSB, result, MSB16, 0);
8155               aopPut (AOP (result), zero, LSB);
8156             }
8157           else if (shCount == 1)
8158             shiftLLong (left, result, MSB16);
8159           else
8160             {
8161               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8162               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8163               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8164               aopPut (AOP (result), zero, LSB);
8165             }
8166         }
8167     }
8168
8169   /* 1 <= shCount <= 7 */
8170   else if (shCount <= 2)
8171     {
8172       shiftLLong (left, result, LSB);
8173       if (shCount == 2)
8174         shiftLLong (result, result, LSB);
8175     }
8176   /* 3 <= shCount <= 7, optimize */
8177   else
8178     {
8179       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8180       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8181       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8182     }
8183 }
8184 #endif
8185
8186 #ifdef BETTER_LITERAL_SHIFT
8187 /*-----------------------------------------------------------------*/
8188 /* genLeftShiftLiteral - left shifting by known count              */
8189 /*-----------------------------------------------------------------*/
8190 static bool
8191 genLeftShiftLiteral (operand * left,
8192                      operand * right,
8193                      operand * result,
8194                      iCode * ic)
8195 {
8196   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8197   int size;
8198
8199   size = getSize (operandType (result));
8200
8201   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8202
8203   /* We only handle certain easy cases so far. */
8204   if ((shCount != 0)
8205    && (shCount < (size * 8))
8206    && (size != 1)
8207    && (size != 2))
8208   {
8209       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8210       return FALSE;
8211   }
8212
8213   freeAsmop (right, NULL, ic, TRUE);
8214
8215   aopOp(left, ic, FALSE, FALSE);
8216   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8217
8218 #if 0 // debug spew
8219   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8220   {
8221         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8222         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8223         {
8224            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8225         }
8226   }
8227   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8228   {
8229         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8230         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8231         {
8232            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8233         }       
8234   }  
8235 #endif
8236   
8237 #if VIEW_SIZE
8238   emitcode ("; shift left ", "result %d, left %d", size,
8239             AOP_SIZE (left));
8240 #endif
8241
8242   /* I suppose that the left size >= result size */
8243   if (shCount == 0)
8244   {
8245         _startLazyDPSEvaluation();
8246         while (size--)
8247         {
8248           movLeft2Result (left, size, result, size, 0);
8249         }
8250         _endLazyDPSEvaluation();
8251   }
8252   else if (shCount >= (size * 8))
8253   {
8254     _startLazyDPSEvaluation();
8255     while (size--)
8256     {
8257       aopPut (AOP (result), zero, size);
8258     }
8259     _endLazyDPSEvaluation();
8260   }
8261   else
8262   {
8263       switch (size)
8264         {
8265         case 1:
8266           genlshOne (result, left, shCount);
8267           break;
8268
8269         case 2:
8270           genlshTwo (result, left, shCount);
8271           break;
8272 #if 0
8273         case 4:
8274           genlshFour (result, left, shCount);
8275           break;
8276 #endif
8277         default:
8278           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8279           break;
8280         }
8281     }
8282   freeAsmop (left, NULL, ic, TRUE);
8283   freeAsmop (result, NULL, ic, TRUE);
8284   return TRUE;
8285 }
8286 #endif
8287
8288 /*-----------------------------------------------------------------*/
8289 /* genLeftShift - generates code for left shifting                 */
8290 /*-----------------------------------------------------------------*/
8291 static void
8292 genLeftShift (iCode * ic)
8293 {
8294   operand *left, *right, *result;
8295   int size, offset;
8296   char *l;
8297   symbol *tlbl, *tlbl1;
8298
8299   D (emitcode (";", "genLeftShift "););
8300
8301   right = IC_RIGHT (ic);
8302   left = IC_LEFT (ic);
8303   result = IC_RESULT (ic);
8304
8305   aopOp (right, ic, FALSE, FALSE);
8306
8307
8308 #ifdef BETTER_LITERAL_SHIFT
8309   /* if the shift count is known then do it
8310      as efficiently as possible */
8311   if (AOP_TYPE (right) == AOP_LIT)
8312     {
8313       if (genLeftShiftLiteral (left, right, result, ic))
8314       {
8315         return;
8316       }
8317     }
8318 #endif
8319
8320   /* shift count is unknown then we have to form
8321      a loop get the loop count in B : Note: we take
8322      only the lower order byte since shifting
8323      more that 32 bits make no sense anyway, ( the
8324      largest size of an object can be only 32 bits ) */
8325
8326   if (AOP_TYPE (right) == AOP_LIT)
8327   {
8328       /* Really should be handled by genLeftShiftLiteral,
8329        * but since I'm too lazy to fix that today, at least we can make
8330        * some small improvement.
8331        */
8332        emitcode("mov", "b,#!constbyte",
8333                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8334   }
8335   else
8336   {
8337       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8338       emitcode ("inc", "b");
8339   }
8340   freeAsmop (right, NULL, ic, TRUE);
8341   aopOp (left, ic, FALSE, FALSE);
8342   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8343
8344   /* now move the left to the result if they are not the
8345      same */
8346   if (!sameRegs (AOP (left), AOP (result)) &&
8347       AOP_SIZE (result) > 1)
8348     {
8349
8350       size = AOP_SIZE (result);
8351       offset = 0;
8352       _startLazyDPSEvaluation ();
8353       while (size--)
8354         {
8355           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8356           if (*l == '@' && (IS_AOP_PREG (result)))
8357             {
8358
8359               emitcode ("mov", "a,%s", l);
8360               aopPut (AOP (result), "a", offset);
8361             }
8362           else
8363             aopPut (AOP (result), l, offset);
8364           offset++;
8365         }
8366       _endLazyDPSEvaluation ();
8367     }
8368
8369   tlbl = newiTempLabel (NULL);
8370   size = AOP_SIZE (result);
8371   offset = 0;
8372   tlbl1 = newiTempLabel (NULL);
8373
8374   /* if it is only one byte then */
8375   if (size == 1)
8376     {
8377       symbol *tlbl1 = newiTempLabel (NULL);
8378
8379       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8380       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8381       emitcode ("", "!tlabeldef", tlbl->key + 100);
8382       emitcode ("add", "a,acc");
8383       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8384       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8385       aopPut (AOP (result), "a", 0);
8386       goto release;
8387     }
8388
8389   reAdjustPreg (AOP (result));
8390
8391   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8392   emitcode ("", "!tlabeldef", tlbl->key + 100);
8393   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8394   emitcode ("add", "a,acc");
8395   aopPut (AOP (result), "a", offset++);
8396   _startLazyDPSEvaluation ();
8397   while (--size)
8398     {
8399       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8400       emitcode ("rlc", "a");
8401       aopPut (AOP (result), "a", offset++);
8402     }
8403   _endLazyDPSEvaluation ();
8404   reAdjustPreg (AOP (result));
8405
8406   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8407   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8408 release:
8409   freeAsmop (left, NULL, ic, TRUE);
8410   freeAsmop (result, NULL, ic, TRUE);
8411 }
8412
8413 #ifdef BETTER_LITERAL_SHIFT
8414 /*-----------------------------------------------------------------*/
8415 /* genrshOne - right shift a one byte quantity by known count      */
8416 /*-----------------------------------------------------------------*/
8417 static void
8418 genrshOne (operand * result, operand * left,
8419            int shCount, int sign)
8420 {
8421   D (emitcode (";", "genrshOne"););
8422   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8423 }
8424 #endif
8425
8426 #ifdef BETTER_LITERAL_SHIFT
8427 /*-----------------------------------------------------------------*/
8428 /* genrshTwo - right shift two bytes by known amount != 0          */
8429 /*-----------------------------------------------------------------*/
8430 static void
8431 genrshTwo (operand * result, operand * left,
8432            int shCount, int sign)
8433 {
8434   D (emitcode (";", "genrshTwo"););
8435
8436   /* if shCount >= 8 */
8437   if (shCount >= 8)
8438     {
8439       shCount -= 8;
8440       _startLazyDPSEvaluation();
8441       if (shCount)
8442       {
8443         shiftR1Left2Result (left, MSB16, result, LSB,
8444                             shCount, sign);
8445       }                     
8446       else
8447       {
8448         movLeft2Result (left, MSB16, result, LSB, sign);
8449       }
8450       addSign (result, MSB16, sign);
8451       _endLazyDPSEvaluation();
8452     }
8453
8454   /*  1 <= shCount <= 7 */
8455   else
8456   {
8457     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8458   }
8459 }
8460 #endif
8461
8462 #if 0
8463 //REMOVE ME!!!
8464 /*-----------------------------------------------------------------*/
8465 /* shiftRLong - shift right one long from left to result           */
8466 /* offl = LSB or MSB16                                             */
8467 /*-----------------------------------------------------------------*/
8468 static void
8469 shiftRLong (operand * left, int offl,
8470             operand * result, int sign)
8471 {
8472   int isSameRegs=sameRegs(AOP(left),AOP(result));
8473
8474   if (isSameRegs && offl>1) {
8475     // we are in big trouble, but this shouldn't happen
8476     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8477   }
8478
8479   MOVA (aopGet (AOP (left), MSB32, FALSE, NULL));
8480   
8481   if (offl==MSB16) {
8482     // shift is > 8
8483     if (sign) {
8484       emitcode ("rlc", "a");
8485       emitcode ("subb", "a,acc");
8486       emitcode ("xch", "a,%s",
8487                 aopGet(AOP(left), MSB32, FALSE, DP2_RESULT_REG));
8488     } else {
8489       aopPut (AOP(result), zero, MSB32);
8490     }
8491   }
8492
8493   if (!sign) {
8494     emitcode ("clr", "c");
8495   } else {
8496     emitcode ("mov", "c,acc.7");
8497   }
8498
8499   emitcode ("rrc", "a");
8500
8501   if (isSameRegs && offl==MSB16) {
8502     emitcode ("xch",
8503               "a,%s",aopGet (AOP (left), MSB24, FALSE, DP2_RESULT_REG));
8504   } else {
8505     aopPut (AOP (result), "a", MSB32);
8506     MOVA (aopGet (AOP (left), MSB24, FALSE, NULL));
8507   }
8508
8509   emitcode ("rrc", "a");
8510   if (isSameRegs && offl==1) {
8511     emitcode ("xch", "a,%s",
8512               aopGet (AOP (left), MSB16, FALSE, DP2_RESULT_REG));
8513   } else {
8514     aopPut (AOP (result), "a", MSB24);
8515     MOVA (aopGet (AOP (left), MSB16, FALSE, NULL));
8516   }
8517   emitcode ("rrc", "a");
8518   aopPut (AOP (result), "a", MSB16 - offl);
8519
8520   if (offl == LSB)
8521     {
8522       MOVA (aopGet (AOP (left), LSB, FALSE, NULL));
8523       emitcode ("rrc", "a");
8524       aopPut (AOP (result), "a", LSB);
8525     }
8526 }
8527 #endif
8528
8529 #if 0
8530 //REMOVE ME!!!
8531 /*-----------------------------------------------------------------*/
8532 /* genrshFour - shift four byte by a known amount != 0             */
8533 /*-----------------------------------------------------------------*/
8534 static void
8535 genrshFour (operand * result, operand * left,
8536             int shCount, int sign)
8537 {
8538   D (emitcode (";", "genrshFour");
8539     );
8540
8541   /* if shifting more that 3 bytes */
8542   if (shCount >= 24)
8543     {
8544       shCount -= 24;
8545       if (shCount)
8546         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8547       else
8548         movLeft2Result (left, MSB32, result, LSB, sign);
8549       addSign (result, MSB16, sign);
8550     }
8551   else if (shCount >= 16)
8552     {
8553       shCount -= 16;
8554       if (shCount)
8555         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8556       else
8557         {
8558           movLeft2Result (left, MSB24, result, LSB, 0);
8559           movLeft2Result (left, MSB32, result, MSB16, sign);
8560         }
8561       addSign (result, MSB24, sign);
8562     }
8563   else if (shCount >= 8)
8564     {
8565       shCount -= 8;
8566       if (shCount == 1)
8567         shiftRLong (left, MSB16, result, sign);
8568       else if (shCount == 0)
8569         {
8570           movLeft2Result (left, MSB16, result, LSB, 0);
8571           movLeft2Result (left, MSB24, result, MSB16, 0);
8572           movLeft2Result (left, MSB32, result, MSB24, sign);
8573           addSign (result, MSB32, sign);
8574         }
8575       else
8576         {
8577           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8578           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8579           /* the last shift is signed */
8580           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8581           addSign (result, MSB32, sign);
8582         }
8583     }
8584   else
8585     {                           /* 1 <= shCount <= 7 */
8586       if (shCount <= 2)
8587         {
8588           shiftRLong (left, LSB, result, sign);
8589           if (shCount == 2)
8590             shiftRLong (result, LSB, result, sign);
8591         }
8592       else
8593         {
8594           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8595           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8596           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8597         }
8598     }
8599 }
8600 #endif
8601
8602 #ifdef BETTER_LITERAL_SHIFT
8603 /*-----------------------------------------------------------------*/
8604 /* genRightShiftLiteral - right shifting by known count            */
8605 /*-----------------------------------------------------------------*/
8606 static bool
8607 genRightShiftLiteral (operand * left,
8608                       operand * right,
8609                       operand * result,
8610                       iCode * ic,
8611                       int sign)
8612 {
8613   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8614   int size;
8615
8616   size = getSize (operandType (result));
8617
8618   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8619
8620   /* We only handle certain easy cases so far. */
8621   if ((shCount != 0)
8622    && (shCount < (size * 8))
8623    && (size != 1)
8624    && (size != 2))
8625   {
8626       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8627       return FALSE;
8628   }
8629
8630   freeAsmop (right, NULL, ic, TRUE);
8631
8632   aopOp (left, ic, FALSE, FALSE);
8633   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8634
8635 #if VIEW_SIZE
8636   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8637             AOP_SIZE (left));
8638 #endif
8639
8640   /* test the LEFT size !!! */
8641
8642   /* I suppose that the left size >= result size */
8643   if (shCount == 0)
8644   {
8645       size = getDataSize (result);
8646       _startLazyDPSEvaluation();
8647       while (size--)
8648       {
8649         movLeft2Result (left, size, result, size, 0);
8650       }
8651       _endLazyDPSEvaluation();
8652   }
8653   else if (shCount >= (size * 8))
8654     {
8655       if (sign)
8656       {
8657         /* get sign in acc.7 */
8658         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8659       }
8660       addSign (result, LSB, sign);
8661     }
8662   else
8663     {
8664       switch (size)
8665         {
8666         case 1:
8667           genrshOne (result, left, shCount, sign);
8668           break;
8669
8670         case 2:
8671           genrshTwo (result, left, shCount, sign);
8672           break;
8673 #if 0
8674         case 4:
8675           genrshFour (result, left, shCount, sign);
8676           break;
8677 #endif    
8678         default:
8679           break;
8680         }
8681     }
8682   freeAsmop (left, NULL, ic, TRUE);
8683   freeAsmop (result, NULL, ic, TRUE);
8684   
8685   return TRUE;
8686 }
8687 #endif
8688
8689 /*-----------------------------------------------------------------*/
8690 /* genSignedRightShift - right shift of signed number              */
8691 /*-----------------------------------------------------------------*/
8692 static void
8693 genSignedRightShift (iCode * ic)
8694 {
8695   operand *right, *left, *result;
8696   int size, offset;
8697   char *l;
8698   symbol *tlbl, *tlbl1;
8699
8700   D (emitcode (";", "genSignedRightShift "););
8701
8702   /* we do it the hard way put the shift count in b
8703      and loop thru preserving the sign */
8704
8705   right = IC_RIGHT (ic);
8706   left = IC_LEFT (ic);
8707   result = IC_RESULT (ic);
8708
8709   aopOp (right, ic, FALSE, FALSE);
8710
8711 #ifdef BETTER_LITERAL_SHIFT
8712   if (AOP_TYPE (right) == AOP_LIT)
8713     {
8714       if (genRightShiftLiteral (left, right, result, ic, 1))
8715       {
8716         return;
8717       }
8718     }
8719 #endif
8720   /* shift count is unknown then we have to form
8721      a loop get the loop count in B : Note: we take
8722      only the lower order byte since shifting
8723      more that 32 bits make no sense anyway, ( the
8724      largest size of an object can be only 32 bits ) */
8725
8726   if (AOP_TYPE (right) == AOP_LIT)
8727   {
8728       /* Really should be handled by genRightShiftLiteral,
8729        * but since I'm too lazy to fix that today, at least we can make
8730        * some small improvement.
8731        */
8732        emitcode("mov", "b,#!constbyte",
8733                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8734   }
8735   else
8736   {
8737         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8738         emitcode ("inc", "b");
8739   }
8740   freeAsmop (right, NULL, ic, TRUE);
8741   aopOp (left, ic, FALSE, FALSE);
8742   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
8743
8744   /* now move the left to the result if they are not the
8745      same */
8746   if (!sameRegs (AOP (left), AOP (result)) &&
8747       AOP_SIZE (result) > 1)
8748     {
8749
8750       size = AOP_SIZE (result);
8751       offset = 0;
8752       _startLazyDPSEvaluation ();
8753       while (size--)
8754         {
8755           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8756           if (*l == '@' && IS_AOP_PREG (result))
8757             {
8758
8759               emitcode ("mov", "a,%s", l);
8760               aopPut (AOP (result), "a", offset);
8761             }
8762           else
8763             aopPut (AOP (result), l, offset);
8764           offset++;
8765         }
8766       _endLazyDPSEvaluation ();
8767     }
8768
8769   /* mov the highest order bit to OVR */
8770   tlbl = newiTempLabel (NULL);
8771   tlbl1 = newiTempLabel (NULL);
8772
8773   size = AOP_SIZE (result);
8774   offset = size - 1;
8775   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8776   emitcode ("rlc", "a");
8777   emitcode ("mov", "ov,c");
8778   /* if it is only one byte then */
8779   if (size == 1)
8780     {
8781       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8782       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8783       emitcode ("", "!tlabeldef", tlbl->key + 100);
8784       emitcode ("mov", "c,ov");
8785       emitcode ("rrc", "a");
8786       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8787       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8788       aopPut (AOP (result), "a", 0);
8789       goto release;
8790     }
8791
8792   reAdjustPreg (AOP (result));
8793   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8794   emitcode ("", "!tlabeldef", tlbl->key + 100);
8795   emitcode ("mov", "c,ov");
8796   _startLazyDPSEvaluation ();
8797   while (size--)
8798     {
8799       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8800       emitcode ("rrc", "a");
8801       aopPut (AOP (result), "a", offset--);
8802     }
8803   _endLazyDPSEvaluation ();
8804   reAdjustPreg (AOP (result));
8805   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8806   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8807
8808 release:
8809   freeAsmop (left, NULL, ic, TRUE);
8810   freeAsmop (result, NULL, ic, TRUE);
8811 }
8812
8813 /*-----------------------------------------------------------------*/
8814 /* genRightShift - generate code for right shifting                */
8815 /*-----------------------------------------------------------------*/
8816 static void
8817 genRightShift (iCode * ic)
8818 {
8819   operand *right, *left, *result;
8820   sym_link *retype;
8821   int size, offset;
8822   char *l;
8823   symbol *tlbl, *tlbl1;
8824
8825   D (emitcode (";", "genRightShift "););
8826
8827   /* if signed then we do it the hard way preserve the
8828      sign bit moving it inwards */
8829   retype = getSpec (operandType (IC_RESULT (ic)));
8830
8831   if (!SPEC_USIGN (retype))
8832     {
8833       genSignedRightShift (ic);
8834       return;
8835     }
8836
8837   /* signed & unsigned types are treated the same : i.e. the
8838      signed is NOT propagated inwards : quoting from the
8839      ANSI - standard : "for E1 >> E2, is equivalent to division
8840      by 2**E2 if unsigned or if it has a non-negative value,
8841      otherwise the result is implementation defined ", MY definition
8842      is that the sign does not get propagated */
8843
8844   right = IC_RIGHT (ic);
8845   left = IC_LEFT (ic);
8846   result = IC_RESULT (ic);
8847
8848   aopOp (right, ic, FALSE, FALSE);
8849
8850 #ifdef BETTER_LITERAL_SHIFT
8851   /* if the shift count is known then do it
8852      as efficiently as possible */
8853   if (AOP_TYPE (right) == AOP_LIT)
8854     {
8855       if (genRightShiftLiteral (left, right, result, ic, 0))
8856       {
8857         return;
8858       }
8859     }
8860 #endif
8861
8862   /* shift count is unknown then we have to form
8863      a loop get the loop count in B : Note: we take
8864      only the lower order byte since shifting
8865      more that 32 bits make no sense anyway, ( the
8866      largest size of an object can be only 32 bits ) */
8867   
8868   if (AOP_TYPE (right) == AOP_LIT)
8869   {
8870       /* Really should be handled by genRightShiftLiteral,
8871        * but since I'm too lazy to fix that today, at least we can make
8872        * some small improvement.
8873        */
8874        emitcode("mov", "b,#!constbyte",
8875                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8876   }
8877   else
8878   {
8879       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8880       emitcode ("inc", "b");
8881   }
8882   freeAsmop (right, NULL, ic, TRUE);
8883   aopOp (left, ic, FALSE, FALSE);
8884   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8885
8886   /* now move the left to the result if they are not the
8887      same */
8888   if (!sameRegs (AOP (left), AOP (result)) &&
8889       AOP_SIZE (result) > 1)
8890     {
8891
8892       size = AOP_SIZE (result);
8893       offset = 0;
8894       _startLazyDPSEvaluation ();
8895       while (size--)
8896         {
8897           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8898           if (*l == '@' && IS_AOP_PREG (result))
8899             {
8900
8901               emitcode ("mov", "a,%s", l);
8902               aopPut (AOP (result), "a", offset);
8903             }
8904           else
8905             aopPut (AOP (result), l, offset);
8906           offset++;
8907         }
8908       _endLazyDPSEvaluation ();
8909     }
8910
8911   tlbl = newiTempLabel (NULL);
8912   tlbl1 = newiTempLabel (NULL);
8913   size = AOP_SIZE (result);
8914   offset = size - 1;
8915
8916   /* if it is only one byte then */
8917   if (size == 1)
8918     {
8919       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8920       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8921       emitcode ("", "!tlabeldef", tlbl->key + 100);
8922       CLRC;
8923       emitcode ("rrc", "a");
8924       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8925       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8926       aopPut (AOP (result), "a", 0);
8927       goto release;
8928     }
8929
8930   reAdjustPreg (AOP (result));
8931   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8932   emitcode ("", "!tlabeldef", tlbl->key + 100);
8933   CLRC;
8934   _startLazyDPSEvaluation ();
8935   while (size--)
8936     {
8937       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8938       emitcode ("rrc", "a");
8939       aopPut (AOP (result), "a", offset--);
8940     }
8941   _endLazyDPSEvaluation ();
8942   reAdjustPreg (AOP (result));
8943
8944   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8945   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8946
8947 release:
8948   freeAsmop (left, NULL, ic, TRUE);
8949   freeAsmop (result, NULL, ic, TRUE);
8950 }
8951
8952 /*-----------------------------------------------------------------*/
8953 /* genUnpackBits - generates code for unpacking bits               */
8954 /*-----------------------------------------------------------------*/
8955 static void
8956 genUnpackBits (operand * result, char *rname, int ptype)
8957 {
8958   int shCnt;
8959   int rlen;
8960   sym_link *etype;
8961   int offset = 0;
8962
8963   D (emitcode (";", "genUnpackBits "););
8964
8965   etype = getSpec (operandType (result));
8966
8967   /* read the first byte  */
8968   switch (ptype)
8969     {
8970
8971     case POINTER:
8972     case IPOINTER:
8973       emitcode ("mov", "a,@%s", rname);
8974       break;
8975
8976     case PPOINTER:
8977       emitcode ("movx", "a,@%s", rname);
8978       break;
8979
8980     case FPOINTER:
8981       emitcode ("movx", "a,@dptr");
8982       break;
8983
8984     case CPOINTER:
8985       emitcode ("clr", "a");
8986       emitcode ("movc", "a,@a+dptr");
8987       break;
8988
8989     case GPOINTER:
8990       emitcode ("lcall", "__gptrget");
8991       break;
8992     }
8993
8994   /* if we have bitdisplacement then it fits   */
8995   /* into this byte completely or if length is */
8996   /* less than a byte                          */
8997   if (((shCnt = SPEC_BSTR (etype)) != 0) || (SPEC_BLEN (etype) <= 8))
8998     {
8999
9000       /* shift right acc */
9001       AccRsh (shCnt);
9002
9003       emitcode ("anl", "a,#!constbyte",
9004                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
9005       aopPut (AOP (result), "a", offset);
9006       return;
9007     }
9008
9009   /* bit field did not fit in a byte  */
9010   rlen = SPEC_BLEN (etype) - 8;
9011   aopPut (AOP (result), "a", offset++);
9012
9013   while (1)
9014     {
9015
9016       switch (ptype)
9017         {
9018         case POINTER:
9019         case IPOINTER:
9020           emitcode ("inc", "%s", rname);
9021           emitcode ("mov", "a,@%s", rname);
9022           break;
9023
9024         case PPOINTER:
9025           emitcode ("inc", "%s", rname);
9026           emitcode ("movx", "a,@%s", rname);
9027           break;
9028
9029         case FPOINTER:
9030           emitcode ("inc", "dptr");
9031           emitcode ("movx", "a,@dptr");
9032           break;
9033
9034         case CPOINTER:
9035           emitcode ("clr", "a");
9036           emitcode ("inc", "dptr");
9037           emitcode ("movc", "a,@a+dptr");
9038           break;
9039
9040         case GPOINTER:
9041           emitcode ("inc", "dptr");
9042           emitcode ("lcall", "__gptrget");
9043           break;
9044         }
9045
9046       rlen -= 8;
9047       /* if we are done */
9048       if (rlen < 8)
9049         break;
9050
9051       aopPut (AOP (result), "a", offset++);
9052
9053     }
9054
9055   if (rlen)
9056     {
9057       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
9058       aopPut (AOP (result), "a", offset);
9059     }
9060
9061   return;
9062 }
9063
9064
9065 /*-----------------------------------------------------------------*/
9066 /* genDataPointerGet - generates code when ptr offset is known     */
9067 /*-----------------------------------------------------------------*/
9068 static void
9069 genDataPointerGet (operand * left,
9070                    operand * result,
9071                    iCode * ic)
9072 {
9073   char *l;
9074   char buff[256];
9075   int size, offset = 0;
9076   aopOp (result, ic, TRUE, FALSE);
9077
9078   /* get the string representation of the name */
9079   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9080   size = AOP_SIZE (result);
9081   _startLazyDPSEvaluation ();
9082   while (size--)
9083     {
9084         if (offset)
9085         {
9086             SNPRINTF (buff, sizeof(buff), 
9087                       "(%s + %d)", l + 1, offset);
9088         }
9089         else
9090         {
9091             SNPRINTF (buff, sizeof(buff), 
9092                       "%s", l + 1);
9093         }
9094       aopPut (AOP (result), buff, offset++);
9095     }
9096   _endLazyDPSEvaluation ();
9097
9098   freeAsmop (left, NULL, ic, TRUE);
9099   freeAsmop (result, NULL, ic, TRUE);
9100 }
9101
9102 /*-----------------------------------------------------------------*/
9103 /* genNearPointerGet - emitcode for near pointer fetch             */
9104 /*-----------------------------------------------------------------*/
9105 static void
9106 genNearPointerGet (operand * left,
9107                    operand * result,
9108                    iCode * ic,
9109                    iCode *pi)
9110 {
9111   asmop *aop = NULL;
9112   regs *preg;
9113   char *rname;
9114   sym_link *rtype, *retype, *letype;
9115   sym_link *ltype = operandType (left);
9116   char buff[80];
9117
9118   rtype = operandType (result);
9119   retype = getSpec (rtype);
9120   letype = getSpec (ltype);
9121
9122   aopOp (left, ic, FALSE, FALSE);
9123
9124   /* if left is rematerialisable and
9125      result is not bit variable type and
9126      the left is pointer to data space i.e
9127      lower 128 bytes of space */
9128   if (AOP_TYPE (left) == AOP_IMMD &&
9129       !IS_BITVAR (retype) &&
9130       !IS_BITVAR (letype) &&
9131       DCL_TYPE (ltype) == POINTER)
9132     {
9133       genDataPointerGet (left, result, ic);
9134       return;
9135     }
9136
9137   /* if the value is already in a pointer register
9138      then don't need anything more */
9139   if (!AOP_INPREG (AOP (left)))
9140     {
9141       /* otherwise get a free pointer register */
9142       aop = newAsmop (0);
9143       preg = getFreePtr (ic, &aop, FALSE);
9144       emitcode ("mov", "%s,%s",
9145                 preg->name,
9146                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9147       rname = preg->name;
9148     }
9149   else
9150     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9151
9152   freeAsmop (left, NULL, ic, TRUE);
9153   aopOp (result, ic, FALSE, FALSE);
9154
9155   /* if bitfield then unpack the bits */
9156   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9157     genUnpackBits (result, rname, POINTER);
9158   else
9159     {
9160       /* we have can just get the values */
9161       int size = AOP_SIZE (result);
9162       int offset = 0;
9163
9164       while (size--)
9165         {
9166           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9167             {
9168
9169               emitcode ("mov", "a,@%s", rname);
9170               aopPut (AOP (result), "a", offset);
9171             }
9172           else
9173             {
9174               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9175               aopPut (AOP (result), buff, offset);
9176             }
9177           offset++;
9178           if (size || pi)
9179             {
9180                 emitcode ("inc", "%s", rname);
9181             }
9182         }
9183     }
9184
9185   /* now some housekeeping stuff */
9186   if (aop)
9187     {
9188       /* we had to allocate for this iCode */
9189       if (pi) { /* post increment present */
9190         aopPut(AOP ( left ),rname,0);
9191       }
9192       freeAsmop (NULL, aop, ic, TRUE);
9193     }
9194   else
9195     {
9196       /* we did not allocate which means left
9197          already in a pointer register, then
9198          if size > 0 && this could be used again
9199          we have to point it back to where it
9200          belongs */
9201       if (AOP_SIZE (result) > 1 &&
9202           !OP_SYMBOL (left)->remat &&
9203           (OP_SYMBOL (left)->liveTo > ic->seq ||
9204            ic->depth) &&
9205           !pi)
9206         {
9207           int size = AOP_SIZE (result) - 1;
9208           while (size--)
9209             emitcode ("dec", "%s", rname);
9210         }
9211     }
9212
9213   /* done */
9214   freeAsmop (result, NULL, ic, TRUE);
9215   if (pi) pi->generated = 1;
9216 }
9217
9218 /*-----------------------------------------------------------------*/
9219 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9220 /*-----------------------------------------------------------------*/
9221 static void
9222 genPagedPointerGet (operand * left,
9223                     operand * result,
9224                     iCode * ic,
9225                     iCode * pi)
9226 {
9227   asmop *aop = NULL;
9228   regs *preg;
9229   char *rname;
9230   sym_link *rtype, *retype, *letype;
9231
9232   rtype = operandType (result);
9233   retype = getSpec (rtype);
9234   letype = getSpec (operandType (left));
9235   aopOp (left, ic, FALSE, FALSE);
9236
9237   /* if the value is already in a pointer register
9238      then don't need anything more */
9239   if (!AOP_INPREG (AOP (left)))
9240     {
9241       /* otherwise get a free pointer register */
9242       aop = newAsmop (0);
9243       preg = getFreePtr (ic, &aop, FALSE);
9244       emitcode ("mov", "%s,%s",
9245                 preg->name,
9246                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9247       rname = preg->name;
9248     }
9249   else
9250     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9251
9252   freeAsmop (left, NULL, ic, TRUE);
9253   aopOp (result, ic, FALSE, FALSE);
9254
9255   /* if bitfield then unpack the bits */
9256   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9257     genUnpackBits (result, rname, PPOINTER);
9258   else
9259     {
9260       /* we have can just get the values */
9261       int size = AOP_SIZE (result);
9262       int offset = 0;
9263
9264       while (size--)
9265         {
9266
9267           emitcode ("movx", "a,@%s", rname);
9268           aopPut (AOP (result), "a", offset);
9269
9270           offset++;
9271
9272           if (size || pi)
9273             emitcode ("inc", "%s", rname);
9274         }
9275     }
9276
9277   /* now some housekeeping stuff */
9278   if (aop)
9279     {
9280       /* we had to allocate for this iCode */
9281       if (pi) aopPut ( AOP (left), rname, 0);
9282       freeAsmop (NULL, aop, ic, TRUE);
9283     }
9284   else
9285     {
9286       /* we did not allocate which means left
9287          already in a pointer register, then
9288          if size > 0 && this could be used again
9289          we have to point it back to where it
9290          belongs */
9291       if (AOP_SIZE (result) > 1 &&
9292           !OP_SYMBOL (left)->remat &&
9293           (OP_SYMBOL (left)->liveTo > ic->seq ||
9294            ic->depth) &&
9295           !pi)
9296         {
9297           int size = AOP_SIZE (result) - 1;
9298           while (size--)
9299             emitcode ("dec", "%s", rname);
9300         }
9301     }
9302
9303   /* done */
9304   freeAsmop (result, NULL, ic, TRUE);
9305   if (pi) pi->generated = 1;
9306 }
9307
9308 /*-----------------------------------------------------------------*/
9309 /* genFarPointerGet - gget value from far space                    */
9310 /*-----------------------------------------------------------------*/
9311 static void
9312 genFarPointerGet (operand * left,
9313                   operand * result, iCode * ic, iCode *pi)
9314 {
9315     int size, offset, dopi=1;
9316   sym_link *retype = getSpec (operandType (result));
9317   sym_link *letype = getSpec (operandType (left));
9318   D (emitcode (";", "genFarPointerGet"););
9319
9320   aopOp (left, ic, FALSE, FALSE);
9321
9322   /* if the operand is already in dptr
9323      then we do nothing else we move the value to dptr */
9324   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9325     {
9326       /* if this is remateriazable */
9327       if (AOP_TYPE (left) == AOP_IMMD)
9328         {
9329           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9330         }
9331       else
9332         {
9333           /* we need to get it byte by byte */
9334           _startLazyDPSEvaluation ();
9335           if (AOP_TYPE (left) != AOP_DPTR)
9336             {
9337               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9338               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9339               if (options.model == MODEL_FLAT24)
9340                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9341             }
9342           else
9343             {
9344               /* We need to generate a load to DPTR indirect through DPTR. */
9345               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9346               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9347               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9348               if (options.model == MODEL_FLAT24)
9349                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9350               emitcode ("pop", "dph");
9351               emitcode ("pop", "dpl");
9352               dopi =0;
9353             }
9354           _endLazyDPSEvaluation ();
9355         }
9356     }
9357   /* so dptr know contains the address */
9358   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9359
9360   /* if bit then unpack */
9361   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9362       if (AOP_INDPTRn(left)) {
9363           genSetDPTR(AOP(left)->aopu.dptr);
9364       }
9365       genUnpackBits (result, "dptr", FPOINTER);
9366       if (AOP_INDPTRn(left)) {
9367           genSetDPTR(0);
9368       }
9369   } else
9370     {
9371       size = AOP_SIZE (result);
9372       offset = 0;
9373
9374       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9375           while (size--) {
9376               genSetDPTR(AOP(left)->aopu.dptr);
9377               emitcode ("movx", "a,@dptr");
9378               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9379                   emitcode ("inc", "dptr");
9380               genSetDPTR (0);
9381               aopPut (AOP (result), "a", offset++);
9382           }
9383       } else {
9384           _startLazyDPSEvaluation ();
9385           while (size--) {
9386               if (AOP_INDPTRn(left)) {
9387                   genSetDPTR(AOP(left)->aopu.dptr);
9388               } else {
9389                   genSetDPTR (0);
9390               }
9391               _flushLazyDPS ();
9392               
9393               emitcode ("movx", "a,@dptr");
9394               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9395                   emitcode ("inc", "dptr");
9396               
9397               aopPut (AOP (result), "a", offset++);
9398           }
9399           _endLazyDPSEvaluation ();
9400       }
9401     }
9402   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9403       if (!AOP_INDPTRn(left)) {
9404           _startLazyDPSEvaluation ();
9405           aopPut ( AOP (left), "dpl", 0);
9406           aopPut ( AOP (left), "dph", 1);
9407           if (options.model == MODEL_FLAT24)
9408               aopPut ( AOP (left), "dpx", 2);
9409           _endLazyDPSEvaluation ();
9410       }
9411     pi->generated = 1;
9412   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) && 
9413              AOP_SIZE(result) > 1 &&
9414              IS_SYMOP(left) &&
9415              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9416       
9417       size = AOP_SIZE (result) - 1;
9418       if (AOP_INDPTRn(left)) {
9419           genSetDPTR(AOP(left)->aopu.dptr);
9420       }
9421       while (size--) emitcode ("lcall","__decdptr");
9422       if (AOP_INDPTRn(left)) {
9423           genSetDPTR(0);
9424       }
9425   }
9426
9427   freeAsmop (left, NULL, ic, TRUE);
9428   freeAsmop (result, NULL, ic, TRUE);
9429 }
9430
9431 /*-----------------------------------------------------------------*/
9432 /* genCodePointerGet - get value from code space                  */
9433 /*-----------------------------------------------------------------*/
9434 static void
9435 genCodePointerGet (operand * left,
9436                     operand * result, iCode * ic, iCode *pi)
9437 {
9438   int size, offset, dopi=1;
9439   sym_link *retype = getSpec (operandType (result));
9440
9441   aopOp (left, ic, FALSE, FALSE);
9442
9443   /* if the operand is already in dptr
9444      then we do nothing else we move the value to dptr */
9445   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9446     {
9447       /* if this is remateriazable */
9448       if (AOP_TYPE (left) == AOP_IMMD)
9449         {
9450           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9451         }
9452       else
9453         {                       /* we need to get it byte by byte */
9454           _startLazyDPSEvaluation ();
9455           if (AOP_TYPE (left) != AOP_DPTR)
9456             {
9457               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9458               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9459               if (options.model == MODEL_FLAT24)
9460                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9461             }
9462           else
9463             {
9464               /* We need to generate a load to DPTR indirect through DPTR. */
9465               D (emitcode (";", "gencodePointerGet -- indirection special case."););
9466               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9467               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9468               if (options.model == MODEL_FLAT24)
9469                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9470               emitcode ("pop", "dph");
9471               emitcode ("pop", "dpl");
9472               dopi=0;
9473             }
9474           _endLazyDPSEvaluation ();
9475         }
9476     }
9477   /* so dptr know contains the address */
9478   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9479
9480   /* if bit then unpack */
9481   if (IS_BITVAR (retype)) {
9482       if (AOP_INDPTRn(left)) {
9483           genSetDPTR(AOP(left)->aopu.dptr);
9484       }
9485       genUnpackBits (result, "dptr", CPOINTER);
9486       if (AOP_INDPTRn(left)) {
9487           genSetDPTR(0);
9488       }
9489   } else
9490     {
9491       size = AOP_SIZE (result);
9492       offset = 0;
9493       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9494           while (size--) {
9495               genSetDPTR(AOP(left)->aopu.dptr);
9496               emitcode ("clr", "a");
9497               emitcode ("movc", "a,@a+dptr");
9498               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9499                   emitcode ("inc", "dptr");
9500               genSetDPTR (0);
9501               aopPut (AOP (result), "a", offset++);
9502           }
9503       } else {
9504           _startLazyDPSEvaluation ();
9505           while (size--)
9506               {
9507                   if (AOP_INDPTRn(left)) {
9508                       genSetDPTR(AOP(left)->aopu.dptr);
9509                   } else {
9510                       genSetDPTR (0);
9511                   }
9512                   _flushLazyDPS ();
9513                   
9514                   emitcode ("clr", "a");
9515                   emitcode ("movc", "a,@a+dptr");
9516                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9517                       emitcode ("inc", "dptr");
9518                   aopPut (AOP (result), "a", offset++);
9519               }
9520           _endLazyDPSEvaluation ();
9521       }
9522     }
9523   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9524       if (!AOP_INDPTRn(left)) {
9525           _startLazyDPSEvaluation ();
9526           
9527           aopPut ( AOP (left), "dpl", 0);
9528           aopPut ( AOP (left), "dph", 1);
9529           if (options.model == MODEL_FLAT24)
9530               aopPut ( AOP (left), "dpx", 2);
9531
9532           _endLazyDPSEvaluation ();
9533       }
9534       pi->generated = 1;
9535   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9536              AOP_SIZE(result) > 1 &&
9537              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9538       
9539       size = AOP_SIZE (result) - 1;
9540       if (AOP_INDPTRn(left)) {
9541           genSetDPTR(AOP(left)->aopu.dptr);
9542       }
9543       while (size--) emitcode ("lcall","__decdptr");
9544       if (AOP_INDPTRn(left)) {
9545           genSetDPTR(0);
9546       }
9547   }
9548   
9549   freeAsmop (left, NULL, ic, TRUE);
9550   freeAsmop (result, NULL, ic, TRUE);
9551 }
9552
9553 /*-----------------------------------------------------------------*/
9554 /* genGenPointerGet - gget value from generic pointer space        */
9555 /*-----------------------------------------------------------------*/
9556 static void
9557 genGenPointerGet (operand * left,
9558                   operand * result, iCode * ic, iCode * pi)
9559 {
9560   int size, offset;
9561   sym_link *retype = getSpec (operandType (result));
9562   sym_link *letype = getSpec (operandType (left));
9563
9564   D (emitcode (";", "genGenPointerGet "); );
9565
9566   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9567
9568   /* if the operand is already in dptr
9569      then we do nothing else we move the value to dptr */
9570   if (AOP_TYPE (left) != AOP_STR)
9571     {
9572       /* if this is remateriazable */
9573       if (AOP_TYPE (left) == AOP_IMMD)
9574         {
9575           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9576           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9577             {
9578                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9579             }
9580             else
9581             {
9582                 emitcode ("mov", "b,#%d", pointerCode (retype));
9583             }
9584         }
9585       else
9586         {                       /* we need to get it byte by byte */
9587             _startLazyDPSEvaluation ();
9588             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9589             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9590             if (options.model == MODEL_FLAT24) {
9591                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9592                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9593             } else {
9594                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9595             }
9596             _endLazyDPSEvaluation ();
9597         }
9598     }
9599
9600   /* so dptr-b now contains the address */
9601   _G.bInUse++;
9602   aopOp (result, ic, FALSE, TRUE);
9603   _G.bInUse--;
9604
9605   /* if bit then unpack */
9606   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9607   {
9608     genUnpackBits (result, "dptr", GPOINTER);
9609   }
9610   else
9611     {
9612         size = AOP_SIZE (result);
9613         offset = 0;
9614
9615         while (size--)
9616         {
9617             if (size)
9618             {
9619                 // Get two bytes at a time, results in _AP & A.
9620                 // dptr will be incremented ONCE by __gptrgetWord.
9621                 //
9622                 // Note: any change here must be coordinated
9623                 // with the implementation of __gptrgetWord
9624                 // in device/lib/_gptrget.c
9625                 emitcode ("lcall", "__gptrgetWord");
9626                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9627                 aopPut (AOP (result), "a", offset++);
9628                 size--;
9629             }
9630             else
9631             {
9632                 // Only one byte to get.
9633                 emitcode ("lcall", "__gptrget");
9634                 aopPut (AOP (result), "a", offset++);
9635             }
9636             
9637             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9638             {
9639                 emitcode ("inc", "dptr");
9640             }
9641         }
9642     }
9643
9644   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9645     _startLazyDPSEvaluation ();
9646       
9647     aopPut ( AOP (left), "dpl", 0);
9648     aopPut ( AOP (left), "dph", 1);
9649     if (options.model == MODEL_FLAT24) {
9650         aopPut ( AOP (left), "dpx", 2);
9651         aopPut ( AOP (left), "b", 3);   
9652     } else  aopPut ( AOP (left), "b", 2);       
9653     
9654     _endLazyDPSEvaluation ();
9655       
9656     pi->generated = 1;
9657   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9658              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9659       
9660       size = AOP_SIZE (result) - 1;
9661       while (size--) emitcode ("lcall","__decdptr");
9662   }
9663
9664   freeAsmop (left, NULL, ic, TRUE);
9665   freeAsmop (result, NULL, ic, TRUE);
9666 }
9667
9668 /*-----------------------------------------------------------------*/
9669 /* genPointerGet - generate code for pointer get                   */
9670 /*-----------------------------------------------------------------*/
9671 static void
9672 genPointerGet (iCode * ic, iCode *pi)
9673 {
9674   operand *left, *result;
9675   sym_link *type, *etype;
9676   int p_type;
9677
9678   D (emitcode (";", "genPointerGet ");
9679     );
9680
9681   left = IC_LEFT (ic);
9682   result = IC_RESULT (ic);
9683
9684   /* depending on the type of pointer we need to
9685      move it to the correct pointer register */
9686   type = operandType (left);
9687   etype = getSpec (type);
9688   /* if left is of type of pointer then it is simple */
9689   if (IS_PTR (type) && !IS_FUNC (type->next))
9690     p_type = DCL_TYPE (type);
9691   else
9692     {
9693       /* we have to go by the storage class */
9694       p_type = PTR_TYPE (SPEC_OCLS (etype));
9695     }
9696   /* special case when cast remat */
9697   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9698       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9699           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9700           type = operandType (left);
9701           p_type = DCL_TYPE (type);
9702   }
9703   /* now that we have the pointer type we assign
9704      the pointer values */
9705   switch (p_type)
9706     {
9707
9708     case POINTER:
9709     case IPOINTER:
9710       genNearPointerGet (left, result, ic, pi);
9711       break;
9712
9713     case PPOINTER:
9714       genPagedPointerGet (left, result, ic, pi);
9715       break;
9716
9717     case FPOINTER:
9718       genFarPointerGet (left, result, ic, pi);
9719       break;
9720
9721     case CPOINTER:
9722       genCodePointerGet (left, result, ic, pi);
9723       break;
9724
9725     case GPOINTER:
9726       genGenPointerGet (left, result, ic, pi);
9727       break;
9728     }
9729
9730 }
9731
9732 /*-----------------------------------------------------------------*/
9733 /* genPackBits - generates code for packed bit storage             */
9734 /*-----------------------------------------------------------------*/
9735 static void
9736 genPackBits (sym_link * etype,
9737              operand * right,
9738              char *rname, int p_type)
9739 {
9740   int offset = 0;
9741   int rLen;
9742   int blen, bstr;
9743   char *l;
9744
9745   blen = SPEC_BLEN (etype);
9746   bstr = SPEC_BSTR (etype);
9747
9748   MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9749
9750   /* if the bit lenth is less than or    */
9751   /* it exactly fits a byte then         */
9752   if (SPEC_BLEN (etype) <= 8)
9753     {
9754       /* shift left acc */
9755       AccLsh (SPEC_BSTR (etype));
9756
9757       if (SPEC_BLEN (etype) < 8)
9758         {                       /* if smaller than a byte */
9759
9760
9761           switch (p_type)
9762             {
9763             case POINTER:
9764               emitcode ("mov", "b,a");
9765               emitcode ("mov", "a,@%s", rname);
9766               break;
9767
9768             case FPOINTER:
9769               emitcode ("mov", "b,a");
9770               emitcode ("movx", "a,@dptr");
9771               break;
9772
9773             case GPOINTER:
9774               emitcode ("push", "b");
9775               emitcode ("push", "acc");
9776               emitcode ("lcall", "__gptrget");
9777               emitcode ("pop", "b");
9778               break;
9779             }
9780
9781           emitcode ("anl", "a,#!constbyte", (unsigned char)
9782                     ((unsigned char) (0xFF << (blen + bstr)) |
9783                      (unsigned char) (0xFF >> (8 - bstr))));
9784           emitcode ("orl", "a,b");
9785           if (p_type == GPOINTER)
9786             emitcode ("pop", "b");
9787         }
9788     }
9789
9790   switch (p_type)
9791     {
9792     case POINTER:
9793       emitcode ("mov", "@%s,a", rname);
9794       break;
9795
9796     case FPOINTER:
9797       emitcode ("movx", "@dptr,a");
9798       break;
9799
9800     case GPOINTER:
9801       emitcode ("lcall", "__gptrput");
9802       break;
9803     }
9804
9805   /* if we r done */
9806   if (SPEC_BLEN (etype) <= 8)
9807     return;
9808
9809   emitcode ("inc", "%s", rname);
9810   rLen = SPEC_BLEN (etype);
9811
9812   /* now generate for lengths greater than one byte */
9813   while (1)
9814     {
9815
9816       l = aopGet (AOP (right), offset++, FALSE, TRUE, NULL);
9817
9818       rLen -= 8;
9819       if (rLen < 8)
9820         break;
9821
9822       switch (p_type)
9823         {
9824         case POINTER:
9825           if (*l == '@')
9826             {
9827               MOVA (l);
9828               emitcode ("mov", "@%s,a", rname);
9829             }
9830           else
9831             emitcode ("mov", "@%s,%s", rname, l);
9832           break;
9833
9834         case FPOINTER:
9835           MOVA (l);
9836           emitcode ("movx", "@dptr,a");
9837           break;
9838
9839         case GPOINTER:
9840           MOVA (l);
9841           emitcode ("lcall", "__gptrput");
9842           break;
9843         }
9844       emitcode ("inc", "%s", rname);
9845     }
9846
9847   MOVA (l);
9848
9849   /* last last was not complete */
9850   if (rLen)
9851     {
9852       /* save the byte & read byte */
9853       switch (p_type)
9854         {
9855         case POINTER:
9856           emitcode ("mov", "b,a");
9857           emitcode ("mov", "a,@%s", rname);
9858           break;
9859
9860         case FPOINTER:
9861           emitcode ("mov", "b,a");
9862           emitcode ("movx", "a,@dptr");
9863           break;
9864
9865         case GPOINTER:
9866           emitcode ("push", "b");
9867           emitcode ("push", "acc");
9868           emitcode ("lcall", "__gptrget");
9869           emitcode ("pop", "b");
9870           break;
9871         }
9872
9873       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9874       emitcode ("orl", "a,b");
9875     }
9876
9877   if (p_type == GPOINTER)
9878     emitcode ("pop", "b");
9879
9880   switch (p_type)
9881     {
9882
9883     case POINTER:
9884       emitcode ("mov", "@%s,a", rname);
9885       break;
9886
9887     case FPOINTER:
9888       emitcode ("movx", "@dptr,a");
9889       break;
9890
9891     case GPOINTER:
9892       emitcode ("lcall", "__gptrput");
9893       break;
9894     }
9895 }
9896 /*-----------------------------------------------------------------*/
9897 /* genDataPointerSet - remat pointer to data space                 */
9898 /*-----------------------------------------------------------------*/
9899 static void
9900 genDataPointerSet (operand * right,
9901                    operand * result,
9902                    iCode * ic)
9903 {
9904   int size, offset = 0;
9905   char *l, buff[256];
9906
9907   aopOp (right, ic, FALSE, FALSE);
9908
9909   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9910   size = AOP_SIZE (right);
9911   while (size--)
9912     {
9913       if (offset)
9914         {
9915             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9916         }
9917       else
9918         {
9919             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9920         }
9921         
9922       emitcode ("mov", "%s,%s", buff,
9923                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9924     }
9925
9926   freeAsmop (right, NULL, ic, TRUE);
9927   freeAsmop (result, NULL, ic, TRUE);
9928 }
9929
9930 /*-----------------------------------------------------------------*/
9931 /* genNearPointerSet - emitcode for near pointer put                */
9932 /*-----------------------------------------------------------------*/
9933 static void
9934 genNearPointerSet (operand * right,
9935                    operand * result,
9936                    iCode * ic,
9937                    iCode * pi)
9938 {
9939   asmop *aop = NULL;
9940   char *rname, *l;
9941   sym_link *retype, *letype;
9942   sym_link *ptype = operandType (result);
9943
9944   retype = getSpec (operandType (right));
9945   letype = getSpec (ptype);
9946
9947   aopOp (result, ic, FALSE, FALSE);
9948
9949   /* if the result is rematerializable &
9950      in data space & not a bit variable */
9951   if (AOP_TYPE (result) == AOP_IMMD &&
9952       DCL_TYPE (ptype) == POINTER &&
9953       !IS_BITVAR (retype) &&
9954       !IS_BITVAR (letype))
9955     {
9956       genDataPointerSet (right, result, ic);
9957       return;
9958     }
9959
9960   /* if the value is already in a pointer register
9961      then don't need anything more */
9962   if (!AOP_INPREG (AOP (result)))
9963     {
9964       /* otherwise get a free pointer register */
9965       regs *preg;
9966         
9967       aop = newAsmop (0);
9968       preg = getFreePtr (ic, &aop, FALSE);
9969       emitcode ("mov", "%s,%s",
9970                 preg->name,
9971                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
9972       rname = preg->name;
9973     }
9974   else
9975     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
9976
9977   aopOp (right, ic, FALSE, FALSE);
9978
9979   /* if bitfield then unpack the bits */
9980   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9981     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9982   else
9983     {
9984       /* we have can just get the values */
9985       int size = AOP_SIZE (right);
9986       int offset = 0;
9987
9988       while (size--)
9989         {
9990           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
9991           if (*l == '@')
9992             {
9993               MOVA (l);
9994               emitcode ("mov", "@%s,a", rname);
9995             }
9996           else
9997             emitcode ("mov", "@%s,%s", rname, l);
9998           if (size || pi)
9999             emitcode ("inc", "%s", rname);
10000           offset++;
10001         }
10002     }
10003
10004   /* now some housekeeping stuff */
10005   if (aop)
10006     {
10007       /* we had to allocate for this iCode */
10008       if (pi) aopPut (AOP (result),rname,0);
10009       freeAsmop (NULL, aop, ic, TRUE);
10010     }
10011   else
10012     {
10013       /* we did not allocate which means left
10014          already in a pointer register, then
10015          if size > 0 && this could be used again
10016          we have to point it back to where it
10017          belongs */
10018       if (AOP_SIZE (right) > 1 &&
10019           !OP_SYMBOL (result)->remat &&
10020           (OP_SYMBOL (result)->liveTo > ic->seq ||
10021            ic->depth) &&
10022           !pi)
10023         {
10024           int size = AOP_SIZE (right) - 1;
10025           while (size--)
10026             emitcode ("dec", "%s", rname);
10027         }
10028     }
10029
10030   /* done */
10031   if (pi) pi->generated = 1;
10032   freeAsmop (result, NULL, ic, TRUE);
10033   freeAsmop (right, NULL, ic, TRUE);
10034
10035
10036 }
10037
10038 /*-----------------------------------------------------------------*/
10039 /* genPagedPointerSet - emitcode for Paged pointer put             */
10040 /*-----------------------------------------------------------------*/
10041 static void
10042 genPagedPointerSet (operand * right,
10043                     operand * result,
10044                     iCode * ic,
10045                     iCode *pi)
10046 {
10047   asmop *aop = NULL;
10048   char *rname;
10049   sym_link *retype, *letype;
10050
10051   retype = getSpec (operandType (right));
10052   letype = getSpec (operandType (result));
10053
10054   aopOp (result, ic, FALSE, FALSE);
10055
10056   /* if the value is already in a pointer register
10057      then don't need anything more */
10058   if (!AOP_INPREG (AOP (result)))
10059     {
10060       /* otherwise get a free pointer register */
10061       regs *preg;
10062         
10063       aop = newAsmop (0);
10064       preg = getFreePtr (ic, &aop, FALSE);
10065       emitcode ("mov", "%s,%s",
10066                 preg->name,
10067                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10068       rname = preg->name;
10069     }
10070   else
10071     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10072
10073   aopOp (right, ic, FALSE, FALSE);
10074
10075   /* if bitfield then unpack the bits */
10076   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10077     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10078   else
10079     {
10080       /* we have can just get the values */
10081       int size = AOP_SIZE (right);
10082       int offset = 0;
10083
10084       while (size--)
10085         {
10086           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10087
10088           emitcode ("movx", "@%s,a", rname);
10089
10090           if (size || pi)
10091             emitcode ("inc", "%s", rname);
10092
10093           offset++;
10094         }
10095     }
10096
10097   /* now some housekeeping stuff */
10098   if (aop)
10099     {
10100       if (pi) aopPut (AOP (result),rname,0);
10101       /* we had to allocate for this iCode */
10102       freeAsmop (NULL, aop, ic, TRUE);
10103     }
10104   else
10105     {
10106       /* we did not allocate which means left
10107          already in a pointer register, then
10108          if size > 0 && this could be used again
10109          we have to point it back to where it
10110          belongs */
10111       if (AOP_SIZE (right) > 1 &&
10112           !OP_SYMBOL (result)->remat &&
10113           (OP_SYMBOL (result)->liveTo > ic->seq ||
10114            ic->depth) &&
10115           !pi)
10116         {
10117           int size = AOP_SIZE (right) - 1;
10118           while (size--)
10119             emitcode ("dec", "%s", rname);
10120         }
10121     }
10122
10123   /* done */
10124   if (pi) pi->generated = 1;
10125   freeAsmop (result, NULL, ic, TRUE);
10126   freeAsmop (right, NULL, ic, TRUE);
10127
10128
10129 }
10130
10131 /*-----------------------------------------------------------------*/
10132 /* genFarPointerSet - set value from far space                     */
10133 /*-----------------------------------------------------------------*/
10134 static void
10135 genFarPointerSet (operand * right,
10136                   operand * result, iCode * ic, iCode *pi)
10137 {
10138   int size, offset, dopi=1;
10139   sym_link *retype = getSpec (operandType (right));
10140   sym_link *letype = getSpec (operandType (result));
10141
10142   aopOp (result, ic, FALSE, FALSE);
10143
10144   /* if the operand is already in dptr
10145      then we do nothing else we move the value to dptr */
10146   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10147     {
10148       /* if this is remateriazable */
10149       if (AOP_TYPE (result) == AOP_IMMD)
10150         emitcode ("mov", "dptr,%s", 
10151                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10152       else
10153         {
10154           /* we need to get it byte by byte */
10155           _startLazyDPSEvaluation ();
10156           if (AOP_TYPE (result) != AOP_DPTR)
10157             {
10158               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10159               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10160               if (options.model == MODEL_FLAT24)
10161                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10162             }
10163           else
10164             {
10165               /* We need to generate a load to DPTR indirect through DPTR. */
10166               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10167                 
10168               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10169               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10170               if (options.model == MODEL_FLAT24)
10171                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10172               emitcode ("pop", "dph");
10173               emitcode ("pop", "dpl");
10174               dopi=0;
10175             }
10176           _endLazyDPSEvaluation ();
10177         }
10178     }
10179   /* so dptr know contains the address */
10180   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10181
10182   /* if bit then unpack */
10183   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10184       if (AOP_INDPTRn(result)) {
10185           genSetDPTR(AOP(result)->aopu.dptr);
10186       }
10187       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10188       if (AOP_INDPTRn(result)) {
10189           genSetDPTR(0);
10190       }
10191   } else {
10192       size = AOP_SIZE (right);
10193       offset = 0;
10194       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10195           while (size--) {
10196               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10197               
10198               genSetDPTR(AOP(result)->aopu.dptr);
10199               emitcode ("movx", "@dptr,a");
10200               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10201                   emitcode ("inc", "dptr");
10202               genSetDPTR (0);
10203           }
10204       } else {
10205           _startLazyDPSEvaluation ();
10206           while (size--) {
10207               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10208               
10209               if (AOP_INDPTRn(result)) {
10210                   genSetDPTR(AOP(result)->aopu.dptr);
10211               } else {
10212                   genSetDPTR (0);
10213               }
10214               _flushLazyDPS ();
10215               
10216               emitcode ("movx", "@dptr,a");
10217               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10218                   emitcode ("inc", "dptr");
10219           }
10220           _endLazyDPSEvaluation ();
10221       }
10222   }
10223   
10224   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10225       if (!AOP_INDPTRn(result)) {
10226           _startLazyDPSEvaluation ();
10227           
10228           aopPut (AOP(result),"dpl",0);
10229           aopPut (AOP(result),"dph",1);
10230           if (options.model == MODEL_FLAT24)
10231               aopPut (AOP(result),"dpx",2);
10232
10233           _endLazyDPSEvaluation ();
10234       }
10235       pi->generated=1;
10236   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10237              AOP_SIZE(right) > 1 &&
10238              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10239       
10240       size = AOP_SIZE (right) - 1;
10241       if (AOP_INDPTRn(result)) {
10242           genSetDPTR(AOP(result)->aopu.dptr);
10243       } 
10244       while (size--) emitcode ("lcall","__decdptr");
10245       if (AOP_INDPTRn(result)) {
10246           genSetDPTR(0);
10247       }
10248   }
10249   freeAsmop (result, NULL, ic, TRUE);
10250   freeAsmop (right, NULL, ic, TRUE);
10251 }
10252
10253 /*-----------------------------------------------------------------*/
10254 /* genGenPointerSet - set value from generic pointer space         */
10255 /*-----------------------------------------------------------------*/
10256 static void
10257 genGenPointerSet (operand * right,
10258                   operand * result, iCode * ic, iCode *pi)
10259 {
10260   int size, offset;
10261   sym_link *retype = getSpec (operandType (right));
10262   sym_link *letype = getSpec (operandType (result));
10263
10264   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10265
10266   /* if the operand is already in dptr
10267      then we do nothing else we move the value to dptr */
10268   if (AOP_TYPE (result) != AOP_STR)
10269     {
10270       _startLazyDPSEvaluation ();
10271       /* if this is remateriazable */
10272       if (AOP_TYPE (result) == AOP_IMMD)
10273         {
10274           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10275           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10276           {
10277               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10278           }
10279           else
10280           {
10281               emitcode ("mov", 
10282                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10283           }
10284         }
10285       else
10286         {                       /* we need to get it byte by byte */
10287           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10288           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10289           if (options.model == MODEL_FLAT24) {
10290             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10291             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10292           } else {
10293             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10294           }
10295         }
10296       _endLazyDPSEvaluation ();
10297     }
10298   /* so dptr + b now contains the address */
10299   _G.bInUse++;
10300   aopOp (right, ic, FALSE, TRUE);
10301   _G.bInUse--;
10302     
10303
10304   /* if bit then unpack */
10305   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10306     {
10307         genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10308     }
10309   else
10310     {
10311         size = AOP_SIZE (right);
10312         offset = 0;
10313
10314         _startLazyDPSEvaluation ();
10315         while (size--)
10316         {
10317             if (size)
10318             {
10319                 // Set two bytes at a time, passed in _AP & A.
10320                 // dptr will be incremented ONCE by __gptrputWord.
10321                 //
10322                 // Note: any change here must be coordinated
10323                 // with the implementation of __gptrputWord
10324                 // in device/lib/_gptrput.c
10325                 emitcode("mov", "_ap, %s", 
10326                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10327                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10328                 
10329                 genSetDPTR (0);
10330                 _flushLazyDPS ();
10331                 emitcode ("lcall", "__gptrputWord");
10332                 size--;
10333             }
10334             else
10335             {
10336                 // Only one byte to put.
10337                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10338
10339                 genSetDPTR (0);
10340                 _flushLazyDPS ();               
10341                 emitcode ("lcall", "__gptrput");
10342             }
10343             
10344             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10345             {
10346                 emitcode ("inc", "dptr");
10347             }
10348         }
10349         _endLazyDPSEvaluation ();
10350     }
10351
10352   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10353       _startLazyDPSEvaluation ();
10354       
10355       aopPut (AOP(result),"dpl",0);
10356       aopPut (AOP(result),"dph",1);
10357       if (options.model == MODEL_FLAT24) {
10358           aopPut (AOP(result),"dpx",2);
10359           aopPut (AOP(result),"b",3);
10360       } else {
10361           aopPut (AOP(result),"b",2);
10362       }
10363       _endLazyDPSEvaluation ();
10364       
10365       pi->generated=1;
10366   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10367              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10368       
10369       size = AOP_SIZE (right) - 1;
10370       while (size--) emitcode ("lcall","__decdptr");
10371   }
10372   freeAsmop (result, NULL, ic, TRUE);
10373   freeAsmop (right, NULL, ic, TRUE);
10374 }
10375
10376 /*-----------------------------------------------------------------*/
10377 /* genPointerSet - stores the value into a pointer location        */
10378 /*-----------------------------------------------------------------*/
10379 static void
10380 genPointerSet (iCode * ic, iCode *pi)
10381 {
10382   operand *right, *result;
10383   sym_link *type, *etype;
10384   int p_type;
10385
10386   D (emitcode (";", "genPointerSet "););
10387
10388   right = IC_RIGHT (ic);
10389   result = IC_RESULT (ic);
10390
10391   /* depending on the type of pointer we need to
10392      move it to the correct pointer register */
10393   type = operandType (result);
10394   etype = getSpec (type);
10395   /* if left is of type of pointer then it is simple */
10396   if (IS_PTR (type) && !IS_FUNC (type->next))
10397     {
10398       p_type = DCL_TYPE (type);
10399     }
10400   else
10401     {
10402       /* we have to go by the storage class */
10403       p_type = PTR_TYPE (SPEC_OCLS (etype));
10404     }
10405   /* special case when cast remat */
10406   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10407       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10408           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10409           type = operandType (result);
10410           p_type = DCL_TYPE (type);
10411   }
10412
10413   /* now that we have the pointer type we assign
10414      the pointer values */
10415   switch (p_type)
10416     {
10417
10418     case POINTER:
10419     case IPOINTER:
10420       genNearPointerSet (right, result, ic, pi);
10421       break;
10422
10423     case PPOINTER:
10424       genPagedPointerSet (right, result, ic, pi);
10425       break;
10426
10427     case FPOINTER:
10428       genFarPointerSet (right, result, ic, pi);
10429       break;
10430
10431     case GPOINTER:
10432       genGenPointerSet (right, result, ic, pi);
10433       break;
10434
10435     default:
10436       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10437               "genPointerSet: illegal pointer type");
10438     }
10439
10440 }
10441
10442 /*-----------------------------------------------------------------*/
10443 /* genIfx - generate code for Ifx statement                        */
10444 /*-----------------------------------------------------------------*/
10445 static void
10446 genIfx (iCode * ic, iCode * popIc)
10447 {
10448   operand *cond = IC_COND (ic);
10449   int isbit = 0;
10450
10451   D (emitcode (";", "genIfx "););
10452
10453   aopOp (cond, ic, FALSE, FALSE);
10454
10455   /* get the value into acc */
10456   if (AOP_TYPE (cond) != AOP_CRY)
10457     {
10458         toBoolean (cond);
10459     }
10460   else
10461     {
10462         isbit = 1;
10463     }
10464     
10465   /* the result is now in the accumulator */
10466   freeAsmop (cond, NULL, ic, TRUE);
10467
10468   /* if there was something to be popped then do it */
10469   if (popIc)
10470     genIpop (popIc);
10471
10472   /* if the condition is  a bit variable */
10473   if (isbit && IS_ITEMP (cond) &&
10474       SPIL_LOC (cond))
10475     {
10476         genIfxJump (ic, SPIL_LOC (cond)->rname);
10477     }
10478   else if (isbit && !IS_ITEMP (cond))
10479     {
10480         genIfxJump (ic, OP_SYMBOL (cond)->rname);
10481     }
10482   else
10483     {
10484         genIfxJump (ic, "a");
10485     }
10486
10487   ic->generated = 1;
10488 }
10489
10490 /*-----------------------------------------------------------------*/
10491 /* genAddrOf - generates code for address of                       */
10492 /*-----------------------------------------------------------------*/
10493 static void
10494 genAddrOf (iCode * ic)
10495 {
10496   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10497   int size, offset;
10498
10499   D (emitcode (";", "genAddrOf ");
10500     );
10501
10502   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10503
10504   /* if the operand is on the stack then we
10505      need to get the stack offset of this
10506      variable */
10507   if (sym->onStack) {
10508       
10509       /* if 10 bit stack */
10510       if (options.stack10bit) {
10511           char buff[10];
10512           tsprintf(buff, sizeof(buff), 
10513                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
10514           /* if it has an offset then we need to compute it */
10515 /*        emitcode ("subb", "a,#!constbyte", */
10516 /*                  -((sym->stack < 0) ? */
10517 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10518 /*                    ((short) sym->stack)) & 0xff); */
10519 /*        emitcode ("mov","b,a"); */
10520 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10521 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10522 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10523           if (sym->stack) {
10524               emitcode ("mov", "a,_bpx");
10525               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10526                                              ((char) (sym->stack - _G.nRegsSaved)) :
10527                                              ((char) sym->stack )) & 0xff);
10528               emitcode ("mov", "b,a");
10529               emitcode ("mov", "a,_bpx+1");
10530               emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ? 
10531                                               ((short) (sym->stack - _G.nRegsSaved)) :
10532                                               ((short) sym->stack )) >> 8) & 0xff);
10533               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10534               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10535               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10536           } else {
10537               /* we can just move _bp */
10538               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10539               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10540               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10541           }       
10542       } else {
10543           /* if it has an offset then we need to compute it */
10544           if (sym->stack) {
10545               emitcode ("mov", "a,_bp");
10546               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10547               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10548           } else {
10549               /* we can just move _bp */
10550               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10551           }
10552           /* fill the result with zero */
10553           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10554           
10555           
10556           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10557               fprintf (stderr,
10558                        "*** warning: pointer to stack var truncated.\n");
10559           }
10560
10561           offset = 1;
10562           while (size--) {
10563               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10564           }      
10565       }
10566       goto release;
10567   }
10568
10569   /* object not on stack then we need the name */
10570   size = AOP_SIZE (IC_RESULT (ic));
10571   offset = 0;
10572
10573   while (size--)
10574     {
10575       char s[SDCC_NAME_MAX];
10576       if (offset) {
10577           switch (offset) {
10578           case 1:
10579               tsprintf(s, sizeof(s), "#!his",sym->rname);
10580               break;
10581           case 2:
10582               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10583               break;
10584           case 3:
10585               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10586               break;
10587           default: /* should not need this (just in case) */
10588               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10589                        sym->rname,
10590                        offset * 8);
10591           }
10592       } 
10593       else
10594       {
10595           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10596       }
10597         
10598       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10599     }
10600
10601 release:
10602   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10603
10604 }
10605
10606 /*-----------------------------------------------------------------*/
10607 /* genArrayInit - generates code for address of                       */
10608 /*-----------------------------------------------------------------*/
10609 static void
10610 genArrayInit (iCode * ic)
10611 {
10612     literalList *iLoop;
10613     int         ix, count;
10614     int         elementSize = 0, eIndex;
10615     unsigned    val, lastVal;
10616     sym_link    *type;
10617     operand     *left=IC_LEFT(ic);
10618     
10619     D (emitcode (";", "genArrayInit "););
10620
10621     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10622     
10623     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10624     {
10625         // Load immediate value into DPTR.
10626         emitcode("mov", "dptr, %s",
10627              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10628     }
10629     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10630     {
10631 #if 0
10632       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10633               "Unexpected operand to genArrayInit.\n");
10634       exit(1);
10635 #else
10636       // a regression because of SDCCcse.c:1.52
10637       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10638       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10639       if (options.model == MODEL_FLAT24)
10640         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10641 #endif
10642     }
10643     
10644     type = operandType(IC_LEFT(ic));
10645     
10646     if (type && type->next)
10647     {
10648         elementSize = getSize(type->next);
10649     }
10650     else
10651     {
10652         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10653                                 "can't determine element size in genArrayInit.\n");
10654         exit(1);
10655     }
10656     
10657     iLoop = IC_ARRAYILIST(ic);
10658     lastVal = 0xffff;
10659     
10660     while (iLoop)
10661     {
10662         bool firstpass = TRUE;
10663         
10664         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10665                  iLoop->count, (int)iLoop->literalValue, elementSize);
10666         
10667         ix = iLoop->count;
10668         
10669         while (ix)
10670         {
10671             symbol *tlbl = NULL;
10672             
10673             count = ix > 256 ? 256 : ix;
10674             
10675             if (count > 1)
10676             {
10677                 tlbl = newiTempLabel (NULL);
10678                 if (firstpass || (count & 0xff))
10679                 {
10680                     emitcode("mov", "b, #!constbyte", count & 0xff);
10681                 }
10682                 
10683                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10684             }
10685             
10686             firstpass = FALSE;
10687                 
10688             for (eIndex = 0; eIndex < elementSize; eIndex++)
10689             {
10690                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10691                 if (val != lastVal)
10692                 {
10693                     emitcode("mov", "a, #!constbyte", val);
10694                     lastVal = val;
10695                 }
10696                 
10697                 emitcode("movx", "@dptr, a");
10698                 emitcode("inc", "dptr");
10699             }
10700             
10701             if (count > 1)
10702             {
10703                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10704             }
10705             
10706             ix -= count;
10707         }
10708         
10709         iLoop = iLoop->next;
10710     }
10711     
10712     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10713 }
10714
10715 /*-----------------------------------------------------------------*/
10716 /* genFarFarAssign - assignment when both are in far space         */
10717 /*-----------------------------------------------------------------*/
10718 static void
10719 genFarFarAssign (operand * result, operand * right, iCode * ic)
10720 {
10721   int size = AOP_SIZE (right);
10722   int offset = 0;
10723   symbol *rSym = NULL;
10724
10725   if (size == 1)
10726   {
10727       /* quick & easy case. */
10728       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10729       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10730       freeAsmop (right, NULL, ic, FALSE);
10731       /* now assign DPTR to result */
10732       _G.accInUse++;
10733       aopOp(result, ic, FALSE, FALSE);
10734       _G.accInUse--;
10735       aopPut(AOP(result), "a", 0);
10736       freeAsmop(result, NULL, ic, FALSE);
10737       return;
10738   }
10739   
10740   /* See if we've got an underlying symbol to abuse. */
10741   if (IS_SYMOP(result) && OP_SYMBOL(result))
10742   {
10743       if (IS_TRUE_SYMOP(result))
10744       {
10745           rSym = OP_SYMBOL(result);
10746       }
10747       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10748       {
10749           rSym = OP_SYMBOL(result)->usl.spillLoc;
10750       }
10751   }
10752              
10753   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10754   {
10755       /* We can use the '390 auto-toggle feature to good effect here. */
10756       
10757       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10758       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10759       emitcode ("mov", "dptr,#%s", rSym->rname); 
10760       /* DP2 = result, DP1 = right, DP1 is current. */
10761       while (size)
10762       {
10763           emitcode("movx", "a,@dptr");
10764           emitcode("movx", "@dptr,a");
10765           if (--size)
10766           {
10767                emitcode("inc", "dptr");
10768                emitcode("inc", "dptr");
10769           }
10770       }
10771       emitcode("mov", "dps,#0");
10772       freeAsmop (right, NULL, ic, FALSE);
10773 #if 0
10774 some alternative code for processors without auto-toggle
10775 no time to test now, so later well put in...kpb
10776         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10777         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10778         emitcode ("mov", "dptr,#%s", rSym->rname); 
10779         /* DP2 = result, DP1 = right, DP1 is current. */
10780         while (size)
10781         {
10782           --size;
10783           emitcode("movx", "a,@dptr");
10784           if (size)
10785             emitcode("inc", "dptr");
10786           emitcode("inc", "dps");
10787           emitcode("movx", "@dptr,a");
10788           if (size)
10789             emitcode("inc", "dptr");
10790           emitcode("inc", "dps");
10791         }
10792         emitcode("mov", "dps,#0");
10793         freeAsmop (right, NULL, ic, FALSE);
10794 #endif
10795   }
10796   else
10797   {
10798       D (emitcode (";", "genFarFarAssign"););
10799       aopOp (result, ic, TRUE, TRUE);
10800
10801       _startLazyDPSEvaluation ();
10802       
10803       while (size--)
10804         {
10805           aopPut (AOP (result),
10806                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10807           offset++;
10808         }
10809       _endLazyDPSEvaluation ();
10810       freeAsmop (result, NULL, ic, FALSE);
10811       freeAsmop (right, NULL, ic, FALSE);
10812   }
10813 }
10814
10815 /*-----------------------------------------------------------------*/
10816 /* genAssign - generate code for assignment                        */
10817 /*-----------------------------------------------------------------*/
10818 static void
10819 genAssign (iCode * ic)
10820 {
10821   operand *result, *right;
10822   int size, offset;
10823   unsigned long lit = 0L;
10824
10825   D (emitcode (";", "genAssign ");
10826     );
10827
10828   result = IC_RESULT (ic);
10829   right = IC_RIGHT (ic);
10830
10831   /* if they are the same */
10832   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10833     return;
10834
10835   aopOp (right, ic, FALSE, FALSE);
10836
10837   emitcode (";", "genAssign: resultIsFar = %s",
10838             isOperandInFarSpace (result) ?
10839             "TRUE" : "FALSE");
10840
10841   /* special case both in far space */
10842   if ((AOP_TYPE (right) == AOP_DPTR ||
10843        AOP_TYPE (right) == AOP_DPTR2) &&
10844   /* IS_TRUE_SYMOP(result)       && */
10845       isOperandInFarSpace (result))
10846     {
10847       genFarFarAssign (result, right, ic);
10848       return;
10849     }
10850
10851   aopOp (result, ic, TRUE, FALSE);
10852
10853   /* if they are the same registers */
10854   if (sameRegs (AOP (right), AOP (result)))
10855     goto release;
10856
10857   /* if the result is a bit */
10858   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10859     {
10860       /* if the right size is a literal then
10861          we know what the value is */
10862       if (AOP_TYPE (right) == AOP_LIT)
10863         {
10864           if (((int) operandLitValue (right)))
10865             aopPut (AOP (result), one, 0);
10866           else
10867             aopPut (AOP (result), zero, 0);
10868           goto release;
10869         }
10870
10871       /* the right is also a bit variable */
10872       if (AOP_TYPE (right) == AOP_CRY)
10873         {
10874           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10875           aopPut (AOP (result), "c", 0);
10876           goto release;
10877         }
10878
10879       /* we need to or */
10880       toBoolean (right);
10881       aopPut (AOP (result), "a", 0);
10882       goto release;
10883     }
10884
10885   /* bit variables done */
10886   /* general case */
10887   size = AOP_SIZE (result);
10888   offset = 0;
10889   if (AOP_TYPE (right) == AOP_LIT)
10890     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10891
10892   if ((size > 1) &&
10893       (AOP_TYPE (result) != AOP_REG) &&
10894       (AOP_TYPE (right) == AOP_LIT) &&
10895       !IS_FLOAT (operandType (right)))
10896     {
10897       _startLazyDPSEvaluation ();
10898       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10899         {
10900           aopPut (AOP (result),
10901                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10902                   offset);
10903           offset++;
10904           size--;
10905         }
10906       /* And now fill the rest with zeros. */
10907       if (size)
10908         {
10909           emitcode ("clr", "a");
10910         }
10911       while (size--)
10912         {
10913           aopPut (AOP (result), "a", offset++);
10914         }
10915       _endLazyDPSEvaluation ();
10916     }
10917   else
10918     {
10919       _startLazyDPSEvaluation ();
10920       while (size--)
10921         {
10922           aopPut (AOP (result),
10923                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10924                   offset);
10925           offset++;
10926         }
10927       _endLazyDPSEvaluation ();
10928     }
10929
10930 release:
10931   freeAsmop (right, NULL, ic, FALSE);
10932   freeAsmop (result, NULL, ic, TRUE);
10933 }
10934
10935 /*-----------------------------------------------------------------*/
10936 /* genJumpTab - generates code for jump table                      */
10937 /*-----------------------------------------------------------------*/
10938 static void
10939 genJumpTab (iCode * ic)
10940 {
10941   symbol *jtab;
10942   char *l;
10943
10944   D (emitcode (";", "genJumpTab ");
10945     );
10946
10947   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10948   /* get the condition into accumulator */
10949   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10950   MOVA (l);
10951   /* multiply by four! */
10952   emitcode ("add", "a,acc");
10953   emitcode ("add", "a,acc");
10954   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10955
10956   jtab = newiTempLabel (NULL);
10957   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10958   emitcode ("jmp", "@a+dptr");
10959   emitcode ("", "!tlabeldef", jtab->key + 100);
10960   /* now generate the jump labels */
10961   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10962        jtab = setNextItem (IC_JTLABELS (ic)))
10963     emitcode ("ljmp", "!tlabel", jtab->key + 100);
10964
10965 }
10966
10967 /*-----------------------------------------------------------------*/
10968 /* genCast - gen code for casting                                  */
10969 /*-----------------------------------------------------------------*/
10970 static void
10971 genCast (iCode * ic)
10972 {
10973   operand *result = IC_RESULT (ic);
10974   sym_link *ctype = operandType (IC_LEFT (ic));
10975   sym_link *rtype = operandType (IC_RIGHT (ic));
10976   operand *right = IC_RIGHT (ic);
10977   int size, offset;
10978
10979   D (emitcode (";", "genCast "););
10980
10981   /* if they are equivalent then do nothing */
10982   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10983     return;
10984
10985   aopOp (right, ic, FALSE, FALSE);
10986   aopOp (result, ic, FALSE, AOP_USESDPTR(right));
10987
10988   /* if the result is a bit */
10989   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10990   if (IS_BITVAR(OP_SYMBOL(result)->type))
10991     {
10992       /* if the right size is a literal then
10993          we know what the value is */
10994       if (AOP_TYPE (right) == AOP_LIT)
10995         {
10996           if (((int) operandLitValue (right)))
10997             aopPut (AOP (result), one, 0);
10998           else
10999             aopPut (AOP (result), zero, 0);
11000
11001           goto release;
11002         }
11003
11004       /* the right is also a bit variable */
11005       if (AOP_TYPE (right) == AOP_CRY)
11006         {
11007           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11008           aopPut (AOP (result), "c", 0);
11009           goto release;
11010         }
11011
11012       /* we need to or */
11013       toBoolean (right);
11014       aopPut (AOP (result), "a", 0);
11015       goto release;
11016     }
11017
11018   /* if they are the same size : or less */
11019   if (AOP_SIZE (result) <= AOP_SIZE (right))
11020     {
11021
11022       /* if they are in the same place */
11023       if (sameRegs (AOP (right), AOP (result)))
11024         goto release;
11025
11026       /* if they in different places then copy */
11027       size = AOP_SIZE (result);
11028       offset = 0;
11029       _startLazyDPSEvaluation ();
11030       while (size--)
11031         {
11032           aopPut (AOP (result),
11033                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11034                   offset);
11035           offset++;
11036         }
11037       _endLazyDPSEvaluation ();
11038       goto release;
11039     }
11040
11041
11042   /* if the result is of type pointer */
11043   if (IS_PTR (ctype))
11044     {
11045
11046       int p_type;
11047       sym_link *type = operandType (right);
11048
11049       /* pointer to generic pointer */
11050       if (IS_GENPTR (ctype))
11051         {
11052           if (IS_PTR (type))
11053             {
11054               p_type = DCL_TYPE (type);
11055             }
11056           else
11057             {
11058 #if OLD_CAST_BEHAVIOR
11059               /* KV: we are converting a non-pointer type to
11060                * a generic pointer. This (ifdef'd out) code
11061                * says that the resulting generic pointer
11062                * should have the same class as the storage
11063                * location of the non-pointer variable.
11064                *
11065                * For example, converting an int (which happens
11066                * to be stored in DATA space) to a pointer results
11067                * in a DATA generic pointer; if the original int
11068                * in XDATA space, so will be the resulting pointer.
11069                *
11070                * I don't like that behavior, and thus this change:
11071                * all such conversions will be forced to XDATA and
11072                * throw a warning. If you want some non-XDATA
11073                * type, or you want to suppress the warning, you
11074                * must go through an intermediate cast, like so:
11075                *
11076                * char _generic *gp = (char _xdata *)(intVar);
11077                */
11078               sym_link *etype = getSpec (type);
11079
11080               /* we have to go by the storage class */
11081               if (SPEC_OCLS (etype) != generic)
11082                 {
11083                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11084                 }
11085               else
11086 #endif
11087                 {
11088                   /* Converting unknown class (i.e. register variable)
11089                    * to generic pointer. This is not good, but
11090                    * we'll make a guess (and throw a warning).
11091                    */
11092                   p_type = FPOINTER;
11093                   werror (W_INT_TO_GEN_PTR_CAST);
11094                 }
11095             }
11096
11097           /* the first two bytes are known */
11098           size = GPTRSIZE - 1;
11099           offset = 0;
11100           _startLazyDPSEvaluation ();
11101           while (size--)
11102             {
11103               aopPut (AOP (result),
11104                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11105                       offset);
11106               offset++;
11107             }
11108           _endLazyDPSEvaluation ();
11109
11110           /* the last byte depending on type */
11111             {
11112                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11113                 char gpValStr[10];
11114             
11115                 if (gpVal == -1)
11116                 {
11117                     // pointerTypeToGPByte will have bitched.
11118                     exit(1);
11119                 }
11120             
11121                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11122                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11123             }
11124           goto release;
11125         }
11126
11127       /* just copy the pointers */
11128       size = AOP_SIZE (result);
11129       offset = 0;
11130       _startLazyDPSEvaluation ();
11131       while (size--)
11132         {
11133           aopPut (AOP (result),
11134                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11135                   offset);
11136           offset++;
11137         }
11138       _endLazyDPSEvaluation ();
11139       goto release;
11140     }
11141
11142   /* so we now know that the size of destination is greater
11143      than the size of the source */
11144   /* we move to result for the size of source */
11145   size = AOP_SIZE (right);
11146   offset = 0;
11147   _startLazyDPSEvaluation ();
11148   while (size--)
11149     {
11150       aopPut (AOP (result),
11151               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11152               offset);
11153       offset++;
11154     }
11155   _endLazyDPSEvaluation ();
11156
11157   /* now depending on the sign of the source && destination */
11158   size = AOP_SIZE (result) - AOP_SIZE (right);
11159   /* if unsigned or not an integral type */
11160   /* also, if the source is a bit, we don't need to sign extend, because
11161    * it can't possibly have set the sign bit.
11162    */
11163   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
11164     {
11165       while (size--)
11166         {
11167           aopPut (AOP (result), zero, offset++);
11168         }
11169     }
11170   else
11171     {
11172       /* we need to extend the sign :{ */
11173       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11174                         FALSE, FALSE, NULL));
11175       emitcode ("rlc", "a");
11176       emitcode ("subb", "a,acc");
11177       while (size--)
11178         aopPut (AOP (result), "a", offset++);
11179     }
11180
11181   /* we are done hurray !!!! */
11182
11183 release:
11184   freeAsmop (right, NULL, ic, TRUE);
11185   freeAsmop (result, NULL, ic, TRUE);
11186
11187 }
11188
11189 /*-----------------------------------------------------------------*/
11190 /* genDjnz - generate decrement & jump if not zero instrucion      */
11191 /*-----------------------------------------------------------------*/
11192 static int
11193 genDjnz (iCode * ic, iCode * ifx)
11194 {
11195   symbol *lbl, *lbl1;
11196   if (!ifx)
11197     return 0;
11198
11199   /* if the if condition has a false label
11200      then we cannot save */
11201   if (IC_FALSE (ifx))
11202     return 0;
11203
11204   /* if the minus is not of the form
11205      a = a - 1 */
11206   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11207       !IS_OP_LITERAL (IC_RIGHT (ic)))
11208     return 0;
11209
11210   if (operandLitValue (IC_RIGHT (ic)) != 1)
11211     return 0;
11212
11213   /* if the size of this greater than one then no
11214      saving */
11215   if (getSize (operandType (IC_RESULT (ic))) > 1)
11216     return 0;
11217
11218   /* otherwise we can save BIG */
11219   D(emitcode(";", "genDjnz"););
11220
11221   lbl = newiTempLabel (NULL);
11222   lbl1 = newiTempLabel (NULL);
11223
11224   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11225
11226   if (AOP_NEEDSACC(IC_RESULT(ic)))
11227   {
11228       /* If the result is accessed indirectly via
11229        * the accumulator, we must explicitly write
11230        * it back after the decrement.
11231        */
11232       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11233       
11234       if (strcmp(rByte, "a"))
11235       {
11236            /* Something is hopelessly wrong */
11237            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11238                    __FILE__, __LINE__);
11239            /* We can just give up; the generated code will be inefficient,
11240             * but what the hey.
11241             */
11242            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11243            return 0;
11244       }
11245       emitcode ("dec", "%s", rByte);
11246       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11247       emitcode ("jnz", "!tlabel", lbl->key + 100);
11248   }
11249   else if (IS_AOP_PREG (IC_RESULT (ic)))
11250     {
11251       emitcode ("dec", "%s",
11252                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11253       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11254       emitcode ("jnz", "!tlabel", lbl->key + 100);
11255     }
11256   else
11257     {
11258       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11259                 lbl->key + 100);
11260     }
11261   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11262   emitcode ("", "!tlabeldef", lbl->key + 100);
11263   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11264   emitcode ("", "!tlabeldef", lbl1->key + 100);
11265
11266   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11267   ifx->generated = 1;
11268   return 1;
11269 }
11270
11271 /*-----------------------------------------------------------------*/
11272 /* genReceive - generate code for a receive iCode                  */
11273 /*-----------------------------------------------------------------*/
11274 static void
11275 genReceive (iCode * ic)
11276 {
11277     int size = getSize (operandType (IC_RESULT (ic)));
11278     int offset = 0;
11279     int rb1off ;
11280     
11281     D (emitcode (";", "genReceive "););
11282
11283     if (ic->argreg == 1) 
11284     {
11285         /* first parameter */
11286         if (AOP_IS_STR(IC_RESULT(ic)))
11287         {
11288             /* Nothing to do: it's already in the proper place. */
11289             return;
11290         }
11291         else
11292         {
11293             bool useDp2;
11294             
11295             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11296                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11297                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11298             
11299             _G.accInUse++;
11300             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11301             _G.accInUse--; 
11302             
11303             /* Sanity checking... */
11304             if (AOP_USESDPTR(IC_RESULT(ic)))
11305             {
11306                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11307                         "genReceive got unexpected DPTR.");
11308             }
11309             assignResultValue (IC_RESULT (ic));
11310         }
11311     } 
11312     else 
11313     { 
11314         /* second receive onwards */
11315         /* this gets a little tricky since unused recevies will be
11316          eliminated, we have saved the reg in the type field . and
11317          we use that to figure out which register to use */
11318         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11319         rb1off = ic->argreg;
11320         while (size--) 
11321         {
11322             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11323         }
11324     }
11325     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11326 }
11327
11328 /*-----------------------------------------------------------------*/
11329 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11330 /*-----------------------------------------------------------------*/
11331 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11332 {
11333     operand *from , *to , *count;
11334     symbol *lbl;
11335     bitVect *rsave;
11336     int i;
11337
11338     /* we know it has to be 3 parameters */
11339     assert (nparms == 3);
11340     
11341     rsave = newBitVect(16);
11342     /* save DPTR if it needs to be saved */
11343     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11344             if (bitVectBitValue(ic->rMask,i))
11345                     rsave = bitVectSetBit(rsave,i);
11346     }
11347     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11348                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11349     savermask(rsave);
11350     
11351     to = parms[0];
11352     from = parms[1];
11353     count = parms[2];
11354
11355     aopOp (from, ic->next, FALSE, FALSE);
11356
11357     /* get from into DPTR1 */
11358     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11359     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11360     if (options.model == MODEL_FLAT24) {
11361         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11362     }
11363
11364     freeAsmop (from, NULL, ic, FALSE);
11365     aopOp (to, ic, FALSE, FALSE);
11366     /* get "to" into DPTR */
11367     /* if the operand is already in dptr
11368        then we do nothing else we move the value to dptr */
11369     if (AOP_TYPE (to) != AOP_STR) {
11370         /* if already in DPTR then we need to push */
11371         if (AOP_TYPE(to) == AOP_DPTR) {
11372             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11373             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11374             if (options.model == MODEL_FLAT24)
11375                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11376             emitcode ("pop", "dph");
11377             emitcode ("pop", "dpl");        
11378         } else {
11379             _startLazyDPSEvaluation ();
11380             /* if this is remateriazable */
11381             if (AOP_TYPE (to) == AOP_IMMD) {
11382                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11383             } else {                    /* we need to get it byte by byte */
11384                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11385                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11386                 if (options.model == MODEL_FLAT24) {
11387                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11388                 }
11389             }
11390             _endLazyDPSEvaluation ();
11391         }
11392     }
11393     freeAsmop (to, NULL, ic, FALSE);
11394     _G.dptrInUse = _G.dptr1InUse = 1;
11395     aopOp (count, ic->next->next, FALSE,FALSE);
11396     lbl =newiTempLabel(NULL);
11397
11398     /* now for the actual copy */
11399     if (AOP_TYPE(count) == AOP_LIT && 
11400         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11401         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11402         if (fromc) {
11403             emitcode ("lcall","__bi_memcpyc2x_s");
11404         } else {
11405             emitcode ("lcall","__bi_memcpyx2x_s");
11406         }
11407         freeAsmop (count, NULL, ic, FALSE);
11408     } else {
11409         symbol *lbl1 = newiTempLabel(NULL);
11410         
11411         emitcode (";"," Auto increment but no djnz");
11412         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11413         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11414         freeAsmop (count, NULL, ic, FALSE);
11415         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11416         emitcode ("","!tlabeldef",lbl->key+100);
11417         if (fromc) {
11418             emitcode ("clr","a");
11419             emitcode ("movc", "a,@a+dptr");
11420         } else 
11421             emitcode ("movx", "a,@dptr");
11422         emitcode ("movx", "@dptr,a");
11423         emitcode ("inc", "dptr");
11424         emitcode ("inc", "dptr");
11425         emitcode ("mov","a,b");
11426         emitcode ("orl","a,_ap");
11427         emitcode ("jz","!tlabel",lbl1->key+100);
11428         emitcode ("mov","a,_ap");
11429         emitcode ("add","a,#!constbyte",0xFF);
11430         emitcode ("mov","_ap,a");
11431         emitcode ("mov","a,b");
11432         emitcode ("addc","a,#!constbyte",0xFF);
11433         emitcode ("mov","b,a");
11434         emitcode ("sjmp","!tlabel",lbl->key+100);
11435         emitcode ("","!tlabeldef",lbl1->key+100);
11436     }
11437     emitcode ("mov", "dps,#0"); 
11438     _G.dptrInUse = _G.dptr1InUse = 0;
11439     unsavermask(rsave);
11440
11441 }
11442
11443 /*-----------------------------------------------------------------*/
11444 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11445 /*-----------------------------------------------------------------*/
11446 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11447 {
11448     operand *from , *to , *count;
11449     symbol *lbl,*lbl2;
11450     bitVect *rsave;
11451     int i;
11452
11453     /* we know it has to be 3 parameters */
11454     assert (nparms == 3);
11455     
11456     rsave = newBitVect(16);
11457     /* save DPTR if it needs to be saved */
11458     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11459             if (bitVectBitValue(ic->rMask,i))
11460                     rsave = bitVectSetBit(rsave,i);
11461     }
11462     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11463                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11464     savermask(rsave);
11465     
11466     to = parms[0];
11467     from = parms[1];
11468     count = parms[2];
11469
11470     aopOp (from, ic->next, FALSE, FALSE);
11471
11472     /* get from into DPTR1 */
11473     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11474     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11475     if (options.model == MODEL_FLAT24) {
11476         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11477     }
11478
11479     freeAsmop (from, NULL, ic, FALSE);
11480     aopOp (to, ic, FALSE, FALSE);
11481     /* get "to" into DPTR */
11482     /* if the operand is already in dptr
11483        then we do nothing else we move the value to dptr */
11484     if (AOP_TYPE (to) != AOP_STR) {
11485         /* if already in DPTR then we need to push */
11486         if (AOP_TYPE(to) == AOP_DPTR) {
11487             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11488             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11489             if (options.model == MODEL_FLAT24)
11490                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11491             emitcode ("pop", "dph");
11492             emitcode ("pop", "dpl");        
11493         } else {
11494             _startLazyDPSEvaluation ();
11495             /* if this is remateriazable */
11496             if (AOP_TYPE (to) == AOP_IMMD) {
11497                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11498             } else {                    /* we need to get it byte by byte */
11499                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11500                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11501                 if (options.model == MODEL_FLAT24) {
11502                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11503                 }
11504             }
11505             _endLazyDPSEvaluation ();
11506         }
11507     }
11508     freeAsmop (to, NULL, ic, FALSE);
11509     _G.dptrInUse = _G.dptr1InUse = 1;
11510     aopOp (count, ic->next->next, FALSE,FALSE);
11511     lbl =newiTempLabel(NULL);
11512     lbl2 =newiTempLabel(NULL);
11513
11514     /* now for the actual compare */
11515     if (AOP_TYPE(count) == AOP_LIT && 
11516         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11517         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11518         if (fromc)
11519             emitcode("lcall","__bi_memcmpc2x_s");
11520         else
11521             emitcode("lcall","__bi_memcmpx2x_s");
11522         freeAsmop (count, NULL, ic, FALSE);
11523         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11524         aopPut(AOP(IC_RESULT(ic)),"a",0);
11525         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11526     } else {
11527         symbol *lbl1 = newiTempLabel(NULL);
11528
11529         emitcode("push","ar0");         
11530         emitcode (";"," Auto increment but no djnz");
11531         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11532         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11533         freeAsmop (count, NULL, ic, FALSE);
11534         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11535         emitcode ("","!tlabeldef",lbl->key+100);
11536         if (fromc) {
11537             emitcode ("clr","a");
11538             emitcode ("movc", "a,@a+dptr");
11539         } else 
11540             emitcode ("movx", "a,@dptr");
11541         emitcode ("mov","r0,a");
11542         emitcode ("movx", "a,@dptr");
11543         emitcode ("clr","c");
11544         emitcode ("subb","a,r0");
11545         emitcode ("jnz","!tlabel",lbl2->key+100);
11546         emitcode ("inc", "dptr");
11547         emitcode ("inc", "dptr");
11548         emitcode ("mov","a,b");
11549         emitcode ("orl","a,_ap");
11550         emitcode ("jz","!tlabel",lbl1->key+100);
11551         emitcode ("mov","a,_ap");
11552         emitcode ("add","a,#!constbyte",0xFF);
11553         emitcode ("mov","_ap,a");
11554         emitcode ("mov","a,b");
11555         emitcode ("addc","a,#!constbyte",0xFF);
11556         emitcode ("mov","b,a");
11557         emitcode ("sjmp","!tlabel",lbl->key+100);
11558         emitcode ("","!tlabeldef",lbl1->key+100);
11559         emitcode ("clr","a");
11560         emitcode ("","!tlabeldef",lbl2->key+100);
11561         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11562         aopPut(AOP(IC_RESULT(ic)),"a",0);
11563         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11564         emitcode("pop","ar0");
11565         emitcode ("mov", "dps,#0");      
11566     }
11567     _G.dptrInUse = _G.dptr1InUse = 0;
11568     unsavermask(rsave);
11569
11570 }
11571
11572 /*-----------------------------------------------------------------*/
11573 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11574 /* port, first parameter output area second parameter pointer to   */
11575 /* port third parameter count                                      */
11576 /*-----------------------------------------------------------------*/
11577 static void genInp( iCode *ic, int nparms, operand **parms)
11578 {
11579     operand *from , *to , *count;
11580     symbol *lbl;
11581     bitVect *rsave;
11582     int i;
11583
11584     /* we know it has to be 3 parameters */
11585     assert (nparms == 3);
11586     
11587     rsave = newBitVect(16);
11588     /* save DPTR if it needs to be saved */
11589     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11590             if (bitVectBitValue(ic->rMask,i))
11591                     rsave = bitVectSetBit(rsave,i);
11592     }
11593     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11594                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11595     savermask(rsave);
11596     
11597     to = parms[0];
11598     from = parms[1];
11599     count = parms[2];
11600
11601     aopOp (from, ic->next, FALSE, FALSE);
11602
11603     /* get from into DPTR1 */
11604     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11605     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11606     if (options.model == MODEL_FLAT24) {
11607         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11608     }
11609
11610     freeAsmop (from, NULL, ic, FALSE);
11611     aopOp (to, ic, FALSE, FALSE);
11612     /* get "to" into DPTR */
11613     /* if the operand is already in dptr
11614        then we do nothing else we move the value to dptr */
11615     if (AOP_TYPE (to) != AOP_STR) {
11616         /* if already in DPTR then we need to push */
11617         if (AOP_TYPE(to) == AOP_DPTR) {
11618             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11619             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11620             if (options.model == MODEL_FLAT24)
11621                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11622             emitcode ("pop", "dph");
11623             emitcode ("pop", "dpl");        
11624         } else {
11625             _startLazyDPSEvaluation ();
11626             /* if this is remateriazable */
11627             if (AOP_TYPE (to) == AOP_IMMD) {
11628                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11629             } else {                    /* we need to get it byte by byte */
11630                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11631                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11632                 if (options.model == MODEL_FLAT24) {
11633                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11634                 }
11635             }
11636             _endLazyDPSEvaluation ();
11637         }
11638     }
11639     freeAsmop (to, NULL, ic, FALSE);
11640
11641     _G.dptrInUse = _G.dptr1InUse = 1;
11642     aopOp (count, ic->next->next, FALSE,FALSE);
11643     lbl =newiTempLabel(NULL);
11644
11645     /* now for the actual copy */
11646     if (AOP_TYPE(count) == AOP_LIT && 
11647         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11648         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11649         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11650         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11651         freeAsmop (count, NULL, ic, FALSE);
11652         emitcode ("","!tlabeldef",lbl->key+100);
11653         emitcode ("movx", "a,@dptr");   /* read data from port */
11654         emitcode ("dec","dps");         /* switch to DPTR */
11655         emitcode ("movx", "@dptr,a");   /* save into location */
11656         emitcode ("inc", "dptr");       /* point to next area */
11657         emitcode ("inc","dps");         /* switch to DPTR2 */
11658         emitcode ("djnz","b,!tlabel",lbl->key+100);
11659     } else {
11660         symbol *lbl1 = newiTempLabel(NULL);
11661         
11662         emitcode (";"," Auto increment but no djnz");
11663         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11664         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11665         freeAsmop (count, NULL, ic, FALSE);
11666         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11667         emitcode ("","!tlabeldef",lbl->key+100);
11668         emitcode ("movx", "a,@dptr");
11669         emitcode ("dec","dps");         /* switch to DPTR */
11670         emitcode ("movx", "@dptr,a");
11671         emitcode ("inc", "dptr");
11672         emitcode ("inc","dps");         /* switch to DPTR2 */
11673 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11674 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11675         emitcode ("mov","a,b");
11676         emitcode ("orl","a,_ap");
11677         emitcode ("jz","!tlabel",lbl1->key+100);
11678         emitcode ("mov","a,_ap");
11679         emitcode ("add","a,#!constbyte",0xFF);
11680         emitcode ("mov","_ap,a");
11681         emitcode ("mov","a,b");
11682         emitcode ("addc","a,#!constbyte",0xFF);
11683         emitcode ("mov","b,a");
11684         emitcode ("sjmp","!tlabel",lbl->key+100);
11685         emitcode ("","!tlabeldef",lbl1->key+100);
11686     }
11687     emitcode ("mov", "dps,#0"); 
11688     _G.dptrInUse = _G.dptr1InUse = 0;
11689     unsavermask(rsave);
11690
11691 }
11692
11693 /*-----------------------------------------------------------------*/
11694 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11695 /* port, first parameter output area second parameter pointer to   */
11696 /* port third parameter count                                      */
11697 /*-----------------------------------------------------------------*/
11698 static void genOutp( iCode *ic, int nparms, operand **parms)
11699 {
11700     operand *from , *to , *count;
11701     symbol *lbl;
11702     bitVect *rsave;
11703     int i;
11704
11705     /* we know it has to be 3 parameters */
11706     assert (nparms == 3);
11707     
11708     rsave = newBitVect(16);
11709     /* save DPTR if it needs to be saved */
11710     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11711             if (bitVectBitValue(ic->rMask,i))
11712                     rsave = bitVectSetBit(rsave,i);
11713     }
11714     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11715                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11716     savermask(rsave);
11717     
11718     to = parms[0];
11719     from = parms[1];
11720     count = parms[2];
11721
11722     aopOp (from, ic->next, FALSE, FALSE);
11723
11724     /* get from into DPTR1 */
11725     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11726     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11727     if (options.model == MODEL_FLAT24) {
11728         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11729     }
11730
11731     freeAsmop (from, NULL, ic, FALSE);
11732     aopOp (to, ic, FALSE, FALSE);
11733     /* get "to" into DPTR */
11734     /* if the operand is already in dptr
11735        then we do nothing else we move the value to dptr */
11736     if (AOP_TYPE (to) != AOP_STR) {
11737         /* if already in DPTR then we need to push */
11738         if (AOP_TYPE(to) == AOP_DPTR) {
11739             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11740             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11741             if (options.model == MODEL_FLAT24)
11742                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11743             emitcode ("pop", "dph");
11744             emitcode ("pop", "dpl");        
11745         } else {
11746             _startLazyDPSEvaluation ();
11747             /* if this is remateriazable */
11748             if (AOP_TYPE (to) == AOP_IMMD) {
11749                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11750             } else {                    /* we need to get it byte by byte */
11751                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11752                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11753                 if (options.model == MODEL_FLAT24) {
11754                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11755                 }
11756             }
11757             _endLazyDPSEvaluation ();
11758         }
11759     }
11760     freeAsmop (to, NULL, ic, FALSE);
11761
11762     _G.dptrInUse = _G.dptr1InUse = 1;
11763     aopOp (count, ic->next->next, FALSE,FALSE);
11764     lbl =newiTempLabel(NULL);
11765
11766     /* now for the actual copy */
11767     if (AOP_TYPE(count) == AOP_LIT && 
11768         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11769         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11770         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11771         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11772         emitcode ("","!tlabeldef",lbl->key+100);
11773         emitcode ("movx", "a,@dptr");   /* read data from port */
11774         emitcode ("inc","dps");         /* switch to DPTR2 */
11775         emitcode ("movx", "@dptr,a");   /* save into location */
11776         emitcode ("inc", "dptr");       /* point to next area */
11777         emitcode ("dec","dps");         /* switch to DPTR */
11778         emitcode ("djnz","b,!tlabel",lbl->key+100);
11779         freeAsmop (count, NULL, ic, FALSE);
11780     } else {
11781         symbol *lbl1 = newiTempLabel(NULL);
11782         
11783         emitcode (";"," Auto increment but no djnz");
11784         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11785         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11786         freeAsmop (count, NULL, ic, FALSE);
11787         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11788         emitcode ("","!tlabeldef",lbl->key+100);
11789         emitcode ("movx", "a,@dptr");
11790         emitcode ("inc", "dptr");
11791         emitcode ("inc","dps");         /* switch to DPTR2 */
11792         emitcode ("movx", "@dptr,a");
11793         emitcode ("dec","dps");         /* switch to DPTR */
11794         emitcode ("mov","a,b");
11795         emitcode ("orl","a,_ap");
11796         emitcode ("jz","!tlabel",lbl1->key+100);
11797         emitcode ("mov","a,_ap");
11798         emitcode ("add","a,#!constbyte",0xFF);
11799         emitcode ("mov","_ap,a");
11800         emitcode ("mov","a,b");
11801         emitcode ("addc","a,#!constbyte",0xFF);
11802         emitcode ("mov","b,a");
11803         emitcode ("sjmp","!tlabel",lbl->key+100);
11804         emitcode ("","!tlabeldef",lbl1->key+100);
11805     }
11806     emitcode ("mov", "dps,#0"); 
11807     _G.dptrInUse = _G.dptr1InUse = 0;
11808     unsavermask(rsave);
11809
11810 }
11811
11812 /*-----------------------------------------------------------------*/
11813 /* genSwapW - swap lower & high order bytes                        */
11814 /*-----------------------------------------------------------------*/
11815 static void genSwapW(iCode *ic, int nparms, operand **parms)
11816 {
11817     operand *dest;
11818     operand *src;
11819     assert (nparms==1);
11820
11821     src = parms[0];
11822     dest=IC_RESULT(ic);
11823
11824     assert(getSize(operandType(src))==2);
11825
11826     aopOp (src, ic, FALSE, FALSE);
11827     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11828     _G.accInUse++;
11829     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11830     _G.accInUse--;
11831     freeAsmop (src, NULL, ic, FALSE);
11832     
11833     aopOp (dest,ic, FALSE, FALSE);
11834     aopPut(AOP(dest),"b",0);
11835     aopPut(AOP(dest),"a",1);
11836     freeAsmop (dest, NULL, ic, FALSE);    
11837 }
11838
11839 /*-----------------------------------------------------------------*/
11840 /* genMemsetX - gencode for memSetX data                           */
11841 /*-----------------------------------------------------------------*/
11842 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11843 {
11844     operand *to , *val , *count;
11845     symbol *lbl;
11846     char *l;
11847     int i;
11848     bitVect *rsave;
11849
11850     /* we know it has to be 3 parameters */
11851     assert (nparms == 3);
11852     
11853     to = parms[0];
11854     val = parms[1];
11855     count = parms[2];
11856         
11857     /* save DPTR if it needs to be saved */
11858     rsave = newBitVect(16);
11859     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11860             if (bitVectBitValue(ic->rMask,i))
11861                     rsave = bitVectSetBit(rsave,i);
11862     }
11863     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11864                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11865     savermask(rsave);
11866
11867     aopOp (to, ic, FALSE, FALSE);
11868     /* get "to" into DPTR */
11869     /* if the operand is already in dptr
11870        then we do nothing else we move the value to dptr */
11871     if (AOP_TYPE (to) != AOP_STR) {
11872         /* if already in DPTR then we need to push */
11873         if (AOP_TYPE(to) == AOP_DPTR) {
11874             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11875             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11876             if (options.model == MODEL_FLAT24)
11877                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11878             emitcode ("pop", "dph");
11879             emitcode ("pop", "dpl");        
11880         } else {
11881             _startLazyDPSEvaluation ();
11882             /* if this is remateriazable */
11883             if (AOP_TYPE (to) == AOP_IMMD) {
11884                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11885             } else {                    /* we need to get it byte by byte */
11886                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11887                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11888                 if (options.model == MODEL_FLAT24) {
11889                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11890                 }
11891             }
11892             _endLazyDPSEvaluation ();
11893         }
11894     }
11895     freeAsmop (to, NULL, ic, FALSE);
11896
11897     aopOp (val, ic->next->next, FALSE,FALSE);
11898     aopOp (count, ic->next->next, FALSE,FALSE);    
11899     lbl =newiTempLabel(NULL);
11900     /* now for the actual copy */
11901     if (AOP_TYPE(count) == AOP_LIT && 
11902         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11903         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11904         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11905         MOVA(l);
11906         emitcode ("","!tlabeldef",lbl->key+100);
11907         emitcode ("movx", "@dptr,a");
11908         emitcode ("inc", "dptr");
11909         emitcode ("djnz","b,!tlabel",lbl->key+100);
11910     } else {
11911         symbol *lbl1 = newiTempLabel(NULL);
11912         
11913         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11914         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11915         emitcode ("","!tlabeldef",lbl->key+100);
11916         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11917         emitcode ("movx", "@dptr,a");
11918         emitcode ("inc", "dptr");
11919         emitcode ("mov","a,b");
11920         emitcode ("orl","a,_ap");
11921         emitcode ("jz","!tlabel",lbl1->key+100);
11922         emitcode ("mov","a,_ap");
11923         emitcode ("add","a,#!constbyte",0xFF);
11924         emitcode ("mov","_ap,a");
11925         emitcode ("mov","a,b");
11926         emitcode ("addc","a,#!constbyte",0xFF);
11927         emitcode ("mov","b,a");
11928         emitcode ("sjmp","!tlabel",lbl->key+100);
11929         emitcode ("","!tlabeldef",lbl1->key+100);
11930     }
11931     freeAsmop (count, NULL, ic, FALSE);
11932     unsavermask(rsave);
11933 }
11934
11935 /*-----------------------------------------------------------------*/
11936 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11937 /*-----------------------------------------------------------------*/
11938 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11939 {
11940         bitVect *rsave ;
11941         operand *pnum, *result;
11942         int i;
11943     
11944         assert (nparms==1);
11945         /* save registers that need to be saved */
11946         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11947                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11948     
11949         pnum = parms[0]; 
11950         aopOp (pnum, ic, FALSE, FALSE);
11951         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11952         freeAsmop (pnum, NULL, ic, FALSE);
11953         emitcode ("lcall","NatLib_LoadPrimitive");
11954         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11955         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
11956             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11957                 for (i = (size-1) ; i >= 0 ; i-- ) {
11958                         emitcode ("push","a%s",javaRet[i]);
11959                 }
11960                 for (i=0; i < size ; i++ ) {
11961                         emitcode ("pop","a%s",
11962                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
11963                 }
11964         } else {
11965                 for (i = 0 ; i < size ; i++ ) {
11966                         aopPut(AOP(result),javaRet[i],i);
11967                 }
11968         }    
11969         freeAsmop (result, NULL, ic, FALSE);
11970         unsavermask(rsave);
11971 }
11972
11973 /*-----------------------------------------------------------------*/
11974 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
11975 /*-----------------------------------------------------------------*/
11976 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11977 {
11978         bitVect *rsave ;
11979         operand *pnum, *result;
11980         int size = 3;
11981         int i;
11982     
11983         assert (nparms==1);
11984         /* save registers that need to be saved */
11985         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11986                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11987     
11988         pnum = parms[0]; 
11989         aopOp (pnum, ic, FALSE, FALSE);
11990         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11991         freeAsmop (pnum, NULL, ic, FALSE);
11992         emitcode ("lcall","NatLib_LoadPointer");
11993         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11994         if (AOP_TYPE(result)!=AOP_STR) {
11995                 for (i = 0 ; i < size ; i++ ) {
11996                         aopPut(AOP(result),fReturn[i],i);
11997                 }
11998         }    
11999         freeAsmop (result, NULL, ic, FALSE);
12000         unsavermask(rsave);
12001 }
12002
12003 /*-----------------------------------------------------------------*/
12004 /* genNatLibInstallStateBlock -                                    */
12005 /*-----------------------------------------------------------------*/
12006 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
12007                                        operand **parms, const char *name)
12008 {
12009         bitVect *rsave ;
12010         operand *psb, *handle;
12011         assert (nparms==2);
12012
12013         /* save registers that need to be saved */
12014         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12015                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12016         psb = parms[0];
12017         handle = parms[1];
12018
12019         /* put pointer to state block into DPTR1 */
12020         aopOp (psb, ic, FALSE, FALSE);
12021         if (AOP_TYPE (psb) == AOP_IMMD) {
12022                 emitcode ("mov","dps,#1");
12023                 emitcode ("mov", "dptr,%s",
12024                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12025                 emitcode ("mov","dps,#0");
12026         } else {
12027                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12028                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12029                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12030         }
12031         freeAsmop (psb, NULL, ic, FALSE);
12032
12033         /* put libraryID into DPTR */
12034         emitcode ("mov","dptr,#LibraryID");
12035
12036         /* put handle into r3:r2 */
12037         aopOp (handle, ic, FALSE, FALSE);
12038         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12039                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12040                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12041                 emitcode ("pop","ar3");
12042                 emitcode ("pop","ar2");
12043         } else {        
12044                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12045                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12046         }
12047         freeAsmop (psb, NULL, ic, FALSE);
12048
12049         /* make the call */
12050         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12051
12052         /* put return value into place*/
12053         _G.accInUse++;
12054         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12055         _G.accInUse--;
12056         aopPut(AOP(IC_RESULT(ic)),"a",0);
12057         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12058         unsavermask(rsave);
12059 }
12060
12061 /*-----------------------------------------------------------------*/
12062 /* genNatLibRemoveStateBlock -                                     */
12063 /*-----------------------------------------------------------------*/
12064 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12065 {
12066         bitVect *rsave ;
12067
12068         assert(nparms==0);
12069
12070         /* save registers that need to be saved */
12071         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12072                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12073
12074         /* put libraryID into DPTR */
12075         emitcode ("mov","dptr,#LibraryID");
12076         /* make the call */
12077         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12078         unsavermask(rsave);
12079 }
12080
12081 /*-----------------------------------------------------------------*/
12082 /* genNatLibGetStateBlock -                                        */
12083 /*-----------------------------------------------------------------*/
12084 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12085                                    operand **parms,const char *name)
12086 {
12087         bitVect *rsave ;
12088         symbol *lbl = newiTempLabel(NULL);
12089         
12090         assert(nparms==0);
12091         /* save registers that need to be saved */
12092         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12093                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12094
12095         /* put libraryID into DPTR */
12096         emitcode ("mov","dptr,#LibraryID");
12097         /* make the call */
12098         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12099         emitcode ("jnz","!tlabel",lbl->key+100);
12100
12101         /* put return value into place */
12102         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12103         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12104                 emitcode ("push","ar3");
12105                 emitcode ("push","ar2");
12106                 emitcode ("pop","%s",
12107                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12108                 emitcode ("pop","%s",
12109                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12110         } else {
12111                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12112                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12113         }
12114         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12115         emitcode ("","!tlabeldef",lbl->key+100);
12116         unsavermask(rsave);
12117 }
12118
12119 /*-----------------------------------------------------------------*/
12120 /* genMMMalloc -                                                   */
12121 /*-----------------------------------------------------------------*/
12122 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12123                          int size, const char *name)
12124 {
12125         bitVect *rsave ;
12126         operand *bsize;
12127         symbol *rsym;
12128         symbol *lbl = newiTempLabel(NULL);
12129
12130         assert (nparms == 1);
12131         /* save registers that need to be saved */
12132         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12133                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12134         
12135         bsize=parms[0];
12136         aopOp (bsize,ic,FALSE,FALSE);
12137
12138         /* put the size in R4-R2 */
12139         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12140                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12141                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12142                 if (size==3) {
12143                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12144                         emitcode("pop","ar4");
12145                 }
12146                 emitcode("pop","ar3");
12147                 emitcode("pop","ar2");          
12148         } else {
12149                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12150                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12151                 if (size==3) {
12152                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12153                 }
12154         }
12155         freeAsmop (bsize, NULL, ic, FALSE);
12156
12157         /* make the call */
12158         emitcode ("lcall","MM_%s",name);
12159         emitcode ("jz","!tlabel",lbl->key+100);
12160         emitcode ("mov","r2,#!constbyte",0xff);
12161         emitcode ("mov","r3,#!constbyte",0xff);
12162         emitcode ("","!tlabeldef",lbl->key+100);
12163         /* we don't care about the pointer : we just save the handle */
12164         rsym = OP_SYMBOL(IC_RESULT(ic));
12165         if (rsym->liveFrom != rsym->liveTo) {
12166                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12167                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12168                         emitcode ("push","ar3");
12169                         emitcode ("push","ar2");
12170                         emitcode ("pop","%s",
12171                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12172                         emitcode ("pop","%s",
12173                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12174                 } else {
12175                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12176                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12177                 }
12178                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12179         }
12180         unsavermask(rsave);
12181 }
12182
12183 /*-----------------------------------------------------------------*/
12184 /* genMMDeref -                                                    */
12185 /*-----------------------------------------------------------------*/
12186 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12187 {
12188         bitVect *rsave ;
12189         operand *handle;
12190
12191         assert (nparms == 1);
12192         /* save registers that need to be saved */
12193         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12194                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12195         
12196         handle=parms[0];
12197         aopOp (handle,ic,FALSE,FALSE);
12198
12199         /* put the size in R4-R2 */
12200         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12201                 emitcode("push","%s",
12202                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12203                 emitcode("push","%s",
12204                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12205                 emitcode("pop","ar3");
12206                 emitcode("pop","ar2");          
12207         } else {
12208                 emitcode ("mov","r2,%s",
12209                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12210                 emitcode ("mov","r3,%s",
12211                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12212         }
12213         freeAsmop (handle, NULL, ic, FALSE);
12214
12215         /* make the call */
12216         emitcode ("lcall","MM_Deref");
12217         
12218         {
12219                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12220                 if (rsym->liveFrom != rsym->liveTo) {                   
12221                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12222                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12223                             _startLazyDPSEvaluation ();
12224                             
12225                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12226                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12227                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12228
12229                             _endLazyDPSEvaluation ();
12230                             
12231                         }
12232                 }
12233         }
12234         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12235         unsavermask(rsave);
12236 }
12237
12238 /*-----------------------------------------------------------------*/
12239 /* genMMUnrestrictedPersist -                                      */
12240 /*-----------------------------------------------------------------*/
12241 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12242 {
12243         bitVect *rsave ;
12244         operand *handle;
12245
12246         assert (nparms == 1);
12247         /* save registers that need to be saved */
12248         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12249                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12250         
12251         handle=parms[0];
12252         aopOp (handle,ic,FALSE,FALSE);
12253
12254         /* put the size in R3-R2 */
12255         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12256                 emitcode("push","%s",
12257                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12258                 emitcode("push","%s",
12259                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12260                 emitcode("pop","ar3");
12261                 emitcode("pop","ar2");          
12262         } else {
12263                 emitcode ("mov","r2,%s",
12264                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12265                 emitcode ("mov","r3,%s",
12266                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12267         }
12268         freeAsmop (handle, NULL, ic, FALSE);
12269
12270         /* make the call */
12271         emitcode ("lcall","MM_UnrestrictedPersist");
12272
12273         {
12274                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12275                 if (rsym->liveFrom != rsym->liveTo) {   
12276                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12277                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12278                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12279                 }
12280         }
12281         unsavermask(rsave);
12282 }
12283
12284 /*-----------------------------------------------------------------*/
12285 /* genSystemExecJavaProcess -                                      */
12286 /*-----------------------------------------------------------------*/
12287 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12288 {
12289         bitVect *rsave ;
12290         operand *handle, *pp;
12291
12292         assert (nparms==2);
12293         /* save registers that need to be saved */
12294         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12295                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12296         
12297         pp = parms[0];
12298         handle = parms[1];
12299         
12300         /* put the handle in R3-R2 */
12301         aopOp (handle,ic,FALSE,FALSE);
12302         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12303                 emitcode("push","%s",
12304                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12305                 emitcode("push","%s",
12306                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12307                 emitcode("pop","ar3");
12308                 emitcode("pop","ar2");          
12309         } else {
12310                 emitcode ("mov","r2,%s",
12311                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12312                 emitcode ("mov","r3,%s",
12313                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12314         }
12315         freeAsmop (handle, NULL, ic, FALSE);
12316         
12317         /* put pointer in DPTR */
12318         aopOp (pp,ic,FALSE,FALSE);
12319         if (AOP_TYPE(pp) == AOP_IMMD) {
12320                 emitcode ("mov", "dptr,%s",
12321                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12322         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12323                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12324                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12325                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12326         }
12327         freeAsmop (handle, NULL, ic, FALSE);
12328
12329         /* make the call */
12330         emitcode ("lcall","System_ExecJavaProcess");
12331         
12332         /* put result in place */
12333         {
12334                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12335                 if (rsym->liveFrom != rsym->liveTo) {   
12336                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12337                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12338                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12339                 }
12340         }
12341         
12342         unsavermask(rsave);
12343 }
12344
12345 /*-----------------------------------------------------------------*/
12346 /* genSystemRTCRegisters -                                         */
12347 /*-----------------------------------------------------------------*/
12348 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12349                                   char *name)
12350 {
12351         bitVect *rsave ;
12352         operand *pp;
12353
12354         assert (nparms==1);
12355         /* save registers that need to be saved */
12356         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12357                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12358         
12359         pp=parms[0];
12360         /* put pointer in DPTR */
12361         aopOp (pp,ic,FALSE,FALSE);
12362         if (AOP_TYPE (pp) == AOP_IMMD) {
12363                 emitcode ("mov","dps,#1");
12364                 emitcode ("mov", "dptr,%s", 
12365                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12366                 emitcode ("mov","dps,#0");
12367         } else {
12368                 emitcode ("mov","dpl1,%s",
12369                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12370                 emitcode ("mov","dph1,%s",
12371                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12372                 emitcode ("mov","dpx1,%s",
12373                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12374         }
12375         freeAsmop (pp, NULL, ic, FALSE);
12376
12377         /* make the call */
12378         emitcode ("lcall","System_%sRTCRegisters",name);
12379
12380         unsavermask(rsave);
12381 }
12382
12383 /*-----------------------------------------------------------------*/
12384 /* genSystemThreadSleep -                                          */
12385 /*-----------------------------------------------------------------*/
12386 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12387 {
12388         bitVect *rsave ;
12389         operand *to, *s;
12390
12391         assert (nparms==1);
12392         /* save registers that need to be saved */
12393         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12394                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12395
12396         to = parms[0];
12397         aopOp(to,ic,FALSE,FALSE);
12398         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12399             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12400                 emitcode ("push","%s",
12401                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12402                 emitcode ("push","%s",
12403                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12404                 emitcode ("push","%s",
12405                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12406                 emitcode ("push","%s",
12407                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12408                 emitcode ("pop","ar3");
12409                 emitcode ("pop","ar2");
12410                 emitcode ("pop","ar1");
12411                 emitcode ("pop","ar0");
12412         } else {
12413                 emitcode ("mov","r0,%s",
12414                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12415                 emitcode ("mov","r1,%s",
12416                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12417                 emitcode ("mov","r2,%s",
12418                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12419                 emitcode ("mov","r3,%s",
12420                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12421         }
12422         freeAsmop (to, NULL, ic, FALSE);
12423
12424         /* suspend in acc */
12425         s = parms[1];
12426         aopOp(s,ic,FALSE,FALSE);
12427         emitcode ("mov","a,%s",
12428                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12429         freeAsmop (s, NULL, ic, FALSE);
12430
12431         /* make the call */
12432         emitcode ("lcall","System_%s",name);
12433
12434         unsavermask(rsave);
12435 }
12436
12437 /*-----------------------------------------------------------------*/
12438 /* genSystemThreadResume -                                         */
12439 /*-----------------------------------------------------------------*/
12440 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12441 {
12442         bitVect *rsave ;
12443         operand *tid,*pid;
12444
12445         assert (nparms==2);
12446         /* save registers that need to be saved */
12447         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12448                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12449         
12450         tid = parms[0];
12451         pid = parms[1];
12452         
12453         /* PID in R0 */
12454         aopOp(pid,ic,FALSE,FALSE);
12455         emitcode ("mov","r0,%s",
12456                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12457         freeAsmop (pid, NULL, ic, FALSE);
12458         
12459         /* tid into ACC */
12460         aopOp(tid,ic,FALSE,FALSE);
12461         emitcode ("mov","a,%s",
12462                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12463         freeAsmop (tid, NULL, ic, FALSE);
12464         
12465         emitcode ("lcall","System_ThreadResume");
12466
12467         /* put result into place */
12468         {
12469                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12470                 if (rsym->liveFrom != rsym->liveTo) {   
12471                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12472                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12473                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12474                 }
12475         }
12476         unsavermask(rsave);
12477 }
12478
12479 /*-----------------------------------------------------------------*/
12480 /* genSystemProcessResume -                                        */
12481 /*-----------------------------------------------------------------*/
12482 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12483 {
12484         bitVect *rsave ;
12485         operand *pid;
12486
12487         assert (nparms==1);
12488         /* save registers that need to be saved */
12489         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12490                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12491         
12492         pid = parms[0];
12493         
12494         /* pid into ACC */
12495         aopOp(pid,ic,FALSE,FALSE);
12496         emitcode ("mov","a,%s",
12497                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12498         freeAsmop (pid, NULL, ic, FALSE);
12499         
12500         emitcode ("lcall","System_ProcessResume");
12501
12502         unsavermask(rsave);
12503 }
12504
12505 /*-----------------------------------------------------------------*/
12506 /* genSystem -                                                     */
12507 /*-----------------------------------------------------------------*/
12508 static void genSystem (iCode *ic,int nparms,char *name)
12509 {
12510         assert(nparms == 0);
12511
12512         emitcode ("lcall","System_%s",name);
12513 }
12514
12515 /*-----------------------------------------------------------------*/
12516 /* genSystemPoll -                                                  */
12517 /*-----------------------------------------------------------------*/
12518 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12519 {
12520         bitVect *rsave ;
12521         operand *fp;
12522
12523         assert (nparms==1);
12524         /* save registers that need to be saved */
12525         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12526                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12527
12528         fp = parms[0];
12529         aopOp (fp,ic,FALSE,FALSE);
12530         if (AOP_TYPE (fp) == AOP_IMMD) {
12531                 emitcode ("mov", "dptr,%s", 
12532                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12533         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12534                 emitcode ("mov","dpl,%s",
12535                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12536                 emitcode ("mov","dph,%s",
12537                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12538                 emitcode ("mov","dpx,%s",
12539                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12540         }
12541         freeAsmop (fp, NULL, ic, FALSE);
12542
12543         emitcode ("lcall","System_%sPoll",name);
12544
12545         /* put result into place */
12546         {
12547                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12548                 if (rsym->liveFrom != rsym->liveTo) {   
12549                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12550                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12551                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12552                 }
12553         }
12554         unsavermask(rsave);
12555 }
12556
12557 /*-----------------------------------------------------------------*/
12558 /* genSystemGetCurrentID -                                         */
12559 /*-----------------------------------------------------------------*/
12560 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12561 {
12562         assert (nparms==0);
12563
12564         emitcode ("lcall","System_GetCurrent%sId",name);
12565         /* put result into place */
12566         {
12567                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12568                 if (rsym->liveFrom != rsym->liveTo) {   
12569                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12570                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12571                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12572                 }
12573         }
12574 }
12575
12576 /*-----------------------------------------------------------------*/
12577 /* genBuiltIn - calls the appropriate function to  generating code */
12578 /* for a built in function                                         */
12579 /*-----------------------------------------------------------------*/
12580 static void genBuiltIn (iCode *ic)
12581 {
12582         operand *bi_parms[MAX_BUILTIN_ARGS];
12583         int nbi_parms;
12584         iCode *bi_iCode;
12585         symbol *bif;
12586
12587         /* get all the arguments for a built in function */
12588         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12589
12590         /* which function is it */
12591         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12592         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12593                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12594         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12595                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12596         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12597                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12598         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12599                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12600         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12601                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12602         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12603                 genInp(bi_iCode,nbi_parms,bi_parms);
12604         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12605                 genOutp(bi_iCode,nbi_parms,bi_parms);
12606         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12607                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12608                 /* JavaNative builtIns */               
12609         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12610                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12611         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12612                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12613         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12614                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12615         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12616                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12617         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12618                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12619         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12620                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12621         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12622                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12623         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12624                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12625         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12626                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12627         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12628                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12629         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12630                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12631         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12632                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12633         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12634                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12635         } else if (strcmp(bif->name,"MM_Free")==0) {
12636                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12637         } else if (strcmp(bif->name,"MM_Deref")==0) {
12638                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12639         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12640                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12641         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12642                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12643         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12644                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12645         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12646                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12647         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12648                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12649         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12650                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12651         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12652                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12653         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12654                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12655         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12656                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12657         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12658                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12659         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12660                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12661         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12662                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12663         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12664                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12665         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12666                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12667         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12668                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12669         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12670                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12671         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12672                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12673         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12674                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12675         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12676                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12677         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12678                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12679         } else {
12680                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12681                 return ;
12682         }
12683         return ;    
12684 }
12685
12686 /*-----------------------------------------------------------------*/
12687 /* gen390Code - generate code for Dallas 390 based controllers     */
12688 /*-----------------------------------------------------------------*/
12689 void
12690 gen390Code (iCode * lic)
12691 {
12692   iCode *ic;
12693   int cln = 0;
12694
12695   lineHead = lineCurr = NULL;
12696   dptrn[1][0] = "dpl1";
12697   dptrn[1][1] = "dph1";
12698   dptrn[1][2] = "dpx1";
12699   
12700   if (options.model == MODEL_FLAT24) {
12701     fReturnSizeDS390 = 5;
12702     fReturn = fReturn24;
12703   } else {
12704     fReturnSizeDS390 = 4;
12705     fReturn = fReturn16;
12706     options.stack10bit=0;
12707   }
12708 #if 1
12709   /* print the allocation information */
12710   if (allocInfo && currFunc)
12711     printAllocInfo (currFunc, codeOutFile);
12712 #endif
12713   /* if debug information required */
12714   if (options.debug && currFunc)
12715     {
12716       debugFile->writeFunction(currFunc);
12717       _G.debugLine = 1;
12718       if (IS_STATIC (currFunc->etype))
12719         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12720       else
12721         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12722       _G.debugLine = 0;
12723     }
12724   /* stack pointer name */
12725   if (options.useXstack)
12726     spname = "_spx";
12727   else
12728     spname = "sp";
12729
12730
12731   for (ic = lic; ic; ic = ic->next)
12732     {
12733
12734       if (ic->lineno && cln != ic->lineno)
12735         {
12736           if (options.debug)
12737             {
12738               _G.debugLine = 1;
12739               emitcode ("", "C$%s$%d$%d$%d ==.",
12740                         FileBaseName (ic->filename), ic->lineno,
12741                         ic->level, ic->block);
12742               _G.debugLine = 0;
12743             }
12744           if (!options.noCcodeInAsm) {
12745             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
12746                       printCLine(ic->filename, ic->lineno));
12747           }
12748           cln = ic->lineno;
12749         }
12750       if (options.iCodeInAsm) {
12751         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12752       }
12753       /* if the result is marked as
12754          spilt and rematerializable or code for
12755          this has already been generated then
12756          do nothing */
12757       if (resultRemat (ic) || ic->generated)
12758         continue;
12759
12760       /* depending on the operation */
12761       switch (ic->op)
12762         {
12763         case '!':
12764           genNot (ic);
12765           break;
12766
12767         case '~':
12768           genCpl (ic);
12769           break;
12770
12771         case UNARYMINUS:
12772           genUminus (ic);
12773           break;
12774
12775         case IPUSH:
12776           genIpush (ic);
12777           break;
12778
12779         case IPOP:
12780           /* IPOP happens only when trying to restore a
12781              spilt live range, if there is an ifx statement
12782              following this pop then the if statement might
12783              be using some of the registers being popped which
12784              would destory the contents of the register so
12785              we need to check for this condition and handle it */
12786           if (ic->next &&
12787               ic->next->op == IFX &&
12788               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12789             genIfx (ic->next, ic);
12790           else
12791             genIpop (ic);
12792           break;
12793
12794         case CALL:
12795           genCall (ic);
12796           break;
12797
12798         case PCALL:
12799           genPcall (ic);
12800           break;
12801
12802         case FUNCTION:
12803           genFunction (ic);
12804           break;
12805
12806         case ENDFUNCTION:
12807           genEndFunction (ic);
12808           break;
12809
12810         case RETURN:
12811           genRet (ic);
12812           break;
12813
12814         case LABEL:
12815           genLabel (ic);
12816           break;
12817
12818         case GOTO:
12819           genGoto (ic);
12820           break;
12821
12822         case '+':
12823           genPlus (ic);
12824           break;
12825
12826         case '-':
12827           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12828             genMinus (ic);
12829           break;
12830
12831         case '*':
12832           genMult (ic);
12833           break;
12834
12835         case '/':
12836           genDiv (ic);
12837           break;
12838
12839         case '%':
12840           genMod (ic);
12841           break;
12842
12843         case '>':
12844           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12845           break;
12846
12847         case '<':
12848           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12849           break;
12850
12851         case LE_OP:
12852         case GE_OP:
12853         case NE_OP:
12854
12855           /* note these two are xlated by algebraic equivalence
12856              during parsing SDCC.y */
12857           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12858                   "got '>=' or '<=' shouldn't have come here");
12859           break;
12860
12861         case EQ_OP:
12862           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12863           break;
12864
12865         case AND_OP:
12866           genAndOp (ic);
12867           break;
12868
12869         case OR_OP:
12870           genOrOp (ic);
12871           break;
12872
12873         case '^':
12874           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12875           break;
12876
12877         case '|':
12878           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12879           break;
12880
12881         case BITWISEAND:
12882           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12883           break;
12884
12885         case INLINEASM:
12886           genInline (ic);
12887           break;
12888
12889         case RRC:
12890           genRRC (ic);
12891           break;
12892
12893         case RLC:
12894           genRLC (ic);
12895           break;
12896
12897         case GETHBIT:
12898           genGetHbit (ic);
12899           break;
12900
12901         case LEFT_OP:
12902           genLeftShift (ic);
12903           break;
12904
12905         case RIGHT_OP:
12906           genRightShift (ic);
12907           break;
12908
12909         case GET_VALUE_AT_ADDRESS:
12910           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12911           break;
12912
12913         case '=':
12914           if (POINTER_SET (ic))
12915             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12916           else
12917             genAssign (ic);
12918           break;
12919
12920         case IFX:
12921           genIfx (ic, NULL);
12922           break;
12923
12924         case ADDRESS_OF:
12925           genAddrOf (ic);
12926           break;
12927
12928         case JUMPTABLE:
12929           genJumpTab (ic);
12930           break;
12931
12932         case CAST:
12933           genCast (ic);
12934           break;
12935
12936         case RECEIVE:
12937           genReceive (ic);
12938           break;
12939
12940         case SEND:
12941           if (ic->builtinSEND) genBuiltIn(ic);
12942           else addSet (&_G.sendSet, ic);
12943           break;
12944
12945         case ARRAYINIT:
12946             genArrayInit(ic);
12947             break;
12948             
12949         default:
12950           ic = ic;
12951         }
12952     }
12953
12954
12955   /* now we are ready to call the
12956      peep hole optimizer */
12957   if (!options.nopeep)
12958     peepHole (&lineHead);
12959
12960   /* now do the actual printing */
12961   printLine (lineHead, codeOutFile);
12962   return;
12963 }