* src/ds390/gen.c (operandsEqu): fixed a little typo, that prevented
[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 /* leftRightUseAcc - returns size of accumulator use by operands   */
443 /*-----------------------------------------------------------------*/
444 static int
445 leftRightUseAcc(iCode *ic)
446 {
447   operand *op;
448   int size;
449   int accuseSize = 0;
450   int accuse = 0;
451   
452   if (!ic)
453     {
454       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
455               "null iCode pointer");
456       return 0;
457     }
458
459   if (ic->op == IFX)
460     {
461       op = IC_COND (ic);
462       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
463         {
464           accuse = 1;
465           size = getSize (OP_SYMBOL (op)->type);
466           if (size>accuseSize)
467             accuseSize = size;
468         }
469     }
470   else if (ic->op == JUMPTABLE)
471     {
472       op = IC_JTCOND (ic);
473       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
474         {
475           accuse = 1;
476           size = getSize (OP_SYMBOL (op)->type);
477           if (size>accuseSize)
478             accuseSize = size;
479         }
480     }
481   else
482     {
483       op = IC_LEFT (ic);
484       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
485         {
486           accuse = 1;
487           size = getSize (OP_SYMBOL (op)->type);
488           if (size>accuseSize)
489             accuseSize = size;
490         }
491       op = IC_RIGHT (ic);
492       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
493         {
494           accuse = 1;
495           size = getSize (OP_SYMBOL (op)->type);
496           if (size>accuseSize)
497             accuseSize = size;
498         }
499     }
500   
501   if (accuseSize)
502     return accuseSize;
503   else
504     return accuse;
505 }
506
507 /*-----------------------------------------------------------------*/
508 /* aopForSym - for a true symbol                                   */
509 /*-----------------------------------------------------------------*/
510 static asmop *
511 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
512 {
513   asmop *aop;
514   memmap *space = SPEC_OCLS (sym->etype);
515   int accuse = leftRightUseAcc (ic);
516
517   /* if already has one */
518   if (sym->aop)
519     {
520       if ((sym->aop->type == AOP_DPTR && useDP2)
521           || (sym->aop->type == AOP_DPTR2 && !useDP2))
522         sym->aop = NULL;
523       else
524         return sym->aop;
525     }
526
527   /* assign depending on the storage class */
528   /* if it is on the stack or indirectly addressable */
529   /* space we need to assign either r0 or r1 to it   */
530   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
531     {
532       sym->aop = aop = newAsmop (0);
533       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
534       aop->size = getSize (sym->type);
535
536       /* now assign the address of the variable to
537          the pointer register */
538       if (aop->type != AOP_STK)
539         {
540
541           if (sym->onStack)
542             {
543               if (_G.accInUse || accuse)
544                 emitcode ("push", "acc");
545
546               if (_G.bInUse || (accuse>1))
547                 emitcode ("push", "b");
548
549               emitcode ("mov", "a,_bp");
550               emitcode ("add", "a,#!constbyte",
551                         ((sym->stack < 0) ?
552                          ((char) (sym->stack - _G.nRegsSaved)) :
553                          ((char) sym->stack)) & 0xff);
554               emitcode ("mov", "%s,a",
555                         aop->aopu.aop_ptr->name);
556
557               if (_G.bInUse || (accuse>1))
558                 emitcode ("pop", "b");
559
560               if (_G.accInUse || accuse)
561                 emitcode ("pop", "acc");
562             }
563           else
564             emitcode ("mov", "%s,#%s",
565                       aop->aopu.aop_ptr->name,
566                       sym->rname);
567           aop->paged = space->paged;
568         }
569       else
570         aop->aopu.aop_stk = sym->stack;
571       return aop;
572     }
573
574   if (sym->onStack && options.stack10bit)
575     {
576         short stack_val = -((sym->stack < 0) ?
577                             ((short) (sym->stack - _G.nRegsSaved)) :
578                             ((short) sym->stack)) ;
579         if (useDP2 && _G.dptr1InUse) {
580             emitcode ("push","dpl1");
581             emitcode ("push","dph1");
582             emitcode ("push","dpx1");
583         } else if (_G.dptrInUse ) {
584             emitcode ("push","dpl");
585             emitcode ("push","dph");
586             emitcode ("push","dpx");
587         }
588       /* It's on the 10 bit stack, which is located in
589        * far data space.
590        */           
591         if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
592             if (useDP2) {
593                 if (options.model == MODEL_FLAT24)
594                 {
595                     emitcode ("mov", "dpx1,#!constbyte",
596                               (options.stack_loc >> 16) & 0xff);
597                 }
598                 emitcode ("mov", "dph1,_bpx+1");
599                 
600                 emitcode ("mov", "dpl1,_bpx");
601                 emitcode ("mov","dps,#1");
602             } else {
603                 if (options.model == MODEL_FLAT24)
604                 {
605                     emitcode ("mov", "dpx,#!constbyte",
606                               (options.stack_loc >> 16) & 0xff);
607                 }
608                 emitcode ("mov", "dph,_bpx+1");
609                 emitcode ("mov", "dpl,_bpx");
610             }
611             stack_val = -stack_val;
612             while (stack_val--) {
613                 emitcode ("inc","dptr");
614             }
615             if (useDP2) {
616                 emitcode("mov","dps,#0");
617             }
618         }  else {
619             if (_G.accInUse || accuse)
620                 emitcode ("push", "acc");
621             
622             if (_G.bInUse || (accuse>1))
623                 emitcode ("push", "b");
624         
625             emitcode ("mov", "a,_bpx");
626             emitcode ("clr","c");
627             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
628             emitcode ("mov","b,a");
629             emitcode ("mov","a,_bpx+1");
630             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
631             if (useDP2) {
632                 if (options.model == MODEL_FLAT24)
633                 {
634                     emitcode ("mov", "dpx1,#!constbyte",
635                               (options.stack_loc >> 16) & 0xff);
636                 }
637                 emitcode ("mov", "dph1,a");
638                 emitcode ("mov", "dpl1,b");
639             } else {
640                 if (options.model == MODEL_FLAT24)
641                 {
642                     emitcode ("mov", "dpx,#!constbyte",
643                               (options.stack_loc >> 16) & 0xff);
644                 }
645                 emitcode ("mov", "dph,a");
646                 emitcode ("mov", "dpl,b");
647             }
648             
649             if (_G.bInUse || (accuse>1))
650                 emitcode ("pop", "b");
651             
652             if (_G.accInUse || accuse)
653                 emitcode ("pop", "acc");
654         }
655         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
656         aop->size = getSize (sym->type);
657         return aop;
658     }
659
660   /* if in bit space */
661   if (IN_BITSPACE (space))
662     {
663       sym->aop = aop = newAsmop (AOP_CRY);
664       aop->aopu.aop_dir = sym->rname;
665       aop->size = getSize (sym->type);
666       return aop;
667     }
668   /* if it is in direct space */
669   if (IN_DIRSPACE (space))
670     {
671       sym->aop = aop = newAsmop (AOP_DIR);
672       aop->aopu.aop_dir = sym->rname;
673       aop->size = getSize (sym->type);
674       return aop;
675     }
676
677   /* special case for a function */
678   if (IS_FUNC (sym->type) && !(sym->isitmp))
679     {
680       sym->aop = aop = newAsmop (AOP_IMMD);
681       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
682       aop->size = FPTRSIZE;
683       return aop;
684     }
685
686   /* only remaining is far space */
687   /* in which case DPTR gets the address */
688   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
689   if (useDP2)
690     {
691       genSetDPTR (1);
692       _flushLazyDPS ();
693       emitcode ("mov", "dptr,#%s", sym->rname);
694       genSetDPTR (0);
695     }
696   else
697     {
698       emitcode ("mov", "dptr,#%s", sym->rname);
699     }
700   aop->size = getSize (sym->type);
701
702   /* if it is in code space */
703   if (IN_CODESPACE (space))
704     aop->code = 1;
705
706   return aop;
707 }
708
709 /*-----------------------------------------------------------------*/
710 /* aopForRemat - rematerialzes an object                           */
711 /*-----------------------------------------------------------------*/
712 static asmop *
713 aopForRemat (symbol * sym)
714 {
715   iCode *ic = sym->rematiCode;
716   asmop *aop = newAsmop (AOP_IMMD);
717   int ptr_type =0;
718   int val = 0;
719
720   for (;;)
721     {
722       if (ic->op == '+')
723         val += (int) operandLitValue (IC_RIGHT (ic));
724       else if (ic->op == '-')
725         val -= (int) operandLitValue (IC_RIGHT (ic));
726       else if (IS_CAST_ICODE(ic)) {
727               sym_link *from_type = operandType(IC_RIGHT(ic));
728               aop->aopu.aop_immd.from_cast_remat = 1;
729               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
730               ptr_type = DCL_TYPE(from_type);
731               if (ptr_type == IPOINTER) {
732                 // bug #481053
733                 ptr_type = POINTER;
734               }
735               continue ;
736       } else break;
737       
738       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
739     }
740
741   if (val)
742   {
743       SNPRINTF (buffer, sizeof(buffer),
744                 "(%s %c 0x%04x)",
745                 OP_SYMBOL (IC_LEFT (ic))->rname,
746                 val >= 0 ? '+' : '-',
747                 abs (val) & 0xffffff);
748   }
749   else 
750   {
751       if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
752       {
753           SNPRINTF(buffer, sizeof(buffer), 
754                    "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
755       }
756       else
757       {
758           strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
759       }
760   }
761
762   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);  
763   /* set immd2 field if required */
764   if (aop->aopu.aop_immd.from_cast_remat) 
765   {
766       tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
767       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
768   }
769
770   return aop;
771 }
772
773 /*-----------------------------------------------------------------*/
774 /* aopHasRegs - returns true if aop has regs between from-to       */
775 /*-----------------------------------------------------------------*/
776 static int aopHasRegs(asmop *aop, int from, int to)
777 {
778     int size =0;
779
780     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
781
782     for (; size < aop->size ; size++) {
783         int reg;
784         for (reg = from ; reg <= to ; reg++)
785             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
786     }
787     return 0;
788 }
789
790 /*-----------------------------------------------------------------*/
791 /* regsInCommon - two operands have some registers in common       */
792 /*-----------------------------------------------------------------*/
793 static bool
794 regsInCommon (operand * op1, operand * op2)
795 {
796   symbol *sym1, *sym2;
797   int i;
798
799   /* if they have registers in common */
800   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
801     return FALSE;
802
803   sym1 = OP_SYMBOL (op1);
804   sym2 = OP_SYMBOL (op2);
805
806   if (sym1->nRegs == 0 || sym2->nRegs == 0)
807     return FALSE;
808
809   for (i = 0; i < sym1->nRegs; i++)
810     {
811       int j;
812       if (!sym1->regs[i])
813         continue;
814
815       for (j = 0; j < sym2->nRegs; j++)
816         {
817           if (!sym2->regs[j])
818             continue;
819
820           if (sym2->regs[j] == sym1->regs[i])
821             return TRUE;
822         }
823     }
824
825   return FALSE;
826 }
827
828 /*-----------------------------------------------------------------*/
829 /* operandsEqu - equivalent                                        */
830 /*-----------------------------------------------------------------*/
831 static bool
832 operandsEqu (operand * op1, operand * op2)
833 {
834   symbol *sym1, *sym2;
835
836   /* if they not symbols */
837   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
838     return FALSE;
839
840   sym1 = OP_SYMBOL (op1);
841   sym2 = OP_SYMBOL (op2);
842
843   /* if both are itemps & one is spilt
844      and the other is not then false */
845   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
846       sym1->isspilt != sym2->isspilt)
847     return FALSE;
848
849   /* if they are the same */
850   if (sym1 == sym2)
851     return TRUE;
852
853   if (strcmp (sym1->rname, sym2->rname) == 0)
854     return TRUE;
855
856
857   /* if left is a tmp & right is not */
858   if (IS_ITEMP (op1) &&
859       !IS_ITEMP (op2) &&
860       sym1->isspilt &&
861       (sym1->usl.spillLoc == sym2))
862     return TRUE;
863
864   if (IS_ITEMP (op2) &&
865       !IS_ITEMP (op1) &&
866       sym2->isspilt &&
867       sym1->level > 0 &&
868       (sym2->usl.spillLoc == sym1))
869     return TRUE;
870
871   /* are they spilt to the same location */
872   if (IS_ITEMP (op2) &&
873       IS_ITEMP (op1) &&
874       sym2->isspilt &&
875       sym1->isspilt &&
876       (sym1->usl.spillLoc == sym2->usl.spillLoc))
877     return TRUE;
878     
879   return FALSE;
880 }
881
882 /*-----------------------------------------------------------------*/
883 /* sameRegs - two asmops have the same registers                   */
884 /*-----------------------------------------------------------------*/
885 static bool
886 sameRegs (asmop * aop1, asmop * aop2)
887 {
888   int i;
889
890   if (aop1 == aop2)
891     {
892       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
893         {
894           return FALSE;
895         }
896       return TRUE;
897     }
898
899   if (aop1->type != AOP_REG ||
900       aop2->type != AOP_REG)
901     return FALSE;
902
903   if (aop1->size != aop2->size)
904     return FALSE;
905
906   for (i = 0; i < aop1->size; i++)
907     if (aop1->aopu.aop_reg[i] !=
908         aop2->aopu.aop_reg[i])
909       return FALSE;
910
911   return TRUE;
912 }
913
914 /*-----------------------------------------------------------------*/
915 /* aopOp - allocates an asmop for an operand  :                    */
916 /*-----------------------------------------------------------------*/
917 static void
918 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
919 {
920   asmop *aop;
921   symbol *sym;
922   int i;
923
924   if (!op)
925     return;
926
927   /* if this a literal */
928   if (IS_OP_LITERAL (op))
929     {
930       op->aop = aop = newAsmop (AOP_LIT);
931       aop->aopu.aop_lit = op->operand.valOperand;
932       aop->size = getSize (operandType (op));
933       return;
934     }
935
936   /* if already has a asmop then continue */
937   if (op->aop)
938     {
939       if ((op->aop->type == AOP_DPTR && useDP2)
940           || (op->aop->type == AOP_DPTR2 && !useDP2))
941         op->aop = NULL;
942       else
943         return;
944     }
945
946   /* if the underlying symbol has a aop */
947   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
948     {
949       op->aop = OP_SYMBOL (op)->aop;
950       if ((op->aop->type == AOP_DPTR && useDP2)
951           || (op->aop->type == AOP_DPTR2 && !useDP2))
952         op->aop = NULL;
953       else
954         return;
955     }
956
957   /* if this is a true symbol */
958   if (IS_TRUE_SYMOP (op))
959     {
960       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
961       return;
962     }
963
964   /* this is a temporary : this has
965      only four choices :
966      a) register
967      b) spillocation
968      c) rematerialize
969      d) conditional
970      e) can be a return use only */
971
972   sym = OP_SYMBOL (op);
973
974
975   /* if the type is a conditional */
976   if (sym->regType == REG_CND)
977     {
978       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
979       aop->size = 0;
980       return;
981     }
982
983   /* if it is spilt then two situations
984      a) is rematerialize
985      b) has a spill location */
986   if (sym->isspilt || sym->nRegs == 0)
987     {
988
989       /* rematerialize it NOW */
990       if (sym->remat)
991         {
992           sym->aop = op->aop = aop =
993             aopForRemat (sym);
994           aop->size = getSize (sym->type);
995           return;
996         }
997
998       if (sym->accuse)
999         {
1000           int i;
1001           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1002           aop->size = getSize (sym->type);
1003           for (i = 0; i < 2; i++)
1004             aop->aopu.aop_str[i] = accUse[i];
1005           return;
1006         }
1007
1008       if (sym->ruonly)
1009         {
1010           int i;
1011
1012           if (useDP2)
1013             {
1014               /* a AOP_STR uses DPTR, but DPTR is already in use;
1015                * we're just hosed.
1016                */
1017                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1018             }
1019
1020           aop = op->aop = sym->aop = newAsmop (AOP_STR);
1021           aop->size = getSize (sym->type);
1022           for (i = 0; i < (int) fReturnSizeDS390; i++)
1023             aop->aopu.aop_str[i] = fReturn[i];
1024           return;
1025         }
1026       
1027       if (sym->dptr) { /* has been allocated to a DPTRn */
1028           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1029           aop->size = getSize (sym->type);
1030           aop->aopu.dptr = sym->dptr;
1031           return ;
1032       }
1033       
1034       if (sym->usl.spillLoc)
1035         {
1036           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1037             {
1038               /* force a new aop if sizes differ */
1039               sym->usl.spillLoc->aop = NULL;
1040             }
1041           sym->aop = op->aop = aop =
1042                      aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1043           aop->size = getSize (sym->type);
1044           return;
1045         }
1046       
1047       /* else must be a dummy iTemp */
1048       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1049       aop->size = getSize (sym->type);
1050       return;
1051     }
1052
1053   /* must be in a register */
1054   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1055   aop->size = sym->nRegs;
1056   for (i = 0; i < sym->nRegs; i++)
1057     aop->aopu.aop_reg[i] = sym->regs[i];
1058 }
1059
1060 /*-----------------------------------------------------------------*/
1061 /* freeAsmop - free up the asmop given to an operand               */
1062 /*----------------------------------------------------------------*/
1063 static void
1064 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1065 {
1066   asmop *aop;
1067
1068   if (!op)
1069     aop = aaop;
1070   else
1071     aop = op->aop;
1072
1073   if (!aop)
1074     return;
1075
1076   if (aop->freed)
1077     goto dealloc;
1078
1079   aop->freed = 1;
1080
1081   /* depending on the asmop type only three cases need work AOP_RO
1082      , AOP_R1 && AOP_STK */
1083   switch (aop->type)
1084     {
1085     case AOP_R0:
1086       if (_G.r0Pushed)
1087         {
1088           if (pop)
1089             {
1090               emitcode ("pop", "ar0");
1091               _G.r0Pushed--;
1092             }
1093         }
1094       bitVectUnSetBit (ic->rUsed, R0_IDX);
1095       break;
1096
1097     case AOP_R1:
1098       if (_G.r1Pushed)
1099         {
1100           if (pop)
1101             {
1102               emitcode ("pop", "ar1");
1103               _G.r1Pushed--;
1104             }
1105         }
1106       bitVectUnSetBit (ic->rUsed, R1_IDX);
1107       break;
1108
1109     case AOP_STK:
1110       {
1111         int sz = aop->size;
1112         int stk = aop->aopu.aop_stk + aop->size;
1113         bitVectUnSetBit (ic->rUsed, R0_IDX);
1114         bitVectUnSetBit (ic->rUsed, R1_IDX);
1115
1116         getFreePtr (ic, &aop, FALSE);
1117
1118         if (options.stack10bit)
1119           {
1120             /* I'm not sure what to do here yet... */
1121             /* #STUB */
1122             fprintf (stderr,
1123                      "*** Warning: probably generating bad code for "
1124                      "10 bit stack mode.\n");
1125           }
1126
1127         if (stk)
1128           {
1129             emitcode ("mov", "a,_bp");
1130             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1131             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1132           }
1133         else
1134           {
1135             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1136           }
1137
1138         while (sz--)
1139           {
1140             emitcode ("pop", "acc");
1141             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1142             if (!sz)
1143               break;
1144             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1145           }
1146         op->aop = aop;
1147         freeAsmop (op, NULL, ic, TRUE);
1148         if (_G.r0Pushed)
1149           {
1150             emitcode ("pop", "ar0");
1151             _G.r0Pushed--;
1152           }
1153
1154         if (_G.r1Pushed)
1155           {
1156             emitcode ("pop", "ar1");
1157             _G.r1Pushed--;
1158           }
1159       }
1160     case AOP_DPTR2:
1161         if (_G.dptr1InUse) {
1162             emitcode ("pop","dpx1");
1163             emitcode ("pop","dph1");
1164             emitcode ("pop","dpl1");
1165         }
1166         break;
1167     case AOP_DPTR:
1168         if (_G.dptrInUse) {
1169             emitcode ("pop","dpx");
1170             emitcode ("pop","dph");
1171             emitcode ("pop","dpl");
1172         }
1173         break;
1174     }
1175 dealloc:
1176   /* all other cases just dealloc */
1177   if (op)
1178     {
1179       op->aop = NULL;
1180       if (IS_SYMOP (op))
1181         {
1182           OP_SYMBOL (op)->aop = NULL;
1183           /* if the symbol has a spill */
1184           if (SPIL_LOC (op))
1185             SPIL_LOC (op)->aop = NULL;
1186         }
1187     }
1188 }
1189
1190 #define DEFAULT_ACC_WARNING 0
1191 static int saveAccWarn = DEFAULT_ACC_WARNING;
1192
1193 /*-------------------------------------------------------------------*/
1194 /* aopGet - for fetching value of the aop                            */
1195 /*                                                                   */
1196 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1197 /* in the accumulator. Set it to the name of a free register         */
1198 /* if acc must be preserved; the register will be used to preserve   */
1199 /* acc temporarily and to return the result byte.                    */
1200 /*-------------------------------------------------------------------*/
1201
1202 static char *
1203 aopGet (asmop *aop,
1204         int   offset,
1205         bool  bit16,
1206         bool  dname,
1207         char  *saveAcc)
1208 {
1209   /* offset is greater than
1210      size then zero */
1211   if (offset > (aop->size - 1) &&
1212       aop->type != AOP_LIT)
1213     return zero;
1214
1215   /* depending on type */
1216   switch (aop->type)
1217     {
1218     case AOP_DUMMY:
1219       return zero;
1220
1221     case AOP_R0:
1222     case AOP_R1:
1223       /* if we need to increment it */
1224       while (offset > aop->coff)
1225         {
1226           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1227           aop->coff++;
1228         }
1229
1230       while (offset < aop->coff)
1231         {
1232           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1233           aop->coff--;
1234         }
1235
1236       aop->coff = offset;
1237       if (aop->paged)
1238         {
1239           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1240           return (dname ? "acc" : "a");
1241         }
1242       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1243       return Safe_strdup(buffer);       
1244
1245     case AOP_DPTRn:
1246         assert(offset <= 3);
1247         return dptrn[aop->aopu.dptr][offset];
1248
1249     case AOP_DPTR:
1250     case AOP_DPTR2:
1251
1252       if (aop->type == AOP_DPTR2)
1253         {
1254           genSetDPTR (1);
1255         }
1256         
1257       if (saveAcc)
1258         {
1259             TR_AP("#1");
1260 //          if (aop->type != AOP_DPTR2)
1261 //          {
1262 //              if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1263 //              emitcode(";", "spanky: saveAcc for DPTR");
1264 //          }
1265             
1266             emitcode ("xch", "a, %s", saveAcc);
1267         }
1268
1269       _flushLazyDPS ();
1270
1271       while (offset > aop->coff)
1272         {
1273           emitcode ("inc", "dptr");
1274           aop->coff++;
1275         }
1276
1277       while (offset < aop->coff)
1278         {
1279           emitcode ("lcall", "__decdptr");
1280           aop->coff--;
1281         }
1282
1283       aop->coff = offset;
1284       if (aop->code)
1285         {
1286           emitcode ("clr", "a");
1287           emitcode ("movc", "a,@a+dptr");
1288         }
1289       else
1290         {
1291           emitcode ("movx", "a,@dptr");
1292         }
1293
1294       if (aop->type == AOP_DPTR2)
1295         {
1296           genSetDPTR (0);
1297         }
1298         
1299         if (saveAcc)
1300         {
1301        TR_AP("#2");
1302               emitcode ("xch", "a, %s", saveAcc);
1303 //            if (strcmp(saveAcc, "_ap"))
1304 //            {
1305 //                emitcode(";", "spiffy: non _ap return from aopGet.");
1306 //            }
1307                   
1308               return saveAcc;
1309         }
1310       return (dname ? "acc" : "a");
1311
1312     case AOP_IMMD:
1313       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) 
1314       {
1315           SNPRINTF(buffer, sizeof(buffer), 
1316                    "%s",aop->aopu.aop_immd.aop_immd2);
1317       } 
1318       else if (bit16)
1319       {
1320          SNPRINTF(buffer, sizeof(buffer), 
1321                   "#%s", aop->aopu.aop_immd.aop_immd1);
1322       }
1323       else if (offset) 
1324       {
1325           switch (offset) {
1326           case 1:
1327               tsprintf(buffer, sizeof(buffer),
1328                        "#!his",aop->aopu.aop_immd.aop_immd1);
1329               break;
1330           case 2:
1331               tsprintf(buffer, sizeof(buffer), 
1332                        "#!hihis",aop->aopu.aop_immd.aop_immd1);
1333               break;
1334           case 3:
1335               tsprintf(buffer, sizeof(buffer),
1336                        "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1337               break;
1338           default: /* should not need this (just in case) */
1339               SNPRINTF (buffer, sizeof(buffer), 
1340                         "#(%s >> %d)",
1341                        aop->aopu.aop_immd.aop_immd1,
1342                        offset * 8);
1343           }
1344       }
1345       else
1346       {
1347         SNPRINTF (buffer, sizeof(buffer), 
1348                   "#%s", aop->aopu.aop_immd.aop_immd1);
1349       }
1350       return Safe_strdup(buffer);       
1351
1352     case AOP_DIR:
1353       if (offset)
1354       {
1355         SNPRINTF (buffer, sizeof(buffer),
1356                   "(%s + %d)",
1357                  aop->aopu.aop_dir,
1358                  offset);
1359       }
1360       else
1361       {
1362         SNPRINTF(buffer, sizeof(buffer), 
1363                  "%s", aop->aopu.aop_dir);
1364       }
1365
1366       return Safe_strdup(buffer);
1367
1368     case AOP_REG:
1369       if (dname)
1370         return aop->aopu.aop_reg[offset]->dname;
1371       else
1372         return aop->aopu.aop_reg[offset]->name;
1373
1374     case AOP_CRY:
1375       emitcode ("clr", "a");
1376       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1377       emitcode ("rlc", "a");
1378       return (dname ? "acc" : "a");
1379
1380     case AOP_ACC:
1381       if (!offset && dname)
1382         return "acc";
1383       return aop->aopu.aop_str[offset];
1384
1385     case AOP_LIT:
1386       return aopLiteral (aop->aopu.aop_lit, offset);
1387
1388     case AOP_STR:
1389       aop->coff = offset;
1390       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1391           dname)
1392         return "acc";
1393
1394       return aop->aopu.aop_str[offset];
1395
1396     }
1397
1398   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1399           "aopget got unsupported aop->type");
1400   exit (1);
1401     
1402   return NULL;  // not reached, but makes compiler happy.
1403 }
1404 /*-----------------------------------------------------------------*/
1405 /* aopPut - puts a string for a aop                                */
1406 /*-----------------------------------------------------------------*/
1407 static void
1408 aopPut (asmop * aop, char *s, int offset)
1409 {
1410   if (aop->size && offset > (aop->size - 1))
1411     {
1412       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1413               "aopPut got offset > aop->size");
1414       exit (1);
1415     }
1416
1417   /* will assign value to value */
1418   /* depending on where it is ofcourse */
1419   switch (aop->type)
1420     {
1421     case AOP_DUMMY:
1422       MOVA (s);         /* read s in case it was volatile */
1423       break;
1424       
1425     case AOP_DIR:
1426         if (offset)
1427         {
1428             SNPRINTF (buffer, sizeof(buffer),
1429                       "(%s + %d)",
1430                       aop->aopu.aop_dir, offset);
1431         }
1432         else
1433         {
1434             SNPRINTF (buffer, sizeof(buffer), 
1435                      "%s", aop->aopu.aop_dir);
1436         }
1437         
1438
1439         if (strcmp (buffer, s))
1440         {
1441             emitcode ("mov", "%s,%s", buffer, s);
1442         }
1443       break;
1444
1445     case AOP_REG:
1446       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1447           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1448         {
1449           if (*s == '@' ||
1450               strcmp (s, "r0") == 0 ||
1451               strcmp (s, "r1") == 0 ||
1452               strcmp (s, "r2") == 0 ||
1453               strcmp (s, "r3") == 0 ||
1454               strcmp (s, "r4") == 0 ||
1455               strcmp (s, "r5") == 0 ||
1456               strcmp (s, "r6") == 0 ||
1457               strcmp (s, "r7") == 0)
1458             {
1459                 emitcode ("mov", "%s,%s",
1460                           aop->aopu.aop_reg[offset]->dname, s);
1461             }
1462             else
1463             {
1464                 emitcode ("mov", "%s,%s",
1465                           aop->aopu.aop_reg[offset]->name, s);
1466             }
1467         }
1468       break;
1469
1470     case AOP_DPTRn:
1471         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1472         break;
1473
1474     case AOP_DPTR:
1475     case AOP_DPTR2:
1476
1477       if (aop->type == AOP_DPTR2)
1478         {
1479           genSetDPTR (1);
1480         }
1481       _flushLazyDPS ();
1482
1483       if (aop->code)
1484         {
1485           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1486                   "aopPut writting to code space");
1487           exit (1);
1488         }
1489
1490       while (offset > aop->coff)
1491         {
1492           aop->coff++;
1493           emitcode ("inc", "dptr");
1494         }
1495
1496       while (offset < aop->coff)
1497         {
1498           aop->coff--;
1499           emitcode ("lcall", "__decdptr");
1500         }
1501
1502       aop->coff = offset;
1503
1504       /* if not in accumulater */
1505       MOVA (s);
1506
1507       emitcode ("movx", "@dptr,a");
1508
1509       if (aop->type == AOP_DPTR2)
1510         {
1511           genSetDPTR (0);
1512         }
1513       break;
1514
1515     case AOP_R0:
1516     case AOP_R1:
1517       while (offset > aop->coff)
1518         {
1519           aop->coff++;
1520           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1521         }
1522       while (offset < aop->coff)
1523         {
1524           aop->coff--;
1525           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1526         }
1527       aop->coff = offset;
1528
1529       if (aop->paged)
1530         {
1531           MOVA (s);
1532           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1533
1534         }
1535       else if (*s == '@')
1536         {
1537           MOVA (s);
1538           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1539         }
1540       else if (strcmp (s, "r0") == 0 ||
1541                strcmp (s, "r1") == 0 ||
1542                strcmp (s, "r2") == 0 ||
1543                strcmp (s, "r3") == 0 ||
1544                strcmp (s, "r4") == 0 ||
1545                strcmp (s, "r5") == 0 ||
1546                strcmp (s, "r6") == 0 ||
1547                strcmp (s, "r7") == 0)
1548         {
1549           char buff[10];
1550           SNPRINTF(buff, sizeof(buff), 
1551                    "a%s", s);
1552           emitcode ("mov", "@%s,%s",
1553                     aop->aopu.aop_ptr->name, buff);
1554         }
1555         else
1556         {
1557             emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1558         }
1559       break;
1560
1561     case AOP_STK:
1562       if (strcmp (s, "a") == 0)
1563         emitcode ("push", "acc");
1564       else
1565         if (*s=='@') {
1566           MOVA(s);
1567           emitcode ("push", "acc");
1568         } else {
1569           emitcode ("push", s);
1570         }
1571
1572       break;
1573
1574     case AOP_CRY:
1575       /* if bit variable */
1576       if (!aop->aopu.aop_dir)
1577         {
1578           emitcode ("clr", "a");
1579           emitcode ("rlc", "a");
1580         }
1581       else
1582         {
1583           if (s == zero)
1584             emitcode ("clr", "%s", aop->aopu.aop_dir);
1585           else if (s == one)
1586             emitcode ("setb", "%s", aop->aopu.aop_dir);
1587           else if (!strcmp (s, "c"))
1588             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1589           else
1590             {
1591               if (strcmp (s, "a"))
1592                 {
1593                   MOVA (s);
1594                 }
1595               {
1596                 /* set C, if a >= 1 */
1597                 emitcode ("add", "a,#!constbyte",0xff);
1598                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1599               }
1600             }
1601         }
1602       break;
1603
1604     case AOP_STR:
1605       aop->coff = offset;
1606       if (strcmp (aop->aopu.aop_str[offset], s))
1607         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1608       break;
1609
1610     case AOP_ACC:
1611       aop->coff = offset;
1612       if (!offset && (strcmp (s, "acc") == 0))
1613         break;
1614
1615       if (strcmp (aop->aopu.aop_str[offset], s))
1616         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1617       break;
1618
1619     default:
1620       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1621               "aopPut got unsupported aop->type");
1622       exit (1);
1623     }
1624
1625 }
1626
1627
1628 /*--------------------------------------------------------------------*/
1629 /* reAdjustPreg - points a register back to where it should (coff==0) */
1630 /*--------------------------------------------------------------------*/
1631 static void
1632 reAdjustPreg (asmop * aop)
1633 {
1634   if ((aop->coff==0) || (aop->size <= 1)) {
1635     return;
1636   }
1637
1638   switch (aop->type)
1639     {
1640     case AOP_R0:
1641     case AOP_R1:
1642       while (aop->coff--)
1643         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1644       break;
1645     case AOP_DPTR:
1646     case AOP_DPTR2:
1647       if (aop->type == AOP_DPTR2)
1648         {
1649           genSetDPTR (1);
1650           _flushLazyDPS ();
1651         }
1652       while (aop->coff--)
1653         {
1654           emitcode ("lcall", "__decdptr");
1655         }
1656
1657       if (aop->type == AOP_DPTR2)
1658         {
1659           genSetDPTR (0);
1660         }
1661       break;
1662
1663     }
1664   aop->coff=0;
1665 }
1666
1667 #define AOP(op) op->aop
1668 #define AOP_TYPE(op) AOP(op)->type
1669 #define AOP_SIZE(op) AOP(op)->size
1670 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1671                        AOP_TYPE(x) == AOP_R0))
1672
1673 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1674                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1675                          AOP(x)->paged))
1676
1677 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1678                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1679                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1680 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1681 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1682 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1683
1684 // The following two macros can be used even if the aop has not yet been aopOp'd.
1685 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1686 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1687
1688 /* Workaround for DS80C390 bug: div ab may return bogus results
1689  * if A is accessed in instruction immediately before the div.
1690  *
1691  * Will be fixed in B4 rev of processor, Dallas claims.
1692  */
1693
1694 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1695     if (!AOP_NEEDSACC(RIGHT))         \
1696     {               \
1697       /* We can load A first, then B, since     \
1698        * B (the RIGHT operand) won't clobber A,   \
1699        * thus avoiding touching A right before the div. \
1700        */             \
1701       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1702       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);     \
1703       MOVA(L);            \
1704       L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1705       MOVB(L); \
1706     }               \
1707     else              \
1708     {               \
1709       /* Just stuff in a nop after loading A. */    \
1710       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1711       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);   \
1712       MOVA(L);            \
1713       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1714     }
1715
1716
1717 /*-----------------------------------------------------------------*/
1718 /* opIsGptr: returns non-zero if the passed operand is       */
1719 /* a generic pointer type.             */
1720 /*-----------------------------------------------------------------*/
1721 static int
1722 opIsGptr (operand * op)
1723 {
1724   sym_link *type = operandType (op);
1725
1726   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1727     {
1728       return 1;
1729     }
1730   return 0;
1731 }
1732
1733 /*-----------------------------------------------------------------*/
1734 /* getDataSize - get the operand data size                         */
1735 /*-----------------------------------------------------------------*/
1736 static int
1737 getDataSize (operand * op)
1738 {
1739   int size;
1740   size = AOP_SIZE (op);
1741   if (size == GPTRSIZE)
1742     {
1743       sym_link *type = operandType (op);
1744       if (IS_GENPTR (type))
1745         {
1746           /* generic pointer; arithmetic operations
1747            * should ignore the high byte (pointer type).
1748            */
1749           size--;
1750         }
1751     }
1752   return size;
1753 }
1754
1755 /*-----------------------------------------------------------------*/
1756 /* outAcc - output Acc                                             */
1757 /*-----------------------------------------------------------------*/
1758 static void
1759 outAcc (operand * result)
1760 {
1761   int size, offset;
1762   size = getDataSize (result);
1763   if (size)
1764     {
1765       aopPut (AOP (result), "a", 0);
1766       size--;
1767       offset = 1;
1768       /* unsigned or positive */
1769       while (size--)
1770         {
1771           aopPut (AOP (result), zero, offset++);
1772         }
1773     }
1774 }
1775
1776 /*-----------------------------------------------------------------*/
1777 /* outBitC - output a bit C                                        */
1778 /*-----------------------------------------------------------------*/
1779 static void
1780 outBitC (operand * result)
1781 {
1782   /* if the result is bit */
1783   if (AOP_TYPE (result) == AOP_CRY)
1784     {
1785       aopPut (AOP (result), "c", 0);
1786     }
1787   else
1788     {
1789       emitcode ("clr", "a");
1790       emitcode ("rlc", "a");
1791       outAcc (result);
1792     }
1793 }
1794
1795 /*-----------------------------------------------------------------*/
1796 /* toBoolean - emit code for orl a,operator(sizeop)                */
1797 /*-----------------------------------------------------------------*/
1798 static void
1799 toBoolean (operand * oper)
1800 {
1801   int   size = AOP_SIZE (oper) - 1;
1802   int   offset = 1;
1803   bool usedB = FALSE;
1804
1805   /* The generic part of a generic pointer should
1806    * not participate in it's truth value.
1807    *
1808    * i.e. 0x10000000 is zero.
1809    */
1810   if (opIsGptr (oper))
1811     {
1812       D (emitcode (";", "toBoolean: generic ptr special case."););
1813       size--;
1814     }
1815
1816   _startLazyDPSEvaluation ();
1817   if (AOP_NEEDSACC (oper) && size)
1818     {
1819       usedB = TRUE;
1820       if (_G.bInUse)
1821       {
1822           emitcode ("push", "b");
1823       }
1824       MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1825     }
1826   else
1827     {
1828       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1829     }
1830     
1831   while (size--)
1832     {
1833       if (usedB)
1834         {
1835           emitcode ("orl", "b,%s",
1836                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1837         }
1838       else
1839         {
1840           emitcode ("orl", "a,%s",
1841                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1842         }
1843     }
1844   _endLazyDPSEvaluation ();
1845
1846   if (usedB)
1847     {
1848       emitcode ("mov", "a,b");
1849       if (_G.bInUse)
1850       {
1851           emitcode ("pop", "b");
1852       }
1853         
1854     }
1855 }
1856
1857
1858 /*-----------------------------------------------------------------*/
1859 /* genNot - generate code for ! operation                          */
1860 /*-----------------------------------------------------------------*/
1861 static void
1862 genNot (iCode * ic)
1863 {
1864   symbol *tlbl;
1865
1866   D (emitcode (";", "genNot "););
1867
1868   /* assign asmOps to operand & result */
1869   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1870   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1871
1872   /* if in bit space then a special case */
1873   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1874     {
1875       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1876       emitcode ("cpl", "c");
1877       outBitC (IC_RESULT (ic));
1878       goto release;
1879     }
1880
1881   toBoolean (IC_LEFT (ic));
1882
1883   tlbl = newiTempLabel (NULL);
1884   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1885   emitcode ("", "!tlabeldef", tlbl->key + 100);
1886   outBitC (IC_RESULT (ic));
1887
1888 release:
1889   /* release the aops */
1890   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1891   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1892 }
1893
1894
1895 /*-----------------------------------------------------------------*/
1896 /* genCpl - generate code for complement                           */
1897 /*-----------------------------------------------------------------*/
1898 static void
1899 genCpl (iCode * ic)
1900 {
1901   int offset = 0;
1902   int size;
1903   symbol *tlbl;
1904
1905   D (emitcode (";", "genCpl "););
1906
1907
1908   /* assign asmOps to operand & result */
1909   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1910   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1911
1912   /* special case if in bit space */
1913   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1914     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1915       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1916       emitcode ("cpl", "c");
1917       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1918       goto release;
1919     }
1920     tlbl=newiTempLabel(NULL);
1921     emitcode ("cjne", "%s,#0x01,%05d$", 
1922               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1923     emitcode ("", "%05d$:", tlbl->key+100);
1924     outBitC (IC_RESULT(ic));
1925     goto release;
1926   }
1927
1928   size = AOP_SIZE (IC_RESULT (ic));
1929   _startLazyDPSEvaluation ();
1930   while (size--)
1931     {
1932       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1933       emitcode ("cpl", "a");
1934       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1935     }
1936   _endLazyDPSEvaluation ();
1937
1938
1939 release:
1940   /* release the aops */
1941   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1942   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1943 }
1944
1945 /*-----------------------------------------------------------------*/
1946 /* genUminusFloat - unary minus for floating points                */
1947 /*-----------------------------------------------------------------*/
1948 static void
1949 genUminusFloat (operand * op, operand * result)
1950 {
1951   int size, offset = 0;
1952     
1953   D(emitcode (";", "genUminusFloat"););
1954   
1955   /* for this we just copy and then flip the bit */
1956     
1957   _startLazyDPSEvaluation ();
1958   size = AOP_SIZE (op) - 1;
1959
1960   while (size--)
1961   {
1962       aopPut (AOP (result),
1963               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1964               offset);
1965       offset++;
1966     }
1967   
1968   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1969
1970   emitcode ("cpl", "acc.7");
1971   aopPut (AOP (result), "a", offset);    
1972   _endLazyDPSEvaluation ();
1973 }
1974
1975 /*-----------------------------------------------------------------*/
1976 /* genUminus - unary minus code generation                         */
1977 /*-----------------------------------------------------------------*/
1978 static void
1979 genUminus (iCode * ic)
1980 {
1981   int offset, size;
1982   sym_link *optype;
1983
1984   D (emitcode (";", "genUminus "););
1985
1986   /* assign asmops */
1987   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1988   aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
1989
1990   /* if both in bit space then special
1991      case */
1992   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1993       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1994     {
1995
1996       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1997       emitcode ("cpl", "c");
1998       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1999       goto release;
2000     }
2001
2002   optype = operandType (IC_LEFT (ic));
2003
2004   /* if float then do float stuff */
2005   if (IS_FLOAT (optype))
2006     {
2007       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2008       goto release;
2009     }
2010
2011   /* otherwise subtract from zero */
2012   size = AOP_SIZE (IC_LEFT (ic));
2013   offset = 0;
2014   _startLazyDPSEvaluation ();
2015   while (size--)
2016     {
2017       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
2018       if (!strcmp (l, "a"))
2019         {
2020           if (offset == 0)
2021             SETC;
2022           emitcode ("cpl", "a");
2023           emitcode ("addc", "a,#0");
2024         }
2025       else
2026         {
2027           if (offset == 0)
2028             CLRC;
2029           emitcode ("clr", "a");
2030           emitcode ("subb", "a,%s", l);
2031         }
2032       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2033     }
2034   _endLazyDPSEvaluation ();
2035
2036   /* if any remaining bytes in the result */
2037   /* we just need to propagate the sign   */
2038   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2039     {
2040       emitcode ("rlc", "a");
2041       emitcode ("subb", "a,acc");
2042       while (size--)
2043         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2044     }
2045
2046 release:
2047   /* release the aops */
2048   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2049   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2050 }
2051
2052 /*-----------------------------------------------------------------*/
2053 /* savermask - saves registers in the mask                         */
2054 /*-----------------------------------------------------------------*/
2055 static void savermask(bitVect *rs_mask)
2056 {
2057     int i;
2058     if (options.useXstack) {
2059         if (bitVectBitValue (rs_mask, R0_IDX))
2060             emitcode ("mov", "b,r0");
2061         emitcode ("mov", "r0,%s", spname);
2062         for (i = 0; i < ds390_nRegs; i++) {
2063             if (bitVectBitValue (rs_mask, i)) {
2064                 if (i == R0_IDX)
2065                     emitcode ("mov", "a,b");
2066                 else
2067                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2068                 emitcode ("movx", "@r0,a");
2069                 emitcode ("inc", "r0");
2070             }
2071         }
2072         emitcode ("mov", "%s,r0", spname);
2073         if (bitVectBitValue (rs_mask, R0_IDX))
2074             emitcode ("mov", "r0,b");
2075     } else {
2076         for (i = 0; i < ds390_nRegs; i++) {
2077             if (bitVectBitValue (rs_mask, i))
2078                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2079         }
2080     }
2081 }
2082
2083 /*-----------------------------------------------------------------*/
2084 /* saveRegisters - will look for a call and save the registers     */
2085 /*-----------------------------------------------------------------*/
2086 static void
2087 saveRegisters (iCode * lic)
2088 {
2089   iCode *ic;
2090   bitVect *rsave;
2091
2092   /* look for call */
2093   for (ic = lic; ic; ic = ic->next)
2094     if (ic->op == CALL || ic->op == PCALL)
2095       break;
2096
2097   if (!ic)
2098     {
2099       fprintf (stderr, "found parameter push with no function call\n");
2100       return;
2101     }
2102
2103   /* if the registers have been saved already then
2104      do nothing */
2105   if (ic->regsSaved 
2106       || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2107     return ;
2108
2109   /* special case if DPTR alive across a function call then must save it 
2110      even though callee saves */
2111   if (IS_SYMOP(IC_LEFT(ic)) &&
2112       IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2113       int i;
2114       rsave = newBitVect(ic->rMask->size);
2115       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2116           if (bitVectBitValue(ic->rMask,i))
2117               rsave = bitVectSetBit(rsave,i);
2118       }
2119       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2120   } else {
2121     /* safe the registers in use at this time but skip the
2122        ones for the result */
2123     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2124                            ds390_rUmaskForOp (IC_RESULT(ic)));
2125   }
2126   ic->regsSaved = 1;
2127   savermask(rsave);
2128 }
2129
2130 /*-----------------------------------------------------------------*/
2131 /* usavermask - restore registers with mask                        */
2132 /*-----------------------------------------------------------------*/
2133 static void unsavermask(bitVect *rs_mask)
2134 {
2135     int i;
2136     if (options.useXstack) {
2137         emitcode ("mov", "r0,%s", spname);
2138         for (i = ds390_nRegs; i >= 0; i--) {
2139             if (bitVectBitValue (rs_mask, i)) {
2140                 emitcode ("dec", "r0");
2141                 emitcode ("movx", "a,@r0");
2142                 if (i == R0_IDX)
2143                     emitcode ("mov", "b,a");
2144                 else
2145                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2146             }       
2147         }
2148         emitcode ("mov", "%s,r0", spname);
2149         if (bitVectBitValue (rs_mask, R0_IDX))
2150             emitcode ("mov", "r0,b");
2151     } else {
2152         for (i = ds390_nRegs; i >= 0; i--) {
2153             if (bitVectBitValue (rs_mask, i))
2154                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2155         }
2156     }
2157 }
2158
2159 /*-----------------------------------------------------------------*/
2160 /* unsaveRegisters - pop the pushed registers                      */
2161 /*-----------------------------------------------------------------*/
2162 static void
2163 unsaveRegisters (iCode * ic)
2164 {
2165   bitVect *rsave;
2166
2167   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2168       int i;
2169       rsave = newBitVect(ic->rMask->size);
2170       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2171           if (bitVectBitValue(ic->rMask,i))
2172               rsave = bitVectSetBit(rsave,i);
2173       }
2174       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2175   } else {
2176     /* restore the registers in use at this time but skip the
2177        ones for the result */
2178     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2179                            ds390_rUmaskForOp (IC_RESULT(ic)));
2180   }
2181   unsavermask(rsave);
2182 }
2183
2184
2185 /*-----------------------------------------------------------------*/
2186 /* pushSide -                */
2187 /*-----------------------------------------------------------------*/
2188 static void
2189 pushSide (operand * oper, int size)
2190 {
2191   int offset = 0;
2192   _startLazyDPSEvaluation ();
2193   while (size--)
2194     {
2195       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2196       if (AOP_TYPE (oper) != AOP_REG &&
2197           AOP_TYPE (oper) != AOP_DIR &&
2198           strcmp (l, "a"))
2199         {
2200           emitcode ("mov", "a,%s", l);
2201           emitcode ("push", "acc");
2202         }
2203       else
2204         emitcode ("push", "%s", l);
2205     }
2206   _endLazyDPSEvaluation ();
2207 }
2208
2209 /*-----------------------------------------------------------------*/
2210 /* assignResultValue -               */
2211 /*-----------------------------------------------------------------*/
2212 static void
2213 assignResultValue (operand * oper)
2214 {
2215   int offset = 0;
2216   int size = AOP_SIZE (oper);
2217   bool pushedAcc = FALSE;
2218
2219   if (size == fReturnSizeDS390)
2220   {
2221       /* I don't think this case can ever happen... */
2222       /* ACC is the last part of this. If writing the result
2223        * uses AC, we must preserve it.
2224        */
2225       if (AOP_NEEDSACC(oper))
2226       {
2227           emitcode(";", "assignResultValue special case for ACC.");
2228           emitcode("push", "acc");
2229           pushedAcc = TRUE;
2230           size--;
2231       }
2232   }
2233     
2234     
2235   _startLazyDPSEvaluation ();
2236   while (size--)
2237     {
2238       aopPut (AOP (oper), fReturn[offset], offset);
2239       offset++;
2240     }
2241   _endLazyDPSEvaluation ();
2242     
2243   if (pushedAcc)
2244     {
2245         emitcode("pop", "acc");
2246         aopPut(AOP(oper), "a", offset);
2247     }
2248 }
2249
2250
2251 /*-----------------------------------------------------------------*/
2252 /* genXpush - pushes onto the external stack                       */
2253 /*-----------------------------------------------------------------*/
2254 static void
2255 genXpush (iCode * ic)
2256 {
2257   asmop *aop = newAsmop (0);
2258   regs *r;
2259   int size, offset = 0;
2260
2261   D (emitcode (";", "genXpush ");
2262     );
2263
2264   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2265   r = getFreePtr (ic, &aop, FALSE);
2266
2267
2268   emitcode ("mov", "%s,_spx", r->name);
2269
2270   size = AOP_SIZE (IC_LEFT (ic));
2271   _startLazyDPSEvaluation ();
2272   while (size--)
2273     {
2274
2275       MOVA (aopGet (AOP (IC_LEFT (ic)),
2276                         offset++, FALSE, FALSE, NULL));
2277       emitcode ("movx", "@%s,a", r->name);
2278       emitcode ("inc", "%s", r->name);
2279
2280     }
2281   _endLazyDPSEvaluation ();
2282
2283
2284   emitcode ("mov", "_spx,%s", r->name);
2285
2286   freeAsmop (NULL, aop, ic, TRUE);
2287   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2288 }
2289
2290 /*-----------------------------------------------------------------*/
2291 /* genIpush - generate code for pushing this gets a little complex  */
2292 /*-----------------------------------------------------------------*/
2293 static void
2294 genIpush (iCode * ic)
2295 {
2296   int size, offset = 0;
2297   char *l;
2298
2299   D (emitcode (";", "genIpush ");
2300     );
2301
2302   /* if this is not a parm push : ie. it is spill push
2303      and spill push is always done on the local stack */
2304   if (!ic->parmPush)
2305     {
2306
2307       /* and the item is spilt then do nothing */
2308       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2309         return;
2310
2311       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2312       size = AOP_SIZE (IC_LEFT (ic));
2313       /* push it on the stack */
2314       _startLazyDPSEvaluation ();
2315       while (size--)
2316         {
2317           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2318           if (*l == '#')
2319             {
2320               MOVA (l);
2321               l = "acc";
2322             }
2323           emitcode ("push", "%s", l);
2324         }
2325       _endLazyDPSEvaluation ();
2326       return;
2327     }
2328
2329   /* this is a paramter push: in this case we call
2330      the routine to find the call and save those
2331      registers that need to be saved */
2332   saveRegisters (ic);
2333
2334   /* if use external stack then call the external
2335      stack pushing routine */
2336   if (options.useXstack)
2337     {
2338       genXpush (ic);
2339       return;
2340     }
2341
2342   /* then do the push */
2343   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2344
2345   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2346   size = AOP_SIZE (IC_LEFT (ic));
2347
2348   _startLazyDPSEvaluation ();
2349   while (size--)
2350     {
2351       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2352       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2353           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2354           strcmp (l, "acc"))
2355         {
2356           emitcode ("mov", "a,%s", l);
2357           emitcode ("push", "acc");
2358         }
2359       else
2360         {
2361             emitcode ("push", "%s", l);
2362         }
2363     }
2364   _endLazyDPSEvaluation ();
2365
2366   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2367 }
2368
2369 /*-----------------------------------------------------------------*/
2370 /* genIpop - recover the registers: can happen only for spilling   */
2371 /*-----------------------------------------------------------------*/
2372 static void
2373 genIpop (iCode * ic)
2374 {
2375   int size, offset;
2376
2377   D (emitcode (";", "genIpop ");
2378     );
2379
2380
2381   /* if the temp was not pushed then */
2382   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2383     return;
2384
2385   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2386   size = AOP_SIZE (IC_LEFT (ic));
2387   offset = (size - 1);
2388   _startLazyDPSEvaluation ();
2389   while (size--)
2390     {
2391       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2392                                      FALSE, TRUE, NULL));
2393     }
2394   _endLazyDPSEvaluation ();
2395
2396   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2397 }
2398
2399 /*-----------------------------------------------------------------*/
2400 /* unsaveRBank - restores the resgister bank from stack            */
2401 /*-----------------------------------------------------------------*/
2402 static void
2403 unsaveRBank (int bank, iCode * ic, bool popPsw)
2404 {
2405   int i;
2406   asmop *aop = NULL;
2407   regs *r = NULL;
2408
2409   if (options.useXstack)
2410   {
2411       if (!ic)
2412       {
2413           /* Assume r0 is available for use. */
2414           r = ds390_regWithIdx (R0_IDX);;          
2415       } 
2416       else
2417       {
2418           aop = newAsmop (0);
2419           r = getFreePtr (ic, &aop, FALSE);
2420       }
2421       emitcode ("mov", "%s,_spx", r->name);      
2422   }
2423   
2424   if (popPsw)
2425     {
2426       if (options.useXstack)
2427       {
2428           emitcode ("movx", "a,@%s", r->name);
2429           emitcode ("mov", "psw,a");
2430           emitcode ("dec", "%s", r->name);
2431         }
2432       else
2433       {
2434         emitcode ("pop", "psw");
2435       }
2436     }
2437
2438   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2439     {
2440       if (options.useXstack)
2441         {
2442           emitcode ("movx", "a,@%s", r->name);
2443           emitcode ("mov", "(%s+%d),a",
2444                     regs390[i].base, 8 * bank + regs390[i].offset);
2445           emitcode ("dec", "%s", r->name);
2446
2447         }
2448       else
2449         emitcode ("pop", "(%s+%d)",
2450                   regs390[i].base, 8 * bank + regs390[i].offset);
2451     }
2452
2453   if (options.useXstack)
2454     {
2455       emitcode ("mov", "_spx,%s", r->name);
2456     }
2457     
2458   if (aop)
2459   {
2460       freeAsmop (NULL, aop, ic, TRUE);  
2461   }    
2462 }
2463
2464 /*-----------------------------------------------------------------*/
2465 /* saveRBank - saves an entire register bank on the stack          */
2466 /*-----------------------------------------------------------------*/
2467 static void
2468 saveRBank (int bank, iCode * ic, bool pushPsw)
2469 {
2470   int i;
2471   asmop *aop = NULL;
2472   regs *r = NULL;
2473
2474   if (options.useXstack)
2475     {
2476         if (!ic)
2477         {
2478           /* Assume r0 is available for use. */
2479                   r = ds390_regWithIdx (R0_IDX);;
2480         }
2481         else
2482         {
2483           aop = newAsmop (0);
2484           r = getFreePtr (ic, &aop, FALSE);
2485         }
2486         emitcode ("mov", "%s,_spx", r->name);    
2487     }
2488
2489   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2490     {
2491       if (options.useXstack)
2492         {
2493           emitcode ("inc", "%s", r->name);
2494           emitcode ("mov", "a,(%s+%d)",
2495                     regs390[i].base, 8 * bank + regs390[i].offset);
2496           emitcode ("movx", "@%s,a", r->name);
2497         }
2498       else
2499         emitcode ("push", "(%s+%d)",
2500                   regs390[i].base, 8 * bank + regs390[i].offset);
2501     }
2502
2503   if (pushPsw)
2504     {
2505       if (options.useXstack)
2506         {
2507           emitcode ("mov", "a,psw");
2508           emitcode ("movx", "@%s,a", r->name);
2509           emitcode ("inc", "%s", r->name);
2510           emitcode ("mov", "_spx,%s", r->name);
2511         }
2512       else
2513       {
2514         emitcode ("push", "psw");
2515       }
2516
2517       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2518     }
2519   
2520   if (aop)
2521   {
2522        freeAsmop (NULL, aop, ic, TRUE);
2523   }    
2524     
2525   if (ic)
2526   {  
2527       ic->bankSaved = 1;
2528   }
2529 }
2530
2531 /*-----------------------------------------------------------------*/
2532 /* genSend - gen code for SEND                                     */
2533 /*-----------------------------------------------------------------*/
2534 static void genSend(set *sendSet)
2535 {
2536     iCode *sic;
2537     int sendCount = 0 ;
2538     static int rb1_count = 0;
2539
2540     for (sic = setFirstItem (sendSet); sic;
2541          sic = setNextItem (sendSet)) {     
2542         int size, offset = 0;
2543         
2544         size=getSize(operandType(IC_LEFT(sic)));
2545         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2546         if (sendCount == 0) { /* first parameter */
2547             // we know that dpl(hxb) is the result, so
2548             rb1_count = 0 ;
2549             _startLazyDPSEvaluation ();
2550             if (size>1) {
2551                 aopOp (IC_LEFT (sic), sic, FALSE, 
2552                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2553             } else {
2554                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2555             }
2556             while (size--) {
2557                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2558                                   FALSE, FALSE, NULL);
2559                 if (strcmp (l, fReturn[offset])) {
2560                     emitcode ("mov", "%s,%s",
2561                               fReturn[offset],
2562                               l);
2563                 }
2564                 offset++;
2565             }
2566             _endLazyDPSEvaluation ();
2567             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2568             rb1_count =0;
2569         } else { /* if more parameter in registers */
2570             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2571             while (size--) {
2572                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2573                                                                 FALSE, FALSE, NULL));
2574             }
2575             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2576         }
2577         sendCount++;
2578     }
2579 }
2580
2581 static void
2582 adjustEsp(const char *reg)
2583 {
2584     emitcode ("anl","%s,#3", reg);
2585     if (TARGET_IS_DS400)
2586     {
2587         emitcode ("orl","%s,#!constbyte",
2588                   reg,
2589                   (options.stack_loc >> 8) & 0xff);
2590     }
2591 }
2592
2593 /*-----------------------------------------------------------------*/
2594 /* genCall - generates a call statement                            */
2595 /*-----------------------------------------------------------------*/
2596 static void
2597 genCall (iCode * ic)
2598 {
2599   sym_link *dtype;
2600   bool restoreBank = FALSE;
2601   bool swapBanks = FALSE;
2602
2603   D (emitcode (";", "genCall "););
2604
2605   /* if we are calling a not _naked function that is not using
2606      the same register bank then we need to save the
2607      destination registers on the stack */
2608   dtype = operandType (IC_LEFT (ic));
2609   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2610       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2611       IFFUNC_ISISR (currFunc->type))
2612   {
2613       if (!ic->bankSaved) 
2614       {
2615            /* This is unexpected; the bank should have been saved in
2616             * genFunction.
2617             */
2618            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2619            restoreBank = TRUE;
2620       }
2621       swapBanks = TRUE;
2622   }
2623   
2624     /* if caller saves & we have not saved then */
2625     if (!ic->regsSaved)
2626       saveRegisters (ic);
2627   
2628   /* if send set is not empty the assign */
2629   /* We've saved all the registers we care about;
2630   * therefore, we may clobber any register not used
2631   * in the calling convention (i.e. anything not in
2632   * fReturn.
2633   */
2634   if (_G.sendSet)
2635     {
2636         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2637             genSend(reverseSet(_G.sendSet));
2638         } else {
2639             genSend(_G.sendSet);
2640         }
2641       _G.sendSet = NULL;
2642     }  
2643     
2644   if (swapBanks)
2645   {
2646         emitcode ("mov", "psw,#!constbyte", 
2647            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2648   }
2649
2650   /* make the call */
2651   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2652                             OP_SYMBOL (IC_LEFT (ic))->rname :
2653                             OP_SYMBOL (IC_LEFT (ic))->name));
2654
2655   if (swapBanks)
2656   {
2657        emitcode ("mov", "psw,#!constbyte", 
2658           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2659   }
2660
2661   /* if we need assign a result value */
2662   if ((IS_ITEMP (IC_RESULT (ic)) &&
2663        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2664         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2665         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2666       IS_TRUE_SYMOP (IC_RESULT (ic)))
2667     {
2668       if (isOperandInFarSpace (IC_RESULT (ic))
2669           && getSize (operandType (IC_RESULT (ic))) <= 2)
2670         {
2671           int size = getSize (operandType (IC_RESULT (ic)));
2672
2673           /* Special case for 1 or 2 byte return in far space. */
2674           MOVA (fReturn[0]);
2675           if (size > 1)
2676             {
2677               emitcode ("mov", "b,%s", fReturn[1]);
2678             }
2679
2680           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2681           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2682
2683           if (size > 1)
2684             {
2685               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2686             }
2687           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2688         }
2689       else
2690         {
2691           _G.bInUse++;
2692           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2693           _G.bInUse--;
2694
2695           assignResultValue (IC_RESULT (ic));
2696
2697           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2698         }
2699     }
2700
2701   /* adjust the stack for parameters if
2702      required */
2703   if (ic->parmBytes) {
2704       int i;
2705       if (options.stack10bit) {
2706           if (ic->parmBytes <= 10) {
2707               emitcode(";","stack adjustment for parms");
2708               for (i=0; i < ic->parmBytes ; i++) {
2709                   emitcode("pop","acc");
2710               }
2711           } else {            
2712               PROTECT_SP;
2713               emitcode ("clr","c");
2714               emitcode ("mov","a,sp");
2715               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2716               emitcode ("mov","sp,a");
2717               emitcode ("mov","a,esp");
2718               adjustEsp("a");
2719               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2720               emitcode ("mov","esp,a");   
2721               UNPROTECT_SP;
2722           }
2723       } else {
2724           if (ic->parmBytes > 3) {
2725               emitcode ("mov", "a,%s", spname);
2726               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2727               emitcode ("mov", "%s,a", spname);
2728           } else
2729               for (i = 0; i < ic->parmBytes; i++)
2730                   emitcode ("dec", "%s", spname);
2731       }
2732   }
2733
2734   /* if we hade saved some registers then unsave them */
2735   if (ic->regsSaved)
2736     unsaveRegisters (ic);
2737
2738   /* if register bank was saved then pop them */
2739   if (restoreBank)
2740     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2741 }
2742
2743 /*-----------------------------------------------------------------*/
2744 /* genPcall - generates a call by pointer statement                */
2745 /*-----------------------------------------------------------------*/
2746 static void
2747 genPcall (iCode * ic)
2748 {
2749   sym_link *dtype;
2750   symbol *rlbl = newiTempLabel (NULL);
2751   bool restoreBank=FALSE;
2752
2753   D (emitcode (";", "genPcall ");
2754     );
2755
2756
2757   /* if caller saves & we have not saved then */
2758   if (!ic->regsSaved)
2759     saveRegisters (ic);
2760
2761   /* if we are calling a function that is not using
2762      the same register bank then we need to save the
2763      destination registers on the stack */
2764   dtype = operandType (IC_LEFT (ic));
2765   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2766       IFFUNC_ISISR (currFunc->type) &&
2767       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2768     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2769     restoreBank=TRUE;
2770   }
2771
2772   /* push the return address on to the stack */
2773   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2774   emitcode ("push", "acc");
2775   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2776   emitcode ("push", "acc");
2777
2778   if (options.model == MODEL_FLAT24)
2779     {
2780       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2781       emitcode ("push", "acc");
2782     }
2783
2784   /* now push the calling address */
2785   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2786
2787   pushSide (IC_LEFT (ic), FPTRSIZE);
2788
2789   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2790
2791   /* if send set is not empty the assign */
2792   if (_G.sendSet)
2793     {
2794         genSend(reverseSet(_G.sendSet));
2795         _G.sendSet = NULL;
2796     }
2797
2798   emitcode ("ret", "");
2799   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2800
2801
2802   /* if we need assign a result value */
2803   if ((IS_ITEMP (IC_RESULT (ic)) &&
2804        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2805         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2806       IS_TRUE_SYMOP (IC_RESULT (ic)))
2807     {
2808
2809       _G.accInUse++;
2810       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2811       _G.accInUse--;
2812
2813       assignResultValue (IC_RESULT (ic));
2814
2815       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2816     }
2817
2818   /* adjust the stack for parameters if
2819      required */
2820   if (ic->parmBytes)
2821     {
2822       int i;
2823       if (options.stack10bit) {
2824           if (ic->parmBytes <= 10) {
2825               emitcode(";","stack adjustment for parms");
2826               for (i=0; i < ic->parmBytes ; i++) {
2827                   emitcode("pop","acc");
2828               }
2829           } else {            
2830               PROTECT_SP;
2831               emitcode ("clr","c");
2832               emitcode ("mov","a,sp");
2833               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2834               emitcode ("mov","sp,a");
2835               emitcode ("mov","a,esp");
2836               adjustEsp("a");
2837               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2838               emitcode ("mov","esp,a");   
2839               UNPROTECT_SP;
2840           }
2841       } else {
2842           if (ic->parmBytes > 3) {
2843               emitcode ("mov", "a,%s", spname);
2844               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2845               emitcode ("mov", "%s,a", spname);
2846           }
2847           else
2848               for (i = 0; i < ic->parmBytes; i++)
2849                   emitcode ("dec", "%s", spname);
2850           
2851       }
2852     }
2853   /* if register bank was saved then unsave them */
2854   if (restoreBank)
2855     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2856   
2857   /* if we hade saved some registers then
2858      unsave them */
2859   if (ic->regsSaved)
2860     unsaveRegisters (ic);
2861
2862 }
2863
2864 /*-----------------------------------------------------------------*/
2865 /* resultRemat - result  is rematerializable                       */
2866 /*-----------------------------------------------------------------*/
2867 static int
2868 resultRemat (iCode * ic)
2869 {
2870   if (SKIP_IC (ic) || ic->op == IFX)
2871     return 0;
2872
2873   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2874     {
2875       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2876       if (sym->remat && !POINTER_SET (ic))
2877         return 1;
2878     }
2879
2880   return 0;
2881 }
2882
2883 #if defined(__BORLANDC__) || defined(_MSC_VER)
2884 #define STRCASECMP stricmp
2885 #else
2886 #define STRCASECMP strcasecmp
2887 #endif
2888
2889 /*-----------------------------------------------------------------*/
2890 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2891 /*-----------------------------------------------------------------*/
2892 static int
2893 regsCmp(void *p1, void *p2)
2894 {
2895   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2896 }
2897
2898 static bool
2899 inExcludeList (char *s)
2900 {
2901   const char *p = setFirstItem(options.excludeRegsSet);
2902
2903   if (p == NULL || STRCASECMP(p, "none") == 0)
2904     return FALSE;
2905
2906
2907   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2908 }
2909
2910 /*-----------------------------------------------------------------*/
2911 /* genFunction - generated code for function entry                 */
2912 /*-----------------------------------------------------------------*/
2913 static void
2914 genFunction (iCode * ic)
2915 {
2916   symbol *sym;
2917   sym_link *ftype;
2918   bool   switchedPSW = FALSE;
2919
2920   D (emitcode (";", "genFunction "););
2921
2922   _G.nRegsSaved = 0;
2923   /* create the function header */
2924   emitcode (";", "-----------------------------------------");
2925   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2926   emitcode (";", "-----------------------------------------");
2927
2928   emitcode ("", "%s:", sym->rname);
2929   ftype = operandType (IC_LEFT (ic));
2930
2931   if (IFFUNC_ISNAKED(ftype))
2932   {
2933       emitcode(";", "naked function: no prologue.");
2934       return;
2935   }
2936   
2937   if (options.stack_probe) 
2938       emitcode ("lcall","__stack_probe");
2939
2940   /* here we need to generate the equates for the
2941      register bank if required */
2942   if (FUNC_REGBANK (ftype) != rbank)
2943     {
2944       int i;
2945
2946       rbank = FUNC_REGBANK (ftype);
2947       for (i = 0; i < ds390_nRegs; i++)
2948         {
2949           if (regs390[i].print) {
2950               if (strcmp (regs390[i].base, "0") == 0)
2951                   emitcode ("", "%s !equ !constbyte",
2952                             regs390[i].dname,
2953                             8 * rbank + regs390[i].offset);
2954               else
2955                   emitcode ("", "%s !equ %s + !constbyte",
2956                             regs390[i].dname,
2957                             regs390[i].base,
2958                             8 * rbank + regs390[i].offset);
2959           }
2960         }
2961     }
2962
2963   /* if this is an interrupt service routine then
2964      save acc, b, dpl, dph  */
2965   if (IFFUNC_ISISR (sym->type))
2966       { /* is ISR */
2967       if (!inExcludeList ("acc"))
2968         emitcode ("push", "acc");
2969       if (!inExcludeList ("b"))
2970         emitcode ("push", "b");
2971       if (!inExcludeList ("dpl"))
2972         emitcode ("push", "dpl");
2973       if (!inExcludeList ("dph"))
2974         emitcode ("push", "dph");
2975       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2976         {
2977           emitcode ("push", "dpx");
2978           /* Make sure we're using standard DPTR */
2979           emitcode ("push", "dps");
2980           emitcode ("mov", "dps,#0");
2981           if (options.stack10bit)
2982             {
2983               /* This ISR could conceivably use DPTR2. Better save it. */
2984               emitcode ("push", "dpl1");
2985               emitcode ("push", "dph1");
2986               emitcode ("push", "dpx1");
2987               emitcode ("push",  DP2_RESULT_REG);
2988             }
2989         }
2990       /* if this isr has no bank i.e. is going to
2991          run with bank 0 , then we need to save more
2992          registers :-) */
2993       if (!FUNC_REGBANK (sym->type))
2994         {
2995             int i;
2996
2997           /* if this function does not call any other
2998              function then we can be economical and
2999              save only those registers that are used */
3000           if (!IFFUNC_HASFCALL(sym->type))
3001             {
3002
3003               /* if any registers used */
3004               if (sym->regsUsed)
3005                 {
3006                   /* save the registers used */
3007                   for (i = 0; i < sym->regsUsed->size; i++)
3008                     {
3009                       if (bitVectBitValue (sym->regsUsed, i) ||
3010                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3011                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3012                     }
3013                 }
3014
3015             }
3016           else
3017             {
3018               /* this function has  a function call cannot
3019                  determines register usage so we will have to push the
3020                  entire bank */
3021               saveRBank (0, ic, FALSE);
3022               if (options.parms_in_bank1) {
3023                   for (i=0; i < 8 ; i++ ) {
3024                       emitcode ("push","%s",rb1regs[i]);
3025                   }
3026               }
3027             }
3028         }
3029         else
3030         {
3031             /* This ISR uses a non-zero bank.
3032              *
3033              * We assume that the bank is available for our
3034              * exclusive use.
3035              *
3036              * However, if this ISR calls a function which uses some
3037              * other bank, we must save that bank entirely.
3038              */
3039             unsigned long banksToSave = 0;
3040             
3041             if (IFFUNC_HASFCALL(sym->type))
3042             {
3043
3044 #define MAX_REGISTER_BANKS 4
3045
3046                 iCode *i;
3047                 int ix;
3048
3049                 for (i = ic; i; i = i->next)
3050                 {
3051                     if (i->op == ENDFUNCTION)
3052                     {
3053                         /* we got to the end OK. */
3054                         break;
3055                     }
3056                     
3057                     if (i->op == CALL)
3058                     {
3059                         sym_link *dtype;
3060                         
3061                         dtype = operandType (IC_LEFT(i));
3062                         if (dtype 
3063                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3064                         {
3065                              /* Mark this bank for saving. */
3066                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3067                              {
3068                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3069                              }
3070                              else
3071                              {
3072                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3073                              }
3074                              
3075                              /* And note that we don't need to do it in 
3076                               * genCall.
3077                               */
3078                              i->bankSaved = 1;
3079                         }
3080                     }
3081                     if (i->op == PCALL)
3082                     {
3083                         /* This is a mess; we have no idea what
3084                          * register bank the called function might
3085                          * use.
3086                          *
3087                          * The only thing I can think of to do is
3088                          * throw a warning and hope.
3089                          */
3090                         werror(W_FUNCPTR_IN_USING_ISR);   
3091                     }
3092                 }
3093
3094                 if (banksToSave && options.useXstack)
3095                 {
3096                     /* Since we aren't passing it an ic, 
3097                      * saveRBank will assume r0 is available to abuse.
3098                      *
3099                      * So switch to our (trashable) bank now, so
3100                      * the caller's R0 isn't trashed.
3101                      */
3102                     emitcode ("push", "psw");
3103                     emitcode ("mov", "psw,#!constbyte", 
3104                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3105                     switchedPSW = TRUE;
3106                 }
3107                 
3108                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3109                 {
3110                      if (banksToSave & (1 << ix))
3111                      {
3112                          saveRBank(ix, NULL, FALSE);
3113                      }
3114                 }
3115             }
3116             // TODO: this needs a closer look
3117             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3118         }
3119     }
3120   else
3121     {
3122       /* if callee-save to be used for this function
3123          then save the registers being used in this function */
3124       if (IFFUNC_CALLEESAVES(sym->type))
3125         {
3126           int i;
3127
3128           /* if any registers used */
3129           if (sym->regsUsed)
3130             {
3131               /* save the registers used */
3132               for (i = 0; i < sym->regsUsed->size; i++)
3133                 {
3134                   if (bitVectBitValue (sym->regsUsed, i) ||
3135                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3136                     {
3137                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3138                       _G.nRegsSaved++;
3139                     }
3140                 }
3141             }
3142         }
3143     }
3144
3145   /* set the register bank to the desired value */
3146   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3147    && !switchedPSW)
3148     {
3149       emitcode ("push", "psw");
3150       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3151     }
3152
3153   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3154        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3155       if (options.stack10bit) {
3156           emitcode ("push","_bpx");
3157           emitcode ("push","_bpx+1");
3158           emitcode ("mov","_bpx,%s",spname);
3159           emitcode ("mov","_bpx+1,esp");
3160           adjustEsp("_bpx+1");
3161       } else {
3162           if (options.useXstack) {
3163               emitcode ("mov", "r0,%s", spname);
3164               emitcode ("mov", "a,_bp");
3165               emitcode ("movx", "@r0,a");
3166               emitcode ("inc", "%s", spname);
3167           } else {
3168               /* set up the stack */
3169               emitcode ("push", "_bp"); /* save the callers stack  */
3170           }
3171           emitcode ("mov", "_bp,%s", spname);
3172       }
3173   }
3174
3175   /* adjust the stack for the function */
3176   if (sym->stack) {
3177       int i = sym->stack;
3178       if (options.stack10bit) {
3179           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3180           assert (sym->recvSize <= 4);
3181           if (sym->stack <= 8) {
3182               while (i--) emitcode ("push","acc");
3183           } else {
3184               PROTECT_SP;
3185               emitcode ("mov","a,sp");
3186               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3187               emitcode ("mov","sp,a");
3188               emitcode ("mov","a,esp");
3189               adjustEsp("a");
3190               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3191               emitcode ("mov","esp,a");
3192               UNPROTECT_SP;
3193           }
3194       } else {
3195           if (i > 256)
3196               werror (W_STACK_OVERFLOW, sym->name);
3197           
3198           if (i > 3 && sym->recvSize < 4) {
3199               
3200               emitcode ("mov", "a,sp");
3201               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3202               emitcode ("mov", "sp,a");
3203               
3204           } else
3205               while (i--)
3206                   emitcode ("inc", "sp");
3207       }
3208   }
3209
3210   if (sym->xstack)
3211     {
3212
3213       emitcode ("mov", "a,_spx");
3214       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3215       emitcode ("mov", "_spx,a");
3216     }
3217   
3218   /* if critical function then turn interrupts off */
3219   if (IFFUNC_ISCRITICAL (ftype))
3220     {
3221       symbol *tlbl = newiTempLabel (NULL);
3222       emitcode ("setb", "c");
3223       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3224       emitcode ("clr", "c");
3225       emitcode ("", "%05d$:", (tlbl->key + 100));
3226       emitcode ("push", "psw"); /* save old ea via c in psw */
3227     }
3228
3229 }
3230
3231 /*-----------------------------------------------------------------*/
3232 /* genEndFunction - generates epilogue for functions               */
3233 /*-----------------------------------------------------------------*/
3234 static void
3235 genEndFunction (iCode * ic)
3236 {
3237   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3238
3239   D (emitcode (";", "genEndFunction "););
3240
3241   if (IFFUNC_ISNAKED(sym->type))
3242   {
3243       emitcode(";", "naked function: no epilogue.");
3244       return;
3245   }
3246
3247   if (IFFUNC_ISCRITICAL (sym->type))
3248     {
3249       emitcode ("pop", "psw"); /* restore ea via c in psw */
3250       emitcode ("mov", "ea,c");
3251     }
3252   
3253   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3254        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3255
3256       if (options.stack10bit) {
3257           PROTECT_SP;     
3258           emitcode ("mov", "sp,_bpx", spname);
3259           emitcode ("mov", "esp,_bpx+1", spname);
3260           UNPROTECT_SP;
3261       } else {
3262           emitcode ("mov", "%s,_bp", spname);
3263       }
3264   }
3265
3266   /* if use external stack but some variables were
3267      added to the local stack then decrement the
3268      local stack */
3269   if (options.useXstack && sym->stack) {
3270       emitcode ("mov", "a,sp");
3271       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3272       emitcode ("mov", "sp,a");
3273   }
3274
3275
3276   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3277        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3278
3279       if (options.useXstack) {
3280           emitcode ("mov", "r0,%s", spname);
3281           emitcode ("movx", "a,@r0");
3282           emitcode ("mov", "_bp,a");
3283           emitcode ("dec", "%s", spname);
3284       } else {
3285           if (options.stack10bit) {
3286               emitcode ("pop", "_bpx+1");
3287               emitcode ("pop", "_bpx");
3288           } else {
3289               emitcode ("pop", "_bp");
3290           }
3291       }
3292   }
3293
3294   /* restore the register bank  */
3295   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3296   {
3297     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3298      || !options.useXstack)
3299     {
3300         /* Special case of ISR using non-zero bank with useXstack
3301          * is handled below.
3302          */
3303         emitcode ("pop", "psw");
3304     }
3305   } 
3306
3307   if (IFFUNC_ISISR (sym->type))
3308       { /* is ISR */  
3309
3310       /* now we need to restore the registers */
3311       /* if this isr has no bank i.e. is going to
3312          run with bank 0 , then we need to save more
3313          registers :-) */
3314       if (!FUNC_REGBANK (sym->type))
3315         {
3316             int i;
3317           /* if this function does not call any other
3318              function then we can be economical and
3319              save only those registers that are used */
3320           if (!IFFUNC_HASFCALL(sym->type))
3321             {
3322
3323               /* if any registers used */
3324               if (sym->regsUsed)
3325                 {
3326                   /* save the registers used */
3327                   for (i = sym->regsUsed->size; i >= 0; i--)
3328                     {
3329                       if (bitVectBitValue (sym->regsUsed, i) ||
3330                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3331                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3332                     }
3333                 }
3334
3335             }
3336           else
3337             {
3338               /* this function has  a function call cannot
3339                  determines register usage so we will have to pop the
3340                  entire bank */
3341               if (options.parms_in_bank1) {
3342                   for (i = 7 ; i >= 0 ; i-- ) {
3343                       emitcode ("pop","%s",rb1regs[i]);
3344                   }
3345               }
3346               unsaveRBank (0, ic, FALSE);
3347             }
3348         }
3349         else
3350         {
3351             /* This ISR uses a non-zero bank.
3352              *
3353              * Restore any register banks saved by genFunction
3354              * in reverse order.
3355              */
3356             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3357             int ix;
3358           
3359             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3360             {
3361                 if (savedBanks & (1 << ix))
3362                 {
3363                     unsaveRBank(ix, NULL, FALSE);
3364                 }
3365             }
3366             
3367             if (options.useXstack)
3368             {
3369                 /* Restore bank AFTER calling unsaveRBank,
3370                  * since it can trash r0.
3371                  */
3372                 emitcode ("pop", "psw");
3373             }
3374         }
3375
3376       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3377         {
3378           if (options.stack10bit)
3379             {
3380               emitcode ("pop", DP2_RESULT_REG);
3381               emitcode ("pop", "dpx1");
3382               emitcode ("pop", "dph1");
3383               emitcode ("pop", "dpl1");
3384             }
3385           emitcode ("pop", "dps");
3386           emitcode ("pop", "dpx");
3387         }
3388       if (!inExcludeList ("dph"))
3389         emitcode ("pop", "dph");
3390       if (!inExcludeList ("dpl"))
3391         emitcode ("pop", "dpl");
3392       if (!inExcludeList ("b"))
3393         emitcode ("pop", "b");
3394       if (!inExcludeList ("acc"))
3395         emitcode ("pop", "acc");
3396
3397       /* if debug then send end of function */
3398       if (options.debug && currFunc) {
3399           _G.debugLine = 1;
3400           emitcode ("", "C$%s$%d$%d$%d ==.",
3401                     FileBaseName (ic->filename), currFunc->lastLine,
3402                     ic->level, ic->block);
3403           if (IS_STATIC (currFunc->etype))
3404             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3405           else
3406             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3407           _G.debugLine = 0;
3408         }
3409
3410       emitcode ("reti", "");
3411     }
3412   else
3413     {
3414       if (IFFUNC_CALLEESAVES(sym->type))
3415         {
3416           int i;
3417
3418           /* if any registers used */
3419           if (sym->regsUsed)
3420             {
3421               /* save the registers used */
3422               for (i = sym->regsUsed->size; i >= 0; i--)
3423                 {
3424                   if (bitVectBitValue (sym->regsUsed, i) ||
3425                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3426                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3427                 }
3428             }
3429
3430         }
3431
3432       /* if debug then send end of function */
3433       if (options.debug && currFunc)
3434         {
3435           _G.debugLine = 1;
3436           emitcode ("", "C$%s$%d$%d$%d ==.",
3437                     FileBaseName (ic->filename), currFunc->lastLine,
3438                     ic->level, ic->block);
3439           if (IS_STATIC (currFunc->etype))
3440             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3441           else
3442             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3443           _G.debugLine = 0;
3444         }
3445
3446       emitcode ("ret", "");
3447     }
3448
3449 }
3450
3451 /*-----------------------------------------------------------------*/
3452 /* genJavaNativeRet - generate code for return JavaNative          */
3453 /*-----------------------------------------------------------------*/
3454 static void genJavaNativeRet(iCode *ic)
3455 {
3456     int i, size;
3457
3458     aopOp (IC_LEFT (ic), ic, FALSE, 
3459            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3460     size = AOP_SIZE (IC_LEFT (ic));
3461
3462     assert (size <= 4);
3463
3464     /* it is assigned to GPR0-R3 then push them */
3465     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3466         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3467         for (i = 0 ; i < size ; i++ ) {
3468             emitcode ("push","%s",
3469                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3470         }
3471         for (i = (size-1) ; i >= 0 ; i--) {
3472             emitcode ("pop","a%s",javaRet[i]);
3473         }
3474     } else {
3475         for (i = 0 ; i < size ; i++) 
3476             emitcode ("mov","%s,%s",javaRet[i],
3477                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3478     }
3479     for (i = size ; i < 4 ; i++ )
3480             emitcode ("mov","%s,#0",javaRet[i]);
3481     return;
3482 }
3483
3484 /*-----------------------------------------------------------------*/
3485 /* genRet - generate code for return statement                     */
3486 /*-----------------------------------------------------------------*/
3487 static void
3488 genRet (iCode * ic)
3489 {
3490   int size, offset = 0, pushed = 0;
3491
3492   D (emitcode (";", "genRet "););
3493
3494   /* if we have no return value then
3495      just generate the "ret" */
3496   if (!IC_LEFT (ic))
3497     goto jumpret;
3498
3499   /* if this is a JavaNative function then return 
3500      value in different register */
3501   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3502       genJavaNativeRet(ic);
3503       goto jumpret;
3504   }
3505   /* we have something to return then
3506      move the return value into place */
3507   aopOp (IC_LEFT (ic), ic, FALSE, 
3508          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3509   size = AOP_SIZE (IC_LEFT (ic));
3510
3511   _startLazyDPSEvaluation ();
3512   while (size--)
3513     {
3514       char *l;
3515       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3516         {
3517           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3518                       FALSE, TRUE, NULL);
3519           emitcode ("push", "%s", l);
3520           pushed++;
3521         }
3522       else
3523         {
3524           /* Since A is the last element of fReturn,
3525            * is is OK to clobber it in the aopGet.
3526            */
3527           l = aopGet (AOP (IC_LEFT (ic)), offset,
3528                       FALSE, FALSE, NULL);
3529           if (strcmp (fReturn[offset], l))
3530             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3531         }
3532     }
3533   _endLazyDPSEvaluation ();
3534
3535   if (pushed)
3536     {
3537       while (pushed)
3538         {
3539           pushed--;
3540           if (strcmp (fReturn[pushed], "a"))
3541             emitcode ("pop", fReturn[pushed]);
3542           else
3543             emitcode ("pop", "acc");
3544         }
3545     }
3546   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3547
3548 jumpret:
3549   /* generate a jump to the return label
3550      if the next is not the return statement */
3551   if (!(ic->next && ic->next->op == LABEL &&
3552         IC_LABEL (ic->next) == returnLabel))
3553
3554     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3555
3556 }
3557
3558 /*-----------------------------------------------------------------*/
3559 /* genLabel - generates a label                                    */
3560 /*-----------------------------------------------------------------*/
3561 static void
3562 genLabel (iCode * ic)
3563 {
3564   /* special case never generate */
3565   if (IC_LABEL (ic) == entryLabel)
3566     return;
3567
3568   D (emitcode (";", "genLabel ");
3569     );
3570
3571   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3572 }
3573
3574 /*-----------------------------------------------------------------*/
3575 /* genGoto - generates a ljmp                                      */
3576 /*-----------------------------------------------------------------*/
3577 static void
3578 genGoto (iCode * ic)
3579 {
3580   D (emitcode (";", "genGoto ");
3581     );
3582   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3583 }
3584
3585 /*-----------------------------------------------------------------*/
3586 /* findLabelBackwards: walks back through the iCode chain looking  */
3587 /* for the given label. Returns number of iCode instructions     */
3588 /* between that label and given ic.          */
3589 /* Returns zero if label not found.          */
3590 /*-----------------------------------------------------------------*/
3591 static int
3592 findLabelBackwards (iCode * ic, int key)
3593 {
3594   int count = 0;
3595
3596   while (ic->prev)
3597     {
3598       ic = ic->prev;
3599       count++;
3600
3601       /* If we have any pushes or pops, we cannot predict the distance.
3602          I don't like this at all, this should be dealt with in the 
3603          back-end */
3604       if (ic->op == IPUSH || ic->op == IPOP) {
3605         return 0;
3606       }
3607
3608       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3609         {
3610           /* printf("findLabelBackwards = %d\n", count); */
3611           return count;
3612         }
3613     }
3614
3615   return 0;
3616 }
3617
3618 /*-----------------------------------------------------------------*/
3619 /* genPlusIncr :- does addition with increment if possible         */
3620 /*-----------------------------------------------------------------*/
3621 static bool
3622 genPlusIncr (iCode * ic)
3623 {
3624   unsigned int icount;
3625   unsigned int size = getDataSize (IC_RESULT (ic));
3626
3627   /* will try to generate an increment */
3628   /* if the right side is not a literal
3629      we cannot */
3630   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3631     return FALSE;
3632
3633   /* if the literal value of the right hand side
3634      is greater than 4 then it is not worth it */
3635   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3636     return FALSE;
3637
3638   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3639       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3640       while (icount--) {
3641           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3642       }
3643       return TRUE;
3644   }
3645   /* if increment 16 bits in register */
3646   if (
3647        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3648        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3649        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3650        (size > 1) &&
3651        (icount == 1))
3652     {
3653       symbol  *tlbl;
3654       int     emitTlbl;
3655       int     labelRange;
3656       char    *l;
3657
3658       /* If the next instruction is a goto and the goto target
3659        * is <= 5 instructions previous to this, we can generate
3660        * jumps straight to that target.
3661        */
3662       if (ic->next && ic->next->op == GOTO
3663           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3664           && labelRange <= 5)
3665         {
3666           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3667           tlbl = IC_LABEL (ic->next);
3668           emitTlbl = 0;
3669         }
3670       else
3671         {
3672           tlbl = newiTempLabel (NULL);
3673           emitTlbl = 1;
3674         }
3675         
3676       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3677       emitcode ("inc", "%s", l);
3678       
3679       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3680           IS_AOP_PREG (IC_RESULT (ic)))
3681       {   
3682         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3683       }
3684       else
3685       {
3686           emitcode ("clr", "a");
3687           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3688       }
3689
3690       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3691       emitcode ("inc", "%s", l);
3692       if (size > 2)
3693         {
3694             if (!strcmp(l, "acc"))
3695             {
3696                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3697             }
3698             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3699                      IS_AOP_PREG (IC_RESULT (ic)))
3700             {
3701                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3702             }
3703             else
3704             {
3705                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3706             }
3707
3708             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3709             emitcode ("inc", "%s", l);
3710         }
3711       if (size > 3)
3712         {
3713             if (!strcmp(l, "acc"))
3714             {
3715                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3716             }
3717             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3718                      IS_AOP_PREG (IC_RESULT (ic)))
3719             {
3720                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3721             }
3722             else
3723             {
3724                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3725             }
3726
3727             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3728             emitcode ("inc", "%s", l);  }
3729
3730       if (emitTlbl)
3731         {
3732           emitcode ("", "!tlabeldef", tlbl->key + 100);
3733         }
3734       return TRUE;
3735     }
3736
3737   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3738       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3739       options.model == MODEL_FLAT24 ) {
3740
3741       switch (size) {
3742       case 3:
3743           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3744       case 2:
3745           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3746       case 1:
3747           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3748           break;
3749       }
3750       while (icount--) emitcode ("inc","dptr");      
3751       return TRUE;
3752   }
3753
3754   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3755       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3756       icount <= 5 ) {
3757       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3758       while (icount--) emitcode ("inc","dptr");
3759       emitcode ("mov","dps,#0");
3760       return TRUE;
3761   }
3762
3763   /* if the sizes are greater than 1 then we cannot */
3764   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3765       AOP_SIZE (IC_LEFT (ic)) > 1)
3766     return FALSE;
3767
3768   /* we can if the aops of the left & result match or
3769      if they are in registers and the registers are the
3770      same */
3771   if (
3772        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3773        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3774        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3775     {
3776
3777       if (icount > 3)
3778         {
3779           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3780           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3781           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3782         }
3783       else
3784         {
3785
3786           _startLazyDPSEvaluation ();
3787           while (icount--)
3788             {
3789               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3790             }
3791           _endLazyDPSEvaluation ();
3792         }
3793
3794       return TRUE;
3795     }
3796
3797   return FALSE;
3798 }
3799
3800 /*-----------------------------------------------------------------*/
3801 /* outBitAcc - output a bit in acc                                 */
3802 /*-----------------------------------------------------------------*/
3803 static void
3804 outBitAcc (operand * result)
3805 {
3806   symbol *tlbl = newiTempLabel (NULL);
3807   /* if the result is a bit */
3808   if (AOP_TYPE (result) == AOP_CRY)
3809     {
3810       aopPut (AOP (result), "a", 0);
3811     }
3812   else
3813     {
3814       emitcode ("jz", "!tlabel", tlbl->key + 100);
3815       emitcode ("mov", "a,%s", one);
3816       emitcode ("", "!tlabeldef", tlbl->key + 100);
3817       outAcc (result);
3818     }
3819 }
3820
3821 /*-----------------------------------------------------------------*/
3822 /* genPlusBits - generates code for addition of two bits           */
3823 /*-----------------------------------------------------------------*/
3824 static void
3825 genPlusBits (iCode * ic)
3826 {
3827   D (emitcode (";", "genPlusBits "););
3828     
3829   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3830     {
3831       symbol *lbl = newiTempLabel (NULL);
3832       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3833       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3834       emitcode ("cpl", "c");
3835       emitcode ("", "!tlabeldef", (lbl->key + 100));
3836       outBitC (IC_RESULT (ic));
3837     }
3838   else
3839     {
3840       emitcode ("clr", "a");
3841       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3842       emitcode ("rlc", "a");
3843       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3844       emitcode ("addc", "a,#0");
3845       outAcc (IC_RESULT (ic));
3846     }
3847 }
3848
3849 static void
3850 adjustArithmeticResult (iCode * ic)
3851 {
3852   if (opIsGptr (IC_RESULT (ic)) &&
3853       opIsGptr (IC_LEFT (ic)) &&
3854       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3855     {
3856       aopPut (AOP (IC_RESULT (ic)),
3857               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3858               GPTRSIZE - 1);
3859     }
3860
3861   if (opIsGptr (IC_RESULT (ic)) &&
3862       opIsGptr (IC_RIGHT (ic)) &&
3863       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3864     {
3865       aopPut (AOP (IC_RESULT (ic)),
3866             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3867               GPTRSIZE - 1);
3868     }
3869
3870   if (opIsGptr (IC_RESULT (ic)) &&
3871       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3872       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3873       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3874       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3875     {
3876       char buff[5];
3877       SNPRINTF (buff, sizeof(buff), 
3878                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3879       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3880     }
3881 }
3882
3883 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3884 // generates the result if possible. If result is generated, returns TRUE; otherwise
3885 // returns false and caller must deal with fact that result isn't aopOp'd.
3886 bool aopOp3(iCode * ic)
3887 {
3888     bool dp1InUse, dp2InUse;
3889     bool useDp2;
3890     
3891     // First, generate the right opcode. DPTR may be used if neither left nor result are
3892     // of type AOP_STR.
3893     
3894 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3895 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3896 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3897 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3898 //      );
3899 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3900 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3901 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3902 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3903 //      );
3904     
3905     // Right uses DPTR unless left or result is an AOP_STR; however,
3906     // if right is an AOP_STR, it must use DPTR regardless.
3907     if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3908      && !AOP_IS_STR(IC_RIGHT(ic)))
3909     {
3910         useDp2 = TRUE;
3911     }
3912     else
3913     {
3914         useDp2 = FALSE;
3915     }
3916         
3917     aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3918     
3919     // if the right used DPTR, left MUST use DPTR2.
3920     // if the right used DPTR2, left MUST use DPTR.
3921     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3922     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3923     // enabling us to assign DPTR to result.
3924      
3925     if (AOP_USESDPTR(IC_RIGHT(ic)))
3926     {
3927         useDp2 = TRUE;
3928     }
3929     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3930     {
3931         useDp2 = FALSE;
3932     }
3933     else
3934     {
3935         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3936         {
3937             useDp2 = TRUE;
3938         }
3939         else
3940         {
3941             useDp2 = FALSE;
3942         }
3943     }
3944
3945     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3946
3947         
3948     // We've op'd the left & right. So, if left or right are the same operand as result, 
3949     // we know aopOp will succeed, and we can just do it & bail.
3950     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3951         isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3952     {
3953 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
3954         aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3955         return TRUE;
3956     }
3957     
3958     // Operands may be equivalent (but not equal) if they share a spill location. If
3959     // so, use the same DPTR or DPTR2.
3960     if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
3961       {
3962         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
3963         return TRUE;
3964       }
3965     if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
3966       {
3967         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
3968         return TRUE;
3969       }
3970     
3971     // Note which dptrs are currently in use.
3972     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3973     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3974     
3975     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
3976     // generate it.
3977     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3978     {
3979         return FALSE;
3980     }
3981     
3982     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3983     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3984     {
3985         return FALSE;
3986     }
3987     
3988     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
3989     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3990     {
3991         return FALSE;
3992     }
3993
3994     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3995
3996     // Some sanity checking...
3997     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3998     {
3999         fprintf(stderr,
4000                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4001                 __FILE__, __LINE__, ic->filename, ic->lineno);  
4002         emitcode(";", ">>> unexpected DPTR here.");
4003     }
4004     
4005     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4006     {
4007         fprintf(stderr,
4008                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4009                 __FILE__, __LINE__, ic->filename, ic->lineno);  
4010         emitcode(";", ">>> unexpected DPTR2 here.");
4011     }    
4012     
4013     return TRUE;
4014 }
4015
4016 // Macro to aopOp all three operands of an ic. If this cannot be done, 
4017 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4018 // will be set TRUE. The caller must then handle the case specially, noting
4019 // that the IC_RESULT operand is not aopOp'd.
4020 // 
4021 #define AOP_OP_3_NOFATAL(ic, rc) \
4022             do { rc = !aopOp3(ic); } while (0)
4023
4024 // aopOp the left & right operands of an ic.
4025 #define AOP_OP_2(ic) \
4026     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4027     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4028
4029 // convienience macro.
4030 #define AOP_SET_LOCALS(ic) \
4031     left = IC_LEFT(ic); \
4032     right = IC_RIGHT(ic); \
4033     result = IC_RESULT(ic);
4034
4035
4036 // Given an integer value of pushedSize bytes on the stack,
4037 // adjust it to be resultSize bytes, either by discarding
4038 // the most significant bytes or by zero-padding.
4039 //
4040 // On exit from this macro, pushedSize will have been adjusted to
4041 // equal resultSize, and ACC may be trashed.
4042 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
4043       /* If the pushed data is bigger than the result,          \
4044        * simply discard unused bytes. Icky, but works.          \
4045        */                                                       \
4046       while (pushedSize > resultSize)                           \
4047       {                                                         \
4048           D (emitcode (";", "discarding unused result byte."););\
4049           emitcode ("pop", "acc");                              \
4050           pushedSize--;                                         \
4051       }                                                         \
4052       if (pushedSize < resultSize)                              \
4053       {                                                         \
4054           emitcode ("clr", "a");                                \
4055           /* Conversly, we haven't pushed enough here.          \
4056            * just zero-pad, and all is well.                    \
4057            */                                                   \
4058           while (pushedSize < resultSize)                       \
4059           {                                                     \
4060               emitcode("push", "acc");                          \
4061               pushedSize++;                                     \
4062           }                                                     \
4063       }                                                         \
4064       assert(pushedSize == resultSize);
4065
4066 /*-----------------------------------------------------------------*/
4067 /* genPlus - generates code for addition                           */
4068 /*-----------------------------------------------------------------*/
4069 static void
4070 genPlus (iCode * ic)
4071 {
4072   int size, offset = 0;
4073   bool pushResult;
4074   int rSize;
4075
4076   D (emitcode (";", "genPlus "););
4077
4078   /* special cases :- */
4079   if ( AOP_IS_STR(IC_LEFT(ic)) &&
4080       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4081       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4082       size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4083       if (size <= 9) {
4084           while (size--) emitcode ("inc","dptr");
4085       } else {
4086           emitcode ("mov","a,dpl");
4087           emitcode ("add","a,#!constbyte",size & 0xff);
4088           emitcode ("mov","dpl,a");
4089           emitcode ("mov","a,dph");
4090           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4091           emitcode ("mov","dph,a");
4092           emitcode ("mov","a,dpx");
4093           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4094           emitcode ("mov","dpx,a");
4095       }
4096       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4097       return ;
4098   }
4099   if ( IS_SYMOP(IC_LEFT(ic)) && 
4100        OP_SYMBOL(IC_LEFT(ic))->remat &&
4101        isOperandInFarSpace(IC_RIGHT(ic))) {
4102       operand *op = IC_RIGHT(ic);
4103       IC_RIGHT(ic) = IC_LEFT(ic);
4104       IC_LEFT(ic) = op;
4105   }
4106                 
4107   AOP_OP_3_NOFATAL (ic, pushResult);
4108     
4109   if (pushResult)
4110     {
4111       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4112     }
4113
4114   if (!pushResult)
4115     {
4116       /* if literal, literal on the right or
4117          if left requires ACC or right is already
4118          in ACC */
4119       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4120        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4121           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4122         {
4123           operand *t = IC_RIGHT (ic);
4124           IC_RIGHT (ic) = IC_LEFT (ic);
4125           IC_LEFT (ic) = t;
4126           emitcode (";", "Swapped plus args.");
4127         }
4128
4129       /* if both left & right are in bit
4130          space */
4131       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4132           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4133         {
4134           genPlusBits (ic);
4135           goto release;
4136         }
4137
4138       /* if left in bit space & right literal */
4139       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4140           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4141         {
4142           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4143           /* if result in bit space */
4144           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4145             {
4146               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4147                 emitcode ("cpl", "c");
4148               outBitC (IC_RESULT (ic));
4149             }
4150           else
4151             {
4152               size = getDataSize (IC_RESULT (ic));
4153               _startLazyDPSEvaluation ();
4154               while (size--)
4155                 {
4156                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4157                   emitcode ("addc", "a,#0");
4158                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4159                 }
4160               _endLazyDPSEvaluation ();
4161             }
4162           goto release;
4163         }
4164
4165       /* if I can do an increment instead
4166          of add then GOOD for ME */
4167       if (genPlusIncr (ic) == TRUE)
4168         {
4169           emitcode (";", "did genPlusIncr");
4170           goto release;
4171         }
4172
4173     }
4174   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4175
4176   _startLazyDPSEvaluation ();
4177   while (size--)
4178     {
4179       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4180         {
4181           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4182           if (offset == 0)
4183             emitcode ("add", "a,%s",
4184                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4185           else
4186             emitcode ("addc", "a,%s",
4187                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4188         }
4189       else
4190         {
4191           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4192           {
4193               /* right is going to use ACC or we would have taken the
4194                * above branch.
4195                */
4196               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4197        TR_AP("#3");
4198               D(emitcode(";", "+ AOP_ACC special case."););
4199               emitcode("xch", "a, %s", DP2_RESULT_REG);
4200           }
4201           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4202           if (offset == 0)
4203           {
4204             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4205             {
4206          TR_AP("#4");
4207                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4208             }
4209             else
4210             {
4211                 emitcode ("add", "a,%s",
4212                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4213                                   DP2_RESULT_REG));
4214             }
4215           }
4216           else
4217           {
4218             emitcode ("addc", "a,%s",
4219                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4220                           DP2_RESULT_REG));
4221           }
4222         }
4223       if (!pushResult)
4224         {
4225           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4226         }
4227       else
4228         {
4229           emitcode ("push", "acc");
4230         }
4231       offset++;
4232     }
4233   _endLazyDPSEvaluation ();
4234
4235   if (pushResult)
4236     {
4237       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4238
4239       size = getDataSize (IC_LEFT (ic));
4240       rSize = getDataSize (IC_RESULT (ic));
4241
4242       ADJUST_PUSHED_RESULT(size, rSize);
4243
4244       _startLazyDPSEvaluation ();
4245       while (size--)
4246         {
4247           emitcode ("pop", "acc");
4248           aopPut (AOP (IC_RESULT (ic)), "a", size);
4249         }
4250       _endLazyDPSEvaluation ();
4251     }
4252
4253   adjustArithmeticResult (ic);
4254
4255 release:
4256   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4257   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4258   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4259 }
4260
4261 /*-----------------------------------------------------------------*/
4262 /* genMinusDec :- does subtraction with deccrement if possible     */
4263 /*-----------------------------------------------------------------*/
4264 static bool
4265 genMinusDec (iCode * ic)
4266 {
4267   unsigned int icount;
4268   unsigned int size = getDataSize (IC_RESULT (ic));
4269
4270   /* will try to generate an increment */
4271   /* if the right side is not a literal
4272      we cannot */
4273   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4274     return FALSE;
4275
4276   /* if the literal value of the right hand side
4277      is greater than 4 then it is not worth it */
4278   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4279     return FALSE;
4280
4281   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4282       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4283       while (icount--) {
4284           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4285       }
4286       return TRUE;
4287   }
4288   /* if decrement 16 bits in register */
4289   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4290       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4291       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4292       (size > 1) &&
4293       (icount == 1))
4294     {
4295       symbol *tlbl;
4296       int    emitTlbl;
4297       int    labelRange;
4298       char   *l;
4299
4300       /* If the next instruction is a goto and the goto target
4301          * is <= 5 instructions previous to this, we can generate
4302          * jumps straight to that target.
4303        */
4304       if (ic->next && ic->next->op == GOTO
4305           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4306           && labelRange <= 5)
4307         {
4308           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4309           tlbl = IC_LABEL (ic->next);
4310           emitTlbl = 0;
4311         }
4312       else
4313         {
4314           tlbl = newiTempLabel (NULL);
4315           emitTlbl = 1;
4316         }
4317
4318       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4319       emitcode ("dec", "%s", l);
4320  
4321       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4322           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4323           IS_AOP_PREG (IC_RESULT (ic)))
4324       {     
4325           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4326       }
4327       else
4328       {
4329           emitcode ("mov", "a,#!constbyte",0xff);
4330           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4331       }
4332       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4333       emitcode ("dec", "%s", l);
4334       if (size > 2)
4335         {
4336             if (!strcmp(l, "acc"))
4337             {
4338                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4339             }
4340             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4341                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4342                      IS_AOP_PREG (IC_RESULT (ic)))
4343             {       
4344                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4345             }
4346             else
4347             {
4348                 emitcode ("mov", "a,#!constbyte",0xff);
4349                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4350             }
4351             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4352             emitcode ("dec", "%s", l);
4353         }
4354       if (size > 3)
4355         {
4356             if (!strcmp(l, "acc"))
4357             {
4358                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4359             }
4360             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4361                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4362                      IS_AOP_PREG (IC_RESULT (ic)))
4363             {       
4364                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4365             }
4366             else
4367             {
4368                 emitcode ("mov", "a,#!constbyte",0xff);
4369                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4370             }       
4371             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4372             emitcode ("dec", "%s", l);
4373         }
4374       if (emitTlbl)
4375         {
4376           emitcode ("", "!tlabeldef", tlbl->key + 100);
4377         }
4378       return TRUE;
4379     }
4380
4381   /* if the sizes are greater than 1 then we cannot */
4382   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4383       AOP_SIZE (IC_LEFT (ic)) > 1)
4384     return FALSE;
4385
4386   /* we can if the aops of the left & result match or
4387      if they are in registers and the registers are the
4388      same */
4389   if (
4390        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4391        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4392        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4393     {
4394
4395       _startLazyDPSEvaluation ();
4396       while (icount--)
4397         {
4398           emitcode ("dec", "%s",
4399                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4400         }
4401       _endLazyDPSEvaluation ();
4402
4403       return TRUE;
4404     }
4405
4406   return FALSE;
4407 }
4408
4409 /*-----------------------------------------------------------------*/
4410 /* addSign - complete with sign                                    */
4411 /*-----------------------------------------------------------------*/
4412 static void
4413 addSign (operand * result, int offset, int sign)
4414 {
4415   int size = (getDataSize (result) - offset);
4416   if (size > 0)
4417     {
4418       _startLazyDPSEvaluation();
4419       if (sign)
4420         {
4421           emitcode ("rlc", "a");
4422           emitcode ("subb", "a,acc");
4423           while (size--)
4424           {
4425             aopPut (AOP (result), "a", offset++);
4426           }
4427         }
4428       else
4429       {
4430         while (size--)
4431         {
4432           aopPut (AOP (result), zero, offset++);
4433         }
4434       }
4435       _endLazyDPSEvaluation();
4436     }
4437 }
4438
4439 /*-----------------------------------------------------------------*/
4440 /* genMinusBits - generates code for subtraction  of two bits      */
4441 /*-----------------------------------------------------------------*/
4442 static void
4443 genMinusBits (iCode * ic)
4444 {
4445   symbol *lbl = newiTempLabel (NULL);
4446
4447   D (emitcode (";", "genMinusBits "););
4448
4449   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4450     {
4451       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4452       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4453       emitcode ("cpl", "c");
4454       emitcode ("", "!tlabeldef", (lbl->key + 100));
4455       outBitC (IC_RESULT (ic));
4456     }
4457   else
4458     {
4459       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4460       emitcode ("subb", "a,acc");
4461       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4462       emitcode ("inc", "a");
4463       emitcode ("", "!tlabeldef", (lbl->key + 100));
4464       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4465       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4466     }
4467 }
4468
4469 /*-----------------------------------------------------------------*/
4470 /* genMinus - generates code for subtraction                       */
4471 /*-----------------------------------------------------------------*/
4472 static void
4473 genMinus (iCode * ic)
4474 {
4475     int size, offset = 0;
4476     int rSize;
4477     long lit = 0L;
4478     bool pushResult;
4479
4480     D (emitcode (";", "genMinus "););
4481
4482     AOP_OP_3_NOFATAL(ic, pushResult);   
4483
4484     if (!pushResult)
4485     {
4486       /* special cases :- */
4487       /* if both left & right are in bit space */
4488       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4489           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4490         {
4491           genMinusBits (ic);
4492           goto release;
4493         }
4494
4495       /* if I can do an decrement instead
4496          of subtract then GOOD for ME */
4497       if (genMinusDec (ic) == TRUE)
4498         goto release;
4499
4500     }
4501
4502   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4503
4504   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4505     {
4506       CLRC;
4507     }
4508   else
4509     {
4510       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4511       lit = -lit;
4512     }
4513
4514
4515   /* if literal, add a,#-lit, else normal subb */
4516   _startLazyDPSEvaluation ();
4517   while (size--) {
4518       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4519           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4520               emitcode ("mov","b,%s",
4521                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4522               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4523               emitcode ("subb","a,b");
4524           } else {
4525               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4526               emitcode ("subb", "a,%s",
4527                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4528                                 DP2_RESULT_REG));
4529           }
4530       } else {
4531           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4532           /* first add without previous c */
4533           if (!offset) {
4534               if (!size && lit==-1) {
4535                   emitcode ("dec", "a");
4536               } else {
4537                   emitcode ("add", "a,#!constbyte",
4538                             (unsigned int) (lit & 0x0FFL));
4539               }
4540           } else {
4541               emitcode ("addc", "a,#!constbyte",
4542                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4543           }
4544       }
4545       
4546       if (pushResult) {
4547           emitcode ("push", "acc");
4548       } else {
4549           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4550       }
4551       offset++;
4552   }
4553   _endLazyDPSEvaluation ();
4554   
4555   if (pushResult)
4556     {
4557       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4558
4559       size = getDataSize (IC_LEFT (ic));
4560       rSize = getDataSize (IC_RESULT (ic));
4561
4562       ADJUST_PUSHED_RESULT(size, rSize);
4563
4564       _startLazyDPSEvaluation ();
4565       while (size--)
4566         {
4567           emitcode ("pop", "acc");
4568           aopPut (AOP (IC_RESULT (ic)), "a", size);
4569         }
4570       _endLazyDPSEvaluation ();
4571     }
4572
4573   adjustArithmeticResult (ic);
4574
4575 release:
4576   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4577   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4578   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4579 }
4580
4581
4582 /*-----------------------------------------------------------------*/
4583 /* genMultbits :- multiplication of bits                           */
4584 /*-----------------------------------------------------------------*/
4585 static void
4586 genMultbits (operand * left,
4587              operand * right,
4588              operand * result,
4589              iCode   * ic)
4590 {
4591   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4592   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4593   aopOp(result, ic, TRUE, FALSE);
4594   outBitC (result);
4595 }
4596
4597
4598 /*-----------------------------------------------------------------*/
4599 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4600 /*-----------------------------------------------------------------*/
4601 static void
4602 genMultOneByte (operand * left,
4603                 operand * right,
4604                 operand * result,
4605                 iCode   * ic)
4606 {
4607   sym_link *opetype = operandType (result);
4608   symbol *lbl;
4609
4610
4611   /* (if two literals: the value is computed before) */
4612   /* if one literal, literal on the right */
4613   if (AOP_TYPE (left) == AOP_LIT)
4614     {
4615       operand *t = right;
4616       right = left;
4617       left = t;
4618       emitcode (";", "swapped left and right");
4619     }
4620
4621   if (SPEC_USIGN(opetype)
4622       // ignore the sign of left and right, what else can we do?
4623       || (SPEC_USIGN(operandType(left)) && 
4624           SPEC_USIGN(operandType(right)))) {
4625     // just an unsigned 8*8=8/16 multiply
4626     //emitcode (";","unsigned");
4627     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4628     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4629     emitcode ("mul", "ab");
4630    
4631     _G.accInUse++; _G.bInUse++;
4632     aopOp(result, ic, TRUE, FALSE);
4633       
4634       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4635       {
4636           // this should never happen
4637           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4638                    AOP_SIZE(result), __FILE__, lineno);
4639           exit (1);
4640       }      
4641       
4642     aopPut (AOP (result), "a", 0);
4643     _G.accInUse--; _G.bInUse--;
4644     if (AOP_SIZE(result)==2) 
4645     {
4646       aopPut (AOP (result), "b", 1);
4647     }
4648     return;
4649   }
4650
4651   // we have to do a signed multiply
4652
4653   emitcode (";", "signed");
4654   emitcode ("clr", "F0"); // reset sign flag
4655   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4656
4657   lbl=newiTempLabel(NULL);
4658   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4659   // left side is negative, 8-bit two's complement, this fails for -128
4660   emitcode ("setb", "F0"); // set sign flag
4661   emitcode ("cpl", "a");
4662   emitcode ("inc", "a");
4663
4664   emitcode ("", "!tlabeldef", lbl->key+100);
4665
4666   /* if literal */
4667   if (AOP_TYPE(right)==AOP_LIT) {
4668     signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4669     /* AND literal negative */
4670     if ((int) val < 0) {
4671       emitcode ("cpl", "F0"); // complement sign flag
4672       emitcode ("mov", "b,#!constbyte", -val);
4673     } else {
4674       emitcode ("mov", "b,#!constbyte", val);
4675     }
4676   } else {
4677     lbl=newiTempLabel(NULL);
4678     emitcode ("mov", "b,a");
4679     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4680     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4681     // right side is negative, 8-bit two's complement
4682     emitcode ("cpl", "F0"); // complement sign flag
4683     emitcode ("cpl", "a");
4684     emitcode ("inc", "a");
4685     emitcode ("", "!tlabeldef", lbl->key+100);
4686   }
4687   emitcode ("mul", "ab");
4688     
4689   _G.accInUse++;_G.bInUse++;
4690   aopOp(result, ic, TRUE, FALSE);
4691     
4692   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4693   {
4694     // this should never happen
4695       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4696                AOP_SIZE(result), __FILE__, lineno);
4697       exit (1);
4698   }    
4699     
4700   lbl=newiTempLabel(NULL);
4701   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4702   // only ONE op was negative, we have to do a 8/16-bit two's complement
4703   emitcode ("cpl", "a"); // lsb
4704   if (AOP_SIZE(result)==1) {
4705     emitcode ("inc", "a");
4706   } else {
4707     emitcode ("add", "a,#1");
4708     emitcode ("xch", "a,b");
4709     emitcode ("cpl", "a"); // msb
4710     emitcode ("addc", "a,#0");
4711     emitcode ("xch", "a,b");
4712   }
4713
4714   emitcode ("", "!tlabeldef", lbl->key+100);
4715   aopPut (AOP (result), "a", 0);
4716   _G.accInUse--;_G.bInUse--;
4717   if (AOP_SIZE(result)==2) {
4718     aopPut (AOP (result), "b", 1);
4719   }
4720 }
4721
4722 /*-----------------------------------------------------------------*/
4723 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4724 /*-----------------------------------------------------------------*/
4725 static void genMultTwoByte (operand *left, operand *right, 
4726                             operand *result, iCode *ic)
4727 {
4728         sym_link *retype = getSpec(operandType(right));
4729         sym_link *letype = getSpec(operandType(left));
4730         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4731         symbol *lbl;
4732
4733         if (AOP_TYPE (left) == AOP_LIT) {
4734                 operand *t = right;
4735                 right = left;
4736                 left = t;
4737         }
4738         /* save EA bit in F1 */
4739         lbl = newiTempLabel(NULL);
4740         emitcode ("setb","F1");
4741         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4742         emitcode ("clr","F1");
4743         emitcode("","!tlabeldef",lbl->key+100);
4744
4745         /* load up MB with right */
4746         if (!umult) {
4747                 emitcode("clr","F0");
4748                 if (AOP_TYPE(right) == AOP_LIT) {
4749                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4750                         if (val < 0) {
4751                                 emitcode("setb","F0");
4752                                 val = -val;
4753                         }
4754                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4755                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4756                 } else {
4757                         lbl = newiTempLabel(NULL);
4758                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4759                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4760                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4761                         emitcode ("xch", "a,b");
4762                         emitcode ("cpl","a");
4763                         emitcode ("add", "a,#1");
4764                         emitcode ("xch", "a,b");
4765                         emitcode ("cpl", "a"); // msb
4766                         emitcode ("addc", "a,#0");
4767                         emitcode ("setb","F0");
4768                         emitcode ("","!tlabeldef",lbl->key+100);
4769                         emitcode ("mov","mb,b");
4770                         emitcode ("mov","mb,a");
4771                 }
4772         } else {
4773                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4774                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4775         }
4776         /* load up MA with left */
4777         if (!umult) {
4778                 lbl = newiTempLabel(NULL);
4779                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4780                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4781                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4782                 emitcode ("xch", "a,b");
4783                 emitcode ("cpl","a");
4784                 emitcode ("add", "a,#1");
4785                 emitcode ("xch", "a,b");
4786                 emitcode ("cpl", "a"); // msb
4787                 emitcode ("addc","a,#0");
4788                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4789                 emitcode ("setb","F0");
4790                 emitcode ("","!tlabeldef",lbl->key+100);
4791                 emitcode ("mov","ma,b");
4792                 emitcode ("mov","ma,a");
4793         } else {
4794                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4795                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4796         }
4797         /* wait for multiplication to finish */
4798         lbl = newiTempLabel(NULL);
4799         emitcode("","!tlabeldef", lbl->key+100);
4800         emitcode("mov","a,mcnt1");
4801         emitcode("anl","a,#!constbyte",0x80);
4802         emitcode("jnz","!tlabel",lbl->key+100);
4803         
4804         freeAsmop (left, NULL, ic, TRUE);
4805         freeAsmop (right, NULL, ic,TRUE);
4806         aopOp(result, ic, TRUE, FALSE);
4807
4808         /* if unsigned then simple */   
4809         if (umult) {
4810                 emitcode ("mov","a,ma");
4811                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4812                 emitcode ("mov","a,ma");
4813                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4814                 aopPut(AOP(result),"ma",1);
4815                 aopPut(AOP(result),"ma",0);
4816         } else {
4817                 emitcode("push","ma");
4818                 emitcode("push","ma");
4819                 emitcode("push","ma");
4820                 MOVA("ma");
4821                 /* negate result if needed */
4822                 lbl = newiTempLabel(NULL);      
4823                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4824                 emitcode("cpl","a");
4825                 emitcode("add","a,#1");
4826                 emitcode("","!tlabeldef", lbl->key+100);
4827                 if (AOP_TYPE(result) == AOP_ACC)
4828                 {
4829                     D(emitcode(";", "ACC special case."););
4830                     /* We know result is the only live aop, and 
4831                      * it's obviously not a DPTR2, so AP is available.
4832                      */
4833                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4834                 }
4835                 else
4836                 {
4837                     aopPut(AOP(result),"a",0);
4838                 }
4839             
4840                 emitcode("pop","acc");
4841                 lbl = newiTempLabel(NULL);      
4842                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4843                 emitcode("cpl","a");
4844                 emitcode("addc","a,#0");
4845                 emitcode("","!tlabeldef", lbl->key+100);
4846                 aopPut(AOP(result),"a",1);
4847                 emitcode("pop","acc");
4848                 if (AOP_SIZE(result) >= 3) {
4849                         lbl = newiTempLabel(NULL);      
4850                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4851                         emitcode("cpl","a");
4852                         emitcode("addc","a,#0");                        
4853                         emitcode("","!tlabeldef", lbl->key+100);
4854                         aopPut(AOP(result),"a",2);
4855                 }
4856                 emitcode("pop","acc");
4857                 if (AOP_SIZE(result) >= 4) {
4858                         lbl = newiTempLabel(NULL);      
4859                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4860                         emitcode("cpl","a");
4861                         emitcode("addc","a,#0");                        
4862                         emitcode("","!tlabeldef", lbl->key+100);
4863                         aopPut(AOP(result),"a",3);
4864                 }
4865                 if (AOP_TYPE(result) == AOP_ACC)
4866                 {
4867                     /* We stashed the result away above. */
4868                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4869                 }           
4870                 
4871         }
4872         freeAsmop (result, NULL, ic, TRUE);
4873
4874         /* restore EA bit in F1 */
4875         lbl = newiTempLabel(NULL);
4876         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4877         emitcode ("setb","EA");
4878         emitcode("","!tlabeldef",lbl->key+100);
4879         return ;
4880 }
4881
4882 /*-----------------------------------------------------------------*/
4883 /* genMult - generates code for multiplication                     */
4884 /*-----------------------------------------------------------------*/
4885 static void
4886 genMult (iCode * ic)
4887 {
4888   operand *left = IC_LEFT (ic);
4889   operand *right = IC_RIGHT (ic);
4890   operand *result = IC_RESULT (ic);
4891
4892   D (emitcode (";", "genMult "););
4893
4894   /* assign the amsops */
4895   AOP_OP_2 (ic);
4896
4897   /* special cases first */
4898   /* both are bits */
4899   if (AOP_TYPE (left) == AOP_CRY &&
4900       AOP_TYPE (right) == AOP_CRY)
4901     {
4902       genMultbits (left, right, result, ic);
4903       goto release;
4904     }
4905
4906   /* if both are of size == 1 */
4907   if (AOP_SIZE (left) == 1 &&
4908       AOP_SIZE (right) == 1)
4909     {
4910       genMultOneByte (left, right, result, ic);
4911       goto release;
4912     }
4913
4914   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4915           /* use the ds390 ARITHMETIC accel UNIT */
4916           genMultTwoByte (left, right, result, ic);
4917           return ;
4918   }
4919   /* should have been converted to function call */
4920   assert (0);
4921
4922 release:
4923   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4924   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4925   freeAsmop (result, NULL, ic, TRUE);
4926 }
4927
4928 /*-----------------------------------------------------------------*/
4929 /* genDivbits :- division of bits                                  */
4930 /*-----------------------------------------------------------------*/
4931 static void
4932 genDivbits (operand * left,
4933             operand * right,
4934             operand * result,
4935             iCode   * ic)
4936 {
4937
4938   char *l;
4939
4940   /* the result must be bit */
4941   LOAD_AB_FOR_DIV (left, right, l);
4942   emitcode ("div", "ab");
4943   emitcode ("rrc", "a");
4944   aopOp(result, ic, TRUE, FALSE);
4945     
4946   aopPut (AOP (result), "c", 0);
4947 }
4948
4949 /*-----------------------------------------------------------------*/
4950 /* genDivOneByte : 8 bit division                                  */
4951 /*-----------------------------------------------------------------*/
4952 static void
4953 genDivOneByte (operand * left,
4954                operand * right,
4955                operand * result,
4956                iCode   * ic)
4957 {
4958   sym_link *opetype = operandType (result);
4959   char *l;
4960   symbol *lbl;
4961   int size, offset;
4962
4963   offset = 1;
4964   /* signed or unsigned */
4965   if (SPEC_USIGN (opetype))
4966     {
4967         /* unsigned is easy */
4968         LOAD_AB_FOR_DIV (left, right, l);
4969         emitcode ("div", "ab");
4970
4971         _G.accInUse++;
4972         aopOp(result, ic, TRUE, FALSE);
4973         aopPut (AOP (result), "a", 0);
4974         _G.accInUse--;
4975
4976         size = AOP_SIZE (result) - 1;
4977         
4978         while (size--)
4979         {
4980             aopPut (AOP (result), zero, offset++);
4981         }
4982       return;
4983     }
4984
4985   /* signed is a little bit more difficult */
4986
4987   /* save the signs of the operands */
4988   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4989   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4990   emitcode ("push", "acc");     /* save it on the stack */
4991
4992   /* now sign adjust for both left & right */
4993   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4994   lbl = newiTempLabel (NULL);
4995   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4996   emitcode ("cpl", "a");
4997   emitcode ("inc", "a");
4998   emitcode ("", "!tlabeldef", (lbl->key + 100));
4999   emitcode ("mov", "b,a");
5000
5001   /* sign adjust left side */
5002   MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5003
5004   lbl = newiTempLabel (NULL);
5005   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5006   emitcode ("cpl", "a");
5007   emitcode ("inc", "a");
5008   emitcode ("", "!tlabeldef", (lbl->key + 100));
5009
5010   /* now the division */
5011   emitcode ("nop", "; workaround for DS80C390 div bug.");
5012   emitcode ("div", "ab");
5013   /* we are interested in the lower order
5014      only */
5015   emitcode ("mov", "b,a");
5016   lbl = newiTempLabel (NULL);
5017   emitcode ("pop", "acc");
5018   /* if there was an over flow we don't
5019      adjust the sign of the result */
5020   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5021   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5022   CLRC;
5023   emitcode ("clr", "a");
5024   emitcode ("subb", "a,b");
5025   emitcode ("mov", "b,a");
5026   emitcode ("", "!tlabeldef", (lbl->key + 100));
5027
5028   /* now we are done */
5029   _G.accInUse++;     _G.bInUse++;
5030     aopOp(result, ic, TRUE, FALSE);
5031     
5032     aopPut (AOP (result), "b", 0);
5033     
5034     size = AOP_SIZE (result) - 1;
5035     
5036     if (size > 0)
5037     {
5038       emitcode ("mov", "c,b.7");
5039       emitcode ("subb", "a,acc");
5040     }
5041     while (size--)
5042     {
5043         aopPut (AOP (result), "a", offset++);
5044     }
5045     _G.accInUse--;     _G.bInUse--;
5046
5047 }
5048
5049 /*-----------------------------------------------------------------*/
5050 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
5051 /*-----------------------------------------------------------------*/
5052 static void genDivTwoByte (operand *left, operand *right, 
5053                             operand *result, iCode *ic)
5054 {
5055         sym_link *retype = getSpec(operandType(right));
5056         sym_link *letype = getSpec(operandType(left));
5057         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5058         symbol *lbl;
5059
5060         /* save EA bit in F1 */
5061         lbl = newiTempLabel(NULL);
5062         emitcode ("setb","F1");
5063         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5064         emitcode ("clr","F1");
5065         emitcode("","!tlabeldef",lbl->key+100);
5066
5067         /* load up MA with left */
5068         if (!umult) {
5069                 emitcode("clr","F0");
5070                 lbl = newiTempLabel(NULL);
5071                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5072                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5073                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5074                 emitcode ("xch", "a,b");
5075                 emitcode ("cpl","a");
5076                 emitcode ("add", "a,#1");
5077                 emitcode ("xch", "a,b");
5078                 emitcode ("cpl", "a"); // msb
5079                 emitcode ("addc","a,#0");
5080                 emitcode ("setb","F0");
5081                 emitcode ("","!tlabeldef",lbl->key+100);
5082                 emitcode ("mov","ma,b");
5083                 emitcode ("mov","ma,a");
5084         } else {
5085                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5086                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5087         }
5088
5089         /* load up MB with right */
5090         if (!umult) {
5091                 if (AOP_TYPE(right) == AOP_LIT) {
5092                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5093                         if (val < 0) {
5094                                 lbl = newiTempLabel(NULL);
5095                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5096                                 emitcode("setb","F0");
5097                                 emitcode ("","!tlabeldef",lbl->key+100);
5098                                 val = -val;
5099                         } 
5100                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
5101                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5102                 } else {
5103                         lbl = newiTempLabel(NULL);
5104                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5105                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5106                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5107                         emitcode ("xch", "a,b");
5108                         emitcode ("cpl","a");
5109                         emitcode ("add", "a,#1");
5110                         emitcode ("xch", "a,b");
5111                         emitcode ("cpl", "a"); // msb
5112                         emitcode ("addc", "a,#0");
5113                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5114                         emitcode ("setb","F0");
5115                         emitcode ("","!tlabeldef",lbl->key+100);
5116                         emitcode ("mov","mb,b");
5117                         emitcode ("mov","mb,a");
5118                 }
5119         } else {
5120                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5121                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5122         }
5123
5124         /* wait for multiplication to finish */
5125         lbl = newiTempLabel(NULL);
5126         emitcode("","!tlabeldef", lbl->key+100);
5127         emitcode("mov","a,mcnt1");
5128         emitcode("anl","a,#!constbyte",0x80);
5129         emitcode("jnz","!tlabel",lbl->key+100);
5130         
5131         freeAsmop (left, NULL, ic, TRUE);
5132         freeAsmop (right, NULL, ic,TRUE);
5133         aopOp(result, ic, TRUE, FALSE);
5134
5135         /* if unsigned then simple */   
5136         if (umult) {
5137                 aopPut(AOP(result),"ma",1);
5138                 aopPut(AOP(result),"ma",0);
5139         } else {
5140                 emitcode("push","ma");
5141                 MOVA("ma");
5142                 /* negate result if needed */
5143                 lbl = newiTempLabel(NULL);      
5144                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5145                 emitcode("cpl","a");
5146                 emitcode("add","a,#1");
5147                 emitcode("","!tlabeldef", lbl->key+100);
5148                 aopPut(AOP(result),"a",0);
5149                 emitcode("pop","acc");
5150                 lbl = newiTempLabel(NULL);      
5151                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5152                 emitcode("cpl","a");
5153                 emitcode("addc","a,#0");
5154                 emitcode("","!tlabeldef", lbl->key+100);
5155                 aopPut(AOP(result),"a",1);
5156         }
5157         freeAsmop (result, NULL, ic, TRUE);
5158         /* restore EA bit in F1 */
5159         lbl = newiTempLabel(NULL);
5160         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5161         emitcode ("setb","EA");
5162         emitcode("","!tlabeldef",lbl->key+100);
5163         return ;
5164 }
5165
5166 /*-----------------------------------------------------------------*/
5167 /* genDiv - generates code for division                            */
5168 /*-----------------------------------------------------------------*/
5169 static void
5170 genDiv (iCode * ic)
5171 {
5172   operand *left = IC_LEFT (ic);
5173   operand *right = IC_RIGHT (ic);
5174   operand *result = IC_RESULT (ic);
5175
5176   D (emitcode (";", "genDiv "););
5177
5178   /* assign the amsops */
5179   AOP_OP_2 (ic);
5180
5181   /* special cases first */
5182   /* both are bits */
5183   if (AOP_TYPE (left) == AOP_CRY &&
5184       AOP_TYPE (right) == AOP_CRY)
5185     {
5186       genDivbits (left, right, result, ic);
5187       goto release;
5188     }
5189
5190   /* if both are of size == 1 */
5191   if (AOP_SIZE (left) == 1 &&
5192       AOP_SIZE (right) == 1)
5193     {
5194       genDivOneByte (left, right, result, ic);
5195       goto release;
5196     }
5197
5198   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5199           /* use the ds390 ARITHMETIC accel UNIT */
5200           genDivTwoByte (left, right, result, ic);
5201           return ;
5202   }
5203   /* should have been converted to function call */
5204   assert (0);
5205 release:
5206   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5207   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5208   freeAsmop (result, NULL, ic, TRUE);
5209 }
5210
5211 /*-----------------------------------------------------------------*/
5212 /* genModbits :- modulus of bits                                   */
5213 /*-----------------------------------------------------------------*/
5214 static void
5215 genModbits (operand * left,
5216             operand * right,
5217             operand * result,
5218             iCode   * ic)
5219 {
5220
5221   char *l;
5222
5223   /* the result must be bit */
5224   LOAD_AB_FOR_DIV (left, right, l);
5225   emitcode ("div", "ab");
5226   emitcode ("mov", "a,b");
5227   emitcode ("rrc", "a");
5228   aopOp(result, ic, TRUE, FALSE);
5229   aopPut (AOP (result), "c", 0);
5230 }
5231
5232 /*-----------------------------------------------------------------*/
5233 /* genModOneByte : 8 bit modulus                                   */
5234 /*-----------------------------------------------------------------*/
5235 static void
5236 genModOneByte (operand * left,
5237                operand * right,
5238                operand * result,
5239                iCode   * ic)
5240 {
5241   sym_link *opetype = operandType (result);
5242   char *l;
5243   symbol *lbl;
5244
5245   /* signed or unsigned */
5246   if (SPEC_USIGN (opetype))
5247     {
5248       /* unsigned is easy */
5249       LOAD_AB_FOR_DIV (left, right, l);
5250       emitcode ("div", "ab");
5251       aopOp(result, ic, TRUE, FALSE);   
5252       aopPut (AOP (result), "b", 0);
5253       return;
5254     }
5255
5256   /* signed is a little bit more difficult */
5257
5258   /* save the signs of the operands */
5259   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5260
5261   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5262   emitcode ("push", "acc");     /* save it on the stack */
5263
5264   /* now sign adjust for both left & right */
5265   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5266
5267   lbl = newiTempLabel (NULL);
5268   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5269   emitcode ("cpl", "a");
5270   emitcode ("inc", "a");
5271   emitcode ("", "!tlabeldef", (lbl->key + 100));
5272   emitcode ("mov", "b,a");
5273
5274   /* sign adjust left side */
5275   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5276
5277   lbl = newiTempLabel (NULL);
5278   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5279   emitcode ("cpl", "a");
5280   emitcode ("inc", "a");
5281   emitcode ("", "!tlabeldef", (lbl->key + 100));
5282
5283   /* now the multiplication */
5284   emitcode ("nop", "; workaround for DS80C390 div bug.");
5285   emitcode ("div", "ab");
5286   /* we are interested in the lower order
5287      only */
5288   lbl = newiTempLabel (NULL);
5289   emitcode ("pop", "acc");
5290   /* if there was an over flow we don't
5291      adjust the sign of the result */
5292   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5293   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5294   CLRC;
5295   emitcode ("clr", "a");
5296   emitcode ("subb", "a,b");
5297   emitcode ("mov", "b,a");
5298   emitcode ("", "!tlabeldef", (lbl->key + 100));
5299   
5300   _G.bInUse++;
5301   /* now we are done */
5302   aopOp(result, ic, TRUE, FALSE);    
5303   aopPut (AOP (result), "b", 0);
5304   _G.bInUse--;
5305
5306 }
5307
5308 /*-----------------------------------------------------------------*/
5309 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5310 /*-----------------------------------------------------------------*/
5311 static void genModTwoByte (operand *left, operand *right, 
5312                             operand *result, iCode *ic)
5313 {
5314         sym_link *retype = getSpec(operandType(right));
5315         sym_link *letype = getSpec(operandType(left));
5316         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5317         symbol *lbl;
5318
5319         /* load up MA with left */
5320         /* save EA bit in F1 */
5321         lbl = newiTempLabel(NULL);
5322         emitcode ("setb","F1");
5323         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5324         emitcode ("clr","F1");
5325         emitcode("","!tlabeldef",lbl->key+100);
5326
5327         if (!umult) {
5328                 lbl = newiTempLabel(NULL);
5329                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5330                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5331                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5332                 emitcode ("xch", "a,b");
5333                 emitcode ("cpl","a");
5334                 emitcode ("add", "a,#1");
5335                 emitcode ("xch", "a,b");
5336                 emitcode ("cpl", "a"); // msb
5337                 emitcode ("addc","a,#0");
5338                 emitcode ("","!tlabeldef",lbl->key+100);
5339                 emitcode ("mov","ma,b");
5340                 emitcode ("mov","ma,a");
5341         } else {
5342                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5343                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5344         }
5345
5346         /* load up MB with right */
5347         if (!umult) {
5348                 if (AOP_TYPE(right) == AOP_LIT) {
5349                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5350                         if (val < 0) {
5351                                 val = -val;
5352                         } 
5353                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5354                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5355                 } else {
5356                         lbl = newiTempLabel(NULL);
5357                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5358                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5359                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5360                         emitcode ("xch", "a,b");
5361                         emitcode ("cpl","a");
5362                         emitcode ("add", "a,#1");
5363                         emitcode ("xch", "a,b");
5364                         emitcode ("cpl", "a"); // msb
5365                         emitcode ("addc", "a,#0");
5366                         emitcode ("","!tlabeldef",lbl->key+100);
5367                         emitcode ("mov","mb,b");
5368                         emitcode ("mov","mb,a");
5369                 }
5370         } else {
5371                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5372                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5373         }
5374
5375         /* wait for multiplication to finish */
5376         lbl = newiTempLabel(NULL);
5377         emitcode("","!tlabeldef", lbl->key+100);
5378         emitcode("mov","a,mcnt1");
5379         emitcode("anl","a,#!constbyte",0x80);
5380         emitcode("jnz","!tlabel",lbl->key+100);
5381         
5382         freeAsmop (left, NULL, ic, TRUE);
5383         freeAsmop (right, NULL, ic,TRUE);
5384         aopOp(result, ic, TRUE, FALSE);
5385
5386         aopPut(AOP(result),"mb",1);
5387         aopPut(AOP(result),"mb",0);
5388         freeAsmop (result, NULL, ic, TRUE);
5389
5390         /* restore EA bit in F1 */
5391         lbl = newiTempLabel(NULL);
5392         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5393         emitcode ("setb","EA");
5394         emitcode("","!tlabeldef",lbl->key+100);
5395         return ;
5396 }
5397
5398 /*-----------------------------------------------------------------*/
5399 /* genMod - generates code for division                            */
5400 /*-----------------------------------------------------------------*/
5401 static void
5402 genMod (iCode * ic)
5403 {
5404   operand *left = IC_LEFT (ic);
5405   operand *right = IC_RIGHT (ic);
5406   operand *result = IC_RESULT (ic);
5407
5408   D (emitcode (";", "genMod "); );
5409
5410   /* assign the amsops */
5411   AOP_OP_2 (ic);
5412
5413   /* special cases first */
5414   /* both are bits */
5415   if (AOP_TYPE (left) == AOP_CRY &&
5416       AOP_TYPE (right) == AOP_CRY)
5417     {
5418       genModbits (left, right, result, ic);
5419       goto release;
5420     }
5421
5422   /* if both are of size == 1 */
5423   if (AOP_SIZE (left) == 1 &&
5424       AOP_SIZE (right) == 1)
5425     {
5426       genModOneByte (left, right, result, ic);
5427       goto release;
5428     }
5429
5430   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5431           /* use the ds390 ARITHMETIC accel UNIT */
5432           genModTwoByte (left, right, result, ic);
5433           return ;
5434   }
5435
5436   /* should have been converted to function call */
5437   assert (0);
5438
5439 release:
5440   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5441   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5442   freeAsmop (result, NULL, ic, TRUE);
5443 }
5444
5445 /*-----------------------------------------------------------------*/
5446 /* genIfxJump :- will create a jump depending on the ifx           */
5447 /*-----------------------------------------------------------------*/
5448 static void
5449 genIfxJump (iCode * ic, char *jval)
5450 {
5451   symbol *jlbl;
5452   symbol *tlbl = newiTempLabel (NULL);
5453   char *inst;
5454
5455   D (emitcode (";", "genIfxJump"););
5456
5457   /* if true label then we jump if condition
5458      supplied is true */
5459   if (IC_TRUE (ic))
5460     {
5461       jlbl = IC_TRUE (ic);
5462       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5463                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5464     }
5465   else
5466     {
5467       /* false label is present */
5468       jlbl = IC_FALSE (ic);
5469       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5470                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5471     }
5472   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5473     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5474   else
5475     emitcode (inst, "!tlabel", tlbl->key + 100);
5476   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5477   emitcode ("", "!tlabeldef", tlbl->key + 100);
5478
5479   /* mark the icode as generated */
5480   ic->generated = 1;
5481 }
5482
5483 /*-----------------------------------------------------------------*/
5484 /* genCmp :- greater or less than comparison                       */
5485 /*-----------------------------------------------------------------*/
5486 static void
5487 genCmp (operand * left, operand * right,
5488         iCode * ic, iCode * ifx, int sign)
5489 {
5490   int size, offset = 0;
5491   unsigned long lit = 0L;
5492   operand *result;
5493
5494   D (emitcode (";", "genCmp"););
5495
5496   result = IC_RESULT (ic);
5497
5498   /* if left & right are bit variables */
5499   if (AOP_TYPE (left) == AOP_CRY &&
5500       AOP_TYPE (right) == AOP_CRY)
5501     {
5502       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5503       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5504     }
5505   else
5506     {
5507       /* subtract right from left if at the
5508          end the carry flag is set then we know that
5509          left is greater than right */
5510       size = max (AOP_SIZE (left), AOP_SIZE (right));
5511
5512       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5513       if ((size == 1) && !sign 
5514           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5515         {
5516           symbol *lbl = newiTempLabel (NULL);
5517           emitcode ("cjne", "%s,%s,!tlabel",
5518                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5519                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5520                     lbl->key + 100);
5521           emitcode ("", "!tlabeldef", lbl->key + 100);
5522         }
5523       else
5524         {
5525           if (AOP_TYPE (right) == AOP_LIT)
5526             {
5527               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5528               /* optimize if(x < 0) or if(x >= 0) */
5529               if (lit == 0L)
5530                 {
5531                   if (!sign)
5532                     {
5533                       CLRC;
5534                     }
5535                   else
5536                     {
5537                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5538
5539                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5540                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5541
5542                       aopOp (result, ic, FALSE, FALSE);
5543
5544                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5545                         {
5546                           freeAsmop (result, NULL, ic, TRUE);
5547                           genIfxJump (ifx, "acc.7");
5548                           return;
5549                         }
5550                       else
5551                         {
5552                           emitcode ("rlc", "a");
5553                         }
5554                       goto release_freedLR;
5555                     }
5556                   goto release;
5557                 }
5558             }
5559           CLRC;
5560           while (size--)
5561             {
5562               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5563               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5564               // emitcode (";", "genCmp #2");
5565               if (sign && (size == 0))
5566                 {
5567                   // emitcode (";", "genCmp #3");
5568                   emitcode ("xrl", "a,#!constbyte",0x80);
5569                   if (AOP_TYPE (right) == AOP_LIT)
5570                     {
5571                       unsigned long lit = (unsigned long)
5572                       floatFromVal (AOP (right)->aopu.aop_lit);
5573                       // emitcode (";", "genCmp #3.1");
5574                       emitcode ("subb", "a,#!constbyte",
5575                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5576                     }
5577                   else
5578                     {
5579                       // emitcode (";", "genCmp #3.2");
5580                       saveAccWarn = 0;  
5581                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5582                       saveAccWarn = DEFAULT_ACC_WARNING;
5583                       emitcode ("xrl", "b,#!constbyte",0x80);
5584                       emitcode ("subb", "a,b");
5585                     }
5586                 }
5587               else
5588                 {
5589                   const char *s;
5590
5591                   // emitcode (";", "genCmp #4");
5592                   saveAccWarn = 0;
5593                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5594                   saveAccWarn = DEFAULT_ACC_WARNING;
5595
5596                   emitcode ("subb", "a,%s", s);
5597                 }
5598             }
5599         }
5600     }
5601
5602 release:
5603 /* Don't need the left & right operands any more; do need the result. */
5604   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5605   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5606
5607   aopOp (result, ic, FALSE, FALSE);
5608
5609 release_freedLR:
5610
5611   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5612     {
5613       outBitC (result);
5614     }
5615   else
5616     {
5617       /* if the result is used in the next
5618          ifx conditional branch then generate
5619          code a little differently */
5620       if (ifx)
5621         {
5622           genIfxJump (ifx, "c");
5623         }
5624       else
5625         {
5626           outBitC (result);
5627         }
5628       /* leave the result in acc */
5629     }
5630   freeAsmop (result, NULL, ic, TRUE);
5631 }
5632
5633 /*-----------------------------------------------------------------*/
5634 /* genCmpGt :- greater than comparison                             */
5635 /*-----------------------------------------------------------------*/
5636 static void
5637 genCmpGt (iCode * ic, iCode * ifx)
5638 {
5639   operand *left, *right;
5640   sym_link *letype, *retype;
5641   int sign;
5642
5643   D (emitcode (";", "genCmpGt ");
5644     );
5645
5646   left = IC_LEFT (ic);
5647   right = IC_RIGHT (ic);
5648
5649   letype = getSpec (operandType (left));
5650   retype = getSpec (operandType (right));
5651   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5652
5653   /* assign the left & right amsops */
5654   AOP_OP_2 (ic);
5655
5656   genCmp (right, left, ic, ifx, sign);
5657 }
5658
5659 /*-----------------------------------------------------------------*/
5660 /* genCmpLt - less than comparisons                                */
5661 /*-----------------------------------------------------------------*/
5662 static void
5663 genCmpLt (iCode * ic, iCode * ifx)
5664 {
5665   operand *left, *right;
5666   sym_link *letype, *retype;
5667   int sign;
5668
5669   D (emitcode (";", "genCmpLt "););
5670
5671   left = IC_LEFT (ic);
5672   right = IC_RIGHT (ic);
5673
5674   letype = getSpec (operandType (left));
5675   retype = getSpec (operandType (right));
5676   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5677
5678   /* assign the left & right amsops */
5679   AOP_OP_2 (ic);
5680
5681   genCmp (left, right, ic, ifx, sign);
5682 }
5683
5684 /*-----------------------------------------------------------------*/
5685 /* gencjneshort - compare and jump if not equal                    */
5686 /*-----------------------------------------------------------------*/
5687 static void
5688 gencjneshort (operand * left, operand * right, symbol * lbl)
5689 {
5690   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5691   int offset = 0;
5692   unsigned long lit = 0L;
5693
5694   D (emitcode (";", "gencjneshort");
5695     );
5696
5697   /* if the left side is a literal or
5698      if the right is in a pointer register and left
5699      is not */
5700   if ((AOP_TYPE (left) == AOP_LIT) ||
5701       (AOP_TYPE (left) == AOP_IMMD) ||
5702       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5703     {
5704       operand *t = right;
5705       right = left;
5706       left = t;
5707     }
5708
5709   if (AOP_TYPE (right) == AOP_LIT)
5710     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5711
5712   if (opIsGptr (left) || opIsGptr (right))
5713     {
5714       /* We are comparing a generic pointer to something.
5715        * Exclude the generic type byte from the comparison.
5716        */
5717       size--;
5718       D (emitcode (";", "cjneshort: generic ptr special case."););
5719     }
5720
5721
5722   /* if the right side is a literal then anything goes */
5723   if (AOP_TYPE (right) == AOP_LIT &&
5724       AOP_TYPE (left) != AOP_DIR)
5725     {
5726       while (size--)
5727         {
5728           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5729           emitcode ("cjne", "a,%s,!tlabel",
5730                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5731                     lbl->key + 100);
5732           offset++;
5733         }
5734     }
5735
5736   /* if the right side is in a register or in direct space or
5737      if the left is a pointer register & right is not */
5738   else if (AOP_TYPE (right) == AOP_REG ||
5739            AOP_TYPE (right) == AOP_DIR ||
5740            AOP_TYPE (right) == AOP_LIT ||
5741            AOP_TYPE (right) == AOP_IMMD ||
5742            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5743            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5744     {
5745       while (size--)
5746         {
5747           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5748           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5749               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5750             emitcode ("jnz", "!tlabel", lbl->key + 100);
5751           else
5752             emitcode ("cjne", "a,%s,!tlabel",
5753                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5754                       lbl->key + 100);
5755           offset++;
5756         }
5757     }
5758   else
5759     {
5760       /* right is a pointer reg need both a & b */
5761       while (size--)
5762         {
5763           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5764           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5765           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5766           offset++;
5767         }
5768     }
5769 }
5770
5771 /*-----------------------------------------------------------------*/
5772 /* gencjne - compare and jump if not equal                         */
5773 /*-----------------------------------------------------------------*/
5774 static void
5775 gencjne (operand * left, operand * right, symbol * lbl)
5776 {
5777   symbol *tlbl = newiTempLabel (NULL);
5778
5779   D (emitcode (";", "gencjne");
5780     );
5781
5782   gencjneshort (left, right, lbl);
5783
5784   emitcode ("mov", "a,%s", one);
5785   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5786   emitcode ("", "!tlabeldef", lbl->key + 100);
5787   emitcode ("clr", "a");
5788   emitcode ("", "!tlabeldef", tlbl->key + 100);
5789 }
5790
5791 /*-----------------------------------------------------------------*/
5792 /* genCmpEq - generates code for equal to                          */
5793 /*-----------------------------------------------------------------*/
5794 static void
5795 genCmpEq (iCode * ic, iCode * ifx)
5796 {
5797   operand *left, *right, *result;
5798
5799   D (emitcode (";", "genCmpEq ");
5800     );
5801
5802   AOP_OP_2 (ic);
5803   AOP_SET_LOCALS (ic);
5804
5805   /* if literal, literal on the right or
5806      if the right is in a pointer register and left
5807      is not */
5808   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5809       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5810     {
5811       operand *t = IC_RIGHT (ic);
5812       IC_RIGHT (ic) = IC_LEFT (ic);
5813       IC_LEFT (ic) = t;
5814     }
5815
5816   if (ifx &&                    /* !AOP_SIZE(result) */
5817       OP_SYMBOL (result) &&
5818       OP_SYMBOL (result)->regType == REG_CND)
5819     {
5820       symbol *tlbl;
5821       /* if they are both bit variables */
5822       if (AOP_TYPE (left) == AOP_CRY &&
5823           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5824         {
5825           if (AOP_TYPE (right) == AOP_LIT)
5826             {
5827               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5828               if (lit == 0L)
5829                 {
5830                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5831                   emitcode ("cpl", "c");
5832                 }
5833               else if (lit == 1L)
5834                 {
5835                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5836                 }
5837               else
5838                 {
5839                   emitcode ("clr", "c");
5840                 }
5841               /* AOP_TYPE(right) == AOP_CRY */
5842             }
5843           else
5844             {
5845               symbol *lbl = newiTempLabel (NULL);
5846               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5847               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5848               emitcode ("cpl", "c");
5849               emitcode ("", "!tlabeldef", (lbl->key + 100));
5850             }
5851           /* if true label then we jump if condition
5852              supplied is true */
5853           tlbl = newiTempLabel (NULL);
5854           if (IC_TRUE (ifx))
5855             {
5856               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5857               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5858             }
5859           else
5860             {
5861               emitcode ("jc", "!tlabel", tlbl->key + 100);
5862               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5863             }
5864           emitcode ("", "!tlabeldef", tlbl->key + 100);
5865         }
5866       else
5867         {
5868           tlbl = newiTempLabel (NULL);
5869           gencjneshort (left, right, tlbl);
5870           if (IC_TRUE (ifx))
5871             {
5872               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5873               emitcode ("", "!tlabeldef", tlbl->key + 100);
5874             }
5875           else
5876             {
5877               symbol *lbl = newiTempLabel (NULL);
5878               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5879               emitcode ("", "!tlabeldef", tlbl->key + 100);
5880               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5881               emitcode ("", "!tlabeldef", lbl->key + 100);
5882             }
5883         }
5884       /* mark the icode as generated */
5885       ifx->generated = 1;
5886
5887       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5888       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5889       return;
5890     }
5891
5892   /* if they are both bit variables */
5893   if (AOP_TYPE (left) == AOP_CRY &&
5894       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5895     {
5896       if (AOP_TYPE (right) == AOP_LIT)
5897         {
5898           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5899           if (lit == 0L)
5900             {
5901               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5902               emitcode ("cpl", "c");
5903             }
5904           else if (lit == 1L)
5905             {
5906               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5907             }
5908           else
5909             {
5910               emitcode ("clr", "c");
5911             }
5912           /* AOP_TYPE(right) == AOP_CRY */
5913         }
5914       else
5915         {
5916           symbol *lbl = newiTempLabel (NULL);
5917           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5918           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5919           emitcode ("cpl", "c");
5920           emitcode ("", "!tlabeldef", (lbl->key + 100));
5921         }
5922
5923       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5924       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5925
5926       aopOp (result, ic, TRUE, FALSE);
5927
5928       /* c = 1 if egal */
5929       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5930         {
5931           outBitC (result);
5932           goto release;
5933         }
5934       if (ifx)
5935         {
5936           genIfxJump (ifx, "c");
5937           goto release;
5938         }
5939       /* if the result is used in an arithmetic operation
5940          then put the result in place */
5941       outBitC (result);
5942     }
5943   else
5944     {
5945       gencjne (left, right, newiTempLabel (NULL));
5946
5947       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5948       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5949
5950       aopOp (result, ic, TRUE, FALSE);
5951
5952       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5953         {
5954           aopPut (AOP (result), "a", 0);
5955           goto release;
5956         }
5957       if (ifx)
5958         {
5959           genIfxJump (ifx, "a");
5960           goto release;
5961         }
5962       /* if the result is used in an arithmetic operation
5963          then put the result in place */
5964       if (AOP_TYPE (result) != AOP_CRY)
5965         outAcc (result);
5966       /* leave the result in acc */
5967     }
5968
5969 release:
5970   freeAsmop (result, NULL, ic, TRUE);
5971 }
5972
5973 /*-----------------------------------------------------------------*/
5974 /* ifxForOp - returns the icode containing the ifx for operand     */
5975 /*-----------------------------------------------------------------*/
5976 static iCode *
5977 ifxForOp (operand * op, iCode * ic)
5978 {
5979   /* if true symbol then needs to be assigned */
5980   if (IS_TRUE_SYMOP (op))
5981     return NULL;
5982
5983   /* if this has register type condition and
5984      the next instruction is ifx with the same operand
5985      and live to of the operand is upto the ifx only then */
5986   if (ic->next &&
5987       ic->next->op == IFX &&
5988       IC_COND (ic->next)->key == op->key &&
5989       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5990     return ic->next;
5991
5992   return NULL;
5993 }
5994 /*-----------------------------------------------------------------*/
5995 /* hasInc - operand is incremented before any other use            */
5996 /*-----------------------------------------------------------------*/
5997 static iCode *
5998 hasInc (operand *op, iCode *ic, int osize)
5999 {
6000   sym_link *type = operandType(op);
6001   sym_link *retype = getSpec (type);
6002   iCode *lic = ic->next;
6003   int isize ;
6004   
6005   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6006   if (!IS_SYMOP(op)) return NULL;
6007
6008   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6009   if (IS_AGGREGATE(type->next)) return NULL;
6010   if (osize != (isize = getSize(type->next))) return NULL;
6011
6012   while (lic) {
6013       /* if operand of the form op = op + <sizeof *op> */
6014       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6015           isOperandEqual(IC_RESULT(lic),op) && 
6016           isOperandLiteral(IC_RIGHT(lic)) &&
6017           operandLitValue(IC_RIGHT(lic)) == isize) {
6018           return lic;
6019       }
6020       /* if the operand used or deffed */
6021       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
6022           return NULL;
6023       }
6024       /* if GOTO or IFX */
6025       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6026       lic = lic->next;
6027   }
6028   return NULL;
6029 }
6030
6031 /*-----------------------------------------------------------------*/
6032 /* genAndOp - for && operation                                     */
6033 /*-----------------------------------------------------------------*/
6034 static void
6035 genAndOp (iCode * ic)
6036 {
6037   operand *left, *right, *result;
6038   symbol *tlbl;
6039
6040   D (emitcode (";", "genAndOp "););
6041
6042   /* note here that && operations that are in an
6043      if statement are taken away by backPatchLabels
6044      only those used in arthmetic operations remain */
6045   AOP_OP_2 (ic);
6046   AOP_SET_LOCALS (ic);
6047
6048   /* if both are bit variables */
6049   if (AOP_TYPE (left) == AOP_CRY &&
6050       AOP_TYPE (right) == AOP_CRY)
6051     {
6052       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6053       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6054       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6055       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6056   
6057       aopOp (result,ic,FALSE, FALSE);
6058       outBitC (result);
6059     }
6060   else
6061     {
6062       tlbl = newiTempLabel (NULL);
6063       toBoolean (left);
6064       emitcode ("jz", "!tlabel", tlbl->key + 100);
6065       toBoolean (right);
6066       emitcode ("", "!tlabeldef", tlbl->key + 100);
6067       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6068       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6069   
6070       aopOp (result,ic,FALSE, FALSE);
6071       outBitAcc (result);
6072     }
6073     freeAsmop (result, NULL, ic, TRUE);
6074 }
6075
6076
6077 /*-----------------------------------------------------------------*/
6078 /* genOrOp - for || operation                                      */
6079 /*-----------------------------------------------------------------*/
6080 static void
6081 genOrOp (iCode * ic)
6082 {
6083   operand *left, *right, *result;
6084   symbol *tlbl;
6085
6086   D (emitcode (";", "genOrOp "););
6087
6088   /* note here that || operations that are in an
6089      if statement are taken away by backPatchLabels
6090      only those used in arthmetic operations remain */
6091   AOP_OP_2 (ic);
6092   AOP_SET_LOCALS (ic);
6093
6094   /* if both are bit variables */
6095   if (AOP_TYPE (left) == AOP_CRY &&
6096       AOP_TYPE (right) == AOP_CRY)
6097     {
6098       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6099       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6100       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6101       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6102   
6103       aopOp (result,ic,FALSE, FALSE);
6104       
6105       outBitC (result);
6106     }
6107   else
6108     {
6109       tlbl = newiTempLabel (NULL);
6110       toBoolean (left);
6111       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6112       toBoolean (right);
6113       emitcode ("", "!tlabeldef", tlbl->key + 100);
6114       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6115       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6116   
6117       aopOp (result,ic,FALSE, FALSE);
6118       
6119       outBitAcc (result);
6120     }
6121
6122   freeAsmop (result, NULL, ic, TRUE);
6123 }
6124
6125 /*-----------------------------------------------------------------*/
6126 /* isLiteralBit - test if lit == 2^n                               */
6127 /*-----------------------------------------------------------------*/
6128 static int
6129 isLiteralBit (unsigned long lit)
6130 {
6131   unsigned long pw[32] =
6132   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6133    0x100L, 0x200L, 0x400L, 0x800L,
6134    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6135    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6136    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6137    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6138    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6139   int idx;
6140
6141   for (idx = 0; idx < 32; idx++)
6142     if (lit == pw[idx])
6143       return idx + 1;
6144   return 0;
6145 }
6146
6147 /*-----------------------------------------------------------------*/
6148 /* continueIfTrue -                                                */
6149 /*-----------------------------------------------------------------*/
6150 static void
6151 continueIfTrue (iCode * ic)
6152 {
6153   if (IC_TRUE (ic))
6154     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6155   ic->generated = 1;
6156 }
6157
6158 /*-----------------------------------------------------------------*/
6159 /* jmpIfTrue -                                                     */
6160 /*-----------------------------------------------------------------*/
6161 static void
6162 jumpIfTrue (iCode * ic)
6163 {
6164   if (!IC_TRUE (ic))
6165     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6166   ic->generated = 1;
6167 }
6168
6169 /*-----------------------------------------------------------------*/
6170 /* jmpTrueOrFalse -                                                */
6171 /*-----------------------------------------------------------------*/
6172 static void
6173 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6174 {
6175   // ugly but optimized by peephole
6176   if (IC_TRUE (ic))
6177     {
6178       symbol *nlbl = newiTempLabel (NULL);
6179       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6180       emitcode ("", "!tlabeldef", tlbl->key + 100);
6181       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6182       emitcode ("", "!tlabeldef", nlbl->key + 100);
6183     }
6184   else
6185     {
6186       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6187       emitcode ("", "!tlabeldef", tlbl->key + 100);
6188     }
6189   ic->generated = 1;
6190 }
6191
6192 // Generate code to perform a bit-wise logic operation
6193 // on two operands in far space (assumed to already have been 
6194 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6195 // in far space. This requires pushing the result on the stack
6196 // then popping it into the result.
6197 static void
6198 genFarFarLogicOp(iCode *ic, char *logicOp)
6199 {
6200       int size, resultSize, compSize;
6201       int offset = 0;
6202       
6203       TR_AP("#5");
6204       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6205       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6206                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6207       
6208       _startLazyDPSEvaluation();
6209       for (size = compSize; (size--); offset++)
6210       {
6211           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6212           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6213           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6214           
6215           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6216           emitcode ("push", "acc");
6217       }
6218       _endLazyDPSEvaluation();
6219      
6220       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6221       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6222       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6223      
6224       resultSize = AOP_SIZE(IC_RESULT(ic));
6225
6226       ADJUST_PUSHED_RESULT(compSize, resultSize);
6227
6228       _startLazyDPSEvaluation();
6229       while (compSize--)
6230       {
6231           emitcode ("pop", "acc");
6232           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6233       }
6234       _endLazyDPSEvaluation();
6235       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6236 }
6237
6238
6239 /*-----------------------------------------------------------------*/
6240 /* genAnd  - code for and                                          */
6241 /*-----------------------------------------------------------------*/
6242 static void
6243 genAnd (iCode * ic, iCode * ifx)
6244 {
6245   operand *left, *right, *result;
6246   int size, offset = 0;
6247   unsigned long lit = 0L;
6248   int bytelit;
6249   char buff[10];
6250   bool pushResult;
6251
6252   D (emitcode (";", "genAnd "););
6253
6254   AOP_OP_3_NOFATAL (ic, pushResult);
6255   AOP_SET_LOCALS (ic);
6256
6257   if (pushResult)
6258   {
6259       genFarFarLogicOp(ic, "anl");
6260       return;
6261   }  
6262
6263 #ifdef DEBUG_TYPE
6264   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6265             AOP_TYPE (result),
6266             AOP_TYPE (left), AOP_TYPE (right));
6267   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6268             AOP_SIZE (result),
6269             AOP_SIZE (left), AOP_SIZE (right));
6270 #endif
6271
6272   /* if left is a literal & right is not then exchange them */
6273   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6274 #ifdef LOGIC_OPS_BROKEN      
6275     ||  AOP_NEEDSACC (left)
6276 #endif
6277     )
6278     {
6279       operand *tmp = right;
6280       right = left;
6281       left = tmp;
6282     }
6283
6284   /* if result = right then exchange them */
6285   if (sameRegs (AOP (result), AOP (right)))
6286     {
6287       operand *tmp = right;
6288       right = left;
6289       left = tmp;
6290     }
6291
6292   /* if right is bit then exchange them */
6293   if (AOP_TYPE (right) == AOP_CRY &&
6294       AOP_TYPE (left) != AOP_CRY)
6295     {
6296       operand *tmp = right;
6297       right = left;
6298       left = tmp;
6299     }
6300   if (AOP_TYPE (right) == AOP_LIT)
6301     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6302
6303   size = AOP_SIZE (result);
6304
6305   // if(bit & yy)
6306   // result = bit & yy;
6307   if (AOP_TYPE (left) == AOP_CRY)
6308     {
6309       // c = bit & literal;
6310       if (AOP_TYPE (right) == AOP_LIT)
6311         {
6312           if (lit & 1)
6313             {
6314               if (size && sameRegs (AOP (result), AOP (left)))
6315                 // no change
6316                 goto release;
6317               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6318             }
6319           else
6320             {
6321               // bit(result) = 0;
6322               if (size && (AOP_TYPE (result) == AOP_CRY))
6323                 {
6324                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6325                   goto release;
6326                 }
6327               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6328                 {
6329                   jumpIfTrue (ifx);
6330                   goto release;
6331                 }
6332               emitcode ("clr", "c");
6333             }
6334         }
6335       else
6336         {
6337           if (AOP_TYPE (right) == AOP_CRY)
6338             {
6339               // c = bit & bit;
6340               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6341               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6342             }
6343           else
6344             {
6345               // c = bit & val;
6346               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6347               // c = lsb
6348               emitcode ("rrc", "a");
6349               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6350             }
6351         }
6352       // bit = c
6353       // val = c
6354       if (size)
6355         outBitC (result);
6356       // if(bit & ...)
6357       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6358         genIfxJump (ifx, "c");
6359       goto release;
6360     }
6361
6362   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6363   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6364   if ((AOP_TYPE (right) == AOP_LIT) &&
6365       (AOP_TYPE (result) == AOP_CRY) &&
6366       (AOP_TYPE (left) != AOP_CRY))
6367     {
6368       int posbit = isLiteralBit (lit);
6369       /* left &  2^n */
6370       if (posbit)
6371         {
6372           posbit--;
6373           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6374           // bit = left & 2^n
6375           if (size)
6376             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6377           // if(left &  2^n)
6378           else
6379             {
6380               if (ifx)
6381                 {
6382                   SNPRINTF (buff, sizeof(buff), 
6383                             "acc.%d", posbit & 0x07);
6384                   genIfxJump (ifx, buff);
6385                 }
6386               else 
6387                   {
6388                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6389                   }
6390               goto release;
6391             }
6392         }
6393       else
6394         {
6395           symbol *tlbl = newiTempLabel (NULL);
6396           int sizel = AOP_SIZE (left);
6397           if (size)
6398             emitcode ("setb", "c");
6399           while (sizel--)
6400             {
6401               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6402                 {
6403                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6404                   // byte ==  2^n ?
6405                   if ((posbit = isLiteralBit (bytelit)) != 0)
6406                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6407                   else
6408                     {
6409                       if (bytelit != 0x0FFL)
6410                         emitcode ("anl", "a,%s",
6411                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6412                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6413                     }
6414                 }
6415               offset++;
6416             }
6417           // bit = left & literal
6418           if (size)
6419             {
6420               emitcode ("clr", "c");
6421               emitcode ("", "!tlabeldef", tlbl->key + 100);
6422             }
6423           // if(left & literal)
6424           else
6425             {
6426               if (ifx)
6427                 jmpTrueOrFalse (ifx, tlbl);
6428               else
6429                 emitcode ("", "!tlabeldef", tlbl->key + 100);
6430               goto release;
6431             }
6432         }
6433       outBitC (result);
6434       goto release;
6435     }
6436
6437   /* if left is same as result */
6438   if (sameRegs (AOP (result), AOP (left)))
6439     {
6440       for (; size--; offset++)
6441         {
6442           if (AOP_TYPE (right) == AOP_LIT)
6443             {
6444               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6445                 continue;
6446               else if (bytelit == 0)
6447                 aopPut (AOP (result), zero, offset);
6448               else if (IS_AOP_PREG (result))
6449                 {
6450                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6451                   emitcode ("anl", "a,%s",
6452                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6453                   aopPut (AOP (result), "a", offset);
6454                 }
6455               else
6456                 emitcode ("anl", "%s,%s",
6457                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6458                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6459             }
6460           else
6461             {
6462               if (AOP_TYPE (left) == AOP_ACC)
6463                 emitcode ("anl", "a,%s",
6464                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6465               else
6466                 {
6467                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6468                   if (IS_AOP_PREG (result))
6469                     {
6470                       emitcode ("anl", "a,%s",
6471                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6472                       aopPut (AOP (result), "a", offset);
6473                     }
6474                   else
6475                     emitcode ("anl", "%s,a",
6476                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6477                 }
6478             }
6479         }
6480     }
6481   else
6482     {
6483       // left & result in different registers
6484       if (AOP_TYPE (result) == AOP_CRY)
6485         {
6486           // result = bit
6487           // if(size), result in bit
6488           // if(!size && ifx), conditional oper: if(left & right)
6489           symbol *tlbl = newiTempLabel (NULL);
6490           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6491           if (size)
6492             emitcode ("setb", "c");
6493           while (sizer--)
6494             {
6495               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6496                 emitcode ("anl", "a,%s",
6497                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6498               } else {
6499                 if (AOP_TYPE(left)==AOP_ACC) {
6500                   emitcode("mov", "b,a");
6501                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6502                   emitcode("anl", "a,b");
6503                 }else {
6504                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6505                   emitcode ("anl", "a,%s",
6506                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6507                 }
6508               }
6509               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6510               offset++;
6511             }
6512           if (size)
6513             {
6514               CLRC;
6515               emitcode ("", "!tlabeldef", tlbl->key + 100);
6516               outBitC (result);
6517             }
6518           else if (ifx)
6519             jmpTrueOrFalse (ifx, tlbl);
6520           else
6521             emitcode ("", "!tlabeldef", tlbl->key + 100);
6522         }
6523       else
6524         {
6525           for (; (size--); offset++)
6526             {
6527               // normal case
6528               // result = left & right
6529               if (AOP_TYPE (right) == AOP_LIT)
6530                 {
6531                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6532                     {
6533                       aopPut (AOP (result),
6534                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6535                               offset);
6536                       continue;
6537                     }
6538                   else if (bytelit == 0)
6539                     {
6540                       aopPut (AOP (result), zero, offset);
6541                       continue;
6542                     }
6543                   D (emitcode (";", "better literal AND."););
6544                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6545                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6546                                                     FALSE, FALSE, DP2_RESULT_REG));
6547
6548                 }
6549               else
6550                 {
6551                   // faster than result <- left, anl result,right
6552                   // and better if result is SFR
6553                   if (AOP_TYPE (left) == AOP_ACC)
6554                     {
6555                       emitcode ("anl", "a,%s", 
6556                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6557                     }
6558                   else
6559                     {
6560                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6561                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6562                       {
6563                           emitcode("mov", "b,a");
6564                           rOp = "b";
6565                       }
6566                         
6567                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6568                       emitcode ("anl", "a,%s", rOp);
6569                     }                   
6570                 }
6571               aopPut (AOP (result), "a", offset);
6572             }
6573         }
6574     }
6575
6576 release:
6577   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6578   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6579   freeAsmop (result, NULL, ic, TRUE);
6580 }
6581
6582
6583 /*-----------------------------------------------------------------*/
6584 /* genOr  - code for or                                            */
6585 /*-----------------------------------------------------------------*/
6586 static void
6587 genOr (iCode * ic, iCode * ifx)
6588 {
6589   operand *left, *right, *result;
6590   int size, offset = 0;
6591   unsigned long lit = 0L;
6592   bool     pushResult;
6593
6594   D (emitcode (";", "genOr "););
6595
6596   AOP_OP_3_NOFATAL (ic, pushResult);
6597   AOP_SET_LOCALS (ic);
6598
6599   if (pushResult)
6600   {
6601       genFarFarLogicOp(ic, "orl");
6602       return;
6603   }
6604
6605
6606 #ifdef DEBUG_TYPE
6607   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6608             AOP_TYPE (result),
6609             AOP_TYPE (left), AOP_TYPE (right));
6610   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6611             AOP_SIZE (result),
6612             AOP_SIZE (left), AOP_SIZE (right));
6613 #endif
6614
6615   /* if left is a literal & right is not then exchange them */
6616   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6617 #ifdef LOGIC_OPS_BROKEN
6618    || AOP_NEEDSACC (left) // I think this is a net loss now.
6619 #endif      
6620       )
6621     {
6622       operand *tmp = right;
6623       right = left;
6624       left = tmp;
6625     }
6626
6627   /* if result = right then exchange them */
6628   if (sameRegs (AOP (result), AOP (right)))
6629     {
6630       operand *tmp = right;
6631       right = left;
6632       left = tmp;
6633     }
6634
6635   /* if right is bit then exchange them */
6636   if (AOP_TYPE (right) == AOP_CRY &&
6637       AOP_TYPE (left) != AOP_CRY)
6638     {
6639       operand *tmp = right;
6640       right = left;
6641       left = tmp;
6642     }
6643   if (AOP_TYPE (right) == AOP_LIT)
6644     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6645
6646   size = AOP_SIZE (result);
6647
6648   // if(bit | yy)
6649   // xx = bit | yy;
6650   if (AOP_TYPE (left) == AOP_CRY)
6651     {
6652       if (AOP_TYPE (right) == AOP_LIT)
6653         {
6654           // c = bit & literal;
6655           if (lit)
6656             {
6657               // lit != 0 => result = 1
6658               if (AOP_TYPE (result) == AOP_CRY)
6659                 {
6660                   if (size)
6661                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6662                   else if (ifx)
6663                     continueIfTrue (ifx);
6664                   goto release;
6665                 }
6666               emitcode ("setb", "c");
6667             }
6668           else
6669             {
6670               // lit == 0 => result = left
6671               if (size && sameRegs (AOP (result), AOP (left)))
6672                 goto release;
6673               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6674             }
6675         }
6676       else
6677         {
6678           if (AOP_TYPE (right) == AOP_CRY)
6679             {
6680               // c = bit | bit;
6681               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6682               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6683             }
6684           else
6685             {
6686               // c = bit | val;
6687               symbol *tlbl = newiTempLabel (NULL);
6688               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6689                 emitcode ("setb", "c");
6690               emitcode ("jb", "%s,!tlabel",
6691                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6692               toBoolean (right);
6693               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6694               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6695                 {
6696                   jmpTrueOrFalse (ifx, tlbl);
6697                   goto release;
6698                 }
6699               else
6700                 {
6701                   CLRC;
6702                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6703                 }
6704             }
6705         }
6706       // bit = c
6707       // val = c
6708       if (size)
6709         outBitC (result);
6710       // if(bit | ...)
6711       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6712            genIfxJump (ifx, "c");
6713       goto release;
6714     }
6715
6716   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6717   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6718   if ((AOP_TYPE (right) == AOP_LIT) &&
6719       (AOP_TYPE (result) == AOP_CRY) &&
6720       (AOP_TYPE (left) != AOP_CRY))
6721     {
6722       if (lit)
6723         {
6724           // result = 1
6725           if (size)
6726             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6727           else
6728             continueIfTrue (ifx);
6729           goto release;
6730         }
6731       else
6732         {
6733           // lit = 0, result = boolean(left)
6734           if (size)
6735             emitcode ("setb", "c");
6736           toBoolean (right);
6737           if (size)
6738             {
6739               symbol *tlbl = newiTempLabel (NULL);
6740               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6741               CLRC;
6742               emitcode ("", "!tlabeldef", tlbl->key + 100);
6743             }
6744           else
6745             {
6746               genIfxJump (ifx, "a");
6747               goto release;
6748             }
6749         }
6750       outBitC (result);
6751       goto release;
6752     }
6753
6754   /* if left is same as result */
6755   if (sameRegs (AOP (result), AOP (left)))
6756     {
6757       for (; size--; offset++)
6758         {
6759           if (AOP_TYPE (right) == AOP_LIT)
6760             {
6761               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6762                 {
6763                   continue;
6764                 }
6765               else
6766                 {
6767                   if (IS_AOP_PREG (left))
6768                     {
6769                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6770                       emitcode ("orl", "a,%s",
6771                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6772                       aopPut (AOP (result), "a", offset);
6773                     }
6774                   else
6775                     {
6776                       emitcode ("orl", "%s,%s",
6777                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6778                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6779                     }
6780                 }
6781             }
6782           else
6783             {
6784               if (AOP_TYPE (left) == AOP_ACC)
6785                 {
6786                   emitcode ("orl", "a,%s",
6787                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6788                 }
6789               else
6790                 {
6791                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6792                   if (IS_AOP_PREG (left))
6793                     {
6794                       emitcode ("orl", "a,%s", 
6795                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6796                       aopPut (AOP (result), "a", offset);
6797                     }
6798                   else
6799                     {
6800                       emitcode ("orl", "%s,a",
6801                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6802                     }
6803                 }
6804             }
6805         }
6806     }
6807   else
6808     {
6809       // left & result in different registers
6810       if (AOP_TYPE (result) == AOP_CRY)
6811         {
6812           // result = bit
6813           // if(size), result in bit
6814           // if(!size && ifx), conditional oper: if(left | right)
6815           symbol *tlbl = newiTempLabel (NULL);
6816           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6817           if (size)
6818             emitcode ("setb", "c");
6819           while (sizer--)
6820             {
6821               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6822                 emitcode ("orl", "a,%s",
6823                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6824               } else {
6825                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6826                 emitcode ("orl", "a,%s",
6827                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6828               }
6829               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6830               offset++;
6831             }
6832           if (size)
6833             {
6834               CLRC;
6835               emitcode ("", "!tlabeldef", tlbl->key + 100);
6836               outBitC (result);
6837             }
6838           else if (ifx)
6839             jmpTrueOrFalse (ifx, tlbl);
6840           else
6841             emitcode ("", "!tlabeldef", tlbl->key + 100);
6842         }
6843       else
6844         {
6845             _startLazyDPSEvaluation();
6846           for (; (size--); offset++)
6847             {
6848               // normal case
6849               // result = left & right
6850               if (AOP_TYPE (right) == AOP_LIT)
6851                 {
6852                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6853                     {
6854                       aopPut (AOP (result),
6855                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6856                               offset);
6857                       continue;
6858                     }
6859                   D (emitcode (";", "better literal OR."););
6860                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6861                   emitcode ("orl", "a, %s",
6862                             aopGet (AOP (right), offset,
6863                                     FALSE, FALSE, DP2_RESULT_REG));
6864
6865                 }
6866               else
6867                 {
6868                   // faster than result <- left, anl result,right
6869                   // and better if result is SFR
6870                   if (AOP_TYPE (left) == AOP_ACC)
6871                     {
6872                       emitcode ("orl", "a,%s",
6873                                 aopGet (AOP (right), offset,
6874                                         FALSE, FALSE, DP2_RESULT_REG));
6875                     }
6876                   else
6877                     {
6878                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6879                         
6880                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6881                       {
6882                           emitcode("mov", "b,a");
6883                           rOp = "b";
6884                       }
6885                         
6886                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6887                       emitcode ("orl", "a,%s", rOp);
6888                     }
6889                 }
6890               aopPut (AOP (result), "a", offset);
6891             }
6892             _endLazyDPSEvaluation();
6893         }
6894     }
6895
6896 release:
6897   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6898   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6899   freeAsmop (result, NULL, ic, TRUE);
6900 }
6901
6902 /*-----------------------------------------------------------------*/
6903 /* genXor - code for xclusive or                                   */
6904 /*-----------------------------------------------------------------*/
6905 static void
6906 genXor (iCode * ic, iCode * ifx)
6907 {
6908   operand *left, *right, *result;
6909   int size, offset = 0;
6910   unsigned long lit = 0L;
6911   bool pushResult;
6912
6913   D (emitcode (";", "genXor "););
6914
6915   AOP_OP_3_NOFATAL (ic, pushResult);
6916   AOP_SET_LOCALS (ic);
6917
6918   if (pushResult)
6919   {
6920       genFarFarLogicOp(ic, "xrl");
6921       return;
6922   }  
6923
6924 #ifdef DEBUG_TYPE
6925   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6926             AOP_TYPE (result),
6927             AOP_TYPE (left), AOP_TYPE (right));
6928   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6929             AOP_SIZE (result),
6930             AOP_SIZE (left), AOP_SIZE (right));
6931 #endif
6932
6933   /* if left is a literal & right is not ||
6934      if left needs acc & right does not */
6935   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6936 #ifdef LOGIC_OPS_BROKEN      
6937       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6938 #endif
6939      )
6940     {
6941       operand *tmp = right;
6942       right = left;
6943       left = tmp;
6944     }
6945
6946   /* if result = right then exchange them */
6947   if (sameRegs (AOP (result), AOP (right)))
6948     {
6949       operand *tmp = right;
6950       right = left;
6951       left = tmp;
6952     }
6953
6954   /* if right is bit then exchange them */
6955   if (AOP_TYPE (right) == AOP_CRY &&
6956       AOP_TYPE (left) != AOP_CRY)
6957     {
6958       operand *tmp = right;
6959       right = left;
6960       left = tmp;
6961     }
6962   if (AOP_TYPE (right) == AOP_LIT)
6963     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6964
6965   size = AOP_SIZE (result);
6966
6967   // if(bit ^ yy)
6968   // xx = bit ^ yy;
6969   if (AOP_TYPE (left) == AOP_CRY)
6970     {
6971       if (AOP_TYPE (right) == AOP_LIT)
6972         {
6973           // c = bit & literal;
6974           if (lit >> 1)
6975             {
6976               // lit>>1  != 0 => result = 1
6977               if (AOP_TYPE (result) == AOP_CRY)
6978                 {
6979                   if (size)
6980                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6981                   else if (ifx)
6982                     continueIfTrue (ifx);
6983                   goto release;
6984                 }
6985               emitcode ("setb", "c");
6986             }
6987           else
6988             {
6989               // lit == (0 or 1)
6990               if (lit == 0)
6991                 {
6992                   // lit == 0, result = left
6993                   if (size && sameRegs (AOP (result), AOP (left)))
6994                     goto release;
6995                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6996                 }
6997               else
6998                 {
6999                   // lit == 1, result = not(left)
7000                   if (size && sameRegs (AOP (result), AOP (left)))
7001                     {
7002                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7003                       goto release;
7004                     }
7005                   else
7006                     {
7007                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7008                       emitcode ("cpl", "c");
7009                     }
7010                 }
7011             }
7012
7013         }
7014       else
7015         {
7016           // right != literal
7017           symbol *tlbl = newiTempLabel (NULL);
7018           if (AOP_TYPE (right) == AOP_CRY)
7019             {
7020               // c = bit ^ bit;
7021               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7022             }
7023           else
7024             {
7025               int sizer = AOP_SIZE (right);
7026               // c = bit ^ val
7027               // if val>>1 != 0, result = 1
7028               emitcode ("setb", "c");
7029               while (sizer)
7030                 {
7031                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
7032                   if (sizer == 1)
7033                     // test the msb of the lsb
7034                     emitcode ("anl", "a,#!constbyte",0xfe);
7035                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
7036                   sizer--;
7037                 }
7038               // val = (0,1)
7039               emitcode ("rrc", "a");
7040             }
7041           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7042           emitcode ("cpl", "c");
7043           emitcode ("", "!tlabeldef", (tlbl->key + 100));
7044         }
7045       // bit = c
7046       // val = c
7047       if (size)
7048         outBitC (result);
7049       // if(bit | ...)
7050       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7051         genIfxJump (ifx, "c");
7052       goto release;
7053     }
7054
7055   if (sameRegs (AOP (result), AOP (left)))
7056     {
7057       /* if left is same as result */
7058       for (; size--; offset++)
7059         {
7060           if (AOP_TYPE (right) == AOP_LIT)
7061             {
7062               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7063                 continue;
7064               else if (IS_AOP_PREG (left))
7065                 {
7066                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7067                   emitcode ("xrl", "a,%s",
7068                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7069                   aopPut (AOP (result), "a", offset);
7070                 }
7071               else
7072                 emitcode ("xrl", "%s,%s",
7073                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7074                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7075             }
7076           else
7077             {
7078               if (AOP_TYPE (left) == AOP_ACC)
7079                 emitcode ("xrl", "a,%s",
7080                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7081               else
7082                 {
7083                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7084                   if (IS_AOP_PREG (left))
7085                     {
7086                       emitcode ("xrl", "a,%s",
7087                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7088                       aopPut (AOP (result), "a", offset);
7089                     }
7090                   else
7091                     emitcode ("xrl", "%s,a",
7092                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7093                 }
7094             }
7095         }
7096     }
7097   else
7098     {
7099       // left & result in different registers
7100       if (AOP_TYPE (result) == AOP_CRY)
7101         {
7102           // result = bit
7103           // if(size), result in bit
7104           // if(!size && ifx), conditional oper: if(left ^ right)
7105           symbol *tlbl = newiTempLabel (NULL);
7106           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7107                   
7108           if (size)
7109             emitcode ("setb", "c");
7110           while (sizer--)
7111             {
7112               if ((AOP_TYPE (right) == AOP_LIT) &&
7113                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7114                 {
7115                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7116                 }
7117               else
7118                 {
7119                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7120                     emitcode ("xrl", "a,%s",
7121                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7122                   } else {
7123                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7124                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7125                       {
7126                           emitcode("mov", "b,a");
7127                           rOp = "b";
7128                       }
7129                         
7130                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7131                       emitcode ("xrl", "a,%s", rOp);                  
7132                   }
7133                 }
7134               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7135               offset++;
7136             }
7137           if (size)
7138             {
7139               CLRC;
7140               emitcode ("", "!tlabeldef", tlbl->key + 100);
7141               outBitC (result);
7142             }
7143           else if (ifx)
7144             jmpTrueOrFalse (ifx, tlbl);
7145         }
7146       else
7147         {
7148         for (; (size--); offset++)
7149           {
7150             // normal case
7151             // result = left & right
7152             if (AOP_TYPE (right) == AOP_LIT)
7153               {
7154                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7155                   {
7156                     aopPut (AOP (result),
7157                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7158                             offset);
7159                     continue;
7160                   }
7161                 D (emitcode (";", "better literal XOR."););
7162                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7163                 emitcode ("xrl", "a, %s",
7164                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7165               }
7166             else
7167               {
7168                 // faster than result <- left, anl result,right
7169                 // and better if result is SFR
7170                 if (AOP_TYPE (left) == AOP_ACC)
7171                   {
7172                     emitcode ("xrl", "a,%s",
7173                               aopGet (AOP (right), offset,
7174                                       FALSE, FALSE, DP2_RESULT_REG));
7175                   }
7176                 else
7177                   {
7178                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7179                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7180                       {
7181                           emitcode("mov", "b,a");
7182                           rOp = "b";
7183                       }
7184                         
7185                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7186                       emitcode ("xrl", "a,%s", rOp);
7187                   }
7188               }
7189             aopPut (AOP (result), "a", offset);
7190           }
7191         }
7192         
7193     }
7194
7195 release:
7196   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7197   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7198   freeAsmop (result, NULL, ic, TRUE);
7199 }
7200
7201 /*-----------------------------------------------------------------*/
7202 /* genInline - write the inline code out                           */
7203 /*-----------------------------------------------------------------*/
7204 static void
7205 genInline (iCode * ic)
7206 {
7207   char *buffer, *bp, *bp1;
7208
7209   D (emitcode (";", "genInline "); );
7210
7211   _G.inLine += (!options.asmpeep);
7212
7213   buffer = Safe_strdup(IC_INLINE(ic));
7214   bp = buffer;
7215   bp1 = buffer;
7216
7217   /* emit each line as a code */
7218   while (*bp)
7219     {
7220       if (*bp == '\n')
7221         {
7222           *bp++ = '\0';
7223           emitcode (bp1, "");
7224           bp1 = bp;
7225         }
7226       else
7227         {
7228           if (*bp == ':')
7229             {
7230               bp++;
7231               *bp = '\0';
7232               bp++;
7233               emitcode (bp1, "");
7234               bp1 = bp;
7235             }
7236           else
7237             bp++;
7238         }
7239     }
7240   if (bp1 != bp)
7241     emitcode (bp1, "");
7242   /*     emitcode("",buffer); */
7243   _G.inLine -= (!options.asmpeep);
7244 }
7245
7246 /*-----------------------------------------------------------------*/
7247 /* genRRC - rotate right with carry                                */
7248 /*-----------------------------------------------------------------*/
7249 static void
7250 genRRC (iCode * ic)
7251 {
7252   operand *left, *result;
7253   int     size, offset;
7254
7255   D (emitcode (";", "genRRC "););
7256
7257   /* rotate right with carry */
7258   left = IC_LEFT (ic);
7259   result = IC_RESULT (ic);
7260   aopOp (left, ic, FALSE, FALSE);
7261   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7262
7263   /* move it to the result */
7264   size = AOP_SIZE (result);
7265   offset = size - 1;
7266   CLRC;
7267
7268   _startLazyDPSEvaluation ();
7269   while (size--)
7270     {
7271       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7272       emitcode ("rrc", "a");
7273       if (AOP_SIZE (result) > 1)
7274         aopPut (AOP (result), "a", offset--);
7275     }
7276   _endLazyDPSEvaluation ();
7277
7278   /* now we need to put the carry into the
7279      highest order byte of the result */
7280   if (AOP_SIZE (result) > 1)
7281     {
7282       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7283     }
7284   emitcode ("mov", "acc.7,c");
7285   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7286   freeAsmop (left, NULL, ic, TRUE);
7287   freeAsmop (result, NULL, ic, TRUE);
7288 }
7289
7290 /*-----------------------------------------------------------------*/
7291 /* genRLC - generate code for rotate left with carry               */
7292 /*-----------------------------------------------------------------*/
7293 static void
7294 genRLC (iCode * ic)
7295 {
7296   operand *left, *result;
7297   int size, offset;
7298   char *l;
7299
7300   D (emitcode (";", "genRLC "););
7301
7302   /* rotate right with carry */
7303   left = IC_LEFT (ic);
7304   result = IC_RESULT (ic);
7305   aopOp (left, ic, FALSE, FALSE);
7306   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7307
7308   /* move it to the result */
7309   size = AOP_SIZE (result);
7310   offset = 0;
7311   if (size--)
7312     {
7313       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7314       MOVA (l);
7315       emitcode ("add", "a,acc");
7316       if (AOP_SIZE (result) > 1)
7317         {
7318           aopPut (AOP (result), "a", offset++);
7319         }
7320
7321       _startLazyDPSEvaluation ();
7322       while (size--)
7323         {
7324           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7325           MOVA (l);
7326           emitcode ("rlc", "a");
7327           if (AOP_SIZE (result) > 1)
7328             aopPut (AOP (result), "a", offset++);
7329         }
7330       _endLazyDPSEvaluation ();
7331     }
7332   /* now we need to put the carry into the
7333      highest order byte of the result */
7334   if (AOP_SIZE (result) > 1)
7335     {
7336       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7337       MOVA (l);
7338     }
7339   emitcode ("mov", "acc.0,c");
7340   aopPut (AOP (result), "a", 0);
7341   freeAsmop (left, NULL, ic, TRUE);
7342   freeAsmop (result, NULL, ic, TRUE);
7343 }
7344
7345 /*-----------------------------------------------------------------*/
7346 /* genGetHbit - generates code get highest order bit               */
7347 /*-----------------------------------------------------------------*/
7348 static void
7349 genGetHbit (iCode * ic)
7350 {
7351   operand *left, *result;
7352   left = IC_LEFT (ic);
7353   result = IC_RESULT (ic);
7354   aopOp (left, ic, FALSE, FALSE);
7355   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7356
7357   D (emitcode (";", "genGetHbit "););
7358
7359   /* get the highest order byte into a */
7360   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7361   if (AOP_TYPE (result) == AOP_CRY)
7362     {
7363       emitcode ("rlc", "a");
7364       outBitC (result);
7365     }
7366   else
7367     {
7368       emitcode ("rl", "a");
7369       emitcode ("anl", "a,#1");
7370       outAcc (result);
7371     }
7372
7373
7374   freeAsmop (left, NULL, ic, TRUE);
7375   freeAsmop (result, NULL, ic, TRUE);
7376 }
7377
7378 /*-----------------------------------------------------------------*/
7379 /* genSwap - generates code to swap nibbles or bytes               */
7380 /*-----------------------------------------------------------------*/
7381 static void
7382 genSwap (iCode * ic)
7383 {
7384   operand *left, *result;
7385
7386   D(emitcode (";     genSwap",""));
7387
7388   left = IC_LEFT (ic);
7389   result = IC_RESULT (ic);
7390   aopOp (left, ic, FALSE, FALSE);
7391   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7392   
7393   _startLazyDPSEvaluation ();
7394   switch (AOP_SIZE (left))
7395     {
7396     case 1: /* swap nibbles in byte */
7397       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7398       emitcode ("swap", "a");
7399       aopPut (AOP (result), "a", 0);
7400       break;
7401     case 2: /* swap bytes in word */
7402       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7403         {
7404           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7405           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7406           aopPut (AOP (result), "a", 1);
7407         }
7408       else if (operandsEqu (left, result))
7409         {
7410           char * reg = "a";
7411           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7412           if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7413             {
7414               emitcode ("mov", "b,a");
7415               reg = "b";
7416               _G.bInUse=1;
7417             }
7418           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7419           aopPut (AOP (result), reg, 1);
7420           _G.bInUse=0;
7421         }
7422       else
7423         {
7424           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7425           aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7426         }
7427       break;
7428     default:
7429       wassertl(FALSE, "unsupported SWAP operand size");
7430     }
7431   _endLazyDPSEvaluation ();
7432   
7433   freeAsmop (left, NULL, ic, TRUE);
7434   freeAsmop (result, NULL, ic, TRUE);
7435 }
7436
7437 /*-----------------------------------------------------------------*/
7438 /* AccRol - rotate left accumulator by known count                 */
7439 /*-----------------------------------------------------------------*/
7440 static void
7441 AccRol (int shCount)
7442 {
7443   shCount &= 0x0007;            // shCount : 0..7
7444
7445   switch (shCount)
7446     {
7447     case 0:
7448       break;
7449     case 1:
7450       emitcode ("rl", "a");
7451       break;
7452     case 2:
7453       emitcode ("rl", "a");
7454       emitcode ("rl", "a");
7455       break;
7456     case 3:
7457       emitcode ("swap", "a");
7458       emitcode ("rr", "a");
7459       break;
7460     case 4:
7461       emitcode ("swap", "a");
7462       break;
7463     case 5:
7464       emitcode ("swap", "a");
7465       emitcode ("rl", "a");
7466       break;
7467     case 6:
7468       emitcode ("rr", "a");
7469       emitcode ("rr", "a");
7470       break;
7471     case 7:
7472       emitcode ("rr", "a");
7473       break;
7474     }
7475 }
7476
7477 /*-----------------------------------------------------------------*/
7478 /* AccLsh - left shift accumulator by known count                  */
7479 /*-----------------------------------------------------------------*/
7480 static void
7481 AccLsh (int shCount)
7482 {
7483   if (shCount != 0)
7484     {
7485       if (shCount == 1)
7486         emitcode ("add", "a,acc");
7487       else if (shCount == 2)
7488         {
7489           emitcode ("add", "a,acc");
7490           emitcode ("add", "a,acc");
7491         }
7492       else
7493         {
7494           /* rotate left accumulator */
7495           AccRol (shCount);
7496           /* and kill the lower order bits */
7497           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7498         }
7499     }
7500 }
7501
7502 /*-----------------------------------------------------------------*/
7503 /* AccRsh - right shift accumulator by known count                 */
7504 /*-----------------------------------------------------------------*/
7505 static void
7506 AccRsh (int shCount)
7507 {
7508   if (shCount != 0)
7509     {
7510       if (shCount == 1)
7511         {
7512           CLRC;
7513           emitcode ("rrc", "a");
7514         }
7515       else
7516         {
7517           /* rotate right accumulator */
7518           AccRol (8 - shCount);
7519           /* and kill the higher order bits */
7520           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7521         }
7522     }
7523 }
7524
7525 #ifdef BETTER_LITERAL_SHIFT
7526 /*-----------------------------------------------------------------*/
7527 /* AccSRsh - signed right shift accumulator by known count                 */
7528 /*-----------------------------------------------------------------*/
7529 static void
7530 AccSRsh (int shCount)
7531 {
7532   symbol *tlbl;
7533   if (shCount != 0)
7534     {
7535       if (shCount == 1)
7536         {
7537           emitcode ("mov", "c,acc.7");
7538           emitcode ("rrc", "a");
7539         }
7540       else if (shCount == 2)
7541         {
7542           emitcode ("mov", "c,acc.7");
7543           emitcode ("rrc", "a");
7544           emitcode ("mov", "c,acc.7");
7545           emitcode ("rrc", "a");
7546         }
7547       else
7548         {
7549           tlbl = newiTempLabel (NULL);
7550           /* rotate right accumulator */
7551           AccRol (8 - shCount);
7552           /* and kill the higher order bits */
7553           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7554           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7555           emitcode ("orl", "a,#!constbyte",
7556                     (unsigned char) ~SRMask[shCount]);
7557           emitcode ("", "!tlabeldef", tlbl->key + 100);
7558         }
7559     }
7560 }
7561 #endif
7562
7563 #ifdef BETTER_LITERAL_SHIFT
7564 /*-----------------------------------------------------------------*/
7565 /* shiftR1Left2Result - shift right one byte from left to result   */
7566 /*-----------------------------------------------------------------*/
7567 static void
7568 shiftR1Left2Result (operand * left, int offl,
7569                     operand * result, int offr,
7570                     int shCount, int sign)
7571 {
7572   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7573   /* shift right accumulator */
7574   if (sign)
7575     AccSRsh (shCount);
7576   else
7577     AccRsh (shCount);
7578   aopPut (AOP (result), "a", offr);
7579 }
7580 #endif
7581
7582 #ifdef BETTER_LITERAL_SHIFT
7583 /*-----------------------------------------------------------------*/
7584 /* shiftL1Left2Result - shift left one byte from left to result    */
7585 /*-----------------------------------------------------------------*/
7586 static void
7587 shiftL1Left2Result (operand * left, int offl,
7588                     operand * result, int offr, int shCount)
7589 {
7590   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7591   /* shift left accumulator */
7592   AccLsh (shCount);
7593   aopPut (AOP (result), "a", offr);
7594 }
7595 #endif
7596
7597 #ifdef BETTER_LITERAL_SHIFT
7598 /*-----------------------------------------------------------------*/
7599 /* movLeft2Result - move byte from left to result                  */
7600 /*-----------------------------------------------------------------*/
7601 static void
7602 movLeft2Result (operand * left, int offl,
7603                 operand * result, int offr, int sign)
7604 {
7605   char *l;
7606   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7607   {
7608       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7609
7610       if (*l == '@' && (IS_AOP_PREG (result)))
7611       {
7612           emitcode ("mov", "a,%s", l);
7613           aopPut (AOP (result), "a", offr);
7614       }
7615       else
7616       {
7617           if (!sign)
7618           {
7619             aopPut (AOP (result), l, offr);
7620           }
7621           else
7622             {
7623               /* MSB sign in acc.7 ! */
7624               if (getDataSize (left) == offl + 1)
7625                 {
7626                   emitcode ("mov", "a,%s", l);
7627                   aopPut (AOP (result), "a", offr);
7628                 }
7629             }
7630       }
7631   }
7632 }
7633 #endif
7634
7635 #ifdef BETTER_LITERAL_SHIFT
7636 /*-----------------------------------------------------------------*/
7637 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7638 /*-----------------------------------------------------------------*/
7639 static void
7640 AccAXRrl1 (char *x)
7641 {
7642   emitcode ("rrc", "a");
7643   emitcode ("xch", "a,%s", x);
7644   emitcode ("rrc", "a");
7645   emitcode ("xch", "a,%s", x);
7646 }
7647 #endif
7648
7649 #ifdef BETTER_LITERAL_SHIFT
7650 //REMOVE ME!!!
7651 /*-----------------------------------------------------------------*/
7652 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7653 /*-----------------------------------------------------------------*/
7654 static void
7655 AccAXLrl1 (char *x)
7656 {
7657   emitcode ("xch", "a,%s", x);
7658   emitcode ("rlc", "a");
7659   emitcode ("xch", "a,%s", x);
7660   emitcode ("rlc", "a");
7661 }
7662 #endif
7663
7664 #ifdef BETTER_LITERAL_SHIFT
7665 /*-----------------------------------------------------------------*/
7666 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7667 /*-----------------------------------------------------------------*/
7668 static void
7669 AccAXLsh1 (char *x)
7670 {
7671   emitcode ("xch", "a,%s", x);
7672   emitcode ("add", "a,acc");
7673   emitcode ("xch", "a,%s", x);
7674   emitcode ("rlc", "a");
7675 }
7676 #endif
7677
7678 #ifdef BETTER_LITERAL_SHIFT
7679 /*-----------------------------------------------------------------*/
7680 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7681 /*-----------------------------------------------------------------*/
7682 static void
7683 AccAXLsh (char *x, int shCount)
7684 {
7685   switch (shCount)
7686     {
7687     case 0:
7688       break;
7689     case 1:
7690       AccAXLsh1 (x);
7691       break;
7692     case 2:
7693       AccAXLsh1 (x);
7694       AccAXLsh1 (x);
7695       break;
7696     case 3:
7697     case 4:
7698     case 5:                     // AAAAABBB:CCCCCDDD
7699
7700       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7701
7702       emitcode ("anl", "a,#!constbyte",
7703                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7704
7705       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7706
7707       AccRol (shCount);         // DDDCCCCC:BBB00000
7708
7709       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7710
7711       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7712
7713       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7714
7715       emitcode ("anl", "a,#!constbyte",
7716                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7717
7718       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7719
7720       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7721
7722       break;
7723     case 6:                     // AAAAAABB:CCCCCCDD
7724       emitcode ("anl", "a,#!constbyte",
7725                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7726       emitcode ("mov", "c,acc.0");      // c = B
7727       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7728 #if 0
7729       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7730       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7731 #else
7732       emitcode("rrc","a"); 
7733       emitcode("xch","a,%s", x); 
7734       emitcode("rrc","a"); 
7735       emitcode("mov","c,acc.0"); //<< get correct bit 
7736       emitcode("xch","a,%s", x); 
7737
7738       emitcode("rrc","a"); 
7739       emitcode("xch","a,%s", x); 
7740       emitcode("rrc","a"); 
7741       emitcode("xch","a,%s", x); 
7742 #endif
7743       break;
7744     case 7:                     // a:x <<= 7
7745
7746       emitcode ("anl", "a,#!constbyte",
7747                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7748
7749       emitcode ("mov", "c,acc.0");      // c = B
7750
7751       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7752
7753       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7754
7755       break;
7756     default:
7757       break;
7758     }
7759 }
7760 #endif
7761
7762 #ifdef BETTER_LITERAL_SHIFT
7763 //REMOVE ME!!!
7764 /*-----------------------------------------------------------------*/
7765 /* AccAXRsh - right shift a:x known count (0..7)                   */
7766 /*-----------------------------------------------------------------*/
7767 static void
7768 AccAXRsh (char *x, int shCount)
7769 {
7770   switch (shCount)
7771     {
7772     case 0:
7773       break;
7774     case 1:
7775       CLRC;
7776       AccAXRrl1 (x);            // 0->a:x
7777
7778       break;
7779     case 2:
7780       CLRC;
7781       AccAXRrl1 (x);            // 0->a:x
7782
7783       CLRC;
7784       AccAXRrl1 (x);            // 0->a:x
7785
7786       break;
7787     case 3:
7788     case 4:
7789     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7790
7791       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7792
7793       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7794
7795       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7796
7797       emitcode ("anl", "a,#!constbyte",
7798                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7799
7800       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7801
7802       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7803
7804       emitcode ("anl", "a,#!constbyte",
7805                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7806
7807       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7808
7809       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7810
7811       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7812
7813       break;
7814     case 6:                     // AABBBBBB:CCDDDDDD
7815
7816       emitcode ("mov", "c,acc.7");
7817       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7818
7819       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7820
7821       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7822
7823       emitcode ("anl", "a,#!constbyte",
7824                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7825
7826       break;
7827     case 7:                     // ABBBBBBB:CDDDDDDD
7828
7829       emitcode ("mov", "c,acc.7");      // c = A
7830
7831       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7832
7833       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7834
7835       emitcode ("anl", "a,#!constbyte",
7836                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7837
7838       break;
7839     default:
7840       break;
7841     }
7842 }
7843 #endif
7844
7845 #ifdef BETTER_LITERAL_SHIFT
7846 /*-----------------------------------------------------------------*/
7847 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7848 /*-----------------------------------------------------------------*/
7849 static void
7850 AccAXRshS (char *x, int shCount)
7851 {
7852   symbol *tlbl;
7853   switch (shCount)
7854     {
7855     case 0:
7856       break;
7857     case 1:
7858       emitcode ("mov", "c,acc.7");
7859       AccAXRrl1 (x);            // s->a:x
7860
7861       break;
7862     case 2:
7863       emitcode ("mov", "c,acc.7");
7864       AccAXRrl1 (x);            // s->a:x
7865
7866       emitcode ("mov", "c,acc.7");
7867       AccAXRrl1 (x);            // s->a:x
7868
7869       break;
7870     case 3:
7871     case 4:
7872     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7873
7874       tlbl = newiTempLabel (NULL);
7875       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7876
7877       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7878
7879       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7880
7881       emitcode ("anl", "a,#!constbyte",
7882                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7883
7884       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7885
7886       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7887
7888       emitcode ("anl", "a,#!constbyte",
7889                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7890
7891       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7892
7893       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7894
7895       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7896
7897       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7898       emitcode ("orl", "a,#!constbyte",
7899                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7900
7901       emitcode ("", "!tlabeldef", tlbl->key + 100);
7902       break;                    // SSSSAAAA:BBBCCCCC
7903
7904     case 6:                     // AABBBBBB:CCDDDDDD
7905
7906       tlbl = newiTempLabel (NULL);
7907       emitcode ("mov", "c,acc.7");
7908       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7909
7910       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7911
7912       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7913
7914       emitcode ("anl", "a,#!constbyte",
7915                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7916
7917       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7918       emitcode ("orl", "a,#!constbyte",
7919                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7920
7921       emitcode ("", "!tlabeldef", tlbl->key + 100);
7922       break;
7923     case 7:                     // ABBBBBBB:CDDDDDDD
7924
7925       tlbl = newiTempLabel (NULL);
7926       emitcode ("mov", "c,acc.7");      // c = A
7927
7928       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7929
7930       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7931
7932       emitcode ("anl", "a,#!constbyte",
7933                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7934
7935       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7936       emitcode ("orl", "a,#!constbyte",
7937                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7938
7939       emitcode ("", "!tlabeldef", tlbl->key + 100);
7940       break;
7941     default:
7942       break;
7943     }
7944 }
7945 #endif
7946
7947 #ifdef BETTER_LITERAL_SHIFT
7948 static void
7949 _loadLeftIntoAx(char    **lsb, 
7950                 operand *left, 
7951                 operand *result,
7952                 int     offl,
7953                 int     offr)
7954 {
7955   // Get the initial value from left into a pair of registers.
7956   // MSB must be in A, LSB can be any register.
7957   //
7958   // If the result is held in registers, it is an optimization
7959   // if the LSB can be held in the register which will hold the,
7960   // result LSB since this saves us from having to copy it into
7961   // the result following AccAXLsh.
7962   //
7963   // If the result is addressed indirectly, this is not a gain.
7964   if (AOP_NEEDSACC(result))
7965   {
7966        char *leftByte;
7967        
7968        _startLazyDPSEvaluation();
7969       if (AOP_TYPE(left) == AOP_DPTR2)
7970        {
7971            // Get MSB in A.
7972            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7973            // get LSB in DP2_RESULT_REG.
7974            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7975            assert(!strcmp(leftByte, DP2_RESULT_REG));
7976        }
7977        else
7978        {
7979            // get LSB into DP2_RESULT_REG
7980            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7981            if (strcmp(leftByte, DP2_RESULT_REG))
7982            {
7983                TR_AP("#7");
7984                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7985            }
7986            // And MSB in A.
7987            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7988            assert(strcmp(leftByte, DP2_RESULT_REG));
7989            MOVA(leftByte);
7990        }
7991        _endLazyDPSEvaluation();
7992        *lsb = DP2_RESULT_REG;
7993   }
7994   else
7995   {
7996       if (sameRegs (AOP (result), AOP (left)) &&
7997         ((offl + MSB16) == offr))
7998       {
7999           /* don't crash result[offr] */
8000           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8001           emitcode ("xch", "a,%s", 
8002                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8003       }
8004       else
8005       {
8006           movLeft2Result (left, offl, result, offr, 0);
8007           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8008       }
8009       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8010       assert(strcmp(*lsb,"a"));      
8011   }
8012 }
8013
8014 static void
8015 _storeAxResults(char    *lsb,
8016                 operand *result,
8017                 int     offr)
8018 {
8019   _startLazyDPSEvaluation();
8020   if (AOP_NEEDSACC(result))
8021   {
8022       /* We have to explicitly update the result LSB.
8023        */
8024       emitcode("xch","a,%s", lsb);
8025       aopPut(AOP(result), "a", offr);
8026       emitcode("mov","a,%s", lsb);
8027   }
8028   if (getDataSize (result) > 1)
8029   {
8030       aopPut (AOP (result), "a", offr + MSB16);
8031   }
8032   _endLazyDPSEvaluation();
8033 }
8034
8035 /*-----------------------------------------------------------------*/
8036 /* shiftL2Left2Result - shift left two bytes from left to result   */
8037 /*-----------------------------------------------------------------*/
8038 static void
8039 shiftL2Left2Result (operand * left, int offl,
8040                     operand * result, int offr, int shCount)
8041 {
8042   char *lsb;
8043
8044   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8045   
8046   AccAXLsh (lsb, shCount);
8047   
8048   _storeAxResults(lsb, result, offr);
8049 }
8050 #endif
8051
8052 #ifdef BETTER_LITERAL_SHIFT
8053 /*-----------------------------------------------------------------*/
8054 /* shiftR2Left2Result - shift right two bytes from left to result  */
8055 /*-----------------------------------------------------------------*/
8056 static void
8057 shiftR2Left2Result (operand * left, int offl,
8058                     operand * result, int offr,
8059                     int shCount, int sign)
8060 {
8061   char *lsb;
8062   
8063   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8064   
8065   /* a:x >> shCount (x = lsb(result)) */
8066   if (sign)
8067   {
8068      AccAXRshS(lsb, shCount);
8069   }
8070   else
8071   {
8072     AccAXRsh(lsb, shCount);
8073   }
8074   
8075   _storeAxResults(lsb, result, offr);
8076 }
8077 #endif
8078
8079 /*-----------------------------------------------------------------*/
8080 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8081 /*-----------------------------------------------------------------*/
8082 static void
8083 shiftLLeftOrResult (operand * left, int offl,
8084                     operand * result, int offr, int shCount)
8085 {
8086   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8087   /* shift left accumulator */
8088   AccLsh (shCount);
8089   /* or with result */
8090   emitcode ("orl", "a,%s",
8091             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8092   /* back to result */
8093   aopPut (AOP (result), "a", offr);
8094 }
8095
8096 #if 0
8097 //REMOVE ME!!!
8098 /*-----------------------------------------------------------------*/
8099 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8100 /*-----------------------------------------------------------------*/
8101 static void
8102 shiftRLeftOrResult (operand * left, int offl,
8103                     operand * result, int offr, int shCount)
8104 {
8105   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8106   /* shift right accumulator */
8107   AccRsh (shCount);
8108   /* or with result */
8109   emitcode ("orl", "a,%s",
8110             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8111   /* back to result */
8112   aopPut (AOP (result), "a", offr);
8113 }
8114 #endif
8115
8116 #ifdef BETTER_LITERAL_SHIFT
8117 /*-----------------------------------------------------------------*/
8118 /* genlshOne - left shift a one byte quantity by known count       */
8119 /*-----------------------------------------------------------------*/
8120 static void
8121 genlshOne (operand * result, operand * left, int shCount)
8122 {
8123   D (emitcode (";", "genlshOne "););
8124   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8125 }
8126 #endif
8127
8128 #ifdef BETTER_LITERAL_SHIFT
8129 /*-----------------------------------------------------------------*/
8130 /* genlshTwo - left shift two bytes by known amount != 0           */
8131 /*-----------------------------------------------------------------*/
8132 static void
8133 genlshTwo (operand * result, operand * left, int shCount)
8134 {
8135   int size;
8136
8137   D (emitcode (";", "genlshTwo "););
8138
8139   size = getDataSize (result);
8140
8141   /* if shCount >= 8 */
8142   if (shCount >= 8)
8143   {
8144       shCount -= 8;
8145
8146       _startLazyDPSEvaluation();
8147
8148       if (size > 1)
8149         {
8150           if (shCount)
8151           {
8152             _endLazyDPSEvaluation();
8153             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8154             aopPut (AOP (result), zero, LSB);       
8155           }
8156           else
8157           {
8158             movLeft2Result (left, LSB, result, MSB16, 0);
8159             aopPut (AOP (result), zero, LSB);
8160             _endLazyDPSEvaluation();
8161           }
8162         }
8163         else
8164         {
8165           aopPut (AOP (result), zero, LSB);
8166           _endLazyDPSEvaluation();
8167         }
8168   }
8169
8170   /*  1 <= shCount <= 7 */
8171   else
8172     {
8173       if (size == 1)
8174       {
8175         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8176       }
8177       else
8178       {
8179         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8180       }
8181     }
8182 }
8183 #endif
8184
8185 #if 0
8186 //REMOVE ME!!!
8187 /*-----------------------------------------------------------------*/
8188 /* shiftLLong - shift left one long from left to result            */
8189 /* offl = LSB or MSB16                                             */
8190 /*-----------------------------------------------------------------*/
8191 static void
8192 shiftLLong (operand * left, operand * result, int offr)
8193 {
8194   char *l;
8195   int size = AOP_SIZE (result);
8196
8197   if (size >= LSB + offr)
8198     {
8199       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8200       MOVA (l);
8201       emitcode ("add", "a,acc");
8202       if (sameRegs (AOP (left), AOP (result)) &&
8203           size >= MSB16 + offr && offr != LSB)
8204         emitcode ("xch", "a,%s",
8205                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8206       else
8207         aopPut (AOP (result), "a", LSB + offr);
8208     }
8209
8210   if (size >= MSB16 + offr)
8211     {
8212       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8213         {
8214           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8215         }
8216       emitcode ("rlc", "a");
8217       if (sameRegs (AOP (left), AOP (result)) &&
8218           size >= MSB24 + offr && offr != LSB)
8219         emitcode ("xch", "a,%s",
8220                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8221       else
8222         aopPut (AOP (result), "a", MSB16 + offr);
8223     }
8224
8225   if (size >= MSB24 + offr)
8226     {
8227       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8228         {
8229           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8230         }
8231       emitcode ("rlc", "a");
8232       if (sameRegs (AOP (left), AOP (result)) &&
8233           size >= MSB32 + offr && offr != LSB)
8234         emitcode ("xch", "a,%s",
8235                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8236       else
8237         aopPut (AOP (result), "a", MSB24 + offr);
8238     }
8239
8240   if (size > MSB32 + offr)
8241     {
8242       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8243         {
8244           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8245         }
8246       emitcode ("rlc", "a");
8247       aopPut (AOP (result), "a", MSB32 + offr);
8248     }
8249   if (offr != LSB)
8250     aopPut (AOP (result), zero, LSB);
8251 }
8252 #endif
8253
8254 #if 0
8255 //REMOVE ME!!!
8256 /*-----------------------------------------------------------------*/
8257 /* genlshFour - shift four byte by a known amount != 0             */
8258 /*-----------------------------------------------------------------*/
8259 static void
8260 genlshFour (operand * result, operand * left, int shCount)
8261 {
8262   int size;
8263
8264   D (emitcode (";", "genlshFour ");
8265     );
8266
8267   size = AOP_SIZE (result);
8268
8269   /* if shifting more that 3 bytes */
8270   if (shCount >= 24)
8271     {
8272       shCount -= 24;
8273       if (shCount)
8274         /* lowest order of left goes to the highest
8275            order of the destination */
8276         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8277       else
8278         movLeft2Result (left, LSB, result, MSB32, 0);
8279       aopPut (AOP (result), zero, LSB);
8280       aopPut (AOP (result), zero, MSB16);
8281       aopPut (AOP (result), zero, MSB24);
8282       return;
8283     }
8284
8285   /* more than two bytes */
8286   else if (shCount >= 16)
8287     {
8288       /* lower order two bytes goes to higher order two bytes */
8289       shCount -= 16;
8290       /* if some more remaining */
8291       if (shCount)
8292         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8293       else
8294         {
8295           movLeft2Result (left, MSB16, result, MSB32, 0);
8296           movLeft2Result (left, LSB, result, MSB24, 0);
8297         }
8298       aopPut (AOP (result), zero, MSB16);
8299       aopPut (AOP (result), zero, LSB);
8300       return;
8301     }
8302
8303   /* if more than 1 byte */
8304   else if (shCount >= 8)
8305     {
8306       /* lower order three bytes goes to higher order  three bytes */
8307       shCount -= 8;
8308       if (size == 2)
8309         {
8310           if (shCount)
8311             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8312           else
8313             movLeft2Result (left, LSB, result, MSB16, 0);
8314         }
8315       else
8316         {                       /* size = 4 */
8317           if (shCount == 0)
8318             {
8319               movLeft2Result (left, MSB24, result, MSB32, 0);
8320               movLeft2Result (left, MSB16, result, MSB24, 0);
8321               movLeft2Result (left, LSB, result, MSB16, 0);
8322               aopPut (AOP (result), zero, LSB);
8323             }
8324           else if (shCount == 1)
8325             shiftLLong (left, result, MSB16);
8326           else
8327             {
8328               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8329               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8330               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8331               aopPut (AOP (result), zero, LSB);
8332             }
8333         }
8334     }
8335
8336   /* 1 <= shCount <= 7 */
8337   else if (shCount <= 2)
8338     {
8339       shiftLLong (left, result, LSB);
8340       if (shCount == 2)
8341         shiftLLong (result, result, LSB);
8342     }
8343   /* 3 <= shCount <= 7, optimize */
8344   else
8345     {
8346       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8347       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8348       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8349     }
8350 }
8351 #endif
8352
8353 #ifdef BETTER_LITERAL_SHIFT
8354 /*-----------------------------------------------------------------*/
8355 /* genLeftShiftLiteral - left shifting by known count              */
8356 /*-----------------------------------------------------------------*/
8357 static bool
8358 genLeftShiftLiteral (operand * left,
8359                      operand * right,
8360                      operand * result,
8361                      iCode * ic)
8362 {
8363   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8364   int size;
8365
8366   size = getSize (operandType (result));
8367
8368   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8369
8370   /* We only handle certain easy cases so far. */
8371   if ((shCount != 0)
8372    && (shCount < (size * 8))
8373    && (size != 1)
8374    && (size != 2))
8375   {
8376       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8377       return FALSE;
8378   }
8379
8380   freeAsmop (right, NULL, ic, TRUE);
8381
8382   aopOp(left, ic, FALSE, FALSE);
8383   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8384
8385 #if 0 // debug spew
8386   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8387   {
8388         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8389         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8390         {
8391            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8392         }
8393   }
8394   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8395   {
8396         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8397         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8398         {
8399            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8400         }       
8401   }  
8402 #endif
8403   
8404 #if VIEW_SIZE
8405   emitcode ("; shift left ", "result %d, left %d", size,
8406             AOP_SIZE (left));
8407 #endif
8408
8409   /* I suppose that the left size >= result size */
8410   if (shCount == 0)
8411   {
8412         _startLazyDPSEvaluation();
8413         while (size--)
8414         {
8415           movLeft2Result (left, size, result, size, 0);
8416         }
8417         _endLazyDPSEvaluation();
8418   }
8419   else if (shCount >= (size * 8))
8420   {
8421     _startLazyDPSEvaluation();
8422     while (size--)
8423     {
8424       aopPut (AOP (result), zero, size);
8425     }
8426     _endLazyDPSEvaluation();
8427   }
8428   else
8429   {
8430       switch (size)
8431         {
8432         case 1:
8433           genlshOne (result, left, shCount);
8434           break;
8435
8436         case 2:
8437           genlshTwo (result, left, shCount);
8438           break;
8439 #if 0
8440         case 4:
8441           genlshFour (result, left, shCount);
8442           break;
8443 #endif
8444         default:
8445           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8446           break;
8447         }
8448     }
8449   freeAsmop (left, NULL, ic, TRUE);
8450   freeAsmop (result, NULL, ic, TRUE);
8451   return TRUE;
8452 }
8453 #endif
8454
8455 /*-----------------------------------------------------------------*/
8456 /* genLeftShift - generates code for left shifting                 */
8457 /*-----------------------------------------------------------------*/
8458 static void
8459 genLeftShift (iCode * ic)
8460 {
8461   operand *left, *right, *result;
8462   int size, offset;
8463   char *l;
8464   symbol *tlbl, *tlbl1;
8465
8466   D (emitcode (";", "genLeftShift "););
8467
8468   right = IC_RIGHT (ic);
8469   left = IC_LEFT (ic);
8470   result = IC_RESULT (ic);
8471
8472   aopOp (right, ic, FALSE, FALSE);
8473
8474
8475 #ifdef BETTER_LITERAL_SHIFT
8476   /* if the shift count is known then do it
8477      as efficiently as possible */
8478   if (AOP_TYPE (right) == AOP_LIT)
8479     {
8480       if (genLeftShiftLiteral (left, right, result, ic))
8481       {
8482         return;
8483       }
8484     }
8485 #endif
8486
8487   /* shift count is unknown then we have to form
8488      a loop get the loop count in B : Note: we take
8489      only the lower order byte since shifting
8490      more that 32 bits make no sense anyway, ( the
8491      largest size of an object can be only 32 bits ) */
8492
8493   if (AOP_TYPE (right) == AOP_LIT)
8494   {
8495       /* Really should be handled by genLeftShiftLiteral,
8496        * but since I'm too lazy to fix that today, at least we can make
8497        * some small improvement.
8498        */
8499        emitcode("mov", "b,#!constbyte",
8500                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8501   }
8502   else
8503   {
8504       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8505       emitcode ("inc", "b");
8506   }
8507   freeAsmop (right, NULL, ic, TRUE);
8508   aopOp (left, ic, FALSE, FALSE);
8509   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8510
8511   /* now move the left to the result if they are not the
8512      same */
8513   if (!sameRegs (AOP (left), AOP (result)) &&
8514       AOP_SIZE (result) > 1)
8515     {
8516
8517       size = AOP_SIZE (result);
8518       offset = 0;
8519       _startLazyDPSEvaluation ();
8520       while (size--)
8521         {
8522           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8523           if (*l == '@' && (IS_AOP_PREG (result)))
8524             {
8525
8526               emitcode ("mov", "a,%s", l);
8527               aopPut (AOP (result), "a", offset);
8528             }
8529           else
8530             aopPut (AOP (result), l, offset);
8531           offset++;
8532         }
8533       _endLazyDPSEvaluation ();
8534     }
8535
8536   tlbl = newiTempLabel (NULL);
8537   size = AOP_SIZE (result);
8538   offset = 0;
8539   tlbl1 = newiTempLabel (NULL);
8540
8541   /* if it is only one byte then */
8542   if (size == 1)
8543     {
8544       symbol *tlbl1 = newiTempLabel (NULL);
8545
8546       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8547       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8548       emitcode ("", "!tlabeldef", tlbl->key + 100);
8549       emitcode ("add", "a,acc");
8550       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8551       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8552       aopPut (AOP (result), "a", 0);
8553       goto release;
8554     }
8555
8556   reAdjustPreg (AOP (result));
8557
8558   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8559   emitcode ("", "!tlabeldef", tlbl->key + 100);
8560   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8561   emitcode ("add", "a,acc");
8562   aopPut (AOP (result), "a", offset++);
8563   _startLazyDPSEvaluation ();
8564   while (--size)
8565     {
8566       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8567       emitcode ("rlc", "a");
8568       aopPut (AOP (result), "a", offset++);
8569     }
8570   _endLazyDPSEvaluation ();
8571   reAdjustPreg (AOP (result));
8572
8573   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8574   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8575 release:
8576   freeAsmop (left, NULL, ic, TRUE);
8577   freeAsmop (result, NULL, ic, TRUE);
8578 }
8579
8580 #ifdef BETTER_LITERAL_SHIFT
8581 /*-----------------------------------------------------------------*/
8582 /* genrshOne - right shift a one byte quantity by known count      */
8583 /*-----------------------------------------------------------------*/
8584 static void
8585 genrshOne (operand * result, operand * left,
8586            int shCount, int sign)
8587 {
8588   D (emitcode (";", "genrshOne"););
8589   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8590 }
8591 #endif
8592
8593 #ifdef BETTER_LITERAL_SHIFT
8594 /*-----------------------------------------------------------------*/
8595 /* genrshTwo - right shift two bytes by known amount != 0          */
8596 /*-----------------------------------------------------------------*/
8597 static void
8598 genrshTwo (operand * result, operand * left,
8599            int shCount, int sign)
8600 {
8601   D (emitcode (";", "genrshTwo"););
8602
8603   /* if shCount >= 8 */
8604   if (shCount >= 8)
8605     {
8606       shCount -= 8;
8607       _startLazyDPSEvaluation();
8608       if (shCount)
8609       {
8610         shiftR1Left2Result (left, MSB16, result, LSB,
8611                             shCount, sign);
8612       }                     
8613       else
8614       {
8615         movLeft2Result (left, MSB16, result, LSB, sign);
8616       }
8617       addSign (result, MSB16, sign);
8618       _endLazyDPSEvaluation();
8619     }
8620
8621   /*  1 <= shCount <= 7 */
8622   else
8623   {
8624     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8625   }
8626 }
8627 #endif
8628
8629 /*-----------------------------------------------------------------*/
8630 /* shiftRLong - shift right one long from left to result           */
8631 /* offl = LSB or MSB16                                             */
8632 /*-----------------------------------------------------------------*/
8633 static void
8634 shiftRLong (operand * left, int offl,
8635             operand * result, int sign)
8636 {
8637   int isSameRegs=sameRegs(AOP(left),AOP(result));
8638
8639   if (isSameRegs && offl>1) {
8640     // we are in big trouble, but this shouldn't happen
8641     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8642   }
8643
8644   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8645   
8646   if (offl==MSB16) {
8647     // shift is > 8
8648     if (sign) {
8649       emitcode ("rlc", "a");
8650       emitcode ("subb", "a,acc");
8651       emitcode ("xch", "a,%s",
8652                 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8653     } else {
8654       aopPut (AOP(result), zero, MSB32);
8655     }
8656   }
8657
8658   if (!sign) {
8659     emitcode ("clr", "c");
8660   } else {
8661     emitcode ("mov", "c,acc.7");
8662   }
8663
8664   emitcode ("rrc", "a");
8665
8666   if (isSameRegs && offl==MSB16) {
8667     emitcode ("xch",
8668               "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8669   } else {
8670     aopPut (AOP (result), "a", MSB32);
8671     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8672   }
8673
8674   emitcode ("rrc", "a");
8675   if (isSameRegs && offl==1) {
8676     emitcode ("xch", "a,%s",
8677               aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8678   } else {
8679     aopPut (AOP (result), "a", MSB24);
8680     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8681   }
8682   emitcode ("rrc", "a");
8683   aopPut (AOP (result), "a", MSB16 - offl);
8684
8685   if (offl == LSB)
8686     {
8687       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8688       emitcode ("rrc", "a");
8689       aopPut (AOP (result), "a", LSB);
8690     }
8691 }
8692
8693 /*-----------------------------------------------------------------*/
8694 /* genrshFour - shift four byte by a known amount != 0             */
8695 /*-----------------------------------------------------------------*/
8696 static void
8697 genrshFour (operand * result, operand * left,
8698             int shCount, int sign)
8699 {
8700   D (emitcode (";", "genrshFour"););
8701
8702   /* if shifting more that 3 bytes */
8703   if (shCount >= 24)
8704     {
8705       shCount -= 24;
8706       _startLazyDPSEvaluation();
8707       if (shCount)
8708         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8709       else
8710         movLeft2Result (left, MSB32, result, LSB, sign);
8711       addSign (result, MSB16, sign);
8712       _endLazyDPSEvaluation();
8713     }
8714   else if (shCount >= 16)
8715     {
8716       shCount -= 16;
8717       _startLazyDPSEvaluation();
8718       if (shCount)
8719         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8720       else
8721         {
8722           movLeft2Result (left, MSB24, result, LSB, 0);
8723           movLeft2Result (left, MSB32, result, MSB16, sign);
8724         }
8725       addSign (result, MSB24, sign);
8726       _endLazyDPSEvaluation();
8727     }
8728   else if (shCount >= 8)
8729     {
8730       shCount -= 8;
8731       _startLazyDPSEvaluation();
8732       if (shCount == 1)
8733         {
8734             shiftRLong (left, MSB16, result, sign);
8735         }
8736       else if (shCount == 0)
8737         {
8738           movLeft2Result (left, MSB16, result, LSB, 0);
8739           movLeft2Result (left, MSB24, result, MSB16, 0);
8740           movLeft2Result (left, MSB32, result, MSB24, sign);
8741           addSign (result, MSB32, sign);
8742         }
8743       else
8744         {
8745           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8746           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8747           /* the last shift is signed */
8748           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8749           addSign (result, MSB32, sign);
8750         }
8751         _endLazyDPSEvaluation();
8752     }
8753   else
8754     {   
8755         /* 1 <= shCount <= 7 */
8756       if (shCount <= 2)
8757         {
8758           shiftRLong (left, LSB, result, sign);
8759           if (shCount == 2)
8760             shiftRLong (result, LSB, result, sign);
8761         }
8762       else
8763         {
8764           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8765           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8766           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8767         }
8768     }
8769 }
8770
8771 #ifdef BETTER_LITERAL_SHIFT
8772 /*-----------------------------------------------------------------*/
8773 /* genRightShiftLiteral - right shifting by known count            */
8774 /*-----------------------------------------------------------------*/
8775 static bool
8776 genRightShiftLiteral (operand * left,
8777                       operand * right,
8778                       operand * result,
8779                       iCode * ic,
8780                       int sign)
8781 {
8782   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8783   int size;
8784
8785   size = getSize (operandType (result));
8786
8787   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8788
8789   /* We only handle certain easy cases so far. */
8790   if ((shCount != 0)
8791    && (shCount < (size * 8))
8792    && (size != 1)
8793    && (size != 2)
8794    && (size != 4))
8795   {
8796       D(emitcode (";", "genRightShiftLiteral wimping out"););
8797       return FALSE;
8798   }
8799
8800   freeAsmop (right, NULL, ic, TRUE);
8801
8802   aopOp (left, ic, FALSE, FALSE);
8803   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8804
8805 #if VIEW_SIZE
8806   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8807             AOP_SIZE (left));
8808 #endif
8809
8810   /* test the LEFT size !!! */
8811
8812   /* I suppose that the left size >= result size */
8813   if (shCount == 0)
8814   {
8815       size = getDataSize (result);
8816       _startLazyDPSEvaluation();
8817       while (size--)
8818       {
8819         movLeft2Result (left, size, result, size, 0);
8820       }
8821       _endLazyDPSEvaluation();
8822   }
8823   else if (shCount >= (size * 8))
8824     {
8825       if (sign)
8826       {
8827         /* get sign in acc.7 */
8828         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8829       }
8830       addSign (result, LSB, sign);
8831     }
8832   else
8833     {
8834       switch (size)
8835         {
8836         case 1:
8837           genrshOne (result, left, shCount, sign);
8838           break;
8839
8840         case 2:
8841           genrshTwo (result, left, shCount, sign);
8842           break;
8843 #if 1
8844         case 4:
8845           genrshFour (result, left, shCount, sign);
8846           break;
8847 #endif    
8848         default:
8849           break;
8850         }
8851     }
8852   freeAsmop (left, NULL, ic, TRUE);
8853   freeAsmop (result, NULL, ic, TRUE);
8854   
8855   return TRUE;
8856 }
8857 #endif
8858
8859 /*-----------------------------------------------------------------*/
8860 /* genSignedRightShift - right shift of signed number              */
8861 /*-----------------------------------------------------------------*/
8862 static void
8863 genSignedRightShift (iCode * ic)
8864 {
8865   operand *right, *left, *result;
8866   int size, offset;
8867   char *l;
8868   symbol *tlbl, *tlbl1;
8869
8870   D (emitcode (";", "genSignedRightShift "););
8871
8872   /* we do it the hard way put the shift count in b
8873      and loop thru preserving the sign */
8874
8875   right = IC_RIGHT (ic);
8876   left = IC_LEFT (ic);
8877   result = IC_RESULT (ic);
8878
8879   aopOp (right, ic, FALSE, FALSE);
8880
8881 #ifdef BETTER_LITERAL_SHIFT
8882   if (AOP_TYPE (right) == AOP_LIT)
8883     {
8884       if (genRightShiftLiteral (left, right, result, ic, 1))
8885       {
8886         return;
8887       }
8888     }
8889 #endif
8890   /* shift count is unknown then we have to form
8891      a loop get the loop count in B : Note: we take
8892      only the lower order byte since shifting
8893      more that 32 bits make no sense anyway, ( the
8894      largest size of an object can be only 32 bits ) */
8895
8896   if (AOP_TYPE (right) == AOP_LIT)
8897   {
8898       /* Really should be handled by genRightShiftLiteral,
8899        * but since I'm too lazy to fix that today, at least we can make
8900        * some small improvement.
8901        */
8902        emitcode("mov", "b,#!constbyte",
8903                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8904   }
8905   else
8906   {
8907         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8908         emitcode ("inc", "b");
8909   }
8910   freeAsmop (right, NULL, ic, TRUE);
8911   aopOp (left, ic, FALSE, FALSE);
8912   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
8913
8914   /* now move the left to the result if they are not the
8915      same */
8916   if (!sameRegs (AOP (left), AOP (result)) &&
8917       AOP_SIZE (result) > 1)
8918     {
8919
8920       size = AOP_SIZE (result);
8921       offset = 0;
8922       _startLazyDPSEvaluation ();
8923       while (size--)
8924         {
8925           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8926           if (*l == '@' && IS_AOP_PREG (result))
8927             {
8928
8929               emitcode ("mov", "a,%s", l);
8930               aopPut (AOP (result), "a", offset);
8931             }
8932           else
8933             aopPut (AOP (result), l, offset);
8934           offset++;
8935         }
8936       _endLazyDPSEvaluation ();
8937     }
8938
8939   /* mov the highest order bit to OVR */
8940   tlbl = newiTempLabel (NULL);
8941   tlbl1 = newiTempLabel (NULL);
8942
8943   size = AOP_SIZE (result);
8944   offset = size - 1;
8945   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8946   emitcode ("rlc", "a");
8947   emitcode ("mov", "ov,c");
8948   /* if it is only one byte then */
8949   if (size == 1)
8950     {
8951       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8952       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8953       emitcode ("", "!tlabeldef", tlbl->key + 100);
8954       emitcode ("mov", "c,ov");
8955       emitcode ("rrc", "a");
8956       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8957       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8958       aopPut (AOP (result), "a", 0);
8959       goto release;
8960     }
8961
8962   reAdjustPreg (AOP (result));
8963   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8964   emitcode ("", "!tlabeldef", tlbl->key + 100);
8965   emitcode ("mov", "c,ov");
8966   _startLazyDPSEvaluation ();
8967   while (size--)
8968     {
8969       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8970       emitcode ("rrc", "a");
8971       aopPut (AOP (result), "a", offset--);
8972     }
8973   _endLazyDPSEvaluation ();
8974   reAdjustPreg (AOP (result));
8975   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8976   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8977
8978 release:
8979   freeAsmop (left, NULL, ic, TRUE);
8980   freeAsmop (result, NULL, ic, TRUE);
8981 }
8982
8983 /*-----------------------------------------------------------------*/
8984 /* genRightShift - generate code for right shifting                */
8985 /*-----------------------------------------------------------------*/
8986 static void
8987 genRightShift (iCode * ic)
8988 {
8989   operand *right, *left, *result;
8990   sym_link *letype;
8991   int size, offset;
8992   char *l;
8993   symbol *tlbl, *tlbl1;
8994
8995   D (emitcode (";", "genRightShift "););
8996
8997   /* if signed then we do it the hard way preserve the
8998      sign bit moving it inwards */
8999   letype = getSpec (operandType (IC_LEFT (ic)));
9000
9001   if (!SPEC_USIGN (letype))
9002     {
9003       genSignedRightShift (ic);
9004       return;
9005     }
9006
9007   /* signed & unsigned types are treated the same : i.e. the
9008      signed is NOT propagated inwards : quoting from the
9009      ANSI - standard : "for E1 >> E2, is equivalent to division
9010      by 2**E2 if unsigned or if it has a non-negative value,
9011      otherwise the result is implementation defined ", MY definition
9012      is that the sign does not get propagated */
9013
9014   right = IC_RIGHT (ic);
9015   left = IC_LEFT (ic);
9016   result = IC_RESULT (ic);
9017
9018   aopOp (right, ic, FALSE, FALSE);
9019
9020 #ifdef BETTER_LITERAL_SHIFT
9021   /* if the shift count is known then do it
9022      as efficiently as possible */
9023   if (AOP_TYPE (right) == AOP_LIT)
9024     {
9025       if (genRightShiftLiteral (left, right, result, ic, 0))
9026       {
9027         return;
9028       }
9029     }
9030 #endif
9031
9032   /* shift count is unknown then we have to form
9033      a loop get the loop count in B : Note: we take
9034      only the lower order byte since shifting
9035      more that 32 bits make no sense anyway, ( the
9036      largest size of an object can be only 32 bits ) */
9037   
9038   if (AOP_TYPE (right) == AOP_LIT)
9039   {
9040       /* Really should be handled by genRightShiftLiteral,
9041        * but since I'm too lazy to fix that today, at least we can make
9042        * some small improvement.
9043        */
9044        emitcode("mov", "b,#!constbyte",
9045                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9046   }
9047   else
9048   {
9049       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9050       emitcode ("inc", "b");
9051   }
9052   freeAsmop (right, NULL, ic, TRUE);
9053   aopOp (left, ic, FALSE, FALSE);
9054   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9055
9056   /* now move the left to the result if they are not the
9057      same */
9058   if (!sameRegs (AOP (left), AOP (result)) &&
9059       AOP_SIZE (result) > 1)
9060     {
9061
9062       size = AOP_SIZE (result);
9063       offset = 0;
9064       _startLazyDPSEvaluation ();
9065       while (size--)
9066         {
9067           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9068           if (*l == '@' && IS_AOP_PREG (result))
9069             {
9070
9071               emitcode ("mov", "a,%s", l);
9072               aopPut (AOP (result), "a", offset);
9073             }
9074           else
9075             aopPut (AOP (result), l, offset);
9076           offset++;
9077         }
9078       _endLazyDPSEvaluation ();
9079     }
9080
9081   tlbl = newiTempLabel (NULL);
9082   tlbl1 = newiTempLabel (NULL);
9083   size = AOP_SIZE (result);
9084   offset = size - 1;
9085
9086   /* if it is only one byte then */
9087   if (size == 1)
9088     {
9089       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9090       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9091       emitcode ("", "!tlabeldef", tlbl->key + 100);
9092       CLRC;
9093       emitcode ("rrc", "a");
9094       emitcode ("", "!tlabeldef", tlbl1->key + 100);
9095       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9096       aopPut (AOP (result), "a", 0);
9097       goto release;
9098     }
9099
9100   reAdjustPreg (AOP (result));
9101   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9102   emitcode ("", "!tlabeldef", tlbl->key + 100);
9103   CLRC;
9104   _startLazyDPSEvaluation ();
9105   while (size--)
9106     {
9107       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9108       emitcode ("rrc", "a");
9109       aopPut (AOP (result), "a", offset--);
9110     }
9111   _endLazyDPSEvaluation ();
9112   reAdjustPreg (AOP (result));
9113
9114   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9115   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9116
9117 release:
9118   freeAsmop (left, NULL, ic, TRUE);
9119   freeAsmop (result, NULL, ic, TRUE);
9120 }
9121
9122
9123 /*-----------------------------------------------------------------*/
9124 /* emitPtrByteGet - emits code to get a byte into A through a      */
9125 /*                  pointer register (R0, R1, or DPTR). The        */
9126 /*                  original value of A can be preserved in B.     */
9127 /*-----------------------------------------------------------------*/
9128 static void
9129 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9130 {
9131   switch (p_type)
9132     {
9133     case IPOINTER:
9134     case POINTER:
9135       if (preserveAinB)
9136         emitcode ("mov", "b,a");
9137       emitcode ("mov", "a,@%s", rname);
9138       break;
9139
9140     case PPOINTER:
9141       if (preserveAinB)
9142         emitcode ("mov", "b,a");
9143       emitcode ("movx", "a,@%s", rname);
9144       break;
9145       
9146     case FPOINTER:
9147       if (preserveAinB)
9148         emitcode ("mov", "b,a");
9149       emitcode ("movx", "a,@dptr");
9150       break;
9151
9152     case CPOINTER:
9153       if (preserveAinB)
9154         emitcode ("mov", "b,a");
9155       emitcode ("clr", "a");
9156       emitcode ("movc", "a,@a+dptr");
9157       break;
9158
9159     case GPOINTER:
9160       if (preserveAinB)
9161         {
9162           emitcode ("push", "b");
9163           emitcode ("push", "acc");
9164         }
9165       emitcode ("lcall", "__gptrget");
9166       if (preserveAinB)
9167         emitcode ("pop", "b");
9168       break;
9169     }
9170 }
9171
9172 /*-----------------------------------------------------------------*/
9173 /* emitPtrByteSet - emits code to set a byte from src through a    */
9174 /*                  pointer register (R0, R1, or DPTR).            */
9175 /*-----------------------------------------------------------------*/
9176 static void
9177 emitPtrByteSet (char *rname, int p_type, char *src)
9178 {
9179   switch (p_type)
9180     {
9181     case IPOINTER:
9182     case POINTER:
9183       if (*src=='@')
9184         {
9185           MOVA (src);
9186           emitcode ("mov", "@%s,a", rname);
9187         }
9188       else
9189         emitcode ("mov", "@%s,%s", rname, src);
9190       break;
9191
9192     case PPOINTER:
9193       MOVA (src);
9194       emitcode ("movx", "@%s,a", rname);
9195       break;
9196       
9197     case FPOINTER:
9198       MOVA (src);
9199       emitcode ("movx", "@dptr,a");
9200       break;
9201
9202     case GPOINTER:
9203       MOVA (src);
9204       emitcode ("lcall", "__gptrput");
9205       break;
9206     }
9207 }
9208
9209 /*-----------------------------------------------------------------*/
9210 /* genUnpackBits - generates code for unpacking bits               */
9211 /*-----------------------------------------------------------------*/
9212 static void
9213 genUnpackBits (operand * result, char *rname, int ptype)
9214 {
9215   int offset = 0;       /* result byte offset */
9216   int rsize;            /* result size */
9217   int rlen = 0;         /* remaining bitfield length */
9218   sym_link *etype;      /* bitfield type information */
9219   int blen;             /* bitfield length */
9220   int bstr;             /* bitfield starting bit within byte */
9221
9222   D(emitcode (";     genUnpackBits",""));
9223
9224   etype = getSpec (operandType (result));
9225   rsize = getSize (operandType (result));
9226   blen = SPEC_BLEN (etype);
9227   bstr = SPEC_BSTR (etype);
9228
9229   /* If the bitfield length is less than a byte */
9230   if (blen < 8)
9231     {
9232       emitPtrByteGet (rname, ptype, FALSE);
9233       AccRsh (bstr);
9234       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9235       aopPut (AOP (result), "a", offset++);
9236       goto finish;
9237     }
9238
9239   /* Bit field did not fit in a byte. Copy all
9240      but the partial byte at the end.  */
9241   for (rlen=blen;rlen>=8;rlen-=8)
9242     {
9243       emitPtrByteGet (rname, ptype, FALSE);
9244       aopPut (AOP (result), "a", offset++);
9245       if (rlen>8)
9246         emitcode ("inc", "%s", rname);
9247     }
9248
9249   /* Handle the partial byte at the end */
9250   if (rlen)
9251     {
9252       emitPtrByteGet (rname, ptype, FALSE);
9253       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9254       aopPut (AOP (result), "a", offset++);
9255     }
9256
9257 finish:
9258   if (offset < rsize)
9259     {
9260       rsize -= offset;
9261       while (rsize--)
9262         aopPut (AOP (result), zero, offset++);
9263     }
9264 }
9265
9266
9267 /*-----------------------------------------------------------------*/
9268 /* genDataPointerGet - generates code when ptr offset is known     */
9269 /*-----------------------------------------------------------------*/
9270 static void
9271 genDataPointerGet (operand * left,
9272                    operand * result,
9273                    iCode * ic)
9274 {
9275   char *l;
9276   char buff[256];
9277   int size, offset = 0;
9278   aopOp (result, ic, TRUE, FALSE);
9279
9280   /* get the string representation of the name */
9281   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9282   size = AOP_SIZE (result);
9283   _startLazyDPSEvaluation ();
9284   while (size--)
9285     {
9286         if (offset)
9287         {
9288             SNPRINTF (buff, sizeof(buff), 
9289                       "(%s + %d)", l + 1, offset);
9290         }
9291         else
9292         {
9293             SNPRINTF (buff, sizeof(buff), 
9294                       "%s", l + 1);
9295         }
9296       aopPut (AOP (result), buff, offset++);
9297     }
9298   _endLazyDPSEvaluation ();
9299
9300   freeAsmop (left, NULL, ic, TRUE);
9301   freeAsmop (result, NULL, ic, TRUE);
9302 }
9303
9304 /*-----------------------------------------------------------------*/
9305 /* genNearPointerGet - emitcode for near pointer fetch             */
9306 /*-----------------------------------------------------------------*/
9307 static void
9308 genNearPointerGet (operand * left,
9309                    operand * result,
9310                    iCode * ic,
9311                    iCode *pi)
9312 {
9313   asmop *aop = NULL;
9314   regs *preg;
9315   char *rname;
9316   sym_link *rtype, *retype, *letype;
9317   sym_link *ltype = operandType (left);
9318   char buff[80];
9319
9320   rtype = operandType (result);
9321   retype = getSpec (rtype);
9322   letype = getSpec (ltype);
9323
9324   aopOp (left, ic, FALSE, FALSE);
9325
9326   /* if left is rematerialisable and
9327      result is not bit variable type and
9328      the left is pointer to data space i.e
9329      lower 128 bytes of space */
9330   if (AOP_TYPE (left) == AOP_IMMD &&
9331       !IS_BITVAR (retype) &&
9332       !IS_BITVAR (letype) &&
9333       DCL_TYPE (ltype) == POINTER)
9334     {
9335       genDataPointerGet (left, result, ic);
9336       return;
9337     }
9338
9339   /* if the value is already in a pointer register
9340      then don't need anything more */
9341   if (!AOP_INPREG (AOP (left)))
9342     {
9343       /* otherwise get a free pointer register */
9344       aop = newAsmop (0);
9345       preg = getFreePtr (ic, &aop, FALSE);
9346       emitcode ("mov", "%s,%s",
9347                 preg->name,
9348                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9349       rname = preg->name;
9350     }
9351   else
9352     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9353
9354   freeAsmop (left, NULL, ic, TRUE);
9355   aopOp (result, ic, FALSE, FALSE);
9356
9357   /* if bitfield then unpack the bits */
9358   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9359     genUnpackBits (result, rname, POINTER);
9360   else
9361     {
9362       /* we have can just get the values */
9363       int size = AOP_SIZE (result);
9364       int offset = 0;
9365
9366       while (size--)
9367         {
9368           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9369             {
9370
9371               emitcode ("mov", "a,@%s", rname);
9372               aopPut (AOP (result), "a", offset);
9373             }
9374           else
9375             {
9376               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9377               aopPut (AOP (result), buff, offset);
9378             }
9379           offset++;
9380           if (size || pi)
9381             {
9382                 emitcode ("inc", "%s", rname);
9383             }
9384         }
9385     }
9386
9387   /* now some housekeeping stuff */
9388   if (aop)
9389     {
9390       /* we had to allocate for this iCode */
9391       if (pi) { /* post increment present */
9392         aopPut(AOP ( left ),rname,0);
9393       }
9394       freeAsmop (NULL, aop, ic, TRUE);
9395     }
9396   else
9397     {
9398       /* we did not allocate which means left
9399          already in a pointer register, then
9400          if size > 0 && this could be used again
9401          we have to point it back to where it
9402          belongs */
9403       if (AOP_SIZE (result) > 1 &&
9404           !OP_SYMBOL (left)->remat &&
9405           (OP_SYMBOL (left)->liveTo > ic->seq ||
9406            ic->depth) &&
9407           !pi)
9408         {
9409           int size = AOP_SIZE (result) - 1;
9410           while (size--)
9411             emitcode ("dec", "%s", rname);
9412         }
9413     }
9414
9415   /* done */
9416   freeAsmop (result, NULL, ic, TRUE);
9417   if (pi) pi->generated = 1;
9418 }
9419
9420 /*-----------------------------------------------------------------*/
9421 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9422 /*-----------------------------------------------------------------*/
9423 static void
9424 genPagedPointerGet (operand * left,
9425                     operand * result,
9426                     iCode * ic,
9427                     iCode * pi)
9428 {
9429   asmop *aop = NULL;
9430   regs *preg;
9431   char *rname;
9432   sym_link *rtype, *retype, *letype;
9433
9434   rtype = operandType (result);
9435   retype = getSpec (rtype);
9436   letype = getSpec (operandType (left));
9437   aopOp (left, ic, FALSE, FALSE);
9438
9439   /* if the value is already in a pointer register
9440      then don't need anything more */
9441   if (!AOP_INPREG (AOP (left)))
9442     {
9443       /* otherwise get a free pointer register */
9444       aop = newAsmop (0);
9445       preg = getFreePtr (ic, &aop, FALSE);
9446       emitcode ("mov", "%s,%s",
9447                 preg->name,
9448                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9449       rname = preg->name;
9450     }
9451   else
9452     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9453
9454   freeAsmop (left, NULL, ic, TRUE);
9455   aopOp (result, ic, FALSE, FALSE);
9456
9457   /* if bitfield then unpack the bits */
9458   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9459     genUnpackBits (result, rname, PPOINTER);
9460   else
9461     {
9462       /* we have can just get the values */
9463       int size = AOP_SIZE (result);
9464       int offset = 0;
9465
9466       while (size--)
9467         {
9468
9469           emitcode ("movx", "a,@%s", rname);
9470           aopPut (AOP (result), "a", offset);
9471
9472           offset++;
9473
9474           if (size || pi)
9475             emitcode ("inc", "%s", rname);
9476         }
9477     }
9478
9479   /* now some housekeeping stuff */
9480   if (aop)
9481     {
9482       /* we had to allocate for this iCode */
9483       if (pi) aopPut ( AOP (left), rname, 0);
9484       freeAsmop (NULL, aop, ic, TRUE);
9485     }
9486   else
9487     {
9488       /* we did not allocate which means left
9489          already in a pointer register, then
9490          if size > 0 && this could be used again
9491          we have to point it back to where it
9492          belongs */
9493       if (AOP_SIZE (result) > 1 &&
9494           !OP_SYMBOL (left)->remat &&
9495           (OP_SYMBOL (left)->liveTo > ic->seq ||
9496            ic->depth) &&
9497           !pi)
9498         {
9499           int size = AOP_SIZE (result) - 1;
9500           while (size--)
9501             emitcode ("dec", "%s", rname);
9502         }
9503     }
9504
9505   /* done */
9506   freeAsmop (result, NULL, ic, TRUE);
9507   if (pi) pi->generated = 1;
9508 }
9509
9510 /*-----------------------------------------------------------------*/
9511 /* genFarPointerGet - gget value from far space                    */
9512 /*-----------------------------------------------------------------*/
9513 static void
9514 genFarPointerGet (operand * left,
9515                   operand * result, iCode * ic, iCode *pi)
9516 {
9517     int size, offset, dopi=1;
9518   sym_link *retype = getSpec (operandType (result));
9519   sym_link *letype = getSpec (operandType (left));
9520   D (emitcode (";", "genFarPointerGet"););
9521
9522   aopOp (left, ic, FALSE, FALSE);
9523
9524   /* if the operand is already in dptr
9525      then we do nothing else we move the value to dptr */
9526   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9527     {
9528       /* if this is remateriazable */
9529       if (AOP_TYPE (left) == AOP_IMMD)
9530         {
9531           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9532         }
9533       else
9534         {
9535           /* we need to get it byte by byte */
9536           _startLazyDPSEvaluation ();
9537           if (AOP_TYPE (left) != AOP_DPTR)
9538             {
9539               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9540               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9541               if (options.model == MODEL_FLAT24)
9542                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9543             }
9544           else
9545             {
9546               /* We need to generate a load to DPTR indirect through DPTR. */
9547               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9548               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9549               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9550               if (options.model == MODEL_FLAT24)
9551                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9552               emitcode ("pop", "dph");
9553               emitcode ("pop", "dpl");
9554               dopi =0;
9555             }
9556           _endLazyDPSEvaluation ();
9557         }
9558     }
9559   /* so dptr know contains the address */
9560   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9561
9562   /* if bit then unpack */
9563   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9564       if (AOP_INDPTRn(left)) {
9565           genSetDPTR(AOP(left)->aopu.dptr);
9566       }
9567       genUnpackBits (result, "dptr", FPOINTER);
9568       if (AOP_INDPTRn(left)) {
9569           genSetDPTR(0);
9570       }
9571   } else
9572     {
9573       size = AOP_SIZE (result);
9574       offset = 0;
9575
9576       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9577           while (size--) {
9578               genSetDPTR(AOP(left)->aopu.dptr);
9579               emitcode ("movx", "a,@dptr");
9580               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9581                   emitcode ("inc", "dptr");
9582               genSetDPTR (0);
9583               aopPut (AOP (result), "a", offset++);
9584           }
9585       } else {
9586           _startLazyDPSEvaluation ();
9587           while (size--) {
9588               if (AOP_INDPTRn(left)) {
9589                   genSetDPTR(AOP(left)->aopu.dptr);
9590               } else {
9591                   genSetDPTR (0);
9592               }
9593               _flushLazyDPS ();
9594               
9595               emitcode ("movx", "a,@dptr");
9596               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9597                   emitcode ("inc", "dptr");
9598               
9599               aopPut (AOP (result), "a", offset++);
9600           }
9601           _endLazyDPSEvaluation ();
9602       }
9603     }
9604   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9605       if (!AOP_INDPTRn(left)) {
9606           _startLazyDPSEvaluation ();
9607           aopPut ( AOP (left), "dpl", 0);
9608           aopPut ( AOP (left), "dph", 1);
9609           if (options.model == MODEL_FLAT24)
9610               aopPut ( AOP (left), "dpx", 2);
9611           _endLazyDPSEvaluation ();
9612       }
9613     pi->generated = 1;
9614   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) && 
9615              AOP_SIZE(result) > 1 &&
9616              IS_SYMOP(left) &&
9617              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9618       
9619       size = AOP_SIZE (result) - 1;
9620       if (AOP_INDPTRn(left)) {
9621           genSetDPTR(AOP(left)->aopu.dptr);
9622       }
9623       while (size--) emitcode ("lcall","__decdptr");
9624       if (AOP_INDPTRn(left)) {
9625           genSetDPTR(0);
9626       }
9627   }
9628
9629   freeAsmop (left, NULL, ic, TRUE);
9630   freeAsmop (result, NULL, ic, TRUE);
9631 }
9632
9633 /*-----------------------------------------------------------------*/
9634 /* genCodePointerGet - get value from code space                  */
9635 /*-----------------------------------------------------------------*/
9636 static void
9637 genCodePointerGet (operand * left,
9638                     operand * result, iCode * ic, iCode *pi)
9639 {
9640   int size, offset, dopi=1;
9641   sym_link *retype = getSpec (operandType (result));
9642
9643   aopOp (left, ic, FALSE, FALSE);
9644
9645   /* if the operand is already in dptr
9646      then we do nothing else we move the value to dptr */
9647   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9648     {
9649       /* if this is remateriazable */
9650       if (AOP_TYPE (left) == AOP_IMMD)
9651         {
9652           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9653         }
9654       else
9655         {                       /* we need to get it byte by byte */
9656           _startLazyDPSEvaluation ();
9657           if (AOP_TYPE (left) != AOP_DPTR)
9658             {
9659               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9660               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9661               if (options.model == MODEL_FLAT24)
9662                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9663             }
9664           else
9665             {
9666               /* We need to generate a load to DPTR indirect through DPTR. */
9667               D (emitcode (";", "gencodePointerGet -- indirection special case."););
9668               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9669               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9670               if (options.model == MODEL_FLAT24)
9671                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9672               emitcode ("pop", "dph");
9673               emitcode ("pop", "dpl");
9674               dopi=0;
9675             }
9676           _endLazyDPSEvaluation ();
9677         }
9678     }
9679   /* so dptr know contains the address */
9680   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9681
9682   /* if bit then unpack */
9683   if (IS_BITVAR (retype)) {
9684       if (AOP_INDPTRn(left)) {
9685           genSetDPTR(AOP(left)->aopu.dptr);
9686       }
9687       genUnpackBits (result, "dptr", CPOINTER);
9688       if (AOP_INDPTRn(left)) {
9689           genSetDPTR(0);
9690       }
9691   } else
9692     {
9693       size = AOP_SIZE (result);
9694       offset = 0;
9695       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9696           while (size--) {
9697               genSetDPTR(AOP(left)->aopu.dptr);
9698               emitcode ("clr", "a");
9699               emitcode ("movc", "a,@a+dptr");
9700               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9701                   emitcode ("inc", "dptr");
9702               genSetDPTR (0);
9703               aopPut (AOP (result), "a", offset++);
9704           }
9705       } else {
9706           _startLazyDPSEvaluation ();
9707           while (size--)
9708               {
9709                   if (AOP_INDPTRn(left)) {
9710                       genSetDPTR(AOP(left)->aopu.dptr);
9711                   } else {
9712                       genSetDPTR (0);
9713                   }
9714                   _flushLazyDPS ();
9715                   
9716                   emitcode ("clr", "a");
9717                   emitcode ("movc", "a,@a+dptr");
9718                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9719                       emitcode ("inc", "dptr");
9720                   aopPut (AOP (result), "a", offset++);
9721               }
9722           _endLazyDPSEvaluation ();
9723       }
9724     }
9725   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9726       if (!AOP_INDPTRn(left)) {
9727           _startLazyDPSEvaluation ();
9728           
9729           aopPut ( AOP (left), "dpl", 0);
9730           aopPut ( AOP (left), "dph", 1);
9731           if (options.model == MODEL_FLAT24)
9732               aopPut ( AOP (left), "dpx", 2);
9733
9734           _endLazyDPSEvaluation ();
9735       }
9736       pi->generated = 1;
9737   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9738              AOP_SIZE(result) > 1 &&
9739              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9740       
9741       size = AOP_SIZE (result) - 1;
9742       if (AOP_INDPTRn(left)) {
9743           genSetDPTR(AOP(left)->aopu.dptr);
9744       }
9745       while (size--) emitcode ("lcall","__decdptr");
9746       if (AOP_INDPTRn(left)) {
9747           genSetDPTR(0);
9748       }
9749   }
9750   
9751   freeAsmop (left, NULL, ic, TRUE);
9752   freeAsmop (result, NULL, ic, TRUE);
9753 }
9754
9755 /*-----------------------------------------------------------------*/
9756 /* genGenPointerGet - gget value from generic pointer space        */
9757 /*-----------------------------------------------------------------*/
9758 static void
9759 genGenPointerGet (operand * left,
9760                   operand * result, iCode * ic, iCode * pi)
9761 {
9762   int size, offset;
9763   sym_link *retype = getSpec (operandType (result));
9764   sym_link *letype = getSpec (operandType (left));
9765
9766   D (emitcode (";", "genGenPointerGet "); );
9767
9768   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9769
9770   /* if the operand is already in dptr
9771      then we do nothing else we move the value to dptr */
9772   if (AOP_TYPE (left) != AOP_STR)
9773     {
9774       /* if this is remateriazable */
9775       if (AOP_TYPE (left) == AOP_IMMD)
9776         {
9777           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9778           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9779             {
9780                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9781             }
9782             else
9783             {
9784                 emitcode ("mov", "b,#%d", pointerCode (retype));
9785             }
9786         }
9787       else
9788         {                       /* we need to get it byte by byte */
9789             _startLazyDPSEvaluation ();
9790             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9791             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9792             if (options.model == MODEL_FLAT24) {
9793                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9794                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9795             } else {
9796                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9797             }
9798             _endLazyDPSEvaluation ();
9799         }
9800     }
9801
9802   /* so dptr-b now contains the address */
9803   _G.bInUse++;
9804   aopOp (result, ic, FALSE, TRUE);
9805   _G.bInUse--;
9806
9807   /* if bit then unpack */
9808   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9809   {
9810     genUnpackBits (result, "dptr", GPOINTER);
9811   }
9812   else
9813     {
9814         size = AOP_SIZE (result);
9815         offset = 0;
9816
9817         while (size--)
9818         {
9819             if (size)
9820             {
9821                 // Get two bytes at a time, results in _AP & A.
9822                 // dptr will be incremented ONCE by __gptrgetWord.
9823                 //
9824                 // Note: any change here must be coordinated
9825                 // with the implementation of __gptrgetWord
9826                 // in device/lib/_gptrget.c
9827                 emitcode ("lcall", "__gptrgetWord");
9828                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9829                 aopPut (AOP (result), "a", offset++);
9830                 size--;
9831             }
9832             else
9833             {
9834                 // Only one byte to get.
9835                 emitcode ("lcall", "__gptrget");
9836                 aopPut (AOP (result), "a", offset++);
9837             }
9838             
9839             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9840             {
9841                 emitcode ("inc", "dptr");
9842             }
9843         }
9844     }
9845
9846   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9847     _startLazyDPSEvaluation ();
9848       
9849     aopPut ( AOP (left), "dpl", 0);
9850     aopPut ( AOP (left), "dph", 1);
9851     if (options.model == MODEL_FLAT24) {
9852         aopPut ( AOP (left), "dpx", 2);
9853         aopPut ( AOP (left), "b", 3);   
9854     } else  aopPut ( AOP (left), "b", 2);       
9855     
9856     _endLazyDPSEvaluation ();
9857       
9858     pi->generated = 1;
9859   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9860              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9861       
9862       size = AOP_SIZE (result) - 1;
9863       while (size--) emitcode ("lcall","__decdptr");
9864   }
9865
9866   freeAsmop (left, NULL, ic, TRUE);
9867   freeAsmop (result, NULL, ic, TRUE);
9868 }
9869
9870 /*-----------------------------------------------------------------*/
9871 /* genPointerGet - generate code for pointer get                   */
9872 /*-----------------------------------------------------------------*/
9873 static void
9874 genPointerGet (iCode * ic, iCode *pi)
9875 {
9876   operand *left, *result;
9877   sym_link *type, *etype;
9878   int p_type;
9879
9880   D (emitcode (";", "genPointerGet ");
9881     );
9882
9883   left = IC_LEFT (ic);
9884   result = IC_RESULT (ic);
9885
9886   /* depending on the type of pointer we need to
9887      move it to the correct pointer register */
9888   type = operandType (left);
9889   etype = getSpec (type);
9890   /* if left is of type of pointer then it is simple */
9891   if (IS_PTR (type) && !IS_FUNC (type->next))
9892     p_type = DCL_TYPE (type);
9893   else
9894     {
9895       /* we have to go by the storage class */
9896       p_type = PTR_TYPE (SPEC_OCLS (etype));
9897     }
9898   /* special case when cast remat */
9899   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9900       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9901           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9902           type = operandType (left);
9903           p_type = DCL_TYPE (type);
9904   }
9905   /* now that we have the pointer type we assign
9906      the pointer values */
9907   switch (p_type)
9908     {
9909
9910     case POINTER:
9911     case IPOINTER:
9912       genNearPointerGet (left, result, ic, pi);
9913       break;
9914
9915     case PPOINTER:
9916       genPagedPointerGet (left, result, ic, pi);
9917       break;
9918
9919     case FPOINTER:
9920       genFarPointerGet (left, result, ic, pi);
9921       break;
9922
9923     case CPOINTER:
9924       genCodePointerGet (left, result, ic, pi);
9925       break;
9926
9927     case GPOINTER:
9928       genGenPointerGet (left, result, ic, pi);
9929       break;
9930     }
9931
9932 }
9933
9934 /*-----------------------------------------------------------------*/
9935 /* genPackBits - generates code for packed bit storage             */
9936 /*-----------------------------------------------------------------*/
9937 static void
9938 genPackBits (sym_link * etype,
9939              operand * right,
9940              char *rname, int p_type)
9941 {
9942   int offset = 0;       /* source byte offset */
9943   int rlen = 0;         /* remaining bitfield length */
9944   int blen;             /* bitfield length */
9945   int bstr;             /* bitfield starting bit within byte */
9946   int litval;           /* source literal value (if AOP_LIT) */
9947   unsigned char mask;   /* bitmask within current byte */
9948
9949   D(emitcode (";     genPackBits",""));
9950
9951   blen = SPEC_BLEN (etype);
9952   bstr = SPEC_BSTR (etype);
9953
9954   /* If the bitfield length is less than a byte */
9955   if (blen < 8)
9956     {
9957       mask = ((unsigned char) (0xFF << (blen + bstr)) |
9958               (unsigned char) (0xFF >> (8 - bstr)));
9959
9960       if (AOP_TYPE (right) == AOP_LIT)
9961         {
9962           /* Case with a bitfield length <8 and literal source
9963           */
9964           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9965           litval <<= bstr;
9966           litval &= (~mask) & 0xff;
9967           emitPtrByteGet (rname, p_type, FALSE);
9968           if ((mask|litval)!=0xff)
9969             emitcode ("anl","a,#!constbyte", mask);
9970           if (litval)
9971             emitcode ("orl","a,#!constbyte", litval);
9972         }
9973       else
9974         {
9975           if ((blen==1) && (p_type!=GPOINTER))
9976             {
9977               /* Case with a bitfield length == 1 and no generic pointer
9978               */
9979               if (AOP_TYPE (right) == AOP_CRY)
9980                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9981               else
9982                 {
9983                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9984                   emitcode ("rrc","a");
9985                 }
9986               emitPtrByteGet (rname, p_type, FALSE);
9987               emitcode ("mov","acc.%d,c",bstr);
9988             }
9989           else
9990             {
9991               /* Case with a bitfield length < 8 and arbitrary source
9992               */
9993               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9994               /* shift and mask source value */
9995               AccLsh (bstr);
9996               emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9997
9998               /* transfer A to B and get next byte */
9999               emitPtrByteGet (rname, p_type, TRUE);
10000
10001               emitcode ("anl", "a,#!constbyte", mask);
10002               emitcode ("orl", "a,b");
10003               if (p_type == GPOINTER)
10004                 emitcode ("pop", "b");
10005            }
10006         }
10007
10008       emitPtrByteSet (rname, p_type, "a");
10009       return;
10010     }
10011
10012   /* Bit length is greater than 7 bits. In this case, copy  */
10013   /* all except the partial byte at the end                 */
10014   for (rlen=blen;rlen>=8;rlen-=8)
10015     {
10016       emitPtrByteSet (rname, p_type, 
10017                       aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10018       if (rlen>8)
10019         emitcode ("inc", "%s", rname);
10020     }
10021
10022   /* If there was a partial byte at the end */
10023   if (rlen)
10024     {
10025       mask = (((unsigned char) -1 << rlen) & 0xff);
10026       
10027       if (AOP_TYPE (right) == AOP_LIT)
10028         {
10029           /* Case with partial byte and literal source
10030           */
10031           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10032           litval >>= (blen-rlen);
10033           litval &= (~mask) & 0xff;
10034           emitPtrByteGet (rname, p_type, FALSE);
10035           if ((mask|litval)!=0xff)
10036             emitcode ("anl","a,#!constbyte", mask);
10037           if (litval)
10038             emitcode ("orl","a,#!constbyte", litval);
10039         }
10040       else
10041         {
10042           /* Case with partial byte and arbitrary source
10043           */
10044           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10045           emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10046
10047           /* transfer A to B and get next byte */
10048           emitPtrByteGet (rname, p_type, TRUE);
10049
10050           emitcode ("anl", "a,#!constbyte", mask);
10051           emitcode ("orl", "a,b");
10052           if (p_type == GPOINTER)
10053             emitcode ("pop", "b");
10054         }
10055       emitPtrByteSet (rname, p_type, "a");
10056     }
10057
10058 }
10059
10060
10061 /*-----------------------------------------------------------------*/
10062 /* genDataPointerSet - remat pointer to data space                 */
10063 /*-----------------------------------------------------------------*/
10064 static void
10065 genDataPointerSet (operand * right,
10066                    operand * result,
10067                    iCode * ic)
10068 {
10069   int size, offset = 0;
10070   char *l, buff[256];
10071
10072   aopOp (right, ic, FALSE, FALSE);
10073
10074   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10075   size = AOP_SIZE (right);
10076   while (size--)
10077     {
10078       if (offset)
10079         {
10080             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10081         }
10082       else
10083         {
10084             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10085         }
10086         
10087       emitcode ("mov", "%s,%s", buff,
10088                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10089     }
10090
10091   freeAsmop (right, NULL, ic, TRUE);
10092   freeAsmop (result, NULL, ic, TRUE);
10093 }
10094
10095 /*-----------------------------------------------------------------*/
10096 /* genNearPointerSet - emitcode for near pointer put                */
10097 /*-----------------------------------------------------------------*/
10098 static void
10099 genNearPointerSet (operand * right,
10100                    operand * result,
10101                    iCode * ic,
10102                    iCode * pi)
10103 {
10104   asmop *aop = NULL;
10105   char *rname, *l;
10106   sym_link *retype, *letype;
10107   sym_link *ptype = operandType (result);
10108
10109   retype = getSpec (operandType (right));
10110   letype = getSpec (ptype);
10111
10112   aopOp (result, ic, FALSE, FALSE);
10113
10114   /* if the result is rematerializable &
10115      in data space & not a bit variable */
10116   if (AOP_TYPE (result) == AOP_IMMD &&
10117       DCL_TYPE (ptype) == POINTER &&
10118       !IS_BITVAR (retype) &&
10119       !IS_BITVAR (letype))
10120     {
10121       genDataPointerSet (right, result, ic);
10122       return;
10123     }
10124
10125   /* if the value is already in a pointer register
10126      then don't need anything more */
10127   if (!AOP_INPREG (AOP (result)))
10128     {
10129       /* otherwise get a free pointer register */
10130       regs *preg;
10131         
10132       aop = newAsmop (0);
10133       preg = getFreePtr (ic, &aop, FALSE);
10134       emitcode ("mov", "%s,%s",
10135                 preg->name,
10136                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10137       rname = preg->name;
10138     }
10139   else
10140     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10141
10142   aopOp (right, ic, FALSE, FALSE);
10143
10144   /* if bitfield then unpack the bits */
10145   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10146     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10147   else
10148     {
10149       /* we have can just get the values */
10150       int size = AOP_SIZE (right);
10151       int offset = 0;
10152
10153       while (size--)
10154         {
10155           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10156           if (*l == '@')
10157             {
10158               MOVA (l);
10159               emitcode ("mov", "@%s,a", rname);
10160             }
10161           else
10162             emitcode ("mov", "@%s,%s", rname, l);
10163           if (size || pi)
10164             emitcode ("inc", "%s", rname);
10165           offset++;
10166         }
10167     }
10168
10169   /* now some housekeeping stuff */
10170   if (aop)
10171     {
10172       /* we had to allocate for this iCode */
10173       if (pi) aopPut (AOP (result),rname,0);
10174       freeAsmop (NULL, aop, ic, TRUE);
10175     }
10176   else
10177     {
10178       /* we did not allocate which means left
10179          already in a pointer register, then
10180          if size > 0 && this could be used again
10181          we have to point it back to where it
10182          belongs */
10183       if (AOP_SIZE (right) > 1 &&
10184           !OP_SYMBOL (result)->remat &&
10185           (OP_SYMBOL (result)->liveTo > ic->seq ||
10186            ic->depth) &&
10187           !pi)
10188         {
10189           int size = AOP_SIZE (right) - 1;
10190           while (size--)
10191             emitcode ("dec", "%s", rname);
10192         }
10193     }
10194
10195   /* done */
10196   if (pi) pi->generated = 1;
10197   freeAsmop (result, NULL, ic, TRUE);
10198   freeAsmop (right, NULL, ic, TRUE);
10199
10200
10201 }
10202
10203 /*-----------------------------------------------------------------*/
10204 /* genPagedPointerSet - emitcode for Paged pointer put             */
10205 /*-----------------------------------------------------------------*/
10206 static void
10207 genPagedPointerSet (operand * right,
10208                     operand * result,
10209                     iCode * ic,
10210                     iCode *pi)
10211 {
10212   asmop *aop = NULL;
10213   char *rname;
10214   sym_link *retype, *letype;
10215
10216   retype = getSpec (operandType (right));
10217   letype = getSpec (operandType (result));
10218
10219   aopOp (result, ic, FALSE, FALSE);
10220
10221   /* if the value is already in a pointer register
10222      then don't need anything more */
10223   if (!AOP_INPREG (AOP (result)))
10224     {
10225       /* otherwise get a free pointer register */
10226       regs *preg;
10227         
10228       aop = newAsmop (0);
10229       preg = getFreePtr (ic, &aop, FALSE);
10230       emitcode ("mov", "%s,%s",
10231                 preg->name,
10232                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10233       rname = preg->name;
10234     }
10235   else
10236     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10237
10238   aopOp (right, ic, FALSE, FALSE);
10239
10240   /* if bitfield then unpack the bits */
10241   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10242     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10243   else
10244     {
10245       /* we have can just get the values */
10246       int size = AOP_SIZE (right);
10247       int offset = 0;
10248
10249       while (size--)
10250         {
10251           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10252
10253           emitcode ("movx", "@%s,a", rname);
10254
10255           if (size || pi)
10256             emitcode ("inc", "%s", rname);
10257
10258           offset++;
10259         }
10260     }
10261
10262   /* now some housekeeping stuff */
10263   if (aop)
10264     {
10265       if (pi) aopPut (AOP (result),rname,0);
10266       /* we had to allocate for this iCode */
10267       freeAsmop (NULL, aop, ic, TRUE);
10268     }
10269   else
10270     {
10271       /* we did not allocate which means left
10272          already in a pointer register, then
10273          if size > 0 && this could be used again
10274          we have to point it back to where it
10275          belongs */
10276       if (AOP_SIZE (right) > 1 &&
10277           !OP_SYMBOL (result)->remat &&
10278           (OP_SYMBOL (result)->liveTo > ic->seq ||
10279            ic->depth) &&
10280           !pi)
10281         {
10282           int size = AOP_SIZE (right) - 1;
10283           while (size--)
10284             emitcode ("dec", "%s", rname);
10285         }
10286     }
10287
10288   /* done */
10289   if (pi) pi->generated = 1;
10290   freeAsmop (result, NULL, ic, TRUE);
10291   freeAsmop (right, NULL, ic, TRUE);
10292
10293
10294 }
10295
10296 /*-----------------------------------------------------------------*/
10297 /* genFarPointerSet - set value from far space                     */
10298 /*-----------------------------------------------------------------*/
10299 static void
10300 genFarPointerSet (operand * right,
10301                   operand * result, iCode * ic, iCode *pi)
10302 {
10303   int size, offset, dopi=1;
10304   sym_link *retype = getSpec (operandType (right));
10305   sym_link *letype = getSpec (operandType (result));
10306
10307   aopOp (result, ic, FALSE, FALSE);
10308
10309   /* if the operand is already in dptr
10310      then we do nothing else we move the value to dptr */
10311   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10312     {
10313       /* if this is remateriazable */
10314       if (AOP_TYPE (result) == AOP_IMMD)
10315         emitcode ("mov", "dptr,%s", 
10316                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10317       else
10318         {
10319           /* we need to get it byte by byte */
10320           _startLazyDPSEvaluation ();
10321           if (AOP_TYPE (result) != AOP_DPTR)
10322             {
10323               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10324               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10325               if (options.model == MODEL_FLAT24)
10326                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10327             }
10328           else
10329             {
10330               /* We need to generate a load to DPTR indirect through DPTR. */
10331               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10332                 
10333               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10334               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10335               if (options.model == MODEL_FLAT24)
10336                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10337               emitcode ("pop", "dph");
10338               emitcode ("pop", "dpl");
10339               dopi=0;
10340             }
10341           _endLazyDPSEvaluation ();
10342         }
10343     }
10344   /* so dptr know contains the address */
10345   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10346
10347   /* if bit then unpack */
10348   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10349       if (AOP_INDPTRn(result)) {
10350           genSetDPTR(AOP(result)->aopu.dptr);
10351       }
10352       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10353       if (AOP_INDPTRn(result)) {
10354           genSetDPTR(0);
10355       }
10356   } else {
10357       size = AOP_SIZE (right);
10358       offset = 0;
10359       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10360           while (size--) {
10361               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10362               
10363               genSetDPTR(AOP(result)->aopu.dptr);
10364               emitcode ("movx", "@dptr,a");
10365               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10366                   emitcode ("inc", "dptr");
10367               genSetDPTR (0);
10368           }
10369       } else {
10370           _startLazyDPSEvaluation ();
10371           while (size--) {
10372               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10373               
10374               if (AOP_INDPTRn(result)) {
10375                   genSetDPTR(AOP(result)->aopu.dptr);
10376               } else {
10377                   genSetDPTR (0);
10378               }
10379               _flushLazyDPS ();
10380               
10381               emitcode ("movx", "@dptr,a");
10382               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10383                   emitcode ("inc", "dptr");
10384           }
10385           _endLazyDPSEvaluation ();
10386       }
10387   }
10388   
10389   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10390       if (!AOP_INDPTRn(result)) {
10391           _startLazyDPSEvaluation ();
10392           
10393           aopPut (AOP(result),"dpl",0);
10394           aopPut (AOP(result),"dph",1);
10395           if (options.model == MODEL_FLAT24)
10396               aopPut (AOP(result),"dpx",2);
10397
10398           _endLazyDPSEvaluation ();
10399       }
10400       pi->generated=1;
10401   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10402              AOP_SIZE(right) > 1 &&
10403              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10404       
10405       size = AOP_SIZE (right) - 1;
10406       if (AOP_INDPTRn(result)) {
10407           genSetDPTR(AOP(result)->aopu.dptr);
10408       } 
10409       while (size--) emitcode ("lcall","__decdptr");
10410       if (AOP_INDPTRn(result)) {
10411           genSetDPTR(0);
10412       }
10413   }
10414   freeAsmop (result, NULL, ic, TRUE);
10415   freeAsmop (right, NULL, ic, TRUE);
10416 }
10417
10418 /*-----------------------------------------------------------------*/
10419 /* genGenPointerSet - set value from generic pointer space         */
10420 /*-----------------------------------------------------------------*/
10421 static void
10422 genGenPointerSet (operand * right,
10423                   operand * result, iCode * ic, iCode *pi)
10424 {
10425   int size, offset;
10426   sym_link *retype = getSpec (operandType (right));
10427   sym_link *letype = getSpec (operandType (result));
10428
10429   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10430
10431   /* if the operand is already in dptr
10432      then we do nothing else we move the value to dptr */
10433   if (AOP_TYPE (result) != AOP_STR)
10434     {
10435       _startLazyDPSEvaluation ();
10436       /* if this is remateriazable */
10437       if (AOP_TYPE (result) == AOP_IMMD)
10438         {
10439           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10440           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10441           {
10442               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10443           }
10444           else
10445           {
10446               emitcode ("mov", 
10447                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10448           }
10449         }
10450       else
10451         {                       /* we need to get it byte by byte */
10452           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10453           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10454           if (options.model == MODEL_FLAT24) {
10455             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10456             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10457           } else {
10458             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10459           }
10460         }
10461       _endLazyDPSEvaluation ();
10462     }
10463   /* so dptr + b now contains the address */
10464   _G.bInUse++;
10465   aopOp (right, ic, FALSE, TRUE);
10466   _G.bInUse--;
10467     
10468
10469   /* if bit then unpack */
10470   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10471     {
10472         genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10473     }
10474   else
10475     {
10476         size = AOP_SIZE (right);
10477         offset = 0;
10478
10479         _startLazyDPSEvaluation ();
10480         while (size--)
10481         {
10482             if (size)
10483             {
10484                 // Set two bytes at a time, passed in _AP & A.
10485                 // dptr will be incremented ONCE by __gptrputWord.
10486                 //
10487                 // Note: any change here must be coordinated
10488                 // with the implementation of __gptrputWord
10489                 // in device/lib/_gptrput.c
10490                 emitcode("mov", "_ap, %s", 
10491                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10492                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10493                 
10494                 genSetDPTR (0);
10495                 _flushLazyDPS ();
10496                 emitcode ("lcall", "__gptrputWord");
10497                 size--;
10498             }
10499             else
10500             {
10501                 // Only one byte to put.
10502                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10503
10504                 genSetDPTR (0);
10505                 _flushLazyDPS ();               
10506                 emitcode ("lcall", "__gptrput");
10507             }
10508             
10509             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10510             {
10511                 emitcode ("inc", "dptr");
10512             }
10513         }
10514         _endLazyDPSEvaluation ();
10515     }
10516
10517   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10518       _startLazyDPSEvaluation ();
10519       
10520       aopPut (AOP(result),"dpl",0);
10521       aopPut (AOP(result),"dph",1);
10522       if (options.model == MODEL_FLAT24) {
10523           aopPut (AOP(result),"dpx",2);
10524           aopPut (AOP(result),"b",3);
10525       } else {
10526           aopPut (AOP(result),"b",2);
10527       }
10528       _endLazyDPSEvaluation ();
10529       
10530       pi->generated=1;
10531   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10532              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10533       
10534       size = AOP_SIZE (right) - 1;
10535       while (size--) emitcode ("lcall","__decdptr");
10536   }
10537   freeAsmop (result, NULL, ic, TRUE);
10538   freeAsmop (right, NULL, ic, TRUE);
10539 }
10540
10541 /*-----------------------------------------------------------------*/
10542 /* genPointerSet - stores the value into a pointer location        */
10543 /*-----------------------------------------------------------------*/
10544 static void
10545 genPointerSet (iCode * ic, iCode *pi)
10546 {
10547   operand *right, *result;
10548   sym_link *type, *etype;
10549   int p_type;
10550
10551   D (emitcode (";", "genPointerSet "););
10552
10553   right = IC_RIGHT (ic);
10554   result = IC_RESULT (ic);
10555
10556   /* depending on the type of pointer we need to
10557      move it to the correct pointer register */
10558   type = operandType (result);
10559   etype = getSpec (type);
10560   /* if left is of type of pointer then it is simple */
10561   if (IS_PTR (type) && !IS_FUNC (type->next))
10562     {
10563       p_type = DCL_TYPE (type);
10564     }
10565   else
10566     {
10567       /* we have to go by the storage class */
10568       p_type = PTR_TYPE (SPEC_OCLS (etype));
10569     }
10570   /* special case when cast remat */
10571   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10572       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10573           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10574           type = operandType (result);
10575           p_type = DCL_TYPE (type);
10576   }
10577
10578   /* now that we have the pointer type we assign
10579      the pointer values */
10580   switch (p_type)
10581     {
10582
10583     case POINTER:
10584     case IPOINTER:
10585       genNearPointerSet (right, result, ic, pi);
10586       break;
10587
10588     case PPOINTER:
10589       genPagedPointerSet (right, result, ic, pi);
10590       break;
10591
10592     case FPOINTER:
10593       genFarPointerSet (right, result, ic, pi);
10594       break;
10595
10596     case GPOINTER:
10597       genGenPointerSet (right, result, ic, pi);
10598       break;
10599
10600     default:
10601       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10602               "genPointerSet: illegal pointer type");
10603     }
10604
10605 }
10606
10607 /*-----------------------------------------------------------------*/
10608 /* genIfx - generate code for Ifx statement                        */
10609 /*-----------------------------------------------------------------*/
10610 static void
10611 genIfx (iCode * ic, iCode * popIc)
10612 {
10613   operand *cond = IC_COND (ic);
10614   int isbit = 0;
10615
10616   D (emitcode (";", "genIfx "););
10617
10618   aopOp (cond, ic, FALSE, FALSE);
10619
10620   /* get the value into acc */
10621   if (AOP_TYPE (cond) != AOP_CRY)
10622     {
10623         toBoolean (cond);
10624     }
10625   else
10626     {
10627         isbit = 1;
10628     }
10629     
10630   /* the result is now in the accumulator */
10631   freeAsmop (cond, NULL, ic, TRUE);
10632
10633   /* if there was something to be popped then do it */
10634   if (popIc)
10635     genIpop (popIc);
10636
10637   /* if the condition is  a bit variable */
10638   if (isbit && IS_ITEMP (cond) &&
10639       SPIL_LOC (cond))
10640     {
10641         genIfxJump (ic, SPIL_LOC (cond)->rname);
10642     }
10643   else if (isbit && !IS_ITEMP (cond))
10644     {
10645         genIfxJump (ic, OP_SYMBOL (cond)->rname);
10646     }
10647   else
10648     {
10649         genIfxJump (ic, "a");
10650     }
10651
10652   ic->generated = 1;
10653 }
10654
10655 /*-----------------------------------------------------------------*/
10656 /* genAddrOf - generates code for address of                       */
10657 /*-----------------------------------------------------------------*/
10658 static void
10659 genAddrOf (iCode * ic)
10660 {
10661   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10662   int size, offset;
10663
10664   D (emitcode (";", "genAddrOf ");
10665     );
10666
10667   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10668
10669   /* if the operand is on the stack then we
10670      need to get the stack offset of this
10671      variable */
10672   if (sym->onStack) {
10673       
10674       /* if 10 bit stack */
10675       if (options.stack10bit) {
10676           char buff[10];
10677           int  offset;
10678           
10679           tsprintf(buff, sizeof(buff), 
10680                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
10681           /* if it has an offset then we need to compute it */
10682 /*        emitcode ("subb", "a,#!constbyte", */
10683 /*                  -((sym->stack < 0) ? */
10684 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10685 /*                    ((short) sym->stack)) & 0xff); */
10686 /*        emitcode ("mov","b,a"); */
10687 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10688 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10689 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10690           if (sym->stack) {
10691               emitcode ("mov", "a,_bpx");
10692               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10693                                              ((char) (sym->stack - _G.nRegsSaved)) :
10694                                              ((char) sym->stack )) & 0xff);
10695               emitcode ("mov", "b,a");
10696               emitcode ("mov", "a,_bpx+1");
10697               
10698               offset = (((sym->stack < 0) ? 
10699                          ((short) (sym->stack - _G.nRegsSaved)) :
10700                          ((short) sym->stack )) >> 8) & 0xff;
10701           
10702               emitcode ("addc","a,#!constbyte", offset);
10703
10704               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10705               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10706               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10707           } else {
10708               /* we can just move _bp */
10709               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10710               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10711               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10712           }       
10713       } else {
10714           /* if it has an offset then we need to compute it */
10715           if (sym->stack) {
10716               emitcode ("mov", "a,_bp");
10717               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10718               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10719           } else {
10720               /* we can just move _bp */
10721               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10722           }
10723           /* fill the result with zero */
10724           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10725           
10726           
10727           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10728               fprintf (stderr,
10729                        "*** warning: pointer to stack var truncated.\n");
10730           }
10731
10732           offset = 1;
10733           while (size--) {
10734               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10735           }      
10736       }
10737       goto release;
10738   }
10739
10740   /* object not on stack then we need the name */
10741   size = AOP_SIZE (IC_RESULT (ic));
10742   offset = 0;
10743
10744   while (size--)
10745     {
10746       char s[SDCC_NAME_MAX];
10747       if (offset) {
10748           switch (offset) {
10749           case 1:
10750               tsprintf(s, sizeof(s), "#!his",sym->rname);
10751               break;
10752           case 2:
10753               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10754               break;
10755           case 3:
10756               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10757               break;
10758           default: /* should not need this (just in case) */
10759               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10760                        sym->rname,
10761                        offset * 8);
10762           }
10763       } 
10764       else
10765       {
10766           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10767       }
10768         
10769       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10770     }
10771
10772 release:
10773   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10774
10775 }
10776
10777 #if 0 // obsolete, and buggy for != xdata
10778 /*-----------------------------------------------------------------*/
10779 /* genArrayInit - generates code for address of                       */
10780 /*-----------------------------------------------------------------*/
10781 static void
10782 genArrayInit (iCode * ic)
10783 {
10784     literalList *iLoop;
10785     int         ix, count;
10786     int         elementSize = 0, eIndex;
10787     unsigned    val, lastVal;
10788     sym_link    *type;
10789     operand     *left=IC_LEFT(ic);
10790     
10791     D (emitcode (";", "genArrayInit "););
10792
10793     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10794     
10795     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10796     {
10797         // Load immediate value into DPTR.
10798         emitcode("mov", "dptr, %s",
10799              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10800     }
10801     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10802     {
10803 #if 0
10804       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10805               "Unexpected operand to genArrayInit.\n");
10806       exit(1);
10807 #else
10808       // a regression because of SDCCcse.c:1.52
10809       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10810       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10811       if (options.model == MODEL_FLAT24)
10812         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10813 #endif
10814     }
10815     
10816     type = operandType(IC_LEFT(ic));
10817     
10818     if (type && type->next)
10819     {
10820         elementSize = getSize(type->next);
10821     }
10822     else
10823     {
10824         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10825                                 "can't determine element size in genArrayInit.\n");
10826         exit(1);
10827     }
10828     
10829     iLoop = IC_ARRAYILIST(ic);
10830     lastVal = 0xffff;
10831     
10832     while (iLoop)
10833     {
10834         bool firstpass = TRUE;
10835         
10836         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10837                  iLoop->count, (int)iLoop->literalValue, elementSize);
10838         
10839         ix = iLoop->count;
10840         
10841         while (ix)
10842         {
10843             symbol *tlbl = NULL;
10844             
10845             count = ix > 256 ? 256 : ix;
10846             
10847             if (count > 1)
10848             {
10849                 tlbl = newiTempLabel (NULL);
10850                 if (firstpass || (count & 0xff))
10851                 {
10852                     emitcode("mov", "b, #!constbyte", count & 0xff);
10853                 }
10854                 
10855                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10856             }
10857             
10858             firstpass = FALSE;
10859                 
10860             for (eIndex = 0; eIndex < elementSize; eIndex++)
10861             {
10862                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10863                 if (val != lastVal)
10864                 {
10865                     emitcode("mov", "a, #!constbyte", val);
10866                     lastVal = val;
10867                 }
10868                 
10869                 emitcode("movx", "@dptr, a");
10870                 emitcode("inc", "dptr");
10871             }
10872             
10873             if (count > 1)
10874             {
10875                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10876             }
10877             
10878             ix -= count;
10879         }
10880         
10881         iLoop = iLoop->next;
10882     }
10883     
10884     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10885 }
10886 #endif
10887
10888 /*-----------------------------------------------------------------*/
10889 /* genFarFarAssign - assignment when both are in far space         */
10890 /*-----------------------------------------------------------------*/
10891 static void
10892 genFarFarAssign (operand * result, operand * right, iCode * ic)
10893 {
10894   int size = AOP_SIZE (right);
10895   int offset = 0;
10896   symbol *rSym = NULL;
10897
10898   if (size == 1)
10899   {
10900       /* quick & easy case. */
10901       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10902       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10903       freeAsmop (right, NULL, ic, FALSE);
10904       /* now assign DPTR to result */
10905       _G.accInUse++;
10906       aopOp(result, ic, FALSE, FALSE);
10907       _G.accInUse--;
10908       aopPut(AOP(result), "a", 0);
10909       freeAsmop(result, NULL, ic, FALSE);
10910       return;
10911   }
10912   
10913   /* See if we've got an underlying symbol to abuse. */
10914   if (IS_SYMOP(result) && OP_SYMBOL(result))
10915   {
10916       if (IS_TRUE_SYMOP(result))
10917       {
10918           rSym = OP_SYMBOL(result);
10919       }
10920       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10921       {
10922           rSym = OP_SYMBOL(result)->usl.spillLoc;
10923       }
10924   }
10925              
10926   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10927   {
10928       /* We can use the '390 auto-toggle feature to good effect here. */
10929       
10930       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10931       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10932       emitcode ("mov", "dptr,#%s", rSym->rname); 
10933       /* DP2 = result, DP1 = right, DP1 is current. */
10934       while (size)
10935       {
10936           emitcode("movx", "a,@dptr");
10937           emitcode("movx", "@dptr,a");
10938           if (--size)
10939           {
10940                emitcode("inc", "dptr");
10941                emitcode("inc", "dptr");
10942           }
10943       }
10944       emitcode("mov", "dps,#0");
10945       freeAsmop (right, NULL, ic, FALSE);
10946 #if 0
10947 some alternative code for processors without auto-toggle
10948 no time to test now, so later well put in...kpb
10949         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10950         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10951         emitcode ("mov", "dptr,#%s", rSym->rname); 
10952         /* DP2 = result, DP1 = right, DP1 is current. */
10953         while (size)
10954         {
10955           --size;
10956           emitcode("movx", "a,@dptr");
10957           if (size)
10958             emitcode("inc", "dptr");
10959           emitcode("inc", "dps");
10960           emitcode("movx", "@dptr,a");
10961           if (size)
10962             emitcode("inc", "dptr");
10963           emitcode("inc", "dps");
10964         }
10965         emitcode("mov", "dps,#0");
10966         freeAsmop (right, NULL, ic, FALSE);
10967 #endif
10968   }
10969   else
10970   {
10971       D (emitcode (";", "genFarFarAssign"););
10972       aopOp (result, ic, TRUE, TRUE);
10973
10974       _startLazyDPSEvaluation ();
10975       
10976       while (size--)
10977         {
10978           aopPut (AOP (result),
10979                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10980           offset++;
10981         }
10982       _endLazyDPSEvaluation ();
10983       freeAsmop (result, NULL, ic, FALSE);
10984       freeAsmop (right, NULL, ic, FALSE);
10985   }
10986 }
10987
10988 /*-----------------------------------------------------------------*/
10989 /* genAssign - generate code for assignment                        */
10990 /*-----------------------------------------------------------------*/
10991 static void
10992 genAssign (iCode * ic)
10993 {
10994   operand *result, *right;
10995   int size, offset;
10996   unsigned long lit = 0L;
10997
10998   D (emitcode (";", "genAssign ");
10999     );
11000
11001   result = IC_RESULT (ic);
11002   right = IC_RIGHT (ic);
11003
11004   /* if they are the same */
11005   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11006     return;
11007
11008   aopOp (right, ic, FALSE, FALSE);
11009
11010   emitcode (";", "genAssign: resultIsFar = %s",
11011             isOperandInFarSpace (result) ?
11012             "TRUE" : "FALSE");
11013
11014   /* special case both in far space */
11015   if ((AOP_TYPE (right) == AOP_DPTR ||
11016        AOP_TYPE (right) == AOP_DPTR2) &&
11017   /* IS_TRUE_SYMOP(result)       && */
11018       isOperandInFarSpace (result))
11019     {
11020       genFarFarAssign (result, right, ic);
11021       return;
11022     }
11023
11024   aopOp (result, ic, TRUE, FALSE);
11025
11026   /* if they are the same registers */
11027   if (sameRegs (AOP (right), AOP (result)))
11028     goto release;
11029
11030   /* if the result is a bit */
11031   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11032     {
11033       /* if the right size is a literal then
11034          we know what the value is */
11035       if (AOP_TYPE (right) == AOP_LIT)
11036         {
11037           if (((int) operandLitValue (right)))
11038             aopPut (AOP (result), one, 0);
11039           else
11040             aopPut (AOP (result), zero, 0);
11041           goto release;
11042         }
11043
11044       /* the right is also a bit variable */
11045       if (AOP_TYPE (right) == AOP_CRY)
11046         {
11047           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11048           aopPut (AOP (result), "c", 0);
11049           goto release;
11050         }
11051
11052       /* we need to or */
11053       toBoolean (right);
11054       aopPut (AOP (result), "a", 0);
11055       goto release;
11056     }
11057
11058   /* bit variables done */
11059   /* general case */
11060   size = AOP_SIZE (result);
11061   offset = 0;
11062   if (AOP_TYPE (right) == AOP_LIT)
11063     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11064
11065   if ((size > 1) &&
11066       (AOP_TYPE (result) != AOP_REG) &&
11067       (AOP_TYPE (right) == AOP_LIT) &&
11068       !IS_FLOAT (operandType (right)))
11069     {
11070       _startLazyDPSEvaluation ();
11071       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11072         {
11073           aopPut (AOP (result),
11074                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11075                   offset);
11076           offset++;
11077           size--;
11078         }
11079       /* And now fill the rest with zeros. */
11080       if (size)
11081         {
11082           emitcode ("clr", "a");
11083         }
11084       while (size--)
11085         {
11086           aopPut (AOP (result), "a", offset++);
11087         }
11088       _endLazyDPSEvaluation ();
11089     }
11090   else
11091     {
11092       _startLazyDPSEvaluation ();
11093       while (size--)
11094         {
11095           aopPut (AOP (result),
11096                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11097                   offset);
11098           offset++;
11099         }
11100       _endLazyDPSEvaluation ();
11101     }
11102
11103 release:
11104   freeAsmop (right, NULL, ic, FALSE);
11105   freeAsmop (result, NULL, ic, TRUE);
11106 }
11107
11108 /*-----------------------------------------------------------------*/
11109 /* genJumpTab - generates code for jump table                      */
11110 /*-----------------------------------------------------------------*/
11111 static void
11112 genJumpTab (iCode * ic)
11113 {
11114   symbol *jtab;
11115   char *l;
11116
11117   D (emitcode (";", "genJumpTab ");
11118     );
11119
11120   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11121   /* get the condition into accumulator */
11122   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11123   MOVA (l);
11124   /* multiply by four! */
11125   emitcode ("add", "a,acc");
11126   emitcode ("add", "a,acc");
11127   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11128
11129   jtab = newiTempLabel (NULL);
11130   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11131   emitcode ("jmp", "@a+dptr");
11132   emitcode ("", "!tlabeldef", jtab->key + 100);
11133   /* now generate the jump labels */
11134   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11135        jtab = setNextItem (IC_JTLABELS (ic)))
11136     emitcode ("ljmp", "!tlabel", jtab->key + 100);
11137
11138 }
11139
11140 /*-----------------------------------------------------------------*/
11141 /* genCast - gen code for casting                                  */
11142 /*-----------------------------------------------------------------*/
11143 static void
11144 genCast (iCode * ic)
11145 {
11146   operand *result = IC_RESULT (ic);
11147   sym_link *ctype = operandType (IC_LEFT (ic));
11148   sym_link *rtype = operandType (IC_RIGHT (ic));
11149   operand *right = IC_RIGHT (ic);
11150   int size, offset;
11151
11152   D (emitcode (";", "genCast "););
11153
11154   /* if they are equivalent then do nothing */
11155   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11156     return;
11157
11158   aopOp (right, ic, FALSE, FALSE);
11159   aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11160
11161   /* if the result is a bit */
11162   if (IS_BITVAR (OP_SYMBOL (result)->type)
11163       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11164     {
11165       /* if the right size is a literal then
11166          we know what the value is */
11167       if (AOP_TYPE (right) == AOP_LIT)
11168         {
11169           if (((int) operandLitValue (right)))
11170             aopPut (AOP (result), one, 0);
11171           else
11172             aopPut (AOP (result), zero, 0);
11173
11174           goto release;
11175         }
11176
11177       /* the right is also a bit variable */
11178       if (AOP_TYPE (right) == AOP_CRY)
11179         {
11180           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11181           aopPut (AOP (result), "c", 0);
11182           goto release;
11183         }
11184
11185       /* we need to or */
11186       toBoolean (right);
11187       aopPut (AOP (result), "a", 0);
11188       goto release;
11189     }
11190
11191   /* if they are the same size : or less */
11192   if (AOP_SIZE (result) <= AOP_SIZE (right))
11193     {
11194
11195       /* if they are in the same place */
11196       if (sameRegs (AOP (right), AOP (result)))
11197         goto release;
11198
11199       /* if they in different places then copy */
11200       size = AOP_SIZE (result);
11201       offset = 0;
11202       _startLazyDPSEvaluation ();
11203       while (size--)
11204         {
11205           aopPut (AOP (result),
11206                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11207                   offset);
11208           offset++;
11209         }
11210       _endLazyDPSEvaluation ();
11211       goto release;
11212     }
11213
11214
11215   /* if the result is of type pointer */
11216   if (IS_PTR (ctype))
11217     {
11218
11219       int p_type;
11220       sym_link *type = operandType (right);
11221
11222       /* pointer to generic pointer */
11223       if (IS_GENPTR (ctype))
11224         {
11225           if (IS_PTR (type))
11226             {
11227               p_type = DCL_TYPE (type);
11228             }
11229           else
11230             {
11231 #if OLD_CAST_BEHAVIOR
11232               /* KV: we are converting a non-pointer type to
11233                * a generic pointer. This (ifdef'd out) code
11234                * says that the resulting generic pointer
11235                * should have the same class as the storage
11236                * location of the non-pointer variable.
11237                *
11238                * For example, converting an int (which happens
11239                * to be stored in DATA space) to a pointer results
11240                * in a DATA generic pointer; if the original int
11241                * in XDATA space, so will be the resulting pointer.
11242                *
11243                * I don't like that behavior, and thus this change:
11244                * all such conversions will be forced to XDATA and
11245                * throw a warning. If you want some non-XDATA
11246                * type, or you want to suppress the warning, you
11247                * must go through an intermediate cast, like so:
11248                *
11249                * char _generic *gp = (char _xdata *)(intVar);
11250                */
11251               sym_link *etype = getSpec (type);
11252
11253               /* we have to go by the storage class */
11254               if (SPEC_OCLS (etype) != generic)
11255                 {
11256                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11257                 }
11258               else
11259 #endif
11260                 {
11261                   /* Converting unknown class (i.e. register variable)
11262                    * to generic pointer. This is not good, but
11263                    * we'll make a guess (and throw a warning).
11264                    */
11265                   p_type = FPOINTER;
11266                   werror (W_INT_TO_GEN_PTR_CAST);
11267                 }
11268             }
11269
11270           /* the first two bytes are known */
11271           size = GPTRSIZE - 1;
11272           offset = 0;
11273           _startLazyDPSEvaluation ();
11274           while (size--)
11275             {
11276               aopPut (AOP (result),
11277                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11278                       offset);
11279               offset++;
11280             }
11281           _endLazyDPSEvaluation ();
11282
11283           /* the last byte depending on type */
11284             {
11285                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11286                 char gpValStr[10];
11287             
11288                 if (gpVal == -1)
11289                 {
11290                     // pointerTypeToGPByte will have bitched.
11291                     exit(1);
11292                 }
11293             
11294                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11295                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11296             }
11297           goto release;
11298         }
11299
11300       /* just copy the pointers */
11301       size = AOP_SIZE (result);
11302       offset = 0;
11303       _startLazyDPSEvaluation ();
11304       while (size--)
11305         {
11306           aopPut (AOP (result),
11307                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11308                   offset);
11309           offset++;
11310         }
11311       _endLazyDPSEvaluation ();
11312       goto release;
11313     }
11314
11315   /* so we now know that the size of destination is greater
11316      than the size of the source */
11317   /* we move to result for the size of source */
11318   size = AOP_SIZE (right);
11319   offset = 0;
11320   _startLazyDPSEvaluation ();
11321   while (size--)
11322     {
11323       aopPut (AOP (result),
11324               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11325               offset);
11326       offset++;
11327     }
11328   _endLazyDPSEvaluation ();
11329
11330   /* now depending on the sign of the source && destination */
11331   size = AOP_SIZE (result) - AOP_SIZE (right);
11332   /* if unsigned or not an integral type */
11333   /* also, if the source is a bit, we don't need to sign extend, because
11334    * it can't possibly have set the sign bit.
11335    */
11336   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11337     {
11338       while (size--)
11339         {
11340           aopPut (AOP (result), zero, offset++);
11341         }
11342     }
11343   else
11344     {
11345       /* we need to extend the sign :{ */
11346       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11347                         FALSE, FALSE, NULL));
11348       emitcode ("rlc", "a");
11349       emitcode ("subb", "a,acc");
11350       while (size--)
11351         aopPut (AOP (result), "a", offset++);
11352     }
11353
11354   /* we are done hurray !!!! */
11355
11356 release:
11357   freeAsmop (right, NULL, ic, TRUE);
11358   freeAsmop (result, NULL, ic, TRUE);
11359
11360 }
11361
11362 /*-----------------------------------------------------------------*/
11363 /* genDjnz - generate decrement & jump if not zero instrucion      */
11364 /*-----------------------------------------------------------------*/
11365 static int
11366 genDjnz (iCode * ic, iCode * ifx)
11367 {
11368   symbol *lbl, *lbl1;
11369   if (!ifx)
11370     return 0;
11371
11372   /* if the if condition has a false label
11373      then we cannot save */
11374   if (IC_FALSE (ifx))
11375     return 0;
11376
11377   /* if the minus is not of the form
11378      a = a - 1 */
11379   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11380       !IS_OP_LITERAL (IC_RIGHT (ic)))
11381     return 0;
11382
11383   if (operandLitValue (IC_RIGHT (ic)) != 1)
11384     return 0;
11385
11386   /* if the size of this greater than one then no
11387      saving */
11388   if (getSize (operandType (IC_RESULT (ic))) > 1)
11389     return 0;
11390
11391   /* otherwise we can save BIG */
11392   D(emitcode(";", "genDjnz"););
11393
11394   lbl = newiTempLabel (NULL);
11395   lbl1 = newiTempLabel (NULL);
11396
11397   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11398
11399   if (AOP_NEEDSACC(IC_RESULT(ic)))
11400   {
11401       /* If the result is accessed indirectly via
11402        * the accumulator, we must explicitly write
11403        * it back after the decrement.
11404        */
11405       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11406       
11407       if (strcmp(rByte, "a"))
11408       {
11409            /* Something is hopelessly wrong */
11410            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11411                    __FILE__, __LINE__);
11412            /* We can just give up; the generated code will be inefficient,
11413             * but what the hey.
11414             */
11415            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11416            return 0;
11417       }
11418       emitcode ("dec", "%s", rByte);
11419       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11420       emitcode ("jnz", "!tlabel", lbl->key + 100);
11421   }
11422   else if (IS_AOP_PREG (IC_RESULT (ic)))
11423     {
11424       emitcode ("dec", "%s",
11425                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11426       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11427       emitcode ("jnz", "!tlabel", lbl->key + 100);
11428     }
11429   else
11430     {
11431       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11432                 lbl->key + 100);
11433     }
11434   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11435   emitcode ("", "!tlabeldef", lbl->key + 100);
11436   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11437   emitcode ("", "!tlabeldef", lbl1->key + 100);
11438
11439   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11440   ifx->generated = 1;
11441   return 1;
11442 }
11443
11444 /*-----------------------------------------------------------------*/
11445 /* genReceive - generate code for a receive iCode                  */
11446 /*-----------------------------------------------------------------*/
11447 static void
11448 genReceive (iCode * ic)
11449 {
11450     int size = getSize (operandType (IC_RESULT (ic)));
11451     int offset = 0;
11452     int rb1off ;
11453     
11454     D (emitcode (";", "genReceive "););
11455
11456     if (ic->argreg == 1) 
11457     {
11458         /* first parameter */
11459         if (AOP_IS_STR(IC_RESULT(ic)))
11460         {
11461             /* Nothing to do: it's already in the proper place. */
11462             return;
11463         }
11464         else
11465         {
11466             bool useDp2;
11467             
11468             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11469                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11470                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11471             
11472             _G.accInUse++;
11473             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11474             _G.accInUse--; 
11475             
11476             /* Sanity checking... */
11477             if (AOP_USESDPTR(IC_RESULT(ic)))
11478             {
11479                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11480                         "genReceive got unexpected DPTR.");
11481             }
11482             assignResultValue (IC_RESULT (ic));
11483         }
11484     } 
11485     else 
11486     { 
11487         /* second receive onwards */
11488         /* this gets a little tricky since unused recevies will be
11489          eliminated, we have saved the reg in the type field . and
11490          we use that to figure out which register to use */
11491         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11492         rb1off = ic->argreg;
11493         while (size--) 
11494         {
11495             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11496         }
11497     }
11498     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11499 }
11500
11501 /*-----------------------------------------------------------------*/
11502 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11503 /*-----------------------------------------------------------------*/
11504 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11505 {
11506     operand *from , *to , *count;
11507     symbol *lbl;
11508     bitVect *rsave;
11509     int i;
11510
11511     /* we know it has to be 3 parameters */
11512     assert (nparms == 3);
11513     
11514     rsave = newBitVect(16);
11515     /* save DPTR if it needs to be saved */
11516     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11517             if (bitVectBitValue(ic->rMask,i))
11518                     rsave = bitVectSetBit(rsave,i);
11519     }
11520     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11521                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11522     savermask(rsave);
11523     
11524     to = parms[0];
11525     from = parms[1];
11526     count = parms[2];
11527
11528     aopOp (from, ic->next, FALSE, FALSE);
11529
11530     /* get from into DPTR1 */
11531     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11532     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11533     if (options.model == MODEL_FLAT24) {
11534         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11535     }
11536
11537     freeAsmop (from, NULL, ic, FALSE);
11538     aopOp (to, ic, FALSE, FALSE);
11539     /* get "to" into DPTR */
11540     /* if the operand is already in dptr
11541        then we do nothing else we move the value to dptr */
11542     if (AOP_TYPE (to) != AOP_STR) {
11543         /* if already in DPTR then we need to push */
11544         if (AOP_TYPE(to) == AOP_DPTR) {
11545             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11546             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11547             if (options.model == MODEL_FLAT24)
11548                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11549             emitcode ("pop", "dph");
11550             emitcode ("pop", "dpl");        
11551         } else {
11552             _startLazyDPSEvaluation ();
11553             /* if this is remateriazable */
11554             if (AOP_TYPE (to) == AOP_IMMD) {
11555                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11556             } else {                    /* we need to get it byte by byte */
11557                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11558                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11559                 if (options.model == MODEL_FLAT24) {
11560                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11561                 }
11562             }
11563             _endLazyDPSEvaluation ();
11564         }
11565     }
11566     freeAsmop (to, NULL, ic, FALSE);
11567     _G.dptrInUse = _G.dptr1InUse = 1;
11568     aopOp (count, ic->next->next, FALSE,FALSE);
11569     lbl =newiTempLabel(NULL);
11570
11571     /* now for the actual copy */
11572     if (AOP_TYPE(count) == AOP_LIT && 
11573         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11574         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11575         if (fromc) {
11576             emitcode ("lcall","__bi_memcpyc2x_s");
11577         } else {
11578             emitcode ("lcall","__bi_memcpyx2x_s");
11579         }
11580         freeAsmop (count, NULL, ic, FALSE);
11581     } else {
11582         symbol *lbl1 = newiTempLabel(NULL);
11583         
11584         emitcode (";"," Auto increment but no djnz");
11585         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11586         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11587         freeAsmop (count, NULL, ic, FALSE);
11588         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11589         emitcode ("","!tlabeldef",lbl->key+100);
11590         if (fromc) {
11591             emitcode ("clr","a");
11592             emitcode ("movc", "a,@a+dptr");
11593         } else 
11594             emitcode ("movx", "a,@dptr");
11595         emitcode ("movx", "@dptr,a");
11596         emitcode ("inc", "dptr");
11597         emitcode ("inc", "dptr");
11598         emitcode ("mov","a,b");
11599         emitcode ("orl","a,_ap");
11600         emitcode ("jz","!tlabel",lbl1->key+100);
11601         emitcode ("mov","a,_ap");
11602         emitcode ("add","a,#!constbyte",0xFF);
11603         emitcode ("mov","_ap,a");
11604         emitcode ("mov","a,b");
11605         emitcode ("addc","a,#!constbyte",0xFF);
11606         emitcode ("mov","b,a");
11607         emitcode ("sjmp","!tlabel",lbl->key+100);
11608         emitcode ("","!tlabeldef",lbl1->key+100);
11609     }
11610     emitcode ("mov", "dps,#0"); 
11611     _G.dptrInUse = _G.dptr1InUse = 0;
11612     unsavermask(rsave);
11613
11614 }
11615
11616 /*-----------------------------------------------------------------*/
11617 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11618 /*-----------------------------------------------------------------*/
11619 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11620 {
11621     operand *from , *to , *count;
11622     symbol *lbl,*lbl2;
11623     bitVect *rsave;
11624     int i;
11625
11626     /* we know it has to be 3 parameters */
11627     assert (nparms == 3);
11628     
11629     rsave = newBitVect(16);
11630     /* save DPTR if it needs to be saved */
11631     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11632             if (bitVectBitValue(ic->rMask,i))
11633                     rsave = bitVectSetBit(rsave,i);
11634     }
11635     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11636                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11637     savermask(rsave);
11638     
11639     to = parms[0];
11640     from = parms[1];
11641     count = parms[2];
11642
11643     aopOp (from, ic->next, FALSE, FALSE);
11644
11645     /* get from into DPTR1 */
11646     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11647     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11648     if (options.model == MODEL_FLAT24) {
11649         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11650     }
11651
11652     freeAsmop (from, NULL, ic, FALSE);
11653     aopOp (to, ic, FALSE, FALSE);
11654     /* get "to" into DPTR */
11655     /* if the operand is already in dptr
11656        then we do nothing else we move the value to dptr */
11657     if (AOP_TYPE (to) != AOP_STR) {
11658         /* if already in DPTR then we need to push */
11659         if (AOP_TYPE(to) == AOP_DPTR) {
11660             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11661             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11662             if (options.model == MODEL_FLAT24)
11663                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11664             emitcode ("pop", "dph");
11665             emitcode ("pop", "dpl");        
11666         } else {
11667             _startLazyDPSEvaluation ();
11668             /* if this is remateriazable */
11669             if (AOP_TYPE (to) == AOP_IMMD) {
11670                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11671             } else {                    /* we need to get it byte by byte */
11672                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11673                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11674                 if (options.model == MODEL_FLAT24) {
11675                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11676                 }
11677             }
11678             _endLazyDPSEvaluation ();
11679         }
11680     }
11681     freeAsmop (to, NULL, ic, FALSE);
11682     _G.dptrInUse = _G.dptr1InUse = 1;
11683     aopOp (count, ic->next->next, FALSE,FALSE);
11684     lbl =newiTempLabel(NULL);
11685     lbl2 =newiTempLabel(NULL);
11686
11687     /* now for the actual compare */
11688     if (AOP_TYPE(count) == AOP_LIT && 
11689         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11690         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11691         if (fromc)
11692             emitcode("lcall","__bi_memcmpc2x_s");
11693         else
11694             emitcode("lcall","__bi_memcmpx2x_s");
11695         freeAsmop (count, NULL, ic, FALSE);
11696         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11697         aopPut(AOP(IC_RESULT(ic)),"a",0);
11698         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11699     } else {
11700         symbol *lbl1 = newiTempLabel(NULL);
11701
11702         emitcode("push","ar0");         
11703         emitcode (";"," Auto increment but no djnz");
11704         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11705         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11706         freeAsmop (count, NULL, ic, FALSE);
11707         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11708         emitcode ("","!tlabeldef",lbl->key+100);
11709         if (fromc) {
11710             emitcode ("clr","a");
11711             emitcode ("movc", "a,@a+dptr");
11712         } else 
11713             emitcode ("movx", "a,@dptr");
11714         emitcode ("mov","r0,a");
11715         emitcode ("movx", "a,@dptr");
11716         emitcode ("clr","c");
11717         emitcode ("subb","a,r0");
11718         emitcode ("jnz","!tlabel",lbl2->key+100);
11719         emitcode ("inc", "dptr");
11720         emitcode ("inc", "dptr");
11721         emitcode ("mov","a,b");
11722         emitcode ("orl","a,_ap");
11723         emitcode ("jz","!tlabel",lbl1->key+100);
11724         emitcode ("mov","a,_ap");
11725         emitcode ("add","a,#!constbyte",0xFF);
11726         emitcode ("mov","_ap,a");
11727         emitcode ("mov","a,b");
11728         emitcode ("addc","a,#!constbyte",0xFF);
11729         emitcode ("mov","b,a");
11730         emitcode ("sjmp","!tlabel",lbl->key+100);
11731         emitcode ("","!tlabeldef",lbl1->key+100);
11732         emitcode ("clr","a");
11733         emitcode ("","!tlabeldef",lbl2->key+100);
11734         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11735         aopPut(AOP(IC_RESULT(ic)),"a",0);
11736         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11737         emitcode("pop","ar0");
11738         emitcode ("mov", "dps,#0");      
11739     }
11740     _G.dptrInUse = _G.dptr1InUse = 0;
11741     unsavermask(rsave);
11742
11743 }
11744
11745 /*-----------------------------------------------------------------*/
11746 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11747 /* port, first parameter output area second parameter pointer to   */
11748 /* port third parameter count                                      */
11749 /*-----------------------------------------------------------------*/
11750 static void genInp( iCode *ic, int nparms, operand **parms)
11751 {
11752     operand *from , *to , *count;
11753     symbol *lbl;
11754     bitVect *rsave;
11755     int i;
11756
11757     /* we know it has to be 3 parameters */
11758     assert (nparms == 3);
11759     
11760     rsave = newBitVect(16);
11761     /* save DPTR if it needs to be saved */
11762     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11763             if (bitVectBitValue(ic->rMask,i))
11764                     rsave = bitVectSetBit(rsave,i);
11765     }
11766     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11767                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11768     savermask(rsave);
11769     
11770     to = parms[0];
11771     from = parms[1];
11772     count = parms[2];
11773
11774     aopOp (from, ic->next, FALSE, FALSE);
11775
11776     /* get from into DPTR1 */
11777     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11778     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11779     if (options.model == MODEL_FLAT24) {
11780         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11781     }
11782
11783     freeAsmop (from, NULL, ic, FALSE);
11784     aopOp (to, ic, FALSE, FALSE);
11785     /* get "to" into DPTR */
11786     /* if the operand is already in dptr
11787        then we do nothing else we move the value to dptr */
11788     if (AOP_TYPE (to) != AOP_STR) {
11789         /* if already in DPTR then we need to push */
11790         if (AOP_TYPE(to) == AOP_DPTR) {
11791             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11792             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11793             if (options.model == MODEL_FLAT24)
11794                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11795             emitcode ("pop", "dph");
11796             emitcode ("pop", "dpl");        
11797         } else {
11798             _startLazyDPSEvaluation ();
11799             /* if this is remateriazable */
11800             if (AOP_TYPE (to) == AOP_IMMD) {
11801                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11802             } else {                    /* we need to get it byte by byte */
11803                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11804                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11805                 if (options.model == MODEL_FLAT24) {
11806                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11807                 }
11808             }
11809             _endLazyDPSEvaluation ();
11810         }
11811     }
11812     freeAsmop (to, NULL, ic, FALSE);
11813
11814     _G.dptrInUse = _G.dptr1InUse = 1;
11815     aopOp (count, ic->next->next, FALSE,FALSE);
11816     lbl =newiTempLabel(NULL);
11817
11818     /* now for the actual copy */
11819     if (AOP_TYPE(count) == AOP_LIT && 
11820         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11821         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11822         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11823         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11824         freeAsmop (count, NULL, ic, FALSE);
11825         emitcode ("","!tlabeldef",lbl->key+100);
11826         emitcode ("movx", "a,@dptr");   /* read data from port */
11827         emitcode ("dec","dps");         /* switch to DPTR */
11828         emitcode ("movx", "@dptr,a");   /* save into location */
11829         emitcode ("inc", "dptr");       /* point to next area */
11830         emitcode ("inc","dps");         /* switch to DPTR2 */
11831         emitcode ("djnz","b,!tlabel",lbl->key+100);
11832     } else {
11833         symbol *lbl1 = newiTempLabel(NULL);
11834         
11835         emitcode (";"," Auto increment but no djnz");
11836         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11837         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11838         freeAsmop (count, NULL, ic, FALSE);
11839         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11840         emitcode ("","!tlabeldef",lbl->key+100);
11841         emitcode ("movx", "a,@dptr");
11842         emitcode ("dec","dps");         /* switch to DPTR */
11843         emitcode ("movx", "@dptr,a");
11844         emitcode ("inc", "dptr");
11845         emitcode ("inc","dps");         /* switch to DPTR2 */
11846 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11847 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11848         emitcode ("mov","a,b");
11849         emitcode ("orl","a,_ap");
11850         emitcode ("jz","!tlabel",lbl1->key+100);
11851         emitcode ("mov","a,_ap");
11852         emitcode ("add","a,#!constbyte",0xFF);
11853         emitcode ("mov","_ap,a");
11854         emitcode ("mov","a,b");
11855         emitcode ("addc","a,#!constbyte",0xFF);
11856         emitcode ("mov","b,a");
11857         emitcode ("sjmp","!tlabel",lbl->key+100);
11858         emitcode ("","!tlabeldef",lbl1->key+100);
11859     }
11860     emitcode ("mov", "dps,#0"); 
11861     _G.dptrInUse = _G.dptr1InUse = 0;
11862     unsavermask(rsave);
11863
11864 }
11865
11866 /*-----------------------------------------------------------------*/
11867 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11868 /* port, first parameter output area second parameter pointer to   */
11869 /* port third parameter count                                      */
11870 /*-----------------------------------------------------------------*/
11871 static void genOutp( iCode *ic, int nparms, operand **parms)
11872 {
11873     operand *from , *to , *count;
11874     symbol *lbl;
11875     bitVect *rsave;
11876     int i;
11877
11878     /* we know it has to be 3 parameters */
11879     assert (nparms == 3);
11880     
11881     rsave = newBitVect(16);
11882     /* save DPTR if it needs to be saved */
11883     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11884             if (bitVectBitValue(ic->rMask,i))
11885                     rsave = bitVectSetBit(rsave,i);
11886     }
11887     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11888                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11889     savermask(rsave);
11890     
11891     to = parms[0];
11892     from = parms[1];
11893     count = parms[2];
11894
11895     aopOp (from, ic->next, FALSE, FALSE);
11896
11897     /* get from into DPTR1 */
11898     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11899     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11900     if (options.model == MODEL_FLAT24) {
11901         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11902     }
11903
11904     freeAsmop (from, NULL, ic, FALSE);
11905     aopOp (to, ic, FALSE, FALSE);
11906     /* get "to" into DPTR */
11907     /* if the operand is already in dptr
11908        then we do nothing else we move the value to dptr */
11909     if (AOP_TYPE (to) != AOP_STR) {
11910         /* if already in DPTR then we need to push */
11911         if (AOP_TYPE(to) == AOP_DPTR) {
11912             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11913             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11914             if (options.model == MODEL_FLAT24)
11915                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11916             emitcode ("pop", "dph");
11917             emitcode ("pop", "dpl");        
11918         } else {
11919             _startLazyDPSEvaluation ();
11920             /* if this is remateriazable */
11921             if (AOP_TYPE (to) == AOP_IMMD) {
11922                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11923             } else {                    /* we need to get it byte by byte */
11924                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11925                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11926                 if (options.model == MODEL_FLAT24) {
11927                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11928                 }
11929             }
11930             _endLazyDPSEvaluation ();
11931         }
11932     }
11933     freeAsmop (to, NULL, ic, FALSE);
11934
11935     _G.dptrInUse = _G.dptr1InUse = 1;
11936     aopOp (count, ic->next->next, FALSE,FALSE);
11937     lbl =newiTempLabel(NULL);
11938
11939     /* now for the actual copy */
11940     if (AOP_TYPE(count) == AOP_LIT && 
11941         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11942         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11943         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11944         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11945         emitcode ("","!tlabeldef",lbl->key+100);
11946         emitcode ("movx", "a,@dptr");   /* read data from port */
11947         emitcode ("inc","dps");         /* switch to DPTR2 */
11948         emitcode ("movx", "@dptr,a");   /* save into location */
11949         emitcode ("inc", "dptr");       /* point to next area */
11950         emitcode ("dec","dps");         /* switch to DPTR */
11951         emitcode ("djnz","b,!tlabel",lbl->key+100);
11952         freeAsmop (count, NULL, ic, FALSE);
11953     } else {
11954         symbol *lbl1 = newiTempLabel(NULL);
11955         
11956         emitcode (";"," Auto increment but no djnz");
11957         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11958         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11959         freeAsmop (count, NULL, ic, FALSE);
11960         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11961         emitcode ("","!tlabeldef",lbl->key+100);
11962         emitcode ("movx", "a,@dptr");
11963         emitcode ("inc", "dptr");
11964         emitcode ("inc","dps");         /* switch to DPTR2 */
11965         emitcode ("movx", "@dptr,a");
11966         emitcode ("dec","dps");         /* switch to DPTR */
11967         emitcode ("mov","a,b");
11968         emitcode ("orl","a,_ap");
11969         emitcode ("jz","!tlabel",lbl1->key+100);
11970         emitcode ("mov","a,_ap");
11971         emitcode ("add","a,#!constbyte",0xFF);
11972         emitcode ("mov","_ap,a");
11973         emitcode ("mov","a,b");
11974         emitcode ("addc","a,#!constbyte",0xFF);
11975         emitcode ("mov","b,a");
11976         emitcode ("sjmp","!tlabel",lbl->key+100);
11977         emitcode ("","!tlabeldef",lbl1->key+100);
11978     }
11979     emitcode ("mov", "dps,#0"); 
11980     _G.dptrInUse = _G.dptr1InUse = 0;
11981     unsavermask(rsave);
11982
11983 }
11984
11985 /*-----------------------------------------------------------------*/
11986 /* genSwapW - swap lower & high order bytes                        */
11987 /*-----------------------------------------------------------------*/
11988 static void genSwapW(iCode *ic, int nparms, operand **parms)
11989 {
11990     operand *dest;
11991     operand *src;
11992     assert (nparms==1);
11993
11994     src = parms[0];
11995     dest=IC_RESULT(ic);
11996
11997     assert(getSize(operandType(src))==2);
11998
11999     aopOp (src, ic, FALSE, FALSE);
12000     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12001     _G.accInUse++;
12002     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12003     _G.accInUse--;
12004     freeAsmop (src, NULL, ic, FALSE);
12005     
12006     aopOp (dest,ic, FALSE, FALSE);
12007     aopPut(AOP(dest),"b",0);
12008     aopPut(AOP(dest),"a",1);
12009     freeAsmop (dest, NULL, ic, FALSE);    
12010 }
12011
12012 /*-----------------------------------------------------------------*/
12013 /* genMemsetX - gencode for memSetX data                           */
12014 /*-----------------------------------------------------------------*/
12015 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12016 {
12017     operand *to , *val , *count;
12018     symbol *lbl;
12019     char *l;
12020     int i;
12021     bitVect *rsave;
12022
12023     /* we know it has to be 3 parameters */
12024     assert (nparms == 3);
12025     
12026     to = parms[0];
12027     val = parms[1];
12028     count = parms[2];
12029         
12030     /* save DPTR if it needs to be saved */
12031     rsave = newBitVect(16);
12032     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12033             if (bitVectBitValue(ic->rMask,i))
12034                     rsave = bitVectSetBit(rsave,i);
12035     }
12036     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12037                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12038     savermask(rsave);
12039
12040     aopOp (to, ic, FALSE, FALSE);
12041     /* get "to" into DPTR */
12042     /* if the operand is already in dptr
12043        then we do nothing else we move the value to dptr */
12044     if (AOP_TYPE (to) != AOP_STR) {
12045         /* if already in DPTR then we need to push */
12046         if (AOP_TYPE(to) == AOP_DPTR) {
12047             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12048             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12049             if (options.model == MODEL_FLAT24)
12050                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12051             emitcode ("pop", "dph");
12052             emitcode ("pop", "dpl");        
12053         } else {
12054             _startLazyDPSEvaluation ();
12055             /* if this is remateriazable */
12056             if (AOP_TYPE (to) == AOP_IMMD) {
12057                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12058             } else {                    /* we need to get it byte by byte */
12059                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12060                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12061                 if (options.model == MODEL_FLAT24) {
12062                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12063                 }
12064             }
12065             _endLazyDPSEvaluation ();
12066         }
12067     }
12068     freeAsmop (to, NULL, ic, FALSE);
12069
12070     aopOp (val, ic->next->next, FALSE,FALSE);
12071     aopOp (count, ic->next->next, FALSE,FALSE);    
12072     lbl =newiTempLabel(NULL);
12073     /* now for the actual copy */
12074     if (AOP_TYPE(count) == AOP_LIT && 
12075         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12076         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12077         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12078         MOVA(l);
12079         emitcode ("","!tlabeldef",lbl->key+100);
12080         emitcode ("movx", "@dptr,a");
12081         emitcode ("inc", "dptr");
12082         emitcode ("djnz","b,!tlabel",lbl->key+100);
12083     } else {
12084         symbol *lbl1 = newiTempLabel(NULL);
12085         
12086         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12087         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12088         emitcode ("","!tlabeldef",lbl->key+100);
12089         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12090         emitcode ("movx", "@dptr,a");
12091         emitcode ("inc", "dptr");
12092         emitcode ("mov","a,b");
12093         emitcode ("orl","a,_ap");
12094         emitcode ("jz","!tlabel",lbl1->key+100);
12095         emitcode ("mov","a,_ap");
12096         emitcode ("add","a,#!constbyte",0xFF);
12097         emitcode ("mov","_ap,a");
12098         emitcode ("mov","a,b");
12099         emitcode ("addc","a,#!constbyte",0xFF);
12100         emitcode ("mov","b,a");
12101         emitcode ("sjmp","!tlabel",lbl->key+100);
12102         emitcode ("","!tlabeldef",lbl1->key+100);
12103     }
12104     freeAsmop (count, NULL, ic, FALSE);
12105     unsavermask(rsave);
12106 }
12107
12108 /*-----------------------------------------------------------------*/
12109 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12110 /*-----------------------------------------------------------------*/
12111 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12112 {
12113         bitVect *rsave ;
12114         operand *pnum, *result;
12115         int i;
12116     
12117         assert (nparms==1);
12118         /* save registers that need to be saved */
12119         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12120                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12121     
12122         pnum = parms[0]; 
12123         aopOp (pnum, ic, FALSE, FALSE);
12124         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12125         freeAsmop (pnum, NULL, ic, FALSE);
12126         emitcode ("lcall","NatLib_LoadPrimitive");
12127         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12128         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
12129             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12130                 for (i = (size-1) ; i >= 0 ; i-- ) {
12131                         emitcode ("push","a%s",javaRet[i]);
12132                 }
12133                 for (i=0; i < size ; i++ ) {
12134                         emitcode ("pop","a%s",
12135                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12136                 }
12137         } else {
12138                 for (i = 0 ; i < size ; i++ ) {
12139                         aopPut(AOP(result),javaRet[i],i);
12140                 }
12141         }    
12142         freeAsmop (result, NULL, ic, FALSE);
12143         unsavermask(rsave);
12144 }
12145
12146 /*-----------------------------------------------------------------*/
12147 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
12148 /*-----------------------------------------------------------------*/
12149 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12150 {
12151         bitVect *rsave ;
12152         operand *pnum, *result;
12153         int size = 3;
12154         int i;
12155     
12156         assert (nparms==1);
12157         /* save registers that need to be saved */
12158         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12159                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12160     
12161         pnum = parms[0]; 
12162         aopOp (pnum, ic, FALSE, FALSE);
12163         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12164         freeAsmop (pnum, NULL, ic, FALSE);
12165         emitcode ("lcall","NatLib_LoadPointer");
12166         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12167         if (AOP_TYPE(result)!=AOP_STR) {
12168                 for (i = 0 ; i < size ; i++ ) {
12169                         aopPut(AOP(result),fReturn[i],i);
12170                 }
12171         }    
12172         freeAsmop (result, NULL, ic, FALSE);
12173         unsavermask(rsave);
12174 }
12175
12176 /*-----------------------------------------------------------------*/
12177 /* genNatLibInstallStateBlock -                                    */
12178 /*-----------------------------------------------------------------*/
12179 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
12180                                        operand **parms, const char *name)
12181 {
12182         bitVect *rsave ;
12183         operand *psb, *handle;
12184         assert (nparms==2);
12185
12186         /* save registers that need to be saved */
12187         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12188                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12189         psb = parms[0];
12190         handle = parms[1];
12191
12192         /* put pointer to state block into DPTR1 */
12193         aopOp (psb, ic, FALSE, FALSE);
12194         if (AOP_TYPE (psb) == AOP_IMMD) {
12195                 emitcode ("mov","dps,#1");
12196                 emitcode ("mov", "dptr,%s",
12197                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12198                 emitcode ("mov","dps,#0");
12199         } else {
12200                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12201                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12202                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12203         }
12204         freeAsmop (psb, NULL, ic, FALSE);
12205
12206         /* put libraryID into DPTR */
12207         emitcode ("mov","dptr,#LibraryID");
12208
12209         /* put handle into r3:r2 */
12210         aopOp (handle, ic, FALSE, FALSE);
12211         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12212                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12213                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12214                 emitcode ("pop","ar3");
12215                 emitcode ("pop","ar2");
12216         } else {        
12217                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12218                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12219         }
12220         freeAsmop (psb, NULL, ic, FALSE);
12221
12222         /* make the call */
12223         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12224
12225         /* put return value into place*/
12226         _G.accInUse++;
12227         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12228         _G.accInUse--;
12229         aopPut(AOP(IC_RESULT(ic)),"a",0);
12230         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12231         unsavermask(rsave);
12232 }
12233
12234 /*-----------------------------------------------------------------*/
12235 /* genNatLibRemoveStateBlock -                                     */
12236 /*-----------------------------------------------------------------*/
12237 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12238 {
12239         bitVect *rsave ;
12240
12241         assert(nparms==0);
12242
12243         /* save registers that need to be saved */
12244         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12245                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12246
12247         /* put libraryID into DPTR */
12248         emitcode ("mov","dptr,#LibraryID");
12249         /* make the call */
12250         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12251         unsavermask(rsave);
12252 }
12253
12254 /*-----------------------------------------------------------------*/
12255 /* genNatLibGetStateBlock -                                        */
12256 /*-----------------------------------------------------------------*/
12257 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12258                                    operand **parms,const char *name)
12259 {
12260         bitVect *rsave ;
12261         symbol *lbl = newiTempLabel(NULL);
12262         
12263         assert(nparms==0);
12264         /* save registers that need to be saved */
12265         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12266                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12267
12268         /* put libraryID into DPTR */
12269         emitcode ("mov","dptr,#LibraryID");
12270         /* make the call */
12271         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12272         emitcode ("jnz","!tlabel",lbl->key+100);
12273
12274         /* put return value into place */
12275         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12276         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12277                 emitcode ("push","ar3");
12278                 emitcode ("push","ar2");
12279                 emitcode ("pop","%s",
12280                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12281                 emitcode ("pop","%s",
12282                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12283         } else {
12284                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12285                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12286         }
12287         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12288         emitcode ("","!tlabeldef",lbl->key+100);
12289         unsavermask(rsave);
12290 }
12291
12292 /*-----------------------------------------------------------------*/
12293 /* genMMMalloc -                                                   */
12294 /*-----------------------------------------------------------------*/
12295 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12296                          int size, const char *name)
12297 {
12298         bitVect *rsave ;
12299         operand *bsize;
12300         symbol *rsym;
12301         symbol *lbl = newiTempLabel(NULL);
12302
12303         assert (nparms == 1);
12304         /* save registers that need to be saved */
12305         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12306                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12307         
12308         bsize=parms[0];
12309         aopOp (bsize,ic,FALSE,FALSE);
12310
12311         /* put the size in R4-R2 */
12312         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12313                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12314                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12315                 if (size==3) {
12316                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12317                         emitcode("pop","ar4");
12318                 }
12319                 emitcode("pop","ar3");
12320                 emitcode("pop","ar2");          
12321         } else {
12322                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12323                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12324                 if (size==3) {
12325                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12326                 }
12327         }
12328         freeAsmop (bsize, NULL, ic, FALSE);
12329
12330         /* make the call */
12331         emitcode ("lcall","MM_%s",name);
12332         emitcode ("jz","!tlabel",lbl->key+100);
12333         emitcode ("mov","r2,#!constbyte",0xff);
12334         emitcode ("mov","r3,#!constbyte",0xff);
12335         emitcode ("","!tlabeldef",lbl->key+100);
12336         /* we don't care about the pointer : we just save the handle */
12337         rsym = OP_SYMBOL(IC_RESULT(ic));
12338         if (rsym->liveFrom != rsym->liveTo) {
12339                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12340                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12341                         emitcode ("push","ar3");
12342                         emitcode ("push","ar2");
12343                         emitcode ("pop","%s",
12344                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12345                         emitcode ("pop","%s",
12346                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12347                 } else {
12348                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12349                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12350                 }
12351                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12352         }
12353         unsavermask(rsave);
12354 }
12355
12356 /*-----------------------------------------------------------------*/
12357 /* genMMDeref -                                                    */
12358 /*-----------------------------------------------------------------*/
12359 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12360 {
12361         bitVect *rsave ;
12362         operand *handle;
12363
12364         assert (nparms == 1);
12365         /* save registers that need to be saved */
12366         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12367                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12368         
12369         handle=parms[0];
12370         aopOp (handle,ic,FALSE,FALSE);
12371
12372         /* put the size in R4-R2 */
12373         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12374                 emitcode("push","%s",
12375                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12376                 emitcode("push","%s",
12377                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12378                 emitcode("pop","ar3");
12379                 emitcode("pop","ar2");          
12380         } else {
12381                 emitcode ("mov","r2,%s",
12382                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12383                 emitcode ("mov","r3,%s",
12384                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12385         }
12386         freeAsmop (handle, NULL, ic, FALSE);
12387
12388         /* make the call */
12389         emitcode ("lcall","MM_Deref");
12390         
12391         {
12392                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12393                 if (rsym->liveFrom != rsym->liveTo) {                   
12394                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12395                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12396                             _startLazyDPSEvaluation ();
12397                             
12398                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12399                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12400                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12401
12402                             _endLazyDPSEvaluation ();
12403                             
12404                         }
12405                 }
12406         }
12407         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12408         unsavermask(rsave);
12409 }
12410
12411 /*-----------------------------------------------------------------*/
12412 /* genMMUnrestrictedPersist -                                      */
12413 /*-----------------------------------------------------------------*/
12414 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12415 {
12416         bitVect *rsave ;
12417         operand *handle;
12418
12419         assert (nparms == 1);
12420         /* save registers that need to be saved */
12421         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12422                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12423         
12424         handle=parms[0];
12425         aopOp (handle,ic,FALSE,FALSE);
12426
12427         /* put the size in R3-R2 */
12428         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12429                 emitcode("push","%s",
12430                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12431                 emitcode("push","%s",
12432                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12433                 emitcode("pop","ar3");
12434                 emitcode("pop","ar2");          
12435         } else {
12436                 emitcode ("mov","r2,%s",
12437                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12438                 emitcode ("mov","r3,%s",
12439                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12440         }
12441         freeAsmop (handle, NULL, ic, FALSE);
12442
12443         /* make the call */
12444         emitcode ("lcall","MM_UnrestrictedPersist");
12445
12446         {
12447                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12448                 if (rsym->liveFrom != rsym->liveTo) {   
12449                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12450                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12451                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12452                 }
12453         }
12454         unsavermask(rsave);
12455 }
12456
12457 /*-----------------------------------------------------------------*/
12458 /* genSystemExecJavaProcess -                                      */
12459 /*-----------------------------------------------------------------*/
12460 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12461 {
12462         bitVect *rsave ;
12463         operand *handle, *pp;
12464
12465         assert (nparms==2);
12466         /* save registers that need to be saved */
12467         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12468                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12469         
12470         pp = parms[0];
12471         handle = parms[1];
12472         
12473         /* put the handle in R3-R2 */
12474         aopOp (handle,ic,FALSE,FALSE);
12475         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12476                 emitcode("push","%s",
12477                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12478                 emitcode("push","%s",
12479                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12480                 emitcode("pop","ar3");
12481                 emitcode("pop","ar2");          
12482         } else {
12483                 emitcode ("mov","r2,%s",
12484                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12485                 emitcode ("mov","r3,%s",
12486                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12487         }
12488         freeAsmop (handle, NULL, ic, FALSE);
12489         
12490         /* put pointer in DPTR */
12491         aopOp (pp,ic,FALSE,FALSE);
12492         if (AOP_TYPE(pp) == AOP_IMMD) {
12493                 emitcode ("mov", "dptr,%s",
12494                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12495         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12496                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12497                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12498                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12499         }
12500         freeAsmop (handle, NULL, ic, FALSE);
12501
12502         /* make the call */
12503         emitcode ("lcall","System_ExecJavaProcess");
12504         
12505         /* put result in place */
12506         {
12507                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12508                 if (rsym->liveFrom != rsym->liveTo) {   
12509                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12510                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12511                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12512                 }
12513         }
12514         
12515         unsavermask(rsave);
12516 }
12517
12518 /*-----------------------------------------------------------------*/
12519 /* genSystemRTCRegisters -                                         */
12520 /*-----------------------------------------------------------------*/
12521 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12522                                   char *name)
12523 {
12524         bitVect *rsave ;
12525         operand *pp;
12526
12527         assert (nparms==1);
12528         /* save registers that need to be saved */
12529         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12530                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12531         
12532         pp=parms[0];
12533         /* put pointer in DPTR */
12534         aopOp (pp,ic,FALSE,FALSE);
12535         if (AOP_TYPE (pp) == AOP_IMMD) {
12536                 emitcode ("mov","dps,#1");
12537                 emitcode ("mov", "dptr,%s", 
12538                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12539                 emitcode ("mov","dps,#0");
12540         } else {
12541                 emitcode ("mov","dpl1,%s",
12542                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12543                 emitcode ("mov","dph1,%s",
12544                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12545                 emitcode ("mov","dpx1,%s",
12546                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12547         }
12548         freeAsmop (pp, NULL, ic, FALSE);
12549
12550         /* make the call */
12551         emitcode ("lcall","System_%sRTCRegisters",name);
12552
12553         unsavermask(rsave);
12554 }
12555
12556 /*-----------------------------------------------------------------*/
12557 /* genSystemThreadSleep -                                          */
12558 /*-----------------------------------------------------------------*/
12559 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12560 {
12561         bitVect *rsave ;
12562         operand *to, *s;
12563
12564         assert (nparms==1);
12565         /* save registers that need to be saved */
12566         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12567                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12568
12569         to = parms[0];
12570         aopOp(to,ic,FALSE,FALSE);
12571         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12572             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12573                 emitcode ("push","%s",
12574                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12575                 emitcode ("push","%s",
12576                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12577                 emitcode ("push","%s",
12578                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12579                 emitcode ("push","%s",
12580                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12581                 emitcode ("pop","ar3");
12582                 emitcode ("pop","ar2");
12583                 emitcode ("pop","ar1");
12584                 emitcode ("pop","ar0");
12585         } else {
12586                 emitcode ("mov","r0,%s",
12587                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12588                 emitcode ("mov","r1,%s",
12589                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12590                 emitcode ("mov","r2,%s",
12591                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12592                 emitcode ("mov","r3,%s",
12593                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12594         }
12595         freeAsmop (to, NULL, ic, FALSE);
12596
12597         /* suspend in acc */
12598         s = parms[1];
12599         aopOp(s,ic,FALSE,FALSE);
12600         emitcode ("mov","a,%s",
12601                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12602         freeAsmop (s, NULL, ic, FALSE);
12603
12604         /* make the call */
12605         emitcode ("lcall","System_%s",name);
12606
12607         unsavermask(rsave);
12608 }
12609
12610 /*-----------------------------------------------------------------*/
12611 /* genSystemThreadResume -                                         */
12612 /*-----------------------------------------------------------------*/
12613 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12614 {
12615         bitVect *rsave ;
12616         operand *tid,*pid;
12617
12618         assert (nparms==2);
12619         /* save registers that need to be saved */
12620         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12621                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12622         
12623         tid = parms[0];
12624         pid = parms[1];
12625         
12626         /* PID in R0 */
12627         aopOp(pid,ic,FALSE,FALSE);
12628         emitcode ("mov","r0,%s",
12629                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12630         freeAsmop (pid, NULL, ic, FALSE);
12631         
12632         /* tid into ACC */
12633         aopOp(tid,ic,FALSE,FALSE);
12634         emitcode ("mov","a,%s",
12635                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12636         freeAsmop (tid, NULL, ic, FALSE);
12637         
12638         emitcode ("lcall","System_ThreadResume");
12639
12640         /* put result into place */
12641         {
12642                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12643                 if (rsym->liveFrom != rsym->liveTo) {   
12644                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12645                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12646                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12647                 }
12648         }
12649         unsavermask(rsave);
12650 }
12651
12652 /*-----------------------------------------------------------------*/
12653 /* genSystemProcessResume -                                        */
12654 /*-----------------------------------------------------------------*/
12655 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12656 {
12657         bitVect *rsave ;
12658         operand *pid;
12659
12660         assert (nparms==1);
12661         /* save registers that need to be saved */
12662         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12663                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12664         
12665         pid = parms[0];
12666         
12667         /* pid into ACC */
12668         aopOp(pid,ic,FALSE,FALSE);
12669         emitcode ("mov","a,%s",
12670                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12671         freeAsmop (pid, NULL, ic, FALSE);
12672         
12673         emitcode ("lcall","System_ProcessResume");
12674
12675         unsavermask(rsave);
12676 }
12677
12678 /*-----------------------------------------------------------------*/
12679 /* genSystem -                                                     */
12680 /*-----------------------------------------------------------------*/
12681 static void genSystem (iCode *ic,int nparms,char *name)
12682 {
12683         assert(nparms == 0);
12684
12685         emitcode ("lcall","System_%s",name);
12686 }
12687
12688 /*-----------------------------------------------------------------*/
12689 /* genSystemPoll -                                                  */
12690 /*-----------------------------------------------------------------*/
12691 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12692 {
12693         bitVect *rsave ;
12694         operand *fp;
12695
12696         assert (nparms==1);
12697         /* save registers that need to be saved */
12698         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12699                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12700
12701         fp = parms[0];
12702         aopOp (fp,ic,FALSE,FALSE);
12703         if (AOP_TYPE (fp) == AOP_IMMD) {
12704                 emitcode ("mov", "dptr,%s", 
12705                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12706         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12707                 emitcode ("mov","dpl,%s",
12708                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12709                 emitcode ("mov","dph,%s",
12710                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12711                 emitcode ("mov","dpx,%s",
12712                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12713         }
12714         freeAsmop (fp, NULL, ic, FALSE);
12715
12716         emitcode ("lcall","System_%sPoll",name);
12717
12718         /* put result into place */
12719         {
12720                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12721                 if (rsym->liveFrom != rsym->liveTo) {   
12722                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12723                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12724                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12725                 }
12726         }
12727         unsavermask(rsave);
12728 }
12729
12730 /*-----------------------------------------------------------------*/
12731 /* genSystemGetCurrentID -                                         */
12732 /*-----------------------------------------------------------------*/
12733 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12734 {
12735         assert (nparms==0);
12736
12737         emitcode ("lcall","System_GetCurrent%sId",name);
12738         /* put result into place */
12739         {
12740                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12741                 if (rsym->liveFrom != rsym->liveTo) {   
12742                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12743                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12744                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12745                 }
12746         }
12747 }
12748
12749 /*-----------------------------------------------------------------*/
12750 /* genDummyRead - generate code for dummy read of volatiles        */
12751 /*-----------------------------------------------------------------*/
12752 static void
12753 genDummyRead (iCode * ic)
12754 {
12755   operand *op;
12756   int size, offset;
12757
12758   D(emitcode(";     genDummyRead",""));
12759
12760   op = IC_RIGHT (ic);
12761   if (op && IS_SYMOP (op))
12762     {
12763       aopOp (op, ic, FALSE, FALSE);
12764
12765       /* if the result is a bit */
12766       if (AOP_TYPE (op) == AOP_CRY)
12767         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
12768       else
12769         {
12770           /* bit variables done */
12771           /* general case */
12772           size = AOP_SIZE (op);
12773           offset = 0;
12774           while (size--)
12775           {
12776             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
12777             offset++;
12778           }
12779         }
12780
12781       freeAsmop (op, NULL, ic, TRUE);
12782     }
12783
12784   op = IC_LEFT (ic);
12785   if (op && IS_SYMOP (op))
12786     {
12787       aopOp (op, ic, FALSE, FALSE);
12788
12789       /* if the result is a bit */
12790       if (AOP_TYPE (op) == AOP_CRY)
12791         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
12792       else
12793         {
12794           /* bit variables done */
12795           /* general case */
12796           size = AOP_SIZE (op);
12797           offset = 0;
12798           while (size--)
12799           {
12800             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
12801             offset++;
12802           }
12803         }
12804
12805       freeAsmop (op, NULL, ic, TRUE);
12806     }
12807     
12808 }
12809
12810 /*-----------------------------------------------------------------*/
12811 /* genCritical - generate code for start of a critical sequence    */
12812 /*-----------------------------------------------------------------*/
12813 static void
12814 genCritical (iCode *ic)
12815 {
12816   symbol *tlbl = newiTempLabel (NULL);
12817
12818   D(emitcode(";     genCritical",""));
12819   
12820   if (IC_RESULT (ic))
12821     aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
12822
12823   emitcode ("setb", "c");
12824   emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
12825   emitcode ("clr", "c");
12826   emitcode ("", "%05d$:", (tlbl->key + 100));
12827
12828   if (IC_RESULT (ic))
12829     outBitC (IC_RESULT (ic)); /* save old ea in an operand */
12830   else
12831     emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
12832
12833   if (IC_RESULT (ic))
12834     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
12835 }
12836
12837 /*-----------------------------------------------------------------*/
12838 /* genEndCritical - generate code for end of a critical sequence   */
12839 /*-----------------------------------------------------------------*/
12840 static void
12841 genEndCritical (iCode *ic)
12842 {
12843   D(emitcode(";     genEndCritical",""));
12844   
12845   if (IC_RIGHT (ic))
12846     {
12847       aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
12848       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
12849         {
12850           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
12851           emitcode ("mov", "ea,c");
12852         }
12853       else
12854         {
12855           MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
12856           emitcode ("rrc", "a");
12857           emitcode ("mov", "ea,c");
12858         }
12859       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
12860     }
12861   else
12862     {
12863       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
12864       emitcode ("mov", "ea,c");
12865     }
12866 }
12867
12868
12869
12870 /*-----------------------------------------------------------------*/
12871 /* genBuiltIn - calls the appropriate function to  generating code */
12872 /* for a built in function                                         */
12873 /*-----------------------------------------------------------------*/
12874 static void genBuiltIn (iCode *ic)
12875 {
12876         operand *bi_parms[MAX_BUILTIN_ARGS];
12877         int nbi_parms;
12878         iCode *bi_iCode;
12879         symbol *bif;
12880
12881         /* get all the arguments for a built in function */
12882         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12883
12884         /* which function is it */
12885         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12886         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12887                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12888         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12889                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12890         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12891                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12892         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12893                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12894         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12895                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12896         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12897                 genInp(bi_iCode,nbi_parms,bi_parms);
12898         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12899                 genOutp(bi_iCode,nbi_parms,bi_parms);
12900         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12901                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12902                 /* JavaNative builtIns */               
12903         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12904                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12905         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12906                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12907         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12908                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12909         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12910                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12911         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12912                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12913         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12914                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12915         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12916                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12917         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12918                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12919         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12920                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12921         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12922                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12923         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12924                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12925         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12926                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12927         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12928                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12929         } else if (strcmp(bif->name,"MM_Free")==0) {
12930                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12931         } else if (strcmp(bif->name,"MM_Deref")==0) {
12932                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12933         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12934                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12935         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12936                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12937         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12938                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12939         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12940                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12941         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12942                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12943         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12944                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12945         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12946                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12947         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12948                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12949         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12950                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12951         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12952                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12953         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12954                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12955         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12956                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12957         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12958                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12959         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12960                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12961         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12962                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12963         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12964                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12965         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12966                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12967         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12968                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12969         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12970                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12971         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12972                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12973         } else {
12974                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12975                 return ;
12976         }
12977         return ;    
12978 }
12979
12980 /*-----------------------------------------------------------------*/
12981 /* gen390Code - generate code for Dallas 390 based controllers     */
12982 /*-----------------------------------------------------------------*/
12983 void
12984 gen390Code (iCode * lic)
12985 {
12986   iCode *ic;
12987   int cln = 0;
12988
12989   lineHead = lineCurr = NULL;
12990   dptrn[1][0] = "dpl1";
12991   dptrn[1][1] = "dph1";
12992   dptrn[1][2] = "dpx1";
12993   
12994   if (options.model == MODEL_FLAT24) {
12995     fReturnSizeDS390 = 5;
12996     fReturn = fReturn24;
12997   } else {
12998     fReturnSizeDS390 = 4;
12999     fReturn = fReturn16;
13000     options.stack10bit=0;
13001   }
13002 #if 1
13003   /* print the allocation information */
13004   if (allocInfo && currFunc)
13005     printAllocInfo (currFunc, codeOutFile);
13006 #endif
13007   /* if debug information required */
13008   if (options.debug && currFunc)
13009     {
13010       debugFile->writeFunction(currFunc);
13011       _G.debugLine = 1;
13012       if (IS_STATIC (currFunc->etype))
13013         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
13014       else
13015         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
13016       _G.debugLine = 0;
13017     }
13018   /* stack pointer name */
13019   if (options.useXstack)
13020     spname = "_spx";
13021   else
13022     spname = "sp";
13023
13024
13025   for (ic = lic; ic; ic = ic->next)
13026     {
13027
13028       if (ic->lineno && cln != ic->lineno)
13029         {
13030           if (options.debug)
13031             {
13032               _G.debugLine = 1;
13033               emitcode ("", "C$%s$%d$%d$%d ==.",
13034                         FileBaseName (ic->filename), ic->lineno,
13035                         ic->level, ic->block);
13036               _G.debugLine = 0;
13037             }
13038           if (!options.noCcodeInAsm) {
13039             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
13040                       printCLine(ic->filename, ic->lineno));
13041           }
13042           cln = ic->lineno;
13043         }
13044       if (options.iCodeInAsm) {
13045         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13046       }
13047       /* if the result is marked as
13048          spilt and rematerializable or code for
13049          this has already been generated then
13050          do nothing */
13051       if (resultRemat (ic) || ic->generated)
13052         continue;
13053
13054       /* depending on the operation */
13055       switch (ic->op)
13056         {
13057         case '!':
13058           genNot (ic);
13059           break;
13060
13061         case '~':
13062           genCpl (ic);
13063           break;
13064
13065         case UNARYMINUS:
13066           genUminus (ic);
13067           break;
13068
13069         case IPUSH:
13070           genIpush (ic);
13071           break;
13072
13073         case IPOP:
13074           /* IPOP happens only when trying to restore a
13075              spilt live range, if there is an ifx statement
13076              following this pop then the if statement might
13077              be using some of the registers being popped which
13078              would destory the contents of the register so
13079              we need to check for this condition and handle it */
13080           if (ic->next &&
13081               ic->next->op == IFX &&
13082               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13083             genIfx (ic->next, ic);
13084           else
13085             genIpop (ic);
13086           break;
13087
13088         case CALL:
13089           genCall (ic);
13090           break;
13091
13092         case PCALL:
13093           genPcall (ic);
13094           break;
13095
13096         case FUNCTION:
13097           genFunction (ic);
13098           break;
13099
13100         case ENDFUNCTION:
13101           genEndFunction (ic);
13102           break;
13103
13104         case RETURN:
13105           genRet (ic);
13106           break;
13107
13108         case LABEL:
13109           genLabel (ic);
13110           break;
13111
13112         case GOTO:
13113           genGoto (ic);
13114           break;
13115
13116         case '+':
13117           genPlus (ic);
13118           break;
13119
13120         case '-':
13121           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13122             genMinus (ic);
13123           break;
13124
13125         case '*':
13126           genMult (ic);
13127           break;
13128
13129         case '/':
13130           genDiv (ic);
13131           break;
13132
13133         case '%':
13134           genMod (ic);
13135           break;
13136
13137         case '>':
13138           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13139           break;
13140
13141         case '<':
13142           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13143           break;
13144
13145         case LE_OP:
13146         case GE_OP:
13147         case NE_OP:
13148
13149           /* note these two are xlated by algebraic equivalence
13150              during parsing SDCC.y */
13151           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13152                   "got '>=' or '<=' shouldn't have come here");
13153           break;
13154
13155         case EQ_OP:
13156           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13157           break;
13158
13159         case AND_OP:
13160           genAndOp (ic);
13161           break;
13162
13163         case OR_OP:
13164           genOrOp (ic);
13165           break;
13166
13167         case '^':
13168           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13169           break;
13170
13171         case '|':
13172           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13173           break;
13174
13175         case BITWISEAND:
13176           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13177           break;
13178
13179         case INLINEASM:
13180           genInline (ic);
13181           break;
13182
13183         case RRC:
13184           genRRC (ic);
13185           break;
13186
13187         case RLC:
13188           genRLC (ic);
13189           break;
13190
13191         case GETHBIT:
13192           genGetHbit (ic);
13193           break;
13194
13195         case LEFT_OP:
13196           genLeftShift (ic);
13197           break;
13198
13199         case RIGHT_OP:
13200           genRightShift (ic);
13201           break;
13202
13203         case GET_VALUE_AT_ADDRESS:
13204           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13205           break;
13206
13207         case '=':
13208           if (POINTER_SET (ic))
13209             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13210           else
13211             genAssign (ic);
13212           break;
13213
13214         case IFX:
13215           genIfx (ic, NULL);
13216           break;
13217
13218         case ADDRESS_OF:
13219           genAddrOf (ic);
13220           break;
13221
13222         case JUMPTABLE:
13223           genJumpTab (ic);
13224           break;
13225
13226         case CAST:
13227           genCast (ic);
13228           break;
13229
13230         case RECEIVE:
13231           genReceive (ic);
13232           break;
13233
13234         case SEND:
13235           if (ic->builtinSEND) genBuiltIn(ic);
13236           else addSet (&_G.sendSet, ic);
13237           break;
13238
13239         case DUMMY_READ_VOLATILE:
13240           genDummyRead (ic);
13241           break;
13242
13243         case CRITICAL:
13244           genCritical (ic);
13245           break;
13246
13247         case ENDCRITICAL:
13248           genEndCritical (ic);
13249           break;
13250         
13251         case SWAP:
13252           genSwap (ic);
13253           break;
13254           
13255 #if 0 // obsolete, and buggy for != xdata
13256         case ARRAYINIT:
13257             genArrayInit(ic);
13258             break;
13259 #endif
13260             
13261         default:
13262           ic = ic;
13263         }
13264     }
13265
13266
13267   /* now we are ready to call the
13268      peep hole optimizer */
13269   if (!options.nopeep)
13270     peepHole (&lineHead);
13271
13272   /* now do the actual printing */
13273   printLine (lineHead, codeOutFile);
13274   return;
13275 }